繼之前給大家介紹了 V3 加密解密的方法之後,今天給大家介紹下支付寶的 AES 加密。
注意: 以下説明均在使用支付寶 SDK 集成的基礎上,未使用支付寶 SDK 的小夥伴要使用的話老老實實從 AES 加密原理開始研究吧。
什麼是AES密鑰
AES 是一種高級加密標準(英語:Advanced Encryption Standard,縮寫:AES),是目前對稱密鑰加密中比較通用的一種加密方式,該加密方式加密/解密的密鑰即為 AES 密鑰。
什麼情況會用到AES加密
在支付寶接口對接中,強制要求使用的 AES 加密的場景並不多,主要是用在前後端敏感信息(如身份證、手機號等)傳輸的時候,對敏感信息進行加密傳輸。
非敏感信息傳輸場景下也可以使用 AES 加密方式對請求數據進行加密傳輸,以保證接口內容在傳輸過程中的安全性。
不過支付寶的 AES 加密僅僅是對 bizContent 的請求內容進行加密,如果你請求的接口沒有 bizContent 的話,那就沒有辦法加密了,強行加密只會報錯 [當前API不支持加密請求]。
AES密鑰如何加密
AES 密鑰在使用過程中主要分為 加密 和 解密 兩個部分,下面我們就來一一説明下這如何實現。
如何配置 AES 密鑰
在加密和解密之前,最重要的一步就是先配置 AES 密鑰。
支付寶在每個應用下都提供了 AES 密鑰的配置入口。
配置路徑: 支付寶開放平台 -> 對應應用詳情 -> 開發設置 -> 接口內容加密方式:
通過短信/密碼驗證之後,就可以獲取到這一串 AES 密鑰了:
如何加密
支付寶的 SDK 提供了加密的封裝方法,只要在初始化的方法中傳入 AES 密鑰,並且在代碼中加入 request.setNeedEncrypt(true) 就可以,下面以 alipay.trade.pay 接口為例:
public class AlipayTradePay {
public static void main(String[] args) throws AlipayApiException {
AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do","app_id","your private_key","json","GBK","alipay_public_key","RSA2","AES密鑰值","AES");
AlipayTradePayRequest request = new AlipayTradePayRequest();
JSONObject Content = new JSONObject() ;
Content.put("out_trade_no", "20200612000001");
Content.put("subject", "subject");
Content.put("total_amount", "0.01");
Content.put("scene", "bar_code");
Content.put("auth_code", "28763443825664394");
Content.put("product_code", "FACE_TO_FACE_PAYMENT");
// 封裝請求參數到biz_content
request.setBizContent(Content.toString());
//將biz_content的內容進行加密
request.setNeedEncrypt(true);
AlipayTradePayResponse response = alipayClient.execute(request);
/** 獲取接口調用結果 **/
System.out.println(response.getBody());
}
}
👉 其他語言的加密方式可以參考:[如何使用AES密鑰加密]
如何解密
解密分為兩種場景:
- 一種對應上述的加密方式,即使用內容加密方式請求到支付寶後,支付寶返回的數據也是加密的方式,需要對支付寶返回的同步響應數據進行解密
- 另一種是請求時沒有使用內容加密的方式,但支付寶自動對敏感數據進行加密了,需要解密後才能獲取到實際的信息,常見於小程序獲取手機號等
返回數據樣例:
{
"response":"m6HvyxulfAnFhlizJoh0sWzUubfBUlXIIJMJtBqIAaCQrbUeHdzI0V3Fh13kvWGRrOajf+Cy6ZQr6jhTFmy/DbXkMLDhDtMPx7oQc96bo73k9XsRuraDRgYm9zMGdU8H7zueR1QO4ZqrHhHm2CoiaNa13X83W2bXmqmu6wKLdXNQUsob64D/IFRMRyluPr9wwXBrVu0WzlT4UsGLxfD7rIvtODkYotD0Nxx3IzCM/Ujb2pAkaRwmq2RqTrbywa+5Y0GBSk9ajeHTqkmq1cTIxPdxzT+IgEjTm3s+ZJRhLXcPCGI0UYOgEOtnGVZ6bwmAxLq2gydmdGIQeJ5TOsnr6W4o4ySTrF03218jbBjKOLPCc8MrTHFiWr9MWSE7fkVXq7tszDXupLAs65IKaRbpO2PJD9GXt7w6TnPfaKRERDrtwteNo9iiu8zNCRWYTPGXxXz0gtN5aQZX6XPGCLCA7LqIxQ=",
"sign":"d9MdAHH4Hug+6CAM0cIVmQgLRQBjq4jeq64ma3BCNuy6Ctpmonn2GYY1Y+aUJr2m8YpfArGtKn6rGVWsvubDH9jEnLj/2D2/Ma8Vfvnl7T+thrBX4J334tmaUMrJZAjiRirHbMpBfUWsnyFuy0EJaYBrC3o7YXDIM7abQFMLnZNe2ByeYEcnrjcYBBWT/kEXwisjy5fm8MDedp0ZSG7YDMbEdNp5M1YTzuSYB0MlmNg7OwHVgZYiR/eEhCvsa3GM91aQa400Lvr1sFiAXRebaC5ufatswnF3szdsiNtgbsF13Vr2sqm0gj82dqATU0XvcbXRlRWInB0XGT7PP7sWBg=="
}
對於這兩種方式的解密方法都是一樣的(下列代碼中包含驗籤步驟):
//小程序前端提交的返回信息
String response = "{"response":"O9WWS91PFVrzBjBCVvYAtLAGqckg28xGgNw1465AuET2zakde6CmploNMH5hiDZctVC/EB2BU409KwQIll3wVRU2hvLhM77THJP9oiarmeqf36lZ9eBJYtCttYn06MCm","sign":"WK0SL/BJcm0NF7bjPtLIbbtlU84iM9X6w/guIFN6ba3yPBtEMjPU81hn2n+qU6ftSJv27Ew4C+Hfrbv/VDe7yzzi7MGxD16nTjNHzmz7FHSET3N71IsqZJoGeu/828vvBMwqTt6zR4m7dig6InAHvuQDeQVg1MA4QiOwUx8sSaBP6uz5rXZVb/n5AlSzaVEWJF1WmJr/fdxkJosgKzHVYUas+8w86eDo4bVMZK6nCn54ON9tt27Gk63jcMmp2FOr/swItfhwkUWSIOYiS/XkQZ3gaPaO1rTSfc7TymTdpJ72YFja5OIaJ5qeG/Hh0glohtyl4ce2cibnAS3omn1Buw=="}";
//1. 獲取驗籤和解密所需要的參數
//參數轉換成json格式
JSONObject jsonObject = JSON.parseObject(response);
//獲取json裏面的值key(可以省略)
String sign=jsonObject.getString("sign");
String content=jsonObject.getString("response");
String signType = "RSA2";
String charset = "UTF-8";
String encryptType = "AES";
//判斷是否為加密內容
boolean isDataEncrypted = !content.startsWith("{");
boolean signCheckPass = false;
//2. 驗籤
String signContent = content;
String signVeriKey = "你的小程序對應的支付寶公鑰(為擴展考慮建議用appId+signType做密鑰存儲隔離)";
String decryptKey = "你的小程序對應的加解密密鑰(為擴展考慮建議用appId+encryptType做密鑰存儲隔離)";
//如果是加密的報文則需要在密文的前後添加雙引號
if (isDataEncrypted) {
signContent = """ + signContent + """;
}
try {
signCheckPass = AlipaySignature.rsaCheck(signContent, sign, signVeriKey, charset, signType);
} catch (AlipayApiException e) {
//驗籤異常, 日誌
}
if(!signCheckPass) {
//驗籤不通過(異常或者報文被篡改),終止流程(不需要做解密)
throw new Exception("驗籤失敗");
}
//3. 解密
String plainData = null;
if (isDataEncrypted) {
try {
plainData = AlipayEncrypt.decryptContent(content, encryptType, decryptKey, charset);
System.out.println("解密信息plainData:"+plainData);
} catch (AlipayApiException e) {
//解密異常, 記錄日誌
throw new Exception("解密異常");
}
} else {
plainData = content;
System.out.println("plainData:"+plainData);
}
👉 其他語言的解密方法參考:[如何使用AES密鑰解密]
可能會遇到的問題
下面列舉一些大家在使用 AES 密鑰過程中可能會遇到的問題:
- [AES密鑰會自動過期嗎]
- [如何更新AES密鑰]
- [java提示:Invalid AES key length: 1218 bytes]
- [AES加密與RSA加簽的順序]
- [isv.decryption-error-unknown (解密出錯, 未知錯誤)]
- [isv.decryption-error-missing-encrypt-type(解密出錯, 未指定加密算法)]
以上就是關於支付寶 AES 內容加密的所有內容啦,希望對你有所幫助