08.04.2022 - Added Monri components - CVV component documentation21.05.2021 - Added Crypto Currencies - PayCek documentation19.02.2021 - Updated Components Style section, added borderTop,borderRight,borderBottomborderLeft27.10.2020 - Updated addChangeListenersection, added20.10.2020 - Updated addChangeListener section,15.10.2020
    06.10.2020 - Updated Components Style section, added more supported properties and style object structure01.09.2020 - Updated supported_payment_methods section, added support for card03.07.2020 - Added addChangeListener section30.06.2020 - Added supported_payment_methods section20.05.2020 - Some typo fixes and clarifications05.05.2020 - Initial versionAll submissions of payment info using Components are made via a secure HTTPS connection. However, to protect yourself
from certain forms of man-in-the-middle attacks, and to prevent your customers from
seeing  Mixed Content  warnings in
modern browsers, you must serve the page containing the payment form over HTTPS as well.
In short, the address of the page containing Components must start with  https://  rather than just  http://. If
you are not familiar with the process of buying SSL certificates and integrating them with your server to enable a
secure HTTPS connection, check out our  security  documentation for more information.
This step is preferably executed when you have enough information to create customer’s order.
For simplicity we’ll show example using curl in PHP.
You can find a demo on this link Demo Components
To create payment on our backend you’ll need:
merchant_key (available on merchant’s dashboard)authenticity_token (available on merchant’s dashboard)Following fields are available/required:
| field | length | type | required | description | 
| amount | 1-11 | Integer | YES | amount is in minor units, ie. 10.24 USD is sent as 1024 | 
| order_number | 2-40 | String | YES | unique order identifier | 
| currency | 3 | String | YES | One of supported currencies (BAM, HRK, EUR, USD, CHF etc) | 
| transaction_type | enum | String | YES | possible values are: authorizeorpurchase | 
| order_info | 3-100 | String | YES | short description of order being processed | 
| scenario | enum | String | NO | possible values are: chargeoradd_payment_method | 
| supported_payment_methods new | predefined | Array<String> | NO | An array of pan-tokens and/or card(see below for more details) | 
Scenario charge charges customer amount. Depending on transaction_type amount is reserved (authorize) or captured (
purchase).
Scenario add_payment_method provides simple way to implement ‘Save card for future payments’ functionality.
----------------------------------------------
WARNING - add_payment_method scenario will automatically execute refund or void depending on transaction type. ONLY use for saving cards.
----------------------------------------------
supported_payment_methods in an array of valid payment methods.
Valid payment methods are:
card - representing new card<pan_token> - secure vault token - Secure Vault TokensRequirements / options:
card is provided then user will be able to enter new card instead of selecting one of saved cards
    <pan_token> is provided provided and valid(cards not expired, valid tokens etc)
    Example of valid payment methods:
{
  "supported_payment_methods": [
    "f167252fecfeff8f134001bf8e7a700c53e8653f631362dd84913e23260199bf",
    "0df5d4eac4f36d0dee9f48c17ddac2f66c12e5edfc4f92a92d3e6085f31368ea",
    "card"
  ]
}
Setup above will result in:
f167252fecfeff8f134001bf8e7a700c53e8653f631362dd84913e23260199bf0df5d4eac4f36d0dee9f48c17ddac2f66c12e5edfc4f92a92d3e6085f31368eaFor request authentication we use Authorization header created from:
authorization schema: String = WP3-v2authenticity_token: String = value from merchant’s configurationtimestamp: Integer = unix timestamp (eg PHP’s time())body_as_string: String = Json encoded request body, eg json_encode($data)digest: String = sha512(merchant_key + timestamp + authenticity_token + body_as_string)You can check digest on this link Calculate Digest
Parts above are joined by space, so Authorization header should be in this form:
Authorization: schema authenticity_token timestamp digest
Example: Authorization: WP3-v2 abc...def 1585229134 314d32d1...0b49
Request endpoint is <base_url>/v2/payment/new where base_url is:
https://ipgtest.monri.com for TEST environmenthttps://ipg.monri.com for PROD environmentTIP: Parametrize merchant_key, authenticity_token and base_url so it can be easily changed when you are ready for
production environment.
Payment/new response contains:
status: String: approved | declined -id: String - Unique payment identifier used to track payment flow on Monri’sclient_secret: String - Value you’ll send to your application which then will use this secret to confirm paymentRequest example in PHP:
$data = [
  'amount' => 100, //minor units = 1EUR
  // unique order identifier
  'order_number' => 'random' . time(),
  'currency' => 'EUR',
  'transaction_type' => 'purchase',
  'order_info' => 'Create payment session order info',
  'scenario' => 'charge'
  'supported_payment_methods' => ['67f35b84811188a5c581b063c4f21bd6760c93b2a04d7ac4f8845dd5bbb3f5c6']
];
$body_as_string = Json::encode($data); // use php's standard library equivalent if Json::encode is not available in your code
$base_url = 'https://ipgtest.monri.com'; // parametrize this value
$ch = curl_init($base_url . '/v2/payment/new');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, $body_as_string);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
$timestamp = time();
$digest = hash('sha512', $key . $timestamp .$authenticity_token. $body_as_string);
$authorization = "WP3-v2 $authenticity_token $timestamp $digest";
            
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
    'Content-Type: application/json',
    'Content-Length: ' . strlen($body_as_string),
    'Authorization: ' . $authorization
  )
);
$result = curl_exec($ch);
if (curl_errno($ch)) {
  curl_close($ch);
  $response = ['client_secret' => null, 'status' => 'declined', 'error' => curl_error($ch)];
} else {
  curl_close($ch);
  $response = ['status' => 'approved', 'client_secret' => Json::decode($result)['client_secret']];
}
var_dump($response);
After you’ve created payment on a backend and sent client_secret back to your application you need to confirm payment
using Monri Components.
Steps:
client_secret (created on backend using payment/new)monri.confirmPaymentConfirmPaymentResponseCreating a custom payment form with Components requires two steps
Components is available as part of  Monri.js. To get started, include the following
script on your pages. This script must always load directly from  monri.com  in order to
remain  PCI compliant—you can’t include it in a bundle or
host a copy of it yourself.
<script src="https://ipgtest.monri.com/dist/components.js"></script>
Next, create an instance of Components:
var monri = Monri('<authenticity-token>');
var components = monri.components({"clientSecret": "<client-secret>"});
Replace <authenticity-token> with value provided in merchant dashboard. Replace <client-secret> with value obtained
in step Creating New Payment on Merchant's Backend
When you’re ready to accept live card payments, replace the authenticity_token and merchant_key with your
production authenticity_token and merchant_key.
Additional options can be passed as optional second parameter to Monri constructor, which additionally can customise
Monri Components. Currently supported options are:
locale  locale which will be used (details below),fonts list of fonts that will be used for custom styling (also explained below)Components can be localised via specifying locale in Monri Options. For example, to use hr locale in Monri
Components (and all underlying components), {locale: 'hr'} can be specified as a second parameter.
var monri = Monri('authenticity-token', {locale: 'hr'});
As of now, supported locales are:
hr locale for Croatia (ICU hr_HR)en locale for USA (ICU en_US)sr locale for Serbia (ICU sr_latn_SR)bs locale for Bosnia and Herzegovina (ICU bs)ba_hr locale for Croatian in BiH (ICU hr_BA)sl locale for Slovenia (ICU sl_Sl)me locale for Montenegro (ICU sr_latn_ME)mk locale for Macedonia (ICU mk_MK)de locale for Germany (ICU de_DE)By “locale” here is assumed “language” only. Number format, date format, etc., as of time of writing, are not supported.
By default, en locale is used.
Components can be stylised via additionally provided fonts in Monri Options. Fonts are provided as an array
of FontFace objects, with these properties:
family Family of the font face.src Path to the font source. Path can be absolute (only http and https URI schemes are supported) or relative todisplay Specifies how font files are loaded and displayed by browser. Supported values are auto, block, swapfallback and optional. If this property is omitted, auto is used by default. For more information about theseweight The weight of the fontstyle Specifies the font style. Supported values are normal, italic and oblique. If omitted, normal is used.stretch Specifies front stretch property.unicode-range The unicode range from font which browser will select to use. If omitted, all characters of font willThe family and src properties are required, others are optional and have default values.
List of fonts is passed as fonts property in Monri Options, like:
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',
                weight: '900'
            }
        ]
    }
);
Localization options and style option can be, of course, combined, like:
var monri = Monri('<authenticity-token>', {
        locale: 'hr',
        fonts: [...]
    }
);
To securely collect card details from your customers, Components creates UI components for you that are hosted by Monri.
They are then placed into your payment form, rather than you creating them directly.
To determine where to insert these components, create empty DOM elements (containers) with unique IDs within your
payment form. We recommend placing your container within a <label> or next to a <label> with a for attribute that
matches the unique id of the Element container. By doing so, the Element automatically gains focus when the customer
clicks on the corresponding label.
For example:
<form action="" method="post" id="payment-form">
    <div class="form-row">
        <label for="card-element">
            Credit or debit card
        </label>
        <div id="card-element">
            <!-- A Monri Component will be inserted here. -->
        </div>
        <!-- Used to display Component errors. -->
        <div id="card-errors" role="alert"></div>
    </div>
    <button>Submit Payment</button>
