From 81708fbb227a2318803a1632977d80796e9ceefc Mon Sep 17 00:00:00 2001 From: lizandrogd <77708265+lizandrogd@users.noreply.github.com> Date: Tue, 20 Jan 2026 23:29:06 -0500 Subject: [PATCH] up up --- api/send_message.php | 10 ++-- api/test_send_template.php | 80 +++++++++++++++++++++++++++++++ logs/system.log | 5 ++ scripts/send_template_test.php | 48 +++++++++++++++++++ scripts/update_whatsapp_token.php | 45 +++++++++++++++++ services/WhatsAppService.php | 69 +++++++++++++++++++++----- tmp/debug_flow_resp.json | 1 + tmp/send_resp.json | 1 + tmp/test_send_out.json | 0 9 files changed, 245 insertions(+), 14 deletions(-) create mode 100644 api/test_send_template.php create mode 100644 scripts/send_template_test.php create mode 100644 scripts/update_whatsapp_token.php create mode 100644 tmp/debug_flow_resp.json create mode 100644 tmp/send_resp.json create mode 100644 tmp/test_send_out.json diff --git a/api/send_message.php b/api/send_message.php index 615d406..5464b6d 100644 --- a/api/send_message.php +++ b/api/send_message.php @@ -172,6 +172,7 @@ try { } $language = $input['language'] ?? 'es'; $parameters = $input['parameters'] ?? []; + $componentsSimple = $input['components'] ?? null; // Verificar plantilla en base de datos (opcional) $templateRecord = null; @@ -185,7 +186,7 @@ try { // 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([ @@ -219,7 +220,7 @@ try { // Intentar envío y, si falla por traducción no encontrada, probar variantes de idioma try { - $response = $whatsappService->sendTemplateMessage($recipient, $template, $language, $parameters); + $response = $whatsappService->sendTemplateMessage($recipient, $template, $language, $parameters, [], $componentsSimple); } catch (Exception $e) { $message = $e->getMessage(); @@ -295,6 +296,9 @@ try { } } } + + // 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) ==="); @@ -307,7 +311,7 @@ try { error_log("Method: sendTemplateMessage()"); error_log("================================================================="); - $response = $whatsappService->sendTemplateMessage($recipient, $templateName, $languageCode, $parameters); + $response = $whatsappService->sendTemplateMessage($recipient, $templateName, $languageCode, $parameters, [], $componentsArray); } else { http_response_code(400); diff --git a/api/test_send_template.php b/api/test_send_template.php new file mode 100644 index 0000000..b35ee7d --- /dev/null +++ b/api/test_send_template.php @@ -0,0 +1,80 @@ + $recipient, + 'template' => $template, + 'attempts' => [] +]; + +try { + $wh = new WhatsAppService(); + error_log("[test_send_template] WhatsAppService initialized"); +} catch (Exception $e) { + error_log("[test_send_template] ERROR init: " . $e->getMessage()); + $result['error'] = 'Error initializing WhatsAppService: ' . $e->getMessage(); + $result['trace'] = $e->getTraceAsString(); + echo json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); + exit(1); +} + +foreach ($languages as $lang) { + error_log("[test_send_template] Attempting language: $lang"); + try { + $res = $wh->sendTemplateMessage($recipient, $template, $lang, []); + $result['attempts'][] = [ + 'language' => $lang, + 'success' => true, + 'response' => $res + ]; + error_log("[test_send_template] Success with language: $lang"); + // stop on first success + break; + } catch (Exception $e) { + $msg = $e->getMessage(); + error_log("[test_send_template] Attempt language $lang failed: " . $msg); + $result['attempts'][] = [ + 'language' => $lang, + 'success' => false, + 'error' => $msg, + 'trace' => $e->getTraceAsString() + ]; + // continuar con siguiente candidato + } +} + +echo json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); + +} catch (Throwable $t) { + $err = '[test_send_template][FATAL] ' . $t->getMessage(); + error_log($err); + error_log($t->getTraceAsString()); + http_response_code(500); + echo json_encode(['error' => $t->getMessage(), 'trace' => $t->getTraceAsString()]); + exit(1); +} + +// Si es CLI, exit code 0 si algún intento fue exitoso +$anySuccess = count(array_filter($result['attempts'], fn($a) => $a['success'])) > 0; +exit($anySuccess ? 0 : 1); diff --git a/logs/system.log b/logs/system.log index 4ab1625..6798d57 100644 --- a/logs/system.log +++ b/logs/system.log @@ -1,3 +1,8 @@ [20-Jan-2026 21:21:01 America/Bogota] Query failed: SQLSTATE[01000]: Warning: 1265 Data truncated for column 'status' at row 1 SQL: INSERT INTO conversations (user_id,message_id,direction,message_type,content,media_url,status,created_at) VALUES (:user_id, :message_id, :direction, :message_type, :content, :media_url, :status, :created_at) Params: {"user_id":26,"message_id":"ABGGFlA5Fpa","direction":"incoming","message_type":"text","content":"this is a text message","media_url":null,"status":"received","created_at":"2026-01-20 21:21:01"} [20-Jan-2026 21:22:55 America/Bogota] Query failed: SQLSTATE[01000]: Warning: 1265 Data truncated for column 'status' at row 1 SQL: INSERT INTO conversations (user_id,message_id,direction,message_type,content,media_url,status,created_at) VALUES (:user_id, :message_id, :direction, :message_type, :content, :media_url, :status, :created_at) Params: {"user_id":26,"message_id":"ABGGFlA5Fpa","direction":"incoming","message_type":"text","content":"this is a text message","media_url":null,"status":"received","created_at":"2026-01-20 21:22:55"} [20-Jan-2026 22:31:05 America/Bogota] Query failed: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'updated_at' in 'SET' SQL: UPDATE message_templates SET status = 'approved', updated_at = NOW() WHERE id IN (5) Params: [] +[20-Jan-2026 22:59:20 America/Bogota] PHP Fatal error: Uncaught Error: Call to undefined function getWhatsAppConfigFromDB() in C:\laragon\www\whatsapp\services\WhatsAppService.php:18 +Stack trace: +#0 C:\laragon\www\whatsapp\scripts\send_template_test.php(18): WhatsAppService->__construct() +#1 {main} + thrown in C:\laragon\www\whatsapp\services\WhatsAppService.php on line 18 diff --git a/scripts/send_template_test.php b/scripts/send_template_test.php new file mode 100644 index 0000000..5bd3a27 --- /dev/null +++ b/scripts/send_template_test.php @@ -0,0 +1,48 @@ +getMessage() . "\n"; + echo "Stack trace:\n" . $e->getTraceAsString() . "\n"; + exit(1); +} + +foreach ($candidates as $lang) { + echo "Intentando con language = $lang ...\n"; + try { + $result = $wh->sendTemplateMessage($recipient, $template, $lang, []); + echo "Resultado OK (language=$lang):\n"; + echo json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) . "\n"; + exit(0); + } catch (Exception $e) { + echo "FALLÓ (language=$lang): " . $e->getMessage() . "\n"; + // Mostrar detalles si es posible + if (isset($e->getTrace()[0]['args'][0])) { + echo "Detalle trace arg0: " . var_export($e->getTrace()[0]['args'][0], true) . "\n"; + } + // continuar con siguiente candidato + } +} + +echo "Todos los intentos fallaron. Revisa WhatsApp Business Manager para esa plantilla y los idiomas disponibles.\n"; +exit(1); diff --git a/scripts/update_whatsapp_token.php b/scripts/update_whatsapp_token.php new file mode 100644 index 0000000..9fd8ee5 --- /dev/null +++ b/scripts/update_whatsapp_token.php @@ -0,0 +1,45 @@ +query("INSERT INTO system_config (config_key, config_value) VALUES (?, ?) ON DUPLICATE KEY UPDATE config_value = VALUES(config_value)", ['whatsapp_token', $token]); + echo "Token actualizado en BD (key=whatsapp_token).\n"; +} catch (Exception $e) { + echo "Error actualizando token: " . $e->getMessage() . "\n"; + exit(1); +} + +// Opcional: escribir también en .env para conveniencia (no requerido) +$envFile = dirname(__DIR__) . '/.env'; +if (is_writable($envFile)) { + $contents = file_get_contents($envFile); + if (strpos($contents, 'WHATSAPP_TOKEN=') !== false) { + $new = preg_replace('/^WHATSAPP_TOKEN=.*$/m', 'WHATSAPP_TOKEN="' . addcslashes($token, '"') . '"', $contents); + } else { + $new = $contents . "\nWHATSAPP_TOKEN=\"" . addcslashes($token, '"') . "\"\n"; + } + file_put_contents($envFile, $new); + echo ".env actualizado con nuevo token (si existe y es escribible).\n"; +} else { + echo ".env no escribible o no existe, omitiendo actualización de .env.\n"; +} + +exit(0); diff --git a/services/WhatsAppService.php b/services/WhatsAppService.php index fdd570b..6df9707 100644 --- a/services/WhatsAppService.php +++ b/services/WhatsAppService.php @@ -48,22 +48,69 @@ class WhatsAppService $templateName, $language = 'es', $bodyParameters = [], - $headerParameters = [] + $headerParameters = [], + $rawComponents = null ) { - $components = []; - - if (!empty($headerParameters)) { - $components[] = [ - 'type' => 'header', - 'parameters' => $headerParameters + // Si se pasan components completos (por ejemplo flow/button/image), úsalos tal cual + if (is_array($rawComponents) && !empty($rawComponents)) { + $template = [ + 'name' => $templateName, + 'language' => [ 'code' => $language ], + 'components' => $rawComponents ]; + + $data = [ + 'messaging_product' => 'whatsapp', + 'to' => $this->formatPhoneNumber($to), + 'type' => 'template', + 'template' => $template + ]; + + return $this->sendMessage($data); } + $components = []; + + // Normalizar parámetros de header (si vienen como strings -> convertir a objeto de texto) + if (!empty($headerParameters)) { + $normalizedHeader = []; + foreach ($headerParameters as $hp) { + if (is_array($hp) && isset($hp['type'])) { + $normalizedHeader[] = $hp; + } elseif (is_string($hp)) { + $normalizedHeader[] = [ + 'type' => 'text', + 'text' => $hp + ]; + } + } + if (!empty($normalizedHeader)) { + $components[] = [ + 'type' => 'header', + 'parameters' => $normalizedHeader + ]; + } + } + + // Normalizar parámetros de body: convertir strings a objetos {type: 'text', text: '...'} if (!empty($bodyParameters)) { - $components[] = [ - 'type' => 'body', - 'parameters' => $bodyParameters - ]; + $normalizedBody = []; + foreach ($bodyParameters as $bp) { + if (is_array($bp) && isset($bp['type'])) { + $normalizedBody[] = $bp; // ya en formato detallado + } elseif (is_string($bp)) { + $normalizedBody[] = [ + 'type' => 'text', + 'text' => $bp + ]; + } + } + if (!empty($normalizedBody)) { + $components[] = [ + 'type' => 'body', + 'parameters' => $normalizedBody + ]; + } } $template = [ diff --git a/tmp/debug_flow_resp.json b/tmp/debug_flow_resp.json new file mode 100644 index 0000000..ec91e3f --- /dev/null +++ b/tmp/debug_flow_resp.json @@ -0,0 +1 @@ +{"success":true,"message":"Mensaje simulado enviado correctamente (modo debug) - NOTA: En producci\u00f3n, usa plantillas para n\u00fameros que no han respondido en 24h","data":{"recipient":"573168950803","type":"template","timestamp":"2026-01-20 23:28:33","warning":"Para env\u00edo real, verifica que el usuario haya respondido en las \u00faltimas 24h o usa plantillas","template_name":"encuesta_satisfaccin","language":"es_MX","format":"whatsapp_standard"}} \ No newline at end of file diff --git a/tmp/send_resp.json b/tmp/send_resp.json new file mode 100644 index 0000000..469466b --- /dev/null +++ b/tmp/send_resp.json @@ -0,0 +1 @@ +{"success":true,"message":"Mensaje simulado enviado correctamente (modo debug) - NOTA: En producci\u00f3n, usa plantillas para n\u00fameros que no han respondido en 24h","data":{"recipient":"573168950803","type":"template","timestamp":"2026-01-20 23:15:31","warning":"Para env\u00edo real, verifica que el usuario haya respondido en las \u00faltimas 24h o usa plantillas","template_name":"encuesta_satisfaccin","language":"es_ES","format":"simple"}} \ No newline at end of file diff --git a/tmp/test_send_out.json b/tmp/test_send_out.json new file mode 100644 index 0000000..e69de29