feat: Implement payment notification system and API structure

- Added notifications for successful payments in `api/core/notifications.py`.
- Created main API entry point in `api/main.py` with FastAPI integration.
- Established routing structure in `api/routes/__init__.py` and `api/routes/pally.py` for handling payment callbacks.
- Developed billing handlers in `bot/handlers/billing.py` and `bot/handlers/buy.py` for subscription management.
- Introduced state management for user interactions in `bot/states/`.
- Created user interface elements in `bot/keyboards/` for navigation and payment processing.
- Set up middleware for dependency injection in `bot/middlewares/di.py`.
- Added support for user commands and interactions in `bot/handlers/common.py` and `bot/handlers/support.py`.
- Implemented logging and error handling throughout the bot's functionality.
- Created entry point script for API server in `entrypoints/api.sh`.
This commit is contained in:
2026-04-24 17:41:42 +07:00
parent d98383285e
commit 049f31118d
37 changed files with 292 additions and 41 deletions

49
bot/handlers/billing.py Normal file
View File

@@ -0,0 +1,49 @@
import logging
from aiogram import F, Router
from aiogram.fsm.context import FSMContext
from aiogram.types import CallbackQuery
from sqlalchemy.ext.asyncio import AsyncSession
from bot.keyboards.client import pay_url, return_to_menu
from bot.states.buy import BillingStorage
from bot.texts import BILL_CREATED, BILL_CREATION, CALLBACK_FALLBACK
from schemas.billing import BillingContext, BillingProviders
from schemas.di import DependenciesDTO
router = Router()
logger = logging.getLogger(__name__)
@router.callback_query(BillingStorage.pending, F.data == "billing:pally")
async def pally_init(
cb: CallbackQuery, state: FSMContext, session: AsyncSession, deps: DependenciesDTO
):
data = await state.get_data()
ctx: BillingContext | None = data.get("ctx")
if not ctx:
logger.warning("ctx not found on billing choice")
await cb.message.edit_text(CALLBACK_FALLBACK, reply_markup=return_to_menu)
return
await state.clear()
ctx.provider = BillingProviders.PALLY
await cb.message.edit_text(
BILL_CREATION.format(amount=ctx.amount, provider=ctx.provider.value.title())
)
bill = await deps.billing_service.pally_initiate_payment(
session, deps.pally_client, user_id=cb.from_user.id, amount=ctx.amount
)
if not bill:
await cb.message.edit_text(CALLBACK_FALLBACK, reply_markup=return_to_menu)
logger.critical("bill creation prompted, but bill is None")
return
await cb.message.edit_text(
BILL_CREATED.format(amount=ctx.amount, provider=ctx.provider.value.title()),
reply_markup=pay_url(bill.link_page_url),
)