const crypto = require('crypto'); // 加密模块 const decodePKCS7 = function (buff) { let pad = buff[buff.length - 1]; if (pad < 1 || pad > 32) { pad = 0; } return buff.slice(0, buff.length - pad); }; // 微信转发客服消息解密 const decryptContact = (key, iv, crypted) => { const aesCipher = crypto.createDecipheriv('aes-256-cbc', key, iv); aesCipher.setAutoPadding(false); let decipheredBuff = Buffer.concat([aesCipher.update(crypted, 'base64'), aesCipher.final()]); decipheredBuff = decodePKCS7(decipheredBuff); const lenNetOrderCorpid = decipheredBuff.slice(16); const msgLen = lenNetOrderCorpid.slice(0, 4).readUInt32BE(0); const result = lenNetOrderCorpid.slice(4, msgLen + 4).toString(); return result; }; // 解密微信返回给配置的消息服务器的信息 const decryptWXContact = (wechatData) => { if(!wechatData){ wechatData = ''; } //EncodingAESKey 为后台配置时随机生成的 const key = Buffer.from(EncodingAESKey + '=', 'base64'); const iv = key.slice(0, 16); const result = decryptContact(key, iv, wechatData); const decryptedResult = JSON.parse(result); console.log(decryptedResult); return decryptedResult; }; module.exports = decryptWXContact;
呼~ 代码终于码完,来看看效果:
总结
开发并不是一帆风顺的,也遇到了一些值得留意的坑,强调一下:
后台配置URL地址一定外网可访问(可以通过内网穿透解决)
文件上传接口uploadTempMedia media参数要用 FormData数据格式 (用node的request库很容易实现。urllib这个库有坑有坑 都是泪T_T)
切记接收消息不论成功失败都要返回success,不然即使成功接收返回消息,日志没有报错的情况下,还是出现IOS提示该小程序提供的服务出现故障 请稍后再试。