ORDER ID added to SUccess info

This commit is contained in:
raufakchurin
2025-10-14 11:28:41 +05:00
parent c891122064
commit 4d43c9cf0f
12 changed files with 126 additions and 48 deletions
+7 -7
View File
@@ -24,6 +24,13 @@ DISABLE_WELCOME_MESSAGE= #
# Webhook Base URL (used for Telegram and payment providers) # Webhook Base URL (used for Telegram and payment providers)
WEBHOOK_BASE_URL=https://webhooks.yourdomain.tld WEBHOOK_BASE_URL=https://webhooks.yourdomain.tld
# Payment Method Toggles
YOOKASSA_ENABLED=True # Turn on YOOKASSA
FREEKASSA_ENABLED=True # Turn on FreeKassa
STARS_ENABLED=True # Turn on STARS
TRIBUTE_ENABLED=True # Turn on TRIBUTE
CRYPTOPAY_ENABLED=True # Turn on CRYPTOPAY
# YooKassa Payment Gateway Configuration # YooKassa Payment Gateway Configuration
YOOKASSA_SHOP_ID=your_shop_id # Your store ID in YooKassa YOOKASSA_SHOP_ID=your_shop_id # Your store ID in YooKassa
YOOKASSA_SECRET_KEY=your_secret_key # Your secret key for YooKassa YOOKASSA_SECRET_KEY=your_secret_key # Your secret key for YooKassa
@@ -33,7 +40,6 @@ YOOKASSA_VAT_CODE=1 #
YOOKASSA_AUTOPAYMENTS_ENABLED=False # Auto-renew toggle YOOKASSA_AUTOPAYMENTS_ENABLED=False # Auto-renew toggle
# FreeKassa Payment Gateway Configuration # FreeKassa Payment Gateway Configuration
FREEKASSA_ENABLED=True # Turn on FreeKassa
FREEKASSA_MERCHANT_ID=your_shop_id # Your shop ID in FreeKassa FREEKASSA_MERCHANT_ID=your_shop_id # Your shop ID in FreeKassa
FREEKASSA_API_KEY=your_api_key # API key for REST requests FREEKASSA_API_KEY=your_api_key # API key for REST requests
FREEKASSA_SECOND_SECRET=your_second_secret # Secret word #2 (used to verify notifications) FREEKASSA_SECOND_SECRET=your_second_secret # Secret word #2 (used to verify notifications)
@@ -50,12 +56,6 @@ TRIBUTE_API_KEY= #
TRIBUTE_SKIP_NOTIFICATIONS=True # Skip renewal notifications for Tribute payments TRIBUTE_SKIP_NOTIFICATIONS=True # Skip renewal notifications for Tribute payments
TRIBUTE_SKIP_CANCELLATION_NOTIFICATIONS=False # Skip cancellation notifications for Tribute payments TRIBUTE_SKIP_CANCELLATION_NOTIFICATIONS=False # Skip cancellation notifications for Tribute payments
# Payment Method Toggles
YOOKASSA_ENABLED=True # Turn on YOOKASSA
STARS_ENABLED=True # Turn on STARS
TRIBUTE_ENABLED=True # Turn on TRIBUTE
CRYPTOPAY_ENABLED=True # Turn on CRYPTOPAY
# Subscription Options. Specify cost parameters or payment links here. # Subscription Options. Specify cost parameters or payment links here.
1_MONTH_ENABLED=True 1_MONTH_ENABLED=True
RUB_PRICE_1_MONTH=150 RUB_PRICE_1_MONTH=150
+1 -1
View File
@@ -280,7 +280,7 @@ async def process_successful_payment(session: AsyncSession, bot: Bot,
details_message = _("payment_successful_error_details") details_message = _("payment_successful_error_details")
details_markup = get_connect_and_main_keyboard( details_markup = get_connect_and_main_keyboard(
user_lang, i18n, settings, config_link user_lang, i18n, settings, config_link, preserve_message=True
) )
try: try:
await bot.send_message( await bot.send_message(
+7
View File
@@ -427,6 +427,13 @@ async def main_action_callback_handler(
subscription_service, subscription_service,
session, session,
is_edit=True) is_edit=True)
elif action == "back_to_main_keep":
await send_main_menu(callback,
settings,
i18n_data,
subscription_service,
session,
is_edit=False)
else: else:
i18n: Optional[JsonI18n] = i18n_data.get("i18n_instance") i18n: Optional[JsonI18n] = i18n_data.get("i18n_instance")
_ = lambda key, **kwargs: i18n.gettext( _ = lambda key, **kwargs: i18n.gettext(
+60 -8
View File
@@ -1,5 +1,7 @@
import logging import logging
from datetime import datetime
from aiogram import Router, F, types from aiogram import Router, F, types
from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup
from typing import Optional from typing import Optional
from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.ext.asyncio import AsyncSession
@@ -238,7 +240,13 @@ async def pay_yk_callback_handler(callback: types.CallbackQuery, settings: Setti
await callback.message.edit_text( await callback.message.edit_text(
get_text(key="payment_link_message", months=months), get_text(key="payment_link_message", months=months),
reply_markup=get_payment_url_keyboard(payment_response_yk["confirmation_url"], current_lang, i18n), reply_markup=get_payment_url_keyboard(
payment_response_yk["confirmation_url"],
current_lang,
i18n,
back_callback=f"subscribe_period:{months}",
back_text_key="back_to_payment_methods_button",
),
disable_web_page_preview=False, disable_web_page_preview=False,
) )
else: else:
@@ -354,7 +362,9 @@ async def pay_fk_callback_handler(
if success: if success:
location = response_data.get("location") location = response_data.get("location")
provider_identifier = response_data.get("orderHash") or response_data.get("orderId") order_hash = response_data.get("orderHash")
order_id_api = response_data.get("orderId")
provider_identifier = order_hash or order_id_api
if provider_identifier: if provider_identifier:
try: try:
@@ -373,18 +383,36 @@ async def pay_fk_callback_handler(
) )
if location: if location:
order_identifier_display = str(order_id_api or provider_identifier or payment_record.payment_id)
order_info_text = get_text(
"free_kassa_order_info",
order_id=order_identifier_display,
date=datetime.now().strftime("%Y-%m-%d"),
)
try: try:
await callback.message.edit_text( await callback.message.edit_text(
get_text(key="payment_link_message", months=months), f"{order_info_text}\n\n" + get_text(key="payment_link_message", months=months),
reply_markup=get_payment_url_keyboard(location, current_lang, i18n), reply_markup=get_payment_url_keyboard(
location,
current_lang,
i18n,
back_callback=f"subscribe_period:{months}",
back_text_key="back_to_payment_methods_button",
),
disable_web_page_preview=False, disable_web_page_preview=False,
) )
except Exception as e_edit: except Exception as e_edit:
logging.warning(f"FreeKassa: failed to display payment link ({e_edit}), sending new message.") logging.warning(f"FreeKassa: failed to display payment link ({e_edit}), sending new message.")
try: try:
await callback.message.answer( await callback.message.answer(
get_text(key="payment_link_message", months=months), f"{order_info_text}\n\n" + get_text(key="payment_link_message", months=months),
reply_markup=get_payment_url_keyboard(location, current_lang, i18n), reply_markup=get_payment_url_keyboard(
location,
current_lang,
i18n,
back_callback=f"subscribe_period:{months}",
back_text_key="back_to_payment_methods_button",
),
disable_web_page_preview=False, disable_web_page_preview=False,
) )
except Exception: except Exception:
@@ -481,14 +509,26 @@ async def pay_crypto_callback_handler(
try: try:
await callback.message.edit_text( await callback.message.edit_text(
get_text(key="payment_link_message", months=months), get_text(key="payment_link_message", months=months),
reply_markup=get_payment_url_keyboard(invoice_url, current_lang, i18n), reply_markup=get_payment_url_keyboard(
invoice_url,
current_lang,
i18n,
back_callback=f"subscribe_period:{months}",
back_text_key="back_to_payment_methods_button",
),
disable_web_page_preview=False, disable_web_page_preview=False,
) )
except Exception: except Exception:
try: try:
await callback.message.answer( await callback.message.answer(
get_text(key="payment_link_message", months=months), get_text(key="payment_link_message", months=months),
reply_markup=get_payment_url_keyboard(invoice_url, current_lang, i18n), reply_markup=get_payment_url_keyboard(
invoice_url,
current_lang,
i18n,
back_callback=f"subscribe_period:{months}",
back_text_key="back_to_payment_methods_button",
),
disable_web_page_preview=False, disable_web_page_preview=False,
) )
except Exception: except Exception:
@@ -555,6 +595,18 @@ async def pay_stars_callback_handler(
) )
if payment_db_id: if payment_db_id:
try:
await callback.message.edit_text(
get_text("payment_invoice_sent_message", months=months),
reply_markup=InlineKeyboardMarkup(inline_keyboard=[
[InlineKeyboardButton(
text=get_text("back_to_payment_methods_button"),
callback_data=f"subscribe_period:{months}",
)]
]),
)
except Exception as e_edit:
logging.warning(f"Stars payment: failed to show invoice info message ({e_edit})")
try: try:
await callback.answer() await callback.answer()
except Exception: except Exception:
+15 -6
View File
@@ -138,13 +138,20 @@ def get_payment_method_keyboard(months: int, price: float,
return builder.as_markup() return builder.as_markup()
def get_payment_url_keyboard(payment_url: str, lang: str, def get_payment_url_keyboard(payment_url: str,
i18n_instance) -> InlineKeyboardMarkup: lang: str,
i18n_instance,
back_callback: Optional[str] = None,
back_text_key: str = "back_to_main_menu_button"
) -> InlineKeyboardMarkup:
_ = lambda key, **kwargs: i18n_instance.gettext(lang, key, **kwargs) _ = lambda key, **kwargs: i18n_instance.gettext(lang, key, **kwargs)
builder = InlineKeyboardBuilder() builder = InlineKeyboardBuilder()
builder.button(text=_(key="pay_button"), url=payment_url) builder.button(text=_(key="pay_button"), url=payment_url)
builder.button(text=_(key="back_to_main_menu_button"), if back_callback:
callback_data="main_action:back_to_main") builder.button(text=_(key=back_text_key), callback_data=back_callback)
else:
builder.button(text=_(key="back_to_main_menu_button"),
callback_data="main_action:back_to_main")
builder.adjust(1) builder.adjust(1)
return builder.as_markup() return builder.as_markup()
@@ -192,7 +199,8 @@ def get_connect_and_main_keyboard(
lang: str, lang: str,
i18n_instance, i18n_instance,
settings: Settings, settings: Settings,
config_link: Optional[str]) -> InlineKeyboardMarkup: config_link: Optional[str],
preserve_message: bool = False) -> InlineKeyboardMarkup:
"""Keyboard with a connect button and a back to main menu button.""" """Keyboard with a connect button and a back to main menu button."""
_ = lambda key, **kwargs: i18n_instance.gettext(lang, key, **kwargs) _ = lambda key, **kwargs: i18n_instance.gettext(lang, key, **kwargs)
builder = InlineKeyboardBuilder() builder = InlineKeyboardBuilder()
@@ -216,10 +224,11 @@ def get_connect_and_main_keyboard(
) )
) )
back_callback = "main_action:back_to_main_keep" if preserve_message else "main_action:back_to_main"
builder.row( builder.row(
InlineKeyboardButton( InlineKeyboardButton(
text=_("back_to_main_menu_button"), text=_("back_to_main_menu_button"),
callback_data="main_action:back_to_main", callback_data=back_callback,
) )
) )
+3 -1
View File
@@ -209,7 +209,9 @@ class CryptoPayService:
end_date=final_end.strftime('%Y-%m-%d'), end_date=final_end.strftime('%Y-%m-%d'),
config_link=config_link) config_link=config_link)
markup = get_connect_and_main_keyboard(lang, i18n, settings, config_link) markup = get_connect_and_main_keyboard(
lang, i18n, settings, config_link, preserve_message=True
)
try: try:
await bot.send_message( await bot.send_message(
user_id, user_id,
+15 -1
View File
@@ -1,4 +1,5 @@
import asyncio import asyncio
from datetime import datetime
import hashlib import hashlib
import hmac import hmac
import json import json
@@ -358,8 +359,21 @@ class FreeKassaService:
end_date=end_date_str, end_date=end_date_str,
config_link=config_link, config_link=config_link,
) )
if provider_payment_id:
order_info_text = _(
"free_kassa_order_full",
order_id=provider_payment_id,
date=datetime.now().strftime("%Y-%m-%d"),
)
text = f"{order_info_text}\n{text}"
markup = get_connect_and_main_keyboard(lang, self.i18n, self.settings, config_link) markup = get_connect_and_main_keyboard(
lang,
self.i18n,
self.settings,
config_link,
preserve_message=True,
)
try: try:
await self.bot.send_message( await self.bot.send_message(
payment.user_id, payment.user_id,
+1 -1
View File
@@ -148,7 +148,7 @@ class StarsService:
config_link=config_link, config_link=config_link,
) )
markup = get_connect_and_main_keyboard( markup = get_connect_and_main_keyboard(
current_lang, i18n, self.settings, config_link current_lang, i18n, self.settings, config_link, preserve_message=True
) )
try: try:
await self.bot.send_message( await self.bot.send_message(
+5 -1
View File
@@ -208,7 +208,11 @@ class TributeService:
config_link=config_link, config_link=config_link,
) )
markup = get_connect_and_main_keyboard( markup = get_connect_and_main_keyboard(
lang, i18n, settings, config_link lang,
i18n,
settings,
config_link,
preserve_message=True,
) )
try: try:
+6 -11
View File
@@ -1,7 +1,6 @@
{ {
"welcome": "Welcome, {user_name}!", "welcome": "Welcome, {user_name}!",
"main_menu_greeting": "Hi, {user_name}! 👋\nWhat would you like to do?", "main_menu_greeting": "Hi, {user_name}! 👋\nWhat would you like to do?",
"menu_activate_trial_button": "🆓 Free Trial", "menu_activate_trial_button": "🆓 Free Trial",
"menu_subscribe_inline": "🚀 Purchase", "menu_subscribe_inline": "🚀 Purchase",
"menu_my_subscription_inline": "🔐 My Subscription", "menu_my_subscription_inline": "🔐 My Subscription",
@@ -13,24 +12,20 @@
"menu_server_status_button": "📊 Status", "menu_server_status_button": "📊 Status",
"menu_support_button": "💬 Support", "menu_support_button": "💬 Support",
"menu_terms_button": "📄 Terms of Service", "menu_terms_button": "📄 Terms of Service",
"back_to_main_menu_button": "⬅️ Back", "back_to_main_menu_button": "⬅️ Back",
"choose_language": "Choose language:", "choose_language": "Choose language:",
"language_set_alert": "Language changed!", "language_set_alert": "Language changed!",
"error_occurred_try_again": "An error occurred, please try again.", "error_occurred_try_again": "An error occurred, please try again.",
"error_try_again": "Please try again.", "error_try_again": "Please try again.",
"error_displaying_menu": "Error displaying menu.", "error_displaying_menu": "Error displaying menu.",
"main_menu_unknown_action": "Unknown action.", "main_menu_unknown_action": "Unknown action.",
"select_subscription_period": "Select subscription period:", "select_subscription_period": "Select subscription period:",
"subscribe_for_months_button": "{months} mo. - {price} {currency_symbol}", "subscribe_for_months_button": "{months} mo. - {price} {currency_symbol}",
"choose_payment_method": "Choose payment method:", "choose_payment_method": "Choose payment method:",
"pay_button": "💳 Pay", "pay_button": "💳 Pay",
"pay_with_yookassa_button": "💳 YooKassa", "pay_with_yookassa_button": "💳 YooKassa",
"pay_with_sbp_button": "📱 SBP", "pay_with_sbp_button": "📱 SBP",
"back_to_payment_methods_button": "⬅️ Back to payment methods",
"pay_with_cryptopay_button": "💎 CryptoBot", "pay_with_cryptopay_button": "💎 CryptoBot",
"pay_with_tribute_button": "❤️ Tribute", "pay_with_tribute_button": "❤️ Tribute",
"pay_with_stars_button": "🌟 Telegram Stars", "pay_with_stars_button": "🌟 Telegram Stars",
@@ -38,13 +33,14 @@
"cancel_button": "❌ Cancel", "cancel_button": "❌ Cancel",
"payment_description_subscription": "Subscription payment for {months} mo.", "payment_description_subscription": "Subscription payment for {months} mo.",
"payment_link_message": "To pay for {months} mo. subscription, click the button below:", "payment_link_message": "To pay for {months} mo. subscription, click the button below:",
"free_kassa_order_info": "Order #{order_id} from {date}",
"payment_invoice_sent_message": "Telegram has sent the invoice above. Complete the payment or pick another method below.",
"payment_successful_error_details": "✅ Payment succeeded, but an error occurred displaying details. Your subscription is active. Contact support if anything is wrong.", "payment_successful_error_details": "✅ Payment succeeded, but an error occurred displaying details. Your subscription is active. Contact support if anything is wrong.",
"payment_successful_full": "✅ Payment successful!\nYour {months}-month subscription is active until {end_date}.\n\nConnection key:\n<code>{config_link}</code>\n\nTo connect, open the link and follow the instructions 👇", "payment_successful_full": "✅ Payment successful!\nYour {months}-month subscription is active until {end_date}.\n\nConnection key:\n<code>{config_link}</code>\n\nTo connect, open the link and follow the instructions 👇",
"payment_successful_with_referral_bonus_full": "✅ Payment successful!\nYour {months}-month subscription (base end date: {base_end_date}) has been extended by {bonus_days} bonus days for referral from {inviter_name} and is now active until {final_end_date}.\n\nConnection key:\n<code>{config_link}</code>\n\nTo connect, open the link and follow the instructions 👇", "payment_successful_with_referral_bonus_full": "✅ Payment successful!\nYour {months}-month subscription (base end date: {base_end_date}) has been extended by {bonus_days} bonus days for referral from {inviter_name} and is now active until {final_end_date}.\n\nConnection key:\n<code>{config_link}</code>\n\nTo connect, open the link and follow the instructions 👇",
"payment_failed": "❌ Payment failed or was cancelled. Please try again or contact support.", "payment_failed": "❌ Payment failed or was cancelled. Please try again or contact support.",
"config_link_not_available": "not available, contact support", "config_link_not_available": "not available, contact support",
"traffic_unlimited": "Unlimited", "traffic_unlimited": "Unlimited",
"promo_code_prompt": "Please enter your promo code:", "promo_code_prompt": "Please enter your promo code:",
"promo_code_not_found": "Promo code <code>{code}</code> not found, expired, or already used the maximum number of times.", "promo_code_not_found": "Promo code <code>{code}</code> not found, expired, or already used the maximum number of times.",
"promo_code_already_used_by_user": "You have already used promo code <code>{code}</code>.", "promo_code_already_used_by_user": "You have already used promo code <code>{code}</code>.",
@@ -66,7 +62,6 @@
"referral_bonus_inviter_notification_extended": "🎉 Congrats! Your friend {referee_name} paid for a subscription. You received {days} bonus days! Your subscription is now active until {new_end_date}.", "referral_bonus_inviter_notification_extended": "🎉 Congrats! Your friend {referee_name} paid for a subscription. You received {days} bonus days! Your subscription is now active until {new_end_date}.",
"referral_bonus_inviter_notification_new_sub": "🎉 Congrats! Your friend {referee_name} paid for a subscription. You received a {days}-day bonus subscription! It is active until {new_end_date}.", "referral_bonus_inviter_notification_new_sub": "🎉 Congrats! Your friend {referee_name} paid for a subscription. You received a {days}-day bonus subscription! It is active until {new_end_date}.",
"user_is_banned": "🚫 Your account is banned. Please contact support.", "user_is_banned": "🚫 Your account is banned. Please contact support.",
"admin_panel_title": "Admin Panel", "admin_panel_title": "Admin Panel",
"admin_stats_button": "📊 Statistics", "admin_stats_button": "📊 Statistics",
"admin_broadcast_button": "📢 Broadcast", "admin_broadcast_button": "📢 Broadcast",
@@ -323,7 +318,6 @@
"admin_user_subscription_active_until": "⏰ <b>Active until:</b>", "admin_user_subscription_active_until": "⏰ <b>Active until:</b>",
"admin_user_subscription_error": "Loading error", "admin_user_subscription_error": "Loading error",
"admin_promo_management_button": "🎟 Promo Management", "admin_promo_management_button": "🎟 Promo Management",
"admin_promo_management_title": "🎟 <b>Promo Code Management</b>\n\nSelect a promo code for detailed view:", "admin_promo_management_title": "🎟 <b>Promo Code Management</b>\n\nSelect a promo code for detailed view:",
"admin_promo_management_empty": "📭 No promo codes available", "admin_promo_management_empty": "📭 No promo codes available",
"admin_promo_card_title": "🎟 <b>Promo Code: {code}</b>", "admin_promo_card_title": "🎟 <b>Promo Code: {code}</b>",
@@ -436,5 +430,6 @@
"admin_ads_delete_button": "🗑 Delete campaign", "admin_ads_delete_button": "🗑 Delete campaign",
"admin_ads_delete_confirm": "Are you sure you want to delete campaign #{id}? This action is irreversible.", "admin_ads_delete_confirm": "Are you sure you want to delete campaign #{id}? This action is irreversible.",
"admin_ads_deleted_success": "Campaign deleted.", "admin_ads_deleted_success": "Campaign deleted.",
"admin_ads_not_found": "Campaign not found." "admin_ads_not_found": "Campaign not found.",
} "free_kassa_order_full": "Order #{order_id} from {date}\n\n"
}
+6 -11
View File
@@ -1,7 +1,6 @@
{ {
"welcome": "Добро пожаловать, {user_name}!", "welcome": "Добро пожаловать, {user_name}!",
"main_menu_greeting": "Привет, {user_name}! 👋\nЧто бы вы хотели сделать?", "main_menu_greeting": "Привет, {user_name}! 👋\nЧто бы вы хотели сделать?",
"menu_activate_trial_button": "🆓 Пробный период", "menu_activate_trial_button": "🆓 Пробный период",
"menu_subscribe_inline": "🚀 Купить", "menu_subscribe_inline": "🚀 Купить",
"menu_my_subscription_inline": "🔐 Моя подписка", "menu_my_subscription_inline": "🔐 Моя подписка",
@@ -13,24 +12,20 @@
"menu_server_status_button": "📊 Статус", "menu_server_status_button": "📊 Статус",
"menu_support_button": "💬 Поддержка", "menu_support_button": "💬 Поддержка",
"menu_terms_button": "📄 Условия сервиса", "menu_terms_button": "📄 Условия сервиса",
"back_to_main_menu_button": "⬅️ Назад", "back_to_main_menu_button": "⬅️ Назад",
"choose_language": "Выберите язык / Select language:", "choose_language": "Выберите язык / Select language:",
"language_set_alert": "Язык изменен!", "language_set_alert": "Язык изменен!",
"error_occurred_try_again": "Произошла ошибка, попробуйте снова.", "error_occurred_try_again": "Произошла ошибка, попробуйте снова.",
"error_try_again": "Попробуйте еще раз.", "error_try_again": "Попробуйте еще раз.",
"error_displaying_menu": "Ошибка отображения меню.", "error_displaying_menu": "Ошибка отображения меню.",
"main_menu_unknown_action": "Неизвестное действие.", "main_menu_unknown_action": "Неизвестное действие.",
"select_subscription_period": "Выберите срок подписки:", "select_subscription_period": "Выберите срок подписки:",
"subscribe_for_months_button": "{months} мес. - {price} {currency_symbol}", "subscribe_for_months_button": "{months} мес. - {price} {currency_symbol}",
"choose_payment_method": "Выберите способ оплаты:", "choose_payment_method": "Выберите способ оплаты:",
"pay_button": "💳 Оплатить", "pay_button": "💳 Оплатить",
"pay_with_yookassa_button": "💳 ЮKassa", "pay_with_yookassa_button": "💳 ЮKassa",
"pay_with_sbp_button": "📱 СБП", "pay_with_sbp_button": "📱 СБП",
"back_to_payment_methods_button": "⬅️ Назад к выбору оплаты",
"pay_with_cryptopay_button": "💎 CryptoBot", "pay_with_cryptopay_button": "💎 CryptoBot",
"pay_with_tribute_button": "❤️ Tribute", "pay_with_tribute_button": "❤️ Tribute",
"pay_with_stars_button": "🌟 Звезды Telegram", "pay_with_stars_button": "🌟 Звезды Telegram",
@@ -38,13 +33,14 @@
"cancel_button": "❌ Отмена", "cancel_button": "❌ Отмена",
"payment_description_subscription": "Оплата подписки на {months} мес.", "payment_description_subscription": "Оплата подписки на {months} мес.",
"payment_link_message": "Для оплаты подписки на {months} мес., нажмите кнопку ниже:", "payment_link_message": "Для оплаты подписки на {months} мес., нажмите кнопку ниже:",
"free_kassa_order_info": "Заказ №{order_id} от {date}",
"payment_invoice_sent_message": "Счёт Telegram Stars отправлен выше. Нажмите «Оплатить» или вернитесь к выбору способа ниже.",
"payment_successful_error_details": "✅ Оплата прошла успешно, но возникла ошибка при отображении деталей. Ваша подписка активна. Свяжитесь с поддержкой, если что-то не так.", "payment_successful_error_details": "✅ Оплата прошла успешно, но возникла ошибка при отображении деталей. Ваша подписка активна. Свяжитесь с поддержкой, если что-то не так.",
"payment_successful_full": "✅ Оплата прошла успешно!\nВаша подписка на {months} мес. активна до {end_date}.\n\nКлюч подключения:\n<code>{config_link}</code>\n\nЧтобы подключиться, перейдите по ссылке и следуйте инструкции 👇", "payment_successful_full": "✅ Оплата прошла успешно!\nВаша подписка на {months} мес. активна до {end_date}.\n\nКлюч подключения:\n<code>{config_link}</code>\n\nЧтобы подключиться, перейдите по ссылке и следуйте инструкции 👇",
"payment_successful_with_referral_bonus_full": "✅ Оплата прошла успешно!\nВаша подписка на {months} мес. (базовая дата окончания: {base_end_date}) продлена на {bonus_days} бонусных дней за приглашение от {inviter_name} и теперь активна до {final_end_date}.\n\nКлюч подключения:\n<code>{config_link}</code>\n\nЧтобы подключиться, перейдите по ссылке и следуйте инструкции 👇", "payment_successful_with_referral_bonus_full": "✅ Оплата прошла успешно!\nВаша подписка на {months} мес. (базовая дата окончания: {base_end_date}) продлена на {bonus_days} бонусных дней за приглашение от {inviter_name} и теперь активна до {final_end_date}.\n\nКлюч подключения:\n<code>{config_link}</code>\n\nЧтобы подключиться, перейдите по ссылке и следуйте инструкции 👇",
"payment_failed": "❌ Оплата не удалась или была отменена. Пожалуйста, попробуйте еще раз или свяжитесь с поддержкой.", "payment_failed": "❌ Оплата не удалась или была отменена. Пожалуйста, попробуйте еще раз или свяжитесь с поддержкой.",
"config_link_not_available": "недоступна, обратитесь в поддержку", "config_link_not_available": "недоступна, обратитесь в поддержку",
"traffic_unlimited": "Безлимитный", "traffic_unlimited": "Безлимитный",
"promo_code_prompt": "Пожалуйста, введите ваш промокод:", "promo_code_prompt": "Пожалуйста, введите ваш промокод:",
"promo_code_not_found": "Промокод <code>{code}</code> не найден, истек или уже использован максимальное количество раз.", "promo_code_not_found": "Промокод <code>{code}</code> не найден, истек или уже использован максимальное количество раз.",
"promo_code_already_used_by_user": "Вы уже активировали промокод <code>{code}</code>.", "promo_code_already_used_by_user": "Вы уже активировали промокод <code>{code}</code>.",
@@ -66,7 +62,6 @@
"referral_bonus_inviter_notification_extended": "🎉 Поздравляем! Ваш друг {referee_name} оплатил подписку. Вам начислено {days} бонусных дней! Ваша подписка теперь активна до {new_end_date}.", "referral_bonus_inviter_notification_extended": "🎉 Поздравляем! Ваш друг {referee_name} оплатил подписку. Вам начислено {days} бонусных дней! Ваша подписка теперь активна до {new_end_date}.",
"referral_bonus_inviter_notification_new_sub": "🎉 Поздравляем! Ваш друг {referee_name} оплатил подписку. Вам начислена бонусная подписка на {days} дней! Она активна до {new_end_date}.", "referral_bonus_inviter_notification_new_sub": "🎉 Поздравляем! Ваш друг {referee_name} оплатил подписку. Вам начислена бонусная подписка на {days} дней! Она активна до {new_end_date}.",
"user_is_banned": "🚫 Ваш аккаунт заблокирован. Пожалуйста, свяжитесь со службой поддержки.", "user_is_banned": "🚫 Ваш аккаунт заблокирован. Пожалуйста, свяжитесь со службой поддержки.",
"admin_panel_title": "Панель администратора", "admin_panel_title": "Панель администратора",
"admin_stats_button": "📊 Статистика", "admin_stats_button": "📊 Статистика",
"admin_broadcast_button": "📢 Рассылка", "admin_broadcast_button": "📢 Рассылка",
@@ -322,7 +317,6 @@
"admin_user_subscription_active_until": "⏰ <b>Действует до:</b>", "admin_user_subscription_active_until": "⏰ <b>Действует до:</b>",
"admin_user_subscription_error": "Ошибка загрузки", "admin_user_subscription_error": "Ошибка загрузки",
"admin_promo_management_button": "🎟 Управление промокодами", "admin_promo_management_button": "🎟 Управление промокодами",
"admin_promo_management_title": "🎟 <b>Управление промокодами</b>\n\nВыберите промокод для детального просмотра:", "admin_promo_management_title": "🎟 <b>Управление промокодами</b>\n\nВыберите промокод для детального просмотра:",
"admin_promo_management_empty": "📭 Промокоды отсутствуют", "admin_promo_management_empty": "📭 Промокоды отсутствуют",
"admin_promo_card_title": "🎟 <b>Промокод: {code}</b>", "admin_promo_card_title": "🎟 <b>Промокод: {code}</b>",
@@ -435,5 +429,6 @@
"admin_ads_delete_button": "🗑 Удалить кампанию", "admin_ads_delete_button": "🗑 Удалить кампанию",
"admin_ads_delete_confirm": "Вы уверены, что хотите удалить кампанию #{id}? Это действие необратимо.", "admin_ads_delete_confirm": "Вы уверены, что хотите удалить кампанию #{id}? Это действие необратимо.",
"admin_ads_deleted_success": "Кампания удалена.", "admin_ads_deleted_success": "Кампания удалена.",
"admin_ads_not_found": "Кампания не найдена." "admin_ads_not_found": "Кампания не найдена.",
} "free_kassa_order_full": "Заказ №{order_id} от {date}\n\n"
}
Binary file not shown.