博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
使用 nodeJs 开发微信公众号(设置自动回复消息)
阅读量:6516 次
发布时间:2019-06-24

本文共 6804 字,大约阅读时间需要 22 分钟。

微信向第三方服务器发送请求时会降 signature 、timestamp、 nonce 、 openid(用户标识),发送内容会以 xml 的形式附加在请求中

回复消息前提我们得拿到用户id , 用户发送内容等信息,用户发送内容格式参考微信官方文档:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140453

想要获取用户发送信息,需要从请求中获得 xml ,因此需要用到 raw-body(获得原生请求体)

npm install raw-body --save

接下来需要将xml从请求中分离并且格式化成json

var getRawBody = require('raw-body')var contentType = require('content-type') var data = getRawBody(req, {        length: req.headers['content-length'],        limit: '1mb',        encoding: contentType.parse(req).parameters.charset    }, function(err, buf) {            utils.formatMessage(buf.toString()).then(message => {               //判断消息,做出回应            })       })

我将格式化 xml 的操作封装在 formatMessage

var xml2js = require('xml2js')exports.formatMessage = function(xml) {    return new Promise((resolve, reject) => {                // 接收文本信息格式        // 
//
//
1348831860
//
//
//
1234567890123456
xml2js.parseString(xml, function(err, content) { var result = content.xml var message = {}; if (typeof result === 'object') { var keys = Object.keys(result); for (var i = 0; i < keys.length; i++) { var key = keys[i]; var item = result[key]; if (!(item instanceof Array) || item.length === 0) continue; if (item.length === 1) { var val = item[0]; if (typeof val === 'object') message[key] = formatMessage(val); else message[key] = (val || '').trim(); } else { message[key] = []; for (var j = 0, k = item.length; j < k; j++) message[key].push(formatMessage(item[j])); } } } resolve(message) }) })}

解析完成后我们可以拿到 FromUserName、MsgType 和 Content

MsgType可能是 event(事件)或者是 text (文本)

event类型有:subscribe,unsubscribe,LOCATION,CLICK,SCAN

根据 content中发送的内容,我们可以进行判断,返回自定义消息回复

微信规定我们返回的数据必须是xml格式的,格式参考:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140543

因此在返回信息前需要拼接内容成指定xml格式,我将拼接方法封装在 template.js 文件中,使用时只要直接调用即可

lib/template.js:

exports.textMessage = function(message){    var createTime = new Date().getTime()    return `
${createTime}
`}exports.imageMessage = function(message){ var createTime = new Date().getTime() return `
${createTime}
`}exports.voiceMessage = function(message){ var createTime = new Date().getTime() return `
${createTime}
`}exports.videoMessage = function(message){ var createTime = new Date().getTime() return `
${createTime}
`}exports.articleMessage = function(message){ var createTime = new Date().getTime() return `
${createTime}
${message.articles.length}
${message.articles.map(article => `
<![CDATA[${article.title}]]>
` ).join('')}
`}

自动回复整体流程:收到微信请求->校验是否来自微信->获取access_token->解析请求体xml->根据类型以及内容作出相应

回复代码:

var express = require('express')var router = express.Router()var getRawBody = require('raw-body')var contentType = require('content-type')var utils = require('../lib/utils.js')var template = require('../lib/template.js')// 微信官方请求回调接口router.all('/', function(req, res, next) {    var data = getRawBody(req, {        length: req.headers['content-length'],        limit: '1mb',        encoding: contentType.parse(req).parameters.charset    }, function(err, buf) {        if (err) return next(err)        utils.formatMessage(buf.toString()).then(message => {            if (message.MsgType == 'event') {                if (message.Event === 'subscribe') {                    if (message.EventKey) {                        console.log('扫描二维码关注:' + message.EventKey + ' ' + message.ticket);                    }                    message.reply = '终于等到你,还好我没放弃';                } else if (message.Event === 'unsubscribe') {                    message.reply = '';                    console.log(message.FromUserName + ' 悄悄地走了...');                } else if (message.Event === 'LOCATION') {                    message.reply = '您上报的地理位置是:' + message.Latitude + ',' + message.Longitude;                } else if (message.Event === 'CLICK') {                    message.reply = '您点击了菜单:' + message.EventKey;                } else if (message.Event === 'SCAN') {                    message.reply = '关注后扫描二维码:' + message.Ticket;                }                res.send(template.textMessage(message))            } else if (message.MsgType === 'text') {                var content = message.Content                if (content === '1') {                    message.reply = '终于等到你'                    res.send(template.textMessage(message))                } else if (content === '2') {                    message.mediaId = '需要发送图片的媒体id'                    res.send(template.imageMessage(message))                } else if (content === '3') {                    message.articles = [{                        title: '标题',                        description: '描述',                        picUrl: '图片路径,不需要事先上传',                        url: '素材路径,素材需要事先上传'                    }]                    res.send(template.articleMessage(message))                } else {                    message.reply = '你说的话:“' + content + '”,我听不懂呀'                    res.send(template.textMessage(message))                }            }        })    })});module.exports = router;

 

转载于:https://www.cnblogs.com/xiaoliwang/p/10196336.html

你可能感兴趣的文章
Redis客户端redisson实战
查看>>
连接到 JasperReports Server
查看>>
java处理高并发高负载类网站问题
查看>>
使用C#生成随机密码(纯数字或字母)和随机卡号(数字与字母组合)
查看>>
CAS服务器端集群
查看>>
JAVA Collections框架
查看>>
进制转换
查看>>
ASCII码
查看>>
java常用四种排序源代码
查看>>
win7 下硬盘安装Redhat7
查看>>
Redis 分布式锁的正确实现方式
查看>>
mysqldump 备份命令使用中的一些经验总结
查看>>
程序猿知道英语词汇
查看>>
数据存储(两)--SAX发动机XML记忆(附Demo)
查看>>
谈谈SQL 语句的优化技术
查看>>
ecshop如何判断缓存文件是否能更新
查看>>
javascript于boolean类型转换,运营商&amp;&amp;和|| 返回值
查看>>
深入分析面向对象中的封装作用
查看>>
深刻理解Python中的元类(metaclass)
查看>>
Java编程的逻辑 (44) - 剖析TreeSet
查看>>