Add cryptocurrency and stars payment handlers to subscription module
- Implemented new callback handlers for cryptocurrency and stars payments, enhancing payment options for users. - Integrated error handling and user feedback mechanisms for payment processes, improving overall user experience. - Updated the pre-checkout and successful payment handling to accommodate new payment methods, ensuring seamless transaction processing. - Organized imports for better modularity and clarity in the payments module.
This commit is contained in:
@@ -6,6 +6,8 @@ from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from config.settings import Settings
|
||||
from bot.keyboards.inline.user_keyboards import get_payment_method_keyboard, get_payment_url_keyboard
|
||||
from bot.services.yookassa_service import YooKassaService
|
||||
from bot.services.crypto_pay_service import CryptoPayService
|
||||
from bot.services.stars_service import StarsService
|
||||
from bot.middlewares.i18n import JsonI18n
|
||||
from db.dal import payment_dal, user_billing_dal
|
||||
|
||||
@@ -259,3 +261,178 @@ async def pay_yk_callback_handler(callback: types.CallbackQuery, settings: Setti
|
||||
pass
|
||||
|
||||
|
||||
@router.callback_query(F.data.startswith("pay_crypto:"))
|
||||
async def pay_crypto_callback_handler(
|
||||
callback: types.CallbackQuery,
|
||||
settings: Settings,
|
||||
i18n_data: dict,
|
||||
session: AsyncSession,
|
||||
cryptopay_service: CryptoPayService,
|
||||
):
|
||||
current_lang = i18n_data.get("current_language", settings.DEFAULT_LANGUAGE)
|
||||
i18n: Optional[JsonI18n] = i18n_data.get("i18n_instance")
|
||||
get_text = (lambda key, **kwargs: i18n.gettext(current_lang, key, **kwargs) if i18n else key)
|
||||
|
||||
if not i18n or not callback.message:
|
||||
try:
|
||||
await callback.answer(get_text("error_occurred_try_again"), show_alert=True)
|
||||
except Exception:
|
||||
pass
|
||||
return
|
||||
|
||||
if not cryptopay_service or not getattr(cryptopay_service, "configured", False):
|
||||
try:
|
||||
await callback.answer(get_text("payment_service_unavailable_alert"), show_alert=True)
|
||||
except Exception:
|
||||
pass
|
||||
return
|
||||
|
||||
try:
|
||||
_, data_payload = callback.data.split(":", 1)
|
||||
months_str, price_str = data_payload.split(":")
|
||||
months = int(months_str)
|
||||
price_amount = float(price_str)
|
||||
except (ValueError, IndexError):
|
||||
try:
|
||||
await callback.answer(get_text("error_try_again"), show_alert=True)
|
||||
except Exception:
|
||||
pass
|
||||
return
|
||||
|
||||
user_id = callback.from_user.id
|
||||
payment_description = get_text("payment_description_subscription", months=months)
|
||||
|
||||
invoice_url = await cryptopay_service.create_invoice(
|
||||
session=session,
|
||||
user_id=user_id,
|
||||
months=months,
|
||||
amount=price_amount,
|
||||
description=payment_description,
|
||||
)
|
||||
|
||||
if invoice_url:
|
||||
try:
|
||||
await callback.message.edit_text(
|
||||
get_text(key="payment_link_message", months=months),
|
||||
reply_markup=get_payment_url_keyboard(invoice_url, current_lang, i18n),
|
||||
disable_web_page_preview=False,
|
||||
)
|
||||
except Exception:
|
||||
try:
|
||||
await callback.message.answer(
|
||||
get_text(key="payment_link_message", months=months),
|
||||
reply_markup=get_payment_url_keyboard(invoice_url, current_lang, i18n),
|
||||
disable_web_page_preview=False,
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
await callback.answer()
|
||||
except Exception:
|
||||
pass
|
||||
return
|
||||
|
||||
try:
|
||||
await callback.answer(get_text("error_payment_gateway"), show_alert=True)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
@router.callback_query(F.data.startswith("pay_stars:"))
|
||||
async def pay_stars_callback_handler(
|
||||
callback: types.CallbackQuery,
|
||||
settings: Settings,
|
||||
i18n_data: dict,
|
||||
session: AsyncSession,
|
||||
stars_service: StarsService,
|
||||
):
|
||||
current_lang = i18n_data.get("current_language", settings.DEFAULT_LANGUAGE)
|
||||
i18n: Optional[JsonI18n] = i18n_data.get("i18n_instance")
|
||||
get_text = (lambda key, **kwargs: i18n.gettext(current_lang, key, **kwargs) if i18n else key)
|
||||
|
||||
if not i18n or not callback.message:
|
||||
try:
|
||||
await callback.answer(get_text("error_occurred_try_again"), show_alert=True)
|
||||
except Exception:
|
||||
pass
|
||||
return
|
||||
|
||||
if not settings.STARS_ENABLED:
|
||||
try:
|
||||
await callback.answer(get_text("payment_service_unavailable_alert"), show_alert=True)
|
||||
except Exception:
|
||||
pass
|
||||
return
|
||||
|
||||
try:
|
||||
_, data_payload = callback.data.split(":", 1)
|
||||
months_str, stars_price_str = data_payload.split(":")
|
||||
months = int(months_str)
|
||||
stars_price = int(stars_price_str)
|
||||
except (ValueError, IndexError):
|
||||
try:
|
||||
await callback.answer(get_text("error_try_again"), show_alert=True)
|
||||
except Exception:
|
||||
pass
|
||||
return
|
||||
|
||||
user_id = callback.from_user.id
|
||||
payment_description = get_text("payment_description_subscription", months=months)
|
||||
|
||||
payment_db_id = await stars_service.create_invoice(
|
||||
session=session,
|
||||
user_id=user_id,
|
||||
months=months,
|
||||
stars_price=stars_price,
|
||||
description=payment_description,
|
||||
)
|
||||
|
||||
if payment_db_id:
|
||||
try:
|
||||
await callback.answer()
|
||||
except Exception:
|
||||
pass
|
||||
return
|
||||
|
||||
try:
|
||||
await callback.answer(get_text("error_payment_gateway"), show_alert=True)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
@router.pre_checkout_query()
|
||||
async def handle_pre_checkout_query(query: types.PreCheckoutQuery):
|
||||
try:
|
||||
await query.answer(ok=True)
|
||||
except Exception:
|
||||
# Nothing else to do here; Telegram will show an error if not answered
|
||||
pass
|
||||
|
||||
|
||||
@router.message(F.successful_payment)
|
||||
async def handle_successful_stars_payment(
|
||||
message: types.Message,
|
||||
settings: Settings,
|
||||
i18n_data: dict,
|
||||
session: AsyncSession,
|
||||
stars_service: StarsService,
|
||||
):
|
||||
payload = (message.successful_payment.invoice_payload
|
||||
if message and message.successful_payment else "")
|
||||
try:
|
||||
payment_db_id_str, months_str = (payload or "").split(":", 1)
|
||||
payment_db_id = int(payment_db_id_str)
|
||||
months = int(months_str)
|
||||
except Exception:
|
||||
return
|
||||
|
||||
stars_amount = int(message.successful_payment.total_amount) if message.successful_payment else 0
|
||||
await stars_service.process_successful_payment(
|
||||
session=session,
|
||||
message=message,
|
||||
payment_db_id=payment_db_id,
|
||||
months=months,
|
||||
stars_amount=stars_amount,
|
||||
i18n_data=i18n_data,
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user