baseUrl = config('services.repuve_federal.base_url'); $this->roboEndpoint = config('services.repuve_federal.robo_endpoint'); $this->inscripcionEndpoint = config('services.repuve_federal.inscripcion_endpoint'); $this->username = config('services.repuve_federal.username'); $this->password = config('services.repuve_federal.password'); } public function consultarPadron(string $niv) { $url = $this->baseUrl . $this->roboEndpoint; $arg2 = $niv . '|||||||'; $soapBody = << {$this->username} {$this->password} {$arg2} 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_HTTPHEADER, [ 'Content-Type: text/xml; charset=utf-8', 'SOAPAction: "doConsPadron"', 'Content-Length: ' . strlen($soapBody), ]); // Ejecutar la solicitud $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $error = curl_error($ch); curl_close($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); } private function parseVehicleResponse(string $soapResponse, string $niv): array { preg_match('/(.*?)<\/return>/s', $soapResponse, $matches); if (!isset($matches[1])) { throw new Exception("No se pudo extraer la respuesta del SOAP"); } $contenido = trim($matches[1]); // Verificar si hay error if (str_starts_with($contenido, 'ERROR:')) { $errorMessage = str_replace('ERROR:', '', $contenido); return [ 'has_error' => true, 'error_code' => 'REPUVE_ERROR', 'error_message' => $errorMessage, 'timestamp' => now()->toDateTimeString(), 'niv' => $niv, 'repuve_response' => null, ]; } // 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', 'folio_ci', 'identificador_ci', '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, ]; } throw new Exception("Formato de respuesta desconocido: {$contenido}"); } /** * Verifica si un vehículo está reportado como robado */ public function verificarRobo(string $niv): bool { try { $resultado = $this->consultarPadron($niv); if ($resultado['has_error']) { return false; } $estatus = $resultado['repuve_response']['estatus_registro'] ?? null; return in_array(strtoupper($estatus), ['ROBADO', 'ROBO']); } catch (Exception $e) { logger()->error("Error al verificar robo en REPUVE: " . $e->getMessage()); return false; } } public function inscribirVehiculo(array $datos): array { $url = $this->baseUrl . $this->inscripcionEndpoint; // DATOS HARDCODEADOS $arg2 = '27|INTERNET|04/01/2022|WNU700B|2020-WNU700B|CHEVROLET G.M.C.|AVEO|PAQ. A LS|AUTOMOVIL|SEDAN|PARTICULAR|2022|BLANCO|H. EN WUHANLL,SGM|LSGHD52H0ND032457||4|COMENTARIO|1||GME111116GJA|||GOLSYSTEMS DE MEXICO|||27|04|BUGAMBILIAS|118||FRACC. BLANCAS MARIPOSAS|86170|0037804|5BK9MDO0|10/01/2025|1'; // Construir el cuerpo SOAP $soapBody = << {$this->username} {$this->password} {$arg2} 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_HTTPHEADER, [ 'Content-Type: text/xml; charset=utf-8', 'SOAPAction: "inscribe"', 'Content-Length: ' . strlen($soapBody), ]); // Ejecutar la petición $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $curlError = curl_error($ch); curl_close($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) { return [ 'has_error' => true, 'error_code' => 'CURL_ERROR', 'error_message' => "Error cURL: {$curlError}", 'timestamp' => now()->toDateTimeString(), 'http_code' => $httpCode, 'raw_response' => $response, ]; } if ($httpCode !== 200) { return [ 'has_error' => true, 'error_code' => 'HTTP_ERROR', 'error_message' => "Error HTTP {$httpCode}", 'timestamp' => now()->toDateTimeString(), 'http_code' => $httpCode, 'raw_response' => $response, ]; } // Parsear la respuesta return $this->parsearRespuestaInscripcion($response); } /** * Parsea la respuesta */ private function parsearRespuestaInscripcion(string $soapResponse): array { // Retornar la respuesta completa return [ 'has_error' => false, 'error_code' => null, 'error_message' => null, 'timestamp' => now()->toDateTimeString(), 'raw_response' => $soapResponse, 'parsed_response' => $this->extraerContenidoSOAP($soapResponse), ]; } private function extraerContenidoSOAP(string $soapResponse): ?string { // Intentar extraer el contenido del tag preg_match('/(.*?)<\/return>/s', $soapResponse, $matches); if (isset($matches[1])) { return trim($matches[1]); } // Si no hay tag , intentar con otros tags comunes preg_match('/(.*?)<\/result>/s', $soapResponse, $matches); if (isset($matches[1])) { return trim($matches[1]); } return null; } }