Funkcje Stripto

Automatyczna synchronizacja faktur ze Stripe: jak działa webhook pipeline w Stripto

Każda płatność w Stripe generuje zdarzenie. Stripto przechwytuje je przez webhook, weryfikuje podpis HMAC-SHA256, sprawdza deduplikację, wyciąga dane klienta i wystawia fakturę VAT w Fakturowni lub inFakt. Cały proces trwa kilka sekund, działa w pełni automatycznie i jest odporny na błędy dzięki mechanizmowi retry. Ten artykuł pokazuje dokładnie, jak wygląda każdy krok pipeline, z przykładami payloadów, diagramem czasowym i rozwiązywaniem problemów.

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.

ZdarzenieKiedy się odpalaJakie dane zawieraCo robi Stripto
invoice.finalizedStripe finalizuje fakturę za nowy okres rozliczeniowy subskrypcjiCustomer ID, kwota, waluta, line_items (nazwa produktu, ilość, cena), okres rozliczeniowy, metadataWystawia fakturę VAT z pozycjami odpowiadającymi line_items subskrypcji
checkout.session.completedKlient zakończył płatność przez Stripe Checkout lub Payment LinkCustomer details (imię, email, adres), custom_fields (NIP), line_items, payment_intent, metadataWystawia fakturę z danymi z formularza Checkout, w tym NIP z custom field
payment_intent.succeededPłatność została potwierdzona (dowolna metoda: karta, BLIK, przelew)Kwota, waluta, customer ID, payment_method, metadata, descriptionUżywane jako alternatywne źródło, gdy checkout.session nie zawiera pełnych danych
charge.succeededKarta lub inna metoda płatności została obciążonaKwota, waluta, billing_details (imię, adres), receipt_email, metadataFallback, 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ść:

MetodaCzas reakcjiNiezawodnośćNakład pracy
Webhook (real-time)3-5 sekundWysoka (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 eksportGodziny do dniNiska (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:

  1. Pobiera timestamp wysłania webhooka (t=1711008000)
  2. Łączy timestamp z body requestu (t=1711008000.{...json...})
  3. 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 safe

Te 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

  1. Zaloguj się do Stripto i przejdź do ustawień integracji
  2. Kliknij „Połącz konto Stripe" i zaloguj się do Stripe
  3. Stripto automatycznie utworzy webhook endpoint z prawidłowym URL, webhook secret i wybranymi zdarzeniami
  4. Status połączenia pojawi się na stronie ustawień

Weryfikacja w panelu Stripe

Po połączeniu konta możesz sprawdzić konfigurację w Stripe:

  1. Otwórz dashboard.stripe.com → Developers → Webhooks
  2. Znajdź endpoint z URL prowadzącym do Stripto
  3. Sprawdź, czy nasłuchiwane zdarzenia to invoice.finalized i checkout.session.completed
  4. 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.

Wypróbuj za darmo

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.

Wypróbuj Stripto