[TOC] #### 1. 前言 --- **特别注意:个人号小程序无法使用** **目前该接口针对非个人开发者,且完成了认证的小程序开放(不包含海外主体)** 微信开发文档: [https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/getPhoneNumber.html](https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/getPhoneNumber.html) #### 2. 获取用户授权手机号 button 组件 --- 定义按钮组件,用于调起授权手机号弹窗 ```html <button open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber">获取手机号</button> ``` `bindgetphonenumber` 事件回调 ```javascript methods: { // 获取用户授权的手机号 getPhoneNumber: e => { if (e.detail.errMsg === 'getPhoneNumber:ok') { wx.request({ url: 'http://tp6.cy/', method: 'POST', data: { iv: e.detail.iv, encryptedData: e.detail.encryptedData, }, success: res => { console.log(res) } }) } else { wx.showToast({ title: '拒绝授权', }) } }, } ``` 将以下数据传给后端,后台可通过解密数据得到手机号 ```json { "encryptedData": "PIxZLRab9M9EQha6Od5WA5NT...", "iv": "CVN4qd7zUe6+vz9wuAvReQ==" } ``` #### 3. 使用 EasyWechat 4.x 消息解密获取手机号 --- ```html composer require overtrue/wechat:~4.0 ``` 消息解密文档: [https://easywechat.com/docs/4.x/mini-program/decrypt](https://easywechat.com/docs/4.x/mini-program/decrypt) **一、获取小程序相关功能所属实例** ``` $app = Factory::miniProgram($config); ``` https://easywechat.com/docs/4.x/mini-program/index **二、进行消息解密时最好使用 `try catch` 捕获可能出现的异常** ``` try { // 消息解密 // $session 根据 wx.login 的临时登录凭证 code 换取的 session_key // $iv, $encryptedData 在 bindgetphonenumber 事件回调中获取 $decryptedData = $app->encryptor->decryptData($session, $iv, $encryptedData); } catch (\Throwable $th) { // 解密失败 // 当使用的$session已过期时,解密会抛出异常, // 此时错误信息:The given payload is invalid. echo $th->getMessage(); } // 手机号为空代表解密失败 fault 是自定义的抛出异常的函数 empty($decryptedData['phoneNumber']) && fault('解密失败'); // 解密成功后的操作 // ... ``` **三、解密成功 `$decryptedData` 的值** ``` { "phoneNumber": "15037846666", "purePhoneNumber": "15037846666", "countryCode": "86", "watermark": { "timestamp": 1622695392, "appid": "wxb80ec74221f8a9ff" } } ``` #### 4. 在 EasyWechat 4.x 使用新接口获取手机号 --- 从基础库 2.21.2 开始,对获取手机号的接口进行了安全升级,bindgetphonenumber 事件回调方法中的 e.detail 中增加了一个 code 属性。新版本接口不再需要提前调用 wx.login 进行登录(调用 wx.login 是为了获取 session_key) ``` { "code": "dbad746bbaf51214f081e133668cc5a5ebbb9a526ad9e7b503e337a59c60414c", "encryptedData": "PIxZLRab9M9EQha6Od5WA5NT...", "iv": "CVN4qd7zUe6+vz9wuAvReQ==" } ``` 前端开发者只需要将上面的 code 传递给接口,后端开发者就能获取到手机号,因为这个接口是新版的,EasyWechat4.x 还没有更新,所以需要自己手动调用新版接口,代码示例如下所示 ``` /** * 获取用户授权手机号 * @param string $code */ function getPhoneNumber(string $code) { $app = Factory::miniProgram($config); $access_token = $app->access_token->getToken()['access_token']; $url = 'https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=' . $access_token; // 使用 curl 发送网络请求 $result = https_request($url, json_encode(['code' => $code])); $array = json_decode($res, true); if (isset($array['errcode']) && $array['errcode'] == 0) { // 获取成功 // 手机号: $array['phone_info']['phoneNumber'] } else { // 获取失败 } } /** * http请求 * @param string $url 请求的地址 * @param string $data 请求参数 */ function https_request($url, $data = null) { $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); if (!empty($data)) { curl_setopt($curl, CURLOPT_POST, 1); curl_setopt($curl, CURLOPT_POSTFIELDS, $data); } curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); $output = curl_exec($curl); curl_close($curl); return $output; } ```