mpVue 微信小程序授权登录流程(即登录鉴权流程)及获取手机号一键登录教程(getPhoneNumber使用)

2,628 阅读2分钟

前言

微信小程序登录鉴权流程如下:

wx.getUserProfilewx.getUserInfo接口被收回了,都不能弹出授权窗口,只能使用头像昵称填写能力去获取微信用户信息。

在鉴权页面如下操作

1、在onShow中调用微信登录wx.login获取到唯一的code(用来获取openid);

2、根据wx.login获取的code调用后台接口来获取openid;

3、根据获取openid调用后台接口获取token是否存在token:有token进入首页,没有则返回登录页面以下将讲解如何使用微信绑定的手机号码一键登录小程序)。

最终效果

在这里插入图片描述

鉴权流程如下(鉴权页面:auth.vue):

1、在onShow中调用微信登录wx.login获取到唯一的code

onShow() {
    // 调用微信登录wx.login
    this.logining()
  },
methods: {
    logining() {
      wx.showLoading({
        title: '登录微信用户',
        mask: true
      })
      wx.login({
        success: (res) => {
          if (res.code) {
            wx.hideLoading()
            this.code = res.code
            // console.log('wx.login获得code成功', res)
            // vuex中的openId/unionId若存在就直接调用获取token接口
            if (this.openId) {
              this.getAccessToken(this.openId)
            } else {
              this.getOpenId({ code: this.code })
            }
          } else {
            console.log('获取用户登录态失败!' + res.errMsg)
          }
        },
        fail(err) {
          wx.hideLoading()
          wx.showToast({
            title: 'wx.login失败' + err,
            icon: 'none',
            duration: 1000
          })
        }
      })
    },
 }

2、根据wx.login获取的code调用后台接口来获取openid

methods: {
 // 获取openid
    async getOpenId(parameter) {
      wx.showLoading({
        title: '获取openId',
        mask: true
      })
      const res = await this.$http('getOpenId', parameter)
      console.log('获取openId', res)
      wx.hideLoading()
      if (res.success) {
        // 生成唯一值
        this.setOpenId(res.data.openid)
        // console.log('获取openId---值', res.data.openid)
        this.getAccessToken(res.data.openid)
      }
    }
  }

3、根据获取openid调用后台接口获取token

