This commit is contained in:
Lizandro Guarnizo
2026-01-12 11:06:43 -05:00
parent ce12ac2cce
commit dd36ed6fe0
110 changed files with 20873 additions and 696 deletions
+76
View File
@@ -0,0 +1,76 @@
<?php
// Archivo para aprobar plantillas manualmente
require_once '../config/config.php';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
try {
$db = Database::connect();
$action = $_POST['action'] ?? '';
if ($action === 'approve_all') {
// Aprobar todas las plantillas pendientes
$stmt = $db->prepare("UPDATE whatsapp_templates SET status = 'approved' WHERE status = 'pending'");
$result = $stmt->execute();
if ($result) {
$affected = $stmt->rowCount();
echo json_encode([
'success' => true,
'message' => "Se aprobaron $affected plantillas exitosamente"
]);
} else {
echo json_encode(['success' => false, 'message' => 'Error al aprobar las plantillas']);
}
}
elseif ($action === 'approve_specific' && !empty($_POST['template_name'])) {
// Aprobar plantilla específica
$templateName = $_POST['template_name'];
$stmt = $db->prepare("UPDATE whatsapp_templates SET status = 'approved' WHERE name = ?");
$result = $stmt->execute([$templateName]);
if ($result && $stmt->rowCount() > 0) {
echo json_encode([
'success' => true,
'message' => "Plantilla '$templateName' aprobada exitosamente"
]);
} else {
echo json_encode(['success' => false, 'message' => 'Plantilla no encontrada o ya aprobada']);
}
}
else {
echo json_encode(['success' => false, 'message' => 'Acción no válida']);
}
} catch (Exception $e) {
echo json_encode([
'success' => false,
'message' => 'Error: ' . $e->getMessage()
]);
}
}
elseif ($_SERVER['REQUEST_METHOD'] === 'GET') {
// Mostrar estado actual de plantillas
try {
$db = Database::connect();
$stmt = $db->prepare("SELECT name, status, language, category FROM whatsapp_templates ORDER BY name");
$stmt->execute();
$templates = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo json_encode([
'success' => true,
'templates' => $templates,
'summary' => [
'total' => count($templates),
'approved' => count(array_filter($templates, fn($t) => $t['status'] === 'approved')),
'pending' => count(array_filter($templates, fn($t) => $t['status'] === 'pending')),
'rejected' => count(array_filter($templates, fn($t) => $t['status'] === 'rejected'))
]
]);
} catch (Exception $e) {
echo json_encode([
'success' => false,
'message' => 'Error: ' . $e->getMessage()
]);
}
}
?>
+54
View File
@@ -0,0 +1,54 @@
<?php
header('Content-Type: application/json');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET');
header('Access-Control-Allow-Headers: Content-Type');
require_once __DIR__ . '/../config/config.php';
try {
// Usar conexión desde config
$db = Database::getInstance();
// Obtener todas las plantillas
$stmt = $db->query("SELECT * FROM message_templates ORDER BY template_name");
$templates = $stmt->fetchAll();
$result = [
'success' => true,
'templates' => [],
'summary' => [
'total' => count($templates),
'approved' => 0,
'pending' => 0,
'rejected' => 0
]
];
foreach ($templates as $template) {
$result['templates'][] = [
'id' => $template['id'],
'name' => $template['template_name'],
'language' => $template['language_code'] ?: 'es',
'status' => $template['status'] ?: 'pending',
'category' => $template['category'] ?: 'UTILITY',
'created' => $template['created_at'] ?: 'N/A'
];
// Contar por estado
$status = $template['status'] ?: 'pending';
if (isset($result['summary'][$status])) {
$result['summary'][$status]++;
}
}
echo json_encode($result);
} catch (Exception $e) {
http_response_code(500);
echo json_encode([
'success' => false,
'error' => 'Error al verificar plantillas: ' . $e->getMessage()
]);
}
?>
+136
View File
@@ -0,0 +1,136 @@
<?php
header('Content-Type: application/json');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, GET');
header('Access-Control-Allow-Headers: Content-Type');
require_once __DIR__ . '/../config/config.php';
try {
// Verificar autenticación si no estás en modo debug
$debugMode = isset($_GET['debug']);
if (!$debugMode) {
if (session_status() === PHP_SESSION_NONE) {
session_start();
}
if (!isset($_SESSION['user_id'])) {
http_response_code(401);
echo json_encode(['error' => 'No autorizado']);
exit;
}
}
// Obtener configuración de WhatsApp
$whatsappConfig = getWhatsAppConfigFromDB();
$diagnostic = [
'success' => true,
'timestamp' => date('Y-m-d H:i:s'),
'config_status' => [],
'template_status' => [],
'api_status' => []
];
// 1. Verificar configuración básica
$diagnostic['config_status'] = [
'phone_number_id' => !empty($whatsappConfig['phone_number_id']),
'access_token' => !empty($whatsappConfig['access_token']),
'webhook_verify_token' => !empty($whatsappConfig['webhook_verify_token']),
'business_account_id' => !empty($whatsappConfig['business_account_id'])
];
$diagnostic['config_status']['complete'] = array_reduce($diagnostic['config_status'], function($carry, $item) {
return $carry && $item;
}, true);
// 2. Verificar plantillas en base de datos
$db = Database::getInstance();
$stmt = $db->query("SELECT status, COUNT(*) as count FROM message_templates GROUP BY status");
$templateCounts = $stmt->fetchAll();
$diagnostic['template_status'] = [
'total' => 0,
'approved' => 0,
'pending' => 0,
'rejected' => 0
];
foreach ($templateCounts as $count) {
$status = $count['status'] ?: 'pending';
$diagnostic['template_status'][$status] = (int)$count['count'];
$diagnostic['template_status']['total'] += (int)$count['count'];
}
// 3. Test básico de API (solo si hay configuración completa)
if ($diagnostic['config_status']['complete']) {
$apiUrl = "https://graph.facebook.com/v18.0/{$whatsappConfig['phone_number_id']}";
$headers = [
'Authorization: Bearer ' . $whatsappConfig['access_token'],
'Content-Type: application/json'
];
// Crear contexto para la solicitud HTTP
$context = stream_context_create([
'http' => [
'method' => 'GET',
'header' => implode("\r\n", $headers),
'timeout' => 10
]
]);
$response = @file_get_contents($apiUrl, false, $context);
if ($response !== false) {
$apiData = json_decode($response, true);
$diagnostic['api_status'] = [
'reachable' => true,
'phone_number' => $apiData['display_phone_number'] ?? 'N/A',
'verified_name' => $apiData['verified_name'] ?? 'N/A',
'quality_rating' => $apiData['quality_rating'] ?? 'N/A'
];
} else {
$diagnostic['api_status'] = [
'reachable' => false,
'error' => 'No se pudo conectar con la API de WhatsApp'
];
}
} else {
$diagnostic['api_status'] = [
'reachable' => false,
'error' => 'Configuración incompleta'
];
}
// 4. Recomendaciones
$diagnostic['recommendations'] = [];
if (!$diagnostic['config_status']['complete']) {
$diagnostic['recommendations'][] = 'Completa la configuración de WhatsApp en la pestaña Configuración';
}
if ($diagnostic['template_status']['approved'] === 0) {
$diagnostic['recommendations'][] = 'Necesitas plantillas aprobadas para enviar mensajes';
$diagnostic['recommendations'][] = 'Crea plantillas en WhatsApp Business Manager y espera su aprobación';
}
if (!$diagnostic['api_status']['reachable']) {
$diagnostic['recommendations'][] = 'Verifica que el token de acceso sea válido';
$diagnostic['recommendations'][] = 'Confirma que el Phone Number ID sea correcto';
}
if (empty($diagnostic['recommendations'])) {
$diagnostic['recommendations'][] = 'Todo parece estar configurado correctamente';
}
echo json_encode($diagnostic, JSON_PRETTY_PRINT);
} catch (Exception $e) {
http_response_code(500);
echo json_encode([
'success' => false,
'error' => 'Error en diagnóstico: ' . $e->getMessage(),
'trace' => $e->getTraceAsString()
]);
}
?>
+3
View File
@@ -6,6 +6,9 @@
require_once '../config/config.php';
// Verificar autenticación
requireAuthentication();
// 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"');
+216
View File
@@ -0,0 +1,216 @@
<?php
/**
* Script de corrección rápida para WhatsApp API
* Fecha: 5 de enero de 2026
*/
require_once 'config/config.php';
header('Content-Type: application/json; charset=utf-8');
// Verificar autenticación si es POST
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
requireAuthentication();
}
try {
$method = $_SERVER['REQUEST_METHOD'];
if ($method === 'GET') {
// Obtener configuración actual y diagnóstico
$db = Database::getInstance();
$currentConfig = [];
$configKeys = ['whatsapp_token', 'whatsapp_phone_number_id', 'whatsapp_api_url', 'webhook_verify_token'];
foreach ($configKeys as $key) {
$config = $db->fetch("SELECT config_value FROM system_config WHERE config_key = ?", [$key]);
$currentConfig[$key] = $config['config_value'] ?? null;
}
// Si no hay configuración en BD, usar constantes
if (empty($currentConfig['whatsapp_token'])) {
$currentConfig = [
'whatsapp_token' => WHATSAPP_TOKEN,
'whatsapp_phone_number_id' => WHATSAPP_PHONE_NUMBER_ID,
'whatsapp_api_url' => WHATSAPP_API_URL,
'webhook_verify_token' => WEBHOOK_VERIFY_TOKEN
];
}
// Diagnóstico del problema
$diagnosis = [
'has_valid_token' => $currentConfig['whatsapp_token'] !== 'TU_TOKEN_DE_WHATSAPP_AQUI' && !empty($currentConfig['whatsapp_token']),
'has_valid_phone_id' => $currentConfig['whatsapp_phone_number_id'] !== 'TU_PHONE_ID_AQUI' && !empty($currentConfig['whatsapp_phone_number_id']),
'problematic_phone_id' => $currentConfig['whatsapp_phone_number_id'] === '858157464051987',
'error_message' => 'Object with ID \'858157464051987\' does not exist, cannot be loaded due to missing permissions, or does not support this operation'
];
echo json_encode([
'success' => true,
'current_config' => $currentConfig,
'diagnosis' => $diagnosis
]);
} elseif ($method === 'POST') {
// Actualizar configuración
$input = json_decode(file_get_contents('php://input'), true);
if (!$input) {
throw new Exception('Datos inválidos');
}
$db = Database::getInstance();
// Validar datos requeridos
$token = trim($input['whatsapp_token'] ?? '');
$phoneId = trim($input['whatsapp_phone_number_id'] ?? '');
$apiUrl = trim($input['whatsapp_api_url'] ?? WHATSAPP_API_URL);
$webhookToken = trim($input['webhook_verify_token'] ?? WEBHOOK_VERIFY_TOKEN);
if (empty($token)) {
throw new Exception('Token de WhatsApp es obligatorio');
}
if (empty($phoneId)) {
throw new Exception('Phone Number ID es obligatorio');
}
// Validar formato del token
if (!preg_match('/^EAA[A-Za-z0-9_-]+$/', $token)) {
throw new Exception('Formato de token inválido. Debe empezar con EAA');
}
// Validar formato del Phone Number ID
if (!preg_match('/^\d{10,20}$/', $phoneId)) {
throw new Exception('Phone Number ID debe ser numérico (10-20 dígitos)');
}
// Probar conexión antes de guardar
$testResult = testConnectionWithCredentials($token, $phoneId, $apiUrl);
if (!$testResult['success']) {
throw new Exception('Error al probar conexión: ' . $testResult['message']);
}
// Guardar configuración
$configs = [
'whatsapp_token' => $token,
'whatsapp_phone_number_id' => $phoneId,
'whatsapp_api_url' => $apiUrl,
'webhook_verify_token' => $webhookToken
];
foreach ($configs as $key => $value) {
$existing = $db->fetch("SELECT id FROM system_config WHERE config_key = ?", [$key]);
if ($existing) {
$db->query(
"UPDATE system_config SET config_value = ?, updated_at = NOW() WHERE config_key = ?",
[$value, $key]
);
} else {
$db->query(
"INSERT INTO system_config (config_key, config_value, created_at, updated_at) VALUES (?, ?, NOW(), NOW())",
[$key, $value]
);
}
}
echo json_encode([
'success' => true,
'message' => 'Configuración actualizada y probada correctamente',
'test_result' => $testResult
]);
} elseif ($method === 'PUT') {
// Solo probar conexión con configuración actual
$currentToken = getConfigFromDB('whatsapp_token', WHATSAPP_TOKEN);
$currentPhoneId = getConfigFromDB('whatsapp_phone_number_id', WHATSAPP_PHONE_NUMBER_ID);
$currentApiUrl = getConfigFromDB('whatsapp_api_url', WHATSAPP_API_URL);
$testResult = testConnectionWithCredentials($currentToken, $currentPhoneId, $currentApiUrl);
echo json_encode([
'success' => true,
'test_result' => $testResult
]);
} else {
throw new Exception('Método no permitido');
}
} catch (Exception $e) {
http_response_code(500);
echo json_encode([
'success' => false,
'error' => $e->getMessage()
]);
}
function testConnectionWithCredentials($token, $phoneId, $apiUrl) {
try {
if (empty($token) || empty($phoneId)) {
return ['success' => false, 'message' => 'Token o Phone ID vacío'];
}
// Probar acceso al Phone Number ID
$ch = curl_init();
$url = $apiUrl . $phoneId;
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $token,
'Content-Type: application/json'
],
CURLOPT_TIMEOUT => 15,
CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_USERAGENT => 'WhatsApp-Bot-Diagnostic/1.0'
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$curlError = curl_error($ch);
curl_close($ch);
if ($curlError) {
return ['success' => false, 'message' => 'Error de conexión: ' . $curlError];
}
$decoded = json_decode($response, true);
if ($httpCode === 200 && $decoded) {
$displayName = $decoded['display_phone_number'] ?? 'N/A';
$verifiedName = $decoded['verified_name'] ?? 'No verificado';
return [
'success' => true,
'message' => "Conexión exitosa. Número: $displayName ($verifiedName)",
'phone_info' => $decoded
];
} else {
$errorMsg = 'Error desconocido';
if ($decoded && isset($decoded['error'])) {
$errorMsg = $decoded['error']['message'] ?? $errorMsg;
$errorCode = $decoded['error']['code'] ?? 'N/A';
$errorType = $decoded['error']['type'] ?? 'N/A';
$errorMsg = "[$errorCode/$errorType] $errorMsg";
}
return [
'success' => false,
'message' => $errorMsg,
'http_code' => $httpCode,
'raw_response' => $response
];
}
} catch (Exception $e) {
return ['success' => false, 'message' => 'Excepción: ' . $e->getMessage()];
}
}
?>
+26 -5
View File
@@ -1,7 +1,7 @@
<?php
/**
* API - Obtener conversaciones recientes
* Fecha: 13 de noviembre de 2025
* Fecha: 4 de enero de 2026
*/
require_once '../config/config.php';
@@ -14,28 +14,49 @@ header('Access-Control-Allow-Headers: Content-Type');
try {
$db = Database::getInstance();
// Obtener conversaciones de la tabla conversations
$conversations = $db->fetchAll(
"SELECT
c.id,
c.user_id,
c.content,
COALESCE(c.content, '') as content,
c.direction,
c.message_type,
c.status,
c.created_at,
u.phone_number,
u.name
COALESCE(u.name, u.phone_number) as name
FROM conversations c
JOIN users u ON c.user_id = u.id
ORDER BY c.created_at DESC
LIMIT 50"
LIMIT 500"
);
// Si no hay datos, retornar array vacío
if (empty($conversations)) {
$conversations = [];
}
// Formatear datos para el frontend
$conversations = array_map(function($conv) {
return [
'id' => intval($conv['id']),
'user_id' => intval($conv['user_id']),
'content' => $conv['content'] ?? '',
'direction' => $conv['direction'] ?? 'incoming',
'message_type' => $conv['message_type'] ?? 'text',
'status' => $conv['status'] ?? 'sent',
'created_at' => $conv['created_at'],
'phone_number' => $conv['phone_number'],
'name' => $conv['name'] ?? $conv['phone_number']
];
}, $conversations);
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']);
echo json_encode(['error' => 'Error interno del servidor: ' . $e->getMessage()]);
}
?>
+3
View File
@@ -6,6 +6,9 @@
require_once '../config/config.php';
// Verificar autenticación
requireAuthentication();
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET');
+3
View File
@@ -6,6 +6,9 @@
require_once '../config/config.php';
// Verificar autenticación
requireAuthentication();
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET');
+10
View File
@@ -6,6 +6,16 @@
require_once '../config/config.php';
// Suprimir errores para obtener JSON limpio
error_reporting(E_ERROR | E_PARSE);
// Modo debug: desactivar autenticación si existe el parámetro debug
$debugMode = isset($_GET['debug']) && $_GET['debug'] === 'true';
if (!$debugMode) {
requireAuthentication();
}
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET');
+18 -2
View File
@@ -6,6 +6,16 @@
require_once '../config/config.php';
// Suprimir errores para obtener JSON limpio
error_reporting(E_ERROR | E_PARSE);
// Modo debug: desactivar autenticación si existe el parámetro debug
$debugMode = isset($_GET['debug']) && $_GET['debug'] === 'true';
if (!$debugMode) {
requireAuthentication();
}
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET');
@@ -27,11 +37,17 @@ try {
ORDER BY name ASC"
);
echo json_encode($templates);
echo json_encode([
'success' => true,
'data' => $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']);
echo json_encode([
'success' => false,
'error' => 'Error interno del servidor'
]);
}
?>
+93
View File
@@ -0,0 +1,93 @@
<?php
/**
* API - Obtener mensajes de un usuario específico
* Fecha: 4 de enero de 2026
*/
require_once '../config/config.php';
// Verificar autenticación
requireAuthentication();
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 {
$userId = intval($_GET['user_id'] ?? 0);
if (!$userId) {
http_response_code(400);
echo json_encode(['error' => 'user_id es requerido']);
exit;
}
$db = Database::getInstance();
// Obtener mensajes del usuario (de ambas tablas para compatibilidad)
$messages = $db->fetchAll(
"SELECT
id,
user_id,
COALESCE(content, message_text) as content,
direction,
message_type,
status,
created_at
FROM conversations
WHERE user_id = :user_id
UNION ALL
SELECT
id,
user_id,
message_text as content,
direction,
message_type,
status,
created_at
FROM messages
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(
"SELECT
id,
user_id,
message_text as content,
direction,
message_type,
status,
created_at
FROM messages
WHERE user_id = :user_id
ORDER BY created_at ASC",
['user_id' => $userId]
);
}
// Formatear fechas y limpiar datos
$messages = array_map(function($msg) {
return [
'id' => intval($msg['id']),
'user_id' => intval($msg['user_id']),
'content' => $msg['content'] ?? '',
'direction' => $msg['direction'] ?? 'incoming',
'message_type' => $msg['message_type'] ?? 'text',
'status' => $msg['status'] ?? 'sent',
'created_at' => $msg['created_at']
];
}, $messages);
echo json_encode($messages);
} catch (Exception $e) {
error_log("Error in get_user_messages.php: " . $e->getMessage());
http_response_code(500);
echo json_encode(['error' => 'Error interno del servidor']);
}
?>
+18 -2
View File
@@ -6,6 +6,16 @@
require_once '../config/config.php';
// Suprimir errores para obtener JSON limpio
error_reporting(E_ERROR | E_PARSE);
// Modo debug: desactivar autenticación si existe el parámetro debug
$debugMode = isset($_GET['debug']) && $_GET['debug'] === 'true';
if (!$debugMode) {
requireAuthentication();
}
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET');
@@ -31,11 +41,17 @@ try {
ORDER BY u.created_at DESC"
);
echo json_encode($users);
echo json_encode([
'success' => true,
'data' => $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']);
echo json_encode([
'success' => false,
'error' => 'Error interno del servidor'
]);
}
?>
+326
View File
@@ -0,0 +1,326 @@
<?php
/**
* API para gestionar configuraciones del sistema
* Permite guardar y obtener configuraciones desde la base de datos
*/
require_once '../config/config.php';
// Suprimir errores para obtener JSON limpio
error_reporting(E_ERROR | E_PARSE);
// Modo debug: desactivar autenticación si existe el parámetro debug
$debugMode = isset($_GET['debug']) && $_GET['debug'] === 'true';
if (!$debugMode) {
requireAuthentication();
} else {
// Simular sesión para modo debug
if (session_status() == PHP_SESSION_NONE) {
session_start();
}
$_SESSION['admin_logged_in'] = true;
$_SESSION['admin_username'] = 'debug_user';
}
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type');
$method = $_SERVER['REQUEST_METHOD'];
$action = $_GET['action'] ?? '';
try {
switch ($method) {
case 'GET':
handleGetRequest($action);
break;
case 'POST':
handlePostRequest($action);
break;
case 'PUT':
handlePutRequest($action);
break;
case 'DELETE':
handleDeleteRequest($action);
break;
default:
throw new Exception('Método HTTP no permitido');
}
} catch (Exception $e) {
http_response_code(500);
echo json_encode([
'success' => false,
'error' => $e->getMessage()
]);
writeLog('ERROR', 'Error en API manage_config: ' . $e->getMessage());
}
/**
* Maneja peticiones GET
*/
function handleGetRequest($action) {
switch ($action) {
case 'all':
// Obtener todas las configuraciones
$configs = getAllConfigsFromDB();
echo json_encode([
'success' => true,
'data' => $configs
]);
break;
case 'whatsapp':
// Obtener configuración específica de WhatsApp
$whatsappConfig = getWhatsAppConfigFromDB();
echo json_encode([
'success' => true,
'data' => $whatsappConfig
]);
break;
case 'validate_whatsapp':
// Validar configuración de WhatsApp
$validation = validateWhatsAppConfigFromDB();
echo json_encode([
'success' => true,
'data' => $validation
]);
break;
case 'get':
// Obtener configuración específica
$key = $_GET['key'] ?? '';
if (empty($key)) {
throw new Exception('Clave de configuración requerida');
}
$value = getConfigFromDB($key);
$default = $_GET['default'] ?? null;
echo json_encode([
'success' => true,
'data' => [
'key' => $key,
'value' => $value ?? $default,
'exists' => $value !== null
]
]);
break;
case 'status':
// Estado general del sistema de configuraciones
$allConfigs = getAllConfigsFromDB();
$whatsappValidation = validateWhatsAppConfigFromDB();
echo json_encode([
'success' => true,
'data' => [
'total_configs' => count($allConfigs),
'whatsapp_configured' => $whatsappValidation['valid'],
'database_migrated' => !empty($allConfigs),
'installation_completed' => isInstallationCompleted()
]
]);
break;
default:
throw new Exception('Acción GET no reconocida');
}
}
/**
* Maneja peticiones POST
*/
function handlePostRequest($action) {
$input = json_decode(file_get_contents('php://input'), true);
if (json_last_error() !== JSON_ERROR_NONE) {
throw new Exception('JSON inválido en el cuerpo de la petición');
}
switch ($action) {
case 'save':
// Guardar configuración individual
$key = $input['key'] ?? '';
$value = $input['value'] ?? '';
$description = $input['description'] ?? null;
if (empty($key)) {
throw new Exception('Clave de configuración requerida');
}
$result = saveConfigToDB($key, $value, $description);
echo json_encode([
'success' => $result,
'message' => $result ? 'Configuración guardada exitosamente' : 'Error al guardar configuración'
]);
if ($result) {
writeLog('INFO', "Configuración '$key' actualizada", ['user' => $_SESSION['admin_username'] ?? 'unknown']);
}
break;
case 'save_multiple':
// Guardar múltiples configuraciones
$configs = $input['configs'] ?? [];
if (empty($configs) || !is_array($configs)) {
throw new Exception('Array de configuraciones requerido');
}
$result = saveMultipleConfigsToDB($configs);
echo json_encode([
'success' => $result,
'message' => $result ? 'Configuraciones guardadas exitosamente' : 'Error al guardar configuraciones',
'count' => count($configs)
]);
if ($result) {
writeLog('INFO', "Guardadas " . count($configs) . " configuraciones", [
'keys' => array_keys($configs),
'user' => $_SESSION['admin_username'] ?? 'unknown'
]);
}
break;
case 'save_whatsapp':
// Guardar configuración específica de WhatsApp
$whatsappConfig = $input['whatsapp'] ?? [];
if (empty($whatsappConfig)) {
throw new Exception('Configuración de WhatsApp requerida');
}
$result = saveWhatsAppConfigToDB($whatsappConfig);
// Validar la configuración guardada
$validation = validateWhatsAppConfigFromDB();
echo json_encode([
'success' => $result,
'message' => $result ? 'Configuración de WhatsApp guardada exitosamente' : 'Error al guardar configuración de WhatsApp',
'validation' => $validation
]);
if ($result) {
writeLog('INFO', 'Configuración de WhatsApp actualizada', [
'configured_fields' => $validation['configured_fields'],
'user' => $_SESSION['admin_username'] ?? 'unknown'
]);
}
break;
case 'initialize_defaults':
// Inicializar configuraciones por defecto
$result = initializeDefaultConfigs();
echo json_encode([
'success' => $result,
'message' => $result ? 'Configuraciones por defecto inicializadas' : 'Error al inicializar configuraciones'
]);
if ($result) {
writeLog('INFO', 'Configuraciones por defecto inicializadas', [
'user' => $_SESSION['admin_username'] ?? 'unknown'
]);
}
break;
case 'migrate_to_database':
// Migrar configuraciones a la base de datos
$result = migrateConfigsToDatabase();
echo json_encode([
'success' => $result,
'message' => $result ? 'Configuraciones migradas exitosamente a la base de datos' : 'Error en la migración'
]);
break;
default:
throw new Exception('Acción POST no reconocida');
}
}
/**
* Maneja peticiones PUT (actualizar)
*/
function handlePutRequest($action) {
$input = json_decode(file_get_contents('php://input'), true);
if (json_last_error() !== JSON_ERROR_NONE) {
throw new Exception('JSON inválido en el cuerpo de la petición');
}
switch ($action) {
case 'update':
// Actualizar configuración específica
$key = $input['key'] ?? '';
$value = $input['value'] ?? '';
$description = $input['description'] ?? null;
if (empty($key)) {
throw new Exception('Clave de configuración requerida');
}
$result = saveConfigToDB($key, $value, $description);
echo json_encode([
'success' => $result,
'message' => $result ? 'Configuración actualizada exitosamente' : 'Error al actualizar configuración'
]);
break;
default:
throw new Exception('Acción PUT no reconocida');
}
}
/**
* Maneja peticiones DELETE
*/
function handleDeleteRequest($action) {
switch ($action) {
case 'delete':
$key = $_GET['key'] ?? '';
if (empty($key)) {
throw new Exception('Clave de configuración requerida');
}
$result = deleteConfigFromDB($key);
echo json_encode([
'success' => $result,
'message' => $result ? 'Configuración eliminada exitosamente' : 'Error al eliminar configuración'
]);
if ($result) {
writeLog('INFO', "Configuración '$key' eliminada", [
'user' => $_SESSION['admin_username'] ?? 'unknown'
]);
}
break;
case 'clear_cache':
// Limpiar cache de configuraciones
clearConfigCache();
echo json_encode([
'success' => true,
'message' => 'Cache de configuraciones limpiado'
]);
break;
default:
throw new Exception('Acción DELETE no reconocida');
}
}
?>
+117
View File
@@ -0,0 +1,117 @@
<?php
header('Content-Type: application/json');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST');
header('Access-Control-Allow-Headers: Content-Type');
require_once __DIR__ . '/../config/config.php';
try {
// Debug mode
$debugMode = isset($_GET['debug']) || php_sapi_name() === 'cli';
if (!$debugMode) {
if (session_status() === PHP_SESSION_NONE) {
session_start();
}
if (!isset($_SESSION['user_id'])) {
http_response_code(401);
echo json_encode(['error' => 'No autorizado']);
exit;
}
}
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
echo json_encode(['error' => 'Método no permitido']);
exit;
}
$input = json_decode(file_get_contents('php://input'), true);
if (!$input) {
http_response_code(400);
echo json_encode(['error' => 'JSON inválido']);
exit;
}
$db = Database::getInstance();
$action = $input['action'] ?? '';
switch ($action) {
case 'update_status':
$templateId = intval($input['template_id'] ?? 0);
$newStatus = $input['status'] ?? '';
if (!$templateId || !in_array($newStatus, ['pending', 'approved', 'rejected'])) {
http_response_code(400);
echo json_encode(['error' => 'template_id y status válido requeridos']);
exit;
}
$stmt = $db->query(
"UPDATE message_templates SET status = ?, updated_at = NOW() WHERE id = ?",
[$newStatus, $templateId]
);
if ($stmt->rowCount() > 0) {
echo json_encode([
'success' => true,
'message' => 'Estado de plantilla actualizado correctamente',
'template_id' => $templateId,
'new_status' => $newStatus
]);
} else {
echo json_encode([
'success' => false,
'error' => 'Plantilla no encontrada o no se pudo actualizar'
]);
}
break;
case 'bulk_approve':
$templateIds = $input['template_ids'] ?? [];
if (empty($templateIds) || !is_array($templateIds)) {
http_response_code(400);
echo json_encode(['error' => 'template_ids requerido como array']);
exit;
}
$placeholders = str_repeat('?,', count($templateIds) - 1) . '?';
$stmt = $db->query(
"UPDATE message_templates SET status = 'approved', updated_at = NOW() WHERE id IN ($placeholders)",
$templateIds
);
echo json_encode([
'success' => true,
'message' => 'Plantillas aprobadas masivamente',
'updated_count' => $stmt->rowCount()
]);
break;
case 'sync_from_meta':
// Función futura para sincronizar desde Meta API
echo json_encode([
'success' => false,
'error' => 'Función no implementada aún',
'note' => 'Para implementar: consultar API de Meta para estado real de plantillas'
]);
break;
default:
http_response_code(400);
echo json_encode(['error' => 'Acción no válida']);
break;
}
} catch (Exception $e) {
http_response_code(500);
echo json_encode([
'success' => false,
'error' => 'Error interno: ' . $e->getMessage()
]);
}
?>
+3
View File
@@ -6,6 +6,9 @@
require_once '../config/config.php';
// Verificar autenticación
requireAuthentication();
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST');
+97
View File
@@ -0,0 +1,97 @@
<?php
/**
* API - Guardar/Crear plantilla de mensaje
* Fecha: 3 de enero de 2026
*/
require_once '../config/config.php';
// Suprimir errores para obtener JSON limpio
error_reporting(E_ERROR | E_PARSE);
// Modo debug: desactivar autenticación si existe el parámetro debug
$debugMode = isset($_GET['debug']) && $_GET['debug'] === 'true';
if (!$debugMode) {
requireAuthentication();
}
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;
}
$name = trim($input['name'] ?? '');
$templateName = trim($input['whatsapp_name'] ?? $input['template_name'] ?? '');
$languageCode = $input['language'] ?? $input['language_code'] ?? 'es';
$category = $input['category'] ?? 'utility';
// Validaciones
if (empty($name)) {
http_response_code(400);
echo json_encode(['error' => 'El nombre es requerido']);
exit;
}
if (empty($templateName)) {
http_response_code(400);
echo json_encode(['error' => 'El nombre de la plantilla de WhatsApp es requerido']);
exit;
}
// Verificar si ya existe
$db = Database::getInstance();
$existing = $db->fetch(
"SELECT id FROM message_templates WHERE name = :name OR template_name = :template_name",
['name' => $name, 'template_name' => $templateName]
);
if ($existing) {
http_response_code(400);
echo json_encode(['error' => 'Ya existe una plantilla con ese nombre']);
exit;
}
// Crear la plantilla
$templateId = $db->insert('message_templates', [
'name' => $name,
'template_name' => $templateName,
'language_code' => $languageCode,
'category' => $category,
'status' => 'pending', // Siempre inicia como pendiente
'created_at' => date('Y-m-d H:i:s')
]);
if ($templateId) {
echo json_encode([
'success' => true,
'message' => 'Plantilla creada correctamente. Estado: Pendiente de aprobación por WhatsApp.',
'id' => $templateId,
'note' => 'La plantilla debe ser aprobada en WhatsApp Business Manager antes de poder usarse.'
]);
} else {
http_response_code(500);
echo json_encode(['error' => 'Error creando la plantilla']);
}
} catch (Exception $e) {
error_log("Error in save_template.php: " . $e->getMessage());
http_response_code(500);
echo json_encode(['error' => 'Error interno del servidor: ' . $e->getMessage()]);
}
?>
+3
View File
@@ -6,6 +6,9 @@
require_once '../config/config.php';
// Verificar autenticación
requireAuthentication();
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST');
+347 -39
View File
@@ -1,11 +1,21 @@
<?php
/**
* API - Enviar mensaje individual
* Fecha: 13 de noviembre de 2025
* Fecha: 4 de enero de 2026
*/
require_once '../config/config.php';
// Suprimir errores para obtener JSON limpio
error_reporting(E_ERROR | E_PARSE);
// Modo debug: desactivar autenticación si existe el parámetro debug
$debugMode = isset($_GET['debug']) && $_GET['debug'] === 'true';
if (!$debugMode) {
requireAuthentication();
}
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST');
@@ -20,54 +30,352 @@ if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
try {
$input = json_decode(file_get_contents('php://input'), true);
if (!$input || !isset($input['recipient'])) {
if (!$input) {
http_response_code(400);
echo json_encode(['error' => 'Datos inválidos']);
echo json_encode(['error' => 'JSON inválido']);
exit;
}
$recipient = $input['recipient'];
$type = $input['type'] ?? 'text';
$db = Database::getInstance();
$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;
// Modo debug: simular envío exitoso
if ($debugMode) {
$recipient = $input['recipient'] ?? $input['user_id'] ?? 'unknown';
$message = $input['message'] ?? 'mensaje de prueba';
$type = $input['type'] ?? 'text';
$template = $input['template'] ?? $input['template_name'] ?? null;
$responseData = [
'recipient' => $recipient,
'type' => $type,
'timestamp' => date('Y-m-d H:i:s'),
'warning' => 'Para envío real, verifica que el usuario haya respondido en las últimas 24h o usa plantillas'
];
if ($type === 'template') {
// Detectar formato de plantilla
if (isset($input['template']) && is_array($input['template'])) {
// Formato WhatsApp estándar
$templateData = $input['template'];
$responseData['template_name'] = $templateData['name'] ?? 'unknown';
$responseData['language'] = $templateData['language']['code'] ?? 'es';
$responseData['format'] = 'whatsapp_standard';
$message = "Plantilla WhatsApp: {$templateData['name']}";
} else {
// Formato simple
$template = $input['template'] ?? $input['template_name'] ?? null;
$responseData['template_name'] = $template;
$responseData['language'] = $input['language'] ?? 'es';
$responseData['format'] = 'simple';
$message = "Plantilla: {$template}";
}
$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) {
} else {
$responseData['message'] = $message;
}
echo json_encode([
'success' => true,
'message' => 'Mensaje enviado correctamente',
'whatsapp_response' => $response
'message' => 'Mensaje simulado enviado correctamente (modo debug) - NOTA: En producción, usa plantillas para números que no han respondido en 24h',
'data' => $responseData
]);
exit;
}
// Modo 1: Envío directo a número de teléfono (formato original)
if (isset($input['recipient'])) {
$recipient = $input['recipient'];
$type = $input['type'] ?? 'text';
// Verificar si es mensaje de texto y si el usuario respondió en las últimas 24h
if ($type === 'text') {
$stmt = $db->query(
"SELECT MAX(created_at) as last_message FROM conversations
WHERE phone_number = ? AND direction = 'incoming'
AND created_at >= DATE_SUB(NOW(), INTERVAL 24 HOUR)",
[$recipient]
);
$lastMessage = $stmt->fetch();
if (!$lastMessage || !$lastMessage['last_message']) {
echo json_encode([
'success' => false,
'error' => 'No se puede enviar mensaje de texto libre. El usuario no ha respondido en las últimas 24 horas.',
'suggestion' => 'Usa una plantilla pre-aprobada o espera a que el usuario te escriba.',
'error_code' => 'OUTSIDE_24H_WINDOW'
]);
exit;
}
}
$whatsappService = new WhatsAppService();
$response = null;
switch ($type) {
case 'text':
if (!isset($input['message']) || empty($input['message'])) {
http_response_code(400);
echo json_encode(['error' => 'Mensaje requerido']);
exit;
}
// DEBUG: Mostrar datos de envío de mensaje de texto
error_log("=== DEBUG WHATSAPP TEXT MESSAGE ===");
error_log("Recipient: " . $recipient);
error_log("Message: " . $input['message']);
error_log("Method: sendTextMessage()");
error_log("====================================");
$response = $whatsappService->sendTextMessage($recipient, $input['message']);
break;
case 'template':
// Formato 1: Simple (actual)
if (isset($input['template_name']) || (isset($input['template']) && !is_array($input['template']))) {
$template = $input['template'] ?? $input['template_name'] ?? '';
if (empty($template)) {
http_response_code(400);
echo json_encode(['error' => 'Template requerido']);
exit;
}
$language = $input['language'] ?? 'es';
$parameters = $input['parameters'] ?? [];
// Verificar plantilla en base de datos (opcional)
$templateRecord = null;
try {
$stmt = $db->query(
"SELECT * FROM message_templates WHERE template_name = ? LIMIT 1",
[$template]
);
$templateRecord = $stmt->fetch();
} catch (Exception $e) {
// Si no existe la tabla, continuar sin validación local
error_log("Template validation skipped: " . $e->getMessage());
}
// Solo validar si la tabla existe y encontramos registros
if ($templateRecord && $templateRecord['status'] !== 'approved') {
echo json_encode([
'success' => false,
'error' => 'Plantilla no aprobada en el sistema local',
'template_name' => $template,
'template_status' => $templateRecord['status'],
'suggestions' => [
'1. Aprueba la plantilla desde la pestaña Plantillas',
'2. O verifica que esté aprobada en WhatsApp Business Manager',
'3. Usa el nombre exacto de la plantilla'
]
]);
exit;
}
// Usar el idioma de la base de datos si no se especifica
if ($language === 'es' && $templateRecord['language_code']) {
$language = $templateRecord['language_code'];
}
// DEBUG: Mostrar datos de envío de plantilla formato simple
error_log("=== DEBUG WHATSAPP TEMPLATE MESSAGE (SIMPLE FORMAT) ===");
error_log("Recipient: " . $recipient);
error_log("Template Name: " . $template);
error_log("Language: " . $language);
error_log("Parameters: " . json_encode($parameters));
error_log("Template Record Status: " . ($templateRecord ? $templateRecord['status'] : 'not found in DB'));
error_log("Method: sendTemplateMessage()");
error_log("========================================================");
$response = $whatsappService->sendTemplateMessage($recipient, $template, $language, $parameters);
}
// Formato 2: WhatsApp Business API estándar
elseif (isset($input['template']) && is_array($input['template'])) {
$templateData = $input['template'];
$templateName = $templateData['name'] ?? '';
$languageCode = $templateData['language']['code'] ?? 'es';
$components = $templateData['components'] ?? [];
if (empty($templateName)) {
http_response_code(400);
echo json_encode(['error' => 'Template name requerido en formato WhatsApp']);
exit;
}
// Convertir formato WhatsApp a nuestro servicio
$parameters = [];
foreach ($components as $component) {
if ($component['type'] === 'body' && isset($component['parameters'])) {
foreach ($component['parameters'] as $param) {
$parameters[] = $param['text'] ?? '';
}
}
}
// DEBUG: Mostrar datos de envío de plantilla formato WhatsApp estándar
error_log("=== DEBUG WHATSAPP TEMPLATE MESSAGE (WHATSAPP STANDARD FORMAT) ===");
error_log("Recipient: " . $recipient);
error_log("Template Name: " . $templateName);
error_log("Language Code: " . $languageCode);
error_log("Original Components: " . json_encode($components));
error_log("Converted Parameters: " . json_encode($parameters));
error_log("Full Template Data: " . json_encode($templateData));
error_log("Method: sendTemplateMessage()");
error_log("=================================================================");
$response = $whatsappService->sendTemplateMessage($recipient, $templateName, $languageCode, $parameters);
}
else {
http_response_code(400);
echo json_encode(['error' => 'Template requerido (formato simple o WhatsApp estándar)']);
exit;
}
break;
default:
http_response_code(400);
echo json_encode(['error' => 'Tipo de mensaje no soportado']);
exit;
}
if ($response) {
// DEBUG: Mostrar respuesta exitosa de WhatsApp
error_log("=== DEBUG WHATSAPP SUCCESS RESPONSE ===");
error_log("Response: " . json_encode($response));
error_log("======================================");
echo json_encode([
'success' => true,
'message' => 'Mensaje enviado correctamente',
'whatsapp_response' => $response
]);
} else {
// DEBUG: Mostrar error de respuesta de WhatsApp
error_log("=== DEBUG WHATSAPP ERROR RESPONSE ===");
error_log("Response was NULL or FALSE");
error_log("Type: " . $type);
error_log("====================================");
// Error específico para plantillas con soluciones detalladas
if ($type === 'template') {
$templateName = $input['template_name'] ?? $input['template'] ?? 'unknown';
$language = $input['language'] ?? 'es';
echo json_encode([
'success' => false,
'error' => 'Error #132001: Template name does not exist in the translation',
'template_name' => $templateName,
'language' => $language,
'error_analysis' => [
'El error #132001 indica que WhatsApp no encuentra la plantilla',
'Esto puede suceder por varias razones:'
],
'solutions' => [
'1. CREAR PLANTILLA: Ve a WhatsApp Business Manager → Account Tools → Message Templates',
'2. APROBAR PLANTILLA: Asegúrate que Meta haya aprobado tu plantilla',
'3. NOMBRE EXACTO: Usa el nombre exacto (case-sensitive)',
'4. IDIOMA CORRECTO: Usa el código exacto (en_US, es_ES, etc.)',
'5. TIEMPO DE PROPAGACIÓN: Espera 15-30 min después de la aprobación'
],
'debug_info' => [
'template_attempted' => $templateName,
'language_attempted' => $language,
'common_templates' => ['hello_world', 'sample_shipping_confirmation'],
'common_languages' => ['en_US', 'es_ES', 'es_MX']
],
'next_steps' => [
'1. Verifica en WhatsApp Business Manager si la plantilla existe',
'2. Crea una plantilla simple primero (ej: "hello_world")',
'3. Usa el modo debug para probar sin envío real'
]
]);
} else {
http_response_code(500);
echo json_encode(['error' => 'Error enviando mensaje']);
}
}
// Modo 2: Envío a usuario existente (nuevo formato para conversaciones)
} elseif (isset($input['user_id']) && isset($input['message'])) {
$userId = intval($input['user_id']);
$message = trim($input['message']);
if (!$userId || !$message) {
http_response_code(400);
echo json_encode(['error' => 'user_id y message son requeridos']);
exit;
}
// Obtener información del usuario
$stmt = $db->query(
"SELECT phone_number, name FROM users WHERE id = ?",
[$userId]
);
$user = $stmt->fetch();
if (!$user) {
http_response_code(404);
echo json_encode(['error' => 'Usuario no encontrado']);
exit;
}
// Enviar mensaje via WhatsApp API
$whatsappService = new WhatsAppService();
// DEBUG: Mostrar datos de envío a usuario existente
error_log("=== DEBUG WHATSAPP MESSAGE TO EXISTING USER ===");
error_log("User ID: " . $userId);
error_log("User Name: " . ($user['name'] ?? 'N/A'));
error_log("Phone Number: " . $user['phone_number']);
error_log("Message: " . $message);
error_log("Method: sendTextMessage()");
error_log("===============================================");
$response = $whatsappService->sendTextMessage($user['phone_number'], $message);
if ($response && isset($response['messages']) && !empty($response['messages'])) {
// Guardar mensaje en la base de datos
$messageData = [
'user_id' => $userId,
'content' => $message,
'direction' => 'outgoing',
'message_type' => 'text',
'status' => 'sent',
'message_id' => $response['messages'][0]['id'] ?? null,
'created_at' => date('Y-m-d H:i:s')
];
// Intentar insertar en conversations primero
try {
$stmt = $db->query(
"INSERT INTO conversations (user_id, content, direction, message_type, status, message_id, created_at) VALUES (?, ?, ?, ?, ?, ?, ?)",
array_values($messageData)
);
} catch (Exception $e) {
// Si falla, intentar en messages
try {
$stmt = $db->query(
"INSERT INTO messages (user_id, message_text, direction, message_type, status, message_id, created_at) VALUES (?, ?, ?, ?, ?, ?, ?)",
[$userId, $message, 'outgoing', 'text', 'sent', $response['messages'][0]['id'] ?? null, date('Y-m-d H:i:s')]
);
} catch (Exception $e2) {
error_log("Error guardando mensaje: " . $e2->getMessage());
}
}
echo json_encode([
'success' => true,
'message' => 'Mensaje enviado correctamente',
'whatsapp_response' => $response
]);
} else {
echo json_encode([
'success' => false,
'error' => 'Error al enviar mensaje por WhatsApp'
]);
}
} else {
http_response_code(500);
echo json_encode(['error' => 'Error enviando mensaje']);
http_response_code(400);
echo json_encode(['error' => 'Formato de datos inválido. Se requiere recipient o user_id+message']);
exit;
}
} catch (Exception $e) {
+152
View File
@@ -0,0 +1,152 @@
<?php
/**
* API de prueba para configuraciones (sin autenticación)
*/
require_once '../config/config.php';
// Simular autenticación para pruebas
session_start();
$_SESSION['admin_logged_in'] = true;
$_SESSION['admin_username'] = 'test_admin';
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type');
$method = $_SERVER['REQUEST_METHOD'];
$action = $_GET['action'] ?? '';
try {
// Respuesta simple para test de conectividad
if ($action === 'ping') {
echo json_encode([
'success' => true,
'message' => 'API funcionando correctamente',
'timestamp' => date('Y-m-d H:i:s'),
'method' => $method
]);
exit;
}
switch ($method) {
case 'GET':
switch ($action) {
case 'status':
// Estado general del sistema
$allConfigs = getAllConfigsFromDB();
$whatsappValidation = validateWhatsAppConfigFromDB();
echo json_encode([
'success' => true,
'data' => [
'total_configs' => count($allConfigs),
'whatsapp_configured' => $whatsappValidation['valid'],
'database_migrated' => !empty($allConfigs),
'installation_completed' => isInstallationCompleted(),
'server_time' => date('Y-m-d H:i:s')
]
]);
break;
case 'all':
// Obtener todas las configuraciones
$configs = getAllConfigsFromDB();
echo json_encode([
'success' => true,
'data' => $configs
]);
break;
case 'whatsapp':
// Obtener configuración de WhatsApp
$whatsappConfig = getWhatsAppConfigFromDB();
echo json_encode([
'success' => true,
'data' => $whatsappConfig
]);
break;
case 'test_db':
// Test de conexión a BD
try {
$pdo = createDbConnection();
$tableExists = $pdo->query("SHOW TABLES LIKE 'system_config'")->rowCount() > 0;
echo json_encode([
'success' => true,
'data' => [
'db_connected' => true,
'table_exists' => $tableExists,
'config_count' => $tableExists ? $pdo->query("SELECT COUNT(*) FROM system_config")->fetchColumn() : 0
]
]);
} catch (Exception $e) {
echo json_encode([
'success' => false,
'error' => 'Error de BD: ' . $e->getMessage()
]);
}
break;
default:
throw new Exception('Acción GET no reconocida: ' . $action);
}
break;
case 'POST':
$input = json_decode(file_get_contents('php://input'), true);
switch ($action) {
case 'save_test':
// Guardar configuración de prueba
$key = 'api_test_' . time();
$value = 'Test desde API - ' . date('Y-m-d H:i:s');
$result = saveConfigToDB($key, $value, 'Prueba desde API');
echo json_encode([
'success' => $result,
'message' => $result ? 'Configuración guardada correctamente' : 'Error guardando configuración',
'data' => [
'key' => $key,
'value' => $value
]
]);
break;
case 'save_whatsapp_test':
// Guardar config de WhatsApp de prueba
$testConfig = [
'token' => 'test_token_' . time(),
'phone_number_id' => '123456789',
'webhook_verify_token' => 'webhook_' . time()
];
$result = saveWhatsAppConfigToDB($testConfig);
echo json_encode([
'success' => $result,
'message' => $result ? 'WhatsApp config guardada' : 'Error guardando WhatsApp config',
'data' => $testConfig
]);
break;
default:
throw new Exception('Acción POST no reconocida: ' . $action);
}
break;
default:
throw new Exception('Método HTTP no permitido: ' . $method);
}
} catch (Exception $e) {
http_response_code(500);
echo json_encode([
'success' => false,
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString()
]);
}
?>
+79
View File
@@ -0,0 +1,79 @@
<?php
/**
* API - Actualizar estado de plantilla
* Fecha: 3 de enero de 2026
*/
require_once '../config/config.php';
// Verificar autenticación
requireAuthentication();
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: PUT, POST');
header('Access-Control-Allow-Headers: Content-Type');
if (!in_array($_SERVER['REQUEST_METHOD'], ['PUT', '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['id']) || !isset($input['status'])) {
http_response_code(400);
echo json_encode(['error' => 'ID y estado requeridos']);
exit;
}
$templateId = (int) $input['id'];
$status = $input['status'];
// Validar estado
if (!in_array($status, ['pending', 'approved', 'rejected'])) {
http_response_code(400);
echo json_encode(['error' => 'Estado inválido']);
exit;
}
$db = Database::getInstance();
// Verificar que la plantilla existe
$template = $db->fetch(
"SELECT * FROM message_templates WHERE id = :id",
['id' => $templateId]
);
if (!$template) {
http_response_code(404);
echo json_encode(['error' => 'Plantilla no encontrada']);
exit;
}
// Actualizar estado
$updated = $db->update('message_templates',
['status' => $status],
['id' => $templateId]
);
if ($updated) {
echo json_encode([
'success' => true,
'message' => 'Estado de plantilla actualizado correctamente',
'template' => $template['name'],
'new_status' => $status
]);
} else {
http_response_code(500);
echo json_encode(['error' => 'Error actualizando el estado']);
}
} catch (Exception $e) {
error_log("Error in update_template_status.php: " . $e->getMessage());
http_response_code(500);
echo json_encode(['error' => 'Error interno del servidor: ' . $e->getMessage()]);
}
?>