Polskie ePłatności (PeP) - Strefa developera (1.0.0)

Download OpenAPI specification:Download

Wstęp do integracji z Polskie ePłatności Online

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.

Przebieg procesu płatności

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

general_flow

  1. Klient kończy zakupy i wyraża chęć dokonania zapłaty.
  2. Sprzedawca wysyła do PeP Online zebrane informacje o kliencie oraz żądanie przetworzenia płatności.
  3. Systemy PeP Online komunikują się ze stosownymi instytucjami (zależnie od metody płatności będą to np. banki, centra rozliczeniowe, wystawcy kart, organizacje kartowe itp.)
  4. Po przetworzeniu płatności, jej status zwracany jest do PeP Online.
  5. Informacje o płatności przesyłane są do strony sprzedawcy.
  6. Klient informowany jest o statusie transakcja.

Platforma e-commerce lub własne rozwiązanie

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.

Pluginy

Oferujemy szereg pluginów. Dzięki nim wdrożenie płatności na Twojej stronie zajmie tylko kilka minut.

Magento

Magento

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

Prestashop

Prestashop

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.

Pobierz plugin do Prestashop

Wordpress

Wordpress

Prosty plugin PeP Online dla WordPressa pozwala na umieszczenie przycisku płatniczego na stronie zbudowanej na WordPress.

Pobierz plugin do Wordpress

WooComerce

WooComerce

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.

Pobierz plugin do WooComerce

WHMCS

WHMCS

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.

Pobierz plugin do WHMCS

Integracje

Oferujemy również wiele integracji do platform e-commerce’owych.

Shopify

Shopify

Polskie ePłatności Online jako pierwsi w Polsce zostaliśmy oficjalnym partnerem Shopify – wiodącą na świecie wielokanałową platformą ecommerce.

Shoplo

Shoplo

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 eSklep

Comarch eSklep

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

Shoper

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'.

Ebexo

Ebexo

Integracja PeP Online z platformą eCommerce Ebexo jest dostępna z panelu administracyjnego sklepu Ebexo.

KQS

KQS

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

Clickshop

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.

RESTful API Whitepaper

restful-api-whitepaper

Pobierz nasz darmowy whitepaper o technologii REST. Dowiesz się z niego m.in.:

  • czym jest REST,
  • dlaczego warto umieć się nim posługiwać,
  • jak korzystać z restowych API,
  • a wszystko to poparte przykładami!

Pobierz whitepaper za darmo

Secure Form

Wprowadzenie do Secure Form

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:

  1. Po wybraniu produktów/usług na stornie sprzedawcy, klient wyraża chęć, by zapłacić za zakupy.
  2. Klient zostaje przekierowany na stronę Polskich ePłatności Online, na której znajduje się Secure Form; wprowadza tam dane niezbędne do dokonania płatności.
  3. Po wysłaniu formularza, klient zostaje przekierowany z powrotem na stronę sprzedawcy, gdzie dowiaduje się o statusie transakcji/płatności.

Co czeka programistę?

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:

  1. Klient, będąc na stronie sprzedawcy, chce zapłacić za wybrane produkty/usługi.
  2. Strona sprzedawcy wysyła informacje o transakcji do formularza płatniczego PeP Online oraz przekierowuje tam klienta.
  3. Po wypełnieniu formularza, PeP Online wykorzystuje podane informacje, by przetworzyć płatność (komunikuje się z centrami rozliczeniowymi, bankami, organizacjami kartowymi itp.).
  4. Wymienione instytucje (ich lista zależna jest od danej metody płatności) odpowiadają do PeP Online, pozwalając na przetworzenie płatności.
  5. PeP Online zwraca informacje o statusie płatności do strony sprzedawcy.
  6. Sprzedawca może wykorzystać otrzymane informacje, by powiadomić klienta, czy transakcja się udała i jaki jest jej status.

Realizacja

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>

Dane dostępowe do Secure 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.

Obliczanie hash

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.

Wartości zapytania

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.

Struktura zapytania

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*).

Odpowiedź

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.

Struktura odpowiedzi

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.

Liczenie wartości hash z odpowiedzi

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.

Dostępne metody płatności

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

Integracja przez API

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:

  1. Po wybraniu produktów/usług na stornie sprzedawcy, klient wyraża chęć, by zapłacić za zakupy.
  2. Klient wypełnia formularz płatniczy bezpośrednio na stronie sprzedawcy.
  3. Po zatwierdzeniu formularza, strona sprzedawcy informuje klienta o statusie transakcji

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.

Co czeka programistę?

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:

  1. Klient, będąc na stronie sprzedawcy, chce zapłacić za wybrane produkty/usługi.
  2. Strona sprzedawcy wysyła informacje o płatności (via API) do PeP Online – klient nie jest nigdzie przekierowany.
  3. PeP Online wykorzystuje podane informacje, by przetworzyć płatność (komunikuje się z centrami rozliczeniowymi, bankami, organizacjami kartowymi itp.).
  4. Wymienione instytucje (ich lista zależna jest od danej metody płatności) odpowiadają do PeP Online, pozwalając na przetworzenie płatności.
  5. PeP Online zwraca informacje o statusie płatności do strony sprzedawcy.
  6. Sprzedawca może wykorzystać otrzymane informacje, by powiadomić klienta, czy transakcja się udała i jaki jest jej status.

PeP Online REST Client

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

Zbieranie danych

Pozyskiwanie danych

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ń.

Metody płatności

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.

Przykład

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>

Pola formularza

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

Wprowadzenie do kart płatniczych

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ą.

Wdrażanie płatności kartą

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.

PHP

  include_once ('PePRestClient.php');
  $client = new PePRestClient('your_login', 'your_password');

Ruby

  require 'pep_client'
  client = PeP::Client.new('your_login', 'your_password')

Python

  from client import PePRestClient
  client = PePRestClient("your_login", "your_password")

