Płatności w railsach
Wypełniając obietnicę złożoną jakiś czas temu niniejszym udostępniam kod pozwalający na integrację aplikacji Railsowej z serwisem platnosci.pl. Ponieważ integracja to nie tylko sam plugin przygotowałem także tekst objaśniający (mam nadzieję) tajniki spinania aplikacji z serwisem transakcyjnym. Zapraszam...
Wstęp
Kod który przedstawiam w tym artykule pochodzi z prawdziwej i żywej aplikacji – webankieta.pl. Działa sprawnie od kilku miesięcy przetwarzając wszystkie zamówienia składane przez moich klientów. Nie można jednak wykluczyć, że w Twoim przypadku coś zacznie działać błędnie. Z tego też względu ostrzegam: używasz przedstawionego tu kodu na własną odpowiedzialność.
Plugin i przykładowa aplikacja były testowane z Railsami w wersji 1.2.x, pliki z kodami źródłowymi są zapisane jako UTF-8.
Zanim rozpoczniemy integrację z systemem transakcyjnym musimy posiadać:
- aktywne konto w platnosci.pl – niestety płatności nie udostępniają konta developerskiego, więc wszystkie testy i próby musimy przeprowadzać na swoim własnym koncie. Na szczęście jest możliwość ustawienia testowego sposobu płatności co pozwala na symulowanie transakcji bez ponoszenia kosztów związanych z prowizją.
- komputer widziany z Internetu - w konfiguracji konta w platnosci.pl będziemy musieli podać urle pod którymi będzie dostępna w sieci nasza aplikacja – wynika to ze sposobu działania całego systemu.
Jak są obsługiwane płatności?
Opis interakcji z systemem platnosci.pl jest szczegółowo wyjaśniony w dokumentacji. Tutaj przedstawiam go więc tylko w skróconej postaci przydatnej w zrozumieniu jak działa kod plugina i gdzie ewentualnie szukać przyczyn błędów podczas samodzielnej integracji.
Oto jak przebiega obsługa płatności:
Klient po podjęciu decyzji o zakupie wchodzi na stronę z formularzem który pozwala mu m.in. wybrać sposób opłacenia zamówienia. Po wyborze rodzaju płatności klika ‘Płacę’ i następuje wysłanie formularza do serwera platnosci.pl. W zależności od rodzaju płatności klient jest przekierowywany na stronę banku, do centrum przetwarzającego karty płatnicze albo widzi wypełniony druk przelewu. Klient podaje oczekiwane informacje i kończy swoje zamówienie. W zależności od efektu następuję przekierowanie do Sklepu z informacją o sukcesie albo błędzie (w dokumentacji odpowiednio UrlPozytywny i UrlNegatywny). Ważne: to przekierowanie nie może służyć jako sygnał do przetwarzania danych w sklepie.
Po pewnym czasie (zwykle kilka sekund) do Sklepu przekazywany jest raport który stanowi informację, że status danej transakcji się zmienił. Raport to request GET wysłany przez serwer platnosci.pl na podany w konfiguracji adres w Sklepie. Sklep jest zobowiązany samodzielnie pobrać szczegóły podanej transakcji i potwierdzić odbiór danych. Jeżeli serwer Sklepu jest niedostępny albo nie zostanie odesłane prawidłowe potwierdzenie będą podejmowane kolejne próby. Po setnej nieudanej próbie raport przestaje być wysyłany, a do właściciela sklepu trafia mail z informacją o błędzie. Historia raportów dla każdej z transakcji jest dostępna w panelu administracyjnym.
Wersja rysunkowa prezentuje się tak:
Przykładowa aplikacja
Ponieważ najlepiej uczyć się psując coś co działa przygotowałem testową aplikację na której można przetestować komunikację z systemem transakcyjnym.
Przed uruchomieniem konieczna jest konfiguracja konta w platnosci.pl i ustawienie parametrów konfiguracyjnych w samej aplikacji.
Konfiguracja POSa
Zaczynamy od konfiguracji konta w panelu administracyjnym platnosci.pl.
W istniejącym lub nowym sklepie tworzymy testowy punkt płatności (POS) – to z nim będzie się komunikowała aplikacja. Właśnie tu potrzebny jest publiczny adres do testowego komputera. Wypełniamy kolejno:
- w polu ‘Nazwa punktu płatności’ wpisując np. ‘testowy POS’
- w polu ‘Adres powrotu błędnego’ wpisując:
http://adreskompa/transaction/error?order_id=%orderId%&error_code=%error%&trans_session_id=%sessionId%- tu będzie przekierowanie gdy system transakcyjny wykryje błąd np. braki w danych, - w polu ‘Adres powrotu pozytywnego’ wpisując:
http://adreskompa/transaction/success?order_id=%orderId%&trans_session_id=%sessionId%- tu nastąpi przekierowanie gdy transakcja przebiegnie pomyślnie, - w polu ‘Adres raportów statusu’ wpisując:
http://adreskompa/transaction/report- ten adres będzie wywoływany przez serwer platnosci.pl aby poinformować aplikację o zmianie statusu transakcji, - Kodowanie ustawiamy na UTF-8
Jak widać w adresach UrlPozytywny i UrlNegatywny przekazywane są zwrotnie: numer zamówienia (order_id), kod błędu (error_code) i id transakcji (trans_session_id). W podobny sposób można przekazać jeszcze inne parametry – szczegóły w dokumentacji.
Po utworzeniu POSa system platnosci.pl tworzy dodatkowe parametry. Ich wartości będą potrzebne w aplikacji, ze szczegółów POSa kolejno odczytujemy:
- ‘Id punktu płatności’ dalej przedstawiany jako
pos_id, - ‘Klucz (MD5)’ dalej przedstawiany jako
key1, - ‘Drugi klucz (MD5)‘ dalej przedstawiany jako
key2.
W tabeli z typami płatności włączamy także ‘Płatność testową’. W ten sposób konfiguracja testowego POSa dobiegła końca.
Konfiguracja aplikacji
Drugim krokiem konfiguracyjnym jest przeniesienie parametrów pos_id, key1, key2 do aplikacji. W pliku conf/environment.rb i w okolicach linii 49 wpisujemy wartości dla naszego POSa:
-
TransactionSupport.config.key1 = #tu wartość key1
-
TransactionSupport.config.key2 = #tu wartość key2
-
TransactionSupport.config.pos_id = #tu wartość pos_id
Na zakupy :)
Aplikacja jest gotowa do testów, uruchamiamy więc serwer
ruby script/server
i jeżeli wszystko poszło dobrze pod adresem http://adreskompa/transaction/ powinna się pokazać strona z formularzem do złożenia zamówienia podobnym do tego:
Formularz zawiera tylko absolutnie wymagane pola, usunięcie zawartości np. ‘Identyfikator płatności:’ spowoduje więc przekierowanie na stronę UrlNegatywny. Jeżeli formularz zostanie wysłany w bez zmian powinna się wyświetlić strona pozwalająca na anulowanie lub zatwierdzenie testowej płatności. W ten sposób można stworzyć płatności które będą już widoczne w panelu administracyjnym platnosci.pl jako transakcje testowe.
Link ‘Wersja z wyborem typu płatności via JS’ prowadzi do tej samej strony ale z wyświetloną pełną listą typów płatności. Teraz można już wybrać np. ‘prawdziwy’ przelew i przekazać pieniądze na własne konto w platnosci.pl (oczywiście od tej transakcji zostanie pobrana prowizja :)) . Lista jest tworzona dynamicznie za pomocą JS pobranego z serwisu transakcyjnego.
Moja przykładowa aplikacja daje tylko ogólny pogląd tego jak integruje się aplikację z system platnosci.pl. Przy prawdziwej aplikacji trzeba uwzględnić jeszcze wiele innych aspektów jak choćby: obieg zamówień w aplikacji, aktualizację stanów w zależności od statusu zamówienia, rozsyłanie informacji do klientów itd.
Integracja zawsze jednak będzie zawierała następujące kroki:
- Instalacja plugina
Plugin jest dostępny wprost z repozytorium SVN, ze względu na jego lokalną specyfikę nie rejestrowałem go w globalnym repo. Instalacja wymaga więc wskazania repozytorium:
CODE:
-
ruby script/plugin install http://svn.jarmark.org/rails/transaction_support/
-
- Konfiguracja
Konfiguracja rozumiana zarówno jako ustawienie parametrów POSa w panelu administracyjnym platnosci.pl, jak i wstawienie wartości parametrów
pos_id, key1, key2w conf/environment.rb. - Formularz zamówienia
W helperze widocznym w szablonie w którym jest budowany formularz zamówienia umieszczamy kod:
RUBY:
-
include TransactionSupport::PlatnosciPl::ViewHelper
Powoduje on udostępnienie w szablonie dwóch metod pomocniczych:
new_payment_urliinclude_javascript_paytype.
Metodanew_payment_urlzwraca adres pod który musi być wysłany gotowy formularz zamówienia, wstawiamy ją więc jako atrybut ‘action’ formularza.
Druga metodainclude_javascript_paytypepozwala na włączenie kodu JavaScript z dynamiczną listą typów płatności. Plik jest pobierany wprost z serwera platnosci.pl. -
- Akcja dla raportów
Kluczowym elementem związanym z przetwarzaniem płatności po stronie integrowanej aplikacji jest akcja wywoływana przez serwis transakcyjny. Akcja ta jest odpowiedzialna za pobranie informacji o transakcji z serwera platnosci.pl i dalsze przetworzenie tej informacji z uwzględniem specyfiki aplikacji.
Z grubsza akcja może wyglądać tak:RUBY:
-
def report
-
result = 'OK'
-
begin
-
state = TransactionSupport.get_state(params)
-
unless state.error?
-
# nie ma blędu mozemy rozpocząc przetwarzanie informacji o transakcji
-
# w szczegolnosci dostępne są informacje o stanie transakcji:
-
case
-
when state.new?: logger.info("Nowo rozpoczeta transakcja")
-
when state.received?: logger.info("Pieniadze na koncie...")
-
when state.cancelled?: logger.info("Transakcja zostala anulowana.")
-
end
-
else
-
logger.error("Coś się nie udało...")
-
raise StandardError, "Response failure."
-
end
-
rescue => e
-
logger.error("Wystapil blad. Details:\n#{$!}\n#{$@}")
-
result = "ERROR: #{e.class}:#{e.message}"
-
end
-
render(:text=>result)
-
end
-
- Testy
Metoda testująca integracje z systemem transakcyjnym może wyglądać tak:
RUBY:
-
# wszystko powinno zakonczyc sie pomyslnie sprawdzam transakcje ktora istnieje i ma sie dobrze:)
-
def test_get_state_ok
-
TransactionSupport.config.key1=KEY1
-
TransactionSupport.config.key2=KEY2
-
TransactionSupport.config.pos_id=POS_ID
-
TransactionSupport.config.http_debug_stream = $stderr
-
-
payment = TransactionSupport.get_state('tutaj wartosc trans_session_id zamowienia ktore rzeczywiscie istnieje w sytemie')
-
-
#puts payment.inspect
-
assert_equal false, payment.error?
-
assert payment.received?
-
assert_nil payment.error_code
-
assert_nil payment.error
-
assert_nil payment.error_details
-
end
-
Zakończenie
Jak zaznaczyłem na wstępie przedstawiony tu kod doskonale spisuje się w warunkach produkcyjnych nie jest to jednak implementacja pełnego API jakie udostępniają platnosci.pl. Jednym z możliwych kierunków rozwoju byłoby więc rozszerzenie o brakujące funkcje, innym (chyba ciekawszym) byłoby dodanie obsługi innych systemów transakcyjnych. Konstrukcja plugina pozwala na stosunkowo proste rozszerzenie o connectory do innych systemów – jeżeli znalazłby się ktoś chętny mogę pomóc.
[plugin rails]








Darek Rusin said,
kwiecień 20, 2007 @ 13:22
Ha! Super, dzieki, ze Ci się chciało i znalazłeś czas. W końcu (kiedyś) będę chciał zrobić obsługę kart kredytowych na www.ezosfera.pl i wtedy skorzystam z Twojej pracy.
Przykładowy stos technologiczny dla startupu : Ruby on Rails said,
sierpień 6, 2007 @ 20:25
[…] transaction_support […]