为什么使用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 三种不同位置代码的写法
Oct 25 Javascript
js数据验证集合、js email验证、js url验证、js长度验证、js数字验证等简单封装
May 15 Javascript
jquery插件制作 表单验证实现代码
Aug 17 Javascript
input禁止键盘及中文输入,但可以点击
Feb 13 Javascript
AngularJS 过滤与排序详解及实例代码
Sep 14 Javascript
BootStrapTable 单选及取值的实现方法
Jan 10 Javascript
深入理解node.js http模块
Jan 24 Javascript
详解vuex状态管理模式
Nov 01 Javascript
详解vue 兼容IE报错解决方案
Dec 29 Javascript
JavaScript和TypeScript中的void的具体使用
Sep 12 Javascript
sharp.js安装过程中遇到的问题总结
Apr 02 Javascript
vue v-for出来的列表,点击某个li使得当前被点击的li字体变红操作
Jul 17 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
星际争霸秘籍
2020/03/04 星际争霸
基于递归实现的php树形菜单代码
2014/11/19 PHP
PHP设计模式之装饰器模式定义与用法详解
2018/04/02 PHP
微信JSSDK分享功能图文实例详解
2019/04/08 PHP
巧妙破除网页右键禁用的十大绝招
2006/08/12 Javascript
Html中JS脚本执行顺序简单举例说明
2010/06/19 Javascript
jquery操作checked属性以及disabled属性的多种方法
2014/06/20 Javascript
纯javascript实现四方向文本无缝滚动效果
2015/06/16 Javascript
聊一聊Vue.js过渡效果
2016/09/07 Javascript
ros::spin() 和 ros::spinOnce()函数的区别及详解
2016/10/01 Javascript
jQuery ajax MD5实现用户注册即时验证功能
2016/10/11 Javascript
String字符串截取的四种方式总结
2016/11/28 Javascript
three.js 入门案例详解
2018/01/23 Javascript
select2 ajax 设置默认值,初始值的方法
2018/08/09 Javascript
jQuery+CSS实现的标签页效果示例【测试可用】
2018/08/14 jQuery
如何在vue里面优雅的解决跨域(路由冲突问题)
2019/01/20 Javascript
layer.confirm()右边按钮实现href的例子
2019/09/27 Javascript
javascript中闭包closure的深入讲解
2021/03/03 Javascript
python使用正则表达式检测密码强度源码分享
2014/06/11 Python
常见的python正则用法实例讲解
2016/06/21 Python
python中yaml配置文件模块的使用详解
2018/04/27 Python
python安装requests库的实例代码
2019/06/25 Python
python程序中的线程操作 concurrent模块使用详解
2019/09/23 Python
python函数map()和partial()的知识点总结
2020/05/26 Python
python实现经典排序算法的示例代码
2021/02/07 Python
英国网上香水店:Fragrance Direct
2016/07/20 全球购物
精油和天然健康美容产品:Art Naturals
2018/01/27 全球购物
国际性能运动服装品牌:Dare 2b
2018/07/27 全球购物
Ooni英国官网:披萨烤箱
2020/05/31 全球购物
电子商务专业求职信
2014/03/08 职场文书
节约用水演讲稿
2014/05/21 职场文书
志愿者宣传口号
2014/06/17 职场文书
乡镇党的群众路线教育实践活动制度建设计划
2014/11/03 职场文书
2019邀请函格式及范文
2019/05/20 职场文书
大学生创业计划书
2019/06/24 职场文书
Golang全局变量加锁的问题解决
2021/05/08 Golang