基于 Web 的支付处理程序 API

W3C 工作草案

关于本文件的更多细节
本版本:
https://www.w3.org/TR/2026/WD-web-based-payment-handler-20260218/
最新发布版本:
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 Payments 工作组维护着一份该工作组尚未处理的所有错误报告列表。本草案强调了一些仍待在工作组内讨论的未决问题。尚未就这些问题的结论作出决定,也未决定它们是否有效。强烈鼓励提交包含针对未决问题的规范文本建议的拉取请求。

本文档由Web Payments 工作组作为工作草案发布,使用了 Recommendation track

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

这是一个草案文档,可能随时被更新、替换或被其他文档废弃。不宜将此文档引用为除正在进行的工作之外的资料。

本文档由在以下政策下运作的小组产生: W3C 专利政策W3C 维护一份与该小组交付物相关的任何专利披露的公开列表;该页面还包含披露专利的说明。任何实际知道并认为包含必要权利要求(Essential Claim(s))的专利的个人,必须按照 W3C 专利政策第6节的规定披露该信息。

本文档受2025年8月18日的 W3C 流程文档的约束。

1. 介绍

本节为非规范性内容。

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

注意

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

2. 概述

本文档设想了如下流程:

  1. 某个源(origin)向用户请求权限,以处理一组支持的支付方式的支付请求。例如,用户访问零售或银行网站时,可能会被提示注册来自该源的基于 Web 的支付处理程序。该源确定权限的作用域,但其能力可以扩展,而无需用户额外授权。
  2. 基于 Web 的支付处理程序Service Worker 代码定义。
  3. 当商家(或其他 收款方)调用 [payment-request] 方法 canMakePayment()show() (例如用户——即 付款方——在结账页面点击按钮时),用户代理会计算候选基于 Web 的支付处理程序列表,将商家接受的支付方式与用户代理已知的支付方式进行比较,这些方式包括但不限于:
    • 之前通过该 API 注册的支付方式。
    • 在交易过程中可能通过该 API 注册的支付方式,例如通过 支付方式清单 确认的方式。
    • 通过其他机制(如操作系统)注册的支付方式。
  4. 用户代理向用户展示一组选项:候选支付处理程序。用户代理通过注册时或 Web 应用所提供的信息(标签与图标)来展示这些选项。
  5. 付款方 用户选择某个基于 Web 的支付处理程序时,用户代理会在该支付处理程序对应的 Service Worker 里触发 PaymentRequestEvent(参考 用户交互任务源)。PaymentRequestEvent 包含 PaymentRequest (定义见 [payment-request])中的部分信息以及其他信息(如收款方 origin)。
  6. 激活后,基于 Web 的支付处理程序执行 处理支付请求 所需的各种步骤,并向 收款方 返回合适的支付响应。如需用户交互,基于 Web 的支付处理程序 可弹窗(window)实现此目的。
  7. 基于 Web 的支付处理程序处理完请求后,用户代理会异步接收响应。该响应将成为 PaymentResponse(见 [payment-request])。

一个源(origin)可以用多个 Service Worker 实现支付应用。因此每个源可以注册多个 基于 Web 的支付处理程序。被调用的处理程序由用户选择决定。

2.1 处理支付请求

本节为非规范性内容。

基于 Web 的支付处理程序 是一种基于 Web 应用的 支付处理程序; 即,能够代表用户处理支付请求的 Web 应用。

基于 Web 的支付处理程序的逻辑由其支持的支付方式驱动。 某些支付方式要求支付处理程序仅进行很少甚至无需处理,仅在响应中直接返回支付卡信息。 此时,收款方网站负责使用返回的数据完成支付处理。

相比之下,某些支付方式(如加密货币支付或银行发起的信用转账)要求基于 Web 的支付处理程序主动发起支付处理。 在这种情形下,支付处理程序将返回一个支付凭证、端点 URL 或其他数据,收款方网站可据此判断支付结果(而不是直接处理支付本身)。

处理支付请求过程可能涉及多种交互:可通过新窗口或其他 API(例如 Web 加密 API)与用户交互,或通过 Web 请求等方式与其他服务、其他源进行交互。

本规范未涉及支付处理程序在接受 PaymentRequestEvent 到返回响应之间发生的这些活动。 配置支付处理程序及处理支付请求所需的所有操作,均由支付处理程序的实现决定,包括:

因此,一个源会依赖于其他 Web 技术(此规范未详细定义)来管理生命周期、安全、用户认证、用户交互等。

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

本节为非规范性内容。

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

Different types of payment apps. Web-based Payment Handler API is for Web apps.
1 基于 Web 的支付处理程序 API 使 Web 应用能够处理支付。 其他类型的支付应用可能使用其它(专有)机制。

3. 注册

通过即时(JIT)注册机制,可以在用户代理中注册基于 Web 的支付处理程序。

