mpVue 微信小程序用户授权及wx.getUserProfile代替wx.getUserInfo获取用户信息及判断用户是否已经授权;不弹出微信授权窗口;只能使用头像、昵称填写能力

一、前言

2021年4月15日整改:为优化用户的使用体验,平台将进行以下调整:
1,2021年2月23日起,若小程序已在微信开放平台进行绑定,则通过wx.login接口获取的登录凭证可直接换取unionID
2,2021年4月13日后发布的小程序新版本,无法通过wx.getUserInfo与获取用户个人信息(头像、昵称、性别与地区),将直接获取匿名数据(包括userInfoencryptedData中的用户个人信息),获取加密后的openIDunionID数据的能力不做调整。此前发布的小程序版本不受影响,但如果要进行版本更新则需要进行适配。
3,新增getUserProfile接口(基础库2.10.4版本开始支持),可获取用户头像、昵称、性别及地区信息,开发者每次通过该接口获取用户个人信息均需用户确认。具体接口文档:《getUserProfile接口文档》

自 2022 年 10 月 25 日 24 时后(以下统称 “生效期” ),用户头像昵称获取规则将进行如下调整:
1、自生效期起,小程序 wx.getUserProfile 接口将被收回:生效期后发布的小程序新版本,通过 wx.getUserProfile 接口获取用户头像将统一返回默认灰色头像,昵称将统一返回 “微信用户”。生效期前发布的小程序版本不受影响,但如果要进行版本更新则需要进行适配。
2、自生效期起,插件通过 wx.getUserInfo 接口获取用户昵称头像将被收回:生效期后发布的插件新版本,通过 wx.getUserInfo 接口获取用户头像将统一返回默认灰色头像,昵称将统一返回 “微信用户”。生效期前发布的插件版本不受影响,但如果要进行版本更新则需要进行适配。通过 wx.loginwx.getUserInfo 接口获取 openIdunionId 能力不受影响。
3、「头像昵称填写能力」支持获取用户头像昵称:如业务需获取用户头像昵称,可以使用「头像昵称填写能力」(基础库 2.21.2 版本开始支持)。
4、小程序 wx.getUserProfile插件 wx.getUserInfo 接口兼容基础库 2.21.2 以下版本的头像昵称获取需求:上述「头像昵称填写能力」从基础库 2.21.2 版本开始支持(覆盖微信 8.0.16 以上版本)。对于来自更低版本的基础库与微信客户端的访问,小程序通过wx.getUserProfile接口将正常返回用户头像昵称,插件通过 wx.getUserInfo 接口将返回用户头像昵称,开发者可继续使用以上能力做向下兼容。

二、微信小程序授权及登录流程

1、调起 wx.getUserProfile 获取用户微信的基本资料
2、通过 wx.login 获取唯一 code,将 code 调用后台接口获取 openid/unionid
3、根据openid/unionid调用后台接口,获取微信登录的token

三、关键步骤(wx.getUserProfile代替wx.getUserInfo使用)

1、template改变对比


<button open-type="getUserInfo" @getuserinfo="bindGetUserInfo">微信授权button>

<button @click="bindGetUserInfo">微信授权button>

2、bindGetUserInfo方法对比

// 旧版
    // 用户按了允许授权按钮
    bindGetUserInfo(e) {
      if (e.mp.detail.userInfo) {
        // 用户按了允许授权按钮
        // console.log('用户的信息:', e.mp.detail.userInfo)
        this.canGetInfo = true
        // 存储微信用户信息
        this.setWxUserInfo(e.mp.detail.userInfo)
        // 存储头像
        this.setAvatarUrl(e.mp.detail.userInfo.avatarUrl)
        wx.hideLoading()
        this.logining()
      } else {
        // 用户按了拒绝按钮
        wx.hideLoading()
        wx.showModal({
          title: '提示',
          content: '拒绝授权将无法注册登陆小程序!',
          showCancel: false,
          success: (res) => {
            if (res.confirm) {
              this.canGetInfo = true
            }
          }
        })
      }
    },
    // 查看是否授权
    getWxInfo() {
      wx.showLoading({
        title: '检查授权情况',
        mask: true
      })
      wx.getSetting({
        success: (res) => {
          if (res.authSetting['scope.userInfo']) {
            wx.getUserInfo({
              success: (data) => {
                // 用户已经授权过,不需要显示授权页面
                this.canGetInfo = true
                // console.log('获取微信用户信息', data, this.openId)
                this.setWxUserInfo(data.userInfo)
                this.setAvatarUrl(data.userInfo.avatarUrl)
                // 调用微信登录wx.login
                this.logining()
              }
            })
          } else {
            // 用户没有授权,显示授权页面
            this.canGetInfo = false
            console.log('用户还未授权', res)
          }
        }
      })
    },
    
