Using PHP with PayPal’s IPN (Instant PayPal Notification) to automate your digital delivery

When you want to sell something through the internet, PayPal is your best choice. Almost every website selling stuff or subscriptions use PayPal to manage its transactions.

While PayPal back-end allows users to fully manage their accounts, there are some features it still lacks.

Real world example: let’s say you are selling a digital good, such as the source code of your latest Flash game, or an ebook.

Since there is no shipment as the buyer will download it or receive it by email, he expects to get the book/game a few minutes after the payment.

That’s ok if you check your PayPal account every 10 minutes, manually sending emails to buyers, but once in a while you need to sleep… or have a shower… who will send your book then?

That’s why services like PayLoadz come into play, managing transactions and digital delivery for a monthly subscription and a per transition fee.

If you don’t want to use third part services, PayPal offers the Instant Payment Notification to automate your digital deliveries.

Instant Payment Notification (IPN) is PayPal’s message service that sends a notification when a transaction is affected. Once IPN is integrated, sellers can automate their back office so they don’t have to wait for payments to come in to trigger order fulfillment.

The process is simple: once you have a PayPal account, in your profile page click “Instant Payment Notification Preferences” under “Selling Preferences”, and you will be asked for an URL.

This is the URL of a page on your server which will act as a listener for PayPal payments.

Then, all you have to do is write your own listener based on the information you will find in the official docs. Wait, I forgot to tell you three things:

1) The script is wrong, it will give an error because there are missing curly brackets

2) The given address where to test the script is wrong, it’s not anymore

3) The script (once corrected) won’t work on every server since relies on fsockopen. In my opinion it would have been better to use cURL

So, this is the script I suggest to use:

Simply comment/uncomment lines 15-16 if you want to use it in sandbox or real mode.

Once the payment is VERIFIED, you can send the email with the game/book/activation code to the email address you will find in POST[payer_email] variable. You can find the complete list of passed variables at this page.

To test it, once you activated your IPN and installed the script on your web server, register as a PayPal developer, then test your IPN in the sandbox page.

