4 mejoras en canales de comunicación con el cliente
1. Reintentos automáticos (Telegram Job): usa autoAplicarRecarga para ejecutar la compra pendiente automáticamente al confirmar el pago, sin botón extra. 2. Pagar servicio directo con Bre-B sin recargar saldo previamente (ambos canales): botón 'Pagar con Bre-B directo' en el flujo de compra con saldo insuficiente. 3. Mensaje de gracias + bloque de credenciales fácil de copiar al entregar servicio: Telegram usa bloque de código (tiene botón Copy nativo), Chat Web muestra el texto completo de gracias con copia por campo y botón 'Copiar todo'. 4. Botón copiar llave Bre-B: ya existía en Chat Web, confirmado sin cambio. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
932a9b43c7
commit
1245d255bb
@@ -500,6 +500,7 @@ class PublicChat extends Component
|
||||
$action === 'historial.ver' => $this->verHistorial(),
|
||||
$action === 'perfil.ver' => $this->verPerfil(),
|
||||
$action === 'asesor.solicitar' => $this->solicitarAsesor(),
|
||||
$action === 'pago.directo.breb' => $this->pagarDirectoBreb($data),
|
||||
$action === 'pago.aplicar' => $this->aplicarRecargaValidada($data),
|
||||
$action === 'pago.reintentar' => $this->reintentarValidacionPago(),
|
||||
$action === 'pago.nombre_previo' => $this->usarNombrePrevio($data['nombre'] ?? ''),
|
||||
@@ -776,7 +777,6 @@ class PublicChat extends Component
|
||||
} else {
|
||||
$falta = $precio - (float) $this->saldoUsuario;
|
||||
|
||||
// Guardar compra pendiente para ejecutarla automáticamente tras recargar
|
||||
$this->flujoData = array_merge($this->flujoData, [
|
||||
'pending_purchase' => [
|
||||
'type' => 'tarifa',
|
||||
@@ -792,9 +792,10 @@ class PublicChat extends Component
|
||||
'conversation_id' => $this->convId,
|
||||
'tipo' => 'bot',
|
||||
'tipo_ui' => 'buttons',
|
||||
'contenido' => "{$tarifa->servicio->nombre} - {$detalle}\nPrecio: $" . number_format($precio) . "\n\nSaldo actual: $" . number_format($this->saldoUsuario) . " — te faltan $" . number_format($falta) . "\n\nRecarga para comprar:",
|
||||
'contenido' => "{$tarifa->servicio->nombre} - {$detalle}\nPrecio: $" . number_format($precio) . "\n\nSaldo actual: $" . number_format($this->saldoUsuario) . " — te faltan $" . number_format($falta) . "\n\n¿Cómo quieres pagar?",
|
||||
'payload' => ['botones' => [
|
||||
['label' => "💰 Recargar $" . number_format($falta) . " para comprar {$tarifa->servicio->nombre}", 'action' => 'recarga.iniciar', 'data' => []],
|
||||
['label' => "💳 Pagar con Bre-B directo ($" . number_format($precio) . ")", 'action' => 'pago.directo.breb', 'data' => ['tipo' => 'tarifa', 'tarifa_id' => $tarifaId, 'valor' => $precio]],
|
||||
['label' => "💰 Recargar saldo ($" . number_format($falta) . " faltantes)", 'action' => 'recarga.iniciar', 'data' => []],
|
||||
['label' => 'Volver', 'action' => 'servicios.listar', 'data' => []],
|
||||
]],
|
||||
'leido' => true,
|
||||
@@ -860,7 +861,7 @@ class PublicChat extends Component
|
||||
'conversation_id' => $this->convId,
|
||||
'tipo' => 'bot',
|
||||
'tipo_ui' => 'credenciales',
|
||||
'contenido' => 'Compra exitosa! Tus credenciales:',
|
||||
'contenido' => '¡Muchas gracias por tu compra! 🎉 Disfruta tu servicio. Si tienes algún inconveniente no dudes en escribirnos, estamos aquí para ayudarte.',
|
||||
'payload' => [
|
||||
'servicio' => $tarifa->servicio->nombre,
|
||||
'email' => $cuenta->correo,
|
||||
@@ -960,7 +961,6 @@ class PublicChat extends Component
|
||||
} else {
|
||||
$falta = $precio - (float) $this->saldoUsuario;
|
||||
|
||||
// Guardar compra pendiente para ejecutarla automáticamente tras recargar
|
||||
$this->flujoData = array_merge($this->flujoData, [
|
||||
'pending_purchase' => [
|
||||
'type' => 'promo',
|
||||
@@ -974,9 +974,10 @@ class PublicChat extends Component
|
||||
'conversation_id' => $this->convId,
|
||||
'tipo' => 'bot',
|
||||
'tipo_ui' => 'buttons',
|
||||
'contenido' => ($promo->nombre ?? 'Promocion') . "\n$" . number_format($precio) . "\n\nSaldo actual: $" . number_format($this->saldoUsuario) . " — te faltan $" . number_format($falta) . "\n\nRecarga para comprar:",
|
||||
'contenido' => ($promo->nombre ?? 'Promocion') . "\n$" . number_format($precio) . "\n\nSaldo actual: $" . number_format($this->saldoUsuario) . " — te faltan $" . number_format($falta) . "\n\n¿Cómo quieres pagar?",
|
||||
'payload' => ['botones' => [
|
||||
['label' => "💰 Recargar $" . number_format($falta) . " para comprar " . ($promo->nombre ?? 'Promo'), 'action' => 'recarga.iniciar', 'data' => []],
|
||||
['label' => "💳 Pagar con Bre-B directo ($" . number_format($precio) . ")", 'action' => 'pago.directo.breb', 'data' => ['tipo' => 'promo', 'promo_id' => $id, 'valor' => $precio]],
|
||||
['label' => "💰 Recargar saldo ($" . number_format($falta) . " faltantes)", 'action' => 'recarga.iniciar', 'data' => []],
|
||||
['label' => 'Volver', 'action' => 'promo.listar', 'data' => []],
|
||||
]],
|
||||
'leido' => true,
|
||||
@@ -1045,7 +1046,7 @@ class PublicChat extends Component
|
||||
'conversation_id' => $this->convId,
|
||||
'tipo' => 'bot',
|
||||
'tipo_ui' => 'credenciales',
|
||||
'contenido' => 'Promo activada! Tus credenciales:',
|
||||
'contenido' => '¡Muchas gracias por tu compra! 🎉 Disfruta tu servicio. Si tienes algún inconveniente no dudes en escribirnos, estamos aquí para ayudarte.',
|
||||
'payload' => [
|
||||
'servicio' => $promo->nombre ?? 'Promocion',
|
||||
'email' => $cuenta->correo,
|
||||
@@ -1059,6 +1060,55 @@ class PublicChat extends Component
|
||||
}
|
||||
|
||||
|
||||
// ─────────────────────────────────────────────────────────
|
||||
// Pago directo con Bre-B sin necesidad de saldo previo
|
||||
// ─────────────────────────────────────────────────────────
|
||||
|
||||
private function pagarDirectoBreb(array $data): void
|
||||
{
|
||||
$tipo = $data['tipo'] ?? 'tarifa';
|
||||
$valor = (int) ($data['valor'] ?? 0);
|
||||
|
||||
if ($valor <= 0) {
|
||||
$this->guardarMensajeBot($this->convId, "No se pudo iniciar el pago. Intenta de nuevo.");
|
||||
return;
|
||||
}
|
||||
|
||||
if ($tipo === 'tarifa') {
|
||||
$tarifa = Tarifas::with('servicio')->find($data['tarifa_id'] ?? 0);
|
||||
if (! $tarifa) {
|
||||
$this->guardarMensajeBot($this->convId, "Plan no encontrado.");
|
||||
return;
|
||||
}
|
||||
$this->flujoData = array_merge($this->flujoData, [
|
||||
'pending_purchase' => [
|
||||
'type' => 'tarifa',
|
||||
'tarifa_id' => $data['tarifa_id'],
|
||||
'valor' => $valor,
|
||||
'servicio' => $tarifa->servicio->nombre,
|
||||
'dias' => $tarifa->dias,
|
||||
'pantallas' => $tarifa->pantallas,
|
||||
],
|
||||
]);
|
||||
} elseif ($tipo === 'promo') {
|
||||
$promo = Promociones::find($data['promo_id'] ?? 0);
|
||||
if (! $promo) {
|
||||
$this->guardarMensajeBot($this->convId, "Promoción no encontrada.");
|
||||
return;
|
||||
}
|
||||
$this->flujoData = array_merge($this->flujoData, [
|
||||
'pending_purchase' => [
|
||||
'type' => 'promo',
|
||||
'promo_id' => $data['promo_id'],
|
||||
'valor' => $valor,
|
||||
'nombre' => $promo->nombre ?? 'Promoción',
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
$this->mostrarTransferencia($valor);
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────
|
||||
// Recarga de saldo
|
||||
// ─────────────────────────────────────────────────────────
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Jobs;
|
||||
|
||||
use App\Models\recarga;
|
||||
use App\Models\Saldo;
|
||||
use App\Models\SolicitudRecarga;
|
||||
use App\Models\User;
|
||||
use App\Services\PagoValidadorService;
|
||||
@@ -56,7 +54,7 @@ class ValidarPagoTelegramJob implements ShouldQueue
|
||||
);
|
||||
|
||||
if ($resultado['estado'] === 'confirmado') {
|
||||
$this->aplicarYNotificar($bot, $state, $cacheKey, $solicitud, $usuarioId);
|
||||
$bot->autoAplicarRecarga($this->chatId, $state, $solicitud, $solicitud->monto);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -86,63 +84,4 @@ class ValidarPagoTelegramJob implements ShouldQueue
|
||||
}
|
||||
}
|
||||
|
||||
private function aplicarYNotificar(
|
||||
TelegramBotService $bot,
|
||||
array $state,
|
||||
string $cacheKey,
|
||||
SolicitudRecarga $solicitud,
|
||||
int $usuarioId
|
||||
): void {
|
||||
$user = User::with('saldo')->find($usuarioId);
|
||||
$saldo = $user->saldo ?? Saldo::create(['usuario_id' => $usuarioId, 'valor' => 0]);
|
||||
$monto = $solicitud->monto;
|
||||
$nuevoSaldo = $saldo->valor + $monto;
|
||||
|
||||
$saldo->update(['valor' => $nuevoSaldo]);
|
||||
|
||||
recarga::create([
|
||||
'usuario_id' => $usuarioId,
|
||||
'saldo_id' => $saldo->id,
|
||||
'monto' => $monto,
|
||||
'valor_recarga' => $monto,
|
||||
'status' => 'Confirmado',
|
||||
'reference' => 'breb-bot-' . $solicitud->id,
|
||||
]);
|
||||
|
||||
$solicitud->confirmar();
|
||||
|
||||
$pp = $state['data']['pending_purchase'] ?? null;
|
||||
unset($state['data']['pago_pendiente'], $state['data']['solicitud_recarga_id'], $state['data']['pending_purchase']);
|
||||
Cache::put($cacheKey, $state, now()->addSeconds(self::STATE_TTL));
|
||||
|
||||
$bot->send($this->chatId,
|
||||
"✅ *¡Tu recarga de \$" . number_format($monto) . " fue aplicada exitosamente!*\n"
|
||||
. "Tu nuevo saldo es *\$" . number_format($nuevoSaldo) . "*"
|
||||
);
|
||||
|
||||
if ($pp && ($pp['type'] ?? '') === 'tarifa') {
|
||||
$bot->sendWithKeyboard(
|
||||
$this->chatId,
|
||||
"🛒 Tienes una compra pendiente: *{$pp['servicio']}* — \$" . number_format($pp['valor']) . "\nPresiona para completarla:",
|
||||
[[['text' => "Comprar {$pp['servicio']}", 'callback_data' => 'buy_start|' . $pp['tarifa_id']]]]
|
||||
);
|
||||
} elseif ($pp && ($pp['type'] ?? '') === 'promo') {
|
||||
$bot->sendWithKeyboard(
|
||||
$this->chatId,
|
||||
"🛒 Tienes una compra pendiente: *{$pp['nombre']}* — \$" . number_format($pp['valor']) . "\nPresiona para completarla:",
|
||||
[[['text' => "Comprar {$pp['nombre']}", 'callback_data' => 'promo_saldo|' . $pp['promo_id']]]]
|
||||
);
|
||||
} else {
|
||||
$bot->sendWithKeyboard($this->chatId, "¿En qué más te puedo ayudar?", [
|
||||
[
|
||||
['text' => '📺 Ver Servicios', 'callback_data' => 'svc_list'],
|
||||
['text' => '🎁 Promociones', 'callback_data' => 'promo_list'],
|
||||
],
|
||||
[
|
||||
['text' => '🔑 Mis Credenciales', 'callback_data' => 'creds'],
|
||||
['text' => '📋 Historial', 'callback_data' => 'history'],
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,24 +133,26 @@ class TelegramBotService
|
||||
'menu' => $this->showMainMenu($chatId),
|
||||
'logout_ask' => $this->showLogoutConfirmation($chatId),
|
||||
'logout_confirm' => $this->confirmLogout($chatId),
|
||||
'svc_list' => $this->listServices($chatId),
|
||||
'svc_view' => $this->viewService($chatId, (int) ($parts[1] ?? 0)),
|
||||
'buy_start' => $this->startPurchase($chatId, (int) ($parts[1] ?? 0)),
|
||||
'buy_saldo' => $this->payWithSaldo($chatId),
|
||||
'promo_list' => $this->listPromos($chatId),
|
||||
'promo_view' => $this->viewPromo($chatId, (int) ($parts[1] ?? 0)),
|
||||
'promo_saldo' => $this->buyPromoSaldo($chatId, (int) ($parts[1] ?? 0)),
|
||||
'rec_init' => $this->showRechargeAmounts($chatId),
|
||||
'rec_custom' => $this->askCustomAmount($chatId),
|
||||
'rec_amount' => $this->chooseRechargeMethod($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),
|
||||
'agent' => $this->showMainMenu($chatId),
|
||||
'pay_retry' => $this->retryPayment($chatId),
|
||||
default => $this->showMainMenu($chatId),
|
||||
'svc_list' => $this->listServices($chatId),
|
||||
'svc_view' => $this->viewService($chatId, (int) ($parts[1] ?? 0)),
|
||||
'buy_start' => $this->startPurchase($chatId, (int) ($parts[1] ?? 0)),
|
||||
'buy_saldo' => $this->payWithSaldo($chatId),
|
||||
'breb_tarifa' => $this->startDirectBrebPayment($chatId, (int) ($parts[1] ?? 0), (int) ($parts[2] ?? 0)),
|
||||
'promo_list' => $this->listPromos($chatId),
|
||||
'promo_view' => $this->viewPromo($chatId, (int) ($parts[1] ?? 0)),
|
||||
'promo_saldo' => $this->buyPromoSaldo($chatId, (int) ($parts[1] ?? 0)),
|
||||
'breb_promo' => $this->startDirectBrebPromo($chatId, (int) ($parts[1] ?? 0), (int) ($parts[2] ?? 0)),
|
||||
'rec_init' => $this->showRechargeAmounts($chatId),
|
||||
'rec_custom' => $this->askCustomAmount($chatId),
|
||||
'rec_amount' => $this->chooseRechargeMethod($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),
|
||||
'agent' => $this->showMainMenu($chatId),
|
||||
'pay_retry' => $this->retryPayment($chatId),
|
||||
default => $this->showMainMenu($chatId),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -823,7 +825,6 @@ class TelegramBotService
|
||||
} else {
|
||||
$falta = $valor - $saldo;
|
||||
|
||||
// Guardar compra pendiente para ejecutarla automáticamente tras recargar
|
||||
$state['data']['pending_purchase'] = [
|
||||
'type' => 'tarifa',
|
||||
'tarifa_id' => $tarifaId,
|
||||
@@ -833,12 +834,13 @@ class TelegramBotService
|
||||
];
|
||||
$this->setState($chatId, $state);
|
||||
|
||||
$buttons[] = [['text' => "💰 Recargar \$" . number_format($falta) . " para comprar {$tarifa->servicio->nombre}", 'callback_data' => 'rec_init']];
|
||||
$buttons[] = [['text' => "💳 Pagar con Bre-B directo (\$" . number_format($valor) . ")", 'callback_data' => 'breb_tarifa|' . $tarifaId . '|' . $valor]];
|
||||
$buttons[] = [['text' => "💰 Recargar saldo (\$" . number_format($falta) . " faltantes)", 'callback_data' => 'rec_init']];
|
||||
$buttons[] = [['text' => '🔙 Ver planes', 'callback_data' => 'svc_view|' . $tarifa->servicio_id]];
|
||||
|
||||
$this->sendWithKeyboard(
|
||||
$chatId,
|
||||
"*{$tarifa->servicio->nombre}* — {$detalle}\nPrecio: *\$" . number_format($valor) . "*\n\nSaldo actual: \$" . number_format($saldo) . " — te faltan *\$" . number_format($falta) . "*\n\nRecarga para continuar:",
|
||||
"*{$tarifa->servicio->nombre}* — {$detalle}\nPrecio: *\$" . number_format($valor) . "*\n\nSaldo actual: \$" . number_format($saldo) . " — te faltan *\$" . number_format($falta) . "*\n\n¿Cómo quieres pagar?",
|
||||
$buttons
|
||||
);
|
||||
}
|
||||
@@ -896,18 +898,22 @@ class TelegramBotService
|
||||
$saldo->update(['valor' => $nuevoSaldo]);
|
||||
});
|
||||
|
||||
$text = "✅ *¡Compra exitosa!*\n\n";
|
||||
$text .= "🎬 *{$tarifa->servicio->nombre}*\n";
|
||||
$text .= "📧 Email: `{$cuenta->correo}`\n";
|
||||
$text .= "🔑 Password: `{$cuenta->password}`\n";
|
||||
if ($tarifa->pantallas) {
|
||||
$text .= "📺 Perfil: {$tarifa->pantallas}\n";
|
||||
}
|
||||
$text .= "📅 Vence: " . now()->addDays($tarifa->dias)->format('d/m/Y') . "\n";
|
||||
$text .= "💰 Pagado: *\$" . number_format($precio) . "*\n";
|
||||
$text .= "\nSaldo restante: *\$" . number_format($nuevoSaldo) . "*";
|
||||
$this->send($chatId,
|
||||
"🎉 *¡Muchas gracias por tu compra!*\n\n" .
|
||||
"Disfruta tu servicio. Si tienes algún inconveniente no dudes en escribirnos, estamos aquí para ayudarte. 😊"
|
||||
);
|
||||
|
||||
$this->send($chatId, $text);
|
||||
$code = "```\n";
|
||||
$code .= "Servicio: {$tarifa->servicio->nombre}\n";
|
||||
$code .= "Email: {$cuenta->correo}\n";
|
||||
$code .= "Password: {$cuenta->password}\n";
|
||||
if ($tarifa->pantallas) {
|
||||
$code .= "Perfil: {$tarifa->pantallas}\n";
|
||||
}
|
||||
$code .= "Vence: " . now()->addDays($tarifa->dias)->format('d/m/Y') . "\n";
|
||||
$code .= "Pagado: \$" . number_format($precio) . "\n";
|
||||
$code .= "```";
|
||||
$this->send($chatId, $code);
|
||||
|
||||
$state['data'] = [];
|
||||
$this->setState($chatId, $state);
|
||||
@@ -915,6 +921,49 @@ class TelegramBotService
|
||||
}
|
||||
|
||||
|
||||
// ─── Direct Bre-B purchase (sin saldo previo) ────────────
|
||||
|
||||
private function startDirectBrebPayment(string $chatId, int $tarifaId, int $valor): void
|
||||
{
|
||||
$state = $this->getState($chatId);
|
||||
$tarifa = Tarifas::with('servicio')->find($tarifaId);
|
||||
|
||||
if (! $tarifa) {
|
||||
$this->send($chatId, "Plan no encontrado.");
|
||||
return;
|
||||
}
|
||||
|
||||
$state['data']['pending_purchase'] = [
|
||||
'type' => 'tarifa',
|
||||
'tarifa_id' => $tarifaId,
|
||||
'valor' => $valor,
|
||||
'servicio' => $tarifa->servicio->nombre,
|
||||
'servicio_id' => $tarifa->servicio_id,
|
||||
];
|
||||
$this->setState($chatId, $state);
|
||||
$this->askRemitenteNombre($chatId, $valor);
|
||||
}
|
||||
|
||||
private function startDirectBrebPromo(string $chatId, int $promoId, int $precio): void
|
||||
{
|
||||
$state = $this->getState($chatId);
|
||||
$promo = \App\Models\Promociones::find($promoId);
|
||||
|
||||
if (! $promo) {
|
||||
$this->send($chatId, "Promoción no encontrada.");
|
||||
return;
|
||||
}
|
||||
|
||||
$state['data']['pending_purchase'] = [
|
||||
'type' => 'promo',
|
||||
'promo_id' => $promoId,
|
||||
'valor' => $precio,
|
||||
'nombre' => $promo->nombre ?? 'Promoción',
|
||||
];
|
||||
$this->setState($chatId, $state);
|
||||
$this->askRemitenteNombre($chatId, $precio);
|
||||
}
|
||||
|
||||
// ─── Promos ───────────────────────────────────────────────
|
||||
|
||||
private function listPromos(string $chatId): void
|
||||
@@ -997,7 +1046,6 @@ class TelegramBotService
|
||||
} else {
|
||||
$falta = $precio - $saldo;
|
||||
|
||||
// Guardar compra pendiente para ejecutarla automáticamente tras recargar
|
||||
$state = $this->getState($chatId);
|
||||
$state['data']['pending_purchase'] = [
|
||||
'type' => 'promo',
|
||||
@@ -1007,12 +1055,13 @@ class TelegramBotService
|
||||
];
|
||||
$this->setState($chatId, $state);
|
||||
|
||||
$buttons[] = [['text' => "💰 Recargar \$" . number_format($falta) . " para comprar " . ($promo->nombre ?? 'Promo'), 'callback_data' => 'rec_init']];
|
||||
$buttons[] = [['text' => "💳 Pagar con Bre-B directo (\$" . number_format($precio) . ")", 'callback_data' => 'breb_promo|' . $promoId . '|' . $precio]];
|
||||
$buttons[] = [['text' => "💰 Recargar saldo (\$" . number_format($falta) . " faltantes)", 'callback_data' => 'rec_init']];
|
||||
$buttons[] = [['text' => '🔙 Promociones', 'callback_data' => 'promo_list']];
|
||||
|
||||
$this->sendWithKeyboard(
|
||||
$chatId,
|
||||
"*{$promo->nombre}*\n\$" . number_format($precio) . "\n\nSaldo actual: \$" . number_format($saldo) . " — te faltan *\$" . number_format($falta) . "*\n\nRecarga para continuar:",
|
||||
"*{$promo->nombre}*\n\$" . number_format($precio) . "\n\nSaldo actual: \$" . number_format($saldo) . " — te faltan *\$" . number_format($falta) . "*\n\n¿Cómo quieres pagar?",
|
||||
$buttons
|
||||
);
|
||||
}
|
||||
@@ -1074,14 +1123,19 @@ class TelegramBotService
|
||||
$saldo->update(['valor' => $nuevoSaldo]);
|
||||
});
|
||||
|
||||
$text = "✅ *¡Promo activada!*\n\n";
|
||||
$text .= "🎬 *{$promo->nombre}*\n";
|
||||
$text .= "📧 Email: `{$cuenta->correo}`\n";
|
||||
$text .= "🔑 Password: `{$cuenta->password}`\n";
|
||||
$text .= "📅 Vence: " . now()->addDays($dias)->format('d/m/Y') . "\n";
|
||||
$text .= "\nSaldo restante: *\$" . number_format($nuevoSaldo) . "*";
|
||||
$this->send($chatId,
|
||||
"🎉 *¡Muchas gracias por tu compra!*\n\n" .
|
||||
"Disfruta tu servicio. Si tienes algún inconveniente no dudes en escribirnos, estamos aquí para ayudarte. 😊"
|
||||
);
|
||||
|
||||
$this->send($chatId, $text);
|
||||
$code = "```\n";
|
||||
$code .= "Promoción: {$promo->nombre}\n";
|
||||
$code .= "Email: {$cuenta->correo}\n";
|
||||
$code .= "Password: {$cuenta->password}\n";
|
||||
$code .= "Vence: " . now()->addDays($dias)->format('d/m/Y') . "\n";
|
||||
$code .= "Pagado: \$" . number_format($precio) . "\n";
|
||||
$code .= "```";
|
||||
$this->send($chatId, $code);
|
||||
$this->showMainMenu($chatId);
|
||||
}
|
||||
|
||||
|
||||
@@ -440,21 +440,62 @@
|
||||
|
||||
{{-- CREDENCIALES: tarjeta con usuario/contraseña --}}
|
||||
@elseif ($tipoUi === 'credenciales')
|
||||
<div class="max-w-[85%] bg-[#202c33] rounded-xl rounded-tl-sm shadow overflow-hidden">
|
||||
<div class="px-4 py-2 bg-[#00a884]/20">
|
||||
<div class="max-w-[85%] bg-[#202c33] rounded-xl rounded-tl-sm shadow overflow-hidden"
|
||||
x-data="{
|
||||
copiado: null,
|
||||
copiarCampo(val, id) {
|
||||
navigator.clipboard.writeText(val).then(() => { this.copiado = id; setTimeout(() => this.copiado = null, 2000); });
|
||||
},
|
||||
copiarTodo() {
|
||||
let email = $refs.cred_email ? $refs.cred_email.innerText : '';
|
||||
let pass = $refs.cred_pass ? $refs.cred_pass.innerText : '';
|
||||
let parts = [
|
||||
'Servicio: {{ addslashes($payload['servicio'] ?? '') }}',
|
||||
email ? 'Email: ' + email : '',
|
||||
pass ? 'Password: ' + pass : '',
|
||||
'{{ !empty($payload['perfil']) ? 'Perfil: ' . addslashes($payload['perfil']) : '' }}',
|
||||
'{{ !empty($payload['vence']) ? 'Vence: ' . $payload['vence'] : '' }}'
|
||||
].filter(Boolean);
|
||||
navigator.clipboard.writeText(parts.join('\n')).then(() => { this.copiado = 'todo'; setTimeout(() => this.copiado = null, 2000); });
|
||||
}
|
||||
}">
|
||||
{{-- Encabezado servicio --}}
|
||||
<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>
|
||||
<span class="text-[#00a884] text-[10px]">✅ Compra exitosa</span>
|
||||
</div>
|
||||
{{-- Mensaje de gracias --}}
|
||||
@if (!empty($msg['contenido']))
|
||||
<div class="px-4 pt-3 pb-1">
|
||||
<p class="text-[#e9edef] text-sm leading-snug">{{ $msg['contenido'] }}</p>
|
||||
</div>
|
||||
@endif
|
||||
{{-- Campos con copiar individual --}}
|
||||
<div class="px-4 py-3 space-y-2">
|
||||
@if (!empty($payload['email']))
|
||||
<div class="bg-[#0b141a] rounded-lg px-3 py-2">
|
||||
<p class="text-[#8696a0] text-[11px] mb-0.5">Usuario / Email</p>
|
||||
<p class="text-white text-sm font-mono break-all">{{ $payload['email'] }}</p>
|
||||
<div class="bg-[#0b141a] rounded-lg px-3 py-2 cursor-pointer active:opacity-70"
|
||||
@click="copiarCampo($refs.cred_email.innerText, 'email')">
|
||||
<div class="flex justify-between items-center mb-0.5">
|
||||
<p class="text-[#8696a0] text-[11px]">Usuario / Email</p>
|
||||
<svg class="w-3.5 h-3.5 transition" :class="copiado==='email' ? 'text-green-400' : 'text-[#8696a0]'" fill="none" viewBox="0 0 24 24" stroke-width="1.8" stroke="currentColor">
|
||||
<template x-if="copiado !== 'email'"><path stroke-linecap="round" stroke-linejoin="round" d="M15.666 3.888A2.25 2.25 0 0 0 13.5 2.25h-3c-1.03 0-1.9.693-2.166 1.638m7.332 0c.055.194.084.4.084.612v0a.75.75 0 0 1-.75.75H9a.75.75 0 0 1-.75-.75v0c0-.212.03-.418.084-.612m7.332 0c.646.049 1.288.11 1.927.184 1.1.128 1.907 1.077 1.907 2.185V19.5a2.25 2.25 0 0 1-2.25 2.25H6.75A2.25 2.25 0 0 1 4.5 19.5V6.257c0-1.108.806-2.057 1.907-2.185a48.208 48.208 0 0 1 1.927-.184" /></template>
|
||||
<template x-if="copiado === 'email'"><path stroke-linecap="round" stroke-linejoin="round" d="m4.5 12.75 6 6 9-13.5" /></template>
|
||||
</svg>
|
||||
</div>
|
||||
<p class="text-white text-sm font-mono break-all" x-ref="cred_email">{{ $payload['email'] }}</p>
|
||||
</div>
|
||||
@endif
|
||||
@if (!empty($payload['password']))
|
||||
<div class="bg-[#0b141a] rounded-lg px-3 py-2">
|
||||
<p class="text-[#8696a0] text-[11px] mb-0.5">Contraseña</p>
|
||||
<p class="text-white text-sm font-mono">{{ $payload['password'] }}</p>
|
||||
<div class="bg-[#0b141a] rounded-lg px-3 py-2 cursor-pointer active:opacity-70"
|
||||
@click="copiarCampo($refs.cred_pass.innerText, 'pass')">
|
||||
<div class="flex justify-between items-center mb-0.5">
|
||||
<p class="text-[#8696a0] text-[11px]">Contraseña</p>
|
||||
<svg class="w-3.5 h-3.5 transition" :class="copiado==='pass' ? 'text-green-400' : 'text-[#8696a0]'" fill="none" viewBox="0 0 24 24" stroke-width="1.8" stroke="currentColor">
|
||||
<template x-if="copiado !== 'pass'"><path stroke-linecap="round" stroke-linejoin="round" d="M15.666 3.888A2.25 2.25 0 0 0 13.5 2.25h-3c-1.03 0-1.9.693-2.166 1.638m7.332 0c.055.194.084.4.084.612v0a.75.75 0 0 1-.75.75H9a.75.75 0 0 1-.75-.75v0c0-.212.03-.418.084-.612m7.332 0c.646.049 1.288.11 1.927.184 1.1.128 1.907 1.077 1.907 2.185V19.5a2.25 2.25 0 0 1-2.25 2.25H6.75A2.25 2.25 0 0 1 4.5 19.5V6.257c0-1.108.806-2.057 1.907-2.185a48.208 48.208 0 0 1 1.927-.184" /></template>
|
||||
<template x-if="copiado === 'pass'"><path stroke-linecap="round" stroke-linejoin="round" d="m4.5 12.75 6 6 9-13.5" /></template>
|
||||
</svg>
|
||||
</div>
|
||||
<p class="text-white text-sm font-mono" x-ref="cred_pass">{{ $payload['password'] }}</p>
|
||||
</div>
|
||||
@endif
|
||||
@if (!empty($payload['perfil']))
|
||||
@@ -464,9 +505,28 @@
|
||||
</div>
|
||||
@endif
|
||||
@if (!empty($payload['vence']))
|
||||
<p class="text-[#8696a0] text-xs text-center mt-1">Vence: {{ $payload['vence'] }}</p>
|
||||
<p class="text-[#8696a0] text-xs text-center">📅 Vence: {{ $payload['vence'] }}</p>
|
||||
@endif
|
||||
</div>
|
||||
{{-- Botón Copiar todo --}}
|
||||
<div class="px-4 pb-3">
|
||||
<button @click="copiarTodo()"
|
||||
class="w-full py-2 rounded-xl text-sm font-semibold transition flex items-center justify-center gap-2"
|
||||
:class="copiado === 'todo' ? 'bg-green-500/20 text-green-400' : 'bg-[#00a884]/10 text-[#00a884] active:bg-[#00a884]/20'">
|
||||
<template x-if="copiado !== 'todo'">
|
||||
<span class="flex items-center gap-1.5">
|
||||
<svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke-width="1.8" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M15.666 3.888A2.25 2.25 0 0 0 13.5 2.25h-3c-1.03 0-1.9.693-2.166 1.638m7.332 0c.055.194.084.4.084.612v0a.75.75 0 0 1-.75.75H9a.75.75 0 0 1-.75-.75v0c0-.212.03-.418.084-.612m7.332 0c.646.049 1.288.11 1.927.184 1.1.128 1.907 1.077 1.907 2.185V19.5a2.25 2.25 0 0 1-2.25 2.25H6.75A2.25 2.25 0 0 1 4.5 19.5V6.257c0-1.108.806-2.057 1.907-2.185a48.208 48.208 0 0 1 1.927-.184" /></svg>
|
||||
Copiar todo
|
||||
</span>
|
||||
</template>
|
||||
<template x-if="copiado === 'todo'">
|
||||
<span class="flex items-center gap-1.5">
|
||||
<svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke-width="2.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="m4.5 12.75 6 6 9-13.5" /></svg>
|
||||
¡Copiado!
|
||||
</span>
|
||||
</template>
|
||||
</button>
|
||||
</div>
|
||||
<div class="px-4 pb-2 text-right">
|
||||
<span class="text-[#8696a0] text-[11px]">{{ $msg['created_at'] }}</span>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user