34849-vm/shalom_api.php
2026-07-07 03:05:06 +00:00

165 lines
4.8 KiB
PHP

<?php
header('Content-Type: application/json');
// Make sure we ALWAYS return valid JSON from this endpoint, even when
// upstream error bodies include invalid UTF-8 bytes.
$jsonOptions = JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE | JSON_PARTIAL_OUTPUT_ON_ERROR;
function respond_json(int $statusCode, array $payload, int $jsonOptions): void {
http_response_code($statusCode);
$json = json_encode($payload, $jsonOptions);
if ($json === false) {
$json = '{"error":"Error serializando la respuesta"}';
}
echo $json;
exit;
}
// Inputs
$orderNumber = trim($_GET['orderNumber'] ?? '');
$orderCode = trim($_GET['orderCode'] ?? '');
if ($orderNumber === '' || $orderCode === '') {
respond_json(400, ['error' => 'Número de orden y código de orden son requeridos.'], $jsonOptions);
}
// Load env from executor/.env (helps when Apache/PHP doesn't export .env vars)
function load_dotenv_if_needed(array $keys): void {
$missing = array_filter($keys, fn($k) => getenv($k) === false || getenv($k) === '');
if (empty($missing)) {
return;
}
static $loaded = false;
if ($loaded) return;
$envPath = realpath(__DIR__ . '/../.env'); // executor/.env
if ($envPath && is_readable($envPath)) {
$lines = @file($envPath, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) ?: [];
foreach ($lines as $line) {
$trimmed = trim($line);
if ($trimmed === '' || $trimmed[0] === '#') {
continue;
}
if (!str_contains($trimmed, '=')) continue;
[$k, $v] = array_map('trim', explode('=', $trimmed, 2));
if ($k === '') continue;
// Strip potential surrounding quotes
$v = trim($v, "\"' ");
// Do not override existing process env
if (getenv($k) === false || getenv($k) === '') {
putenv("{$k}={$v}");
}
}
$loaded = true;
}
}
load_dotenv_if_needed(['SHALOM_API_KEY']);
// API
$apiKey = getenv('SHALOM_API_KEY');
// Fallback: allow setting the key from the DB (so the app works even if you can't edit .env)
if (!$apiKey) {
try {
require_once __DIR__ . '/db/config.php';
$pdo = db();
$stmt = $pdo->prepare('SELECT valor FROM configuracion WHERE clave = ? LIMIT 1');
$stmt->execute(['SHALOM_API_KEY']);
$apiKey = $stmt->fetchColumn();
if (is_string($apiKey)) {
$apiKey = trim($apiKey);
} else {
$apiKey = null;
}
} catch (Throwable $e) {
$apiKey = null;
}
}
if (!$apiKey) {
respond_json(500, [
'error' => 'Falta SHALOM_API_KEY. Configura la clave en Configuración General (Administrador) o en tu .env para poder consultar el tracking.',
], $jsonOptions);
}
$url = 'https://shalom-api.lat/api/track';
$postData = [
'orderNumber' => $orderNumber,
'orderCode' => $orderCode,
];
$jsonData = json_encode($postData, JSON_UNESCAPED_UNICODE);
if ($jsonData === false) {
respond_json(500, ['error' => 'Error serializando la solicitud a Shalom.'], $jsonOptions);
}
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $jsonData,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Accept: application/json',
"Authorization: Bearer {$apiKey}",
],
// Timeouts: evitamos que la UI quede esperando indefinidamente
CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_TIMEOUT => 25,
CURLOPT_FOLLOWLOCATION => true,
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$curlError = curl_error($ch);
curl_close($ch);
if ($curlError) {
respond_json(502, [
'error' => 'Error en la comunicación con la API de Shalom',
'details' => $curlError,
], $jsonOptions);
}
if ($response === false || $response === null || $response === '') {
respond_json(502, [
'error' => 'Shalom no devolvió respuesta',
'http_code' => $httpCode ?: null,
], $jsonOptions);
}
// Error HTTP del proveedor
if ($httpCode >= 400) {
$errorBody = json_decode($response, true);
$shMessage = null;
if (json_last_error() === JSON_ERROR_NONE && is_array($errorBody)) {
$shMessage = $errorBody['message'] ?? $errorBody['error'] ?? null;
}
if ($shMessage) {
respond_json($httpCode, [
'error' => "Error de la API de Shalom: {$shMessage}",
'http_code' => $httpCode,
'details' => $errorBody ?: $response,
], $jsonOptions);
}
respond_json($httpCode, [
'error' => "Error de la API de Shalom (código {$httpCode}).",
'http_code' => $httpCode,
'details' => $response,
], $jsonOptions);
}
// OK: devolvemos tal cual lo que responde Shalom (la UI espera JSON)
echo $response;