feat: implement parallel SOAP requests for vehicle verification and add supervisor configuration
This commit is contained in:
parent
b17b6608d3
commit
f2a15ef113
@ -17,6 +17,7 @@ RUN apk add --no-cache \
|
||||
mysql-client \
|
||||
libreoffice \
|
||||
ttf-dejavu \
|
||||
supervisor \
|
||||
&& docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd zip \
|
||||
&& echo "upload_max_filesize=150M" > /usr/local/etc/php/conf.d/uploads.ini \
|
||||
&& echo "post_max_size=150M" >> /usr/local/etc/php/conf.d/uploads.ini
|
||||
@ -32,6 +33,9 @@ COPY . .
|
||||
COPY entrypoint-dev.sh /usr/local/bin/entrypoint-dev.sh
|
||||
RUN chmod +x /usr/local/bin/entrypoint-dev.sh
|
||||
|
||||
COPY Docker/supervisor/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
|
||||
RUN mkdir -p /var/log/supervisor
|
||||
|
||||
RUN mkdir -p storage/app/keys storage/logs bootstrap/cache
|
||||
|
||||
RUN chown -R www-data:www-data /var/www/repuve-backend-v1/storage /var/www/repuve-backend-v1/bootstrap/cache
|
||||
@ -40,4 +44,4 @@ RUN chmod -R 775 /var/www/repuve-backend-v1/storage /var/www/repuve-backend-v1/b
|
||||
EXPOSE 9000
|
||||
|
||||
ENTRYPOINT ["/usr/local/bin/entrypoint-dev.sh"]
|
||||
CMD ["php-fpm"]
|
||||
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]
|
||||
|
||||
@ -14,6 +14,7 @@ RUN apk add --no-cache \
|
||||
bash \
|
||||
libreoffice \
|
||||
ttf-dejavu \
|
||||
supervisor \
|
||||
&& docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd zip \
|
||||
&& echo "upload_max_filesize=150M" > /usr/local/etc/php/conf.d/uploads.ini \
|
||||
&& echo "post_max_size=150M" >> /usr/local/etc/php/conf.d/uploads.ini
|
||||
@ -29,6 +30,9 @@ COPY . .
|
||||
COPY entrypoint-prod.sh /usr/local/bin/entrypoint-prod.sh
|
||||
RUN chmod +x /usr/local/bin/entrypoint-prod.sh
|
||||
|
||||
COPY Docker/supervisor/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
|
||||
RUN mkdir -p /var/log/supervisor
|
||||
|
||||
RUN mkdir -p storage/app/keys storage/logs bootstrap/cache
|
||||
|
||||
RUN chown -R www-data:www-data /var/www/repuve-backend-v1/storage /var/www/repuve-backend-v1/bootstrap/cache
|
||||
@ -37,4 +41,4 @@ RUN chmod -R 775 /var/www/repuve-backend-v1/storage /var/www/repuve-backend-v1/b
|
||||
EXPOSE 9000
|
||||
|
||||
ENTRYPOINT ["/usr/local/bin/entrypoint-prod.sh"]
|
||||
CMD ["php-fpm"]
|
||||
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]
|
||||
|
||||
30
Docker/supervisor/supervisord.conf
Normal file
30
Docker/supervisor/supervisord.conf
Normal file
@ -0,0 +1,30 @@
|
||||
[supervisord]
|
||||
nodaemon=true
|
||||
user=root
|
||||
logfile=/dev/null
|
||||
logfile_maxbytes=0
|
||||
pidfile=/var/run/supervisord.pid
|
||||
|
||||
[program:php-fpm]
|
||||
command=php-fpm
|
||||
autostart=true
|
||||
autorestart=true
|
||||
priority=1
|
||||
stdout_logfile=/dev/stdout
|
||||
stdout_logfile_maxbytes=0
|
||||
stderr_logfile=/dev/stderr
|
||||
stderr_logfile_maxbytes=0
|
||||
|
||||
[program:queue-worker]
|
||||
command=php /var/www/repuve-backend-v1/artisan queue:work --tries=3 --timeout=300 --sleep=3 --max-time=3600
|
||||
autostart=true
|
||||
autorestart=true
|
||||
priority=2
|
||||
user=www-data
|
||||
numprocs=1
|
||||
stopwaitsecs=60
|
||||
stdout_logfile=/var/www/repuve-backend-v1/storage/logs/worker.log
|
||||
stdout_logfile_maxbytes=50MB
|
||||
stdout_logfile_backups=5
|
||||
stderr_logfile=/var/www/repuve-backend-v1/storage/logs/worker.log
|
||||
stderr_logfile_maxbytes=0
|
||||
@ -19,6 +19,7 @@
|
||||
use App\Services\RepuveService;
|
||||
use App\Services\PadronEstatalService;
|
||||
use App\Jobs\ProcessRepuveResponse;
|
||||
use App\Supports\SoapParallelExecutor;
|
||||
use Illuminate\Routing\Controllers\HasMiddleware;
|
||||
|
||||
class InscriptionController extends Controller implements HasMiddleware
|
||||
@ -119,8 +120,17 @@ public function vehicleInscription(VehicleStoreRequest $request)
|
||||
]);
|
||||
}
|
||||
|
||||
// Consultar REPUVE Nacional para corroborar el vehículo y obtener folio_CI
|
||||
$repuveNacionalData = $this->repuveService->consultarVehiculo($niv, $placa);
|
||||
// Consultar REPUVE Nacional y verificar robo en paralelo
|
||||
$parallelRequests = [
|
||||
'repuve' => $this->repuveService->prepareConsultarVehiculoRequest($niv, $placa),
|
||||
'robo' => $this->repuveService->prepareVerificarRoboRequest($niv, $placa),
|
||||
];
|
||||
$parallelResults = SoapParallelExecutor::execute($parallelRequests);
|
||||
|
||||
// Parsear respuesta REPUVE Nacional
|
||||
$repuveNacionalData = $this->repuveService->parseConsultarVehiculoResponse(
|
||||
$parallelResults['repuve']['response'] ?: ''
|
||||
);
|
||||
|
||||
// Verificar si hubo error en la consulta a REPUVE Nacional
|
||||
if ($repuveNacionalData['has_error'] ?? false) {
|
||||
@ -136,8 +146,11 @@ public function vehicleInscription(VehicleStoreRequest $request)
|
||||
$folioRepuve = $repuveNacionalData['folio_CI'] ?? null;
|
||||
$actionType = empty($folioRepuve) ? 'sustitucion_primera_vez' : 'sustitucion';
|
||||
|
||||
// Verificar robo
|
||||
$roboResult = $this->checkIfStolen($niv, $placa);
|
||||
// Parsear respuesta de robo
|
||||
$roboResult = $this->repuveService->parseRoboResponse(
|
||||
$parallelResults['robo']['response'] ?: '',
|
||||
$niv ?: $placa ?: 'N/A'
|
||||
);
|
||||
// Solo bloquear si está marcado como robado
|
||||
if ($roboResult['is_robado'] ?? false) {
|
||||
DB::rollBack();
|
||||
|
||||
@ -21,6 +21,7 @@
|
||||
use Exception;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use App\Jobs\ProcessRepuveResponse;
|
||||
use App\Supports\SoapParallelExecutor;
|
||||
use App\Models\CatalogTagStatus;
|
||||
use Illuminate\Routing\Controllers\HasMiddleware;
|
||||
|
||||
@ -141,10 +142,20 @@ public function tagSubstitution(Request $request)
|
||||
]);
|
||||
}
|
||||
|
||||
// Validar vehículo en PadronEstatal antes de proceder con la sustitución
|
||||
// Consultar PadronEstatal, verificar robo y consultar REPUVE en paralelo
|
||||
$parallelRequests = [
|
||||
'padron' => $this->padronEstatalService->prepareConsultarPadronRequest('placa', $vehicle->placa),
|
||||
'robo' => $this->repuveService->prepareVerificarRoboRequest($vehicle->niv, null),
|
||||
'repuve' => $this->repuveService->prepareConsultarVehiculoRequest($vehicle->niv, $vehicle->placa),
|
||||
];
|
||||
$parallelResults = SoapParallelExecutor::execute($parallelRequests);
|
||||
|
||||
// Parsear respuesta del Padrón Estatal
|
||||
try {
|
||||
$datosEstatal = $this->padronEstatalService->getVehiculoByPlaca($vehicle->placa);
|
||||
$vehicleDataEstatal = $this->padronEstatalService->extraerDatosVehiculo($datosEstatal);
|
||||
$datosEstatalRaw = $this->padronEstatalService->parsearRespuesta(
|
||||
$parallelResults['padron']['response'] ?: ''
|
||||
);
|
||||
$vehicleDataEstatal = $this->padronEstatalService->extraerDatosVehiculo($datosEstatalRaw);
|
||||
} catch (PadronEstatalException $e) {
|
||||
return ApiResponse::BAD_REQUEST->response([
|
||||
'message' => 'No se pudo validar el vehículo en el Padrón Estatal.',
|
||||
@ -161,7 +172,11 @@ public function tagSubstitution(Request $request)
|
||||
]);
|
||||
}
|
||||
|
||||
$roboResult = $this->checkIfStolen($vehicle->niv);
|
||||
// Parsear respuesta de robo
|
||||
$roboResult = $this->repuveService->parseRoboResponse(
|
||||
$parallelResults['robo']['response'] ?: '',
|
||||
$vehicle->niv
|
||||
);
|
||||
|
||||
// Solo bloquear si explícitamente está marcado como robado
|
||||
if ($roboResult['is_robado'] ?? false) {
|
||||
@ -170,8 +185,10 @@ public function tagSubstitution(Request $request)
|
||||
]);
|
||||
}
|
||||
|
||||
// Obtener folio_CI de REPUVE antes de cancelar (folio anterior)
|
||||
$repuveData = $this->repuveService->consultarVehiculo($vehicle->niv, $vehicle->placa);
|
||||
// Parsear respuesta REPUVE para obtener folio_CI anterior
|
||||
$repuveData = $this->repuveService->parseConsultarVehiculoResponse(
|
||||
$parallelResults['repuve']['response'] ?: ''
|
||||
);
|
||||
$folioAnterior = $repuveData['folio_CI'] ?? null;
|
||||
|
||||
DB::beginTransaction();
|
||||
|
||||
@ -31,7 +31,35 @@ public function getVehiculoByFolio(string $folio): array
|
||||
|
||||
/**
|
||||
* 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 = <<<XML
|
||||
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsdl="http://mx/tgc/ConsultaPadronVehicular.wsdl">
|
||||
<soapenv:Header/>
|
||||
<soapenv:Body>
|
||||
<wsdl:getVehiculosRepuve>
|
||||
<Data>{$data}</Data>
|
||||
</wsdl:getVehiculosRepuve>
|
||||
</soapenv:Body>
|
||||
</soapenv:Envelope>
|
||||
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');
|
||||
@ -114,7 +142,7 @@ private function consultarPadron(string $tipo, string $valor): array
|
||||
/**
|
||||
* Parsea la respuesta del padrón estatal
|
||||
*/
|
||||
private function parsearRespuesta(string $soapResponse): array
|
||||
public function parsearRespuesta(string $soapResponse): array
|
||||
{
|
||||
$logger = Log::channel('padron_estatal');
|
||||
|
||||
|
||||
@ -470,6 +470,84 @@ public function consultarVehiculo(?string $niv = null, ?string $placa = null)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepara la petición SOAP de consultarVehiculo sin ejecutarla.
|
||||
* Retorna ['url', 'body', 'headers'] para usar con SoapParallelExecutor.
|
||||
*/
|
||||
public function prepareConsultarVehiculoRequest(?string $niv = null, ?string $placa = null): array
|
||||
{
|
||||
$this->asegurarCargaCredenciales();
|
||||
|
||||
$url = $this->baseUrl . '/jaxws-consultarpv/ConsultaRpv';
|
||||
|
||||
$campos = array_fill(0, 8, '');
|
||||
$campos[0] = $niv ?? '';
|
||||
$campos[2] = $placa ?? '';
|
||||
$arg2 = implode('|', $campos);
|
||||
|
||||
$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;
|
||||
|
||||
return [
|
||||
'url' => $url,
|
||||
'body' => $soapBody,
|
||||
'headers' => [
|
||||
'Content-Type: text/xml; charset=utf-8',
|
||||
'SOAPAction: "doConsRPV"',
|
||||
'Content-Length: ' . strlen($soapBody),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepara la petición SOAP de verificarRobo sin ejecutarla.
|
||||
* Retorna ['url', 'body', 'headers'] para usar con SoapParallelExecutor.
|
||||
*/
|
||||
public function prepareVerificarRoboRequest(?string $niv = null, ?string $placa = null): array
|
||||
{
|
||||
$this->asegurarCargaCredenciales();
|
||||
|
||||
$url = $this->baseUrl . $this->roboEndpoint;
|
||||
|
||||
$campos = array_fill(0, 8, '');
|
||||
$campos[0] = $niv ?? '';
|
||||
$campos[2] = $placa ?? '';
|
||||
$arg2 = implode('|', $campos);
|
||||
|
||||
$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;
|
||||
|
||||
return [
|
||||
'url' => $url,
|
||||
'body' => $soapBody,
|
||||
'headers' => [
|
||||
'Content-Type: text/xml; charset=utf-8',
|
||||
'SOAPAction: "doConsRepRobo"',
|
||||
'Content-Length: ' . strlen($soapBody),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function inscribirVehiculo(array $datos)
|
||||
{
|
||||
$this->asegurarCargaCredenciales();
|
||||
@ -674,7 +752,7 @@ private function parsearRespuestaInscripcion(string $soapResponse)
|
||||
];
|
||||
}
|
||||
|
||||
private function parseRoboResponse(string $soapResponse, string $valor): array
|
||||
public function parseRoboResponse(string $soapResponse, string $valor): array
|
||||
{
|
||||
// Extraer contenido del tag <return>
|
||||
preg_match('/<return>(.*?)<\/return>/s', $soapResponse, $matches);
|
||||
|
||||
53
app/Supports/SoapParallelExecutor.php
Normal file
53
app/Supports/SoapParallelExecutor.php
Normal file
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace App\Supports;
|
||||
|
||||
class SoapParallelExecutor
|
||||
{
|
||||
/**
|
||||
* Ejecuta múltiples peticiones SOAP en paralelo usando curl_multi_exec.
|
||||
*
|
||||
* @param array $requests Mapa de clave => ['url' => string, 'body' => string, 'headers' => array]
|
||||
* @return array Mapa de clave => ['response' => string|false, 'http_code' => int, 'curl_error' => string]
|
||||
*/
|
||||
public static function execute(array $requests): array
|
||||
{
|
||||
$multiHandle = curl_multi_init();
|
||||
$handles = [];
|
||||
|
||||
foreach ($requests as $key => $req) {
|
||||
$ch = curl_init($req['url']);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $req['body']);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
|
||||
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $req['headers']);
|
||||
curl_multi_add_handle($multiHandle, $ch);
|
||||
$handles[$key] = $ch;
|
||||
}
|
||||
|
||||
$running = null;
|
||||
do {
|
||||
$status = curl_multi_exec($multiHandle, $running);
|
||||
if ($running) {
|
||||
curl_multi_select($multiHandle);
|
||||
}
|
||||
} while ($running > 0 && $status === CURLM_OK);
|
||||
|
||||
$results = [];
|
||||
foreach ($handles as $key => $ch) {
|
||||
$results[$key] = [
|
||||
'response' => curl_multi_getcontent($ch),
|
||||
'http_code' => curl_getinfo($ch, CURLINFO_HTTP_CODE),
|
||||
'curl_error' => curl_error($ch),
|
||||
];
|
||||
curl_multi_remove_handle($multiHandle, $ch);
|
||||
curl_close($ch);
|
||||
}
|
||||
|
||||
curl_multi_close($multiHandle);
|
||||
|
||||
return $results;
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user