[TOC] #### 1. 前言 --- **特別注意:個(gè)人號(hào)小程序無法使用** **目前該接口針對(duì)非個(gè)人開發(fā)者,且完成了認(rèn)證的小程序開放(不包含海外主體)** 微信開發(fā)文檔: [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. 獲取用戶授權(quán)手機(jī)號(hào) button 組件 --- 定義按鈕組件,用于調(diào)起授權(quán)手機(jī)號(hào)彈窗 ```html <button open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber">獲取手機(jī)號(hào)</button> ``` `bindgetphonenumber` 事件回調(diào) ```javascript methods: { // 獲取用戶授權(quán)的手機(jī)號(hào) 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: '拒絕授權(quán)', }) } }, } ``` 將以下數(shù)據(jù)傳給后端,后臺(tái)可通過解密數(shù)據(jù)得到手機(jī)號(hào) ```json { "encryptedData": "PIxZLRab9M9EQha6Od5WA5NT...", "iv": "CVN4qd7zUe6+vz9wuAvReQ==" } ``` #### 3. 使用 EasyWechat 4.x 消息解密獲取手機(jī)號(hào) --- ```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) **一、獲取小程序相關(guān)功能所屬實(shí)例** ``` $app = Factory::miniProgram($config); ``` https://easywechat.com/docs/4.x/mini-program/index **二、進(jìn)行消息解密時(shí)最好使用 `try catch` 捕獲可能出現(xiàn)的異常** ``` try { // 消息解密 // $session 根據(jù) wx.login 的臨時(shí)登錄憑證 code 換取的 session_key // $iv, $encryptedData 在 bindgetphonenumber 事件回調(diào)中獲取 $decryptedData = $app->encryptor->decryptData($session, $iv, $encryptedData); } catch (\Throwable $th) { // 解密失敗 // 當(dāng)使用的$session已過期時(shí),解密會(huì)拋出異常, // 此時(shí)錯(cuò)誤信息:The given payload is invalid. echo $th->getMessage(); } // 手機(jī)號(hào)為空代表解密失敗 fault 是自定義的拋出異常的函數(shù) empty($decryptedData['phoneNumber']) && fault('解密失敗'); // 解密成功后的操作 // ... ``` **三、解密成功 `$decryptedData` 的值** ``` { "phoneNumber": "15037846666", "purePhoneNumber": "15037846666", "countryCode": "86", "watermark": { "timestamp": 1622695392, "appid": "wxb80ec74221f8a9ff" } } ``` #### 4. 在 EasyWechat 4.x 使用新接口獲取手機(jī)號(hào) --- 從基礎(chǔ)庫(kù) 2.21.2 開始,對(duì)獲取手機(jī)號(hào)的接口進(jìn)行了安全升級(jí),bindgetphonenumber 事件回調(diào)方法中的 e.detail 中增加了一個(gè) code 屬性。新版本接口不再需要提前調(diào)用 wx.login 進(jìn)行登錄(調(diào)用 wx.login 是為了獲取 session_key) ``` { "code": "dbad746bbaf51214f081e133668cc5a5ebbb9a526ad9e7b503e337a59c60414c", "encryptedData": "PIxZLRab9M9EQha6Od5WA5NT...", "iv": "CVN4qd7zUe6+vz9wuAvReQ==" } ``` 前端開發(fā)者只需要將上面的 code 傳遞給接口,后端開發(fā)者就能獲取到手機(jī)號(hào),因?yàn)檫@個(gè)接口是新版的,EasyWechat4.x 還沒有更新,所以需要自己手動(dòng)調(diào)用新版接口,代碼示例如下所示 ``` /** * 獲取用戶授權(quán)手機(jī)號(hào) * @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 發(fā)送網(wǎng)絡(luò)請(qǐng)求 $result = https_request($url, json_encode(['code' => $code])); $array = json_decode($res, true); if (isset($array['errcode']) && $array['errcode'] == 0) { // 獲取成功 // 手機(jī)號(hào): $array['phone_info']['phoneNumber'] } else { // 獲取失敗 } } /** * http請(qǐng)求 * @param string $url 請(qǐng)求的地址 * @param string $data 請(qǐng)求參數(shù) */ 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; } ```