UI: тарифы Basic/Pro/Family и меню оплат

This commit is contained in:
unknown
2025-11-25 15:40:33 +03:00
parent 779f13b98e
commit f042cc2f9e
2 changed files with 112 additions and 55 deletions

View File

@@ -4,11 +4,18 @@ from instences.config import BASE_URL_FASTAPI
import aiohttp import aiohttp
from aiogram.enums.parse_mode import ParseMode from aiogram.enums.parse_mode import ParseMode
from aiogram.filters import Command from aiogram.filters import Command
from keyboard.keyboards import tarif_Lark_pro_keyboard, tarif_Lark_keyboard, tarif_confirm_keyboard,buy_keyboard from keyboard.keyboards import (
tarif_Lark_pro_keyboard,
tarif_Lark_keyboard,
tarif_Lark_family_keyboard,
tarif_confirm_keyboard,
buy_keyboard,
)
router = Router() router = Router()
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
async def call_api(method, endpoint, data=None): async def call_api(method, endpoint, data=None):
""" """
Выполняет HTTP-запрос к FastAPI. Выполняет HTTP-запрос к FastAPI.
@@ -19,22 +26,25 @@ async def call_api(method, endpoint, data=None):
try: try:
async with aiohttp.ClientSession() as session: async with aiohttp.ClientSession() as session:
async with session.request(method, url, json=data) as response: async with session.request(method, url, json=data) as response:
logger.info(f"Получен ответ от {url}: статус {response.status}") logger.info(
f"Получен ответ от {url}: статус {response.status}")
if response.status in {200, 201}: if response.status in {200, 201}:
result = await response.json() result = await response.json()
logger.debug(f"Ответ JSON: {result}") logger.debug(f"Ответ JSON: {result}")
return result return result
if response.status in {404,400}: if response.status in {404, 400}:
result = await response.json() result = await response.json()
logger.debug(f"Код {response.status}, возвращаю {result}") logger.debug(f"Код {response.status}, возвращаю {result}")
return result return result
logger.error(f"Ошибка в запросе: статус {response.status}, причина {response.reason}") logger.error(
f"Ошибка в запросе: статус {response.status}, причина {response.reason}")
return "ERROR" return "ERROR"
except Exception as e: except Exception as e:
logger.exception(f"Исключение при выполнении запроса к {url}: {e}") logger.exception(f"Исключение при выполнении запроса к {url}: {e}")
return "ERROR" return "ERROR"
def escape_markdown_v2(text: str) -> str: def escape_markdown_v2(text: str) -> str:
""" """
Экранирует специальные символы для Markdown_V2. Экранирует специальные символы для Markdown_V2.
@@ -45,7 +55,6 @@ def escape_markdown_v2(text: str) -> str:
return text return text
@router.message(Command("subscriptions")) @router.message(Command("subscriptions"))
async def supp(message: types.Message): async def supp(message: types.Message):
""" """
@@ -56,7 +65,8 @@ async def supp(message: types.Message):
try: try:
# Вызов API для получения URI # Вызов API для получения URI
result = await call_api("GET", f"/uri?telegram_id={message.from_user.id}") result = await call_api("GET", f"/uri?telegram_id={message.from_user.id}")
uri = result.get('detail', "Error") # Получаем URI из ответа или "Error", если ключ отсутствует # Получаем URI из ответа или "Error", если ключ отсутствует
uri = result.get('detail', "Error")
# Проверка результата # Проверка результата
if uri == "Error": if uri == "Error":
@@ -71,7 +81,8 @@ async def supp(message: types.Message):
except Exception as e: except Exception as e:
# Логирование ошибок # Логирование ошибок
logger.error(f"Ошибка при вызове API для подписки: {e}") logger.error(f"Ошибка при вызове API для подписки: {e}")
text = escape_markdown_v2("Произошла неожиданная ошибка при получении подписки.") text = escape_markdown_v2(
"Произошла неожиданная ошибка при получении подписки.")
# Ответ пользователю # Ответ пользователю
await message.answer( await message.answer(
@@ -79,16 +90,33 @@ async def supp(message: types.Message):
parse_mode=ParseMode.MARKDOWN_V2 parse_mode=ParseMode.MARKDOWN_V2
) )
@router.callback_query(lambda callback: callback.data == "buy_subscription") @router.callback_query(lambda callback: callback.data == "buy_subscription")
async def buy_subscription_callback_handler(callback: types.CallbackQuery): async def buy_subscription_callback_handler(callback: types.CallbackQuery):
""" """
Обработчик callback_query с data="buy_subscription". Меню выбора тарифа: Basic / Pro / Family + показ баланса.
""" """
await callback.message.edit_text( # Тянем пользователя, чтобы показать баланс
f"Ознакомься с условиями в вкладке \"О тарифах\" и выбери подходящий 🦅", user_data = await call_api("GET", f"/user/{callback.from_user.id}")
reply_markup=buy_keyboard() balance = user_data.get("balance", 0) if user_data else "?"
text = (
" <b>Подключить новую подписку</b>\n\n"
"🐣 Lark Basic - 200 ₽ / мес\n"
"🦅 Lark Pro - 400 ₽ / мес\n"
"👨‍👩‍👧 Lark Family - 700 ₽ / мес\n\n"
f"💰 Баланс: {balance}\n\n"
"Выбери тариф:"
) )
await callback.message.edit_text(
text,
parse_mode=ParseMode.HTML,
reply_markup=buy_keyboard(),
)
await callback.answer()
@router.callback_query(lambda callback: callback.data == "subs") @router.callback_query(lambda callback: callback.data == "subs")
async def subs_callback_handler(callback: types.CallbackQuery): async def subs_callback_handler(callback: types.CallbackQuery):
""" """
@@ -99,6 +127,7 @@ async def subs_callback_handler(callback: types.CallbackQuery):
reply_markup=tarif_Lark_keyboard() reply_markup=tarif_Lark_keyboard()
) )
@router.callback_query(lambda callback: callback.data == "subs_pro") @router.callback_query(lambda callback: callback.data == "subs_pro")
async def subs_pro_callback_handler(callback: types.CallbackQuery): async def subs_pro_callback_handler(callback: types.CallbackQuery):
""" """
@@ -109,6 +138,19 @@ async def subs_pro_callback_handler(callback: types.CallbackQuery):
reply_markup=tarif_Lark_pro_keyboard() reply_markup=tarif_Lark_pro_keyboard()
) )
@router.callback_query(lambda callback: callback.data == "subs_family")
async def subs_family_callback_handler(callback: types.CallbackQuery):
"""
Обработчик callback_query с data="subs_family".
"""
await callback.message.edit_text(
"Подписки Lark Family",
reply_markup=tarif_Lark_family_keyboard(),
)
await callback.answer()
@router.callback_query(lambda callback: callback.data.startswith("Lark:")) @router.callback_query(lambda callback: callback.data.startswith("Lark:"))
async def lark_tariff_callback_handler(callback: types.CallbackQuery): async def lark_tariff_callback_handler(callback: types.CallbackQuery):
""" """
@@ -133,6 +175,7 @@ async def lark_tariff_callback_handler(callback: types.CallbackQuery):
keyboard = tarif_confirm_keyboard(tariff_name, tariff_time, tariff_class) keyboard = tarif_confirm_keyboard(tariff_name, tariff_time, tariff_class)
await callback.message.edit_text(text=text, reply_markup=keyboard) await callback.message.edit_text(text=text, reply_markup=keyboard)
@router.callback_query(lambda callback: callback.data.startswith("confirm:")) @router.callback_query(lambda callback: callback.data.startswith("confirm:"))
async def confirm_callback_handler(callback: types.CallbackQuery): async def confirm_callback_handler(callback: types.CallbackQuery):
""" """
@@ -164,5 +207,3 @@ async def confirm_callback_handler(callback: types.CallbackQuery):
await callback.message.edit_text("Произошла ошибка при оформлении подписки.") await callback.message.edit_text("Произошла ошибка при оформлении подписки.")
finally: finally:
await callback.answer() await callback.answer()

