【微信小程序】用户授权及getUserProfile接口使用

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

以上说明的核心要点就是废弃下面两个相关代码

wx.getUserInfo
<button open-type="getUserInfo"/>

替换成新的代码

getUserProfile

1、旧版授权方法

getUserInfo: function(e) {
    // 获取用户信息
    wx.getSetting({
      success(res) {
        if (res.authSetting['scope.userInfo']) {
          console.log("已授权=====")
          // 已经授权,可以直接调用 getUserInfo 获取头像昵称
          wx.getUserInfo({
            success(res) {
              console.log("获取用户信息成功", res)
            },
            fail(res) {
              console.log("获取用户信息失败", res)
            }
          })
        } else {
          console.log("未授权=====")
        }
      }
    })
  },

2,新版方法
(1)在onLoad中,获取openId

  onLoad: function (options) {
    var self = this
    wx.cloud.callFunction({
      name: 'getOpenId',
      complete: res => {
        var openid = res.result.event.userInfo.openId
        // 根据openid查询是否授权
        self.queryAuthByOpenid(openid)
      }
    })
  },

(2)根据openId到云开发数据库user表中查询该用户是否授权,如果已授权就直接显示界面内容,否则弹出授权提示框

 queryAuthByOpenid: function (openid) {
    var self = this
    user.where({
        _openid: openid
      })
      .get({
        success(res) {
          if (res.data.length != 0 && res.data[0].auth) {
            // 已经授权,可直接显示页面信息 
            self.initView()
          } else {
            // 未授权,弹框
            self.showDialog()
          }
        }
      })
  },

此处的dialog使用的是自定义组件,也可以使用微信自带的showModal

   onReady: function () {
    this.dialog = this.selectComponent("#dialog")
  },
  showDialog: function () {
    let dialog = this.dialog
    dialog.showDialog()
  },

在这里插入图片描述
(3)此时点击授权登陆会触发以下事件,调用新版的getUserProfile方法弹出授权弹框,根据返回的msg判断用户点击了允许还是拒绝,点击拒绝的话就直接toast提示用户,点击允许的话就更新云数据库user表中的auth为true并显示界面内容

confirmEvent: function () {
    var self = this
    let dialog = this.dialog
    dialog.hideDialog()
    if (!this.data.isAuth) {
      wx.getUserProfile({
        desc: '仅作展示',
        success: function (res) {
        },
        complete: function (res) {
          var msg = res.errMsg
          var index = msg.indexOf('ok')
          if (index == -1) {
            // 拒绝授权
            wx.showToast({
              title: '您已拒绝授权',
              image: '../../images/error.png'
            })
          } else {
            // 允许授权 更新auth为true
            self.updateUserAuth(res.userInfo)
            self.initView()
          }
        }
      })
    }
  },

(4)更新用户授权信息。先获取当前用户openId,然后根据openId到user表中查询信息,查不到结果的话就直接新增一条,查到一条结果的话就先删除原有的再新增一条(此处应该改为直接更新记录)

updateUserAuth: function (userInfo) {
    var self = this
    wx.cloud.callFunction({
      name: 'getOpenId',
      complete: res => {
        var openid = res.result.event.userInfo.openId;
        user
          .where({
            _openid: openid
          })
          .get({
            success(res) {
              if (res.data.length == 1) {
                self.deleteAndSaveUser(res.data[0]._id,userInfo)
              } else {
                self.saveUser(userInfo)
              }
            },
            fail(res) {
              console.log(res)
            }
          })
      }
    })
  },
  deleteAndSaveUser: function (sid,userInfo) {
    var self = this
    user.doc(sid).remove({
      success(res) {
        console.log('remove success')
        self.saveUser(userInfo)
      },
      fail: console.error,
    })
  },
  // 插入用户数据到数据库:_openId,头像,昵称,性别,国家,省份,城市,auth
  saveUser: function (userInfo) {
    user
      .add({
        data: {
          auth: true,
          avatar: userInfo.avatarUrl,
          nickname: userInfo.nickName,
          gender: userInfo.gender,
          country: userInfo.country,
          province: userInfo.province,
          city: userInfo.city,
          createtime: util.formatTime(new Date())
        },
        success: function (res) {
          // res 是一个对象,其中有 _id 字段标记刚创建的记录的 id
          console.log(res)
        },
        fail: console.error,
        // complete: console.log
      })
  },

附录一:云函数getOpenId

// 云函数入口文件
const cloud = require('wx-server-sdk')

cloud.init()

