美文网首页
node(egg)完成微信公众号自动回复功能

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

作者: w晚风 | 来源:发表于2020-11-03 16:14 被阅读0次

    项目背景:

    我这里是在使用微信公众号获取用户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

    相关文章

      网友评论

          本文标题:node(egg)完成微信公众号自动回复功能

          本文链接:https://www.haomeiwen.com/subject/szzbvktx.html