Payment Request API(支付请求 API)

W3C 候选推荐标准草案

关于此文档的更多细节
此版本
https://w3org.cn/TR/2026/CRD-payment-request-20260327/
最新发布版本
https://w3org.cn/TR/payment-request/
最新编辑草案
https://w3c.github.io/payment-request/
历史
https://w3org.cn/standards/history/payment-request/
提交历史
测试套件
https://wpt.live/payment-request/
实现报告
https://w3c.github.io/test-results/payment-request/all.html
最新推荐标准
https://w3org.cn/TR/2022/REC-payment-request-20220908/
编辑
Marcos Cáceres (Apple Inc.)
Ian Jacobs (W3C)
Stephen McGruer (Google)
前任编辑
Domenic Denicola (Google)
Adrian Bateman (Microsoft Corporation)
Zach Koch (Google)
Roy McElmurry (Facebook)
Danyao Wang (Google)
Rouslan Solomakhin (Google) - 直至
反馈
GitHub w3c/payment-request (pull requests, 新议题, 开放议题)
浏览器支持
caniuse.com

摘要

本规范标准化了一个 API,允许商家(即销售实物或数字商品的网站)以最小的集成成本使用一种或多种支付方式。用户代理(例如浏览器)在商家和用户之间促进支付流程。

本文档状态

本节描述了本文件发布时的状态。当前的 W3C 出版物列表和本技术报告的最新版本可以在 W3C 标准和草案索引中找到。

Web 支付工作组于 2022 年 9 月发布了《支付请求推荐标准》。经过隐私和国际化审查,该推荐标准排除了与账单和收货地址相关的 功能。然而,各实现方仍持续以互操作方式支持这些特性,因此工作组决定尝试重新使规范与实现保持一致,并就相关议题重新与社区接触。

作为重新添加地址支持的一部分,本规范现在引用 Contact Picker API 中定义的地址组件,而不是自行定义这些组件。事实上,Contact Picker API 正是衍生自 Payment Request API 中的原始定义,并因地址在支付之外的 Web 场景中同样有用而从本规范中抽离出来。

工作组计划在将规范推进到“建议推荐标准”(Proposed Recommendation)状态之前,进行讨论并遵循常规的审查流程。

工作组将通过制作一份 实现报告 来展示实现经验。该报告将显示两个或多个独立实现通过 测试套件 中的每一项强制测试(即,每一项测试对应规范中的一项 必须 (MUST) 要求)。

本文档由 Web 支付工作组 作为候选推荐标准草案,按照 推荐标准轨道 发布。

作为候选推荐标准发布并不意味着得到 W3C 及其成员的认可。候选推荐标准草案整合了来自先前候选推荐标准的更改,工作组打算将其包含在后续的候选推荐标准快照中。

本文件为草案,可能随时被其他文件更新、替换或废弃。将其作为非进展中的工作进行引用是不恰当的。对此未来推荐标准的更新可能会纳入 新特性

本文档由在 W3C 专利政策 下运作的组织编写。W3C 维护一份 与该组交付成果相关的公开专利披露列表;该页面还包含披露专利的说明。任何知晓某项专利包含 必要权利要求 (Essential Claim) 的个人,必须根据 W3C 专利政策第 6 节 披露该信息。

本文件受 2025 年 8 月 18 日 W3C 流程文档约束。

1. 简介

本节是非规范性的。

本规范描述了一个 API,允许 用户代理(例如浏览器)充当交易中三方之间的中介

支付方式定义了

可选的 附加数据类型
可选地,一个 IDL 类型,支付方式预期将其作为 PaymentMethodDatadata 成员接收。如果给定支付方式未指定,则不进行 IDL 转换,支付方式将以 JSON 格式接收 data
验证支付方式数据的步骤
算法步骤,规定了 支付方式 在转换为支付方式的 附加数据类型 后,如何验证 data 成员。如果给定支付方式未指定,则不进行验证。

如何为给定的 支付方式 完成支付请求的细节属于 支付处理器 (payment handler) 的实现细节,后者是一个处理支付请求的应用程序或服务。具体而言,支付处理器定义了

检查是否可以进行支付的步骤:
支付处理器如何确定其自身或用户是否潜在可以“进行支付”,同样属于支付处理器的实现细节。
响应支付请求的步骤:
返回商家用于处理或验证交易的对象或 字典 的步骤。此对象的结构对于每种 支付方式 都是特定的。
用户变更支付方式时的步骤 (可选)

描述如何处理用户更改支付方式或货币工具(例如,从借记卡更改为信用卡)的步骤,该更改导致 字典object 或 null。

此 API 还使网站能够利用标准的 JavaScript 库无法实现的高安全性支付方案(例如,令牌化和系统级认证)。这有可能降低商家的责任,并有助于保护敏感的用户信息。

1.1 目标与范围

以下内容不在本规范的范围内

2. 使用示例

本节是非规范性的。

为了使用此 API,开发人员需要提供并跟踪一些关键信息。这些信息位作为参数传递给 PaymentRequest 构造函数,并随后用于更新向用户显示的支付请求。具体而言,这些信息位是

一旦构建了 PaymentRequest,它就会通过 show() 方法呈现给最终用户。show() 返回一个 Promise,该 Promise 在用户确认支付请求后,解析为一个 PaymentResponse

2.1 声明多种支付方式

在构建新的 PaymentRequest 时,商家使用第一个参数 (methodData) 来列出用户可以支付的不同方式(例如,信用卡、Apple Pay、Google Pay 等)。更具体地说,methodData 序列包含 PaymentMethodData 字典,其中包含商家接受的 支付方式支付方式标识符 以及任何关联的 支付方式 特定数据(例如,支持哪些信用卡网络)。

示例 1:`methodData` 参数
const methodData = [
  {
    supportedMethods: "https://example.com/payitforward",
    data: {
      payItForwardField: "ABC",
    },
  },
  {
    supportedMethods: "https://example.com/bobpay",
    data: {
      merchantIdentifier: "XXXX",
      bobPaySpecificField: true,
    },
  },
];

2.2 描述支付内容

在构建新的 PaymentRequest 时,商家使用构造函数的第二个参数 (details) 来提供用户被要求完成的交易详情。这包括订单总额,以及可选的行项目,可以详细分解支付内容。

示例 2:`details` 参数
const details = {
  id: "super-store-order-123-12312",
  displayItems: [
    {
      label: "Sub-total",
      amount: { currency: "GBP", value: "55.00" },
    },
    {
      label: "Value-Added Tax (VAT)",
      amount: { currency: "GBP", value: "5.00" },
    },
  ],
  total: {
    label: "Total due",
    // The total is GBP£65.00 here because we need to
    // add shipping (below). The selected shipping
    // costs GBP£5.00.
    amount: { currency: "GBP", value: "65.00" },
  },
};

2.3 添加配送选项

这里我们展示了一个如何将两个配送选项添加到 details 的示例。

示例 3:添加配送选项
const shippingOptions = [
  {
    id: "standard",
    // Shipping by truck, 2 days
    label: "🚛  Envío por camión (2 dias)",
    amount: { currency: "EUR", value: "5.00" },
    selected: true,
  },
  {
    id: "drone",
    // Drone shipping, 2 hours
    label: "🚀 Drone Express (2 horas)",
    amount: { currency: "EUR", value: "25.00" }
  },
];
Object.assign(details, { shippingOptions });

2.4 对支付请求的条件性修改

这里我们展示如何为在特定网络上使用卡添加处理费。请注意,这需要重新计算总额。

示例 4:根据卡类型修改支付请求
// Certain cards incur a $3.00 processing fee.
const cardFee = {
  label: "Card processing fee",
  amount: { currency: "AUD", value: "3.00" },
};

// Modifiers apply when the user chooses to pay with
// a card.
const modifiers = [
  {
    additionalDisplayItems: [cardFee],
    supportedMethods: "https://example.com/cardpay",
    total: {
      label: "Total due",
      amount: { currency: "AUD", value: "68.00" },
    },
    data: {
      supportedNetworks: networks,
    },
  },
];
Object.assign(details, { modifiers });

2.5 请求最终用户的特定信息

某些金融交易要求用户提供特定信息,以便商家履行购买(例如,如果需要配送实物商品,则需要用户的配送地址)。为了请求此信息,商家可以向 PaymentRequest 构造函数传递第三个可选参数 (options),指示他们需要哪些信息。当支付请求显示时,用户代理将向最终用户请求此信息,并在用户接受支付请求时将其返回给商家。

示例 5:`options` 参数
const options = {
  requestPayerEmail: false,
  requestPayerName: true,
  requestPayerPhone: false,
  requestShipping: true,
}

2.6 构建 PaymentRequest

收集了所有必要的信息位后,我们现在可以构建一个 PaymentRequest,并请求浏览器将其呈现给用户

