网络编程 
首页 > 网络编程 > 浏览文章

详解nodejs 开发企业微信第三方应用入门教程

(编辑:jimmy 日期: 2024/11/5 浏览:3 次 )

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

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

一、注册第三发服务商

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

二、配置开发信息

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

详解nodejs 开发企业微信第三方应用入门教程

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

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

详解nodejs 开发企业微信第三方应用入门教程

要求填写应用的 URL、Token、EncodingAESKey 三个参数

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

 2.1 验证 url 有效性

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

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

请求地址: https://api.worktile.com/"height: 149px; width: 663px"> 参数 说明 msg_signature 企业微信加密签名,msg_signature 结合了企业填写的 token、请求中的 timestamp、nonce 参数、加密的消息体 timestamp 时间戳 nonce 随机数 echostr 加密的字符串。需要解密得到消息内容明文,解密后有random、msg_len、msg、receiveid 四个字段,其中 msg 即为消息内容明文

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

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

function sha1(str) {
 const md5sum = crypto.createHash('sha1');
 md5sum.update(str);
 const ciphertext = md5sum.digest('hex');
 return ciphertext;
}
function checkSignature(req, res, encrypt) {
 const query = req.query;
 console.log('Request URL: ', req.url);
 const signature = query.msg_signature;
 const timestamp = query.timestamp;
 const nonce = query.nonce;
 let echostr;
 console.log('encrypt', encrypt);
 if (!encrypt) {
  echostr = query.echostr;
 } else {
  echostr = encrypt;
 }
 console.log('timestamp: ', timestamp);
 console.log('nonce: ', nonce);
 console.log('signature: ', signature);
 // 将 token/timestamp/nonce 三个参数进行字典序排序
 const tmpArr = [token, timestamp, nonce, echostr];
 const tmpStr = sha1(tmpArr.sort().join(''));
 console.log('Sha1 String: ', tmpStr);
 // 验证排序并加密后的字符串与 signature 是否相等
 if (tmpStr === signature) {
  // 原样返回echostr参数内容
  const result = _decode(echostr);
  console.log('last', result);
  console.log('Check Success');
  return result;
 } else {
  console.log('Check Failed');
  return 'failed';
 }
}

2.1.2 解密 echostr 得到 msg 并返回

密文解密过程:

对刚才生成的 AESKey 进行 base64 解码

const EncodingAESKey = '21IpFqj8qolJbaqPqe1rVTAK5sgkaQ3GQmUKiUQLwRe';
let aesKey = Buffer.from(EncodingAESKey + '=', 'base64');

对 AESKey 进行 aes-256-cbc 解密

function _decode(data) {
 let aesKey = Buffer.from('21IpFqj8qolJbaqPqe1rVTAK5sgkaQ3GQmUKiUQLwRe' + '=', 'base64');
 let aesCipher = crypto.createDecipheriv("aes-256-cbc", aesKey, aesKey.slice(0, 16));
 aesCipher.setAutoPadding(false);
 let decipheredBuff = Buffer.concat([aesCipher.update(data, 'base64'), aesCipher.final()]);
 decipheredBuff = PKCS7Decoder(decipheredBuff);
 let len_netOrder_corpid = decipheredBuff.slice(16);
 let msg_len = len_netOrder_corpid.slice(0, 4).readUInt32BE(0);
 const result = len_netOrder_corpid.slice(4, msg_len + 4).toString();
 return result; // 返回一个解密后的明文-
}
function PKCS7Decoder (buff) {
 var pad = buff[buff.length - 1];
 if (pad < 1 || pad > 32) {
  pad = 0;
 }
 return buff.slice(0, buff.length - pad);
}

然后返回 result 即可

res.end(result);

2.2 回调 url 验证失败问题

验证 URL 时,经常会碰到 URL 验证失败的问题,解决思路是借助微信企业号 接口调试工具

三、创建应用

详解nodejs 开发企业微信第三方应用入门教程

四、测试应用

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

详解nodejs 开发企业微信第三方应用入门教程

从企业微信应用市场发起授权时,企业微信给刚才应用设置的 指令回调 url 发送一个 post 请求,比如:

https://api.worktile.com/worktile"htmlcode">

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

测试应用注意事项

  1. 用于安装测试的企业微信帐号需服务商自行注册,每个应用支持同时添加 10 个测试企业微信账号
  2. 安装测试的企业微信帐号使用的是当前的应用配置信息,后续的修改不会进行同步;如需更新应用信息请重新授权安装
  3. 同一企业微信帐号,不支持同时安装测试应用和正式发布的应用

五、应用上线

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

六、用户网页授权登录

6.1 构造第三方应用网页授权链接

如果第三方应用需要在打开的网页里面携带用户的身份信息,第一步需要构造如下的链接来获取 code:

https://open.weixin.qq.com/connect/oauth2/authorize"height: 230px; width: 663px"> 参数 必须 说明 appid 是 第三方应用 id(即 ww 或 wx 开头的 suite_id)。注意与企业的网页授权登录不同 redirect_uri 是 授权后重定向的回调链接地址,请使用 urlencode 对链接进行处理 ,注意域名需要设置为第三方应用的可信域名 response_type 是 返回类型,此时固定为:code scope 是 应用授权作用域。snsapi_base:静默授权,可获取成员的基础信息(UserId与DeviceId);snsapi_userinfo:静默授权,可获取成员的详细信息,但不包含手机、邮箱等敏感信息;snsapi_privateinfo:手动授权,可获取成员的详细信息,包含手机、邮箱等敏感信息。 state 否 重定向后会带上 state 参数,企业可以填写 a-zA-Z0-9 的参数值,长度不可超过 128 个字节 #wechat_redirect 是 终端使用此参数判断是否需要带上身份信息

