feat: validación exacta de hora + remitente obligatorio + nombres guardados
- Hora exacta: tolerancia 0 (timestamp comprobante = timestamp email) - Remitente bloquea: si el email trae el nombre del remitente y no coincide, rechaza - Nuevo paso antes de mostrar datos bancarios: bot pide nombre completo del titular - Nombres aceptados se guardan en solicitudes_recarga.nombre_remitente - Próxima recarga: muestra botones con nombres anteriores confirmados o ingresa uno nuevo - Funciona igual en Telegram y web chat Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
b66b828ded
commit
bb311e7dcd
@@ -375,6 +375,24 @@ class PublicChat extends Component
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Capturar nombre del titular bancario para validación de recarga
|
||||||
|
if ($this->flujo === 'pago.esperando_nombre') {
|
||||||
|
$nombre = trim($texto);
|
||||||
|
if (strlen($nombre) < 3) {
|
||||||
|
$this->guardarMensajeBot($this->convId, "Por favor escribe tu nombre completo (mínimo 3 caracteres).");
|
||||||
|
$this->cargarMensajes();
|
||||||
|
$this->dispatchBrowserEvent('scroll-chat');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$monto = (int) ($this->flujoData['monto'] ?? 0);
|
||||||
|
$this->flujoData['nombre_remitente'] = $nombre;
|
||||||
|
$this->flujo = '';
|
||||||
|
$this->mostrarTransferenciaDatos($monto);
|
||||||
|
$this->cargarMensajes();
|
||||||
|
$this->dispatchBrowserEvent('scroll-chat');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Capturar monto personalizado de recarga
|
// Capturar monto personalizado de recarga
|
||||||
if ($this->flujo === 'recarga.monto_custom') {
|
if ($this->flujo === 'recarga.monto_custom') {
|
||||||
$monto = (int) preg_replace('/\D/', '', $texto);
|
$monto = (int) preg_replace('/\D/', '', $texto);
|
||||||
@@ -446,6 +464,8 @@ class PublicChat extends Component
|
|||||||
$action === 'asesor.solicitar' => $this->solicitarAsesor(),
|
$action === 'asesor.solicitar' => $this->solicitarAsesor(),
|
||||||
$action === 'pago.aplicar' => $this->aplicarRecargaValidada($data),
|
$action === 'pago.aplicar' => $this->aplicarRecargaValidada($data),
|
||||||
$action === 'pago.reintentar' => $this->reintentarValidacionPago(),
|
$action === 'pago.reintentar' => $this->reintentarValidacionPago(),
|
||||||
|
$action === 'pago.nombre_previo' => $this->usarNombrePrevio($data['nombre'] ?? ''),
|
||||||
|
$action === 'pago.nombre_nuevo' => $this->pedirNombreNuevo(),
|
||||||
$action === 'sesion.cerrar' => $this->confirmarCierreSesion(),
|
$action === 'sesion.cerrar' => $this->confirmarCierreSesion(),
|
||||||
$action === 'sesion.cerrar.confirmar' => $this->cerrarSesion(),
|
$action === 'sesion.cerrar.confirmar' => $this->cerrarSesion(),
|
||||||
default => $this->mostrarMenuPrincipal($this->convId),
|
default => $this->mostrarMenuPrincipal($this->convId),
|
||||||
@@ -518,8 +538,10 @@ class PublicChat extends Component
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$nombreParaValidar = $this->flujoData['nombre_remitente'] ?? $this->nombreUsuario;
|
||||||
|
|
||||||
$resultado = app(\App\Services\PagoValidadorService::class)->validar(
|
$resultado = app(\App\Services\PagoValidadorService::class)->validar(
|
||||||
$datosPago, $this->userId, $this->nombreUsuario, 'web'
|
$datosPago, $this->userId, $nombreParaValidar, 'web'
|
||||||
);
|
);
|
||||||
|
|
||||||
$motivo = $resultado['motivo'] ?? '';
|
$motivo = $resultado['motivo'] ?? '';
|
||||||
@@ -1109,6 +1131,51 @@ class PublicChat extends Component
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->flujoData = ['monto' => $monto];
|
||||||
|
|
||||||
|
$nombresPrevios = $this->userId ? \App\Models\SolicitudRecarga::nombresPrevios($this->userId) : [];
|
||||||
|
|
||||||
|
if (! empty($nombresPrevios)) {
|
||||||
|
$this->flujo = 'pago.esperando_nombre';
|
||||||
|
|
||||||
|
$botones = array_map(fn($n) => ['label' => $n, 'action' => 'pago.nombre_previo', 'data' => ['nombre' => $n]], $nombresPrevios);
|
||||||
|
$botones[] = ['label' => '✏️ Usar otro nombre', 'action' => 'pago.nombre_nuevo', 'data' => []];
|
||||||
|
|
||||||
|
ChatMessage::create([
|
||||||
|
'conversation_id' => $this->convId,
|
||||||
|
'tipo' => 'bot',
|
||||||
|
'tipo_ui' => 'buttons',
|
||||||
|
'contenido' => '👤 ¿Desde qué cuenta vas a transferir? Elige un nombre anterior o usa uno nuevo:',
|
||||||
|
'payload' => ['botones' => $botones],
|
||||||
|
'leido' => true,
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
$this->flujo = 'pago.esperando_nombre';
|
||||||
|
$this->guardarMensajeBot($this->convId, "👤 Escribe tu nombre completo tal como aparece en tu cuenta bancaria o billetera:");
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->cargarMensajes();
|
||||||
|
$this->dispatchBrowserEvent('scroll-chat');
|
||||||
|
}
|
||||||
|
|
||||||
|
private function usarNombrePrevio(string $nombre): void
|
||||||
|
{
|
||||||
|
if (strlen(trim($nombre)) < 3) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$this->flujoData['nombre_remitente'] = trim($nombre);
|
||||||
|
$this->flujo = '';
|
||||||
|
$this->mostrarTransferenciaDatos((int) ($this->flujoData['monto'] ?? 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function pedirNombreNuevo(): void
|
||||||
|
{
|
||||||
|
$this->flujo = 'pago.esperando_nombre';
|
||||||
|
$this->guardarMensajeBot($this->convId, "👤 Escribe tu nombre completo tal como aparece en tu cuenta bancaria:");
|
||||||
|
}
|
||||||
|
|
||||||
|
private function mostrarTransferenciaDatos(int $monto): void
|
||||||
|
{
|
||||||
$banco = \App\Models\ChatConfig::get('recarga_banco_nombre', '');
|
$banco = \App\Models\ChatConfig::get('recarga_banco_nombre', '');
|
||||||
$clave = \App\Models\ChatConfig::get('recarga_banco_llave', '');
|
$clave = \App\Models\ChatConfig::get('recarga_banco_llave', '');
|
||||||
$titular = \App\Models\ChatConfig::get('recarga_banco_titular', '');
|
$titular = \App\Models\ChatConfig::get('recarga_banco_titular', '');
|
||||||
@@ -1134,11 +1201,11 @@ class PublicChat extends Component
|
|||||||
|
|
||||||
$this->guardarMensajeBot($this->convId, "Cuando hayas transferido, envia el comprobante usando el icono de camara (📷) y el sistema lo validara automaticamente.\n\nTienes hasta 15 minutos despues de la transferencia para enviar el soporte.");
|
$this->guardarMensajeBot($this->convId, "Cuando hayas transferido, envia el comprobante usando el icono de camara (📷) y el sistema lo validara automaticamente.\n\nTienes hasta 15 minutos despues de la transferencia para enviar el soporte.");
|
||||||
|
|
||||||
// Registrar solicitud pendiente
|
|
||||||
if ($this->userId) {
|
if ($this->userId) {
|
||||||
$solicitud = \App\Models\SolicitudRecarga::crear($this->userId, $monto, 'web');
|
$nombre = $this->flujoData['nombre_remitente'] ?? null;
|
||||||
|
$solicitud = \App\Models\SolicitudRecarga::crear($this->userId, $monto, 'web', $nombre);
|
||||||
$this->flujo = 'pago.solicitud';
|
$this->flujo = 'pago.solicitud';
|
||||||
$this->flujoData = ['solicitud_id' => $solicitud->id, 'monto' => $monto];
|
$this->flujoData = array_merge($this->flujoData, ['solicitud_id' => $solicitud->id, 'monto' => $monto]);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->volver('menu.principal');
|
$this->volver('menu.principal');
|
||||||
|
|||||||
@@ -10,22 +10,22 @@ class SolicitudRecarga extends Model
|
|||||||
|
|
||||||
public $timestamps = false;
|
public $timestamps = false;
|
||||||
|
|
||||||
protected $fillable = ['user_id', 'monto', 'canal', 'estado'];
|
protected $fillable = ['user_id', 'monto', 'canal', 'estado', 'nombre_remitente'];
|
||||||
|
|
||||||
protected $casts = ['created_at' => 'datetime'];
|
protected $casts = ['created_at' => 'datetime'];
|
||||||
|
|
||||||
public static function crear(int $userId, int $monto, string $canal): static
|
public static function crear(int $userId, int $monto, string $canal, ?string $nombreRemitente = null): static
|
||||||
{
|
{
|
||||||
// Expirar cualquier solicitud pendiente anterior del mismo usuario
|
|
||||||
static::where('user_id', $userId)
|
static::where('user_id', $userId)
|
||||||
->where('estado', 'pendiente')
|
->where('estado', 'pendiente')
|
||||||
->update(['estado' => 'expirada']);
|
->update(['estado' => 'expirada']);
|
||||||
|
|
||||||
return static::create([
|
return static::create([
|
||||||
'user_id' => $userId,
|
'user_id' => $userId,
|
||||||
'monto' => $monto,
|
'monto' => $monto,
|
||||||
'canal' => $canal,
|
'canal' => $canal,
|
||||||
'estado' => 'pendiente',
|
'estado' => 'pendiente',
|
||||||
|
'nombre_remitente' => $nombreRemitente,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,6 +38,19 @@ class SolicitudRecarga extends Model
|
|||||||
->first();
|
->first();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function nombresPrevios(int $userId): array
|
||||||
|
{
|
||||||
|
return static::where('user_id', $userId)
|
||||||
|
->where('estado', 'confirmada')
|
||||||
|
->whereNotNull('nombre_remitente')
|
||||||
|
->orderByDesc('id')
|
||||||
|
->limit(10)
|
||||||
|
->pluck('nombre_remitente')
|
||||||
|
->unique()
|
||||||
|
->values()
|
||||||
|
->toArray();
|
||||||
|
}
|
||||||
|
|
||||||
public function confirmar(): void
|
public function confirmar(): void
|
||||||
{
|
{
|
||||||
$this->update(['estado' => 'confirmada']);
|
$this->update(['estado' => 'confirmada']);
|
||||||
|
|||||||
@@ -82,12 +82,11 @@ class PagoValidadorService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── 3. Hora (±2 min) — la hora del comprobante y del correo deben ser la misma
|
// ── 3. Hora exacta — el timestamp del comprobante y del correo deben coincidir
|
||||||
// El correo puede demorar en llegar al inbox, pero el timestamp interno registra
|
// El correo llega tarde al inbox pero su contenido registra la hora exacta de la transacción.
|
||||||
// el momento exacto de la transacción, igual que el comprobante.
|
|
||||||
if ($horaIA && ($datosCorreo['hora'] ?? '')) {
|
if ($horaIA && ($datosCorreo['hora'] ?? '')) {
|
||||||
if (! $this->horaProxima($horaIA, $datosCorreo['hora'], 2)) {
|
if (! $this->horaProxima($horaIA, $datosCorreo['hora'], 0)) {
|
||||||
Log::info("[PagoValidador] Correo #{$i}: hora fuera de rango (ia={$horaIA} correo={$datosCorreo['hora']})");
|
Log::info("[PagoValidador] Correo #{$i}: hora no coincide (ia={$horaIA} correo={$datosCorreo['hora']})");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -117,10 +116,16 @@ class PagoValidadorService
|
|||||||
return ['estado' => 'no_encontrado', 'correo' => null, 'motivo' => 'error_sistema'];
|
return ['estado' => 'no_encontrado', 'correo' => null, 'motivo' => 'error_sistema'];
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── 6. Remitente (informativo, no bloquea) ──────────────
|
// ── 6. Remitente (bloquea si el correo trae el campo y no coincide) ──
|
||||||
$coincideRemitente = $this->remitenteCoincide($datosCorreo['remitente'] ?? '', $nombreUsuario ?? '');
|
$remitenteCorreo = $datosCorreo['remitente'] ?? '';
|
||||||
|
if ($remitenteCorreo && $nombreUsuario) {
|
||||||
|
if (! $this->remitenteCoincide($remitenteCorreo, $nombreUsuario)) {
|
||||||
|
Log::info("[PagoValidador] Correo #{$i}: remitente no coincide (correo={$remitenteCorreo} usuario={$nombreUsuario})");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Log::info("[PagoValidador] Correo #{$i}: CONFIRMADO (remitente_coincide=" . ($coincideRemitente ? 'SI' : 'NO') . ")");
|
Log::info("[PagoValidador] Correo #{$i}: CONFIRMADO (remitente={$remitenteCorreo})");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
PagoConfirmado::marcar($emailHash, [
|
PagoConfirmado::marcar($emailHash, [
|
||||||
@@ -137,9 +142,8 @@ class PagoValidadorService
|
|||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'estado' => 'confirmado',
|
'estado' => 'confirmado',
|
||||||
'correo' => $datosCorreo,
|
'correo' => $datosCorreo,
|
||||||
'coincide_remitente' => $coincideRemitente,
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ class TelegramBotService
|
|||||||
$step = $state['step'] ?? 'await_email';
|
$step = $state['step'] ?? 'await_email';
|
||||||
|
|
||||||
// Guardar último texto para que handleFreeText pueda pasarlo a Gemini
|
// Guardar último texto para que handleFreeText pueda pasarlo a Gemini
|
||||||
if (! in_array($step, ['await_email', 'await_otp', 'await_nombre', 'await_celular', 'await_amount'])) {
|
if (! in_array($step, ['await_email', 'await_otp', 'await_nombre', 'await_celular', 'await_amount', 'await_remitente_nombre'])) {
|
||||||
$state['data']['last_text'] = $text;
|
$state['data']['last_text'] = $text;
|
||||||
$this->setState($chatId, $state);
|
$this->setState($chatId, $state);
|
||||||
}
|
}
|
||||||
@@ -107,8 +107,9 @@ class TelegramBotService
|
|||||||
'await_otp' => $this->processOtp($chatId, $text),
|
'await_otp' => $this->processOtp($chatId, $text),
|
||||||
'await_nombre' => $this->processNombre($chatId, $text),
|
'await_nombre' => $this->processNombre($chatId, $text),
|
||||||
'await_celular' => $this->processCelular($chatId, $text),
|
'await_celular' => $this->processCelular($chatId, $text),
|
||||||
'await_amount' => $this->processCustomAmount($chatId, $text),
|
'await_amount' => $this->processCustomAmount($chatId, $text),
|
||||||
default => $this->handleFreeText($chatId, $state),
|
'await_remitente_nombre' => $this->processRemitenteNombre($chatId, $text),
|
||||||
|
default => $this->handleFreeText($chatId, $state),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,7 +145,8 @@ class TelegramBotService
|
|||||||
'rec_custom' => $this->askCustomAmount($chatId),
|
'rec_custom' => $this->askCustomAmount($chatId),
|
||||||
'rec_amount' => $this->chooseRechargeMethod($chatId, (int) ($parts[1] ?? 0)),
|
'rec_amount' => $this->chooseRechargeMethod($chatId, (int) ($parts[1] ?? 0)),
|
||||||
'rec_mp' => $this->rechargeMP($chatId, (int) ($parts[1] ?? 0)),
|
'rec_mp' => $this->rechargeMP($chatId, (int) ($parts[1] ?? 0)),
|
||||||
'rec_breb' => $this->rechargeBreb($chatId, (int) ($parts[1] ?? 0)),
|
'rec_breb' => $this->askRemitenteNombre($chatId, (int) ($parts[1] ?? 0)),
|
||||||
|
'breb_nom' => $this->seleccionarNombreRemitente($chatId, (string) ($parts[1] ?? 'nuevo')),
|
||||||
'creds' => $this->showCredentials($chatId),
|
'creds' => $this->showCredentials($chatId),
|
||||||
'history' => $this->showHistory($chatId),
|
'history' => $this->showHistory($chatId),
|
||||||
'profile' => $this->showProfile($chatId),
|
'profile' => $this->showProfile($chatId),
|
||||||
@@ -170,7 +172,7 @@ class TelegramBotService
|
|||||||
}
|
}
|
||||||
|
|
||||||
$usuarioId = $state['user_id'] ?? null;
|
$usuarioId = $state['user_id'] ?? null;
|
||||||
$nombreUsuario = $usuarioId ? (User::find($usuarioId)?->name ?? '') : '';
|
$nombreUsuario = $state['data']['nombre_remitente'] ?? ($usuarioId ? (User::find($usuarioId)?->name ?? '') : '');
|
||||||
|
|
||||||
// Verificar solicitud de recarga activa ANTES de cualquier llamada de API
|
// Verificar solicitud de recarga activa ANTES de cualquier llamada de API
|
||||||
$solicitud = $usuarioId ? SolicitudRecarga::pendiente($usuarioId) : null;
|
$solicitud = $usuarioId ? SolicitudRecarga::pendiente($usuarioId) : null;
|
||||||
@@ -1210,6 +1212,93 @@ class TelegramBotService
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function askRemitenteNombre(string $chatId, int $monto): void
|
||||||
|
{
|
||||||
|
$state = $this->getState($chatId);
|
||||||
|
$state['data']['monto'] = $monto;
|
||||||
|
$this->setState($chatId, $state);
|
||||||
|
|
||||||
|
$userId = $state['user_id'] ?? null;
|
||||||
|
$nombresPrevios = $userId ? SolicitudRecarga::nombresPrevios((int) $userId) : [];
|
||||||
|
|
||||||
|
if (empty($nombresPrevios)) {
|
||||||
|
$state['step'] = 'await_remitente_nombre';
|
||||||
|
$this->setState($chatId, $state);
|
||||||
|
$this->send($chatId, "👤 Escribe tu *nombre completo* tal como aparece en tu cuenta bancaria o billetera:");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Guardar nombres en state por índice (callback_data tiene límite de 64 chars)
|
||||||
|
$state['data']['nombres_previos'] = $nombresPrevios;
|
||||||
|
$this->setState($chatId, $state);
|
||||||
|
|
||||||
|
$keyboard = [];
|
||||||
|
foreach ($nombresPrevios as $i => $nombre) {
|
||||||
|
$keyboard[] = [['text' => $nombre, 'callback_data' => "breb_nom|{$i}"]];
|
||||||
|
}
|
||||||
|
$keyboard[] = [['text' => '✏️ Usar otro nombre', 'callback_data' => 'breb_nom|nuevo']];
|
||||||
|
|
||||||
|
$this->sendWithKeyboard($chatId, "👤 ¿Desde qué cuenta vas a transferir?\nElige un nombre anterior o escribe uno nuevo:", $keyboard);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function seleccionarNombreRemitente(string $chatId, string $indiceONuevo): void
|
||||||
|
{
|
||||||
|
$state = $this->getState($chatId);
|
||||||
|
$monto = (int) ($state['data']['monto'] ?? 0);
|
||||||
|
|
||||||
|
if ($monto <= 0) {
|
||||||
|
$this->send($chatId, "Ocurrió un error. Por favor inicia el proceso de recarga de nuevo.");
|
||||||
|
$this->showMainMenu($chatId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($indiceONuevo === 'nuevo') {
|
||||||
|
$state['step'] = 'await_remitente_nombre';
|
||||||
|
$this->setState($chatId, $state);
|
||||||
|
$this->send($chatId, "👤 Escribe tu *nombre completo* tal como aparece en tu cuenta bancaria o billetera:");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$nombres = $state['data']['nombres_previos'] ?? [];
|
||||||
|
$nombre = $nombres[(int) $indiceONuevo] ?? null;
|
||||||
|
|
||||||
|
if (! $nombre) {
|
||||||
|
$state['step'] = 'await_remitente_nombre';
|
||||||
|
$this->setState($chatId, $state);
|
||||||
|
$this->send($chatId, "No encontré ese nombre. Escríbelo de nuevo:");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$state['step'] = 'menu';
|
||||||
|
$state['data']['nombre_remitente'] = $nombre;
|
||||||
|
$this->setState($chatId, $state);
|
||||||
|
$this->rechargeBreb($chatId, $monto);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function processRemitenteNombre(string $chatId, string $texto): void
|
||||||
|
{
|
||||||
|
$nombre = trim($texto);
|
||||||
|
if (strlen($nombre) < 3) {
|
||||||
|
$this->send($chatId, "Por favor escribe tu nombre completo (mínimo 3 caracteres).");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$state = $this->getState($chatId);
|
||||||
|
$monto = (int) ($state['data']['monto'] ?? 0);
|
||||||
|
|
||||||
|
if ($monto <= 0) {
|
||||||
|
$this->send($chatId, "Ocurrió un error. Por favor inicia el proceso de recarga de nuevo.");
|
||||||
|
$this->showMainMenu($chatId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$state['step'] = 'menu';
|
||||||
|
$state['data']['nombre_remitente'] = $nombre;
|
||||||
|
$this->setState($chatId, $state);
|
||||||
|
|
||||||
|
$this->rechargeBreb($chatId, $monto);
|
||||||
|
}
|
||||||
|
|
||||||
private function rechargeBreb(string $chatId, int $monto): void
|
private function rechargeBreb(string $chatId, int $monto): void
|
||||||
{
|
{
|
||||||
$banco = ChatConfig::get('recarga_banco_nombre', '');
|
$banco = ChatConfig::get('recarga_banco_nombre', '');
|
||||||
@@ -1233,10 +1322,10 @@ class TelegramBotService
|
|||||||
$text .= "\n⚠️ Después de transferir, envía la *foto del comprobante* aquí y el sistema lo validará automáticamente."
|
$text .= "\n⚠️ Después de transferir, envía la *foto del comprobante* aquí y el sistema lo validará automáticamente."
|
||||||
. "\n_Tienes hasta 15 minutos después de la transferencia para enviar el soporte._";
|
. "\n_Tienes hasta 15 minutos después de la transferencia para enviar el soporte._";
|
||||||
|
|
||||||
// Registrar solicitud de recarga pendiente
|
|
||||||
if ($userId = ($this->getState($chatId)['user_id'] ?? null)) {
|
if ($userId = ($this->getState($chatId)['user_id'] ?? null)) {
|
||||||
$solicitud = SolicitudRecarga::crear($userId, $monto, 'telegram');
|
$state = $this->getState($chatId);
|
||||||
$state = $this->getState($chatId);
|
$nombre = $state['data']['nombre_remitente'] ?? null;
|
||||||
|
$solicitud = SolicitudRecarga::crear($userId, $monto, 'telegram', $nombre);
|
||||||
$state['data']['solicitud_recarga_id'] = $solicitud->id;
|
$state['data']['solicitud_recarga_id'] = $solicitud->id;
|
||||||
$this->setState($chatId, $state);
|
$this->setState($chatId, $state);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('solicitudes_recarga', function (Blueprint $table) {
|
||||||
|
$table->string('nombre_remitente', 200)->nullable()->after('canal');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('solicitudes_recarga', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('nombre_remitente');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user