Egg + Vue + 微信公众号开发(回复用户消息)

362 阅读1分钟

前言

本篇在上一篇文章(《Egg + Vue + 微信公众号开发(基础框架搭建)》)的基础之上进行

需求:自定义开发微信公众号中,当普通微信用户向公众账号发消息时,微信公众号自动回复相应的内容。

一. 文档

官方文档描述: image.png

image.png

二. 代码展示

1. parseStringXml方法

首先安装 npm i xml2js ,xml2js是用于解析xml文件的扩展,使用后可以将xml格式数据转为json格式。

// app/util/common.js

const { parseString } = require('xml2js');

class Common {
  parseStringXml(xml) {
    return new Promise((resolve, reject) => {
      parseString(xml, async (err, result) => {
        if (!err) {
          const xmlData = result.xml;
          const { MsgType, ToUserName, FromUserName, Event, Content } = xmlData;
          const createTime = Date.parse(new Date());
          const msgType = MsgType[0]; // 消息类型,event
          const toUserName = ToUserName[0]; // 开发人员微信号
          const toFromName = FromUserName[0]; // 发送方帐号(一个OpenID)
          const event = Event ? Event[0] : ''; // 事件类型,subscribe(订阅)、unsubscribe(取消订阅)
          const msgContent = Content ? Content[0] : ''; // 消息内容
          resolve({
            createTime,
            msgType,
            toUserName,
            toFromName,
            event,
            msgContent,
          });
        } else {
          console.log('err******', err);
          reject(new Error('解析失败'));
        }
      });
    });
  }
}

module.exports = new Common();

2. 覆盖egg自带的配置 使支持接收xml参数

// config/config.default.js

// 新增以下配置
config.bodyParser = {
  enable: true,
  encoding: 'utf8',
  formLimit: '100kb',
  jsonLimit: '100kb',
  strict: true,
  queryString: {
    arrayLimit: 100,
    depth: 5,
    parameterLimit: 1000,
  },
  enableTypes: [ 'json', 'form', 'text' ],
  extendTypes: {
    text: [ 'text/xml', 'application/xml' ],
  },
};

3.contoller

// app/controller/basic_message.js

'use strict';

const { Controller } = require('egg');
const { parseStringXml } = require('../util/common');

class BasicMessageController extends Controller {
  async replyMessage() {
    const { ctx } = this;
    const xml = this.ctx.request.body;
    try {
      const {
        createTime, msgType, toUserName, toFromName, event, msgContent,
      } = await parseStringXml(xml);
      const dataPool = [
        {
          msgContent: '你好,您好,嗨',
          reply_msg: '您好,请问有什么需要帮您的?☺☺☺'
        },
        {
          msgContent: '歌曲推荐',
          reply_msg: '上QQ音乐,找到你喜欢的歌曲,https://y.qq.com/'
        }
      ];
      const replyResultFilter = dataPool.filter(item => item.msgContent.includes(msgContent));
      const replyResult = replyResultFilter.length !== 0 ? replyResultFilter[0] : {
        msgContent: 'No Msg',
        reply_msg: '你说的我听不懂,请详细描述一下你的问题!😭'
      };
      let body = '';
      if (msgType === 'event' && event === 'subscribe') {
        body = `
              <xml>
                  <ToUserName><![CDATA[${toFromName}]]></ToUserName>
                  <FromUserName><![CDATA[${toUserName}]]></FromUserName>
                  <CreateTime>${createTime}</CreateTime>
                  <MsgType><![CDATA[text]]></MsgType>
                  <Content><![CDATA[欢迎关注公众号,下面请开始你的表演!🧐]]></Content>
              </xml>
          `;
      } else if (msgType === 'text') {
        const { reply_msg } = replyResult;
        body = `
            <xml>
                <ToUserName><![CDATA[${toFromName}]]></ToUserName>
                <FromUserName><![CDATA[${toUserName}]]></FromUserName>
                <CreateTime>${createTime}</CreateTime>
                <MsgType><![CDATA[text]]></MsgType>
                <Content><![CDATA[${reply_msg}]]></Content>
                <MediaId><![CDATA[media_id]]></MediaId>
            </xml>
        `;
      } else if (msgType === 'event' && event === 'unsubscribe') {
        this.ctx.logger.info(`微信号为:“${toFromName}”的用户取消订阅!`);
      }
      ctx.body = body;
    } catch (e) {
      console.log(e);
    }
  }
}

module.exports = BasicMessageController;

4. 路由

// app/router.js

'use strict';

module.exports = app => {
  const { router, controller, middleware } = app;
 
  // .......
  router.post('/wechat', controller.basicMessage.replyMessage);
};

源码参考(狂戳我~~)