added gb packets selling
This commit is contained in:
@@ -34,7 +34,7 @@ async def get_payments_with_pagination(session: AsyncSession, page: int = 0,
|
||||
return payments, total_count
|
||||
|
||||
|
||||
def format_payment_text(payment: Payment, i18n: JsonI18n, lang: str) -> str:
|
||||
def format_payment_text(payment: Payment, i18n: JsonI18n, lang: str, settings: Settings) -> str:
|
||||
"""Format single payment info as text."""
|
||||
_ = lambda key, **kwargs: i18n.gettext(lang, key, **kwargs)
|
||||
|
||||
@@ -66,12 +66,21 @@ def format_payment_text(payment: Payment, i18n: JsonI18n, lang: str) -> str:
|
||||
'severpay': 'SeverPay',
|
||||
'platega': 'Platega',
|
||||
}.get(payment.provider, payment.provider or 'Unknown')
|
||||
|
||||
traffic_mode = getattr(settings, "traffic_sale_mode", False)
|
||||
if traffic_mode:
|
||||
traffic_val = payment.subscription_duration_months or 0
|
||||
traffic_display = str(int(traffic_val)) if float(traffic_val).is_integer() else f"{traffic_val:g}"
|
||||
period_line = _("admin_payment_traffic_label", default="🗂 Трафик: <b>{traffic_gb} GB</b>", traffic_gb=traffic_display)
|
||||
else:
|
||||
period_line = _("admin_payment_months_label", default="📅 Период: <b>{months} мес.</b>", months=payment.subscription_duration_months or 0)
|
||||
|
||||
return (
|
||||
f"{status_emoji} <b>{payment.amount} {payment.currency}</b>\n"
|
||||
f"👤 {user_info}\n"
|
||||
f"💳 {provider_text}\n"
|
||||
f"📅 {payment_date}\n"
|
||||
f"{period_line}\n"
|
||||
f"📋 {payment.status}\n"
|
||||
f"📝 {payment.description or 'N/A'}"
|
||||
)
|
||||
@@ -109,7 +118,7 @@ async def view_payments_handler(callback: types.CallbackQuery, i18n_data: dict,
|
||||
total_pages=total_pages) + "\n")
|
||||
|
||||
for i, payment in enumerate(payments, 1):
|
||||
text_parts.append(f"<b>{page * page_size + i}.</b> {format_payment_text(payment, i18n, current_lang)}")
|
||||
text_parts.append(f"<b>{page * page_size + i}.</b> {format_payment_text(payment, i18n, current_lang, settings)}")
|
||||
text_parts.append("") # Empty line between payments
|
||||
|
||||
# Build keyboard with pagination and export
|
||||
@@ -202,13 +211,21 @@ async def export_payments_csv_handler(callback: types.CallbackQuery, i18n_data:
|
||||
_("admin_csv_provider", default="Provider"),
|
||||
_("admin_csv_status", default="Status"),
|
||||
_("admin_csv_description", default="Description"),
|
||||
_("admin_csv_months", default="Months"),
|
||||
_("admin_csv_units", default="Months/GB"),
|
||||
_("admin_csv_created_at", default="Created At"),
|
||||
_("admin_csv_provider_payment_id", default="Provider Payment ID")
|
||||
])
|
||||
|
||||
traffic_mode = getattr(settings, "traffic_sale_mode", False)
|
||||
|
||||
# Write payment data
|
||||
for payment in all_payments:
|
||||
units_val = payment.subscription_duration_months or ""
|
||||
if traffic_mode and units_val not in ("", None):
|
||||
try:
|
||||
units_val = str(int(units_val)) if float(units_val).is_integer() else f"{units_val:g}"
|
||||
except Exception:
|
||||
units_val = payment.subscription_duration_months or ""
|
||||
writer.writerow([
|
||||
payment.payment_id,
|
||||
payment.user_id,
|
||||
@@ -219,7 +236,7 @@ async def export_payments_csv_handler(callback: types.CallbackQuery, i18n_data:
|
||||
payment.provider or "",
|
||||
payment.status,
|
||||
payment.description or "",
|
||||
payment.subscription_duration_months or "",
|
||||
units_val,
|
||||
payment.created_at.strftime('%Y-%m-%d %H:%M:%S') if payment.created_at else "",
|
||||
payment.provider_payment_id or ""
|
||||
])
|
||||
|
||||
@@ -40,6 +40,8 @@ async def process_successful_payment(session: AsyncSession, bot: Bot,
|
||||
metadata = payment_info_from_webhook.get("metadata", {})
|
||||
user_id_str = metadata.get("user_id")
|
||||
subscription_months_str = metadata.get("subscription_months")
|
||||
traffic_gb_str = metadata.get("traffic_gb")
|
||||
sale_mode = metadata.get("sale_mode") or ("traffic" if settings.traffic_sale_mode else "subscription")
|
||||
promo_code_id_str = metadata.get("promo_code_id")
|
||||
payment_db_id_str = metadata.get("payment_db_id")
|
||||
auto_renew_subscription_id_str = metadata.get(
|
||||
@@ -47,8 +49,11 @@ async def process_successful_payment(session: AsyncSession, bot: Bot,
|
||||
|
||||
# For auto-renew payments, payment_db_id may be absent. In that case,
|
||||
# we will create/ensure a payment record idempotently using provider payment id.
|
||||
if (not user_id_str or not subscription_months_str
|
||||
or (not payment_db_id_str and not auto_renew_subscription_id_str)):
|
||||
if (
|
||||
not user_id_str
|
||||
or (not subscription_months_str and not traffic_gb_str)
|
||||
or (not payment_db_id_str and not auto_renew_subscription_id_str)
|
||||
):
|
||||
logging.error(
|
||||
f"Missing crucial metadata for payment: {payment_info_from_webhook.get('id')}, metadata: {metadata}"
|
||||
)
|
||||
@@ -57,15 +62,17 @@ async def process_successful_payment(session: AsyncSession, bot: Bot,
|
||||
db_user = None
|
||||
try:
|
||||
user_id = int(user_id_str)
|
||||
subscription_months = int(subscription_months_str)
|
||||
subscription_months = float(subscription_months_str or 0)
|
||||
traffic_amount_gb = float(traffic_gb_str) if traffic_gb_str else subscription_months
|
||||
payment_db_id = int(
|
||||
payment_db_id_str) if payment_db_id_str and payment_db_id_str.isdigit() else None
|
||||
is_auto_renew = bool(auto_renew_subscription_id_str and not payment_db_id)
|
||||
is_auto_renew = bool(auto_renew_subscription_id_str and not payment_db_id and sale_mode != "traffic")
|
||||
promo_code_id = int(
|
||||
promo_code_id_str
|
||||
) if promo_code_id_str and promo_code_id_str.isdigit() else None
|
||||
|
||||
amount_data = payment_info_from_webhook.get("amount", {})
|
||||
months_for_record = int(subscription_months) if sale_mode != "traffic" else 0
|
||||
payment_value = float(amount_data.get("value", 0.0))
|
||||
|
||||
# If this is an auto-renewal (no payment_db_id in metadata), ensure a payment record exists
|
||||
@@ -79,9 +86,9 @@ async def process_successful_payment(session: AsyncSession, bot: Bot,
|
||||
user_id=user_id,
|
||||
amount=payment_value,
|
||||
currency=amount_data.get("currency", settings.DEFAULT_CURRENCY_SYMBOL),
|
||||
months=subscription_months,
|
||||
months=months_for_record or 1,
|
||||
description=payment_info_from_webhook.get(
|
||||
"description") or f"Auto-renewal for {subscription_months} months",
|
||||
"description") or f"Auto-renewal for {months_for_record or subscription_months} months",
|
||||
provider="yookassa",
|
||||
provider_payment_id=yk_payment_id_from_hook,
|
||||
)
|
||||
@@ -196,14 +203,18 @@ async def process_successful_payment(session: AsyncSession, bot: Bot,
|
||||
raise Exception(
|
||||
f"DB Error: Could not update payment record {payment_db_id}")
|
||||
|
||||
months_for_activation = int(subscription_months) if sale_mode != "traffic" else 0
|
||||
activation_details = await subscription_service.activate_subscription(
|
||||
session,
|
||||
user_id,
|
||||
subscription_months,
|
||||
months_for_activation,
|
||||
payment_value,
|
||||
payment_db_id,
|
||||
promo_code_id_from_payment=promo_code_id,
|
||||
provider="yookassa")
|
||||
provider="yookassa",
|
||||
sale_mode=sale_mode,
|
||||
traffic_gb=traffic_amount_gb if sale_mode == "traffic" else None,
|
||||
)
|
||||
|
||||
if not activation_details or not activation_details.get('end_date'):
|
||||
logging.error(
|
||||
@@ -217,13 +228,15 @@ async def process_successful_payment(session: AsyncSession, bot: Bot,
|
||||
applied_promo_bonus_days = activation_details.get(
|
||||
"applied_promo_bonus_days", 0)
|
||||
|
||||
referral_bonus_info = await referral_service.apply_referral_bonuses_for_payment(
|
||||
session,
|
||||
user_id,
|
||||
subscription_months,
|
||||
current_payment_db_id=payment_db_id,
|
||||
skip_if_active_before_payment=False,
|
||||
)
|
||||
referral_bonus_info = None
|
||||
if sale_mode != "traffic":
|
||||
referral_bonus_info = await referral_service.apply_referral_bonuses_for_payment(
|
||||
session,
|
||||
user_id,
|
||||
months_for_activation or int(subscription_months) or 1,
|
||||
current_payment_db_id=payment_db_id,
|
||||
skip_if_active_before_payment=False,
|
||||
)
|
||||
applied_referee_bonus_days_from_referral: Optional[int] = None
|
||||
if referral_bonus_info and referral_bonus_info.get(
|
||||
"referee_new_end_date"):
|
||||
@@ -236,14 +249,28 @@ async def process_successful_payment(session: AsyncSession, bot: Bot,
|
||||
user_lang = db_user.language_code if db_user and db_user.language_code else settings.DEFAULT_LANGUAGE
|
||||
_ = lambda key, **kwargs: i18n.gettext(user_lang, key, **kwargs)
|
||||
|
||||
traffic_label = (
|
||||
str(int(traffic_amount_gb)) if float(traffic_amount_gb).is_integer() else f"{traffic_amount_gb:g}"
|
||||
)
|
||||
# For auto-renew charges, avoid re-sending config link; send concise message
|
||||
if is_auto_renew and final_end_date_for_user:
|
||||
if sale_mode != "traffic" and is_auto_renew and final_end_date_for_user:
|
||||
details_message = _(
|
||||
"yookassa_auto_renewal",
|
||||
months=subscription_months,
|
||||
months=int(subscription_months),
|
||||
end_date=final_end_date_for_user.strftime('%Y-%m-%d'),
|
||||
)
|
||||
details_markup = None
|
||||
elif sale_mode == "traffic":
|
||||
config_link = activation_details.get("subscription_url") or _("config_link_not_available")
|
||||
details_message = _(
|
||||
"payment_successful_traffic_full",
|
||||
traffic_gb=traffic_label,
|
||||
end_date=final_end_date_for_user.strftime('%Y-%m-%d') if final_end_date_for_user else "—",
|
||||
config_link=config_link,
|
||||
)
|
||||
details_markup = get_connect_and_main_keyboard(
|
||||
user_lang, i18n, settings, config_link, preserve_message=True
|
||||
)
|
||||
else:
|
||||
config_link = activation_details.get("subscription_url") or _(
|
||||
"config_link_not_available"
|
||||
@@ -263,7 +290,7 @@ async def process_successful_payment(session: AsyncSession, bot: Bot,
|
||||
|
||||
details_message = _(
|
||||
"payment_successful_with_referral_bonus_full",
|
||||
months=subscription_months,
|
||||
months=int(subscription_months),
|
||||
base_end_date=base_subscription_end_date.strftime('%Y-%m-%d'),
|
||||
bonus_days=applied_referee_bonus_days_from_referral,
|
||||
final_end_date=final_end_date_for_user.strftime('%Y-%m-%d'),
|
||||
@@ -273,7 +300,7 @@ async def process_successful_payment(session: AsyncSession, bot: Bot,
|
||||
elif applied_promo_bonus_days > 0 and final_end_date_for_user:
|
||||
details_message = _(
|
||||
"payment_successful_with_promo_full",
|
||||
months=subscription_months,
|
||||
months=int(subscription_months),
|
||||
bonus_days=applied_promo_bonus_days,
|
||||
end_date=final_end_date_for_user.strftime('%Y-%m-%d'),
|
||||
config_link=config_link,
|
||||
@@ -281,7 +308,7 @@ async def process_successful_payment(session: AsyncSession, bot: Bot,
|
||||
elif final_end_date_for_user:
|
||||
details_message = _(
|
||||
"payment_successful_full",
|
||||
months=subscription_months,
|
||||
months=int(subscription_months),
|
||||
end_date=final_end_date_for_user.strftime('%Y-%m-%d'),
|
||||
config_link=config_link,
|
||||
)
|
||||
@@ -315,9 +342,10 @@ async def process_successful_payment(session: AsyncSession, bot: Bot,
|
||||
user_id=user_id,
|
||||
amount=payment_value,
|
||||
currency=settings.DEFAULT_CURRENCY_SYMBOL,
|
||||
months=subscription_months,
|
||||
months=int(subscription_months) if sale_mode != "traffic" else 0,
|
||||
payment_provider="yookassa", # This is specifically for YooKassa webhook
|
||||
username=user.username if user else None
|
||||
username=user.username if user else None,
|
||||
traffic_gb=traffic_amount_gb if sale_mode == "traffic" else None,
|
||||
)
|
||||
except Exception as e:
|
||||
logging.error(f"Failed to send payment notification: {e}")
|
||||
|
||||
@@ -74,24 +74,26 @@ async def referral_command_handler(event: Union[types.Message,
|
||||
return
|
||||
|
||||
bonus_info_parts = []
|
||||
if settings.subscription_options:
|
||||
if getattr(settings, "traffic_sale_mode", False):
|
||||
bonus_details_str = _("referral_not_available_for_traffic")
|
||||
else:
|
||||
if settings.subscription_options:
|
||||
for months_period_key, _price in sorted(
|
||||
settings.subscription_options.items()):
|
||||
|
||||
for months_period_key, _price in sorted(
|
||||
settings.subscription_options.items()):
|
||||
inv_bonus = settings.referral_bonus_inviter.get(months_period_key)
|
||||
ref_bonus = settings.referral_bonus_referee.get(months_period_key)
|
||||
if inv_bonus is not None or ref_bonus is not None:
|
||||
bonus_info_parts.append(
|
||||
_("referral_bonus_per_period",
|
||||
months=months_period_key,
|
||||
inviter_bonus_days=inv_bonus
|
||||
if inv_bonus is not None else _("no_bonus_placeholder"),
|
||||
referee_bonus_days=ref_bonus
|
||||
if ref_bonus is not None else _("no_bonus_placeholder")))
|
||||
|
||||
inv_bonus = settings.referral_bonus_inviter.get(months_period_key)
|
||||
ref_bonus = settings.referral_bonus_referee.get(months_period_key)
|
||||
if inv_bonus is not None or ref_bonus is not None:
|
||||
bonus_info_parts.append(
|
||||
_("referral_bonus_per_period",
|
||||
months=months_period_key,
|
||||
inviter_bonus_days=inv_bonus
|
||||
if inv_bonus is not None else _("no_bonus_placeholder"),
|
||||
referee_bonus_days=ref_bonus
|
||||
if ref_bonus is not None else _("no_bonus_placeholder")))
|
||||
|
||||
bonus_details_str = "\n".join(bonus_info_parts) if bonus_info_parts else _(
|
||||
"referral_no_bonuses_configured")
|
||||
bonus_details_str = "\n".join(bonus_info_parts) if bonus_info_parts else _(
|
||||
"referral_no_bonuses_configured")
|
||||
|
||||
# Get referral statistics
|
||||
referral_stats = await referral_service.get_referral_stats(session, inviter_user_id)
|
||||
|
||||
@@ -40,11 +40,15 @@ async def display_subscription_options(event: Union[types.Message, types.Callbac
|
||||
return
|
||||
|
||||
currency_symbol_val = settings.DEFAULT_CURRENCY_SYMBOL
|
||||
text_content = get_text("select_subscription_period") if settings.subscription_options else get_text("no_subscription_options_available")
|
||||
traffic_mode = bool(getattr(settings, "traffic_sale_mode", False))
|
||||
options = settings.traffic_packages if traffic_mode else settings.subscription_options
|
||||
text_content = (
|
||||
get_text("select_traffic_package") if traffic_mode else get_text("select_subscription_period")
|
||||
) if options else get_text("no_subscription_options_available")
|
||||
|
||||
reply_markup = (
|
||||
get_subscription_options_keyboard(settings.subscription_options, currency_symbol_val, current_lang, i18n)
|
||||
if settings.subscription_options
|
||||
get_subscription_options_keyboard(options, currency_symbol_val, current_lang, i18n, traffic_mode=traffic_mode)
|
||||
if options
|
||||
else get_back_to_main_menu_markup(current_lang, i18n)
|
||||
)
|
||||
|
||||
@@ -125,17 +129,50 @@ async def my_subscription_command_handler(
|
||||
|
||||
end_date = active.get("end_date")
|
||||
days_left = (end_date.date() - datetime.now().date()).days if end_date else 0
|
||||
text = get_text(
|
||||
"my_subscription_details",
|
||||
end_date=end_date.strftime("%Y-%m-%d") if end_date else "N/A",
|
||||
days_left=max(0, days_left),
|
||||
status=active.get("status_from_panel", get_text("status_active")).capitalize(),
|
||||
config_link=active.get("config_link") or get_text("config_link_not_available"),
|
||||
traffic_limit=(f"{active['traffic_limit_bytes'] / 2**30:.2f} GB" if active.get("traffic_limit_bytes") else get_text("traffic_unlimited")),
|
||||
traffic_used=(
|
||||
f"{active['traffic_used_bytes'] / 2**30:.2f} GB" if active.get("traffic_used_bytes") is not None else get_text("traffic_na")
|
||||
),
|
||||
)
|
||||
traffic_mode = bool(getattr(settings, "traffic_sale_mode", False))
|
||||
def _fmt_gb(val: Optional[float]) -> str:
|
||||
if val is None:
|
||||
return get_text("traffic_na")
|
||||
try:
|
||||
if isinstance(val, (int, float)):
|
||||
val_gb = float(val) / (2**30)
|
||||
return f"{val_gb:.2f} GB"
|
||||
except Exception:
|
||||
pass
|
||||
return str(val)
|
||||
|
||||
if traffic_mode:
|
||||
limit_display = _fmt_gb(active.get("traffic_limit_bytes"))
|
||||
used_display = _fmt_gb(active.get("traffic_used_bytes"))
|
||||
remaining_display = get_text("traffic_na")
|
||||
try:
|
||||
limit_val = active.get("traffic_limit_bytes") or 0
|
||||
used_val = active.get("traffic_used_bytes") or 0
|
||||
remaining_val = max(0, float(limit_val) - float(used_val))
|
||||
remaining_display = _fmt_gb(remaining_val)
|
||||
except Exception:
|
||||
pass
|
||||
text = get_text(
|
||||
"my_traffic_details",
|
||||
status=active.get("status_from_panel", get_text("status_active")).capitalize(),
|
||||
end_date=end_date.strftime("%Y-%m-%d") if end_date else get_text("traffic_no_expiry"),
|
||||
traffic_limit=limit_display,
|
||||
traffic_used=used_display,
|
||||
traffic_left=remaining_display,
|
||||
config_link=active.get("config_link") or get_text("config_link_not_available"),
|
||||
)
|
||||
else:
|
||||
text = get_text(
|
||||
"my_subscription_details",
|
||||
end_date=end_date.strftime("%Y-%m-%d") if end_date else "N/A",
|
||||
days_left=max(0, days_left),
|
||||
status=active.get("status_from_panel", get_text("status_active")).capitalize(),
|
||||
config_link=active.get("config_link") or get_text("config_link_not_available"),
|
||||
traffic_limit=(f"{active['traffic_limit_bytes'] / 2**30:.2f} GB" if active.get("traffic_limit_bytes") else get_text("traffic_unlimited")),
|
||||
traffic_used=(
|
||||
f"{active['traffic_used_bytes'] / 2**30:.2f} GB" if active.get("traffic_used_bytes") is not None else get_text("traffic_na")
|
||||
),
|
||||
)
|
||||
|
||||
base_markup = get_back_to_main_menu_markup(current_lang, i18n)
|
||||
kb = base_markup.inline_keyboard
|
||||
@@ -214,7 +251,7 @@ async def my_subscription_command_handler(
|
||||
])
|
||||
|
||||
# 2) Auto-renew toggle (YooKassa only)
|
||||
if local_sub and local_sub.provider == "yookassa" and settings.yookassa_autopayments_active:
|
||||
if not traffic_mode and local_sub and local_sub.provider == "yookassa" and settings.yookassa_autopayments_active:
|
||||
toggle_text = (
|
||||
get_text("autorenew_disable_button") if local_sub.auto_renew_enabled else get_text("autorenew_enable_button")
|
||||
)
|
||||
@@ -226,7 +263,7 @@ async def my_subscription_command_handler(
|
||||
])
|
||||
|
||||
# 3) Payment methods management (when autopayments enabled)
|
||||
if settings.yookassa_autopayments_active:
|
||||
if not traffic_mode and settings.yookassa_autopayments_active:
|
||||
prepend_rows.append([
|
||||
InlineKeyboardButton(text=get_text("payment_methods_manage_button"), callback_data="pm:manage")
|
||||
])
|
||||
|
||||
@@ -390,8 +390,15 @@ async def payment_method_history(callback: types.CallbackQuery, settings: Settin
|
||||
await callback.message.edit_text(_("payment_method_no_history"), reply_markup=back_markup)
|
||||
return
|
||||
|
||||
traffic_mode = getattr(settings, "traffic_sale_mode", False)
|
||||
|
||||
def _format_item(p: Payment) -> str:
|
||||
title = p.description or _("subscription_purchase_title", months=p.subscription_duration_months or 1)
|
||||
if traffic_mode:
|
||||
units_val = p.subscription_duration_months or 0
|
||||
units_display = str(int(units_val)) if float(units_val).is_integer() else f"{units_val:g}"
|
||||
title = p.description or _("traffic_purchase_title", traffic_gb=units_display)
|
||||
else:
|
||||
title = p.description or _("subscription_purchase_title", months=p.subscription_duration_months or 1)
|
||||
date_str = p.created_at.strftime('%Y-%m-%d') if p.created_at else "N/A"
|
||||
return f"{date_str} — {title} — {p.amount:.2f} {p.currency}"
|
||||
|
||||
@@ -455,4 +462,3 @@ async def payment_methods_list(callback: types.CallbackQuery, settings: Settings
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
|
||||
@@ -39,9 +39,10 @@ async def pay_crypto_callback_handler(
|
||||
|
||||
try:
|
||||
_, data_payload = callback.data.split(":", 1)
|
||||
months_str, price_str = data_payload.split(":")
|
||||
months = int(months_str)
|
||||
price_amount = float(price_str)
|
||||
parts = data_payload.split(":")
|
||||
months = float(parts[0])
|
||||
price_amount = float(parts[1])
|
||||
sale_mode = parts[2] if len(parts) > 2 else "subscription"
|
||||
except (ValueError, IndexError):
|
||||
try:
|
||||
await callback.answer(get_text("error_try_again"), show_alert=True)
|
||||
@@ -50,7 +51,12 @@ async def pay_crypto_callback_handler(
|
||||
return
|
||||
|
||||
user_id = callback.from_user.id
|
||||
payment_description = get_text("payment_description_subscription", months=months)
|
||||
human_value = str(int(months)) if float(months).is_integer() else f"{months:g}"
|
||||
payment_description = (
|
||||
get_text("payment_description_traffic", traffic_gb=human_value)
|
||||
if sale_mode == "traffic"
|
||||
else get_text("payment_description_subscription", months=int(months))
|
||||
)
|
||||
|
||||
invoice_url = await cryptopay_service.create_invoice(
|
||||
session=session,
|
||||
@@ -58,17 +64,22 @@ async def pay_crypto_callback_handler(
|
||||
months=months,
|
||||
amount=price_amount,
|
||||
description=payment_description,
|
||||
sale_mode=sale_mode,
|
||||
)
|
||||
|
||||
if invoice_url:
|
||||
try:
|
||||
await callback.message.edit_text(
|
||||
get_text(key="payment_link_message", months=months),
|
||||
get_text(
|
||||
key="payment_link_message_traffic" if sale_mode == "traffic" else "payment_link_message",
|
||||
months=int(months),
|
||||
traffic_gb=human_value,
|
||||
),
|
||||
reply_markup=get_payment_url_keyboard(
|
||||
invoice_url,
|
||||
current_lang,
|
||||
i18n,
|
||||
back_callback=f"subscribe_period:{months}",
|
||||
back_callback=f"subscribe_period:{human_value}",
|
||||
back_text_key="back_to_payment_methods_button",
|
||||
),
|
||||
disable_web_page_preview=False,
|
||||
@@ -76,12 +87,16 @@ async def pay_crypto_callback_handler(
|
||||
except Exception:
|
||||
try:
|
||||
await callback.message.answer(
|
||||
get_text(key="payment_link_message", months=months),
|
||||
get_text(
|
||||
key="payment_link_message_traffic" if sale_mode == "traffic" else "payment_link_message",
|
||||
months=int(months),
|
||||
traffic_gb=human_value,
|
||||
),
|
||||
reply_markup=get_payment_url_keyboard(
|
||||
invoice_url,
|
||||
current_lang,
|
||||
i18n,
|
||||
back_callback=f"subscribe_period:{months}",
|
||||
back_callback=f"subscribe_period:{human_value}",
|
||||
back_text_key="back_to_payment_methods_button",
|
||||
),
|
||||
disable_web_page_preview=False,
|
||||
|
||||
@@ -47,9 +47,10 @@ async def pay_fk_callback_handler(
|
||||
|
||||
try:
|
||||
_, data_payload = callback.data.split(":", 1)
|
||||
months_str, price_str = data_payload.split(":")
|
||||
months = int(months_str)
|
||||
price_rub = float(price_str)
|
||||
parts = data_payload.split(":")
|
||||
months = float(parts[0])
|
||||
price_rub = float(parts[1])
|
||||
sale_mode = parts[2] if len(parts) > 2 else "subscription"
|
||||
except (ValueError, IndexError):
|
||||
logging.error(f"Invalid pay_fk data in callback: {callback.data}")
|
||||
try:
|
||||
@@ -59,7 +60,12 @@ async def pay_fk_callback_handler(
|
||||
return
|
||||
|
||||
user_id = callback.from_user.id
|
||||
payment_description = get_text("payment_description_subscription", months=months)
|
||||
human_value = str(int(months)) if float(months).is_integer() else f"{months:g}"
|
||||
payment_description = (
|
||||
get_text("payment_description_traffic", traffic_gb=human_value)
|
||||
if sale_mode == "traffic"
|
||||
else get_text("payment_description_subscription", months=int(months))
|
||||
)
|
||||
currency_code = getattr(freekassa_service, "default_currency", None) or settings.DEFAULT_CURRENCY_SYMBOL or "RUB"
|
||||
|
||||
payment_record_payload = {
|
||||
@@ -68,7 +74,7 @@ async def pay_fk_callback_handler(
|
||||
"currency": currency_code,
|
||||
"status": "pending_freekassa",
|
||||
"description": payment_description,
|
||||
"subscription_duration_months": months,
|
||||
"subscription_duration_months": int(months),
|
||||
"provider": "freekassa",
|
||||
}
|
||||
|
||||
@@ -135,12 +141,16 @@ async def pay_fk_callback_handler(
|
||||
)
|
||||
try:
|
||||
await callback.message.edit_text(
|
||||
f"{order_info_text}\n\n" + get_text(key="payment_link_message", months=months),
|
||||
f"{order_info_text}\n\n" + get_text(
|
||||
key="payment_link_message_traffic" if sale_mode == "traffic" else "payment_link_message",
|
||||
months=int(months),
|
||||
traffic_gb=human_value,
|
||||
),
|
||||
reply_markup=get_payment_url_keyboard(
|
||||
location,
|
||||
current_lang,
|
||||
i18n,
|
||||
back_callback=f"subscribe_period:{months}",
|
||||
back_callback=f"subscribe_period:{human_value}",
|
||||
back_text_key="back_to_payment_methods_button",
|
||||
),
|
||||
disable_web_page_preview=False,
|
||||
@@ -149,12 +159,16 @@ async def pay_fk_callback_handler(
|
||||
logging.warning(f"FreeKassa: failed to display payment link ({e_edit}), sending new message.")
|
||||
try:
|
||||
await callback.message.answer(
|
||||
f"{order_info_text}\n\n" + get_text(key="payment_link_message", months=months),
|
||||
f"{order_info_text}\n\n" + get_text(
|
||||
key="payment_link_message_traffic" if sale_mode == "traffic" else "payment_link_message",
|
||||
months=int(months),
|
||||
traffic_gb=human_value,
|
||||
),
|
||||
reply_markup=get_payment_url_keyboard(
|
||||
location,
|
||||
current_lang,
|
||||
i18n,
|
||||
back_callback=f"subscribe_period:{months}",
|
||||
back_callback=f"subscribe_period:{human_value}",
|
||||
back_text_key="back_to_payment_methods_button",
|
||||
),
|
||||
disable_web_page_preview=False,
|
||||
|
||||
@@ -47,9 +47,10 @@ async def pay_platega_callback_handler(
|
||||
|
||||
try:
|
||||
_, data_payload = callback.data.split(":", 1)
|
||||
months_str, price_str = data_payload.split(":")
|
||||
months = int(months_str)
|
||||
price_rub = float(price_str)
|
||||
parts = data_payload.split(":")
|
||||
months = float(parts[0])
|
||||
price_rub = float(parts[1])
|
||||
sale_mode = parts[2] if len(parts) > 2 else "subscription"
|
||||
except (ValueError, IndexError):
|
||||
logging.error(f"Invalid pay_platega data in callback: {callback.data}")
|
||||
try:
|
||||
@@ -59,7 +60,12 @@ async def pay_platega_callback_handler(
|
||||
return
|
||||
|
||||
user_id = callback.from_user.id
|
||||
payment_description = get_text("payment_description_subscription", months=months)
|
||||
human_value = str(int(months)) if float(months).is_integer() else f"{months:g}"
|
||||
payment_description = (
|
||||
get_text("payment_description_traffic", traffic_gb=human_value)
|
||||
if sale_mode == "traffic"
|
||||
else get_text("payment_description_subscription", months=int(months))
|
||||
)
|
||||
currency_code = settings.DEFAULT_CURRENCY_SYMBOL or "RUB"
|
||||
|
||||
payment_record_payload = {
|
||||
@@ -68,7 +74,7 @@ async def pay_platega_callback_handler(
|
||||
"currency": currency_code,
|
||||
"status": "pending_platega",
|
||||
"description": payment_description,
|
||||
"subscription_duration_months": months,
|
||||
"subscription_duration_months": int(months),
|
||||
"provider": "platega",
|
||||
}
|
||||
|
||||
@@ -96,6 +102,7 @@ async def pay_platega_callback_handler(
|
||||
"payment_db_id": payment_record.payment_id,
|
||||
"user_id": user_id,
|
||||
"months": months,
|
||||
"sale_mode": sale_mode,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -136,12 +143,16 @@ async def pay_platega_callback_handler(
|
||||
|
||||
try:
|
||||
await callback.message.edit_text(
|
||||
get_text(key="payment_link_message", months=months),
|
||||
get_text(
|
||||
key="payment_link_message_traffic" if sale_mode == "traffic" else "payment_link_message",
|
||||
months=int(months),
|
||||
traffic_gb=human_value,
|
||||
),
|
||||
reply_markup=get_payment_url_keyboard(
|
||||
redirect_url,
|
||||
current_lang,
|
||||
i18n,
|
||||
back_callback=f"subscribe_period:{months}",
|
||||
back_callback=f"subscribe_period:{human_value}",
|
||||
back_text_key="back_to_payment_methods_button",
|
||||
),
|
||||
disable_web_page_preview=False,
|
||||
@@ -150,12 +161,16 @@ async def pay_platega_callback_handler(
|
||||
logging.warning(f"Platega: failed to display payment link ({e_edit}), sending new message.")
|
||||
try:
|
||||
await callback.message.answer(
|
||||
get_text(key="payment_link_message", months=months),
|
||||
get_text(
|
||||
key="payment_link_message_traffic" if sale_mode == "traffic" else "payment_link_message",
|
||||
months=int(months),
|
||||
traffic_gb=human_value,
|
||||
),
|
||||
reply_markup=get_payment_url_keyboard(
|
||||
redirect_url,
|
||||
current_lang,
|
||||
i18n,
|
||||
back_callback=f"subscribe_period:{months}",
|
||||
back_callback=f"subscribe_period:{human_value}",
|
||||
back_text_key="back_to_payment_methods_button",
|
||||
),
|
||||
disable_web_page_preview=False,
|
||||
|
||||
@@ -46,9 +46,10 @@ async def pay_severpay_callback_handler(
|
||||
|
||||
try:
|
||||
_, data_payload = callback.data.split(":", 1)
|
||||
months_str, price_str = data_payload.split(":")
|
||||
months = int(months_str)
|
||||
price_rub = float(price_str)
|
||||
parts = data_payload.split(":")
|
||||
months = float(parts[0])
|
||||
price_rub = float(parts[1])
|
||||
sale_mode = parts[2] if len(parts) > 2 else "subscription"
|
||||
except (ValueError, IndexError):
|
||||
logging.error(f"Invalid pay_severpay data in callback: {callback.data}")
|
||||
try:
|
||||
@@ -58,7 +59,12 @@ async def pay_severpay_callback_handler(
|
||||
return
|
||||
|
||||
user_id = callback.from_user.id
|
||||
payment_description = get_text("payment_description_subscription", months=months)
|
||||
human_value = str(int(months)) if float(months).is_integer() else f"{months:g}"
|
||||
payment_description = (
|
||||
get_text("payment_description_traffic", traffic_gb=human_value)
|
||||
if sale_mode == "traffic"
|
||||
else get_text("payment_description_subscription", months=int(months))
|
||||
)
|
||||
currency_code = settings.DEFAULT_CURRENCY_SYMBOL or "RUB"
|
||||
|
||||
payment_record_payload = {
|
||||
@@ -67,7 +73,7 @@ async def pay_severpay_callback_handler(
|
||||
"currency": currency_code,
|
||||
"status": "pending_severpay",
|
||||
"description": payment_description,
|
||||
"subscription_duration_months": months,
|
||||
"subscription_duration_months": int(months),
|
||||
"provider": "severpay",
|
||||
}
|
||||
|
||||
@@ -126,12 +132,16 @@ async def pay_severpay_callback_handler(
|
||||
if payment_link:
|
||||
try:
|
||||
await callback.message.edit_text(
|
||||
get_text(key="payment_link_message", months=months),
|
||||
get_text(
|
||||
key="payment_link_message_traffic" if sale_mode == "traffic" else "payment_link_message",
|
||||
months=int(months),
|
||||
traffic_gb=human_value,
|
||||
),
|
||||
reply_markup=get_payment_url_keyboard(
|
||||
payment_link,
|
||||
current_lang,
|
||||
i18n,
|
||||
back_callback=f"subscribe_period:{months}",
|
||||
back_callback=f"subscribe_period:{human_value}",
|
||||
back_text_key="back_to_payment_methods_button",
|
||||
),
|
||||
disable_web_page_preview=False,
|
||||
@@ -140,12 +150,16 @@ async def pay_severpay_callback_handler(
|
||||
logging.warning(f"SeverPay: failed to display payment link ({e_edit}), sending new message.")
|
||||
try:
|
||||
await callback.message.answer(
|
||||
get_text(key="payment_link_message", months=months),
|
||||
get_text(
|
||||
key="payment_link_message_traffic" if sale_mode == "traffic" else "payment_link_message",
|
||||
months=int(months),
|
||||
traffic_gb=human_value,
|
||||
),
|
||||
reply_markup=get_payment_url_keyboard(
|
||||
payment_link,
|
||||
current_lang,
|
||||
i18n,
|
||||
back_callback=f"subscribe_period:{months}",
|
||||
back_callback=f"subscribe_period:{human_value}",
|
||||
back_text_key="back_to_payment_methods_button",
|
||||
),
|
||||
disable_web_page_preview=False,
|
||||
|
||||
@@ -40,9 +40,10 @@ async def pay_stars_callback_handler(
|
||||
|
||||
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)
|
||||
parts = data_payload.split(":")
|
||||
months = float(parts[0])
|
||||
stars_price = int(float(parts[1]))
|
||||
sale_mode = parts[2] if len(parts) > 2 else "subscription"
|
||||
except (ValueError, IndexError):
|
||||
try:
|
||||
await callback.answer(get_text("error_try_again"), show_alert=True)
|
||||
@@ -51,7 +52,12 @@ async def pay_stars_callback_handler(
|
||||
return
|
||||
|
||||
user_id = callback.from_user.id
|
||||
payment_description = get_text("payment_description_subscription", months=months)
|
||||
human_value = str(int(months)) if float(months).is_integer() else f"{months:g}"
|
||||
payment_description = (
|
||||
get_text("payment_description_traffic", traffic_gb=human_value)
|
||||
if sale_mode == "traffic"
|
||||
else get_text("payment_description_subscription", months=int(months))
|
||||
)
|
||||
|
||||
payment_db_id = await stars_service.create_invoice(
|
||||
session=session,
|
||||
@@ -59,16 +65,21 @@ async def pay_stars_callback_handler(
|
||||
months=months,
|
||||
stars_price=stars_price,
|
||||
description=payment_description,
|
||||
sale_mode=sale_mode,
|
||||
)
|
||||
|
||||
if payment_db_id:
|
||||
try:
|
||||
await callback.message.edit_text(
|
||||
get_text("payment_invoice_sent_message", months=months),
|
||||
get_text(
|
||||
"payment_invoice_sent_message_traffic" if sale_mode == "traffic" else "payment_invoice_sent_message",
|
||||
months=int(months),
|
||||
traffic_gb=human_value,
|
||||
),
|
||||
reply_markup=InlineKeyboardMarkup(inline_keyboard=[
|
||||
[InlineKeyboardButton(
|
||||
text=get_text("back_to_payment_methods_button"),
|
||||
callback_data=f"subscribe_period:{months}",
|
||||
callback_data=f"subscribe_period:{human_value}",
|
||||
)]
|
||||
]),
|
||||
)
|
||||
@@ -106,9 +117,10 @@ async def handle_successful_stars_payment(
|
||||
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)
|
||||
parts = (payload or "").split(":")
|
||||
payment_db_id = int(parts[0])
|
||||
months = float(parts[1]) if len(parts) > 1 else 0
|
||||
sale_mode = parts[2] if len(parts) > 2 else "subscription"
|
||||
except Exception:
|
||||
return
|
||||
|
||||
@@ -120,4 +132,5 @@ async def handle_successful_stars_payment(
|
||||
months=months,
|
||||
stars_amount=stars_amount,
|
||||
i18n_data=i18n_data,
|
||||
sale_mode=sale_mode,
|
||||
)
|
||||
|
||||
@@ -29,8 +29,9 @@ async def select_subscription_period_callback_handler(
|
||||
pass
|
||||
return
|
||||
|
||||
traffic_mode = bool(getattr(settings, "traffic_sale_mode", False))
|
||||
try:
|
||||
months = int(callback.data.split(":")[-1])
|
||||
months = float(callback.data.split(":")[-1])
|
||||
except (ValueError, IndexError):
|
||||
logging.error(f"Invalid subscription period in callback_data: {callback.data}")
|
||||
try:
|
||||
@@ -39,10 +40,13 @@ async def select_subscription_period_callback_handler(
|
||||
pass
|
||||
return
|
||||
|
||||
price_rub = settings.subscription_options.get(months)
|
||||
price_source = settings.traffic_packages if traffic_mode else settings.subscription_options
|
||||
stars_price_source = settings.stars_traffic_packages if traffic_mode else settings.stars_subscription_options
|
||||
|
||||
price_rub = price_source.get(months)
|
||||
if price_rub is None:
|
||||
logging.error(
|
||||
f"Price not found for {months} months subscription period in settings.subscription_options."
|
||||
f"Price not found for option {months} using {'traffic_packages' if traffic_mode else 'subscription_options'}."
|
||||
)
|
||||
try:
|
||||
await callback.answer(get_text("error_try_again"), show_alert=True)
|
||||
@@ -51,8 +55,8 @@ async def select_subscription_period_callback_handler(
|
||||
return
|
||||
|
||||
currency_symbol_val = settings.DEFAULT_CURRENCY_SYMBOL
|
||||
text_content = get_text("choose_payment_method")
|
||||
stars_price = settings.stars_subscription_options.get(months)
|
||||
text_content = get_text("choose_payment_method_traffic") if traffic_mode else get_text("choose_payment_method")
|
||||
stars_price = stars_price_source.get(months)
|
||||
reply_markup = get_payment_method_keyboard(
|
||||
months,
|
||||
price_rub,
|
||||
@@ -61,6 +65,7 @@ async def select_subscription_period_callback_handler(
|
||||
current_lang,
|
||||
i18n,
|
||||
settings,
|
||||
sale_mode="traffic" if traffic_mode else "subscription",
|
||||
)
|
||||
|
||||
try:
|
||||
|
||||
@@ -18,10 +18,17 @@ from db.dal import payment_dal, user_billing_dal
|
||||
router = Router(name="user_subscription_payments_yookassa_router")
|
||||
|
||||
|
||||
def _parse_months_and_price(payload: str) -> Optional[Tuple[int, float]]:
|
||||
def _format_value(val: float) -> str:
|
||||
return str(int(val)) if float(val).is_integer() else f"{val:g}"
|
||||
|
||||
|
||||
def _parse_offer_payload(payload: str) -> Optional[Tuple[float, float, str]]:
|
||||
try:
|
||||
months_str, price_str = payload.split(":")
|
||||
return int(months_str), float(price_str)
|
||||
parts = payload.split(":")
|
||||
value = float(parts[0])
|
||||
price = float(parts[1])
|
||||
sale_mode = parts[2] if len(parts) > 2 else "subscription"
|
||||
return value, price, sale_mode
|
||||
except (ValueError, IndexError):
|
||||
return None
|
||||
|
||||
@@ -64,19 +71,24 @@ async def _initiate_yk_payment(
|
||||
back_callback: str,
|
||||
payment_method_id: Optional[str] = None,
|
||||
selected_method_internal_id: Optional[int] = None,
|
||||
sale_mode: str = "subscription",
|
||||
) -> bool:
|
||||
"""Create payment record and initiate YooKassa payment (new card or saved card)."""
|
||||
if not callback.message:
|
||||
return False
|
||||
|
||||
payment_description = get_text("payment_description_subscription", months=months)
|
||||
payment_description = (
|
||||
get_text("payment_description_traffic", traffic_gb=_format_value(months))
|
||||
if sale_mode == "traffic"
|
||||
else get_text("payment_description_subscription", months=int(months))
|
||||
)
|
||||
payment_record_data = {
|
||||
"user_id": user_id,
|
||||
"amount": price_rub,
|
||||
"currency": currency_code_for_yk,
|
||||
"status": "pending_yookassa",
|
||||
"description": payment_description,
|
||||
"subscription_duration_months": months,
|
||||
"subscription_duration_months": int(months),
|
||||
}
|
||||
|
||||
db_payment_record = None
|
||||
@@ -109,7 +121,10 @@ async def _initiate_yk_payment(
|
||||
"user_id": str(user_id),
|
||||
"subscription_months": str(months),
|
||||
"payment_db_id": str(db_payment_record.payment_id),
|
||||
"sale_mode": sale_mode,
|
||||
}
|
||||
if sale_mode == "traffic":
|
||||
yookassa_metadata["traffic_gb"] = str(months)
|
||||
if payment_method_id:
|
||||
yookassa_metadata["used_saved_payment_method_id"] = payment_method_id
|
||||
|
||||
@@ -198,7 +213,11 @@ async def _initiate_yk_payment(
|
||||
|
||||
try:
|
||||
await callback.message.edit_text(
|
||||
get_text(key="payment_link_message", months=months),
|
||||
get_text(
|
||||
key="payment_link_message_traffic" if sale_mode == "traffic" else "payment_link_message",
|
||||
months=int(months),
|
||||
traffic_gb=_format_value(months),
|
||||
),
|
||||
reply_markup=get_payment_url_keyboard(
|
||||
payment_response_yk["confirmation_url"],
|
||||
current_lang,
|
||||
@@ -214,7 +233,11 @@ async def _initiate_yk_payment(
|
||||
)
|
||||
try:
|
||||
await callback.message.answer(
|
||||
get_text(key="payment_link_message", months=months),
|
||||
get_text(
|
||||
key="payment_link_message_traffic" if sale_mode == "traffic" else "payment_link_message",
|
||||
months=int(months),
|
||||
traffic_gb=_format_value(months),
|
||||
),
|
||||
reply_markup=get_payment_url_keyboard(
|
||||
payment_response_yk["confirmation_url"],
|
||||
current_lang,
|
||||
@@ -328,7 +351,7 @@ async def pay_yk_callback_handler(callback: types.CallbackQuery, settings: Setti
|
||||
pass
|
||||
return
|
||||
|
||||
parsed = _parse_months_and_price(data_payload)
|
||||
parsed = _parse_offer_payload(data_payload)
|
||||
if not parsed:
|
||||
logging.error(f"Invalid pay_yk payload structure: {callback.data}")
|
||||
try:
|
||||
@@ -337,10 +360,10 @@ async def pay_yk_callback_handler(callback: types.CallbackQuery, settings: Setti
|
||||
pass
|
||||
return
|
||||
|
||||
months, price_rub = parsed
|
||||
months, price_rub, sale_mode = parsed
|
||||
user_id = callback.from_user.id
|
||||
currency_code_for_yk = "RUB"
|
||||
autopay_enabled = bool(settings.yookassa_autopayments_active)
|
||||
autopay_enabled = bool(settings.yookassa_autopayments_active and sale_mode != "traffic" and not settings.traffic_sale_mode)
|
||||
autopay_require_binding = bool(
|
||||
getattr(settings, 'YOOKASSA_AUTOPAYMENTS_REQUIRE_CARD_BINDING', True)
|
||||
)
|
||||
@@ -364,6 +387,7 @@ async def pay_yk_callback_handler(callback: types.CallbackQuery, settings: Setti
|
||||
current_lang,
|
||||
i18n,
|
||||
has_saved_cards=True,
|
||||
sale_mode=sale_mode,
|
||||
),
|
||||
)
|
||||
except Exception as e_edit:
|
||||
@@ -377,6 +401,7 @@ async def pay_yk_callback_handler(callback: types.CallbackQuery, settings: Setti
|
||||
current_lang,
|
||||
i18n,
|
||||
has_saved_cards=True,
|
||||
sale_mode=sale_mode,
|
||||
),
|
||||
)
|
||||
except Exception:
|
||||
@@ -400,7 +425,8 @@ async def pay_yk_callback_handler(callback: types.CallbackQuery, settings: Setti
|
||||
price_rub=price_rub,
|
||||
currency_code_for_yk=currency_code_for_yk,
|
||||
save_payment_method=autopay_enabled and autopay_require_binding,
|
||||
back_callback=f"subscribe_period:{months}",
|
||||
back_callback=f"subscribe_period:{_format_value(months)}",
|
||||
sale_mode=sale_mode,
|
||||
)
|
||||
try:
|
||||
await callback.answer()
|
||||
@@ -443,7 +469,7 @@ async def pay_yk_new_card_handler(callback: types.CallbackQuery, settings: Setti
|
||||
pass
|
||||
return
|
||||
|
||||
parsed = _parse_months_and_price(data_payload)
|
||||
parsed = _parse_offer_payload(data_payload)
|
||||
if not parsed:
|
||||
logging.error(f"Invalid pay_yk_new payload structure: {callback.data}")
|
||||
try:
|
||||
@@ -452,10 +478,10 @@ async def pay_yk_new_card_handler(callback: types.CallbackQuery, settings: Setti
|
||||
pass
|
||||
return
|
||||
|
||||
months, price_rub = parsed
|
||||
months, price_rub, sale_mode = parsed
|
||||
user_id = callback.from_user.id
|
||||
currency_code_for_yk = "RUB"
|
||||
autopay_enabled = bool(settings.yookassa_autopayments_active)
|
||||
autopay_enabled = bool(settings.yookassa_autopayments_active and sale_mode != "traffic" and not settings.traffic_sale_mode)
|
||||
autopay_require_binding = bool(
|
||||
getattr(settings, 'YOOKASSA_AUTOPAYMENTS_REQUIRE_CARD_BINDING', True)
|
||||
)
|
||||
@@ -473,7 +499,8 @@ async def pay_yk_new_card_handler(callback: types.CallbackQuery, settings: Setti
|
||||
price_rub=price_rub,
|
||||
currency_code_for_yk=currency_code_for_yk,
|
||||
save_payment_method=autopay_enabled and autopay_require_binding,
|
||||
back_callback=f"subscribe_period:{months}",
|
||||
back_callback=f"subscribe_period:{_format_value(months)}",
|
||||
sale_mode=sale_mode,
|
||||
)
|
||||
try:
|
||||
await callback.answer()
|
||||
@@ -494,14 +521,6 @@ async def pay_yk_saved_list_handler(callback: types.CallbackQuery, settings: Set
|
||||
pass
|
||||
return
|
||||
|
||||
autopay_enabled = bool(settings.yookassa_autopayments_active)
|
||||
if not autopay_enabled:
|
||||
try:
|
||||
await callback.answer(get_text("error_try_again"), show_alert=True)
|
||||
except Exception:
|
||||
pass
|
||||
return
|
||||
|
||||
try:
|
||||
_, data_payload = callback.data.split(":", 1)
|
||||
except ValueError:
|
||||
@@ -522,9 +541,10 @@ async def pay_yk_saved_list_handler(callback: types.CallbackQuery, settings: Set
|
||||
return
|
||||
|
||||
try:
|
||||
months = int(parts[0])
|
||||
months = float(parts[0])
|
||||
price_rub = float(parts[1])
|
||||
page = int(parts[2]) if len(parts) > 2 else 0
|
||||
sale_mode = parts[3] if len(parts) > 3 else "subscription"
|
||||
except (ValueError, IndexError):
|
||||
logging.error(f"pay_yk_saved_list payload parsing error: {callback.data}")
|
||||
try:
|
||||
@@ -533,6 +553,14 @@ async def pay_yk_saved_list_handler(callback: types.CallbackQuery, settings: Set
|
||||
pass
|
||||
return
|
||||
|
||||
autopay_enabled = bool(settings.yookassa_autopayments_active and sale_mode != "traffic" and not settings.traffic_sale_mode)
|
||||
if not autopay_enabled:
|
||||
try:
|
||||
await callback.answer(get_text("error_try_again"), show_alert=True)
|
||||
except Exception:
|
||||
pass
|
||||
return
|
||||
|
||||
user_id = callback.from_user.id
|
||||
try:
|
||||
saved_methods = await user_billing_dal.list_user_payment_methods(
|
||||
@@ -552,6 +580,7 @@ async def pay_yk_saved_list_handler(callback: types.CallbackQuery, settings: Set
|
||||
current_lang,
|
||||
i18n,
|
||||
has_saved_cards=False,
|
||||
sale_mode=sale_mode,
|
||||
),
|
||||
)
|
||||
except Exception as e_edit:
|
||||
@@ -565,6 +594,7 @@ async def pay_yk_saved_list_handler(callback: types.CallbackQuery, settings: Set
|
||||
current_lang,
|
||||
i18n,
|
||||
has_saved_cards=False,
|
||||
sale_mode=sale_mode,
|
||||
),
|
||||
)
|
||||
except Exception:
|
||||
@@ -596,6 +626,7 @@ async def pay_yk_saved_list_handler(callback: types.CallbackQuery, settings: Set
|
||||
current_lang,
|
||||
i18n,
|
||||
page=page,
|
||||
sale_mode=sale_mode,
|
||||
),
|
||||
)
|
||||
except Exception as e_edit:
|
||||
@@ -610,6 +641,7 @@ async def pay_yk_saved_list_handler(callback: types.CallbackQuery, settings: Set
|
||||
current_lang,
|
||||
i18n,
|
||||
page=page,
|
||||
sale_mode=sale_mode,
|
||||
),
|
||||
)
|
||||
except Exception:
|
||||
@@ -633,14 +665,6 @@ async def pay_yk_use_saved_handler(callback: types.CallbackQuery, settings: Sett
|
||||
pass
|
||||
return
|
||||
|
||||
autopay_enabled = bool(settings.yookassa_autopayments_active)
|
||||
if not autopay_enabled:
|
||||
try:
|
||||
await callback.answer(get_text("error_try_again"), show_alert=True)
|
||||
except Exception:
|
||||
pass
|
||||
return
|
||||
|
||||
if not yookassa_service or not yookassa_service.configured:
|
||||
logging.error("YooKassa service unavailable for pay_yk_use_saved.")
|
||||
try:
|
||||
@@ -673,8 +697,9 @@ async def pay_yk_use_saved_handler(callback: types.CallbackQuery, settings: Sett
|
||||
return
|
||||
|
||||
try:
|
||||
months = int(parts[0])
|
||||
months = float(parts[0])
|
||||
price_rub = float(parts[1])
|
||||
sale_mode = parts[3] if len(parts) > 3 else "subscription"
|
||||
except (ValueError, IndexError):
|
||||
logging.error(f"pay_yk_use_saved months/price parsing error: {callback.data}")
|
||||
try:
|
||||
@@ -683,6 +708,14 @@ async def pay_yk_use_saved_handler(callback: types.CallbackQuery, settings: Sett
|
||||
pass
|
||||
return
|
||||
|
||||
autopay_enabled = bool(settings.yookassa_autopayments_active and sale_mode != "traffic" and not settings.traffic_sale_mode)
|
||||
if not autopay_enabled:
|
||||
try:
|
||||
await callback.answer(get_text("error_try_again"), show_alert=True)
|
||||
except Exception:
|
||||
pass
|
||||
return
|
||||
|
||||
method_identifier = parts[2]
|
||||
user_id = callback.from_user.id
|
||||
|
||||
@@ -727,9 +760,10 @@ async def pay_yk_use_saved_handler(callback: types.CallbackQuery, settings: Sett
|
||||
price_rub=price_rub,
|
||||
currency_code_for_yk=currency_code_for_yk,
|
||||
save_payment_method=False,
|
||||
back_callback=f"pay_yk_saved_list:{months}:{price_rub}",
|
||||
back_callback=f"pay_yk_saved_list:{_format_value(months)}:{price_rub}:{sale_mode}",
|
||||
payment_method_id=selected_method.provider_payment_method_id,
|
||||
selected_method_internal_id=selected_method.method_id,
|
||||
sale_mode=sale_mode,
|
||||
)
|
||||
try:
|
||||
await callback.answer()
|
||||
|
||||
Reference in New Issue
Block a user