准备
- sunny-ngrok工具安装及注册账号(国内建的私服)
- 什么叫做内网穿透
- 内网下可以调别人,别人连接自己是不行的,因为没有公网ip,所以需要公网ip地址
- 什么叫做内网穿透
- 模拟公网IP端口方法
- 申请一台阿里云ECS
- 公司网络有一个公网IP 路由器端口映射
- ngrok 内网穿透 国际版本(二级域名,每次启动都不一样)
客服消息
开发者工具 -> 公众平台测试账号 ,微信认证 验证成功,就会继续往下走。
-
我们验证微信,认证很重要 ,再有签名算法也是这样完成的,SHA1加密()
- hash算法不可逆
- 消息摘要,雪崩效应
- 防止第三方劫持盗取服务器信息
- 防止资源被诱导走,或者发送不健康的请求
const url = require('url') //引入url包 const { query } = url.parse(ctx.url, true) const { signature, // 微信加密签名,signature结合了开发者填写的token参数和请求中的 timestamp参数、nonce参数。 timestamp, // 时间戳 nonce, // 随机数 echostr // 随机字符串 } = query // 将 token timestamp nonce 三个参数进行字典序排序并用sha1加密 对比签名 加密规则是已知的 let str = [conf.token, timestamp, nonce].sort().join(''); let strSha1 = crypto.createHash('sha1').update(str).digest('hex'); console.log(`自己加密后的字符串为:${strSha1}`); console.log(`微信传入的加密字符串为:${signature}`); console.log(`两者比较结果为:${signature == strSha1}`); -
设置一个密钥,是以某种方式设置到服务器端,让双方知晓,对方发请求时会给发一次签名,签名算法是公开,但是对方知道是利用密钥产生的,加密密文是随机数。验证对方是否拥有token,只有拥有token才可以产生签名。再次签名,如果签名正确,则判断是token的使用者并且是合法用户。(很多地方会用到这种设计)
-
微信请求(源码接收部分)
- 接收时 (报文body xml格式)
- 发送要发送 xml
- const xml2js = require('xml2js') xml和json两者转换
const { xml: msg // 接收xml } = ctx.request.body const builder = new xml2js.Builder() const result = builder.buildObject({ xml: { // 返回xml ToUserName: msg.FromUserName, FromUserName: msg.ToUserName, CreateTime: Date.now(), MsgType: msg.MsgType, Content: 'Hello ' + msg.Content } })
服务端API调用 (菜单的工作变成程序的实现)
- 不需要ngroke,调用服务器接口不要
- 不是restful接口,微信官方定义风格,链接最后是get
- 获取的用户id,叫opneId,保证在同一个公众号统一的,在不同的不一样,要想保证一样,要注册,会有unionid,unionid可以保证在多个公众号一致。
- 第一步要 获取access_token 才可以使用其他API
https请求方式: GET https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET - AOP切面编程 intercpter,拦截器
- 微信公共平台API
const WechatAPI = require('co-wechat-api'); const api = new WechatAPI(conf.appid, conf.appsecret) // 创建实例 //微信API所有方法都有封装 api.getFollowers();- co-wechat-api
1. promise风格 2. mixin方法,内部自己写了个mixin方法 const API = require('./lib/api_common'); // 菜单接口 API.mixin(require('./lib/api_menu')); /** * 用于支持对象合并。将对象合并到API.prototype上,使得能够支持扩展 * Examples: * ``` * // 媒体管理(上传、下载) * API.mixin(require('./lib/api_media')); * ``` * @param {Object} obj 要合并的对象 */ API.mixin = function (obj) { for (var key in obj) { if (API.prototype.hasOwnProperty(key)) { throw new Error('Don\'t allow override existed prototype method. method: '+ key); } API.prototype[key] = obj[key]; } }; - token要放起来,mongodb或者redias(key-value存储系统)里面
const { ServerToken} = require('./mongoose') const api = new WechatAPI( conf.appid, conf.appsecret, async function () { // 取token return await ServerToken.findOne() }, async function (token) { // 存token const res = await ServerToken.updateOne({}, token, { upsert: true }) } ); - 标准restful接口,github,es
- graphql格式
- 测试驱动开发(TDD Test Driver Development)
- 官方文
- npm库
- co-wechat-api文档
- co-wechat-api源码地址