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>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
1245d255bb
commit
16315da176
@@ -852,6 +852,7 @@ class PublicChat extends Component
|
|||||||
'nombre_cliente' => $user->name,
|
'nombre_cliente' => $user->name,
|
||||||
]);
|
]);
|
||||||
Historial_cuenta::create(['historial_id' => $historial->id, 'cuenta_id' => $cuenta->id]);
|
Historial_cuenta::create(['historial_id' => $historial->id, 'cuenta_id' => $cuenta->id]);
|
||||||
|
$cuenta->update(['estado' => 'ocupado']);
|
||||||
$saldo->update(['valor' => $nuevoSaldo]);
|
$saldo->update(['valor' => $nuevoSaldo]);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1019,6 +1020,9 @@ class PublicChat extends Component
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$nuevoSaldo = $saldo->valor - $precio;
|
||||||
|
|
||||||
|
DB::transaction(function () use ($promo, $user, $saldo, $cuenta, $precio, $utilidad, $promoId, $nuevoSaldo) {
|
||||||
$historial = Historiale::create([
|
$historial = Historiale::create([
|
||||||
'fecha_inicio' => now(),
|
'fecha_inicio' => now(),
|
||||||
'fecha_final' => now()->addDays(30),
|
'fecha_final' => now()->addDays(30),
|
||||||
@@ -1031,10 +1035,6 @@ class PublicChat extends Component
|
|||||||
'cliente_id' => $this->userId,
|
'cliente_id' => $this->userId,
|
||||||
'nombre_cliente' => $user->name,
|
'nombre_cliente' => $user->name,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$nuevoSaldo = $saldo->valor - $precio;
|
|
||||||
|
|
||||||
DB::transaction(function () use ($historial, $cuenta, $saldo, $nuevoSaldo) {
|
|
||||||
Historial_cuenta::create(['historial_id' => $historial->id, 'cuenta_id' => $cuenta->id]);
|
Historial_cuenta::create(['historial_id' => $historial->id, 'cuenta_id' => $cuenta->id]);
|
||||||
$cuenta->update(['estado' => 'ocupado']);
|
$cuenta->update(['estado' => 'ocupado']);
|
||||||
$saldo->update(['valor' => $nuevoSaldo]);
|
$saldo->update(['valor' => $nuevoSaldo]);
|
||||||
@@ -1171,7 +1171,7 @@ class PublicChat extends Component
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->flujoData = ['monto' => $monto];
|
$this->flujoData = array_merge($this->flujoData, ['monto' => $monto]);
|
||||||
|
|
||||||
$nombresPrevios = $this->userId ? \App\Models\SolicitudRecarga::nombresPrevios($this->userId) : [];
|
$nombresPrevios = $this->userId ? \App\Models\SolicitudRecarga::nombresPrevios($this->userId) : [];
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
namespace App\Jobs;
|
namespace App\Jobs;
|
||||||
|
|
||||||
use App\Models\SolicitudRecarga;
|
use App\Models\SolicitudRecarga;
|
||||||
use App\Models\User;
|
|
||||||
use App\Services\PagoValidadorService;
|
use App\Services\PagoValidadorService;
|
||||||
use App\Services\TelegramBotService;
|
use App\Services\TelegramBotService;
|
||||||
use Illuminate\Bus\Queueable;
|
use Illuminate\Bus\Queueable;
|
||||||
|
|||||||
@@ -311,20 +311,28 @@ class TelegramBotService
|
|||||||
{
|
{
|
||||||
$usuarioId = $state['user_id'];
|
$usuarioId = $state['user_id'];
|
||||||
$user = User::with('saldo')->find($usuarioId);
|
$user = User::with('saldo')->find($usuarioId);
|
||||||
|
|
||||||
|
if (! $user) {
|
||||||
|
Log::warning("[TelegramBot] autoAplicarRecarga: usuario {$usuarioId} no encontrado.");
|
||||||
|
$this->send($chatId, "⚠️ Error al aplicar la recarga. Por favor contacta a un asesor.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$saldo = $user->saldo ?? Saldo::create(['usuario_id' => $usuarioId, 'valor' => 0]);
|
$saldo = $user->saldo ?? Saldo::create(['usuario_id' => $usuarioId, 'valor' => 0]);
|
||||||
$nuevoSaldo = $saldo->valor + $monto;
|
$nuevoSaldo = $saldo->valor + $monto;
|
||||||
$saldo->update(['valor' => $nuevoSaldo]);
|
|
||||||
|
|
||||||
|
DB::transaction(function () use ($saldo, $nuevoSaldo, $usuarioId, $monto, $solicitud) {
|
||||||
|
$saldo->update(['valor' => $nuevoSaldo]);
|
||||||
\App\Models\recarga::create([
|
\App\Models\recarga::create([
|
||||||
'usuario_id' => $usuarioId,
|
'usuario_id' => $usuarioId,
|
||||||
'saldo_id' => $saldo->id,
|
'saldo_id' => $saldo->id,
|
||||||
'monto' => $monto,
|
'monto' => $monto,
|
||||||
'valor_recarga'=> $monto,
|
'valor_recarga' => $monto,
|
||||||
'status' => 'Confirmado',
|
'status' => 'Confirmado',
|
||||||
'reference' => 'breb-bot-' . $solicitud->id,
|
'reference' => 'breb-bot-' . $solicitud->id,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$solicitud->confirmar();
|
$solicitud->confirmar();
|
||||||
|
});
|
||||||
|
|
||||||
$pp = $state['data']['pending_purchase'] ?? null;
|
$pp = $state['data']['pending_purchase'] ?? null;
|
||||||
unset($state['data']['pago_pendiente'], $state['data']['solicitud_recarga_id'], $state['data']['pending_purchase']);
|
unset($state['data']['pago_pendiente'], $state['data']['solicitud_recarga_id'], $state['data']['pending_purchase']);
|
||||||
|
|||||||
@@ -447,21 +447,19 @@
|
|||||||
navigator.clipboard.writeText(val).then(() => { this.copiado = id; setTimeout(() => this.copiado = null, 2000); });
|
navigator.clipboard.writeText(val).then(() => { this.copiado = id; setTimeout(() => this.copiado = null, 2000); });
|
||||||
},
|
},
|
||||||
copiarTodo() {
|
copiarTodo() {
|
||||||
let email = $refs.cred_email ? $refs.cred_email.innerText : '';
|
|
||||||
let pass = $refs.cred_pass ? $refs.cred_pass.innerText : '';
|
|
||||||
let parts = [
|
let parts = [
|
||||||
'Servicio: {{ addslashes($payload['servicio'] ?? '') }}',
|
'Servicio: ' + ($refs.cred_servicio?.innerText ?? ''),
|
||||||
email ? 'Email: ' + email : '',
|
$refs.cred_email ? 'Email: ' + $refs.cred_email.innerText : '',
|
||||||
pass ? 'Password: ' + pass : '',
|
$refs.cred_pass ? 'Password: ' + $refs.cred_pass.innerText : '',
|
||||||
'{{ !empty($payload['perfil']) ? 'Perfil: ' . addslashes($payload['perfil']) : '' }}',
|
$refs.cred_perfil ? 'Perfil: ' + $refs.cred_perfil.innerText : '',
|
||||||
'{{ !empty($payload['vence']) ? 'Vence: ' . $payload['vence'] : '' }}'
|
$refs.cred_vence ? 'Vence: ' + $refs.cred_vence.innerText : '',
|
||||||
].filter(Boolean);
|
].filter(Boolean);
|
||||||
navigator.clipboard.writeText(parts.join('\n')).then(() => { this.copiado = 'todo'; setTimeout(() => this.copiado = null, 2000); });
|
navigator.clipboard.writeText(parts.join('\n')).then(() => { this.copiado = 'todo'; setTimeout(() => this.copiado = null, 2000); });
|
||||||
}
|
}
|
||||||
}">
|
}">
|
||||||
{{-- Encabezado servicio --}}
|
{{-- Encabezado servicio --}}
|
||||||
<div class="px-4 py-2 bg-[#00a884]/20 flex items-center justify-between">
|
<div class="px-4 py-2 bg-[#00a884]/20 flex items-center justify-between">
|
||||||
<p class="text-[#00a884] text-xs font-semibold uppercase tracking-wider">{{ $payload['servicio'] ?? 'Credenciales' }}</p>
|
<p class="text-[#00a884] text-xs font-semibold uppercase tracking-wider" x-ref="cred_servicio">{{ $payload['servicio'] ?? 'Credenciales' }}</p>
|
||||||
<span class="text-[#00a884] text-[10px]">✅ Compra exitosa</span>
|
<span class="text-[#00a884] text-[10px]">✅ Compra exitosa</span>
|
||||||
</div>
|
</div>
|
||||||
{{-- Mensaje de gracias --}}
|
{{-- Mensaje de gracias --}}
|
||||||
@@ -501,11 +499,11 @@
|
|||||||
@if (!empty($payload['perfil']))
|
@if (!empty($payload['perfil']))
|
||||||
<div class="bg-[#0b141a] rounded-lg px-3 py-2">
|
<div class="bg-[#0b141a] rounded-lg px-3 py-2">
|
||||||
<p class="text-[#8696a0] text-[11px] mb-0.5">Perfil</p>
|
<p class="text-[#8696a0] text-[11px] mb-0.5">Perfil</p>
|
||||||
<p class="text-white text-sm">{{ $payload['perfil'] }}</p>
|
<p class="text-white text-sm" x-ref="cred_perfil">{{ $payload['perfil'] }}</p>
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
@if (!empty($payload['vence']))
|
@if (!empty($payload['vence']))
|
||||||
<p class="text-[#8696a0] text-xs text-center">📅 Vence: {{ $payload['vence'] }}</p>
|
<p class="text-[#8696a0] text-xs text-center">📅 Vence: <span x-ref="cred_vence">{{ $payload['vence'] }}</span></p>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
{{-- Botón Copiar todo --}}
|
{{-- Botón Copiar todo --}}
|
||||||
|
|||||||
Reference in New Issue
Block a user