//新版
 // 查看是否授权
    bindGetUserInfo() {
      wx.showLoading({
        title: '请求授权中...',
        mask: true
      })
      if (this.wxUserInfo.avatarUrl) {
        console.log('获取微信用户信息--', this.wxUserInfo)
        // 用户已经授权过,不需要显示授权页面
        this.canGetInfo = true
        console.log('用户已经授权过22222---')
        // 调用微信登录wx.login
        this.logining()
      } else {
        wx.getUserProfile({
          desc: '必须授权才能继续使用',
          success: (data) => {
            this.canGetInfo = true
            console.log('获取微信用户信息', data)
            wx.hideLoading()
            this.setWxUserInfo(data.userInfo)
            this.setAvatarUrl(data.userInfo.avatarUrl)
            // 调用微信登录wx.login
            this.logining()
          },
          fail: (error) => {
            this.canGetInfo = false
            wx.hideLoading()
            console.log('用户还未授权', error)
          }
        })
      }
    },

3、判断用户是否已经授权

授权弹窗:是自己css布局的界面弹窗(因为自 2022 年 10 月 25 日 24 时后,是否显示微信授权弹窗都需要用户手动点击触发);因为wx.getUserProfilewx.getUserInfo都已经被收回所有都不弹出授权窗口,只能使用头像昵称填写能力

1、旧版根据wx.getSetting['scope.userInfo']来判断是否已经授权过

2、新版是判断 是否存储过微信的用户信息,有则已经授权过,没有则弹出授权弹窗(自己css布局弹窗)

四、具体授权完整步骤

1、旧版授权方法( wx.getUserInfo使用),如下:

<template>
  <div class="auth flex-box flex-ver">
    
    <section v-if="!canGetInfo" class="sec-mask">
      <div class="wrapper flex-box flex-ver flex-col">
        <img class="wechat-auth-img" src="../../static/images/logo.png" />
        <p class="hint">小程序希望获取您的微信授权p>
        <button
          class="btn flex-box flex-ver"
          type="primary"
          open-type="getUserInfo"
          @getuserinfo="bindGetUserInfo"
        >微信授权button>
      div>
    section>
  div>
