最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

NodeJS實(shí)現(xiàn)微信公眾號(hào)關(guān)注后自動(dòng)回復(fù)功能

 更新時(shí)間:2017年05月31日 08:26:58   作者:姜騰騰  
這篇文章主要為大家詳細(xì)介紹了NodeJS實(shí)現(xiàn)微信公眾號(hào)關(guān)注后自動(dòng)回復(fù)功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

一 實(shí)先自動(dòng)回復(fù)功能的邏輯步驟

  1 處理POST類型的控制邏輯,接收XML的數(shù)據(jù)包;

  2 解析XML數(shù)據(jù)包(獲得數(shù)據(jù)包的消息類型或者是事件類型);

  3 拼裝我們定義好的消息;

  4 包裝成XML格式;

  5 在5秒內(nèi)返回回去

二 代碼實(shí)操

  本節(jié)代碼參照上節(jié)課繼續(xù)修改和完善,目錄結(jié)構(gòu)跟之前相同,新引入的模塊raw-body使用npm install安裝一下即可,app.js啟動(dòng)文件和util.js不做變動(dòng),主要修改一下generator.js文件,以及在generator.js同級(jí)目錄下新建wechat.js文件和tools.js文件。

  wechat.js文件是將前一節(jié)generator.js文件中票據(jù)部分的代碼抽離出來(lái)單獨(dú)放在一個(gè)文件中,具體代碼如下:

'use strict';
// 引入模塊
var Promise = require('bluebird');
var request = Promise.promisify(require('request'));

//增加url配置項(xiàng)
var prefix = 'https://api.weixin.qq.com/cgi-bin/';
var api = {
  accessToken: prefix + 'token?grant_type=client_credential'
};

//利用構(gòu)造函數(shù)生成實(shí)例 完成票據(jù)存儲(chǔ)邏輯
function weChat(opts) {
  var that = this;
  this.appID = opts.appID;
  this.appSecret = opts.appSecret;
  this.getAccessToken = opts.getAccessToken;
  this.saveAccessToken = opts.saveAccessToken;
  //獲取票據(jù)的方法
  this.getAccessToken()
    .then(function(data) {
      //從靜態(tài)文件獲取票據(jù),JSON化數(shù)據(jù),如果有異常,則嘗試更新票據(jù)
      try {
        data = JSON.parse(data);
      } catch (e) {
        return that.updateAccessToken();
      }
      //判斷票據(jù)是否在有效期內(nèi),如果合法,向下傳遞票據(jù),如果不合法,更新票據(jù)
      if (that.isValidAccessToken(data)) {
        Promise.resolve(data);
      } else {
        return that.updateAccessToken();
      }
    })
    //將拿到的票據(jù)信息和有效期信息存儲(chǔ)起來(lái)
    .then(function(data) {
      //console.log(data);
      that.access_token = data.access_token;
      that.expires_in = data.expires_in;

      that.saveAccessToken(data);
    })
};

//在weChat的原型鏈上增加驗(yàn)證有效期的方法
weChat.prototype.isValidAccessToken = function(data) {
  //進(jìn)行判斷,如果票據(jù)不合法,返回false
  if (!data || !data.access_token || !data.expires_in) {
    return false;
  }
  //拿到票據(jù)和過(guò)期時(shí)間的數(shù)據(jù)
  var access_token = data.access_token;
  var expires_in = data.expires_in;
  //獲取當(dāng)前時(shí)間
  var now = (new Date().getTime());
  //如果當(dāng)前時(shí)間小于票據(jù)過(guò)期時(shí)間,返回true,否則返回false
  if (now < expires_in) {
    return true;
  } else {
    return false;
  };
};

