Easy payments using Paypal IPN

There are several PHP scripts and classes to process PayPal payments using their native IPN (Internet payment notification) feature. Because the whole process is based on the data you need to send via a web form to the PayPal payment processor these script look very similar.

The payment / notification process is shown via the following graphic:

paypal payment validation process

Inside the form there are several required values to process a payment. PayPal gives the advice to post them all to get everything working. The following variables get some special attention:

business = your PayPal email address
cmd = single payments or subscription service (_xclick or _xclick-subscriptions)
return = the URL where the buyer get back after the payment is processed
cancel_return = the URL where the buyer get back if he has cancelled the payment
notify_url = the location where your IPN script is located
rm = how you need the data submitted from PayPal to your IPN script (1=get, 2=post)
currency_code = the currency you accept for your payment
lc = the country version of PayPal where your buyer is send to

Skrill MoneybookersThere are much more variables, but we think that the other variables (product, order and shipment information) speak for themselves. Find a complete form provided with the example files.

To run some IPN enabled payment process we need a small script which will double check if the data which is send to the IPN script is valid according the data which is stored on the PayPal server. This feature is very important if your e-commerce accepts automatic payments.

The following code is able to check if the payment is valid against the PayPal server. Use this test to decide if the payment is valid or not.

$url = 'https://www.paypal.com/cgi-bin/webscr';
$postdata = '';
foreach($_POST as $i => $v) {
$postdata .= $i.'='.urlencode($v).'&';
$postdata .= 'cmd=_notify-validate';

$web = parse_url($url);
if ($web['scheme'] == 'https') {
$web['port'] = 443;
$ssl = 'ssl://';
} else {
$web['port'] = 80;
$ssl = '';
$fp = @fsockopen($ssl.$web['host'], $web['port'], $errnum, $errstr, 30);

if (!$fp) {
echo $errnum.': '.$errstr;
} else {
fputs($fp, "POST ".$web['path']." HTTP/1.1\r\n");
fputs($fp, "Host: ".$web['host']."\r\n");
fputs($fp, "Content-type: application/x-www-form-urlencoded\r\n");
fputs($fp, "Content-length: ".strlen($postdata)."\r\n");
fputs($fp, "Connection: close\r\n\r\n");
fputs($fp, $postdata . "\r\n\r\n");

while(!feof($fp)) {
$info[] = @fgets($fp, 1024);
$info = implode(',', $info);
if (eregi('VERIFIED', $info)) {
// yes valid, f.e. change payment status
} else {
// invalid, log error or something

As mentioned before there are some complete solutions available on the internet. If your e-commerce site doesn’t have a complex product catalog you should use some static code from the PayPal website. For this guide we checked the PHP toolkit provided by PayPal.

Code condition
The first thing I noticed the code is not very clean and is using a coding style which is based on older PHP versions (f.e. for systems using register globals = On)

After some code clean-up it was possible to use the included file together with my shopping cart script. Static variables are defined in one central configuration file and dynamic files are posted via the form in your web application.

IPN features
This script is written to handle the IPN validation process with different methods: cURL, fsockopen, and libcURL. I tried only the fsockopen option because this method looks good to me and should work on almost every web platform.

There is a “Readme” file with the information about the most important features. A complete guide is not included and the information about subscription payments is missing in all files and documents. If you decide to start with the original files you should check also the comments within the configuration and example files.

Example files
The included files are good enough to jump start your Paypal payment application. All files are included for a single buy button and also for processing the payment f.e. for the items from a shopping cart. The bad thing is that the bad coding style makes it not easy to integrate the script into you own application if you’re an PHP beginner.


Published in: eCommerce Solutions · PHP Scripts


  1. While it may be easy – which is also debatable – it’s reliability leaves much to be desired. For much of January and February PayPal was having severe service issues: IPN notifications not being delivered, E-check pending statuses not resolved, etc. Just read some of the threads on paypaldeveloper.com. I would advise taking that into consideration.

  2. Hi Andrei,

    thanks fo your comment.
    Sure there will be always issues and I think every solid application need some safety belt, but this would be an item for the next article :)

    PS. I hate the paypal sandbox!

  3. I am currently working on an E-commerce project and until now, we had not looked at Pay Pal as a viable option for us, however, it looks like it may just work. Along with others, Pay Pal pro integrates with Zen cart!

  4. Just a quick question, how do I access the variables send from the form.
    For example the custom field has the username in it. I need to update data in a MySQL database where the row matchs the username, would I use
    Thanks in advance

  5. would be nice if you could translate this with curl, curl is faster and I would prefer to use curl. I know how to snag the source of an element but not sure how to do it with ssl or https

  6. Hi Matt,

    in fact the form which is send to paypal would be the same, the only thing you need to know write is the IPN script, is there no example on the PP site?

  7. I tried to use this script but I get an error:
    Parse error: parse error, unexpected ‘:’ in /home/content/s/e/f/sefru/html/ylbmessa/thankyou.php on line 2

    And line 2 is: $url = “https://www.paypal.com/cgi-bin/webscr”;

    What should I do?

  8. i got your sample files.can you tell me how make to many products /two or more product to payment in paypal?
    i saw in your sample just 1 product


  9. Hi jokonardi,

    the IPN feature is not related to the number of products you have in your paypal shopping cart or product list. Sure you need to use a different form.

  10. Hey just wanted to say thanks for this excellent piece of code! The one from PayPal is so messy I just ended up with a headache. This works like a charm and was exactly what I was looking for.


  11. I have some issue with IPN I think.

    I realized some script that include your one listed. the script itself works fine.
    but if the payment at the last moment is refused by the client, the IPN page script is not called, while the redirection to the “sorry” page is done correctly.

    So, for instance, the client arrives to my page.
    He choose what wants to buy.
    The total amount with the client data, is sent to PayPal by the PayPal’s button.
    The page of PayPal appears with all the correct data.
    The client should only give his login and password to paypal

    But at this point the client no wants anymore to buy the product and he clicks on “Cancel and return to mysomain@mydomain.com

    The “sorry” page appears correctly.

    The IPN is not called at all (at least so it seems).

    What’s wrong please?

    1. Hello Tiziano and welcome,
      I remember that I had this problem too, but the problem occurs randomly. It should work for 70%? There are many user writing about this problem and Paypal has no intention to solve that bug (or to stabilize the feature). It seems that the server doesn’t send a response for all payments. Seems like that Paypal gives here a signal to use their premium services. :(

  12. Hello Olaf

    the problem is that it never worked to me.
    I also emulated the full payment with sandbox.paypal and not any notification was sent to my server through ipn.php
    I mean: PayPal never called it.
    Moreover in theory it should works with all kind of subscriptions, not only with premium :(

    1. Tiziano, that is an easy one: It doesn’t work in the sandbox

      I did always some tests with real payments (not so much because of possible refunds)

  13. Well but the “cancelled payments” I tested in real platform. I sued the SandBox yesterday cause I’m desperate.

    In other words, you tell me:

    In SandBox (which is designed to test everything) the ipn test doesn’t work.
    Working in the real platform, it works at the 70% (while to me never worked).

    I’m really concerned with them

    1. Yes, that was my experience a view years ago. The “simple” Paypal IPN was never a great solution, many people complaining this on the Paypal forum

  14. Is PayPal “hiding” from IPN due some security lack ?
    I mean it was much easy to use IPN because all the operations can be automatized without any human intervention.
    BUt this kind of behavior from payPal is making me suspecting that there is some lack some where …

    1. This article is about an old IPN feature from ~5 years ago. At the same tome they started to provide premium services and maybe they never fixed the problems…

      I did a search on Google for “paypal ipn problem” and found this post.

  15. I ‘ve read the link you posted.
    The declared solution it seems in MySQL. It’s a pity that nor 1 line of PHP refers to MySQL but to a socket to PayPal.

    1. The problem from that guy lies in some script errors, that tells me that the IPN should work using the sandbox. That brings us to the beginning :)
      If you check the transactions in your sandbox account, are there the payments you have done with your application?

  16. Well this is mine one very basic just the PayPal script.
    In case the transaction is successful, it should send me an OK email. In case is negative a NO OK email in case neutral a NEUTRAL email. No one of these works. Nor in the SandBox nor in the reality.

    I even tried yesterday just to create a file in a 777 directory to see if something “hidden” happens. Zero.

    Here the code, please :)

    ## code removed ##

  17. When I’m handling the IPN response I don’t get a “VERIFIED” or “INVALID” but some error info like “HTTP/1.0 302 Found” and no error or error string. The variables do come through OK. Can you help?

  18. @Jim – getting the same here – the response that comes back from the PayPal sandbox is:
    HTTP/1.0 302 Found
    Location: https://www.sandbox.paypal.com
    Server: BigIP
    Connection: close
    Content-Length: 0

    Looks like the Sandbox is requesting us to redirect to a HTTPS location and repost. The code above doesn’t handle redirects. The curl library does though (I think) so I’ll be looking closer at that.

    Maybe it’s a setting on the PayPal sandbox because our live accounts don’t have the same problem. Like Andrei (poster #1 above) stated this isn’t a very robust way of doing things but it does work.

Comments are closed.