安全上下文
此特征只可用于
安全上下文
(HTTPS),在某些或所有
支持浏览器
.
PaymentRequest
接口的
show()
method instructs the user agent to begin the process of showing and handling the user interface for the payment request to the user.
For security reasons, the
PaymentRequest.show()
method can't just be initiated at any time. It may only be called while handling events that represent user interactions, such as
click
,
keyup
, or the like.
Only one payment request can be in the process of being handled at once, across all documents. Once one
PaymentRequest
's
show()
method has been called, any other call to
show()
will by rejected with an
AbortError
until the returned promise has been concluded, either by being fulfilled with a
PaymentResponse
indicating the results of the payment request, or by being rejected with an error.
注意: In reality, despite the fact that the specification says this can't be done, some browsers, including Firefox, support multiple active payment requests at a time.
If your architecture doesn't necessarily have all of the data ready to go at the moment it instantiates the payment interface by calling
show()
,指定
detailsPromise
parameter, providing a
Promise
that is fulfilled once the data is ready. If this is provided,
show()
will not allow the user to interact with the payment interface until the promise is fulfilled, so that data can be updated prior to the user engaging with the payment process.
Processing the result and, if necessary, calling
PaymentResponse.retry()
to retry a failed payment can all be done either asynchronously or synchronously, depending on your needs. For the best user experience, asynchronous solutions are typically the best way to go. Most examples on MDN and elsewhere use
async
/
await
to wait asynchronously while results are validated and so forth.
paymentPromise = paymentRequest.show(detailsPromise);
detailsPromise
可选
Promise
that you can provide if your architecture requires that the payment request's details need to be updated between instantiating the payment interface and the user beginning to interact with it. The promise should resolve with a
PaymentDetailsUpdate
object containing the updated information.
A
Promise
that eventually resolves with a
PaymentResponse
. The promise is resolved when the user accepts the payment request (such as by clicking a "Pay" button in the browser's payment sheet).
AbortError
The returned promise rejects with an
AbortError
若
用户代理
is already showing a payment panel. Only one payment panel may be visible at a time
across all documents loaded by the user agent
.
The promise is also rejected with
AbortError
if the user cancels the payment request.
InvalidStateError
InvalidStateError
if the same payment has already been shown for this request (its state is
interactive
because it is being shown already).
NotSupportedError
NotSupportedError
if the user agent does not support the payment methods specified when the
PaymentRequest
constructor was called.
SecurityError
SecurityError
if the call to
show()
was not in response to a user action, such as a
click
or
keyup
event. Other reasons a
SecurityError
may be thrown are at the discretion of the user agent, and may include situations such as too many calls to
show()
being made in a short time or
show()
being called while payment requests are blocked by parental controls.
The most common patterns for using
show()
involve either the
async
/
await
syntax or the use of
show().then().catch()
to handle the response and any possible rejection. Those look like this:
使用
await
to wait for a promise to be resolved makes it possible to write the code to handle payments particularly cleanly:
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 repsonse = await payRequest.show();
await validateResponse(response);
} catch(err) {
/* handle the error; AbortError usually means a user cancellation */
}
}
In this code, the methods
checkAddress()
and
checkShipping()
, respectively, check the shipping address and the shipping option changes and supply in response either a
PaymentDetailsUpdate
object or a promise to return one; this object contains the fields in the
PaymentResponse
which have been or need to be changed.
validateResponse()
method, below, is called once
show()
returns, in order to look at the returned
response
and either submit the payment or reject the payment as failed:
async function validateResponse(response) {
try {
if (await checkAllValues(response)) {
await response.complete("success");
} else {
await response.complete("fail");
}
} catch(err) {
await response.complete("fail");
}
}
Here, a custom function called
checkAllValues()
looks at each value in the
response
and ensures that they're valid, returning
true
if every field is valid or
false
if any are not. If and only if every field is valid, the
complete()
method is called on the response with the string
"success"
, which indicates that everything is valid and that the payment can complete accordingly.
If any fields have unacceptable values, or if an exception is thrown by the previous code,
complete()
is called with the string
"fail"
, which indicates that the payment process is complete and failed.
Instead of immediately failing, you could choose to call
retry()
on the response object to ask the user agent to try to process the payment again; this should usually only be done after the user has made any needed corrections to the order.
Starting the payment process, in the end, is as simple as calling the
processPayment()
方法。
You can also use the older promise-based approach to work with payments, using the
then()
and
catch()
functions on the promise returned by
show()
:
function processsPayment() {
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));
}
This is functionally equivalent to the
processPayment()
方法使用
await
句法。
function validateResponse(response) {
checkAllValues(response)
.then(response => response.complete("success"))
.catch(response => response.complete("fail"));
}
You could even have
checkAllValues()
be a synchronous function, although that may have performance implications you don't want to deal with:
function validateResponse(response) {
if (checkAllValues(response) {
response.complete("success");
} else {
response.complete("fail");
}
}
See the article Using promises for more information if you need more information about working with promises.
In the following example, a
PaymentRequest
object is instantiated before the
show()
method is called. This method triggers the user agent's built-in process for retrieving payment information from the user. The
show()
方法返回
Promise
解析为
PaymentResponse
object when the user interaction is complete. The developer then uses the information in the
PaymentResponse
object to format and send payment data to the server. You should send the payment information to the server asynchronously so that the final call to
paymentResponse.complete()
can indicate the success or failure of the payment.
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);
}
}
The following example shows how to update the payment sheet as it's being presented to the end-user.
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 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;
| 规范 | 状态 | 注释 |
|---|---|---|
|
支付请求 API
The definition of 'show(optional detailsPromise)' in that specification. |
候选推荐 | 初始定义。 |
| 桌面 | 移动 | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
show
|
Chrome 61 | Edge 15 |
Firefox
55
注意事项
Disabled
|
IE 不支持 No | Opera 不支持 No | Safari 11.1 | WebView Android 不支持 No | Chrome Android 53 |
Firefox Android
55
注意事项
Disabled
|
Opera Android 不支持 No | Safari iOS 11.3 | Samsung Internet Android 6.0 |
完整支持
不支持
见实现注意事项。
用户必须明确启用此特征。
PaymentRequest.abort()
PaymentRequest.retry()
PaymentRequest.complete()
PaymentResponse
PaymentRequest
canMakePayment()
show()