fix: send tariff currency to PayKilla
This commit is contained in:
@@ -416,7 +416,7 @@ class PaykillaService(HttpClientMixin):
|
|||||||
currency: Optional[str],
|
currency: Optional[str],
|
||||||
description: str,
|
description: str,
|
||||||
) -> Dict[str, Any]:
|
) -> Dict[str, Any]:
|
||||||
currency_code = self.currency
|
currency_code = normalize_payment_currency_code(currency or self.currency)
|
||||||
invoice_text = _invoice_text(getattr(self.settings, "WEBAPP_TITLE", None), payment_db_id)
|
invoice_text = _invoice_text(getattr(self.settings, "WEBAPP_TITLE", None), payment_db_id)
|
||||||
body: Dict[str, Any] = {
|
body: Dict[str, Any] = {
|
||||||
"type": _invoice_type_for(self.config, currency_code),
|
"type": _invoice_type_for(self.config, currency_code),
|
||||||
@@ -449,8 +449,7 @@ class PaykillaService(HttpClientMixin):
|
|||||||
logging.error("PaykillaService is not configured. Cannot create payment link.")
|
logging.error("PaykillaService is not configured. Cannot create payment link.")
|
||||||
return False, {"message": "service_not_configured"}
|
return False, {"message": "service_not_configured"}
|
||||||
|
|
||||||
payment_currency = normalize_payment_currency_code(currency or self.currency)
|
currency_code = normalize_payment_currency_code(currency or self.currency)
|
||||||
currency_code = self.currency
|
|
||||||
supported = parse_supported_currency_codes(self.config.SUPPORTED_CURRENCIES)
|
supported = parse_supported_currency_codes(self.config.SUPPORTED_CURRENCIES)
|
||||||
if supported and currency_code not in supported:
|
if supported and currency_code not in supported:
|
||||||
return False, {
|
return False, {
|
||||||
@@ -458,13 +457,6 @@ class PaykillaService(HttpClientMixin):
|
|||||||
"currency": currency_code,
|
"currency": currency_code,
|
||||||
"supported_currencies": list(supported),
|
"supported_currencies": list(supported),
|
||||||
}
|
}
|
||||||
if payment_currency and payment_currency != currency_code:
|
|
||||||
logging.info(
|
|
||||||
"Paykilla create_payment_link: using configured invoice currency %s "
|
|
||||||
"instead of payment record currency %s; amount is sent unchanged.",
|
|
||||||
currency_code,
|
|
||||||
payment_currency,
|
|
||||||
)
|
|
||||||
|
|
||||||
body = self._invoice_body(
|
body = self._invoice_body(
|
||||||
payment_db_id=payment_db_id,
|
payment_db_id=payment_db_id,
|
||||||
@@ -994,8 +986,8 @@ _CONFIG_MANIFEST = (
|
|||||||
"string",
|
"string",
|
||||||
"Invoice currency",
|
"Invoice currency",
|
||||||
description=(
|
description=(
|
||||||
"PayKilla invoice currency. Amount is sent unchanged, so keep tariffs "
|
"Fallback invoice currency when the payment flow does not provide one. "
|
||||||
"priced in this currency or use a PayKilla-enabled fiat such as USD."
|
"Usually matches the tariff/default currency, e.g. RUB."
|
||||||
),
|
),
|
||||||
placeholder="RUB",
|
placeholder="RUB",
|
||||||
subsection="PayKilla",
|
subsection="PayKilla",
|
||||||
|
|||||||
@@ -376,7 +376,7 @@ Webhook настраивается в PayKilla Dashboard: **Settings -> Webhooks
|
|||||||
| `PAYKILLA_WIDGET_URL` | URL hosted checkout, по умолчанию `https://gopay.paykilla.com`. |
|
| `PAYKILLA_WIDGET_URL` | URL hosted checkout, по умолчанию `https://gopay.paykilla.com`. |
|
||||||
| `PAYKILLA_API_KEY` / `PAYKILLA_V2_API_KEY` | Public HMAC key с правом `INVOICE`. |
|
| `PAYKILLA_API_KEY` / `PAYKILLA_V2_API_KEY` | Public HMAC key с правом `INVOICE`. |
|
||||||
| `PAYKILLA_SECRET_KEY` / `PAYKILLA_V2_SECRET_KEY` | Secret HMAC key для подписи API-запросов и проверки webhook. |
|
| `PAYKILLA_SECRET_KEY` / `PAYKILLA_V2_SECRET_KEY` | Secret HMAC key для подписи API-запросов и проверки webhook. |
|
||||||
| `PAYKILLA_CURRENCY` | Валюта инвойса PayKilla. Сумма отправляется без FX-конвертации, поэтому цены должны быть в этой валюте или валюта должна быть включена у PayKilla. Для RUB/USD/EUR/AED/GBP используется `FIAT_BASED`, для остальных - `FIXED_AMOUNT`. |
|
| `PAYKILLA_CURRENCY` | Резервная валюта инвойса PayKilla, если платежный поток не передал валюту тарифа. Обычно совпадает с `DEFAULT_CURRENCY_SYMBOL`, например `RUB`. Для RUB/USD/EUR/AED/GBP используется `FIAT_BASED`, для остальных - `FIXED_AMOUNT`. |
|
||||||
| `PAYKILLA_PAYMENT_CURRENCIES` | Crypto tickers для оплаты, например `USDTTRC,BTC,ETH`. |
|
| `PAYKILLA_PAYMENT_CURRENCIES` | Crypto tickers для оплаты, например `USDTTRC,BTC,ETH`. |
|
||||||
| `PAYKILLA_SUPPORTED_CURRENCIES` | Валюты инвойса, разрешенные в этом магазине. |
|
| `PAYKILLA_SUPPORTED_CURRENCIES` | Валюты инвойса, разрешенные в этом магазине. |
|
||||||
| `PAYKILLA_INVOICE_TYPE` | Необязательный override: `FIAT_BASED`, `FIXED_AMOUNT` или `OPEN_AMOUNT`. |
|
| `PAYKILLA_INVOICE_TYPE` | Необязательный override: `FIAT_BASED`, `FIXED_AMOUNT` или `OPEN_AMOUNT`. |
|
||||||
|
|||||||
@@ -160,6 +160,8 @@ PayKilla используется для крипто-инвойсов V2 чер
|
|||||||
|
|
||||||
PayKilla строго валидирует текстовые поля invoice. Поэтому Minishop отправляет в `purpose` и `description` простой английский текст `<WEBAPP_TITLE> payment <id>`, а локализованное описание платежа оставляет только внутри Minishop. Дополнительно эти поля проходят ASCII-safe sanitizer: допускаются ASCII-буквы, цифры, пробелы, `_`, `.`, `,`.
|
PayKilla строго валидирует текстовые поля invoice. Поэтому Minishop отправляет в `purpose` и `description` простой английский текст `<WEBAPP_TITLE> payment <id>`, а локализованное описание платежа оставляет только внутри Minishop. Дополнительно эти поля проходят ASCII-safe sanitizer: допускаются ASCII-буквы, цифры, пробелы, `_`, `.`, `,`.
|
||||||
|
|
||||||
|
Для `FIAT_BASED` инвойса Minishop отправляет сумму и валюту тарифа как есть, например `190.00 RUB`. PayKilla рассчитывает сумму к оплате в выбранной криптовалюте из `paymentCurrencies`.
|
||||||
|
|
||||||
Какие полномочия нужны API key:
|
Какие полномочия нужны API key:
|
||||||
|
|
||||||
1. В PayKilla Dashboard откройте **Settings -> API keys**.
|
1. В PayKilla Dashboard откройте **Settings -> API keys**.
|
||||||
@@ -181,7 +183,7 @@ PayKilla строго валидирует текстовые поля invoice.
|
|||||||
|
|
||||||
1. Включите `PAYKILLA_ENABLED`.
|
1. Включите `PAYKILLA_ENABLED`.
|
||||||
2. Укажите `PAYKILLA_API_KEY` и `PAYKILLA_SECRET_KEY`.
|
2. Укажите `PAYKILLA_API_KEY` и `PAYKILLA_SECRET_KEY`.
|
||||||
3. Проверьте `PAYKILLA_CURRENCY` и `PAYKILLA_PAYMENT_CURRENCIES`, например `USD` и `USDTTRC,BTC,ETH`. `PAYKILLA_CURRENCY` теперь напрямую задаёт валюту invoice; Minishop не конвертирует сумму между RUB/USD/EUR.
|
3. Проверьте валюту тарифов/`DEFAULT_CURRENCY_SYMBOL` и `PAYKILLA_CURRENCY`, например `RUB`; в `PAYKILLA_PAYMENT_CURRENCIES` укажите crypto tickers, например `USDTTRC,BTC,ETH`.
|
||||||
4. Убедитесь, что webhook `/webhook/paykilla` настроен в PayKilla: Minishop не отправляет redirect URLs в PayKilla и полагается на webhook для активации платежа.
|
4. Убедитесь, что webhook `/webhook/paykilla` настроен в PayKilla: Minishop не отправляет redirect URLs в PayKilla и полагается на webhook для активации платежа.
|
||||||
5. Добавьте `paykilla` в `PAYMENT_METHODS_ORDER`, если хотите задать явный порядок кнопок.
|
5. Добавьте `paykilla` в `PAYMENT_METHODS_ORDER`, если хотите задать явный порядок кнопок.
|
||||||
|
|
||||||
|
|||||||
@@ -3975,7 +3975,7 @@
|
|||||||
"section_order": 4,
|
"section_order": 4,
|
||||||
"subsection": "PayKilla",
|
"subsection": "PayKilla",
|
||||||
"label": "Invoice currency",
|
"label": "Invoice currency",
|
||||||
"description": "PayKilla invoice currency. Amount is sent unchanged, so keep tariffs priced in this currency or use a PayKilla-enabled fiat such as USD.",
|
"description": "Fallback invoice currency when the payment flow does not provide one. Usually matches the tariff/default currency, e.g. RUB.",
|
||||||
"i18n_label_key": "admin_settings_field_paykilla_currency_label",
|
"i18n_label_key": "admin_settings_field_paykilla_currency_label",
|
||||||
"i18n_description_key": "admin_settings_field_paykilla_currency_description",
|
"i18n_description_key": "admin_settings_field_paykilla_currency_description",
|
||||||
"i18n_subsection_key": "admin_settings_subsection_paykilla",
|
"i18n_subsection_key": "admin_settings_subsection_paykilla",
|
||||||
|
|||||||
+15
-1
@@ -260,7 +260,7 @@ class PaykillaServiceTests(unittest.TestCase):
|
|||||||
self.assertRegex(body["purpose"], r"^[A-Za-z0-9_\s.,]+$")
|
self.assertRegex(body["purpose"], r"^[A-Za-z0-9_\s.,]+$")
|
||||||
self.assertNotIn("urls", body)
|
self.assertNotIn("urls", body)
|
||||||
|
|
||||||
def test_invoice_body_uses_configured_paykilla_currency(self):
|
def test_invoice_body_uses_payment_currency_before_configured_fallback(self):
|
||||||
service = self._make_service()
|
service = self._make_service()
|
||||||
service.config.CURRENCY = "USD"
|
service.config.CURRENCY = "USD"
|
||||||
|
|
||||||
@@ -271,6 +271,20 @@ class PaykillaServiceTests(unittest.TestCase):
|
|||||||
description="ignored",
|
description="ignored",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self.assertEqual(body["currency"], "RUB")
|
||||||
|
self.assertEqual(body["type"], "FIAT_BASED")
|
||||||
|
|
||||||
|
def test_invoice_body_uses_configured_currency_as_fallback(self):
|
||||||
|
service = self._make_service()
|
||||||
|
service.config.CURRENCY = "USD"
|
||||||
|
|
||||||
|
body = service._invoice_body(
|
||||||
|
payment_db_id=556,
|
||||||
|
amount=100,
|
||||||
|
currency=None,
|
||||||
|
description="ignored",
|
||||||
|
)
|
||||||
|
|
||||||
self.assertEqual(body["currency"], "USD")
|
self.assertEqual(body["currency"], "USD")
|
||||||
self.assertEqual(body["type"], "FIAT_BASED")
|
self.assertEqual(body["type"], "FIAT_BASED")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user