为什么使用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 相关文章推荐
js 与或运算符 || && 妙用
Dec 09 Javascript
jQuery使用动态渲染表单功能完成ajax文件下载
Jan 15 Javascript
jQuery函数的等价原生函数代码示例
May 27 Javascript
javascript实现简单的html5视频播放器
May 06 Javascript
理解JavaScript中worker事件api
Dec 25 Javascript
jQuery搜索框效果实现代码(百度关键词联想)
Feb 25 Javascript
关于JavaScript数组你所不知道的3件事
Aug 24 Javascript
Angular2表单自定义验证器的实现
Oct 19 Javascript
js中常用的Math方法总结
Jan 12 Javascript
web前端vue实现插值文本和输出原始html
Jan 19 Javascript
Vue监听事件实现计数点击依次增加的方法
Sep 26 Javascript
Vue + Scss 动态切换主题颜色实现换肤的示例代码
Apr 27 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
thinkphp3.2.2前后台公用类架构问题分析
2014/11/25 PHP
php mongodb操作类 带几个简单的例子
2016/08/25 PHP
PHP使用递归算法无限遍历数组示例
2017/01/13 PHP
PHP命名空间namespace的定义方法详解
2017/03/29 PHP
JavaScript开发时的五个注意事项
2007/12/08 Javascript
JavaScript入门教程(12) js对象化编程
2009/01/31 Javascript
javascript与asp.net(c#)互相调用方法
2009/12/13 Javascript
JS操作Cookie写入和读取实例代码
2013/10/20 Javascript
javascript中的取反再取反~~没有意义
2014/04/06 Javascript
js获取页面description的方法
2015/05/21 Javascript
日常收藏的jquery技巧
2015/12/02 Javascript
通用无限极下拉菜单的实现代码
2016/05/31 Javascript
Vue.js学习笔记之常用模板语法详解
2017/07/25 Javascript
vue.js分页中单击页码更换页面内容的方法(配合spring springmvc)
2018/02/10 Javascript
create-react-app构建项目慢的解决方法
2018/03/14 Javascript
Vue infinite update loop的问题解决
2019/04/23 Javascript
webpack3.0升级4.0的方法步骤
2020/04/02 Javascript
Vue性能优化的方法
2020/07/30 Javascript
关于小程序优化的一些建议(小结)
2020/12/10 Javascript
使用 Python 获取 Linux 系统信息的代码
2014/07/13 Python
python使用socket向客户端发送数据的方法
2015/04/29 Python
django实现分页的方法
2015/05/26 Python
tensorflow通过模型文件,使用tensorboard查看其模型图Graph方式
2020/01/23 Python
python爬虫筛选工作实例讲解
2020/11/23 Python
如何使用canvas绘制可移动网格的示例代码
2020/12/14 HTML / CSS
欧洲最大的拼图游戏商店:JigsawPuzzle.co.uk
2018/07/04 全球购物
聊城大学毕业生自荐书
2014/02/01 职场文书
倡议书格式范文
2014/04/14 职场文书
经典演讲稿开场白
2014/08/25 职场文书
关于工作经历的证明书
2014/10/11 职场文书
学子宴致辞大全
2015/07/27 职场文书
安全教育培训制度
2015/08/06 职场文书
班主任班级管理心得体会
2016/01/07 职场文书
话题作文之呼唤
2019/12/18 职场文书
世界无敌的ICOM IC-R9500宽频接收机
2022/03/25 无线电
微信小程序实现轮播图指示器
2022/06/25 Javascript