微信小程序手机号快速验证授权失败?

645 阅读3分钟

微信小程序手机号快速验证授权失败?

一、前言

应用场景

授权获取微信绑定手机号。

使用方法

目前该项能力为微信收费能力,文章后续讲解了微信目前提供的2种实现方案,另整理了一下常见的授权问题。

二、微信能力

2.1 前提条件

  1. 要用户主动触发才能发起手机号快速验证, 需用 button 组件的点击来触发
  2. 满足验证额度;
  • 1000次体验额度 = 正式版+体验版+开发版;
  • 自2023年8月28日起,手机号快速验证组件执行付费使用。标准单价为:调用成功0.03元/次
  1. 服务器域名已授权在微信服务
    设置路径: 开发 → 开发管理 → 开发设置 → 服务器域名 (配置)

image.png

image.png

2.2 实现方案

2种方案基本流程
① 前端调用获取微信服务的数据
② 前端将必要数据传给服务端做记录
③ 服务端调用openAPI接口获取手机号,必要参数依赖②

方案一: 2.21.2之前的老方案

方案需要的code是wx.login的获取的code

步骤1:获取手机号;前端通过用户主动触发,回调获得加密数据

<button open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber" onGetPhoneNumber={handleGetPhoneNumber}></button>
  // 方式一:原生
  Page({
      getPhoneNumber (e) {
        console.log(e.detail.errMsg)
        console.log(e.detail.iv) // 加密算法初始向量
        console.log(e.detail.encryptedData) // 加密数据
      }
    })
  // 方式二:自定义方法
  const handleGetPhoneNumber = (e) => {
   const { iv, encryptedData , cloudID } = e?.detail || {};

   console.log(e?.detail);
  }

步骤2:登录,获取手机解密必须的session_key
① 前端wx.login()登录获取code传给服务端
② 调用openAPI登录接口获取session_key

// ① 触发登录 wx.login()
wx.login({
  success (res) {
    if (res.code) {
      //发起网络请求
      wx.request({
        url: 'https://example.com/api/path/to/put/logincode',
        data: {
          code: res.code
        }
      })
 
    } else {
      console.log('登录失败!' + res.errMsg)
    }
  }
})
// ② 调用OpenAPI jscode2session
// GET https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code 
 
GET https://api.weixin.qq.com/sns/jscode2session 

Request 
      { 
        appid,  
        secret, // 小程序 appSecret 
        js_code, // ① wx.login()中code
        grant_type // authorization_code 
      }

 Response
    {
        session_key, // 目标数据
        unionid,
        openid,
        errmsg,
        errcode
    }

步骤3:解密手机号;服务端依据解密规则获取开发数据;(2种方式 服务端开发或云开发)

方式一:服务端开发 ① 校验签名 ② 解密开放数据

image.png


① 【签名】 调用接口(如 wx.getUserInfo)获取数据时,接口会同时返回 rawData、signature,其中 signature = sha1( rawData + session_key )
② 【解密】 将 signature、rawData 发送到开发者服务器进行校验。服务器利用用户对应的 session_key 使用相同的算法计算出签名 signature2 ,比对 signature 与 signature2 即可校验数据的完整性。 注意session_key的有效性,有效期或重新登录都有影响

方式二:云调用 ① 获取cloudId ② 调用云函数 具体详见解密规则

方案二:2.21.2 之后新方案

方案获取的code是前端获取手机号api的code,带着accessToken去调用最新的api接口去获取手机号,无需解密。

步骤1:获取动态令牌;前端通过用户主动触发,回调获得令牌

<button open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber"></button>
Page({
  getPhoneNumber (e) {
    console.log(e.detail.code)  // 【动态令牌】与方案一的差异 

    console.log(e.detail.errMsg) // 回调信息(成功失败都会返回)
    console.log(e.detail.errno)  // 错误码(失败时返回)
  }
})

步骤2:获取手机号;服务端通过通过动态令牌换取用户手机号。使用方法详情 phonenumber.getPhoneNumber 

POST https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=ACCESS_TOKEN 

Response { errorCode, errorMsg, phone_info }

phone_info { 
    phoneNumber: '+8613208021234', // 国内外带区号手机号
    purePhoneNumber: '13208021234', // 不带区号手机号
    countryCode: '86' // 区号
    watermark: { // 水印
      timestamp: 123455, // 获取手机号的时间戳
      appid: 'xxxxxx', // 小程序appid
    }
 } 


FAQ