CyberLibrarian

【注意】 このドキュメントは、W3CのPayment Request API W3C Recommendation 08 September 2022の和訳です。
このドキュメントの正式版はW3Cのサイト上にある英語版であり、このドキュメントには翻訳に起因する誤りがありえます。誤訳、誤植などのご指摘は、訳者までお願い致します。

First Update: 2023年12月24日


決済リクエストAPI

W3C勧告

このドキュメントの詳細
本バージョン:
https://www.w3.org/TR/2022/REC-payment-request-20220908/
最新公開バージョン:
https://www.w3.org/TR/payment-request/
最新編集者草案:
https://w3c.github.io/payment-request/
履歴:
https://www.w3.org/standards/history/payment-request
Commit history
テスト・スイート:
https://wpt.live/payment-request/
実装報告書:
https://w3c.github.io/test-results/payment-request/all.html
編集者:
Marcos Caceres (Apple Inc.)
Rouslan Solomakhin (Google)
Ian Jacobs (W3C)
旧編集者:
Domenic Denicola (Google)
Adrian Bateman (Microsoft Corporation)
Zach Koch (Google)
Roy McElmurry (Facebook)
Danyao Wang (Google)
フィードバック:
GitHub w3c/payment-request (プルリクエスト新しい課題未解決の課題)
正誤表:
正誤表があります
ブラウザ対応:
caniuse.com

翻訳版も参照してください。


要約

この仕様では、加盟店(merchant。つまり、物理的な商品やデジタルの商品を販売するウェブ・サイト)が1つ以上の決済方式を最小限の組み合わせで利用できるようにするためのAPIを標準化します。ユーザ・エージェント(ブラウザなど)により、加盟店とユーザの間の決済フローが容易になります。

このドキュメントのステータス

この項は、このドキュメントの公開時のステータスについて記述しています。現行のW3Cの刊行物およびこの技術報告の最新の改訂版のリストは、https://www.w3.org/TR/のW3C技術報告インデックスにあります。

ワーキンググループは、未対処のバグ報告のリストを管理しています。未解決の課題に対する仕様文の提案を含むプルリクエストが強く推奨されます。

ワーキンググループは、実装報告書を作成することにより、実装経験を実証します。この報告書は、テストスイートの各必須テスト(各テストは仕様の要件に対応していなければならない(MUST))に合格した2つ以上の独立した実装を示します。

この仕様の開発中には、他のワーキンググループとの依存関係に変更はありませんでした。

このドキュメントは、ウェブ決済ワーキンググループ(Web Payments Working Group)が勧告トラックを用いて勧告として公開しました。

W3Cは、この仕様をウェブの標準として広く展開することを推奨します。

W3C勧告は、広範な合意形成の後、W3Cとそのメンバーの協賛を得て、ワーキンググループのメンバーから実装のためのロイヤルティ・フリーのライセンスを約束された仕様です。この勧告の将来の更新では、新しい機能を組み込む可能性があります。

このドキュメントは、2017年8月1日のW3C特許方針の下で活動しているグループによって作成されました。W3Cは、このグループの成果物に関連するあらゆる特許の開示の公開リストを維持し、このページには特許の開示に関する指示も含まれています。不可欠な請求権(Essential Claim(s))を含んでいると思われる特許に関して実際に知っている人は、W3C特許方針の6項に従って情報を開示しなければなりません。

このドキュメントは、2021年11月2日のW3Cプロセス・ドキュメントによって管理されています。

最終公開以後の変更

このバージョンの仕様では、APIからデータ機能を削除し、基本的にデータの詳細を決済方式の説明に押し込んでいます。編集上のすべての変更を含む変更点の完全なリストは、コミット履歴で見ることができます。主な変更点は変更履歴で見ることができます。

1. はじめに

この項は非規範的です。

この仕様は、ユーザ・エージェント(ブラウザなど)が取引において次の三者間の仲介役を果たすことができるようにするAPIについて説明しています。

特定の決済方式による決済リクエストをどのように履行するのかの詳細は、決済リクエストを処理するアプリケーションやサービスである決済ハンドラの実装詳細です。具体的には、決済ハンドラは次のステップを定義します。

決済の可否を確認するステップ:
決済ハンドラが、自身またはユーザが潜在的に「決済を行う」ことができるかどうかをどのように判断するかも、決済ハンドラの実装詳細です。
決済リクエストに応答するステップ:
加盟店が取引の処理や妥当性検証を行うために用いるオブジェクトや辞書を返すステップ。このオブジェクトの構造は、決済方式ごとに異なります。
ユーザが決済方式を変更する場合のステップ(オプション)

ユーザが決済方式や貨幣代替物(monetary instrument)を(デビットカードからクレジットカードなどに)変更すると、辞書objectやヌル(null)になる場合の処理方法を説明するステップです。

また、このAPIにより、標準的なJavaScriptライブラリでは不可能な、より安全な決済スキーム(トークン化、システム・レベルの認証など)をウェブ・サイトで利用することができます。これにより、加盟店の責任が軽減される可能性があり、機密性の高いユーザ情報の保護に役立ちます。

1.1 目標と範囲

次の事項は、この仕様の範囲外です。

2. 使用例

この項は非規範的です。

APIを用いるためには、開発者はいくつかの重要な情報を提供し、それを追跡する必要があります。この情報は、PaymentRequestコンストラクタに引数として渡され、その後、ユーザに表示される決済リクエストを更新するために用いられます。具体的には、この情報は次のとおりです。

PaymentRequestが構築されると、これは、show()メソッドを介してエンド・ユーザに提示されます。show()は、ユーザが決済リクエストを確認すると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を構築する際に、加盟店はコンストラクタの2番目の引数(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" },
    },
    {
      label: "Standard shipping",
      amount: { currency: "GBP", value: "5.00" },
    },
  ],
  total: {
    label: "Total due",
    // 税金と送料を加算する必要があるため、
    // ここでは、合計は65英ポンドとなる。
    amount: { currency: "GBP", value: "65.00" },
  },
};

2.3 決済リクエストの条件付き変更

ここでは、特定のネットワークでカードを用いる場合に処理手数料を追加する方法を示します。合計を再計算する必要があることに注意してください。

3: カードの種類に基づく決済リクエストの変更
// 特定のカードには、3ドルの処理手数料がかかる。
const cardFee = {
  label: "Card processing fee",
  amount: { currency: "AUD", value: "3.00" },
};

// ユーザがカード決済を選択した場合、
// 修飾子が適用される。
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.4 PaymentRequestの構築

必要な情報がすべて集まったため、PaymentRequestを構築し、ブラウザがそれをユーザに提示するようにリクエストすることができるようになりました。

4: 「PaymentRequest」の構築
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) {
    // 何か問題があった...
    await response.complete("fail");
  }
}
// クリックまたは何らかの明示的なユーザ・アクション
// の結果として呼び出されなければならない。
doPaymentRequest();

2.5 決済応答をPOSTでサーバーに返す

PaymentResponse内のデータは、処理のためにサーバーにPOSTで返されることが期待されます。これをできる限り簡単にするために、PaymentResponseは、デフォルトのtoJSONステップ(つまり、.toJSON())を用いて、オブジェクトを直接JSONにシリアル化することができます。これにより、フェッチ標準を用いて、結果のJSONをサーバーにPOSTすることが容易になります。

5: 「fetch()」を用いたPOST処理
async function doPaymentRequest() {
  const payRequest = new PaymentRequest(methodData, details, options);
  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.6 クロスオリジンiframeでの使用

クロスオリジンiframeで決済リクエストAPIを呼び出すことができることを示すために、iframe要素にallow属性と「payment」キーワードを一緒に指定することができます。

6: クロスオリジンiframeでの決済リクエストAPIの使用
<iframe
  src="https://cross-origin.example"
  allow="payment">
</iframe>

決済リクエストAPIをサポートする複数のオリジン間をiframeが移動する場合は、allow"payment *"に設定することができます。許可方針仕様にさらなる詳細と例が記載されています。

3. PaymentRequestインターフェース

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

  readonly attribute DOMString id;

  attribute EventHandler onpaymentmethodchange;
};

