---
title: "Components"
slug: "components-integration"
updated: 2025-07-31T05:53:12Z
published: 2025-07-31T05:53:12Z
canonical: "docs.monri.com/components-integration"
---

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

# Components

This documentation provides a comprehensive guide to integrating Monri Components into your web application for secure and flexible payment processing.

---
## 1. Overview

Monri Components are a set of UI elements provided by Monri.js that allow you to securely collect sensitive payment information (like card details or cryptocurrency payment initiation) directly from your customers' browsers without compromising PCI DSS compliance.

By using Components, you embed hosted fields directly into your payment form, ensuring that sensitive data never touches your servers.

### Key Benefits:

* **PCI DSS Compliance:** Sensitive data is handled directly by Monri.
* **Customizable UI:** Components can be styled to match your brand.
* **Simplified Integration:** Streamlined process for card and crypto payments.
<br/>
---
## 2. Requirements

### 2.1. HTTPS
All submissions of payment information using Monri Components are made via a secure HTTPS connection. To ensure maximum security and prevent Mixed Content warnings in modern browsers, **the page containing your payment form MUST also be served over HTTPS (`https://`)** rather than just `http://`.

For more information on SSL certificates and enabling HTTPS, please refer to our [security documentation](https://ipgtest.monri.com/en/security){target=`_blank`}.

### 2.2. Components script loading from the source
Components script **must always load directly from `monri.com`**. For more information please refer to [3.2.1. Set Up Monri Components](/v1/docs/components-integration#321-set-up-monri-components) below.
<br/>

---
## 3. Core Integration: Card Payments

This section details the primary integration steps for accepting card payments using Monri Components.

### 3.1. Creating a New Payment on Your Backend

This is the initial step, ideally executed once you have sufficient information to create a customer's order. You will typically generate a `client_secret` on your backend which is then sent to your frontend for use with Monri Components.

For detailed backend integration, refer to the [Payment API documentation](../api-documentation/api-v2/payment-api.md){target=`_blank`}.

**Demo:** See a live demonstration of Components integration here: [Demo Components](https://ipgtest.monri.com/services-demo/integration/components-create-payment){target=`_blank`}

### 3.2. Confirming Payment on Your Application (Frontend)

After generating the `client_secret` on your backend and sending it to your frontend application, you will use Monri Components to confirm the payment.

**Steps:**

1.  Ensure you have a valid `client_secret` (obtained from your backend via `payment/new` API call).
2.  Set up Monri Components (initialize `Monri.js`).
3.  Create the necessary HTML containers for your custom payment form.
4.  Confirm payment using `monri.confirmPayment`.
5.  Handle the `ConfirmPaymentResponse`.

#### 3.2.1. Set Up Monri Components

Components are part of the `Monri.js` library. To get started, include the following script on your pages. This script **must always load directly from `monri.com`** to remain PCI compliant; you cannot bundle it or host a copy yourself.

```HTML
<script src="[https://ipgtest.monri.com/dist/components.js](https://ipgtest.monri.com/dist/components.js)"></script>
```
Next, create an instance of Monri and components:

```JavaScript
var monri = Monri('<authenticity-token>');
var components = monri.components({"clientSecret": "<client-secret>"});
```
* Replace `<authenticity-token>` with the value provided in your merchant dashboard.
* Replace `<client-secret>` with the value obtained in the "Creating New Payment on Merchant's Backend" step.
When ready to accept live payments, ensure you replace the `authenticity-token` and `client-secret` with your production values.
<br/>
**Monri Constructor Options:**
The `Monri` constructor accepts an optional second parameter for customization:
`locale`: Sets the language for components (details below).
`fonts`: An array of `FontFace` objects for custom styling (explained below).

**Localization:**
Components can be localized by specifying the `locale` option. For example, to use the Croatian (`hr`) locale:
```JavaScript
var monri = Monri('authenticity-token', {locale: 'hr'});
```
Currently supported locales are:
* `hr` (Croatian - ICU `hr_HR`)
* `en` (English - ICU `en_US`, default)
* `sr` (Serbian - ICU `sr_SR`)
:::(Info) (Note:)
*"Locale" currently refers to language only; number and date formats are not supported.*
:::

**Custom Fonts:**
Components can be styled using custom fonts by passing an array of `FontFace` objects to the `fonts` property in `Monri` options:
```JavaScript
var monri = Monri('<authenticity-token>', {
    fonts: [
        {
            family: 'Rubik-Light',
            src: '/static/fonts/rubik-light.ttf'
        },
        {
            family: 'Rubik-Regular',
            src: '[https://some-site.com/fonts/roboto.ttf](https://some-site.com/fonts/roboto.ttf)',
            weight: '900'
        }
    ]
});
```
The `family` and `src` properties are required. Optional properties include `display`, `weight`, `style`, `stretch`, and `unicode-range`. For `display` values, refer to [MDN web docs](https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display#values){target=`_blank`}.

Localization and font options can be combined:
```JavaScript
var monri = Monri('<authenticity-token>', {
    locale: 'hr',
    fonts: [...] // Your font array
});
```
#### 3.2.2. Create Your Payment Form
To securely collect card details, Monri Components create UI elements that are hosted by Monri and then embedded into your form.

Create empty DOM elements (containers) with unique IDs within your payment form. We recommend using a `<label>` with a `for` attribute matching the container's `id` for improved accessibility (automatic focus when the label is clicked).

**Example HTML Structure:**
```HTML
<form action="" method="post" id="payment-form">
    <div class="form-row">
        <label for="card-element">
            Credit or debit card
        </label>
        <div id="card-element">
            </div>

        <div id="card-errors" role="alert"></div>
    </div>

    <button>Submit Payment</button>
</form>
```
:::(Info) (Note:)
*If your inserted payment form is invisible, it might be a CSS issue. Try removing classes like `form-row` for diagnostics.*
:::
After your form loads, create an instance of a Component and mount it to its container:
```JavaScript
// Custom styling can be passed to options when creating an Component.
var style = {
    base: {
        // Add your base input styles here. For example:
        fontSize: '16px',
        color: '#663399',
    }
};
// Create an instance of the card Component.
var card = components.create('card', {style: style});
// Add an instance of the card Component into the `card-element` <div>.
card.mount('card-element');
```
The `card` Component simplifies the form by providing a single, flexible input field for all necessary card details.

In addition to the `card` component, `saved_card` and `cvv` components are also available:
```JavaScript
var savedCard = components.create('saved_card', {style: style});
// Mount savedCard...
```
```JavaScript
var cvvComponent = components.create('cvv', {style: style});
// Mount cvvComponent...
```
For the `cvv` component, you can change the default payment method using `_setActivePaymentMethod` and providing a valid token for the saved card.

#### 3.2.3. Validation & Listening to Changes
Components validate user input as it is typed. Listen to `change` events on the `card` Component to display validation errors to your customers.

**Listening to `change` Events:**
```JavaScript
card.onChange(function (event) {
    var displayError = document.getElementById('card-errors');
    if (event.error) {
        displayError.textContent = event.error.message;
    } else {
        displayError.textContent = '';
    }
});
```

**Reacting to Specific Input Element Changes - `addChangeListener`:**
You can add listeners for specific input elements using the `addChangeListener` method:
```JavaScript
card.addChangeListener('<input_element>', function (event) {
    console.log(event.data);
    console.log(event.message);
    console.log(event.valid);
    console.log(event.element);
});
```
Supported input elements for `addChangeListener` are: `card_number`, `expiry_date`, and `cvv`.

**Card Number Change Listener**
```JavaScript
card.addChangeListener('card_number', function (event) {
    console.log(event.data);
    console.log(event.data.bin);
    console.log(event.data.brand);
    console.log(event.message);
    console.log(event.valid);
    console.log(event.element);
});
```

**Event Details:**
* `key`: `card_number`
* `event` object:
    * `data`: object
        * `bin`: `String | null` (min-length: 6, max-length: 6). Available only if at least 6 digits are entered, otherwise `null`.
        * `brand`: `String` (e.g., `visa`, `master`, `amex`).
    * `element`: `String` (`card_number`).
    * `message`: `String | null` (`null` if valid, message if invalid).
    * `valid`: `boolean` (`false` if input is invalid).

**Example `card_number` Event Data:**
```JSON
{
    "data": {
        "bin": "411111",
        "brand": "visa"
    },
    "element": "card_number",
    "message": null,
    "valid": true
}
```

**Save Card Change Listener**
```JavaScript
card.addChangeListener('save_card', function (event) {
    console.log(event.data);
    console.log(event.data.checked); // true if user clicked on save card
    console.log(event.valid); // always true
});
```

**Event Details:**
* `key`: `save_card`
* `event` object:
    * `data`: object
        * `checked`: `boolean`.
    * `element`: `String` (`save_card`).
    * `message`: `String | null` (`null` if valid).
    * `valid`: `boolean` (always `true` for this event).

**Example `save_card` Event Data:**
```JSON
{
    "data": {
        "checked": true
    },
    "element": "save_card",
    "message": null,
    "valid": true
}
```

**Expiry Date Change Listener**
```JavaScript
card.addChangeListener('expiry_date', function (event) {
    console.log(event.data);
    console.log(event.data.month);
    console.log(event.data.year);
    console.log(event.message);
    console.log(event.valid);
    console.log(event.element);
});
```

**Event Details:**
* `key`: `expiry_date`
* event object:
    * `data`: object
        * `month`: `Number` (1-12).
        * `year`: `Number` (e.g., 2024).
    * `element`: `String` (`expiry_date`).
    * `message`: `String | null` (`null` if valid, message if expiry date is in the past or invalid).
    * `valid`: `boolean` (`false` if input is invalid).

**Example `expiry_date` Event Data:**
```JSON
{
    "data": {
        "month": 11,
        "year": 2021
    },
    "element": "expiry_date",
    "message": null,
    "valid": true
}
```

**CVV Change Event**
```JavaScript
card.addChangeListener('cvv', function (event) {
    console.log(event.data);
    console.log(event.message);
    console.log(event.valid);
    console.log(event.element);
});
```

**Event Details:**
* `key`: `cvv`
* `event` object:
    * `data`: `object` (empty object).
    * `element`: `String` (`cvv`).
    * `message`: `String | null` (`null` if valid, message if invalid).
    * `valid`: `boolean` (`false` if input is invalid).

**Example `cvv` Event Data:**
```JSON
{
    "data": {},
    "element": "cvv",
    "message": null,
    "valid": true
}
```

**Installments Change Event**
```JavaScript
card.addChangeListener('installments', function (event) {
    console.log(event.data);
    console.log(event.data.selectedInstallment);
    console.log(event.message);
    console.log(event.valid);
    console.log(event.element);
});
```

**Event Details:**
* `key`: `installments`
* `event` object:
    * `data`: object
        * `selectedInstallment`: `Number`.
    * `element`: `String` (`installments`).
    * `message`: `String | null` (`null` if valid, message if invalid).
    * `valid`: `boolean` (`false` if input is invalid).

**Example `installments` Event Data:**
```JSON
    {
    "data": {
        "selectedInstallment": 11
    },
    "element": "cvv",
    "message": null,
    "valid": true
}
```
#### 3.2.4. Authorization
Although you can easily collect payment result directly in application via onSuccess call it’s better to implement callback listener (WebHook) on your backend.
{{snippet.IPG Digest Calc -Components-}}

#### 3.2.5. Confirm Payment using Monri Components
When the payment details are ready, invoke `monri.confirmPayment` to finalize the transaction. While `confirmPayment` can be called at any time, it's best practice to intercept the form's `submit` event and then call it.

`confirmPayment` accepts two arguments:
1. `component`: The component instance you created (e.g., `card`).
2. `transactionParams`: An object containing buyer and order information.

All `transactionParams` fields are validated against the rules defined in "Variables - Names, Lengths, and Formats" (see section 7).

**`MonriError` and `PaymentResult` Types:**
```TypeScript
type MonriError = {
    message: string
}

type Result<PaymentResult> = {
    result: PaymentResult | null,
    error: MonriError | null
}

type PaymentResult = {
    status: string, // approved or declined
    currency: string,
    amount: number, // amount in minor units, eg 10.24 USD is 1024
    order_number: string,
    pan_token: string | null, // pan token representing tokenized card
    created_at: string,
    transaction_type: string, // authorize or purchase, depending on trx type used in payment/new
    payment_method: SavedCardPaymentMethod | null, // available if card is tokenized for future payments, null if not
    errors: Array<string> | null // errors if transaction is declined
}

type SavedCardPaymentMethod = {
    type: string,
    data: SavedCardPaymentMethodData
}

type SavedCardPaymentMethodData = {
    brand: string,
    issuer: string,
    masked: string,
    expiration_date: string,
    token: string
}
```
**Important**: 3D Secure (3DS) authentication is automatically handled by the Monri Components library.

**Card Component Example:**
```JavaScript
// Confirm payment or display an error when the form is submitted.
var form = document.getElementById('payment-form');
form.addEventListener('submit', function (event) {
    event.preventDefault();
    const transactionParams = {
        address: "Adresa",
        fullName: "Test Test",
        city: "Sarajevo",
        zip: "71000",
        phone: "+38761000111",
        country: "BA",
        email: "tester+components_sdk@monri.com",
        orderInfo: "Testna trx"
    }

    monri.confirmPayment(card, transactionParams).then(function (result) {
        if (result.error) {
            // Inform the customer that there was an error.
            var errorElement = document.getElementById('card-errors');
            errorElement.textContent = result.error.message;
        } else {
            handlePaymentResult(result.result)
        }
    });
});
```

#### 3.2.6. Handle Payment Result (Frontend)

The final step on the frontend is to handle the `PaymentResult`. This depends entirely on your application's use case. The response can be submitted to your merchant's backend or handled directly within the client-side application.

For a secure and stable transaction processed notification, we highly recommend implementing a callback listener (WebHook) on your backend (see section 6).

```JavaScript
function handlePaymentResult(paymentResult) {
    // Handle PaymentResult
    if (paymentResult.status == 'approved') {
        alert("Transaction approved")
    } else {
        alert("Transaction declined")
    }
}
```

### 3.3. Getting Payment Result on Merchant’s Backend (WebHook)
:::(Warning) (Warning:)
While you can collect payment results on the client-side via the `onSuccess` callback, it is **highly recommended** to implement a {{glossary.MD-Pay Callback}} listener (WebHook) on your backend for secure and stable transaction notifications.
:::

**Requirements for your WebHook Endpoint:**
* Must be publicly available over the internet.
* Must be secured (HTTPS).
* Must be configured in your merchant's settings on the Monri dashboard (contact support if you need assistance setting this value).

**How it Works:**
1.  Upon successful transaction processing and approval, Monri will send an HTTP POST request to your configured callback endpoint.
2.  Your backend should validate the received request to ensure it originates from Monri.
3.  Update or deliver the order based on the transaction status.

**Example POST Request Body Sent to Callback Endpoint:**
```JSON
{
    "id": 214,
    "acquirer": "integration_acq",
    "order_number": "3159daf002e3809",
    "amount": 100,
    "currency": "EUR",
    "ch_full_name": "John Doe",
    "outgoing_amount": 100,
    "outgoing_currency": "EUR",
    "approval_code": "687042",
    "response_code": "0000",
    "response_message": "approved",
    "reference_number": "000003036888",
    "systan": "000214",
    "eci": "06",
    "xid": null,
    "acsv": null,
    "cc_type": "visa",
    "status": "approved",
    "created_at": "2020-03-26T11:09:17.959+01:00",
    "transaction_type": "purchase",
    "enrollment": "N",
    "authentication": null,
    "pan_token": null,
    "masked_pan": "411111-xxx-xxx-1111",
    "issuer": "xml-sim",
    "number_of_installments": null,
    "custom_params": "{a:b, c:d}"
}
```

**Example Request Headers:**

| Header              | Value                                                                                                                                                                                                                                                                       |
| :------------------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `accept-encoding`   | `gzip;q=1.0,deflate;q=0.6,identity;q=0.3`                                                                                                                                                                                                                                   |
| `authorization`     | `WP3-callback d5e4528ad8a0e0f4262e518c663d5ff83cd4a8f381db68f9d30f99961409ceebb719c16d423757fc36c532b902c987012f5825dc8d32dde3a9b7ed95876be77a` |
| `content-type`      | `application/json`                                                                                                                                                                                                                                                          |
| `http_authorization`| `WP3-callback d5e4528ad8a0e0f4262e518c663d5ff83cd4a8f381db68f9d30f99961409ceebb719c16d423757fc36c532b902c987012f5825dc8d32dde3a9b7ed95876be77a` |
| `user-agent`        | `Faraday v0.15.4`                                                                                                                                                                                                                                                           |
| `content-length`    | `621`                                                                                                                                                                                                                                                                       |
| `connection`        | `keep-alive`                                                                                                                                                                                                                                                                |

The `authorization` and `http_authorization` headers are generated as:
`digest = sha512(merchant_key + body)`
(You can check the digest on this link: [Calculate Digest](https://ipgtest.monri.com/services-demo/integration/authorization){target=`_blank`})
`authorization_header_value = WP3-callback digest`

To validate if the request is from Monri, you should:
* Check if the authorization header schema is `WP3-callback`.
* Extract the digest (the second part of the header value).
* Verify the extracted digest against a locally computed digest using your `merchant_key` and the received `body`.
<br/>
---
## 4. Crypto Currencies: PayCek Payments

Monri Components also support integration with PayCek for cryptocurrency payments.

### 4.1. Set Up PayCek Component

The PayCek component is available via `Monri.js`. As with other components, it must be loaded directly from `monri.com`.

**Test Environment:**
```HTML
<script src="https://ipgtest.monri.com/dist/components.js"></script>
```
**Production Environment:**
```HTML
<script src="https://ipg.monri.com/dist/components.js"></script>
```
Initialize `Monri` and `components` instances:
```JavaScript
var monri = Monri('<authenticity-token>');
var components = monri.components({"clientSecret": "<client-secret>"});
```
* Replace `<authenticity-token>` with your merchant dashboard value.
* Replace `<client-secret>` with the value from your backend's "Creating New Payment" step.

**Monri Options:**
Additional options can be passed to the `Monri` constructor, such as `locale`. For localization details, refer to [section 3.2.1](#3.2.1-set-up-monri-components).

### 4.2. Create Your PayCek Payment Form

Similar to card components, create an empty DOM container with a unique ID for the PayCek component within your payment form.

**Example HTML:**
```HTML
<form action="" method="post" id="pay-cek-payment-form-form">
    <div class="form-row">
        <div id="pay-cek-element">
            </div>
    </div>

    <button>Submit Payment</button>
</form>
```
:::(Info) (Note:)
*If your inserted payment form is invisible, it might be a CSS issue. Try removing classes like `form-row` for diagnostics.*
:::

Once the form is loaded, create and mount the PayCek Component:
```JavaScript
// Custom styling can be passed to options when creating PayCek Component.
var options = {
    payCekOptions: {size: "small"}
};
// Create an instance of the PayCek Component.
var payCek = components.create("pay-cek", options)
    .onStartPayment(() => {
        // This is invoked after user clicks on PayCek button
        // Here you can:
        // 1. Collect user's info such as name, email address
        // 2. Invoke confirmPayment with PayCek
        const transactionParams = {
            address: "Adresa",
            fullName: "Test Test",
            city: "Sarajevo",
            zip: "71000",
            phone: "+38761000111",
            country: "BA",
            email: "tester+components_sdk@monri.com",
            orderInfo: "Testna trx"
        }
        monri
            // confirmPayment opens a popup window for crypto currency selection
            // then displays a QR code with wallet address
            // finally, returns an Approved or Declined transaction response as a Promise
            .confirmPayment(payCek, transactionParams) // Changed 'params' to 'transactionParams' for consistency
            .then(e => {
                if (e.error) {
                    // Inform the customer that there was an error.
                    alert(e.error.message)
                } else {
                    // Handle approved or declined result
                    // For secure and stable result, handle on backend via WebHook (section 6)
                }
            })
            .catch(e => {
                alert(e);
            })
    });
// Add an instance of the PayCek component into the `pay-cek-element` <div>.
payCek.mount("pay-cek-element");
```
<br/>

---
## 5. Customizing Components
Monri Components offer various options for styling and specific functionalities.

### 5.1. Styling Components
Components can be styled via the `style` property in the second parameter of the `create` method (as shown in section 3.2.2).

The `style` object consists of four properties representing component element states, which override the `base` style if specified:
* `base`: Defines the default style applied to each component element.
* `complete`: Style applied when a component element is filled with a valid value.
* `empty`: Style applied when a component element is empty and loses focus.
* `invalid`: Style applied when a component element contains an invalid value and loses focus.

Additionally, `style` properties for `label`, `input`, `rememberCardLabel`, and `selectPaymentMethod` elements can be set explicitly.

Styles are applied to all component elements that have received focus at least once.

**Supported CSS Properties (all string type, all optional):**
| Attribute           | CSS attribute                   | Description                          |
| :------------------ | :------------------------------ | :----------------------------------- |
| `fontSize`          | `font-size`                     | Size of the font                     |
| `color`             | `color`                         | Component element color              |
| `fontFamily`        | `font-family`                   | Family of the font                   |
| `fontSmoothing`     | `font-smoothing`                | Selected font smoothing              |
| `fontVariant`       | `font-variant`                  | Variant of the font                  |
| `fontWeight`        | `font-weight`                   | Font weight                          |
| `letterSpacing`     | `letter-spacing`                | Font letter spacing                  |
| `textDecoration`    | `text-decoration`               | Component element text decoration    |
| `textShadow`        | `text-shadow`                   | Component element text shadow        |
| `textTransform`     | `text-transform`                | Component element text transform     |
| `border`            | `border`                        | Component element border             |
| `borderTop`         | `border-top`                    | Component element top border         |
| `borderRight`       | `border-right`                  | Component element right border       |
| `borderBottom`      | `border-bottom`                 | Component element bottom border      |
| `borderLeft`        | `border-left`                   | Component element left border        |
| `borderRadius`      | `border-radius`                 | Component element border radius      |
| `padding`           | `padding`                       | Component element padding            |
| `margin`            | `margin`                        | Component element margin             |
| `lineHeight`        | `line-height`                   | Component element line height        |
| `textIndent`        | `text-indent`                   | Component element text indent        |
| `position`          | `position`                      | Component element position           |
| `top`               | `top`                           | Component element top                |
| `bottom`            | `bottom`                        | Component element bottom             |
| `left`              | `left`                          | Component element left               |
| `right`             | `right`                         | Component element right              |
| `width`             | `width`                         | Component element width              |
| `backgroundColor`   | `background-color`              | Component element background color   |
| `height`            | `height`                        | Component element height             |
| `boxShadow`         | `box-shadow, moz-box-shadow, webkit-box-shadow` | Component element box shadow       |

**Example of Custom Style Object:**
```JavaScript
var style = {
    base: {
        fontFamily: 'Rubik-Regular'
    },
    invalid: {
        color: 'red'
    },
    complete: {
        color: 'blue'
    },
    label: {
        base: {
            color: 'blue',
            textTransform: 'none'
        },
        invalid: {
            color: 'gray'
        },
        complete: {
            color: 'green'
        }
    },
    input: {
        base: {
            fontSize: '15px',
            color: "#663399",
            borderBottom: "1px solid purple"
        }
    },
    rememberCardLabel: {
        base: {
            fontSize: '15px',
            color: "#663399"
        }
    },
    selectPaymentMethod: {
        base: {
            fontSize: '15px',
            color: "#663399"
        }
    }
};
```

**Style Object Structure (empty fields can be omitted):**
```JavaScript
var style = {
    base: {},
    invalid: {},
    complete: {},
    empty: {},
    label: {
        base: {},
        invalid: {},
        complete: {},
        empty: {}
    },
    input: {
        base: {},
        invalid: {},
        complete: {},
        empty: {}
    },
    rememberCardLabel: {
        base: {},
        invalid: {},
        complete: {},
        empty: {}
    },
    selectPaymentMethod: {
        base: {},
        invalid: {},
        complete: {},
        empty: {}
    }
}
```

### 5.2. Component-Specific Options

#### Card Component Options

Card component options extend common component options with:

| Option                    | Type    | Description                                            | Default Value |
| :------------------------ | :------ | :----------------------------------------------------- | :------------ |
| `tokenizePan`             | boolean | Tokenizes the PAN when the client enters card info.    | `false`       |
| `tokenizePanOffered`      | boolean | Offers the client the option to tokenize their PAN.    | `false`       |
| `showInstallmentsSelection` | boolean | Shows the installments selection dropdown if enabled. | `false`       |

**`tokenizePan` Option:**
If `true`, the PAN is tokenized upon transaction approval, and the `pan_token` value is populated in the transaction response.
```JavaScript
var style = {} // Define styling options for card component
var card = components.create("card", {
    style: style,
    tokenizePan: true // This will tokenize the PAN upon transaction approval
});
```

**`tokenizePanOffered` Option:**
If `true`, a "save card for future payments" checkbox is presented to the customer. If checked, the PAN is tokenized upon transaction approval, and `pan_token` is populated.

```JavaScript
var style = {} // Define styling options for card component
var card = components.create("card", {
    style: style,
    tokenizePanOffered: true // This enables the 'save card for future payments' checkbox in the form
});
```

**Important Notes:**
* If `tokenizePan` is `true`, `tokenizePanOffered` is ignored.
* Setting `tokenizePan` to `true` requires prior user consent (e.g., through accepted terms and conditions).

**`showInstallmentsSelection` Option:**
If `true` and installments are enabled for your merchant account, a dropdown for installment selection will be displayed.
```JavaScript
var style = {} // Define styling options for card component
var card = components.create("card", {
    style: style,
    showInstallmentsSelection: true // This enables installments selection
});
```
**Important Note:** If `showInstallmentsSelection` is `true` but the dropdown doesn't appear, it means installments are disabled for your merchant account. Contact [support@monri.com](mailto:support@monri.com){target=`_blank`} to enable them.
<br/>

---
## 6. Transactions API: Variables, Lengths, and Formats

This section defines the variables and their properties used in API calls, particularly for JSON documents.

### Buyer's Profile Fields

| Name           | Length   | Format       | Additional Info                                                    |
| :------------- | :------- | :----------- | :----------------------------------------------------------------- |
| `ch_full_name` | 3-30     | alphanumeric | Buyer's full name                                                  |
| `ch_address`   | 3-100    | alphanumeric | Buyer's address                                                    |
| `ch_city`      | 3-30     | alphanumeric | Buyer's postal code (ZIP)                                          |
| `ch_zip`       | 3-9      | alphanumeric | Buyer's postal code (ZIP)                                          |
| `ch_country`   | 2-3      | alphanumeric | Buyer’s country in alpha2, alpha3 letter code, or 3-digit ISO numeric code |
| `ch_phone`     | 3-30     | alphanumeric | Buyer's phone number                                               |
| `ch_email`     | 3-100    | alphanumeric | Buyer's email address                                              |

### Order Details Fields

| Name           | Length     | Format             | Additional Info                                               |
| :------------- | :--------- | :----------------- | :------------------------------------------------------------ |
| `order_info`   | 3-100      | alphanumeric       | Short description of the order being processed                |
| `order_number` | 1-40       | printable characters | Unique identifier for the order                               |
| `amount`       | 3-11       | integer            | Amount in minor units (e.g., 10.24 USD is sent as 1024)       |
| `currency`     | predefined | alphabetic         | Possible values are USD, EUR, or BAM                          |

<br/>

---
## 7. Viewport Meta Tag Requirements

To ensure an optimal user experience for 3D Secure (3DS) authentication across all devices, you should set your page’s viewport `width` to `device-width` using the [viewport meta tag](https://developer.mozilla.org/en-US/docs/Web/HTML/Viewport_meta_tag){target=`_blank`}. Other viewport settings can be configured as needed, but `width=device-width` is crucial.

**Example:**
```HTML
<meta name="viewport" content="width=device-width, initial-scale=1"/>
```
If this tag is already present on your page and includes `width=device-width`, no further action is required.
<br/>

---
## 8. API References

* [List of Response Codes](/v1/docs/list-of-response-codes){target=`_blank`}
* [Payment API](/v1/docs/payment-api){target=`_blank`}
