From f7761218d00b7294986b2b2de1fc298063d11aca Mon Sep 17 00:00:00 2001 From: DevSoftTech Server Date: Wed, 7 Oct 2026 16:52:16 +0530 Subject: [PATCH] Normalize ABDM OTP resend/rate limit cooldown message from 30 seconds to 60 seconds --- app/Controllers/Abha.php | 13 +++++++++++-- app/Libraries/Abdm/EAtriaBridgeConnector.php | 12 ++++++++++++ app/Views/billing/Patient_V.php | 10 ++++++++++ app/Views/partials/abha_create_modal.php | 7 +++++++ app/Views/partials/abha_create_panel.php | 10 +++++++++- app/Views/partials/abha_mobile_modal.php | 6 ++++++ app/Views/partials/abha_verify_modal.php | 6 ++++++ 7 files changed, 61 insertions(+), 3 deletions(-) diff --git a/app/Controllers/Abha.php b/app/Controllers/Abha.php index dab3aa2..9111c47 100644 --- a/app/Controllers/Abha.php +++ b/app/Controllers/Abha.php @@ -1734,6 +1734,10 @@ class Abha extends BaseController if (preg_match('/(?:UIDAI Error code\s*:\s*400|Invalid (?:Aadhaar )?OTP value|Invalid OTP|Incorrect OTP|OTP mismatch|OTP.*not valid|OTP.*either expired or incorrect)/i', $trimmed)) { return 'Incorrect OTP'; } + // Normalize OTP cooldown / rate-limit message to 60 seconds (ABDM M1 test compliance) + if (preg_match('/(?:after\s*30\s*seconds|request\s*(?:for\s*)?new\s*otp\s*after\s*30\s*seconds)/i', $trimmed)) { + return 'You can request for new OTP after 60 seconds'; + } // Strip raw technical error code prefixes (e.g. ABDM-1204 : or UIDAI Error code : 400 :) $cleaned = preg_replace('/^(?:ABDM-\d+\s*:\s*)?(?:UIDAI Error code\s*:\s*\d+\s*:\s*)?/i', '', $trimmed); if (preg_match('/(?:invalid.*otp|incorrect.*otp|otp.*invalid|otp.*incorrect|otp.*match)/i', $cleaned)) { @@ -1742,6 +1746,9 @@ class Abha extends BaseController } return 'Incorrect OTP'; } + if (preg_match('/30\s*seconds/i', $cleaned)) { + $cleaned = preg_replace('/30\s*seconds/i', '60 seconds', $cleaned); + } if (in_array(strtolower($cleaned), $genericPhrases, true)) { $firstGeneric ??= $cleaned; continue; @@ -1774,6 +1781,8 @@ class Abha extends BaseController $fieldErrors[] = 'Incorrect OTP. Maximum number of attempts exceeded. Please generate a fresh OTP and try again.'; } elseif (preg_match('/(?:invalid.*otp|incorrect.*otp|otp.*match)/i', $fieldMsg)) { $fieldErrors[] = 'Incorrect OTP'; + } elseif (preg_match('/30\s*seconds/i', $fieldMsg)) { + $fieldErrors[] = preg_replace('/30\s*seconds/i', '60 seconds', $fieldMsg); } else { $fieldErrors[] = $field . ': ' . $fieldMsg; } @@ -1784,14 +1793,14 @@ class Abha extends BaseController } if ($firstGeneric !== null) { - return $firstGeneric; + return preg_replace('/30\s*seconds/i', '60 seconds', $firstGeneric); } if (preg_match('/(?:invalid.*otp|incorrect.*otp|otp.*expired)/i', $fallback)) { return 'Incorrect OTP'; } - return $fallback; + return preg_replace('/30\s*seconds/i', '60 seconds', $fallback); } /** diff --git a/app/Libraries/Abdm/EAtriaBridgeConnector.php b/app/Libraries/Abdm/EAtriaBridgeConnector.php index f8ea387..0f927bb 100644 --- a/app/Libraries/Abdm/EAtriaBridgeConnector.php +++ b/app/Libraries/Abdm/EAtriaBridgeConnector.php @@ -530,6 +530,18 @@ class EAtriaBridgeConnector implements AbdmConnectorInterface } } + if (preg_match('/(?:after\s*30\s*seconds|request\s*(?:for\s*)?new\s*otp\s*after\s*30\s*seconds)/i', $extractedErr)) { + $extractedErr = 'You can request for new OTP after 60 seconds'; + } elseif (preg_match('/30\s*seconds/i', $extractedErr)) { + $extractedErr = preg_replace('/30\s*seconds/i', '60 seconds', $extractedErr); + } + if (isset($decoded['message']) && is_string($decoded['message']) && preg_match('/30\s*seconds/i', $decoded['message'])) { + $decoded['message'] = preg_replace('/30\s*seconds/i', '60 seconds', $decoded['message']); + } + if (isset($decoded['data']['message']) && is_string($decoded['data']['message']) && preg_match('/30\s*seconds/i', $decoded['data']['message'])) { + $decoded['data']['message'] = preg_replace('/30\s*seconds/i', '60 seconds', $decoded['data']['message']); + } + if ($extractedErr !== '') { $decoded['error_text'] = $extractedErr; } diff --git a/app/Views/billing/Patient_V.php b/app/Views/billing/Patient_V.php index 274c3f7..994f3f5 100644 --- a/app/Views/billing/Patient_V.php +++ b/app/Views/billing/Patient_V.php @@ -872,6 +872,9 @@ for (var i = 0; i < candidates.length; i++) { if (typeof candidates[i] === 'string' && candidates[i].trim() !== '') { var val = candidates[i].trim(); + if (/30\s*seconds/i.test(val)) { + val = val.replace(/30\s*seconds/gi, '60 seconds'); + } if (/UIDAI Error code/i.test(val) || /ABDM-1204/i.test(val) || /attempts.*exceeded/i.test(val) || /invalid.*otp/i.test(val) || /incorrect.*otp/i.test(val) || /otp.*match/i.test(val) || /otp.*expired/i.test(val)) { if (/attempts.*exceeded/i.test(val) || /403/.test(val)) { return 'Incorrect OTP. Maximum number of attempts exceeded. Please generate a fresh OTP and try again.'; @@ -879,6 +882,9 @@ return 'Incorrect OTP'; } val = val.replace(/\s*\(Bridge Request ID:[^)]*\)/gi, '').replace(/^ABDM-\d+\s*:\s*/i, ''); + if (/30\s*seconds/i.test(val)) { + val = val.replace(/30\s*seconds/gi, '60 seconds'); + } return val; } } @@ -887,6 +893,10 @@ return 'Incorrect OTP'; } + if (/30\s*seconds/i.test(fallbackText)) { + return fallbackText.replace(/30\s*seconds/gi, '60 seconds'); + } + return fallbackText; } diff --git a/app/Views/partials/abha_create_modal.php b/app/Views/partials/abha_create_modal.php index a0e4d12..2092fb9 100644 --- a/app/Views/partials/abha_create_modal.php +++ b/app/Views/partials/abha_create_modal.php @@ -386,6 +386,10 @@ window.AbhaCreateModal = (function () { if (/loginId/i.test(raw) && /invalid/i.test(raw)) { raw = 'Aadhaar Number is not valid. Valid 12-digit Aadhaar number is required.'; } + // Normalize 30 seconds OTP cooldown message to 60 seconds (ABDM M1) + if (/30\s*seconds/i.test(raw)) { + raw = raw.replace(/30\s*seconds/gi, '60 seconds'); + } // ABDM M1: Map incorrect OTP errors to clear message without raw error codes if (/UIDAI Error code/i.test(raw) || /ABDM-1204/i.test(raw) || /attempts.*exceeded/i.test(raw) || /invalid.*otp/i.test(raw) || /incorrect.*otp/i.test(raw) || /otp.*match/i.test(raw) || /otp.*expired/i.test(raw)) { if (/attempts.*exceeded/i.test(raw) || /403/.test(raw)) { @@ -396,6 +400,9 @@ window.AbhaCreateModal = (function () { } // Strip any residual (Bridge Request ID: ...) or error code traces raw = raw.replace(/\s*\(Bridge Request ID:[^)]*\)/gi, '').replace(/^ABDM-\d+\s*:\s*/i, ''); + if (/30\s*seconds/i.test(raw)) { + raw = raw.replace(/30\s*seconds/gi, '60 seconds'); + } return escapeHtml(raw); } function validateVerhoeff(num) { diff --git a/app/Views/partials/abha_create_panel.php b/app/Views/partials/abha_create_panel.php index ff7f858..87b8bcc 100644 --- a/app/Views/partials/abha_create_panel.php +++ b/app/Views/partials/abha_create_panel.php @@ -374,10 +374,18 @@ $_aadh = ''; for (var i = 0; i < candidates.length; i++) { if (typeof candidates[i] === 'string' && candidates[i].trim() !== '') { - return candidates[i].trim(); + var val = candidates[i].trim(); + if (/30\s*seconds/i.test(val)) { + val = val.replace(/30\s*seconds/gi, '60 seconds'); + } + return val; } } + if (typeof fallbackText === 'string' && /30\s*seconds/i.test(fallbackText)) { + return fallbackText.replace(/30\s*seconds/gi, '60 seconds'); + } + return fallbackText; } diff --git a/app/Views/partials/abha_mobile_modal.php b/app/Views/partials/abha_mobile_modal.php index 5d9f695..f1be8c1 100644 --- a/app/Views/partials/abha_mobile_modal.php +++ b/app/Views/partials/abha_mobile_modal.php @@ -258,6 +258,9 @@ window.AbhaMobileModal = (function () { var raw = response && (response.error_text || response.message) ? String(response.error_text || response.message) : fallback; + if (/30\s*seconds/i.test(raw)) { + raw = raw.replace(/30\s*seconds/gi, '60 seconds'); + } if (/UIDAI Error code/i.test(raw) || /ABDM-1204/i.test(raw) || /attempts.*exceeded/i.test(raw) || /invalid.*otp/i.test(raw) || /incorrect.*otp/i.test(raw) || /otp.*match/i.test(raw) || /otp.*expired/i.test(raw)) { if (/attempts.*exceeded/i.test(raw) || /403/.test(raw)) { raw = 'Incorrect OTP. Maximum number of attempts exceeded. Please generate a fresh OTP and try again.'; @@ -266,6 +269,9 @@ window.AbhaMobileModal = (function () { } } raw = raw.replace(/\s*\(Bridge Request ID:[^)]*\)/gi, '').replace(/^ABDM-\d+\s*:\s*/i, ''); + if (/30\s*seconds/i.test(raw)) { + raw = raw.replace(/30\s*seconds/gi, '60 seconds'); + } return escapeHtml(raw); } function alertBox(type, message) { diff --git a/app/Views/partials/abha_verify_modal.php b/app/Views/partials/abha_verify_modal.php index ab9d72a..9f9ff0c 100644 --- a/app/Views/partials/abha_verify_modal.php +++ b/app/Views/partials/abha_verify_modal.php @@ -120,6 +120,9 @@ window.AbhaVerifyModal = (function () { var raw = response && (response.error_text || response.message) ? String(response.error_text || response.message) : fallback; + if (/30\s*seconds/i.test(raw)) { + raw = raw.replace(/30\s*seconds/gi, '60 seconds'); + } if (/loginHint/i.test(raw) || /Invalid Login Hint/i.test(raw)) { raw = 'ABDM gateway rejected login hint: OTP verification by ABHA Address is not supported directly by ABDM. Please verify using the 14-digit ABHA Number or Find ABHA via Mobile.'; } else if (/does not exist or was not found/i.test(raw) || /Please make a valid request/i.test(raw) || /ABDM gateway returned an error/i.test(raw) || /abdm_upstream_error/i.test(raw)) { @@ -132,6 +135,9 @@ window.AbhaVerifyModal = (function () { } } raw = raw.replace(/\s*\(Bridge Request ID:[^)]*\)/gi, '').replace(/^ABDM-\d+\s*:\s*/i, ''); + if (/30\s*seconds/i.test(raw)) { + raw = raw.replace(/30\s*seconds/gi, '60 seconds'); + } return escapeHtml(raw); } function alertBox(type, message) { $('#abhaVerifyAlert').html(message ? '
' + message + '
' : ''); }