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

# Checkout Web integration

This guide helps you get started with the Checkout SDK on web browsers.

<Info>
  **Prerequisite**

  * A Mangopay ClientId and API key (get a Sandbox API key for free)
  * A User and their associated Wallet to complete the pay-in
  * A card to register or payment method setup (see [Testing - Payment methods](/testing/payment-methods) for testing information)

  **Supported browsers:** Chrome 117, Firefox 118, Safari 16, or higher
</Info>

{/* To support you with your integration, be sure to make use of our <a href="https://github.com/Mangopay/mangopay-checkout-web/tree/main/examples" target="_blank">example app</a> on GitHub, which has a <a href="https://checkout-demo-mangopay.netlify.app/">deployed demo</a>. */}

## Installation

You can install the Mangopay Checkout SDK using [npm](https://www.npmjs.com/package/@mangopay/checkout-sdk) or yarn.

Install with npm:

```shell theme={null}
npm install --save @mangopay/checkout-sdk
```

Install with yarn:

```shell theme={null}
yarn add @mangopay/checkout-sdk
```

#### Install via CDN

If you are using script tags to load files, include the Mangopay SDK script in your HTML:

```html theme={null}
<script src="https://checkout.mangopay.com/sdk/checkout-sdk.min.js"></script>
```

<Warning>
  **Warning – Load script from Mangopay Checkout domain**

  To maintain PCI compliance, the script must be loaded directly from the Mangopay Checkout domain:

  > http<span>://</span>checkout.mangopay.com

  The script must not be bundled or hosted on other domains. You must reference it directly from our domain.
</Warning>

### Content Security Policy (CSP)

<Warning>
  **Caution - Allow policies if using CSP**

  If your web page is using the Content-Security-Policy response header, you need to allow the policies below.
</Warning>

<table>
  <thead>
    <tr>
      <th class="header">Policy</th>
      <th class="header">URLs</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td class="table-content">script-src</td>
      <td class="table-content">\*.google.com</td>
    </tr>

    <tr>
      <td class="table-content">connect-src</td>

      <td class="table-content">
        api.mangopay.com

        api.sandbox.mangopay.com

        \*.payline.com
      </td>
    </tr>
  </tbody>
</table>

## Initialization

Initialize the SDK and specify the configuration options.

```javascript Example - Initialization theme={null}
import { CheckoutSdk } from '@mangopay/checkout-sdk';

const mangopaySdk = await CheckoutSdk.loadCheckoutSdk(elementOrSelector, options);
```

### Initialization parameters

<table>
  <thead>
    <tr>
      <th class="header">Property</th>
      <th class="header">Type</th>
      <th class="header">Description</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td class="table-content">`elementOrSelector`</td>

      <td class="table-content">
        HTMLElement | String
        **REQUIRED**
      </td>

      <td class="table-content">The container element or the selector of the container element.</td>
    </tr>

    <tr>
      <td class="table-content">`options`</td>

      <td class="table-content">
        Object \
        **REQUIRED**
      </td>

      <td class="table-content">The options of the Checkout SDK configuration.</td>
    </tr>
  </tbody>
</table>

### options

The child parameters of the `options` object parameter:

<table>
  <thead>
    <tr>
      <th class="header">Property</th>
      <th class="header">Type</th>
      <th class="header">Description</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td class="table-content">`clientId`</td>

      <td class="table-content">
        String
        **REQUIRED**
      </td>

      <td class="table-content">The unique identifier associated with the Mangopay API key, giving access to the Mangopay API.</td>
    </tr>

    <tr>
      <td class="table-content">`environment`</td>
      <td class="table-content">String</td>

      <td class="table-content">
        The Mangopay environment. \
        **Allowed values:** SANDBOX, PRODUCTION\
        **Default values:** SANDBOX
      </td>
    </tr>

    <tr>
      <td class="table-content">`profilingMerchantId`</td>

      <td class="table-content">
        String
        **REQUIRED**
      </td>

      <td class="table-content">The unique identifier associated with your fraud protection package. Contact Mangopay to obtain this value.</td>
    </tr>

    <tr>
      <td class="table-content">`amount`</td>

      <td class="table-content">
        String
        **REQUIRED**
      </td>

      <td class="table-content">
        Information about the debited funds.

        The currency (ISO\_4217 format) and value (expressed in minor units) of the debited funds.
      </td>
    </tr>

    <tr>
      <td class="table-content">`paymentMethods`</td>

      <td class="table-content">
        Array
        **REQUIRED**
      </td>

      <td class="table-content">
        The payment methods presented to the user.

        Array of objects detailing the `type` and configuration `options` for specific payment methods. Each payment method includes configuration options tailored to its specific requirements.
      </td>
    </tr>

    <tr>
      <td class="table-content">`respectPaymentMethodsOrder`</td>
      <td class="table-content">Boolean</td>

      <td class="table-content">
        Controls how payment methods are ordered and which one is initially active.

        When `true`, the SDK renders methods in the order provided by `paymentMethods` and the first item in that array becomes the initial selection.

        When `false` (default), `card` is rendered first and used as the initial selection; other methods are rendered in an order determined by the SDK.

        **Default value:** `false`
      </td>
    </tr>

    <tr>
      <td class="table-content">`branding`</td>
      <td class="table-content">Object</td>
      <td class="table-content">The custom branding of the payment page (see Customization section below).</td>
    </tr>

    <tr>
      <td class="table-content">`locale`</td>
      <td class="table-content">String | Object</td>
      <td class="table-content">The language for the payment page. Specify one of the built-in languages (`en`, `fr`) or send an object with custom messages (see Customization section below).</td>
    </tr>

    <tr>
      <td class="table-content">`tenantId`</td>
      <td class="table-content">String</td>

      <td class="table-content">
        The Mangopay tenant being used by the platform. Platforms that have contracted with Mangopay’s UK entity must set the value to `UK`.

        **Allowed values:** `EU`, `UK`
        **Default value:** `EU`
      </td>
    </tr>

    <tr>
      <td class="table-content">`clientToken`</td>
      <td class="table-content">String</td>

      <td class="table-content">
        A token used to authenticate and enable specific SDK features. Today, only [PayPal One-Click](#configuring-paypal-one-click-payments) requires a `clientToken` (PayPal without One-Click and other payment methods do not require it).

        Obtain the `clientToken` from your server before initializing the SDK - see the [PayPal One-Click](#configuring-paypal-one-click-payments) section for details.
      </td>
    </tr>
  </tbody>
</table>

## Configuration

Configure the MangopayCheckout parameters and delegates.

### Example - Vanilla JS

```html HTML  theme={null}
<body>
    <div id="checkoutForm">
        <div id="container"></div>
    </div>
    <script src="/index.js"></script>
</body>
```

```javascript JavaScript theme={null}
window.addEventListener('load', async () => {
    const mangopaySdk = await CheckoutSdk.loadCheckoutSdk('#container', options);
    if (!mangopaySdk) {
        throw new Error('Failed to load MangopayCheckoutSdk');
    }

    mangopaySdk.on('error', (event: CustomEvent<ErrorEventDetails>) => console.error(event.detail));

    mangopaySdk.on('tokenizationComplete', (event: CustomEvent<TokenizationCompleteEventDetails>) => {
        // handle tokenization complete
    });

    mangopaySdk.on('paymentComplete', (event: CustomEvent<PaymentCompleteEventDetails>) => {
        // handle payment complete
    });
});
```

### Example - ReactJS

```javascript JavaScript theme={null}
import { MangopayCheckout } from '@mangopay/checkout-sdk-react';

const CheckoutComponent = () => {

  const sdkRef = useRef(null);

  const onTokenizationComplete = () => {
      /* Handle Card/GooglePay/ApplePay token here
             e.g charge customer card using CardId
      */
  };

  const onPaymentComplete = () => {
      /* Handle Card/PayPal payment complete */
  };

  const onCancel = () => {
      /* Handle cancellation of payment  */
  };

  return (
    <MangopayCheckout
      ref={sdkRef}
      options={options}
      disabled={disabled}
      onError={onError}
      onLoaded={onLoaded}
      onChange={onChange}
      onTokenizationComplete={onTokenizationComplete}
      onPaymentComplete={onPaymentComplete}
      onCancel={onCancel}
    />
  )
}

```

### MangopayCheckout parameters

<table>
  <thead>
    <tr>
      <th class="header">Property</th>
      <th class="header">Type</th>
      <th class="header">Description</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td class="table-content">`ref`</td>
      <td class="table-content">React.RefObject\<MangopayCheckoutForwardedRef></td>
      <td class="table-content">React reference object: `import { MangopayCheckoutForwardedRef } from '@mangopay/checkout-sdk-react';`</td>
    </tr>

    <tr>
      <td class="table-content">`onPaymentComplete`</td>
      <td class="table-content">Function(event)</td>
      <td class="table-content">Triggered when the transaction is completed, whatever the outcome (whether successful or failed).</td>
    </tr>

    <tr>
      <td class="table-content">`options`</td>
      <td class="table-content">Object</td>
      <td class="table-content">Checkout SDK configuration options</td>
    </tr>

    <tr>
      <td class="table-content">`disabled`</td>
      <td class="table-content">Boolean</td>
      <td class="table-content">Applies a disabled state to the Checkout component such that user input is not accepted.</td>
    </tr>

    <tr>
      <td class="table-content">`onError`</td>
      <td class="table-content">Function(event)</td>
      <td class="table-content">Triggered when an internal SDK error has occurred.</td>
    </tr>

    <tr>
      <td class="table-content">`onLoaded`</td>
      <td class="table-content">Function(event)</td>
      <td class="table-content">Triggered when the Checkout SDK is loaded.</td>
    </tr>

    <tr>
      <td class="table-content">`onChange`</td>
      <td class="table-content">Function(event)</td>
      <td class="table-content">Triggered when data exposed by the Checkout SDK is changed.</td>
    </tr>

    <tr>
      <td class="table-content">`onTokenizationComplete`</td>
      <td class="table-content">Function(event)</td>

      <td class="table-content">
        Triggered when:

        * A card tokenization is completed and a `CardId` is returned.
        * The user authorizes a Google Pay or Apple Pay payment.
      </td>
    </tr>

    <tr>
      <td class="table-content">`onPaymentComplete`</td>
      <td class="table-content">Function(event)</td>
      <td class="table-content">Triggered when the transaction is completed, whatever the outcome (whether successful or failed).</td>
    </tr>

    <tr>
      <td class="table-content">`onCancel`</td>
      <td class="table-content">Function()</td>
      <td class="table-content">Triggered when the payment process is canceled by the user. This can occur when the 3D Secure authentication window or PayPal, Google Pay, or Apple Pay popup is closed before completion.</td>
    </tr>
  </tbody>
</table>

## Updating options

After the SDK has been initialized you can update the options without needing to fully reinitialize again by using the `updateOptions` method. Make sure you pass a complete updated `options` object as specified in the Configuration section.

```js theme={null}
import { CheckoutSdk } from '@mangopay/checkout-sdk';
const mangopaySdk = await CheckoutSdk.loadCheckoutSdk('#container', options);
// update options
mangopaySdk.updateOptions({...options, amount: {...options.amount, value: updatedValue});
```

## Handling redirection

<Warning>
  **Warning – Use Mangopay Checkout domain as return URL**

  When making the pay-in request from your backend, use the Mangopay Checkout URL as the `SecureModeReturnURL` or `ReturnURL` (depending on the payment method):

  > http<span>://</span>checkout.mangopay.com

  The user must be returned to this URL after redirection.
</Warning>

Some payment methods (card, Google Pay, PayPal) require or may require the user to be redirected to authorize or complete a transaction.

The Checkout SDK allows you to manage the entire payment flow seamlessly while retaining control over transaction logic in your backend. Once a payment method is selected and payment details are provided, use the `options.onCreatePayment` function to request the transaction from your backend.

Subsequently, and when necessary for the transaction type, the Checkout SDK seamlessly manages additional redirect actions for 3DS authorization or otherwise validating the payment.

To manage transaction redirects effectively with the SDK:

<Steps>
  <Step title="Define onCreatePayment">
    In your `paymentMethods` configurations, define an `options.onCreatePayment` attribute as a function.
  </Step>

  <Step title="Within your function:">
    * Request a transaction from your server and subsequently, Mangopay.
    * Return the unaltered transaction response object to the SDK.
  </Step>

  <Step title="The SDK:">
    * Redirects the user to the payment authentication page when necessary.
    * Manages payment provider redirects back to the SDK.
    * Triggers the `onPaymentComplete` event with the ID and status of the transaction.
    * Confirms the redirect result on your server by invoking the corresponding GET API of the transaction.
    * Presents the payment result to the user.
  </Step>
</Steps>

```js theme={null}
paymentMethods: [
    {
        type: 'card | paypal | googlepay',
        onCreatePayment: function (event) {
            // 1. implement server-side call to request a transaction.
            // 2. return the card transaction object.
        }
    }
]
```

## Configuring card payments

To configure the card payment method, specify `card` as the `type` of the `paymentMethods` object. For the `options`, use the following configuration parameters.

### options

<table>
  <thead>
    <tr>
      <th class="header">Property</th>
      <th class="header">Type</th>
      <th class="header">Description</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td class="table-content">`options.supportedCardBrands`</td>
      <td class="table-content">Array
      **REQUIRED**</td>

      <td class="table-content">
        The card brands supported.\
        **Allowed values:** VISA, MASTERCARD, AMEX, MAESTRO, CB
      </td>
    </tr>

    <tr>
      <td class="table-content">`options.onCreateCardRegistration`</td>
      <td class="table-content">Function
      **REQUIRED**</td>
      <td class="table-content">Use this attribute to request and return a Card Registration.</td>
    </tr>

    <tr>
      <td class="table-content">`options.onCreatePayment`</td>
      <td class="table-content">Function
      **REQUIRED**</td>
      <td class="table-content">To handle 3DS redirects for card payments, use this attribute to request and return a pay-in.</td>
    </tr>

    <tr>
      <td class="table-content">`options.enableSaveCard`</td>
      <td class="table-content">Boolean</td>

      <td class="table-content">
        If set to `true`, a ***Save Card*** checkbox will appear in the UI. When checked, `SaveCard: true` will be returned in the `CreatePaymentData` object, and you can forward this flag to your backend for further handling (read more about [managing saved cards](#managing-saved-cards)).
      </td>
    </tr>

    <tr>
      <td class="table-content">`options.savedCards`</td>
      <td class="table-content">Array of `SavedCard`</td>

      <td class="table-content">
        A list of cards previously saved by the user. If provided, a button will appear within the card number input field that opens a dropdown of saved cards to select from.
      </td>
    </tr>

    <tr>
      <td class="table-content">`options.onDeactivateSavedCard`</td>
      <td class="table-content">Function</td>

      <td class="table-content">
        A callback that is triggered when the user chooses to deactivate a saved card. Receives an object containing `{ cardId: string }`. You can use this ID to inform your backend which card should be deactivated.
      </td>
    </tr>
  </tbody>
</table>

### Card configuration example

```typescript TypeScript theme={null}

export interface CreatePaymentData {
  Id: string;
  Tag: string;
  CreationDate: string;
  UserId: string;
  CardId: string;
  CardType: string;
  Currency: string;
  PreferredCardNetwork?: 'VISA' | 'MASTERCARD' | 'CB' | 'MAESTRO';
  ProfilingAttemptReference: string;
  SaveCard: boolean;
}

export interface SavedCard {
    Id: string;
    ExpirationDate: string;
    CreationDate: number;
    Alias: string;
    Tag?: string;
    CardProvider: CardBrand;
    CardType: string;
    Country: string;
    Product: string;
    BankCode: string;
    Active: boolean;
    Currency: string;
    Validity: string;
    UserId: string;
    CardHolderName: string;
    Fingerprint: string;
    PreferredCardNetwork?: CardBrand;
}

const options = {
    clientId: 'MANGOPAY_CLIENT_ID',
    environment: 'SANDBOX | PRODUCTION',
    amount: {
        value: 1000,
        currency: "EUR"
    },
    paymentMethods: [
        {
            type: 'card',
            enableSaveCard: true,  // show the “Save Card” checkbox
            savedCards: [
                {
                    Id: '12345',
                    ExpirationDate: '1026',
                    CreationDate: 1692817000,
                    Alias: 'XXXX XXXX XXXX 1234',
                    CardProvider: 'MASTERCARD',
                    CardType: 'CB_VISA_MASTERCARD',
                    Country: 'FR',
                    Product: 'Debit',
                    BankCode: '01234',
                    Active: true,
                    Currency: 'EUR',
                    Validity: 'VALID',
                    UserId: '67890',
                    CardHolderName: 'John Doe',
                    Fingerprint: 'fing3rpr1nt'
                }
            ],
            onDeactivateSavedCard: function({ cardId }) {
                // 1. Call your server to remove card and deactivate in Mangopay API
            },
            onCreateCardRegistration: function (cardType: 'CB_VISA_MASTERCARD' | 'AMEX' | 'MAESTRO') {
                // 1. Implement server-side call to create a card registration.
                // 2. Return the card registration.
            },
            onCreatePayment: function (event: CreatePaymentData) {
                // 1. Implement server-side call to request a card transaction.
                // 2. Return the card transaction object.
                // 3. The SDK handles 3DS redirect for you.
            }
        }
    ]
};
const mangopaySdk = await CheckoutSdk.loadCheckoutSdk(elementOrSelector, options);
```

### Card tokenization

In the `options` for the card payment method, create a function to handle creation of Card Registration event handler in the `paymentMethods` object:

* Your `onCreateCardRegistration` function calls your server, and passes it the card brand of the user.
* Your server makes a request to [Create a Card Registration](/api-reference/card-registrations/create-card-registration).
* In response, your server receives a Card Registration object.
* In your `onCreateCardRegistration` function, return the unmodified Card Registration object to the SDK.
* The SDK [tokenizes the card](/api-reference/card-registrations/tokenize-card) and [updates the Card Registration](/api-reference/card-registrations/update-card-registration) object to create the `CardId` which is used for payment.

```typescript TypeScript theme={null}
// Vanilla JS
mangopaySdk.on('tokenizationComplete', (event: CustomEvent<TokenizationCompleteEventDetails>) => {
    // handle tokenization complete
});

mangopaySdk.on('paymentComplete', (event: CustomEvent<PaymentCompleteEventDetails>) => {
    // handle payment complete
});

// React.js
const onTokenizationComplete = () => {
    // handle tokenization complete
};

const onPaymentComplete = () => {
    // handle payment complete
};

<MangopayCheckout
    ref={sdkRef}
    options={options}
    onTokenizationComplete={onTokenizationComplete}
    onPaymentComplete={onPaymentComplete}
/>
```

### tokenizationComplete output

```json REST theme={null}
{
  "Id": "cardreg_m_01HQ0J6GB3JFZ1NC5EGCJBE4PB",
  "Tag": null,
  "CreationDate": 1708342329,
  "UserId": "user_m_01HP6ZG0XXZ89V34GRZEY9HQCE",
  "AccessKey": "1X0m87dmM2LiwFgxPLBJ",
  "PreregistrationData": "YkgVxL1yNY4ZOfKtqEew_Zj34Eg4_H3r-UyvrLWB_MHYF1OqkWAtDMwDMZ0pSZfliRF4hvSrtJCvT7-9XAi0Xsj7Q1OS-vT4lpHzEztZoLs",
  "RegistrationData": "data=iN_eoipU7i2AEuTss7wuoPRZYTuNVHlTvhc4dEXHczhSWquUg8N2vrbXU91rCDepo0Fw6rcqxRBK8KMWk8xhHGOBEuIr9_d-Xo64K6cr5w-lY2yXbTUOs7e-S6CpTShm",
  "CardId": "card_m_01HQ0J6H02QXH3HATEYW0FMJKP",
  "CardType": "CB_VISA_MASTERCARD",
  "CardRegistrationURL": "https://pci.sandbox.mangopay.com/api/mangopay/vault/tokenize/eyJjbGllbnQiOiJjbGllbnRJZCIsInRva2VuIjoidW5xaXVlVG9rZW4ifQ==",
  "ResultCode": "000000",
  "ResultMessage": "Success",
  "Currency": "EUR",
  "Status": "VALIDATED",
  "ProfilingAttemptReference": "25e5c450-7f00-4805-af04-4330e4dc0cee"
}
```

### Requesting card pay-ins

You can use a registered card (`CardId`) for requests with the following API objects:

* [The Card Validation object](/api-reference/card-validations/card-validation-object), to validate a card without debit
* [The Direct Card PayIn object](/api-reference/direct-card-payins/direct-card-payin-object), for one-shot card payments
* [The Recurring PayIn Registration object](/api-reference/recurring-payin-registrations/recurring-payin-registration-object), for recurring card payments
* [The Preauthorization object](/api-reference/preauthorizations/preauthorization-object), for 7-day preauthorized card payments
* [The Deposit Preauthorization object](/api-reference/deposit-preauthorizations/deposit-preauthorization-object), for 30-day preauthorized card payments

In your requests:

* Ensure that the `SecureModeReturnURL` parameter is set to `https://checkout.mangopay.com`
* Submit the `PreferredCardNetwork` value if it was received by `onCreatePayment`

### Managing saved cards

The Checkout SDK can allow the user to save their card for a future payment.

<Steps>
  <Step title="Enable saving cards">
    To enable saving cards, set `enableSaveCard` to `true` to present a ***Save card*** checkbox on the user interface.
  </Step>

  <Step title="Deactivate if card not saved">
    If the user doesn’t check the box, then the `CreatePaymentData` object returns `SaveCard : false`. In this case, you must systematically call [PUT Deactivate or edit a Card](/api-reference/cards/deactivate-edit-card) to deactivate it in the Mangopay API.
  </Step>

  <Step title="If saved, store tokenized card in your system">
    If the user checks the box, the `SaveCard` flag is set to `true` and passed to your `onCreatePayment` handler. You can then store the card object in your system.
  </Step>

  <Step title="Re-use saved cards">
    To present the user's saved cards in the next payment session, send an array of card objects in the `savedCards` array in the payment method configuration.

    If sent, then a dropdown appears in the interface in the card number input field. When a saved card is selected, the SDK uses it for the payment process.
  </Step>

  <Step title="Deactivate card if user removes it">
    In the dropdown, there is an option for the user to remove a saved card. In this case, the `onDeactivateSavedCard` is triggered and you must:

    * Remove the card in your system
    * Call [PUT Deactivate or edit a Card](/api-reference/cards/deactivate-edit-card) to deactivate it in the Mangopay API

    <Warning>
      **Caution - Deactivate card systematically unless user saves it**

      Under no circumstances should card information be kept without the end user's approval.

      If `CreatePaymentData` returns `SaveCard : false`, indicating the user doesn't wish to save it, then you must call [PUT Deactivate or edit a Card](/api-reference/cards/deactivate-edit-card) to deactivate it in the Mangopay API.

      The same is true if the `onDeactivateSavedCard` is triggered, indicating that the user wishes to remove the card.
    </Warning>
  </Step>
</Steps>

### Diagram - Saved cards

The following diagram shows the flow of managing saved cards:

<div>
  <iframe width="100%" height="700" src="https://cdn.swimlanes.io/dist/embeded.html#fZBNbsIwEIX3OcVbAiWwRwWpgkpFbdWIwAGGZCgpiY3scVB3vUNv2JPUDj8iEu0qVubNe9+8ZSElj5BSzTkyMrnFz9c3nvQBheCgzc5G0cqyuY/j6ZaznXaCdPY8QmLYshLs6bMK3402VaOM40lb+aiETWOOnIWK0oKUTwsiaAOnjs9erxc4GqV/3zZL3boqLqnR9RDxBElJEkh8au3nI2g1NUzCyQmzc+bNSQh3zeXTgCbG8XBDpeVudHZpOy4401542UBNpeOW+JXUu/YJeEjmvqK3dIljPHz+XGEYaiMnW3QWLM6o1eJlnJ1uGFSn7UGmq2507YW4RRL++Pr3Wln+A3a+uYCOw2l92HO30OsPzuQf8OvlppI+ktUSM6ZMijqcE0a/#fZB0a" />
</div>

#### Saved card example

```typescript TypeScript theme={null}
const options = {
  amount: {
    value: 1000,
    currency: 'EUR'
  },
  paymentMethods: [
    {
      type: 'card',
      enableSaveCard: true, // display the "Save Card" checkbox
      savedCards: [
        {
          Id: '12345',
          Alias: '497010XXXXXX8183',
          ExpirationDate: '1026',
          CardProvider: 'MASTERCARD',
          Active: true,
          UserId: '67890',
          Validity: 'VALID',
          CardType: 'CB_VISA_MASTERCARD',
          Country: 'FRA',
          Product: 'I',
          BankCode: 'unknown',
          Currency: 'EUR',
          Tag: null,
          CreationDate: 1744280826,
          Fingerprint: '48d63bbcfc2c47fcbc19df35e47b2f8d',
          CardHolderName: 'John Doe'
        }
      ],
      onDeactivateSavedCard: function({ cardId }) {
        // 1. Call your server to remove card and deactivate in Mangopay API
      },
      onCreatePayment: function (event) {
        // 1. Check if event.SaveCard === true
        // 2. Deactivate if false
      }
    }
  ]
};

// Vanilla JS
const mangopaySdk = await CheckoutSdk.loadCheckoutSdk('#container', options);

// React.js
<MangopayCheckout ref={sdkRef} options={options} />
```

## Configuring Apple Pay

<Note>
  **Note - Apple Pay integration required**

  Offering Apple Pay requires additional setup by the platform, including certification and integration. For more information, see the [Apple Pay guide](/guides/payment-methods/apple-pay).
</Note>

<Warning>
  **Caution - Apple Pay on the Web availability**

  [Apple Pay on the Web](https://developer.apple.com/documentation/apple_pay_on_the_web/), using the JavaScript Checkout SDK, is only available on Mac and iOS devices. Apple Pay on the Web also requires additional certification.
</Warning>

To configure the Apple Pay payment method, specify `apple_pay` as the `type` of the `paymentMethods` object. For the `options`, use the following configuration parameters.

### Apple Pay configuration options

<table>
  <thead>
    <tr>
      <th class="header">Property</th>
      <th class="header">Type</th>
      <th class="header">Description</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td class="table-content">`paymentRequest`</td>
      <td class="table-content">Object
      **REQUIRED**</td>
      <td class="table-content">The specifications of the payment request.</td>
    </tr>

    <tr>
      <td class="table-content">`onCreatePayment`</td>
      <td class="table-content">Function
      **REQUIRED**</td>
      <td class="table-content">Function called after the user has successfully authenticated a card for payment from the Apple Pay sheet. Use this attribute to implement backend creation of the <a href="/api-reference/apple-pay">Apple Pay PayIn</a> from your server. After creating the pay-in, return the pay-in object to the SDK.</td>
    </tr>
  </tbody>
</table>

#### paymentRequest

<table>
  <thead>
    <tr>
      <th class="header">Property</th>
      <th class="header">Type</th>
      <th class="header">Description</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td class="table-content">`countryCode`</td>
      <td class="table-content">String
      **REQUIRED**</td>
      <td class="table-content">The platform’s two-letter ISO 3166 country code.</td>
    </tr>

    <tr>
      <td class="table-content">`currencyCode`</td>
      <td class="table-content">String
      **REQUIRED**</td>
      <td class="table-content">The three-letter <a href="/api-reference/overview/data-formats" target="_blank">ISO 4217 code</a> (EUR, GBP, etc) of a <a href="/guides/currencies" target="_blank">supported currency</a> (depends on feature, contract, and activation settings).</td>
    </tr>

    <tr>
      <td class="table-content">`merchantCapabilities`</td>
      <td class="table-content">Array
      **REQUIRED**</td>
      <td class="table-content">Information about the card types and authentication protocols you support (see [Apple Pay documentation](https://developer.apple.com/documentation/apple_pay_on_the_web/applepaypaymentrequest/1916123-merchantcapabilities)).</td>
    </tr>

    <tr>
      <td class="table-content">`supportedNetworks`</td>
      <td class="table-content">Array
      **REQUIRED**</td>

      <td class="table-content">
        The card networks supported by Mangopay

        **[Allowed values](https://developer.apple.com/documentation/applepayontheweb/applepaypaymentrequest/supportednetworks):** `visa`, `masterCard`
      </td>
    </tr>

    <tr>
      <td class="table-content">`total`</td>
      <td class="table-content">Object
      **REQUIRED**</td>
      <td class="table-content">The line item total for the payment (see Apple Pay documentation).</td>
    </tr>

    <tr>
      <td class="table-content">`merchantIdentifier`</td>
      <td class="table-content">String
      **REQUIRED**</td>
      <td class="table-content">Your platform’s Apple Pay Merchant ID.</td>
    </tr>

    <tr>
      <td class="table-content">`merchantName`</td>
      <td class="table-content">String
      **REQUIRED**</td>
      <td class="table-content">The name of your platform.</td>
    </tr>

    <tr>
      <td class="table-content">`onValidateMerchant`</td>
      <td class="table-content">Function
      **REQUIRED**</td>
      <td class="table-content">Use this attribute to request and return a ApplePay session. Function called when the SDK receives an [onvalidatemerchant merchant event](https://developer.apple.com/documentation/apple_pay_on_the_web/applepaysession/1778021-onvalidatemerchant) from the Apple Pay sheet. The assigned function should implement backend creation of the [merchant session object](https://developer.apple.com/documentation/apple_pay_on_the_web/apple_pay_js_api/creating_an_apple_pay_session) from your server. After creating the session object, return the [session object](https://developer.apple.com/documentation/apple_pay_on_the_web/applepaysession#2930465) to the SDK.</td>
    </tr>

    <tr>
      <td class="table-content">`requiredBillingContactFields`</td>
      <td class="table-content">Array
      **REQUIRED**</td>
      <td class="table-content">The billing information to fulfill the order (see [Apple Pay documentation](https://developer.apple.com/documentation/apple_pay_on_the_web/applepaypaymentrequest/2216120-requiredbillingcontactfields)).</td>
    </tr>
  </tbody>
</table>

### Requesting the merchant session from your server

Displaying the Apple Pay payment sheet using the Mangopay Checkout SDK works as follows:

1. You generate the merchant session from your server
2. The SDK’s `onValidateMerchant` function calls your server and passes it the static hostname `apple-pay-gateway.apple.com` as the validation URL. In the China region, use `cn-apple-pay-gateway.apple.com`.
3. Your server uses the validation URL to request a session from the Apple Pay server, as described in [Requesting an Apple Pay Payment Session](https://developer.apple.com/documentation/apple_pay_on_the_web/apple_pay_js_api/requesting_an_apple_pay_payment_session).
4. In the response, your server receives an opaque merchant session object: `MerchantSession`.
5. You pass the merchant session object to the `completeMerchantValidation` method of the SDK (see [Apple Pay documentation](https://developer.apple.com/documentation/apple_pay_on_the_web/applepaysession/1778015-completemerchantvalidation) for more information on this method).

```javascript theme={null}
//Define ApplePay Merchant session delegate
const validateApplePayMerchant = (validationURL: string): Promise<ApplePayMerchantSession> => {
	return fetch(
    'https://backend-api-url/get-apple-pay-session',
    method: 'POST',
    body: JSON.stringify({
      validationURL,
      merchantIdentifier: 'merchant.com.example.mystore',
	    displayName: 'MyStore',
	    initiative: 'web',
	    initiativeContext: 'mystore.example.com'
    })
  );
};
```

### Requesting Apple Pay pay-in

To request the payment, use the [Create an Apple Pay PayIn](/api-reference/apple-pay/create-apple-pay-payin) endpoint and include the Apple Pay `PaymentData`.

1. Set up payment delegate – Assign a delegate function to the `onCreatePayment` attribute in your Apple Pay options.
2. Handle payment authorization – After the user successfully authorizes a card for payment through the Apple Pay sheet, the SDK will call your `onCreatePayment` function and pass the `PaymentData` to it.
3. Create pay-in – Implement the backend creation of the [Apple Pay PayIn](/api-reference/apple-pay/create-apple-pay-payin) on your server using the `PaymentData` provided.
4. Return pay-in object – After creating the pay-in, return the pay-in object to the SDK.

```javascript theme={null}
interface CreateApplePayPaymentData {
  PaymentData: {
    transactionId: string;
    network: string;
    tokenData: string;
  };
  ProfilingAttemptReference?: string;
}

//Define ApplePay PayIn delegate
const handleCreateApplePayPayIn = (data: CreateApplePayPaymentData): Promise<CreateApplePayPayInResult> => {
	return fetch(
    'https://backend-api-url/create-applepay-payin',
    method: 'POST',
    body: JSON.stringify(data)
  );
};
```

### Apple Pay configuration example

```typescript TypeScript theme={null}
const options = {
  clientId: 'MANGOPAY_CLIENT_ID',
	environment: 'SANDBOX | PRODUCTION',
	paymentMethods: [
		{
      type: 'apple_pay',
      options: {
        paymentRequest: {
          countryCode: 'IE',
          currencyCode: 'EUR',
          merchantCapabilities: ['supports3DS'],
          supportedNetworks: ['visa', 'masterCard'],
          total: {
            label: 'Demo (Card is not charged)',
            type: 'final',
            amount: '20.00',
          },
          merchantIdentifier: 'merchant.com.example.mystore',
          merchantName: 'MyStore',
          onValidateMerchant: validateApplePayMerchant,
          requiredBillingContactFields: ['email']
        },
        onCreatePayment: handleCreateApplePayPayIn
      },
    }
	]
};

// Vanilla JS
const mangopaySdk = await CheckoutSdk.loadCheckoutSdk(elementOrSelector, options);

// React.js
<MangopayCheckout ref={sdkRef} options={options} />
```

## Configuring Google Pay

<Note>
  **Note - Google Pay setup required**

  Offering Google Pay requires additional setup by the platform. For more information, see the [How to process a Google Pay payment](/guides/payment-methods/google-pay/how-to) tutorial.
</Note>

<Warning>
  **Caution - Add Mangopay Checkout to your Google Console**

  You need to add `checkout.mangopay.com` along with your domain to the authorized list in the Google Business Console to view the Google Pay payment popup.

  This allows the Checkout SDK to ensure the Google Pay experience is presented appropriately to your users. Not following this guidance may impact your payment acceptance on Google Pay.
</Warning>

To configure the Google Pay payment method, specify `google_pay` as the `type` of the `paymentMethods` object. For the `options`, use the following configuration parameters.

### Google Pay configuration options

<table>
  <thead>
    <tr>
      <th class="header">Property</th>
      <th class="header">Type</th>
      <th class="header">Description</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td class="table-content">`merchantInfo.merchantId`</td>
      <td class="table-content">String
      **REQUIRED**</td>
      <td class="table-content">Your Google Pay **Business ID**, which you can find in [Google Pay & Wallet Console](https://pay.google.com/business/console/profiles).</td>
    </tr>

    <tr>
      <td class="table-content">`merchantInfo.merchantName`</td>
      <td class="table-content">String
      **REQUIRED**</td>
      <td class="table-content">Your Google Pay **Business Name**, which you can find in [Google Pay & Wallet Console](https://pay.google.com/business/console/profiles).</td>
    </tr>

    <tr>
      <td class="table-content">`gateway`</td>
      <td class="table-content">String
      **REQUIRED**</td>

      <td class="table-content">
        The orchestration used: in this case, whenthen.\
        **Allowed values:** whenthen
      </td>
    </tr>

    <tr>
      <td class="table-content">`gatewayMerchantId`</td>
      <td class="table-content">String
      **REQUIRED**</td>
      <td class="table-content">Your Mangopay `ClientId`.</td>
    </tr>

    <tr>
      <td class="table-content">`cardParameters.allowedAuthMethods`</td>
      <td class="table-content">Array
      **REQUIRED**</td>

      <td class="table-content">
        The supported authentication methods: PAN\_ONLY, meaning the card is registered in the user’s Google account and requires additional authentication; CRYPTOGRAM\_3DS, meaning the card is enrolled in the customer’s Google Wallet and authentication is handled by Google, with no 3DS redirection and no liability for the platform.\
        **Allowed values:** PAN\_ONLY, CRYPTOGRAM\_3DS
      </td>
    </tr>

    <tr>
      <td class="table-content">`cardParameters.allowedCardNetworks `</td>
      <td class="table-content">Array
      **REQUIRED**</td>

      <td class="table-content">
        The card networks supported by Mangopay.

        **Allowed values:** VISA, MASTERCARD
      </td>
    </tr>

    <tr>
      <td class="table-content">`transactionInfo`</td>
      <td class="table-content">Object
      **REQUIRED**</td>

      <td class="table-content">
        Information about the transaction and its authorization, such as whether the user agrees to the transaction, the total price and price status. For more information on this object parameter, see the [Google Pay documentation](https://developers.google.com/pay/api/web/reference/request-objects#TransactionInfo).
      </td>
    </tr>

    <tr>
      <td class="table-content">`onCreatePayment`</td>
      <td class="table-content">Function
      **REQUIRED**</td>

      <td class="table-content">
        Function called after the user has successfully authorized a card for payment from the Google Pay sheet.

        The assigned function should implement backend creation of the [Google Pay PayIn](/api-reference/google-pay/create-google-pay-payin) from your server. After creating the pay-in, return the pay-in object to the SDK.
      </td>
    </tr>

    <tr>
      <td class="table-content">`button.buttonColor`</td>
      <td class="table-content">String</td>

      <td class="table-content">
        The color of the button.

        **Default value:** default

        **Allowed values:**

        * default – A Google-selected default value (currently black but it may change over time).
        * black – A black button suitable for use on white or light backgrounds.
        * white – A white button suitable for use on colorful backgrounds.
      </td>
    </tr>

    <tr>
      <td class="table-content">`button.buttonType`</td>
      <td class="table-content">String</td>

      <td class="table-content">
        The type of the button, determining the text to display.

        **Default value:** buy

        **Allowed values:**

        * book – The "Book with Google Pay" payment button.
        * buy – The "Buy with Google Pay" payment button.
        * checkout – The "Checkout with Google Pay" payment button.
        * donate – The "Donate with Google Pay" payment button.
        * order – The "Order with Google Pay" payment button.
        * pay – The "Pay with Google Pay" payment button.
        * plain – The Google Pay payment button without the additional text.
        * subscribe – The "Subscribe with Google Pay" payment button.
      </td>
    </tr>

    <tr>
      <td class="table-content">`button.buttonLocale`</td>
      <td class="table-content">String</td>

      <td class="table-content">
        The ISO 639-1 code representing the desired button language.

        **Default value:** The browser or operating system language settings.

        **Allowed values:** en, ar, bg, ca, cs, da, de, el, es, et, fi, fr, hr, id, it, ja, ko, ms, nl, no, pl, pt, ru, sk, sl, sr, sv, th, tr, uk, and zh.
      </td>
    </tr>
  </tbody>
</table>

### Obtaining Google Pay token

The `onTokenizationComplete` function is called after the user approves the payment on the Google Pay form. The output contains the `paymentData` object (see [Google Pay documentation](https://developers.google.com/pay/api/web/reference/response-objects#PaymentData)) which is needed to request the Google Pay payment via the API from your backend.

### Requesting Google Pay pay-in

To request the payment, use the [Create a Google Pay PayIn](/api-reference/google-pay/create-google-pay-payin) endpoint. Include the Google Pay `PaymentData` and ensure that the `SecureModeReturnURL` parameter is set to `https://checkout.mangopay.com`.

1. **Set up payment delegate** – Assign a delegate function to the `onCreatePayment` attribute in your Google Pay options.
2. **Handle payment authorization** – After the user successfully authorizes a card for payment through the Google Pay sheet, the SDK will call your `onCreatePayment` function and pass the `PaymentData` to it.
3. **Create pay-in** – Implement the backend creation of the [Google Pay PayIn](/api-reference/google-pay/create-google-pay-payin) on your server using the `PaymentData` provided.
4. **Return pay-in object** – After creating the pay-in, return the pay-in object to the SDK.

```javascript theme={null}
interface CreateGooglePayPaymentData {
  PaymentData: string;
  ProfilingAttemptReference: string;
}

//Define GooglePay PayIn delegate
const handleCreateGooglePayPayIn = (data: CreateGooglePayPaymentData): Promise<CreateGooglePayPayInResult> => {
	return fetch(
    'https://your-backend-api-url/create-googlepay-payin',
    method: 'POST',
    body: JSON.stringify(data)
  );
};
```

### Google Pay configuration example

```javascript theme={null}
const options = {
  clientId: 'MANGOPAY_CLIENT_ID',
	environment: 'SANDBOX | PRODUCTION',
	paymentMethods: [
		{
      type: 'google_pay',
      options: {
        merchantInfo: {
			    merchantId: 'test',
			    merchantName: 'Test',
			  },
				gateway: 'whenthen',
			  cardParameters: {
			    allowedAuthMethods: ['PAN_ONLY', 'CRYPTOGRAM_3DS'],
					allowedCardNetworks: ['VISA', 'MASTERCARD'],
			  },
			  transactionInfo: {
			    totalPrice: '20.00',
			    totalPriceStatus: 'FINAL',
			    currencyCode: 'EUR',
			    countryCode: 'DE', // required for EEA only
			    transactionId: '123456789',
			    totalPriceLabel: '20.00', // required if displayItems is provided
			    displayItems: [
			      {
			        label: 'PS5',
			        type: 'SUBTOTAL',
			        price: '20.00',
			      },
			    ],
			  },
			  paymentData: {
			    emailRequired: true,
			  },
			  onCreatePayment: (paymentData) => handleCreateGooglePayPayIn(paymentData),
        button: {
          buttonLocale: 'fr',
          buttonType: 'book'
        },
      },
    }
	]
};

// Vanilla JS
const mangopaySdk = await CheckoutSdk.loadCheckoutSdk(elementOrSelector, options);

// React.js
<MangopayCheckout ref={sdkRef} options={options} />
```

## Configuring PayPal

<Note>
  **Note – PayPal setup required**

  Offering PayPal requires approval from PayPal and activation. For more information, see the [PayPal](/guides/payment-methods/paypal) article.
</Note>

### PayPal configuration options

To configure PayPal, specify `paypal` as the `type` of the `paymentMethods` object. For the `options`, use the following configuration parameters.

<table>
  <thead>
    <tr>
      <th class="header">Property</th>
      <th class="header">Type</th>
      <th class="header">Description</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td class="table-content">`options.onCreatePayment`</td>
      <td class="table-content">Function
      **REQUIRED**</td>

      <td class="table-content">
        Use this attribute to request and return a PayPal pay-in.

        The assigned function should implement backend creation of the [PayPal pay-in](/api-reference/paypal/create-paypal-payin) from your server.
      </td>
    </tr>

    <tr>
      <td class="table-content">`options.merchantId`</td>
      <td class="table-content">string **REQUIRED**</td>

      <td class="table-content">
        Unique identifier for your PayPal business account, required to process pay-ins.

        * Production: Available in your PayPal Business Account Dashboard (***Account Settings*** > ***Business information*** > ***Business profile***, see <a href="https://www.paypal.com/us/cshelp/article/how-do-i-find-my-secure-merchant-id-on-my-paypal-account-help538" target="_blank">PayPal help</a>).
        * Sandbox: Contact our support team to obtain.
      </td>
    </tr>
  </tbody>
</table>

### PayPal configuration example

```javascript theme={null}
//Define PayPal PayIn delegate
const createPayPalPayIn = (profilingAttemptReference: string): Promise<CreatePayPalPayInResult> => {
	return fetch(
    'https://your-backend-api-url/create-paypal-payin',
    body: JSON.stringify({ProfilingAttemptReference: profilingAttemptReference})
  );
};

const options = {
    clientId: 'MANGOPAY_CLIENT_ID',
    environment: 'SANDBOX | PRODUCTION',
    amount: {
        value: 1000,
        currency: "EUR"
    },
    paymentMethods: [
        {
	        type: "paypal",
	        options: {
            merchantId: 'YOUR_PAYPAL_MERCHANT_ID', 
	          //define delegate to call when Paypal button is clicked
	          onCreatePayment: (data) => createPayPalPayIn(data)
	        }
	      }
    ]
};

const mangopaySdk = await CheckoutSdk.loadCheckoutSdk(elementOrSelector, options);

//this event is triggered when redirect/payment is completed
mangopaySdk.on('paymentComplete', (event: CustomEvent<PaymentCompleteEventDetails>) => {
    //  verify payment result
    //  unmount checkout and present payment result.
});
```

### Requesting PayPal pay-in

To request the payment, use the [POST Create a PayPal PayIn](/api-reference/paypal/create-paypal-payin) endpoint. Ensure that the `ReturnURL` parameter is set to `https://checkout.mangopay.com`.

## Configuring PayPal One-Click payments

PayPal One-Click allows returning customers to pay without re-entering their PayPal credentials. When enabled, the SDK displays a checkbox that lets customers opt in to save their PayPal account for future payments.

### How it works

1. You configure the SDK with the `clientToken` (root-level, see below) and `enableOneClick` set to `true` (PayPal options)
2. The SDK renders a checkbox allowing the customer to opt in for one-click payments
3. When the customer completes the payment, `onCreatePayment` receives a second boolean argument indicating if the checkbox was checked
4. If `true`, your backend creates a [Recurring PayIn Registration](/api-reference/recurring-payin-registrations/create-recurring-payin-registration-paypal) object and then a linked [CIT pay-in](/api-reference/paypal/create-recurring-paypal-payin-cit)
5. When the customer returns, the one-click payment experience is rendered automatically, allowing them to pay without logging in to PayPal
6. For the subsequent payments, you create a [non-recurring PayPal pay-in](/api-reference/paypal/create-paypal-payin)

### Prerequisites

Before implementing PayPal One-Click payments, you must have PayPal activated on your platform (see [PayPal setup requirements](/guides/payment-methods/paypal)).

#### Obtaining the clientToken

To initialize the SDK for PayPal One-Click, you need to obtain the `clientToken` as follows:

1. Contact Mangopay (<a href="https://hub.mangopay.com/" target="_blank">via the Dashboard</a>) to obtain a dedicated API key for use with `clientToken` features
2. From your server, call the [POST Create an OAuth bearer token](/api-reference/overview/authentication/create-oauth-token) endpoint using the API key (with Basic authentication, encoding the string `ClientId`:`ApiKey` in Base64)
3. Using the `access_token` returned from the previous step, from your server call the [POST Create an access token for Checkout SDK features](/api-reference/overview/authentication/create-access-token-checkout) using Bearer authentication

In response, the API returns another `access_token` which is the value to use as the `clientToken` when initializing the SDK for PayPal One-Click. The `clientToken` has a validity of 15 minutes, meaning the user must complete the transaction in that time.

### PayPal One-Click configuration options

<table>
  <thead>
    <tr>
      <th class="header">Property</th>
      <th class="header">Type</th>
      <th class="header">Description</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td class="table-content">`clientToken`</td>
      <td class="table-content">String **REQUIRED**</td>

      <td class="table-content">
        A token required for PayPal One-Click payments. This is a root-level SDK option (not part of the PayPal payment method options).
      </td>
    </tr>

    <tr>
      <td class="table-content">`options.enableOneClick`</td>
      <td class="table-content">Boolean</td>

      <td class="table-content">
        Set to `true` to enable the One-Click payment checkbox. When enabled, customers can opt in to save their PayPal account for future payments.

        **Default value:** `false`
      </td>
    </tr>

    <tr>
      <td class="table-content">`options.onCreatePayment`</td>
      <td class="table-content">Function **REQUIRED**</td>

      <td class="table-content">
        Function called when the customer initiates payment. Receives two arguments:

        * `profilingAttemptReference` – Reference for fraud profiling
        * `enableOneClick` – Boolean indicating if the customer checked the One-Click checkbox

        When `enableOneClick` is `true`, your backend should create a [Recurring PayIn Registration](/api-reference/recurring-payin-registrations/create-recurring-payin-registration-paypal) object and then a linked [CIT pay-in](/api-reference/paypal/create-recurring-paypal-payin-cit)
      </td>
    </tr>

    <tr>
      <td class="table-content">`options.merchantId`</td>
      <td class="table-content">String **REQUIRED**</td>

      <td class="table-content">
        Your PayPal merchant account identifier.

        You can find your `merchantId` in your PayPal Business Account Dashboard.
      </td>
    </tr>
  </tbody>
</table>

### Complete code example

```javascript theme={null}
// 1. Obtain clientToken from your backend
async function getClientToken() {
  const response = await fetch('/api/get-client-token');
  const data = await response.json();
  return data.clientToken;
}

// 2. Create PayPal payment on your backend
async function createPayPalPayment(profilingAttemptReference, enableOneClick) {
  const response = await fetch('/api/create-paypal-payment', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ 
      profilingAttemptReference,
      enableOneClick // If true, backend creates RecurringPayinRegistration + CIT
    })
  });
  const data = await response.json();
  return data.payInId;
}

// 3. Initialize SDK with clientToken and enableOneClick
const clientToken = await getClientToken();

const checkout = await MangopayCheckout.init({
  clientId: 'your-mangopay-client-id',
  clientToken: clientToken, // REQUIRED for one-click
  environment: 'SANDBOX',
  paymentMethods: [
    {
      type: 'paypal',
      options: {
        merchantId: 'YOUR_PAYPAL_MERCHANT_ID',
        enableOneClick: true, // Enables the one-click checkbox
        onCreatePayment: async (profilingAttemptReference, enableOneClick) => {
          // enableOneClick is true if customer checked the checkbox
          return createPayPalPayment(profilingAttemptReference, enableOneClick);
        }
      }
    }
  ]
});
```

### Backend implementation

When `enableOneClick` is `true`, your backend should:

1. Call [POST Create a Recurring PayIn Registration (PayPal)](/api-reference/recurring-payin-registrations/create-recurring-payin-registration-paypal) for the user
2. Call [POST Create a Recurring PayPal PayIn (CIT)](/api-reference/paypal/create-recurring-paypal-payin-cit)
3. Store the `RecurringPayinRegistrationId` for future one-click payments

For subsequent one-click payments for the user, call the non-recurring [POST Create a PayPal PayIn](/api-reference/paypal/create-paypal-payin) endpoint.

### Standard PayPal vs PayPal One-Click comparison

<table>
  <thead>
    <tr>
      <th class="header">Feature</th>
      <th class="header">Standard PayPal</th>
      <th class="header">PayPal One-Click</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td class="table-content">**Use case**</td>
      <td class="table-content">One-off payments</td>
      <td class="table-content">Returning customers opting in to save PayPal</td>
    </tr>

    <tr>
      <td class="table-content">**User experience**</td>
      <td class="table-content">User logs in to PayPal each time</td>
      <td class="table-content">Checkbox to opt in; future payments skip PayPal login</td>
    </tr>

    <tr>
      <td class="table-content">**SDK parameters**</td>
      <td class="table-content">`onCreatePayment`, `merchantId`</td>
      <td class="table-content">`clientToken`, `enableOneClick`, `onCreatePayment`, `merchantId`</td>
    </tr>

    <tr>
      <td class="table-content">**onCreatePayment arguments**</td>
      <td class="table-content">`(profilingAttemptReference)`</td>
      <td class="table-content">`(profilingAttemptReference, enableOneClick)`</td>
    </tr>

    <tr>
      <td class="table-content">**Backend action when opted in**</td>
      <td class="table-content">[POST Create a PayPal PayIn](/api-reference/paypal/create-paypal-payin)</td>
      <td class="table-content">[POST Create a Recurring PayIn Registration](/api-reference/recurring-payin-registrations/create-recurring-payin-registration-paypal) and [POST Create a Recurring PayPal PayIn (CIT)](/api-reference/paypal/create-recurring-paypal-payin-cit); then for subsequent payments byt the user [POST Create a PayPal PayIn](/api-reference/paypal/create-paypal-payin)</td>
    </tr>
  </tbody>
</table>

## Obtaining browser info for a pay-in

The `browserInfo` object is required when submitting a pay-in request. To get the required values for the transaction, use the `getBrowserInfo` function from the Checkout SDK instance. Pass on the values to your server.

```javascript theme={null}
//Using checkout-sdk or checkout-sdk-react package from npm.
import { getBrowserInfo } from '@mangopay/checkout-sdk'

//alternatively, if you are using the cdn script
const mangopaySdk = await CheckoutSdk.loadCheckoutSdk('#container', options);
const browserInfo = mangopaySdk.getBrowserInfo();

const payInRequestObj =
{
		...
    browserInfo         : {
        "AcceptHeader"  : browserInfo.AcceptHeader,
        "JavaEnabled"   : browserInfo.JavaEnabled,
        "Language"      : browserInfo.Language,
        "ColorDepth"    : browserInfo.ColorDepth,
        "ScreenHeight"  : browserInfo.ScreenHeight,
        "ScreenWidth"   : browserInfo.ScreenWidth,
        "TimeZoneOffset": browserInfo.TimeZoneOffset,
        "UserAgent"     : browserInfo.UserAgent,
        "JavascriptEnabled": browserInfo.JavascriptEnabled
    }
};
```

## Verifying the payment result

Once the `onPaymentComplete` event is triggered, verify the status of the relevant Mangopay API object:

* [View a PayIn](/api-reference/direct-card-payins/view-payin-direct-card)
* [View a Preauthorization](/api-reference/preauthorizations/view-preauthorization)
* [View a Deposit Preauthorization](/api-reference/deposit-preauthorizations/view-deposit-preauthorization)
* [View a Card Validation](/api-reference/card-validations/view-card-validation)

<Warning>
  **Caution – Check payment result from backend**

  You should confirm the transaction result returned by the Checkout SDK by calling the Mangopay API from your backend.
</Warning>

```javascript Verify payment result theme={null}
//This event is triggered by the SDK when a full payment cycle is complete.
mangopaySdk.on('paymentComplete', (event: CustomEvent<PaymentCompleteEventDetails>) => {

    const { Id } = event.details

    // 1. Verify payment result using the transaction Id.
    // 2. Present payment result to user.
});
```

## Showing and dismissing the loading spinner

When processing a token request, the SDK shows a loading spinner and retains it until the loading state is set to `false`. This provides a temporary state for the user until the full payment is complete, including calls from your platform's backend.

The `setLoading` method handles the loading state for displaying and dismissing the spinner.

```js theme={null}
import { CheckoutSdk } from '@mangopay/checkout-sdk';
const mangopaySdk = await CheckoutSdk.loadCheckoutSdk('#container', options);
// dismiss the  loader spinner
mangopaySdk.setLoading(false);
```

## Using Card Element

Card Element is a ready-made component that allows you to create your own card payment experience and tokenize card payment details. With Card Element, you can incorporate a custom pay button and have control over the tokenization process.

When using Card Element, you still benefit from card data validation, and the ability to customize the payment form.

Initialize the `cardFormElement` with your `ClientId` and select your environment (Sandbox or Production).

```js theme={null}
import { CheckoutSdk } from '@mangopay/checkout-sdk';

const cardFormElement = await CheckoutSdk.loadCardFormElement(elementOrSelector, options);
```

### cardFormElement-specific options

<table>
  <thead>
    <tr>
      <th class="header">Property</th>
      <th class="header">Type</th>
      <th class="header">Description</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td class="table-content">`paymentMethod`</td>
      <td class="table-content">Object</td>
      <td class="table-content">The payment method used with the card form element. Only `'card'` is supported. See **Configuring card payments** section for details</td>
    </tr>
  </tbody>
</table>

### Vanilla JS usage example

```html HTML theme={null}
<body>
    <form novalidate id="checkoutForm">
        <div id="container"></div>
        <button type="submit" id="submitButton">Pay now</button>
    </form>
    <script src="/index.js"></script>
</body>
```

```typescript TypeScript theme={null}
import { CheckoutSdk } from '@mangopay/checkout-sdk';

window.addEventListener('load', async () => {
    const cardFormElement = await CheckoutSdk.loadCardFormElement('#container', options);
    if (!cardFormElement) {
        throw new Error('Failed to load MangopayCardFormElement');
    }

    const submitButton = document.querySelector('#submitButton');
    if (!submitButton) {
        throw new Error('Submit button is missing.');
    }

    submitButton.addEventListener('click', async (event) => {
        event.preventDefault();
        cardFormElement.disable();
        try {
            cardFormElement.completePayment();
        } finally {
            cardFormElement.enable();
        }
    });

    cardFormElement.on('error', (event: CustomEvent<ErrorEventDetails>) => console.error(event.detail));

    cardFormElement.on('tokenizationComplete', (event: CustomEvent<TokenizationCompleteEventDetails>) => {
        // handle tokenization complete
    });
});
```

### ReactJS usage example

```typescript TypeScript theme={null}
import { CardFormElement } from '@mangopay/checkout-sdk-react';

const CheckoutFormComponent = () => {
    const sdkRef = useRef(null);

    const onTokenizationComplete = () => {
        /* Handle Card token here
               e.g charge customer card using CardId
        */
    };

    return (
        <>
            <form noValidate>
                <CardFormElement
                    ref={sdkRef}
                    options={options}
                    disabled={disabled}
                    onError={onError}
                    onLoaded={onLoaded}
                    onChange={onChange}
                    onTokenizationComplete={onTokenizationComplete}
                />
            </form>
            <button onClick={handleCompletePayment} className="btn pay-btn">
                Pay now
            </button>
        </>
    );
}

```

## Branding

You can customize the appearance of the checkout using the `branding` object.

```typescript TypeScript - Branding example theme={null}
const options = {
    branding: {
        fontFamily: 'Helvetica Neue',
        fontSize: {
            primary: '14px',
            secondary: '12px',
        },
        borderType: 'square', // 'square' | 'round' | 'bottom'
        colors: {
            primary: '#000000',
            secondary: '#545A61',
            accent: '#4E40EF',
            accentContrast: '#FFFFFF',
            border: '#E6E9EC',
            borderFocused: '#000000',
            error: '#EC0B43',
        },
        borderRadius: '0',
        backgroundColor: '#ffffff',
        textColor: '#000000',
        lineHeight: '48px',
        variables: undefined,
        rules: undefined,
    },
},
};

// Vanilla JS
const mangopaySdk = await MangopaySdkLoader.loadCheckoutSdk('#container', options);

// React.js
<MangopayCheckout ref={sdkRef} options={options} />
```

### Theme variables and rules

You can use the `rules` and `variables` objects for further customization.

#### Variables

Variables are CSS variables that you can declare and use in your theme rules.

```typescript TypeScript theme={null}
{
    theme: {
    ...,
        variables: {
            primaryColor: "#1D3557"
            secondaryColor: "#457B9D"
        }

        rules: {
            PayButton: `
            backgroundColor: var(--primaryColor);
            `
        }
    }
}
```

#### Rules

Rules allows you to apply CSS styles to Checkout SDK components. To do so, target components by class names, with or without the CSS class selector prefix (`FieldContainer` or `.FieldContainer`), and specify the styles to apply. The feature supports all native CSS properties and nesting.

```typescript TypeScript theme={null}
{
    theme: {
      ...,
        variables: {
            primaryColor: "#1D3557"
            secondaryColor: "#457B9D"
        }

        rules: {
            '.FieldContainer': `
              height: 40px;
              border-radius: 8px;
              backgroundColor: var(--primaryColor);
              
              &:hover {
                backgroundColor: var(--secondaryColor);
              }
          `
        }
    }
}
```

## Localization

Mangopay Checkout SDK has built-in localization support for: DE, EN, ES, FR, NL, PT

```typescript TypeScript theme={null}
const options = {
    locale: 'en', // 'en' | 'fr' | 'es' | 'de' | 'pt' | 'nl' | Object
};

// Vanilla JS
const mangopaySdk = await MangopaySdkLoader.loadCheckoutSdk('#container', options);

// React.js
<MangopayCheckout ref={sdkRef} options={options} />
```

You can customize labels, placeholder and success and error messages by providing a `customLanguage` object.

```javascript theme={null}
const customLanguage = {
  "card-information.header.label": "Card information",
  "card.number.placeholder": "1234 1234 1234 1234",
  "card.number.aria-label": "Card number",
  "card.number.errors.required": "Card number is required",
  "card.number.errors.min-length": "Minimum number of digits is 13",
  "card.number.errors.invalid-number": "Invalid card number",

  "card.psp.legal.notice": "Processed with Mangopay",
  "card.psp.legal.privacy": "Privacy.",
  "card.save.label": "Save payment details for future use",
  "card.saved-cards.choose-card.label": "Choose card",
  "card.saved-cards.clear-card.label": "Clear",
  "card.saved-cards.saved-card.aria-label": "The card ending in",
  "card.billing-name.placeholder": "Name on card",
  "card.billing-name.aria-label": "Name on card",
  "card.billing-name.errors.required": "Full name is required",
  "card.expiry.placeholder": "MM / YY",
  "card.expiry.aria-label": "Card expiration",
  "card.expiry.errors.required": "Expiration date is required",
  "card.expiry.errors.pattern": "Expiration date format is not valid (MM/YY)",
  "card.expiry.errors.expired": "Your card is expired",
  "card.cvc.placeholder": "CVC",
  "card.cvc.aria-label": "Card CVC",
  "card.cvc.errors.required": "Security code is required",
  "card.cvc.errors.min-length": "Security code is too short",
  "card.cvc.errors.max-length": "Security code is too long",
  "pay-button.label": "Pay",
  "pay-button.aria-label": "Pay",
  "payment-methods.card.label": "Card",
  "payment-methods.show-less.label": "Show less",
  "payment-methods.show-more.label": "Show more",
  "payment-methods.applepay.label": "Apple Pay",
  "payment-methods.applepay.aria-label": "Pay with Apple Pay",
  "payment-methods.googlepay.label": "Google Pay",
  "payment-methods.googlepay.aria-label": "Pay with Google Pay",
  "payment-methods.paypal.label": "PayPal",
  "payment-methods.paypal.aria-label": "Pay with PayPal",
  "payment-methods.paypal.overlay.message": "Don’t see the secure paypal browser? We’ll help you re-launch the window to complete your purchase",
  "payment-methods.paypal.overlay.continue": "Click to Continue",
  "payment-success-state.label": "Payment Succeeded",
  "redirect-note.label": "After submitting your order, you will be securely redirected to complete your purchase.",
  "loading.label": "Processing your payment",

	//errors
  "error.invalid_cvc": "Invalid CVC",
  "error.authorization_required": "Authorization Required",
  "error.contact_card_issuer": "Contact Card Issuer",
  "error.unsupported_card": "Unsupported Card",
  "error.insufficient_funds": "Insufficient Funds",
  "error.unsupported_currency": "Unsupported Currency",
  "error.card_rejected": "Card Rejected",
  "error.expired_card": "Expired Card",
  "error.suspected_fraud": "Suspected Fraud",
  "error.general_decline": "General Decline",
  "error.incorrect_number": "Incorrect Number",
  "error.incorrect_pin": "Incorrect Pin",
  "error.invalid_address": "Invalid Address",
  "error.invalid_card_or_account": "Invalid Card or Account",
  "error.invalid_amount": "Invalid Amount",
  "error.invalid_date": "Invalid Date",
  "error.lost_restricted_or_stolen_card": "Lost, Restricted or Stolen Card",
  "error.blocked_list": "Blocked List",
  "error.not_permitted": "Not Permitted",
  "error.offline_or_online_pin_required": "Offline or Online Pin Required",
  "error.pin_retry_exceeded": "Pin Retry Exceeded",
  "error.processing_error": "Processing Error",
  "error.withdrawal_count_limit_exceeded": "Withdrawal Count Limit Exceeded",
  "error.unknown": "Unknown error",
  "error.fraud": "Fraud",
  "error.three_d_secure": "3DS Failed",
  "error.custom_rule": "Custom Rule",
  "error.payment_cancelled": "Try making your payment again or select a different bank to continue",
  "error.payment_rejected": "The payment was rejected by the institution. Try again, or select another account or institution",
  "error.internal_server_error": "An unexpected error occurred",
  "error.institution_not_responding": "This financial institution is not currently responding to requests. We apologize for the inconvenience",
  "error.authorize.payment-already-authorized": "This payment has been already authorized",
  "error.param_error": "One or several required parameters are missing or incorrect",
  "error.payment_restart": "The payment wasn't successful, please try again",
  "error.ressource_not_found": "The resource does not exist"
};

const options = {
  locale: customLanguage
};

// Vanilla JS
const mangopaySdk = await CheckoutSdk.loadCheckoutSdk('#container', options);

// React.js
<MangopayCheckout ref={sdkRef} options={options} />
```
