Integracja z systemem PayPal

Pobieranie opłat poprzez system PayPal przy wykorzystaniu języka PHP

20 Październik 2010

Autor: Grzegorz Biela / Weeby.pl

PayPal jest najpopularniejszym na świecie systemem płatności elektronicznych – pozwala na zautomatyzowanie pobierania opłat na witrynie internetowej. System ten jest powszechnie stosowany zwłaszcza w USA, jednak od kilku lat zdobywa popularność również w Polsce. Wdrożenie płatności poprzez PayPal nie jest operacją skomplikowaną, istnieje możliwość integracji z aplikacją napisaną w języku PHP.

Ogólna zasada działania systemu PayPal opiera się na czterech krokach. Pierwszym z nich jest odesłanie użytkownika na stronę PayPal i przekazanie informacji dotyczących zakupowanego produktu. W tym czasie użytkownik (na stronie PayPal) dokonuje płatności, co jest równoznaczne z wywołaniem skryptu błyskawicznego dokonania płatności (Instant Payment Notification) wskazanego przez programistę. Na koniec użytkownik zostaje odesłany na jedną z dwóch podstron mówiących o powodzeniu lub braku powodzenia w dokonaniu transakcji.

Do integracji z PayPal można wykorzystać gotową bibliotekę Free PHP PayPal, którą można pobrać ze strony http://phpweby.com/software/php-paypal. Dostępnych jest wiele konkurencyjnych klas o podobnej funkcjonalności, jednak wskazane rozwiązanie jest bardzo przyjazne we wdrożeniu i stosowaniu.

Pierwszy skrypt powinien wygenerować formularz zapłaty – można go oczywiście stworzyć „ręcznie” pisząc odpowiedni kod HTML, jednakże w większości przypadków zachodzi potrzeba wygenerowania formularza automatycznie, na podstawie danych użytkownika i sprzedawanego produktu lub usługi. Wykorzystując bibliotekę Free PHP PayPal sprowadza się to do następującego kodu:

<?php

include_once('paypal.inc.php');
$paypal = new paypal();

// Ustawienie nagłówków
$paypal->headers_nocache();

// Cena produktu/usługi
$paypal->price=50;

// Adres skryptu IPN
$paypal->ipn='http://www.przykladowy-sklep.pl/ipn.php';

// Ustawienie powtarzalności pobierania oplat (jednorazowo lub wskazanie
// co jaki czas ma być pobierana podana kwota
$paypal->enable_payment();
// lub
$paypal->recurring_year($r);
// lub
$paypal->recurring_month($r);
// lub
$paypal->recurring_day($r); 

// Ustawienie waluty
$paypal->add('currency_code', 'PLN');

// Adres e-mail właściciela sklepu
$paypal->add('business', 'adres@email.pl');

// Nazwa produktu
$paypal->add('item_name','Nazwa produktu');

// Numer produktu
$paypal->add('item_number','1238');

// Ilość
$paypal->add('quantity',1);

// Adres strony powodzenia transakcji
$paypal->add('return','http://www.przykladowy-sklep.pl/success.php');

// Adres strony niepowodzenia
$paypal->add('cancel_return','http://www.przykladowy-sklep.pl/failed.php');

// Wyświetlenie formularza
$paypal->output_form();

Wygląd formularza można dostosować poprzez metodę output_form().

Po wysłaniu formularza użytkownik loguje się na stronie PayPal i następnie klika w przycisk „zapłać”. W tym momencie PayPal wywołuje skrypt ipn.php na naszym serwerze. Transakcja dokonuje się w momencie sprawdzenia danych przesłanych przez system PayPal. Dlatego należy przy tym przewidzieć takie sytuacje, gdy skrypt się wykona na serwerze, a np. baza danych zwróci błąd w czasie próby zapisu danych. Aby zapobiec opisanej powyżej sytuacji można, w przypadku błędu bazy danych zalogować informacje do pliku:

<?php

include_once('paypal.inc.php');
$paypal=new paypal();