Android

  PePApi api = PePClientFactory.createClassicClient(context, "your_login", "your_password");

PeP.js

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:

  1. Kod HTML jest przesyłany do przeglądarki; strona jest wyświetlana.
  2. Klient PeP.js zostaje zainicjowany i czeka na zatwierdzenie formularza płatności.
  3. Gdy formularz zostaje zatwierdzony, klient PeP.js wysyła informacje o karcie do serwerów PeP Online. W odpowiedzi generowany jest tymczasowy token dla karty (64-bajtowy heksadecymalny łańcuch znaków), który wstawiany jest do formularza płatności w formie ukrytego pola.
  4. Proces wysyłania formularza płatności jest wznawiany, a serwery sprzedawcy otrzymują token wraz z pozostałymi informacjami z formularza (z wyłaczaniem wrażliwych danych karty).
  5. Sprzedawca może wywołać metodę sale /authorization/checkCar/checkCard3DSecure używając wygenerowanego tokenu (musi to nastąpić w ciągu 15 minut od wygenerowania tokenu; po upływie tego czasu traci on ważność).

PeP.js: Inicjalizacja

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:

  1. Pola dotyczące danych kart muszą mieć ustawione stosowne atrybuty data-paylane.
  2. Pola dotyczące danych kart nie mogą mieć atrybutów name. To wymóg bezpieczeństwa, który zapobiega wysłaniu danych kart do serwerów sprzedawcy.
  3. Formularz płatniczy musi miec nadany unikalny atrybut 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.

  • klucz API jest 40-znakowym łańcuchem znaków, który można znaleźć w Merchant Panelu PeP (Administracja -> Integracja -> Podstawowe -> Integracja API)
  • na formularz płatniczy można wskazać przekazując jako argument jedną z poniższych wartości:
    1. atrybut id formularza
    2. węzeł drzewa DOM, który reprezentuje formularz (np. osiągalny przez document.forms[i])
    3. obiekt jQuery zawierający jedynie formularz płatniczy

Poniższe wartości mogą być opcjonalnie przekazane do klienta PeP.js (jeśli nie zostaną zdefiniowane, zostaną użyte wartości):

  1. cardNumberInputName (domyślnie: cc-number) – alternatywna wartość data-paylane odnosząca się do pola numeru karty
  2. cardExpiryMonthInputName (domyślnie: cc-expiry-month) – alternatywna wartość data-paylane odnosząca się do pola miesiąca ważności karty
  3. cardExpiryYearInputName (domyślnie: cc-expiry-year) – alternatywna wartość data-paylane odnosząca się do pola roku ważności karty
  4. cardSecurityvarInputName (domyślnie: cc-cvv) – alternatywna wartość data-paylane odnosząca się do pola kodu CVV2/CVC2
  5. cardHolderInputName (domyślnie: cc-name-on-card) – alternatywna wartość data-paylane odnosząca się do pola z imieniem i nazwiskiem posiadacza karty
  6. errorTypeInputName (domyślnie: paylane_error_type) – alternatywna wartość name odnosząca się do pola typu błędu
  7. errorCodeInputName (domyślnie: paylane_error_code) – alternatywna wartość name odnosząca się do pola kodu błędu
  8. errorDescriptionInputName (domyślnie: paylane_error_description) – alternatywna wartość name odnosząca się do pola opisu błędu
  9. tokenInputId (domyślnie: paylane-token) – alternatywna wartość id odnosząca się do pola tokenu
  10. tokenInputName (domyślnie: paylane_token) – alternatywna wartość name odnosząca się do pola tokenu
  11. errorHandler (domyślnie: pusta funkcja) – funkcja obsługi błędu, przyjmuje trzy argumenty: type, code, description
  12. 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: Obsługa błędów

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).

  1. Obsługa błędów: ```javascript /**
  • Custom error handler which allows the merchant to
  • handle errors raised by the PePClient class,
  • such as connection errors or erroneous API responses.
  • @param {int} type Error type from PePClient.errorTypes
  • @param {int} [code] Error code from the API response
  • @param {string} [description] Error description from the API response
  • @return {void} */ function errorHandler(type, code, description) { console.log(type, code, description); } ```
  1. Ukryte pola formularza: Poniższe ukryte pola zostaną dodane do formularza płatniczego (należy pamietać ich, że ich nazwy mogą zostać nadpisane podczas przekazywania parametrów error* do konstruktora):
  • 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 PeP
  • paylane_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)

Pojedyncza transakcja

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.

Próbka kodu - przygotowanie danych

PHP

  $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',
      ),
  );

Ruby

  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'
      }
  }

Python

  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'
    }
  }

Android

  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
  );

Próbka kodu - wykonanie płatności (cardSaleByToken)

PHP

  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']}");
  }

Ruby

  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

Python

  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"]))

Android

  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.
        }

Autoryzacja

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:

  • pobieranie numeru karty podczas zakładania darmowego konta próbnego w Twojej usłudze (później można już automatycznie obciążać kartę),
  • sprawdzanie karty (np. czy są dostępne środki lub czy transakcje internetowe nie są zablokowane),
  • potwierdzenie numeru karty, gdy klient tworzy konto w Twoim e-sklepie (np. jeśli chcesz mu udostępnić płatności single-click).

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.

Próbka kodu - Przygotowanie danych do autoryzacji

PHP

  $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'
      ),
  );

Ruby

  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'
      }
  }

Python

  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'
    }
  }

Android

  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");

Próbka kodu - Realizacja autoryzacji

PHP

  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']}");
  }

Ruby

  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

Python

  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"]))

Android

  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

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:

Płatności cykliczne bazujące na wcześniejszych transakcjach

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.

Próbka kodu - Pobranie ID pierwszej transakcji

PHP

  $status = $client->cardSale($card_params);
  $id_first_sale = $status['id_sale'];

Ruby

  status = client.card_sale(card_params)
  id_first_sale = status['id_sale']

Python

  status = client.card_sale(card_params)
  id_first_sale = status['id_sale']

