Archiwa tagu: paypal

Paypal – wstÄ?p

Do napisania tego oto tutorialu zmotywowa??y mnie wiele rzeczy po pierwsze w polskim internecie nie ma zbyt wiele na temat p??atno??ci paypal’em. Znalaz??em na kilku forach zapytania na ten temat. Z czego sam jedno napisa??em na forum.php.pl. DrugÄ? przes??ankÄ? kt??ra u??wiadomi??a, ??e paypal zaczyna zdobywaÄ? polski rynek p??atno??ci online jest fakt umowy jakÄ? paypal.com podpisa?? z p??atno??ci.pl i ju?? nied??ugo bÄ?dziemy mogli siÄ? cieszyÄ? p??aceniem za us??ugi i produkty w ten wygodny spos??b. KolejnÄ? sprawÄ?, kt??ra pokaza??a mi jak bardzo szkodliwÄ? rzeczÄ? mo??e byÄ? nieumiejÄ?tne korzystanie z „Buy Now” (tych nie kodowanych) gdzie wystarczy ze ??r??d??a strony wyciÄ?Ä?:

<input type="hidden" name="return" value="url_po_udanej_transakcji" />

by uzyskaÄ? dostÄ?p do zasobu kt??ry chcemy kupiÄ?. NastÄ?pny fakt wyp??ynÄ??? na ??wiat??o dzienne gdy sam pisa??em obs??ugÄ? IPN na Paypal’u i zobaczy??em, ??e nawet tutorial’e i przyk??ady na stronie developer center @ paypal majÄ? b??Ä?dy(mnie szczeg??lnie ineteresowa?? ten do php4). A Koniec ko??c??w w poszukiwaniu gotowych rozwiÄ?za?? tj. klas, funkcji kt??re mog??y by zaspokoiÄ? moje potrzeby. Znalaz??em dwa takie rozwiÄ?zania. Pierwsze z nich na phpclasses.org by??o mocno rozbudowane i zabezpieczone szyfrowaniem. Jednak mia??o jednÄ? podstawowÄ? wadÄ? wymaga??o „doklejenia” kolejnych 3 du??ych bibliotek. Natomiast drugie z nich po wstÄ?pnych testach okaza??o siÄ? nie dzia??aÄ? tak jak bym chcia??, wiÄ?c postanowi??em napisaÄ? co?? w??asnego.
Tyle s??owem wstÄ?pu teraz przedstawie czego bÄ?dziemy potrzebowaÄ? do wdro??enia p??atno??ci paypal’em na naszej stronie.

Po pierwsze do test??w paypal udostÄ?pnia nam sandbox. ??eby do owej „piaskownicy” uzyskaÄ? dostÄ?p trzeba za??o??yÄ? sobie konto na: developer.paypal.com . Po za??o??eniu konta i potwierdzeniu prawdziwo??ci skrzynki e-mail. Mamy mo??liwo??Ä? za??o??enia kont testowych. BÄ?dÄ? nam potrzebne takie dwa: pierwsze buissnes account do testowania p??atno??ci i wygenerowania kodu button??w na, kt??rych bÄ?dziemy testowali nasze rozwiÄ?zania, drugie natomiast kupujÄ?cego po to by zbadaÄ? sam proces dokonywania p??atno??ci.

Uwaga! wa??ne do testowania p??atno??ci na sandbox’ie wymaga bycia zalogowanym na developer.paypal.com

Aby zrozumieÄ? temat bardziej sp??jrzmy na poni??szy schemat.

Schemat Dzia??ania IPN w p??atno??ciach paypal.com

Dla klienta zasada jest prosta. Rejestruje siÄ? na naszej stronie. Op??aca us??ugÄ? np. abonament na dostÄ?p do poprzednich wyda?? naszego magazynu w plikach pdf po przez klikniÄ?cie Buy Now. Jest przekierowany na strone paypal’a gdzie loguje siÄ? na swoje konto lub p??aci kartÄ? p??atniczÄ?. Po pozytywnym zako??czeniu transakcji wraca na naszÄ? stronÄ? z podziÄ?kowaniami tzw „return”. Paypal gubi ka??dÄ? sesje wiÄ?c nie ma co liczyÄ? na jej odzyskanie po powrocie. RozwiÄ?zaniem najprostszym jest odes??anie klienta po podziÄ?kowaniu do formularza logowania.

