微信小程序学习日记 L05 拉起授权

最后更新:

在实际业务场景中,最常接触到的就是拉取微信登陆了,但单纯的一个点击按钮直接微信登录的需要获取多少微信权限呢?

最少的需要使用到1个微信开放接口:wx.login
如果需要获取用户头像和昵称,需要调用 wx.getUserProfile 方法 (wx.getUserInfo 已调整【尾声#1】),并且需要在绑定在按钮上 ,并会唤起授权提示;
如果需要获取用户手机号信息,需要在按钮上绑定 getPhoneNumber 事件。

一般来说非敏感信息可以直接调用,含有敏感信息的接口需要绑定在按钮上,在用户自行操作之后才可以调用。

开放接口

1、 微信登陆

如果只是单纯需要获取用户的微信 openId关联用户账户,则可以直接调用 wx.login() 方法,把获取的 code(登录凭证) 传递给后端就可以,后端可以根据 code 请求微信的服务器端Api来换取 [ openid, unionid, session_key ]

一个简单的示例:

// login.js
Page({
  onLoad(){
    // 可以绑定在页面中的某个按钮上,也可以页面载入后就直接请求
    this.onWechatLogin()
  }
  // 微信登陆操作
  onWechatLogin () {
    // 请求微信登陆api
    wx.login({
      success: (wxRes) => {
        const data = {
          code: wxRes.code
        }
        // 请求后端登陆API,这个方法是我自己封装的请求函数,
        // 具体请看 小程序学习日记 L04 网络请求
        postAction("/pub/weChat/login", data).then(res => {
          // 服务器返回数据后的操作
        })
      }
    })
  },
})

2、 获取用户资料

在早些时候是调用微信的 wx.getUserInfo 接口,但是从我开始写小程序的时间,正好是 wx.getUserProfile() 更新替代的时候,所以我的获取用户资料的demo就直接使用 wx.getUserProfile() 接口。
其实如果不需要保存用户头像和昵称,可以使用微信新提供的 <open-data> 组件直接在界面中展示 预览代码片段

<!-- 直接使用 open-data 组件展示用户头像和昵称 -->
<open-data type="userAvatarUrl"></open-data>
<open-data type="userNickName"></open-data>

然后需要做头像固定宽高圆角之类样式的,给 <open-data> 添加 className 就可以了。
不过这不在拉取授权的范畴内,所以只是举例,如果需要获取用户资料的需要以下方式来唤起授权

<!--  page.wxml -->
<view class="container">
  <!-- 需要在按钮上绑定获取用户信息的事件来触发 wx.getUserProfile -->
  <button bindtap="getUserProfile" wx:if="{{!hasUserInfo}}"> 获取头像昵称 </button>
  <view wx:else>
    <image src="{{ userInfo.avatarUrl }}" mode="cover"></image>
    <text>{{ userInfo.nickName }}</text>
  </view>
</view>
// page.js
Page({
  data: {
    userInfo: {},
    hasUserInfo: false,
  },
  getUserProfile() {
    // 要直接在按钮绑定的方法内调用 wx.getUserProfile
    // 不能在 callback 或者在 promise.then 中调用
    wx.getUserProfile({
      desc: '用于完善会员资料', 
      success: (res) => {
        this.setData({
          userInfo: res.userInfo,
          hasUserInfo: true
        })
      }
    })
  },
})

3、 获取用户手机号

和以前的 wx.getUserInfo 获取微信用户个人信息一样,需要指定 open-type 的值为 getPhoneNumber,以及使用 bindgetphonenumber 绑定事件。
在用户确认授权之后可以在 event 获取到加密后的 用户信息(encryptedData),以及加密向量(iv)等信息,最后就看需不需要回填到前台,如果不需要就直接在后端处理就可以了。

<!-- page.wxml -->
<button open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber">获取手机号</button>
// page.js
Page({
  getPhoneNumber (e) {
    // 检查服务器端 sessionKey 是否过期
    wx.checkSession({
      success () {
        // sessionKey 未过期
        const { iv, encryptedData } = e.detail
        if(!iv) {
          wx.showToast({ title:'授权失败请重试' })
          return
        }
        const data = {
          iv:iv, // 加密算法的初始向量
          encryptedData:encryptedData // 加密后的用户信息
        }
        // 请求服务端解密手机号
        postAction("/user/weChat/getPhoneNumber", data).then(res=>{
          // 根据是否需要回填手机号做对应操作
        })
      },
      fail () {
        // sessionKey过期,重新做登录动作,
        // 让后端更新 sessionKey,并提示用户重新授权
      }
    })
  }
})

注意:在回调中调用 wx.login 登录,可能会刷新登录态。此时服务器使用 code 换取的 sessionKey 不是加密时使用的 sessionKey,导致解密失败。建议开发者提前进行 login;或者在回调中先使用 checkSession 进行登录态检查,避免 login 刷新登录态。

解密后的数据为:

{
  "phoneNumber": "13580006666", // 用户绑定的手机号(国外手机号会有国际区号)
  "purePhoneNumber": "13580006666", // 没有国际区号的手机号
  "countryCode": "86", // 国际区号
  "watermark": // 数据水印
  {
    "appid":"APPID", // 归属小程序appid
    "timestamp": TIMESTAMP // 数据获取的时间戳
  }
}

4、 调用微信支付

支付 | 微信开放文档

5、 获取收货地址

收货地址 | 微信开放文档

6、 获取微信运动

微信运动 | 微信开放文档

7、 获取自定义权限

wx.authorize | 微信开放文档
授权 | 微信开放文档

————– 未完成 —————

🔊 尾声

● 2021/04/15后(基础库2.10.4起) 微信调整了 wx.getUserInfo 接口

现在已经只会返回匿名用户信息了,加密信息(encryptedData)中的 openIDunionID还可以获取,如果要获取用户个人信息,则需要使用 wx.getUserProfile 来代替,会唤起微信的授权窗口。
调整说明 👉 小程序登录、用户信息相关接口调整说明 | 微信开放社区

资源 📚

开放接口 | 微信开放文档
服务端 | 微信开放文档