feat: add PayKilla payment provider
This commit is contained in:
@@ -16,7 +16,7 @@ Remnawave Minishop - Telegram-бот и Web App (Mini App) для продажи
|
|||||||
- Web App / Mini App с входом через Telegram или email;
|
- Web App / Mini App с входом через Telegram или email;
|
||||||
- встроенные инструкции установки в Mini App: личный экран `/install` и публичная ссылка `/s/<token>` для передачи инструкции;
|
- встроенные инструкции установки в Mini App: личный экран `/install` и публичная ссылка `/s/<token>` для передачи инструкции;
|
||||||
- пробный период, промокоды и реферальная программа;
|
- пробный период, промокоды и реферальная программа;
|
||||||
- оплата через YooKassa, FreeKassa, Platega, SeverPay, Wata, CryptoPay, Heleket и Telegram Stars;
|
- оплата через YooKassa, FreeKassa, Platega, SeverPay, Wata, CryptoPay, Heleket, PayKilla и Telegram Stars;
|
||||||
- тикеты поддержки в Web App и внешняя ссылка на поддержку;
|
- тикеты поддержки в Web App и внешняя ссылка на поддержку;
|
||||||
- раздел "Мои устройства" при включенном `MY_DEVICES_SECTION_ENABLED`.
|
- раздел "Мои устройства" при включенном `MY_DEVICES_SECTION_ENABLED`.
|
||||||
|
|
||||||
|
|||||||
@@ -369,7 +369,7 @@ SETTINGS_MANIFEST: List[SettingField] = [
|
|||||||
"string",
|
"string",
|
||||||
"payments",
|
"payments",
|
||||||
"Порядок методов оплаты",
|
"Порядок методов оплаты",
|
||||||
"Через запятую: severpay,freekassa,yookassa,platega,stars,cryptopay,heleket",
|
"Через запятую: severpay,freekassa,yookassa,platega,stars,cryptopay,heleket,paykilla",
|
||||||
subsection="common",
|
subsection="common",
|
||||||
),
|
),
|
||||||
# ─── Trial ─────────────────────────────────────────────────────
|
# ─── Trial ─────────────────────────────────────────────────────
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
from typing import Any, Dict, Iterable, List, Mapping, Optional
|
from typing import Any, Dict, Iterable, List, Mapping, Optional
|
||||||
|
|
||||||
from . import cryptopay, freekassa, heleket, platega, severpay, stars, wata, yookassa
|
from . import cryptopay, freekassa, heleket, paykilla, platega, severpay, stars, wata, yookassa
|
||||||
from .base import (
|
from .base import (
|
||||||
PaymentProviderPresentation,
|
PaymentProviderPresentation,
|
||||||
PaymentProviderSpec,
|
PaymentProviderSpec,
|
||||||
@@ -21,6 +21,7 @@ PAYMENT_PROVIDER_SPECS: tuple[PaymentProviderSpec, ...] = (
|
|||||||
stars.SPEC,
|
stars.SPEC,
|
||||||
cryptopay.SPEC,
|
cryptopay.SPEC,
|
||||||
heleket.SPEC,
|
heleket.SPEC,
|
||||||
|
paykilla.SPEC,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ class PaymentContextMixin:
|
|||||||
"severpay": "SeverPay",
|
"severpay": "SeverPay",
|
||||||
"wata": "Wata",
|
"wata": "Wata",
|
||||||
"cryptopay": "Crypto Pay",
|
"cryptopay": "Crypto Pay",
|
||||||
|
"paykilla": "PayKilla",
|
||||||
"telegram_stars": "Telegram Stars",
|
"telegram_stars": "Telegram Stars",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -305,7 +305,7 @@ class Settings(BaseSettings):
|
|||||||
STARS_ADMIN_ONLY_ENABLED: bool = Field(default=False)
|
STARS_ADMIN_ONLY_ENABLED: bool = Field(default=False)
|
||||||
PAYMENT_METHODS_ORDER: Optional[str] = Field(
|
PAYMENT_METHODS_ORDER: Optional[str] = Field(
|
||||||
default=None,
|
default=None,
|
||||||
description="Comma-separated list of payment methods to show (e.g., severpay,wata,freekassa,yookassa,platega,stars,cryptopay)", # noqa: E501
|
description="Comma-separated list of payment methods to show (e.g., severpay,wata,freekassa,yookassa,platega,stars,cryptopay,heleket,paykilla)", # noqa: E501
|
||||||
)
|
)
|
||||||
SUBSCRIPTION_PURCHASE_DESCRIPTION_ENABLED: bool = Field(
|
SUBSCRIPTION_PURCHASE_DESCRIPTION_ENABLED: bool = Field(
|
||||||
default=True,
|
default=True,
|
||||||
@@ -1026,6 +1026,7 @@ class Settings(BaseSettings):
|
|||||||
"stars",
|
"stars",
|
||||||
"cryptopay",
|
"cryptopay",
|
||||||
"heleket",
|
"heleket",
|
||||||
|
"paykilla",
|
||||||
]
|
]
|
||||||
# Make sure default_order itself includes every registered spec.
|
# Make sure default_order itself includes every registered spec.
|
||||||
for sid in spec_ids:
|
for sid in spec_ids:
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ SUPPORTED_REMNASHOP_PROVIDER_TYPES = {
|
|||||||
"TELEGRAM_STARS",
|
"TELEGRAM_STARS",
|
||||||
"YOOKASSA",
|
"YOOKASSA",
|
||||||
"HELEKET",
|
"HELEKET",
|
||||||
|
"PAYKILLA",
|
||||||
"CRYPTOPAY",
|
"CRYPTOPAY",
|
||||||
"FREEKASSA",
|
"FREEKASSA",
|
||||||
"PLATEGA",
|
"PLATEGA",
|
||||||
@@ -93,6 +94,7 @@ PAYMENT_WEBHOOK_PATHS = {
|
|||||||
"wata": "/webhook/wata",
|
"wata": "/webhook/wata",
|
||||||
"cryptopay": "/webhook/cryptopay",
|
"cryptopay": "/webhook/cryptopay",
|
||||||
"heleket": "/webhook/heleket",
|
"heleket": "/webhook/heleket",
|
||||||
|
"paykilla": "/webhook/paykilla",
|
||||||
"freekassa": "/webhook/freekassa",
|
"freekassa": "/webhook/freekassa",
|
||||||
"platega": "/webhook/platega",
|
"platega": "/webhook/platega",
|
||||||
}
|
}
|
||||||
@@ -477,6 +479,26 @@ def remnashop_payment_gateway_overrides(
|
|||||||
)
|
)
|
||||||
return _provider_mapping_result(gateway_type, ["heleket"], overrides, warnings)
|
return _provider_mapping_result(gateway_type, ["heleket"], overrides, warnings)
|
||||||
|
|
||||||
|
if gateway_type == "PAYKILLA":
|
||||||
|
_add_override(overrides, "PAYKILLA_ENABLED", active)
|
||||||
|
_add_override(
|
||||||
|
overrides,
|
||||||
|
"PAYKILLA_API_KEY",
|
||||||
|
settings.get("api_key") or settings.get("public_key") or settings.get("publicKey"),
|
||||||
|
)
|
||||||
|
_add_override(
|
||||||
|
overrides,
|
||||||
|
"PAYKILLA_SECRET_KEY",
|
||||||
|
settings.get("secret_key") or settings.get("secretKey"),
|
||||||
|
)
|
||||||
|
if currency and currency != "RUB":
|
||||||
|
warnings.append(
|
||||||
|
f"PayKilla source currency was {currency}; Minishop keeps payment currency "
|
||||||
|
"controlled by tariffs/default currency. Configure PAYKILLA_CURRENCY and "
|
||||||
|
"PAYKILLA_PAYMENT_CURRENCIES manually if this instance needs a different default."
|
||||||
|
)
|
||||||
|
return _provider_mapping_result(gateway_type, ["paykilla"], overrides, warnings)
|
||||||
|
|
||||||
if gateway_type == "FREEKASSA":
|
if gateway_type == "FREEKASSA":
|
||||||
_add_override(overrides, "FREEKASSA_ENABLED", active)
|
_add_override(overrides, "FREEKASSA_ENABLED", active)
|
||||||
_add_override(overrides, "FREEKASSA_MERCHANT_ID", settings.get("shop_id"))
|
_add_override(overrides, "FREEKASSA_MERCHANT_ID", settings.get("shop_id"))
|
||||||
@@ -539,6 +561,7 @@ def remnashop_post_migration_actions(
|
|||||||
"wata": "WATA merchant dashboard -> webhook/callback URL",
|
"wata": "WATA merchant dashboard -> webhook/callback URL",
|
||||||
"cryptopay": "CryptoBot/Crypto Pay app -> webhook URL",
|
"cryptopay": "CryptoBot/Crypto Pay app -> webhook URL",
|
||||||
"heleket": "Heleket merchant dashboard -> payment webhook/callback URL",
|
"heleket": "Heleket merchant dashboard -> payment webhook/callback URL",
|
||||||
|
"paykilla": "PayKilla Dashboard -> Settings -> Webhooks",
|
||||||
"freekassa": "FreeKassa shop settings -> notification/result URL",
|
"freekassa": "FreeKassa shop settings -> notification/result URL",
|
||||||
"platega": "Platega merchant/project settings -> webhook URL",
|
"platega": "Platega merchant/project settings -> webhook URL",
|
||||||
}.get(provider_id, "Payment provider dashboard -> webhook/callback URL"),
|
}.get(provider_id, "Payment provider dashboard -> webhook/callback URL"),
|
||||||
|
|||||||
@@ -197,7 +197,7 @@
|
|||||||
|
|
||||||
| Переменная | Назначение |
|
| Переменная | Назначение |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| `PAYMENT_METHODS_ORDER` | Порядок кнопок оплаты: `severpay,wata,freekassa,platega,yookassa,stars,cryptopay,heleket`. |
|
| `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_<METHOD>_WEBAPP_LABEL_RU` / `PAYMENT_<METHOD>_WEBAPP_LABEL_EN` | Текст кнопки провайдера в Web App. |
|
| `PAYMENT_<METHOD>_WEBAPP_LABEL_RU` / `PAYMENT_<METHOD>_WEBAPP_LABEL_EN` | Текст кнопки провайдера в Web App. |
|
||||||
@@ -213,6 +213,7 @@
|
|||||||
| `WATA_ENABLED` | Включает Wata. |
|
| `WATA_ENABLED` | Включает Wata. |
|
||||||
| `CRYPTOPAY_ENABLED` | Включает CryptoPay. |
|
| `CRYPTOPAY_ENABLED` | Включает CryptoPay. |
|
||||||
| `HELEKET_ENABLED` | Включает Heleket. |
|
| `HELEKET_ENABLED` | Включает Heleket. |
|
||||||
|
| `PAYKILLA_ENABLED` | Включает PayKilla. |
|
||||||
|
|
||||||
Конкретные ключи отображения:
|
Конкретные ключи отображения:
|
||||||
|
|
||||||
@@ -271,6 +272,12 @@ PAYMENT_HELEKET_WEBAPP_ICON
|
|||||||
PAYMENT_HELEKET_TELEGRAM_LABEL_RU
|
PAYMENT_HELEKET_TELEGRAM_LABEL_RU
|
||||||
PAYMENT_HELEKET_TELEGRAM_LABEL_EN
|
PAYMENT_HELEKET_TELEGRAM_LABEL_EN
|
||||||
PAYMENT_HELEKET_TELEGRAM_EMOJI
|
PAYMENT_HELEKET_TELEGRAM_EMOJI
|
||||||
|
PAYMENT_PAYKILLA_WEBAPP_LABEL_RU
|
||||||
|
PAYMENT_PAYKILLA_WEBAPP_LABEL_EN
|
||||||
|
PAYMENT_PAYKILLA_WEBAPP_ICON
|
||||||
|
PAYMENT_PAYKILLA_TELEGRAM_LABEL_RU
|
||||||
|
PAYMENT_PAYKILLA_TELEGRAM_LABEL_EN
|
||||||
|
PAYMENT_PAYKILLA_TELEGRAM_EMOJI
|
||||||
```
|
```
|
||||||
|
|
||||||
### YooKassa
|
### YooKassa
|
||||||
@@ -357,6 +364,33 @@ PAYMENT_HELEKET_TELEGRAM_EMOJI
|
|||||||
| `HELEKET_VERIFY_WEBHOOK_SIGNATURE` | Проверять подпись webhook. |
|
| `HELEKET_VERIFY_WEBHOOK_SIGNATURE` | Проверять подпись webhook. |
|
||||||
| `HELEKET_TRUSTED_IPS` | Список доверенных IP webhook-источников. |
|
| `HELEKET_TRUSTED_IPS` | Список доверенных IP webhook-источников. |
|
||||||
|
|
||||||
|
### PayKilla
|
||||||
|
|
||||||
|
Для приема оплат нужен API key типа **HMAC** с правом **INVOICE**. Право **WITHDRAWAL** для оплаты подписок не требуется; включайте его только для отдельной интеграции выплат.
|
||||||
|
|
||||||
|
Webhook настраивается в PayKilla Dashboard: **Settings -> Webhooks**. Укажите `WEBHOOK_BASE_URL` + `/webhook/paykilla`, например `https://bot.example.com/webhook/paykilla`. Включите события `INVOICE_PAID` и `INVOICE_EXPIRED` как минимум. Рекомендуемый набор галочек: `INVOICE_PAID`, `PAYMENT_COMPLETED`, `PAYMENT_FAILED`, `PAYMENT_OVERPAID`, `PAYMENT_UNDERPAID`, `PAYMENT_PARTIAL`, `INVOICE_EXPIRED`, `COMPLIANCE_FAILED`. Если хотите видеть промежуточные статусы в логах PayKilla, дополнительно включите `INVOICE_CREATED`, `PAYMENT_PENDING`, `TRANSACTION_CONFIRMED` и `TRANSACTION_FINAL`.
|
||||||
|
|
||||||
|
| Переменная | Назначение |
|
||||||
|
| --- | --- |
|
||||||
|
| `PAYKILLA_BASE_URL` | Базовый URL API, по умолчанию `https://account-api.paykilla.com`. |
|
||||||
|
| `PAYKILLA_WIDGET_URL` | URL hosted checkout, по умолчанию `https://gopay.paykilla.com`. |
|
||||||
|
| `PAYKILLA_API_KEY` / `PAYKILLA_V2_API_KEY` | Public HMAC key с правом `INVOICE`. |
|
||||||
|
| `PAYKILLA_SECRET_KEY` / `PAYKILLA_V2_SECRET_KEY` | Secret HMAC key для подписи API-запросов и проверки webhook. |
|
||||||
|
| `PAYKILLA_CURRENCY` | Валюта инвойса. Для RUB/USD/EUR/AED/GBP используется `FIAT_BASED`, для остальных - `FIXED_AMOUNT`. |
|
||||||
|
| `PAYKILLA_PAYMENT_CURRENCIES` | Crypto tickers для оплаты, например `USDTTRC,BTC,ETH`. |
|
||||||
|
| `PAYKILLA_SUPPORTED_CURRENCIES` | Валюты инвойса, разрешенные в этом магазине. |
|
||||||
|
| `PAYKILLA_INVOICE_TYPE` | Необязательный override: `FIAT_BASED`, `FIXED_AMOUNT` или `OPEN_AMOUNT`. |
|
||||||
|
| `PAYKILLA_RETURN_URL` | URL кнопки возврата на checkout-странице. |
|
||||||
|
| `PAYKILLA_SUCCESS_URL` | URL после успешной оплаты; используется с auto-redirect. |
|
||||||
|
| `PAYKILLA_CANCEL_URL` | URL после отмены оплаты. |
|
||||||
|
| `PAYKILLA_LIFETIME_SECONDS` | TTL инвойса, отправляется как `expiredAt`. |
|
||||||
|
| `PAYKILLA_RECV_WINDOW_MS` | `recvWindow` для подписанных API-запросов. |
|
||||||
|
| `PAYKILLA_USER_PAYS_SERVICE_FEE` | `true`, если пользователь оплачивает service fee. |
|
||||||
|
| `PAYKILLA_USER_PAYS_NETWORK_FEE` | `true`, если пользователь оплачивает network fee. |
|
||||||
|
| `PAYKILLA_VERIFY_WEBHOOK_SIGNATURE` | Проверять `X-API-SIGN` по raw body webhook. |
|
||||||
|
| `PAYKILLA_WEBHOOK_URL` | Точный публичный webhook URL для проверки подписи, если он отличается от `WEBHOOK_BASE_URL` + `/webhook/paykilla`. |
|
||||||
|
| `PAYKILLA_TRUSTED_IPS` | Необязательный список доверенных IP webhook-источников. |
|
||||||
|
|
||||||
## Тарифы и legacy-цены
|
## Тарифы и legacy-цены
|
||||||
|
|
||||||
Рекомендуемый способ настройки тарифов - раздел **Система -> Тарифы** в админке. Он сохраняет JSON в `TARIFFS_CONFIG_PATH`.
|
Рекомендуемый способ настройки тарифов - раздел **Система -> Тарифы** в админке. Он сохраняет JSON в `TARIFFS_CONFIG_PATH`.
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
| Wata | `WEBHOOK_BASE_URL` + `/webhook/wata` | Если включена проверка подписи, настройте `WATA_WEBHOOK_VERIFY_SIGNATURE` и `WATA_PUBLIC_KEY`. |
|
| Wata | `WEBHOOK_BASE_URL` + `/webhook/wata` | Если включена проверка подписи, настройте `WATA_WEBHOOK_VERIFY_SIGNATURE` и `WATA_PUBLIC_KEY`. |
|
||||||
| CryptoPay | `WEBHOOK_BASE_URL` + `/webhook/cryptopay` | Указывается в настройках Crypto Bot / CryptoPay webhook. |
|
| CryptoPay | `WEBHOOK_BASE_URL` + `/webhook/cryptopay` | Указывается в настройках Crypto Bot / CryptoPay webhook. |
|
||||||
| Heleket | `WEBHOOK_BASE_URL` + `/webhook/heleket` | При необходимости включите `HELEKET_VERIFY_WEBHOOK_SIGNATURE` и `HELEKET_TRUSTED_IPS`. |
|
| Heleket | `WEBHOOK_BASE_URL` + `/webhook/heleket` | При необходимости включите `HELEKET_VERIFY_WEBHOOK_SIGNATURE` и `HELEKET_TRUSTED_IPS`. |
|
||||||
|
| PayKilla | `WEBHOOK_BASE_URL` + `/webhook/paykilla` | Указывается в PayKilla Dashboard -> Settings -> Webhooks; включите события оплаты инвойсов. |
|
||||||
| Telegram Stars | Отдельный платежный webhook не нужен | Stars-события приходят через webhook Telegram-бота: `WEBHOOK_BASE_URL` + `/tg/webhook`. |
|
| Telegram Stars | Отдельный платежный webhook не нужен | Stars-события приходят через webhook Telegram-бота: `WEBHOOK_BASE_URL` + `/tg/webhook`. |
|
||||||
|
|
||||||
После настройки сделайте тестовый платеж и проверьте, что в логах `backend` видно входящий `POST` на нужный путь. Если провайдер сообщает, что адрес недоступен, сначала проверьте DNS/HTTPS и reverse proxy для `WEBHOOK_BASE_URL`, затем убедитесь, что путь начинается ровно с `/webhook/...` без `/api`, `/auth` и frontend-домена.
|
После настройки сделайте тестовый платеж и проверьте, что в логах `backend` видно входящий `POST` на нужный путь. Если провайдер сообщает, что адрес недоступен, сначала проверьте DNS/HTTPS и reverse proxy для `WEBHOOK_BASE_URL`, затем убедитесь, что путь начинается ровно с `/webhook/...` без `/api`, `/auth` и frontend-домена.
|
||||||
@@ -153,6 +154,37 @@ Heleket используется для крипто-инвойсов с отд
|
|||||||
|
|
||||||
Справочник переменных: [Heleket](../configuration/env-vars.md#heleket).
|
Справочник переменных: [Heleket](../configuration/env-vars.md#heleket).
|
||||||
|
|
||||||
|
## PayKilla
|
||||||
|
|
||||||
|
PayKilla используется для крипто-инвойсов V2 через hosted checkout `https://gopay.paykilla.com/{invoice_id}`. API-запросы подписываются HMAC-SHA256, webhook проверяется по заголовку `X-API-SIGN` и raw body.
|
||||||
|
|
||||||
|
Какие полномочия нужны API key:
|
||||||
|
|
||||||
|
1. В PayKilla Dashboard откройте **Settings -> API keys**.
|
||||||
|
2. Создайте ключ типа **HMAC**.
|
||||||
|
3. Для приема оплат включите permission **INVOICE**.
|
||||||
|
4. Permission **WITHDRAWAL** не нужен для Minishop-платежей; не включайте его без отдельной необходимости выплат.
|
||||||
|
5. Сохраните `publicKey` в `PAYKILLA_API_KEY`, а `secretKey` в `PAYKILLA_SECRET_KEY`.
|
||||||
|
|
||||||
|
Как настроить webhook в PayKilla:
|
||||||
|
|
||||||
|
1. Откройте **Settings -> Webhooks**.
|
||||||
|
2. В URL укажите `WEBHOOK_BASE_URL` + `/webhook/paykilla`, например `https://bot.example.com/webhook/paykilla`.
|
||||||
|
3. Минимальные галочки: `INVOICE_PAID`, `INVOICE_EXPIRED`.
|
||||||
|
4. Рекомендуемые галочки для production: `INVOICE_PAID`, `PAYMENT_COMPLETED`, `PAYMENT_FAILED`, `PAYMENT_OVERPAID`, `PAYMENT_UNDERPAID`, `PAYMENT_PARTIAL`, `INVOICE_EXPIRED`, `COMPLIANCE_FAILED`.
|
||||||
|
5. Опционально включите `INVOICE_CREATED`, `PAYMENT_PENDING`, `TRANSACTION_CONFIRMED` и `TRANSACTION_FINAL`, если нужны промежуточные события в логах.
|
||||||
|
6. Оставьте `PAYKILLA_VERIFY_WEBHOOK_SIGNATURE=True`. Если публичный URL у PayKilla отличается от `WEBHOOK_BASE_URL` + `/webhook/paykilla`, задайте точное значение в `PAYKILLA_WEBHOOK_URL`.
|
||||||
|
|
||||||
|
Что настроить в Minishop:
|
||||||
|
|
||||||
|
1. Включите `PAYKILLA_ENABLED`.
|
||||||
|
2. Укажите `PAYKILLA_API_KEY` и `PAYKILLA_SECRET_KEY`.
|
||||||
|
3. Проверьте `PAYKILLA_CURRENCY` и `PAYKILLA_PAYMENT_CURRENCIES`, например `USDTTRC,BTC,ETH`.
|
||||||
|
4. При необходимости задайте `PAYKILLA_SUCCESS_URL`, `PAYKILLA_RETURN_URL` и `PAYKILLA_CANCEL_URL`.
|
||||||
|
5. Добавьте `paykilla` в `PAYMENT_METHODS_ORDER`, если хотите задать явный порядок кнопок.
|
||||||
|
|
||||||
|
Справочник переменных: [PayKilla](../configuration/env-vars.md#paykilla).
|
||||||
|
|
||||||
## Telegram Stars
|
## Telegram Stars
|
||||||
|
|
||||||
Telegram Stars используются напрямую и поддерживаются в legacy-ценах и JSON-каталоге тарифов.
|
Telegram Stars используются напрямую и поддерживаются в legacy-ценах и JSON-каталоге тарифов.
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ App, а не веб-кабинетом Remnashop. В Minishop `SUBSCRIPTION_MINI
|
|||||||
|
|
||||||
Платежные провайдеры берутся из таблицы Remnashop `payment_gateways`.
|
Платежные провайдеры берутся из таблицы Remnashop `payment_gateways`.
|
||||||
Поддерживаются и автоматически маппятся: Telegram Stars, YooKassa, WATA,
|
Поддерживаются и автоматически маппятся: Telegram Stars, YooKassa, WATA,
|
||||||
CryptoPay, Heleket, FreeKassa и Platega. Для них importer переносит флаги
|
CryptoPay, Heleket, PayKilla, FreeKassa и Platega. Для них importer переносит флаги
|
||||||
включения, API-ключи/merchant IDs и прямые технические параметры, без которых
|
включения, API-ключи/merchant IDs и прямые технические параметры, без которых
|
||||||
провайдер не сможет работать: YooKassa receipt email/VAT, FreeKassa second
|
провайдер не сможет работать: YooKassa receipt email/VAT, FreeKassa second
|
||||||
secret/payment method/server IP и Platega payment method.
|
secret/payment method/server IP и Platega payment method.
|
||||||
@@ -55,7 +55,8 @@ Provider currency и supported-currency ограничения не перено
|
|||||||
в Minishop валюта платежа управляется тарифами и `DEFAULT_CURRENCY_SYMBOL`.
|
в Minishop валюта платежа управляется тарифами и `DEFAULT_CURRENCY_SYMBOL`.
|
||||||
Если старый gateway Remnashop был настроен на нестандартную валюту, importer
|
Если старый gateway Remnashop был настроен на нестандартную валюту, importer
|
||||||
оставит предупреждение в JSON-сводке; проверьте `CRYPTOPAY_ASSET`,
|
оставит предупреждение в JSON-сводке; проверьте `CRYPTOPAY_ASSET`,
|
||||||
`HELEKET_CURRENCY`, `HELEKET_SUPPORTED_CURRENCIES` или
|
`HELEKET_CURRENCY`, `HELEKET_SUPPORTED_CURRENCIES`, `PAYKILLA_CURRENCY`,
|
||||||
|
`PAYKILLA_PAYMENT_CURRENCIES` или
|
||||||
`PLATEGA_SUPPORTED_CURRENCIES` вручную.
|
`PLATEGA_SUPPORTED_CURRENCIES` вручную.
|
||||||
|
|
||||||
Провайдеры YooMoney, Cryptomus, MulenPay, PayMaster, RoboKassa и UrlPay сейчас
|
Провайдеры YooMoney, Cryptomus, MulenPay, PayMaster, RoboKassa и UrlPay сейчас
|
||||||
@@ -77,6 +78,7 @@ Remnashop может хранить секреты в формате `enc_...`.
|
|||||||
- WATA webhook/callback URL: `WEBHOOK_BASE_URL` + `/webhook/wata`;
|
- WATA webhook/callback URL: `WEBHOOK_BASE_URL` + `/webhook/wata`;
|
||||||
- CryptoBot/Crypto Pay webhook URL: `WEBHOOK_BASE_URL` + `/webhook/cryptopay`;
|
- CryptoBot/Crypto Pay webhook URL: `WEBHOOK_BASE_URL` + `/webhook/cryptopay`;
|
||||||
- Heleket payment webhook/callback URL: `WEBHOOK_BASE_URL` + `/webhook/heleket`;
|
- Heleket payment webhook/callback URL: `WEBHOOK_BASE_URL` + `/webhook/heleket`;
|
||||||
|
- PayKilla webhook URL: `WEBHOOK_BASE_URL` + `/webhook/paykilla`;
|
||||||
- FreeKassa notification/result URL: `WEBHOOK_BASE_URL` + `/webhook/freekassa`;
|
- FreeKassa notification/result URL: `WEBHOOK_BASE_URL` + `/webhook/freekassa`;
|
||||||
- Platega webhook URL: `WEBHOOK_BASE_URL` + `/webhook/platega`;
|
- Platega webhook URL: `WEBHOOK_BASE_URL` + `/webhook/platega`;
|
||||||
- Telegram webhook `WEBHOOK_BASE_URL` + `/tg/webhook` выставляется ботом
|
- Telegram webhook `WEBHOOK_BASE_URL` + `/tg/webhook` выставляется ботом
|
||||||
|
|||||||
@@ -479,6 +479,11 @@ export const DEMO_DATASET = {
|
|||||||
name: "Heleket",
|
name: "Heleket",
|
||||||
icon: "CreditCard",
|
icon: "CreditCard",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: "paykilla",
|
||||||
|
name: "PayKilla",
|
||||||
|
icon: "Bitcoin",
|
||||||
|
},
|
||||||
],
|
],
|
||||||
referral: {
|
referral: {
|
||||||
code: "DEMO0001",
|
code: "DEMO0001",
|
||||||
|
|||||||
@@ -650,7 +650,7 @@
|
|||||||
"section_order": 4,
|
"section_order": 4,
|
||||||
"subsection": "common",
|
"subsection": "common",
|
||||||
"label": "Порядок методов оплаты",
|
"label": "Порядок методов оплаты",
|
||||||
"description": "Через запятую: severpay,freekassa,yookassa,platega,stars,cryptopay,heleket",
|
"description": "Через запятую: severpay,freekassa,yookassa,platega,stars,cryptopay,heleket,paykilla",
|
||||||
"i18n_label_key": "admin_settings_field_payment_methods_order_label",
|
"i18n_label_key": "admin_settings_field_payment_methods_order_label",
|
||||||
"i18n_description_key": "admin_settings_field_payment_methods_order_description",
|
"i18n_description_key": "admin_settings_field_payment_methods_order_description",
|
||||||
"i18n_subsection_key": "admin_settings_subsection_common",
|
"i18n_subsection_key": "admin_settings_subsection_common",
|
||||||
@@ -3839,6 +3839,692 @@
|
|||||||
"overridden": false,
|
"overridden": false,
|
||||||
"updated_at": null,
|
"updated_at": null,
|
||||||
"webhook_base_url_configured": false
|
"webhook_base_url_configured": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "PAYKILLA_ENABLED",
|
||||||
|
"type": "bool",
|
||||||
|
"section": "payments",
|
||||||
|
"section_order": 4,
|
||||||
|
"subsection": "PayKilla",
|
||||||
|
"label": "Enabled",
|
||||||
|
"description": "",
|
||||||
|
"i18n_label_key": "admin_settings_field_paykilla_enabled_label",
|
||||||
|
"i18n_description_key": null,
|
||||||
|
"i18n_subsection_key": "admin_settings_subsection_paykilla",
|
||||||
|
"i18n_placeholder_key": null,
|
||||||
|
"placeholder": "",
|
||||||
|
"optional": true,
|
||||||
|
"secret": false,
|
||||||
|
"mutually_exclusive_key": "PAYKILLA_ADMIN_ONLY_ENABLED",
|
||||||
|
"provider_id": "paykilla",
|
||||||
|
"provider_label": "PayKilla",
|
||||||
|
"webhook_provider_id": "paykilla",
|
||||||
|
"webhook_path": "/webhook/paykilla",
|
||||||
|
"webhook_requires_base_url": false,
|
||||||
|
"value": "",
|
||||||
|
"overridden": false,
|
||||||
|
"updated_at": null,
|
||||||
|
"webhook_base_url_configured": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "PAYKILLA_API_KEY",
|
||||||
|
"type": "string",
|
||||||
|
"section": "payments",
|
||||||
|
"section_order": 4,
|
||||||
|
"subsection": "PayKilla",
|
||||||
|
"label": "API key",
|
||||||
|
"description": "PayKilla public HMAC key with INVOICE permission.",
|
||||||
|
"i18n_label_key": "admin_settings_field_paykilla_api_key_label",
|
||||||
|
"i18n_description_key": "admin_settings_field_paykilla_api_key_description",
|
||||||
|
"i18n_subsection_key": "admin_settings_subsection_paykilla",
|
||||||
|
"i18n_placeholder_key": null,
|
||||||
|
"placeholder": "",
|
||||||
|
"optional": true,
|
||||||
|
"secret": true,
|
||||||
|
"provider_id": "paykilla",
|
||||||
|
"provider_label": "PayKilla",
|
||||||
|
"webhook_provider_id": "paykilla",
|
||||||
|
"webhook_path": "/webhook/paykilla",
|
||||||
|
"webhook_requires_base_url": false,
|
||||||
|
"value": "",
|
||||||
|
"overridden": false,
|
||||||
|
"updated_at": null,
|
||||||
|
"has_value": false,
|
||||||
|
"webhook_base_url_configured": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "PAYKILLA_SECRET_KEY",
|
||||||
|
"type": "string",
|
||||||
|
"section": "payments",
|
||||||
|
"section_order": 4,
|
||||||
|
"subsection": "PayKilla",
|
||||||
|
"label": "Secret key",
|
||||||
|
"description": "PayKilla HMAC secret key. Never expose it client-side.",
|
||||||
|
"i18n_label_key": "admin_settings_field_paykilla_secret_key_label",
|
||||||
|
"i18n_description_key": "admin_settings_field_paykilla_secret_key_description",
|
||||||
|
"i18n_subsection_key": "admin_settings_subsection_paykilla",
|
||||||
|
"i18n_placeholder_key": null,
|
||||||
|
"placeholder": "",
|
||||||
|
"optional": true,
|
||||||
|
"secret": true,
|
||||||
|
"provider_id": "paykilla",
|
||||||
|
"provider_label": "PayKilla",
|
||||||
|
"webhook_provider_id": "paykilla",
|
||||||
|
"webhook_path": "/webhook/paykilla",
|
||||||
|
"webhook_requires_base_url": false,
|
||||||
|
"value": "",
|
||||||
|
"overridden": false,
|
||||||
|
"updated_at": null,
|
||||||
|
"has_value": false,
|
||||||
|
"webhook_base_url_configured": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "PAYKILLA_BASE_URL",
|
||||||
|
"type": "url",
|
||||||
|
"section": "payments",
|
||||||
|
"section_order": 4,
|
||||||
|
"subsection": "PayKilla",
|
||||||
|
"label": "Base URL",
|
||||||
|
"description": "",
|
||||||
|
"i18n_label_key": "admin_settings_field_paykilla_base_url_label",
|
||||||
|
"i18n_description_key": null,
|
||||||
|
"i18n_subsection_key": "admin_settings_subsection_paykilla",
|
||||||
|
"i18n_placeholder_key": "admin_settings_field_paykilla_base_url_placeholder",
|
||||||
|
"placeholder": "https://account-api.paykilla.com",
|
||||||
|
"optional": true,
|
||||||
|
"secret": false,
|
||||||
|
"provider_id": "paykilla",
|
||||||
|
"provider_label": "PayKilla",
|
||||||
|
"webhook_provider_id": "paykilla",
|
||||||
|
"webhook_path": "/webhook/paykilla",
|
||||||
|
"webhook_requires_base_url": false,
|
||||||
|
"value": "",
|
||||||
|
"overridden": false,
|
||||||
|
"updated_at": null,
|
||||||
|
"webhook_base_url_configured": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "PAYKILLA_WIDGET_URL",
|
||||||
|
"type": "url",
|
||||||
|
"section": "payments",
|
||||||
|
"section_order": 4,
|
||||||
|
"subsection": "PayKilla",
|
||||||
|
"label": "Widget URL",
|
||||||
|
"description": "",
|
||||||
|
"i18n_label_key": "admin_settings_field_paykilla_widget_url_label",
|
||||||
|
"i18n_description_key": null,
|
||||||
|
"i18n_subsection_key": "admin_settings_subsection_paykilla",
|
||||||
|
"i18n_placeholder_key": "admin_settings_field_paykilla_widget_url_placeholder",
|
||||||
|
"placeholder": "https://gopay.paykilla.com",
|
||||||
|
"optional": true,
|
||||||
|
"secret": false,
|
||||||
|
"provider_id": "paykilla",
|
||||||
|
"provider_label": "PayKilla",
|
||||||
|
"webhook_provider_id": "paykilla",
|
||||||
|
"webhook_path": "/webhook/paykilla",
|
||||||
|
"webhook_requires_base_url": false,
|
||||||
|
"value": "",
|
||||||
|
"overridden": false,
|
||||||
|
"updated_at": null,
|
||||||
|
"webhook_base_url_configured": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "PAYKILLA_CURRENCY",
|
||||||
|
"type": "string",
|
||||||
|
"section": "payments",
|
||||||
|
"section_order": 4,
|
||||||
|
"subsection": "PayKilla",
|
||||||
|
"label": "Invoice currency",
|
||||||
|
"description": "Fiat or crypto invoice currency. FIAT_BASED is selected for RUB/USD/EUR/AED/GBP.",
|
||||||
|
"i18n_label_key": "admin_settings_field_paykilla_currency_label",
|
||||||
|
"i18n_description_key": "admin_settings_field_paykilla_currency_description",
|
||||||
|
"i18n_subsection_key": "admin_settings_subsection_paykilla",
|
||||||
|
"i18n_placeholder_key": "admin_settings_field_paykilla_currency_placeholder",
|
||||||
|
"placeholder": "RUB",
|
||||||
|
"optional": true,
|
||||||
|
"secret": false,
|
||||||
|
"provider_id": "paykilla",
|
||||||
|
"provider_label": "PayKilla",
|
||||||
|
"webhook_provider_id": "paykilla",
|
||||||
|
"webhook_path": "/webhook/paykilla",
|
||||||
|
"webhook_requires_base_url": false,
|
||||||
|
"value": "",
|
||||||
|
"overridden": false,
|
||||||
|
"updated_at": null,
|
||||||
|
"webhook_base_url_configured": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "PAYKILLA_SUPPORTED_CURRENCIES",
|
||||||
|
"type": "string",
|
||||||
|
"section": "payments",
|
||||||
|
"section_order": 4,
|
||||||
|
"subsection": "PayKilla",
|
||||||
|
"label": "Supported invoice currencies",
|
||||||
|
"description": "Comma-separated invoice currencies allowed for PayKilla in this shop.",
|
||||||
|
"i18n_label_key": "admin_settings_field_paykilla_supported_currencies_label",
|
||||||
|
"i18n_description_key": "admin_settings_field_paykilla_supported_currencies_description",
|
||||||
|
"i18n_subsection_key": "admin_settings_subsection_paykilla",
|
||||||
|
"i18n_placeholder_key": "admin_settings_field_paykilla_supported_currencies_placeholder",
|
||||||
|
"placeholder": "RUB,USD,EUR,AED,GBP,BTC,ETH,TRX,TON,USDTTRC,USDTETH,USDTBSC,USDCETH,USDCBSC,DAIETH,DAIBSC,BNBBSC,ETHBSC,LINKETH,LINKBSC,USDTTON,AAVEETH,MANAETH,SHIBETH",
|
||||||
|
"optional": true,
|
||||||
|
"secret": false,
|
||||||
|
"provider_id": "paykilla",
|
||||||
|
"provider_label": "PayKilla",
|
||||||
|
"webhook_provider_id": "paykilla",
|
||||||
|
"webhook_path": "/webhook/paykilla",
|
||||||
|
"webhook_requires_base_url": false,
|
||||||
|
"value": "",
|
||||||
|
"overridden": false,
|
||||||
|
"updated_at": null,
|
||||||
|
"webhook_base_url_configured": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "PAYKILLA_PAYMENT_CURRENCIES",
|
||||||
|
"type": "string",
|
||||||
|
"section": "payments",
|
||||||
|
"section_order": 4,
|
||||||
|
"subsection": "PayKilla",
|
||||||
|
"label": "Accepted crypto tickers",
|
||||||
|
"description": "Comma-separated PayKilla tickers sent as paymentCurrencies, e.g. USDTTRC,BTC,ETH.",
|
||||||
|
"i18n_label_key": "admin_settings_field_paykilla_payment_currencies_label",
|
||||||
|
"i18n_description_key": "admin_settings_field_paykilla_payment_currencies_description",
|
||||||
|
"i18n_subsection_key": "admin_settings_subsection_paykilla",
|
||||||
|
"i18n_placeholder_key": "admin_settings_field_paykilla_payment_currencies_placeholder",
|
||||||
|
"placeholder": "USDTTRC,BTC,ETH",
|
||||||
|
"optional": true,
|
||||||
|
"secret": false,
|
||||||
|
"provider_id": "paykilla",
|
||||||
|
"provider_label": "PayKilla",
|
||||||
|
"webhook_provider_id": "paykilla",
|
||||||
|
"webhook_path": "/webhook/paykilla",
|
||||||
|
"webhook_requires_base_url": false,
|
||||||
|
"value": "",
|
||||||
|
"overridden": false,
|
||||||
|
"updated_at": null,
|
||||||
|
"webhook_base_url_configured": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "PAYKILLA_INVOICE_TYPE",
|
||||||
|
"type": "string",
|
||||||
|
"section": "payments",
|
||||||
|
"section_order": 4,
|
||||||
|
"subsection": "PayKilla",
|
||||||
|
"label": "Invoice type",
|
||||||
|
"description": "Optional override: FIAT_BASED, FIXED_AMOUNT, or OPEN_AMOUNT.",
|
||||||
|
"i18n_label_key": "admin_settings_field_paykilla_invoice_type_label",
|
||||||
|
"i18n_description_key": "admin_settings_field_paykilla_invoice_type_description",
|
||||||
|
"i18n_subsection_key": "admin_settings_subsection_paykilla",
|
||||||
|
"i18n_placeholder_key": null,
|
||||||
|
"placeholder": "",
|
||||||
|
"optional": true,
|
||||||
|
"secret": false,
|
||||||
|
"provider_id": "paykilla",
|
||||||
|
"provider_label": "PayKilla",
|
||||||
|
"webhook_provider_id": "paykilla",
|
||||||
|
"webhook_path": "/webhook/paykilla",
|
||||||
|
"webhook_requires_base_url": false,
|
||||||
|
"choices": [
|
||||||
|
{
|
||||||
|
"value": "",
|
||||||
|
"label": "Auto",
|
||||||
|
"i18n_label_key": "admin_settings_field_paykilla_invoice_type_choice_default"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value": "FIAT_BASED",
|
||||||
|
"label": "FIAT_BASED",
|
||||||
|
"i18n_label_key": "admin_settings_field_paykilla_invoice_type_choice_fiat_based"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value": "FIXED_AMOUNT",
|
||||||
|
"label": "FIXED_AMOUNT",
|
||||||
|
"i18n_label_key": "admin_settings_field_paykilla_invoice_type_choice_fixed_amount"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value": "OPEN_AMOUNT",
|
||||||
|
"label": "OPEN_AMOUNT",
|
||||||
|
"i18n_label_key": "admin_settings_field_paykilla_invoice_type_choice_open_amount"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"value": "",
|
||||||
|
"overridden": false,
|
||||||
|
"updated_at": null,
|
||||||
|
"webhook_base_url_configured": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "PAYKILLA_RETURN_URL",
|
||||||
|
"type": "url",
|
||||||
|
"section": "payments",
|
||||||
|
"section_order": 4,
|
||||||
|
"subsection": "PayKilla",
|
||||||
|
"label": "Return URL",
|
||||||
|
"description": "",
|
||||||
|
"i18n_label_key": "admin_settings_field_paykilla_return_url_label",
|
||||||
|
"i18n_description_key": null,
|
||||||
|
"i18n_subsection_key": "admin_settings_subsection_paykilla",
|
||||||
|
"i18n_placeholder_key": null,
|
||||||
|
"placeholder": "",
|
||||||
|
"optional": true,
|
||||||
|
"secret": false,
|
||||||
|
"provider_id": "paykilla",
|
||||||
|
"provider_label": "PayKilla",
|
||||||
|
"webhook_provider_id": "paykilla",
|
||||||
|
"webhook_path": "/webhook/paykilla",
|
||||||
|
"webhook_requires_base_url": false,
|
||||||
|
"value": "",
|
||||||
|
"overridden": false,
|
||||||
|
"updated_at": null,
|
||||||
|
"webhook_base_url_configured": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "PAYKILLA_SUCCESS_URL",
|
||||||
|
"type": "url",
|
||||||
|
"section": "payments",
|
||||||
|
"section_order": 4,
|
||||||
|
"subsection": "PayKilla",
|
||||||
|
"label": "Success URL",
|
||||||
|
"description": "",
|
||||||
|
"i18n_label_key": "admin_settings_field_paykilla_success_url_label",
|
||||||
|
"i18n_description_key": null,
|
||||||
|
"i18n_subsection_key": "admin_settings_subsection_paykilla",
|
||||||
|
"i18n_placeholder_key": null,
|
||||||
|
"placeholder": "",
|
||||||
|
"optional": true,
|
||||||
|
"secret": false,
|
||||||
|
"provider_id": "paykilla",
|
||||||
|
"provider_label": "PayKilla",
|
||||||
|
"webhook_provider_id": "paykilla",
|
||||||
|
"webhook_path": "/webhook/paykilla",
|
||||||
|
"webhook_requires_base_url": false,
|
||||||
|
"value": "",
|
||||||
|
"overridden": false,
|
||||||
|
"updated_at": null,
|
||||||
|
"webhook_base_url_configured": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "PAYKILLA_CANCEL_URL",
|
||||||
|
"type": "url",
|
||||||
|
"section": "payments",
|
||||||
|
"section_order": 4,
|
||||||
|
"subsection": "PayKilla",
|
||||||
|
"label": "Cancel URL",
|
||||||
|
"description": "",
|
||||||
|
"i18n_label_key": "admin_settings_field_paykilla_cancel_url_label",
|
||||||
|
"i18n_description_key": null,
|
||||||
|
"i18n_subsection_key": "admin_settings_subsection_paykilla",
|
||||||
|
"i18n_placeholder_key": null,
|
||||||
|
"placeholder": "",
|
||||||
|
"optional": true,
|
||||||
|
"secret": false,
|
||||||
|
"provider_id": "paykilla",
|
||||||
|
"provider_label": "PayKilla",
|
||||||
|
"webhook_provider_id": "paykilla",
|
||||||
|
"webhook_path": "/webhook/paykilla",
|
||||||
|
"webhook_requires_base_url": false,
|
||||||
|
"value": "",
|
||||||
|
"overridden": false,
|
||||||
|
"updated_at": null,
|
||||||
|
"webhook_base_url_configured": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "PAYKILLA_LIFETIME_SECONDS",
|
||||||
|
"type": "int",
|
||||||
|
"section": "payments",
|
||||||
|
"section_order": 4,
|
||||||
|
"subsection": "PayKilla",
|
||||||
|
"label": "Invoice lifetime (seconds)",
|
||||||
|
"description": "Used to send expiredAt to PayKilla.",
|
||||||
|
"i18n_label_key": "admin_settings_field_paykilla_lifetime_seconds_label",
|
||||||
|
"i18n_description_key": "admin_settings_field_paykilla_lifetime_seconds_description",
|
||||||
|
"i18n_subsection_key": "admin_settings_subsection_paykilla",
|
||||||
|
"i18n_placeholder_key": null,
|
||||||
|
"placeholder": "",
|
||||||
|
"optional": true,
|
||||||
|
"secret": false,
|
||||||
|
"min": 300,
|
||||||
|
"max": 2592000,
|
||||||
|
"provider_id": "paykilla",
|
||||||
|
"provider_label": "PayKilla",
|
||||||
|
"webhook_provider_id": "paykilla",
|
||||||
|
"webhook_path": "/webhook/paykilla",
|
||||||
|
"webhook_requires_base_url": false,
|
||||||
|
"value": "",
|
||||||
|
"overridden": false,
|
||||||
|
"updated_at": null,
|
||||||
|
"webhook_base_url_configured": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "PAYKILLA_RECV_WINDOW_MS",
|
||||||
|
"type": "int",
|
||||||
|
"section": "payments",
|
||||||
|
"section_order": 4,
|
||||||
|
"subsection": "PayKilla",
|
||||||
|
"label": "Request recvWindow (ms)",
|
||||||
|
"description": "Validity window for signed PayKilla API requests.",
|
||||||
|
"i18n_label_key": "admin_settings_field_paykilla_recv_window_ms_label",
|
||||||
|
"i18n_description_key": "admin_settings_field_paykilla_recv_window_ms_description",
|
||||||
|
"i18n_subsection_key": "admin_settings_subsection_paykilla",
|
||||||
|
"i18n_placeholder_key": null,
|
||||||
|
"placeholder": "",
|
||||||
|
"optional": true,
|
||||||
|
"secret": false,
|
||||||
|
"min": 1000,
|
||||||
|
"max": 60000,
|
||||||
|
"provider_id": "paykilla",
|
||||||
|
"provider_label": "PayKilla",
|
||||||
|
"webhook_provider_id": "paykilla",
|
||||||
|
"webhook_path": "/webhook/paykilla",
|
||||||
|
"webhook_requires_base_url": false,
|
||||||
|
"value": "",
|
||||||
|
"overridden": false,
|
||||||
|
"updated_at": null,
|
||||||
|
"webhook_base_url_configured": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "PAYKILLA_USER_PAYS_SERVICE_FEE",
|
||||||
|
"type": "bool",
|
||||||
|
"section": "payments",
|
||||||
|
"section_order": 4,
|
||||||
|
"subsection": "PayKilla",
|
||||||
|
"label": "User pays service fee",
|
||||||
|
"description": "",
|
||||||
|
"i18n_label_key": "admin_settings_field_paykilla_user_pays_service_fee_label",
|
||||||
|
"i18n_description_key": null,
|
||||||
|
"i18n_subsection_key": "admin_settings_subsection_paykilla",
|
||||||
|
"i18n_placeholder_key": null,
|
||||||
|
"placeholder": "",
|
||||||
|
"optional": true,
|
||||||
|
"secret": false,
|
||||||
|
"provider_id": "paykilla",
|
||||||
|
"provider_label": "PayKilla",
|
||||||
|
"webhook_provider_id": "paykilla",
|
||||||
|
"webhook_path": "/webhook/paykilla",
|
||||||
|
"webhook_requires_base_url": false,
|
||||||
|
"value": "",
|
||||||
|
"overridden": false,
|
||||||
|
"updated_at": null,
|
||||||
|
"webhook_base_url_configured": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "PAYKILLA_USER_PAYS_NETWORK_FEE",
|
||||||
|
"type": "bool",
|
||||||
|
"section": "payments",
|
||||||
|
"section_order": 4,
|
||||||
|
"subsection": "PayKilla",
|
||||||
|
"label": "User pays network fee",
|
||||||
|
"description": "",
|
||||||
|
"i18n_label_key": "admin_settings_field_paykilla_user_pays_network_fee_label",
|
||||||
|
"i18n_description_key": null,
|
||||||
|
"i18n_subsection_key": "admin_settings_subsection_paykilla",
|
||||||
|
"i18n_placeholder_key": null,
|
||||||
|
"placeholder": "",
|
||||||
|
"optional": true,
|
||||||
|
"secret": false,
|
||||||
|
"provider_id": "paykilla",
|
||||||
|
"provider_label": "PayKilla",
|
||||||
|
"webhook_provider_id": "paykilla",
|
||||||
|
"webhook_path": "/webhook/paykilla",
|
||||||
|
"webhook_requires_base_url": false,
|
||||||
|
"value": "",
|
||||||
|
"overridden": false,
|
||||||
|
"updated_at": null,
|
||||||
|
"webhook_base_url_configured": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "PAYKILLA_VERIFY_WEBHOOK_SIGNATURE",
|
||||||
|
"type": "bool",
|
||||||
|
"section": "payments",
|
||||||
|
"section_order": 4,
|
||||||
|
"subsection": "PayKilla",
|
||||||
|
"label": "Verify webhook signature",
|
||||||
|
"description": "",
|
||||||
|
"i18n_label_key": "admin_settings_field_paykilla_verify_webhook_signature_label",
|
||||||
|
"i18n_description_key": null,
|
||||||
|
"i18n_subsection_key": "admin_settings_subsection_paykilla",
|
||||||
|
"i18n_placeholder_key": null,
|
||||||
|
"placeholder": "",
|
||||||
|
"optional": true,
|
||||||
|
"secret": false,
|
||||||
|
"provider_id": "paykilla",
|
||||||
|
"provider_label": "PayKilla",
|
||||||
|
"webhook_provider_id": "paykilla",
|
||||||
|
"webhook_path": "/webhook/paykilla",
|
||||||
|
"webhook_requires_base_url": false,
|
||||||
|
"value": "",
|
||||||
|
"overridden": false,
|
||||||
|
"updated_at": null,
|
||||||
|
"webhook_base_url_configured": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "PAYKILLA_WEBHOOK_URL",
|
||||||
|
"type": "url",
|
||||||
|
"section": "payments",
|
||||||
|
"section_order": 4,
|
||||||
|
"subsection": "PayKilla",
|
||||||
|
"label": "Exact webhook URL",
|
||||||
|
"description": "Optional override for signature verification. Leave empty to use WEBHOOK_BASE_URL + /webhook/paykilla.",
|
||||||
|
"i18n_label_key": "admin_settings_field_paykilla_webhook_url_label",
|
||||||
|
"i18n_description_key": "admin_settings_field_paykilla_webhook_url_description",
|
||||||
|
"i18n_subsection_key": "admin_settings_subsection_paykilla",
|
||||||
|
"i18n_placeholder_key": null,
|
||||||
|
"placeholder": "",
|
||||||
|
"optional": true,
|
||||||
|
"secret": false,
|
||||||
|
"provider_id": "paykilla",
|
||||||
|
"provider_label": "PayKilla",
|
||||||
|
"webhook_provider_id": "paykilla",
|
||||||
|
"webhook_path": "/webhook/paykilla",
|
||||||
|
"webhook_requires_base_url": false,
|
||||||
|
"value": "",
|
||||||
|
"overridden": false,
|
||||||
|
"updated_at": null,
|
||||||
|
"webhook_base_url_configured": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "PAYKILLA_TRUSTED_IPS",
|
||||||
|
"type": "string",
|
||||||
|
"section": "payments",
|
||||||
|
"section_order": 4,
|
||||||
|
"subsection": "PayKilla",
|
||||||
|
"label": "Trusted IPs",
|
||||||
|
"description": "Optional comma-separated IP addresses accepted for PayKilla webhooks.",
|
||||||
|
"i18n_label_key": "admin_settings_field_paykilla_trusted_ips_label",
|
||||||
|
"i18n_description_key": "admin_settings_field_paykilla_trusted_ips_description",
|
||||||
|
"i18n_subsection_key": "admin_settings_subsection_paykilla",
|
||||||
|
"i18n_placeholder_key": null,
|
||||||
|
"placeholder": "",
|
||||||
|
"optional": true,
|
||||||
|
"secret": false,
|
||||||
|
"provider_id": "paykilla",
|
||||||
|
"provider_label": "PayKilla",
|
||||||
|
"webhook_provider_id": "paykilla",
|
||||||
|
"webhook_path": "/webhook/paykilla",
|
||||||
|
"webhook_requires_base_url": false,
|
||||||
|
"value": "",
|
||||||
|
"overridden": false,
|
||||||
|
"updated_at": null,
|
||||||
|
"webhook_base_url_configured": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "PAYMENT_PAYKILLA_WEBAPP_LABEL_RU",
|
||||||
|
"type": "string",
|
||||||
|
"section": "payments",
|
||||||
|
"section_order": 4,
|
||||||
|
"subsection": "PayKilla",
|
||||||
|
"label": "WebApp button text (RU)",
|
||||||
|
"description": "Custom Russian text shown in the Web App payment method button.",
|
||||||
|
"i18n_label_key": "admin_settings_field_payment_paykilla_webapp_label_ru_label",
|
||||||
|
"i18n_description_key": "admin_settings_field_payment_paykilla_webapp_label_ru_description",
|
||||||
|
"i18n_subsection_key": "admin_settings_subsection_paykilla",
|
||||||
|
"i18n_placeholder_key": "admin_settings_field_payment_paykilla_webapp_label_ru_placeholder",
|
||||||
|
"placeholder": "PayKilla",
|
||||||
|
"optional": true,
|
||||||
|
"secret": false,
|
||||||
|
"default": "PayKilla",
|
||||||
|
"provider_id": "paykilla",
|
||||||
|
"provider_label": "PayKilla",
|
||||||
|
"webhook_provider_id": "paykilla",
|
||||||
|
"webhook_path": "/webhook/paykilla",
|
||||||
|
"webhook_requires_base_url": false,
|
||||||
|
"value": "",
|
||||||
|
"overridden": false,
|
||||||
|
"updated_at": null,
|
||||||
|
"webhook_base_url_configured": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "PAYMENT_PAYKILLA_WEBAPP_LABEL_EN",
|
||||||
|
"type": "string",
|
||||||
|
"section": "payments",
|
||||||
|
"section_order": 4,
|
||||||
|
"subsection": "PayKilla",
|
||||||
|
"label": "WebApp button text (EN)",
|
||||||
|
"description": "Custom English text shown in the Web App payment method button.",
|
||||||
|
"i18n_label_key": "admin_settings_field_payment_paykilla_webapp_label_en_label",
|
||||||
|
"i18n_description_key": "admin_settings_field_payment_paykilla_webapp_label_en_description",
|
||||||
|
"i18n_subsection_key": "admin_settings_subsection_paykilla",
|
||||||
|
"i18n_placeholder_key": "admin_settings_field_payment_paykilla_webapp_label_en_placeholder",
|
||||||
|
"placeholder": "PayKilla",
|
||||||
|
"optional": true,
|
||||||
|
"secret": false,
|
||||||
|
"default": "PayKilla",
|
||||||
|
"provider_id": "paykilla",
|
||||||
|
"provider_label": "PayKilla",
|
||||||
|
"webhook_provider_id": "paykilla",
|
||||||
|
"webhook_path": "/webhook/paykilla",
|
||||||
|
"webhook_requires_base_url": false,
|
||||||
|
"value": "",
|
||||||
|
"overridden": false,
|
||||||
|
"updated_at": null,
|
||||||
|
"webhook_base_url_configured": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "PAYMENT_PAYKILLA_WEBAPP_ICON",
|
||||||
|
"type": "icon",
|
||||||
|
"section": "payments",
|
||||||
|
"section_order": 4,
|
||||||
|
"subsection": "PayKilla",
|
||||||
|
"label": "WebApp button icon",
|
||||||
|
"description": "Lucide icon name rendered inside the Web App payment method button.",
|
||||||
|
"i18n_label_key": "admin_settings_field_payment_paykilla_webapp_icon_label",
|
||||||
|
"i18n_description_key": "admin_settings_field_payment_paykilla_webapp_icon_description",
|
||||||
|
"i18n_subsection_key": "admin_settings_subsection_paykilla",
|
||||||
|
"i18n_placeholder_key": "admin_settings_field_payment_paykilla_webapp_icon_placeholder",
|
||||||
|
"placeholder": "Bitcoin",
|
||||||
|
"optional": true,
|
||||||
|
"secret": false,
|
||||||
|
"default": "Bitcoin",
|
||||||
|
"provider_id": "paykilla",
|
||||||
|
"provider_label": "PayKilla",
|
||||||
|
"webhook_provider_id": "paykilla",
|
||||||
|
"webhook_path": "/webhook/paykilla",
|
||||||
|
"webhook_requires_base_url": false,
|
||||||
|
"value": "",
|
||||||
|
"overridden": false,
|
||||||
|
"updated_at": null,
|
||||||
|
"webhook_base_url_configured": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "PAYMENT_PAYKILLA_TELEGRAM_LABEL_RU",
|
||||||
|
"type": "string",
|
||||||
|
"section": "payments",
|
||||||
|
"section_order": 4,
|
||||||
|
"subsection": "PayKilla",
|
||||||
|
"label": "Telegram button text (RU)",
|
||||||
|
"description": "Custom Russian text shown in Telegram bot payment buttons.",
|
||||||
|
"i18n_label_key": "admin_settings_field_payment_paykilla_telegram_label_ru_label",
|
||||||
|
"i18n_description_key": "admin_settings_field_payment_paykilla_telegram_label_ru_description",
|
||||||
|
"i18n_subsection_key": "admin_settings_subsection_paykilla",
|
||||||
|
"i18n_placeholder_key": "admin_settings_field_payment_paykilla_telegram_label_ru_placeholder",
|
||||||
|
"placeholder": "PayKilla",
|
||||||
|
"optional": true,
|
||||||
|
"secret": false,
|
||||||
|
"default": "PayKilla",
|
||||||
|
"provider_id": "paykilla",
|
||||||
|
"provider_label": "PayKilla",
|
||||||
|
"webhook_provider_id": "paykilla",
|
||||||
|
"webhook_path": "/webhook/paykilla",
|
||||||
|
"webhook_requires_base_url": false,
|
||||||
|
"value": "",
|
||||||
|
"overridden": false,
|
||||||
|
"updated_at": null,
|
||||||
|
"webhook_base_url_configured": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "PAYMENT_PAYKILLA_TELEGRAM_LABEL_EN",
|
||||||
|
"type": "string",
|
||||||
|
"section": "payments",
|
||||||
|
"section_order": 4,
|
||||||
|
"subsection": "PayKilla",
|
||||||
|
"label": "Telegram button text (EN)",
|
||||||
|
"description": "Custom English text shown in Telegram bot payment buttons.",
|
||||||
|
"i18n_label_key": "admin_settings_field_payment_paykilla_telegram_label_en_label",
|
||||||
|
"i18n_description_key": "admin_settings_field_payment_paykilla_telegram_label_en_description",
|
||||||
|
"i18n_subsection_key": "admin_settings_subsection_paykilla",
|
||||||
|
"i18n_placeholder_key": "admin_settings_field_payment_paykilla_telegram_label_en_placeholder",
|
||||||
|
"placeholder": "PayKilla",
|
||||||
|
"optional": true,
|
||||||
|
"secret": false,
|
||||||
|
"default": "PayKilla",
|
||||||
|
"provider_id": "paykilla",
|
||||||
|
"provider_label": "PayKilla",
|
||||||
|
"webhook_provider_id": "paykilla",
|
||||||
|
"webhook_path": "/webhook/paykilla",
|
||||||
|
"webhook_requires_base_url": false,
|
||||||
|
"value": "",
|
||||||
|
"overridden": false,
|
||||||
|
"updated_at": null,
|
||||||
|
"webhook_base_url_configured": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "PAYMENT_PAYKILLA_TELEGRAM_EMOJI",
|
||||||
|
"type": "string",
|
||||||
|
"section": "payments",
|
||||||
|
"section_order": 4,
|
||||||
|
"subsection": "PayKilla",
|
||||||
|
"label": "Telegram button emoji",
|
||||||
|
"description": "Emoji prepended to the Telegram bot payment button when customized.",
|
||||||
|
"i18n_label_key": "admin_settings_field_payment_paykilla_telegram_emoji_label",
|
||||||
|
"i18n_description_key": "admin_settings_field_payment_paykilla_telegram_emoji_description",
|
||||||
|
"i18n_subsection_key": "admin_settings_subsection_paykilla",
|
||||||
|
"i18n_placeholder_key": null,
|
||||||
|
"placeholder": "",
|
||||||
|
"optional": true,
|
||||||
|
"secret": false,
|
||||||
|
"default": "",
|
||||||
|
"provider_id": "paykilla",
|
||||||
|
"provider_label": "PayKilla",
|
||||||
|
"webhook_provider_id": "paykilla",
|
||||||
|
"webhook_path": "/webhook/paykilla",
|
||||||
|
"webhook_requires_base_url": false,
|
||||||
|
"value": "",
|
||||||
|
"overridden": false,
|
||||||
|
"updated_at": null,
|
||||||
|
"webhook_base_url_configured": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "PAYKILLA_ADMIN_ONLY_ENABLED",
|
||||||
|
"type": "bool",
|
||||||
|
"section": "payments",
|
||||||
|
"section_order": 4,
|
||||||
|
"subsection": "PayKilla",
|
||||||
|
"label": "Only for admins",
|
||||||
|
"description": "Shows this payment method only to users from ADMIN_IDS. Webhooks and provider services remain active for admin test payments.",
|
||||||
|
"i18n_label_key": "admin_settings_provider_admin_only_label",
|
||||||
|
"i18n_description_key": "admin_settings_provider_admin_only_description",
|
||||||
|
"i18n_subsection_key": "admin_settings_subsection_paykilla",
|
||||||
|
"i18n_placeholder_key": null,
|
||||||
|
"placeholder": "",
|
||||||
|
"optional": true,
|
||||||
|
"secret": false,
|
||||||
|
"mutually_exclusive_key": "PAYKILLA_ENABLED",
|
||||||
|
"provider_id": "paykilla",
|
||||||
|
"provider_label": "PayKilla",
|
||||||
|
"webhook_provider_id": "paykilla",
|
||||||
|
"webhook_path": "/webhook/paykilla",
|
||||||
|
"webhook_requires_base_url": false,
|
||||||
|
"value": "",
|
||||||
|
"overridden": false,
|
||||||
|
"updated_at": null,
|
||||||
|
"webhook_base_url_configured": false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -874,6 +874,7 @@ remnashop_webhook_checklist() {
|
|||||||
printf ' WATA merchant dashboard -> webhook/callback URL: %s/webhook/wata\n' "$base_url"
|
printf ' WATA merchant dashboard -> webhook/callback URL: %s/webhook/wata\n' "$base_url"
|
||||||
printf ' CryptoBot/Crypto Pay app -> webhook URL: %s/webhook/cryptopay\n' "$base_url"
|
printf ' CryptoBot/Crypto Pay app -> webhook URL: %s/webhook/cryptopay\n' "$base_url"
|
||||||
printf ' Heleket merchant dashboard -> payment webhook/callback URL: %s/webhook/heleket\n' "$base_url"
|
printf ' Heleket merchant dashboard -> payment webhook/callback URL: %s/webhook/heleket\n' "$base_url"
|
||||||
|
printf ' PayKilla Dashboard -> Settings -> Webhooks URL: %s/webhook/paykilla\n' "$base_url"
|
||||||
printf ' FreeKassa shop settings -> notification/result URL: %s/webhook/freekassa\n' "$base_url"
|
printf ' FreeKassa shop settings -> notification/result URL: %s/webhook/freekassa\n' "$base_url"
|
||||||
printf ' Platega merchant/project settings -> webhook URL: %s/webhook/platega\n' "$base_url"
|
printf ' Platega merchant/project settings -> webhook URL: %s/webhook/platega\n' "$base_url"
|
||||||
printf ' Telegram webhook: %s/tg/webhook (configured automatically on bot startup)\n' "$base_url"
|
printf ' Telegram webhook: %s/tg/webhook (configured automatically on bot startup)\n' "$base_url"
|
||||||
|
|||||||
@@ -175,6 +175,7 @@ class BuildServicesWiringTests(unittest.TestCase):
|
|||||||
"severpay_service",
|
"severpay_service",
|
||||||
"wata_service",
|
"wata_service",
|
||||||
"heleket_service",
|
"heleket_service",
|
||||||
|
"paykilla_service",
|
||||||
}
|
}
|
||||||
self.assertEqual(set(services), expected_keys)
|
self.assertEqual(set(services), expected_keys)
|
||||||
|
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ def test_shell_installer_prints_remnashop_webhook_checklist():
|
|||||||
assert "/webhook/wata" in script
|
assert "/webhook/wata" in script
|
||||||
assert "/webhook/cryptopay" in script
|
assert "/webhook/cryptopay" in script
|
||||||
assert "/webhook/heleket" in script
|
assert "/webhook/heleket" in script
|
||||||
|
assert "/webhook/paykilla" in script
|
||||||
assert "/webhook/freekassa" in script
|
assert "/webhook/freekassa" in script
|
||||||
assert "/webhook/platega" in script
|
assert "/webhook/platega" in script
|
||||||
assert "/tg/webhook" in script
|
assert "/tg/webhook" in script
|
||||||
|
|||||||
@@ -203,6 +203,7 @@ class RemnashopMigrationDocumentationFactsTests(unittest.TestCase):
|
|||||||
"/webhook/wata",
|
"/webhook/wata",
|
||||||
"/webhook/cryptopay",
|
"/webhook/cryptopay",
|
||||||
"/webhook/heleket",
|
"/webhook/heleket",
|
||||||
|
"/webhook/paykilla",
|
||||||
"/webhook/freekassa",
|
"/webhook/freekassa",
|
||||||
"/webhook/platega",
|
"/webhook/platega",
|
||||||
"/tg/webhook",
|
"/tg/webhook",
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ _PROVIDER_MODULES = {
|
|||||||
"stars": "StarsService",
|
"stars": "StarsService",
|
||||||
"wata": "WataService",
|
"wata": "WataService",
|
||||||
"heleket": "HeleketService",
|
"heleket": "HeleketService",
|
||||||
|
"paykilla": "PaykillaService",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -125,6 +126,7 @@ def test_service_keys_and_statuses_come_from_provider_specs():
|
|||||||
"stars_service",
|
"stars_service",
|
||||||
"cryptopay_service",
|
"cryptopay_service",
|
||||||
"heleket_service",
|
"heleket_service",
|
||||||
|
"paykilla_service",
|
||||||
}
|
}
|
||||||
assert set(pending_statuses()) >= {
|
assert set(pending_statuses()) >= {
|
||||||
"pending",
|
"pending",
|
||||||
@@ -136,6 +138,7 @@ def test_service_keys_and_statuses_come_from_provider_specs():
|
|||||||
"pending_cryptopay",
|
"pending_cryptopay",
|
||||||
"pending_stars",
|
"pending_stars",
|
||||||
"pending_heleket",
|
"pending_heleket",
|
||||||
|
"pending_paykilla",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -152,6 +155,7 @@ def test_provider_labels_and_emojis_include_storage_keys_and_method_aliases():
|
|||||||
assert emojis["stars"] == get_provider_spec("stars").default_telegram_emoji
|
assert emojis["stars"] == get_provider_spec("stars").default_telegram_emoji
|
||||||
assert emojis["telegram_stars"] == get_provider_spec("stars").default_telegram_emoji
|
assert emojis["telegram_stars"] == get_provider_spec("stars").default_telegram_emoji
|
||||||
assert emojis["cryptopay"] == get_provider_spec("cryptopay").default_telegram_emoji
|
assert emojis["cryptopay"] == get_provider_spec("cryptopay").default_telegram_emoji
|
||||||
|
assert labels["paykilla"] == "PayKilla"
|
||||||
|
|
||||||
|
|
||||||
def test_provider_presentation_resolves_defaults_and_overrides():
|
def test_provider_presentation_resolves_defaults_and_overrides():
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ _PROVIDERS_FROM_CALLERS = {
|
|||||||
"severpay",
|
"severpay",
|
||||||
"wata",
|
"wata",
|
||||||
"cryptopay",
|
"cryptopay",
|
||||||
|
"paykilla",
|
||||||
"telegram_stars",
|
"telegram_stars",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -185,6 +185,22 @@ def test_remnashop_crypto_provider_currency_is_not_imported_as_setting_override(
|
|||||||
}
|
}
|
||||||
assert "HELEKET_CURRENCY" not in heleket["overrides"]
|
assert "HELEKET_CURRENCY" not in heleket["overrides"]
|
||||||
|
|
||||||
|
paykilla = remnashop_payment_gateway_overrides(
|
||||||
|
{
|
||||||
|
"type": "PAYKILLA",
|
||||||
|
"currency": "USD",
|
||||||
|
"is_active": True,
|
||||||
|
"settings": {"public_key": "public", "secret_key": "secret"},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
assert paykilla["overrides"] == {
|
||||||
|
"PAYKILLA_ENABLED": True,
|
||||||
|
"PAYKILLA_API_KEY": "public",
|
||||||
|
"PAYKILLA_SECRET_KEY": "secret",
|
||||||
|
}
|
||||||
|
assert "PAYKILLA_CURRENCY" not in paykilla["overrides"]
|
||||||
|
assert any("source currency was USD" in warning for warning in paykilla["warnings"])
|
||||||
|
|
||||||
|
|
||||||
def test_remnashop_unsupported_gateway_is_reported_without_overrides():
|
def test_remnashop_unsupported_gateway_is_reported_without_overrides():
|
||||||
result = remnashop_payment_gateway_overrides(
|
result = remnashop_payment_gateway_overrides(
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import hashlib
|
import hashlib
|
||||||
import hmac
|
import hmac
|
||||||
import json
|
import json
|
||||||
|
import time
|
||||||
import unittest
|
import unittest
|
||||||
from types import SimpleNamespace
|
from types import SimpleNamespace
|
||||||
from unittest.mock import AsyncMock, patch
|
from unittest.mock import AsyncMock, patch
|
||||||
@@ -19,6 +20,12 @@ from bot.app.web.webapp_auth import (
|
|||||||
from bot.payment_providers.cryptopay import CryptoPayService
|
from bot.payment_providers.cryptopay import CryptoPayService
|
||||||
from bot.payment_providers.freekassa import FreeKassaService
|
from bot.payment_providers.freekassa import FreeKassaService
|
||||||
from bot.payment_providers.heleket import HeleketConfig, HeleketService, _compute_signature
|
from bot.payment_providers.heleket import HeleketConfig, HeleketService, _compute_signature
|
||||||
|
from bot.payment_providers.paykilla import (
|
||||||
|
PaykillaConfig,
|
||||||
|
PaykillaService,
|
||||||
|
_sign_query,
|
||||||
|
_webhook_signature,
|
||||||
|
)
|
||||||
from bot.payment_providers.yookassa import yookassa_webhook_route
|
from bot.payment_providers.yookassa import yookassa_webhook_route
|
||||||
from bot.services.email_templates import render_login_code
|
from bot.services.email_templates import render_login_code
|
||||||
from bot.utils.request_security import request_client_ip
|
from bot.utils.request_security import request_client_ip
|
||||||
@@ -199,6 +206,79 @@ class HeleketServiceTests(unittest.TestCase):
|
|||||||
self.assertFalse(service._verify_signature({"order_id": "435", "sign": "bad"}))
|
self.assertFalse(service._verify_signature({"order_id": "435", "sign": "bad"}))
|
||||||
|
|
||||||
|
|
||||||
|
class PaykillaServiceTests(unittest.TestCase):
|
||||||
|
def _make_service(self, *, webhook_url: str = "https://shop.example/webhook/paykilla"):
|
||||||
|
service = PaykillaService.__new__(PaykillaService)
|
||||||
|
service.config = PaykillaConfig(
|
||||||
|
ENABLED=True,
|
||||||
|
API_KEY="public-key",
|
||||||
|
SECRET_KEY="secret-key",
|
||||||
|
WEBHOOK_URL=webhook_url,
|
||||||
|
)
|
||||||
|
service.settings = SimpleNamespace(
|
||||||
|
WEBHOOK_BASE_URL="https://shop.example",
|
||||||
|
trusted_proxies=["127.0.0.1"],
|
||||||
|
)
|
||||||
|
return service
|
||||||
|
|
||||||
|
def test_sign_query_uses_timestamp_and_recv_window_only(self):
|
||||||
|
query, signature = _sign_query(1738800000000, 5000, "secret-key")
|
||||||
|
expected = hmac.new(
|
||||||
|
b"secret-key",
|
||||||
|
b"timestamp=1738800000000&recvWindow=5000",
|
||||||
|
hashlib.sha256,
|
||||||
|
).hexdigest()
|
||||||
|
|
||||||
|
self.assertEqual(query, "timestamp=1738800000000&recvWindow=5000")
|
||||||
|
self.assertEqual(signature, expected)
|
||||||
|
|
||||||
|
def test_verify_webhook_signature_accepts_raw_body_signature(self):
|
||||||
|
service = self._make_service()
|
||||||
|
raw_body = (
|
||||||
|
b'{"id":"evt_1","priority":"HIGH","eventType":"INVOICE_PAID",'
|
||||||
|
b'"data":{"id":"inv_1","clientOrderId":"42"}}'
|
||||||
|
)
|
||||||
|
timestamp = str(int(time.time() * 1000))
|
||||||
|
signature = _webhook_signature(
|
||||||
|
timestamp=timestamp,
|
||||||
|
method="POST",
|
||||||
|
url="https://shop.example/webhook/paykilla",
|
||||||
|
raw_body=raw_body,
|
||||||
|
secret_key="secret-key",
|
||||||
|
)
|
||||||
|
request = SimpleNamespace(
|
||||||
|
headers={
|
||||||
|
"X-API-KEY": "public-key",
|
||||||
|
"X-API-TIMESTAMP": timestamp,
|
||||||
|
"X-API-RECV-WINDOW": "5000",
|
||||||
|
"X-API-SIGN": signature,
|
||||||
|
},
|
||||||
|
method="POST",
|
||||||
|
scheme="https",
|
||||||
|
host="shop.example",
|
||||||
|
path_qs="/webhook/paykilla",
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertTrue(service._verify_webhook_signature(request, raw_body))
|
||||||
|
|
||||||
|
def test_verify_webhook_signature_rejects_invalid_signature(self):
|
||||||
|
service = self._make_service()
|
||||||
|
request = SimpleNamespace(
|
||||||
|
headers={
|
||||||
|
"X-API-KEY": "public-key",
|
||||||
|
"X-API-TIMESTAMP": str(int(time.time() * 1000)),
|
||||||
|
"X-API-RECV-WINDOW": "5000",
|
||||||
|
"X-API-SIGN": "bad",
|
||||||
|
},
|
||||||
|
method="POST",
|
||||||
|
scheme="https",
|
||||||
|
host="shop.example",
|
||||||
|
path_qs="/webhook/paykilla",
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertFalse(service._verify_webhook_signature(request, b"{}"))
|
||||||
|
|
||||||
|
|
||||||
class WebAppSecurityTests(unittest.IsolatedAsyncioTestCase):
|
class WebAppSecurityTests(unittest.IsolatedAsyncioTestCase):
|
||||||
class _AsyncSessionFactory:
|
class _AsyncSessionFactory:
|
||||||
def __call__(self):
|
def __call__(self):
|
||||||
|
|||||||
Reference in New Issue
Block a user