详解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之请求路由概述
Jul 05 NodeJs
Nodejs Post请求报socket hang up错误的解决办法
Sep 25 NodeJs
Nodejs学习笔记之NET模块
Jan 13 NodeJs
NodeJS连接MongoDB数据库时报错的快速解决方法
May 13 NodeJs
详解Windows下安装Nodejs步骤
May 18 NodeJs
Nodejs模块载入运行原理
Feb 23 NodeJs
Nodejs 和 Electron ubuntu下快速安装过程
May 04 NodeJs
nodeJS服务器的创建和重新启动的实现方法
May 12 NodeJs
nodeJS与MySQL实现分页数据以及倒序数据
Jun 05 NodeJs
通过实例了解Nodejs模块系统及require机制
Jul 16 NodeJs
分享node.js实现简单登录注册的具体代码
Apr 26 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
php实现文件下载(支持中文文名)
2013/12/04 PHP
[原创]php实现子字符串位置相互对调互换的方法
2016/06/02 PHP
TP(thinkPHP)框架多层控制器和多级控制器的使用示例
2018/06/13 PHP
一张表格告诉你windows.onload()与$(document).ready()的区别
2014/05/16 Javascript
js操作css属性实现div层展开关闭效果的方法
2015/05/11 Javascript
javascript基础语法学习笔记
2016/01/04 Javascript
浅析$.getJSON异步请求和同步请求
2016/06/06 Javascript
vue-hook-form使用详解
2017/04/07 Javascript
BootStrap中的Fontawesome 图标
2017/05/25 Javascript
JS实现的视频弹幕效果示例
2018/08/17 Javascript
vue 设置 input 为不可以编辑的实现方法
2019/09/19 Javascript
解决VUE 在IE下出现ReferenceError: Promise未定义的问题
2020/11/07 Javascript
[01:00:53]2018DOTA2亚洲邀请赛3月29日 小组赛B组 iG VS Secret
2018/03/30 DOTA
将图片文件嵌入到wxpython代码中的实现方法
2014/08/11 Python
Anaconda多环境多版本python配置操作方法
2017/09/12 Python
python3使用requests模块爬取页面内容的实战演练
2017/09/25 Python
Python实现线程状态监测简单示例
2018/03/28 Python
Python采集代理ip并判断是否可用和定时更新的方法
2018/05/07 Python
python正向最大匹配分词和逆向最大匹配分词的实例
2018/11/14 Python
原生python实现knn分类算法
2019/10/24 Python
利用python实现冒泡排序算法实例代码
2019/12/01 Python
如何用OpenCV -python3实现视频物体追踪
2019/12/04 Python
Python栈的实现方法示例【列表、单链表】
2020/02/22 Python
深入浅析pycharm中 Make available to all projects的含义
2020/09/15 Python
Prometheus开发中间件Exporter过程详解
2020/11/30 Python
一款利用纯css3实现的360度翻转按钮的实例教程
2014/11/05 HTML / CSS
京东港澳售:京东直邮港澳台
2018/01/31 全球购物
Boom手表官网:瑞典手表品牌,设计你的手表
2019/03/11 全球购物
英国手机壳购买网站:Case Hut
2019/04/11 全球购物
食堂采购员岗位职责
2014/03/17 职场文书
导师鉴定意见
2015/06/05 职场文书
妈妈别哭观后感
2015/06/08 职场文书
python 机器学习的标准化、归一化、正则化、离散化和白化
2021/04/16 Python
SpringBoot 集成Redis 过程
2021/06/02 Redis
MySQL 十大常用字符串函数详解
2021/06/30 MySQL
Python如何使用循环结构和分支结构
2022/04/13 Python