详解nodejs微信公众号开发——3.封装消息响应模块


Posted in NodeJs onApril 10, 2017

上一篇文章:nodejs微信公众号开发(2)自动回复,实现了简单的关注回复。采用拼接字符串的形式,并不是很方便,这里我们将其封装承接口。

1. ejs模板引擎

不使用拼接字符串的方式,那么模板引擎就是较好的选择。Nodejs开源模板的选择很多,程序中使用 EJS,有Classic ASP/PHP/JSP的经验用起EJS来的确可以很自然,也就是说,你能够在 <%...%> 块中安排 JavaScript 代码,利用最传统的方式 <%=输出变量%>(另外 <%-输出变量是不会对 & 等符号进行转义的).

2. heredoc

在php、python中都有heredoc方式的字符串定义方法,JavaScript也实现了heredoc模块,主要解决大量字符串拼接问题。
新建模板文件tpl.js:

'use strict'

var ejs = require('ejs');
var heredoc = require('heredoc');

var tpl = heredoc(function(content){/*
  <xml>
    <ToUserName><![CDATA[<%= toUserName %>]]></ToUserName>
    <FromUserName><![CDATA[<%= fromUserName %>]]></FromUserName>
    <CreateTime><%= createTime%></CreateTime>
    <MsgType><![CDATA[<%= msgType %>]]></MsgType>
    <% if(msgType ==='text') { %>
      <Content><![CDATA[<%= content %>]]></Content>
    <% }else if(msgType ==='image'){ %>
      <Image>
        <MediaId><![CDATA[<%= content.mediaId %>]]></MediaId>
      </Image>
    <% }else if(msgType ==='voice'){ %>
      <Voice>
        <MediaId><![CDATA[<%= content.mediaId %>]]></MediaId>
      </Voice>
    <% } %>else if(msgType ==='video'){ %>
      <Video>
        <MediaId><![CDATA[<%= content.mediaId %>]]></MediaId>
        <Title><![CDATA[<%= content.title %>]]></Title>
        <Description><![CDATA[<%= content.description %>]]></Description>
      </Video>   
    <% } %>else if(msgType ==='music'){ %>
      <Music>
        <Title><![CDATA[<%= content.title %>]]></Title>
        <Description><![CDATA[<%= content.description %>]]></Description>
        <MusicUrl><![CDATA[<%= content.musicUrl %>]]></MusicUrl>
        <HQMusicUrl><![CDATA[<%= content.hqMusicUrl %>]]></HQMusicUrl>
        <ThumbMediaId><![CDATA[<%= content.thumbMediaId %>]]></ThumbMediaId>  
      </Music>
    <% } %>else if(msgType ==='news'){ %>
      <ArticleCount><%= content.length %></ArticleCount>
      <Articles>
        <% content.forEach(function(item){ %>
        <item>
          <Title><![CDATA[<%= item.title %>]]></Title> 
          <Description><![CDATA[<%= item.description %>]]></Description>
          <PicUrl><![CDATA[<%= item.picUrl %>]]></PicUrl>
          <Url><![CDATA[<%= item.url %>]]></Url>
        </item>
        <% }) %>
      </Articles>
    <% } %>  
  </xml>
*/});

var compiled = ejs.compiled(tpl);

exports = module.exports = {
  compiled:compiled
};

3. 处理接收到的消息

修改generator.js中之前直接回复消息的那部分代码,我们将处理回复内容的逻辑交给业务层,等其处理完毕,继续执行下面的代码,封装消息内容成xml并回复出去。

var message = util.formatMessage(content.xml);
    
this.weixin = message; //挂载消息

yield handler.call(this,next);  //转到业务层逻辑

wechat.replay.call(this); //真正回复

4.业务层的处理逻辑

app.js里面中间件的使用方式修改为:

var weixin = require('./weixin');
...
app.use(wechat(config.wechat,weixin.reply));

weixin.replygenerator.js中的handler,我们将公众号业务成的逻辑都写在weixin.js里面,如回复消息、将来的爬取电影网站信息、支付等。

exports.reply = function* (next){
  var message = this.weixin;

  if(message.magType === 'event'){
    if(message.Event === 'subscribe'){
      if(message.EventKey) console.log('扫描二维码关注:'+message.EventKey+' '+message.ticket);
      this.body = '终于等到你,还好我没放弃';
    }else if(message.Event === 'unsubscribe'){
      console.log(message.FromUserName +' 悄悄地走了...');
    }
  }else{
    //
  }

  yield next;
}

5.回复消息

我们在Wechat原型链上增加replay方法:

Wechat.prototype.replay = function(){
  var content = this.body;
  var message = this.weixin;

  var xml = util.tpl(content,message);

  this.status = 200;
  this.type = 'application/xml';
  this.body = xml;
}

这样实现了wechat.replay.call(this); 的回复消息功能。

