企业微信开发采坑——会话代理,会话内容解密

在聊企业微信会话内容解密之前,先说一说会话内容白名单遇到的问题,因为部署的服务器是不能连接外网的,所以需要通过服务器的另一台机器代理请求访问,先来看一下官方文档给出的描述

/**
     * 拉取聊天记录函数
     * Return值=0表示该API调用成功
     * 
     *
     * @param [in]  sdk                NewSdk返回的sdk指针
     * @param [in]  seq                从指定的seq开始拉取消息,注意的是返回的消息从seq+1开始返回,seq为之前接口返回的最大seq值。首次使用请使用seq:0
     * @param [in]  limit            一次拉取的消息条数,最大值1000条,超过1000条会返回错误
     * @param [in]  proxy            使用代理的请求,需要传入代理的链接。如:socks5://10.0.0.1:8081 或者 http://10.0.0.1:8081
     * @param [in]  passwd            代理账号密码,需要传入代理的账号密码。如 user_name:passwd_123
     * @param [in]  timeout            超时时间,单位秒
     * @param [out] chatDatas        返回本次拉取消息的数据,slice结构体.内容包括errcode/errmsg,以及每条消息内容。示例如下:
     {"errcode":0,"errmsg":"ok","chatdata":[{"seq":196,"msgid":"CAQQ2fbb4QUY0On2rYSAgAMgip/yzgs=","publickey_ver":3,"encrypt_random_key":"ftJ+uz3n/z1DsxlkwxNgE+mL38H42/KCvN8T60gbbtPD+Rta1hKTuQPzUzO6Hzne97MgKs7FfdDxDck/v8cDT6gUVjA2tZ/M7euSD0L66opJ/IUeBtpAtvgVSD5qhlaQjvfKJc/zPMGNK2xCLFYqwmQBZXbNT7uA69Fflm512nZKW/piK2RKdYJhRyvQnA1ISxK097sp9WlEgDg250fM5tgwMjujdzr7ehK6gtVBUFldNSJS7ndtIf6aSBfaLktZgwHZ57ONewWq8GJe7WwQf1hwcDbCh7YMG8nsweEwhDfUz+u8rz9an+0lgrYMZFRHnmzjgmLwrR7B/32Qxqd79A==","encrypt_chat_msg":"898WSfGMnIeytTsea7Rc0WsOocs0bIAerF6de0v2cFwqo9uOxrW9wYe5rCjCHHH5bDrNvLxBE/xOoFfcwOTYX0HQxTJaH0ES9OHDZ61p8gcbfGdJKnq2UU4tAEgGb8H+Q9n8syRXIjaI3KuVCqGIi4QGHFmxWenPFfjF/vRuPd0EpzUNwmqfUxLBWLpGhv+dLnqiEOBW41Zdc0OO0St6E+JeIeHlRZAR+E13Isv9eS09xNbF0qQXWIyNUi+ucLr5VuZnPGXBrSfvwX8f0QebTwpy1tT2zvQiMM2MBugKH6NuMzzuvEsXeD+6+3VRqL"}]}
     *
     * @return 返回是否调用成功
     *      0   - 成功
     *      !=0 - 失败    
     */        
    int GetChatData(WeWorkFinanceSdk_t* sdk, unsigned long long seq, unsigned int limit, const char *proxy,const char* passwd,int timeout,Slice_t* chatDatas);
proxy使用代理的请求,需要传入代理的链接。如:socks5://10.0.0.1:8081 或者 http://10.0.0.1:8081.如不使用代理可以设置为空. 支持sock5跟http代理
paswd代理账号密码,需要传入代理的账号密码。如 user_name:passwd_123

在这里proxy是指我可以访问公网并且添加了对应白名单的机器,paswd是指用户名和密码,中间用【:】分隔。

首先需要一台代理机器,开始我再代理机器A上部署了nginx,并且用curl也可以尝试请求到数据

curl --proxy http://192.168.xx.xx:8001 http://qyapi.weixin.qq.com/cgi-bin/gettoken

