Paypal Instant Payment Notification (IPN)

This is continuation of the previous post how to setup Paypal Express Checkout in your website. You do not necessarily need to setup Paypal Instant Payment Notification (IPN), but if want to automate tasks and keep track of customer actions back in their PayPal account, you should create and setup an IPN listener script.

How IPN works

Lets say, a customer has pending transaction, after few days he authorizes the payment using PayPal, how will you know? will you wait for PayPal to send you email? or have IPN script setup. PayPal can send $_POST variables to your script, containing various information about your customer transaction, your script should collect these values and use them to update database records, email user etc.

In this tutorial, we will store information received from PayPal using IPN listener script, but you can program your own script to do lot more than just store information.

MySQL table

Let’s say we want to create a list of history by inserting received info in the database, we need to create a table similar to below:

 
1
2
3
4
5
6
7
8
9
10
11
CREATE TABLE IF NOT EXISTS 'ibn_table' (
'id' int(11) NOT NULL AUTO_INCREMENT,
'itransaction_id' varchar(60) NOT NULL,
'ipayerid' varchar(60) NOT NULL,
'iname' varchar(60) NOT NULL,
'iemail' varchar(60) NOT NULL,
'itransaction_date' datetime NOT NULL,
'ipaymentstatus' varchar(60) NOT NULL,
'ieverything_else' text NOT NULL,
PRIMARY KEY ('id')
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

Listener Script

PHP script ipn_paypal.php below stores any incoming message from Paypal in MySql table. Just put this file somewhere in your website and point IPN Url to this script from your Paypal IPN settings.

To test this script in Paypal sandbox mode, just create an account in Paypal Developer website, once you are logged in to the site, click ‘test tools‘ on sidebar, and click “Instant Payment Notification (IPN) Simulator” and enter this script URL in “IPN handler URL” field, choose Web Accept from “Transaction type” dropdown.

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
<?php
       //Change these with your information
    $paypalmode = 'sandbox'; //Sandbox for testing or empty ''
    $dbusername     = 'xxxxxx_username'; //db username
    $dbpassword     = 'xxxxxx_password'; //db password
    $dbhost     = 'localhost'; //db host
    $dbname     = 'xxxxxx_db_name'; //db name

if($_POST)
{
        if($paypalmode=='sandbox')
        {
            $paypalmode     =   '.sandbox';
        }
        $req = 'cmd=' . urlencode('_notify-validate');
        foreach ($_POST as $key => $value) {
            $value = urlencode(stripslashes($value));
            $req .= "&$key=$value";
        }
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, 'https://www'.$paypalmode.'.paypal.com/cgi-bin/webscr');
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array('Host: www'.$paypalmode.'.sandbox.paypal.com'));
        $res = curl_exec($ch);
        curl_close($ch);

        if (strcmp ($res, "VERIFIED") == 0)
        {
            $transaction_id = $_POST['txn_id'];
            $payerid = $_POST['payer_id'];
            $firstname = $_POST['first_name'];
            $lastname = $_POST['last_name'];
            $payeremail = $_POST['payer_email'];
            $paymentdate = $_POST['payment_date'];
            $paymentstatus = $_POST['payment_status'];
            $mdate= date('Y-m-d h:i:s',strtotime($paymentdate));
            $otherstuff = json_encode($_POST);

            $conn = mysql_connect($dbhost,$dbusername,$dbpassword);
            if (!$conn)
            {
             die('Could not connect: ' . mysql_error());
            }

            mysql_select_db($dbname, $conn);

            // insert in our IPN record table
            $query = "INSERT INTO ibn_table
            (itransaction_id,ipayerid,iname,iemail,itransaction_date, ipaymentstatus,ieverything_else)
            VALUES
            ('$transaction_id','$payerid','$firstname $lastname','$payeremail','$mdate', '$paymentstatus','$otherstuff')"
;

            if(!mysql_query($query))
            {
                //mysql error..!
            }
            mysql_close($conn);

        }
}
?>

That’s it! you just wait and let script store any information received in the database. Remember you can extend this script functionality to do lot more. Good luck!

Related Articles:

Article by on July 23, 2012 Tagged under Tagged under , . If you like this article, please consider sharing it.

9 Thoughts

  1. Hi,

    Thanks for both this tutorial and the Express checkout. Unfortunately this script isn’t returning anything to the database, any suggestion?

  2. Hi Saran,

    If I am storing the results of the transaction in the database using your paypal express script, why do I need to store them again using the IPN script?

    many Thanks
    aidan

    • Example above just shows what you can do with received information, question is how are you going to use it. IPN notifies merchants almost instantly, your script can act based on the information it receives, for example: it can update customer record, email confirmations, trigger order fulfillment, send and enable download links etc, all these tasks can be automated with IPN script, I think it saves lots of time if you are selling many products everyday in your site, think of doing everything manually! More info here :
      http://j.mp/Yoi5Xu
      http://j.mp/Yoi3yD

    • Thanks Saran,

      Thanks for the speedy response!
      I think I get what you mean, so if for example, if I get a ‘pending’ payment via PayPal Express, the IPN script is required to change that pending payment to complete when it is completed on PayPal’s servers – otherwise it wouldn’t update in my db, and always remain pending, even if the payment status has become ‘complete’?
      Is that correct?

      Thanks,
      Aidan

Leave a Comment

Get your comment picture from Gravatar.com.
Your email address will not be published. Required fields are marked *