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

# Wallet Block

> Embed Apple Pay and Google Pay for a connected account, with automatic payment confirmation.

The Wallet Block adds Apple Pay and Google Pay to your platform's payment page.
The buyer approves the wallet sheet and Ionic confirms the existing [PaymentIntent](/concepts/key-concepts#how-the-objects-connect)
automatically. Your application receives the payment result; it does not handle
wallet tokens or call confirmation after wallet approval.

## Before mounting

Complete the [Connect Blocks integration](/guides/connect-blocks) and
[wallet setup for your payment domain](/guides/platform-wallets). Ionic must have
enabled Wallet Blocks for your environment. Use an HTTPS page and a positive,
fixed-total PaymentIntent with automatic capture, owned by the receiving merchant.
The merchant needs complete business name and country information.

This release supports platform-connected, one-time payments. It does not save
wallet credentials, create SetupIntents, activate subscriptions, or calculate
shipping/tax inside the wallet sheet. Keep the Payment Block for card payments
and optional card saving. Direct merchants' legacy Apple Pay settings do not
enable this platform Wallet Block.

## Mount the block

Use the platform publishable key and the same receiving merchant and client secret
as the card integration. The server creates the PaymentIntent and owns its amount
and currency. Wallet sheet values are not browser configuration options.

```html theme={null}
<div id="wallet"></div>
<div id="payment"></div>
<button id="pay-card" type="button">Pay by card</button>
<p id="message" role="status" aria-live="polite"></p>
```

```typescript theme={null}
import { loadIonic } from '@ionicfi/js';

// These values come from your authenticated checkout backend.
const response = await fetch('/checkout/payment', { method: 'POST' });
if (!response.ok) throw new Error('Could not load this payment.');
const { publishableKey, connectedMerchantId, clientSecret } =
  await response.json() as {
    publishableKey: string;
    connectedMerchantId: string;
    clientSecret: string;
  };
const ionic = await loadIonic(publishableKey, { account: connectedMerchantId });
const blocks = ionic.blocks({ clientSecret });
const wallet = blocks.create('wallet');
const message = document.querySelector('#message')!;

wallet.on('complete', ({ paymentIntent, wallet }) => {
  message.textContent = 'Payment complete.';
  // Update the receipt using paymentIntent.id. Confirm fulfillment on your server.
});
wallet.on('error', (error) => {
  message.textContent = error.message;
});
wallet.on('change', ({ availableWallets, busy }) => {
  // Optional: show a divider only when at least one wallet button is rendered.
});

document.querySelector('#pay-card')!.addEventListener('click', async () => {
  const result = await ionic.confirmPayment({ blocks });
  message.textContent = result.error?.message ??
    (result.paymentIntent?.status === 'succeeded' ? 'Payment complete.' : 'Checking payment…');
});

// Mount independently so optional wallet loading cannot hold up card collection.
await Promise.all([
  wallet.mount('#wallet'),
  blocks.create('payment').mount('#payment'),
]);

// On navigation: blocks.destroy(). To remove only wallets: wallet.destroy().
```

One group supports one Wallet Block and one Payment Block. Wallet-only mounting
is also supported. Use `blocks.create('wallet', { wallets: ['google_pay'] })` to
restrict displayed wallets; this preference cannot enable an unready wallet.

## Availability and payment recovery

`ready` means initialization finished; `change.availableWallets` lists the buttons
actually rendered. Apple availability depends on browser/device support. A rendered
Google Pay button does not prove the buyer already has a supported card. The block
collapses when no wallet is available. Registration errors stay in platform setup,
and the card form remains available if wallet loading fails.

Wallet and card confirmation share one payment attempt. While a wallet result is
unknown or processing, the card form stays locked and the Wallet Block provides
**Check payment status**. It retrieves the same intent and, where necessary,
retries the original request with the original idempotency key. Do not create a new
PaymentIntent to recover an unknown result. Only `succeeded` emits `complete`.
After a decline, Ionic refreshes wallet collection for a new approval. Wallet
configuration expires after five minutes. Expired buttons are retired and the
block offers **Refresh payment options** before another approval. An unresolved
payment keeps **Check payment status** and its original attempt. A changed
configuration requires fresh approval before the Wallet Block can proceed.

Wallet settings control availability in Blocks. They do not revoke previously
issued payment tokens or restrict payment methods across the existing payment API.

Keep fulfillment authoritative on your backend using the merchant's PaymentIntent
and webhooks. Browser events never replace that confirmation.

## Page integration requirements

Wallet buttons run on your page; card inputs remain in Ionic's isolated frame.
If your page sends a Content Security Policy, allow the
[Ionic origins used by Blocks](/guides/payment-fields#content-security-policy),
`https://applepay.cdn-apple.com` for the Apple Pay button script, and inline
button styles. The wallet buttons may need other origins allowlisted. If a
wallet button does not load while you test your integration, contact Ionic
support for the origins to add. Do not replace or restyle the Apple Pay or
Google Pay logos.

Mount on the registered top-level platform page. A surrounding custom iframe adds
wallet permissions and domain requirements and is outside this release's validated
integration. For a different receiving merchant, use a full page navigation. The
Wallet Block supports one wallet configuration per page, so another wallet
integration cannot run on the same page as this block.

### Recover an interrupted payment

Keep the same PaymentIntent when a response is lost or the page reloads. While
this Block remains mounted, **Check payment status** can recover the original
request using its existing key. Expired wallet options do not prevent recovery of
that submitted payment. After reload, the Block reads the stored intent; server
reconciliation and webhooks establish the result. A confirmed decline makes
payment options available again, without submitting another payment for you.

Creating a separate PaymentIntent is a separate payment. The previous payment
can still succeed, so creating another intent is not a recovery step.

## What's next

<CardGroup cols={2}>
  <Card title="Refund and capture" icon="rotate-left" href="/guides/connect-refunds-captures">
    Refund, capture, or cancel a connected account's payment from your platform.
  </Card>

  <Card title="Handle webhooks" icon="tower-broadcast" href="/guides/connect-webhooks">
    Receive every connected account's events on one endpoint and match each to its connected account.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.