博客 / 詳情

返回

支付寶AES如何加密

繼之前給大家介紹了 V3 加密解密的方法之後,今天給大家介紹下支付寶的 AES 加密。

image.png

注意: 以下説明均在使用支付寶 SDK 集成的基礎上,未使用支付寶 SDK 的小夥伴要使用的話老老實實從 AES 加密原理開始研究吧。

什麼是AES密鑰

AES 是一種高級加密標準(英語:Advanced Encryption Standard,縮寫:AES),是目前對稱密鑰加密中比較通用的一種加密方式,該加密方式加密/解密的密鑰即為 AES 密鑰。

什麼情況會用到AES加密

在支付寶接口對接中,強制要求使用的 AES 加密的場景並不多,主要是用在前後端敏感信息(如身份證、手機號等)傳輸的時候,對敏感信息進行加密傳輸

非敏感信息傳輸場景下也可以使用 AES 加密方式對請求數據進行加密傳輸,以保證接口內容在傳輸過程中的安全性。

不過支付寶的 AES 加密僅僅是對 bizContent 的請求內容進行加密,如果你請求的接口沒有 bizContent 的話,那就沒有辦法加密了,強行加密只會報錯 [當前API不支持加密請求]。

AES密鑰如何加密

AES 密鑰在使用過程中主要分為 加密 和 解密 兩個部分,下面我們就來一一説明下這如何實現。

如何配置 AES 密鑰

在加密和解密之前,最重要的一步就是先配置 AES 密鑰。

支付寶在每個應用下都提供了 AES 密鑰的配置入口。

配置路徑: 支付寶開放平台 -> 對應應用詳情 -> 開發設置 -> 接口內容加密方式:

image.png

通過短信/密碼驗證之後,就可以獲取到這一串 AES 密鑰了:

image.png

如何加密

支付寶的 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 內容加密的所有內容啦,希望對你有所幫助

user avatar eisuto 頭像 mokeywie 頭像 huzilachadedanche 頭像 redorblack 頭像 knifeblade 頭像 buxiyan 頭像 91cyz 頭像 tengteng_5c7902af4b01e 頭像 thinkfault 頭像 chengxuyuanxiaohui 頭像
10 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.