wx:获取微信手机号

  1. 获取微信手机号

获取微信手机号

  1. 获取手机号的按钮

    <!-- 用户展示手机号,无法输入 -->
    <uni-easyinput class="input disabled-input-click" placeholder="清输入手机号"
      v-model.trim="formData.phone" disabled />
    
    <!-- open-type:开放能力 是配合某些事件的,比如
       @getphonenumber:获取用户手机号回调,使用这个函数的前提是 open-type="getPhoneNumber"
       @getphonenumber:微信、支付宝、百度、抖音、快手、京东小程序、小红书小程序
    -->
    <button size="mini" open-type="getPhoneNumber" @getphonenumber="getPhone">获取手机号</button>
    
  2. 点击按钮的时候,会先出现一个弹窗。这个时候还没有触发getPhone方法。无论点击Cancel还是Authorize都会触发getPhone方法

  3. 点击Cancel时,组件传递的值:

  4. 点击Authorize组件传递的值:

  5. 上面的整个流程是这样的

    // 1. 开发者只定义了按钮
    <button open-type="getPhoneNumber" @getphonenumber="getPhone">
      获取手机号
    </button>
    
    // 2. 用户点击按钮
    //    ↓
    // 3. 微信客户端检测到 open-type="getPhoneNumber"
    //    ↓
    // 4. 微信客户端检查权限:
    //    - 小程序是否有权限请求手机号(企业认证)
    //    - 用户是否已登录微信
    //    - 用户是否之前拒绝过授权
    //    ↓
    // 5. 微信客户端在系统层渲染弹窗
    //    ↓
    // 6. 用户操作弹窗:
    //    - 点击"允许" → 生成code,回调 getPhone 并传入 code
    //    - 点击"拒绝" → 生成错误信息,回调 getPhone 并传入错误
    //    ↓
    // 7. 你的 getPhone 方法被执行
    
  6. 这个弹窗是微信App内置的系统级授权弹窗,由微信客户端直接渲染和控制,不是小程序前端代码可以模拟或自定义的。

  7. code 是由微信客户端生成的:当用户点击 <button open-type="getPhoneNumber"> 并授权后,微信客户端(微信App本身)会在本地生成一个临时的、一次性的授权凭证(code),并通过 @getphonenumber 回调返回给你的前端。

    getPhone(e) {
      const code = e.detail.code;  // 这是微信客户端生成的临时凭证
    }
    

    这个 code 实际上是一个加密的授权票据,包含了:

    • 用户的身份信息(openId 的加密映射)
    • 授权时间戳
    • 授权范围(获取手机号)
    • 小程序的 AppID

    这个 code 具有以下特性:

    • 时效性:通常有效期为5分钟
    • 一次性:使用后立即失效
    • 绑定性:与特定小程序、特定用户、特定授权绑定
  8. 前端getPhone代码,调用后端,传入e.detail.code获取电话号码。不能在前端直接获取,因为需要用到appid和secret,在前端获取不安全。

    const toolsCloudObj = uniCloud.importObject('public-tools', {customUI: true});
    const getPhone = async (e) => {
      try {
        console.log(e.detail);
    
        showLoading({
          title: '获取中',
          mask: true
        });
        // 使用解构赋值
        let {data:{phone_info:{phoneNumber}}} = await toolsCloudObj.phone({
          code: e.detail.code
        });
        formData.value.phone = phoneNumber;
      } finally {
        hideLoading();
      }
    };
    
  9. 后端获取电话的代码:

    //unicloud云对象内的phone方法,params是客户端传来的值
    async phone(params){
      //调用微信凭证接口,获取access_token,传入appid和secret
      //在这里可以判断是否已经有access_token缓存,如果没有再去调用凭证接口,避免重复调用
      let {data:{access_token}} = await uniCloud.request({
        url:"https://api.weixin.qq.com/cgi-bin/token",
        data:{
          grant_type:"client_credential", // 填写 client_credential
          appid:"w...................5", // 账号的唯一凭证,即 AppID
          secret:"5c......................................43" //唯一凭证密钥,即 AppSecret
        }
      })
      let res = await uniCloud.request({
        url:"https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token="+access_token,
        method:"POST",
        data:{
          code:params.code
        }
      })
      return res;
    }
    
    • https://api.weixin.qq.com/cgi-bin/token:获取接口调用凭据。本接口用于获取获取全局唯一后台接口调用凭据(Access Token),token 有效期为 7200 秒。(getAccessToken

      • access_token微信服务端颁发给小程序的接口调用凭证,类似于一把”钥匙”或”通行证”。微信服务端需要验证”你是谁”,但又不能让前端直接使用 AppSecret(密钥),因此设计了 access_token 机制。为的是证明调用接口的是合法的小程序,而不是恶意攻击者。
      • 返回参数
        • access_token:获取到的凭证
        • expires_in:凭证有效时间,单位:秒。目前是7200秒之内的值。
      • access_token 使用说明里面,建议开发者使用中控服务器统一获取和刷新access_token,其他业务逻辑服务器所使用的access_token 均来自于该中控服务器,不应该各自去刷新,否则容易造成冲突,导致access_token覆盖而影响业务。
        • 在Java中应该是可以统一放在缓存里面,或者服务器文件
    • https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token="+access_token

      • 该接口用于将code换取用户手机号。 说明,每个code只能使用一次,code的有效期为5min。

      • 查询参数:access_token,接口调用凭证

      • 请求体:code,由微信客户端生

      • 返回参数:

        {
            "statusCode": 200,
            "header": {
                "connection": "keep-alive",
                "content-type": "application/json; charset=UTF-8",
                "content-length": "187"
            },
            "data": {
                "errcode": 0,
                "errmsg": "ok",
                "phone_info": {
                    "phoneNumber": "1..........7",
                    "purePhoneNumber": "1..........7",
                    "countryCode": "86",
                    "watermark": {
                        "timestamp": 1774245023,
                        "appid": "w....................5"
                    }
                }
            }
        }
        

×

喜欢就点赞,疼爱就打赏