使用安全支付確認
透過支付請求 API (Payment Request API) 可用的安全支付確認 (SPC) 提供了一種在結賬過程中進行強客戶身份驗證的機制,從而有效防止線上支付欺詐。
概述
為了防止線上支付欺詐,通常需要對賬戶持有人進行身份驗證。強身份驗證可以降低欺詐風險,但也會增加結賬過程中出現的阻礙導致購物車被放棄的可能性。因此,銀行、商家、支付服務提供商以及支付生態系統中的其他實體在決定每次交易應使用何種型別和強度的身份驗證時,會考慮多種因素,包括交易金額、購買的商品、使用者的支付歷史、欺詐發生時的責任方以及法規要求(例如 歐洲支付服務指令 2 關於強客戶身份驗證和使用者同意證明的要求)。
目前有多種機制結合使用以實現強身份驗證,包括密碼、一次性簡訊驗證碼、移動應用程式和 Web 身份驗證。每種方法都有其優缺點。例如,一次性簡訊驗證碼對使用者來說已相當熟悉,但可能存在可用性問題(如裝置不可用)和安全漏洞。Web 身份驗證提供了更好的安全性,並且可在所有主流瀏覽器、所有現代移動裝置和計算機上使用。然而,單獨的 Web 身份驗證並不能提供使用者同意進行支付的證明。
SPC 的設計旨在實現各種支付系統中簡化的強客戶身份驗證 (SCA),並提供加密證據證明使用者已同意交易條款。當呼叫該 API 時,瀏覽器會在對話方塊中顯示交易的要素:商戶名稱、支付工具、支付金額和貨幣。例如,這是 Chrome 瀏覽器(M118 版本)中 SPC 的交易對話方塊。

