From b0482cca1a5c2f7e1c0ae3532cdca159dabc5864 Mon Sep 17 00:00:00 2001 From: Boris Kovalskii <36034823+JustYay@users.noreply.github.com> Date: Mon, 15 Sep 2025 22:13:57 +0000 Subject: [PATCH] =?UTF-8?q?FIX=20"=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B1=D1=8B=D1=81=D1=82=D1=80=D0=BE?= =?UTF-8?q?=D0=B3=D0=BE=20=D1=84=D0=BB=D0=BE=D1=83=20=D0=B4=D0=BB=D1=8F=20?= =?UTF-8?q?=D0=BA=D0=B0=D1=81=D1=82=D0=BE=D0=BC=D0=BD=D1=8B=D1=85=20=D0=BA?= =?UTF-8?q?=D0=B0=D1=81=D1=81"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- handlers/payments/heleket/heleket.py | 82 ++++++++++++++- handlers/payments/kassai/kassai.py | 145 ++++++++++++++++++++++++++- handlers/payments/providers.py | 6 +- 3 files changed, 226 insertions(+), 7 deletions(-) diff --git a/handlers/payments/heleket/heleket.py b/handlers/payments/heleket/heleket.py index f8f1f99b..5a788fc0 100644 --- a/handlers/payments/heleket/heleket.py +++ b/handlers/payments/heleket/heleket.py @@ -22,10 +22,11 @@ from config import ( ) from handlers.payments.providers import get_providers from ..currency_rates import get_rub_rate -from handlers.buttons import BACK, HELEKET, PAY_2 -from handlers.texts import ENTER_SUM, HELEKET_CRYPTO_DESCRIPTION, HELEKET_PAYMENT_MESSAGE, PAYMENT_OPTIONS +from handlers.buttons import BACK, HELEKET, PAY_2, MAIN_MENU +from handlers.texts import DEFAULT_PAYMENT_MESSAGE, ENTER_SUM, HELEKET_CRYPTO_DESCRIPTION, HELEKET_PAYMENT_MESSAGE, PAYMENT_OPTIONS from handlers.utils import edit_or_send_message -from database import add_payment, async_session_maker +from handlers.payments.currency_rates import format_for_user +from database import add_payment, async_session_maker, get_temporary_data from logger import logger @@ -451,3 +452,78 @@ async def generate_heleket_payment_link(amount: int, tg_id: int, method: dict) - except Exception as e: logger.error(f"Error creating Heleket payment: {e}") return "https://heleket.com/" + + +async def handle_custom_amount_input_heleket( + event: types.Message | types.CallbackQuery, + session: AsyncSession, + pay_button_text: str = PAY_2, + main_menu_text: str = MAIN_MENU, +): + """ + Функция быстрого потока для Heleket - принимает недостающую сумму и формирует платеж. + Работает с временными данными из fast_payment_flow для создания/продления/подарка. + """ + if isinstance(event, types.CallbackQuery): + message = event.message + from_user = event.from_user + tg_id = from_user.id + temp_data = await get_temporary_data(session, tg_id) + if not temp_data or temp_data["state"] not in ["waiting_for_payment", "waiting_for_renewal_payment", "waiting_for_gift_payment"]: + await edit_or_send_message(target_message=message, text="❌ Не удалось получить данные для оплаты.") + return + amount = int(temp_data["data"].get("required_amount", 0)) + if amount <= 0: + await edit_or_send_message(target_message=message, text="❌ Не удалось определить сумму оплаты.") + return + if amount < 10: + await edit_or_send_message(target_message=message, text="❌ Минимальная сумма для оплаты криптовалютой — 10 рублей.") + return + enabled_methods = [m for m in HELEKET_PAYMENT_METHODS if m["enable"]] + if not enabled_methods: + await edit_or_send_message(target_message=message, text="❌ Способ оплаты Heleket временно недоступен.") + return + method = enabled_methods[0] + else: + message = event + from_user = message.from_user + tg_id = from_user.id + text = message.text + if not text or not text.isdigit(): + await message.answer("Введите корректную сумму числом.") + return + amount = int(text) + if amount <= 0: + await message.answer("Сумма должна быть больше нуля.") + return + if amount < 10: + await message.answer("Минимальная сумма для оплаты криптовалютой — 10 рублей.") + return + enabled_methods = [m for m in HELEKET_PAYMENT_METHODS if m["enable"]] + if not enabled_methods: + await message.answer("❌ Способ оплаты Heleket временно недоступен.") + return + method = enabled_methods[0] + + try: + payment_url = await generate_heleket_payment_link(amount, tg_id, method) + + markup = InlineKeyboardMarkup( + inline_keyboard=[ + [InlineKeyboardButton(text=pay_button_text, url=payment_url)], + [InlineKeyboardButton(text=main_menu_text, callback_data="profile")], + ] + ) + + language_code = getattr(from_user, "language_code", None) + amount_text = await format_for_user(session, tg_id, float(amount), language_code, force_currency="RUB") + text_out = DEFAULT_PAYMENT_MESSAGE.format(amount=amount_text) + + await edit_or_send_message(target_message=message, text=text_out, reply_markup=markup) + except Exception as e: + logger.error(f"Ошибка при создании платежа Heleket для пользователя {tg_id}: {e}") + await edit_or_send_message( + target_message=message, + text="Произошла ошибка при создании платежа. Попробуйте позже.", + reply_markup=InlineKeyboardMarkup(inline_keyboard=[]), + ) diff --git a/handlers/payments/kassai/kassai.py b/handlers/payments/kassai/kassai.py index c0905805..87628737 100644 --- a/handlers/payments/kassai/kassai.py +++ b/handlers/payments/kassai/kassai.py @@ -21,8 +21,9 @@ from config import ( PROVIDERS_ENABLED, ) from handlers.payments.providers import get_providers -from handlers.buttons import BACK, KASSAI_CARDS, KASSAI_SBP, PAY_2 +from handlers.buttons import BACK, KASSAI_CARDS, KASSAI_SBP, PAY_2, MAIN_MENU from handlers.texts import ( + DEFAULT_PAYMENT_MESSAGE, ENTER_SUM, KASSAI_CARDS_DESCRIPTION, KASSAI_PAYMENT_MESSAGE, @@ -30,6 +31,8 @@ from handlers.texts import ( PAYMENT_OPTIONS, ) from handlers.utils import edit_or_send_message +from handlers.payments.currency_rates import format_for_user +from database import get_temporary_data from logger import logger router = Router() @@ -397,3 +400,143 @@ def verify_kassai_signature(data: dict, signature: str) -> bool: except Exception as e: logger.error(f"Ошибка проверки подписи KassaAI: {e}") return False + + +async def handle_custom_amount_input_kassai_cards( + event: types.Message | types.CallbackQuery, + session: AsyncSession, + pay_button_text: str = PAY_2, + main_menu_text: str = MAIN_MENU, +): + """ + Функция быстрого потока для KassaI Cards - принимает недостающую сумму и формирует платеж картами. + Работает с временными данными из fast_payment_flow для создания/продления/подарка. + """ + if isinstance(event, types.CallbackQuery): + message = event.message + from_user = event.from_user + tg_id = from_user.id + temp_data = await get_temporary_data(session, tg_id) + if not temp_data or temp_data["state"] not in ["waiting_for_payment", "waiting_for_renewal_payment", "waiting_for_gift_payment"]: + await edit_or_send_message(target_message=message, text="❌ Не удалось получить данные для оплаты.") + return + amount = int(temp_data["data"].get("required_amount", 0)) + if amount <= 0: + await edit_or_send_message(target_message=message, text="❌ Не удалось определить сумму оплаты.") + return + method = next((m for m in KASSAI_PAYMENT_METHODS if m["name"] == "cards" and m["enable"]), None) + if not method: + await edit_or_send_message(target_message=message, text="❌ Оплата картами KassaAI временно недоступна.") + return + else: + message = event + from_user = message.from_user + tg_id = from_user.id + text = message.text + if not text or not text.isdigit(): + await message.answer("Введите корректную сумму числом.") + return + amount = int(text) + if amount <= 0: + await message.answer("Сумма должна быть больше нуля.") + return + method = next((m for m in KASSAI_PAYMENT_METHODS if m["name"] == "cards" and m["enable"]), None) + if not method: + await message.answer("❌ Оплата картами KassaAI временно недоступна.") + return + + try: + payment_url = await generate_kassai_payment_link(amount, tg_id, method) + + markup = InlineKeyboardMarkup( + inline_keyboard=[ + [InlineKeyboardButton(text=pay_button_text, url=payment_url)], + [InlineKeyboardButton(text=main_menu_text, callback_data="profile")], + ] + ) + + language_code = getattr(from_user, "language_code", None) + amount_text = await format_for_user(session, tg_id, float(amount), language_code, force_currency="RUB") + text_out = DEFAULT_PAYMENT_MESSAGE.format(amount=amount_text) + + await edit_or_send_message(target_message=message, text=text_out, reply_markup=markup) + except Exception as e: + logger.error(f"Ошибка при создании платежа KassaAI Cards для пользователя {tg_id}: {e}") + await edit_or_send_message( + target_message=message, + text="Произошла ошибка при создании платежа. Попробуйте позже.", + reply_markup=InlineKeyboardMarkup(inline_keyboard=[]), + ) + + +async def handle_custom_amount_input_kassai_sbp( + event: types.Message | types.CallbackQuery, + session: AsyncSession, + pay_button_text: str = PAY_2, + main_menu_text: str = MAIN_MENU, +): + """ + Функция быстрого потока для KassaI SBP - принимает недостающую сумму и формирует платеж через СБП. + Работает с временными данными из fast_payment_flow для создания/продления/подарка. + """ + if isinstance(event, types.CallbackQuery): + message = event.message + from_user = event.from_user + tg_id = from_user.id + temp_data = await get_temporary_data(session, tg_id) + if not temp_data or temp_data["state"] not in ["waiting_for_payment", "waiting_for_renewal_payment", "waiting_for_gift_payment"]: + await edit_or_send_message(target_message=message, text="❌ Не удалось получить данные для оплаты.") + return + amount = int(temp_data["data"].get("required_amount", 0)) + if amount <= 0: + await edit_or_send_message(target_message=message, text="❌ Не удалось определить сумму оплаты.") + return + if amount < 10: + await edit_or_send_message(target_message=message, text="❌ Минимальная сумма для оплаты через СБП — 10 рублей.") + return + method = next((m for m in KASSAI_PAYMENT_METHODS if m["name"] == "sbp" and m["enable"]), None) + if not method: + await edit_or_send_message(target_message=message, text="❌ Оплата через СБП KassaAI временно недоступна.") + return + else: + message = event + from_user = message.from_user + tg_id = from_user.id + text = message.text + if not text or not text.isdigit(): + await message.answer("Введите корректную сумму числом.") + return + amount = int(text) + if amount <= 0: + await message.answer("Сумма должна быть больше нуля.") + return + if amount < 10: + await message.answer("Минимальная сумма для оплаты через СБП — 10 рублей.") + return + method = next((m for m in KASSAI_PAYMENT_METHODS if m["name"] == "sbp" and m["enable"]), None) + if not method: + await message.answer("❌ Оплата через СБП KassaAI временно недоступна.") + return + + try: + payment_url = await generate_kassai_payment_link(amount, tg_id, method) + + markup = InlineKeyboardMarkup( + inline_keyboard=[ + [InlineKeyboardButton(text=pay_button_text, url=payment_url)], + [InlineKeyboardButton(text=main_menu_text, callback_data="profile")], + ] + ) + + language_code = getattr(from_user, "language_code", None) + amount_text = await format_for_user(session, tg_id, float(amount), language_code, force_currency="RUB") + text_out = DEFAULT_PAYMENT_MESSAGE.format(amount=amount_text) + + await edit_or_send_message(target_message=message, text=text_out, reply_markup=markup) + except Exception as e: + logger.error(f"Ошибка при создании платежа KassaAI SBP для пользователя {tg_id}: {e}") + await edit_or_send_message( + target_message=message, + text="Произошла ошибка при создании платежа. Попробуйте позже.", + reply_markup=InlineKeyboardMarkup(inline_keyboard=[]), + ) diff --git a/handlers/payments/providers.py b/handlers/payments/providers.py index e2c2e040..ec3ad55d 100644 --- a/handlers/payments/providers.py +++ b/handlers/payments/providers.py @@ -20,12 +20,12 @@ PROVIDERS_BASE: Dict[str, dict] = { "KASSAI_CARDS": { "currency": "RUB", "value": "pay_kassai_cards", - "fast": None, + "fast": "handle_custom_amount_input_kassai_cards", }, "KASSAI_SBP": { "currency": "RUB", "value": "pay_kassai_sbp", - "fast": None, + "fast": "handle_custom_amount_input_kassai_sbp", }, "WATA_RU": { "currency": "RUB", @@ -45,7 +45,7 @@ PROVIDERS_BASE: Dict[str, dict] = { "HELEKET": { "currency": "USD", "value": "pay_heleket_crypto", - "fast": None, + "fast": "handle_custom_amount_input_heleket", }, "CRYPTOBOT": { "currency": "USD",