Introduction To Paypal Payment Data Transfer
Normally payment data is returned in the browser url. We have to extract the details using $_GET and process it on our application in order to complete the payment. Although paypal pdt is a reliable way of getting payment data, there are some issues in certain situations. For example payment data will be lost when the user closes the browser after completing the payment, without allowing the browser to automatically redirect to your application. In such cases there is a separate payment data transfer method called Instant Payment Notifications (IPN). In the next tutorial I’ll talk more about using IPN.
Following section contains a sample url with payment data which was received after a successful payment. Look at the set of pdt variables after the success.php file. These variables contains the data needed to capture the payment.
https://innovativephp.com/demo/paypal-process/success.php?tx=6WL26360NV805022T&st=Completed&amt=12.99&cc=USD&cm=&item_number=
Extracting Paypal Payment Data From URL
In order to save payment details to your application, you need to extract the required data from URL. If you are using core php without any framework, you can extract the data using $_GET variables. Following code shows you how to extract data using $_GET.
$paypal_transaction_token = $_GET['tx']; $payment_status = $_GET['st']; $payment_amount = $_GET['amt']; $payment_currency = $_GET['cc']; $payment_item = $_GET['item_number'];
If you are using php frameworks, you might not be able to extract the payment details using $_GET. In such cases you can use the url components to extract the required data using following code.
$this_url = $_SERVER["REQUEST_URI"]; $var_set = explode("?", $this_url); $paypal_transaction_token = ''; $payment_status = ''; $payment_amount = ''; $payment_currency = ''; $payment_item = ''; if(count($var_set) > 1) { $paras = explode("&",$var_set[1]); for($i = 0; $i < count($paras); $i++) { $tmp_vals = explode('=', $paras[$i]); if($tmp_vals[0] == 'tx') { $paypal_transaction_token = $tmp_vals[1]; } if($tmp_vals[0] == 'st') { $payment_status = $tmp_vals[1]; } if($tmp_vals[0] == 'amt') { $payment_amount = $tmp_vals[1]; } if($tmp_vals[0] == 'cc') { $payment_currency = $tmp_vals[1]; } if($tmp_vals[0] == 'item_number') { $payment_item = $tmp_vals[1]; } } }
Validating Payment Data Using PHP CURL Library
Paypal sends payment details using URL parameters. This has lot of security risks if you are only relying on URL parameters for payment validation. Anyone can change the URL parameters and modify the payment details. For example if someone changes the amount and item name in URL, the application will record false details providing the user with an item of higher value. So that is why paypal sends a payment token to validate the payment details. Next section will show you how to avoid this security risks.
We can use PHP Curl known as Client URL Library to make a request to paypal using the pdt token and validate the payment data. When you use curl, you can directly connect to the server using one of http, https, ftp, gopher, telnet, dict, file, and ldap protocols. In this method you can not see anything happening on browser since this is an internal request. Hence users will not be able to modify the payment data. Curl makes the request using payment data and returns the complete payment details to the application.
Paypal provides a unique identifier called pdt token to validate payment data. This is sent via the URL with the parameter name tx. Extract this value and send it to paypal to get the complete payment details.
Following code can be used in the return page to validate the payment details after the payment is completed.
$this_url = $_SERVER["REQUEST_URI"]; $var_set = explode("?", $this_url); $paypal_transaction_token = ''; $payment_status = ''; $payment_amount = ''; $payment_currency = ''; $payment_item = '';
if(count($var_set) > 1) { $paras = explode("&",$var_set[1]); for($i = 0; $i < count($paras); $i++) { $tmp_vals = explode('=', $paras[$i]); if($tmp_vals[0] == 'tx') { $paypal_transaction_token = $tmp_vals[1]; } if($tmp_vals[0] == 'st') { $payment_status = $tmp_vals[1]; } if($tmp_vals[0] == 'amt') { $payment_amount = $tmp_vals[1]; } if($tmp_vals[0] == 'cc') { $payment_currency = $tmp_vals[1]; } if($tmp_vals[0] == 'item_number') { $payment_item = $tmp_vals[1]; } } }
/* Part - 1 */ $req = 'cmd=_notify-synch'; $req .= "&tx=$paypal_transaction_token&at=A9L0IFi0HZXfefRWEfFR-6AiMXD7xa2De3Svm29K1WbjqH2Bcn"; // test key
/* Part - 2 */ $ipnexec = curl_init(); curl_setopt($ipnexec, CURLOPT_URL, "https://www.sandbox.paypal.com/webscr&"); // test url //curl_setopt($ipnexec, CURLOPT_URL, 'https://www.paypal.com/cgi-bin/webscr'); // live url curl_setopt($ipnexec, CURLOPT_HEADER, 0); curl_setopt($ipnexec, CURLOPT_USERAGENT, 'Server Software: '.@$_SERVER['SERVER_SOFTWARE'].' PHP Version: '.phpversion()); curl_setopt($ipnexec, CURLOPT_REFERER, $_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'].@$_SERVER['QUERY_STRING']); curl_setopt($ipnexec, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($ipnexec, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($ipnexec, CURLOPT_POST, 1); curl_setopt($ipnexec, CURLOPT_POSTFIELDS, $req); curl_setopt($ipnexec, CURLOPT_FOLLOWLOCATION, 0); curl_setopt($ipnexec, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ipnexec, CURLOPT_TIMEOUT, 30); $ipnresult = trim(curl_exec($ipnexec)); $ipnresult = "status=".$ipnresult; curl_close($ipnexec);
/* Part - 3 */ $parameter_value_array = explode("\n", $ipnresult); $value_array =array(); foreach ($parameter_value_array as $key=>$value) { $key_values = explode("=", $value); $value_array[$key_values[0]] = $key_values[1]; } if(array_key_exists("status", $value_array) && $value_array['status'] == 'SUCCESS') { print_r($value_array); }
- Above code is used to validate the payment details received from payment data transfer using the paypal pdt token. I have break the code into 3 parts for simplification.
- In part 1 we prepare the request variables. Command is specified as _notify-synch and we have assigned the paypal pdt token received from payment data transfer.
- Also we have to provide the paypal identity token of our application. This is configured in the Website Payment Preferences section in business account. Click here for more details.
- Part 2 contains the necessary configurations to use Curl request. In CURLOPT_URL parameter I have defined the sandbox url. If you are using this code in live payments use the live site url shown under that using comments.
- You can change other parameters depending on your requirements. I am going to keep the other parameters in it's default values.
- In part 2 request is made to paypal using curl and the response is stored in $ipnresult variable.
- In part 3 I have extracted the returned array and used some array functions to assign the required data to $value_array.
- Now we have the response from paypal and we can use it to do the validations. You can check whether actual payment details matches the confirmed payment details using paypal payment token.
- Following code contains how the $value_array will be structured using a pdt example request.
Use the values of this payment details array to verify the payment details received from paypal with the item details sent to paypal and save in your application database.
Array ( [status] => SUCCESS [mc_gross] => 12.99 [protection_eligibility] => Eligible [address_status] => confirmed [payer_id] => ZW9LAU3QP3PBY [tax] => 0.00 [address_street] => 1+Main+St [payment_date] => 00%3A05%3A44+Oct+05%2C+2011+PDT [payment_status] => Completed [charset] => windows-1252 [address_zip] => 95131 [first_name] => Test [mc_fee] => 0.68 [address_country_code] => US [address_name] => Test+User [custom] => [payer_status] => verified [business] => innova_1316586326_biz%40gmail.com [address_country] => United+States [address_city] => San+Jose [quantity] => 1 [payer_email] => innova_1316585354_per%40gmail.com [txn_id] => 7M988566AJ442924C [payment_type] => instant [last_name] => User [address_state] => CA [receiver_email] => innova_1316586326_biz%40gmail.com [payment_fee] => 0.68 [receiver_id] => 4AE4S9WKM34MA [txn_type] => web_accept [item_name] => Innovative+Book [mc_currency] => USD [item_number] => [residence_country] => US [handling_amount] => 0.00 [transaction_subject] => Innovative+Book [payment_gross] => 12.99 [shipping] => 0.00 )
October 11th, 2011 at 3:45 pm
You have showed great perseverance behind the blog. It
October 12th, 2011 at 5:52 pm
Awsome website! I will for sure Check it more often!
October 23rd, 2011 at 5:25 am
Very nice article and straight to the point. I am not sure if this is actually the best place to ask but do you people have any thoughts on where to hire some professional writers? Thx
October 29th, 2011 at 6:04 am
Simply desire to say your article is as amazing. The clearness in your post is simply great and i could assume you are an expert on this subject. Well with your permission let me to grab your RSS feed to keep up to date with forthcoming post. Thanks a million and please keep up the gratifying work.
October 31st, 2011 at 3:50 pm
Thanks for investing time and resources to submit this document. This blog post also has been beneficial in my opinion.