在微信返回的退款结果通知中,包含了一个加密信息字段req_info

微信支付文档中有提及到如何解密:
前提工作:
1、添加maven依赖

        <dependency>  <groupId>org.bouncycastle</groupId>  <artifactId>bcprov-jdk15on</artifactId>  <version>1.47</version>  </dependency>

2、替换jar包
JAVA运行环境默认不允许256位密钥的AES加解密,解决方法就是修改策略文件

JDK7版本JCE下载地址: http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html
JDK8版本JCE下载地址:http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html

下载后解压,可以看到local_policy.jar和US_export_policy.jar以及readme.txt
如果安装了JRE,将两个jar文件放到%JRE_HOME%\lib\security目录下覆盖原来的文件
如果安装了JDK,将两个jar文件放到%JDK_HOME%\jre\lib\security目录下覆盖原来文件

实践:
以JDK8为例,系统为WIN10,替换上述security文件夹下\policy\limited文件夹和\policy\unlimited文件夹里面的local_policy.jar和US_export_policy.jar这两个文件。

若是在服务器上,则只有在security目录下有local_policy.jar和US_export_policy.jar,替换即可

开始解密:
Base64Util

import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;public class Base64Util {private static final char S_BASE64CHAR[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S','T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't','u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};private static final byte S_DECODETABLE[];static {S_DECODETABLE = new byte[128];for (int i = 0; i < S_DECODETABLE.length; i++)S_DECODETABLE[i] = 127;for (int i = 0; i < S_BASE64CHAR.length; i++)S_DECODETABLE[S_BASE64CHAR[i]] = (byte) i;}/*** @param ibuf* @param obuf* @param wp* @return*/private static int decode0(char ibuf[], byte obuf[], int wp) {int outlen = 3;if (ibuf[3] == '=')outlen = 2;if (ibuf[2] == '=')outlen = 1;int b0 = S_DECODETABLE[ibuf[0]];int b1 = S_DECODETABLE[ibuf[1]];int b2 = S_DECODETABLE[ibuf[2]];int b3 = S_DECODETABLE[ibuf[3]];switch (outlen) {case 1: // '\001'obuf[wp] = (byte) (b0 << 2 & 252 | b1 >> 4 & 3);return 1;case 2: // '\002'obuf[wp++] = (byte) (b0 << 2 & 252 | b1 >> 4 & 3);obuf[wp] = (byte) (b1 << 4 & 240 | b2 >> 2 & 15);return 2;case 3: // '\003'obuf[wp++] = (byte) (b0 << 2 & 252 | b1 >> 4 & 3);obuf[wp++] = (byte) (b1 << 4 & 240 | b2 >> 2 & 15);obuf[wp] = (byte) (b2 << 6 & 192 | b3 & 63);return 3;}throw new RuntimeException("Internal error");}/*** @param data* @param off* @param len* @return*/public static byte[] decode(char data[], int off, int len) {char ibuf[] = new char[4];int ibufcount = 0;byte obuf[] = new byte[(len / 4) * 3 + 3];int obufcount = 0;for (int i = off; i < off + len; i++) {char ch = data[i];if (ch != '=' && (ch >= S_DECODETABLE.length || S_DECODETABLE[ch] == 127))continue;ibuf[ibufcount++] = ch;if (ibufcount == ibuf.length) {ibufcount = 0;obufcount += decode0(ibuf, obuf, obufcount);}}if (obufcount == obuf.length) {return obuf;} else {byte ret[] = new byte[obufcount];System.arraycopy(obuf, 0, ret, 0, obufcount);return ret;}}/*** @param data* @return*/public static byte[] decode(String data) {char ibuf[] = new char[4];int ibufcount = 0;byte obuf[] = new byte[(data.length() / 4) * 3 + 3];int obufcount = 0;for (int i = 0; i < data.length(); i++) {char ch = data.charAt(i);if (ch != '=' && (ch >= S_DECODETABLE.length || S_DECODETABLE[ch] == 127))continue;ibuf[ibufcount++] = ch;if (ibufcount == ibuf.length) {ibufcount = 0;obufcount += decode0(ibuf, obuf, obufcount);}}if (obufcount == obuf.length) {return obuf;} else {byte ret[] = new byte[obufcount];System.arraycopy(obuf, 0, ret, 0, obufcount);return ret;}}/*** @param data* @param off* @param len* @param ostream* @throws IOException*/public static void decode(char data[], int off, int len, OutputStream ostream) throws IOException {char ibuf[] = new char[4];int ibufcount = 0;byte obuf[] = new byte[3];for (int i = off; i < off + len; i++) {char ch = data[i];if (ch != '=' && (ch >= S_DECODETABLE.length || S_DECODETABLE[ch] == 127))continue;ibuf[ibufcount++] = ch;if (ibufcount == ibuf.length) {ibufcount = 0;int obufcount = decode0(ibuf, obuf, 0);ostream.write(obuf, 0, obufcount);}}}/*** @param data* @param ostream* @throws IOException*/public static void decode(String data, OutputStream ostream) throws IOException {char ibuf[] = new char[4];int ibufcount = 0;byte obuf[] = new byte[3];for (int i = 0; i < data.length(); i++) {char ch = data.charAt(i);if (ch != '=' && (ch >= S_DECODETABLE.length || S_DECODETABLE[ch] == 127))continue;ibuf[ibufcount++] = ch;if (ibufcount == ibuf.length) {ibufcount = 0;int obufcount = decode0(ibuf, obuf, 0);ostream.write(obuf, 0, obufcount);}}}/*** @param data* @return*/public static String encode(byte data[]) {return encode(data, 0, data.length);}/*** @param data* @param off* @param len* @return*/public static String encode(byte data[], int off, int len) {if (len <= 0)return "";char out[] = new char[(len / 3) * 4 + 4];int rindex = off;int windex = 0;int rest;for (rest = len - off; rest >= 3; rest -= 3) {int i = ((data[rindex] & 255) << 16) + ((data[rindex + 1] & 255) << 8) + (data[rindex + 2] & 255);out[windex++] = S_BASE64CHAR[i >> 18];out[windex++] = S_BASE64CHAR[i >> 12 & 63];out[windex++] = S_BASE64CHAR[i >> 6 & 63];out[windex++] = S_BASE64CHAR[i & 63];rindex += 3;}if (rest == 1) {int i = data[rindex] & 255;out[windex++] = S_BASE64CHAR[i >> 2];out[windex++] = S_BASE64CHAR[i << 4 & 63];out[windex++] = '=';out[windex++] = '=';} else if (rest == 2) {int i = ((data[rindex] & 255) << 8) + (data[rindex + 1] & 255);out[windex++] = S_BASE64CHAR[i >> 10];out[windex++] = S_BASE64CHAR[i >> 4 & 63];out[windex++] = S_BASE64CHAR[i << 2 & 63];out[windex++] = '=';}return new String(out, 0, windex);}/*** @param data* @param off* @param len* @param ostream* @throws IOException*/public static void encode(byte data[], int off, int len, OutputStream ostream) throws IOException {if (len <= 0)return;byte out[] = new byte[4];int rindex = off;int rest;for (rest = len - off; rest >= 3; rest -= 3) {int i = ((data[rindex] & 255) << 16) + ((data[rindex + 1] & 255) << 8) + (data[rindex + 2] & 255);out[0] = (byte) S_BASE64CHAR[i >> 18];out[1] = (byte) S_BASE64CHAR[i >> 12 & 63];out[2] = (byte) S_BASE64CHAR[i >> 6 & 63];out[3] = (byte) S_BASE64CHAR[i & 63];ostream.write(out, 0, 4);rindex += 3;}if (rest == 1) {int i = data[rindex] & 255;out[0] = (byte) S_BASE64CHAR[i >> 2];out[1] = (byte) S_BASE64CHAR[i << 4 & 63];out[2] = 61;out[3] = 61;ostream.write(out, 0, 4);} else if (rest == 2) {int i = ((data[rindex] & 255) << 8) + (data[rindex + 1] & 255);out[0] = (byte) S_BASE64CHAR[i >> 10];out[1] = (byte) S_BASE64CHAR[i >> 4 & 63];out[2] = (byte) S_BASE64CHAR[i << 2 & 63];out[3] = 61;ostream.write(out, 0, 4);}}/*** @param data* @param off* @param len* @param writer* @throws IOException*/public static void encode(byte data[], int off, int len, Writer writer) throws IOException {if (len <= 0)return;char out[] = new char[4];int rindex = off;int rest = len - off;int output = 0;do {if (rest < 3)break;int i = ((data[rindex] & 255) << 16) + ((data[rindex + 1] & 255) << 8) + (data[rindex + 2] & 255);out[0] = S_BASE64CHAR[i >> 18];out[1] = S_BASE64CHAR[i >> 12 & 63];out[2] = S_BASE64CHAR[i >> 6 & 63];out[3] = S_BASE64CHAR[i & 63];writer.write(out, 0, 4);rindex += 3;rest -= 3;if ((output += 4) % 76 == 0)writer.write("\n");}while (true);if (rest == 1) {int i = data[rindex] & 255;out[0] = S_BASE64CHAR[i >> 2];out[1] = S_BASE64CHAR[i << 4 & 63];out[2] = '=';out[3] = '=';writer.write(out, 0, 4);} else if (rest == 2) {int i = ((data[rindex] & 255) << 8) + (data[rindex + 1] & 255);out[0] = S_BASE64CHAR[i >> 10];out[1] = S_BASE64CHAR[i >> 4 & 63];out[2] = S_BASE64CHAR[i << 2 & 63];out[3] = '=';writer.write(out, 0, 4);}}}
import java.security.MessageDigest;public class MD5Util {public final static String MD5(String s) {char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};try {byte[] btInput = s.getBytes();// 获得MD5摘要算法的 MessageDigest 对象MessageDigest mdInst = MessageDigest.getInstance("MD5");// 使用指定的字节更新摘要mdInst.update(btInput);// 获得密文byte[] md = mdInst.digest();// 把密文转换成十六进制的字符串形式int j = md.length;char str[] = new char[j * 2];int k = 0;for (int i = 0; i < j; i++) {byte byte0 = md[i];str[k++] = hexDigits[byte0 >>> 4 & 0xf];str[k++] = hexDigits[byte0 & 0xf];}return new String(str);} catch (Exception e) {e.printStackTrace();return null;}}private static String byteArrayToHexString(byte b[]) {StringBuffer resultSb = new StringBuffer();for (int i = 0; i < b.length; i++)resultSb.append(byteToHexString(b[i]));return resultSb.toString();}private static String byteToHexString(byte b) {int n = b;if (n < 0)n += 256;int d1 = n / 16;int d2 = n % 16;return hexDigits[d1] + hexDigits[d2];}public static String MD5Encode(String origin, String charsetname) {String resultString = null;try {resultString = new String(origin);MessageDigest md = MessageDigest.getInstance("MD5");if (charsetname == null || "".equals(charsetname))resultString = byteArrayToHexString(md.digest(resultString.getBytes()));elseresultString = byteArrayToHexString(md.digest(resultString.getBytes(charsetname)));} catch (Exception exception) {}return resultString;}private static final String hexDigits[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};}``````java
import org.bouncycastle.jce.provider.BouncyCastleProvider;import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.security.Security;public class AESUtil {/*** 密钥算法*/private static final String ALGORITHM = "AES";/*** 加解密算法/工作模式/填充方式*/private static final String ALGORITHM_MODE_PADDING = "AES/ECB/PKCS7Padding";/*** 生成key*///微信支付API密钥设置路径:微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置private static String paySign = "微信支付API密钥";//对商户key做md5,得到32位小写key*private static SecretKeySpec key = new SecretKeySpec(MD5Util.MD5Encode(paySign, "UTF-8").toLowerCase().getBytes(), ALGORITHM);static {}/*** AES加密** @param data* @return* @throws Exception*/public static String encryptData(String data) throws Exception {Security.addProvider(new BouncyCastleProvider());// 创建密码器Cipher cipher = Cipher.getInstance(ALGORITHM_MODE_PADDING, "BC");// 初始化cipher.init(Cipher.ENCRYPT_MODE, key);return Base64Util.encode(cipher.doFinal(data.getBytes()));}/*** AES解密**(1)对加密串A做base64解码,得到加密串B*(2)用key*对加密串B做AES-256-ECB解密(PKCS7Padding)* @param base64Data* @return* @throws Exception*/public static String decryptData(String base64Data) throws Exception {Security.addProvider(new BouncyCastleProvider());Cipher cipher = Cipher.getInstance(ALGORITHM_MODE_PADDING, "BC");cipher.init(Cipher.DECRYPT_MODE, key);return new String(cipher.doFinal(Base64Util.decode(base64Data)));}public static void main(String[] args) throws Exception {String A = "微信返回的加密信息req_info";System.out.println(AESUtil.decryptData(A));}```

解密微信退款结果通知中的加密信息req_info遇到的坑相关推荐

  1. 微信退款通知req_info解密java_2018.05.24 解密微信退款结果通知中的加密信息req_info...

    在微信返回的退款结果通知中,包含了一个加密信息字段req_info 微信支付文档中有提及到如何解密: 现在我们就一步一步解密得到返回的字段信息: 前提工作: 1.添加maven依赖 org.bounc ...

  2. java微信退款解密,微信退款-异步通知 报文解密

    拿到报文 对req_info 用商户秘钥进行解密 package com.ly.upg.message.util; import com.alibaba.fastjson.JSONObject; im ...

  3. 微信退款异步通知获得的req_infoAES加密和解密方法以及常见的问题

    在接触到微信退款时了解到AES解密 微信退款异步通知接口地址 https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=9_16&index= ...

  4. 【java】微信退款结果通知解密

    整理了一份较为完整的java关于微信退款结果通知解密 (1)对加密串A做base64解码,得到加密串B (2)对商户key做md5,得到32位小写key* ( key设置路径:微信商户平台(pay.w ...

  5. 利用 node.js 云函数解密获取微信小程序的手机号码等加密信息 encryptedData 的内容。

    首先你必须会用微信小程序的云函数功能: 1.创建一个名为token的云函数 2.在云开发的云函数管理中添加对应的token云函数 3.在开发工具中编辑云函数token 4.点击右键,安装并部署 大致是 ...

  6. php微信退款回调通知,微信退款异步回调通知

    以上为微信官方的文档,想要实现微信退款通知处理业务,使用的thinkphp3.2 通过对上述完成 使用php 无论如何对都req_info 无法解密 求大神指导 ,或提供一个dmeo const CI ...

  7. 微信退款异步通知解密异常-填充无效,无法被移除

    2019独角兽企业重金招聘Python工程师标准>>> 该问题是怎么引起的? AESDecrypt 加密处理发生异常 重现步骤 使用模拟工具 POSTMan 发送模拟通知 示例报文一 ...

  8. 解密微信小程序用户敏感数据获取用户信息

    /*** 解密用户敏感数据获取用户信息** @param encryptedData 包括敏感数据在内的完整用户信息的加密数据* @param sessionKey 数据进行加密签名的密钥 通过get ...

  9. SpringAop @AfterThrowing通知中获取异常信息并且在控制台打印

    @AfterThrowing(pointcut = "anyOldTransfer()",throwing ="ex") public void afterTh ...

最新文章

  1. 【计算机网络】数据链路层 : 选择重传协议 SR ( 帧分类 | “发送方“ 确认帧、超时事件 | “接受方“ 接收帧机制 | 滑动窗口长度 | 计算示例 )★
  2. JavaScript 学习笔记-- ES6学习(一)介绍以及Babel的使用
  3. 四十二、开始Vuex的学习:如何在Vue中使用Vuex
  4. 值班问题:insert语句插入了两条数据?
  5. XSS:RPO(Relative Path Overwrite)攻击
  6. elasticsearch 查询数据 | 分页查询
  7. 125条常见的java面试笔试题大汇总1
  8. (WCF)阅读WCF分布式开发步步为赢(2)自定义托管宿主WCF解决方案开发配置过程详解的一点心得...
  9. svn版本管理软件——svn分支管理
  10. 电脑硬件故障排除经验
  11. 滴滴校招面经(已拿offer)
  12. 计算机二级考试准考证打印指南 计算机二级考试准考证打印入口
  13. 2021 ICCV论文分享 | 遮挡边界检测
  14. 360极速浏览器以及360安全浏览器在兼容模式下验证码图片显示不来,但是极速模式可以显示?
  15. (信贷风控十一)随机森林在催收评分卡还款率模型的应用(python代码实现)
  16. 【腾讯Bugly干货分享】QFix探索之路—手Q热补丁轻量级方案
  17. java中使用poi读取excel单元格日期值
  18. win10 如何开启guest
  19. 物联网的物流企业信息集成综合管理平台,主要有哪些特征?
  20. 如何导出Navicat的数据库连接配置

热门文章

  1. Unity 实现像LOL选择皮肤效果(卡片抽换效果)的制作思路
  2. 如何查找SCI期刊的iso缩写?
  3. 记一次ansible执行报错Structure needs cleaning
  4. 广州服务器哪个区最多,广州哪个区人口最多?官方数据来了
  5. A级项目发布!2018中国区块链行业白皮书 | 鲸准研究院出品
  6. 基于Matlab创建跟踪场景、模拟目标运动和模拟雷达检测仿真(附源码)
  7. 景观生态学原理| 4 景观生态过程
  8. Elasticsearch极速入门
  9. 新的JAX Mag问题:探索物联网世界
  10. vsomeip第一课: vsomeip的安装和demo演示