Synchronizacja zamówień z IdoSell do systemu zewnętrznego
Wzorce integracji dla developerów: webhook czy polling, jak zapewnić idempotentność, jak zbudować retry z backoff, jak obsłużyć rozjazdy statusów. Praktyczny przewodnik po scenariuszach, w których integracja się psuje — i jak temu zapobiec.
CZAS CZYTANIA: ~13 MIN · POZIOM: TECHNICZNY
Synchronizacja zamówień z IdoSell do zewnętrznego systemu (ERP, CRM, WMS, custom app) wydaje się prosta — pobierz zamówienie, wyślij do systemu, gotowe. Rzeczywistość jest bardziej niuansowa: zamówienie ma stan, który się zmienia w czasie; sieć czasami zawodzi; system docelowy bywa niedostępny; klient anuluje zamówienie zanim wpadło do ERP. Ten wpis pokazuje wzorce, które sprawiają, że integracja działa niezawodnie — nie tylko w happy path, ale i w scenariuszach awaryjnych.
Kiedy synchronizacja zamówień jest potrzebna
Sklep IdoSell w wielu przypadkach działa samowystarczalnie — panel obsługuje zamówienia, wystawia faktury, aktualizuje statusy. Integracja z zewnętrznym systemem jest potrzebna, gdy jedno z tych stwierdzeń jest prawdą:
Dla scenariuszy „przekazania zamówień do księgowości" IdoSell ma natywne integracje z popularnymi polskimi systemami (opisaliśmy je w wpisie o sprzedaży zagranicznej). Ten wpis dotyczy custom integracji — gdy natywne nie wystarczają.
Co dokładnie synchronizujemy
„Synchronizacja zamówień" to skrót — pod nim kryje się kilka strumieni danych z różnymi wymogami niezawodności:
Nowe zamówienia (event: order.created)
Kluczowy strumień. Każde nowe zamówienie z IdoSell musi trafić do systemu docelowego. Zawartość: dane klienta, produkty (SKU, ilość, cena), metoda dostawy, metoda płatności, adres wysyłki, kwota zamówienia. Bez tego strumienia nic dalej nie zadziała.
Zmiany statusu (event: order.status_changed)
Klient anulował zamówienie w panelu klienta, obsługa ręcznie zmieniła status, płatność została zaksięgowana. Każda zmiana statusu w IdoSell powinna aktualizować status w systemie docelowym. Częste źródło niespójności danych — jeśli synchronizacja tylko dodaje nowe zamówienia, a nie aktualizuje istniejące, oba systemy szybko się rozjeżdżają.
Zmiany w zamówieniu (event: order.modified)
Obsługa dodała produkt do zamówienia, zmieniła adres wysyłki, zaktualizowała kwotę (np. rabat). Rzadziej występuje niż zmiana statusu, ale jest istotny — bez synchronizacji zmian, system docelowy ma nieaktualne dane.
Zwroty i reklamacje (event: order.returned)
Klient zwrócił zamówienie w części lub całości. To osobny strumień, bo dane zwrotu różnią się od danych zamówienia (jakie produkty zwrócone, jaka kwota do zwrotu, kiedy zwrot zaakceptowany). Wymaga aktualizacji stanu magazynowego w systemie docelowym.
Kierunek zwrotny (system → IdoSell)
To często pomijany element. Gdy zamówienie jest przetworzone w ERP (spakowane, wysłane), status musi wrócić do IdoSell, żeby panel klienta go pokazał, żeby klient dostał powiadomienie o wysyłce. Bez tego klient dzwoni z pytaniem „gdzie moja paczka".
Webhook vs polling — dwa fundamentalne wzorce
Sposób, w jaki system docelowy dowiaduje się o nowym zamówieniu — najważniejsza decyzja architektoniczna. Dwa podejścia, każde z innymi kompromisami:
Webhook — push notification z IdoSell
IdoSell po utworzeniu zamówienia wysyła HTTP POST na Twój endpoint. Ty odbierasz, przetwarzasz, zwracasz 2xx status. Plus: real-time, niska latencja, brak zbędnych zapytań. Minus: wymaga publicznego endpointu (HTTPS), musisz obsłużyć restart własnej infrastruktury (webhook może przyjść w niedostępny moment), weryfikacja autentyczności.
Polling — pobieranie zmian z IdoSell API
Twój system co N minut wysyła zapytanie do IdoSell API: „daj mi zamówienia utworzone po timestamp X". Przetwarzasz każde nowe zamówienie, aktualizujesz timestamp cursora. Plus: proste do zaimplementowania, odporne na przerwy Twojej infrastruktury (nie tracisz nic, „doholujesz" po restarcie). Minus: latencja (do N minut opóźnienia), zbędne zapytania w okresach bez zamówień.
Kompromis: hybrydowy model
Najbardziej niezawodne rozwiązanie w praktyce: webhook jako główny kanał + polling jako fallback. Webhook daje real-time, polling co godzinę weryfikuje, że żadne zamówienie nie zostało zgubione (np. przez chwilową awarię endpointu). Polling wtedy staje się nie primary, a safety net.
Kiedy który wzorzec
IdoSell API dla zamówień
IdoSell udostępnia dwie warstwy API dla zamówień: admin (v8 lub nowszy, dla operacji sklepowych) i gate (v5, dla integracji zewnętrznych). Wybór zależy od kontekstu:
Endpointy zamówień w admin API
Pełen zakres operacji: pobieranie zamówień z filtrami (po dacie, statusie, klientach), tworzenie nowych, modyfikacja istniejących, dodawanie notatek, zmiana statusów. Autoryzacja przez klucz API konfigurowany w panelu. Limit zapytań: typowo kilka na sekundę per klucz, przy większym wolumenie warto negocjować podniesienie limitów.
Paginacja i cursor
IdoSell zwraca zamówienia stronicowane. Domyślnie od strony 0 (nie 1 — częsty błąd), zwykle 100 wyników na stronę. Dla pełnego pobrania musisz iterować przez wszystkie strony. Praktyczna wskazówka: filtruj po dacie modyfikacji, nie utworzenia — dostajesz wtedy też zamówienia, których status się zmienił, nie tylko nowe.
Webhook — konfiguracja w panelu IdoSell
IdoSell pozwala skonfigurować URL webhooka w panelu (opcja „Dodatki i integracje" → „Powiadomienia HTTP"). Wskazujesz URL, wybierasz zdarzenia (nowe zamówienie, zmiana statusu, itd.), IdoSell wysyła POST z JSON payloadem. Ważne: IdoSell nie wysyła całego zamówienia w webhooku — tylko ID i typ zdarzenia. Ty musisz odpytać API po szczegóły. To celowe (mniejszy payload, bezpieczeństwo), ale wymaga dodatkowego zapytania.
Weryfikacja autentyczności webhooka
IdoSell może podpisywać webhooki tokenem (konfigurowanym w panelu). Twój endpoint musi weryfikować, że request faktycznie przyszedł z IdoSell, a nie od atakującego. Bez tego ktoś mógłby wysłać do Twojego endpointu spreparowany webhook i sfałszować zamówienie w Twoim systemie. Podstawowe zabezpieczenie: sprawdzenie tokenu w headerze przed przetworzeniem payloadu.
Idempotentność — dlaczego kluczowa
Idempotentność znaczy, że powtórzenie tej samej operacji daje ten sam wynik. W kontekście synchronizacji zamówień: przetworzenie tego samego zamówienia dwukrotnie nie może skutkować dwiema fakturami, dwiema wysyłkami, dwoma rezerwacjami magazynowymi.
Dlaczego to problem
Webhook może być wysłany dwukrotnie (retry po timeoutcie), polling może pobrać to samo zamówienie w dwóch iteracjach (jeśli źle zaimplementowany cursor), system docelowy może przetworzyć zamówienie i timeoutować przed potwierdzeniem — po restarcie IdoSell wyśle jeszcze raz. W każdym z tych scenariuszy potrzebujesz mechanizmu, który rozpozna „już to widziałem" i nie przetworzy duplikatu.
Wzorzec: klucz idempotencji w bazie
Najprostsza implementacja: w bazie po stronie systemu docelowego trzymasz tabelę
processed_orders (idosell_order_id, processed_at, target_system_id). Przed
przetworzeniem zamówienia sprawdzasz, czy idosell_order_id już istnieje. Jeśli tak —
zwracasz sukces bez ponownego przetwarzania. Jeśli nie — przetwarzasz, zapisujesz do tabeli
w tej samej transakcji.
Pułapka: race condition
Naiwna implementacja może mieć problem: sprawdzasz „czy istnieje", widzisz „nie", zaczynasz przetwarzać — w tym momencie drugi webhook robi to samo. Rozwiązanie: UNIQUE constraint na idosell_order_id w bazie. Drugi INSERT rzuci błędem, który obsługujesz jako „duplikat, zignoruj". Baza gwarantuje atomiczność, ty nie musisz o niej myśleć.
Idempotentność dla aktualizacji statusów
Aktualizacja statusu też powinna być idempotentna. Trik: zamiast „ustaw status na X" wysyłaj
„ustaw status na X jeśli obecny to Y (poprzedni)". W SQL: UPDATE orders SET status='paid'
WHERE order_id=? AND status='pending'. Powtórne wywołanie z tym samym payloadem po prostu
zaktualizuje 0 wierszy — bez efektów ubocznych.
Retry z exponential backoff
System docelowy chwilowo niedostępny (deploy, awaria, przeciążenie). Bez retry — zamówienie zgubione. Z niepoprawnym retry — DoS na własny system podczas przywrócenia. Poprawny wzorzec:
Exponential backoff — czasy między próbami
Każda kolejna próba po dłuższej przerwie: 1s, 2s, 4s, 8s, 16s, 32s, 64s. Zapobiega „grzybieniu" requestów na system, który dopiero wstaje. Praktyczne górne ograniczenie: 5-7 prób przez 2-5 minut, potem porzucamy i wpisujemy do kolejki „manual review".
Jitter — losowy dodatek do backoff
Bez jitter wszystkie retry przychodzą jednocześnie (co 2s, co 4s...). Z 10 klientów wszystkie uderzają w system w tym samym momencie. Dodaj losową odchyłkę ±25% do każdego backoff: 1s ± 250ms, 2s ± 500ms itp. Rozkłada requesty w czasie.
Rozróżnianie błędów: retryable vs terminal
Dead letter queue (DLQ) — dla zamówień, których nie da się przetworzyć
Po wyczerpaniu retry, zamówienie ląduje w DLQ z pełną historią prób. Manualne narzędzie (dashboard dla ops-teamu) pokazuje takie zamówienia, admin może ponowić po naprawie problemu albo oznaczyć jako „ręcznie obsłużone". Bez DLQ awarie zewnętrznego systemu prowadzą do niewidocznej utraty danych.
Kierunek zwrotny — system → IdoSell
Zamówienie przetworzone w ERP, spakowane, nadane — status musi wrócić do IdoSell. To osobny strumień z osobnymi wyzwaniami:
Aktualizacja statusu w IdoSell przez API
IdoSell API pozwala aktualizować status zamówienia. Mapowanie statusów z systemu docelowego na IdoSell (najczęstsze: „wysłane" → „sent", „zwrócone" → „returned") wymaga świadomej decyzji, bo oba systemy mają różne słowniki. Zaleca się utrzymywanie mapowania w konfiguracji, nie hardcode.
Dodawanie numeru śledzenia
Po nadaniu paczki w systemie logistycznym dostajesz tracking number. Ten numer musi trafić do zamówienia w IdoSell, żeby klient go zobaczył w panelu i dostał link do śledzenia w mailu. IdoSell przyjmuje tracking przez API — dodajesz przy aktualizacji statusu na „wysłane".
Konflikty stanu
Scenariusz: system docelowy chce ustawić status na „wysłane", ale w IdoSell obsługa już ustawiła na „anulowane" (klient dzwonił, chciał anulacji). Kierunek zwrotny nie powinien nadpisać „anulowane" na „wysłane" — trzeba wykryć konflikt i zgłosić do manualnej weryfikacji. Trik: optimistic locking (wysyłaj „ustaw wysłane jeśli obecny to nowy") ochrania przed nadpisaniem.
Obsługa błędów i monitoring
Integracja bez monitoringu to bomba zegarowa — nie wiesz, że nie działa, dopóki klient nie zadzwoni. Cztery kluczowe elementy każdej produkcyjnej integracji:
Logging każdego zdarzenia
Log wpis dla każdego webhooka (przyjęcia i wyniku), każdej próby retry, każdej odpowiedzi API IdoSell. Format strukturalny (JSON), z timestampem, order_id, event_type, result. Pozwala odtworzyć każdy scenariusz post-factum — kluczowe przy diagnozie „dlaczego to zamówienie nie trafiło do ERP 3 dni temu".
Metryki dla dashboardu
Alerty na krytyczne zdarzenia
Reconciliation — codzienna weryfikacja spójności
Nocne zadanie porównuje: ile zamówień w IdoSell z ostatnich 24h vs ile w systemie docelowym. Rozjazd >0 to sygnał, że jakieś zamówienie zostało zgubione. Skrypt reconciliation raportuje i (opcjonalnie) automatycznie retryuje brakujące zamówienia. Klucz do „nigdy nie tracimy zamówień" — bez tego integracja się rozjeżdża, wiesz dopiero po tygodniach.
Najczęstsze pułapki
Synchronizacja zamówień tylko w jedną stronę
Częsty błąd MVP: synchronizujemy nowe zamówienia, ale nie aktualizacje statusów. Po tygodniu oba systemy się rozjeżdżają: IdoSell mówi „opłacone", ERP wciąż widzi „oczekujące". Konieczna bidirectional synchronization od dnia 1.
Brak weryfikacji autentyczności webhooka
Endpoint webhooka publiczny, bez sprawdzania tokenu. Atakujący może wysłać spreparowany webhook z fałszywym zamówieniem. Konsekwencje: fałszywe faktury, ruszona logistyka, wysyłka „na koszt sklepu". Weryfikacja tokenu w headerze — 5 minut pracy, ratuje przed katastrofą.
Timeout w endpointcie webhooka
Endpoint po odebraniu webhooka od razu wchodzi w ciężkie przetwarzanie (walidacja, kilka zapytań do bazy, kilka wywołań API). Po 30 sekundach timeout, IdoSell traktuje jako nieudane i retry. Wzorzec: endpoint tylko zapisuje payload do kolejki (SQS, Redis, RabbitMQ) i zwraca 200 OK w <1s. Osobny worker przetwarza z kolejki w tle. Rozdziel przyjęcie od przetworzenia.
Brak idempotentności
Pierwszy webhook przyszedł, przetworzył zamówienie, ale timeoutował przed odpowiedzią. IdoSell wysyła retry, drugi webhook tworzy drugą fakturę, drugą wysyłkę. Klient dostaje 2 paczki, ty księgujesz 2 przychody. Bez UNIQUE constraint na order_id to wszystko jest realne.
Ignorowanie limitów API IdoSell
Duży sklep, restart integracji po awarii — worker próbuje „doholować" 10 000 zamówień, wysyłając zapytania do API IdoSell w pełnej prędkości. IdoSell zwraca 429 Too Many Requests i tymczasowo blokuje klucz. Wzorzec: rate limiter po stronie workera, respektujący nagłówki Retry-After. Znacznie lepiej „doholować" w 30 minut niż zostać zablokowanym.
Brak testów na środowisku staging
Integracja pisana i testowana bezpośrednio na produkcji. Każdy błąd = realny problem klienta. IdoSell udostępnia klucze testowe/staging — użyj ich. Pełen test end-to-end (webhook → przetworzenie → aktualizacja zwrotna) na środowisku testowym przed wypuszczeniem na produkcję.
Kiedy samodzielnie, kiedy zlecić
Custom integracja z IdoSell to projekt na 2-8 tygodni pracy, zależnie od skomplikowania. Wybór między samodzielnym a zleconym:
Samodzielnie ma sens gdy
Zlecić ma sens gdy
Nasze doświadczenie
W IdoScale piszemy custom integracje z IdoSell od kilku lat — od prostych synchronizacji do ERP po zaawansowane wielosystemowe pipelines z reguły biznesowymi. Znamy klasyczne pułapki, wiemy gdzie szukać ograniczeń IdoSell API, mamy sprawdzone wzorce retry, idempotentności, monitoringu. Jeśli planujesz custom integrację i chcesz uniknąć nauki na własnych błędach — napisz do nas, zaczynamy od bezpłatnej konsultacji technicznej.
Podsumowanie
Synchronizacja zamówień z IdoSell do systemu zewnętrznego to nie „napisz endpoint i połącz" — to kilka warstw architektury, w których każda ma swoje wzorce. Kluczowe wnioski:
Integracje produkcyjne to nie coś, co pisze się w dwa dni. To 2-8 tygodni z uwzględnieniem wszystkich edge cases, testowaniem na staging, monitoringiem po wdrożeniu. Ale zrobione poprawnie — działają latami bez potrzeby ingerencji. Jeśli chcesz zbudować taką integrację dla swojego sklepu IdoSell, porozmawiajmy o konkretnym zakresie i budżecie.