为什么使用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 相关文章推荐
鼠标图片振动代码
Jul 06 Javascript
记录几个javascript有关的小细节
Apr 02 Javascript
jQuery Validation实例代码 让验证变得如此容易
Oct 18 Javascript
JavaScript中标识符提升问题
Jun 11 Javascript
Javascript之String对象详解
Jun 08 Javascript
老生常谈JavaScript中的this关键字
Oct 01 Javascript
canvas简单快速的实现知乎登录页背景效果
May 08 Javascript
微信JSAPI Ticket接口签名详解
Jun 28 Javascript
jQuery获取复选框选中的当前行的某个字段的值
Sep 15 jQuery
vue-cli2.9.3 详细教程
Apr 23 Javascript
原生JS实现$.param() 函数的方法
Aug 10 Javascript
vue实现类似淘宝商品评价页面星级评价及上传多张图片功能
Oct 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中的strtr函数使用介绍(str_replace)
2011/10/20 PHP
php操作xml入门之cdata区段
2015/01/23 PHP
php实现学生管理系统
2020/03/21 PHP
设定php简写功能的方法
2019/11/28 PHP
用javascript实现在小方框中浏览大图的代码
2007/08/14 Javascript
JavaScript OOP类与继承
2009/11/15 Javascript
javascript使用activex控件的代码
2011/01/27 Javascript
SyntaxHighlighter语法高亮插件使用说明
2011/08/14 Javascript
javascript三元运算符用法实例
2015/04/16 Javascript
javascript日期验证之输入日期大于等于当前日期
2015/12/13 Javascript
jQuery使用zTree插件实现树形菜单和异步加载
2016/02/25 Javascript
Bootstrap图片轮播组件使用实例解析
2016/06/30 Javascript
JS实现数字格式千分位相互转换方法
2016/08/01 Javascript
JS实现放大、缩小及拖拽图片的方法【可兼容IE、火狐】
2016/08/23 Javascript
JavaScript实现多叉树的递归遍历和非递归遍历算法操作示例
2018/02/08 Javascript
基于Bootstrap下拉框插件bootstrap-select使用方法详解
2018/08/07 Javascript
json前后端数据交互相关代码
2018/09/19 Javascript
js实现旋转的星空效果
2019/11/01 Javascript
Vue实现返回顶部按钮实例代码
2020/10/21 Javascript
在Python的Flask框架下收发电子邮件的教程
2015/04/21 Python
Python的函数的一些高阶特性
2015/04/27 Python
Python常用小技巧总结
2015/06/01 Python
Python3学习urllib的使用方法示例
2017/11/29 Python
Python机器学习算法之k均值聚类(k-means)
2018/02/23 Python
python实现windows下文件备份脚本
2018/05/27 Python
Python continue继续循环用法总结
2018/06/10 Python
Python3多线程基础知识点
2019/02/19 Python
下载与当前Chrome对应的chromedriver.exe(用于python+selenium)
2020/01/14 Python
了解一下python内建模块collections
2020/09/07 Python
CSS3制作ajax loader icon实现思路及代码
2013/08/25 HTML / CSS
详解CSS3的box-shadow属性制作边框阴影效果的方法
2016/05/10 HTML / CSS
蒙蒂塞罗商店:Monticello Shop
2018/11/25 全球购物
故宫导游词
2015/01/31 职场文书
基层组织建设年活动总结
2015/05/09 职场文书
python制作图形界面的2048游戏, 基于tkinter
2021/04/06 Python
画错魏国疆域啦!《派对咖孔明》动画因作画失误于官网致歉
2022/04/07 日漫