From e97f7dbd81603af60c608f5467faa2ef5b2fa4c7 Mon Sep 17 00:00:00 2001 From: Tadas Labutis Date: Fri, 23 Jan 2026 15:14:16 +0200 Subject: [PATCH] Improve dynamic terminal selection with AJAX loading --- ...dminSaferPayOfficialSettingsController.php | 55 +++++ src/Service/SaferPayTerminalService.php | 6 +- views/js/admin/saferpay_settings.js | 215 +++++++++++++++++- .../admin/partials/field-terminal-id.tpl | 59 +++-- 4 files changed, 307 insertions(+), 28 deletions(-) diff --git a/controllers/admin/AdminSaferPayOfficialSettingsController.php b/controllers/admin/AdminSaferPayOfficialSettingsController.php index 701ffa418..2c06629b7 100644 --- a/controllers/admin/AdminSaferPayOfficialSettingsController.php +++ b/controllers/admin/AdminSaferPayOfficialSettingsController.php @@ -51,9 +51,64 @@ public function __construct() public function initContent() { + if (Tools::getValue('ajax') && Tools::getValue('action') === 'getTerminals') { + $this->displayAjaxGetTerminals(); + return; + } + parent::initContent(); } + public function displayAjaxGetTerminals() + { + $environment = Tools::getValue('environment', 'live'); + $customerId = Tools::getValue('customer_id'); + $username = Tools::getValue('username'); + $password = Tools::getValue('password'); + + if (empty($customerId) || empty($username) || empty($password)) { + $this->ajaxRender(json_encode([ + 'success' => false, + 'error' => $this->module->l('Customer ID, Username, and Password are required', self::FILE_NAME), + 'terminals' => [], + ])); + die(); + } + + $isTestMode = $environment === 'test'; + + try { + /** @var SaferPayTerminalService $terminalService */ + $terminalService = $this->module->getService(SaferPayTerminalService::class); + + $terminals = $terminalService->getAvailableTerminals($customerId, $username, $password, $isTestMode); + + $this->ajaxRender(json_encode([ + 'success' => true, + 'terminals' => $terminals, + 'count' => count($terminals), + ])); + die(); + } catch (Exception $e) { + /** @var LoggerInterface $logger */ + $logger = $this->module->getService(LoggerInterface::class); + $logger->error(sprintf('%s - AJAX failed to get terminals: %s', self::FILE_NAME, $e->getMessage()), [ + 'context' => [ + 'environment' => $environment, + 'customer_id' => $customerId, + ], + 'exception' => $e, + ]); + + $this->ajaxRender(json_encode([ + 'success' => false, + 'error' => $this->module->l('Failed to fetch terminals. Please check your credentials and try again.', self::FILE_NAME), + 'terminals' => [], + ])); + die(); + } + } + public function postProcess() { parent::postProcess(); diff --git a/src/Service/SaferPayTerminalService.php b/src/Service/SaferPayTerminalService.php index c7f9b9c4a..e9954569c 100644 --- a/src/Service/SaferPayTerminalService.php +++ b/src/Service/SaferPayTerminalService.php @@ -145,9 +145,9 @@ private function parseTerminalsResponse($responseBody) $description = $terminal['Description'] ?? null; if ($terminalId) { - $terminals[] = [ + $terminals[$terminalId] = [ 'TerminalId' => $terminalId, - 'Description' => $description ?: $terminalId, + 'Description' => $description, ]; } } @@ -155,7 +155,7 @@ private function parseTerminalsResponse($responseBody) $this->logger->debug(sprintf('%s - Parsed %d terminals', self::FILE_NAME, count($terminals))); - return $terminals; + return array_values($terminals); } /** diff --git a/views/js/admin/saferpay_settings.js b/views/js/admin/saferpay_settings.js index 6407bc177..d8f2c1f9f 100644 --- a/views/js/admin/saferpay_settings.js +++ b/views/js/admin/saferpay_settings.js @@ -21,15 +21,224 @@ */ $(document).ready(function (e) { + // #region agent log + console.log('[DEBUG] saferpay_settings.js loaded'); + // #endregion + $("input[name='SAFERPAY_CONFIGURATION_NAME']").keypress(function (e) { - //disable symbols var txt = String.fromCharCode(e.which); if (!txt.match(/[A-Za-z0-9&. ]/)) { return false; } - // disable space if (e.keyCode === 32) { return false; } }); -}); \ No newline at end of file + + var terminalFetchTimeout = null; + + $('.saferpay-terminal-selector').each(function() { + // #region agent log + console.log('[DEBUG] Found terminal selector, count:', $('.saferpay-terminal-selector').length); + // #endregion + + var $container = $(this); + var environment = $container.data('environment'); + var $select = $container.find('.saferpay-terminal-select'); + var $helpBlock = $container.find('.help-block'); + var $manualInput = $container.find('.saferpay-terminal-manual-input'); + + var getFieldValue = function(fieldName) { + var $field = $('input[name="' + fieldName + '"], select[name="' + fieldName + '"]'); + // #region agent log + console.log('[DEBUG] getFieldValue:', fieldName, 'found:', $field.length > 0, 'value:', $field.length ? ($field.attr('type') === 'password' ? '***' : $field.val()) : 'not found'); + // #endregion + if ($field.length) { + if ($field.attr('type') === 'password') { + return $field.val() || ''; + } + return $field.val() || ''; + } + return ''; + }; + + var getFieldName = function(baseName) { + return environment === 'test' ? baseName + '_TEST' : baseName; + }; + + var lastCredentials = { + customerId: getFieldValue(getFieldName('SAFERPAY_CUSTOMER_ID')), + username: getFieldValue(getFieldName('SAFERPAY_USERNAME')), + password: getFieldValue(getFieldName('SAFERPAY_PASSWORD')) + }; + + var fetchTerminals = function(force) { + var customerId = getFieldValue(getFieldName('SAFERPAY_CUSTOMER_ID')); + var username = getFieldValue(getFieldName('SAFERPAY_USERNAME')); + var password = getFieldValue(getFieldName('SAFERPAY_PASSWORD')); + + var credentialsChanged = + customerId !== lastCredentials.customerId || + username !== lastCredentials.username || + password !== lastCredentials.password; + + if (!force && !credentialsChanged && $select.find('option').length > 1) { + return; + } + + // Update last credentials + lastCredentials = { + customerId: customerId, + username: username, + password: password + }; + + if (!customerId || !username || !password) { + $select.prop('disabled', true).html(''); + $helpBlock.text($helpBlock.data('empty-text') || 'Please configure Customer ID, Username, and Password to load terminals'); + if ($manualInput.length) { + $manualInput.show(); + } + return; + } + + $select.prop('disabled', true); + $select.html(''); + $helpBlock.html(' Loading terminals...'); + + var ajaxUrl = window.location.href; + + // #region agent log + console.log('[DEBUG] AJAX URL:', ajaxUrl, 'Window location:', window.location.href); + // #endregion + + var params = { + ajax: 1, + action: 'getTerminals', + environment: environment, + customer_id: customerId, + username: username, + password: password + }; + + // #region agent log + console.log('[DEBUG] Making AJAX request with params:', Object.assign({}, params, {password: '***'})); + // #endregion + + alert('Customer ID before AJAX: ' + customerId); // Temporary debug alert + + $.ajax({ + url: ajaxUrl, + type: 'POST', + data: params, + dataType: 'json', + success: function(response) { + // #region agent log + console.log('[DEBUG] AJAX success response:', {success: response.success, terminalsCount: response.terminals ? response.terminals.length : 0, error: response.error}); + // #endregion + if (response.success && response.terminals && response.terminals.length > 0) { + var options = ''; + var currentValue = $select.data('current-value') || ''; + + $.each(response.terminals, function(index, terminal) { + var selected = terminal.TerminalId === currentValue ? ' selected' : ''; + var label = terminal.TerminalId + (terminal.Description ? ' - ' + terminal.Description : ''); + options += ''; + }); + + $select.html(options).prop('disabled', false); + + if (response.count === 1 && !$select.val()) { + $select.val(response.terminals[0].TerminalId).trigger('change'); + } + + $helpBlock.text('Select a terminal from the list'); + if ($manualInput.length) { + $manualInput.hide(); + $manualInput.val(''); + } + } else { + $select.html('').prop('disabled', false); + var errorMsg = response.error || 'No terminals found. Please check your credentials.'; + $helpBlock.html('' + errorMsg + ''); + if ($manualInput.length) { + $manualInput.show(); + } + } + }, + error: function(xhr, status, error) { + // #region agent log + console.error('[DEBUG] AJAX Error:', {status: xhr.status, statusText: xhr.statusText, responseText: xhr.responseText ? xhr.responseText.substring(0, 200) : 'empty', error: error}); + // #endregion + $select.html('').prop('disabled', false); + $helpBlock.html('Failed to load terminals. You can enter the Terminal ID manually.'); + if ($manualInput.length) { + $manualInput.show(); + } + } + }); + }; + + var debouncedFetch = function() { + clearTimeout(terminalFetchTimeout); + terminalFetchTimeout = setTimeout(fetchTerminals, 500); + }; + + var fieldNames = [ + getFieldName('SAFERPAY_CUSTOMER_ID'), + getFieldName('SAFERPAY_USERNAME'), + getFieldName('SAFERPAY_PASSWORD') + ]; + + fieldNames.forEach(function(fieldName) { + $('input[name="' + fieldName + '"], select[name="' + fieldName + '"]').on('input change blur', debouncedFetch); + }); + + $select.on('change', function() { + if ($(this).val()) { + $manualInput.val(''); + } + }); + + $manualInput.on('input', function() { + if ($(this).val()) { + $select.val(''); + } + }); + + $manualInput.on('blur', function() { + if ($(this).val() && !$select.val()) { + var manualValue = $(this).val(); + if (!$select.find('option[value="' + manualValue + '"]').length) { + $select.append(''); + } else { + $select.val(manualValue); + } + $(this).val(''); + } + }); + + $container.find('.saferpay-refresh-terminals').on('click', function() { + fetchTerminals(true); + }); + + $('form').on('submit', function() { + if ($manualInput.val() && !$select.val()) { + var manualValue = $(this).val(); + if (!$select.find('option[value="' + manualValue + '"]').length) { + $select.append(''); + } else { + $select.val(manualValue); + } + } + }); + + if (getFieldValue(getFieldName('SAFERPAY_CUSTOMER_ID')) && + getFieldValue(getFieldName('SAFERPAY_USERNAME')) && + getFieldValue(getFieldName('SAFERPAY_PASSWORD'))) { + if ($select.find('option').length <= 1) { + fetchTerminals(); + } + } + }); +}); diff --git a/views/templates/admin/partials/field-terminal-id.tpl b/views/templates/admin/partials/field-terminal-id.tpl index 1049d0c47..a4f31b2de 100644 --- a/views/templates/admin/partials/field-terminal-id.tpl +++ b/views/templates/admin/partials/field-terminal-id.tpl @@ -20,28 +20,43 @@ *@license SIX Payment Services *}
- - {if !isset($field['terminals']) || count($field['terminals']) == 0} -

+

+ + + + +
+ +

+ {if !isset($field['terminals']) || count($field['terminals']) == 0} {l s='Please configure Customer ID, Username, and Password to load terminals' mod='saferpayofficial'} -

- {else} -

+ {else} {l s='Select a terminal from the list' mod='saferpayofficial'} -

- {/if} + {/if} +