微信公眾號有個規(guī)則,一旦開啟了開發(fā)者模式,其他的常規(guī)功能就都必須通過接口調(diào)用完成。比如說自定義菜單功能,必須通過發(fā)送post請求的方式生成。本章就通過關(guān)注到取消關(guān)注的整個過程來談一談nodejs是怎么樣與微信交互的。這些功能的入口就是你在測試公眾號里面填寫的URL(以下用/login/wechat代替)。
事件交互
掃碼關(guān)注微信公眾號后,微信會調(diào)用你的接口/login/wechat,并且附帶一段xml信息,首先你需要獲取一些簽名,通過加密、排序比對是否與你填寫的TOKEN一致,如果一致則進(jìn)行xml的解析。node解析xml時必須先引用模塊。所以,先引入xml解析模塊
//xml解析模塊var XMLJS = require('xml2js');//解析,將xml解析為jsonvar parser = new XMLJS.Parser();//重組,將json重組為xmlvar builder = new XMLJS.Builder(); 通過req的監(jiān)聽data,來獲取微信發(fā)送過來的xml包。以下是某個新用戶關(guān)注公眾號后微信向你的后臺接口(上一篇中提到的/yourapi)發(fā)送的xml包數(shù)據(jù),經(jīng)過解析后,他的結(jié)構(gòu)如下:

tousername:收信人【此處為公眾微信號】
fromusername:發(fā)信人【此處為用戶openid】
createTime:發(fā)送時間
msgtype:消息類型【event(響應(yīng)事件)、text(推送消息)、image(推送圖文消息)等】
event:消息名稱【此處為關(guān)注】
eventkey:自定義的key,在設(shè)置網(wǎng)頁時可以自定義后文中會講到
以上就是當(dāng)一個用戶關(guān)注后微信往你接口發(fā)送的數(shù)據(jù)包。上面對我們有用的是fromusername,即關(guān)注人的openid,我們在關(guān)注時獲取了用戶的該openid后可以通過微信提供的特定接口(https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN)獲取用戶的頭像,性別,昵稱等信息,為你的app建立一個可靠的資料庫。
代碼實現(xiàn)
//微信事件推送的入口app.post('/yourapi', function(req, res, next) {//獲取參數(shù)var query = req.query; //簽名var signature = query.signature; //輸出的字符,你填寫的TOKEN var echostr = query.echostr; //時間戳var timestamp = query['timestamp']; //隨機(jī)字符串var nonce = query.nonce; var oriArray = new Array(); oriArray[] = nonce; oriArray[] = timestamp; oriArray[] = appConfig.token;//排序參數(shù)oriArray.sort(); var original = oriArray[]+oriArray[]+oriArray[]; //加密var scyptoString = sha(original); //判斷是否與你填寫TOKEN相等if (signature == scyptoString) {//獲取xml數(shù)據(jù)req.on("data", function(data) {//將xml解析parser.parseString(data.toString(), function(err, result) {var body = result.xml;var messageType = body.MsgType[];//用戶點擊菜單響應(yīng)事件if(messageType === 'event') {var eventName = body.Event[];(EventFunction[eventName]||function(){})(body, req, res);//自動回復(fù)消息}else if(messageType === 'text') {EventFunction.responseNews(body, res);//第一次填寫URL時確認(rèn)接口是否有效}else {res.send(echostr);}});});} else { //認(rèn)證失敗,非法操作res.send("Bad Token!"); }});//微信客戶端各類回調(diào)用接口var EventFunction = {//關(guān)注subscribe: function(result, req, res) {//存入openid 通過微信的接口獲取用戶的信息同時存入數(shù)據(jù)庫。},//注銷unsubscribe: function(openid, req, res) {//刪除對應(yīng)id},//打開某個網(wǎng)頁VIEW: function() {//根據(jù)需求,處理不同的業(yè)務(wù)},//自動回復(fù)responseNews: function(body, res) {//組裝微信需要的jsonvar xml = {xml: {ToUserName: body.FromUserName,FromUserName: body.ToUserName,CreateTime: + new Date(),MsgType: 'text',Content: '編輯@+您想說的話,我們可以收到'}};var reciviMessage = body.Content[]if(/^/@.*/.test(reciviMessage)) {xml.xml.Content = '已經(jīng)收到您的建議,會及時處理!'}<br>//將json轉(zhuǎn)為xmlxml = builder.buildObject(xml);<br>//發(fā)送給微信res.send(xml);}}此處,適合采用JS設(shè)計模式中的策略模式,在subscribe方法里面寫上你自己的業(yè)務(wù),通過發(fā)送帶openid參數(shù)的請求,可以在用戶關(guān)注微信號的時候?qū)⑵鋷妆举Y料存入數(shù)據(jù)庫,并且建立會話。這樣在用戶接下來打開你的網(wǎng)頁的時候就無需再次認(rèn)證,只需要比對openid然后查詢數(shù)據(jù)庫就行了。
新聞熱點
疑難解答