示例 6:构建 `PaymentRequest`
async function doPaymentRequest() {
  try {
    const request = new PaymentRequest(methodData, details, options);
    // See below for a detailed example of handling these events
    request.onshippingaddresschange = ev => ev.updateWith(details);
    request.onshippingoptionchange = ev => ev.updateWith(details);
    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();

2.7 处理事件并更新支付请求

在用户接受支付之前,站点有机会响应用户输入来更新支付请求。这可以包括例如提供额外的配送选项(或修改其成本)、移除无法配送到特定地址的商品等。

示例 7:注册事件处理器
const request = new PaymentRequest(methodData, details, options);
// Async update to details
request.onshippingaddresschange = ev => {
  ev.updateWith(checkShipping(request));
};
// Sync update to the total
request.onshippingoptionchange = ev => {
  // selected shipping option
  const { shippingOption } = request;
  const newTotal = {
    currency: "USD",
    label: "Total due",
    value: calculateNewTotal(shippingOption),
  };
  ev.updateWith({ total: newTotal });
};
async function checkShipping(request) {
  try {
    const { shippingAddress } = request;

    await ensureCanShipTo(shippingAddress);
    const { shippingOptions, total } = await calculateShipping(shippingAddress);

    return { shippingOptions, total };
  } catch (err) {
    // Shows error to user in the payment sheet.
    return { error: `Sorry! we can't ship to your address.` };
  }
}

2.8 精细化错误报告

开发人员可以使用 shippingAddressErrors 字典成员(PaymentDetailsUpdate 的成员)来指示 ContactAddress 的特定属性存在验证错误。shippingAddressErrors 成员是一个 AddressErrors 字典,其成员明确划定了 物理地址 的错误字段,同时提供有助于显示给最终用户的错误消息。

request.onshippingaddresschange = ev => {
  ev.updateWith(validateAddress(request.shippingAddress));
};
function validateAddress(shippingAddress) {
  const error = "Can't ship to this address.";
  const shippingAddressErrors = {
    city: "FarmVille is not a real place.",
    postalCode: "Unknown postal code for your country.",
  };
  // Empty shippingOptions implies that we can't ship
  // to this address.
  const shippingOptions = [];
  return { error, shippingAddressErrors, shippingOptions };
}

2.9 将支付响应 POST 回服务器

PaymentResponse 中的数据预期会被 POST 回服务器进行处理。为了尽可能简化此过程,PaymentResponse 可以使用 默认 toJSON 步骤 (即 .toJSON()) 将对象直接序列化为 JSON。这使得使用 Fetch 标准 将生成的 JSON POST 回服务器变得非常简单

示例 9:使用 `fetch()` 进行 POST
async function doPaymentRequest() {
  const payRequest = new PaymentRequest(methodData, details);
  const payResponse = await payRequest.show();
  let result = "";
  try {
    const httpResponse = await fetch("/process-payment", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: payResponse.toJSON(),
    });
    result = httpResponse.ok ? "success" : "fail";
  } catch (err) {
    console.error(err);
    result = "fail";
  }
  await payResponse.complete(result);
}
doPaymentRequest();

2.10 在跨域 iframe 中使用

为了指示允许跨域 iframe 调用支付请求 API,可以在 iframe 元素上指定 allow 属性以及 "payment" 关键字。

示例 10:在跨域 iframe 中使用支付请求 API
<iframe
  src="https://cross-origin.example"
  allow="payment">
</iframe>

如果 iframe 将在多个支持支付请求 API 的源之间导航,则可以将 allow 设置为 "payment *"权限策略 规范提供了更多详细信息和示例。

3. PaymentRequest 接口

WebIDL[SecureContext, Exposed=Window]
interface PaymentRequest : EventTarget {
  constructor(
    sequence<PaymentMethodData> methodData,
    PaymentDetailsInit details,
    optional PaymentOptions options = {}
  );
  [NewObject]
  Promise<PaymentResponse> show(optional Promise<PaymentDetailsUpdate> detailsPromise);
  [NewObject]
  Promise<undefined> abort();
  [NewObject]
  Promise<boolean> canMakePayment();

  readonly attribute DOMString id;
  readonly attribute ContactAddress? shippingAddress;
  readonly attribute DOMString? shippingOption;
  readonly attribute PaymentShippingType? shippingType;

  attribute EventHandler onshippingaddresschange;
  attribute EventHandler onshippingoptionchange;
  attribute EventHandler onpaymentmethodchange;
};

开发人员创建 PaymentRequest 以发起支付请求。这通常与用户启动支付流程相关联(例如,通过激活网站上的“购买”、“支付”或“结账”按钮,在互动游戏中选择“强化”,或在停车场的自助终端支付)。PaymentRequest 允许开发人员在用户提供输入时与 用户代理 交换信息(直至用户批准或拒绝支付请求)。

如果设置了 requestShipping 成员,则 shippingAddressshippingOptionshippingType 属性会在处理过程中被填充。

request支付相关浏览上下文 是该 PaymentRequest相关全局对象浏览上下文顶级浏览上下文。每个 支付相关浏览上下文 都有一个 支付请求正在显示 (payment request is showing) 布尔值,用于防止同时显示多个支付 UI。

支付请求正在显示 布尔值仅防止在单个浏览器标签页中显示多个支付 UI。然而,支付处理器 可以限制 用户代理 在所有浏览器窗口和标签页中仅显示一个支付 UI。其他支付处理器可能允许在不同的浏览器标签页中显示支付 UI。

3.1 构造函数

PaymentRequest 使用所提供的 PaymentMethodData methodData 序列构建,其中包括任何 支付方式 特定的 dataPaymentDetailsInit details 以及 PaymentOptions options

PaymentRequest(methodData, details, options) 构造函数 必须 (MUST) 按以下方式操作

  1. 如果 对象的 相关全局对象关联 Document获准使用 "payment" 权限,则 抛出 一个 "SecurityError" DOMException
  2. 建立请求的 id
    1. 如果 details.id 缺失,则向 details 添加一个 id 成员,并将其值设置为 UUID [RFC4122]。
  3. serializedMethodData 为一个空列表。
  4. 处理支付方式
    1. 如果 methodData 序列的长度为零,则 抛出 一个 TypeError,并可选择告知开发人员至少需要一种 支付方式
    2. seenPMIs 为一个空 集合
    3. 对于 methodData 中的每个 paymentMethod
      1. 使用 paymentMethod.supportedMethods 运行 验证支付方式标识符 的步骤。如果返回 false,则抛出 RangeError 异常。可选择告知开发人员支付方式标识符无效。
      2. pmi 为使用 基本 URL 解析器 解析 paymentMethod.supportedMethods 的结果
        1. 如果失败,将 pmi 设为 paymentMethod.supportedMethods
      3. 如果 seenPMIs 包含 pmi,则抛出 RangeError DOMException,并可选择告知开发人员此 支付方式标识符 是重复的。
      4. pmi 追加到 seenPMIs
      5. 如果 paymentMethoddata 成员缺失,设 serializedData 为 null。否则,设 serializedData 为将 paymentMethod.data 序列化 为 JSON 字符串的结果。重新抛出任何异常。
      6. 如果 serializedData 不为 null,且定义 paymentMethod.supportedMethods 的规范指定了一个 附加数据类型
        1. objectJSON 解析 serializedData 的结果。
        2. idl object 转换为 附加数据类型 的 IDL 值的结果。重新抛出任何异常。

        3. 运行定义 paymentMethod.supportedMethods 的规范中关于 object验证支付方式数据的步骤(如有)。重新抛出任何异常。

          这些步骤确保任何 IDL 类型转换和验证错误都能尽早被捕获。

      7. 将元组 (paymentMethod.supportedMethods, serializedData) 添加到 serializedMethodData
  5. 处理总额
    1. 检查并规范化总金额 details.total.amount。重新抛出任何异常。
  6. 如果 detailsdisplayItems 成员存在,则对于 details.displayItems 中的每个 item
    1. 检查并规范化金额 item.amount。重新抛出任何异常。
  7. selectedShippingOption 为 null。
  8. 如果 optionsrequestShipping 成员存在并设置为 true,则处理配送选项
    1. options 为一个空 sequence<PaymentShippingOption>。
    2. 如果 detailsshippingOptions 成员存在,则
      1. seenIDs 为一个空集合。
      2. 对于 details.shippingOptions 中的每个 option
        1. 检查并规范化金额 item.amount。重新抛出任何异常。
        2. 如果 seenIDs 包含 option.id,则抛出 TypeError。可选择告知开发人员配送选项 ID 必须唯一。
        3. 否则,将 option.id 追加到 seenIDs
        4. 如果 option.selected 为 true,则将 selectedShippingOption 设为 option.id
    3. details.shippingOptions 设为 options
  9. serializedModifierData 为一个空列表。
  10. 处理支付详情修饰符
    1. modifiers 为一个空 sequence<PaymentDetailsModifier>。
    2. 如果 detailsmodifiers 成员存在,则
      1. modifiers 设为 details.modifiers
      2. 对于 modifiers 中的每个 modifier
        1. 如果 modifiertotal 成员存在,则
          1. 检查并规范化总金额 modifier.total.amount。重新抛出任何异常。
        2. 如果 modifieradditionalDisplayItems 成员存在,则对于 modifier.additionalDisplayItems 中的每个 item
          1. 检查并规范化金额 item.amount。重新抛出任何异常。
        3. 如果 modifierdata 成员缺失,设 serializedData 为 null。否则,设 serializedData 为将 modifier.data 序列化 为 JSON 字符串的结果。重新抛出任何异常。
        4. 将元组 (modifier.supportedMethods, serializedData) 添加到 serializedModifierData
        5. 移除 modifierdata 成员(如果存在)。
    3. details.modifiers 设为 modifiers
  11. request 为一个新的 PaymentRequest
  12. request.[[handler]] 设为 null
  13. request.[[options]] 设为 options
  14. request.[[state]] 设为 "created"。
  15. request.[[updating]] 设为 false。
  16. request.[[details]] 设为 details
  17. request.[[serializedModifierData]] 设为 serializedModifierData
  18. request.[[serializedMethodData]] 设为 serializedMethodData
  19. request.[[response]] 设为 null。
  20. requestshippingOption 属性的值设为 selectedShippingOption
  21. request 上的 shippingAddress 属性的值设为 null。
  22. 如果 options.requestShipping 设置为 true,则将 request 上的 shippingType 属性的值设为 options.shippingType。否则,将其设为 null。
  23. 返回 request

3.2 id 属性

获取时,id 属性返回此 PaymentRequest[[details]].id

出于审计和核对目的,商家可以将每个交易的唯一标识符与 id 属性相关联。

3.3 show() 方法

当开发人员想要开始支付请求的用户交互时,调用 show() 方法。show() 方法返回一个 Promise,该 Promise 将在 用户接受支付请求 时解析。在 show() 方法返回后,将向用户呈现某种用户界面以促进支付请求。

每个支付处理器控制当多个浏览上下文同时调用 show() 方法时会发生什么。例如,一些支付处理器将允许在不同的浏览器标签页/窗口中显示多个支付 UI。其他支付处理器可能只允许整个用户代理显示一个支付 UI。

show(optional detailsPromise) 方法 必须 (MUST) 按以下方式操作

  1. request 对象。
  2. 如果 request相关全局对象 没有 瞬时激活,则用户代理 可以 (MAY)
    1. 返回 一个被拒绝的 promise,并带有 "SecurityError" DOMException

    这允许用户代理不需要用户激活,例如支持重定向流程,因为在重定向时可能不存在用户激活。有关安全考量,请参阅 19.9 用户激活要求

    另请参阅 issue #1022,关于在规范中提供更多指导的讨论,即用户代理何时应该或不应该要求用户激活以进行 show()

  3. 否则,消耗 相关全局对象 的用户激活。
  4. documentrequest相关全局对象关联 Document
  5. 如果 document完全活跃 (fully active),则返回 一个被拒绝的 promise,并带有 "InvalidStateError" DOMException
  6. 如果 document可见性状态 不为 "visible",则返回 一个被拒绝的 promise,并带有 "AbortError" DOMException
  7. 可选地,如果 用户代理 希望为了保护用户而禁止调用 show(),则返回一个被拒绝的 promise,并带有 "SecurityError" DOMException。例如,用户代理 可以限制页面调用 show() 的频率,如 19. 隐私与安全考量 所述。

  8. 如果 request.[[state]] 不为 "created",则返回 一个被拒绝的 promise,并带有 "InvalidStateError" DOMException
  9. 如果 用户代理支付请求正在显示 布尔值为 true,则
    1. request.[[state]] 设为 "closed"。
    2. 返回 一个被拒绝的 promise,并带有 "AbortError" DOMException
  10. request.[[state]] 设为 "interactive"。
  11. acceptPromise一个新 promise
  12. request.[[acceptPromise]] 设为 acceptPromise
  13. 可选地:

    1. 以 "AbortError" DOMException 拒绝 acceptPromise
    2. request.[[state]] 设为 "closed"。
    3. 返回 acceptPromise

    这允许 用户代理 根据其自行决定,表现得好像用户已立即 中止了支付请求。例如,在“隐私浏览”模式或类似模式下,用户代理可能会利用此步骤。

  14. request支付相关浏览上下文支付请求正在显示 布尔值设为 true。
  15. 返回 acceptPromise并行 执行剩余步骤。
  16. handlers 为一个空 列表
  17. 对于 request.[[serializedMethodData]] 中的每个 paymentMethod 元组
    1. identifierpaymentMethod 元组的第一个元素。
    2. dataJSON 解析 该元组第二个元素的结果。
    3. 如果定义 identifier 的规范指定了一个 附加数据类型,则 转换 data 为该类型的 IDL 值。否则,转换 dataobject
    4. 如果转换结果为 异常 error
      1. request.[[state]] 设为 "closed"。
      2. error 拒绝 acceptPromise
      3. request支付相关浏览上下文支付请求正在显示 布尔值设为 false。
      4. 终止此算法。
    5. registeredHandlers 为支付方式 identifier 的注册支付处理器的 列表
      :支付处理器注册
    6. 对于 registeredHandlers 中的每个 handler
      1. canMakePayment 为运行 handler检查是否可以进行支付的步骤(传入 data)的结果。
      2. 如果 canMakePayment 为 true,则将 handler 追加到 handlers
  18. 如果 handlers 为空,则
    1. request.[[state]] 设为 "closed"。
    2. 以 "NotSupportedError" DOMException 拒绝 acceptPromise
    3. request支付相关浏览上下文支付请求正在显示 布尔值设为 false。
    4. 终止此算法。
  19. 呈现一个用户界面,允许用户与 handlers 进行交互。用户代理 应当 (SHOULD) 在呈现支付方式时优先考虑用户的偏好。用户界面 应当 (SHOULD) 使用与 document文档元素语言(如有)匹配的语言和基于本地的格式来呈现,如果该语言不可用,则使用适当的备用格式。

    :支付用户界面的本地化
  20. 如果传递了 detailsPromise,则
    1. 使用 detailsPromiserequest 和 null 运行 更新 PaymentRequest 详情算法
    2. 等待 detailsPromise 结算。

      基于 detailsPromise 的结算方式,更新 PaymentRequest 详情算法 决定支付 UI 的行为。即, detailsPromise 被拒绝时,支付请求中止。否则, detailsPromise 被履行时,用户代理重新启用支付请求 UI,支付流程可以继续。

  21. request.[[handler]] 设为最终用户选择的 支付处理器
  22. modifiers 为一个空列表。
  23. 对于 [[serializedModifierData]] 中的每个 tuple
    1. 如果 tuple 的第一个元素(一个 PMI)匹配 request.[[handler]]支付方式标识符,则将 tuple 的第二个元素(序列化的方式数据)追加到 modifiers
  24. 传递 转换后的 paymentMethod 元组中的第二个元素和 modifiers。可选地,用户代理 应当 (SHOULD)request 中的适当数据发送给用户选择的 支付处理器,以便引导用户完成支付流程。这包括 request 的各种属性和其他 内部槽位(出于隐私原因,某些 可以 (MAY) 被排除)。

    [[serializedModifierData]] 内部槽位 中多个适用修饰符的处理属于 支付处理器 特有,不在本规范范围内。尽管如此,建议 (RECOMMENDED) 支付处理器[[serializedModifierData]] 列表中的项使用“后者获胜 (last one wins)”的方法:也就是说,列表末尾的项总是优先于列表开头的任何项(参见下例)。

    acceptPromise 稍后将由 用户接受支付请求算法用户中止支付请求算法(通过用户界面交互触发),或 支付处理器指示内部错误算法 解析或拒绝。

    如果在显示用户界面时 document 停止 完全活跃,或者到达此步骤时不再是完全活跃状态,则

    1. 关闭用户界面。
    2. request.[[state]] 设为 "closed"。
    3. request支付相关浏览上下文支付请求正在显示 布尔值设为 false。
    4. 用户交互任务源 上排队一个任务,以 拒绝 acceptPromise,并带有 "AbortError" DOMException

3.4 abort() 方法

如果开发人员希望告诉 用户代理 中止支付 request 并撤销可能显示的任何用户界面,则调用 abort() 方法。abort() 只能在 show() 方法被调用后(参见 状态)且在此实例的 [[acceptPromise]] 被解析之前调用。例如,如果商家销售的商品仅在有限的时间内可用,开发人员可能会选择这样做。如果用户未在允许的时间内接受支付请求,则请求将被中止。

用户代理 可能并不总是能够中止请求。例如,如果 用户代理 已将请求的责任委托给另一个应用程序。在这种情况下,abort() 将拒绝返回的 Promise

另请参阅 用户中止支付请求 时的算法。

abort() 方法 必须 (MUST) 按以下方式操作

  1. request 对象。
  2. 如果 request.[[response]] 不为 null,且 request.[[response]].[[retryPromise]] 不为 null,则返回 一个被拒绝的 promise,并带有 "InvalidStateError" DOMException
  3. 如果 request.[[state]] 的值不是 "interactive"(交互中),则返回 一个被拒绝的 Promise,其拒绝理由为 "InvalidStateError" DOMException
  4. promise一个新 Promise
  5. 返回 promise并行执行剩余步骤。
  6. 尝试终止当前用户与支付处理程序的交互,并关闭任何剩余的用户界面。
  7. 用户交互任务源排队一个任务以执行以下步骤
    1. 如果无法终止当前用户交互,则以 "InvalidStateError" DOMException 拒绝 promise,并终止这些步骤。
    2. request.[[state]] 设置为 "closed"(已关闭)。
    3. 以 "AbortError" DOMException 拒绝 Promise request.[[acceptPromise]]
    4. 使用 undefined 解析 promise

3.5 canMakePayment() 方法

: canMakePayment()

开发者可以使用 canMakePayment() 方法来确定用户代理是否支持某种所需的支付方式。请参阅 19.8 canMakePayment() 保护措施

canMakePayment() 返回 true 并不意味着用户拥有已配置好并可供支付的工具。

canMakePayment() 方法必须运行可进行支付算法

3.6 shippingAddress 属性

PaymentRequestshippingAddress 属性在用户提供送货地址时被填充。它默认为 null。当用户提供送货地址时,会运行送货地址变更算法

3.7 shippingType 属性

PaymentRequestshippingType 属性是用于完成交易的送货类型。其值要么是一个 PaymentShippingType 枚举值,要么是在构造期间未由开发者提供时的 null(参见 PaymentOptionsshippingType 成员)。

3.8 onshippingaddresschange 属性

PaymentRequestonshippingaddresschange 属性是一个用于名为 shippingaddresschangePaymentRequestUpdateEvent 事件的 EventHandler

3.9 shippingOption 属性

PaymentRequestshippingOption 属性在用户选择送货选项时被填充。它默认为 null。当用户选择送货选项时,会运行送货选项变更算法

3.10 onshippingoptionchange 属性

PaymentRequestonshippingoptionchange 属性是一个用于名为 shippingoptionchangePaymentRequestUpdateEvent 事件的 EventHandler

3.11 onpaymentmethodchange 属性

PaymentRequestonpaymentmethodchange 属性是一个用于名为 "paymentmethodchange" 的 PaymentMethodChangeEvent 事件的 EventHandler

3.12 内部槽位 (Internal Slots)

PaymentRequest 的实例创建时带有下表中所示的内部槽位

内部槽 描述(非规范性
[[serializedMethodData]] 提供给构造函数的 methodData,但表示为包含所支持方式和用于数据的字符串或 null 的元组(而非原始对象形式)。
[[serializedModifierData]] 一个列表,包含 [[details]].modifier 序列中每个对应项目的每个 data 成员的序列化字符串形式,如果不存在此类成员则为 null。
[[details]] 支付请求当前使用的 PaymentDetailsBase,最初提供给构造函数,随后通过调用 updateWith() 进行更新。注意,modifiers 成员中包含的所有 PaymentDetailsModifier 实例的 data 成员都将被移除,因为它们改以序列化形式存储在 [[serializedModifierData]] 内部槽位中。
[[options]] 提供给构造函数的 PaymentOptions
[[state]]

支付请求的当前 状态,它从

"created"(已创建)
支付请求已构造,尚未呈现给用户。
"interactive"(交互中)
支付请求正在呈现给用户。
"closed"(已关闭)
支付请求已完成。

状态转换如下图所示

1 构造函数将初始状态设置为 "created"。 show() 方法将状态更改为 "interactive"。在此之后,abort() 方法或任何其他错误可以将状态发送至 "closed";同样,用户接受支付请求算法用户终止支付请求算法会将状态更改为 "closed"。
[[updating]] 如果存在待处理的 updateWith() 调用以更新支付请求则为 true,否则为 false。
[[acceptPromise]] show() 期间创建的待处理 Promise,如果用户接受支付请求,它将被解析。
[[response]] Null,或由该 PaymentRequest 实例化的 PaymentResponse
[[handler]] 与此 PaymentRequest 关联的支付处理程序。初始化为 null

4. PaymentMethodData 字典

WebIDLdictionary PaymentMethodData {
  required DOMString supportedMethods;
  object data;
};

PaymentMethodData 字典用于指示一组支持的支付方式,以及这些方式的任何关联的支付方式特定数据。

supportedMethods 成员
商家网站接受的支付方式支付方式标识符
data 成员
提供受支持支付方式可能需要的可选信息的对象。如果提供,它将被序列化

supportedMethods 的值已从数组改为字符串,但名称仍保持复数形式,以保持与 Web 上现有内容的兼容性。

5. PaymentCurrencyAmount 字典

WebIDLdictionary PaymentCurrencyAmount {
  required DOMString currency;
  required DOMString value;
};

PaymentCurrencyAmount 字典用于提供货币金额。

currency 成员

一个 [ISO4217] 格式规范的 3 字母字母代码(即不支持数字代码)。其标准形式为大写。然而,可获得本地化货币符号的货币代码组合集取决于具体实现。

在显示货币价值时,建议用户代理显示货币代码,但用户代理显示货币符号是可选的。这是因为由于在多种不同货币中使用,货币符号可能会产生歧义(例如,“$”可能指 USD、AUD、NZD、CAD 等)。

用户代理可以格式化显示 currency 成员以符合操作系统约定(例如,用于本地化目的)。

: 数字货币与 ISO 4217 货币代码

实现本规范的用户代理通过 ECMAScript 的 isWellFormedCurrencyCode 抽象操作强制执行 [ISO4217] 的 3 字母代码格式,该操作作为检查并规范化金额算法的一部分被调用。当代码不符合 [ISO4217] 定义的格式时,将抛出 RangeError

因此,当前的实现将允许使用不属于官方 [ISO4217] 列表(如 XBT、XRP 等)但格式规范的货币代码。如果提供的代码是浏览器知道如何显示的货币,则实现通常会在用户界面中显示适当的货币符号(例如,“USD”显示为 U+0024 美元符号 ($),“GBP”显示为 U+00A3 英镑符号 (£),“PLN”显示为 U+007A U+0142 兹罗提 (zł),非标准的“XBT”可以显示为 U+0243 带有横线的拉丁大写字母 B (Ƀ))。

ISO 正在努力处理数字货币,这可能会导致 [ISO4217] 注册表或全新的注册表进行更新。社区预期这将解决因使用非标准 3 字母代码而产生的歧义;例如,“BTC”是指比特币还是指未来不丹的货币?在发布之时,尚不清楚这种演变将采取何种形式,甚至不清楚完成这项工作的时间框架。W3C Web Payments 工作组正在与 ISO 联系,以便未来对本规范的修订能与相关的 ISO 注册表保持兼容。

value 成员
包含货币金额的有效十进制货币值
示例 12: 如何表示 1.234 阿曼里亚尔
{
   "currency": "OMR",
   "value": "1.234"
}

5.1 有效性检查器

如果 JavaScript 字符串按给定的顺序由以下码位组成,则它是一个 有效十进制货币值

  1. 可选地,一个 U+002D (-),用于指示金额为负。
  2. 一个或多个在 U+0030 (0) 到 U+0039 (9) 范围内的码位
  3. 可选地,一个 U+002E (.) 后跟一个或多个在 U+0030 (0) 到 U+0039 (9) 范围内的码位
以下正则表达式是上述定义的一种实现。
^-?[0-9]+(\.[0-9]+)?$

给定 PaymentCurrencyAmount amount,若要检查并规范化金额,请运行以下步骤

  1. 如果 IsWellFormedCurrencyCode(amount.currency) 的结果为 false,则抛出 RangeError 异常,并可选地通知开发者货币无效。
  2. 如果 amount.value 不是一个有效十进制货币值,则抛出 TypeError,并可选地通知开发者货币无效。
  3. amount.currency 设置为 ASCII 大写 amount.currency 的结果。

给定 PaymentCurrencyAmount amount,若要检查并规范化总金额,请运行以下步骤

  1. 检查并规范化金额 amount。重新抛出任何异常。
  2. 如果 amount.value 的第一个码位是 U+002D (-),则抛出 TypeError,并可选地通知开发者总金额不能为负数。
: 不修改值

6. 支付详情字典

6.1 PaymentDetailsBase 字典

WebIDLdictionary PaymentDetailsBase {
  sequence<PaymentItem> displayItems;
  sequence<PaymentShippingOption> shippingOptions;
  sequence<PaymentDetailsModifier> modifiers;
};
displayItems 成员
一系列 PaymentItem 字典,包含用户代理可以显示的支付请求行项目。
shippingOptions 成员

包含用户可选择的不同送货选项的序列。

如果序列中的某个项目将 selected 成员设置为 true,则这是默认使用的送货选项,并且 shippingOption 将设置为该选项的 id,而无需运行送货选项变更算法。如果序列中超过一个项目将 selected 设置为 true,则用户代理会选择序列中的最后一个。

shippingOptions 成员仅在 PaymentRequest 使用 PaymentOptions 构造且 requestShipping 设置为 true 时使用。

modifiers 成员
一系列包含特定支付方式标识符修改器的 PaymentDetailsModifier 字典。例如,它允许你根据支付方式调整总金额。

6.2 PaymentDetailsInit 字典

WebIDLdictionary PaymentDetailsInit : PaymentDetailsBase {
  DOMString id;
  required PaymentItem total;
};

除了从 PaymentDetailsBase 字典继承的成员外,以下成员也是 PaymentDetailsInit 字典的一部分

id 成员
此支付请求的自由格式标识符。
total 成员
一个包含支付请求非负总金额的 PaymentItem

6.3 PaymentDetailsUpdate 字典

WebIDLdictionary PaymentDetailsUpdate : PaymentDetailsBase {
  DOMString error;
  PaymentItem total;
  AddressErrors shippingAddressErrors;
  PayerErrors payerErrors;
  object paymentMethodErrors;
};

PaymentDetailsUpdate 字典用于使用 updateWith() 更新支付请求。

除了从 PaymentDetailsBase 字典继承的成员外,以下成员也是 PaymentDetailsUpdate 字典的一部分

error 成员
一个人可读的字符串,解释了为何无法将货物送达所选的送货地址,或没有送货选项可用的任何其他原因。当使用 updateWith() 更新支付请求时,PaymentDetailsUpdate 可在 error 成员中包含一条消息,如果 PaymentDetailsUpdate 指出不存在有效的 shippingOptions(且 PaymentRequest 在构造时将 requestShipping 选项设置为 true),则该消息将显示给用户。
total 成员
包含非负 amountPaymentItem

本规范中接受 PaymentDetailsUpdate 字典的算法,如果 total.amount.value 为负数,则会抛出异常。

shippingAddressErrors 成员
表示与潜在事件目标相关联的送货地址的验证错误。
payerErrors 成员
付款人详细信息相关的验证错误。
paymentMethodErrors 成员

支付方式特定错误。

7. PaymentDetailsModifier 字典

WebIDLdictionary PaymentDetailsModifier {
  required DOMString supportedMethods;
  PaymentItem total;
  sequence<PaymentItem> additionalDisplayItems;
  object data;
};

PaymentDetailsModifier 字典提供了基于支付方式标识符修改 PaymentDetailsBase 的详细信息。它包含以下成员

supportedMethods 成员
一个支付方式标识符PaymentDetailsModifier 的成员仅在用户选择此支付方式时应用。
total 成员
一个 PaymentItem 值,它会针对 supportedMethods 成员的支付方式标识符,覆盖 PaymentDetailsInit 字典中的 total 成员。
additionalDisplayItems 成员
一系列 PaymentItem 字典,提供附加的显示项目,这些项目会针对 supportedMethods 成员中的支付方式标识符,被追加到 PaymentDetailsBase 字典的 displayItems 成员中。此成员通常用于添加折扣或附加费行项目,表明用户代理可能显示的所选支付方式出现不同 total 金额的原因。

开发者有责任验证 total 金额是否为 displayItemsadditionalDisplayItems 的总和。

data 成员
提供受支持支付方式可能需要的可选信息的对象。如果提供,它将被序列化

8. PaymentShippingType 枚举

WebIDLenum PaymentShippingType {
  "shipping",
  "delivery",
  "pickup"
};
"shipping"(送货)
这是默认值,指代作为送货目的地收集的地址
"delivery"(递送)
指代作为递送目的地收集的地址。这通常比送货更快。例如,它可能用于食品配送。
"pickup"(取货)
指代作为服务取货一部分收集的地址。例如,这可能是洗衣取货的地址。

9. PaymentOptions 字典

WebIDLdictionary PaymentOptions {
  boolean requestPayerName = false;
  boolean requestBillingAddress = false;
  boolean requestPayerEmail = false;
  boolean requestPayerPhone = false;
  boolean requestShipping = false;
  PaymentShippingType shippingType = "shipping";
};

PaymentOptions 字典被传递给 PaymentRequest 构造函数,并提供有关支付请求所需选项的信息。

requestBillingAddress 成员
一个布尔值,指示用户代理应当收集并返回与支付方式相关联的账单地址(例如,与信用卡关联的账单地址)。通常,用户代理会将账单地址作为 PaymentMethodChangeEventmethodDetails 的一部分返回。商家可以使用此信息来计算某些司法管辖区的税费并更新显示的金额。有关隐私考虑,请参阅下文关于暴露用户信息的内容。
requestPayerName 成员
一个布尔值,指示用户代理应当收集并返回付款人姓名作为支付请求的一部分。例如,将其设置为 true 以允许商家以付款人名义进行预订。
requestPayerEmail 成员
一个布尔值,指示用户代理应当收集并返回付款人电子邮箱地址作为支付请求的一部分。例如,将其设置为 true 以允许商家发送电子收据。
requestPayerPhone 成员
一个布尔值,指示用户代理应当收集并返回付款人电话号码作为支付请求的一部分。例如,将其设置为 true 以允许商家致电客户咨询账单事宜。
requestShipping 成员
一个布尔值,指示用户代理应当收集并返回一个送货地址作为支付请求的一部分。例如,当商家需要向用户邮寄实体商品时,将其设置为 true。对于购买数字商品,则将其设置为 false。
shippingType 成员
一个 PaymentShippingType 枚举值。有些交易需要一个地址进行送货,但“shipping”一词并不合适。例如,“pizza delivery”(比萨配送)而非“pizza shipping”,以及“laundry pickup”(洗衣取货)而非“laundry shipping”。如果 requestShipping 设置为 true,则 shippingType 成员可以影响用户代理呈现收集送货地址的用户界面的方式。shippingType 成员仅影响支付请求的用户界面。

10. PaymentItem 字典

WebIDLdictionary PaymentItem {
  required DOMString label;
  required PaymentCurrencyAmount amount;
  boolean pending = false;
};

PaymentDetailsBase 字典中包含一个或多个 PaymentItem 字典的序列,用于指示支付请求的目的以及所要求的金额。

label 成员
项目的可读描述。用户代理可能会向用户显示此内容。
: 标签的国际化
amount 成员
一个包含该项目货币金额的 PaymentCurrencyAmount
pending 成员
一个布尔值。当设置为 true 时,意味着 amount 成员不是最终值。这通常用于显示取决于送货地址或送货选项选择的项目,例如运费或税额。用户代理可能会在支付请求的用户界面中指示待处理字段。

11. PaymentCompleteDetails 字典

WebIDLdictionary PaymentCompleteDetails {
  object? data = null;
};

PaymentCompleteDetails 字典在支付请求完成时,向支付处理程序提供来自商家网站的额外信息。

PaymentCompleteDetails 字典包含以下成员

data 成员
提供PaymentResponse 关联支付方式可能需要的可选信息的对象。如果提供,它将被序列化

12. PaymentComplete 枚举

WebIDLenum PaymentComplete {
  "fail",
  "success",
  "unknown"
};
"fail"(失败)
指示支付处理失败。用户代理可能显示指示失败的 UI。
"success"(成功)
指示支付已成功处理。用户代理可能显示指示成功的 UI。
"unknown"(未知)
开发者未指明成功或失败,用户代理不应当显示指示成功或失败的 UI。

13. PaymentShippingOption 字典

WebIDLdictionary PaymentShippingOption {
  required DOMString id;
  required DOMString label;
  required PaymentCurrencyAmount amount;
  boolean selected = false;
};

PaymentShippingOption 字典具有描述送货选项的成员。开发者可以通过在响应变更事件时调用 updateWith() 方法,向用户提供一个或多个送货选项。

id 成员
用于引用此 PaymentShippingOption 的字符串标识符。对于给定的 PaymentRequest,它必须是唯一的。
label 成员
该项目的可读字符串描述。用户代理应当使用此字符串向用户显示送货选项。
amount 成员
一个包含该项目货币金额的 PaymentCurrencyAmount
selected 成员
一个布尔值。当为 true 时,指示这是序列中默认选中的 PaymentShippingOption用户代理应当在用户界面中默认显示此选项。

14. PaymentResponse 接口

WebIDL[SecureContext, Exposed=Window]
interface PaymentResponse : EventTarget  {
  [Default] object toJSON();

  readonly attribute DOMString requestId;
  readonly attribute DOMString methodName;
  readonly attribute object details;
  readonly attribute ContactAddress? shippingAddress;
  readonly attribute DOMString? shippingOption;
  readonly attribute DOMString? payerName;
  readonly attribute DOMString? payerEmail;
  readonly attribute DOMString? payerPhone;

  [NewObject]
  Promise<undefined> complete(
    optional PaymentComplete result = "unknown",
    optional PaymentCompleteDetails details = {}
  );
  [NewObject]
  Promise<undefined> retry(optional PaymentValidationErrors errorFields = {});

  attribute EventHandler onpayerdetailchange;
};

当用户选择了支付方式并批准了支付请求时,会返回 PaymentResponse

14.1 retry() 方法

retry(errorFields) 方法必须按照以下方式执行

  1. responsethis
  2. requestresponse.[[request]]
  3. documentrequest相关全局对象关联 Document
  4. 如果 document 不处于完全活动状态,则返回一个被拒绝的 Promise,其拒绝理由为 "InvalidStateError" DOMException
  5. 如果 response.[[complete]] 为 true,返回一个被拒绝的 Promise,其拒绝理由为 "InvalidStateError" DOMException
  6. 如果 response.[[retryPromise]] 不为 null,返回一个被拒绝的 Promise,其拒绝理由为 "InvalidStateError" DOMException
  7. request.[[state]] 设置为 "interactive"(交互中)。
  8. retryPromise一个新 Promise
  9. response.[[retryPromise]] 设置为 retryPromise
  10. 如果传递了 errorFields
  11. 如果以下任何一项为 true,可选地在开发者控制台中显示警告
  12. request.[[options]].requestPayerName 为 false,且 errorFields.payer.name 存在。
  13. request.[[options]].requestPayerEmail 为 false,且 errorFields.payer.email 存在。
  14. request.[[options]].requestPayerPhone 为 false,且 errorFields.payer.phone 存在。
  15. request.[[options]].requestShipping 为 false,且 errorFields.shippingAddress 存在。
  • 如果传入了 errorFields.paymentMethod 成员,且定义 response.methodName 的规范有要求,则将 errorFieldspaymentMethod 成员转换为该规范所指定类型的 IDL 值。否则,转换为 object
  • request支付相关浏览上下文支付请求显示中布尔值设为 false。
  • 如果转换结果产生一个 异常 error
    1. 使用 error 拒绝 retryPromise
    2. 用户代理支付请求显示中布尔值设为 false。
    3. 返回。
  • 通过将 errorFields 的成员与用户代理 UI 中的输入字段匹配,向最终用户指出支付响应的数据存在问题。例如,用户代理可以在浏览器 UI 中引起用户对错误的 errorFields 的注意,并以有助于用户修复每个错误的方式显示字段值。同样,如果传递了 error 成员,则在用户代理 UI 中呈现该错误。如果成员的值为空字符串,用户代理可以替换为一个合适的错误信息值。
  • 否则,如果未传递 errorFields,则通知最终用户尝试重试支付。重新启用任何赋予最终用户重试接受支付请求能力的 UI 元素。
  • 如果在显示用户界面时 document 停止处于 完全激活 状态,或者在到达此步骤时已不再处于该状态,则
    1. 关闭用户界面。
    2. request.[[state]] 设为 "关闭"。
    3. request支付相关浏览上下文支付请求显示中布尔值设为 false。
    4. 用户交互任务源排队一个任务,以使用 "AbortError" DOMException 拒绝 retryPromise
  • 最后,当 retryPromise 敲定时,将 response.[[retryPromise]] 设为 null。
  • 返回 retryPromise
  • 14.1.1 PaymentValidationErrors 字典

    WebIDLdictionary PaymentValidationErrors {
      PayerErrors payer;
      AddressErrors shippingAddress;
      DOMString error;
      object paymentMethod;
    };
    payer 成员
    付款人详细信息相关的验证错误。
    shippingAddress 成员
    表示 PaymentResponseshippingAddress 出现的验证错误。
    error 成员
    对支付错误的通用描述,用户可以尝试从中恢复。例如,用户可以通过重试支付来恢复。开发者可以选择单独传递 error 成员来给出验证问题的通用概述,也可以结合 PaymentValidationErrors 字典的其他成员一起传递。
    : 错误的国际化
    paymentMethod 成员
    支付方式特定的错误。

    14.1.2 PayerErrors 字典

    WebIDLdictionary PayerErrors {
      DOMString email;
      DOMString name;
      DOMString phone;
    };

    PayerErrors 用于表示一个或多个付款人详细信息的验证错误。

    付款人详细信息是指付款人姓名、付款人电话号码和付款人电子邮件中的任意一项。

    email 成员
    表示付款人的电子邮件存在验证错误。在用户代理的 UI 中,此成员对应于提供 PaymentResponsepayerEmail 属性值的输入字段。
    name 成员
    表示付款人的姓名存在验证错误。在用户代理的 UI 中,此成员对应于提供 PaymentResponsepayerName 属性值的输入字段。
    phone 成员
    表示付款人的电话号码存在验证错误。在用户代理的 UI 中,此成员对应于提供 PaymentResponsepayerPhone 属性值的输入字段。

    14.2 methodName 属性

    用户为完成交易而选择的支付方式支付方式标识符

    14.3 details 属性

    支付方式生成的object字典,商户可以使用它来处理或验证交易(取决于支付方式)。

    14.4 shippingAddress 属性

    如果传递给 PaymentRequest 构造函数的 PaymentOptions 中的 requestShipping 成员被设置为 true,则 shippingAddress 将是用户选择的完整且最终的送货地址

    14.5 shippingOption 属性

    如果传递给 PaymentRequest 构造函数的 PaymentOptions 中的 requestShipping 成员被设置为 true,则 shippingOption 将是所选送货选项的 id 属性。

    14.6 payerName 属性

    如果传递给 PaymentRequest 构造函数的 PaymentOptions 中的 requestPayerName 成员被设置为 true,则 payerName 将是用户提供的姓名。

    14.7 payerEmail 属性

    如果传递给 PaymentRequest 构造函数的 PaymentOptions 中的 requestPayerEmail 成员被设置为 true,则 payerEmail 将是用户选择的电子邮件地址。

    14.8 payerPhone 属性

    如果传递给 PaymentRequest 构造函数的 PaymentOptions 中的 requestPayerPhone 成员被设置为 true,则 payerPhone 将是用户选择的电话号码。

    14.9 requestId 属性

    生成此支付响应的相应支付请求 id

    14.10 complete() 方法

    complete() 方法在用户接受支付请求且 [[acceptPromise]] 已解析后调用。调用 complete() 方法告知用户代理支付交互已结束(并应当导致任何剩余的用户界面被关闭)。

    支付请求被接受且 PaymentResponse 返回给调用者后,但在调用者调用 complete() 之前,支付请求用户界面保持挂起状态。此时,用户界面不应当提供取消命令,因为接受支付请求的结果已经返回。然而,如果出现问题且开发者从未调用 complete(),则用户界面会被阻塞。

    因此,实现可以为开发者调用 complete() 施加超时限制。如果超时,实现将表现得如同调用了不带参数的 complete() 一样。

    complete() 方法必须按以下方式执行

    1. responsethis
    2. 如果 response.[[complete]] 为 true,则返回一个 "InvalidStateError" DOMException 拒绝的 Promise
    3. 如果 response.[[retryPromise]] 不为 null,则返回一个 "InvalidStateError" DOMException 拒绝的 Promise
    4. promise一个新 Promise
    5. serializedData 为将 details.data 序列化为 JSON 字符串的结果。
    6. 如果序列化抛出异常,则返回一个该异常 拒绝的 Promise
    7. 如果定义 response.methodName 的规范有要求
      1. json 为调用 JSONparse() 方法并传入 serializedData 的结果。
      2. idl json 转换为定义 response.methodName 的规范所指定类型的 IDL 值的结果。
      3. 如果转换为 IDL 值抛出异常,则返回一个该异常 拒绝的 Promise
      4. 如果定义 response.methodName 的规范有要求,则验证 idl 的成员。如果成员的值无效,则返回一个 TypeError 拒绝的 Promise
        : 恢复的机会
    8. response.[[complete]] 设为 true。
    9. 返回 promise并行执行剩余步骤。
    10. 如果在显示用户界面时 document 停止 完全活跃,或者到达此步骤时不再是完全活跃状态,则
      1. 关闭用户界面。
      2. request支付相关浏览上下文支付请求显示中布尔值设为 false。
      3. 用户交互任务源排队一个任务,以使用 "AbortError" DOMException 拒绝 promise
    11. 否则
      1. 关闭任何剩余的用户界面。用户代理可以使用值 resultserializedData 来影响用户体验。
      2. request支付相关浏览上下文支付请求显示中布尔值设为 false。
      3. 使用 undefined 解析 promise

    14.11 onpayerdetailchange 属性

    允许开发者处理 "payerdetailchange" 事件。

    14.12 内部槽位

    PaymentResponse 的实例是使用下表中的内部槽位创建的

    内部槽 描述(非规范性
    [[complete]] 如果支付请求已完成(即调用了 complete(),或者发生了致命错误导致响应不再可用),则为 true,否则为 false。
    [[request]] 实例化此 PaymentResponsePaymentRequest 实例。
    [[retryPromise]] Null,或一个在用户接受支付请求时解析,或在用户终止支付请求时拒绝的 Promise

    15. 配送地址与账单地址

    PaymentRequest 接口允许商户出于送货和/或账单目的向用户请求物理地址送货地址账单地址都是物理地址

    15.1 AddressErrors 字典

    WebIDLdictionary AddressErrors {
      DOMString addressLine;
      DOMString city;
      DOMString country;
      DOMString dependentLocality;
      DOMString organization;
      DOMString phone;
      DOMString postalCode;
      DOMString recipient;
      DOMString region;
      DOMString sortingCode;
    };

    AddressErrors 字典的成员表示物理地址特定部分的验证错误。每个字典成员都有双重功能:首先,它的存在表示地址的特定部分出现验证错误。其次,字符串值允许开发者描述验证错误(以及最终用户可能如何修复该错误)。

    开发者需要注意,用户可能无法修复地址的某些部分。因此,他们需要注意不要要求用户修复他们可能无法控制的问题。

    addressLine 成员
    表示地址行存在验证错误。在用户代理的 UI 中,此成员对应于提供 ContactAddressaddressLine 属性值的输入字段。
    city 成员
    表示城市存在验证错误。在用户代理的 UI 中,此成员对应于提供 ContactAddresscity 属性值的输入字段。
    country 成员
    表示国家存在验证错误。在用户代理的 UI 中,此成员对应于提供 ContactAddresscountry 属性值的输入字段。
    dependentLocality 成员
    表示从属区域存在验证错误。在用户代理的 UI 中,此成员对应于提供 ContactAddressdependentLocality 属性值的输入字段。
    organization 成员
    表示组织存在验证错误。在用户代理的 UI 中,此成员对应于提供 ContactAddressorganization 属性值的输入字段。
    phone 成员
    表示电话号码存在验证错误。在用户代理的 UI 中,此成员对应于提供 ContactAddressphone 属性值的输入字段。
    postalCode 成员
    表示邮政编码存在验证错误。在用户代理的 UI 中,此成员对应于提供 ContactAddresspostalCode 属性值的输入字段。
    recipient 成员
    表示收件人存在验证错误。在用户代理的 UI 中,此成员对应于提供 ContactAddressaddressLine 属性值的输入字段。
    region 成员
    表示区域存在验证错误。在用户代理的 UI 中,此成员对应于提供 ContactAddressregion 属性值的输入字段。
    sortingCode 成员
    表示分拣代码存在验证错误。在用户代理的 UI 中,此成员对应于提供 ContactAddresssortingCode 属性值的输入字段。

    16. 权限策略 (Permissions Policy) 集成

    本规范定义了一个由字符串 "payment" 标识的策略控制功能 [permissions-policy]。其默认允许列表'self'

    17. 事件

    17.1 摘要

    本节是非规范性的。

    事件名称 Interface 分派于…… 目标
    shippingaddresschange PaymentRequestUpdateEvent 用户提供一个新的送货地址。 PaymentRequest
    shippingoptionchange PaymentRequestUpdateEvent 用户选择一个新的送货选项。 PaymentRequest
    payerdetailchange PaymentRequestUpdateEvent 用户更改付款人姓名、付款人电子邮件或付款人电话(参见付款人详细信息更改算法)。 PaymentResponse
    paymentmethodchange PaymentMethodChangeEvent 用户在支付处理程序内选择不同的支付方式 PaymentRequest

    17.2 PaymentMethodChangeEvent 接口

    WebIDL[SecureContext, Exposed=Window]
    interface PaymentMethodChangeEvent : PaymentRequestUpdateEvent {
      constructor(DOMString type, optional PaymentMethodChangeEventInit eventInitDict = {});
      readonly attribute DOMString methodName;
      readonly attribute object? methodDetails;
    };

    17.2.1 methodDetails 属性

    获取时,返回其初始化时的值。有关更多信息,请参见 PaymentMethodChangeEventInitmethodDetails 成员。

    17.2.2 methodName 属性

    获取时,返回其初始化时的值。有关更多信息,请参见 PaymentMethodChangeEventInitmethodName 成员。

    17.2.3 PaymentMethodChangeEventInit 字典

    WebIDLdictionary PaymentMethodChangeEventInit : PaymentRequestUpdateEventInit {
      DOMString methodName = "";
      object? methodDetails = null;
    };
    methodName 成员
    表示支付方式标识符的字符串。
    methodDetails 成员
    表示来自支付方式的某些数据的对象,或 null。

    17.3 PaymentRequestUpdateEvent 接口

    WebIDL[SecureContext, Exposed=Window]
    interface PaymentRequestUpdateEvent : Event {
      constructor(DOMString type, optional PaymentRequestUpdateEventInit eventInitDict = {});
      undefined updateWith(Promise<PaymentDetailsUpdate> detailsPromise);
    };

    PaymentRequestUpdateEvent 使开发者能够响应用户交互来更新支付请求的详细信息。

    17.3.1 构造函数

    PaymentRequestUpdateEvent构造函数(type, eventInitDict) 必须按以下方式执行

    1. event 为使用 typeeventInitDict 调用 PaymentRequestUpdateEvent构造函数的结果。
    2. event.[[waitForUpdate]] 设为 false。
    3. 返回 event

    17.3.2 updateWith() 方法

    detailsPromiseupdateWith() 方法必须按以下方式执行

    1. eventthis
    2. 如果 eventisTrusted 属性为 false,则抛出一个 "InvalidStateError" DOMException
    3. 如果 event.[[waitForUpdate]] 为 true,则抛出一个 "InvalidStateError" DOMException
    4. 如果 event目标PaymentResponse 的实例,令 requestevent目标[[request]]
    5. 否则,令 requestevent目标 的值。
    6. 断言: requestPaymentRequest 的实例。
    7. 如果 request.[[state]] 不为 "交互中",则抛出一个 "InvalidStateError" DOMException
    8. 如果 request.[[updating]] 为 true,则抛出一个 "InvalidStateError" DOMException
    9. 设置 event停止传播标志立即停止传播标志
    10. event.[[waitForUpdate]] 设为 true。
    11. pmi 为 null。
    12. 如果 eventmethodName 属性,则将 pmi 设为 methodName 属性的值。
    13. 使用 detailsPromiserequestpmi 运行 更新 PaymentRequest 详细信息算法

    17.3.3 内部槽位

    PaymentRequestUpdateEvent 的实例是使用下表中的内部槽位创建的

    内部槽 描述(非规范性
    [[waitForUpdate]] 一个布尔值,指示 updateWith() 发起的更新当前是否正在进行中。

    17.3.4 PaymentRequestUpdateEventInit 字典

    WebIDLdictionary PaymentRequestUpdateEventInit : EventInit {};

    18. 算法

    PaymentRequest 对象的 内部槽位 [[state]] 被设为 "交互中" 时,用户代理将根据用户交互触发以下算法。

    18.1 可支付算法

    可进行支付算法 检查用户代理是否支持使用构造 PaymentRequest 时所使用的支付方式进行支付。

    1. request 为在其上调用该方法的 PaymentRequest 对象。
    2. 如果 request.[[state]] 不为 "已创建",则返回一个 "InvalidStateError" DOMException 拒绝的 Promise
    3. documentrequest相关全局对象关联 Document
    4. 如果 document完全活跃 (fully active),则返回 一个被拒绝的 promise,并带有 "InvalidStateError" DOMException
    5. 可选地,由顶级浏览上下文自行决定,返回一个 "NotAllowedError" DOMException 拒绝的 Promise

      这允许用户代理应用启发式方法来检测并防止滥用调用该方法进行指纹识别,例如创建具有各种支持的支付方式PaymentRequest 对象,并依次在它们上触发可进行支付算法。例如,用户代理可以根据顶级浏览上下文或进行这些调用的时间段来限制可以进行的成功调用次数。

    6. hasHandlerPromise一个新 Promise
    7. 返回 hasHandlerPromise,并并行执行其余步骤。
    8. 对于 request.[[serializedMethodData]] 中的每个 paymentMethod 元组
    9. identifierpaymentMethod 元组的第一个元素。
    10. 如果用户代理有一个支持处理 identifier 支付请求的支付处理程序,则用 true 解析 hasHandlerPromise 并终止此算法。
  • 用 false 解析 hasHandlerPromise
  • 18.2 配送地址变更算法

    送货地址更改算法 在用户提供新的送货地址时运行。它 必须运行以下步骤

    1. request 为用户正在交互的 PaymentRequest 对象。
    2. 用户交互任务源排队一个任务以运行以下步骤
    3. : 收件人信息的隐私

      redactList 限制了 API 与商户共享的关于收件人的个人信息量。

      对于商户而言,由此产生的 ContactAddress 对象提供了足够的信息来(例如)计算运费,但在大多数情况下,不足以在物理上定位和唯一识别收件人。

      不幸的是,即使有了 redactList,收件人的匿名性也无法保证。这是因为在一些国家,邮政编码的粒度非常细,以至于它们可以唯一识别收件人。

    4. redactList 为空列表。将 redactList 设为 « "organization", "phone", "recipient", "addressLine" »。
    5. address 为运行通过用户提供的输入创建 contactaddress 步骤(传入 redactList)的结果。
    6. request.shippingAddress 设为 address
    7. 使用 request 和 "shippingaddresschange" 运行 PaymentRequest 更新算法

    18.3 配送选项变更算法

    送货选项更改算法 在用户选择新的送货选项时运行。它 必须运行以下步骤

    1. request 为用户正在交互的 PaymentRequest 对象。
    2. 用户交互任务源排队一个任务以运行以下步骤
    3. request 上的 shippingOption 属性设为用户提供的 PaymentShippingOptionid 字符串。
    4. 使用 request 和 "shippingoptionchange" 运行 PaymentRequest 更新算法

    18.4 支付方式变更算法

    当用户更改支付方式时,支付处理程序可以运行支付方式更改算法,并传入 methodDetails(其为一个字典object 或 null)和一个 methodName(其为一个表示用户正在与之交互的支付处理程序支付方式标识符的 DOMString)。

    : paymentmethodchange 事件共享信息的隐私

    当用户选择或更改支付方式(例如信用卡)时,PaymentMethodChangeEvent 包含为了进行税务计算而脱敏的账单地址信息。脱敏属性包括但不限于地址行从属区域组织电话号码收件人

    1. request 为用户正在交互的 PaymentRequest 对象。
    2. 用户交互任务源排队一个任务以运行以下步骤
    3. 断言: request.[[updating]] 为 false。一次只能进行一个更新。
    4. 断言: request.[[state]] 为 "交互中"。
    5. request触发一个事件,命名为 "paymentmethodchange",使用 PaymentMethodChangeEvent,其 methodName 属性初始化为 methodName,其 methodDetails 属性初始化为 methodDetails

    18.5 PaymentRequest 更新算法

    PaymentRequest 更新算法由上述其他算法运行,以触发事件来指示用户已对名为 requestPaymentRequest 进行了更改,且事件名为 name

    1. 断言: request.[[updating]] 为 false。一次只能进行一个更新。
    2. 断言: request.[[state]] 为 "交互中"。
    3. event 为使用 PaymentRequestUpdateEvent 接口创建事件的结果。
    4. eventtype 属性初始化为 name
    5. request分发 event
    6. 如果 event.[[waitForUpdate]] 为 true,则禁用任何可能导致触发另一个更新事件的用户界面部分。
    7. 否则,将 event.[[waitForUpdate]] 设为 true。

    18.6 支付人详情变更算法

    当用户在用户界面中更改 付款人姓名付款人电子邮件付款人电话 时,用户代理 必须 运行 付款人详细信息更改算法

    1. request 为用户正在交互的 PaymentRequest 对象。
    2. 如果 request.[[response]] 为 null,则返回。
    3. responserequest.[[response]]
    4. 用户交互任务源排队一个任务以运行以下步骤
    5. 断言request.[[updating]] 为 false。
    6. 断言request.[[state]] 为 "交互中"。
    7. optionsrequest.[[options]]
    8. 如果 付款人姓名 发生变化且 options.requestPayerName 为 true
      1. response.payerName 属性设置为 付款人姓名
    9. 如果 付款人电子邮件 发生变化且 options.requestPayerEmail 为 true
      1. response.payerEmail 设置为 付款人电子邮件
    10. 如果 付款人电话 发生变化且 options.requestPayerPhone 为 true
      1. response.payerPhone 设置为 付款人电话
    11. event 为使用 PaymentRequestUpdateEvent 创建事件 的结果。
    12. eventtype 属性初始化为 "payerdetailchange"。
    13. response分发 event
    14. 如果 event.[[waitForUpdate]] 为 true,则禁用用户界面中任何可能导致再次触发付款人详细信息更改的部分。
    15. 否则,将 event.[[waitForUpdate]] 设置为 true。

    18.7 用户接受支付请求算法

    用户接受付款请求算法 在用户接受付款请求并确认想要支付时运行。它 必须用户交互任务源排队一个任务 来执行以下步骤。

    1. request 为用户正在交互的 PaymentRequest 对象。
    2. 如果 request.[[updating]] 为 true,则终止此算法且不采取进一步操作。用户代理 用户界面 应该 确保这种情况永远不会发生。
    3. 如果 request.[[state]] 不为 "交互中",则终止此算法且不采取进一步操作。用户代理 用户界面 应该 确保这种情况永远不会发生。
    4. 如果 request.[[options]]requestShipping 值为 true,且 requestshippingAddress 属性为 null,或者 requestshippingOption 属性为 null,则终止此算法且不采取进一步操作。用户代理 应该 确保这种情况永远不会发生。
    5. request.[[response]] 不为 null,则令 isRetry 为 true,否则为 false。
    6. isRetry 为 true,令 responserequest.[[response]];否则令其为一个新的 PaymentResponse
    7. isRetry 为 false,初始化新创建的 response
      1. response.[[request]] 设置为 request
      2. response.[[retryPromise]] 设置为 null。
      3. response.[[complete]] 设置为 false。
      4. responserequestId 属性值设置为 request.[[details]].id 的值。
      5. request.[[response]] 设置为 response
    8. handlerrequest.[[handler]]
    9. responsemethodName 属性值设置为 handler支付方式标识符
    10. responsedetails 属性值设置为运行 handler响应付款请求的步骤 后得到的对象。
    11. request.[[options]]requestShipping 值为 false,则将 responseshippingAddress 属性值设置为 null。否则,
    12. shippingAddress从用户提供的输入创建 ContactAddress 的结果。
    13. responseshippingAddress 属性值设置为 shippingAddress
    14. requestshippingAddress 属性值设置为 shippingAddress
  • request.[[options]]requestShipping 值为 true,则将 responseshippingOption 属性设置为 requestshippingOption 属性值。否则,将其设置为 null。
  • request.[[options]]requestPayerName 值为 true,则将 responsepayerName 属性设置为用户提供的付款人姓名,若未提供则设为 null。否则,将其设置为 null。
  • request.[[options]]requestPayerEmail 值为 true,则将 responsepayerEmail 属性设置为用户提供的付款人电子邮件地址,若未提供则设为 null。否则,将其设置为 null。
  • request.[[options]]requestPayerPhone 值为 true,则将 responsepayerPhone 属性设置为用户提供的付款人电话号码,若未提供则设为 null。在设置 payerPhone 值时,用户代理 应该 将电话号码格式化为符合 [E.164] 标准。
  • request.[[state]] 设置为 "已关闭"。
  • isRetry 为 true,则用 undefined 解析 response.[[retryPromise]]。否则,用 response 解析 request.[[acceptPromise]]
  • 18.8 用户中止支付请求算法

    用户中止付款请求算法 在用户通过当前交互式用户界面中止付款请求时运行。它 必须用户交互任务源排队一个任务 来执行以下步骤。

    1. request 为用户正在交互的 PaymentRequest 对象。
    2. request.[[state]] 不为 "交互中",则终止此算法且不采取进一步操作。用户代理 用户界面 应该 确保这种情况永远不会发生。
    3. request.[[state]] 设置为 "已关闭"。
    4. request与支付相关的浏览上下文付款请求显示中 布尔值设置为 false。
    5. error 为一个 "AbortError" DOMException
    6. responserequest.[[response]]
    7. response 不为 null
    8. response.[[complete]] 设置为 true。
    9. 断言response.[[retryPromise]] 不为 null。
    10. error 拒绝 response.[[retryPromise]]
  • 否则,用 error 拒绝 request.[[acceptPromise]]
  • 中止当前的用户交互并关闭所有剩余的用户界面。
  • 18.9 支付处理器指示内部错误算法

    付款处理程序指示内部错误算法 在用户选择的 付款处理程序 遇到阻止其完成支付的内部错误时运行。发生此情况的原因包括操作系统终止了付款处理程序(例如,由于内存压力),或付款处理程序自身遇到了不可恢复的错误。

    1. 用户交互任务源排队一个任务以执行以下步骤
      1. request 为用户正在交互的 PaymentRequest 对象。
      2. request.[[state]] 不为 "交互中",则终止此算法且不采取进一步操作。
      3. error 为一个 "OperationError" DOMException
      4. request.[[state]] 设置为 "已关闭"。
      5. request与支付相关的浏览上下文付款请求显示中 布尔值设置为 false。
      6. responserequest.[[response]]
      7. response 不为 null
      8. response.[[complete]] 设置为 true。
      9. 断言response.[[retryPromise]] 不为 null。
      10. error 拒绝 response.[[retryPromise]]
    2. 否则,用 error 拒绝 request.[[acceptPromise]]
    3. 可选地,向用户显示一条通用错误消息,表明无法完成付款。
    4. 可选地,将详细错误信息记录到开发者控制台以进行调试。
    5. 中止当前的用户交互并关闭所有剩余的用户界面。

    "OperationError" 类型允许商户将付款处理程序错误与用户取消操作(使用 "AbortError")区分开来。

    18.10 更新 PaymentRequest 详情算法

    更新 PaymentRequest 详细信息算法 接收一个 PaymentDetailsUpdate detailsPromise、一个 PaymentRequest request,以及一个 pmi(DOMString 或 null,即 支付方式标识符)。这些步骤取决于 detailsPromise 的状态。如果 detailsPromise 永远不结算,则付款请求会被阻塞。用户代理 应该 提供用户中止付款请求的方法。实现 可以 选择为待处理的更新实现超时,如果 detailsPromise 在合理的时间内未结算。

    在发生超时、用户手动中止,或 付款处理程序 决定中止此特定支付的情况下,用户代理 必须 运行 用户中止付款请求算法

    1. request.[[updating]] 设置为 true。
    2. 并行地,禁用允许用户接受付款请求的用户界面。这是为了确保在用户界面更新了任何新详细信息之前,不会接受付款。
    3. 在拒绝 detailsPromise
    4. request 和一个 "AbortError" DOMException 中止更新
  • 在履行 detailsPromise 并返回值 value
  • details转换 valuePaymentDetailsUpdate 字典的结果。如果这 抛出 异常,则用 request 和抛出的异常 中止更新
  • serializedModifierData 为一个空列表。
  • selectedShippingOption 为 null。
  • shippingOptions 为一个空的 序列<PaymentShippingOption>。
  • 验证并规范化这些详细信息。
  • detailstotal 成员存在,则
  • 检查并规范化总金额 details.total.amount。如果抛出异常,则用 request 和该异常 中止更新
  • detailsdisplayItems 成员存在,则对于 details.displayItems 中的每个 item
  • 检查并规范化金额 item.amount。如果抛出异常,则用 request 和该异常 中止更新
  • detailsshippingOptions 成员存在,且 request.[[options]].requestShipping 为 true,则
  • seenIDs 为一个空集合。
  • 对于 details.shippingOptions 中的每个 option
  • 检查并规范化金额 option.amount。如果抛出异常,则用 request 和该异常 中止更新
  • seenIDs[option.{{PaymentShippingOption/id}}] 存在,则用 request 和一个 TypeError 中止更新
  • option.id 追加到 seenIDs
  • option 追加到 shippingOptions
  • option.selected 为 true,则将 selectedShippingOption 设置为 option.id
  • detailsmodifiers 成员存在,则
  • modifiers 为序列 details.modifiers
  • serializedModifierData 为一个空列表。
  • 对于 modifiers 中的每个 PaymentDetailsModifier modifier
  • 运行 验证支付方式标识符 的步骤,针对 modifier.supportedMethods。若返回 false,则用 request 和一个 RangeError 异常 中止更新。可选地,告知开发者该支付方式标识符无效。
  • modifiertotal 成员存在,则
  • 检查并规范化总金额 modifier.total.amount。如果抛出异常,则用 request 和该异常 中止更新
  • modifieradditionalDisplayItems 成员存在,则对于 modifier.additionalDisplayItems 中的每个 PaymentItem item
  • 检查并规范化金额 item.amount。如果抛出异常,则用 request 和该异常 中止更新
  • modifierdata 成员缺失,令 serializedData 为 null。否则,令 serializedData 为将 modifier.data 序列化 为 JSON 字符串的结果。如果抛出异常,则用 request 和该异常 中止更新
  • serializedData 添加到 serializedModifierData
  • 移除 modifierdata 成员(如果存在)。
  • paymentMethodErrors 成员存在且 identifier 不为 null
  • 若定义 pmi 的规范要求,则将 paymentMethodErrors 转换为 IDL 值。
  • 若转换导致 异常 error,则用 error 中止更新
  • 付款处理程序 应该paymentMethodErrors 的每个相关错误字段显示错误。
  • 使用新详细信息更新 PaymentRequest
  • detailstotal 成员存在,则
  • request.[[details]].total 设置为 details.total
  • detailsdisplayItems 成员存在,则
  • request.[[details]].displayItems 设置为 details.displayItems
  • detailsshippingOptions 成员存在,且 request.[[options]].requestShipping 为 true,则
  • request.[[details]].shippingOptions 设置为 shippingOptions
  • requestshippingOption 属性值设置为 selectedShippingOption
  • detailsmodifiers 成员存在,则
  • request.[[details]].modifiers 设置为 details.modifiers
  • request.[[serializedModifierData]] 设置为 serializedModifierData
  • request.[[options]].requestShipping 为 true,且 request.[[details]].shippingOptions 为空,则表明开发者已表示当前选择的送货地址(由 requestshippingAddress 提供)没有有效的送货选项。

    在这种情况下,用户代理 应该 显示指示此情况的错误,并 可以 指出当前选择的送货地址在某种程度上无效。用户代理 应该 使用 detailserror 成员(如果存在),提供有关该地址为何没有有效送货选项的更多信息。

    此外,若 details["shippingAddressErrors"] 成员存在,用户代理 应该 为送货地址的每个错误字段专门显示错误。这是通过将 AddressErrors 的每个现有成员与显示的用户界面中对应的输入字段进行匹配来实现的。

    类似地,若 details["payerErrors"] 成员存在,且 request.[[options]]requestPayerNamerequestPayerEmailrequestPayerPhone 为 true,则为每个错误字段专门显示错误。

    同样,若 details.paymentMethodErrors 存在,则为特定支付方式的每个错误输入字段专门显示错误。

  • request.[[updating]] 设置为 false。
  • 根据 request 中的任何已更改值更新用户界面。重新启用在运行此算法之前禁用的用户界面元素。

    18.10.1 中止更新

    对于 PaymentRequest request异常 exception中止更新 如下

    1. 可选地,通过控制台告知开发者在更新付款请求时发生了错误。
    2. 中止当前的用户交互并关闭所有剩余的用户界面。
    3. 用户交互任务源排队一个任务以执行以下步骤
      1. request与支付相关的浏览上下文付款请求显示中 布尔值设置为 false。
      2. request.[[state]] 设置为 "已关闭"。
      3. responserequest.[[response]]
      4. response 不为 null,则
      5. response.[[complete]] 设置为 true。
      6. 断言response.[[retryPromise]] 不为 null。
      7. exception 拒绝 response.[[retryPromise]]
    4. 否则,用 exception 拒绝 request.[[acceptPromise]]
    5. request.[[updating]] 设置为 false。
  • 中止算法。
  • 中止更新 在更新付款请求出现致命错误时运行,例如提供的 detailsPromise 被拒绝,或其履行值包含无效数据。这可能会使付款请求处于不一致的状态,因为开发者尚未成功处理更改事件。

    因此,PaymentRequest 会进入 "已关闭" 状态。错误通过 [[acceptPromise]] 的拒绝向开发者发出信号,即 show() 返回的 Promise。

    类似地,在 retry() 期间发生的 中止更新 会导致 [[retryPromise]] 被拒绝,并且相应的 PaymentResponse[[complete]] 内部槽 将被设置为 true(即它不再能被使用)。

    19. 隐私与安全考量

    19.1 使用 show() 方法时的用户保护

    本节是非规范性的。

    为了帮助确保用户不会无意中与来源共享敏感凭据,此 API 要求在相关 Window 具有 瞬态激活(例如通过点击或按下)时调用 PaymentRequest 的 show() 方法。

    为避免混乱的用户体验,本规范通过 show() 方法将用户代理限制为一次仅显示一个。此外,用户代理可以限制页面调用 show() 的速率。

    19.2 安全上下文

    本节是非规范性的。

    本规范中定义的 API 仅在 安全上下文 中公开 - 有关更多详细信息,请参阅 Secure Contexts 规范。在实践中,这意味着此 API 仅可通过 HTTPS 使用。这是为了限制支付方式数据(如信用卡号)以明文形式发送的可能性。

    19.3 跨域支付请求

    本节是非规范性的。

    商户和其他收款方通常通过 iframe 将结账和其他电子商务活动委托给支付服务提供商。此 API 通过 [HTML] 的 allow 属性支持收款方授权的跨源 iframe。

    付款处理程序 可以访问托管 iframe 的来源以及 iframe 内容的来源(即 PaymentRequest 发起的地方)。

    19.4 数据字段加密

    本节是非规范性的。

    PaymentRequest API 不直接支持数据字段的加密。个别 支付方式 可以选择包含对加密数据的支持,但并非所有 支付方式 都强制要求支持此功能。

    19.5 用户代理如何匹配支付处理器

    本节是非规范性的。

    出于安全原因,用户代理可以限制将匹配(在 show()canMakePayment() 中)限制为与作为 URL 支付方式标识符来源 相同的 付款处理程序

    19.6 数据使用

    支付方式 所有者为收集用于支付方式的用户数据如何使用制定隐私政策。Payment Request API 明确期望数据将用于完成交易的目的,并且与此 API 关联的用户体验传达了该意图。收款方有责任确保任何数据使用符合支付方式政策。对于完成交易之外的任何允许用途,收款方应向用户明确传达该用途。

    19.7 暴露用户信息

    用户代理 不得 在未经用户同意的情况下与开发者共享有关用户的信息(例如 送货地址)。

    特别地,PaymentMethodDatadataPaymentResponsedetails 成员允许进行任意数据交换。鉴于现有支付方式使用的数据模型范围广泛,在本 API 中规定数据细节将限制其有用性。details 成员承载来自付款处理程序的数据,无论是基于 Web 的(根据 Web-based Payment Handler API 定义)还是专有的。用户代理 不得 支持付款处理程序,除非它们包含足够的获取用户同意的机制(例如了解交易各方以及展示共享数据意图的机制)。

    用户代理 不得 出于完成交易之外的任何目的共享 displayItems 成员或 additionalDisplayItems 成员的值。

    PaymentMethodChangeEvent 使收款方能够根据所选 支付方式 特有的信息更新显示的金额。例如,与所选 支付方式 关联的账单地址可能会影响税款计算(例如 VAT),理想情况下用户界面应在付款人完成交易之前准确显示金额。同时,理想情况下应在付款完成前尽可能少地共享信息。因此,当 支付方式 定义 用户更改支付方式时的步骤 时,通过 PaymentMethodChangeEventmethodDetails 属性共享的数据最小化非常重要。最小化共享数据的要求和方法可能因 支付方式 而异,可能包括

    在共享隐私敏感信息对用户而言可能不明显的情况下(例如,当 更改支付方式 时),建议 用户代理向用户准确告知正在与商户共享哪些信息。

    19.8 canMakePayment() 保护

    canMakePayment() 方法为不同的支付方式提供了功能检测。如果未来有大量的支付方式可用,它可能会成为一种指纹识别向量。用户代理应保护用户免受该方法的滥用。例如,用户代理可以通过以下方式减少用户指纹识别

    为了进行速率限制,用户代理可能会查看来自以下方面的重复调用

    这些速率限制技术旨在增加与重复调用相关的成本,无论是管理多个 可注册域名 的成本,还是打开多个窗口(标签页或弹出窗口)带来的用户体验摩擦。

    19.9 用户激活要求

    如果用户代理不需要用户激活作为 show() 方法的一部分,则应考虑一些额外的安全缓解措施。不要求用户激活会增加垃圾邮件和点击劫持攻击的风险,因为它允许在用户未事先与页面进行即时交互的情况下启动付款请求 UI。

    为了缓解垃圾邮件,用户代理可以决定在达到某个阈值后执行用户激活要求,例如在用户已经无需在当前页面上进行用户激活即被显示付款请求 UI 之后。为了缓解点击劫持攻击,用户代理可以在对话框显示后立即忽略点击的时间阈值。

    另一个相关的缓解措施存在于 show() 的第 6 步中,其中文档必须可见才能启动用户交互。

    20. 可访问性考量

    本节是非规范性的。

    对于 Payment Request API 的面向用户方面,实现通过表单控件和其他输入模态与平台辅助功能 API 集成。此外,为了提高金额、送货地址和联系信息的易理解性,实现会根据系统约定格式化数据。

    21. 依赖关系

    本规范依赖于其他若干基础规范。

    ECMAScript
    内部槽 一词定义在 [ECMASCRIPT] 中。

    22. 一致性

    除了标记为非规范性的章节外,本规范中的所有创作指南、图表、示例和注释均为非规范性内容。本规范中的其他所有内容均为规范性内容。

    本文档中的关键字 MAYMUSTMUST NOTOPTIONALRECOMMENDEDSHOULDSHOULD NOT 仅在以全大写形式出现时,应按照 BCP 14 [RFC2119] [RFC8174] 的描述进行解释。

    只有一类产品可以声称符合本规范:用户代理

    尽管本规范主要针对 Web 浏览器,但其他软件也可能以符合规范的方式实现本规范。

    用户代理 可以 以任何期望的方式实现本规范中给出的算法,只要最终结果与通过本规范的算法获得的结果无法区分即可。

    用户代理 可以 对原本不受限制的输入施加特定于实现的限制,例如为了防止拒绝服务攻击、防止内存耗尽或绕过特定于平台的限制。当输入超过特定于实现的限制时,用户代理 必须 抛出,或者在 Promise 的上下文中拒绝并返回一个 TypeError,并可选地告知开发者特定输入如何超过了特定于实现的限制。

    A. IDL 索引

    WebIDL[SecureContext, Exposed=Window]
    interface PaymentRequest : EventTarget {
      constructor(
        sequence<PaymentMethodData> methodData,
        PaymentDetailsInit details,
        optional PaymentOptions options = {}
      );
      [NewObject]
      Promise<PaymentResponse> show(optional Promise<PaymentDetailsUpdate> detailsPromise);
      [NewObject]
      Promise<undefined> abort();
      [NewObject]
      Promise<boolean> canMakePayment();
    
      readonly attribute DOMString id;
      readonly attribute ContactAddress? shippingAddress;
      readonly attribute DOMString? shippingOption;
      readonly attribute PaymentShippingType? shippingType;
    
      attribute EventHandler onshippingaddresschange;
      attribute EventHandler onshippingoptionchange;
      attribute EventHandler onpaymentmethodchange;
    };
    
    dictionary PaymentMethodData {
      required DOMString supportedMethods;
      object data;
    };
    
    dictionary PaymentCurrencyAmount {
      required DOMString currency;
      required DOMString value;
    };
    
    dictionary PaymentDetailsBase {
      sequence<PaymentItem> displayItems;
      sequence<PaymentShippingOption> shippingOptions;
      sequence<PaymentDetailsModifier> modifiers;
    };
    
    dictionary PaymentDetailsInit : PaymentDetailsBase {
      DOMString id;
      required PaymentItem total;
    };
    
    dictionary PaymentDetailsUpdate : PaymentDetailsBase {
      DOMString error;
      PaymentItem total;
      AddressErrors shippingAddressErrors;
      PayerErrors payerErrors;
      object paymentMethodErrors;
    };
    
    dictionary PaymentDetailsModifier {
      required DOMString supportedMethods;
      PaymentItem total;
      sequence<PaymentItem> additionalDisplayItems;
      object data;
    };
    
    enum PaymentShippingType {
      "shipping",
      "delivery",
      "pickup"
    };
    
    dictionary PaymentOptions {
      boolean requestPayerName = false;
      boolean requestBillingAddress = false;
      boolean requestPayerEmail = false;
      boolean requestPayerPhone = false;
      boolean requestShipping = false;
      PaymentShippingType shippingType = "shipping";
    };
    
    dictionary PaymentItem {
      required DOMString label;
      required PaymentCurrencyAmount amount;
      boolean pending = false;
    };
    
    dictionary PaymentCompleteDetails {
      object? data = null;
    };
    
    enum PaymentComplete {
      "fail",
      "success",
      "unknown"
    };
    
    dictionary PaymentShippingOption {
      required DOMString id;
      required DOMString label;
      required PaymentCurrencyAmount amount;
      boolean selected = false;
    };
    
    [SecureContext, Exposed=Window]
    interface PaymentResponse : EventTarget  {
      [Default] object toJSON();
    
      readonly attribute DOMString requestId;
      readonly attribute DOMString methodName;
      readonly attribute object details;
      readonly attribute ContactAddress? shippingAddress;
      readonly attribute DOMString? shippingOption;
      readonly attribute DOMString? payerName;
      readonly attribute DOMString? payerEmail;
      readonly attribute DOMString? payerPhone;
    
      [NewObject]
      Promise<undefined> complete(
        optional PaymentComplete result = "unknown",
        optional PaymentCompleteDetails details = {}
      );
      [NewObject]
      Promise<undefined> retry(optional PaymentValidationErrors errorFields = {});
    
      attribute EventHandler onpayerdetailchange;
    };
    
    dictionary PaymentValidationErrors {
      PayerErrors payer;
      AddressErrors shippingAddress;
      DOMString error;
      object paymentMethod;
    };
    
    dictionary PayerErrors {
      DOMString email;
      DOMString name;
      DOMString phone;
    };
    
    dictionary AddressErrors {
      DOMString addressLine;
      DOMString city;
      DOMString country;
      DOMString dependentLocality;
      DOMString organization;
      DOMString phone;
      DOMString postalCode;
      DOMString recipient;
      DOMString region;
      DOMString sortingCode;
    };
    
    [SecureContext, Exposed=Window]
    interface PaymentMethodChangeEvent : PaymentRequestUpdateEvent {
      constructor(DOMString type, optional PaymentMethodChangeEventInit eventInitDict = {});
      readonly attribute DOMString methodName;
      readonly attribute object? methodDetails;
    };
    
    dictionary PaymentMethodChangeEventInit : PaymentRequestUpdateEventInit {
      DOMString methodName = "";
      object? methodDetails = null;
    };
    
    [SecureContext, Exposed=Window]
    interface PaymentRequestUpdateEvent : Event {
      constructor(DOMString type, optional PaymentRequestUpdateEventInit eventInitDict = {});
      undefined updateWith(Promise<PaymentDetailsUpdate> detailsPromise);
    };
    
    dictionary PaymentRequestUpdateEventInit : EventInit {};

    B. 致谢

    本规范源自 Web 平台孵化器社区组 先前发布的一份报告。

    C. 更新日志

    D. 参考文献

    D.1 规范性参考文献

    [contact-picker]
    联系人选择器 API。Peter Beverloo。W3C。2024 年 7 月 8 日。W3C 工作草案。URL: https://w3org.cn/TR/contact-picker/
    [dom]
    DOM Standard. Anne van Kesteren. WHATWG. Living Standard. URL: https://dom.spec.whatwg.org/
    [E.164]
    国际公共电信编号计划。ITU-T。2010 年 11 月。建议书。URL: https://www.itu.int/rec/dologin_pub.asp?lang=e&id=T-REC-E.164-201011-I!!PDF-E&type=items
    [ecma-402]
    ECMAScript 国际化 API 规范. Ecma International. URL: https://tc39.es/ecma402/
    [ECMASCRIPT]
    ECMAScript 语言规范. Ecma International. URL: https://tc39.es/ecma262/multipage/
    [fetch]
    获取 (Fetch) 标准. Anne van Kesteren. WHATWG. 活标准. URL: https://fetch.spec.whatwg.org/
    [HTML]
    HTML 标准. Anne van Kesteren; Domenic Denicola; Dominic Farolino; Ian Hickson; Philip Jägenstedt; Simon Pieters. WHATWG. 活标准. URL: https://html.whatwg.cn/multipage/
    [infra]
    Infra Standard. Anne van Kesteren; Domenic Denicola. WHATWG. Living Standard. URL: https://infra.spec.whatwg.org/
    [ISO4217]
    货币代码 - ISO 4217。ISO。2015。国际标准。URL: http://www.iso.org/iso/home/standards/currency_codes.htm
    [payment-method-id]
    支付方式标识符。Marcos Caceres。W3C。2022 年 9 月 8 日。W3C 推荐标准。URL: https://w3org.cn/TR/payment-method-id/
    [permissions-policy]
    权限策略. Ian Clelland. W3C. 2025年10月6日. W3C 工作草案. URL: https://w3org.cn/TR/permissions-policy-1/
    [RFC2119]
    Key words for use in RFCs to Indicate Requirement Levels. S. Bradner. IETF. 1997年3月. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc2119
    [RFC4122]
    通用唯一标识符 (UUID) URN 命名空间. P. Leach; M. Mealling; R. Salz. IETF. 2005年7月. 提议标准. URL: https://www.rfc-editor.org/rfc/rfc4122
    [RFC8174]
    RFC 2119 关键词中大小写的歧义. B. Leiba. IETF. 2017年5月. 最佳当前实践. URL: https://www.rfc-editor.org/rfc/rfc8174
    [url]
    URL 标准. Anne van Kesteren. WHATWG. 活标准. URL: https://url.spec.whatwg.org/
    [web-based-payment-handler]
    基于 Web 的支付处理程序 API。Ian Jacobs; Stephen McGruer; Jinho Bang。W3C。2026 年 2 月 18 日。W3C 工作草案。URL: https://w3org.cn/TR/web-based-payment-handler/
    [WEBIDL]
    Web IDL Standard. Edgar Chen; Timothy Gu. WHATWG. Living Standard. URL: https://webidl.spec.whatwg.org/

    D.2 资料性参考文献

    [rfc6454]
    Web 源概念。A. Barth。IETF。2011 年 12 月。提议标准。URL: https://www.rfc-editor.org/rfc/rfc6454
    [secure-contexts]
    安全上下文。Mike West。W3C。2023 年 11 月 10 日。CRD。网址:https://w3org.cn/TR/secure-contexts/