3、微信公共號(hào)自動(dòng)回復(fù)

當(dāng)普通微信用戶向公眾賬號(hào)發(fā)消息時(shí),微信服務(wù)器將POST消息的XML數(shù)據(jù)包到開發(fā)者填寫的URL上。
微信用戶向公共賬號(hào)發(fā)送的消息類型包括:文本消息、圖片消息、語音消息、視頻消息、小視頻消息、地理位置消息、鏈接消息。除了發(fā)送消息,微信用戶還會(huì)向公共賬號(hào)推送事件:
1 關(guān)注/取消關(guān)注事件
2 掃描帶參數(shù)二維碼事件
3 上報(bào)地理位置事件
4 自定義菜單事件
5 點(diǎn)擊菜單拉取消息時(shí)的事件推送
6 點(diǎn)擊菜單跳轉(zhuǎn)鏈接時(shí)的事件推送
當(dāng)你的微信公共賬號(hào)接入第三方服務(wù)器的時(shí)候,微信服務(wù)器會(huì)把這些消息和事件通通推送到第三方服務(wù)器,如果第三方服務(wù)器沒有做合適的處理向微信服務(wù)器返回信息的話,微信服務(wù)器會(huì)向用戶返回:“該公告號(hào)服務(wù)不可用”等錯(cuò)誤信息,所以,我們需要對(duì)這些POST請(qǐng)求進(jìn)行處理。

我們?cè)谔幚砦⑿臥OST請(qǐng)求的時(shí)候先要照“接入微信”的驗(yàn)證流程進(jìn)行驗(yàn)證,如果驗(yàn)證成功的話再做出響應(yīng),微信POST過來的消息和事件都是XML格式的字符串,因此,我們需要下載一個(gè)XML解析插件:express-xml-bodyparser。



下載并應(yīng)用這個(gè)插件后,我們的程序便可以通過這個(gè)插件進(jìn)行解析XML數(shù)據(jù)了
微信POST過來的數(shù)據(jù)是這個(gè)樣子的:

<xml>
 <ToUserName><![CDATA[toUser]]></ToUserName>
 <FromUserName><![CDATA[fromUser]]></FromUserName>
 <CreateTime>1348831860</CreateTime>
 <MsgType><![CDATA[text]]></MsgType>
 <Content><![CDATA[this is a test]]></Content>
 <MsgId>1234567890123456</MsgId>
 </xml>

我們通過這種方式進(jìn)行解析:

var msgtype = req.body.xml.msgtype[0].toString();
var tousername = req.body.xml.tousername[0].toString();
var fromusername = req.body.xml.fromusername[0].toString();
var createtime = Math.round(Date.now() / 1000);
var content = req.body.xml.content[0].toString();

拿到數(shù)據(jù)后我們還需要再次拼接成XML格式的數(shù)據(jù)返回給微信,注意,此處的發(fā)送方(fromusername)和接受方(tousername)發(fā)生了反轉(zhuǎn):

var xmlstr=`<xml>
             <ToUserName><![CDATA[${fromusername}]]></ToUserName>
             <FromUserName><![CDATA[${tousername}]]></FromUserName>
             <CreateTime>${createtime}</CreateTime>
             <MsgType><![CDATA[${msgtype}]]></MsgType>
                 <Content><![CDATA[${content}]]></Content>
            </xml>`
res.set('Content-Type','text/xml')
res.send(xmlstr)    

公共平臺(tái)響應(yīng)的消息類型和數(shù)據(jù)格式請(qǐng)參考:
1 回復(fù)文本消息
2 回復(fù)圖片消息
3 回復(fù)語音消息
4 回復(fù)視頻消息
5 回復(fù)音樂消息
6 回復(fù)圖文消息

我們需要對(duì)不同類型的消息做出判斷,我們可以在程序中做簡(jiǎn)單處理:

