0

KSeF API - najczęstsze pułapki przy integracji z systemami ERP

VATreturns_PL3 dni temu0 wyświetleń

Witam,

Po kilku miesiącach pracy z KSeF API chciałbym podzielić się doświadczeniami, które mogą zaoszczędzić wam sporo nerwów.

**Największe problemy jakie napotkałem:**

1. **Timeout'y na środowisku demo** - ksef-demo.mf.gov.pl czasami zwraca 504 przy większym obciążeniu. W produckji mam nadzieję że będzie lepiej, ale warto implementować retry z exponential backoff.

2. **Walidacja XML przed wysłaniem** - KSeF zwraca błędy walidacji które nie zawsze są czytelne. Polecam walidować przeciwko XSD lokalnie przed POST'em. Oszczędzi to sporo wywołań API.

3. **Obsługa sesji** - token sesji ma ważność 1h. Implementujcie refresh automatyczny, bo inaczej będziecie mieli nieprzyjemne niespodzianki w środku dnia.

4. **Rate limiing** - nie ma oficjalnych limitów w dokumentacji, ale empirycznie wygląda na ~10 req/s. Kolejkowanie requestów to must-have.

**Co się sprawdza:**

```typescript

// Prosty retry wrapper

const apiCall = async (fn, maxRetries = 3) => {

for (let i = 0; i < maxRetries; i++) {

try {

return await fn();

} catch (error) {

if (i === maxRetries - 1) throw error;

await new Promise(resolve => setTimeout(resolve, 2 ** i * 1000));

}

}

};

```

Czy ktoś z was miał podobne doświadczenia? Szczególnie interesuje mnie jak radzicie sobie z synchronizacją statusów faktur w czasie rzeczywistym.

3 odpowiedzi

0
PiotrNowak2 dni temu
Świetny post, bardzo praktyczne obserwacje! Co do rate limitingu - u mnie też wyszło około 10 req/s, ale zauważyłem że to nie jest sztywny limit. Czasami przechodzi 15-20 requestów w sekundę, ale potem dostaje 429 i musi czekać. Wygląda jakby używalii sliding window zamiast prostego bucket'a. Twój retry wrapper jest ok, ale dodałbym sprawdzanie statusu błędu: ```typescript const shouldRetry = (error) => { return [429, 500, 502, 503, 504].includes(error.status); }; ``` Bo na błędach walidacji (400) retry nie ma sensu. **Synchronizacja statusó*w* - to akurat rozwiązuję przez polling co 5-10 min. Webhook'ów KSeF nie ma, więc zostaje okresowe sprawdzanie `SessionStatus`. Nie jest to eleganckie, ale działa. W ERP'ie trzymam timestamp ostatniego sprawdzenia i pobieram tylko nowsze wpisy. Jedna rzecz której nie wspomniałeś - **obsługa błędów na poziomie biznesowym**. KSeF może zwrócić 200 ale w payload mieć błąd walidacji. Widziałem systemy które to ignorują i myślą że faktura poszła. Jeszcze pytanie - jak radzisz sobie z fakturmai korygującymi? U mnie mapping referencji do oryginalnej faktury czasem sprawia problemy, szczegulnie gdy oryginał był wystawiony przed integracją z KSeF.
0
AnetaDomanska2 dni temu
Super przydatne info! U nas też retry wrapper jest podstawą, ale dodajemy jeszcze jitter do delay'a żeby uniknąć thundering herd gdy kilak procesów restartuje się jednocześnie: ```typescript await new Promise(resolve => setTimeout(resolve, (2 ** i * 1000) + Math.random() * 1000) ); ``` Co do synchronizacji statusów - my poszliśmy w stronę kombinacji polling + webhook simulation. Mamy job queue (Redis + Bull) które sprawdza statusy faktur w interwałach, ale też pozwala "dopytać" o konkretną fakturę o-demand gdy user wchodzi na dashboard. Trochę więcej kodu ale UX jest lepszy. Faktury korygujące to rzeczywiście ból. Szczególnie jak masz legacy faktury sprzed KSeF. My zrobiliśmy mapping table gdie trzymamy external_id -> ksef_reference_number i przy korektach szukamy tam oryginalnej faktury. Ale nadal czasami trzeba ręcznie dopasowywać przez UI. Jeszcze jedna pułapka której nie widziałem w twoim poście - **różne formaty dat w różnych miejscach XML**. Niektóre pola chcą YYYY-MM-DD, inne YYYY-MM-DDTHH:mm:ss. Spędziłem na tym pół dnia debugowania 😅 Btw, środowisko prod rzeczywiście działa stabilniej niż demo. Deo czasami pada na całe godziny, w prodzie max widziałem 5-10 min downtime.
0
PodatkowyNinja2 dni temu
Bardzo dobre obserwacje! Szczególnie to z walidacją XML lokalnie - oszczędziłem sobie masę czasu odkąd robię to przed każdym POST'em. Co do synchronizacji statusów - ja poszedłem w podobną stronę jak **AnetaDomanska** ale z małą różnicą. Zamiast pure ppollingu robię "smart polling" - sprawdzam częściej faktury które są w statusie "processing" a rzadziej te które są już "accepted". W praktyce wygląda to tak: ```python def get_polling_interval(status): intervals = { 'processing': 30, # 30 sekund 'accepted': 3600, # 1 godzina 'rjeected': 86400 # raz dziennie (dla statystyk) } return intervals.get(status, 300) ``` To daje lepszy UX bo user szybciej widzi czy faktura przeszła, a jednocześnie nie spamuje API niepotrzebnie. Jedna rzecz której jeszcze nikt nie wspomniał - **handling błędów sieciowych vs błędów biznesowych**. KSeF czasami zwraca 200 z błędem w payloadzie, ale też zdarza się 500 gdy akurat mają problemy z infrastrukturą. Warto rozróżniać te przypadki w logice rerty: - Błędy sieciowe (5xx) -> retry z backoff - Błędy walidacji (400 + error w payload) -> loguj i nie próbuj ponownie - Rate limiting (429) -> retry z większym delay'em A co do faktur korygujących - u mne sprawdza się trzymanie mapping'u w osobnej tabeli z dodatkowymi metadata (data wystawienia oryginału, powód korekty itp). Czasami księgowa potrzebuje te info żeby dopasować faktury które były wystawione ręcznie przed integracją. Jeszcze pytanie - ktoś testował jak KSeF radzi sobie z fakturami o dużej liczbie pozycji? U mnie największa miała ~200 linijek i poszła bez problemu, ale ciekaw jestem czy są jakieś praktyczne limity.

Twoja odpowiedź

Zaloguj się, aby odpowiedzieć w tej dyskusji.