Podstawy API
Błędy
Każda odpowiedź 4xx i 5xx, także 404 nieznanej trasy, 405, 429 i 500, ma tę samą postać: obiekt error z klasą, stałym kodem, komunikatem po polsku, nazwą pola i adresem opisu w tej dokumentacji. Obsługę buduj na polu code, komunikat pokazuj ludziom w logach, a request_id podawaj w zgłoszeniach.
Klucz testowy w przykładach
Wklej klucz sk_test_ z panelu (zakładka Deweloperzy), a każdy przykład będzie gotowy do uruchomienia. Klucz zostaje w tej karcie przeglądarki, nie wysyłamy go nigdzie.
Przykłady używają Twojego klucza testowego. Produkcyjnego klucza nie przyjmujemy.
Obiekt błędu#
| Pole | Znaczenie |
|---|---|
type | klasa błędu: invalid_request_error, authentication_error, idempotency_error, rate_limit_error, api_error |
code | stały kod do obsługi w kodzie integracji, z katalogu niżej |
message | komunikat po polsku, mówi co poprawić; może się zmieniać, nie porównuj go w kodzie |
param | nazwa pola żądania, którego dotyczy błąd (kropka dla pól zagnieżdżonych: customer.email), albo null |
doc_url | adres opisu kodu: https://oplac.pl/docs/bledy#<code> |
request_id | identyfikator żądania req_, ten sam co w nagłówku X-Request-Id |
HTTP/1.1 400 Bad Request
X-Request-Id: req_7mK2pQ9rT4vX1bN8cD3fG6hJ
{
"error": {
"type": "invalid_request_error",
"code": "parameter_missing",
"message": "Podaj kwotę w groszach w polu amount, np. 12900 dla 129,00 zł.",
"param": "amount",
"doc_url": "https://oplac.pl/docs/bledy#parameter_missing",
"request_id": "req_7mK2pQ9rT4vX1bN8cD3fG6hJ"
}
}
Klasy błędów i kody HTTP#
invalid_request_error
- HTTP
- 400, 402, 403, 404, 405, 422
- Co oznacza i co zrobić
- żądanie do poprawy albo stan obiektu nie pozwala na operację; popraw i wyślij ponownie, bez automatycznych powtórek
authentication_error
- HTTP
- 401
- Co oznacza i co zrobić
- brak albo nieważny klucz; sprawdź nagłówek
Authorizationi tryb klucza
idempotency_error
- HTTP
- 400, 409
- Co oznacza i co zrobić
- zły albo ponownie użyty
Idempotency-Key, albo pierwsze żądanie z tym kluczem jeszcze trwa
rate_limit_error
- HTTP
- 429
- Co oznacza i co zrobić
- limit zapytań; odczekaj
Retry-Aftersekund i ponów
api_error
- HTTP
- 500, 502
- Co oznacza i co zrobić
- błąd po stronie Oplac albo operatora płatności; ponów z tym samym
Idempotency-Key, przy powtórce podajrequest_id
Wzorzec obsługi w kodzie#
- 01Sprawdź kod HTTP. 2xx to sukces; wszystko inne ma obiekt
error. - 02Rozgałęź po
error.code, nie pomessage. Nieznany kod traktuj wedługerror.type. - 03Błędy
invalid_request_erroriauthentication_errorto błędy programu albo konfiguracji: zalogujrequest_id,code,parami nie ponawiaj automatycznie. - 04
rate_limit_erroriapi_errorponawiaj z odstępem (Retry-Afteralbo wykładniczo) i tym samymIdempotency-Key. Te odpowiedzi nie są zapamiętywane w idempotencji, więc ponowienie wykona żądanie normalnie. - 05
idempotency_key_in_use(409) to wyścig dwóch równoległych żądań: odczekaj chwilę i ponów, dostaniesz wynik pierwszego.
# -f kończy curl błędem przy 4xx i 5xx, -s wycisza pasek postępu, -S pokazuje komunikat
curl -fsS https://oplac.pl/api/v1/payments \
-H "Authorization: Bearer sk_test_TWOJ_KLUCZ" \
-H "Content-Type: application/json" \
-d '{"currency": "PLN"}'
$kod = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
$dane = json_decode($odpowiedz, true);
if ($kod >= 400) {
$blad = $dane['error'];
match ($blad['code']) {
'parameter_missing', 'parameter_invalid' => throw new InvalidArgumentException($blad['param'] . ': ' . $blad['message']),
'rate_limited', 'api_error', 'provider_error' => ponowPozniej($blad['request_id']),
'resource_missing' => null, // obiekt nie istnieje w tym trybie
default => throw new RuntimeException($blad['code'] . ' (' . $blad['request_id'] . ')'),
};
}
const res = await fetch(url, opcje);
const dane = await res.json();
if (!res.ok) {
const { code, message, param, request_id: requestId } = dane.error;
switch (code) {
case 'parameter_missing':
case 'parameter_invalid':
throw new Error(`${param}: ${message}`);
case 'rate_limited':
case 'api_error':
case 'provider_error':
return ponowPozniej(requestId);
case 'resource_missing':
return null; // obiekt nie istnieje w tym trybie
default:
throw new Error(`${code} (${requestId})`);
}
}
res = requests.post(url, headers=headers, json=dane)
body = res.json()
if res.status_code >= 400:
err = body["error"]
if err["code"] in ("parameter_missing", "parameter_invalid"):
raise ValueError(f"{err['param']}: {err['message']}")
if err["code"] in ("rate_limited", "api_error", "provider_error"):
ponow_pozniej(err["request_id"])
elif err["code"] == "resource_missing":
pass # obiekt nie istnieje w tym trybie
else:
raise RuntimeError(f"{err['code']} ({err['request_id']})")
Błędy walidacji i pole param#
Przy złym żądaniu API zwraca pierwszy napotkany błąd z nazwą pola w param i komunikatem, jak go poprawić: parameter_missing (brak pola), parameter_invalid (zła wartość albo typ), parameter_unknown (pole, którego zasób nie przyjmuje), metadata_invalid, expand_invalid. Popraw pole i wyślij żądanie jeszcze raz; możesz użyć tego samego Idempotency-Key, bo odpowiedzi 400 nie są zapamiętywane.
Katalog kodów#
41 kodów w 5 klasach. Kod jest stały i to na nim opieraj obsługę w kodzie integracji; komunikat w polu message może się zmieniać. Pole doc_url każdej odpowiedzi prowadzi do wiersza poniżej.
invalid_request_error żądanie do poprawy
| Kod | HTTP | Znaczenie i co zrobić |
|---|---|---|
parameter_missing |
400 | Brakuje wymaganego pola. Pole param mówi którego. |
parameter_invalid |
400 | Pole ma złą wartość albo zły typ. Pole param mówi które, message jak poprawić. |
parameter_unknown |
400 | Żądanie zawiera pole, którego ten zasób nie przyjmuje. |
parameter_unsupported |
400 | Pole istnieje, ale nie jest obsługiwane w tym planie albo trybie. |
metadata_invalid |
400 | Metadata to do 50 kluczy, klucz do 40 znaków, wartość tekstowa do 500 znaków. |
expand_invalid |
400 | Pole w expand[] nie jest rozwijalne w tym zasobie. |
api_version_invalid |
400 | Nagłówek Oplac-Version wskazuje nieznaną wersję API. |
url_not_found |
404 | Nie ma takiej trasy API. Sprawdź ścieżkę i wersję (/v1). |
method_not_allowed |
405 | Ta trasa nie obsługuje tej metody HTTP. Nagłówek Allow wymienia dozwolone. |
resource_missing |
404 | Nie ma obiektu o tym identyfikatorze w tym koncie i trybie (sk_test_ widzi tylko obiekty testowe). |
resource_deleted |
400 | Obiekt został usunięty i nie można go zmieniać. |
module_not_in_plan |
403 | Moduł (Bill, Invoices) jest w wyższym planie konta. |
currency_not_in_plan |
403 | Waluty EUR i USD są od planu Skala. |
connect_not_in_plan |
403 | Podział płatności (Connect) jest w planie Platforma. |
sandbox_limit_reached |
403 | Piaskownica demo mieści kilka linków testowych. Więcej po wyborze planu. |
test_helpers_live_mode |
403 | Pomocnicy testowi działają wyłącznie z kluczem sk_test_. |
provider_not_connected |
402 | Konto nie ma podpiętego dostawcy płatności. Podepnij go w panelu, w zakładce Dostawca. |
payment_not_cancelable |
422 | Anulować można tylko płatność w statusie pending albo requires_confirmation. |
payment_not_confirmable |
422 | Potwierdzić w piaskownicy można tylko płatność otwartą (pending, requires_confirmation). |
payment_not_refundable |
422 | Zwrot dotyczy tylko płatności w statusie succeeded. |
refund_exceeds_amount |
422 | Suma zwrotów przekroczyłaby kwotę płatności. |
payment_link_inactive |
422 | Link do płatności jest wyłączony. |
coupon_invalid |
400 | Kupon nie istnieje, jest wyłączony, wyczerpany albo ma inną walutę niż plan. |
subscription_not_active |
422 | Operacja wymaga żywej subskrypcji (trialing, active, past_due). |
currency_mismatch |
400 | Waluta nowego planu różni się od waluty subskrypcji. |
connected_account_invalid |
400 | Konto sprzedawcy platformy nie należy do tego konta albo nie istnieje. |
connected_account_not_ready |
400 | Sprzedawca platformy nie przeszedł jeszcze weryfikacji u dostawcy. |
application_fee_invalid |
400 | Prowizja platformy musi być od 0 do kwoty płatności. |
amount_too_large |
400 | Suma faktury przekracza 999 999 999,99. |
seller_details_missing |
400 | Dane firmy sprzedawcy (nazwa, NIP, adres) są puste. Uzupełnij je w panelu, w Ustawieniach. |
webhook_not_configured |
400 | Konto nie ma adresu webhooka trybu testowego. Zapisz go w panelu, w zakładce Deweloperzy. |
product_inactive |
422 | Produkt jest wyłączony (active: false), więc nie można dla niego utworzyć strony sprzedaży. |
checkout_page_inactive |
422 | Strona sprzedaży jest wyłączona albo jej produkt nie przyjmuje zakupów. |
portal_disabled |
400 | Portal klienta jest wyłączony w panelu, więc sesji portalu nie da się utworzyć. |
authentication_error klucz API
| Kod | HTTP | Znaczenie i co zrobić |
|---|---|---|
api_key_invalid |
401 | Brak nagłówka Authorization albo klucz jest nieważny, odwołany lub konto nie ma aktywnego planu. |
api_error błąd po stronie Oplac albo dostawcy
| Kod | HTTP | Znaczenie i co zrobić |
|---|---|---|
provider_error |
502 | Dostawca płatności nie odpowiedział albo odrzucił operację. Ponów żądanie za chwilę. |
api_error |
500 | Błąd po stronie Oplac. Ponów żądanie; jeśli się powtarza, podaj request_id w zgłoszeniu. |
idempotency_error nagłówek Idempotency-Key
| Kod | HTTP | Znaczenie i co zrobić |
|---|---|---|
idempotency_key_invalid |
400 | Nagłówek Idempotency-Key ma od 1 do 255 znaków. |
idempotency_key_reused |
400 | Ten Idempotency-Key był już użyty z inną treścią albo na innej trasie. Nowy zamiar to nowy klucz. |
idempotency_key_in_use |
409 | Żądanie z tym Idempotency-Key jest właśnie przetwarzane. Ponów za chwilę, dostaniesz jego wynik. |
rate_limit_error limit zapytań
| Kod | HTTP | Znaczenie i co zrobić |
|---|---|---|
rate_limited |
429 | Przekroczony limit zapytań konta. Odczekaj tyle sekund, ile podaje Retry-After. |
Powiązane
Klucz testowy dostajesz od razu po zapisie
Adres e-mail, kod z maila i piaskownica z kodami BLIK. Produkcję włączasz sam w panelu: plan, dostawca płatności, klucz sk_live_. Wolisz, żeby wdrożenie w sklepie zrobił nasz zespół? To też jest za darmo.