前端开发攻略---微信JSSDK iOS签名失败终极解决方案:Android正常但iOS报错“invalid signature”
这个问题很经典根源在于iOS 和 Android 对单页应用SPA路由的底层处理机制不同。简单来说在进行 JSSDK 签名时Android认为当前页面的 URL 就是你浏览器地址栏里看到的 URL。iOS则比较“固执”它只认用户第一次进入网页时的入口 URL。即使用前端路由跳转了无数个页面在 iOS 的微信内部机制里当前页面的 URL 可能还是最初的那个 。因此当你在一个非入口页调用wx.config进行签名时在Android上你用当前页面的 URL 去获取签名完美匹配签名成功。在iOS上你同样用当前页面的 URL 去获取签名但微信内部校验时使用的却是入口 URL两者不一致自然就报invalid signature了 。️ 解决方案解决这个问题的核心思路是让 iOS 设备进行签名时使用的总是那个“入口 URL”。这里有几种由好到次的方案供你选择。方案一保存并使用入口 URL最推荐用户体验最好这个方案在用户首次进入应用时就把这个入口 URL 存下来。当需要调用 JSSDK 的页面准备签名时先判断设备如果是 iOS 且存有入口 URL就用它去后端获取签名否则就用当前页面的 URL 。第一步在应用入口保存 URL在你的项目入口文件比如 Vue 的main.js或App.vue的最开始添加以下代码。关键点这段逻辑必须在任何路由跳转之前执行 。// main.js 或 App.vue const isIOS /iPad|iPhone|iPod/.test(navigator.userAgent) !window.MSStream; // 如果是 iOS 并且还没有保存过入口 URL if (isIOS !sessionStorage.getItem(WX_ENTRY_URL)) { // 保存时建议 split(#)[0]只保留 # 之前的部分避免 hash 路由的干扰 sessionStorage.setItem(WX_ENTRY_URL, window.location.href.split(#)[0]); }第二步封装一个获取签名 URL 的方法创建一个工具函数专门用来判断应该用哪个 URL 去后端获取签名 。// utils/wxHelper.js export function getWxSignatureUrl() { // 获取当前页面的真实 URL去除 hash 部分 const currentUrl window.location.href.split(#)[0]; const isIOS /iPad|iPhone|iPod/.test(navigator.userAgent) !window.MSStream; // 注意微信开发者工具的 UA 也包含 iPhone 字段但它的行为与 Android 一致需要排除 [citation:2] const isWechatDevTools /wechatdevtools/i.test(navigator.userAgent); const iosEntryUrl sessionStorage.getItem(WX_ENTRY_URL); // 如果是 iOS 真机非开发者工具并且存有入口 URL就使用入口 URL if (isIOS !isWechatDevTools iosEntryUrl) { console.log(使用 iOS 入口 URL 签名:, iosEntryUrl); return iosEntryUrl; } // 其他情况Android、开发者工具、或没有入口URL的iOS都使用当前URL console.log(使用当前页面 URL 签名:, currentUrl); return currentUrl; }第三步在调用签名接口时使用在你需要初始化 JSSDK 的页面或函数中调用getWxSignatureUrl()方法将得到的 URL 传给后端去生成签名。// 在你的业务页面中 import { getWxSignatureUrl } from /utils/wxHelper; import wx from weixin-js-sdk; async function initJssdk() { const signatureUrl getWxSignatureUrl(); // 获取正确的 URL // 调用后端接口获取签名把 signatureUrl 传给后端 const res await fetch(/api/get-signature?url${encodeURIComponent(signatureUrl)}); const { appId, timestamp, nonceStr, signature } await res.json(); wx.config({ debug: false, // 开发阶段可以开 true appId, timestamp, nonceStr, signature, jsApiList: [你要使用的API列表如chooseImage], }); wx.ready(() { console.log(JSSDK 准备就绪); }); wx.error((err) { console.error(JSSDK 配置失败:, err); }); }方案二放弃前端路由改用原生页面跳转这个方案最简单粗暴在需要用到 JSSDK 的页面之间跳转时不使用vue-router的push方法而是直接用window.location.href或a标签 。优点无需额外的代码逻辑每次跳转都是真正的页面刷新iOS 就能正确识别 URL。缺点会完全失去单页应用SPA无刷新、状态保持等优势用户体验会打折有白屏刷新感。方案三紧急情况下的“刷新大法”如果你现在正急着上线没时间改代码可以先用这个办法“救火”。原理是在签名失败时如果是 iOS 设备就自动刷新一下页面。刷新后当前页面就变成了新的“入口 URL”签名就能成功了 。wx.error((err) { if (err.errMsg.includes(invalid signature)) { const isIOS /iPad|iPhone|iPod/.test(navigator.userAgent) !window.MSStream; const isWechatDevTools /wechatdevtools/i.test(navigator.userAgent); if (isIOS !isWechatDevTools) { // 加一个标记防止无限刷新 if (!sessionStorage.getItem(wx_reload_flag)) { sessionStorage.setItem(wx_reload_flag, true); location.reload(); } else { // 如果刷新后还失败就清掉标记并报错 sessionStorage.removeItem(wx_reload_flag); console.error(iOS 微信签名失败请检查配置); } } } }); // 成功后清除标记 wx.ready(() { sessionStorage.removeItem(wx_reload_flag); }); 补充提醒安全域名请确保你在微信公众平台后台配置的JS 接口安全域名与你网站的域名完全一致这是签名能成功的基础前提 。URL 编码当把 URL 传给后端时建议使用encodeURIComponent()进行一次编码可以避免一些特殊字符导致的问题 。sessionStorage 的有效性sessionStorage在用户关闭当前网页标签页或窗口后就会清空。这符合业务场景因为用户重新打开页面新的 URL 就是新的“入口 URL”。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2410400.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!