为什么使用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 日期比较相关天数代码
Apr 02 Javascript
JavaScript中实现PHP的打乱数组函数shuffle实例
Oct 11 Javascript
jquery中EasyUI实现异步树
Mar 01 Javascript
利用CSS3在Angular中实现动画
Jan 15 Javascript
举例讲解jQuery中可见性过滤选择器的使用
Apr 18 Javascript
浅谈JavaScript 中有关时间对象的方法
Aug 15 Javascript
jQuery EasyUI Tab 选项卡问题小结
Aug 16 Javascript
JS实现浏览器打印、打印预览示例
Feb 28 Javascript
移动端手指放大缩小插件与js源码
May 22 Javascript
vue将data恢复到初始状态 && 重新渲染组件实例
Sep 04 Javascript
javascript实现京东快递单号的查询效果
Nov 30 Javascript
React-vscode使用jsx语法的问题及解决方法
Jun 21 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全局变量和类配合使用深刻理解
2013/06/05 PHP
php jsonp单引号转义
2014/11/23 PHP
javascript 24小时弹出一次的代码(利用cookies)
2009/09/03 Javascript
javascript 特性检测并非浏览器检测
2010/01/15 Javascript
用Javascript评估用户输入密码的强度(Knockout版)
2011/11/30 Javascript
Jquery 自定义动画概述及示例
2013/03/29 Javascript
jquery ajax jsonp跨域调用实例代码
2013/12/11 Javascript
input链接页面、打开新网页等等的具体实现
2013/12/30 Javascript
js实现类似新浪微博首页内容渐显效果的方法
2015/04/10 Javascript
jquery实现界面无刷新加载登陆注册
2016/07/30 Javascript
详解Vue.js 2.0 如何使用axios
2017/04/21 Javascript
slideToggle+slideup实现手机端折叠菜单效果
2017/05/25 Javascript
使用Dropzone.js上传的示例代码
2017/10/10 Javascript
详解@Vue/Cli 3 Invalid Host header 错误解决办法
2019/01/02 Javascript
Vue.set 全局操作简单示例
2019/09/19 Javascript
[41:20]2014 DOTA2华西杯精英邀请赛 5 24 NewBee VS DK
2014/05/26 DOTA
[00:58]2016年国际邀请赛勇士令状宣传片
2016/06/01 DOTA
[10:34]DOTA2上海特级锦标赛全纪录
2016/03/25 DOTA
Python和Ruby中each循环引用变量问题(一个隐秘BUG?)
2014/06/04 Python
Python使用bs4获取58同城城市分类的方法
2015/07/08 Python
Python+Turtle动态绘制一棵树实例分享
2018/01/16 Python
centos6.8安装python3.7无法import _ssl的解决方法
2018/09/17 Python
深入解析Python小白学习【操作列表】
2019/03/23 Python
如何解决tensorflow恢复模型的特定值时出错
2020/02/06 Python
Python如何把Spark数据写入ElasticSearch
2020/04/18 Python
Pytorch生成随机数Tensor的方法汇总
2020/09/09 Python
HTML5中的拖放实现详解
2017/08/23 HTML / CSS
鞋子女王塔玛拉·梅隆同名奢侈品牌:Tamara Mellon
2017/11/22 全球购物
eDreams葡萄牙:全球最大的在线旅行社之一
2019/04/15 全球购物
Stio官网:男女、儿童户外服装
2019/12/13 全球购物
校运会口号
2014/06/18 职场文书
廉政教育的心得体会
2014/09/01 职场文书
2014年六五普法工作总结
2014/11/25 职场文书
新兵入伍决心书
2015/09/22 职场文书
职场新人刚入职工作总结该怎么写?
2019/05/15 职场文书
Java 常见的限流算法详细分析并实现
2022/04/07 Java/Android