4.Node.js 微信消息管理

1、寫在前面的話

  當用戶發送消息給公衆號時(或某些特定的用戶操做引起的事件推送時),會產生一個POST請求,開發者能夠在響應包(Get)中返回特定XML結構,來對該消息進行響應。javascript

  消息推送也是微信公衆號開發更爲有趣的功能,涉及到文本消息、圖片消息、語音消息、視頻消息、音樂消息以及圖文消息。而且最爲有趣的功能當屬消息加解密了,固然因爲篇文章篇幅的緣由我會在下一篇文章中去着重說明。html

咱們接着來,微信消息管理

2、微信消息管理

1.捕獲消息信息java

  在文章的第一句話中,爲咱們指明瞭微信消息產生的請求方式爲 POST,所以首先咱們就去對 Node.js 的 Post 請求進行監聽。git

  在咱們的 app.js 文件中添加一個POST監聽,並將獲取的結果輸出:github

//用於處理全部進入 3000 端口 post 的鏈接請求
app.post('/',function(req,res){
    var buffer = [];
    //監聽 data 事件 用於接收數據
    req.on('data',function(data){
        buffer.push(data);
    });
    //監聽 end 事件 用於處理接收完成的數據
    req.on('end',function(){
    //輸出接收完成的數據   
         console.log(Buffer.concat(buffer).toString('utf-8'));
    });
});

  隨後將 Node.js 啓動後映射至外網,關注咱們的微信公衆號,在控制檯中則會看到:
輸出結果npm

  打開 微信幫助文檔,點擊左側菜單的消息管理,選擇其子菜單 接收事件推送,如圖:
消息管理 - 接收事件推送微信

微信接收事件推送

  從上圖咱們不難看出,微信 接收事件推送 確實不少,而咱們最終目標是要實現,在用戶觸發事件時返回其相應的回覆消息。所以咱們總結一下咱們要實現的步驟:app

  1. 解析 XML ,使用 Event 參數判斷事件類型
  2. 返回相應的事件信息

總結完實現步驟後,咱們就開始動手實現第一個被動回覆消息吧。微信公衆平臺

別攔我,讓我去裝逼

2.以關注事件爲例,實現第一個被動回覆異步

  解析 XML 我這裏使用了 第三方的包 xml2js(npm install xml2js ),並在 wechat.js 中引入。

parseString = require('xml2js').parseString;//引入xml2js包

  爲 WeChat 對象添加一個消息處理的方法 handleMsg,將 app.js 中捕獲 POST 實現的寫入在其代碼塊中,並使用 xml2js 解析,代碼以下

/**
 * 微信消息
 */
WeChat.prototype.handleMsg = function(req,res){
    var buffer = [];
    //監聽 data 事件 用於接收數據
    req.on('data',function(data){
        buffer.push(data);
    });
    //監聽 end 事件 用於處理接收完成的數據
    req.on('end',function(){
        var msgXml = Buffer.concat(buffer).toString('utf-8');
        //解析xml
        parseString(msgXml,{explicitArray : false},function(err,result){
            if(!err){
                //打印解析結果
                console.log(result);
            }else{
                 //打印錯誤信息
                console.log(err);
            }
        })
    });
}

  在 app.js 中調用 handleMsg 方法

//用於處理全部進入 3000 端口 post 的鏈接請求
app.post('/',function(req,res){
    wechatApp.handleMsg(req,res);
});

  完成了代碼的編寫後,將公衆號從新關注
運行結果

最後打印爲一個 JSON 格式的結果,也就是預示着咱們第1步工做已經完成。下面開始咱們的第2步,微信被動回覆。

  在文章的第一句話的後邊提到 開發者能夠在響應包(Get)中返回特定XML結構,那麼這個特定的 XML 結構在哪呢?再次打開微信幫助文檔,點擊左側菜單的消息管理,選擇其子菜單 被動回覆消息,如圖:
消息管理 - 被動回覆消息

  直接來到 回覆文本消息:
回覆文本消息

  拿到回覆文本消息格式後,咱們就來爲關注咱們公衆號的同窗打聲招呼吧。在 wechat 文件中 建立 msg.js 文件用於消息的管理。
這裏寫圖片描述

並在 msg.js 中添加處理文本消息的接口,並在 wechat.js 中引用

'use strict' //設置爲嚴格模式

//回覆文本消息
exports.txtMsg = function(toUser,fromUser,content){
    var xmlContent =  "<xml><ToUserName><![CDATA["+ toUser +"]]></ToUserName>";
        xmlContent += "<FromUserName><![CDATA["+ fromUser +"]]></FromUserName>";
        xmlContent += "<CreateTime>"+ new Date().getTime() +"</CreateTime>";
        xmlContent += "<MsgType><![CDATA[text]]></MsgType>";
        xmlContent += "<Content><![CDATA["+ content +"]]></Content></xml>";
    return xmlContent;
}

