fix(abha): persist OTP-verified mobile number when bridge response omits it

Abha::verifyOtp() and Abha::verifyCommOtp() were overwriting the
user-typed, OTP-verified mobile number with whatever the ABDM bridge's
verify-otp response echoed back for 'mobile'. Many bridge responses
(especially plain mobile-OTP verification, as opposed to Aadhaar eKYC)
do not echo the mobile at all, so it silently became empty and was
never saved to patient_master.mphone1 during ABHA Register (By ABHA
Number / QR / Facility QR / Mobile OTP) or ABHA Create/Verify.

Fix: fall back to the originally submitted/verified mobile when the
gateway response omits it. Also updated Patient_V.php JS (Verify ABHA
tab, ABHA Register Method 1 and Method 4) to resend the mobile number
along with the verify_comm_otp call so the server has it available.

Address/email are unaffected by this bug: those fields are already
mapped via applyAbhaMetaColumns() when present, but the ABDM mobile-OTP
verification API generally doesn't return KYC demographic data (that
only comes from the Aadhaar-eKYC flow) - so they may legitimately
stay blank for phone-based registration methods.
This commit is contained in:
DevSoftTech Server 2026-07-29 13:52:07 +05:30
parent a5bbe3cc20
commit 82b7b27273
2 changed files with 17 additions and 8 deletions

View File

@ -61,14 +61,14 @@ class Abha extends BaseController
$txnId = trim((string) ($this->request->getPost('txn_id') ?? $this->request->getPost('txnId') ?? ''));
$otp = trim((string) ($this->request->getPost('otp') ?? ''));
$mobile = trim((string) ($this->request->getPost('mobile') ?? ''));
$requestMobile = trim((string) ($this->request->getPost('mobile') ?? ''));
if ($txnId === '' || $otp === '') {
return $this->response->setJSON(['ok' => 0, 'error_text' => 'txn_id and otp are required']);
}
try {
$result = AbdmConnectorFactory::make()->abhaAadhaarVerifyOtp(['txnId' => $txnId, 'otp' => $otp, 'mobile' => $mobile]);
$result = AbdmConnectorFactory::make()->abhaAadhaarVerifyOtp(['txnId' => $txnId, 'otp' => $otp, 'mobile' => $requestMobile]);
} catch (\Throwable $e) {
return $this->response->setStatusCode(500)->setJSON(['ok' => 0, 'error_text' => $e->getMessage()]);
}
@ -97,7 +97,9 @@ class Abha extends BaseController
);
$name = $this->extractAbhaProfileName($profile, $payload);
$photo = (string) ($profile['profilePhoto'] ?? $profile['profile_photo'] ?? $payload['profilePhoto'] ?? $payload['profile_photo'] ?? '');
$mobile = (string) ($profile['mobile'] ?? $payload['mobile'] ?? $payload['mobileNumber'] ?? '');
// Bridge/gateway verify-otp responses don't always echo the mobile back;
// fall back to the mobile the user actually typed and OTP-verified.
$mobile = (string) ($profile['mobile'] ?? $payload['mobile'] ?? $payload['mobileNumber'] ?? $requestMobile ?? '');
$profileGender = (string) ($profile['gender'] ?? $payload['gender'] ?? '');
$profileDob = (string) ($profile['dob'] ?? $profile['date_of_birth'] ?? $payload['dob'] ?? $payload['date_of_birth'] ?? '');
$verifiedStatus = (string) (($payload['gateway_abha_profile']['status'] ?? '') ?: ($profile['verifiedStatus'] ?? '') ?: ($profile['status'] ?? '') ?: ($payload['verifiedStatus'] ?? '') ?: ($payload['status'] ?? ''));
@ -192,6 +194,10 @@ class Abha extends BaseController
$txnId = trim((string) ($this->request->getPost('txn_id') ?? $this->request->getPost('txnId') ?? ''));
$otp = trim((string) ($this->request->getPost('otp') ?? ''));
// The mobile itself isn't part of the OTP-verify payload (it's tied to txn_id
// on the bridge side), but the caller may resend it so we can persist it even
// if the gateway response doesn't echo it back.
$requestMobile = trim((string) ($this->request->getPost('mobile') ?? ''));
if ($txnId === '' || $otp === '') {
return $this->response->setJSON(['ok' => 0, 'error_text' => 'txn_id and otp are required']);
@ -229,7 +235,9 @@ class Abha extends BaseController
$photo = (string) ($profile['profilePhoto'] ?? $profile['profile_photo'] ?? $payload['profilePhoto'] ?? $payload['profile_photo'] ?? '');
$gender = (string) ($profile['gender'] ?? $payload['gender'] ?? '');
$dob = (string) ($profile['dob'] ?? $profile['date_of_birth'] ?? $payload['dob'] ?? $payload['date_of_birth'] ?? '');
$mobile = (string) ($profile['mobile'] ?? $payload['mobile'] ?? $payload['mobileNumber'] ?? '');
// Bridge/gateway verify-otp responses don't always echo the mobile back;
// fall back to the mobile the user actually typed and OTP-verified.
$mobile = (string) ($profile['mobile'] ?? $payload['mobile'] ?? $payload['mobileNumber'] ?? $requestMobile ?? '');
$verifiedStatus = (string) (($payload['gateway_abha_profile']['status'] ?? '') ?: ($profile['verifiedStatus'] ?? '') ?: ($profile['status'] ?? '') ?: ($payload['verifiedStatus'] ?? '') ?: ($payload['status'] ?? ''));
$verificationType = (string) (($payload['gateway_abha_profile']['abha_type'] ?? '') ?: ($profile['verificationType'] ?? '') ?: ($profile['abhaType'] ?? '') ?: ($payload['verificationType'] ?? '') ?: ($payload['abhaType'] ?? ''));
$kycVerified = $profile['kycVerified'] ?? $payload['kycVerified'] ?? null;

View File

@ -1007,6 +1007,7 @@
$.post('<?= base_url('abha/create/verify_comm_otp') ?>', {
otp: otp,
txn_id: linkTxnId,
mobile: $('#abha_link_mobile').val().trim(),
'<?= csrf_token() ?>': csrfToken()
}, function(resp) {
$('#abha_link_verify_spinner').addClass('d-none');
@ -1450,13 +1451,13 @@
});
}
function verifyOtpFromMobile(otp, alertId, spinId, btnId) {
function verifyOtpFromMobile(otp, alertId, spinId, btnId, mobile) {
if (!/^\d{6}$/.test(otp)) { regAlert(alertId, 'warning', 'Please enter the 6-digit OTP.'); return; }
regAlert(alertId, '', '');
$('#' + spinId).removeClass('d-none');
$('#' + btnId).prop('disabled', true);
$.post('<?= base_url('abha/create/verify_comm_otp') ?>', {
otp: otp, txn_id: regTxnId, '<?= csrf_token() ?>': csrf()
otp: otp, txn_id: regTxnId, mobile: mobile || '', '<?= csrf_token() ?>': csrf()
}, function(resp) {
$('#' + spinId).addClass('d-none');
$('#' + btnId).prop('disabled', false);
@ -1481,7 +1482,7 @@
});
});
$('#abhareg_num_verify_otp_btn').on('click', function() {
verifyOtpFromMobile($('#abhareg_num_otp_input').val().trim(), 'abhareg_num_stepC_alert', 'abhareg_num_verify_spinner', 'abhareg_num_verify_otp_btn');
verifyOtpFromMobile($('#abhareg_num_otp_input').val().trim(), 'abhareg_num_stepC_alert', 'abhareg_num_verify_spinner', 'abhareg_num_verify_otp_btn', $('#abhareg_num_mobile').val().trim());
});
$('#abhareg_num_resend_btn').on('click', function() {
$('#abhareg_num_stepC').addClass('d-none');
@ -1498,7 +1499,7 @@
});
});
$('#abhareg_mob_verify_btn').on('click', function() {
verifyOtpFromMobile($('#abhareg_mob_otp_input').val().trim(), 'abhareg_mob_step2_alert', 'abhareg_mob_verify_spinner', 'abhareg_mob_verify_btn');
verifyOtpFromMobile($('#abhareg_mob_otp_input').val().trim(), 'abhareg_mob_step2_alert', 'abhareg_mob_verify_spinner', 'abhareg_mob_verify_btn', $('#abhareg_mob_mobile').val().trim());
});
$('#abhareg_mob_resend_btn').on('click', function() {
$('#abhareg_mob_step2').addClass('d-none');