Architektura synchronizacji
Synchronizacja faktur w Stripto to pipeline złożony z 9 kroków. Każdy krok ma jasno zdefiniowaną odpowiedzialność, a awaria na dowolnym etapie nie powoduje utraty danych. Oto pełny diagram przepływu:
Stripe Event (np. invoice.finalized) │ ▼ Webhook Endpoint (POST /api/webhooks/stripe) │ ▼ Signature Verification (HMAC-SHA256, whsec_...) │ ▼ Event Parsing (JSON → typed object) │ ▼ Deduplication Check (event ID + transaction ID) │ ▼ Data Extraction (klient, kwota, waluta, NIP, opis) │ ▼ Invoice API Call (Fakturownia / inFakt REST API) │ ▼ KSeF Submission (przez system fakturowania) │ ▼ Status Update (completed / error → retry)
Kluczowa cecha tej architektury: pipeline jest idempotentny. Możesz wysłać to samo zdarzenie 10 razy i wynik zawsze będzie taki sam: jedna faktura. To gwarancja bezpieczeństwa w środowisku rozproszonym, gdzie webhooki mogą być dostarczane więcej niż raz.
Stripe Event → Webhook → Weryfikacja → Deduplikacja → Ekstrakcja danych → API fakturowania → KSeF → Status
Pipeline przetwarza zdarzenie w 3-5 sekund. Najdłuższy krok to wywołanie API systemu fakturowania (2-3 sekundy).
Diagram czasowy (latency per step)
Dokładne czasy na każdym etapie pipeline, mierzone na produkcyjnym ruchu Stripto:
T+0.0s Stripe wysyła webhook (event created)
T+0.8s Stripto odbiera POST request (~800ms network)
T+0.85s Weryfikacja podpisu HMAC-SHA256 (~50ms)
T+0.90s Parsowanie JSON + walidacja typu zdarzenia (~50ms)
T+1.00s Sprawdzenie deduplikacji w bazie danych (~100ms)
T+1.05s Ekstrakcja danych klienta i transakcji (~50ms)
T+1.10s Wywołanie API Fakturowni / inFakt (start)
T+3.50s Odpowiedź z API fakturowania (~2.4s)
T+3.55s Zapis statusu w bazie danych (~50ms)
T+3.60s Zwrot HTTP 200 do Stripe
─────────────────────────────────────────
Łączny czas: ~3.6s (typowy)Najwolniejszym elementem jest zawsze wywołanie zewnętrznego API systemu fakturowania. Weryfikacja, deduplikacja i ekstrakcja danych zajmują łącznie ok. 250 ms. Stripto zwraca HTTP 200 do Stripe w ciągu 20 sekund (limit Stripe), więc nawet przy wolnym API fakturowania zdarzenie nie zostanie ponowione niepotrzebnie.
Obsługiwane zdarzenia Stripe
Stripe generuje dziesiątki typów zdarzeń, ale tylko kilka z nich niesie dane potrzebne do wystawienia faktury VAT. Stripto nasłuchuje na cztery typy, z których każdy obsługuje inny scenariusz płatności.
| Zdarzenie | Kiedy się odpala | Jakie dane zawiera | Co robi Stripto |
|---|---|---|---|
| invoice.finalized | Stripe finalizuje fakturę za nowy okres rozliczeniowy subskrypcji | Customer ID, kwota, waluta, line_items (nazwa produktu, ilość, cena), okres rozliczeniowy, metadata | Wystawia fakturę VAT z pozycjami odpowiadającymi line_items subskrypcji |
| checkout.session.completed | Klient zakończył płatność przez Stripe Checkout lub Payment Link | Customer details (imię, email, adres), custom_fields (NIP), line_items, payment_intent, metadata | Wystawia fakturę z danymi z formularza Checkout, w tym NIP z custom field |
| payment_intent.succeeded | Płatność została potwierdzona (dowolna metoda: karta, BLIK, przelew) | Kwota, waluta, customer ID, payment_method, metadata, description | Używane jako alternatywne źródło, gdy checkout.session nie zawiera pełnych danych |
| charge.succeeded | Karta lub inna metoda płatności została obciążona | Kwota, waluta, billing_details (imię, adres), receipt_email, metadata | Fallback, gdy inne zdarzenia nie dotarły lub nie zawierają wystarczających danych |
Domyślna konfiguracja
Po podłączeniu konta Stripe, Stripto automatycznie włącza nasłuchiwanie na invoice.finalized i checkout.session.completed. Pozostałe zdarzenia możesz włączyć w ustawieniach, jeśli korzystasz z niestandardowych integracji Stripe API.
Porównanie metod synchronizacji
Webhook to nie jedyna metoda pobierania danych ze Stripe. Oto porównanie trzech podejść:
| Metoda | Czas reakcji | Niezawodność | Nakład pracy |
|---|---|---|---|
| Webhook (real-time) | 3-5 sekund | Wysoka (retry po stronie Stripe + Stripto) | Zerowy (Stripto konfiguruje automatycznie) |
| Polling (cykliczne odpytywanie) | 1-60 minut (zależy od interwału) | Średnia (zależy od implementacji, brak push) | Duży (własny scheduler, obsługa paginacji) |
| Ręczny eksport | Godziny do dni | Niska (zależy od człowieka, błędy ręczne) | Bardzo duży (każda transakcja osobno) |
Webhook to jedyna metoda, która łączy szybkość reakcji z niezawodnością i zerowym nakładem pracy po stronie użytkownika. Dlatego Stripto opiera się wyłącznie na webhookach.
Od webhooka do faktury krok po kroku
Zobaczmy dokładnie, co dzieje się na każdym etapie pipeline, z prawdziwymi przykładami payloadów JSON, jakie Stripe wysyła do Stripto.
Krok 1: Stripe wysyła webhook
Po zdarzeniu (np. finalizacji faktury za subskrypcję) Stripe wysyła request POST na endpoint Stripto. Oto skrócony payload zdarzenia invoice.finalized:
{
"id": "evt_1RBxYz2eZvKYlo2C0abc1234",
"type": "invoice.finalized",
"created": 1711008000,
"data": {
"object": {
"id": "in_1RBxYz2eZvKYlo2Cdef5678",
"customer": "cus_PqRsT1234567",
"customer_email": "jan.kowalski@firma.pl",
"customer_name": "Jan Kowalski",
"currency": "pln",
"amount_due": 29900,
"lines": {
"data": [
{
"description": "Stripto Pro Plan (Mar 21 - Apr 20)",
"amount": 29900,
"quantity": 1,
"period": {
"start": 1711008000,
"end": 1713686400
}
}
]
},
"metadata": {
"nip": "1234567890",
"company_name": "Firma Kowalski Sp. z o.o."
}
}
}
}Kwota amount_due jest w groszach (29900 = 299,00 zł). Dane klienta, email, nazwa i NIP (w metadata) to wszystko, czego Stripto potrzebuje do wystawienia faktury.
Krok 2: payload checkout.session.completed
Dla płatności jednorazowych przez Checkout, payload wygląda inaczej. Oto przykład:
{
"id": "evt_1RCaBC2eZvKYlo2Cxyz9876",
"type": "checkout.session.completed",
"data": {
"object": {
"id": "cs_live_a1B2c3D4e5F6g7H8i9J0",
"payment_intent": "pi_3RCaBC2eZvKYlo2C1234",
"customer_details": {
"name": "Anna Nowak",
"email": "anna@startup.pl",
"address": {
"city": "Warszawa",
"country": "PL",
"line1": "ul. Marszałkowska 1",
"postal_code": "00-001"
}
},
"custom_fields": [
{
"key": "nip",
"text": { "value": "9876543210" }
}
],
"amount_total": 9900,
"currency": "pln",
"metadata": {}
}
}
}Zwróć uwagę na custom_fields: to pole, w którym Stripe Checkout zbiera NIP od klienta. Stripto automatycznie rozpoznaje pole o kluczu „nip" i używa go na fakturze.
Krok 3: weryfikacja i parsowanie
Po odebraniu requestu Stripto natychmiast weryfikuje podpis (szczegóły w następnej sekcji) i parsuje JSON do typowanego obiektu TypeScript. Jeśli podpis jest nieprawidłowy lub JSON jest uszkodzony, request jest odrzucany z kodem 400.
Krok 4: deduplikacja
Stripto sprawdza w bazie danych, czy zdarzenie o danym ID (evt_...) było już przetworzone. Jeśli tak, zwraca HTTP 200 (żeby Stripe nie ponawiał) i kończy przetwarzanie. Jeśli nie, sprawdza też, czy faktura za daną transakcję (payment_intent lub invoice ID) już istnieje.
Krok 5: ekstrakcja danych i wywołanie API
Stripto wyciąga z payloadu: imię i nazwisko (lub nazwę firmy), adres, NIP, email, kwotę, walutę, opis pozycji i okres rozliczeniowy. Te dane są mapowane na format wymagany przez API Fakturowni lub inFakt i wysyłane jako request POST tworzący nową fakturę.
Krok 6: faktura gotowa
System fakturowania tworzy fakturę, nadaje jej numer zgodny z Twoją numeracją i (jeśli masz włączoną integrację z KSeF) wysyła ją do Krajowego Systemu e-Faktur. Stripto zapisuje ID faktury w bazie, aktualizuje status na „completed" i zwraca HTTP 200 do Stripe.
Weryfikacja podpisu webhooka
Każdy webhook od Stripe zawiera nagłówek Stripe-Signature. To podpis kryptograficzny, który pozwala zweryfikować, że request naprawdę pochodzi od Stripe, a nie od kogoś, kto zna URL Twojego endpointu.
Jak działa podpis HMAC-SHA256
Stripe generuje podpis w trzech krokach:
- Pobiera timestamp wysłania webhooka (t=1711008000)
- Łączy timestamp z body requestu (t=1711008000.{...json...})
- Oblicza HMAC-SHA256 z tego ciągu, używając webhook secret (whsec_...) jako klucza
Wynikowy nagłówek wygląda tak:
Stripe-Signature: t=1711008000, v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd
Stripto odtwarza ten sam proces: łączy timestamp z body, oblicza HMAC-SHA256 z webhook secret i porównuje wynik z podpisem z nagłówka. Jeśli się zgadzają, request jest autentyczny.
Ochrona przed replay attacks
Sam podpis nie chroni przed atakiem powtórzeniowym (ktoś przechwytuje prawidłowy webhook i wysyła go ponownie). Dlatego Stripto sprawdza też timestamp: jeśli różnica między aktualnym czasem a timestamp z nagłówka przekracza 5 minut, request jest odrzucany. To standard Stripe, który Stripto implementuje automatycznie.
Webhook secret jest ustawiany automatycznie
Podczas łączenia konta Stripe ze Stripto, system automatycznie tworzy webhook endpoint i zapisuje webhook secret (whsec_...). Nie musisz ręcznie kopiować kluczy ani konfigurować endpointu w panelu Stripe.
Co się dzieje przy nieprawidłowym podpisie
Jeśli podpis nie zgadza się (np. ktoś wysłał fałszywy webhook na endpoint Stripto), system zwraca HTTP 400 i loguje próbę w monitoringu. Zdarzenie nie jest przetwarzane, faktura nie jest wystawiana. W dashboardzie nie pojawi się żaden ślad, bo nieprawidłowe requesty są odrzucane na najwcześniejszym etapie pipeline.
Deduplikacja: ochrona przed duplikatami
W systemach rozproszonych zdarzenia mogą dotrzeć więcej niż raz. Stripe ponawia webhooki, sieci mogą powodować duplikaty, a w skrajnych przypadkach dwa identyczne requesty mogą dotrzeć jednocześnie. Deduplikacja to nie opcja, to konieczność.
Poziom 1: identyfikator zdarzenia Stripe
Każde zdarzenie Stripe ma unikalny identyfikator (np. evt_1RBxYz2eZvKYlo2C0abc1234). Po pomyślnym przetworzeniu zdarzenia Stripto zapisuje ten ID w bazie danych. Przy kolejnym odebraniu zdarzenia o tym samym ID, system natychmiast zwraca HTTP 200 bez dalszego przetwarzania.
Poziom 2: identyfikator transakcji
Stripe może wygenerować różne zdarzenia dla tej samej transakcji (np. checkout.session.completed i payment_intent.succeeded dla jednej płatności). Każde z nich ma inny event ID, ale dotyczy tego samego payment_intent. Stripto sprawdza, czy dla danego payment_intent lub invoice ID z Stripe nie została już wystawiona faktura. Jeśli tak, pomija przetwarzanie.
Poziom 3: constraint bazodanowy
Nawet jeśli dwa identyczne requesty dotrą w tej samej milisekundzie (race condition), baza danych ma constraint UNIQUE na kolumnie przechowującej ID zdarzenia. Próba zapisania duplikatu kończy się błędem constraint violation, który Stripto obsługuje gracefully, zwracając HTTP 200 bez wystawiania drugiej faktury.
Schemat klucza idempotencji:
stripe_event_id: evt_1RBxYz2eZvKYlo2C0abc1234 (UNIQUE)
transaction_ref: pi_3RCaBC2eZvKYlo2C1234 (UNIQUE)
Sprawdzenie:
1. SELECT COUNT(*) FROM webhook_events
WHERE stripe_event_id = 'evt_...' → jeśli > 0, SKIP
2. SELECT COUNT(*) FROM invoices
WHERE transaction_ref = 'pi_...' → jeśli > 0, SKIP
3. INSERT INTO webhook_events (...)
ON CONFLICT DO NOTHING → race condition safeTe trzy poziomy ochrony działają razem i gwarantują, że każda płatność w Stripe generuje dokładnie jedną fakturę. Nie ma znaczenia, ile razy webhook dotrze do Stripto.
Mechanizm retry
Retry (ponowienie) działa na dwóch niezależnych poziomach: po stronie Stripe (dostawa webhooka) i po stronie Stripto (wystawienie faktury). Każdy poziom ma własny harmonogram i logikę.
Retry po stronie Stripe
Jeśli Stripto nie odpowie na webhook w ciągu 20 sekund (timeout) lub zwróci kod HTTP 5xx, Stripe ponawia wysyłkę według ustalonego harmonogramu:
Próba 1: natychmiast (oryginalna wysyłka) Próba 2: +1 godzina Próba 3: +6 godzin (łącznie 7h od pierwszej) Próba 4: +24 godziny (łącznie 31h) Próba 5: +48 godzin (łącznie 79h) Próba 6: +72 godziny (łącznie 151h, ok. 6 dni) Po 6 nieudanych próbach → zdarzenie oznaczone jako failed w panelu Stripe (Developers → Webhooks → Event deliveries)
Stripe stosuje exponential backoff. Dzięki temu krótkotrwała awaria (np. restart serwera) nie powoduje utraty zdarzeń. Stripe będzie próbował dostarczyć webhook przez kilka dni.
Retry po stronie Stripto
Jeśli Stripto odebrał webhook poprawnie (podpis OK, deduplikacja OK), ale nie może wystawić faktury, bo API systemu fakturowania zwraca błąd, Stripto uruchamia własny mechanizm retry:
Próba 1: natychmiast (w ramach przetwarzania webhooka) Próba 2: +30 sekund Próba 3: +5 minut (łącznie 5.5 min od pierwszej) Próba 4: +30 minut (łącznie 35.5 min) Po 4 nieudanych próbach → status: error → widoczne w dashboardzie z opisem błędu → możliwość ręcznego ponowienia jednym kliknięciem
Stripto przy pierwszej próbie natychmiast odpowiada HTTP 200 do Stripe (żeby Stripe nie rozpoczynał swoich retry), a dalsze próby wystawienia faktury wykonuje asynchronicznie w tle.
Retry nie powoduje duplikatów
Każda próba retry przechodzi przez ten sam pipeline deduplikacji. Nawet jeśli Stripe ponowi webhook w trakcie trwania retry po stronie Stripto, mechanizm UNIQUE constraint zapobiega wystawieniu podwójnej faktury.
Kiedy retry nie pomoże
Retry jest skuteczny przy tymczasowych problemach: timeout API, błąd 503 (service unavailable), problemy sieciowe. Nie pomoże przy błędach logicznych, np. brakujący NIP wymagany przez system fakturowania, nieprawidłowa waluta czy brak konfiguracji konta w Fakturowni. W takich przypadkach Stripto od razu oznacza zdarzenie jako error z czytelnym opisem problemu, bez marnowania prób retry.
Stany synchronizacji
Każde zdarzenie przetwarzane przez Stripto przechodzi przez ściśle zdefiniowane stany. Ten „state machine" pozwala w każdym momencie sprawdzić, co się dzieje z daną transakcją.
received
│
▼
processing
/ \
▼ ▼
invoice_created error
│ │
▼ ▼
sent_to_ksef retrying
│ │
▼ ▼
completed error (po wyczerpaniu prób)
│
▼
(ręczne ponowienie)
│
▼
processing → ...Opis każdego stanu
- received: webhook dotarł do Stripto, podpis zweryfikowany, zdarzenie zapisane w bazie. Przetwarzanie jeszcze się nie rozpoczęło.
- processing: Stripto przetwarza zdarzenie. Trwa ekstrakcja danych, przygotowanie requestu do API fakturowania.
- invoice_created: faktura została pomyślnie utworzona w Fakturowni lub inFakt. System fakturowania nadał jej numer.
- sent_to_ksef: system fakturowania potwierdził wysłanie faktury do KSeF. Ten status pojawia się tylko wtedy, gdy masz włączoną integrację z KSeF w Fakturowni/inFakt.
- completed: cały proces zakończony. Faktura wystawiona, opcjonalnie wysłana do KSeF i na email klienta.
- error: przetwarzanie zakończyło się błędem. Dashboard pokazuje szczegóły: kod błędu, odpowiedź API, timestamp.
- retrying: wystąpił błąd tymczasowy, Stripto automatycznie ponawia próbę wystawienia faktury zgodnie z harmonogramem retry.
- skipped: zdarzenie pominięte, bo zostało rozpoznane jako duplikat lub typ zdarzenia jest wyłączony w konfiguracji.
Filtrowanie po statusach w dashboardzie
W dashboardzie Stripto możesz filtrować zdarzenia po statusie. Najważniejszy filtr to „error", który pozwala szybko znaleźć transakcje wymagające uwagi.
Log webhooków i monitoring
Dashboard Stripto zawiera pełny log wszystkich odebranych webhooków. Każdy wpis w logu zawiera informacje potrzebne do szybkiego debugowania.
Co pokazuje wpis w logu
Oto przykładowy wpis dla pomyślnie przetworzonego zdarzenia:
┌─────────────────────────────────────────────────────┐ │ Zdarzenie: invoice.finalized │ │ Event ID: evt_1RBxYz2eZvKYlo2C0abc1234 │ │ Data: 2026-03-21 14:23:07 UTC │ │ Status: completed ✓ │ │ │ │ Klient: Jan Kowalski (jan.kowalski@firma.pl) │ │ Kwota: 299,00 PLN │ │ NIP: 1234567890 │ │ │ │ Faktura: FV 15/03/2026 (Fakturownia #1847293) │ │ KSeF: wysłana │ │ │ │ Czas przetwarzania: 3.4s │ │ Próby: 1/4 │ └─────────────────────────────────────────────────────┘
Wpis z błędem
┌─────────────────────────────────────────────────────┐ │ Zdarzenie: checkout.session.completed │ │ Event ID: evt_1RCaBC2eZvKYlo2Cxyz9876 │ │ Data: 2026-03-21 15:01:33 UTC │ │ Status: error ✗ │ │ │ │ Klient: Anna Nowak (anna@startup.pl) │ │ Kwota: 99,00 PLN │ │ NIP: 9876543210 │ │ │ │ Błąd: Fakturownia API 503 Service Unavailable │ │ Odpowiedź: "Serwer tymczasowo niedostępny" │ │ │ │ Próby: 4/4 (wyczerpane) │ │ Ostatnia próba: 2026-03-21 15:37:03 UTC │ │ │ │ [Ponów przetwarzanie] │ └─────────────────────────────────────────────────────┘
Każdy wpis z błędem zawiera przycisk „Ponów przetwarzanie", który pozwala ręcznie uruchomić pipeline od nowa. Przydatne, gdy problem po stronie systemu fakturowania został rozwiązany.
Monitoring po stronie Stripe
Oprócz logu w Stripto, historię webhooków możesz sprawdzić w panelu Stripe: Developers → Webhooks → wybierz endpoint → zakładka „Event deliveries". Stripe pokazuje status dostarczenia (succeeded, failed, pending), kod odpowiedzi HTTP i czas odpowiedzi. Jeśli coś nie działa, porównanie logów z obu stron pozwala szybko zlokalizować problem.
Konfiguracja i weryfikacja
Stripto konfiguruje webhook endpoint automatycznie podczas łączenia konta Stripe. Ale jeśli chcesz sprawdzić, czy wszystko działa poprawnie, lub przetestować webhook lokalnie, oto jak to zrobić.
Automatyczna konfiguracja w Stripto
- Zaloguj się do Stripto i przejdź do ustawień integracji
- Kliknij „Połącz konto Stripe" i zaloguj się do Stripe
- Stripto automatycznie utworzy webhook endpoint z prawidłowym URL, webhook secret i wybranymi zdarzeniami
- Status połączenia pojawi się na stronie ustawień
Weryfikacja w panelu Stripe
Po połączeniu konta możesz sprawdzić konfigurację w Stripe:
- Otwórz dashboard.stripe.com → Developers → Webhooks
- Znajdź endpoint z URL prowadzącym do Stripto
- Sprawdź, czy nasłuchiwane zdarzenia to invoice.finalized i checkout.session.completed
- W zakładce „Event deliveries" sprawdź, czy ostatnie zdarzenia mają status „succeeded"
Testowanie za pomocą Stripe CLI
Stripe CLI to narzędzie do lokalnego testowania webhooków. Przydatne, jeśli budujesz własną integrację lub chcesz zrozumieć, jak działają zdarzenia Stripe.
# Zainstaluj Stripe CLI brew install stripe/stripe-cli/stripe # Zaloguj się stripe login # Nasłuchuj webhooków i przekieruj na localhost stripe listen --forward-to localhost:3000/api/webhooks/stripe # W osobnym terminalu: wyślij testowe zdarzenie stripe trigger invoice.finalized # Lub wyślij checkout.session.completed stripe trigger checkout.session.completed
Stripe CLI pokaże w konsoli pełny payload zdarzenia i odpowiedź Twojego endpointu. To najszybszy sposób na sprawdzenie, czy pipeline działa poprawnie.
Wysłanie testowego webhooka z panelu Stripe
W panelu Stripe (Developers → Webhooks → wybierz endpoint) jest przycisk „Send test webhook". Pozwala wybrać typ zdarzenia i wysłać testowy payload na Twój endpoint. Uwaga: testowe zdarzenia mają prefix evt_test_, a Stripto rozpoznaje je i nie wystawia faktury produkcyjnej.
Obsługa dużego wolumenu transakcji
Stripto zostało zaprojektowane z myślą o firmach, które przetwarzają setki lub tysiące transakcji dziennie. Architektura oparta na kolejce webhooków zapewnia, że każde zdarzenie Stripe jest przetwarzane niezależnie i w odpowiedniej kolejności, nawet przy gwałtownym wzroście ruchu.
Kolejka webhooków i przetwarzanie wsadowe
Każdy odebrany webhook trafia do wewnętrznej kolejki. Stripto natychmiast zwraca HTTP 200 do Stripe (potwierdzając odbiór), a następnie przetwarza zdarzenie asynchronicznie. Dzięki temu nawet przy 500 webhookach w ciągu minuty żaden nie zostanie odrzucony przez timeout. Kolejka gwarantuje przetwarzanie w kolejności FIFO (first in, first out), co jest istotne przy subskrypcjach z wieloma zdarzeniami w krótkim czasie.
Wydajność przy dużej skali
Stripto przetwarza pojedynczy webhook w ok. 3-5 sekund. Przy równoległym przetwarzaniu kolejki system obsługuje kilkadziesiąt faktur na minutę. Dla typowego e-commerce z kilkuset transakcjami dziennie oznacza to, że wszystkie faktury są gotowe w ciągu kilku minut od płatności. Przy szczytowym obciążeniu (np. kampania Black Friday) Stripto automatycznie skaluje przetwarzanie, utrzymując stały czas generowania faktury.
Ochrona przed duplikatami przy dużym ruchu
Duży wolumen transakcji zwiększa ryzyko duplikatów, szczególnie gdy Stripe ponawia webhooki. Trójpoziomowa deduplikacja (ID zdarzenia, ID transakcji, constraint UNIQUE) działa niezależnie od obciążenia. Nawet jeśli dwa identyczne webhooki trafią do kolejki w tej samej sekundzie, mechanizm ON CONFLICT DO NOTHING na poziomie bazy danych gwarantuje, że powstanie dokładnie jedna faktura.
Rate limiting i systemy fakturowania
Przy dużym wolumenie system fakturowania (Fakturownia, inFakt) może ograniczać liczbę zapytań API. Stripto automatycznie dostosowuje tempo wysyłania requestów do limitu dostawcy, stosując strategię backoff. Faktury, które trafiły na limit, są kolejkowane i przetwarzane, gdy limit się odnowi.
Monitoring i alerty
Automatyczna synchronizacja działa w tle, ale musisz mieć pewność, że wszystko przebiega poprawnie. Stripto oferuje zestaw narzędzi do monitorowania stanu synchronizacji i natychmiastowego reagowania na problemy.
Status synchronizacji w dashboardzie
Dashboard Stripto wyświetla podsumowanie synchronizacji w czasie rzeczywistym. Na głównym ekranie widoczne są liczniki: przetworzone zdarzenia, oczekujące w kolejce, zakończone błędem i pominięte duplikaty. Każdy licznik jest klikalny i prowadzi do filtrowanej listy zdarzeń z pełnymi szczegółami.
Powiadomienia o błędach
Gdy zdarzenie przechodzi do statusu „error" po wyczerpaniu prób retry, Stripto wysyła powiadomienie email na adres właściciela konta. Wiadomość zawiera: typ zdarzenia, dane klienta, kwotę transakcji i opis błędu. Dzięki temu możesz zareagować bez konieczności codziennego sprawdzania dashboardu.
Monitoring dostarczania webhooków
Oprócz logów w Stripto, warto regularnie sprawdzać status dostarczania webhooków w panelu Stripe (Developers → Webhooks → Event deliveries). Stripe pokazuje procent udanych dostaw, średni czas odpowiedzi i listę niedostarczonych zdarzeń. Jeśli wskaźnik sukcesu spada poniżej 100%, Stripe wyświetla ostrzeżenie w panelu.
Identyfikacja luk w synchronizacji
Luka w synchronizacji to sytuacja, gdy płatność w Stripe nie ma odpowiadającej faktury. Najczęstsza przyczyna: webhook nie dotarł lub zdarzenie zakończyło się błędem. Aby znaleźć luki, porównaj liczbę transakcji w Stripe z liczbą faktur w dashboardzie Stripto za dany okres. Filtr „error" pokaże transakcje wymagające ręcznego ponowienia.
Log aktywności
Każda operacja w Stripto (odbiór webhooka, próba wystawienia faktury, retry, zmiana statusu) jest zapisywana w logu aktywności z dokładnym timestampem. Log jest dostępny w dashboardzie i pozwala prześledzić pełną historię przetwarzania każdego zdarzenia.
Porównanie z innymi rozwiązaniami
Na rynku istnieje kilka podejść do wystawiania faktur za płatności Stripe. Każde ma swoje ograniczenia. Oto porównanie Stripto z alternatywnymi rozwiązaniami.
Ręczne wystawianie faktur
Najprostsze podejście: logujesz się do systemu fakturowania, sprawdzasz transakcje w Stripe i ręcznie tworzysz fakturę. Przy kilku transakcjach miesięcznie to wykonalne. Przy kilkudziesięciu dziennie staje się pełnoetatowym zajęciem. Ryzyko pomyłek (zła kwota, brakujący NIP, pominięta transakcja) rośnie z każdą fakturą. Stripto eliminuje ten proces całkowicie.
Zapier i Make (generyczne narzędzia automatyzacji)
Zapier i Make pozwalają połączyć Stripe z systemem fakturowania przez gotowe integracje. Problem polega na tym, że są to narzędzia generyczne. Nie obsługują deduplikacji na poziomie transakcji Stripe, nie weryfikują podpisu webhooka po swojej stronie i nie mają wbudowanego retry dostosowanego do API fakturowania. Przy dużym wolumenie koszty Zapier/Make rosną szybko (każda transakcja to osobny „task"), a debugowanie złożonych scenariuszy (zwroty, częściowe płatności, wiele walut) wymaga budowania skomplikowanych workflow.
Natywna synchronizacja webhook vs polling
Niektóre narzędzia odpytują API Stripe w regularnych odstępach (polling), zamiast nasłuchiwać na webhooki. To podejście wprowadza opóźnienia (od minut do godzin) i obciąża API Stripe niepotrzebnymi zapytaniami. Stripto korzysta z webhooków, co oznacza reakcję w sekundach, zerowe obciążenie API Stripe i natychmiastową informację o każdej transakcji.
Dlaczego dedykowane narzędzie wygrywa
Stripto to narzędzie zbudowane wyłącznie do jednego zadania: wystawiania polskich faktur VAT za płatności Stripe. Każda decyzja architektoniczna (trójpoziomowa deduplikacja, automatyczny retry, kolejka webhooków, obsługa NIP z custom fields) jest zoptymalizowana pod ten konkretny przypadek użycia. Generyczne narzędzia automatyzacji muszą obsługiwać tysiące integracji, więc żadna z nich nie jest dopracowana tak dobrze jak dedykowane rozwiązanie.
Porównanie kosztów
Zapier z integracją Stripe + Fakturownia to koszt od 20 USD miesięcznie za 750 tasków. Przy 500 transakcjach miesięcznie potrzebujesz planu za 50+ USD. Stripto oferuje stały cennik niezależny od liczby tasków, a 5 pierwszych transakcji jest darmowych.
Rozwiązywanie problemów
Oto sześć najczęstszych problemów z synchronizacją webhooków i konkretne kroki do ich rozwiązania.
Problem 1: Webhook signature verification failed
Objaw: Stripe pokazuje HTTP 400, w logu Stripto brak wpisu
Przyczyna: webhook secret (whsec_...) jest nieaktualny lub nieprawidłowy. Może się zdarzyć po ręcznym usunięciu i ponownym utworzeniu endpointu w Stripe.
Rozwiązanie: w ustawieniach Stripto kliknij „Odłącz konto Stripe" i połącz je ponownie. Stripto utworzy nowy endpoint z nowym webhook secret.
Problem 2: Fakturownia API timeout (504)
Objaw: status „retrying" w dashboardzie, po 4 próbach „error"
Przyczyna: API Fakturowni jest przeciążone lub niedostępne (np. przerwa techniczna).
Rozwiązanie: poczekaj, aż Fakturownia przywróci dostępność, a następnie kliknij „Ponów przetwarzanie" przy zdarzeniach ze statusem error. Możesz też sprawdzić status API Fakturowni na ich stronie statusowej.
Problem 3: duplikat zdarzenia ze Stripe
Objaw: w logu Stripto widoczne dwa wpisy dla tego samego zdarzenia, jeden ze statusem „completed", drugi „skipped"
Przyczyna: to normalne zachowanie. Stripe ponowił webhook (np. bo pierwsza odpowiedź dotarła po timeout), a Stripto poprawnie rozpoznał duplikat i pominął go.
Rozwiązanie: żadne działanie nie jest wymagane. Faktura została wystawiona dokładnie raz. Status „skipped" potwierdza, że deduplikacja działa poprawnie.
Problem 4: brakujące dane klienta na fakturze
Objaw: faktura wystawiona, ale bez NIP-u, nazwy firmy lub z niepełnym adresem
Przyczyna: Stripe nie zawiera tych danych w webhooku, bo klient ich nie podał. Dotyczy to najczęściej pola NIP (custom field w Checkout) lub adresu (opcjonalne pole billing_details).
Rozwiązanie: upewnij się, że w konfiguracji Stripe Checkout masz włączone zbieranie adresu (billing_address_collection: required) i dodane custom field na NIP. Stripto automatycznie użyje tych danych, jeśli są dostępne w webhooku.
Problem 5: rate limiting z systemu fakturowania
Objaw: wiele zdarzeń jednocześnie ze statusem „retrying", błąd HTTP 429 w logach
Przyczyna: system fakturowania (Fakturownia lub inFakt) ogranicza liczbę zapytań API na minutę. Przy dużej liczbie jednoczesnych płatności (np. kampania marketingowa) limit może zostać przekroczony.
Rozwiązanie: Stripto automatycznie spowalnia wysyłanie requestów i ponawia je po upływie czasu. Przy regularnym przekraczaniu limitu sprawdź plan API w systemie fakturowania, bo wyższy plan zazwyczaj oznacza wyższy limit zapytań.
Problem 6: KSeF niedostępny
Objaw: faktura wystawiona w Fakturowni/inFakt, ale status KSeF to „oczekuje" lub „błąd wysyłki"
Przyczyna: Krajowy System e-Faktur ma przerwy techniczne lub jest czasowo niedostępny. To problem po stronie KSeF, nie Stripto ani systemu fakturowania.
Rozwiązanie: faktura jest wystawiona i czeka na wysyłkę do KSeF. System fakturowania (Fakturownia, inFakt) sam ponowi próbę wysłania po przywróceniu dostępności KSeF. Nie musisz podejmować żadnego działania. Możesz sprawdzić aktualny status KSeF na stronie Ministerstwa Finansów.
Automatyczne faktury ze Stripe w kilka sekund
Webhook pipeline, retry, deduplikacja. Wszystko skonfigurowane automatycznie. 5 pierwszych transakcji za darmo, bez karty.
Najczęściej zadawane pytania
Jak szybko po płatności Stripe pojawia się faktura?
Typowy czas to 3-5 sekund od momentu płatności. Stripe wysyła webhook natychmiast po zdarzeniu (opóźnienie poniżej 1 sekundy). Stripto weryfikuje podpis i parsuje dane w ok. 150 ms, a wywołanie API Fakturowni lub inFakt zajmuje 2-3 sekundy. W skrajnych przypadkach (duże obciążenie API systemu fakturowania) czas może wzrosnąć do 10-15 sekund.
Co się stanie, jeśli webhook od Stripe nie dotrze do Stripto?
Stripe automatycznie ponawia wysyłkę webhooka z rosnącymi odstępami: po 1 godzinie, 6 godzinach, 24 godzinach, 48 godzinach i 72 godzinach. To łącznie 5 prób w ciągu 3 dni. Stripto przetworzy zdarzenie przy pierwszej udanej dostawie, a mechanizm deduplikacji zapobiega wystawieniu podwójnej faktury, nawet jeśli zdarzenie dotrze kilkakrotnie.
Czy mogę przetestować webhook lokalnie przed wdrożeniem?
Tak. Stripe CLI pozwala na przekierowanie webhooków na lokalny serwer poleceniem stripe listen --forward-to localhost:3000/api/webhooks/stripe. Stripto tworzy endpoint automatycznie, ale jeśli chcesz sprawdzić przepływ ręcznie, możesz użyć stripe trigger invoice.finalized, żeby wysłać testowe zdarzenie.
Jakie typy zdarzeń Stripe obsługuje Stripto?
Stripto nasłuchuje na: invoice.finalized (subskrypcje Stripe Billing), checkout.session.completed (płatności jednorazowe przez Checkout i Payment Links), payment_intent.succeeded (alternatywne potwierdzenie płatności) oraz charge.succeeded (niskopoziomowe obciążenie karty). Domyślnie aktywne są invoice.finalized i checkout.session.completed.
Jak Stripto zapobiega wystawieniu podwójnej faktury?
Na trzech poziomach. Pierwszy: każde zdarzenie Stripe ma unikalne ID (evt_...), które jest zapisywane w bazie po przetworzeniu. Drugi: Stripto sprawdza, czy dla danego payment_intent lub invoice Stripe nie istnieje już faktura. Trzeci: constraint UNIQUE na poziomie bazy danych blokuje duplikaty nawet przy jednoczesnym przetwarzaniu (race condition).
Co się dzieje, gdy API Fakturowni lub inFakt jest niedostępne?
Stripto automatycznie ponawia próbę wystawienia faktury. Pierwszy retry po 30 sekundach, drugi po 5 minutach, trzeci po 30 minutach. Jeśli wszystkie 3 próby zawiodą, zdarzenie otrzymuje status error i jest widoczne w dashboardzie. Możesz ponowić przetwarzanie ręcznie jednym kliknięciem po przywróceniu dostępności API.
Czy Stripto obsługuje webhooki z trybu testowego Stripe?
Tak. Webhooki z trybu testowego (test mode) są odbierane i przetwarzane przez pipeline, ale nie tworzą faktur produkcyjnych. Stripto rozpoznaje zdarzenia testowe i oznacza je odpowiednim statusem w dashboardzie. Dzięki temu możesz bezpiecznie przetestować całą integrację przed uruchomieniem produkcji.
Czy mogę wyłączyć synchronizację dla wybranych typów zdarzeń?
Tak. W ustawieniach Stripto możesz włączyć lub wyłączyć poszczególne typy zdarzeń Stripe, które wyzwalają tworzenie faktur. Domyślnie aktywne są invoice.finalized i checkout.session.completed. Jeśli np. nie korzystasz z Stripe Billing, możesz wyłączyć invoice.finalized i zostawić tylko checkout.session.completed.
Połącz Stripe z Fakturownią lub inFakt
Konfiguracja w minutę. Automatyczne faktury gotowe na KSeF.