企业微信第三方应用配置(附接口示意代码)

企业微信第三方应用配置

TIPS:在我开发之前,在网上找的文档之类的,都是说应用要在套件下创建,但是企业微信已经取消了这个套件,直接就是应用了

创建应用

前期配置

  • 想要发布第三方应用,首先要注册成微信服务商
  • 完善品牌、官网等信息,提交申请。注:品牌下可以有多个应用,目前企业微信已取消了,套件这个东西
  • 登录服务商应用后台 -> 标准应用服务 -> 本地应用 -> 创建应用(创建应用配置分基础信息和开发信息,开发信息是重头戏)

开发配置

捡了一此主要的配置来写:

  • 应用主页:这个是在工作台点击应用后,直接跳转的页面。这个url中支持$CORPID$,这个会转换成打开应用的企业的corpid,前端获得这个参数,传给后台处理得到签名(如果想使用jsapi的功能的话)。
  • 可信域名:这个就是填写你的网站的域名即可
  • 数据回调URL指令回调URL:这两个在创建应用的时候,微信服务器都会发送一个校验,这个是官网教的处理方法。从校验的角度来说这两个接口是一样的。但是功能上是有区别的。
    • 数据回调URL:这个是第三方应用创建完成后,接收企业信息的。这个URL中支持和应用主页一样的$CORPID$参数,来区分是哪个企业发来的信息
    • 指令回调URL:这个作用比较大,是接收一些授权信息ticket参数

说明:这两个回调URL在验证的时候是GET请求,在业务处理上是POST请求。
所以写下来代码结构应该是这样的

获取到永久授权码和corpid之后,需要存到数据库中

最后在使用的时候就是这么个过程

  1. 前端请求后台接口,获取签名,携带参数为corpid,这个值前端可以从应用主页的url中就可以获取。另一个参数是当前页面的url用于后台生成签名。
  2. 后台接收corpid后从数据库中查询出该企业的永久授权码,再结合推送到指令回调的ticket,三个参数去获取access_token详情
  3. 使用上步获取的access_token来获取jsapi_ticket详情
  4. 使用jsapi_ticketurl和随机字符串和时间戳四个参数,去生成签名,详情
  5. 最后返回前端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');
posted @ 2018-03-01 18:20  哲楠  阅读(17389)  评论(3编辑  收藏  举报