PayPal is notorious for being hard to interface with. People install eStore packages just because they don’t want to deal with it! But I finally found a way to access the data fairly reliably.
If you are trying to use PayPal for your web site payments and want as simple an interface as possible, I highly recommend THIS tutorial. All the others I tried didn’t work. This one was written in 2010 and uses cURL, and remarkably, it actually works.
Step 3: Catch the return
The URL they are returned to could for example look like this (split for easier reading):http://business.example.com/order/123/?tx=6BC88318RN685282M
As you can see we get some GET parameters to work with here, but the only one you need is the Transaction ID,
$tx = $_GET[‘tx’];
// Further processing
The reason we don’t care about the rest is that they’re not trustworthy at all. Since they are GET parameters we can easily tamper with them in the address bar of our browser, and we just can’t have any of that, can we?
To get good and trustworthy data we need to send this transaction id back to PayPal together with our PDT Identity Token. If the id and token are valid, we will get real and actual transaction details back in return.
Step 4: Do a POST request back to PayPal
Sending the Transaction ID and our PDT Identity Token back to PayPal can be done in various ways from PHP. I used cURL which I found to be pretty clean and easy to use.// Init cURL
$request = curl_init();// Set request options
CURLOPT_URL => ‘https://www.sandbox.paypal.com/cgi-bin/webscr’,
CURLOPT_POST => TRUE,
CURLOPT_POSTFIELDS => http_build_query(array
‘cmd’ => ‘_notify-synch’,
‘tx’ => $tx,
‘at’ => $your_pdt_identity_token,
CURLOPT_RETURNTRANSFER => TRUE,
CURLOPT_HEADER => FALSE,
// CURLOPT_SSL_VERIFYPEER => TRUE,
// CURLOPT_CAINFO => ‘cacert.pem’,
// Execute request and get response and status code
$response = curl_exec($request);
$status = curl_getinfo($request, CURLINFO_HTTP_CODE);
// Close connection
The cURL options we set means roughly: Use this URL, do a POST, send these variables, return the transfer as a string when I call
curl_execand do not include the HTTP headers in that string. The reason behind the last two are in this post. I’ve commented them out, and if it works without them, just leave them out. For me it worked fine on one server, while on another I had to add them.
Note: For security reasons, PayPal will only allow you to use the transaction id to get a response up to 5 times. After that it will be invalidated and you will get an error back instead of the transaction data. Fair enough for regular use, but found it a bit annoying while developing since it took some tries to get the result I wanted
Step 5: Check the response
The response will be a string that looks something like this:SUCCESS
To make sure everything is well we must check that the status code is 200 and that the first line says SUCCESS. On failure it would say FAIL, or something like that. We can do that like this:if($status == 200 AND strpos($response, ‘SUCCESS’) === 0)
// Further processing
// Log the error, ignore it, whatever
That response is not very useful right now though. Even if it is valid, the string is just, well, a long string. Not to mention it’s URL encoded and possibly in the wrong character encoding. We want to clean it up and turn it into a much more handy associative array.
Step 6: Clean up the response
We want to remove the first line, URL decode the string, turn it into an associative array and convert the encoding if needed. This is how you might do that:// Remove SUCCESS part (7 characters long)
$response = substr($response, 7);// URL decode
$response = urldecode($response);
// Turn into associative array
preg_match_all(‘/^([^=\s]++)=(.*+)/m’, $response, $m, PREG_PATTERN_ORDER);
$response = array_combine($m, $m);
// Fix character encoding if different from UTF-8 (in my case)
if(isset($response[‘charset’]) AND strtoupper($response[‘charset’]) !== ‘UTF-8’)
foreach($response as $key => &$value)
$value = mb_convert_encoding($value, ‘UTF-8’, $response[‘charset’]);
$response[‘charset_original’] = $response[‘charset’];
$response[‘charset’] = ‘UTF-8’;
// Sort on keys for readability (handy when debugging)
$responseshould now contain a nice and sorted associative array with the correct encoding and it’s ready to be used for whatever purpose you need.