</form>
(Note: if inserted payment form is invisible, this may be a CSS issue. Start diagnostics by removig class form-row,
the only one CSS in example)
When the form above has loaded, create an instance of an Component and mount it to the Component
container created above:
// 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 and minimises the number of fields required by inserting a single, flexible
input field that securely collects all necessary card details.
In addition to the card component, we also offer a saved card component and cvv component. They can be easily created like as the card mentioned above.
For example:
var savedCard = components.create('saved_card', {style: style});
var cvvComponent = components.create('cvv', {style: style});
Default payment method is provided via supported payment_methods to change it on cvv component you can call setActivePaymentMethod 
where you have to provide valid token for saved card.
Components can be styled via style property of second parameter in create method, as shown above in example. For all
styling options please see section Components - style
Components validates user input as it is typed. To help your customers catch mistakes, you should listen to change
events on the card Component and display any errors:
card.onChange(function (event) {
    var displayError = document.getElementById('card-errors');
    if (event.error) {
        displayError.textContent = event.error.message;
    } else {
        displayError.textContent = '';
    }
});
addChangeListenerWe support adding changeListener via addChangeListener method. To add change listener simply invoke:
card.addChangeListener('<input_element>', function (event) {
    console.log(event.data)
    console.log(event.message)
    console.log(event.valid)
    console.log(event.element)
});
It’s possible to add change listener for:
card_numberexpiry_datecvvcard.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)
});
card_numberString | null, min-length: 6, max-length: 6, only available if user has entered at least 6 digits, nullString, one of visa, master, amex etcString - in this case it’s card_numberString | null - non null if card number input is invalidboolean - false if input is invalid{
  "data": {
    "bin": "411111",
    "brand": "visa"
  },
  "element": "card_number",
  "message": null,
  "valid": true
}
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)
});
expiry_dateNumber, 1 - 12Number, eg 2024String - in this case it’s expiry_dateString | null - non null if expiry date is in past or invalidboolean - false if input is invalid{
  "data": {
    "month": 11,
    "year": 2021
  },
  "element": "expiry_date",
  "message": null,
  "valid": true
}
card.addChangeListener('cvv', function (event) {
    console.log(event.data)
    console.log(event.message)
    console.log(event.valid)
    console.log(event.element)
});
cvvobject - empty objectString - in this case it’s cvvString | null - non null if cvv is invalidboolean - false if input is invalid{
  "data": {},
  "element": "cvv",
  "message": null,
  "valid": true
}
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)
});
installmentsNumberString - in this case it’s installmentsString | null - non null if cvv is invalidboolean - false if input is invalid{
  "data": {
    "selectedInstallment": 11
  },
  "element": "cvv",
  "message": null,
  "valid": true
}
The payment details collected using Components can be used to confirm payment.
Although payment can be confirmed at any moment it is a good practice to intercept form submit and then
invoke monri.confirmPayment.
confirmPayment accepts two arguments:
components.createAll transaction params fields are validated using rules defined in Variables - names, lengths and formats
Create an event handler that handles the submit event on the form. The handler invokes confirmPayment which confirms
transaction and returns Result<PaymentResult>.
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 3DS authentication is automatically handled by Monri Components library.
// 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: "[email protected]",
        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)
        }
    });
});
The last step is to handle payment result. This step completely depends on application use case. Response can be
submitted to the merchant’s backend or handled in application.
If you want secure and stable transaction processed notification continue to the
section Getting payment result on merchant's backend
function handlePaymentResult(paymentResult) {
    // Handle PaymentResult
    if (paymentResult.status == 'approved') {
        alert("Transaction approved")
    } else {
        alert("Transaction declined")
    }
}
PayCek component is available as part of Monri.js. To get started include the following script on your pages. This script must always load directly from monri.com in order to remain PCI compliant you can’t include it in a bundle or host a copy of it yourself.
Test Environment
<script src="https://ipgtest.monri.com/dist/components.js"></script>
Production Environment
<script src="https://ipg.monri.com/dist/components.js"></script>
Next, create an instance of Components:
var monri = Monri('<authenticity-token>');
var components = monri.components({"clientSecret": "<client-secret>"});
Replace <authenticity-token> with value provided in merchant dashboard. Replace <client-secret> with value obtained
in step Creating New Payment on Merchant's Backend
When you’re ready to accept live payments, replace the authenticity_token and merchant_key with your
production authenticity_token and merchant_key.
Additional options can be passed as optional second parameter to Monri constructor, which additionally can customise
Monri Components. Currently supported options are:
locale  locale which will be used (details below)Components can be localized via specifying locale in Monri Options. For example, to use hr locale in Monri
Components (and all underlying components), {locale: 'hr'} can be specified as a second parameter.
For more details check localize components
To determine where to insert these components, create empty DOM elements (containers) with unique IDs within your
payment form. For example:
<form action="" method="post" id="pay-cek-payment-form-form">
    <div class="form-row">
        <div id="pay-cek-element">
            <!-- A Monri PayCek Component will be inserted here. -->
        </div>
    </div>
    <button>Submit Payment</button>
