上一篇文章介绍过 微信小程序配置消息推送,没有看过的可以先去查看一下,这里就直接去把那个客服消息接口去解密那个消息了。

  在这里我选择的还是json格式的加密。

  也就是给小程序客服消息发送的消息都会被微信转发到这里配置的地址和接口上面。

  在页面中使用客服消息也就是如下这个效果,是需要用到微信提供的button标签上面的open-type的

  

  点击进入客服消息也就是如下这个效果。

  

  然后你发送的消息就会被转发到上面你配置的那个服务器的端口和那个接口上面,也就是例子中的

  只不过配置确认的时候的接口是get请求方式,而微信转发消息到这里的接口这里是post请求方式。

  在聊天窗口中发送消息,微信就会把加密后的消息转发到我们的接口  也就是 /checkPushMsg 上面,post请求方式。

  在node中的代码接收,看看微信给我们转发了什么东西呢

 // 配置前后端的推送消息
router.get('/checkPushMsg', wx_msg.check_push); // 那个函数就是如下的处理
exports.handle_customer_sevice = (req, res) => {
console.log('接收到了消息,请求体中');
console.log(req.body);
console.log('接收到了消息,请求url中');
console.log(req.query);
}

  我们来查看一下发送过来的什么,我再用文档来比对一下哈。

  现在我在手机上面那个页面里面发送一条消息,任意内容。

  这里服务器的图片太小了,可以 按住 ctrl + 鼠标滚轮把这里放大看一下,我相信你肯定知道的。

  

  请求url中的内容如下

  请求体中的内容一个是发送者的 openid,另外一个加密的就是消息内容,它的构成是由  16个字节的随机字符串,4个字节的消息长度,发送的消息,appId由基于AES加解密算法加密而成的。

  这里咱们先不着急解密发送的内容,我们要在解密之前先判断一下是不是微信发送过来的呢,如果不是你在这里解密半天然后发出去那不就难受了。

  上面的图片中也详细的介绍了如何去判断是不是微信发送过来的消息。

  我什么也不想解释了,直接上代码啦。

  

 exports.handle_customer_sevice = (req, res) => {
console.log('接收到了消息,请求体中');
console.log(req.body);
console.log('接收到了消息,请求url中');
console.log(req.query);
let signature = req.query.signature,
timestamp = req.query.timestamp,
nonce = req.query.nonce,
openid = req.query.openid,
encrypt_type = req.query.encrypt_type,
msg_signature = req.query.msg_signature,
msg_encrypt = req.body.Encrypt; // 密文体 // 开发者计算签名
let devMsgSignature = sha1(pushToken, timestamp, nonce, msg_encrypt); // 这里的pushToken是 上面那个 配置消息推送 里面设置的Token令牌 if(devMsgSignature == msg_signature){
console.log('验证成功,是从微信服务器转发过来的消息'); res.send('success');
}else{
console.log('error');
res.send('error');
}
};

  上面的那个sha1函数是这样的

 /*
@explain sh1加密
@version 1.0.1 @author : Z
@data : 2019-2-13 @params : a,b,c……
@return : String 加密完成后的字符串
*/
exports.sha1 = function (...arr) {
return crypto.createHash('sha1').update(arr.sort().join('')).digest('hex');
};

  上面就可以验证出来如果那个加密的东西确实是那样的就可以验证出来消息确实是由微信发送过来的。

  然后就要开始解密了,这里我遇到了好多坑,说实话我也不知道下面的代码是谁第一个写出来的,因为官网上面根本就没有Node.js的代码,所以我也是看到了加密消息的构成部分,然后使用下面封装的函数解密。

  

 /*
@explain: 微信的消息密文解密方法
@version 1.0.1
修复部分消息解析失败的情况
@author: Z
@data :2019-02-14
@params:
obj.AESKey:解密的aesKey值 这里的key就是配置消息推送的那部分
obj.text: 需要解密的密文
obj.corpid: 企业的id / 微信小程序的appid @return
obj.noncestr 随机数
obj.msg_len 微信密文的len
obj.msg 解密后的明文
*/ exports.decrypt = function (obj) {
let aesKey = Buffer.from(obj.AESKey + '=', 'base64');
const cipherEncoding = 'base64';
const clearEncoding = 'utf8';
const cipher = crypto.createDecipheriv('aes-256-cbc',aesKey,aesKey.slice(0, 16));
cipher.setAutoPadding(false); // 是否取消自动填充 不取消
let this_text = cipher.update(obj.text, cipherEncoding, clearEncoding) + cipher.final(clearEncoding);
/*
密文的构成
Base64_Encode(AES_Encrypt[random(16B) + msg_len(4B) + msg + $appId])
但是由于部分消息是不满足那个 32 位的,所以导致上面那个 cipher.final() 函数报错,所以修改为了自动填充,所以 appId后面还跟着一些字符
就无法正常解析了,所以就不返回 corpid 了,然后返回我们想要的东西。
*/
return {
noncestr:this_text.substring(0,16),
msg_len:this_text.substring(16,20),
msg:this_text.substring(20,this_text.lastIndexOf("}")+1)
}
};

  其中的坑就是我遇到了那个  cipher.setAutoPadding(false) 这里填充的问题,但是有的消息是可以解密出来的,但是有的消息是不可以解密出来的,会报错,所以我就让所有的消息都填充了。

  let this_tex = cipher.update(obj.text, cipherEncoding, clearEncoding) + cipher.final(clearEncoding);

  解密消息这里的问题是,这是一个加法,前面的那个更新函数会改变 cipher的值,然后导致后面的那个值发生改变,当时找这个错误出现了很多问题。这个问题就是当字体的内容的长度不是32个字节还是什么的倍数的时候,这个函数会报一个500的错误码,然后不知道是哪里的问题,所以我就取消自动填充设置为了false,我就让它一直填充,然后处理那个消息,最后那个明文我再把最后的一个 } 后面截取掉。就可以展示出来了,但是这个里面就无法获取到小程序 appId 了,但是这又有什么必要呢?你后台肯定是知道appId的。

  我把消息处理的完整代码发出来。

 /*
消息体验证和解密
客服接收到的消息
handle_customer_sevice */ exports.handle_customer_sevice = (req, res) => {
console.log('接收到了消息,请求体中');
console.log(req.body);
console.log('接收到了消息,请求url中');
console.log(req.query);
let signature = req.query.signature,
timestamp = req.query.timestamp,
nonce = req.query.nonce,
openid = req.query.openid,
encrypt_type = req.query.encrypt_type,
msg_signature = req.query.msg_signature,
msg_encrypt = req.body.Encrypt; // 密文体 // 开发者计算签名
let devMsgSignature = sha1(pushToken, timestamp, nonce, msg_encrypt); if(devMsgSignature == msg_signature){
console.log('验证成功,是从微信服务器转发过来的消息'); let returnObj = decrypt({
AESKey: config.server.EncodingAESKey,
text: msg_encrypt,
corpid: config.app.appId
});
console.log('解密后的消息');
console.log(returnObj);
console.log('解密后的消息内容');
const decryptMessage = JSON.parse(returnObj.msg);
console.log(decryptMessage); /*
详细参数请查看官网 消息 https://developers.weixin.qq.com/miniprogram/dev/api/sendCustomerMessage.html
@params
access_token 调用接口凭证
touser 用户的openid
msgtype 消息类型
*/ if(JSON.parse(returnObj.msg).Content == '值班'){
axios.post(config.url.ip + config.url.P_CustomSend + '?access_token='+config.access_token, {
touser: decryptMessage.FromUserName,
msgtype: "text",
text: {
content: "发送消息"
}
})
.then(res => {
console.log('消息接口发送成功'); console.log(res.data);
if(res.data.errcode == 0){
console.log('消息发送成功');
}else if(res.data.errcode == 40001){
console.log('access_token过期');
}else{
console.log('其他错误信息')
}
console.log(res.data);
})
.catch(err => {
console.log('错误消息');
console.log(err);
})
}
res.send('success');
}else{
console.log('error');
res.send('error');
}
};

  

  上面用到的两个函数 一个 sha1,另外一个就是 解密函数。

  现在发送一下消息,看一看服务器上面的处理过程。

  如此是可以解密出来那个消息的内容的,然后我设置了一个发送值班的话会给我发送一个消息。

  

  如此 就大功告成了。

  看了网上的许多文章大多都是Java,php的代码,很少有Node的代码,而且看了之后也不知道能不能弄出来,如果你遇到这个问题, 仔细看了我的文章之后,还有地方不知道,欢迎打扰我,告诉我哪里不清楚,我也会和你一起把你的问题解决掉。

  如果解决了你的问题我会非常高兴的,其实上面的文章中我也感觉到了有一些地方描述的不是那么清晰,比如说消息加密的那一块,说实话,我也不是那么了解他的加密,只是微信 这里是有讲述的 点击查看

  它的加密我会在最近几天研究一下,把他的加密的细节也给发出来,下一篇文章你可以查看到它的加密。

  如果解决了你的问题我真的会非常高兴,因为我开发了这么久感觉开发出来的东西都没有去影响一些人,甚至我想先给自己做一些程序,并且我已经开始着手去做了,先去方便一下自己再去做一些去对一些人有好处的影响的东西。

