微信退款通知信息解密


 在最近的開發需求中,有一個需求,就是需要把微信退款通知記錄在數據庫中,原本以為是一個簡單的需求,但是微信文檔的坑,是你不能理解的。

 在微信退款通知返回的字段中有一個加密信息字段req_info。這個加密字段需要三個解密步驟才能最終獲取到信息。由此可見,這個字段是多么的重要。以下是微信官方文檔給出的解密步驟:

解密步驟如下:

(1)對加密串A做base64解碼,得到加密串B

(2)對商戶key做md5,得到32位小寫key* ( key設置路徑:微信商戶平台(pay.weixin.qq.com)-->賬戶設置-->API安全-->密鑰設置 )

(3)用key*對加密串B做AES-256-ECB解密(PKCS7Padding)

第一步,第二步都好理解,但是第三步說的真是太簡單了。被坑了一天,現在把代碼留下。

 1.通過微信退款通知先獲取到req_info這個字段

public static Map<String, String> xmlToMap(HttpServletRequest request) throws Exception {
Map<String, String> map = new HashMap<String, String>();
SAXReader reader = new SAXReader();
InputStream ins = request.getInputStream();
Document doc = reader.read(ins);
Element root = doc.getRootElement();
List<Element> list = root.elements();
for (Element e : list) {
map.put(e.getName(), e.getText());
}
ins.close();
return map;
}

這里使用DOM4j 首先把返回來的xml轉換成map。從中獲取req_info。

2.就是對req_info這個字段信息進行解密。

    1. 對加密信息進行base64位解碼。

      byte[] b = org.bouncycastle.util.encoders.Base64.decode(req_info);

    2.對商戶API秘鑰做MD5加密,得到小寫的32位key

     String key* = getMD5("your  API key").toLowerCase().getBytes();

   3.用剛才得到的key對加密串B做AES-256-ECB解密(PKCS7Padding) 

public static String decryptData(byte[] b) throws Exception {
Cipher cipher = null;
cipher = Cipher.getInstance("AES/ECB/PKCS7Padding");
SecretKeySpec key = new SecretKeySpec(key*.getBytes(), "AES");
cipher.init(Cipher.DECRYPT_MODE, key);
return new String(cipher.doFinal(b));
}

解密過后,就會返還xml,需要對xml進一步解析。

在整個解密過程中需要注意以下幾點:

 1. java 目前只支持PKCS5Padding,所以需要額外添加依賴。

<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-ext-jdk16</artifactId>
<version>1.45</version>
</dependency>

2.如果報這個錯 Illegal key size or default parameters 就需要替換你JAVA_HOME/jre/lib/security 下面的兩個jar包 local_policy.jar和US_export_policy.jar。

3.在解密類中需要添加一個靜態代碼塊來提供支持,靜態代碼塊如下:

static {
try {
Security.addProvider(new BouncyCastleProvider());
} catch (Exception e) {
e.printStackTrace();
}
}

 

以下 附上完整代碼:

 public class CipherTextUtil  {

    private static final String serectKey = "your API Serect key";

/**
* 密鑰算法
*/
private static final String ALGORITHM = "AES";
/**
* 加解密算法/工作模式/填充方式
*/
private static final String ALGORITHM_MODE_PADDING = "AES/ECB/PKCS7Padding";
/**
* 生成key
*/
private static SecretKeySpec key = new SecretKeySpec(MD5Util.MD5Encode(serectKey).toLowerCase().getBytes(), ALGORITHM);

static {
try {
Security.addProvider(new BouncyCastleProvider());
} catch (Exception e) {
e.printStackTrace();
}
}

/**
* AES解密
*/
public static String decryptData(byte[] b) throws Exception {
Cipher cipher = Cipher.getInstance(ALGORITHM_MODE_PADDING);
cipher.init(Cipher.DECRYPT_MODE, key);
return new String(cipher.doFinal(b));
}


public static void main(String[] args) throws Exception {

String A = "cms0dmeMS39cUWRUz19yJiPifeLRXoZjXhOnIhQlrz4SxDa2kmPVxHkMv2BeE+H+xr8euGyAO9sBNmS9ffugL7Xj47b9K6bwI8BLrP6/SwL3nTcrm44oimbJ4axAQLoaNuheqWYFS7pRBXAbByjjsBLzdMh+thCJjhFvyCK61fRMaUlkn6eZsc7fs609KgELGqSBdDlNsbXpTurgqdLdW07jPlsJZyXshg1gJ3b+n2wMC/pEZwPA/w7E0bAt0xzTIsYKmtLEwJlWg6Vf1KiocDfU0oVnhd5JPozxx4Cve67kUuGqDpdoStTBMXywHoAytklE610DvVKT59gkK9MqFU97SXV714wko6ZRKQAW0Utpx9DUko4jV3Hdwspr1JYUAg/GnINom25YbWQqKp28VKkJveXGeif5GEeUxeAmr4mYGvf9vD+bvBP2sH06koiOTJVVuIhvWmAdmFnNdk2hJkJdKvEtxxaNP7/eha5jDKNgjvCGV/hJNasl8U3qZX1qR0RtvcgoORt3nNvUOjQESNeS+tXlZtcpdZqDR4g7kQl5grAs+BOF6rk0qJ0PagxWF+arDSReLYBN5ihBkvai56s5Cv9iXFpVNkMwTBqYC4OpqzIN1EecA5fpi9pk7nVB3v5HLwp3oBYhbNiPNXkGTkuw634wBQtDLmeG3mXAYTX4xWdsYrkg4RY/rqFKsgeeBzGs7a7+PgbcE8B/t4/jVX3qVwbBkacqhG1l/W0zfZA8vHOJzVJhWEjXzn1iccQLiA6OASfnvRYoPnBoCX1qIjo0e55oCvRDau7hVTSvBx0hcpIjXmlcMcpJgiRXrPZFXgWh9myRkYtkCRleX49NELBOnK+sRHuJlfnpYYs9d1TurWzhXuu6wMow/wGQtyGC3XtQv0QTTg1KKDPRiqYq0QXMJ28+jL216Eg8qGrxmzXGYJ9Nf3oLh2TOZZvdhBbj+EM8T9+c/h3bAEe2L1wYtEJrqAMiSwZ6qW4dElQHBwL7sWha63gIB37vJ0SbyjWkqWWLUwwOMkDgvJ9r5I58O4OgzBtinC9k9yl90wO/dm0yuDTwF9agYlsPFP8XXClVdnvGQd+HUPk9YKB+WkyUww==";
byte[] b = Base64.decode(A);
String B = AESUtil.decryptData(b);
System.out.println(B);


}
}

 

完結,撒花撒花。。。。。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM