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