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

# Accept a payment in the browser

> Collect a card or a wallet and confirm a Payments API payment with @tagadapay/core-js/payments-v3.

> [!NOTE]
>
> **Preview.** The Payments API (V3) is live at `https://api.tagada.io/v1`, but it is not open to self-serve integrations yet: merchant secret keys cannot be created from the dashboard. Every merchant processes on [V2](https://docs.tagada.io/payments-api/v2-or-v3.md) today. Contact [api-support@tagadapay.com](mailto:api-support@tagadapay.com) if you plan a new integration.

`@tagadapay/core-js/payments-v3` is the browser client of the Payments API. It ships inside `@tagadapay/core-js` since **3.7.0**. It holds a publishable key and one payment's `client_secret`, and it:

* mounts secure card fields and Apple Pay or Google Pay buttons,
* turns them into a payment method (`inst_...`),
* confirms the payment and performs every [`next_action`](https://docs.tagada.io/payments-api/payment-lifecycle#next_action) (3DS, redirects, wallet steps),
* reads the payment and handles the return from a redirect.

It never creates a payment: your server does, with a secret key.

## Install

```bash theme={null}
npm install @tagadapay/core-js@^3.7.0
```

## 1. Create the payment on your server

Create the payment with your secret key and hand its `client_secret` to the page. See [Payment lifecycle](https://docs.tagada.io/payments-api/payment-lifecycle.md#create-on-the-server).

## 2. Load the client

```typescript theme={null}
import { loadPayments } from '@tagadapay/core-js/payments-v3';

const tp = await loadPayments({ publishableKey: 'tpk_test_...' });
```

| Option | Description |
| - | - |
| `publishableKey` | Required. `tpk_live_...` or `tpk_test_...`. Any other value is refused. |
| `locale` | Language of the messages the client shows. |
| `apiBase` | Defaults to `https://api.tagada.io`. |
| `fetch` | A custom `fetch` implementation. |

`loadPayments` reads the store's configuration (`GET /v1/client-config`) before it resolves. Your page's origin must be in the key's `allowed_origins`.

## 3. Collect a card and confirm

```typescript theme={null}
const fields = await tp.cardFields(document.getElementById('card')!);

payButton.addEventListener('click', async () => {
  if (!fields.isComplete) return;
  const method = await tp.createPaymentMethod({ card: fields });

  const payment = await tp.confirmPayment({
    clientSecret,
    paymentMethod: method.id,
    returnUrl: 'https://shop.example.com/checkout/return',
    billingDetails: { name: 'Jane Doe', email: 'jane@example.com' },
  });

  if (payment.status === 'succeeded' || payment.status === 'requires_capture') {
    showSuccess();
  } else if (payment.status === 'failed') {
    showError(payment.last_outcome?.reason);
  }
});
```

* `cardFields` loads the vault's fields on demand. They never expose the card number to your page.
* `createPaymentMethod` refuses incomplete fields and fields created by another client instance.
* `confirmPayment` does not tokenize a card by itself: create the payment method first.
* Send `billingDetails` when you have them: 3DS providers need the cardholder's name and email.

## Wallets

```typescript theme={null}
const button = await tp.walletButton('apple_pay', document.getElementById('wallet')!, {
  amount: 1999,
  currency: 'USD',
  country: 'US',
  label: 'Example Shop',
});

button.on('authorize', async (authorization) => {
  const method = await tp.createPaymentMethod({ wallet: authorization.wallet });
  const payment = await tp.confirmPayment({ clientSecret, paymentMethod: method.id });
  authorization.complete(payment.status === 'failed' ? 'failure' : 'success');
});
button.on('error', (error) => console.error(error.code));
```

Use `'google_pay'` for Google Pay. A shopper who closes the sheet is not an error. The wallet must be enabled in the store's configuration.

## Redirect methods

For a redirect method (PayPal, Klarna, iDEAL...), confirm with the method type instead of an `inst_` id:

```typescript theme={null}
await tp.confirmPayment({ clientSecret, paymentMethod: 'paypal', returnUrl: 'https://shop.example.com/checkout/return' });
```

The client navigates to the provider. On your return page, report the return:

```typescript theme={null}
const payment = await tp.handleReturn({ clientSecret });
```

Pass `redirect: 'manual'` to `confirmPayment` if you want the `requires_action` payment back instead of an automatic navigation.

## Other methods

| Method | Use |
| - | - |
| `retrievePayment({ clientSecret })` | Read the payment. |
| `handleNextAction({ clientSecret })` | Perform the pending action of a payment your server confirmed (for example an upsell). |
| `retryPayment({ clientSecret })` | After a decline, create a new payment. Returns `{ payment, clientSecret }`: use the new secret from then on. |

## What you get back

The methods return a `PublicPayment`: `id`, `object`, `mode`, `status`, `amount`, `currency`, `purpose`, `payment_method_type`, `next_action`, `last_outcome`, `saved_payment_method`, `statement_descriptor`, `created_at`, `concluded_at`. It never includes the client secret.

> [!WARNING]
>
> A resolved promise does not mean the payment succeeded. Check `status`. Fulfil orders from your server after reading the payment with your secret key.

## Errors

| Class | Raised when |
| - | - |
| `ApiError` | The API answered with an [error](https://docs.tagada.io/payments-api/errors.md). Has `status` and `code`. |
| `NetworkError` | The API did not answer. |
| `FieldValidationError` | Card fields are incomplete or invalid. |
| `NextActionError` | A 3DS, redirect or wallet step failed. |
| `UnsupportedNextActionError` | The payment needs a `next_action` this version does not handle. |
| `PaymentsJsError` | The base class of all of the above. |

The client retries network errors, `429`, `500`, `502`, `503`, `504` and `idempotency_key_in_progress` up to two times, with the same `Idempotency-Key`. Every request sends `Payments-Version` and `X-Tagada-SDK`.


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