詳解nodejs微信公眾號(hào)開發(fā)——2.自動(dòng)回復(fù)

上一篇文章:nodejs微信公眾號(hào)開發(fā)(1)接入微信公眾號(hào),本篇文章將在此基礎(chǔ)上實(shí)現(xiàn)簡(jiǎn)單的回復(fù)功能。

成都網(wǎng)站建設(shè)哪家好,找創(chuàng)新互聯(lián)建站!專注于網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站建設(shè)、微信開發(fā)、小程序制作、集團(tuán)企業(yè)網(wǎng)站設(shè)計(jì)等服務(wù)項(xiàng)目。核心團(tuán)隊(duì)均擁有互聯(lián)網(wǎng)行業(yè)多年經(jīng)驗(yàn),服務(wù)眾多知名企業(yè)客戶;涵蓋的客戶類型包括:酒店設(shè)計(jì)等眾多領(lǐng)域,積累了大量豐富的經(jīng)驗(yàn),同時(shí)也獲得了客戶的一致表?yè)P(yáng)!

1. 接入代碼的優(yōu)化

之前我們簡(jiǎn)單粗暴的實(shí)現(xiàn)了微信公眾號(hào)的接入,接入的代碼直接寫在了app.js文件里面,從項(xiàng)目開發(fā)的角度而言,不便于日后代碼的維護(hù),所以將這部分代碼獨(dú)立出來(lái),按照koa的風(fēng)格,寫成一個(gè)中間件。

在根目錄下新建wechat文件夾,新建generator.js文件,

var sha1 = require('sha1');

module.exports = function(opts){
  return function *(next){
    var token = opts.token;
    var signature = this.query.signature;
    var nonce = this.query.nonce;
    var timestamp = this.query.timestamp;
    var echostr = this.query.echostr;
    var str = [token,timestamp,nonce].sort().join('');
    var sha = sha1(str);
    this.body = (sha === signature) ? echostr + '' : 'failed';
  };
}

此時(shí)app.js的內(nèi)容變成:

'use strict'

var Koa = require('koa');
var wechat = require('./wechat/generator');

var config = {
  wechat:{
    appID:'...',
    appSecret:'...',
    token:'...'
  }
};

var app = new Koa();
app.use(wechat(config.wechat));
app.listen(8080);
console.log('Listening 8080...')

2. 獲取access_token

access_token是開發(fā)程序與wexin公眾平臺(tái)交互的一把鑰匙,調(diào)用絕大部分接口都需要用到access_token。

access_token的特點(diǎn):

  1. 有效期為2小時(shí)(7200s),過(guò)期自動(dòng)失效,需要重新獲取;
  2. 只要更新了access_token,之前的access_token自動(dòng)失效;

解決方案:

  1. 系統(tǒng)每隔2小時(shí)自動(dòng)去獲取一下access_token的值,確保access_token始終是有效的;
  2. 為了方便頻繁調(diào)用,將access_token存儲(chǔ)在唯一的一個(gè)地方(數(shù)據(jù)庫(kù)、文件等),所有子系統(tǒng)都能訪問(wèn)。

程序中采用構(gòu)造函數(shù)的方式,在生成實(shí)例,完成初始化工作的的過(guò)程中,讀取存儲(chǔ)在config/wechat.txt文件中的票據(jù),判斷是否為空且是否過(guò)期,選擇性的重新獲取數(shù)字并且保存在原文件里面,關(guān)于獲取access_token的官方文檔介紹可見:獲取access_token。

function Wechat(opts){   //構(gòu)造函數(shù),用以生成實(shí)例,完成初始化工作,讀寫票據(jù)
  var that = this;
  this.appID = opts.appID;
  this.appSecret = opts.appSecret;
  this.getAccessToken = opts.getAccessToken;
  this.saveAccessToken = opts.saveAccessToken;

  this.getAccessToken().then(function(data){
    try{
      data = JSON.parse(data);
    }catch(e){
      return that.updateAccessToken();
    }
    if(that.isvalidAccessToken(data)){
      Promise.resolve(data);
    }else{
      return that.updateAccessToken();
    }
  }).then(function(data){
    that.access_token = data.access_token;
    that.expires_in = data.expires_in;
    that.saveAccessToken(JSON.stringify(data));
  });
}

我們?cè)?code>moudle.exports中實(shí)例化一個(gè)Wechat

var wechat = new Wechat(opts);

這樣確保了每次程序啟動(dòng)都會(huì)獲取對(duì)access_token的有效性進(jìn)行檢驗(yàn),并且每個(gè)一段時(shí)間會(huì)自動(dòng)獲取一個(gè)新的access_token。

3. 處理微信消息的步驟

