uniapp h5页面集成企业微信js-sdk

956 阅读6分钟

因为我是第一次接触企业微信js-sdk,所以在写应用的时候踩过了很多坑,而网上的一些东西又不全,每个人的说法不一致,所以今天我就把我最后实现的代码给贴出来,供大家参考,顺便自己备个份,防止以后自己忘记。

其中最大的一个坑就是jweixin.js版本问题,我用的是jweixin-1.2.0.js,其他版本没试过。然后就是在使用wx.config的时候ios和安卓有一点点区别,按照官方文档上面,导入jweixin-1.2.0.js后,直接使用wx.config注入权限验证,在ios上面是可以,但是在Android端上面会报 “wx.config is a function”,于是我继续找度娘帮忙,网上有人说,因为项目是uniapp的,uniapp框架已经内置了wx这个对象,而企业微信官方文档里调用api的前缀又是wx,所以呢,就冲突了,所以官方提供了“jWeixin”’对象;但是在我开发过程中发现,在Android端用“jWeixin”,的确没问题,但是ios就不起作用了,经过我测试才发现还是得用“wx”才行,至于原因,还没找到。r然后我判断平台,分别处理了Android端和ios在使用wx.config的问题,然后就大功告成。

代码如下:

import config from "@/common/config.js";

let wxTicket = ''; //企业jsapi_ticket
let appTicket = ''; //应用jsapi_ticket
const corpid = 'xxxxxxx'; //企业微信的corpid
const url = 'xxxxxxx'; //当前网页的URL, 不包含#及其后面部分

/**
 * 随机字符串16位
 */
function createNonceStr() {
	let chars = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
		'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c',
		'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
		'x', 'y', 'z'
	];
	let nums = "";
	for (let i = 0; i < 16; i++) {
		let id = parseInt(Math.random() * 61);
		nums += chars[id];
	}
	return nums;
}

/**
 * 获取企业jsapi_ticket
 */
function getwxTicket() {
	return new Promise((resolve, reject) => {
		uni.request({
			url: config.baseUrl + '/api/user/getCompanyJsApiTicket',
			header: {
				Authorization: 'U66v7sMAdZvb ' + uni.getStorageSync('token')
			},
			success: (result) => {
				if (result.data.code == 0) {
					wxTicket = result.data.data.ticket;
				} else {
					uni.showToast({
						icon: 'none',
						title: result.data.message
					})
				}
				resolve(result);
			},
			fail: (e) => {
				reject(e);
			}
		})
	})
}

/**
 * 获取应用的jsapi_ticket
 * type 0 劳务管理 1 档案管理 2 环境监测 3 视频监控查看 4 实名认证 5 疫情防控 6 奖惩
 */
function getappTicket(type) {
	return new Promise((resolve, reject) => {
		uni.request({
			url: config.baseUrl + '/api/user/getJsApiTicket',
			header: {
				Authorization: 'U66v7sMAdZvb ' + uni.getStorageSync('token')
			},
			data: {
				type: type
			},
			success: (result) => {
				if (result.data.code == 0) {
					appTicket = result.data.data.ticket;
				} else {
					uni.showToast({
						icon: 'none',
						title: result.data.message
					})
				}
				resolve(result);
			},
			fail: (e) => {
				reject(e);
			}
		})
	})
}

/**
 * 注入权限验证配置
 * @param {Object} type 0 劳务管理 1 档案管理 2 环境监测 3 视频监控查看 4 实名认证 5 疫情防控 6 奖惩
 * @param {Object} agentid 企业微信的应用id
 */
