企業微信第三方應用配置
TIPS:在我開發之前,在網上找的文檔之類的,都是說應用要在套件下創建,但是企業微信已經取消了這個套件,直接就是應用了
創建應用
前期配置
- 想要發布第三方應用,首先要注冊成微信服務商
- 完善品牌、官網等信息,提交申請。注:品牌下可以有多個應用,目前企業微信已取消了,套件這個東西
- 登錄服務商應用后台 -> 標准應用服務 -> 本地應用 -> 創建應用(創建應用配置分基礎信息和開發信息,開發信息是重頭戲)
開發配置
撿了一此主要的配置來寫:
- 應用主頁:這個是在工作台點擊應用后,直接跳轉的頁面。這個url中支持
$CORPID$,這個會轉換成打開應用的企業的corpid,前端獲得這個參數,傳給后台處理得到簽名(如果想使用jsapi的功能的話)。 - 可信域名:這個就是填寫你的網站的域名即可
- 數據回調URL和指令回調URL:這兩個在創建應用的時候,微信服務器都會發送一個校驗,這個是官網教的處理方法。從校驗的角度來說這兩個接口是一樣的。但是功能上是有區別的。
- 數據回調URL:這個是第三方應用創建完成后,接收企業信息的。這個URL中支持和應用主頁一樣的
$CORPID$參數,來區分是哪個企業發來的信息 - 指令回調URL:這個作用比較大,是接收一些授權信息和ticket參數
- 數據回調URL:這個是第三方應用創建完成后,接收企業信息的。這個URL中支持和應用主頁一樣的
說明:這兩個回調URL在驗證的時候是GET請求,在業務處理上是POST請求。
所以寫下來代碼結構應該是這樣的
獲取到永久授權碼和corpid之后,需要存到數據庫中
最后在使用的時候就是這么個過程
- 前端請求后台接口,獲取簽名,攜帶參數為
corpid,這個值前端可以從應用主頁的url中就可以獲取。另一個參數是當前頁面的url用於后台生成簽名。 - 后台接收
corpid后從數據庫中查詢出該企業的永久授權碼,再結合推送到指令回調的ticket,三個參數去獲取access_token,詳情 - 使用上步獲取的
access_token來獲取jsapi_ticket,詳情 - 使用
jsapi_ticket和url和隨機字符串和時間戳四個參數,去生成簽名,詳情 - 最后返回前端3個參數,即:簽名+生成簽名的隨機字符串+生成簽名的時間戳
前端拿到參數后,進行wx.config配置后就可以愉快地使用wx的api了。
接口業務代碼
只是示意,沒寫過后台代碼
const Express = require('express');
const app = Express();
const bodyParser = require('body-parser');
require('body-parser-xml')(bodyParser);
const axios = require('axios');
app.use(bodyParser.xml());
let ticketCount = 0; // 推送ticket計數器
let suite_access_token = ''; // 全局的suite_access_token,getSuiteAccessToken調用成功后會更新一次
/**
* getSuiteAccessToken:獲取suite_access_token
* @param:
* ticket[string]:由指令接口接收到
* */
function getSuiteAccessToken(ticket) {
let data = {
suite_id: 'xxx', // 固定值
suite_secret: 'yyy', // 固定值
suite_ticket: ticket
};
axios.post('https://qyapi.weixin.qq.com/cgi-bin/service/get_suite_token', data).then(result => {
suite_access_token = result.body.suite_access_token;
ticketCount = 0;
}).catch(error => {
console.log(error);
// 獲取失敗,再次獲取
getSuiteAccessToken(ticket);
});
}
/**
* getPermanentCode:獲取永久授權碼
* @param:
* createAuth:臨時授權碼
* */
function getPermanentCode(createAuth) {
let data = {auth_code: createAuth};
axios.post('https://qyapi.weixin.qq.com/cgi-bin/service/get_permanent_code?suite_access_token=' + suite_access_token, data).then(result => {
// 請求永久授權碼成功,連接數據庫,將企業corpid和永久授權碼等信息保存至數據庫
});
}
/**
* getAccessToken:根據corpid獲取accesstoken
* */
function getAccessToken(corpid) {
// 同樣,獲取jsApiTicket的AccessToken也是7200s的有效期,也保存到數據庫中
// 先查詢,如果沒有,或者過期 就重新執行一次請求accessToken的過程
return new Promise(async function(resolve, reject) {
let accessToken = 'accessToken'; // 查詢
let accessTokenExpiresTime = 'xxx'; // 查詢
let isOverdue = new Data() - accessTokenExpiresTime > 7200 * 1000;
if (accessToken && !isOverdue) {
resolve(accessToken);
} else {
let data = {
auth_corpid: corpid,
permanent_code: 'permanent_code' // 需要查詢
};
axios.post('https://qyapi.weixin.qq.com/cgi-bin/service/get_corp_token?suite_access_token=' + suite_access_token, data).then(result => {
resolve(result.data.access_token);
});
}
});
}
/**
* getJsApiTicket:獲取jsapi ticket
* @param:
* corpid[string]:企業id
* @return:
* ticket[string]:
* */
function getJsApiTicket(corpid) {
// 一個企業的jsApiTicket保存時間為7200s 獲得之后就保存到數據庫中,有一個字段jsApiTicketExpiresTime記錄一下過期時間
// 先從數據庫中根據corpid取值,如果沒有或者過期則重新請求一次
return new Promise(async function(resolve, reject) {
let jsApiTicket = 'ticket'; // 數據庫中查詢
let jsApiTicketExpiresTime = 'xxx'; // 數據庫中查詢
let isOverdue = new Data() - jsApiTicketExpiresTime > 7200 * 1000;
// 沒有過期並且存在就使用這個
if (jsApiTicket && !isOverdue) {
resolve(jsApiTicket);
} else {
let accessToken = await getAccessToken();
axios.get('https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=' + accessToken).then(result => {
resolve(result.data.ticket);
});
}
});
}
/**
* getSign:生成簽名算法
* */
function getSign() {
// 生成簽名算法
}
// 校驗接口
app.get('/verify', function (req, res) {
// 創建應用的校驗過程
});
// 指令校驗接口
app.get('/orderUrl', function (req, res) {
// 轉發到 /verify 接口
});
// 數據校驗接口
app.get('/dataUrl', function (req, res) {
// 轉發到 /verify 接口
});
// 指令接口 可以獲取ticket和AuthCode
app.post('/orderUrl', function (req, res) {
// 獲取數據類型
let infoType = req.body.InfoType;
if (infoType === 'create_auth') {
// 企業推送授權信息
let authCode = req.body.AuthCode;
getPermanentCode(authCode);
} else if (infoType === 'suite_ticket') {
// 微信后台推送 ticket
ticketCount++;
if (ticketCount >= 10) {
// 10min推送一次,計10次,執行一次獲取suite_access_token請求
let ticket = req.body.SuiteTicket;
getSuiteAccessToken(ticket);
}
}
res.send('success');
});
app.get('/sign', async function (req, res) {
let corpid = req.query.corpid;
let url = req.query.url;
let jsApiTicket = await getJsApiTicket(corpid);
let noncestr = 'Wm3WZYTPz0wzccnW'; // 隨機生成
let timestamp = 1414587457; // 時間戳
// 根據4個參數生成簽名
let sign = getSign(jsApiTicket, url, noncestr, timestamp);
res.send({
sign,
noncestr,
timestamp
});
});
app.listen('8001');