修改 wechat.js 中 handleMsg 方法

/**
 * 微信消息
 */
WeChat.prototype.handleMsg = function(req,res){
    var buffer = [];
    //監聽 data 事件 用於接收數據
    req.on('data',function(data){
        buffer.push(data);
    });
    //監聽 end 事件 用於處理接收完成的數據
    req.on('end',function(){
        var msgXml = Buffer.concat(buffer).toString('utf-8');
        //解析xml
        parseString(msgXml,{explicitArray : false},function(err,result){
            if(!err){
                   result = result.xml;
                   var toUser = result.ToUserName; //接收方微信
                   var fromUser = result.FromUserName;//發送仿微信
                   //判斷事件類型
                   switch(result.Event.toLowerCase()){
                      case 'subscribe':
                             //回覆消息
                             res.send(msg.txtMsg(fromUser,toUser,'歡迎關注 hvkcoder 公衆號,一塊兒鬥圖吧'));
                             break;
                   }
            }else{
                 //打印錯誤信息
                console.log(err);
            }
        })
    });
}

實現結果

   沒錯就是這麼簡單。這裏有個邏輯是這樣的 toUser 表示接收方,也就是我們的微信公衆號;fromUser 表示發送方,也就是觸發事件的用戶。而咱們要回複用戶時,此時 接收方 就是 觸發事件的用戶,而發送方則是 咱們的微信公衆號。這塊比較繞,你們能夠慢慢去理解。

  因爲咱們尚未對微信的素材管理進行講解,這裏咱們暫時跳過 圖片消息、語音消息、視頻消息、以及音樂消息。直接實現圖文消息的推送。

3.圖文消息
這裏寫圖片描述
  在 msg.js 文件中添加圖文XML模板

//回覆圖文消息
exports.graphicMsg = function(toUser,fromUser,contentArr){
     var xmlContent =  "<xml><ToUserName><![CDATA["+ toUser +"]]></ToUserName>";
        xmlContent += "<FromUserName><![CDATA["+ fromUser +"]]></FromUserName>";
        xmlContent += "<CreateTime>"+ new Date().getTime() +"</CreateTime>";
        xmlContent += "<MsgType><![CDATA[news]]></MsgType>";
        xmlContent += "<ArticleCount>"+contentArr.length+"</ArticleCount>";
        xmlContent += "<Articles>";
        contentArr.map(function(item,index){
            xmlContent+="<item>";
            xmlContent+="<Title><![CDATA["+ item.Title +"]]></Title>";
            xmlContent+="<Description><![CDATA["+ item.Description +"]]></Description>";
            xmlContent+="<PicUrl><![CDATA["+ item.PicUrl +"]]></PicUrl>";
            xmlContent+="<Url><![CDATA["+ item.Url +"]]></Url>";
            xmlContent+="</item>";
        });
        xmlContent += "</Articles></xml>";
    return xmlContent;
}
}

  更改 wechat.js 文件中的 handleMsg 方法,將圖消息推送響應在點擊事件中

case 'click':
                                var contentArr = [
                                    {Title:"Node.js 微信自定義菜單",Description:"使用Node.js實現自定義微信菜單",PicUrl:"http://img.blog.csdn.net/20170605162832842?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaHZrQ29kZXI=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast",Url:"http://blog.csdn.net/hvkcoder/article/details/72868520"},
                                    {Title:"Node.js access_token的獲取、存儲及更新",Description:"Node.js access_token的獲取、存儲及更新",PicUrl:"http://img.blog.csdn.net/20170528151333883?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaHZrQ29kZXI=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast",Url:"http://blog.csdn.net/hvkcoder/article/details/72783631"},
                                    {Title:"Node.js 接入微信公衆平臺開發",Description:"Node.js 接入微信公衆平臺開發",PicUrl:"http://img.blog.csdn.net/20170605162832842?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaHZrQ29kZXI=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast",Url:"http://blog.csdn.net/hvkcoder/article/details/72765279"}
                                ];
                               //回覆圖文消息
                               res.send(msg.graphicMsg(fromUser,toUser,contentArr));
                            break;

  點擊菜單下的 今日推薦
今日推薦

  圖文推送就是這麼簡單的被咱們給實現了。

4.接收普通消息

  微信除了爲咱們接收事件推送外,千萬不要忘了微信還能經過發送文字。而這一節咱們也就來玩玩微信接收普通消息。

  打開 微信幫助文檔,點擊左側菜單的消息管理,選擇其子菜單 接收普通消息,如圖:
消息管理 - 接收普通消息

  依然如接收事件推送的套路,不一樣的是參數發生了改變,但這並步影響咱們的開發,只須要幾步就可以完美的解決。更改 wechat.js 文件 handleMsg方法,這裏我先暫時只針對用戶輸入的文本消息作處理,其餘的跟其相似。

