5.3. Forms Customization

Payment Page Display Logic

  skinparam ConditionEndStyle hline
 : (1) Initiate transaction;
 if ((2) Additional Payer input required?) then (yes)
 : (3) return input form;
 : (4) submit form;
 else (no)
 endif
 if ((5) External form required?) then (yes)
 : (6) request external form from the payment provider;
 : (7) redirect to external form;
 : (8) submit form on payment provider side;
 else (no)
 endif
 : (9) show wait form;
 : (10) process transaction;
 : (11) show finish form or redirect \nto Connecting Party website;

(1) Transactions can be initiated with API requests, batch upload or via Virtual terminal on UI. Each payment method has its own payment page display logic.

Note

Payment Cashier might have multiple transactions initiated within the same payment session, because it can have multiple payment methods available for the Payer. When Payer selects payment tab, respective auxiliary transaction is initiated. See Payment Cashier Page Customization.

(3) For credit card payment method form is displayed on Payment Gateway side and can be customized. See Payment Page Customization. Some other payment methods may have additional forms on Payment Gateway side. Contact Billblend support for details.

(7) Some payment methods require the Payer to be redirected to their own form. That form is not hosted by Payment Gateway and can`t be customized.

(9) Until transaction reaches final status, Payment Gateway displays Wait Form for the Payer.

(11) After the transaction reaches the final status, Payment Gateway displays Finish Form for the Payer or Redirect to Connecting Party website.

Payment Page Customization

Payment Page Example

<html>
<head>
<script type="text/javascript">
  function isCCValid(r){var n=r.length;if(n>19||13>n)return!1;
    for(i=0,s=0,m=1,l=n;i<l;i++)d=parseInt(r.substring(l-i-1,l-i),10)*m,s+=d>=10?d%10+1:d,1==m?m++:m--;
    return s%10==0?!0:!1}
</script>
</head>
<body>
<h3>Order #$!MERCHANT_ORDER_ID - $!ORDERDESCRIPTION</h3>
<h3>Total amount: $!AMOUNT $!CURRENCY to $!MERCHANT</h3>
<form action="${ACTION}" method="post">
  <div>Cardholder name: <input name="${CARDHOLDER}" type="text" maxlength="64"/></div>
  <div><label for="cc-number">Credit Card Number</label> <input id="cc-number" name="${CARDNO}" type="text" maxlength="19" autocomplete="cc-number"/></div>
  <div>Card verification value: <input name="${CVV2}" type="text" maxlength="4" autocomplete="off"/></div>
  <div>
    Expiration date:
    <select class="expiry-month" name="${EXPMONTH}" size="1" autocomplete="cc-exp-month" >
      <option value="01">January</option><option value="02">February</option><option value="03">March</option>
      <option value="04">April</option><option value="05">May</option><option value="06">June</option>
      <option value="07">July</option><option value="08">August</option><option value="09">September</option>
      <option value="10">October</option><option value="11">November</option><option value="12">December</option>
    </select>
      <select class="expiry-year" id="cc-exp-year" name="${EXPYEAR}" size="1" autocomplete="cc-exp-year">
      ${EXPIRE_YEARS}
    </select>
  </div>
  <div><label for="dest-number">Destination card number:</label> <input id="dest-number" name="${DESTINATIONCARDNO}" type="text" maxlength="19" autocomplete="off"/></div>
  $!{INTERNAL_SECTION}
  #if($!card_error)
  <div style="color: red;">$!card_error</div>
  #end
  <input name="submit" onclick="return isCCValid(document.getElementById('cardnumber').value);" type="submit" value="Pay"/>
</form>
</body>
</html>

Note

The code described below allows to submit destination card data in Transfer type transactions:

<div><label for="dest-number">Destination card number:</label>
<input id="dest-number" name="${DESTINATIONCARDNO}" type="text" maxlength="19" autocomplete="off"/></div>

Payment Page Autofill

If Connecting Party wants to use autofill in payment form, certain element attributes <id> <autocomplete> <label for> should be hardcoded in the following manner:

<label for="cc-number">Credit Card Number</label><span class="form-label-comment">The 13-19 digits on the front of your card</span>
<input class="card-number-field" id="cc-number" name="${CARDNO}" type="text" maxlength="19" autocomplete="cc-number" />

If autofill in the transfer form must be used, certain element attributes <id> <autocomplete> <label for> should be hardcoded in the following manner:

#if ($INPUT_SOURCE_CARD_CARDHOLDER)
<!-- Card printed name field -->
<li class="form-li">
    <label class="form-label" for="cc-name">Card printed name:</label>
    <input class="form-name-field" id="cc-name" name="${CARDHOLDER}" type="text" maxlength="50" autocomplete="cc-name" value="${CARDHOLDER_VALUE}"/>
</li>
#end
#if ($INPUT_SOURCE_CARD_CVV2)
<!-- CVV field -->
<li class="form-li">
    <label class="form-label" for="${CVV2}">Card security code (CVV2/CVC2):</label>
    <input class="form-cvv-field" name="${CVV2}" id="${CVV2}" type="password" maxlength="4" autocomplete="off"/>
</li>
#end
#end
#if ($INPUT_DESTINATION_CARD)
<!-- Destination Card Number field -->
#if($!DESTINATIONCARDNO)
<li class="form-li">
    <label class="form-label" for="${DESTINATIONCARDNO}">Destination card number:</label>
    <input class="form-number-field" id="${DESTINATIONCARDNO}" name="${DESTINATIONCARDNO}" type="text" maxlength="19" autocomplete="off"/>
</li>
#end
#end

Billblend has default payment form template which supports autocomplete. In case if Connecting Party wants to add additional fields for autocomplete, this specification should be used for naming references.

Payment Page Template Macros

Field Name MacroField Value MacroDescription
${APPLE_PAY}n/aApple Pay buy button will be available if this macros is used. Not available for Transfer transactions.
${GOOGLE_PAY}n/aGoogle Pay buy button will be available if this macros is used. Not available for Transfer transactions.
${CARDNO}${CARDNOVALUE}Payer’s credit card number.
${EXPMONTH}n/aCredit card expiration month.
${EXPYEAR}n/aCredit card expiration year.
${CVV2}${CVV2VALUE}Card security code. Example: 432
${CARDHOLDER}${CARDHOLDER_VALUE}Card printed name.
${MERCHANT}n/aEnd point display name.
${SKIN_VERSION}n/aCSS skin version.
${ORDERDESCRIPTION}n/aOrder description.
${CUSTOMER_FIRST_NAME}n/aPayer first name sent by Connecting Party via input parameters.
${CUSTOMER_LAST_NAME}n/aPayer last name sent by Connecting Party via input parameters.
${CUSTOMER_EMAIL}n/aPayer E-mail address sent by Connecting Party via input parameters.
${DESTINATION_CARD_TYPE}n/aDestination card type. Available for Transfer transactions.
${DESTINATION_LAST_FOUR_DIGITS}n/aDestination card last four digits. Available for Transfer transactions.
${AMOUNT}n/aAmount.
${CURRENCY}n/aCurrency.
${DESTINATION_PURPOSE}n/aPurpose sent by Connecting Party via input parameters.
${PAYNET_ORDER_ID}n/aBillblend order id.
${MERCHANT_ORDER_ID}n/aConnecting Party order id.
${refresh_interval}n/aRefresh interval recommended by system.
${uuid}n/aInternal.
${INTERNAL_SECTION}n/aInternal for iFrame integration.
${CUSTOMER_IP_COUNTRY_ISO_CODE}n/aPayer country defined by IP Address.
${PREFERRED_LANGUAGE}n/aPayer language sent by Connecting Party via input parameters. Not available for Account Verification.
${BROWSER_LANGUAGE}n/aPayer language defined by browser settings.
${CUSTOMER_LANGUAGE}n/aPayer language send by Connecting Party via input parameters or defined by browser settings if first is not set.
${MERCHANT_FORM_DATA}n/aParameters sent in MERCHANT_FORM_DATA API parameter are parsed into macros with the same name, the parameter is url-encoded, example: testparam%3Dtest1%26mynewparam%3Dtest2 and is parsed into $MFD_testparam = test1 and $MFD_mynewparam = test2 macros in the form. Parameter name characters[a-zA-Z0-9], parameter value characters[a-zA-Z0-9], control characters [=&], 2MB max size. Not available for Account Verification. For example, this parameter can be used to display payment form in light/dark mode depending on the value passed by Connecting Party (e.g. pass merchant_form_data=theme%3Ddark in request and $MFD_theme macro placeholder on payment form will be changed to dark.
${MIN_AMOUNT}n/aThis macro has the value provided in minimum-transaction-amount parameter in initial request. It can be used to validate the transaction amount before payment form is submitted. Contact support manager to enable this feature.
${MAX_AMOUNT}n/aThis macro has the value provided in maximum-transaction-amount parameter in initial request. It can be used to validate the transaction amount before payment form is submitted. Contact support manager to enable this feature.
${CUSTOMER_ZIP_CODE}n/aGenerates a ZIP code if it was not received from the Payer. Not available for Account Verification.

Prefilled Cardholder Data in Payment Page

Payer’s cardholder data, used for processing of a previous transaction, can be tokenized for future use with request to /api/v2/create-card-ref/. The obtained token cardrefid then can be passed in the next requests to relevant API. If this parameter is sent, all cardholder data input will be immutable and prefilled on the payment page. CVV is not tokenized and must be provided by Payer on this payment page. Below is the example of form customization to work with prefilled cardholder data in payment page.

Note

This feature is available only for Sale and Preauth transaction types and cannot be used in Payment Cashier.

Prefilled Cardholder Data Payment Page Example

<html>
<head>
</head>
<body>
  <h3>Order #$!MERCHANT_ORDER_ID - $!ORDERDESCRIPTION</h3>
  <h3>Total amount: $!AMOUNT $!CURRENCY to $!MERCHANT</h3>
  <h4>Card Holder: ${CARDHOLDER} </h4>
  <h4>Card Number: $!CARD_BIN ...... $!CARD_LAST4DIGITS </h4>
  <h4>Exp year: $!EXPYEAR_VALUE </h4>
  <h4>Exp month: $!EXPMONTH_VALUE </h4>
  <form action="${ACTION}" method="post">
    <div>Cvv: <input name="${CVV2}" type="text" maxlength="4" autocomplete="off"/></div>
    $!{INTERNAL_SECTION}
    #if($!card_error)
      <div style="color: red;">$!card_error</div>
    #end
    <input name="submit" type="submit" value="Pay"/>
  </form>
</body>
</html>

Prefilled Cardholder Data Payment Page Macros

Field Name MacroField Value MacroDescription
${CARDHOLDER}n/aCardholder name.
${CARD_BIN}n/aFull card number.
${CARD_LAST4DIGITS}n/aLast 4 digits of the card.
${EXPMONTH_VALUE}n/aCard expiry month value.
${EXPYEAR_VALUE}n/aCard expiry year value.
${CVV2}n/aCVV2 card value.

Wait Page Customization

Wait Page Template

Wait Page is the form where the Payer’s stays on until transaction reaches it’s final status.

<html>
<head>
    <script type="text/javascript">
      function fc(t) {
        document.getElementById("seconds-remaining").innerHTML = t;
        (t > 0) ? setTimeout(function(){fc(--t);}, 1000) : document.checkform.submit();}
    </script>
</head>
<body onload="fc($!refresh_interval)">
    <h3>Order #$!MERCHANT_ORDER_ID - $!ORDERDESCRIPTION</h3>
    <h3>Total amount: $!AMOUNT $!CURRENCY to $!MERCHANT</h3>
    Please wait, your payment is being processed, remaining <span id="seconds-remaining">&nbsp;</span> seconds.
    <form name="checkform" method="post">
        <input type="hidden" name="tmp" value="$!uuid"/>
        $!{INTERNAL_SECTION}
        <input type="submit" value="Check" />
    </form>
</body>
</html>

Note

The code described below do not regard to the Account Verification:

<h3>Total amount: $!AMOUNT $!CURRENCY to $!MERCHANT</h3>

Wait Page Template Macros

Field Name MacroField Value MacroDescription
$!refresh_intervaln/aRefresh interval recommended by system.
$!MERCHANT_ORDER_IDn/aConnecting Party order id.
$!ORDERDESCRIPTIONn/aOrder description.
$!AMOUNTn/aAmount. Not available for Account verification.
$!CURRENCYn/aCurrency. Not available for Account verification.
$!MERCHANTn/aEnd point display name.
$!uuidn/aInternal.
$!{INTERNAL_SECTION}n/aInternal for iFrame integration.
${SKIN_VERSION}n/aCSS skin version.
${PAYNET_ORDER_ID}n/aBillblend order id.
${CUSTOMER_IP_COUNTRY_ISO_CODE}n/aPayer country defined by IP Address.
${PREFERRED_LANGUAGE}n/aPayer language send by Connecting Party via input parameters.
${BROWSER_LANGUAGE}n/aPayer language defined by browser settings.
${CUSTOMER_LANGUAGE}n/aPayer language send by Connecting Party via input parameters or defined by browser settings if first is not set.

Finish Page Customization

Finish Page Template

A form on which the Payer is shown the final status of his request.

<html>
    <head>
    </head>
    <body>
        <h3>Processing of the payment has finished</h3>
        <h3>Order Invoice: $!{MERCHANT_ORDER_ID}</h3>
        <h3>Order ID: $!{PAYNET_ORDER_ID}</h3>
        <h3>Status: $!{STATUS}</h3>
        #if($ERROR_MESSAGE)
            <h3>Error: $!{ERROR_MESSAGE}</h3>
        #end
    </body>
</html>

Finish Page Macros

Field Name MacroField Value MacroDescription
${STATUS}n/aOrder status.
${PAYNET_ORDER_ID}n/aSystem order id.
${MERCHANT_ORDER_ID}n/aConnecting Party order id.
${ERROR_MESSAGE}n/aContains the reason for decline or error details.
${SKIN_VERSION}n/aCSS skin version.
${CUSTOMER_IP_COUNTRY_ISO_CODE}n/aPayer country defined by IP Address.
${PREFERRED_LANGUAGE}n/aPayer language send by Connecting Party via input parameters.
${BROWSER_LANGUAGE}n/aPayer language defined by browser settings.
${CUSTOMER_LANGUAGE}n/aPayer language send by Connecting Party via input parameters or defined by browser settings if first is not set.
${AMOUNT}n/aAmount. Not available for Account verification.
${CURRENCY}n/aCurrency. Not available for Account verification.
${DESCRIPTION}n/aTransaction description. Not available for Account verification.
${DATE}n/aTransaction date. Not available for Account verification.
${PAYNET_PROCESSING_DATE}n/aBillblend processing date. Not available for Account verification.
${RRN}n/aRetrieval Reference Number. Not available for Account verification.
${AUTH_CODE}n/aAuthorization Code. Not available for Account verification.
${CARD_TYPE}n/aCard type. Not available for Account verification.
${LAST_FOUR_DIGITS}n/aLast four digits of a card. Not available for Account verification.
${CUSTOMER_REDIRECT_URL}n/aURL the cardholder will be redirected to upon completion of the transaction.

Payment Cashier Page Customization

Note

This page is relevant only for Payment Cashier integration.

Parallel Form Template Sample

Parallel Form is a form for the Payer to select one of the available payment methods to perform a transaction.

<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
</head>
<body>
<!-- country selector -->
<span id="countryIsoCode" style="display: none;">$!CUSTOMER_IP_COUNTRY_ISO_CODE</span>
<div class="container">
    <input name="customer_language_code" id="iso" type="hidden" value="$CUSTOMER_LANGUAGE"/>
    #if (!$HAS_PARALLEL_FORM_PAYMENT_METHODS)
        <select id="countrySelector" onchange="onCountrySelected(this);">
            <option value="EU">Europe</option>
            <!-- You may add other countries for selection to this list -->
        </select>
    #end
    #if ($HAS_PARALLEL_FORM_PAYMENT_METHODS)
        <div class="form-tabs">
            <ul id="formTabs" class="form-tabs-ul">
                #foreach ($paymentMethod in $PARALLEL_FORM_PAYMENT_METHODS)
                    <li id="$!{paymentMethod.identifier}-FORM-button" class="form-tab-button#if($velocityCount == 1) form-tab-button-active form-tab-button-active-$!{paymentMethod.identifier}#end" #if($paymentMethod.iframe) onclick="chooseIframe('$!{paymentMethod.identifier}');" #end>
                        $!{paymentMethod.name}
                    </li>
                #end
            </ul>
            <select id="countrySelector" onchange="onCountrySelected(this);">
                <option value="EU">Europe</option>
                <!-- You may add other countries for selection to this list -->
            </select>
        </div>
    #foreach ($paymentMethod in $PARALLEL_FORM_PAYMENT_METHODS)
        <div class="ssl-header ssl-header-$!{paymentMethod.identifier}" id="merchant-description-$!{paymentMethod.identifier}" #if ($velocityCount> 1) style="display: none;"#end>
            <span class="ssl-text">${MERCHANT}</span>
            <div>
                <span class="flag-EN" id="flag-$!{paymentMethod.identifier}"></span>
                <select id="langSelector-$!{paymentMethod.identifier}" class="langSelector langSelector-$!{paymentMethod.identifier}" onchange="selectLang('$!{paymentMethod.identifier}');">
                    <option value="EN">English</option>
                    <!-- You may add other languages for selection to this list -->
                </select>
            </div>
        </div>
        <script>
            merchantDescriptionIds.push("merchant-description-$!{paymentMethod.identifier}");
            paymentMethodsCountries["$!{paymentMethod.identifier}"] = "$!{paymentMethod.countries}";
        </script>
    #end
    #end
    #if ($HAS_PARALLEL_FORM_PAYMENT_METHODS)
        #foreach ($paymentMethod in $PARALLEL_FORM_PAYMENT_METHODS)
            #if ($paymentMethod.iframe)
                <div class="frame-container-$!{paymentMethod.identifier} payment-method-iframe" id="$!{paymentMethod.identifier}-FORM" pneopen="#if ($velocityCount == 1)true#{else} false#end" pnesrc="$!paymentMethod.initSessionUrl" #if ($velocityCount> 1) style="display: none;"#end>
                    <iframe src="#if ($velocityCount == 1)$!paymentMethod.initSessionUrl#end" scrolling="#if $!{paymentMethod.identifier} == 'QIWI' || $!{paymentMethod.identifier} == 'ASTROPAY')yes#{else}no#end">
                    </iframe>
                </div>
            #end
        #end
        <form id="waitForm" action="$!WAIT_FORM_URL">
            #foreach( $p in $WAIT_FORM_PARAMETERS )
                <input type="hidden" name="$p.key" value="$!p.value">
            #end
            <!--$!{INTERNAL_SECTION}-->
        </form>
    #end
</div>
</body>
</html>

For more information see Country Codes and Language Codes.

Parallel Form Macros

Field Name MacroField Value MacroDescription
$!CUSTOMER_IP_COUNTRY_ISO_CODEn/aPayer`s country defined by IP Address.
$!CUSTOMER_COUNTRY_CODEn/aBilling country of customer sent in incoming API request.
$CUSTOMER_LANGUAGEn/aPayer language sent by Connecting Party via input parameters or defined by browser settings if first is not set.
$HAS_PARALLEL_FORM_PAYMENT_METHODSn/aDetermines the availability of parallel form payment methods.
$paymentMethodn/aPayment method object.
$PARALLEL_FORM_PAYMENT_METHODSn/aArray with available parallel form payment methods.
$!{paymentMethod.identifier}n/aPayment method identifier.
$velocityCountn/aSequence number of the payment method.
$paymentMethod.iframen/aIframe of payment method.
$!{paymentMethod.name}n/aPayment method name.
${MERCHANT}n/aEnd point display name.
$!{paymentMethod.countries}n/aCountries which are set for this payment method.
$$!paymentMethod.initSessionUrln/aURL for payment method session initialization.
$!WAIT_FORM_URLn/aWaiting form URL.
$pn/aWaiting form parameter.
$WAIT_FORM_PARAMETERSn/aWaiting form parameters array.
$p.keyn/aWaiting form parameter key.
$!p.valuen/aWaiting form parameter value.
$!{INTERNAL_SECTION}n/aInternal for iFrame integration.

