详解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 后缀名判断限制代码
Mar 31 NodeJs
Nodejs使用mysql模块之获得更新和删除影响的行数的方法
Mar 18 NodeJs
nodejs中简单实现Javascript Promise机制的实例
Dec 06 NodeJs
NodeJS使用formidable实现文件上传
Oct 27 NodeJs
Nodejs中解决cluster模块的多进程如何共享数据问题
Nov 10 NodeJs
基于NodeJS+MongoDB+AngularJS+Bootstrap开发书店案例分析
Jan 12 NodeJs
nodejs简单实现TCP服务器端和客户端的聊天功能示例
Jan 04 NodeJs
nodejs使用redis作为缓存介质实现的封装缓存类示例
Feb 07 NodeJs
利用nodeJs anywhere搭建本地服务器环境的方法
May 12 NodeJs
nodejs中用npm初始化来创建package.json的实例讲解
Oct 10 NodeJs
Nodejs实现的操作MongoDB数据库功能完整示例
Feb 02 NodeJs
详解利用nodejs对本地json文件进行增删改查
Sep 20 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
极典R601SW收音机
2021/03/02 无线电
PHP n个不重复的随机数生成代码
2009/06/23 PHP
PHP使用CURL_MULTI实现多线程采集的例子
2014/07/29 PHP
php检测mysql表是否存在的方法小结
2017/07/20 PHP
filemanage功能中用到的lib.js
2007/04/08 Javascript
用CSS+JS实现的进度条效果效果
2007/06/05 Javascript
JavaScript面向对象编程
2008/03/02 Javascript
javascript中的onkeyup和onkeydown区别介绍
2013/04/28 Javascript
多个jQuery版本共存的处理方案
2015/03/17 Javascript
JQuery自动触发事件的方法
2015/06/13 Javascript
jQuery实现可以控制图片旋转角度效果(附demo源码下载)
2016/01/27 Javascript
js获取iframe中的window对象的实现方法
2016/05/20 Javascript
JSON键值对序列化和反序列化解析
2017/01/24 Javascript
微信小程序表单验证错误提示效果
2017/05/19 Javascript
实例学习JavaScript读取和写入cookie
2018/01/29 Javascript
原生JS实现的雪花飘落动画效果
2018/05/03 Javascript
JavaScript常用数学函数用法示例
2018/05/14 Javascript
详解解决使用axios发送json后台接收不到的问题
2018/06/27 Javascript
Array.filter中如何正确使用Async
2020/11/04 Javascript
Python调用C/C++动态链接库的方法详解
2014/07/22 Python
Python实现windows下模拟按键和鼠标点击的方法
2015/03/13 Python
python实现复制整个目录的方法
2015/05/12 Python
Python实现可获取网易页面所有文本信息的网易网络爬虫功能示例
2018/01/15 Python
tensorflow创建变量以及根据名称查找变量
2018/03/10 Python
python处理multipart/form-data的请求方法
2018/12/26 Python
Django 过滤器汇总及自定义过滤器使用详解
2019/07/19 Python
如何用Python来搭建一个简单的推荐系统
2019/08/07 Python
tensorflow多维张量计算实例
2020/02/11 Python
意大利会呼吸的鞋:Geox健乐士
2017/02/12 全球购物
PHP笔试题
2012/02/22 面试题
社区娱乐活动方案
2014/08/21 职场文书
打架检讨书范文
2015/01/27 职场文书
手术室护士个人总结
2015/02/13 职场文书
婚礼家长致辞
2015/07/27 职场文书
小公司融资,商业计划书的8切记
2019/07/15 职场文书
Mysql分库分表之后主键处理的几种方法
2022/02/15 MySQL