//判斷消息類型
                   if(result.MsgType.toLowerCase() === "event"){
                        //判斷事件類型
                        switch(result.Event.toLowerCase()){
                            case 'subscribe':
                                    //回覆消息
                                    var content = "歡迎關注 hvkcoder 公衆號,一塊兒鬥圖吧。回覆如下數字:\n";
                                        content += "1.你是誰\n";
                                        content += "2.關於Node.js\n";
                                        content += "回覆 「文章」  能夠獲得圖文推送哦~\n";
                                    res.send(msg.txtMsg(fromUser,toUser,''));
                                    break;
                            case 'click':
                                        var contentArr = [
                                            {Title:"Node.js 微信自定義菜單",Description:"使用Node.js實現自定義微信菜單",PicUrl:"http://img.blog.csdn.net/20170605162832842?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaHZrQ29kZXI=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast",Url:"http://blog.csdn.net/hvkcoder/article/details/72868520"},
                                            {Title:"Node.js access_token的獲取、存儲及更新",Description:"Node.js access_token的獲取、存儲及更新",PicUrl:"http://img.blog.csdn.net/20170528151333883?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaHZrQ29kZXI=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast",Url:"http://blog.csdn.net/hvkcoder/article/details/72783631"},
                                            {Title:"Node.js 接入微信公衆平臺開發",Description:"Node.js 接入微信公衆平臺開發",PicUrl:"http://img.blog.csdn.net/20170605162832842?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaHZrQ29kZXI=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast",Url:"http://blog.csdn.net/hvkcoder/article/details/72765279"}
                                        ];
                                    //回覆圖文消息
                                    res.send(msg.graphicMsg(fromUser,toUser,contentArr));
                                    break;
                        }
                   }else{
                       //判斷消息類型爲 文本消息
                       if(result.MsgType.toLowerCase() === "text"){
                           //根據消息內容返回消息信息
                           switch(result.Content){
                               case '1':
                                        res.send(msg.txtMsg(fromUser,toUser,'Hello !個人英文名字叫 H-VK'));
                                    break;
                               case '2':
                                        res.send(msg.txtMsg(fromUser,toUser,'Node.js是一個開放源代碼、跨平臺的JavaScript語言運行環境,採用Google開發的V8運行代碼,使用事件驅動、非阻塞和異步輸入輸出模型等技術來提升性能,可優化應用程序的傳輸量和規模。這些技術一般用於數據密集的事實應用程序'));
                                    break;
                               case '文章':
                                      var contentArr = [
                                            {Title:"Node.js 微信自定義菜單",Description:"使用Node.js實現自定義微信菜單",PicUrl:"http://img.blog.csdn.net/20170605162832842?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaHZrQ29kZXI=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast",Url:"http://blog.csdn.net/hvkcoder/article/details/72868520"},
                                            {Title:"Node.js access_token的獲取、存儲及更新",Description:"Node.js access_token的獲取、存儲及更新",PicUrl:"http://img.blog.csdn.net/20170528151333883?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaHZrQ29kZXI=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast",Url:"http://blog.csdn.net/hvkcoder/article/details/72783631"},
                                            {Title:"Node.js 接入微信公衆平臺開發",Description:"Node.js 接入微信公衆平臺開發",PicUrl:"http://img.blog.csdn.net/20170605162832842?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaHZrQ29kZXI=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast",Url:"http://blog.csdn.net/hvkcoder/article/details/72765279"}
                                        ];
                                        //回覆圖文消息
                                        res.send(msg.graphicMsg(fromUser,toUser,contentArr));
                                    break;
                                default :
                                         res.send(msg.txtMsg(fromUser,toUser,'沒有這個選項哦'));
                                    break;
                           }
                       }
                   }

微信消息 文本消息處理

微信消息 文本消息處理

測試微信公衆號

  OK !至此咱們就完成了微信消息管理的講解,彷佛真的沒有什麼難度。預留了一章,主要想要去細說一下說消息加解密,由於在網上涉及 Node.js 微信消息加解密的文章確實不多,微信幫助文檔給的案例也沒有 Node.js 的詳細說明。

  最後文章代碼部分,因爲網上編輯器的代碼換行作的不是很好可能有些亂,建議能夠去個人 github 上查看源碼。

  文章源代碼:https://github.com/SilenceHVK/wechatByNode 。對文章有不正確之處,請給予糾正。github源代碼請順手給個 Star,最後感謝您的閱讀。

文章目錄:
        1.Node.js 接入微信公衆平臺開發
        2.Node.js access_token的獲取、存儲及更新
        3.Node.js 自定義微信菜單
        4.Node.js 微信消息管理

相關文章
相關標籤/搜索