付款交易的生命周期

了解商家如何集成付款应用,以及付款交易如何与 Payment Request API 搭配使用。

Web Payments API 是首次内置于浏览器中的专用付款功能。借助 Web Payments,商家与付款应用的集成变得更简单,同时客户体验也更加顺畅、安全。

如需详细了解使用 Web Payments 的好处,请参阅利用 Web Payments 为付款应用赋能

本文将详细介绍商家网站上的付款交易,并帮助您了解付款应用集成的工作原理。

该流程包括 6 个步骤:

  1. 商家发起付款交易。
  2. 商家会显示付款按钮。
  3. 客户按下付款按钮。

    一张示意图,显示了奶酪店网站上显示的 BobPay(付款应用)按钮。

  4. 浏览器启动付款应用。

    奶酪店网站的示意图,其中 BobPay 应用以模态窗口的形式启动。模态窗口会显示配送选项和总费用。

  5. 如果客户更改了任何详细信息(例如配送方式或地址),商家会更新交易详情以反映相应更改。

    一张示意图,显示客户在 BobPay 应用模态中选择其他配送方式。第二张图显示了商家更新 BobPay 中显示的总费用。

  6. 客户确认购买后,商家会验证付款并完成交易。

    一张示意图,显示客户按下

第 1 步:商家发起付款交易

当客户决定购买商品时,商家会通过构建 PaymentRequest 对象来发起付款交易。此对象包含有关交易的重要信息:

  • 处理交易所需的可接受付款方式及其数据。
  • 总价(必填)和商品相关信息等详细信息。
  • 商家可以通过这些选项请求配送信息,例如送货地址和配送方式。
  • 商家还可以请求获取账单邮寄地址、付款人姓名、电子邮件地址和电话号码。
  • 商家还可以在 PaymentRequest 中添加可选的配送方式shippingdeliverypickup)。付款应用可以此为提示,在其界面中显示正确的标签。
const request = new PaymentRequest([{
  supportedMethods: 'https://bobpay.xyz/pay',
  data: {
    transactionId: '****'
  }
}], {
  displayItems: [{
    label: 'Anvil L/S Crew Neck - Grey M x1',
    amount: { currency: 'USD', value: '22.15' }
  }],
  total: {
    label: 'Total due',
    amount: { currency: 'USD', value : '22.15' }
  }
}, {
  requestShipping: true,
  requestBillingAddress: true,
  requestPayerEmail: true,
  requestPayerPhone: true,
  requestPayerName: true,
  shippingType: 'delivery'
});
添加交易 ID

某些付款处理程序可能会要求商家提供其提前签发的交易 ID,作为交易信息的一部分。典型的集成包括商家服务器与付款处理方服务器之间的通信,以预留总价。这样可以防止恶意客户在交易结束时通过验证操纵价格并欺骗商家。

商家可以将交易 ID 作为 PaymentMethodData 对象的 data 属性的一部分传递。

提供交易信息后,浏览器会根据付款方式标识符,完成 PaymentRequest 中指定的付款应用的发现流程。这样一来,当商家准备好继续交易时,浏览器就可以立即确定要启动的付款应用。

如需详细了解发现流程的运作方式,请参阅设置付款方式

第 2 步:商家显示付款按钮

商家可以支持多种付款方式,但应仅显示客户实际可以使用的付款方式的付款按钮。显示无法使用的付款按钮会给用户带来糟糕的体验。如果商家可以预测 PaymentRequest 对象中指定的付款方式不适用于客户,则可以提供后备解决方案,或者根本不显示该按钮。

使用 PaymentRequest 实例,商家可以查询客户是否有可用的付款应用。

客户是否有可用的付款应用?

如果客户设备上有可用的付款应用,PaymentRequestcanMakePayment() 方法会返回 true。“可用”表示系统发现了支持相应付款方式的付款应用,并且已安装平台专用付款应用,或者基于 Web 的付款应用已准备好注册

const canMakePayment = await request.canMakePayment();
if (!canMakePayment) {
  // Fallback to other means of payment or hide the button.
}

第 3 步:客户按付款按钮

当客户按下付款按钮时,商家会调用 PaymentRequest 实例的 show() 方法,该方法会立即触发付款界面的启动。

如果最终总价是动态设置的(例如从服务器检索),商家可以推迟启动付款界面,直到总金额确定为止。

推迟启动付款界面

查看演示,了解如何在确定最终总价之前推迟显示付款界面

