PaymentRequest: show() 方法

安全上下文:此功能仅在安全上下文(HTTPS)中可用,在某些或所有支持的浏览器中。

PaymentRequest 接口的 show() 方法指示用户代理开始显示和处理付款请求用户界面的过程。

在所有文档中,一次只能处理一个付款请求。一旦一个 PaymentRequestshow() 方法被调用,任何其他对 show() 的调用都会被拒绝并返回 AbortError,直到返回的 Promise 完成,要么通过一个 PaymentResponse 满足,指示付款请求的结果,要么被拒绝并返回一个错误。

注意:实际上,尽管规范说明不能这样做,但包括 Firefox 在内的一些浏览器支持一次处理多个活动的付款请求。

如果您的架构在调用 show() 实例化支付接口时不一定准备好所有数据,请指定 detailsPromise 参数,提供一个 Promise,并在数据准备就绪后将其完成。如果提供了此参数,则 show() 将不允许用户与支付界面交互,直到 Promise 完成,以便在用户参与支付流程之前更新数据。

处理结果,并在必要时调用 PaymentResponse.retry() 重试失败的支付,可以异步或同步完成,具体取决于您的需求。为了获得最佳的用户体验,异步解决方案通常是最佳选择。MDN 和其他地方的大多数示例都使用 async/await 异步等待验证结果等。

语法

js
show()
show(details)

参数

details 可选

对象或解析为对象的 Promise。如果您的架构需要在实例化支付接口和用户开始与其交互之间更新付款请求的详细信息,请提供此参数。该对象应包含更新的信息

displayItems 可选

对象数组,每个对象描述付款请求的一行项目。这些表示收据或发票上的行项目,每个项目具有以下属性

amount

描述项目货币价值的对象。此对象包含以下字段

currency

包含有效的 3 个字母 ISO 4217 货币标识符(ISO 4217)的字符串,指示用于支付 value 的货币。

value

包含有效十进制值的字符串,表示构成支付金额的货币数量。此字符串只能包含一个可选的前导 "-" 以指示负值,然后是一个或多个数字 0 到 9,以及一个可选的小数点(“.”,与语言环境无关),后跟至少一位数字。不允许使用空格。

label

指定要收取费用项或服务的易于理解的名称或描述的字符串。这可能会由 用户代理 显示给用户,具体取决于界面的设计。

pending

布尔值,如果指定的 amount 尚未最终确定,则为 true。这可用于显示诸如运费或税款等项目,这些项目取决于送货地址、送货方式等的选定。用户代理可能会显示此信息,但不强制要求。

error 可选 已弃用 非标准

指定要显示给用户的错误消息的字符串。调用 updateWith() 时,在更新的数据中包含 error 会导致 用户代理 将文本显示为常规错误消息。对于地址字段特定的错误,请使用 shippingAddressErrors 字段。

modifiers 可选

对象数组,每个对象描述特定支付方法标识符的修饰符,每个对象具有以下属性

supportedMethods

表示支付方法标识符的字符串。仅当用户选择此支付方法时,支付方法标识符才适用。

total 可选

如果用户选择了此支付方法,则覆盖 detailsPromise 参数的 total 属性的对象。该属性与 detailsPromise 参数的 total 属性具有相同的输入。

additionalDisplayItems 可选

提供附加显示项目的 Array,如果用户选择了此支付方法,则将其附加到 detailsPromise 参数的 displayItems 属性。此属性通常用于添加折扣或附加费行项目,指示用户代理可能显示的用户选择的支付方法的不同总金额的原因。该属性与 detailsPromise 参数的 displayItems 属性具有相同的输入。

data 可选

可序列化对象,提供受支持的支付方法可能需要的可选信息。

例如,您可以使用它根据所选的支付方法调整总支付金额(“现金折扣 5%!”)。

shippingAddressErrors 可选 已弃用 非标准

包含无法验证的送货地址每个属性的错误消息的对象。

shippingOptions 可选 已弃用 非标准

对象数组,每个对象描述一个可供用户选择的送货选项。

total 可选

具有与 displayItems 中的对象相同属性的对象,提供支付的更新总计。确保这等于 displayItems 中所有项目的总和。不会自动计算。每当应付总金额发生变化时,您必须自己更新此值。这使您可以灵活地处理税款、折扣和其他对收取的总价的调整。

返回值

一个最终会解析为 PaymentResponsePromise。当用户接受付款请求时(例如,点击浏览器付款表单中的“支付”按钮),此 Promise 就会被解析。

异常

Promise 拒绝时,不会抛出异常,而是返回异常。

AbortError DOMException

如果 用户代理 已经在显示付款面板,则返回此异常。同一时间,在用户代理加载的所有文档中,只能显示一个付款面板。

如果用户取消付款请求,Promise 也会使用 AbortError 拒绝。

InvalidStateError DOMException

如果已为此请求显示相同的付款,则返回此异常(其状态为 interactive,因为它已在显示)。

NotSupportedError DOMException

如果用户代理不支持在调用 PaymentRequest 构造函数时指定的付款方式,则返回此异常。

SecurityError DOMException

如果调用 show() 不是响应用户操作(例如 clickkeyup 事件),则返回此异常。用户代理可以自行决定 SecurityError 抛出的其他原因,可能包括短时间内多次调用 show() 或在付款请求被家长控制阻止时调用 show() 等情况。

安全

需要 短暂的用户激活。用户必须与页面或 UI 元素交互才能使用此功能。

使用注意事项

使用 show() 的最常见模式包括使用 async/await 语法或使用 show().then().catch() 来处理响应和任何可能的拒绝。它们看起来像这样

async/await 语法

使用 await 等待 Promise 解析,可以编写特别简洁的处理付款的代码。

js
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 并提交付款或拒绝付款。

js
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() 函数。

js
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() 方法。

js
function validateResponse(response) {
  checkAllValues(response)
    .then((response) => response.complete("success"))
    .catch((response) => response.complete("fail"));
}

您甚至可以将 checkAllValues() 设为同步函数,尽管这可能会带来您不想处理的性能问题。

js
function validateResponse(response) {
  if (checkAllValues(response)) {
    response.complete("success");
  } else {
    response.complete("fail");
  }
}

如果您需要更多有关使用 Promise 的信息,请参阅文章 使用 Promise

示例

在以下示例中,在调用 show() 方法之前实例化了一个 PaymentRequest 对象。此方法触发用户代理内置的从用户处检索付款信息的流程。当用户交互完成后,show() 方法返回一个解析为 PaymentResponse 对象的 Promise。然后,开发人员使用 PaymentResponse 对象中的信息来格式化并将付款数据发送到服务器。您应该异步地将付款信息发送到服务器,以便最终对 paymentResponse.complete() 的调用可以指示付款的成功或失败。

js
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);
  }
};

以下示例显示了如何在向最终用户呈现付款表单时更新它。

js
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 的浏览器中加载。

另请参阅