Setting Up Paypal IPN, Trials and Tribulations

Getting Started

This PDF File is a great place to start.

It will show you how to set up IPN notifications, what to expect from paypal, the process to verify the notification and even gives you some sample code.

IPN, while not required, is a great way to know when you’ve actually gotten paid. This way you don not have to sift through the mountains of emails of profile creation, payment reversed, payment canceled, payment completed, etc. Getting the IPN that says Complete lets you know to make a shipment because you’ve actually gotten paid. At least in theory.

Example Code

The example code provided by Paypal is written in PHP and is a good starting place.

I’m repeating it below, for the most part, with my modifications to ignore IPN notifications I don’t care about and to use CURL instead of fgets


There are two ways to test before pushing up to production which ultimately leads to the problem. You can force an IPN to be sent to you through the sandbox with 100% test data or actually do a test purchase.

Following the code provided leads to the issue. The forced test IPN works quite nicely; you get it, send it back and Paypal says VERIFIED every single time. Doing a test transaction however returns INVALID without fail.

I found the solution on this site. The long and short is there is a carriage return between address line 1 and line 2 that paypal represents as %0D%0A but is represented as %0A in PHP 5.2.

So below is what I hope is simplified code, assumes you have magic quotes turned on, uses curl and has the carriage return fix:

  1. <?php
  2. $PAYPAL_URL = “”; //or
  3. $PAYPAL_EMAIL = “[email protected]”; //usually your login email
  5. if($_POST[‘txn_id’] && $_POST[‘receiver_email’] == $PAYPAL_EMAIL){
  6. //Check for Primary PayPal email, also ignores profile creation IPNs, just care about payments for now
  8. $url = “$PAYPAL_URL/cgi-bin/webscr”;
  9. $http_status = 0;
  10. $params = “cmd=_notify-validate”;
  12. foreach ($_POST as $key => $value){
  13. $value = urlencode(stripslashes($value));
  14. $value = preg_replace(‘/(.*[^%^0^D])(%0A)(.*)/i’,’${1}%0D%0A${3}’,$value);//return fix
  15. $params .= “&$key=$value”;
  16. }
  18. $response = http($url, $http_status, $params);
  19. if($response == “VERIFIED” && $http_status == 200){
  20. //Check that txn_id has not been previously processed
  21. //Process the IPN recieved based on the payment_status
  22. }
  23. else{
  24. //store for further investigation or ignore
  25. }
  26. }
  28. function http($url, &$http_status, $post_data){
  29. $ch = curl_init();
  30. if (defined(“CURL_CA_BUNDLE_PATH”)) curl_setopt($ch, CURLOPT_CAINFO, CURL_CA_BUNDLE_PATH);
  31. curl_setopt($ch, CURLOPT_URL, $url);
  32. curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
  33. curl_setopt($ch, CURLOPT_TIMEOUT, 30);
  34. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  36. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
  37. if (isset($post_data)){
  38. curl_setopt($ch, CURLOPT_POST, 1);
  39. curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
  40. }
  41. $r = curl_exec($ch);
  42. $http_status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  44. curl_close ($ch);
  45. return $r;
  46. }
  47. ?>

3 thoughts on “Setting Up Paypal IPN, Trials and Tribulations

  1. Francine  

    Finally i quit my regular job, now i earn a lot of money online you should try too, just
    type in google – bluehand roulette system

  2. Kyle  

    I see a lot of interesting articles on your website. You have to spend a lot of time writing, i
    know how to save you a lot of time, there is a tool that creates high quality, google friendly articles in couple of seconds, just search in google
    – k2 unlimited content

  3. Quentin  

    I read a lot of interesting articles here. Probably you spend a lot of time writing, i know how to save you a
    lot of time, there is an online tool that creates unique, SEO friendly articles
    in minutes, just search in google – laranitas free content

Leave a Reply

Your email address will not be published. Required fields are marked *