/
home
/
suroeste
/
public_html
/
payments.transportessuroeste.com
/
public
/
/home/suroeste/public_html/payments.transportessuroeste.com/public
mkdir
upload
Name
Size
Mode
Actions
assets/
-
0755
rm
payment/
-
0755
rm
epayco-check.php
89
0644
edit
dl
rm
index.php
9280
0644
edit
dl
rm
Edit:
/home/suroeste/public_html/payments.transportessuroeste.com/public/index.php
(9280B)
<?php /** * ============================================================================ * TRANSPORTES SUROESTE - API PASARELA DE PAGOS * ============================================================================ */ declare(strict_types=1); // ============================================================================ // PÁGINAS DE PAGO - CSP específico para ePayco // ============================================================================ $requestUri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); if (strpos($requestUri, '/payment/response') !== false || strpos($requestUri, '/payment/checkout') !== false || strpos($requestUri, '/payment/retry') !== false) { // Limpiar headers previos if (function_exists('header_remove')) { header_remove(); } // Generar nonce único $nonce = base64_encode(random_bytes(16)); // Todos los dominios de ePayco (descubiertos de los errores) $epaycoConnect = implode(' ', [ 'https://checkout.epayco.co', 'https://api.epayco.co', 'https://apify.epayco.co', 'https://apify-private.epayco.co', 'https://ms-checkout-create-transaction.epayco.co', 'https://*.epayco.co', 'https://fonts.googleapis.com' // // Wildcard para futuros subdominios ]); $epaycoFrames = implode(' ', [ 'https://checkout.epayco.co', 'https://new-checkout.epayco.co', 'https://*.epayco.co', 'https://fonts.googleapis.com' ]); $epaycoScripts = 'https://checkout.epayco.co https://*.epayco.co https://fonts.googleapis.com'; $epaycoImages = 'https://369969691f476073508a-60bf0867add971908d4f26a64519c2aa.ssl.cf5.rackcdn.com https://*.epayco.co https://fonts.googleapis.com' ; // CSP para páginas de pago $csp = implode('; ', [ "default-src 'self'", "script-src 'self' 'nonce-{$nonce}' 'unsafe-eval' {$epaycoScripts}", "script-src-elem 'self' 'nonce-{$nonce}' {$epaycoScripts}", "style-src 'self' 'unsafe-inline'", "style-src-elem 'self' 'unsafe-inline'", "img-src 'self' data: {$epaycoImages}", "connect-src 'self' {$epaycoConnect}", "frame-src 'self' {$epaycoFrames}", "object-src 'none'", "base-uri 'self'" ]); header("Content-Security-Policy: {$csp}"); header('X-Frame-Options: SAMEORIGIN'); header('X-Content-Type-Options: nosniff'); header('X-XSS-Protection: 1; mode=block'); header('Referrer-Policy: strict-origin-when-cross-origin'); header('Content-Type: text/html; charset=utf-8'); define('CSP_NONCE', $nonce); define('SKIP_SECURITY_HEADERS', true); require_once __DIR__ . '/../config/config.php'; if (strpos($requestUri, '/payment/checkout') !== false) { require __DIR__ . '/payment/checkout.php'; } elseif (strpos($requestUri, '/payment/retry') !== false) { require __DIR__ . '/payment/retry.php'; } else { require __DIR__ . '/payment/response.php'; } exit; } // ============================================================================ // API NORMAL // ============================================================================ error_reporting(E_ALL); ini_set('display_errors', '0'); $startTime = microtime(true); require_once __DIR__ . '/../config/config.php'; use TransportesSuroeste\Controllers\ApiController; use TransportesSuroeste\Middleware\{AuthMiddleware, RateLimiter, SecurityMiddleware}; use TransportesSuroeste\Services\LogService; use TransportesSuroeste\Utils\{Router, JsonResponse}; use TransportesSuroeste\Exceptions\{ApiException, ValidationException, AuthenticationException, RateLimitException, SecurityException}; // ============================================================================ // MANEJO DE ERRORES // ============================================================================ set_error_handler(function ($severity, $message, $file, $line) { throw new ErrorException($message, 0, $severity, $file, $line); }); set_exception_handler(function (Throwable $e) use ($startTime) { $code = $e instanceof ApiException ? $e->getHttpCode() : 500; $errors = $e instanceof ValidationException ? $e->getErrors() : []; // Log completo (siempre, incluyendo detalles internos) LogService::error('errors', $e->getMessage(), [ 'exception' => get_class($e), 'file' => $e->getFile(), 'line' => $e->getLine(), 'trace' => APP_DEBUG ? $e->getTraceAsString() : null ]); $responseTime = (microtime(true) - $startTime) * 1000; LogService::access($_SERVER['REQUEST_METHOD'], $_SERVER['REQUEST_URI'], $code, $responseTime); // Mensaje seguro para el usuario: nunca filtrar SQL, paths, o stack traces $safeMessage = $e->getMessage(); if (!($e instanceof ApiException)) { // Excepcion no controlada: mensaje generico en produccion $safeMessage = APP_DEBUG ? $e->getMessage() : 'Error interno del servidor'; $code = 500; } JsonResponse::error($safeMessage, $code, $errors); }); // ============================================================================ // CORS // ============================================================================ $allowedOrigin = getenv('CORS_ALLOWED_ORIGIN') ?: ''; if (empty($allowedOrigin) && !empty($_SERVER['HTTP_ORIGIN'])) { // En produccion, restringir a origenes conocidos $allowedOrigin = $_SERVER['HTTP_ORIGIN']; } if (empty($allowedOrigin)) { $allowedOrigin = APP_URL; } if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { header('Access-Control-Allow-Origin: ' . $allowedOrigin); header('Access-Control-Allow-Methods: GET, POST, OPTIONS'); header('Access-Control-Allow-Headers: Content-Type, X-API-Key, X-Signature, X-Timestamp, X-Request-ID'); header('Access-Control-Max-Age: 86400'); exit(0); } header('Access-Control-Allow-Origin: ' . $allowedOrigin); // ============================================================================ // SEGURIDAD // ============================================================================ // Excluir webhooks de ePayco del middleware de seguridad $isEpaycoWebhook = strpos($_SERVER['REQUEST_URI'], '/webhook/epayco') !== false || strpos($_SERVER['REQUEST_URI'], '/callback') !== false; if (!$isEpaycoWebhook) { $security = new SecurityMiddleware(); $security->apply(); } // ============================================================================ // RATE LIMITING // ============================================================================ $rateLimiter = new RateLimiter(); $clientIp = LogService::getClientIp(); try { $rateLimiter->check($clientIp, $_SERVER['REQUEST_URI']); foreach ($rateLimiter->getHeaders($clientIp) as $header => $value) { header("{$header}: {$value}"); } } catch (RateLimitException $e) { throw $e; } // ============================================================================ // CALCULAR URI // ============================================================================ $method = $_SERVER['REQUEST_METHOD']; $uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); $scriptDir = dirname($_SERVER['SCRIPT_NAME']); if ($scriptDir !== '/' && $scriptDir !== '\\' && strpos($uri, $scriptDir) === 0) { $uri = substr($uri, strlen($scriptDir)); } if (empty($uri) || $uri === false) { $uri = '/'; } elseif ($uri[0] !== '/') { $uri = '/' . $uri; } // ============================================================================ // RUTAS // ============================================================================ $router = new Router(); $controller = new ApiController(); // Rutas públicas (sin autenticación) $router->get('/api/v1/health', fn() => $controller->healthCheck(), false); $router->get('/api/v1/banks/pse', fn() => $controller->getPseBanks(), false); $router->post('/api/v1/webhook/epayco', fn() => $controller->handleCallback(), false); $router->get('/api/v1/callback', fn() => $controller->handleCallback(), false); $router->post('/api/v1/callback', fn() => $controller->handleCallback(), false); // Rutas protegidas (requieren API Key) $router->post('/api/v1/payments', fn() => $controller->createPayment(), true); $router->get('/api/v1/payments/{uuid}', fn($p) => $controller->getPayment($p['uuid']), true); $router->get('/api/v1/payments/ticket/{reference}', fn($p) => $controller->getPaymentByTicket($p['reference']), true); // ============================================================================ // DESPACHAR // ============================================================================ $route = $router->dispatch($method, $uri); if ($route['handler'] === null) { throw new ApiException("Endpoint no encontrado: {$method} {$uri}", 404); } // Autenticar si es necesario $client = null; if ($route['auth']) { $auth = new AuthMiddleware(); $client = $auth->authenticate(); $controller->setClient($client); } // Ejecutar $result = call_user_func($route['handler'], $route['params']); // Responder $responseTime = (microtime(true) - $startTime) * 1000; LogService::access($method, $uri, 200, $responseTime, $client['uuid'] ?? null); JsonResponse::send($result, 200);
Save
cmd:
run