微信支付分回调接口中返回的数据为AES非对称密钥加密数据,需要进行解密才可读取,官方文档中只提供了JAVA、PHP、Python、GO的参考实例,未提供NodeJS版本的示例,本文提供NodeJS版本的解密实现。
1、用商户平台上设置的APIv3密钥(微信商户平台(pay.weixin.qq.com)-账户设置-API安全-设置APIv3密钥),记为key
2、针对resource.algorithm中描述的算法(目前为AEAD_AES_256_GCM),取得对应的参数nonce和associated_data。
3、使用key、nonce和associated_data,对数据密文resource.ciphertext进行解密,得到JSON形式的资源对象
注: AEAD_AES_256_GCM算法的接口细节,请参考rfc5116。微信支付使用的密钥key长度为32个字节,随机串nonce长度12个字节,associated_data长度小于16个字节并可能为空。
/**
* 使用AEAD_AES_256_GCM解密数据
* @param cipherText 密文
* @param key API V3密钥
* @param iv nonce字符串
* @param add associated_data字符串
*/
decodeByAES: (cipherText: any, key: string, iv: string, add: string) => {
let rst = '';
cipherText = Buffer.from(cipherText, 'base64');
let authTag = cipherText.slice(cipherText.length - 16);
let data = cipherText.slice(0, cipherText.length - 16);
let decipher = crypto.createDecipheriv('aes-256-gcm', key, iv);
decipher.setAuthTag(authTag);
decipher.setAAD(Buffer.from(add));
rst = decipher.update(data, 'binary', 'utf8');
try {
rst += decipher.final('utf-8');
} catch (e) {
think.logger.error(e.toString());
}
return rst;
},
在最终final时,会报错,抛出异常Error: Unsupported state or unable to authenticate data,我的方法是丢弃掉,因为密文可以被正常解密,这个异常参考文档 Crypter | Apps | Electron
读者如果有更合理的方法请告诉博主。