Android

  api.cardSale(sale, customer, card, new Callback<CardSaleResult>() {
      @Override
      public void onFinish(CardSaleResult result) {
          long idFirstSale = result.getIdSale();
      }
  });

Próbka kodu - Realizacja transakcji / resale

PHP

  $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']}");
  }

Ruby

  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

Python

  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"]))

Android

  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.
          }
      }
  );

Płatności cykliczne bazujące na autoryzacji karty

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.:

  • kiedy klient zakłada konto w Twoim e-sklepie,
  • gdy klient zapisuje się na bezpłatny okres testowy Twojej usługi. Gdy zbierzesz te dane, wykonaj autoryzację karty i zapisz jej numer ID.

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.

Próbka kodu - Pobranie id autoryzacji

PHP

  $id_authorization = $status['id_authorization'];

Ruby

  id_authorization = status["id_authorization"]

Python

  id_authorization = status['id_authorization']

Android

  AuthorizationResult result =...;
  long idAuthorization = result.getIdAuthorization();

Próbka kodu - Zrealizowanie transakcji w oparciu o wcześniejszą autoryzację

PHP

  $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']}");
  }

Ruby

  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

Python

  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"]))

Android

  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.
      }
  });

Zwrot środków

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.

Próbka kodu - Pobranie id transakcji

PHP

  $status = $client->cardSale($card_params);
  $id_sale = $status['id_sale'];

Ruby

  status = client.card_sale(card_params)
  id_sale = status['id_sale']

Python

  status = client.card_sale(card_params)
  id_sale = status['id_sale']

Android

  api.cardSale(sale, customer, card, new Callback<CardSaleResult>() {
      @Override
      public void onFinish(CardSaleResult result) {
          long idFirstSale = result.getIdSale();
      }
  });

Próbka kodu - Realizacja refundu

PHP

  $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']}");
  }

Ruby

  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

Python

  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"]))

Android

  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 / one click

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.:

Single-click bazujące na wcześniejszych transakcjach

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.

Próbka kodu - Zrealizowanie transakcji single click

PHP

  $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']}");
  }

Ruby

  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

Python

  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"]))

Android

  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.
          }
      }
  );

Single-click bazujące na autoryzacji

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.

Próbka kodu - Pobranie id autoryzacji

PHP

  $id_authorization = $status['id_authorization'];

Ruby

  id_authorization = status["id_authorization"]

Python

  id_authorization = status['id_authorization']

Android

  AuthorizationResult result =...;
  long idAuthorization = result.getIdAuthorization();

Próbka kodu - Realizacja single click w oparciu o id autoryzacji

PHP

  $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']}");
  }

Ruby

  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

Python

  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"]))

Android

  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.
      }
  });

3-D Secure

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ą.

3-D Secure Krok 1: Przygotuj dane

Przygotuj dane potrzebne do przeprowadzenia płatności jak w przykładzie.

Próbka kodu - Przygotowanie danych do transakcji 3-D Secure

PHP

  $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
  );

Ruby

  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'
  }

Python

  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'
  }

Android

  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")

3-D Secure Krok 2: Sprawdź kartę

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.

Próbka kodu - Sprawdzenie czy karta jest w systemie 3-D Secure

PHP

  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;
  }

Ruby

  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

Python

  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()

Android

  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.
      }
  });

3-D Secure Krok 3: Transakcja

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.

Próbka kodu - Sprawdzenie danych po powrocie ze strony z zabezpieczeniem 3-D Secure

PHP

  $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
  }

Ruby

  # 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

Python

  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'

Android

  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);
  }

Próbka kodu - Zrealizowanie transakcji po weryfikacji 3-D Secure

PHP

  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']}");
  }

Ruby

  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

Python

  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'))

Android

  Secure3DSaleResult result =...;
  long id3dSecureAuth = result.getId3dSecureAuth();
  api.secure3DAuthSale(id3dSecureAuth, new Callback<CardSaleResult>() {

      @Override
      public void onFinish(CardSaleResult result) {
          // success
      }
  });

3-D Secure Krok 3a: Karta niezapisana do 3-D Secure

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.

Próbka kodu - Realizacja transakcji gdy karta nie jest w systemie 3-D Secure

PHP

  $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']}");
  }

Ruby

  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

Python

  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'))

Android

  Secure3DSaleResult result =...;
  if (!result.isEnrolled()) {
      api.secure3DAuthSale(result.getId3dSecureAuth(), new Callback<CardSaleResult>() {

          @Override
          public void onFinish(CardSaleResult result) {
              // success
          }
      });
  }

Google Pay

Wprowadzenie do Google Pay

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.

Zanim zaczniesz wprowadzać Google Pay

Zapoznaj się z poniższą dokumetnacją:

Oraz załóż konto produkcyjne Google Pay:

PeP.js: Inicjalizacja Google Pay

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.

Google Pay check 3DS

Do Requestów używamy naszych danych autoryzacyjnych:

PHP

  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"

Sample Request

  {
      "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"
  }

Sample Response

  {
      "success"           :   true,
      "id_3dsecure_auth"  :   1234567,
      "is_card_enrolled"  :   true,
      "redirect_url"      :   "https://secure.pep.pl/payment/123"
  }

Google Pay sale

Został nam ostatni krok! Używamy do tego "id_3dsecure_auth" uzyskany w poprzednim kroku Dokładniejszy opis requestu i odpowiedzi, wraz z Endpointami:

  1. Google Pay check 3DS
  2. 3DS Sale

Przelewy internetowe

Internetowe przelewy bankowe

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.

Wdrożenie przelewów internetowych

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.

Próbka kodu

PHP

  include_once ('PePRestClient.php');
  $client = new PePRestClient('your_login', 'your_password');

Ruby

  require 'pep_client'
  client = PeP::Client.new('your_login', 'your_password')

Python

  from client import PePRestClient
  client = PePRestClient("your_login", "your_password")

