371 lines
13 KiB
PHP
371 lines
13 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 consultarRobado(?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);
|
|
}
|
|
|
|
$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 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'
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Consultar datos del vehículo (sin reporte de robo)
|
|
*/
|
|
public function consultarVehiculo(?string $niv = null, ?string $placa = null): array
|
|
{
|
|
try {
|
|
if (empty($niv) && empty($placa)) {
|
|
Log::warning('ReporteRoboService: consultarVehiculo sin NIV ni PLACA');
|
|
return [
|
|
'success' => false,
|
|
'has_error' => true,
|
|
'error_message' => 'Debe proporcionar al menos NIV o PLACA',
|
|
'datos' => []
|
|
];
|
|
}
|
|
|
|
$url = $this->baseUrl . '/jaxws-consultarpv/ConsultaRpv';
|
|
|
|
// Construir arg2
|
|
if ($placa) {
|
|
$arg2 = ($niv ?? '') . '|' . $placa . str_repeat('|', 5);
|
|
} else {
|
|
$arg2 = ($niv ?? '') . str_repeat('|', 7);
|
|
}
|
|
|
|
$soapBody = <<<XML
|
|
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsdl="http://consultaRpv.org/wsdl">
|
|
<soapenv:Header/>
|
|
<soapenv:Body>
|
|
<wsdl:doConsRPV>
|
|
<arg0>{$this->username}</arg0>
|
|
<arg1>{$this->password}</arg1>
|
|
<arg2>{$arg2}</arg2>
|
|
</wsdl:doConsRPV>
|
|
</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: "doConsRPV"',
|
|
'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: consultarVehiculo - Error de conexión', [
|
|
'error' => $error,
|
|
'niv' => $niv,
|
|
'placa' => $placa
|
|
]);
|
|
return [
|
|
'success' => false,
|
|
'has_error' => true,
|
|
'error_message' => 'Error de conexión',
|
|
'datos' => []
|
|
];
|
|
}
|
|
|
|
if ($httpCode !== 200) {
|
|
Log::error('ReporteRoboService: consultarVehiculo - HTTP error', [
|
|
'http_code' => $httpCode,
|
|
'niv' => $niv,
|
|
'placa' => $placa
|
|
]);
|
|
return [
|
|
'success' => false,
|
|
'has_error' => true,
|
|
'error_message' => "Error HTTP {$httpCode}",
|
|
'datos' => []
|
|
];
|
|
}
|
|
|
|
return $this->parseConsultaVehiculoResponse($response);
|
|
|
|
} finally {
|
|
unset($ch);
|
|
}
|
|
} catch (\Exception $e) {
|
|
Log::error('ReporteRoboService: consultarVehiculo - Excepción', [
|
|
'niv' => $niv,
|
|
'placa' => $placa,
|
|
'exception' => $e->getMessage()
|
|
]);
|
|
return [
|
|
'success' => false,
|
|
'has_error' => true,
|
|
'error_message' => $e->getMessage(),
|
|
'datos' => []
|
|
];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Parsear respuesta de consulta de vehículo
|
|
* Extrae solo: VIN, placa, marca, modelo y color
|
|
*/
|
|
private function parseConsultaVehiculoResponse(string $soapResponse): array
|
|
{
|
|
// Extraer contenido del tag <return>
|
|
preg_match('/<return>(.*?)<\/return>/s', $soapResponse, $matches);
|
|
|
|
if (!isset($matches[1])) {
|
|
Log::error('ReporteRoboService: parseConsultaVehiculoResponse - Respuesta inválida');
|
|
return [
|
|
'success' => false,
|
|
'has_error' => true,
|
|
'error_message' => 'Respuesta inválida del servicio',
|
|
'datos' => []
|
|
];
|
|
}
|
|
|
|
$contenido = trim($matches[1]);
|
|
|
|
// Verificar si hay error
|
|
if (preg_match('/(ERR|ERROR):(-?\d+)/i', $contenido, $errorMatch)) {
|
|
$errorCode = $errorMatch[2];
|
|
Log::warning('ReporteRoboService: parseConsultaVehiculoResponse - Error del servicio', [
|
|
'error_code' => $errorCode
|
|
]);
|
|
return [
|
|
'success' => false,
|
|
'has_error' => true,
|
|
'error_message' => "Error REPUVE código {$errorCode}",
|
|
'datos' => []
|
|
];
|
|
}
|
|
|
|
// Si empieza con OK:, parsear los datos
|
|
if (str_starts_with($contenido, 'OK:')) {
|
|
$datos = str_replace('OK:', '', $contenido);
|
|
$valores = explode('|', $datos);
|
|
|
|
// Estructura esperada del REPUVE Nacional
|
|
// Posiciones aproximadas basadas en el servicio
|
|
$datosVehiculo = [
|
|
'vin' => $valores[0] ?? null,
|
|
'placa' => $valores[1] ?? null,
|
|
'marca' => $valores[2] ?? null,
|
|
'modelo' => $valores[3] ?? null,
|
|
'color' => $valores[4] ?? null,
|
|
];
|
|
|
|
// Filtrar valores vacíos
|
|
$datosVehiculo = array_filter($datosVehiculo, fn($v) => !empty($v));
|
|
|
|
if (empty($datosVehiculo)) {
|
|
return [
|
|
'success' => false,
|
|
'has_error' => false,
|
|
'error_message' => 'No se encontró información del vehículo',
|
|
'datos' => []
|
|
];
|
|
}
|
|
|
|
Log::info('ReporteRoboService: Vehículo encontrado en REPUVE Nacional', [
|
|
'vin' => $datosVehiculo['vin'] ?? null,
|
|
'placa' => $datosVehiculo['placa'] ?? null
|
|
]);
|
|
|
|
return [
|
|
'success' => true,
|
|
'has_error' => false,
|
|
'datos' => $datosVehiculo
|
|
];
|
|
}
|
|
|
|
Log::error('ReporteRoboService: parseConsultaVehiculoResponse - Formato no reconocido', [
|
|
'contenido' => $contenido
|
|
]);
|
|
return [
|
|
'success' => false,
|
|
'has_error' => true,
|
|
'error_message' => 'Formato de respuesta no reconocido',
|
|
'datos' => []
|
|
];
|
|
}
|
|
}
|