为什么使用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 相关文章推荐
学习ExtJS TextField常用方法
Oct 07 Javascript
js 上传图片预览问题
Dec 06 Javascript
javascript Event对象详解及使用示例
Nov 22 Javascript
jQuery控制TR显示隐藏的三种常用方法
Aug 21 Javascript
浅谈javascript 函数属性和方法
Jan 21 Javascript
jQuery实现当前页面标签高亮显示的方法
Mar 10 Javascript
jQuery中animate()的使用方法及解决$(”body“).animate({“scrollTop”:top})不被Firefox支持的问题
Apr 04 jQuery
微信小程序支付功能 php后台对接完整代码分享
Jun 12 Javascript
JS实现关键词高亮显示正则匹配
Jun 22 Javascript
解决vue单页路由跳转后scrollTop的问题
Sep 03 Javascript
详解Element 指令clickoutside源码分析
Feb 15 Javascript
Vue项目引发的「过滤器」使用教程
Mar 12 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
玩转虚拟域名◎+ .
2006/10/09 PHP
php 获取完整url地址
2008/12/20 PHP
PHP游戏编程25个脚本代码
2011/02/08 PHP
比较简单的百度网盘文件直链PHP代码
2013/03/24 PHP
PHP使用DES进行加密与解密的方法详解
2013/06/06 PHP
如何让CI框架支持service层
2014/10/29 PHP
PHP发送短信代码分享
2015/08/11 PHP
Zend Framework框架路由机制代码分析
2016/03/22 PHP
ThinkPHP like模糊查询,like多匹配查询,between查询,in查询,一般查询书写方法
2018/09/26 PHP
PHP实现微信退款功能
2018/10/02 PHP
各种常用的JS函数整理
2013/10/25 Javascript
javascript中的__defineGetter__和__defineSetter__介绍
2014/08/15 Javascript
JavaScript中实现异步编程模式的4种方法
2014/09/24 Javascript
JS DOM实现鼠标滑动图片效果
2020/09/17 Javascript
ionic实现带字的toggle滑动组件
2016/08/27 Javascript
js在ie下打开对话窗口的方法小结
2016/10/24 Javascript
bootstrap实现图片自动轮播
2016/12/21 Javascript
基于bootstrap风格的弹框插件
2016/12/28 Javascript
Bootstrap按钮组简单实现代码
2017/03/06 Javascript
微信小程序 开发之全局配置
2017/05/05 Javascript
jQuery序列化后的表单值转换成Json
2017/06/16 jQuery
js数组方法reduce经典用法代码分享
2018/01/07 Javascript
Python编程中time模块的一些关键用法解析
2016/01/19 Python
python对视频画框标记后保存的方法
2018/12/07 Python
pandas 数据索引与选取的实现方法
2019/06/21 Python
pygame实现俄罗斯方块游戏(基础篇2)
2019/10/29 Python
Python爬虫小例子——爬取51job发布的工作职位
2020/07/10 Python
Sofmap官网:日本著名的数码电器专卖店
2017/05/19 全球购物
现代生活方式的家具和装饰:Dot & Bo
2018/12/26 全球购物
璀璨的珍珠、密钉和个性化珠宝:Lily & Roo
2021/01/21 全球购物
安全责任书怎么写
2014/07/28 职场文书
单位单身证明样本
2014/10/11 职场文书
2014教师评职称工作总结
2014/11/10 职场文书
优秀护士事迹材料
2014/12/25 职场文书
婚礼新人答谢词
2015/01/04 职场文书
Redis全局ID生成器的实现
2022/06/05 Redis