Co mówi GoCardless
| Reason | Typ | HTTP | Tekst GoCardless |
|---|---|---|---|
rate_limit_exceeded | invalid_api_usage | 429 | Rate limit reached. Check headers for reset time. |
Strona limitów GoCardless podaje liczbę: 1600 żądań na minutę w standardowej integracji i 1600 na minutę i sprzedawcę w integracji partnerskiej. Po przekroczeniu API zwraca 429, a GoCardless wyjaśnia, że te żądania można bezpiecznie ponowić: „These requests are safe to retry.”. Informacji o tym, kiedy to zrobić, szukaj w nagłówkach odpowiedzi: ratelimit-limit, ratelimit-remaining i ratelimit-reset.

Skąd tyle żądań
Limit liczy wszystkie żądania do API, nie tylko te, które tworzą płatności. W konektorze każda płatność z zapisanym mandatem to jedno żądanie, niezależnie od tego, czy pochodzi z odnawiającej się subskrypcji, czy z płatności zarejestrowanej metodą płatności klienta. Każde zdarzenie płatności, które trafia do Odoo, to kolejne żądanie, bo konektor nie ufa samemu powiadomieniu: pobiera tę płatność z GoCardless i stosuje zwrócony status. Duża partia w tym samym momencie, na przykład wiele odnowień naraz w czasie, gdy napływają zdarzenia wcześniejszych płatności, sumuje oba rodzaje żądań.
GoCardless zalicza ten reason do błędów invalid_api_usage, czyli tych wynikających ze sposobu wykonania żądania, i dla nich zaleca powiadomić zespół techniczny („alert your dev team”). Pojedynczy 429 tego nie wymaga; taki, który powtarza się każdego dnia, już tak.
Co robi konektor
- Odczytuje nagłówek
ratelimit-reseti wylicza, ile czasu zostało: podaną godzinę minus godzinę serwera Odoo. - Czeka ten czas, co najmniej 1 sekundę i co najwyżej 65. Jeśli nagłówka brakuje albo nie da się go odczytać, czeka 1 sekundę. Ten limit czasu istnieje po to, by błędnie ustawiony zegar nie zablokował procesu Odoo, który na to czeka.
- Ponawia żądanie tylko raz.
- Jeśli ponowienie też dostanie 429, już nie czeka: traktuje to jak każde inne odrzucenie przez API.
Konektor nie liczy swoich żądań i nie hamuje ich z wyprzedzeniem. Nie odczytuje ratelimit-remaining: czeka wyłącznie wtedy, gdy GoCardless już odpowiedział 429.

