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
拒绝时,不会抛出异常,而是返回异常。
AbortError
DOMException
-
如果 用户代理 已经在显示付款面板,则返回此异常。同一时间,在用户代理加载的所有文档中,只能显示一个付款面板。
如果用户取消付款请求,Promise 也会使用
AbortError
拒绝。 InvalidStateError
DOMException
-
如果已为此请求显示相同的付款,则返回此异常(其状态为
interactive
,因为它已在显示)。 NotSupportedError
DOMException
-
如果用户代理不支持在调用
PaymentRequest
构造函数时指定的付款方式,则返回此异常。 SecurityError
DOMException
-
如果调用
show()
不是响应用户操作(例如click
或keyup
事件),则返回此异常。用户代理可以自行决定SecurityError
抛出的其他原因,可能包括短时间内多次调用show()
或在付款请求被家长控制阻止时调用show()
等情况。
安全
需要 短暂的用户激活。用户必须与页面或 UI 元素交互才能使用此功能。
使用注意事项
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 function handlePurchase() {
// 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 |
浏览器兼容性
BCD 表格仅在启用 JavaScript 的浏览器中加载。