Android

  PePApi api = PePClientFactory.createClassicClient(context, "your_login", "your_password");

Transakcja

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.

Próbka kodu - Przygotowanie danych do transakcji

PHP

  $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',
  );

Ruby

  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'
  }

Python

  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'
  }

Android

  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);

Płatność / przekierowanie do banku

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.

Próbka kodu - Przekierowanie do banku

PHP

  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;

Ruby

  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

Python

  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()

Android

  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.
      }
  });

Weryfikacja płatności

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.

Próbka kodu - Sprawdzenie poprawności płatności

PHP

  $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;
  }

Ruby

  # 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

Python

  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'

Android

  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);
  }

Sprawdzanie transakcji (ręczne)

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.

Próbka kodu - Ręczne sprawdzenie statusu transakcji

PHP

  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']}");
  }

Ruby

  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

Python

  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"]))

Android

  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.
      }
  })

Sprawdzanie transakcji (automatyczne)

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:

Próbka kodu - Odbieranie notyfikacji o transakcjach

PHP

  // 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']);

Ruby

  # 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']

Python

  # 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

Wprowadzenie do PayPal

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.

Wdrożenie płatności PayPal

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.

Próbka kodu - PeP Online Rest Client

PHP

  include_once ('PePRestClient.php');
  $client = new PePRestClient('your_login', 'your_password');

Ruby

  require 'pep_client'
  client = PeP::Client.new('your_login', 'your_password')

Python

  from client import PePRestClient
  client = PePRestClient("your_login", "your_password")

Android

  PePApi api = PePClientFactory.createClassicClient(context, "your_login", "your_password");

Pojedyncza transakcja

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.

Próbka kodu - Przygotowanie danych do transakcji

PHP

  $paypal_params = array(
      'sale'     => array(
          'amount'      => 19.99,
          'currency'    => 'EUR',
          'description' => 'Product #1'
      ),
      'back_url'  => 'http://example-page.com',
  );

Ruby

  paypal_params = {
      'sale' => {
          'amount'      => 19.99,
          'currency'    => 'EUR',
          'description' => 'Product #1'
      },
      'back_url' => 'http://example-page.com'
  }

Python

  paypal_params = {
    'sale' : {
      'amount'      : 19.99,
      'currency'    : 'EUR',
      'description' : 'Product #1'
    },
    'back_url' : 'http://example.com'
  }

Android

  Sale sale = new Sale(19.99, "EUR", "Product #1");

Próbka kodu - Realizacja transakcji

PHP

  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;

Ruby

  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

Python

  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()

Android

  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.
      }
  });

Weryfikacja transakcji

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.

Próbka kodu -

PHP

  $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;
  }

Ruby

  # 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

Python

  # 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')

Android

  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

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.

Transakcje cykliczne PayPal

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.

Próbka kodu - Przygotowanie danych do profilu recurringowego

PHP

  $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'
      ),
  );

Ruby

  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'
      )
  }

Python

  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

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.

Próbka kodu - Zrealizowanie pierwszej transakcji PayPal

PHP

  $status = $client->paypalSale($paypal_params);
  $id_first_sale = $status['id_sale'];

Ruby

  status = client.paypal_sale(paypal_params)
  id_first_sale = status['id_sale']

Python

  status = client.paypal_sale(paypal_params)
  id_first_sale = status['id_sale']

Android

  api.payPalSale(sale,"http://example-page.com",new Callback<RedirectSaleResult>() {
      @Override
      public void onFinish(RedirectSaleResult result) {
          long idSale=result.getIdSale();
      }
  });

Próbka kodu

PHP

        $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']}");
  }

Ruby

  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

Python

  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"]))

Android

  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.
      }
  });

Zwrot środków

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.

Próbka kodu - Pobranie ID pierwszej transakcji

PHP

  $status = $client->paypalSale($paypal_params);
  $id_sale = $status['id_sale'];

Ruby

  status = client.paypal_sale(paypal_params)
  id_sale = status['id_sale']

Python

  status = client.paypal_sale(paypal_params)
  id_sale = status['id_sale']

Android

  api.payPalSale(sale,"http://example-page.com",new Callback<RedirectSaleResult>() {
      @Override
      public void onFinish(RedirectSaleResult result) {
          long idSale=result.getIdSale();
      }
  });

Próbka kodu - Realizacja refundu

PHP

  $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']}");
  }

Ruby

  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

Python

  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"]))

Android

  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.
      }
  });

Autoryzacja

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.

Próbka kodu - Przygotowanie danych do autoryzacji

PHP

  $paypal_params = array(
      'sale'     => array(
          'amount'      => 19.99,
          'currency'    => 'EUR',
          'description' => 'Product #1'
      ),
      'back_url'  => 'http://example-page.com',
  );

Ruby

  paypal_params = {
      'sale' => {
          'amount'      => 19.99,
          'currency'    => 'EUR',
          'description' => 'Product #1'
      },
      'back_url' => 'http://example-page.com'
  }

Python

  paypal_params = {
    'sale' : {
      'amount'      : 19.99,
      'currency'    : 'EUR',
      'description' : 'Product #1'
    },
    'back_url' : 'http://example.com'
  }

Android

  Sale sale = new Sale(19.99, "EUR", "Product #1");

Próbka kodu - Realizacja autoryzacji

PHP

  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']}");
  }

Ruby

  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

Python

  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"]))

Android

  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

Wprowadzenie do Direct Debit

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).

Wdrożenie płatności Direct Debit

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.

Próbka kodu - PeP Online Rest Client

PHP

  include_once ('PePRestClient.php');
  $client = new PePRestClient('your_login', 'your_password');

Ruby

  require 'pep_client'
  client = PeP::Client.new('your_login', 'your_password')

Python

  from client import PePRestClient
  client = PePRestClient("your_login", "your_password")

Android

  PePApi api = PePClientFactory.createClassicClient(context, "your_login", "your_password");

