为什么使用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之锁定表格栏位
Jun 29 Javascript
jquery 新建的元素事件绑定问题解决方案
Jun 12 Javascript
Blocksit插件实现瀑布流数据无限( 异步)加载
Jun 20 Javascript
jquery解决客户端跨域访问问题
Jan 06 Javascript
Js与Jq 获取页面元素值的方法和差异对比
Apr 30 Javascript
js 判断一组日期是否是连续的简单实例
Jul 11 Javascript
JavaScript实现前端实时搜索功能
Mar 26 Javascript
详解Angular 4.x Injector
May 04 Javascript
基于vue-cli配置lib-flexible + rem实现移动端自适应
Dec 26 Javascript
浅谈实现vue2.0响应式的基本思路
Feb 13 Javascript
vue 组件高级用法实例详解
Apr 11 Javascript
原生js实现表格翻页和跳转
Sep 29 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处理大量表单字段的便捷方法
2015/02/07 PHP
PHP消息队列用法实例分析
2016/02/12 PHP
php mysql_real_escape_string addslashes及mysql绑定参数防SQL注入攻击
2016/12/23 PHP
使用jQuery validate 验证注册表单实例演示
2013/03/25 Javascript
js 程序执行与顺序实现详解
2013/05/13 Javascript
jQuery实现鼠标经过图片预览大图效果
2014/04/10 Javascript
js实现弹出窗口、页面变成灰色并不可操作的例子分享
2014/05/10 Javascript
现代 JavaScript 开发编程风格Idiomatic.js指南中文版
2014/05/28 Javascript
HTML5+jQuery插件Quicksand实现超酷的星际争霸2兵种分类展示效果(附demo源码下载)
2016/05/25 Javascript
JS数组返回去重后数据的方法解析
2017/01/03 Javascript
Vue如何实现组件的源码解析
2017/06/08 Javascript
纯JS实现只能输入数字的简单代码
2017/06/21 Javascript
原生JS实现动态加载js文件并在加载成功后执行回调函数的方法
2020/12/30 Javascript
zepto.js 实时监听输入框的方法
2018/12/04 Javascript
JS/HTML5游戏常用算法之碰撞检测 包围盒检测算法详解【圆形情况】
2018/12/13 Javascript
在Vue中用canvas实现二维码和图片合成海报的方法
2019/06/10 Javascript
JavaScript Window窗口对象属性和使用方法
2020/01/19 Javascript
vue结合el-upload实现腾讯云视频上传功能
2020/07/01 Javascript
Vue2.0 $set()的正确使用详解
2020/07/28 Javascript
[50:34]VGJ.T vs Fnatic 2018国际邀请赛小组赛BO2 第二场 8.16
2018/08/17 DOTA
python下载文件时显示下载进度的方法
2015/04/02 Python
Python中的is和==比较两个对象的两种方法
2017/09/06 Python
Python解决N阶台阶走法问题的方法分析
2017/12/28 Python
Python实现的圆形绘制(画圆)示例
2018/01/31 Python
python自动发送邮件脚本
2018/06/20 Python
你还在@微信官方?聊聊Python生成你想要的微信头像
2019/09/25 Python
python修改linux中文件(文件夹)的权限属性操作
2020/03/05 Python
详解pycharm的python包opencv(cv2)无代码提示问题的解决
2021/01/29 Python
如何用Python编写一个电子考勤系统
2021/02/08 Python
Canvas 文本转粒子效果的实现代码
2019/02/14 HTML / CSS
MADE荷兰:提供原创设计师家具
2018/04/03 全球购物
匈牙利最大的健身制造商和销售商:inSPORTline
2018/10/30 全球购物
环境工程专业自荐信
2014/03/03 职场文书
法定代表人授权委托书格式
2014/10/14 职场文书
超市工作总结范文2014
2014/12/19 职场文书
Java GUI编程菜单组件实例详解
2022/04/07 Java/Android