[记录]vue3实现PC项目微信扫码进行账号注册/登录(内嵌二维码)

记录 "PC端采用微信扫码,进行账号注册/登录功能" 的实现过程(仅前端)

使用场景:在网站顶部导航栏的登录入口,中实现微信扫码登录功能

开发参考文档:微信官方文档(微信登录功能-网站应用微信登录开发指南)

微信提供的扫码方式有两种,分别是:

  • 跳转二维码扫描页面
  • 内嵌式二维码(本记录选用的扫码方式)

根据文档我们可以知道关于扫码授权的模式整体流程为:

1. 第三方发起微信授权登录请求,微信用户允许授权第三方应用后,微信会拉起应用或重定向到第三方网站,并且带上授权临时票据 code 参数;

2. 通过 code 参数加上 AppID 和AppSecret等,通过 API 换取access_token;

3. 通过access_token进行接口调用,获取用户基本数据资源或帮助用户实现基本操作。

通过 微信开放平台 申请账号拿到appId和appSecret

页面中先引入如下 JS 文件,若网站不支持https可把前缀改为http

<script src="https://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js"></script>

创建登录组件:login.vue

<template>
  <div>
    <!-- 登录方式tab(非二维码登录方式) -->
    <div class="login-type" v-if="!showQR">
        ...
    </div>
    <!-- 二维码登录 -->
    <div id="login_container" v-show="showQR"></div>
  </div>
</template>

<script>
import {
  reactive,
  watch,
  toRefs,
  getCurrentInstance,
} from 'vue'
export default {
  props: {},
  setup(props, context) {
    const { appContext } = getCurrentInstance()
    const { $http } = appContext.config.globalProperties
    const state = reactive({
      showQR: true,
      loginType: 'QRcode',
      showReg: false,
      showLogin: true,
    })
    watch(
      () => state.loginType,
      newVal=> {
          state.showLogin = false
          state.showQR = false
          state.showReg = false
          switch(newVal){
            case 'QRcode':
              state.showQR = true
              break; 
            case 'register':
              state.showReg = true
              break;
            default: 
              state.showLogin = true
          }
      }
    )
    // 微信登录
    const wechatLogin = async () => {
      // 从后端获取appid以及重定向地址
      let { data, status } = await $http.get('XXX') 
      if (!status == 200) return
      // 官方文档提供的实例对象,具体参数说明可往下看
      let state = parseInt(new Date().getTime() / 1000)
      let obj = new WxLogin({
        self_redirect: false,
        id: 'login_container',
        appid: data.appid,
        scope: 'snsapi_login',
        redirect_uri: data.redirect_url, // 这里跳的是扫码成功后,账户操作的地址
        state: state,
        style: 'black',
        href: '',
      })
      // 自己封装的sessionStorage方法
      sessionStorage.setItem('beforeLogin', window.location.href) // 记录当前操作页面,以备后面跳转
      sessionStorage.setItem('QRcode', 'login') // 记录当前扫码是注册还是登录
      state.loginType = 'QRcode'
    }
    return {
      ...toRefs(state),
      wechatLogin
    }
  }
}
</script>

扫码成功后,将会自动跳转到自定义的重定向地址,并能在地址上看到我们的code

https://www.xxx.com?code=0719adHa1IuEpD0NHCHa1MQtv30&state=1655733828


接着,我们就可以根据code,用文档给出的API,获取所需的数据

https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

API相关参数说明

 返回样例:

// 正确返回样例
{ 
"access_token":"ACCESS_TOKEN", 
"expires_in":7200, 
"refresh_token":"REFRESH_TOKEN",
"openid":"OPENID", 
"scope":"SCOPE",
"unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
}

// 错误返回样例
{"errcode":40029,"errmsg":"invalid code"}

 正确的返回参数说明:


在本项目我们获取code后,我们需要通过code去判断这个微信是否已经绑定账号,我们定向到操作页面,把code交给后端判断此code是否已绑定账户,并根据判断结果进行不同操作:

<template>
  <el-skeleton class="wxLogin-skeleton" :loading="!unionid" animated>
    <template #template>
      <el-skeleton :rows="2" animated />
    </template>
    <template #default>
      <el-card shadow="never" v-show="isLogin && !hasBind">
        <!-- 绑定信息表格 start -->
        ...
        <!-- 绑定信息表格 end -->

        <!-- 提交按钮 -->
        <el-row type="flex" class="row">
          <el-button class="submit-btn" @click="wxL">绑定账号</el-button>
        </el-row>
      </el-card>
      <el-card shadow="never" v-show="!isLogin || hasBind">
        <div class="waiting-box">操作成功,正在跳转,请稍等</div>
      </el-card>
    </template>
  </el-skeleton>
