部分内容参考:https://blog.csdn.net/L_K_ong/article/details/90410085
这里主要描述 退款回调信息内容:
微信申请退款接口文档:
https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=9_4&index=4
微信退款通知接口文档:
https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=9_16&index=10
【退款回调参数 】
{nonce_str=cc071fc5877f7d89b308be3d6e4f3c19,
req_info=LmCGMTk2/zKAR2pwxsg+NrzO8pQuSkfPDPyVnLO9Jyr8KcyrUoxBewHd+cH2MNXpYU1Ht+gEprP/EAg2JfC9qcpMkSOuOlbxw0a2we0bPXrYGMHGOGxZsyOcAqkmVV1NgaQoJjopQNQpjDcF8QWIw+CAxe9J7lYn4TYPKphtbnUKYrP3tcsKxuToKy8FSLTYREWOjxVqq37yoiQmTtaBE22SaRN4zAR1hbfn7HH1sZ4HAoWpRRa50ZP8Xk/uudhhiZ2B3KhPfVMb8/VGqKp360prF+BTsVSUH3sMPS58PvNx0KjbKiYC/VFyfstJN3VaKyR9zhuwoT5Enddr9au77BBpuGh21ZRY3LaXWmse5/2YHcmEP2v8tF6AZBNcm1m1CRjH3HynXLx9KrVviDlCrnujDasvaIIDGyz7f6n+2Q8EyarBEYzCg9WtLBbBWWP/MJUCfrVp9oQls7fJuNQijAqu5jDPGWmfLLNsPvsy1YNces1HoAJmDgpsAskYWrVdxvusgA41mUqV/22+OQhgxrsQJWk1ybdOXshrbUJSdI/3mowiIYpgFN3GyHb8omASp4+nMvmAnxQ6hobT+rmFhjJHMd8qR8iAVhttBWm8wariuWZsizr8lmLAPVILRrvl/awq+/pyoSnDrqJsyr4VvWL4tIADc96vnlAVicw8s/A7J/ZrvR/NGsD58OO1kDyzGtkCB3mzegUhBEm9phWR/csDEpxNYYOCajOiYczEe73FzNWy8CYrPRaRq0Ea/ZmDm6xBy+Gkp3h0MDqAV1huNzWjXTswBsCi3VNghUE/ddhZZ4M3XhgwAMglP0us7J3b8MFPYtvLPU7ZY3PavP6WAxB190gY3b9x32DC3F2hW77bw7xiGjoCQUA47bkCyiq3Q64KFko3Rarv9c+b/P2804kOI1+pPFN9bwCErm8CcpgK5YyV1OAO47U9bbNP+tybHtWIyoCJ0EYJmC38CVSt6TtWHAuYBlblweWqt+PsYC2H3xvV8aLCTlh2GwSW8PQfSvqaU00Uu81i2PWiMMBjaU9zqT+V6TZ5A4wVSgLBmBLMUg2icnzvVuLcq73cy0F/nWa2tPhK9qZp+exa1Q==,
appid=wx0000000004,
mch_id=1xxxxxxxxx2,
return_code=SUCCESS}
我们需要的参数都在req_info当中,包含了微信订单号,商户订单号等信息,解析了req_info字段后,商户才能知道这笔退款来自哪一个订单。
官方文档中解密流程:
在解码之前需要需要调用如下代码,Security.addProvider(new BouncyCastleProvider());使解码器生效,这个加载过程还挺慢的,有时候要好几秒,还好只需要加载一次就能一直使用。所以加在static代码中。
static{
if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null){
System.out.println("security provider BC not found");
Security.addProvider(new BouncyCastleProvider());
}
}
要使用BouncyCastleProvider类,需要额外引入jar包,pom依赖是这样的:
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.59</version>
</dependency>
第一步, base64解码,得到byte数组。这个直接用java的Base64.decode就可以
//1,对加密串A做base64解码,得到加密串B。
Base64.Decoder decoder = Base64.getDecoder();
byte[] base64ByteArr = decoder.decode(req_info);
第二步,对key做MD5加密,这一步也不是很复杂。
可在线生成之后拿来使用
第三步,使用PKCS7Padding 格式做AES-256-ECB解密。这一步坑略大。
java提供了
javax.crypto.spec. SecretKeySpec
javax.crypto. Cipher
这两个类来应对AES解密,然而因为某些原因,中国的JDK版本并不能支持256格式的AES解密,也就是所谓的PKCS7Padding,中国的JDK能支持的是128格式的AES解密,也就是PKCS5Padding,。
所以,我们需要网上下两个jar包,替换我们机器上JDK目录下的jar包,别下错版本,JDK8版本的这两个jar包下载地址:
https://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html
下载的jar有两个:local_policy.jar和US_export_policy.jar
下载之后解压里面,有两个jar包替换#JavaHome#\jre\lib\security\policy下的同名jar包,有可能这个目录下还有俩文件夹,limited和unlimited,jar包在这两个文件夹下,反正lib\security目录下肯定是有同名文件的,替换了就好了。
替换jar包后java程序需要重启。
暂时来看替换了这两个jar包还不会引起什么不好的影响。
//params为退款回调参数
Map params = XMLUtil.doXMLParse(xmlMsg);
log.info("【退款回调参数 】"+params);
String req_info=params.get("req_info").toString();//回调加密字段
log.info("【req_info】 : "+req_info);
//1,对加密串A做base64解码,得到加密串B。
Base64.Decoder decoder = Base64.getDecoder();
byte[] base64ByteArr = decoder.decode(req_info);
String md5_key = "123432445432;
SecretKey secretKey = new SecretKeySpec(md5_key.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
byte[] resultbt = cipher.doFinal(base64ByteArr);
String result = new String(resultbt);
log.info("【req_info】 : "+result);
Map result_params = XMLUtil.doXMLParse(result);