专栏首页前端开发随笔Vue实现微信授权登录

Vue实现微信授权登录

新建个文件wechatAuth.js 这个文件可以不用更改

const queryString = require('qs')
// 应用授权作用域,snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid),
// snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且,即使在未关注的情况下,只要用户授权,也能获取其信息)
const SCOPES = ['snsapi_base', 'snsapi_userinfo']

class VueWechatAuthPlugin {
  install(Vue, options) {
    let wechatAuth = this
    this.setAppId(options.appid)
    this.scope = SCOPES[options.scope ? 1 : 0]
    Vue.mixin({
      created() {
        this.$wechatAuth = wechatAuth
      },
    })
  }

  constructor() {
    this.appid = null
    this.redirectUri = null
    this.scope = null
    this._code = null
    this._redirectUri = null
  }

  static makeState() {
    return (
      Math.random()
      .toString(36)
      .substring(2, 15) +
      Math.random()
      .toString(36)
      .substring(2, 15)
    )
  }

  setAppId(appid) {
    this.appid = appid
  }

  set redirectUri(redirectUri) {
    this._redirectUri = encodeURIComponent(redirectUri)
  }

  get redirectUri() {
    return this._redirectUri
  }

  get state() {
    return localStorage.getItem('wechat_auth:state')
  }

  set state(state) {
    localStorage.setItem('wechat_auth:state', state)
  }

  get authUrl() {
    if (this.appid === null) {
      throw new Error('appid must not be null')
    }
    if (this.redirectUri === null) {
      throw new Error('redirect uri must not be null')
    }
    this.state = VueWechatAuthPlugin.makeState()
    return `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${this.appid}&redirect_uri=${
      this.redirectUri
    }&response_type=code&scope=${this.scope}&state=${this.state}#wechat_redirect`
  }


  returnFromWechat(redirectUri) {
    let parsedUrl = queryString.parse(redirectUri.split('?')[1])
    if (process.env.NODE_ENV === 'development') {
      this.state = null
      this._code = parsedUrl.code
    } else {
      if (this.state === null) {
        throw new Error("You did't set state")
      }
      if (parsedUrl.state.replace('#/', '') === this.state) {
        this.state = null
        this._code = parsedUrl.code
      } else {
        this.state = null
        throw new Error(`Wrong state: ${parsedUrl.state}`)
      }
    }
  }

  get code() {
    console.log('code', this._code)
    if (this._code === null) {
      throw new Error('Not get the code from wechat server!')
    }

    const code = this._code
    this._code = null
    return code
  }
}

const vueWechatAuthPlugin = new VueWechatAuthPlugin()
export default vueWechatAuthPlugin

在main.js里

import wechatAuth from './axios/wechatAuth'

//这里是配置微信公众号的appid
Vue.use(wechatAuth, {
  appid: "123",
  scope: 'snsapi_userinfo',
})

在router里的js里

import Vue from 'vue'
import Router from 'vue-router'
import wechatAuth from '../axios/wechatAuth'
import axios from 'axios'
Vue.use(Router)
Vue.prototype.$axios = axios;
import {
  Dialog
} from "vant";

在路由里配置路由守卫

//截取code
function getCode() {
  var url = location.search;
  var code = "";
  if (url.indexOf("?") != -1) {
    var split = url.split("?code=")
    code = split[1].split("&")[0]
  }
  return code;
}

// 获取sign
function getSign(next) {
  let theCode = getCode();
  if (theCode) {
    var formData = new FormData();
    formData.append("code", theCode);
    axios({
      method: "post",
      url: "http:api",
      data: formData
    }).then(res => {
      if (res.data.status == 1) {
        localStorage.setItem("wx_sign", res.data.data.sign);
        let realUrl = window.location.href.split("?")[0];
        window.location.href = realUrl;
        next()
      } else {
        Dialog.alert({
          title: '提示',
          message: res.data.msg,
        }).then(() => {
          WeixinJSBridge.call('closeWindow')
        })
      }
    });
  } else if (localStorage.getItem("wx_sign") == null) {
    wechatAuth.redirectUri = window.location.href
    window.location.href = wechatAuth.authUrl
  } else {
    next()
  }
}

router.beforeEach((to, from, next) => {
  window.document.title = to.meta.title;
  if (process.env.NODE_ENV == "production") {
    getSign(next)
  } else {
    next();
  }
});

github拉取完整项目

https://github.com/skywalk94/vueWechatH5

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Vue页面中引用自定义组件

    比如我想引用一个外部的头部导航的组件,因为这个导航在很多地方都用到,避免每个页面都写一遍 首先 我先在components这里创建一个navmenu的组件

    任我行RQ
  • ElementUI引入到vue项目开发

    假设我们已经创建了vue项目了 这里是Element官方文档https://element.eleme.cn/#/zh-CN/component/instal...

    任我行RQ
  • vue-cropper裁剪图片

    任我行RQ
  • 【笔记】《计算机图形学》(7)——观察

    这系列的笔记来自著名的图形学虎书《Fundamentals of Computer Graphics》,这里我为了保证与最新的技术接轨看的是英文第五版,而没有选...

    ZifengHuang
  • 当我们讨论性能测试时,我们在说什么?

    说起性能测试,大家会想到哪些词?录制脚本、模拟高并发?性能需求分析、业务流程梳理?监控资源耗用、性能瓶颈定位?优化代码处理逻辑、提升服务器配置?但这真的是性能测...

    写博客的老张
  • 基于微信社交链的读书APP——微信读书,用户体验5要素简要分析

    2 . 产品定位 从产品的slogan,让阅读不再孤独,表明产品从社交链切入阅读这一块,和市面其他阅读产品定位不一样,形成产品差异化竞争。

    葆宁
  • 加固你的服务器,防止SSH攻击

    Secure Shell(安全外壳协议,简称SSH)是一种加密的网络传输协议,可在不安全的网络中为网络服务提供安全的传输环境。SSH通过在网络中创建安全隧道来实...

    苏子晨
  • 【目标检测系列】个人整理目标检测框架yolo v1深入剖析

    faster-RCNN在目标检测精度上已经能够达到一个很高的水准,但是作为RCNN系列的最巅峰,它提出了RPN网络产生推荐性区域,但是它依旧有着一些缺点,这些区...

    小草AI
  • 浏览器中的跨域问题与 CORS

    跨域,这或许是前端面试中最常碰到的问题了,大概因为跨域问题是浏览器环境中的特有问题,而且随处可见,如同蚊子不仅盯你肉而且处处围着你转让你心烦。「你看,在服务器发...

    山月
  • 浏览器中的跨域问题与 CORS

    跨域,这或许是前端面试中最常碰到的问题了,大概因为跨域问题是浏览器环境中的特有问题,而且随处可见,如同蚊子不仅盯你肉而且处处围着你转让你心烦。「你看,在服务器发...

    夜尽天明

扫码关注云+社区

领取腾讯云代金券