为什么使用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 相关文章推荐
javascript之AJAX框架使用说明
Apr 24 Javascript
两种简单实现菜单高亮显示的JS类代码
Jun 27 Javascript
TreeView 用法(有代码)(asp.net)
Jul 15 Javascript
jquery获取table中的某行全部td的内容方法
Mar 08 Javascript
遮罩层点击按钮弹出并且具有拖动和关闭效果(两种方法)
Aug 20 Javascript
jQuery代码实现表格中点击相应行变色功能
May 09 Javascript
jQuery animate easing使用方法图文详解
Jun 17 Javascript
jQuery删除当前节点元素
Dec 07 Javascript
JavaScript中数组Array方法详解
Feb 27 Javascript
JS秒杀倒计时功能完整实例【使用jQuery3.1.1】
Sep 03 jQuery
浅谈微信小程序列表埋点曝光指南
Oct 15 Javascript
Vue Element UI自定义描述列表组件
May 18 Vue.js
详解基于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调用Java对象的方法
2006/10/09 PHP
PHP5 面向对象程序设计
2008/02/13 PHP
php空间不支持socket但支持curl时recaptcha的用法
2011/11/07 PHP
php使用str_shuffle()函数生成随机字符串的方法分析
2017/02/17 PHP
php 静态属性和静态方法区别详解
2017/04/09 PHP
基于swoole实现多人聊天室
2018/06/14 PHP
js获取当前日期代码适用于网页头部
2013/06/27 Javascript
使用node.js 制作网站前台后台
2014/11/13 Javascript
高性能JavaScript 重排与重绘(2)
2015/08/11 Javascript
在javascript中随机数 math random如何生成指定范围数值的随机数
2015/10/21 Javascript
JavaScript使用DeviceOne开发实战(二) 生成调试安装包
2015/12/01 Javascript
JS Array.slice 截取数组的实现方法
2016/01/02 Javascript
JQuery遍历元素的父辈和祖先的方法
2016/09/18 Javascript
jQuery内容筛选选择器实例代码
2017/02/06 Javascript
浅谈angularJS的$watch失效问题的解决方案
2017/08/11 Javascript
基于angular-utils-ui-breadcrumbs使用心得(分享)
2017/11/03 Javascript
JavaScript实现百度搜索框效果
2020/03/26 Javascript
详解vue的diff算法原理
2018/05/20 Javascript
解决element-ui中下拉菜单子选项click事件不触发的问题
2018/08/22 Javascript
js构造函数constructor和原型prototype原理与用法实例分析
2020/03/02 Javascript
浅谈js中的attributes和Attribute的用法与区别
2020/07/16 Javascript
关于element-ui表单中限制输入纯数字的解决方式
2020/09/08 Javascript
[01:06]欢迎来到上海,TI9
2018/08/26 DOTA
Python中内置的日志模块logging用法详解
2016/07/12 Python
解决Pycharm运行时找不到文件的问题
2018/10/29 Python
selenium在执行phantomjs的API并获取执行结果的方法
2018/12/17 Python
Python对ElasticSearch获取数据及操作
2019/04/24 Python
英国网上超市:Ocado
2020/03/05 全球购物
简历中个人自我评价范文
2013/12/26 职场文书
社会保险接收函
2014/01/12 职场文书
活动总结报告格式
2014/05/09 职场文书
文明家庭先进事迹材料
2014/05/14 职场文书
团队队名口号大全
2014/06/06 职场文书
2015年大学迎新工作总结
2015/07/16 职场文书
制定企业培训计划的五大要点!
2019/07/10 职场文书
jQuery ajax - getScript() 方法和getJSON方法
2021/05/14 jQuery