From c7d0b8b70cbe44c44b9755dd8eb74aabb04d7f40 Mon Sep 17 00:00:00 2001 From: lizandrogd <77708265+lizandrogd@users.noreply.github.com> Date: Wed, 21 Jan 2026 11:58:17 -0500 Subject: [PATCH] up --- api/get_media.php | 12 ++++- api/webhook.php | 28 ++++++++++- scripts/check_get_media.php | 11 ++++ scripts/check_user_messages_by_phone.php | 9 ++++ scripts/debug_process_message.php | 64 ++++++++++++++++++++++++ scripts/find_message_by_id.php | 7 +++ scripts/get_media_direct.php | 24 +++++++++ scripts/inspect_webhook.php | 9 ++++ scripts/replay_missing_messages.php | 35 +++++++++++++ scripts/replay_webhook_by_id.php | 41 +++++++++++++++ scripts/test_get_conversation_detail.php | 13 +++++ 11 files changed, 250 insertions(+), 3 deletions(-) create mode 100644 scripts/check_get_media.php create mode 100644 scripts/check_user_messages_by_phone.php create mode 100644 scripts/debug_process_message.php create mode 100644 scripts/find_message_by_id.php create mode 100644 scripts/get_media_direct.php create mode 100644 scripts/inspect_webhook.php create mode 100644 scripts/replay_missing_messages.php create mode 100644 scripts/replay_webhook_by_id.php create mode 100644 scripts/test_get_conversation_detail.php diff --git a/api/get_media.php b/api/get_media.php index 2041a49..64193ec 100644 --- a/api/get_media.php +++ b/api/get_media.php @@ -4,7 +4,17 @@ * Parámetros: id (media id) */ require_once '../config/config.php'; -requireAuthentication(); + +// Permitir que accesos directos desde navegador (GET sin Accept:application/json) redirijan al media sin requerir sesión. +$isGet = $_SERVER['REQUEST_METHOD'] === 'GET'; +$accept = $_SERVER['HTTP_ACCEPT'] ?? ''; +$wantsJson = strpos($accept, 'application/json') !== false; + +// Requerir autenticación sólo para peticiones que no sean GET puro o cuando se solicite JSON (AJAX/API) +if (!$isGet || $wantsJson) { + requireAuthentication(); +} + header('Content-Type: application/json; charset=utf-8'); $mediaId = $_GET['id'] ?? ($_POST['id'] ?? null); diff --git a/api/webhook.php b/api/webhook.php index 75007dc..46c1162 100644 --- a/api/webhook.php +++ b/api/webhook.php @@ -194,12 +194,18 @@ class WhatsAppWebhook { 'message_type' => $messageType, 'content' => $messageText, 'media_url' => $mediaUrl, - 'filename' => isset($filename) ? $filename : null, - 'mime_type' => isset($mimeType) ? $mimeType : null, 'status' => 'received', 'is_read' => 0 ]; + // Añadir campos opcionales solo si existen para evitar errores en esquemas antiguos + if (isset($filename) && $filename !== null) { + $saveData['filename'] = $filename; + } + if (isset($mimeType) && $mimeType !== null) { + $saveData['mime_type'] = $mimeType; + } + // Si el mensaje incluye contexto (es respuesta a otro mensaje) if (isset($message['context']) && isset($message['context']['id'])) { $saveData['reply_to_message_id'] = $message['context']['id']; @@ -210,6 +216,8 @@ class WhatsAppWebhook { $saveData = array_merge($saveData, $extraFields); } + // Filtrar campos según columnas existentes para evitar errores en esquemas antiguos + $saveData = $this->filterColumns('conversations', $saveData); $this->saveMessage($saveData); // Crear notificación para UI (nuevo mensaje entrante) @@ -290,6 +298,22 @@ class WhatsAppWebhook { private function saveMessage($messageData) { return $this->db->insert('conversations', $messageData); } + + /** + * Filtrar los datos para dejar solo las columnas que existen en la tabla + * Evita errores cuando la BD está en un esquema más antiguo + */ + private function filterColumns($table, array $data) { + static $columnsCache = []; + if (!isset($columnsCache[$table])) { + $cols = $this->db->fetchAll("SHOW COLUMNS FROM {$table}"); + $columnsCache[$table] = array_map(function($c){ return $c['Field']; }, $cols); + } + $allowed = $columnsCache[$table]; + return array_filter($data, function($v, $k) use ($allowed) { + return in_array($k, $allowed, true); + }, ARRAY_FILTER_USE_BOTH); + } private function logWebhook($requestBody, $responseBody, $statusCode) { if (ENABLE_LOGGING) { diff --git a/scripts/check_get_media.php b/scripts/check_get_media.php new file mode 100644 index 0000000..9c3af37 --- /dev/null +++ b/scripts/check_get_media.php @@ -0,0 +1,11 @@ + ['method' => 'GET', 'header' => "Accept: application/json\r\n"]]; +$ctx = stream_context_create($opts); +$url = "http://localhost/whatsapp/api/get_media.php?id=" . urlencode($mediaId); +$s = @file_get_contents($url, false, $ctx); +if ($s === false) { + echo "Request failed\n"; + exit(1); +} +echo $s . "\n"; diff --git a/scripts/check_user_messages_by_phone.php b/scripts/check_user_messages_by_phone.php new file mode 100644 index 0000000..140e1d2 --- /dev/null +++ b/scripts/check_user_messages_by_phone.php @@ -0,0 +1,9 @@ +fetch('SELECT * FROM users WHERE phone_number = ?', [$phone]); +if (!$user) { echo "User not found for phone $phone\n"; exit; } +$rows = $db->fetchAll('SELECT * FROM conversations WHERE user_id = ? ORDER BY created_at DESC LIMIT 10', [$user['id']]); +echo "User id: " . $user['id'] . "\n"; +echo json_encode($rows, JSON_PRETTY_PRINT) . "\n"; \ No newline at end of file diff --git a/scripts/debug_process_message.php b/scripts/debug_process_message.php new file mode 100644 index 0000000..41f5582 --- /dev/null +++ b/scripts/debug_process_message.php @@ -0,0 +1,64 @@ +\n"; exit; } +$db = Database::getInstance(); +$row = $db->fetch('SELECT request_body FROM webhook_logs WHERE id = ?', [$id]); +if (!$row) { echo "Log not found\n"; exit; } +$data = json_decode($row['request_body'], true); +$messages = $data['entry'][0]['changes'][0]['value']['messages'] ?? null; +if (!$messages) { echo "No messages in log\n"; exit; } +foreach ($messages as $message) { + echo "--- Message ---\n"; + print_r($message); + $phoneNumber = $message['from'] ?? ($message['wa_id'] ?? null); + $messageId = $message['id'] ?? ($message['message_id'] ?? null); + $timestamp = $message['timestamp'] ?? null; + echo "phone=$phoneNumber messageId=$messageId ts=$timestamp\n"; + + if (empty($phoneNumber) || empty($messageId)) { echo "Missing phone or msg id\n"; continue; } + + $existing = $db->fetch('SELECT id FROM conversations WHERE message_id = ?', [$messageId]); + echo "existing: "; var_export((bool)$existing); echo "\n"; + + $user = $db->fetch('SELECT * FROM users WHERE phone_number = ?', [$phoneNumber]); + if (!$user) { echo "User not found, creating...\n"; $id = $db->insert('users', ['phone_number' => $phoneNumber, 'status' => 'active', 'created_at' => date('Y-m-d H:i:s')]); $user = $db->fetch('SELECT * FROM users WHERE id = ?', [$id]); } + echo "user id: " . $user['id'] . "\n"; + + $messageText = ''; + $messageType = 'text'; + $mediaUrl = null; $mimeType = null; $filename = null; + if (isset($message['text']) || (($message['type'] ?? '') === 'text')) { + $messageText = isset($message['text']['body']) ? $message['text']['body'] : ($message['body'] ?? ''); + $messageType = 'text'; + } elseif (isset($message['image'])) { + $messageText = $message['image']['caption'] ?? ''; + $messageType = 'image'; + $mediaUrl = $message['image']['url'] ?? ($message['image']['id'] ?? null); + $mimeType = $message['image']['mime_type'] ?? null; + $filename = $message['image']['filename'] ?? null; + } + echo "type=$messageType text=" . substr($messageText,0,100) . " mediaUrl=" . ($mediaUrl ?? 'NULL') . "\n"; + + $saveData = [ + 'user_id' => $user['id'], + 'message_id' => $messageId, + 'direction' => 'incoming', + 'message_type' => $messageType, + 'content' => $messageText, + 'media_url' => $mediaUrl, + 'filename' => $filename, + 'mime_type' => $mimeType, + 'status' => 'received', + 'is_read' => 0, + 'created_at' => date('Y-m-d H:i:s') + ]; + + try { + $res = $db->insert('conversations', $saveData); + echo "Insert returned: "; var_export($res); echo "\n"; + } catch (Exception $e) { + echo "Insert failed: " . $e->getMessage() . "\n"; + } +} diff --git a/scripts/find_message_by_id.php b/scripts/find_message_by_id.php new file mode 100644 index 0000000..b28e773 --- /dev/null +++ b/scripts/find_message_by_id.php @@ -0,0 +1,7 @@ +\n"; exit; } +$db = Database::getInstance(); +$res = $db->fetch('SELECT * FROM conversations WHERE message_id = ?', [$message_id]); +if ($res) echo json_encode($res, JSON_PRETTY_PRINT) . "\n"; else echo "Not found\n"; diff --git a/scripts/get_media_direct.php b/scripts/get_media_direct.php new file mode 100644 index 0000000..9c62661 --- /dev/null +++ b/scripts/get_media_direct.php @@ -0,0 +1,24 @@ +\n"; exit(1); } +$token = getConfigFromDB('whatsapp_token', ''); +$apiUrl = rtrim(getConfigFromDB('whatsapp_api_url', 'https://graph.facebook.com/v22.0/'), '/'); +$url = "{$apiUrl}/{$mediaId}"; +echo "Calling: $url\n"; +$ch = curl_init(); +curl_setopt_array($ch, [ + CURLOPT_URL => $url, + CURLOPT_RETURNTRANSFER => true, + CURLOPT_HTTPHEADER => [ 'Authorization: Bearer ' . $token ], + CURLOPT_TIMEOUT => 10, +]); +$response = curl_exec($ch); +$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); +$err = curl_error($ch); +curl_close($ch); +if ($err) { + echo "CURL ERR: $err\n"; exit(1); +} +echo "HTTP Code: $httpCode\n"; +echo "$response\n"; diff --git a/scripts/inspect_webhook.php b/scripts/inspect_webhook.php new file mode 100644 index 0000000..eee1c74 --- /dev/null +++ b/scripts/inspect_webhook.php @@ -0,0 +1,9 @@ +\n"; exit; } +$db = Database::getInstance(); +$row = $db->fetch('SELECT request_body FROM webhook_logs WHERE id = ?', [$id]); +if (!$row) { echo "Log not found\n"; exit; } +$data = json_decode($row['request_body'], true); +print_r($data); diff --git a/scripts/replay_missing_messages.php b/scripts/replay_missing_messages.php new file mode 100644 index 0000000..46224c7 --- /dev/null +++ b/scripts/replay_missing_messages.php @@ -0,0 +1,35 @@ +fetchAll('SELECT id, request_body FROM webhook_logs WHERE created_at >= ? ORDER BY id ASC', [$cutoff]); +$webhook = new WhatsAppWebhook(); +$replayed = 0; +foreach ($rows as $row) { + $data = json_decode($row['request_body'], true); + if (empty($data) || !isset($data['entry'])) continue; + $needReplay = false; + foreach ($data['entry'] as $entry) { + foreach ($entry['changes'] as $change) { + $value = $change['value'] ?? []; + $messages = $value['messages'] ?? []; + foreach ($messages as $m) { + $mid = $m['id'] ?? null; + if ($mid && !$db->fetch('SELECT id FROM conversations WHERE message_id = ?', [$mid])) { + $needReplay = true; break 3; + } + } + } + } + if ($needReplay) { + echo "Replaying webhook_log id={$row['id']}\n"; + $ok = $webhook->processPayload($data); + echo " -> processPayload returned: " . ($ok ? 'true' : 'false') . "\n"; + $replayed++; + } +} + +echo "Completed. Replayed $replayed logs.\n"; diff --git a/scripts/replay_webhook_by_id.php b/scripts/replay_webhook_by_id.php new file mode 100644 index 0000000..624731a --- /dev/null +++ b/scripts/replay_webhook_by_id.php @@ -0,0 +1,41 @@ +\n"; + exit; +} +$db = Database::getInstance(); +$row = $db->fetch('SELECT request_body FROM webhook_logs WHERE id = ?', [$id]); +if (!$row) { echo "Log id $id not found\n"; exit; } + +$data = json_decode($row['request_body'], true); +if (!$data) { echo "Invalid JSON in log id $id\n"; exit; } + +$webhook = new WhatsAppWebhook(); +$ok = $webhook->processPayload($data); +echo "processPayload returned: " . ($ok ? 'true' : 'false') . "\n"; + +// Try to show messages for the involved phone numbers +$phones = []; +foreach ($data['entry'] as $entry) { + foreach ($entry['changes'] as $change) { + $val = $change['value'] ?? []; + if (isset($val['contacts'])) { + foreach ($val['contacts'] as $c) if (isset($c['wa_id'])) $phones[] = $c['wa_id']; + } + if (isset($val['messages'])) { + foreach ($val['messages'] as $m) if (isset($m['from'])) $phones[] = $m['from']; + } + } +} +$phones = array_unique($phones); +foreach ($phones as $p) { + $user = $db->fetch('SELECT * FROM users WHERE phone_number = ?', [$p]); + echo "Phone: $p\n"; + if (!$user) { echo " No user found\n"; continue; } + $msgs = $db->fetchAll('SELECT id,message_id,message_type,content,media_url,created_at FROM conversations WHERE user_id = ? ORDER BY created_at DESC LIMIT 5', [$user['id']]); + echo json_encode($msgs, JSON_PRETTY_PRINT) . "\n"; +} diff --git a/scripts/test_get_conversation_detail.php b/scripts/test_get_conversation_detail.php new file mode 100644 index 0000000..6b66402 --- /dev/null +++ b/scripts/test_get_conversation_detail.php @@ -0,0 +1,13 @@ +getMessage(); +} +$out = ob_get_clean(); +echo $out;