from aiogram import Router, types from aiogram.filters import Command from aiogram.types import Message, InlineKeyboardMarkup, InlineKeyboardButton from decimal import Decimal import aiohttp from tg_bot.config.settings import settings from tg_bot.payment.yookassa.client import yookassa_client from tg_bot.domain.services.user_service import UserService from datetime import datetime router = Router() user_service = UserService() @router.message(Command("buy")) async def cmd_buy(message: Message): user_id = message.from_user.id username = message.from_user.username or f"user_{user_id}" try: user = await user_service.get_user_by_telegram_id(user_id) if user and user.is_premium and user.premium_until and user.premium_until > datetime.now(): days_left = (user.premium_until - datetime.now()).days await message.answer( f"У вас уже есть активная подписка!\n\n" f"• Статус: Premium активен\n" f"• Действует до: {user.premium_until.strftime('%d.%m.%Y')}\n" f"• Осталось дней: {days_left}\n\n" f"Новая подписка будет добавлена к текущей.", parse_mode="HTML" ) except aiohttp.ClientError as e: print(f"Не удалось подключиться к backend при проверке подписки: {e}") except Exception as e: print(f"Ошибка при проверке подписки: {e}") await message.answer( "*Создаю ссылку для оплаты...*\n\n" "Пожалуйста, подождите несколько секунд.", parse_mode="Markdown" ) try: payment_data = await yookassa_client.create_payment( amount=Decimal(str(settings.PAYMENT_AMOUNT)), description=f"Подписка VibeLawyerBot для @{username}", user_id=user_id ) print(f"Платёж создан в ЮKассе: {payment_data['id']}") keyboard = InlineKeyboardMarkup( inline_keyboard=[ [ InlineKeyboardButton( text="Оплатить онлайн", url=payment_data["confirmation_url"] ) ], [ InlineKeyboardButton( text="Проверить статус оплаты", callback_data=f"check_payment:{payment_data['id']}" ) ] ] ) response_text = ( f"Оплата подписки VibeLawyerBot\n\n" f"Детали платежа:\n" f"• Сумма: {settings.PAYMENT_AMOUNT} руб.\n" f"• Описание: Подписка на 30 дней\n" f"• ID платежа: {payment_data['id'][:20]}...\n\n" f"Что даёт подписка:\n" f"• Неограниченное число вопросов\n" f"• Приоритетная обработка\n" f"• Доступ ко всем функциям\n\n" f"После оплаты доступ активируется автоматически в течение 1-2 минут." ) await message.answer( response_text, parse_mode="HTML", reply_markup=keyboard, disable_web_page_preview=True ) await message.answer( "Инструкция по оплате:\n\n" "1. Нажмите кнопку 'Оплатить онлайн'\n" "2. Введите данные банковской карты\n" "3. Подтвердите оплату\n" "4. После успешной оплаты нажмите 'Проверить статус оплаты'\n\n" "Тестовые карты для проверки:\n" "• 5555 5555 5555 4477 - успешная оплата\n" " Срок: любой будущий (напр. 12/30)\n" " CVV: любые 3 цифры (напр. 123)\n\n" "Это тестовые карты, реальные деньги не списываются!", parse_mode="HTML" ) except Exception as e: print(f"Ошибка создания платежа: {e}") await message.answer( "Произошла ошибка при создании платежа\n\n" "Пожалуйста, попробуйте позже или обратитесь к администратору.\n\n" f"Ошибка: {str(e)[:100]}", parse_mode="HTML" ) @router.callback_query(lambda c: c.data.startswith("check_payment:")) async def check_payment_status(callback_query: types.CallbackQuery): yookassa_id = callback_query.data.split(":")[1] user_id = callback_query.from_user.id await callback_query.answer("Проверяю статус оплаты...") try: from yookassa import Payment as YooPayment payment = YooPayment.find_one(yookassa_id) if payment.status == "succeeded": try: success = await user_service.activate_premium(user_id) if success: user = await user_service.get_user_by_telegram_id(user_id) if user: await callback_query.message.answer( "Оплата подтверждена!\n\n" f"Ваш premium-доступ активирован до: " f"{user.premium_until.strftime('%d.%m.%Y') if user.premium_until else 'Не указано'}\n\n" "Теперь вы можете:\n" "• Задавать неограниченное количество вопросов\n" "• Получать приоритетные ответы\n" "• Использовать все функции бота\n\n" "Спасибо за покупку!", parse_mode="HTML" ) else: await callback_query.message.answer( "Оплата подтверждена, но не удалось активировать premium\n\n" "Пожалуйста, обратитесь к администратору.", parse_mode="HTML" ) else: await callback_query.message.answer( "Оплата подтверждена, но не удалось активировать premium\n\n" "Пожалуйста, обратитесь к администратору.", parse_mode="HTML" ) except Exception as e: print(f"Ошибка обработки платежа: {e}") await callback_query.message.answer( "Ошибка активации premium\n\n" "Пожалуйста, обратитесь к администратору.", parse_mode="HTML" ) elif payment.status == "pending": await callback_query.message.answer( "Платёж ещё не завершён\n\n" "Если вы уже оплатили, пожалуйста, подождите 1-2 минуты " "и проверьте статус снова.\n\n" "Проверьте правильность данных карты:\n" "• Срок действия должен быть будущим\n" "• CVV - 3 цифры на обратной стороне карты", parse_mode="HTML" ) else: await callback_query.message.answer( f"Статус платежа: {payment.status}\n\n" "Попробуйте оплатить ещё раз или обратитесь в поддержку.\n\n" "Для теста используйте карту:\n" "5555 5555 5555 4477\n" "Срок: 12/30, CVV: 123", parse_mode="HTML" ) except Exception as e: print(f"Ошибка проверки статуса: {e}") await callback_query.message.answer( "Не удалось проверить статус платежа\n\n" "Попробуйте позже или обратитесь к администратору.", parse_mode="HTML" ) @router.message(Command("mypayments")) async def cmd_my_payments(message: Message): await message.answer( "История платежей\n\n" "История платежей хранится в системе оплаты ЮKassa.\n" "Для проверки статуса подписки используйте команду /stats.\n\n" "Для оформления новой подписки используйте команду /buy", parse_mode="HTML" ) @router.message(Command("testcards")) async def cmd_testcards(message: Message): testcards_text = ( f"Тестовые банковские карты для оплаты\n\n" f"Для тестирования оплаты используйте:\n\n" f"Карта для успешной оплаты:\n" f"• Номер: 5555 5555 5555 4477\n" f"• Срок действия: ЛЮБОЙ будущий (например: 12/30)\n" f"• CVV код: ЛЮБЫЕ 3 цифры (например: 123)\n" f"• Результат: Оплата пройдёт успешно\n\n" f"Карта для отказа в оплате:\n" f"• Номер: 5555 5555 5555 4445\n" f"• Срок действия: ЛЮБОЙ будущий\n" f"• CVV код: ЛЮБЫЕ 3 цифры\n" f"• Результат: Оплата будет отклонена\n\n" f"Важно:\n" f"• Это тестовые карты, реальные деньги не списываются\n" f"• Используются только для проверки работы оплаты\n" f"• После успешной тестовой оплаты premium активируется\n\n" f"Для оплаты подписки используйте команду /buy" ) await message.answer(testcards_text, parse_mode="HTML")