Files
whatsapp/test_webhook.php
T
2026-01-13 00:31:22 -05:00

367 lines
16 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/**
* Test de Webhook - Diagnóstico completo
* Fecha: 13 de enero de 2026
*/
require_once 'config/config.php';
// Verificar autenticación
if (!isUserLoggedIn()) {
header('Location: login.php');
exit;
}
header('Content-Type: text/html; charset=utf-8');
?>
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Diagnóstico de Webhook - WhatsApp Bot</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
body { background: #f8f9fa; padding: 20px; }
.test-card { background: white; border-radius: 10px; padding: 20px; margin-bottom: 20px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
.ok { color: #28a745; font-weight: bold; }
.error { color: #dc3545; font-weight: bold; }
.warning { color: #ffc107; font-weight: bold; }
.info { color: #17a2b8; font-weight: bold; }
.code-box { background: #f8f9fa; border: 1px solid #dee2e6; border-radius: 5px; padding: 15px; margin: 10px 0; font-family: 'Courier New', monospace; font-size: 12px; }
.badge-status { font-size: 14px; padding: 8px 15px; }
</style>
</head>
<body>
<div class="container">
<div class="test-card">
<h1 class="mb-4">
<i class="fas fa-plug"></i> Diagnóstico de Webhook WhatsApp
</h1>
<p class="text-muted">Verificación completa del estado del webhook y configuración</p>
</div>
<?php
$db = Database::getInstance();
$allOk = true;
// Test 1: Verificar configuración
echo "<div class='test-card'>";
echo "<h3><i class='fas fa-cog'></i> 1. Configuración del Sistema</h3>";
$config = [
'WHATSAPP_TOKEN' => defined('WHATSAPP_TOKEN') ? WHATSAPP_TOKEN : null,
'WHATSAPP_PHONE_NUMBER_ID' => defined('WHATSAPP_PHONE_NUMBER_ID') ? WHATSAPP_PHONE_NUMBER_ID : null,
'WEBHOOK_VERIFY_TOKEN' => defined('WEBHOOK_VERIFY_TOKEN') ? WEBHOOK_VERIFY_TOKEN : null,
'WHATSAPP_API_URL' => defined('WHATSAPP_API_URL') ? WHATSAPP_API_URL : null,
];
echo "<table class='table table-sm'>";
foreach ($config as $key => $value) {
$status = !empty($value) ? 'ok' : 'error';
$icon = !empty($value) ? '✅' : '❌';
$displayValue = !empty($value) ? (strlen($value) > 30 ? substr($value, 0, 30) . '...' : $value) : 'NO CONFIGURADO';
if ($status === 'error') $allOk = false;
echo "<tr>";
echo "<td class='$status'>$icon $key</td>";
echo "<td><code>$displayValue</code></td>";
echo "</tr>";
}
echo "</table>";
echo "</div>";
// Test 2: URL del Webhook
echo "<div class='test-card'>";
echo "<h3><i class='fas fa-link'></i> 2. URL del Webhook</h3>";
$protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http';
$host = $_SERVER['HTTP_HOST'];
$webhookUrl = $protocol . '://' . $host . '/api/webhook.php';
echo "<div class='alert alert-info'>";
echo "<strong>URL para configurar en Meta/Facebook:</strong><br>";
echo "<code style='font-size: 14px;'>$webhookUrl</code>";
echo "<button class='btn btn-sm btn-outline-primary ms-2' onclick='navigator.clipboard.writeText(\"$webhookUrl\")'>
<i class='fas fa-copy'></i> Copiar
</button>";
echo "</div>";
// Verificar si el archivo existe
$webhookFile = __DIR__ . '/api/webhook.php';
if (file_exists($webhookFile)) {
echo "<p class='ok'>✅ Archivo webhook.php existe</p>";
} else {
echo "<p class='error'>❌ Archivo webhook.php NO encontrado</p>";
$allOk = false;
}
echo "</div>";
// Test 3: Verificación GET
echo "<div class='test-card'>";
echo "<h3><i class='fas fa-check-circle'></i> 3. Test de Verificación (GET)</h3>";
$verifyUrl = $webhookUrl . '?hub.mode=subscribe&hub.verify_token=' . urlencode(WEBHOOK_VERIFY_TOKEN) . '&hub.challenge=test_challenge_12345';
echo "<p><strong>URL de prueba:</strong></p>";
echo "<div class='code-box'>" . htmlspecialchars($verifyUrl) . "</div>";
echo "<div class='alert alert-info'>";
echo "<strong>💡 Nota:</strong> Este test intenta verificar el webhook desde el servidor mismo. ";
echo "Si estás en localhost, es normal que falle. Lo importante es que el archivo exista y esté configurado correctamente.";
echo "</div>";
// Intentar hacer la verificación solo si no es localhost
$isLocalhost = (strpos($host, 'localhost') !== false || strpos($host, '127.0.0.1') !== false);
if (!$isLocalhost) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $verifyUrl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
if ($httpCode == 200 && $response === 'test_challenge_12345') {
echo "<p class='ok'>✅ Verificación GET exitosa - El webhook responde correctamente</p>";
echo "<p>Respuesta: <code>$response</code></p>";
} else {
echo "<p class='error'>❌ Error en verificación GET</p>";
echo "<p>Código HTTP: <code>$httpCode</code></p>";
echo "<p>Respuesta: <code>" . htmlspecialchars($response) . "</code></p>";
if ($error) echo "<p>Error cURL: <code>$error</code></p>";
$allOk = false;
}
} else {
// Test manual para localhost
echo "<div class='alert alert-warning'>";
echo "<strong>⚠️ Entorno Local Detectado</strong><br>";
echo "No se puede hacer la verificación automática en localhost. ";
echo "En su lugar, puedes probar manualmente:";
echo "</div>";
echo "<ol>";
echo "<li>Haz clic en el botón de abajo para probar el webhook</li>";
echo "<li>Deberías ver el texto: <code>test_challenge_12345</code></li>";
echo "</ol>";
echo "<a href='$verifyUrl' target='_blank' class='btn btn-primary mb-3'>";
echo "<i class='fas fa-external-link-alt'></i> Probar Webhook Manualmente";
echo "</a>";
// Verificar el archivo directamente
$webhookFilePath = __DIR__ . '/api/webhook.php';
if (file_exists($webhookFilePath)) {
echo "<p class='ok'>✅ El archivo webhook.php existe y es accesible</p>";
// Verificar permisos de lectura
if (is_readable($webhookFilePath)) {
echo "<p class='ok'>✅ El archivo tiene permisos de lectura</p>";
// Verificar que contenga el código necesario
$webhookContent = file_get_contents($webhookFilePath);
if (strpos($webhookContent, 'hub_verify_token') !== false &&
strpos($webhookContent, 'hub_challenge') !== false) {
echo "<p class='ok'>✅ El archivo contiene el código de verificación correcto</p>";
} else {
echo "<p class='warning'>⚠️ El archivo puede no contener el código de verificación</p>";
}
} else {
echo "<p class='error'>❌ El archivo no tiene permisos de lectura</p>";
$allOk = false;
}
}
}
echo "</div>";
// Test 4: Estructura de tablas
echo "<div class='test-card'>";
echo "<h3><i class='fas fa-database'></i> 4. Estructura de Base de Datos</h3>";
$requiredTables = ['users', 'conversations', 'menus', 'menu_options', 'autoresponses', 'webhook_logs'];
echo "<table class='table table-sm'>";
foreach ($requiredTables as $table) {
$exists = $db->fetchAll("SHOW TABLES LIKE '$table'");
$status = !empty($exists) ? 'ok' : 'error';
$icon = !empty($exists) ? '✅' : '❌';
if ($status === 'error') $allOk = false;
echo "<tr>";
echo "<td class='$status'>$icon Tabla: <strong>$table</strong></td>";
if (!empty($exists)) {
// Contar registros
$count = $db->fetch("SELECT COUNT(*) as total FROM $table");
echo "<td><span class='badge bg-info'>{$count['total']} registros</span></td>";
} else {
echo "<td><span class='badge bg-danger'>NO EXISTE</span></td>";
}
echo "</tr>";
}
echo "</table>";
echo "</div>";
// Test 5: Últimos mensajes recibidos
echo "<div class='test-card'>";
echo "<h3><i class='fas fa-inbox'></i> 5. Mensajes Recibidos Recientemente</h3>";
$recentMessages = $db->fetchAll(
"SELECT c.*, u.phone_number, u.name
FROM conversations c
LEFT JOIN users u ON c.user_id = u.id
WHERE c.direction = 'incoming'
ORDER BY c.created_at DESC
LIMIT 5"
);
if (!empty($recentMessages)) {
echo "<p class='ok'>✅ Se encontraron mensajes entrantes</p>";
echo "<table class='table table-sm table-striped'>";
echo "<thead><tr><th>Fecha</th><th>Usuario</th><th>Mensaje</th><th>Estado</th></tr></thead>";
echo "<tbody>";
foreach ($recentMessages as $msg) {
$date = date('d/m/Y H:i', strtotime($msg['created_at']));
$phone = $msg['phone_number'] ?? 'Desconocido';
$content = htmlspecialchars(substr($msg['content'], 0, 50));
$status = $msg['status'];
echo "<tr>";
echo "<td>$date</td>";
echo "<td>$phone</td>";
echo "<td>$content</td>";
echo "<td><span class='badge bg-success'>$status</span></td>";
echo "</tr>";
}
echo "</tbody></table>";
} else {
echo "<p class='warning'>⚠️ No se encontraron mensajes entrantes. El webhook puede no estar recibiendo datos.</p>";
echo "<div class='alert alert-warning'>";
echo "<strong>Posibles causas:</strong><ul>";
echo "<li>El webhook no está configurado en Meta/Facebook</li>";
echo "<li>La URL del webhook es incorrecta</li>";
echo "<li>El servidor no es accesible desde Internet</li>";
echo "<li>Aún no se han enviado mensajes de prueba</li>";
echo "</ul></div>";
}
echo "</div>";
// Test 6: Webhook Logs
echo "<div class='test-card'>";
echo "<h3><i class='fas fa-file-alt'></i> 6. Logs del Webhook</h3>";
$webhookLogs = $db->fetchAll(
"SELECT * FROM webhook_logs
ORDER BY created_at DESC
LIMIT 5"
);
if (!empty($webhookLogs)) {
echo "<p class='ok'>✅ Se encontraron logs del webhook</p>";
echo "<table class='table table-sm'>";
echo "<thead><tr><th>Fecha</th><th>Status</th><th>IP</th><th>Detalles</th></tr></thead>";
echo "<tbody>";
foreach ($webhookLogs as $log) {
$date = date('d/m/Y H:i:s', strtotime($log['created_at']));
$status = $log['status_code'];
$ip = $log['ip_address'];
$statusClass = $status == 200 ? 'success' : 'danger';
echo "<tr>";
echo "<td>$date</td>";
echo "<td><span class='badge bg-$statusClass'>$status</span></td>";
echo "<td>$ip</td>";
echo "<td><button class='btn btn-sm btn-outline-info' onclick='alert(\"Request: " . addslashes(substr($log['request_body'], 0, 200)) . "\")'>Ver</button></td>";
echo "</tr>";
}
echo "</tbody></table>";
} else {
echo "<p class='info'>️ No hay logs del webhook registrados</p>";
}
echo "</div>";
// Test 7: Configuración de Menús y Respuestas
echo "<div class='test-card'>";
echo "<h3><i class='fas fa-robot'></i> 7. Configuración del Bot</h3>";
$menuCount = $db->fetch("SELECT COUNT(*) as total FROM menus WHERE is_active = 1");
$optionCount = $db->fetch("SELECT COUNT(*) as total FROM menu_options WHERE is_active = 1");
$autoResponseCount = $db->fetch("SELECT COUNT(*) as total FROM autoresponses WHERE is_active = 1");
echo "<div class='row'>";
echo "<div class='col-md-4'>";
echo "<div class='alert alert-info text-center'>";
echo "<h4>{$menuCount['total']}</h4>";
echo "<p>Menús Activos</p>";
echo "</div>";
echo "</div>";
echo "<div class='col-md-4'>";
echo "<div class='alert alert-info text-center'>";
echo "<h4>{$optionCount['total']}</h4>";
echo "<p>Opciones de Menú</p>";
echo "</div>";
echo "</div>";
echo "<div class='col-md-4'>";
echo "<div class='alert alert-info text-center'>";
echo "<h4>{$autoResponseCount['total']}</h4>";
echo "<p>Respuestas Automáticas</p>";
echo "</div>";
echo "</div>";
echo "</div>";
echo "</div>";
// Resumen final
echo "<div class='test-card'>";
if ($allOk) {
echo "<div class='alert alert-success'>";
echo "<h4><i class='fas fa-check-circle'></i> ¡Sistema Configurado Correctamente!</h4>";
echo "<p>El webhook está listo para recibir mensajes de WhatsApp.</p>";
echo "</div>";
} else {
echo "<div class='alert alert-danger'>";
echo "<h4><i class='fas fa-exclamation-triangle'></i> Se encontraron problemas</h4>";
echo "<p>Revisa los errores anteriores y corrígelos antes de continuar.</p>";
echo "</div>";
}
echo "<div class='mt-3'>";
echo "<h5>Próximos pasos:</h5>";
echo "<ol>";
echo "<li>Copia la URL del webhook y configúrala en Meta Developer Console</li>";
echo "<li>Usa el token de verificación: <code>" . WEBHOOK_VERIFY_TOKEN . "</code></li>";
echo "<li>Envía un mensaje de prueba desde WhatsApp</li>";
echo "<li>Verifica que aparezca en la sección de mensajes recibidos</li>";
echo "</ol>";
echo "</div>";
echo "</div>";
?>
<div class="text-center mt-4">
<a href="index.php" class="btn btn-primary">
<i class="fas fa-home"></i> Volver al Dashboard
</a>
<button onclick="location.reload()" class="btn btn-secondary">
<i class="fas fa-sync"></i> Recargar Test
</button>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>