3.1 及时注册

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

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

用户代理可以通过从商家请求的 支付方式清单 中,通过 基于 URL 的支付方式标识符 获取,推导出基于 Web 的支付处理程序信息,从而实现即时安装。

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 收到请求后,用户代理必须(MUST) 运行以下步骤:

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

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 的支付处理程序,如果该支付处理程序可用于支付,则此算法返回 true

  1. methodName支付方式标识符 字符串,由 PaymentMethodData 中指定。
  2. methodDataPaymentMethodData 的支付方式专有数据。
  3. paymentHandlerOrigin 为该基于 Web 的支付处理程序的 ServiceWorkerRegistration 作用域 URL 的
  4. paymentMethodManifestmethodName已获取已解析支付方式清单
  5. 如果 methodName 是一个 基于 URL 的支付方式标识符, 且 paymentMethodManifest"*" 字符串已被 support origins 支持,则返回 true
  6. 否则,如果 methodName 这个 基于 URL 的支付方式标识符paymentHandlerOrigin 有相同的 , 则在该基于 Web 的支付处理程序中触发 CanMakePaymentEvent 并返回其结果。
  7. 否则,如果 paymentMethodManifest支持源 是一个有序 源(origin) 集合,并包含 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 表示在用户选择之后,支付处理程序可用的数据和方法。用户代理会将 PaymentRequest 中可用数据的一个子集传递给支付处理程序。

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 属性

返回一个字符串,指示顶层 收款方网页的来源(origin)。 此属性由处理 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 字典,包含网站可接受的支付方法标识符以及任何相关的特定 支付方法数据。它由 PaymentRequest 使用下文定义的 方法数据填充算法进行填充。

6.3.5 total 属性

此属性表示请求支付的总金额。其类型为 PaymentCurrencyAmount 字典(定义见 [payment-request]),并使用在实例化相应 PaymentRequest 对象时所提供的 total 字段的副本进行初始化。

6.3.6 modifiers 属性

PaymentDetailsModifier 字典序列包含针对特定支付方法标识符的修饰符(例如,如果基于每种支付方法,支付金额或货币类型有所不同)。它由 PaymentRequest 使用下文定义的 修饰符填充算法进行填充。

6.3.7 paymentOptions 属性

相应 PaymentRequestPaymentOptions 的取值。 仅当请求收货地址和/或付款人联系信息的任意子集时可用。

6.3.8 shippingOptions 属性

相应 PaymentDetailsInit 字典中的 ShippingOptions 的取值。(PaymentDetailsInit 继承了 PaymentDetailsBase 的 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;
};

topOriginpaymentRequestOriginpaymentRequestIdmethodDatatotalmodifierspaymentOptionsshippingOptions 成员与 PaymentRequestEvent 中的相应定义共享定义。

6.3.15 方法数据填充算法

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

  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 的值,用户代理 必须(MUST)执行以下步骤或等效步骤:

  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, 利用 PaymentRequest.show() 接收到付款请求,并且用户随后选择了某个基于 Web 的支付处理程序时, 用户代理 必须执行以下步骤:

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

    topOrigin
    付款网页顶层页面的 origin 的序列化
    paymentRequestOrigin
    初始化 PaymentRequest 的上下文 origin 的序列化
    methodData
    执行 方法数据填充算法 的结果。
    modifiers
    执行 修饰符填充算法 的结果。
    total
    来自对应 PaymentDetailsInit 的总金额字段的副本。
    paymentRequestId
    \[\[details\]\].id ,取自对应 PaymentRequest
    paymentOptions
    传递给对应 PaymentRequest 构造函数的 paymentOptions 字典的副本。
    shippingOptions
    来自对应 PaymentDetailsInit 的 shippingOptions 字段副本。

    然后在并行中,以 dispatchedEvent 执行以下步骤:

    1. 等待 dispatchedEvent 的所有 扩展生命周期 promise 均已解决。
    2. 如果 基于 Web 的支付处理程序 未提供 PaymentHandlerResponse, 则拒绝由 Promise (由 PaymentRequest.show() 创建) 并返回 "OperationError" DOMException

7. 窗口

被调用的基于 Web 的支付处理程序可能需要,也可能不需要,显示自身相关信息或请求用户输入。基于 Web 的支付处理程序可能显示的情况示例包括:

基于 Web 的支付处理程序需要可视化展示和用户交互,可调用 openWindow() 向用户展示页面。

由于用户代理知晓该方法与 PaymentRequestEvent 是相关联的,应当以合理且不造成用户困惑的方式渲染窗口。最终生成的窗口 client 会绑定到发起 PaymentRequest 的标签页/窗口。 单个基于 Web 的支付处理程序 不应允许通过该方法打开多个 client 窗口。

7.1 打开窗口算法

Issue 115:打开窗口算法

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

