基于 Web 的支付处理器 API

W3C 工作草案

关于本文件的更多信息
本版本:
https://www.w3.org/TR/2026/WD-web-based-payment-handler-20260423/
最新发布版本:
https://www.w3.org/TR/web-based-payment-handler/
最新编辑草案:
https://w3c.github.io/web-based-payment-handler/
历史:
https://www.w3.org/standards/history/web-based-payment-handler/
提交历史
测试套件:
https://wpt.live/payment-handler/
编辑者:
Ian Jacobs (W3C)
Jinho Bang (受邀专家)
Stephen McGruer (Google)
前任编辑者:
Andre Lyver (Shopify)
Tommy Thorsen (Opera)
Adam Roach (Mozilla)
Rouslan Solomakhin (Google)
Adrian Hope-Bailie (Coil)
反馈:
GitHub w3c/web-based-payment-handler (拉取请求, 新议题, 开放议题)

摘要

本规范定义了使 Web 应用能够 处理支付请求的相关能力。

本文档状态

本节描述了本 文档在发布时的状态。当前 W3C 发布物及本技术报告最新修订版可在 W3C 标准与草案索引 中找到。

Web 支付工作组维护着 尚未处理的所有 问题报告清单。本草案指出了一些待讨论的问题项。 这些问题的结果尚未做出决定,包括它们是否有效。对于未解决的 问题,欢迎提交包含规范建议文本的拉取请求。

本文档由Web 支付工作组 作为工作草案,并按照 推荐轨道 发布。

作为 工作草案发布并不意味着 W3C及其成员的认可。

本文为草案文件,可能会被随时更新、替换或废止。 除作为进行中的工作外,不应引用本文件。

本文档由 W3C 专利政策 下运行的小组制作。 W3C 维护着 任何与小组 交付成果相关的公开专利披露列表 ;该页面还包含 披露专利的说明。如个人确实 知晓某专利且认为该专利包含 必要权利要求, 必须根据 《W3C专利政策》第6节 披露相关信息。

本文档适用 2025年8月18日 W3C 流程文档管理。

1. 引言

本节为非规范性内容。

本规范定义了若干新特性,以允许 Web 应用代表用户处理支付请求:

本规范未涉及使用操作系统特定机制构建的软件 (即“原生应用”)如何处理 支付请求。

2. 概述

在本文档中,我们设想如下流程:

  1. 某个源向用户请求权限,以处理一组受支持支付方式的 支付请求。例如,访问零售商或银行网站的用户 可能会被提示注册来自该源的一个基于 Web 的 支付处理器。该源确定该权限的范围, 但该源的能力可以在无需 额外用户同意的情况下演进。
  2. 基于 Web 的支付处理器定义在 service worker 代码中。
  3. 当商家(或其他收款方)调用 [payment-request] 方法 canMakePayment()show() (例如,当用户——即付款方——在 结账页面按下按钮时),用户代理会计算候选的基于 Web 的 支付处理器列表,将商家接受的支付方式 与用户代理通过任意数量机制已知的支付方式进行比较, 其中包括但不限于:
    • 那些此前通过此 API 注册的支付处理器。
    • 那些可能在交易过程中通过此 API 注册的支付处理器, 例如通过支付方式 清单识别的处理器。
    • 那些通过其他机制注册的处理器,例如操作 系统。
  4. 用户代理向用户显示一组选项:候选的 支付处理器。用户代理使用注册时提供的 信息(标签和图标)或从 Web 应用中 以其他方式获得的信息来显示这些选项。
  5. 付款方用户选择某个基于 Web 的支付处理器时,用户 代理会在所选基于 Web 的 支付处理器的service worker中触发一个 PaymentRequestEvent(参见 用户 交互 任务源)。该 PaymentRequestEvent 包含一些来自 PaymentRequest(定义于 [payment-request])的信息,以及 附加信息(例如,收款方的源)。
  6. 一旦被激活,基于 Web 的支付处理器将执行任何 必要步骤以处理该 支付请求,并向 收款方返回适当的支付响应。如果 需要与用户交互,基于 Web 的 支付处理器可以为此打开一个窗口。
  7. 一旦基于 Web 的支付 处理器完成请求处理,用户代理会异步接收响应。该响应将成为 PaymentResponse(属于 [payment-request])。

一个源可能会使用多个 service worker 实现一个支付应用, 因此每个源可能注册多个基于 Web 的支付处理器。被调用的处理器 由用户所作的选择决定。

2.1 处理支付请求

本节为非规范性内容。

基于 Web 的支付处理器是一种基于 Web 应用的 支付 处理器;也就是说,这是一种能够代表用户处理 支付请求的 Web 应用。

基于 Web 的支付处理器的逻辑由其所支持的支付 方式驱动。某些支付方式几乎不需要 基于 Web 的支付处理器进行处理,它只需在响应中简单返回 支付卡详细信息。随后由收款方 网站使用返回的数据作为输入来处理支付。

相比之下,某些支付方式,例如加密货币支付 或由银行发起的贷记转账,要求基于 Web 的 支付处理器发起支付处理。在这种情况下,该 基于 Web 的支付处理器将返回一个支付参考、端点 URL 或其他某种数据,收款方网站可用其来确定 支付结果(而不是自行处理支付)。

处理支付请求可能包括大量交互:与 用户通过新窗口或其他 API(例如 Web Cryptography API)进行交互,或通过 Web 请求或其他方式与其他服务和源进行交互。

本规范不涉及发生在 基于 Web 的支付处理器接受 PaymentRequestEvent 与 基于 Web 的支付处理器返回 响应之间的这些活动。所有这些为配置 基于 Web 的支付处理器并处理支付请求而可能需要的活动, 都留给基于 Web 的支付处理器的实现来决定, 其中包括:

因此,一个源将依赖许多其他地方定义的 Web 技术 来完成生命周期管理、安全性、用户身份验证、 用户交互等工作。

2.2 与其他类型支付应用的关系