無(wú)論是事件推送還是消息推送,微信服務(wù)器都是以post的方式發(fā)送請(qǐng)求,推送的數(shù)據(jù)類型不是json而是xml,處理推送消息一般分為五個(gè)步驟:

  1. 處理POST類型的控制邏輯,接收xml數(shù)據(jù)包;
  2. 解析數(shù)據(jù)包,獲取數(shù)據(jù)包的消息類型或數(shù)據(jù)類型;
  3. 拼裝自定義的消息;
  4. 包裝成xml格式;
  5. 在5秒鐘內(nèi)返回消息。

3.1 接收xml數(shù)據(jù)

通過(guò)raw-body模塊可以獲取http模塊中的request對(duì)象,并且可以對(duì)數(shù)據(jù)進(jìn)行拼裝,從而拿到一個(gè)buffer的xml對(duì)象

var data = yield rawBody(this.req,{
        length:this.length,
        limit:'1mb',
        encoding:this.charset
      });
console.log('data:'+data);

詳解nodejs微信公眾號(hào)開發(fā)——2.自動(dòng)回復(fù)

3.2 解析xml數(shù)據(jù)

使用xml2js模塊,將xml數(shù)據(jù)解析成對(duì)象格式

var content = yield util.parseXMLAsync(data);
util中的parseXMLAsync方法:

exports.parseXMLAsync = function(xml){
  return new Promise(function(resolve,reject){
    xml2js.parseString(xml,{trim:true},function(err,content){
      err ? reject(err) : resolve(content);
    })
  });
}

詳解nodejs微信公眾號(hào)開發(fā)——2.自動(dòng)回復(fù)

3.3 格式化xml數(shù)據(jù)

從解析的xml數(shù)據(jù)來(lái)看,數(shù)據(jù)雖然已經(jīng)呈現(xiàn)鍵值對(duì)的形式,但是其值是數(shù)組的形式,需要進(jìn)行扁平化處理:

var message = util.formatMessage(content.xml);

其本質(zhì)就是遍歷數(shù)組中的值,因?yàn)樵诙鄨D文的消息中存在嵌套的情況:

function formatMessage(result){
  var message = {};
  if(typeof result === 'object'){
    var keys = Object.keys(result);
    for(var i=0;i<keys.length;i++){
      var key = keys[i];
      var item = result[key];
      if(!(item instanceof Array) || item.length === 0) continue;
      if (item.length === 1){
        var val = item[0];
        if (typeof val === 'object') message[key] = formatMessage(val);
        else message[key] = (val || '').trim();
      }else{
        message[key] = [];
        for(var j=0,k=item.length;j<k;j++) message[key].push(formatMessage(item[j]));
      }
    }
  }
  return message;
}

詳解nodejs微信公眾號(hào)開發(fā)——2.自動(dòng)回復(fù)

3.4 判斷消息類型并回復(fù)

這里針對(duì)subscribe事件,新關(guān)注后自動(dòng)回復(fù)文本消息終于等到你,還好我沒放棄

if(message.MsgType === 'event'){
  if(message.Event === 'subscribe'){
    var createTime = new Date().getTime();
    that.status = 200;
    that.type = 'application/xml';
    that.body = '<xml>'+
          '<ToUserName><![CDATA['+ message.FromUserName +']]></ToUserName>'+
          '<FromUserName><![CDATA['+ message.ToUserName +']]></FromUserName>'+
          '<CreateTime>'+createTime+'</CreateTime>'+
          '<MsgType><![CDATA[text]]></MsgType>'+
          '<Content><![CDATA[終于等到你,還好我沒放棄]]></Content>'+
          '</xml>'
    return;
  }
}

注:這里只是簡(jiǎn)單地實(shí)現(xiàn)一下自動(dòng)回復(fù)功能,這種拼接字符串的方式還是很不方便的,后面會(huì)封裝成接口。

使用手機(jī)微信掃描測(cè)試賬號(hào)的二維碼,即可關(guān)注,同時(shí)接收到測(cè)試公眾號(hào)推送的消息!

詳解nodejs微信公眾號(hào)開發(fā)——2.自動(dòng)回復(fù)

啦啦,一個(gè)簡(jiǎn)單的關(guān)注回復(fù)就完成了。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。

新聞名稱:詳解nodejs微信公眾號(hào)開發(fā)——2.自動(dòng)回復(fù)
分享網(wǎng)址:http://muchs.cn/article12/pjjjdc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供外貿(mào)網(wǎng)站建設(shè)、動(dòng)態(tài)網(wǎng)站小程序開發(fā)、品牌網(wǎng)站設(shè)計(jì)App設(shè)計(jì)、移動(dòng)網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

小程序開發(fā)