背景
vue先後端分離開發微信受權
2018-08-14更新
時隔四個月第一次更新,由於項目重構有一次接觸到了微信受權,思路已經比原來清晰的多了,將從新修改一下整個文章php
場景
app將商品分享到微信朋友圈或者分享給微信好友,用戶點擊頁面時進行微信受權登錄,獲取用戶信息。
問題:沒有固定的h5應用首頁,回調不能到index。受權後重定向url帶參數而且很長css
本人愚鈍,開發過程當中,嘗試過不少方法,踩坑不足以形容個人心情,能夠說每一次都是一次跳井的體驗啊。前端
1.一開始嘗試的方式是前端請求微信鏈接,返回code,而後code做爲再去請求後臺接口獲取token,後面看到別人的博客說這個方法很差,最好就是直接請求後臺接口,而後後臺返回url作跳轉,因此就採用了最傳統的方法,後臺返回url,前臺跳轉。vue
2.這個時候就出現一個問題,微信受權要跳跳跳,最終想回到第一次點進來時候的連接就蛋疼了,從網上查了一下解決方法,將連接自己做爲redirect_uri參數,大概就是這個樣子java
https://open.weixin.qq.com/connect/oauth2/authorizeappid=xxxxxxxxxxxxxxxxxx&redirect_uri=*www.admin?http://www.xxx.com/h5/product*&response_type=code&scope=snsapi_userinfo&state=STATE&connect_redirect=1#wechat_redirect
然而咱們的前臺連接是這個鬼樣子的,自己帶參數,並且超長,what?微信可能不會接受我長這麼醜。/(ㄒoㄒ)/~~vuex
http://www.xxx.com/h5/product?id=6RedfM5O4xeyl0AmOwmyipkHr8AQCv-hYXZVAIFTwDXOsWSKqgu3VaCmaKSerBnacvWuzO3Zwdf8y%2F2K2lvqkluV6Ane4LCAKyPU2tPAPj%2FMF6F6xkzp27GqqpNya7HbdEA34qGQJvHIA9tlIMkeEWid1112b8oZuP3FQBwU%2F%2FMaSrovzQP6LlzWamyPnv0vMizu8uh0ItpJOQUV1m%2FtemF3U9KuHo8rXCw%3D
最終放棄了這個方案後端
3.考慮如何重定向個人前臺地址,而且獲取tokenapi
接下來就是我如今用的方法,bug還有不少,先分享一下個人方法,後期優化或有更好的方法再作修改
在main.js中路由全局鉤子判斷本地是否是有user_token,也就是微信受權後返回的token,若是沒有token,而且當前的路由不是author(專門爲了受權而生的頁面),那就保存當前的url,好比www.xxx.com/h5/product?id=6RedfM5O4xeyl0AmOwm,而後進入author。那若是本地有token,就是用戶以前受權拿到過token而且vuex裏沒有用戶信息,那我就獲取用戶信息並保存在vuex中,這裏遇到一個問題就是token會出現過時的狀況,那我就刪除了本地的user_token,window.localStorage.removeItem("user_token");刷新頁面 router.go(0);這個時候就從新走了一遍若是沒有token的狀況。
初版方法微信
router.beforeEach((to, from, next) => { // 第一次進入項目 let token = window.localStorage.getItem("user_token"); if (!token && to.path != "/author") { window.localStorage.setItem("beforeLoginUrl", to.fullPath); // 保存用戶進入的url next("/author"); return false; } else if (token && !store.getters.userInfo) { //獲取用戶信息接口 store .dispatch("GetUserInfo", { user_token: token }) .catch(err => { window.localStorage.removeItem("user_token"); router.go(0); return false; }); } next(); });
2018-08-14第二版方法
不一樣的地方是將跳轉判斷從author.vue裏拿出來放這裏了邏輯其實很簡單,有token獲取信息,沒token跳轉受權app
router.beforeEach((to, from, next) => { const token = window.localStorage.getItem('user_token') if (token) { if (to.path === '/author') { next({ path: '/' }) } else { store .dispatch('GetUserInfo', { user_token: token }) .then(res => { // 拉取用戶信息 next() }) } } else { if (to.path !== '/author') { // 保存用戶進入的url if (to.path === '/shop' || to.path === '/product') { window.localStorage.setItem('authUrl', to.fullPath) // 保存用戶進入的url } store.dispatch('GetAuthUrl').then(res => { // 此處返回的是後臺拼接的微信受權地址,前臺也是能夠拼接的,跳轉到微信受權 window.location.href = res.data.url //https://open.weixin.qq.com/connect/oauth2/authorize?appid=aaaaa&redirect_uri=後端java或php地址&response_type=code&scope=snsapi_userinfo&state=STATE&connect_redirect=1#wechat_redirect }) } else { next() } } })
下面就是進入author.vue的邏輯,第一次進入author, www.xxxx.com/h5/author,判斷連接有沒有token參數,若是沒有就跳微信受權,而後後臺會重定向回來並攜帶token,如: www.xxxx.com/h5/author?token=xxxxxxxxx&msg=200
初版
<template> <div> 受權中。。。 </div> </template> <script> import { getWxAuth } from '@/service/getData' import { GetQueryString } from '@/utils/mixin'; export default { data() { return { token: '', }; }, computed: { }, created() { this.token = window.localStorage.getItem("user_token"); //判斷當前的url有沒有token參數,若是不存在那就跳轉到微信受權的url //就是前面說的ReturnGetCodeUrl方法 if (!GetQueryString("token")) { this.ReturnGetCodeUrl(); } else { //若是有token,如http://www.xxxx.com/h5/author?token=xxxxxxxxx&msg=200,這裏的參數就是後臺重定向到前臺http://www.xxxx.com/h5/author,並攜帶的參數。這樣就能夠拿到咱們想要的token了 //判斷一下後臺返回的狀態碼msg,由於可能出現微信拿不到token的狀況 let msg = GetQueryString("msg") if (msg = 200) { this.token = GetQueryString("token"); //存儲token到本地 window.localStorage.setItem("user_token", this.token); //獲取beforeLoginUrl,咱們的前端頁面 let url = window.localStorage.getItem("beforeLoginUrl"); //跳轉 this.$router.push(url); //刪除本地beforeLoginUrl removeLocalStorage("beforeLoginUrl"); }else{ //msg不是200的狀況,可能跳到404的錯誤頁面 } } }, methods: { async ReturnGetCodeUrl() { let { data } = await getWxAuth({}); if (data.status == 200) { window.location.href = data.url; } }, }, watch: {}, components: {}, mounted: function () {} } </script> <style lang='scss' scoped> </style>
GetQueryString方法
mixin.js
export const GetQueryString = name => { var url = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"); var newUrl = window.location.search.substr(1).match(url); if (newUrl != null) { return unescape(newUrl[2]); } else { return false; } };
第二版
只用來後臺拿到參數返回到author頁面後的攜帶的參數若是獲取成功則跳轉到受權以前保存的url若是失敗提示用戶關閉網頁從新受權,另外有一點值得注意,微信名裏有特殊字符的須要轉碼要不受權會失敗
<!-- author --> <template> <div> 受權中。。。 </div> </template> <script> import { mapGetters } from 'vuex' import { Toast } from 'mint-ui' import { GetQueryString, setLocalStorage, getLocalStorage, removeLocalStorage } from '@/utils' export default { data() { return { token: '' } }, computed: { ...mapGetters([ 'userInfo' ]) }, created() { const wxtoken = GetQueryString('token') const code = GetQueryString('msg') if (wxtoken && Number(code) === 200) { setLocalStorage('user_token', wxtoken) const historyUrl = getLocalStorage('authUrl') this.$router.replace(historyUrl) // removeLocalStorage('authUrl') } else { // 沒有拿到後臺訪問微信返回的token Toast('受權失敗請關閉網頁從新進入') removeLocalStorage('share_token') removeLocalStorage('authUrl') } } } </script> <style lang='scss' scoped> </style>
整個過程是能夠實現受權,可是以爲代碼寫得很差,之後的開發中但願可以有更優的方法。但願能和你們交流學習。2018-08-14更新,總結一下,第二次開發流程作了簡化,可是整個思路仍是同樣,我以前想到過另一種方法,是將個人那串長參數先保存在本地,而後去受權的時候就可讓後臺幫我跳轉到固定頁面如/product我在從本地拿參數解析,這個方法應該也是可行的,下次嘗試後更新