開発者は、PaymentRequestを作成して決済リクエストを行います。これは通常、ユーザが決済プロセスを開始することに関連します(例えば、ウェブ・サイトで「買う」、「購入する」や「精算」のボタンを有効にしたり、対話型ゲームで「パワー・アップ」を選択したり、立体駐車場の自動券売機で決済するなど)。PaymentRequestにより、開発者は、ユーザが入力を行っている間に(ユーザが決済リクエストを承認または拒否する時点まで)、ユーザ・エージェントと情報交換を行えるようになります。

request決済関連ブラウジング・コンテキストは、PaymentRequest関連するグローバ・ルオブジェクトのブラウジング・コンテキストの最上位のブラウジング・コンテキストです。すべての決済関連ブラウジング・コンテキストには、決済リクエストを表示中というブール値があるため、一度に複数の決済UIを表示することはできません。

決済リクエストを表示中というブール値は、単に、ブラウザの1つのタブに複数の決済UIが表示されないようにするだけです。しかし、決済ハンドラは、ブラウザのすべてのウィンドウとタブで1つの決済UIのみを表示するようにユーザ・エージェントを制限することができます。決済ハンドラによっては、ブラウザの異なるタブにまたがって決済UIを表示できる場合もあります。

3.1 コンストラクタ

PaymentRequestは、決済方式固有のdataを含む供給されたPaymentMethodData methodDataのシーケンスと、PaymentDetailsInit detailsを用いて構築されます。

PaymentRequest(methodData, details)コンストラクタは、次のように動作しなければなりません(MUST)。

  1. 現在の設定オブジェクト関連するグローバルなオブジェクト関連付けられたDocumentが、「payment」許可の使用を許可されていない場合、「SecurityErrorDOMExceptionスローします。
  2. 次のようにリクエストのidを確立します。
    1. details.idが存在していない場合、idメンバーをdetailsに追加し、その値をUUID[RFC4122]に設定します。
  3. serializedMethodDataを空のリストとします。
  4. 次のように決済方式を処理します。
    1. methodDataシーケンスの長さが0の場合、TypeErrorスローし、オプションで、少なくとも1つの決済方式が必要であることを開発者に通知します。
    2. seenPMIsを空の集合とします。
    3. methodDatapaymentMethodごとに、
      1. paymentMethod.supportedMethods決済方式識別子の妥当性検証を行うステップを実行します。偽(false)を返した場合、RangeErrorの例外をスローします。オプションで、決済方式識別子が無効であることを開発者に通知します。
      2. pmiを、基本的なURLパーサpaymentMethod.supportedMethodsを解析した結果とします。
        1. 失敗した場合、pmipaymentMethod.supportedMethodsに設定します。
      3. If seenPMIs contains pmi throw a RangeError DOMException optionally letting the developer this payment method identifier is a duplicate. seenPMIspmi含まれている場合、RangeError DOMExceptionをスローし、オプションで開発者にこの決済方式識別子が重複していることを知らせます。
      4. pmiseenPMIs追加します。
      5. paymentMethoddataメンバーが存在していない場合、serializedDataをヌル(null)にします。そうでない場合は、serializedDataを、paymentMethod.dataを文字列にJSONシリアル化した結果とします。例外があれば再度スローします。
      6. serializedDataがヌル(null)でない場合、およびpaymentMethod.supportedMethodsを定義している仕様で要求されている場合、
        1. objectを、serializedDataJSON解析した結果とします。
        2. objectを、paymentMethod.supportedMethodsを定義している仕様で指定されている型のIDL値に変換します。例外があれば再度スローします。

          このステップにより、IDLの型変換エラーを可能な限り早期に検出することができます。

      7. タプル(paymentMethod.supportedMethods, serializedData)をserializedMethodDataに追加します。
  5. 次のように合計を処理します。
    1. details.total.amount合計金額の確認と正規化を行います。例外があれば再度スローします。
  6. detailsdisplayItemsメンバーが存在している場合、details.displayItemsitemごとに、
    1. item.amount金額の確認と正規化を行います。例外があれば再度スローします。
  7. serializedModifierDataを空のリストとします。
  8. 次のように決済明細の修飾子を処理します。
    1. modifiersを空のsequence<PaymentDetailsModifier>とします。
    2. detailsmodifiersメンバーが存在している場合、
      1. modifiersdetails.modifiersに設定します。
      2. modifiersmodifierごとに、
        1. modifiertotalメンバーが存在している場合、
          1. modifier.total.amount合計金額の確認と正規化を行います。例外があれば再度スローします。
        2. modifieradditionalDisplayItemsメンバーが存在している場合、modifier.additionalDisplayItemsitemごとに、
          1. item.amount金額の確認と正規化を行います。例外があれば再度スローします。
        3. modifierdataメンバーが存在していない場合、serializedDataをヌル(null)とします。そうでない場合は、serializedDataを、modifier.dataを文字列にJSONシリアル化した結果とします。例外があれば再度スローします。
        4. タプル(modifier.supportedMethods, serializedData)をserializedModifierDataに追加します。
        5. modifierdataメンバーが存在している場合、それを削除します。
    3. details.modifiersmodifiersに設定します。
  9. requestを新しいPaymentRequestとします。
  10. request.[[handler]]をヌル(null)に設定します。
  11. request.[[state]]を「created」に設定します。
  12. request.[[updating]]を偽(false)に設定します。
  13. request.[[details]]detailsに設定します。
  14. request.[[serializedModifierData]]serializedModifierDataに設定します。
  15. request.[[serializedMethodData]]serializedMethodDataに設定します。
  16. request.[[response]]をヌル(null)に設定します。
  17. requestを返します。

3.2 id属性

id属性は、取得すると、このPaymentRequest[[details]].idを返します。

監査と照合のために、加盟店は、取引ごとに一意の識別子をid属性に関連付けることができます。

3.3 show()メソッド

show()メソッドは、開発者が決済リクエストに対するユーザ・インタラクションを開始したい場合に呼び出されます。show()メソッドは、ユーザが決済リクエストを受け入れた場合に解決されるPromiseを返します。show()メソッドが返された後、決済リクエストを容易にするために、何らかのユーザ・インターフェースがユーザに表示されます。

各決済ハンドラは、複数のブラウジング・コンテキストが同時にshow()メソッドを呼び出したときに何が起こるかを制御します。例えば、複数の決済UIをブラウザの異なるタブやウィンドウに表示することを認める決済ハンドラもあれば、ユーザ・エージェント全体に対して1つの決済UIのみを表示することしか認めない決済ハンドラもあります。

