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
@@ -97,7 +97,7 @@ class TelegramBotService
|
||||
$step = $state['step'] ?? 'await_email';
|
||||
|
||||
// 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;
|
||||
$this->setState($chatId, $state);
|
||||
}
|
||||
@@ -107,8 +107,9 @@ class TelegramBotService
|
||||
'await_otp' => $this->processOtp($chatId, $text),
|
||||
'await_nombre' => $this->processNombre($chatId, $text),
|
||||
'await_celular' => $this->processCelular($chatId, $text),
|
||||
'await_amount' => $this->processCustomAmount($chatId, $text),
|
||||
default => $this->handleFreeText($chatId, $state),
|
||||
'await_amount' => $this->processCustomAmount($chatId, $text),
|
||||
'await_remitente_nombre' => $this->processRemitenteNombre($chatId, $text),
|
||||
default => $this->handleFreeText($chatId, $state),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -144,7 +145,8 @@ class TelegramBotService
|
||||
'rec_custom' => $this->askCustomAmount($chatId),
|
||||
'rec_amount' => $this->chooseRechargeMethod($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),
|
||||
'history' => $this->showHistory($chatId),
|
||||
'profile' => $this->showProfile($chatId),
|
||||
@@ -170,7 +172,7 @@ class TelegramBotService
|
||||
}
|
||||
|
||||
$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
|
||||
$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
|
||||
{
|
||||
$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."
|
||||
. "\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)) {
|
||||
$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;
|
||||
$this->setState($chatId, $state);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user