6.总结

上面代码已经基本实现了消息的封装,回复规则和回复内容写在业务层代码weixin.js中,里面简单的实现了关注和取关的事件处理。

由于koa框架是基于ES6,里面充斥了大量的Promisegenaratoryield等内容,对ES6不了解的,可以学习一下此篇文章:ECMAScript6快速入手攻略

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

NodeJs 相关文章推荐
基于NodeJS的前后端分离的思考与实践(三)轻量级的接口配置建模框架
Sep 26 NodeJs
详解Nodejs之静态资源处理
Jun 05 NodeJs
nodejs中解决异步嵌套循环和循环嵌套异步的问题
Jul 12 NodeJs
nodejs实现大文件(在线视频)的读取
Oct 16 NodeJs
nodejs基于express实现文件上传的方法
Mar 19 NodeJs
NodeJS安装图文教程
Apr 19 NodeJs
NodeJS实现自定义流的方法
Aug 01 NodeJs
Nodejs实现多文件夹文件同步
Oct 17 NodeJs
nodejs基础之常用工具模块util用法分析
Dec 26 NodeJs
纯异步nodejs文件夹(目录)复制功能
Sep 03 NodeJs
使用nodeJS中的fs模块对文件及目录进行读写,删除,追加,等操作详解
Feb 06 NodeJs
NodeJS配置CORS实现过程详解
Dec 02 NodeJs
详解nodejs微信公众号开发——2.自动回复
Apr 10 #NodeJs
详解nodejs微信公众号开发——1.接入微信公众号
Apr 10 #NodeJs
使用 NodeJS+Express 开发服务端的简单介绍
Apr 07 #NodeJs
初识NodeJS服务端开发入门(Express+MySQL)
Apr 07 #NodeJs
nodejs服务搭建教程 nodejs访问本地站点文件
Apr 07 #NodeJs
nodejs爬虫遇到的乱码问题汇总
Apr 07 #NodeJs
详解nodejs爬虫程序解决gbk等中文编码问题
Apr 06 #NodeJs
You might like
JoshChen_php新手进阶高手不可或缺的规范介绍
2013/08/16 PHP
PHP处理Oracle的CLOB实例
2014/11/03 PHP
PHP获取数组长度或某个值出现次数的方法
2015/02/11 PHP
PHP使用XMLWriter读写xml文件操作详解
2018/07/31 PHP
javascript prototype 原型链
2009/03/12 Javascript
firefox和IE系列的相关区别整理 以备后用
2009/12/28 Javascript
js遍历、动态的添加数据的小例子
2013/06/22 Javascript
js阻止事件追加的具体实现
2014/10/15 Javascript
使用AngularJS和PHP的Laravel实现单页评论的方法
2015/06/19 Javascript
在jQuery中使用$而避免跟其它库产生冲突的方法
2015/08/13 Javascript
javaScript事件学习小结(四)event的公共成员(属性和方法)
2016/06/09 Javascript
js删除数组元素、清空数组的简单方法(必看)
2016/07/27 Javascript
angularjs ocLazyLoad分步加载js文件实例
2017/01/17 Javascript
基于nodejs+express4.X实现文件下载的实例代码
2017/07/13 NodeJs
vue 中基于html5 drag drap的拖放效果案例分析
2018/11/01 Javascript
vue自定义js图片碎片轮播图切换效果的实现代码
2019/04/28 Javascript
原生javascript的ajax请求及后台PHP响应操作示例
2020/02/24 Javascript
Vue vm.$attrs使用场景详解
2020/03/08 Javascript
详解Vue.js 响应接口
2020/07/04 Javascript
python 将md5转为16字节的方法
2018/05/29 Python
Django contenttypes 框架详解(小结)
2018/08/13 Python
Python 实现某个功能每隔一段时间被执行一次的功能方法
2018/10/14 Python
对pandas中时间窗函数rolling的使用详解
2018/11/28 Python
手把手教你使用Python创建微信机器人
2019/04/29 Python
python3.6 如何将list存入txt后再读出list的方法
2019/07/02 Python
python多线程分块读取文件
2019/08/29 Python
Python 实现一个手机号码获取妹子名字的功能
2019/09/25 Python
django实现模型字段动态choice的操作
2020/04/01 Python
英国领先的品牌珠宝和配件供应商:Acotis Jewellery
2018/03/07 全球购物
美国汽车零部件和配件网站:CarParts
2019/03/13 全球购物
旅游与环境专业求职信
2014/06/05 职场文书
经营理念口号
2014/06/21 职场文书
法制教育演讲稿
2014/09/10 职场文书
党员年终个人总结
2015/02/14 职场文书
CSS中Single Div 绘图技巧的实现
2021/06/18 HTML / CSS
Java的Object类的九种方法
2022/04/13 Java/Android