Serwer paypala opr??cz tego. ??e przeprowadza ca??Ä? transakcje i odpowiedzialno??Ä? za wpisane tam poufne dane takie jak numer karty kredytowej sÄ? po jego stronie. To jeszcze przekazuje nam dane na temat transakcji za po??rednictwem IPN(instant payment notification). Dzieje siÄ? to w nastÄ?pujÄ?cy spos??b. Po dokonaniu wp??aty na paypalu wysy??a do naszego skryptu na adres podany w:

<input type="hidden" name="notify_url" value="url_do_skryptu_obs??ugujÄ?cego_ipn"  />

przekazuje nam pule zmiennych metodÄ? POST min.

$invoice = $_POST['invoice'];

$receiver_email = $_POST['receiver_email'];

$item_name = $_POST['item_name'];

$item_number = $_POST['item_number'];

$quantity= $_POST['invoice'];

$payment_status = $_POST['payment_status'];

$pending_reason = $_POST['pending_reason'];

$payment_date = $_POST['payment_date'];

$payment_gross = $_POST['payment_gross'];

$payment_fee = $_POST['payment_fee'];

$payment_amount = $_POST['mc_gross'];

$payment_currency = $_POST['mc_currency'];

$txn_id = $_POST['txn_id'];

$txn_type = $_POST['txn_type'];

$first_name = $_POST['first_name'];

$last_name = $_POST['last_name'];

$address_street = $_POST['address_street'];

$address_city = $_POST['address_city'];

$address_state = $_POST['address_state'];

$address_zip = $_POST['address_zip'];

$address_country = $_POST['address_country'];

$payer_email = $_POST['payer_email'];

$address_status = $_POST['address_status'];

$payment_type = $_POST['payment_type'];

$notify_version = $_POST['notify_version'];

$verify_sign =$_POST['verify_sign'];

DziÄ?ki tym zmiennym mo??emy po pierwsze rozpoznaÄ? czy p??atno??Ä? zosta??a zako??czona powodzeniem:

$_POST['payment_status'] == "succes"

Oraz poznaÄ? bli??ej dane naszego klienta. Jego dane jakie poda?? na naszej stronie mogÄ? siÄ? r????niÄ? od tych danych jakie widniejÄ? na paypalu. Mo??emy je wykorzystaÄ? jako powiÄ?kszenie naszej bazy do mailing??w z promocjami, bÄ?d?? zachowaÄ? je tylko po to by rejestrowaÄ? sprzeda?? prowadzonÄ? na naszej stronie.

Jednak zanim obs??u??ymy otrzymane ??Ä?danie musimy sprawdziÄ? czy aby na pewno pochodzi z paypal’a. Wystarczy z??o??yÄ? wszystkie zmienne przekazane postem w ciÄ?g znak??w typu zmienna1=5&zmienna2=6&….. itd. Jednak zanim to jednak zrobimy musimy dodaÄ? na samym poczÄ?tku komendÄ?, kt??ra poinformuje paypal, ??e chcemy dokonaÄ? potwierdzenia czy takie ??Ä?danie zosta??o wys??ane przez paypal czy te?? nie. Zrobimy to nastÄ?pujÄ?cym kodem:

$req = 'cmd=_notify-validate'; //dok??adamy komendÄ? z pro??bÄ? o potwierdzenie tego powiadomienia o p??atno??ci
foreach ($_POST as $key => $value) {
$value = urlencode($value);
$req .= "&$key=$value";

}

//zmienna req teraz przechowuje wszystkie zmienne z $_POST w postaci kt??rÄ? opisywa??em wcze??niej

