本節主要介紹下在開發公衆號消息消息管理中踩過的坑,有與好久纔來寫一次,文筆不是太好。爲了讓你發現想要的重點,將以問答的形式進行編寫。node
1.爲何先開發消息管理模塊:json
剛剛開始接觸這個,看了api文檔後第一感受是亂、多。對應新手來講這麼多東西該從那裏下手呢?看了下jssdk部分,由於有騰訊的demo,因此爲了學習方面能夠直接將代碼弄到本地跟着調式就行,主要涉及一些wx.config裏面的參數獲取邏輯須要整理下。由於以前已經經過postman測試了自定義菜單了,那乾脆就接着作人機交互部分-消息接收和回覆。api
2.消息管理這塊能夠作什麼事情:promise
總結了一下,消息管理主要作兩方面的事情。服務器
第一:與用戶進行交互(包括接收用戶發來的文本、語言、視頻等信息,同時能夠對用戶發送的信息進行回覆)微信
第二:與微信服務器進行交互(對於一些指定的動做,微信會發送信息到後臺、部分須要咱們的服務器進行回覆。好比:新用戶關注公衆號、取消關注公衆號、上報地理位置事件等)運維
具體能夠參考https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140454 中 消息管理->接收事件推送異步
3.接收消息要作一些什麼:async
第一:在微信管理平臺配置URL, 路徑爲 開發-》基本配置-》服務器配置(這個要先啓動)post
其中URL爲本身後臺服務器的一個服務,微信將經過post請求將消息發送到這個地方,同時在配置點確認的時候,微信會發送get請求到這個路徑進行驗證,具體驗證邏輯能夠參考個人上一篇文章。
這個地方特別要注意:一個get請求一個post請求分別有不一樣的目的
第二:搭建本身的服務器,要保證第一點中的URL能正常接收post請求
3.開發消息管理後臺遇到了什麼坑
第一:晚上不少文章都是別人寫的demo,不少代碼有誤導性。要有本身的思考。同時細看api文檔。
第二:我用的node(eggjs),因此遇到了異步的問題,當時看網上不少人都是經過req.on()去監聽接收text/xml數據流,而後就直接返回了。在這重申:這些都是坑,及其不負責任,要同步方法。這個異步形成微信根本收不到。
要將監聽獲取數據流方法同步化。我用了raw-body插件,這個會返回xml格式的字符串,還須要用xml2js轉成json (這個須要本身promise封裝成同步)便可,接着根據指定格式返回信息給微信
第三:直接將參數賦值給res.body就能夠了,不要想的很複雜。
第四:新手建議不要用測試帳號,用正式帳號。爲何呢?由於正式帳號能夠從管理平臺中看到返回給微信的日誌,方便查錯(高手請忽略)
開發-》運維中心-》日誌查詢 日誌類型選擇:公衆號被動回覆,類型自選便可
4.代碼實現
//controller方法,暫時沒有分service const rawBody = require('raw-body') var contentType = require('content-type') const tool = require('../../utils/tool.js') //處理方法 async message(){ //獲取微信推送過來的消息 const { ctx ,config} = this console.log('message request:', ctx.request.body) var data = await rawBody(ctx.req, { length : ctx.request.headers['content-length'], limit : '1mb', encoding: contentType.parse(ctx.request).parameters.charset }); console.log('data+++:' + data); let jsonData = await tool.parseXMLAsync(data) let getData = jsonData.xml let { ToUserName, FromUserName, MsgType, Content, MsgId } = getData console.log('****************', getData) let rst = `<xml><ToUserName><![CDATA[${FromUserName}]]></ToUserName> <FromUserName><![CDATA[${ToUserName}]]></FromUserName> <CreateTime>1540993144</CreateTime> <MsgType><![CDATA[${ MsgType}]]></MsgType> <Content><![CDATA[${Content}]]></Content> <MsgId>${MsgId}</MsgId> </xml>` ctx.body = rst } //一下爲tool.js 簡單的封裝了xml2js方法,將其同步化 var xml2js = require('xml2js'); //導出解析XML的方法 function parseXMLAsync (xml) { return new Promise(function (resolve, reject) { xml2js.parseString(xml, { explicitArray: true }, function (err, content) { err ? reject(err): resolve(content); }); }); }; module.exports = { parseXMLAsync }