微信公衆號開發: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'})
      }
    }

 

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