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).

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. 

<?php

//Check if the customer download form is submitted

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

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

?>
<html>
<head>
<title>Download your Ebook here</title>
</head>
<body>
<form action="<?php echo $SERVER['PHP_SELF']; ?>"
method="post">
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–>

<?php

//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

require_once(‘recaptchalib.php’);
$publickey = "ENTER_YOUR_RECAPTCHA_PUBLIC_KEY_HERE";
echo recaptcha_get_html($publickey);
?>
<br />
<input type="submit" name="submit" value="Download my ebook">
</form>
<?php
}
else
{

//Web form submitted, validate the recaptcha first.

require_once(‘recaptchalib.php’);
$privatekey = "ENTER_YOUR_RECAPTCHA_PUBLIC_KEY_HERE";
$resp = recaptcha_check_answer ($privatekey,
                                $_SERVER["REMOTE_ADDR"],
                                $_POST["recaptcha_challenge_field"],
                                $_POST["recaptcha_response_field"]);
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.
$errors=array();

//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-type:application/pdf");
header(‘Content-Disposition: attachment; filename="http://www.php-developer.org/paypal_ipn_demo/ebookdownloads/’.$filename.’"’);
readfile("/home/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"

$updateddownloadstatus=’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.'; 
}
}
}
?>
</body>
</html>

{mospagebreak title=Customer Download Page}

This is how the customer download page will look in the web browser:

To implement the customerdownload.php script, this must be placed inside the paypal_ipn_demo folder.

Bear in mind that all of required files for this project have been completely discussed as of this part (part five) of this tutorial series. Below you’ll see all of the files that should be found inside the paypal_ipn_demo folder:

In the next part, you will learn how to implement this project on your own LAMPP (Linux/Apache, MySQL and PHP) server.

[gp-comments width="770" linklove="off" ]

chat