show(optional detailsPromise)メソッドは、次のように動作しなければなりません(MUST)。

  1. requestこれとします。
  2. request関連するグローバルなオブジェクト一時的な有効化(transient activation)がない場合、
    1. SecurityErrorDOMException拒否されたプロミスを返します。
  3. 関連するグローバルなオブジェクトユーザの有効化を利用します。
  4. documentrequest関連するグローバルなオブジェクト関連付けられたDocumentとします。
  5. document完全に有効でない場合、「AbortErrorDOMExceptionで拒否されたプロミスを返します。
  6. オプションで、ユーザ・エージェントがユーザを保護するためにshow()の呼び出しを禁止したい場合は、「SecurityErrorDOMExceptionで拒否されたプロミスを返します。例えば、ユーザ・エージェントは、14. プライバシーとセキュリティに関する留意点の項で説明しているように、ページがshow()を呼び出すことができる割合を制限することができます。

  7. request.[[state]]が「created」でない場合、「InvalidStateErrorDOMExceptionで拒否されたプロミスを返します。
  8. ユーザ・エージェント決済リクエストを表示中というブール値が真(true)の場合、
    1. request.[[state]]を「closed」に設定します。
    2. AbortErrorDOMExceptionで拒否されたプロミスを返します。
  9. request.[[state]]を「interactive」に設定します。
  10. acceptPromise新しいプロミスとします。
  11. request.[[acceptPromise]]acceptPromiseに設定します。
  12. オプションで、

    1. AbortErrorDOMExceptionacceptPromiseを拒否します。
    2. request.[[state]]を「closed」に設定します。
    3. acceptPromiseを返します。

    これにより、ユーザ・エージェントは、その裁量により、あたかもユーザが直ちに決済リクエストを中止したかのように動作することができます。例えば、「プライベート・ブラウジング」モードなどで、ユーザ・エージェントがこのステップを利用することができます。

  13. request決済関連ブラウジング・コンテキスト決済リクエストを表示中というブール値を真(true)に設定します。
  14. acceptPromiseを返し、残りのステップを並行して実行します。
  15. handlersを空のリストとします。
  16. request.[[serializedMethodData]]paymentMethodタプルごとに、
    1. identifierpaymentMethodタプルの最初の要素とします。
    2. datapaymentMethodタプルの2番目の要素をJSON解析した結果とします。
    3. identifierを定義している仕様で必須とされている場合、dataを、そこで指定されている型のIDL値に変換します。そうでない場合は、object変換します。
    4. 変換の結果、例外errorが発生した場合、
      1. request.[[state]]を「closed」に設定します。
      2. erroracceptPromiseを拒否します。
      3. request決済関連ブラウジング・コンテキスト決済リクエストを表示中というブール値を偽(false)に設定します。
      4. このアルゴリズムを終了します。
    5. registeredHandlersを、決済方式identifierに対する登録済み決済ハンドラのリストとします。
      : 決済ハンドラの登録
    6. registeredHandlershandlerごとに、
      1. canMakePayment を、handler決済の可否を確認するステップdataで実行した結果とします。
      2. canMakePaymentが真(true)の場合、handlerhandlersに追加します。
  17. handlersが空である場合、
    1. request.[[state]]を「closed」に設定します。
    2. NotSupportedErrorDOMExceptionacceptPromiseを拒否します。
    3. request決済関連ブラウジング・コンテキスト決済リクエストを表示中というブール値を偽(false)に設定します。
    4. このアルゴリズムを終了します。
  18. ユーザがhandlersとインタラクションを行えるようにするユーザ・インターフェースを提示します。ユーザ・エージェントは、決済方式を提示する際にユーザの好みを優先すべきです(SHOULD)。ユーザ・インターフェースは、documentドキュメント要素言語とマッチする言語とロケールに基づく形式がもしあればそれを用いて、またはそれが利用できない場合は適切なフォールバックを用いて提示されるべきです(SHOULD)。

    : 決済ユーザ・インターフェースのローカライゼーション
  19. detailsPromiseが渡された場合、
    1. detailsPromiserequest、ヌル(null)でPaymentRequestのdetail更新アルゴリズムを実行します。
    2. detailsPromiseが決定するのを待ちます。

      PaymentRequestのdetails更新アルゴリズムは、detailsPromiseがどのように決定したかに基づいて、決済UIの動作方法を決定します。すなわち、detailsPromise拒否時には、決済リクエストは中止されます。そうでない場合は、detailsPromise履行時に、ユーザ・エージェントが決済リクエストUIを再び有効にし、決済フローを継続することができます。

  20. request.[[handler]]を、エンド・ユーザによって選択された決済ハンドラに設定します。
  21. modifiersを空のリストとします。
  22. [[serializedModifierData]]tupleごとに、
    1. tupleの最初の要素(PMI)がrequest.[[handler]]決済方式識別子にマッチする場合、tupleの2番目の要素(シリアル化された方式データ)をmodifiersに追加します。
  23. paymentMethodタプルの変換された2番目の要素とmodifiersを渡します。オプションで、ユーザ・エージェントは、ユーザを決済プロセスに導くために、リクエストからユーザが選択した決済ハンドラへと適切なデータを送るべきです(SHOULD)。これには、requestの様々な属性とその他の内部スロットが含まれます(プライバシー上の理由から、必要に応じて一部を除外することができます(MAY))。

    [[serializedModifierData]]内部スロットにおける複数の適用可能な修飾子の処理は、決済ハンドラに固有のものであり、この仕様の範囲外です。しかし、決済ハンドラ[[serializedModifierData]]リスト内の項目では「最後のものが優先される」アプローチを用いることが推奨されます(RECOMMENDED)。つまり、リストの最後にある項目が、リストの先頭にあるどの項目よりも常に優先されます(以下の例を参照)。

    acceptPromiseは、後に、ユーザによる決済リクエストの受け入れアルゴリズムまたはユーザによる決済リクエストの中止アルゴリズムのいずれかによって解決または拒否されますが、これらはユーザ・インターフェースとの相互作用によってもたらされます。

    ユーザ・インターフェースの表示中にdocument完全に有効でなくなるか、このステップに到達するまでに有効でなくなった場合、

    1. ユーザ・インターフェースを閉じます。
    2. request決済関連ブラウジング・コンテキスト決済リクエストを表示中というブール値を偽(false)に設定します。

3.4 abort()メソッド

abort()メソッドは、開発者がユーザ・エージェントに対し、決済requestを中止し、表示される可能性のあるユーザ・インターフェースを破棄するように指示したい場合に呼び出されます。 abort()は、show()メソッドが呼び出された後(状態を参照)で、このインスタンスの[[acceptPromise]]が解決される前にのみ呼び出すことができます。例えば、開発者は、自身が販売している商品が期限限定でのみ入手可能な場合に、この方法を選択する可能性があります。与えられた期間内にユーザが決済リクエストを受け入れなければ、リクエストは中止されます。

ユーザ・エージェントは、常にリクエストを中止できるとは限りません。例えば、ユーザ・エージェントがリクエストの責任を他のアプリに委任している場合です。この状況では、abort()は返されるPromiseを拒否します。

ユーザが決済リクエストを中止する場合のアルゴリズムも参照してください。

abort()メソッドは、次のように動作しなければなりません(MUST)。

  1. requestこれとします。
  2. request.[[response]]がヌル(null)でなく、request.[[response]].[[retryPromise]]がヌル(null)でない場合、「InvalidStateErrorDOMExceptionで拒否されたプロミスを返します。
  3. request.[[state]]の値が 「interactive」でない場合、「InvalidStateErrorDOMExceptionで拒否されたプロミスを返します。
  4. promise新しいプロミスとします。
  5. promiseを返し、残りのステップを並行して実行します。
  6. 決済ハンドラとの現在のユーザ・インタラクションを中止し、残りのユーザ・インターフェースを閉じようと試みます。
  7. ユーザ・インタラクションのタスク源タスクをキューに入れ、次のステップを実行します。
    1. 現在のユーザ・インタラクションを中止することができない場合、「InvalidStateErrorDOMExceptionpromiseを拒否し、これらのステップを中止します。
    2. request.[[state]]を「closed」に設定します。
    3. AbortErrorDOMExceptionでプロミスrequest.[[acceptPromise]]を拒否します。
    4. promiseを未定義(undefined)で解決します。

3.5 canMakePayment()メソッド

: canMakePayment()

開発者は、canMakePayment()メソッドを用いて、 希望する決済方式のいずれかをユーザ・エージェントがサポートしているかどうかを判断することができます。14.8 canMakePayment()保護を参照してください。

canMakePayment()の結果が真(true)であっても、ユーザが決済用に提供されている手段を準備していることを意味するわけではありません。

canMakePayment()メソッドは、決済可能アルゴリズムを実行しなければなりません(MUST)。

3.6 onpaymentmethodchange属性

PaymentRequestonpaymentmethodchange属性は、「paymentmethodchange」という名前のPaymentMethodChangeEventに対するEventHandlerです。

3.7 内部スロット

PaymentRequestのインスタンスは、次の表の内部スロットを用いて作成されます。

