feat: show optional serivce description before payment
This commit is contained in:
@@ -18,9 +18,9 @@ from .registry import (
|
||||
get_spec_presentation,
|
||||
iter_provider_manifest_fields,
|
||||
iter_provider_specs,
|
||||
manifest_field_default,
|
||||
iter_service_keys,
|
||||
iter_unique_provider_routers,
|
||||
manifest_field_default,
|
||||
pending_statuses,
|
||||
provider_emoji_map,
|
||||
provider_label_map,
|
||||
|
||||
@@ -2,7 +2,7 @@ from __future__ import annotations
|
||||
|
||||
import os
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Any, Awaitable, Callable, List, Mapping, Optional, Sequence, Type
|
||||
from typing import Any, Awaitable, Callable, Mapping, Optional, Sequence, Type
|
||||
|
||||
from pydantic_settings import BaseSettings, SettingsConfigDict
|
||||
|
||||
@@ -65,7 +65,9 @@ class ProviderManifestField:
|
||||
choices: Optional[Sequence[tuple[str, str]]] = None
|
||||
subsection: Optional[str] = None
|
||||
target: str = "config" # "config" or "presentation" — which bundle slot it writes to
|
||||
attr: Optional[str] = None # attribute name on the target model; defaults to key without env_prefix
|
||||
attr: Optional[str] = (
|
||||
None # attribute name on the target model; defaults to key without env_prefix
|
||||
)
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
|
||||
@@ -349,10 +349,7 @@ async def pay_crypto_callback_handler(
|
||||
await notify_callback_parse_error(callback, translator)
|
||||
return
|
||||
|
||||
if (
|
||||
not cryptopay_service
|
||||
or not getattr(cryptopay_service, "configured", False)
|
||||
):
|
||||
if not cryptopay_service or not getattr(cryptopay_service, "configured", False):
|
||||
await notify_service_unavailable(callback, translator)
|
||||
return
|
||||
|
||||
@@ -390,7 +387,11 @@ async def pay_crypto_callback_handler(
|
||||
|
||||
def create_service(ctx: ServiceFactoryContext) -> CryptoPayService:
|
||||
bundle = ctx.config_for("cryptopay_service")
|
||||
config = bundle.config if bundle and isinstance(bundle.config, CryptoPayConfig) else CryptoPayConfig()
|
||||
config = (
|
||||
bundle.config
|
||||
if bundle and isinstance(bundle.config, CryptoPayConfig)
|
||||
else CryptoPayConfig()
|
||||
)
|
||||
return CryptoPayService(
|
||||
bot=ctx.bot,
|
||||
settings=ctx.settings,
|
||||
@@ -422,40 +423,99 @@ async def create_webapp_payment(ctx: WebAppPaymentContext) -> web.Response:
|
||||
|
||||
_PRESENTATION_MANIFEST = tuple(
|
||||
ProviderManifestField(
|
||||
key=key, type=type_, label=label, description=description,
|
||||
placeholder=placeholder, subsection="CryptoPay",
|
||||
target="presentation", attr=attr,
|
||||
key=key,
|
||||
type=type_,
|
||||
label=label,
|
||||
description=description,
|
||||
placeholder=placeholder,
|
||||
subsection="CryptoPay",
|
||||
target="presentation",
|
||||
attr=attr,
|
||||
)
|
||||
for key, type_, label, description, placeholder, attr in (
|
||||
("PAYMENT_CRYPTOPAY_WEBAPP_LABEL_RU", "string", "WebApp button text (RU)",
|
||||
"Custom Russian text shown in the Web App payment method button.", "", "WEBAPP_LABEL_RU"),
|
||||
("PAYMENT_CRYPTOPAY_WEBAPP_LABEL_EN", "string", "WebApp button text (EN)",
|
||||
"Custom English text shown in the Web App payment method button.", "", "WEBAPP_LABEL_EN"),
|
||||
("PAYMENT_CRYPTOPAY_WEBAPP_ICON", "icon", "WebApp button icon",
|
||||
"Lucide icon name rendered inside the Web App payment method button.",
|
||||
"Bitcoin", "WEBAPP_ICON"),
|
||||
("PAYMENT_CRYPTOPAY_TELEGRAM_LABEL_RU", "string", "Telegram button text (RU)",
|
||||
"Custom Russian text shown in Telegram bot payment buttons.", "", "TELEGRAM_LABEL_RU"),
|
||||
("PAYMENT_CRYPTOPAY_TELEGRAM_LABEL_EN", "string", "Telegram button text (EN)",
|
||||
"Custom English text shown in Telegram bot payment buttons.", "", "TELEGRAM_LABEL_EN"),
|
||||
("PAYMENT_CRYPTOPAY_TELEGRAM_EMOJI", "string", "Telegram button emoji",
|
||||
"Emoji prepended to the Telegram bot payment button when customized.",
|
||||
"₿", "TELEGRAM_EMOJI"),
|
||||
(
|
||||
"PAYMENT_CRYPTOPAY_WEBAPP_LABEL_RU",
|
||||
"string",
|
||||
"WebApp button text (RU)",
|
||||
"Custom Russian text shown in the Web App payment method button.",
|
||||
"",
|
||||
"WEBAPP_LABEL_RU",
|
||||
),
|
||||
(
|
||||
"PAYMENT_CRYPTOPAY_WEBAPP_LABEL_EN",
|
||||
"string",
|
||||
"WebApp button text (EN)",
|
||||
"Custom English text shown in the Web App payment method button.",
|
||||
"",
|
||||
"WEBAPP_LABEL_EN",
|
||||
),
|
||||
(
|
||||
"PAYMENT_CRYPTOPAY_WEBAPP_ICON",
|
||||
"icon",
|
||||
"WebApp button icon",
|
||||
"Lucide icon name rendered inside the Web App payment method button.",
|
||||
"Bitcoin",
|
||||
"WEBAPP_ICON",
|
||||
),
|
||||
(
|
||||
"PAYMENT_CRYPTOPAY_TELEGRAM_LABEL_RU",
|
||||
"string",
|
||||
"Telegram button text (RU)",
|
||||
"Custom Russian text shown in Telegram bot payment buttons.",
|
||||
"",
|
||||
"TELEGRAM_LABEL_RU",
|
||||
),
|
||||
(
|
||||
"PAYMENT_CRYPTOPAY_TELEGRAM_LABEL_EN",
|
||||
"string",
|
||||
"Telegram button text (EN)",
|
||||
"Custom English text shown in Telegram bot payment buttons.",
|
||||
"",
|
||||
"TELEGRAM_LABEL_EN",
|
||||
),
|
||||
(
|
||||
"PAYMENT_CRYPTOPAY_TELEGRAM_EMOJI",
|
||||
"string",
|
||||
"Telegram button emoji",
|
||||
"Emoji prepended to the Telegram bot payment button when customized.",
|
||||
"₿",
|
||||
"TELEGRAM_EMOJI",
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
_CONFIG_MANIFEST = (
|
||||
ProviderManifestField("CRYPTOPAY_ENABLED", "bool", "Включена",
|
||||
subsection="CryptoPay", attr="ENABLED"),
|
||||
ProviderManifestField("CRYPTOPAY_TOKEN", "string", "Token",
|
||||
subsection="CryptoPay", secret=True, attr="TOKEN"),
|
||||
ProviderManifestField("CRYPTOPAY_NETWORK", "string", "Network",
|
||||
placeholder="mainnet", subsection="CryptoPay", attr="NETWORK"),
|
||||
ProviderManifestField("CRYPTOPAY_CURRENCY_TYPE", "string", "Currency type",
|
||||
description="fiat or crypto.",
|
||||
placeholder="fiat", subsection="CryptoPay", attr="CURRENCY_TYPE"),
|
||||
ProviderManifestField("CRYPTOPAY_ASSET", "string", "Asset",
|
||||
placeholder="RUB", subsection="CryptoPay", attr="ASSET"),
|
||||
ProviderManifestField(
|
||||
"CRYPTOPAY_ENABLED", "bool", "Включена", subsection="CryptoPay", attr="ENABLED"
|
||||
),
|
||||
ProviderManifestField(
|
||||
"CRYPTOPAY_TOKEN", "string", "Token", subsection="CryptoPay", secret=True, attr="TOKEN"
|
||||
),
|
||||
ProviderManifestField(
|
||||
"CRYPTOPAY_NETWORK",
|
||||
"string",
|
||||
"Network",
|
||||
placeholder="mainnet",
|
||||
subsection="CryptoPay",
|
||||
attr="NETWORK",
|
||||
),
|
||||
ProviderManifestField(
|
||||
"CRYPTOPAY_CURRENCY_TYPE",
|
||||
"string",
|
||||
"Currency type",
|
||||
description="fiat or crypto.",
|
||||
placeholder="fiat",
|
||||
subsection="CryptoPay",
|
||||
attr="CURRENCY_TYPE",
|
||||
),
|
||||
ProviderManifestField(
|
||||
"CRYPTOPAY_ASSET",
|
||||
"string",
|
||||
"Asset",
|
||||
placeholder="RUB",
|
||||
subsection="CryptoPay",
|
||||
attr="ASSET",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -71,9 +71,7 @@ class FreeKassaConfig(ProviderEnvConfig):
|
||||
API_KEY: Optional[str] = None
|
||||
PAYMENT_IP: Optional[str] = None
|
||||
PAYMENT_METHOD_ID: Optional[int] = None
|
||||
TRUSTED_IPS: str = Field(
|
||||
default="168.119.157.136,168.119.60.227,178.154.197.79,51.250.54.238"
|
||||
)
|
||||
TRUSTED_IPS: str = Field(default="168.119.157.136,168.119.60.227,178.154.197.79,51.250.54.238")
|
||||
|
||||
@field_validator("PAYMENT_METHOD_ID", mode="before")
|
||||
@classmethod
|
||||
@@ -85,7 +83,11 @@ class FreeKassaConfig(ProviderEnvConfig):
|
||||
return v
|
||||
|
||||
@field_validator(
|
||||
"MERCHANT_ID", "FIRST_SECRET", "SECOND_SECRET", "API_KEY", "PAYMENT_IP",
|
||||
"MERCHANT_ID",
|
||||
"FIRST_SECRET",
|
||||
"SECOND_SECRET",
|
||||
"API_KEY",
|
||||
"PAYMENT_IP",
|
||||
mode="before",
|
||||
)
|
||||
@classmethod
|
||||
@@ -505,8 +507,10 @@ async def pay_fk_callback_handler(
|
||||
provider_identifier = first_value(response_data, "orderHash", "orderId")
|
||||
lead_text: Optional[str] = None
|
||||
if success and location:
|
||||
order_id_display = first_value(response_data, "orderId") or provider_identifier or str(
|
||||
payment_record.payment_id
|
||||
order_id_display = (
|
||||
first_value(response_data, "orderId")
|
||||
or provider_identifier
|
||||
or str(payment_record.payment_id)
|
||||
)
|
||||
lead_text = translator(
|
||||
"free_kassa_order_info",
|
||||
@@ -532,7 +536,11 @@ async def pay_fk_callback_handler(
|
||||
|
||||
def create_service(ctx: ServiceFactoryContext) -> FreeKassaService:
|
||||
bundle = ctx.config_for("freekassa_service")
|
||||
config = bundle.config if bundle and isinstance(bundle.config, FreeKassaConfig) else FreeKassaConfig()
|
||||
config = (
|
||||
bundle.config
|
||||
if bundle and isinstance(bundle.config, FreeKassaConfig)
|
||||
else FreeKassaConfig()
|
||||
)
|
||||
return FreeKassaService(
|
||||
bot=ctx.bot,
|
||||
settings=ctx.settings,
|
||||
@@ -584,51 +592,130 @@ async def create_webapp_payment(ctx: WebAppPaymentContext) -> web.Response:
|
||||
|
||||
_PRESENTATION_MANIFEST = tuple(
|
||||
ProviderManifestField(
|
||||
key=key, type=type_, label=label, description=description,
|
||||
placeholder=placeholder, subsection="FreeKassa",
|
||||
target="presentation", attr=attr,
|
||||
key=key,
|
||||
type=type_,
|
||||
label=label,
|
||||
description=description,
|
||||
placeholder=placeholder,
|
||||
subsection="FreeKassa",
|
||||
target="presentation",
|
||||
attr=attr,
|
||||
)
|
||||
for key, type_, label, description, placeholder, attr in (
|
||||
("PAYMENT_FREEKASSA_WEBAPP_LABEL_RU", "string", "WebApp button text (RU)",
|
||||
"Custom Russian text shown in the Web App payment method button.", "", "WEBAPP_LABEL_RU"),
|
||||
("PAYMENT_FREEKASSA_WEBAPP_LABEL_EN", "string", "WebApp button text (EN)",
|
||||
"Custom English text shown in the Web App payment method button.", "", "WEBAPP_LABEL_EN"),
|
||||
("PAYMENT_FREEKASSA_WEBAPP_ICON", "icon", "WebApp button icon",
|
||||
"Lucide icon name rendered inside the Web App payment method button.",
|
||||
"Smartphone", "WEBAPP_ICON"),
|
||||
("PAYMENT_FREEKASSA_TELEGRAM_LABEL_RU", "string", "Telegram button text (RU)",
|
||||
"Custom Russian text shown in Telegram bot payment buttons.", "", "TELEGRAM_LABEL_RU"),
|
||||
("PAYMENT_FREEKASSA_TELEGRAM_LABEL_EN", "string", "Telegram button text (EN)",
|
||||
"Custom English text shown in Telegram bot payment buttons.", "", "TELEGRAM_LABEL_EN"),
|
||||
("PAYMENT_FREEKASSA_TELEGRAM_EMOJI", "string", "Telegram button emoji",
|
||||
"Emoji prepended to the Telegram bot payment button when customized.",
|
||||
"📱", "TELEGRAM_EMOJI"),
|
||||
(
|
||||
"PAYMENT_FREEKASSA_WEBAPP_LABEL_RU",
|
||||
"string",
|
||||
"WebApp button text (RU)",
|
||||
"Custom Russian text shown in the Web App payment method button.",
|
||||
"",
|
||||
"WEBAPP_LABEL_RU",
|
||||
),
|
||||
(
|
||||
"PAYMENT_FREEKASSA_WEBAPP_LABEL_EN",
|
||||
"string",
|
||||
"WebApp button text (EN)",
|
||||
"Custom English text shown in the Web App payment method button.",
|
||||
"",
|
||||
"WEBAPP_LABEL_EN",
|
||||
),
|
||||
(
|
||||
"PAYMENT_FREEKASSA_WEBAPP_ICON",
|
||||
"icon",
|
||||
"WebApp button icon",
|
||||
"Lucide icon name rendered inside the Web App payment method button.",
|
||||
"Smartphone",
|
||||
"WEBAPP_ICON",
|
||||
),
|
||||
(
|
||||
"PAYMENT_FREEKASSA_TELEGRAM_LABEL_RU",
|
||||
"string",
|
||||
"Telegram button text (RU)",
|
||||
"Custom Russian text shown in Telegram bot payment buttons.",
|
||||
"",
|
||||
"TELEGRAM_LABEL_RU",
|
||||
),
|
||||
(
|
||||
"PAYMENT_FREEKASSA_TELEGRAM_LABEL_EN",
|
||||
"string",
|
||||
"Telegram button text (EN)",
|
||||
"Custom English text shown in Telegram bot payment buttons.",
|
||||
"",
|
||||
"TELEGRAM_LABEL_EN",
|
||||
),
|
||||
(
|
||||
"PAYMENT_FREEKASSA_TELEGRAM_EMOJI",
|
||||
"string",
|
||||
"Telegram button emoji",
|
||||
"Emoji prepended to the Telegram bot payment button when customized.",
|
||||
"📱",
|
||||
"TELEGRAM_EMOJI",
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
_CONFIG_MANIFEST = (
|
||||
ProviderManifestField("FREEKASSA_ENABLED", "bool", "Включена",
|
||||
subsection="FreeKassa", attr="ENABLED"),
|
||||
ProviderManifestField("FREEKASSA_MERCHANT_ID", "string", "Merchant ID",
|
||||
subsection="FreeKassa", attr="MERCHANT_ID"),
|
||||
ProviderManifestField("FREEKASSA_FIRST_SECRET", "string", "First secret",
|
||||
subsection="FreeKassa", secret=True, attr="FIRST_SECRET"),
|
||||
ProviderManifestField("FREEKASSA_SECOND_SECRET", "string", "Second secret",
|
||||
subsection="FreeKassa", secret=True, attr="SECOND_SECRET"),
|
||||
ProviderManifestField("FREEKASSA_API_KEY", "string", "API key",
|
||||
subsection="FreeKassa", secret=True, attr="API_KEY"),
|
||||
ProviderManifestField("FREEKASSA_PAYMENT_URL", "url", "Payment URL",
|
||||
placeholder="https://pay.freekassa.ru/",
|
||||
subsection="FreeKassa", attr="PAYMENT_URL"),
|
||||
ProviderManifestField("FREEKASSA_PAYMENT_METHOD_ID", "int", "Payment method ID",
|
||||
description="See https://merchant.freekassa.net/settings/currencies",
|
||||
subsection="FreeKassa", attr="PAYMENT_METHOD_ID"),
|
||||
ProviderManifestField("FREEKASSA_PAYMENT_IP", "string", "Server IP",
|
||||
description="Public IP address reported to FreeKassa.",
|
||||
subsection="FreeKassa", attr="PAYMENT_IP"),
|
||||
ProviderManifestField("FREEKASSA_TRUSTED_IPS", "string", "Trusted IPs",
|
||||
description="Comma-separated IP addresses accepted for FreeKassa webhooks.",
|
||||
subsection="FreeKassa", attr="TRUSTED_IPS"),
|
||||
ProviderManifestField(
|
||||
"FREEKASSA_ENABLED", "bool", "Включена", subsection="FreeKassa", attr="ENABLED"
|
||||
),
|
||||
ProviderManifestField(
|
||||
"FREEKASSA_MERCHANT_ID", "string", "Merchant ID", subsection="FreeKassa", attr="MERCHANT_ID"
|
||||
),
|
||||
ProviderManifestField(
|
||||
"FREEKASSA_FIRST_SECRET",
|
||||
"string",
|
||||
"First secret",
|
||||
subsection="FreeKassa",
|
||||
secret=True,
|
||||
attr="FIRST_SECRET",
|
||||
),
|
||||
ProviderManifestField(
|
||||
"FREEKASSA_SECOND_SECRET",
|
||||
"string",
|
||||
"Second secret",
|
||||
subsection="FreeKassa",
|
||||
secret=True,
|
||||
attr="SECOND_SECRET",
|
||||
),
|
||||
ProviderManifestField(
|
||||
"FREEKASSA_API_KEY",
|
||||
"string",
|
||||
"API key",
|
||||
subsection="FreeKassa",
|
||||
secret=True,
|
||||
attr="API_KEY",
|
||||
),
|
||||
ProviderManifestField(
|
||||
"FREEKASSA_PAYMENT_URL",
|
||||
"url",
|
||||
"Payment URL",
|
||||
placeholder="https://pay.freekassa.ru/",
|
||||
subsection="FreeKassa",
|
||||
attr="PAYMENT_URL",
|
||||
),
|
||||
ProviderManifestField(
|
||||
"FREEKASSA_PAYMENT_METHOD_ID",
|
||||
"int",
|
||||
"Payment method ID",
|
||||
description="See https://merchant.freekassa.net/settings/currencies",
|
||||
subsection="FreeKassa",
|
||||
attr="PAYMENT_METHOD_ID",
|
||||
),
|
||||
ProviderManifestField(
|
||||
"FREEKASSA_PAYMENT_IP",
|
||||
"string",
|
||||
"Server IP",
|
||||
description="Public IP address reported to FreeKassa.",
|
||||
subsection="FreeKassa",
|
||||
attr="PAYMENT_IP",
|
||||
),
|
||||
ProviderManifestField(
|
||||
"FREEKASSA_TRUSTED_IPS",
|
||||
"string",
|
||||
"Trusted IPs",
|
||||
description="Comma-separated IP addresses accepted for FreeKassa webhooks.",
|
||||
subsection="FreeKassa",
|
||||
attr="TRUSTED_IPS",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -93,7 +93,12 @@ class HeleketConfig(ProviderEnvConfig):
|
||||
return min(43200, max(300, value))
|
||||
|
||||
@field_validator(
|
||||
"MERCHANT_ID", "API_KEY", "TO_CURRENCY", "NETWORK", "RETURN_URL", "SUCCESS_URL",
|
||||
"MERCHANT_ID",
|
||||
"API_KEY",
|
||||
"TO_CURRENCY",
|
||||
"NETWORK",
|
||||
"RETURN_URL",
|
||||
"SUCCESS_URL",
|
||||
mode="before",
|
||||
)
|
||||
@classmethod
|
||||
@@ -644,7 +649,9 @@ async def heleket_webhook_route(request: web.Request) -> web.Response:
|
||||
|
||||
def create_service(ctx: ServiceFactoryContext) -> HeleketService:
|
||||
bundle = ctx.config_for("heleket_service")
|
||||
config = bundle.config if bundle and isinstance(bundle.config, HeleketConfig) else HeleketConfig()
|
||||
config = (
|
||||
bundle.config if bundle and isinstance(bundle.config, HeleketConfig) else HeleketConfig()
|
||||
)
|
||||
return HeleketService(
|
||||
bot=ctx.bot,
|
||||
settings=ctx.settings,
|
||||
@@ -669,51 +676,142 @@ _PRESENTATION_MANIFEST = tuple(
|
||||
attr=attr,
|
||||
)
|
||||
for key, type_, label, description, placeholder, attr in (
|
||||
("PAYMENT_HELEKET_WEBAPP_LABEL_RU", "string", "WebApp button text (RU)",
|
||||
"Custom Russian text shown in the Web App payment method button.", "", "WEBAPP_LABEL_RU"),
|
||||
("PAYMENT_HELEKET_WEBAPP_LABEL_EN", "string", "WebApp button text (EN)",
|
||||
"Custom English text shown in the Web App payment method button.", "", "WEBAPP_LABEL_EN"),
|
||||
("PAYMENT_HELEKET_WEBAPP_ICON", "icon", "WebApp button icon",
|
||||
"Lucide icon name rendered inside the Web App payment method button.", "Bitcoin", "WEBAPP_ICON"),
|
||||
("PAYMENT_HELEKET_TELEGRAM_LABEL_RU", "string", "Telegram button text (RU)",
|
||||
"Custom Russian text shown in Telegram bot payment buttons.", "", "TELEGRAM_LABEL_RU"),
|
||||
("PAYMENT_HELEKET_TELEGRAM_LABEL_EN", "string", "Telegram button text (EN)",
|
||||
"Custom English text shown in Telegram bot payment buttons.", "", "TELEGRAM_LABEL_EN"),
|
||||
("PAYMENT_HELEKET_TELEGRAM_EMOJI", "string", "Telegram button emoji",
|
||||
"Emoji prepended to the Telegram bot payment button when customized.", "🪙", "TELEGRAM_EMOJI"),
|
||||
(
|
||||
"PAYMENT_HELEKET_WEBAPP_LABEL_RU",
|
||||
"string",
|
||||
"WebApp button text (RU)",
|
||||
"Custom Russian text shown in the Web App payment method button.",
|
||||
"",
|
||||
"WEBAPP_LABEL_RU",
|
||||
),
|
||||
(
|
||||
"PAYMENT_HELEKET_WEBAPP_LABEL_EN",
|
||||
"string",
|
||||
"WebApp button text (EN)",
|
||||
"Custom English text shown in the Web App payment method button.",
|
||||
"",
|
||||
"WEBAPP_LABEL_EN",
|
||||
),
|
||||
(
|
||||
"PAYMENT_HELEKET_WEBAPP_ICON",
|
||||
"icon",
|
||||
"WebApp button icon",
|
||||
"Lucide icon name rendered inside the Web App payment method button.",
|
||||
"Bitcoin",
|
||||
"WEBAPP_ICON",
|
||||
),
|
||||
(
|
||||
"PAYMENT_HELEKET_TELEGRAM_LABEL_RU",
|
||||
"string",
|
||||
"Telegram button text (RU)",
|
||||
"Custom Russian text shown in Telegram bot payment buttons.",
|
||||
"",
|
||||
"TELEGRAM_LABEL_RU",
|
||||
),
|
||||
(
|
||||
"PAYMENT_HELEKET_TELEGRAM_LABEL_EN",
|
||||
"string",
|
||||
"Telegram button text (EN)",
|
||||
"Custom English text shown in Telegram bot payment buttons.",
|
||||
"",
|
||||
"TELEGRAM_LABEL_EN",
|
||||
),
|
||||
(
|
||||
"PAYMENT_HELEKET_TELEGRAM_EMOJI",
|
||||
"string",
|
||||
"Telegram button emoji",
|
||||
"Emoji prepended to the Telegram bot payment button when customized.",
|
||||
"🪙",
|
||||
"TELEGRAM_EMOJI",
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
_CONFIG_MANIFEST = (
|
||||
ProviderManifestField("HELEKET_ENABLED", "bool", "Enabled", subsection="Heleket", attr="ENABLED"),
|
||||
ProviderManifestField("HELEKET_MERCHANT_ID", "string", "Merchant ID", subsection="Heleket",
|
||||
secret=True, attr="MERCHANT_ID"),
|
||||
ProviderManifestField("HELEKET_API_KEY", "string", "Payment API key", subsection="Heleket",
|
||||
secret=True, attr="API_KEY"),
|
||||
ProviderManifestField("HELEKET_BASE_URL", "url", "Base URL",
|
||||
placeholder="https://api.heleket.com", subsection="Heleket", attr="BASE_URL"),
|
||||
ProviderManifestField("HELEKET_CURRENCY", "string", "Invoice currency",
|
||||
description="Fiat or crypto code (RUB, USD, USDT).",
|
||||
placeholder="RUB", subsection="Heleket", attr="CURRENCY"),
|
||||
ProviderManifestField("HELEKET_TO_CURRENCY", "string", "Target crypto",
|
||||
description="Optional target cryptocurrency for conversion.",
|
||||
subsection="Heleket", attr="TO_CURRENCY"),
|
||||
ProviderManifestField("HELEKET_NETWORK", "string", "Blockchain network",
|
||||
description="Optional blockchain network code (tron, bsc, eth).",
|
||||
subsection="Heleket", attr="NETWORK"),
|
||||
ProviderManifestField("HELEKET_RETURN_URL", "url", "Return URL", subsection="Heleket",
|
||||
attr="RETURN_URL"),
|
||||
ProviderManifestField("HELEKET_SUCCESS_URL", "url", "Success URL", subsection="Heleket",
|
||||
attr="SUCCESS_URL"),
|
||||
ProviderManifestField("HELEKET_LIFETIME_SECONDS", "int", "Invoice lifetime (seconds)",
|
||||
description="300..43200; Heleket defaults to 3600.",
|
||||
subsection="Heleket", min=300, max=43200, attr="LIFETIME_SECONDS"),
|
||||
ProviderManifestField("HELEKET_VERIFY_WEBHOOK_SIGNATURE", "bool", "Verify webhook signature",
|
||||
subsection="Heleket", attr="VERIFY_WEBHOOK_SIGNATURE"),
|
||||
ProviderManifestField("HELEKET_TRUSTED_IPS", "string", "Trusted IPs",
|
||||
description="Comma-separated IP addresses accepted for Heleket webhooks.",
|
||||
subsection="Heleket", attr="TRUSTED_IPS"),
|
||||
ProviderManifestField(
|
||||
"HELEKET_ENABLED", "bool", "Enabled", subsection="Heleket", attr="ENABLED"
|
||||
),
|
||||
ProviderManifestField(
|
||||
"HELEKET_MERCHANT_ID",
|
||||
"string",
|
||||
"Merchant ID",
|
||||
subsection="Heleket",
|
||||
secret=True,
|
||||
attr="MERCHANT_ID",
|
||||
),
|
||||
ProviderManifestField(
|
||||
"HELEKET_API_KEY",
|
||||
"string",
|
||||
"Payment API key",
|
||||
subsection="Heleket",
|
||||
secret=True,
|
||||
attr="API_KEY",
|
||||
),
|
||||
ProviderManifestField(
|
||||
"HELEKET_BASE_URL",
|
||||
"url",
|
||||
"Base URL",
|
||||
placeholder="https://api.heleket.com",
|
||||
subsection="Heleket",
|
||||
attr="BASE_URL",
|
||||
),
|
||||
ProviderManifestField(
|
||||
"HELEKET_CURRENCY",
|
||||
"string",
|
||||
"Invoice currency",
|
||||
description="Fiat or crypto code (RUB, USD, USDT).",
|
||||
placeholder="RUB",
|
||||
subsection="Heleket",
|
||||
attr="CURRENCY",
|
||||
),
|
||||
ProviderManifestField(
|
||||
"HELEKET_TO_CURRENCY",
|
||||
"string",
|
||||
"Target crypto",
|
||||
description="Optional target cryptocurrency for conversion.",
|
||||
subsection="Heleket",
|
||||
attr="TO_CURRENCY",
|
||||
),
|
||||
ProviderManifestField(
|
||||
"HELEKET_NETWORK",
|
||||
"string",
|
||||
"Blockchain network",
|
||||
description="Optional blockchain network code (tron, bsc, eth).",
|
||||
subsection="Heleket",
|
||||
attr="NETWORK",
|
||||
),
|
||||
ProviderManifestField(
|
||||
"HELEKET_RETURN_URL", "url", "Return URL", subsection="Heleket", attr="RETURN_URL"
|
||||
),
|
||||
ProviderManifestField(
|
||||
"HELEKET_SUCCESS_URL", "url", "Success URL", subsection="Heleket", attr="SUCCESS_URL"
|
||||
),
|
||||
ProviderManifestField(
|
||||
"HELEKET_LIFETIME_SECONDS",
|
||||
"int",
|
||||
"Invoice lifetime (seconds)",
|
||||
description="300..43200; Heleket defaults to 3600.",
|
||||
subsection="Heleket",
|
||||
min=300,
|
||||
max=43200,
|
||||
attr="LIFETIME_SECONDS",
|
||||
),
|
||||
ProviderManifestField(
|
||||
"HELEKET_VERIFY_WEBHOOK_SIGNATURE",
|
||||
"bool",
|
||||
"Verify webhook signature",
|
||||
subsection="Heleket",
|
||||
attr="VERIFY_WEBHOOK_SIGNATURE",
|
||||
),
|
||||
ProviderManifestField(
|
||||
"HELEKET_TRUSTED_IPS",
|
||||
"string",
|
||||
"Trusted IPs",
|
||||
description="Comma-separated IP addresses accepted for Heleket webhooks.",
|
||||
subsection="Heleket",
|
||||
attr="TRUSTED_IPS",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -429,7 +429,11 @@ async def pay_platega_callback_handler(
|
||||
return
|
||||
|
||||
callback_prefix, _, _ = (callback.data or "").partition(":")
|
||||
variant = _resolve_platega_variant(callback_prefix, platega_service.config) if platega_service else None
|
||||
variant = (
|
||||
_resolve_platega_variant(callback_prefix, platega_service.config)
|
||||
if platega_service
|
||||
else None
|
||||
)
|
||||
if variant is None:
|
||||
await safe_callback_answer(callback)
|
||||
return
|
||||
@@ -513,7 +517,9 @@ async def pay_platega_callback_handler(
|
||||
|
||||
def create_service(ctx: ServiceFactoryContext) -> PlategaService:
|
||||
bundle = ctx.config_for("platega_service")
|
||||
config = bundle.config if bundle and isinstance(bundle.config, PlategaConfig) else PlategaConfig()
|
||||
config = (
|
||||
bundle.config if bundle and isinstance(bundle.config, PlategaConfig) else PlategaConfig()
|
||||
)
|
||||
return PlategaService(
|
||||
bot=ctx.bot,
|
||||
settings=ctx.settings,
|
||||
@@ -613,52 +619,109 @@ def _platega_presentation_manifest(subsection: str, default_icon: str, prefix: s
|
||||
attr=attr,
|
||||
)
|
||||
for suffix_key, type_, label, description, placeholder, attr in (
|
||||
("WEBAPP_LABEL_RU", "string", "WebApp button text (RU)",
|
||||
"Custom Russian text shown in the Web App payment method button.",
|
||||
"", "WEBAPP_LABEL_RU"),
|
||||
("WEBAPP_LABEL_EN", "string", "WebApp button text (EN)",
|
||||
"Custom English text shown in the Web App payment method button.",
|
||||
"", "WEBAPP_LABEL_EN"),
|
||||
("WEBAPP_ICON", "icon", "WebApp button icon",
|
||||
"Lucide icon name rendered inside the Web App payment method button.",
|
||||
default_icon, "WEBAPP_ICON"),
|
||||
("TELEGRAM_LABEL_RU", "string", "Telegram button text (RU)",
|
||||
"Custom Russian text shown in Telegram bot payment buttons.",
|
||||
"", "TELEGRAM_LABEL_RU"),
|
||||
("TELEGRAM_LABEL_EN", "string", "Telegram button text (EN)",
|
||||
"Custom English text shown in Telegram bot payment buttons.",
|
||||
"", "TELEGRAM_LABEL_EN"),
|
||||
("TELEGRAM_EMOJI", "string", "Telegram button emoji",
|
||||
"Emoji prepended to the Telegram bot payment button when customized.",
|
||||
"", "TELEGRAM_EMOJI"),
|
||||
(
|
||||
"WEBAPP_LABEL_RU",
|
||||
"string",
|
||||
"WebApp button text (RU)",
|
||||
"Custom Russian text shown in the Web App payment method button.",
|
||||
"",
|
||||
"WEBAPP_LABEL_RU",
|
||||
),
|
||||
(
|
||||
"WEBAPP_LABEL_EN",
|
||||
"string",
|
||||
"WebApp button text (EN)",
|
||||
"Custom English text shown in the Web App payment method button.",
|
||||
"",
|
||||
"WEBAPP_LABEL_EN",
|
||||
),
|
||||
(
|
||||
"WEBAPP_ICON",
|
||||
"icon",
|
||||
"WebApp button icon",
|
||||
"Lucide icon name rendered inside the Web App payment method button.",
|
||||
default_icon,
|
||||
"WEBAPP_ICON",
|
||||
),
|
||||
(
|
||||
"TELEGRAM_LABEL_RU",
|
||||
"string",
|
||||
"Telegram button text (RU)",
|
||||
"Custom Russian text shown in Telegram bot payment buttons.",
|
||||
"",
|
||||
"TELEGRAM_LABEL_RU",
|
||||
),
|
||||
(
|
||||
"TELEGRAM_LABEL_EN",
|
||||
"string",
|
||||
"Telegram button text (EN)",
|
||||
"Custom English text shown in Telegram bot payment buttons.",
|
||||
"",
|
||||
"TELEGRAM_LABEL_EN",
|
||||
),
|
||||
(
|
||||
"TELEGRAM_EMOJI",
|
||||
"string",
|
||||
"Telegram button emoji",
|
||||
"Emoji prepended to the Telegram bot payment button when customized.",
|
||||
"",
|
||||
"TELEGRAM_EMOJI",
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
_CONFIG_MANIFEST = (
|
||||
ProviderManifestField("PLATEGA_ENABLED", "bool", "Включена",
|
||||
subsection="Platega", attr="ENABLED"),
|
||||
ProviderManifestField("PLATEGA_BASE_URL", "url", "Base URL",
|
||||
placeholder="https://app.platega.io",
|
||||
subsection="Platega", attr="BASE_URL"),
|
||||
ProviderManifestField("PLATEGA_MERCHANT_ID", "string", "Merchant ID",
|
||||
subsection="Platega", attr="MERCHANT_ID"),
|
||||
ProviderManifestField("PLATEGA_SECRET", "string", "Secret",
|
||||
subsection="Platega", secret=True, attr="SECRET"),
|
||||
ProviderManifestField("PLATEGA_PAYMENT_METHOD", "int", "Метод оплаты (legacy)",
|
||||
subsection="Platega", attr="PAYMENT_METHOD"),
|
||||
ProviderManifestField("PLATEGA_SBP_ENABLED", "bool", "SBP-кнопка",
|
||||
subsection="Platega", attr="SBP_ENABLED"),
|
||||
ProviderManifestField("PLATEGA_SBP_METHOD", "int", "SBP method ID",
|
||||
subsection="Platega", attr="SBP_METHOD"),
|
||||
ProviderManifestField("PLATEGA_CRYPTO_ENABLED", "bool", "Crypto-кнопка",
|
||||
subsection="Platega", attr="CRYPTO_ENABLED"),
|
||||
ProviderManifestField("PLATEGA_CRYPTO_METHOD", "int", "Crypto method ID",
|
||||
subsection="Platega", attr="CRYPTO_METHOD"),
|
||||
ProviderManifestField("PLATEGA_RETURN_URL", "url", "Return URL",
|
||||
subsection="Platega", attr="RETURN_URL"),
|
||||
ProviderManifestField("PLATEGA_FAILED_URL", "url", "Failed URL",
|
||||
subsection="Platega", attr="FAILED_URL"),
|
||||
ProviderManifestField(
|
||||
"PLATEGA_ENABLED", "bool", "Включена", subsection="Platega", attr="ENABLED"
|
||||
),
|
||||
ProviderManifestField(
|
||||
"PLATEGA_BASE_URL",
|
||||
"url",
|
||||
"Base URL",
|
||||
placeholder="https://app.platega.io",
|
||||
subsection="Platega",
|
||||
attr="BASE_URL",
|
||||
),
|
||||
ProviderManifestField(
|
||||
"PLATEGA_MERCHANT_ID", "string", "Merchant ID", subsection="Platega", attr="MERCHANT_ID"
|
||||
),
|
||||
ProviderManifestField(
|
||||
"PLATEGA_SECRET", "string", "Secret", subsection="Platega", secret=True, attr="SECRET"
|
||||
),
|
||||
ProviderManifestField(
|
||||
"PLATEGA_PAYMENT_METHOD",
|
||||
"int",
|
||||
"Метод оплаты (legacy)",
|
||||
subsection="Platega",
|
||||
attr="PAYMENT_METHOD",
|
||||
),
|
||||
ProviderManifestField(
|
||||
"PLATEGA_SBP_ENABLED", "bool", "SBP-кнопка", subsection="Platega", attr="SBP_ENABLED"
|
||||
),
|
||||
ProviderManifestField(
|
||||
"PLATEGA_SBP_METHOD", "int", "SBP method ID", subsection="Platega", attr="SBP_METHOD"
|
||||
),
|
||||
ProviderManifestField(
|
||||
"PLATEGA_CRYPTO_ENABLED",
|
||||
"bool",
|
||||
"Crypto-кнопка",
|
||||
subsection="Platega",
|
||||
attr="CRYPTO_ENABLED",
|
||||
),
|
||||
ProviderManifestField(
|
||||
"PLATEGA_CRYPTO_METHOD",
|
||||
"int",
|
||||
"Crypto method ID",
|
||||
subsection="Platega",
|
||||
attr="CRYPTO_METHOD",
|
||||
),
|
||||
ProviderManifestField(
|
||||
"PLATEGA_RETURN_URL", "url", "Return URL", subsection="Platega", attr="RETURN_URL"
|
||||
),
|
||||
ProviderManifestField(
|
||||
"PLATEGA_FAILED_URL", "url", "Failed URL", subsection="Platega", attr="FAILED_URL"
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -672,7 +735,9 @@ SBP_SPEC = PaymentProviderSpec(
|
||||
telegram_labels={"ru": "Оплата через СБП", "en": "Pay via SBP"},
|
||||
telegram_emoji="🏦",
|
||||
pending_status="pending_platega",
|
||||
enabled=lambda config: bool(getattr(config, "ENABLED", False) and getattr(config, "SBP_ENABLED", False)),
|
||||
enabled=lambda config: bool(
|
||||
getattr(config, "ENABLED", False) and getattr(config, "SBP_ENABLED", False)
|
||||
),
|
||||
service_key="platega_service",
|
||||
callback_prefix="pay_platega_sbp",
|
||||
aliases=("platega",),
|
||||
@@ -683,9 +748,8 @@ SBP_SPEC = PaymentProviderSpec(
|
||||
create_webapp_payment=create_sbp_webapp_payment,
|
||||
config_class=PlategaConfig,
|
||||
presentation_class=PlategaSbpPresentation,
|
||||
manifest_fields=_CONFIG_MANIFEST + _platega_presentation_manifest(
|
||||
"Platega SBP", "CreditCard", "PLATEGA_SBP"
|
||||
),
|
||||
manifest_fields=_CONFIG_MANIFEST
|
||||
+ _platega_presentation_manifest("Platega SBP", "CreditCard", "PLATEGA_SBP"),
|
||||
)
|
||||
|
||||
CRYPTO_SPEC = PaymentProviderSpec(
|
||||
@@ -700,15 +764,15 @@ CRYPTO_SPEC = PaymentProviderSpec(
|
||||
pending_status="pending_platega",
|
||||
# Uses the same PlategaConfig as SBP_SPEC (shared service_key); enable
|
||||
# flag combines the global PLATEGA_ENABLED with the per-button toggle.
|
||||
enabled=lambda config: bool(getattr(config, "ENABLED", False) and getattr(config, "CRYPTO_ENABLED", False)),
|
||||
enabled=lambda config: bool(
|
||||
getattr(config, "ENABLED", False) and getattr(config, "CRYPTO_ENABLED", False)
|
||||
),
|
||||
service_key="platega_service",
|
||||
callback_prefix="pay_platega_crypto",
|
||||
create_webapp_payment=create_crypto_webapp_payment,
|
||||
config_class=PlategaConfig,
|
||||
presentation_class=PlategaCryptoPresentation,
|
||||
manifest_fields=_platega_presentation_manifest(
|
||||
"Platega Crypto", "Bitcoin", "PLATEGA_CRYPTO"
|
||||
),
|
||||
manifest_fields=_platega_presentation_manifest("Platega Crypto", "Bitcoin", "PLATEGA_CRYPTO"),
|
||||
)
|
||||
|
||||
SPECS = (SBP_SPEC, CRYPTO_SPEC)
|
||||
|
||||
@@ -211,10 +211,7 @@ def resolve_provider_presentation(
|
||||
or _localized_default(spec.webapp_labels, lang, spec.webapp_label)
|
||||
or spec.label
|
||||
)
|
||||
webapp_icon = (
|
||||
_bare_setting_value(settings, spec, "WEBAPP_ICON")
|
||||
or spec.webapp_icon
|
||||
)
|
||||
webapp_icon = _bare_setting_value(settings, spec, "WEBAPP_ICON") or spec.webapp_icon
|
||||
telegram_label_override = _localized_setting_value(
|
||||
settings,
|
||||
spec,
|
||||
@@ -351,15 +348,9 @@ def manifest_field_default(
|
||||
return None
|
||||
attr = manifest_field.attr or manifest_field.key
|
||||
if attr == "WEBAPP_LABEL_RU":
|
||||
return (
|
||||
_localized_default(spec.webapp_labels, "ru", spec.webapp_label)
|
||||
or spec.label
|
||||
)
|
||||
return _localized_default(spec.webapp_labels, "ru", spec.webapp_label) or spec.label
|
||||
if attr == "WEBAPP_LABEL_EN":
|
||||
return (
|
||||
_localized_default(spec.webapp_labels, "en", spec.webapp_label)
|
||||
or spec.label
|
||||
)
|
||||
return _localized_default(spec.webapp_labels, "en", spec.webapp_label) or spec.label
|
||||
if attr == "WEBAPP_ICON":
|
||||
return spec.webapp_icon
|
||||
if attr == "TELEGRAM_LABEL_RU":
|
||||
|
||||
@@ -453,7 +453,9 @@ async def pay_severpay_callback_handler(
|
||||
|
||||
def create_service(ctx: ServiceFactoryContext) -> SeverPayService:
|
||||
bundle = ctx.config_for("severpay_service")
|
||||
config = bundle.config if bundle and isinstance(bundle.config, SeverPayConfig) else SeverPayConfig()
|
||||
config = (
|
||||
bundle.config if bundle and isinstance(bundle.config, SeverPayConfig) else SeverPayConfig()
|
||||
)
|
||||
return SeverPayService(
|
||||
bot=ctx.bot,
|
||||
settings=ctx.settings,
|
||||
@@ -506,42 +508,96 @@ async def create_webapp_payment(ctx: WebAppPaymentContext) -> web.Response:
|
||||
|
||||
_PRESENTATION_MANIFEST = tuple(
|
||||
ProviderManifestField(
|
||||
key=key, type=type_, label=label, description=description,
|
||||
placeholder=placeholder, subsection="SeverPay",
|
||||
target="presentation", attr=attr,
|
||||
key=key,
|
||||
type=type_,
|
||||
label=label,
|
||||
description=description,
|
||||
placeholder=placeholder,
|
||||
subsection="SeverPay",
|
||||
target="presentation",
|
||||
attr=attr,
|
||||
)
|
||||
for key, type_, label, description, placeholder, attr in (
|
||||
("PAYMENT_SEVERPAY_WEBAPP_LABEL_RU", "string", "WebApp button text (RU)",
|
||||
"Custom Russian text shown in the Web App payment method button.", "", "WEBAPP_LABEL_RU"),
|
||||
("PAYMENT_SEVERPAY_WEBAPP_LABEL_EN", "string", "WebApp button text (EN)",
|
||||
"Custom English text shown in the Web App payment method button.", "", "WEBAPP_LABEL_EN"),
|
||||
("PAYMENT_SEVERPAY_WEBAPP_ICON", "icon", "WebApp button icon",
|
||||
"Lucide icon name rendered inside the Web App payment method button.",
|
||||
"CreditCard", "WEBAPP_ICON"),
|
||||
("PAYMENT_SEVERPAY_TELEGRAM_LABEL_RU", "string", "Telegram button text (RU)",
|
||||
"Custom Russian text shown in Telegram bot payment buttons.", "", "TELEGRAM_LABEL_RU"),
|
||||
("PAYMENT_SEVERPAY_TELEGRAM_LABEL_EN", "string", "Telegram button text (EN)",
|
||||
"Custom English text shown in Telegram bot payment buttons.", "", "TELEGRAM_LABEL_EN"),
|
||||
("PAYMENT_SEVERPAY_TELEGRAM_EMOJI", "string", "Telegram button emoji",
|
||||
"Emoji prepended to the Telegram bot payment button when customized.",
|
||||
"💳", "TELEGRAM_EMOJI"),
|
||||
(
|
||||
"PAYMENT_SEVERPAY_WEBAPP_LABEL_RU",
|
||||
"string",
|
||||
"WebApp button text (RU)",
|
||||
"Custom Russian text shown in the Web App payment method button.",
|
||||
"",
|
||||
"WEBAPP_LABEL_RU",
|
||||
),
|
||||
(
|
||||
"PAYMENT_SEVERPAY_WEBAPP_LABEL_EN",
|
||||
"string",
|
||||
"WebApp button text (EN)",
|
||||
"Custom English text shown in the Web App payment method button.",
|
||||
"",
|
||||
"WEBAPP_LABEL_EN",
|
||||
),
|
||||
(
|
||||
"PAYMENT_SEVERPAY_WEBAPP_ICON",
|
||||
"icon",
|
||||
"WebApp button icon",
|
||||
"Lucide icon name rendered inside the Web App payment method button.",
|
||||
"CreditCard",
|
||||
"WEBAPP_ICON",
|
||||
),
|
||||
(
|
||||
"PAYMENT_SEVERPAY_TELEGRAM_LABEL_RU",
|
||||
"string",
|
||||
"Telegram button text (RU)",
|
||||
"Custom Russian text shown in Telegram bot payment buttons.",
|
||||
"",
|
||||
"TELEGRAM_LABEL_RU",
|
||||
),
|
||||
(
|
||||
"PAYMENT_SEVERPAY_TELEGRAM_LABEL_EN",
|
||||
"string",
|
||||
"Telegram button text (EN)",
|
||||
"Custom English text shown in Telegram bot payment buttons.",
|
||||
"",
|
||||
"TELEGRAM_LABEL_EN",
|
||||
),
|
||||
(
|
||||
"PAYMENT_SEVERPAY_TELEGRAM_EMOJI",
|
||||
"string",
|
||||
"Telegram button emoji",
|
||||
"Emoji prepended to the Telegram bot payment button when customized.",
|
||||
"💳",
|
||||
"TELEGRAM_EMOJI",
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
_CONFIG_MANIFEST = (
|
||||
ProviderManifestField("SEVERPAY_ENABLED", "bool", "Включена",
|
||||
subsection="SeverPay", attr="ENABLED"),
|
||||
ProviderManifestField(
|
||||
"SEVERPAY_ENABLED", "bool", "Включена", subsection="SeverPay", attr="ENABLED"
|
||||
),
|
||||
ProviderManifestField("SEVERPAY_MID", "int", "MID", subsection="SeverPay", attr="MID"),
|
||||
ProviderManifestField("SEVERPAY_TOKEN", "string", "Token", subsection="SeverPay",
|
||||
secret=True, attr="TOKEN"),
|
||||
ProviderManifestField("SEVERPAY_BASE_URL", "url", "Base URL",
|
||||
placeholder="https://severpay.io/api/merchant",
|
||||
subsection="SeverPay", attr="BASE_URL"),
|
||||
ProviderManifestField("SEVERPAY_RETURN_URL", "url", "Return URL",
|
||||
subsection="SeverPay", attr="RETURN_URL"),
|
||||
ProviderManifestField("SEVERPAY_LIFETIME_MINUTES", "int", "Payment link lifetime (minutes)",
|
||||
description="30..4320; leave empty for the SeverPay default.",
|
||||
subsection="SeverPay", min=30, max=4320, attr="LIFETIME_MINUTES"),
|
||||
ProviderManifestField(
|
||||
"SEVERPAY_TOKEN", "string", "Token", subsection="SeverPay", secret=True, attr="TOKEN"
|
||||
),
|
||||
ProviderManifestField(
|
||||
"SEVERPAY_BASE_URL",
|
||||
"url",
|
||||
"Base URL",
|
||||
placeholder="https://severpay.io/api/merchant",
|
||||
subsection="SeverPay",
|
||||
attr="BASE_URL",
|
||||
),
|
||||
ProviderManifestField(
|
||||
"SEVERPAY_RETURN_URL", "url", "Return URL", subsection="SeverPay", attr="RETURN_URL"
|
||||
),
|
||||
ProviderManifestField(
|
||||
"SEVERPAY_LIFETIME_MINUTES",
|
||||
"int",
|
||||
"Payment link lifetime (minutes)",
|
||||
description="30..4320; leave empty for the SeverPay default.",
|
||||
subsection="SeverPay",
|
||||
min=30,
|
||||
max=4320,
|
||||
attr="LIFETIME_MINUTES",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -125,11 +125,7 @@ def payment_link_message_text(
|
||||
"topup",
|
||||
"premium_topup",
|
||||
}
|
||||
key = (
|
||||
"payment_link_message_traffic"
|
||||
if traffic_like
|
||||
else "payment_link_message"
|
||||
)
|
||||
key = "payment_link_message_traffic" if traffic_like else "payment_link_message"
|
||||
body = translator(
|
||||
key,
|
||||
months=int(parts.months),
|
||||
|
||||
@@ -35,9 +35,7 @@ async def resolve_user_language(
|
||||
if db_user is None:
|
||||
db_user = await user_dal.get_user_by_id(session, user_id)
|
||||
language = (
|
||||
db_user.language_code
|
||||
if db_user and db_user.language_code
|
||||
else settings.DEFAULT_LANGUAGE
|
||||
db_user.language_code if db_user and db_user.language_code else settings.DEFAULT_LANGUAGE
|
||||
)
|
||||
return db_user, language
|
||||
|
||||
@@ -256,9 +254,7 @@ async def finalize_successful_payment(
|
||||
activation_months = (
|
||||
int(float(req.months)) if is_subscription else int(float(req.traffic_amount or req.months))
|
||||
)
|
||||
traffic_gb_for_activation = (
|
||||
float(req.traffic_amount or req.months) if is_traffic else None
|
||||
)
|
||||
traffic_gb_for_activation = float(req.traffic_amount or req.months) if is_traffic else None
|
||||
|
||||
try:
|
||||
activation = await req.subscription_service.activate_subscription(
|
||||
@@ -308,9 +304,7 @@ async def finalize_successful_payment(
|
||||
base_end_date = activation.get("end_date") if activation else None
|
||||
final_end_date = base_end_date
|
||||
applied_referee_bonus_days = 0
|
||||
applied_promo_bonus_days = (
|
||||
activation.get("applied_promo_bonus_days", 0) if activation else 0
|
||||
)
|
||||
applied_promo_bonus_days = activation.get("applied_promo_bonus_days", 0) if activation else 0
|
||||
|
||||
inviter_name: Optional[str] = None
|
||||
if referral_bonus and referral_bonus.get("referee_new_end_date"):
|
||||
@@ -351,9 +345,7 @@ async def finalize_successful_payment(
|
||||
log_prefix=req.log_prefix,
|
||||
)
|
||||
|
||||
refreshed_payment = await payment_dal.get_payment_by_db_id(
|
||||
req.session, req.payment.payment_id
|
||||
)
|
||||
refreshed_payment = await payment_dal.get_payment_by_db_id(req.session, req.payment.payment_id)
|
||||
tariff_key = getattr(refreshed_payment or req.payment, "tariff_key", None)
|
||||
|
||||
await notify_admins_payment_received(
|
||||
|
||||
@@ -36,9 +36,7 @@ async def lookup_payment_by_order_or_provider_id(
|
||||
if payment_db_id is not None:
|
||||
payment = await payment_dal.get_payment_by_db_id(session, payment_db_id)
|
||||
if not payment and provider_payment_id:
|
||||
payment = await payment_dal.get_payment_by_provider_payment_id(
|
||||
session, provider_payment_id
|
||||
)
|
||||
payment = await payment_dal.get_payment_by_provider_payment_id(session, provider_payment_id)
|
||||
return payment
|
||||
|
||||
|
||||
@@ -54,9 +52,7 @@ async def notify_user_payment_failed(
|
||||
"""Send the localized ``payment_failed`` text to the user; never raises."""
|
||||
db_user = payment.user or await user_dal.get_user_by_id(session, payment.user_id)
|
||||
language = (
|
||||
db_user.language_code
|
||||
if db_user and db_user.language_code
|
||||
else settings.DEFAULT_LANGUAGE
|
||||
db_user.language_code if db_user and db_user.language_code else settings.DEFAULT_LANGUAGE
|
||||
)
|
||||
translator = make_translator(i18n, language)
|
||||
try:
|
||||
|
||||
@@ -323,9 +323,7 @@ async def create_webapp_payment(ctx: WebAppPaymentContext) -> web.Response:
|
||||
provider="telegram_stars",
|
||||
)
|
||||
payload_units = amounts.purchased_gb if amounts.traffic_sale else ctx.months
|
||||
payload = (
|
||||
f"{payment.payment_id}:{format_number_for_payload(payload_units)}:{ctx.sale_mode}"
|
||||
)
|
||||
payload = f"{payment.payment_id}:{format_number_for_payload(payload_units)}:{ctx.sale_mode}"
|
||||
prices = [LabeledPrice(label=ctx.description, amount=ctx.stars_price)]
|
||||
create_invoice_link = getattr(bot, "create_invoice_link", None)
|
||||
if callable(create_invoice_link):
|
||||
@@ -371,25 +369,64 @@ async def create_webapp_payment(ctx: WebAppPaymentContext) -> web.Response:
|
||||
|
||||
_PRESENTATION_MANIFEST = tuple(
|
||||
ProviderManifestField(
|
||||
key=key, type=type_, label=label, description=description,
|
||||
placeholder=placeholder, subsection="Telegram Stars",
|
||||
target="presentation", attr=attr,
|
||||
key=key,
|
||||
type=type_,
|
||||
label=label,
|
||||
description=description,
|
||||
placeholder=placeholder,
|
||||
subsection="Telegram Stars",
|
||||
target="presentation",
|
||||
attr=attr,
|
||||
)
|
||||
for key, type_, label, description, placeholder, attr in (
|
||||
("PAYMENT_STARS_WEBAPP_LABEL_RU", "string", "WebApp button text (RU)",
|
||||
"Custom Russian text shown in the Web App payment method button.", "", "WEBAPP_LABEL_RU"),
|
||||
("PAYMENT_STARS_WEBAPP_LABEL_EN", "string", "WebApp button text (EN)",
|
||||
"Custom English text shown in the Web App payment method button.", "", "WEBAPP_LABEL_EN"),
|
||||
("PAYMENT_STARS_WEBAPP_ICON", "icon", "WebApp button icon",
|
||||
"Lucide icon name rendered inside the Web App payment method button.",
|
||||
"Sparkles", "WEBAPP_ICON"),
|
||||
("PAYMENT_STARS_TELEGRAM_LABEL_RU", "string", "Telegram button text (RU)",
|
||||
"Custom Russian text shown in Telegram bot payment buttons.", "", "TELEGRAM_LABEL_RU"),
|
||||
("PAYMENT_STARS_TELEGRAM_LABEL_EN", "string", "Telegram button text (EN)",
|
||||
"Custom English text shown in Telegram bot payment buttons.", "", "TELEGRAM_LABEL_EN"),
|
||||
("PAYMENT_STARS_TELEGRAM_EMOJI", "string", "Telegram button emoji",
|
||||
"Emoji prepended to the Telegram bot payment button when customized.",
|
||||
"🌟", "TELEGRAM_EMOJI"),
|
||||
(
|
||||
"PAYMENT_STARS_WEBAPP_LABEL_RU",
|
||||
"string",
|
||||
"WebApp button text (RU)",
|
||||
"Custom Russian text shown in the Web App payment method button.",
|
||||
"",
|
||||
"WEBAPP_LABEL_RU",
|
||||
),
|
||||
(
|
||||
"PAYMENT_STARS_WEBAPP_LABEL_EN",
|
||||
"string",
|
||||
"WebApp button text (EN)",
|
||||
"Custom English text shown in the Web App payment method button.",
|
||||
"",
|
||||
"WEBAPP_LABEL_EN",
|
||||
),
|
||||
(
|
||||
"PAYMENT_STARS_WEBAPP_ICON",
|
||||
"icon",
|
||||
"WebApp button icon",
|
||||
"Lucide icon name rendered inside the Web App payment method button.",
|
||||
"Sparkles",
|
||||
"WEBAPP_ICON",
|
||||
),
|
||||
(
|
||||
"PAYMENT_STARS_TELEGRAM_LABEL_RU",
|
||||
"string",
|
||||
"Telegram button text (RU)",
|
||||
"Custom Russian text shown in Telegram bot payment buttons.",
|
||||
"",
|
||||
"TELEGRAM_LABEL_RU",
|
||||
),
|
||||
(
|
||||
"PAYMENT_STARS_TELEGRAM_LABEL_EN",
|
||||
"string",
|
||||
"Telegram button text (EN)",
|
||||
"Custom English text shown in Telegram bot payment buttons.",
|
||||
"",
|
||||
"TELEGRAM_LABEL_EN",
|
||||
),
|
||||
(
|
||||
"PAYMENT_STARS_TELEGRAM_EMOJI",
|
||||
"string",
|
||||
"Telegram button emoji",
|
||||
"Emoji prepended to the Telegram bot payment button when customized.",
|
||||
"🌟",
|
||||
"TELEGRAM_EMOJI",
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -542,50 +542,120 @@ def create_service(ctx: ServiceFactoryContext) -> WataService:
|
||||
|
||||
_PRESENTATION_MANIFEST = tuple(
|
||||
ProviderManifestField(
|
||||
key=key, type=type_, label=label, description=description,
|
||||
placeholder=placeholder, subsection="Wata",
|
||||
target="presentation", attr=attr,
|
||||
key=key,
|
||||
type=type_,
|
||||
label=label,
|
||||
description=description,
|
||||
placeholder=placeholder,
|
||||
subsection="Wata",
|
||||
target="presentation",
|
||||
attr=attr,
|
||||
)
|
||||
for key, type_, label, description, placeholder, attr in (
|
||||
("PAYMENT_WATA_WEBAPP_LABEL_RU", "string", "WebApp button text (RU)",
|
||||
"Custom Russian text shown in the Web App payment method button.", "", "WEBAPP_LABEL_RU"),
|
||||
("PAYMENT_WATA_WEBAPP_LABEL_EN", "string", "WebApp button text (EN)",
|
||||
"Custom English text shown in the Web App payment method button.", "", "WEBAPP_LABEL_EN"),
|
||||
("PAYMENT_WATA_WEBAPP_ICON", "icon", "WebApp button icon",
|
||||
"Lucide icon name rendered inside the Web App payment method button.",
|
||||
"WalletCards", "WEBAPP_ICON"),
|
||||
("PAYMENT_WATA_TELEGRAM_LABEL_RU", "string", "Telegram button text (RU)",
|
||||
"Custom Russian text shown in Telegram bot payment buttons.", "", "TELEGRAM_LABEL_RU"),
|
||||
("PAYMENT_WATA_TELEGRAM_LABEL_EN", "string", "Telegram button text (EN)",
|
||||
"Custom English text shown in Telegram bot payment buttons.", "", "TELEGRAM_LABEL_EN"),
|
||||
("PAYMENT_WATA_TELEGRAM_EMOJI", "string", "Telegram button emoji",
|
||||
"Emoji prepended to the Telegram bot payment button when customized.",
|
||||
"💳", "TELEGRAM_EMOJI"),
|
||||
(
|
||||
"PAYMENT_WATA_WEBAPP_LABEL_RU",
|
||||
"string",
|
||||
"WebApp button text (RU)",
|
||||
"Custom Russian text shown in the Web App payment method button.",
|
||||
"",
|
||||
"WEBAPP_LABEL_RU",
|
||||
),
|
||||
(
|
||||
"PAYMENT_WATA_WEBAPP_LABEL_EN",
|
||||
"string",
|
||||
"WebApp button text (EN)",
|
||||
"Custom English text shown in the Web App payment method button.",
|
||||
"",
|
||||
"WEBAPP_LABEL_EN",
|
||||
),
|
||||
(
|
||||
"PAYMENT_WATA_WEBAPP_ICON",
|
||||
"icon",
|
||||
"WebApp button icon",
|
||||
"Lucide icon name rendered inside the Web App payment method button.",
|
||||
"WalletCards",
|
||||
"WEBAPP_ICON",
|
||||
),
|
||||
(
|
||||
"PAYMENT_WATA_TELEGRAM_LABEL_RU",
|
||||
"string",
|
||||
"Telegram button text (RU)",
|
||||
"Custom Russian text shown in Telegram bot payment buttons.",
|
||||
"",
|
||||
"TELEGRAM_LABEL_RU",
|
||||
),
|
||||
(
|
||||
"PAYMENT_WATA_TELEGRAM_LABEL_EN",
|
||||
"string",
|
||||
"Telegram button text (EN)",
|
||||
"Custom English text shown in Telegram bot payment buttons.",
|
||||
"",
|
||||
"TELEGRAM_LABEL_EN",
|
||||
),
|
||||
(
|
||||
"PAYMENT_WATA_TELEGRAM_EMOJI",
|
||||
"string",
|
||||
"Telegram button emoji",
|
||||
"Emoji prepended to the Telegram bot payment button when customized.",
|
||||
"💳",
|
||||
"TELEGRAM_EMOJI",
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
_CONFIG_MANIFEST = (
|
||||
ProviderManifestField("WATA_ENABLED", "bool", "Enabled", subsection="Wata", attr="ENABLED"),
|
||||
ProviderManifestField("WATA_API_TOKEN", "string", "API token", subsection="Wata",
|
||||
secret=True, attr="API_TOKEN"),
|
||||
ProviderManifestField("WATA_BASE_URL", "url", "Base URL",
|
||||
placeholder="https://api.wata.pro/api/h2h",
|
||||
subsection="Wata", attr="BASE_URL"),
|
||||
ProviderManifestField("WATA_RETURN_URL", "url", "Return URL",
|
||||
subsection="Wata", attr="RETURN_URL"),
|
||||
ProviderManifestField("WATA_FAILED_URL", "url", "Failed URL",
|
||||
subsection="Wata", attr="FAILED_URL"),
|
||||
ProviderManifestField("WATA_PAYMENT_LINK_TTL_DAYS", "int", "Payment link lifetime (days)",
|
||||
description="1..30; Wata defaults to 3 days and allows up to 30 days.",
|
||||
subsection="Wata", min=1, max=30, attr="PAYMENT_LINK_TTL_DAYS"),
|
||||
ProviderManifestField("WATA_WEBHOOK_VERIFY_SIGNATURE", "bool", "Verify webhook signature",
|
||||
subsection="Wata", attr="WEBHOOK_VERIFY_SIGNATURE"),
|
||||
ProviderManifestField("WATA_PUBLIC_KEY", "text", "Webhook public key",
|
||||
description="Optional. If empty, the backend fetches it from Wata.",
|
||||
subsection="Wata", secret=True, attr="PUBLIC_KEY"),
|
||||
ProviderManifestField("WATA_TRUSTED_IPS", "string", "Trusted IPs",
|
||||
description="Comma-separated IP addresses accepted for Wata webhooks.",
|
||||
subsection="Wata", attr="TRUSTED_IPS"),
|
||||
ProviderManifestField(
|
||||
"WATA_API_TOKEN", "string", "API token", subsection="Wata", secret=True, attr="API_TOKEN"
|
||||
),
|
||||
ProviderManifestField(
|
||||
"WATA_BASE_URL",
|
||||
"url",
|
||||
"Base URL",
|
||||
placeholder="https://api.wata.pro/api/h2h",
|
||||
subsection="Wata",
|
||||
attr="BASE_URL",
|
||||
),
|
||||
ProviderManifestField(
|
||||
"WATA_RETURN_URL", "url", "Return URL", subsection="Wata", attr="RETURN_URL"
|
||||
),
|
||||
ProviderManifestField(
|
||||
"WATA_FAILED_URL", "url", "Failed URL", subsection="Wata", attr="FAILED_URL"
|
||||
),
|
||||
ProviderManifestField(
|
||||
"WATA_PAYMENT_LINK_TTL_DAYS",
|
||||
"int",
|
||||
"Payment link lifetime (days)",
|
||||
description="1..30; Wata defaults to 3 days and allows up to 30 days.",
|
||||
subsection="Wata",
|
||||
min=1,
|
||||
max=30,
|
||||
attr="PAYMENT_LINK_TTL_DAYS",
|
||||
),
|
||||
ProviderManifestField(
|
||||
"WATA_WEBHOOK_VERIFY_SIGNATURE",
|
||||
"bool",
|
||||
"Verify webhook signature",
|
||||
subsection="Wata",
|
||||
attr="WEBHOOK_VERIFY_SIGNATURE",
|
||||
),
|
||||
ProviderManifestField(
|
||||
"WATA_PUBLIC_KEY",
|
||||
"text",
|
||||
"Webhook public key",
|
||||
description="Optional. If empty, the backend fetches it from Wata.",
|
||||
subsection="Wata",
|
||||
secret=True,
|
||||
attr="PUBLIC_KEY",
|
||||
),
|
||||
ProviderManifestField(
|
||||
"WATA_TRUSTED_IPS",
|
||||
"string",
|
||||
"Trusted IPs",
|
||||
description="Comma-separated IP addresses accepted for Wata webhooks.",
|
||||
subsection="Wata",
|
||||
attr="TRUSTED_IPS",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -90,9 +90,7 @@ class YooKassaConfig(ProviderEnvConfig):
|
||||
AUTOPAYMENTS_ENABLED: bool = Field(default=False)
|
||||
AUTOPAYMENTS_REQUIRE_CARD_BINDING: bool = Field(default=True)
|
||||
|
||||
@field_validator(
|
||||
"SHOP_ID", "SECRET_KEY", "RETURN_URL", "DEFAULT_RECEIPT_EMAIL", mode="before"
|
||||
)
|
||||
@field_validator("SHOP_ID", "SECRET_KEY", "RETURN_URL", "DEFAULT_RECEIPT_EMAIL", mode="before")
|
||||
@classmethod
|
||||
def _strip_optional(cls, v):
|
||||
if isinstance(v, str) and not v.strip():
|
||||
@@ -147,7 +145,9 @@ class YooKassaService:
|
||||
self.config = config or YooKassaConfig()
|
||||
self._bot_username_for_default_return = bot_username_for_default_return
|
||||
self._configured_return_url_override = configured_return_url
|
||||
self._sdk_configured_for = None # (shop_id, secret_key) currently loaded into the global SDK
|
||||
self._sdk_configured_for = (
|
||||
None # (shop_id, secret_key) currently loaded into the global SDK
|
||||
)
|
||||
|
||||
if not self.configured:
|
||||
if not self.config.ENABLED:
|
||||
@@ -1214,9 +1214,7 @@ async def _initiate_yk_payment(
|
||||
"description": payment_description,
|
||||
"subscription_duration_months": int(months) if sale_base == "subscription" else None,
|
||||
"sale_mode": sale_base,
|
||||
"tariff_key": sale_mode.split("@", 1)[1].split("|", 1)[0]
|
||||
if "@" in sale_mode
|
||||
else None,
|
||||
"tariff_key": sale_mode.split("@", 1)[1].split("|", 1)[0] if "@" in sale_mode else None,
|
||||
"purchased_gb": float(months)
|
||||
if sale_base in {"traffic", "traffic_package", "topup", "premium_topup"}
|
||||
else None,
|
||||
@@ -2505,7 +2503,9 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
def create_service(ctx: ServiceFactoryContext) -> YooKassaService:
|
||||
bundle = ctx.config_for("yookassa_service")
|
||||
config = bundle.config if bundle and isinstance(bundle.config, YooKassaConfig) else YooKassaConfig()
|
||||
config = (
|
||||
bundle.config if bundle and isinstance(bundle.config, YooKassaConfig) else YooKassaConfig()
|
||||
)
|
||||
return YooKassaService(
|
||||
shop_id=config.SHOP_ID,
|
||||
secret_key=config.SECRET_KEY,
|
||||
@@ -2516,12 +2516,7 @@ def create_service(ctx: ServiceFactoryContext) -> YooKassaService:
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
async def create_webapp_payment(ctx: WebAppPaymentContext) -> web.Response:
|
||||
settings = ctx.request.app["settings"]
|
||||
service: YooKassaService = ctx.request.app["yookassa_service"]
|
||||
if not service or not service.configured:
|
||||
return payment_unavailable()
|
||||
@@ -2588,49 +2583,116 @@ async def create_webapp_payment(ctx: WebAppPaymentContext) -> web.Response:
|
||||
|
||||
_PRESENTATION_MANIFEST = tuple(
|
||||
ProviderManifestField(
|
||||
key=key, type=type_, label=label, description=description,
|
||||
placeholder=placeholder, subsection="YooKassa",
|
||||
target="presentation", attr=attr,
|
||||
key=key,
|
||||
type=type_,
|
||||
label=label,
|
||||
description=description,
|
||||
placeholder=placeholder,
|
||||
subsection="YooKassa",
|
||||
target="presentation",
|
||||
attr=attr,
|
||||
)
|
||||
for key, type_, label, description, placeholder, attr in (
|
||||
("PAYMENT_YOOKASSA_WEBAPP_LABEL_RU", "string", "WebApp button text (RU)",
|
||||
"Custom Russian text shown in the Web App payment method button.", "", "WEBAPP_LABEL_RU"),
|
||||
("PAYMENT_YOOKASSA_WEBAPP_LABEL_EN", "string", "WebApp button text (EN)",
|
||||
"Custom English text shown in the Web App payment method button.", "", "WEBAPP_LABEL_EN"),
|
||||
("PAYMENT_YOOKASSA_WEBAPP_ICON", "icon", "WebApp button icon",
|
||||
"Lucide icon name rendered inside the Web App payment method button.",
|
||||
"CreditCard", "WEBAPP_ICON"),
|
||||
("PAYMENT_YOOKASSA_TELEGRAM_LABEL_RU", "string", "Telegram button text (RU)",
|
||||
"Custom Russian text shown in Telegram bot payment buttons.", "", "TELEGRAM_LABEL_RU"),
|
||||
("PAYMENT_YOOKASSA_TELEGRAM_LABEL_EN", "string", "Telegram button text (EN)",
|
||||
"Custom English text shown in Telegram bot payment buttons.", "", "TELEGRAM_LABEL_EN"),
|
||||
("PAYMENT_YOOKASSA_TELEGRAM_EMOJI", "string", "Telegram button emoji",
|
||||
"Emoji prepended to the Telegram bot payment button when customized.",
|
||||
"💳", "TELEGRAM_EMOJI"),
|
||||
(
|
||||
"PAYMENT_YOOKASSA_WEBAPP_LABEL_RU",
|
||||
"string",
|
||||
"WebApp button text (RU)",
|
||||
"Custom Russian text shown in the Web App payment method button.",
|
||||
"",
|
||||
"WEBAPP_LABEL_RU",
|
||||
),
|
||||
(
|
||||
"PAYMENT_YOOKASSA_WEBAPP_LABEL_EN",
|
||||
"string",
|
||||
"WebApp button text (EN)",
|
||||
"Custom English text shown in the Web App payment method button.",
|
||||
"",
|
||||
"WEBAPP_LABEL_EN",
|
||||
),
|
||||
(
|
||||
"PAYMENT_YOOKASSA_WEBAPP_ICON",
|
||||
"icon",
|
||||
"WebApp button icon",
|
||||
"Lucide icon name rendered inside the Web App payment method button.",
|
||||
"CreditCard",
|
||||
"WEBAPP_ICON",
|
||||
),
|
||||
(
|
||||
"PAYMENT_YOOKASSA_TELEGRAM_LABEL_RU",
|
||||
"string",
|
||||
"Telegram button text (RU)",
|
||||
"Custom Russian text shown in Telegram bot payment buttons.",
|
||||
"",
|
||||
"TELEGRAM_LABEL_RU",
|
||||
),
|
||||
(
|
||||
"PAYMENT_YOOKASSA_TELEGRAM_LABEL_EN",
|
||||
"string",
|
||||
"Telegram button text (EN)",
|
||||
"Custom English text shown in Telegram bot payment buttons.",
|
||||
"",
|
||||
"TELEGRAM_LABEL_EN",
|
||||
),
|
||||
(
|
||||
"PAYMENT_YOOKASSA_TELEGRAM_EMOJI",
|
||||
"string",
|
||||
"Telegram button emoji",
|
||||
"Emoji prepended to the Telegram bot payment button when customized.",
|
||||
"💳",
|
||||
"TELEGRAM_EMOJI",
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
_CONFIG_MANIFEST = (
|
||||
ProviderManifestField("YOOKASSA_ENABLED", "bool", "Включена",
|
||||
subsection="YooKassa", attr="ENABLED"),
|
||||
ProviderManifestField("YOOKASSA_SHOP_ID", "string", "Shop ID",
|
||||
subsection="YooKassa", attr="SHOP_ID"),
|
||||
ProviderManifestField("YOOKASSA_SECRET_KEY", "string", "Secret key",
|
||||
subsection="YooKassa", secret=True, attr="SECRET_KEY"),
|
||||
ProviderManifestField("YOOKASSA_RETURN_URL", "url", "Return URL",
|
||||
subsection="YooKassa", attr="RETURN_URL"),
|
||||
ProviderManifestField("YOOKASSA_DEFAULT_RECEIPT_EMAIL", "string",
|
||||
"Email для чека по умолчанию",
|
||||
subsection="YooKassa", attr="DEFAULT_RECEIPT_EMAIL"),
|
||||
ProviderManifestField("YOOKASSA_VAT_CODE", "int", "VAT code",
|
||||
description="1..6 в зависимости от системы налогообложения",
|
||||
subsection="YooKassa", min=1, max=6, attr="VAT_CODE"),
|
||||
ProviderManifestField("YOOKASSA_AUTOPAYMENTS_ENABLED", "bool",
|
||||
"Автоплатежи (recurring)",
|
||||
subsection="YooKassa", attr="AUTOPAYMENTS_ENABLED"),
|
||||
ProviderManifestField("YOOKASSA_AUTOPAYMENTS_REQUIRE_CARD_BINDING", "bool",
|
||||
"Принудительная привязка карты",
|
||||
subsection="YooKassa", attr="AUTOPAYMENTS_REQUIRE_CARD_BINDING"),
|
||||
ProviderManifestField(
|
||||
"YOOKASSA_ENABLED", "bool", "Включена", subsection="YooKassa", attr="ENABLED"
|
||||
),
|
||||
ProviderManifestField(
|
||||
"YOOKASSA_SHOP_ID", "string", "Shop ID", subsection="YooKassa", attr="SHOP_ID"
|
||||
),
|
||||
ProviderManifestField(
|
||||
"YOOKASSA_SECRET_KEY",
|
||||
"string",
|
||||
"Secret key",
|
||||
subsection="YooKassa",
|
||||
secret=True,
|
||||
attr="SECRET_KEY",
|
||||
),
|
||||
ProviderManifestField(
|
||||
"YOOKASSA_RETURN_URL", "url", "Return URL", subsection="YooKassa", attr="RETURN_URL"
|
||||
),
|
||||
ProviderManifestField(
|
||||
"YOOKASSA_DEFAULT_RECEIPT_EMAIL",
|
||||
"string",
|
||||
"Email для чека по умолчанию",
|
||||
subsection="YooKassa",
|
||||
attr="DEFAULT_RECEIPT_EMAIL",
|
||||
),
|
||||
ProviderManifestField(
|
||||
"YOOKASSA_VAT_CODE",
|
||||
"int",
|
||||
"VAT code",
|
||||
description="1..6 в зависимости от системы налогообложения",
|
||||
subsection="YooKassa",
|
||||
min=1,
|
||||
max=6,
|
||||
attr="VAT_CODE",
|
||||
),
|
||||
ProviderManifestField(
|
||||
"YOOKASSA_AUTOPAYMENTS_ENABLED",
|
||||
"bool",
|
||||
"Автоплатежи (recurring)",
|
||||
subsection="YooKassa",
|
||||
attr="AUTOPAYMENTS_ENABLED",
|
||||
),
|
||||
ProviderManifestField(
|
||||
"YOOKASSA_AUTOPAYMENTS_REQUIRE_CARD_BINDING",
|
||||
"bool",
|
||||
"Принудительная привязка карты",
|
||||
subsection="YooKassa",
|
||||
attr="AUTOPAYMENTS_REQUIRE_CARD_BINDING",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user