Files
sirpremiumv2/app/Jobs/ValidarPagoTelegramJob.php
T
LizandroandClaude Sonnet 4.6 16315da176 fix: correcciones de seguridad pre-producción identificadas en code review
- autoAplicarRecarga: null-check en User::find + DB::transaction atómico
- pagarConSaldo: $cuenta->update('ocupado') dentro de la transacción (evita doble venta)
- comprarPromoConSaldo: Historiale::create movido dentro de la transacción (evita registros huérfanos)
- mostrarTransferencia: array_merge en lugar de asignación directa (preserva pending_purchase)
- Blade copiarTodo: lee valores desde x-ref del DOM en vez de escapado PHP→JS
- ValidarPagoTelegramJob: eliminado import App\Models\User no utilizado

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-29 19:24:36 +00:00

87 lines
3.0 KiB
PHP

<?php
namespace App\Jobs;
use App\Models\SolicitudRecarga;
use App\Services\PagoValidadorService;
use App\Services\TelegramBotService;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
class ValidarPagoTelegramJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public int $tries = 1;
public int $timeout = 60;
private const MAX_INTENTOS = 9;
private const STATE_TTL = 315360000;
public function __construct(
private string $chatId,
private array $datosPago,
private int $intento = 1
) {}
public function handle(): void
{
$cacheKey = "tgbot_state_{$this->chatId}";
$state = Cache::get($cacheKey, []);
$usuarioId = $state['user_id'] ?? null;
$bot = new TelegramBotService();
if (! $usuarioId) {
return;
}
$solicitud = SolicitudRecarga::pendiente($usuarioId);
if (! $solicitud) {
Log::info("[ValidarPagoTelegramJob] chatId={$this->chatId}: solicitud ya no está pendiente, abortando.");
return;
}
$nombreUsuario = $state['data']['nombre_remitente'] ?? null;
$resultado = app(PagoValidadorService::class)->validar(
$this->datosPago, $usuarioId, $nombreUsuario, 'telegram'
);
if ($resultado['estado'] === 'confirmado') {
$bot->autoAplicarRecarga($this->chatId, $state, $solicitud, $solicitud->monto);
return;
}
if ($resultado['estado'] === 'ya_usado') {
$bot->sendWithKeyboard($this->chatId,
"⛔ *Comprobante ya utilizado.*\nEste pago ya fue registrado anteriormente.",
[[['text' => '🔙 Menú principal', 'callback_data' => 'menu']]]
);
return;
}
// No encontrado — reintentar o agotar
if ($this->intento < self::MAX_INTENTOS) {
Log::info("[ValidarPagoTelegramJob] chatId={$this->chatId}: intento {$this->intento}/" . self::MAX_INTENTOS . " — reintentando en 20s");
self::dispatch($this->chatId, $this->datosPago, $this->intento + 1)
->delay(now()->addSeconds(20));
} else {
Log::info("[ValidarPagoTelegramJob] chatId={$this->chatId}: intentos agotados, mostrando botón manual");
$bot->sendWithKeyboard(
$this->chatId,
"⚠️ No pudimos confirmar tu pago automáticamente.\nSi ya realizaste la transferencia, presiona Reintentar.",
[
[['text' => '🔄 Reintentar', 'callback_data' => 'pay_retry']],
[['text' => '🔙 Menú principal', 'callback_data' => 'menu']],
]
);
}
}
}