Thursday, November 1, 2007

Chapter 9: Processing Payments for Your Website


When it is time to move into processing payments for your website, you will find many solutions available. The Internet is constantly expanding, and e-commerce is still blooming with ways to earn money on the Internet. As a webmaster, you can take advantage of these opportunities by utilizing merchant account gateway Application Programming Interfaces (APIs) such as VeriSign or third-party payment solutions such as PayPal.

Chapter 8, "Creating a Shopping Cart System," left off at the billing pages. Your shopping cart system is ready to allow the customer to pay for their items and complete their shopping experience. It is up to you, the web developer, to determine how to obtain a customer's money and complete their order. This chapter discusses the differences between using a merchant account gateway API and using third-party payment solutions. It also shows you practical uses of each type of payment system.




Merchant Account Gateways vs. Third-Party Payment Solutions

The major goal I try to accomplish when selling products or services on the Internet is to project a professional, business-like appearance. The best method I can recommend is to utilize a merchant account gateway instead of a third-party payment solution. Why? Because the processing of the customer information remains on your website with a merchant account gateway compared to outside your site with PayPal or another third-party payment solution. There are plenty of pros and cons when trying to determine the best method to utilize. The following sections explore some of them.

What Is a Merchant Account Gateway?

A merchant account gateway is a service you can utilize to process billing information regarding a specific transaction with your customers. The customer information is compiled into a special format and sent through a back-end resource to the gateway. The gateway validates the information, processes it through a bank or financial institution, receives a response, and in turn generates a response to send back to the requesting site (you) while recording the transaction into your gateway account.

Merchant account gateways are growing rapidly in popularity, with more companies starting to offer them. You must have a valid merchant account through a financial institution to utilize a merchant account gateway. Some companies on the Internet offer a merchant account gateway in conjunction with a merchant account. Do not get the impression that you cannot get a merchant account because you do not have a business license, though. This myth is not true; however, you will have to dig a little when talking to the merchant account sales representatives. If you do not have a business license, ask about opening an account based on a sole proprietorship, meaning that you are opening the account in your name to do business.

Usually, when you set up a merchant account gateway, the gateway provider will list merchant accounts they partner with, and you can get special deals through them.

This chapter covers using VeriSign because it offers a free 30-day trial (demo) account that you do not need a merchant account to use. The following are some of the most popular merchant account gateway providers:

Gateway Provider URL

VeriSign www.verisign.com/products/payment.html

Authorize.Net http://www.authorize.net/

Cardservice International (LinkPoint) http://www.cardservice.com/

