This commit is contained in:
lizandrogd
2025-11-18 20:26:36 -05:00
commit ce12ac2cce
45 changed files with 10517 additions and 0 deletions
+79
View File
@@ -0,0 +1,79 @@
<?php
/**
* API - Exportar usuarios a CSV
* Fecha: 13 de noviembre de 2025
*/
require_once '../config/config.php';
// Headers para descarga de archivo
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename="usuarios_whatsapp_' . date('Y-m-d') . '.csv"');
header('Cache-Control: no-cache, must-revalidate');
try {
$db = Database::getInstance();
// Obtener todos los usuarios con información adicional
$users = $db->fetchAll(
"SELECT
u.id,
u.phone_number,
u.name,
u.email,
u.status,
u.created_at,
u.updated_at,
COUNT(c.id) as total_messages,
MAX(c.created_at) as last_activity
FROM users u
LEFT JOIN conversations c ON u.id = c.user_id
GROUP BY u.id
ORDER BY u.created_at DESC"
);
// Crear el archivo CSV
$output = fopen('php://output', 'w');
// BOM para UTF-8
fprintf($output, chr(0xEF).chr(0xBB).chr(0xBF));
// Encabezados
fputcsv($output, [
'ID',
'Teléfono',
'Nombre',
'Email',
'Estado',
'Total Mensajes',
'Última Actividad',
'Fecha Registro'
], ';');
// Datos
foreach ($users as $user) {
fputcsv($output, [
$user['id'],
$user['phone_number'],
$user['name'] ?? 'Sin nombre',
$user['email'] ?? 'Sin email',
$user['status'],
$user['total_messages'],
$user['last_activity'] ? date('d/m/Y H:i', strtotime($user['last_activity'])) : 'Nunca',
date('d/m/Y H:i', strtotime($user['created_at']))
], ';');
}
fclose($output);
} catch (Exception $e) {
error_log("Error in export_users.php: " . $e->getMessage());
// Cambiar headers para error
header('Content-Type: application/json; charset=utf-8');
header('Content-Disposition: inline');
http_response_code(500);
echo json_encode(['error' => 'Error interno del servidor']);
}
?>
+47
View File
@@ -0,0 +1,47 @@
<?php
/**
* API - Obtener datos para gráficos
* Fecha: 13 de noviembre de 2025
*/
require_once '../config/config.php';
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET');
header('Access-Control-Allow-Headers: Content-Type');
try {
$db = Database::getInstance();
// Obtener datos de los últimos 7 días
$chartData = $db->fetchAll(
"SELECT
DATE(created_at) as date,
COUNT(*) as message_count
FROM conversations
WHERE created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY)
GROUP BY DATE(created_at)
ORDER BY date ASC"
);
// Formatear datos para Chart.js
$labels = [];
$data = [];
foreach ($chartData as $row) {
$labels[] = date('d/m', strtotime($row['date']));
$data[] = (int)$row['message_count'];
}
echo json_encode([
'labels' => $labels,
'data' => $data
]);
} catch (Exception $e) {
error_log("Error in get_chart_data.php: " . $e->getMessage());
http_response_code(500);
echo json_encode(['error' => 'Error interno del servidor']);
}
?>
+41
View File
@@ -0,0 +1,41 @@
<?php
/**
* API - Obtener conversaciones recientes
* Fecha: 13 de noviembre de 2025
*/
require_once '../config/config.php';
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET');
header('Access-Control-Allow-Headers: Content-Type');
try {
$db = Database::getInstance();
$conversations = $db->fetchAll(
"SELECT
c.id,
c.user_id,
c.content,
c.direction,
c.message_type,
c.status,
c.created_at,
u.phone_number,
u.name
FROM conversations c
JOIN users u ON c.user_id = u.id
ORDER BY c.created_at DESC
LIMIT 50"
);
echo json_encode($conversations);
} catch (Exception $e) {
error_log("Error in get_conversations.php: " . $e->getMessage());
http_response_code(500);
echo json_encode(['error' => 'Error interno del servidor']);
}
?>
+44
View File
@@ -0,0 +1,44 @@
<?php
/**
* API - Obtener logs del webhook
* Fecha: 13 de noviembre de 2025
*/
require_once '../config/config.php';
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET');
header('Access-Control-Allow-Headers: Content-Type');
try {
$db = Database::getInstance();
$limit = $_GET['limit'] ?? 50;
$offset = $_GET['offset'] ?? 0;
$logs = $db->fetchAll(
"SELECT
id,
status_code,
ip_address,
created_at,
SUBSTRING(request_body, 1, 100) as request_preview,
SUBSTRING(response_body, 1, 100) as response_preview
FROM webhook_logs
ORDER BY created_at DESC
LIMIT :limit OFFSET :offset",
[
'limit' => (int)$limit,
'offset' => (int)$offset
]
);
echo json_encode($logs);
} catch (Exception $e) {
error_log("Error in get_logs.php: " . $e->getMessage());
http_response_code(500);
echo json_encode(['error' => 'Error interno del servidor']);
}
?>
+51
View File
@@ -0,0 +1,51 @@
<?php
/**
* API - Obtener menús
* Fecha: 13 de noviembre de 2025
*/
require_once '../config/config.php';
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET');
header('Access-Control-Allow-Headers: Content-Type');
try {
$db = Database::getInstance();
$menus = $db->fetchAll(
"SELECT
id,
name,
title,
description,
parent_id,
is_root,
is_active,
order_position,
created_at,
updated_at
FROM menus
ORDER BY order_position ASC, title ASC"
);
// Obtener opciones de cada menú
foreach ($menus as &$menu) {
$options = $db->fetchAll(
"SELECT * FROM menu_options
WHERE menu_id = :menu_id
ORDER BY option_number ASC",
['menu_id' => $menu['id']]
);
$menu['options'] = $options;
}
echo json_encode($menus);
} catch (Exception $e) {
error_log("Error in get_menus.php: " . $e->getMessage());
http_response_code(500);
echo json_encode(['error' => 'Error interno del servidor']);
}
?>
+39
View File
@@ -0,0 +1,39 @@
<?php
/**
* API - Obtener mensajes recientes para dashboard
* Fecha: 13 de noviembre de 2025
*/
require_once '../config/config.php';
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET');
header('Access-Control-Allow-Headers: Content-Type');
try {
$db = Database::getInstance();
$recentMessages = $db->fetchAll(
"SELECT
c.content,
c.direction,
c.message_type,
c.created_at,
u.phone_number,
u.name
FROM conversations c
JOIN users u ON c.user_id = u.id
WHERE c.content IS NOT NULL AND c.content != ''
ORDER BY c.created_at DESC
LIMIT 10"
);
echo json_encode($recentMessages);
} catch (Exception $e) {
error_log("Error in get_recent_messages.php: " . $e->getMessage());
http_response_code(500);
echo json_encode(['error' => 'Error interno del servidor']);
}
?>
+33
View File
@@ -0,0 +1,33 @@
<?php
/**
* API - Obtener configuración del sistema
* Fecha: 13 de noviembre de 2025
*/
require_once '../config/config.php';
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET');
header('Access-Control-Allow-Headers: Content-Type');
try {
$db = Database::getInstance();
$configs = $db->fetchAll(
"SELECT config_key, config_value FROM system_config"
);
$settings = [];
foreach ($configs as $config) {
$settings[$config['config_key']] = $config['config_value'];
}
echo json_encode($settings);
} catch (Exception $e) {
error_log("Error in get_settings.php: " . $e->getMessage());
http_response_code(500);
echo json_encode(['error' => 'Error interno del servidor']);
}
?>
+48
View File
@@ -0,0 +1,48 @@
<?php
/**
* API - Obtener estadísticas del dashboard
* Fecha: 13 de noviembre de 2025
*/
require_once '../config/config.php';
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET');
header('Access-Control-Allow-Headers: Content-Type');
try {
$db = Database::getInstance();
// Total de usuarios
$totalUsers = $db->fetch("SELECT COUNT(*) as count FROM users")['count'];
// Mensajes hoy
$messagesToday = $db->fetch(
"SELECT COUNT(*) as count FROM conversations WHERE DATE(created_at) = CURDATE()"
)['count'];
// Usuarios activos (último mes)
$activeUsers = $db->fetch(
"SELECT COUNT(DISTINCT user_id) as count FROM conversations
WHERE created_at >= DATE_SUB(NOW(), INTERVAL 30 DAY)"
)['count'];
// Total de mensajes
$totalMessages = $db->fetch("SELECT COUNT(*) as count FROM conversations")['count'];
$stats = [
'total_users' => (int)$totalUsers,
'messages_today' => (int)$messagesToday,
'active_users' => (int)$activeUsers,
'total_messages' => (int)$totalMessages
];
echo json_encode($stats);
} catch (Exception $e) {
error_log("Error in get_stats.php: " . $e->getMessage());
http_response_code(500);
echo json_encode(['error' => 'Error interno del servidor']);
}
?>
+37
View File
@@ -0,0 +1,37 @@
<?php
/**
* API - Obtener plantillas de mensaje
* Fecha: 13 de noviembre de 2025
*/
require_once '../config/config.php';
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET');
header('Access-Control-Allow-Headers: Content-Type');
try {
$db = Database::getInstance();
$templates = $db->fetchAll(
"SELECT
id,
name,
template_name,
language_code,
category,
status,
created_at
FROM message_templates
ORDER BY name ASC"
);
echo json_encode($templates);
} catch (Exception $e) {
error_log("Error in get_templates.php: " . $e->getMessage());
http_response_code(500);
echo json_encode(['error' => 'Error interno del servidor']);
}
?>
+41
View File
@@ -0,0 +1,41 @@
<?php
/**
* API - Obtener usuarios
* Fecha: 13 de noviembre de 2025
*/
require_once '../config/config.php';
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET');
header('Access-Control-Allow-Headers: Content-Type');
try {
$db = Database::getInstance();
$users = $db->fetchAll(
"SELECT
u.id,
u.phone_number,
u.name,
u.email,
u.status,
u.current_menu_id,
u.current_step,
u.created_at,
u.updated_at,
m.name as current_menu
FROM users u
LEFT JOIN menus m ON u.current_menu_id = m.id
ORDER BY u.created_at DESC"
);
echo json_encode($users);
} catch (Exception $e) {
error_log("Error in get_users.php: " . $e->getMessage());
http_response_code(500);
echo json_encode(['error' => 'Error interno del servidor']);
}
?>
+64
View File
@@ -0,0 +1,64 @@
<?php
/**
* API - Guardar menú
* Fecha: 13 de noviembre de 2025
*/
require_once '../config/config.php';
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST');
header('Access-Control-Allow-Headers: Content-Type');
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
echo json_encode(['error' => 'Método no permitido']);
exit;
}
try {
$input = json_decode(file_get_contents('php://input'), true);
if (!$input || !isset($input['name']) || !isset($input['title'])) {
http_response_code(400);
echo json_encode(['error' => 'Nombre y título son requeridos']);
exit;
}
$db = Database::getInstance();
// Verificar si es menú raíz
$isRoot = empty($input['parent_id']) ? 1 : 0;
// Obtener próximo order_position
$maxOrder = $db->fetch(
"SELECT COALESCE(MAX(order_position), 0) as max_order FROM menus"
);
$menuData = [
'name' => $input['name'],
'title' => $input['title'],
'description' => $input['description'] ?? '',
'parent_id' => empty($input['parent_id']) ? null : $input['parent_id'],
'is_root' => $isRoot,
'is_active' => $input['is_active'] ?? 1,
'order_position' => $maxOrder['max_order'] + 1,
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s')
];
$menuId = $db->insert('menus', $menuData);
echo json_encode([
'success' => true,
'message' => 'Menú guardado correctamente',
'menu_id' => $menuId
]);
} catch (Exception $e) {
error_log("Error in save_menu.php: " . $e->getMessage());
http_response_code(500);
echo json_encode(['error' => 'Error interno del servidor: ' . $e->getMessage()]);
}
?>
+89
View File
@@ -0,0 +1,89 @@
<?php
/**
* API - Guardar configuración del sistema
* Fecha: 13 de noviembre de 2025
*/
require_once '../config/config.php';
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST');
header('Access-Control-Allow-Headers: Content-Type');
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
echo json_encode(['error' => 'Método no permitido']);
exit;
}
try {
$input = json_decode(file_get_contents('php://input'), true);
if (!$input) {
http_response_code(400);
echo json_encode(['error' => 'Datos inválidos']);
exit;
}
$db = Database::getInstance();
// Mapear configuraciones
$configMap = [
'whatsapp_token' => $input['whatsapp_token'] ?? '',
'phone_number_id' => $input['phone_number_id'] ?? '',
'webhook_verify_token' => $input['webhook_token'] ?? '',
'business_name' => $input['business_name'] ?? '',
'welcome_message' => $input['welcome_message'] ?? ''
];
$db->beginTransaction();
try {
foreach ($configMap as $key => $value) {
if (!empty($value)) {
// Verificar si la configuración existe
$existing = $db->fetch(
"SELECT id FROM system_config WHERE config_key = :key",
['key' => $key]
);
if ($existing) {
// Actualizar
$db->update(
'system_config',
['config_value' => $value, 'updated_at' => date('Y-m-d H:i:s')],
'config_key = :key',
['key' => $key]
);
} else {
// Insertar
$db->insert('system_config', [
'config_key' => $key,
'config_value' => $value,
'description' => 'Configurado desde la interfaz web',
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s')
]);
}
}
}
$db->commit();
echo json_encode([
'success' => true,
'message' => 'Configuración guardada correctamente'
]);
} catch (Exception $e) {
$db->rollback();
throw $e;
}
} catch (Exception $e) {
error_log("Error in save_settings.php: " . $e->getMessage());
http_response_code(500);
echo json_encode(['error' => 'Error interno del servidor: ' . $e->getMessage()]);
}
?>
+88
View File
@@ -0,0 +1,88 @@
<?php
/**
* API - Envío masivo de mensajes
* Fecha: 13 de noviembre de 2025
*/
require_once '../config/config.php';
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST');
header('Access-Control-Allow-Headers: Content-Type');
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
echo json_encode(['error' => 'Método no permitido']);
exit;
}
try {
$input = json_decode(file_get_contents('php://input'), true);
if (!$input || !isset($input['message'])) {
http_response_code(400);
echo json_encode(['error' => 'Mensaje requerido']);
exit;
}
$filter = $input['filter'] ?? 'all';
$message = $input['message'];
$db = Database::getInstance();
$whatsappService = new WhatsAppService();
// Construir query según filtro
$whereClause = "WHERE u.status = 'active'";
switch ($filter) {
case 'active':
$whereClause .= " AND EXISTS (
SELECT 1 FROM conversations c
WHERE c.user_id = u.id
AND c.created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY)
)";
break;
case 'recent':
$whereClause .= " AND u.created_at >= DATE_SUB(NOW(), INTERVAL 30 DAY)";
break;
}
// Obtener usuarios según filtro
$users = $db->fetchAll(
"SELECT phone_number FROM users u " . $whereClause
);
$sentCount = 0;
$errorCount = 0;
foreach ($users as $user) {
try {
$response = $whatsappService->sendTextMessage($user['phone_number'], $message);
if ($response) {
$sentCount++;
}
// Pequeña pausa para no saturar la API
usleep(100000); // 0.1 segundo
} catch (Exception $e) {
$errorCount++;
error_log("Error sending broadcast to {$user['phone_number']}: " . $e->getMessage());
}
}
echo json_encode([
'success' => true,
'sent_count' => $sentCount,
'error_count' => $errorCount,
'total_users' => count($users)
]);
} catch (Exception $e) {
error_log("Error in send_broadcast.php: " . $e->getMessage());
http_response_code(500);
echo json_encode(['error' => 'Error interno del servidor: ' . $e->getMessage()]);
}
?>
+78
View File
@@ -0,0 +1,78 @@
<?php
/**
* API - Enviar mensaje individual
* Fecha: 13 de noviembre de 2025
*/
require_once '../config/config.php';
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST');
header('Access-Control-Allow-Headers: Content-Type');
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
echo json_encode(['error' => 'Método no permitido']);
exit;
}
try {
$input = json_decode(file_get_contents('php://input'), true);
if (!$input || !isset($input['recipient'])) {
http_response_code(400);
echo json_encode(['error' => 'Datos inválidos']);
exit;
}
$recipient = $input['recipient'];
$type = $input['type'] ?? 'text';
$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;
}
$response = $whatsappService->sendTextMessage($recipient, $input['message']);
break;
case 'template':
if (!isset($input['template']) || empty($input['template'])) {
http_response_code(400);
echo json_encode(['error' => 'Plantilla requerida']);
exit;
}
$language = $input['language'] ?? 'es';
$parameters = $input['parameters'] ?? [];
$response = $whatsappService->sendTemplateMessage($recipient, $input['template'], $language, $parameters);
break;
default:
http_response_code(400);
echo json_encode(['error' => 'Tipo de mensaje no válido']);
exit;
}
if ($response) {
echo json_encode([
'success' => true,
'message' => 'Mensaje enviado correctamente',
'whatsapp_response' => $response
]);
} else {
http_response_code(500);
echo json_encode(['error' => 'Error enviando mensaje']);
}
} 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()]);
}
?>
+221
View File
@@ -0,0 +1,221 @@
<?php
/**
* Webhook para recibir mensajes de WhatsApp
* Fecha: 13 de noviembre de 2025
*/
require_once '../config/config.php';
// Headers para API
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST');
header('Access-Control-Allow-Headers: Content-Type');
class WhatsAppWebhook {
private $db;
private $whatsappService;
private $botService;
public function __construct() {
$this->db = Database::getInstance();
$this->whatsappService = new WhatsAppService();
$this->botService = new BotService();
}
public function handleRequest() {
$method = $_SERVER['REQUEST_METHOD'];
if ($method === 'GET') {
$this->verifyWebhook();
} elseif ($method === 'POST') {
$this->processIncomingMessage();
} else {
http_response_code(405);
echo json_encode(['error' => 'Método no permitido']);
}
}
private function verifyWebhook() {
$verifyToken = $_GET['hub_verify_token'] ?? '';
$challenge = $_GET['hub_challenge'] ?? '';
$mode = $_GET['hub_mode'] ?? '';
if ($mode === 'subscribe' && $verifyToken === WEBHOOK_VERIFY_TOKEN) {
echo $challenge;
exit;
} else {
http_response_code(403);
echo json_encode(['error' => 'Token de verificación inválido']);
}
}
private function processIncomingMessage() {
$input = file_get_contents('php://input');
$data = json_decode($input, true);
// Registrar webhook en logs
$this->logWebhook($input, json_encode(['status' => 'received']), 200);
if (!$data || !isset($data['entry'])) {
http_response_code(400);
echo json_encode(['error' => 'Datos inválidos']);
return;
}
try {
foreach ($data['entry'] as $entry) {
if (isset($entry['changes'])) {
foreach ($entry['changes'] as $change) {
if ($change['field'] === 'messages') {
$this->processMessages($change['value']);
}
}
}
}
echo json_encode(['status' => 'success']);
} catch (Exception $e) {
error_log("Error processing webhook: " . $e->getMessage());
http_response_code(500);
echo json_encode(['error' => 'Error interno del servidor']);
}
}
private function processMessages($value) {
if (!isset($value['messages'])) {
return;
}
foreach ($value['messages'] as $message) {
$phoneNumber = $message['from'];
$messageId = $message['id'];
$timestamp = $message['timestamp'];
// Verificar si ya procesamos este mensaje
$existing = $this->db->fetch(
"SELECT id FROM conversations WHERE message_id = :message_id",
['message_id' => $messageId]
);
if ($existing) {
continue; // Ya procesamos este mensaje
}
// Obtener o crear usuario
$user = $this->getUserByPhone($phoneNumber);
if (!$user) {
$userId = $this->createUser($phoneNumber);
$user = $this->getUserById($userId);
}
// Procesar diferentes tipos de mensaje
$messageText = '';
$messageType = 'text';
$mediaUrl = null;
if (isset($message['text'])) {
$messageText = $message['text']['body'];
$messageType = 'text';
} elseif (isset($message['image'])) {
$messageText = $message['image']['caption'] ?? '';
$messageType = 'image';
$mediaUrl = $message['image']['id'];
} elseif (isset($message['audio'])) {
$messageType = 'audio';
$mediaUrl = $message['audio']['id'];
} elseif (isset($message['video'])) {
$messageText = $message['video']['caption'] ?? '';
$messageType = 'video';
$mediaUrl = $message['video']['id'];
} elseif (isset($message['document'])) {
$messageText = $message['document']['filename'] ?? '';
$messageType = 'document';
$mediaUrl = $message['document']['id'];
}
// Guardar mensaje en base de datos
$this->saveMessage([
'user_id' => $user['id'],
'message_id' => $messageId,
'direction' => 'incoming',
'message_type' => $messageType,
'content' => $messageText,
'media_url' => $mediaUrl,
'status' => 'received'
]);
// Procesar con bot
$this->botService->processMessage($user, $messageText, $messageType);
}
// Procesar estados de mensajes (entregado, leído, etc.)
if (isset($value['statuses'])) {
$this->processMessageStatuses($value['statuses']);
}
}
private function processMessageStatuses($statuses) {
foreach ($statuses as $status) {
$messageId = $status['id'];
$newStatus = $status['status']; // sent, delivered, read, failed
$this->db->update(
'conversations',
['status' => $newStatus],
'message_id = :message_id',
['message_id' => $messageId]
);
}
}
private function getUserByPhone($phoneNumber) {
return $this->db->fetch(
"SELECT * FROM users WHERE phone_number = :phone",
['phone' => $phoneNumber]
);
}
private function getUserById($userId) {
return $this->db->fetch(
"SELECT * FROM users WHERE id = :id",
['id' => $userId]
);
}
private function createUser($phoneNumber) {
return $this->db->insert('users', [
'phone_number' => $phoneNumber,
'status' => 'active',
'created_at' => date('Y-m-d H:i:s')
]);
}
private function saveMessage($messageData) {
return $this->db->insert('conversations', $messageData);
}
private function logWebhook($requestBody, $responseBody, $statusCode) {
if (ENABLE_LOGGING) {
$this->db->insert('webhook_logs', [
'request_body' => $requestBody,
'response_body' => $responseBody,
'status_code' => $statusCode,
'ip_address' => $_SERVER['REMOTE_ADDR'] ?? 'unknown',
'created_at' => date('Y-m-d H:i:s')
]);
}
}
}
// Procesar la solicitud
try {
$webhook = new WhatsAppWebhook();
$webhook->handleRequest();
} catch (Exception $e) {
error_log("Fatal error in webhook: " . $e->getMessage());
http_response_code(500);
echo json_encode(['error' => 'Error fatal del servidor']);
}
?>