Revert "Show maintenance notice in miniapp"

This commit is contained in:
Egor
2025-11-25 03:45:46 +03:00
committed by GitHub
parent b117df126a
commit 5c7ec8c4a2
4 changed files with 42 additions and 445 deletions

View File

@@ -128,7 +128,6 @@ class PlategaPaymentMixin:
"status": status,
"expires_at": expires_at,
"correlation_id": correlation_id,
"payload": payload_token,
}
async def process_platega_webhook(

View File

@@ -64,7 +64,6 @@ from app.services.remnawave_service import (
from app.services.payment_service import PaymentService, get_wata_payment_by_link_id
from app.services.promo_offer_service import promo_offer_service
from app.services.promocode_service import PromoCodeService
from app.services.maintenance_service import maintenance_service
from app.services.subscription_service import SubscriptionService
from app.services.subscription_renewal_service import (
SubscriptionRenewalChargeError,
@@ -116,7 +115,6 @@ from ..schemas.miniapp import (
MiniAppDevice,
MiniAppDeviceRemovalRequest,
MiniAppDeviceRemovalResponse,
MiniAppMaintenanceStatusResponse,
MiniAppFaq,
MiniAppFaqItem,
MiniAppLegalDocuments,
@@ -127,7 +125,6 @@ from ..schemas.miniapp import (
MiniAppPaymentMethod,
MiniAppPaymentMethodsRequest,
MiniAppPaymentMethodsResponse,
MiniAppPaymentOption,
MiniAppPaymentStatusQuery,
MiniAppPaymentStatusRequest,
MiniAppPaymentStatusResponse,
@@ -628,23 +625,6 @@ def _build_mulenpay_iframe_config() -> Optional[MiniAppPaymentIframeConfig]:
return None
@router.post(
"/maintenance/status",
response_model=MiniAppMaintenanceStatusResponse,
)
async def get_maintenance_status(
payload: MiniAppSubscriptionRequest,
db: AsyncSession = Depends(get_db_session),
) -> MiniAppMaintenanceStatusResponse:
_, _ = await _resolve_user_from_init_data(db, payload.init_data)
status_info = maintenance_service.get_status_info()
return MiniAppMaintenanceStatusResponse(
is_active=bool(status_info.get("is_active")),
message=maintenance_service.get_maintenance_message(),
reason=status_info.get("reason"),
)
@router.post(
"/payments/methods",
response_model=MiniAppPaymentMethodsResponse,
@@ -728,24 +708,6 @@ async def get_payment_methods(
min_amount_kopeks=settings.PAL24_MIN_AMOUNT_KOPEKS,
max_amount_kopeks=settings.PAL24_MAX_AMOUNT_KOPEKS,
integration_type=MiniAppPaymentIntegrationType.REDIRECT,
options=[
MiniAppPaymentOption(
id="sbp",
icon="🏦",
title_key="topup.method.pal24.option.sbp.title",
description_key="topup.method.pal24.option.sbp.description",
title="Faster Payments (SBP)",
description="Instant SBP transfer with no fees.",
),
MiniAppPaymentOption(
id="card",
icon="💳",
title_key="topup.method.pal24.option.card.title",
description_key="topup.method.pal24.option.card.description",
title="Bank card",
description="Pay with a bank card via PayPalych.",
),
],
)
)
@@ -762,37 +724,6 @@ async def get_payment_methods(
)
)
if settings.is_platega_enabled() and settings.get_platega_active_methods():
platega_methods = settings.get_platega_active_methods()
definitions = settings.get_platega_method_definitions()
options: List[MiniAppPaymentOption] = []
for method_code in platega_methods:
info = definitions.get(method_code, {})
options.append(
MiniAppPaymentOption(
id=str(method_code),
icon=info.get("icon") or ("🏦" if method_code == 2 else "💳"),
title_key=f"topup.method.platega.option.{method_code}.title",
description_key=f"topup.method.platega.option.{method_code}.description",
title=info.get("title") or info.get("name") or f"Platega {method_code}",
description=info.get("description") or info.get("name"),
)
)
methods.append(
MiniAppPaymentMethod(
id="platega",
icon="💳",
requires_amount=True,
currency=settings.PLATEGA_CURRENCY,
min_amount_kopeks=settings.PLATEGA_MIN_AMOUNT_KOPEKS,
max_amount_kopeks=settings.PLATEGA_MAX_AMOUNT_KOPEKS,
integration_type=MiniAppPaymentIntegrationType.REDIRECT,
options=options,
)
)
if settings.is_cryptobot_enabled():
rate = await _get_usd_to_rub_rate()
min_amount_kopeks, max_amount_kopeks = _compute_cryptobot_limits(rate)
@@ -838,11 +769,10 @@ async def get_payment_methods(
"yookassa": 3,
"mulenpay": 4,
"pal24": 5,
"platega": 6,
"wata": 7,
"cryptobot": 8,
"heleket": 9,
"tribute": 10,
"wata": 6,
"cryptobot": 7,
"heleket": 8,
"tribute": 9,
}
methods.sort(key=lambda item: order_map.get(item.id, 99))
@@ -1019,54 +949,6 @@ async def create_payment_link(
},
)
if method == "platega":
if not settings.is_platega_enabled() or not settings.get_platega_active_methods():
raise HTTPException(status.HTTP_400_BAD_REQUEST, detail="Payment method is unavailable")
if amount_kopeks is None or amount_kopeks <= 0:
raise HTTPException(status.HTTP_400_BAD_REQUEST, detail="Amount must be positive")
if amount_kopeks < settings.PLATEGA_MIN_AMOUNT_KOPEKS:
raise HTTPException(status.HTTP_400_BAD_REQUEST, detail="Amount is below minimum")
if amount_kopeks > settings.PLATEGA_MAX_AMOUNT_KOPEKS:
raise HTTPException(status.HTTP_400_BAD_REQUEST, detail="Amount exceeds maximum")
active_methods = settings.get_platega_active_methods()
method_option = payload.payment_option or str(active_methods[0])
try:
method_code = int(str(method_option).strip())
except (TypeError, ValueError):
raise HTTPException(status.HTTP_400_BAD_REQUEST, detail="Invalid Platega payment option")
if method_code not in active_methods:
raise HTTPException(status.HTTP_400_BAD_REQUEST, detail="Selected Platega method is unavailable")
payment_service = PaymentService()
result = await payment_service.create_platega_payment(
db=db,
user_id=user.id,
amount_kopeks=amount_kopeks,
description=settings.get_balance_payment_description(amount_kopeks),
language=user.language or settings.DEFAULT_LANGUAGE,
payment_method_code=method_code,
)
redirect_url = result.get("redirect_url") if result else None
if not result or not redirect_url:
raise HTTPException(status.HTTP_502_BAD_GATEWAY, detail="Failed to create payment")
return MiniAppPaymentCreateResponse(
method=method,
payment_url=redirect_url,
amount_kopeks=amount_kopeks,
extra={
"local_payment_id": result.get("local_payment_id"),
"payment_id": result.get("transaction_id"),
"correlation_id": result.get("correlation_id"),
"selected_option": str(method_code),
"payload": result.get("payload"),
"requested_at": _current_request_timestamp(),
},
)
if method == "wata":
if not settings.is_wata_enabled():
raise HTTPException(status.HTTP_400_BAD_REQUEST, detail="Payment method is unavailable")
@@ -1361,8 +1243,6 @@ async def _resolve_payment_status_entry(
)
if method == "mulenpay":
return await _resolve_mulenpay_payment_status(payment_service, db, user, query)
if method == "platega":
return await _resolve_platega_payment_status(payment_service, db, user, query)
if method == "wata":
return await _resolve_wata_payment_status(payment_service, db, user, query)
if method == "pal24":
@@ -1515,85 +1395,6 @@ async def _resolve_mulenpay_payment_status(
)
async def _resolve_platega_payment_status(
payment_service: PaymentService,
db: AsyncSession,
user: User,
query: MiniAppPaymentStatusQuery,
) -> MiniAppPaymentStatusResult:
from app.database.crud.platega import (
get_platega_payment_by_correlation_id,
get_platega_payment_by_id,
get_platega_payment_by_transaction_id,
)
payment = None
local_id = query.local_payment_id
if local_id:
payment = await get_platega_payment_by_id(db, local_id)
if not payment and query.payment_id:
payment = await get_platega_payment_by_transaction_id(db, query.payment_id)
if not payment and query.payload:
correlation = str(query.payload).replace("platega:", "")
payment = await get_platega_payment_by_correlation_id(db, correlation)
if not payment or payment.user_id != user.id:
return MiniAppPaymentStatusResult(
method="platega",
status="pending",
is_paid=False,
amount_kopeks=query.amount_kopeks,
message="Payment not found",
extra={
"local_payment_id": query.local_payment_id,
"payment_id": query.payment_id,
"payload": query.payload,
"started_at": query.started_at,
},
)
status_info = await payment_service.get_platega_payment_status(db, payment.id)
refreshed_payment = (status_info or {}).get("payment") or payment
status_raw = (status_info or {}).get("status") or getattr(payment, "status", None)
is_paid_flag = bool((status_info or {}).get("is_paid") or getattr(payment, "is_paid", False))
status_value = _classify_status(status_raw, is_paid_flag)
completed_at = (
getattr(refreshed_payment, "paid_at", None)
or getattr(refreshed_payment, "updated_at", None)
or getattr(refreshed_payment, "created_at", None)
)
extra: Dict[str, Any] = {
"local_payment_id": refreshed_payment.id,
"payment_id": refreshed_payment.platega_transaction_id,
"correlation_id": refreshed_payment.correlation_id,
"status": status_raw,
"is_paid": getattr(refreshed_payment, "is_paid", False),
"payload": query.payload,
"started_at": query.started_at,
}
if status_info and status_info.get("remote"):
extra["remote"] = status_info.get("remote")
return MiniAppPaymentStatusResult(
method="platega",
status=status_value,
is_paid=status_value == "paid",
amount_kopeks=refreshed_payment.amount_kopeks,
currency=refreshed_payment.currency,
completed_at=completed_at,
transaction_id=refreshed_payment.transaction_id,
external_id=refreshed_payment.platega_transaction_id,
message=None,
extra=extra,
)
async def _resolve_wata_payment_status(
payment_service: PaymentService,
db: AsyncSession,

View File

@@ -17,12 +17,6 @@ class MiniAppSubscriptionRequest(BaseModel):
init_data: str = Field(..., alias="initData")
class MiniAppMaintenanceStatusResponse(BaseModel):
is_active: bool = Field(..., alias="isActive")
message: Optional[str] = None
reason: Optional[str] = None
class MiniAppSubscriptionUser(BaseModel):
telegram_id: int
username: Optional[str] = None
@@ -379,17 +373,6 @@ class MiniAppPaymentIntegrationType(str, Enum):
REDIRECT = "redirect"
class MiniAppPaymentOption(BaseModel):
id: str
icon: Optional[str] = None
title: Optional[str] = None
description: Optional[str] = None
title_key: Optional[str] = Field(default=None, alias="titleKey")
description_key: Optional[str] = Field(default=None, alias="descriptionKey")
model_config = ConfigDict(populate_by_name=True)
class MiniAppPaymentIframeConfig(BaseModel):
expected_origin: str
@@ -419,7 +402,6 @@ class MiniAppPaymentMethod(BaseModel):
max_amount_kopeks: Optional[int] = None
amount_step_kopeks: Optional[int] = None
integration_type: MiniAppPaymentIntegrationType
options: List[MiniAppPaymentOption] = Field(default_factory=list)
iframe_config: Optional[MiniAppPaymentIframeConfig] = None
@model_validator(mode="after")

View File

@@ -40,7 +40,6 @@
--success: #10b981;
--success-rgb: 16, 185, 129;
--warning: #f59e0b;
--warning-rgb: 245, 158, 11;
--danger: #ef4444;
--danger-rgb: 239, 68, 68;
--info: #3b82f6;
@@ -289,41 +288,6 @@
padding: 80px 20px;
}
.maintenance-banner {
display: flex;
gap: 12px;
align-items: flex-start;
padding: 14px 16px;
margin-bottom: 16px;
border-radius: var(--radius-lg);
border: 1px solid rgba(var(--warning-rgb), 0.18);
background: linear-gradient(135deg, rgba(var(--warning-rgb), 0.08), rgba(var(--warning-rgb), 0.02));
color: var(--text-primary);
box-shadow: var(--shadow-sm);
}
.maintenance-icon {
font-size: 22px;
line-height: 1;
}
.maintenance-content {
display: flex;
flex-direction: column;
gap: 4px;
}
.maintenance-title {
font-weight: 800;
font-size: 15px;
}
.maintenance-text {
font-size: 13px;
color: var(--text-secondary);
line-height: 1.4;
}
.spinner {
width: 48px;
height: 48px;
@@ -4802,16 +4766,6 @@
<div class="subtitle" data-i18n="app.subtitle">Secure & Fast Connection</div>
</div>
<div id="maintenanceBanner" class="maintenance-banner hidden" role="status" aria-live="polite">
<div class="maintenance-icon" aria-hidden="true">🔧</div>
<div class="maintenance-content">
<div class="maintenance-title" data-i18n="maintenance.title">Технические работы</div>
<div id="maintenanceMessage" class="maintenance-text" data-i18n="maintenance.message">
Сервис временно недоступен из-за технических работ. Попробуйте позже.
</div>
</div>
</div>
<!-- Loading State -->
<div id="loadingState" class="loading">
<div class="spinner"></div>
@@ -5632,8 +5586,6 @@
'values.not_available': 'Not available',
'app.subtitle': 'Secure & Fast Connection',
'app.loading': 'Loading your subscription...',
'maintenance.title': 'Technical maintenance',
'maintenance.message': 'The service is temporarily in maintenance mode. Some actions may be unavailable.',
'error.default.title': 'Subscription Not Found',
'error.default.message': 'Please contact support to activate your subscription.',
'error.user_not_found.title': 'Register in the bot',
@@ -5663,18 +5615,6 @@
'topup.method.yookassa.description': 'Pay securely with a bank card',
'topup.method.mulenpay.title': 'Bank card (Mulen Pay)',
'topup.method.mulenpay.description': 'Fast payment with bank card',
'topup.method.platega.title': 'Platega.io',
'topup.method.platega.description': 'Bank cards and SBP via Platega',
'topup.method.platega.option.2.title': 'SBP (QR)',
'topup.method.platega.option.2.description': 'Pay with Faster Payments QR code.',
'topup.method.platega.option.10.title': 'Bank cards (RUB)',
'topup.method.platega.option.10.description': 'Russian bank cards through Platega.',
'topup.method.platega.option.11.title': 'Bank cards',
'topup.method.platega.option.11.description': 'Local bank cards via Platega.',
'topup.method.platega.option.12.title': 'International cards',
'topup.method.platega.option.12.description': 'International cards supported by Platega.',
'topup.method.platega.option.13.title': 'Cryptocurrency',
'topup.method.platega.option.13.description': 'Top up balance with crypto via Platega.',
'topup.method.wata.title': 'Bank card (Wata)',
'topup.method.wata.description': 'Pay with a bank card via Wata',
'topup.method.pal24.title': 'SBP (PayPalych)',
@@ -6052,8 +5992,6 @@
'values.not_available': 'Закрыто',
'app.subtitle': 'Безопасное и быстрое подключение',
'app.loading': 'Загружаем вашу подписку...',
'maintenance.title': 'Технические работы',
'maintenance.message': 'Сервис находится в режиме технических работ. Некоторые действия могут быть недоступны.',
'error.default.title': 'Подписка не найдена',
'error.default.message': 'Свяжитесь с поддержкой, чтобы активировать подписку.',
'error.user_not_found.title': 'Зарегистрируйтесь в боте',
@@ -6083,18 +6021,6 @@
'topup.method.yookassa.description': 'Безопасная оплата банковской картой',
'topup.method.mulenpay.title': 'Банковская карта (Mulen Pay)',
'topup.method.mulenpay.description': 'Мгновенное списание с карты',
'topup.method.platega.title': 'Platega.io',
'topup.method.platega.description': 'Карта или СБП через Platega',
'topup.method.platega.option.2.title': 'СБП (QR)',
'topup.method.platega.option.2.description': 'Оплата по QR-коду через СБП.',
'topup.method.platega.option.10.title': 'Банковские карты (RUB)',
'topup.method.platega.option.10.description': 'Российские карты через Platega.',
'topup.method.platega.option.11.title': 'Банковские карты',
'topup.method.platega.option.11.description': 'Оплата картами через Platega.',
'topup.method.platega.option.12.title': 'Международные карты',
'topup.method.platega.option.12.description': 'Оплата международными картами.',
'topup.method.platega.option.13.title': 'Криптовалюта',
'topup.method.platega.option.13.description': 'Пополнение через криптовалюту в Platega.',
'topup.method.wata.title': 'Банковская карта (Wata)',
'topup.method.wata.description': 'Оплата банковской картой через Wata',
'topup.method.pal24.title': 'СБП (PayPalych)',
@@ -6738,7 +6664,6 @@
let paymentMethodsCache = null;
let paymentMethodsPromise = null;
let activePaymentMethod = null;
let maintenanceState = { isActive: false, message: null };
const paymentMethodSelections = {};
const activePaymentMonitors = new Map();
let paymentStatusPollTimer = null;
@@ -6916,18 +6841,13 @@
return;
}
const optionsMap = (Array.isArray(monitor.method.options) ? monitor.method.options : []).reduce((map, item) => {
map[String(item.id)] = item;
return map;
}, {});
if (monitor.method.id === 'pal24' || monitor.method.id === 'platega') {
const option = (monitor.option || monitor.extra?.selected_option || 'sbp').toString();
const optionKey = ['card', 'sbp'].includes(option) ? option : option;
const optionConfig = optionsMap[optionKey];
const fallback = optionConfig?.title || (optionKey === 'card' ? 'Bank card payment' : 'Faster Payments (SBP)');
const titleKey = optionConfig?.titleKey || optionConfig?.title_key || `topup.method.${monitor.method.id}.option.${optionKey}.title`;
setTopupModalSubtitle(titleKey, fallback || monitor.method.id);
if (monitor.method.id === 'pal24') {
const option = (monitor.option || 'sbp').toLowerCase();
const optionKey = option === 'card' ? 'card' : 'sbp';
const fallback = optionKey === 'card'
? 'Bank card payment'
: 'Faster Payments (SBP)';
setTopupModalSubtitle(`topup.method.pal24.option.${optionKey}.title`, fallback);
return;
}
@@ -6958,11 +6878,6 @@
identifiers.paymentId = extra.payment_id;
}
if (extra.correlation_id && !query.payload) {
query.payload = extra.correlation_id;
identifiers.payload = extra.correlation_id;
}
const payloadValue = extra.payload || extra.invoice_payload;
if (payloadValue) {
query.payload = payloadValue;
@@ -7547,41 +7462,6 @@
label.textContent = t(key);
}
function renderMaintenanceBanner() {
const banner = document.getElementById('maintenanceBanner');
const messageElement = document.getElementById('maintenanceMessage');
if (!banner || !messageElement) {
return;
}
if (!maintenanceState?.isActive) {
banner.classList.add('hidden');
return;
}
const resolvedMessage = (typeof maintenanceState.message === 'string'
? maintenanceState.message.trim()
: '')
|| t('maintenance.message');
const translatedFallback = t('maintenance.message');
const messageFallback = translatedFallback === 'maintenance.message'
? 'The service is temporarily unavailable due to maintenance. Please try again later.'
: translatedFallback;
messageElement.textContent = resolvedMessage === 'maintenance.message'
? messageFallback
: resolvedMessage;
banner.classList.remove('hidden');
}
function applyMaintenanceStatus(status) {
const isActive = Boolean(status?.isActive ?? status?.is_active);
const message = typeof status?.message === 'string' ? status.message : null;
maintenanceState = { isActive, message };
renderMaintenanceBanner();
}
function refreshAfterLanguageChange() {
applyTranslations();
if (userData) {
@@ -7591,7 +7471,6 @@
}
renderApps();
updateActionButtons();
renderMaintenanceBanner();
}
function setLanguage(language, options = {}) {
@@ -7790,22 +7669,6 @@
hasAnimatedCards = true;
}
async function fetchMaintenanceStatus(initData) {
const response = await fetch('/miniapp/maintenance/status', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ initData })
});
if (response.ok) {
return response.json();
}
throw new Error('Unable to fetch maintenance status');
}
async function fetchSubscriptionPayload(initData) {
const response = await fetch('/miniapp/subscription', {
method: 'POST',
@@ -8047,21 +7910,6 @@
return applySubscriptionData(payload);
}
async function checkMaintenance(initData) {
if (!initData) {
applyMaintenanceStatus({ isActive: false, message: null });
return;
}
try {
const status = await fetchMaintenanceStatus(initData);
applyMaintenanceStatus(status);
} catch (error) {
console.warn('Unable to load maintenance status:', error);
applyMaintenanceStatus({ isActive: false, message: null });
}
}
async function init() {
try {
const telegramUser = tg.initDataUnsafe?.user;
@@ -8075,8 +7923,6 @@
}
await loadAppsConfig();
const initData = tg.initData || '';
await checkMaintenance(initData);
await refreshSubscriptionData();
} catch (error) {
console.error('Initialization error:', error);
@@ -11657,44 +11503,32 @@
form.appendChild(hint);
}
const providedOptions = Array.isArray(method.options) ? method.options : [];
const fallbackOptions = method.id === 'pal24'
? [
if (method.id === 'pal24') {
const optionsConfig = [
{
id: 'sbp',
icon: '🏦',
titleKey: 'topup.method.pal24.option.sbp.title',
descriptionKey: 'topup.method.pal24.option.sbp.description',
title: 'Faster Payments (SBP)',
description: 'Instant SBP transfer with no fees.',
fallbackTitle: 'Faster Payments (SBP)',
fallbackDescription: 'Instant SBP transfer with no fees.',
},
{
id: 'card',
icon: '💳',
titleKey: 'topup.method.pal24.option.card.title',
descriptionKey: 'topup.method.pal24.option.card.description',
title: 'Bank card',
description: 'Pay with a bank card via PayPalych.',
fallbackTitle: 'Bank card',
fallbackDescription: 'Pay with a bank card via PayPalych.',
},
]
: [];
];
const optionsConfig = (providedOptions.length ? providedOptions : fallbackOptions).map(option => ({
id: String(option.id),
icon: option.icon || '💳',
titleKey: option.titleKey || option.title_key || option.titlekey,
descriptionKey: option.descriptionKey || option.description_key || option.descriptionkey,
fallbackTitle: option.title || option.name || String(option.id),
fallbackDescription: option.description || '',
}));
if (optionsConfig.length) {
const defaultSelection = options.selectedOption
const selectedDefault = options.selectedOption
|| paymentMethodSelections[method.id]
|| optionsConfig[0]?.id;
let currentOption = optionsConfig.some(option => option.id === defaultSelection)
? defaultSelection
: optionsConfig[0]?.id;
|| 'sbp';
let currentOption = optionsConfig.some(option => option.id === selectedDefault)
? selectedDefault
: 'sbp';
paymentMethodSelections[method.id] = currentOption;
form.dataset.paymentOption = currentOption;
@@ -11703,7 +11537,7 @@
const optionTitle = document.createElement('div');
optionTitle.className = 'payment-option-title';
const titleKey = `topup.method.${method.id}.title`;
const titleKey = 'topup.method.pal24.title';
const titleValue = t(titleKey);
optionTitle.textContent = titleValue === titleKey ? 'Choose payment type' : titleValue;
optionGroup.appendChild(optionTitle);
@@ -11729,23 +11563,22 @@
const label = document.createElement('div');
label.className = 'payment-option-label';
const labelValue = config.titleKey ? t(config.titleKey) : config.fallbackTitle;
label.textContent = labelValue && labelValue !== config.titleKey
? labelValue
: config.fallbackTitle;
const labelValue = t(config.titleKey);
label.textContent = labelValue === config.titleKey ? config.fallbackTitle : labelValue;
const description = document.createElement('div');
description.className = 'payment-option-description';
const descriptionValue = config.descriptionKey ? t(config.descriptionKey) : config.fallbackDescription;
const finalDescription = descriptionValue && descriptionValue !== config.descriptionKey
? descriptionValue
: config.fallbackDescription;
const descriptionValue = t(config.descriptionKey);
const finalDescription = descriptionValue === config.descriptionKey
? config.fallbackDescription
: descriptionValue;
description.textContent = finalDescription;
text.appendChild(label);
if (finalDescription) {
description.textContent = finalDescription;
text.appendChild(description);
}
text.appendChild(label);
button.appendChild(icon);
button.appendChild(text);
@@ -11983,19 +11816,8 @@
const normalizedAmount = Number.isFinite(amountKopeks) ? Number(amountKopeks) : null;
const monitorExtra = { ...extra };
const methodOptions = Array.isArray(method.options) ? method.options : [];
const optionsMap = methodOptions.reduce((map, item) => {
const key = String(item.id);
map[key] = item;
return map;
}, {});
let option = null;
if (methodOptions.length) {
option = (options.providerOption || monitorExtra.selected_option || paymentMethodSelections[method.id] || methodOptions[0]?.id || '').toString();
paymentMethodSelections[method.id] = option;
monitorExtra.selected_option = option;
} else if (method.id === 'pal24') {
if (method.id === 'pal24') {
option = (options.providerOption || monitorExtra.selected_option || paymentMethodSelections[method.id] || 'sbp').toLowerCase();
if (!['card', 'sbp'].includes(option)) {
option = 'sbp';
@@ -12004,19 +11826,12 @@
monitorExtra.selected_option = option;
}
const selectedOption = option && (optionsMap[option] || optionsMap[String(option)]);
const optionTitleKey = selectedOption?.titleKey || selectedOption?.title_key;
const optionTitleFallback = selectedOption?.title || selectedOption?.name || option || method.id;
const titleKey = selectedOption && optionTitleKey
? optionTitleKey
: option
? `topup.method.${method.id}.option.${option}.title`
: `topup.method.${method.id}.title`;
const titleFallback = selectedOption
? optionTitleFallback
: method.id === 'pal24'
? (option === 'card' ? 'Bank card payment' : 'Faster Payments (SBP)')
: method.id;
const titleKey = method.id === 'pal24' && option
? `topup.method.pal24.option.${option}.title`
: `topup.method.${method.id}.title`;
const titleFallback = method.id === 'pal24'
? (option === 'card' ? 'Bank card payment' : 'Faster Payments (SBP)')
: method.id;
setTopupModalSubtitle(titleKey, titleFallback);
body.innerHTML = '';
@@ -12087,8 +11902,8 @@
summary.appendChild(usdAmount);
}
const descriptionKey = option
? `topup.method.${method.id}.option.${option}.description`
const descriptionKey = method.id === 'pal24' && option
? `topup.method.pal24.option.${option}.description`
: `topup.method.${method.id}.description`;
const descriptionValue = t(descriptionKey);
if (descriptionValue && descriptionValue !== descriptionKey) {