// 4、開發(fā)者獲得加密后的字符串可與signature對(duì)比,標(biāo)識(shí)該請(qǐng)求來源于微信
    if (signature===sign) {

        // 如果簽名驗(yàn)證通過后
        var msgtype = req.body.xml.msgtype[0].toString();

        if (msgtype=='text') {
            var tousername = req.body.xml.tousername[0].toString();
            var fromusername = req.body.xml.fromusername[0].toString();
            var createtime = Math.round(Date.now() / 1000);
            var content = req.body.xml.content[0].toString();
            var xmlstr=`<xml>
                                     <ToUserName><![CDATA[${fromusername}]]></ToUserName>
                                     <FromUserName><![CDATA[${tousername}]]></FromUserName>
                                     <CreateTime>${createtime}</CreateTime>
                                     <MsgType><![CDATA[${msgtype}]]></MsgType>
                                     <Content><![CDATA[${content}]]></Content>
                                 </xml>`
            res.set('Content-Type','text/xml')
            res.send(xmlstr)                     
        } else if(msgtype=='image') {
            var tousername = req.body.xml.tousername[0].toString();
            var fromusername = req.body.xml.fromusername[0].toString();
            var createtime = Math.round(Date.now() / 1000);
            var content = "您好,您發(fā)過來的是一張圖片";
            var xmlstr=`<xml>
                                     <ToUserName><![CDATA[${fromusername}]]></ToUserName>
                                     <FromUserName><![CDATA[${tousername}]]></FromUserName>
                                     <CreateTime>${createtime}</CreateTime>
                                     <MsgType><![CDATA[text]]></MsgType>
                                     <Content><![CDATA[${content}]]></Content>
                                 </xml>`
            res.set('Content-Type','text/xml')
            res.send(xmlstr)    
        } else if(msgtype=='voice') {
            var tousername = req.body.xml.tousername[0].toString();
            var fromusername = req.body.xml.fromusername[0].toString();
            var createtime = Math.round(Date.now() / 1000);
            var content = "您好,您發(fā)過來的是一段語音";
            var xmlstr=`<xml>
                                     <ToUserName><![CDATA[${fromusername}]]></ToUserName>
                                     <FromUserName><![CDATA[${tousername}]]></FromUserName>
                                     <CreateTime>${createtime}</CreateTime>
                                     <MsgType><![CDATA[text]]></MsgType>
                                     <Content><![CDATA[${content}]]></Content>
                                 </xml>`
            res.set('Content-Type','text/xml')
            res.send(xmlstr)    
        } else if(msgtype=='video') {
            var tousername = req.body.xml.tousername[0].toString();
            var fromusername = req.body.xml.fromusername[0].toString();
            var createtime = Math.round(Date.now() / 1000);
            var content = "您好,您發(fā)過來的是一段視頻";
            var xmlstr=`<xml>
                                     <ToUserName><![CDATA[${fromusername}]]></ToUserName>
                                     <FromUserName><![CDATA[${tousername}]]></FromUserName>
                                     <CreateTime>${createtime}</CreateTime>
                                     <MsgType><![CDATA[text]]></MsgType>
                                     <Content><![CDATA[${content}]]></Content>
                                 </xml>`
            res.set('Content-Type','text/xml')
            res.send(xmlstr)    
        } else if(msgtype=='shortvideo') {
            var tousername = req.body.xml.tousername[0].toString();
            var fromusername = req.body.xml.fromusername[0].toString();
            var createtime = Math.round(Date.now() / 1000);
            var content = "您好,您發(fā)過來的是一段短視頻";
            var xmlstr=`<xml>
                                     <ToUserName><![CDATA[${fromusername}]]></ToUserName>
                                     <FromUserName><![CDATA[${tousername}]]></FromUserName>
                                     <CreateTime>${createtime}</CreateTime>
                                     <MsgType><![CDATA[text]]></MsgType>
                                     <Content><![CDATA[${content}]]></Content>
                                 </xml>`
            res.set('Content-Type','text/xml')
            res.send(xmlstr)    
        } else if(msgtype=='location') {
            var tousername = req.body.xml.tousername[0].toString();
            var fromusername = req.body.xml.fromusername[0].toString();
            var createtime = Math.round(Date.now() / 1000);
            var content = "您好,您發(fā)過來的是一個(gè)地理位置";
            var xmlstr=`<xml>
                                     <ToUserName><![CDATA[${fromusername}]]></ToUserName>
                                     <FromUserName><![CDATA[${tousername}]]></FromUserName>
                                     <CreateTime>${createtime}</CreateTime>
                                     <MsgType><![CDATA[text]]></MsgType>
                                     <Content><![CDATA[${content}]]></Content>
                                 </xml>`
            res.set('Content-Type','text/xml')
            res.send(xmlstr)    
        } else if(msgtype=='link') {
            var tousername = req.body.xml.tousername[0].toString();
            var fromusername = req.body.xml.fromusername[0].toString();
            var createtime = Math.round(Date.now() / 1000);
            var content = "您好,您發(fā)過來的是個(gè)網(wǎng)站鏈接";
            var xmlstr=`<xml>
                                     <ToUserName><![CDATA[${fromusername}]]></ToUserName>
                                     <FromUserName><![CDATA[${tousername}]]></FromUserName>
                                     <CreateTime>${createtime}</CreateTime>
                                     <MsgType><![CDATA[text]]></MsgType>
                                     <Content><![CDATA[${content}]]></Content>
                                 </xml>`
            res.set('Content-Type','text/xml')
            res.send(xmlstr)    
        } else if(msgtype=='event') {
            var tousername = req.body.xml.tousername[0].toString();
            var fromusername = req.body.xml.fromusername[0].toString();
            var Event = req.body.xml.event[0].toString();
            var createtime = Math.round(Date.now() / 1000);
            var content = "您好,您觸發(fā)了一個(gè)事件";
            var xmlstr=`<xml>
                                     <ToUserName><![CDATA[${fromusername}]]></ToUserName>
                                     <FromUserName><![CDATA[${tousername}]]></FromUserName>
                                     <CreateTime>${createtime}</CreateTime>
                                     <MsgType><![CDATA[text]]></MsgType>
                                     <Content><![CDATA[${content}]]></Content>
                                 </xml>`
            res.set('Content-Type','text/xml')
            res.send(xmlstr)    
        } else{
            var tousername = req.body.xml.tousername[0].toString();
            var fromusername = req.body.xml.fromusername[0].toString();
            var createtime = Math.round(Date.now() / 1000);
            var content = "抱歉,我們不能接受此類型的消息";
            var xmlstr=`<xml>
                                     <ToUserName><![CDATA[${fromusername}]]></ToUserName>
                                     <FromUserName><![CDATA[${tousername}]]></FromUserName>
                                     <CreateTime>${createtime}</CreateTime>
                                     <MsgType><![CDATA[text]]></MsgType>
                                     <Content><![CDATA[${content}]]></Content>
                                 </xml>`
            res.set('Content-Type','text/xml')
            res.send(xmlstr)    
        };

    }else{
        res.send("invalid sign")
    }

這是我們?cè)诖a中寫死的回復(fù)規(guī)則,每次更新都需要重新更改代碼,比較麻煩。如果在生產(chǎn)環(huán)境,有需求的話,我們可以做一個(gè)消息回復(fù)管理系統(tǒng),代替微信的默認(rèn)內(nèi)管,這樣只需要在系統(tǒng)中做一個(gè)規(guī)則配置,公共號(hào)便可以按照配置進(jìn)行響應(yīng)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,699評(píng)論 19 139
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,355評(píng)論 25 708
  • 國(guó)家電網(wǎng)公司企業(yè)標(biāo)準(zhǔn)(Q/GDW)- 面向?qū)ο蟮挠秒娦畔?shù)據(jù)交換協(xié)議 - 報(bào)批稿:20170802 前言: 排版 ...
    庭說閱讀 12,537評(píng)論 6 13
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,703評(píng)論 4 61
  • 斷篇十二 第二天雪夜就去找夏哥了,她是去辭職的,總之就是不想在這里干了。去的時(shí)候他不在辦公室里,結(jié)果雪夜就只能在辦...
    等待自由的青鳥閱讀 860評(píng)論 0 2

友情鏈接更多精彩內(nèi)容