——都说微信开发多坑,没想到遇到一个天坑。

在做一个vue项目时,要用到微信JS-SDK,官方文档详见:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html

将当前页面url传给后端接口,再通过返回的配置信息,用wx.config成功注入,一切看起来很顺利,在安卓上运行没问题,在iphone上测试,发现浏览器刚进入时(注册页做了注入)没报错,登录后也没错,一登录再退出就报“invalid signature”,再登录回首页(首页也做了注入),也报签名错误,一刷新又正常了。检查传的url也是当前页面url,有点奇怪。以为这只是小小的bug,没想到后来进入了一个“漫长艰辛”的探索之旅...

首先,官方文档有提到这个常见错误及解决方法,一一仔细查看过,连报错的签名都用 https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign 页面工具校验过,都没问题。

然后,去网上一查ios注入权限是否有不同,果然找到原来单页面应用还真的不一样!!!

在微信官方文档有这么一句话:

所有需要使用JS-SDK的页面必须先注入配置信息,否则将无法调用(同一个url仅需调用一次,对于变化url的SPA的web app可在每次url变化时进行调用,目前Android微信客户端不支持pushState的H5新特性,所以使用pushState来实现web app的页面会导致签名失败,此问题会在Android6.2中修复)。

但在实际测试中,安卓并没问题,反而是iphone有问题,应该是安卓版本做了修复。此为第一坑。

继续查资料得知,在ios上,无论路由切换到哪个页面,实际真正有效的的签名url是【第一次进入应用时的URL】。

从A页面跳转到B页面时,由于是使用vue-router切换,都是操作浏览器历史记录,所以ios端微信浏览器锁定的url的还是A页面的url。

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

很多文档都是说history路由模式有问题,而hash模式没问题,但我用的hash模式依旧签名错误。此为第二坑。

再来,既然是第一次进入应用时的url,那我进入应用时就把当前url保存到vuex里面,永久保存在localstorage,每次进入都是拿这个去注入权限不就行了。

在main.js里判断是否是ios和vuex保存的这个url是否为空,为空则存入当前url:

  1. 1 router.beforeEach((to, from, next) => {
  2. 2 if (isIOS() && store.state.user.wechatSignUrl === "") {
  3. 3 store.dispatch("user/setWechatSignUrl", location.href.split("#")[0]);
  4. 4 }
  5. 5 });

打开后发现刚进入没问题,注册页也ok,登录后没错,感觉到胜利在望时,一退出登录又报错,关闭微信浏览器再进入,就一直报错。。。

经过苦苦思索,突然灵光一现,想到这里说的【第一次进入应用时的URL】,应该指的是页面加载、重载或刷新后第一次进入页面时的url,之后无论路由怎么切换url都不变,所以每次整个页面加载或刷新都要清空wechatSignUrl,在再次进入时就保存当前url,这样才能锁定真正能用来签名的url。此为第三坑。

那么为什么每次退出后的url就失效了呢?原来退出后用了页面重载,还做了微信网页授权,微信网页授权要引导用户打开授权页,用户点击后再跳回来页面算加载了一次,此时跳转回来带有code和state的这个url才是有效的签名url!!!而不再是刚进入时的url。。(吐血ing)

所以退出后的页面重载前要清空wechatSignUrl:

  1. 1 commit("SET_WECHAT_SIGN_URL", ""); //退出要重载 所以重置ios微信签名地址
  2. 2 location.reload();

在跳转到授权页之前也清空wechatSignUrl:

  1. 1 store.dispatch("user/setWechatSignUrl", ""); //此处会跳到微信授权页,页面会刷新,所以要重置签名url
  2. 2 window.location.href = wechatAuth.authUrl;

我看了下,就这两个地方需要页面刷新,其他都是路由切换,刷新前清空,刷新后再进入路由就会重新保存当前的url,这个url就肯定是有效的了。

试了下,果然,打开页面后怎么跳,怎么退出再登录,不会再报“invalid signature”。