本节为非规范性内容。

本规范不涉及第三方移动支付 应用如何(通过专有机制)与用户代理交互,或 用户代理自身如何提供简单的支付应用功能。

不同类型的支付应用。Web-based Payment Handler API 面向 Web 应用。
1 Web-based Payment Handler API 使 Web 应用能够处理支付。其他 类型的支付应用可能使用其他(专有)机制。

3. 注册

可通过即时(JIT)注册机制,将基于 Web 的支付处理器 向用户代理注册。

3.1 即时注册

如果在商家调用 show() 方法时,某个基于 Web 的支付处理器尚未注册, 用户代理可以允许 用户在交易过程中注册这个基于 Web 的支付处理器 (“即时”)。

本节其余内容为非规范性内容。

用户代理可以通过推导 基于 Web 的支付处理器信息来执行即时安装,这些信息来自通过 支付方式 清单找到的内容,而该清单是通过商家请求的 基于 URL 的 支付方式 标识符发现的。

4. 管理

本节描述了基于 Web 的 支付处理器可用于管理其自身属性的功能。

4.1 ServiceWorkerRegistration 接口的扩展

WebIDLpartial interface ServiceWorkerRegistration {
  [SameObject] readonly attribute PaymentManager paymentManager;
};

paymentManager 属性公开了基于 Web 的支付 处理器管理功能。

4.2 PaymentManager 接口

WebIDL[SecureContext, Exposed=(Window)]
interface PaymentManager {
  attribute DOMString userHint;
  Promise<undefined> enableDelegations(sequence<PaymentDelegation> delegations);
};

PaymentManager基于 Web 的支付处理器用来 管理其支持的委托项。

4.2.1 userHint 属性

在显示基于 Web 的支付处理器名称和图标时,用户 代理可以使用该字符串来改善用户体验。例如, 类似“**** 1234”这样的用户提示可以提醒用户, 某张特定卡可通过该基于 Web 的支付处理器使用。

4.2.2 enableDelegations() 方法

该方法允许基于 Web 的支付处理器 以异步方式声明其支持的 PaymentDelegation 列表。

4.3 PaymentDelegation 枚举

WebIDLenum PaymentDelegation {
  "shippingAddress",
  "payerName",
  "payerPhone",
  "payerEmail"
};
"shippingAddress"
基于 Web 的支付处理器将在需要时提供收货地址。
"payerName"
基于 Web 的支付处理器将在需要时提供付款方姓名。
"payerPhone"
基于 Web 的支付处理器将在需要时提供付款方电话。
"payerEmail"
基于 Web 的支付处理器将在需要时提供付款方电子邮件。

5. 是否可以支付

如果基于 Web 的支付处理器支持 CanMakePaymentEvent,则用户 代理可以用它来帮助 过滤可用的基于 Web 的支付处理器。

实现可以对开发者响应 CanMakePaymentEvent 施加超时限制。如果超时到期, 则该 实现的行为将如同调用了 respondWith() 且参数为 false

5.1 ServiceWorkerGlobalScope 的扩展

WebIDLpartial interface ServiceWorkerGlobalScope {
  attribute EventHandler oncanmakepayment;
};

5.1.1 oncanmakepayment 属性

oncanmakepayment 属性是一个 事件处理器, 其对应的事件 处理器事件 类型为 "canmakepayment"。

5.2 CanMakePaymentEvent

CanMakePaymentEvent 用作一个信号, 用于表明 基于 Web 的支付处理器是否能够响应支付请求。

WebIDL[Exposed=ServiceWorker]
interface CanMakePaymentEvent : ExtendableEvent {
  constructor(DOMString type);
  undefined respondWith(Promise<boolean> canMakePaymentResponse);
};

5.2.1 respondWith() 方法

该方法被基于 Web 的支付处理器用作一个信号, 以表明其是否能够响应支付请求。

5.3 处理 CanMakePaymentEvent

在收到一个 PaymentRequest 后,用户 代理 必须 运行以下步骤:

  1. 如果用户代理设置禁止使用 CanMakePaymentEvent(例如,在私密 浏览模式下), 则终止这些步骤。
  2. registration 为一个 ServiceWorkerRegistration
  3. 如果未找到 registration,则终止这些步骤。
  4. 使用 CanMakePaymentEventregistration 上触发 触发功能事件 "canmakepayment"。

5.4 处理 CanMakePaymentEvent 的示例

本节为非规范性内容。

本示例展示了如何编写一个监听 CanMakePaymentEvent 的 service worker。当收到一个 CanMakePaymentEvent 时, 该 service worker 始终返回 true。

示例 1:处理 CanMakePaymentEvent
self.addEventListener("canmakepayment", function(e) {
  e.respondWith(new Promise(function(resolve, reject) {
    resolve(true);
  }));
});

5.5 支付处理器的过滤

给定一个 PaymentMethodData 以及 一个在支付 方式标识符上匹配的基于 Web 的支付处理器,如果该基于 Web 的支付处理器可用于 支付,则此算法返回 true

  1. methodName支付方式标识符 字符串,该字符串在 PaymentMethodData 中指定。
  2. methodDataPaymentMethodData 的支付方式特定数据。
  3. paymentHandlerOrigin 为该 基于 Web 的支付处理器的 ServiceWorkerRegistration 作用域 URL 的
  4. paymentMethodManifestmethodName摄取解析后的 支付方式 清单
  5. 如果 methodName 是一个基于 URL 的 支付方式 标识符,且在 paymentMethodManifest 中其 受支持的 源包含字符串 "*",则返回 true
  6. 否则,如果基于 URL 的 支付方式标识符 methodNamepaymentHandlerOrigin 具有相同的,则在该 基于 Web 的支付处理器中触发 CanMakePaymentEvent, 并返回结果。
  7. 否则,如果 paymentMethodManifest 中的 受支持的 源是一个包含 paymentHandlerOrigin 的有序 集合,则在该 基于 Web 的支付处理器中触发 CanMakePaymentEvent 并返回 结果。
  8. 否则,返回 false