template>
<script>
export default {
  name: 'Auth',
  data() {
    return {
      code: '', // wx.login拿回来的code
      canGetInfo: true // 授权状态,能否获取用户信息
    }
  },
  computed: {
    ...mapGetters([
      'userType', // 当前登录用户 EXTERNAL_DRIVER-司机 EXTERNAL_SUP-供应商
      'openId',
      'userInfo',
      'unionId',
      'mpBinding'
    ])
  },
  onShow() {
    this.getWxInfo()
  },
  methods: {
    ...mapMutations({
      setAvatarUrl: 'user/SET_AVATAR_URL',
      setToken: 'user/SET_TOKEN',
      setOpenId: 'user/SET_OPEN_ID',
      setUnionId: 'user/SET_UNION_ID',
      setWxUserInfo: 'user/SET_WX_USER_INFO'
    }),
    // 用户按了允许授权按钮
    bindGetUserInfo(e) {
      if (e.mp.detail.userInfo) {
        // 用户按了允许授权按钮
        // console.log('用户的信息:', e.mp.detail.userInfo)
        this.canGetInfo = true
        // 存储微信用户信息
        this.setWxUserInfo(e.mp.detail.userInfo)
        // 存储头像
        this.setAvatarUrl(e.mp.detail.userInfo.avatarUrl)
        wx.hideLoading()
        // 调用微信登录wx.login
        this.logining()
      } else {
        // 用户按了拒绝按钮
        wx.hideLoading()
        wx.showModal({
          title: '提示',
          content: '拒绝授权将无法注册登陆小程序!',
          showCancel:false,
          success: (res) => {
            if (res.confirm) {
              this.canGetInfo = false
            }
          }
        })
      }
    },
    // 查看是否授权
    getWxInfo() {
      wx.showLoading({
        title: '检查授权情况',
        mask: true
      })
      wx.getSetting({
        success: (res) => {
          if (res.authSetting['scope.userInfo']) {
            wx.getUserInfo({
              success: (data) => {
                // 用户已经授权过,不需要显示授权页面
                this.canGetInfo = true
                // console.log('获取微信用户信息', data, this.openId)
                this.setWxUserInfo(data.userInfo)
                this.setAvatarUrl(data.userInfo.avatarUrl)
                // 调用微信登录wx.login
                this.logining()
              }
            })
          } else {
            // 用户没有授权,显示授权页面
            this.canGetInfo = false
            console.log('用户还未授权', res)
          }
        }
      })
    },
    // 调用微信登录wx.login获取code
    logining() {
      wx.showLoading({
        title: '登录微信用户',
        mask: true
      })
      wx.login({
        success: (res) => {
          if (res.code) {
            wx.hideLoading()
            // 通过code获取openid和session_key
            this.code = res.code
            // console.log('wx.login获得code成功', res)
            // 调用获取用户信息接口
            if (this.openId) {
              // vuex中的openId/unionId
              this.getAccessToken(this.openId)
            } else {
              this.getAsyncOpenId({ code: this.code })
            }
          } else {
            console.log('获取用户登录态失败!' + res.errMsg)
          }
        },
        fail(err) {
          wx.hideLoading()
          wx.showToast({
            title: 'wx.login失败' + err,
            icon: 'none',
            duration: 1000
          })
        }
      })
    },
    // 获取openid
    async getAsyncOpenId(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 })
      if (res.data.success) {
        this.setToken(res.data.data)
        wx.showLoading({
          title: '获取用户信息',
          mask: true
        })
        // 获取登录用户的user信息
        const userRole = await this.$store.dispatch('user/getUserInfo')
        // console.log('userRole---', userRole)
        if (userRole.success) {
          wx.hideLoading()
          const findRole = userRole.data.post
          //进入首页
          if (findRole) {
            this.$reLaunch('/pages/tabbarPage/main')
          } else {
            wx.showToast({
              title: '当前用户未绑定合法角色',
              icon: 'none',
              duration: 3000
            })
          }
        }
      } else {
        switch (res.data.code) {
          case 10000:
            this.$reLaunch('/pages/register/main')
            break
          case 10009:
            // console.log('直接进入首页')
            this.$reLaunch('/pages/tabbarPage/main')
            break
          case 11002:
          case 11003:
            this.loginErr(`获取token失败,${res.msg}`)
            break
        }
      }
    },
    // 当前用户未绑定、登录失败、异常等
    loginErr(msg = '') {
      const query = this.$mp.query
      // console.log('query--', query)
      wx.showModal({
        title: '登录失败',
        content: msg,
        confirmText: '刷新',
        showCancel: false,
        success: () => {
          this.$reLaunch(`/pages/auth/main`)
        }
      })
    }
  }
}
script>

2、新版授权方法(wx.getUserProfile),如下:

<template>
  <div class="auth flex-box flex-ver">
    
    <section v-if="!canGetInfo" class="sec-mask">
      <div class="wrapper flex-box flex-ver flex-col">
        <img class="wechat-auth-img" src="../../static/images/logo.png" />
        <div class="flex-box flex-col">
          <p class="hint t-font-size-16">申请获取以下权限p>
          <div class="t-margin-top-5" style="color: #9d9d9d;">获得你的公开信息(昵称,头像等)div>
        div>
        <button class="btn flex-box flex-ver" type="primary" @tap="getWxInfo">微信授权button>
      div>
    section>
  div>
