Обратный вызов возврата Wechat сообщит об ошибке при расшифровке req_info: недопустимый размер ключа или параметры по умолчанию.
- Официальный адрес документа WeChat: https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_16&index=10#menu1
Метод
дешифрования Шаги дешифрования следующие:
(1) Расшифруйте зашифрованную строку A с помощью base64, чтобы получить зашифрованную строку B
(2) Сделайте md5 для ключа продавца, чтобы получить 32-битный ключ нижнего регистра * (путь установки ключа: WeChat merchant платформа (pay.weixin.qq) .com) -> Настройки учетной записи–> Безопасность API–> Настройки ключа)
(3) Используйте ключ * для дешифрования зашифрованной строки B с помощью AES-256-ECB (PKCS7Padding)
Решение ошибки при расшифровке [суть здесь]:
- Сначала загрузите jce_policy от официального представителя оракула, мой - jdk8
- Адрес загрузки JDK7:
http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html
Адрес загрузки JDK8:
http://www.oracle.com/technetwork/java / javase /downloads/jce8-download-2133166.html
После скачивания распаковываем zip jce_policy, видим два пакета jar
Замените два пакета jar, только что загруженных в jdk и jre, двумя банками в
Java \ jdk1.8.0_71 \ jre \ lib \ security \ на
пакеты в Java \ jre1.8.0_71 \ lib \ security \ Замените две банки
Вот код обратного вызова после успешного возврата денег:
@PostMapping("/refundNotify")
public String refund(HttpServletRequest request) {
System.out.println("退款回调的请求方式" + request.getMethod());
String xmlSuccess = "<xml>\n" +
" <return_code><![CDATA[SUCCESS]]></return_code>\n" +
" <return_msg><![CDATA[OK]]></return_msg>\n" +
"</xml>";
String xmlFail = "<xml>\n" +
" <return_code><![CDATA[FAIL]]></return_code>\n" +
" <return_msg><![CDATA[OK]]></return_msg>\n" +
"</xml>";
try {
String xmlResult = PayUtil.getPostStr(request);
Map<String, String> resultMap = null;
try {
//将结果转成map
resultMap = PayUtil.xmlToMap(xmlResult);
} catch (Exception e1) {
e1.printStackTrace();
}
//商户订单号
String req_info = resultMap.get("req_info");
String return_code = resultMap.get("return_code");
if ("SUCCESS".equals(return_code)) {
//解密步骤如下:
//(1)对加密串A做base64解码,得到加密串B
Base64.Decoder decoder = Base64.getDecoder();
byte[] base64ByteArr = decoder.decode(req_info);
//(2)对商户key做md5,得到32位小写key* ( key设置路径:微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置 )
String key = MD5(PayConfig.KEY).toLowerCase();
//(3)用key*对加密串B做AES-256-ECB解密(PKCS7Padding)*/
String xml = init(key,base64ByteArr);
Map<String,String> xmlMasp = PayUtil.xmlToMap(xml);
String orderId = xmlMasp.get("out_trade_no");
System.err.println("退款单号:" + orderId);
Result res = orderService.refundSuccessUpdateStatus(orderId);//根据商户订单号ID更新状态
if (res.getCode() == 200) {
System.out.println("退款成功,并且订单状态已更新");
return xmlSuccess;
}
}
} catch (Exception e) {
System.out.println("退款失败,发生异常,可能由于:" + e.getMessage());
return xmlFail;
}
return xmlFail;
}
/**
* 生成 MD5
* 微信SDK中的生成MD5方法
*
* @param data 待处理数据
* @return MD5结果
*/
private static String MD5(String data) throws Exception {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] array = md.digest(data.getBytes("UTF-8"));
StringBuilder sb = new StringBuilder();
for (byte item : array) {
sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
}
return sb.toString().toUpperCase();
}
private static String init(String key,byte[] str){
SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(),"AES");
Security.addProvider(new BouncyCastleProvider());
try {
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding");
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
String result = new String(cipher.doFinal(str));
return result;
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
}
return null;
}