但是curl https的时候会返回400

 curl --proxy https://192.168.xx.xx:8001 https://qyapi.weixin.qq.com/cgi-bin/gettoken

这里前面是对应A机器的内网地址,8001是转发服务的端口,nginx的配置也只是利用8001的端口进行监听,然后转发到qyapi.weixin.qq.com,后来在sdk包联调调用的时候,想到转发的接口用到的应该是https请求,但是https在ng中需要升级对应的模块,而且ng上配置也比较多,不能随便乱改,后台直接在A机器上装了squid代理服务。解决问题。

至于ng为什么转发https需要单独的模块,可以参考下面几篇文章

Nginx正向代理请求https报400_ibigboy-CSDN博客

使用 Nginx 搭建 HTTPS 正向代理服务 | Bigzuo's Blog

linux 搭建squid可以参考如下文章,一种是源码安装,一种是yum安装

https://blog.csdn.net/weixin_30363817/article/details/98212574

https://www.cnblogs.com/suntray/p/14452861.html

最后在调用 curl --proxy https://192.168.xx.xx:8001 https://qyapi.weixin.qq.com/cgi-bin/gettoken

成功

------------------------------------------------------------------------------------------------------------------------------

下面继续聊一聊企业微信会话内容开发过程中的解密问题

首先还是看官方文档给出的内容讲解

ChatDatas详解:

 
  1. {"errcode":0,"errmsg":"ok","chatdata":[{"seq":196,"msgid":"CAQQ2fbb4QUY0On2rYSAgAMgip/yzgs=","publickey_ver":3,"encrypt_random_key":"ftJ+uz3n/z1DsxlkwxNgE+mL38H42/KCvN8T60gbbtPD+Rta1hKTuQPzUzO6Hzne97MgKs7FfdDxDck/v8cDT6gUVjA2tZ/M7euSD0L66opJ/IUeBtpAtvgVSD5qhlaQjvfKJc/zPMGNK2xCLFYqwmQBZXbNT7uA69Fflm512nZKW/piK2RKdYJhRyvQnA1ISxK097sp9WlEgDg250fM5tgwMjujdzr7ehK6gtVBUFldNSJS7ndtIf6aSBfaLktZgwHZ57ONewWq8GJe7WwQf1hwcDbCh7YMG8nsweEwhDfUz+u8rz9an+0lgrYMZFRHnmzjgmLwrR7B/32Qxqd79A==","encrypt_chat_msg":"898WSfGMnIeytTsea7Rc0WsOocs0bIAerF6de0v2cFwqo9uOxrW9wYe5rCjCHHH5bDrNvLxBE/xOoFfcwOTYX0HQxTJaH0ES9OHDZ61p8gcbfGdJKnq2UU4tAEgGb8H+Q9n8syRXIjaI3KuVCqGIi4QGHFmxWenPFfjF/vRuPd0EpzUNwmqfUxLBWLpGhv+dLnqiEOBW41Zdc0OO0St6E+JeIeHlRZAR+E13Isv9eS09xNbF0qQXWIyNUi+ucLr5VuZnPGXBrSfvwX8f0QebTwpy1tT2zvQiMM2MBugKH6NuMzzuvEsXeD+6+3VRqL"}]}

返回参数说明:

参数说明
errcode0表示成功,错误返回非0错误码,需要参看errmsg。Uint32类型
errmsg返回信息,如非空为错误原因。String类型
chatdata聊天记录数据内容。数组类型。包括seq、msgid等内容
seq消息的seq值,标识消息的序号。再次拉取需要带上上次回包中最大的seq。Uint64类型,范围0-pow(2,64)-1
msgid消息id,消息的唯一标识,企业可以使用此字段进行消息去重。String类型。msgid以_external结尾的消息,表明该消息是一条外部消息。
publickey_ver加密此条消息使用的公钥版本号。Uint32类型
encrypt_random_key使用publickey_ver指定版本的公钥进行非对称加密后base64加密的内容,需要业务方先base64 decode处理后,再使用指定版本的私钥进行解密,得出内容。String类型
encrypt_chat_msg消息密文。需要业务方使用将encrypt_random_key解密得到的内容,与encrypt_chat_msg,传入sdk接口DecryptData,得到消息明文。String类型

