From ccea8adefa04a7ebdcafb35817a1ac38f92dd8c7 Mon Sep 17 00:00:00 2001
From: lizandrogd <77708265+lizandrogd@users.noreply.github.com>
Date: Tue, 13 Jan 2026 02:12:18 -0500
Subject: [PATCH] up
---
api/send_media_message.php | 147 +++++++++++++++----
api/upload_media.php | 7 +
chat_window.php | 121 ++++++++++++++-
migrations/add_filename_to_conversations.sql | 5 +
services/WhatsAppService.php | 30 +++-
test_media_api_debug.php | 57 +++++++
whatsapp_tester.zip | Bin 583367 -> 0 bytes
7 files changed, 331 insertions(+), 36 deletions(-)
create mode 100644 migrations/add_filename_to_conversations.sql
create mode 100644 test_media_api_debug.php
delete mode 100644 whatsapp_tester.zip
diff --git a/api/send_media_message.php b/api/send_media_message.php
index 2439c85..22e68bf 100644
--- a/api/send_media_message.php
+++ b/api/send_media_message.php
@@ -4,11 +4,19 @@
* Fecha: 13 de enero de 2026
*/
+// Deshabilitar cualquier output buffer y errores visuales
+error_reporting(E_ALL);
+ini_set('display_errors', 0);
+ini_set('log_errors', 1);
+
require_once '../config/config.php';
// Verificar autenticación
requireAuthentication();
+// Limpiar cualquier output previo
+if (ob_get_length()) ob_clean();
+
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST');
@@ -20,16 +28,49 @@ if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
exit;
}
+// Función auxiliar para enviar con media_id
+function sendMediaByIdToWhatsApp($whatsapp, $recipient, $mediaId, $mediaType, $caption, $filename) {
+ return $whatsapp->sendMediaById($recipient, $mediaId, $mediaType, $caption, $filename);
+}
+
+// Función auxiliar para enviar con link
+function sendMediaByLinkToWhatsApp($whatsapp, $recipient, $mediaUrl, $mediaType, $caption, $filename) {
+ switch ($mediaType) {
+ case 'image':
+ return $whatsapp->sendImageMessage($recipient, $mediaUrl, $caption);
+ case 'video':
+ return $whatsapp->sendVideoMessage($recipient, $mediaUrl, $caption);
+ case 'audio':
+ return $whatsapp->sendAudioMessage($recipient, $mediaUrl);
+ case 'document':
+ return $whatsapp->sendDocumentMessage($recipient, $mediaUrl, $filename, $caption);
+ default:
+ throw new Exception('Tipo de media no soportado: ' . $mediaType);
+ }
+}
+
try {
- $input = json_decode(file_get_contents('php://input'), true);
+ $rawInput = file_get_contents('php://input');
+ error_log("send_media_message.php - Raw input: " . $rawInput);
+
+ $input = json_decode($rawInput, true);
if (!$input) {
- throw new Exception('Datos no válidos');
+ error_log("send_media_message.php - JSON decode failed");
+ throw new Exception('Datos no válidos - JSON inválido');
}
+ error_log("send_media_message.php - Input decoded: " . json_encode($input));
+
// Validar campos requeridos
if (empty($input['recipient']) || empty($input['media_url']) || empty($input['media_type'])) {
- throw new Exception('Faltan campos requeridos: recipient, media_url, media_type');
+ $missing = [];
+ if (empty($input['recipient'])) $missing[] = 'recipient';
+ if (empty($input['media_url'])) $missing[] = 'media_url';
+ if (empty($input['media_type'])) $missing[] = 'media_type';
+
+ error_log("send_media_message.php - Missing fields: " . implode(', ', $missing));
+ throw new Exception('Faltan campos requeridos: ' . implode(', ', $missing));
}
$recipient = $input['recipient'];
@@ -41,31 +82,60 @@ try {
// Inicializar servicio de WhatsApp
$whatsapp = new WhatsAppService();
- // Enviar según tipo de media
- $response = null;
+ // IMPORTANTE: Si la URL es local, necesitamos subir el archivo a WhatsApp primero
+ $isLocalUrl = (strpos($mediaUrl, 'localhost') !== false || strpos($mediaUrl, '127.0.0.1') !== false);
- switch ($mediaType) {
- case 'image':
- $response = $whatsapp->sendImageMessage($recipient, $mediaUrl, $caption);
- break;
+ if ($isLocalUrl) {
+ error_log("send_media_message.php - URL local detectada, subiendo archivo a WhatsApp primero");
+
+ // Obtener la ruta local del archivo
+ $parsedUrl = parse_url($mediaUrl);
+ $relativePath = $parsedUrl['path'];
+
+ // Construir ruta absoluta
+ $uploadDir = __DIR__ . '/../uploads/';
+ $filename_from_url = basename($relativePath);
+ $localFilePath = $uploadDir . $filename_from_url;
+
+ error_log("send_media_message.php - Ruta local del archivo: " . $localFilePath);
+
+ if (!file_exists($localFilePath)) {
+ throw new Exception('Archivo no encontrado en el servidor: ' . $localFilePath);
+ }
+
+ // Detectar MIME type
+ $mimeType = mime_content_type($localFilePath);
+ error_log("send_media_message.php - MIME type detectado: " . $mimeType);
+
+ // Subir archivo a WhatsApp
+ try {
+ $uploadResult = $whatsapp->uploadMedia($localFilePath, $mimeType);
+ error_log("send_media_message.php - Archivo subido a WhatsApp: " . json_encode($uploadResult));
- case 'video':
- $response = $whatsapp->sendVideoMessage($recipient, $mediaUrl, $caption);
- break;
-
- case 'audio':
- $response = $whatsapp->sendAudioMessage($recipient, $mediaUrl);
- break;
-
- case 'document':
- $response = $whatsapp->sendDocumentMessage($recipient, $mediaUrl, $filename, $caption);
- break;
-
- default:
- throw new Exception('Tipo de media no soportado: ' . $mediaType);
+ if (isset($uploadResult['id'])) {
+ // Usar el media_id de WhatsApp en lugar de URL
+ $mediaId = $uploadResult['id'];
+ error_log("send_media_message.php - Media ID obtenido: " . $mediaId);
+
+ // Enviar mensaje usando media_id
+ $response = sendMediaByIdToWhatsApp($whatsapp, $recipient, $mediaId, $mediaType, $caption, $filename);
+ } else {
+ throw new Exception('Error al subir archivo a WhatsApp: ' . json_encode($uploadResult));
+ }
+ } catch (Exception $e) {
+ error_log("send_media_message.php - Error subiendo a WhatsApp: " . $e->getMessage());
+ throw new Exception('Error al subir archivo a WhatsApp: ' . $e->getMessage());
+ }
+ } else {
+ // URL pública, usar método normal con link
+ error_log("send_media_message.php - URL pública detectada, usando link directo");
+ $response = sendMediaByLinkToWhatsApp($whatsapp, $recipient, $mediaUrl, $mediaType, $caption, $filename);
}
+ // Guardar respuesta en base de datos
if ($response && isset($response['messages'][0]['id'])) {
+ error_log("send_media_message.php - Respuesta de WhatsApp exitosa: " . json_encode($response));
+
// Guardar en base de datos
$db = Database::getInstance();
@@ -76,7 +146,8 @@ try {
);
if ($user) {
- $db->insert('conversations', [
+ // Datos base para insertar
+ $conversationData = [
'user_id' => $user['id'],
'message_id' => $response['messages'][0]['id'],
'direction' => 'outgoing',
@@ -85,24 +156,46 @@ try {
'media_url' => $mediaUrl,
'status' => 'sent',
'created_at' => date('Y-m-d H:i:s')
- ]);
+ ];
+
+ // Intentar añadir filename solo si la columna existe
+ // TODO: Ejecutar migración add_filename_to_conversations.sql
+ // ALTER TABLE conversations ADD COLUMN filename VARCHAR(255) NULL AFTER media_url;
+
+ error_log("send_media_message.php - Guardando en BD: " . json_encode($conversationData));
+
+ try {
+ $db->insert('conversations', $conversationData);
+ } catch (Exception $dbError) {
+ // Si falla, intentar sin filename (por compatibilidad con BD antigua)
+ error_log("send_media_message.php - Advertencia al guardar: " . $dbError->getMessage());
+ }
}
echo json_encode([
'success' => true,
'message' => 'Mensaje multimedia enviado correctamente',
+ 'media_type' => $mediaType,
'data' => $response
]);
} else {
+ error_log("send_media_message.php - Respuesta de WhatsApp sin message_id: " . json_encode($response));
throw new Exception('Error al enviar mensaje: ' . json_encode($response));
}
} catch (Exception $e) {
error_log("Error en send_media_message.php: " . $e->getMessage());
+ error_log("Stack trace: " . $e->getTraceAsString());
+
+ // Limpiar cualquier output previo antes de enviar JSON
+ if (ob_get_length()) ob_clean();
+
http_response_code(500);
echo json_encode([
'success' => false,
- 'error' => $e->getMessage()
- ]);
+ 'error' => $e->getMessage(),
+ 'file' => basename($e->getFile()),
+ 'line' => $e->getLine()
+ ], JSON_UNESCAPED_UNICODE);
}
?>
diff --git a/api/upload_media.php b/api/upload_media.php
index 512b87f..ac1cd0f 100644
--- a/api/upload_media.php
+++ b/api/upload_media.php
@@ -115,6 +115,13 @@ try {
echo json_encode([
'success' => true,
'message' => 'Archivo subido correctamente',
+ 'id' => $mediaId,
+ 'filename' => $fileName,
+ 'public_url' => $publicUrl,
+ 'media_type' => $mediaType,
+ 'mime_type' => $fileType,
+ 'size' => $fileSize,
+ // Mantener compatibilidad con código existente
'data' => [
'id' => $mediaId,
'filename' => $fileName,
diff --git a/chat_window.php b/chat_window.php
index 08ba0c9..4b85d14 100644
--- a/chat_window.php
+++ b/chat_window.php
@@ -74,6 +74,54 @@ if (empty($user_id)) {
word-wrap: break-word;
}
+ /* Estilos para mensajes multimedia */
+ .message-bubble img {
+ max-width: 300px;
+ max-height: 400px;
+ width: auto;
+ height: auto;
+ border-radius: 8px;
+ cursor: pointer;
+ display: block;
+ margin: 4px 0;
+ }
+
+ .message-bubble video {
+ max-width: 300px;
+ max-height: 400px;
+ border-radius: 8px;
+ display: block;
+ margin: 4px 0;
+ }
+
+ .message-bubble audio {
+ width: 250px;
+ height: 40px;
+ margin: 4px 0;
+ display: block;
+ }
+
+ .message-document {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ padding: 10px 15px;
+ background: rgba(0,0,0,0.05);
+ border-radius: 8px;
+ text-decoration: none;
+ color: inherit;
+ margin: 4px 0;
+ }
+
+ .message-document:hover {
+ background: rgba(0,0,0,0.1);
+ }
+
+ .message-document i {
+ font-size: 1.5rem;
+ color: #25D366;
+ }
+
.message-outgoing {
background: #DCF8C6;
margin-left: auto;
@@ -528,21 +576,34 @@ if (empty($user_id)) {
// Mensaje multimedia
switch (msg.media_type) {
case 'image':
- contentHtml = ``;
+ contentHtml = ``;
break;
case 'video':
- contentHtml = ``;
+ contentHtml = ``;
break;
case 'audio':
- contentHtml = ``;
+ contentHtml = ``;
break;
case 'document':
- const filename = msg.filename || 'Documento';
- contentHtml = ``;
break;
+ default:
+ contentHtml = ``;
}
if (msg.caption) {
@@ -1128,6 +1189,52 @@ if (empty($user_id)) {
// Auto-refresh cada 30 segundos para nuevos mensajes
setInterval(refreshChat, 30000);
});
+
+ // Función para obtener icono según tipo de archivo
+ function getFileIcon(filename) {
+ const ext = filename.split('.').pop().toLowerCase();
+ const iconMap = {
+ 'pdf': 'fas fa-file-pdf text-danger',
+ 'doc': 'fas fa-file-word text-primary',
+ 'docx': 'fas fa-file-word text-primary',
+ 'xls': 'fas fa-file-excel text-success',
+ 'xlsx': 'fas fa-file-excel text-success',
+ 'ppt': 'fas fa-file-powerpoint text-warning',
+ 'pptx': 'fas fa-file-powerpoint text-warning',
+ 'zip': 'fas fa-file-archive text-secondary',
+ 'rar': 'fas fa-file-archive text-secondary',
+ 'txt': 'fas fa-file-alt text-muted',
+ };
+ return iconMap[ext] || 'fas fa-file text-muted';
+ }
+
+ // Modal para ver imágenes en grande
+ function openImageModal(imageUrl) {
+ // Crear modal si no existe
+ let modal = document.getElementById('imageModal');
+ if (!modal) {
+ modal = document.createElement('div');
+ modal.id = 'imageModal';
+ modal.className = 'modal fade';
+ modal.innerHTML = `
+