Using PayPal Instant Payment Notification with PHP

Using PayPal’s Instant Payment Notification with PHP

Mar 4th in PHP by Philo

Hi there! Today we are going to combine Paypal with PHP to allow for the easy processing of payments on your website.

PG

Author: Philo

Hi there! My name is Philo from The Netherlands. I am a freelance web designer / developer and love to design and build websites and web applications. Ill try to write more high quality tutorials for nettuts.com soon! Follow me on Twitter or check out my website

Finished Product: Preview

Step 1 - Creating a PayPal Account

For this tutorial you will need a Premier PayPal Account and an online website. Begin by going to paypal.com and click "signup" at the top of the page.

Step 1

Click Get Started under the Premier Title; you will be redirected to a signup form. Please fill in all necessary information. When your account has been created, login and move on to step 2.

Step 2 - Enable IPN

In this step we are going to enable Instant Payment Notification (IPN), so while logged in, please click Profile and then choose Instant Payment Notification

Step 2

Now on the next screen you will see that IPN is set to "off"; click "Edit" to change that.

At the start of this tutorial, I mentioned that you would need an online website. Why? Well we are going to ask PayPal to send us data when a payment is complete. PayPal can't reach local hosted websites unless you have all settings configured correctly. (This involves opening ports on your router). So, I'll enter the url to my validation script for example http://www.yourdomain.com/PayPal/ipn.php. PayPal will then post a notification to my server, at the URL I've specified.

Step 3 - Building a Simple HTML Page

Okay, now we need a simple and basic html page where your visitor can buy access to your download area. I'm not going to explain all the HTML because i think you should know the basics of HTML before you start with PHP.

index.php - A simple HTML page with a stylesheet.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Nettuts.com | Purchase access to download area</title>
<link rel="stylesheet" type="text/css" media="All" href="css/style.css" />
</head>
<body>

	<div id="wrap">
		<h3>Purchase Access</h3>
		<p>Please click the button below to receive login details for the download area. <br />
		   Already have an account? <a href="login.php">Login</a> here.</p>
		   <!-- Paste your PayPal button code here (That you will get in the next step) -->
	</div>

</body>
</html>

css/style.css - A simple stylesheet for our HTML Page.

body{
	background: #2D2D2D; /* Set Website Background Color */
	font: 11px 'Verdana'; /* Set Website Font Size & Font Type */
}

#wrap{
	margin: 0 auto; /* Center Our Content */
	width: 500px; /* Set The Width For Our Content */
	background: #FFF; /* Set Content Background Color */
	padding: 10px; /* Set Padding For Content */
	border: 1px solid #000; /* Add A Border Around The Content */
}
step 3

Step 4 - Building a PayPal Button

We need to create a purchase button, so please click Merchant Services, and then chooseWebsite Payments Standard

You may choose three types of buttons, Sell single items, Sell multiple items and, Subscription. Now in this tutorial we are going to create a single item. When someone purchases this single item, in this case access to a download area. Once the payment has been validated, an email will be sent with there details.

Step 4

Let's enter some information for our purchase button; you may leave the rest as it is.

Step 4 Settings

When you have finished filling in each section, generate the code. Copy this code to your clipboard, and then paste it insideindex.php - where I added the comment in the html page. Please review step 3, if needed.

This should work perfectly. Users can click the button and complete their purchase.

Step 5 - Writing ipn.php

First, create ipn.php so we can start writing. We'll use a small snippet that I made from a larger snippet that you can get from Paypal's website. Please note that there is no reason to learn this code out of your head! Snippets are handy and save time. I will break it down below.

<?php

mysql_connect("localhost", "user", "password") or die(mysql_error());
mysql_select_db("PayPal") or die(mysql_error());

// read the post from PayPal system and add 'cmd'
$req = 'cmd=_notify-validate';
foreach ($_POST as $key => $value) {
$value = urlencode(stripslashes($value));
$req .= "&$key=$value";
}
// post back to PayPal system to validate
$header = "POST /cgi-bin/webscr HTTP/1.0\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Content-Length: " . strlen($req) . "\r\n\r\n";

