I just completed a website where the client uses PayPal to handle the payment transaction. I have used PayPal quite a bit in the past, but I have always had problems using IPN (Instant Payment Notification). Because of the problems, I usually opted not to use IPN, but I was determined to use it for this project. The primary problem with testing IPN is, because the transaction occurs in the background, it is difficult to figure out where the point of failure is. But that is all behind me now.
First sign up for a developer account in PayPal’s Sandbox. The Sandbox is a test environment that can be used to test PayPal transactions without having to use a real credit card on a live site.
Once you log into PayPal’s Sandbox, you should create two test accounts (1 buyer and 1 seller).
PayPal Script
Next, you have to make changes to your PayPal script. In this case, I am using a CodeIgniter PayPal Library. It is based upon Micah Carrick’s PayPal IPN Integration class, so if you don’t use CodeIgniter, you can use Micah’s script instead. You can also get a PayPal script from here.
If you are using CodeIgniter PayPal Library, open the PayPal Controller. If you are using Micah Carrick’s Class or any other script, look for the code that adds the business. You want to add the seller’s test account that you added in the sandbox:
$this->paypal_lib->add_field('business', 'seller_1202178625_biz@greenscorpion.com');
You also want to make sure that the notify_url field is set. The IPN will not work without it. The notify_url field tells PayPal where to send the data back to. You can also set this in your PayPal profile.
Next you want to change the PayPal post URL. In the CI Library, the url is located in the Paypal_Lib library. So you want to change any occurence of this:
https://www.paypal.com/cgi-bin/webscr
to this:
https://www.sandbox.paypal.com/cgi-bin/webscr
You also have to change the Port from 80 to 443. With the Paypal_Lib file, I changed:
$fp = fsockopen($url_parsed['host'],"80",$err_num,$err_str,30);
to:
$fp = fsockopen('ssl://www.sandbox.paypal.com',443,$err_num,$err_str,30);
Testing
Now comes the fun part. I struggled to figure out where my script was failing. I had created additional code in the PayPal controller that updates the database once data was received back from PayPal. The script wasn’t being called.
There is an IPN testing tool located in the PayPal Sandbox (IPN Simulator). First you enter your IPN handler URL (notify_url field). Then you select the transaction type (Express Checkout, Cart Checkout, Web Accept, etc). Make sure that you select the correct transaction type. I assumed the the CI PayPal Library was using Express Checkout, but it is using “Web Accept”. The amount that the person pays is a field name ‘mc_gross1′ for Express Checkout and ‘mc_gross’ for Web Accept.
Note: PayPal’s custom field has proved invaluable to me. You can add anything you want to this field and PayPal will return it with the other data. For instance, the last project that I worked on, members can sign up for tours. So I added the member_id and tour_id to the custom field separated by an ‘&’ (ie, 498&3). So when the data comes back from PayPal, I know which member signed up for the tour and which tour they signed up for:
list($memberId, $tourId) = explode('&', $_POST['custom']);
By using the IPN simulator, I was able to test the IPN process in a fraction of the time because I did not have to deal with the other portions of the website application (logging in, ordering, etc). Just click the “Send IPN” button and test the results (if you get any results).
Most of the PayPal IPN scripts that I have seen, including the CI Paypal Library, writes the data received back from PayPal to a log file. This log file was the start of my troubles. No matter what I changed, the data was never being written to the log file. I changed the permissions to the log file, change the location, nothing worked. So I removed the log file from the equation. I changed the code so that it would send me an email upon receipt of the data.
I did not receive an email during my first run. The email code was initially placed within:
if ($this->paypal_lib->validate_ipn()) {
//email code
}
I moved the email code to the beginning of the ipn function. I received an email so I knew that the error was occurring in the validate_ipn method. I continued to move the email code to different positions within the valide_ipn method until I stopped receiving an email. If I did not receive an email, then I knew that the code was blowing up in that area. I continued to move the position of the email code until I had corrected all errors.
While this may be an unpleasant way to debug code, it works. In may case, the code was failing when it attempted to write to the log file, so I commented out that portion of the code. I didn’t need to write to a file because I was posting the data directly to a database.


thanks a lot! clear cut instruction.
I have been having a bad luck since past 2 years. I have never integrated pay pal. This is the first time.
i download a library from http://codeigniter.com/wiki/PayPal_Lib/ and made necessary changes as given in CI’s wiki.
I’m just enable to manage this whole stuff.
I have a shopping cart(the inbuilt CI one). I need to put a check out button. and what should i do next..
Please help
Thanks 4 sharing.
yes indeed! clear, concise instructions; helped me so much with the darn thing kep fighting with for 2 days!! It was the fsocket connection, first didnt have correct sandbox address (but I missed the 443 port!); then not until I read your post did I realize that was the final piece of the puzzle… darn 443!!
thanks for posting such helpful info…
Thank goodness I found this early on! I had everything covered on updates in the wiki, but I would NOT have known to use the ssl before the hostname! Also what I did – I just put ‘ssl://’ and then still used the $url_parsed['host']. Maybe on some installations the parse_url will return https as part of the host name, but I don’t think so. Anyway for me it’s reliable and I can still keep host name dynamic that way. But if I had not known to force ssl in hostname as well as via port number, I would have spent way more time debugging, so thank you again!
Nice work! This came in handy big time! I had done a paypal integration with IPN a little over a year ago in ColdFusion and I knew I had to flip the url settings and the port for Sandbox purposes, but couldn’t remember exactly what they were. This post was perfect saved me a bunch of time. thanks and keep up the good work!
Testing with Ran’s PayPal_Lib for CodeIgniter can be a bit hit and miss – and like equalizer says, it can be a bit confusing how to update the URLs to handle https:// for the fsockopen command. To deal with these issues we’ve done a full rewrite of Ran’s library internally, and we’ve now open-sourced it on GitHub, I hope you find it useful: https://github.com/orderly/codeigniter-paypal-ipn
Thanks, very useful to me.
Thanks for the post,helped me a lot.