Pojedyncza transakcja

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.

Próbka kodu - Przygotowanie danych do transakcji

PHP

  $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',
      ),
  );

Ruby

  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'
      }
  }

Python

  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'
    }
  }

Android

  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");

Próbka kodu - Realizacja transakcji

PHP

  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']}");
  }

Ruby

  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

Python

  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"]))

Android

  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.
      }
  });

Reversal

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.

Próbka kodu

PHP

  try {
      $sale_info = $client->getSaleInfo(array('id_sale' => $id_sale));
  }
  catch (Exception $e) {
      // handle exceptions here
  }

Ruby

  begin
      status = client.get_sale_info({"id_sale" => id_sale})
  rescue PeP::ClientError => e
      # handle exceptions here
  end

Python

  try:
      sale_info = client.get_sale_info({'id_sale': id_sale})
  except Exception, e:
      # handle exceptions here

Android

  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

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.

Próbka kodu - Pobranie ID pierwszej transakcji

PHP

  $status = $client->directDebitSale($ddebit_params);
  $id_first_sale = $status['id_sale'];

Ruby

  status = client.direct_debit_sale(ddebit_params)
  d_first_sale = status["id_sale"]

Python

  status = client.direct_debit_sale(ddebit_params)
  id_first_sale = status['id_sale']

Android

  api.directDebitSale(sale, customer, account, new Callback<SaleResult>() {
      @Override
      public void onFinish(SaleResult result) {
          long idSale=result.getIdSale();
      }
  });

Próbka kodu - Realizacja transakcji / resale

PHP

  $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']}");
  }

Ruby

  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

Python

  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"]))

Android

  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.
      }
  });

Zwrot środków

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.

Próbka kodu - Pobranie id transakcji

PHP

  $status = $client->directDebitSale($ddebit_params);
  $id_sale = $status['id_sale'];

Ruby

  status = client.direct_debit_sale(ddebit_params)
  id_sale = status["id_sale"]

Python

  status = client.direct_debit_sale(ddebit_params)
  id_sale = status['id_sale']

Android

  api.directDebitSale(sale, customer, account, new Callback<SaleResult>() {
      @Override
      public void onFinish(SaleResult result) {
          long idSale=result.getIdSale();
      }
  });

Próbka kodu - Realizacja refundu

PHP

  $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']}");
  }

Ruby

  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

Python

  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"]))

Android

  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

Wprowadzenie do SOFORT Banking

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).

Wdrożenie płatności SOFORT

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.

Próbka kodu - PeP Online Rest Client

PHP

  include_once ('PePRestClient.php');
  $client = new PePRestClient('your_login', 'your_password');

Ruby

  require 'pep_client'
  client = PeP::Client.new('your_login', 'your_password')

Python

  from client import PePRestClient
  client = PePRestClient("your_login", "your_password")

Android

  PePApi api = PePClientFactory.createClassicClient(context, "your_login", "your_password");

Transakcja

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.

Próbka kodu - Przygotowanie danych do transakcji

PHP

  $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',
  );

Ruby

  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'
  }

Python

  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'
  }

Android

  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);

Płatność

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.

Próbka kodu - Realizacja transakcji

PHP

  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;

Ruby

  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

Python

  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()

Android

  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.
      }
  });

Weryfikacja

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.

Próbka kodu - Zweryfikowanie danych

PHP

  $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;
  }

Ruby

  # 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

Python

  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')

Sprawdzanie transakcji (automatyczne)

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:

Próbka kodu - Sprawdzenie danych

PHP

  // 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']);

Ruby

  # 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']

Python

  # 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')

Sprawdzanie transakcji (ręczne)

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.

Próbka kodu - Sprawdzenie danych

PHP

  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']}");
  }

Ruby

  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

Python

  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"]))

Android

  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

Wprowadzenie do iDEAL

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.

Wdrożenie płatności IDEAL

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.

Próbka kodu - PeP Online Rest Client

PHP

  include_once ('PePRestClient.php');
  $client = new PePRestClient('your_login', 'your_password');

Ruby

  require 'pep_client'
  client = PeP::Client.new('your_login', 'your_password')

Python

  from client import PePRestClient
  client = PePRestClient("your_login", "your_password")

Android

  PePApi api = PePClientFactory.createClassicClient(context, "your_login", "your_password");

Lista kodów banków

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.

Próbka kodu - Lista banków

PHP

  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
  }

Ruby

  begin
    status = client.ideal_bank_codes()
  rescue PeP::ClientError => e
    # handle exception here
  end

Python

  try:
    status = client.ideal_bank_codes()
  except Exception, e:
    # handle exception
    print e
    sys.exit()

Próbka kodu - Opcje płatności

PHP

  <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>

Ruby

  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

Python

  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"]))

Transakcja

Zacznij od przygotowania danych do przeprowadzenia płatności z użyciem systemu iDEAL:

  1. informacje o transakcji
  2. kliencie
  3. typie płatności

Zdefiniuj także adres (back_url), na który klient zostanie przekierowany po dokonaniu płatności.

Próbka kodu -

PHP

  $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',
  );

Ruby

  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'
  }

Python

  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'
  }

Płatność

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.

Próbka kodu - Realizacja transakcji

PHP

  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;

Ruby

  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

Python

  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/')

Weryfikacja

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.

Próbka kodu - Zweryfikowanie danych

PHP

  $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;
  }

Ruby

  # 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

Python

  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')

Sprawdzanie transakcji (ręczne)

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.

Próbka kodu - Sprawdzenie danych

PHP

  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']}");
  }

Ruby

  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

Python

  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"]))

Android

  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.
      }
  });

Sprawdzanie transakcji (automatyczne)

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.

Próbka kodu - Sprawdzenie danych

PHP

  // 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']);

Ruby

  # 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']

Python

  # 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')

Wdrażanie i testy

Wstęp do wdrażania i testów