encrypt_random_key内容解密说明:
encrypt_random_key是使用企业在管理端填写的公钥(使用模值为2048bit的秘钥),采用RSA加密算法进行加密处理后base64 encode的内容,加密内容为企业微信产生。RSA使用PKCS1。
企业通过GetChatData获取到会话数据后:
a) 需首先对每条消息的encrypt_random_key内容进行base64 decode,得到字符串str1.
b) 使用publickey_ver指定版本的私钥,使用RSA PKCS1算法对str1进行解密,得到解密内容str2.
c) 得到str2与对应消息的encrypt_chat_msg,调用下方描述的DecryptData接口,即可获得消息明文。

这里先聊一聊后台怎么配置,在配置秘钥的时候,先要生成好公钥和私钥,如果想方便一些,可以到下面的网站直接生成在线RSA公钥加密解密、RSA public key encryption and decryption--查错网

 把上面的公钥内容设置到后台的公钥中,下面的私钥自己保存好,用于解密

然后解密的内容可以参考下面几篇文章

企业微信会话存档消息解密(Java RSA PKCS1解密) - 是谁啊? - 博客园

这里主要说一下PKCS8的秘钥格式,由于我当时生成秘钥的时候没有选秘钥格式,默认的是PKCS8,后来在同事的帮助下最终还是解析出来了数据内容。

记得调试的时候把

-----BEGIN PUBLIC KEY-----

-----END PUBLIC KEY-----

-----BEGIN PRIVATE KEY-----

-----END PRIVATE KEY-----

-----BEGIN RSA PRIVATE KEY-----

-----END RSA PRIVATE KEY-----

换行符/n都替换成""空字符串。

//encryptionDto是解析出来的密文对象
String encryptChatMsg = encryptionDto.getEncrypt_chat_msg();
String encryptRandomKey = encryptionDto.getEncrypt_random_key();

String encrypt_key = null;
try {
    //syncSessionUtil.getPrivateKey()是自己保存的对应的私钥

    encrypt_key = RSAUtil.getPrivateKey3(encryptRandomKey,syncSessionUtil.getPrivateKey());
} catch (Exception e) {
  log.error("解密数据会话数据失败 encryptionDto:"+JSONObject.toJSONString(encryptionDto), e);
  continue;
}
// 将获取到的数据进行解密操作
//long msg = Finance.NewSlice();
log.info("=======msgs==msgs=======:"+slice);
int ret = Finance.DecryptData(sdk, encrypt_key, encryptChatMsg, slice);
log.info("=======ret==ret=======:"+ret);
String decrypt_msg = Finance.GetContentFromSlice(slice);// 解密后的消息
log.info("解密后的内容 {}", decrypt_msg);

import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

/**
 * RSA加密和解密工具
 *
 */
public class RSAUtil {

	/**
	 * 数字签名,密钥算法
	 */
	private static final String RSA_KEY_ALGORITHM = "RSA";

	/**
	 * 数字签名签名/验证算法
	 */
	private static final String SIGNATURE_ALGORITHM = "MD5withRSA";

	/**
	 * RSA密钥长度,RSA算法的默认密钥长度是1024密钥长度必须是64的倍数,在512到65536位之间
	 */
	private static final int KEY_SIZE = 1024;

	/**
	 * 生成密钥对
	 */
	private static Map<String, String> initKey() throws Exception {
		KeyPairGenerator keygen = KeyPairGenerator.getInstance(RSA_KEY_ALGORITHM);
		SecureRandom secrand = new SecureRandom();
		/**
		 * 初始化随机产生器
		 */
		secrand.setSeed("initSeed".getBytes());
		/**
		 * 初始化密钥生成器
		 */
		keygen.initialize(KEY_SIZE, secrand);
		KeyPair keys = keygen.genKeyPair();

		byte[] pub_key = keys.getPublic().getEncoded();
		String publicKeyString = Base64.encodeBase64String(pub_key);

		byte[] pri_key = keys.getPrivate().getEncoded();
		String privateKeyString = Base64.encodeBase64String(pri_key);

		Map<String, String> keyPairMap = new HashMap<String, String>();
		keyPairMap.put("publicKeyString", publicKeyString);
		keyPairMap.put("privateKeyString", privateKeyString);

		return keyPairMap;
	}

