业务场景
使用JSSDK开发微信公众号网页,支持在微信浏览器中、微信小程序中使用。微信小程序采用webview方式内嵌微信网页。
网页为React单页面应用,路由方式采用history。首页路由为/,登录页面为/login。
登录检测逻辑
进入首页/,检测当前页面登录状态,如已登录停留在首页/;如未登录则跳转登录页面/login。
代码版本1(错误):IOS网页、小程序报错
提供方
cb.utils.initWeChat = function () {
//传入url获取微信配置,包括签名等。
const config = {
url: "bill/client/pay/getWeChatConfig",
method: "POST",
params: {
url:cb.rest.AppContext.serviceUrl + "/",
},
};
proxy(config).then(function (json) {
if (json.code !== 200) {
console.error(json.message);
return;
}
let obj = json.data;
wx.config({
debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: obj.appId, // 必填,公众号的唯一标识
timestamp: obj.timestamp, // 必填,生成签名的时间戳
nonceStr: obj.nonceStr, // 必填,生成签名的随机串
signature: obj.signature, // 必填,签名
jsApiList: [
"scanQRCode",
"chooseImage",
"getLocation",
"getLocalImgData",
], // 必填,需要使用的JS接口列表
});
wx.ready(function () {
console.log("wx初始化----ready");
});
wx.error(function (res) {
console.log("wx初始化----error" + JSON.stringify(res));
});
});
};
调用方
cb.utils.initWeChat();
版本1代码问题
安卓端网页无问题,在IOS端网页、小程序端的登录页面/login报错签名失败invalid signature。而登录后到首页/刷新网页则不会报签名失败错误。传递的url参数为/。
经过查阅资料了解到操作的浏览器历史记录,真实URL为第一次刚进入时的URL。理论上来说,传递的cb.rest.AppContext.serviceUrl + "/"即为首页,应不会报错。猜测url有字符不同。为了保险起见更改代码版本2,url参数改为初始化时从url取。
代码版本2(错误):IOS小程序报错
提供方
//存储微信配置
if (!window.__retail_wx_config) {
window.__retail_wx_config = {
iosHomePageUrl: null, //缓存ios第一次进入页面的url
};
}
cb.utils.getIOSHomePage = function () {
if (cb.utils.isIos()) {
//ios需缓存第一次进入页面的url,否则在微信网页中wx.config鉴权失败invalid signature,在微信小程序webview未登录初始化会鉴权失败
if(!window.__retail_wx_config.iosHomePageUrl){
//只在第一次进入页面时候取
window.__retail_wx_config.iosHomePageUrl = window.location.href
.split("?")[0]
.split("#")[0];
}
console.log(
"当前为ios,ios首页url为",
window.__retail_wx_config.iosHomePageUrl
);
}
}
cb.utils.initWeChat = function () {
//传入url获取微信配置,包括签名等。
const config = {
url: "bill/client/pay/getWeChatConfig",
method: "POST",
params: {
url: window.__retail_wx_config.iosHomePageUrl
? window.__retail_wx_config.iosHomePageUrl
: cb.rest.AppContext.serviceUrl + "/",
},
};
proxy(config).then(function (json) {
...
});
};
调用方
cb.utils.initWeChat();
版本2代码问题
IOS微信网页无问题了,但是在IOS微信小程序中登录后报错名失败invalid signature,realAuthUrl提示为登录页/login。
传递的url为/。理论上来说未登录跳转逻辑为/=>/login。已登录不跳转。则url应永远为/。由于报了这个错误,猜测webview里面IOS签名与url的获取/检测时机有区别。抱着试一试的态度更改为代码版本3,在小程序中使用setTimeout获取跳转后的url去签名,主要更改了调用时机。
代码版本3(正确)
提供方
//存储微信配置
if (!window.__retail_wx_config) {
window.__retail_wx_config = {
iosHomePageUrl: null, //缓存ios第一次进入页面的url
};
}
cb.utils.getIOSHomePage = function () {
if (cb.utils.isIos()) {
//ios需缓存第一次进入页面的url,否则在微信网页中wx.config鉴权失败invalid signature,在微信小程序webview未登录初始化会鉴权失败,调用逻辑见src\mobile\containers\App\Index.jsx line31
if(!window.__retail_wx_config.iosHomePageUrl){
//只在第一次进入页面时候取
window.__retail_wx_config.iosHomePageUrl = window.location.href
.split("?")[0]
.split("#")[0];
}
console.log(
"当前为ios,ios首页url为",
window.__retail_wx_config.iosHomePageUrl
);
}
}
cb.utils.initWeChat = function () {
const config = {
url: "bill/client/pay/getWeChatConfig",
method: "POST",
params: {
url:
window.__retail_wx_config.iosHomePageUrl
? window.__retail_wx_config.iosHomePageUrl
: cb.rest.AppContext.serviceUrl + "/",
},
};
proxy(config).then(function (json) {
if (json.code !== 200) {
// cb.utils.alert(json.message, 'error');
console.error(json.message);
return;
}
let obj = json.data;
cb.rest.WeChatConfig = obj;
wx.config({
debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: obj.appId, // 必填,公众号的唯一标识
timestamp: obj.timestamp, // 必填,生成签名的时间戳
nonceStr: obj.nonceStr, // 必填,生成签名的随机串
signature: obj.signature, // 必填,签名
jsApiList: [
"scanQRCode",
"chooseImage",
"getLocation",
"getLocalImgData",
], // 必填,需要使用的JS接口列表
});
wx.ready(function () {
console.log("wx初始化----ready");
cb.rest.weChatReady = true;
});
wx.error(function (res) {
console.log("wx初始化----error" + JSON.stringify(res));
cb.rest.weChatReady = false;
});
});
};
调用方
此处初始化wxConfig,小程序环境与微信网页环境需区分,此处不要修改!!!,后续逻辑见src\mobile\init.jsx line 591,
wx.miniProgram.getEnv((res) => {
if (res.miniprogram) {
setTimeout(function () {
//重置ios首页变量start=============
cb.utils.getIOSHomePage();
//重置ios首页变量end=============
cb.utils.initWeChat();
console.log("小程序webview延迟执行initWeChat");
});
} else {
cb.utils.getIOSHomePage();
cb.utils.initWeChat();
console.log("微信浏览器正常执行initWeChat");
}
});
总结
在微信环境中,单页面应用使用JSSDK初始化签名检测机制与当前页面的URL对比有兼容问题。主要表现为
- IOS与Andriod的页面真实URL不同,IOS为第一次刚进入时的URL。
- IOS在微信浏览器与在小程序webview中获取的真实URL不同,在小程序的webview中存储的真实URL应该是获取页面初始化之后(包含跳转)的URL(此项为测试后猜测)。 关于第一条IOS与Andriod的页面真实URL的相关资料还能查到,第二条微信浏览器和微信小程序webview的区别却没有找到相关资料,如有大佬找到相关资料,欢迎交流。 由于小程序的webview与JSSDK的ip白名单等问题,必须在线上测试。此问题耗费了3天时间,记录下,给后面遇到此问题的朋友做一点参考。
参考文章
微信JSSDK 签名错误invalid signature排查
调用wx.config时,遇到invalid signature的解决方法(解决IOS端签名失败问题)
微信JSSDK弹框显示config:invalid signature,realAuthURL