Issue 115:打开窗口算法

我们是否应该直接引用 Service Workers 规范而不是把其步骤复制过来?

  1. event 为此 PaymentRequestEvent
  2. 如果 eventisTrusted 属性为 false,则返回以 "InvalidStateError" DOMException 拒绝的 Promise
  3. request 为触发此 PaymentRequestEventPaymentRequest
  4. url解析 url 参数的结果。
  5. 如果 url 解析抛出异常,则返回以该异常拒绝的 Promise
  6. urlabout:blank,则返回以 TypeError 拒绝的 Promise
  7. 如果 url 的 origin 与与该基于 Web 的支付处理程序相关联的 service worker 的 origin 不同,则返回以 null 解决的 Promise
  8. promise 为新的 Promise
  9. 返回 promise,并在并行中执行后续步骤:
  10. event.[[windowClient]] 不为 null,则:
    1. event.[[windowClient]].visibilityState 不为 "unloaded",用 "InvalidStateError" DOMException 拒绝 promise,并终止这些步骤。
  11. newContext 为新的 顶级浏览上下文
  12. 用启用异常和启用替换的模式 导航 newContexturl
  13. 如果导航抛出异常,则以该异常拒绝 promise 并终止这些步骤。
  14. newContext 的 origin 与与该基于 Web 的支付处理程序相关联的 service worker client 的 origin 不同,则:
    1. 用 null 解决 promise
    2. 终止这些步骤。
  15. client 为以 newContext 作为参数,运行 创建窗口 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 字典

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 序列化的对象, 提供一条由商户用于处理交易并判断资金转账是否成功的, 支付方法 专有消息。

用户代理通过对应 respondWith 函数 所提供 Promise 的解决,从基于 Web 的支付处理程序处收到成功响应。 应用需用包含支付响应的 PaymentHandlerResponse 实例 来解决该 Promise。 如遇用户取消或出错,应用可通过拒绝该 Promise 来表示失败。

如果该 Promise 被拒绝,则用户代理必须运行 支付应用失败算法。 该算法的具体细节留给各实现者决定。 可接受的行为包括但不限于:

  • 允许用户重试,可以使用同一个基于 Web 的支付处理程序,也可以换一个;
  • 拒绝由 PaymentRequest.show() 创建的 Promise。

8.1.3 payerName 属性

用户提供的付款人姓名。

8.1.4 payerEmail 属性

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

8.1.5 payerPhone 属性

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

8.1.6 shippingAddress 属性

用户提供的收货地址。

8.1.7 shippingOption 属性

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

8.2 变更支付方法算法

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

  1. 以给定的 methodNamemethodDetails 参数构造 PaymentMethodChangeEvent event,并运行 payment method changed algorithm
  2. 如果 eventupdateWith(detailsPromise) 未被运行,则返回 null
  3. 如果 eventupdateWith(detailsPromise) 抛出异常,则重新抛出该错误。
  4. 如果 eventupdateWith(detailsPromise) 超时(可选),则抛出 "InvalidStateError" DOMException
  5. event.updateWith(detailsPromise) 中的 detailsPromise 构造并返回一个 PaymentRequestDetailsUpdate

8.3 变更支付详情算法

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

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