node配置微信小程序解密消息以及推送消息的更多相关文章

  1. java微信小程序解密AES/CBC/PKCS7Padding

    摘要:微信小程序解密建议使用1.6及以上的环境使用maven下载jar包org.bouncycastlebcprov-jdk15on1.55加密类代码importorg.bouncycastle.jc ...

  2. node.js微信小程序配置消息推送

    在开发微信小程序时,有一个消息推送,它的解释是这样的. 消息推送具体的内容是下面的这个网址   https://developers.weixin.qq.com/miniprogram/dev/fra ...

  3. C# .net 填充无效,无法被移除 微信小程序解密失败的解决办法

    微信小程序获取用户信息诸如unionId的时候需要解密,如果遇到偶然的解密失败(填充无效,无法被移除),原因很有可能是session_key错误, 也是就你用作解密的session_key并不是微信用 ...

  4. 微信小程序-登陆、支付、模板消息

    wx.login(OBJECT) 调用接口获取登录凭证(code)进而换取用户登录态信息,包括用户的唯一标识(openid) 及本次登录的 会话密钥(session_key).用户数据的加解密通讯需要 ...

  5. 微信小程序解密得到unoinid和手机号 (开放数据的校验和解密 获取手机号)

    实际测试 两种方法都可以: 第一种方法: public static string DecodeUserInfo(string encryptedData, string iv, string cod ...

  6. WebStorm 配置微信小程序开发 用html样式打开wxml 用css样式打开wxss 配置微信小程序提醒

    1.点开preferences 2.搜索找到“File Types” 3.找到"HTML",点击“+”按钮,添加“*.wxml”然后“apply” 4.和3一样,再找到 ‘casc ...

  7. 微信小程序解密

    获取OpenId和SessionKey private string GetOpenIdAndSessionKeyString(string code) { string wxUrl = " ...

  8. 微信小程序客服消息使用指南

    客服消息使用指南 为丰富小程序的服务能力,提高服务质量,微信为小程序提供客服消息能力,以便小程序用户可以方便快捷地与小程序服务提供方进行沟通. 功能介绍 用户可使用小程序客服消息功能,与小程序的客服人 ...

  9. 微信小程序客服消息使用

    客服消息使用 为丰富小程序的服务能力,提高服务质量,微信为小程序提供客服消息能力,以便小程序用户可以方便快捷地与小程序服务提供方进行沟通. xiaokefu.com.cn 功能介绍 用户可使用小程序客 ...

随机推荐

  1. 两个月的Java实习结束,继续努力

    前言 只有光头才能变强 2018年8月30日,今天我辞职了.在6月25号入职,到现在也有两个月时间了. 感受: 第一天是期待的:第一次将项目拉到本地上看的时候,代码很多,有非常多的模块,模块下又有da ...

  2. jbpm - 工作流的基本操作

    Jbpm流程引擎. 定义:jbpm,全称是Java Business Process Management(业务流程管理),他是覆盖了业务流程管理,工作流管理,服务协作等领域的一个开源的,灵活的,易扩 ...

  3. Nodejs实现用户注册

    1创建连接池对象 2导出连接池对象 /** * 1.引入mysql模块 * 2.创建连接池对象 * 3.导出连接池对象 */ const mysql = require('mysql'); var p ...

  4. Odoo开源ERP:功能模块操作-销售功能篇

    客户基础资料 1. 所有的客户基础资料,智云ERP开账启用时,期初的客户数据如果大于200条,可以批量导入: 2. 点“销售/订单/客户”菜单可以查看.编辑修改.搜索所有的客户基础资料: 3. 多层级 ...

  5. (办公)springboot配置aop处理请求.

    最近项目用到springboot,就是需要配置一些东西.比如用aop处理请求.方法前通知获取url,method,ip,类方法,参数,方法后通知,返回参数,而且还可以记录一下日志.下面是操作的代码. ...

  6. 通信(二):进程间通信之socket

    一.为什么要学习socket? 我们打开浏览器浏览网页时,浏览器的进程怎么与web服务器通信的?我们用QQ聊天时,QQ进程怎么与服务器或你好友所在的QQ进程通信?这些都得靠socket.本地的进程间通 ...

  7. 漫谈Linux标准的文件系统(Ext2/Ext3/Ext4)

    Ext 全称Linux extended file system, extfs,即Linux扩展文件系统,Ext2就代表第二代文件扩展系统,Ext3/Ext4以此类推,它们都是Ext2的升级版,只不过 ...

  8. leaflet 学习备忘

    leaflet 开源js地图工具.非常好用. leaflet参考:http://leafletjs.com/ 特性: 完全开源,可以基于不同的第三方瓦片生成地图. 基于原始GPS,无需转换 可创建离线 ...

  9. 关于Layer ui的加载层位置居中问题

    最近在项目中一直使用layerui的相应的提示框以及它的加载层,然而就在今天遇到了一个神奇的问题,我使用 var index = layer.load(0, {shade: false}); 结果一直 ...

  10. ubuntu修改键盘映射

    code {margin: 0;padding: 0;font-size: 100%;word-break: normal;background: transparent;border: 0;}ol ...