6. 调用

一旦用户选择了某个基于 Web 的支付处理器,用户代理 就会触发一个 PaymentRequestEvent,并使用 随后的 PaymentHandlerResponse 来创建一个供 [payment-request] 使用的 PaymentResponse

Issue 117: 支持将 Abort() 委托给支付 处理器

Payment Request API 支持将管理 中止操作的责任委托给支付应用。当前有一项提案,计划向 Web-based Payment Handler 接口添加一个 paymentRequestAborted 事件。 该事件将带有一个 respondWith 方法,其接受一个布尔参数, 用于指示 paymentRequest 是否已被成功中止。

6.1 ServiceWorkerGlobalScope 的扩展

本规范扩展了 ServiceWorkerGlobalScope 接口。

WebIDLpartial interface ServiceWorkerGlobalScope {
  attribute EventHandler onpaymentrequest;
};

6.1.1 onpaymentrequest 属性

onpaymentrequest 属性是一个 事件处理器, 其对应的 事件 处理器事件类型PaymentRequestEvent

6.2 PaymentRequestDetailsUpdate

PaymentRequestDetailsUpdate 包含更新后的 总额(可选地包含修饰项和配送选项)以及由于用户在 基于 Web 的支付处理器中选择某种支付方式、配送 地址或配送选项而产生的可能错误。

WebIDLdictionary PaymentRequestDetailsUpdate {
  DOMString error;
  PaymentCurrencyAmount total;
  sequence<PaymentDetailsModifier> modifiers;
  sequence<PaymentShippingOption> shippingOptions;
  object paymentMethodErrors;
  AddressErrors shippingAddressErrors;
};

6.2.1 error 成员

一段人类可读的字符串,用于解释为什么用户所选的 基于 Web 的支付方式、配送地址或配送选项不能 被使用。

6.2.2 total 成员

根据变化后的支付方式、配送 地址或配送选项更新后的总额。例如,总额可能会变化, 因为用户所选支付方式的账单地址 改变了增值税(VAT);或者因为用户选择/提供的配送 选项/地址改变了配送 成本。

6.2.3 modifiers 成员

根据变化后的支付方式、配送 地址或配送选项更新后的修饰项。例如,如果总体总额 因账单地址或配送地址而增加了 €1.00,那么 每个修饰项中指定的总额也应相应增加 €1.00。

6.2.4 shippingOptions 成员

根据变化后的配送地址更新后的 shippingOptions。例 如,对于用户提供的国家/地区,加急配送可能更贵, 或者不可用。

6.2.5 paymentMethodErrors 成员

支付方式的校验错误(如果有)。

6.2.6 shippingAddressErrors 成员

配送地址的校验错误(如果有)。

6.3 PaymentRequestEvent

PaymentRequestEvent 表示在用户选择之后, Payment Handler 可用的数据和方法。用户代理 会将 PaymentRequest 中可用数据的一个子集传递给 Payment Handler。

WebIDL[Exposed=ServiceWorker]
interface PaymentRequestEvent : ExtendableEvent {
  constructor(DOMString type, optional PaymentRequestEventInit eventInitDict = {});
  readonly attribute USVString topOrigin;
  readonly attribute USVString paymentRequestOrigin;
  readonly attribute DOMString paymentRequestId;
  readonly attribute FrozenArray<PaymentMethodData> methodData;
  readonly attribute object total;
  readonly attribute FrozenArray<PaymentDetailsModifier> modifiers;
  readonly attribute object? paymentOptions;
  readonly attribute FrozenArray<PaymentShippingOption>? shippingOptions;
  Promise<WindowClient?> openWindow(USVString url);
  Promise<PaymentRequestDetailsUpdate?> changePaymentMethod(DOMString methodName, optional object? methodDetails = null);
  Promise<PaymentRequestDetailsUpdate?> changeShippingAddress(optional AddressInit shippingAddress = {});
  Promise<PaymentRequestDetailsUpdate?> changeShippingOption(DOMString shippingOption);
  undefined respondWith(Promise<PaymentHandlerResponse> handlerResponsePromise);
};

6.3.1 topOrigin 属性

返回一个字符串,用来指示顶级 收款方网页的 。该属性由 处理 PaymentRequestEvent 进行初始化。

6.3.2 paymentRequestOrigin 属性

返回一个字符串,用来指示 PaymentRequest 被初始化时所在的 。当一个 PaymentRequesttopOrigin 中被初始化时,这些属性具有 相同的 值;否则,这些属性具有不同的值。例如, 当一个 PaymentRequest 在一个 来自不同于 topOrigin 的源的 iframe 中 被初始化时,此属性的值 就是该 iframe 的源。该属性由 处理 PaymentRequestEvent 初始化。

6.3.3 paymentRequestId 属性

获取时,paymentRequestId 属性返回与此 PaymentRequestEvent 对应的 PaymentRequest[[details]].id

6.3.4 methodData 属性

该属性包含 PaymentMethodData 字典, 其中包含网站接受的支付方式标识符 以及任何相关的支付 方式特定数据。它使用下文定义的 MethodData 填充 算法PaymentRequest 中填充。

6.3.5 total 属性

该属性表示请求支付的总金额。 它的类型是 [payment-request] 中定义的 PaymentCurrencyAmount 字典,并使用 相应 PaymentRequest 对象在实例化时 提供的 PaymentDetailsInittotal 字段的一个副本进行初始化。

6.3.6 modifiers 属性

这一组 PaymentDetailsModifier 字典 包含针对特定支付方式标识符的修饰项(例如, 如果支付金额或货币类型根据 每种支付方式而有所不同)。它使用下文定义的 Modifiers 填充 算法PaymentRequest 中填充。

6.3.7 paymentOptions 属性

PaymentOptionsPaymentRequest 中的值。仅当请求配送地址和/或 付款人联系信息中的任意子集时可用。

