Karty - pre-autoryzacja i przechwycenie (capture)
Pre-autoryzacja pozwala zablokować środki na karcie klienta bez natychmiastowego obciążenia, a następnie przechwycić (capture) je w wybranym momencie - w całości lub częściowo. Niewykorzystaną blokadę można anulować (cancellation). To standardowy model dla scenariuszy, gdzie kwota końcowa lub moment obciążenia nie są znane w chwili zakupu.
POST/api/v1_0/cards/payment/{transactionId}/pay/card-pre-authZablokuj środki na karcie bez obciążenia (z 3D Secure).Pełny kontrakt w API Reference
POST/api/v1_0/cards/payment/{transactionId}/capturePrzechwyć zablokowane środki - w całości lub częściowo.Pełny kontrakt w API Reference
POST/api/v1_0/cards/payment/{transactionId}/cancellationZwolnij niewykorzystaną blokadę środków.Pełny kontrakt w API Reference
Kiedy używać
- Rezerwacje (hotele, wynajem) - blokada kaucji, obciążenie po pobycie
- Wysyłka po skompletowaniu - obciążenie dopiero przy wysyłce towaru
- Kwota zmienna - autoryzacja z zapasem, capture rzeczywistej kwoty
- Marketplace - autoryzacja teraz, rozliczenie po potwierdzeniu przez sprzedawcę
Pre-autoryzację można wykonać także na zapisanym tokenie (card-on-file) - przez pole authorize_only na aliasie mandatu cyklicznego; patrz Karty - płatności cykliczne. Ta strona opisuje pre-autoryzację świeżej karty. Krok przechwycenia (capture) i anulowania jest wspólny dla obu.
Jak działa?
Proces składa się z dwóch faz:
- Pre-autoryzacja - blokada środków na karcie (bez obciążenia). Klient przechodzi 3D Secure tak jak przy zwykłej płatności.
- Przechwycenie (capture) LUB anulowanie (cancellation) - pobranie zablokowanych środków (pełne/częściowe) albo zwolnienie blokady.
Pre-autoryzacja korzysta z tego samego mechanizmu szyfrowania danych karty i obsługi 3D Secure co płatności kartowe Server-to-Server. Zapoznaj się z nią najpierw - poniżej opisujemy tylko różnice.
Wymagania
- Aktywna integracja kartowa Server-to-Server (wymaga certyfikacji PCI DSS i zgody dpay - patrz Karty S2S)
- Pre-autoryzacja włączona na Punkcie Płatności (skontaktuj się z dpay)
Krok 1. Rejestracja i pre-autoryzacja
Zarejestruj transakcję (transactionType: card_auth), pobierz klucz publiczny i zaszyfruj dane karty dokładnie tak jak w Karty S2S (kroki 1-3). Różnica jest tylko w endpointie płatności - zamiast /pay/card-otp użyj /pay/card-pre-auth:
POST https://api-payments.dpay.pl/api/v1_0/cards/payment/{transactionId}/pay/card-pre-auth
Content-Type: application/json
Parametry zapytania
Identyczne jak dla /pay/card-otp:
{
"encryptedCardData": "Base64-encoded-encrypted-data...",
"deviceInfo": {
"browserAcceptHeader": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"browserJavaEnabled": "false",
"browserLanguage": "pl-PL",
"browserColorDepth": "24",
"browserScreenHeight": "1080",
"browserScreenWidth": "1920",
"browserTZ": "-60",
"browserUserAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)...",
"systemFamily": "Windows",
"geoLocalization": "52.2297,21.0122",
"deviceID": "device-unique-id",
"applicationName": "Chrome"
}
}
Obiekt deviceInfo wymaga kompletu pól - w tym systemFamily, geoLocalization, deviceID i applicationName. Brak któregokolwiek zwróci HTTP 422. Pełna specyfikacja w Karty S2S.
Odpowiedź
Odpowiedź ma tę samą strukturę co /pay/card-otp - pole message.redirectType determinuje dalszą akcję:
redirectType | Znaczenie |
|---|---|
SUCCESS | Środki zablokowane (autoryzacja udana) - przejdź do capture/cancellation |
FORM | Wymagana autoryzacja 3D Secure - wyrenderuj formularz, potem ponów z threeDsConfirmed: true |
Obsługa 3D Secure (FORM) jest identyczna jak w Karty S2S. Po udanej autoryzacji środki są zablokowane, ale jeszcze nie pobrane - kwota value z rejestracji to maksymalna kwota, którą możesz przechwycić.
Blokada środków wygasa po stronie banku wydawcy po określonym czasie (zwykle kilka-kilkanaście dni, zależnie od banku). Wykonaj capture lub cancellation przed wygaśnięciem.
Krok 2a. Przechwycenie (capture)
Aby pobrać zablokowane środki, wywołaj endpoint capture. Możesz przechwycić całość lub część autoryzacji, a także wykonać wiele przechwyceń do sumy nieprzekraczającej autoryzowanej kwoty.
POST https://api-payments.dpay.pl/api/v1_0/cards/payment/{transactionId}/capture
Content-Type: application/json
Parametry zapytania
| Pole | Typ | Wymagane | Opis |
|---|---|---|---|
service | string | Tak | Nazwa serwisu, do którego należy płatność |
amount | number | Tak | Kwota do przechwycenia w PLN (np. 59.99). Suma wszystkich przechwyceń nie może przekroczyć kwoty autoryzacji |
checksum | string | Tak | Suma kontrolna SHA-256 (patrz niżej) |
webhook | object | Nie | Adres zdarzenia payment.captured z tego przechwycenia: url i opcjonalnie events (tylko payment.captured). Ma pierwszeństwo przed adresem z rejestracji płatności i wymaga sekretu webhooków serwisu - patrz Webhooki. Nie wchodzi do sumy kontrolnej |
Suma kontrolna
Capture przesuwa pieniądze, więc żądanie podpisujesz kluczem Hash serwisu:
sha256(capture|{service}|{transactionId}|{amount}|{hash})
captureto stały napis - suma przechwycenia nie przejdzie jako suma anulowania.transactionIdto identyfikator płatności z adresu żądania (transactionIdz rejestracji).amountliczysz z dwoma miejscami po przecinku, np.59.99albo100.00.
Bez sumy albo z błędną sumą żądanie kończy się kodem HTTP 401, zanim cokolwiek się stanie.
Przykład
curl -X POST https://api-payments.dpay.pl/api/v1_0/cards/payment/abc-def-123/capture \
-H "Content-Type: application/json" \
-d '{ "service": "abc123", "amount": 59.99, "checksum": "..." }'
$checksum = hash('sha256', implode('|', ['capture', $service, $transactionId, number_format($amount, 2, '.', ''), $hash]));
Odpowiedź
{
"success": true,
"status": "success",
"message": { "redirectType": "SUCCESS" }
}
Gdy suma przechwyceń osiągnie pełną kwotę autoryzacji, transakcja przechodzi w stan przechwycony (captured). O każdym przechwyceniu, także częściowym, informuje też zdarzenie webhook payment.captured - przechwycenie nie generuje IPN.
Jeśli kwota końcowa jest niższa niż autoryzowana (np. część zamówienia niedostępna), przechwyć tylko rzeczywistą kwotę. Pozostałą część możesz przechwycić kolejnym wywołaniem lub anulować (patrz niżej).
Krok 2b. Anulowanie autoryzacji (cancellation)
Aby zwolnić zablokowane środki bez pobrania, wywołaj endpoint anulowania. Działa tylko na autoryzacji, która nie została jeszcze w pełni przechwycona.
POST https://api-payments.dpay.pl/api/v1_0/cards/payment/{transactionId}/cancellation
Content-Type: application/json
Parametry zapytania
| Pole | Typ | Wymagane | Opis |
|---|---|---|---|
service | string | Tak | Nazwa serwisu, do którego należy płatność |
amount | number | Nie | Kwota do anulowania w PLN. Pominięcie = anulowanie pełne (cała pozostała, nieprzechwycona kwota). Podanie kwoty = anulowanie częściowe |
checksum | string | Tak | Suma kontrolna SHA-256 (patrz niżej) |
Suma kontrolna
sha256(cancellation|{service}|{transactionId}|{amount}|{hash})
Przy anulowaniu pełnym (bez amount) segment kwoty jest pusty, ale separatory zostają: sha256(cancellation|{service}|{transactionId}||{hash}). Kwotę liczysz z dwoma miejscami po przecinku, jak przy capture.
Przykłady
Pełne anulowanie (zwolnienie całej blokady):
curl -X POST https://api-payments.dpay.pl/api/v1_0/cards/payment/abc-def-123/cancellation \
-H "Content-Type: application/json" \
-d '{ "service": "abc123", "checksum": "..." }'
Częściowe anulowanie (zwolnienie części blokady):
curl -X POST https://api-payments.dpay.pl/api/v1_0/cards/payment/abc-def-123/cancellation \
-H "Content-Type: application/json" \
-d '{ "service": "abc123", "amount": 30.00, "checksum": "..." }'
Odpowiedź
{
"success": true,
"status": "success",
"message": { "redirectType": "SUCCESS" }
}
Pełne anulowanie zamyka autoryzację - kolejne capture/cancellation nie będą już możliwe.
Cykl życia i ograniczenia
| Reguła | Opis |
|---|---|
Capture wymaga amount | Kwota przechwycenia jest obowiązkowa; suma przechwyceń ≤ kwota autoryzacji |
Cancellation amount opcjonalne | Brak amount = pełne anulowanie pozostałej kwoty |
| Kolejność | Anulować można tylko żywą autoryzację - nie po pełnym przechwyceniu, anulowaniu ani finalizacji |
| Część przechwycona | Nie podlega anulowaniu - anulować można tylko nieprzechwyconą resztę |
| Wygaśnięcie | Nieprzechwycona blokada wygasa po stronie banku wydawcy |
Obsługa błędów
| Komunikat | Przyczyna | Działanie |
|---|---|---|
Missing service or checksum (HTTP 401, kod CHECKSUM_REQUIRED) | Brak pola service albo checksum | Podpisz żądanie kluczem Hash serwisu |
Invalid checksum (HTTP 401, kod INVALID_CHECKSUM) | Błędna suma, obcy serwis albo suma innej operacji | Sprawdź wzór, kwotę z dwoma miejscami po przecinku i nazwę operacji |
Invalid webhook URL: ... (HTTP 400, kod WEBHOOK_URL_INVALID) | Adres w obiekcie webhook nie przechodzi reguł, przyczyna w reason | Podaj publiczny adres HTTPS na porcie 443 |
Generate the webhook secret ... (HTTP 400, kod WEBHOOK_SECRET_MISSING) | Capture z obiektem webhook bez sekretu webhooków serwisu | Wygeneruj sekret w ustawieniach serwisu |
Invalid webhook object (HTTP 422, kod WEBHOOK_INVALID) | Zła struktura obiektu webhook albo typ inny niż payment.captured | Popraw obiekt według tabeli parametrów |
Invalid capture amount | Brak lub nieprawidłowa kwota capture | Podaj dodatnią amount |
Capture amount exceeds authorized amount | Suma przechwyceń > autoryzacja | Zmniejsz kwotę |
Transaction cannot be captured in its current state. | Autoryzacja już przechwycona/anulowana/sfinalizowana | Sprawdź status transakcji |
Transaction cannot be cancelled in its current state. | Autoryzacja już przechwycona/anulowana/sfinalizowana | Sprawdź status transakcji |
Cancellation amount exceeds remaining authorized amount | Kwota anulowania > pozostała blokada | Zmniejsz kwotę |
Missing authorization reference for capture. / ... for cancellation. | Transakcja nie ma referencji autoryzacji (nie jest żywą pre-autoryzacją) | Sprawdź czy transakcja to poprawna, niezaksięgowana pre-autoryzacja |
Capture was declined by the card issuer. / Cancellation was declined by the card issuer. | Wydawca odrzucił przechwycenie / anulowanie | Sprawdź stan transakcji i ponów w razie potrzeby |
Pozostałe błędy przetwarzania (odmowa autoryzacji, nieprawidłowa karta) opisuje wspólna sekcja Komunikaty przetwarzania płatności. Pole message bywa różne w zależności od sytuacji - dopasowuj logikę luźno.
Testowanie w trybie sandbox
Na serwisie z włączonym trybem testowym cały przepływ pre-autoryzacji jest symulowany po stronie dpay - bez wychodzenia do zewnętrznego procesora kart. Możesz przećwiczyć pełną ścieżkę pre-autoryzacja → capture / cancellation przy użyciu numerów testowych kart.
| Krok | Zachowanie w trybie testowym |
|---|---|
card-pre-auth z numerem sukcesu | Autoryzacja zakończona sukcesem - transakcja przechodzi w stan oczekiwania na capture |
card-pre-auth z numerem odmownym | Autoryzacja odrzucona - transakcja anulowana, zwracany jest błąd symulacji |
capture | Symulowane przechwycenie środków - po pełnym capture transakcja otrzymuje status captured |
cancellation | Symulowane anulowanie - pre-autoryzacja zostaje zamknięta (status canceled) |
Scenariusz autoryzacji (sukces / odmowa) wybierany jest na podstawie numeru karty przekazanego w zaszyfrowanych danych karty - tak samo jak dla płatności card-otp. Numery testowe znajdziesz w sekcji Środowisko testowe.