單頁面應用微信分享跳坑指南

前言

最近在開發的時候遇到了一個微信分享的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的使用有了大概的認識和了解,雖然其中也遇到很多的坑和麻煩的地方,可是既然問題出現就只能儘可能地去簡化問題再解決它。

相關文章
相關標籤/搜索