详解nodejs 开发企业微信第三方应用入门教程

企业员工点击后,页面将跳转至 redirect_uri"height: 110px; width: 650px"> 参数 必须 说明 access_token 是 第三方应用的 suite_access_token,参见“获取第三方应用凭证” code 是 通过成员授权获取到的 code,最大为 512 字节。每次成员授权带上的 code 将不一样,code 只能使用一次,5 分钟未被使用自动过期。

 6.2.1 获取第三方应用的 suite_access_token

请求方式:POST(HTTPS)

请求地址: https://qyapi.weixin.qq.com/cgi-bin/service/get_suite_token

参数 是否必须 说明 suite_id 是 以 ww 或 wx 开头应用 id(对应于旧的以 tj 开头的套件 id) suite_secret 是 应用 secret suite_ticket 是 企业微信后台推送的 ticket

由于第三方服务商可能托管了大量的企业,其安全问题造成的影响会更加严重,故 API 中除了合法来源 IP 校验之外,还额外增加了 suite_ticket 作为安全凭证。

获取 suite_access_token 时,需要 suite_ticket 参数。suite_ticket 由企业微信后台定时推送给“指令回调 URL”,每十分钟更新一次,见推送 suite_ticket 。

suite_ticket 实际有效期为 30 分钟,可以容错连续两次获取 suite_ticket 失败的情况,但是请永远使用最新接收到的 suite_ticket。

通过本接口获取的 suite_access_token 有效期为 2 小时,开发者需要进行缓存,不可频繁获取。

6.2.2 获取推送 suite_ticket

企业微信服务器会定时(每十分钟)推送 ticket。ticket 会实时变更,并用于后续接口的调用。

请求方式:POST(HTTPS)

请求地址: https://api.ninesix.cc/worktile"text-align: center">详解nodejs 开发企业微信第三方应用入门教程

6.3 获取用户敏感信息

请求方式:POST(HTTPS)

请求地址: https://qyapi.weixin.qq.com/cgi-bin/service/getuserdetail3rd"htmlcode">

{
  "user_ticket": "USER_TICKET"
}

参数 必须 说明 access_token 是 第三方应用的 suite_access_token,参见“获取第三方应用凭证” user_ticket 是 成员票据

返回结果:

{
  "errcode": 0,
  "errmsg": "ok",
  "corpid": "wwxxxxxxyyyyy",
  "userid": "lisi",
  "name": "李四",
  "mobile": "15913215421",
  "gender": "1",
  "email": "xxx@xx.com",
  "avatar": "http://shp.qpic.cn/bizmp/xxxxxxxxxxx/0",
  "qr_code": "https://open.work.weixin.qq.com/wwopen/userQRCode"
}

七、用户授权成功

首页

详解nodejs 开发企业微信第三方应用入门教程

详情页

详解nodejs 开发企业微信第三方应用入门教程

八、给用户发消息

我们可以给推送文本、图片、视频、文件、图文等类型。

请求方式:POST(HTTPS)

请求地址: https://qyapi.weixin.qq.com/cgi-bin/message/send"_blank" href="https://work.weixin.qq.com/api/doc#10975/获取企业授权信息" rel="external nofollow" >获取企业授权信息 获取该参数值,其实可以直接通过获取企业永久授权码 直接取到这两个值。

在我们测试安装应用成功之后,企业微信会 post 一条请求给指令回调 URL,通过上面的解密方式,可以解析到 xml 中的 auth_code

详解nodejs 开发企业微信第三方应用入门教程

然后通过 https://qyapi.weixin.qq.com/cgi-bin/service/get_permanent_code"text-align: center">详解nodejs 开发企业微信第三方应用入门教程

当点击链接时,可以跳到指定任务或者日程等,只不过返回时还是在企业微信的消息模块,并不能自动打开第三方应用,客服回复不支持这么做。

九、注意事项

api 可能有时效性,如有差异,以官方 api 为准。

完整 demo

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

上一篇:微信小程序picker组件关于objectArray数据类型的绑定方法
下一篇:详解NodeJS Https HSM双向认证实现
荣耀猎人回归!七大亮点看懂不只是轻薄本,更是游戏本的MagicBook Pro 16.
人们对于笔记本电脑有一个固有印象:要么轻薄但性能一般,要么性能强劲但笨重臃肿。然而,今年荣耀新推出的MagicBook Pro 16刷新了人们的认知——发布会上,荣耀宣布猎人游戏本正式回归,称其继承了荣耀 HUNTER 基因,并自信地为其打出“轻薄本,更是游戏本”的口号。
众所周知,寻求轻薄本的用户普遍更看重便携性、外观造型、静谧性和打字办公等用机体验,而寻求游戏本的用户则普遍更看重硬件配置、性能释放等硬核指标。把两个看似难以相干的产品融合到一起,我们不禁对它产生了强烈的好奇:作为代表荣耀猎人游戏本的跨界新物种,它究竟做了哪些平衡以兼顾不同人群的各类需求呢?