nodejs 开发企业微信第三方应用简明教程

最近公司要开发企业微信端的 worktile,以前做的是企业微信内部应用,由于开发的是企业内部应用,所有只适用于私有部署客户,对于公有云客户就无法使用,所有就准备开发企业微信的第三方应用,本文主要介绍在调研阶段遇到的山珍海味。

开发之前你需要前注册为第三方服务商,然后用第三方服务商的账号创建应用,创建之后只需要管理员授权应用,第三方服务商即可为用户提供服务。这里我们主要研究第三方服务商注册应用。

注册第三发服务商

登陆服务商官网,注册成为服务商,并登陆服务商管理后台。

配置开发信息

1、在创建应用之前,首先要配置好通用开发参数

在填写系统事件接收 url 时,要正确响应企业微信验证 url 的请求。这个可以参考企业微信后台,自建应用的接收消息API

在企业的管理端后台,进入需要设置接收消息的目标应用,点击“接收消息”的“设置API接收”按钮,进入配置页面。

 要求填写应用的 URL、Token、EncodingAESKey 三个参数,这三个参数的用处在加解密方案说明

  • URL 是企业后台接收企业微信推送请求的访问协议和地址,支持 http 或 https 协议(为了提高安全性,建议使用 https)。
  • Token 可由企业任意填写,用于生成签名。
  • EncodingAESKey 用于消息体的加密,是 AES 密钥的 Base64 编码。

验证 URL 有效性

当点击保存的时候,企业微信会发生一条 get 请求到填写的 url

扫描二维码关注公众号,回复: 5421551 查看本文章

比如 url 设置的是https://api.worktile.com, 企业微信将发送如下验证请求:

请求地址:https://api.worktile.com/?msg_signature=ASDFQWEXZCVAQFASDFASDFSS×tamp=13500001234&nonce=123412323&echostr=ENCRYPT_STR

参数 说明
msg_signature 企业微信加密签名,msg_signature 结合了企业填写的 token、请求中的 timestamp、nonce 参数、加密的消息体
timestamp 时间戳
nonce 随机数
echostr 加密的字符串。需要解密得到消息内容明文,解密后有random、msg_len、msg、receiveid 四个字段,其中 msg 即为消息内容明文

企业后台收到请求后,需要做如下操作:

  1. 对收到的请求做Urldecode处理
  2. 通过参数msg_signature对请求进行校验,确认调用者的合法性。
  3. 解密echostr参数得到消息内容(即msg字段)
  4. 1秒内响应GET请求,响应内容为上一步得到的明文消息内容(不能加引号,不能带bom头,不能带换行符)

通过参数 msg_signature 对请求进行校验

首先要把刚才配置时随机生成的 token, timestamp, nonce, msg_encrypt 进行 sha1 加密,这里我们可以直接使用 npm 模块 sha1 进行加密,然后判断得到的 str 是否和 msg_signature 相等。

npm i sha1 --save
const sha1 = require('sha1');
const query = req.query;
const signature = query.msg_signature;
const timestamp = query.timestamp;
const nonce = query.nonce;
const echostr = query.echostr;
const tmpArr = [token, timestamp, nonce, echostr];
const tmpStr = sha1(tmpArr.sort().join(''));
if (tmpStr === signature) {
  console.log('Check Success');
} else {
  console.log('Check Failed');
}

解密 echostr 得到 消息明文msg 并返回 

密文解密过程:

  1. 对刚才生成的 AESKey 进行 base64 解码
    1. const EncodingAESKey = '21IpFqj8qolJbaqPqe1rVTAK5sgkaQ3GQmUKiUQLwRe';
      let aesKey = Buffer.from(EncodingAESKey + '=', 'base64');
  2. 对 AESKey 进行 aes-256-cbc 解密
    1. // 去掉 decipheredBuff 头部的16个随机字节和4个字节的 msg_len,截取 msg_len 长度的部分即为msg,剩下的为尾部的 receiveid
      const crypto = require('crypto');
      let aesCipher = crypto.createDecipheriv("aes-256-cbc", aesKey, aesKey.slice(0, 16));
      
  3. 去掉补全的明文的头部的16个随机字节和4个字节的msg_len,截取msg_len长度的部分即为msg,并返回msg进行验证比对
    1. aesCipher.setAutoPadding(false); 
      let decipheredBuff = Buffer.concat([aesCipher.update(data, 'base64'), aesCipher.final()]); 
      decipheredBuff = PKCS7Decoder(decipheredBuff); // 微信要求用 pkcs7进行补全
      const len_netOrder_corpid = decipheredBuff.slice(16);
      const msg_len = len_netOrder_corpid.slice(0, 4).readUInt32BE(0);
      const msg = len_netOrder_corpid.slice(4, msg_len + 4).toString();
      function PKCS7Decoder (buff) {
        var pad = buff[buff.length - 1];
        if (pad < 1 || pad > 32) {
          pad = 0;
        }
        return buff.slice(0, buff.length - pad);
      }

回调url验证失败问题

验证URL时,经常会碰到URL验证失败的问题,解决思路是借助微信企业号接口调试工具: http://qydev.weixin.qq.com/debug,

具体各种坑详见:URL校验失败的终极解决方法

使用说明:

  • 选择合适的接口。
  • 系统会生成该接口的参数表,您可以直接在文本框内填入对应的参数值。(红色星号表示该字段必填)
  • 点击检查问题按钮,即可得到相应的调试信息。

验证URL对应的接口类型为 "建立连接",接口列表选择"测试回调模式"

2、设置白名单

在后台主页->服务商信息->基本信息->IP白名单->点击修改按钮,添加白名单IP列表 

参数内容 说明
白名单IP列表 服务商调用企业微信API时的合法IP列表,只有白名单内的IP才能正常调用企业微信API,修改后立即生效。支持“222.209.201.*” 这样用通配符表示IP段;多个IP以英文分号;分隔

创建应用

创建完成之后,在“本地应用”栏可以看到该应用,点击进入此应用,可以看到应用的SuiteId和SuiteSecret等信息,这些信息可用于调用第三方应用接口.

测试应用

应用创建成功后,服务商可以授权 10 个测试企业

从企业微信应用市场发起授权时,企业微信给刚才应用设置的指令回调 url 发送一个 post 请求,比如:
https://api.worktile.com/worktile?msg_signature=b99605616153ffbfbe6ebbb500bd211e67ed714d&timestamp=1551076894&nonce=1551709703,直接返回成功即可。

app.post('/worktile', function (req, res) {
  console.log('req.body', req.body);
  res.send('success');
});

测试应用安装成功之后,就可以通过企业微信——工作台中测试应用

应用上线

已认证企业微信的服务商,可进入应用管理—点击提交上线—勾选应用—提交上线。

注意事项

  • 本文更新于 2019 年 2 月 25 日,api 可能有时效性,如有差异,以 官方 api 为准。
  • worktile 正在开发测试 企业微信、钉钉、h5 端,上线之后欢迎使用。
  • 完整 demo

猜你喜欢

转载自blog.csdn.net/weboof/article/details/87969858