Poniżej znajdziesz kilka przydatnych informacji, które sprawią, że wdrażanie płatności PeP Online będzie jeszcze łatwiejsze i wygodniejsze.

Używaj konta testowego

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.

Podstawy wdrożenia i testó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.

Próbka kodu - PeP Online Rest Client

PHP

  include_once ('PePRestClient.php');
  $client = new PePRestClient('your_login', 'your_password');

Ruby

  require 'pep_client'
  client = PeP::Client.new('your_login', 'your_password')

Python

  from client import PePRestClient
  client = PePRestClient("your_login", "your_password")

Jak wywołać błędy transakcji

To bardzo łatwe – po prostu wprowadź odpowiedni kod błędu jako kwotę transakcji__.

Testowe numery kart

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.

Common sale tests

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.

3-D Secure tests

Tabela kodów

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)

AVS (Addres Verification System) tests

Tabela kodów

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)

Kody błędów

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.

Tabela kodów

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).
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.

Kody AVS

Tabela kodów

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

Mechanizm powiadomień

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

Używanie powiadomień o transakcjach

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ń.

Harmonogramy

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.

Wdrożenie

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:

  • HTTP,
  • HTTPS.

Zapytania

Struktura zapytania

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.

Struktura tablicy content

Tablica content zawiera tablice reprezentujące poszczególne notyfikacje. Przykładowe dane POST (w postaci tablicy PHP):

Opis pól tablicy

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ład zapytania

Przykładowe dane POST (w postaci tablicy PHP)

Przykładowe dane

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 
  )

Przykładowy klient i odpowiedź

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

Próbka kodu

PHP

  $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']);

Typy transakcji

Tabela typów

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.
3DSAUTH 3DSecure auth notification.

Modele biznesowe

Wprowadzenie do modeli biznesowych

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).

Pojedyncza płatność – sposób klasyczny

To oczywiście najpopularniejszy schemat zakupów online – klient każdą transakcję (a więc i płatność) inicjuje “ręcznie”.

bussiness-model-classic

Krok do przodu

“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

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.

Inicjowanie przez pierwszą sprzedaż

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).

first-sale

Inicjowanie przez autoryzację karty

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.

authorization

Tokenizacja

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

Opis funkcji API

API Cards

POST cards / sale

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.

Request Body schema: application/json

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

Responses

Request samples

Content type
application/json
{
  • "sale": {
    },
  • "customer": {
    },
  • "card": {
    }
}

POST cards / saleByToken

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.

Request Body schema: application/json

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

Responses

Request samples

Content type
application/json
{
  • "sale": {
    },
  • "customer": {
    },
  • "card": {
    }
}

POST cards / authorization

Metoda cards/authorization umożliwia autoryzowanie karty (kredytowej, debetowej, przedpłaconej itd.). Oznacza to, że określona kwota zostaje jedynie zablokowana, ale nie będzie pobrana z karty. Zablokowane środki mogą zostać później pobrane (metoda authorizations/capture) lub zwolnione (metoda authorization/close) automatyczne zwolnienie środków nastąpi też po określonym czasie). Mechanizm autoryzacji jest często stosowany do zweryfikowania karty.

Request Body schema: application/json

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

Responses

Request samples

Content type
application/json
{
  • "sale": {
    },
  • "customer": {
    },
  • "card": {
    }
}

POST cards / authorizationByToken

Metoda cards/authorizationByToken umożliwia autoryzowanie karty (kredytowej, debetowej, przedpłaconej itd.). Oznacza to, że określona kwota zostaje jedynie zablokowana, ale nie będzie pobrana z karty. Zablokowane środki mogą zostać później pobrane (metoda authorizations/capture) lub zwolnione (metoda authorization/close) automatyczne zwolnienie środków nastąpi też po określonym czasie). Mechanizm autoryzacji jest często stosowany do zweryfikowania karty.

Request Body schema: application/json

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

Responses

Request samples

Content type
application/json
{
  • "sale": {
    },
  • "customer": {
    },
  • "card": {
    }
}

POST cards / generateToken

Metoda cards/generateToken tworzy tymczasowy, unikalny token dla podanego zestawu danych karty. Token jest ważny przez 15 minut od utworzenia.

Request Body schema: application/json

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)

Responses

Request samples

Content type
application/json
{
  • "public_api_key": "71426338751d8c8e454a13fa4c44a3094cbab89c",
  • "card_number": "4111111111111111",
  • "expiration_month": "2017",
  • "expiration_year": "71426338751d8c8e454a13fa4c44a3094cbab89c",
  • "name_on_card": "John Doe",
  • "card_code": "123"
}

POST cards / check

Metoda cards/check sprawdza, czy podany numer karty jest prawidłowy oraz rozpoznaje wystawcę karty.

Request Body schema: application/json

Struktura zapytania

card_number
required
string <13-19 digits>

The full number of the card without any whitespaces. Only digits are allowed.

Responses

Request samples

Content type
application/json
{
  • "card_number": "4200000000000000"
}

POST cards / checkByToken

Metoda cards/checkByToken sprawdza, czy podany numer karty jest prawidłowy oraz rozpoznaje wystawcę karty.

Request Body schema: application/json

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.

Responses

Request samples

Content type
application/json
{
  • "token": "12a34b45c67d89e00f1aa2bb3cc4dd5ee6ff12a34b45c67d89e00f1aa2bb3cc4"
}

API PayPal

POST paypal / sale

Metoda paypal/sale umożliwia przeprowadzenie płatności z użyciem konta PayPal.

Request Body schema: application/json

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.

Responses

Request samples

Content type
application/json
{
  • "sale": {
    },
  • "recurring": {
    }
}

POST paypal / authorization

Metoda paypal/authorization umożliwia autoryzację konta PayPal (blokadę środków).

Request Body schema: application/json

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.

Responses

Request samples

Content type
application/json
{}

POST paypal / stopRecurring

Metoda paypal/stopRecurring umożliwia zatrzymanie aktywnego profilu recurringowego PayPala.