	/**
	 * 密钥转成字符串
	 *
	 * @param key
	 * @return
	 */
	public static String encodeBase64String(byte[] key) {
		return Base64.encodeBase64String(key);
	}

	/**
	 * 密钥转成byte[]
	 *
	 * @param key
	 * @return
	 */
	public static byte[] decodeBase64(String key) {
		return Base64.decodeBase64(key);
	}

	/**
	 * 公钥加密
	 *
	 * @param data      加密前的字符串
	 * @param publicKey 公钥
	 * @return 加密后的字符串
	 * @throws Exception
	 */
	public static String encryptByPubKey(String data, String publicKey) throws Exception {
		byte[] pubKey = RSAUtil.decodeBase64(publicKey);
		byte[] enSign = encryptByPubKey(data.getBytes(), pubKey);
		return Base64.encodeBase64String(enSign);
	}

	/**
	 * 公钥加密
	 *
	 * @param data   待加密数据
	 * @param pubKey 公钥
	 * @return
	 * @throws Exception
	 */
	public static byte[] encryptByPubKey(byte[] data, byte[] pubKey) throws Exception {
		X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(pubKey);
		KeyFactory keyFactory = KeyFactory.getInstance(RSA_KEY_ALGORITHM);
		PublicKey publicKey = keyFactory.generatePublic(x509KeySpec);
		Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
		cipher.init(Cipher.ENCRYPT_MODE, publicKey);
		return cipher.doFinal(data);
	}

	/**
	 * 私钥加密
	 *
	 * @param data       加密前的字符串
	 * @param privateKey 私钥
	 * @return 加密后的字符串
	 * @throws Exception
	 */
	public static String encryptByPriKey(String data, String privateKey) throws Exception {
		byte[] priKey = RSAUtil.decodeBase64(privateKey);
		byte[] enSign = encryptByPriKey(data.getBytes(), priKey);
		return Base64.encodeBase64String(enSign);
	}

	/**
	 * 私钥加密
	 *
	 * @param data   待加密的数据
	 * @param priKey 私钥
	 * @return 加密后的数据
	 * @throws Exception
	 */
	public static byte[] encryptByPriKey(byte[] data, byte[] priKey) throws Exception {
		PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(priKey);
		KeyFactory keyFactory = KeyFactory.getInstance(RSA_KEY_ALGORITHM);
		PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
		Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
		cipher.init(Cipher.ENCRYPT_MODE, privateKey);
		return cipher.doFinal(data);
	}

	/**
	 * 公钥解密
	 *
	 * @param data   待解密的数据
	 * @param pubKey 公钥
	 * @return 解密后的数据
	 * @throws Exception
	 */
	public static byte[] decryptByPubKey(byte[] data, byte[] pubKey) throws Exception {
		X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(pubKey);
		KeyFactory keyFactory = KeyFactory.getInstance(RSA_KEY_ALGORITHM);
		PublicKey publicKey = keyFactory.generatePublic(x509KeySpec);
		Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
		cipher.init(Cipher.DECRYPT_MODE, publicKey);
		return cipher.doFinal(data);
	}

	/**
	 * 公钥解密
	 *
	 * @param data      解密前的字符串
	 * @param publicKey 公钥
	 * @return 解密后的字符串
	 * @throws Exception
	 */
	public static String decryptByPubKey(String data, String publicKey) throws Exception {
		byte[] pubKey = RSAUtil.decodeBase64(publicKey);
		byte[] design = decryptByPubKey(Base64.decodeBase64(data), pubKey);
		return new String(design);
	}