In a few days, a fully working example on this site, with some deals at an extraordinary price.

  • Ronny

    Oh thats great thanks emanuel
    i learnt something new today :)
    keep up the great stuff:D

  • I’ll have to bone up on my PHP. I don’t have a website right now, but I’m interested in getting the source to a game sold. I think that this will be very helpful. If I figure out a way to implement this in Flash, it might be helpful as well.

  • Great. Very useful. I have to put me up to date with php

  • Cierrovachi

    Hi, very nice and informative. Thanks.

    Can I ask you a question regarding (sandbox and) IPN.

    I’ve used the PHP script for IPN from their official site and then created Buy now button, connected them (ok, set ipn (enabled it before)) and tested the whole procedure.

    Tests have shown me some weird things;

    when i “buy” (in sandbox) the item it says that my payment is completed (only on the buyer side), then I log in to my sandbox merchant account and the money is not there.

    Then I check my IPN log (file on my server that checks all POSTs and writes them to a file for reference) and I see 13 exactly same messages from paypal, all including payment_status=Completed.

    But the sandbox money is still not on merchant’s account.

    I have figured it out how to make it work:
    when I buy (click on button pay now, login, click pay (then I am as a buyer redirected back to seller’s site), I have to login to my buyers account, go to last transaction (it has status completed, which is not really true) click on details and scroll to the bottom of details page and click confirm.

    Only then test payment is really made to merchant.

    I suppose this is only needed in Sandbox account?
    Do / did you have the same scenario or am I doing something wrong?

    I can of course go live with my script and ask a friend to pay with real money (and pay him back) but that would be the last option.

    My second concern is the following:

    1.) somebody registers on my site, buys my digital product (software or just access to the site) with paypal
    2.) uses / saves the access/sw
    3.) open an dispute with paypal and reclaim his money

    How to prevent this?
    How to prove paypal that you have provided the customer with what you’ ve promised?

  • Emanuele Feronato

    First, the confirm button is only active in the sandbox mode.

    Second, you can’t prevent people for downloading and then reclaiming their money.

    Anyway, this never happened to me, as of today.

  • yoji

    I’m implementing Paypal Express Checkout solution for digital goods.
    I started some tests : when a buyer clicks on the “Pay” button, I confirm the transaction, calling Paypal API and I get a response, Success or Failure. Then why would I need IPN ?
    The transaction success response is not enough to send the digital good ?

  • Emanuele Feronato

    Sure, it’s enough, but you might want to automate digital good delivery, and store buyers data somewhere to have some kind of statistics.

  • yoji

    The php script which processes the payment can automatically deliver digital good and store data when the success response is received. Tell me if I’m wrong, but as this success response seems reliable, then we don’t need IPN.

    I only see IPN would be usefull for recurrent payment : I get a success response only when I process one payment but if it is a recurrent payment, I would use IPN to automatically deliver the digital good every time the payment is completed.

  • For the wishlist:
    It would be great to have a detailed tutorial on paypal subscriptions!

  • Iggy

    Hey Emanuele,

    thanks for the code!

    I still have a challenge while putting this to work, and maybe you could help me out. How would I impelement a personal link with an expiration date for each buyer? For me, that’s the whole point in implemeting IPN (otherwise, I would just let the buyer download from the link after the sucessful payment included the “buy now” button set up).



  • Emanuele Feronato

    Sure you can Iggy, you will need a mysql database to store payer information as well as payment timestamp.

    You will mail the payer a link with an ID, and before letting him download anything, just check the timestamp.

  • Oh! thats great, thanks emanuel. Its Very useful!

  • Hello, you would not have a sample form to use your example?
    I try to create a form that sends data to paypal, then inserted into the database on the status of payment.
    Sorry for my english, i speak french :)

  • frank

    Ok, so I am a Nob at all of this. I want buyer to have a quick and painless transaction, and i dont want to do anything, so , quick story, I created buy now buttons for digital music. I used mobile me as website, it doesnt have server side, or what ever you guys call it, i got the buttons to work, but the user had to click after payment to get a download link. but anyone could copy and paste the link and send to others, SO
    this ipn i want to implement, to safe gaurd my files, first off, were do i put this php file on my server? thats number one, i am a nob? I just got a bluehost account, and set up the website via ftp, domain name comes from go daddy. anyway.
    number 2, how do i create this php to send the link to them, Not via email(maybe as well as) but right away after they paid!!! and how do i make sure each time a new person pays for the same digital media, the link is different?
    creating all of this in the 1 php file? I need to learn really, but hey…..
    post anything you can , to help a noob. cheers….
    ps. I have researched alot of stuff, and have come to the conclusion this ipn paypal way is the easiest, cheapest and most reliable, and most people have a paypal account, so they dont have to fill in forms, Please Help!!!!!

  • If you don’t want to mess around with PHP scripts, you can always use an IPN service, such as MyPal IPN. Google it.

  • Thanks a lot for your advise but when I use your code, it’s ok at first but now there is no response in ipn page ( case: default). What should I do?

  • trau

    Ciao Emanuele, complimenti per il blog, volevo chiederti se è possibile automatizzare tramite php anche le mail di pagamento di paypal e se sai come farlo?

  • Jenny

    Thanks for the info; very clearly explained. Is it possible to produce expired links w/o database?

    The whole point of me going with paypal cart over Zencart is the fact that I don’t have to maintain a database on my server. I was hoping that digital delivery would be integrated in Paypal shopping cart. Seems half baked.

    Turns out I still have to do php coding and quite important piece at that. Very disappointing.

  • Joe

    I just want to clear up the benefit of ipn over payment success for yoji above.

    Payments can take a while to clear, not all are instant, and sometimes people will be sent back to your page while their payment is still clearing. In this instance the “Payment success” method will fail, and you will have to start a manual check for the payment.

    IPN waits until the payment clears, even if its an echeque and takes a while, then sends the message to your server, your server then can send off the email saying its been processed.

    so IPN allows the whole system to be automated. “payment success” can lead you to times when manual checking will be needed.

  • MiKan

    Hi, I just wanna thank you for your work !

    I was trying to implement a Paypal Module, and I’d some troubles, like the “VERIFIED” status…
    I implemented some others paypal module in the past but today it was a great (and difficult -_-‘) challenge because of Paypal Sandbox Behaviors…
    I wasted my time to understand why, because my script seems to be ‘OK’, and everything might be all right !
    So i’m seeking for an answer with my best friend google, and I discovered your script, and your suggestion is very interessant, I tried with cURL (and no fsOpen) in my IPN file AND… DONE !!


  • Grazie Emanuele!
    I was in trouble with the sandbox behaviour for Paypal. I was not able to get the “VERIFIED” status and your script solved it.
    So thank you very much!

  • Thanks, looks good but I’m wondering if line 10 is correct.

    Shouldn’t it be…

    $varvalue = urlencode($varvalue);

    Also, in line 5 will $email be used for anything?

  • Hi, thanks for posting your solution I’ve been bashing my head against the desk for days with this thing.

    I just tried your code and it doesn’t work. I copied and pasted it exactly and used the ipn tester in sandbox..nothing.

    Is this code dated? Or is it still correct?

    Thank you.

  • Beth

    Will this send the payer an email stating that the payment has been processed? I’m not needing to send a file to the payer, just an email saying that they have paid for the item.

  • Hans Zemm

    Hi Emanuele,

    This just to thank you for this awesome tutorial. I’ve been bashing my head against the wall for 2 days trying to get IPN to work, and I tried multiple libraries and tutorials, and nothing worked except for your script.

    Thanks a lot for posting this! You’re awesome!


  • Thanks for posting this. This script and PHPMailer allowed me to automate sending PDFs to buyers. Also, I found this helpful to cycle through the item numbers, names, etc.

    for ($i = 1; $i <= $_POST['num_cart_items']; $i++) {
    $number = $_POST['item_number'.$i];

  • Jo


    I host a server for an online game and would like to integrate paypal in game purchases but I don’t know how to confirm that the item has been paid for and then for the customer to receive that item in game. Do you know where I can get some help with that?

  • Yeah, I have tried many ones that are shared on stackoverflow but finally found a working one here, bunch of thanks to you.

  • Dear Emanuele Feronato,

    I have a doubt how could I verify the recurring payment information through php once the automatic payment processed , thanks in advance

  • shobhit

    I am fighting with paypal ipn for so long, i have gone through so many blogs…. and documentation….. but not succidded………..but you are just osm….
    i just took your code just did the copy past and now it working…

    thanks(Which i really mean)

  • krishna

    Hello, As you said earlier, are you done with the complete example for using php with paypal integration. Please let me know.

  • hello
    thanks for the paypal ipn,

    thanks for the code

  • Gulo gulo

    Hello Emanuelle,

    I was looking at lines 15 & 16 of your script:


    I was wondering if the URL for the live IPN verification should also have ‘/cgi-bin/webscr’ appended to it?


    Your code worked just fine for me with the PayPal Sandbox IPN Simulator (

  • Jonathan

    I’m using this, however I keep getting an error. I continously get the case default even though I’m getting the fields.

    I have it logging to a text file and in that text file I get

    residence_country: US
    invoice: abc1234
    address_city: San Jose
    first_name: John
    payer_id: TESTBUYERID01
    mc_fee: 0.44
    txn_id: 471896486
    custom: xyz123
    payment_date: 12:26:50 16 Dec 2013 PST
    address_country_code: US
    address_zip: 95131
    item_name1: something
    mc_handling: 2.06
    mc_handling1: 1.67
    tax: 2.02
    address_name: John Smith
    last_name: Smith
    verify_sign: An5ns1Kso7MWUdW4ErQKJJJ4qi4-ANeMCuo4DGcuzVExKBQeoBkpaFYw
    address_country: United States
    payment_status: Completed
    address_status: confirmed
    notify_version: 2.4
    txn_type: cart
    test_ipn: 1
    payer_status: unverified
    mc_currency: USD
    mc_gross: 12.34
    mc_shipping: 3.02
    mc_shipping1: 1.02
    item_number1: AK-1234
    address_state: CA
    mc_gross1: 9.34
    payment_type: instant
    address_street: 123, any street

    I’m using the Sandbox IPN Simulator

  • Jonathan

    My previous error with it not working with Sandbox IPN has been fixed. The reason for this issue is because it’s trying to verify Paypal’s false SSL cert. To fix this issue simply add curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE); to the set opts.

    Should look like this now

  • Thanks a lot i searched the net and read many tutorials but none of them worked for me finally this one is awesome.

    Thanks a lot once again and how can i make it secure.

  • ithelps

    I don’t understand how to do this? I need a server to do this? how much for someone to help me set this up?