你的小程序突然無法獲取用戶手機(jī)號,后臺錯誤日志顯示“該接口已廢棄”。微信在 2024 年徹底切斷了免費(fèi)解密手機(jī)號的舊通道,所有獲取手機(jī)號的請求必須通過官方付費(fèi)組件完成。如果你上次接入還是 getPhoneNumber + 后端解密,現(xiàn)在就需要重新理解一整套新規(guī)則:兩種組件、兩套接入方式、按次收費(fèi)的預(yù)購資源包,以及前端就能直接拿到的明文手機(jī)號。

手機(jī)號獲取方案的前世今生

小程序獲取手機(jī)號的核心能力是獲取微信側(cè)綁定的手機(jī)號,而不是讓用戶手動輸入。這一能力經(jīng)歷了三個(gè)階段:

  1. 免費(fèi)解密時(shí)代(已廢棄):前端通過 button 組件設(shè)置 open-type="getPhoneNumber",回調(diào)返回 encryptedDataiv,后端利用 session_key 解密獲得手機(jī)號。不收費(fèi),但對后端解密邏輯、session_key 有效期管理要求較高。
  2. 過渡期:微信推出“手機(jī)號快速驗(yàn)證組件”和“手機(jī)號實(shí)時(shí)驗(yàn)證組件”,兩種組件均需付費(fèi)使用,舊接口逐漸不可用。
  3. 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ù) encryptedDataiv,需要后端配合 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)憑證(如 encryptedDataiv)存入數(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)記錄成敗:在 handleGetPhoneNumberhandleRealTimePhone 中加入業(yè)務(wù)埋點(diǎn),區(qū)分“用戶拒絕授權(quán)”“code 換取失敗”“實(shí)時(shí)驗(yàn)證無返回”三種異常,便于后續(xù)優(yōu)化轉(zhuǎn)化漏斗和排查成本異常。
← 上一篇 在德清開發(fā)微信小程序,為什么模板套用這條路走不遠(yuǎn) 下一篇 → 百度 SEO 與 Google SEO:同一套打法,為什么在另一個(gè)搜索引擎上失效?