	/*private static PrivateKey getPrivateKey (String privateKey) throws Exception {
		Reader privateKeyReader = new StringReader(privateKey);
		PEMParser privatePemParser = new PEMParser(privateKeyReader);
		Object privateObject = privatePemParser.readObject();
		if (privateObject instanceof PEMKeyPair) {
			PEMKeyPair pemKeyPair = (PEMKeyPair) privateObject;
			JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
			PrivateKey privKey = converter.getPrivateKey(pemKeyPair.getPrivateKeyInfo());
			return privKey;
		}
		return null;
	}*/

//	//读取pkcs1格式的private key
//	public static PrivateKey getPrivateKey2(String privKeyPEM) throws Exception{
//
//		String privKeyPEMnew = privKeyPEM.replaceAll("\\n", "").replace("-----BEGIN RSA PRIVATE KEY-----", "").replace("-----END RSA PRIVATE KEY-----", "");
//		byte[] bytes = RSAUtil.decodeBase64(privKeyPEMnew);
//
//		DerInputStream derReader = new DerInputStream(bytes);
//		DerValue[] seq = derReader.getSequence(0);
//		BigInteger modulus = seq[1].getBigInteger();
//		BigInteger publicExp = seq[2].getBigInteger();
//		BigInteger privateExp = seq[3].getBigInteger();
//		BigInteger prime1 = seq[4].getBigInteger();
//		BigInteger prime2 = seq[5].getBigInteger();
//		BigInteger exp1 = seq[6].getBigInteger();
//		BigInteger exp2 = seq[7].getBigInteger();
//		BigInteger crtCoef = seq[8].getBigInteger();
//
//		RSAPrivateCrtKeySpec keySpec = new RSAPrivateCrtKeySpec(modulus, publicExp, privateExp, prime1, prime2, exp1, exp2, crtCoef);
//		KeyFactory keyFactory = KeyFactory.getInstance("RSA");
//		PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
//		return privateKey;
//	}
	/*public static RSAPrivateKey loadPrivateKeyByStr(String privateKeyStr)
			throws Exception {
		try {

			byte[] buffer = Base64.decodeBase64(privateKeyStr);
			PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);
			KeyFactory keyFactory = KeyFactory.getInstance("RSA");
			return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
		} catch (NoSuchAlgorithmException e) {
			throw new Exception("无此算法");
		} catch (InvalidKeySpecException e) {
			throw new Exception("私钥非法");
		} catch (NullPointerException e) {
			throw new Exception("私钥数据为空");
		}
	}*/

	/**
	 * 私钥解密
	 *
	 * @param data   待解密的数据
	 * @param priKey 私钥
	 * @return
	 * @throws Exception
	 */
	/*public static byte[] decryptByPriKey(byte[] data, byte[] priKey) throws Exception {
//		PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(priKey);
//		KeyFactory keyFactory = KeyFactory.getInstance(RSA_KEY_ALGORITHM);
//		PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);


		RSAPrivateKeyStructure asn1PrivKey = new RSAPrivateKeyStructure((ASN1Sequence) ASN1Sequence.fromByteArray(priKey));
        RSAPrivateKeySpec rsaPrivKeySpec = new RSAPrivateKeySpec(asn1PrivKey.getModulus(), asn1PrivKey.getPrivateExponent());
        KeyFactory keyFactory= KeyFactory.getInstance("RSA");
        PrivateKey privateKey= keyFactory.generatePrivate(rsaPrivKeySpec);
		Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
		cipher.init(Cipher.DECRYPT_MODE, privateKey);
		return cipher.doFinal(data);
	}*/

	/**
	 * 私钥解密
	 *
	 * @param data       解密前的字符串
	 * @param privateKey 私钥
	 * @return 解密后的字符串
	 * @throws Exception
	 */
	/*public static String decryptByPriKey(String data, String privateKey) throws Exception {
		Security.addProvider(new BouncyCastleProvider());
		Cipher rsa = Cipher.getInstance("RSA/ECB/PKCS1Padding", "BC");
		rsa.init(Cipher.DECRYPT_MODE, getPrivateKey(privateKey));
		byte[] utf8 = rsa.doFinal(Base64.decodeBase64(data));
		String result = new String(utf8,"UTF-8");
		return result;
	}*/

