前言
在使用uni-app打包出的H5页面中,通过微信JS-SDK,调用微信的分享功能。
微信JS-SDK使用
一、绑定域名
公众号:登陆微信公众平台 --> 公众号设置 --> 功能设置 --> 填写“JS接口安全域名”;
这里不是必须使用公众号,绑定小程序的也可以,使用小程序中配置的安全域名。
二、优化JS-SDK
从官网下载JS-SDK1.6.0,在源码内修改部分内容:
源码
!(function(e, n) {
typeof define === 'function' && (define.amd || define.cmd) ? define(function() { return n(e) }) : n(e, !0)
}
修改为:
!(function (e, n) {
module.exports = n(e)
}
三、代码引入JS-SDK
在需要分享的页面引入:
import wx from '../../static/jweixin-module/jweixin-1.6.0';
四、通过config接口注入权限验证配置
所有需要使用JS-SDK的页面必须先注入配置信息,否则将无法调用。
本项目流程是将需要验证的signLink发送给后台,后台进行签名操作,然后将签名信息返回给前端,前端根据返回信息通过config接口注入权限验证配置。
五、通过ready接口处理成功验证
ready函数中执行调用的微信API。
代码如下:
// 将需要验证的signLink发送给后台
uni.request({
// 后台接口地址
url: 'https://***.***.com/getSignature/api/creatSignature',
method: 'POST',
data: {
// 这里进行编码是为了发送途中不被截取,后台会进行解码
url: encodeURIComponent(signLink)
},
success: res => {
// 通过config接口注入权限验证配置
wx.config({
debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来。
appId: '', // 必填,公众号的唯一标识,也可以使用小程序的唯一标识
signature: res.data.signature, // 必填,生成签名的时间戳
timestamp: res.data.timestamp.toString(), // 必填,生成签名的随机串
nonceStr: res.data.noncestr, // 必填,签名
jsApiList: ['updateAppMessageShareData', 'updateTimelineShareData'] // 必填,需要使用的JS接口列表
});
wx.ready(function() {
// 需在用户可能点击分享按钮前就先调用
wx.checkJsApi({
jsApiList: ['updateAppMessageShareData', 'updateTimelineShareData'], // 需要检测的JS接口列表
success: function(res) {
// 以键值对的形式返回,可用的api值true,不可用为false
// 如:{"checkResult":{"chooseImage":true},"errMsg":"checkJsApi:ok"}
}
});
const shareLink = "shareLink";
const desc = '分享信息简介';
wx.updateAppMessageShareData({
title: '分享标题', // 分享标题
desc: desc, // 分享描述
link: shareLink, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
imgUrl: 'https://***.***.com/shareLog.png', // 分享图标,分享图标的url,以http或https开头
success: function() {
// 用户点击了分享后执行的回调函数
},
cancel: function() {}
});
});
wx.error(function(res) {
// config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
});
}
});
错误总结
一、签名错误
当wx.config的debug设为true的话打开页面会显示签名是否成功,若显示 invalid signature,则是签名报错,这时候你就需要去检查你的签名配置。
校验签名算法:
- 确认签名算法是否正确,可用 mp.weixin.qq.com/debug/cgi-b… 页面工具进行校验。
- 确认config中noncestr, timestamp与用以签名中的对应noncestr, timestamp一致。
- 确认 config 中的 appid 与用来获取 jsapi_ticket 的 appid 一致。
- 确认url是页面完整的url,包括GET参数部分。
页面url错误导致:
在路由模式为history模式时,iOS需要使用第一次进入页面的URL获取签名,安卓每次路由切换都重新配置签名。
iOS端
这里先说本项目实现。在项目入口时,将入口url保存下来,
uni.setStorageSync('entryUrl', location.href.split('#')[0]);
再在分享页面时获取:
iOSLocalUrl: function() {
const entryUrl = uni.getStorageSync('entryUrl');
if (entryUrl === '') {
entryUrl = location.href.split('#')[0];
}
return entryUrl;
}
将该返回url做为需要验证的signLink,进行签名校验。
这里也可以借助路由钩子,在每次页面跳转时保存。
router.afterEach(() => {
Promise.resolve()
.then(() => {
getSign({
url: global.location.href.split('#')[0]
})
})
})
Andriod端
直接在分享页面获取location.href.split('#')[0]即可。
signLink = location.href.split('#')[0];
原因分析
下图模拟了一个用户进入你的应用(网页)后的一些行为,包括:
-
点击链接或按钮跳转到其他页面
-
刷新页面
其中:
- currentPage表示你正在看的页面
- langdingPage表示落地页,也就是浏览器认为的页面
Andriod系统对url的识别机制
iOS系统对url的识别机制
如上,Andriod系统更符合我们对url的认知,而iOS系统中的每个页面的url都是刚进入项目的第一页的url,除非是刷新页面;即:在SPA模式下:
- iOS中,页面A为整个项目的真实url
- Andriod中,每次路由跳转都会产生新的url
微信js-sdk配置加密所校验的url是落地页url(即:landingPage),所以以下情况若调用微信API需要在当前页面配置:
- iOS进入项目的第一页
- iOS页面刷新后
- Andriod路由跳转或页面刷新后
二、微信分享非安全域名链接导致分享失败
下面代码中的shareLink即分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致,否则将调用失败。
wx.updateAppMessageShareData({
title: '会议邀请', // 分享标题
desc: desc, // 分享描述
link: shareLink, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
imgUrl: 'https://xlite.kedacom.com/conference/2020/shareLog.png', // 分享图标,分享图标的url,以http或https开头
success: function() {
// 用户点击了分享后执行的回调函数
},
cancel: function() {}
});
网上有分析,例如,当前页面是 www.abc.com/123,其公众号对应的… www.abc.com 以及 www.xyz.com,则分享自定义链接 www.abc.com/456 可以成功,分享 www.xyz.com/123 或 www.def.com/123 均将失败。
但是我在实际开发中,分享的链接即使与JS安全域名一致也无法分享成功,链接必须与分享页面地址一致。
const localUrl = "https://xlite.kedacom.com/conference/pages/share/share?confname=123";
// 分享不成功
const shareUrl = "https://xlite.kedacom.com/conference?confname=123";
// 分享成功
const shareUrl = "https://xlite.kedacom.com/conference/pages/share/share?confname=123";
如果说你分享跳转页面必须是非安全域名下的链接,那你可以单独做一个转发页面,通过转发链接进入这个转发页面后,再直接跳转到拼接好的授权页面。参考代码:非安全链接分享解决办法
三、分享链接参数带中文或者特殊字符
Andriod会自动encodeURIComponent(),而iOS不会。所以会出现Andriod自定义可以正常分享,但是iOS就不行。处理如下:
const shareUrl = 'https://xlite.kedacom.com/conference/pages/share/share?confname=' + encodeURIComponent(this.confname) + '&confno=' + encodeURIComponent(this.confno);
小记
以上只是我在实现微信JS-SDK1.6.0自定义分享中遇到的问题,网上还有很多分享只得参考。
参考文章:
[微信分享填坑指南]
欢迎关注我的公众号,谢谢大家!