$fp = fsockopen ('ssl://www.paypal.com', 443, $errno, $errstr, 30);


if (!$fp) {
// HTTP ERROR
} else {
fputs ($fp, $header . $req);
while (!feof($fp)) {
$res = fgets ($fp, 1024);
if (strcmp ($res, "VERIFIED") == 0) {

// PAYMENT VALIDATED & VERIFIED!

}

else if (strcmp ($res, "INVALID") == 0) {

// PAYMENT INVALID & INVESTIGATE MANUALY!

}
}
fclose ($fp);
}
?>

Please fill in the correct credentials for your database so we can insert data in the next step.

PayPal POSTS data to the url we specified. In this example we only need the email address from the buyer, so that we may send him his login information. This code above will read the data PayPal sends and return the info to PayPal. I've added two comments where the code should come if its validated. Additionally, I've also added a comment that specifies what should be done if it's not validated.

Step 6 - Creating the Database

Now we are going to focus on what should happen if the payment is verified. First, we need to build a MySQL table where we store the users information. Just a simple one with an id, email and password field.

Next, we must enter our table details; we need an ID with a primary key selection and it should auto increment; next an email and password field.

For those of you don't have the time to enter all of this information, below is a small MySQL Dump code to recreate the table.

CREATE TABLE `users` (
  `id` int(10) NOT NULL auto_increment,
  `email` varchar(50) NOT NULL,
  `password` varchar(32) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

Step 7 - Account Creation

Open ipn.php again. We are going to write the following code below the "// PAYMET VALIDATED" line.

Our first step is to retrieve the email address of the buyer; PayPal sends all of this info over to ipn.php.


// PAYMENT VALIDATED & VERIFIED!

$email = $_POST['payer_email'];

We must create one last variable - which is the password that we will generate using php.

// PAYMENT VALIDATED & VERIFIED!

$email = $_POST['payer_email'];
$password = mt_rand(1000, 9999);

As you can see, we used mt_rand to generate a random password - in this case a numeric value between 1000 and 9999. Next, we need to insert this data into our database. To do so, we'll use the mysql insert query.

// PAYMENT VALIDATED & VERIFIED!

$email = $_POST['payer_email'];
$password = mt_rand(1000, 9999);

mysql_query("INSERT INTO users (email, password) VALUES('". mysql_escape_string($email) ."', '".md5($password)."' ) ") or die(mysql_error());

Here we tell our script to insert the email and the password into our database. I've added a mysql_escape_string to ensure that mysql injection isn't possible. I've also added the md5 function to our password so that it will be stored as a 32-character hash. Now the account is created; let's move on to the next step.

Step 8 - Emailing the Login Credentials

We need to write some code that will email the login information to the buyer. To accomplish this, we will use the php mail function.

// PAYMENT VALIDATED & VERIFIED!

$email = $_POST['payer_email'];
$password = mt_rand(1000, 9999);

mysql_query("INSERT INTO users (email, password) VALUES('". mysql_escape_string($email) ."', '".md5($password)."' ) ") or die(mysql_error());

$to      = $email;
$subject = 'Download Area | Login Credentials';
$message = '

Thank you for your purchase

Your account information
-------------------------
Email: '.$email.'
Password: '.$password.'
-------------------------
            
You can now login at http://yourdomain.com/PayPal/';
$headers = 'From:noreply@yourdomain.com' . "\r\n";

mail($to, $subject, $message, $headers);

Let's break this email function down. We use the variable $email to get the user's email address and assign it to the $to variable. The variable $subject is the title/subject that you will see in your email program. After this, we have our message, which will contain a thank you note as well as the account information. The $email and $password variables in the message will change to the correct information once the email has been sent. We also have set a custom header. When the user receives the email, the "from" address will display as "noreply@yourdomain.com".

Step 9 - Invalid Payment Email

An invalid payment might occur because of fraud, but also because of a problem with PayPal; so we want to make sure that our customer gets what he paid for. So we are going to send an email to our site administrator, telling him to contact the buyer for more information. Simply copy the email code we used before and then make the changes listed below.

// PAYMENT INVALID & INVESTIGATE MANUALY!

$to      = 'invalid@yourdomain.com';
$subject = 'Download Area | Invalid Payment';
$message = '

Dear Administrator,

A payment has been made but is flagged as INVALID.
Please verify the payment manualy and contact the buyer.

Buyer Email: '.$email.'
';
$headers = 'From:noreply@yourdomain.com' . "\r\n";

mail($to, $subject, $message, $headers);

This code is nearly the same as above, only we made some changes to the receiver, subject and message.

Step 10 - User Login

This is our final step, where we build a simple login form for our buyers. Make a new php file, and name it login.php. We'll use the same HTML page as used for the index.php, only we will make some adjustments to the content of the page, and of course add a bit of styling to our login form.

login.php - This is the page where our buyers can login.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Nettuts.com | Login</title>
<link rel="stylesheet" type="text/css" media="All" href="css/style.css" />
</head>
<body>

	<div id="wrap">
		<h3>Login</h3>
		<p>Please enter your login credentials to get access to the download area</p>
		
		<form method="post" action="" >
			<fieldset>
				<label for="email">Email:</label><input type="text" name="email" value="" />
				<label for="password">Password:</label><input type="text" name="password" value="" />
				<input type="submit" value="Login" />
			</fieldset>
		</form>
		   
	</div>

</body>
</html>

Add to style.css

label{
	display: block; /* Make sure the label is on a single line */
	margin: 3px; /* Create some distance away from the input fields */
}

input{
	padding: 3px; /* Give the text some more space */
	border: 1px solid gray; /* Add a border around the input fields */
	margin: 3px; /* Create some distance away from the labels */
}

Now that we've made our form, we need to check if the login credentials are correct. I made a few changes to login.php so we can get started:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Nettuts.com | Login</title>
<link rel="stylesheet" type="text/css" media="All" href="css/style.css" />
</head>
<body>

	<div id="wrap">
		
		<?php 
		
		mysql_connect("localhost", "paypalUser", "test123") or die(mysql_error());
                mysql_select_db("PayPal") or die(mysql_error());

		
		if(isset($_POST['email']) && isset($_POST['password'])){
			// Verify
		}else{
		?>
	
		<h3>Login</h3>
		<p>Please enter your login credentials to get access to the download area</p>
		
		<form method="post" action="" >
			<fieldset>
				<label for="email">Email:</label><input type="text" name="email" value="" />
				<label for="password">Password:</label><input type="text" name="password" value="" />
				<input type="submit" value="Login" />
			</fieldset>
		</form>
		
		<?php
		}
		?>
		   
	</div>

</body>
</html>

The code above will check if email and password are both posted. If true, we can verify the credentials. If not, we return a error. The next code we are going to write will be placed below "// Verify". First we need to turn the post variables into local variables.

$email = mysql_escape_string($_POST['email']);
$password = md5($_POST['password']);

I've added an escape function to prevent mysql injection and have transformed the posted password into a md5 hash. Because we did this in our database, we must also hash the user's password to compare the two values correctly. Now it's time to verify the data.

$email = mysql_escape_string($_POST['email']);
$password = md5($_POST['password']);
			
$gUser = mysql_query("SELECT * FROM users WHERE email='".$email."' AND password='".$password."' LIMIT 1") or die(mysql_error());
$verify = mysql_num_rows($gUser);
			
if($verify > 0){
	echo '<h3>Login Complete</h3>
		  <p>Click here to download our program</p>';
}else{
	echo '<h3>Login Failed</h3>
		  <p>Sorry your login credentials are incorrect.';
}

As you can see, we are running a mysql query, and are selecting all the data from our user table - but only the row where the user's email address matches the one from the database. mysql_num_rows checks if a match has been found: 1 = true; 0 = false.

That's All!

And that's the end of this tutorial. I hope you enjoyed it, and feel free to leave a comment with your thoughts. Have any tips that might help?

  • Subscribe to the NETTUTS RSS Feed for more daily web development tuts and articles.


Related Posts

Check out some more great tutorials and articles that you might like

Enjoy this Post?

Your vote will help us grow this site and provide even more awesomeness

Plus Members

Source Files, Bonus Tutorials and
More for $9 a month for all TUTS+
sites in one subscription.

Join Now

User Comments

( ADD YOURS )
  1. PG

    mark March 4th

    That’s Really good

    ( Reply )
  2. PG

    Timothy March 4th

    Great tutorial. Could come in really handy. Thanks

    ( Reply )
  3. PG

    Nathan Williams March 4th

    Cool beans, I’ll be adding that to me bookmarks

    ( Reply )
  4. PG

    iPad March 4th

    Great tutorial!! this is what i need

    ( Reply )
  5. PG

    Bjorn March 4th

    Nice. Solid and well-directed, step-by-step. Thanks!

    ( Reply )
  6. PG

    codex73 March 4th

    Nice!

    ( Reply )
  7. PG

    Alex Hughes March 4th

    Great tutorial.
    Never seen such a clear tutorial on this topic.

    Thank you with a cherry on top

    ( Reply )
  8. PG

    Parkkipirkko March 4th

    Some kind of expiration mechanism would be nice… for example username/password works only 24 hours or something like that.

    ( Reply )
  9. PG

    Max March 4th

    NOW WE’RE TALKING!!!!

    ( Reply )
  10. PG

    Ryan March 4th

    I just build a whole application using this method, it works really great… although paypal is sometimes late in sending the notification…

    great tut!

    ( Reply )
    1. PG

      Philo March 5th

      Hi Ryan,

      This is correct, it could take up to 5 min in my experience with the PayPal IPN.

      ( Reply )
  11. PG

    Tommy M March 4th

    Really looking forward to reading this!! I have been waiting for a good tutorial to harness Paypals IPN for a while now.

    ( Reply )
  12. PG

    Michael Mullen March 4th

    wow, great tutorial. just what i was looking for

    ( Reply )
  13. PG

    Evan Byrne March 4th

    Wow, it’s like you read my mind. I was just about to work on something that uses Paypal for a client.

    ( Reply )
  14. PG

    Wayne March 4th

    The problem with this is if someone already has a paypal account and enters the card number that is on file with paypal, he will be asked to login instead.

    In past experience this is a little bit of a problem because some people never use paypal and forget their password.

    ( Reply )
  15. PG

    Philo March 4th

    Thanks for replies & kind words! :)
    Happy to know that you enjoyed the tutorial.

    ( Reply )
  16. PG

    Guillaume March 4th

    This is an awesome tutorial. I am a bit new to PHP and I am wondering about the next step of putting the file url to be downloadable. Then how can you secure the file if someone is trying to access it from the full URL of the file, is it possible to redirect the person to the login page?

    Thanks !

    ( Reply )
    1. PG

      Philo March 4th

      This is possible, with PHP you can build a download system like download.php?filename=movie.zip

      In download.php you check if the user is logged in, if yes the download will start.

      If you would like to see an tutorial about this, please make a suggestion here:
      http://psdtuts.uservoice.com/pages/nettuts_tutorial_suggestions

      If enough people are interested, i might write a tutorial about it ;)

      ( Reply )
      1. PG

        David Singer March 4th

        Its very easy to do. 20 lines of code tops. just be sure to set your headers correctly in download.php.

        I wrote a function to do it
        /**
        * @brief Sets headers correctly for downloading a file.
        * @return void.
        */
        function header_download($filename, $contentLength = -1, $contentType = ‘application/force-download’) {
        $filename = basename($filename);
        $contentLength = (int) $contentLength;
        $contentType = trim($contentType);

        // check if content length is a positive integer or 0
        if (ctype_digit((string) $contentLength)) {
        header(’Content-Length: ‘ . $contentLength);
        }

        header(’Pragma: public’); // required
        header(’Expires: 0′);
        header(’Cache-Control: must-revalidate, post-check=0, pre-check=0′);
        header(’Cache-Control: private’,false); // required for certain browsers
        if ($contentType) {
        header(”Content-Type: {$contentType}”);
        }
        header(’Content-Transfer-Encoding: binary’);
        header(”Content-Disposition: attachment; filename={$filename}”);
        }

        Used it like this:
        $source = read_file(’yourfile’);
        header_download(”yourfile}”, strlen($source), $mimeType);

        echo $source;
        exit;

      2. PG

        Guillaume March 5th

        Thanks !!

  17. PG

    ibrahim March 4th

    yeah what i was looking for…
    maybe you could show us some extra features like payment amount checking
    etc

    ( Reply )
  18. PG

    Tom March 4th

    Great tutorial! I’ve being looking for something like this all over.

    ( Reply )
  19. PG

    Shibi Kannan March 4th

    Fantastic Tutorial
    I was looking for something like this and very happy to find solution at nettuts. I have used this method in my website and it works fine.
    Few points:
    database info: this differs from server to server, in my case “localhost” setting gave me an error posted below:

    [ Warning: mysql_connect() [function.mysql-connect]: Can’t connect to local MySQL server through socket ‘/var/lib/mysql/mysql.sock’ (2) in
    /websites/webfusionus/LinuxPackage11/wf/us/_2/wfus-2019-1.webfusion-hosting.com/public_html/paypal/login.php on line 13
    Can’t connect to local MySQL server through socket ‘/var/lib/mysql/mysql.sock’ (2) ]

    I guess some other folks might have similar problem so I wanted to share my experience.

    very simple solution:
    Look at the database info in phpmyadmin and note down server id
    and replace ‘localhost’ with the server id: exmaple curas-mysql-us-01

    That should take care of it.

    Another issue in login page, the password field needs to be formatted to show **** instead of actual password.

    We expect more such great functional tuts
    Keep up the good work guys.
    Thank you

    ( Reply )
  20. PG

    Sirwan March 4th

    Iv done this before, but i went through pain doing this, it was also costly to test!

    good tutorial!

    ( Reply )
    1. PG

      Jonathan Cousins April 17th

      You should have used the sandbox features by Paypal (developer.paypal.com) it allows you to test this feature with no real money exchanging hands (just fake hands).

      ( Reply )
  21. PG

    crysfel March 4th

    this is a good post!! i like it!!

    ( Reply )
  22. PG

    Angel March 4th

    Thank you, Thank you, Thank you

    ( Reply )
  23. PG

    Nick March 4th

    Thank you, very useful for me.

    ( Reply )
  24. PG

    JĂłnatas March 4th

    OMG Thank You

    your are perfect!

    ( Reply )
  25. PG

    EmpireFX March 4th

    Very good tutorial, i do not imagine that would be so easy

    ( Reply )
  26. PG

    Jash Sayani March 4th

    Are there platforms that allow people to easily make sites like http://mydisk.se/ ?

    I would really like to get a ready-made system made in PHP and deploy it on my server….

    ( Reply )
  27. PG

    Steve March 4th

    Very good, I would really like to see an advanced version on this tutorial too, adding amounts, time limits etc.

    ( Reply )
  28. PG

    Doug March 4th

    Thanks for this. If I ever use PayPal, it should be much easier to understand now!

    ( Reply )
  29. PG

    josheat March 4th

    I was needing something like this in the my next job, which coincidentally is today =D

    Cheers!

    ( Reply )
  30. PG

    Rocky March 4th

    Wow just the type of tutorial that most people are after including myself i like how u covered testing as well as the final use for payment and how to verify payments, and allow access to your login area /based on IPN

    ( Reply )
  31. PG

    leksa March 4th

    I LOVE EFFECTIVE TUTORIAL!!
    again and again,.. nice work, Nettuts :D

    ( Reply )
  32. PG

    Brenelz March 4th

    I needed this about a month ago when I was working on a certain project.

    Great tutorial!

    ( Reply )
  33. PG

    Ian B March 4th

    Nice tutorial.

    A few years back I implemented IPN on one of my sites. It took me forever to figure out how to get it all working.

    ( Reply )
  34. PG

    Neil March 4th

    See the quality of web casts has remained HIGH quality since the launch of plus Tuts,

    ( Reply )
  35. PG

    leksa March 4th

    Jeff,.. just to confirm. The layout for this comment(s) look weird in Opera.

    *no problem if you deleted this message after fix the problem.

    ( Reply )
  36. PG

    Brake March 4th

    Great tut!,

    Is there any way to do this?

    Setup a button through PayPal’s merchant tools, in the additional fields create one that has their session id (hidden).

    Before sending them to PayPal stuff their url / other info into your database along with their session id, and then when PayPal hit your IPN script have it match it up and flag it as paid for or active or whatever.

    ( Reply )
    1. PG

      Philo March 5th

      Hi Brake,

      Yes this is possible, you can add additional fields, in your case their session id.
      PayPal sends all date including additional fields to your IPN url, you could then check if there session id’s matches up.

      ( Reply )
  37. PG

    Otto March 4th

    PERFECT!!!!!

    Thanks!!!!!!!!!!!

    ( Reply )
  38. PG

    John S March 4th

    You should probably add that paypal has a test site where you can sign up for test buyer and sellers accounts. This way you can actually test your scripts out with fake money. The site is http://www.sandbox.paypal.com.

    ( Reply )
  39. PG

    insic March 5th

    good job. a lot of developers need this.

    ( Reply )
  40. PG

    Robert Wictorzon March 5th

    Very nice! Seems simple enough.. :) I will try this.

    ( Reply )
  41. PG

    Martyn March 5th

    Great Tutorial, Very handy indeed!

    ( Reply )
  42. PG

    Ben Blogged March 5th

    Just looking for something like this!

    ( Reply )
  43. PG

    Kitson March 5th

    Downloaded the source code but extract error. Damaged file

    ( Reply )
    1. PG

      Philo March 5th

      Hi Kitson,

      I downloaded and extracted the files with no problems.
      Please re-download the source files and try to again, or use a other program to extract the files.

      ( Reply )
  44. PG

    Braden Keith March 5th

    Interesting! I was wondering!

    BTW on step 9, the error message manually is spelled wrong.

    ( Reply )
  45. PG

    Carl O'Dell March 5th

    Great tutorial, Would be nice to show how to have a dynamic buy now button instead of a static product.

    ( Reply )
  46. PG

    Chris Gunther March 5th

    Nice introduction to using this PayPal feature.

    ( Reply )
  47. PG

    OSXBOY March 6th

    $gUser = mysql_query(”SELECT * FROM users WHERE email=’”.$email.”‘ AND password=’”.$password.”‘ LIMIT 1″) or die(mysql_error());

    Not ideal on a production server, the or die(mysql_error()) could expose the email and password.

    Also a good idea to encrypt the passwords in the DB

    ( Reply )
    1. PG

      Philo March 6th

      Hi OSXBOY,

      True, i have added it to the tutorial so people can see if something goes wrong.
      The passwords are encrypted as you can see, the password is being insert as a md5 hash, and is also being used to check if the login password hash matches up with the hash in the database.

      ( Reply )
  48. PG

    Marcel Doornbos March 6th

    Hi,

    Great tutorial. Thought I have found a paypal payment processor that does something similar to this. But in that one you can specify the price, where the payment has to be made to, the quantity, etc.. Is it possible to add that here too? because than it would be easy to have the price of the product depend on what the users choose to buy etc..
    If you want to take a look at that paypal script I found,
    E-mail me :)

    Regards,

    Marcel Doornbos

    ( Reply )
    1. PG

      Jonathan Cousins April 17th

      Free Paypal ‘buy it now’ button php script here:
      http://profitphp.com/2009/02/make-paypal-buttons/

      ( Reply )
  49. PG

    osearth March 6th

    Incredible! I am stuck on a project and this is all i need. Amazing timing with this tutorial! I appreciate sharing your work thank you.

    ( Reply )
  50. PG

    carl March 6th

    Great tutorial, wish I would have had this a while ago when I had to work this all out by myself.

    Anyway, thanks again.

    ( Reply )
  51. PG

    Md Emran Hasan March 7th

    If anyone need to handle other popular payment gateway such as Authorize.net or 2CheckOut along with Paypal, you guys can take a look into my unified Payment Gateway Library. It will also allow you to run the payment process in test environment.

    Btw, good article Philo!

    Cheers

    ( Reply )
  52. PG

    Paulius March 7th

    It was time for me to go sleep (because it`s 3 am at my place now), but I found this post of Yours! How could You sleep, then one guy explains all what You need for tomorrow work! Thank You very much!. You are really Great teacher :) And That`s wonderful! Hope to read something more interesting and useful from You! Don`t stop! We are watching for Your actions ;)

    Good night :)

    p.s. Actually, I need not static prices (like You showed the example with 10 USD), but more flexible prices… It might be any sum my site visitor wants… But, hope to make it somehow, because You gave me basics of PayPal+PHP. Thanks one more time!

    ( Reply )
  53. PG

    James March 8th

    Waited along time for this! thanks!

    ( Reply )
  54. PG

    Dave Jones March 9th

    Ok tutorial, but the verification process is missing several critical steps

    When you receive a VERIFIED postback response, perform the following checks on data in
    the IPN:
    1. Check that the payment_status is Completed.
    2. If the payment_status is Completed, check the txn_id against the previous PayPal
    transaction that you processed to ensure it is not a duplicate.
    3. Check that the receiver_email is an email address registered in your PayPal account.
    4. Check that the price, carried in mc_gross, and the currency, carried in mc_currency, are
    correct for the item, carried in item_name or item_number.
    After you complete the above checks, notification validation is complete. You can update your
    database with the information provided, and you can initiate other appropriate automated
    back-end processing.

    ( Reply )
    1. PG

      Dave Jones March 9th

      Actually let me rephrase that. This is a GREAT tutorial – apart from the poor verification of the transaction, which really let’s it down. If you don’t take all those steps to verify the transaction your server could easily be spoofed.

      Apart from that it is awesome and I hope you write some more TUTs soon!

      ( Reply )
      1. PG

        Aurel Dragut April 10th

        The IPN url address is not public so i guess some verifications are useless. I guess all you need to check would be payment status and the txn id.

    2. PG

      Chuck March 13th

      How can I make these changes? Can someone point me into the right direction on how to fix these problems. Thanks

      ( Reply )
    3. PG

      Jonathan Cousins April 17th

      “2. If the payment_status is Completed, check the txn_id against the previous PayPal transaction that you processed to ensure it is not a duplicate.”

      How do you do that? What do you check it against?

      Do you need a database of every txn_id?

      ( Reply )
  55. PG

    sx March 9th

    Here you can sign up for paypal sandbox to safely test your code:
    https://developer.paypal.com/devscr?cmd=_signup-run

    Here is a link related to paypal api coding with sample codes:
    https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=developer/library_code

    ( Reply )
  56. PG

    SX March 9th

    What Dave Jones said is required. This code will only check to see if the data paypal sent to your script is actually what paypal sent. You still need to check the data. Anyone can click buy it now and have a failed payment, yet you will still get a verified response from paypal, but with this code the user will still be able to access the download area without payment going through. Not safe for production.

    ( Reply )
  57. PG

    ben March 16th

    what is the point of the “Finished Product: Preview” heading at the top of this article? there is no finished product preview. that heading doesn’t link to anything. god i get fed up with things which don’t just join up and work on websites.

    ( Reply )
  58. PG

    Eneza March 17th

    does this tutorial works on Personal Account?

    Detailed Tutorial Thanks!

    ( Reply )
  59. PG

    Waldemar Axdorph March 20th

    Please use mysql_real_escape_string instead of mysql_escape_string. mysql_escape_string is deprecated (source: php.net’s manual; http://se2.php.net/mysql_escape_string ).

    Great tut though!

    ( Reply )
  60. PG

    atlante April 3rd

    I can’t get it to work. I never get an email notification and paypal’s sandbox isn’t really giving me any confirmations either.

    ( Reply )
  61. PG

    atlante April 6th

    When I get a payment I get this messae:

    Dear Administrator,

    A payment has been mae but is flagged as INVALID.
    Please verify the payment manualy and contact the buyer.

    Buyer Email: (no email address sent)

    for some reason, It’s not giving me a valid payment(which it is) and I’m not getting the email address sent to me… why is this happening?

    Please help!

    ( Reply )
  62. PG

    Edmonton April 8th

    I also get payments flagged as INVALID everytime I use the Instant Payment Notification (IPN) simulator from http://www.sandbox.paypal.com
    I can choose the payment_status and set it to Completed, but still cant get a payment flagged as VERIFIED.
    Does it always respond with INVALID as its a fake-simulated payment?
    Will it be flagged as VERIFIED when not using the simulator?

    ( Reply )
    1. PG

      Jonathan Cousins April 17th

      Try creating a ‘buy it now’ button a do a sandbox payment process because it will actually create a IPN anyway (if you have selected it in your profile settings)…

      Change “$fp = fsockopen (’ssl://www.paypal.com’, 443, $errno, $errstr, 30);” to “$fp = fsockopen (’www.sandbox.paypal.com’, 80, $errno, $errstr, 30);” otherwise it may not work.

      I get an error when using the ssl.

      ( Reply )
      1. PG

        Dan Rumney July 3rd

        I don’t thing the problem is the SSL… it’s the actual domain name that you’re using.

        You need to POST to sandbox.paypal.com when you’re using the IPN simulator… *not* http://www.paypal.com

  63. PG

    Chen April 21st

    been looking for this for a long time now, thank you very much for creating such awesome tutorial

    ( Reply )
  64. PG

    nitin April 24th

    Hi I am creating website. i had completed the payment donation using above. Now i want to ask one thing that how to come back from paypal sandbox to our site.
    Thank U.

    ( Reply )
  65. PG

    tonu May 1st

    very nice………………

    ( Reply )
  66. PG

    Glen May 4th

    Without a doubt the best Paypal IPN tutorial on the net. Thankyou so much you have saved me a lot of time.

    ( Reply )
  67. PG

    Mike May 8th

    Hi guys, i test this and write in the Database Perfectly, BUT!!!

    i never recieve the email, any tip?

    ( Reply )
  68. PG

    Aaron Healey June 20th

    Hey i need help with IPN, i get stuck on the a script i am doing for instant download “Getting back that the person paid”

    ( Reply )
  69. PG

    Vedhanish June 24th

    Hi,

    Thats a great tutorial. But do we need a premier account or even a Business account will do this.

    Please advice.

    ( Reply )
  70. PG

    winda June 29th

    great tutorial,,

    thanks for the explaination,,,

    ( Reply )
  71. PG

    memati July 7th

    thank you. i managed to get it working. it took me 7 hours. There is problem on sandbox. i could not get it working on there then i tried the normal one and it worked.

    perfect

    ( Reply )
  72. PG

    memati July 13th

    One question:

    How can i display login information on the returning page of paypal. Which method shoud i use? (I am not talking about the ipn.php)

    Thanks

    ( Reply )
  73. PG

    Jeff hunt July 24th

    This is a GREAT tutorial. Very handy! Thanks!

    ( Reply )
  74. PG

    nagarjuna August 26th

    its really great…a clear explanation

    ( Reply )
  75. PG

    Harry August 26th

    Great toot. It answered ALL the questions I had that couldn’t be answered on the PayPal site. You go, Philo.

    ( Reply )
  76. PG

    Chrispass September 10th

    Respect my friend….
    RESPECT!

    thank you VERY much

    Chris from Greece

    ( Reply )
  77. PG

    Sebastian September 16th

    This is great

    I just have one little thing.

    ipn.php adds two records in the database when you submits from paypal!

    Can anyone help me?

    Best regards
    Sebastian

    ( Reply )
  78. PG

    abcdef October 9th

    Thanks tutsplus for a useful tutorial.

    ( Reply )
  79. PG

    Joe October 11th

    Could come in handy :P

    ( Reply )
  80. PG

    Naveen October 12th

    Superb tutorial!!! Thanks

    ( Reply )
  81. PG

    umesh chandra October 29th

    This tutorial is really good to use.
    But how to to send paid money through query string.

    ( Reply )
  1. Arrow
    Gravatar

    Your Name
    October 29th