8.4 响应 PaymentRequest 算法

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

  1. 如果 eventisTrusted 为 false, 则抛出 "InvalidStateError" DOMException 并中止这些步骤。
  2. 如果 eventdispatch flag 未设置,则抛出 "InvalidStateError" DOMException 并中止这些步骤。
  3. 如果 event[[respondWithCalled]] 为 true,则抛出 "InvalidStateError" DOMException 并中止这些步骤。
  4. event[[respondWithCalled]] 设为 true。
  5. 设置 eventstop propagation flageventstop immediate propagation flag
  6. handlerResponsePromise 添加到 eventextend lifetime promises 中。
  7. eventpending promises count 增加 1。
  8. 当被拒绝时(Upon rejection), 针对 handlerResponsePromise
    1. 运行 支付应用失败算法 并中止这些步骤。
  9. 当被兑现时(Upon fulfillment), 针对 handlerResponsePromise
    1. handlerResponse 为将 value 转换为 IDL 值 的结果,类型为 PaymentHandlerResponse。若此操作抛出异常, 则运行 支付应用失败算法 并中止这些步骤。
    2. 校验 handlerResponse 中所有必需成员是否存在且格式正确。
      1. handlerResponsemethodName 不存在,或未设置为 eventmethodData 中的某个值,则运行 支付应用失败算法 并中止这些步骤。
      2. handlerResponsedetails 不存在或不是可 JSON 序列化的, 则运行 支付应用失败算法 并中止这些步骤。
      3. shippingRequired 为关联的 PaymentRequest 的 requestShipping 取值,来自 paymentOptions。 如果 shippingRequiredhandlerResponseshippingAddress 不存在,则运行 支付应用失败算法 并中止这些步骤。
      4. 如果 shippingRequiredhandlerResponseshippingOption 不存在,或未设置为来自 eventshippingOptions 中的某个配送选项标识符,则运行 支付应用失败算法 并中止这些步骤。
      5. payerNameRequired 为关联的 PaymentRequest 的 requestPayerName 取值,来自 paymentOptions。 如果 payerNameRequiredhandlerResponsepayerName 不存在,则运行 支付应用失败算法 并中止这些步骤。
      6. payerEmailRequired 为关联的 PaymentRequest 的 requestPayerEmail 取值,来自 paymentOptions。 如果 payerEmailRequiredhandlerResponsepayerEmail 不存在,则运行 支付应用失败算法 并中止这些步骤。
      7. payerPhoneRequired 为关联的 PaymentRequest 的 requestPayerPhone 取值,来自 paymentOptions。 如果 payerPhoneRequiredhandlerResponsepayerPhone 不存在,则运行 支付应用失败算法 并中止这些步骤。
    3. 序列化 handlerResponse 的必需成员(methodNamedetails 始终必需; 当 shippingRequired 为 true 时,shippingAddressshippingOption 必需; 当 payerNameRequiredpayerEmailRequiredpayerPhoneRequired 分别为 true 时,payerNamepayerEmailpayerPhone 必需):
      1. handlerResponse 中的每个 member,令 serializeMember 为调用 StructuredSerialize 处理 handlerResponse.member 的结果。若有异常则重新抛出。
    4. 用户代理MUST运行 [payment-request] 中定义的 user accepts the payment request algorithm,并以以下步骤替换其第 9-15 步或其等效步骤。
      1. 反序列化已序列化的成员:
        1. 对每个 serializeMember,令 member 为调用 StructuredDeserialize 处理 serializeMember 的结果。若有异常则重新抛出。
      2. 如果上述步骤中出现任何异常,则运行 支付应用失败算法 并中止这些步骤。
      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. 当被兑现(Upon fulfillment)当被拒绝(upon rejection) handlerResponsePromise 时, 将一个微任务排入队列以执行以下步骤:
    1. eventpending promises count 减一。
    2. registrationthis相关全局对象 所关联的 service workercontaining 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,生态系统中的各方(包括支付应用提供方和收款方)可在网络或其他故障后使用其进行对账。

9. 安全与隐私注意事项

9.1 地址

由于隐私问题,Web Payments 工作组从最初版本的 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] 所述,仅当且仅当这些词以此处所示的全大写形式出现时适用。

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

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

用户代理MAY对原本无限制的输入施加与实现相关的限制,例如为了防止拒绝服务攻击、避免内存耗尽或绕开平台特定限制。当某个输入超出与实现相关的限制时,用户代理MUST抛出,或在 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 Standard. Anne van Kesteren. WHATWG. Living Standard. URL: https://dom.spec.whatwg.org/
[ECMASCRIPT]
ECMAScript Language Specification. Ecma International. URL: https://tc39.es/ecma262/multipage/
[HTML]
HTML Standard. Anne van Kesteren; Domenic Denicola; Dominic Farolino; Ian Hickson; Philip Jägenstedt; Simon Pieters. WHATWG. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[payment-method-id]
Payment Method Identifiers. Marcos Caceres. W3C. 8 September 2022. W3C Recommendation. URL: https://www.w3.org/TR/payment-method-id/
[payment-method-manifest]
Payment Method Manifest. Dapeng(Max) Liu; Domenic Denicola; Zach Koch. W3C. 12 December 2017. FPWD. URL: https://www.w3.org/TR/payment-method-manifest/
[payment-request]
Payment Request API. Marcos Caceres; Ian Jacobs; Stephen McGruer. W3C. 27 January 2026. CRD. URL: https://www.w3.org/TR/payment-request/
[RFC2119]
Key words for use in RFCs to Indicate Requirement Levels. S. Bradner. IETF. March 1997. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc2119
[RFC8174]
Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words. B. Leiba. IETF. May 2017. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc8174
[SERVICE-WORKERS]
Service Workers Nightly. Monica CHINTALA; Yoshisato Yanagisawa. W3C. 26 January 2026. CRD. URL: https://www.w3.org/TR/service-workers/
[URL]
URL Standard. Anne van Kesteren. WHATWG. Living Standard. URL: https://url.spec.whatwg.org/
[WEBIDL]
Web IDL Standard. Edgar Chen; Timothy Gu. WHATWG. Living Standard. URL: https://webidl.spec.whatwg.org/

B.2 参考资料

[WebCryptoAPI]
Web Cryptography API. Mark Watson. W3C. 26 January 2017. W3C Recommendation. URL: https://www.w3.org/TR/WebCryptoAPI/