template>
<script>
import { mapMutations, mapGetters } from 'vuex'
export default {
  name: 'Auth',
  data() {
    return {
      code: '', // wx.login拿回来的code
      canGetInfo: false // 授权状态,能否获取用户信息
    }
  },
  computed: {
    ...mapGetters([
      'userType', // 当前登录用户 EXTERNAL_DRIVER-司机 EXTERNAL_SUP-供应商
      'openId',
      'userInfo',
      'unionId',
      'mpBinding',
      'wxUserInfo'
    ])
  },
  onShow() {
    this.getWxInfo()
  },
  methods: {
    ...mapMutations({
      setAvatarUrl: 'user/SET_AVATAR_URL',
      setToken: 'user/SET_TOKEN',
      setOpenId: 'user/SET_OPEN_ID',
      setWxUserInfo: 'user/SET_WX_USER_INFO'
    }),
    // 查看是否授权
    getWxInfo() {
      wx.showLoading({
        title: '请求授权中...',
        mask: true
      })
      // 判断用户是否已经授权,若已经授权直接调用wx.login,不然则先调用wx.getUserProfile
      if (this.wxUserInfo.avatarUrl) {
        console.log('1111', this.wxUserInfo)
        this.canGetInfo = true
        console.log('用户已经授权过')
        // 调用微信登录wx.login获取code
        this.logining()
      } else {
        wx.getUserProfile({
      	  desc: '获取用户信息', // 声明获取用户个人信息后的用途,后续会展示在弹窗中(必填项)
          success: (data) => {
            this.canGetInfo = true
            wx.hideLoading()
            // 存储微信userInfo
            this.setWxUserInfo(data.userInfo)
            // 存储微信头像
            this.setAvatarUrl(data.userInfo.avatarUrl)
            // 调用微信登录wx.login获取code
            this.logining()
          },
          fail: (error) => {
            this.canGetInfo = false
            wx.hideLoading()
            console.log('用户还未授权', error)
          }
        })
      }
    },
    // 调用微信登录wx.login获取code
    logining() {
      wx.showLoading({
        title: '登录微信用户',
        mask: true
      })
      wx.login({
        success: (res) => {
          if (res.code) {
            wx.hideLoading()
            // 通过code获取openid和session_key
            this.code = res.code
            // console.log('wx.login获得code成功', res)
            // 判断若存在openId/unionId,则直接去获取token,不然则先获取openId,在去获取token
            if (this.openId) {
              this.getAccessToken(this.openId)
            } else {
              this.getAsyncOpenId({ code: this.code })
            }
          } else {
            console.log('获取用户登录态失败!' + res.errMsg)
          }
        },
        fail(err) {
          wx.hideLoading()
          wx.showToast({
            title: 'wx.login失败' + err,
            icon: 'none',
            duration: 1000
          })
        }
      })
    },
    // 获取openid
    async getAsyncOpenId(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 })
      if (res.data.success) {
        this.setToken(res.data.data)
        wx.showLoading({
          title: '获取用户信息',
          mask: true
        })
        // 获取用户user信息
        const userRole = await this.$store.dispatch('user/getUserInfo')
        // console.log('userRole---', userRole)
        if (userRole.success) {
          wx.hideLoading()
          // 获取角色
          const findRole = userRole.data.post
          // 进入首页
          if (findRole) {
            this.$reLaunch('/pages/tabbarPage/main')
          } else {
            wx.showToast({
              title: '当前用户未绑定合法角色',
              icon: 'none',
              duration: 3000
            })
          }
        }
      } else {
        switch (res.data.code) {
          case 10000:
            // console.log('进入注册页面')
            this.$reLaunch('/pages/register/main')
            break
          case 10009:
            // console.log('直接进入首页')
            this.$reLaunch('/pages/tabbarPage/main')
            break
          case 11002:
          case 11003:
            this.loginErr(`获取token失败,${res.msg}`)
            break
        }
      }
    },
    // 当前用户未绑定、登录失败、异常等
    loginErr(msg = '') {
      const query = this.$mp.query
      wx.showModal({
        title: '登录失败',
        content: msg,
        confirmText: '刷新',
        showCancel: false,
        success: () => {
          this.$reLaunch(`/pages/auth/main`)
        }
      })
    }
  }
}
script>
<style lang="scss">
.auth {
  height: 100%;
  .loading-wrap {
    padding-bottom: 160px;
    .launch_loading_logo {
      width: 50px;
      height: 50px;
      border-radius: 50px;
    }
    .app-name {
      margin-top: 20px;
    }
  }
  /* 授权页样式 */
  .sec-mask {
    background: rgba(0, 0, 0, 0.4);
    position: fixed;
    display: flex;
    justify-content: center;
    align-items: center;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    z-index: 99;
    .wrapper {
      width: 90%;
      height: 40%;
      background-color: #fff;
      border-radius: 8rpx;
      .wechat-auth-img {
        display: block;
        width: 162px;
        height: 143px;
      }
      .hint {
        margin-top: 30rpx;
      }
      button {
        width: 80%;
        height: 100rpx;
        background-color: #259b24;
        border-radius: 70rpx;
        margin-top: 60rpx;
      }
    }
  }
}
style>

3、效果,如下:

源码地址

gitHub地址

码云地址

其他文章

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


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


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

你可能感兴趣的:(mpvue,微信小程序组件封装,微信小程序,mpvue,wx.getUserInfo,getUserProfile,小程序,用户授权,授权)