'Método no permitido. Use POST.', 'method_received' => $_SERVER['REQUEST_METHOD']]); exit; } try { $rawInput = file_get_contents('php://input'); $input = json_decode($rawInput, true); // Debug logging if ($debugMode) { error_log("=== SEND MESSAGE DEBUG ==="); error_log("Method: " . $_SERVER['REQUEST_METHOD']); error_log("Content-Type: " . ($_SERVER['CONTENT_TYPE'] ?? 'not set')); error_log("Raw input: " . $rawInput); error_log("Parsed JSON: " . json_encode($input)); error_log("========================"); } if (!$input) { // Si no viene JSON válido, intentar leer datos from form-encoded POST if (!empty($_POST)) { $input = $_POST; // Si el formulario incluye template_params como JSON string, decodificarlo if (isset($input['template_params']) && is_string($input['template_params'])) { $decodedTp = json_decode($input['template_params'], true); if ($decodedTp !== null) { $input['template_params'] = $decodedTp; } } } else { http_response_code(400); echo json_encode(['error' => 'JSON inválido o vacío', 'raw_input' => $rawInput]); exit; } } $db = Database::getInstance(); // Modo debug: simular envío exitoso if ($debugMode) { $recipient = $input['recipient'] ?? $input['user_id'] ?? 'unknown'; $message = $input['message'] ?? 'mensaje de prueba'; $type = $input['type'] ?? 'text'; $template = $input['template'] ?? $input['template_name'] ?? null; $responseData = [ 'recipient' => $recipient, 'type' => $type, 'timestamp' => date('Y-m-d H:i:s'), 'warning' => 'Para envío real, verifica que el usuario haya respondido en las últimas 24h o usa plantillas' ]; if ($type === 'template') { // Detectar formato de plantilla if (isset($input['template']) && is_array($input['template'])) { // Formato WhatsApp estándar $templateData = $input['template']; $responseData['template_name'] = $templateData['name'] ?? 'unknown'; $responseData['language'] = $templateData['language']['code'] ?? 'es'; $responseData['format'] = 'whatsapp_standard'; $message = "Plantilla WhatsApp: {$templateData['name']}"; } else { // Formato simple $template = $input['template'] ?? $input['template_name'] ?? null; $responseData['template_name'] = $template; $responseData['language'] = $input['language'] ?? 'es'; $responseData['format'] = 'simple'; $message = "Plantilla: {$template}"; } } else { $responseData['message'] = $message; } echo json_encode([ 'success' => true, 'message' => 'Mensaje simulado enviado correctamente (modo debug) - NOTA: En producción, usa plantillas para números que no han respondido en 24h', 'data' => $responseData ]); exit; } // Modo 1: Envío directo a número de teléfono (formato original) if (isset($input['recipient'])) { $recipient = $input['recipient']; $type = $input['type'] ?? 'text'; // Verificar si es mensaje de texto y si el usuario respondió en las últimas 24h if ($type === 'text') { // Permitir número específico que sí ha respondido if ($recipient === '573168950803') { // Este número específico tiene permitido envío de texto libre error_log("NÚMERO AUTORIZADO: 573168950803 - Permitiendo envío de texto libre"); } else { // Primero obtener el user_id del teléfono $userStmt = $db->query( "SELECT id FROM users WHERE phone_number = ? LIMIT 1", [$recipient] ); $user = $userStmt->fetch(); if ($user) { $stmt = $db->query( "SELECT MAX(created_at) as last_message FROM conversations WHERE user_id = ? AND direction = 'incoming' AND created_at >= DATE_SUB(NOW(), INTERVAL 24 HOUR)", [$user['id']] ); $lastMessage = $stmt->fetch(); if (!$lastMessage || !$lastMessage['last_message']) { echo json_encode([ 'success' => false, 'error' => 'No se puede enviar mensaje de texto libre. El usuario no ha respondido en las últimas 24 horas.', 'suggestion' => 'Usa una plantilla pre-aprobada o espera a que el usuario te escriba.', 'error_code' => 'OUTSIDE_24H_WINDOW' ]); exit; } } // Si no existe el usuario, permitir envío (se creará automáticamente) } } $whatsappService = new WhatsAppService(); $response = null; switch ($type) { case 'text': if (!isset($input['message']) || empty($input['message'])) { http_response_code(400); echo json_encode(['error' => 'Mensaje requerido']); exit; } // DEBUG: Mostrar datos de envío de mensaje de texto error_log("=== DEBUG WHATSAPP TEXT MESSAGE ==="); error_log("Recipient: " . $recipient); error_log("Message: " . $input['message']); error_log("Method: sendTextMessage()/sendTextReply()"); error_log("===================================="); // Si viene reply_to, usar reply con contexto $operatorId = $_SESSION['admin_user']['id'] ?? null; if (!empty($input['reply_to'])) { $replyTo = $input['reply_to']; $response = $whatsappService->sendTextReply($recipient, $replyTo, $input['message'], $operatorId ? ['operator_id' => $operatorId] : null); } else { $response = $whatsappService->sendTextMessage($recipient, $input['message'], $operatorId ? ['operator_id' => $operatorId] : null); } break; case 'template': // Formato 1: Simple (actual) if (isset($input['template_name']) || (isset($input['template']) && !is_array($input['template']))) { $template = $input['template'] ?? $input['template_name'] ?? ''; if (empty($template)) { http_response_code(400); echo json_encode(['error' => 'Template requerido']); exit; } $language = $input['language'] ?? 'es'; $parameters = $input['parameters'] ?? []; // Also accept template_params (from form or hidden input) if ((empty($parameters) || $parameters === []) && isset($input['template_params'])) { $tp = $input['template_params']; if (is_string($tp)) { $decoded = json_decode($tp, true); if ($decoded !== null) { $parameters = $decoded; } else { // fallback: treat string as a single named parameter value (name) $parameters = ['name' => $tp]; } } elseif (is_array($tp)) { $parameters = $tp; } } $componentsSimple = $input['components'] ?? null; // Verificar plantilla en base de datos (opcional) $templateRecord = null; try { $stmt = $db->query( "SELECT * FROM message_templates WHERE template_name = ? LIMIT 1", [$template] ); $templateRecord = $stmt->fetch(); } catch (Exception $e) { // Si no existe la tabla, continuar sin validación local error_log("Template validation skipped: " . $e->getMessage()); } // Solo validar si la tabla existe y encontramos registros if ($templateRecord && $templateRecord['status'] !== 'approved') { echo json_encode([ 'success' => false, 'error' => 'Plantilla no aprobada en el sistema local', 'template_name' => $template, 'template_status' => $templateRecord['status'], 'suggestions' => [ '1. Aprueba la plantilla desde la pestaña Plantillas', '2. O verifica que esté aprobada en WhatsApp Business Manager', '3. Usa el nombre exacto de la plantilla' ] ]); exit; } // Usar el idioma de la base de datos si no se especifica if ($language === 'es' && $templateRecord['language_code']) { $language = $templateRecord['language_code']; } // DEBUG: Mostrar datos de envío de plantilla formato simple error_log("=== DEBUG WHATSAPP TEMPLATE MESSAGE (SIMPLE FORMAT) ==="); error_log("Recipient: " . $recipient); error_log("Template Name: " . $template); error_log("Language: " . $language); error_log("Parameters: " . json_encode($parameters)); error_log("Template Record Status: " . ($templateRecord ? $templateRecord['status'] : 'not found in DB')); error_log("Method: sendTemplateMessage()"); error_log("========================================================"); // Intentar envío y, si falla por traducción no encontrada, probar variantes de idioma try { $response = $whatsappService->sendTemplateMessage($recipient, $template, $language, $parameters, [], $componentsSimple); } catch (Exception $e) { $message = $e->getMessage(); if (strpos($message, 'Template name does not exist in the translation') !== false || strpos($message, '#132001') !== false) { error_log("Template translation missing for language: $language. Attempting fallbacks..."); $candidates = []; // Añadir language_code de la BD si existe y es distinto if (!empty($templateRecord['language_code']) && $templateRecord['language_code'] !== $language) { $candidates[] = $templateRecord['language_code']; } // Si viene con formato regional (es_ES) intentar la base (es) if (strpos($language, '_') !== false) { $base = explode('_', $language)[0]; if ($base !== $language) $candidates[] = $base; } else { // Si es código corto (es) intentar variantes comunes if (strlen($language) === 2) { $candidates[] = strtoupper($language) === $language ? $language : $language . '_ES'; $candidates[] = $language . '_MX'; $candidates[] = $language . '_PE'; } } // Eliminar duplicados y vacíos $candidates = array_values(array_unique(array_filter($candidates))); foreach ($candidates as $cand) { try { error_log("Retrying template send with language candidate: $cand"); $response = $whatsappService->sendTemplateMessage($recipient, $template, $cand, $parameters); if ($response) { error_log("Template send succeeded with fallback language: $cand"); break; } } catch (Exception $e2) { error_log("Fallback language $cand failed: " . $e2->getMessage()); // seguir intentando con siguientes candidatos } } if (empty($response)) { // Re-lanzar el error original si no encontramos nada que funcione throw $e; } } else { // Re-lanzar si es otro tipo de error throw $e; } } } // Formato 2: WhatsApp Business API estándar elseif (isset($input['template']) && is_array($input['template'])) { $templateData = $input['template']; $templateName = $templateData['name'] ?? ''; $languageCode = $templateData['language']['code'] ?? 'es'; $components = $templateData['components'] ?? []; if (empty($templateName)) { http_response_code(400); echo json_encode(['error' => 'Template name requerido en formato WhatsApp']); exit; } // Convertir formato WhatsApp a nuestro servicio $parameters = []; foreach ($components as $component) { if ($component['type'] === 'body' && isset($component['parameters'])) { foreach ($component['parameters'] as $param) { $parameters[] = $param['text'] ?? ''; } } } // Preserve raw components (flow/buttons/header/image) and pass through $componentsArray = $templateData['components'] ?? null; // DEBUG: Mostrar datos de envío de plantilla formato WhatsApp estándar error_log("=== DEBUG WHATSAPP TEMPLATE MESSAGE (WHATSAPP STANDARD FORMAT) ==="); error_log("Recipient: " . $recipient); error_log("Template Name: " . $templateName); error_log("Language Code: " . $languageCode); error_log("Original Components: " . json_encode($components)); error_log("Converted Parameters: " . json_encode($parameters)); error_log("Full Template Data: " . json_encode($templateData)); error_log("Method: sendTemplateMessage()"); error_log("================================================================="); $response = $whatsappService->sendTemplateMessage($recipient, $templateName, $languageCode, $parameters, [], $componentsArray); } else { http_response_code(400); echo json_encode(['error' => 'Template requerido (formato simple o WhatsApp estándar)']); exit; } break; default: http_response_code(400); echo json_encode(['error' => 'Tipo de mensaje no soportado']); exit; } if ($response) { // DEBUG: Mostrar respuesta exitosa de WhatsApp error_log("=== DEBUG WHATSAPP SUCCESS RESPONSE ==="); error_log("Response: " . json_encode($response)); error_log("======================================"); // Guardar mensaje en la base de datos try { // Buscar o crear usuario por teléfono $stmt = $db->query( "SELECT id FROM users WHERE phone_number = ? LIMIT 1", [$recipient] ); $user = $stmt->fetch(); $userId = null; if ($user) { $userId = $user['id']; } else { // Crear nuevo usuario $stmt = $db->query( "INSERT INTO users (phone_number, name, created_at) VALUES (?, ?, NOW())", [$recipient, $recipient] ); $userId = $stmt ? $db->lastInsertId() : null; } if ($userId) { // Preparar datos del mensaje $messageContent = ''; $messageType = $type; if ($type === 'text') { $messageContent = $input['message']; } elseif ($type === 'template') { $templateName = $input['template'] ?? $input['template_name'] ?? ''; $messageContent = "Plantilla: {$templateName}"; } // Guardado en BD manejado por WhatsAppService->saveOutgoingMessage() error_log("Outgoing message saving delegated to WhatsAppService - User ID: $userId, Content: $messageContent"); } else { error_log("Error: No se pudo obtener o crear user_id para recipient: $recipient"); } } catch (Exception $e) { error_log("Error detallado guardando mensaje en base de datos: " . $e->getMessage()); error_log("Stack trace: " . $e->getTraceAsString()); } echo json_encode([ 'success' => true, 'message' => 'Mensaje enviado correctamente', 'whatsapp_response' => $response ]); } else { // DEBUG: Mostrar error de respuesta de WhatsApp error_log("=== DEBUG WHATSAPP ERROR RESPONSE ==="); error_log("Response was NULL or FALSE"); error_log("Type: " . $type); error_log("===================================="); // Error específico para plantillas con soluciones detalladas if ($type === 'template') { $templateName = $input['template_name'] ?? $input['template'] ?? 'unknown'; $language = $input['language'] ?? 'es'; echo json_encode([ 'success' => false, 'error' => 'Error #132001: Template name does not exist in the translation', 'template_name' => $templateName, 'language' => $language, 'error_analysis' => [ 'El error #132001 indica que WhatsApp no encuentra la plantilla', 'Esto puede suceder por varias razones:' ], 'solutions' => [ '1. CREAR PLANTILLA: Ve a WhatsApp Business Manager → Account Tools → Message Templates', '2. APROBAR PLANTILLA: Asegúrate que Meta haya aprobado tu plantilla', '3. NOMBRE EXACTO: Usa el nombre exacto (case-sensitive)', '4. IDIOMA CORRECTO: Usa el código exacto (en_US, es_ES, etc.)', '5. TIEMPO DE PROPAGACIÓN: Espera 15-30 min después de la aprobación' ], 'debug_info' => [ 'template_attempted' => $templateName, 'language_attempted' => $language, 'common_templates' => ['hello_world', 'sample_shipping_confirmation'], 'common_languages' => ['en_US', 'es_ES', 'es_MX'] ], 'next_steps' => [ '1. Verifica en WhatsApp Business Manager si la plantilla existe', '2. Crea una plantilla simple primero (ej: "hello_world")', '3. Usa el modo debug para probar sin envío real' ] ]); } else { http_response_code(500); echo json_encode(['error' => 'Error enviando mensaje']); } } // Modo 2: Envío a usuario existente (nuevo formato para conversaciones) } elseif (isset($input['user_id']) && isset($input['message'])) { $userId = intval($input['user_id']); $message = trim($input['message']); if (!$userId || !$message) { http_response_code(400); echo json_encode(['error' => 'user_id y message son requeridos']); exit; } // Obtener información del usuario $stmt = $db->query( "SELECT phone_number, name FROM users WHERE id = ?", [$userId] ); $user = $stmt->fetch(); if (!$user) { http_response_code(404); echo json_encode(['error' => 'Usuario no encontrado']); exit; } // Enviar mensaje via WhatsApp API $whatsappService = new WhatsAppService(); // DEBUG: Mostrar datos de envío a usuario existente error_log("=== DEBUG WHATSAPP MESSAGE TO EXISTING USER ==="); error_log("User ID: " . $userId); error_log("User Name: " . ($user['name'] ?? 'N/A')); error_log("Phone Number: " . $user['phone_number']); error_log("Message: " . $message); error_log("Method: sendTextMessage()"); error_log("==============================================="); $response = $whatsappService->sendTextMessage($user['phone_number'], $message); if ($response && isset($response['conversations']) && !empty($response['conversations'])) { // Saving handled by WhatsAppService->saveOutgoingMessage(), skip manual insert to avoid duplicates echo json_encode([ 'success' => true, 'message' => 'Mensaje enviado correctamente', 'whatsapp_response' => $response ]); } else { echo json_encode([ 'success' => false, 'error' => 'Error al enviar mensaje por WhatsApp' ]); } } else { http_response_code(400); echo json_encode(['error' => 'Formato de datos inválido. Se requiere recipient o user_id+message']); exit; } } catch (Exception $e) { error_log("Error in send_message.php: " . $e->getMessage()); http_response_code(500); echo json_encode(['error' => 'Error interno del servidor: ' . $e->getMessage()]); } ?>