收藏
回答

微信小店的消息解密时而成功,时而失败?

我使用云函数订阅了微信小店的事件消息,现在我在测试订单的相关消息,但是发现接收到的消息有的能解密,有的就解密失败。

消息的签名验证是通过的。

报错信息如下:

解密代码如下:

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'



上面这组的解析结果:

回答关注问题邀请回答
收藏

2 个回答

登录 后发表内容
问题标签