Jeśli druga próba też trafi w limit
Zależy to od tego, co Odoo robiło w tym momencie.
- Jeśli chodziło o płatność, transakcja przechodzi w stan „Błąd” z komunikatem „GoCardless rejected the request.” i pod spodem z komunikatem GoCardless zawierającym
rate_limit_exceededorazrequest_idw nawiasach kwadratowych. Faktura pozostaje do zapłaty. - Jeśli Odoo stosowało zdarzenie z GoCardless, webhook odpowiada 500, by GoCardless ponowił wysyłkę, a zdarzenia już zastosowane nie są stosowane drugi raz. Godzinna synchronizacja odzyskująca również nie pomija nieudanego zdarzenia: pobiera je ponownie przy kolejnym przebiegu.
429 to nie to samo co płatność bez odpowiedzi. Bez odpowiedzi konektor nie wie, czy GoCardless utworzył płatność, więc zostawia ją oczekującą i wysyła ponownie z tym samym kluczem w ciągu godziny. Przy 429 odpowiedź jest: GoCardless nie przyjął żądania, dlatego transakcja kończy się błędem.
Konektor nie jest przetłumaczony na polski: te teksty zawsze pojawiają się po angielsku, także w Odoo po polsku, niezależnie od tego, czy uruchamia je użytkownik, czy zaplanowane działanie: „GoCardless rejected the request.”.
Co zrobić
- Otwórz transakcję z faktury, przyciskiem „Transakcja płatnicza” na górze; menu transakcji jest widoczne tylko w trybie deweloperskim, a w Odoo 20 nie istnieje. Jeśli komunikat wymienia
rate_limit_exceeded, GoCardless odrzucił to żądanie ze względu na limit, a nie przez klienta ani jego mandat. - Po chwili spróbuj obciążyć fakturę zapisaną metodą płatności klienta jeszcze raz.
- Jeśli zdarza się to często, sprawdź godzinę serwera Odoo: czas oczekiwania wynika z odjęcia jej od
ratelimit-reset, a zegar przesunięty do przodu go skraca. - Jeśli potrzebujesz pomocy GoCardless, zapisz
request_idz komunikatu: ich dokumentacja prosi o jego podanie przy kontakcie z pomocą techniczną.
Czy konektor rozkłada żądania, żeby nie dojść do limitu?
Nie. Nie liczy ich i nie hamuje z wyprzedzeniem: reaguje, gdy GoCardless odpowie 429, czekaniem i jednym ponowieniem.
Dlaczego czeka najwyżej 65 sekund?
Podczas oczekiwania proces Odoo wykonujący żądanie nic innego nie robi. Ten limit w kodzie konektora chroni przed zablokowaniem, gdy zegar jest źle ustawiony.
Czy przez limit gubi się jakieś zdarzenie z GoCardless?
Nie uznaje się go za utracone: webhook prosi GoCardless o ponowną wysyłkę, a godzinna synchronizacja pobiera je ponownie przy kolejnym przebiegu.
Z naszym konektorem
W Odoo 17, 18, 19 i 20 konektor traktuje 429 jak pauzę: czeka tyle, ile podaje GoCardless, ponawia raz, a jeśli limit nadal obowiązuje, zostawia transakcję w błędzie z request_id, żebyś wiedział, co się stało i co przekazać GoCardless.
Czytaj dalej
Sprawdzone w kodzie źródłowym konektora (wersja 17.0, 18.0, 19.0 i 20.0) i w podlinkowanych źródłach
Źródła
- docs.gocardless.com/docs/api-reference/limits
- docs.gocardless.com/docs/api-reference/responses-and-errors
- Kod modułu: flexigo_payment_gocardless: const.py, wiersz 113 w 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) i 20.0 (688d86b)
- Kod modułu: flexigo_payment_gocardless: models/payment_provider.py, wiersz 378 w 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) i 20.0 (688d86b)
- Kod modułu: flexigo_payment_gocardless: models/payment_provider.py, wiersz 408 w 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) i 20.0 (688d86b)
- Kod modułu: flexigo_payment_gocardless: models/payment_provider.py, wiersz 379 w 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) i 20.0 (688d86b)
- Kod modułu: flexigo_payment_gocardless: models/payment_provider.py, wiersz 383 w 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) i 20.0 (688d86b)
- Kod modułu: flexigo_payment_gocardless: models/payment_provider.py, wiersz 397 w 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) i 20.0 (688d86b)
- Kod modułu: flexigo_payment_gocardless: models/payment_provider.py, wiersz 462 w 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) i 20.0 (688d86b)
- Kod modułu: flexigo_payment_gocardless: models/payment_transaction.py, wiersz 281 w 17.0 (d203ee6), wiersz 281 w 18.0 (e2ab18b), wiersz 281 w 19.0 (ce7f5a3) i wiersz 292 w 20.0 (688d86b)
- Kod modułu: flexigo_payment_gocardless: models/payment_transaction.py, wiersz 247 w 17.0 (d203ee6), wiersz 247 w 18.0 (e2ab18b), wiersz 247 w 19.0 (ce7f5a3) i wiersz 258 w 20.0 (688d86b)
- Kod modułu: flexigo_payment_gocardless: models/payment_transaction.py, wiersz 299 w 17.0 (d203ee6), wiersz 299 w 18.0 (e2ab18b), wiersz 299 w 19.0 (ce7f5a3) i wiersz 310 w 20.0 (688d86b)
- Kod modułu: flexigo_payment_gocardless: models/payment_transaction.py, wiersz 589 w 17.0 (d203ee6), wiersz 589 w 18.0 (e2ab18b), wiersz 588 w 19.0 (ce7f5a3) i wiersz 607 w 20.0 (688d86b)
- Kod modułu: flexigo_payment_gocardless: controllers/main.py, wiersz 124 w 17.0 (d203ee6), wiersz 124 w 18.0 (e2ab18b), wiersz 124 w 19.0 (ce7f5a3) i wiersz 127 w 20.0 (688d86b)
- Kod modułu: flexigo_payment_gocardless: controllers/main.py, wiersz 96 w 20.0 (688d86b)
- Kod modułu: flexigo_payment_gocardless: models/gocardless_webhook_event.py, wiersz 7 w 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) i 20.0 (688d86b)
- Kod modułu: flexigo_payment_gocardless: const.py, wiersz 117 w 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) i 20.0 (688d86b)
- Kod modułu: flexigo_payment_gocardless: models/payment_provider.py, wiersz 603 w 17.0 (d203ee6), wiersz 603 w 18.0 (e2ab18b), wiersz 603 w 19.0 (ce7f5a3) i wiersz 605 w 20.0 (688d86b)
- docs.gocardless.com/docs/api-reference/webhooks
- Kod modułu: flexigo_payment_gocardless: i18n/flexigo_payment_gocardless.pot, wiersz 521 w 17.0 (d203ee6), wiersz 521 w 18.0 (e2ab18b), wiersz 521 w 19.0 (ce7f5a3) i wiersz 523 w 20.0 (688d86b)
- github.com/odoo/odoo/blob/20.0/addons/payment/i18n/pl.po
- github.com/odoo/odoo/blob/20.0/addons/payment/views/payment_transaction_views.xml
- github.com/odoo/odoo/blob/17.0/odoo/http.py
- github.com/odoo/odoo/blob/20.0/addons/account_payment/views/account_move_views.xml
- Kod modułu: flexigo_payment_gocardless: __manifest__.py, wiersz 31 w 17.0 (d203ee6), 18.0 (e2ab18b), 19.0 (ce7f5a3) i 20.0 (688d86b)
