单页面应用微信分享跳坑指南

前言

最近在开发的时候遇到了一个微信分享的bug,就是不管你在哪一个路径下的页面,发送给朋友后点开都只会跳到项目的首页。原本微信分享这个只算是一个小功能,也很好解决,但因为项目的特殊性,使得在这个bug解决起来并无那么顺手,因此记录一下备之后翻阅。前端

坑点

  • Vue单页面应用,前端经过Hash控制路由——iOS在微信中不能正常地改变浏览器的hash值,分享出去的页面地址被莫名其妙地添加了参数。vue

  • 微信的安全策略——因为存在js安全域名限制,使得在本地调试更难。vue-router

  • jssdk配置签名。后端

跳坑方法

分享地址被奇怪的被带上了参数

在传统开发中,路由一般都是在后端完成的,可是在Vue单页面中,都是经过控制history interface来控制页面之间的跳转,在咱们的项目中咱们使用hash的方式,可是在分享给朋友后却发现分享地址被加上了一些参数,好比:api

我分享出去的地址是:market.lenkuntang.cn/#/home,分享后会变成了market.lenkuntang.cn/?from=singlemessage#/home。这到底会不会影响到咱们的分享操做呢?这就要了解vue-router的工做原理了,翻看了一下vue-router的源码,发现以下代码:浏览器

// this is delayed until the app mounts
  // to avoid the hashchange listener being fired too early
  setupListeners () {
    const router = this.router
    const expectScroll = router.options.scrollBehavior
    const supportsScroll = supportsPushState && expectScroll

    if (supportsScroll) {
      setupScroll()
    }

    window.addEventListener(supportsPushState ? 'popstate' : 'hashchange', () => {
      const current = this.current
      if (!ensureSlash()) {
        return
      }
      this.transitionTo(getHash(), route => {
        if (supportsScroll) {
          handleScroll(this.router, route, current, true)
        }
        if (!supportsPushState) {
          replaceHash(route.fullPath)
        }
      })
    })
  }
复制代码

hash.js安全

原来在vue-router初始化的时候,会监听window对象的hashchange属性,如想发现浏览器的hash值发生变化了,就会调用History.transitionTo方法,关键就在这个方法会传入一个getHash方法为做参数,若是在这种地址market.lenkuntang.cn/?from=singlemessage#/home也能正确地拿到正确的hash的话,那咱们就能够判定这种意外对咱们的分享是没有影响的。当咱们继续去看getHash方法,在hash.js往下翻点会找到这个方法的实现:bash

export function getHash (): string {
  // We can't use window.location.hash here because it's not
  // consistent across browsers - Firefox will pre-decode it!
  const href = window.location.href
  const index = href.indexOf('#')
  return index === -1 ? '' : href.slice(index + 1)
}
复制代码

咱们能够清楚地知道,当这条地址market.lenkuntang.cn/?from=singlemessage#/home通过getHash以后会直接返回#号后面的字符串,也就是 /home,因此能够得出是不会对咱们分享的功能有影响的。服务器

iOS在微信环境中浏览器地址不变

在Vue-router实现前端控制路由都是经过HTML5 新增的History Interface接口来控制页面之间的跳转的,在跳转的同时经过修改windowloactionhash属性反映回浏览器的地址,可是当遇到iOS时却意外地发现这个hash属性一直没有被改变,致使每次分享出去的地址都是首页,在网上一查发现这原来是个通病,解决的方法就是引入微信的JsSDK来手动控制分享的地址。微信

引入JsSDK所带来的问题

在引入了JsSDK后,首先要对它进行配置,相关配置项以下:

wx.config({
    debug: true, // 开启调试模式,调用的全部api的返回值会在客户端alert出来,若要查看传入的参数,能够在pc端打开,参数信息会经过log打出,仅在pc端时才会打印。
    appId: '', // 必填,公众号的惟一标识
    timestamp: , // 必填,生成签名的时间戳
    nonceStr: '', // 必填,生成签名的随机串
    signature: '',// 必填,签名
    jsApiList: [] // 必填,须要使用的JS接口列表
});
复制代码

说明一下这里的参数分别从哪里来,appId是从微信公众号里获取的,timestampnonceStr还有signature是从服务器中返回的。jsApiList能够在全部JS接口列表中找到。

注:timestampnonceStr实际上是能够在前端生成而后传给服务器再参与签名的计算的,但通常在考虑到安全缘由,timestamp, nonceStr这些参数应该从服务器返回回来(由于它参与了签名的计算)。

注意:这里的传入的随机字符串字段nonceStr驼峰命名!!!

