Download OpenAPI specification:Download
Integracja systemów Polskie ePłatności Online z Twoją stroną oznacza wybrania jednej z dwóch głównych metod, które różnią się zarówno sposobem implementacji, jak i późniejszym user experience Twoich klientów:
Secure Form to gotowe i proste do wdrożenia rozwiązanie płatnicze. Wystarczy, że przekierujesz klienta w odpowiedni sposób do przygotowanego przez nas formularza płatniczego. Hostowany jest on na specjalnych, bezpiecznych serwerach w domenie Polskich ePłatności Online – stąd właśnie bierze się jego nazwa.
API pozwoli Ci na przyjmowanie płatności bezpośrednio na Twojej stronie! Dla Twoich klientów PeP Online pozostanie niewidoczne. Możesz wdrożyć API wykorzystując PHP, Ruby, Pythona lub dowolny inny język programowania. Będziesz mieć też do dyspozycji wiele zaawansowanych funkcji.
Na poniższym schemacie przedstawiamy uogólniony przepływ danych podczas przetwarzania płatności internetowych. Daje on ogólny obraz, ale polecamy zapoznanie się też ze schematami dotyczącymi API oraz Secure Form – obie metody różnią się między sobą. Pamiętaj aby niezależnie od wybranej metody płatności zaimplementować powiadomienia o transakcjach
Jeśli korzystasz (lub planujesz) z gotowego systemu e-commerce, prawdopodobnie zechcesz skorzystać z jednego z naszych pluginów do takich systemów. Umożliwiają one łatwe połączenie takich platform z naszymi systemami płatniczymi. Przygotowaliśmy również kilka opisów różnych modeli biznesowych, które mogą Cię zainspirować przy tworzeniu własnego rozwiązania. Być może któryś z nich idealnie wpasuje się z specyfikę Twojego produktu/usługi i pozwoli nawet zwiększyć dochody.
Oferujemy szereg pluginów. Dzięki nim wdrożenie płatności na Twojej stronie zajmie tylko kilka minut.
Dedykowany plugin do platformy Magento, umożliwiający włączenie płatności z wykorzystaniem systemów PeP Online w sklepach działających w oparciu o Magento.
Pobierz plugin do Magento 1 | Pobierz plugin do Magento 2
Dedykowany plugin do platformy Presta Shop, umożliwiający włączenie płatności z wykorzystaniem systemów PeP Online w sklepach działających w oparciu o Presta Shop.
Prosty plugin PeP Online dla WordPressa pozwala na umieszczenie przycisku płatniczego na stronie zbudowanej na WordPress.
Dedykowany plugin do WooCommerce, umożliwiający włączenie płatności z wykorzystaniem systemów PeP Online w sklepach działających w oparciu o WooCommerce. Wtyczka wspiera również WooCommerce Subscriptions.
WHMCS jest wiodącą, międzynarodową platformą automatyzacji płatności w sieci, zasilającą dziesiątki tysięcy firm hostingowych. Wtyczka PeP Online do platformy WHMCS, pozwoli Ci szybko zaimplementować bezpieczne płatności w Twoim biznesie.
Oferujemy również wiele integracji do platform e-commerce’owych.
Shoplo to platforma ecommerce, która oferuje narzędzie do tworzenia sklepu internetowego. Dodatkowo umożliwia sprzedaż produktów na Facebooku, poprzez mobile oraz na portalach aukcyjnych, takich jak Allegro czy eBay. Płatności PeP Online stają się aktywne po wprowadzeniu wartości Merchant ID i hash salt w panelu Shoplo. Na stronie zamówienia pojawi się dodatkowy sposób płatności od PeP Online.
Comarch e-Sklep to nowoczesna platforma eCommerce do prowadzenia własnego sklepu internetowego, funkcjonująca bezbłędnie w środowisku Comarch ERP. Integracja z PeP Online umożliwia przyjmowanie bezpiecznych płatności z całego świata. Integracja z PeP Online następuje z panelu eSklepu.
Shoper to platforma eCommerce dla sklepu internetowego obsługujące cały proces zakupowy: od przyjęcia zamówienia, przez jego wysyłkę, aż do ostatniego etapu rozliczenia księgowo-magazynowego. Integracja z PeP Online umożliwia Ci przyjmowanie płatności z całego świata. Integracja przebiega w Twoim koncie PeP w zakładce 'Administracja'.
Integracja PeP Online z platformą eCommerce Ebexo jest dostępna z panelu administracyjnego sklepu Ebexo.
To oprogramowanie eCommerce mające jednorazową opłatę bez dodatkowych zobowiązań licencyjnych. Integracja z PeP Online jest dostępna z poziomu panelu admina sklepu, po pobraniu i wprowadzeniu najnowszej aktualizacji sklepu w dziale 'Formy płatności'.
Clickshop to platforma eCommerce dla sklepu internetowego obsługujące cały proces zakupowy: od przyjęcia zamówienia, przez jego wysyłkę, aż do ostatniego etapu rozliczenia księgowo-magazynowego. Integracja z PeP Online umożliwia Ci przyjmowanie płatności z całego świata.
Pobierz nasz darmowy whitepaper o technologii REST. Dowiesz się z niego m.in.:
Secure Form to gotowe i łatwe w implementacji rozwiązanie płatnicze, dzięki któremu możesz przyjmować płatności z PeP Online. Wystarczy, że przekierujesz klienta na formularz płatniczy, który od nas dostaniesz. Nie musisz także przechodzić żadnych audytów/skanów PCI ani nawet mieć certyfikatu SSL (choć posiadanie go jest oczywiście zalecane). Wszystko to dlatego, że płatność odbywa się z całości po naszej stronie, tj. w domenie Polskich ePłatności Online. Z punktu widzenia klientów, dokonywanie płatności może wyglądać następująco:
Musisz tylko przekazać informacje (z użyciem POST
) dotyczące transakcji (takie jak nazwa produktu, cena itp.) do naszego Secure Form.
Po wysłaniu formularza, klient zostanie przekierowany z powrotem na Twoją stronę, do której przesłane zostaną też informacje zwrotne.
Do Ciebie należy już wybór, czy zostaną przesłane z użyciem POST
czy GET
.
Możesz wykorzystać te dane, by poinformować klienta o statusie transakcji.
Podsumowując, cały proces może być przedstawiony z poniższych krokach:
Secure Form to gotowy formularz płatniczy przygotowany przez Polskie ePłatności Online. Jeśli nie chcesz integrować się z naszymi systemami przez API, Secure Form jest rozwiązaniem dla Ciebie.
Wystarczy, że przekierujesz klienta na przygotowany przez PeP Online formularz płatniczy. Klient bezpiecznie dokona tam płatności i powróci na Twoją stronę.
Przykład:
<form action="https://secure.pep.pl/order/cart.html" method="post">
<input type="hidden" name="amount" value="19.99">
<input type="hidden" name="currency" value="EUR">
<input type="hidden" name="merchant_id" value="john_test">
<input type="hidden" name="description" value="TR001" />
<input type="hidden" name="transaction_description" value="Product 1 transaction" />
<input type="hidden" name="transaction_type" value="S">
<input type="hidden" name="back_url" value="http://johns-shop.com/purchased">
<input type="hidden" name="language" value="pl">
<input type="hidden" name="hash" value="6926ed14d1ae4d8eb2350d3c15e6a420e3bb7052" />
<button type="submit">Zapłać z PeP</button>
</form>
Żeby uzyskać dane dostępowe do Secure Form, po prostu zaloguj się do Merchant Panelu, wybierz kolejno
Administracja -> Integracja -> Podstawowe -> Integracja Secure Form
Znajdziesz tam swoje merchant_id
oraz hash salt
– dzięki tym informacjom możesz poprawnie przekierować klientów na Secure Form przez POST
.
Wartość hash
jest liczona w następujący sposób:
hash = SHA1(salt + "|" + description + "|" + amount + "|" + currency + "|" + transaction_type)
Przykład:
hash = SHA1("MySalt|TR001|19.99|EUR|S") = "6926ed14d1ae4d8eb2350d3c15e6a420e3bb7052"
Możesz ustawić wartość salt
w Merchant Panelu.
UWAGA! Nigdy nie należy przesyłać wartości salt ani liczyć wartości hash po stronie klienta. Powinno to się odbywać zawsze po stronie serwera.
Poniżej znajdziesz pełna listę parametrów, które mogą (lub muszą) być wysłane w zapytaniu POST
.
Pola customer_*
nie są wymagane, jednak ich użycie jest mocno zalecane, ponieważ w przypadku nie wysłania ich, użytkownik będzie proszony o uzupełnienie tych danych na Secure Formie PeP Online.
Pole | Format | Wymagane | Opis |
---|---|---|---|
merchant_id | string (32) | tak | Twój Numer ID umożliwiający dostęp do Secure Form. Możesz znaleźć ten numer w Merchant Panelu (account => secure form customization => options) |
description | string(1-255) | tak | Tylko znaki alfanumeryczne. Identyfikator transakcji, który zostanie przekazany do systemu PeP Online. Wartość pola musi być unikalna dla każdej transakcji! Zalecamy by wartością tego pola był identyfikator transakcji w Twoim systemie (sklepie). Będzie później widoczny w Merchant Panelu jako opis danej transakcji. Dozwolone są jedynie znaki alfanumeryczne. |
transaction_description | string(2-10000) | tak | Krótki opis produktu/usługi/transakcji. Pojawi się w polu opisu na formularzu płatniczym. |
amount | decimal(12,2) | tak | **Używaj kropki (.) jako separatora dziesiętnego.**Całkowita kwota do pobrania. |
currency | string(3) | tak | Kod waluty ISO 4217; kwota określona w wartości amount będzie pobrana w tej walucie (na przykład “PLN” lub “EUR”). |
back_url | string(500) | tak | Adres strony, na którą klient zostanie przekierowany po dokonaniu płatności, np. http://mojsklep.pl/zaplacone |
transaction_type | string(1) | tak | Trzy możliwe wartości: A – tylko autoryzacja, S – sprzedaż, T - tokenizacja (tokenizacja karty bez pobrania środków klienta). W przypadku płatności kartami, wybierz preferowaną wartość, w przypadku innych metod płatności, wybierz S |
hash | string(64) | tak | Security hash. |
hash_type | string(8) | nie | SHA256 dla transaction_type=T |
language | string(2) | nie | Kod języka ISO 639. Obecnie Secure Form może być wyświetlony w następujących językach: en – angielski, pl – polski, de – niemiecki, es – hiszpański, fr – francuski, nl – holenderski, it – włoski, cz – czeski, fi – fiński, dk – duński, no – norweski, sk – słowacki, se – szwedzki. Jeżeli to pole nie zostanie wysłane, formularz wybierze język na podstawie języka przeglądarki lub wyświetli się w wersji angielskiej. |
payment_methods | string | nie | Lista ID metod płatności możliwych do wybrania w bramce. Używaj przecinka jako separatora wartości. Lista dostępnych metod znajduje się tutaj. |
customer_id | string(12) - tylko znaki numeryczne | Tak - dla transaction_type=T | identyfikator płatnika w systemie Merchanta. |
customer_name | string(50) | nie | Imię i nazwisko klienta (zalecane*). |
customer_email | string(80) | nie | Adres e-mail klienta (zalecane*). |
customer_zip | string(9) | nie | Kod pocztowy klienta (jeśli dotyczy). |
customer_city | string(40) | nie | Miasto (zalecane*). |
customer_state | string(40) | nie | Stan/województwo (jeśli dotyczy). |
customer_country | string(2) | nie | Kod kraju klienta ISO 3166, np. PL lub GB (zalecane*). |
Kiedy klient zapłaci (dokona płatności w Secure Formie), zostanie przekierowany z powrotem na Twoją stronę (na adres podany w polu back_url
).
W trakcie przekierowania przekazywany jest zestaw parametrów za pomocą metody POST
lub GET
(metoda ustawiana w Merchant Panelu).
Jako dodatkowy mechanizm zabezpieczający otrzymanie potwierdzenia zaimplementuj również powiadomienia o transakcjach.
Pole | Format | Opis |
---|---|---|
status | string | Status transakcji. Zobacz listę dostępnych statusów. |
customer_id | string(12) | Parametr customer_id przekazany w trakcie tokenizacji, gdy parametr transaction_type=T |
description | string(20) | Identyfikator transakcji – ten sam, który był wysłany w żądaniu. |
amount | decimal(12,2) | Kwota transakcji. |
currency | string(3) | Kod waluty transakcji w standardzie ISO 4217, np. PLN, GBP, EUR. |
hash | string(40) | Security hash. |
id_authorization | integer(10) | Numer ID autoryzacji transakcji w systemie PeP Online. Pusty, jeśli: typ transakcji to S (sale), T (tokenizacja) lub wystąpił błąd. |
id_sale | integer(10) | Numer ID transakcji w systemie PeP Online. Pusty, jeśli: typ transakcji to A (authorization), T (tokenizacja) lub wystąpił błąd. |
id_error | integer(10) | Numer ID błędu w systemie PeP Online. Pusty, jeśli błąd nie wystąpił. |
error_code | integer(3) | Kod błędu. |
error_text | string(500) | Krótki opis błędu. |
fraud_score | decimal(4,2) | Wynik oceny ryzyka. 0.00 – niskie ryzyko, 10.00 – wysokie ryzyko. Puste, jeśli ocena ryzyka nie została przeprowadzona. |
avs_result | string(2) | Wynik sprawdzania AVS. Puste, jeśli sprawdzenie AVS nie zostało przeprowadzone. |
PeP Online wykorzystuje tę samą wartość salt
do wygenerowania innej wartości hash
wysyłanej w odpowiedzi. Jest ona liczona w następujący sposób:
hash = SHA1(salt + "|" + status + "|" + description + "|" + amount + "|" + currency + "|" + id)
Wartość id to, w zależności od otrzymanej odpowiedzi, albo id_sale
, albo id_authorization
. Jeśli zostanie zwrócony błąd, wartość id
powinna być pustym łańcuchem znaków.
Wystarczy, że porównasz otrzymaną w odpowiedzi wartość hash z obliczoną przez siebie, by poznać status transakcji.
ID | Metoda płatności |
---|---|
1 | Visa Card |
2 | MasterCard |
3 | Maestro UK Card |
4 | American Express Card |
5 | Direct Debit in Germany (ELV) |
6 | Direct Debit in the Netherlands (ENL) |
7 | Direct Debit in Austria (EEV) |
8 | Solo Card |
9 | Maestro International Card |
10 | Diners |
11 | Discover Card |
12 | JCB Card |
13 | Direct Debit in France |
14 | Direct Debit in United Kingdom |
15 | Direct Debit in Belgium |
16 | Direct Debit in Switzerland |
17 | Direct Debit in Italy |
18 | Direct Debit in Spain |
19 | Direct Debit in USA |
20 | Direct Debit in Canada |
21 | Direct Debit in Australia |
22 | Direct Debit in Irland |
23 | PayPal |
24 | Sofortbanking |
25 | Inteligo |
26 | iPko |
27 | mTransfer |
31 | Alior Bank |
32 | Alior Sync |
33 | Millenium |
35 | WBK |
36 | Credit Agricole |
37 | Other |
38 | Poczta Polska |
41 | Getin Bank |
42 | ING Bank Śląski |
44 | Giropay |
45 | Pekao SA |
46 | Ideal |
47 | SEPA Direct Debit |
48 | Bank Pocztowy |
50 | BNP Paribas |
52 | Blik |
53 | Apple Pay |
54 | Citi Handlowy |
55 | Plus Bank |
56 | Noble Pay |
57 | Bank Spółdzielczy |
58 | Nest Bank |
59 | Podkarpacki Bank Spółdzielczy |
60 | SGB |
61 | Google Pay |
62 | Toyota Bank |
63 | BOŚ Bank |
64 | Visa Mobile |
API jest najlepszym sposobem integracji z PeP Online, jeśli chcesz mieć pełną kontrolę i wszystko dokładnie tak, jak sobie zaplanujesz. Jednocześnie dokonywanie płatności będzie wygodniejsze dla Twoich klientów, ponieważ cały proces będzie można zredukować nawet do pojedynczego kliknięcia! Konieczne będzie jednak spełnienie pewnych wymagań (na przykład posiadanie certyfikatu SSL), ale za to stworzysz takie rozwiązania, które idealnie będą odpowiadały specyfice Twojego biznesu (zobacz podstronę o modelach biznesowych, by dowiedzieć się więcej).
Z punktu widzenia klientów, dokonywanie płatności może wyglądać następująco:
Ponieważ nie ma przekierowania do żadnych innych domen a cały proces płatności odbywa się na jednej stronie, możesz niemal dowolnie zdefiniować proces płatności, w tym wygląd/zachowanie (np. formularzy), sposób ładowania (np. wykorzystując AJAX, jeśli zechcesz), komunikaty itp. Ponadto możesz implementować wiele innych modeli płatniczych. W zależności od Twoich potrzeb, biznesu i wybranych metod płatności, mogą to być płatności jednym kliknięciem, płatności cykliczne, obsługa transakcji zwrotnych (refund) i wiele innych.
Możesz również dodatkowo zabezpieczyć swoje płatności dodając adres IP serwera do whitelisty w Merchant Panelu w zakładce Administracja >> Whitelisty.
Nie zapomnij również aby dodać mechanizm powiadomień o transakcjach aby otrzymywać zawsze informacje o udanych transakcjach.
Cóż, w tym przypadku wszystko zależy od Ciebie. Wiesz najlepiej, czego potrzebujesz i co chcesz osiągnąć – my zapewniamy Ci narzędzia i proponujemy pomoc. Przygotowaliśmy nakładkę do API (PeP Online REST Client) w kilku językach programowania i gotowe przykłady kodu w całej dokumentacji. Możesz wykorzystać to w swoim projekcie, a możesz potraktować jedynie jako przykład zastosowania i stworzyć własną implementację. Przygotowaliśmy też sekcję wdrażanie i testy, gdzie znajdziesz informacje pomocne podczas integrowania się z naszymi systemami i pozwalające na łatwe testowanie. Cały proces płatności z wykorzystaniem API może być przedstawiony z poniższych krokach:
PeP Online REST Client to nakładka na nasze restowe API. Możesz wybrać wersję w określonym języku programowania i skorzystać z niej, by wywoływać poszczególne metody API. Wszystkie przykłady kodu na tej stronie opierają się na metodach PeP Online REST Client.
JavaScript | PHP | Ruby | Python | Android
Jeśli wybierzesz nasze restowe API zamiast formularza Secure Form, to znaczy, że prawdopodobnie chcesz przyjmować płatności na swojej stronie i tym samym poprawić komfort zakupów. Oznacza to też, że musisz pozyskać odpowiednie dane, by przekazać je do systemu PeP Online wraz ze zgłoszeniem żądania płatności.
Większość informacji wymaganych do wysłania żądania płatności nie musi być wprowadzania przez klienta (a przynajmniej nie za każdym razem). Przykładowo dane takie jak imię, nazwisko, e-mail czy adres klienta mogą być pobrane z Twojej bazy danych – oczywiście przy założeniu, że klient utworzył na Twojej stronie (serwisie, sklepie) konto i takie dane wprowadził. Podobnie dane dotyczące samej płatności (kwota, waluta, opis transakcji) mogą być wygenerowane lub pobrane automatycznie. Dobrze jest jednak wyświetlić te informacje na ekranie płatności – dzięki temu klient nie będzie miał żadnych wątpliwości ile i za co płaci i nie dojdzie do nieporozumień.
W zależności od konkretnej metody płatności, możesz wymagać od klienta podania określonych informacji podczas realizowania płatności. Najczęściej stosuje się po prostu formularz HTML, w którym klient wpisuje odpowiednie dane. Kiedy to zrobi i zatwierdzi formularz, po prostu przesyłasz te dane do PeP Online.
W wielu przypadkach dane karty będą wymagane, jeśli klient zdecyduje się płacić tą właśnie metodą (można to jednak ominąć np. płatnościami single-click). Typowy, prosty formularz może wyglądać następująco:
<form action="#" id="payment-form" method="post">
<label>Numer karty:</label>
<input type="text" id="card_number" name="card[card_number]" size="19" />
<label>Imię i nazwisko na karcie:</label>
<input type="text" id="name_on_card" name="card[name_on_card]" size="50" />
<label>Data ważności:</label>
<input type="text" id="expiration_month" name="card[expiration_month]" size="2" />
<input type="text" id="expiration_year" name="card[expiration_year]" size="4" />
<label>CVV/CVC:</label>
<input type="text" id="card_code" name="card[card_code]" size="4" />
<button type="submit">Zapłać z PeP</button>
</form>
Liczba pól formularza zależy od Twojego przypadku, modelu biznesowego – to Twoja decyzja. Co istotne, możesz zminimalizować formularz nawet tylko do jednego przycisku! To właśnie płatności single-click, czyli płatności jednym kliknięciem – najszybszy i najwygodniejszy sposób robienia zakupów online.
Karty to jedne z najpopularniejszych i najwygodniejszych metod płatności na świecie. Klienci mogą używać różnego rodzaju kart do płacenia przez internet, w tym m.in. kart kredytowych, debetowych czy przedpłaconych (pre-paid). Karty stanowią dobry wybór dla większości rynków, a na niektórych wręcz dominują.
Zanim zaczniesz wywoływać metody naszego API, pamiętaj, aby poprawnie zainicjować PeP Online Rest Client. To bardzo łatwe, po prostu załącz odpowiedni plik oraz podaj swoją nazwę użytkownika i hasło. Więcej informacji na temat integracji z naszymi systemami znajdziesz na stronie wdrażanie i testy.
include_once ('PePRestClient.php');
$client = new PePRestClient('your_login', 'your_password');
require 'pep_client'
client = PeP::Client.new('your_login', 'your_password')
from client import PePRestClient
client = PePRestClient("your_login", "your_password")
PePApi api = PePClientFactory.createClassicClient(context, "your_login", "your_password");
PeP.js to autorska biblioteka JavaScriptowa, której zadaniem jest ztokenizowanie danych kartowych, które Twój klient podaje na Twojej stronie. Dzięki niej dane dotyczące kart płatniczych Twoich klientów są wysyłane w tle do naszych serwerów, a my zwracamy Tobie token, którego możesz używać do realizowania płatności, czy autoryzacji. Ściągnij bibliotekę PeP.js stąd. Przebieg płatności z użyciem PeP Online REST.js:
Oto prosty przykład typowego formularza płatności:
<form id="checkout-form" action="" type="">
<!-- merchant's input elements, as many as required -->
<input type="text" name="first-name" value="">
<input type="text" name="last-name" value="">
<input type="text" name="email" value="">
<input type="text" name="address" value="">
<!-- card related input elements: -->
<input type="text" value="" data-paylane="cc-number">
<input type="text" value="" data-paylane="cc-expiry-month">
<input type="text" value="" data-paylane="cc-expiry-year">
<input type="text" value="" data-paylane="cc-cvv">
<input type="text" value="" data-paylane="cc-name-on-card">
<input type="submit" value="submit">
</form>
Rzeczywisty kod formularza można dowolnie zmieniać według własnych potrzeb, należy jednak spełniać przy tym poniższe wymagania:
data-paylane
.name
. To wymóg bezpieczeństwa, który zapobiega wysłaniu danych kart do serwerów sprzedawcy.id
.
Klient PeP.js będzie się posługiwał tą wartością.W następnej kolejności zainicjalizuj klienta PeP.js:
<script src="path/to/PeP.js"></script>
<script>
try
{
var client = new PePClient({
publicApiKey : 'PUBLIC_API_KEY',
paymentForm : 'checkout-form',
});
}
catch (e)
{
console.log(e); // exceptions are fatal
}
</script>
Klient PeP.js wymaga podania jedynie publicznego klucza API oraz wskazania na formularz płatniczy.
Administracja -> Integracja -> Podstawowe -> Integracja API
)id
formularzaPoniższe wartości mogą być opcjonalnie przekazane do klienta PeP.js (jeśli nie zostaną zdefiniowane, zostaną użyte wartości):
cardNumberInputName
(domyślnie: cc-number
) – alternatywna wartość data-paylane
odnosząca się do pola numeru kartycardExpiryMonthInputName
(domyślnie: cc-expiry-month
) – alternatywna wartość data-paylane
odnosząca się do pola miesiąca ważności kartycardExpiryYearInputName
(domyślnie: cc-expiry-year
) – alternatywna wartość data-paylane
odnosząca się do pola roku ważności kartycardSecurityvarInputName
(domyślnie: cc-cvv
) – alternatywna wartość data-paylane
odnosząca się do pola kodu CVV2/CVC2cardHolderInputName
(domyślnie: cc-name-on-card
) – alternatywna wartość data-paylane
odnosząca się do pola z imieniem i nazwiskiem posiadacza kartyerrorTypeInputName
(domyślnie: paylane_error_type
) – alternatywna wartość name
odnosząca się do pola typu błęduerrorCodeInputName
(domyślnie: paylane_error_code
) – alternatywna wartość name
odnosząca się do pola kodu błęduerrorDescriptionInputName
(domyślnie: paylane_error_description
) – alternatywna wartość name
odnosząca się do pola opisu błędutokenInputId
(domyślnie: paylane-token
) – alternatywna wartość id
odnosząca się do pola tokenutokenInputName
(domyślnie: paylane_token
) – alternatywna wartość name
odnosząca się do pola tokenuerrorHandler
(domyślnie: pusta funkcja) – funkcja obsługi błędu, przyjmuje trzy argumenty: type
, code
, description
callbackHandler
(domyślnie: pusta funkcja) – opcjonalna funkcja obsługująca zatwierdzenie formularza. Zostanie ona wywołana w momencie, gdy zakończy się wykonywanie żądania AJAX z tokenem. Token pojawi się w formularzu jako ukryte pole i zostanie przekazany do funkcji jako jedyny argument. Jeśli funkcja nie zostanie określona, zatwierdzenie formularza będzie miało standardowy przebieg. /**
Custom token callback handler.
@param {string} token Temporary credit card token
@return {void}
*/
callbackHandler: function(token){}
PeP.js może wywoływać wyjątki i błędy.
Wyjątki mogą powstać jedynie podczas inicjalizacji klienta, np. gdy wymagany formularz lub jego pola nie zostaną znalezione lub został podany pusty klucz publiczny. Takie wyjątki muszą być obsłużone standardowo z użyciem try/catch, aczkolwiek nie powinny wystepować, jeśli tylko formularz został prawidłowo przygotowany.
Z kolei błędy mogą występować niespodziewanie z różnych przyczyn, takich jak przerwy w połączeniu sieciowym, źle sformatowane dane (np. token czy numer karty) itp. Klient PeP.js umożliwia obsługe błędów na dwa sposoby: z użyciem funkcji obsługi błędów (przekazywanej do konstruktora jako errorHandler) i jako ukryte pola formularza (które można obsłużyć po stronie serwera).
paylane_error_type
: typ błędu; 1
, jeśli to błąd połączenia, 2
, jeśli to błąd zwrócony przez API REST.js PePpaylane_error_code
: występuje tylko w przypadku błędów API (kod zwracany przez API REST.js)paylane_error_description
: występuje tylko w przypadku błędów API (opis zwracany przez API REST.js)Przygotuj dane potrzebne do przeprowadzenia płatności jak w przykładzie poniżej. Jak widzisz, w przypadku płatności kartą potrzebne są trzy zestawy informacji: dotyczące transakcji (sale), klienta (customer) oraz karty (card). Dla transakcji na terenie UE użyj metody 3DSecure/checkCardByToken.
Następnie wykonaj płatność używając metody cardSaleByToken lub 3DSecure/authSale dla transakcji na terenie UE.
Możesz sprawdzić, czy płatność się powiodła, wywołując metodę isSuccess
. Pozyskanie numeru ID transakcji (lub informacji o błędzie, jeśli coś pójdzie nie tak), jest również bardzo proste i może wyglądać jak na poniższym przykładzie.
Dokładne opisy wszystkich metod i struktur znajdziesz w opisie funkcji.
$card_params = array(
'sale' => array(
'amount' => 19.99,
'currency' => 'EUR',
'description' => 'Product #1'
),
'customer' => array(
'name' => 'John Doe',
'email' => 'john@doe.com',
'ip' => '127.0.0.1',
'address' => array (
'street_house' => '1600 Pennsylvania Avenue Northwest',
'city' => 'Washington',
'state' => 'DC',
'zip' => '500',
'country_code' => 'US',
),
),
'card' => array(
'token' => '12a34b45c67d89e00f1aa2bb3cc4dd5ee6ff12a34b45c67d89e00f1aa2bb3cc4',
),
);
card_params = {
'sale' => {
'amount' => 19.99,
'currency' => 'EUR',
'description' => 'Product #1',
},
'customer' => {
'name' => 'John Doe',
'email' => 'john@doe.com',
'ip' => '127.0.0.1',
'address' => {
'street_house' => '1600 Pennsylvania Avenue Northwest',
'city' => 'Washington',
'state' => 'DC',
'zip' => '500',
'country_code' => 'US'
}
},
'card' => {
'token' => '12a34b45c67d89e00f1aa2bb3cc4dd5ee6ff12a34b45c67d89e00f1aa2bb3cc4'
}
}
card_params = {
'sale' : {
'amount' : 19.99,
'currency' : 'EUR',
'description' : 'Product #1'
},
'customer' : {
'name' : 'John Doe',
'email' : 'john@doe.com',
'ip' : '127.0.0.1',
'address' : {
'street_house' : '1600 Pennsylvania Avenue Northwest',
'city' : 'Washington',
'state' : 'DC',
'zip' : '500',
'country_code' : 'US'
}
},
'card' : {
'token' : '12a34b45c67d89e00f1aa2bb3cc4dd5ee6ff12a34b45c67d89e00f1aa2bb3cc4'
}
}
Sale sale = new Sale(
19.99,
"EUR",
"Product #1"
);
Card card = new Card(
"4111111111111111",
"03",
"2017",
"John Doe",
"123"
);
Address address = new Address(
"1600 Pennsylvania Avenue Northwest",
"Washington",
"DC",
"500",
"US"
);
Customer customer = new Customer(
"John Doe",
"john@doe.com",
"127.0.0.1",
address
);
try {
$status = $client->cardSaleByToken($card_params);
} catch (Exception $e) {
// handle exceptions here
}
// checking transaction status example (optional):
if ($client->isSuccess()) {
echo "Success, id_sale: {$status['id_sale']} \n";
} else {
die("Error ID: {$status['error']['id_error']}, \n".
"Error number: {$status['error']['error_number']}, \n".
"Error description: {$status['error']['error_description']}");
}
begin
status = client.card_sale_by_token(card_params)
rescue PeP::ClientError => e
# handle exceptions here
end
# checking transaction status example (optional):
if client.success?
puts "Success, id_sale: #{status["id_sale"]}"
else
puts "Error ID: #{status["error"]["id_error"]}, \n"\
"Error number: #{status["error"]["error_number"]}, \n"\
"Error description: #{status["error"]["error_description"]}"
exit
end
try:
status = client.card_sale_by_token(card_params)
except Exception, e:
# handle exceptions here
# checking transaction status example (optional):
if client.is_success():
print 'Success, id_sale: %s' % status['id_sale']
else:
sys.exit('Error ID: ' + str(status["error"]["id_error"]) + '\n' \
'Error number: ' + str(status["error"]["error_number"]) + '\n' \
'Error description: ' + str(status["error"]["error_description"]))
api.cardSale(sale, customer, card, new Callback<CardSaleResult>() {
@Override
public void onFinish(CardSaleResult result) {
// success
}
@HandleException
public void onProtocolError(ProtocolException e) {
// invoke if not success
// e.getCode() - error code
// e.getMessage() - error message
}
@Override
public void onError(Exception e) {
// connection error etc.
}
Możesz nie chcieć od razu pobrać pieniędzy z karty klienta, ale jedynie autoryzować jego kartę. To dość użyteczne w wielu przypadkach, takich jak:
Autoryzacja karty skutkuje zablokowaniem określonej kwoty na karcie klienta (na pewien czas). Możesz zablokować całą kwotę danej transakcji (i pobrać środki później) lub zablokować tylko 1 zł (lub $1, €1, £1…), aby jedynie zweryfikować kartę.
Przygotuj dane potrzebne do autoryzacji karty. Będą to identyczne informacje jak w przypadku “zwykłej” płatności kartą.
Jeśli procesujesz na terenie UE musisz do autoryzacji użyć 3DSecure/checkCard. Dokładniejszy opis przygotowania danych karty z użyciem 3-D Secure znajdziesz tutaj
Mając te dane, po prostu wywołaj metodę cardAuthorizationByToken (podobnie jak w przypadku płatności wywołasz cardSale).
Jeśli używasz 3-D Secure użyj 3DSecure/auth w celu dokonania autoryzacji.
3DSecure/checkCard musisz zastosować tylko w momencie autoryzacji. Później jeśli ponawiasz płatność za pomocą resales/authorization nie musisz ponownie sprawdzać karty w programie 3-D Secure
Możesz łatwo sprawdzić, czy autoryzacja się powiodła oraz sprawdzić numer ID autoryzacji – możesz go potem użyć do ponownych obciążeń karty (resale), jeśli chcesz wykorzystać np. płatności cykliczne lub single-click.
$card_params = array(
'sale' => array(
'amount' => 1.00,
'currency' => 'EUR',
'description' => 'Product #1'
),
'customer' => array(
'name' => 'John Doe',
'email' => 'john@doe.com',
'ip' => '127.0.0.1',
'address' => array (
'street_house' => '1600 Pennsylvania Avenue Northwest',
'city' => 'Washington',
'state' => 'DC',
'zip' => '500',
'country_code' => 'US',
),
),
'card' => array(
'token' => '12a34b45c67d89e00f1aa2bb3cc4dd5ee6ff12a34b45c67d89e00f1aa2bb3cc4'
),
);
card_params = {
'sale' => {
'amount' => 19.99,
'currency' => 'EUR',
'description' => 'Product #1',
},
'customer' => {
'name' => 'John Doe',
'email' => 'john@doe.com',
'ip' => '127.0.0.1',
'address' => {
'street_house' => '1600 Pennsylvania Avenue Northwest',
'city' => 'Washington',
'state' => 'DC',
'zip' => '500',
'country_code' => 'US'
}
},
'card' => {
'token' => '12a34b45c67d89e00f1aa2bb3cc4dd5ee6ff12a34b45c67d89e00f1aa2bb3cc4'
}
}
card_params = {
'sale' : {
'amount' : 19.99,
'currency' : 'EUR',
'description' : 'Product #1'
},
'customer' : {
'name' : 'John Doe',
'email' : 'john@doe.com',
'ip' : '127.0.0.1',
'address' : {
'street_house' : '1600 Pennsylvania Avenue Northwest',
'city' : 'Washington',
'state' : 'DC',
'zip' : '500',
'country_code' : 'US'
}
},
'card' : {
'token' : '12a34b45c67d89e00f1aa2bb3cc4dd5ee6ff12a34b45c67d89e00f1aa2bb3cc4'
}
}
Sale sale = new Sale(19.99, "EUR", "Product #1");
Address address = new Address("1600 Pennsylvania Avenue Northwest", "Washington", "DC", "500", "US");
Customer customer = new Customer("John Doe", "john@doe.com", "127.0.0.1", address);
Card card = new Card("4111111111111111", "03", "2017", "John Doe", "123");
try {
$status = $client->cardAuthorizationByToken($card_params);
} catch (Exception $e) {
// handle exceptions here
}
// checking authorization status example (optional):
if ($client->isSuccess()) {
echo "Success, id_authorization: {$status['id_authorization']} \n";
} else {
die("Error ID: {$status['error']['id_error']}, \n".
"Error number: {$status['error']['error_number']}, \n".
"Error description: {$status['error']['error_description']}");
}
begin
status = client.card_authorization_by_token(card_params)
rescue PeP::ClientError => e
# handle exceptions here
end
# checking authorization status example (optional):
if client.success?
puts "Success, id_authorization: #{status["id_authorization"]}"
else
puts "Error ID: #{status["error"]["id_error"]}, \n"\
"Error number: #{status["error"]["error_number"]}, \n"\
"Error description: #{status["error"]["error_description"]}"
exit
end
try:
status = client.card_authorization_by_token(card_params)
except Exception, e:
# handle exceptions here
# checking authorization status example (optional):
if client.is_success():
print 'Success, id_authorization: %s' % status['id_authorization']
else:
sys.exit('Error ID: ' + str(status["error"]["id_error"]) + '\n' \
'Error number: ' + str(status["error"]["error_number"]) + '\n' \
'Error description: ' + str(status["error"]["error_description"]))
api.cardAuthorization(sale, customer, card, new Callback<AuthorizationResult>() {
@Override
public void onFinish(AuthorizationResult result) {
// success
}
@HandleException
public void onProtocolError(ProtocolException e) {
// invoke if not success
// e.getCode() - error code
// e.getMessage() - error message
}
@Override
public void onError(Exception e) {
// connection error etc.
}
});
Płatności cykliczne to po prostu ponowne obciążenia karty (resale) wykonywane w określonych odstępach czasowych. Możesz wykonywać je według schematu określanego przez Twój model biznesowy.
Resale nie wymaga kompletu informacji o karcie i kliencie. Dlatego właśnie potrzebna jest najpierw przynajmniej jedna płatność lub autoryzacja karty.
Oznacza to, że możemy wyróżnić dwa rodzaje płatności cyklicznych:
Zacznij od przygotowania informacji potrzebnych do zrealizowania ponownego obciążenia karty. W tym celu musisz najpierw pozyskać numer ID wcześniejszej transakcji, który jednoznacznie określa daną płatność w systemie PeP Online. Możesz łatwo odczytać ten numer podczas przeprowadzania transakcji. Wprawdzie możesz odwołać się do dowolnej wcześniejszej transakcji dokonanej daną kartą, to jednak zalecamy odnoszenie się do ostatniej dokonanej płatności. Takie podejście ma wiele zalet, pozwala m.in. na łatwe śledzenie przepływu płatności. Zazwyczaj sprzedawcy przechowują takie numery ID w swoich bazach danych. W ten sposób nie muszą przechowywać żadnych wrażliwych danych, a jednocześnie mają możliwość bezpośredniego odwołania się do wybranej transakcji. Gdy posiadasz już numer ID (np. pobrany z bazy danych), możesz przygotować dane potrzebne do obciążenia karty i wywołać metodę resaleBySale. Możesz sprawdzić czy płatność została wykonana prawidłowo wywołując metodę isSuccess. Pozyskanie numeru ID transakcji (lub danych o błędzie, jeśli operacja się nie powiodła) jest również bardzo proste. Płatności cykliczne są po prostu ponownymi obciążeniami karty. Od Ciebie zależy, czy będą to odstępy tygodniowe, miesięczne, roczne czy inne; podobnie możesz obciążyć kartę np. dopiero, gdy klient osiągnie określoną kwotę do spłaty.
$status = $client->cardSale($card_params);
$id_first_sale = $status['id_sale'];
status = client.card_sale(card_params)
id_first_sale = status['id_sale']
status = client.card_sale(card_params)
id_first_sale = status['id_sale']
api.cardSale(sale, customer, card, new Callback<CardSaleResult>() {
@Override
public void onFinish(CardSaleResult result) {
long idFirstSale = result.getIdSale();
}
});
$resale_params = array(
'id_sale' => $id_first_sale,
'amount' => 99.99,
'currency' => 'EUR',
'description' => 'Recurring billing product #1',
);
// perform the resale:
try {
$status = $client->resaleBySale($resale_params);
} catch (Exception $e) {
// handle exceptions here
}
// checking transaction status example (optional):
if ($client->isSuccess()) {
echo "Success, second id_sale: {$status['id_sale']} \n";
} else {
die("Error ID: {$status['error']['id_error']}, \n".
"Error number: {$status['error']['error_number']}, \n".
"Error description: {$status['error']['error_description']}");
}
resale_params = {
'id_sale' => id_first_sale,
'amount' => 99.99,
'currency' => 'EUR',
'description' => 'Recurring billing product #1'
}
# perform the resale:
begin
status = client.resale_by_sale(resale_params)
rescue PeP::ClientError => e
# handle exceptions here
end
# checking transaction status example (optional):
if client.success?
puts "Success, id_second_sale: #{status["id_sale"]}"
else
puts "Error ID: #{status["error"]["id_error"]}, \n"\
"Error number: #{status["error"]["error_number"]}, \n"\
"Error description: #{status["error"]["error_description"]}"
exit
end
resale_params = {
'id_sale' : id_first_sale,
'amount' : 99.99,
'currency' : 'EUR',
'description' : 'Recurring billing product #1'
}
# perform the resale:
try:
status = client.resale_by_sale(resale_params)
except Exception, e:
# handle exceptions here
# checking transaction status example (optional):
if client.is_success():
print 'Success, second id_sale: %s' % status['id_sale']
else:
sys.exit('Error ID: ' + str(status["error"]["id_error"]) + '\n' \
'Error number: ' + str(status["error"]["error_number"]) + '\n' \
'Error description: ' + str(status["error"]["error_description"]))
api.resaleSale(
idFirstSale,
99.99,
"EUR",
"Recurring billing product #1",
new Callback<FraudSaleResult>() {
@Override
public void onFinish(FraudSaleResult result) {
// success
}
@HandleException
public void onProtocolError(ProtocolException e) {
// invoke if not success
// e.getCode() - error code
// e.getMessage() - error message
}
@Override
public void onError(Exception e) {
// connection error etc.
}
}
);
Jeśli klient nie dokonał jeszcze żadnego zakupu (a więc nie było ani jednej płatności), nadal możesz rozpocząć płatności cykliczne. Klient musi tylko podać potrzebne dane karty.
Możesz zebrać wymagane informacje w różnych sytuacjach, np.:
Wróćmy do płatności cyklicznych. Zakładając, że dysponujesz już numerem ID autoryzacji karty klienta, możesz przygotować dane potrzebne do pobrania środków, czyli wykonania resale’a (a więc wywołania metody resaleByAuthorization).
Podobnie jak w przypadku płatności bazujących na wcześniejszych transakcjach, tak i tu możesz sprawdzić, czy płatność cykliczna się powiodła, wywołując metodę isSuccess. Możesz także odczytać numer ID transakcji lub dane o błędzie, w razie niepowodzenia operacji.
$id_authorization = $status['id_authorization'];
id_authorization = status["id_authorization"]
id_authorization = status['id_authorization']
AuthorizationResult result =...;
long idAuthorization = result.getIdAuthorization();
$resale_params = array(
'id_authorization' => $id_authorization,
'amount' => 99.99,
'currency' => 'EUR',
'description' => 'Recurring billing product #1',
);
// perform the resale:
try {
$status = $client->resaleByAuthorization($resale_params);
} catch (Exception $e) {
// handle exceptions here
}
// checking transaction status example (optional):
if ($client->isSuccess()) {
echo "Success, second id_sale: {$status['id_sale']} \n";
} else {
die("Error ID: {$status['error']['id_error']}, \n".
"Error number: {$status['error']['error_number']}, \n".
"Error description: {$status['error']['error_description']}");
}
resale_params = {
'id_authorization' => id_authorization,
'amount' => 99.99,
'currency' => 'EUR',
'description' => 'Recurring billing product #1'
}
# perform the resale:
begin
status = client.resale_by_authorization(resale_params)
rescue PeP::ClientError => e
# handle exceptions here
end
# checking transaction status example (optional):
if client.success?
puts "Success, id_second_sale: #{status["id_sale"]}"
else
puts "Error ID: #{status["error"]["id_error"]}, \n"\
"Error number: #{status["error"]["error_number"]}, \n"\
"Error description: #{status["error"]["error_description"]}"
exit
end
resale_params = {
'id_authorization' : id_authorization,
'amount' : 99.99,
'currency' : 'EUR',
'description' : 'Recurring billing product #1'
}
# perform the resale:
try:
status = client.resale_by_authorization(resale_params)
except Exception, e:
# handle exceptions here
# checking transaction status example (optional):
if client.is_success():
print 'Success, second id_sale: %s' % status['id_sale']
else:
sys.exit('Error ID: ' + str(status["error"]["id_error"]) + '\n' \
'Error number: ' + str(status["error"]["error_number"]) + '\n' \
'Error description: ' + str(status["error"]["error_description"]))
api.resaleAuthorization(idAuthorization, 99.99, "EUR", "Recurring billing product #1", new Callback<FraudSaleResult>() {
@Override
public void onFinish(FraudSaleResult result) {
// success
}
@HandleException
public void onProtocolError(ProtocolException e) {
// invoke if not success
// e.getCode() - error code
// e.getMessage() - error message
}
@Override
public void onError(Exception e) {
// connection error etc.
}
});
Zdarza się, że chcesz zwrócić klientowi pieniądze (np. oddał lub reklamował towar) – całą kwotę lub tylko jej część. Do tego właśnie służy refund, czyli zwrot środków; pozwala na oddanie określonej kwoty w powiązaniu z konkretną transakcją. Aby przeprowadzić refund, musisz znać numer ID transakcji, który jednoznacznie identyfikuje daną płatność w systemach PeP Online. Możesz łatwo pozyskać ten numer podczas dokonywania transakcji. Zazwyczaj sprzedawcy zapisują takie numery ID transakcji w swoich bazach danych. Dzięki temu nie muszą sami przechowywać wrażliwych danych i wciąż są w stanie odnieść się do konkretnej płatności. Przygotuj dane potrzebne do wykonania refunda. Zauważ, że możesz podać kwotę transakcji lub mniejszą; jeśli podasz kwotę większą niż kwota transakcji, system zwróci błąd. Możesz również określić walutę oraz powód zwrotu środków. Podobnie jak w przypadku każdej innej transakcji, tak i tu możesz sprawdzić czy refund został wykonany prawidłowo wywołując metodę isSuccess. Pozyskanie numeru ID refundu (lub danych o błędzie, jeśli operacja się nie powiodła) jest również bardzo proste i może wyglądać jak na poniższym przykładzie.
$status = $client->cardSale($card_params);
$id_sale = $status['id_sale'];
status = client.card_sale(card_params)
id_sale = status['id_sale']
status = client.card_sale(card_params)
id_sale = status['id_sale']
api.cardSale(sale, customer, card, new Callback<CardSaleResult>() {
@Override
public void onFinish(CardSaleResult result) {
long idFirstSale = result.getIdSale();
}
});
$refund_params = array(
'id_sale' => $id_sale,
'amount' => 9.99,
'reason' => 'Partial refund',
);
// perform the refund:
try {
$status = $client->refund($refund_params);
} catch (Exception $e) {
// handle exceptions here
}
// checking refund status example (optional):
if ($client->isSuccess()) {
echo "Success, id_refund: {$status['id_refund']} \n";
} else {
die("Error ID: {$status['error']['id_error']}, \n".
"Error number: {$status['error']['error_number']}, \n".
"Error description: {$status['error']['error_description']}");
}
refund_params = {
'id_sale' => id_sale,
'amount' => 9.99,
'reason' => 'Partial refund.'
}
# perform the refund:
begin
status = client.refund(refund_params)
rescue PeP::ClientError => e
# handle exceptions here
end
# checking refund status example (optional):
if client.success?
puts "Success, id_refund: #{status["id_refund"]}"
else
puts "Error ID: #{status["error"]["id_error"]}, \n"\
"Error number: #{status["error"]["error_number"]}, \n"\
"Error description: #{status["error"]["error_description"]}"
exit
end
refund_params = {
'id_sale' : id_sale,
'amount' : 9.99,
'reason' : 'Partial refund'
}
# perform the refund:
try:
status = client.refund(refund_params)
except Exception, e:
# handle exceptions here
# checking refund status example (optional):
if client.is_success():
print 'Success, id_refund: %s' % status['id_refund']
else:
sys.exit('Error ID: ' + str(status["error"]["id_error"]) + '\n' \
'Error number: ' + str(status["error"]["error_number"]) + '\n' \
'Error description: ' + str(status["error"]["error_description"]))
api.refund(idSale, 9.99, "EUR", "Partial refund", new Callback<FraudSaleResult>() {
@Override
public void onFinish(FraudSaleResult result) {
// success
}
@HandleException
public void onProtocolError(ProtocolException e) {
// invoke if not success
// e.getCode() - error code
// e.getMessage() - error message
}
@Override
public void onError(Exception e) {
// connection error etc.
}
});
Płatności single-click pozwalają na zakup jednym kliknięciem – klient nie musi podawać żadnych informacji. Usługa wykorzystuje mechanizm resale (podobnie jak płatności cykliczne) pozwalający na pobranie środków z karty.
Możesz dokonywać takich transakcji wykorzystując informacje, które klient podał przy innej okazji, np.:
Po przeprowadzeniu pierwszej transakcji, możesz łatwo przeprowadzić kolejne wykorzystując informacje podane przy pierwszej płatności. Oznacza to, że nie musisz wymagać podania informacji o karcie i kliencie za każdym razem, co stanowi duże udogodnienie dla Ciebie oraz kupujących.
Jeśli powracający klient zainicjuje transakcję (np. klikając przycisk “Kup” na stronie produktu), możesz wykorzystać informacje z jego wcześniejszej płatności.
Pozyskaj numer ID poprzedniej transakcji. Jeśli przeprowadziłeś ją bezpośrednio przed ponownym pobraniem środków (resale), możesz otrzymać numer ID z informacji zwracanych przez metodę cardSale.
Sprawdzenie statusu transakcji, pobranie numeru ID czy sprawdzenie informacji o ewentualnym błędzie odbywa się w taki sam sposób, jak przy zwykłej płatności.
$resale_params = array(
'id_sale' => $id_first_sale,
'amount' => 99.99,
'currency' => 'EUR',
'description' => 'Recurring billing product #1',
);
// perform the resale:
try {
$status = $client->resaleBySale($resale_params);
} catch (Exception $e) {
// handle exceptions here
}
// checking transaction status example (optional):
if ($client->isSuccess()) {
echo "Success, second id_sale: {$status['id_sale']} \n";
} else {
die("Error ID: {$status['error']['id_error']}, \n".
"Error number: {$status['error']['error_number']}, \n".
"Error description: {$status['error']['error_description']}");
}
resale_params = {
'id_sale' => id_first_sale,
'amount' => 99.99,
'currency' => 'EUR',
'description' => 'Recurring billing product #1'
}
# perform the resale:
begin
status = client.resale_by_sale(resale_params)
rescue PeP::ClientError => e
# handle exceptions here
end
# checking transaction status example (optional):
if client.success?
puts "Success, id_second_sale: #{status["id_sale"]}"
else
puts "Error ID: #{status["error"]["id_error"]}, \n"\
"Error number: #{status["error"]["error_number"]}, \n"\
"Error description: #{status["error"]["error_description"]}"
exit
end
resale_params = {
'id_sale' : id_first_sale,
'amount' : 99.99,
'currency' : 'EUR',
'description' : 'Recurring billing product #1'
}
# perform the resale:
try:
status = client.resale_by_sale(resale_params)
except Exception, e:
# handle exceptions here
# checking transaction status example (optional):
if client.is_success():
print 'Success, second id_sale: %s' % status['id_sale']
else:
sys.exit('Error ID: ' + str(status["error"]["id_error"]) + '\n' \
'Error number: ' + str(status["error"]["error_number"]) + '\n' \
'Error description: ' + str(status["error"]["error_description"]))
api.resaleSale(
idFirstSale,
99.99,
"EUR",
"Recurring billing product #1",
new Callback<FraudSaleResult>() {
@Override
public void onFinish(FraudSaleResult result) {
// success
}
@HandleException
public void onProtocolError(ProtocolException e) {
// invoke if not success
// e.getCode() - error code
// e.getMessage() - error message
}
@Override
public void onError(Exception e) {
// connection error etc.
}
}
);
Nie musisz wymagać wcześniej zrealizowanej płatności, by udostępnić klientowi usługę single-click. Wystarczy, jesli klient poda informacje potrzebne do jej zrealizowania. Może zrobić to np. podczas zakładania konta w Twoim e-sklepie lub zapisując się do Twojej usługi.
Gdy pozyskasz takie informacje, musisz tylko autoryzować kartę i zapisać otrzymany numer ID.
Dzięki numerowi ID autoryzacji możesz dokonywać dalszych obciążeń karty. Najczęściej sprzedawcy zapisują taki numer w swojej bazie danych – dzięki temu są w stanie używać go w przyszłości do powtórnych obciążeń, a jednocześnie nie muszą operować wrażliwymi danymi.
Teraz przygotuj informacje potrzebne do obciążenia karty (wykonania resale’a). Potrzebujesz jedynie numeru ID autoryzacji oraz informacje opisujące transakcję.
Sprawdzenie statusu transakcji, pobranie numeru ID czy sprawdzenie informacji o ewentualnym błędzie odbywa się w taki sam sposób, jak przy zwykłej płatności.
$id_authorization = $status['id_authorization'];
id_authorization = status["id_authorization"]
id_authorization = status['id_authorization']
AuthorizationResult result =...;
long idAuthorization = result.getIdAuthorization();
$resale_params = array(
'id_authorization' => $id_authorization,
'amount' => 99.99,
'currency' => 'EUR',
'description' => 'Recurring billing product #1',
);
// perform the resale:
try {
$status = $client->resaleByAuthorization($resale_params);
} catch (Exception $e) {
// handle exceptions here
}
// checking transaction status example (optional):
if ($client->isSuccess()) {
echo "Success, second id_sale: {$status['id_sale']} \n";
} else {
die("Error ID: {$status['error']['id_error']}, \n".
"Error number: {$status['error']['error_number']}, \n".
"Error description: {$status['error']['error_description']}");
}
resale_params = {
'id_authorization' => id_authorization,
'amount' => 99.99,
'currency' => 'EUR',
'description' => 'Recurring billing product #1'
}
# perform the resale:
begin
status = client.resale_by_authorization(resale_params)
rescue PeP::ClientError => e
# handle exceptions here
end
# checking transaction status example (optional):
if client.success?
puts "Success, id_second_sale: #{status["id_sale"]}"
else
puts "Error ID: #{status["error"]["id_error"]}, \n"\
"Error number: #{status["error"]["error_number"]}, \n"\
"Error description: #{status["error"]["error_description"]}"
exit
end
resale_params = {
'id_authorization' : id_authorization,
'amount' : 99.99,
'currency' : 'EUR',
'description' : 'Recurring billing product #1'
}
# perform the resale:
try:
status = client.resale_by_authorization(resale_params)
except Exception, e:
# handle exceptions here
# checking transaction status example (optional):
if client.is_success():
print 'Success, second id_sale: %s' % status['id_sale']
else:
sys.exit('Error ID: ' + str(status["error"]["id_error"]) + '\n' \
'Error number: ' + str(status["error"]["error_number"]) + '\n' \
'Error description: ' + str(status["error"]["error_description"]))
api.resaleAuthorization(idAuthorization, 99.99, "EUR", "Recurring billing product #1", new Callback<FraudSaleResult>() {
@Override
public void onFinish(FraudSaleResult result) {
// success
}
@HandleException
public void onProtocolError(ProtocolException e) {
// invoke if not success
// e.getCode() - error code
// e.getMessage() - error message
}
@Override
public void onError(Exception e) {
// connection error etc.
}
});
Zrealizowanie transakcji 3-D Secure odbywa się w kilku krokach i wymaga wykonania kilku dodatkowych czynności w porównaniu z normalną (niezabezpieczoną mechanizmem 3-D Secure) transakcją płatniczą.
Przygotuj dane potrzebne do przeprowadzenia płatności jak w przykładzie.
$card_params = array(
'sale' => array(
'amount' => 100.00,
'currency' => 'EUR',
'description' => 'Product #1'
),
'customer' => array(
'name' => 'John Doe',
'email' => 'john@doe.com',
'ip' => '127.0.0.1',
'address' => array (
'street_house' => '1600 Pennsylvania Avenue Northwest',
'city' => 'Washington',
'state' => 'DC',
'zip' => '500',
'country_code' => 'US',
),
),
'card' => array(
'token' => '12a34b45c67d89e00f1aa2bb3cc4dd5ee6ff12a34b45c67d89e00f1aa2bb3cc4'
),
'back_url' => 'http://example.com/3dsecure', // 3d secure back redirect url
);
card_params = {
'sale' => {
'amount' => 19.99,
'currency' => 'EUR',
'description' => 'Product #1',
},
'customer' => {
'name' => 'John Doe',
'email' => 'john@doe.com',
'ip' => '127.0.0.1',
'address' => {
'street_house' => '1600 Pennsylvania Avenue Northwest',
'city' => 'Washington',
'state' => 'DC',
'zip' => '500',
'country_code' => 'US'
}
},
'card' => {
'token' => '12a34b45c67d89e00f1aa2bb3cc4dd5ee6ff12a34b45c67d89e00f1aa2bb3cc4'
},
'back_url' => 'http://example-url.com'
}
card_params = {
'sale' : {
'amount' : 19.99,
'currency' : 'EUR',
'description' : 'Product #1'
},
'customer' : {
'name' : 'John Doe',
'email' : 'john@doe.com',
'ip' : '127.0.0.1',
'address' : {
'street_house' : '1600 Pennsylvania Avenue Northwest',
'city' : 'Washington',
'state' : 'DC',
'zip' : '500',
'country_code' : 'US'
}
},
'card' : {
'token' : '12a34b45c67d89e00f1aa2bb3cc4dd5ee6ff12a34b45c67d89e00f1aa2bb3cc4'
},
'back_url' : 'http://example.com/3dsecure'
}
Sale sale = new Sale(19.99, "EUR", "Product #1");
Address address = new Address("1600 Pennsylvania Avenue Northwest", "Washington", "DC", "500", "US");
Customer customer = new Customer("John Doe", "john@doe.com", "127.0.0.1", address);
Card card = new Card("4111111111111111", "03", "2017", "John Doe", "123")
Aby sprawdzić, czy karta jest zapisana do programu 3-D Secure, po prostu wywołaj metodę checkCard3DSecureByToken. Jeśli karta jest zapisana do programu 3-D Secure, otrzymasz numer autoryzacji id_3dsecure_auth.
Jeśli autoryzacja 3-D Secure się powiodła (karta jest zapisana do programu 3-D Secure), możesz przeprowadzić transakcję z użyciem tego mechanizmu i przekierować klienta na stronę dostawcy usługi 3-D Secure (używając adresu otrzymanego w wartości redirect_url).
Jeśli karta nie jest zapisana do programu 3-D przejdź do kroku 3a.
try {
$status = $client->checkCard3DSecureByToken($card_params);
}
catch (Exception $e) {
// Handle exception here, for example show an error page, stop action
}
if ($client->isSuccess()) {
echo "Success, id_3dsecure_auth: {$status['id_3dsecure_auth']} \n";
} else {
echo "Error ID: {$status['error']['id_error']}, \n".
"Error number: {$status['error']['error_number']}, \n".
"Error description: {$status['error']['error_description']}";
}
if (true == $status['is_card_enrolled'])
{
// redirect to 3-D Secure provider
header('Location: ' . $status['redirect_url']);
die;
}
begin
status = client.check_card_3d_secure_by_token(card_params)
rescue PeP::ClientError => e
# handle exceptions here
end
if client.success?
puts "Success, id_3dsecure_auth: #{status["id_3dsecure_auth"]}"
else
puts "Error ID: #{status["error"]["id_error"]}, \n"\
"Error number: #{status["error"]["error_number"]}, \n"\
"Error description: #{status["error"]["error_description"]}"
end
if status['is_card_enrolled']
# redirect to url in status['redirect_url']
exit
end
try:
status = client.check_card_3d_secure_by_token(card_params)
except Exception, e:
# handle exceptions here
if client.is_success():
print 'Success, id_3dsecure_auth: %s' % status['id_3dsecure_auth']
else:
print 'Error (%s), %s - %s' % (status['error'].get('id_error'),
status['error'].get('error_number'),
status['error'].get('error_description'))
if status['is_card_enrolled']:
# redirect to url in status['redirect_url']
sys.exit()
api.secure3DCheckCard(sale, customer, card, "http:// example.com/3dsecure", new Callback<Secure3DSaleResult>() {
@Override
public void onFinish(Secure3DSaleResult result) {
if (result.isEnrolled()) {
WebView webview =...;
webview.loadUrl(result.getRedirectUrl());
}
}
@HandleException
public void onProtocolError(ProtocolException e) {
// invoke if not success
// e.getCode() - error code
// e.getMessage() - error message
}
@Override
public void onError(Exception e) {
// connection error etc.
}
});
Po wprowadzeniu stosownych danych, klient zostanie przekierowany z powrotem na Twoją stronę(back_url). Powinieneś teraz sprawdzić zwrócone informacje, aby uniknąć ewentualnych prób oszustwa i sprawdzić status transakcji.
Jeśli wszystko odbyło się poprawnie, to po tej weryfikacji możesz już przeprowadzić faktyczną płatność opartą na autoryzacji 3-D Secure.
Dla pojedynczej płatności wywołaj metodę 3DSecure/authSale a dla autoryzacji 3DSecure/auth.
Możesz sprawdzić, czy płatność się powiodła, wywołując metodę isSuccess. Pozyskanie numeru ID transakcji (lub informacji o błędzie, jeśli coś pójdzie nie tak), jest również bardzo proste i może wyglądać jak w przykładzie.
$salt = 'YOUR_HASH_SALT';
$status = $_GET['status'];
$description = $_GET['description'];
$amount = $_GET['amount'];
$currency = $_GET['currency'];
$hash = $_GET['hash'];
$id = '';
if ($status !== 'ERROR') // success, get id_3dsecure_auth
$id = $_GET['id_3dsecure_auth'];
$calc_hash = sha1("{$salt}|{$status}|{$description}|{$amount}|{$currency}|{$id}");
// check hash salt
if ( $calc_hash !== $hash ) {
die ("Error, wrong hash");
}
// check transaction status
if ($status === 'ERROR') {
die("Error, 3-D auth transaction declined");
} else {
// 3-D Secure authorization completed, perform sale
}
# Simple controller action code in Rails
# it's just an example - most of the logic should be moved to model
salt = 'YOUR_HASH_SALT'
status = params['status']
description = params['description']
amount = params['amount']
currency = params['currency']
hash = params['hash']
id = ''
unless status == 'ERROR'
id = params['id_3dsecure_auth']
else
# redirect to an index action to correct the payment + simple notice
# for Rails: redirect_to :index, :notice => "Error, 3-D auth transaction declined"
end
calc_hash = Digest::SHA1.hexdigest("#{salt}|#{status}|#{description}|#{amount}|#{currency}|#{id}")
unless calc_hash == hash
# redirect to an index action to correct the payment
# for Rails: redirect_to :index, :notice => "Wrong hash"
end
# check transaction status
if status == 'ERROR'
# redirect to an index action to correct the payment + simple notice
# for Rails: redirect_to :index, :notice => "Error, 3-D auth transaction declined"
else
# 3-D Secure authorization completed, perform sale
end
salt = 'YOUR_HASH_SALT'
status = get_request_param('status')
description = get_request_param('description')
amount = get_request_param('amount')
currency = get_request_param('currency')
hash = get_request_param('hash')
id_3dsecure_auth = None
# success, get id_3dsecure_auth
if status != 'ERROR':
id_3dsecure_auth = get_request_param('id_3dsecure_auth')
calc_hash = hashlib.sha1(
'|'.join([salt, status, description, amount, currency, id_3dsecure_auth])).hexdigest()
# check hash salt
if calc_hash != hash:
sys.exit('Error, wrong hash')
# check transaction status
if status == 'ERROR':
sys.exit('Error, 3-D auth transaction declined')
else:
# '3-D Secure authorization completed, perform sale'
webview.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.contains(redirectUrl)) {
try {
Map<String, String> map = getQueryMap(new URL(url).getQuery());
String salt = "YOUR_HASH_SALT";
String status = map.get("status");
String description = map.get("description");
String amount = map.get("amount");
String currency = map.get("currency");
String hash = map.get("hash");
String id = map.get("id_3dsecure_auth");
String calcHash = sha1(String.format("%1$s|%2$s|%3$s|%4$s|%5$s|%6$s", salt, status, description, amount, currency, id));
// check hash salt
if (!calcHash.equals(hash)) {
// Error, wrong hash
}
if (status.equals("ERROR")) {
String errorDescription=map.get("error_description");
// Error, transaction declined
} else {
String idSale=map.get("id_sale");
// Success, transaction completed
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
} else {
view.loadUrl(url);
}
return true;
}
});
public static Map<String, String> getQueryMap(String query) {
String[] params = query.split("&");
Map<String, String> map = new HashMap<String, String>();
for (String param : params) {
String name = param.split("=")[0];
String value = param.split("=")[1];
map.put(name, value);
}
return map;
}
private static String convertToHex(byte[] data) {
StringBuilder buf = new StringBuilder();
for (byte b : data) {
int halfbyte = (b >>> 4) & 0x0F;
int two_halfs = 0;
do {
buf.append((0 <= halfbyte) && (halfbyte <= 9) ? (char) ('0' + halfbyte) : (char) ('a' + (halfbyte - 10)));
halfbyte = b & 0x0F;
} while (two_halfs++ < 1);
}
return buf.toString();
}
public static String sha1(String text) throws NoSuchAlgorithmException, UnsupportedEncodingException {
MessageDigest md = MessageDigest.getInstance("SHA-1");
md.update(text.getBytes("utf-8"), 0, text.length());
byte[] sha1hash = md.digest();
return convertToHex(sha1hash);
}
try {
$status = $client->saleBy3DSecureAuthorization(array ('id_3dsecure_auth' => $id));
} catch (Exception $e) {
// Handle exception here, for example show an error page, stop action
}
if ($client->isSuccess())
{
echo "Success, id_sale: {$status['id_sale']} \n";
} else {
echo "Error ID: {$status['error']['id_error']}, \n".
"Error number: {$status['error']['error_number']}, \n".
"Error description: {$status['error']['error_description']}");
}
begin
status = client.sale_by_3d_secure_authorization({"id_3dsecure_auth" => id})
rescue PeP::ClientError => e
# handle exceptions here
end
if client.success?
puts "Success, id_sale: #{status["id_sale"]}"
else
puts "Error ID: #{status["error"]["id_error"]}, \n"\
"Error number: #{status["error"]["error_number"]}, \n"\
"Error description: #{status["error"]["error_description"]}"
end
try:
status = client.sale_by_3d_secure_authorization(
{'id_3dsecure_auth': id_3dsecure_auth})
except Exception, e:
# handle exceptions here
if client.is_success():
print 'Success, id_sale: %s' % status['id_sale']
else:
print 'Error (%s), %s - %s' % (status['error'].get('id_error'),
status['error'].get('error_number'),
status['error'].get('error_description'))
Secure3DSaleResult result =...;
long id3dSecureAuth = result.getId3dSecureAuth();
api.secure3DAuthSale(id3dSecureAuth, new Callback<CardSaleResult>() {
@Override
public void onFinish(CardSaleResult result) {
// success
}
});
Sytuacja opisana powyżej jest przypadkiem idealnym. Może się jednak okazać, że karta nie jest zapisana do programu 3-D Secure i wynik autoryzacji 3-D Secure będzie negatywny. Oto jak należy postąpić w takim przypadku.
Po wywołaniu metody mającej zrealizować autoryzację 3-D Secure, po prostu wywołaj metodę saleBy3DSecureAuthorization zupełnie tak, jakbyś zrobił w przypadku, gdyby wynik autoryzacji był pozytywny. To ważne (ze względów bezpieczeństwa), by posłużyć się ta metodą, a nie przeprowadzać w tym momencie zwykłej transakcji kartą – dzięki temu próba przeprowadzenia płatności z użyciem 3-D Secure zostanie zarejestrowana.
Możesz sprawdzić, czy płatność się powiodła, wywołując metodę isSuccess. Pozyskanie numeru ID transakcji (lub informacji o błędzie, jeśli coś pójdzie nie tak), jest również bardzo proste i może wyglądać jak w przykładzie.
$id_3dsecure_auth = $status['id_3dsecure_auth'];
if (true != $status['is_card_enrolled'])
{
try {
$status = $client->saleBy3DSecureAuthorization(array ('id_3dsecure_auth' => $id_3dsecure_auth));
} catch (Exception $e) {
// Handle exception here, for example show an error page, stop action
}
}
if ($client->isSuccess()) {
echo "Success, id_sale: {$status['id_sale']} \n";
} else {
echo "Error ID: {$status['error']['id_error']}, \n".
"Error number: {$status['error']['error_number']}, \n".
"Error description: {$status['error']['error_description']}");
}
id_3dsecure_auth = status['id_3dsecure_auth']
unless status['is_card_enrolled']
begin
status = client.sale_by_3d_secure_authorization({"id_3dsecure_auth" => id_3dsecure_auth})
rescue PeP::ClientError => e
# Handle exception here, for example show an error page, stop action
end
end
if client.success?
puts "Success, id_sale: #{status["id_sale"]}"
else
puts "Error ID: #{status["error"]["id_error"]}, \n"\
"Error number: #{status["error"]["error_number"]}, \n"\
"Error description: #{status["error"]["error_description"]}"
end
if not is_card_enrolled:
try:
status = client.sale_by_3d_secure_authorization(
{'id_3dsecure_auth': id_3dsecure_auth})
except Exception, e:
# Handle exception here, for example show an error page, stop action
if client.is_success():
print 'Success, id_sale: %s' % status['id_sale']
else:
print 'Error (%s), %s - %s' % (status['error'].get('id_error'),
status['error'].get('error_number'),
status['error'].get('error_description'))
Secure3DSaleResult result =...;
if (!result.isEnrolled()) {
api.secure3DAuthSale(result.getId3dSecureAuth(), new Callback<CardSaleResult>() {
@Override
public void onFinish(CardSaleResult result) {
// success
}
});
}
Google Pay™ jest nowoczesną wygodną metodą płatności. Klienci mogą jedny kliknięciem szybko opłacić zakupy zarówno z urządzenia mobilnego jak i przez przeglądarkę. Google Pay™ jest dobrym wyborem dla każdego modelu biznesowego.
Pobieramy niezbędne biblioteki:
"https://pay.google.com/gp/p/js/pay.js"
"https://js.pep.pl/v1"
Inicjujemy klienta PeP.js:
// set up PeP JS client
PeP.setPublicApiKey('MY_PUBLIC_API_KEY');
// set up Google Pay with production Account
PeP.googlePay.init({
environment: 'PRODUCTION',
googleMerchantId: 'ID UZYSKAZANE PO ZAŁOŻENIU KONTA PRODUKCYJNEGO W GOOGLE'
});
// prepare basic transaction data
const TRANSACTION = {
currencyCode: "USD",
totalPrice: "1.00"
};
// check whether Google pay is available
PeP.googlePay
.isReadyToPay()
.then(function(response) {
if (response.result) {
// proceed
showGooglePayBtn();
} else {
console.warn("Google Pay is not available");
}
})
.catch(function(err) {
// handle errors here
console.error(err);
});
const showGooglePayBtn = function() {
// create Google Pay button
const button = PeP.googlePay.createButton({
onClick: onGooglePaymentButtonClicked
});
// append button
document.getElementById('container').appendChild(button);
};
const onGooglePaymentButtonClicked = function() {
PeP.googlePay
.loadPayment(TRANSACTION)
.then(function(paymentData) {
// extract and encode payment token
const token = btoa(paymentData.paymentMethodData.tokenizationData.token);
// pass required transaction data along with the `token` to your backend
// application and perform transaction
})
.catch(function(err) {
// handle errors here
console.error(err);
});
};
Teraz wykonujemy zapytanie używając uzyskany token.
Do Requestów używamy naszych danych autoryzacyjnych:
include_once ('PePRestClient.php');
$client = new PePRestClient('your_API_login', 'your_API_password');
Jeżeli w odpowiedzi otrzymamy REDIRECT URL przekierowujemy na ten URL płatnika, jeśli nie - od razu przechodzimy do ostatniego kroku. W obu wypadkach przechodzimy do ostatniego kroku używając otrzymany "id_3dsecure_auth"
{
"sale": {
"amount": 1.00,
"currency": "USD",
"description": "TR001"
},
"customer": {
"name": "John Doe",
"email": "john.doe@example.com",
"country_code": "US",
"ip": "127.0.0.1"
},
"card": {
"token": "eyJzaWduYXR1cmUiOiJNRVlDSVFDcUE1T0Vpd1ptR29GNlVqUEI3MktBNWtOa2lyUE5WMGN0T1A4Uytwam1qd0loQUo1QjVXa3Vnd1JhNWk3enRUWjE4eHBEWjJXK0hNTjh3a0M2SFFCZ3ZyUWkiLCJwcm90b2NvbFZlcnNpb24iOiJFQ3YxIiwic2lnbmVkTWVzc2FnZSI6IntcImVuY3J5cHRlZE1lc3NhZ2VcIjpcIlJnSGV1UVA4OVFpa1FDZmtLemRia1g3dU4wUE8zSmFDcE5hRHRhQ1ZkQ0ErZFkvL0VyRzZvQ1NZZ3Yyc3dONkdaRmZwd09zL1ZiVTNjcVFLRC81YXRNQVV5STNidnZpOGRxcXlOb0J4aTVkUi9tbS9OZmRJdHpSdEE3YXovSndMTEpreGNOMzRLZHNQV3VhVHhRZ2MyWFBCUkN2TVpLeUQ1VWNuY1U4cktKSEhnSWlNZEMwUnhNU0Uxc1RVWEwxVDk0eURJck9jdlNlcmRYdnpLZGhUOUQxcUl0azA2VW5uc2dhRHFWdGg0SHMyY1hTUFVJYlNIc25ydlRsZGg2dGlkOTF2WWZRYldYeElqQUF1ZFRQME8xR25oTnJjYXo5WjBxeUVWUEVQQnVzc29kWU1pL1JQa3VNREh6TU1sUUV2Mms3SXBtdDZJZGVnd0t5L21VYlFNeld1NDdzc2Jmb2xWbW1vOGRrTlJhYmo5Z0dtQWwrL1ErelY1MUNPeG5CSWhBUHU2NUMwZ3RuTi8yZWJMNnZNdWQxbE5xRXV0WVd4alpGRWY4Q2ZkZ3lQM3M5WXdYWXdoenRTTi9ycGhCV1hpWmNOT29Ea2xxWWEvSVphT2o0TnVnNVdLU3hka2pVazhmSTJiNlV2ZEIwbHMrakpuenZRdStzUndlWHZoNmRRa2JuazhGS3VKeVdkZGl2c3NJcjlJZW1Jc3JFOUE5T3FlSnpWOVRjSThRb01ZWmNiQUZkcUlBRjhWTUJLSjMwU28yYyt4SnU5b21FUy9QbFVXU1hJdXltL1hXMldhd1xcdTAwM2RcXHUwMDNkXCIsXCJlcGhlbWVyYWxQdWJsaWNLZXlcIjpcIkJGZzZoNWZkQ0RIbWFNODlNN0VKOVdyWHVkZWh3bzFrci8rWmdNZDJiUE5NNmhHVVZRZVp2VHRZSm5ua1dGY2JVODZteXU0WmduM2VyL05pMUNwVFk1RVxcdTAwM2RcIixcInRhZ1wiOlwiY3NzcXNmcnJpSDRwSzlUQmJPRWpSMDc2Slc2YWNKL3JEQ3JHTUpaLzFaa1xcdTAwM2RcIn0ifQ=="
}
"back_url" : "http://example-url.com"
}
{
"success" : true,
"id_3dsecure_auth" : 1234567,
"is_card_enrolled" : true,
"redirect_url" : "https://secure.pep.pl/payment/123"
}
Został nam ostatni krok! Używamy do tego "id_3dsecure_auth" uzyskany w poprzednim kroku Dokładniejszy opis requestu i odpowiedzi, wraz z Endpointami:
Internetowe przelewy bankowe są – obok kart – jedną z popularniejszych metod płatności. W Polsce przelewy pozostają najczęściej wybieraną metodą płatności online i część banków upraszcza proces płatności.
Zanim zaczniesz wywoływać metody naszego API, pamiętaj, aby poprawnie zainicjować PeP Online Rest Client. To bardzo łatwe, po prostu załącz odpowiedni plik oraz podaj swoją nazwę użytkownika i hasło.
include_once ('PePRestClient.php');
$client = new PePRestClient('your_login', 'your_password');
require 'pep_client'
client = PeP::Client.new('your_login', 'your_password')
from client import PePRestClient
client = PePRestClient("your_login", "your_password")
PePApi api = PePClientFactory.createClassicClient(context, "your_login", "your_password");
Zacznij od przygotowania danych do przeprowadzenia przelewu: informacje o transakcji, kliencie, typie płatności. Zdefiniuj także adres (back_url), na który klient zostanie przekierowany po dokonaniu płatności.
$bt_params = array(
'sale' => array(
'amount' => 19.99,
'currency' => 'PLN',
'description' => 'Product #1'
),
'customer' => array(
'name' => 'John Doe',
'email' => 'john@doe.com',
'ip' => '127.0.0.1',
'address' => array (
'street_house' => '1600 Pennsylvania Avenue Northwest',
'city' => 'Washington',
'state' => 'DC',
'zip' => '500',
'country_code' => 'US',
),
),
'payment_type' => 'MT',
'back_url' => 'http://example-page.com',
);
bt_params = {
'sale' => {
'amount' => 19.99,
'currency' => 'PLN',
'description' => 'Product #1'
},
'customer' => {
'name' => 'John Doe',
'email' => 'john@doe.com',
'ip' => '127.0.0.1',
'address' => {
'street_house' => '1600 Pennsylvania Avenue Northwest',
'city' => 'Washington',
'state' => 'DC',
'zip' => '500',
'country_code' => 'US'
},
},
'payment_type' => 'MT',
'back_url' => 'http://example-page.com'
}
bt_params = {
'sale' : {
'amount' : 19.99,
'currency' : 'PLN',
'description' : 'Product #1'
},
'customer' : {
'name' : 'John Doe'
'email' : 'john@doe.com',
'ip' : '127.0.0.1',
'address' : {
'street_house' : '1600 Pennsylvania Avenue Northwest',
'city' : 'Washington',
'state' : 'DC',
'zip' : '500'
'country_code' : 'US'
},
},
'payment_type' : 'MT',
'back_url' : 'http://example.com'
}
Sale sale = new Sale(19.99, "EUR", "Product #1");
Address address = new Address("1600 Pennsylvania Avenue Northwest", "Washington", "DC", "500", "US");
Customer customer = new Customer("John Doe", "john@doe.com", "127.0.0.1", address);
Po prostu wywołaj metodę bankTransferSale. Możesz także sprawdzić, czy płatność się powiodła, pozyskać numer ID transakcji lub informacji o błędzie, jeśli coś pójdzie nie tak.
Jeśli metoda bankTransferSale została wywołana z powodzeniem, możesz przekierować klienta na stronę banku, gdzie dokona płatności. Użyj adresu URL zwróconego przez metodę bankTransferSale.
try {
$status = $client->bankTransferSale($bt_params);
}
catch (Exception $e) {
// handle exceptions here
}
if ($client->isSuccess()) {
echo "Success, transaction initiated, id_sale: {$status['id_sale']}, \n
redirect_url: {$status['redirect_url']} \n";
} else {
die("Error ID: {$status['error']['id_error']}, \n".
"Error number: {$status['error']['error_number']}, \n".
"Error description: {$status['error']['error_description']}");
}
header('Location: ' . $status['redirect_url']);
die;
begin
status = client.bank_transfer_sale(bt_params)
rescue PeP::ClientError => e
# handle exceptions here
end
if client.success?
puts "Success, transaction initiated, id_sale: #{status["id_sale"]}, "\
"redirect_url: #{status["redirect_url"]}"
else
puts "Error ID: #{status["error"]["id_error"]}, \n"\
"Error number: #{status["error"]["error_number"]}, \n"\
"Error description: #{status["error"]["error_description"]}"
exit
end
# redirect to url in status['redirect_url']
exit
try:
status = client.bank_transfer_sale(bt_params)
except Exception, e:
# handle exceptions here
if client.is_success():
print 'Success, transaction initiated, id_sale: %s, redirect_url: %s' % \
(status['id_sale'], status['redirect_url'])
else:
sys.exit('Error ID: ' + str(status["error"]["id_error"]) + '\n' \
'Error number: ' + str(status["error"]["error_number"]) + '\n' \
'Error description: ' + str(status["error"]["error_description"]))
# redirect to url in status['redirect_url']
sys.exit()
api.bankTransferSale(sale, customer, "http://example-page.com", PaymentType.MT, new Callback<PayPalAuthorizationResult>() {
@Override
public void onFinish(PayPalAuthorizationResult result) {
WebView webview =...;
webview.loadUrl(result.getRedirectUrl());
}
@HandleException
public void onProtocolError(ProtocolException e) {
// invoke if not success
// e.getCode() - error code
// e.getMessage() - error message
}
@Override
public void onError(Exception e) {
// connection error etc.
}
});
Po dokonaniu płatności na stronie banku, klient zostanie przekierowany z powrotem na Twoją stronę (na adres back_url). Powinieneś teraz zweryfikować zwrócone dane, aby uniknąć ewentualnych prób oszustwa i sprawdzić status transakcji.
$salt = 'YOUR_HASH_SALT';
$status = $_GET['status'];
$description = $_GET['description'];
$amount = $_GET['amount'];
$currency = $_GET['currency'];
$hash = $_GET['hash'];
$id = '';
if ($status !== 'ERROR') // success, get id_sale
$id = $_GET['id_sale'];
$calc_hash = sha1("{$salt}|{$status}|{$description}|{$amount}|{$currency}|{$id}");
// check hash salt
if ( $calc_hash !== $hash ) {
die ("Error, wrong hash");
}
// check transaction status
switch ($status) {
case 'ERROR':
die("Error, transaction declined, {$_GET['error_text']}");
break;
case 'CLEARED':
echo "Success, transaction completed, id_sale: {$_GET['id_sale']}";
break;
default:
/* transaction pending:
* check status regularly using the saleStatus method
* or wait for notification */
echo "Transaction pending";
break;
}
# Simple controller action code in Rails
# it's just an example - most of the logic should be moved to model
salt = 'YOUR_HASH_SALT'
status = params['status']
description = params['description']
amount = params['amount']
currency = params['currency']
hash = params['hash']
id = ''
unless status == 'ERROR'
id = params['id_sale']
else
# redirect to an index action to correct the payment + simple notice
# for rails: redirect_to :index, :notice => "Error, transaction declined, #{description}"
end
calc_hash = Digest::SHA1.hexdigest("#{salt}|#{status}|#{description}|#{amount}|#{currency}|#{id}")
unless calc_hash == hash
# redirect to an index action to correct the payment
# for rails: redirect_to :index
end
# check transaction status
case status
when 'ERROR'
# redirect to an index action to correct the payment + simple notice
# for rails: redirect_to :index, :notice => "Error, transaction declined, #{response["error"]["error_text"]}"
when 'CLEARED'
# redirect to an index action to correct the payment + simple notice
# for rails: redirect_to :index, :notice => "Success, transaction completed, id_sale: #{id}"
else
# redirect to an index action to correct the payment + simple notice
# for rails: redirect_to :index, :notice => "Transaction pending"
end
salt = 'YOUR_HASH_SALT'
status = get_request_param('status')
description = get_request_param('description')
amount = get_request_param('amount')
currency = get_request_param('currency')
hash = get_request_param('hash')
id_sale = None
# success, get id_sale
if status != 'ERROR':
id_sale = get_request_param('id_sale')
calc_hash = hashlib.sha1(
'|'.join([salt, status, description, amount, currency, id_sale])).hexdigest()
# check hash salt
if calc_hash != hash:
sys.exit('Error, wrong hash')
# check transaction status
if status == 'ERROR':
sys.exit('Error, transaction declined, %s' % \
get_request_param('error_text'))
elif status == 'CLEARED':
print 'Success, transaction completed, id_sale: %s' % id_sale
else:
# transaction pending: check status regularly using the saleStatus
# method or wait for notification
print 'Transaction pending'
webview.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.contains(redirectUrl)) {
try {
Map<String, String> map = getQueryMap(new URL(url).getQuery());
String salt = "YOUR_HASH_SALT";
String status = map.get("status");
String description = map.get("description");
String amount = map.get("amount");
String currency = map.get("currency");
String id = map.get("id_sale");
String calcHash = sha1(String.format("%1$s|%2$s|%3$s|%4$s|%5$s|%6$s", salt, status, description, amount, currency, id));
// check hash salt
if (!calcHash.equals(hash)) {
// Error, wrong hash
}
if (status.equals("ERROR")) {
String errorDescription=map.get("error_text");
// Error, transaction declined
} else if (status.equals("CLEARED")) {
String idSale=map.get("id_sale");
// Success, transaction completed
} else {
/* transaction pending:
* check status regularly using the saleStatus method
* or wait for notification */
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
} else {
view.loadUrl(url);
}
return true;
}
});
public static Map<String, String> getQueryMap(String query) {
String[] params = query.split("&");
Map<String, String> map = new HashMap<String, String>();
for (String param : params) {
String name = param.split("=")[0];
String value = param.split("=")[1];
map.put(name, value);
}
return map;
}
private static String convertToHex(byte[] data) {
StringBuilder buf = new StringBuilder();
for (byte b : data) {
int halfbyte = (b >>> 4) & 0x0F;
int two_halfs = 0;
do {
buf.append((0 <= halfbyte) && (halfbyte <= 9) ? (char) ('0' + halfbyte) : (char) ('a' + (halfbyte - 10)));
halfbyte = b & 0x0F;
} while (two_halfs++ < 1);
}
return buf.toString();
}
public static String sha1(String text) throws NoSuchAlgorithmException, UnsupportedEncodingException {
MessageDigest md = MessageDigest.getInstance("SHA-1");
md.update(text.getBytes("utf-8"), 0, text.length());
byte[] sha1hash = md.digest();
return convertToHex(sha1hash);
}
Sprawdź status transakcji wywołując metodę getSaleInfo. Teraz możesz sprawdzić, czy dana transakcja się powiodła. Wystarczy, że wywołasz metodę isSuccess i sprawdzisz dodatkowe informacje lub ewentualne dane o błędach.
try {
$status = $client->getSaleInfo(array('id_sale' => $id_sale));
}
catch (Exception $e) {
// handle exceptions here
}
if ($client->isSuccess()) {
if ('CLEARED' === $status['status']) {
echo "Success, transaction completed, id_sale: {$id_sale}";
}
} else {
die("Error ID: {$status['error']['id_error']}, \n".
"Error number: {$status['error']['error_number']}, \n".
"Error description: {$status['error']['error_description']}");
}
begin
status = client.get_sale_info({"id_sale" => id_sale})
rescue PeP::ClientError => e
# handle exceptions here
end
if client.success?
puts "Success, transaction completed, id_sale: #{id_sale}" if status['status'] == 'CLEARED'
else
puts "Error ID: #{status["error"]["id_error"]}, \n"\
"Error number: #{status["error"]["error_number"]}, \n"\
"Error description: #{status["error"]["error_description"]}"
exit
end
try:
status = client.get_sale_info({'id_sale': id_sale})
except Exception, e:
# handle exceptions here
if client.is_success():
if status['status'] == 'CLEARED':
print 'Success, transaction completed, id_sale: %s' % id_sale
else:
sys.exit('Error ID: ' + str(status["error"]["id_error"]) + '\n' \
'Error number: ' + str(status["error"]["error_number"]) + '\n' \
'Error description: ' + str(status["error"]["error_description"]))
api.saleInfo(idSale, new Callback<SaleInfoResult>() {
@Override
public void onFinish(SaleInfoResult result) {
// success
}
@HandleException
public void onProtocolError(ProtocolException e) {
// invoke if not success
// e.getCode() - error code
// e.getMessage() - error message
}
@Override
public void onError(Exception e) {
// connection error etc.
}
})
Zamiast sprawdzać statusy transakcji ręcznie, możesz po prostu skorzystać z mechanizmu powiadamiania o transakcjach (gorąco do tego zachęcamy). Nasze systemy same wyślą Ci stosowne informacje z użyciem POST – nie musisz wywoływać żadnych funkcji ani wysyłać żądań.
Oto przykład jak możesz sprawdzić komunikację i odebrać powiadomienie:
// check communication
if (empty($_POST['communication_id'])) {
die('Empty communication id');
}
// check if token correct
if ('YOUR_TOKEN' !== $_POST['token']) {
die('Wrong token');
}
foreach ($_POST['content'] as $notification) {
if ($notification['type'] === 'S') { // sale created
// transaction completed, do something useful with id_sale
$id_sale = $notification['id_sale'];
}
}
// return communication_id
die($_POST['communication_id']);
# check communication
if params['communication_id'].blank?
puts "Empty communication id"
exit
end
# check if token is correct
unless 'YOUR_TOKEN' == params['token']
puts "Wrong token"
exit
end
@content = params['content']
# You can do something useful in Rails view later on
@content.each do |notification|
@id_sale = notification['id_sale'] if notification['type'] == 'S'
end
# render :text => params['communication_id']
# check communication
communication_id = get_request_param('communication_id')
if not communication_id:
sys.exit('Empty communication id')
# check if token correct
token = get_request_param('token')
if token != 'YOUR_TOKEN':
sys.exit('Wrong token')
#content = get_request_param('content')
content = [{'type': 'S', 'id_sale': 123456789}]
for notification in content:
if notification['type'] == 'S': # sale created
# transaction completed, do something useful with id_sale
id_sale = notification['id_sale']
# print communication_id
PayPal jest jedną z bardziej rozpoznawalnych metod płatności na świecie. Znany jest głównie ze swojego mechanizmu e-portfela, ale umożliwia też płatności kartami czy przeprowadzanie płatności cyklicznych.
Dość często PayPal jest wybierany przez młode biznesy jako pierwsza metoda płatności, ale zazwyczaj dobrze spisuje się jako dodatkowy kanał płatniczy także w późniejszym czasie.
Zanim zaczniesz wywoływać metody naszego API, pamiętaj, aby poprawnie zainicjować PeP Online Rest Client. To bardzo łatwe, po prostu załącz odpowiedni plik oraz podaj swoją nazwę użytkownika i hasło. ięcej informacji na temat integracji z naszymi systemami znajdziesz na stronie wdrażanie i testy.
include_once ('PePRestClient.php');
$client = new PePRestClient('your_login', 'your_password');
require 'pep_client'
client = PeP::Client.new('your_login', 'your_password')
from client import PePRestClient
client = PePRestClient("your_login", "your_password")
PePApi api = PePClientFactory.createClassicClient(context, "your_login", "your_password");
Przygotuj dane potrzebne do przeprowadzenia płatności jak w przykładzie.
Teraz po prostu wykonaj płatność używając metody paypalSale
.
Możesz sprawdzić, czy płatność się powiodła, wywołując metodę is_success
. Pozyskanie numeru ID transakcji (lub informacji o błędzie, jeśli coś pójdzie nie tak), jest również bardzo proste i może wyglądać jak w przykładzie.
Jeśli metoda paypalSale nie zwróciła błędu, możesz przekierować klienta na stronę PayPala, gdzie dokona płatności. Użyj adresu URL zwróconego przez metodę paypalSale.
$paypal_params = array(
'sale' => array(
'amount' => 19.99,
'currency' => 'EUR',
'description' => 'Product #1'
),
'back_url' => 'http://example-page.com',
);
paypal_params = {
'sale' => {
'amount' => 19.99,
'currency' => 'EUR',
'description' => 'Product #1'
},
'back_url' => 'http://example-page.com'
}
paypal_params = {
'sale' : {
'amount' : 19.99,
'currency' : 'EUR',
'description' : 'Product #1'
},
'back_url' : 'http://example.com'
}
Sale sale = new Sale(19.99, "EUR", "Product #1");
try {
$status = $client->paypalSale($paypal_params);
} catch (Exception $e) {
// handle exceptions here
}
if ($client->isSuccess()) {
echo "Success, id_sale: {$status['id_sale']} \n";
} else {
die("Error ID: {$status['error']['id_error']}, \n".
"Error number: {$status['error']['error_number']}, \n".
"Error description: {$status['error']['error_description']}");
}
header('Location: ' . $status['redirect_url']);
die;
begin
status = client.paypal_sale(paypal_params)
rescue PeP::ClientError => e
# handle exceptions here
end
if client.success?
puts "Success, id_sale: #{status["id_sale"]}"
else
puts "Error ID: #{status["error"]["id_error"]}, \n"\
"Error number: #{status["error"]["error_number"]}, \n"\
"Error description: #{status["error"]["error_description"]}"
end
# redirect to url in status['redirect_url']
exit
try:
status = client.paypal_sale(paypal_params)
except Exception, e:
# handle exceptions here
if client.is_success():
print 'Success, id_sale: %s' % status['id_sale']
else:
print 'Error (%s), %s - %s' % (status['error'].get('id_error'),
status['error'].get('error_number'),
status['error'].get('error_description'))
# redirect to url in status['redirect_url']
sys.exit()
api.payPalSale(sale,"http://example-page.com",new Callback<RedirectSaleResult>(){
@Override
public void onFinish(RedirectSaleResult result) {
WebView webview =...;
webview.loadUrl(result.getRedirectUrl());
}
@HandleException
public void onProtocolError(ProtocolException e) {
// invoke if not success
// e.getCode() - error code
// e.getMessage() - error message
}
@Override
public void onError(Exception e) {
// connection error etc.
}
});
Po zatwierdzeniu płatności na stronie PayPala, klient zostanie przekierowany z powrotem na Twoją stronę (zgodnie z parametrem back_url). Powinieneś teraz zweryfikować zwrócone dane, aby uniknąć ewentualnych prób oszustwa i sprawdzić status transakcji.
$salt = 'YOUR_HASH_SALT';
$status = $_GET['status'];
$description = $_GET['description'];
$amount = $_GET['amount'];
$currency = $_GET['currency'];
$hash = $_GET['hash'];
$id = '';
if ($status !== 'ERROR') // success, get id_sale
$id = $_GET['id_sale'];
$calc_hash = sha1("{$salt}|{$status}|{$description}|{$amount}|{$currency}|{$id}");
// check hash salt
if ( $calc_hash !== $hash ) {
die ("Error, wrong hash");
}
// check transaction status
switch ($status) {
case 'PERFORMED':
echo "Success, transaction completed, id_sale: {$_GET['id_sale']}";
break;
default:
die("Error, transaction declined, {$_GET['error_description']}");
break;
}
# Simple controller action code in Rails
# it's just an example - most of the logic should be moved to model
salt = 'YOUR_HASH_SALT'
status = params['status']
description = params['description']
amount = params['amount']
currency = params['currency']
hash = params['hash']
id = ''
unless status == 'ERROR'
id = params['id_sale']
else
# redirect to an index action to correct the payment + simple notice
# for Rails: redirect_to :index, :notice => "Error, transaction declined, #{description}"
end
calc_hash = Digest::SHA1.hexdigest("#{salt}|#{status}|#{description}|#{amount}|#{currency}|#{id}")
unless calc_hash == hash
# redirect to an index action to correct payment
# for Rails: redirect_to :index, :notice => "Wrong hash"
end
# check transaction status
if status = 'PERFORMED'
# redirect to some index action to correct payment and simple notice
# for rails: redirect_to :index, :notice => "Success, transaction completed, id_sale: #{id}"
else
# redirect to some index action to correct payment and simple notice
# for rails: redirect_to :index, :notice => "Transaction pending"
end
# after back redirect
salt = 'YOUR_HASH_SALT'
status = get_request_param('status')
description = get_request_param('description')
amount = get_request_param('amount')
currency = get_request_param('currency')
hash = get_request_param('hash')
id_sale = None
# success, get id_sale
if status != 'ERROR':
id_sale = get_request_param('id_sale')
calc_hash = hashlib.sha1(
'|'.join([salt, status, description, amount, currency, id_sale])).hexdigest()
# check hash salt
if calc_hash != hash:
sys.exit('Error, wrong hash')
# check transaction status
if status == 'PERFORMED':
print 'Success, transaction completed, id_sale: %s' % id_sale
else:
sys.exit('Error, transaction declined, %s' % \
get_request_param('error_description'))
# Uwaga dot. Pythona:
# Funkcja get_request_param ma za zadanie pobrać wartości GET. Użyj odpowiednich funkcji oferowanych przez framework, z którego korzystasz, lub napisz własną funkcję.
# W przypadku Django możesz użyć:
# param_from_get = request.GET.get('param_name')
# W przypadku Pylons możesz użyć:
# from pylons import request
# param_from_get = request.GET.get('param_name')
api.payPalSale(sale,"http://example-page.com",new Callback<RedirectSaleResult>(){
@Override
public void onFinish(RedirectSaleResult result) {
WebView webview =...;
webview.loadUrl(result.getRedirectUrl());
}
@HandleException
public void onProtocolError(ProtocolException e) {
// invoke if not success
// e.getCode() - error code
// e.getMessage() - error message
}
@Override
public void onError(Exception e) {
// connection error etc.
}
});
Płatności cykliczne to po prostu ponowne obciążenia karty (resale) wykonywane w określonych odstępach czasowych.
Możesz wykonywać je według schematu określanego przez Twój model biznesowy.
Standardowo transakcje cykliczne odbywają się za pośrednictwem tzw. profili recurringowych. Dzięki nim PayPal sam automatycznie inicjuje kolejne płatności według instrukcji, jakie przekażemy mu wraz z pierwszą transakcją.
Konfiguracja powiadomień: Aby poprawnie zintegrować takie transakcje z systemem PeP Online, należy ustawić powiadomienia na koncie PayPal tak, by wskazywały na serwer PeP Online: https://secure.pep.pl/paypalIPN.
Tworzenie profilu recurringowego: Aby stworzyć profil recurringowy należy do parametrów pierwszej płatności dodać strukturę recurring określającą własności profilu. Przykładowo:
W strukturze recurring mamy trzy parametry:
amount
– kwota, jaka będzie cyklicznie pobierana (separator dziesiętny: kropka),start_date
– data (w formacie RRRR-MM-DD) określająca początek cyklu,period
– okres cyklu płatności; możliwe wartości: day – dzień, week – tydzień, month – miesiąc, year – rok. $paypal_params = array(
'sale' => array(
'amount' => 19.99,
'currency' => 'EUR',
'description' => 'Product #1'
),
'back_url' => 'http://example-page.com',
'recurring' => array(
'amount' => '19.99',
'start_date' => '2014-11-01',
'period' => 'month'
),
);
paypal_params = {
'sale' => {
'amount' => 19.99,
'currency' => 'EUR',
'description' => 'Product #1'
},
'back_url' => 'http://example-page.com',
'recurring' => array(
'amount' => '19.99',
'start_date' => '2014-11-01',
'period' => 'month'
)
}
paypal_params = {
'sale' : {
'amount' : 19.99,
'currency' : 'EUR',
'description' : 'Product #1'
},
'back_url' : 'http://example.com',
'recurring' : {
'amount' => '19.99',
'start_date' => '2014-11-01',
'period' => 'month'
}
}
Transakcje referencyjne (tzw. resale odwołujące sie do wcześniejszych płatności) oferują nieco większe możliwości dla bardziej doświadczonych użytkowników – to oni sami bezpośrednio inicjują każdą kolejną płatność. Należy jednak mieć na uwadze, że takie rozwiązanie trzeba dodatkowo samodzielnie zaimplementować.
Co więcej, aby móc skorzystać z tego rozwiązania, należy zgłosić się do PayPala w celu aktywacji transakcji referencyjnych. PayPal wymaga odpowiednich miesięcznych obrotów (np. rzędu 100000 USD) i decyzja o włączeniu transakcji referencyjnych należy do niego.
Resale nie wymaga kompletu informacji o transakcji/kliencie. Dlatego właśnie potrzebna jest najpierw przynajmniej jedna płatność, do której można się odwołać.
Zacznij od przygotowania informacji potrzebnych do zrealizowania ponownej płatności. W tym celu musisz najpierw pozyskać numer ID wcześniejszej transakcji, który jednoznacznie określa daną płatność w systemie PeP Online. Możesz łatwo odczytać ten numer podczas przeprowadzania transakcji, jak w przykładzie.
Wprawdzie możesz odwołać się do dowolnej wcześniejszej transakcji PayPal, to jednak zalecamy odnoszenie się do ostatniej (najnowszej) płatności. Takie podejście ma wiele zalet, pozwala m.in. na łatwe śledzenie przepływu płatności.
Zazwyczaj sprzedawcy przechowują takie numery ID w swoich bazach danych. W ten sposób nie muszą przechowywać żadnych wrażliwych danych, a jednocześnie mają możliwość bezpośredniego odwołania się do wybranej transakcji.
Gdy posiadasz już numer ID (np. pobrany z bazy danych), możesz przygotować dane potrzebne do obciążenia karty i wywołać metodę resaleBySale.
Możesz sprawdzić czy płatność została wykonana prawidłowo wywołując metodę isSuccess. Pozyskanie numeru ID transakcji (lub danych o błędzie, jeśli operacja się nie powiodła) jest również bardzo proste i może wyglądać jak w przykładzie.
Płatności cykliczne są po prostu ponownymi obciążeniami konta PayPal. Od Ciebie zależy, czy będą to odstępy tygodniowe, miesięczne, roczne czy inne; podobnie możesz wykonać resale np. dopiero, gdy klient osiągnie określoną kwotę do spłaty.
$status = $client->paypalSale($paypal_params);
$id_first_sale = $status['id_sale'];
status = client.paypal_sale(paypal_params)
id_first_sale = status['id_sale']
status = client.paypal_sale(paypal_params)
id_first_sale = status['id_sale']
api.payPalSale(sale,"http://example-page.com",new Callback<RedirectSaleResult>() {
@Override
public void onFinish(RedirectSaleResult result) {
long idSale=result.getIdSale();
}
});
$resale_params = array(
'id_sale' => $id_first_sale,
'amount' => 99.99,
'currency' => 'EUR',
'description' => 'Recurring billing product #1',
);
try {
$status = $client->resaleBySale($resale_params);
} catch (Exception $e) {
// handle exceptions here
}
if ($client->isSuccess()) {
echo "Success, second id_sale: {$status['id_sale']} \n";
} else {
die("Error ID: {$status['error']['id_error']}, \n".
"Error number: {$status['error']['error_number']}, \n".
"Error description: {$status['error']['error_description']}");
}
resale_params = {
'id_sale' => id_first_sale,
'amount' => 99.99,
'currency' => 'EUR',
'description' => 'Recurring billing product #1'
}
begin
status = client.resale_by_sale(resale_params)
rescue PeP::ClientError => e
# handle exceptions here
end
if client.success?
puts "Success, id_second_sale: #{status["id_sale"]}"
else
puts "Error ID: #{status["error"]["id_error"]}, \n"\
"Error number: #{status["error"]["error_number"]}, \n"\
"Error description: #{status["error"]["error_description"]}"
exit
end
resale_params = {
'id_sale' : id_first_sale,
'amount' : 99.99,
'currency' : 'EUR',
'description' : 'Recurring billing product #1'
}
try:
status = client.resale_by_sale(resale_params)
except Exception, e:
# handle exceptions here
if client.is_success():
print 'Success, second id_sale: %s' % status['id_sale']
else:
sys.exit('Error ID: ' + str(status["error"]["id_error"]) + '\n' \
'Error number: ' + str(status["error"]["error_number"]) + '\n' \
'Error description: ' + str(status["error"]["error_description"]))
api.resaleSale(idSale, 99.99, "EUR", "Recurring billing product #1", new Callback<FraudSaleResult>() {
@Override
public void onFinish(FraudSaleResult result) {
// success
}
@HandleException
public void onProtocolError(ProtocolException e) {
// invoke if not success
// e.getCode() - error code
// e.getMessage() - error message
}
@Override
public void onError(Exception e) {
// connection error etc.
}
});
Zdarza się, że chcesz zwrócić klientowi pieniądze (np. oddał lub reklamował towar) – całą kwotę lub tylko jej część. Do tego właśnie służy refund, czyli zwrot środków; pozwala na oddanie określonej kwoty w powiązaniu z konkretną transakcją.
Aby przeprowadzić refund, musisz znać numer ID transakcji, który jednoznacznie identyfikuje daną płatność w systemach PeP Online. Możesz łatwo pozyskać ten numer podczas dokonywania transakcji np. jak w przykładzie.
Na stronie Pojedyncza transakcja znajdziesz więcej informacji na temat dokonywania pojedynczej płatności.
Zazwyczaj sprzedawcy zapisują takie numery ID transakcji w swoich bazach danych. Dzięki temu nie muszą sami przechowywać wrażliwych danych i wciąż są w stanie odnieść się do konkretnej płatności.
Przygotuj dane potrzebne do wykonania refunda (wywołaj metodę refund). Zauważ, że możesz podać kwotę transakcji lub mniejszą; jeśli podasz kwotę większą niż kwota transakcji, system zwróci błąd. Możesz również określić walutę oraz powód zwrotu środków.
Podobnie jak w przypadku każdej innej transakcji, tak i tu możesz sprawdzić czy refund został wykonany prawidłowo wywołując metodę isSuccess. Pozyskanie numeru ID refundu (lub danych o błędzie, jeśli operacja się nie powiodła) jest również bardzo proste i może wyglądać jak na poniższym przykładzie.
$status = $client->paypalSale($paypal_params);
$id_sale = $status['id_sale'];
status = client.paypal_sale(paypal_params)
id_sale = status['id_sale']
status = client.paypal_sale(paypal_params)
id_sale = status['id_sale']
api.payPalSale(sale,"http://example-page.com",new Callback<RedirectSaleResult>() {
@Override
public void onFinish(RedirectSaleResult result) {
long idSale=result.getIdSale();
}
});
$refund_params = array(
'id_sale' => $id_sale,
'amount' => 9.99,
'reason' => 'Partial refund',
);
try {
$status = $client->refund($refund_params);
} catch (Exception $e) {
// handle exceptions here
}
if ($client->isSuccess()) {
echo "Success, id_refund: {$status['id_refund']} \n";
} else {
die("Error ID: {$status['error']['id_error']}, \n".
"Error number: {$status['error']['error_number']}, \n".
"Error description: {$status['error']['error_description']}");
}
refund_params = {
'id_sale' => id_sale,
'amount' => 9.99,
'reason' => 'Partial refund.'
}
begin
status = client.refund(refund_params)
rescue PeP::ClientError => e
# handle exceptions here
end
if client.success?
puts "Success, id_refund: #{status["id_refund"]}"
else
puts "Error ID: #{status["error"]["id_error"]}, \n"\
"Error number: #{status["error"]["error_number"]}, \n"\
"Error description: #{status["error"]["error_description"]}"
exit
end
refund_params = {
'id_sale' : id_sale,
'amount' : 9.99,
'reason' : 'Partial refund'
}
try:
status = client.refund(refund_params)
except Exception, e:
# handle exceptions here
if client.is_success():
print 'Success, id_refund: %s' % status['id_refund']
else:
sys.exit('Error ID: ' + str(status["error"]["id_error"]) + '\n' \
'Error number: ' + str(status["error"]["error_number"]) + '\n' \
'Error description: ' + str(status["error"]["error_description"]))
api.refund(idSale, 9.99, "EUR", "Partial refund", new Callback<FraudSaleResult>() {
@Override
public void onFinish(FraudSaleResult result) {
// success
}
@HandleException
public void onProtocolError(ProtocolException e) {
// invoke if not success
// e.getCode() - error code
// e.getMessage() - error message
}
@Override
public void onError(Exception e) {
// connection error etc.
}
});
Możesz nie chcieć od razu pobrać środków klienta, a jedynie dokonać autoryzacji. Może to być użyteczne w różnych przypadkach biznesowych, np. gdy chcesz sprawdzić, czy płatność jest możliwa lub zablokować środki, by pobrać je (lub ich część) później.
Przygotuj dane potrzebne do autoryzacji. Będą to identyczne informacje jak w przypadku “zwykłej” płatności.
Mając te dane, po prostu wywołaj metodę paypalAuthorization (podobnie jak w przypadku płatności wywołasz paypalSale).
Możesz łatwo sprawdzić, czy autoryzacja się powiodła oraz sprawdzić numer ID autoryzacji – możesz go potem użyć do ponownych obciążeń (resale), jeśli chcesz wykorzystać np. płatności cykliczne.
$paypal_params = array(
'sale' => array(
'amount' => 19.99,
'currency' => 'EUR',
'description' => 'Product #1'
),
'back_url' => 'http://example-page.com',
);
paypal_params = {
'sale' => {
'amount' => 19.99,
'currency' => 'EUR',
'description' => 'Product #1'
},
'back_url' => 'http://example-page.com'
}
paypal_params = {
'sale' : {
'amount' : 19.99,
'currency' : 'EUR',
'description' : 'Product #1'
},
'back_url' : 'http://example.com'
}
Sale sale = new Sale(19.99, "EUR", "Product #1");
try {
$status = $client->paypalAuthorization($paypal_params);
} catch (Exception $e) {
// handle exceptions here
}
if ($client->isSuccess()) {
echo "Success, id_authorization: {$status['id_authorization']} \n";
} else {
die("Error ID: {$status['error']['id_error']}, \n".
"Error number: {$status['error']['error_number']}, \n".
"Error description: {$status['error']['error_description']}");
}
begin
status = client.paypal_authorization(paypal_params)
rescue PeP::ClientError => e
# handle exceptions here
end
if client.success?
puts "Success, id_authorization: #{status["id_authorization"]}"
else
puts "Error ID: #{status["error"]["id_error"]}, \n"\
"Error number: #{status["error"]["error_number"]}, \n"\
"Error description: #{status["error"]["error_description"]}"
exit
end
try:
status = client.paypal_authorization(paypal_params)
except Exception, e:
# handle exceptions here
if client.is_success():
print 'Success, id_authorization: %s' % status['id_authorization']
else:
sys.exit('Error ID: ' + str(status["error"]["id_error"]) + '\n' \
'Error number: ' + str(status["error"]["error_number"]) + '\n' \
'Error description: ' + str(status["error"]["error_description"]))
api.payPalAuthorization(sale, "http://example-page.com", new Callback<PayPalAuthorizationResult>() {
@Override
public void onFinish(PayPalAuthorizationResult result) {
// success
}
@HandleException
public void onProtocolError(ProtocolException e) {
// invoke if not success
// e.getCode() - error code
// e.getMessage() - error message
}
@Override
public void onError(Exception e) {
// connection error etc.
}
});
Direct debit to metoda płatności popularna w niektórych krajach europejskich (np. w Niemczech). Łączy pewne cechy kart i przelewów – pobranie środków może być zainicjowane przez sprzedawcę (jak w przypadku kart), natomiast są one pobierane nie z karty, ale z konta (jak w przypadku przelewów).
Zanim zaczniesz wywoływać metody naszego API, pamiętaj, aby poprawnie zainicjować PeP Online Rest Client. To bardzo łatwe, po prostu załącz odpowiedni plik oraz podaj swoją nazwę użytkownika i hasło.
Więcej informacji na temat integracji z naszymi systemami znajdziesz na stronie - Wdrożenia i testy.
include_once ('PePRestClient.php');
$client = new PePRestClient('your_login', 'your_password');
require 'pep_client'
client = PeP::Client.new('your_login', 'your_password')
from client import PePRestClient
client = PePRestClient("your_login", "your_password")
PePApi api = PePClientFactory.createClassicClient(context, "your_login", "your_password");
Przygotuj dane potrzebne do przeprowadzenia płatności jak w przykładzie poniżej. Jak widzisz, w przypadku płatności kartą potrzebne są trzy zestawy informacji: dotyczące transakcji (sale), klienta (customer) oraz konta (account).
Teraz po prostu wykonaj płatność używając metody directDebitSale.
Możesz sprawdzić, czy płatność się powiodła, wywołując metodę isSuccess. Pozyskanie numeru ID transakcji (lub informacji o błędzie, jeśli coś pójdzie nie tak), jest również bardzo proste i może wyglądać jak w przykładzie.
Dokładne opisy wszystkich metod i struktur znajdziesz w opisie funkcji.
Zauważ, że transakcje direct debit oznaczane są po wykonaniu jako pending. Możesz sprawdzić ich status (czy zmienił się na performed, cleared itd.) korzystając z metody getSaleInfo.
$ddebit_params = array(
'sale' => array(
'amount' => 19.99,
'currency' => 'EUR',
'description' => 'Product #1'
),
'customer' => array(
'name' => 'Hans Muller',
'email' => 'hans@muller.de',
'ip' => '127.0.0.1',
'address' => array (
'street_house' => 'Platz der Republik 1',
'city' => 'Berlin',
'state' => 'Berlin',
'zip' => '11011',
'country_code' => 'DE',
),
),
'account' => array(
'account_holder' => 'Hans Muller',
'account_country' => 'DE',
'iban' => 'DE12345678901234567890',
'bic' => 'BICBICDE',
'mandate_id' => '54321',
),
);
ddebit_params = {
'sale'=> {
'amount' => 19.99,
'currency' => 'EUR',
'description' => 'Product #1'
},
'customer' => {
'name' => 'Hans Muller',
'email' => 'hans@muller.de',
'ip' => '127.0.0.1',
'address' => {
'street_house' => 'Platz der Republik 1',
'city' => 'Berlin',
'state' => 'Berlin',
'zip' => '11011',
'country_code' => 'DE'
}
},
'account' => {
'account_holder' => 'Hans Muller',
'account_country' => 'DE',
'iban' => 'DE12345678901234567890',
'bic' => 'BICBICDE',
'mandate_id' => '54321'
}
}
ddebits_params = {
'sale' : {
'amount' : 19.99,
'currency' : 'EUR',
'description' : 'Product #1'
}
'customer' : {
'name' : 'Hans Muller',
'email' : 'hans@muller.de',
'ip' : '127.0.0.1',
'address' : {
'street_house' : 'Platz der Republik 1',
'city' : 'Berlin',
'state' : 'Berlin',
'zip' : '500',
'country_code' : 'DE'
},
},
'account' : {
'account_holder' : 'Hans Muller',
'account_country' : 'DE',
'iban' : 'DE12345678901234567890',
'bic' : 'BICBICDE',
'mandate_id' : '54321'
}
}
Sale sale = new Sale(19.99, "EUR", "Product #1");
Address address = new Address("1600 Pennsylvania Avenue Northwest", "Washington", "DC", "500", "US");
Customer customer = new Customer("John Doe", "john@doe.com", "127.0.0.1", address);
Account account = new Account("Hans Muller","de","DE12345678901234567890","BICBICDE","54321");
try {
$status = $client->directDebitSale($ddebit_params);
} catch (Exception $e) {
// handle exceptions here
}
if ($client->isSuccess()) {
echo "Success, id_sale: {$status['id_sale']} \n";
} else {
die("Error ID: {$status['error']['id_error']}, \n".
"Error number: {$status['error']['error_number']}, \n".
"Error description: {$status['error']['error_description']}");
}
begin
status = client.direct_debit_sale(ddebit_params)
rescue PeP::ClientError => e
# handle exceptions here
end
if client.success?
puts "Success, id_sale: #{status["id_sale"]}"
else
puts "Error ID: #{status["error"]["id_error"]}, \n"\
"Error number: #{status["error"]["error_number"]}, \n"\
"Error description: #{status["error"]["error_description"]}"
exit
end
try:
status = client.direct_debit_sale(ddebits_params)
except Exception, e:
# handle exceptions here
if client.is_success():
print 'Success, id_sale: %s' % status['id_sale']
else:
sys.exit('Error ID: ' + str(status["error"]["id_error"]) + '\n' \
'Error number: ' + str(status["error"]["error_number"]) + '\n' \
'Error description: ' + str(status["error"]["error_description"]))
api.directDebitSale(sale, customer, account, new Callback<SaleResult>() {
@Override
public void onFinish(SaleResult result) {
// success
}
@HandleException
public void onProtocolError(ProtocolException e) {
// invoke if not success
// e.getCode() - error code
// e.getMessage() - error message
}
@Override
public void onError(Exception e) {
// connection error etc.
}
});
Podobnie jak w przypadku kart występują chargebacki (obciążenia zwrotne), w płatnościach direct debit występuje mechanizm reversal.
Sprawdzanie statusów transakcji direct debit jest wysoce zalecane – w ten sposób można określić, czy reversal (a więc żądanie zwrotu środków) wystąpił, czy nie. Możesz sprawdzać statusy transakcji ręcznie w Merchant Panelu, ale również automatycznie przez API.
Jeśli chcesz użyć API, by sprawdzić status transakcji direct debit, użyj metody getSaleInfo.
Teraz po prostu sprawdź, czy pole is_reversal w sale_info ma wartość true czy false.
Możesz również użyć mechanizmu powiadomień o transakcjach, by sprawdzać statusy transakcji automatycznie. Dzięki temu nie będziesz musiał wysyłać żadnych żądań do naszych systemów – otrzymasz powiadomienie, gdy tylko transakcja zmieni swój status.
try {
$sale_info = $client->getSaleInfo(array('id_sale' => $id_sale));
}
catch (Exception $e) {
// handle exceptions here
}
begin
status = client.get_sale_info({"id_sale" => id_sale})
rescue PeP::ClientError => e
# handle exceptions here
end
try:
sale_info = client.get_sale_info({'id_sale': id_sale})
except Exception, e:
# handle exceptions here
api.saleInfo(idSale, new Callback<SaleInfoResult>() {
@Override
public void onFinish(SaleInfoResult result) {
// success
}
@HandleException
public void onProtocolError(ProtocolException e) {
// invoke if not success
// e.getCode() - error code
// e.getMessage() - error message
}
@Override
public void onError(Exception e) {
// connection error etc.
}
});
Płatności cykliczne to po prostu ponowne obciążenia karty (resale) wykonywane w określonych odstępach czasowych. Możesz wykonywać je według schematu określanego przez Twój model biznesowy.
Resale nie wymaga kompletu informacji o karcie i kliencie. Dlatego właśnie potrzebna jest najpierw przynajmniej jedna płatność, do której można się odwołać.
Zacznij od przygotowania informacji potrzebnych do zrealizowania ponownej transakcji direct debit. W tym celu musisz najpierw pozyskać numer ID wcześniejszej transakcji, który jednoznacznie określa daną płatność w systemie PeP Online. Możesz łatwo odczytać ten numer podczas przeprowadzania transakcji, np. jak w przykładzie.
Na stronie Pojedyncza transakcja znajdziesz więcej informacji na temat dokonywania pojedynczej płatności.
Wprawdzie możesz odwołać się do dowolnej wcześniejszej transakcji direct debit, to jednak zalecamy odnoszenie się do ostatniej płatności. Takie podejście ma wiele zalet, pozwala m.in. na łatwe śledzenie przepływu płatności.
Zazwyczaj sprzedawcy przechowują takie numery ID w swoich bazach danych. W ten sposób nie muszą przechowywać żadnych wrażliwych danych, a jednocześnie mają możliwość bezpośredniego odwołania się do wybranej transakcji.
Gdy posiadasz już numer ID (np. pobrany z bazy danych), możesz wywołać metodę resaleBySale.
Możesz sprawdzić czy płatność została wykonana prawidłowo wywołując metodę isSuccess. Pozyskanie numeru ID transakcji (lub danych o błędzie, jeśli operacja się nie powiodła) jest również bardzo proste i może wyglądać jak na poniższym przykładzie.
Płatności cykliczne są po prostu ponownymi obciążeniami konta. Od Ciebie zależy, czy będą to odstępy tygodniowe, miesięczne, roczne czy inne; podobnie możesz obciążyć konto np. dopiero, gdy klient osiągnie określoną kwotę do spłaty.
$status = $client->directDebitSale($ddebit_params);
$id_first_sale = $status['id_sale'];
status = client.direct_debit_sale(ddebit_params)
d_first_sale = status["id_sale"]
status = client.direct_debit_sale(ddebit_params)
id_first_sale = status['id_sale']
api.directDebitSale(sale, customer, account, new Callback<SaleResult>() {
@Override
public void onFinish(SaleResult result) {
long idSale=result.getIdSale();
}
});
$resale_params = array(
'id_sale' => $id_first_sale,
'amount' => 99.99,
'currency' => 'EUR',
'description' => 'Recurring billing product #1',
);
try {
$status = $client->resaleBySale($resale_params);
} catch (Exception $e) {
// handle exceptions here
}
if ($client->isSuccess()) {
echo "Success, second id_sale: {$status['id_sale']} \n";
} else {
die("Error ID: {$status['error']['id_error']}, \n".
"Error number: {$status['error']['error_number']}, \n".
"Error description: {$status['error']['error_description']}");
}
resale_params = {
'id_sale' => id_first_sale,
'amount' => 99.99,
'currency' => 'EUR',
'description' => 'Recurring billing product #1'
}
begin
status = client.resale_by_sale(resale_params)
rescue PeP::ClientError => e
# handle exceptions here
end
if client.success?
puts "Success, id_second_sale: #{status["id_sale"]}"
else
puts "Error ID: #{status["error"]["id_error"]}, \n"\
"Error number: #{status["error"]["error_number"]}, \n"\
"Error description: #{status["error"]["error_description"]}"
exit
end
resale_params = {
'id_sale' : id_first_sale,
'amount' : 99.99,
'currency' : 'EUR',
'description' : 'Recurring billing product #1'
}
try:
status = client.resale_by_sale(resale_params)
except Exception, e:
# handle exceptions here
if client.is_success():
print 'Success, second id_sale: %s' % status['id_sale']
else:
sys.exit('Error ID: ' + str(status["error"]["id_error"]) + '\n' \
'Error number: ' + str(status["error"]["error_number"]) + '\n' \
'Error description: ' + str(status["error"]["error_description"]))
api.resaleSale(idSale, 99.99, "EUR", "Recurring billing product #1", new Callback<FraudSaleResult>() {
@Override
public void onFinish(FraudSaleResult result) {
// success
}
@HandleException
public void onProtocolError(ProtocolException e) {
// invoke if not success
// e.getCode() - error code
// e.getMessage() - error message
}
@Override
public void onError(Exception e) {
// connection error etc.
}
});
Zdarza się, że chcesz zwrócić klientowi pieniądze (np. oddał lub reklamował towar) – całą kwotę lub tylko jej część. Do tego właśnie służy refund, czyli zwrot środków; pozwala na oddanie określonej kwoty w powiązaniu z konkretną transakcją.
Aby przeprowadzić refund, musisz znać numer ID transakcji, który jednoznacznie identyfikuje daną płatność w systemach PeP Online. Możesz łatwo pozyskać ten numer podczas dokonywania transakcji np. jak w przykładzie.
Na stronie Pojedyncza transakcja znajdziesz więcej informacji na temat dokonywania pojedynczej płatności.
Zazwyczaj sprzedawcy zapisują takie numery ID transakcji w swoich bazach danych. Dzięki temu nie muszą sami przechowywać wrażliwych danych i wciąż są w stanie odnieść się do konkretnej płatności.
Przygotuj dane potrzebne do wykonania refunda. Zauważ, że możesz podać kwotę transakcji lub mniejszą; jeśli podasz kwotę większą niż kwota transakcji, system zwróci błąd. Możesz również określić walutę oraz powód zwrotu środków.
Po prostu wywołaj metodę refund. Podobnie jak w przypadku każdej innej transakcji, tak i tu możesz sprawdzić czy refund został wykonany prawidłowo wywołując metodę isSuccess. Pozyskanie numeru ID refundu (lub danych o błędzie, jeśli operacja się nie powiodła) jest również bardzo proste i może wyglądać jak na poniższym przykładzie.
$status = $client->directDebitSale($ddebit_params);
$id_sale = $status['id_sale'];
status = client.direct_debit_sale(ddebit_params)
id_sale = status["id_sale"]
status = client.direct_debit_sale(ddebit_params)
id_sale = status['id_sale']
api.directDebitSale(sale, customer, account, new Callback<SaleResult>() {
@Override
public void onFinish(SaleResult result) {
long idSale=result.getIdSale();
}
});
$refund_params = array(
'id_sale' => $id_sale,
'amount' => 9.99,
'reason' => 'Partial refund',
);
try {
$status = $client->refund($refund_params);
} catch (Exception $e) {
// handle exceptions here
}
if ($client->isSuccess()) {
echo "Success, id_refund: {$status['id_refund']} \n";
} else {
die("Error ID: {$status['error']['id_error']}, \n".
"Error number: {$status['error']['error_number']}, \n".
"Error description: {$status['error']['error_description']}");
}
refund_params = {
'id_sale' => id_sale,
'amount' => 9.99,
'reason' => 'Partial refund.'
}
begin
status = client.refund(refund_params)
rescue PeP::ClientError => e
# handle exceptions here
end
if client.success?
puts "Success, id_refund: #{status["id_refund"]}"
else
puts "Error ID: #{status["error"]["id_error"]}, \n"\
"Error number: #{status["error"]["error_number"]}, \n"\
"Error description: #{status["error"]["error_description"]}"
exit
end
refund_params = {
'id_sale' : id_sale,
'amount' : 9.99,
'reason' : 'Partial refund'
}
try:
status = client.refund(refund_params)
except Exception, e:
# handle exceptions here
if client.is_success():
print 'Success, id_refund: %s' % status['id_refund']
else:
sys.exit('Error ID: ' + str(status["error"]["id_error"]) + '\n' \
'Error number: ' + str(status["error"]["error_number"]) + '\n' \
'Error description: ' + str(status["error"]["error_description"]))
api.refund(idSale, 9.99, "EUR", "Partial refund", new Callback<FraudSaleResult>() {
@Override
public void onFinish(FraudSaleResult result) {
// success
}
@HandleException
public void onProtocolError(ProtocolException e) {
// invoke if not success
// e.getCode() - error code
// e.getMessage() - error message
}
@Override
public void onError(Exception e) {
// connection error etc.
}
});
SOFORT Banking to międzynarodowy system płatności online dostępny w wybranych krajach europejskich (Polska, Niemcy, Austria, Szwajcaria, Wielka Brytania, Belgia, Francja, Włochy, Hiszpania).
Zanim zaczniesz wywoływać metody naszego API, pamiętaj, aby poprawnie zainicjować PeP Online Rest Client.
To bardzo łatwe, po prostu załącz odpowiedni plik oraz podaj swoją nazwę użytkownika i hasło.
include_once ('PePRestClient.php');
$client = new PePRestClient('your_login', 'your_password');
require 'pep_client'
client = PeP::Client.new('your_login', 'your_password')
from client import PePRestClient
client = PePRestClient("your_login", "your_password")
PePApi api = PePClientFactory.createClassicClient(context, "your_login", "your_password");
Zacznij od przygotowania danych do przeprowadzenia płatności z użyciem systemu SOFORT: informacje o transakcji, kliencie, typie płatności. Zdefiniuj także adres (back_url), na który klient zostanie przekierowany po dokonaniu płatności.
$sofort_params = array(
'sale' => array(
'amount' => 19.99,
'currency' => 'PLN',
'description' => 'Product #1'
),
'customer' => array(
'name' => 'John Doe',
'email' => 'john@doe.com',
'ip' => '127.0.0.1',
'address' => array (
'street_house' => '1600 Pennsylvania Avenue Northwest',
'city' => 'Washington',
'state' => 'DC',
'zip' => '500',
'country_code' => 'US',
),
),
'back_url' => 'http://example-page.com',
);
sofort_params = {
'sale' => {
'amount' => 19.99,
'currency' => 'PLN',
'description' => 'Product #1'
},
'customer' => {
'name' => 'John Doe',
'email' => 'john@doe.com',
'ip' => '127.0.0.1',
'address' => array (
'street_house' => '1600 Pennsylvania Avenue Northwest',
'city' => 'Washington',
'state' => 'DC',
'zip' => '500',
'country_code' => 'US'
}
},
'back_url' => 'http://example-page.com'
}
bt_params = {
'sale' : {
'amount' : 19.99,
'currency' : 'PLN',
'description' : 'Product #1'
},
'customer' : {
'name' : 'John Doe'
'email' : 'john@doe.com',
'ip' : '127.0.0.1',
'address' : {
'street_house' : '1600 Pennsylvania Avenue Northwest',
'city' : 'Washington',
'state' : 'DC',
'zip' : '500'
'country_code' : 'US'
},
},
'back_url' : 'http://example.com'
}
Sale sale = new Sale(19.99, "EUR", "Product #1");
Address address = new Address("1600 Pennsylvania Avenue Northwest", "Washington", "DC", "500", "US");
Customer customer = new Customer("John Doe", "john@doe.com", "127.0.0.1", address);
Po prostu wywołaj metodę sofortSale. Możesz także sprawdzić, czy płatność się powiodła, pozyskać numer ID transakcji lub informacji o błędzie, jeśli coś pójdzie nie tak.
Jeśli metoda sofortSale została wywołana z powodzeniem, możesz przekierować klienta na stronę banku, gdzie dokona płatności. Użyj adresu URL zwróconego przez metodę sofortSale.
try {
$status = $client->sofortSale($bt_params);
}
catch (Exception $e) {
// handle exceptions here
}
if ($client->isSuccess()) {
echo "Success, transaction initiated, id_sale: {$status['id_sale']}, \n
redirect_url: {$status['redirect_url']} \n";
} else {
die("Error ID: {$status['error']['id_error']}, \n".
"Error number: {$status['error']['error_number']}, \n".
"Error description: {$status['error']['error_description']}");
}
header('Location: ' . $status['redirect_url']);
die;
begin
status = client.sofort_sale(bt_params)
rescue PeP::ClientError => e
# handle exceptions here
end
if client.success?
puts "Success, transaction initiated, id_sale: #{status["id_sale"]}"\
"redirect_url: #{status["redirect_url"]}"
else
puts "Error ID: #{status["error"]["id_error"]}, \n"\
"Error number: #{status["error"]["error_number"]}, \n"\
"Error description: #{status["error"]["error_description"]}"
exit
end
# redirect to url in status['redirect_url']
exit
try:
status = client.sofort_sale(bt_params)
except Exception, e:
# handle exceptions here
if client.is_success():
print 'Success, transaction initiated, id_sale: %s, redirect_url: %s' % \
(status['id_sale'], status['redirect_url'])
else:
sys.exit('Error ID: ' + str(status["error"]["id_error"]) + '\n' \
'Error number: ' + str(status["error"]["error_number"]) + '\n' \
'Error description: ' + str(status["error"]["error_description"]))
# redirect to url in status['redirect_url']
sys.exit()
api.sofortSale(sale, customer, "http://example-page.com", new Callback<RedirectSaleResult>() {
@Override
public void onFinish(RedirectSaleResult result) {
WebView webview =...;
webview.loadUrl(result.getRedirectUrl());
}
@HandleException
public void onProtocolError(ProtocolException e) {
// invoke if not success
// e.getCode() - error code
// e.getMessage() - error message
}
@Override
public void onError(Exception e) {
// connection error etc.
}
});
Po dokonaniu płatności na stronie banku, klient zostanie przekierowany z powrotem na Twoją stronę (na adres back_url). Powinieneś teraz zweryfikować zwrócone dane, aby uniknąć ewentualnych prób oszustwa i sprawdzić status transakcji.
$salt = 'YOUR_HASH_SALT';
$status = $_GET['status'];
$description = $_GET['description'];
$amount = $_GET['amount'];
$currency = $_GET['currency'];
$hash = $_GET['hash'];
$id = '';
if ($status !== 'ERROR') // success, get id_sale
$id = $_GET['id_sale'];
$calc_hash = sha1("{$salt}|{$status}|{$description}|{$amount}|{$currency}|{$id}");
// check hash salt
if ( $calc_hash !== $hash ) {
die ("Error, wrong hash");
}
// check transaction status
switch ($status) {
case 'ERROR':
die("Error, transaction declined, {$_GET['error_description']}");
break;
case 'CLEARED':
echo "Success, transaction completed, id_sale: {$_GET['id_sale']}";
break;
default:
/* transaction pending:
* check status regularly using the saleStatus method
* or wait for notification */
echo "Transaction pending";
break;
}
# Simple controller action code in Rails
# it's just an example - most of the logic should be moved to model
salt = 'YOUR_HASH_SALT'
status = params['status']
description = params['description']
amount = params['amount']
currency = params['currency']
hash = params['hash']
id = ''
unless status == 'ERROR'
id = params['id_sale']
else
# redirect to an index action to correct the payment + simple notice
# for rails: redirect_to :index, :notice => "Error, transaction declined, #{description}"
end
calc_hash = Digest::SHA1.hexdigest("#{salt}|#{status}|#{description}|#{amount}|#{currency}|#{id}")
unless calc_hash == hash
# redirect to an index action to correct the payment
# for rails: redirect_to :index
end
# check transaction status
case status
when 'ERROR'
# redirect to an index action to correct the payment + simple notice
# for rails: redirect_to :index, :notice => "Error, transaction declined, #{response["error"]["error_description"]}"
when 'CLEARED'
# redirect to an index action to correct the payment + simple notice
# for rails: redirect_to :index, :notice => "Success, transaction completed, id_sale: #{id}"
else
# redirect to an index action to correct the payment + simple notice
# for rails: redirect_to :index, :notice => "Transaction pending"
end
salt = 'YOUR_HASH_SALT'
status = get_request_param('status')
description = get_request_param('description')
amount = get_request_param('amount')
currency = get_request_param('currency')
hash = get_request_param('hash')
id_sale = None
# success, get id_sale
if status != 'ERROR':
id_sale = get_request_param('id_sale')
calc_hash = hashlib.sha1(
'|'.join([salt, status, description, amount, currency, id_sale])).hexdigest()
# check hash salt
if calc_hash != hash:
sys.exit('Error, wrong hash')
# check transaction status
if status == 'ERROR':
sys.exit('Error, transaction declined, %s' % \
get_request_param('error_description'))
elif status == 'CLEARED':
print 'Success, transaction completed, id_sale: %s' % id_sale
else:
# transaction pending: check status regularly using the saleStatus
# method or wait for notification
print 'Transaction pending'
# Uwaga dot. Pythona:
# Funkcja get_request_param ma za zadanie pobrać wartości GET. Użyj odpowiednich funkcji oferowanych przez framework, z którego korzystasz, lub napisz własną funkcję.
# W przypadku Django możesz użyć:
# param_from_get = request.GET.get('param_name')
# W przypadku Pylons możesz użyć:
# from pylons import request param_from_get = request.GET.get('param_name')
Zamiast sprawdzać statusy transakcji ręcznie, możesz po prostu skorzystać z mechanizmu powiadamiania o transakcjach.
Nasze systemy same wyślą Ci stosowne informacje z użyciem POST – nie musisz wywoływać żadnych funkcji ani wysyłać żądań.
Oto przykład jak możesz sprawdzić komunikację i odebrać powiadomienie:
// check communication
if (empty($_POST['communication_id'])) {
die('Empty communication id');
}
// check if token correct
if ('YOUR_TOKEN' !== $_POST['token']) {
die('Wrong token');
}
foreach ($_POST['content'] as $notification) {
if ($notification['type'] === 'S') { // sale created
// transaction completed, do something useful with id_sale
$id_sale = $notification['id_sale'];
}
}
// return communication_id
die($_POST['communication_id']);
# check communication
if params['communication_id'].blank?
print "Empty communication id"
exit
end
# check if token is correct
unless 'YOUR_TOKEN' == params['token']
print "Wrong token"
exit
end
@content = params['content']
# You can do something useful in Rails view later on
@content.each do |notification|
@id_sale = notification['id_sale'] if notification['type'] == 'S'
end
# render :text => params['communication_id']
# check communication
communication_id = get_request_param('communication_id')
if not communication_id:
sys.exit('Empty communication id')
# check if token correct
token = get_request_param('token')
if token != 'YOUR_TOKEN':
sys.exit('Wrong token')
#content = get_request_param('content')
content = [{'type': 'S', 'id_sale': 123456789}]
for notification in content:
if notification['type'] == 'S': # sale created
# transaction completed, do something useful with id_sale
id_sale = notification['id_sale']
# print communication_id
# Uwaga dot. Pythona:
# Funkcja get_request_param ma za zadanie pobrać wartości GET. Użyj odpowiednich funkcji oferowanych przez framework, z którego korzystasz, lub napisz własną funkcję.
# W przypadku Django możesz użyć:
# param_from_get = request.GET.get('param_name')
# W przypadku Pylons możesz użyć:
# from pylons import request param_from_get = request.GET.get('param_name')
Sprawdź status transakcji wywołując metodę getSaleInfo. Teraz możesz sprawdzić, czy dana transakcja się powiodła. Wystarczy, że wywołasz metodę isSuccess czy sprawdzisz dodatkowe informacje lub ewentualne dane o błędach.
try {
$status = $client->getSaleInfo(array('id_sale' => $id_sale));
}
catch (Exception $e) {
// handle exceptions here
}
if ($client->isSuccess()) {
if ('CLEARED' === $status['status']) {
echo "Success, transaction completed, id_sale: {$id_sale}";
}
} else {
die("Error ID: {$status['error']['id_error']}, \n".
"Error number: {$status['error']['error_number']}, \n".
"Error description: {$status['error']['error_description']}");
}
begin
status = client.get_sale_info({"id_sale" => id_sale})
rescue PeP::ClientError => e
# handle exceptions here
end
if client.success?
puts "Success, transaction completed, id_sale: #{id_sale}" if status['status'] == 'CLEARED'
else
puts "Error ID: #{status["error"]["id_error"]}, \n"\
"Error number: #{status["error"]["error_number"]}, \n"\
"Error description: #{status["error"]["error_description"]}"
exit
end
try:
status = client.get_sale_info({'id_sale': id_sale})
except Exception, e:
# handle exceptions here
if client.is_success():
if status['status'] == 'CLEARED':
print 'Success, transaction completed, id_sale: %s' % id_sale
else:
sys.exit('Error ID: ' + str(status["error"]["id_error"]) + '\n' \
'Error number: ' + str(status["error"]["error_number"]) + '\n' \
'Error description: ' + str(status["error"]["error_description"]))
api.saleInfo(idSale, new Callback<SaleInfoResult>() {
@Override
public void onFinish(SaleInfoResult result) {
// success
}
@HandleException
public void onProtocolError(ProtocolException e) {
// invoke if not success
// e.getCode() - error code
// e.getMessage() - error message
}
@Override
public void onError(Exception e) {
// connection error etc.
}
});
iDEAL to holenderski system umożliwiający przyjmowanie płatności w Holandii z użyciem przelewów bankowych.
W przeciwieństwie do wielu innych lokalnych systemów przelewowych, iDEAL charakteryzuje się zunifikowanym interfejsem do bezpiecznego przetwarzania płatności w czasie rzeczywistymi.
iDEAL jest bardzo popularny na rynku holenderskim.
Zanim zaczniesz wywoływać metody naszego API, pamiętaj, aby poprawnie zainicjować PeP Online Rest Client. To bardzo łatwe, po prostu załącz odpowiedni plik oraz podaj swoją nazwę użytkownika i hasło.
include_once ('PePRestClient.php');
$client = new PePRestClient('your_login', 'your_password');
require 'pep_client'
client = PeP::Client.new('your_login', 'your_password')
from client import PePRestClient
client = PePRestClient("your_login", "your_password")
PePApi api = PePClientFactory.createClassicClient(context, "your_login", "your_password");
Aby wyświetlić klientom formularz płatniczy, przez który będą mogli zapłacić z użyciem systemu iDEAL, musisz najpierw pobrać listę dostępnych banków. Służy do tego metoda idealBankCodes.
Zacznij od odpytania PeP Online o listę banków (jak w przykładzie po prawej stronie)
Teraz możesz wyświetlić swoim klientom opcje płatności (może się to różnić w zależności od języka programowania / frameworku). W przykładzie po prawej możesz zobaczyć próbkę kodu.
Gdy formularz zostanie wysłany, należy wywołać metodę ideal/sale, co pozwoli na przeprowadzenie transakcji.
try {
$status = $client->idealBankCodes();
}
catch (Exception $e) {
// handle exception
}
if (!$client->isSuccess()) {
$error_number = $status['error']['error_number'];
$error_description = $status['error']['error_description'];
// handle error
}
begin
status = client.ideal_bank_codes()
rescue PeP::ClientError => e
# handle exception here
end
try:
status = client.ideal_bank_codes()
except Exception, e:
# handle exception
print e
sys.exit()
<select name="bank-code">
<?php
foreach ($status['data'] as $bank) {
echo sprintf('<option value="%s">%s</option>', $bank['bank_code'], $bank['bank_name']), "\n";
}
?>
</select>
if client.success?
status['data'].each do |bank|
# inject the returned bank data into your payment form, example:
puts '<option value="%s">%s</option>' % [bank['bank_code'], bank['bank_name']]
end
else
puts "Error number: #{status["error"]["error_number"]}, \n"\
"Error description: #{status["error"]["error_description"]}"
exit
end
if client.is_success():
for bank in status['data']:
# inject the returned bank data into your payment form, example:
print '<option value="%s">%s</option>' % (bank['bank_code'], bank['bank_name'])
else:
sys.exit('Error number: ' + str(status["error"]["error_number"]) + '\n' \
'Error description: ' + str(status["error"]["error_description"]))
Zacznij od przygotowania danych do przeprowadzenia płatności z użyciem systemu iDEAL:
Zdefiniuj także adres (back_url), na który klient zostanie przekierowany po dokonaniu płatności.
$params = array(
'sale' => array(
'amount' => 19.99,
'currency' => 'EUR',
'description' => 'Product #1'
),
'customer' => array(
'name' => 'John Doe',
'email' => 'john@doe.com',
'ip' => '127.0.0.1',
'address' => array (
'street_house' => '1600 Pennsylvania Avenue Northwest',
'city' => 'Washington',
'state' => 'DC',
'zip' => '500',
'country_code' => 'US',
),
),
'back_url' => 'http://example-page.com',
'bank_code' => 'INGBNL2A',
);
params = {
'sale' => {
'amount' => 19.99,
'currency' => 'EUR',
'description' => 'Product #1'
},
'customer' => {
'name' => 'John Doe',
'email' => 'john@doe.com',
'ip' => '127.0.0.1',
'address' => {
'street_house' => '1600 Pennsylvania Avenue Northwest',
'city' => 'Washington',
'state' => 'DC',
'zip' => '500',
'country_code' => 'US'
}
},
'back_url' => 'http://example-page.com',
'bank_code' => 'INGBNL2A'
}
params = {
'sale' : {
'amount' : 19.99,
'currency' : 'EUR',
'description' : 'Product #1'
},
'customer' : {
'name' : 'John Doe'
'email' : 'john@doe.com',
'ip' : '127.0.0.1',
'address' : {
'street_house' : '1600 Pennsylvania Avenue Northwest',
'city' : 'Washington',
'state' : 'DC',
'zip' : '500'
'country_code' : 'US'
},
},
'back_url' : 'http://example.com',
'bank_code' : 'INGBNL2A'
}
Po prostu wywołaj metodę idealSale. Możesz także sprawdzić, czy płatność się powiodła, pozyskać numer ID transakcji lub informacji o błędzie, jeśli coś pójdzie nie tak.
Jeśli metoda idealSale została wywołana z powodzeniem, możesz przekierować klienta na stronę banku, gdzie dokona płatności. Użyj adresu URL zwróconego przez metodę idealSale.
try
{
$status = $client->idealSale($params);
}
catch (Exception $e)
{
// handle exception
}
if ($client->isSuccess()) {
echo "Success, transaction initiated, id_sale: {$status['id_sale']}, \n
redirect_url: {$status['redirect_url']} \n";
} else {
die("Error ID: {$status['error']['id_error']}, \n".
"Error number: {$status['error']['error_number']}, \n".
"Error description: {$status['error']['error_description']}");
}
header('Location: ' . $status['redirect_url']);
die;
begin
status = client.ideal_sale(params)
rescue PeP::ClientError => e
# handle exception here
end
if client.success?
puts "Success, transaction initiated, id_sale: #{status["id_sale"]}"\
"redirect_url: #{status["redirect_url"]}"
else
puts "Error ID: #{status["error"]["id_error"]}, \n"\
"Error number: #{status["error"]["error_number"]}, \n"\
"Error description: #{status["error"]["error_description"]}"
exit
end
# redirect to url in status['redirect_url']
exit
try:
status = client.ideal_sale(params)
except Exception, e:
# handle exception
print e
sys.exit()
if client.is_success():
print 'Success, transaction initiated, id_sale: %s, redirect_url: %s' % \
(status['id_sale'], status['redirect_url'])
else:
sys.exit('Error ID: ' + str(status["error"]["id_error"]) + '\n' \
'Error number: ' + str(status["error"]["error_number"]) + '\n' \
'Error description: ' + str(status["error"]["error_description"]))
# redirect to url in status['redirect_url']
sys.exit()
# Uwaga dot. Pythona:
# W Pythonie nie ma natywnej funkcji służącej do przekierowania na inną stronę – musisz albo skorzystać z funkcji oferowanych przez framework, z którego korzystasz, albo napisać własną funkcję.
# W przypadku Django możesz użyć:
# from django.http import HttpResponseRedirect
# HttpResponseRedirect('http://example.com/')
# W przypadku Pylons możesz użyć:
# from pylons.controllers.util import redirectredirect('http://example.com/')
Po dokonaniu płatności na stronie banku, klient zostanie przekierowany z powrotem na Twoją stronę (na adres back_url). Powinieneś teraz zweryfikować zwrócone dane, aby uniknąć ewentualnych prób oszustwa i sprawdzić status transakcji.
$salt = 'YOUR_HASH_SALT';
$status = $_GET['status'];
$description = $_GET['description'];
$amount = $_GET['amount'];
$currency = $_GET['currency'];
$hash = $_GET['hash'];
$id = '';
if ($status !== 'ERROR') // success, get id_sale
$id = $_GET['id_sale'];
$calc_hash = sha1("{$salt}|{$status}|{$description}|{$amount}|{$currency}|{$id}");
// check hash salt
if ( $calc_hash !== $hash ) {
die ("Error, wrong hash");
}
// check transaction status
switch ($status) {
case 'ERROR':
die("Error, transaction declined, {$_GET['error_description']}");
break;
case 'CLEARED':
echo "Success, transaction completed, id_sale: {$_GET['id_sale']}";
break;
default:
/* transaction pending:
* check status regularly using the saleStatus method
* or wait for notification */
echo "Transaction pending";
break;
}
# Simple controller action code in Rails
# it's just an example - most of the logic should be moved to model
salt = 'YOUR_HASH_SALT'
status = params['status']
description = params['description']
amount = params['amount']
currency = params['currency']
hash = params['hash']
id = ''
unless status == 'ERROR'
id = params['id_sale']
else
# redirect to an index action to correct the payment + simple notice
# for rails: redirect_to :index, :notice => "Error, transaction declined, #{description}"
end
calc_hash = Digest::SHA1.hexdigest("#{salt}|#{status}|#{description}|#{amount}|#{currency}|#{id}")
unless calc_hash == hash
# redirect to an index action to correct the payment
# for rails: redirect_to :index
end
# check transaction status
case status
when 'ERROR'
# redirect to an index action to correct the payment + simple notice
# for rails: redirect_to :index, :notice => "Error, transaction declined, #{response["error"]["error_description"]}"
when 'CLEARED'
# redirect to an index action to correct the payment + simple notice
# for rails: redirect_to :index, :notice => "Success, transaction completed, id_sale: #{id}"
else
# redirect to an index action to correct the payment + simple notice
# for rails: redirect_to :index, :notice => "Transaction pending"
end
salt = 'YOUR_HASH_SALT'
status = get_request_param('status')
description = get_request_param('description')
amount = get_request_param('amount')
currency = get_request_param('currency')
hash = get_request_param('hash')
id_sale = None
# success, get id_sale
if status != 'ERROR':
id_sale = get_request_param('id_sale')
calc_hash = hashlib.sha1(
'|'.join([salt, status, description, amount, currency, id_sale])).hexdigest()
# check hash salt
if calc_hash != hash:
sys.exit('Error, wrong hash')
# check transaction status
if status == 'ERROR':
sys.exit('Error, transaction declined, %s' % \
get_request_param('error_description'))
elif status == 'CLEARED':
print 'Success, transaction completed, id_sale: %s' % id_sale
else:
# transaction pending: check status regularly using the saleStatus
# method or wait for notification
print 'Transaction pending'
# Python note:
# The get_request_param function is supposed to collect data from GET params. Depending on your framework or any other toolkit, please use a proper function or write one that suits you best.
# For Django, you can use:
# param_from_get = request.GET.get('param_name')
# For Pylons, you can use:
# from pylons import requestparam_from_get = request.GET.get('param_name')
Sprawdź status transakcji wywołując metodę getSaleInfo. Teraz możesz sprawdzić, czy dana transakcja się powiodła. Wystarczy, że wywołasz metodę isSuccess czy sprawdzisz dodatkowe informacje lub ewentualne dane o błędach.
try {
$status = $client->getSaleInfo(array('id_sale' => $id_sale));
}
catch (Exception $e) {
// handle exceptions here
}
if ($client->isSuccess()) {
if ('CLEARED' === $status['status']) {
echo "Success, transaction completed, id_sale: {$id_sale}";
}
} else {
die("Error ID: {$status['error']['id_error']}, \n".
"Error number: {$status['error']['error_number']}, \n".
"Error description: {$status['error']['error_description']}");
}
begin
status = client.get_sale_info({"id_sale" => id_sale})
rescue PeP::ClientError => e
# handle exceptions here
end
if client.success?
puts "Success, transaction completed, id_sale: #{id_sale}" if status['status'] == 'CLEARED'
else
puts "Error ID: #{status["error"]["id_error"]}, \n"\
"Error number: #{status["error"]["error_number"]}, \n"\
"Error description: #{status["error"]["error_description"]}"
exit
end
try:
status = client.get_sale_info({'id_sale': id_sale})
except Exception, e:
# handle exceptions here
if client.is_success():
if status['status'] == 'CLEARED':
print 'Success, transaction completed, id_sale: %s' % id_sale
else:
sys.exit('Error ID: ' + str(status["error"]["id_error"]) + '\n' \
'Error number: ' + str(status["error"]["error_number"]) + '\n' \
'Error description: ' + str(status["error"]["error_description"]))
api.saleInfo(idSale, new Callback<SaleInfoResult>() {
@Override
public void onFinish(SaleInfoResult result) {
// success
}
@HandleException
public void onProtocolError(ProtocolException e) {
// invoke if not success
// e.getCode() - error code
// e.getMessage() - error message
}
@Override
public void onError(Exception e) {
// connection error etc.
}
});
Zamiast sprawdzać statusy transakcji ręcznie, możesz po prostu skorzystać z mechanizmu powiadamiania o transakcjach. Nasze systemy same wyślą Ci stosowne informacje z użyciem POST – nie musisz wywoływać żadnych funkcji ani wysyłać żądań. Zobacz przykład aby dowiedzieć się jak możesz sprawdzić komunikację i odebrać powiadomienie.
// check communication
if (empty($_POST['communication_id'])) {
die('Empty communication id');
}
// check if token correct
if ('YOUR_TOKEN' !== $_POST['token']) {
die('Wrong token');
}
foreach ($_POST['content'] as $notification) {
if ($notification['type'] === 'S') { // sale created
// transaction completed, do something useful with id_sale
$id_sale = $notification['id_sale'];
}
}
// return communication_id
die($_POST['communication_id']);
# check communication
if params['communication_id'].blank?
print "Empty communication id"
exit
end
# check if token is correct
unless 'YOUR_TOKEN' == params['token']
print "Wrong token"
exit
end
@content = params['content']
# You can do something useful in Rails view later on
@content.each do |notification|
@id_sale = notification['id_sale'] if notification['type'] == 'S'
end
# render :text => params['communication_id']
# check communication
communication_id = get_request_param('communication_id')
if not communication_id:
sys.exit('Empty communication id')
# check if token correct
token = get_request_param('token')
if token != 'YOUR_TOKEN':
sys.exit('Wrong token')
#content = get_request_param('content')
content = [{'type': 'S', 'id_sale': 123456789}]
for notification in content:
if notification['type'] == 'S': # sale created
# transaction completed, do something useful with id_sale
id_sale = notification['id_sale']
# print communication_id
# Uwaga dot. Pythona:
# Funkcja get_request_param ma za zadanie pobrać wartości GET. Użyj odpowiednich funkcji oferowanych przez framework, z którego korzystasz, lub napisz własną funkcję.
# W przypadku Django możesz użyć:
# param_from_get = request.GET.get('param_name')
# W przypadku Pylons możesz użyć:
# from pylons import request
# param_from_get = request.GET.get('param_name')
Poniżej znajdziesz kilka przydatnych informacji, które sprawią, że wdrażanie płatności PeP Online będzie jeszcze łatwiejsze i wygodniejsze.
Zawsze korzystaj z konta testowego podczas integracji z Polskimi ePłatnościami Online. Każde konto tworzone na naszych stronach jest kontem testowym. Co istotne, żadne środki nigdy nie zostaną pobrane, zwrócone czy przetworzone w inny sposób, jeśli używasz konta testowego. Wszystko pozostaje zupełnie bezpieczne podczas wdrażania i testów, nawet jeśli coś pójdzie nie tak.
Zanim zaczniesz wywoływać metody naszego API, pamiętaj, aby poprawnie zainicjować PeP Online Rest Client. To bardzo łatwe, po prostu załącz odpowiedni plik oraz podaj swoją nazwę użytkownika i hasło.
include_once ('PePRestClient.php');
$client = new PePRestClient('your_login', 'your_password');
require 'pep_client'
client = PeP::Client.new('your_login', 'your_password')
from client import PePRestClient
client = PePRestClient("your_login", "your_password")
To bardzo łatwe – po prostu wprowadź odpowiedni kod błędu jako kwotę transakcji__.
Aby dobrze przeprowadzić testy, potrzebujesz oczywiście stosownego zestawu danych kart. Nie ma potrzeby, byś używał do testów własnej karty. Wprawdzie żadne środki nie zostaną z niej pobrane, jeśli korzystasz z konta testowego, to jednak z pewnością będziesz chciał przeprowadzić testy symulujące konkretne sytuacje, np. użycie różnego rodzaju kart. Poniżej znajduje się tabela z zestawem numerów testowych kart, których można używać do symulacji.
Możesz także wywołać konkretne błędy transakcji (dla celów testowych) wpisując kod błędu jako kwotę transakcji.
Numer | Wystawca | Test/przeznaczenie |
---|---|---|
4111111111111111 | Visa | Sale successful. |
4200000000000000 | Visa | Sale successful. |
5500000000000004 | MasterCard | Sale successful. |
370000000000002 | American Express | Sale successful. |
586824160825533338 | Maestro International | Sale successful. |
Numer | Wystawca | Test/przeznaczenie |
---|---|---|
4000000000000069 | Visa | 3-D Secure authentication is required.(sale error 700) |
4012001036275556 | Visa | Unable to verify card enrollment (enrollment check error 720) |
4012001038488884 | Visa | Unable to verify card enrollment (enrollment check error 720) |
4012001036298889 | Visa | Unable to verify card enrollment (enrollment check error 720) |
4012001038443335 | Visa | 3-D Secure Enrollment testing – card not enrolled in 3-D Secure |
4012001036853337 | Visa | Card enrolled, verification failed (sale error 703) |
4012001036983332 | Visa | Card enrolled, verification failed (sale error 703) |
4012001037490006 | Visa | Card enrolled, verification failed (sale error 703) |
4012001037461114 | Visa | Card enrolled, authentication failure (sale error 704) |
4012001037484447 | Visa | Card enrolled, authentication not available (sale error 725) |
Numer | Wystawca | Test/przeznaczenie |
---|---|---|
4055018123456780 | Visa | AVS result “X” (exact match) |
4055019123456788 | Visa | AVS result “Y” (exact match) |
4055010123456787 | Visa | AVS result “A” (ZIP mismatch) |
4055017123456782 | Visa | AVS result “W” (street mismatch) |
4055020123456786 | Visa | AVS result “Z” (street mismatch) |
4055013123456781 | Visa | AVS result “N” (ZIP and street mismatch) |
4055011123456785 | Visa | AVS result “E” (logical error/AVS not supported) |
4055012123456783 | Visa | AVS result “G” (logical error/AVS not supported) |
4055015123456786 | Visa | AVS result “S” (logical error/AVS not supported) |
4055016123456784 | Visa | AVS result “U” (logical error/AVS not supported) |
4055014123456789 | Visa | AVS result “R” (technical error/issuer not available) |
Jeśli chcesz wywołać konkretny błąd podczas integrowania się z systemami PeP Online (używając konta testowego), po prostu wprowadź odpowiedni kod błędu jako kwotę transakcji.
Kod błędu | Opis systemowy |
---|---|
302 | Direct debit is not accessible for this country [account_country_code]. |
303 | Direct debit declined. |
312 | Account holder name is not valid. |
313 | Customer name is not valid. |
314 | Customer e-mail is not valid. |
315 | Customer address (street and house) is not valid. |
316 | Customer city is not valid. |
317 | Customer zip code is not valid. |
318 | Customer state is not valid. |
319 | Customer country is not valid. |
320 | Amount is not valid. |
321 | Amount is too low. |
322 | Currency code is not valid. |
323 | Customer IP address is not valid. |
324 | Description is not valid. |
325 | Account country is not valid. |
326 | Bank code (SWIFT/BIC/BLZ) is not valid. |
327 | Account number is not valid. |
401 | Multiple same transactions lock triggered. Wait [number of seconds] s and try again. |
402 | Payment gateway problem. Please try again later. |
403 | Card declined. |
404 | Transaction in this currency [currency code] is not allowed. |
405 | Unknown payment method or method not set. |
406 | More than one payment method provided. Only one payment method is allowed. |
407 | Capture later not possible with this payment method. |
408 | Feature [feature] not available for this payment method. |
409 | Overriding default [feature] not allowed for this merchant account. |
410 | Unsupported payment method. |
411 | Card number format is not valid. |
412 | Card expiration year is not valid. |
413 | Card expiration month is not valid. |
414 | Card expiration year in the past. |
415 | Card has expired. |
416 | Card code (CVV2/CVC2/CID) format is not valid. |
417 | Name on card is not valid. |
418 | Cardholder name is not valid. |
419 | Cardholder e-mail is not valid. |
420 | Cardholder address (street and house) is not valid. |
421 | Cardholder city is not valid. |
422 | Cardholder zip is not valid. |
423 | Cardholder state is not valid. |
424 | Cardholder country is not valid |
425 | Amount is not valid. |
426 | Amount is too low. |
427 | Currency code is not valid. |
428 | Client IP is not valid. |
429 | Description is not valid. |
430 | Unknown card type or card number invalid. |
431 | Card issue number is not valid. |
432 | Fraud check on is not valid. |
433 | AVS level is not valid. |
441 | Sale Authorization ID is not valid. |
442 | Sale Authorization ID not found or the authorization has been closed. |
443 | Capture sale amount greater than the authorization amount. |
470 | Resale without card code is not allowed for this merchant account. |
471 | Sale ID is not valid. |
472 | Resale amount is not valid. |
473 | Amount is too low |
474 | Resale currency code is not valid. |
475 | Resale description is not valid. |
476 | Sale ID not found. |
477 | Cannot resale. Chargeback assigned to Sale ID. |
478 | Cannot resale this sale. |
479 | Card has expired. |
480 | Cannot resale. Reversal assigned to Sale ID. |
481 | Sale ID is not valid. |
482 | Refund amount is not valid. |
483 | Refund reason is not valid. |
484 | Sale ID not found. |
485 | Cannot refund. Chargeback assigned to Sale ID. |
486 | Cannot refund. Exceeded available refund amount. |
487 | Cannot refund. Sale is already completely refunded. |
488 | Cannot refund this sale. |
491 | Sale ID list is not set or empty |
492 | Sale ID list is too large (more than 100). |
493 | Sale ID [sale_id] at position [number] is not valid. |
501 | Internal server error. Please try again later. |
502 | Payment gateway error. Please try again later. |
503 | Payment method [payment_method_name] not allowed for this merchant account. |
505 | This merchant account is inactive. |
601 | Fraud attempt detected. Score is: [score] (range is 0-100). |
610 | Risk department rejection. |
611 | Blacklisted account number found. |
612 | Blacklisted card country found. |
613 | Blacklisted card number found. |
614 | Blacklisted customer country found. |
615 | Blacklisted customer email found. |
616 | Blacklisted customer IP address found. |
700 | 3-D Secure authentication is required. |
701 | 3-D Secure authentication server error. Please try again later or use card not enrolled in 3-D Secure. |
702 | 3-D Secure authentication server problem. Please try again later or use card not enrolled in 3-D Secure. |
703 | 3-D Secure authentication failed. Credit card cannot be accepted for payment. |
704 | 3-D Secure authentication failed. Card declined |
711 | Card number format is not valid. |
712 | Card expiration year is not valid. |
713 | Card expiration month is not valid. |
714 | Card has expired. |
715 | Amount is not valid. |
716 | Currency code is not valid. |
717 | Back URL is not valid. |
718 | Unknown card type or card number invalid. |
719 | Card issue number is not valid. |
720 | Unable to verify enrollment for 3-D Secure. You can perform a normal payment without 3-D Secure or decline the transaction. |
731 | Completed authentication with this Secure3d ID not found. |
732 | Sale and 3-D Secure card numbers are different. |
733 | Sale and 3-D Secure card expiration years are different. |
734 | Sale and 3-D Secure card expiration months are different. |
735 | Sale and 3-D Secure amounts are different. |
736 | Sale and 3-D Secure currency codes are different. |
737 | Sale with ID [id_sale] was performed for this Secure3d ID. |
780 | Service fee amount not set. |
781 | Sub-merchant ID not set. |
782 | Company cannot process sub-merchant transactions. |
783 | Invalid sub-merchant ID. |
784 | Sub-merchant is disabled. |
785 | Service fee amount is too low. |
786 | Invalid service fee amount. |
787 | Sub-merchant ID mismatch. |
Kod | Opis systemowy |
---|---|
A | Street address matches, but 5-digit and 9-digit postal codes do not match. |
B | Street address matches, but postal code not verified. |
C | Street address and postal code do not match. |
D | Street address and postal code match. |
E | AVS data is invalid or AVS is not allowed for this card type. |
F | Card member’s name does not match, but billing postal code matches. |
G | Non-U.S. issuing bank does not support AVS. |
H | Card member’s name does not match. Street address and postal code match. |
I | Address not verified. |
J | Card member’s name, billing address, and postal code match. |
K | Card member’s name matches but billing address and billing postal code do not match. |
L | Card member’s name and billing postal code match, but billing address does not match. |
M | Street address and postal code match. |
N | Street address and postal code do not match. |
O | Card member’s name and billing address match, but billing postal code does not match. |
P | Postal code matches, but street address not verified. |
Q | Card member’s name, billing address, and postal code match. |
R | System unavailable. |
S | Bank does not support AVS. |
T | Card member’s name does not match, but street address matches. |
U | Address information unavailable. Returned if the U.S. bank does not support non-U.S. AVS or if the AVS in a U.S. bank is notfunctioning properly. |
V | Card member’s name, billing address, and billing postal code match. |
W | Street address does not match, but 9-digit postal code matches. |
X | Street address and 9-digit postal code match. |
Y | Street address and 5-digit postal code match |
Z | Street address does not match, but 5-digit postal code matches. |
Powiadomienia o transakcjach to mechanizm ułatwiający automatyczną komunikację między Twoimi systemami i PeP Online.
Zarówno Ty, jak i Twoi klienci możecie inicjować wiele różnych operacji płatniczych (płatności, zwroty środków itd.), ale są przypadki, gdy chcesz po prostu sprawdzić ich statusy (np. czy płatność się powiodła, czy środki zostały ściągnięte). Są również operacje płatnicze, które odbywają się bez Twojego udziału, a o których z pewnością chciałbyś wiedzieć (np. chargebacki czy reversale). Dzięki powiadomieniom o transakcjach nie musisz ręcznie kontrolować i sprawdzać transakcji w Merchant Panelu ani czekać na powiadomienia mailowe od PeP Online.
Powiadomienia zostaną wygenerowane tylko dla transakcji o statusie SUCCES
, CHARGEBACK
lub REFUND
. Dla ERROR
i PENDING
powiadomienie nie zostanie wygenerowane
Aby uruchomić powiadomienia przechodzimy w naszym Merchant Panelu do zakładki Administracja >> Integracja >> Notyfikacje. Tam możemy dodać adres do powiadomień i dodatkowe zabezpieczenie (opcjonalne).
Możemy również w tej zakładce przetestować działanie powiadomień i podejrzeć ostatnie 50 powiadomień.
Notyfikacje są wysyłane w pakietach obejmujących maksymalnie 100 transakcji. Takie paczki są tworzone i wysyłane na bieżąco lub w odstępach 5-minutowych (zależy to od metody płatności). Jeśli pakiet nie zostanie wysłany pomyślnie za pierwszym razem, system będzie próbował wysłać go ponownie co 5 minut przez pierwszą godzinę, a później co godzinę. Jeśli pakiet notyfikacji nie zostanie odebrany przez Twój system przez określony czas (2 dni), stosowna informacja o tym zostanie wysłana do supportu Polskich ePłatności Online. Dzięki temu powiadomimy Cię o tym i pomożemy rozwiązać ewentualne problemy. Dla kont testowych, powiadomienia wysyłane są tylko raz.
Notyfikacje są wysyłane z użyciem HTTP POST. Aby odbierać notyfikacje od PeP Online, musisz napisać skrypt, który pozwoli Ci odbierać dane POST i zwrócić odpowiedź z określoną zawartością. Skrypt musi być dostępny z wykorzystaniem jednego z następujących protokołów:
Nazwa | Typ | Opis |
---|---|---|
content | array | Notification content (array of notification data arrays). |
content_size | integer | Size of the content array – number of notifications in package. |
communication_id | string(30) | Unique string identifying the notifications package. |
token string(50) | Optional. | Static string sent only if configured for merchant account. |
Tablica content zawiera tablice reprezentujące poszczególne notyfikacje. Przykładowe dane POST (w postaci tablicy PHP):
Nazwa | Typ | Opis |
---|---|---|
type | string(6) | Transaction type. You can find the full list on the Transaction types page. |
id | integer(10) Optional. | Filled only if notification is about other transaction type than sale (see type field). Accordingly, id field may represent id_refund, id_chargeback etc. |
id_sale | integer(10) | PeP Online sale ID number. If notification is about other transaction type than sale, this id points to related sale transaction. |
date | string(10) | Transaction date, YYYY-MM-DD format. |
amount | decimal(12,2) | Transaction amount (depending on the case: sale amount, refund amount etc.). |
currency_code | string(3) | Transaction currency code. |
text | string(200) UTF-8 encoded Optional. | Transaction description. Accordingly, it may be sale description, refund reason, chargeback reason etc. |
Przykładowe dane POST (w postaci tablicy PHP)
Array
(
[content] => Array
(
[0] => Array
(
[type] => S
[id_sale] => 123
[date] => 2012-05-29
[amount] => 12.34
[currency_code] => EUR
[text] => Product #1
)
[1] => Array
(
[type] => R
[id_sale] => 123
[id] => 99
[date] => 2012-05-30
[amount] => 12.34
[currency_code] => EUR
[text] => Money back guarantee
)
)
[content_size] => 2
[communication_id] => 2012-05-30 10:41:36 0002 00933
[token] => token
)
Skrypt powinien dawać odpowiedź HTTP o kodzie 200 (OK). W odpowiedzi powinna się znaleźć tylko wartość communication_id otrzymanego pakietu notyfikacji. Cokolwiek innego lub pusta strona zostanie zinterpretowane jako błąd
$user = "user";
$password = "password";
// check HTTP Basic authentication data
if (!isset($_SERVER['PHP_AUTH_USER']) || !isset($_SERVER['PHP_AUTH_PW'])
|| $user != $_SERVER['PHP_AUTH_USER'] || $password != $_SERVER['PHP_AUTH_PW']) {
// authentication failed
header("WWW-Authenticate: Basic realm=\"Secure Area\"");
header("HTTP/1.0 401 Unauthorized");
exit();
}
// check communication
if (empty($_POST['communication_id'])) {
die('Empty communication id');
}
// check if token correct
if ('YOUR_TOKEN' !== $_POST['token']) {
die('Wrong token');
}
foreach ($_POST['content'] as $notification) {
if ($notification['type'] === 'S') { // sale created
// transaction completed, do something useful with id_sale
$id_sale = $notification['id_sale'];
}
}
// return communication_id
die($_POST['communication_id']);
Typ | Opis systemowy |
---|---|
SA | Sale authorization. Only for card transactions in auth+capture model. Capture is indicated with “S” type notification. Associated with Sale Authorization ID in PeP Online system. |
S | Sale. Either card or Direct Debit. Associated with Sale ID in PeP Online system. |
R | Refund. Multiple refunds for single sale may be performed. Associated with Refund ID in PeP Online system. |
RV | Reversal. Direct Debit transactions-specific. Sale was reversed e.g. because funds were not available on charged account. |
RRO | Retrieval Request Open. Card transactions-specific. Request from bank for additional documents (sale proof). Unanswered retrieval requests in most cases result in chargeback being issued by the bank. |
RRA | Retrieval Request Answer. Indicates that answer for retrieval request was sent (either using Merchant Panel or through PeP Online Support). |
RRC | Retrieval Request Closed. End of retrieval request procedure. |
CB1O | Chargeback 1 Open. Card transaction-specific. First chargeback was issued. Associated with Chargeback ID in PeP Online system. |
CB1RR | Chargeback 1 Reject Request. Indicates that request for chargeback rejection was sent. Requests may be sent using Merchant Panel or through PeP Online Support (must be accompanied with sale proof documents). |
CB1RF | Chargeback 1 Reject Fulfilled. Sent documents were accepted by the bank and chargeback was successfully rejected. |
CB1RRC | Chargeback 1 Reject Request Cancellation. Chargeback rejection (CB1RF) was issued due to technical error and is cancelled. |
CB1R | Chargeback 1 Reversal. Chargeback (CB1O) was issued due to technical error and is reversed. |
CB1C | Chargeback 1 Closed. Chargeback procedure is closed (chargeback expires). Closed chargebacks cannot be contested. |
CB2O | Chargeback 2 Open. Second chargeback. May be issued only if first chargeback procedure is closed and first chargeback was successfully rejected. Procedure is similar to first chargeback. Associated with Chargeback ID in PeP Online system. |
CB2RR | Chargeback 2 Reject Request. See CB1RR. |
CB2RF | Chargeback 2 Reject Fulfilled. See CB1RF. |
CB2RRC | Chargeback 2 Reject Request Cancellation. See CB1RRC. |
CB2R | Chargeback 2 Reversal. See CB1R. |
CB2C | Chargeback 2 Closed. See CB1C. Closing second chargeback ends whole chargeback procedure. |
CAD | Compliance Arbitration Debit. Arbitration resulted in money returned to client. Treated similarly to chargeback in PeP Online system and associated with Chargeback ID. |
CAC | Compliance Arbitration Credit. Issued after CAD. Arbitration resulted in money returned to merchant. Treated similarly to successful chargeback rejection in PeP Online system. |
PAO | Pre-Arbitration or Pre-Compliance Open. Marks request for an arbitration which takes place before credit card company arbitral court. Such disputes can be initiated by merchant request in some especially difficult cases. |
PAA | Pre-Arbitration or Pre-Compliance Answer. Answer to previously made request for arbitration. |
PAC | Pre-Arbitration or Pre-Compliance Closed. End of Pre-Arbitration or Pre-Compliance phase. |
AO | Arbitration Open. Announces start of arbitration before credit card company court. Only if request for arbitration was accepted. |
EOR | End of Ruling. Closing of arbitral court hearing. |
OD | Objection Declined. Sent after RRA, CB1RR or CB2RR. Indicates that sent documents (for Retrieval Request or Chargeback Rejection) were not accepted. For retrieval request it usually means that chargeback will be issued, for chargebacks it means that chargeback stands. |
C | Cancellation. Notification from credit card issuer to merchant that no debit entries from the credit card in question will be accepted in the future. |
Integracja z systemami Polskich ePłatności Online pozwoli Ci stworzyć takie rozwiązanie, które będzie idealnie dopasowane do Twojego biznesu, a nawet pomoże zwiększyć Twoje dochody. Możesz nawet samodzielnie zaprojektować model biznesowy i wykorzystać nasze API, by przyjmować płatności w sposób, który najbardziej Ci odpowiada. Poniżej przedstawiamy kilka przykładów popularnych mechanizmów przyjmowania płatności – być może któryś z nich będzie pasował do Twojego biznesu (albo okaże się inspiracją do opracowania własnego modelu).
To oczywiście najpopularniejszy schemat zakupów online – klient każdą transakcję (a więc i płatność) inicjuje “ręcznie”.
“Klasyczne” zakupy online są oczywiście jak najbardziej poprawne, ale często sprzedawcy starają się je jakoś usprawnić. Przykładowo sklepy umożliwiają klientom zakładanie kont. Dzięki temu jeśli dana osoba powraca do sklepu, nie musi ponownie wpisywać danych do wysyłki, ponieważ ma je zapisane na koncie w tym sklepie. Dlaczego by więc nie zrobić tak samo z płatnościami? Oczywiście w tym przypadku dane są dużo bardziej wrażliwe. Jeśli jednak nie chcesz martwić się kwestiami bezpieczeństwa związanymi z przechowywaniem takich informacji po swojej stronie, zapewne ucieszy Cię wiadomość, że Polskie ePłatności Online mają taką usługę (co więcej, jest ona zupełnie darmowa!). Operujesz jedynie numerami ID, które odwołują się do rekordów w naszych bazach danych. Ponieważ nie przechowujesz żadnych wrażliwych danych, nie musisz tworzyć dodatkowych zabezpieczeń, przechodzić audytów itp. Możesz także dowolnie skrócić proces dokonywania płatności (choć jedno kliknięcie stanowi minimum). Pomyśl w ten sposób: masz dane klienta do wysyłki na swoim serwerze i dostęp do danych do płatności na naszych serwerach. To wystarczy, by przetworzyć płatność i tylko od Ciebie zależy w jaki sposób klient ją zainicjuje. Czy to będzie klasyczny koszyk, czy zakup kilkoma (albo nawet jednym!) kliknięciami – decyzja o modelu biznesowym należy do Ciebie.
Płatności cykliczne to rozwiązanie powszechnie stosowane m.in. w przypadku wszelkich subskrypcji czy abonamentów. Znakomicie sprawdza się przy prenumeratach za czasopisma (w tym elektroniczne), usługi online (np. miesięczne/roczne opłaty za konta pro w aplikacjach webowych/mobilnych) i tym podobnych.
Aby umożliwić Ci pobieranie opłat ze swojego konta, klient musi najpierw podać dane karty. Często dokonuje tego podczas pierwszej sprzedaży – każda następna płatność odbywa się automatycznie i odwołuje do tej pierwszej. W ten sposób niejako pierwsza sprzedaż stanowi upoważnienie dla sprzedawcy, umożliwiając mu pobieranie środków z karty klienta.
Tak więc w praktyce wygląda to następująco: klient kupuje coś po raz pierwszy (np. pierwszy numer e-czasopisma lub konto w Twojej usłudze), następnie na podstawie tej sprzedaży jesteś w stanie pobierać automatycznie (bez angażowania klienta) należność z karty (za kolejne wydania/okresy).
Bywają przypadki, kiedy sprzedawca nie chce pobierać opłaty od razu, stąd też istnieje alternatywa dla poprzedniego modelu. Klient nie musi faktycznie dokonać płatności przy pierwszej sprzedaży, by umożliwić Ci pobieranie należności automatycznie. Wystarczy Ci do tego autoryzacja jego karty.
Oczywiście dane karty nadal muszą zostać podane, także w wielu wypadkach różnica może być prawie niezauważalna (nie licząc faktu, że żadne pieniądze nie są pobierane). Są jednak modele biznesowe, dla których takie rozwiązanie sprawdza się całkiem dobrze.
Wyobraź sobie płatny dostęp do jakichś treści albo prenumeratę tygodnika. Dajesz tydzień czy dwa darmowego dostępu, by klient mógł zapoznać się z usługą, przetestować ją. Jeśli po tym czasie nie zrezygnuje, po prostu zaczynasz pobierać opłaty. Co więcej, jeśli oferujesz wiele subskrypcji i masz już zapisane dane klienta, wystarczy kliknięcie czy dwa, by zapisał się on do kolejnej. Klient nie musi się wiele wahać, zapisuje się do czegoś darmowego.
Dopiero gdy nie zrezygnuje, zaczniesz pobierać opłaty (podczas gdy on nie musi logować się i fatygować, by zapłacić, jeśli chce przejść z okresu testowego do płatnego). A jeśli zaczyna Ci to brzmieć odrobinę znajomo, to podpowiadamy: dokładnie tak robi m.in. Amazon, gdy sprzedaje prenumeraty na Kindle.
Tokenizacja umożliwia dokonywanie transakcji z wykorzystaniem tokenu, po uprzednim ztokenizowaniu karty płatniczej. Dostępna jest ona wyłącznie na wybranych kontach merchanckich, na których taka usługa została uruchomiona. Można przy jej użyciu płacić kartami Visa oraz MasterCard.
W przypadku tokenizacji adres endpointa do secure forma zmienia się z https://secure.pep.pl/order/cart.html
na https://secure.pep.pl/order.html
W przypadku chęci użycia tokenizacji wymagane są specyficzne dane przekazywane do secure-forma. Jako transaction_type konieczne jest podanie wartości "T" a ponadto zmieniają się wymagania odnośnie poniższych pól:
Pole | Format | Wymagane | Opis |
---|---|---|---|
customer_id | string(12) - tylko znaki numeryczne | tak | identyfikator płatnika w systemie Merchanta. |
description | string(1-255) | tak | Tylko znaki alfanumeryczne. Identyfikator transakcji, który zostanie przekazany do systemu PeP Online. Wartość pola musi być unikalna dla każdej transakcji! Zalecamy by wartością tego pola był identyfikator transakcji w Twoim systemie (sklepie). Będzie później widoczny w Merchant Panelu jako opis danej transakcji. |
amount | decimal(12,2) | tak | Używaj kropki (.) jako separatora dziesiętnego. Całkowita kwota do pobrania. |
currency | string(3) | tak | Kod waluty ISO 4217, kwota określona w wartości amount będzie pobrana w tej walucie (na przykład “PLN” lub “EUR”). |
hash_type | string(8) | nie | SHA256 |
Metoda cards/sale umożliwia przeprowadzenie pojedynczej płatności z użyciem karty (kredytowej, debetowej, przedpłaconej itd.). Uwzględnia dodatkowe mechanizmy bezpieczeństwa, takie jak AVS czy fraud check.
Struktura zapytania
required | object (Sale) A structure containing sale information. |
required | object (Customer) A structure containing customer data. |
required | object (Card) A structure containing card information |
{- "sale": {
- "amount": "100.00",
- "currency": "EUR",
- "description": "TR001",
- "fraud_check_on": true,
- "avs_check_level": 2,
- "id_sub_merchant": 3128,
- "service_fee_amount": 0.3
}, - "customer": {
- "name": "John Doe",
- "email": "john@doe.com",
- "ip": "123.456.78.90",
- "address": {
- "street_house": "1600 Pennsylvania Avenue Northwest",
- "city": "Washington",
- "state": "DC",
- "zip": "20500",
- "country_code": "US"
}
}, - "card": {
- "card_number": "4111111111111111",
- "expiration_month": "03",
- "expiration_year": "2017",
- "name_on_card": "John Doe",
- "card_code": "123"
}
}
Metoda cards/saleByToken umożliwia przeprowadzenie pojedynczej płatności z użyciem karty (kredytowej, debetowej, przedpłaconej itd.). Uwzględnia dodatkowe mechanizmy bezpieczeństwa, takie jak AVS czy fraud check.
Struktura zapytania
required | object (Sale) A structure containing sale information. |
required | object (Customer) A structure containing customer data. |
required | object (Token) A structure containing card information |
{- "sale": {
- "amount": "100.00",
- "currency": "EUR",
- "description": "TR001",
- "fraud_check_on": true,
- "avs_check_level": 2,
- "id_sub_merchant": 3128,
- "service_fee_amount": 0.3
}, - "customer": {
- "name": "John Doe",
- "email": "john@doe.com",
- "ip": "123.456.78.90",
- "address": {
- "street_house": "1600 Pennsylvania Avenue Northwest",
- "city": "Washington",
- "state": "DC",
- "zip": "20500",
- "country_code": "US"
}
}, - "card": {
- "token": "12a34b45c67d89e00f1aa2bb3cc4dd5ee6ff12a34b45c67d89e00f1aa2bb3cc4"
}
}
Metoda cards/generateToken tworzy tymczasowy, unikalny token dla podanego zestawu danych karty. Token jest ważny przez 15 minut od utworzenia.
Struktura zapytania
public_api_key required | string <40 characters> Your Public API Key. |
card_number required | string <13-19 digits> The full number of the card without any whitespaces. Only digits are allowed. |
expiration_month required | string <2 digits, 01…12> Expiration month. 01 to 12. |
expiration_year required | string <4 digits> Expiration year as on the card. |
name_on_card required | string <2-50 characters, UTF-8 encoded> Cardholder name as written on the card. |
card_code required | string <3-4 digits> Depending on the type of the card this will be either CVV2 (Visa), CVC2 (MasterCard) or CID (American Express) |
{- "public_api_key": "71426338751d8c8e454a13fa4c44a3094cbab89c",
- "card_number": "4111111111111111",
- "expiration_month": "2017",
- "expiration_year": "71426338751d8c8e454a13fa4c44a3094cbab89c",
- "name_on_card": "John Doe",
- "card_code": "123"
}
Metoda cards/check sprawdza, czy podany numer karty jest prawidłowy oraz rozpoznaje wystawcę karty.
Struktura zapytania
card_number required | string <13-19 digits> The full number of the card without any whitespaces. Only digits are allowed. |
{- "card_number": "4200000000000000"
}
Metoda cards/checkByToken sprawdza, czy podany numer karty jest prawidłowy oraz rozpoznaje wystawcę karty.
Struktura zapytania
token required | string <64 chars> A unique string that identifies a specific card. It’s generated by PeP when making a payment and remains active for 15 minutes. |
{- "token": "12a34b45c67d89e00f1aa2bb3cc4dd5ee6ff12a34b45c67d89e00f1aa2bb3cc4"
}
Metoda paypal/sale umożliwia przeprowadzenie płatności z użyciem konta PayPal.
Struktura zapytania
required | object (SaleForPayPal) A structure containing sale information. |
back_url required | string <10-255 characters, UTF-8 encoded> Website address where a customer will be redirected after performing the payment. |
object (Recurring) A structure containing recurring profile information. |
{- "sale": {
- "amount": "100.00",
- "currency": "EUR",
- "description": "TR001"
}, - "recurring": {
- "amount": "100.00",
- "start_date": "2022-01-01",
- "period": "day"
}
}
Metoda paypal/stopRecurring umożliwia zatrzymanie aktywnego profilu recurringowego PayPala.
Struktura zapytania
id_paypal_recurring required | integer <unsigned long> Identification number of recurring profile. |
{- "id_paypal_recurring": 1
}
Metoda banktransfers/sale umożliwia przeprowadzenie płatności z wykorzystaniem przelewu bankowego.
Struktura zapytania
required | object (Sale) A structure containing sale information. |
required | object (Customer) A structure containing customer data. |
back_url required | string <10-255 characters, UTF-8 encoded> Website address where a customer will be redirected after performing the payment. |
payment_type required | string <2-4 characters> Enum: "AB" "AS" "MT" "IN" "IP" "MI" "CA" "PP" "PCZ" "IB" "PO" "GB" "IG" "WB" "PB" "CT" "PL" "NP" "BS" "NB" "RF" "PBS" "SGB" "BLIK" "OH" Bank code:
|
{- "sale": {
- "amount": "100.00",
- "currency": "EUR",
- "description": "TR001",
- "fraud_check_on": true,
- "avs_check_level": 2,
- "id_sub_merchant": 3128,
- "service_fee_amount": 0.3
}, - "customer": {
- "name": "John Doe",
- "email": "john@doe.com",
- "ip": "123.456.78.90",
- "address": {
- "street_house": "1600 Pennsylvania Avenue Northwest",
- "city": "Washington",
- "state": "DC",
- "zip": "20500",
- "country_code": "US"
}
},
}
Metoda directdebits/sale umożliwia przeprowadznei płatności Direct Debit.
Struktura zapytania
required | object (Sale) A structure containing sale information. |
required | object (Customer) A structure containing customer data. |
required | object (Account) A structure containing account data. |
{- "sale": {
- "amount": "100.00",
- "currency": "EUR",
- "description": "TR001",
- "fraud_check_on": true,
- "avs_check_level": 2,
- "id_sub_merchant": 3128,
- "service_fee_amount": 0.3
}, - "customer": {
- "name": "John Doe",
- "email": "john@doe.com",
- "ip": "123.456.78.90",
- "address": {
- "street_house": "1600 Pennsylvania Avenue Northwest",
- "city": "Washington",
- "state": "DC",
- "zip": "20500",
- "country_code": "US"
}
}, - "account": {
- "iban": "DE12345678901234567890",
- "bic": "BICBICDE",
- "account_holder": "John Doe",
- "account_country": "DE",
- "mandate_id": "54321"
}
}
Metoda sofort/sale umożliwia przeprowadzenie płatności w wykorzystaniem systemu SOFORT Banking.
Struktura zapytania
required | object (Sale) A structure containing sale information. |
required | object (Customer) A structure containing customer data. |
back_url required | string <10-255 characters, UTF-8 encoded> Website address where a customer will be redirected after performing the payment. |
{- "sale": {
- "amount": "100.00",
- "currency": "EUR",
- "description": "TR001",
- "fraud_check_on": true,
- "avs_check_level": 2,
- "id_sub_merchant": 3128,
- "service_fee_amount": 0.3
}, - "customer": {
- "name": "John Doe",
- "email": "john@doe.com",
- "ip": "123.456.78.90",
- "address": {
- "street_house": "1600 Pennsylvania Avenue Northwest",
- "city": "Washington",
- "state": "DC",
- "zip": "20500",
- "country_code": "US"
}
},
}
Metoda applepay/sale umożliwia przeprowadzenie pojedynczej transakcji z użyciem tokenu płatniczego Apple Pay.
Struktura zapytania
required | object (Sale) A structure containing sale information. |
required | object (Customer) A structure containing customer data. |
required | object (ApplePayToken) A structure containing card information |
{- "sale": {
- "amount": "100.00",
- "currency": "EUR",
- "description": "TR001",
- "fraud_check_on": true,
- "avs_check_level": 2,
- "id_sub_merchant": 3128,
- "service_fee_amount": 0.3
}, - "customer": {
- "name": "John Doe",
- "email": "john@doe.com",
- "ip": "123.456.78.90",
- "address": {
- "street_house": "1600 Pennsylvania Avenue Northwest",
- "city": "Washington",
- "state": "DC",
- "zip": "20500",
- "country_code": "US"
}
}, - "card": {
- "token": "eyJwYXltZW50RGF0YSI6eyJ2ZXJzaW9uIjoiRUNfdjEiLCJkYXRhIjoicFpkZERNL2VmQm1qZ0drTk1RUmJncjM3VjdXVzhVMW40WlNXRjZzK2R4ZHBSMVRpbmI1aFlVVXRnQVBRRGZSV3NmR21ldEQ5RUF0cGFRTThPbEJGS21sdThKUXkrSUNhOXMyeDdSY3hFV1A4NXBsWWxNWjgvNkMwQWhLSGNEdkhuaW01VHZLVUZVY0NoeXhHNVlrNDhENUZObGl0OG0yL0dnWmkxVXkwS1RwTTZzZVMwMGpuRHl1a3hCenJmOGRVMFkrTzRSSWFPODhkNS9OSlA1ZVNnay8vVTlHb1lWUXBjZjQzL3BQbGt4ZUgrRGhwSVFuRHRza0ZhTFpNSkhaKzU3YUZUbVYvcXBPdHRmQ1dZRFp2MWF1aEUrRUJsbHltYmVCcUZUR21ySUt1NmFYNC83VEE0MXppalAyS1ZwaW5MOFUwaEg0Z2I2ZWZ4eVVOWHlPZVBJQXdzdUNqRkRKMmw2citySWhJZ05qdi9WQzdCYzBjelp4d29NKy9NRjRWNFJUb2gzUjZtU1ZiaGxTU1F2cWNwQnAvZDlFc3Z5aHFlVEVZT3YrUGF3PT0iLCJzaWduYXR1cmUiOiJNSUFHQ1NxR1NJYjNEUUVIQXFDQU1JQUNBUUV4RHpBTkJnbGdoa2dCWlFNRUFnRUZBRENBQmdrcWhraUc5dzBCQndFQUFLQ0FNSUlENGpDQ0E0aWdBd0lCQWdJSUpFUHlxQWFkOVhjd0NnWUlLb1pJemowRUF3SXdlakV1TUN3R0ExVUVBd3dsUVhCd2JHVWdRWEJ3YkdsallYUnBiMjRnU1c1MFpXZHlZWFJwYjI0Z1EwRWdMU0JITXpFbU1DUUdBMVVFQ3d3ZFFYQndiR1VnUTJWeWRHbG1hV05oZEdsdmJpQkJkWFJvYjNKcGRIa3hFekFSQmdOVkJBb01Da0Z3Y0d4bElFbHVZeTR4Q3pBSkJnTlZCQVlUQWxWVE1CNFhEVEUwTURreU5USXlNRFl4TVZvWERURTVNRGt5TkRJeU1EWXhNVm93WHpFbE1DTUdBMVVFQXd3Y1pXTmpMWE50Y0MxaWNtOXJaWEl0YzJsbmJsOVZRelF0VUZKUFJERVVNQklHQTFVRUN3d0xhVTlUSUZONWMzUmxiWE14RXpBUkJnTlZCQW9NQ2tGd2NHeGxJRWx1WXk0eEN6QUpCZ05WQkFZVEFsVlRNRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUV3aFYzN2V2V3g3SWhqMmpkY0pDaElZM0hzTDF2TENnOWhHQ1YyVXIwcFVFYmcwSU8yQkh6UUg2RE14OGNWTVAzNnpJZzFyclYxTy8wa29tSlBud1BFNk9DQWhFd2dnSU5NRVVHQ0NzR0FRVUZCd0VCQkRrd056QTFCZ2dyQmdFRkJRY3dBWVlwYUhSMGNEb3ZMMjlqYzNBdVlYQndiR1V1WTI5dEwyOWpjM0F3TkMxaGNIQnNaV0ZwWTJFek1ERXdIUVlEVlIwT0JCWUVGSlJYMjIvVmRJR0dpWWwyTDM1WGhRZm5tMWdrTUF3R0ExVWRFd0VCL3dRQ01BQXdId1lEVlIwakJCZ3dGb0FVSS9KSnhFK1Q1TzhuNXNUMktHdy9vcnY5TGtzd2dnRWRCZ05WSFNBRWdnRVVNSUlCRURDQ0FRd0dDU3FHU0liM1kyUUZBVENCL2pDQnd3WUlLd1lCQlFVSEFnSXdnYllNZ2JOU1pXeHBZVzVqWlNCdmJpQjBhR2x6SUdObGNuUnBabWxqWVhSbElHSjVJR0Z1ZVNCd1lYSjBlU0JoYzNOMWJXVnpJR0ZqWTJWd2RHRnVZMlVnYjJZZ2RHaGxJSFJvWlc0Z1lYQndiR2xqWVdKc1pTQnpkR0Z1WkdGeVpDQjBaWEp0Y3lCaGJtUWdZMjl1WkdsMGFXOXVjeUJ2WmlCMWMyVXNJR05sY25ScFptbGpZWFJsSUhCdmJHbGplU0JoYm1RZ1kyVnlkR2xtYVdOaGRHbHZiaUJ3Y21GamRHbGpaU0J6ZEdGMFpXMWxiblJ6TGpBMkJnZ3JCZ0VGQlFjQ0FSWXFhSFIwY0RvdkwzZDNkeTVoY0hCc1pTNWpiMjB2WTJWeWRHbG1hV05oZEdWaGRYUm9iM0pwZEhrdk1EUUdBMVVkSHdRdE1Dc3dLYUFub0NXR0kyaDBkSEE2THk5amNtd3VZWEJ3YkdVdVkyOXRMMkZ3Y0d4bFlXbGpZVE11WTNKc01BNEdBMVVkRHdFQi93UUVBd0lIZ0RBUEJna3Foa2lHOTJOa0JoMEVBZ1VBTUFvR0NDcUdTTTQ5QkFNQ0EwZ0FNRVVDSUhLS253K1NveXE1bVhRcjFWNjJjMEJYS3BhSG9kWXU5VFdYRVBVV1BwYnBBaUVBa1RlY2ZXNitXNWwwcjBBRGZ6VENQcTJZdGJTMzl3MDFYSWF5cUJOeThiRXdnZ0x1TUlJQ2RhQURBZ0VDQWdoSmJTKy9PcGphbHpBS0JnZ3Foa2pPUFFRREFqQm5NUnN3R1FZRFZRUUREQkpCY0hCc1pTQlNiMjkwSUVOQklDMGdSek14SmpBa0JnTlZCQXNNSFVGd2NHeGxJRU5sY25ScFptbGpZWFJwYjI0Z1FYVjBhRzl5YVhSNU1STXdFUVlEVlFRS0RBcEJjSEJzWlNCSmJtTXVNUXN3Q1FZRFZRUUdFd0pWVXpBZUZ3MHhOREExTURZeU16UTJNekJhRncweU9UQTFNRFl5TXpRMk16QmFNSG94TGpBc0JnTlZCQU1NSlVGd2NHeGxJRUZ3Y0d4cFkyRjBhVzl1SUVsdWRHVm5jbUYwYVc5dUlFTkJJQzBnUnpNeEpqQWtCZ05WQkFzTUhVRndjR3hsSUVObGNuUnBabWxqWVhScGIyNGdRWFYwYUc5eWFYUjVNUk13RVFZRFZRUUtEQXBCY0hCc1pTQkpibU11TVFzd0NRWURWUVFHRXdKVlV6QlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJQQVhFWVFaMTJTRjFScGVKWUVIZHVpQW91L2VlNjVONEkzOFM1UGhNMWJWWmxzMXJpTFFsM1lOSWs1N3VnajlkaGZPaU10MnUyWnd2c2pvS1lUL1ZFV2pnZmN3Z2ZRd1JnWUlLd1lCQlFVSEFRRUVPakE0TURZR0NDc0dBUVVGQnpBQmhpcG9kSFJ3T2k4dmIyTnpjQzVoY0hCc1pTNWpiMjB2YjJOemNEQTBMV0Z3Y0d4bGNtOXZkR05oWnpNd0hRWURWUjBPQkJZRUZDUHlTY1JQaytUdkorYkU5aWhzUDZLNy9TNUxNQThHQTFVZEV3RUIvd1FGTUFNQkFmOHdId1lEVlIwakJCZ3dGb0FVdTdEZW9WZ3ppSnFraXBuZXZyM3JyOXJMSktzd053WURWUjBmQkRBd0xqQXNvQ3FnS0lZbWFIUjBjRG92TDJOeWJDNWhjSEJzWlM1amIyMHZZWEJ3YkdWeWIyOTBZMkZuTXk1amNtd3dEZ1lEVlIwUEFRSC9CQVFEQWdFR01CQUdDaXFHU0liM1kyUUdBZzRFQWdVQU1Bb0dDQ3FHU000OUJBTUNBMmNBTUdRQ01EclBjb05SRnBteGh2czF3MWJLWXIvMEYrM1pEM1ZOb282KzhaeUJYa0szaWZpWTk1dFpuNWpWUVEyUG5lbkMvZ0l3TWkzVlJDR3dvd1YzYkYzek9EdVFaLzBYZkN3aGJaWlB4bkpwZ2hKdlZQaDZmUnVaeTVzSmlTRmhCcGtQQ1pJZEFBQXhnZ0dNTUlJQmlBSUJBVENCaGpCNk1TNHdMQVlEVlFRRERDVkJjSEJzWlNCQmNIQnNhV05oZEdsdmJpQkpiblJsWjNKaGRHbHZiaUJEUVNBdElFY3pNU1l3SkFZRFZRUUxEQjFCY0hCc1pTQkRaWEowYVdacFkyRjBhVzl1SUVGMWRHaHZjbWwwZVRFVE1CRUdBMVVFQ2d3S1FYQndiR1VnU1c1akxqRUxNQWtHQTFVRUJoTUNWVk1DQ0NSRDhxZ0duZlYzTUEwR0NXQ0dTQUZsQXdRQ0FRVUFvSUdWTUJnR0NTcUdTSWIzRFFFSkF6RUxCZ2txaGtpRzl3MEJCd0V3SEFZSktvWklodmNOQVFrRk1ROFhEVEU0TURjeE9URXpORGt6TVZvd0tnWUpLb1pJaHZjTkFRazBNUjB3R3pBTkJnbGdoa2dCWlFNRUFnRUZBS0VLQmdncWhrak9QUVFEQWpBdkJna3Foa2lHOXcwQkNRUXhJZ1FnR1ZOZlJESkZIclBYR0M0Z3MrTWJaZmtKZ2xXbkxKcDNoOTFkb2laTHVISXdDZ1lJS29aSXpqMEVBd0lFUnpCRkFpRUEvai9SV2hFZER4dEhSdlF3VlNTK1V5azNBbnE5ZmIwa09uMGl5d21jTGdFQ0lDNWN1Y0FRSXk1SHI5UzhqWHRWREJsU2lpeDBDYnVsRlppOGR6bUZ3RkZxQUFBQUFBQUEiLCJoZWFkZXIiOnsiZXBoZW1lcmFsUHVibGljS2V5IjoiTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFWmUrMlc5cTNyTEFETnNrNVdxc0VmR2cvQ01pdXNOWVpYdlJIeVZMWEowcFRSQ0VUR1dLQjl2dzNHZm9IZnA2RFFrK2FFTGxGeXFSRUswZC9MRDlWM1E9PSIsInB1YmxpY0tleUhhc2giOiJIYVZ4ZmdDUnVkOFpsRk1FWHZiTk1yNlk1MlhLQTNFaDljY0kveXR4eGxnPSIsInRyYW5zYWN0aW9uSWQiOiI4N2Q4MWIxNGQ1MzU4ZmFkZjE1ZjU1MWI5ZTM2MTg1Mzc4N2IyNjA2ZTM3MTY2Y2JkN2NhZjdmZWI5ZTczZDg3In19LCJwYXltZW50TWV0aG9kIjp7ImRpc3BsYXlOYW1lIjoiVmlzYSAxNDQ1IiwibmV0d29yayI6IlZpc2EiLCJ0eXBlIjoiZGViaXQifSwidHJhbnNhY3Rpb25JZGVudGlmaWVyIjoiODdEODFCMTRENTM1OEZBREYxNUY1NTFCOUUzNjE4NTM3ODdCMjYwNkUzNzE2NkNCRDdDQUY3RkVCOUU3M0Q4NyJ9"
}
}
Metoda googlepay/sale umożliwia przeprowadzenie pojedynczej transakcji z użyciem tokenu płatniczego Google Pay.
Struktura zapytania
required | object (Sale) A structure containing sale information. |
required | object (Customer) A structure containing customer data. |
required | object (GooglePayToken) A structure containing card information |
{- "sale": {
- "amount": "100.00",
- "currency": "EUR",
- "description": "TR001",
- "fraud_check_on": true,
- "avs_check_level": 2,
- "id_sub_merchant": 3128,
- "service_fee_amount": 0.3
}, - "customer": {
- "name": "John Doe",
- "email": "john@doe.com",
- "ip": "123.456.78.90",
- "address": {
- "street_house": "1600 Pennsylvania Avenue Northwest",
- "city": "Washington",
- "state": "DC",
- "zip": "20500",
- "country_code": "US"
}
}, - "card": {
- "token": "eyJzaWduYXR1cmUiOiJNRVlDSVFDcUE1T0Vpd1ptR29GNlVqUEI3MktBNWtOa2lyUE5WMGN0T1A4Uytwam1qd0loQUo1QjVXa3Vnd1JhNWk3enRUWjE4eHBEWjJXK0hNTjh3a0M2SFFCZ3ZyUWkiLCJwcm90b2NvbFZlcnNpb24iOiJFQ3YxIiwic2lnbmVkTWVzc2FnZSI6IntcImVuY3J5cHRlZE1lc3NhZ2VcIjpcIlJnSGV1UVA4OVFpa1FDZmtLemRia1g3dU4wUE8zSmFDcE5hRHRhQ1ZkQ0ErZFkvL0VyRzZvQ1NZZ3Yyc3dONkdaRmZwd09zL1ZiVTNjcVFLRC81YXRNQVV5STNidnZpOGRxcXlOb0J4aTVkUi9tbS9OZmRJdHpSdEE3YXovSndMTEpreGNOMzRLZHNQV3VhVHhRZ2MyWFBCUkN2TVpLeUQ1VWNuY1U4cktKSEhnSWlNZEMwUnhNU0Uxc1RVWEwxVDk0eURJck9jdlNlcmRYdnpLZGhUOUQxcUl0azA2VW5uc2dhRHFWdGg0SHMyY1hTUFVJYlNIc25ydlRsZGg2dGlkOTF2WWZRYldYeElqQUF1ZFRQME8xR25oTnJjYXo5WjBxeUVWUEVQQnVzc29kWU1pL1JQa3VNREh6TU1sUUV2Mms3SXBtdDZJZGVnd0t5L21VYlFNeld1NDdzc2Jmb2xWbW1vOGRrTlJhYmo5Z0dtQWwrL1ErelY1MUNPeG5CSWhBUHU2NUMwZ3RuTi8yZWJMNnZNdWQxbE5xRXV0WVd4alpGRWY4Q2ZkZ3lQM3M5WXdYWXdoenRTTi9ycGhCV1hpWmNOT29Ea2xxWWEvSVphT2o0TnVnNVdLU3hka2pVazhmSTJiNlV2ZEIwbHMrakpuenZRdStzUndlWHZoNmRRa2JuazhGS3VKeVdkZGl2c3NJcjlJZW1Jc3JFOUE5T3FlSnpWOVRjSThRb01ZWmNiQUZkcUlBRjhWTUJLSjMwU28yYyt4SnU5b21FUy9QbFVXU1hJdXltL1hXMldhd1xcdTAwM2RcXHUwMDNkXCIsXCJlcGhlbWVyYWxQdWJsaWNLZXlcIjpcIkJGZzZoNWZkQ0RIbWFNODlNN0VKOVdyWHVkZWh3bzFrci8rWmdNZDJiUE5NNmhHVVZRZVp2VHRZSm5ua1dGY2JVODZteXU0WmduM2VyL05pMUNwVFk1RVxcdTAwM2RcIixcInRhZ1wiOlwiY3NzcXNmcnJpSDRwSzlUQmJPRWpSMDc2Slc2YWNKL3JEQ3JHTUpaLzFaa1xcdTAwM2RcIn0ifQ"
}
}
Metoda blik/sale to transparentna płatność kodem BLIK (BLIK level 0).
Struktura zapytania
required | object (Sale) A structure containing sale information. |
required | object (Customer) A structure containing customer data. |
code required | string <6 digits> Only digits are allowed. For test account CODE only ex. 123456 |
{- "sale": {
- "amount": "100.00",
- "currency": "EUR",
- "description": "TR001",
- "fraud_check_on": true,
- "avs_check_level": 2,
- "id_sub_merchant": 3128,
- "service_fee_amount": 0.3
}, - "customer": {
- "name": "John Doe",
- "email": "john@doe.com",
- "ip": "123.456.78.90",
- "address": {
- "street_house": "1600 Pennsylvania Avenue Northwest",
- "city": "Washington",
- "state": "DC",
- "zip": "20500",
- "country_code": "US"
}
}, - "code": 123456
}
Metoda refunds umożliwia dokonanie zwrotu środków w odniesieniu do konkretnej transakcji (niezależnie od rodzaju metody płatności).
Struktura zapytania
id_sale required | integer <unsigned long> Identification number of the sale that should be refunded. |
amount required | decimal <12,2> Amount to be refunded (always a positive value). Note that partial refunds are possible and can be issued up to the amount of the original transaction. |
reason required | string <2-200 characters> A reason for the refund. Should be always entered, as the refund ratio should be kept on the reasonable low level. PeP risk management team will occasionally check the reason fields of the merchant when the refund ratio is too high. |
{- "id_sale": 1234567,
- "amount": 15,
- "reason": "Special discount."
}
Metoda refunds/info zwraca dane o zwrocie/zwrotach
Struktura zapytania
id_sale required | integer <unsigned long> Identification number of the sale that should be refunded. |
{- "id_sale": 1234567
}
Metoda sales/info zwraca dane o transakcji, które pozwalają na określenie statusu płatności (włącznie z tym, czy środki były zwracane).
Struktura zapytania
id_sale required | integer <unsigned long> Identification number of a sale. |
{- "id_sale": 12345
}
Metoda sale/status umożliwia pobranie statusu pojedynczej transakcji w momencie, gdy nie jest znany jej numer ID. Jeśli numer ID jest znany, należy użyć metody sales/info.
Struktura zapytania
amount required | decimal <12,2> Amount of the performed sale. |
currency required | string <3 characters> Currency code of the performed sale. ISO 4217 format, all uppercase. |
description required | string <2-200 characters, UTF-8 encoded> Transaction Identifier will be sent to PeP's system. The field value needs to be unique for each transaction! We recommend that the value of this field is the transaction id in your system (store). It will later be visible in the Merchant Panel as a description of the transaction. Only alphanumeric characters are allowed. |
{- "amount": 45,
- "currency": "EUR",
- "description": "TR001"
}
Metoda resales/sale umożliwia przeprowadzenie transakcji na podstawie wcześniej wykonanej płatności. Dzięki takiemu odniesieniu metoda nie wymaga podawania kompletnych danych (np. karty) i pozwala na szybsze dokonanie płatności.
Struktura zapytania
id_sale required | integer <unsigned long> Identification number of a sale. |
amount required | decimal <12,2> The total amount of the sale. Use dot (.) as decimal separator. |
currency required | string <3 characters> Transaction currency code. ISO 4217 format, all uppercase. |
description required | string <2-200 characters, UTF-8 encoded> Transaction Identifier will be sent to PeP's system. The field value needs to be unique for each transaction! We recommend that the value of this field is the transaction id in your system (store). It will later be visible in the Merchant Panel as a description of the transaction. Only alphanumeric characters are allowed. |
id_sub_merchant | integer <unsigned long> Sub-merchant ID, available in Merchant Panel after Sub-merchant profile is confirmed. |
service_fee_amount | decimal <12,2> This fee will be subtracted from amount and sent to the master merchant. |
{- "id_sale": 436635,
- "amount": 4.99,
- "currency": "EUR",
- "description": "TR001",
- "id_sub_merchant": 3128,
- "service_fee_amount": 0.3
}
Metoda 3DSecure/checkCard sprawdza, czy karta uczestniczy w programie 3-D Secure – to pierwszy krok podczas przeprowadzania płatności z użyciem tego zabezpieczenia.
Struktura zapytania
required | object (Sale) A structure containing sale information. |
required | object (Customer) A structure containing customer data. |
required | object (Card) A structure containing card information |
back_url required | string <2-200 characters, UTF-8 encoded> Website address where a customer will be redirected after performing the payment. |
{- "sale": {
- "amount": "100.00",
- "currency": "EUR",
- "description": "TR001",
- "fraud_check_on": true,
- "avs_check_level": 2,
- "id_sub_merchant": 3128,
- "service_fee_amount": 0.3
}, - "customer": {
- "name": "John Doe",
- "email": "john@doe.com",
- "ip": "123.456.78.90",
- "address": {
- "street_house": "1600 Pennsylvania Avenue Northwest",
- "city": "Washington",
- "state": "DC",
- "zip": "20500",
- "country_code": "US"
}
}, - "card": {
- "card_number": "4111111111111111",
- "expiration_month": "03",
- "expiration_year": "2017",
- "name_on_card": "John Doe",
- "card_code": "123"
},
}
Metoda 3DSecure/checkCardByToken sprawdza, czy karta uczestniczy w programie 3-D Secure – to pierwszy krok podczas przeprowadzania płatności z użyciem tego zabezpieczenia.
Struktura zapytania
required | object (Sale) A structure containing sale information. |
required | object (Customer) A structure containing customer data. |
required | object (Token) A structure containing card information |
back_url required | string <2-200 characters, UTF-8 encoded> Website address where a customer will be redirected after performing the payment. |
{- "sale": {
- "amount": "100.00",
- "currency": "EUR",
- "description": "TR001",
- "fraud_check_on": true,
- "avs_check_level": 2,
- "id_sub_merchant": 3128,
- "service_fee_amount": 0.3
}, - "customer": {
- "name": "John Doe",
- "email": "john@doe.com",
- "ip": "123.456.78.90",
- "address": {
- "street_house": "1600 Pennsylvania Avenue Northwest",
- "city": "Washington",
- "state": "DC",
- "zip": "20500",
- "country_code": "US"
}
}, - "card": {
- "token": "12a34b45c67d89e00f1aa2bb3cc4dd5ee6ff12a34b45c67d89e00f1aa2bb3cc4"
},
}
Metoda 3DSecure/authSale umożliwia przeprowadzenie płatności kartą na podstawie wcześniej przeprowadzonej autoryzacji 3-D Secure.
Struktura zapytania
id_3dsecure_auth required | integer <unsigned long> Identification number of initiated 3-D Secure authentication. |
{- "id_3dsecure_auth": 237473
}
Metoda 3DSecure/auth umożliwia przeprowadzenie autoryzacji karty na podstawie wcześniej przeprowadzonej autoryzacji 3-D Secure.
Struktura zapytania
id_3dsecure_auth required | integer <unsigned long> Identification number of initiated 3-D Secure authentication. |
{- "id_3dsecure_auth": 237473
}
Metoda ideal/sale wykonuje transakcję iDEAL.
Struktura zapytania
required | object (Sale) A structure containing sale information. |
required | object (Customer) A structure containing customer data. |
back_url required | string <2-200 characters, UTF-8 encoded> Website address where a customer will be redirected after performing the payment. |
bank_code required | string <8-11 characters> Bank BIC code. |
{- "sale": {
- "amount": "100.00",
- "currency": "EUR",
- "description": "TR001",
- "fraud_check_on": true,
- "avs_check_level": 2,
- "id_sub_merchant": 3128,
- "service_fee_amount": 0.3
}, - "customer": {
- "name": "John Doe",
- "email": "john@doe.com",
- "ip": "123.456.78.90",
- "address": {
- "street_house": "1600 Pennsylvania Avenue Northwest",
- "city": "Washington",
- "state": "DC",
- "zip": "20500",
- "country_code": "US"
}
}, - "bank_code": "INGBNL2A"
}
Metoda api_beta/addAccountSubmerchant
umożliwia zgłoszenie nowego merchanta przez API.
Struktura zapytania
required | object (Company) A structure containing company data. |
required | Array of objects (Persons) |
required | object (BankAccount) A structure containing bank account data. |
{- "company": {
- "name": "John Doe Company",
- "business_type": "registered-partnership",
- "company_number": "01033457801230",
- "krs": "0012333391",
- "vat_id": "5221233782",
- "phone": "544323233",
- "email": "jan@kowalski.pl",
- "address": {
- "street_house": "1600 Pennsylvania Avenue Northwest",
- "city": "Washington",
- "state": "DC",
- "zip": "20500",
- "country_code": "US"
}
}, - "persons": [
- {
- "first_name": "John",
- "last_name": "Doe",
- "citizenship": "PL",
- "pesel": "82010123223",
- "date_of_birth": "1982-01-01",
- "is_representative": "Y",
- "is_ubo": "Y",
- "identity_doc_number": "XYZ123211",
- "identity_doc_expiration_date": "2028-12-12"
}
], - "bank_account": {
- "iban": "PL40864910155342868951311268",
- "bic": "SADSAEXZ",
- "currency": "PLN"
}
}
Metoda api_beta/addSubmerchantDocument
umożliwia dodania dokumentów dotyczących danego submerchanta przez API.
Struktura zapytania
id_submerchant required | integer <unsigned long> Identification number of the submerchant. |
required | object (Document) A structure containing document data. |
{- "id_submerchant": 1,
- "document": {
- "file_name": "document.pdf",
- "file_content": "<base64>",
- "doc_type": "bank_account_proof"
}
}
Metoda cards/token/getData
umożliwia pobranie informacji na temat tokenu.
Struktura zapytania
token required | string Identyfikator tokenu, przekazany po udanej tokenizacji karty. |
{- "token": "string"
}
Metoda cards/token/sale
umożliwia przeprowadzenie pojedynczej płatności z użyciem ztokenizowanej karty.
Struktura zapytania
token required | string Identyfikator tokenu, przekazany po udanej tokenizacji karty. |
amount required | decimal (12,2) Kwota transakcji (kropka jako separator) |
currency required | string (3) Waluta transakcji w literowym formacie ISO 4217 |
description required | string (1-255) Identyfikator transakcji, który zostanie przekazany do systemu PeP Online. Wartość pola musi być unikalna dla każdej transakcji! Zalecamy by wartością tego pola był identyfikator transakcji w Twoim systemie (sklepie). Będzie później widoczny w Merchant Panelu jako opis danej transakcji. Dozwolone są jedynie znaki alfanumeryczne. |
{- "token": "string",
- "amount": null,
- "currency": null,
- "description": null
}
Metoda cards/token/revoke
służy anulowaniu danego tokena. Anulowany token, nie będzie mógł być użyty do przeprowadzenia transakcji.
Struktura zapytania
token required | string Identyfikator tokenu, przekazany po udanej tokenizacji karty. |
{- "token": "string"
}