Using MCP (Multi-Currency Pricing) with the WebSDK

📘

Before you start

This guide assumes that you have already integrated with the WebSDK component for N-Genius Online. If this is not the case, you should refer to Web SDK Integration Guide before attempting to further integrate the MCP feature of this service.

Step 1: Retrieve Available Currencies:

First, ensure that MCP is enabled for your integration, and can be switched on/off during testing by setting the relevant constant in your merchant server script:

const isMCPEnabled = true|false 		// set to 'true' to enable MCP

You need to define the appendOptionInDropDown function.

Example:
1.	function appendOptionInDropDown(currency) {
2.	  const option = document.createElement('option');
3.	  option.value = currency.currencyCode;
4.	  option.text = currency.currencyCode;
5.	  return option;
};

Next, create a currency drop-down (select) in your UI with an appropriate input identifier and bind the getSupportedCurrencies() method from the NI WebSDK to this currency dropdown input.

Example:

<select class="currency-list" id="currency-list">
  <option value="" disabled>Select Currency</option>
</select>
function getSupportedCurrencies() 
{
const currencyInput = document.getElementById('currency-list');
let defaultCurrencyValue = merchantCurrency; // set merchant currency value
let isCurrencyListNull = true;
try {
  const {
    response: currencyListResponse,
    error
  } = await window.NI.handleGetSupportedCurrencies('currency-input', {
    style,
    apiKey,
    outletRef: testOutletRef,
    merchantCurrency
  });
  if (currencyListResponse.currencyList) {
    const { currencyList } = currencyListResponse;
    currencyList.forEach(currency => {
      const currencyOption = appendOptionInDropDown(currency);
      currencyInput.append(currencyOption);
    });
    defaultCurrencyValue = currencyList[0].currencyCode;
    isCurrencyListNull = false;
  }
  if (
    (currencyListResponse.currencyList &&
      currencyListResponse.currencyList.length === 0) ||
    !currencyListResponse.currencyList ||
    error
  ) {
    const currencyOption = appendOptionInDropDown(defaultCurrenyOption);
    currencyInput.append(currencyOption);
    if (error) console.error('===currency list error', error);
  }
} catch (e) {
  console.error('===currency list error', e);
  const currencyOption = appendOptionInDropDown(defaultCurrenyOption);
  currencyInput.append(currencyOption);
}
document.getElementById('currency-list').value = defaultCurrencyValue;
if (!isCurrencyListNull) {
  getConvertedAmountForCurrency(); // call forex currency conversion when currency list been shown
}
}

The above example provides the logic to bind the currency list from the N-Genius Online API response, and insert these as option elements list in the currency drop down.

A sample of the currency response from the N-Genius Online API is below.

  • Error exemption has been handled when the API call fails or any other subsequent calls fail inside the getSupportedCurrencies() method, and should be interrogated from there.
  • If the API call or logic fails, getSupportedCurrencies() method will append the merchant currency code (only) in the select dropdown input, to ensure that payment processing falls back to the default (non-FX) mode.

Step 2: Currency Conversion

Assuming no API or logic failures are present from the above step, the next step is to execute the currency conversion on the basket amount for the shopper/card-holder.

The method getConvertedAmountForCurrency()should be used to retrieve the MCP converted value for the card-holder's total payment amount in the currencies available from the previous step. This method calls the N-Genius Online FX lookup APIs to get the currency conversion response from the NI SDK.

As such, you should bind the getConvertedAmountForCurrency()method to the dropdown input component we created in the previous step:

<select
  class="currency-list"
  id="currency-list"
  onchange="payment.getConvertedAmountForCurrency()">
  <option value="" disabled>Select Currency</option>
</select>

The inclusion of the onchange="payment.getConvertedAmountForCurrency()"instruction will trigger the currency conversion method as described above, and will execute each time the user selects a new option from this dropdown input.

When the getConvertedAmountForCurrency() method is executed, it will fetch the currency dropdown input value and send it to the N-Genius OnlineFX API to retrieve the converted amountvalue in the user's chosen currency.

<!----HTML------!>
<div id="currency-conversion-value">
  <span class="">Converted Amount</span>
  <span class="" id="converted-amount-value"></span>
</div>


{* Style *}
#currency-conversion-value {
  display: none;
  flex-direction: row;
  padding: 10px 0;
  margin-bottom: 25px;
  justify-content: space-between;
}

To show the converted currency value in the screen add the above code in index.html and index.css.

