Розробка кастомного плагіна Saleor
Saleor побудований на Django і надає явну точку розширення через систему плагінів — BasePlugin. Кожен плагін реєструється в налаштуванні PLUGINS Django і перехоплює eventos через хуки. Це не плагіни в стилі WordPress: тут немає магії, лише Python-класи з передбачуваним життєвим циклом.
Архітектура плагіна
Плагін у Saleor — це клас, який успадковує BasePlugin з saleor.plugins.base_plugin. Доступні хуки охоплюють весь життєвий цикл замовлення, платіжний pipeline, відображення товарів і webhook-события.
from saleor.plugins.base_plugin import BasePlugin, ConfigurationTypeField
class TaxProviderPlugin(BasePlugin):
PLUGIN_ID = "custom.tax_provider"
PLUGIN_NAME = "Custom Tax Provider"
DEFAULT_ACTIVE = False
CONFIG_STRUCTURE = {
"api_key": {
"type": ConfigurationTypeField.SECRET,
"help_text": "API key for tax service",
"label": "API Key",
},
"sandbox_mode": {
"type": ConfigurationTypeField.BOOLEAN,
"help_text": "Use sandbox endpoint",
"label": "Sandbox",
},
}
def calculate_checkout_line_tax(
self, checkout_line_info, checkout_info, address, discounts, previous_value
):
config = self._get_config()
api_key = next(
(c["value"] for c in config if c["name"] == "api_key"), None
)
# обчислюємо податок через зовнішній API
return TaxedMoney(
net=checkout_line_info.line.unit_price_net,
gross=self._fetch_tax(checkout_line_info, api_key),
)
Метод _get_config() повертає конфігурацію, збережену через Dashboard. Значення типу SECRET зберігаються зашифрованими.
Хуки для платіжного pipeline
Найбільш затребувані хуки — платіжні. Saleor розділяє обробку на authorize, capture, refund, void:
def authorize_payment(
self, payment_information: "PaymentData", previous_value
) -> "GatewayResponse":
token = payment_information.token
amount = payment_information.amount
currency = payment_information.currency
response = self._call_payment_gateway(
action="authorize",
token=token,
amount=amount,
currency=currency,
)
return GatewayResponse(
is_success=response.get("status") == "authorized",
action_required=False,
kind=TransactionKind.AUTH,
amount=amount,
currency=currency,
transaction_id=response.get("transaction_id"),
error=response.get("error_message"),
)
Webhook-события
Починаючи з версії 3.x, Saleor підтримує асинхронні webhooks. Плагін може оголосити підписки через GraphQL subscriptions замість polling:
WEBHOOK_EVENTS_SUBSCRIPTIONS = """
subscription {
event {
... on OrderCreated {
order {
id
number
total { gross { amount currency } }
user { email }
}
}
}
}
"""
Saleor відправить POST з payload на вказаний endpoint при кожній подіїі ORDER_CREATED. Тіло підписки визначає, які поля потрапляють у payload — це GraphQL фрагмент, не просто конфіг.
Реєстрація та налаштування
# settings.py
PLUGINS = [
"myapp.plugins.tax_provider.TaxProviderPlugin",
"myapp.plugins.custom_payment.CustomPaymentPlugin",
]
Після перезавантаження сервера плагін з'явиться у розділі Plugins Dashboard. Поля конфігурації з CONFIG_STRUCTURE рендерять автоматично.
Тестування
Saleor надає PluginsManager — тестуйте плагіни через нього без запуску повного Django оточення:
from unittest.mock import patch, MagicMock
from saleor.plugins.manager import PluginsManager
def test_tax_calculation():
plugin = TaxProviderPlugin(
configuration=[{"name": "api_key", "value": "test-key"}],
active=True,
)
with patch.object(plugin, "_fetch_tax", return_value=Decimal("12.50")):
result = plugin.calculate_checkout_line_tax(
checkout_line_info=mock_line,
checkout_info=mock_checkout,
address=mock_address,
discounts=[],
previous_value=TaxedMoney(net=Decimal("100"), gross=Decimal("100")),
)
assert result.gross.amount == Decimal("12.50")
Типові завдання та часові рамки
| Завдання | Складність | Часова рамка |
|---|---|---|
| Плагін податків із зовнішнім API | Середня | 3–5 днів |
| Платіжний gateway (authorize + capture + refund) | Висока | 5–8 днів |
| Webhook-інтеграція з CRM/ERP | Середня | 2–4 дні |
| Кастомна логіка знижок | Середня | 3–4 дні |
| Плагін сповіщень (email/SMS) | Низька | 1–2 дні |
Що потрібно надати перед стартом
- Версія Saleor (3.x змінює сигнатури хуків відносно 2.x)
- Опис бізнес-логіки: які события перехоплюємо, який зовнішній API викликаємо
- Облікові дані тестового оточення
- Вимоги до конфігурації через Dashboard (потрібні таємні поля?)
Розробка проводиться в окремому Python-пакеті, підключеному через pip install -e. Це дозволяє версіонувати плагін незалежно від ядра Saleor і оновлювати його без форкування.