	/**
	 * RSA签名
	 *
	 * @param data   待签名数据
	 * @param priKey 私钥
	 * @return 签名
	 * @throws Exception
	 */
	public static String sign(byte[] data, byte[] priKey) throws Exception {
		// 取得私钥
		PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(priKey);
		KeyFactory keyFactory = KeyFactory.getInstance(RSA_KEY_ALGORITHM);
		// 生成私钥
		PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
		// 实例化Signature
		Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
		// 初始化Signature
		signature.initSign(privateKey);
		// 更新
		signature.update(data);
		return Base64.encodeBase64String(signature.sign());
	}

	/**
	 * RSA校验数字签名
	 *
	 * @param data   待校验数据
	 * @param sign   数字签名
	 * @param pubKey 公钥
	 * @return boolean 校验成功返回true,失败返回false
	 */
	public boolean verify(byte[] data, byte[] sign, byte[] pubKey) throws Exception {
		// 实例化密钥工厂
		KeyFactory keyFactory = KeyFactory.getInstance(RSA_KEY_ALGORITHM);
		// 初始化公钥
		X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(pubKey);
		// 产生公钥
		PublicKey publicKey = keyFactory.generatePublic(x509KeySpec);
		// 实例化Signature
		Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
		// 初始化Signature
		signature.initVerify(publicKey);
		// 更新
		signature.update(data);
		// 验证
		return signature.verify(sign);
	}

	// 用此方法先获取秘钥
	public static String getPrivateKey3(String str, String privKeyPEMnew) throws Exception {

//		String privKeyPEMnew = privKeyPEM.replaceAll("\\n", "").replace("-----BEGIN PRIVATE KEY-----", "").replace("-----END PRIVATE KEY-----", "");

		byte[] decoded = java.util.Base64.getDecoder().decode(privKeyPEMnew);
		java.security.interfaces.RSAPrivateKey priKey = (java.security.interfaces.RSAPrivateKey) KeyFactory.getInstance("RSA")
				.generatePrivate(new PKCS8EncodedKeySpec(decoded));
		// 64位解码加密后的字符串
		byte[] inputByte = java.util.Base64.getDecoder().decode(str);

		// RSA解密
		Cipher cipher = Cipher.getInstance("RSA");
		cipher.init(Cipher.DECRYPT_MODE, priKey);
		String outStr = new String(cipher.doFinal(inputByte));
		return outStr;
	}

}

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
微信支付回调结果包括两部分:一是在 HTTP 请求中的明文参数,二是经过加密后在 HTTP 请求中的密文参数。其中,明文参数需要校验其真实性,而密文参数需要进行解密才能获取其中的明文参数。 以下是Java代码示例,演示如何对微信支付回调结果进行解密: ```java import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.util.Base64; public class WeChatPayCallbackDecryptor { public static String decrypt(String encryptedData, String sessionKey, String iv) throws Exception { byte[] encryptedBytes = Base64.getDecoder().decode(encryptedData); byte[] sessionKeyBytes = Base64.getDecoder().decode(sessionKey); byte[] ivBytes = Base64.getDecoder().decode(iv); SecretKeySpec keySpec = new SecretKeySpec(sessionKeyBytes, "AES"); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(ivBytes)); byte[] decryptedBytes = cipher.doFinal(encryptedBytes); return new String(decryptedBytes); } } ``` 其中,`encryptedData` 为加密后的回调结果,`sessionKey` 为微信支付 API 返回的会话密钥,`iv` 为微信支付 API 返回的加密算法的初始向量。 调用示例: ```java String encryptedData = "xxxxx"; // 加密后的回调结果 String sessionKey = "yyyyy"; // 微信支付 API 返回的会话密钥 String iv = "zzzzz"; // 微信支付 API 返回的加密算法的初始向量 String decryptedData = WeChatPayCallbackDecryptor.decrypt(encryptedData, sessionKey, iv); System.out.println(decryptedData); ``` 解密后的结果为一个 JSON 字符串,包含了微信支付回调的各项参数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值