node(egg)完成微信公众号自动回复功能

项目背景:

我这里是在使用微信公众号获取用户openid的时候希望不经过网页授权方式获取。所以就想到通过事件消息推送的方式来进行,也就是说用户关注,取消关注,发送消息,返回回来的数据都会携带openid,这是我想要的。这边使用的是node来作为服务端

1.首先需要在微信公众平台 - 基础设置 - 设置服务器地址

image.png
image.png

2.配置服务器地址时可能出现“参数错误,。。。。”的情况,可能是因为域名被拦截,不能使用。

那么首先就需要在后台实现这么个接口来开启这个url接口。这个地方填写服务器地址接口域名,就是用来跟公众号交互的。

首先实现一个get请求通过这个配置鉴权

async index() {
        const { ctx, app } = this;
        let { signature, echostr, timestamp, nonce } = ctx.query;
        
        console.log(ctx.query)
        
        const token = 'zwp123'; // 这个地方就是公众平台上所谓的token 必须一样
        
        // 将token、timestamp、nonce三个参数进行字典序排序
        const arr = [token, timestamp, nonce];
        arr.sort();
        
        // 将三个参数字符串拼接成一个字符串进行sha1加密
        const str = arr[0]+ arr[1] + arr[2];
        var sha1 = require('sha1');
        console.log(sha1(str))
        
        // 开发者获得加密后的字符串可与signature对比
        if(sha1(str) === signature){
            ctx.body = echostr;
        }else{
            ctx.body = false;
        }
    }

配置好服务器地址等信息,提交成功,点击启用完成服务器配置

3. 回复消息,分为关注后自动回复以及粉丝向公众号发消息时的回复等等情况

如何捕获用户。实际上都是微信服务器post请求配置好的服务器地址

async index2() {
    const { ctx, app } = this;
    
    console.log(this.ctx.request.body)
    
    // 用xml2js模块来处理xml
    var parseString = require('xml2js').parseString;
    
    var xml = this.ctx.request.body;
    
    parseString(xml, function (err, result) {
        // console.log(result.xml)
        
        const xmlData = result.xml;
        
        const createTime = Date.parse(new Date());
        const msgType = xmlData.MsgType[0]; // 消息类型,event
        const toUserName = xmlData.ToUserName[0]; // 开发人员微信号
        const toFromName = xmlData.FromUserName[0]; // 发送方帐号(一个OpenID)
        const event = xmlData.Event ? xmlData.Event[0] : ''; // 事件类型,subscribe(订阅)、unsubscribe(取消订阅)
        
        console.log(event)
        
        if(msgType == 'event' && event == 'subscribe'){ // 关注后
            ctx.body = `<xml>
                             <ToUserName><![CDATA[${toFromName}]]></ToUserName>
                             <FromUserName><![CDATA[${toUserName}]]></FromUserName>
                             <CreateTime>${createTime}</CreateTime>
                             <MsgType><![CDATA[text]]></MsgType>
                             <Content><![CDATA[欢迎关注w满城不及她公众号,下面请开始你的表演!]]></Content>
                        </xml>`;
        }
        else{// 其他情况
            ctx.body = `<xml>
                             <ToUserName><![CDATA[${toFromName}]]></ToUserName>
                             <FromUserName><![CDATA[${toUserName}]]></FromUserName>
                             <CreateTime>${createTime}</CreateTime>
                             <MsgType><![CDATA[text]]></MsgType>
                             <Content><![CDATA[啊~啊~啊~你在发什么消息?]]></Content>
                        </xml>`;
        }   
    })
}

来解释下,当用户点击关注,取消,发送消息的时候,会调用post接口推送xml数据信息,格式如下所示

<xml>
  <ToUserName><![CDATA[gh_a0df2b564971]]></ToUserName>
  <FromUserName><![CDATA[opNck1VdVevJsMeTfICgyHpW-Y_k]]></FromUserName>
  <CreateTime>1604312087</CreateTime>
  <MsgType><![CDATA[event]]></MsgType>
  <Event><![CDATA[subscribe]]></Event>
  <EventKey><![CDATA[]]></EventKey>
</xml>

在使用node的过程中打印接收body里面的数据为空,这是格式位xml数据,需要进行处理,我这里用的egg。

解决办法:config.default.js 文件中配置

// 覆盖egg自带的配置 使支持接收xml参数
  config.bodyParser = {
    enable: true,
    encoding: 'utf8',
    formLimit: '100kb',
    jsonLimit: '100kb',
    strict: true,
    // @see https://github.com/hapijs/qs/blob/master/lib/parse.js#L8 for more options
    queryString: {
      arrayLimit: 100,
      depth: 5,
      parameterLimit: 1000,
    },
    enableTypes: ['json', 'form', 'text'],
    extendTypes: {
      text: ['text/xml', 'application/xml'],
    },
  };

这样就能看到xml数据了。
再然后就要去解析xml数据了,我这里用到了一个插件xml2js
地址:https://www.npmjs.com/package/xml2js

安装:

npm i xml2js

简单用法:

var parseString = require('xml2js').parseString;
var xml = "<root>Hello xml2js!</root>"
parseString(xml, function (err, result) {
    console.dir(result);
});

再解析数据后就可以捕获用户的动作,返回各种信息了


image.png

image.png

这样就好了。

注意:我这里配置的路由是这样的

// 公众号测试
  router.get('/index', controller.demo.index);
  router.post('/index', controller.demo.index2);

可以看到是相同的接口名称,只是接口请求方式不一样,一个是get,一个是post
get请求是用来通过配置服务器地址的
post请求是用来捕获用户在微信公众号各种操作的

可能讲的不是清楚,请见谅,也是这两天才琢磨出来的,因此记录下来,以便后续不忘记

推荐文章:
https://www.cnblogs.com/kakayang/p/9729541.html
https://blog.csdn.net/m0_37805167/article/details/84327354

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,544评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,430评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,764评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,193评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,216评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,182评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,063评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,917评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,329评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,543评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,722评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,425评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,019评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,671评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,825评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,729评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,614评论 2 353