813 lines
30 KiB
PHP
813 lines
30 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use Exception;
|
|
use App\Models\Error;
|
|
use App\Models\Setting;
|
|
use App\Helpers\EncryptionHelper;
|
|
|
|
class RepuveService
|
|
{
|
|
private string $baseUrl;
|
|
private string $roboEndpoint;
|
|
private string $inscripcionEndpoint;
|
|
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->inscripcionEndpoint = config('services.repuve_federal.inscripcion_endpoint');
|
|
|
|
// Cargar credenciales desde BD (encriptadas)
|
|
$this->loadCredentials();
|
|
}
|
|
|
|
/**
|
|
* Cargar credenciales desde BD
|
|
*/
|
|
private function loadCredentials(): void
|
|
{
|
|
try {
|
|
// Obtener credenciales encriptadas desde BD
|
|
$encryptedCredentials = Setting::value('repuve_federal_credentials');
|
|
|
|
if (!$encryptedCredentials) {
|
|
throw new Exception('Credenciales REPUVE no configuradas en el sistema');
|
|
}
|
|
|
|
$credentials = EncryptionHelper::decryptData($encryptedCredentials);
|
|
|
|
if (!$credentials || !isset($credentials['username'], $credentials['password'])) {
|
|
throw new Exception('Error al desencriptar credenciales REPUVE');
|
|
}
|
|
|
|
$this->username = $credentials['username'];
|
|
$this->password = $credentials['password'];
|
|
|
|
logger()->info('RepuveService: Credenciales cargadas correctamente desde BD');
|
|
} catch (Exception $e) {
|
|
logger()->error('RepuveService: Error al cargar credenciales', [
|
|
'error' => $e->getMessage()
|
|
]);
|
|
|
|
throw new Exception('No se pudieron cargar las credenciales REPUVE: ' . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
public function consultarPadron(string $niv)
|
|
{
|
|
$url = $this->baseUrl . $this->roboEndpoint;
|
|
$arg2 = $niv . '|||||||';
|
|
|
|
$soapBody = <<<XML
|
|
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsdl="http://consultaRpv.org/wsdl">
|
|
<soapenv:Header/>
|
|
<soapenv:Body>
|
|
<wsdl:doConsPadron>
|
|
<arg0>{$this->username}</arg0>
|
|
<arg1>{$this->password}</arg1>
|
|
<arg2>{$arg2}</arg2>
|
|
</wsdl:doConsPadron>
|
|
</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: "doConsPadron"',
|
|
'Content-Length: ' . strlen($soapBody),
|
|
]);
|
|
|
|
try {
|
|
// Ejecutar la solicitud
|
|
$response = curl_exec($ch);
|
|
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
$error = curl_error($ch);
|
|
|
|
if ($error) {
|
|
throw new Exception("Error en la petición SOAP: {$error}");
|
|
}
|
|
|
|
if ($httpCode !== 200) {
|
|
throw new Exception("Error al consultar REPUVE: Código HTTP {$httpCode}");
|
|
}
|
|
|
|
return $this->parseVehicleResponse($response, $niv);
|
|
} finally {
|
|
unset($ch);
|
|
}
|
|
}
|
|
|
|
|
|
private function parseVehicleResponse(string $soapResponse, string $niv)
|
|
{
|
|
preg_match('/<return>(.*?)<\/return>/s', $soapResponse, $matches);
|
|
|
|
if (!isset($matches[1])) {
|
|
$errorFromDb = Error::where('code', '108')->first();
|
|
return [
|
|
'has_error' => true,
|
|
'error_code' => '108',
|
|
'error_name' => $errorFromDb?->name,
|
|
'error_message' => $errorFromDb?->description ?? 'Error al parsear respuesta',
|
|
'timestamp' => now()->toDateTimeString(),
|
|
'niv' => $niv,
|
|
'repuve_response' => null,
|
|
];
|
|
}
|
|
|
|
$contenido = trim($matches[1]);
|
|
|
|
// Verificar si hay error de REPUVE Nacional (cualquier formato con ERR o ERROR)
|
|
if (preg_match('/(ERR|ERROR|err|error):(-?\d+)/i', $contenido, $errorMatch)) {
|
|
$errorCode = $errorMatch[2];
|
|
|
|
// Buscar el error completo en la base de datos
|
|
$errorFromDb = Error::where('code', $errorCode)->first();
|
|
|
|
return [
|
|
'has_error' => true,
|
|
'error_code' => $errorCode,
|
|
'error_name' => $errorFromDb?->name,
|
|
'error_message' => $errorFromDb?->description ?? "Error código {$errorCode} - no catalogado",
|
|
'timestamp' => now()->toDateTimeString(),
|
|
'niv' => $niv,
|
|
'repuve_response' => $contenido,
|
|
];
|
|
}
|
|
|
|
// Si empieza con OK:, parsear los datos
|
|
if (str_starts_with($contenido, 'OK:')) {
|
|
$datos = str_replace('OK:', '', $contenido);
|
|
$valores = explode('|', $datos);
|
|
|
|
$campos = [
|
|
'marca',
|
|
'submarca',
|
|
'tipo_vehiculo',
|
|
'fecha_expedicion',
|
|
'oficina',
|
|
'niv',
|
|
'placa',
|
|
'motor',
|
|
'modelo',
|
|
'color',
|
|
'version',
|
|
'entidad',
|
|
'marca_padron',
|
|
'submarca_padron',
|
|
'tipo_uso_padron',
|
|
'tipo_vehiculo_padron',
|
|
'estatus_registro',
|
|
'aduana',
|
|
'nombre_aduana',
|
|
'patente',
|
|
'pedimento',
|
|
'fecha_pedimento',
|
|
'clave_importador',
|
|
'observaciones'
|
|
];
|
|
|
|
$jsonResponse = [];
|
|
foreach ($campos as $i => $campo) {
|
|
$jsonResponse[$campo] = $valores[$i] ?? null;
|
|
}
|
|
|
|
return [
|
|
'has_error' => false,
|
|
'error_code' => null,
|
|
'error_message' => null,
|
|
'timestamp' => now()->toDateTimeString(),
|
|
'niv' => $niv,
|
|
'repuve_response' => $jsonResponse,
|
|
];
|
|
}
|
|
|
|
$errorFromDb = Error::where('code', '108')->first();
|
|
return [
|
|
'has_error' => true,
|
|
'error_code' => '108',
|
|
'error_name' => $errorFromDb?->name,
|
|
'error_message' => $errorFromDb?->description ?? 'Error al parsear respuesta',
|
|
'timestamp' => now()->toDateTimeString(),
|
|
'niv' => $niv,
|
|
'repuve_response' => null,
|
|
];
|
|
}
|
|
|
|
public function verificarRobo(?string $niv = null, ?string $placa = null): array
|
|
{
|
|
try {
|
|
|
|
if (empty($niv) && empty($placa)) {
|
|
logger()->warning('REPUVE verificarRobo: No se proporcionó NIV ni PLACA');
|
|
return [
|
|
'is_robado' => false,
|
|
'has_error' => true,
|
|
'error_message' => 'Debe proporcionar al menos NIV o PLACA para verificar robo',
|
|
];
|
|
}
|
|
|
|
$url = $this->baseUrl . $this->roboEndpoint;
|
|
|
|
// Construir arg2 según los parámetros enviados
|
|
if (!empty($niv) && !empty($placa)) {
|
|
$arg2 = $niv . '|' . $placa . str_repeat('|', 5);
|
|
} elseif (!empty($niv)) {
|
|
$arg2 = $niv . str_repeat('|', 7);
|
|
} else {
|
|
$arg2 = '||' . $placa . str_repeat('|', 5);
|
|
}
|
|
|
|
logger()->info('REPUVE verificarRobo: Cadena construida', [
|
|
'niv' => $niv,
|
|
'placa' => $placa,
|
|
'arg2' => $arg2,
|
|
'total_pipes' => substr_count($arg2, '|'),
|
|
'ejemplo_visual' => str_replace('|', ' | ', $arg2),
|
|
]);
|
|
|
|
|
|
$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);
|
|
|
|
// Si hay error de conexión, retornar error
|
|
if ($error) {
|
|
logger()->error('REPUVE verificarRobo: Error de conexión', [
|
|
'error' => $error,
|
|
'niv' => $niv,
|
|
'placa' => $placa,
|
|
]);
|
|
return [
|
|
'is_robado' => false,
|
|
'has_error' => true,
|
|
'error_message' => 'Error de conexión con el servicio REPUVE',
|
|
];
|
|
}
|
|
|
|
// Si hay error HTTP, retornar error
|
|
if ($httpCode !== 200) {
|
|
logger()->error('REPUVE verificarRobo: HTTP error', [
|
|
'http_code' => $httpCode,
|
|
'niv' => $niv,
|
|
'placa' => $placa,
|
|
]);
|
|
return [
|
|
'is_robado' => false,
|
|
'has_error' => true,
|
|
'error_message' => "Error HTTP {$httpCode} del servicio REPUVE",
|
|
];
|
|
}
|
|
|
|
// Parsear respuesta
|
|
$valorBuscado = $niv ?: $placa ?: 'N/A';
|
|
$resultado = $this->parseRoboResponse($response, $valorBuscado);
|
|
|
|
// Si hubo error al parsear, loguear pero retornar el resultado completo
|
|
if ($resultado['has_error'] ?? false) {
|
|
logger()->warning('REPUVE verificarRobo: Error al parsear respuesta', [
|
|
'niv' => $niv,
|
|
'placa' => $placa,
|
|
'error' => $resultado['error_message'] ?? 'Desconocido',
|
|
]);
|
|
}
|
|
|
|
// Retornar el array completo con toda la información
|
|
return $resultado;
|
|
} finally {
|
|
unset($ch);
|
|
}
|
|
} catch (Exception $e) {
|
|
logger()->error('REPUVE verificarRobo: Excepción capturada', [
|
|
'niv' => $niv,
|
|
'placa' => $placa,
|
|
'exception' => $e->getMessage(),
|
|
]);
|
|
return [
|
|
'is_robado' => false,
|
|
'has_error' => true,
|
|
'error_message' => 'Excepción capturada: ' . $e->getMessage(),
|
|
];
|
|
}
|
|
}
|
|
|
|
public function consultarVehiculo(?string $niv = null, ?string $placa = null)
|
|
{
|
|
try {
|
|
$url = $this->baseUrl . '/jaxws-consultarpv/ConsultaRpv';
|
|
|
|
// Construir arg2: NIV||||||||
|
|
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) {
|
|
logger()->error('REPUVE consultarVehiculo: Error de conexión', [
|
|
'error' => $error,
|
|
'niv' => $niv,
|
|
'placa' => $placa,
|
|
]);
|
|
return [
|
|
'success' => false,
|
|
'has_error' => true,
|
|
'error_message' => 'Error de conexión con el servicio REPUVE',
|
|
];
|
|
}
|
|
|
|
if ($httpCode !== 200) {
|
|
logger()->error('REPUVE consultarVehiculo: HTTP error', [
|
|
'http_code' => $httpCode,
|
|
'niv' => $niv,
|
|
'placa' => $placa,
|
|
]);
|
|
return [
|
|
'success' => false,
|
|
'has_error' => true,
|
|
'error_message' => "Error HTTP {$httpCode} del servicio REPUVE",
|
|
];
|
|
}
|
|
|
|
// Parsear respuesta
|
|
$resultado = $this->parseConsultarVehiculoResponse($response);
|
|
|
|
if ($resultado['has_error'] ?? false) {
|
|
logger()->warning('REPUVE consultarVehiculo: Error al parsear', [
|
|
'niv' => $niv,
|
|
'placa' => $placa,
|
|
'error' => $resultado['error_message'] ?? 'Desconocido',
|
|
]);
|
|
}
|
|
|
|
return $resultado;
|
|
} finally {
|
|
unset($ch);
|
|
}
|
|
} catch (Exception $e) {
|
|
logger()->error('REPUVE consultarVehiculo: Excepción', [
|
|
'niv' => $niv,
|
|
'placa' => $placa,
|
|
'exception' => $e->getMessage(),
|
|
]);
|
|
return [
|
|
'success' => false,
|
|
'has_error' => true,
|
|
'error_message' => 'Excepción: ' . $e->getMessage(),
|
|
];
|
|
}
|
|
}
|
|
|
|
public function inscribirVehiculo(array $datos)
|
|
{
|
|
$url = $this->baseUrl . $this->inscripcionEndpoint;
|
|
|
|
// DATOS HARDCODEADOS
|
|
$arg2 = implode('|', [
|
|
$datos['ent_fed'] ?? '', // 1. Entidad federativa
|
|
$datos['ofcexp'] ?? '', // 2. Oficina expedición
|
|
$datos['fechaexp'] ?? '', // 3. Fecha expedición
|
|
$datos['placa'] ?? '', // 4. Placa
|
|
$datos['tarjetacir'] ?? '', // 5. Tarjeta circulación
|
|
$datos['marca'] ?? '', // 6. Marca
|
|
$datos['submarca'] ?? '', // 7. Submarca
|
|
$datos['version'] ?? '', // 8. Versión
|
|
$datos['clase_veh'] ?? '', // 9. Clase vehículo
|
|
$datos['tipo_veh'] ?? '', // 10. Tipo vehículo
|
|
$datos['tipo_uso'] ?? '', // 11. Tipo uso
|
|
$datos['modelo'] ?? '', // 12. Modelo (año)
|
|
$datos['color'] ?? '', // 13. Color
|
|
$datos['motor'] ?? '', // 14. Número motor
|
|
$datos['niv'] ?? '', // 15. NIV
|
|
$datos['rfv'] ?? '', // 16. RFV
|
|
$datos['numptas'] ?? '', // 17. Número puertas
|
|
$datos['observac'] ?? '', // 18. Observaciones
|
|
$datos['tipopers'] ?? '', // 19. Tipo persona
|
|
$datos['curp'] ?? '', // 20. CURP
|
|
$datos['rfc'] ?? '', // 21. RFC
|
|
$datos['pasaporte'] ?? '', // 22. Pasaporte
|
|
$datos['licencia'] ?? '', // 23. Licencia
|
|
$datos['nombre'] ?? '', // 24. Nombre
|
|
$datos['ap_paterno'] ?? '', // 25. Apellido paterno
|
|
$datos['ap_materno'] ?? '', // 26. Apellido materno
|
|
$datos['ent_fed'] ?? '', // 27. Entidad federativa propietario
|
|
$datos['munic'] ?? '', // 28. Municipio
|
|
$datos['callep'] ?? '', // 29. Calle principal
|
|
$datos['num_ext'] ?? '', // 30. Número exterior
|
|
$datos['num_int'] ?? '', // 31. Número interior
|
|
$datos['colonia'] ?? '', // 32. Colonia
|
|
$datos['cp'] ?? '', // 33. Código postal
|
|
$datos['cve_vehi'] ?? '', // 34. Clave vehículo
|
|
$datos['nrpv'] ?? '', // 35. NRPV
|
|
$datos['fe_act'] ?? '', // 36. Fecha actualización
|
|
$datos['tipo_mov'] ?? '', // 37. Tipo movimiento
|
|
]);
|
|
|
|
// Construir el cuerpo SOAP
|
|
$soapBody = <<<XML
|
|
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsdl="http://inscripcion.org/wsdl">
|
|
<soapenv:Header/>
|
|
<soapenv:Body>
|
|
<wsdl:inscribe>
|
|
<arg0>{$this->username}</arg0>
|
|
<arg1>{$this->password}</arg1>
|
|
<arg2>{$arg2}</arg2>
|
|
</wsdl:inscribe>
|
|
</soapenv:Body>
|
|
</soapenv:Envelope>
|
|
XML;
|
|
|
|
// Configurar cURL
|
|
$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: "inscribe"',
|
|
'Content-Length: ' . strlen($soapBody),
|
|
]);
|
|
|
|
try {
|
|
// Ejecutar la petición
|
|
$response = curl_exec($ch);
|
|
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
$curlError = curl_error($ch);
|
|
|
|
// Loguear para debug
|
|
logger()->info('REPUVE Inscripción Request', [
|
|
'url' => $url,
|
|
'soap_body' => $soapBody
|
|
]);
|
|
|
|
logger()->info('REPUVE Inscripción Response', [
|
|
'http_code' => $httpCode,
|
|
'curl_error' => $curlError,
|
|
'response' => $response
|
|
]);
|
|
|
|
if ($curlError) {
|
|
$errorFromDb = Error::where('code', '103')->first();
|
|
return [
|
|
'has_error' => true,
|
|
'error_code' => '103',
|
|
'error_name' => $errorFromDb?->name,
|
|
'error_message' => $errorFromDb?->description ?? "Error de conexión: {$curlError}",
|
|
'timestamp' => now()->toDateTimeString(),
|
|
'http_code' => $httpCode,
|
|
'raw_response' => $response,
|
|
];
|
|
}
|
|
|
|
if ($httpCode !== 200) {
|
|
$errorFromDb = Error::where('code', '-1')->first();
|
|
return [
|
|
'has_error' => true,
|
|
'error_code' => '-1',
|
|
'error_name' => $errorFromDb?->name,
|
|
'error_message' => $errorFromDb?->description ?? "Error interno HTTP {$httpCode}",
|
|
'timestamp' => now()->toDateTimeString(),
|
|
'http_code' => $httpCode,
|
|
'raw_response' => $response,
|
|
];
|
|
}
|
|
|
|
// Parsear la respuesta
|
|
return $this->parsearRespuestaInscripcion($response);
|
|
} finally {
|
|
unset($ch);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Parsea la respuesta
|
|
*/
|
|
private function parsearRespuestaInscripcion(string $soapResponse)
|
|
{
|
|
preg_match('/<return>(.*?)<\/return>/s', $soapResponse, $matches);
|
|
|
|
if (!isset($matches[1])) {
|
|
$errorFromDb = Error::where('code', '108')->first();
|
|
return [
|
|
'has_error' => true,
|
|
'error_code' => '108',
|
|
'error_name' => $errorFromDb?->name,
|
|
'error_message' => $errorFromDb?->description ?? 'Error al parsear respuesta',
|
|
'timestamp' => now()->toDateTimeString(),
|
|
'raw_response' => $soapResponse,
|
|
'repuve_response' => null,
|
|
];
|
|
}
|
|
|
|
$contenido = trim($matches[1]);
|
|
|
|
// Buscar patrones de error: ERR:, ERROR:, err:, error:
|
|
if (preg_match('/(ERR|ERROR|err|error):(-?\d+)/i', $contenido, $errorMatch)) {
|
|
$errorCode = $errorMatch[2];
|
|
|
|
// Buscar el error completo en la base de datos
|
|
$errorFromDb = Error::where('code', $errorCode)->first();
|
|
|
|
if ($errorFromDb) {
|
|
// Retornar nombre y descripción de la BD
|
|
return [
|
|
'has_error' => true,
|
|
'error_code' => $errorCode,
|
|
'error_name' => $errorFromDb->name,
|
|
'error_message' => $errorFromDb->description,
|
|
'timestamp' => now()->toDateTimeString(),
|
|
'raw_response' => $soapResponse,
|
|
'repuve_response' => $contenido,
|
|
];
|
|
}
|
|
|
|
// Si no existe en BD, retornar el código sin descripción
|
|
return [
|
|
'has_error' => true,
|
|
'error_code' => $errorCode,
|
|
'error_name' => null,
|
|
'error_message' => "Error código {$errorCode} - no catalogado",
|
|
'timestamp' => now()->toDateTimeString(),
|
|
'raw_response' => $soapResponse,
|
|
'repuve_response' => $contenido,
|
|
];
|
|
}
|
|
|
|
// Si empieza con OK: es éxito
|
|
if (preg_match('/^OK:/i', $contenido)) {
|
|
$datos = preg_replace('/^OK:/i', '', $contenido);
|
|
|
|
return [
|
|
'has_error' => false,
|
|
'error_code' => null,
|
|
'error_message' => null,
|
|
'timestamp' => now()->toDateTimeString(),
|
|
'raw_response' => $soapResponse,
|
|
'repuve_response' => [
|
|
'status' => 'OK',
|
|
'data' => $datos,
|
|
],
|
|
];
|
|
}
|
|
|
|
// Si no hay ERR/ERROR y no es OK, asumir que es respuesta exitosa
|
|
return [
|
|
'has_error' => false,
|
|
'error_code' => null,
|
|
'error_name' => null,
|
|
'error_message' => null,
|
|
'timestamp' => now()->toDateTimeString(),
|
|
'raw_response' => $soapResponse,
|
|
'repuve_response' => [
|
|
'status' => 'OK',
|
|
'data' => $contenido,
|
|
],
|
|
];
|
|
}
|
|
|
|
private function parseRoboResponse(string $soapResponse, string $valor): array
|
|
{
|
|
// Extraer contenido del tag <return>
|
|
preg_match('/<return>(.*?)<\/return>/s', $soapResponse, $matches);
|
|
|
|
if (!isset($matches[1])) {
|
|
logger()->error('REPUVE parseRoboResponse: No se encontró tag <return>', [
|
|
'soap_response' => substr($soapResponse, 0, 500),
|
|
'valor' => $valor,
|
|
]);
|
|
|
|
return [
|
|
'has_error' => true,
|
|
'is_robado' => false,
|
|
'error_message' => 'Respuesta SOAP inválida',
|
|
];
|
|
}
|
|
|
|
$contenido = trim($matches[1]);
|
|
|
|
// Verificar si hay error de REPUVE Nacional (ERR: o ERROR:)
|
|
if (preg_match('/(ERR|ERROR|err|error):(-?\d+)/i', $contenido, $errorMatch)) {
|
|
$errorCode = $errorMatch[2];
|
|
|
|
logger()->warning('REPUVE parseRoboResponse: Servicio retornó error', [
|
|
'error_code' => $errorCode,
|
|
'contenido' => $contenido,
|
|
'valor' => $valor,
|
|
]);
|
|
|
|
return [
|
|
'has_error' => true,
|
|
'is_robado' => false,
|
|
'error_code' => $errorCode,
|
|
'error_message' => "Error REPUVE código {$errorCode}",
|
|
'raw_response' => $contenido,
|
|
];
|
|
}
|
|
|
|
// Si empieza con OK:, parsear los datos de robo
|
|
if (str_starts_with($contenido, 'OK:')) {
|
|
$datos = str_replace('OK:', '', $contenido);
|
|
$valores = explode('|', $datos);
|
|
|
|
// 1 = robado, 0 = no robado
|
|
$indicador = $valores[0] ?? '0';
|
|
$isRobado = ($indicador === '1');
|
|
|
|
$roboData = [
|
|
'has_error' => false,
|
|
'is_robado' => $isRobado,
|
|
'indicador' => $indicador,
|
|
'fecha_robo' => $valores[1] ?? null,
|
|
'placa' => $valores[2] ?? null,
|
|
'niv' => $valores[3] ?? null,
|
|
'autoridad' => $valores[4] ?? null,
|
|
'acta' => $valores[5] ?? null,
|
|
'denunciante' => $valores[6] ?? null,
|
|
'fecha_acta' => $valores[7] ?? null,
|
|
'raw_response' => $contenido,
|
|
];
|
|
|
|
// Log importante si está robado
|
|
if ($isRobado) {
|
|
logger()->warning('REPUVE: Vehículo reportado como ROBADO', [
|
|
'valor_buscado' => $valor,
|
|
'niv' => $roboData['niv'],
|
|
'placa' => $roboData['placa'],
|
|
'autoridad' => $roboData['autoridad'],
|
|
'acta' => $roboData['acta'],
|
|
'denunciante' => $roboData['denunciante'],
|
|
]);
|
|
} else {
|
|
logger()->info('REPUVE: Vehículo NO reportado como robado', [
|
|
'valor_buscado' => $valor,
|
|
]);
|
|
}
|
|
|
|
return $roboData;
|
|
}
|
|
|
|
// Si no tiene formato reconocido
|
|
logger()->error('REPUVE parseRoboResponse: Formato desconocido', [
|
|
'contenido' => $contenido,
|
|
'valor' => $valor,
|
|
]);
|
|
|
|
return [
|
|
'has_error' => true,
|
|
'is_robado' => false,
|
|
'error_message' => 'Formato de respuesta no reconocido',
|
|
'raw_response' => $contenido,
|
|
];
|
|
}
|
|
|
|
public function parseConsultarVehiculoResponse(string $xmlResponse): array
|
|
{
|
|
try {
|
|
$xml = simplexml_load_string($xmlResponse);
|
|
|
|
if ($xml === false) {
|
|
return [
|
|
'success' => false,
|
|
'has_error' => true,
|
|
'error_message' => 'Error al parsear XML',
|
|
'raw_response' => $xmlResponse,
|
|
];
|
|
}
|
|
|
|
$xml->registerXPathNamespace('ns2', 'http://consultaRpv.org/wsdl');
|
|
$return = $xml->xpath('//ns2:doConsRPVResponse/return');
|
|
|
|
if (empty($return)) {
|
|
return [
|
|
'success' => false,
|
|
'has_error' => true,
|
|
'error_message' => 'No se encontró elemento return en la respuesta',
|
|
'raw_response' => $xmlResponse,
|
|
];
|
|
}
|
|
$contenido = trim((string)$return[0]);
|
|
|
|
// Verificar si la respuesta es OK
|
|
if (!str_starts_with($contenido, 'OK:')) {
|
|
return [
|
|
'success' => false,
|
|
'has_error' => true,
|
|
'error_message' => $contenido,
|
|
'raw_response' => $xmlResponse,
|
|
];
|
|
}
|
|
|
|
// Remover "OK:" del inicio
|
|
$data = substr($contenido, 3);
|
|
|
|
// Separar por |
|
|
$campos = explode('|', $data);
|
|
|
|
return [
|
|
'success' => true,
|
|
'has_error' => false,
|
|
'entidad_federativa' => $campos[0] ?? null,
|
|
'oficina' => $campos[1] ?? null,
|
|
'folio_tarjeta' => $campos[2] ?? null,
|
|
'niv' => $campos[3] ?? null,
|
|
'fecha_expedicion' => $campos[4] ?? null,
|
|
'hora_expedicion' => $campos[5] ?? null,
|
|
'procedencia' => $campos[6] ?? null,
|
|
'origen' => $campos[7] ?? null,
|
|
'clave_vehicular' => $campos[8] ?? null,
|
|
'fecha_emplacado' => $campos[9] ?? null,
|
|
'municipio' => $campos[10] ?? null,
|
|
'serie' => $campos[11] ?? null,
|
|
'placa' => $campos[12] ?? null,
|
|
'tipo_vehiculo' => $campos[13] ?? null,
|
|
'modelo' => $campos[14] ?? null,
|
|
'color' => $campos[15] ?? null,
|
|
'version' => $campos[16] ?? null,
|
|
'entidad_placas' => $campos[17] ?? null,
|
|
'marca' => $campos[18] ?? null,
|
|
'linea' => $campos[19] ?? null,
|
|
'uso' => $campos[20] ?? null,
|
|
'clase' => $campos[21] ?? null,
|
|
'estatus' => $campos[22] ?? null,
|
|
'observaciones' => $campos[23] ?? null,
|
|
'raw_response' => $contenido,
|
|
];
|
|
} catch (Exception $e) {
|
|
return [
|
|
'success' => false,
|
|
'has_error' => true,
|
|
'error_message' => 'Excepción al parsear: ' . $e->getMessage(),
|
|
'raw_response' => $xmlResponse,
|
|
];
|
|
}
|
|
}
|
|
}
|