diff --git a/metadata/site_import/meta/system-objecttype-extensions.xml b/metadata/site_import/meta/system-objecttype-extensions.xml index b096fa6e2..883155cb0 100644 --- a/metadata/site_import/meta/system-objecttype-extensions.xml +++ b/metadata/site_import/meta/system-objecttype-extensions.xml @@ -529,6 +529,15 @@ 0 0 + + Selected StoreId for Terminal API + Selected StoreId for Terminal API + string + false + false + 0 + 0 + X-API-KEY of Web service X-API-KEY of Web service @@ -713,6 +722,7 @@ + diff --git a/metadata/site_import/services.xml b/metadata/site_import/services.xml index 2d884663e..764b4e732 100644 --- a/metadata/site_import/services.xml +++ b/metadata/site_import/services.xml @@ -110,6 +110,16 @@ + + https://management-test.adyen.com/v3/stores + + + + + https://management-live.adyen.com/v3/stores + + + 30000 @@ -228,4 +238,13 @@ Adyen AdyenPaypalUpdateOrder + + HTTP + true + adyen + true + false + Adyen + AdyenManagementApiGetStores + diff --git a/src/cartridges/bm_adyen/cartridge/controllers/AdyenSettings.js b/src/cartridges/bm_adyen/cartridge/controllers/AdyenSettings.js index 4ad5cf358..ac3deffa1 100644 --- a/src/cartridges/bm_adyen/cartridge/controllers/AdyenSettings.js +++ b/src/cartridges/bm_adyen/cartridge/controllers/AdyenSettings.js @@ -6,6 +6,7 @@ const AdyenConfigs = require('*/cartridge/adyen/utils/adyenConfigs'); const AdyenHelper = require('*/cartridge/adyen/utils/adyenHelper'); const constants = require('*/cartridge/adyen/config/constants'); const AdyenLogs = require('*/cartridge/adyen/logs/adyenCustomLogs'); +const bmHelper = require('*/cartridge/utils/helper'); server.get('Start', (_req, res, next) => { if (!csrfProtection.validateRequest()) { @@ -84,4 +85,32 @@ server.post('TestConnection', server.middleware.https, (req, res, next) => { return next(); }); +server.get('GetStores', server.middleware.https, (req, res, next) => { + try { + const service = bmHelper.initializeAdyenService( + constants.SERVICE.GETSTORES, + 'GET', + ); + const merchantAccount = AdyenConfigs.getAdyenMerchantAccount(); + const callResult = service.call(JSON.stringify({ merchantAccount })); + + if (!callResult.isOk()) { + throw new Error('/getStores call failed'); + } + const resultObject = callResult.object; + const response = JSON.parse(resultObject.getText()); + const mappedData = response.data.map((store) => ({ + id: store.id, + description: store.description, + })); + + bmHelper.saveMetadataField('Adyen_StoreId', mappedData); + res.json({ success: true, stores: mappedData }); + } catch (error) { + AdyenLogs.error_log('Error while fetching stores:', error); + res.json({ success: false }); + } + return next(); +}); + module.exports = server.exports(); diff --git a/src/cartridges/bm_adyen/cartridge/static/default/js/adyenSettings.js b/src/cartridges/bm_adyen/cartridge/static/default/js/adyenSettings.js index c5a3c9831..08892b316 100644 --- a/src/cartridges/bm_adyen/cartridge/static/default/js/adyenSettings.js +++ b/src/cartridges/bm_adyen/cartridge/static/default/js/adyenSettings.js @@ -47,6 +47,17 @@ const expressPaymentMethods = [ }, ]; +document.addEventListener('DOMContentLoaded', async () => { + const response = await fetch('AdyenSettings-GetStores', { + headers: { + 'Content-Type': 'application/json; charset=utf-8', + }, + method: 'GET', + }); + const result = await response.json(); + return result; +}); + document.addEventListener('DOMContentLoaded', () => { const form = document.querySelector('#settingsForm'); const troubleshootingForm = document.querySelector('#troubleshootingForm'); @@ -89,12 +100,28 @@ document.addEventListener('DOMContentLoaded', () => { const params = 'resizable=yes,width=1000,height=500,left=100,top=100'; const draggableList = document.getElementById('draggable-list'); + const availableStores = document.getElementById('storeID').value; + const terminalDropdown = document.getElementById('terminalDropdown'); + const activeSelectedStores = document.getElementById('selectedStoreID').value; let ruleCounter = 0; const installmentsResult = {}; const listItems = []; let dragStartIndex; + function renderStores() { + const stores = JSON.parse(availableStores); + stores.forEach((store) => { + const option = document.createElement('option'); + option.value = store.id; + option.textContent = `${store.description} (${store.id})`; + terminalDropdown.appendChild(option); + if (activeSelectedStores.includes(store.id)) { + option.selected = true; + } + }); + } + function settingChanged(key, value) { const settingIndex = changedSettings.findIndex( (setting) => setting.key === key, @@ -563,26 +590,40 @@ document.addEventListener('DOMContentLoaded', () => { })(); }); - // add event listener to maintain form updates - form.addEventListener('change', (event) => { - const { name } = event.target; - let { value } = event.target; // get checked boolean value for checkboxes - - if (event.target.type === 'checkbox') { - value = event.target.checked; - } + function parseRadioValue(rawValue) { + if (rawValue === 'true') return true; + if (rawValue === 'false') return false; + return rawValue; + } - // convert radio button strings to boolean if values are 'true' or 'false' - if (event.target.type === 'radio') { - if (event.target.value === 'true') { - value = true; - } + function getMultipleSelectValues(selectedOptions) { + return Array.from(selectedOptions) + .map((option) => option.value) + .join(','); + } - if (event.target.value === 'false') { - value = false; - } + function getValueFromInput(type, rawValue, checked, selectedOptions) { + if (type === 'checkbox') { + return checked; } + if (type === 'select-multiple') { + return getMultipleSelectValues(selectedOptions); + } + if (type === 'radio') { + return parseRadioValue(rawValue); + } + return rawValue; + } + form.addEventListener('change', (event) => { + const { + name, + type, + value: rawValue, + checked, + selectedOptions, + } = event.target; + const value = getValueFromInput(type, rawValue, checked, selectedOptions); settingChanged(name, value); }); @@ -648,5 +689,6 @@ document.addEventListener('DOMContentLoaded', () => { window.location.reload(); }); + renderStores(); createExpressPaymentsComponent(expressPaymentMethods, draggableList); }); diff --git a/src/cartridges/bm_adyen/cartridge/templates/default/adyenSettings/settingCards/posSettings.isml b/src/cartridges/bm_adyen/cartridge/templates/default/adyenSettings/settingCards/posSettings.isml index f19557b49..cf8ab9888 100644 --- a/src/cartridges/bm_adyen/cartridge/templates/default/adyenSettings/settingCards/posSettings.isml +++ b/src/cartridges/bm_adyen/cartridge/templates/default/adyenSettings/settingCards/posSettings.isml @@ -13,7 +13,11 @@ If you want a POS in your physical store, enter the unique store ID. Keep in mind that you can only assign your POS to a single store.
- + + +
diff --git a/src/cartridges/bm_adyen/cartridge/utils/helper.js b/src/cartridges/bm_adyen/cartridge/utils/helper.js new file mode 100644 index 000000000..c59a137af --- /dev/null +++ b/src/cartridges/bm_adyen/cartridge/utils/helper.js @@ -0,0 +1,31 @@ +const Site = require('dw/system/Site'); +const Transaction = require('dw/system/Transaction'); +const AdyenConfigs = require('*/cartridge/adyen/utils/adyenConfigs'); +const AdyenHelper = require('*/cartridge/adyen/utils/adyenHelper'); + +// Helper function to save to metadata field +function saveMetadataField(field, data) { + const currentSite = Site.getCurrent(); + Transaction.wrap(() => { + currentSite.setCustomPreferenceValue(field, JSON.stringify(data)); + }); +} + +// Helper function to initialize a service +function initializeAdyenService(svc, reqMethod) { + const service = AdyenHelper.getService(svc, reqMethod); + const apiKey = AdyenConfigs.getAdyenApiKey(); + const merchantAccount = AdyenConfigs.getAdyenMerchantAccount(); + + if (!service || !apiKey || !merchantAccount) { + throw new Error('Missing request parameters, could not perform the call'); + } + + service.addHeader('Content-type', 'application/json'); + service.addHeader('charset', 'UTF-8'); + service.addHeader('X-API-key', apiKey); + + return service; +} + +module.exports = { saveMetadataField, initializeAdyenService }; diff --git a/src/cartridges/int_adyen_SFRA/cartridge/adyen/config/constants.js b/src/cartridges/int_adyen_SFRA/cartridge/adyen/config/constants.js index 2c4759fce..1179575c4 100644 --- a/src/cartridges/int_adyen_SFRA/cartridge/adyen/config/constants.js +++ b/src/cartridges/int_adyen_SFRA/cartridge/adyen/config/constants.js @@ -49,6 +49,7 @@ module.exports = { CANCELPARTIALPAYMENTORDER: 'AdyenCancelPartialPaymentOrder', PARTIALPAYMENTSORDER: 'AdyenPartialPaymentsOrder', PAYPALUPDATEORDER: 'AdyenPaypalUpdateOrder', + GETSTORES: 'AdyenManagementApiGetStores', }, CONTRACT: { ONECLICK: 'ONECLICK', diff --git a/src/cartridges/int_adyen_SFRA/cartridge/adyen/utils/adyenConfigs.js b/src/cartridges/int_adyen_SFRA/cartridge/adyen/utils/adyenConfigs.js index c6f5831a4..e2c57144d 100644 --- a/src/cartridges/int_adyen_SFRA/cartridge/adyen/utils/adyenConfigs.js +++ b/src/cartridges/int_adyen_SFRA/cartridge/adyen/utils/adyenConfigs.js @@ -98,6 +98,10 @@ const adyenConfigsObj = { return getCustomPreference('Adyen_StoreId'); }, + getAdyenActiveStoreId() { + return getCustomPreference('Adyen_SelectedStoreID'); + }, + getAdyenApiKey() { return getCustomPreference('Adyen_API_Key'); }, diff --git a/src/cartridges/int_adyen_SFRA/cartridge/adyen/utils/adyenHelper.js b/src/cartridges/int_adyen_SFRA/cartridge/adyen/utils/adyenHelper.js index 9cad8e3f1..36ba7f41b 100644 --- a/src/cartridges/int_adyen_SFRA/cartridge/adyen/utils/adyenHelper.js +++ b/src/cartridges/int_adyen_SFRA/cartridge/adyen/utils/adyenHelper.js @@ -42,13 +42,13 @@ const AdyenLogs = require('*/cartridge/adyen/logs/adyenCustomLogs'); /* eslint no-var: off */ let adyenHelperObj = { // Create the service config used to make calls to the Adyen Checkout API (used for all services) - getService(service) { + getService(service, reqMethod = 'POST') { let adyenService = null; try { adyenService = LocalServiceRegistry.createService(service, { createRequest(svc, args) { - svc.setRequestMethod('POST'); + svc.setRequestMethod(reqMethod); if (args) { return args; }