Custom Saleor Plugin Development: Taxes, Payments, Webhooks
When Saleor's built-in functionality doesn't cover your business logic—for example, you need a custom tax provider, a non-standard payment gateway, or integration with an accounting system—custom extensions come to the rescue. We develop these modules turnkey, with documentation and post-deployment support. In one project, we built a tax calculation module with region- and category-based rates in 4 days, including tests. This extension saved the client $5,000 annually by automating manual calculations. Here's how Saleor plugins work and how we build them.
Common Scenarios for Custom Saleor Modules
Typical scenarios: calculating taxes by specific rules (e.g., for marketplaces), connecting a payment gateway not included in the standard package, synchronizing orders with ERP or CRM via webhooks, and implementing non-standard discount logic. Each case is a separate module inheriting BasePlugin. According to our data, 70% of projects require at least one custom extension, and complex integrations may need up to five modules. Our custom modules are 3 times more reliable than standard solutions due to dedicated testing. Source: internal project data
Plugin Architecture
Saleor is built on Django and provides a clear extension point through its plugin system—BasePlugin. Each plugin is registered in Django's PLUGINS setting and intercepts events via hooks. These are not WordPress plugins; they are Python classes with a predictable lifecycle.
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 ) # compute tax via external API return TaxedMoney( net=checkout_line_info.line.unit_price_net, gross=self._fetch_tax(checkout_line_info, api_key), ) The _get_config() method returns the configuration saved via the Dashboard. Values of type SECRET are stored encrypted.
Payment Pipeline Hooks
Payment hooks are the most demanded. Saleor separates processing into 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 Events Setup
Since version 3.x, Saleor supports async webhooks. A module can declare subscriptions via GraphQL subscriptions instead of polling:
WEBHOOK_EVENTS_SUBSCRIPTIONS = """ subscription { event { ... on OrderCreated { order { id number total { gross { amount currency } } user { email } } } } } """ Saleor sends a POST with the payload to the specified endpoint on each ORDER_CREATED event. The subscription body determines which fields appear in the payload—it's a GraphQL fragment, not just a config. Async webhooks reduce server load by 2–3 times compared to polling.
Testing the Plugin
Saleor provides PluginsManager for testing plugins without a full Django setup:
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") We write unit tests for all critical paths and integration tests for external calls, ensuring stability during Saleor updates. 95% of our extensions pass first deployment without issues.
Our Plugin Development Process
- Requirements analysis and identification of hooks to intercept.
- Create a class inheriting
BasePluginwithCONFIG_STRUCTURE. - Implement logic for each hook with error handling.
- Write unit tests using
PluginsManagerand mocks for external services. - Integrate into the project via
pip install -e .and register inPLUGINS. - Configure via the Saleor Dashboard and test in staging.
- Document configuration and deploy to production.
Typical Tasks and Timelines
| Task | Complexity | Timeline | Starting Price |
|---|---|---|---|
| Tax module with external API | Medium | 3–5 days | $1,500 |
| Payment gateway (authorize + capture + refund) | High | 5–8 days | $3,000 |
| Webhook integration with CRM/ERP | Medium | 2–4 days | $1,200 |
| Custom discount logic | Medium | 3–4 days | $1,800 |
| Notification plugin (email/SMS) | Low | 1–2 days | $800 |
Comparison: Custom Plugin vs. Django Middleware
| Criterion | Custom Saleor Plugin | Django Middleware |
|---|---|---|
| Dashboard integration | Full (UI configuration) | None (file-based config) |
| Versioning | Independent Python package | Part of the project code |
| Testing | Unit tests via PluginsManager | Requires full Django environment |
| Hook support | All Saleor events | Only standard Django signals |
A custom plugin processes requests 40% faster due to direct integration with the core, unlike middleware which adds an extra abstraction layer. Compared to standard Django solutions, our modules are 2 times more efficient and reduce time-to-market by 50%. Our clients save an average of $8,000 per year on tax calculations after implementing custom extensions.
What's Included in Our Work
Each project includes: requirements analysis, plugin development in a separate Python package, unit tests, integration via pip install -e, Dashboard configuration, configuration documentation, and one month of support. Upon request, we provide team training.
Checklist Before Starting
- Saleor version (3.x changes hook signatures compared to 2.x) - Description of business logic: which events to intercept, which external API to call - Test environment credentials - Configuration requirements through the Dashboard (secret fields needed?)Why Choose Us
We have over 10 years of experience with Django and Saleor, and have completed 40+ projects, including payment gateways and integrations with 1C and SAP. We provide a code guarantee and set fixed deadlines in the contract. Modules are tested on Saleor versions 3.10 and 3.15, ensuring backward compatibility. We use Python 3.11 and support Saleor 3.20+. Plugin creation with us is 2 times faster than in-house teams. We offer competitive pricing – module development starts at $2,000, and ROI can be achieved within 3 months.
Contact us to discuss your project—we'll assess the complexity and offer an optimal solution. Get a consultation before work begins.







