Koa2微信公众号开发之消息管理(2)

这儿我们在只在GET中验证了签名值是否合法,实际上我们在POST中也应该验证签名。

将签名验证写成一个函数

function getSignature (timestamp, nonce, token) {
 let hash = crypto.createHash('sha1')
 const arr = [token, timestamp, nonce].sort()
 hash.update(arr.join(''))
 return hash.digest('hex')
}

优化代码,再POST中也加入验证

...

app.use(async ctx => {
 const { signature, timestamp, nonce, echostr } = ctx.query
 const TOKEN = config.wechat.token
 if (ctx.method === 'GET') {
  if (signature === getSignature(timestamp, nonce, TOKEN)) {
   return ctx.body = echostr
  }
  ctx.status = 401
  ctx.body = 'Invalid signature'
 }else if (ctx.method === 'POST') {
  if (signature !== getSignature(timestamp, nonce, TOKEN)) {
   ctx.status = 401
   return ctx.body = 'Invalid signature'
  }
  // TODO
 }
});
...

到这儿我们都没有开始实现接受XML数据包的功能,而是在修改之前的代码。这是为了演示在实际开发中的过程,写任何代码都不是一步到位的,好的代码都是改出来的。

2.3 接收公众号普通消息的XML数据包

现在开始进入本节的重点,接受XML数据包并转为JSON

$ npm install raw-body --save
...
const getRawBody = require('raw-body')
...

// TODO
// 取原始数据
const xml = await getRawBody(ctx.req, {
 length: ctx.request.length,
 limit: '1mb',
 encoding: ctx.request.charset || 'utf-8'
});
console.log(xml)
return ctx.body = 'success' // 直接回复success,微信服务器不会对此作任何处理

给你的测试号发送文本消息,你可以在命令行看见打印出如下数据

<xml>
 <ToUserName><![CDATA[gh_9d2d49e7e006]]></ToUserName>
 <FromUserName><![CDATA[oBp2T0wK8lM4vIkmMTJfFpk6Owlo]]></FromUserName>
 <CreateTime>1516940059</CreateTime>
 <MsgType><![CDATA[text]]></MsgType>
 <Content><![CDATA[JavaScript之禅]]></Content>
 <MsgId>6515207943908059832</MsgId>
</xml>

恭喜,到此你已经可以接收到XML数据了。😯 但是我们还需要将XML转为JSON方便我们的使用,我们将用到xml2js这个包

$ npm install xml2js --save

我们需要写一个解析XML的异步函数,返回一个Promise对象

function parseXML(xml) {
 return new Promise((resolve, reject) => {
  xml2js.parseString(xml, { trim: true, explicitArray: false, ignoreAttrs: true }, function (err, result) {
   if (err) {
    return reject(err)
   }
   resolve(result.xml)
  })
 })
}
      

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/141.html