From 35e1018c6ba312dfd5b09923bb88b5d46b8e4bc5 Mon Sep 17 00:00:00 2001 From: DevSoftTech Server Date: Sat, 12 Sep 2026 01:48:33 +0530 Subject: [PATCH] fix(abdm): prevent modal redirect to profile step on wrong OTP verification --- app/Controllers/Abha.php | 72 ++++++++++++++------ app/Libraries/Abdm/EAtriaBridgeConnector.php | 67 +++++++++++++++++- app/Views/partials/abha_verify_modal.php | 9 ++- 3 files changed, 123 insertions(+), 25 deletions(-) diff --git a/app/Controllers/Abha.php b/app/Controllers/Abha.php index 42d2498..24a80ef 100644 --- a/app/Controllers/Abha.php +++ b/app/Controllers/Abha.php @@ -94,9 +94,15 @@ class Abha extends BaseController return $this->response->setStatusCode(500)->setJSON(['ok' => 0, 'error_text' => $e->getMessage()]); } + $authResult = strtolower(trim((string) ($result['authResult'] ?? $result['data']['authResult'] ?? $result['auth_result'] ?? $result['data']['auth_result'] ?? ''))); + $status = strtolower(trim((string) ($result['status'] ?? $result['data']['status'] ?? ''))); + if ($authResult === 'failed' || in_array($status, ['failed', 'failure', 'error'], true)) { + $result['ok'] = 0; + } + if (empty($result['ok']) || $result['ok'] != 1) { $requestId = trim((string) ($result['request_id'] ?? '')); - $errorText = $this->extractBridgeErrorText($result, 'OTP verification failed'); + $errorText = $this->extractBridgeErrorText($result, 'Please enter a valid OTP. Entered OTP is either expired or incorrect.'); if ($requestId !== '') { $errorText .= ' (Bridge Request ID: ' . $requestId . ')'; } @@ -1637,24 +1643,6 @@ class Abha extends BaseController */ private function extractBridgeErrorText(array $result, string $fallback): string { - $fieldErrors = []; - if (is_array($result['data'] ?? null)) { - foreach ($result['data'] as $field => $message) { - if ($field === 'timestamp' || ! is_string($message) || trim($message) === '') { - continue; - } - $fieldMsg = trim($message); - if (strcasecmp($field, 'loginId') === 0 && stripos($fieldMsg, 'invalid') !== false) { - $fieldErrors[] = 'Aadhaar Number is not valid. Valid 12-digit Aadhaar number is required.'; - } else { - $fieldErrors[] = $field . ': ' . $fieldMsg; - } - } - } - if ($fieldErrors !== []) { - return implode('; ', $fieldErrors); - } - $candidates = [ $result['error_text'] ?? null, $result['message'] ?? null, @@ -1685,6 +1673,33 @@ class Abha extends BaseController } } + $ignoreFields = [ + 'timestamp', 'txnid', 'txn_id', 'authresult', 'auth_result', + 'authmethod', 'auth_method', 'status', 'token', 'tokens', + 'refreshtoken', 'refresh_token', 'expiresin', 'expires_in', + 'refreshexpiresin', 'refresh_expires_in', 'request_id', 'requestid', + 'scope', 'accounts', 'message', 'error', 'error_text', 'code', + ]; + + $fieldErrors = []; + if (is_array($result['data'] ?? null)) { + foreach ($result['data'] as $field => $message) { + $lowerField = strtolower(trim((string) $field)); + if (in_array($lowerField, $ignoreFields, true) || ! is_string($message) || trim($message) === '') { + continue; + } + $fieldMsg = trim($message); + if (strcasecmp($field, 'loginId') === 0 && stripos($fieldMsg, 'invalid') !== false) { + $fieldErrors[] = 'Aadhaar Number is not valid. Valid 12-digit Aadhaar number is required.'; + } else { + $fieldErrors[] = $field . ': ' . $fieldMsg; + } + } + } + if ($fieldErrors !== []) { + return implode('; ', $fieldErrors); + } + return $fallback; } @@ -2897,14 +2912,20 @@ class Abha extends BaseController return $this->response->setStatusCode(502)->setJSON(['ok' => 0, 'error_text' => $e->getMessage()]); } + $authResult = strtolower(trim((string) ($result['authResult'] ?? $result['data']['authResult'] ?? $result['auth_result'] ?? $result['data']['auth_result'] ?? ''))); + $status = strtolower(trim((string) ($result['status'] ?? $result['data']['status'] ?? ''))); + if ($authResult === 'failed' || in_array($status, ['failed', 'failure', 'error'], true)) { + $result['ok'] = 0; + } + if (empty($result['ok']) || (int) $result['ok'] !== 1) { $httpCode = (int) ($result['http_code'] ?? 0); if ($httpCode < 400 || $httpCode > 599) { - $httpCode = 502; + $httpCode = 422; } return $this->response->setStatusCode($httpCode)->setJSON([ 'ok' => 0, - 'error_text' => $this->extractBridgeErrorText($result, 'OTP verification failed.'), + 'error_text' => $this->extractBridgeErrorText($result, 'Please enter a valid OTP. Entered OTP is either expired or incorrect.'), 'request_id' => (string) ($result['request_id'] ?? ''), ]); } @@ -2928,6 +2949,15 @@ class Abha extends BaseController }; $abhaNumber = preg_replace('/\D/', '', $firstNonEmpty([$profile['ABHANumber'] ?? null, $profile['abhaNumber'] ?? null, $profile['abha_number'] ?? null, $profile['abha_id'] ?? null, $payload['ABHANumber'] ?? null, $payload['abhaNumber'] ?? null, $payload['abha_id'] ?? null])); $abhaAddress = $firstNonEmpty([$profile['preferredAddress'] ?? null, $profile['preferredAbhaAddress'] ?? null, $profile['abhaAddress'] ?? null, $profile['abha_address'] ?? null, $payload['preferredAddress'] ?? null, $payload['abhaAddress'] ?? null, $payload['abha_address'] ?? null]); + $userToken = trim((string) ($payload['token'] ?? $payload['tokens']['token'] ?? $payload['auth_token'] ?? $payload['user_token'] ?? '')); + + if ($abhaNumber === '' && $abhaAddress === '' && $userToken === '') { + return $this->response->setStatusCode(422)->setJSON([ + 'ok' => 0, + 'error_text' => $this->extractBridgeErrorText($result, 'Please enter a valid OTP. Entered OTP is either expired or incorrect.'), + 'request_id' => (string) ($result['request_id'] ?? ''), + ]); + } $name = $this->extractAbhaProfileName($profile, $payload); $mobile = $firstNonEmpty([$profile['mobile'] ?? null, $profile['mobileNumber'] ?? null, $profile['mobile_number'] ?? null, $payload['mobile'] ?? null, $payload['mobileNumber'] ?? null, $payload['mobile_number'] ?? null]); $gender = $firstNonEmpty([$profile['gender'] ?? null, $payload['gender'] ?? null]); diff --git a/app/Libraries/Abdm/EAtriaBridgeConnector.php b/app/Libraries/Abdm/EAtriaBridgeConnector.php index f1664e6..64a8778 100644 --- a/app/Libraries/Abdm/EAtriaBridgeConnector.php +++ b/app/Libraries/Abdm/EAtriaBridgeConnector.php @@ -449,8 +449,31 @@ class EAtriaBridgeConnector implements AbdmConnectorInterface return ['ok' => 0, 'error_text' => 'Non-JSON response', 'http_code' => $httpCode, 'raw' => (string) $raw, 'auth_debug' => $authDebug]; } - $ok = ($httpCode >= 200 && $httpCode < 300) ? (int) ($decoded['ok'] ?? 1) : 0; - $logErr = $ok === 0 ? (string) ($decoded['message'] ?? $decoded['error_text'] ?? '') : ''; + $authResult = strtolower(trim((string) ($decoded['authResult'] ?? $decoded['auth_result'] ?? $decoded['data']['authResult'] ?? $decoded['data']['auth_result'] ?? ''))); + $statusVal = strtolower(trim((string) ($decoded['status'] ?? $decoded['data']['status'] ?? ''))); + $hasFailedAuth = ($authResult === 'failed' || in_array($statusVal, ['failed', 'failure', 'error', 'rejected'], true)); + if (isset($decoded['success']) && ($decoded['success'] === false || $decoded['success'] === 0 || $decoded['success'] === 'false')) { + $hasFailedAuth = true; + } + if (isset($decoded['data']['success']) && ($decoded['data']['success'] === false || $decoded['data']['success'] === 0 || $decoded['data']['success'] === 'false')) { + $hasFailedAuth = true; + } + + if ($hasFailedAuth) { + $ok = 0; + } elseif ($httpCode >= 200 && $httpCode < 300) { + $ok = (int) ($decoded['ok'] ?? 1); + } else { + $ok = 0; + } + + if ($ok === 0 && empty($decoded['error_text'])) { + $errMsg = trim((string) ($decoded['message'] ?? $decoded['data']['message'] ?? $decoded['error']['message'] ?? (is_string($decoded['error'] ?? null) ? $decoded['error'] : ''))); + if ($errMsg !== '') { + $decoded['error_text'] = $errMsg; + } + } + $logErr = $ok === 0 ? (string) ($decoded['error_text'] ?? $decoded['message'] ?? '') : ''; if ($ok === 0) { $logErr .= ($logErr !== '' ? ' | ' : '') . 'auth=' . json_encode($authDebug); } @@ -712,6 +735,16 @@ class EAtriaBridgeConnector implements AbdmConnectorInterface } $result = $this->post('/v3/abha/login/verify-otp', $body); + $authResult = strtolower(trim((string) ($result['authResult'] ?? $result['data']['authResult'] ?? $result['auth_result'] ?? $result['data']['auth_result'] ?? ''))); + $status = strtolower(trim((string) ($result['status'] ?? $result['data']['status'] ?? ''))); + if ($authResult === 'failed' || in_array($status, ['failed', 'failure', 'error'], true)) { + $err = trim((string) ($result['message'] ?? $result['data']['message'] ?? $result['error_text'] ?? 'Please enter a valid OTP. Entered OTP is either expired or incorrect.')); + return array_merge($result, [ + 'ok' => 0, + 'error_text' => $err !== '' ? $err : 'Please enter a valid OTP. Entered OTP is either expired or incorrect.', + 'message' => $err !== '' ? $err : 'Please enter a valid OTP. Entered OTP is either expired or incorrect.', + ]); + } if (empty($result['ok']) || (int) $result['ok'] !== 1) { return $result; } @@ -941,6 +974,16 @@ class EAtriaBridgeConnector implements AbdmConnectorInterface } $result = $this->post('/v3/abha/aadhaar/verify-otp', $body); + $authResult = strtolower(trim((string) ($result['authResult'] ?? $result['data']['authResult'] ?? $result['auth_result'] ?? $result['data']['auth_result'] ?? ''))); + $status = strtolower(trim((string) ($result['status'] ?? $result['data']['status'] ?? ''))); + if ($authResult === 'failed' || in_array($status, ['failed', 'failure', 'error'], true)) { + $err = trim((string) ($result['message'] ?? $result['data']['message'] ?? $result['error_text'] ?? 'Please enter a valid OTP. Entered OTP is either expired or incorrect.')); + return array_merge($result, [ + 'ok' => 0, + 'error_text' => $err !== '' ? $err : 'Please enter a valid OTP. Entered OTP is either expired or incorrect.', + 'message' => $err !== '' ? $err : 'Please enter a valid OTP. Entered OTP is either expired or incorrect.', + ]); + } if (empty($result['ok']) || (int) $result['ok'] !== 1) { return $result; } @@ -978,6 +1021,16 @@ class EAtriaBridgeConnector implements AbdmConnectorInterface } $result = $this->post('/v3/abha/mobile/verify-otp', $body); + $authResult = strtolower(trim((string) ($result['authResult'] ?? $result['data']['authResult'] ?? $result['auth_result'] ?? $result['data']['auth_result'] ?? ''))); + $status = strtolower(trim((string) ($result['status'] ?? $result['data']['status'] ?? ''))); + if ($authResult === 'failed' || in_array($status, ['failed', 'failure', 'error'], true)) { + $err = trim((string) ($result['message'] ?? $result['data']['message'] ?? $result['error_text'] ?? 'Please enter a valid OTP. Entered OTP is either expired or incorrect.')); + return array_merge($result, [ + 'ok' => 0, + 'error_text' => $err !== '' ? $err : 'Please enter a valid OTP. Entered OTP is either expired or incorrect.', + 'message' => $err !== '' ? $err : 'Please enter a valid OTP. Entered OTP is either expired or incorrect.', + ]); + } if (empty($result['ok']) || (int) $result['ok'] !== 1) { return $result; } @@ -1009,6 +1062,16 @@ class EAtriaBridgeConnector implements AbdmConnectorInterface } $result = $this->post('/v3/abha/enrol/mobile/verify-otp', $body); + $authResult = strtolower(trim((string) ($result['authResult'] ?? $result['data']['authResult'] ?? $result['auth_result'] ?? $result['data']['auth_result'] ?? ''))); + $status = strtolower(trim((string) ($result['status'] ?? $result['data']['status'] ?? ''))); + if ($authResult === 'failed' || in_array($status, ['failed', 'failure', 'error'], true)) { + $err = trim((string) ($result['message'] ?? $result['data']['message'] ?? $result['error_text'] ?? 'Please enter a valid OTP. Entered OTP is either expired or incorrect.')); + return array_merge($result, [ + 'ok' => 0, + 'error_text' => $err !== '' ? $err : 'Please enter a valid OTP. Entered OTP is either expired or incorrect.', + 'message' => $err !== '' ? $err : 'Please enter a valid OTP. Entered OTP is either expired or incorrect.', + ]); + } if (empty($result['ok']) || (int) $result['ok'] !== 1) { return $result; } diff --git a/app/Views/partials/abha_verify_modal.php b/app/Views/partials/abha_verify_modal.php index bed3cee..ec6a1b5 100644 --- a/app/Views/partials/abha_verify_modal.php +++ b/app/Views/partials/abha_verify_modal.php @@ -262,12 +262,17 @@ window.AbhaVerifyModal = (function () { var button = $('#abhaVerifyOtpBtn').prop('disabled', true).html('Verifying'); $.post('', { txn_id:lookupResponse.txn_id, auth_method:lookupResponse.auth_method, otp:otp, '':csrf() }, function (response) { button.prop('disabled', false).html('Verify OTP'); - if (!response || response.ok != 1) { alertBox('danger', apiMessage(response, 'OTP verification failed.')); return; } + if (!response || response.ok != 1) { + alertBox('danger', apiMessage(response, 'Please enter a valid OTP. Entered OTP is either expired or incorrect.')); + $('#abhaVerifyOtp').val('').trigger('focus'); + return; + } stopTimer(); renderProfile(response); }, 'json').fail(function (xhr) { button.prop('disabled', false).html('Verify OTP'); - alertBox('danger', apiMessage(xhr.responseJSON, 'OTP verification failed.')); + alertBox('danger', apiMessage(xhr.responseJSON, 'Please enter a valid OTP. Entered OTP is either expired or incorrect.')); + $('#abhaVerifyOtp').val('').trigger('focus'); }); } $(function () {