yoowinsu / blog

issues blog
17 stars 3 forks source link

vue-router的history模式在IOS微信分享下url不变的坑以及解决办法 #71

Open yoowinsu opened 6 years ago

yoowinsu commented 6 years ago

问题

此次的问题是在SPA(单页面应用)中存在的问题。在微信分享时,需要获取到前台页面的url,因为微信需要签名认证前台页面url是否是所在安全域名下的页面,如果url出错,一般会报invalid signature的签名错误。 url怎样才算是出错呢? 一般来讲,后台获取签名配置是需要前台把当前页面的url传给后台的(如果已知只有一个不会变的url,后台可以写死),后台需要传api_ticket(临时票据)、随机字符串、时间戳、前台页面url这几个数据给微信才会获取到签名配置。 上面的url要与前台页面的真实url一致! 这里在安卓机中一般没有问题,在IOS下排查后会发现传给后台的url并不是当前页面的真实url,而是第一次进入页面的url,这也是问题所在,这是因为微信IOS系统的机制问题,两种机制如下

解决办法(两种):

1.写一个公共变量储存当前页面url

1.写一个全局变量global.entryUrl(可以写到一个公共的js文件中,main.js里面import一下就可以)

---config.js

global.entryUrl = location.href.split('#')[0];

---需要配置的页面

    let url;
    if (navigator.userAgent.toLowerCase().match(/iphone|ipad/i)) {
      url = global.entryUrl;
    } else {
      url = location.href.split('#')[0];
    }

ps: 公共配置下的global.entryUrl获取的是第一次进入页面的url或者刷新后页面的url,页面内的location.href.split('#')[0]获取的是所在页面的url,两者是不同的 2. 微信规定 签名的URL要与当前页面URL一致! 微信规定 签名的URL要与当前页面URL一致! 微信规定 签名的URL要与当前页面URL一致!

所以每次分享的时候判断是否是IOS系统,IOS微信会认为当前页面的URL是第一次进入时的URL,所以把入口的global.entryUrl传给服务器,安卓传当前页面的URL即可

      let url;
      // 判断是否IOS系统
      if (navigator.userAgent.toLowerCase().match(/iphone|ipad/i)) {
        url = global.entryUrl;
      } else {
        url = location.href.split('#')[0];
      }
      this.axios.post('/goods/goodsShare', {
        goodId: this.$route.query.id,
        url: url
      })
        .then(({data}) => {
          if (data.status === 200) {

            【other coding ...】

            wx.config({
              debug: false,
              appId: _data.appId,
              timestamp: _data.timestamp,
              nonceStr: _data.nonceStr,
              signature: _data.signature,
              jsApiList: ['onMenuShareAppMessage']
            });
            wx.ready(function () {
              wx.onMenuShareAppMessage({
                title: goosname, // 分享标题
                desc: goosdescription, // 分享描述
                link: url, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
                imgUrl: goodsimg, // 分享图标
                type: '', // 分享类型,music、video或link,不填默认为link
                dataUrl: '', // 如果type是music或video,则要提供数据链接,默认为空
                success: function () {
                  // alert('分享成功');
                },
                cancel: function () {
                  // alert('分享已取消');
                }
              });
            });
        });

2.location.href跳转到该分享页面

这种办法其实相当于改变了IOS下当前URL为要分享的URL,其实是和vue-router的思想相违背的,所以只有一个分享页面的情况下可以这样解决,要分享页面多的话就不推荐这样的方法来解决了

zzxiexin commented 5 years ago

if (navigator.userAgent.toLowerCase().match(/iphone|ipad/i)) { url = global.entryUrl; } else { url = location.href.split('#')[0]; } 请教下,这么写不是一样的吗,有什么区别呢?

zzxiexin commented 5 years ago

global.entryUrl = location.href.split('#')[0]; if (navigator.userAgent.toLowerCase().match(/iphone|ipad/i)) { url = global.entryUrl; } else { url = location.href.split('#')[0]; }