单页面应用微信分享跳坑指南
前言
最近在開發的時候遇到了一個微信分享的bug,就是無論你在哪個路徑下的頁面,發送給朋友后點開都只會跳到項目的首頁。本來微信分享這個只算是一個小功能,也很好解決,但由于項目的特殊性,使得在這個bug解決起來并沒有那么順手,所以記錄一下備以后翻閱。
坑點
-
Vue單頁面應用,前端通過Hash控制路由——iOS在微信中不能正常地改變瀏覽器的hash值,分享出去的頁面地址被莫名其妙地添加了參數。
-
微信的安全策略——由于存在js安全域名限制,使得在本地調試更難。
-
jssdk配置簽名。
跳坑方法
分享地址被奇怪的被帶上了參數
在傳統開發中,路由通常都是在后端完成的,但是在Vue單頁面中,都是通過控制history interface來控制頁面之間的跳轉,在我們的項目中我們使用hash的方式,但是在分享給朋友后卻發現分享地址被加上了一些參數,比如:
我分享出去的地址是: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 earlysetupListeners () {const router = this.routerconst expectScroll = router.options.scrollBehaviorconst supportsScroll = supportsPushState && expectScrollif (supportsScroll) {setupScroll()}window.addEventListener(supportsPushState ? 'popstate' : 'hashchange', () => {const current = this.currentif (!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往下翻點會找到這個方法的實現:
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.hrefconst index = href.indexOf('#')return index === -1 ? '' : href.slice(index + 1) } 復制代碼我們可以清楚地知道,當這條地址market.lenkuntang.cn/?from=singlemessage#/home經過getHash之后會直接返回#號后面的字符串,也就是 /home,所以可以得出是不會對我們分享的功能有影響的。
iOS在微信環境中瀏覽器地址不變
在Vue-router實現前端控制路由都是通過HTML5 新增的History Interface接口來控制頁面之間的跳轉的,在跳轉的同時通過修改window中loaction的hash屬性反映回瀏覽器的地址,但是當遇到iOS時卻意外地發現這個hash屬性一直沒有被改變,導致每次分享出去的地址都是首頁,在網上一查發現這原來是個通病,解決的方法就是引入微信的JsSDK來手動控制分享的地址。
引入JsSDK所帶來的問題
在引入了JsSDK后,首先要對它進行配置,相關配置項如下:
wx.config({debug: true, // 開啟調試模式,調用的所有api的返回值會在客戶端alert出來,若要查看傳入的參數,可以在pc端打開,參數信息會通過log打出,僅在pc端時才會打印。appId: '', // 必填,公眾號的唯一標識timestamp: , // 必填,生成簽名的時間戳nonceStr: '', // 必填,生成簽名的隨機串signature: '',// 必填,簽名jsApiList: [] // 必填,需要使用的JS接口列表 }); 復制代碼說明一下這里的參數分別從哪里來,appId是從微信公眾號里獲取的,timestamp和nonceStr還有signature是從服務器中返回的。jsApiList可以在所有JS接口列表中找到。
注:timestamp和nonceStr其實是可以在前端生成然后傳給服務器再參與簽名的計算的,但一般在考慮到安全原因,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…
得到簽名后再把timestamp,nonceStr和signature傳回給前端進行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的使用有了大概的認識和了解,雖然其中也遇到不少的坑和麻煩的地方,但是既然問題出現就只能盡量地去簡化問題再解決它。
總結
以上是生活随笔為你收集整理的单页面应用微信分享跳坑指南的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: json如何把键名作为变量?
- 下一篇: java根据经纬度坐标计算两点的距离算法