Home arrow PHP arrow Developing a PayPal Customer Download Script

Developing a PayPal Customer Download Script

This is the fifth part of the PayPal IPN PHP script tutorial. This part will discuss the details of the customer download script (customerdownload.php).

  1. Developing a PayPal Customer Download Script
  2. Customer Download Page
By: Codex-M
Rating: starstarstarstarstar / 2
February 01, 2011

print this article



The process flow and purpose of this script can be summarized with a flow chart, shown below:

The important thing to note is that the moment the customer lands on the download page in your website, the IPN has already been successfully processed by the IPN handler script (ipnhandler.php) and inserted into the customer records table.

All the download script needs to do is retrieve and validate the user input invoice number and IP address records, and then compare that with the IPN data saved in the customer records database table to make sure it belongs to a valid, paid-up customer.

The project's complete source code will be available for downloading at the end of this tutorial series (in part six, the next part). It covers all of the scripts discussed in parts one through five. It also illustrates in detail how to implement this project on your own test server, using your own server-specific information and PayPal sandbox test accounts.

The PHP script: customerdownload.php

Below is the complete, working script for customerdownload.php. It will be able to execute the process as stated in the flow chart. 


//Check if the customer download form is submitted

if (!isset($_POST['invoicenumber']))

//Form is not submitted, show the web form to the customer

<title>Download your Ebook here</title>
<form action="<?php echo $SERVER['PHP_SELF']; ?>"
Enter your Paypal Invoice Number to download the ebook: <input name="invoicenumber" size="40">

<!--Retrieve the user IP address, then assign it to the visitor IP field-->

<input type="hidden" name="visitorip" value="<?php echo $_SERVER["REMOTE_ADDR"]; ?>">
<br />
<br />
<i>Note: Invoice number is found in your Paypal Receipt.</i>
<br />

<!--Show recaptcha to the user-->


//You need a recaptcha account to have your own public and private keys
//Visit this page for details:http://code.google.com/apis/recaptcha/docs/php.html

echo recaptcha_get_html($publickey);
<br />
<input type="submit" name="submit" value="Download my ebook">

//Web form submitted, validate the recaptcha first.