//在weChat的原型鏈上增加更新票據(jù)的方法
weChat.prototype.updateAccessToken = function() {
  var appID = this.appID;
  var appSecret = this.appSecret;
  var url = api.accessToken + '&appid=' + appID + '&secret=' + appSecret;

  return new Promise(function(resolve, reject) {
    //使用request發(fā)起請(qǐng)求
    request({
      url: url,
      json: true
    }).then(function(response) {
      var data = response.body;
      var now = (new Date().getTime());
      var expires_in = now + (data.expires_in - 20) * 1000;
      //把新票據(jù)的有效時(shí)間賦值給data
      data.expires_in = expires_in;
      resolve(data);
    })
  })
};

//向外暴露weChat
module.exports = weChat;

  generator.js文件進(jìn)行精簡(jiǎn)后,添加判斷對(duì)xml數(shù)據(jù)的格式化方法以及判斷事件,添加關(guān)注事件測(cè)試信息,具體代碼如下:

'use strict';
// 引入模塊
var sha1 = require('sha1');
var getRawBody = require('raw-body');
var weChat = require('./wechat');
var tools = require('./tools');

// 建立中間件函數(shù)并暴露出去
module.exports = function(opts) {
  //實(shí)例化weChat()函數(shù)
  //var wechat = new weChat(opts);
  return function*(next) {
    //console.log(this.query);
    var that = this;
    var token = opts.token;
    var signature = this.query.signature;
    var nonce = this.query.nonce;
    var timestamp = this.query.timestamp;
    var echostr = this.query.echostr;
    // 進(jìn)行字典排序
    var str = [token, timestamp, nonce].sort().join('');
    // 進(jìn)行加密
    var sha = sha1(str);
    //使用this.method對(duì)請(qǐng)求方法進(jìn)行判斷
    if (this.method === 'GET') {
      // 如果是get請(qǐng)求 判斷加密后的值是否等于簽名值
      if (sha === signature) {
        this.body = echostr + '';
      } else {
        this.body = 'wrong';
      };
    } else if (this.method === 'POST') {
      //如果是post請(qǐng)求 也是先判斷簽名是否合法 如果不合法 直接返回wrong
      if (sha !== signature) {
        this.body = 'wrong';
        return false;
      };
      //通過(guò)raw-body模塊 可以把把this上的request對(duì)象 也就是http模塊中的request對(duì)象 去拼裝它的數(shù)據(jù) 最終拿到一個(gè)buffer的xml數(shù)據(jù)
      //通過(guò)yield關(guān)鍵字 獲取到post過(guò)來(lái)的原始的XML數(shù)據(jù)
      var data = yield getRawBody(this.req, {
        length: this.length,
        limit: '1mb',
        encoding: this.charset
      });
      //console.log(data.toString());打印XML數(shù)據(jù)(當(dāng)微信公眾號(hào)有操作的時(shí)候 終端可以看到返回的XML數(shù)據(jù))
      //tools為處理XML數(shù)據(jù)的工具包 使用tools工具包的parseXMLAsync方法 把XML數(shù)據(jù)轉(zhuǎn)化成數(shù)組對(duì)象
      var content = yield tools.parseXMLAsync(data);
      //console.log(content);打印轉(zhuǎn)化后的數(shù)組對(duì)象
      //格式化content數(shù)據(jù)為json對(duì)象
      var message = tools.formatMessage(content.xml);
      console.log(message);
      //打印message
      //判斷message的MsgType 如果是event 則是一個(gè)事件
      if (message.MsgType === 'event') {
        //如果是訂閱事件
        if (message.Event === 'subscribe') {
          //獲取當(dāng)前時(shí)間戳
          var now = new Date().getTime();
          //設(shè)置回復(fù)狀態(tài)是200
          that.status = 200;
          //設(shè)置回復(fù)的類型是xml格式
          that.type = 'application/xml';
          //設(shè)置回復(fù)的主體
          that.body = '<xml>' +
            '<ToUserName><![CDATA[' + message.FromUserName + ']]></ToUserName>' +
            '<FromUserName><![CDATA[' + message.ToUserName + ']]></FromUserName>' +
            '<CreateTime>' + now + '</CreateTime>' +
            '<MsgType><![CDATA[text]]></MsgType>' +
            '<Content><![CDATA[你好,同學(xué)!]]></Content>' +
            '</xml>';
          return;
        }
      }
    }

  }
};

  tools.js是處理XML數(shù)據(jù)的工具文件:

