koa2实现微信公众号关注自动回复消息

2020-08-01 15:15:26

基于koa框架接入微信公众号实现自动回复消息的功能

准备工作

  • 注册一个服务号或者申请一个测试公众号
  • 一台服务器或者本地使用内网穿透软件(ngrok、花生壳、lanproxy...)

公众号接入配置

在公众号管理后台填写接口配置信息。
开发者提交信息后,微信服务器将发送GET请求到填写的服务器地址URL上,开发者通过检验signature对请求进行校验(下面有校验方式)。若确认此次GET请求来自微信服务器,请原样返回echostr参数内容,则接入生效,成为开发者成功,否则接入失败
加密/校验流程如下:

  • 将token、timestamp、nonce三个参数进行字典序排序
  • 将三个参数字符串拼接成一个字符串进行sha1加密
  • 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信

服务号配置

在公众平台官网的开发-基本设置页面,勾选协议成为开发者,点击“修改配置”按钮,填写服务器地址(URL)、Token和EncodingAESKey,其中URL是开发者用来接收微信消息和事件的接口URL。Token可由开发者可以任意填写,用作生成签名(该Token会和接口URL中包含的Token进行比对,从而验证安全性)。EncodingAESKey由开发者手动填写或随机生成,将用作消息体加解密密钥

测试号配置

配置成功会有消息提示

主要代码


// 验证消息的确来自微信服务器
router.get('/', async (ctx, next) => {
  let signature = ctx.query.signature,
    timestamp = ctx.query.timestamp,
    nonce = ctx.query.nonce,
    token = '123456'
  let str = [token, timestamp, nonce].sort().join('')
  let result = sha1(str)
  let rt
  if (result === signature) {
    rt = ctx.query.echostr
  } else {
    rt = {
      code: -1,
      msg: 'fail',
    }
  }
  ctx.body = rt
  await next()
})

router.post('/', async (ctx, next) => {
  var data = await getRawBody(ctx.req, {
    length: ctx.length,
    limit: '1mb',
    encoding: ctx.charset,
  })
  const xml = await parseXMLAsync(data)
  const createTime = Date.parse(new Date())
  const msgType = xml.xml.MsgType[0]
  const toUserName = xml.xml.ToUserName[0]
  const toFromName = xml.xml.FromUserName[0]
  const event = xml.xml.Event ? xml.xml.Event[0] : ''
  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[欢迎关注]]></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>`
  }
})

function parseXMLAsync(xml) {
  return new Promise((resolve, reject) => {
    xml2js.parseString(xml, { trim: true }, function (err, content) {
      if (err) {
        reject(err)
      }
      resolve(content)
    })
  })
}

扫码体验

测试号二维码

参考资料

本文链接:
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-ND 3.0 许可协议。可自由转载、引用,但需署名作者且注明文章出处。如转载至微信公众号,请在文末添加作者公众号二维码。

扫描下方二维码阅读当前文章

浏览器、微信扫码

评 论:

好文推荐
每天进步一点点~