感觉已经可以收工了是不是?当我放心地关闭页面再次点进去的时候,又报错了!!!(心累)

只好继续默默探索,关闭页面再点进去也算加载,url也不能再用之前的了,所以关闭页面前也要清空wechatSignUrl!还有微信浏览器还有个刷新功能,刷新页面前也要清空,那么怎么监听这个页面关闭和刷新功能呢?

网上说vue中监听页面刷新和关闭可以用beforeunload,所以可以用:

  1. 1 // 当浏览器界面关闭或刷新时触发该事件
  2. 2 window.addEventListener("beforeunload", () => {
  3. 3 this.$store.dispatch("user/setWechatSignUrl", "");
  4. 4 });

在pc端微信web开发者工具可以运行,但在手机上无论怎样刷都保错!!!

继续深耕,原来用onbeforeunload来监听用户离开,浏览器可以,但是在微信中无效。微信浏览器不能用这个。此为第四坑。

经过查询,微信浏览器监听离开事件需要使用pagehide事件,关闭或刷新可用。

所以在需要调用jssdk的页面增加以下事件处理程序:

  1. 1 mounted() {
  2. 2 window.addEventListener("pagehide", this.pageHide);
  3. 3 },
  4. 4 destroyed() {
  5. 5 //移除事件处理程序
  6. 6 window.removeEventListener("pagehide", this.pageHide);
  7. 7 },
  8. 8 methods: {
  9. 9 //页面关闭或刷新时触发
  10. 10 pageHide() {
  11. 11 this.$store.dispatch("user/setWechatSignUrl", "");
  12. 12 },
  13. 13 }

此刻再测试,发现终于完美运行,无论怎么关闭刷新、跳转重载都不再弹出“invalid signature”错误,天可怜见,看了多少文档,经过多少努力,才总算从这个天坑中爬出来了...^o^y...

ps:对于网上提到的第二种方法,是在进入调用jssdk的页面之前,即beforeRouteEnter钩子函数中用直接刷新方式进入(location.href),此时页面记录的当前url就是有效的url,但实测并不成功,这样页面也会刷新抖动太厉害不够平滑过渡,不推荐使用。

解决vue单页面应用做微信JSSDK注入权限时出现“invalid signature”(ios端)的更多相关文章

  1. 在不使用ssr的情况下解决Vue单页面SEO问题

    遇到的问题: 近来在写个人博客的时候遇到了大家可能都会遇到的问题 Vue单页面在SEO时显得很无力,尤其是百度不会抓取动态脚本 Vue-Router配合前后端分离无法让meta标签在蜘蛛抓取时动态填充 ...

  2. vue 单页面(SPA) history模式调用微信jssdk 跳转后偶尔 "invalid signature"错误解决方案

    项目背景 vue-cli生成的单页面项目,router使用history模式.产品会在公众号内使用,需要添加微信JSSDK,做分享相关配置. 遇到的问题 相关配置与JS接口安全域名都已经ok,发布后, ...

  3. nginx配置解决vue单页面打包文件大,首次加载慢的问题

    cnpm run build 文件过大,其中主要是vender.js有1.5M,代码部署到服务器,首次访问加载页面时比较慢,耗时6.5s左右,所以需要优化下. 1.Nginx开启gzip 找到ngin ...

  4. vue单页面前端做非空校验

    form表单 确定按钮 js部分 确定按钮的方法

  5. [微信JSSDK] 解决SDK注入权限验证 安卓正常,IOS出现config fail

    实测有效 解决微信游览器和企业微信游览器JSSDK注入权限验证 安卓正常,IOS出现config fail 一开始我们想到的是可能微信这边的Bug,但细想一下应该不是.因为可能涉及到了IOS的底层原理 ...

  6. fullpage在vue单页面当中使用会出现的问题以及解决办法

    在 vue 单页面当中发现fullpage会报错,报错信息大概意思为,fullpage不允许初始化多次. 解决办法,在使用fullpage的组件跳转路由进入销毁组件之前的生命周期的时候对fullpag ...

  7. vue 单页应用中微信支付的坑

    vue 单页应用中微信支付的坑 标签(空格分隔): 微信 支付 坑 vue 场景 在微信H5页面(使用 vue-router2 控制路由的 vue2 单页应用项目)中使用微信 jssdk 进行微信支付 ...

  8. [转] 2017-11-20 发布 另辟蹊径:vue单页面,多路由,前进刷新,后退不刷新

    目的:vue-cli构建的vue单页面应用,某些特定的页面,实现前进刷新,后退不刷新,类似app般的用户体验.注: 此处的刷新特指当进入此页面时,触发ajax请求,向服务器获取数据.不刷新特指当进入此 ...

  9. 另辟蹊径:vue单页面,多路由,前进刷新,后退不刷新

    目的:vue-cli构建的vue单页面应用,某些特定的页面,实现前进刷新,后退不刷新,类似app般的用户体验.注: 此处的刷新特指当进入此页面时,触发ajax请求,向服务器获取数据.不刷新特指当进入此 ...