Request Body schema: application/json

Struktura zapytania

id_paypal_recurring
required
integer <unsigned long>

Identification number of recurring profile.

Responses

Request samples

Content type
application/json
{
  • "id_paypal_recurring": 1
}

API BankTransfers

POST banktransfers / sale

Metoda banktransfers/sale umożliwia przeprowadzenie płatności z wykorzystaniem przelewu bankowego.

Request Body schema: application/json

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:

  • AB – Alior Bank,
  • AS – T-Mobile Usługi Bankowe,
  • MT – mBank (mTransfer),
  • IN – Inteligo,
  • IP – iPKO,
  • MI – Millennium,
  • CA – Credit Agricole,
  • PP – Poczta Polska,
  • PCZ – Bank Pocztowy,
  • IB – Idea Bank,
  • PO – Pekao S.A.,
  • GB – Getin Bank,
  • IG – ING Bank Śląski,
  • WB – Santander Bank,
  • PB – Bank BGŻ BNP PARIBAS,
  • CT – Citi Handlowy,
  • PL – PlusBank,
  • NP – Noble Pay,
  • BS – Bank Spółdzielczy,
  • NB – NestBank,
  • RF - Raiffeisen,
  • PBS – Podkarpacki Bank Spółdzielczy,
  • SGB – SGB,
  • BLIK - Blik,
  • OH – other.

Responses

Request samples

Content type
application/json
{
  • "sale": {
    },
  • "customer": {
    },
}

API DirectDebits

POST directdebits / sale

Metoda directdebits/sale umożliwia przeprowadznei płatności Direct Debit.

Request Body schema: application/json

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.

Responses

Request samples

Content type
application/json
{
  • "sale": {
    },
  • "customer": {
    },
  • "account": {
    }
}

API Sofort

POST sofort / sale

Metoda sofort/sale umożliwia przeprowadzenie płatności w wykorzystaniem systemu SOFORT Banking.

Request Body schema: application/json

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.

Responses

Request samples

Content type
application/json
{
  • "sale": {
    },
  • "customer": {
    },
}

API ApplePay

POST applepay / sale

Metoda applepay/sale umożliwia przeprowadzenie pojedynczej transakcji z użyciem tokenu płatniczego Apple Pay.

Request Body schema: application/json

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

Responses

Request samples

Content type
application/json
{
  • "sale": {
    },
  • "customer": {
    },
  • "card": {
    }
}

POST applepay / authorization

Metoda applepay/authorization umożliwia autoryzowanie karty (kredytowej, debetowej, przedpłaconej itd.) z użyciem tokenu płatniczego Apple Pay. Oznacza to, że określona kwota zostaje jedynie zablokowana, ale nie będzie pobrana z karty. Zablokowane środki mogą zostać później pobrane (metoda authorizations/capture) lub zwolnione (metoda authorization/close; automatyczne zwolnienie środków nastąpi też po określonym czasie). Mechanizm autoryzacji jest często stosowany do zweryfikowania karty.

Request Body schema: application/json

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

Responses

Request samples

Content type
application/json
{
  • "sale": {
    },
  • "customer": {
    },
  • "card": {
    }
}

API GooglePay

POST googlepay / sale

Metoda googlepay/sale umożliwia przeprowadzenie pojedynczej transakcji z użyciem tokenu płatniczego Google Pay.

Request Body schema: application/json

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

Responses

Request samples

Content type
application/json
{
  • "sale": {
    },
  • "customer": {
    },
  • "card": {
    }
}

POST googlepay / authorization

Metoda googlepay/authorization umożliwia autoryzowanie karty (kredytowej, debetowej, przedpłaconej itd.) z użyciem tokenu płatniczego Google Pay. Oznacza to, że określona kwota zostaje jedynie zablokowana, ale nie będzie pobrana z karty. Zablokowane środki mogą zostać później pobrane (metoda authorizations/capture) lub zwolnione (metoda authorization/close; automatyczne zwolnienie środków nastąpi też po określonym czasie). Mechanizm autoryzacji jest często stosowany do zweryfikowania karty.

Request Body schema: application/json

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

Responses

Request samples

Content type
application/json
{
  • "sale": {
    },
  • "customer": {
    },
  • "card": {
    }
}

API Blik

POST blik / sale

Metoda blik/sale to transparentna płatność kodem BLIK (BLIK level 0).

Responses

API Refunds

POST refunds

Metoda refunds umożliwia dokonanie zwrotu środków w odniesieniu do konkretnej transakcji (niezależnie od rodzaju metody płatności).

Request Body schema: application/json

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.

Responses

Request samples

Content type
application/json
{
  • "id_sale": 1234567,
  • "amount": 15,
  • "reason": "Special discount."
}

POST refunds / info

Metoda refunds/info zwraca dane o zwrocie/zwrotach

Request Body schema: application/json

Struktura zapytania

id_sale
required
integer <unsigned long>

Identification number of the sale that should be refunded.

Responses

Request samples

Content type
application/json
{
  • "id_sale": 1234567
}

API Authorizations

POST authorizations / capture

Metoda authorizations/capture umożliwia pobranie kwoty, która została uprzednio zablokowana podczas autoryzacji na karcie, koncie PayPal lub przy transakcji Direct Debit.

Request Body schema: application/json

Struktura zapytania

id_authorization
required
integer <unsigned long>

Identification number of the authorization.

amount
required
decimal <12,2>

Amount to be captured. This amount must not be larger than previously authorized amount. It is possible to capture lower amount than authorized (e.g. when charging for partially fulfilled order).

description
string <2-200 characters>

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.

Responses

Request samples

Content type
application/json
{
  • "id_authorization": 1234567,
  • "amount": 75.5,
  • "description": "TR001"
}

POST authorizations / close

