<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
ini_set('default_charset', 'UTF-8');
date_default_timezone_set('America/Argentina/Buenos_Aires');
header('HTTP/1.1 200 OK');

function saveLog($text, $dump=0) {
    $xpldName = explode('.', basename(__FILE__));
    $secretName = explode('_', $xpldName[0]);
    $f = fopen("logs/".$secretName[0]."_".date('m-Y')."__".md5($secretName[1]).".txt","a+");
    $t = date('d/m/Y H:i').": ".$text.($dump==1 ? " - Dump: ".strtr(print_r($_POST, true), array('  ' => ' ')) : "")."\r\n";
    fwrite($f, $t, strlen($t));
    fclose($f);
}

function notificarFraudeAdmin($mensaje, $datos_atacante = null) {
    // 📧 Emails de administradores a notificar
    $admin_emails = [
        'juanvicttori@gmail.com',
        'maycoballatore@gmail.com'
    ];
    
    $subject = "🚨 ALERTA DE FRAUDE - PayPal IPN";
    
    // Extraer datos del mensaje para el HTML
    preg_match('/Transacción ID: (.+)/', $mensaje, $matches);
    $transaccion_id = isset($matches[1]) ? trim($matches[1]) : 'N/A';
    
    preg_match('/IP de origen: (.+)/', $mensaje, $matches);
    $ip_atacante = isset($matches[1]) ? trim($matches[1]) : ($_SERVER['REMOTE_ADDR'] ?? 'N/A');
    
    // Construir email HTML con datos completos del atacante
    $email_body = '
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <style>
            body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
            .container { max-width: 800px; margin: 0 auto; padding: 20px; }
            .header { background: #dc3545; color: white; padding: 20px; text-align: center; border-radius: 8px 8px 0 0; }
            .content { background: #f8f9fa; padding: 20px; border: 1px solid #dee2e6; }
            .details { background: white; padding: 15px; border-radius: 5px; margin: 15px 0; }
            .detail-row { display: flex; justify-content: space-between; padding: 8px 0; border-bottom: 1px solid #eee; }
            .detail-label { font-weight: bold; color: #495057; }
            .detail-value { color: #dc3545; font-weight: bold; word-break: break-all; }
            .footer { background: #6c757d; color: white; padding: 15px; text-align: center; border-radius: 0 0 8px 8px; font-size: 12px; }
            .fraud-icon { font-size: 48px; color: #dc3545; }
            .alert { background: #f8d7da; padding: 15px; border-left: 4px solid #dc3545; margin: 10px 0; color: #721c24; }
            .danger { background: #f5c6cb; padding: 10px; border-radius: 4px; margin: 10px 0; }
            .code-block { background: #f4f4f4; padding: 10px; border-radius: 4px; font-family: monospace; font-size: 12px; margin: 10px 0; max-height: 300px; overflow-y: auto; }
            .section-title { background: #e9ecef; padding: 10px; margin: 15px 0 5px 0; font-weight: bold; border-left: 4px solid #dc3545; }
        </style>
    </head>
    <body>
        <div class="container">
            <div class="header">
                <div class="fraud-icon">🚨</div>
                <h2>ALERTA DE FRAUDE DETECTADO</h2>
                <p>Sistema Anti-Fraude PayPal IPN</p>
            </div>
            
            <div class="content">
                <div class="alert">
                    <strong>⚠️ SE HA DETECTADO UN POSIBLE INTENTO DE FRAUDE</strong><br>
                    IP NO OFICIAL intentando acceder al sistema PayPal IPN
                </div>
                
                <div class="details">
                    <h3 style="color: #dc3545; margin-top: 0;">🔍 INFORMACIÓN BÁSICA</h3>
                    
                    <div class="detail-row">
                        <span class="detail-label">🆔 ID Transacción:</span>
                        <span class="detail-value">' . htmlspecialchars($transaccion_id) . '</span>
                    </div>
                    
                    <div class="detail-row">
                        <span class="detail-label">🌍 IP del atacante:</span>
                        <span class="detail-value">' . htmlspecialchars($ip_atacante) . '</span>
                    </div>
                    
                    <div class="detail-row">
                        <span class="detail-label">📅 Fecha:</span>
                        <span class="detail-value">' . date('d/m/Y H:i:s') . '</span>
                    </div>
                    
                    <div class="detail-row">
                        <span class="detail-label">🖥️ Servidor:</span>
                        <span class="detail-value">' . ($_SERVER['SERVER_NAME'] ?? 'N/A') . '</span>
                    </div>
                </div>';

    // Si tenemos datos del atacante, incluirlos en el email
    if ($datos_atacante) {
        $email_body .= '
                <div class="section-title">📊 DATOS COMPLETOS DEL ATACANTE</div>
                
                <div class="details">
                    <h4>📝 Datos POST Enviados:</h4>
                    <div class="code-block">' . htmlspecialchars(json_encode($datos_atacante['POST_DATA'], JSON_PRETTY_PRINT)) . '</div>
                </div>
                
                <div class="details">
                    <h4>🌐 Headers HTTP:</h4>
                    <div class="code-block">' . htmlspecialchars(json_encode($datos_atacante['HTTP_HEADERS'], JSON_PRETTY_PRINT)) . '</div>
                </div>
                
                <div class="details">
                    <h4>🖥️ Información del Servidor:</h4>
                    <div class="code-block">' . htmlspecialchars(json_encode($datos_atacante['SERVER_INFO'], JSON_PRETTY_PRINT)) . '</div>
                </div>';
        
        // Si hay datos RAW, incluirlos
        if (!empty($datos_atacante['RAW_POST'])) {
            $email_body .= '
                <div class="details">
                    <h4>📋 Datos RAW del POST:</h4>
                    <div class="code-block">' . htmlspecialchars($datos_atacante['RAW_POST']) . '</div>
                </div>';
        }
        
        $email_body .= '
                <div class="details">
                    <h4>⏰ Información de Tiempo:</h4>
                    <div class="code-block">' . htmlspecialchars(json_encode($datos_atacante['TIMESTAMP_INFO'], JSON_PRETTY_PRINT)) . '</div>
                </div>';
    }

    $email_body .= '
                <div class="danger">
                    <strong>🛡️ ACCIÓN TOMADA:</strong><br>
                    • Conexión <strong>BLOQUEADA</strong> automáticamente<br>
                    • No se procesó ningún dato<br>
                    • Evento registrado en logs de seguridad<br>
                    • Datos completos capturados para análisis
                </div>
            </div>
            
            <div class="footer">
                <strong>🔒 Sistema Anti-Fraude PayPal IPN</strong><br>
                L2Jade - Protección Automática Activada<br>
                <em>Analiza los datos capturados para identificar nuevos patrones de ataque</em>
            </div>
        </div>
    </body>
    </html>';
    
    // Enviar a cada administrador
    $enviados = 0;
    foreach ($admin_emails as $email) {
        if (enviarEmailSMTP($email, $subject, $email_body, true)) { // true = HTML
            $enviados++;
            saveLog("Notificación de fraude enviada a: $email", 0);
            logToServer("Email de fraude enviado exitosamente a: $email", 'EMAIL');
        } else {
            saveLog("ERROR: No se pudo enviar notificación a: $email", 0);
            logToServer("ERROR: Falló envío de email de fraude a: $email", 'EMAIL');
        }
    }
    
    if ($enviados > 0) {
        saveLog("Notificaciones de fraude enviadas: $enviados/" . count($admin_emails), 0);
        logToServer("Notificaciones de fraude completadas: $enviados/" . count($admin_emails) . " emails enviados", 'EMAIL');
    } else {
        saveLog("ERROR CRÍTICO: No se pudo enviar ninguna notificación de fraude", 0);
        logToServer("ERROR CRÍTICO: Todos los emails de fraude fallaron", 'EMAIL');
    }
}

// ✅ NOTIFICACIÓN DE TRANSACCIÓN EXITOSA
function notificarTransaccionExitosa($transaccion_id, $personaje, $cantidad_original, $cantidad_final, $precio, $payer_email) {
    // 📧 Emails de administradores a notificar
    $admin_emails = [
        'juanvicttori@gmail.com',
        'maycoballatore@gmail.com'
    ];
    
    $subject = "✅ TRANSACCIÓN EXITOSA - PayPal IPN";
    
    $bonus_coins = $cantidad_final - $cantidad_original;
    $porcentaje_bonus = ($bonus_coins / $cantidad_original) * 100;
    
    // Construir email HTML
    $email_body = '
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <style>
            body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
            .container { max-width: 600px; margin: 0 auto; padding: 20px; }
            .header { background: #28a745; color: white; padding: 20px; text-align: center; border-radius: 8px 8px 0 0; }
            .content { background: #f8f9fa; padding: 20px; border: 1px solid #dee2e6; }
            .details { background: white; padding: 15px; border-radius: 5px; margin: 15px 0; }
            .detail-row { display: flex; justify-content: space-between; padding: 8px 0; border-bottom: 1px solid #eee; }
            .detail-label { font-weight: bold; color: #495057; }
            .detail-value { color: #28a745; font-weight: bold; }
            .footer { background: #6c757d; color: white; padding: 15px; text-align: center; border-radius: 0 0 8px 8px; font-size: 12px; }
            .success-icon { font-size: 48px; color: #28a745; }
            .highlight { background: #d4edda; padding: 10px; border-left: 4px solid #28a745; margin: 10px 0; }
        </style>
    </head>
    <body>
        <div class="container">
            <div class="header">
                <div class="success-icon">✅</div>
                <h2>TRANSACCIÓN EXITOSA</h2>
                <p>Sistema PayPal IPN - L2Jade</p>
            </div>
            
            <div class="content">
                <div class="highlight">
                    <strong>Se ha procesado exitosamente una transacción PayPal</strong>
                </div>
                
                <div class="details">
                    <h3 style="color: #28a745; margin-top: 0;">📋 DETALLES DE LA TRANSACCIÓN</h3>
                    
                    <div class="detail-row">
                        <span class="detail-label">🆔 ID Transacción:</span>
                        <span class="detail-value">' . $transaccion_id . '</span>
                    </div>
                    
                    <div class="detail-row">
                        <span class="detail-label">🎮 Personaje:</span>
                        <span class="detail-value">' . $personaje . '</span>
                    </div>
                    
                    <div class="detail-row">
                        <span class="detail-label">📧 Email del pagador:</span>
                        <span class="detail-value">' . $payer_email . '</span>
                    </div>
                    
                    <div class="detail-row">
                        <span class="detail-label">💰 Monto pagado:</span>
                        <span class="detail-value">$' . $precio . ' USD</span>
                    </div>
                    
                    <div class="detail-row">
                        <span class="detail-label">🪙 Coins comprados:</span>
                        <span class="detail-value">' . $cantidad_original . ' coins</span>
                    </div>
                    
                    <div class="detail-row">
                        <span class="detail-label">🎁 Bonus aplicado:</span>
                        <span class="detail-value">' . $bonus_coins . ' coins (' . number_format($porcentaje_bonus, 0) . '%)</span>
                    </div>
                    
                    <div class="detail-row" style="border-bottom: 2px solid #28a745; font-size: 18px;">
                        <span class="detail-label">✨ Total entregado:</span>
                        <span class="detail-value" style="font-size: 20px;">' . $cantidad_final . ' coins</span>
                    </div>
                </div>
                
                <div class="details">
                    <h3 style="color: #6c757d; margin-top: 0;">🌐 INFORMACIÓN TÉCNICA</h3>
                    
                    <div class="detail-row">
                        <span class="detail-label">🌍 IP del comprador:</span>
                        <span class="detail-value">' . $_SERVER['REMOTE_ADDR'] . '</span>
                    </div>
                    
                    <div class="detail-row">
                        <span class="detail-label">📅 Fecha:</span>
                        <span class="detail-value">' . date('d/m/Y H:i:s') . '</span>
                    </div>
                    
                    <div class="detail-row">
                        <span class="detail-label">🖥️ Servidor:</span>
                        <span class="detail-value">' . $_SERVER['SERVER_NAME'] . '</span>
                    </div>
                </div>
            </div>
            
            <div class="footer">
                <strong>Sistema Anti-Fraude PayPal IPN</strong><br>
                L2Jade - Notificación Automática
            </div>
        </div>
    </body>
    </html>';
    
    // Enviar a cada administrador
    $enviados = 0;
    foreach ($admin_emails as $email) {
        if (enviarEmailSMTP($email, $subject, $email_body, true)) { // true = HTML
            $enviados++;
            saveLog("Notificación de transacción exitosa enviada a: $email", 0);
            logToServer("Email de transacción exitosa enviado a: $email - TXN: $transaccion_id", 'EMAIL');
        } else {
            saveLog("ERROR: No se pudo enviar notificación exitosa a: $email", 0);
            logToServer("ERROR: Falló envío de email exitoso a: $email - TXN: $transaccion_id", 'EMAIL');
        }
    }
    
    if ($enviados > 0) {
        saveLog("Notificaciones de transacción exitosa enviadas: $enviados/" . count($admin_emails), 0);
        logToServer("Notificaciones exitosas completadas: $enviados/" . count($admin_emails) . " emails enviados - TXN: $transaccion_id", 'EMAIL');
    } else {
        saveLog("ERROR: No se pudo enviar ninguna notificación de transacción exitosa", 0);
        logToServer("ERROR CRÍTICO: Todos los emails exitosos fallaron - TXN: $transaccion_id", 'EMAIL');
    }
}

// 📧 CONFIGURACIÓN SMTP - Configurar estos valores
function getSmtpConfig() {
    return [
        'host' => 'mail.l2jade.com.ar',
        'port' => 465,
        'username' => 'soporte@l2jade.com.ar',
        'password' => 'Za6s;-9^#A*e',
        'encryption' => 'ssl',
        'from_email' => 'soporte@l2jade.com.ar',
        'from_name' => 'Sistema Anti-Fraude MercadoPago'
    ];
}

// 🔧 CONFIGURACIÓN DE LOGGING AL SERVIDOR WEB
function getServerLogConfig() {
    return [
        'enabled' => true,                // 🔧 true = ON, false = OFF
        'prefix' => '[PAYPAL-IPN]',      // Prefijo para identificar logs
        'log_successful' => true,        // Log transacciones exitosas
        'log_fraud' => true,             // Log intentos de fraude
        'log_errors' => true,            // Log errores del sistema
        'log_email_status' => true       // Log estado de envío de emails
    ];
}

// 📝 FUNCIÓN PARA LOG AL SERVIDOR WEB
function logToServer($message, $type = 'INFO') {
    $config = getServerLogConfig();
    
    if (!$config['enabled']) {
        return; // Logging deshabilitado
    }
    
    // Filtrar según tipo de log
    switch ($type) {
        case 'SUCCESS':
            if (!$config['log_successful']) return;
            break;
        case 'FRAUD':
            if (!$config['log_fraud']) return;
            break;
        case 'ERROR':
            if (!$config['log_errors']) return;
            break;
        case 'EMAIL':
            if (!$config['log_email_status']) return;
            break;
    }
    
    $timestamp = date('Y-m-d H:i:s');
    $ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown';
    $script = basename(__FILE__);
    
    $logMessage = "{$config['prefix']} [$timestamp] [$type] [$ip] [$script] $message";
    
    // Escribir al log del servidor web (Apache/Nginx error.log)
    error_log($logMessage);
    
    // 📁 TAMBIÉN ESCRIBIR A ARCHIVO LOCAL (para cPanel)
    $localLogFile = "logs/paypal_debug_" . date('Y-m') . ".log";
    $localLogMessage = "[$timestamp] [$type] $message\n";
    
    // Crear directorio si no existe
    if (!file_exists('logs')) {
        mkdir('logs', 0755, true);
    }
    
    // Escribir al archivo local
    file_put_contents($localLogFile, $localLogMessage, FILE_APPEND | LOCK_EX);
}

// 🚨 SMTP NATIVO - Envío de emails
function enviarEmailSMTP($to, $subject, $body, $isHtml = false) {
    $config = getSmtpConfig();
    
    logToServer("Iniciando envío SMTP a: $to, Subject: $subject", 'EMAIL');
    
    // Crear conexión socket con SSL si es necesario
    $socket_url = $config['host'];
    if ($config['encryption'] === 'ssl') {
        $socket_url = 'ssl://' . $config['host'];
    }
    
    $socket = fsockopen($socket_url, $config['port'], $errno, $errstr, 10); // Timeout reducido a 10 segundos
    if (!$socket) {
        saveLog("ERROR SMTP: No se pudo conectar - $errno: $errstr", 0);
        logToServer("ERROR SMTP: Conexión fallida - Host: {$socket_url}:{$config['port']}, Error: $errno: $errstr", 'EMAIL');
        return false;
    }
    
    // Configurar timeout del socket
    stream_set_timeout($socket, 10);
    
    logToServer("Conexión SMTP establecida - Host: {$socket_url}:{$config['port']}", 'EMAIL');
    
    // Función para leer respuesta del servidor (maneja respuestas multi-línea)
    $read = function() use ($socket) {
        $response = '';
        do {
            $line = fgets($socket, 515);
            $response .= $line;
            // Continuar leyendo si la línea termina con '-' (respuesta multi-línea)
        } while (isset($line[3]) && $line[3] === '-');
        $clean_response = trim($response);
        logToServer("SMTP <- $clean_response", 'EMAIL');
        return $clean_response;
    };
    
    // Función para enviar comando
    $send = function($command) use ($socket) {
        logToServer("SMTP -> $command", 'EMAIL');
        fputs($socket, $command . "\r\n");
    };
    
    try {
        // Leer saludo del servidor
        $response = $read();
        if (strpos($response, '220') !== 0) {
            throw new Exception("Error en saludo SMTP: $response");
        }
        
        // EHLO
        $send("EHLO " . $config['host']);
        $response = $read();
        if (strpos($response, '250') !== 0) {
            throw new Exception("Error en EHLO: $response");
        }
        
        // STARTTLS solo si es TLS (no SSL)
        if ($config['encryption'] === 'tls') {
            logToServer("Iniciando STARTTLS", 'EMAIL');
            $send("STARTTLS");
            $response = $read();
            if (strpos($response, '220') !== 0) {
                throw new Exception("Error en STARTTLS: $response");
            }
            
            if (!stream_socket_enable_crypto($socket, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) {
                throw new Exception("Error al habilitar TLS");
            }
            
            logToServer("TLS habilitado exitosamente", 'EMAIL');
            
            // EHLO después de TLS
            $send("EHLO " . $config['host']);
            $response = $read();
        }
        
        // Autenticación
        logToServer("Iniciando autenticación SMTP - Usuario: {$config['username']}", 'EMAIL');
        $send("AUTH LOGIN");
        $response = $read();
        if (strpos($response, '334') !== 0) {
            throw new Exception("Error iniciando AUTH LOGIN: $response");
        }
        
        // Enviar usuario codificado
        $send(base64_encode($config['username']));
        $response = $read();
        if (strpos($response, '334') !== 0) {
            throw new Exception("Error con usuario: $response");
        }
        
        // Enviar contraseña codificada
        $send(base64_encode($config['password']));
        $response = $read();
        if (strpos($response, '235') !== 0) {
            throw new Exception("Error de autenticación - credenciales incorrectas: $response");
        }
        
        logToServer("Autenticación SMTP exitosa", 'EMAIL');
        
        // FROM
        $send("MAIL FROM: <" . $config['from_email'] . ">");
        $response = $read();
        if (strpos($response, '250') !== 0) {
            throw new Exception("Error en MAIL FROM: $response");
        }
        
        // TO (puede ser array de emails)
        $recipients = is_array($to) ? $to : [$to];
        foreach ($recipients as $recipient) {
            $send("RCPT TO: <$recipient>");
            $response = $read();
            if (strpos($response, '250') !== 0) {
                throw new Exception("Error en RCPT TO: $response");
            }
        }
        
        logToServer("Destinatarios configurados: " . implode(', ', $recipients), 'EMAIL');
        
        // DATA
        $send("DATA");
        $response = $read();
        if (strpos($response, '354') !== 0) {
            throw new Exception("Error en DATA: $response");
        }
        
        // Headers y cuerpo del email
        $headers = "From: " . $config['from_name'] . " <" . $config['from_email'] . ">\r\n";
        $headers .= "Reply-To: " . $config['from_email'] . "\r\n";
        $headers .= "Content-Type: " . ($isHtml ? "text/html" : "text/plain") . "; charset=UTF-8\r\n";
        $headers .= "X-Priority: 1\r\n";
        $headers .= "Date: " . date('r') . "\r\n";
        
        $emailContent = "To: " . implode(', ', $recipients) . "\r\n";
        $emailContent .= "Subject: $subject\r\n";
        $emailContent .= $headers . "\r\n";
        $emailContent .= $body . "\r\n.\r\n";
        
        $send($emailContent);
        $response = $read();
        if (strpos($response, '250') !== 0) {
            throw new Exception("Error enviando email: $response");
        }
        
        logToServer("Contenido del email enviado", 'EMAIL');
        
        // QUIT
        $send("QUIT");
        fclose($socket);
        
        logToServer("Email enviado exitosamente a: $to", 'EMAIL');
        return true;
        
    } catch (Exception $e) {
        saveLog("ERROR SMTP: " . $e->getMessage(), 0);
        logToServer("ERROR SMTP: " . $e->getMessage() . " - Destinatario: $to", 'EMAIL');
        fclose($socket);
        return false;
    }
}

// 🛡️ VALIDACIÓN DE IPs OFICIALES DE PAYPAL
function validarIPPayPal($ip) {
    // Rangos oficiales de IP de PayPal (actualizado 2024)
    $paypal_ip_ranges = [
        '64.4.240.0/21',
        '64.4.248.0/22',
        '66.211.168.0/22',
        '91.243.72.0/23',
        '173.0.80.0/20',
        '185.177.52.0/22',
        '192.160.215.0/24',
        '198.54.216.0/23'
    ];
    
    foreach ($paypal_ip_ranges as $range) {
        if (ipEnRango($ip, $range)) {
            return true;
        }
    }
    
    return false;
}

// Función auxiliar para verificar si una IP está en un rango CIDR
function ipEnRango($ip, $range) {
    list($subnet, $bits) = explode('/', $range);
    
    // Convertir IP y subnet a enteros
    $ip_long = ip2long($ip);
    $subnet_long = ip2long($subnet);
    
    // Calcular la máscara
    $mask = -1 << (32 - $bits);
    
    // Verificar si la IP está en el rango
    return ($ip_long & $mask) == ($subnet_long & $mask);
}

saveLog("Retorno de paypal", 2);

$indexing = 1;
include '../configs.php';
include '../functions/func.php';

// 🚨 VALIDAR IP DE ORIGEN - Solo IPs oficiales de PayPal
$client_ip = $_SERVER['REMOTE_ADDR'];

// Manejar IPs detrás de proxies/CDN
if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    $forwarded_ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
    $client_ip = trim($forwarded_ips[0]); // Primera IP de la cadena
}
if (!empty($_SERVER['HTTP_X_REAL_IP'])) {
    $client_ip = $_SERVER['HTTP_X_REAL_IP'];
}

// 🔍 Log detallado de detección de IP
logToServer("DEBUG - IP Detection: REMOTE_ADDR=" . ($_SERVER['REMOTE_ADDR'] ?? 'N/A') . ", X_FORWARDED_FOR=" . ($_SERVER['HTTP_X_FORWARDED_FOR'] ?? 'N/A') . ", X_REAL_IP=" . ($_SERVER['HTTP_X_REAL_IP'] ?? 'N/A') . ", Final IP: $client_ip", 'DEBUG');

// Validación adicional de formato IP antes de procesar
if (!filter_var($client_ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
    logToServer("ERROR - IP con formato inválido detectada: '$client_ip'", 'ERROR');
    saveLog("🚨 IP INVÁLIDA: $client_ip", 1);
    http_response_code(400);
    exit("Bad Request - Invalid IP format");
}

// Validar que la IP sea de PayPal
if (!validarIPPayPal($client_ip)) {
    // 📊 CAPTURAR TODOS LOS DATOS DEL ATACANTE
    $datos_atacante = capturarDatosAtacante();
    
    $fraud_message = "IP NO OFICIAL DETECTADA - POSIBLE FRAUDE!\n";
    $fraud_message .= "IP de origen: $client_ip\n";
    $fraud_message .= "Esta IP NO está en los rangos oficiales de PayPal\n";
    $fraud_message .= "Transacción ID: " . ($_POST['txn_id'] ?? 'N/A') . "\n";
    $fraud_message .= "Fecha: " . date('d/m/Y H:i:s') . "\n";
    
    saveLog("🚨 IP NO OFICIAL BLOQUEADA: $client_ip - Datos completos capturados", 1);
    
    // Enviar notificación con TODOS los datos capturados
    notificarFraudeAdmin($fraud_message, $datos_atacante);
    
    logToServer("🚨 IP BLOQUEADA - IP no oficial: $client_ip, TXN: " . ($_POST['txn_id'] ?? 'unknown') . " - Datos completos enviados por email", 'FRAUD');
    
    // Responder con código 403 Forbidden
    http_response_code(403);
    exit("Access denied - Unauthorized IP");
}

logToServer("IP validada - IP oficial de PayPal: $client_ip", 'INFO');

// Log inicial al servidor web
logToServer("IPN iniciado - POST recibido de PayPal", 'INFO');
logToServer("Datos POST recibidos: " . json_encode($_POST), 'INFO');

// 🚨 VALIDACIÓN ANTI-FRAUDE OPTIMIZADA
function detectarFraude() {
    // Test IPN oficial
    if (isset($_POST['test_ipn']) && $_POST['test_ipn'] == '1') {
        return "Test IPN oficial";
    }
    
    // User-Agent sospechoso
    if (isset($_SERVER['HTTP_USER_AGENT'])) {
        $ua = strtolower($_SERVER['HTTP_USER_AGENT']);
        $patterns = ['curl', 'postman', 'mmoweb', 'panel', 'test', 'sandbox'];
        foreach ($patterns as $p) {
            if (strpos($ua, $p) !== false) return "User-Agent: $p";
        }
    }
    
    // Headers/POST con MMOWeb
    $all_data = strtolower(json_encode(array_merge($_POST, getallheaders())));
    if (strpos($all_data, 'mmoweb') !== false) return "MMOWeb detectado";
    
    return false;
}

$fraud = detectarFraude();
if ($fraud) {
    // 📊 CAPTURAR TODOS LOS DATOS DEL ATACANTE
    $datos_atacante = capturarDatosAtacante();
    
    $msg = "FRAUDE DETECTADO: $fraud\nIP: " . $_SERVER['REMOTE_ADDR'] . "\nTXN: " . ($_POST['txn_id'] ?? 'N/A');
    saveLog("🚨 FRAUDE: $fraud", 1);
    notificarFraudeAdmin($msg, $datos_atacante);
    logToServer("🚨 FRAUDE: $fraud", 'FRAUD');
    exit;
}

// 🔐 VALIDACIÓN OFICIAL PAYPAL IPN - Verificar que el IPN realmente venga de PayPal
function validarIPNPayPal($post_data) {
    global $paypal_mode; // Usar modo desde configs.php
    
    if ($paypal_mode == 1) {
        $paypal_url = 'https://ipnpb.paypal.com/cgi-bin/webscr'; // Producción
        logToServer("Validando IPN con PayPal PRODUCCIÓN", 'INFO');
    } else {
        $paypal_url = 'https://ipnpb.sandbox.paypal.com/cgi-bin/webscr'; // Sandbox
        logToServer("Validando IPN con PayPal SANDBOX", 'INFO');
    }
    
    // Preparar datos para validación
    $req = 'cmd=_notify-validate';
    foreach ($post_data as $key => $value) {
        $value = urlencode(stripslashes($value));
        $req .= "&$key=$value";
    }
    
    logToServer("Datos de validación preparados para PayPal", 'INFO');
    
    // Configurar cURL
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $paypal_url);
    curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
    curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close'));
    curl_setopt($ch, CURLOPT_TIMEOUT, 30);
    curl_setopt($ch, CURLOPT_USERAGENT, 'L2OrdinaryWorld-IPN-Validator/1.0');
    
    // Ejecutar cURL
    $res = curl_exec($ch);
    $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $curl_error = curl_error($ch);
    curl_close($ch);
    
    if ($curl_error) {
        logToServer("ERROR cURL validando IPN: $curl_error", 'ERROR');
        return false;
    }
    
    if ($http_code != 200) {
        logToServer("ERROR HTTP validando IPN: Código $http_code", 'ERROR');
        return false;
    }
    
    // Verificar respuesta de PayPal
    if (strcmp($res, "VERIFIED") == 0) {
        logToServer("✅ IPN VERIFICADO por PayPal - Es LEGÍTIMO", 'INFO');
        return true;
    } elseif (strcmp($res, "INVALID") == 0) {
        logToServer("❌ IPN RECHAZADO por PayPal - Es FAKE", 'FRAUD');
        return false;
    } else {
        logToServer("ERROR: Respuesta inesperada de PayPal: $res", 'ERROR');
        return false;
    }
}

// 🚨 EJECUTAR VALIDACIÓN OFICIAL CON PAYPAL
if (!validarIPNPayPal($_POST)) {
    // 📊 CAPTURAR TODOS LOS DATOS DEL ATACANTE
    $datos_atacante = capturarDatosAtacante();
    
    $fraud_message = "FAKE IPN DETECTADO - NO VIENE DE PAYPAL!\n";
    $fraud_message .= "Transacción ID: " . ($_POST['txn_id'] ?? 'N/A') . "\n";
    $fraud_message .= "IP atacante: " . $_SERVER['REMOTE_ADDR'] . "\n";
    $fraud_message .= "Fecha: " . date('d/m/Y H:i:s') . "\n";
    $fraud_message .= "ESTE IPN NO PROVIENE DE PAYPAL - ES COMPLETAMENTE FALSO!";
    
    saveLog("🚨 FAKE IPN RECHAZADO - No verificado por PayPal!", 1);
    notificarFraudeAdmin($fraud_message, $datos_atacante);
    logToServer("🚨 FAKE IPN BLOQUEADO - TXN: " . ($_POST['txn_id'] ?? 'unknown'), 'FRAUD');
    exit;
}

// Verificación de parámetros POST
$required_params = ['txn_id', 'payment_status', 'mc_gross', 'mc_currency', 'item_number', 'payer_email'];
foreach ($required_params as $param) {
    if (empty($_POST[$param])) {
        saveLog("RAW POSTs incompletos! Falta: $param", 1);
        logToServer("ERROR: Falta parámetro requerido: $param", 'ERROR');
        exit;
    }
}
logToServer("Validación de parámetros POST: TODOS los parámetros requeridos presentes", 'INFO');

if (empty($_POST['receiver_email']) && empty($_POST['business'])) {
    saveLog("RAW POSTs incompletos! Falta receiver_email o business", 1);
    logToServer("ERROR: Falta receiver_email o business", 'ERROR');
    exit;
}
logToServer("Validación de receiver_email/business: OK", 'INFO');

// Validación de configuración PayPal
// Validar que el email receptor sea el correcto (tu cuenta PayPal)
$paypal_emails_validos = [
    $email_paypal,  // Email de PayPal desde configs.php
];

$receiver_email = !empty($_POST['receiver_email']) ? $_POST['receiver_email'] : $_POST['business'];
$email_valido = false;

foreach ($paypal_emails_validos as $email_valido_paypal) {
    if (strtolower($receiver_email) === strtolower($email_valido_paypal)) {
        $email_valido = true;
        break;
    }
}

if (!$email_valido) {
    $fraud_message = "EMAIL RECEPTOR INCORRECTO - POSIBLE FRAUDE!\n";
    $fraud_message .= "Email receptor recibido: $receiver_email\n";
    $fraud_message .= "Emails válidos: " . implode(', ', $paypal_emails_validos) . "\n";
    $fraud_message .= "Transacción ID: " . $_POST['txn_id'] . "\n";
    $fraud_message .= "Personaje: " . ($_POST['item_name'] ?? 'N/A') . "\n";
    $fraud_message .= "Email atacante: " . $_POST['payer_email'] . "\n";
    $fraud_message .= "IP atacante: " . $_SERVER['REMOTE_ADDR'] . "\n";
    $fraud_message .= "Fecha: " . date('d/m/Y H:i:s') . "\n";
    
    saveLog("🚨 EMAIL RECEPTOR INCORRECTO: $receiver_email", 1);
    notificarFraudeAdmin($fraud_message);
    logToServer("🚨 EMAIL RECEPTOR FALSO - Recibido: $receiver_email, TXN: " . $_POST['txn_id'], 'FRAUD');
    exit;
}

logToServer("Validación de email receptor: OK - $receiver_email", 'INFO');

// Validar moneda (debe ser USD)
if (strtoupper($_POST['mc_currency']) !== 'USD') {
    $fraud_message = "MONEDA INCORRECTA - POSIBLE FRAUDE!\n";
    $fraud_message .= "Moneda recibida: " . $_POST['mc_currency'] . "\n";
    $fraud_message .= "Moneda esperada: USD\n";
    $fraud_message .= "Transacción ID: " . $_POST['txn_id'] . "\n";
    $fraud_message .= "Personaje: " . ($_POST['item_name'] ?? 'N/A') . "\n";
    $fraud_message .= "Email atacante: " . $_POST['payer_email'] . "\n";
    $fraud_message .= "IP atacante: " . $_SERVER['REMOTE_ADDR'] . "\n";
    $fraud_message .= "Fecha: " . date('d/m/Y H:i:s') . "\n";
    
    saveLog("🚨 MONEDA INCORRECTA: " . $_POST['mc_currency'], 1);
    notificarFraudeAdmin($fraud_message);
    logToServer("🚨 MONEDA INCORRECTA - Recibida: " . $_POST['mc_currency'] . ", TXN: " . $_POST['txn_id'], 'FRAUD');
    exit;
}

logToServer("Validación de moneda: OK - USD", 'INFO');

// Sanitización de datos
$tid = vCode($_POST['txn_id']);
$status = strtolower(vCode($_POST['payment_status']));
$curr = vCode($_POST['mc_currency']);
$email = !empty($_POST['receiver_email']) ? vCode($_POST['receiver_email']) : '';
$email2 = !empty($_POST['business']) ? vCode($_POST['business']) : '';
$payer_email = vCode($_POST['payer_email']);
$price = floatval($_POST['mc_gross']);
$security_token = vCode($_POST['item_number']); // Ahora es el token de seguridad
$nombre_personaje = vCode($_POST['item_name']);

// Validar token de transacción usando la misma clave secreta
$secret_key = 'L2_SECRET_2024_' . md5($email_paypal); // Misma clave que don_save.php

// Primero verificar que el token existe como archivo
$txn_file = sys_get_temp_dir() . '/paypal_txn_' . $security_token . '.json';

if (!file_exists($txn_file)) {
    saveLog("Invalid token: Transaction file not found for token: " . substr($security_token, 0, 10) . "...", 1);
    logToServer("SECURITY ERROR - Invalid token or missing file: TXN $tid", 'FRAUD');
    exit;
}

// Leer datos de transacción
$original_data = json_decode(file_get_contents($txn_file), true);
if (!$original_data) {
    saveLog("Corrupted file: Cannot read transaction file: $txn_file", 1);
    logToServer("SECURITY ERROR - Corrupted transaction file: TXN $tid", 'FRAUD');
    exit;
}

// Verificar expiración (24 horas)
if ((time() - $original_data['timestamp']) > 86400) {
    unlink($txn_file);
    saveLog("Expired transaction: Token expired (>24h): " . substr($security_token, 0, 10) . "...", 1);
    logToServer("SECURITY ERROR - Expired transaction: TXN $tid", 'FRAUD');
    exit;
}

// Recuperar datos originales
$cantidad = intval($original_data['cantidad']);
$precio_original = floatval($original_data['precio']);
$personaje_original = $original_data['personaje'];
$ip_original = $original_data['ip'];
$timestamp_original = $original_data['timestamp'];

// Validación adicional: regenerar el token y comparar
$expected_token = hash_hmac('sha256', 
    $personaje_original . '|' . $cantidad . '|' . $precio_original . '|' . $timestamp_original . '|' . $ip_original, 
    $secret_key
);

if ($security_token !== $expected_token) {
    saveLog("Token forgery detected: Expected token mismatch", 1);
    logToServer("SECURITY ERROR - Token forgery detected: TXN $tid", 'FRAUD');
    exit;
}

// Verificar integridad de datos
if ($nombre_personaje !== $personaje_original || abs($price - $precio_original) > 0.01) {
    $fraud_message = "Data manipulation detected!\n";
    $fraud_message .= "TXN: $tid\n";
    $fraud_message .= "Original data: $personaje_original, $cantidad coins, $$precio_original USD\n";
    $fraud_message .= "Received data: $nombre_personaje, $$price USD\n";
    $fraud_message .= "Email: $payer_email\n";
    $fraud_message .= "IP: " . $_SERVER['REMOTE_ADDR'] . "\n";
    
    saveLog("Data mismatch: $personaje_original ($cantidad@$$precio_original) vs $nombre_personaje ($$price)", 1);
    logToServer("MANIPULATION DETECTED - TXN: $tid, Expected: $cantidad@$$precio_original, Got: $$price", 'FRAUD');
    notificarFraudeAdmin($fraud_message);
    
    exit;
}

// Transacción válida - limpiar archivo
unlink($txn_file);

logToServer("Datos validados - TXN: $tid, Status: $status, Precio: $$price, Cantidad: $cantidad, Personaje: $nombre_personaje, Email: $payer_email", 'INFO');

if (empty($nombre_personaje)) {
    saveLog("Nombre de personaje no especificado!", 1);
    logToServer("ERROR: Nombre de personaje vacío", 'ERROR');
    exit;
}

if ($cantidad <= 0) {
    saveLog("¡Error en la cantidad de coins! ($cantidad)", 1);
    logToServer("ERROR: Cantidad de coins inválida: $cantidad", 'ERROR');
    exit;
}

// ✅ Los datos ya fueron validados por el token de seguridad
logToServer("Transacción validada exitosamente - TXN: $tid, $cantidad coins por $$price USD", 'INFO');

// Determinación del estado final del pago
$finalStatus = in_array($status, ['canceled_reversal', 'completed', 'processed']) ? 3 : 1;

logToServer("Estado final determinado - Status PayPal: $status, Estado final: $finalStatus", 'INFO');

try {
    $pdo->beginTransaction();
    logToServer("Transacción de BD iniciada", 'INFO');

    // Verificar si el pago ya está almacenado
    $stmt = $pdo->prepare("SELECT * FROM items_pagos WHERE pay_id = ?");
    $stmt->execute([$tid]);
    if ($stmt->rowCount() > 0) {
        saveLog("Pago ya almacenado #$tid", 1);
        logToServer("ERROR: Pago duplicado detectado - TXN: $tid", 'ERROR');
        $pdo->rollBack();
        exit;
    }
    logToServer("Verificación de pago duplicado: OK - TXN no existe previamente", 'INFO');

    if ($finalStatus == 3) {
        logToServer("Procesando pago aprobado - TXN: $tid", 'INFO');
        
        // Obtener id del personaje
        $stmt = $pdo->prepare("SELECT obj_id FROM characters WHERE char_name = ?");
        $stmt->execute([$nombre_personaje]);
        $pers_row = $stmt->fetch(PDO::FETCH_ASSOC);
        if (!$pers_row) {
            saveLog("Error al obtener el id del personaje # $nombre_personaje", 1);
            logToServer("ERROR: Personaje no encontrado en BD: $nombre_personaje", 'ERROR');
            $pdo->rollBack();
            exit;
        }
        $pers_id = $pers_row['obj_id'];
        logToServer("Personaje encontrado en BD - ID: $pers_id, Nombre: $nombre_personaje", 'INFO');

        // Cálculo de bonus
        $num_bonus = 0;
        if ($cantidad <= 99) {
            $num_bonus = $cantidad * 0.10;
            $bonus_percent = '10%';
        } elseif ($cantidad <= 499) {
            $num_bonus = $cantidad * 0.15;
            $bonus_percent = '15%';
        } elseif ($cantidad <= 999) {
            $num_bonus = $cantidad * 0.20;
            $bonus_percent = '20%';
        } elseif ($cantidad <= 2999) {
            $num_bonus = $cantidad * 0.25;
            $bonus_percent = '25%';
        } elseif ($cantidad <= 7499) {
            $num_bonus = $cantidad * 0.30;
            $bonus_percent = '30%';
        } else {
            $num_bonus = $cantidad * 0.35;
            $bonus_percent = '35%';
        }
        
        $bonus_coins = intval($num_bonus);
        $cantidad_original = $cantidad;
        $cantidad += $bonus_coins;
        
        logToServer("Cálculo de bonus - Cantidad original: $cantidad_original, Bonus: $bonus_coins ($bonus_percent), Total final: $cantidad", 'INFO');

        // Insertar comprobante de pago
        $stmt = $pdo->prepare("INSERT INTO items_pagos (pay_id, estado_pago, metodo_pago, personaje, precio, cantidad, is_claimed) VALUES (?, 'approved', 'paypal', ?, ?, ?, 0)");
        $result = $stmt->execute([$tid, $nombre_personaje, $price, $cantidad]);
        
        if ($result) {
            logToServer("Registro insertado en BD - TXN: $tid, Personaje: $nombre_personaje, Precio: $$price, Cantidad final: $cantidad", 'INFO');
        } else {
            logToServer("ERROR: Falló inserción en BD - TXN: $tid", 'ERROR');
            throw new Exception("Error al insertar en BD");
        }

        // Verificar y actualizar items
        $stmt = $pdo->prepare("SELECT owner_id, count, item_id, loc FROM items WHERE owner_id = ? AND item_id = '9623'");
        $stmt->execute([$pers_id]);
        $items = $stmt->fetchAll(PDO::FETCH_ASSOC);

        if (count($items) > 1) {
            saveLog("Se detectaron items repetidos para el personaje $nombre_personaje", 1);
        }
        

        $pdo->commit();
        logToServer("Transacción de BD confirmada exitosamente", 'INFO');
        saveLog("Pago aprobado #$tid para el personaje $nombre_personaje", 2);

        // Notificar transacción exitosa
        $cantidad_original = $cantidad - $bonus_coins; // Cantidad sin bonus
        notificarTransaccionExitosa($tid, $nombre_personaje, $cantidad_original, $cantidad, $price, $payer_email);

        // Log al servidor web
        logToServer("TRANSACCIÓN EXITOSA - TXN: $tid, Personaje: $nombre_personaje, Pagado: $$price USD, Coins: $cantidad_original, Bonus: $bonus_coins, Total: $cantidad, Email: $payer_email", 'SUCCESS');
    } else {
        saveLog("Pago no realizado o transacción cancelada para #$tid", 1);
        logToServer("Pago cancelado/pendiente - TXN: $tid, Status: $status", 'INFO');
        $pdo->rollBack();
    }
} catch (PDOException $e) {
    $pdo->rollBack();
    saveLog("Error en la base de datos: " . $e->getMessage(), 1);
    logToServer("ERROR BD - TXN: $tid, Error: " . $e->getMessage(), 'ERROR');
} catch (Exception $e) {
    $pdo->rollBack();
    logToServer("ERROR GENERAL - TXN: $tid, Error: " . $e->getMessage(), 'ERROR');
}

logToServer("Script PayPal IPN finalizado - TXN: $tid", 'INFO');

// 📊 FUNCIÓN PARA CAPTURAR TODOS LOS DATOS DEL ATACANTE
function capturarDatosAtacante() {
    $datos_completos = [];
    
    // Capturar TODOS los datos POST
    $datos_completos['POST_DATA'] = $_POST;
    
    // Capturar TODOS los headers HTTP
    $datos_completos['HTTP_HEADERS'] = getallheaders();
    
    // Capturar TODAS las variables del servidor
    $datos_completos['SERVER_INFO'] = [
        'REMOTE_ADDR' => $_SERVER['REMOTE_ADDR'] ?? 'N/A',
        'HTTP_X_FORWARDED_FOR' => $_SERVER['HTTP_X_FORWARDED_FOR'] ?? 'N/A',
        'HTTP_X_REAL_IP' => $_SERVER['HTTP_X_REAL_IP'] ?? 'N/A',
        'REQUEST_METHOD' => $_SERVER['REQUEST_METHOD'] ?? 'N/A',
        'REQUEST_URI' => $_SERVER['REQUEST_URI'] ?? 'N/A',
        'HTTP_USER_AGENT' => $_SERVER['HTTP_USER_AGENT'] ?? 'N/A',
        'HTTP_REFERER' => $_SERVER['HTTP_REFERER'] ?? 'N/A',
        'REQUEST_TIME' => $_SERVER['REQUEST_TIME'] ?? 'N/A',
        'CONTENT_TYPE' => $_SERVER['CONTENT_TYPE'] ?? 'N/A',
        'CONTENT_LENGTH' => $_SERVER['CONTENT_LENGTH'] ?? 'N/A'
    ];
    
    // Capturar datos RAW del POST
    $datos_completos['RAW_POST'] = file_get_contents('php://input');
    
    // Capturar información de tiempo
    $datos_completos['TIMESTAMP_INFO'] = [
        'servidor_timestamp' => time(),
        'servidor_fecha' => date('Y-m-d H:i:s'),
        'timezone' => date_default_timezone_get()
    ];
    
    return $datos_completos;
}
?>