View File

@@ -92,12 +92,11 @@ def ticket_keyboard():
def buy_keyboard(): def buy_keyboard():
""" """
Меню выбора тарифа. Меню выбора тарифа.
Лейблы ближе к твоему стилю, но callbackи остаются старые.
""" """
builder = InlineKeyboardBuilder() builder = InlineKeyboardBuilder()
builder.row( builder.row(
InlineKeyboardButton( InlineKeyboardButton(
text="🐣 Lark (Basic)", text="🐣 Lark Basic",
callback_data="subs", callback_data="subs",
) )
) )
@@ -109,8 +108,8 @@ def buy_keyboard():
) )
builder.row( builder.row(
InlineKeyboardButton( InlineKeyboardButton(
text=" О тарифах", text="👨‍👩‍👧 Lark Family",
url="https://t.me/proxylark/19", callback_data="subs_family",
) )
) )
builder.row( builder.row(
@@ -136,51 +135,36 @@ def subhist_keyboard():
return builder.as_markup() return builder.as_markup()
def popup_keyboard(): def payment_methods_keyboard(amount: int):
""" """
Пополнение: суммы как в твоём топап-меню. Способы оплаты для выбранной суммы.
ЛаркинсКоины убрал нахер
""" """
builder = InlineKeyboardBuilder() builder = InlineKeyboardBuilder()
for amount in [200, 300, 600, 1000]: builder.row(
builder.row( InlineKeyboardButton(
InlineKeyboardButton( text="⭐ Telegram Stars",
text=f"{amount}", callback_data=f"method_stars_{amount}",
callback_data=f"popup:{amount}",
)
) )
)
builder.row(
InlineKeyboardButton(
text="💵 YooKassa",
callback_data=f"method_ykassa_{amount}",
)
)
builder.row(
InlineKeyboardButton(
text="🪙 CryptoBot",
callback_data=f"method_crypto_{amount}",
)
)
builder.row( builder.row(
InlineKeyboardButton( InlineKeyboardButton(
text="🔙 Назад", text="🔙 Назад",
callback_data="profile",
)
)
return builder.as_markup()
def balance_keyboard():
"""
Баланс
"""
builder = InlineKeyboardBuilder()
builder.row(
InlineKeyboardButton(
text="🪙 Пополнить баланс",
callback_data="popup", callback_data="popup",
) )
) )
builder.row(
InlineKeyboardButton(
text="🧾 История транзакций",
callback_data="tranhist",
)
)
builder.row(
InlineKeyboardButton(
text="🔙 Назад",
callback_data="profile",
)
)
return builder.as_markup() return builder.as_markup()
@@ -248,6 +232,38 @@ def tarif_Lark_pro_keyboard():
return builder.as_markup() return builder.as_markup()
def tarif_Lark_family_keyboard():
"""
Тариф Lark Family.
"""
builder = InlineKeyboardBuilder()
builder.row(
InlineKeyboardButton(
text="👨‍👩‍👧 Lark Family 1 месяц",
callback_data="Lark:Family:1",
)
)
builder.row(
InlineKeyboardButton(
text="👨‍👩‍👧 Lark Family 6 месяцев",
callback_data="Lark:Family:6",
)
)
builder.row(
InlineKeyboardButton(
text="👨‍👩‍👧 Lark Family 12 месяцев",
callback_data="Lark:Family:12",
)
)
builder.row(
InlineKeyboardButton(
text="🔙 Назад",
callback_data="buy_subscription",
)
)
return builder.as_markup()
def guide_keyboard(): def guide_keyboard():
""" """
Руководство по подключению Руководство по подключению