PaymentRequest: show() 方法
PaymentRequest 接口的 show() 方法指示用户代理开始向用户显示和处理支付请求的用户界面。
所有文档中,一次只能处理一个支付请求。一旦某个 PaymentRequest 的 show() 方法被调用,任何对 show() 的其他调用都将被 AbortError 拒绝,直到返回的 Promise 完成,无论是通过一个 PaymentResponse(指示支付请求的结果)完成,还是被错误拒绝。
注意: 实际上,尽管规范规定不能这样做,但包括 Firefox 在内的一些浏览器支持同时有多个活跃的支付请求。
如果您的架构在调用 show() 实例化支付界面时,不一定准备好所有数据,请指定 detailsPromise 参数,提供一个在数据准备好后完成的 Promise。如果提供了此参数,show() 将不允许用户与支付界面交互,直到该 Promise 完成,以便在用户开始支付过程之前更新数据。
处理结果,并在必要时调用 PaymentResponse.retry() 重试失败的支付,都可以异步或同步完成,具体取决于您的需求。为了获得最佳用户体验,异步解决方案通常是最佳选择。MDN 和其他地方的大多数示例都使用 async/await 异步等待结果验证等。
语法
show()
show(details)
参数
details可选-
一个对象或一个解析为对象的
Promise。如果您的架构要求在实例化支付界面和用户开始与其交互之间更新支付请求的详细信息,请提供此参数。该对象应包含更新后的信息。displayItems可选-
一个对象数组,每个对象描述支付请求的一个行项目。这些代表收据或发票上的行项目,每个都具有以下属性:
error可选 已废弃 非标准-
一个字符串,指定要呈现给用户的错误消息。当调用
updateWith()时,在更新数据中包含error会导致 用户代理 显示文本作为一般错误消息。对于地址字段特定的错误,请使用shippingAddressErrors字段。 modifiers可选-
一个对象数组,每个对象描述特定支付方法标识符的修饰符,每个都具有以下属性:
supportedMethods-
一个字符串,表示支付方法标识符。支付方法标识符仅在用户选择此支付方法时适用。
total可选-
一个对象,如果用户选择了此支付方法,它将覆盖
detailsPromise参数的total属性。该属性接受与detailsPromise参数的total属性相同的输入。 additionalDisplayItems可选-
一个
Array对象,如果用户选择了此支付方法,它将提供附加显示项目,这些项目将附加到detailsPromise参数的displayItems属性。此属性通常用于添加折扣或附加费行项目,以指示所选支付方法不同总金额的原因,用户代理可以显示这些信息。该属性接受与detailsPromise参数的displayItems属性相同的输入。 data可选-
一个可序列化对象,提供受支持的支付方法可能需要的可选信息。
例如,您可以使用它根据所选支付方式调整总支付金额(“5% 现金折扣!”)。
shippingAddressErrors可选 已废弃 非标准-
一个对象,其中包含配送地址的每个无法验证的属性的错误消息。
shippingOptions可选 已废弃 非标准-
一个对象数组,每个对象描述用户可能选择的一个可用配送选项。
total可选-
一个具有与
displayItems中的对象相同属性的对象,提供更新后的支付总额。请确保此值等于displayItems中所有项目的总和。这不是自动计算的。无论何时总欠款金额发生变化,您都必须自行更新此值。这让您可以灵活处理税费、折扣和对总价格的其他调整。
返回值
一个最终解析为 PaymentResponse 的 Promise。当用户接受支付请求时(例如通过单击浏览器支付表中的“支付”按钮),Promise 将被解析。
异常
当 Promise 拒绝时,不会抛出异常,而是返回异常。
AbortErrorDOMException-
如果 用户代理 已经显示支付面板,则返回此错误。在用户代理加载的所有文档中,一次只能显示一个支付面板。
如果用户取消支付请求,Promise 也会被
AbortError拒绝。 InvalidStateErrorDOMException-
如果此请求已显示相同的支付(其状态为
interactive,因为它已经显示),则返回此错误。 NotSupportedErrorDOMException-
如果在调用
PaymentRequest构造函数时用户代理不支持指定的支付方法,则返回此错误。 SecurityErrorDOMException-
如果调用
show()不是响应用户操作(例如click或keyup事件)而发出的,则返回此错误。抛出SecurityError的其他原因由用户代理自行决定,可能包括在短时间内调用show()次数过多,或在家长控制阻止支付请求时调用show()等情况。
安全
需要瞬态用户激活。用户必须与页面或 UI 元素交互才能使此功能正常工作。
用法说明
使用 show() 最常见的模式涉及 async/await 语法或使用 show().then().catch() 来处理响应和任何可能的拒绝。它们看起来像这样:
async/await 语法
使用 await 等待 Promise 解析,可以特别清晰地编写处理支付的代码。
async function processPayment() {
try {
const payRequest = new PaymentRequest(methodData, details, options);
payRequest.onshippingaddresschange = (ev) =>
ev.updateWith(checkAddress(payRequest));
payRequest.onshippingoptionchange = (ev) =>
ev.updateWith(checkShipping(payRequest));
const response = await payRequest.show();
await validateResponse(response);
} catch (err) {
/* handle the error; AbortError usually means a user cancellation */
}
}
在此代码中,方法 checkAddress() 和 checkShipping() 分别检查送货地址和送货选项的更改,并响应提供一个对象或一个返回对象的 Promise;此对象包含 PaymentResponse 中已更改或需要更改的字段。
下面的 validateResponse() 方法在 show() 返回后被调用,以查看返回的 response 并提交支付或拒绝支付为失败。
async function validateResponse(response) {
try {
if (await checkAllValues(response)) {
await response.complete("success");
} else {
await response.complete("fail");
}
} catch (err) {
await response.complete("fail");
}
}
在这里,一个名为 checkAllValues() 的自定义函数查看 response 中的每个值并确保它们有效,如果每个字段都有效则返回 true,如果任何字段无效则返回 false。当且仅当每个字段都有效时,在响应上调用 complete() 方法并传入字符串 "success",这表示一切都有效并且支付可以相应完成。
如果任何字段具有不可接受的值,或者前面的代码抛出异常,则调用 complete() 并传入字符串 "fail",这表示支付过程完成但失败。
您也可以选择在响应对象上调用 retry(),而不是立即失败,以要求用户代理尝试再次处理支付;这通常只应在用户对订单进行任何必要的更正后进行。
最后,启动支付过程就像调用 processPayment() 方法一样简单。
then/catch 语法
您也可以使用较旧的基于 Promise 的方法来处理支付,使用 show() 返回的 Promise 上的 then() 和 catch() 函数。
function processPayment() {
const payRequest = new PaymentRequest(methodData, details, options);
payRequest.onshippingaddresschange = (ev) =>
ev.updateWith(checkAddress(payRequest));
payRequest.onshippingoptionchange = (ev) =>
ev.updateWith(checkShipping(payRequest));
payRequest
.show()
.then((response) => validateResponse(response))
.catch((err) => handleError(err));
}
这在功能上等同于使用 await 语法的 processPayment() 方法。
function validateResponse(response) {
checkAllValues(response)
.then((response) => response.complete("success"))
.catch((response) => response.complete("fail"));
}
你甚至可以让 checkAllValues() 成为一个同步函数,尽管这可能会带来你不希望处理的性能影响。
function validateResponse(response) {
if (checkAllValues(response)) {
response.complete("success");
} else {
response.complete("fail");
}
}
如果您需要更多关于使用 Promise 的信息,请参阅文章 使用 Promise。
示例
在以下示例中,在调用 show() 方法之前实例化一个 PaymentRequest 对象。此方法触发用户代理内置的从用户那里获取支付信息的流程。当用户交互完成时,show() 方法返回一个解析为 PaymentResponse 对象的 Promise。然后,开发人员使用 PaymentResponse 对象中的信息格式化并向服务器发送支付数据。您应该异步地将支付信息发送到服务器,以便对 paymentResponse.complete() 的最终调用可以指示支付的成功或失败。
button.onclick = async () => {
// Initialization of PaymentRequest arguments are excerpted for the sake of
// brevity.
const payment = new PaymentRequest(methods, details, options);
try {
const response = await payment.show();
// Process response here, including sending payment instrument
// (e.g., credit card) information to the server.
// paymentResponse.methodName contains the selected payment method
// paymentResponse.details contains a payment method specific response
await response.complete("success");
} catch (err) {
console.error("Uh oh, something bad happened", err.message);
}
};
以下示例展示了如何在向最终用户呈现支付表单时更新它。
async function requestPayment() {
// We start with AU$0 as the total.
const initialDetails = {
total: {
label: "Total",
amount: { value: "0", currency: "AUD" },
},
};
const request = new PaymentRequest(methods, initialDetails, options);
// Check if the user supports the `methods`
if (!(await request.canMakePayment())) {
return; // no, so use a web form instead.
}
// Let's update the total as the sheet is shown
const updatedDetails = {
total: {
label: "Total",
amount: { value: "20", currency: "AUD" },
},
};
const response = await request.show(updatedDetails);
// Check response, etc.
}
document.getElementById("buyButton").onclick = requestPayment;
规范
| 规范 |
|---|
| Payment Request API # dom-paymentrequest-show |
浏览器兼容性
加载中…