Przejdź do treści
Oplac

Zacznij

Piaskownica

Klucz sk_test_ otwiera piaskownicę: te same trasy, obiekty, statusy i zdarzenia co w produkcji, tylko bez pieniędzy. Strona płatności piaskownicy ma deterministyczne kody BLIK i przyciski wyniku karty, a pomocnicy testowi pozwalają przejść całą integrację z terminala, bez klikania.

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.

Tryb testowy

Jak działa piaskownica#

  • Tryb wynika z klucza: sk_test_ tworzy obiekty z livemode: false, których nie widać kluczem sk_live_ i odwrotnie.
  • Po zapisie dostajesz jednorazową piaskownicę demo na 14 dni, bez planu, z limitem kilku linków testowych. Po wyborze planu piaskownica działa bez ograniczeń obok produkcji.
  • Płatności, zwroty, subskrypcje i faktury piaskownicy przechodzą przez te same ścieżki co produkcyjne i wysyłają te same webhooki, na adres testowy (osobny od produkcyjnego).
  • Limit zapytań w piaskownicy to 25 na sekundę.

Testowe kody BLIK#

Na stronie płatności piaskownicy (checkout_url) wybierz BLIK i wpisz jeden z kodów. Ten sam kod możesz wysłać polem blik_code do pomocnika POST /v1/test_helpers/payments/{id}/confirm.

777 123

Wynik
zapłacona
Pola płatności
status: succeeded, method: blik, paid_at

777 000

Wynik
odrzucona przez klienta
Pola płatności
status: failed, failure_code: blik_rejected

777 408

Wynik
kod wygasł albo błędny
Pola płatności
status: failed, failure_code: blik_code_invalid

Każdy inny kod strona odrzuca jako nieprawidłowy, bez zmiany statusu płatności.

curl https://oplac.pl/api/v1/test_helpers/payments/pay_Ab12Cd34Ef56Gh/confirm \
  -H "Authorization: Bearer sk_test_TWOJ_KLUCZ" \
  -H "Content-Type: application/json" \
  -d '{"blik_code": "777000"}'
$ch = curl_init('https://oplac.pl/api/v1/test_helpers/payments/pay_Ab12Cd34Ef56Gh/confirm');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => ['Authorization: Bearer sk_test_TWOJ_KLUCZ', 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => json_encode(['blik_code' => '777000']),
    CURLOPT_RETURNTRANSFER => true,
]);
$payment = json_decode(curl_exec($ch), true);
const res = await fetch('https://oplac.pl/api/v1/test_helpers/payments/pay_Ab12Cd34Ef56Gh/confirm', {
  method: 'POST',
  headers: { Authorization: 'Bearer sk_test_TWOJ_KLUCZ', 'Content-Type': 'application/json' },
  body: JSON.stringify({ blik_code: '777000' }),
});
const payment = await res.json();
import requests

res = requests.post(
    "https://oplac.pl/api/v1/test_helpers/payments/pay_Ab12Cd34Ef56Gh/confirm",
    headers={"Authorization": "Bearer sk_test_TWOJ_KLUCZ"},
    json={"blik_code": "777000"},
)
payment = res.json()
Odpowiedź
HTTP/1.1 200 OK
{
  "id": "pay_Ab12Cd34Ef56Gh",
  "object": "payment",
  "status": "failed",
  "method": "blik",
  "failure_code": "blik_rejected",
  "amount": 12900,
  "currency": "PLN",
  "livemode": false
}

Karta w piaskownicy#

W piaskownicy nie wpisujesz numeru karty. Strona płatności ma dwa przyciski: Zapłać daje succeeded z method: card, Odrzuć daje failed z failure_code: card_declined. Przez API ten sam wybór to outcome: succeeded albo outcome: failed z method: card w pomocniku potwierdzenia. Wszystkie kody odmowy, jakie może zwrócić płatność, to card_declined, blik_rejected, blik_code_invalid, insufficient_funds i stolen_card; w produkcji surowy kod operatora jest dodatkowo w decline_code.

Subskrypcje testowe#

Subskrypcja po utworzeniu ma status incomplete i checkout_url (strona zapisu). Zamiast klikać, opłać pierwszy okres pomocnikiem POST /v1/test_helpers/subscriptions/{id}/confirm (outcome: succeeded albo failed). Odnowienie przed terminem symuluje POST /v1/test_helpers/subscriptions/{id}/renew z wynikiem succeeded, failed (odmowa przejściowa, Recover ponawia i wysyła e-mail z linkiem do dopłaty) albo failed_permanently (karta zastrzeżona, bez ponowień). Każdy wynik uruchamia prawdziwe zdarzenia subscription.*, payment.* i faktury.

curl https://oplac.pl/api/v1/test_helpers/subscriptions/sub_Ab12Cd34Ef56Gh/renew \
  -H "Authorization: Bearer sk_test_TWOJ_KLUCZ" \
  -H "Content-Type: application/json" \
  -d '{"outcome": "failed"}'
$ch = curl_init('https://oplac.pl/api/v1/test_helpers/subscriptions/sub_Ab12Cd34Ef56Gh/renew');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => ['Authorization: Bearer sk_test_TWOJ_KLUCZ', 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => json_encode(['outcome' => 'failed']),
    CURLOPT_RETURNTRANSFER => true,
]);
$subscription = json_decode(curl_exec($ch), true);
const res = await fetch('https://oplac.pl/api/v1/test_helpers/subscriptions/sub_Ab12Cd34Ef56Gh/renew', {
  method: 'POST',
  headers: { Authorization: 'Bearer sk_test_TWOJ_KLUCZ', 'Content-Type': 'application/json' },
  body: JSON.stringify({ outcome: 'failed' }),
});
const subscription = await res.json();
import requests

res = requests.post(
    "https://oplac.pl/api/v1/test_helpers/subscriptions/sub_Ab12Cd34Ef56Gh/renew",
    headers={"Authorization": "Bearer sk_test_TWOJ_KLUCZ"},
    json={"outcome": "failed"},
)
subscription = res.json()
Odpowiedź
HTTP/1.1 200 OK
{
  "id": "sub_Ab12Cd34Ef56Gh",
  "object": "subscription",
  "status": "past_due",
  "plan": "plan_Ab12Cd34Ef56Gh",
  "last_decline_code": "card_declined",
  "current_period_end": 1762592000,
  "livemode": false
}

Zdarzenie próbne na webhook#

POST /v1/test_helpers/webhooks z polem type wysyła na testowy adres webhooka podpisane zdarzenie wybranego typu z przykładowym obiektem w data.object. Sprawdzisz nim weryfikację podpisu i routing po typie bez tworzenia płatności. Bez zapisanego adresu testowego dostaniesz 400 webhook_not_configured. Zdarzenie próbne widać w panelu i pod GET /v1/events jak każde inne.

curl https://oplac.pl/api/v1/test_helpers/webhooks \
  -H "Authorization: Bearer sk_test_TWOJ_KLUCZ" \
  -H "Content-Type: application/json" \
  -d '{"type": "payment.succeeded"}'
$ch = curl_init('https://oplac.pl/api/v1/test_helpers/webhooks');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => ['Authorization: Bearer sk_test_TWOJ_KLUCZ', 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => json_encode(['type' => 'payment.succeeded']),
    CURLOPT_RETURNTRANSFER => true,
]);
$event = json_decode(curl_exec($ch), true);
const res = await fetch('https://oplac.pl/api/v1/test_helpers/webhooks', {
  method: 'POST',
  headers: { Authorization: 'Bearer sk_test_TWOJ_KLUCZ', 'Content-Type': 'application/json' },
  body: JSON.stringify({ type: 'payment.succeeded' }),
});
const event = await res.json();
import requests

res = requests.post(
    "https://oplac.pl/api/v1/test_helpers/webhooks",
    headers={"Authorization": "Bearer sk_test_TWOJ_KLUCZ"},
    json={"type": "payment.succeeded"},
)
event = res.json()
Odpowiedź
HTTP/1.1 201 Created
{
  "id": "evt_Ab12Cd34Ef56Gh",
  "object": "event",
  "type": "payment.succeeded",
  "api_version": "2026-10-03",
  "livemode": false,
  "created": 1760000000,
  "data": {"object": {"id": "pay_Ab12Cd34Ef56Gh", "object": "payment", "status": "succeeded"}},
  "pending_webhooks": 1,
  "delivery": {"attempts": 1, "last_status": 200, "delivered_at": 1760000001, "next_attempt": null}
}

Czego piaskownica nie udaje#

  • Wyglądu strony płatności operatora i 3D Secure: w produkcji klient widzi stronę operatora płatności Twojego konta.
  • Czasu zwrotów: w piaskownicy zwrot ma od razu succeeded, w produkcji operator może zwrócić pending i wynik przyjdzie zdarzeniem.
  • Smart routingu i pola provider_account: wybór konta operatora dotyczy tylko płatności produkcyjnych.
  • Pomocnicy testowi z kluczem sk_live_ zwracają 403 test_helpers_live_mode.

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.

Zamów integrację za darmo

BLIK, karty, subskrypcje i KSeF w jednym panelu.