内部スロット 説明(非規範的)
[[serializedMethodData]] コンストラクタに供給されるmethodDataだが、サポートされているメソッドとデータ用の文字列またはヌル(null)を含んでいるタプル(元のオブジェクト形式ではなく)として表される。
[[serializedModifierData]] [[details]].modifierというシーケンスの対応する項目ごとに、各dataメンバーのシリアル化された文字列形式を含んでいるリスト、またはそのようなメンバーが存在ていない場合はヌル(null)。
[[details]] 最初はコンストラクタに供給され、その後updateWith()の呼び出しによって更新される決済リクエストの現在のPaymentDetailsBasemodifiersメンバーに含まれる PaymentDetailsModifierインスタンスのすべてのdataメンバーは、代わりに[[serializedModifierData]]内部スロットにシリアル化された形式で格納されているため、削除されることに注意。
[[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メンバー
サポートされる決済方式で必要とされる可能性のあるオプションの情報を提供するオブジェクト。供給される場合、それはJSONシリアル化されているでしょう。

supportedMethodsの値を配列から文字列に変更しましたが、ウェブ上の既存のコンテンツとの互換性を保つため、名称は複数形のままとしました。

5. PaymentCurrencyAmount辞書

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

PaymentCurrencyAmount辞書は、金額を供給するために用いられます。

currencyメンバー

[ISO4217]整形式の3文字のアルファベット・コード(すなわち、数値コードはサポートされていない)。正規形は大文字です。しかし、ローカライズされた通貨記号を使用できる通貨コードの組み合わせは、実装依存です。

貨幣価値(monetary value)を表示する場合、ユーザ・エージェントは通貨コードを表示することが推奨されますが(RECOMMENDED)、ユーザ・エージェントが通貨記号を表示することはオプションです(OPTIONAL)。これは、通貨記号は様々な通貨で用いられるため、曖昧になる可能性があるからです(例えば、「$」は、USD、AUD、NZD、CADなどのいずれかを意味する可能性があります)。

ユーザ・エージェントは、(ローカライゼーションのためなど)OSの規定に従ってcurrencyメンバーの表示をフォーマット化することができます(MAY)。

: デジタル通貨と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ウェブ決済ワーキンググループは、将来、この仕様の改訂が関連するISOレジストリと互換性を保つようにISOと連携しています。

valueメンバー
金額を含む有効な10進数の貨幣価値
8: 1.234オマーン・リアルの表し方
{
   "currency": "OMR",
   "value": "1.234"
}

5.1 妥当性チェッカー

JavaScriptの文字列は、指定された順序で次のコード・ポイントで構成されている場合、有効な10進数の貨幣価値です。

  1. オプションで、1つのU+002D(-)。金額が負であることを示します。
  2. U+0030(0)からU+0039(9)までの範囲の1つ以上のコード・ポイント
  3. オプションで、U+0030(0)からU+0039(9)までの範囲の1つ以上のコード・ポイントが後続する1つのU+002E(.)。
次の正規表現は、上記の定義を実装したものです。
^-?[0-9]+(\.[0-9]+)?$

PaymentCurrencyAmount amountである場合に金額の確認と正規化を行うには、次のステップを実行します。

  1. IsWellFormedCurrencyCode(amount.currency)の結果が偽(false)である場合、RangeError例外をスローし、オプションで通貨が無効であることを開発者に通知します。
  2. amount.value有効な10進数の貨幣価値でない場合は、TypeErrorをスローし、オプションで通貨が無効であることを開発者に通知します。
  3. amount.currencyを、amount.currencyASCII大文字にした結果に設定します。

PaymentCurrencyAmount amountである場合に合計金額の確認と正規化を行うには、次のステップを実行します。

  1. 金額の確認と正規化 amountを行います。例外があれば再度スローします。
  2. amount.valueの最初のコード・ポイントがU+002D(-)である場合、TypeErrorをスローし、オプションで開発者に合計の値は負の数であってはならないことを通知します。
: 値の変更を行わない

6. 決済明細辞書

6.1 PaymentDetailsBase辞書

WebIDLdictionary PaymentDetailsBase {
  sequence<PaymentItem> displayItems;
  sequence<PaymentDetailsModifier> modifiers;
};
displayItemsメンバー
PaymentItem辞書のシーケンスには、ユーザ・エージェントが表示できる(MAY)決済リクエストの明細項目が含まれます。
modifiersメンバー
特定の決済方式識別子に対する修飾子を含むPaymentDetailsModifier辞書のシーケンス。例えば、それによって、決済方式に基づいて合計金額を調整することができます。

6.2 PaymentDetailsInit辞書

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

PaymentDetailsBase辞書から継承されたメンバーに加えて、次のメンバーはPaymentDetailsInit辞書の一部です。

idメンバー
この決済リクエストのための自由形式の識別子。
totalメンバー
決済リクエストの負ではない合計金額を含んでいるPaymentItem

6.3 PaymentDetailsUpdate辞書

WebIDLdictionary PaymentDetailsUpdate : PaymentDetailsBase {
  PaymentItem total;
  object paymentMethodErrors;
};

PaymentDetailsUpdate辞書は、updateWith()を用いて決済リクエストを更新するために用いられます。

PaymentDetailsBase辞書から継承されたメンバに加えて、次のメンバーはPaymentDetailsUpdate辞書の一部です。

totalメンバー
負ではないamountを含んでいるPaymentItem

PaymentDetailsUpdate辞書を受け入れるこの仕様のアルゴリズムは、total.amount.valueが負の数である場合、スローします。

paymentMethodErrorsメンバー

決済方式固有のエラー。

7. PaymentDetailsModifier辞書

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

PaymentDetailsModifier辞書は、決済方式識別子に基づいてPaymentDetailsBaseを修正する詳細を提供します。これには、次のメンバーが含まれます。

supportedMethodsメンバー
決済方式識別子PaymentDetailsModifierのメンバーは、ユーザがこの決済方式を選択した場合にのみ適用されます。
totalメンバー
supportedMethodsメンバーの決済方式識別子に関して、PaymentDetailsInit辞書のtotalメンバーを上書きするPaymentItem値。
additionalDisplayItemsメンバー
PaymentItem辞書のシーケンスは、supportedMethodsメンバーの決済方式識別子に関して、PaymentDetailsBase辞書のdisplayItemsメンバーに追加される追加表示項目を提供します。このメンバーは一般的に、ユーザ・エージェントが表示できる(MAY)、選択した決済方式によってtotalの金額が異なる理由を示す、割引または追加料金の明細項目を追加するために用いられます。

totalの金額がdisplayItemsadditionalDisplayItemsの合計であることを確認する責任は開発者にあります。

dataメンバー
サポートされている決済方式で必要となる可能性があるオプション情報を提供するオブジェクトです。供給される場合は、JSONシリアル化されたものになるでしょう。

8. PaymentItem辞書

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

PaymentDetailsBase辞書には、決済リクエストの目的と要求される値を示すために、1つ以上のPaymentItem辞書のシーケンスが含まれます。

labelメンバー
人間が読める、項目の記述。ユーザ・エージェントはこれをユーザに表示できます。
: ラベルの国際化
amountメンバー
項目の金額を含んでいるPaymentCurrencyAmount
pendingメンバー
ブール値。真(true)に設定した場合、amountメンバーが最終的なものではないことを意味します。これは一般的に、配送先住所や配送オプションの選択に応じて配送料や税額などの項目を表示するために用いられます。ユーザ・エージェントは、決済リクエスト用のユーザ・インターフェースで待機中(pending)フィールドを示すことができます(MAY)。

9. PaymentComplete列挙

WebIDLenum PaymentComplete {
  "fail",
  "success",
  "unknown"
};
fail」(失敗)
決済処理に失敗したことを示します。ユーザ・エージェントは、失敗を示すUIを表示できます(MAY)。
success」(成功)
決済が正常に処理されたことを示します。ユーザ・エージェントは、成功を示すUIを表示できます(MAY)。
unknown」(不明)
開発者が成功か失敗かを示さなかったため、ユーザ・エージェントは、成功か失敗かを示すUIを表示すべきではありません(SHOULD NOT)。

10. PaymentResponseインターフェース

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

  readonly attribute DOMString requestId;
  readonly attribute DOMString methodName;
  readonly attribute object details;

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

PaymentResponse は、ユーザが決済方式を選択し、決済リクエストを承認した場合に返されます。

10.1 retry()メソッド

retry(errorFields)メソッドは、次のように動作しなければなりません(MUST)。

  1. responseこれとします
  2. requestresponse.[[request]]とします。
  3. documentrequest関連するグローバルなオブジェクト関連付けられたドキュメントとします。
  4. document完全に有効でない場合、「AbortErrorDOMExceptionで拒否されたプロミスを返します。
  5. response.[[complete]]が真(true)の場合、「InvalidStateErrorDOMExceptionで拒否されたプロミスを返します。
  6. response.[[retryPromise]]がヌル(null)でない場合、「InvalidStateErrorDOMExceptionで拒否されたプロミスを返します。
  7. request.[[state]]を「interactive」に設定します。
  8. retryPromise新しいプロミスとします。
  9. response.[[retryPromise]]retryPromiseに設定します。
  10. errorFieldsが渡された場合。
    1. errorFields.paymentMethodメンバーが渡され、response.paymentを定義している仕様で要求されている場合、errorFieldspaymentMethodメンバーをそこで指定されている型のIDL値に変換します。そうでない場合は、object変換します。
    2. request決済関連ブラウジング・コンテキスト決済リクエストを表示中というブール値を偽(false)に設定します。
    3. 変換の結果、例外errorが発生した場合、
      1. errorretryPromiseを拒否します。
      2. ユーザ・エージェント決済リクエストを表示中というブール値を偽(false)に設定します。
      3. 戻ります。
    4. errorFieldsのメンバーをユーザ・エージェントのUIの入力フィールドにマッチングさせることにより、決済応答(payment response)のデータに何か問題があることをエンド・ユーザに示します。例えば、ユーザ・エージェントは、ブラウザのUIで、ユーザの注意を誤りのあるerrorFieldsに向けさせ、ユーザが各エラーを修正できるように各フィールドの値を表示する可能性があります。同様に、errorメンバーが渡された場合は、ユーザ・エージェントのUIでエラーを示します。メンバの値が空の文字列であった場合には、ユーザ・エージェントは値を適切なエラー・メッセージに置き換えることができます(MAY)。
  11. そうでない場合は、errorFieldsが渡されなかった場合は、決済の再試行(retry)を試みるようエンド・ユーザに通知します。エンド・ユーザが決済リクエストの受け入れを再試行できるようにするUI要素を再度有効にします。
  12. ユーザ・インターフェースの表示中にdocument完全に有効でなくなるか、このステップに到達するまでに有効でなくなった場合、
    1. ユーザ・インターフェースを閉じます。
    2. request決済関連ブラウジング・コンテキスト決済リクエストを表示中というブール値を偽(false)に設定します。
  13. 最後に、retryPromiseが決定した場合、response.[[retryPromise]]をヌル(null)に設定します。
  14. retryPromiseを返します。

    retryPromiseは、後に、ユーザによる決済リクエストの受け入れアルゴリズムによって解決されるか、ユーザによる決済リクエストの中止アルゴリズムまたは更新の中止のいずれかによって拒否されます。

10.1.1 PaymentValidationErrors辞書

WebIDLdictionary PaymentValidationErrors {
  DOMString error;
  object paymentMethod;
};
errorメンバー
ユーザが回復を試みることができる、決済に関するエラーの一般的な記述。例えば、ユーザは決済を再試行することで回復することができます。開発者は、オプションでerrorメンバーを単独で渡して、検証の課題の概要を示したり、それをPaymentValidationErrors辞書の他のメンバーと組み合わせて渡したりすることができます。
: エラーの国際化
paymentMethodメンバー
決済方式固有のエラー。

10.2 methodName属性

ユーザが取引を履行するために選択した決済方式決済方式識別子

10.3 details属性

加盟店が取引を処理または検証するために使用できる、決済方式によって生成されるobjectまたは辞書(決済方式によって異なる)。

10.4 requestId属性

この決済応答を生成した、対応する決済リクエストid

10.5 complete()メソッド

complete()メソッドは、ユーザが決済リクエストを受け入れ、[[acceptPromise]]が解決された後に呼び出されます。complete()メソッドを呼び出すと、ユーザ・エージェントに決済のインタラクションが終了したことが伝えられます(そして、残りのユーザ・インターフェースは閉じられるべきです(SHOULD))。

決済リクエストが受け入れられ、PaymentResponseが呼び出し元に返された後ではあるけれども、呼び出し元がcomplete()を呼び出す前は、決済リクエストのユーザ・インターフェースは待機状態のままですす。決済リクエストの受け入れが返されているため、この時点では、ユーザ・インターフェースはキャンセル・コマンドを提供すべきではありません(SHOULD NOT)。しかし、何らかの問題が発生して、開発者がcomplete()を呼び出さない場合、ユーザ・インターフェースはブロックされます。

このため、実装では開発者がcomplete()を呼び出す際にタイムアウトを課すことができます(MAY)。タイムアウトとなった場合、実装は引数なしでcomplete()が呼び出されたかのように動作します。

complete()メソッドは、次のように動作しなければなりません(MUST)。

  1. responseこれとします。
  2. response.[[complete]]が真(true)の場合、「InvalidStateErrorDOMExceptionで拒否されたプロミスを返します。
  3. response.[[retryPromise]]がヌル(null)でない場合、「InvalidStateErrorDOMExceptionで拒否されたプロミスを返します。
  4. promise新しいプロミスとします。
  5. response.[[complete]]を真(true)に設定します。
  6. promiseを返し、残りのステップを並行して実行します。
  7. ユーザ・インターフェースの表示中にdocument完全に有効でなくなるか、このステップに到達するまでに有効でなくなった場合、
    1. ユーザ・インターフェースを閉じます。
    2. request決済関連ブラウジング・コンテキスト決済リクエストの表示中というブール値を偽(false)に設定します。
  8. そうでない場合は、
    1. 残りのユーザ・インターフェースを閉じます。ユーザ・エージェントは、ユーザ体験に影響を与えるために、resultという値を使用できます(MAY)。
    2. request決済関連ブラウジング・コンテキスト決済リクエストを表示中というブール値を偽(false)に設定します
    3. promiseを未定義(undefined)で解決します。

10.6 内部スロット

PaymentResponseのインスタンスは、次の表の内部スロットを用いて作成されます。

内部スロット 説明(非規範的)
[[complete]] 決済のリクエストが完了した場合(complete()が呼び出された、または致命的なエラーがあり、応答が使用できなくなったなど)は真(true)、そうでない場合は偽(false)。
[[request]] このPaymentResponseをインスタンス化したPaymentRequestのインスタンス。
[[retryPromise]] ヌル(null)、またはユーザによる決済リクエストの受け入れの場合には解決する、ユーザによる決済リクエストの中止の場合には拒否するPromise

11. 許可方針の統合

この仕様は、文字列「payment」によって識別される方針制御機能を定義します[permissions-policy]。そのデフォルトの許可リストは「self」です。

12. イベント

12.1 要約

この項は非規範的です。

イベント名 インターフェース 送る場合 ターゲット
paymentmethodchange PaymentMethodChangeEvent ユーザが決済ハンドラ内で異なる決済方式を選択した場合。 PaymentRequest

12.2 PaymentMethodChangeEventインターフェース

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

12.2.1 methodDetails属性

取得すると、その初期化に用いられた値を返します。詳細については、PaymentMethodChangeEventInitmethodDetailsメンバーを参照してください。

12.2.2 methodName属性

取得すると、その初期化に用いられた値を返します。詳細については、PaymentMethodChangeEventInitmethodNameメンバーを参照してください。

12.2.3 PaymentMethodChangeEventInit辞書

WebIDLdictionary PaymentMethodChangeEventInit : PaymentRequestUpdateEventInit {
  DOMString methodName = "";
  object? methodDetails = null;
};
methodNameメンバー
決済方式識別子を表す文字列。
methodDetailsメンバー
決済方式のデータを表すオブジェクト、またはヌル(null)。

12.3 PaymentRequestUpdateEventインターフェース

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

PaymentRequestUpdateEventにより、開発者がユーザ・インタラクションに応答して決済リクエストの詳細を更新できるようになります。

12.3.1 Constructor

PaymentRequestUpdateEventconstructor(type, eventInitDict)は、次のように動作しなければなりません(MUST)。

  1. eventを、PaymentRequestUpdateEventコンストラクタtypeeventInitDictで呼び出した結果とします。
  2. event.[[waitForUpdate]]を偽(false)に設定します。
  3. eventを返します。

12.3.2 updateWith()メソッド

detailsPromiseメソッドを用いたupdateWith()は、次のように動作しなければなりません(MUST)。

  1. eventこれとします。
  2. eventisTrusted属性が偽(false)の場合、「InvalidStateErrorDOMExceptionスローします。
  3. event.[[waitForUpdate]]が真(true)の場合、「InvalidStateErrorDOMExceptionスローします。
  4. event対象PaymentResponseのインスタンスである場合、requesteventtarget[[request]]とします。
  5. そうでない場合は、requestevent対象の値とします。
  6. 言明: requestPaymentRequestのインスタンスです。
  7. request.[[state]]が「interactive」でない場合、「InvalidStateErrorDOMExceptionスローします。
  8. request.[[updating]]が真(true)の場合、「InvalidStateErrorDOMExceptionスローします。
  9. event伝播停止フラグ即時伝播停止フラグを設定します。
  10. event.[[waitForUpdate]]を真(true)に設定します。
  11. pmiをヌル(null)とします。
  12. eventmethodName属性がある場合、pmimethodName属性の値に設定します。
  13. detailsPromiserequestpmiPaymentRequestのdetails更新アルゴリズムを実行します。

12.3.3 内部スロット

PaymentRequestUpdateEventのインスタンスは、次の表の内部スロットを用いて生成されます。

内部スロット 説明(非規範的)
[[waitForUpdate]] updateWith()で開始された更新が現在進行中かどうかを示すブール値。

12.3.4 PaymentRequestUpdateEventInit辞書

WebIDLdictionary PaymentRequestUpdateEventInit : EventInit {};

13. アルゴリズム

PaymentRequestオブジェクトの内部スロット[[state]]が「interactive」に設定された場合、ユーザ・エージェントはユーザ・インタラクションに基づいて次のアルゴリズムを起動します。

13.1 決済可能アルゴリズム

決済可能アルゴリズムは、PaymentRequestが構築された決済方式での決済をユーザ・エージェントがサポートしているかどうかを確認します。

  1. requestを、このメソッドが呼び出されたPaymentRequestオブジェクトとします。
  2. request.[[state]]が「created」でない場合、「InvalidStateErrorDOMExceptionで拒否されたプロミスを返します。
  3. オプションで、最上位のブラウジング・コンテキストの裁量で、「NotAllowedErrorDOMExceptionで拒否されたプロミスを返します。

    これにより、ユーザ・エージェントは、サポートされている様々な決済方式PaymentRequestオブジェクトを作成し、それらで決済可能アルゴリズムを次々に起動するなど、フィンガープリントを目的とした呼び出し方式の乱用を検出し防ぐためのヒューリスティックを適用することができます。例えば、ユーザ・エージェントは、最上位のブラウジング・コンテキストまたは呼び出しが行われた期間に基づいて成功となる呼び出しの数を制限することができます。

  4. hasHandlerPromise新しいプロミスとします。
  5. hasHandlerPromiseを返し、残りのステップを並行して実行します。
  6. request.[[serializedMethodData]]paymentMethodタプルごとに、
    1. identifierpaymentMethodタプルの最初の要素とします。
    2. ユーザ・エージェントにidentifierに対する決済リクエストの処理をサポートする決済ハンドラがある場合、hasHandlerPromiseを真(true)で解決し、このアルゴリズムを終了します。
  7. hasHandlerPromiseを偽(false)で解決します。

13.2 決済方式変更アルゴリズム

決済ハンドラは、辞書またはobjectまたはヌル(null)であるmethodDetailsと、ユーザがインタラクションを行っている決済ハンドラ決済方式識別子を表すDOMStringであるmethodName決済方式をユーザが変更する場合に決済方式変更アルゴリズムを実行することができます(MAY)。

  1. requestを、ユーザがインタラクションを行っているPaymentRequestオブジェクトとします。
  2. ユーザ・インタラクションのタスク源タスクをキューに入れ、次のステップを実行します。
    1. 言明: request.[[updating]]は偽(false)です。一度に1回しか更新できません。
    2. 言明: request.[[state]]は「interactive」です。
    3. methodName属性をmethodNameに初期化し、そのmethodDetails属性をmethodDetailsに初期化して、PaymentMethodChangeEventを用いて、request時に「paymentmethodchange」という名前のイベントを発火させます。

13.3 PaymentRequest更新アルゴリズム

PaymentRequest更新アルゴリズムは、上記の他のアルゴリズムによって実行され、ユーザがnameというイベント名でrequestと呼ばれるPaymentRequestに変更を加えたことを示すイベントを発火させます。

  1. 言明: request.[[updating]]は偽(false)です。一度に1回しか更新できません。
  2. 言明: request.[[state]]は「interactive」です。
  3. eventを、PaymentRequestUpdateEventインターフェースを用いてイベントを作成した結果とします。
  4. eventtype属性をnameに初期化します。
  5. request時にevent送ります。
  6. event.[[waitForUpdate]]が真(true)の場合、他の更新イベントを発火させる可能性のあるユーザ・インターフェースの部分を無効化します。
  7. そうでない場合は、event.[[waitForUpdate]]を真(true)に設定します。

13.4 ユーザによる決済リクエストの受け入れアルゴリズム

ユーザによる決済リクエストの受け入れアルゴリズムは、ユーザが決済リクエストを受け入れ、決済を望むことを確認した場合に実行されます。ユーザ・インタラクションのタスク源タスクをキューに入れ、次のステップを実行しなければなりません(MUST)。

  1. requestを、ユーザがインタラクションを行っているPaymentRequestオブジェクトとします。
  2. request.[[updating]]が真(true)の場合、このアルゴリズムを終了し、それ以上のアクションを取りません。ユーザ・エージェントのユーザ・インターフェースは、これが決して発生しないことを保証すべきです(SHOULD)。
  3. request.[[state]]が「interactive」でない場合、このアルゴリズムを終了し、それ以上のアクションを取りません。ユーザ・エージェントのユーザ・インターフェースは、これが決して発生しないことを保証すべきです(SHOULD)。
  4. isRetryを、request.[[response]]がヌル(null)でない場合は真(true)、そうでない場合は偽(false)とします。
  5. responseを、isRetryが真(true)の場合はrequest.[[response]]、そうでない場合は、新しいPaymentResponseとします。
  6. isRetryが偽(false)の場合、新しく作成されたresponseを初期化します。
    1. response.[[request]]requestに設定します。
    2. response.[[retryPromise]]をヌル(null)に設定します。
    3. response.[[complete]]を偽(false)に設定します。
    4. responserequestId属性の値をrequest.[[details]].idの値に設定します。
    5. request.[[response]]responseに設定します。
  7. handlerrequest.[[handler]]とします。
  8. responsemethodName属性の値をhandler決済方式識別子に設定します。
  9. responsedetails属性の値を、handlerの、決済リクエストに応答するステップを実行した結果得られたオブジェクトに設定します。
  10. request.[[state]]を「closed」に設定します。
  11. isRetryが真(true)の場合、未定義(undefined)でresponse.[[retryPromise]]を解決します。そうでない場合は、responserequest.[[acceptPromise]]を解決します。

13.5 ユーザによる決済リクエストの中止アルゴリズム

ユーザによる決済リクエストの中止アルゴリズムは、現在のインタラクティブなユーザ・インターフェースを通じてユーザが決済リクエストを中止する場合に実行されます。ユーザ・インタラクションのタスク源タスクをキューに入れ、次のステップを実行しなければなりません(MUST)。

  1. requestを、ユーザがインタラクションを行っているPaymentRequestオブジェクトとします。
  2. request.[[state]]が「interactive」でない場合、このアルゴリズムを終了し、それ以上のアクションを取りません。ユーザ・エージェントのユーザ・インターフェースは、これが決して発生しないことを保証すべきです(SHOULD)
  3. request.[[state]]を「closed」に設定します。
  4. request決済関連ブラウジング・コンテキスト決済リクエストを表示中というブール値を偽(false)に設定します。
  5. errorを「AbortErrorDOMExceptionとします。
  6. responserequest.[[response]]とします。
  7. responseがヌル(null)でない場合、
    1. response.[[complete]]を真(true)に設定します。
    2. 言明: response.[[retryPromise]]はヌル(null)ではありません。
    3. errorresponse.[[retryPromise]]を拒否します。
  8. そうでない場合は、errorrequest.[[acceptPromise]]を拒否します。
  9. 現在のユーザ・インタラクションを中止し、残りのユーザ・インターフェースを閉じます。

13.6 PaymentRequestのdetails更新アルゴリズム

PaymentRequestのdetails更新アルゴリズムは、PaymentDetailsUpdate detailsPromisePaymentRequest request、およびDOMStringまたはヌル(null)(決済方式識別子)のいずれかであるpmiを取ります。このステップはdetailsPromiseの決定が条件となります。detailsPromiseが決して決定しない場合、決済リクエストはブロックされます。ユーザ・エージェントは、決済リクエストを中止する手段をユーザに提供すべきです(SHOULD)。実装は、detailsPromiseが合理的な時間内に決定されない場合、待機中の更新に対するタイムアウトを実装することを選択できます(MAY)。

タイムアウトが発生した場合、ユーザが手動で中止した場合、または決済ハンドラがこの特定の決済を中止することを決定した場合、ユーザ・エージェントは、ユーザによる決済リクエストの中止アルゴリズムを実行しなければなりません(MUST)。

  1. request.[[updating]]を真(true)に設定します。
  2. 並行して、ユーザが決済リクエストを受け入れることができるユーザ・インターフェースを無効にします。これは、ユーザ・インターフェースが新しい詳細で更新されるまで、決済が受け入れられないようにするためです。
  3. detailsPromise拒否時に、
    1. requestと 「AbortErrorDOMException更新の中止を行います。
  4. valueという値でのdetailsPromise履行時に、
    1. detailsを、valuePaymentDetailsUpdate辞書に変換した結果とします。これが例外をスローする場合、requestおよびスローされた例外で更新の中止を行います。
    2. serializedModifierDataを空のリストとします。
    3. 詳細の妥当性検証を行い、正規化します。
      1. detailstotalメンバーが存在している場合、
        1. details.total.amount合計金額の確認と正規化を行います。例外がスローされた場合、requestとその例外で更新の中止を行います。
      2. detailsdisplayItemsメンバが存在している場合、details.displayItemsitemごとに、
        1. item.amount金額の確認と正規化を行います。例外がスローされた場合は、requestとその例外で更新の中止を行います。
      3. detailsmodifiersメンバが存在している場合、
        1. modifiersをシーケンスdetails.modifiersとします。
        2. serializedModifierDataを空のリストとします。
        3. modifiersPaymentDetailsModifierごとに、
          1. modifier.supportedMethods決済方式識別子の妥当性検証を行うステップを実行します。偽(false)を返した場合、requestRangeErrorの例外で更新の中止を行います。オプションで、決済方式識別子が無効であることを開発者に通知します。
          2. modifiertotalメンバーが存在している場合、
            1. modifier.total.amount合計金額の確認と正規化を行います。例外がスローされた場合、requestとその例外で更新の中止を行います。
          3. modifieradditionalDisplayItemsメンバーが存在している場合、modifier.additionalDisplayItemsPaymentItem itemごとに、
            1. item.amount金額の確認と正規化を行います。例外がスローされた場合、requestとその例外で更新の中止を行います。
          4. modifierdataメンバーが存在していない場合、serializedDataをヌル(null)とします。そうでない場合は、serializedDataを、modifier.dataJSONシリアル化して文字列にした結果とします。JSONシリアル化が例外をスローした場合、requestとその例外で更新の中止を行います。
          5. serializedDataserializedModifierDataに追加します。
          6. modifierdataメンバーが存在している場合、それを削除します。
    4. paymentMethodErrorsメンバーが存在しており、identifierがヌル(null)でない場合、
      1. pmiを定義している仕様で要求されている場合、paymentMethodErrorsをIDL値に変換します。
      2. 変換の結果、例外errorが発生した場合、error更新の中止を行います。
      3. 決済ハンドラは、paymentMethodErrorsの関連するエラー・フィールドごとにエラーを表示すべきです(SHOULD)。
    5. 新しい詳細を用いてPaymentRequestを更新します。
      1. detailstotalメンバーが存在している場合、
        1. request.[[details]].totaldetails.totalに設定します。
      2. detailsdisplayItemsメンバーが存在している場合、
        1. request.[[details]].displayItemsdetails.displayItemsに設定します。
      3. detailsmodifiersメンバーが存在している場合、
        1. request.[[details]].modifiersdetails.modifiersに設定します。
        2. request.[[serializedModifierData]]serializedModifierDataに設定します。
  5. request.[[updating]]を偽(false)に設定します。
  6. requestの変更された値に基づいてユーザ・インターフェースを更新します。このアルゴリズムを実行する前に無効になっていたユーザ・インターフェースの要素を再度有効にします。

13.6.1 更新の中止

PaymentRequest request例外 exception更新の中止を行うために、

  1. オプションで、エラーが発生したことを知らせる際に、ユーザにエラー・メッセージを表示します。
  2. 現在のユーザ・インタラクションを中止し、残りのユーザ・インターフェースを閉じます。
  3. ユーザ・インタラクションのタスク源タスクをキューに入れ、次のステップを実行します。
    1. request決済関連ブラウジング・コンテキスト決済リクエストを表示中というブール値を偽(false)に設定します。
    2. request.[[state]]を「closed」に設定します。
    3. responserequest.[[response]]とします。
    4. responseがヌル(null)でない場合、
      1. response.[[complete]]を真(true)に設定します。
      2. 言明: response.[[retryPromise]]はヌル(null)ではありません。
      3. exceptionresponse.[[retryPromise]]を拒否します。
    5. そうでない場合は、exceptionrequest.[[acceptPromise]]を拒否します。
    6. request.[[updating]]を偽(false)に設定します。
  4. アルゴリズムを中止します。

供給されたdetailsPromiseが拒否されたり、その履行価値(fulfillment value)に無効なデータが含まれているなど、決済リクエストの更新に致命的なエラーがある場合、更新の中止が実行されます。これにより、開発者が変更イベントを正常に処理できていないため、決済リクエストは矛盾した状態のままとなる可能性があります。

その結果、PaymentRequestは「closed」の状態に移行します。このエラーは、[[acceptPromise]]が拒否されること(すなわちshow()が返すプロミス)で、開発者に通知されます。

同様に、retry()中に発生する更新の中止により、[[retryPromise]]が拒否され、対応するPaymentResponse[[complete]]内部スロットが真(true)に設定されます(すなわち、使用できなくなります)。

14. プライバシーとセキュリティに関する留意点

14.1 show()メソッドによるユーザ保護

この項は非規範的です。

ユーザが不用意に機密情報をオリジンと共有しないようにするため、このAPIでは、関連するWindow一時的な有効化がある間に、(クリックや押下などにより)PaymentRequestのshow()メソッドを呼び出す必要があります。

ユーザ体験の混乱を避けるため、この仕様では、ユーザ・エージェントはshow()メソッドによって一度に1つずつ表示するように制限されています。さらに、ユーザ・エージェントは、ページがshow()を呼び出すことができる割合を制限することができます。

14.2 安全なコンテキスト

この項は非規範的です。

この仕様で定義しているAPIは、安全なコンテキストでのみ公開されます。詳細については、安全なコンテキスト仕様も参照してください。実際には、これは、このAPIがHTTPSでのみ利用可能であることを意味します。これは、決済方式のデータ(クレジット・カード番号など)が暗号化されずに(in the clear)送信される可能性を制限するためです。

14.3 クロス・オリジンの決済リクエスト

この項は非規範的です。

加盟店などの被決済者は、チェックアウトなどのeコマース活動を、iframeを通じて決済サービス・プロバイダに委任するのが一般的です。このAPIは、[HTML]のallow属性により、被決済者が許可したクロス・オリジンのiframeをサポートしています。

決済ハンドラは、iframeを提供するオリジンとiframeコンテンツのオリジン(PaymentRequestが開始される場所)の両方にアクセスすることができます。

14.4 データ・フィールドの暗号化

この項は非規範的です。

PaymentRequest APIは、データ・フィールドの暗号化を直接的にはサポートしていません。個々の決済方式は、暗号化されたデータのサポートを含めることを選択できますが、すべての決済方式がこれをサポートすることは必須ではありません。

14.5 ユーザ・エージェントと決済ハンドラのマッチング方法

この項は非規範的です。

セキュリティ上の理由から、ユーザ・エージェントは、(show()およびcanMakePayment()における)マッチングを、URL決済方式識別子と同じオリジン決済ハンドラに制限することができます。

14.6 データの利用方法

決済方式の所有者は、決済方式のために収集されたユーザ・データの利用方法に関するプライバシー方針を定めます。決済リクエストAPIは、取引を完了させる目的でデータが用いられることを明確に想定しており、このAPIに関連付けられたユーザ体験はその意図を伝えます。データの利用が決済方式の方針に適合していることを確認する責任は被決済者にあります。取引完了後に許可されている使用方法に関しては、被決済者はその使用方法をユーザに明確に伝えるべきです。

14.7 ユーザ情報の公開

ユーザ・エージェントは、ユーザの同意なく、ユーザに関する情報を開発者と共有してはなりません(MUST NOT)。

特に、PaymentMethodDatadataPaymentResponsedetailsメンバーでは、任意のデータ交換が可能となります。多様なデータ・モデルが既存の決済方式で用いられていることから考えると、このAPIでデータの詳細を規定すると、その有用性が制限されることになるでしょう。detailsメンバーは、ウェブ・ベース(決済ハンドラーAPIで定義されている)であるか独自のものであるかにかかわらず、決済ハンドラーからのデータを伝達します。ユーザ・エージェントは、ユーザが適切に同意を行う仕組み(取引の当事者の認識や、データを共有する意思を示す仕組みなど)が含まれていない限り、決済ハンドラーをサポートしてはなりません(MUST NOT)。

ユーザ・エージェントは、取引の完了を容易にする以外のいかなる目的でも、displayItemsメンバーやadditionalDisplayItemsメンバーの値を共有してはなりません(MUST NOT)。

PaymentMethodChangeEventは、選択された決済方式に固有の情報に基づいて、被決済者が表示された合計を更新できるようにします。例えば、選択された決済方式に関連付けられている請求先住所は、税金の計算(例えば、VAT)に影響を与える可能性があり、決済者が取引を完了する前にユーザ・インターフェースで合計を正確に表示することが望ましいです。同時に、決済完了前には、情報共有をできる限り少なくすることが望ましいです。したがって、ユーザが決済方式を変更する場合のステップ決済方式で定義する場合、PaymentMethodChangeEventmethodDetails属性を介して共有されるデータを最小限に抑えることが重要です。共有データを最小限に抑えるための要件とアプローチは、決済方式によって異なる可能性があります。

プライバシーに関わる情報の共有がユーザにとって明らかでない可能性がある場合(決済方式の変更を行う場合など)、ユーザ・エージェントは、どの情報が加盟店と共有されるかを正確にユーザに通知することをお勧めします(RECOMMENDED)。

14.8 canMakePayment()保護

canMakePayment()メソッドは、異なる決済方式に関する機能検出を提供します。将来、多数の決済方式を利用できるようになった場合、これは、フィンガープリントのベクトル(fingerprinting vector)になりえます。ユーザ・エージェントは、メソッドの悪用からユーザを保護することが期待されます。例えば、ユーザ・エージェントは、次の方法でユーザのフィンガープリントを減少させることができます。

レート制限に関し、ユーザ・エージェントは、次のものからの度重なる呼び出しに注目するかもしれません。

これらのレート制限技術は、複数の登録可能なドメインを管理するコストであるか、複数のウィンドウ(タブやポップアップ)を開くことによるユーザ体験上のフリクションであるかにかかわらず、度重なる呼び出しに関連するコストを増大させることを目的としています。

15. アクセシビリティに関する留意点

この項は非規範的です。

決済リクエストAPIのユーザ向けの側面に関し、実装はフォーム制御やその他の入力のモダリティーを介して、プラットフォームのアクセシビリティAPIと統合されます。

16. 依存関係

この仕様は、他のいくつかの基礎となる仕様に依存しています。

ECMAScript
内部スロットという用語は[ECMASCRIPT]で定義されています。

JSONシリアル化は、stringify()を実行し、供給されたオブジェクトを唯一の引数として渡し、その結果の文字列を返します。これは例外をスローることができます。

17. 適合性

非規範的と記している項と同じく、この仕様のすべての作成ガイドライン、図、例、注は、非規範的です。この仕様のその他の部分はすべて規範的です。

このドキュメントの「することができる/してもよい(MAY)」、「しなければならない(MUST)」、「してはならない(MUST NOT)」、「選択できる/任意である(OPTIONAL)」、「推奨される(RECOMMENDED)」、「すべきである/する必要がある(SHOULD)」、「すべきでない/する必要がない(SHOULD NOT)」というキーワードは、ここで示しているように、すべて大文字で表示されている場合にのみ、BCP 14 [RFC2119] [RFC8174]で記述されているように解釈されるべきです。

この仕様への適合性を主張できる種類の成果物は、ユーザ・エージェントのみです。

この仕様は主にウェブ・ブラウザを対象としていますが、他のソフトウェアでもこの仕様に適合した方法で実装することができます。

ユーザ・エージェントは、最終結果がこの仕様のアルゴリズムによって得られると思われる結果と区別できない限り、この仕様で示しているアルゴリズムを、任意の望ましい方法で実装することができます(MAY)。

ユーザ・エージェントは、サービス拒否攻撃の防止、メモリ不足の防止、プラットフォーム固有の制限の回避などのために、その他の点で制約のない入力に対して実装固有の制限を課すことができます(MAY)。入力が実装固有の制限を超えた場合、ユーザ・エージェントは、TypeErrorをスローするか、プロミスの場合はそれを用いて拒否しなければならず(MUST)、オプションで、特定の入力がどのように実装固有の制限を超えたかを開発者に通知します。

A. IDL索引

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

  readonly attribute DOMString id;

  attribute EventHandler onpaymentmethodchange;
};

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

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

dictionary PaymentDetailsBase {
  sequence<PaymentItem> displayItems;
  sequence<PaymentDetailsModifier> modifiers;
};

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

dictionary PaymentDetailsUpdate : PaymentDetailsBase {
  PaymentItem total;
  object paymentMethodErrors;
};

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

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

enum PaymentComplete {
  "fail",
  "success",
  "unknown"
};

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

  readonly attribute DOMString requestId;
  readonly attribute DOMString methodName;
  readonly attribute object details;

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

dictionary PaymentValidationErrors {
  DOMString error;
  object paymentMethod;
};

[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 Platform Incubator Community Group)が以前に発表した報告書から派生したものです。

C. 変更履歴

CR2とPRの間の変更

CR1とCR2の間の変更

D. 参考文献

D.1 規範的な参考文献

[dom]
DOM Standard. Anne van Kesteren. WHATWG. Living Standard. URL: https://dom.spec.whatwg.org/
[ecma-402]
ECMAScript Internationalization API Specification. Ecma International. URL: https://tc39.es/ecma402/
[ECMASCRIPT]
ECMAScript Language Specification. Ecma International. URL: https://tc39.es/ecma262/multipage/
[fetch]
Fetch Standard. Anne van Kesteren. WHATWG. Living Standard. URL: https://fetch.spec.whatwg.org/
[HTML]
HTML Standard. Anne van Kesteren; Domenic Denicola; Ian Hickson; Philip Jagenstedt; Simon Pieters. WHATWG. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[infra]
Infra Standard. Anne van Kesteren; Domenic Denicola. WHATWG. Living Standard. URL: https://infra.spec.whatwg.org/
[ISO4217]
Currency codes - ISO 4217. ISO. 2015. International Standard. URL: http://www.iso.org/iso/home/standards/currency_codes.htm
[payment-handler]
Payment Handler API. Adrian Hope-Bailie; Ian Jacobs; Rouslan Solomakhin; Jinho Bang; Jason Normore; Tommy Thorsen; Adam Roach. W3C. 4 October 2021. W3C Working Draft. URL: https://www.w3.org/TR/payment-handler/
[payment-method-id]
Payment Method Identifiers. Marcos Caceres. W3C. 30 September 2021. W3C Proposed Recommendation. URL: https://www.w3.org/TR/payment-method-id/
[permissions-policy]
Permissions Policy. Ian Clelland. W3C. 16 July 2020. W3C Working Draft. URL: https://www.w3.org/TR/permissions-policy-1/
[RFC2119]
Key words for use in RFCs to Indicate Requirement Levels. S. Bradner. IETF. March 1997. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc2119
[RFC4122]
A Universally Unique IDentifier (UUID) URN Namespace. P. Leach; M. Mealling; R. Salz. IETF. July 2005. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc4122
[RFC8174]
Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words. B. Leiba. IETF. May 2017. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc8174
[url]
URL Standard. Anne van Kesteren. WHATWG. Living Standard. URL: https://url.spec.whatwg.org/
[WEBIDL]
Web IDL Standard. Edgar Chen; Timothy Gu. WHATWG. Living Standard. URL: https://webidl.spec.whatwg.org/

D.2 参考情報の参考文献

[rfc6454]
The Web Origin Concept. A. Barth. IETF. December 2011. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc6454
[secure-contexts]
Secure Contexts. Mike West. W3C. 18 September 2021. W3C Candidate Recommendation. URL: https://www.w3.org/TR/secure-contexts/