// Ustawienie logowania transakcji
// $paypal->log=1;
// $paypal->logfile='/home/uzytkownik/log_paypal.txt';

// Sprawdzenie poprawności tokena
if($paypal->validate_ipn())
{
	// Sprawdzenie powodzenia transakcji
	if($paypal->payment_success==1)
	{
		// Transakcja zakończona powodzeniem
		// Pobranie danych o produkcie
		$id = intval($paypal->posted_data['item_number']);

		// Odpowiednia reakcja na dokonanie transakcji
		//(np. oznaczenie zamówienia jako opłacone)
	}
	else
	{
		// Transakcja nie powiodła się lub użytkownik
		// wycofał się z jej sfinalizowania
	}
}
else
{
	// Niewłaściwy token operacji (najprawdopodobniej ktoś
	// ręcznie próbuje wywołać skrypt). Tu można zwrócić np. w nagłówkach błąd 404
}

Po uruchomieniu skryptu ipn.php system Paypal przekierowuje użytkownika, w zależności od statusu transakcji, na stronę dokonania lub braku dokonania transakcji. Dodatkowo do tych skryptów zostaje przekazana tablica $_POST zawierająca informacje o stanie transakcji.

Źródła:
https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=developer/e_howto_admin_IPNIntro
http://paypal.com
http://phpweby.com/software/php-paypal