随机推荐

  1. SpringMVC主要组件

    1.DispatcherServlet:前端控制器,接收所有请求(如果配置/,则不包含jsp) 2.handlermapping:判断请求格式,判断希望具体要执行的那个方法 3.HanderAdapt ...

  2. Hadoop完全分布式的配置

    选取机器sam01作为主节点,并进行分布式文件的配置 1.进入Hadoop配置文件路径/usr/local/hadoop/etc/hadoop(这里我把Hadoop安装在/usr/local目录下) ...

  3. Docker prefereces

    https://docs.docker.com/docker-for-mac/#preferences-menu docker 的镜像命令需要抽时间了解

  4. 一次Kafka内存泄露排查经过

    一.现象 服务部署后内存总体呈上升趋势 二.排查过程 通过go tool pprof收集了三天内存数据 2月11号数据: 2月14号数据: 2月15号数据: 可以看到newPartitionProdu ...

  5. Solution -「SDOI 2017」「洛谷 P3784」遗忘的集合

    \(\mathcal{Description}\)   Link.   给定 \(\{f_1,f_2,\cdots,f_n\}\),素数 \(p\).求字典序最小的 \(\{a_1,a_2,\cdot ...

  6. MySQL架构原理之体系架构

    MySQL是最流行的关系型数据库软件之一,由于其体量小.速度快.开源免费.简单易用.维护成本低等,在季军架构中易于扩展.高可用等优势,深受开发者和企业的欢迎,在互联网行业广泛使用. 其系统架构如下: ...

  7. Java基于ClassLoder/ InputStream 配合读取配置文件

    阅读java开源框架源码或者自己开发系统时配置文件是一个不能忽略的,在阅读开源代码的过程中尝尝困惑配置文件是如何被读取到内存中的.配置文件本身只是为系统运行提供参数的支持,个人阅读源码时重点不大可能放 ...

  8. JDK、JRE 和 JVM 有什么用,它们是怎样运行的

    JDK如何运作? JDK 功能 以下是JDK的重要组件: JDK 和 JRE:程序员通过使用JDK 创建由 JRE 运行的 Java 程序,其中包括 JVM 和类库. 类库:是一组可动态加载的库,Ja ...

  9. [c语言]c语言中的内存分配[转]

    在任何程序设计环境及语言中,内存管理都十分重要.在目前的计算机系统或嵌入式系统中,内存资源仍然是有限的.因此在程序设计中,有效地管理内存资源是程序员首先考虑的问题. 第1节主要介绍内存管理基本概念,重 ...

  10. 用商业智能BI做出来的报表,甩别人一条街!

    同样是做数据分析的,会商业智能BI的人做的报表都比别人好看.这里所说的好看其实是包括了两个意义,一是排版.色彩搭配等,颜值上的好看:二是把数据分析结果展现地直观易懂上的"好看".想 ...