详解IOS微信上Vue单页面应用JSSDK签名失败解决方案

作者:我叫她兜兜 时间:2024-04-30 10:25:40 

背景

手机型号:

型号:iphone 7 / iphone xs max
版本:ios 10.3.1 / ios 12.1
微信版本:WeChat 6.7.3

问题还原:

Vue应用(vue-router)上使用history模式,在某个页面内调用微信JSSDK相关API,如扫码、分享等,使用当前页面URL总会出现签名错误(invalid signature),导致API调用失败。

问题根源

Vue-Router进行路由切换的时候,总是会操作浏览器的历史记录,从而响应页面URL变化。

在JSSDK文档页面有这么一句话:

同一个url仅需调用一次,对于变化url的SPA的web app可在每次url变化时进行调用,目前Android微信客户端不支持pushState的H5新特性,所以使用pushState来实现web app的页面会导致签名失败,此问题会在Android6.2中修复

但根据多次测试情况来看,情况恰好相反,在Android下直接使用 window.location.href 得出的URL进行签名是完全没问题(可能已升级至Android6.2以上版本),在IOS上就不行了。

这是因为在IOS上,无论路由切换到哪个页面,实际真正有效的的签名URL是【第一次进入应用时的URL】。

比如进入应用首页是: https://m.app.com,需要使用JSSDK的页面A是:https://m.app.com/product1/123,无论从首页进入到A页面之前,中间跳转过多少次路由,最终签名有效的URL还是首页URL。

解决方案

方案一

直接粗暴处理方式:

在进入需要使用JSSDK页面(B)的前一个页面(A),即 A > B,直接使用 window.location.href 或 window.open 打开B页面,此时因为B页面是直接刷新方式进入,所以当前B页面URL无论IOS或Android都是可以直接拿来签名的。

这种方式处理缺点也很明显,如页面刷新抖动太厉害不够平滑过渡,再比如B页面需要从vuex中取出缓存信息,如果这些缓存信息不是通过vuex保存在localstorage的话,取出来的肯定都是空的。

方案二

思路:既然IOS仅可使用第一次进入应用的URL来签名,那么在vuex上缓存一个微信签名URL,IOS保存第一次进入应用的URL,Android则缓存为每个页面的URL。签名时,直接从缓存拿出签名URL来处理。


// 全局判断是否IOS方法
function isIos(){
const u = navigator.userAgent;
return u.indexOf("iPhone") > -1 || u.indexOf("Mac OS") > -1;
}

1. 定义vuex缓存


...

{
state: {
 wechatSignUrl: ""
},

mutations: {
 setWechatSignUrl(state, wxSignUrl) {
  // 关键点
  // IOS仅记录第一次进入页面时的URL
  // IOS微信切换路由实际URL不变,只能使用第一进入页面的URL进行签名
  if (isIos() && state.wxSignUrl !== '') {
   return;
  }
  state.wxSignUrl = wxSignUrl;
 }
},

getters: {
 getWechatSignUrl: (state) => state.wxSignUrl
}
}

...

关键点在于设置更新微信签名URL判断的地方:首次进入应用页面的时候肯定会触发更新,若是IOS且签名URL已经设置过了,那么就不需要更新设置了,只要不退出或刷新应用,缓存永远都会是首次进入页面URL。

2. 路由守卫内触发更新签名URL


import store form "@/stores"

// 获取真实有效微信签名URL
function getWechatSignUrl(to){
 if(isIos()) {
  return window.location.href;
 } else {
  // 此处$appHost需要自行处理
  return $appHost + to.fullPath
 }
}

...
$router.beforeEach((to, from, next) => {
 store.commit("setWechatSignUrl", getWechatSignUrl(to));  
})
...

在路由守卫内更新签名URL,保证IOS是使用当前页面URL,Android是使用目标路由完整地址再加上域名

3. 使用签名URL调用JSSDK API

在使用JSSDK API的页面通过vuex取出缓存的微信签名URL,然后进行签名。

比如:


import store form "@/stores"

...
{
methods: {
 initWechatShareConfig() {
  const that = this;
  const wxSignUrl = store.getters['getWechatSignUrl'];
  const wxShareConfigs = {
   // 微信分享配置
  }

// 初始化微信分享
  $wechat.share(wxSignUrl, wxShareConfigs);
 }
}
}
...

$wechat.share 是根据JSSDK文档二次封装的分享方法,内部是根据wxSignUrl先进行签名,然后再调用分享API

来源:https://segmentfault.com/a/1190000017009560

标签:IOS,微信,JSSDK签名,Vue单页面
0
投稿

猜你喜欢

  • 服务器XMLHTTP(Server XMLHTTP in ASP)基础

    2008-11-11 12:45:00
  • Jupyter Notebook读取csv文件出现的问题及解决

    2023-08-09 23:11:50
  • Python学习之加密模块使用详解

    2022-06-01 03:58:03
  • 如何使用PHP中的字符串函数

    2024-05-11 10:01:59
  • vue项目无法删除的问题及解决

    2024-05-02 17:08:36
  • golang cache带索引超时缓存库实战示例

    2023-07-24 04:43:11
  • Java连接数据库步骤解析(Oracle、MySQL)

    2024-01-18 09:42:22
  • PHP Ajax JavaScript Json获取天气信息实现代码

    2023-11-20 20:51:27
  • python删除文件夹下相同文件和无法打开的图片

    2023-03-09 19:26:42
  • golang中defer的基本使用教程

    2023-07-03 01:19:02
  • 使用PyCharm创建Django项目及基本配置详解

    2021-03-31 10:51:36
  • 利用JS打造黑客代码雨效果

    2024-05-03 15:05:16
  • python 发送邮件的示例代码(Python2/3都可以直接使用)

    2023-05-12 08:53:56
  • 支持多浏览器(IE、Firefox、Opera)剪切板复制函数_脚本之家修正版

    2024-05-03 15:08:06
  • sql server通过脚本进行数据库压缩全备份的方法【推荐】

    2024-01-14 18:26:39
  • 使用Djongo模块在Django中使用MongoDB数据库

    2024-01-21 21:10:17
  • 编写一个javascript元循环求值器的方法

    2024-04-23 09:28:15
  • JavaScript实现点击按钮切换网页背景色的方法

    2024-04-16 09:02:43
  • 教你用压缩技术给SQL Server备份文件瘦身

    2009-03-05 14:59:00
  • 浅谈pytorch和Numpy的区别以及相互转换方法

    2022-02-12 03:51:47
  • asp之家 网络编程 m.aspxhome.com