redirectToLogin('Session expired. Please log in again.');
}
// Initialize database
try {
$db = new Database();
$pdo = $db->getConnection();
} catch (Exception $e) {
logError('Database connection failed in mobile-verification.php: ' . $e->getMessage());
die('System error. Please try again later.');
}
$errors = [];
$success_message = '';
$step = 'enter_mobile'; // enter_mobile, verify_otp, completed
// Allow user to go back to enter_mobile via ?step=enter_mobile (Change Number link)
$forceEnterMobile = (isset($_GET['step']) && $_GET['step'] === 'enter_mobile');
// Check if mobile is already verified
$mobileData = null;
try {
$stmt = $pdo->prepare("SELECT mobile_number, is_verified, otp_code, otp_expires_at, verification_attempts FROM mobile_verifications WHERE user_id = ?");
$stmt->execute([$user['id']]);
$mobileData = $stmt->fetch();
if ($mobileData && $mobileData['is_verified']) {
$step = 'completed';
} elseif (!$forceEnterMobile && $mobileData && $mobileData['otp_code'] && $mobileData['otp_expires_at'] > date('Y-m-d H:i:s')) {
$step = 'verify_otp';
}
} catch (Exception $e) {
logError('Error fetching mobile verification data', ['user_id' => $user['id'], 'error' => $e->getMessage()]);
}
// Handle form submissions
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (isset($_POST['action'])) {
if ($_POST['action'] === 'send_otp') {
$mobileNumber = isset($_POST['mobile_number']) ? sanitize($_POST['mobile_number']) : '';
// Validate mobile number
if (empty($mobileNumber)) {
$errors[] = 'Please enter your mobile number.';
} elseif (!preg_match('/^[6-9]\d{9}$/', $mobileNumber)) {
$errors[] = 'Please enter a valid 10-digit mobile number starting with 6, 7, 8, or 9.';
} else {
// Check if mobile number is already verified by another user
try {
$stmt = $pdo->prepare("SELECT user_id FROM mobile_verifications WHERE mobile_number = ? AND is_verified = 1 AND user_id != ?");
$stmt->execute([$mobileNumber, $user['id']]);
$existingUser = $stmt->fetch();
if ($existingUser) {
$errors[] = 'This mobile number is already verified by another account.';
} else {
// Generate OTP
$otpCode = sprintf('%06d', mt_rand(100000, 999999));
$otpExpiry = date('Y-m-d H:i:s', strtotime('+10 minutes'));
// Store OTP in database
$stmt = $pdo->prepare("INSERT INTO mobile_verifications (user_id, mobile_number, otp_code, otp_expires_at, verification_attempts) VALUES (?, ?, ?, ?, 0) ON DUPLICATE KEY UPDATE mobile_number = ?, otp_code = ?, otp_expires_at = ?, verification_attempts = 0, updated_at = NOW()");
$stmt->execute([$user['id'], $mobileNumber, $otpCode, $otpExpiry, $mobileNumber, $otpCode, $otpExpiry]);
// Send OTP via 2Factor SMS
$smsResult = sendOTPSMS($mobileNumber, $otpCode);
if ($smsResult['success']) {
logError('OTP sent successfully via 2Factor', [
'user_id' => $user['id'],
'mobile_number' => $mobileNumber,
'sms_response' => $smsResult['response']
]);
$success_message = 'OTP sent to your mobile number +91-' . $mobileNumber;
$step = 'verify_otp';
$mobileData = ['mobile_number' => $mobileNumber];
} else {
logError('Failed to send OTP via 2Factor', [
'user_id' => $user['id'],
'mobile_number' => $mobileNumber,
'error' => $smsResult['message']
]);
$errors[] = 'Failed to send OTP. Please try again or contact support.';
}
}
} catch (Exception $e) {
logError('Error sending OTP', ['user_id' => $user['id'], 'error' => $e->getMessage()]);
$errors[] = 'Error sending OTP. Please try again.';
}
}
} elseif ($_POST['action'] === 'verify_otp') {
$inputOtp = isset($_POST['otp_code']) ? trim($_POST['otp_code']) : '';
if (empty($inputOtp) || !preg_match('/^\d{6}$/', $inputOtp)) {
$errors[] = 'Please enter a valid 6-digit OTP code.';
} else {
try {
$stmt = $pdo->prepare("SELECT * FROM mobile_verifications WHERE user_id = ?");
$stmt->execute([$user['id']]);
$storedData = $stmt->fetch();
if (!$storedData) {
$errors[] = 'No OTP request found. Please request a new OTP.';
$step = 'enter_mobile';
} elseif ($storedData['otp_expires_at'] < date('Y-m-d H:i:s')) {
$errors[] = 'OTP has expired. Please request a new one.';
$step = 'enter_mobile';
} elseif ($storedData['verification_attempts'] >= 5) {
$errors[] = 'Too many failed attempts. Please request a new OTP.';
$step = 'enter_mobile';
} elseif ($storedData['otp_code'] !== $inputOtp) {
$stmt = $pdo->prepare("UPDATE mobile_verifications SET verification_attempts = verification_attempts + 1 WHERE user_id = ?");
$stmt->execute([$user['id']]);
$remaining = 5 - ($storedData['verification_attempts'] + 1);
$errors[] = "Incorrect OTP. $remaining attempts remaining.";
$step = 'verify_otp';
$mobileData = $storedData;
} else {
$pdo->beginTransaction();
$stmt = $pdo->prepare("UPDATE mobile_verifications SET is_verified = 1, otp_code = NULL, otp_expires_at = NULL, updated_at = NOW() WHERE user_id = ?");
$stmt->execute([$user['id']]);
$pointsStmt = $pdo->prepare("INSERT INTO user_points (user_id, points, total_earned) VALUES (?, 10.00, 10.00) ON DUPLICATE KEY UPDATE points = points + 10.00, total_earned = total_earned + 10.00");
$pointsStmt->execute([$user['id']]);
$transStmt = $pdo->prepare("INSERT INTO point_transactions (user_id, transaction_type, points, source, description) VALUES (?, 'earned', 10.00, 'mobile_verification', 'Mobile number verified')");
$transStmt->execute([$user['id']]);
$pdo->commit();
$step = 'completed';
$mobileData = array_merge($storedData, ['is_verified' => 1]);
}
} catch (Exception $e) {
$pdo->rollback();
logError('Error verifying OTP', ['user_id' => $user['id'], 'error' => $e->getMessage()]);
$errors[] = 'Error verifying OTP. Please try again.';
}
}
} elseif ($_POST['action'] === 'resend_otp') {
try {
$stmt = $pdo->prepare("SELECT mobile_number FROM mobile_verifications WHERE user_id = ?");
$stmt->execute([$user['id']]);
$existing = $stmt->fetch();
if ($existing) {
// Generate new OTP
$otpCode = sprintf('%06d', mt_rand(100000, 999999));
$otpExpiry = date('Y-m-d H:i:s', strtotime('+10 minutes'));
$stmt = $pdo->prepare("UPDATE mobile_verifications SET otp_code = ?, otp_expires_at = ?, verification_attempts = 0, updated_at = NOW() WHERE user_id = ?");
$stmt->execute([$otpCode, $otpExpiry, $user['id']]);
// Send SMS using 2Factor
$smsResult = sendOTPSMS($existing['mobile_number'], $otpCode);
if ($smsResult['success']) {
logError('OTP resent successfully via 2Factor', [
'user_id' => $user['id'],
'mobile_number' => $existing['mobile_number'],
'sms_response' => $smsResult['response']
]);
$success_message = 'New OTP sent to your mobile number +91-' . $existing['mobile_number'];
} else {
logError('Failed to resend OTP via 2Factor', [
'user_id' => $user['id'],
'mobile_number' => $existing['mobile_number'],
'error' => $smsResult['message']
]);
$errors[] = 'Failed to resend OTP. Please try again or contact support.';
}
$step = 'verify_otp';
$mobileData = $existing;
}
} catch (Exception $e) {
logError('Error resending OTP', ['user_id' => $user['id'], 'error' => $e->getMessage()]);
$errors[] = 'Error resending OTP. Please try again.';
}
}
}
}
// Get user display info for sidebar
$firstName = htmlspecialchars($user['first_name'] ?? explode('@', $user['email'])[0]);
$initials = strtoupper(substr($user['first_name'] ?? $user['email'], 0, 1) . substr($user['last_name'] ?? '', 0, 1));
if (strlen($initials) < 2) $initials = strtoupper(substr($user['email'], 0, 2));
$userPoints = ['points' => 0];
try { $stmt = $pdo->prepare("SELECT points FROM user_points WHERE user_id = ?"); $stmt->execute([$user['id']]); $p = $stmt->fetch(); if ($p) $userPoints = $p; } catch (Exception $e) {}
?>
Mobile Verification - Relevant Reflex
Enter Mobile
Verify OTP
Done
Enter Your Mobile Number
We'll send a 6-digit OTP to verify your number
Enter OTP Code
Sent to +91
Mobile Verified!
You earned 10 points!
Your number +91 is verified.
You'll receive survey notifications and updates on this number.
Continue Profile
View My Points
Why Verify Your Mobile?
- Earn 10 Points — instant reward for verification
- Survey Notifications — receive SMS alerts for new surveys
- Quick Support — get faster support via WhatsApp
- Account Security — extra layer of protection
- Payment Updates — get notified about reward payments