使用安全支付确认

安全上下文:此功能仅在安全上下文(HTTPS)中可用,部分或所有支持的浏览器中。

安全支付确认 (SPC) 通过支付请求 API 提供,为结账过程中提供强大的客户身份验证机制,从而防止在线支付欺诈。

概述

为了防止在线支付欺诈,通常需要对账户持有人进行身份验证。 强烈身份验证可以降低欺诈风险,但也会增加结账过程中的摩擦,导致购物车放弃。 因此,银行、商家、支付服务提供商和支付生态系统中的其他实体在决定对每笔交易使用何种类型和强度的身份验证时,会考虑许多因素,包括交易金额、所购商品、用户的支付历史记录、欺诈情况下哪方承担责任以及监管要求(例如,欧洲支付服务指令 2 对强大的客户身份验证和用户同意证据的要求)。

多种机制结合使用以实现强大身份验证,包括密码、一次性短信代码、移动应用程序和 Web 身份验证。 每个机制都有其优势和劣势。 例如,一次性短信代码现在已为用户所熟悉,但可能会涉及可用性问题(例如设备不可用)和安全漏洞。 Web 身份验证提供更好的安全性,可在所有主流浏览器以及所有现代移动设备和计算机中使用。 然而,仅凭 Web 身份验证无法提供用户同意进行支付的证据。

SPC 旨在支持多种支付系统中的简化强大客户身份验证 (SCA),并提供用户已同意交易条款的加密证据。 当调用该 API 时,浏览器会在对话框中显示交易的某些元素:商家名称、支付工具以及支付金额和货币。 例如,以下是 Chrome 浏览器(M118 版本)用于 SPC 的交易对话框

Chrome M118 transaction dialog for SPC

选择“验证”将启动 Web 身份验证流程。 当用户成功进行身份验证(例如,使用其手机或笔记本电脑上的生物识别身份验证器)后,浏览器会将对话框中显示的数据传递到身份验证器,身份验证器会对其进行签名并将其作为 Web 身份验证断言的一部分返回。 然后,断言可以传递给依赖方以进行验证。 由于浏览器直接将显示的数据传递到身份验证器(没有任何 JavaScript 代码能够更改数据),因此依赖方可以高度相信用户已同意显示的交易数据。

因此,SPC 在 Web 身份验证的基础上,使网站能够执行简化的强大身份验证并提供用户同意的证据。 SPC 通常用作特定支付系统身份验证框架的一部分。 例如,EMV® 3-D Secure(2.3.1 版)和 EMV® Secure Remote Commerce(1.3 版)都支持 SPC,但旨在与各种支付类型一起使用,包括“推送支付”,例如直接信用卡转账和钱包支付。

支付请求方法

安全支付确认利用了支付请求 API 的底层功能。 安全支付确认支付处理程序的标准化支付方法标识符为"secure-payment-confirmation"

Web 身份验证扩展

安全支付确认定义了一个Web 身份验证扩展payment,在传统 Web 身份验证的基础上增加了三种特定于支付的功能

  1. 当依赖方选择加入时,允许除依赖方之外的实体使用依赖方的凭据发起支付身份验证仪式。 SPC 将身份验证仪式与身份验证结果的验证分离。 这允许商家(或其支付服务提供商在跨域 iframe 中)保持对身份验证用户体验的控制,而无需将用户(通过重定向)转发到另一个网站或移动应用程序。 例如,如果依赖方是银行,则这使商家能够管理身份验证的用户体验,而银行仍然可以验证身份验证的结果。 实体之间的通信(凭据和身份验证结果)通常通过特定于支付系统的轨道进行,例如 EMV® 3-D Secure。
  2. 强制用户代理适当地向用户传达他们正在验证交易以及交易详细信息。 然后,这些详细信息将包含在身份验证器签名的断言中。
  3. 允许在跨域 iframe 中调用 navigator.credentials.create,只要在 iframe 上设置了“payment”权限策略。 注意:此功能现在已成为 WebAuthn Level 3 的一部分,在 Level 3 中,它使用“publickey-credential-create”权限策略。 鼓励开发人员在可用时使用此策略,而不是依赖 SPC 的“payment”权限。

示例

创建凭据

在安全支付确认中创建凭据是通过与 Web 身份验证相同的navigator.credentials.create() 调用来完成的,但指定了payment 扩展。

js
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: "[email protected]",
    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 权限策略。

例如

html
<!-- 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>

身份验证支付

源可以调用 Payment Request API,使用"secure-payment-confirmation" 支付方法提示用户验证由任何其他源创建的安全支付确认凭据。 浏览器将显示一个本机用户界面(“交易对话框”),其中包含交易详细信息(例如,支付货币和金额以及收款方源)。

注意:根据支付请求 API,如果PaymentRequest 在跨域 iframe 中使用(例如,如果merchant.com 嵌入了来自psp.com 的 iframe,并且psp.com 希望使用PaymentRequest),则该 iframe 必须设置了payment 权限策略。

js
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
}

规范

规范
支付请求 API
支付方法标识符
Web 身份验证:访问公钥凭据的 API - Level 3

另请参阅