> ## Documentation Index
> Fetch the complete documentation index at: https://docs.overflow.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Wallets

> Accept Apple Pay and Google Pay, standalone or inside Checkout.

Wallet elements (`applePay`, `googlePay`) render a native payment button that opens the wallet sheet on tap. The sheet drives the flow: the shopper authorizes, the SDK receives a cryptogram, and `onSubmit` fires with the tokenized payload ready for your server.

## Availability

Wallets probe device availability at mount time. Availability depends on the shopper's device, browser, wallet configuration, and (for Apple Pay) merchant certificate. Handle both outcomes.

```javascript theme={null}
const applePay = overflow.applePay();

applePay.on('onChange', ({ available }) => {
  applePayBtn.hidden = !available;
});

applePay.on('onReady', () => {
  console.log('Apple Pay ready');
});

applePay.mount('#apple-pay');
```

* On an unavailable device, `onChange` fires with `{ available: false, reason }` and `onReady` is suppressed. Hide the button and, if you want, render a non-wallet fallback.
* On an available device, `onChange` fires with `{ available: true }`, the button mounts, then `onReady` fires.

Availability is environment-only. It does not require a provisioned card in the wallet; the wallet sheet handles "no card" by letting the shopper add one.

## Request contact details from the sheet

Ask the wallet sheet to return shopper contact and address fields by setting `require`:

```javascript theme={null}
overflow.applePay({
  transaction: { amount: 5000, currency: 'USD' },
  require: {
    email: true,
    name: true,
    phone: true,
    billingAddress: true,
    shippingAddress: true,
  },
});
```

Requested fields land on `onSubmit.value` as optional keys once the shopper authorizes:

```javascript theme={null}
applePay.on('onSubmit', async ({ value }) => {
  await fetch('/your-backend/authorize', {
    method: 'POST',
    body: JSON.stringify({
      email: value.email,           // present when require.email was true
      name: value.name,             // { firstName, lastName }
      phone: value.phone,           // raw sheet string
      billingAddress: value.billingAddress,
      shippingAddress: value.shippingAddress,
      paymentMethod: {
        type: value.walletType === 'applePay' ? 'applepay' : 'googlepay',
        walletToken: value.walletToken,
      },
    }),
  });
});
```

Fields the sheet did not return are omitted from `value` (never `null`).

## Gate the sheet with `onClick`

Subscribe to `onClick` to validate external state before the sheet opens. The handler receives a gate primitive: call `preventDefault()` to interrupt the default action, then `resolve()` to let the sheet open or `reject()` to cancel.

```javascript theme={null}
applePay.on('onClick', (event) => {
  event.preventDefault();
  if (cart.total <= 0) {
    event.reject();
    return;
  }
  event.resolve();
});
```

Skipping `preventDefault()` opens the sheet immediately. Calling `reject()` fires no `onError`; a deliberate cancellation is not a failure.

### Apple Pay synchronous constraint

Safari validates that the call that opens the Apple Pay sheet runs in the same synchronous task as the originating click. `await` between `preventDefault()` and `resolve()` invalidates the user gesture and the sheet fails to open, silently.

Apple Pay handlers that need to gate must do so synchronously: read pre-validated state from a local variable rather than awaiting a network call.

Google Pay does not have this restriction; asynchronous gating works fine.

## Handle sheet dismissal with `onExit`

When the shopper dismisses the wallet sheet without authorizing, `onExit` fires. This is not an error; it is a deliberate dismissal.

```javascript theme={null}
applePay.on('onExit', () => {
  showPaymentMethodPicker();
});
```

Use `onExit` to track abandonment, re-show a payment-method picker, or restore prior UI state.

## Handle failures with `onError`

Sheet errors mid-flow surface through `onError` with `code: 'wallet_failed'`:

```javascript theme={null}
applePay.on('onError', ({ code, message }) => {
  if (code === 'wallet_failed') toast(message);
});
```

Note: `available: false` on `onChange` is not an error. `onError` is reserved for actual mid-flow failures.

## Wallets inside Checkout

When a wallet is one of the tabs inside a `checkout` element, `onClick` fires with an additional `paymentMethod` discriminator so a single handler can branch on which wallet was tapped:

```javascript theme={null}
checkout.on('onClick', (event) => {
  if (event.paymentMethod === 'applePay') {
    // Apple Pay: gate synchronously.
    event.preventDefault();
    if (cart.total <= 0) { event.reject(); return; }
    event.resolve();
  } else {
    // Google Pay: async gating is fine.
    event.preventDefault();
    reserveInventory().then((ok) => ok ? event.resolve() : event.reject());
  }
});
```

Checkout's `onExit` fires with the same `paymentMethod` discriminator so you can distinguish which sheet the shopper dismissed.

## See also

* [Apple Pay reference](/payment-elements/elements/payment-methods/wallets/apple-pay)
* [Google Pay reference](/payment-elements/elements/payment-methods/wallets/google-pay)
* [`onClick`](/payment-elements/events/on-click)
* [`onExit`](/payment-elements/events/on-exit)
* [Wallets reference](/payment-elements/elements/payment-methods/wallets/reference)
