From 19de401a480e8f79b5e9473a48b6a541b431ce8a Mon Sep 17 00:00:00 2001 From: Stephen McGruer Date: Wed, 4 Mar 2026 08:59:14 -0500 Subject: [PATCH 1/2] Allow web-based payment handlers to report back internal error See #428 and https://github.com/w3c/payment-request/issues/1040 --- index.html | 113 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 72 insertions(+), 41 deletions(-) diff --git a/index.html b/index.html index d92812c..d67fb9a 100644 --- a/index.html +++ b/index.html @@ -1334,8 +1334,21 @@

"PaymentHandlerResponse">

PaymentHandlerResponse dictionary -

The PaymentHandlerResponse is conveyed using the following - dictionary: + +

+ The user agent receives a successful response from the web-based + payment handler through resolution of the Promise provided to the + {{PaymentRequestEvent/respondWith}} function of the corresponding + {{PaymentRequestEvent}} interface. The application is expected to + resolve the Promise with a PaymentHandlerResponse instance + containing the payment response. In case of user cancellation or + error, the application may signal failure by rejecting the Promise. +

+ +

+ The PaymentHandlerResponse is conveyed using the following dictionary: +

+
           dictionary PaymentHandlerResponse {
           DOMString methodName;
@@ -1365,29 +1378,6 @@ 

method specific message used by the merchant to process the transaction and determine successful fund transfer.

-

- The user agent receives a successful response from the web-based - payment handler through resolution of the Promise provided to the - {{PaymentRequestEvent/respondWith}} function of the corresponding - {{PaymentRequestEvent}} interface. The application is expected to - resolve the Promise with a PaymentHandlerResponse instance - containing the payment response. In case of user cancellation or - error, the application may signal failure by rejecting the Promise. -

-

- If the Promise is rejected, the user agent MUST run the - payment app failure algorithm. The exact details of this - algorithm are left to implementers. Acceptable behaviors include, - but are not limited to: -

-
    -
  • Letting the user try again, with the same web-based payment - handler or with a different one. -
  • -
  • Rejecting the Promise that was created by PaymentRequest.show(). -
  • -

@@ -1519,10 +1509,10 @@

  • Increment the |event|'s pending promises count by one.
  • - Upon rejection of handlerResponsePromise: + Upon rejection of handlerResponsePromise with |reason|:
      -
    1. Run the payment app failure algorithm and terminate - these steps. +
    2. Run the payment app failure algorithm with |reason|, and + terminate these steps.
  • @@ -1531,8 +1521,8 @@

    1. Let handlerResponse be |value| converted to an IDL value {{PaymentHandlerResponse}}. If this throws an - exception, run the payment app failure algorithm and - terminate these steps. + exception, run the payment app failure algorithm with an + {{"OperationError"}} {{DOMException}}, and terminate these steps.
    2. Validate that all required members exist in handlerResponse and are well formed. @@ -1542,7 +1532,8 @@

      present or not set to one of the values from |event|.methodData, run the - payment app failure algorithm and terminate these + payment app failure algorithm with an + {{"OperationError"}} {{DOMException}}, and terminate these steps.

    3. If handlerResponse. handlerResponse.shippingAddress is not present, run the payment app failure algorithm - and terminate these steps. + with an {{"OperationError"}} {{DOMException}}, and terminate + these steps.
    4. If shippingRequired and handlerResponse. not present or not set to one of shipping options identifiers from |event|.shippingOptions, - run the payment app failure algorithm and terminate - these steps. + run the payment app failure algorithm with an + {{"OperationError"}} {{DOMException}}, and terminate these + steps.
    5. Let payerNameRequired be the requestPayerName @@ -1574,8 +1567,9 @@

      paymentOptions. If payerNameRequired and handlerResponse.payerName is not - present, run the payment app failure algorithm and - terminate these steps. + present, run the payment app failure algorithm with an + {{"OperationError"}} {{DOMException}}, and terminate these + steps.

    6. Let payerEmailRequired be the requestPayerEmail @@ -1583,8 +1577,9 @@

      paymentOptions. If payerEmailRequired and handlerResponse.payerEmail is not - present, run the payment app failure algorithm and - terminate these steps. + present, run the payment app failure algorithm with an + {{"OperationError"}} {{DOMException}}, and terminate these + steps.

    7. Let payerPhoneRequired be the requestPayerPhone @@ -1592,8 +1587,9 @@

      paymentOptions. If payerPhoneRequired and handlerResponse.payerPhone is not - present, run the payment app failure algorithm and - terminate these steps. + present, run the payment app failure algorithm with an + {{"OperationError"}} {{DOMException}}, and terminate these + steps.

    @@ -1629,7 +1625,8 @@

  • If any exception occurs in the above step, then run the - payment app failure algorithm and terminate these + payment app failure algorithm with an + {{"OperationError"}} {{DOMException}}, and terminate these steps.
  • Assign methodName to associated @@ -1737,6 +1734,40 @@

    reconciliation after network or other failures.

  • +
    +

    + Payment App Failure Algorithm +

    +

    + When this algorithm is invoked with |reason|, the user agent MUST run + the following steps: +

    +
      +
    1. + If |reason| is an {{"OperationError"}} {{DOMException}}, then run + the Payment handler indicates an internal error algorithm as + defined in [[!payment-request]]. +
    2. +
    3. + Otherwise, run the user aborts the payment request algorithm + as defined in [[!payment-request]]. + +

      + Previous versions of this specification did not define what + happened when the payment app failure algorithm was + invoked. In practice, implementors acted as if the + user aborts the payment request algorithm was run. + + To maintain as much backwards compatibility as possible, while + still introducing a way for web-based payment handlers to indicate + internal error, this specification now maps all |reason|s other + than a {{"OperationError"}} {{DOMException}} to user abort. Future + versions of this specification may add additional handled |reason| + types. +

      +
    4. +
    +
    From 20f5584f0167f0d1ee26c1cc4454b3d946b80639 Mon Sep 17 00:00:00 2001 From: Stephen McGruer Date: Wed, 4 Mar 2026 09:03:03 -0500 Subject: [PATCH 2/2] Fixup --- index.html | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/index.html b/index.html index d67fb9a..30921c6 100644 --- a/index.html +++ b/index.html @@ -1760,10 +1760,9 @@

    To maintain as much backwards compatibility as possible, while still introducing a way for web-based payment handlers to indicate - internal error, this specification now maps all |reason|s other + internal error, this specification now maps all reason values other than a {{"OperationError"}} {{DOMException}} to user abort. Future - versions of this specification may add additional handled |reason| - types. + versions of this specification may add additional handled values.