Zwroty
Płatność może zostać zwrócona wielokrotnie na łączną kwotę nieprzekraczającą kwoty płatności i jest to dozwolone tylko w przypadku
płatności w statusie CONFIRMED.
Paynow akceptuje zwroty z minimalną kwotą 1 PLN dla płatności kartą a dla innych metod 0,01 PLN.
Aby móc dokonać standardowego zwrotu za pomocą API, Twój sklep musi mieć włączoną opcję „dziennie” w Harmonogramie wypłat dla danego sklepu. Środki potrzebne do dokonania zwrotu zostaną pobrane z Twojego salda.
Jeśli na Twoim saldzie nie ma wystarczających środków na wykonanie zwrotu (np. Twój sklep ma mało sprzedaży lub nie miał ich w ostatnim czasie), możesz skorzystać ze zwrotu przelewem. Taki zwrot nie jest pobierany z Twojego salda – jest finansowany dedykowanym przelewem bankowym wykonanym na potrzeby tego konkretnego zwrotu.
Możesz również otrzymywać powiadomienia, gdy zwrot osiągnie status końcowy.
Zwroty oczekujące - opcjonalne
Zwrot oczekujący to specjalny rodzaj zwrotu, który można zainicjować nawet jeśli kwota zwrotu przekracza saldo.
Po zainicjowaniu taki zwrot będzie miał status NEW.
Po zgromadzeniu wystarczającej ilości środków na saldzie zwroty zostaną przetworzone przy użyciu algorytmu FIFO (co oznacza, że
zwroty są przetwarzane w kolejności, w jakiej zostały zainicjowane).
Jeśli nie zgromadzisz wymaganych środków na zwrot na saldzie przez 120 godzin (5 dni, wartość domyślna),
status zwrotu zmieni się na CANCELLED.
Możesz zmienić czas, po którym zwroty oczekujące zostaną anulowane - jednostką tego parametru jest godzina.
Aby włączyć tę funkcję w swoim sklepie i/lub zmienić domyślny czas anulowania zwrotu oczekującego (opcjonalnie), przejdź
do zakładki Ustawienia > Zwroty oczekujące w Panelu Merchanta.
Zwrot oczekujący czeka na zgromadzenie środków z przyszłej sprzedaży na Twoim saldzie. Zwrot przelewem w ogóle nie korzysta z Twojego salda – jest finansowany przelewem bankowym wykonanym dla tego konkretnego zwrotu. Użyj go, gdy nie spodziewasz się wystarczającej sprzedaży, aby pokryć zwrot na czas.
Diagram procesu zwrotu
Poniższy diagram sekwencji przedstawia proces zwrotu zakończony sukcesem:

Mapa statusów zwrotu
Na poniższym obrazku przedstawiono wszystkie statusy, jakie może przyjąć zwrot, oraz możliwe przejścia między nimi:

