企业微信小程序访问的是在线子应用(即可直接通过浏览器访问),因此只需将海马汇打包部署到服务器上即可。
海马汇子应用目前使用过两种模式:
纯原生海马汇框架开发
该模式所有子应用/页面都需要自己开发,不存在标准子应用,因此开发工作量大,但无冗余的内容
uni-app壳子嵌套含标准子应用海马汇(srm-uni-app-map & srm-fronr-app-map)
该模式拥有大量标准子应用,因此有类似开发需求可直接使用标准子应用页面或在标准页面上进行二开,开发工作量会相对较少,但会存在冗余内容(未使用的标准子应用)
第一种模式需要自己根据企业微信提供的信息获取token等;第二种模式uni-app壳子已经做好相对应的功能,因此不需要前端再次获取相应信息。
本篇文章主要讲第一种模式下企业微信对接海马汇子应用的一些内容。
在讲海马汇获取企业微信用户信息之前,先了解一下企业微信是如何将用户信息传递给小程序的,这有利于了解后续的步骤。
首先,需要在企业微信管理平台创建小程序并填写相关信息,然后在“应用管理”中点击对应的子应用可以查看子应用的相关信息。如下图:
主要关注这个应用主页信息,该信息是企业微信传递用户信息的关键。该链接中对应参数如下:
参数 | 说明 |
---|---|
appid | 第三方应用id(即ww或wx开头的suite_id)。注意与企业的网页授权登录不同 |
redirect_uri | 授权后重定向的回调链接地址(即子应用首页),请使用urlencode对链接进行处理 ,注意域名需要设置为第三方应用的可信域名 |
response_type | 返回类型,此时固定为:code |
scope | 应用授权作用域。 snsapi_base:静默授权,可获取成员的的基础信息(UserId与DeviceId); snsapi_userinfo:静默授权,可获取成员的详细信息,但不包含手机、邮箱; snsapi_privateinfo:手动授权,可获取成员的详细信息,包含手机、邮箱 注意:**企业自建应用可以根据userid获取成员详情,无需使用snsapi_userinfo和snsapi_privateinfo两种scope。**更多说明见scope |
agentid | 企业应用的id。 当scope是snsapi_userinfo或snsapi_privateinfo时,该参数必填 注意redirect_uri的域名必须与该应用的可信域名一致。 |
state | 重定向后会带上state参数,企业可以填写a-zA-Z0-9的参数值,长度不可超过128个字节 |
#wechat_redirect | 终端使用此参数判断是否需要带上身份信息 |
当进入小程序时会首先访问该链接,企业微信根据该链接校验相关信息无误后会重定向至redirect_uri
并携带两个参数。
重定向地址格式如: redirect_uri?code=CODE&state=STATE
将参数传递给后端,后端可根据企业微信官方API获取到用户userId从而返回token。
关于这部分的详细内容详见企业微信API文档(https://developer.work.weixin.qq.com/document/path/91120)
注:分享页面如需获取用户信息,则分享链接应根据该要求进行分享,从而保证进入分享页面时获取到相关信息
了解了企业微信传递用户信息的过程,那获取企业微信token就容易了许多,以下是某个项目获取企业微信token的代码示例
// 页面mounted获取token相关代码
let url = location.href;
const code = url.match(/code=(.*)&/)[1];
const state = url.match(/state=(.*?)(&|#)/)[1];
const [ thirdPartyCode, srmAccount ] = state.split('-');
const params = {
code,
srmAccount,
thirdPartyCode,
clientId: "srm-front",
clientSecret: "secret",
changeDefaultTenantFlag: true,
};
await api.getToken(params);
// 接口axios代码
/**
* 获取token
* @param {Object} params - 请求参数
*/
getToken: async (params) => {
const url = `/smbl/v1/map-third-party-oauth/user/auto-login-by-phone`;
const res = await noAuthHttp.post(url, params);
if (res.accessToken !== '') {
window.localStorage.setItem("user-token", res.accessToken);
} else {
console.log('获取Token失败!')
}
console.log('设置TOKEN成功,Token为', window.localStorage.getItem('user-token'));
},
如果在企业微信中需要使用扫一扫、分享、获取设备信息等相关功能(更详细的功能详见官方文档),则需要使用企业微信JSSDK。
由于官方推荐的是script导入的方式,因此我们需要在public/index.html
文件中导入JSSDK文件
所有需要使用JS-SDK的页面必须先注入配置信息,否则将无法调用(同一个url仅需调用一次,对于变化url的SPA(single-page application)的web app可在每次url变化时进行调用)。
一般在子应用首页配置JSSDK,项目配置JSSDK如下
/**
* 设置wxjssdk配置
* @param{String} url - 当前地址
*/
async setJSSDK(url) {
const wx = parent.wxBridge || window.wx;
if (url.includes('#')) {
url = url.match(/(.*)#/)[1];
}
const config = await api.getJSSDK({ url });
const {
appId = '',
timestamp = new Date().getTime(),
nonceStr,
signature,
} = config;
// 注入的是企业的身份与权限
wx.config({
beta: true, // 必须这么写,否则wx.invoke调用形式的jsapi会有问题
debug: false, // 是否开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId, // 必填,企业微信的corpID
timestamp, // 必填,生成签名的时间戳,精确到秒
nonceStr, // 必填,生成签名的随机串
signature, // 必填,签名,见 附录-JS-SDK使用权限签名算法
jsApiList: [ 'setClipboardData', 'onMenuShareAppMessage' ], // 必填,需要使用的JS接口列表,凡是要调用的接口都需要传进来
});
},
其中appId, timestamp, nonceStr, signature信息推荐后端处理返回,因为每个环境的企业微信小程序的appId都不一样,后端处理返回利于上线。
若由前端生成对应信息,则需要符合企业微信对应信息规则。(规则地址:https://work.weixin.qq.com/api/doc/90001/90144/90539)
配置完成后即可在对应页面使用JSSDK接口,如要在配置完JSSDK后立即使用则需要在wx.ready函数内使用。因为jssdk配置是异步的,直接使用JSSDK相关接口会导致在配置未完成之前使用从而导致报错。
项目使用JSSDK接口示例如下(此处使用的是转发配置接口)
// 转发单据
async shareTicket() {
const { poPlanHeaderId } = this.$route.params;
const { poPlanNumber } = this.baseData;
const wx = parent.wxBridge || window.wx;
const baseURL = process.env.VUE_APP_DOMAIN_NAME;
console.log(baseURL);
// 获取链接配置信息
const {
appId,
state,
// secret,
agentId,
} = await api.getLinkConfig();
// 获取“转发”按钮点击状态及自定义分享内容接口
wx.ready(() => {
wx.onMenuShareAppMessage({
title: '标题', // 分享标题
desc: `描述号: ${poPlanNumber}`, // 分享描述
link: `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appId}&redirect_uri=${baseURL}/SRM_Platform_Map/#/purchaseMaintain/detail/${poPlanHeaderId}?fromShare=true&response_type=code&scope=snsapi_base&agentid=${agentId}&state=${state}#wechat_redirect`, // 分享链接;在微信上分享时,该链接的域名必须与企业某个应用的可信域名一致
imgUrl: 'https://oss-agri-map-srm-public-bucket.oss-cn-beijing.aliyuncs.com/hpfm05/1173/04b99e226752432b9a07c34937aadcdc@MAP_LOGO.png', // 分享图标
success: function () {
// 用户确认分享后执行的回调函数
console.log('转发成功');
},
cancel: function () {
// 用户取消分享后执行的回调函数
this.$hips.toast({
message: '转发失败!',
});
},
});
})
},
API | 作用 | 示例 |
---|---|---|
wx.checkJsApi | 判断当前客户端版本是否支持指定JS接口 | https://developer.work.weixin.qq.com/document/path/94324 |
wx.agentConfig | 通过agentConfig注入应用的权限 | https://developer.work.weixin.qq.com/document/path/94325 |
wx.invoke(‘getContext’, fn) | 获取进入H5页面的入口环境 | https://developer.work.weixin.qq.com/document/path/94326 |
API | 作用 | 示例 |
---|---|---|
wx.onMenuShareAppMessage | 获取“转发”按钮点击状态及自定义分享内容接口 | https://developer.work.weixin.qq.com/document/path/90523 |
wx.onHistoryBack | 在用户返回上个页面时,回调开发者注册的函数,处理业务需要的逻辑(如确认或重定向到指定的页面) | https://developer.work.weixin.qq.com/document/path/90524 |
wx.hideOptionMenu | 隐藏右上角菜单接口 | https://developer.work.weixin.qq.com/document/path/90524 |
wx.showOptionMenu | 显示右上角菜单接口 | https://developer.work.weixin.qq.com/document/path/90524 |
wx.closeWindow | 关闭当前网页窗口接口 | https://developer.work.weixin.qq.com/document/path/90524 |
wx.hideMenuItems | 批量隐藏功能按钮接口 | https://developer.work.weixin.qq.com/document/path/90524 |
wx.showMenuItems | 批量显示功能按钮接口 | https://developer.work.weixin.qq.com/document/path/90524 |
wx.hideAllNonBaseMenuItem | 隐藏所有非基础按钮接口 | https://developer.work.weixin.qq.com/document/path/90524 |
wx.showAllNonBaseMenuItem | 显示所有功能按钮接口 | https://developer.work.weixin.qq.com/document/path/90524 |
wx.invoke(‘openDefaultBrowser’, fn) | 打开系统默认浏览器 | https://developer.work.weixin.qq.com/document/path/90524 |
wx.onUserCaptureScreen | 用户截屏事件 | https://developer.work.weixin.qq.com/document/path/90524 |
wx.scanQRCode | 调起企业微信扫一扫接口 | https://developer.work.weixin.qq.com/document/path/90525 |
wx.invoke(‘launchMiniprogram’, obj, fn) | 在企业微信内快速跳转到指定的小程序页面 | https://developer.work.weixin.qq.com/document/path/93114 |
API | 作用 | 示例 |
---|---|---|
wx.getLocalImgData | 获取本地图片接口 | https://developer.work.weixin.qq.com/document/path/90528 |
wx.chooseImage | 拍照或从手机相册中选图接口 | https://developer.work.weixin.qq.com/document/path/90528 |
wx.previewImage | 预览图片接口 | https://developer.work.weixin.qq.com/document/path/90528 |
wx.uploadImage | 上传图片接口 | https://developer.work.weixin.qq.com/document/path/90528 |
wx.downloadImage | 下载图片接口 | https://developer.work.weixin.qq.com/document/path/90528 |
wx.startRecord | 开始录音接口 | https://developer.work.weixin.qq.com/document/path/90529 |
wx.stopRecord | 停止录音接口 | https://developer.work.weixin.qq.com/document/path/90529 |
wx.onVoiceRecordEnd | 监听录音自动停止接口 | https://developer.work.weixin.qq.com/document/path/90529 |
wx.playVoice | 播放语音接口 | https://developer.work.weixin.qq.com/document/path/90529 |
wx.pauseVoice | 暂停播放接口 | https://developer.work.weixin.qq.com/document/path/90529 |
wx.previewFile | 预览文件接口 | https://developer.work.weixin.qq.com/document/path/90530 |
API | 作用 | 示例 |
---|---|---|
wx.setClipboardData | 设置系统剪贴板的内容 | https://developer.work.weixin.qq.com/document/path/90535 |
wx.getLocation | 获取地理位置接口 | https://developer.work.weixin.qq.com/document/path/90537 |
调用config接口的时候传入参数debug: true 可以开启debug模式,页面会alert出错误信息。以下为常见错误及解决方法:
报错信息/具象 | 报错原因及解决办法 |
---|---|
invalid url domain | 当前页面所在域名与使用的corpid没有绑定(可在该应用的可信域名中配置域名) |
invalid signature签名错误 | 解决办法: \1) 确认签名算法正确,可用http://work.weixin.qq.com/api/jsapisign页面工具进行校验。 \2) 确认config中nonceStr(js中驼峰标准大写S), timestamp与用以签名中的对应noncestr, timestamp一致。 \3) 确认url是页面完整的url(请在当前页面alert(location.href.split(‘#’)[0])确认),包括’http(s)/‘部分,以及’?‘后面的GET参数部分,但不包括’#'hash后面的部分。 \4) 确认config中的appid与用来获取jsapi_ticket的corpid一致。 \5) 确保一定缓存access_token和jsapi_ticket。 \6) 确保你获取用来签名的url是动态获取的,动态页面可参见实例代码中php的实现方式。如果是html的静态页面在前端通过ajax将url传到后台签名,前端需要用js获取当前页面除去’#‘hash部分的链接(可用location.href.split(’#')[0]获取,而且需要encodeURIComponent),因为页面一旦分享,企业微信客户端会在你的链接末尾加入其它参数,如果不是动态获取当前链接,将导致分享后的页面签名失败。 |
the permission value is offline verifying 或者 fail_nopermission | 错误原因: config没有正确执行,或者是调用的JSAPI没有传入config的jsApiList参数中 解决办法: \1) 确认config正确通过。 \2) 如果是在页面加载好时就调用了JSAPI,则必须写在wx.ready的回调中。 \3) 确认config的jsApiList参数包含了这个JSAPI。 |
permission denied | 该应用没有权限使用这个接口 |
function not exist | 当前客户端版本不支持该接口,请升级到新版体验。 |
服务上线之后无法获取jsapi_ticket,自己测试时没问题 | 因为access_token和jsapi_ticket必须要在自己的服务器缓存,否则上线后会触发频率限制。请确保在服务上线前一定全局缓存access_token和jsapi_ticket,两者有效期均为7200秒(以返回结果中的expires_in为准),否则一旦上线触发频率限制,服务将不再可用。 |
uploadImage怎么传多图 | 目前只支持一次上传一张,多张图片需等前一张图片上传之后再调用该接口 |
通过a链接(例如先通过企业微信授权登录)跳转到b链接,invalid signature签名失败 | 后台生成签名的链接为使用jssdk的当前链接,也就是跳转后的b链接,请不要用企业微信登录的授权链接进行签名计算,后台签名的url一定是使用jssdk的当前页面的完整url除去’#'部分。 |
出现config:fail错误 | 这是由于传入的config参数不全导致,请确保传入正确的appId、timestamp、nonceStr、signature和需要使用的jsApiList。 |