soapUrl = config('services.padron_estatal.url'); } public function getVehiculoByNiv(string $niv): array { return $this->consultarPadron('niv', $niv); } public function getVehiculoByPlaca(string $placa): array { return $this->consultarPadron('placa', $placa); } public function getVehiculoByFolio(string $folio): array { return $this->consultarPadron('folio', $folio); } /** * Consulta el padrón vehicular estatal * Prepara la petición SOAP sin ejecutarla. * Retorna ['url', 'body', 'headers'] para usar con SoapParallelExecutor. */ public function prepareConsultarPadronRequest(string $tipo, string $valor): array { $data = json_encode(['tipo' => $tipo, 'valor' => $valor]); $soapBody = << {$data} XML; return [ 'url' => $this->soapUrl, 'body' => $soapBody, 'headers' => [ 'Content-Type: text/xml; charset=utf-8', 'SOAPAction: ""', 'Content-Length: ' . strlen($soapBody), ], ]; } private function consultarPadron(string $tipo, string $valor): array { $logger = Log::channel('padron_estatal'); // Construir el Data en formato JSON $data = json_encode([ 'tipo' => $tipo, 'valor' => $valor ]); // Construir el cuerpo SOAP $soapBody = << {$data} XML; $logger->info('Consulta al padrón estatal', [ 'url' => $this->soapUrl, 'tipo' => $tipo, 'valor' => $valor, ]); $logger->debug('SOAP request body', ['body' => $soapBody]); // Configurar cURL $ch = curl_init($this->soapUrl); 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: ""', 'Content-Length: ' . strlen($soapBody) ]); try { // Ejecutar la petición $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $curlInfo = curl_getinfo($ch); $error = curl_error($ch); $logger->debug('Respuesta cURL', [ 'http_code' => $httpCode, 'total_time' => $curlInfo['total_time'] ?? null, 'connect_time' => $curlInfo['connect_time'] ?? null, 'namelookup_time' => $curlInfo['namelookup_time'] ?? null, 'curl_error' => $error ?: null, ]); if ($error) { $logger->error('Error cURL al consultar padrón estatal', ['error' => $error]); throw new PadronEstatalException("Error en la petición al padrón estatal: {$error}"); } if ($httpCode !== 200) { $logger->error('HTTP error al consultar padrón estatal', [ 'http_code' => $httpCode, 'response' => $response, ]); throw new PadronEstatalException("Error HTTP {$httpCode} al consultar padrón estatal"); } $logger->debug('SOAP response body', ['body' => $response]); // Parsear la respuesta return $this->parsearRespuesta($response); } finally { unset($ch); } } /** * Parsea la respuesta del padrón estatal */ public function parsearRespuesta(string $soapResponse): array { $logger = Log::channel('padron_estatal'); // Extraer el contenido del tag preg_match('/(.*?)<\/result>/s', $soapResponse, $matches); if (!isset($matches[1])) { $logger->error('No se encontró tag en la respuesta SOAP', ['response' => $soapResponse]); throw new PadronEstatalException("No se pudo extraer el resultado del padrón estatal"); } $jsonContent = trim($matches[1]); // Decodificar el JSON $result = json_decode($jsonContent, true); if (json_last_error() !== JSON_ERROR_NONE) { $logger->error('Error al decodificar JSON del padrón estatal', [ 'json_error' => json_last_error_msg(), 'content' => $jsonContent, ]); throw new PadronEstatalException("Error al decodificar JSON del padrón estatal: " . json_last_error_msg()); } // La respuesta es un array con un objeto que tiene error y datos if (!isset($result[0])) { $logger->error('Formato de respuesta inesperado (sin índice 0)', ['result' => $result]); throw new PadronEstatalException("Formato de respuesta inesperado del padrón estatal"); } $data = $result[0]; // Verificar si hay error if ($data['error'] !== 0) { $logger->warning('El padrón estatal devolvió un código de error', [ 'error_code' => $data['error'], 'data' => $data, ]); throw new PadronEstatalException("Error en consulta al padrón estatal: código {$data['error']}"); } // Verificar si hay datos if (!isset($data['datos'][0])) { $logger->warning('El padrón estatal no devolvió datos del vehículo', ['data' => $data]); throw new PadronEstatalException("No se encontraron datos del vehículo en el padrón estatal"); } $logger->info('Consulta al padrón estatal exitosa'); return $data['datos'][0]; } /** * Extrae los datos del vehículo del resultado */ public function extraerDatosVehiculo(array $datos): array { $fechaexpedicion = $datos['fechaexp'] ?? null; return [ 'placa' => $datos['placa'] ?? null, 'niv' => $datos['niv'] ?? null, 'marca' => $datos['marca'] ?? null, 'linea' => $datos['submarca'] ?? null, 'sublinea' => $datos['version'] ?? null, 'modelo' => $datos['modelo'] ?? null, 'color' => $datos['color'] ?? null, 'numero_motor' => $datos['motor'] ?? null, 'clase_veh' => $datos['clase_veh'] ?? null, 'tipo_servicio' => $datos['tipo_uso'] ?? null, 'rfv' => $datos['rfv'] ?? null, 'ofcexpedicion' => $datos['ofcexp'] ?? null, 'fechaexpedicion' => $fechaexpedicion, 'tipo_veh' => $datos['tipo_veh'] ?? null, 'numptas' => $datos['numptas'] ?? null, 'observac' => $datos['observac'] ?? null, 'cve_vehi' => $datos['cve_vehi'] ?? null, 'nrpv' => $datos['nrpv'] ?? null, 'tipo_mov' => $datos['tipo_mov'] ?? null, ]; } /** * Extrae los datos del propietario del resultado */ public function extraerDatosPropietario(array $datos): array { // Construir dirección completa $addressParts = array_filter([ $datos['callep'] ?? null, isset($datos['num_ext']) && $datos['num_ext'] ? "Num {$datos['num_ext']}" : null, isset($datos['num_int']) && $datos['num_int'] ? "Int {$datos['num_int']}" : null, $datos['colonia'] ?? null, isset($datos['cp']) && $datos['cp'] ? "CP {$datos['cp']}" : null, isset($datos['munic']) && $datos['munic'] ? "Mun {$datos['munic']}" : null, isset($datos['ent_fed']) && $datos['ent_fed'] ? "Edo {$datos['ent_fed']}" : null, ]); $address = implode(', ', $addressParts); return [ 'name' => $datos['nombre'] ?? null, 'paternal' => $datos['ap_paterno'] ?? null, 'maternal' => $datos['ap_materno'] ?? null, 'rfc' => $datos['rfc'] ?? null, 'curp' => $datos['curp'] ?? null, 'address' => $address, 'tipopers' => $datos['tipopers'] ?? null, 'pasaporte' => $datos['pasaporte'] ?? null, 'licencia' => $datos['licencia'] ?? null, 'ent_fed' => $datos['ent_fed'] ?? null, 'munic' => $datos['munic'] ?? null, 'callep' => $datos['callep'] ?? null, 'num_ext' => $datos['num_ext'] ?? null, 'num_int' => $datos['num_int'] ?? null, 'colonia' => $datos['colonia'] ?? null, 'cp' => $datos['cp'] ?? null, ]; } }