'use strict';
//引入模塊
var xml2js = require('xml2js');
var Promise = require('bluebird');
//導(dǎo)出解析XML的方法
exports.parseXMLAsync = function(xml) {
  return new Promise(function(resolve, reject) {
    xml2js.parseString(xml, { trim: true }, function(err, content) {
      if (err) {
        reject(err);
      } else {
        resolve(content);
      };
    });
  });
};
//因?yàn)関alue值可能是嵌套多層的 所以先對(duì)value值進(jìn)行遍歷
function formatMessage(result) {
  //聲明空對(duì)象message
  var message = {};
  //對(duì)result類型進(jìn)行判斷
  if (typeof result === 'object') {
    //如果是object類型 通過(guò)Object.keys()方法拿到result所有的key 并存入keys變量中
    var keys = Object.keys(result);
    //對(duì)keys進(jìn)行循環(huán)遍歷
    for (var i = 0; i < keys.length; i++) {
      //拿到每個(gè)key對(duì)應(yīng)的value值
      var item = result[keys[i]];
      //拿到key
      var key = keys[i];
      //判斷item是否為數(shù)組或者長(zhǎng)度是否為0
      if (!(item instanceof Array) || item.length === 0) {
        //如果item不是數(shù)組或者長(zhǎng)度為0 則跳過(guò)繼續(xù)向下解析
        continue;
      }
      //如果長(zhǎng)度為1
      if (item.length === 1) {
        //拿到value值存入val變量
        var val = item[0];
        //判斷val是否為對(duì)象
        if (typeof val === 'object') {
          //如果val為對(duì)象 則進(jìn)一步進(jìn)行遍歷
          message[key] = formatMessage(val);
        } else {
          //如果不是對(duì)象 就把值賦給當(dāng)前的key放入message里 并去除收尾空格
          message[key] = (val || '').trim();
        }
      }
      //如果item的長(zhǎng)度既不是0也不是1 則說(shuō)明它是一個(gè)數(shù)組
      else {
        //把message的key設(shè)置為空數(shù)組
        message[key] = [];
        //對(duì)數(shù)組進(jìn)行遍歷
        for (var j = 0, k = item.length; j < k; j++) {
          message[key].push(formatMessage(item[j]));
        }
      }
    }
  }
  return message;
}

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

