diff --git a/controllers/admin/AdminSaferPayOfficialSettingsController.php b/controllers/admin/AdminSaferPayOfficialSettingsController.php index 71ffd95e..0e5883c4 100755 --- a/controllers/admin/AdminSaferPayOfficialSettingsController.php +++ b/controllers/admin/AdminSaferPayOfficialSettingsController.php @@ -40,6 +40,7 @@ use Invertus\SaferPay\Service\SaferPayRestrictionCreator; use Invertus\SaferPay\Exception\Api\SaferPayApiException; use Invertus\SaferPay\Exception\Restriction\RestrictionException; +use Invertus\SaferPay\Logger\LoggerInterface; require_once dirname(__FILE__) . '/../../vendor/autoload.php'; @@ -209,8 +210,8 @@ public function ajaxProcessSaveCredentials() // Auto-detect license features from Saferpay Management API $suffix = $isTestMode ? SaferPayConfig::TEST_SUFFIX : ''; - $licenseMessage = ''; $hasBusinessLicense = false; + $licenseFetchFailed = false; if (!empty($activeUsername) && !empty($activePassword) && !empty($activeCustomerId)) { try { @@ -227,18 +228,28 @@ public function ajaxProcessSaveCredentials() $configuration->set(SaferPayConfig::BUSINESS_LICENSE . $suffix, $hasBusinessLicense ? 1 : 0); } catch (\Exception $e) { $configuration->set(SaferPayConfig::BUSINESS_LICENSE . $suffix, 0); + $licenseFetchFailed = true; - $licenseMessage = ' ' . $this->module->l('Could not retrieve license information. Please verify your credentials.', self::FILE_NAME); + /** @var LoggerInterface $logger */ + $logger = $this->module->getService(LoggerInterface::class); + $logger->error('License fetch failed on credentials save: ' . $e->getMessage(), [ + 'context' => ['exception_class' => get_class($e)], + ]); } } else { $configuration->set(SaferPayConfig::BUSINESS_LICENSE . $suffix, 0); } + $message = $licenseFetchFailed + ? $this->module->l('Settings saved, but Saferpay Fields availability could not be confirmed. Please try again later or check the module Logs for details.', self::FILE_NAME) + : $this->module->l('Settings saved successfully.', self::FILE_NAME); + $this->ajaxResponse( true, - $this->module->l('Settings saved successfully.', self::FILE_NAME) . $licenseMessage, + $message, [ 'hasBusinessLicense' => $hasBusinessLicense, + 'warning' => $licenseFetchFailed, ] ); } diff --git a/views/js/admin/settings-app/src/components/settings/toast-container.tsx b/views/js/admin/settings-app/src/components/settings/toast-container.tsx index 39d96074..0b5f905d 100644 --- a/views/js/admin/settings-app/src/components/settings/toast-container.tsx +++ b/views/js/admin/settings-app/src/components/settings/toast-container.tsx @@ -15,7 +15,9 @@ export function ToastContainer() { className={`sp-rounded-lg sp-border sp-px-4 sp-py-3 sp-shadow-lg sp-text-sm sp-animate-in sp-slide-in-from-bottom-2 ${ t.variant === 'destructive' ? 'sp-bg-destructive sp-text-destructive-foreground sp-border-destructive' - : 'sp-bg-emerald-600 sp-text-white sp-border-emerald-700' + : t.variant === 'warning' + ? 'sp-bg-amber-500 sp-text-white sp-border-amber-600' + : 'sp-bg-emerald-600 sp-text-white sp-border-emerald-700' }`} > {t.title &&
{t.title}
} diff --git a/views/js/admin/settings-app/src/context/settings-context.tsx b/views/js/admin/settings-app/src/context/settings-context.tsx index c4ce8f6c..aa54b787 100644 --- a/views/js/admin/settings-app/src/context/settings-context.tsx +++ b/views/js/admin/settings-app/src/context/settings-context.tsx @@ -48,7 +48,7 @@ export function SettingsProvider({ children }: { children: React.ReactNode }) { }, []) const handleSave = useCallback(async ( - saveFn: () => Promise<{ success: boolean; message?: string }>, + saveFn: () => Promise<{ success: boolean; message?: string; warning?: boolean }>, label: string, section: SavingSection, ) => { @@ -56,7 +56,8 @@ export function SettingsProvider({ children }: { children: React.ReactNode }) { try { const result = await saveFn() if (result.success) { - toast({ title: result.message || t('savedSuccessfully', label), variant: 'default' }) + const variant = result.warning ? 'warning' : 'default' + toast({ title: result.message || t('savedSuccessfully', label), variant }) } else { toast({ title: result.message || t('failedToSave', label), variant: 'destructive' }) } @@ -94,7 +95,7 @@ export function SettingsProvider({ children }: { children: React.ReactNode }) { if (result.success && typeof data.hasBusinessLicense === 'boolean') { setSettings((prev) => ({ ...prev, hasBusinessLicense: data.hasBusinessLicense as boolean })) } - return result + return { ...result, warning: data.warning === true } }, 'API Credentials', 'credentials') }, [handleSave]) diff --git a/views/js/admin/settings-app/src/hooks/use-toast.ts b/views/js/admin/settings-app/src/hooks/use-toast.ts index ec210341..f0af5fe0 100644 --- a/views/js/admin/settings-app/src/hooks/use-toast.ts +++ b/views/js/admin/settings-app/src/hooks/use-toast.ts @@ -7,7 +7,7 @@ export interface ToasterToast { id: string title?: string description?: string - variant?: 'default' | 'destructive' + variant?: 'default' | 'destructive' | 'warning' } type Action =