feat: enable payment provider for admin only

This commit is contained in:
3252a8
2026-05-25 11:19:54 +03:00
parent d30b069876
commit de1763cfe1
24 changed files with 509 additions and 39 deletions
@@ -261,6 +261,19 @@ SETTINGS_MANIFEST: List[SettingField] = [
# ─── Payment providers (toggles) ───────────────────────────────
# Common
SettingField("STARS_ENABLED", "bool", "payments", "Telegram Stars", subsection="common"),
SettingField(
"STARS_ADMIN_ONLY_ENABLED",
"bool",
"payments",
"Telegram Stars admin-only",
(
"Shows Telegram Stars only to users from ADMIN_IDS. "
"Payment callbacks remain active for admin test payments."
),
subsection="common",
i18n_label_key="admin_settings_provider_admin_only_label",
i18n_description_key="admin_settings_provider_admin_only_description",
),
SettingField(
"PAYMENT_METHODS_ORDER",
"string",
@@ -603,6 +616,7 @@ def manifest_payload() -> List[dict]:
from bot.payment_providers import (
find_manifest_owner,
manifest_field_default,
provider_admin_only_pairs,
provider_webhook_metadata,
)
@@ -618,6 +632,11 @@ def manifest_payload() -> List[dict]:
"devices": 9,
"subscription_guides": 10,
}
exclusive_map = {
key: opposite
for public_key, admin_key in provider_admin_only_pairs()
for key, opposite in ((public_key, admin_key), (admin_key, public_key))
}
items: List[dict] = []
for field in aggregated_manifest():
auto_label_i18n_key = f"admin_settings_field_{field.key.lower()}_label"
@@ -659,6 +678,8 @@ def manifest_payload() -> List[dict]:
"optional": field.optional,
"secret": field.secret,
}
if field.key in exclusive_map:
item["mutually_exclusive_key"] = exclusive_map[field.key]
if default_value is not None:
item["default"] = default_value
if webhook_metadata:
+6 -2
View File
@@ -253,6 +253,8 @@ async def create_payment_route(request: web.Request) -> web.Response:
if not db_user or db_user.is_banned:
return _json_error(403, "access_denied", "Access denied")
lang = db_user.language_code or settings.DEFAULT_LANGUAGE
admin_ids = {int(item) for item in (settings.ADMIN_IDS or [])}
is_admin = bool(db_user.telegram_id and int(db_user.telegram_id) in admin_ids)
return await _create_subscription_payment(
request=request,
session=session,
@@ -264,6 +266,7 @@ async def create_payment_route(request: web.Request) -> web.Response:
lang=lang,
sale_mode=sale_mode,
traffic_gb=traffic_gb_for_payment,
is_admin=is_admin,
)
@@ -796,6 +799,7 @@ async def _create_subscription_payment(
lang: str,
sale_mode: str = "subscription",
traffic_gb: Optional[float] = None,
is_admin: bool = False,
) -> web.Response:
settings: Settings = request.app["settings"]
sale_mode = str(sale_mode or "subscription")
@@ -813,11 +817,11 @@ async def _create_subscription_payment(
provider_spec = get_provider_spec(method)
if provider_spec and provider_spec.create_webapp_payment:
if not provider_spec.is_visible(settings, request.app):
if not provider_spec.is_visible_for_user(settings, request.app, is_admin=is_admin):
logger.warning(
"WebApp payment method unavailable: method=%s enabled=%s configured=%s",
method,
provider_spec.is_enabled(settings),
provider_spec.is_effectively_enabled(settings),
provider_spec.is_service_configured(request.app),
)
return _json_error(400, "payment_unavailable", "Payment method unavailable")
+9 -2
View File
@@ -118,7 +118,12 @@ async def _build_user_payload(request: web.Request, user_id: int) -> Dict[str, A
traffic_packages=cached["traffic_packages"],
stars_traffic_packages=cached["stars_traffic_packages"],
),
"payment_methods": _serialize_payment_methods(settings, request.app, lang),
"payment_methods": _serialize_payment_methods(
settings,
request.app,
lang,
is_admin=is_admin,
),
"themes_catalog": public_themes_catalog_payload(
settings.webapp_themes_catalog,
settings.WEBAPP_PRIMARY_COLOR or "#00fe7a",
@@ -645,6 +650,8 @@ def _serialize_payment_methods(
settings: Settings,
app: web.Application,
lang: str = "ru",
*,
is_admin: bool = False,
) -> List[Dict[str, Any]]:
from bot.payment_providers import get_provider_spec, resolve_provider_presentation
@@ -652,7 +659,7 @@ def _serialize_payment_methods(
for method in settings.payment_methods_order:
method = method.lower()
spec = get_provider_spec(method)
if spec and spec.is_visible(settings, app):
if spec and spec.is_visible_for_user(settings, app, is_admin=is_admin):
presentation = resolve_provider_presentation(spec, settings, language=lang)
methods.append(
{