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 amount
value 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
minorUnits
element 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 payment
block 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>
Updated 6 months ago