Zacznij
Hostowana strona płatności
Najprostsza integracja: Twój serwer tworzy płatność i przekierowuje klienta na checkout_url. Stronę płatności, metody (BLIK, karta, Apple Pay, Google Pay, szybki przelew), 3D Secure i obsługę błędów bierze na siebie strona hostowana. Klient wraca na return_url, a Twój system dowiaduje się o wyniku z webhooka. Nie dotykasz danych kart i nie potrzebujesz formularza płatności.
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.
Przepływ krok po kroku#
- 01Klient klika „Zapłać” w Twoim sklepie. Serwer wywołuje
POST /v1/paymentsz kwotą, walutą,return_urlimetadataz numerem zamówienia. - 02Serwer odpowiada przekierowaniem 302 na
checkout_urlz odpowiedzi (albo oddaje adres aplikacji, która go otwiera). - 03Klient płaci na stronie hostowanej. W piaskownicy to strona Oplac z kodami BLIK; w produkcji strona operatora płatności Twojego konta.
- 04Po zapłacie klient wraca na
return_urlz parametrem?payment=pay_.... Pokaż stronę „Dziękujemy” i sprawdź stan żądaniemGET /v1/payments/{id}. - 05Niezależnie od powrotu Twój serwer dostaje zdarzenie
payment.succeededalbopayment.failed. Na nim oznaczasz zamówienie, bo klient może zamknąć kartę przed powrotem.
Płatność żyje domyślnie 24 godziny (expires_at). Po tym czasie strona przestaje przyjmować zapłatę, płatność dostaje status canceled i przychodzi zdarzenie payment.canceled. Krótszy termin ustawisz polem expires_at (znacznik Unix w przyszłości).
curl https://oplac.pl/api/v1/payments \
-H "Authorization: Bearer sk_test_TWOJ_KLUCZ" \
-H "Idempotency-Key: zamowienie-10482" \
-H "Content-Type: application/json" \
-d '{
"amount": 12900,
"currency": "PLN",
"description": "Zamówienie 10482",
"return_url": "https://sklep.example.com/zamowienie/10482/powrot",
"expires_at": 1760003600,
"customer": {"email": "[email protected]", "name": "Anna Nowak"},
"metadata": {"order_id": "10482"}
}'
$ch = curl_init('https://oplac.pl/api/v1/payments');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer sk_test_TWOJ_KLUCZ',
'Idempotency-Key: zamowienie-10482',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'amount' => 12900,
'currency' => 'PLN',
'description' => 'Zamówienie 10482',
'return_url' => 'https://sklep.example.com/zamowienie/10482/powrot',
'expires_at' => time() + 3600,
'customer' => ['email' => '[email protected]', 'name' => 'Anna Nowak'],
'metadata' => ['order_id' => '10482'],
]),
CURLOPT_RETURNTRANSFER => true,
]);
$payment = json_decode(curl_exec($ch), true);
header('Location: ' . $payment['checkout_url'], true, 302);
const res = await fetch('https://oplac.pl/api/v1/payments', {
method: 'POST',
headers: {
Authorization: 'Bearer sk_test_TWOJ_KLUCZ',
'Idempotency-Key': 'zamowienie-10482',
'Content-Type': 'application/json',
},
body: JSON.stringify({
amount: 12900,
currency: 'PLN',
description: 'Zamówienie 10482',
return_url: 'https://sklep.example.com/zamowienie/10482/powrot',
expires_at: Math.floor(Date.now() / 1000) + 3600,
customer: { email: '[email protected]', name: 'Anna Nowak' },
metadata: { order_id: '10482' },
}),
});
const payment = await res.json();
reply.redirect(payment.checkout_url);
import time
import requests
res = requests.post(
"https://oplac.pl/api/v1/payments",
headers={
"Authorization": "Bearer sk_test_TWOJ_KLUCZ",
"Idempotency-Key": "zamowienie-10482",
},
json={
"amount": 12900,
"currency": "PLN",
"description": "Zamówienie 10482",
"return_url": "https://sklep.example.com/zamowienie/10482/powrot",
"expires_at": int(time.time()) + 3600,
"customer": {"email": "[email protected]", "name": "Anna Nowak"},
"metadata": {"order_id": "10482"},
},
)
payment = res.json()
return redirect(payment["checkout_url"], code=302)
HTTP/1.1 201 Created
{
"id": "pay_Ab12Cd34Ef56Gh",
"object": "payment",
"amount": 12900,
"currency": "PLN",
"status": "pending",
"checkout_url": "https://oplac.pl/p/Ab12Cd34Ef56Gh",
"return_url": "https://sklep.example.com/zamowienie/10482/powrot",
"customer": "cus_Xy98Zw76Vu54Ts",
"customer_email": "[email protected]",
"metadata": {"order_id": "10482"},
"livemode": false,
"expires_at": 1760003600,
"created": 1760000000
}
Powrót klienta na return_url#
Klient wraca na return_url z parametrem payment równym identyfikatorowi płatności. Adres powrotu to sygnał, nie dowód: parametr można wpisać ręcznie, a klient może wrócić zanim operator potwierdzi zapłatę. Dlatego na stronie powrotu zawsze pobierz płatność i pokaż stan według pola status.
| Status po powrocie | Co pokazać |
|---|---|
| succeeded | potwierdzenie i dalsze kroki zamówienia |
| processing, requires_confirmation | „płatność jest w trakcie”, odśwież po chwili albo czekaj na webhook |
| pending | klient wrócił bez zapłaty; pokaż przycisk „Zapłać ponownie” z tym samym checkout_url |
| failed | odmowa; powód w failure_code, zaproponuj inną metodę nową płatnością |
| canceled | płatność wygasła albo została anulowana; utwórz nową |
curl https://oplac.pl/api/v1/payments/pay_Ab12Cd34Ef56Gh \
-H "Authorization: Bearer sk_test_TWOJ_KLUCZ"
$id = preg_replace('/[^A-Za-z0-9_]/', '', $_GET['payment'] ?? '');
$ch = curl_init('https://oplac.pl/api/v1/payments/' . $id);
curl_setopt_array($ch, [
CURLOPT_HTTPHEADER => ['Authorization: Bearer sk_test_TWOJ_KLUCZ'],
CURLOPT_RETURNTRANSFER => true,
]);
$payment = json_decode(curl_exec($ch), true);
if (($payment['status'] ?? null) === 'succeeded') {
// pokaż potwierdzenie; zamówienie oznacza webhook payment.succeeded
}
const id = String(req.query.payment || '').replace(/[^A-Za-z0-9_]/g, '');
const res = await fetch(`https://oplac.pl/api/v1/payments/${id}`, {
headers: { Authorization: 'Bearer sk_test_TWOJ_KLUCZ' },
});
const payment = await res.json();
if (payment.status === 'succeeded') {
// pokaż potwierdzenie; zamówienie oznacza webhook payment.succeeded
}
import re
import requests
payment_id = re.sub(r"[^A-Za-z0-9_]", "", request.args.get("payment", ""))
res = requests.get(
f"https://oplac.pl/api/v1/payments/{payment_id}",
headers={"Authorization": "Bearer sk_test_TWOJ_KLUCZ"},
)
payment = res.json()
if payment.get("status") == "succeeded":
pass # pokaż potwierdzenie; zamówienie oznacza webhook payment.succeeded
HTTP/1.1 200 OK
{
"id": "pay_Ab12Cd34Ef56Gh",
"object": "payment",
"status": "succeeded",
"method": "blik",
"amount": 12900,
"currency": "PLN",
"paid_at": 1760000040,
"metadata": {"order_id": "10482"},
"livemode": false
}
Dane klienta i NIP#
Pole customer przyjmuje identyfikator istniejącego klienta cus_ albo obiekt z email, name, tax_id i address; wtedy klient powstaje razem z płatnością i jego identyfikator wraca w odpowiedzi. Dzięki temu płatności, subskrypcje i faktury jednej osoby są połączone, a strona płatności ma wstępnie wypełniony adres e-mail. Jeśli klient poda NIP na stronie płatności, znajdziesz go w polu tax_id płatności. Zapisane metody płatności przechowuje operator płatności, nie Oplac.
Link do płatności zamiast integracji#
Gdy nie masz serwera albo sprzedajesz poza sklepem (e-mail, komunikator, wydruk z kodem QR), utwórz link do płatności żądaniem POST /v1/payment_links albo z panelu. Link ma stały adres https://oplac.pl/<kod> i kod QR; każde opłacenie tworzy osobną płatność pay_ ze zdarzeniami payment.* i identyfikatorem linku w polu payment_link. Link jednorazowy (reusable: false) przestaje przyjmować zapłatę po pierwszej udanej płatności, link bez kwoty pozwala klientowi wpisać kwotę samemu.
Produkcja i rola operatora płatności#
W trybie produkcyjnym checkout_url prowadzi na stronę płatności operatora płatności podpiętego do Twojego konta; dane kart i 3D Secure zostają po jego stronie. Płatność produkcyjna bez podpiętego operatora kończy się błędem 402 provider_not_connected. Przy Smart routingu (plan Skala) pole provider_account mówi, które konto operatora obsłużyło płatność; przy Connect (plan Platforma) płatność trafia do sprzedawcy platformy z pola connected_account po potrąceniu application_fee.
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.