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

微信支付文档中有提及到如何解密:

现在我们就一步一步解密得到返回的字段信息:

前提工作:

1、添加maven依赖

org.bouncycastle

bcprov-jdk15on

1.47

2、替换jar包

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

在官方网站下载JCE无限制权限策略文件

下载后解压,可以看到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,替换即可

开始解密:

1、用到的工具类Base64Util.java 和 MD5Util.java

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);

}

}

}

MD5Util

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()));

else

resultString = 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"};

}

2、解密

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));

}

至此就解密完毕啦,返回的的xml结构的数据,包含微信退款单号等数据,之后就可以自由处理啦!

微信退款通知req_info解密java_2018.05.24 解密微信退款结果通知中的加密信息req_info...相关推荐

  1. 解密微信退款结果通知中的加密信息req_info遇到的坑

    在微信返回的退款结果通知中,包含了一个加密信息字段req_info 微信支付文档中有提及到如何解密: 前提工作: 1.添加maven依赖 <dependency> <groupId& ...

  2. 微信退款通知,退款回调数据解密.SHA256签名AEAD_AES_256_GCM解密

    $xmlResult = file_get_contents("php://input");//获取微信的数据$result = $this->xmlToArray($xml ...

  3. 微信java 签名验证_JAVA版微信小程序用户数据的签名验证和加解密

    签名验证和加解密 数据签名校验 为了确保 开放接口 返回用户数据的安全性,微信会对明文数据进行签名.开发者可以根据业务需要对数据包进行签名校验,确保数据的完整性. 签名校验算法涉及用户的session ...

  4. Python如何实现24个微信大群万人同步转发直播?

    作者 | 猪哥66 来源 | CSDN博客 今天我们来学习微信机器人多群转发做同步图文直播! 一.背景介绍 猪哥一年前在建Python学习群的时候就说过,要邀请企业大佬来学习群做直播. 其实文章早就写 ...

  5. Python如何实现24个微信大群(共万人)同步转发直播?

    很多人传言微信网页版(https://wx.qq.com/)接口已经被封了,所以所有的微信都不能登录网页版,这是错误的. 2019年7月微信对网页版微信进行了动态安全策略调整,导致一大批微信号不能登录 ...

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

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

  7. http://www.cnblogs.com/tornadomeet/archive/2012/05/24/2515980.html

    转载: Deep Learning(深度学习): ufldl的2个教程(这个没得说,入门绝对的好教程,Ng的,逻辑清晰有练习):一 ufldl的2个教程(这个没得说,入门绝对的好教程,Ng的,逻辑清晰 ...

  8. 46.深度解密四十六:微信KOl、微博大V等“移动营销资源”全揭秘

    网络营销推广技术.技巧深度解密(四十六)指南: 1.本文档适合零基础以及互联网营销推广工作者,主要讲解移动资源的相关问题. 2.原创版权文档,任何抄袭或者全部.部分模仿都是侵权行为. 3.敬畏法律,尊 ...

  9. PC微信逆向:两种姿势教你解密数据库文件

    文章目录 定位数据库文件密码 定位数据库密钥的思路 获取数据库密钥的实战分析 CreateFileW断点 常见错误 排查堆栈 排查堆栈地址 单步跟踪 用代码实现解密数据库 编译选项 解密代码 实际效果 ...

最新文章

  1. matlab labs,DOCOMO Beijing Labs 借助 MATLAB 将移动通信技术的开发时间缩短 50%
  2. 重温经典之《企业应用架构模式》——.NET中的架构模式运用 (Base Patterns 1)
  3. 使用Python操作MySQL数据库
  4. centos7.6+vim8.1
  5. 解决安装kali 2020.1版本后的中文乱码问题:只需要安装中文字体(而不需要像之前版本那样需要选择locales和编码)。
  6. 自旋锁/互斥锁/读写锁/递归锁的区别与联系
  7. linux文件IO——目录操作和文件属性
  8. 现代软件工程 第三章 【软件工程师的成长】练习与讨论
  9. 这十个不常见但却十分实用的Python库,你知道几个?
  10. [gtest][001] A quick introduction to the Google C++ Testing Framework
  11. php查询mongo数据库效率,2000000万数据库 MongoDB 查询速度慢
  12. NSX发布Guest Introspection虚拟机时,主机报错的解决方法
  13. Python 编程技巧:PyCharm 官方汉化插件
  14. 博客9-12css2
  15. 考研数学(二)知识点回顾及笔记(第五章 定积分及应用)
  16. GridView指定列求和
  17. 我的家用户外监控摄像头的选购和安装记录
  18. 基于任务点的加速仿真
  19. Lombok Plugin
  20. 【物联网中间件平台-04】YFIOs驱动开发指南

热门文章

  1. 微信小程序实验报告-----学生家教小程序
  2. 丁俊辉——超越所有奥运冠军的平民英雄
  3. 105页5万字XXX县30MWp光伏发电项目可行性报告
  4. 一款简洁优雅的 Typecho主题-VOID
  5. Vetur can‘t find`package.json`in路径 和 Vetur can‘t find`tsconfig.json`or`jsconfig.json`in路径 VSCode弹框
  6. Helm的安装和使用
  7. 【引言】浙大机器学习课程记录
  8. 吉大珠海学院计算机系,杨永健-吉林大学计算机科学与技术学院
  9. The isls找不到服务器,theisle搜不到国内服务器
  10. 基于计算机视觉的UC小游戏外挂