描述
最近在开发过程中遇到一个问题:开启了history模式下的vue单页面应用,在iOS进行微信自定义分享时一直报错invalid signature
,但是在安卓下却一点问题都没有。
在iOS上的表现具体如下:
- 进入网站,未切换路由,此时分享完全没有问题;
- 进入网站后,切换了路由,此时会报错
invalid signature
; - 进入网站后,切换了路由,手动刷新该页面,此时能正常分享了。
分析
在使用微信JSSDK时前端需要传当前页面的URL(不带hash值)给后端,然后后端返回相关配置信息(appId、timestamp、nonceStr、signature)给前端,前端然后根据这些配置参数调用微信提供的wx.config()
。在后端返回信息无误的情况下,如果当前的URL和传递给后端的URL是相同的,那么微信提供的API才能正常调用。
按照正常情况下,传递给后端的URL和此时网站的URL肯定是一样的。但是,**在iOS环境下,当切换路由时,网站的真实URL是不变的,**而安卓下的真实URL会随着路由切换而变化,这就是问题的原因所在。
因此可以解释上述iOS的表现:
- 点击
www.test.com
进入网站,没有切换路由,此时真实的URL和表面的URL都是www.test.com
,能正常分享; - 切换路由到
www.test.com/page1
,此时表面的URL已经是www.test.com/page1
,这个时候使用location.href
获取到的也是www.test.com/page1
,但真实的URL还是www.test.com
。在这个时候,我们获取到的当前地址是www.test.com/page1
,把这个URL传递给后端获取到的配置参数和现在真实的URL不符,所以报错invalid signature
; - 当手动刷新
www.test.com/page1
后,真实的URL也变成了www.test.com/page1
了,此时分享也就正常了。
解决办法
针对上述情况,可以对安卓和iOS系统采取不同解决办法。
安卓系统在每次路由切换后,重新请求配置接口,传给后端的URL就是当前的URL。
iOS系统则需要在页面加载的时候,保存下初始的URL,以后每次请求配置接口时,都使用这个初始URL。
具体实现代码可以参考如下:
// 微信分享
Vue.prototype._share = function (param) {
// 默认配置
let set = {
title: '我是自定义的标题', // 分享标题
desc: '我是自定义的分享描述', // 分享描述
link: location.href.split('#')[0], // 分享链接
imgUrl: 'http://images-gungunbook.oss-cn-hangzhou.aliyuncs.com/20180510/5af3eb2c6f628.png', // 分享配图
callback: function () {} // 分享回调
}
Object.assign(set,param);
Vue.prototype.fetch({
url: `jssdk`,
method: 'post',
// _isiOS是判断是否是iOS环境的函数
// g_first_url是进入网站的初始URL
data: { url: Vue.prototype._isiOS() ? encodeURIComponent(Vue.prototype.g_first_url) :encodeURIComponent(location.href.split('#')[0])},
success: data => {
wx.config({
debug: false, // 开启调试模式
appId: data.appId, // 必填,公众号的唯一标识
timestamp: data.timestamp, // 必填,生成签名的时间戳
nonceStr: data.nonceStr, // 必填,生成签名的随机串
signature: data.signature,// 必填,签名
jsApiList: ['onMenuShareAppMessage','onMenuShareTimeline'] // 必填,需要使用的JS接口列表
});
wx.ready(() => {
// 分享给朋友
wx.onMenuShareAppMessage({
title: set.title,
desc: set.desc,
link: set.link,
imgUrl: set.imgUrl,
type: 'link',
dataUrl: '',
complete: function () {
set.callback('friend')
},
});
// 分享到朋友圈
wx.onMenuShareTimeline({
title: set.desc,
link: set.link,
imgUrl: set.imgUrl,
complete: function () {
set.callback('timeline')
},
});
})
}
})
}
复制代码