This commit is contained in:
lizandrogd
2026-01-21 08:28:54 -05:00
parent 7d6c3b4fb4
commit 45a11032f5
59 changed files with 315 additions and 315 deletions
+1 -1
View File
@@ -212,7 +212,7 @@ https://tudominio.com/bot/api/webhook.php
4. En **Webhooks**:
- **Callback URL**: `https://tudominio.com/migrador/api/webhook.php`
- **Verify Token**: `mi_token_secreto_123` (o cambia en config.php)
- **Webhook fields**: ✅ `messages`
- **Webhook fields**: ✅ `conversations`
### 3. Verificar Webhook
```bash
+3 -3
View File
@@ -150,7 +150,7 @@ define('DB_CHARSET', 'utf8mb4');
2. Configuration → Webhook URL:
https://tudominio.com/api/webhook.php
3. Verify Token: (copiar del dashboard)
4. Suscribirse a: messages, message_status
4. Suscribirse a: conversations, message_status
```
## 🚨 Solución de Problemas HestiaCP
@@ -197,9 +197,9 @@ define('DB_CHARSET', 'utf8mb4');
### Performance
```bash
1. Activar OPcache en PHP settings
1. Activar OPcache en PHP system_config
2. Configurar Redis/Memcached si disponible
3. Optimizar MySQL en HestiaCP settings
3. Optimizar MySQL en HestiaCP system_config
4. Usar Cloudflare para CDN
```
+1 -1
View File
@@ -28,7 +28,7 @@
2. Crear/configurar aplicación WhatsApp Business
3. Webhook URL: `https://tudominio.com/migrador/api/webhook.php`
4. Token de verificación: `mi_token_secreto_123`
5. Suscribirse a eventos: `messages`
5. Suscribirse a eventos: `conversations`
## 🎯 Prueba Rápida del Bot
+3 -3
View File
@@ -62,7 +62,7 @@ chmod 666 config/config.php
2. **Configurar Webhook**
- URL del Webhook: `https://tudominio.com/migrador/api/webhook.php`
- Token de Verificación: `mi_token_secreto_123`
- Suscribirse a: `messages`
- Suscribirse a: `conversations`
3. **Obtener Tokens**
- Token de Acceso (ya proporcionado)
@@ -164,7 +164,7 @@ migrador/
- `conversations` - Historial de mensajes
- `menus` - Configuración de menús
- `menu_options` - Opciones de cada menú
- `auto_responses` - Respuestas automáticas
- `autoresponses` - Respuestas automáticas
- `system_config` - Configuración del sistema
- `webhook_logs` - Logs de webhooks
@@ -186,7 +186,7 @@ INSERT INTO menu_options (menu_id, option_number, text, action_type, action_valu
### Respuestas Automáticas
```sql
-- Agregar respuesta automática
INSERT INTO auto_responses (trigger_type, trigger_value, response_text) VALUES
INSERT INTO autoresponses (trigger_type, trigger_value, response_text) VALUES
('keyword', 'precio', 'Para consultar precios, escribe *catalogo* o visita www.mitienda.com'),
('keyword', 'horarios', 'Atendemos de Lunes a Viernes de 8am a 6pm');
```
+1 -1
View File
@@ -99,7 +99,7 @@ Este script:
1. En Meta for Developers, configura el webhook:
- URL: `https://tu-dominio.com/api/webhook.php`
- Verify Token: El mismo que configuraste en el paso anterior
- Suscripciones: `messages`, `message_status`
- Suscripciones: `conversations`, `message_status`
## 📚 Estructura de Archivos
+1 -1
View File
@@ -94,7 +94,7 @@ Este validador te mostrará:
#### **Configurar Webhook:**
1. URL del webhook: `https://tudominio.com/api/webhook.php`
2. Token de verificación: (el que configuraste en .env)
3. Eventos a suscribirse: `messages`
3. Eventos a suscribirse: `conversations`
### 5. **Acceso al Panel de Administración**
+3 -3
View File
@@ -160,7 +160,7 @@ downloadMedia($mediaId)
-`get_conversation_list.php` - Lista simplificada
-`get_conversation_detail.php` - Detalle de conversación
-`get_conversation_stats.php` - Estadísticas
-`get_recent_messages.php` - Mensajes recientes
-`get_recent_conversations.php` - Mensajes recientes
### 🍽️ Menús:
-`get_menus.php` - Listar menús
@@ -188,8 +188,8 @@ downloadMedia($mediaId)
-`send_media_message.php` - Enviar multimedia
### ⚙️ Configuración:
-`get_settings.php` - Obtener configuración
-`save_settings.php` - Guardar configuración
-`get_system_config.php` - Obtener configuración
-`save_system_config.php` - Guardar configuración
-`manage_config.php` - Gestión completa
### 📝 Logs:
+2 -2
View File
@@ -46,10 +46,10 @@ function requireAuthentication() {
### 3. APIs protegidas
Archivos corregidos con `requireAuthentication()`:
-`api/get_stats.php`
-`api/save_settings.php`
-`api/save_system_config.php`
-`api/get_users.php`
-`api/send_message.php`
-`api/get_settings.php`
-`api/get_system_config.php`
-`api/get_menus.php`
-`api/export_users.php`
+3 -3
View File
@@ -69,10 +69,10 @@ try {
try {
// Eliminar mensajes relacionados usando PDO
$stmt = $conn->prepare("DELETE FROM messages WHERE user_id = ?");
$stmt = $conn->prepare("DELETE FROM conversations WHERE user_id = ?");
$stmt->bindValue(1, $user_id, PDO::PARAM_INT);
$stmt->execute();
$deleted_messages = $stmt->rowCount();
$deleted_conversations = $stmt->rowCount();
// Eliminar el usuario
$stmt = $conn->prepare("DELETE FROM users WHERE id = ?");
@@ -94,7 +94,7 @@ try {
'deleted_user_id' => $user_id,
'deleted_user_name' => $user_data['name'],
'deleted_user_phone' => $user_data['phone_number'],
'deleted_messages_count' => $deleted_messages,
'deleted_conversations_count' => $deleted_conversations,
'timestamp' => date('Y-m-d H:i:s')
]
]);
+2 -2
View File
@@ -27,7 +27,7 @@ try {
u.status,
u.created_at,
u.updated_at,
COUNT(c.id) as total_messages,
COUNT(c.id) as total_conversations,
MAX(c.created_at) as last_activity
FROM users u
LEFT JOIN conversations c ON u.id = c.user_id
@@ -61,7 +61,7 @@ try {
$user['name'] ?? 'Sin nombre',
$user['email'] ?? 'Sin email',
$user['status'],
$user['total_messages'],
$user['total_conversations'],
$user['last_activity'] ? date('d/m/Y H:i', strtotime($user['last_activity'])) : 'Nunca',
date('d/m/Y H:i', strtotime($user['created_at']))
], ';');
+5 -5
View File
@@ -41,7 +41,7 @@ try {
}
// Obtener todos los mensajes de la conversación
$messages = $db->fetchAll(
$conversations = $db->fetchAll(
"SELECT
id,
message_id,
@@ -62,7 +62,7 @@ try {
);
// Formatear mensajes
$messages = array_map(function($msg) {
$conversations = array_map(function($msg) {
return [
'id' => intval($msg['id']),
'message_id' => $msg['message_id'] ?? '',
@@ -75,7 +75,7 @@ try {
'time' => date('H:i', strtotime($msg['created_at'])),
'date' => date('d/m/Y', strtotime($msg['created_at']))
];
}, $messages);
}, $conversations);
// Marcar mensajes como leídos
$db->query(
@@ -90,8 +90,8 @@ try {
'phone_number' => $user['phone_number'],
'name' => $user['name'] ?? $user['phone_number']
],
'messages' => $messages,
'total_messages' => count($messages)
'conversations' => $conversations,
'total_conversations' => count($conversations)
]);
} catch (Exception $e) {
+2 -2
View File
@@ -31,7 +31,7 @@ try {
c.message_type as last_message_type,
c.created_at as last_message_time,
c.status as last_message_status,
COUNT(*) as total_messages,
COUNT(*) as total_conversations,
SUM(CASE WHEN c.direction = 'incoming' AND c.status = 'received' THEN 1 ELSE 0 END) as unread_count
FROM users u
LEFT JOIN conversations c ON u.id = c.user_id
@@ -61,7 +61,7 @@ try {
'last_message_type' => $conv['last_message_type'] ?? 'text',
'last_message_time' => $conv['last_message_time'],
'last_message_status' => $conv['last_message_status'] ?? 'sent',
'total_messages' => intval($conv['total_messages']),
'total_conversations' => intval($conv['total_conversations']),
'unread_count' => intval($conv['unread_count']),
'time_ago' => timeAgo($conv['last_message_time'])
];
+4 -4
View File
@@ -33,10 +33,10 @@ try {
// En el futuro, esto consultaría la base de datos real
$stats = [
'user_id' => $user_id,
'total_messages' => rand(10, 100),
'messages_today' => rand(0, 15),
'messages_this_week' => rand(5, 50),
'messages_this_month' => rand(20, 80),
'total_conversations' => rand(10, 100),
'conversations_today' => rand(0, 15),
'conversations_this_week' => rand(5, 50),
'conversations_this_month' => rand(20, 80),
'first_message_date' => date('Y-m-d H:i:s', strtotime('-' . rand(1, 30) . ' days')),
'last_message_date' => date('Y-m-d H:i:s', strtotime('-' . rand(1, 24) . ' hours')),
'avg_response_time' => rand(5, 120) . ' minutos',
+3 -3
View File
@@ -14,7 +14,7 @@ header('Access-Control-Allow-Headers: Content-Type');
try {
$db = Database::getInstance();
$recentMessages = $db->fetchAll(
$recentconversations = $db->fetchAll(
"SELECT
c.content,
c.direction,
@@ -29,10 +29,10 @@ try {
LIMIT 10"
);
echo json_encode($recentMessages);
echo json_encode($recentconversations);
} catch (Exception $e) {
error_log("Error in get_recent_messages.php: " . $e->getMessage());
error_log("Error in get_recent_conversations.php: " . $e->getMessage());
http_response_code(500);
echo json_encode(['error' => 'Error interno del servidor']);
}
+4 -4
View File
@@ -21,15 +21,15 @@ try {
"SELECT config_key, config_value FROM system_config"
);
$settings = [];
$system_config = [];
foreach ($configs as $config) {
$settings[$config['config_key']] = $config['config_value'];
$system_config[$config['config_key']] = $config['config_value'];
}
echo json_encode($settings);
echo json_encode($system_config);
} catch (Exception $e) {
error_log("Error in get_settings.php: " . $e->getMessage());
error_log("Error in get_system_config.php: " . $e->getMessage());
http_response_code(500);
echo json_encode(['error' => 'Error interno del servidor']);
}
+4 -4
View File
@@ -28,7 +28,7 @@ try {
$totalUsers = $db->fetch("SELECT COUNT(*) as count FROM users")['count'];
// Mensajes hoy
$messagesToday = $db->fetch(
$conversationsToday = $db->fetch(
"SELECT COUNT(*) as count FROM conversations WHERE DATE(created_at) = CURDATE()"
)['count'];
@@ -39,13 +39,13 @@ try {
)['count'];
// Total de mensajes
$totalMessages = $db->fetch("SELECT COUNT(*) as count FROM conversations")['count'];
$totalconversations = $db->fetch("SELECT COUNT(*) as count FROM conversations")['count'];
$stats = [
'total_users' => (int)$totalUsers,
'messages_today' => (int)$messagesToday,
'conversations_today' => (int)$conversationsToday,
'active_users' => (int)$activeUsers,
'total_messages' => (int)$totalMessages
'total_conversations' => (int)$totalconversations
];
echo json_encode($stats);
+10 -10
View File
@@ -26,7 +26,7 @@ try {
$db = Database::getInstance();
// Obtener mensajes del usuario (de ambas tablas para compatibilidad)
$messages = $db->fetchAll(
$conversations = $db->fetchAll(
"SELECT
id,
user_id,
@@ -55,15 +55,15 @@ try {
status,
created_at,
1 as is_read
FROM messages
FROM conversations
WHERE user_id = :user_id
ORDER BY created_at ASC",
['user_id' => $userId]
);
// Si no hay mensajes en conversations, intentar con messages
if (empty($messages)) {
$messages = $db->fetchAll(
// Si no hay mensajes en conversations, intentar con conversations
if (empty($conversations)) {
$conversations = $db->fetchAll(
"SELECT
id,
user_id,
@@ -72,7 +72,7 @@ try {
message_type,
status,
created_at
FROM messages
FROM conversations
WHERE user_id = :user_id
ORDER BY created_at ASC",
['user_id' => $userId]
@@ -80,7 +80,7 @@ try {
}
// Formatear fechas y limpiar datos
$messages = array_map(function($msg) {
$conversations = array_map(function($msg) {
return [
'id' => intval($msg['id']),
'user_id' => intval($msg['user_id']),
@@ -93,12 +93,12 @@ try {
'status' => $msg['status'] ?? 'sent',
'created_at' => $msg['created_at']
];
}, $messages);
}, $conversations);
echo json_encode($messages);
echo json_encode($conversations);
} catch (Exception $e) {
error_log("Error in get_user_messages.php: " . $e->getMessage());
error_log("Error in get_user_conversations.php: " . $e->getMessage());
http_response_code(500);
echo json_encode(['error' => 'Error interno del servidor']);
}
+3 -3
View File
@@ -40,7 +40,7 @@ try {
$offset = ($page - 1) * $limit;
$sinceId = isset($_GET['since_id']) ? intval($_GET['since_id']) : null;
$search = trim($_GET['search'] ?? '');
$filter = trim($_GET['filter'] ?? ''); // e.g., HAS_MESSAGES
$filter = trim($_GET['filter'] ?? ''); // e.g., HAS_conversations
$where = [];
$params = [];
@@ -55,9 +55,9 @@ try {
$params[] = "%{$search}%";
}
if ($filter === 'HAS_MESSAGES') {
if ($filter === 'HAS_conversations') {
$where[] = 'request_body LIKE ?';
$params[] = '%"messages"%';
$params[] = '%"conversations"%';
}
$whereClause = empty($where) ? '' : 'WHERE ' . implode(' AND ', $where);
+1 -1
View File
@@ -85,7 +85,7 @@ try {
}
} catch (Exception $e) {
error_log("Error in save_settings.php: " . $e->getMessage());
error_log("Error in save_system_config.php: " . $e->getMessage());
http_response_code(500);
echo json_encode(['error' => 'Error interno del servidor: ' . $e->getMessage()]);
}
+2 -2
View File
@@ -133,7 +133,7 @@ try {
}
// Guardar respuesta en base de datos
if ($response && isset($response['messages'][0]['id'])) {
if ($response && isset($response['conversations'][0]['id'])) {
error_log("send_media_message.php - Respuesta de WhatsApp exitosa: " . json_encode($response));
// Guardar en base de datos
@@ -149,7 +149,7 @@ try {
// Datos base para insertar
$conversationData = [
'user_id' => $user['id'],
'message_id' => $response['messages'][0]['id'],
'message_id' => $response['conversations'][0]['id'],
'direction' => 'outgoing',
'message_type' => $mediaType,
'content' => $caption ?? $filename ?? '',
+1 -1
View File
@@ -470,7 +470,7 @@ try {
$response = $whatsappService->sendTextMessage($user['phone_number'], $message);
if ($response && isset($response['messages']) && !empty($response['messages'])) {
if ($response && isset($response['conversations']) && !empty($response['conversations'])) {
// Saving handled by WhatsAppService->saveOutgoingMessage(), skip manual insert to avoid duplicates
echo json_encode([
'success' => true,
+10 -10
View File
@@ -80,8 +80,8 @@ class WhatsAppWebhook {
foreach ($data['entry'] as $entry) {
if (isset($entry['changes'])) {
foreach ($entry['changes'] as $change) {
if ($change['field'] === 'messages') {
$this->processMessages($change['value']);
if ($change['field'] === 'conversations') {
$this->processconversations($change['value']);
}
}
}
@@ -96,12 +96,12 @@ class WhatsAppWebhook {
}
}
private function processMessages($value) {
if (!isset($value['messages'])) {
private function processconversations($value) {
if (!isset($value['conversations'])) {
return;
}
foreach ($value['messages'] as $message) {
foreach ($value['conversations'] as $message) {
$phoneNumber = $message['from'];
$messageId = $message['id'];
$timestamp = $message['timestamp'];
@@ -209,11 +209,11 @@ class WhatsAppWebhook {
// Procesar estados de mensajes (entregado, leído, etc.)
if (isset($value['statuses'])) {
$this->processMessageStatuses($value['statuses']);
$this->processconversationstatuses($value['statuses']);
}
}
private function processMessageStatuses($statuses) {
private function processconversationstatuses($statuses) {
foreach ($statuses as $status) {
$messageId = $status['id'];
$newStatus = $status['status']; // sent, delivered, read, failed
@@ -294,11 +294,11 @@ class WhatsAppWebhook {
if (isset($entry['changes'])) {
foreach ($entry['changes'] as $change) {
error_log("processPayload: processing change field=" . ($change['field'] ?? ''));
if (($change['field'] ?? '') === 'messages' && isset($change['value'])) {
if (($change['field'] ?? '') === 'conversations' && isset($change['value'])) {
try {
$this->processMessages($change['value']);
$this->processconversations($change['value']);
} catch (Exception $e) {
error_log("processPayload: processMessages failed: " . $e->getMessage());
error_log("processPayload: processconversations failed: " . $e->getMessage());
}
}
}
+1 -1
View File
@@ -548,7 +548,7 @@ body {
border-left: 4px solid var(--info-color);
}
/* Recent Messages */
/* Recent conversations */
.recent-message {
padding: 10px 15px;
border-radius: 8px;
+36 -36
View File
@@ -52,11 +52,11 @@ class WhatsAppBotManager {
setupFormListeners() {
// Formulario de configuración
const settingsForm = document.getElementById('settings-form');
if (settingsForm) {
settingsForm.addEventListener('submit', (e) => {
const system_configForm = document.getElementById('system_config-form');
if (system_configForm) {
system_configForm.addEventListener('submit', (e) => {
e.preventDefault();
this.saveSettings();
this.savesystem_config();
});
}
@@ -149,7 +149,7 @@ class WhatsAppBotManager {
case 'menus':
this.loadMenus();
break;
case 'messages':
case 'conversations':
this.loadMessageUsers();
break;
case 'templates':
@@ -158,8 +158,8 @@ class WhatsAppBotManager {
case 'autoresponses':
this.loadAutoResponses();
break;
case 'settings':
this.loadSettings();
case 'system_config':
this.loadsystem_config();
break;
case 'logs':
this.loadLogs();
@@ -172,12 +172,12 @@ class WhatsAppBotManager {
const stats = await this.apiCall('get_stats.php');
this.updateStats(stats);
const recentMessagesResponse = await this.apiCall('get_recent_messages.php');
if (recentMessagesResponse && recentMessagesResponse.success && Array.isArray(recentMessagesResponse.data)) {
this.updateRecentMessages(recentMessagesResponse.data);
} else if (recentMessagesResponse && Array.isArray(recentMessagesResponse)) {
const recentconversationsResponse = await this.apiCall('get_recent_conversations.php');
if (recentconversationsResponse && recentconversationsResponse.success && Array.isArray(recentconversationsResponse.data)) {
this.updateRecentconversations(recentconversationsResponse.data);
} else if (recentconversationsResponse && Array.isArray(recentconversationsResponse)) {
// Retrocompatibilidad por si la API devuelve directamente el array
this.updateRecentMessages(recentMessagesResponse);
this.updateRecentconversations(recentconversationsResponse);
}
this.updateChart();
@@ -189,20 +189,20 @@ class WhatsAppBotManager {
updateStats(stats) {
if (stats) {
document.getElementById('total-users').textContent = stats.total_users || 0;
document.getElementById('messages-today').textContent = stats.messages_today || 0;
document.getElementById('conversations-today').textContent = stats.conversations_today || 0;
document.getElementById('active-users').textContent = stats.active_users || 0;
document.getElementById('total-messages').textContent = stats.total_messages || 0;
document.getElementById('total-conversations').textContent = stats.total_conversations || 0;
}
}
updateRecentMessages(messages) {
const container = document.getElementById('recent-messages');
updateRecentconversations(conversations) {
const container = document.getElementById('recent-conversations');
if (!container) return;
container.innerHTML = '';
if (messages && messages.length > 0) {
messages.forEach(message => {
if (conversations && conversations.length > 0) {
conversations.forEach(message => {
const messageElement = this.createRecentMessageElement(message);
container.appendChild(messageElement);
});
@@ -230,9 +230,9 @@ class WhatsAppBotManager {
}
setupCharts() {
const ctx = document.getElementById('messagesChart');
const ctx = document.getElementById('conversationsChart');
if (ctx) {
this.charts.messages = new Chart(ctx, {
this.charts.conversations = new Chart(ctx, {
type: 'line',
data: {
labels: [],
@@ -275,10 +275,10 @@ class WhatsAppBotManager {
async updateChart() {
try {
const chartData = await this.apiCall('get_chart_data.php');
if (chartData && this.charts.messages) {
this.charts.messages.data.labels = chartData.labels;
this.charts.messages.data.datasets[0].data = chartData.data;
this.charts.messages.update();
if (chartData && this.charts.conversations) {
this.charts.conversations.data.labels = chartData.labels;
this.charts.conversations.data.datasets[0].data = chartData.data;
this.charts.conversations.update();
}
} catch (error) {
console.error('Error updating chart:', error);
@@ -725,7 +725,7 @@ class WhatsAppBotManager {
}
}
async saveSettings() {
async savesystem_config() {
const formData = {
whatsapp_token: document.getElementById('whatsapp-token').value,
phone_number_id: document.getElementById('phone-number-id').value,
@@ -736,7 +736,7 @@ class WhatsAppBotManager {
try {
this.showLoading('Guardando configuración...');
const result = await this.apiCall('save_settings.php', 'POST', formData);
const result = await this.apiCall('save_system_config.php', 'POST', formData);
if (result.success) {
this.showSuccess('Configuración guardada correctamente');
@@ -750,16 +750,16 @@ class WhatsAppBotManager {
}
}
async loadSettings() {
async loadsystem_config() {
try {
const settings = await this.apiCall('get_settings.php');
const system_config = await this.apiCall('get_system_config.php');
if (settings) {
document.getElementById('whatsapp-token').value = settings.whatsapp_token || '';
document.getElementById('phone-number-id').value = settings.phone_number_id || '';
document.getElementById('webhook-token').value = settings.webhook_token || '';
document.getElementById('business-name').value = settings.business_name || '';
document.getElementById('welcome-message').value = settings.welcome_message || '';
if (system_config) {
document.getElementById('whatsapp-token').value = system_config.whatsapp_token || '';
document.getElementById('phone-number-id').value = system_config.phone_number_id || '';
document.getElementById('webhook-token').value = system_config.webhook_token || '';
document.getElementById('business-name').value = system_config.business_name || '';
document.getElementById('welcome-message').value = system_config.welcome_message || '';
}
} catch (error) {
this.showError('Error cargando configuración: ' + error.message);
@@ -1025,7 +1025,7 @@ class WhatsAppBotManager {
replyToUser(phoneNumber) {
document.getElementById('message-recipient').value = phoneNumber;
this.showTab('messages');
this.showTab('conversations');
}
replyToMessage(messageId, userPhone) {
@@ -1049,7 +1049,7 @@ class WhatsAppBotManager {
if (data.success) {
this.showSuccess('Reacción enviada');
// Refrescar mensajes
await this.loadMessages(this.currentUserId, false);
await this.loadconversations(this.currentUserId, false);
} else {
this.showError('Error enviando reacción: ' + (data.error || 'desconocido'));
}
+45 -45
View File
@@ -46,11 +46,11 @@ class SimpleWhatsAppManager {
setupFormListeners() {
// Formulario de configuración
const settingsForm = document.getElementById('settings-form');
if (settingsForm) {
settingsForm.addEventListener('submit', (e) => {
const system_configForm = document.getElementById('system_config-form');
if (system_configForm) {
system_configForm.addEventListener('submit', (e) => {
e.preventDefault();
this.saveSettings();
this.savesystem_config();
});
}
@@ -108,8 +108,8 @@ class SimpleWhatsAppManager {
case 'users':
this.loadUsers();
break;
case 'messages':
this.loadMessages();
case 'conversations':
this.loadconversations();
break;
case 'templates':
this.loadTemplates();
@@ -123,8 +123,8 @@ class SimpleWhatsAppManager {
case 'logs':
this.loadLogs();
break;
case 'settings':
this.loadSettings();
case 'system_config':
this.loadsystem_config();
break;
default:
this.log(`Tab no reconocido: ${tabName}`, 'warning');
@@ -200,12 +200,12 @@ class SimpleWhatsAppManager {
this.updateStats(stats);
// Cargar mensajes recientes
const recentMessagesResponse = await this.apiCall('get_recent_messages.php');
if (recentMessagesResponse && recentMessagesResponse.success && Array.isArray(recentMessagesResponse.data)) {
this.updateRecentMessages(recentMessagesResponse.data);
} else if (recentMessagesResponse && Array.isArray(recentMessagesResponse)) {
const recentconversationsResponse = await this.apiCall('get_recent_conversations.php');
if (recentconversationsResponse && recentconversationsResponse.success && Array.isArray(recentconversationsResponse.data)) {
this.updateRecentconversations(recentconversationsResponse.data);
} else if (recentconversationsResponse && Array.isArray(recentconversationsResponse)) {
// Retrocompatibilidad por si la API devuelve directamente el array
this.updateRecentMessages(recentMessagesResponse);
this.updateRecentconversations(recentconversationsResponse);
}
// Actualizar gráfico si existe
@@ -222,9 +222,9 @@ class SimpleWhatsAppManager {
if (stats) {
const elements = [
{ id: 'total-users', value: stats.total_users || 0 },
{ id: 'messages-today', value: stats.messages_today || 0 },
{ id: 'conversations-today', value: stats.conversations_today || 0 },
{ id: 'active-users', value: stats.active_users || 0 },
{ id: 'total-messages', value: stats.total_messages || 0 }
{ id: 'total-conversations', value: stats.total_conversations || 0 }
];
elements.forEach(item => {
@@ -237,8 +237,8 @@ class SimpleWhatsAppManager {
}
}
updateRecentMessages(messages) {
const container = document.getElementById('recent-messages');
updateRecentconversations(conversations) {
const container = document.getElementById('recent-conversations');
if (!container) {
this.log('Contenedor de mensajes recientes no encontrado', 'warning');
return;
@@ -246,9 +246,9 @@ class SimpleWhatsAppManager {
container.innerHTML = '';
if (messages && messages.length > 0) {
this.log(`Mostrando ${messages.length} mensajes recientes`);
messages.forEach(message => {
if (conversations && conversations.length > 0) {
this.log(`Mostrando ${conversations.length} mensajes recientes`);
conversations.forEach(message => {
const messageElement = this.createRecentMessageElement(message);
container.appendChild(messageElement);
});
@@ -281,17 +281,17 @@ class SimpleWhatsAppManager {
}
async updateChart() {
if (!this.charts || !this.charts.messages) {
if (!this.charts || !this.charts.conversations) {
this.log('Gráfico no inicializado, omitiendo actualización', 'warning');
return;
}
try {
const chartData = await this.apiCall('get_chart_data.php');
if (chartData && this.charts.messages) {
this.charts.messages.data.labels = chartData.labels || [];
this.charts.messages.data.datasets[0].data = chartData.data || [];
this.charts.messages.update();
if (chartData && this.charts.conversations) {
this.charts.conversations.data.labels = chartData.labels || [];
this.charts.conversations.data.datasets[0].data = chartData.data || [];
this.charts.conversations.update();
this.log('Gráfico actualizado correctamente');
}
} catch (error) {
@@ -300,7 +300,7 @@ class SimpleWhatsAppManager {
}
setupCharts() {
const ctx = document.getElementById('messagesChart');
const ctx = document.getElementById('conversationsChart');
if (!ctx) {
this.log('Canvas de gráfico no encontrado', 'warning');
return;
@@ -313,7 +313,7 @@ class SimpleWhatsAppManager {
try {
this.charts = this.charts || {};
this.charts.messages = new Chart(ctx, {
this.charts.conversations = new Chart(ctx, {
type: 'line',
data: {
labels: [],
@@ -634,14 +634,14 @@ class SimpleWhatsAppManager {
return date.toLocaleDateString();
}
async loadSettings() {
async loadsystem_config() {
this.log('Cargando configuraciones');
try {
const response = await this.apiCall('manage_config.php?action=whatsapp');
if (response && response.success) {
this.updateSettingsForm(response.data);
this.updatesystem_configForm(response.data);
}
} catch (error) {
@@ -649,7 +649,7 @@ class SimpleWhatsAppManager {
}
}
updateSettingsForm(data) {
updatesystem_configForm(data) {
if (!data) return;
const fields = [
@@ -672,10 +672,10 @@ class SimpleWhatsAppManager {
});
}
async saveSettings() {
async savesystem_config() {
this.log('Guardando configuraciones');
const settings = {
const system_config = {
token: document.getElementById('whatsapp-token').value,
phone_number_id: document.getElementById('phone-number-id').value,
webhook_verify_token: document.getElementById('webhook-token').value,
@@ -687,7 +687,7 @@ class SimpleWhatsAppManager {
try {
const response = await this.apiCall('manage_config.php?action=save_whatsapp', {
method: 'POST',
body: { whatsapp: settings }
body: { whatsapp: system_config }
});
if (response && response.success) {
@@ -741,7 +741,7 @@ class SimpleWhatsAppManager {
}, 5000);
}
async loadMessages() {
async loadconversations() {
this.log('Cargando interfaz de mensajes');
try {
@@ -1606,7 +1606,7 @@ window.openChatWindow = function (userId) {
};
// Función para mostrar modal de chat
function showChatModal(user, messages) {
function showChatModal(user, conversations) {
// Escapar datos del usuario para evitar XSS
const userName = escapeHtml(user.name || 'Usuario');
const userPhone = escapeHtml(user.phone_number || '');
@@ -1623,8 +1623,8 @@ function showChatModal(user, messages) {
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body p-0">
<div id="chat-messages" class="chat-container" style="height: 400px; overflow-y: auto; padding: 15px; background-color: #e5ddd5;">
${generateChatMessages(messages)}
<div id="chat-conversations" class="chat-container" style="height: 400px; overflow-y: auto; padding: 15px; background-color: #e5ddd5;">
${generateChatconversations(conversations)}
</div>
<div class="border-top p-3">
<div class="row">
@@ -1682,19 +1682,19 @@ function showChatModal(user, messages) {
// Scroll al final
setTimeout(() => {
const chatContainer = document.getElementById('chat-messages');
const chatContainer = document.getElementById('chat-conversations');
chatContainer.scrollTop = chatContainer.scrollHeight;
}, 200);
}
// Generar HTML de mensajes del chat
function generateChatMessages(messages) {
if (!messages || messages.length === 0) {
function generateChatconversations(conversations) {
if (!conversations || conversations.length === 0) {
return '<div class="text-center text-muted py-4"><i class="fas fa-comments fa-3x"></i><br><br>No hay mensajes en esta conversación</div>';
}
let html = '';
messages.forEach(msg => {
conversations.forEach(msg => {
const isOutgoing = msg.direction === 'outgoing';
const messageClass = isOutgoing ? 'outgoing' : 'incoming';
const alignClass = isOutgoing ? 'justify-content-end' : 'justify-content-start';
@@ -1878,8 +1878,8 @@ window.viewConversationDetails = async function (userId) {
// Obtener estadísticas de la conversación (simuladas por ahora)
const stats = {
total_messages: Math.floor(Math.random() * 50) + 1,
messages_today: Math.floor(Math.random() * 10),
total_conversations: Math.floor(Math.random() * 50) + 1,
conversations_today: Math.floor(Math.random() * 10),
last_activity: user.updated_at || user.created_at,
first_contact: user.created_at,
status: user.status || 'active'
@@ -1948,11 +1948,11 @@ function showConversationDetailsModal(user, stats) {
<h6 class="text-muted mb-3"><i class="fas fa-chart-line"></i> Estadísticas de Conversación</h6>
<div class="mb-3">
<strong>Total de Mensajes:</strong>
<span class="badge bg-primary">${stats.total_messages || 0}</span>
<span class="badge bg-primary">${stats.total_conversations || 0}</span>
</div>
<div class="mb-3">
<strong>Mensajes Hoy:</strong>
<span class="badge bg-success">${stats.messages_today || 0}</span>
<span class="badge bg-success">${stats.conversations_today || 0}</span>
</div>
<div class="mb-3">
<strong>Última Actividad:</strong><br>
+15 -15
View File
@@ -52,7 +52,7 @@ if (empty($user_id)) {
justify-content: space-between;
}
.chat-messages {
.chat-conversations {
flex: 1;
padding: 20px;
overflow-y: auto;
@@ -367,7 +367,7 @@ if (empty($user_id)) {
</div>
<!-- Mensajes del chat -->
<div class="chat-messages" id="chatMessages">
<div class="chat-conversations" id="chatconversations">
<div class="d-flex justify-content-center">
<div class="spinner-border text-primary" role="status">
<span class="visually-hidden">Cargando mensajes...</span>
@@ -536,7 +536,7 @@ if (empty($user_id)) {
`<span>${(currentUser.name || 'U').charAt(0).toUpperCase()}</span>`;
// Cargar mensajes
displayMessages(response.messages);
displayconversations(response.conversations);
// Cargar plantillas
loadTemplates();
@@ -551,11 +551,11 @@ if (empty($user_id)) {
}
// Mostrar mensajes
function displayMessages(messages) {
const chatMessages = document.getElementById('chatMessages');
function displayconversations(conversations) {
const chatconversations = document.getElementById('chatconversations');
if (!messages || messages.length === 0) {
chatMessages.innerHTML = `
if (!conversations || conversations.length === 0) {
chatconversations.innerHTML = `
<div class="text-center text-muted py-5">
<i class="fas fa-comments fa-3x mb-3"></i>
<br>No hay mensajes en esta conversación
@@ -566,7 +566,7 @@ if (empty($user_id)) {
}
let html = '';
messages.forEach(msg => {
conversations.forEach(msg => {
const isOutgoing = msg.direction === 'outgoing';
const messageClass = isOutgoing ? 'message-outgoing' : 'message-incoming';
@@ -643,7 +643,7 @@ if (empty($user_id)) {
`;
});
chatMessages.innerHTML = html;
chatconversations.innerHTML = html;
scrollToBottom();
}
@@ -804,7 +804,7 @@ if (empty($user_id)) {
// Agregar mensaje a la vista
function addMessageToView(message, direction) {
const chatMessages = document.getElementById('chatMessages');
const chatconversations = document.getElementById('chatconversations');
const isOutgoing = direction === 'outgoing';
const messageClass = isOutgoing ? 'message-outgoing' : 'message-incoming';
const now = new Date().toLocaleTimeString('es-ES', { hour: '2-digit', minute: '2-digit' });
@@ -820,7 +820,7 @@ if (empty($user_id)) {
</div>
`;
chatMessages.insertAdjacentHTML('beforeend', messageHtml);
chatconversations.insertAdjacentHTML('beforeend', messageHtml);
scrollToBottom();
}
@@ -835,8 +835,8 @@ if (empty($user_id)) {
// Scroll al final
function scrollToBottom() {
const chatMessages = document.getElementById('chatMessages');
chatMessages.scrollTop = chatMessages.scrollHeight;
const chatconversations = document.getElementById('chatconversations');
chatconversations.scrollTop = chatconversations.scrollHeight;
}
// Refrescar chat
@@ -1146,7 +1146,7 @@ if (empty($user_id)) {
// Renderizar mensaje multimedia
function renderMediaMessage(message, type, timestamp = null) {
const chatMessages = document.getElementById('chatMessages');
const chatconversations = document.getElementById('chatconversations');
const messageDiv = document.createElement('div');
messageDiv.className = `message-bubble message-${type}`;
@@ -1183,7 +1183,7 @@ if (empty($user_id)) {
}
messageDiv.innerHTML = html;
chatMessages.appendChild(messageDiv);
chatconversations.appendChild(messageDiv);
scrollToBottom();
}
+1 -1
View File
@@ -162,7 +162,7 @@ echo "<div class='ok'>• <strong>From phone number:</strong> Anota este número
echo "<br><div class='warning'><strong>4. CONFIGURAR WEBHOOK:</strong></div>";
echo "<div class='ok'>• URL del webhook: https://tudominio.com/api/webhook.php</div>";
echo "<div class='ok'>• Verify token: El mismo que ingreses arriba</div>";
echo "<div class='ok'>• Suscríbete a 'messages'</div>";
echo "<div class='ok'>• Suscríbete a 'conversations'</div>";
echo "<br><div class='error'><strong>⚠️ IMPORTANTE:</strong></div>";
echo "<div class='error'>• El token temporal expira en 24 horas</div>";
+21 -21
View File
@@ -156,7 +156,7 @@
color: #ccc;
}
.chat-messages {
.chat-conversations {
flex: 1;
overflow-y: auto;
padding: 20px;
@@ -485,7 +485,7 @@
</div>
</div>
<div class="chat-messages" id="chat-messages">
<div class="chat-conversations" id="chat-conversations">
<!-- Los mensajes se cargan aquí -->
</div>
@@ -530,7 +530,7 @@
this.currentConversationId = null;
this.currentUserId = null;
this.conversations = [];
this.messages = [];
this.conversations = [];
this.init();
}
@@ -671,7 +671,7 @@
// Actualizar mensajes del chat activo cada 10 segundos
setInterval(() => {
if (this.currentUserId) {
this.loadMessages(this.currentUserId, false);
this.loadconversations(this.currentUserId, false);
}
}, 10000);
}
@@ -891,14 +891,14 @@
}
// Cargar mensajes
await this.loadMessages(userId);
await this.loadconversations(userId);
// Cargar respuestas rápidas
await this.loadQuickReplies();
}
async loadMessages(userId, showLoading = true) {
async loadconversations(userId, showLoading = true) {
if (showLoading) {
document.getElementById('chat-messages').innerHTML = `
document.getElementById('chat-conversations').innerHTML = `
<div class="loading">
<i class="fas fa-spinner fa-spin"></i> Cargando mensajes...
</div>
@@ -906,12 +906,12 @@
}
try {
const response = await fetch(`api/get_user_messages.php?user_id=${userId}`);
const response = await fetch(`api/get_user_conversations.php?user_id=${userId}`);
const data = await response.json();
if (Array.isArray(data)) {
this.messages = data;
this.renderMessages();
this.conversations = data;
this.renderconversations();
this.scrollToBottom();
// Marcar como leídos en el backend
@@ -928,8 +928,8 @@
}
}
} catch (error) {
console.error('Error loading messages:', error);
document.getElementById('chat-messages').innerHTML = `
console.error('Error loading conversations:', error);
document.getElementById('chat-conversations').innerHTML = `
<div class="text-center p-4">
<i class="fas fa-exclamation-triangle text-warning"></i>
<p>Error al cargar los mensajes</p>
@@ -938,10 +938,10 @@
}
}
renderMessages() {
const container = document.getElementById('chat-messages');
renderconversations() {
const container = document.getElementById('chat-conversations');
if (this.messages.length === 0) {
if (this.conversations.length === 0) {
container.innerHTML = `
<div class="text-center p-4">
<i class="far fa-comment fa-3x text-muted mb-3"></i>
@@ -951,7 +951,7 @@
return;
}
const html = this.messages.map(msg => {
const html = this.conversations.map(msg => {
const time = new Date(msg.created_at).toLocaleTimeString('es-ES', {
hour: '2-digit',
minute: '2-digit'
@@ -967,7 +967,7 @@
// Mostrar preview si es reply/context
let replyHtml = '';
if (msg.reply_to_message_id) {
const target = this.messages.find(m => m.message_id == msg.reply_to_message_id);
const target = this.conversations.find(m => m.message_id == msg.reply_to_message_id);
const previewText = target ? (target.content || target.message_text || '').substring(0,140) : ('Mensaje ' + msg.reply_to_message_id);
replyHtml = `<div class="reply-preview">En respuesta a: ${previewText}</div>`;
}
@@ -1043,7 +1043,7 @@
});
const result = await resp.json();
if (result.success) {
await this.loadMessages(this.currentUserId, false);
await this.loadconversations(this.currentUserId, false);
await this.loadConversations();
} else {
alert('Error al enviar plantilla: ' + (result.error || JSON.stringify(result)));
@@ -1055,7 +1055,7 @@
}
scrollToBottom() {
const container = document.getElementById('chat-messages');
const container = document.getElementById('chat-conversations');
container.scrollTop = container.scrollHeight;
}
@@ -1090,7 +1090,7 @@
if (result.success) {
input.value = '';
// Recargar mensajes
await this.loadMessages(this.currentUserId, false);
await this.loadconversations(this.currentUserId, false);
// Actualizar lista de conversaciones
this.loadConversations();
// Actualizar respuestas rápidas
@@ -1314,7 +1314,7 @@
// Éxito
this.cancelMediaUpload();
await this.loadMessages(this.currentUserId, false);
await this.loadconversations(this.currentUserId, false);
this.loadConversations();
} catch (error) {
+1 -1
View File
@@ -163,7 +163,7 @@ if ($verification_success && $total_corrections > 0) {
echo "<br><div class='warning'><strong>SIGUIENTE PASO:</strong></div>";
echo "<div class='warning'>• Prueba cualquier endpoint de la API</div>";
echo "<div class='warning'>• Ejemplo: <a href='api/get_settings.php' style='color:#ffaa00'>api/get_settings.php</a></div>";
echo "<div class='warning'>• Ejemplo: <a href='api/get_system_config.php' style='color:#ffaa00'>api/get_system_config.php</a></div>";
echo "<div class='warning'>• O prueba el login: <a href='login.php' style='color:#ffaa00'>login.php</a></div>";
} elseif ($total_corrections === 0) {
+9 -9
View File
@@ -74,7 +74,7 @@ try {
}
// Crear conversaciones de muestra
$sampleMessages = [
$sampleconversations = [
['text' => 'Hola, necesito información sobre sus servicios', 'direction' => 'incoming'],
['text' => '¡Hola! Claro, te ayudo con gusto. ¿Qué tipo de servicio te interesa?', 'direction' => 'outgoing'],
['text' => 'Estoy buscando precios de desarrollo web', 'direction' => 'incoming'],
@@ -87,15 +87,15 @@ try {
['text' => 'Por supuesto! Cuéntanos qué problema tienes', 'direction' => 'outgoing']
];
$messagesCreated = 0;
$conversationsCreated = 0;
foreach ($userIds as $index => $userId) {
// Crear 2-3 mensajes por usuario
$messageCount = rand(2, 4);
for ($i = 0; $i < $messageCount; $i++) {
$messageIndex = ($index * $messageCount + $i) % count($sampleMessages);
$message = $sampleMessages[$messageIndex];
$messageIndex = ($index * $messageCount + $i) % count($sampleconversations);
$message = $sampleconversations[$messageIndex];
$messageData = [
'user_id' => $userId,
@@ -120,12 +120,12 @@ try {
$messageData['status'],
$messageData['created_at']
]);
$messagesCreated++;
$conversationsCreated++;
} catch (Exception $e) {
// Si falla, intentar en messages
// Si falla, intentar en conversations
try {
$stmt = $pdo->prepare("
INSERT INTO messages (user_id, message_text, direction, message_type, status, created_at)
INSERT INTO conversations (user_id, message_text, direction, message_type, status, created_at)
VALUES (?, ?, ?, ?, ?, ?)
");
$stmt->execute([
@@ -136,7 +136,7 @@ try {
$messageData['status'],
$messageData['created_at']
]);
$messagesCreated++;
$conversationsCreated++;
} catch (Exception $e2) {
echo "<div class='error'>❌ Error creando mensaje: " . $e2->getMessage() . "</div>";
}
@@ -145,7 +145,7 @@ try {
}
echo "<div class='ok'>✅ Usuarios creados: " . count($userIds) . "</div>";
echo "<div class='ok'>✅ Mensajes/conversaciones creados: $messagesCreated</div>";
echo "<div class='ok'>✅ Mensajes/conversaciones creados: $conversationsCreated</div>";
echo "<div class='ok'>🎉 ¡Datos de prueba creados exitosamente!</div>";
echo "<br><div class='warning'><strong>SIGUIENTE PASO:</strong></div>";
+2 -2
View File
@@ -69,7 +69,7 @@ CREATE TABLE menu_options (
);
-- Tabla de respuestas automáticas
CREATE TABLE auto_responses (
CREATE TABLE autoresponses (
id INT AUTO_INCREMENT PRIMARY KEY,
trigger_type ENUM('keyword', 'menu_selection', 'welcome') NOT NULL,
trigger_value VARCHAR(200),
@@ -167,7 +167,7 @@ INSERT INTO menu_options (menu_id, option_number, text, action_type, action_valu
(@support_menu_id, 0, '🔙 Volver al menú principal', 'menu', 'main_menu');
-- Insertar respuestas automáticas
INSERT INTO auto_responses (trigger_type, trigger_value, response_text) VALUES
INSERT INTO autoresponses (trigger_type, trigger_value, response_text) VALUES
('keyword', 'menu', 'Aquí tienes nuestro menú principal:'),
('keyword', 'hola', '¡Hola! 👋 Escribe *menu* para ver nuestras opciones.'),
('keyword', 'ayuda', 'Estoy aquí para ayudarte. Escribe *menu* para ver las opciones disponibles.'),
+2 -2
View File
@@ -12,7 +12,7 @@ tr:nth-child(even) { background-color: #f2f2f2; }
pre { background: #f4f4f4; padding: 10px; overflow-x: auto; }
</style>";
$messages = $db->fetchAll("
$conversations = $db->fetchAll("
SELECT
c.id,
c.user_id,
@@ -40,7 +40,7 @@ echo "<tr>
<th>Fecha</th>
</tr>";
foreach ($messages as $msg) {
foreach ($conversations as $msg) {
echo "<tr>";
echo "<td>{$msg['id']}</td>";
echo "<td>{$msg['phone_number']}</td>";
+3 -3
View File
@@ -17,9 +17,9 @@ try {
ORDER BY created_at DESC LIMIT 5"
);
$messages = $stmt->fetchAll();
if ($messages) {
foreach ($messages as $msg) {
$conversations = $stmt->fetchAll();
if ($conversations) {
foreach ($conversations as $msg) {
echo "ID: {$msg['id']}, Contenido: {$msg['content']}, Fecha: {$msg['created_at']}\n";
}
} else {
+1 -1
View File
@@ -151,7 +151,7 @@ if (defined('DB_HOST') && defined('DB_NAME')) {
echo "<div class='ok'>✅ Conexión a base de datos exitosa</div>";
// Verificar tablas principales
$tables = ['conversations', 'messages', 'settings'];
$tables = ['conversations', 'conversations', 'system_config'];
foreach ($tables as $table) {
$stmt = $pdo->query("SHOW TABLES LIKE '$table'");
if ($stmt->rowCount() > 0) {
+1 -1
View File
@@ -20,7 +20,7 @@ try {
echo "✅ Conexión exitosa<br>";
// Verificar tablas
$tables = ['users', 'conversations', 'messages'];
$tables = ['users', 'conversations', 'conversations'];
foreach ($tables as $table) {
try {
$stmt = $db->query("SHOW TABLES LIKE '$table'");
+1 -1
View File
@@ -248,7 +248,7 @@ echo "</div>";
echo "<div class='card'>
<h2>🛠️ Acciones Rápidas</h2>
<div style='display: flex; gap: 10px; flex-wrap: wrap;'>
<a href='index.php#settings' style='padding: 10px 20px; background: #007bff; color: white; text-decoration: none; border-radius: 5px;'>⚙️ Ir a Configuración</a>
<a href='index.php#system_config' style='padding: 10px 20px; background: #007bff; color: white; text-decoration: none; border-radius: 5px;'>⚙️ Ir a Configuración</a>
<a href='configurar_whatsapp.php' style='padding: 10px 20px; background: #28a745; color: white; text-decoration: none; border-radius: 5px;'>📱 Configurar WhatsApp</a>
<a href='test_whatsapp_completo.php' style='padding: 10px 20px; background: #17a2b8; color: white; text-decoration: none; border-radius: 5px;'>🧪 Probar API</a>
</div>
+11 -11
View File
@@ -52,10 +52,10 @@ try {
<li><a href="#conversations" class="nav-link" data-tab="conversations"><i class="fas fa-comments"></i> Conversaciones</a></li>
<li><a href="#users" class="nav-link" data-tab="users"><i class="fas fa-users"></i> Usuarios</a></li>
<li><a href="#menus" class="nav-link" data-tab="menus"><i class="fas fa-list"></i> Menús</a></li>
<li><a href="#messages" class="nav-link" data-tab="messages"><i class="fas fa-paper-plane"></i> Enviar Mensaje</a></li>
<li><a href="#conversations" class="nav-link" data-tab="conversations"><i class="fas fa-paper-plane"></i> Enviar Mensaje</a></li>
<li><a href="#templates" class="nav-link" data-tab="templates"><i class="fas fa-file-text"></i> Plantillas</a></li>
<li><a href="#autoresponses" class="nav-link" data-tab="autoresponses"><i class="fas fa-robot"></i> Respuestas Auto</a></li>
<li><a href="#settings" class="nav-link" data-tab="settings"><i class="fas fa-cog"></i> Configuración</a></li>
<li><a href="#system_config" class="nav-link" data-tab="system_config"><i class="fas fa-cog"></i> Configuración</a></li>
<li><a href="#logs" class="nav-link" data-tab="logs"><i class="fas fa-file-alt"></i> Logs</a></li>
<li class="sidebar-divider"></li>
<li><a href="logout.php" class="nav-link logout-link" onclick="return confirm('¿Está seguro que desea cerrar sesión?')"><i class="fas fa-sign-out-alt"></i> Cerrar Sesión</a></li>
@@ -112,7 +112,7 @@ try {
<div class="row align-items-center">
<div class="col">
<h6 class="card-stat-title">Mensajes Hoy</h6>
<h3 class="card-stat-number" id="messages-today">-</h3>
<h3 class="card-stat-number" id="conversations-today">-</h3>
</div>
<div class="col-auto">
<i class="fas fa-comment fa-2x"></i>
@@ -144,7 +144,7 @@ try {
<div class="row align-items-center">
<div class="col">
<h6 class="card-stat-title">Total Mensajes</h6>
<h3 class="card-stat-number" id="total-messages">-</h3>
<h3 class="card-stat-number" id="total-conversations">-</h3>
</div>
<div class="col-auto">
<i class="fas fa-envelope fa-2x"></i>
@@ -163,7 +163,7 @@ try {
<h5><i class="fas fa-chart-line"></i> Actividad Reciente</h5>
</div>
<div class="card-body">
<canvas id="messagesChart" height="100"></canvas>
<canvas id="conversationsChart" height="100"></canvas>
</div>
</div>
</div>
@@ -173,7 +173,7 @@ try {
<h5><i class="fas fa-clock"></i> Últimos Mensajes</h5>
</div>
<div class="card-body">
<div id="recent-messages" class="list-group">
<div id="recent-conversations" class="list-group">
<!-- Contenido dinámico -->
</div>
</div>
@@ -275,8 +275,8 @@ try {
</div>
</div>
<!-- Messages Tab -->
<div id="messages" class="tab-content">
<!-- conversations Tab -->
<div id="conversations" class="tab-content">
<div class="row">
<div class="col-lg-6">
<div class="card">
@@ -423,8 +423,8 @@ try {
</div>
</div>
<!-- Settings Tab -->
<div id="settings" class="tab-content">
<!-- system_config Tab -->
<div id="system_config" class="tab-content">
<div class="row">
<div class="col-lg-8">
<div class="card">
@@ -432,7 +432,7 @@ try {
<h5><i class="fas fa-cog"></i> Configuración del Sistema</h5>
</div>
<div class="card-body">
<form id="settings-form">
<form id="system_config-form">
<div class="mb-4">
<h6 class="text-muted">WhatsApp Business API</h6>
<div class="mb-3">
+6 -6
View File
@@ -49,7 +49,7 @@ $currentUser = $_SESSION['admin_username'] ?? 'admin';
</a>
</li>
<li class="nav-item">
<a class="nav-link" data-tab="settings" href="#">
<a class="nav-link" data-tab="system_config" href="#">
⚙️ Configuraciones
</a>
</li>
@@ -84,7 +84,7 @@ $currentUser = $_SESSION['admin_username'] ?? 'admin';
<div class="col-md-3">
<div class="card text-center">
<div class="card-body">
<h5 id="messages-today" class="text-success">--</h5>
<h5 id="conversations-today" class="text-success">--</h5>
<p class="card-text">WhatsApp</p>
</div>
</div>
@@ -100,7 +100,7 @@ $currentUser = $_SESSION['admin_username'] ?? 'admin';
<div class="col-md-3">
<div class="card text-center">
<div class="card-body">
<h5 id="total-messages" class="text-warning">--</h5>
<h5 id="total-conversations" class="text-warning">--</h5>
<p class="card-text">Instalación</p>
</div>
</div>
@@ -149,8 +149,8 @@ $currentUser = $_SESSION['admin_username'] ?? 'admin';
</div>
</div>
<!-- Settings Tab -->
<div id="settings" class="tab-content">
<!-- system_config Tab -->
<div id="system_config" class="tab-content">
<div class="d-flex justify-content-between align-items-center mb-4">
<h2>⚙️ Configuraciones</h2>
</div>
@@ -160,7 +160,7 @@ $currentUser = $_SESSION['admin_username'] ?? 'admin';
<h5>📱 Configuración WhatsApp</h5>
</div>
<div class="card-body">
<form id="settings-form">
<form id="system_config-form">
<div class="mb-3">
<label for="whatsapp_token" class="form-label">Token de WhatsApp</label>
<input type="text" class="form-control" id="whatsapp_token" name="whatsapp_token"
+15 -15
View File
@@ -115,10 +115,10 @@ echo "</div>";
echo "<div class='section'>";
echo "<h2>🔧 CREANDO TABLAS FALTANTES...</h2>";
// Crear tabla 'messages' como alias de conversations
// Crear tabla 'conversations' como alias de conversations
try {
$pdo->exec("
CREATE TABLE IF NOT EXISTS messages (
CREATE TABLE IF NOT EXISTS conversations (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
phone_number VARCHAR(20) NOT NULL,
@@ -132,19 +132,19 @@ try {
INDEX idx_created (created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
");
echo "<div class='ok'>✅ Tabla 'messages' creada</div>";
echo "<div class='ok'>✅ Tabla 'conversations' creada</div>";
} catch (PDOException $e) {
if (strpos($e->getMessage(), 'already exists') === false) {
echo "<div class='error'>❌ Error creando tabla messages: " . htmlspecialchars($e->getMessage()) . "</div>";
echo "<div class='error'>❌ Error creando tabla conversations: " . htmlspecialchars($e->getMessage()) . "</div>";
} else {
echo "<div class='warning'>⚠️ Tabla 'messages' ya existe</div>";
echo "<div class='warning'>⚠️ Tabla 'conversations' ya existe</div>";
}
}
// Crear tabla 'settings' como alias de system_config
// Crear tabla 'system_config' como alias de system_config
try {
$pdo->exec("
CREATE TABLE IF NOT EXISTS settings (
CREATE TABLE IF NOT EXISTS system_config (
id INT AUTO_INCREMENT PRIMARY KEY,
setting_key VARCHAR(100) UNIQUE NOT NULL,
setting_value TEXT,
@@ -153,25 +153,25 @@ try {
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
");
echo "<div class='ok'>✅ Tabla 'settings' creada</div>";
echo "<div class='ok'>✅ Tabla 'system_config' creada</div>";
} catch (PDOException $e) {
if (strpos($e->getMessage(), 'already exists') === false) {
echo "<div class='error'>❌ Error creando tabla settings: " . htmlspecialchars($e->getMessage()) . "</div>";
echo "<div class='error'>❌ Error creando tabla system_config: " . htmlspecialchars($e->getMessage()) . "</div>";
} else {
echo "<div class='warning'>⚠️ Tabla 'settings' ya existe</div>";
echo "<div class='warning'>⚠️ Tabla 'system_config' ya existe</div>";
}
}
echo "</div>";
// Copiar datos de system_config a settings si no existen
// Copiar datos de system_config a system_config si no existen
echo "<div class='section'>";
echo "<h2>📊 SINCRONIZANDO CONFIGURACIÓN...</h2>";
try {
// Copiar datos de system_config a settings
// Copiar datos de system_config a system_config
$pdo->exec("
INSERT IGNORE INTO settings (setting_key, setting_value, description, created_at)
INSERT IGNORE INTO system_config (setting_key, setting_value, description, created_at)
SELECT config_key, config_value, description, created_at
FROM system_config
WHERE config_key IS NOT NULL
@@ -188,7 +188,7 @@ try {
try {
if (!defined('SECRET_KEY') || empty(SECRET_KEY)) {
$secret_key = bin2hex(random_bytes(32));
$pdo->prepare("INSERT INTO settings (setting_key, setting_value, description) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE setting_value = VALUES(setting_value)")
$pdo->prepare("INSERT INTO system_config (setting_key, setting_value, description) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE setting_value = VALUES(setting_value)")
->execute(['SECRET_KEY', $secret_key, 'Clave secreta para encriptación']);
echo "<div class='ok'>✅ SECRET_KEY generada y guardada</div>";
echo "<div class='warning'>🔑 IMPORTANTE: Agrega esta línea a config/config.php:</div>";
@@ -204,7 +204,7 @@ echo "</div>";
echo "<div class='section'>";
echo "<h2>✅ VERIFICACIÓN FINAL</h2>";
$required_tables = ['conversations', 'messages', 'settings', 'message_templates', 'users', 'menus'];
$required_tables = ['conversations', 'conversations', 'system_config', 'message_templates', 'users', 'menus'];
$missing_tables = [];
foreach ($required_tables as $table) {
+2 -2
View File
@@ -93,7 +93,7 @@ $integratedSchema = [
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
)",
"CREATE TABLE IF NOT EXISTS auto_responses (
"CREATE TABLE IF NOT EXISTS autoresponses (
id INT AUTO_INCREMENT PRIMARY KEY,
trigger_type ENUM('keyword', 'menu_selection', 'welcome') NOT NULL,
trigger_value VARCHAR(200),
@@ -136,7 +136,7 @@ $initialData = [
(1, 0, '❌ Salir', 'end', 'Gracias por contactarnos. ¡Hasta pronto!')",
// Respuestas automáticas
"INSERT IGNORE INTO auto_responses (trigger_type, trigger_value, response_text) VALUES
"INSERT IGNORE INTO autoresponses (trigger_type, trigger_value, response_text) VALUES
('keyword', 'menu', 'Aquí tienes nuestro menú principal:'),
('keyword', 'hola', '¡Hola! 👋 Escribe *menu* para ver opciones.'),
('welcome', '', '¡Bienvenido! 👋 Escribe *menu* para comenzar.')"
+2 -2
View File
@@ -242,7 +242,7 @@ if ($_POST && !$loginBlocked) {
</div>
</div>
<!-- Success Messages -->
<!-- Success conversations -->
<?php if ($success): ?>
<div class="alert alert-success">
<i class="fas fa-check-circle me-2"></i>
@@ -250,7 +250,7 @@ if ($_POST && !$loginBlocked) {
</div>
<?php endif; ?>
<!-- Error Messages -->
<!-- Error conversations -->
<?php if ($error && !$loginBlocked): ?>
<div class="alert alert-danger">
<i class="fas fa-exclamation-triangle me-2"></i>
+4 -4
View File
@@ -14,8 +14,8 @@ try {
if (!empty($entry['changes'])) {
foreach ($entry['changes'] as $change) {
$val = $change['value'] ?? [];
if (!empty($val['messages'])) {
foreach ($val['messages'] as $m) {
if (!empty($val['conversations'])) {
foreach ($val['conversations'] as $m) {
$mid = $m['id'] ?? null;
$from = $m['from'] ?? null;
if ($mid) {
@@ -33,9 +33,9 @@ try {
}
if (empty($missing)) {
echo "All recent messages found in conversations.\n";
echo "All recent conversations found in conversations.\n";
} else {
echo "Missing messages (not found in conversations):\n";
echo "Missing conversations (not found in conversations):\n";
foreach ($missing as $m) {
echo json_encode($m) . PHP_EOL;
}
+1 -1
View File
@@ -6,7 +6,7 @@ try {
$rows = $db->fetchAll('SELECT id, request_body, created_at FROM webhook_logs ORDER BY created_at DESC LIMIT 20');
foreach ($rows as $r) {
$rb = $r['request_body'];
$has = strpos($rb, '"messages"') !== false ? 'HAS_MESSAGES' : (strpos($rb, '"statuses"') !== false ? 'ONLY_STATUSES' : 'OTHER');
$has = strpos($rb, '"conversations"') !== false ? 'HAS_conversations' : (strpos($rb, '"statuses"') !== false ? 'ONLY_STATUSES' : 'OTHER');
echo $r['created_at'] . ' | id:' . $r['id'] . ' | ' . $has . PHP_EOL;
}
} catch (Exception $e) {
+2 -2
View File
@@ -12,8 +12,8 @@ try {
foreach ($payload['entry'] as $entry) {
foreach ($entry['changes'] as $change) {
$val = $change['value'];
if (!empty($val['messages'])) {
foreach ($val['messages'] as $message) {
if (!empty($val['conversations'])) {
foreach ($val['conversations'] as $message) {
$phone = $message['from'];
$mid = $message['id'];
$text = $message['text']['body'] ?? '';
+2 -2
View File
@@ -9,9 +9,9 @@ $payload = [
[
'changes' => [
[
'field' => 'messages',
'field' => 'conversations',
'value' => [
'messages' => [
'conversations' => [
[
'from' => '573019999900',
'id' => 'NTFTEST1',
+4 -4
View File
@@ -27,7 +27,7 @@ $payload = [
[
'changes' => [
[
'field' => 'messages',
'field' => 'conversations',
'value' => [
'messaging_product' => 'whatsapp',
'metadata' => [
@@ -37,7 +37,7 @@ $payload = [
'contacts' => [
[ 'profile' => ['name' => 'reactor'], 'wa_id' => $testPhone ]
],
'messages' => [
'conversations' => [
[
'from' => $testPhone,
'id' => '2001',
@@ -86,9 +86,9 @@ $payload2 = [
[
'changes' => [
[
'field' => 'messages',
'field' => 'conversations',
'value' => [
'messages' => [
'conversations' => [
[
'from' => $testPhone2,
'id' => '2002',
+1 -1
View File
@@ -1 +1 @@
{"object":"whatsapp_business_account","entry":[{"id":"0","changes":[{"field":"messages","value":{"messaging_product":"whatsapp","metadata":{"display_phone_number":"16505551111","phone_number_id":"123456123"},"contacts":[{"profile":{"name":"test user name"},"wa_id":"16315551181"}],"messages":[{"from":"16315551181","id":"ABGGFlA5Fpa","timestamp":"1504902988","type":"text","text":{"body":"this is a text message"}}]}}]}]}
{"object":"whatsapp_business_account","entry":[{"id":"0","changes":[{"field":"conversations","value":{"messaging_product":"whatsapp","metadata":{"display_phone_number":"16505551111","phone_number_id":"123456123"},"contacts":[{"profile":{"name":"test user name"},"wa_id":"16315551181"}],"conversations":[{"from":"16315551181","id":"ABGGFlA5Fpa","timestamp":"1504902988","type":"text","text":{"body":"this is a text message"}}]}}]}]}
+4 -4
View File
@@ -11,7 +11,7 @@ $payload = [
"id" => "0",
"changes" => [
[
"field" => "messages",
"field" => "conversations",
"value" => [
"messaging_product" => "whatsapp",
"metadata" => [
@@ -24,7 +24,7 @@ $payload = [
"wa_id" => "16315551181"
]
],
"messages" => [
"conversations" => [
[
"from" => "16315551181",
"id" => "ABGGFlA5Fpa",
@@ -54,7 +54,7 @@ try {
"id" => "0",
"changes" => [
[
"field" => "messages",
"field" => "conversations",
"value" => [
"messaging_product" => "whatsapp",
"metadata" => [
@@ -67,7 +67,7 @@ try {
"wa_id" => "16315551181"
]
],
"messages" => [
"conversations" => [
[
"from" => "16315551181",
"id" => "REACTION1",
+1 -1
View File
@@ -262,7 +262,7 @@ $step = $_GET['step'] ?? 'welcome';
<ul class="mt-2 mb-0">
<li><strong>Webhook URL:</strong> https://<?= htmlspecialchars($domain) ?>/bot/api/webhook.php</li>
<li><strong>Verify Token:</strong> <?= htmlspecialchars($webhook_token) ?></li>
<li><strong>Subscribe to:</strong> messages</li>
<li><strong>Subscribe to:</strong> conversations</li>
</ul>
</div>
+2 -2
View File
@@ -442,12 +442,12 @@ class BotService {
)['count'];
// Total de mensajes
$stats['total_messages'] = $this->db->fetch(
$stats['total_conversations'] = $this->db->fetch(
"SELECT COUNT(*) as count FROM conversations"
)['count'];
// Mensajes hoy
$stats['messages_today'] = $this->db->fetch(
$stats['conversations_today'] = $this->db->fetch(
"SELECT COUNT(*) as count FROM conversations
WHERE DATE(created_at) = CURDATE()"
)['count'];
+4 -4
View File
@@ -233,7 +233,7 @@ class WhatsAppService
'message_id' => $messageId
];
$url = $this->apiUrl . $this->phoneNumberId . '/messages';
$url = $this->apiUrl . $this->phoneNumberId . '/conversations';
return $this->makeRequest('POST', $url, $data);
}
@@ -400,7 +400,7 @@ class WhatsAppService
private function sendMessage($data)
{
// Construir URL correctamente
$url = rtrim($this->apiUrl, '/') . '/' . $this->phoneNumberId . '/messages';
$url = rtrim($this->apiUrl, '/') . '/' . $this->phoneNumberId . '/conversations';
// Debug log
error_log("WhatsApp API URL: " . $url);
@@ -410,7 +410,7 @@ class WhatsAppService
$response = $this->makeRequest('POST', $url, $data);
// Guardar mensaje enviado en la base de datos
if ($response && isset($response['messages'][0]['id'])) {
if ($response && isset($response['conversations'][0]['id'])) {
$this->saveOutgoingMessage($data, $response);
}
@@ -506,7 +506,7 @@ class WhatsAppService
if ($user) {
$messageData = [
'user_id' => $user['id'],
'message_id' => $response['messages'][0]['id'],
'message_id' => $response['conversations'][0]['id'],
'direction' => 'outgoing',
'message_type' => $data['type'],
'content' => $this->extractMessageContent($data),
+1 -1
View File
@@ -108,7 +108,7 @@ header('Content-Type: text/html; charset=utf-8');
$tablesDetails = '';
if ($dbOk) {
try {
$requiredTables = ['users', 'conversations', 'menus', 'menu_options', 'auto_responses', 'system_config'];
$requiredTables = ['users', 'conversations', 'menus', 'menu_options', 'autoresponses', 'system_config'];
$db = Database::getInstance();
$existingTables = [];
$missingTables = [];
+27 -27
View File
@@ -279,31 +279,31 @@ class APITestSuite {
private function testConfigurationAPIs() {
echo "<h4>⚙️ Tests de APIs de Configuración</h4>";
// Test get_settings.php
$this->apiTest("API get_settings existe", function() {
if (!file_exists(__DIR__ . '/../api/get_settings.php')) {
throw new Exception("get_settings.php no existe");
// Test get_system_config.php
$this->apiTest("API get_system_config existe", function() {
if (!file_exists(__DIR__ . '/../api/get_system_config.php')) {
throw new Exception("get_system_config.php no existe");
}
$content = file_get_contents(__DIR__ . '/../api/get_settings.php');
$content = file_get_contents(__DIR__ . '/../api/get_system_config.php');
if (strpos($content, 'requireAuthentication()') === false) {
throw new Exception("get_settings no requiere autenticación");
throw new Exception("get_system_config no requiere autenticación");
}
return "API get_settings correcta";
return "API get_system_config correcta";
});
// Test save_settings.php
$this->apiTest("API save_settings existe", function() {
if (!file_exists(__DIR__ . '/../api/save_settings.php')) {
throw new Exception("save_settings.php no existe");
// Test save_system_config.php
$this->apiTest("API save_system_config existe", function() {
if (!file_exists(__DIR__ . '/../api/save_system_config.php')) {
throw new Exception("save_system_config.php no existe");
}
$content = file_get_contents(__DIR__ . '/../api/save_settings.php');
$content = file_get_contents(__DIR__ . '/../api/save_system_config.php');
if (strpos($content, 'requireAuthentication()') === false) {
throw new Exception("save_settings no requiere autenticación");
throw new Exception("save_system_config no requiere autenticación");
}
$fields = ['business_name', 'whatsapp_token', 'phone_number_id'];
@@ -313,16 +313,16 @@ class APITestSuite {
}
}
return "API save_settings completa";
return "API save_system_config completa";
});
// Verificar tabla settings
// Verificar tabla system_config
$this->apiTest("Verificar tabla configuración", function() {
$db = Database::getInstance();
$result = $db->fetchAll("SHOW TABLES LIKE 'settings'");
$result = $db->fetchAll("SHOW TABLES LIKE 'system_config'");
if (!$result || empty($result)) {
throw new Exception("Tabla settings no existe");
throw new Exception("Tabla system_config no existe");
}
return "Tabla de configuración existe";
@@ -344,7 +344,7 @@ class APITestSuite {
throw new Exception("get_stats no requiere autenticación");
}
$stats = ['total_users', 'messages_today', 'active_users', 'total_messages'];
$stats = ['total_users', 'conversations_today', 'active_users', 'total_conversations'];
foreach ($stats as $stat) {
if (strpos($content, $stat) === false) {
throw new Exception("Estadística '$stat' no está implementada");
@@ -369,30 +369,30 @@ class APITestSuite {
return "API get_chart_data correcta";
});
// Test get_recent_messages.php
$this->apiTest("API get_recent_messages existe", function() {
if (!file_exists(__DIR__ . '/../api/get_recent_messages.php')) {
throw new Exception("get_recent_messages.php no existe");
// Test get_recent_conversations.php
$this->apiTest("API get_recent_conversations existe", function() {
if (!file_exists(__DIR__ . '/../api/get_recent_conversations.php')) {
throw new Exception("get_recent_conversations.php no existe");
}
$content = file_get_contents(__DIR__ . '/../api/get_recent_messages.php');
$content = file_get_contents(__DIR__ . '/../api/get_recent_conversations.php');
if (strpos($content, 'requireAuthentication()') === false) {
throw new Exception("get_recent_messages no requiere autenticación");
throw new Exception("get_recent_conversations no requiere autenticación");
}
if (strpos($content, 'messages') === false && strpos($content, 'conversations') === false) {
if (strpos($content, 'conversations') === false && strpos($content, 'conversations') === false) {
throw new Exception("No consulta mensajes");
}
return "API get_recent_messages correcta";
return "API get_recent_conversations correcta";
});
// Test de integridad de datos
$this->apiTest("Verificar tablas de analytics", function() {
$db = Database::getInstance();
$tables = ['messages', 'conversations'];
$tables = ['conversations', 'conversations'];
foreach ($tables as $table) {
$result = $db->fetchAll("SHOW TABLES LIKE '$table'");
if (!$result || empty($result)) {
+2 -2
View File
@@ -314,7 +314,7 @@ class TestRunner {
'changes' => [
[
'value' => [
'messages' => [
'conversations' => [
[
'from' => '573001234567',
'text' => ['body' => 'test message'],
@@ -442,7 +442,7 @@ class TestRunner {
$db = Database::getInstance();
$requiredTables = [
'users', 'conversations', 'menus', 'menu_options',
'system_config', 'auto_responses', 'message_templates',
'system_config', 'autoresponses', 'message_templates',
'webhook_logs'
];
+1 -1
View File
@@ -114,7 +114,7 @@ class SecurityTestSuite {
$this->securityTest("APIs requieren autenticación", function() {
$protectedAPIs = [
'get_stats.php', 'get_users.php', 'send_message.php',
'save_template.php', 'get_templates.php', 'save_settings.php'
'save_template.php', 'get_templates.php', 'save_system_config.php'
];
unset($_SESSION['admin_logged_in']);
+2 -2
View File
@@ -203,7 +203,7 @@ class ServiceTestSuite {
$this->serviceTest("Test de respuestas automáticas", function() {
// Verificar que hay respuestas automáticas configuradas
$responses = $this->db->fetchAll(
"SELECT * FROM auto_responses WHERE trigger_type = 'keyword'"
"SELECT * FROM autoresponses WHERE trigger_type = 'keyword'"
);
if (empty($responses)) {
@@ -216,7 +216,7 @@ class ServiceTestSuite {
foreach ($requiredFields as $field) {
if (!isset($firstResponse[$field])) {
throw new Exception("Campo requerido '$field' faltante en auto_responses");
throw new Exception("Campo requerido '$field' faltante en autoresponses");
}
}
+8 -8
View File
@@ -159,7 +159,7 @@ class WebhookTestSuite {
'display_phone_number' => '573001234567',
'phone_number_id' => WHATSAPP_PHONE_NUMBER_ID
],
'messages' => [
'conversations' => [
[
'from' => '573009876543',
'id' => 'wamid.test123',
@@ -171,7 +171,7 @@ class WebhookTestSuite {
]
]
],
'field' => 'messages'
'field' => 'conversations'
]
]
]
@@ -183,7 +183,7 @@ class WebhookTestSuite {
throw new Exception("Estructura de payload incorrecta");
}
if (!isset($validPayload['entry'][0]['changes'][0]['value']['messages'])) {
if (!isset($validPayload['entry'][0]['changes'][0]['value']['conversations'])) {
throw new Exception("Estructura de mensajes incorrecta");
}
@@ -205,7 +205,7 @@ class WebhookTestSuite {
'changes' => [
[
'value' => [
'messages' => [
'conversations' => [
[
'from' => $testPhone,
'id' => 'test_message_id',
@@ -328,9 +328,9 @@ class WebhookTestSuite {
[
'changes' => [
[
'field' => 'messages',
'field' => 'conversations',
'value' => [
'messages' => [
'conversations' => [
[
'from' => $testPhone,
'id' => '2001',
@@ -383,9 +383,9 @@ class WebhookTestSuite {
[
'changes' => [
[
'field' => 'messages',
'field' => 'conversations',
'value' => [
'messages' => [
'conversations' => [
[
'from' => $testPhone,
'id' => '2002',
+2 -2
View File
@@ -21,7 +21,7 @@ $data = [
'type' => 'reaction',
'reaction' => ['message_id' => '5001', 'emoji' => '❤️']
];
$response = ['messages' => [['id' => 'out_msg_1']]];
$response = ['conversations' => [['id' => 'out_msg_1']]];
$foundUser = $db->fetch('SELECT * FROM users WHERE phone_number = :p', ['p' => $phone]);
echo "User found for outgoing reaction? " . ($foundUser ? 'yes' : 'no') . "\n";
@@ -71,7 +71,7 @@ $data2 = [
'context' => ['message_id' => '5002'],
'text' => ['body' => 'Gracias']
];
$response2 = ['messages' => [['id' => 'out_msg_2']]];
$response2 = ['conversations' => [['id' => 'out_msg_2']]];
$method->invokeArgs($service, [$data2, $response2]);
$conv2 = $db->fetch('SELECT * FROM conversations WHERE message_id = :mid', ['mid' => 'out_msg_2']);
if ($conv2) {
+3 -3
View File
@@ -89,7 +89,7 @@ if (defined('DB_HOST') && defined('DB_NAME') && defined('DB_USER') && defined('D
$successes++;
// Verificar tablas principales
$tables = ['conversations', 'messages', 'settings', 'message_templates'];
$tables = ['conversations', 'conversations', 'system_config', 'message_templates'];
foreach ($tables as $table) {
$stmt = $pdo->query("SHOW TABLES LIKE '$table'");
if ($stmt->rowCount() > 0) {
@@ -135,8 +135,8 @@ echo "<h2>🔌 Verificación de APIs</h2>";
$apis = [
'api/send_message.php',
'api/webhook.php',
'api/get_settings.php',
'api/save_settings.php',
'api/get_system_config.php',
'api/save_system_config.php',
'api/get_templates.php'
];