// 云函数入口函数
exports.main = async (event, context) => {
  const wxContext = cloud.getWXContext()

  return {
    event,
    openid: wxContext.OPENID,
    appid: wxContext.APPID,
    unionid: wxContext.UNIONID,
  }
}

附录二:自定义dialog组件

dialog.js

Component({
  options: {
    multipleSlots: true // 在组件定义时的选项中启用多slot支持
  },
  /**
   * 组件的属性列表
   */
  properties: {
    // 弹窗标题
    title: {
      type: String,
      value: '标题' // 默认值
    },
    // 弹窗内容
    content: {
      type: String,
      value: '弹窗内容'
    },

    // 弹窗确认按钮文字
    confirmText: {
      type: String,
      value: '确定'
    }
  },

  /**
   * 组件内私有数据
   */
  data: {
    // 弹窗显示控制
    isShow: false
  },

  /**
   * 组件的公有方法列表
   */
  methods: {

    //隐藏弹框
    hideDialog() {
      this.setData({
        isShow: !this.data.isShow
      })
    },
    //展示弹框
    showDialog() {
      this.setData({
        isShow: !this.data.isShow
      })
    },
    isShowing(){
      return this.data.isShow
    },
    /**
    * triggerEvent 组件之间通信
    */
    confirmEvent() {
      this.triggerEvent("confirmEvent");
    },

    bindGetUserInfo(e) {
      this.triggerEvent("bindGetUserInfo",{event:e});
    }

  }
})

dialog.json

{
  "component": true,
  "usingComponents": {}
}

dialog.wxml

<view class='dialog-container' hidden="{{!isShow}}">
    <view class='dialog-mask'></view>
    <view class='dialog-info'>
        <view class='dialog-title'>{{ title }}</view>
        <view class='dialog-content'>{{ content }}</view>
        <view class='dialog-footer'>
          <button class='dialog-btn'  catchtap='confirmEvent'>{{ confirmText }}</button>
        </view>
    </view>
</view>

dialog.wxss

.dialog-mask{
  position: fixed;
    z-index: 1000;
    top: 0;
    right: 0;
    left: 0;
    bottom: 0;
    background: rgba(0, 0, 0, 0.3);
}
.dialog-info{
    position: fixed;
    z-index: 5000;
    width: 80%;
    max-width: 600rpx;
    top: 50%;
    left: 50%;
    -webkit-transform: translate(-50%, -50%);
    transform: translate(-50%, -50%);
    background-color: #FFFFFF;
    text-align: center;
    border-radius: 3px;
    overflow: hidden;
}
.dialog-title{
    font-size: 36rpx;
    padding: 30rpx 30rpx 10rpx;
}
.dialog-content{
    padding: 10rpx 30rpx 20rpx;
    min-height: 80rpx;
    font-size: 32rpx;
    line-height: 1.3;
    word-wrap: break-word;
    word-break: break-all;
    color: #999999;
    text-align: left;
}
.dialog-footer{
    display: flex;
    align-items: center;
    position: relative;
    line-height: 90rpx;
    font-size: 34rpx;
}
.dialog-btn{
    display: block;
    -webkit-flex: 1;
    flex: 1;
    position: relative;
    color: #3CC51F;
}

附录三:不通过云开发获取openid

鉴于云开发已经收费,19元每月,到2023年就会恢复原价38元每月,对个人开发者极其不友好,所以小程序正在考虑云开发替代方案

 wx.login({
      success: (res) => {
          // 通过 code 换取openid
          if (res.code) {
            let code = res.code
              wx.request({
                  url: "https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=APPSECRET&js_code="+code+"&grant_type=authorization_code",
                  method: "post",
                  success: (res) => {
                      if (res.data && res.data.openid) {
                        console.log(res.data.openid)
                          // 获取的 openid 存入storage,方便之后使用
                          wx.setStorageSync("openId", res.data.openid);
                      }
                  },
              });
          }
      },
      fail: () => {},
      complete: () => {},
  });

以上代码在小程序开发版确实能获取到openid,但要勾选一个选项
在这里插入图片描述
这样的话,就没法在正式版使用了,因为api.weixin.qq.com不能被配置为服务器域名
在这里插入图片描述
那只剩下一种方法:使用自己的服务器或者云服务器,反正就是得有一个后端服务器,参考以下文章
微信小程序、获取openid
微信小程序,如何获取openid(带后端代码)

  • 15
    点赞
  • 111
    收藏
    觉得还不错? 一键收藏
  • 21
    评论
评论 21
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值