你的小程序突然無法獲取用戶手機(jī)號,后臺錯誤日志顯示“該接口已廢棄”。微信在 2024 年徹底切斷了免費(fèi)解密手機(jī)號的舊通道,所有獲取手機(jī)號的請求必須通過官方付費(fèi)組件完成。如果你上次接入還是 getPhoneNumber + 后端解密,現(xiàn)在就需要重新理解一整套新規(guī)則:兩種組件、兩套接入方式、按次收費(fèi)的預(yù)購資源包,以及前端就能直接拿到的明文手機(jī)號。
手機(jī)號獲取方案的前世今生
小程序獲取手機(jī)號的核心能力是獲取微信側(cè)綁定的手機(jī)號,而不是讓用戶手動輸入。這一能力經(jīng)歷了三個(gè)階段:
- 免費(fèi)解密時(shí)代(已廢棄):前端通過
button組件設(shè)置open-type="getPhoneNumber",回調(diào)返回encryptedData和iv,后端利用session_key解密獲得手機(jī)號。不收費(fèi),但對后端解密邏輯、session_key有效期管理要求較高。 - 過渡期:微信推出“手機(jī)號快速驗(yàn)證組件”和“手機(jī)號實(shí)時(shí)驗(yàn)證組件”,兩種組件均需付費(fèi)使用,舊接口逐漸不可用。
- 2024 年現(xiàn)狀:舊接口徹底關(guān)閉。當(dāng)前只保留兩種手機(jī)號驗(yàn)證組件——“快速驗(yàn)證組件”和“實(shí)時(shí)驗(yàn)證組件”,均需預(yù)購資源包,按成功驗(yàn)證次數(shù)扣費(fèi)。
兩種組件的核心區(qū)別在于手機(jī)號的傳輸方式:
- 快速驗(yàn)證組件:返回加密數(shù)據(jù)
encryptedData和iv,需要后端配合session_key解密,流程與舊接口類似,但需要消耗購買的次數(shù)。 - 實(shí)時(shí)驗(yàn)證組件:微信服務(wù)器直接返回明文手機(jī)號給前端,免去后端解密環(huán)節(jié),開發(fā)者前端就能拿到手機(jī)號。
組件選擇與接入實(shí)現(xiàn)
你需要在兩種組件之間做出選擇。決策依據(jù)主要看兩點(diǎn):是否需要后端留存解密記錄,以及能否承受加解密帶來的維護(hù)成本。
快速驗(yàn)證組件:保留解密鏈路
如果你已有成熟的后端解密邏輯,并且需要將完整授權(quán)憑證(如 encryptedData、iv)存入數(shù)據(jù)庫以備審計(jì),快速驗(yàn)證組件是更平滑的遷移選項(xiàng)。
前端接入:在頁面使用 button 組件,設(shè)置 open-type="getPhoneNumber",綁定事件處理函數(shù)?;卣{(diào)中通過 e.detail 拿到 code,將該 code 傳給后端換取手機(jī)號。
<!-- 快速驗(yàn)證組件:通過 button 觸發(fā) -->
<button open-type="getPhoneNumber" bindgetphonenumber="handleGetPhoneNumber">
授權(quán)手機(jī)號
</button>
// 頁面 JS
handleGetPhoneNumber(e) {
if (e.detail.errMsg === 'getPhoneNumber:ok') {
const code = e.detail.code
// 將 code 發(fā)送到你的后端接口,換取手機(jī)號
wx.request({
url: 'https://your-api.com/decryptPhone',
data: { code },
success: (res) => {
console.log('手機(jī)號:', res.data.phoneNumber)
}
})
} else {
console.error('用戶拒絕授權(quán)或組件異常')
}
}
后端需要使用 code 調(diào)用微信接口 https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=ACCESS_TOKEN,發(fā)送 code 換取手機(jī)號。注意,這里返回的手機(jī)號已經(jīng)是明文,不需要自己解密 encryptedData——這是快速驗(yàn)證組件與舊接口的最大差異。舊接口返回 encryptedData,而新快速驗(yàn)證組件返回 code,后端用 code 直接換明文。如果你還看到 encryptedData 的文檔,那已經(jīng)是歷史版本。
實(shí)時(shí)驗(yàn)證組件:前端直接拿號
實(shí)時(shí)驗(yàn)證組件的核心優(yōu)勢是繞過所有后端解密流程,手機(jī)號直接返回到前端回調(diào)中。但代價(jià)是必須使用 <phone-dock> 組件(基礎(chǔ)庫 2.22.0+),且需要提前購買資源包并配置插件。
步驟一:購買資源包并添加插件
進(jìn)入微信小程序后臺 -> “開發(fā)” -> “開發(fā)設(shè)置” -> “手機(jī)號驗(yàn)證組件”,購買實(shí)時(shí)驗(yàn)證資源包(單價(jià) 0.03 元/次,具體以當(dāng)時(shí)定價(jià)為準(zhǔn))。然后在 app.json 中聲明插件:
{
"plugins": {
"phoneNumberPlugin": {
"version": "latest",
"provider": "wx1f9d5f5d6e7e8f9c"
}
}
}
注意 provider 值需從微信官方文檔獲取,這里使用占位符。
步驟二:頁面使用 <phone-dock>
<!-- 實(shí)時(shí)驗(yàn)證組件:phone-dock -->
<phone-dock
id="phoneDock"
show="{{showPhoneDock}}"
bindgetphonenumber="handleRealTimePhone"
/>
// 頁面 JS
Page({
data: {
showPhoneDock: false
},
onReady() {
// 必須等頁面渲染完成后初始化組件
this.phoneDock = this.selectComponent('#phoneDock')
},
// 在某個(gè)用戶點(diǎn)擊事件中觸發(fā)(例如點(diǎn)擊“獲取手機(jī)號”按鈕)
triggerPhoneAuth() {
if (this.phoneDock) {
this.phoneDock.show() // 調(diào)起手機(jī)號授權(quán)彈窗
}
},
handleRealTimePhone(e) {
const { detail } = e
if (detail.phoneNumber) {
console.log('明文字段:', detail.phoneNumber)
// 直接拿到手機(jī)號,無需后端解密
this.loginWithPhone(detail.phoneNumber)
} else {
console.error('實(shí)時(shí)驗(yàn)證失敗', detail)
}
}
})
實(shí)時(shí)驗(yàn)證組件只能通過用戶點(diǎn)擊事件中的同步調(diào)用 show() 來喚起,不支持自動彈出,這是微信強(qiáng)制的用戶行為檢查。
成本邊界與常見故障模式
1. 扣費(fèi)規(guī)則與資源包管理
兩種組件均按成功驗(yàn)證次數(shù)扣費(fèi),用戶點(diǎn)擊授權(quán)后即計(jì)費(fèi)一次,無論你的業(yè)務(wù)后續(xù)是否使用該手機(jī)號。資源包有有效期(通常為一年),過期未用完的次數(shù)作廢且不退款。建議根據(jù)你小程序的日活躍用戶量和授權(quán)轉(zhuǎn)化率估算購買量,避免一次性購入過多。
2. 組件降級不可混淆
實(shí)時(shí)驗(yàn)證組件在資源包耗盡或網(wǎng)絡(luò)異常時(shí),不會自動降級為快速驗(yàn)證組件。你的業(yè)務(wù)代碼必須設(shè)計(jì)容錯路徑:例如,當(dāng) handleRealTimePhone 回調(diào)無 phoneNumber 時(shí),引導(dǎo)用戶以手動輸入手機(jī)號的方式走短信驗(yàn)證碼登錄,或者提示“當(dāng)前授權(quán)擁擠,請稍后重試”。
3. 快速驗(yàn)證的 code 有效期
快速驗(yàn)證組件返回的 code 只有 5 分鐘有效期,且只能使用一次。如果你的后端處理鏈路較長,需確保在有效期內(nèi)完成換號請求,否則 code 過期會返回錯誤碼 -1。
4. 不要在前端暴露成本
無論日志還是 UI 提示,都不要出現(xiàn)“本次授權(quán)花費(fèi) 0.03 元”之類信息。微信服務(wù)端可能調(diào)整計(jì)費(fèi)規(guī)則,前端硬編碼價(jià)格會導(dǎo)致后續(xù)維護(hù)混亂,并且容易引起用戶不必要的追問。
5. 舊接口遷移的硬性死線
使用舊版 getPhoneNumber 返回 encryptedData 的接口已不可調(diào)用。如果你的基礎(chǔ)庫版本設(shè)置過低,微信會直接返回“該接口已廢棄”錯誤,需將基礎(chǔ)庫最低版本要求設(shè)置為 2.21.2 以上,并切換到上述組件之一。
行動建議
- 先清點(diǎn)業(yè)務(wù)場景:統(tǒng)計(jì)目前有哪些頁面需要獲取手機(jī)號(登錄、綁定、領(lǐng)券等),為每個(gè)場景選擇統(tǒng)一的組件類型,降低維護(hù)復(fù)雜度。
- 購買最小可用資源包:先用最小階梯包(例如 1000 次)跑通鏈路并驗(yàn)證呼叫量預(yù)估,再按需追加購買。資源包支持疊加,疊加后有效期以最后一個(gè)包的到期日為準(zhǔn)。
- 兼容手動輸入路徑:無論使用哪種驗(yàn)證組件,都應(yīng)保留“手動輸入手機(jī)號 + 驗(yàn)證碼”的兜底方案。微信手機(jī)號授權(quán)只覆蓋用戶曾綁定過手機(jī)號的情況,未綁定或海外號碼無法通過組件獲取。
- 埋點(diǎn)記錄成敗:在
handleGetPhoneNumber和handleRealTimePhone中加入業(yè)務(wù)埋點(diǎn),區(qū)分“用戶拒絕授權(quán)”“code 換取失敗”“實(shí)時(shí)驗(yàn)證無返回”三種異常,便于后續(xù)優(yōu)化轉(zhuǎn)化漏斗和排查成本異常。