Parallel Form Scripts

The following Parallel Form scripts are required for it`s operating. The first script should be added into <head> tag of html document:

<script type="text/javascript">
var merchantDescriptionIds = [];
var paymentMethodsCountries = {};
function isCCValid(r) {
    var n = r.length;
    if (n > 19 || 13 > n) return !1;
    for (i = 0, s = 0, m = 1, l = n; i < l; i++) d = parseInt(r.substring(l - i - 1, l - i), 10) * m, s += d >= 10 ? d % 10 + 1 : d, 1 == m ? m++ : m--;
    return s % 10 == 0 ? !0 : !1
}

function runPayment(t) {
    if (isCCValid(t)) {
        return !0;
    } else {
        document.getElementById('cardnumber').style.borderColor = '#fb860f';
        return !1;
    }
}

function chooseIframe(paymentMethodName) {
    var id = paymentMethodName + '-FORM';
    var iframes = document.getElementsByTagName('IFRAME');
    for (var i = 0; i < iframes.length; i++) {
        var iframe = iframes[i].parentNode;
        var isCurrent = iframe.id == id;
        iframe.style.display = isCurrent ? 'block' : 'none';
        if (isCurrent && iframe.getAttribute("pneopen") == 'false') {
            iframe.firstElementChild.src = iframe.getAttribute("pnesrc") + "?country=" + document.getElementById("countryIsoCode").innerText;
            iframe.setAttribute("pneopen", 'true');
        }
        var buttonElem = document.getElementById(iframe.id + '-button');
        buttonElem.className = (iframe.id == id) ? 'form-tab-button form-tab-button-active form-tab-button-active-' + paymentMethodName : 'form-tab-button';
    }
    var descriptionId = 'merchant-description-' + paymentMethodName;
    for (var i = 0; i < merchantDescriptionIds.length; i++) {
        var isCurrent = merchantDescriptionIds[i] == descriptionId;
        document.getElementById(merchantDescriptionIds[i]).style.display = isCurrent ? 'flex' : 'none';
    }
}

function pneInit() {
    window.pneMasterSessionProcessed = function() {
        document.getElementById('waitForm').submit()
    }
    foreach( $paymentMethod in $PARALLEL_FORM_PAYMENT_METHODS )
        if( $paymentMethod.default )chooseIframe('$!{paymentMethod.identifier}-FORM');
        break
    end
    end
}
</script>

Second script should be added to html code before the </body> close tag.

<script type="text/javascript">
function updateTabsVisibility() {
    var countryCode = getSelectedCountryCode();
    var paymentMethods = getPaymentMethods();
    var someIframeShown = false;
    for (var i = 0; i < paymentMethods.length; i++) {
        var paymentMethod = paymentMethods[i];
        var visible = isPaymentMethodVisible(paymentMethod, countryCode);
        updateTabVisibility(paymentMethod, visible);
        if (visible && !someIframeShown) {
            chooseIframe(paymentMethod);
            someIframeShown = true;
        }
    }
}

function getSelectedCountryCode() {
    return document.getElementById('countryIsoCode').innerText;
}

function setSelectedCountryCode(countryCode) {
    document.getElementById('countryIsoCode').innerText = countryCode;
}

function getPaymentMethods() {
    var lis = document.getElementById("formTabs").children;
    var result = [];
    for (var i = 0; i < lis.length; i++) {
        var li = lis[i];
        var id = li.id;
        if (id != null) {
            result.push(id.substring(0, id.indexOf("-FORM-button")));
        }
    }
    return result;
}

function isPaymentMethodVisible(paymentMethodId, countryCode) {
    if (paymentMethodsCountries[paymentMethodId] == "") {
        return true;
    } else {
        return paymentMethodsCountries[paymentMethodId].indexOf(countryCode) > -1;
    }
}

function updateTabVisibility(paymentMethod, visible) {
    document.getElementById(paymentMethod + '-FORM-button').style.display = visible ? 'inline-block' : 'none';
}

function onCountrySelected(selector) {
    setSelectedCountryCode(selector.value);
    updateTabsVisibility();
}

document.addEventListener('DOMContentLoaded', function() {
    pneInit();
    updateTabsVisibility();
    document.getElementById('countrySelector').value = getSelectedCountryCode();
});

function syncLangSelectors(ISO) {
    var methods = getPaymentMethods();
    for (var i = 0; i < methods.length; i++) {
        document.getElementById('flag-' + methods[i]).className = "flag-" + ISO;
        document.getElementById('langSelector-' + methods[i]).value = ISO;
    }
}

var ISO = document.getElementById('iso').value.toUpperCase();
ISO = 'EN';
document.getElementById('iso').value = ISO;
syncLangSelectors(ISO);

document.addEventListener('DOMContentLoaded', function() {
    //l10n();
});

function selectLang(method) {
    var ISO = document.getElementById('langSelector-' + method).value.toUpperCase();
    document.getElementById('iso').value = ISO;

    syncLangSelectors(ISO);
    //l10n();
}
</script>

If needed to determine the Payer billing country on the data sent via the API, $!CUSTOMER_COUNTRY_CODE is used. If needed to determine the Payer billing country on the IP address from the Payer browser, use $!CUSTOMER_IP_COUNTRY_ISO_CODE, billing country will also change according to IP.

The master set up by Billing country:

<span id="countryIsoCode" style="display: none;">$!CUSTOMER_COUNTRY_CODE</span>
<input name="customer_language_code" id="iso" type="hidden" value="$CUSTOMER_LANGUAGE"/>
        <div class="country-select">

Contact us

By clicking on the button, you agree to the data protection policy

Complete the quiz

By clicking on the button, you agree to the data protection policy