今天在做微信转发的时候,在微信开发工具中转发始终都是可以的,但是到ios手机上就不行,总是报invalid signature错误
问题描述:
单页面应用(使用pushState更新url),iOS 10或Android 6.0
同样的web代码和网址,
使用安卓访问,能正常调用微信API注册并分享;
使用iOS 10则注册失败,返回’invalid signature’
signature生成算法没有问题。(将输入和输出贴到微信提供的验证网页上,都一致)
调查发现:
安卓需要使用当前URL进行微信API注册(即当场调用location.href.split(’#’)[0])
iOS需要使用进入页面的初始URL进行注册,(即在任何pushstate发生前,调用location.href.split(’#’)[0])
解决(规避):
保存进入页面最初的URL,假设为INIT_URL
根据客户端的不同:
2.1 安卓:在准备分享前(或发生URL跳转后)使用当前URL进行wx.config, 如果失败,则尝试使用INIT_URL注册
2.2 iOS:在准备分享前(或发生URL跳转后)使用INIT_URL进行wx.config, 如果失败,则尝试使用当前URL注册
结论:
其实问题就是IOS微信里的current page url(微信右上角“复制链接”的结果)等于初始化进入页面的url,而用document.href获取却是真实的url,这样url不一样,导致签名失败。所以你使用INIT_URL解决了IOS里面的问题。
贴上我的代码
import React from 'react';
import './App.css';
class App extends React.Component {
constructor() {
super();
}
componentDidMount() {
const init_url=window.location.href;
if(init_url){
sessionStorage.setItem('init_url',init_url);
}
}
//首先判断是否完成初始化
render(){
return (
<div>
{
this.state.initDone ? this.props.children : <div>正在加载</div>
}
</div>
);
}
}
export default App
export function jsSdkConfig(obj) {
const host=config.DEV_URL;
let token=util.storageToken();
let u = window.navigator.userAgent;
let isAndroid = u.indexOf('Android') > -1 || u.indexOf('Adr') > -1; //android终端
let isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端
//安卓需要使用当前URL进行微信API注册(即当场调用location.href.split('#')[0])
//iOS需要使用进入页面的初始URL进行注册,(即在任何pushstate发生前,调用location.href.split('#')[0])
let url = '';
if (isiOS) {
if(sessionStorage.getItem("init_url")){
url=encodeURIComponent(sessionStorage.getItem('init_url'))
}else{
url = encodeURIComponent(window.location.href.split('#')[0]);
}
//url = encodeURIComponent(`http://www.qq.com/home/index?op=${window.sessionStorage.getItem('option')}`);//获取初始化的url相关参数
} else {
url = encodeURIComponent(window.location.href.split('#')[0]);
}
//let url = encodeURIComponent(window.location.href.split('#')[0]);
let time = Math.round(new Date().getTime() / 1000); //获取10位时间戳
// alert(window.location.href.split('#')[0]);]
alert(`${host}/service/wechat/forward?token=${token}&url=${url}`);
axios.get(`${host}/service/wechat/forward?token=${token}&url=${url}`).then(function (response) {
alert(response.data.data.appId);
alert(response.data.data.timestamp);
alert(response.data.data.nonceStr);
alert(response.data.data.signature);
alert(response.data.data.jsApiList);
if (response.status === 200) {
/*配置微信jssdk*/
window.wx.config({
debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: response.data.data.appId, // 必填,企业号的唯一标识,此处填写企业号corpid
timestamp: response.data.data.timestamp, // 必填,生成签名的时间戳(10位)
nonceStr: response.data.data.nonceStr, // 必填,生成签名的随机串,注意大小写
signature: response.data.data.signature,// 必填,签名,见附录1(通过https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign 验证)
jsApiList: response.data.data.jsApiList // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
});
window.wx.ready(function () { //必须写在wx.ready里面
var link = obj.link||"";
var imgPath =obj.img||""; // 不大于300*300
var title =obj.title||"";
var desc = obj.desc||"";
window.wx.onMenuShareTimeline({
title: title, // 分享标题
link: link, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
imgUrl: imgPath, // 分享图标
success: function () {
},
cancel: function () {
// 用户取消分享后执行的回调函数
}
});
window.wx.onMenuShareAppMessage({
title: title, // 分享标题
link: link, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
imgUrl: imgPath, // 分享图标
desc: desc,
success: function () {
},
cancel: function () {
// 用户取消分享后执行的回调函数
}
});
});
}
}).catch(function (errors) {
console.log('errors', errors);
});
}