<!----HTML------!>
<div id="currency-conversion-value">
  <span class="">Converted Amount</span>
  <span class="" id="converted-amount-value"></span>
</div>


{* Style *}
#currency-conversion-value {
  display: none;
  flex-direction: row;
  padding: 10px 0;
  margin-bottom: 25px;
  justify-content: space-between;
}
To show the converted currency value in the screen add the above code in index.html and index.css

 

When getConvertedAmountForCurrency() method triggered, it will fetch the currency dropdown input value and send it to the api to get the converted amount data.

funtion getConvertedAmountForCurrency() 
{
document.getElementById('currency-conversion-value').style.display = 'none';
const selectedCurrencyCode = document.getElementById('currency-list').value;

// To avoid forex currency conversion when selected currency value is same as merchant currency
if (merchantCurrency === selectedCurrencyCode) {
  console.info(
    '=====Target currency is same as Merchant currency. So currency conversion is not needed'
  );
  return null;
}

try {
  const {
    response: convertedAmountResponse,
    error
  } = await window.NI.handleForexCurrencyConversion('currency-conversion', {
    style,
    apiKey,
    outletRef: testOutletRef,
    orderAmount: {
      value: orderAmount,
      currencyCode: merchantCurrency
    },
    targetCurrencyCode: selectedCurrencyCode
  });
  if (error) {
    console.error('===forex converted amount error', error);
    return null;
  }
  
  // bind converted currency value in html code
  document.getElementById('currency-conversion-value').style.display = 'flex';
  document.getElementById(
    'converted-amount-value'
  ).innerHTML = convertedAmountResponse;

  return convertedAmountResponse;
} catch (e) {
  console.error('===forex converted amount error', e);
  return null;
}
}

This response contains the final converted amount data for the selected currency, along with the order amount.

Sample response:

🚧

Handling Minor Units