6.3.8 shippingOptions 属性

相应 PaymentRequestPaymentDetailsInit 字典中 ShippingOptions 的值。(PaymentDetailsInitPaymentDetailsBase 继承 ShippingOptions)。仅在请求配送地址时 可用。

6.3.9 openWindow() 方法

该方法由基于 Web 的支付处理器用来向 用户显示一个窗口。调用时,它会运行 打开窗口 算法

6.3.10 changePaymentMethod() 方法

该方法由基于 Web 的支付处理器用来根据 账单地址等支付方式详细信息获取更新后的总额。调用时, 它会运行 更改支付方式 算法

6.3.11 changeShippingAddress() 方法

该方法由基于 Web 的支付处理器用来根据 shippingAddress 获取更新后的支付详情。调用时, 它会运行 更改支付详情算法

6.3.12 changeShippingOption() 方法

该方法由基于 Web 的支付处理器用来根据 shippingOption 标识符获取更新后的支付详情。调用时, 它会运行 更改支付详情算法

6.3.13 respondWith() 方法

该方法由基于 Web 的支付处理器在支付成功 完成时用来提供一个 PaymentHandlerResponse。调用时, 它会以 eventhandlerResponsePromise 作为 参数运行 响应 PaymentRequest 算法

Issue 123: 与 支付应用共享用户数据?

支付应用是否应在用户明确同意的前提下接收 存储于用户代理中的用户数据?支付应用可以在 安装时或首次被调用时请求 权限。

6.3.14 PaymentRequestEventInit 字典

WebIDLdictionary PaymentRequestEventInit : ExtendableEventInit {
  USVString topOrigin;
  USVString paymentRequestOrigin;
  DOMString paymentRequestId;
  sequence<PaymentMethodData> methodData;
  PaymentCurrencyAmount total;
  sequence<PaymentDetailsModifier> modifiers;
  PaymentOptions paymentOptions;
  sequence<PaymentShippingOption> shippingOptions;
};

topOriginpaymentRequestOriginpaymentRequestIdmethodDatatotalmodifierspaymentOptions 以及 shippingOptions 成员与 为 PaymentRequestEvent 定义的对应成员共享其定义

6.3.15 MethodData 填充算法

为初始化 methodData 的值,用户代理 必须 执行以下步骤或其等效步骤:

  1. registeredMethods 为已调用的基于 Web 的支付 处理器所注册的 支付方式 标识符集合。
  2. 创建一个新的空 Sequence
  3. dataList 设为新创建的 Sequence
  4. 对于对应支付请求中 PaymentRequest@[[methodData]] 内的每一项,执行以下步骤:
    1. inData 设为当前考虑的项。
    2. commonMethods 设为 inData.supportedMethodsregisteredMethods 的集合交集。
    3. 如果 commonMethods 为空,则跳过其余 子步骤并继续处理下一项(若有)。
    4. 创建一个新的 PaymentMethodData 对象。
    5. outData 设为新创建的 PaymentMethodData
    6. outData.supportedMethods 设为一个 包含 commonMethods 成员的列表。
    7. outData.data 设为 inData.data 的一个副本。
    8. outData 追加到 dataList
  5. methodData 设为 dataList

6.3.16 Modifiers 填充算法

为初始化 modifiers 的值,用户代理 必须 执行以下步骤或其等效步骤:

  1. registeredMethods 为已调用的基于 Web 的支付 处理器所注册的 支付方式 标识符集合。
  2. 创建一个新的空 Sequence
  3. modifierList 设为新创建的 Sequence
  4. 对于对应支付请求中 PaymentRequest@[[paymentDetails]].modifiers 内的每一项,执行以下步骤:
    1. inModifier 设为当前考虑的项。
    2. commonMethods 设为 inModifier.supportedMethodsregisteredMethods 的集合交集。
    3. 如果 commonMethods 为空,则跳过其余 子步骤并继续处理下一项(若有)。
    4. 创建一个新的 PaymentDetailsModifier 对象。
    5. outModifier 设为新创建的 PaymentDetailsModifier
    6. outModifier.supportedMethods 设为一个 包含 commonMethods 成员的 列表。
    7. outModifier.total 设为 inModifier.total 的一个副本。
    8. outModifier 追加到 modifierList
  5. modifiers 设为 modifierList

6.4 内部槽

PaymentRequestEvent 的实例 会使用下表中的内部 槽创建:

