Add global payment request timeout setting
This commit is contained in:
@@ -348,6 +348,16 @@ SETTINGS_MANIFEST: List[SettingField] = [
|
|||||||
"Английская версия текста на этапе оплаты.",
|
"Английская версия текста на этапе оплаты.",
|
||||||
subsection="checkout",
|
subsection="checkout",
|
||||||
),
|
),
|
||||||
|
SettingField(
|
||||||
|
"PAYMENT_REQUEST_TIMEOUT_SECONDS",
|
||||||
|
"float",
|
||||||
|
"payments",
|
||||||
|
"Таймаут запроса к провайдеру",
|
||||||
|
"Максимальное общее время одного API-запроса к платёжному провайдеру, в секундах.",
|
||||||
|
optional=False,
|
||||||
|
min=1,
|
||||||
|
subsection="checkout",
|
||||||
|
),
|
||||||
# ─── Payment providers (toggles) ───────────────────────────────
|
# ─── Payment providers (toggles) ───────────────────────────────
|
||||||
# Common
|
# Common
|
||||||
SettingField("STARS_ENABLED", "bool", "payments", "Telegram Stars", subsection="common"),
|
SettingField("STARS_ENABLED", "bool", "payments", "Telegram Stars", subsection="common"),
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ class FreeKassaService(HttpClientMixin):
|
|||||||
self.default_currency: str = default_payment_currency_code_for_settings(settings).upper()
|
self.default_currency: str = default_payment_currency_code_for_settings(settings).upper()
|
||||||
|
|
||||||
self.api_base_url: str = "https://api.fk.life/v1"
|
self.api_base_url: str = "https://api.fk.life/v1"
|
||||||
self._init_http_client(total_timeout=15)
|
self._init_http_client(total_timeout=self.settings.PAYMENT_REQUEST_TIMEOUT_SECONDS)
|
||||||
self._nonce_lock = asyncio.Lock()
|
self._nonce_lock = asyncio.Lock()
|
||||||
self._last_nonce = int(time.time() * 1000)
|
self._last_nonce = int(time.time() * 1000)
|
||||||
|
|
||||||
|
|||||||
@@ -243,7 +243,7 @@ class HeleketService(HttpClientMixin):
|
|||||||
self.referral_service = referral_service
|
self.referral_service = referral_service
|
||||||
self._default_return_url = default_return_url
|
self._default_return_url = default_return_url
|
||||||
|
|
||||||
self._init_http_client(total_timeout=20)
|
self._init_http_client(total_timeout=self.settings.PAYMENT_REQUEST_TIMEOUT_SECONDS)
|
||||||
if not self.configured:
|
if not self.configured:
|
||||||
logging.warning(
|
logging.warning(
|
||||||
"HeleketService initialized but not fully configured. Payments disabled."
|
"HeleketService initialized but not fully configured. Payments disabled."
|
||||||
|
|||||||
@@ -369,7 +369,7 @@ class PaykillaService(HttpClientMixin):
|
|||||||
self.referral_service = referral_service
|
self.referral_service = referral_service
|
||||||
self._default_return_url = default_return_url
|
self._default_return_url = default_return_url
|
||||||
|
|
||||||
self._init_http_client(total_timeout=20)
|
self._init_http_client(total_timeout=self.settings.PAYMENT_REQUEST_TIMEOUT_SECONDS)
|
||||||
if not self.configured:
|
if not self.configured:
|
||||||
logging.warning(
|
logging.warning(
|
||||||
"PaykillaService initialized but not fully configured. Payments disabled."
|
"PaykillaService initialized but not fully configured. Payments disabled."
|
||||||
|
|||||||
@@ -157,7 +157,7 @@ class PlategaService(HttpClientMixin):
|
|||||||
self.referral_service = referral_service
|
self.referral_service = referral_service
|
||||||
self._default_return_url = default_return_url
|
self._default_return_url = default_return_url
|
||||||
|
|
||||||
self._init_http_client(total_timeout=60)
|
self._init_http_client(total_timeout=self.settings.PAYMENT_REQUEST_TIMEOUT_SECONDS)
|
||||||
if not self.configured:
|
if not self.configured:
|
||||||
logging.warning(
|
logging.warning(
|
||||||
"PlategaService initialized but not fully configured. Payments disabled."
|
"PlategaService initialized but not fully configured. Payments disabled."
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ class SeverPayService(HttpClientMixin):
|
|||||||
self.referral_service = referral_service
|
self.referral_service = referral_service
|
||||||
self._default_return_url = default_return_url
|
self._default_return_url = default_return_url
|
||||||
|
|
||||||
self._init_http_client(total_timeout=15)
|
self._init_http_client(total_timeout=self.settings.PAYMENT_REQUEST_TIMEOUT_SECONDS)
|
||||||
|
|
||||||
if not self.configured:
|
if not self.configured:
|
||||||
logging.warning(
|
logging.warning(
|
||||||
|
|||||||
@@ -206,7 +206,7 @@ class WataService(HttpClientMixin):
|
|||||||
self._default_return_url = default_return_url
|
self._default_return_url = default_return_url
|
||||||
self._cached_public_key_pem = None # populated by webhook on first verify
|
self._cached_public_key_pem = None # populated by webhook on first verify
|
||||||
|
|
||||||
self._init_http_client(total_timeout=10)
|
self._init_http_client(total_timeout=self.settings.PAYMENT_REQUEST_TIMEOUT_SECONDS)
|
||||||
if not self.configured:
|
if not self.configured:
|
||||||
logging.warning("WataService initialized but not fully configured. Payments disabled.")
|
logging.warning("WataService initialized but not fully configured. Payments disabled.")
|
||||||
|
|
||||||
|
|||||||
@@ -319,6 +319,11 @@ class Settings(BaseSettings):
|
|||||||
default=DEFAULT_SUBSCRIPTION_PURCHASE_DESCRIPTION_EN,
|
default=DEFAULT_SUBSCRIPTION_PURCHASE_DESCRIPTION_EN,
|
||||||
description="English subscription description shown before purchase/renewal options.",
|
description="English subscription description shown before purchase/renewal options.",
|
||||||
)
|
)
|
||||||
|
PAYMENT_REQUEST_TIMEOUT_SECONDS: float = Field(
|
||||||
|
default=20,
|
||||||
|
ge=1,
|
||||||
|
description="Maximum total time for one payment provider API request, in seconds.",
|
||||||
|
)
|
||||||
|
|
||||||
MONTH_1_ENABLED: bool = Field(default=True, alias="1_MONTH_ENABLED")
|
MONTH_1_ENABLED: bool = Field(default=True, alias="1_MONTH_ENABLED")
|
||||||
MONTH_3_ENABLED: bool = Field(default=True, alias="3_MONTHS_ENABLED")
|
MONTH_3_ENABLED: bool = Field(default=True, alias="3_MONTHS_ENABLED")
|
||||||
|
|||||||
@@ -200,6 +200,7 @@
|
|||||||
| `PAYMENT_METHODS_ORDER` | Порядок кнопок оплаты: `severpay,wata,freekassa,platega,yookassa,stars,cryptopay,heleket,paykilla`. |
|
| `PAYMENT_METHODS_ORDER` | Порядок кнопок оплаты: `severpay,wata,freekassa,platega,yookassa,stars,cryptopay,heleket,paykilla`. |
|
||||||
| `SUBSCRIPTION_PURCHASE_DESCRIPTION_ENABLED` | Показывать описание подписки перед выбором срока. |
|
| `SUBSCRIPTION_PURCHASE_DESCRIPTION_ENABLED` | Показывать описание подписки перед выбором срока. |
|
||||||
| `SUBSCRIPTION_PURCHASE_DESCRIPTION_RU` / `SUBSCRIPTION_PURCHASE_DESCRIPTION_EN` | Локализованное описание подписки. |
|
| `SUBSCRIPTION_PURCHASE_DESCRIPTION_RU` / `SUBSCRIPTION_PURCHASE_DESCRIPTION_EN` | Локализованное описание подписки. |
|
||||||
|
| `PAYMENT_REQUEST_TIMEOUT_SECONDS` | Общий таймаут одного API-запроса к платёжному провайдеру, в секундах. По умолчанию `20`. |
|
||||||
| `PAYMENT_<METHOD>_WEBAPP_LABEL_RU` / `PAYMENT_<METHOD>_WEBAPP_LABEL_EN` | Текст кнопки провайдера в Web App. |
|
| `PAYMENT_<METHOD>_WEBAPP_LABEL_RU` / `PAYMENT_<METHOD>_WEBAPP_LABEL_EN` | Текст кнопки провайдера в Web App. |
|
||||||
| `PAYMENT_<METHOD>_WEBAPP_ICON` | Lucide-иконка кнопки в Web App. |
|
| `PAYMENT_<METHOD>_WEBAPP_ICON` | Lucide-иконка кнопки в Web App. |
|
||||||
| `PAYMENT_<METHOD>_TELEGRAM_LABEL_RU` / `PAYMENT_<METHOD>_TELEGRAM_LABEL_EN` | Текст кнопки в Telegram. |
|
| `PAYMENT_<METHOD>_TELEGRAM_LABEL_RU` / `PAYMENT_<METHOD>_TELEGRAM_LABEL_EN` | Текст кнопки в Telegram. |
|
||||||
|
|||||||
@@ -603,6 +603,26 @@
|
|||||||
"overridden": false,
|
"overridden": false,
|
||||||
"updated_at": null
|
"updated_at": null
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"key": "PAYMENT_REQUEST_TIMEOUT_SECONDS",
|
||||||
|
"type": "float",
|
||||||
|
"section": "payments",
|
||||||
|
"section_order": 4,
|
||||||
|
"subsection": "checkout",
|
||||||
|
"label": "Таймаут запроса к провайдеру",
|
||||||
|
"description": "Максимальное общее время одного API-запроса к платёжному провайдеру, в секундах.",
|
||||||
|
"i18n_label_key": "admin_settings_field_payment_request_timeout_seconds_label",
|
||||||
|
"i18n_description_key": "admin_settings_field_payment_request_timeout_seconds_description",
|
||||||
|
"i18n_subsection_key": "admin_settings_subsection_checkout",
|
||||||
|
"i18n_placeholder_key": null,
|
||||||
|
"placeholder": "",
|
||||||
|
"optional": false,
|
||||||
|
"secret": false,
|
||||||
|
"min": 1,
|
||||||
|
"value": "",
|
||||||
|
"overridden": false,
|
||||||
|
"updated_at": null
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"key": "STARS_ENABLED",
|
"key": "STARS_ENABLED",
|
||||||
"type": "bool",
|
"type": "bool",
|
||||||
|
|||||||
@@ -1170,6 +1170,7 @@
|
|||||||
"admin_settings_subsection_cryptopay": "CryptoPay",
|
"admin_settings_subsection_cryptopay": "CryptoPay",
|
||||||
"admin_settings_subsection_wata": "Wata",
|
"admin_settings_subsection_wata": "Wata",
|
||||||
"admin_settings_subsection_heleket": "Heleket",
|
"admin_settings_subsection_heleket": "Heleket",
|
||||||
|
"admin_settings_subsection_paykilla": "PayKilla",
|
||||||
"admin_settings_provider_webhook_url": "Webhook URL",
|
"admin_settings_provider_webhook_url": "Webhook URL",
|
||||||
"admin_settings_provider_webhook_url_hint": "Use this URL in the provider webhook settings.",
|
"admin_settings_provider_webhook_url_hint": "Use this URL in the provider webhook settings.",
|
||||||
"admin_settings_panel_webhook_url_hint": "Use this URL as WEBHOOK_URL in Remnawave Panel.",
|
"admin_settings_panel_webhook_url_hint": "Use this URL as WEBHOOK_URL in Remnawave Panel.",
|
||||||
@@ -1676,6 +1677,8 @@
|
|||||||
"admin_settings_field_subscription_purchase_description_ru_description": "Russian text shown during checkout.",
|
"admin_settings_field_subscription_purchase_description_ru_description": "Russian text shown during checkout.",
|
||||||
"admin_settings_field_subscription_purchase_description_en_label": "Subscription description (EN)",
|
"admin_settings_field_subscription_purchase_description_en_label": "Subscription description (EN)",
|
||||||
"admin_settings_field_subscription_purchase_description_en_description": "English text shown during checkout.",
|
"admin_settings_field_subscription_purchase_description_en_description": "English text shown during checkout.",
|
||||||
|
"admin_settings_field_payment_request_timeout_seconds_label": "Payment provider request timeout",
|
||||||
|
"admin_settings_field_payment_request_timeout_seconds_description": "Maximum total time for one payment provider API request, in seconds.",
|
||||||
"admin_settings_field_stars_enabled_label": "Stars Enabled",
|
"admin_settings_field_stars_enabled_label": "Stars Enabled",
|
||||||
"admin_settings_field_yookassa_enabled_label": "YooKassa Enabled",
|
"admin_settings_field_yookassa_enabled_label": "YooKassa Enabled",
|
||||||
"admin_settings_field_yookassa_shop_id_label": "YooKassa Shop ID",
|
"admin_settings_field_yookassa_shop_id_label": "YooKassa Shop ID",
|
||||||
|
|||||||
@@ -1170,6 +1170,7 @@
|
|||||||
"admin_settings_subsection_cryptopay": "CryptoPay",
|
"admin_settings_subsection_cryptopay": "CryptoPay",
|
||||||
"admin_settings_subsection_wata": "Wata",
|
"admin_settings_subsection_wata": "Wata",
|
||||||
"admin_settings_subsection_heleket": "Heleket",
|
"admin_settings_subsection_heleket": "Heleket",
|
||||||
|
"admin_settings_subsection_paykilla": "PayKilla",
|
||||||
"admin_settings_provider_webhook_url": "Webhook URL",
|
"admin_settings_provider_webhook_url": "Webhook URL",
|
||||||
"admin_settings_provider_webhook_url_hint": "Укажите этот адрес в настройках вебхуков провайдера.",
|
"admin_settings_provider_webhook_url_hint": "Укажите этот адрес в настройках вебхуков провайдера.",
|
||||||
"admin_settings_panel_webhook_url_hint": "Укажите этот адрес как WEBHOOK_URL в Remnawave Panel.",
|
"admin_settings_panel_webhook_url_hint": "Укажите этот адрес как WEBHOOK_URL в Remnawave Panel.",
|
||||||
@@ -1676,6 +1677,8 @@
|
|||||||
"admin_settings_field_subscription_purchase_description_ru_description": "Русская версия текста на этапе оплаты.",
|
"admin_settings_field_subscription_purchase_description_ru_description": "Русская версия текста на этапе оплаты.",
|
||||||
"admin_settings_field_subscription_purchase_description_en_label": "Описание подписки (EN)",
|
"admin_settings_field_subscription_purchase_description_en_label": "Описание подписки (EN)",
|
||||||
"admin_settings_field_subscription_purchase_description_en_description": "Английская версия текста на этапе оплаты.",
|
"admin_settings_field_subscription_purchase_description_en_description": "Английская версия текста на этапе оплаты.",
|
||||||
|
"admin_settings_field_payment_request_timeout_seconds_label": "Таймаут запроса к провайдеру",
|
||||||
|
"admin_settings_field_payment_request_timeout_seconds_description": "Максимальное общее время одного API-запроса к платёжному провайдеру, в секундах.",
|
||||||
"admin_settings_field_stars_enabled_label": "Telegram Stars",
|
"admin_settings_field_stars_enabled_label": "Telegram Stars",
|
||||||
"admin_settings_field_yookassa_enabled_label": "Включена",
|
"admin_settings_field_yookassa_enabled_label": "Включена",
|
||||||
"admin_settings_field_yookassa_shop_id_label": "Shop ID",
|
"admin_settings_field_yookassa_shop_id_label": "Shop ID",
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ SUBSCRIPTION_PURCHASE_DESCRIPTION_SETTINGS = (
|
|||||||
"SUBSCRIPTION_PURCHASE_DESCRIPTION_ENABLED",
|
"SUBSCRIPTION_PURCHASE_DESCRIPTION_ENABLED",
|
||||||
"SUBSCRIPTION_PURCHASE_DESCRIPTION_RU",
|
"SUBSCRIPTION_PURCHASE_DESCRIPTION_RU",
|
||||||
"SUBSCRIPTION_PURCHASE_DESCRIPTION_EN",
|
"SUBSCRIPTION_PURCHASE_DESCRIPTION_EN",
|
||||||
|
"PAYMENT_REQUEST_TIMEOUT_SECONDS",
|
||||||
)
|
)
|
||||||
|
|
||||||
SUBSCRIPTION_GUIDE_SETTINGS = (
|
SUBSCRIPTION_GUIDE_SETTINGS = (
|
||||||
@@ -177,6 +178,11 @@ def test_support_settings_i18n_keys_exist_in_admin_locales():
|
|||||||
def test_subscription_purchase_description_settings_i18n_keys_exist():
|
def test_subscription_purchase_description_settings_i18n_keys_exist():
|
||||||
manifest = _manifest_by_key()
|
manifest = _manifest_by_key()
|
||||||
|
|
||||||
|
timeout_field = manifest["PAYMENT_REQUEST_TIMEOUT_SECONDS"]
|
||||||
|
assert timeout_field["type"] == "float"
|
||||||
|
assert timeout_field["optional"] is False
|
||||||
|
assert timeout_field["min"] == 1
|
||||||
|
|
||||||
for language in ("ru", "en"):
|
for language in ("ru", "en"):
|
||||||
messages = _locale(language)
|
messages = _locale(language)
|
||||||
for setting_key in SUBSCRIPTION_PURCHASE_DESCRIPTION_SETTINGS:
|
for setting_key in SUBSCRIPTION_PURCHASE_DESCRIPTION_SETTINGS:
|
||||||
|
|||||||
Reference in New Issue
Block a user