而后就是引入JsSDK中遇到最大的问题——签名问题,要正确地实现使用JsSDK,在服务器端首先要集齐这四种元素:

  • noncestr(随机字符串)
  • jsapi_ticket(经过微信接口得到的ticket)
  • timestamp(时间戳)
  • url(当前网页的URL,不包含#及其后面部分)

而后把这些元素按字典序(ASCII 码从小到大排序)排后使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串,再对字符串进行sha1加密,字段名和字段值都采用原始值,不进行URL 转义,便可获得所谓的签名。

注意:这里的传入的随机字符串字段noncestr全小写!!!

最后附上签名检验工具的地址:mp.weixin.qq.com/debug/cgi-b…

还有示例代码:demo.open.weixin.qq.com/jssdk/sampl…

获得签名后再把timestampnonceStrsignature传回给前端进行JsSDK的初始化配置。

再说计算签名的URL

这里再说说参与签名的url,由于这里传过去的是当前见面的URL且不包括#及其后面部分,这对于使用Hash模式的单页面应用来讲是个好消息,这样就表明咱们只须要在页面加载时初始化一次后即可以在全部页面上使用(对于传统的路径导航,由于URL变了因此要从新初始化,也就是说要在使用到的JsSDK功能的页面中都要从新请求后台接口拿签名再初始化!!)。因此,通常来讲咱们一般会在App.vue这个文件中做JsSDK的初始化操做,当初始化正确后即可在其它页面上直接使用JsSDK接口的功能。

次外,因为微信存在对JsSDK的使用限定在微信公众号里所设置的JS接口安全域名范围里,因此对于本地调度用的localhost域名来讲是不可行的,直接提示invalid url domain,在这里有两种方式能够解决这个问题,一种是经过修改host的方法来实现本地调试,方法以下:

window系统:

进入系统盘目录(一般是C盘): C:\Windows\System32\drivers\etc,找到hosts文件,打开后文件末尾添加一条记录127.0.0.1 market.lenkuntang.cn,这条记录的意思是当你访问market.lenkuntang.cn这个地址的时候会重定向到127.0.0.1这个ip地址,从而实现本地调试的目的。

mac系统

打开一个finder,而后按快捷键command+shift+G,输入private/etc/hosts回车后就能找到对应的hosts文件,因为是权限问题,是没法直接在那个目录中修改hosts文件的,因此要把文件复制到桌面或者其它有修改权限的目录,而后打开后也是相似window同样在文件末尾添加一条记录127.0.0.1 market.lenkuntang.cn,保存后拖回原目录肯定覆盖。

另外一种是使用腾讯云的开发者实验室的在线Web IDE来登陆到测试服务器,而后直接在服务器上进行修改,线上验证。可是因为这个Web IDE目前不支持SSH密钥方式登陆,只能用帐号和密码的方式登陆。因此也是有必定的局限性的。

附上Web IDE工具地址:cloud.tencent.com/developer/l…

点击其中一个教程,而后选择开始上机下方的使用已有云主机标签,在弹出的登陆界面中正确填写你服务器的IP地址和帐号密码即可直接登入服务器内进行相关操做。

登陆界面

  • 登陆界面

登陆成功后的界面

  • 登陆成功后的界面

使用微信开发者工具来本地调试

当咱们配置好了全部东西后,打开浏览器咱们能够在控制台的输出中看到JsSDK的相关信息,可是咱们殊不知道是否能够正确分享,难道咱们每次都要使用手机来访问本地服务来验证吗?并且在使用手机来访问本地服务的时候,使用的是本地电脑的ip地址,这样去拿到签名确定是不对,会报invalid url domain错误,固然也能够改手机的hosts,可是这就不是那么容易改了,安卓的话要root,苹果的话...算了算了。仍是换种方法,这个时候咱们应该使用微信开发者工具来进行调试,微信开发者工具能够模拟微信环境,能够进行微信想着的操做,因此使用这个工具咱们就能够愉快地在本地进行调试啦。

并且,在遇到须要微信登陆的页面时,如何是用普通的浏览器来打开就会跳到微信的受权登陆页,而用开发者工具来打开则会像手机同样弹出受权页:

普通浏览器打开

  • 普通浏览器打开

微信开发者工具

  • 微信开发者工具

总结

经过这几天对微信分享的研究,整体对微信的JsSDK的使用有了大概的认识和了解,虽然其中也遇到很多的坑和麻烦的地方,可是既然问题出现就只能尽可能地去简化问题再解决它。

相关文章
相关标签/搜索