18 komentarzy do wpisu:

  1. A czy da się jakoś dodać dodatkowe parametry do płatności? Muszę przesłać dwie dodatkowe informacje od nadawcy i nie mogę znaleźć takiej możliwości. W normalnym koszyku PayPal jest taka możliwość…

  2. W dokumentacji PayPala (pierwszy link ze źródeł pod artykułem) jest pole „custom”, w którym można zawrzeć dowolne, dodatkowe informacje. Użycie tego wygląda następująco:

    $paypal->add(‘custom’, „dodatkowe informacje”);

  3. O – dzięki wielkie. Klasa przyda się na pewno :)

  4. Mam jeszcze jeden problem. Do tych moich zmiennych dostałem się w ipn.php przez $_POST["custom"]. Nie wiem jednak, jak w ipn.php odczytać takie dane, jak ID, kwotę i walutę transakcji.

  5. Dane transakcji jak id, kwota czy waluta przychodzą po prostu POSTem, czyli wystarczy:

    echo $_POST['mc_fee']; // kwota
    echo $_POST['mc_currency']; // waluta
    echo $_POST['tax']; // podatek
    echo $_POST['item_number']; // id produktu

    etc.

  6. Czarek pisze:

    Cześć,
    Fajnie, że opisaliście tą klasę, jednak mam z nią problem.
    Po dokonaniu transakcji validate_ipn() zwraca 0.
    Ciągle nie przechodzę validacji. Co to może być za problem?

    (Nie mam pojęcie co się stało, może PayPal zmienił coś w specyfikacji?)

    Mam jeszcze jedno pytanie.
    Jaka jest różnica między skryptami:

    // Adres skryptu IPN
    $paypal->ipn=’http://www.przykladowy-sklep.pl/ipn.php’;

    a

    // Adres strony powodzenia transakcji
    $paypal->add(‘return’,’http://www.przykladowy-sklep.pl/success.php‘);

    Czy tu nie chodzi o to samo?

    Z góry dzięki za pomoc!

  7. Ciężko powiedzieć dlaczego validate_ipn() zwraca 0 – należałoby zbadać po kolei wykonywanie się tej funkcji i zobaczyć jaka dokładnie odpowiedź przychodzi z PayPala (a może w ogóle nie przychodzi, gdyż nie dociera do niego żądanie weryfikacji).

    Co do adresu IPN i adresu strony powodzenia transakcji – nie są to absolutnie „te same” skrypty. Adres powodzenia transakcji jest to URL, na który użytkownik zostanie przekierowany po zakończeniu transakcji – powinno się tam jedynie wyświetlić komunikat typu „Dziękujemy za płatność” – należy przyjąć założenie, że ten adres jest publiczny i każdy może go odwiedzić, więc w żaden sposób nie można tam sprawdzać poprawności dokonania transakcji – jedynie wyświetlić komunikat.

    Adres skryptu IPN w założeniu jest ukryty przed użytkownikiem (aczkolwiek można go podejrzeć w formularzu (pole hidden)) i ma służyć do komunikacji pomiędzy serwerem PayPala a skryptem odpowiedzialnym za sprawdzenie czy transakcja doszła do skutku.

  8. Hester pisze:

    Hej mam takie pytanko próbowałem na rożne sposoby ale chodzi mianowicie o to że jeśli klient zapłaci ma dodawać zmienną do sql nie wiem gdzie ten kod dokładnie dodac

  9. Czarek pisze:

    Wojciech: Dzięki serdeczne za odpowiedź. Już do tego doszedłem, wszystko śmiga aż miło, jedynie martwię się tym, że nie można zablokować dostępu do skryptu IPN tak aby był wywoływany tylko przez serwer PayPal. Myślałem, że .htaccess da radę ale „pagib” ;)

    Pozdro.

  10. Bman pisze:

    Dzięki za artykuł, bardzo się przyda.
    Chciałbym jeszcze zapytać czy jest możliwość wysłania takiej płatności testowo, aby sprawdzić poprawność integracji oprogramowania sklepu z systemem PayPala. Przejrzałem z grubsza specyfikacje zmiennych jakie można wysłać w formularzu do serwera PayPala ale opcji testowej tam nie widzę. Jest jakiś na to sposób?

  11. Odnośnie testowania to polecam na stronie PayPala poszukać o tzw. „Sandbox” – środowisku testowym PayPala.

    Manual w wersji PDF do pobrania: https://cms.paypal.com/cms_content/US/en_US/files/developer/PP_Sandbox_UserGuide.pdf

  12. Witam ponownie :)

    Mam jeszcze jedno pytanko. Da się w jakiś sposób wymusić, w jakim języku ma się ładować witryna PayPal po kliknięciu „zapłać” w koszyku? Generalnie mam anglojęzyczną stronę dla obcokrajowców, ale płatności przyjmuję tylko w PLN. Dopiero dzisiaj ktoś mi zwrócił uwagę, że także poza granicami naszego kraju serwis PP ładuje się moim klientom w polskiej wersji językowej. Prawdopodobnie przyczyną jest wybrana waluta. Da się to jakoś obejść (żeby mieć i walutę w PLN i serwis PP ładowany w angielskiej wersji językowej)?

    Z góry dziękuję za pomoc!

  13. Daniel pisze:

    Witam. Mam ten sam problem co kolega Łukasz Więcek. Jednak walutą u mnie jest EUR, a mimo to strona płatności jest w języku polskim. Pisano już o tym cztery lata temu i jak dotąd, jak widać nic się nie zmieniło – http://hacking.pl/pl/news-6404-PayPal_mocno_utrudnia_dzialalnosc_polskim_przedsiebiorcom.html
    Chyba że jest jakiś sposób ustawienia języka strony płatności na angielski?

    Pozdrawiam,
    Daniel

    • Jakiś czas temu znalazłem rozwiązanie :) Wystarczy w dodać jedną zmienną:

      $paypal->add(‘lc’,US);

      Lub bezpośrednio w formularzu:

      Pozdrawiam!

    • Daniel pisze:

      Dzieki, tez znalazlem to rozwiazanie wczoraj zaraz po napisaniu tamtego posta :)

  14. bebidek pisze:

    Mam takie pytanie:
    Czy na przykład, gdy podaję walutę PLN to cenę(price) podaję w złotówkach czy groszach?

  15. Dominik pisze:

    Ktoś ma pomysł dlaczego payment_success nie ustawia się na 1 pomimo, że transakcja przebiega poprawnie (ipn poprawnie zwalidowany, po dokonanu płatności przenosi mnie na stronę, na która powinien w razie pomyślnej transakcji) ???
    Będę bardzo wdzięczny za każdną wskazówkę ;)

Dodaj komentarz