如需延迟显示付款界面,商家会将 promise 传递给 show() 方法。浏览器将显示一个加载指示器,直到 promise 来解析并且事务准备好开始。

const getTotalAmount = async () => {
  // Fetch the total amount from the server, etc.
};

try {
  const result = await request.show(getTotalAmount());
  // Process the result…
} catch(e) {
  handleError(e);
}

如果未指定将 Promise 作为 show() 的参数,浏览器将立即启动付款界面。

第 4 步:浏览器启动付款应用

浏览器可以启动平台专用付款应用或基于网络的付款应用。您可以详细了解 Chrome 如何确定要启动哪个付款应用

付款应用的构建方式在很大程度上取决于开发者,但从商家发出和接收的事件以及随这些事件传递的数据结构是标准化的。

启动付款应用时,它会接收在第 1 步中传递给 PaymentRequest 对象的交易信息,其中包括:

  • 付款方式数据
  • 总价
  • 付款方式

付款应用使用交易信息来标记其界面。

第 5 步:商家如何根据客户的操作更新交易详情

客户可以选择在付款应用中更改交易详情,例如付款方式和运费选项。在客户进行更改时,商家会收到更改事件并更新交易详情。

商家可以接收四种类型的事件:

  • 付款方式更改事件
  • 送货地址更改事件
  • 配送选项更改事件
  • 商家验证事件

付款方式更改事件

付款应用可以支持多种付款方式,商家可能会根据客户的选择提供特别折扣。为了涵盖此用例,付款方式更改事件可以告知商家新的付款方式,以便他们更新含折扣的总金额并将其返回给付款应用。

request.addEventListener('paymentmethodchange', e => {
  e.updateWith({
    // Add discount etc.
  });
});

送货地址更改事件

付款应用可以选择提供客户的送货地址。这对客户来说很方便,因为他们无需手动在表单中输入任何详细信息,并且可以将送货地址存储在首选付款应用中,而不是在多个不同的商家网站上。

如果客户在交易开始后在付款应用中更新送货地址,系统会向商家发送 'shippingaddresschange' 事件。此事件可帮助商家根据新地址确定运费、更新总金额,并将其返回到付款应用。

request.addEventListener('shippingaddresschange', e => {
  e.updateWith({
    // Update the details
  });
});

如果商家无法配送到更新后的地址,则可以向返回给付款应用的交易详情添加错误参数,以提供错误消息。

配送选项更改事件

商家可以为客户提供多个配送选项,并且可以将该选择委托给付款应用。配送选项显示为客户可以从中进行选择的价格和服务名称列表。例如:

  • 标准配送 - 免费
  • 极速配送 - 5 美元

当客户在付款应用中更新配送选项时,系统会向商家发送 'shippingoptionchange' 事件。然后,商家可以确定运费、更新总价,并将其返回到付款应用。

request.addEventListener('shippingoptionchange', e => {
  e.updateWith({
    // Update the details
  });
});

商家还可以根据客户的送货地址动态修改配送选项。如果商家想要为国内和国际客户提供不同的配送选项,此属性非常有用。

商家验证事件

为了进一步提高安全性,付款应用可以在继续付款流程之前执行商家验证。验证机制的设计取决于付款应用,但商家验证事件用于告知商家可用于自行验证的网址。

request.addEventListener('merchantvalidation', e => {
  e.updateWith({
    // Use `e.validateURL` to validate
  });
});

第 6 步:商家验证付款并完成交易

当客户成功授权付款时,show() 方法会返回一个 promise,该 promise 会解析为 PaymentResponsePaymentResponse 对象包含以下信息:

  • 付款结果详情
  • 送货地址
  • 送货方式
  • 联系信息

此时,浏览器界面可能仍会显示加载指示器,表示交易尚未完成。

如果付款应用因付款失败或出错而终止,则从 show() 返回的 Promise 会被拒绝,并且浏览器会终止付款交易。

处理和验证付款

PaymentResponse 中的 details 是从付款应用返回的付款凭据对象。商家可以使用该凭据来处理或验证付款。此关键流程的运作方式取决于付款处理程序。

完成或重试交易

在确定交易是成功还是失败后,商家可以执行以下任一操作:

  • 调用 .complete() 方法以完成事务并关闭加载指示器。
  • 让客户通过调用 retry() 方法重试。
async function doPaymentRequest() {
  try {
    const request = new PaymentRequest(methodData, details, options);
    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();

后续步骤