async function initSdk(type, agentid) {
	let timestamp = new Date().getTime();
	let nonceStr = createNonceStr();

	// 获取企业的jsapi_ticket
	await getwxTicket();
	// 获取应用的jsapi_ticket
	await getappTicket(type);

	let wxStr = 'jsapi_ticket=' + wxTicket + '&noncestr=' + nonceStr + '&timestamp=' +
		timestamp + '&url=' + url;
	let appStr = 'jsapi_ticket=' + appTicket + '&noncestr=' + nonceStr + '&timestamp=' +
		timestamp + '&url=' + url;

	let wxSignature = sha1(wxStr);
	let appSignature = sha1(appStr);

	let platform = uni.getSystemInfoSync().platform;

	// ios环境下
	if (platform == 'ios') {
		wx.config({
			beta: true, // 必须这么写,否则wx.invoke调用形式的jsapi会有问题
			debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
			appId: corpid, // 必填,企业微信的corpID
			timestamp: timestamp, // 必填,生成签名的时间戳
			nonceStr: nonceStr, // 必填,生成签名的随机串
			signature: wxSignature, // 必填,签名,见 附录-JS-SDK使用权限签名算法
			jsApiList: [
				"onMenuShareAppMessage",
				"onMenuShareWechat",
				"onMenuShareTimeline",
				"startRecord",
				"stopRecord",
				"onVoiceRecordEnd",
				"playVoice",
				"pauseVoice",
				"stopVoice",
				"onVoicePlayEnd",
				"uploadVoice",
				"downloadVoice",
				"chooseImage",
				"predivImage",
				"uploadImage",
				"downloadImage",
				"getLocalImgData",
				"predivFile",
				"getNetworkType",
				"onNetworkStatusChange",
				"openLocation",
				"getLocation",
				"startAutoLBS",
				"stopAutoLBS",
				"onLocationChange",
				"onHistoryBack",
				"hideOptionMenu",
				"showOptionMenu",
				"hideMenuItems",
				"showMenuItems",
				"hideAllNonBaseMenuItem",
				"showAllNonBaseMenuItem",
				"closeWindow",
				"openDefaultBrowser",
				"scanQRCode",
				"selectEnterpriseContact",
				"openEnterpriseChat",
				"chooseInvoice",
				"selectExternalContact",
				"getCurExternalContact",
				"openUserProfile",
				"shareAppMessage",
				"shareWechatMessage",
				"startWifi",
				"stopWifi",
				"connectWifi",
				"getWifiList",
				"onGetWifiList",
				"onWifiConnected",
				"getConnectedWifi",
				"setClipboardData",
				"getClipboardData"
			] // 必填,需要使用的JS接口列表,凡是要调用的接口都需要传进来
		});

		wx.ready(() => {
			// 通过agentConfig注入应用的权限
			wx.agentConfig({
				corpid: corpid, // 必填,企业微信的corpid,必须与当前登录的企业一致
				agentid: agentid, // 必填,企业微信的应用id (e.g. 1000247)
				timestamp: timestamp, // 必填,生成签名的时间戳
				nonceStr: nonceStr, // 必填,生成签名的随机串
				signature: appSignature, // 必填,签名,见附录-JS-SDK使用权限签名算法
				jsApiList: [
					"selectExternalContact",
					"openUserProfile",
					"thirdPartyOpenPage",
					"sendChatMessage",
					"getCurExternalContact",
					"shareToExternalContact"
				], //必填,传入需要使用的接口名称
				success: (res) => {
					return true;
				},
				fail: (res) => {
					if (res.errMsg.indexOf('function not exist') > -1) {
						uni.showToast({
							title: '版本过低请升级!',
							icon: 'none'
						})
					} else {
						uni.showToast({
							title: 'agentConfig注入应用权限失败:' + res.errMsg,
							icon: 'none'
						})
					}
					return false;
				}
			})
		});

		wx.error((res) => {
			// config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
			uni.showToast({
				title: res,
				icon: 'none'
			})
		});
	}

	// 安卓环境下
	if (platform == 'android') {
		jWeixin.config({
			beta: true, // 必须这么写,否则wx.invoke调用形式的jsapi会有问题
			debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
			appId: corpid, // 必填,企业微信的corpID
			timestamp: timestamp, // 必填,生成签名的时间戳
			nonceStr: nonceStr, // 必填,生成签名的随机串
			signature: wxSignature, // 必填,签名,见 附录-JS-SDK使用权限签名算法
			jsApiList: [
				"onMenuShareAppMessage",
				"onMenuShareWechat",
				"onMenuShareTimeline",
				"startRecord",
				"stopRecord",
				"onVoiceRecordEnd",
				"playVoice",
				"pauseVoice",
				"stopVoice",
				"onVoicePlayEnd",
				"uploadVoice",
				"downloadVoice",
				"chooseImage",
				"predivImage",
				"uploadImage",
				"downloadImage",
				"getLocalImgData",
				"predivFile",
				"getNetworkType",
				"onNetworkStatusChange",
				"openLocation",
				"getLocation",
				"startAutoLBS",
				"stopAutoLBS",
				"onLocationChange",
				"onHistoryBack",
				"hideOptionMenu",
				"showOptionMenu",
				"hideMenuItems",
				"showMenuItems",
				"hideAllNonBaseMenuItem",
				"showAllNonBaseMenuItem",
				"closeWindow",
				"openDefaultBrowser",
				"scanQRCode",
				"selectEnterpriseContact",
				"openEnterpriseChat",
				"chooseInvoice",
				"selectExternalContact",
				"getCurExternalContact",
				"openUserProfile",
				"shareAppMessage",
				"shareWechatMessage",
				"startWifi",
				"stopWifi",
				"connectWifi",
				"getWifiList",
				"onGetWifiList",
				"onWifiConnected",
				"getConnectedWifi",
				"setClipboardData",
				"getClipboardData"
			] // 必填,需要使用的JS接口列表,凡是要调用的接口都需要传进来
		});

		jWeixin.ready(() => {
			// 通过agentConfig注入应用的权限
			jWeixin.agentConfig({
				corpid: corpid, // 必填,企业微信的corpid,必须与当前登录的企业一致
				agentid: agentid, // 必填,企业微信的应用id (e.g. 1000247)
				timestamp: timestamp, // 必填,生成签名的时间戳
				nonceStr: nonceStr, // 必填,生成签名的随机串
				signature: appSignature, // 必填,签名,见附录-JS-SDK使用权限签名算法
				jsApiList: [
					"selectExternalContact",
					"openUserProfile",
					"thirdPartyOpenPage",
					"sendChatMessage",
					"getCurExternalContact",
					"shareToExternalContact"
				], //必填,传入需要使用的接口名称
				success: (res) => {
					return true;
				},
				fail: (res) => {
					if (res.errMsg.indexOf('function not exist') > -1) {
						uni.showToast({
							title: '版本过低请升级!',
							icon: 'none'
						})
					} else {
						uni.showToast({
							title: 'agentConfig注入应用权限失败:' + res.errMsg,
							icon: 'none'
						})
					}
					return false;
				}
			})
		});

		jWeixin.error((res) => {
			// config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
			uni.showToast({
				title: res,
				icon: 'none'
			})
		});
	}
}

module.exports = {
	initSdk
}

注意:

  1. 因为我这里的签名是在前端生成,所以我这里引入了sha1,,并且自己生成了随机字符串等等,代码里都有注释,一般情况,签名什么的,还有wx.configwx.agentConfig接口里面需要的参数都是后台接口直接返回给前端的,所以说具体情况具体分析,我这里提供的代码只是供大家参考,请勿直接使用。
  2. 我代码里使用到的config.baseUrl 是我事先在config.js文件里配置好的,就是请求接口的地址,你们在使用的时候换成自己的接口地址就好了,请自行处理。
  3. /api/user/getCompanyJsApiTicket/api/user/getJsApiTicket分别是后端提供的“获取企业jsapi_ticket”和“获取应用的jsapi_ticket”的接口,这个请大家自己视情况而定,如果签名等参数都是后端返回给你们,你们就可以直接去掉相关代码。
  4. 总之,该代码只供大家参考,请结合自己的实际情况使用。
  5. 第一次写文章,文笔什么之类的都不好,全口水话,请大家多多包涵,谢谢!