PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC ] ); // Check if affiliate exists and is active $stmt = $adminPdo->prepare("SELECT * FROM affiliates WHERE affiliate_code = ? AND status = 'active'"); $stmt->execute([$affiliate_code]); $affiliate = $stmt->fetch(); if ($affiliate) { // Track the click (only if not already tracked in this session) if (!isset($_SESSION['affiliate_tracked_' . $affiliate['id']])) { $trackStmt = $adminPdo->prepare(" INSERT INTO affiliate_signups (affiliate_id, ip_address, user_agent, clicked_at) VALUES (?, ?, ?, NOW()) "); $trackStmt->execute([ $affiliate['id'], $_SERVER['REMOTE_ADDR'] ?? null, $_SERVER['HTTP_USER_AGENT'] ?? null ]); $_SESSION['affiliate_tracked_' . $affiliate['id']] = true; $_SESSION['affiliate_signup_id'] = $adminPdo->lastInsertId(); } $affiliate_signup_id = $_SESSION['affiliate_signup_id'] ?? null; } } catch (Exception $e) { logError('Affiliate tracking error: ' . $e->getMessage()); } } // ===== END AFFILIATE TRACKING CODE ===== // ===== MEMBER REFERRAL TRACKING CODE ===== $mref_code = isset($_GET['mref']) ? strtoupper(sanitize($_GET['mref'])) : ''; $mref_user = null; $mref_click_id = null; if (!empty($mref_code) && preg_match('/^RR\d{7}$/', $mref_code)) { try { $mrefPdo = new PDO( "mysql:host=localhost;dbname=u752449863_rrpanel;charset=utf8mb4", 'u752449863_rrpaneladmin', 'S@n@h2016', [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC] ); // Resolve member ID to numeric user id $mrefNumericId = intval(ltrim(substr($mref_code, 2), '0') ?: '0'); $stmt = $mrefPdo->prepare("SELECT id, email, status FROM users WHERE id = ? AND status = 'active' AND email_verified = 1"); $stmt->execute([$mrefNumericId]); $mref_user = $stmt->fetch(); if ($mref_user) { $clientIP = $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0'; // Block if visitor IP matches the referrer's own signup IP $ipCheck = $mrefPdo->prepare("SELECT signup_ip FROM users WHERE id = ?"); $ipCheck->execute([$mref_user['id']]); $referrerIpRow = $ipCheck->fetch(); $isSameIPAsReferrer = ($referrerIpRow && !empty($referrerIpRow['signup_ip']) && $referrerIpRow['signup_ip'] === $clientIP); // SPAM: max 5 hits per IP per referrer link $spamCheck = $mrefPdo->prepare("SELECT COUNT(*) as cnt FROM member_referral_clicks WHERE referrer_user_id = ? AND ip_address = ?"); $spamCheck->execute([$mref_user['id'], $clientIP]); $spamRow = $spamCheck->fetch(); // Also block Facebook/crawler IPs (2a03:2880:: prefix) $isCrawler = (strpos($clientIP, '2a03:2880:') === 0); if (!$isCrawler && !$isSameIPAsReferrer && $spamRow['cnt'] < 5 && !isset($_SESSION['mref_tracked_' . $mref_user['id']])) { $ins = $mrefPdo->prepare("INSERT INTO member_referral_clicks (referrer_user_id, ip_address, user_agent, clicked_at) VALUES (?, ?, ?, NOW())"); $ins->execute([$mref_user['id'], $clientIP, $_SERVER['HTTP_USER_AGENT'] ?? null]); $_SESSION['mref_click_id'] = $mrefPdo->lastInsertId(); $_SESSION['mref_tracked_' . $mref_user['id']] = true; } $mref_click_id = $_SESSION['mref_click_id'] ?? null; } } catch (Exception $e) { logError('Member referral tracking error: ' . $e->getMessage()); } } // ===== END MEMBER REFERRAL TRACKING CODE ===== $errors = []; $success_message = ''; $form_data = []; $fire_conversion = false; // Google Ads conversion flag // ===== ANTI-BOT: Generate CSRF token ===== if (!isset($_SESSION['csrf_token'])) { $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); } // Reset form timing on page load (GET), not POST if ($_SERVER['REQUEST_METHOD'] !== 'POST') { $_SESSION['form_loaded_at'] = time(); } // ===== ANTI-BOT: reCAPTCHA v3 config ===== $recaptcha_site_key = defined('RECAPTCHA_SITE_KEY') ? RECAPTCHA_SITE_KEY : ''; $recaptcha_secret_key = defined('RECAPTCHA_SECRET_KEY') ? RECAPTCHA_SECRET_KEY : ''; // Handle form submission if ($_SERVER['REQUEST_METHOD'] === 'POST') { // Initialize database try { $db = new Database(); $pdo = $db->getConnection(); } catch (Exception $e) { logError('Database connection failed in signup.php: ' . $e->getMessage()); $errors[] = 'System error. Please try again later.'; } if (empty($errors)) { $clientIP = $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0'; $userAgent = $_SERVER['HTTP_USER_AGENT'] ?? ''; $honeypotTriggered = false; // ===== ANTI-BOT CHECK 1: Honeypot field ===== if (!empty($_POST['website_url'])) { // Bots fill hidden fields - silently reject $honeypotTriggered = true; logError('Honeypot triggered on signup', ['ip' => $clientIP, 'ua' => $userAgent]); // Log the attempt try { $pdo->prepare("INSERT INTO registration_attempts (ip_address, email, attempt_type, success, user_agent, honeypot_triggered) VALUES (?, ?, 'registration', 0, ?, 1)") ->execute([$clientIP, $_POST['email'] ?? '', $userAgent]); } catch (Exception $e) {} // Show fake success to not alert the bot $success_message = 'Registration successful! We\'ve sent a verification link to your email address. Please check your inbox and click the link to activate your account.'; $form_data = []; } // ===== ANTI-BOT CHECK 2: CSRF token ===== if (!$honeypotTriggered) { $submittedToken = $_POST['csrf_token'] ?? ''; if (empty($submittedToken) || !hash_equals($_SESSION['csrf_token'], $submittedToken)) { $errors[] = 'Security validation failed. Please refresh the page and try again.'; logError('CSRF token mismatch on signup', ['ip' => $clientIP]); } } // ===== ANTI-BOT CHECK 3: Time-based detection (form filled too fast) ===== if (!$honeypotTriggered && empty($errors)) { $formLoadedAt = $_SESSION['form_loaded_at'] ?? time(); $timeTaken = time() - $formLoadedAt; if ($timeTaken < 3) { $errors[] = 'Please take your time filling out the form.'; logError('Form submitted too quickly', ['ip' => $clientIP, 'seconds' => $timeTaken]); try { $pdo->prepare("INSERT INTO registration_attempts (ip_address, attempt_type, success, user_agent) VALUES (?, 'registration', 0, ?)") ->execute([$clientIP, $userAgent]); } catch (Exception $e) {} } } // ===== ANTI-BOT CHECK 4: IP blocklist ===== if (!$honeypotTriggered && empty($errors)) { try { $stmt = $pdo->prepare("SELECT id FROM ip_blocklist WHERE ip_address = ? AND (expires_at IS NULL OR expires_at > NOW())"); $stmt->execute([$clientIP]); if ($stmt->fetch()) { $errors[] = 'Registration is temporarily unavailable from your network. Please contact support.'; logError('Blocked IP attempted signup', ['ip' => $clientIP]); } } catch (Exception $e) {} } // ===== ANTI-BOT CHECK 5: Rate limiting ===== if (!$honeypotTriggered && empty($errors)) { try { $stmt = $pdo->prepare("SELECT COUNT(*) as cnt FROM registration_attempts WHERE ip_address = ? AND attempt_type = 'registration' AND created_at > DATE_SUB(NOW(), INTERVAL 1 HOUR)"); $stmt->execute([$clientIP]); $attempts = $stmt->fetch(); if ($attempts && $attempts['cnt'] >= MAX_ATTEMPTS_PER_IP_HOUR) { $errors[] = 'Too many registration attempts. Please try again later.'; logError('Rate limit exceeded on signup', ['ip' => $clientIP, 'attempts' => $attempts['cnt']]); if ($attempts['cnt'] >= MAX_ATTEMPTS_PER_IP_HOUR * 3) { try { $pdo->prepare("INSERT IGNORE INTO ip_blocklist (ip_address, reason, blocked_by, expires_at) VALUES (?, 'Excessive registration attempts', 'system', DATE_ADD(NOW(), INTERVAL 2 HOUR))") ->execute([$clientIP]); } catch (Exception $e) {} } } } catch (Exception $e) {} } // ===== ANTI-BOT CHECK 6: IP duplicate registration (permanent - no time window) ===== if (!$honeypotTriggered && empty($errors)) { try { $stmt = $pdo->prepare("SELECT COUNT(*) as cnt FROM users WHERE signup_ip = ?"); $stmt->execute([$clientIP]); $ipSignups = $stmt->fetch(); if ($ipSignups && $ipSignups['cnt'] >= 1) { $errors[] = 'An account has already been registered from your network. If you believe this is an error, please contact support@relevantreflex.com.'; logError('Duplicate IP registration blocked (permanent)', ['ip' => $clientIP, 'existing_count' => $ipSignups['cnt']]); try { $pdo->prepare("INSERT INTO registration_attempts (ip_address, email, attempt_type, success, user_agent) VALUES (?, ?, 'registration', 0, ?)") ->execute([$clientIP, $_POST['email'] ?? '', $userAgent]); } catch (Exception $e) {} } } catch (Exception $e) {} } // ===== ANTI-BOT CHECK 7: reCAPTCHA v3 verification ===== if (!$honeypotTriggered && empty($errors) && !empty($recaptcha_secret_key)) { $recaptchaResponse = $_POST['g-recaptcha-response'] ?? ''; if (empty($recaptchaResponse)) { $errors[] = 'Security verification failed. Please try again.'; } else { $verifyUrl = 'https://www.google.com/recaptcha/api/siteverify'; $response = file_get_contents($verifyUrl . '?' . http_build_query([ 'secret' => $recaptcha_secret_key, 'response' => $recaptchaResponse, 'remoteip' => $clientIP ])); $recaptchaResult = json_decode($response, true); $captchaScore = $recaptchaResult['score'] ?? 0; if (!($recaptchaResult['success'] ?? false) || $captchaScore < 0.3) { $errors[] = 'Security verification failed. If you are not a robot, please try again.'; logError('reCAPTCHA failed', ['ip' => $clientIP, 'score' => $captchaScore]); try { $pdo->prepare("INSERT INTO registration_attempts (ip_address, attempt_type, success, user_agent, captcha_score) VALUES (?, 'registration', 0, ?, ?)") ->execute([$clientIP, $userAgent, $captchaScore]); } catch (Exception $e) {} } } } // Get and sanitize form data $email = isset($_POST['email']) ? sanitize($_POST['email']) : ''; $email_confirm = isset($_POST['email_confirm']) ? sanitize($_POST['email_confirm']) : ''; $password = isset($_POST['password']) ? $_POST['password'] : ''; $gender = isset($_POST['gender']) ? sanitize($_POST['gender']) : ''; $dateOfBirth = isset($_POST['date_of_birth']) ? sanitize($_POST['date_of_birth']) : ''; $postcode = isset($_POST['postcode']) ? sanitize($_POST['postcode']) : ''; $privacyAccepted = isset($_POST['privacy_policy']) ? true : false; // FIX #4: Age confirmation checkbox validation $ageConfirmed = isset($_POST['age_confirm']) ? true : false; // Store form data for repopulating form on error $form_data = [ 'email' => $email, 'gender' => $gender, 'date_of_birth' => $dateOfBirth, 'postcode' => $postcode, 'whatsapp_number' => isset($_POST['whatsapp_number']) ? sanitize($_POST['whatsapp_number']) : '', ]; // Validation if (empty($email)) { $errors[] = 'Email is required.'; } if (!empty($email) && !empty($email_confirm) && $email !== $email_confirm) { $errors[] = 'Email addresses do not match. Please check and try again.'; } if (empty($email_confirm)) { $errors[] = 'Please confirm your email address.'; } if (empty($password)) { $errors[] = 'Password is required.'; } if (empty($gender)) { $errors[] = 'Gender is required.'; } if (empty($dateOfBirth)) { $errors[] = 'Date of birth is required.'; } if (empty($postcode)) { $errors[] = 'Postcode is required.'; } if (!$privacyAccepted) { $errors[] = 'You must agree to the Privacy Policy and Terms & Conditions.'; } // FIX #4: Validate age confirmation if (!$ageConfirmed) { $errors[] = 'You must confirm that you are 18 years of age or older.'; } // Validate email format if (!empty($email) && !validateEmail($email)) { $errors[] = 'Please provide a valid email address.'; } // Validate password strength if (!empty($password) && !validatePassword($password)) { $errors[] = 'Password must be at least 8 characters long.'; } // Validate gender if (!empty($gender) && !in_array($gender, ['Male', 'Female'])) { $errors[] = 'Please select a valid gender.'; } // Validate date of birth if (!empty($dateOfBirth) && !validateDateOfBirth($dateOfBirth)) { $errors[] = 'You must be at least 18 years old to register.'; } // Validate postcode if (!empty($postcode) && !validatePostcode($postcode)) { $errors[] = 'Please provide a valid 6-digit postal code.'; } // ===== WHATSAPP / MOBILE NUMBER ===== $whatsapp_number = isset($_POST['whatsapp_number']) ? preg_replace('/\D/', '', sanitize($_POST['whatsapp_number'])) : ''; $whatsapp_number_confirm = isset($_POST['whatsapp_number_confirm']) ? preg_replace('/\D/', '', sanitize($_POST['whatsapp_number_confirm'])) : ''; $is_whatsapp = isset($_POST['is_whatsapp']) ? 1 : 0; $form_data['whatsapp_number'] = $whatsapp_number; if (empty($whatsapp_number)) { $errors[] = 'Mobile/WhatsApp number is required.'; } elseif (!preg_match('/^[6-9][0-9]{9}$/', $whatsapp_number)) { $errors[] = 'Please enter a valid 10-digit Indian mobile number (starting with 6–9).'; } elseif ($whatsapp_number !== $whatsapp_number_confirm) { $errors[] = 'Mobile numbers do not match. Please check and try again.'; } // ===== END WHATSAPP / MOBILE NUMBER ===== // If no validation errors, proceed with registration if (empty($errors)) { try { // Check if email already exists $stmt = $pdo->prepare("SELECT id FROM users WHERE email = ?"); $stmt->execute([$email]); if ($stmt->rowCount() > 0) { $errors[] = 'An account with this email address already exists. Please try logging in or use a different email.'; } else { // Hash the password $hashedPassword = hashPassword($password); // Start transaction $pdo->beginTransaction(); // Insert new user (with signup IP and WhatsApp number) $stmt = $pdo->prepare(" INSERT INTO users (email, password, gender, date_of_birth, postcode, whatsapp_number, whatsapp_is_whatsapp, signup_ip, email_verified, status, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, 0, 'inactive', NOW()) "); $stmt->execute([$email, $hashedPassword, $gender, $dateOfBirth, $postcode, $whatsapp_number, $is_whatsapp, $clientIP]); $userId = $pdo->lastInsertId(); // Auto-map state & city from PIN code try { $pinStmt = $pdo->prepare("SELECT state, city FROM pin_lookup WHERE pincode = ? LIMIT 1"); $pinStmt->execute([$postcode]); $pinRow = $pinStmt->fetch(PDO::FETCH_ASSOC); if ($pinRow) { $pdo->prepare("UPDATE users SET state = ?, city = ? WHERE id = ?")->execute([$pinRow['state'], $pinRow['city'], $userId]); } } catch (Exception $e) {} // Generate verification token $verificationToken = generateSecureToken(); $expiresAt = date('Y-m-d H:i:s', strtotime('+' . TOKEN_EXPIRY_HOURS . ' hours')); // Insert verification token $stmt = $pdo->prepare(" INSERT INTO email_verifications (user_id, token, expires_at, created_at) VALUES (?, ?, ?, NOW()) "); $stmt->execute([$userId, $verificationToken, $expiresAt]); // Save WhatsApp number to mobile_verifications (unverified) so it shows in admin immediately if (!empty($whatsapp_number)) { $pdo->prepare(" INSERT INTO mobile_verifications (user_id, mobile_number, is_verified, verification_attempts, created_at) VALUES (?, ?, 0, 0, NOW()) ON DUPLICATE KEY UPDATE mobile_number = ?, updated_at = NOW() ")->execute([$userId, $whatsapp_number, $whatsapp_number]); } // Commit transaction $pdo->commit(); // Log successful registration attempt try { $pdo->prepare("INSERT INTO registration_attempts (ip_address, email, attempt_type, success, user_agent) VALUES (?, ?, 'registration', 1, ?)") ->execute([$clientIP, $email, $userAgent]); } catch (Exception $e) {} // Regenerate CSRF token $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); // ===== UPDATE MEMBER REFERRAL TRACKING ===== if ($mref_user && $mref_click_id && isset($mrefPdo)) { try { $refIpCheck = $mrefPdo->prepare("SELECT signup_ip FROM users WHERE id = ?"); $refIpCheck->execute([$mref_user['id']]); $refIpRow = $refIpCheck->fetch(); $isSameIP = ($refIpRow && !empty($refIpRow['signup_ip']) && $refIpRow['signup_ip'] === $clientIP); if ($mref_user['id'] != $userId && !$isSameIP) { $mrefPdo->prepare(" UPDATE member_referral_clicks SET referee_user_id = ?, email = ?, signup_completed = 1, signed_up_at = NOW() WHERE id = ? ")->execute([$userId, $email, $mref_click_id]); } } catch (Exception $e) { logError('Member referral signup update error: ' . $e->getMessage()); } } // ===== END UPDATE MEMBER REFERRAL TRACKING ===== // ===== UPDATE AFFILIATE TRACKING ===== if ($affiliate && $affiliate_signup_id && $adminPdo) { try { $updateStmt = $adminPdo->prepare(" UPDATE affiliate_signups SET panel_user_id = ?, email = ?, signup_completed = 1, signed_up_at = NOW(), reward_amount = ? WHERE id = ? "); $updateStmt->execute([ $userId, $email, $affiliate['signup_reward'], $affiliate_signup_id ]); $adminPdo->exec("UPDATE affiliates SET total_signups = total_signups + 1 WHERE id = " . intval($affiliate['id'])); logError('Affiliate signup tracked', [ 'user_id' => $userId, 'affiliate_code' => $affiliate_code, 'email' => $email ]); } catch (Exception $e) { logError('Failed to update affiliate tracking: ' . $e->getMessage()); } } // ===== END UPDATE AFFILIATE TRACKING ===== // Send verification email $emailHandler = new EmailHandler(); $emailSent = $emailHandler->sendVerificationEmail($email, $verificationToken); if ($emailSent) { logError('User registered successfully', [ 'user_id' => $userId, 'email' => $email, 'verification_token_sent' => true, 'affiliate_code' => $affiliate_code ?? null ]); $success_message = 'Registration successful! We\'ve sent a verification link to your email address. Please check your inbox and click the link to activate your account.'; $form_data = []; $fire_conversion = true; // Real signup - fire Google Ads conversion } else { logError('User registered but email verification failed', [ 'user_id' => $userId, 'email' => $email ]); $success_message = 'Registration successful! However, we encountered an issue sending the verification email. Please contact support at support@relevantreflex.com to activate your account.'; $form_data = []; $fire_conversion = true; // Real signup - fire Google Ads conversion } } } catch (PDOException $e) { if ($pdo->inTransaction()) { $pdo->rollback(); } logError('Database error during registration', ['error' => $e->getMessage(), 'email' => $email]); $errors[] = 'Registration failed due to a system error. Please try again later.'; } catch (Exception $e) { if ($pdo->inTransaction()) { $pdo->rollback(); } logError('General error during registration', ['error' => $e->getMessage(), 'email' => $email]); $errors[] = 'An unexpected error occurred. Please try again later.'; } } } } ?>
Furnish some of your basic information below and start participating in paid surveys to earn rewards.
We've sent a verification link to:
Click the link in the email to activate your account and start earning.
OPEN YOUR EMAIL NOW:
Can't find it? Check your Spam or Junk folder. The email is from registration@relevantreflex.com