vue 微信授权解决方案

背景

vue前后端分离开发微信授权
2018-08-14更新
时隔四个月第一次更新,因为项目重构有一次接触到了微信授权,思路已经比原来清晰的多了,将重新修改一下整个文章

场景

app将商品分享到微信朋友圈或者分享给微信好友,用户点击页面时进行微信授权登陆,获取用户信息。
问题:没有固定的h5应用首页,回调不能到index。授权后重定向url带参数并且很长

本人愚钝,开发过程中,尝试过很多方法,踩坑不足以形容我的心情,可以说每一次都是一次跳井的体验啊。

1.一开始尝试的方式是前端请求微信连接,返回code,然后code作为再去请求后台接口获取token,后面看到别人的博客说这个方法不好,最好就是直接请求后台接口,然后后台返回url做跳转,所以就采用了最传统的方法,后台返回url,前台跳转。

2.这个时候就出现一个问题,微信授权要跳跳跳,最终想回到第一次点进来时候的链接就蛋疼了,从网上查了一下解决方法,将链接本身作为redirect_uri参数,大概就是这个样子

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ㄒ)/~~

 http://www.xxx.com/h5/product?id=6RedfM5O4xeyl0AmOwmyipkHr8AQCv-hYXZVAIFTwDXOsWSKqgu3VaCmaKSerBnacvWuzO3Zwdf8y%2F2K2lvqkluV6Ane4LCAKyPU2tPAPj%2FMF6F6xkzp27GqqpNya7HbdEA34qGQJvHIA9tlIMkeEWid1112b8oZuP3FQBwU%2F%2FMaSrovzQP6LlzWamyPnv0vMizu8uh0ItpJOQUV1m%2FtemF3U9KuHo8rXCw%3D

最终放弃了这个方案

3.考虑如何重定向我的前台地址,并且获取token

接下来就是我现在用的方法,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跳转授权

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

第一版

vue 微信授权解决方案
 <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我在从本地拿参数解析,这个方法应该也是可行的,下次尝试后更新

相关文章