The previous list is a small group of the most popular gateways. You can find thousands of results by going to Google (http://www.google.com/) and searching for merchant account gateways.

Merchant Account Gateway Pros

The following are some of the advantages of processing payments with a gateway:

  • You do not have to redirect the customer to a different site to perform the billing.

  • You project a more business-like appearance without losing the relationship between your business and the customer performing the transaction.

  • You have more options when logging the transaction; by gathering the billing information on your site, you can log as much user input as you like.

  • It is easier to set up recurring billing by altering the responses sent to the merchant account gateway for the transaction.

  • The customer is not forced to create an account on a third-party site to process the payment.

  • They have extremely fast processing! Usually it is quicker than three seconds from submission to retrieval of results.

Merchant Account Gateway Cons

Every solution has disadvantages; the following are some cons of a merchant account gateway:

  • They are usually expensive to set up, about $300 in some cases.

  • Monthly fees are not uncommon, sometimes up to $60 per month.

  • An average of 2.5-percent transaction fees are deducted for the company that runs the gateway.

  • It is not as easy to develop for them. Sometimes they do not offer PHP support; however, this is not a showstopper! Keep reading in this chapter to find out how to get around a lack of PHP support.

  • You should utilize a Secure Sockets Layer (SSL) certificate and a Hypertext Transfer Protocol-Secure (HTTPS) website while gathering billing information from the customer. SSL certificates cost from $39 per year to $199 per year, depending on where you buy them.


    Tip

    You can purchase valid QuickSSL certificates from http://www.rackshack.net/ in quicker than 20 minutes for less than $50. This is extremely easy to do, and you do not have to go through the difficult process that most companies provide.

  • If the gateway goes offline and your website is running, billing will fail. This causes customers to get frustrated and cancel their orders because they may think your system is not running properly and they lose trust in you.

What Is a Third-Party Payment Solution?

A third-party payment solution is a company that allows you to create virtual accounts with a company; it processes transactions on your behalf. These companies are growing in popularity since the advent of PayPal.

These companies have many different methods of allowing you to send your customers to their websites and process a transaction on your behalf. Once the transaction has cleared through their system, the company will credit the money to your virtual account, and you can transfer or spend the money how you desire from that point.

This chapter shows how to use PayPal because it is the most popular and commonly used third-party payment solution. However, the following are some of the other popular third-party payment solutions I have found (and used) on the Internet.

Third-Party Payment Solution URL

PayPal http://www.paypal.com/

iBill http://www.ibill.com/

CCBill http://www.ccbill.com/

2CheckOut.com http://www.2checkout.com/

You can also find a complete list of these by searching the keywords credit card processing in the Google search engine.

Third-Party Payment Solution Pros

The following are some of the advantages of third-party payment solutions:

  • They are usually easy to set up without a large fee up front.

  • They usually have an easy-to-use interface.

  • They allow you to transfer the money you make to your bank account at any time and allow you to pay other members with it (PayPal).

  • They process the customers' billing information and provide records of the payments.

  • They usually do not charge monthly fees.

Third-Party Payment Solution Cons

Even third-party payment solutions have some disadvantages:

  • When your customer leaves your site to complete a purchase, they may lose a brand awareness of your site during the transaction. As a business, you should always try to eliminate the middleman, especially when dealing with money. Third-party payment solutions have a tendency to break this rule of thumb.

  • They charge an average of 2.5-percent transaction fees. PayPal charges a different amount every transaction, sometimes up to 5 percent or more.

  • Support staff is overloaded. Because these companies usually process multiple types of payments from a large quantity of users, you will usually get the runaround when trying to contact support.

  • They could require more extensive planning on your part to determine how to properly check the customer out in your shopping cart system because the customer will depart your site while making the transaction.

What's the Major Difference?

There are many major differences between the two systems. Not only do you have to develop your systems differently, the control panels between a merchant account gateway and a third-party payment solution could differ greatly. Let's concentrate on the process of accepting customer payments through each of these solutions.

Figure 9.1 shows the processing of payments through your website with a merchant account gateway API.



Click To expand

Figure 9.1: Processing payments through a merchant account gateway

The following are the steps of Figure 9.1:

The customer comes to your website and populates their shopping cart system with the products they want to purchase. Then they go to the checkout page, select the credit card payment method, and enter their billing information.

Your script will compile the information required and send the customer's billing information to the payment gateway for processing.

The payment gateway will send a response through the API to the binary that is on your server, and your script will decode the results and perform the proper checkout actions in your shopping cart system.

You present a custom response to the customer.

That looks pretty simple, doesn't it? The entire process takes usually less than three seconds to complete! During this entire process, your customer never leaves your website to process a payment somewhere else.

Figure 9.2 shows the third-party payment solution process.

Click To expand

Figure 9.2: Processing payments through a third-party payment solution

This is the process step by step:

The customer comes to your website and populates their shopping cart system with the products they want to purchase. When they go to the checkout page, they select a third-party payment solution for their payment method.

Your scripts will generate a special form and send it to the customer's web browser.

Upon receiving the form, the customer's web browser will be redirected to the third- party payment solution's billing pages, and the user will enter their billing information for processing.

The customer is still on the third-party website, and the results are displayed in the third-party payment processor.

The third-party payment processor provides a method for the customer to return to your website with a "token" key that you embedded into the form from step 2. Once your script receives this token, you process it immediately and check out the customer from the shopping cart.

You now send the final custom response to the customer's web browser.

As you may notice, the process of using a third-party payment solution is a lot more work for you as the developer and for the customer. Furthermore, this process generally takes longer to complete than a merchant account gateway takes.

Now that you have a better understanding of gateways and third-party payment solutions, you will begin developing for them.

Preparing Your Site for E-Commerce



Before you begin processing, you need to prepare your site by adding some new tables to your database. The first table you will create is for a special security measure called tokens, which you will create in your processing scripts. I will explain using tokens later; for now, you will just create the tables. Table 9.1 shows the structure for the shopping_cart_tokens table.

9.1 shows the structure for the shopping_cart_tokens table.






















Table 9.1: Structure for shopping_cart_tokens Table

Field Name


Data Type


Length


Extra


cart_id



VARCHAR


255


Primary key



token


VARCHAR


100



If you prefer the command line, you can use this query:
CREATE TABLE shopping_cart_tokens (
cart_id varchar(255) NOT NULL default '',
token varchar(100) NOT NULL default '',
PRIMARY KEY (cart_id)
) TYPE=MyISAM COMMENT='Tokens for Shopping Carts';

Next, you create another table to store the order information upon successful checkout. This table is named shopping_cart_orders (see Table 9.2).

Table 9.2: Structure for shopping_cart_orders Table


















































Table 9.2: Structure for shopping_cart_orders Table

Field Name


Data Type


Length


Extra


orderid



MEDIUMINT


25


Primary key, auto increment



order_date


DATETIME





token


VARCHAR


100



products


TEXT




total


FLOAT


0



type


VARCHAR


25



user_id


VARCHAR



10




If you prefer the command line, you can use this query:
CREATE TABLE shopping_cart_orders (
orderid mediumint(25) NOT NULL auto_increment,
order_date datetime NOT NULL default '0000-00-00 00:00:00',
token varchar(100) NOT NULL default '',
products text NOT NULL,
total float NOT NULL default '0',
type varchar(25) NOT NULL default '',
user_id varchar(10) NOT NULL default '',
PRIMARY KEY (orderid)
) TYPE=MyISAM COMMENT='Shopping Cart Orders';

That concludes the preparation for this chapter. Let's jump into processing some payments!

Creating the Payment Processing Scripts



In Chapter 8, "Creating a Shopping Cart System," you left your shopping cart system ready for the payment pages. This chapter covers two methods to process payments: VeriSign Payflow Pro payment services (with a payment gateway API) and PayPal (a third-party payment service).

The checkout page in the shopping cart performed one last sanity check, adjusted the customer's order as necessary, and gave them a link to make a payment. The link pointed to a script named payment.php, so you will create that script now.

Create a file in your document root named payment.php. This file will be a simple page that asks the customer which method of payment they would like to use. In this book, I cover two payment methods, so you will give hyperlinks to those payment methods in this script. If you are going to offer only one payment method in your shopping cart, you can bypass this page by altering the link in your shopping cart checkout page and pointing it to the relevant script you will create in this chapter.

The following is the code for the payment.php script:
Please choose your ".
"payment method:
".
"".
"Credit Card via our Secure Server

".
"".
"Pay using PayPal

";
footer();
?>

When a user goes through your shopping cart system and confirms their order by clicking the Submit Payment hyperlink, they will see a page like Figure 9.3 depicts.


Click To expand

Figure 9.3: Payment options page

As you may notice, you will give an option to process payments via your secure server first, so the next section shows how to process credit cards with a payment gateway.
Processing Payments with VeriSign Payflow Pro

VeriSign has one of the best payment processing gateways available. VeriSign offers a gateway payment service called Payflow Pro that is fully loaded with all kinds of options including: the Payflow Pro Manager (PPM) control panel, Address Verification Service (AVS), recurring billing services, and much more. Additionally, VeriSign offers a 30-day trial account that you can enable in less than an hour. This is a perfect place for you to explore the developmental process for a payment services gateway!

Warning

Before you begin processing any live payments on your website, you should obtain an SSL certificate for your website and run your processing scripts on your SSL website using HTTPS. If you are using virtual web hosting, contact your web hosting provider and obtain an SSL certificate. If you are using your own server, you can obtain an SSL certificate for cheap at http://www.rackshack.net/ in less than 20 minutes.

Getting Your Payflow Pro Demo Account



Begin the process of setting up your payment gateway by going to www.verisign.com/products/payflow/pro/ and signing up for a trial account. While viewing this page, you should see a Free Payment Trial Account link. Click this link, and complete the signup process. Once you have completed the signup process, you will receive an e-mail notifying you of the signup and giving you some links to the PPM control panel. The Uniform Resource Locator (URL) I received was https://manager.verisign.com/login/login.cfm?partner=VeriSign.

Preparing Your System for Payflow Pro



Before you begin coding for the Payflow Pro payment services, you need to set up your web server for its system. This is easy and does not require any compilations or restarting. Follow these steps:

First, log in to the PPM with the username and password you created during signup.

Once you have logged in, click the Downloads tab at the top of the PPM.

Under the Documentation section, download the developer guide to your hard drive. Click the Payflow Pro Developers Guide-Zipped PDF link. This is important because you will learn how to use a developer guide in this chapter.

Under the Payflow Pro Software Development Kit (SDK) section, download the appropriate SDK for your system. I will cover how to use how to install the Windows SDK in this chapter; however, the Linux installation is not much different. If you are a Linux user, click the Linux-libc6 / glibc2 / ELF kernels 2.0.36 and Above link (or the one called something similar). If you are a Windows user, click the Windows NT 4.0 or Windows 2000 link.

Depending on which file you downloaded in the previous step, extract these files onto your web server. Do not put them in your website's document root because it is not secure to do so. Put them somewhere on your system that the public cannot access through their web browser. On my Windows system, I put them in d:\sites\sybex\win32 whereas my document root is d:\sites\sybex\public_html.

Believe it or not, those are all of the prerequisites for configuring your system to develop your scripts to use Payflow Pro.

You need the files you downloaded in the previous steps to utilize Payflow Pro. The main files in the SDK consist of a binary file that will perform the transaction and return the results and a certificate file that is required for the binary file to authenticate to the gateway. These files really have nothing to do with PHP, but using some PHP system commands, you will call these files, pass the arguments required to them, and capture the output.

Before you go any further, you should also understand that PHP supports Payflow Pro through a special module that you can compile during installation. However, because your web hosting provider probably does not have the Payflow Pro support modules enabled, I cover how to use this payment service without them. By giving you the examples in this chapter, you should be able to figure out how to code for any payment gateway, not just VeriSign.

Understanding the Gateway and API Documentation



Each payment processing gateway has some sort of developer guide associated with its documentation. In the previous section, you downloaded the Payflow Pro developer guide from the PPM. If you have never seen this type of documentation before, it could be difficult to understand. Basically, these guides tell a developer how to determine where, how, and what information to send to the payment gateway. Additionally, a good developer guide will list the required data to send and give you a list of response codes.

After analyzing the Payflow Pro developer guide, you can determine how to develop your scripts for the results you will retrieve. Looking through the documentation, you should notice that you will have to develop your scripts to execute a binary file with arguments such as the credit card numbers, your gateway username, and your gateway password in a URL-encoded format. By executing this binary file, you will be able to retrieve a result, usually in a URL-encoded format such as this: variable=value&variable2=value&variable3=value.

Do not worry; I will cover this in depth when it is time to start processing the information through the gateway.

VeriSign Payflow Pro Payment Processing Scripts



The first script you will create is named creditcard.php. The payment.php page links to it when the user clicks the Credit Card via Our Secure Server hyperlink. This script will gather the required billing information from the customer, send it to the VeriSign Payflow Pro gateway for processing, retrieve a result from the gateway, and redirect the user to your ordercomplete.php script according to the results.

Before you begin with this script, I have created a PHP class file that takes care of the hard work involved in creating a billing information form. This class is the payment forms class, and you can download it at www.phpfreaks.com/script/view/209.php. Download this class file, and extract it into your website document root under the classes directory.

Next, you will create the Hypertext Markup Language (HTML) form that will gather the customer billing information. Create a new HTML file named payment_form.html, and place it in html/payment under your website document root.

This HTML page will utilize embedded PHP with the functions inside the payment forms class to generate drop-down menus for dates, states, and countries. Listing 9.1 shows this HTML form.

Listing 9.1: Billing Information Form


Please
Enter Your Billing Information
















































Order Total$
Name on Credit Card
Credit Card Number
CCV2 Number
Expiration Date
month_select($month);?>
/
year_select($year);?>
Street Address
City
State
state_select($state);?>
Zip Code
Country
country_select($country);?>







Next, you will create the script that will utilize the previous HTML form and process your payments using the gateway. Create a new file inside your website document root, and name it creditcard.php. Listing 9.2 shows the script, which I will explain in further detail.
Listing 9.2: creditcard.php Processing Script

get_cart_id();

switch($_REQUEST['req']){
default:
myheader("Payment Information");

include $_SERVER['DOCUMENT_ROOT'].
'/classes/clsCCForms.php';

// Get shopping cart total.
$total = mysql_result(mysql_query("SELECT
sum(product_qty * product_price) AS subtotal
FROM shopping_carts
WHERE cart_identifier='$cart_id'"),0);
$total = number_format($total, 2);

// Credit Card Forms Class by phpfreak
$ccform = &new CCForms;
include $_SERVER['DOCUMENT_ROOT'].
'/html/payment/payment_form.html';

break;

case "process":
stripslashes(extract($_POST));

$total = mysql_result(mysql_query("SELECT
sum(product_qty * product_price) AS subtotal
FROM shopping_carts
WHERE cart_identifier='$cart_id'"),0);
$total = number_format($total, 2);

$expdate = $month.substr($year, 2, 2);

$pfpro_path = "d:\sites\sybex\win32\bin\pfpro.exe";
$params = "TRXTYPE=S&TENDER=C".
"&PWD=XXXXXXXX&USER=XXXXXXXX".
"&PARTNER=VeriSign".
"&ACCT=$cardnumber&CCV2=$ccv2".
"&EXPDATE=$expdate&AMT=$total".
"&NAME=$name&STREET=$street".
"&ZIP=$zip";
putenv("PFPRO_CERT_PATH=d:\sites\sybex\win32\certs");
$transaction = exec($pfpro_path.'
test-payflow.verisign.com 443
"'.$params.'" 30');

// Convert the results into an array
$tmp_results = explode('&', $transaction);
foreach($tmp_results AS $tmp_result){
$tmp = explode('=', $tmp_result);
$result[$tmp[0]] = $tmp[1];
}
// Debug: Uncomment lines below
// to see $result array

// echo "
";
// print_r($result);
// echo "
";
// exit();

switch($result[RESULT]){
case "0":
// Generate token
$token = md5(uniqid(rand(),1));

// Insert token into DB
$token_check = mysql_result(mysql_query("SELECT COUNT(*)
FROM shopping_cart_tokens
WHERE cart_id='$cart_id'"),0);

if($token_check == 0){
mysql_query("INSERT INTO shopping_cart_tokens
(cart_id, token)
VALUES ('$cart_id', '$token')");
} else {
mysql_query("UPDATE shopping_cart_tokens
SET token='$token'
WHERE cart_id='$cart_id'");
}

// Redirect user to ordercomplete.php
header("Location: /ordercomplete.php?req=success&t=$token");
break;

default:
myheader("Transaction Error");
echo "There has been a problem with your transaction. ".
"You have not been charged for this order.
".
"Please see below:
".
"Results: $result[RESPMSG]
".
"Reference Number: $result[PNREF]
";
break;
}
break;
}
footer();
?>



The first portion of this script should be pretty standard to you by now. You start the PHP engine, include your required files, and then initialize the switch for the script. Because this script is related to your shopping cart system, you utilize the ShoppingCart class and get the cart identifier:
get_cart_id();

switch($_REQUEST['req']){

The default case includes the payment forms class (clsCCForms.php) that you downloaded earlier and then performs a query to get the total price of everything in the customer's shopping cart. After you initialize the payment forms class, you include the payment_form.html file. Note
I show the default case in this switch first. This is to show you that even though the PHP documentation shows the default case last, you can still use it in the first position.


The following is the default case:
default:
myheader("Payment Information");

include $_SERVER['DOCUMENT_ROOT'].
'/classes/clsCCForms.php';

// Get shopping cart total.
$total = mysql_result(mysql_query("SELECT
sum(product_qty * product_price) AS subtotal
FROM shopping_carts
WHERE cart_identifier='$cart_id'"),0);
$total = number_format($total, 2);

// Credit Card Forms Class by phpfreak
$ccform = &new CCForms;
include $_SERVER['DOCUMENT_ROOT'].
'/html/payment/payment_form.html';

break;

The form in the default case will post the user inputs to the process case. Now you get to figure out how to use that Payflow Pro gateway! Like always, I will break this case down into smaller portions:
case "process":

First, you extract the $_POST values into simple variables. Remember, when you use extract, the key in an array becomes the variable name, and the value is assigned to it. For example, $_POST['myvar'] = "test" would become $myvar = "test":
stripslashes(extract($_POST));

Second, for security purposes, you never want to allow the total to be obtained by input from the HTML form. Sooner or later, someone will try to alter their form posts and even alter the prices of their shopping carts; therefore, you always recalculate after the form has been submitted:
$total = mysql_result(mysql_query("SELECT
sum(product_qty * product_price) AS subtotal
FROM shopping_carts
WHERE cart_identifier='$cart_id'"),0);
$total = number_format($total, 2);

VeriSign requires the credit card expiration date to be formatted as MMYY, and in my payment forms class the output of the year is YYYY. To compensate for the requirements of Payflow Pro, you combine the $month and $year values and use the substring (substr) PHP function to chop off the first two numbers of the year to make a variable named $expdate. To simplify the explanation, the expiration date of January 2004 would be 0104 after you have corrected it with this code:
$expdate = $month.substr($year, 2, 2);

Now you will dig into the Payflow Pro processing. You will define some variables that you will pass into the PHP exec function, which will execute system commands, such as executables, with the arguments you pass into it. Using the exec function is similar to typing into a DOS or shell prompt. Note
For this example, you will assign variables to each element of the exec argument. If you choose, you could create one simple string and execute it with all of the variables in Table 9.3.


The first variable you will define is the path to the Payflow Pro executable (pfpro.exe) file:
$pfpro_path = "d:\sites\sybex\win32\bin\pfpro.exe";

The next variable you will create is the querystring of information about the user and your Payflow Pro account. Table 9.3 explains the querystring.

Table 9.3: Querystring Variables
































































Table 9.3: Querystring Variables

Variable



Value


Purpose


TRXTYPE


S


The transaction type. Use S
for sale.



PWD


XXXXXXXX


Your Payflow Pro password.


USER


XXXXXXXX


Your Payflow Pro username or store name.


Partner


VeriSign


Required! Demo accounts use VeriSign.


ACCT


$cardnumber


Credit card number. You obtained this by extracting
the $_POST array from the billing information
form.


CCV2


$ccv2


Credit card verification number obtained from the
billing information form.


EXPDATE


$expdate


Expiration date. Previously defined in this
script.


AMT


$total


Order total price. Previously obtained in this
script.


NAME


$name


Name on credit card from billing information
form.


STREET


$street


Street address from billing information
form.


ZIP


$zip


ZIP code from billing information
form.


The following shows the querystring:
$params = "TRXTYPE=S&TENDER=C".
"&PWD=XXXXXXXX&USER=XXXXXXXX".
"&PARTNER=VeriSign".
"&ACCT=$cardnumber&CCV2=$ccv2".
"&EXPDATE=$expdate&AMT=$total".
"&NAME=$name&STREET=$street".
"&ZIP=$zip";

Next, you have to notify your system where the Payflow Pro certificate file is located. You downloaded this file in the SDK during the "Preparing Your System for Payflow Pro" section of this chapter. When I extracted the SDK, the file was located at d:\sites\sybex\win32\certs. Using the PHP putenv function, you can put the required PFPRO_CERT into your system environment variable path:
putenv("PFPRO_CERT_PATH=d:\sites\sybex\win32\certs");

Now you will execute the Payflow Pro binary with all of the information you have gathered. Look at the usage of the following exec function. You will assign a variable $transaction to it. All of the output from the execution of the binary will be assigned to the $transaction variable, and from there you can figure out how to use it:
$transaction = exec($pfpro_path.'
test-payflow.verisign.com 443
"'.$params.'" 30');

This exec function is executing a command line like this:
d:\sites\sybex\win32\bin\pfpro.exe test-payflow.verisign.com 443 [PARAMS] 30 Note
Notice the 30 after PARAMS. This is the number of seconds to allow the binary file to wait before it times out if no response is available from the gateway. Do not set this too high or your PHP script may time out and the user may click away from the page; however, do not set this too low or the script may not receive a response from the gateway. Fifteen to thirty seconds is sufficient.


Now you have the output assigned to the $transaction string. This output is in the format of a querystring, as mentioned earlier. With this string, you can break it into an array using the explode function. The explode function accepts an argument and a string. It will search for the argument inside of the string and create a new array key each time it finds a match for the argument passed to it.

If you were to run your transaction script right now and echo the $transaction, you would see something like this:
RESULT=0&PNREF=V64A31660131&RESPMSG=Approved&AUTHCODE=023PNI&AVSADDR=X&AVSZIP=X&IAVS=X

The previous result will do you no good until you can break it apart. Break each element into an array using the & argument:
// Convert the results into an array
$tmp_results = explode('&', $transaction);

The output of the $tmp_results array using print_r and preformatted HTML tags would be as follows:
Array
(
[0] => RESULT=0
[1] => PNREF=V64A31660131
[2] => RESPMSG=Approved
[3] => AUTHCODE=023PNI
[4] => AVSADDR=X
[5] => AVSZIP=X
[6] => IAVS=X
)

Now that you have $tmp_results in an array, you still do not have exactly what you need to best determine how to handle the transaction results. Let's break this array down one more time using explode on the = argument:
foreach($tmp_results AS $tmp_result){
$tmp = explode('=', $tmp_result);
$result[$tmp[0]] = $tmp[1];
}

The output of the $result array you generated in the previous code would look like this:
Array
(
[RESULT] => 0
[PNREF] => V64A31660131
[RESPMSG] => Approved
[AUTHCODE] => 023PNI
[AVSADDR] => X
[AVSZIP] => X
[IAVS] => X
)

Now you have something with which to work!

If you would like to debug your arrays at any time, you can uncomment the following code to see output similar to the previous examples:
// Debug: Uncomment lines below
// to see $result array

// echo "
";
// print_r($result);
// echo "
";
// exit();

After you have processed the return from $transaction, you can use a switch on the value of $result[RESULT] to redirect the customer to the desired results based on the success or failure of the transaction:
switch($result[RESULT]){

The first case is a successful transaction because the value of $result[RESULT] is 0. Check the Payflow Pro developer guide to see what other values may be assigned to the RESULT. For now, you really only care about 0 because for anything else you will display the other array values and tell the customer their transaction has failed:
case "0":

Okay, you are inside the successful transaction case now. Before you direct the customer to a shopping cart checkout page where you record the order and empty their cart, you will add some security to this transaction. This prevents anyone with an active shopping cart on your site to find your ordercomplete.php script and check out by accident.

First, you use the md5, uniqid, and rand functions to generate an unpredictable and difficult-to-reproduce unique ID. You assign this value to the $token variable:
// Generate token
$token = md5(uniqid(rand(),1));

Second, you check and see if the $cart_id is already in your shopping_cart_tokens table. If it is, you update the row with the new $token; if it is not, you insert a new row. This check allows your users to use the same shopping cart identifier for multiple purchases:
// Insert token into DB
$token_check = mysql_result(mysql_query("SELECT COUNT(*)
FROM shopping_cart_tokens
WHERE cart_id='$cart_id'"),0);

if($token_check == 0){
mysql_query("INSERT INTO shopping_cart_tokens
(cart_id, token)
VALUES ('$cart_id', '$token')");
} else {
mysql_query("UPDATE shopping_cart_tokens
SET token='$token'
WHERE cart_id='$cart_id'");
}

After you have the $token generated and stored properly, you redirect the customer to the ordercomplete.php script, which you will develop later in this chapter:
// Redirect user to ordercomplete.php
header("Location: /ordercomplete.php?req=success&t=$token");
break;

The default case is for any results other than 0 on the $result[RESULT] values. By using the method shown here, you can eliminate long code by simply showing $result[RESPMSG], which is the response message from the gateway, and giving the customer the PNREF code, which is the transaction ID stored in the PPM:
default:
myheader("Transaction Error");
echo "There has been a problem with your transaction. ".
"You have not been charged for this order.
".
"Please see below:
".
"Results: $result[RESPMSG]
".
"Reference Number: $result[PNREF]
";
break;

The rest of this script is cleanup from the open switches and displays the custom footer function:
}
break;
}
footer();
?>

If you are up to speed now, then congratulations! You are now processing payments with a gateway! This example is as simple as possible to describe the basics of this process. I recommend you put extra-heavy error checking in your billing pages. Furthermore, I recommend you use PHP to validate the information to the payment gateway because web browsers give your users the ability to disable JavaScript; therefore, the information may be processed without any error checking and could result in a declined transaction. When a customer gets a "declined" message from a gateway, and you could have prevented it by error checking, then you have just potentially lost money. So, be smart!

You will break apart from this script now and develop the script to use PayPal. After you are done with the PayPal script, you will pick up where you left off and develop the ordercomplete.php script.
Processing Payments with PayPal

PayPal offers a simple method to accept payments for orders on your website, known as the Buy Now buttons. With some creative thinking, you can utilize the Buy Now buttons and manipulate them to fit your needs.

A common thought about the Buy Now buttons is that you have to generate them from the PayPal website and then copy and paste the code into your website; however, this is not true. You will create a script that will generate the required information and automatically send the customer to the PayPal payment pages.

The methods you will use in this section will help you prevent users from altering their shopping cart total price. You will use the $token system that you utilized earlier to identify the customer when they return to your ordercomplete.php script after a successful transaction at PayPal.

Begin by creating a file named paypal.php in your website document root. This file is also linked to from the payment.php page when a customer clicks the Pay Using PayPal hyperlink. Listing 9.3 shows this script.

Listing 9.3: PayPal Script



<?php

include $_SERVER['DOCUMENT_ROOT'].

'/layout.php';



$cart = &new ShoppingCart;

$cart_id = $cart->get_cart_id();


$total = mysql_result(mysql_query("SELECT

sum(product_qty * product_price) AS subtotal

FROM shopping_carts

WHERE cart_identifier='$cart_id'"),0);

$total = number_format($total, 2);


// Generate token

$token = md5(uniqid(rand(),1));


// Insert token into DB

$token_check = mysql_result(mysql_query("SELECT COUNT(*)

FROM shopping_cart_tokens

WHERE cart_id='$cart_id'"),0);


if($token_check == 0){

mysql_query("INSERT INTO shopping_cart_tokens

(cart_id, token)

VALUES ('$cart_id', '$token')");

} else {

mysql_query("UPDATE shopping_cart_tokens

SET token='$token'

WHERE cart_id='$cart_id'");

}


// Redirect user to PayPal

?>

<html>

<head>

<body onload="document.paypal.submit();">

<form name="paypal" action="https://www.paypal.com/cgi-bin/webscr" method="post">

<input type="hidden" name="cmd" value="_xclick">

<input type="hidden" name="business" value="you@you.com">

<input type="hidden" name="return" value="http://<?=$_SERVER['SERVER_NAME']?>/ordercomplete.php?req=success&type=paypal&t=<?=$token?>">

<input type="hidden" name="item_name" value="MyPHP Site Order">

<input type="hidden" name="item_number" value="<?=$token?>">

<input type="hidden" name="amount" value="<?=$total?>">

<input type="hidden" name="no_shipping" value="1">

<input type="hidden" name="cancel_return" value="http://<?=$_SERVER['SERVER_NAME']?>/ordercomplete.php?req=error">

<input type="hidden" name="quantity" value="1">

<input type="hidden" name=" no_note" value="1">

</form>

</body>

</html>


<hr/>


In this script, your first tasks are to start PHP, include the shopping cart class file, and get the cart identifier of this customer:

<?php

include $_SERVER['DOCUMENT_ROOT'].

'/layout.php';



$cart = &new ShoppingCart;

$cart_id = $cart->get_cart_id();


Next, you determine the total amount of the order and assign it to the $total variable:

$total = mysql_result(mysql_query("SELECT

sum(product_qty * product_price) AS subtotal

FROM shopping_carts

WHERE cart_identifier='$cart_id'"),0);

$total = number_format($total, 2);


Now you generate the $token key like you did for the credit card processing earlier in this chapter. This is where the $token is really going to shine because you need to figure out who this customer is when PayPal sends them back to your site. Utilizing the $token in this matter will help you:

// Generate token

$token = md5(uniqid(rand(),1));


// Insert token into DB

$token_check = mysql_result(mysql_query("SELECT COUNT(*)

FROM shopping_cart_tokens

WHERE cart_id='$cart_id'"),0);


if($token_check == 0){

mysql_query("INSERT INTO shopping_cart_tokens

(cart_id, token)

VALUES ('$cart_id', '$token')");

} else {

mysql_query("UPDATE shopping_cart_tokens

SET token='$token'

WHERE cart_id='$cart_id'");

}

// Redirect user to PayPal

?>


The next portion of the script builds the HTML form with hidden input values and automatically submits it to PayPal by using a JavaScript onload function in the BODY tag of the HTML. Table 9.4 explains the fields and values you are posting to PayPal for the payment processing.































































Table 9.4: PayPal Data Fields

Field



Value


Purpose


Form Action


https://www.paypal.com/cgi-bin/webscr


URL of the PayPal payment processor.


cmd


_xclick


The type of transaction for the PayPal server. Do not
change this value!


business


You@you.com


This is your PayPal ID or e-mail address used to
create your PayPal account.


return


http://<?=$_SERVER['SERVER_NAME']?>/ordercomplete.php?req= success&type=paypal&t=<?=$token?>


The URL to return the customer to after a successful
transaction. Notice the usage of $token.


item_name


MyPHP Site Order


Name of the item, in your case the order. Can be
anything you want.


item_number


$token


This identifies a stock number of an item. For your
purposes, you use $token.


amount


$total


The total amount of the order.


no_shipping


1


Do not display shipping pages. For these purposes, I
do not cover shipping, so you can alter or remove this if you
want.


cancel_return


http://<?=$_SERVER['SERVER_NAME']?>/ordercomplete.php?req=error



This is the error page the customer will be returned
to if the transaction was not successful. Do not put the $token here!


quantity


1


The quantity of the item to purchase. In your case,
you use 1 and define it here. If you alter this,
the total amount will be multiplied by this value. Do not alter
this!


no_note



1


Displays the note box to the customer. Use 0 for yes and 1 for
no.



Based on the fields in Table 9.4, build an HTML page that will automatically submit the form contained inside it when the page loads into the web browser:

<html>

<head>

<body onload="document.paypal.submit();">

<form name="paypal" action="https://www.paypal.com/cgi-bin/webscr" method="post">

<input type="hidden" name="cmd" value="_xclick">

<input type="hidden" name="business" value="you@you.com">

<input type="hidden" name="return" value="http://<?=$_SERVER['SERVER_NAME']?>/ordercomplete.php?req=success&type=paypal&t=<?=$token?>">

<input type="hidden" name="item_name" value="MyPHP Site Order">

<input type="hidden" name="item_number" value="<?=$token?>">

<input type="hidden" name="amount" value="<?=$total?>">

<input type="hidden" name="no_shipping" value="1">

<input type="hidden" name="cancel_return" value="http://<?=$_SERVER['SERVER_NAME']?>/ordercomplete.php?req=error">

<input type="hidden" name="quantity" value="1">

<input type="hidden" name="no_note" value="1">

</form>

</body>

</html>

Once this page loads into the web browser after the user clicks the Pay with PayPal link on the payment.php page, the user will be redirected almost immediately to PayPal, and all of the required information will be passed to the PayPal system to process the transaction with the user input for their billing information. Pretty easy, no?

You can utilize more options in the Buy Now section of the PayPal website once you log in. See the PayPal Buy Now Buttons Manual at https://www.paypal.com/html/single_item.pdf.

Also, PayPal is developing a new system called Instant Payment Notification (IPN), which will send special responses back to your script regarding the transactions. You can find more information about IPN at https://www.paypal.com/html/ipn.pdf.
Note

When testing the PayPal scripts, you need to use a different PayPal account as either the store account or the customer account. In other words, PayPal will not allow you to pay yourself for a transaction.

Now that you have your payment methods complete, it is time to build the script to accept the responses from these different payment options and record the orders.

Completing the Order: ordercomplete.php



This chapter has been building up to the ordercomplete.php script for some time. The previous scripts, creditcard.php and paypal.php, are sending triggers to this script that allow you to perform the final steps in the customer order if it was successful after the payment processing.

Create a script named ordercomplete.php in your website document root (see Listing 9.4).

Listing 9.4: ordercomplete.php Script

<?php

include $_SERVER['DOCUMENT_ROOT'].
'/layout.php';
$cart = &new ShoppingCart;
$cart_id = $cart->get_cart_id();

switch($_REQUEST['req']){
case "success":

$sql = mysql_query("SELECT * FROM shopping_cart_tokens
WHERE token='{$_REQUEST['t']}'");
// Quick $token check
if(mysql_num_rows($sql) != 1){
echo "<center>Error! Please contact webmaster!</center>";
footer();
exit();
}
list($cart_id, $token) = mysql_fetch_row($sql);
// if customer came from paypal,
// log them back in.
if($_REQUEST['type'] == "paypal"){
$_SESSION['cid'] = $cart_id;
mysql_query("SELECT * FROM members
members WHERE cart_id='$cart_id'");
while($row = mysql_fetch_array($sql)){
$_SESSION['login'] = true;
$_SESSION['userid'] = $row['id'];
$_SESSION['first_name'] = $row['first_name'];
$_SESSION['last_name'] = $row['last_name'];
$_SESSION['email_address'] = $row['email_address'];
if($row['admin_access'] == 1){
$_SESSION['admin'] = true;
}
}
} else {
$type = "credit";
}
// Get shopping car total again.
$total = mysql_result(mysql_query("SELECT
sum(product_qty * product_price) AS subtotal
FROM shopping_carts
WHERE cart_identifier='$cart_id'"),0);
$total = number_format($total, 2);
$sql_get_cart = mysql_query("SELECT * FROM
shopping_carts
WHERE cart_identifier='$cart_id'");
while($row = mysql_fetch_array($sql_get_cart)){
mysql_query("UPDATE shopping_products
SET product_qty = (product_qty - {$row['product_qty']})
WHERE product_id ='{$row['product_id']}'");
$storage_array[$row['product_id']]['qty'] =
$row['product_qty'];
$storage_array[$row['product_id']]['price'] =
$row['product_price'];
$storage_array[$row['product_id']]['name'] =
$row['product_title'];
}
$sproducts = serialize($storage_array);
// record the order into the shopping cart
mysql_query("INSERT INTO shopping_cart_orders
(order_date, token, products, total, type, user_id)
VALUES (now(), '$token', '$sproducts', '$total',
'$type', '{$_SESSION['userid']}')");
// Empty the shopping cart
$cart->empty_cart();
// E-mail users and Store Owner a receipt
// Display message
myheader("Payment Success");
echo "<center>Thank you for your payment!<br /><br />".
"Please check your email for your receipt.</center>";
break;
case "error":

// This case used for PayPal only.
myheader("Payment Error");
echo "<center>We're sorry, there have been problems ".
"with your payment</center>";
break;
default:
myheader("Access Denied");
echo "<center>You can't access ".
"this page directly!</center>";
break;

}

footer();

?>

In this code, you start PHP, include your layout and shopping cart class files, and then grab the $cart_id:

<?php
include $_SERVER['DOCUMENT_ROOT'].
'/layout.php';
$cart = &new ShoppingCart;
$cart_id = $cart->get_cart_id();

Next, you define your switch and build the case used when you have a successful payment:
switch($_REQUEST['req']){
case "success":

No comments yet