微信公众号开发:VSCode+Vue+vux 微信授权解决方案

业务需求:

使用Vue+vux开发微信公众号页面需要微信授权登录,再通过后台换取openId,公众号页面中有些页面不需要登录,有些页面不需要登录,在用户从普通页面访问需登录页面时,自动跳转至登录页面,授权后继续登录前的操作;

解决方案

*前提:微信开发环境、后端配置均已完成

解决思路

  1. 在main.js中添加路由守卫,路由跳转时检测是否已登录,已登录则通过,未登录则拉起微信登录并记录当前要访问的页面和参数,存放到localStorage中;
  2. 把根路径映射到微信登录成功后要跳转的页面,接收code;
  3. 登录页面接收到code后,转发给自己的后台服务器,让它换取openId和token
  4. 把后台返回的openid和token存起来,把登录前的操作从localStorage取出来,继续跳转;

解决问题

前端代码------------------------------->>>>

const ServerAPI = {
  host: "https://www.abc.com", //外网可访问的域名
  port: 80, //外网可访问端口
  name: "webapp",//后台导出war包到Tomcat webapp目录下的app名
  imgRoot: 'static',//后台图片存放根目录
  hostPort: function () {
    // return this.host + ":" + this.port;
    return this.host
  }
};

const API = {
  APP_LIST: "xxx/xxxxxx",
  G_APP_DETAIL: "xxx/xxxxxxxxx",
  G_OPEN_ID:"xxx/xxxx",
  CREATE_ORDER:"xx/xxxx",
  CREATE_PRE_ORDER:"xxx/xxxx",
};
//组装访问后台API的封装
const assembleAPI = function (api, ...params) {
  let url = ServerAPI.hostPort();
  if (ServerAPI.name.length >= 1) {
    url = url + "/" + ServerAPI.name;
  }

  url = url + "/" + api;
  if (params.length > 0) {
    for (let i = 0; i < params.length; i++) {
      let p = params[i];
    if (i === 0) {
        url = url + "?" + p.n + "=" + p.v;
      } else {
        url = url + "&" + p.n + "=" + p.v;
      }
    }
  }
  return url;
};
const assembleImageAPI = function (imageUri) {
  return ServerAPI.hostPort() + "/" + imageUri;
};

const assembleImageAPIFromServer = function (imageUri) {
  let url = ServerAPI.hostPort();
  if (ServerAPI.name.length >= 1) {
    url = url + "/" + ServerAPI.name;
  }
  if (ServerAPI.imgRoot.length >= 1) {
    url = url + "/" + ServerAPI.imgRoot;
  }

  return url + "/" + imageUri;
};

export default {
  API,
  assembleAPI,
  assembleImageAPI,
  assembleImageAPIFromServer
}
  • 路由配置如下:
 routes: [
    {
      path: '/',
      name: 'login',
      component: Login,
      meta: {
        title: "授权跳转中...",
        keepAlive: true,
        refreshPage: false,
        skipAuth: true,//跳过验证
      }
    }, {
      path: '/home',
      name: 'home',
      component: Home,
      meta: {
        title: "产品列表",
        keepAlive: true,
        refreshPage: false,
        skipAuth: true,
      }
    },
    //...省略
    ]

* 为什么要把根路径映射到登录页面:微信获取code回调到指定地址,如果映射到其他地址会导致微信回调时地址错误等问题 暂时没有找到其他解决办法;

  • 路由守卫配置:拦截页面路由跳转 main.js
/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  store,
  components: {App},
  template: '<App/>'
});

//注册VUX组件
Vue.component('x-header', XHeader);
Vue.component('tabbar', Tabbar);
Vue.component('tabbar-item', TabbarItem);

let that = this;
router.beforeEach((to, from, , next) => {
  //提高用户体验 减少卡顿 每个页面进入时均弹出加载提示
  utils.LoadingDialogUtil.showLoading(store, '数据加载中...');
  store.commit('referRouterStatus', {to: to});
  if (!WXManager.Configure.NEED_AUTH) {//调试页面时用 可忽略
    next();
    return;
  }
  const token = localStorage.getItem(const_key.KEY.TOKEN);

  let openid = router.app.$store.state.user.openid;
    //这里只检查openid
  if (!openid) {
    if (to.meta.hasOwnProperty('skipAuth') && to.meta.skipAuth) {
      next();
    } else {
     //当前页url与参数放入缓存
      let tempRouter = {to: to.name, from: from.path, params: to.params};
      //把操作信息格式化成json字符串存到localStorage
      localStorage.setItem(const_key.KEY.TEMP_ROUTER, JSON.stringify(tempRouter));
      let authUrl = WXManager.g_codeUrl();
      //重定向至授权地址
      window.location.href = authUrl;
    }
  } else {
    next()
  }
});

* 这里经过多次尝试发现: 不能把要访问的路由信息存放带store中,微信获取code成功回调后store存的路由信息会丢失,不知道为啥;

  • 获取openid组件 Login.vue(只贴script代码):
import ServerAPI from "../common/ServerAPI";
  import utils from "../common/utils";
  import CONST_KEY from "../common/CONST_KEY";

  export default {
    name: "Login",
    components: {},
    data() {
      return {
        msg: "正在获取code"
      }
    },
    created() {
      utils.LoadingDialogUtil.hideLoading(this.$store);
      const code = this.getUrlParams('code'); // 截取code
      const uri = localStorage.getItem("now_url");
      if (code) {
        //带有code
        let h = window.location.href;
        let hArr = h.split('?');
        let url = hArr[0];
        url = url + '#' + uri;
        this.msg = "正在请求微信授权...";
         //获取用户信息
        let openIdUrl = ServerAPI.assembleAPI(ServerAPI.API.G_OPEN_ID, {n: "code", v: code}, {n: "state", v: "y"});
        this.axios.get(openIdUrl).then(response => {
          let res = response.data;
          if (res.status === 200) {let user = res.data;
            localStorage.setItem(CONST_KEY.KEY.OPEN_ID, user.openid);
            this.$store.state.user.openid = user.openid;
            this.msg = "登录成功,正在为您定向到目标页面...";
            let tempRouter = localStorage.getItem(CONST_KEY.KEY.TEMP_ROUTER);
            tempRouter  = JSON.parse(tempRouter);
            //登录成功均跳转到首页
            // this.$router.push({name: 'home'});
            //跳转至原页面
            this.$router.push({name: tempRouter.to, params: tempRouter.params});
          } else {
            this.msg = res.msg;
          }
           }).catch(err => {
          console.error(err);
        })
      } else {
        this.msg = "获取微信授权失败";
        this.$router.push({name: 'home'})
      }
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章