对于特定的信用卡或银行账户,商家可以在强健的客户身份验证 (SCA) 流程中使用安全付款确认 (SPC)。WebAuthn 会执行身份验证(通常是通过生物识别)。您必须提前注册 WebAuthn,相关信息请参阅注册安全付款确认。
典型实现的工作原理
SPC 最常见的用途是,顾客在商家的网店购物 网站,并且信用卡发卡机构或银行要求付款人进行身份验证。
我们来了解一下身份验证流程:
- 客户提供其付款凭据(例如信用卡) 信息)。
- 商家询问付款凭据的对应发卡机构或银行
(依赖方或 RP)。这个
例如
EMV® 3-D Secure。
- 如果 RP 希望商家使用 SPC,并且用户之前 RP 会在响应中包含 和验证。
- 如果不需要身份验证,商家可以继续 以便完成交易
- 如果需要进行身份验证,则由商家确定浏览器是否支持 SPC。
- 如果浏览器不支持 SPC,则使用现有的 身份验证流程。
- 商家调用 SPC。浏览器会显示一个确认对话框。
- 如果没有从 RP 传递的凭据 ID,则回退到 现有身份验证流程。 成功通过身份验证后,请考虑使用 SPC 注册 简化未来的身份验证流程。
- 用户确认和验证 通过解锁设备进行付款。
- 商家通过身份验证接收凭据。
- RP 从商家接收凭据并验证其 真实性
- RP 将验证结果发送给商家。
- 商家向用户显示一条消息,说明付款是否 无论成功还是失败
功能检测
要检测浏览器是否支持 SPC,您可以向
canMakePayment()
。
复制并粘贴以下代码,以在商家网站上实现 SPC 检测功能。
const isSecurePaymentConfirmationSupported = async () => {
if (!'PaymentRequest' in window) {
return [false, 'Payment Request API is not supported'];
}
try {
// The data below is the minimum required to create the request and
// check if a payment can be made.
const supportedInstruments = [
{
supportedMethods: "secure-payment-confirmation",
data: {
// RP's hostname as its ID
rpId: 'rp.example',
// A dummy credential ID
credentialIds: [new Uint8Array(1)],
// A dummy challenge
challenge: new Uint8Array(1),
instrument: {
// Non-empty display name string
displayName: ' ',
// Transparent-black pixel.
icon: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+P+/HgAFhAJ/wlseKgAAAABJRU5ErkJggg==',
},
// A dummy merchant origin
payeeOrigin: 'https://non-existent.example',
}
}
];
const details = {
// Dummy shopping details
total: {label: 'Total', amount: {currency: 'USD', value: '0'}},
};
const request = new PaymentRequest(supportedInstruments, details);
const canMakePayment = await request.canMakePayment();
return [canMakePayment, canMakePayment ? '' : 'SPC is not available'];
} catch (error) {
console.error(error);
return [false, error.message];
}
};
isSecurePaymentConfirmationSupported().then(result => {
const [isSecurePaymentConfirmationSupported, reason] = result;
if (isSecurePaymentConfirmationSupported) {
// Display the payment button that invokes SPC.
} else {
// Fallback to the legacy authentication method.
}
});
对用户进行身份验证
如需对用户进行身份验证,请使用以下代码调用 PaymentRequest.show()
方法:
secure-payment-confirmation
和 WebAuthn 参数:
PublicKeyCredentialRequestOptions
- 商家平台上的其他付款专用参数。
以下是您应该提供给付款方式的 data
属性 SecurePaymentConfirmationRequest
的参数。
请查看此示例代码:
// After confirming SPC is available on this browser via a feature detection,
// fetch the request options cross-origin from the RP server.
const options = fetchFromServer('https://rp.example/spc-auth-request');
const { credentialIds, challenge } = options;
const request = new PaymentRequest([{
// Specify `secure-payment-confirmation` as payment method.
supportedMethods: "secure-payment-confirmation",
data: {
// The RP ID
rpId: 'rp.example',
// List of credential IDs obtained from the RP server.
credentialIds,
// The challenge is also obtained from the RP server.
challenge,
// A display name and an icon that represent the payment instrument.
instrument: {
displayName: "Fancy Card ****1234",
icon: "https://rp.example/card-art.png",
iconMustBeShown: false
},
// The origin of the payee (merchant)
payeeOrigin: "https://merchant.example",
// The number of milliseconds to timeout.
timeout: 360000, // 6 minutes
}
}], {
// Payment details.
total: {
label: "Total",
amount: {
currency: "USD",
value: "5.00",
},
},
});
try {
const response = await request.show();
// response.details is a PublicKeyCredential, with a clientDataJSON that
// contains the transaction data for verification by the issuing bank.
// Make sure to serialize the binary part of the credential before
// transferring to the server.
const result = fetchFromServer('https://rp.example/spc-auth-response', response.details);
if (result.success) {
await response.complete('success');
} else {
await response.complete('fail');
}
} catch (err) {
// SPC cannot be used; merchant should fallback to traditional flows
console.error(err);
}
.show()
函数会生成一个
PaymentResponse
对象(details
除外)包含具有
包含交易数据的 clientDataJSON
(payment
)
供 RP 进行验证。
生成的凭据必须跨源传输到 RP,并且 已通过验证。
RP 如何验证交易
在 RP 服务器上,验证交易数据是 付款流程
为了验证交易数据,RP 可以按照 WebAuthn 的身份验证断言验证流程进行操作。
此外,他们还需要
验证 payment
。
clientDataJSON
的载荷示例:
{
"type":"payment.get",
"challenge":"SAxYy64IvwWpoqpr8JV1CVLHDNLKXlxbtPv4Xg3cnoc",
"origin":"https://spc-merchant.glitch.me",
"crossOrigin":false,
"payment":{
"rp":"spc-rp.glitch.me",
"topOrigin":"https://spc-merchant.glitch.me",
"payeeOrigin":"https://spc-merchant.glitch.me",
"total":{
"value":"15.00",
"currency":"USD"
},
"instrument":{
"icon":"https://cdn.glitch.me/94838ffe-241b-4a67-a9e0-290bfe34c351%2Fbank.png?v=1639111444422",
"displayName":"Fancy Card 825809751248"
}
}
}
rp
与 RP 的来源一致。topOrigin
与 RP 预期的顶级来源一致(即 商家的来源)。payeeOrigin
与应 显示给用户total
与应该显示的交易金额一致 。instrument
与应具有的 向用户展示的所有图片
const clientData = base64url.decode(response.clientDataJSON);
const clientDataJSON = JSON.parse(clientData);
if (!clientDataJSON.payment) {
throw 'The credential does not contain payment payload.';
}
const payment = clientDataJSON.payment;
if (payment.rp !== expectedRPID ||
payment.topOrigin !== expectedOrigin ||
payment.payeeOrigin !== expectedOrigin ||
payment.total.value !== '15.00' ||
payment.total.currency !== 'USD') {
throw 'Malformed payment information.';
}
通过所有验证标准后,RP 可以告知 表明交易成功。
后续步骤
- 阅读安全付款确认概览
- 了解如何通过安全付款确认功能进行注册