</template>
<script>
import {
  reactive,
  toRefs,
  getCurrentInstance
} from 'vue'
export default {
  components: {},
  setup(props, context) {
    const { appContext } = getCurrentInstance()
    const { $g, $router, $http, $message } = appContext.config.globalProperties
    const state = reactive({
      unionid: null,
      isLogin: sessionStorage.getItem('QRcode') == 'login',
      hasBind: false
    })
    // 设置用户登录信息
    const setInfo = (data, duration = 3000) => {
      let temp = data.user
      ...
      sessionStorage.removeItem('QRcode') // 移除QRcode标志
    }
    // 跳转登录页面
    const backPage = () => {
      const beforeLogin = sessionStorage.getItem('beforeLogin')
      sessionStorage.removeItem('beforeLogin')
      window.location.replace(beforeLogin)
    }
    // 第一次微信快捷登录,创建并绑定手机账号
    const wxL = async () => {
      if (!state.unionid) return $message.warning('扫码失效,请重新扫码登录')
      let { data, status } = await $http.post('xxxxx', {
        unionid: state.unionid,
        ...
      })
      if (status != 200) return
      setInfo(data)
      $message({
        message: '登录绑定成功,正在跳转,请稍等',
        type: 'success',
        duration: 1000,
        onClose: () => {
          backPage()
        }
      })
    }
    // 已有账号绑定微信
    const wxB = async () => {
      let { data, status } = await $http.post('xxxx', {
        unionid: state.unionid,
        ...
      })
      if (status != 200) return
      setInfo(data)
      $message({
        message: '绑定成功,正在跳转,请稍等',
        type: 'success',
        duration: 1000,
        onClose: () => {
          backPage()
        }
      })
    }
    // 获取unionid
    const getUnionid = async () => {
      let { data, status } = await $http.get('xxx', {
        code: $router.currentRoute.value.query.code
      })
      if (status != 200) return
      // 从未绑定
      if (!data.state) {
        state.unionid = data.unionid
        if (state.isLogin) return
        return wxB() //已有账号绑定微信       
      }
      state.hasBind = true
      setInfo(data)
      $message({
        message: '登录成功,正在跳转,请稍等',
        type: 'success',
        duration: 1000,
        onClose: () => {
          backPage()
        }
      })
    }
    getUnionid()
    return {
      ...toRefs(state),
      setInfo,
      backPage,
      getUnionid,
      wxL,
      wxB
    }
  }
}
</script>
  • 3
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在 Vue PC端页面实现微信扫码支付,你需要使用微信支付的 Native 支付模式。具体步骤如下: 1. 向服务器获取支付二维码链接:你需要向服务器发送请求,获取支付二维码的链接。 2. 生成支付二维码:你可以使用第三方库 `qrcode` 来生成支付二维码,并将生成的二维码显示在页面上。 ```javascript import QRCode from 'qrcode' export default { data() { return { qrCodeUrl: '' // 存储二维码链接 } }, mounted() { this.getPayQrCode() }, methods: { getPayQrCode() { // 向服务器获取支付二维码链接 axios.get('/api/getPayQrCode') .then(res => { const qrCodeUrl = res.data.qrCodeUrl // 生成二维码 QRCode.toDataURL(qrCodeUrl, { errorCorrectionLevel: 'H', margin: 1 }) .then(dataUrl => { this.qrCodeUrl = dataUrl }) .catch(err => { console.error(err) }) }) .catch(err => { console.error(err) }) } } } ``` 以上代码中,`getPayQrCode` 方法向服务器获取支付二维码链接,然后使用 `qrcode` 库生成二维码,并将二维码链接存储在 `qrCodeUrl` 变量中,你可以将该变量绑定到一个 `img` 标签上来显示二维码。 3. 轮询支付状态:使用轮询的方式来查询支付状态,如果支付成功,则弹出支付成功的提示框。 ```javascript checkPayStatus() { setInterval(() => { axios.get('/api/checkPayStatus') .then(res => { const status = res.data.status if (status === 'success') { // 支付成功 this.showPaySuccess() } }) .catch(err => { console.error(err) }) }, 3000) }, showPaySuccess() { // 弹出支付成功的提示框 alert('支付成功!') } ``` 以上代码中,`checkPayStatus` 方法使用轮询的方式查询支付状态,每隔 3 秒发送一次请求,如果支付成功,则调用 `showPaySuccess` 方法弹出支付成功的提示框。 4. 调起微信扫码支付界面:在支付成功后,你需要调用微信扫码支付界面,在微信扫描支付二维码后完成支付。 ```javascript startNativePay() { const qrCodeUrl = '支付二维码的链接' const userAgent = window.navigator.userAgent.toLowerCase() if (userAgent.indexOf('micromessenger') === -1) { // 不在微信中,跳转到支付链接 window.location.href = qrCodeUrl } else { // 在微信中,调起微信扫码支付界面 window.location.href = 'weixin://wxpay/bizpayurl?url=' + encodeURIComponent(qrCodeUrl) this.checkPayStatus() } } ``` 以上代码中,`startNativePay` 方法判断当前是否在微信中,如果在微信中,则使用 `weixin://wxpay/bizpayurl?url=` 协议调起微信扫码支付界面,并将支付二维码的链接作为参数传递给微信支付界面。支付成功后,使用轮询的方式查询支付状态,如果支付成功,则弹出支付成功的提示框。 希望这能帮助到你。如果你有其他问题,请随时提出。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值