botToken = config('services.telegram.bot_token', env('TELEGRAM_BOT_TOKEN')); $appUrl = config('app.url', env('APP_URL', 'http://nomina-pegaso.casa')); $this->webhookUrl = rtrim($appUrl, '/') . '/telegram/webhook'; } /** * Procesar actualización recibida del webhook */ public function handleUpdate(array $update): array { if (!isset($update['message'])) { return ['ok' => false, 'error' => 'No message found']; } $message = $update['message']; $chatId = $message['chat']['id']; $text = $message['text'] ?? ''; $from = $message['from'] ?? []; Log::info('Telegram update received', [ 'chat_id' => $chatId, 'text' => $text, 'from' => $from ]); // Verificar si el usuario está verificado $telegramAccount = TelegramAccount::where('chat_id', $chatId)->first(); if (!$telegramAccount || !$telegramAccount->is_verified) { return $this->handleUnverifiedUser($chatId, $text); } // Procesar comandos del usuario verificado return $this->handleCommand($telegramAccount->user, $text, $chatId); } /** * Manejar usuario no verificado */ private function handleUnverifiedUser(string $chatId, string $text): array { // Si es un código de verificación if (strlen($text) === 6 && is_numeric($text)) { $telegramAccount = TelegramAccount::where('chat_id', $chatId) ->where('verification_code', $text) ->first(); if ($telegramAccount) { $telegramAccount->update([ 'is_verified' => true, 'verification_code' => null ]); $user = $telegramAccount->user; $this->sendMessage($chatId, "¡Verificación exitosa! Tu cuenta de Telegram está vinculada a {$user->name}. Ahora recibirás notificaciones de tus comisiones."); return ['ok' => true, 'verified' => true]; } else { $this->sendMessage($chatId, "Código de verificación inválido. Por favor intenta con el código correcto."); return ['ok' => true, 'verified' => false]; } } // Mensaje de bienvenida para usuarios no verificados $this->sendMessage($chatId, "¡Hola! Para usar este bot necesitas verificar tu cuenta.\n\nPor favor ingresa el código de verificación de 6 dígitos que encontrarás en la sección de Telegram de tu panel de usuario."); return ['ok' => true, 'verified' => false]; } /** * Manejar comandos de usuario verificado */ private function handleCommand(User $user, string $text, string $chatId): array { $command = strtolower(trim($text)); $commandParts = explode(' ', $command); $mainCommand = $commandParts[0] ?? ''; switch ($mainCommand) { case '/start': $this->sendMessage($chatId, "¡Hola {$user->name}! Usa /help para ver los comandos disponibles."); break; case '/help': $this->sendHelp($chatId); break; case '/mes': $this->showCurrentMonth($user, $chatId); break; case '/ventas': $this->showSales($user, $chatId); break; case '/gastos': $this->showExpenses($user, $chatId); break; case '/resumen': $this->showSummary($user, $chatId); break; default: $this->sendMessage($chatId, "Comando no reconocido. Usa /help para ver los comandos disponibles."); } return ['ok' => true]; } /** * Enviar mensaje */ public function sendMessage(string $chatId, string $text): array { if (!$this->botToken) { Log::warning('Telegram bot token not configured'); return ['ok' => false, 'error' => 'Bot token not configured']; } try { $response = Http::post("https://api.telegram.org/bot{$this->botToken}/sendMessage", [ 'chat_id' => $chatId, 'text' => $text, 'parse_mode' => 'Markdown' ]); return $response->json(); } catch (\Exception $e) { Log::error('Telegram send message error', ['error' => $e->getMessage()]); return ['ok' => false, 'error' => $e->getMessage()]; } } /** * Enviar mensaje de ayuda */ private function sendHelp(string $chatId): void { $text = "📋 *Comandos disponibles:*\n\n" . "• /start - Iniciar bot\n" . "• /help - Mostrar ayuda\n" . "• /mes - Ver mes actual\n" . "• /ventas - Ver ventas del mes\n" . "• /gastos - Ver gastos del mes\n" . "• /resumen - Resumen de comisiones\n"; $this->sendMessage($chatId, $text); } /** * Mostrar mes actual */ private function showCurrentMonth(User $user, string $chatId): void { $month = $user->getCurrentMonth(); if (!$month) { $this->sendMessage($chatId, "No tienes ningún mes abierto actualmente."); return; } $statusText = match($month->status) { 'open' => '🟢 Abierto', 'closed' => '🟡 Cerrado', 'paid' => '✅ Pagado', default => 'Desconocido' }; $text = "📅 *Mes Actual*\n\n" . "• *Nombre:* {$month->name} {$month->year}\n" . "• *Estado:* {$statusText}"; $this->sendMessage($chatId, $text); } /** * Mostrar ventas del mes */ private function showSales(User $user, string $chatId): void { $month = $user->getCurrentMonth(); if (!$month) { $this->sendMessage($chatId, "No tienes ningún mes abierto actualmente."); return; } $totalUserSales = $month->dailySales()->sum('user_sales'); $totalSystemSales = $month->dailySales()->sum('system_sales'); $diff = $totalUserSales - $totalSystemSales; $text = "💰 *Ventas del Mes*\n\n" . "• *Usuario:* $" . number_format($totalUserSales, 2) . "\n" . "• *Sistema:* $" . number_format($totalSystemSales, 2) . "\n" . "• *Diferencia:* $" . number_format($diff, 2); $this->sendMessage($chatId, $text); } /** * Mostrar gastos del mes */ private function showExpenses(User $user, string $chatId): void { $month = $user->getCurrentMonth(); if (!$month) { $this->sendMessage($chatId, "No tienes ningún mes abierto actualmente."); return; } $totalExpenses = $month->expenses()->sum('amount'); $expensesList = $month->expenses()->latest()->limit(5)->get(); $text = "📝 *Gastos del Mes*\n\n" . "• *Total:* $" . number_format($totalExpenses, 2) . "\n\n"; if ($expensesList->count() > 0) { $text .= "Últimos gastos:\n"; foreach ($expensesList as $expense) { $text .= "• {$expense->description}: \$" . number_format($expense->amount, 2) . "\n"; } } $this->sendMessage($chatId, $text); } /** * Mostrar resumen de comisiones */ private function showSummary(User $user, string $chatId): void { $month = $user->getCurrentMonth(); if (!$month) { $this->sendMessage($chatId, "No tienes ningún mes abierto actualmente."); return; } $data = CommissionCalculator::calculateForMonth($user, $month); $text = "💵 *Resumen de Comisiones*\n\n" . "• *Mes:* {$data['month_name']}\n" . "• *Ventas Sistema:* \$" . number_format($data['total_system_sales'], 2) . "\n" . "• *Comisión ({$data['commission_percentage']}%):* \$" . number_format($data['commission_amount'], 2) . "\n" . "• *Salario:* \$" . number_format($data['monthly_salary'], 2) . "\n" . "• *Gastos:* \$" . number_format($data['total_expenses'], 2) . "\n" . "• *Total a Recibir:* \$" . number_format($data['total_earning'], 2); $this->sendMessage($chatId, $text); } /** * Generar código de verificación */ public static function generateVerificationCode(): string { return str_pad((string) random_int(0, 999999), 6, '0', STR_PAD_LEFT); } /** * Configurar webhook */ public function setWebhook(): bool { if (!$this->botToken || !$this->webhookUrl) { Log::warning('Cannot set webhook: missing configuration'); return false; } try { $response = Http::post("https://api.telegram.org/bot{$this->botToken}/setWebhook", [ 'url' => $this->webhookUrl ]); return $response->json('ok', false); } catch (\Exception $e) { Log::error('Telegram set webhook error', ['error' => $e->getMessage()]); return false; } } }