</form>
(Note: if inserted payment form is invisible, this may be a CSS issue. Start diagnostics by removing class form-row,
the only one CSS in example)
When the form above has loaded, create an instance of PayCek Component and mount it to the PayCek Component container created above:
// Custom styling can be passed to options when creating PayCek Component.
var options = {
    payCekOptions: {size: "small"}
};
// Create an instance of the card 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: "[email protected]",
            orderInfo: "Testna trx"
        }
        monri
            // Confirm payment does few things
            // 1. it opens a popup window where and option to pick between supported Crypto currencies is shown
            // 2. after user selects one of currencies QR code with wallet address is shown
            // 3. Approved or declined transaction response is then send as Promise
            .confirmPayment(payCek, params)
            .then(e => {
                if (e.error) {
                    // Inform the customer that there was an error.
                    alert(e.error.message)
                } else {
                    // Handle approved or declined result
                }
            })
            .catch(e => {
                alert(e);
            })
                        
    })
// Add an instance of the PayCek component into the `pay-cek-element` <div>.
payCek.mount("pay-cek-element")
Although payment can be confirmed at any moment it is a good practice to invoke monri.confirmPayment.
confirmPayment accepts two arguments:
components.createAll transaction params fields are validated using rules defined in Variables - names, lengths and formats
Create an event handler that handles the submit event on the form. The handler invokes confirmPayment which confirms
transaction.
const transactionParams = {
    address: "Adresa",
    fullName: "Test Test",
    city: "Sarajevo",
    zip: "71000",
    phone: "+38761000111",
    country: "BA",
    email: "[email protected]",
    orderInfo: "Testna trx"
}
payCek.onStartPayment(() => {
    monri.confirmPayment(payCek, transactionParams)
        .then(e => {
            if (e.error) {
                // Inform the customer that there was an error.
                alert(e.error.message)
            } else {
                handlePaymentResult(e.result)
            }
        })
        .catch(e => {
            alert(e);
        })
    
})
Although you can easily collect payment result directly in application via onSuccess call it’s better to implement
callback listener (WebHook) on your backend.
Requirements:
How it works:
Example of POST request sent to callback endpoint:
Body:
{
  "id": 214,
  "acquirer": "integration_acq",
  "order_number": "3159daf002e3809",
  "amount": 100,
  "currency": "HRK",
  "ch_full_name": "John Doe",
  "outgoing_amount": 100,
  "outgoing_currency": "HRK",
  "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}"
}
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 | 
Where authorization and http_authorization headers are created as:
digest = sha512(merchant_key + body)
authorization_header_value = WP3-callback digest
To check if request is valid check:
WP3-callbackIn order to provide a great user experience for  3D Secure  on all devices,
you should set your page’s viewport  width  to  device-width  with the
the  viewport meta tag. There are several
other viewport settings, and you can configure those based on your needs. Just make sure you
include  width=device-width  somewhere in your configuration.
For instance the following will work with Components:
<meta name="viewport" content="width=device-width, initial-scale=1"/>
If you already have this tag on your page and it includes  width=device-width, then you are all set.
All Components accept a common set of options, and then some Component-specific options.
Customize appearance using CSS properties. Styles are passed via the style property of options.
Style property consist of four properties which represent the states of the component elements (e.g. card fields).
There is base property which defines style that is applied to each component element, and there are three additional
properties which, if specified, will override the base style. These properties are:
complete style applied when component element is completed e.g. filled with valid valueempty style applied when component element is empty (focus is moved away but element remained without entered value)invalid style applied when component element contains invalid value. Style is applied only when element loses focusAdditionaly, as shown in example below, style property of label elements, input elements, remember card label element
and select payment method element can be set explicitly.
Styles are applied to all component elements based on their state which had focus at least once. Currently, available
style properties are as follows, all of string type and 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 height | 
Example of custom style:
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 has structure like the one below, where empty fields can be omitted:
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: {}
    }
}
Card component options extends shared component options with:
| option | type | description | default value | 
|---|---|---|---|
| tokenizePan | boolean | tokenize PAN when the client enters card info | false | 
| tokenizePanOffered | boolean | offer the client to tokenize his PAN | false | 
| showInstallmentsSelection | boolean | show installments select if installments are enabled for merchant | false | 
If enabled, PAN is tokenizen upon transaction approval and pan_token value is populated in transaction response.
Example:
var style = {} // define styling options for card component
var card = components.create("card", {
	style: style,
	tokenizePan: true // this will tokenize pan upon transaction approval
});
If enabled save card for future payments checkbox is presented to a customer. If user checks the checkbox, PAN is
tokenized upon transaction approval and pan_token value is populated in transaction response.
Example:
var style = {} // define styling options for card component
var card = components.create("card", {
	style: style,
	tokenizePanOffered: true // this will enable 'save card for future payments' checkbox in form
});
NOTICE - if tokenizePan is set to true then tokenizePanOffered is ignored.
NOTICE - setting tokenizePan to true requires user consent beforehand, in form of accepting terms and conditions
or alike.
If enabled & merchant has enabled installments then dropdown for installments selection will be shown.
Example:
var style = {} // define styling options for card component
var card = components.create("card", {
	style: style,
	showInstallmentsSelection: true // this will enable installments selection
});
NOTICE - if set to true and not shown then installments for merchant are disabled. Contact [email protected]
Here are the variables and their definitions used when generating JSON documents for API calls:
| 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 city | 
| ch_zip | 3-9 | alphanumeric | buyer’s 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 | 
| ch_email | 3-100 | alphanumeric | buyer’s email | 
| name | length | format | additional info | 
|---|---|---|---|
| order_info | 3-100 | alphanumeric | short description of order being processed | 
| order_number | 1-40 | printable characters | unique identifier | 
| amount | 3-11 | integer | amount is in minor units, ie. 10.24 USD is sent as 1024 | 
| currency | predefined | alphabetic | possible values are USD, EUR, BAM or HRK |