Re: [w3c/payment-request] Allow payment handlers to report back errors via Payment Request API (PR #1050)

marcoscaceres left a comment (w3c/payment-request#1050)

Alternative, building on @stephenmcgruer proposal:
https://github.com/w3c/payment-request/pull/1050/commits/236c39b6a6aa579c130b8b8b9e4c780536212cca

PayPal's SDK exposes `onError` and `onCancel` callbacks to merchants. Currently, the Payment Request API returns `AbortError` for both user cancellation AND payment handler errors, forcing PayPal to parse `error.message` strings that vary by browser version.

## Proposed Solution

Use the existing WebIDL `OperationError` DOMException type to distinguish payment handler errors from user cancellation (`AbortError`).

## Two `OperationError` Cases

### Case 1: OS-Level Error
When the operating system kills the payment UI (e.g., memory pressure when user switches apps):

```
User opens payment sheet → Switches to another app → 
OS kills payment UI for memory → OperationError
```

This is **not** user cancellation - the user didn't intentionally close the sheet.

### Case 2: Payment Handler Internal Error  
When the payment handler encounters an error during processing:

```
User selects PayPal → PayPal server returns 500 → 
PayPal handler signals error → OperationError
```

This is **not** user cancellation - the payment failed due to a technical issue.

## Backwards Compatibility

**Self-healing approach:**
1. PayPal continues using message-based detection for old browsers
2. New browsers will throw `OperationError` instead of `AbortError`
3. PayPal can add `error.name === "OperationError"` check
4. Code naturally works in both old and new browsers:

```javascript
function handlePaymentError(error) {
  // New path: check error type first
  if (error.name === "OperationError") {
    this.onError(error);
    return;
  }
  
  // Legacy path: message-based detection for old browsers
  if (error.name === "AbortError") {
    const cancelMessages = [
      "Request cancelled",
      "User closed the Payment Request UI."
    ];
    if (cancelMessages.some(m => error.message?.includes(m))) {
      this.onCancel();
    } else {
      this.onError(error);
    }
  }
}
```


-- 
Reply to this email directly or view it on GitHub:
https://github.com/w3c/payment-request/pull/1050#issuecomment-3983746014
You are receiving this because you are subscribed to this thread.

Message ID: <w3c/payment-request/pull/1050/c3983746014@github.com>

Received on Monday, 2 March 2026 11:18:03 UTC