nodejs 開發企業微信--第三方應用服務商註冊應用

最近公司要開發企業微信端的 worktile,以前做的是企業微信內部應用,由於開發的是企業內部應用,所有隻適用於私有部署客戶,對於公有云客戶就無法使用,所有就準備開發企業微信的第三方應用,本文主要介紹在調研階段遇到的山珍海味。

開發之前你需要前註冊爲第三方服務商,然後用第三方服務商的賬號創建應用,創建之後只需要管理員授權應用,第三方服務商即可爲用戶提供服務。這裏我們主要研究第三方服務商註冊應用。

註冊第三方服務商

登陸服務商官網,註冊成爲服務商,並登陸服務商管理後臺。

配置開發信息

1、在創建應用之前,首先要配置好通用開發參數

在填寫系統事件接收 url 時,要正確響應企業微信驗證 url 的請求。這個可以參考企業微信後臺,自建應用的接收消息API

在企業的管理端後臺,進入需要設置接收消息的目標應用,點擊“接收消息”的“設置API接收”按鈕,進入配置頁面。

 要求填寫應用的 URL、Token、EncodingAESKey 三個參數,這三個參數的用處在加解密方案說明

  • URL 是企業後臺接收企業微信推送請求的訪問協議和地址,支持 http 或 https 協議(爲了提高安全性,建議使用 https)。
  • Token 可由企業任意填寫,用於生成簽名。
  • EncodingAESKey 用於消息體的加密,是 AES 密鑰的 Base64 編碼。

驗證 URL 有效性

當點擊保存的時候,企業微信會發生一條 get 請求到填寫的 url

比如 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,直接返回成功即可。

各個事件的回調,服務商在收到推送後都必須直接返回字符串 “success”,若返回值不是 “success”,企業微信會把返回內容當作錯誤信息。

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

測試應用安裝成功之後,就可以通過企業微信——工作臺中測試應用

應用上線

已認證企業微信的服務商,可進入應用管理—點擊提交上線—勾選應用—提交上線。

注意事項

  • 本文更新於 2019 年 2 月 25 日,api 可能有時效性,如有差異,以 官方 api 爲準。
  • worktile 正在開發測試 企業微信、釘釘、h5 端,上線之後歡迎使用。
  • 完整 demo
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章