Copyright © 2025 World Wide Web Consortium. W3C® liability, trademark and permissive document license rules apply.
本规范标准化了一个 API,允许商家(即销售实体或数字商品的网站)以最少的集成来利用一种或多种支付方式。用户代理(例如浏览器)促进商家和用户之间的支付流程。
本节描述了本文档发布时的状态。当前的 W3C 出版物列表以及本技术报告的最新修订版可以在位于 https://www.w3.org/TR/ 的 W3C 标准和草案索引中找到。
2022 年 9 月,Web 支付工作组发布了 Payment Request Recommendation。经过隐私和国际化审查后,该推荐标准排除了与账单和送货地址相关的功能。然而,实现一直在互操作地支持这些功能,因此工作组决定尝试使规范与实现重新对齐,并就相关问题重新与社区进行沟通。
本文档是基于原始推荐标准文本的候选推荐标准快照。随后的候选推荐标准草案将重新添加地址功能以及自推荐标准发布以来所做的一些其他更改。
作为重新添加地址支持的一部分,本规范现在引用 Contact Picker API 中定义的地址组件,而不是自行定义这些组件。实际上,Contact Picker API 源自 Payment Request API 中的原始定义,并从规范中分离出来,因为地址在 Web 上的用途超出了支付范围。
工作组计划在将规范推进到建议推荐标准状态之前进行讨论并遵循通常的审查流程。
工作组将通过生成实现报告来展示实现经验。该报告将显示两个或多个独立实现在测试套件中通过每个强制性测试(即,每个测试对应于规范的 MUST 要求)。
本文档由 Web 支付工作组作为候选推荐标准草案发布,采用推荐标准流程。
作为候选推荐标准发布并不意味着 W3C 及其成员的认可。候选推荐标准草案整合了工作组打算包含在后续候选推荐标准快照中的先前候选推荐标准的更改。
这是一份草案文件,可能随时被其他文件更新、替换或废弃。引用本文档作为正在进行的工作以外的任何内容都是不合适的。 本规范的未来更新可能会包含新功能。
本文档由一个在W3C 专利政策下运作的小组制作。 W3C 维护一个与该小组的可交付成果相关的任何专利披露的公开列表;该页面还包括披露专利的说明。任何实际知晓某项专利且认为该专利包含基本权利要求的个人必须按照W3C 专利政策第 6 节的规定披露该信息。
本文档受 2023年11月3日 W3C 流程文档的约束。
本节是非规范性的。
本规范描述了一个 API,该 API 允许 用户代理 (例如浏览器)在交易中的三方之间充当媒介:
支付方式定义了:
PaymentMethodData
的 data
成员接收。如果未为给定的支付方式指定,则不进行 IDL 转换,支付方式将以 JSON 格式接收
data
。
PaymentMethodData
的 data
成员的算法步骤。如果未为给定的支付方式指定,则不进行验证。
对于给定的支付方式,如何完成支付请求的详细信息是支付处理程序的实现细节,支付处理程序是处理支付请求的应用程序或服务。具体来说,支付处理程序定义了:
描述如何处理用户更改支付方式或货币工具(例如,从借记卡更改为信用卡)的步骤,这些步骤会产生字典、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.` };
}
}
开发者可以使用
PaymentDetailsUpdate
字典的 shippingAddressErrors
成员来指示 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 Standard
将生成的 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
将在支持 Payment Request API 的多个源之间导航,则可以将
allow
设置为
"payment *"
。 Permissions Policy 规范提供了更多详细信息和示例。
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
的相关全局对象的浏览上下文的
顶级浏览上下文。每个与支付相关的浏览上下文都有一个 支付请求正在显示布尔值,用于防止同时显示多个支付 UI。
支付请求正在显示布尔值仅防止在单个浏览器选项卡中显示多个支付 UI。但是, 支付处理程序可以将用户代理限制为仅在所有浏览器窗口和选项卡中显示一个支付 UI。其他支付处理程序可能允许在不同的浏览器选项卡中显示支付 UI。
PaymentRequest
是使用提供的
PaymentMethodData
序列
methodData(包括任何支付方式特定的 data
)、
PaymentDetailsInit
details 和
PaymentOptions
options 构造的。
PaymentRequest(methodData,
details, options)
构造函数必须按如下方式操作:
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)
方法必须按如下方式操作:
SecurityError
"
DOMException
。
这允许用户代理不需要用户激活,例如支持重定向流程,其中重定向后可能不存在用户激活。有关安全注意事项,请参见 19.9 用户激活要求。
另请参见
问题 #1022,其中讨论了在规范中提供更多关于用户代理何时应该或不应该为 show
()
要求用户激活的指导。
Document
。
AbortError
" 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"。
[[state]]
设置为
"closed"。
NotSupportedError
"
DOMException
拒绝
acceptPromise。
呈现一个用户界面,允许用户与 handlers 交互。用户代理应该在呈现支付方式时优先考虑用户的偏好。用户界面应该使用与 document 的文档元素的语言(如果有)匹配的语言和基于区域设置的格式,或者如果不可用,则使用适当的回退。
PaymentRequest
详情算法,使用 detailsPromise、request 和 null。
根据 detailsPromise 的稳定方式,更新
PaymentRequest
详情算法决定支付 UI 的行为方式。也就是说,在
detailsPromise 被拒绝时,支付请求中止。否则,在
detailsPromise 被满足时,用户代理重新启用支付请求 UI,支付流程可以继续。
[[handler]]
设置为最终用户选择的支付处理程序。
[[serializedModifierData]]
中的每个
tuple:
[[handler]]
的支付方式标识符匹配,则将
tuple 的第二个元素(序列化的方法数据)追加到 modifiers。
传递转换后的 paymentMethod 元组中的第二个元素和 modifiers。可选地,用户代理应该将 request 中的适当数据发送给用户选择的支付处理程序,以指导用户完成支付过程。这包括 request 的各种属性和其他内部插槽(出于隐私原因,在适当的情况下可以排除某些内容)。
[[serializedModifierData]]
内部插槽中多个适用修饰符的处理是支付处理程序特定的,超出了本规范的范围。然而,建议支付处理程序对
[[serializedModifierData]]
列表中的项目使用“后来者居上”的方法:也就是说,列表末尾的项目始终优先于列表开头的任何项目(参见下面的示例)。
acceptPromise 稍后将由用户接受支付请求算法或用户中止支付请求算法解析或拒绝,这些算法通过与用户界面的交互触发。
如果在显示用户界面时 document 不再完全激活,或者在此步骤到达时不再是,则:
abort
()
方法必须按如下方式操作:
[[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
()
方法必须运行can
make payment 算法。
当用户提供送货地址时,会填充 PaymentRequest
的 shippingAddress
属性。默认情况下,它为
null。当用户提供送货地址时,会运行送货地址更改算法。
PaymentRequest
的 shippingType
属性是用于完成交易的送货类型。其值为
PaymentShippingType
枚举值,如果开发者在构造
期间未提供(请参阅
PaymentOptions
的 shippingType
成员),则为 null。
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 ,如果用户接受支付请求,则该
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 位字母代码(即不支持数字代码)。它们的规范形式是大写。但是,可用的本地化货币符号的货币代码组合集取决于实现。
显示货币值时,建议用户代理显示货币代码,但用户代理显示货币符号是可选的。这是因为货币符号可能由于在多种不同货币中使用而含糊不清(例如,“$”可能表示美元、澳元、新西兰元、加元等)。
用户代理可以格式化
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 支付工作组正在与 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,则用户代理会选择序列中的最后一个。
仅当使用 PaymentOptions
构造 PaymentRequest
并且将 requestShipping
设置为 true
时,才会使用 shippingOptions
成员。
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
表明没有有效的 shippingOptions
(并且 PaymentRequest
是使用 requestShipping
选项设置为 true
构造的),则 PaymentDetailsUpdate
可以在
error
成员中包含一条消息,该消息将显示给用户。
total
成员
PaymentItem
,包含一个非负的 amount
。
本规范中接受
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
值,它会覆盖 PaymentDetailsInit
字典中针对
supportedMethods
成员的支付方式标识符的 total
成员。
additionalDisplayItems
成员
PaymentItem
字典序列,提供附加的显示项目,这些项目将附加到
PaymentDetailsBase
字典中的
displayItems
成员,用于 supportedMethods
成员中的支付方式标识符。此成员通常用于添加折扣或附加费行项目,以指示所选支付方式的不同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
枚举值。某些交易需要实际地址进行交付,但术语“配送”并不合适。例如,“披萨外送”而不是“披萨配送”,“洗衣取件”而不是“洗衣配送”。如果将
requestShipping
设置为 true,则 shippingType
成员会影响用户代理呈现用于收集送货地址的用户界面的方式。
shippingType
成员仅影响支付请求的用户界面。
WebIDLdictionary PaymentItem
{
required DOMString label
;
required PaymentCurrencyAmount
amount
;
boolean pending
= false;
};
一个或多个 PaymentItem
字典的序列包含在
PaymentDetailsBase
字典中,以指示支付请求的内容和请求的金额。
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
。
AbortError
" 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
中显示错误。在成员的值为空字符串的情况下,用户代理可以用适当的错误消息替换该值。
[[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
。
在用户接受支付请求并且 [[acceptPromise]]
已解决后,会调用
complete
()
方法。调用 complete
()
方法会告知用户代理支付交互已结束(并且应该导致关闭任何剩余的用户界面)。
在支付请求被接受并将 PaymentResponse
返回给调用者之后,但在调用者调用 complete
()
之前,支付请求用户界面保持待处理状态。此时,用户界面不应提供取消命令,因为已返回对支付请求的接受。但是,如果出现问题并且开发者从未调用 complete
()
,则用户界面将被阻止。
因此,实现可以为开发者调用 complete
()
设置超时。如果超时到期,则实现将表现得如同调用了不带参数的 complete
()
一样。
complete
()
方法必须按以下方式操作:
[[complete]]
为 true,则返回一个被拒绝的 promise,并带有 "InvalidStateError
"
DOMException
。
[[retryPromise]]
不为 null,则返回一个被拒绝的
promise,并带有 "InvalidStateError
"
DOMException
。
data
序列化为
JSON 字符串的结果。
methodName
的规范要求:
JSON
的 parse
()
的结果。
methodName
的规范指定的类型的 IDL
值的结果。
methodName
的规范要求,则验证
idl 的成员。如果成员的值无效,则返回一个被拒绝的 promise,并带有 TypeError
。
[[complete]]
设置为 true。
允许开发者处理“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'。
本节内容不具约束力。
事件名称 | 接口 | 分派时机… | 目标 |
---|---|---|---|
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
的 constructor
(type, eventInitDict)
必须按以下方式操作:
PaymentRequestUpdateEvent
的构造函数的结果。
[[waitForUpdate]]
设置为 false。
带有 detailsPromise 参数的 updateWith
()
方法必须按以下方式操作:
isTrusted
属性为
false,则抛出一个 "InvalidStateError
"
DOMException
。
[[waitForUpdate]]
为 true,则抛出一个 "InvalidStateError
"
DOMException
。
PaymentResponse
的实例,则令 request 为 event 的目标的 [[request]]
。
PaymentRequest
的实例。
[[state]]
不是 "interactive",则抛出一个 "InvalidStateError
"
DOMException
。
[[updating]]
为 true,则抛出一个 "InvalidStateError
"
DOMException
。
[[waitForUpdate]]
设置为 true。
methodName
属性,则将
pmi 设置为 methodName
属性的值。
PaymentRequest
详细信息算法。
PaymentRequestUpdateEvent
的实例是使用下表中的内部插槽创建的:
内部插槽 | 描述 (非规范性) |
---|---|
[[waitForUpdate]] |
一个布尔值,指示由 updateWith ()
启动的更新当前是否正在进行中。
|
WebIDLdictionary PaymentRequestUpdateEventInit
: EventInit {};
当 PaymentRequest
对象的内部插槽 [[state]]
设置为“interactive”时,用户代理将根据用户交互触发以下算法。
“可以付款”算法检查用户代理是否支持使用构建 PaymentRequest
时所用的付款方式进行付款。
PaymentRequest
对象。
[[state]]
不是“created”,则返回一个被拒绝的 promise,并附带一个“InvalidStateError
”DOMException
。
NotAllowedError
”DOMException
。
这允许用户代理应用启发式方法来检测和防止滥用调用方法进行指纹识别,例如创建具有各种受支持付款方式的 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]]
为 "interactive"。
PaymentMethodChangeEvent
在
request 上触发一个名为 "paymentmethodchange
" 的事件,其 methodName
属性初始化为 methodName,其 methodDetails
属性初始化为 methodDetails。
PaymentRequest 更新算法由上述其他算法运行,以触发一个事件,指示用户已对名为 request 的 PaymentRequest
进行了更改,事件名称为 name:
[[updating]]
为 false。一次只能进行一次更新。
[[state]]
为 "interactive"。
PaymentRequestUpdateEvent
接口创建事件的结果。
type
属性初始化为 name。
[[waitForUpdate]]
为
true,则禁用用户界面中可能导致触发另一个更新事件的任何部分。
[[waitForUpdate]]
设置为 true。
当用户在用户界面中更改付款人姓名、付款人电子邮件或付款人电话时,用户代理必须运行付款人详细信息更改算法:
PaymentRequest
对象。
[[response]]
为 null,则返回。
[[response]]
。
[[updating]]
为 false。
[[state]]
为 "interactive"。
[[options]]
。
requestPayerName
为
true:
payerName
属性设置为
付款人姓名。
requestPayerEmail
为
true:
payerEmail
设置为
付款人电子邮件。
requestPayerPhone
为
true:
payerPhone
设置为
付款人电话。
PaymentRequestUpdateEvent
创建事件的结果。
type
属性初始化为 "payerdetailchange
"。
[[waitForUpdate]]
为
true,则禁用用户界面中可能导致再次触发付款人详细信息更改的任何部分。
[[waitForUpdate]]
设置为 true。
当用户接受支付请求并确认他们想要支付时,会运行用户接受支付请求算法。它必须在用户交互任务源上排队一个任务以执行以下步骤:
PaymentRequest
对象。
[[updating]]
为 true,则终止此算法并且不执行任何进一步操作。用户代理用户界面应该确保这种情况永远不会发生。
[[state]]
不是“interactive”,则终止此算法并且不执行任何进一步操作。用户代理用户界面应该确保这种情况永远不会发生。
[[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]]
设置为“closed”。
[[retryPromise]]
。否则,使用 response 解析 request.[[acceptPromise]]
。
当用户通过当前交互式用户界面中止支付请求时,会运行用户中止支付请求算法。它必须在用户交互任务源上排队一个任务以执行以下步骤:
PaymentRequest
对象。
[[state]]
不是“interactive”,则终止此算法并且不执行任何进一步操作。用户代理用户界面应该确保这种情况永远不会发生。
[[state]]
设置为“closed”。
AbortError
”DOMException
。
[[response]]
。
[[complete]]
设置为 true。
[[retryPromise]]
不为 null。
[[retryPromise]]
。
[[acceptPromise]]
。
更新 PaymentRequest
的详细信息算法接受一个 PaymentDetailsUpdate
detailsPromise、一个 PaymentRequest
request 和一个 pmi(一个 DOMString 或 null,即支付方式标识符)。这些步骤取决于
detailsPromise 的解决情况。如果 detailsPromise 永远不解决,则支付请求将被阻塞。用户代理应该为用户提供中止支付请求的方法。如果 detailsPromise 在合理的时间内没有解决,实现可以选择为待处理的更新实现超时。
如果发生超时、用户手动中止或支付处理程序决定中止此特定支付,用户代理必须运行用户中止支付请求算法。
[[updating]]
设置为 true。
AbortError
”DOMException
中止更新。
PaymentDetailsUpdate
字典的结果。如果此操作抛出异常,则使用 request
和抛出的异常中止更新。
sequence
<PaymentShippingOption
>。
total
成员存在,则:
displayItems
成员存在,则对于 details.displayItems
中的每个 item:
shippingOptions
成员存在,并且 request.[[options]]
.requestShipping
为 true,则:
shippingOptions
中的每个 option:
modifiers
成员存在,则:
modifiers
。
PaymentDetailsModifier
modifier:
supportedMethods
运行验证支付方式标识符的步骤。如果返回
false,则使用 request 和一个 RangeError
异常中止更新。可选地,通知开发者支付方式标识符无效。
total
成员存在,则:
additionalDisplayItems
成员存在,则对于 modifier.additionalDisplayItems
中的每个 PaymentItem
item:
data
成员缺失,则令 serializedData 为 null。否则,令
serializedData 为将 modifier.data
序列化为
JSON 字符串的结果。如果抛出异常,则使用 request 和该异常中止更新。
data
成员存在,则移除它。
paymentMethodErrors
成员存在且 identifier 不为 null:
paymentMethodErrors
转换为
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]]
设置为“closed”。
[[response]]
。
[[complete]]
设置为 true。
[[retryPromise]]
不为 null。
[[retryPromise]]
。
[[acceptPromise]]
。
[[updating]]
设置为 false。
当更新支付请求时发生致命错误(例如提供的 detailsPromise 被拒绝,或其满足值包含无效数据)时,会运行中止更新。这可能会使支付请求处于不一致状态,因为开发者尚未成功处理更改事件。
因此,PaymentRequest
会进入“closed”状态。错误通过拒绝 [[acceptPromise]]
(即 show
()
返回的
promise)向开发者发出信号。
类似地,在 retry
()
期间发生中止更新会导致 [[retryPromise]]
被拒绝,并且相应的 PaymentResponse
的
[[complete]]
内部插槽将被设置为
true(即,它不能再使用)。
本节内容不具约束力。
为帮助确保用户不会无意中与某个来源共享敏感凭据,此 API 要求在相关 Window
具有瞬时激活(例如,通过单击或按压)时调用
PaymentRequest 的 show
()
方法。
为避免混乱的用户体验,本规范限制用户代理通过 show
()
方法一次仅显示一个。此外,用户代理可以限制页面调用 show
()
的速率。
本节内容不具约束力。
本规范中定义的 API 仅在安全上下文中公开——另请参阅 安全上下文规范了解更多详细信息。实际上,这意味着此 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 的(由
支付处理程序
API 定义)还是专有的。用户代理不得支持支付处理程序,除非它们包含足够的用户同意机制(例如交易各方的知情权和表明共享数据意图的机制)。
用户代理不得出于促进交易完成以外的任何目的共享 displayItems
成员或 additionalDisplayItems
成员的值。
PaymentMethodChangeEvent
使收款人能够根据所选支付方式的特定信息更新显示的总额。例如,与所选支付方式关联的账单地址可能会影响税款计算(例如增值税),并且希望用户界面在付款人完成交易之前准确显示总额。同时,希望在完成付款之前尽可能少地共享信息。因此,当支付方式定义用户更改支付方式时的步骤时,重要的是尽量减少通过 PaymentMethodChangeEvent
的 methodDetails
属性共享的数据。最小化共享数据的要求和方法可能因支付方式而异,并且可能包括:
shippingAddress
)。
PaymentResponse
.details
返回)中排除或包含的特定元素的说明。收款人可以通过 PaymentMethodData
.data
提供这些说明,从而使支付方式定义能够在不需要更改当前 API 的情况下进行演变。
在共享隐私敏感信息可能对用户不明显的情况下(例如,当更改支付方式时),建议用户代理告知用户正在与商家共享哪些确切信息。
canMakePayment
()
方法为不同的支付方式提供功能检测。如果将来有大量支付方式可用,它可能会成为一个指纹识别向量。用户代理应保护用户免受该方法的滥用。例如,用户代理可以通过以下方式减少用户指纹识别:
对于速率限制,用户代理可能会查看来自以下位置的重复调用:
这些速率限制技术旨在增加与重复调用相关的成本,无论是管理多个可注册域的成本,还是打开多个窗口(选项卡或弹出窗口)的用户体验摩擦。
如果用户代理不要求用户激活作为 show
()
方法的一部分,则应考虑一些额外的安全缓解措施。不要求用户激活会增加垃圾邮件和点击劫持攻击的风险,因为它允许在用户没有立即与页面交互的情况下启动支付请求 UI。
为了缓解垃圾邮件,用户代理可以决定在某个阈值之后强制执行用户激活要求,例如在用户已经在当前页面上看到没有用户激活的支付请求 UI 之后。为了缓解点击劫持攻击,用户代理可以实现一个时间阈值,在该阈值内,在显示对话框后立即忽略点击。
show
()
的步骤 6
中存在另一个相关的缓解措施,其中文档必须可见才能启动用户交互。
本节内容不具约束力。
对于 Payment Request API 面向用户的方面,实现通过表单控件和其他输入方式与平台无障碍 API 集成。此外,为了提高总计、送货地址和联系信息的可理解性,实现会根据系统约定格式化数据。
本规范依赖于其他几个底层规范。
除了标记为非规范性的章节外,本规范中的所有创作指南、图表、示例和注释都是非规范性的。本规范中的其他所有内容都是规范性的。
本文档中的关键词 可以、必须、不得、可选、建议、应该 和 不应 按照 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 平台孵化器社区组先前发布的一份报告。
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
从 CR2 到现在的变更:
CR1 和 CR2 之间的变更: