Using PayPal’s WebSite Payments Pro with “Effortless E-Commerce with PHP and MySQL”

March 7, 2012

In Part 3 of my “[intlink id=”1578″ type=”page”]Effortless E-Commerce with PHP and MySQL[/intlink]” book, I use Authorize.net to process payments for a site that sells physical goods. Authorize.net accepts credit cards and can be directly integrated into your site, so that the customer never leaves (unlike, for example, PayPal’s Website Payments Standard, used in Part 2 of the book, which goes through PayPal’s site). The code in the book was written in a very modular style, with the intent that you can use the components you need, and swap others in and out. A reader specifically wanted to know how you would use PayPal’s Website Payments Pro instead of Authorize.net, and that’s what I’ll explain here.

PayPal’s Website Payments Pro provides two APIs for processing payments: Direct Payment and Express Checkout. Both allow you to accept debit and credit cards (the specific cards will differ slightly from one region to the next), while Express Checkout also allows users to pay with their PayPal account. In both cases, the customer never leaves your site, unlike when using PayPal’s Website Payments Standard. PayPal does require you to use both APIs in order to use Website Payments Pro. To keep this post from getting too long, I’ll only address the Direct Payment, which most easily correlates to the Authorize.net code in the book. If you need help with the Express Checkout aspect, let me know.

To understand how to use Website Payments Pro instead of Authorize.net for the second example, let’s first look at how Authorize.net is used. The customer begins the checkout process on checkout.php. This script takes and validates the user’s shipping information. Upon successful validation, the user is redirected to billing.php, which takes and validates the billing information, including the credit card. Upon successful validation, the payment is processed by including two scripts: gateway_setup.php and gateway_process.php. For extra security, these two files are stored in a private folder outside of the Web root directory.

Within gateway_setup.php, a bunch of parameters are set within an array named $data:

<?php
$data = array();
$data['x_type'] = 'AUTH_ONLY';
$data['x_card_num'] = $cc_number;
$data['x_exp_date'] = $cc_exp;
// etc. 

Then the gateway_process.php script adds some more details to the array:

// Your account info:
$data['x_login'] = '75sqQ96qHEP8';
$data['x_tran_key'] = '7r83Sb4HUd58Tz5p';
// etc. 

Finally, gateway_process.php converts that data into a useable format for the cURL request, performs the cURL request, and reads the response into the $response variable. Finally, this variable is converted into an array:

$response_array = explode($data["x_delim_char"],$response);

That’s the end of the gateway_process.php script. The script that invokes it—billing.php—will then use $response_array to take the next logical steps.

In order to switch the payment gateway in use, you must replace the code in gateway_setup.php and gateway_process.php. This is much easier than you might think. For PayPal’s Website Payments Pro, you’ll need to change the code in those two files so that instead of creating, for example, $data[‘x_card_num’], it creates $data[‘ACCT’]. The proper values and their meanings can be found in the PayPal documentation.  This means that gateway_setup.php would contain:

<?php
$data['PAYMENTACTION'] = 'Authorization';

// Billing info:
$data['ACCT'] = $cc_number;
$data['EXPDATE'] = $cc_exp;
$data['CREDITCARDTYPE'] = $cc_type;
$data['CVV2'] = $cc_cvv;
$data['FIRSTNAME'] = $cc_first_name;
$data['LASTNAME'] = $cc_last_name;
$data['STREET'] = $cc_address;
$data['STATE'] = $cc_state;
$data['CITY'] = $cc_city;
$data['ZIP'] = $cc_zip;
$data['COUNTRY'] = 'US'; // Or other, if accepting international orders.
$data['IPADDRESS'] = $_SERVER['REMOTE_ADDR'];

As in the book, these orders are being authorized first and captured later. The actual transfer of funds takes place in a second step, when the order ships. For simplicity sake, you could change the PAYMENTACTION to Sale, assuming that would be appropriate (and legal) in your situation. PayPal also wants you to pass along the customer’s IP address, for fraud prevention purposes. And you’ll need to get the credit card type from the user, which isn’t requested in the book’s original code.

Next, gateway_process.php needs your own information:

// Your account info:
$data['SIGNATURE'] = 'your API signature';
$data['USER'] = 'your API username';
$data['PWD'] = 'your API password';

This information will be determined when you sign up for Website Payments Pro with your PayPal business account.
Next, there’s the payment gateway stuff:

// PayPal Website Payments Pro Stuff:
$data['VERSION'] = '85.0';

// Transaction stuff:
$data['METHOD'] = 'DoDirectPayment';

And then there’s the order information:

// Order info:
$data['AMT'] = $order_total;
$data['CURRENCYCODE'] = 'USD';
$data['INVNUM'] = $order_id;
$data['CUSTOM'] = $customer_id;

The CUSTOM option lets you send your own data along, in this case the customer ID (although the customer ID could also be retrieved later via the transaction ID).

(Note: Dividing the data into these two files may seem odd, but it’s done so that the administrative side can easily use the same gateway_process.php script, after running a gateway_setup_admin.php script. If you need help with the admin process, to capture a prior authorization, let me know.)

Also, the GATEWAY_API_URL constant in gateway_process.php needs to be changed to PayPal’s proper URL: https://api-3t.sandbox.paypal.com/nvp for testing, https://api-3t.paypal.com/nvp for live purposes.

After identifying all the values, the gateway_process.php script converts that data into a string of URL-encoded name-value pairs. That does not need to be changed, nor does the cURL request made at the end of that script.

In response to the request, PayPal will return a string which contains more name-value pairs: TIMESTAMP=X&ACK=Success&VERSION=85&… This must be broken into an array:

$a = explode('&', $response);
$response_array = array();
foreach ($a as $item) {
 list($key, $value) = explode('=', $item);
 $response_array[$key] = $value;
}

This code is a bit different and more complex than the Authorize.net code, as Authorize.net only returns a string broken up by the pipe character (|). But at this point, <strong>$response_array</strong> is usable. Unfortunately, <strong>billing.php</strong> will need to be modified, because that script assumes a numerically indexed array. First, you’ll need to change the call to the stored procedure:

$r = mysqli_query($dbc, "CALL add_transaction($order_id, '{$data['PAYMENTACTION']}', $response_array['AMT'], $response_array['ACK'], '$response_array['PAYMENTADVICECODE']', $response_array['TRANSACTIONID'], '$response')");

After that code, different reactions occur based upon the success of the transaction. To check that, use $response_array[‘ACK’], which should have a value of Success. Other values include SuccessWithWarning, Failure, and FailureWithWarning. The response array will store the actual reasons in order elements in those situations. The unique transaction ID will be stored in $response_array[‘TRANSACTIONID’]. This would be needed for the capture phase, if using that route. Again, if you need help with updating the admin pieces, let me know.

So that’s the gist of how you would use PayPal’s Website Payments Pro instead of Authorize.net for direct payment with the second e-commerce example in the book. As already mentioned, PayPal does insist that you create an Express Checkout process, too. It’s actually slightly simpler than this code because the user’s billing and shipping information is already stored in PayPal. To integrate this option, you’d add PayPal’s Express Checkout button to your cart.php page, and that would take the user to a different page on your site, where he or she enters his or her PayPal email address and password. This is then sent to PayPal for authorization, along with the order particulars. For more, see PayPal’s documentation.