refactor: payments providers
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import Any, Awaitable, Callable, Mapping, Optional, Sequence
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class ServiceFactoryContext:
|
||||
settings: Any
|
||||
bot: Any
|
||||
async_session_factory: Any
|
||||
i18n: Any
|
||||
bot_username_for_default_return: str
|
||||
subscription_service: Any
|
||||
referral_service: Any
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class WebAppPaymentContext:
|
||||
request: Any
|
||||
session: Any
|
||||
user_id: int
|
||||
method: str
|
||||
months: Any
|
||||
price: float
|
||||
stars_price: Optional[int]
|
||||
description: str
|
||||
sale_mode: str
|
||||
traffic_gb: Optional[float] = None
|
||||
|
||||
|
||||
EnabledPredicate = Callable[[Any], bool]
|
||||
ServiceFactory = Callable[[ServiceFactoryContext], Any]
|
||||
WebhookPathGetter = Callable[[Any], str]
|
||||
WebhookRoute = Callable[[Any], Awaitable[Any]]
|
||||
WebAppPaymentFactory = Callable[[WebAppPaymentContext], Awaitable[Any]]
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class PaymentProviderSpec:
|
||||
id: str
|
||||
provider_key: str
|
||||
label: str
|
||||
pending_status: str
|
||||
enabled: EnabledPredicate
|
||||
service_key: Optional[str] = None
|
||||
button_text_key: Optional[str] = None
|
||||
callback_prefix: Optional[str] = None
|
||||
webapp_label: Optional[str] = None
|
||||
webapp_labels: Optional[Mapping[str, str]] = None
|
||||
telegram_labels: Optional[Mapping[str, str]] = None
|
||||
aliases: Sequence[str] = ()
|
||||
router: Any = None
|
||||
create_service: Optional[ServiceFactory] = None
|
||||
webhook_path: Optional[WebhookPathGetter] = None
|
||||
webhook_route: Optional[WebhookRoute] = None
|
||||
webhook_requires_base_url: bool = False
|
||||
create_webapp_payment: Optional[WebAppPaymentFactory] = None
|
||||
requires_configured_service: bool = True
|
||||
price_source: str = "rub"
|
||||
emoji: str = "💳"
|
||||
webapp_icon: Optional[str] = None
|
||||
telegram_emoji: Optional[str] = None
|
||||
|
||||
@property
|
||||
def settings_key(self) -> str:
|
||||
return self.id.upper()
|
||||
|
||||
@property
|
||||
def default_telegram_emoji(self) -> str:
|
||||
return self.telegram_emoji or self.emoji
|
||||
|
||||
@property
|
||||
def method_ids(self) -> tuple[str, ...]:
|
||||
return (self.id, *tuple(self.aliases))
|
||||
|
||||
def is_enabled(self, settings: Any) -> bool:
|
||||
return bool(self.enabled(settings))
|
||||
|
||||
def is_service_configured(self, app: Any) -> bool:
|
||||
if not self.requires_configured_service:
|
||||
return True
|
||||
if not self.service_key:
|
||||
return True
|
||||
service = app.get(self.service_key) if hasattr(app, "get") else None
|
||||
return bool(service and getattr(service, "configured", False))
|
||||
|
||||
def is_visible(self, settings: Any, app: Any) -> bool:
|
||||
return self.is_enabled(settings) and self.is_service_configured(app)
|
||||
|
||||
def load_router(self) -> Any:
|
||||
return self.router
|
||||
|
||||
def load_webhook_route(self) -> Optional[WebhookRoute]:
|
||||
return self.webhook_route
|
||||
|
||||
def callback_data(
|
||||
self,
|
||||
*,
|
||||
value: str,
|
||||
rub_price: float,
|
||||
stars_price: Optional[int],
|
||||
sale_mode: str,
|
||||
) -> Optional[str]:
|
||||
if not self.callback_prefix:
|
||||
return None
|
||||
if self.price_source == "stars":
|
||||
if stars_price is None:
|
||||
return None
|
||||
price: Any = stars_price
|
||||
else:
|
||||
price = rub_price
|
||||
return f"{self.callback_prefix}:{value}:{price}:{sale_mode}"
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class PaymentProviderPresentation:
|
||||
webapp_label: str
|
||||
webapp_icon: Optional[str]
|
||||
telegram_label: str
|
||||
telegram_emoji: str
|
||||
telegram_customized: bool
|
||||
Reference in New Issue
Block a user