NastÄ?pnie wystarczy wys??aÄ? takie zapytanie do serwera paypala. SÄ? dwie szko??y wysy??ania, albo fsockopen() albo za pomocÄ? klasy cURL. Oba sÄ? poprawne. Ja zaprezentuje fragment kodu wykorzystujÄ?cy pierwszÄ? z nich.

$header .= "POST /cgi-bin/webscr HTTP/1.0\r\n"; // ustawiamy nag????wki zapytania.

$header .= "Content-Type: application/x-www-form-urlencoded\r\n";

$header .= "Content-Length: " . strlen($req) . "\r\n\r\n"; // w tej linii zamieszczamy d??ugo??Ä? naszego zapytania

$fp = fsockopen (paypal_adr, 80, $errno, $errstr, 30); //sta??a paypal_adr jest adresem na kt??ry wysy??amy nasze zapytanie z pro??bÄ? o validacje

Sta??a paypal_adr mo??e mieÄ? dwie warto??ci: pierwszÄ? testowÄ? https://www.sandbox.paypal.com lub drugÄ? ju?? w pe??ni funkcjonalnÄ? https://www.paypal.com czasami pojawia siÄ? problem z https:// poniewa?? niekt??re serwery nie majÄ? skonfigurowanego portu.

Otwarli??my deskryptor portu $fp. Teraz musimy wys??aÄ? nasze dane do validacji.

if (!$fp) { // sprawdzamy czy wszystko ok z naszym po??Ä?czeniem je??eli nie jest to deskryptor przyjmuje warto??Ä? false
	// tutaj mo??emy napisaÄ? obs??ugÄ? HTTP ERROR
} else {
	fputs ($fp, $header . $req); // je??eli deskryptor jest ok to wysy??amy mu nasze nag????wki po??Ä?czone z zapytaniem o validacje powiadomienia

Je??eli ju?? wys??ali??my naszÄ? pro??be o potwierdzenie ??Ä?dania teraz musimy obs??u??yÄ? odpowied?? serwera paypal, kt??ry zwr??ci nam string z informacjÄ? czy wszystko posz??o tak jak powinno czy te?? to odwo??anie by??o tylko pr??bÄ? wy??udzenia od nas towaru.
Zatem zaczynamy od odczytania odpowiedzi do p??ty do p??ki nie dostaniemy znaku ko??ca pliku. Kod kt??ry siÄ? tym zajmie mo??e wyglÄ?daÄ? tak:

while (!feof($fp)) {
	$res = fgets ($fp, 1024);

Otrzymali??my wiÄ?c ju?? ca??Ä? zawarto??Ä? odpowiedzi i przechowujemy jÄ? w zmiennej $res. Teraz trzeba by by??o sprawdziÄ? czy ta p??atno??Ä? jest potwierdzona czy te?? nie. Do tego pos??u??y nam funkcja kt??ra por??wnuje binarnie dwa ciÄ?gi znak??w strcmp(). Je??eli oba por??wnywane ciÄ?gi sÄ? identyczne to funkcja zwraca 0. Kod, kt??ry sprawdzi odpowied?? m??g?? by wyglÄ?daÄ? tak:

if (strcmp($res, "VERIFIED")==0) {
	//Sprawdzamy czy transakcja ma status jako zako??czona
	if (strcmp ($payment_status, "Completed") == 0) {
		//je??eli tak to mo??emy spokojnie dalej przetwarzaÄ? dane
	}
}else if(strcmp($res, "INVALID")==0){
	// mo??emy zarejstrowaÄ? do pliku wszystkie pr??by atak??w na nasz serwis np. tak:
	$fplog = fopen('ipnlog.txt','a');
	fwrite($fplog, gmstrftime ("%b %d %Y %H:%M:%S", time())." -- ".$res." -- ".$req."\n");
	fclose($fplog);
}

Zatem wiecie ju?? na jakiej zasadzie mo??na obs??ugiwaÄ? IPN otrzymany od paypal’a. Nie taki diabe?? straszny jak siÄ? okazuje. Jednak mi on napsu?? sporo krwi. CiÄ?g dalszy wkr??tce nastÄ?pi jak tylko znajdÄ? trochÄ? czasu.