内部槽 默认值 描述(非规范性
[[windowClient]] null 当前活动的 WindowClient。如果某个 基于 Web 的支付处理器当前正在向 用户显示一个窗口,则设置此值。否则,它为 null。
[[respondWithCalled]] false YAHO

6.5 处理 PaymentRequestEvent

当通过 PaymentRequest.show() 接收到一个 PaymentRequest,并且用户随后选择了某个基于 Web 的支付处理器时,用户 代理 必须 运行以下步骤:

  1. registration 为与用户选择的基于 Web 的支付处理器对应的 ServiceWorkerRegistration
  2. 如果未找到 registration,则用一个 "InvalidStateError" DOMException 拒绝由 PaymentRequest.show() 创建的 Promise,并 终止这些步骤。
  3. registration 上,使用 PaymentRequestEvent 触发 触发功能事件 "paymentrequest",并带有以下属性:

    topOrigin
    顶层收款方网页的 源的序列化表示
    paymentRequestOrigin
    PaymentRequest 被初始化所在上下文的 源的序列化表示
    methodData
    执行 MethodData 填充 算法 的结果。
    modifiers
    执行 Modifiers 填充 算法 的结果。
    total
    对应 PaymentRequestPaymentDetailsInit 上 total 字段的一个副本。
    paymentRequestId
    来自 PaymentRequest 的 \[\[details\]\].id
    paymentOptions
    传递给对应 PaymentRequest 构造函数的 paymentOptions 字典的一个副本。
    shippingOptions
    对应 PaymentRequestPaymentDetailsInit 上 shippingOptions 字段的一个副本。

    然后,以 dispatchedEvent 并行运行以下步骤:

    1. 等待 dispatchedEvent 的所有 延长 生命周期 promise 解析完成。
    2. 如果基于 Web 的支付处理器尚未提供 PaymentHandlerResponse, 则使用一个 "OperationError" DOMException 拒绝由 PaymentRequest.show() 创建的 Promise

7. 窗口

被调用的基于 Web 的支付处理器可能需要,也可能不需要显示 关于其自身的信息或请求用户输入。基于 Web 的 支付处理器显示的一些潜在示例包括:

需要可视化显示和用户 交互的基于 Web 的支付处理器,可以调用 openWindow() 向用户 显示一个页面。

由于用户代理知道此方法与 PaymentRequestEvent 相关联, 它们应当以与流程一致且不会让用户困惑的方式 渲染该窗口。生成的 窗口客户端会绑定到发起 PaymentRequest 的标签页/窗口。单个基于 Web 的支付处理器 不应被允许使用此方法打开多个客户端窗口。

7.1 打开 窗口算法

Issue 115: 打开窗口 算法

该算法类似于 Service Workers 规范中的 打开窗口算法

Issue 115: 打开窗口 算法

我们是否应该改为引用 Service Workers 规范, 而不是复制它们的步骤?

  1. event 为此 PaymentRequestEvent
  2. 如果 eventisTrusted 属性为 false,则返回一个 被拒绝并带有 "InvalidStateError" DOMExceptionPromise
  3. request 为触发此 PaymentRequestEventPaymentRequest
  4. url 为对 url 参数执行解析的结果。
  5. 如果 url 解析抛出异常,则返回一个 被该异常拒绝的 Promise
  6. 如果 urlabout:blank,则返回一个 被 TypeError 拒绝的 Promise
  7. 如果 url 的源与和该基于 Web 的支付处理器相关联的 service worker 的源不同, 则返回一个以 null 解决的 Promise
  8. promise 为一个新的 Promise
  9. 返回 promise,并并行执行其余步骤:
  10. 如果 event.[[windowClient]] 不为 null,则:
    1. 如果 event.[[windowClient]].visibilityState 不为 "unloaded",则用一个 "InvalidStateError" DOMException 拒绝 promise, 并中止这些步骤。
  11. newContext 为一个新的 顶级 浏览 上下文
  12. newContext 导航url,并启用 异常和替换。
  13. 如果导航抛出异常,则用该异常拒绝 promise, 并中止这些步骤。
  14. 如果 newContext 的源与和该基于 Web 的支付处理器相关联的 service worker 客户端源不同,则:
    1. 以 null 解决 promise
    2. 中止这些步骤。
  15. client 为使用 newContext 作为 参数运行 create window client 算法的结果。
  16. event.[[windowClient]] 设为 client
  17. client 解决 promise

7.2 处理 PaymentRequestEvent 的示例

本节为非规范性内容。

本示例展示了如何编写一个监听 PaymentRequestEvent 的 service worker。 当接收到一个 PaymentRequestEvent 时, service worker 会打开一个窗口与用户交互。

示例 2: 处理 PaymentRequestEvent
async function getPaymentResponseFromWindow() {
  return new Promise((resolve, reject) => {
    self.addEventListener("message", listener = e => {
      self.removeEventListener("message", listener);
      if (!e.data || !e.data.methodName) {
        reject();
        return;
      }
      resolve(e.data);
    });
  });
}

self.addEventListener("paymentrequest", e => {
  e.respondWith((async() => {
    // Open a new window for providing payment UI to user.
    const windowClient = await e.openWindow("payment_ui.html");

    // Send data to the opened window.
    windowClient.postMessage({
      total: e.total,
      modifiers: e.modifiers
    });

    // Wait for a payment response from the opened window.
    return await getPaymentResponseFromWindow();
  })());
});

使用上文描述的简单方案,一个加载到 基于 Web 的支付处理器窗口中的简单 HTML 页面可能如下所示:

示例 3: 简单的支付处理器窗口
<form id="form">
<table>
  <tr><th>Cardholder Name:</th><td><input name="cardholderName"></td></tr>
  <tr><th>Card Number:</th><td><input name="cardNumber"></td></tr>
  <tr><th>Expiration Month:</th><td><input name="expiryMonth"></td></tr>
  <tr><th>Expiration Year:</th><td><input name="expiryYear"></td></tr>
  <tr><th>Security Code:</th><td><input name="cardSecurityCode"></td></tr>
  <tr><th></th><td><input type="submit" value="Pay"></td></tr>
</table>
</form>

<script>
navigator.serviceWorker.addEventListener("message", e => {
  /* Note: message sent from payment app is available in e.data */
});

document.getElementById("form").addEventListener("submit", e => {
  const details = {};
  ["cardholderName", "cardNumber", "expiryMonth", "expiryYear", "cardSecurityCode"]
  .forEach(field => {
    details[field] = form.elements[field].value;
  });

  const paymentAppResponse = {
    methodName: "https://example.com/pay",
    details
  };

  navigator.serviceWorker.controller.postMessage(paymentAppResponse);
  window.close();
});
</script>

8. 响应

8.1 PaymentHandlerResponse 字典

用户代理通过对提供给相应 PaymentRequestEvent 接口的 respondWith 函数的 Promise 进行解析,来接收来自基于 Web 的 支付处理器的成功响应。应用程序应当使用一个包含支付响应的 PaymentHandlerResponse 实例来解析该 Promise。若用户取消或发生错误, 应用程序可以通过拒绝该 Promise 来表示失败。

PaymentHandlerResponse 通过以下字典进行传递:

WebIDLdictionary PaymentHandlerResponse {
DOMString methodName;
object details;
DOMString? payerName;
DOMString? payerEmail;
DOMString? payerPhone;
AddressInit shippingAddress;
DOMString? shippingOption;
};

8.1.1 methodName 属性

用户为完成该交易而选择的 支付方式 标识符,对应于该 支付方式

8.1.2 details 属性

一个可 JSON 序列化 的对象, 它提供一条特定于 支付 方式 的消息,供商家用来处理该 交易并确定资金是否成功转移。

8.1.3 payerName 属性

用户提供的付款人姓名。

8.1.4 payerEmail 属性

用户提供的付款人电子邮件。

8.1.5 payerPhone 属性

用户提供的付款人电话号码。

8.1.6 shippingAddress 属性

用户提供的配送地址。

8.1.7 shippingOption 属性

用户所选配送选项的标识符。

8.2 更改支付方式算法

当以 methodNamemethodDetails 参数调用此算法时,用户代理 必须 运行 以下步骤:

  1. 使用根据给定 methodNamemethodDetails 参数构造的 PaymentMethodChangeEvent event, 运行 支付方式 更改算法
  2. 如果没有运行 event.updateWith(detailsPromise), 则返回 null
  3. 如果 event.updateWith(detailsPromise) 抛出异常,则重新抛出该 错误。
  4. 如果 event.updateWith(detailsPromise) 超时 (可选),则抛出 "InvalidStateError" DOMException
  5. 根据 event.updateWith(detailsPromise) 中的 detailsPromise 构造并返回一个 PaymentRequestDetailsUpdate

8.3 更改支付详情算法

当以 shippingAddressshippingOption 调用此算法时,用户代理 必须 运行以下 步骤:

  1. 使用根据 更新后的详情(shippingAddressshippingOption)构造的 PaymentRequestUpdateEvent event, 运行 PaymentRequest 更新算法
  2. 如果没有运行 event.updateWith(detailsPromise), 则返回 null
  3. 如果 event.updateWith(detailsPromise) 抛出异常,则重新抛出该 错误。
  4. 如果 event.updateWith(detailsPromise) 超时 (可选),则抛出 "InvalidStateError" DOMException
  5. 根据 event.updateWith(detailsPromise) 中的 detailsPromise 构造并返回一个 PaymentRequestDetailsUpdate

8.4 响应 PaymentRequest 算法

当以 eventhandlerResponsePromise 参数调用此算法时,用户代理 必须 运行 以下步骤:

  1. 如果 eventisTrusted 为 false, 则抛出一个 "InvalidStateError" DOMException 并中止 这些步骤。
  2. 如果 eventdispatch flag 未设置,则抛出一个 "InvalidStateError" DOMException 并中止 这些步骤。
  3. 如果 event.[[respondWithCalled]] 为 true,则抛出一个 "InvalidStateError" DOMException 并中止 这些步骤。
  4. event.[[respondWithCalled]] 设为 true。
  5. 设置 event停止传播标志event立即停止传播 标志
  6. handlerResponsePromise 添加到 event延长 生命周期 promises
  7. event待处理 promises 计数 加一。
  8. handlerResponsePromisereason被拒绝时
    1. reason 运行 支付应用 失败算法,并 终止这些步骤。
  9. handlerResponsePromise 兑现时
    1. handlerResponsevalue 转换为 IDL 值 后的 PaymentHandlerResponse。 如果此过程抛出异常,则用一个 "OperationError" DOMException 运行 支付应用 失败算法, 并终止这些步骤。
    2. 验证 handlerResponse 中所有必需成员都存在 且格式良好。
      1. 如果 handlerResponse.methodName 不存在, 或未设置为来自 event.methodData 的值之一, 则用一个 "OperationError" DOMException 运行 支付应用失败算法, 并终止这些 步骤。
      2. 如果 handlerResponse.details 不存在 或不可 JSON 序列化, 则用一个 "OperationError" DOMException 运行 支付应用 失败算法, 并终止这些步骤。
      3. shippingRequired 为关联 PaymentRequest 的 paymentOptions 中的 requestShipping 值。 如果 shippingRequired 为真且 handlerResponse.shippingAddress 不存在,则用一个 "OperationError" DOMException 运行 支付应用失败 算法, 并终止 这些步骤。
      4. 如果 shippingRequired 为真且 handlerResponse.shippingOption 不存在, 或未设置为来自 event.shippingOptions 的配送选项标识符之一, 则用一个 "OperationError" DOMException 运行 支付应用 失败算法, 并终止这些 步骤。
      5. payerNameRequired 为关联 PaymentRequest 的 paymentOptions 中的 requestPayerName 值。 如果 payerNameRequired 为真且 handlerResponse.payerName 不存在, 则用一个 "OperationError" DOMException 运行 支付应用 失败算法, 并终止这些 步骤。
      6. payerEmailRequired 为关联 PaymentRequest 的 paymentOptions 中的 requestPayerEmail 值。 如果 payerEmailRequired 为真且 handlerResponse.payerEmail 不存在, 则用一个 "OperationError" DOMException 运行 支付应用 失败算法, 并终止这些 步骤。
      7. payerPhoneRequired 为关联 PaymentRequest 的 paymentOptions 中的 requestPayerPhone 值。 如果 payerPhoneRequired 为真且 handlerResponse.payerPhone 不存在, 则用一个 "OperationError" DOMException 运行 支付应用 失败算法, 并终止这些 步骤。
    3. 序列化 handlerResponse 的必需成员( methodNamedetails 始终是必需的; 当 shippingRequired 为 true 时, shippingAddressshippingOption 是必需的; 当 payerNameRequiredpayerEmailRequiredpayerPhoneRequired 分别为 true 时, payerNamepayerEmailpayerPhone 是必需的。):
      1. 对于 handlerResponse 中的每个 member, 令 serializeMember 为使用 handlerResponse.member 执行 StructuredSerialize 的结果。重新抛出任何 异常。
    4. 用户代理 必须 按照 [payment-request] 中的定义运行 用户 接受支付 请求算法, 并用这些步骤或其等效步骤替换其中的第 9-15 步。
      1. 反序列化已序列化的成员:
        1. 对于每个 serializeMember, 令 member 为使用 serializeMember 执行 StructuredDeserialize 的结果。重新抛出任何异常。
      2. 如果上述步骤中发生任何异常,则用一个 "OperationError" DOMException 运行 支付应用 失败算法, 并终止这些 步骤。
      3. methodName 赋值给关联 PaymentRequest 的 response.methodName
      4. details 赋值给关联 PaymentReqeust 的 response.details
      5. 如果 shippingRequired 为真,则将关联 PaymentReqeust 的 shippingAddress 属性设为 shippingAddress。否则,将其设为 null。
      6. 如果 shippingRequired 为真,则将关联 PaymentReqeust 的 shippingOption 属性设为 shippingOption。否则,将其设为 null。
      7. 如果 payerNameRequired 为真,则将关联 PaymentReqeust 的 payerName 属性设为 payerName。否则,将其设为 null。
      8. 如果 payerEmailRequired 为真,则将关联 PaymentReqeust 的 payerEmail 属性设为 payerEmail。否则,将其设为 null。
      9. 如果 payerPhoneRequired 为真,则将关联 PaymentReqeust 的 payerPhone 属性设为 payerPhone。否则,将其设为 null。
  10. handlerResponsePromise 兑现时拒绝时排入一个微任务 以执行 以下步骤:
    1. event待处理 promises 计数 减一。
    2. registrationthis相关 全局对象 所关联的 service worker所属 service worker registration
    3. 如果 registration 不为 null,则用 registration 调用 Try Activate

以下示例展示了如何响应支付请求:

示例 4: 发送支付响应
paymentRequestEvent.respondWith(new Promise(function(accept,reject) {
  /* ... processing may occur here ... */
  accept({
    methodName: "https://example.com/pay",
    details: {
      cardHolderName:   "John Smith",
      cardNumber:       "1232343451234",
      expiryMonth:      "12",
      expiryYear :      "2020",
      cardSecurityCode: "123"
     },
    shippingAddress: {
      addressLine: [
        "1875 Explorer St #1000",
      ],
      city: "Reston",
      country: "US",
      dependentLocality: "",
      organization: "",
      phone: "+15555555555",
      postalCode: "20190",
      recipient: "John Smith",
      region: "VA",
      sortingCode: ""
    },
    shippingOption: "express",
    payerEmail: "john.smith@gmail.com",
  });
}));

[payment-request] 定义了一个 ID,生态系统中的各方 (包括支付应用提供商和收款方)可以在网络 或其他故障发生后使用它进行 对账。

8.5 支付应用失败算法

当以 reason 调用此算法时,用户代理 必须 运行 以下步骤:

  1. 如果 reason 是一个 "OperationError" DOMException,则运行 [payment-request] 中定义的 支付 处理器指示内部错误算法
  2. 否则,运行 [payment-request] 中定义的 用户 中止支付请求算法

    本规范的先前版本并未定义当 支付应用 失败算法 被 调用时会发生什么。实际上,实现者的行为如同 运行了 用户 中止支付请求算法。 为了尽可能保持向后兼容,同时 仍然引入一种让基于 Web 的支付处理器指示 内部错误的方式,本规范现将除 "OperationError" DOMException 之外的所有 reason 值映射为用户中止。未来 版本的本规范可能会增加其他受处理的值。

9. 安全与隐私注意事项

9.1 地址

由于隐私问题,Web Payments Working Group 在 Payment Request API 的原始版本中移除了对配送地址和 账单地址的支持;参见 issue 842。为了给那些仍继续支持此能力的实现提供文档,工作组现正 恢复该特性,并期望解决相关隐私 问题。在这样做的同时,工作组也可能基于其他 API 的演进(例如 Content Picker API)对 Payment Request API 作出修改。

9.2 关于用户环境的信息

9.5 用户对跨源共享数据的知情

9.6 安全通信

9.7 已授权的支付应用

9.8 支持的源

9.9 数据校验

9.10 隐私浏览模式

10. 支付处理器显示注意事项

本节为非规范性内容。

在对基于 Web 的支付处理器进行排序时,期望用户代理 优先遵从用户偏好而非其他偏好。期望用户代理 允许手动配置选项,例如为某个源设置首选的 基于 Web 的支付处理器显示顺序,或者为所有 源设置统一顺序。

用户体验细节留给实现者决定。

11. 依赖项

本规范依赖于若干其他基础规范。

Payment Request API
术语 payment methodPaymentRequestPaymentResponsesupportedMethodsPaymentCurrencyAmountpaymentDetailsModifierpaymentDetailsInitpaymentDetailsBasePaymentMethodDataPaymentOptionsPaymentShippingOptionAddressInitAddressErrorsPaymentMethodChangeEventPaymentRequestUpdateEventIDcanMakePayment()show()updateWith(detailsPromise)user accepts the payment request algorithmpayment method changed algorithmPaymentRequest updated algorithm 以及 JSON-serializable 由 Payment Request API 规范 [payment-request] 定义。
ECMAScript
术语 internal slotJSON.stringify 由 [ECMASCRIPT] 定义。
Payment Method Manifest
术语 payment method manifestingest payment method manifestparsed payment method manifest 以及 supported origins 由 Payment Method Manifest 规范 [payment-method-manifest] 定义。
Service Workers
术语 service workerservice worker registrationservice worker clientServiceWorkerRegistrationServiceWorkerGlobalScopefire functional eventextend lifetime promisespending promises countcontaining service worker registrationTry Clear RegistrationTry ActivateExtendableEventExtendableEventInit、 以及 scope URL 定义于 [SERVICE-WORKERS]。

12. 一致性

除了标记为非规范性的章节外,本规范中的所有编写指南、图表、示例和注释 也都是非规范性的。本规范中的其他所有内容均为规范性内容。

本文档中的关键词 MAYMUSTSHOULD、 以及 SHOULD NOT 应按 BCP 14 [RFC2119] [RFC8174] 中所描述的方式进行解释, 但前提是,并且仅当,它们像这里这样以全大写形式 出现时。

只有一种产品类别可以声称符合本 规范:即 用户代理

用户代理可以以本规范中给出的任意方式实现算法, 只要最终结果与按本规范算法所得到的 结果不可区分。

用户代理可以对原本不受约束的输入施加实现特定限制, 例如为了防止拒绝服务攻击、避免 内存耗尽,或为了规避 平台特定限制。当输入超过 实现特定限制时,用户代理必须抛出,或者在 Promise 的上下文中,以一个 TypeError 拒绝,并可选地 告知 开发者某个特定输入是如何超过 实现特定限制的。

A. IDL 索引

WebIDLpartial interface ServiceWorkerRegistration {
  [SameObject] readonly attribute PaymentManager paymentManager;
};

[SecureContext, Exposed=(Window)]
interface PaymentManager {
  attribute DOMString userHint;
  Promise<undefined> enableDelegations(sequence<PaymentDelegation> delegations);
};

enum PaymentDelegation {
  "shippingAddress",
  "payerName",
  "payerPhone",
  "payerEmail"
};

partial interface ServiceWorkerGlobalScope {
  attribute EventHandler oncanmakepayment;
};

[Exposed=ServiceWorker]
interface CanMakePaymentEvent : ExtendableEvent {
  constructor(DOMString type);
  undefined respondWith(Promise<boolean> canMakePaymentResponse);
};

partial interface ServiceWorkerGlobalScope {
  attribute EventHandler onpaymentrequest;
};

dictionary PaymentRequestDetailsUpdate {
  DOMString error;
  PaymentCurrencyAmount total;
  sequence<PaymentDetailsModifier> modifiers;
  sequence<PaymentShippingOption> shippingOptions;
  object paymentMethodErrors;
  AddressErrors shippingAddressErrors;
};

[Exposed=ServiceWorker]
interface PaymentRequestEvent : ExtendableEvent {
  constructor(DOMString type, optional PaymentRequestEventInit eventInitDict = {});
  readonly attribute USVString topOrigin;
  readonly attribute USVString paymentRequestOrigin;
  readonly attribute DOMString paymentRequestId;
  readonly attribute FrozenArray<PaymentMethodData> methodData;
  readonly attribute object total;
  readonly attribute FrozenArray<PaymentDetailsModifier> modifiers;
  readonly attribute object? paymentOptions;
  readonly attribute FrozenArray<PaymentShippingOption>? shippingOptions;
  Promise<WindowClient?> openWindow(USVString url);
  Promise<PaymentRequestDetailsUpdate?> changePaymentMethod(DOMString methodName, optional object? methodDetails = null);
  Promise<PaymentRequestDetailsUpdate?> changeShippingAddress(optional AddressInit shippingAddress = {});
  Promise<PaymentRequestDetailsUpdate?> changeShippingOption(DOMString shippingOption);
  undefined respondWith(Promise<PaymentHandlerResponse> handlerResponsePromise);
};

dictionary PaymentRequestEventInit : ExtendableEventInit {
  USVString topOrigin;
  USVString paymentRequestOrigin;
  DOMString paymentRequestId;
  sequence<PaymentMethodData> methodData;
  PaymentCurrencyAmount total;
  sequence<PaymentDetailsModifier> modifiers;
  PaymentOptions paymentOptions;
  sequence<PaymentShippingOption> shippingOptions;
};

dictionary PaymentHandlerResponse {
DOMString methodName;
object details;
DOMString? payerName;
DOMString? payerEmail;
DOMString? payerPhone;
AddressInit shippingAddress;
DOMString? shippingOption;
};

B. 参考文献

B.1 规范性引用

[dom]
DOM 标准. Anne van Kesteren. WHATWG. 现行标准。URL: https://dom.spec.whatwg.org/
[ECMASCRIPT]
ECMAScript 语言规范. Ecma International. URL: https://tc39.es/ecma262/multipage/
[HTML]
HTML 标准. Anne van Kesteren; Domenic Denicola; Dominic Farolino; Ian Hickson; Philip Jägenstedt; Simon Pieters. WHATWG. 现行 标准。URL: https://html.spec.whatwg.org/multipage/
[payment-method-id]
支付方式标识符. Marcos Caceres. W3C. 2022年9月8日. W3C 推荐标准. URL: https://www.w3.org/TR/payment-method-id/
[payment-method-manifest]
支付方式清单. Dapeng(Max) Liu; Domenic Denicola; Zach Koch. W3C. 2017年12月12日. FPWD. URL: https://www.w3.org/TR/payment-method-manifest/
[payment-request]
Payment Request API. Marcos Caceres; Ian Jacobs; Stephen McGruer. W3C. 2026年3月27日. CRD. URL: https://www.w3.org/TR/payment-request/
[RFC2119]
在 RFC 中用于表示 需求级别的关键词. S. Bradner. IETF. 1997年3月. 当前最佳实践. URL: https://www.rfc-editor.org/rfc/rfc2119
[RFC8174]
RFC 2119 关键词中大写与小写的歧义. B. Leiba. IETF. 2017年5月. 当前最佳实践. URL: https://www.rfc-editor.org/rfc/rfc8174
[SERVICE-WORKERS]
Service Workers Nightly. Monica CHINTALA; Yoshisato Yanagisawa. W3C. 2026年4月9日. CRD. URL: https://www.w3.org/TR/service-workers/
[URL]
URL 标准. Anne van Kesteren. WHATWG. 现行标准。URL: https://url.spec.whatwg.org/
[WEBIDL]
Web IDL 标准. Edgar Chen; Timothy Gu. WHATWG. 现行标准。URL: https://webidl.spec.whatwg.org/

B.2 参考性引用

[WebCryptoAPI]
Web Cryptography API. Mark Watson. W3C. 2017年1月26日. W3C 推荐标准. URL: https://www.w3.org/TR/WebCryptoAPI/