methods: {
 // 获取token
   async getAccessToken(openId) {
      const res = await this.$http('getAccessToken', { openid: openId })
      // console.log('获取token', res)
      if (res.success) {
        if (res.data) {
          this.isShowPhone = false
          this.setToken(res.data)
          this.$reLaunch('/pages/tabbarPage/main')
        } else {
         // 是否显示 一键登录按钮
          this.isShowPhone = true
        }
      }
    },

如何使用微信绑定的手机号码实现一键登录小程序

1、微信小程序开发文档地址

2、步骤及注意事项:

1、因为需要用户主动触发才能发起获取手机号接口,所以该功能不由 API 来调用,需用 button 组件的点击来触发。

2、需要将button组件 open-type 的值设置为 getPhoneNumber,当用户点击并允许之后,可以通过 bindgetphonenumber 事件回调获取到动态令牌code,根据code调用phonenumber.getPhoneNumber接口,消费code来换取用户手机号。每个code有效期为5分钟,且只能消费一次。

注:getPhoneNumber 返回的 codewx.login 返回的 code 作用是不一样的,不能混用。

3、页面使用

<template>
  <div class="auth flex-box flex-ver flex-col">
    <button
      class="btn flex-box flex-ver"
      v-if="isShowPhone"
      type="primary"
      open-type="getPhoneNumber"
      @getphonenumber="getPhoneNumber"
    >门店手机号一键登录</button>
  </div>
</template>
<script>
export default {
  name: 'Auth',
  data() {
    return {
      isShowPhone: false // 是否显示获取手机号按钮
    }
  },
  methods: {
    // 用户按了允许授权按钮
    async getPhoneNumber(e) {
      console.log('获取手机号码Code:', e.mp.detail)
      if (e.mp.detail.code) {
        // 用户按了允许授权按钮
        // console.log('获取手机号码:', e.mp.detail)
        this.isShowPhone = false
        const res = await this.$http('registerPhone', { code: e.mp.detail.code, openid: this.openId })
        if (res.success) {
          this.setToken(res.data)
          this.$reLaunch('/pages/tabbarPage/main')
        }
      } else {
        // 用户按了拒绝按钮
        wx.hideLoading()
        wx.showModal({
          title: '提示',
          content: '拒绝授权将无法注册登陆小程序!',
          showCancel: false,
          success: (res) => {
            if (res.confirm) {
              this.isShowPhone = true
            }
          }
        })
      }
    }
  }
}
</script>

4、页面效果截图如下

1、初始页面如下:

在这里插入图片描述

2、点击按钮后如下:

在这里插入图片描述

3、点击不允许后如下:

在这里插入图片描述

4、点击允许后(直接进入首页)如下:

在这里插入图片描述

鉴权页面:auth.vue代码如下:

<template>
  <div class="auth flex-box flex-ver flex-col">
    <div class="loading-wrap flex-box flex-col flex-ver">
      <img class="launch_loading_logo" src="../../static/images/logo.png" />
      <p class="app-name">{{ appName }}</p>
    </div>
    <button
      class="btn flex-box flex-ver"
      v-if="isShowPhone"
      type="primary"
      open-type="getPhoneNumber"
      @getphonenumber="getPhoneNumber"
    >门店手机号一键登录</button>
  </div>
</template>
<script>
import { mapMutations, mapGetters } from 'vuex'
import { APP_NAME } from '@/utils/settingConfig'
export default {
  name: 'Auth',
  data() {
    return {
      appName: APP_NAME,
      code: '', // wx.login拿回来的code
      isShowPhone: false // 是否显示获取手机号按钮
    }
  },
  computed: {
    ...mapGetters([
      'openId'
    ])
  },
  onLoad(option) {
    // console.log('接受参数', option)
    wx.showLoading({
      title: '检查应用版本',
      mask: true
    })
    // 检测IOS版本
    wx.getSystemInfo({
      success: (res) => {
        wx.hideLoading()
        // console.log(11, res)
        let versionIos = res.system.split(' ')[1].split('.')[0]
        let version = res.system.split(' ')[0].toLowerCase()
        // console.log(222, version, versionIos)
        if (version === 'ios' && versionIos < 10) {
          wx.showModal({
            title: '提示',
            content: `当前ios版本为${res.system.split(' ')[1]},请升级10以上再登录!`,
            showCancel: false,
            success(res) {
              if (res.confirm) {
                console.log('用户点击确定')
              }
            }
          })
        }
      }
    })
  },
  onShow() {
    // 调用微信登录wx.login
    this.logining()
  },
  methods: {
    ...mapMutations({
      setToken: 'user/SET_TOKEN',
      setOpenId: 'user/SET_OPEN_ID'
    }),
    // 调用微信登录wx.login获取code
    logining() {
      wx.showLoading({
        title: '登录微信用户',
        mask: true
      })
      wx.login({
        success: (res) => {
          if (res.code) {
            wx.hideLoading()
            this.code = res.code
            // console.log('wx.login获得code成功', res)
            // vuex中的openId/unionId若存在就直接调用获取token接口
            if (this.openId) {
              this.getAccessToken(this.openId)
            } else {
              this.getOpenId({ code: this.code })
            }
          } else {
            console.log('获取用户登录态失败!' + res.errMsg)
          }
        },
        fail(err) {
          wx.hideLoading()
          wx.showToast({
            title: 'wx.login失败' + err,
            icon: 'none',
            duration: 1000
          })
        }
      })
    },
    // 获取openid
    async getOpenId(parameter) {
      wx.showLoading({
        title: '获取openId',
        mask: true
      })
      const res = await this.$http('getOpenId', parameter)
      console.log('获取openId', res)
      wx.hideLoading()
      if (res.success) {
        // 生成唯一值
        this.setOpenId(res.data.openid)
        // console.log('获取openId---值', res.data.openid)
        this.getAccessToken(res.data.openid)
      }
    },
    // 获取token
    async getAccessToken(openId) {
      const res = await this.$http('getAccessToken', { openid: openId })
      // console.log('获取token', res)
      if (res.success) {
        if (res.data) {
          this.isShowPhone = false
          this.setToken(res.data)
          this.$reLaunch('/pages/tabbarPage/main')
        } else {
          this.isShowPhone = true
        }
      }
    },
    // 用户按了允许授权按钮
    async getPhoneNumber(e) {
      console.log('获取手机号码Code:', e.mp.detail)
      if (e.mp.detail.code) {
        // 用户按了允许授权按钮
        // console.log('获取手机号码:', e.mp.detail)
        this.isShowPhone = false
        const res = await this.$http('registerPhone', { code: e.mp.detail.code, openid: this.openId })
        if (res.success) {
          this.setToken(res.data)
          this.$reLaunch('/pages/tabbarPage/main')
        }
      } else {
        // 用户按了拒绝按钮
        wx.hideLoading()
        wx.showModal({
          title: '提示',
          content: '拒绝授权将无法注册登陆小程序!',
          showCancel: false,
          success: (res) => {
            if (res.confirm) {
              this.isShowPhone = true
            }
          }
        })
      }
    }
  }
}
</script>
<style lang="scss">
.auth {
  height: 100%;
  .loading-wrap {
    .launch_loading_logo {
      width: 80px;
      height: 80px;
      border-radius: 80px;
    }
    .app-name {
      margin-top: 20px;
    }
  }
  .btn {
    position: fixed;
    bottom: 35px;
    width: 90%;
    border-radius: 20px;
  }
}
</style>

源码地址

gitHub地址

码云地址

其他文章

Vue3 + Vite + Ts开源后台管理系统模板


基于ElementUi或AntdUI再次封装基础组件文档


基于Element-plus再次封装基础组件文档(vue3+ts)