由于一直在開發公司雙十一的各種活動,最近一直也沒來得及寫筆記。昨天項目成功搞完,今天一大早就迫不及待的來給大家分享一下這次在開發中遇到的一些坑及解決辦法。

由于這次雙十一的活動主要是微信內傳播的小游戲,所以需要用到微信分享,授權等功能。網上關于vue2與微信分享功能的文章挺多,但是內容大多不太全,希望小呆的這篇筆記能夠幫助到你。


公眾號配置

如果你們的公眾號有專人保管,那么跟他說把安全域名加一下,安全域名用于微信的驗證,沒有這一步操作,下面的都白搭。比如我們的測試公眾號,綁定的就是我們測試服務器的域名。同理,生產也是如此。


后端配置

要想使用微信的JS-SDK功能,需要生成簽名,配合appId才能使用,這些步驟通常是由后端生成的。這里省去3000字描述如何生成簽名,反正你找后端同學就對了。


前端配置

終于輪到我們前端上場了,啰嗦了那么多,下面讓我們正式起飛~┏ (゜ω゜)=?

安裝微信JS-SDK

首先我們通過npm 安裝 微信的js-sdk,當然你也可以在index.html頁面中直接加<script>引用,哪種方式都可以。

npm -install weixin-js-sdk --save

判斷是否為微信瀏覽器

既然我們要用,我們就搞一個通用的mixins嘛,也方便以后在不同的項目中調用。那么,新建一個wxapi.js吧,然后引入之前安裝的JS-SDK。既然用微信的JS-SDK,那么肯定非微信瀏覽器就無法訪問該頁面啦,所以我們要先寫一個判斷瀏覽器的方法。

// wxapi.js
import wx from 'weixin-js-sdk'
const wxApi = {
 /**
 * [isweixin 判斷是否微信瀏覽器]
 */
 isweixin () {
  const ua = window.navigator.userAgent.toLowerCase()
  if (ua.match(/MicroMessenger/i) == 'micromessenger') {
   return true
  } else {
   this.$router.push({path: '/wxkj/isnotWechat'})
   return false
  }
 }
}
export default wxApi

微信JS-SDK初始化

接著,我們寫一個微信初始化的方法,用來初始化微信的JS-SDK。該方法接受一個參數,用于傳入后續調用的微信功能(如分享,獲取地理位置等等)。因為微信的簽名等數據是由后端同學生成的,所以我們需要通過ajax來獲取這些數據。這里的this.ajaxGet換成你們自己的ajax方法就好啦。

在獲取到后端同學的數據之后,我們調用wx.config方法,來校驗是否可以使用微信的JS-SDK。注意,jsApiList是用來配置可以注冊哪些微信功能的,這里舉例了2個,一個是分享給朋友,一個是分享到朋友圈,其他功能請到微信JS-SDK文檔中自行查看。之后我們調用wx.ready方法,用來處理驗證成功后的事件。

 isweixin () {
  ...
 },
// 這里接著上面的代碼
/**
* [wxRegister 微信Api初始化]
* @param  {Function} callback [ready回調函數]
*/
wxRegister (callback) {
 let data = {params: {reqUrl: window.location.href}}
 this.ajaxGet(false, '/wxpl/cfgInfo', data).then((res) => {
    wx.config({
     debug: false, // 開啟調試模式
     appId: res.appId, // 必填,公眾號的唯一標識
     timestamp: res.timestamp, // 必填,生成簽名的時間戳
     nonceStr: res.noncestr, // 必填,生成簽名的隨機串
     signature: res.signature, // 必填,簽名,見附錄1
     jsApiList: [
        'onMenuShareAppMessage', // 獲取“分享給朋友”按鈕點擊狀態及自定義分享內容接口
        'onMenuShareTimeline' // 獲取“分享到朋友圈”按鈕點擊狀態及自定義分享內容接口
     ] // 必填,需要使用的JS接口列表,所有JS接口列表見附錄2
    })
 }).catch((error) => {
    console.log(error)
 })
 wx.ready((res) => {
    // 如果需要定制ready回調方法
    if (callback) {
     callback()
    }
 })
}

微信分享到朋友圈

初始化之后,我們接著往下寫,這里拿分享到朋友圈舉例。寫一個方法,用來調用微信的分享朋友圈。因為不同的頁面分享的內容不一樣,成功或者失敗后的回調函數也不同,所以我們這里做個簡單配置。傳一個參數。

// 接上面的代碼
/**
* [ShareTimeline 微信分享到朋友圈]
* @param {[type]} opstion [分享信息]
* @param {[type]} success [成功回調]
* @param {[type]} error   [失敗回調]
*/
 ShareTimeline (opstion) {
  wx.onMenuShareTimeline({
   title: opstion.title, // 分享標題
   link: opstion.link, // 分享鏈接
   imgUrl: opstion.imgUrl, // 分享圖標
   success () {
    // 用戶成功分享后執行的回調函數
    opstion.success()
   },
   cancel () {
    // 用戶取消分享后執行的回調函數
    opstion.error()
   }
 })
}

頁面中調用微信功能