Since the N-Genius Online APIs typically handle all currency amounts in minor units (i.e. 100.00 AED becomes a value of 10000, it is important to ensure that your UI can handle minor units effectively, and to the local conventions of the shopper.

For example, whilst most currencies use two decimal points to represent sub-unit values (i.e. AED, GBP, USD, etc.), other currencies may use more than two decimal points, only one or none at all. The number of minor units a currency expects is denoted by the minorUnitselement of each currency block.

Failure to accommodate this in your UI is likely to result in shoppers paying more/less than expected for any given transaction, or in transaction failure altogether.

Step 3: Complete Payment with Chosen Currency

The third and final step will be to process the payment in the currency chosen by the shopper.

It is important to note, at this stage, that you must always provide an option for the card-holder to pay in the default merchant currency (likely AED for merchants operating in the UAE), and that all alternative currency payment options are clearly marked as such in your chosen UI design.

To complete the payment, please refer to Step 4 (onwards) from the Web SDK Integration Guidearticle, ensuring that the card-holder's chosen currency value from the previous steps in this guide is reflected in the API call from your server to N-Genius Online, as below.

Note the addition of a paymentblock to the server request:

{
      "action": "PURCHASE",
      "amount": {
        "currencyCode": "AED",			// original currency
        "value": 100								// original amount
      },
      "payment": {
        "currency": "USD"						// target currency
      }
    }

Sample Code Snippet

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <meta http-equiv="X-UA-Compatible" content="ie=edge" />
        <!--SDK url with rest of your scripts-->
        <script
            src="https://paypage.sandbox.ngenius-payments.com/hosted-sessions/sdk.js"></script>
    </head>
    <body>
        <!--Your website code goes here-->
        <div style="width: 500px; height: 220px;" id="mount-id"></div>
        <div style="width: 100%; height: 20px;" id="currency-input"></div>
        <div style="width: 100%; height: 20px;" id="currency-conversion"></div>
        <select class="currency-list" id="currency-list"
            onchange="getConvertedAmountForCurrency()">
            <option value disabled>Select Currency</option>
        </select>
        <div id="currency-conversion-value">
            <span class>Converted Amount</span>
            <span class id="converted-amount-value"></span>
        </div>
    </body>
    <script>
    // variables required
    const isMCPEnabled = true
    const orderAmount = 100
    const style = {
      input: {
        borderStyle: 'solid',
        borderWidth: '1px',
        padding: '10px 5px',
        borderColor: 'black',
        borderRadius: '10px'
      }
    }
    const apiKey =
      'API_KEY'
    const outletRef = 'OUTLET_REF'
    const merchantCurrency = 'GBP'
    const defaultCurrenyOption = {
      currencyCode: merchantCurrency
    }

    // functions required
    function appendOptionInDropDown (currency) {
      const option = document.createElement('option')
      option.value = currency.currencyCode
      option.text = currency.currencyCode
      return option
    }

    async function getConvertedAmountForCurrency () {
      document.getElementById('currency-conversion-value').style.display = 'none'
      const selectedCurrencyCode = document.getElementById('currency-list').value

      if (merchantCurrency === selectedCurrencyCode) {
        console.info(
          '=====Target currency is same as Merchant currency. So currency conversion is not needed'
        )
        return null
      }

      try {
        const { response: convertedAmountResponse, error } =
          await window.NI.handleForexCurrencyConversion('currency-conversion', {
            style,
            apiKey,
            outletRef,
            orderAmount: {
              value: orderAmount,
              currencyCode: merchantCurrency
            },
            targetCurrencyCode: selectedCurrencyCode
          })
        if (error) {
          console.error('===forex converted amount error', error)
          return null
        }
        if (convertedAmountResponse === 'FAILED') {
          console.error('===forex convertion failed', error)
          document.getElementById('currency-conversion-value').style.display =
            'flex'
          document.getElementById(
            'converted-amount-value'
          ).innerHTML = `<span style="display: block; text-align: end;">${convertedAmountResponse}</span>
            <span style="display: block; text-align: end; width: 120px; margin-top: 10px;">
              Please select a different currency.
            </span>`
          return null
        }
        if (
          convertedAmountResponse &&
          !convertedAmountResponse.includes(selectedCurrencyCode)
        ) {
          console.error(
            '===forex converted amount is different than selected amount'
          )
          document.getElementById('currency-conversion-value').style.display =
            'flex'
          document.getElementById(
            'converted-amount-value'
          ).innerHTML = `<span style="display: block; text-align: end;">${convertedAmountResponse}</span>
            <span style="display: block; text-align: end; width: 120px; margin-top: 10px;">
              Couldn't convert to selected currency, Showing converted amount in your local currency. Please select a different currency.
            </span>`
          return null
        }
        document.getElementById('currency-conversion-value').style.display = 'flex'
        document.getElementById('converted-amount-value').innerHTML =
          convertedAmountResponse
        return convertedAmountResponse
      } catch (e) {
        console.error('===forex converted amount error', e)
        return null
      }
    }

    async function getSupportedCurrencies () {
      const currencyInput = document.getElementById('currency-list')
      let defaultCurrencyValue = merchantCurrency // define merchantCurrency - 1
      let isCurrencyListNull = true
      try {
        const { response: currencyListResponse, error } =
          await window.NI.handleGetSupportedCurrencies('currency-input', {
            style, 
            apiKey, 
            outletRef,
            merchantCurrency
          })
        if (currencyListResponse.currencyList) {
          const { currencyList } = currencyListResponse
          currencyList.forEach(currency => {
            const currencyOption = appendOptionInDropDown(currency)
            currencyInput.append(currencyOption)
          })
          defaultCurrencyValue = currencyList[0].currencyCode
          isCurrencyListNull = false
        }
        if (
          (currencyListResponse.currencyList &&
            currencyListResponse.currencyList.length === 0) ||
          !currencyListResponse.currencyList ||
          error
        ) {
          const currencyOption = appendOptionInDropDown(defaultCurrenyOption)
          currencyInput.append(currencyOption)
          if (error) console.error('===currency list error', error)
        }
      } catch (e) {
        console.error('===currency list error', e)
        const currencyOption = appendOptionInDropDown(defaultCurrenyOption)
        currencyInput.append(currencyOption)
      }
      document.getElementById('currency-list').value = defaultCurrencyValue
      if (!isCurrencyListNull) {
        getConvertedAmountForCurrency() // call forex currency conversion when currency list been shown
      }
    }

    // mount card and fetch  all the supported currencies
    window.onload = function () {
      window.NI.mountCardInput('mount-id' /* the mount id*/, {
        style, // Style configuration you can pass to customize the UI
        apiKey, // // Hosted Session Key which is used to generate Session ID
        outletRef, // outlet reference from the portal
        onSuccess: getSupportedCurrencies, // Success callback if hostedSessionApiKey validation succeeds
        onFail: () => {},
        onChangeValidStatus: () => {}
      })
    }
    </script>
</html>