> ## 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.

# Alternative payment methods

> Klarna, iDEAL, PayPal, BLIK and the rest — which processor charges them, and how the redirect lifecycle works.

# Alternative payment methods

An **alternative payment method** (APM) is anything that is not a card and not a wallet: bank
redirects, buy-now-pay-later, e-wallets and vouchers. They all share one property that shapes your
integration:

<Warning>
  **APMs are asynchronous.** The charge call does not return a final result — it returns a redirect
  URL. The shopper authorises on the provider's page, comes back, and the real outcome arrives on a
  webhook. Never treat the charge response as a completed payment.
</Warning>

## Availability

| Method              | `code`       | TagadaPay | Stripe | Airwallex | Coverage               |
| ------------------- | ------------ | :-------: | :----: | :-------: | ---------------------- |
| iDEAL               | `ideal`      |     ✓     |    ✓   |     ✓     | NL · EUR               |
| Bancontact          | `bancontact` |     ✓     |    ✓   |     ✓     | BE · EUR               |
| Klarna              | `klarna`     |     ✓     |    ✓   |     ✓     | EU · US · AU · CA      |
| Afterpay / Clearpay | `afterpay`   |     ✓     |    ✓   |     ✓     | AU · CA · NZ · US · GB |
| Affirm              | `affirm`     |     ✓     |    ✓   |     —     | US · CA · GB           |
| PayPal              | `paypal`     |     ✓     |    —   |     ✓     | Worldwide              |
| TWINT               | `twint`      |     ✓     |    ✓   |     ✓     | CH · CHF               |
| BLIK                | `blik`       |     ✓     |    ✓   |     —     | PL · PLN               |
| EPS                 | `eps`        |     ✓     |    —   |     —     | AT · EUR               |
| Przelewy24          | `p24`        |     ✓     |    —   |     —     | PL · PLN               |
| Multibanco          | `multibanco` |     ✓     |    —   |     —     | PT · EUR               |
| KNET                | `knet`       |     ✓     |    —   |     —     | KW · KWD               |
| Fawry               | `fawry`      |     ✓     |    —   |     —     | EG · EGP               |
| Sofort              | `sofort`     |     ✓     |    —   |     —     | DE · AT · BE · NL · GB |
| Skrill              | `skrill`     |     ✓     |    —   |     ✓     | EU · GB · US           |

<Info>
  The **TagadaPay** column is the managed catalogue. Which of those methods your specific account
  can charge depends on your configuration and region — resolve it at runtime with `paymentSetup`,
  never from this table.
</Info>

### Not supported

These come up often enough to be worth stating plainly. There is no integration for them today:
Alipay, WeChat Pay, GrabPay, Swish, Vipps, MobilePay, Satispay, Trustly, MB WAY, Cash App Pay,
Giropay and Neteller.

**Bank debits are also not available.** SEPA Direct Debit and ACH appear in some older material and
in our internal type definitions, but no processor can charge them today — treat them as
unsupported until this page says otherwise.

<Note>
  Giropay and Sofort are being retired by their own schemes across the industry. Sofort remains
  chargeable on the managed catalogue; Giropay is not.
</Note>

## The three shapes of an APM

Not all APMs behave the same once the shopper commits.

<CardGroup cols={3}>
  <Card title="Bank redirect" icon="building-columns">
    iDEAL, Bancontact, EPS, Przelewy24, Sofort. The shopper authorises in their bank. Funds are
    guaranteed on confirmation.
  </Card>

  <Card title="Buy now, pay later" icon="calendar">
    Klarna, Afterpay, Affirm. The provider underwrites the shopper. Usually needs line items and a
    billing address to get approved.
  </Card>

  <Card title="Voucher" icon="receipt">
    Multibanco, Fawry. The shopper gets a reference and pays later, in cash or at a bank. Settlement
    can take days — the order stays pending.
  </Card>
</CardGroup>

<Warning>
  **Vouchers do not settle at checkout.** A Fawry or Multibanco order is unpaid until the shopper
  goes and pays it, which may never happen. Do not fulfil on the redirect — fulfil on the webhook.
</Warning>

## The redirect lifecycle

