[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; } ```