false, 'error' => 'Método no permitido']); 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 { $rawInput = file_get_contents('php://input'); error_log("send_media_message.php - Raw input: " . $rawInput); smm_log("Raw input: " . $rawInput); $input = json_decode($rawInput, true); if (!$input) { error_log("send_media_message.php - JSON decode failed"); smm_log("JSON decode failed. Raw: " . $rawInput); throw new Exception('Datos no válidos - JSON inválido'); } error_log("send_media_message.php - Input decoded: " . json_encode($input)); smm_log("Input decoded: " . json_encode($input)); // Debug flag: permitir depuración remota si se pasa debug=true en query o en body $debugMode = (isset($_GET['debug']) && $_GET['debug'] === 'true') || (!empty($input['debug'])); $debugInfo = []; // Helper: hacer HEAD request para verificar accesibilidad de URL de media function headCheckUrl($url) { $ch = curl_init(); curl_setopt_array($ch, [ CURLOPT_URL => $url, CURLOPT_NOBODY => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HEADER => true, CURLOPT_FOLLOWLOCATION => true, CURLOPT_TIMEOUT => 10 ]); $res = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $contentType = curl_getinfo($ch, CURLINFO_CONTENT_TYPE); $contentLength = curl_getinfo($ch, CURLINFO_CONTENT_LENGTH_DOWNLOAD); $err = curl_error($ch); if (version_compare(PHP_VERSION, '8.5.0', '<')) { curl_close($ch); } return [ 'http_code' => $httpCode, 'content_type' => $contentType, 'content_length' => $contentLength, 'error' => $err ]; } // Validar campos requeridos if (empty($input['recipient']) || empty($input['media_url']) || empty($input['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']; $mediaUrl = $input['media_url']; $mediaType = $input['media_type']; // image, video, audio, document $caption = $input['caption'] ?? null; $filename = $input['filename'] ?? null; // Inicializar servicio de WhatsApp $whatsapp = new WhatsAppService(); // 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); 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)); smm_log("Upload result: " . json_encode($uploadResult)); 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); smm_log("Media ID obtained: " . $mediaId); // Enviar mensaje usando media_id $response = sendMediaByIdToWhatsApp($whatsapp, $recipient, $mediaId, $mediaType, $caption, $filename); smm_log("Send media by id response: " . json_encode($response)); } else { smm_log("Upload did not return id: " . json_encode($uploadResult)); 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: " . $mediaUrl); smm_log("Public URL: " . $mediaUrl); // Chequear accesibilidad de la URL antes de pedir a WhatsApp que la descargue try { $head = headCheckUrl($mediaUrl); smm_log("HEAD check: " . json_encode($head)); if ($debugMode) $debugInfo['media_head'] = $head; if (isset($head['http_code']) && intval($head['http_code']) >= 400) { smm_log("send_media_message.php - Warning: media URL returned HTTP " . $head['http_code']); } } catch (Exception $e) { smm_log("send_media_message.php - HEAD check failed: " . $e->getMessage()); if ($debugMode) $debugInfo['media_head_error'] = $e->getMessage(); } $response = sendMediaByLinkToWhatsApp($whatsapp, $recipient, $mediaUrl, $mediaType, $caption, $filename); } // Guardar respuesta en base de datos // Aceptar tanto respuestas con 'conversations' como con 'messages' $sentMessageId = null; if ($response) { if (isset($response['conversations'][0]['id'])) { $sentMessageId = $response['conversations'][0]['id']; } elseif (isset($response['messages'][0]['id'])) { $sentMessageId = $response['messages'][0]['id']; } } // Si no hay id, pero la respuesta es un string (posible JSON crudo), intentar decodificar if (!$sentMessageId && is_string($response)) { $maybe = json_decode($response, true); if (is_array($maybe)) { error_log("send_media_message.php - Decoded raw response string to array for inspection"); // Reasignar response para usar la estructura decodificada $response = $maybe; if (isset($response['conversations'][0]['id'])) { $sentMessageId = $response['conversations'][0]['id']; } elseif (isset($response['messages'][0]['id'])) { $sentMessageId = $response['messages'][0]['id']; } } } if ($response && $sentMessageId) { error_log("send_media_message.php - Respuesta de WhatsApp exitosa: " . json_encode($response)); smm_log("WhatsApp response (successful): " . json_encode($response)); if ($debugMode) $debugInfo['whatsapp_response'] = $response; // Guardar en base de datos $db = Database::getInstance(); // Obtener usuario $user = $db->fetch( "SELECT id FROM users WHERE phone_number = ?", [$recipient] ); if ($user) { // Datos base para insertar $conversationData = [ 'user_id' => $user['id'], 'message_id' => $sentMessageId, 'direction' => 'outgoing', 'message_type' => $mediaType, 'content' => $caption ?? $filename ?? '', '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()); } } $out = [ 'success' => true, 'message' => 'Mensaje multimedia enviado correctamente', 'media_type' => $mediaType, 'data' => $response ]; if ($debugMode) $out['debug'] = $debugInfo; echo json_encode($out); } else { error_log("send_media_message.php - Respuesta de WhatsApp sin message_id: " . json_encode($response)); // Añadir contexto adicional para debugging: guardar la respuesta cruda y tipo $raw = is_string($response) ? $response : json_encode($response); error_log("send_media_message.php - Raw response: " . substr($raw, 0, 2000)); smm_log("Raw response: " . substr($raw, 0, 2000)); throw new Exception('Error al enviar mensaje: ' . $raw); } } 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); $errOut = [ 'success' => false, 'error' => $e->getMessage(), 'file' => basename($e->getFile()), 'line' => $e->getLine() ]; if (isset($debugMode) && $debugMode) { $errOut['debug'] = $debugInfo; } echo json_encode($errOut, JSON_UNESCAPED_UNICODE); } ?>