Metoda authorizations/close umożliwia zamknięcie wcześniejszej autoryzacji (np. karty lub konta PayPal) i zwolnienie zablokowanych środków. Autoryzacje wygasają samoistnie po określonym czasie, niemniej w niektórych przypadkach może być uzasadnione wcześniejsze zamknięcie.

Request Body schema: application/json

Struktura zapytania

id_authorization
required
integer <unsigned long>

Identification number of the authorization.

Responses

Request samples

Content type
application/json
{
  • "id_authorization": 12345
}

POST authorizations / info

Metoda authorizations/info zwraca dane dotyczące konkretnej autoryzacji (jednoznacznie określonej przez jej numer ID).

Request Body schema: application/json

Struktura zapytania

id_authorization
required
integer <unsigned long>

Identification number of the authorization.

Responses

Request samples

Content type
application/json
{
  • "id_authorization": 12345
}

API Sales

POST sales / info

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).

Request Body schema: application/json

Struktura zapytania

id_sale
required
integer <unsigned long>

Identification number of a sale.

Responses

Request samples

Content type
application/json
{
  • "id_sale": 12345
}

POST sales / status

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.

Request Body schema: application/json

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.

Responses

Request samples

Content type
application/json
{
  • "amount": 45,
  • "currency": "EUR",
  • "description": "TR001"
}

API Resales

POST resales / sale

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.

Request Body schema: application/json

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.

Responses

Request samples

Content type
application/json
{
  • "id_sale": 436635,
  • "amount": 4.99,
  • "currency": "EUR",
  • "description": "TR001",
  • "id_sub_merchant": 3128,
  • "service_fee_amount": 0.3
}

POST resales / authorization

Metoda resales/authorization umożliwia przeprowadznie płatności na podstawie wcześniej dokonanej autoryzacji. Dzięki takiemu odniesieniu metoda nie wymaga podawania kompletnych danych (np. karty) i pozwala na szybsze dokonanie płatności.

Request Body schema: application/json

Struktura zapytania

id_authorization
required
integer <unsigned long>

Identification number of the authorization.

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.

Responses

Request samples

Content type
application/json
{
  • "id_authorization": 436635,
  • "amount": 4.99,
  • "currency": "EUR",
  • "description": "TR001",
  • "id_sub_merchant": 3128,
  • "service_fee_amount": 0.3
}

API 3DSecure

POST 3DSecure / checkCard

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.

Request Body schema: application/json

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.

Responses

Request samples

Content type
application/json
{
  • "sale": {
    },
  • "customer": {
    },
  • "card": {
    },
}

POST 3DSecure / checkCardByToken

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.

Request Body schema: application/json

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.

Responses

Request samples

Content type
application/json
{
  • "sale": {
    },
  • "customer": {
    },
  • "card": {
    },
}

POST 3DSecure / authSale

Metoda 3DSecure/authSale umożliwia przeprowadzenie płatności kartą na podstawie wcześniej przeprowadzonej autoryzacji 3-D Secure.

Request Body schema: application/json

Struktura zapytania

id_3dsecure_auth
required
integer <unsigned long>

Identification number of initiated 3-D Secure authentication.

Responses

Request samples

Content type
application/json
{
  • "id_3dsecure_auth": 237473
}

POST 3DSecure / auth

Metoda 3DSecure/auth umożliwia przeprowadzenie autoryzacji karty na podstawie wcześniej przeprowadzonej autoryzacji 3-D Secure.

Request Body schema: application/json

Struktura zapytania

id_3dsecure_auth
required
integer <unsigned long>

Identification number of initiated 3-D Secure authentication.

Responses

Request samples

Content type
application/json
{
  • "id_3dsecure_auth": 237473
}

API iDEAL

POST ideal / sale

Metoda ideal/sale wykonuje transakcję iDEAL.

Request Body schema: application/json

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.

Responses

Request samples

Content type
application/json
{
  • "sale": {
    },
  • "customer": {
    },
  • "bank_code": "INGBNL2A"
}

GET ideal / bankcodes

Metoda ideal/bankcodes zwraca informacje o wszystkich dostępnych bankach.

Responses

API Marketplace

POST addAccountSubmerchant

Metoda api_beta/addAccountSubmerchant umożliwia zgłoszenie nowego merchanta przez API.

Request Body schema: application/json

Struktura zapytania

required
object (Company)

A structure containing company data.

required
Array of objects (Persons)
required
object (BankAccount)

A structure containing bank account data.

Responses

Request samples

Content type
application/json
{
  • "company": {
    },
  • "persons": [
    ],
  • "bank_account": {
    }
}

POST addSubmerchantDocument

Metoda api_beta/addSubmerchantDocument umożliwia dodania dokumentów dotyczących danego submerchanta przez API.

Request Body schema: application/json

Struktura zapytania

id_submerchant
required
integer <unsigned long>

Identification number of the submerchant.

required
object (Document)

A structure containing document data.

Responses

Request samples

Content type
application/json
{
  • "id_submerchant": 1,
  • "document": {
    }
}

API Tokenizacja

POST cards / token / getData

Metoda cards/token/getData umożliwia pobranie informacji na temat tokenu.

Request Body schema: application/json

Struktura zapytania

token
required
string

Identyfikator tokenu, przekazany po udanej tokenizacji karty.

Responses

Request samples

Content type
application/json
{
  • "token": "string"
}

POST cards / token / sale

Metoda cards/token/sale umożliwia przeprowadzenie pojedynczej płatności z użyciem ztokenizowanej karty.

Request Body schema: application/json

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.

Responses

Request samples

Content type
application/json
{
  • "token": "string",
  • "amount": null,
  • "currency": null,
  • "description": null
}

POST cards / token / revoke

Metoda cards/token/revoke służy anulowaniu danego tokena. Anulowany token, nie będzie mógł być użyty do przeprowadzenia transakcji.

Request Body schema: application/json

Struktura zapytania

token
required
string

Identyfikator tokenu, przekazany po udanej tokenizacji karty.

Responses

Request samples

Content type
application/json
{
  • "token": "string"
}