題幹與適用場景
一個多商戶支付平台希望在結帳時讓使用者確認收款方、金額和幣別,並產生可由銀行或支付服務驗證的密碼學證據。團隊考慮採用 W3C 於 2026 年 7 月 2 日發布的 Secure Payment Confirmation Candidate Recommendation Draft(SPC)。商戶頁面、支付編排服務和發卡行驗證頁可能來自不同來源,舊瀏覽器仍需繼續使用現有驗證方式。
請設計從 SPC 憑證註冊到驗證斷言的完整系統,說明第三方如何代表依賴方發起驗證、哪些資料必須由伺服器綁定、如何處理 API 不可用、使用者取消、重複支付和回滾。該規範仍是草案,不能把草案狀態當成所有瀏覽器都已穩定支援。
面試官考察點
面試官看重候選人是否把「使用者看到的交易明細」「伺服器批准的訂單」和「驗證斷言」綁定在同一筆交易上,能否解釋 SPC 與 WebAuthn 的關係及跨來源呼叫的風險。
強回答還會涵蓋 payment Permission Policy、securePaymentConfirmationAvailability() 的隱私限制、憑證隔離、冪等鍵、風控降級、證據保存和灰度開關,而不是只描述彈出一個生物辨識對話框。
回答前需要澄清的問題
- SPC 憑證由誰註冊,是否與登入憑證分離?
- 發卡行、商戶和支付編排服務各自是什麼來源,誰是 WebAuthn Relying Party?
- 驗證資料是否包含金額、收款方、幣別、訂單號和過期時間?
- 不支援 SPC 或使用者取消時,現有驗證路徑能否安全接管?
- 重試、重複回呼、退款和爭議處理需要保存哪些證據?
30 秒回答框架
「我會先把訂單和驗證交易建立不可變的伺服器記錄,再註冊專用 SPC 憑證並限制呼叫來源。結帳時由伺服器產生一次性 challenge 和訂單摘要,商戶把已批准的支付資料傳給 SPC,回呼後由伺服器驗證來源、challenge、憑證、使用者驗證結果和訂單狀態。能力不可用或使用者取消時走原有驗證,但不能把『沒有 SPC』當成支付成功。所有狀態用冪等鍵推進,先小流量驗證失敗率、爭議率和回退率,異常時關閉 SPC 新請求並保留進行中交易證據。」
分步驟深入解答
先劃分來源與憑證所有權
SPC 建立在 WebAuthn 之上,但允許第三方代表依賴方觸發驗證。平台應為支付憑證使用專用 Relying Party ID 或支付子網域,避免登入憑證與支付憑證混用。註冊介面只接受伺服器簽發的使用者和商戶綁定權杖,記錄憑證 ID、來源、建立時間、撤銷狀態和裝置綁定屬性;絕不讓瀏覽器提交任意 Relying Party ID 作為可信事實。
把訂單狀態綁定到 challenge
伺服器建立 payment_attempt,保存訂單版本、金額、幣別、收款方、challenge、過期時間和冪等鍵。challenge 必須一次性消費,訂單修改、幣別轉換或收款方變更都要產生新嘗試。客戶端展示的明細來自同一份伺服器簽名或摘要,不能讓商戶前端自行拼接金額後直接呼叫 SPC。
type PaymentAttempt = {
id: string;
orderVersion: number;
amountMinor: bigint;
currency: string;
payeeOrigin: string;
challenge: Uint8Array;
expiresAt: Date;
status: "created" | "authorizing" | "approved" | "cancelled" | "expired";
};設計跨來源呼叫邊界
SPC 的關鍵變化是第三方可以使用另一依賴方的憑證發起驗證,因此必須把 caller、Relying Party、訂單和允許的驗證來源寫入伺服器策略。嵌入支付 iframe 前配置 payment Permission Policy,並校驗頂層頁面與商戶白名單。跨來源斷言回到第三方後,第三方只能得到完成該筆交易所需的結果,不得藉機請求任意 WebAuthn 擴充或讀取登入憑證。
做能力偵測與相容回退
優先呼叫 PaymentRequest.securePaymentConfirmationAvailability(),把 available 與不可用原因分開記錄;該介面可能回傳模糊原因以降低指紋風險。能力可用仍不代表特定憑證存在,因此不能把偵測結果當作授權。回退鏈可按風控等級選擇 SPC、銀行驗證、一次性驗證碼或人工複核;每條路徑都必須重新校驗訂單狀態和 challenge,禁止「SPC 失敗就直接標記成功」。
驗證斷言和交易語義
伺服器驗證客戶端資料來源、challenge、Relying Party ID、簽章、使用者驗證標誌、憑證狀態和訂單摘要。支付服務收到斷言後先以條件更新搶占 created 狀態,再執行扣款;重複回呼只回傳同一結果。若金額或收款方摘要不匹配,標記安全失敗並阻止重試放大攻擊面。斷言本身只證明使用者完成驗證,不等同於資金已結算。
處理取消、逾時和故障
使用者取消、無可用驗證器、瀏覽器關閉和銀行逾時都進入可區分的終態,客戶端可以重試但必須產生新的 attempt。支付閘道逾時不能自動重放原 challenge;透過查詢冪等鍵確認扣款結果,再決定展示待確認、成功或人工介入。支付服務、商戶和發卡行之間的事件要帶版本號,拒絕舊事件覆蓋新狀態。
觀測風控與證據保存
按瀏覽器版本、來源組合、驗證方式和風險分層統計 SPC 可用率、使用者取消率、斷言驗證失敗、重複回呼、回退率、扣款延遲和爭議率。日誌保存訂單摘要雜湊、憑證 ID 的不可逆標識、attempt ID、策略版本和驗證結果,不記錄原始生物特徵或私鑰。對跨來源異常、相同憑證高頻嘗試和金額突變設定限流與二次複核。
灰度、回滾與安全測試
先在內部商戶和低風險金額開啟,隨後按瀏覽器、來源和地區分層擴大。測試跨來源 iframe、缺少 Permission Policy、使用者拒絕、憑證不存在、challenge 重放、訂單修改、重複回呼、閘道逾時和退款競態。回滾時關閉新 attempt 的 SPC 建立,保留已進入驗證的交易並讓它們按狀態機完成;新交易切回舊驗證,不能刪除斷言和訂單證據。
高品質示範回答
「SPC 是驗證證據產生器,不是支付結算本身。我會用伺服器 payment_attempt 把訂單版本、金額、收款方、challenge、來源策略和冪等鍵綁定起來;支付憑證與登入憑證分離,並透過 Permission Policy 限制跨來源呼叫。驗證後檢查 WebAuthn 斷言和訂單摘要,再以條件更新推進扣款狀態。能力不可用、取消或逾時都走明確回退,重複回呼只回傳已確定結果。灰度階段觀測斷言失敗、回退、爭議和跨來源異常;發現問題就停止新 SPC 請求,保留進行中證據並將新交易切回舊路徑。」
常見錯誤
- 把
available當成有憑證 → 使用者仍可能無法驗證 → 把能力偵測和憑證可用分開處理。 - 讓前端決定金額 → 使用者確認內容與扣款金額不一致 → 由伺服器訂單摘要和 challenge 綁定。
- 把跨來源呼叫當成普通登入 → 可能洩露登入憑證或擴大擴充權限 → 隔離支付憑證並限制 caller。
- SPC 失敗就標記支付成功 → 驗證失敗被誤當成結算成功 → 驗證、扣款、結算分別建狀態。
- 重試複用 challenge → 斷言可被重放 → 一次性消費並為新 attempt 產生新 challenge。
- 回滾刪除全部記錄 → 爭議和重複扣款無法追溯 → 凍結新請求,保留進行中狀態與證據。
追問及應對
追問一:為什麼不直接複用登入 passkey?
支付與登入的威脅模型、來源和授權目的不同。規範允許 WebAuthn 憑證參與 SPC,但平台仍可用支付子網域和獨立憑證降低登入攻擊面;若複用,必須明確斷言用途、Relying Party 和伺服器校驗邊界。
追問二:如何避免商戶把 1 元展示給使用者卻扣 100 元?
商戶前端不能成為金額真源。支付服務根據訂單版本產生摘要並傳給驗證流程,扣款服務只接受同一 attempt 的摘要和金額;斷言驗證通過後再次讀取不可變訂單,任何欄位變化都要求新 attempt。
追問三:securePaymentConfirmationAvailability() 回傳不可用原因有什麼風險?
過細原因可能形成裝置或設定指紋,因此使用者代理可以回傳 unavailable-unknown-reason。業務只把結果用於體驗選擇,不把原因作為使用者畫像、風控分數或授權依據。
追問四:支付服務逾時後能否再次呼叫 SPC?
先按冪等鍵查詢扣款和驗證狀態。若原 attempt 仍未終態,不能盲目重放;需要明確取消或過期後建立新 attempt,重新產生 challenge 和訂單摘要。