$resp = recaptcha_check_answer ($privatekey,
if (!$resp->is_valid) {
die ("The reCAPTCHA wasn't entered correctly. Go back and try it again." .
         "(reCAPTCHA said: " . $resp->error . ")");
else {

//Recaptcha validation succeeded, process the customer request
//Retrieve the posted invoice number from the web form

$invoicenumber = trim($_POST['invoicenumber']);

//Retrieve the posted IP address from the web form

$visitoripaddress = trim($_POST['visitorip']);

//Initialize errors array, this will contain any errors found during the validation.

//Validate the invoice number submitted
//Check if the invoice number field is empty

if (empty($invoicenumber)) {
$errors[] = 'ERROR: The invoice number data field is empty.';

//Check if the invoice number is alpha-numeric.

if (!(ctype_alnum($invoicenumber))){
$errors[] = 'ERROR: The invoice number data is not valid.';

//Check if the IP address is valid

if (!(filter_var($visitoripaddress, FILTER_VALIDATE_IP))){
$errors[] = 'ERROR: Your IP address is using invalid format.';

//If there are any errors found during the validation, return it to the user.

if (sizeof($errors) > 0)
        echo "<ul>";
        foreach ($errors as $e)
                echo "<li>$e</li>";
        echo "</ul>";
        die ();

//There are no errors found in the validation, connect to MySQL database

include '/home/www/php-developer.org/paypal_ipn_demo/connect.php';

//Sanitize the invoice number variable in preparation for a MySQL query.

$invoicenumber = mysql_real_escape_string($invoicenumber);

//check if the invoice number exists in the customer records database table

if ($fetch = mysql_fetch_array( mysql_query("SELECT `InvoiceNumber` FROM `customerrecords` WHERE `InvoiceNumber`='$invoicenumber'"))) {

//Invoice number records found, check if the customer has already downloaded the ebook

//You should only allow downloading for customers who have not yet claimed their digital product purchase.

//Retrieve the download status of this transaction based on the given invoice number.
$result1 = mysql_query("SELECT `DownloadStatus` FROM `customerrecords` WHERE `InvoiceNumber`='$invoicenumber'")
or die(mysql_error());
$row = mysql_fetch_array($result1)
or die("Invalid query: " . mysql_error());
$downloadstatus = $row['DownloadStatus'];

//Check also if the payment status is COMPLETED. This is very important; you should not allow downloading to an incomplete/unpaid transaction.

//Retrieve the payment status associated with the invoice number in the customer records table.

$result2 = mysql_query("SELECT `PaymentStatus` FROM `customerrecords` WHERE `InvoiceNumber`='$invoicenumber'")
or die(mysql_error());
$row = mysql_fetch_array($result2)
or die("Invalid query: " . mysql_error());
$paymentstatus = $row['PaymentStatus'];

//Check if the IP address of the customer downloading is an IP address of a valid customer.
//This will prevent spoofing in case the invoice number is leaked to a malicious user.
//Only the customer originating the transaction and paying successfully in PayPal should be allowed to download the digital products.
//This can be done by recording the customer IP address the moment the customer originates the transaction from your shopping page and posts the button values to PayPal.
//PayPal then posts this customer IP address back to you using an IPN message, then the IPN script (ipnhandler.php) saves that in the customer records table.
//This IP address should then be compared to the one planning to download the digital products to ensure that it belongs to a valid customer.
//Retrieve the IP address of the customer associated with that invoice number.

$result3 = mysql_query("SELECT `IPAddress` FROM `customerrecords` WHERE `InvoiceNumber`='$invoicenumber'")
or die(mysql_error());
$row = mysql_fetch_array($result3)
or die("Invalid query: " . mysql_error());
$validipaddress = $row['IPAddress'];

//Finally, once all of the important data is retrieved, check if the download status is incomplete, payment status is complete and the IP address is valid.

if (($downloadstatus=='incomplete') && ($paymentstatus=='Completed') && ($validipaddress==$visitoripaddress)) {

//The transaction is valid.
//Before the script will force download the purchased digital product to the customer
//It needs to know the product name of the purchased products.
//The purpose of this product name is to retrieve the product file name, which will be streamed to the user.
//Retrieve the purchased product name associated with the invoice number.

$result4 = mysql_query("SELECT `ProductPurchased` FROM `customerrecords` WHERE `InvoiceNumber`='$invoicenumber'")
or die(mysql_error());
$row = mysql_fetch_array($result4)
or die("Invalid query: " . mysql_error());
$productpurchased = $row['ProductPurchased'];

//Now retrieve the product filename associated with that digital product
//This product filename is saved in the products table

$productpurchased = mysql_real_escape_string($productpurchased);
$result5 = mysql_query("SELECT `Filename` FROM `productstable` WHERE `ProductName`='$productpurchased'")
or die(mysql_error());
$row = mysql_fetch_array($result5)
or die("Invalid query: " . mysql_error());
$filename = $row['Filename'];

//Force download the ebook to the customer
//Initialize and set the headers; the content-type depends on the type of digital products
//Use readfile to stream the ebook to the customer.

header('Content-Disposition: attachment; filename="http://www.php-developer.org/paypal_ipn_demo/ebookdownloads/'.$filename.'"');

//Now that the customer has completed the downloading, update its records in the customer records table.
//For example, changing the download status to from "incomplete" to "completed"

mysql_query("UPDATE `customerrecords` SET `DownloadStatus` = '$updateddownloadstatus' WHERE `InvoiceNumber` = '$invoicenumber'")
or die(mysql_error());
else {

//Invalid transaction because of one of the reasons stated below:

echo 'Sorry but the downloading process are denied because your transaction happens to be:<br />';
echo '1. A complete transaction, you already downloaded the ebook.<br />';
echo '2. Incomplete, you have not paid fully the product price in Paypal.<br />';
echo '3. Your IP address does not belong to a valid customer.Make sure you are using the same computer during the time of purchase.<br />';
echo 'In this case, please contact the seller to report this problem and provide your Paypal receipt information.Thank you.';
else {

//Invalid transaction because the invoice number submitted by the user is not found in the database.

echo 'Sorry but the Invoice Number is an invalid Paypal Transaction.'; 

>>> More PHP Articles          >>> More By Codex-M

blog comments powered by Disqus
escort Bursa Bursa escort Antalya eskort


- Hackers Compromise PHP Sites to Launch Attac...
- Red Hat, Zend Form OpenShift PaaS Alliance
- PHP IDE News
- BCD, Zend Extend PHP Partnership
- PHP FAQ Highlight
- PHP Creator Didn't Set Out to Create a Langu...
- PHP Trends Revealed in Zend Study
- PHP: Best Methods for Running Scheduled Jobs
- PHP Array Functions: array_change_key_case
- PHP array_combine Function
- PHP array_chunk Function
- PHP Closures as View Helpers: Lazy-Loading F...
- Using PHP Closures as View Helpers
- PHP File and Operating System Program Execut...
- PHP: Effects of Wrapping Code in Class Const...

Developer Shed Affiliates


Dev Shed Tutorial Topics: