为什么使用koa2搭建微信第三方公众平台的原因


Posted in Javascript onMay 16, 2018

在写之前我想先说说koa,koa相比express,在执行流程,以及组件方面优秀的多,koa本身没有提供过多的扩展组建,但是它便捷的组建扩展,可以让你自由的发挥,可以想写其他语言一样并行执行代码,如果说promise解放了繁琐的callback,那么 koa 编写 web 应用,通过组合不同的 generator,可以免除重复繁琐的回调函数嵌套,并极大地提升错误处理的效率。koa 不在内核方法中绑定任何中间件,它仅仅提供了一个轻量优雅的函数库,使得编写 Web 应用变得得心应手,nodejs的天生的异步处理流程,使得它很适合微信公众号这种频繁的消息互动,再加上pm2的多进程管理,可以说已经很大程度的满足大号的消息转发互动已经公众号内部红包玩法。

在使用koa2搭建微信第三方公众平台是,首先要解决的是如果获取微信返回的xml流,以及如何返回对应的XML体给微信。
由于本身koa不是一个框架,所以得益于网上众多的中间件,自己搭建了一个类似于express的框架,本框架已经开源,详情请看我的git地址:https://github.com/yxz1025/koa-lana,所有的微信接发消息均在此框架中,请读者自行下载!

好了,首先,我们看看如何获取微信返回的xml流:

======tool.js=====
//截获微信返回的xml流文件
const Promise = require('bluebird');
//普通post流转化为promise
var Tool = {
  convertPost: function(req) {
    let post_data = "";
    return new Promise(function(resolve, reject){
      req.on('data', function(chunk) {
        post_data += chunk;
      });

      req.on('end', function() {
        resolve(post_data);
      });
    });

  },
};
module.exports = Tool;

=====weichat.js======
//微信响应主体文件
const router = require('koa-router')();
const parseMessage = require('../common/parseMessage');
const config = require('../config');
const WXBizMsgCrypt = require('wechat-crypto');
const middleware = require('../model/middleware');
const validator = require('validator');
const Aes = require('../common/aes');
const Tool = require('../common/tool');
const cryptor = new WXBizMsgCrypt(config.component_config.token, config.component_config.key, config.component_config.component_appid);

//第三方授权路径 /:appid/callback  /wechat/100234/callback
router.post('/:appid/callback', async function(ctx, next) {
  let post_data = "";
  let req = ctx.req;
  post_data = await Tool.convertPost(req);
  let xml = parseMessage(post_data);
  let signature = cryptor.getSignature(ctx.query.timestamp, ctx.query.nonce, xml.encrypt);
  if (ctx.query.msg_signature != signature) {
    ctx.body = 'Auth failed!'; // 指纹码不匹配时返回错误信息,禁止后面的消息接受及发送
  }
  let message = middleware.decryptXml(xml);
  let appid = ctx.params.appid;
  message.appId = appid;
  //发送消息队列
  switch (message.msgType) {
    case 'text':
      //测试
      if (message.toUserName == "gh_3c884a361561") {
        if (message.content == "TESTCOMPONENT_MSG_TYPE_TEXT") {
          let text = middleware.text(message, message.content + "_callback");
          let reply = middleware.encryptXml(text);
          return ctx.body = reply;
        }
        let content = message.content;
        if (content.indexOf("QUERY_AUTH_CODE") != -1) {
          ctx.body = "";
          let code_li = content.split(":");
          await middleware.customSend(message.fromUserName, code_li[1]);
          return;
        }
      }
      let keywords = validator.trim(message.content).toLowerCase();
      let member_config = await middleware.getMemberConfig(message.toUserName, keywords);
      if (!member_config) {
        await middleware.sendMnsQuene(message);
        return ctx.body = "success";
      }else{
         //匹配成功
        message.packetsId = parseInt(member_config.hongbaoId);
        message.keywords = keywords;
        await middleware.sendMnsQuene(message);

        let data = {
          title: member_config.news_title || '点我领红包',
          description: member_config.description || '第一轮红包雨开始了,手快有,手慢无!',
          picurl: member_config.picurl || 'http://7xqomp.com2.z0.glb.qiniucdn.com/17269743.png'
        };
        let key = {
          fromUserName: message.fromUserName,
          toUserName: message.toUserName,
          keywords: keywords,
          appId: appid
        };
        key = JSON.stringify(key);
        key = Aes.encypt(key);
        key = Aes.base64_encode(key);

        //获取授权域名
        let auth_url = await middleware.packetDomain();
        data.url = "http://" + appid + "." + auth_url + "/redPackets/koulin?key=" + key;
        let news = middleware.news(message, [data]);
        let reply = middleware.encryptXml(news);
        ctx.body = reply; 
        return;       
      }
      break;
    case 'event':
      await middleware.sendMnsQuene(message);
      //测试专用
      if (message.toUserName == "gh_3c884a361561") {
        let text = middleware.text(message, message.event + "from_callback");
        let reply = middleware.encryptXml(text);
        ctx.body = reply;
        return;
      }
      break;
    default:
      await middleware.sendMnsQuene(message);
      ctx.body = "success";
      return;

  };
});
module.exports = router;

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

Javascript 相关文章推荐
IE8 原生JSON支持
Apr 13 Javascript
js弹出窗口之弹出层的小例子
Jun 17 Javascript
基于jquery实现最简单的选项卡切换效果
May 08 Javascript
第一次动手实现bootstrap table分页效果
Sep 22 Javascript
纯js实现手风琴效果代码
Apr 17 Javascript
jQuery树控件zTree使用方法详解(一)
Feb 28 Javascript
Vue原理剖析 实现双向绑定MVVM
May 03 Javascript
Bootstrap弹出框之自定义悬停框标题、内容和样式示例代码
Jul 11 Javascript
浅谈webpack打包生成的bundle.js文件过大的问题
Feb 22 Javascript
JS的Ajax与后端交互数据的实例
Aug 08 Javascript
javascript数组的定义及操作实例
Nov 10 Javascript
Openlayers测量距离与面积的实现方法
Sep 25 Javascript
详解基于Koa2开发微信二维码扫码支付相关流程
May 16 #Javascript
AngularJS标签页tab选项卡切换功能经典实例详解
May 16 #Javascript
解决Mac node版本升级失败的问题
May 16 #Javascript
在Mac下彻底卸载node和npm的方法
May 16 #Javascript
完美解决linux下node.js全局模块找不到的情况
May 16 #Javascript
AngularJS中的作用域实例分析
May 16 #Javascript
element-ui 限制日期选择的方法(datepicker)
May 16 #Javascript
You might like
PHP中array_map与array_column之间的关系分析
2014/08/19 PHP
php字符串按照单词进行反转的方法
2015/03/14 PHP
CodeIgniter读写分离实现方法详解
2016/01/20 PHP
浅谈PHP接入(第三方登录)QQ登录 OAuth2.0 过程中遇到的坑
2017/10/13 PHP
Laravel框架实现利用中间件进行操作日志记录功能
2018/06/06 PHP
laravel中数据显示方法(默认值和下拉option默认选中)
2019/10/11 PHP
PHP执行系统命令函数实例讲解
2021/03/03 PHP
jquery限制输入字数,并提示剩余字数实现代码
2012/12/24 Javascript
jQuery使用append在html元素后同时添加多项内容的方法
2015/03/26 Javascript
javascript实现画不相交的圆
2015/04/07 Javascript
jquery+html5制作超酷的圆盘时钟表
2015/04/14 Javascript
JS判断当前页面是否在微信浏览器打开的方法
2015/12/08 Javascript
在Docker快速部署Node.js应用的详细步骤
2016/09/02 Javascript
简单谈谈ES6的六个小特性
2016/11/18 Javascript
详解jQuery简单的表格应用
2016/12/16 Javascript
VueRouter导航守卫用法详解
2017/12/25 Javascript
JavaScript设计模式之单例模式原理与用法实例分析
2018/07/26 Javascript
vue-quill-editor+plupload富文本编辑器实例详解
2018/10/19 Javascript
用vscode开发vue应用的方法步骤
2019/05/06 Javascript
JS中实现浅拷贝和深拷贝的代码详解
2019/06/05 Javascript
[01:03:54]Liquid vs IG 2018国际邀请赛小组赛BO2 第一场 8.17
2018/08/18 DOTA
[37:45]完美世界DOTA2联赛PWL S3 LBZS vs Phoenix 第二场 12.09
2020/12/11 DOTA
python二分法实现实例
2013/11/21 Python
python实现多线程采集的2个代码例子
2014/07/07 Python
深入浅出分析Python装饰器用法
2017/07/28 Python
pycharm远程调试openstack的图文教程
2017/11/21 Python
Python实现简单的文本相似度分析操作详解
2018/06/16 Python
python3读取excel文件只提取某些行某些列的值方法
2018/07/10 Python
浅析python中numpy包中的argsort函数的使用
2018/08/30 Python
对python requests的content和text方法的区别详解
2018/10/11 Python
使用python实现http及ftp服务进行数据传输的方法
2018/10/26 Python
python实现键盘输入的实操方法
2019/07/16 Python
意大利运动服减价商店:ScontoSport
2020/03/10 全球购物
大学三年计划书范文
2014/04/30 职场文书
大学生入党积极分子党校学习思想汇报
2014/10/25 职场文书
Nginx+Windows搭建域名访问环境的操作方法
2022/03/17 Servers