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


Posted in Javascript onNovember 14, 2018

背景

手机型号:

型号: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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
asp.net+jquery滚动滚动条加载数据的下拉控件
Jun 25 Javascript
JavaScript常用代码书写规范的超全面总结
Sep 11 Javascript
ionic由于使用了header和subheader导致被遮挡的问题的两种解决方法
Sep 22 Javascript
单行 JS 实现移动端金钱格式的输入规则
May 22 Javascript
基于JS代码实现简单易用的倒计时 x 天 x 时 x 分 x 秒效果
Jul 13 Javascript
jQuery实现简单的回到顶部totop功能示例
Oct 16 jQuery
VUE饿了么树形控件添加增删改功能的示例代码
Oct 17 Javascript
Vue中this.$router.push参数获取方法
Feb 27 Javascript
jQuery 导航自动跟随滚动的实现代码
May 30 jQuery
vue中的计算属性实例详解
Sep 19 Javascript
在vue+element ui框架里实现lodash的debounce防抖
Nov 13 Javascript
element-ui和vue表单(对话框)验证提示语(残留)清除操作
Sep 11 Javascript
laydate时间日历插件使用方法详解
Nov 14 #Javascript
JQuery模拟实现网页中自定义鼠标右键菜单功能
Nov 14 #jQuery
你应该了解的JavaScript Array.map()五种用途小结
Nov 14 #Javascript
微信小程序中的canvas 文字断行和省略号显示功能的处理方法
Nov 14 #Javascript
Vue 框架之动态绑定 css 样式实例分析
Nov 14 #Javascript
js删除对象/数组中null、undefined、空对象及空数组方法示例
Nov 14 #Javascript
Vue 框架之键盘事件、健值修饰符、双向数据绑定
Nov 14 #Javascript
You might like
手把手教你使用DedeCms的采集的图文教程
2007/03/11 PHP
php+highchats生成动态统计图
2014/05/21 PHP
PHP调用C#开发的dll类库方法
2014/07/28 PHP
PHP批量生成图片缩略图的方法
2015/06/18 PHP
PHP的Yii框架中YiiBase入口类的扩展写法示例
2016/03/17 PHP
js利用div背景,做一个竖线的效果。
2008/11/22 Javascript
jQuery live
2009/05/15 Javascript
下载站控制介绍字数显示的脚本 显示全部 隐藏介绍等功能
2009/09/19 Javascript
JQuery动画和停止动画实例代码
2013/03/01 Javascript
JS常用函数使用指南
2014/11/23 Javascript
Clipboard.js 无需Flash的JavaScript复制粘贴库
2015/10/02 Javascript
JS实现点击网页判断是否安装app并打开否则跳转app store
2016/11/18 Javascript
详解js的事件处理函数和动态创建html标记方法
2016/12/16 Javascript
JavaScript实现动态增删表格的方法
2017/03/09 Javascript
JavaScript实现移动端轮播效果
2017/06/06 Javascript
关于Stream和Buffer的相互转换详解
2017/07/26 Javascript
js获取html页面代码中图片地址的实现代码
2018/03/05 Javascript
使用Angular CLI快速创建Angular项目的一些基本概念和写法小结
2018/04/22 Javascript
解决iview多表头动态更改列元素发生的错误的方法
2018/11/02 Javascript
JavaScript实现选项卡效果的分析及步骤
2019/04/16 Javascript
d3.js 地铁轨道交通项目实战
2019/11/27 Javascript
[59:30]VG vs LGD 2019国际邀请赛淘汰赛 胜者组 BO3 第二场 8.22
2019/09/05 DOTA
[04:29]【TI9采访】OG.N0tail在胜者组决赛后接受采访
2019/08/25 DOTA
python使用multiprocessing模块实现带回调函数的异步调用方法
2015/04/18 Python
基于python select.select模块通信的实例讲解
2017/09/21 Python
利用pandas进行大文件计数处理的方法
2018/07/25 Python
Python中asyncio模块的深入讲解
2019/06/10 Python
django一对多模型以及如何在前端实现详解
2019/07/24 Python
python字典的setdefault的巧妙用法
2019/08/07 Python
Django如何使用asyncio协程和ThreadPoolExecutor多线程
2020/10/12 Python
DJI大疆无人机官方商城:全球领先的无人飞行器研发和生产商
2016/12/21 全球购物
关于赌博的检讨书
2014/01/24 职场文书
自我鉴定 电子商务专业
2014/01/30 职场文书
企业党员岗位承诺书
2015/04/27 职场文书
2019年最新七夕唯美祝福语(60条)
2019/07/22 职场文书
my.ini优化mysql数据库性能的十个参数(推荐)
2021/05/26 MySQL