Wtyczka integrująca BaseLinker z platformą e-commerce Sylius ^2.1. Zbudowana w warstwowej architekturze inspirowanej DDD z wydzieleniem warstw Application / Domain / Infrastructure / UI oraz asynchronicznym przetwarzaniem komend przez Symfony Messenger.
| Zależność | Wersja |
|---|---|
| PHP | ^8.1 |
| Sylius | ^2.1 |
| Symfony | ^7.0 |
| MySQL/MariaDB | dowolna wspierająca utf8mb4 |
composer require darksidepro/sylius-baselinker-pluginW config/bundles.php:
return [
// ...
DarkSidePro\SyliusBaselinkerPlugin\DarkSideProSyliusBaselinkerPlugin::class => ['all' => true],
];W config/packages/acme_sylius_baselinker.yaml (utwórz plik jeśli nie istnieje):
# config/packages/acme_sylius_baselinker.yaml
DarkSidePro_sylius_baselinker:
api:
token: '%env(BASELINKER_API_TOKEN)%'
endpoint: 'https://api.baselinker.com/connector.php'
timeout: 30
max_retries: 3
rate_limit: 5
synchronization:
enabled: true
interval: 300
batch_size: 100
features:
orders:
enabled: '%env(bool:BASELINKER_ORDERS_ENABLED)%'
auto_export: '%env(bool:default:true:BASELINKER_ORDERS_AUTO_EXPORT)%'
auto_sync_status: '%env(bool:default:true:BASELINKER_ORDERS_AUTO_SYNC_STATUS)%'
confirmed_only: true
products:
enabled: '%env(bool:BASELINKER_PRODUCTS_ENABLED)%'
auto_sync: '%env(bool:default:true:BASELINKER_PRODUCTS_AUTO_SYNC)%'
default_inventory_id: '%env(int:default::BASELINKER_DEFAULT_INVENTORY_ID)%'
inventory:
enabled: '%env(bool:BASELINKER_INVENTORY_ENABLED)%'
sync_stock: '%env(bool:default:true:BASELINKER_INVENTORY_SYNC_STOCK)%'
default_warehouse_id: '%env(default:bl_1:BASELINKER_DEFAULT_WAREHOUSE_ID)%'
shipping:
enabled: '%env(bool:default:false:BASELINKER_SHIPPING_ENABLED)%'W config/routes.yaml:
DarkSidePro_baselinker_webhook:
resource: '../../vendor/darksidepro/sylius-baselinker-plugin/config/routes/webhook.yaml'
DarkSidePro_baselinker_operations:
resource: '../../vendor/darksidepro/sylius-baselinker-plugin/config/routes/operations.yaml'W config/packages/messenger.yaml dodaj routing komend (lub zaimportuj plik z pluginu):
framework:
messenger:
default_bus: command.bus
buses:
command.bus:
middleware: [validation, doctrine_transaction]
query.bus:
middleware: [validation]
event.bus:
default_middleware: allow_no_handlers
transports:
async:
dsn: '%env(MESSENGER_TRANSPORT_DSN)%'
retry_strategy:
max_retries: 3
delay: 1000
multiplier: 2
sync:
dsn: 'sync://'
routing:
'DarkSidePro\SyliusBaselinkerPlugin\Application\Command\Order\ImportOrderFromBaselinkerCommand': async
'DarkSidePro\SyliusBaselinkerPlugin\Application\Command\Order\ExportOrderToBaselinkerCommand': async
'DarkSidePro\SyliusBaselinkerPlugin\Application\Command\Order\SynchronizeOrderStatusCommand': async
'DarkSidePro\SyliusBaselinkerPlugin\Application\Command\Product\SyncProductToBaselinkerCommand': async
'DarkSidePro\SyliusBaselinkerPlugin\Application\Command\Inventory\UpdateProductStockCommand': async
'DarkSidePro\SyliusBaselinkerPlugin\Application\Command\Inventory\SyncStockFromBaselinkerCommand': asyncPlugin tworzy trzy własne tabele. Wykonaj migrację ręcznie lub przez narzędzie migracji:
Uwaga: Przy rozbudowie obsługi wariantów schemat może zostać uzupełniony o dodatkową tabelę mapowania wariantów — sprawdź katalog
migrations/po aktualizacji pluginu.
# Ręcznie przez migrację SQL:
mysql -u user -p dbname < vendor/darksidepro/sylius-baselinker-plugin/migrations/001_initial_schema.sqlTabele:
| Tabela | Opis |
|---|---|
DarkSidePro_baselinker_order_mapping |
Mapowanie ID zamówień Sylius ↔ BaseLinker |
DarkSidePro_baselinker_product_mapping |
Mapowanie ID produktów Sylius ↔ BaseLinker |
DarkSidePro_baselinker_sync_log |
Log operacji synchronizacji |
Skopiuj .env.example i uzupełnij wartości:
# API
BASELINKER_API_TOKEN=your_api_token_here
BASELINKER_WEBHOOK_SECRET=your_webhook_secret_here
BASELINKER_BASE_URL=https://twojsklep.pl
# Magazyn i inwentarz
BASELINKER_DEFAULT_INVENTORY_ID=307
BASELINKER_DEFAULT_WAREHOUSE_ID=bl_1
BASELINKER_DEFAULT_PRICE_GROUP_ID=
# Mapowanie statusów (Sylius state => BaseLinker status ID)
BASELINKER_STATUS_NEW=6624
BASELINKER_STATUS_FULFILLED=6625
BASELINKER_STATUS_CANCELLED=6626
BASELINKER_IMPORT_LOCALE=pl_PL
# Opcjonalne mapowania statusów płatności/wysyłki (0 = wyłączone)
BASELINKER_STATUS_PAYMENT_PAID=0
BASELINKER_STATUS_PAYMENT_PARTIALLY_PAID=0
BASELINKER_STATUS_PAYMENT_REFUNDED=0
BASELINKER_STATUS_SHIPPING_SHIPPED=0
BASELINKER_STATUS_SHIPPING_PARTIALLY_SHIPPED=0
# Feature flags
BASELINKER_ORDERS_ENABLED=true
BASELINKER_ORDERS_AUTO_EXPORT=true
BASELINKER_ORDERS_AUTO_SYNC_STATUS=true
BASELINKER_PRODUCTS_ENABLED=true
BASELINKER_PRODUCTS_AUTO_SYNC=true
BASELINKER_INVENTORY_ENABLED=true
BASELINKER_INVENTORY_SYNC_STOCK=true
BASELINKER_SHIPPING_ENABLED=false
# Messenger
MESSENGER_TRANSPORT_DSN=doctrine://default- Eksport zamówień z Sylius do BaseLinker (automatyczny po złożeniu lub ręczny)
- Import zamówień z BaseLinker do Sylius
- Synchronizacja statusów — zdarzenia Sylius (zmiana stanu zamówienia, płatności, wysyłki) są mapowane na statusy BaseLinker
- Mapowanie statusów odbywa się przez zmienne środowiskowe (
BASELINKER_STATUS_*)
- Eksport produktów do katalogu BaseLinker (batch lub per-produkt)
- Podstawowe wsparcie wariantów produktów; pełne mapowanie wielowariantowe zależy od konfiguracji i modelu danych integracji
- Opcja synchronizacji wyłącznie produktów bez istniejącego mapowania (
--unmapped-only)
- Synchronizacja stanów magazynowych z BaseLinker do Sylius
- Stan pobierany z jednego magazynu określonego przez
BASELINKER_DEFAULT_WAREHOUSE_ID(domyślniebl_1) — sumowanie wielu magazynów nie jest aktualnie obsługiwane - Obsługa webhooków aktualizacji stanu (
/baselinker/webhook/stock) - Weryfikacja podpisu webhooków przez nagłówek
X-BLToken
| Obszar | Ograniczenie |
|---|---|
| Warianty produktów | Przy braku jawnego mapowania wariant→BaseLinker produkt może być wysłany z danymi rodzica; pełne wsparcie wielowariantowe wymaga weryfikacji konfiguracji |
| Stan magazynowy | Synchronizacja z jednego magazynu; obsługa wielu magazynów wymaga własnej implementacji StockSyncServiceInterface |
| Import zamówień | Przy braku mapowania statusu BaseLinker → Sylius zamówienie importowane jest ze statusem new; nieznane statusy nie blokują importu |
# Import zamówień z ostatnich 7 dni (domyślnie)
php bin/console baselinker:orders:import
# Import zamówień z ostatnich 30 dni, limit 200
php bin/console baselinker:orders:import --days=30 --limit=200 --confirmed-only
# Eksport wszystkich zamówień do BaseLinker
php bin/console baselinker:orders:export
# Synchronizacja produktów do BaseLinker
php bin/console baselinker:products:sync --inventory-id=307
# Tylko produkty bez istniejącego mapowania, batch po 50
php bin/console baselinker:products:sync --inventory-id=307 --unmapped-only --batch-size=50
# Test połączenia z API BaseLinker
php bin/console baselinker:test-connectionWszystkie endpointy wymagają uprawnień administracyjnych Sylius.
| Metoda | Ścieżka | Opis |
|---|---|---|
GET |
/admin/baselinker/orders/list |
Lista zamówień z BaseLinker |
POST |
/admin/baselinker/order/import |
Importuj zamówienie po order_id |
POST |
/admin/baselinker/order/export |
Eksportuj zamówienie po order_id |
POST |
/admin/baselinker/orders/export-batch |
Batch eksport zamówień |
POST |
/admin/baselinker/stock/sync |
Synchronizacja stanów magazynowych |
| Metoda | Ścieżka | Opis |
|---|---|---|
POST |
/baselinker/webhook/order |
Powiadomienie o zmianie zamówienia |
POST |
/baselinker/webhook/stock |
Powiadomienie o zmianie stanu |
Webhooki weryfikują sygnaturę przez nagłówek X-BLToken (BASELINKER_WEBHOOK_SECRET).
Plugin stosuje warstwową architekturę inspirowaną DDD z podziałem na cztery warstwy:
src/
├── Application/ # Komendy, zapytania (CQRS), interfejsy serwisów
│ ├── Command/ # Commands + Handlers (Order, Product, Inventory)
│ ├── Query/ # Queries + Handlers
│ ├── EventHandler/ # Obsługa domain events
│ └── Service/ # Interfejsy: OrderMapper, ProductMapper, StockSync...
│
├── Domain/ # Czysta logika biznesowa (bez zależności infrastruktury)
│ ├── Order/ # Value objects, repo interfaces, domain events
│ ├── Product/ # Value objects, repo interfaces, domain events
│ └── Inventory/ # Value objects, repo interfaces, domain events
│
├── Infrastructure/ # Implementacje: HTTP client, mappery, repozytoria Doctrine
│ ├── Baselinker/ # BaselinkerHttpClient + wyjątki API
│ ├── EventListener/ # Subskrybenci zdarzeń Sylius (order state, product)
│ ├── Mapper/ # OrderMapper, ProductMapper
│ ├── Persistence/ # Repozytoria Doctrine + BaseLinker API
│ └── Service/ # StockSyncService, WebhookSignatureVerifier
│
└── UI/ # Interfejs użytkownika
├── Command/ # Komendy konsolowe (bin/console)
└── Controller/ # WebhookController, OperationsController
Wszystkie ciężkie operacje (import/eksport zamówień, sync produktów, aktualizacja stanu) są wysyłane przez Symfony Messenger na transport async. Zapytania (Query) i domain events działają synchronicznie.
Wymagane jest uruchomienie workera:
php bin/console messenger:consume async --time-limit=3600Operacje integracyjne są projektowane jako idempotentne — ponowne przetworzenie tej samej komendy (np. przy retry po błędzie API) nie zduplikuje danych. Asynchroniczny transport oddziela czas odpowiedzi sklepu od opóźnień API BaseLinker, co zapewnia skalowalność przy dużym wolumenie zamówień.
Plugin udostępnia interfejsy, które możesz podmienić przez własne implementacje:
| Interfejs | Domyślna implementacja | Opis |
|---|---|---|
BaselinkerClientInterface |
BaselinkerHttpClient |
Klient HTTP API BaseLinker |
OrderMapperInterface |
OrderMapper |
Mapowanie Sylius Order ↔ BaseLinker |
ProductMapperInterface |
ProductMapper |
Mapowanie Sylius Product ↔ BaseLinker |
StockSyncServiceInterface |
StockSyncService |
Synchronizacja stanów magazynowych |
WebhookSignatureVerifierInterface |
WebhookSignatureVerifier |
Weryfikacja podpisów webhooków |
StockWebhookHandlerInterface |
StockWebhookHandler |
Obsługa webhooków stanu |
Nadpisanie przez alias w services.yaml:
services:
DarkSidePro\SyliusBaselinkerPlugin\Application\Service\Order\OrderMapperInterface:
alias: App\Integration\Baselinker\CustomOrderMapper# Unit testy
php vendor/bin/phpunit
# Analiza statyczna (PHPStan)
php vendor/bin/phpstan analyse src --level=max
# Code style
php vendor/bin/ecs check srcMIT — szczegóły w pliku LICENSE.