選擇“驗證”將啟動 Web 身份驗證流程。當用戶成功透過身份驗證後(例如,使用其手機或筆記型電腦上的生物識別身份驗證器),瀏覽器會將對話方塊中顯示的資料傳遞給身份驗證器,身份驗證器將對這些資料進行簽名,並將其作為最終的 Web 身份驗證斷言的一部分返回。然後,該斷言可以傳遞給依賴方進行驗證。由於瀏覽器直接將顯示的資料傳遞給身份驗證器(沒有任何 JavaScript 程式碼可以修改這些資料),因此依賴方可以高度確信使用者已同意顯示在對話方塊中的交易資料。
因此,SPC 在 Web 身份驗證的基礎上,使網站能夠執行簡化的強身份驗證並提供使用者同意的證明。SPC 通常將作為給定支付系統的身份驗證框架的一部分使用。例如,SPC 同時支援 EMV® 3-D Secure(2.3.1 版本)和 EMV® Secure Remote Commerce(1.3 版本),並且被設計用於支援各種支付型別,包括“推送支付”,如直接信用轉賬和錢包支付。
支付請求方法
安全支付確認利用了支付請求 API 的底層功能。安全支付確認支付處理程式的標準化支付方法識別符號是 "secure-payment-confirmation"。
Web 身份驗證擴充套件
安全支付確認定義了一個 Web 身份驗證擴充套件,稱為 payment,它在傳統 Web 身份驗證的基礎上增加了三個支付特定的功能。
- 當依賴方選擇啟用時,它允許除依賴方以外的實體使用依賴方的憑據啟動支付身份驗證流程。SPC 將身份驗證流程與身份驗證結果的驗證分離開來。這使得商家(或其支付服務提供商在跨域 iframe 中)能夠控制身份驗證的使用者體驗,而無需將使用者(透過重定向)轉發到另一個網站或移動應用程式。例如,如果依賴方是銀行,這就可以讓商家管理身份驗證的使用者體驗,同時銀行仍然可以驗證身份驗證的結果。各方之間(憑據和身份驗證結果)的通訊通常透過特定於支付系統的渠道進行,例如 EMV® 3-D Secure。
- 強制要求使用者代理正確地向用戶傳達他們正在進行交易身份驗證以及交易的詳細資訊。這些詳細資訊隨後將包含在身份驗證器簽名的斷言中。
- 允許在跨域 iframe 中呼叫 navigator.credentials.create,前提是 iframe 上設定了“payment”許可權策略。注意:此功能現在是 WebAuthn Level 3 的一部分,它使用“publickey-credential-create”許可權策略。建議開發者在可用時使用後者,而不是依賴 SPC 的“payment”許可權。
示例
建立憑據
在安全支付確認中建立憑據的操作與 Web 身份驗證的 navigator.credentials.create() 呼叫相同,但需要指定 payment 擴充套件。
const publicKey = {
challenge: Uint8Array.from(randomStringFromServer, (c) => c.charCodeAt(0)),
rp: {
name: "Fancy Bank",
},
user: {
// Assuming that userId is ASCII-only
id: Uint8Array.from(userId, (c) => c.charCodeAt(0)),
name: "jane.doe@example.org",
displayName: "Jane Doe",
},
pubKeyCredParams: [
{
type: "public-key",
alg: -7, // "ES256"
},
{
type: "public-key",
alg: -257, // "RS256"
},
],
authenticatorSelection: {
userVerification: "required",
residentKey: "required",
authenticatorAttachment: "platform",
},
timeout: 60000, // 1 minute
extensions: {
payment: {
isPayment: true,
},
},
};
navigator.credentials
.create({ publicKey })
.then((newCredentialInfo) => {
// Send new credential info to server for verification and registration.
})
.catch((err) => {
// No acceptable authenticator or user refused consent. Handle appropriately.
});
在跨域 iframe 中建立憑據
SPC 允許在跨域 iframe 中建立憑據(例如,如果 merchant.com 嵌入了來自 bank.com 的 iframe)。
在此流程中,作為交易的一部分,依賴方(例如銀行)透過除 SPC 以外的某種機制(例如,使用一次性密碼或其他機制)對賬戶持有人進行身份驗證。然後,依賴方向使用者提供註冊 SPC 憑據以簡化未來交易的選項。使用者向依賴方註冊 SPC 憑據。為了使這些步驟能在商家上下文中進行(即,無需重定向),跨域 iframe 必須設定 payment 許可權策略。
例如
<!-- Assume parent origin is merchant.com -->
<!-- Inside this cross-origin iframe, script would be allowed to create a SPC credential for example.org -->
<iframe src="https://example.org" allow="payment"></iframe>
驗證支付
某個源可以呼叫帶有 "secure-payment-confirmation" 支付方法的支付請求 API,以提示使用者驗證由任何其他源建立的安全支付確認憑據。瀏覽器將顯示一個原生使用者介面(“交易對話方塊”),其中包含交易詳情(例如,支付貨幣和金額以及收款方源)。
注意:根據支付請求 API 的規定,如果在跨域 iframe 中使用 PaymentRequest(例如,如果 merchant.com 嵌入了來自 psp.com 的 iframe,而 psp.com 希望使用 PaymentRequest),則該 iframe 必須設定 payment 許可權策略。
const request = new PaymentRequest(
[
{
supportedMethods: "secure-payment-confirmation",
data: {
// List of credential IDs obtained from the Account Provider.
credentialIds,
// The challenge is also obtained from the Account Provider.
challenge: new Uint8Array(randomStringFromServer, (c) =>
c.charCodeAt(0),
),
instrument: {
displayName: "Fancy Card ****1234",
icon: "https://fancybank.com/card-art.png",
},
payeeOrigin: "https://merchant.com",
timeout: 60000, // 1 minute
},
},
],
{
total: {
label: "Total",
amount: {
currency: "USD",
value: "5.00",
},
},
},
);
try {
// NOTE: canMakePayment() checks only public information for whether the SPC
// call is valid. To preserve user privacy, it does not check whether any
// passed credentials match the current device.
const canMakePayment = await request.canMakePayment();
if (!canMakePayment) {
throw new Error("Cannot make payment");
}
const response = await request.show();
await response.complete("success");
// response.details is a PublicKeyCredential, with a clientDataJSON that
// contains the transaction data for verification by the issuing bank.
// send response.details to the issuing bank for verification
} catch (err) {
// SPC cannot be used; merchant should fallback to traditional flows
}
在開始支付流程之前,可以透過呼叫 PaymentRequest.securePaymentConfirmationAvailability() 靜態方法來確定 SPC 是否可用。例如:
async function spcSupport() {
const support = await PaymentRequest.securePaymentConfirmationAvailability();
if (support === "available") {
// Commence SPC payment flow
} else {
// Fallback to traditional flows
}
}
規範
| 規範 |
|---|
| Payment Request API |
| 支付方法識別符號 |
| Web Authentication:訪問公鑰憑證的 API - 第 3 級 |