4.Node.js 微信消息管理


一、寫在前面的話

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

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

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

二、微信消息管理

1.捕獲消息信息

  在文章的第一句話中,為我們指明了微信消息產生的請求方式為 POST,因此首先我們就去對 Node.js 的 Post 請求進行監聽。

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

//用於處理所有進入 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 啟動后映射至外網,關注我們的微信公眾號,在控制台中則會看到:
輸出結果

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

微信接收事件推送

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

  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 微信消息管理


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM