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
Mobile Verification
pts
Enter Mobile
Verify OTP
Done
'; ?>

Enter Your Mobile Number

We'll send a 6-digit OTP to verify your number

+91
Enter a mobile number that you have access to

Enter OTP Code

Sent to +91

OTP is valid for 10 minutes
| Change Number

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