exports.formatMessage = formatMessage;

  完成這節(jié)的代碼后,當(dāng)關(guān)注微信測(cè)試公眾號(hào)的時(shí)候,會(huì)自動(dòng)回復(fù)『你好,同學(xué)!』的提示信息。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Node中fs文件系統(tǒng)模塊的使用方法詳解

    Node中fs文件系統(tǒng)模塊的使用方法詳解

    fs?模塊是?Node.js?官方提供的、用來(lái)操作文件的模塊(內(nèi)置api),它提供了一系列的方法和屬性,用來(lái)滿足用戶對(duì)文件的操作需求,本文給大家介紹了Node中fs文件系統(tǒng)模塊的使用方法,需要的朋友可以參考下
    2024-03-03
  • 詳解Express筆記之動(dòng)態(tài)渲染HTML(新手入坑)

    詳解Express筆記之動(dòng)態(tài)渲染HTML(新手入坑)

    這篇文章主要介紹了詳解Express筆記之動(dòng)態(tài)渲染HTML(新手入坑),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-12-12
  • Node.js中的模塊化,npm包管理器詳解

    Node.js中的模塊化,npm包管理器詳解

    這篇文章主要介紹了node模塊與npm包管理工具,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2021-09-09
  • node.js實(shí)現(xiàn)的裝飾者模式示例

    node.js實(shí)現(xiàn)的裝飾者模式示例

    這篇文章主要介紹了node.js實(shí)現(xiàn)的裝飾者模式,簡(jiǎn)單說(shuō)明了裝飾者模式的原理、功能并結(jié)合實(shí)例形式給出了node.js裝飾者模式的實(shí)現(xiàn)方法,需要的朋友可以參考下
    2017-09-09
  • Nodejs之http的表單提交

    Nodejs之http的表單提交

    這篇文章主要為大家詳細(xì)介紹了Nodejs之http的表單提交,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-07-07
  • 一個(gè)簡(jiǎn)單的node.js界面實(shí)現(xiàn)方法

    一個(gè)簡(jiǎn)單的node.js界面實(shí)現(xiàn)方法

    今天小編就為大家分享一篇一個(gè)簡(jiǎn)單的node.js界面實(shí)現(xiàn)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-06-06
  • nodejs中操作mysql數(shù)據(jù)庫(kù)示例

    nodejs中操作mysql數(shù)據(jù)庫(kù)示例

    這篇文章主要介紹了nodejs中操作mysql數(shù)據(jù)庫(kù)示例,本文演示了如何在NodeJS中創(chuàng)建創(chuàng)建mysql連接、mysql數(shù)據(jù)庫(kù)、插入數(shù)據(jù)、查詢數(shù)據(jù)等功能,需要的朋友可以參考下
    2014-12-12
  • Nodejs實(shí)現(xiàn)獲取實(shí)時(shí)數(shù)據(jù)的三種主流方式詳解

    Nodejs實(shí)現(xiàn)獲取實(shí)時(shí)數(shù)據(jù)的三種主流方式詳解

    這篇文章主要為大家詳細(xì)介紹了Nodejs前端獲取實(shí)時(shí)數(shù)據(jù)的三種主流方式,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-02-02
  • NodeJS學(xué)習(xí)筆記之(Url,QueryString,Path)模塊

    NodeJS學(xué)習(xí)筆記之(Url,QueryString,Path)模塊

    今天我們來(lái)看一下在nodejs中路徑的相關(guān)操作方法。在我們開(kāi)發(fā)過(guò)程中路徑主要有:URL路徑,在瀏覽器中進(jìn)行使用,當(dāng)然這個(gè)也包含查詢字符串QueryString的相關(guān)操作;而另一種是磁盤路徑,主要用于文件等等進(jìn)行操作,我們稱為Path,所以我將它們放在一起進(jìn)行總結(jié)學(xué)習(xí)。
    2015-01-01
  • 使用GruntJS構(gòu)建Web程序之Tasks(任務(wù))篇

    使用GruntJS構(gòu)建Web程序之Tasks(任務(wù))篇

    任務(wù)(Tasks)是grunt的核心概念,你所做的很多工作比如資源合并(concat)、壓縮(uglify)都是在配置任務(wù)。 每次grunt運(yùn)行的時(shí)候,你指定的一個(gè)或多個(gè)任務(wù)也在運(yùn)行,如果你沒(méi)有指定任務(wù),那么一個(gè)默認(rèn)名為“default”的任務(wù)將自動(dòng)運(yùn)行。
    2014-06-06

最新評(píng)論

南部县| 彭泽县| 芦山县| 两当县| 新和县| 津南区| 德庆县| 金秀| 科尔| 楚雄市| 乐至县| 慈利县| 且末县| 南华县| 卫辉市| 富宁县| 宜都市| 黑水县| 卢湾区| 本溪| 舒兰市| 县级市| 上杭县| 朝阳县| 兴安盟| 天峻县| 淮安市| 信宜市| 邛崃市| 昭通市| 雷州市| 蓝田县| 七台河市| 永胜县| 无极县| 无为县| 灌阳县| 库车县| 清涧县| 长寿区| 文山县|