版权所有 © 2026 万维网联盟 (W3C)。W3C® 法律免责声明、商标及宽松文档许可规则适用。
本规范标准化了一个 API,允许商家(即销售实物或数字商品的网站)以最小的集成成本使用一种或多种支付方式。用户代理(例如浏览器)在商家和用户之间促进支付流程。
本节描述了本文件发布时的状态。当前的 W3C 出版物列表和本技术报告的最新版本可以在 W3C 标准和草案索引中找到。
Web 支付工作组于 2022 年 9 月发布了《支付请求推荐标准》。经过隐私和国际化审查,该推荐标准排除了与账单和收货地址相关的 功能。然而,各实现方仍持续以互操作方式支持这些特性,因此工作组决定尝试重新使规范与实现保持一致,并就相关议题重新与社区接触。
作为重新添加地址支持的一部分,本规范现在引用 Contact Picker API 中定义的地址组件,而不是自行定义这些组件。事实上,Contact Picker API 正是衍生自 Payment Request API 中的原始定义,并因地址在支付之外的 Web 场景中同样有用而从本规范中抽离出来。
工作组计划在将规范推进到“建议推荐标准”(Proposed Recommendation)状态之前,进行讨论并遵循常规的审查流程。
工作组将通过制作一份 实现报告 来展示实现经验。该报告将显示两个或多个独立实现通过 测试套件 中的每一项强制测试(即,每一项测试对应规范中的一项 必须 (MUST) 要求)。
本文档由 Web 支付工作组 作为候选推荐标准草案,按照 推荐标准轨道 发布。
作为候选推荐标准发布并不意味着得到 W3C 及其成员的认可。候选推荐标准草案整合了来自先前候选推荐标准的更改,工作组打算将其包含在后续的候选推荐标准快照中。
本文件为草案,可能随时被其他文件更新、替换或废弃。将其作为非进展中的工作进行引用是不恰当的。对此未来推荐标准的更新可能会纳入 新特性。
本文档由在 W3C 专利政策 下运作的组织编写。W3C 维护一份 与该组交付成果相关的公开专利披露列表;该页面还包含披露专利的说明。任何知晓某项专利包含 必要权利要求 (Essential Claim) 的个人,必须根据 W3C 专利政策第 6 节 披露该信息。
本文件受 2025 年 8 月 18 日 W3C 流程文档约束。
本节是非规范性的。
本规范描述了一个 API,允许 用户代理(例如浏览器)充当交易中三方之间的中介
支付方式定义了
PaymentMethodData 的 data 成员接收。如果给定支付方式未指定,则不进行 IDL 转换,支付方式将以 JSON 格式接收 data。data 成员。如果给定支付方式未指定,则不进行验证。如何为给定的 支付方式 完成支付请求的细节属于 支付处理器 (payment handler) 的实现细节,后者是一个处理支付请求的应用程序或服务。具体而言,支付处理器定义了
描述如何处理用户更改支付方式或货币工具(例如,从借记卡更改为信用卡)的步骤,该更改导致 字典 或 object 或 null。
此 API 还使网站能够利用标准的 JavaScript 库无法实现的高安全性支付方案(例如,令牌化和系统级认证)。这有可能降低商家的责任,并有助于保护敏感的用户信息。
以下内容不在本规范的范围内
本节是非规范性的。
为了使用此 API,开发人员需要提供并跟踪一些关键信息。这些信息位作为参数传递给 PaymentRequest 构造函数,并随后用于更新向用户显示的支付请求。具体而言,这些信息位是
PaymentMethodData,代表站点支持的 支付方式(例如,“我们支持卡基支付,但仅限 Visa 和 MasterCard 信用卡。”)。PaymentDetailsInit 字典形式。这包括总金额,以及可选的购买商品或服务列表(针对实物商品)和配送选项。此外,它还可以可选地包含对支付方式的“修饰符”。例如,“如果您使用属于网络 X 的卡支付,则会产生 3.00 美元的处理费”。PaymentOptions 形式的一系列站点交付商品或服务所需的信息(例如,对于实物商品,商家通常需要物理配送地址。对于数字商品,电子邮件通常就足够了)。一旦构建了 PaymentRequest,它就会通过 show() 方法呈现给最终用户。show() 返回一个 Promise,该 Promise 在用户确认支付请求后,解析为一个 PaymentResponse。
在构建新的 PaymentRequest 时,商家使用第一个参数 (methodData) 来列出用户可以支付的不同方式(例如,信用卡、Apple Pay、Google Pay 等)。更具体地说,methodData 序列包含 PaymentMethodData 字典,其中包含商家接受的 支付方式 的 支付方式标识符 以及任何关联的 支付方式 特定数据(例如,支持哪些信用卡网络)。
const methodData = [
{
supportedMethods: "https://example.com/payitforward",
data: {
payItForwardField: "ABC",
},
},
{
supportedMethods: "https://example.com/bobpay",
data: {
merchantIdentifier: "XXXX",
bobPaySpecificField: true,
},
},
];
在构建新的 PaymentRequest 时,商家使用构造函数的第二个参数 (details) 来提供用户被要求完成的交易详情。这包括订单总额,以及可选的行项目,可以详细分解支付内容。
const details = {
id: "super-store-order-123-12312",
displayItems: [
{
label: "Sub-total",
amount: { currency: "GBP", value: "55.00" },
},
{
label: "Value-Added Tax (VAT)",
amount: { currency: "GBP", value: "5.00" },
},
],
total: {
label: "Total due",
// The total is GBP£65.00 here because we need to
// add shipping (below). The selected shipping
// costs GBP£5.00.
amount: { currency: "GBP", value: "65.00" },
},
};
这里我们展示了一个如何将两个配送选项添加到 details 的示例。
const shippingOptions = [
{
id: "standard",
// Shipping by truck, 2 days
label: "🚛 Envío por camión (2 dias)",
amount: { currency: "EUR", value: "5.00" },
selected: true,
},
{
id: "drone",
// Drone shipping, 2 hours
label: "🚀 Drone Express (2 horas)",
amount: { currency: "EUR", value: "25.00" }
},
];
Object.assign(details, { shippingOptions });
这里我们展示如何为在特定网络上使用卡添加处理费。请注意,这需要重新计算总额。
// Certain cards incur a $3.00 processing fee.
const cardFee = {
label: "Card processing fee",
amount: { currency: "AUD", value: "3.00" },
};
// Modifiers apply when the user chooses to pay with
// a card.
const modifiers = [
{
additionalDisplayItems: [cardFee],
supportedMethods: "https://example.com/cardpay",
total: {
label: "Total due",
amount: { currency: "AUD", value: "68.00" },
},
data: {
supportedNetworks: networks,
},
},
];
Object.assign(details, { modifiers });
某些金融交易要求用户提供特定信息,以便商家履行购买(例如,如果需要配送实物商品,则需要用户的配送地址)。为了请求此信息,商家可以向 PaymentRequest 构造函数传递第三个可选参数 (options),指示他们需要哪些信息。当支付请求显示时,用户代理将向最终用户请求此信息,并在用户接受支付请求时将其返回给商家。
const options = {
requestPayerEmail: false,
requestPayerName: true,
requestPayerPhone: false,
requestShipping: true,
}
收集了所有必要的信息位后,我们现在可以构建一个 PaymentRequest,并请求浏览器将其呈现给用户
async function doPaymentRequest() {
try {
const request = new PaymentRequest(methodData, details, options);
// See below for a detailed example of handling these events
request.onshippingaddresschange = ev => ev.updateWith(details);
request.onshippingoptionchange = ev => ev.updateWith(details);
const response = await request.show();
await validateResponse(response);
} catch (err) {
// AbortError, SecurityError
console.error(err);
}
}
async function validateResponse(response) {
try {
const errors = await checkAllValuesAreGood(response);
if (errors.length) {
await response.retry(errors);
return validateResponse(response);
}
await response.complete("success");
} catch (err) {
// Something went wrong...
await response.complete("fail");
}
}
// Must be called as a result of a click
// or some explicit user action.
doPaymentRequest();
在用户接受支付之前,站点有机会响应用户输入来更新支付请求。这可以包括例如提供额外的配送选项(或修改其成本)、移除无法配送到特定地址的商品等。
const request = new PaymentRequest(methodData, details, options);
// Async update to details
request.onshippingaddresschange = ev => {
ev.updateWith(checkShipping(request));
};
// Sync update to the total
request.onshippingoptionchange = ev => {
// selected shipping option
const { shippingOption } = request;
const newTotal = {
currency: "USD",
label: "Total due",
value: calculateNewTotal(shippingOption),
};
ev.updateWith({ total: newTotal });
};
async function checkShipping(request) {
try {
const { shippingAddress } = request;
await ensureCanShipTo(shippingAddress);
const { shippingOptions, total } = await calculateShipping(shippingAddress);
return { shippingOptions, total };
} catch (err) {
// Shows error to user in the payment sheet.
return { error: `Sorry! we can't ship to your address.` };
}
}
开发人员可以使用 shippingAddressErrors 字典成员(PaymentDetailsUpdate 的成员)来指示 ContactAddress 的特定属性存在验证错误。shippingAddressErrors 成员是一个 AddressErrors 字典,其成员明确划定了 物理地址 的错误字段,同时提供有助于显示给最终用户的错误消息。
request.onshippingaddresschange = ev => {
ev.updateWith(validateAddress(request.shippingAddress));
};
function validateAddress(shippingAddress) {
const error = "Can't ship to this address.";
const shippingAddressErrors = {
city: "FarmVille is not a real place.",
postalCode: "Unknown postal code for your country.",
};
// Empty shippingOptions implies that we can't ship
// to this address.
const shippingOptions = [];
return { error, shippingAddressErrors, shippingOptions };
}
PaymentResponse 中的数据预期会被 POST 回服务器进行处理。为了尽可能简化此过程,PaymentResponse 可以使用 默认 toJSON 步骤 (即 .toJSON()) 将对象直接序列化为 JSON。这使得使用 Fetch 标准 将生成的 JSON POST 回服务器变得非常简单
async function doPaymentRequest() {
const payRequest = new PaymentRequest(methodData, details);
const payResponse = await payRequest.show();
let result = "";
try {
const httpResponse = await fetch("/process-payment", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: payResponse.toJSON(),
});
result = httpResponse.ok ? "success" : "fail";
} catch (err) {
console.error(err);
result = "fail";
}
await payResponse.complete(result);
}
doPaymentRequest();
为了指示允许跨域 iframe 调用支付请求 API,可以在 iframe 元素上指定 allow 属性以及 "payment" 关键字。
<iframe
src="https://cross-origin.example"
allow="payment">
</iframe>
如果 iframe 将在多个支持支付请求 API 的源之间导航,则可以将 allow 设置为 "payment *"。权限策略 规范提供了更多详细信息和示例。
WebIDL[SecureContext, Exposed=Window]
interface PaymentRequest : EventTarget {
constructor(
sequence<PaymentMethodData> methodData,
PaymentDetailsInit details,
optional PaymentOptions options = {}
);
[NewObject]
Promise<PaymentResponse> show(optional Promise<PaymentDetailsUpdate> detailsPromise);
[NewObject]
Promise<undefined> abort();
[NewObject]
Promise<boolean> canMakePayment();
readonly attribute DOMString id;
readonly attribute ContactAddress? shippingAddress;
readonly attribute DOMString? shippingOption;
readonly attribute PaymentShippingType? shippingType;
attribute EventHandler onshippingaddresschange;
attribute EventHandler onshippingoptionchange;
attribute EventHandler onpaymentmethodchange;
};
开发人员创建 PaymentRequest 以发起支付请求。这通常与用户启动支付流程相关联(例如,通过激活网站上的“购买”、“支付”或“结账”按钮,在互动游戏中选择“强化”,或在停车场的自助终端支付)。PaymentRequest 允许开发人员在用户提供输入时与 用户代理 交换信息(直至用户批准或拒绝支付请求)。
如果设置了 requestShipping 成员,则 shippingAddress、shippingOption 和 shippingType 属性会在处理过程中被填充。
request 的 支付相关浏览上下文 是该 PaymentRequest 的 相关全局对象 的 浏览上下文 的 顶级浏览上下文。每个 支付相关浏览上下文 都有一个 支付请求正在显示 (payment request is showing) 布尔值,用于防止同时显示多个支付 UI。
支付请求正在显示 布尔值仅防止在单个浏览器标签页中显示多个支付 UI。然而,支付处理器 可以限制 用户代理 在所有浏览器窗口和标签页中仅显示一个支付 UI。其他支付处理器可能允许在不同的浏览器标签页中显示支付 UI。
PaymentRequest 使用所提供的 PaymentMethodData methodData 序列构建,其中包括任何 支付方式 特定的 data、PaymentDetailsInit details 以及 PaymentOptions options。
PaymentRequest(methodData, details, options) 构造函数 必须 (MUST) 按以下方式操作
Document 未 获准使用 "payment" 权限,则 抛出 一个 "SecurityError" DOMException。TypeError,并可选择告知开发人员至少需要一种 支付方式。supportedMethods 运行 验证支付方式标识符 的步骤。如果返回 false,则抛出 RangeError 异常。可选择告知开发人员支付方式标识符无效。supportedMethods 的结果supportedMethods。RangeError DOMException,并可选择告知开发人员此 支付方式标识符 是重复的。data 成员缺失,设 serializedData 为 null。否则,设 serializedData 为将 paymentMethod.data 序列化 为 JSON 字符串的结果。重新抛出任何异常。supportedMethods 的规范指定了一个 附加数据类型运行定义 paymentMethod.supportedMethods 的规范中关于 object 的 验证支付方式数据的步骤(如有)。重新抛出任何异常。
这些步骤确保任何 IDL 类型转换和验证错误都能尽早被捕获。
supportedMethods, serializedData) 添加到 serializedMethodData。displayItems 成员存在,则对于 details.displayItems 中的每个 item
requestShipping 成员存在并设置为 true,则处理配送选项sequence<PaymentShippingOption>。shippingOptions 成员存在,则
shippingOptions 设为 options。sequence<PaymentDetailsModifier>。modifiers 成员存在,则modifiers。total 成员存在,则
additionalDisplayItems 成员存在,则对于 modifier.additionalDisplayItems 中的每个 item
data 成员缺失,设 serializedData 为 null。否则,设 serializedData 为将 modifier.data 序列化 为 JSON 字符串的结果。重新抛出任何异常。supportedMethods, serializedData) 添加到 serializedModifierData。data 成员(如果存在)。modifiers 设为 modifiers。PaymentRequest。[[handler]] 设为 null。[[options]] 设为 options。[[state]] 设为 "created"。[[updating]] 设为 false。[[details]] 设为 details。[[serializedModifierData]] 设为 serializedModifierData。[[serializedMethodData]] 设为 serializedMethodData。[[response]] 设为 null。shippingOption 属性的值设为 selectedShippingOption。shippingAddress 属性的值设为 null。requestShipping 设置为 true,则将 request 上的 shippingType 属性的值设为 options.shippingType。否则,将其设为 null。获取时,id 属性返回此 PaymentRequest 的 [[details]].id。
出于审计和核对目的,商家可以将每个交易的唯一标识符与 id 属性相关联。
show(optional detailsPromise) 方法 必须 (MUST) 按以下方式操作
SecurityError" DOMException。这允许用户代理不需要用户激活,例如支持重定向流程,因为在重定向时可能不存在用户激活。有关安全考量,请参阅 19.9 用户激活要求。
另请参阅 issue #1022,关于在规范中提供更多指导的讨论,即用户代理何时应该或不应该要求用户激活以进行 show()。
Document。InvalidStateError" DOMException。"visible",则返回 一个被拒绝的 promise,并带有 "AbortError" DOMException。可选地,如果 用户代理 希望为了保护用户而禁止调用 show(),则返回一个被拒绝的 promise,并带有 "SecurityError" DOMException。例如,用户代理 可以限制页面调用 show() 的频率,如 19. 隐私与安全考量 所述。
[[state]] 不为 "created",则返回 一个被拒绝的 promise,并带有 "InvalidStateError" DOMException。[[state]] 设为 "closed"。AbortError" DOMException。[[state]] 设为 "interactive"。[[acceptPromise]] 设为 acceptPromise。可选地:
AbortError" DOMException 拒绝 acceptPromise。[[state]] 设为 "closed"。[[serializedMethodData]] 中的每个 paymentMethod 元组object。[[state]] 设为 "closed"。NotSupportedError" DOMException 拒绝 acceptPromise。呈现一个用户界面,允许用户与 handlers 进行交互。用户代理 应当 (SHOULD) 在呈现支付方式时优先考虑用户的偏好。用户界面 应当 (SHOULD) 使用与 document 的 文档元素 的 语言(如有)匹配的语言和基于本地的格式来呈现,如果该语言不可用,则使用适当的备用格式。
PaymentRequest 详情算法。基于 detailsPromise 的结算方式,更新 PaymentRequest 详情算法 决定支付 UI 的行为。即,在 detailsPromise 被拒绝时,支付请求中止。否则,在 detailsPromise 被履行时,用户代理重新启用支付请求 UI,支付流程可以继续。
[[handler]] 设为最终用户选择的 支付处理器。[[serializedModifierData]] 中的每个 tuple[[handler]] 的 支付方式标识符,则将 tuple 的第二个元素(序列化的方式数据)追加到 modifiers。传递 转换后的 paymentMethod 元组中的第二个元素和 modifiers。可选地,用户代理 应当 (SHOULD) 将 request 中的适当数据发送给用户选择的 支付处理器,以便引导用户完成支付流程。这包括 request 的各种属性和其他 内部槽位(出于隐私原因,某些 可以 (MAY) 被排除)。
[[serializedModifierData]] 内部槽位 中多个适用修饰符的处理属于 支付处理器 特有,不在本规范范围内。尽管如此,建议 (RECOMMENDED) 支付处理器 对 [[serializedModifierData]] 列表中的项使用“后者获胜 (last one wins)”的方法:也就是说,列表末尾的项总是优先于列表开头的任何项(参见下例)。
acceptPromise 稍后将由 用户接受支付请求算法、用户中止支付请求算法(通过用户界面交互触发),或 支付处理器指示内部错误算法 解析或拒绝。
如果在显示用户界面时 document 停止 完全活跃,或者到达此步骤时不再是完全活跃状态,则
[[state]] 设为 "closed"。AbortError" DOMException。abort() 方法 必须 (MUST) 按以下方式操作
[[response]] 不为 null,且 request.[[response]].[[retryPromise]] 不为 null,则返回 一个被拒绝的 promise,并带有 "InvalidStateError" DOMException。[[state]] 的值不是 "interactive"(交互中),则返回 一个被拒绝的 Promise,其拒绝理由为 "InvalidStateError" DOMException。InvalidStateError" DOMException 拒绝 promise,并终止这些步骤。[[state]] 设置为 "closed"(已关闭)。AbortError" DOMException 拒绝 Promise request.[[acceptPromise]]。开发者可以使用 canMakePayment() 方法来确定用户代理是否支持某种所需的支付方式。请参阅 19.8 canMakePayment() 保护措施。
canMakePayment() 返回 true 并不意味着用户拥有已配置好并可供支付的工具。
canMakePayment() 方法必须运行可进行支付算法。
PaymentRequest 的 shippingAddress 属性在用户提供送货地址时被填充。它默认为 null。当用户提供送货地址时,会运行送货地址变更算法。
PaymentRequest 的 shippingType 属性是用于完成交易的送货类型。其值要么是一个 PaymentShippingType 枚举值,要么是在构造期间未由开发者提供时的 null(参见 PaymentOptions 的 shippingType 成员)。
PaymentRequest 的 onshippingaddresschange 属性是一个用于名为 shippingaddresschange 的 PaymentRequestUpdateEvent 事件的 EventHandler。
PaymentRequest 的 shippingOption 属性在用户选择送货选项时被填充。它默认为 null。当用户选择送货选项时,会运行送货选项变更算法。
PaymentRequest 的 onshippingoptionchange 属性是一个用于名为 shippingoptionchange 的 PaymentRequestUpdateEvent 事件的 EventHandler。
PaymentRequest 的 onpaymentmethodchange 属性是一个用于名为 "paymentmethodchange" 的 PaymentMethodChangeEvent 事件的 EventHandler。
PaymentRequest 的实例创建时带有下表中所示的内部槽位
| 内部槽 | 描述(非规范性) |
|---|---|
| [[serializedMethodData]] | 提供给构造函数的 methodData,但表示为包含所支持方式和用于数据的字符串或 null 的元组(而非原始对象形式)。 |
| [[serializedModifierData]] | 一个列表,包含 [[details]].modifier 序列中每个对应项目的每个 data 成员的序列化字符串形式,如果不存在此类成员则为 null。 |
| [[details]] | 支付请求当前使用的 PaymentDetailsBase,最初提供给构造函数,随后通过调用 updateWith() 进行更新。注意,modifiers 成员中包含的所有 PaymentDetailsModifier 实例的 data 成员都将被移除,因为它们改以序列化形式存储在 [[serializedModifierData]] 内部槽位中。 |
| [[options]] | 提供给构造函数的 PaymentOptions。 |
| [[state]] |
支付请求的当前 状态,它从
状态转换如下图所示 show() 方法将状态更改为 "interactive"。在此之后,abort() 方法或任何其他错误可以将状态发送至 "closed";同样,用户接受支付请求算法和用户终止支付请求算法会将状态更改为 "closed"。 |
| [[updating]] | 如果存在待处理的 updateWith() 调用以更新支付请求则为 true,否则为 false。 |
| [[acceptPromise]] | 在 show() 期间创建的待处理 Promise,如果用户接受支付请求,它将被解析。 |
| [[response]] | Null,或由该 PaymentRequest 实例化的 PaymentResponse。 |
| [[handler]] | 与此 PaymentRequest 关联的支付处理程序。初始化为 null。 |
WebIDLdictionary PaymentMethodData {
required DOMString supportedMethods;
object data;
};
PaymentMethodData 字典用于指示一组支持的支付方式,以及这些方式的任何关联的支付方式特定数据。
supportedMethods 成员data 成员supportedMethods 的值已从数组改为字符串,但名称仍保持复数形式,以保持与 Web 上现有内容的兼容性。
WebIDLdictionary PaymentCurrencyAmount {
required DOMString currency;
required DOMString value;
};
PaymentCurrencyAmount 字典用于提供货币金额。
currency 成员一个 [ISO4217] 格式规范的 3 字母字母代码(即不支持数字代码)。其标准形式为大写。然而,可获得本地化货币符号的货币代码组合集取决于具体实现。
在显示货币价值时,建议用户代理显示货币代码,但用户代理显示货币符号是可选的。这是因为由于在多种不同货币中使用,货币符号可能会产生歧义(例如,“$”可能指 USD、AUD、NZD、CAD 等)。
用户代理可以格式化显示 currency 成员以符合操作系统约定(例如,用于本地化目的)。
实现本规范的用户代理通过 ECMAScript 的 isWellFormedCurrencyCode 抽象操作强制执行 [ISO4217] 的 3 字母代码格式,该操作作为检查并规范化金额算法的一部分被调用。当代码不符合 [ISO4217] 定义的格式时,将抛出 RangeError。
因此,当前的实现将允许使用不属于官方 [ISO4217] 列表(如 XBT、XRP 等)但格式规范的货币代码。如果提供的代码是浏览器知道如何显示的货币,则实现通常会在用户界面中显示适当的货币符号(例如,“USD”显示为 U+0024 美元符号 ($),“GBP”显示为 U+00A3 英镑符号 (£),“PLN”显示为 U+007A U+0142 兹罗提 (zł),非标准的“XBT”可以显示为 U+0243 带有横线的拉丁大写字母 B (Ƀ))。
ISO 正在努力处理数字货币,这可能会导致 [ISO4217] 注册表或全新的注册表进行更新。社区预期这将解决因使用非标准 3 字母代码而产生的歧义;例如,“BTC”是指比特币还是指未来不丹的货币?在发布之时,尚不清楚这种演变将采取何种形式,甚至不清楚完成这项工作的时间框架。W3C Web Payments 工作组正在与 ISO 联系,以便未来对本规范的修订能与相关的 ISO 注册表保持兼容。
value 成员{
"currency": "OMR",
"value": "1.234"
}
如果 JavaScript 字符串按给定的顺序由以下码位组成,则它是一个 有效十进制货币值
^-?[0-9]+(\.[0-9]+)?$
给定 PaymentCurrencyAmount amount,若要检查并规范化金额,请运行以下步骤
currency) 的结果为 false,则抛出 RangeError 异常,并可选地通知开发者货币无效。value 不是一个有效十进制货币值,则抛出 TypeError,并可选地通知开发者货币无效。currency 设置为 ASCII 大写 amount.currency 的结果。给定 PaymentCurrencyAmount amount,若要检查并规范化总金额,请运行以下步骤
WebIDLdictionary PaymentDetailsBase {
sequence<PaymentItem> displayItems;
sequence<PaymentShippingOption> shippingOptions;
sequence<PaymentDetailsModifier> modifiers;
};
displayItems 成员PaymentItem 字典,包含用户代理可以显示的支付请求行项目。shippingOptions 成员包含用户可选择的不同送货选项的序列。
如果序列中的某个项目将 selected 成员设置为 true,则这是默认使用的送货选项,并且 shippingOption 将设置为该选项的 id,而无需运行送货选项变更算法。如果序列中超过一个项目将 selected 设置为 true,则用户代理会选择序列中的最后一个。
shippingOptions 成员仅在 PaymentRequest 使用 PaymentOptions 构造且 requestShipping 设置为 true 时使用。
modifiers 成员PaymentDetailsModifier 字典。例如,它允许你根据支付方式调整总金额。WebIDLdictionary PaymentDetailsInit : PaymentDetailsBase {
DOMString id;
required PaymentItem total;
};
除了从 PaymentDetailsBase 字典继承的成员外,以下成员也是 PaymentDetailsInit 字典的一部分
id 成员total 成员PaymentItem。WebIDLdictionary PaymentDetailsUpdate : PaymentDetailsBase {
DOMString error;
PaymentItem total;
AddressErrors shippingAddressErrors;
PayerErrors payerErrors;
object paymentMethodErrors;
};
PaymentDetailsUpdate 字典用于使用 updateWith() 更新支付请求。
除了从 PaymentDetailsBase 字典继承的成员外,以下成员也是 PaymentDetailsUpdate 字典的一部分
error 成员updateWith() 更新支付请求时,PaymentDetailsUpdate 可在 error 成员中包含一条消息,如果 PaymentDetailsUpdate 指出不存在有效的 shippingOptions(且 PaymentRequest 在构造时将 requestShipping 选项设置为 true),则该消息将显示给用户。total 成员amount 的 PaymentItem。本规范中接受 PaymentDetailsUpdate 字典的算法,如果 total.amount.value 为负数,则会抛出异常。
shippingAddressErrors 成员payerErrors 成员paymentMethodErrors 成员支付方式特定错误。
WebIDLdictionary PaymentDetailsModifier {
required DOMString supportedMethods;
PaymentItem total;
sequence<PaymentItem> additionalDisplayItems;
object data;
};
PaymentDetailsModifier 字典提供了基于支付方式标识符修改 PaymentDetailsBase 的详细信息。它包含以下成员
supportedMethods 成员PaymentDetailsModifier 的成员仅在用户选择此支付方式时应用。total 成员PaymentItem 值,它会针对 supportedMethods 成员的支付方式标识符,覆盖 PaymentDetailsInit 字典中的 total 成员。additionalDisplayItems 成员PaymentItem 字典,提供附加的显示项目,这些项目会针对 supportedMethods 成员中的支付方式标识符,被追加到 PaymentDetailsBase 字典的 displayItems 成员中。此成员通常用于添加折扣或附加费行项目,表明用户代理可能显示的所选支付方式出现不同 total 金额的原因。开发者有责任验证 total 金额是否为 displayItems 和 additionalDisplayItems 的总和。
data 成员WebIDLenum PaymentShippingType {
"shipping",
"delivery",
"pickup"
};
shipping"(送货)delivery"(递送)pickup"(取货)WebIDLdictionary PaymentOptions {
boolean requestPayerName = false;
boolean requestBillingAddress = false;
boolean requestPayerEmail = false;
boolean requestPayerPhone = false;
boolean requestShipping = false;
PaymentShippingType shippingType = "shipping";
};
PaymentOptions 字典被传递给 PaymentRequest 构造函数,并提供有关支付请求所需选项的信息。
requestBillingAddress 成员PaymentMethodChangeEvent 的 methodDetails 的一部分返回。商家可以使用此信息来计算某些司法管辖区的税费并更新显示的金额。有关隐私考虑,请参阅下文关于暴露用户信息的内容。requestPayerName 成员requestPayerEmail 成员requestPayerPhone 成员requestShipping 成员shippingType 成员PaymentShippingType 枚举值。有些交易需要一个地址进行送货,但“shipping”一词并不合适。例如,“pizza delivery”(比萨配送)而非“pizza shipping”,以及“laundry pickup”(洗衣取货)而非“laundry shipping”。如果 requestShipping 设置为 true,则 shippingType 成员可以影响用户代理呈现收集送货地址的用户界面的方式。shippingType 成员仅影响支付请求的用户界面。
WebIDLdictionary PaymentItem {
required DOMString label;
required PaymentCurrencyAmount amount;
boolean pending = false;
};
PaymentDetailsBase 字典中包含一个或多个 PaymentItem 字典的序列,用于指示支付请求的目的以及所要求的金额。
label 成员amount 成员PaymentCurrencyAmount。pending 成员amount 成员不是最终值。这通常用于显示取决于送货地址或送货选项选择的项目,例如运费或税额。用户代理可能会在支付请求的用户界面中指示待处理字段。WebIDLdictionary PaymentCompleteDetails {
object? data = null;
};
PaymentCompleteDetails 字典在支付请求完成时,向支付处理程序提供来自商家网站的额外信息。
PaymentCompleteDetails 字典包含以下成员
data 成员PaymentResponse 关联支付方式可能需要的可选信息的对象。如果提供,它将被序列化。WebIDLenum PaymentComplete {
"fail",
"success",
"unknown"
};
fail"(失败)success"(成功)unknown"(未知)WebIDLdictionary PaymentShippingOption {
required DOMString id;
required DOMString label;
required PaymentCurrencyAmount amount;
boolean selected = false;
};
PaymentShippingOption 字典具有描述送货选项的成员。开发者可以通过在响应变更事件时调用 updateWith() 方法,向用户提供一个或多个送货选项。
id 成员PaymentShippingOption 的字符串标识符。对于给定的 PaymentRequest,它必须是唯一的。label 成员amount 成员PaymentCurrencyAmount。selected 成员PaymentShippingOption。用户代理应当在用户界面中默认显示此选项。WebIDL[SecureContext, Exposed=Window]
interface PaymentResponse : EventTarget {
[Default] object toJSON();
readonly attribute DOMString requestId;
readonly attribute DOMString methodName;
readonly attribute object details;
readonly attribute ContactAddress? shippingAddress;
readonly attribute DOMString? shippingOption;
readonly attribute DOMString? payerName;
readonly attribute DOMString? payerEmail;
readonly attribute DOMString? payerPhone;
[NewObject]
Promise<undefined> complete(
optional PaymentComplete result = "unknown",
optional PaymentCompleteDetails details = {}
);
[NewObject]
Promise<undefined> retry(optional PaymentValidationErrors errorFields = {});
attribute EventHandler onpayerdetailchange;
};
当用户选择了支付方式并批准了支付请求时,会返回 PaymentResponse。
retry(errorFields) 方法必须按照以下方式执行
[[request]]。Document。InvalidStateError" DOMException。[[complete]] 为 true,返回一个被拒绝的 Promise,其拒绝理由为 "InvalidStateError" DOMException。[[retryPromise]] 不为 null,返回一个被拒绝的 Promise,其拒绝理由为 "InvalidStateError" DOMException。[[state]] 设置为 "interactive"(交互中)。[[retryPromise]] 设置为 retryPromise。[[options]].requestPayerName 为 false,且 errorFields.payer.name 存在。[[options]].requestPayerEmail 为 false,且 errorFields.payer.email 存在。[[options]].requestPayerPhone 为 false,且 errorFields.payer.phone 存在。[[options]].requestShipping 为 false,且 errorFields.shippingAddress 存在。paymentMethod 成员,且定义 response.methodName 的规范有要求,则将 errorFields 的 paymentMethod 成员转换为该规范所指定类型的 IDL 值。否则,转换为 object。error 成员,则在用户代理 UI 中呈现该错误。如果成员的值为空字符串,用户代理可以替换为一个合适的错误信息值。[[state]] 设为 "关闭"。AbortError" DOMException 拒绝 retryPromise。[[retryPromise]] 设为 null。retryPromise 将在稍后由用户接受支付请求算法解析,或者由用户终止支付请求算法、终止更新或支付处理程序指示内部错误算法拒绝。
WebIDLdictionary PaymentValidationErrors {
PayerErrors payer;
AddressErrors shippingAddress;
DOMString error;
object paymentMethod;
};
payer 成员shippingAddress 成员PaymentResponse 的 shippingAddress 出现的验证错误。error 成员error 成员来给出验证问题的通用概述,也可以结合 PaymentValidationErrors 字典的其他成员一起传递。paymentMethod 成员WebIDLdictionary PayerErrors {
DOMString email;
DOMString name;
DOMString phone;
};
PayerErrors 用于表示一个或多个付款人详细信息的验证错误。
付款人详细信息是指付款人姓名、付款人电话号码和付款人电子邮件中的任意一项。
email 成员PaymentResponse 的 payerEmail 属性值的输入字段。name 成员PaymentResponse 的 payerName 属性值的输入字段。phone 成员PaymentResponse 的 payerPhone 属性值的输入字段。由支付方式生成的object 或 字典,商户可以使用它来处理或验证交易(取决于支付方式)。
如果传递给 PaymentRequest 构造函数的 PaymentOptions 中的 requestShipping 成员被设置为 true,则 shippingAddress 将是用户选择的完整且最终的送货地址。
如果传递给 PaymentRequest 构造函数的 PaymentOptions 中的 requestShipping 成员被设置为 true,则 shippingOption 将是所选送货选项的 id 属性。
如果传递给 PaymentRequest 构造函数的 PaymentOptions 中的 requestPayerName 成员被设置为 true,则 payerName 将是用户提供的姓名。
如果传递给 PaymentRequest 构造函数的 PaymentOptions 中的 requestPayerEmail 成员被设置为 true,则 payerEmail 将是用户选择的电子邮件地址。
如果传递给 PaymentRequest 构造函数的 PaymentOptions 中的 requestPayerPhone 成员被设置为 true,则 payerPhone 将是用户选择的电话号码。
生成此支付响应的相应支付请求 id。
complete() 方法在用户接受支付请求且 [[acceptPromise]] 已解析后调用。调用 complete() 方法告知用户代理支付交互已结束(并应当导致任何剩余的用户界面被关闭)。
支付请求被接受且 PaymentResponse 返回给调用者后,但在调用者调用 complete() 之前,支付请求用户界面保持挂起状态。此时,用户界面不应当提供取消命令,因为接受支付请求的结果已经返回。然而,如果出现问题且开发者从未调用 complete(),则用户界面会被阻塞。
因此,实现可以为开发者调用 complete() 施加超时限制。如果超时,实现将表现得如同调用了不带参数的 complete() 一样。
complete() 方法必须按以下方式执行
[[complete]] 为 true,则返回一个以 "InvalidStateError" DOMException 拒绝的 Promise。[[retryPromise]] 不为 null,则返回一个以 "InvalidStateError" DOMException 拒绝的 Promise。data 序列化为 JSON 字符串的结果。methodName 的规范有要求JSON 的 parse() 方法并传入 serializedData 的结果。methodName 的规范所指定类型的 IDL 值的结果。methodName 的规范有要求,则验证 idl 的成员。如果成员的值无效,则返回一个以 TypeError 拒绝的 Promise。[[complete]] 设为 true。AbortError" DOMException 拒绝 promise。允许开发者处理 "payerdetailchange" 事件。
PaymentResponse 的实例是使用下表中的内部槽位创建的
| 内部槽 | 描述(非规范性) |
|---|---|
| [[complete]] | 如果支付请求已完成(即调用了 complete(),或者发生了致命错误导致响应不再可用),则为 true,否则为 false。 |
| [[request]] | 实例化此 PaymentResponse 的 PaymentRequest 实例。 |
| [[retryPromise]] | Null,或一个在用户接受支付请求时解析,或在用户终止支付请求时拒绝的 Promise。 |
PaymentRequest 接口允许商户出于送货和/或账单目的向用户请求物理地址。送货地址和账单地址都是物理地址。
WebIDLdictionary AddressErrors {
DOMString addressLine;
DOMString city;
DOMString country;
DOMString dependentLocality;
DOMString organization;
DOMString phone;
DOMString postalCode;
DOMString recipient;
DOMString region;
DOMString sortingCode;
};
AddressErrors 字典的成员表示物理地址特定部分的验证错误。每个字典成员都有双重功能:首先,它的存在表示地址的特定部分出现验证错误。其次,字符串值允许开发者描述验证错误(以及最终用户可能如何修复该错误)。
开发者需要注意,用户可能无法修复地址的某些部分。因此,他们需要注意不要要求用户修复他们可能无法控制的问题。
addressLine 成员ContactAddress 的 addressLine 属性值的输入字段。city 成员ContactAddress 的 city 属性值的输入字段。country 成员ContactAddress 的 country 属性值的输入字段。dependentLocality 成员ContactAddress 的 dependentLocality 属性值的输入字段。organization 成员ContactAddress 的 organization 属性值的输入字段。phone 成员ContactAddress 的 phone 属性值的输入字段。postalCode 成员ContactAddress 的 postalCode 属性值的输入字段。recipient 成员ContactAddress 的 addressLine 属性值的输入字段。region 成员ContactAddress 的 region 属性值的输入字段。sortingCode 成员ContactAddress 的 sortingCode 属性值的输入字段。本规范定义了一个由字符串 "payment" 标识的策略控制功能 [permissions-policy]。其默认允许列表为 'self'。
本节是非规范性的。
| 事件名称 | Interface | 分派于…… | 目标 |
|---|---|---|---|
shippingaddresschange
|
PaymentRequestUpdateEvent
|
用户提供一个新的送货地址。 |
PaymentRequest
|
shippingoptionchange
|
PaymentRequestUpdateEvent
|
用户选择一个新的送货选项。 |
PaymentRequest
|
payerdetailchange
|
PaymentRequestUpdateEvent
|
用户更改付款人姓名、付款人电子邮件或付款人电话(参见付款人详细信息更改算法)。 |
PaymentResponse
|
paymentmethodchange
|
PaymentMethodChangeEvent
|
用户在支付处理程序内选择不同的支付方式。 |
PaymentRequest
|
WebIDL[SecureContext, Exposed=Window]
interface PaymentMethodChangeEvent : PaymentRequestUpdateEvent {
constructor(DOMString type, optional PaymentMethodChangeEventInit eventInitDict = {});
readonly attribute DOMString methodName;
readonly attribute object? methodDetails;
};
获取时,返回其初始化时的值。有关更多信息,请参见 PaymentMethodChangeEventInit 的 methodDetails 成员。
获取时,返回其初始化时的值。有关更多信息,请参见 PaymentMethodChangeEventInit 的 methodName 成员。
WebIDLdictionary PaymentMethodChangeEventInit : PaymentRequestUpdateEventInit {
DOMString methodName = "";
object? methodDetails = null;
};
methodName 成员methodDetails 成员WebIDL[SecureContext, Exposed=Window]
interface PaymentRequestUpdateEvent : Event {
constructor(DOMString type, optional PaymentRequestUpdateEventInit eventInitDict = {});
undefined updateWith(Promise<PaymentDetailsUpdate> detailsPromise);
};
PaymentRequestUpdateEvent 使开发者能够响应用户交互来更新支付请求的详细信息。
PaymentRequestUpdateEvent 的 构造函数(type, eventInitDict) 必须按以下方式执行
PaymentRequestUpdateEvent 的 构造函数的结果。[[waitForUpdate]] 设为 false。带 detailsPromise 的 updateWith() 方法必须按以下方式执行
isTrusted 属性为 false,则抛出一个 "InvalidStateError" DOMException。[[waitForUpdate]] 为 true,则抛出一个 "InvalidStateError" DOMException。PaymentResponse 的实例,令 request 为 event 的 目标 的 [[request]]。PaymentRequest 的实例。[[state]] 不为 "交互中",则抛出一个 "InvalidStateError" DOMException。[[updating]] 为 true,则抛出一个 "InvalidStateError" DOMException。[[waitForUpdate]] 设为 true。methodName 属性,则将 pmi 设为 methodName 属性的值。PaymentRequest 详细信息算法。PaymentRequestUpdateEvent 的实例是使用下表中的内部槽位创建的
| 内部槽 | 描述(非规范性) |
|---|---|
| [[waitForUpdate]] | 一个布尔值,指示 updateWith() 发起的更新当前是否正在进行中。 |
WebIDLdictionary PaymentRequestUpdateEventInit : EventInit {};
当 PaymentRequest 对象的 内部槽位 [[state]] 被设为 "交互中" 时,用户代理将根据用户交互触发以下算法。
可进行支付算法 检查用户代理是否支持使用构造 PaymentRequest 时所使用的支付方式进行支付。
PaymentRequest 对象。[[state]] 不为 "已创建",则返回一个以 "InvalidStateError" DOMException 拒绝的 Promise。Document。InvalidStateError" DOMException。NotAllowedError" DOMException 拒绝的 Promise。这允许用户代理应用启发式方法来检测并防止滥用调用该方法进行指纹识别,例如创建具有各种支持的支付方式的 PaymentRequest 对象,并依次在它们上触发可进行支付算法。例如,用户代理可以根据顶级浏览上下文或进行这些调用的时间段来限制可以进行的成功调用次数。
[[serializedMethodData]] 中的每个 paymentMethod 元组送货地址更改算法 在用户提供新的送货地址时运行。它 必须运行以下步骤
PaymentRequest 对象。redactList 限制了 API 与商户共享的关于收件人的个人信息量。
对于商户而言,由此产生的 ContactAddress 对象提供了足够的信息来(例如)计算运费,但在大多数情况下,不足以在物理上定位和唯一识别收件人。
不幸的是,即使有了 redactList,收件人的匿名性也无法保证。这是因为在一些国家,邮政编码的粒度非常细,以至于它们可以唯一识别收件人。
shippingAddress 设为 address。shippingaddresschange" 运行 PaymentRequest 更新算法。送货选项更改算法 在用户选择新的送货选项时运行。它 必须运行以下步骤
PaymentRequest 对象。shippingOption 属性设为用户提供的 PaymentShippingOption 的 id 字符串。shippingoptionchange" 运行 PaymentRequest 更新算法。当用户更改支付方式时,支付处理程序可以运行支付方式更改算法,并传入 methodDetails(其为一个字典、object 或 null)和一个 methodName(其为一个表示用户正在与之交互的支付处理程序的支付方式标识符的 DOMString)。
当用户选择或更改支付方式(例如信用卡)时,PaymentMethodChangeEvent 包含为了进行税务计算而脱敏的账单地址信息。脱敏属性包括但不限于地址行、从属区域、组织、电话号码和收件人。
PaymentRequest 对象。[[updating]] 为 false。一次只能进行一个更新。[[state]] 为 "交互中"。paymentmethodchange",使用 PaymentMethodChangeEvent,其 methodName 属性初始化为 methodName,其 methodDetails 属性初始化为 methodDetails。PaymentRequest 更新算法由上述其他算法运行,以触发事件来指示用户已对名为 request 的 PaymentRequest 进行了更改,且事件名为 name
[[updating]] 为 false。一次只能进行一个更新。[[state]] 为 "交互中"。PaymentRequestUpdateEvent 接口创建事件的结果。type 属性初始化为 name。[[waitForUpdate]] 为 true,则禁用任何可能导致触发另一个更新事件的用户界面部分。[[waitForUpdate]] 设为 true。当用户在用户界面中更改 付款人姓名、付款人电子邮件 或 付款人电话 时,用户代理 必须 运行 付款人详细信息更改算法。
PaymentRequest 对象。[[response]] 为 null,则返回。[[response]]。[[updating]] 为 false。[[state]] 为 "交互中"。[[options]]。requestPayerName 为 truepayerName 属性设置为 付款人姓名。requestPayerEmail 为 truepayerEmail 设置为 付款人电子邮件。requestPayerPhone 为 truepayerPhone 设置为 付款人电话。PaymentRequestUpdateEvent 创建事件 的结果。type 属性初始化为 "payerdetailchange"。[[waitForUpdate]] 为 true,则禁用用户界面中任何可能导致再次触发付款人详细信息更改的部分。[[waitForUpdate]] 设置为 true。用户接受付款请求算法 在用户接受付款请求并确认想要支付时运行。它 必须 在 用户交互任务源 上 排队一个任务 来执行以下步骤。
PaymentRequest 对象。[[updating]] 为 true,则终止此算法且不采取进一步操作。用户代理 用户界面 应该 确保这种情况永远不会发生。[[state]] 不为 "交互中",则终止此算法且不采取进一步操作。用户代理 用户界面 应该 确保这种情况永远不会发生。[[options]] 的 requestShipping 值为 true,且 request 的 shippingAddress 属性为 null,或者 request 的 shippingOption 属性为 null,则终止此算法且不采取进一步操作。用户代理 应该 确保这种情况永远不会发生。[[response]] 不为 null,则令 isRetry 为 true,否则为 false。[[response]];否则令其为一个新的 PaymentResponse。[[request]] 设置为 request。[[retryPromise]] 设置为 null。[[complete]] 设置为 false。requestId 属性值设置为 request.[[details]].id 的值。[[response]] 设置为 response。[[handler]]。methodName 属性值设置为 handler 的 支付方式标识符。details 属性值设置为运行 handler 的 响应付款请求的步骤 后得到的对象。[[options]] 的 requestShipping 值为 false,则将 response 的 shippingAddress 属性值设置为 null。否则,shippingAddress 属性值设置为 shippingAddress。shippingAddress 属性值设置为 shippingAddress。[[options]] 的 requestShipping 值为 true,则将 response 的 shippingOption 属性设置为 request 的 shippingOption 属性值。否则,将其设置为 null。[[options]] 的 requestPayerName 值为 true,则将 response 的 payerName 属性设置为用户提供的付款人姓名,若未提供则设为 null。否则,将其设置为 null。[[options]] 的 requestPayerEmail 值为 true,则将 response 的 payerEmail 属性设置为用户提供的付款人电子邮件地址,若未提供则设为 null。否则,将其设置为 null。[[options]] 的 requestPayerPhone 值为 true,则将 response 的 payerPhone 属性设置为用户提供的付款人电话号码,若未提供则设为 null。在设置 payerPhone 值时,用户代理 应该 将电话号码格式化为符合 [E.164] 标准。[[state]] 设置为 "已关闭"。[[retryPromise]]。否则,用 response 解析 request.[[acceptPromise]]。用户中止付款请求算法 在用户通过当前交互式用户界面中止付款请求时运行。它 必须 在 用户交互任务源 上 排队一个任务 来执行以下步骤。
PaymentRequest 对象。[[state]] 不为 "交互中",则终止此算法且不采取进一步操作。用户代理 用户界面 应该 确保这种情况永远不会发生。[[state]] 设置为 "已关闭"。AbortError" DOMException。[[response]]。[[complete]] 设置为 true。[[retryPromise]] 不为 null。[[retryPromise]]。[[acceptPromise]]。付款处理程序指示内部错误算法 在用户选择的 付款处理程序 遇到阻止其完成支付的内部错误时运行。发生此情况的原因包括操作系统终止了付款处理程序(例如,由于内存压力),或付款处理程序自身遇到了不可恢复的错误。
PaymentRequest 对象。[[state]] 不为 "交互中",则终止此算法且不采取进一步操作。OperationError" DOMException。[[state]] 设置为 "已关闭"。[[response]]。[[complete]] 设置为 true。[[retryPromise]] 不为 null。[[retryPromise]]。[[acceptPromise]]。"OperationError" 类型允许商户将付款处理程序错误与用户取消操作(使用 "AbortError")区分开来。
更新 PaymentRequest 详细信息算法 接收一个 PaymentDetailsUpdate detailsPromise、一个 PaymentRequest request,以及一个 pmi(DOMString 或 null,即 支付方式标识符)。这些步骤取决于 detailsPromise 的状态。如果 detailsPromise 永远不结算,则付款请求会被阻塞。用户代理 应该 提供用户中止付款请求的方法。实现 可以 选择为待处理的更新实现超时,如果 detailsPromise 在合理的时间内未结算。
在发生超时、用户手动中止,或 付款处理程序 决定中止此特定支付的情况下,用户代理 必须 运行 用户中止付款请求算法。
[[updating]] 设置为 true。AbortError" DOMException 中止更新。PaymentDetailsUpdate 字典的结果。如果这 抛出 异常,则用 request 和抛出的异常 中止更新。序列<PaymentShippingOption>。total 成员存在,则
displayItems 成员存在,则对于 details.displayItems 中的每个 item
shippingOptions 成员存在,且 request.[[options]].requestShipping 为 true,则shippingOptions 中的每个 option
modifiers 成员存在,则modifiers。PaymentDetailsModifier modifiersupportedMethods。若返回 false,则用 request 和一个 RangeError 异常 中止更新。可选地,告知开发者该支付方式标识符无效。total 成员存在,则
additionalDisplayItems 成员存在,则对于 modifier.additionalDisplayItems 中的每个 PaymentItem item
data 成员缺失,令 serializedData 为 null。否则,令 serializedData 为将 modifier.data 序列化 为 JSON 字符串的结果。如果抛出异常,则用 request 和该异常 中止更新。data 成员(如果存在)。paymentMethodErrors 成员存在且 identifier 不为 nullpaymentMethodErrors 转换为 IDL 值。paymentMethodErrors 的每个相关错误字段显示错误。PaymentRequest。total 成员存在,则[[details]].total 设置为 details.total。displayItems 成员存在,则[[details]].displayItems 设置为 details.displayItems。shippingOptions 成员存在,且 request.[[options]].requestShipping 为 true,则[[details]].shippingOptions 设置为 shippingOptions。shippingOption 属性值设置为 selectedShippingOption。modifiers 成员存在,则[[details]].modifiers 设置为 details.modifiers。[[serializedModifierData]] 设置为 serializedModifierData。若 request.[[options]].requestShipping 为 true,且 request.[[details]].shippingOptions 为空,则表明开发者已表示当前选择的送货地址(由 request 的 shippingAddress 提供)没有有效的送货选项。
在这种情况下,用户代理 应该 显示指示此情况的错误,并 可以 指出当前选择的送货地址在某种程度上无效。用户代理 应该 使用 details 的 error 成员(如果存在),提供有关该地址为何没有有效送货选项的更多信息。
此外,若 details["shippingAddressErrors"] 成员存在,用户代理 应该 为送货地址的每个错误字段专门显示错误。这是通过将 AddressErrors 的每个现有成员与显示的用户界面中对应的输入字段进行匹配来实现的。
类似地,若 details["payerErrors"] 成员存在,且 request.[[options]] 的 requestPayerName、requestPayerEmail 或 requestPayerPhone 为 true,则为每个错误字段专门显示错误。
同样,若 details.paymentMethodErrors 存在,则为特定支付方式的每个错误输入字段专门显示错误。
[[updating]] 设置为 false。对于 PaymentRequest request 和 异常 exception,中止更新 如下
[[state]] 设置为 "已关闭"。[[response]]。[[complete]] 设置为 true。[[retryPromise]] 不为 null。[[retryPromise]]。[[acceptPromise]]。[[updating]] 设置为 false。中止更新 在更新付款请求出现致命错误时运行,例如提供的 detailsPromise 被拒绝,或其履行值包含无效数据。这可能会使付款请求处于不一致的状态,因为开发者尚未成功处理更改事件。
因此,PaymentRequest 会进入 "已关闭" 状态。错误通过 [[acceptPromise]] 的拒绝向开发者发出信号,即 show() 返回的 Promise。
类似地,在 retry() 期间发生的 中止更新 会导致 [[retryPromise]] 被拒绝,并且相应的 PaymentResponse 的 [[complete]] 内部槽 将被设置为 true(即它不再能被使用)。
本节是非规范性的。
为了帮助确保用户不会无意中与来源共享敏感凭据,此 API 要求在相关 Window 具有 瞬态激活(例如通过点击或按下)时调用 PaymentRequest 的 show() 方法。
为避免混乱的用户体验,本规范通过 show() 方法将用户代理限制为一次仅显示一个。此外,用户代理可以限制页面调用 show() 的速率。
本节是非规范性的。
本规范中定义的 API 仅在 安全上下文 中公开 - 有关更多详细信息,请参阅 Secure Contexts 规范。在实践中,这意味着此 API 仅可通过 HTTPS 使用。这是为了限制支付方式数据(如信用卡号)以明文形式发送的可能性。
本节是非规范性的。
商户和其他收款方通常通过 iframe 将结账和其他电子商务活动委托给支付服务提供商。此 API 通过 [HTML] 的 allow 属性支持收款方授权的跨源 iframe。
付款处理程序 可以访问托管 iframe 的来源以及 iframe 内容的来源(即 PaymentRequest 发起的地方)。
本节是非规范性的。
PaymentRequest API 不直接支持数据字段的加密。个别 支付方式 可以选择包含对加密数据的支持,但并非所有 支付方式 都强制要求支持此功能。
本节是非规范性的。
出于安全原因,用户代理可以限制将匹配(在 show() 和 canMakePayment() 中)限制为与作为 URL 支付方式标识符 的 来源 相同的 付款处理程序。
支付方式 所有者为收集用于支付方式的用户数据如何使用制定隐私政策。Payment Request API 明确期望数据将用于完成交易的目的,并且与此 API 关联的用户体验传达了该意图。收款方有责任确保任何数据使用符合支付方式政策。对于完成交易之外的任何允许用途,收款方应向用户明确传达该用途。
用户代理 不得 在未经用户同意的情况下与开发者共享有关用户的信息(例如 送货地址)。
特别地,PaymentMethodData 的 data 和 PaymentResponse 的 details 成员允许进行任意数据交换。鉴于现有支付方式使用的数据模型范围广泛,在本 API 中规定数据细节将限制其有用性。details 成员承载来自付款处理程序的数据,无论是基于 Web 的(根据 Web-based Payment Handler API 定义)还是专有的。用户代理 不得 支持付款处理程序,除非它们包含足够的获取用户同意的机制(例如了解交易各方以及展示共享数据意图的机制)。
用户代理 不得 出于完成交易之外的任何目的共享 displayItems 成员或 additionalDisplayItems 成员的值。
PaymentMethodChangeEvent 使收款方能够根据所选 支付方式 特有的信息更新显示的金额。例如,与所选 支付方式 关联的账单地址可能会影响税款计算(例如 VAT),理想情况下用户界面应在付款人完成交易之前准确显示金额。同时,理想情况下应在付款完成前尽可能少地共享信息。因此,当 支付方式 定义 用户更改支付方式时的步骤 时,通过 PaymentMethodChangeEvent 的 methodDetails 属性共享的数据最小化非常重要。最小化共享数据的要求和方法可能因 支付方式 而异,可能包括
shippingAddress 中编校 地址行、组织、电话号码 和 收件人。PaymentResponse.details 返回)中排除或包含的特定元素。收款方可以通过 PaymentMethodData.data 提供这些指令,使 支付方式 定义能够在无需更改当前 API 的情况下演进。在共享隐私敏感信息对用户而言可能不明显的情况下(例如,当 更改支付方式 时),建议 用户代理向用户准确告知正在与商户共享哪些信息。
canMakePayment() 方法为不同的支付方式提供了功能检测。如果未来有大量的支付方式可用,它可能会成为一种指纹识别向量。用户代理应保护用户免受该方法的滥用。例如,用户代理可以通过以下方式减少用户指纹识别
为了进行速率限制,用户代理可能会查看来自以下方面的重复调用
这些速率限制技术旨在增加与重复调用相关的成本,无论是管理多个 可注册域名 的成本,还是打开多个窗口(标签页或弹出窗口)带来的用户体验摩擦。
如果用户代理不需要用户激活作为 show() 方法的一部分,则应考虑一些额外的安全缓解措施。不要求用户激活会增加垃圾邮件和点击劫持攻击的风险,因为它允许在用户未事先与页面进行即时交互的情况下启动付款请求 UI。
为了缓解垃圾邮件,用户代理可以决定在达到某个阈值后执行用户激活要求,例如在用户已经无需在当前页面上进行用户激活即被显示付款请求 UI 之后。为了缓解点击劫持攻击,用户代理可以在对话框显示后立即忽略点击的时间阈值。
另一个相关的缓解措施存在于 show() 的第 6 步中,其中文档必须可见才能启动用户交互。
本节是非规范性的。
对于 Payment Request API 的面向用户方面,实现通过表单控件和其他输入模态与平台辅助功能 API 集成。此外,为了提高金额、送货地址和联系信息的易理解性,实现会根据系统约定格式化数据。
本规范依赖于其他若干基础规范。
除了标记为非规范性的章节外,本规范中的所有创作指南、图表、示例和注释均为非规范性内容。本规范中的其他所有内容均为规范性内容。
本文档中的关键字 MAY、MUST、MUST NOT、OPTIONAL、RECOMMENDED、SHOULD 和 SHOULD NOT 仅在以全大写形式出现时,应按照 BCP 14 [RFC2119] [RFC8174] 的描述进行解释。
只有一类产品可以声称符合本规范:用户代理。
尽管本规范主要针对 Web 浏览器,但其他软件也可能以符合规范的方式实现本规范。
用户代理 可以 以任何期望的方式实现本规范中给出的算法,只要最终结果与通过本规范的算法获得的结果无法区分即可。
用户代理 可以 对原本不受限制的输入施加特定于实现的限制,例如为了防止拒绝服务攻击、防止内存耗尽或绕过特定于平台的限制。当输入超过特定于实现的限制时,用户代理 必须 抛出,或者在 Promise 的上下文中拒绝并返回一个 TypeError,并可选地告知开发者特定输入如何超过了特定于实现的限制。
WebIDL[SecureContext, Exposed=Window]
interface PaymentRequest : EventTarget {
constructor(
sequence<PaymentMethodData> methodData,
PaymentDetailsInit details,
optional PaymentOptions options = {}
);
[NewObject]
Promise<PaymentResponse> show(optional Promise<PaymentDetailsUpdate> detailsPromise);
[NewObject]
Promise<undefined> abort();
[NewObject]
Promise<boolean> canMakePayment();
readonly attribute DOMString id;
readonly attribute ContactAddress? shippingAddress;
readonly attribute DOMString? shippingOption;
readonly attribute PaymentShippingType? shippingType;
attribute EventHandler onshippingaddresschange;
attribute EventHandler onshippingoptionchange;
attribute EventHandler onpaymentmethodchange;
};
dictionary PaymentMethodData {
required DOMString supportedMethods;
object data;
};
dictionary PaymentCurrencyAmount {
required DOMString currency;
required DOMString value;
};
dictionary PaymentDetailsBase {
sequence<PaymentItem> displayItems;
sequence<PaymentShippingOption> shippingOptions;
sequence<PaymentDetailsModifier> modifiers;
};
dictionary PaymentDetailsInit : PaymentDetailsBase {
DOMString id;
required PaymentItem total;
};
dictionary PaymentDetailsUpdate : PaymentDetailsBase {
DOMString error;
PaymentItem total;
AddressErrors shippingAddressErrors;
PayerErrors payerErrors;
object paymentMethodErrors;
};
dictionary PaymentDetailsModifier {
required DOMString supportedMethods;
PaymentItem total;
sequence<PaymentItem> additionalDisplayItems;
object data;
};
enum PaymentShippingType {
"shipping",
"delivery",
"pickup"
};
dictionary PaymentOptions {
boolean requestPayerName = false;
boolean requestBillingAddress = false;
boolean requestPayerEmail = false;
boolean requestPayerPhone = false;
boolean requestShipping = false;
PaymentShippingType shippingType = "shipping";
};
dictionary PaymentItem {
required DOMString label;
required PaymentCurrencyAmount amount;
boolean pending = false;
};
dictionary PaymentCompleteDetails {
object? data = null;
};
enum PaymentComplete {
"fail",
"success",
"unknown"
};
dictionary PaymentShippingOption {
required DOMString id;
required DOMString label;
required PaymentCurrencyAmount amount;
boolean selected = false;
};
[SecureContext, Exposed=Window]
interface PaymentResponse : EventTarget {
[Default] object toJSON();
readonly attribute DOMString requestId;
readonly attribute DOMString methodName;
readonly attribute object details;
readonly attribute ContactAddress? shippingAddress;
readonly attribute DOMString? shippingOption;
readonly attribute DOMString? payerName;
readonly attribute DOMString? payerEmail;
readonly attribute DOMString? payerPhone;
[NewObject]
Promise<undefined> complete(
optional PaymentComplete result = "unknown",
optional PaymentCompleteDetails details = {}
);
[NewObject]
Promise<undefined> retry(optional PaymentValidationErrors errorFields = {});
attribute EventHandler onpayerdetailchange;
};
dictionary PaymentValidationErrors {
PayerErrors payer;
AddressErrors shippingAddress;
DOMString error;
object paymentMethod;
};
dictionary PayerErrors {
DOMString email;
DOMString name;
DOMString phone;
};
dictionary AddressErrors {
DOMString addressLine;
DOMString city;
DOMString country;
DOMString dependentLocality;
DOMString organization;
DOMString phone;
DOMString postalCode;
DOMString recipient;
DOMString region;
DOMString sortingCode;
};
[SecureContext, Exposed=Window]
interface PaymentMethodChangeEvent : PaymentRequestUpdateEvent {
constructor(DOMString type, optional PaymentMethodChangeEventInit eventInitDict = {});
readonly attribute DOMString methodName;
readonly attribute object? methodDetails;
};
dictionary PaymentMethodChangeEventInit : PaymentRequestUpdateEventInit {
DOMString methodName = "";
object? methodDetails = null;
};
[SecureContext, Exposed=Window]
interface PaymentRequestUpdateEvent : Event {
constructor(DOMString type, optional PaymentRequestUpdateEventInit eventInitDict = {});
undefined updateWith(Promise<PaymentDetailsUpdate> detailsPromise);
};
dictionary PaymentRequestUpdateEventInit : EventInit {};本规范源自 Web 平台孵化器社区组 先前发布的一份报告。
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
引用自
自 CR2 以来的变更
CR1 和 CR2 之间的变更