refactor: move severpay env-config into module
This commit is contained in:
@@ -336,32 +336,6 @@ SETTINGS_MANIFEST: List[SettingField] = [
|
|||||||
SettingField("PLATEGA_FAILED_URL", "url", "payments", "Failed URL", subsection="Platega"),
|
SettingField("PLATEGA_FAILED_URL", "url", "payments", "Failed URL", subsection="Platega"),
|
||||||
*_payment_presentation_fields("PLATEGA_SBP", "Platega SBP", default_icon="CreditCard"),
|
*_payment_presentation_fields("PLATEGA_SBP", "Platega SBP", default_icon="CreditCard"),
|
||||||
*_payment_presentation_fields("PLATEGA_CRYPTO", "Platega Crypto", default_icon="Bitcoin"),
|
*_payment_presentation_fields("PLATEGA_CRYPTO", "Platega Crypto", default_icon="Bitcoin"),
|
||||||
# SeverPay
|
|
||||||
SettingField("SEVERPAY_ENABLED", "bool", "payments", "Включена", subsection="SeverPay"),
|
|
||||||
SettingField("SEVERPAY_MID", "int", "payments", "MID", subsection="SeverPay"),
|
|
||||||
SettingField(
|
|
||||||
"SEVERPAY_TOKEN", "string", "payments", "Token", subsection="SeverPay", secret=True
|
|
||||||
),
|
|
||||||
SettingField(
|
|
||||||
"SEVERPAY_BASE_URL",
|
|
||||||
"url",
|
|
||||||
"payments",
|
|
||||||
"Base URL",
|
|
||||||
placeholder="https://severpay.io/api/merchant",
|
|
||||||
subsection="SeverPay",
|
|
||||||
),
|
|
||||||
SettingField("SEVERPAY_RETURN_URL", "url", "payments", "Return URL", subsection="SeverPay"),
|
|
||||||
SettingField(
|
|
||||||
"SEVERPAY_LIFETIME_MINUTES",
|
|
||||||
"int",
|
|
||||||
"payments",
|
|
||||||
"Срок жизни ссылки (мин)",
|
|
||||||
"30..4320; пусто — значение провайдера",
|
|
||||||
subsection="SeverPay",
|
|
||||||
min=30,
|
|
||||||
max=4320,
|
|
||||||
),
|
|
||||||
*_payment_presentation_fields("SEVERPAY", "SeverPay", default_icon="CreditCard"),
|
|
||||||
# Wata
|
# Wata
|
||||||
SettingField("WATA_ENABLED", "bool", "payments", "Enabled", subsection="Wata"),
|
SettingField("WATA_ENABLED", "bool", "payments", "Enabled", subsection="Wata"),
|
||||||
SettingField(
|
SettingField(
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ from typing import Any, Dict, Optional, Tuple
|
|||||||
|
|
||||||
from aiogram import Bot, F, Router, types
|
from aiogram import Bot, F, Router, types
|
||||||
from aiohttp import web
|
from aiohttp import web
|
||||||
|
from pydantic import Field, field_validator
|
||||||
|
from pydantic_settings import SettingsConfigDict
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
from sqlalchemy.orm import sessionmaker
|
from sqlalchemy.orm import sessionmaker
|
||||||
|
|
||||||
@@ -16,7 +18,13 @@ from bot.services.subscription_service import SubscriptionService
|
|||||||
from config.settings import Settings
|
from config.settings import Settings
|
||||||
from db.dal import payment_dal
|
from db.dal import payment_dal
|
||||||
|
|
||||||
from .base import PaymentProviderSpec, ServiceFactoryContext, WebAppPaymentContext
|
from .base import (
|
||||||
|
PaymentProviderSpec,
|
||||||
|
ProviderEnvConfig,
|
||||||
|
ProviderManifestField,
|
||||||
|
ServiceFactoryContext,
|
||||||
|
WebAppPaymentContext,
|
||||||
|
)
|
||||||
from .shared import (
|
from .shared import (
|
||||||
HttpClientMixin,
|
HttpClientMixin,
|
||||||
PaymentSuccessRequest,
|
PaymentSuccessRequest,
|
||||||
@@ -43,12 +51,65 @@ from .shared import (
|
|||||||
_LOG = "severpay"
|
_LOG = "severpay"
|
||||||
|
|
||||||
|
|
||||||
|
class SeverPayConfig(ProviderEnvConfig):
|
||||||
|
model_config = SettingsConfigDict(
|
||||||
|
env_file=".env",
|
||||||
|
env_file_encoding="utf-8",
|
||||||
|
env_prefix="SEVERPAY_",
|
||||||
|
extra="ignore",
|
||||||
|
)
|
||||||
|
|
||||||
|
ENABLED: bool = Field(default=False)
|
||||||
|
MID: Optional[int] = None
|
||||||
|
TOKEN: Optional[str] = None
|
||||||
|
RETURN_URL: Optional[str] = None
|
||||||
|
BASE_URL: str = Field(default="https://severpay.io/api/merchant")
|
||||||
|
LIFETIME_MINUTES: Optional[int] = None
|
||||||
|
|
||||||
|
@field_validator("MID", "LIFETIME_MINUTES", mode="before")
|
||||||
|
@classmethod
|
||||||
|
def _empty_to_none_int(cls, v):
|
||||||
|
if isinstance(v, str):
|
||||||
|
v = v.strip()
|
||||||
|
if not v:
|
||||||
|
return None
|
||||||
|
return v
|
||||||
|
|
||||||
|
@field_validator("TOKEN", "RETURN_URL", mode="before")
|
||||||
|
@classmethod
|
||||||
|
def _strip_optional(cls, v):
|
||||||
|
if isinstance(v, str) and not v.strip():
|
||||||
|
return None
|
||||||
|
return v
|
||||||
|
|
||||||
|
@property
|
||||||
|
def webhook_path(self) -> str:
|
||||||
|
return "/webhook/severpay"
|
||||||
|
|
||||||
|
|
||||||
|
class SeverPayPresentation(ProviderEnvConfig):
|
||||||
|
model_config = SettingsConfigDict(
|
||||||
|
env_file=".env",
|
||||||
|
env_file_encoding="utf-8",
|
||||||
|
env_prefix="PAYMENT_SEVERPAY_",
|
||||||
|
extra="ignore",
|
||||||
|
)
|
||||||
|
|
||||||
|
WEBAPP_LABEL_RU: Optional[str] = None
|
||||||
|
WEBAPP_LABEL_EN: Optional[str] = None
|
||||||
|
WEBAPP_ICON: Optional[str] = None
|
||||||
|
TELEGRAM_LABEL_RU: Optional[str] = None
|
||||||
|
TELEGRAM_LABEL_EN: Optional[str] = None
|
||||||
|
TELEGRAM_EMOJI: Optional[str] = None
|
||||||
|
|
||||||
|
|
||||||
class SeverPayService(HttpClientMixin):
|
class SeverPayService(HttpClientMixin):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
*,
|
*,
|
||||||
bot: Bot,
|
bot: Bot,
|
||||||
settings: Settings,
|
settings: Settings,
|
||||||
|
config: SeverPayConfig,
|
||||||
i18n: JsonI18n,
|
i18n: JsonI18n,
|
||||||
async_session_factory: sessionmaker,
|
async_session_factory: sessionmaker,
|
||||||
subscription_service: SubscriptionService,
|
subscription_service: SubscriptionService,
|
||||||
@@ -57,22 +118,21 @@ class SeverPayService(HttpClientMixin):
|
|||||||
):
|
):
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
self.settings = settings
|
self.settings = settings
|
||||||
|
self.config = config
|
||||||
self.i18n = i18n
|
self.i18n = i18n
|
||||||
self.async_session_factory = async_session_factory
|
self.async_session_factory = async_session_factory
|
||||||
self.subscription_service = subscription_service
|
self.subscription_service = subscription_service
|
||||||
self.referral_service = referral_service
|
self.referral_service = referral_service
|
||||||
|
|
||||||
self.base_url = (settings.SEVERPAY_BASE_URL or "https://severpay.io/api/merchant").rstrip(
|
self.base_url = (config.BASE_URL or "https://severpay.io/api/merchant").rstrip("/")
|
||||||
"/"
|
self.mid = config.MID
|
||||||
)
|
self.token = config.TOKEN or ""
|
||||||
self.mid = settings.SEVERPAY_MID
|
self.return_url = config.RETURN_URL or f"https://t.me/{default_return_url}"
|
||||||
self.token = settings.SEVERPAY_TOKEN or ""
|
self.lifetime_minutes = config.LIFETIME_MINUTES
|
||||||
self.return_url = settings.SEVERPAY_RETURN_URL or f"https://t.me/{default_return_url}"
|
|
||||||
self.lifetime_minutes = settings.SEVERPAY_LIFETIME_MINUTES
|
|
||||||
|
|
||||||
self._init_http_client(total_timeout=15)
|
self._init_http_client(total_timeout=15)
|
||||||
|
|
||||||
self.configured: bool = bool(settings.SEVERPAY_ENABLED and self.mid and self.token)
|
self.configured: bool = bool(config.ENABLED and self.mid and self.token)
|
||||||
if not self.configured:
|
if not self.configured:
|
||||||
logging.warning(
|
logging.warning(
|
||||||
"SeverPayService initialized but not fully configured. Payments disabled."
|
"SeverPayService initialized but not fully configured. Payments disabled."
|
||||||
@@ -373,9 +433,12 @@ async def pay_severpay_callback_handler(
|
|||||||
|
|
||||||
|
|
||||||
def create_service(ctx: ServiceFactoryContext) -> SeverPayService:
|
def create_service(ctx: ServiceFactoryContext) -> SeverPayService:
|
||||||
|
bundle = ctx.config_for("severpay_service")
|
||||||
|
config = bundle.config if bundle and isinstance(bundle.config, SeverPayConfig) else SeverPayConfig()
|
||||||
return SeverPayService(
|
return SeverPayService(
|
||||||
bot=ctx.bot,
|
bot=ctx.bot,
|
||||||
settings=ctx.settings,
|
settings=ctx.settings,
|
||||||
|
config=config,
|
||||||
i18n=ctx.i18n,
|
i18n=ctx.i18n,
|
||||||
async_session_factory=ctx.async_session_factory,
|
async_session_factory=ctx.async_session_factory,
|
||||||
subscription_service=ctx.subscription_service,
|
subscription_service=ctx.subscription_service,
|
||||||
@@ -422,6 +485,47 @@ 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,
|
||||||
|
)
|
||||||
|
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"),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
_CONFIG_MANIFEST = (
|
||||||
|
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"),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
SPEC = PaymentProviderSpec(
|
SPEC = PaymentProviderSpec(
|
||||||
id="severpay",
|
id="severpay",
|
||||||
provider_key="severpay",
|
provider_key="severpay",
|
||||||
@@ -432,12 +536,15 @@ SPEC = PaymentProviderSpec(
|
|||||||
telegram_labels={"ru": "SeverPay", "en": "SeverPay"},
|
telegram_labels={"ru": "SeverPay", "en": "SeverPay"},
|
||||||
telegram_emoji="💳",
|
telegram_emoji="💳",
|
||||||
pending_status="pending_severpay",
|
pending_status="pending_severpay",
|
||||||
enabled=lambda settings: settings.SEVERPAY_ENABLED,
|
enabled=lambda config: bool(getattr(config, "ENABLED", False)),
|
||||||
service_key="severpay_service",
|
service_key="severpay_service",
|
||||||
callback_prefix="pay_severpay",
|
callback_prefix="pay_severpay",
|
||||||
router=router,
|
router=router,
|
||||||
create_service=create_service,
|
create_service=create_service,
|
||||||
webhook_path=lambda settings: settings.severpay_webhook_path,
|
webhook_path=lambda source: "/webhook/severpay",
|
||||||
webhook_route=severpay_webhook_route,
|
webhook_route=severpay_webhook_route,
|
||||||
create_webapp_payment=create_webapp_payment,
|
create_webapp_payment=create_webapp_payment,
|
||||||
|
config_class=SeverPayConfig,
|
||||||
|
presentation_class=SeverPayPresentation,
|
||||||
|
manifest_fields=_CONFIG_MANIFEST + _PRESENTATION_MANIFEST,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -56,12 +56,6 @@ class PaymentSettings(BaseModel):
|
|||||||
platega_crypto_method: int
|
platega_crypto_method: int
|
||||||
platega_return_url: Optional[str]
|
platega_return_url: Optional[str]
|
||||||
platega_failed_url: Optional[str]
|
platega_failed_url: Optional[str]
|
||||||
severpay_enabled: bool
|
|
||||||
severpay_mid: Optional[int]
|
|
||||||
severpay_token: Optional[str]
|
|
||||||
severpay_return_url: Optional[str]
|
|
||||||
severpay_base_url: str
|
|
||||||
severpay_lifetime_minutes: Optional[int]
|
|
||||||
wata_enabled: bool
|
wata_enabled: bool
|
||||||
wata_api_token: Optional[str]
|
wata_api_token: Optional[str]
|
||||||
wata_base_url: str
|
wata_base_url: str
|
||||||
@@ -254,16 +248,6 @@ class Settings(BaseSettings):
|
|||||||
description="Comma-separated FreeKassa webhook IP allowlist.",
|
description="Comma-separated FreeKassa webhook IP allowlist.",
|
||||||
)
|
)
|
||||||
|
|
||||||
SEVERPAY_ENABLED: bool = Field(default=False)
|
|
||||||
SEVERPAY_MID: Optional[int] = None
|
|
||||||
SEVERPAY_TOKEN: Optional[str] = None
|
|
||||||
SEVERPAY_RETURN_URL: Optional[str] = None
|
|
||||||
SEVERPAY_BASE_URL: str = Field(default="https://severpay.io/api/merchant")
|
|
||||||
SEVERPAY_LIFETIME_MINUTES: Optional[int] = Field(
|
|
||||||
default=None,
|
|
||||||
description="Lifetime of the payment link in minutes (30-4320, defaults to provider value)",
|
|
||||||
)
|
|
||||||
|
|
||||||
WATA_ENABLED: bool = Field(default=False)
|
WATA_ENABLED: bool = Field(default=False)
|
||||||
WATA_API_TOKEN: Optional[str] = None
|
WATA_API_TOKEN: Optional[str] = None
|
||||||
WATA_BASE_URL: str = Field(default="https://api.wata.pro/api/h2h")
|
WATA_BASE_URL: str = Field(default="https://api.wata.pro/api/h2h")
|
||||||
@@ -307,12 +291,6 @@ class Settings(BaseSettings):
|
|||||||
PAYMENT_PLATEGA_CRYPTO_TELEGRAM_LABEL_RU: Optional[str] = None
|
PAYMENT_PLATEGA_CRYPTO_TELEGRAM_LABEL_RU: Optional[str] = None
|
||||||
PAYMENT_PLATEGA_CRYPTO_TELEGRAM_LABEL_EN: Optional[str] = None
|
PAYMENT_PLATEGA_CRYPTO_TELEGRAM_LABEL_EN: Optional[str] = None
|
||||||
PAYMENT_PLATEGA_CRYPTO_TELEGRAM_EMOJI: Optional[str] = None
|
PAYMENT_PLATEGA_CRYPTO_TELEGRAM_EMOJI: Optional[str] = None
|
||||||
PAYMENT_SEVERPAY_WEBAPP_LABEL_RU: Optional[str] = None
|
|
||||||
PAYMENT_SEVERPAY_WEBAPP_LABEL_EN: Optional[str] = None
|
|
||||||
PAYMENT_SEVERPAY_WEBAPP_ICON: Optional[str] = None
|
|
||||||
PAYMENT_SEVERPAY_TELEGRAM_LABEL_RU: Optional[str] = None
|
|
||||||
PAYMENT_SEVERPAY_TELEGRAM_LABEL_EN: Optional[str] = None
|
|
||||||
PAYMENT_SEVERPAY_TELEGRAM_EMOJI: Optional[str] = None
|
|
||||||
PAYMENT_WATA_WEBAPP_LABEL_RU: Optional[str] = None
|
PAYMENT_WATA_WEBAPP_LABEL_RU: Optional[str] = None
|
||||||
PAYMENT_WATA_WEBAPP_LABEL_EN: Optional[str] = None
|
PAYMENT_WATA_WEBAPP_LABEL_EN: Optional[str] = None
|
||||||
PAYMENT_WATA_WEBAPP_ICON: Optional[str] = None
|
PAYMENT_WATA_WEBAPP_ICON: Optional[str] = None
|
||||||
@@ -602,12 +580,6 @@ class Settings(BaseSettings):
|
|||||||
platega_crypto_method=self.PLATEGA_CRYPTO_METHOD,
|
platega_crypto_method=self.PLATEGA_CRYPTO_METHOD,
|
||||||
platega_return_url=self.PLATEGA_RETURN_URL,
|
platega_return_url=self.PLATEGA_RETURN_URL,
|
||||||
platega_failed_url=self.PLATEGA_FAILED_URL,
|
platega_failed_url=self.PLATEGA_FAILED_URL,
|
||||||
severpay_enabled=self.SEVERPAY_ENABLED,
|
|
||||||
severpay_mid=self.SEVERPAY_MID,
|
|
||||||
severpay_token=self.SEVERPAY_TOKEN,
|
|
||||||
severpay_return_url=self.SEVERPAY_RETURN_URL,
|
|
||||||
severpay_base_url=self.SEVERPAY_BASE_URL,
|
|
||||||
severpay_lifetime_minutes=self.SEVERPAY_LIFETIME_MINUTES,
|
|
||||||
wata_enabled=self.WATA_ENABLED,
|
wata_enabled=self.WATA_ENABLED,
|
||||||
wata_api_token=self.WATA_API_TOKEN,
|
wata_api_token=self.WATA_API_TOKEN,
|
||||||
wata_base_url=self.WATA_BASE_URL,
|
wata_base_url=self.WATA_BASE_URL,
|
||||||
@@ -791,19 +763,6 @@ class Settings(BaseSettings):
|
|||||||
return f"{base.rstrip('/')}{self.freekassa_webhook_path}"
|
return f"{base.rstrip('/')}{self.freekassa_webhook_path}"
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@computed_field
|
|
||||||
@property
|
|
||||||
def severpay_webhook_path(self) -> str:
|
|
||||||
return "/webhook/severpay"
|
|
||||||
|
|
||||||
@computed_field
|
|
||||||
@property
|
|
||||||
def severpay_full_webhook_url(self) -> Optional[str]:
|
|
||||||
base = self.WEBHOOK_BASE_URL
|
|
||||||
if base:
|
|
||||||
return f"{base.rstrip('/')}{self.severpay_webhook_path}"
|
|
||||||
return None
|
|
||||||
|
|
||||||
@computed_field
|
@computed_field
|
||||||
@property
|
@property
|
||||||
def wata_webhook_path(self) -> str:
|
def wata_webhook_path(self) -> str:
|
||||||
@@ -1164,7 +1123,6 @@ class Settings(BaseSettings):
|
|||||||
"REQUIRED_CHANNEL_LINK",
|
"REQUIRED_CHANNEL_LINK",
|
||||||
"PLATEGA_RETURN_URL",
|
"PLATEGA_RETURN_URL",
|
||||||
"PLATEGA_FAILED_URL",
|
"PLATEGA_FAILED_URL",
|
||||||
"SEVERPAY_RETURN_URL",
|
|
||||||
"WATA_RETURN_URL",
|
"WATA_RETURN_URL",
|
||||||
"WATA_FAILED_URL",
|
"WATA_FAILED_URL",
|
||||||
"WATA_API_TOKEN",
|
"WATA_API_TOKEN",
|
||||||
@@ -1189,9 +1147,7 @@ class Settings(BaseSettings):
|
|||||||
return None
|
return None
|
||||||
return v
|
return v
|
||||||
|
|
||||||
@field_validator(
|
@field_validator("USER_HWID_DEVICE_LIMIT", mode="before")
|
||||||
"USER_HWID_DEVICE_LIMIT", "SEVERPAY_MID", "SEVERPAY_LIFETIME_MINUTES", mode="before"
|
|
||||||
)
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def validate_optional_int(cls, v):
|
def validate_optional_int(cls, v):
|
||||||
if isinstance(v, str):
|
if isinstance(v, str):
|
||||||
@@ -1297,11 +1253,6 @@ def get_settings() -> Settings:
|
|||||||
logging.warning(
|
logging.warning(
|
||||||
"CRITICAL: Platega is enabled but merchant credentials (PLATEGA_MERCHANT_ID/PLATEGA_SECRET) are missing. Platega payments will not work." # noqa: E501
|
"CRITICAL: Platega is enabled but merchant credentials (PLATEGA_MERCHANT_ID/PLATEGA_SECRET) are missing. Platega payments will not work." # noqa: E501
|
||||||
)
|
)
|
||||||
if _settings_instance.SEVERPAY_ENABLED:
|
|
||||||
if not _settings_instance.SEVERPAY_MID or not _settings_instance.SEVERPAY_TOKEN:
|
|
||||||
logging.warning(
|
|
||||||
"CRITICAL: SeverPay is enabled but MID or TOKEN is missing. SeverPay payments will not work." # noqa: E501
|
|
||||||
)
|
|
||||||
if _settings_instance.WATA_ENABLED:
|
if _settings_instance.WATA_ENABLED:
|
||||||
if not _settings_instance.WATA_API_TOKEN:
|
if not _settings_instance.WATA_API_TOKEN:
|
||||||
logging.warning(
|
logging.warning(
|
||||||
|
|||||||
Reference in New Issue
Block a user