为什么使用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 - HTML的request类
Jul 15 Javascript
jQuery UI Autocomplete 体验分享
Feb 14 Javascript
js鼠标滑过弹出层的定位IE6bug解决办法
Dec 26 Javascript
jquery 关于event.target使用的几点说明介绍
Apr 26 Javascript
JS是按值传递还是按引用传递
Jan 30 Javascript
jQuery实现简洁的导航菜单效果
Nov 23 Javascript
微信小程序 两种滑动方式(横向滑动,竖向滑动)详细及实例代码
Jan 13 Javascript
javascript+html5+css3自定义弹出窗口效果
Oct 26 Javascript
关于JavaScript语句后面的分号问题
Dec 07 Javascript
微信小程序把百度地图坐标转换成腾讯地图坐标过程详解
Jul 10 Javascript
深入理解基于vue-cli的webpack打包优化实践及探索
Oct 14 Javascript
vue中activated的用法
Jan 03 Vue.js
详解基于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 HTML代码串 截取实现代码
2009/06/29 PHP
修改apache配置文件去除thinkphp url中的index.php
2014/01/17 PHP
php实现微信公众平台账号自定义菜单类
2015/10/11 PHP
今天你说520了吗?不仅有php表白书还有java表白神器
2016/05/20 PHP
PHP里的$_GET数组介绍
2019/03/22 PHP
javascript 函数使用说明
2010/04/07 Javascript
jquery里的each使用方法详解
2010/12/22 Javascript
Javascript的getYear、getFullYear、getUTCFullYear异同分享
2011/11/30 Javascript
通过javascript获取iframe里的值示例代码
2013/06/24 Javascript
javascript日期对象格式化为字符串的实现方法
2014/01/14 Javascript
页面js遇到乱码问题的解决方法是和无法转码的情况
2014/04/30 Javascript
js+html5绘制图片到canvas的方法
2015/06/05 Javascript
分离与继承的思想实现图片上传后的预览功能:ImageUploadView
2016/04/07 Javascript
ionic实现底部分享功能
2017/05/11 Javascript
使用JavaScript根据图片获取条形码的方法
2017/07/04 Javascript
原生JS实现ajax与ajax的跨域请求实例
2017/12/01 Javascript
Vue导出json数据到Excel电子表格的示例
2017/12/04 Javascript
vscode下的vue文件格式化问题
2018/11/28 Javascript
node实现生成带参数的小程序二维码并保存到本地功能示例
2018/12/05 Javascript
详解key在Vue列表渲染时究竟起到了什么作用
2019/04/20 Javascript
vue+moment实现倒计时效果
2019/08/26 Javascript
three.js着色器材质的内置变量示例详解
2020/08/16 Javascript
详解Python验证码识别
2016/01/25 Python
selenium处理元素定位点击无效问题
2019/06/12 Python
关于PyTorch 自动求导机制详解
2019/08/18 Python
python 字符串常用方法汇总详解
2019/09/16 Python
Python3读写Excel文件(使用xlrd,xlsxwriter,openpyxl3种方式读写实例与优劣)
2020/02/13 Python
Python实现自动访问网页的例子
2020/02/21 Python
俄罗斯奢侈品牌衣服、鞋子和配饰的在线商店:INTERMODA
2020/07/17 全球购物
电子商务个人自荐信
2013/12/12 职场文书
全陪导游词
2015/02/04 职场文书
教师学习十八届五中全会精神心得体会
2016/01/05 职场文书
创业计划书之孕婴生活馆
2019/11/11 职场文书
CSS3实现的文字弹出特效
2021/04/16 HTML / CSS
Python re.sub 反向引用的实现
2021/07/07 Python