<Steps>
  <Step title="Charge with an explicit method">
    Send `paymentMethod` + `processorId` + `customerId` + `returnUrl`, and **no**
    `paymentInstrumentId` — the absence of an instrument is what makes it a redirect APM charge.

    ```ts theme={null}
    const { payment } = await tagada.payments.process({
      amount: 4999,
      currency: 'EUR',
      storeId: 'store_xxx',
      customerId: 'cus_xxx',
      paymentMethod: 'ideal',
      processorId: 'proc_xxx',
      returnUrl: 'https://store.example/checkout/return',
    });
    ```
  </Step>

  <Step title="Handle requireAction">
    A successful APM charge comes back **pending**, carrying a redirect.

    ```ts theme={null}
    const redirectUrl = payment.requireActionData?.metadata?.redirect?.redirectUrl;
    if (redirectUrl) {
      // Hand this URL to the shopper's browser.
    }
    ```
  </Step>

  <Step title="The shopper returns to your returnUrl">
    Treat this as "the shopper came back", not "the payment succeeded". They may have abandoned,
    failed, or simply hit the back button.
  </Step>

  <Step title="Confirm on the webhook">
    The provider's confirmation is the only authoritative result. Fulfil there.

    ```ts theme={null}
    // payment.succeeded / payment.failed
    ```

    See [Webhooks & events](/developer-tools/node-sdk/webhooks-events).
  </Step>
</Steps>

### BLIK needs a code

BLIK is the exception to "redirect and wait". The shopper generates a six-digit code in their
banking app and types it into your checkout, and you send it with the charge. The code rides the
checkout-session pay path (plugin-sdk shown):

```ts theme={null}
await tagada.payments.processPaymentDirect(checkoutSessionId, paymentInstrumentId, undefined, {
  paymentMethod: 'blik',
  processorId: 'proc_xxx',
  blikCode: '123456',
});
```

### Fawry needs a basket

Fawry is a cash voucher, so the shopper has to be reachable and the basket itemised. A charge
without `lineItems`, an email and a phone number is rejected before it leaves us.

## Discovery

Do not hard-code the table above into a checkout. Ask what the store has enabled:

<CodeGroup>
  ```ts core-js (browser) theme={null}
  import { getStorePaymentSetup } from '@tagadapay/core-js';

  const setup = await getStorePaymentSetup({
    storeId: 'store_xxx',
    apiKey: 'tp_pk_live_***',
  });

  const apms = Object.values(setup.config).filter((m) => m.type === 'apm' && m.enabled);
  ```

  ```ts node-sdk (server) theme={null}
  const setup = await tagada.paymentSetup.get('store_xxx');
  const apms = Object.values(setup.config).filter((m) => m.type === 'apm' && m.enabled);
  ```
</CodeGroup>

### The config shape

Keys are **two-dimensional**. A method routed through exactly one provider is keyed by its own
name; a method available through several is keyed `method:provider`.

```jsonc theme={null}
{
  "klarna":        { "enabled": true, "method": "klarna", "provider": "tagada",  "type": "apm" },
  "klarna:stripe": { "enabled": true, "method": "klarna", "provider": "stripe",  "type": "apm",
                     "processorId": "proc_xxx", "publishableKey": "pk_live_***" },
  "ideal":         { "enabled": false, "method": "ideal", "provider": "tagada",  "type": "apm" }
}
```

| Field            | Meaning                                             |
| ---------------- | --------------------------------------------------- |
| `enabled`        | Whether the shopper can pick it right now           |
| `method`         | The logical method (`klarna`, `ideal`, …)           |
| `provider`       | Which infrastructure charges it                     |
| `type`           | `card`, `apm` or `wallet` — use it to group your UI |
| `processorId`    | Pass this back on the charge to pin the route       |
| `publishableKey` | Present when the method needs a client-side SDK     |

## Recurring payments

<Warning>
  **Do not build a subscription on an APM.** Almost every APM here authorises one specific amount,
  once. There is no stored credential to rebill against, so the second charge has nothing to use.
</Warning>

If a funnel mixes a subscription product with an APM, either hide the APM for that cart or collect
a card for the renewals. Cards and wallets are the reusable instruments — see
[Wallets](/developer-tools/payments/wallets#recurring-and-wallets).

## Refunds

Refunds are issued against the **processor**, not the method:

```ts theme={null}
await tagada.payments.refund({ paymentIds: ['pay_xxx'], amount: 1999 });
```

Two caveats worth designing around:

* A voucher that has not settled yet cannot be refunded — there is no money to return.
* Some BNPL providers reverse the shopper's instalment plan on their own schedule, so the shopper
  may see the refund later than your dashboard does.

## Next

<CardGroup cols={3}>
  <Card title="Support matrix" icon="table" href="/developer-tools/payments/support-matrix">
    Filter every method by processor.
  </Card>

  <Card title="Apple Pay & Google Pay" icon="wallet" href="/developer-tools/payments/wallets">
    Wallets follow different rules.
  </Card>

  <Card title="From the SDKs" icon="code" href="/developer-tools/payments/sdk-usage">
    `processApm`, `payments.process` and friends.
  </Card>
</CardGroup>
