资讯专栏INFORMATION COLUMN

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

lixiang / 1599人阅读

摘要:路由守卫内触发更新签名获取真实有效微信签名此处需要自行处理在路由守卫内更新签名,保证是使用当前页面,是使用目标路由完整地址再加上域名使用签名调用在使用的页面通过取出缓存的微信签名,然后进行签名。

背景

手机型号:

型号: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.hrefwindow.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://www.ucloud.cn/yun/99286.html

相关文章

  • 使用vue开发微信公众号下SPA站点的填坑之旅

    摘要:原文见我的博客,点击进入使用开发微信公众号下站点的填坑之旅本文为我创业过程中,开发项目的填坑之旅。作为一个技术宅男,我的项目是做一个微信公众号,前后端全部自己搞定,不浪费国家一分钱。 原文见我的博客,点击进入使用vue开发微信公众号下SPA站点的填坑之旅 本文为我创业过程中,开发项目的填坑之旅。作为一个技术宅男,我的项目是做一个微信公众号,前后端全部自己搞定,不浪费国家一分钱^_^。 ...

    yeyan1996 评论0 收藏0
  • vue+微信支付目录+JSSDK签名解决方案

    摘要:主要是用,每当用户第一次进来时,去获取一次签名验证。注意只获取一次,这样签名就解决了。 vue+微信支付目录+JSSDK签名解决方案 遇坑如下 注意:此方法仅为个人总结,并非唯一解决方案 微信JSSDK签名出错 微信支付 调起支付缺少API参数 微信支付目录配置,只有5个配置,可能超过5个地方有配置,路由规划 微信授权回调处理 我所使用的技术 vue路由模式 history 模...

    Little_XM 评论0 收藏0
  • 微信 jssdk 签名错误 invalid signature

    摘要:你的页面还是无法正常使用微信函数的。这样似乎就解决了微信签名失败的问题。但是,我们又遇到了另外一种情况在微信小程序里用内嵌的网页,在安卓下也报和错误。 几乎每一个开发用于微信公众号页面的工程师都遇到过微信jssdk报的各种错误,通常是permission denied,类似这样: showImg(https://segmentfault.com/img/bVbm8YB?w=320&h=...

    lei___ 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<