我使用云函数订阅了微信小店的事件消息,现在我在测试订单的相关消息,但是发现接收到的消息有的能解密,有的就解密失败。
消息的签名验证是通过的。
报错信息如下:
解密代码如下:
function decryptWXMessage(EncodingAESKey, Encrypt, expectedAppId) {
try {
console.log('开始解密...');
console.log('EncodingAESKey:', EncodingAESKey);
console.log('Encrypt长度:', Encrypt.length);
console.log('expectedAppId:', expectedAppId);
// 1. 生成AESKey
const aesKey = Buffer.from(EncodingAESKey + '=', 'base64');
console.log('AESKey字节长度:', aesKey.length);
console.log('AESKey (hex):', aesKey.toString('hex'));
if (aesKey.length !== 32) {
throw new Error('Invalid AES Key length');
}
// 2. Base64解码Encrypt密文
const tmpMsg = Buffer.from(Encrypt, 'base64');
console.log(`TmpMsg字节长度: ${tmpMsg.length}`);
// 3. AES解密
const iv = aesKey.slice(0, 16); // CBC模式的IV是AESKey的前16字节
console.log('IV (hex):', iv.toString('hex'));
const decipher = crypto.createDecipheriv('aes-256-cbc', aesKey, iv);
decipher.setAutoPadding(true); // 自动处理PKCS#7填充
let decrypted = Buffer.concat([decipher.update(tmpMsg), decipher.final()]);
console.log(`FullStr字节长度: ${decrypted.length}`);
console.log('FullStr (hex):', decrypted.toString('hex'));
// 4. 解析FullStr结构
// random(16B) + msg_len(4B) + msg + appid
const randomStr = decrypted.slice(0, 16).toString('hex');
console.log(`random(16B): ${randomStr}`);
// 读取msg_len (网络字节序,大端序)
const msgLen = decrypted.readUInt32BE(16);
console.log(`msg_len: ${msgLen}`);
// 提取msg
const msgStart = 20; // 16 + 4
const msgEnd = msgStart + msgLen;
if (msgEnd > decrypted.length) {
throw new Error(`消息长度超出范围: msgEnd=${msgEnd}, decrypted.length=${decrypted.length}`);
}
const msg = decrypted.slice(msgStart, msgEnd).toString('utf8');
console.log(`msg: ${msg}`);
// 提取appid
const appid = decrypted.slice(msgEnd).toString('utf8');
console.log(`appid: ${appid}`);
// 5. 验证AppId
if (appid !== expectedAppId) {
throw new Error(`AppId不匹配: 期望 ${expectedAppId}, 实际 ${appid}`);
}
return {
random: randomStr,
msg_len: msgLen,
msg: JSON.parse(msg), // 解析JSON消息
appid: appid
};
} catch (error) {
console.error('解密失败:', error.message);
console.error(error.stack);
throw error;
}
}
无法解密的这条消息的消息参数如下:
body: '{"ToUserName":"gh_5f4c50c935eb","Encrypt":"GKsTtFYTq3g4XOQzh7aa2dz+0fv0f4Pnj+7yhd5QdijrNQNUYtjrgCmmMwdZOK4zBqElQ5B/ga1ooq2SP8pmjsDe0qs9t9+dPYbCTrjQomqKf4S/33UYnqbo7Ph+aLCyY8i8HxFstbAyO71cF+jKZHOqWfbESFedLoNFaq+C8oqx1CxECtMtvqFV/ToUdqy69PTH8WoRMbOnHU1jfXrAIPmGcCmoU5RkUCCZjwCqGZhfexER0bjaLuKBrmGa6aSJ66X4F8Ho7P4KTBcA83Rcs4FQWPGbC5TpsyGIxXm/7JHLXVXwHyRkwL+6ArAHCQa9HyYNwJhKQJ2VsGFMhZCt6k9Iv32CSJCWNHxFA/+1BrotS3tdN+WWvDYrTh7p+vz3"}';
aesKey:'MqueyTZsLhJS3o3L4gTkuapiwXc1K2ASkUD8kDrkdAS';
appId:'wxfeedff1d7050a2fd'
可以看到,签名都是验证通过的:
另外,提供一组解密成功的参数:
body: '{"ToUserName":"gh_5f4c50c935eb","Encrypt":"Iv0naarho/gX68QP+KOeLe9FIrdlqWRtkVblvvURvFDT963SAcicwclw9stFBmC1DMi7WrigFElTiIGX+hisCSlxW2RSZ2bmTD7jbNaL/LeoKWJSNmA4fQWrjT7RXljqGWEf+p/IkY5QLjg0c8uWFMsHVX9UTRd8K/JXl/uCOfJxfpdTfIEB3VZTNJZbmvsBNsutwpDKNSCPiDwgGB5G6Aza6bZy2g9tVRBzoDHMyDJ3M9pk4o8189o29xfM6v0FYWlAuKFhDmxn0F5XxSC1IlnaeHinHxR6JwbSTX0NYxlrbWCNeq0PwWri2TwfQ0BH39L4QNXx9kd+1p02Dfqhuh9PXl22gl6DcYXNIDY4M2LQkI1wCnX3yrMIpLPZz4uEhuMUMvNNlgDRUNGYDpZaMONIoVdjrOeWJyYMjRSyRAYV/2S+aQUeqRz+kI3dlGvr8EIuMNLNNCXJ58d58NtSxA=="}';
aesKey:'MqueyTZsLhJS3o3L4gTkuapiwXc1K2ASkUD8kDrkdAS';
appId:'wxfeedff1d7050a2fd'
上面这组的解析结果:

用这个函数试试
https://developers.weixin.qq.com/community/develop/article/doc/000c2a14b54b407d09e1e73a769c13