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.
Jak działa piaskownica#
-
Tryb wynika z klucza:
sk_test_tworzy obiekty zlivemode: false, których nie widać kluczemsk_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()
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()
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()
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ćpendingi 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.