# Apple Pay

> How to accept Apple Pay with the V2 SDK (2.1.1) — requirements, steps, example, payment sheet data and common problems.

- kind: guide
- status: stable
- sdk_version: 2.1.1
- last_verified: 2026-10-21
- url: https://tilopay.com/en/developers/sdk/apple-pay

## What it is [#que-es]

The SDK draws the Apple Pay button inside your form, opens Apple's payment sheet and processes
the payment with Apple's encrypted token. The buyer does not type the card.

## Requirements [#requisitos]

| Requirement | Detail |
|---|---|
| Production account | In testing mode the button does not appear and `applePaySupported` is `false`: it cannot be tested in testing mode. |
| Payment method with Apple Pay | In `init.methods` the method has `apple_pay = 1`. If your method does not, the button is not shown. |
| Certified domain | The domain must be certified for Apple Pay in your Tilopay account. The match is exact: `www.comercio.com` and `comercio.com` are different domains. To certify it, write to soporte@tilopay.com with the exact domain. |
| HTTPS | The page is served over HTTPS. |
| Browser | Safari on an Apple device with Apple Pay set up. |
| Cards | Visa, Mastercard or American Express. |

## Steps [#pasos]

1. Load the [v2 SDK](/en/developers/sdk/instalacion).
2. Inside `.payFormTilopay` add `<div id="tlpy_apple_pay_button_div"></div>` where the button
   goes and, optionally, `<input type="hidden" id="tlpy_apple_pay_cancel">` to know when the
   buyer closes the sheet (its value changes to `"cancelled"` and fires `change`).
3. Call [`Init()`](/en/developers/sdk/reference/init) as usual (token, currency, amount, order,
   billing, `capture` and `redirect`). `applePaySupported: true` means the requirements are met
   for that domain and browser.
4. Fill `#tlpy_payment_method` with `init.methods`.
5. The button appears when the select fires the `change` event with a method that has Apple
   Pay. If you select the method from code, fire
   `select.dispatchEvent(new Event('change'))`.
6. When the button is tapped, the SDK opens Apple Pay and, once the buyer authorizes, processes
   the payment: if approved it redirects to `redirect`; if the bank asks for 3DS it shows it in
   `#responseTilopay`.

> **Note:** The card fields are still required. `tlpy_cc_number`, `tlpy_cc_expiration_date` and
> `tlpy_cvv` must be in the HTML even if the buyer pays with Apple Pay, because the SDK
> initializes them in `Init()`.

## Example [#ejemplo]

```html
<div class="payFormTilopay">
  <select id="tlpy_payment_method" name="tlpy_payment_method"></select>
  <select id="tlpy_saved_cards" name="tlpy_saved_cards"></select>
  <input type="text" id="tlpy_cc_number" name="tlpy_cc_number" />
  <input type="text" id="tlpy_cc_expiration_date" name="tlpy_cc_expiration_date" />
  <input type="text" id="tlpy_cvv" name="tlpy_cvv" />

  <div id="tlpy_apple_pay_button_div"></div>
  <input type="hidden" id="tlpy_apple_pay_cancel" />
</div>

<div id="responseTilopay"></div>

<script src="https://app.tilopay.com/sdk/v2/sdk_tpay.min.js"></script>
<script>
  (async () => {
    const init = await Tilopay.Init({
      token: "<token_del_sdk>",
      currency: "CRC",
      language: "en",
      amount: 100.0,
      billToEmail: "ana@ejemplo.com",
      orderNumber: "ORD-2026-000124",
      billToFirstName: "Ana",
      billToLastName: "Rojas",
      capture: 1,
      redirect: "https://ejemplo.com/resultado",
    });

    console.log("applePaySupported:", init.applePaySupported);

    const select = document.getElementById("tlpy_payment_method");
    init.methods.forEach((m) => select.add(new Option(m.name, m.id)));
    select.dispatchEvent(new Event("change"));

    document.getElementById("tlpy_apple_pay_cancel").addEventListener("change", (e) => {
      if (e.target.value === "cancelled") console.log("The buyer closed Apple Pay");
    });
  })();
</script>
```

## Apple Pay sheet data [#hoja]

| Field | Value |
|---|---|
| Country | `CR` |
| Currency | The one from `Init()`, uppercase |
| Networks | `visa`, `mastercard` and `amex` |
| Capability | `supports3DS` |
| Label | `Tilopay: <merchant name>` |
| Amount | The one from `Init()` |

## Behavior to keep in mind [#comportamiento]

- The Apple Pay payment result **is not returned to your code** (the button calls the SDK
  directly): it arrives on the `redirect` URL like any payment. Confirm it with
  `POST /api/v1/consult` from your server. See [confirm the result](/en/developers/sdk#confirmar).
- You can only listen for cancellation, with `tlpy_apple_pay_cancel`.
- If the payment fails, the sheet stays open until the buyer closes it or it expires, and the
  detail is logged in the browser console.

## Common problems [#problemas]

| Symptom | Cause and fix |
|---|---|
| `applePaySupported` is `false` | Account in testing mode, no method with `apple_pay = 1`, browser without Apple Pay or uncertified domain. When it is the domain, the console shows `Apple Pay not allowed for this domain`. |
| `applePaySupported` is `true` but the button does not appear | The div is not inside `.payFormTilopay`, the selected method has no Apple Pay or the select did not fire `change`. |
| It works on one domain but not with `www` | Certify the other form too, or always use the certified one. |
| The button opens the sheet and it closes right away | Merchant validation with Apple failed: check that the domain certification is current and write to soporte@tilopay.com with the domain and the time. |
| The buyer authorizes and the sheet keeps loading | The payment failed: check the console and look up the transaction by order number. |