通過以上代碼,我們封裝了一個簡單的微信JS-SDK功能,那么在頁面中如何調用這些封裝好的方法呢。首先我們編寫一個方法用來作為wx.ready中的callback,然后在通過配置opstion的方式,將自定義信息注入到之前封裝好的通用分享方法中。實現隨用隨調,靈活配置的微信功能。

//a.vue
import wxapi from '../mixins/wxapi.js'

export default {
 mixins: [wxapi],
 mounted () {
  this.wxRegister(this.wxRegCallback)
 },
 methods: {
  /**
  * [wxRegCallback 用于微信JS-SDK回調]
  */
  wxRegCallback () {
     this.wxShareTimeline()
  },
     /**
  * [wxShareTimeline 微信自定義分享到朋友圈]
  */
    wxShareTimeline () {
   let opstion = {
    title: '胡小呆&曹小萌的情侶博客', // 分享標題
    link: 'http://www.pvmy.icu',      // 分享鏈接
   imgUrl: 'http://www.pvmy.icu/wordpress/wp-content/themes/wordpress_thems/images/lib/logo.png'// 分享圖標
   success: function () {
      alert('分享成功')
   },
   error: function () {
       alert('分享失敗')
   }
  }
  // 將配置注入通用方法
  this.ShareTimeline(opstion)
  },
 }
}

微信授權

微信授權的功能其實我們前端只需要存儲好用戶的uid和token即可。驗證的邏輯一般都是后端那邊進行的。授權的方法同樣歸類為微信操作,所以代碼也封裝在wxapi.js中,可以參考如下代碼:(hostName是當前域名,因為開發,測試,生產的域名不一樣,所以做了變量配置)

 /**
 * [isWxAuth 微信授權]
 */
 isWxAuth () {
  let localUid = localStorage.getItem('localUid')
  let localToken = localStorage.getItem('localToken')
  if (!localToken) {
   let token = this.$route.query.token
   let uid = this.$route.query.uid
   if (token) {
    localStorage.setItem('localToken', token)
    localStorage.setItem('localUid', uid)
   } else {
    // 將url編碼后傳給后端,解決微信過濾Vue hash模式 #被過濾的問題
    var u = encodeURIComponent(window.location.href)
    window.location.href = hostName + '/wxpl/oauth?forwardUrl=' + u
   }
  }
 }

思路也很簡單,每次進入頁面的時候就會判斷本地存儲中是否有token,如果沒有,去url中查看是否帶有token參數,有的話存到本地。沒有的話將當前頁面地址編碼后傳給后端,進行授權。

但是這樣做,token過期后,頁面一直取過期的token,就會導致授權一直失敗。所以我們還需要在token過期之后,將舊的token從本地存儲中刪掉,更新為新的token。我是這么做的:(因為調用后端接口需要我將token傳給他們驗證是否過期,所以后端會返回一個字段告訴是否需要重新授權)

這里有一點需要注意: 就是如果當前url中帶著參數,比如www.pvmy.icu/#hello?uid=200&token=abcdefg這種形式,如果我們還是取window.localtion.href,授權的就是www.pvmy.icu/#hello?uid=200&token=abcdefg這個頁面,和www.pvmy.icu/#hello是不同的,出現的問題就是頁面一直在不斷的往url后面加uidtoken,一直跳授權,導致死循環。

所以我這里用域名 + 路徑 + vue的path來拼裝url,這樣就可以解決發送給后端的url錯誤的問題。

// 通用ajax方法中
...
 // 微信token是否過期 這里的字段是后端返回的,如果為true就說明token已經過期
 if (response.data.invalid_auth == 'true') {
  localStorage.removeItem('localToken')
  localStorage.removeItem('localUid')
  var u = encodeURIComponent(hostName + window.location.pathname + '#' + this.$route.path)
  window.location.href = hostName + '/wxpl/oauth?forwardUrl=' + u
 } else {
  resolve(response.data)
 }
...

踩坑分享

1.簽名驗證失敗

解決思路:(1)先查看是否是因為字母大小寫等原因造成的。(2)之后查看是否因為路由的變化導致簽名校驗失效。用小呆的這種方式可以避免因路由變化導致校驗失敗的問題。因為每次路由變化后都會重新生成簽名進行校驗。

2.分享出去的URL被微信插入其他字符

比如我分享的url是www.pvmy.icu/#hello,但是實際在微信中打開的鏈接是www.pvmy.icu?from=xxxxxxxx/#hello

解決思路:暫無。目前測試,加入微信的參數之后,頁面可以正常打開。

3.hash模式,微信授權會將url中的#過濾掉,導致授權的token和url不一致

解決思路:將url進行轉碼后在傳給后端,即可解決。

4.授權url錯誤導致的一直重復授權的死循環

解決思路: url不用window.location.href,采用拼裝方式處理

好啦,到這里這篇筆記就寫完了,如果對你有幫助,就給本文點個贊吧。如果能把博客收藏起來時不時轉轉,那就更好啦~

(PS:其實這篇文章應該昨天發布的,但是昨天寫到一半,就被產品插了其他事情進來,筆記沒保存,干別的事兒去了,結果下午測試過程中,chrome崩潰了…o(╥﹏╥)o,只好今天重新寫一遍了)