Wyjaśnienie:
| Code | Description |
|---|---|
| NEW | Zwrot został zaakceptowany. |
| PENDING | Paynow rozpoczyna przetwarzanie żądania zwrotu. |
| SUCCESSFUL | Zwrot został pomyślnie przetworzony przez Paynow, a pieniądze zostały przelane na konto kupującego. |
| FAILED | Wystąpił problem podczas przetwarzania zwrotu. Pieniądze nie zostały przelane na rzecz kupującego. |
| CANCELLED | Zwrot został anulowany. Pieniądze nie zostały przelane na rzecz kupującego. Anulować można tylko zwroty o statusie NEW. |
Utwórz zwrot
Na potrzeby tego przewodnika przyjmiemy założenie, że dane autoryzacyjne to:
- Api-Key =
97a55694-5478-43b5-b406-fb49ebfdd2b5 - Signature-Key =
b305b996-bca5-4404-a0b7-2ccea3d2b64b
Załóżmy również, że paymentId to NOR3-FUN-D4U-LOL
Krok 1: Przygotuj wiadomość z żądanien zwrotu. W tym przykładzie użyjemy prostej wiadomości zawierającej tylko wymagane pola, które wyglądają następująco:
{
"amount": 100,
"reason": "RMA"
}
Podana kwota powinna być podana w najmniejszej jednostce waluty zwrotu (grosz w przypadku PLN). Oznacza to, że powyższe żądanie definiuje zwrot w wysokości 1,00 PLN. Pole opisu powinno zawierać powód zwrotu. Pełną specyfikację wiadomości żądania zwrotu można znaleźć poniżej
Opcjonalnie możesz dodać pole notificationUrl. Jeśli zostanie podane, Paynow wyśle powiadomienie na ten adres, gdy
zwrot osiągnie status końcowy. Zobacz Powiadomienia o statusie zwrotu.
{
"amount": 100,
"reason": "RMA",
"notificationUrl": "https://shop.example.com/paynow/refund-notifications"
}
Krok 2: Dołącz nagłówek Api-Key z wartością Api-Key, którą znajdziesz w Panelu Merchanta.
Krok 3: Oblicz podpis i dołącz go jako nagłówek Signature. Dla podanego
przykładu prawidłowy podpis to o5HQfxngBqr68sLOEtJu0fd1Cl/GzfehZEswk6KMb0w=
Jeśli próbujesz obliczyć podpis z przykładu w swoim kodzie i otrzymujesz inny wynik, upewnij się, że Twoja wiadomość JSON jest sformatowana w ten sam sposób, co wiadomość w przykładzie, tj. z wcięciem czterech spacji i bez znaku nowej linii na końcu.
Krok 4: Wygeneruj losowy ciąg o maksymalnej długości 45 znaków dla nagłówka Idempotency-Key.
Krok 5: Wykonaj żądanie POST z przygotowaną wiadomością na endpoint żądania zwrotu
curl --location 'https://api.sandbox.paynow.pl/v3/payments/NOM3-VWX-YS7-J43/refunds' \
--header 'Api-Key: 97a55694-5478-43b5-b406-fb49ebfdd2b5' \
--header 'Signature: o5HQfxngBqr68sLOEtJu0fd1Cl/GzfehZEswk6KMb0w=' \
--header 'Content-Type: application/json' \
--data '{
"amount": 100
}'
Pamiętaj, że żądanie musi zawierać nagłówki Host i Accept jak opisano tutaj.
Nie są one wymienione powyżej, ponieważ polecenie curl domyślnie je zawiera.
Krok 6: Obsłuż zwróconą odpowiedź:
{
"refundId": "RE6-9YD-ULU-MRL",
"status": "PENDING"
}
Odpowiedź zawiera ID zwrotu wygenerowanego przez Paynow i aktualny status zwrotu.
Zwrócony refundId powinien zostać zapisany przez Merchanta w celu późniejszego wykorzystania.
Krok 7: Zapytaj o status zwrotu. Sprawdź opis endpointu zapytania o status.
curl --location --request GET 'https://api.sandbox.paynow.pl/v3/refunds/RE6-9YD-ULU-MRL/status' \
--header 'Api-Key: 97a55694-5478-43b5-b406-fb49ebfdd2b5' \
--header 'Idempotency-Key: 6228e8f1-4fd9-40bc-9660-37b03c968590' \
--header 'Signature: Aqy2xIQAZghJX4jdzeMZa7I/3WcI2saIAt0qzLoZiMU='
Zamiast odpytywać o status, możesz przekazać notificationUrl w Kroku 1 i zaczekać na
powiadomienie.
Aby zobaczyć więcej szczegółów na temat statusów, zapoznaj się z Mapą statusów zwrotu
Anulowanie zwrotu oczekującego
Jeśli włączyłeś mechanizm Zwrotów oczekujących, każdy nowy zwrot z salda zostanie wykonany z pewnym opóźnieniem. Kiedy zwrot ma status NEW (oczekujący), możesz go anulować
za pomocą żądania API. To samo żądanie anuluje zwrot przelewem, który nadal oczekuje na przelew bankowy.
Poniżej możesz zobaczyć, jak to zrobić.
Na potrzeby tego przewodnika przyjmiemy założenie, że dane autoryzacyjne to:
- Api-Key =
97a55694-5478-43b5-b406-fb49ebfdd2b5 - Refund Id =
RE1-K7E-206-31J
Krok 1: Wygeneruj losowy ciąg o maksymalnej długości 45 znaków dla nagłówka Idempotency-Key.
Krok 2: Wykonaj poniższe żądanie do naszego API:
curl --location --request POST 'https://api.sandbox.paynow.pl/v3/refunds/RE6-9YD-ULU-MRL/cancel' \
-H 'Api-Key: 97a55694-5478-43b5-b406-fb49ebfdd2b5' \
-H 'Signature: e3JjMoexXydWjfBX8ArbExJu8YhTycwKEk0uWc9rXuM='
Należy pamiętać, że za pomocą tego żądania można anulować wyłącznie zwroty w statusie NEW: zwroty oczekujące z salda oraz zwroty przelewem, dla których przelew nie został jeszcze zaksięgowany.
Zwrot przelewem
Zwrot przelewem pozwala zwrócić płatność nawet wtedy, gdy na Twoim saldzie nie ma wystarczających środków. Zamiast pobierać środki z salda, Paynow zwraca dane do przelewu bankowego, który należy wykonać w celu pokrycia zwrotu. Gdy przelew zostanie zaksięgowany na rachunku zwrotów Paynow, zwrot zostaje przetworzony, a środki są przekazywane kupującemu.
Jak to działa
- (Opcjonalnie) Zlecasz standardowy zwrot i otrzymujesz błąd
INSUFFICIENT_BALANCE_FUNDS, co oznacza brak wystarczających środków na saldzie. - Zlecasz zwrot przelewem i określasz, jak długo Paynow ma czekać na przelew (
validityTime, od 3 do 10 dni). - Paynow tworzy zwrot w statusie
NEWi zwraca dane do przelewu (bankTransferData): numer rachunku, kwotę, walutę, tytuł oraz dane odbiorcy. Zwrot nie jest jeszcze przetwarzany. - Wykonujesz przelew bankowy.
- Gdy przelew zostanie zaksięgowany na rachunku zwrotów Paynow, zwrot jest przetwarzany, a środki trafiają do kupującego.
- Jeśli przelew nie zostanie zaksięgowany w czasie
validityTime, zwrot zostaje anulowany (CANCELLED). - Jeśli podałeś
notificationUrl, Paynow wyśle powiadomienie, gdy zwrot zostanie zakończony, nie powiedzie się lub zostanie anulowany.
Przelew musi dokładnie odpowiadać zwróconym danym bankTransferData – ta sama kwota i waluta, na podany numer rachunku oraz z podanym tytułem (title). W przeciwnym razie Paynow nie będzie w stanie powiązać przelewu ze zwrotem i zwrot nie zostanie przetworzony.
Utwórz zwrot przelewem
Wymagane nagłówki są takie same jak dla standardowego zwrotu: Api-Key, Signature, Idempotency-Key,
Content-Type, Host oraz Accept.
Krok 1: Przygotuj wiadomość z żądaniem zwrotu:
{
"amount": 10000,
"reason": "RMA",
"validityTime": 432000,
"notificationUrl": "https://shop.example.com/paynow/refund-notifications"
}
amount(wymagane) – kwota zwrotu w najmniejszej jednostce waluty (np. grosz dla PLN).validityTime(wymagane) – czas w sekundach, przez jaki Paynow oczekuje na przelew bankowy (od259200do864000, czyli od 3 do 10 dni).reason(opcjonalne) – powód zwrotu (RMA,REFUND_BEFORE_14,REFUND_AFTER_14,OTHER).notificationUrl(opcjonalne) – adres URL dla powiadomień o statusie zwrotu.
Krok 2: Dołącz nagłówek Api-Key, oblicz podpis i dołącz go jako nagłówek Signature, wygeneruj Idempotency-Key.
Krok 3: Wykonaj żądanie POST z przygotowaną wiadomością na endpoint zwrotu przelewem:
curl --location 'https://api.sandbox.paynow.pl/v3/payments/NOM3-VWX-YS7-J43/refunds/accounts' \
--header 'Api-Key: 97a55694-5478-43b5-b406-fb49ebfdd2b5' \
--header 'Signature: {calculated-signature}' \
--header 'Idempotency-Key: {idempotency-key}' \
--header 'Content-Type: application/json' \
--data '{
"amount": 10000,
"reason": "RMA",
"validityTime": 432000,
"notificationUrl": "https://shop.example.com/paynow/refund-notifications"
}'
Krok 4: Obsłuż zwróconą odpowiedź:
{
"refundId": "RE6-9YD-ULU-MRL",
"status": "NEW",
"bankTransferData": {
"accountNumber": "{refund-account-number}",
"amount": 10000,
"currency": "PLN",
"title": "{transfer-title}",
"recipientName": "{recipient-name}",
"recipientAddress": "{recipient-address}"
}
}
Krok 5: Wykonaj przelew bankowy zgodnie z bankTransferData – dokładna kwota i waluta, na podany numer rachunku oraz z podanym tytułem (title).
Krok 6: Zaczekaj na powiadomienie lub odpytaj o status zwrotu zgodnie z opisem w sekcji Utwórz zwrot, Krok 7. Do momentu zaksięgowania przelewu zwrot pozostaje w statusie NEW.
Aby anulować zwrot przelewem przed zaksięgowaniem przelewu, użyj żądania anulowania.
Powiadomienia o statusie zwrotu
Paynow może powiadomić Cię, gdy zwrot osiągnie status końcowy, w taki sam sposób jak w przypadku płatności. Powiadomienia działają dla wszystkich typów zwrotów. Są szczególnie przydatne dla zwrotów przelewem oraz zwrotów oczekujących, które mogą zostać zrealizowane nawet kilka dni po ich zleceniu – zamiast wielokrotnie odpytywać o status zwrotu, możesz polegać na powiadomieniu.
Aby otrzymywać powiadomienia, przekaż opcjonalne pole notificationUrl podczas zlecania zwrotu – zarówno standardowego zwrotu (w tym zwrotu oczekującego), jak i zwrotu przelewem. Adres ustawiany jest dla każdego zwrotu osobno. Jeśli go nie podasz, powiadomienia dla tego zwrotu nie będą wysyłane.
Powiadomienia są wysyłane wyłącznie wtedy, gdy zwrot zmieni status na jeden ze statusów końcowych:
| Code | Description |
|---|---|
| SUCCESSFUL | Zwrot został pomyślnie przetworzony, a środki zostały przekazane kupującemu. |
| FAILED | Wystąpił problem podczas przetwarzania zwrotu. |
| CANCELLED | Zwrot został anulowany przez API lub z powodu upływu czasu validityTime. |
Paynow wysyła żądanie POST z nagłówkami Content-Type: application/json oraz Signature na podany adres notificationUrl:
{
"refundId": "RE6-9YD-ULU-MRL",
"status": "SUCCESSFUL"
}
Gdy status przyjmuje wartość FAILED, powiadomienie zawiera dodatkowo pole failureReason (CARD_BALANCE_ERROR, BUYER_ACCOUNT_CLOSED lub OTHER):
{
"refundId": "RE6-9YD-ULU-MRL",
"status": "FAILED",
"failureReason": "OTHER"
}
- Zweryfikuj nagłówek
Signaturew taki sam sposób jak dla powiadomień o płatnościach – zobacz Podpis dla powiadomień. Jeśli podpis się nie zgadza, nie przetwarzaj wiadomości. - Odpowiedz statusem
200 OKlub202 Acceptedz pustym body. Każda inna odpowiedź jest traktowana jako błąd dostarczenia. - Nieudane próby dostarczenia są ponawiane zgodnie z tym samym harmonogramem co dla płatności. Jeśli wszystkie próby zakończą się niepowodzeniem, odpytaj o status zwrotu.
- To samo powiadomienie może zostać dostarczone więcej niż raz – upewnij się, że jego obsługa po Twojej stronie jest idempotentna.