arcos-backend/app/Services/ReporteRoboService.php

188 lines
6.3 KiB
PHP

<?php
namespace App\Services;
use Exception;
use Illuminate\Support\Facades\Log;
class ReporteRoboService
{
private string $baseUrl;
private string $roboEndpoint;
private string $username;
private string $password;
public function __construct()
{
$this->baseUrl = config('services.repuve_federal.base_url');
$this->roboEndpoint = config('services.repuve_federal.robo_endpoint');
$this->username = config('services.repuve_federal.username');
$this->password = config('services.repuve_federal.password');
}
public function consultarPorVin(?string $vin = null, ?string $placa = null)
{
try {
if (empty($vin) && empty($placa)) {
Log::warning('ReporteRoboService: No se proporcionó VIN ni PLACA');
return [
'tiene_reporte' => false,
'datos' => [],
'error' => 'Debe proporcionar al menos VIN o PLACA'
];
}
$url = $this->baseUrl . $this->roboEndpoint;
// Construir arg2 según los parámetros
if (!empty($vin) && !empty($placa)) {
$arg2 = $vin . '|' . $placa . str_repeat('|', 5);
} elseif (!empty($vin)) {
$arg2 = $vin . str_repeat('|', 7);
} else {
$arg2 = '||' . $placa . str_repeat('|', 5);
}
Log::info('ReporteRoboService: Consultando REPUVE', [
'vin' => $vin,
'placa' => $placa
]);
$soapBody = <<<XML
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsdl="http://consultaRpv.org/wsdl">
<soapenv:Header/>
<soapenv:Body>
<wsdl:doConsRepRobo>
<arg0>{$this->username}</arg0>
<arg1>{$this->password}</arg1>
<arg2>{$arg2}</arg2>
</wsdl:doConsRepRobo>
</soapenv:Body>
</soapenv:Envelope>
XML;
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $soapBody);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: text/xml; charset=utf-8',
'SOAPAction: "doConsRepRobo"',
'Content-Length: ' . strlen($soapBody),
]);
try {
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
if ($error) {
Log::error('ReporteRoboService: Error de conexión', ['error' => $error]);
return [
'tiene_reporte' => false,
'datos' => [],
'error' => 'Error de conexión con REPUVE'
];
}
if ($httpCode !== 200) {
Log::error('ReporteRoboService: HTTP error', ['http_code' => $httpCode]);
return [
'tiene_reporte' => false,
'datos' => [],
'error' => "Error HTTP {$httpCode}"
];
}
return $this->parseRoboResponse($response, $vin ?? $placa);
} finally {
unset($ch);
}
} catch (Exception $e) {
Log::error('ReporteRoboService: Excepción', ['message' => $e->getMessage()]);
return [
'tiene_reporte' => false,
'datos' => [],
'error' => $e->getMessage()
];
}
}
/**
* Parsea la respuesta del servicio de robo
*/
private function parseRoboResponse(string $soapResponse, string $valor)
{
// Extraer contenido
preg_match('/<return>(.*?)<\/return>/s', $soapResponse, $matches);
if (!isset($matches[1])) {
Log::error('ReporteRoboService:');
return [
'tiene_reporte' => false,
'datos' => [],
'error' => 'Respuesta SOAP inválida'
];
}
$contenido = trim($matches[1]);
// Verificar si hay error (ERR: o ERROR:)
if (preg_match('/(ERR|ERROR|err|error):(-?\d+)/i', $contenido, $errorMatch)) {
$errorCode = $errorMatch[2];
Log::warning('ReporteRoboService: Error del servicio', ['error_code' => $errorCode]);
return [
'tiene_reporte' => false,
'datos' => ['error_code' => $errorCode],
'error' => "Error REPUVE código {$errorCode}"
];
}
// Si empieza con OK:, parsear los datos
if (str_starts_with($contenido, 'OK:')) {
$datos = str_replace('OK:', '', $contenido);
$valores = explode('|', $datos);
// 1 = robado, 0 = no robado
$indicador = $valores[0] ?? '0';
$tieneReporte = ($indicador === '1');
$datosRobo = [
'indicador' => $indicador,
'fecha_robo' => $valores[1] ?? null,
'placa' => $valores[2] ?? null,
'vin' => $valores[3] ?? null,
'autoridad' => $valores[4] ?? null,
'acta' => $valores[5] ?? null,
'denunciante' => $valores[6] ?? null,
'fecha_acta' => $valores[7] ?? null,
];
if ($tieneReporte) {
Log::warning('ReporteRoboService: ¡VEHÍCULO ROBADO DETECTADO!', [
'vin' => $datosRobo['vin'],
'placa' => $datosRobo['placa'],
'autoridad' => $datosRobo['autoridad']
]);
}
return [
'tiene_reporte' => $tieneReporte,
'datos' => $datosRobo
];
}
Log::error('ReporteRoboService:', ['contenido' => $contenido]);
return [
'tiene_reporte' => false,
'datos' => [],
'error' => 'Formato de respuesta no reconocido'
];
}
}