Introduction

PHP has become an extremely popular scripting language for developing web-based applications.  Developers are able to keep it as simple as possible and use “spaghetti code” within their HTML pages, or they can choose to build applications using a number of PHP frameworks available for free today.

One such framework that I’ve found myself using quite a bit lately, mostly because my clients are already using it, is CodeIgniter.  I’ve found that I like it a lot, so I decided to convert my existing PHP class library for PayPal to a custom library for the CodeIgniter framework.

In this article, we’ll spend just a little bit of time discussing CodeIgniter itself, and why developers like myself have grown to like it. Then I will dive into CodeIgniter PayPal integration using our CodeIgniter PayPal library.

You’ll need to download the library to get started. If you’re already familiar with CodeIgniter you may want to skip ahead to the information on the custom PayPal library.

CodeIgniter Overview

At first glance, a PHP developer may feel like CodeIgniter makes things difficult.  This is because it follows the MVC (model/view/controller) standard, and if you’re not familiar with it, it can seem very confusing.  Once you begin using it, though, you’ll quickly understand the benefits and you’ll probably never turn back whether you’re using CodeIgniter or one of many other MVC frameworks for PHP.

I’ll leave it to the vast array of MVC articles readily available online today to explain the details.  I’d highly recommend you take some time to get a good understanding of the way MVC structure works before taking on a project in full.  That said, the CodeIgniter documentation itself is terrific and it was one of the first pieces of information that I, myself, used to learn about MVC, and how CodeIgniter works, of course.

So you might be wondering, why CodeIgniter? First, it’s free. This is typical of PHP frameworks, but always worth mentioning.  Also, CodeIgniter is very light-weight when compared to other frameworks you might come across.  It only requires a few small libraries of code and does not use nearly the amount of server resources that some of these other frameworks chew up.  As I already mentioned, it follows the MVC standard, and this leads into my final thought about its benefits:  it’s extremely easy to extend with your own customized libraries, which is exactly what I did with my PayPal library.

PayPal Custom Library for CodeIgniter

I’m going to assume at this point you’re either already developing with CodeIgniter and were bored with my introduction, or you’ve read enough to understand how MVC structures work and how CodeIgniter specifically utilizes it.  As such, I’ll simply explain each piece of the library, where it resides in the directory structure of CodeIgniter, and then we’ll walk through some complete samples to see exactly how it all comes together.

Configuration File

CodeIgniter stores all configuration files in the /application/config directory.    There are various configuration files located within this directory that allow you to set things like the site’s base URL, database credentials, and a whole lot more.

The PayPal library includes its own configuration file: /application/config/paypal.php.  Here is an empty sample of the configuration file for your review.

$config['Sandbox'] = TRUE;
$config['APIVersion'] = '78.0';
$config['APIUsername'] = $config['Sandbox'] ? 'SANDBOX_USERNAME_GOES_HERE' : 'PRODUCTION_USERNAME_GOES_HERE';
$config['APIPassword'] = $config['Sandbox'] ? 'SANDBOX_PASSWORD_GOES_HERE' : 'PRODUCTION_PASSWORD_GOES_HERE';
$config['APISignature'] = $config['Sandbox'] ? 'SANDBOX_SIGNATURE_GOES_HERE' : 'PRODUCTION_SIGNATURE_GOES_HERE';
$config['DeviceID'] = $config['Sandbox'] ? 'SANDBOX_DEVICE_ID_GOES_HERE' : 'PRODUCTION_DEVICE_ID_GOES_HERE';
$config['ApplicationID'] = $config['Sandbox'] ? 'APP-80W284485P519543T' : 'PRODUCTION_APP_ID_GOES_HERE';
$config['DeveloperEmailAccount'] = $config['Sandbox'] ? 'SANDBOX_DEV_EMAIL_GOES_HERE' : 'PRODUCTION_DEV_EMAIL_GOES_HERE';

Here, you can easily adjust whether or not your application is using the PayPal sandbox or production servers (testing or live mode) and there are placeholders for you to store credentials for both with shorthand PHP if/else statements.

Once this configuration file has been filled in you can simply switch the Sandbox value from TRUE to FALSE and visa-versa to easily switch back and forth between testing and live servers.

As an extra tip, if your test servers run on a subdomain like sandbox.yourdomain.com, you could use this PHP snippet to automatically adjust the value of Sandbox based on the server that it’s running from and you won’t even have to adjust it manually.

$host_split = explode('.',$_SERVER['HTTP_HOST']);
$config['Sandbox'] = $host_split[0] == 'sandbox' ? TRUE : FALSE;

This will check the URL currently in use and if it begins with the sandbox subdomain it will automatically use the sandbox credentials for PayPal.  Otherwise, it will use the live PayPal credentials.

Library Files

CodeIgniter stores all of its PHP libraries within the /application/libraries directory.  This is where you will find the raw class library files.  These are converted to CodeIgniter from my original PHP class library that I’ve written about previously.

There are three separate library files to handle Adaptive Payments, PayPal Pro and Classic APIs, and the PayFlow gateway.

/application/libraries/paypal/Paypal_adaptive.php
/application/libraries/paypal/Paypal_payflow.php
/application/libraries/paypal/Paypal_pro.php

If you’re interested in studying just exactly how the API calls are being generated and the communication with PayPal is occurring feel free to geek out on these files.  If you just want to get PayPal integrated, though, you don’t have to worry about these, and I would recommend you do not touch them unless replacing them with an updated version of the library.

If you would like to customize these libraries, you can easily do so by extending the existing classes with your own and overriding existing functions, adding your own, or whatever you’d like to do.  This way, future updates will not overwrite your work.

Views

Views are the V in MVC, and are where all of the design aspects of the project reside.  This is mainly HTML, CSS, and JavaScript files that make up the “look and feel” of your website or application.

Views are stored within the /application/views directory in CodeIgniter, and they are generally loaded by controller files that pass data to them for display.

This PayPal library includes basic view files to display information returned by the controllers.  We’ll look at a sample of this as we get into controllers next, and then look at an example of all this working together.

Controllers

Controllers represent the C in MVC and are an important piece of the puzzle.  The controller is basically a collection of functions, or methods, that control what the application is doing any given time.  Controllers are stored within the /application/controllers directory.

One important feature of many MVC solutions, and definitely CodeIgniter, is that the controller and the methods within it are essentially what make up the URLs within a CodeIgniter project.  An example of this can be seen in the following sample URL:

http://sandbox.domain.com/controller_name/method_name.

Now let’s apply that to the PayPal library we’re working with.  It actually includes an additional subdirectory for /paypal/templates/ and three separate controller files to handle various PayPal APIs.

/application/controllers/paypal/Adaptive_payments.php
/application/controllers/paypal/Payflow.php
/application/controllers/paypal/Payments_pro.php

These controllers are provided with the library simply to be used as templates to get started quickly and easily with making calls to PayPal.  You could simply strip methods from them and include them in your own controller(s) if you want to, or you can build right into the controllers included since they’re already setup for you.

If you open up any of the controller files you’ll see that there are methods that correspond to every call available in the PayPal API.  Included within these methods are arrays that make every request parameter available within PayPal’s system available to the application with an empty value.  All you have to do is populate these values with your own data.  Commented notes are provided for each parameter to give you an idea of what type of data is necessary and you can simply leave anything that you don’t need blank.

The controllers are many lines long, so I did not want to include the entire thing within the article directly.  Of course, it’s available in the download, so feel free to open them up and take a closer look.

For now, though, we’ll simply pull out one API call and walk through it entirely.

Let’s take a look at the sample included with the library at /application/controllers/paypal/samples/Payments_pro.php.  Open that and find the Do_direct_payment() function, which should look something like this.

function Do_direct_payment()
{
	$DPFields = array(
		'paymentaction' => 'Sale', // How you want to obtain payment. Authorization indidicates the payment is a basic auth subject to settlement with Auth & Capture. Sale indicates that this is a final sale for which you are requesting payment. Default is Sale.
		'ipaddress' => $_SERVER['REMOTE_ADDR'], // Required. IP address of the payer's browser.
		'returnfmfdetails' => '1' // Flag to determine whether you want the results returned by FMF. 1 or 0. Default is 0.
	);

	$CCDetails = array(
		'creditcardtype' => 'MasterCard', // Required. Type of credit card. Visa, MasterCard, Discover, Amex, Maestro, Solo. If Maestro or Solo, the currency code must be GBP. In addition, either start date or issue number must be specified.
		'acct' => '5424180818927383', // Required. Credit card number. No spaces or punctuation.
		'expdate' => '102012', // Required. Credit card expiration date. Format is MMYYYY
		'cvv2' => '123', // Requirements determined by your PayPal account settings. Security digits for credit card.
		'startdate' => '', // Month and year that Maestro or Solo card was issued. MMYYYY
		'issuenumber' => ''	// Issue number of Maestro or Solo card. Two numeric digits max.
	);

	$PayerInfo = array(
		'email' => 'test@domain.com', // Email address of payer.
		'payerid' => '', // Unique PayPal customer ID for payer.
		'payerstatus' => '', // Status of payer. Values are verified or unverified
		'business' => 'Testers, LLC' // Payer's business name.
	);

	$PayerName = array(
		'salutation' => 'Mr.', // Payer's salutation. 20 char max.
		'firstname' => 'Tester', // Payer's first name. 25 char max.
		'middlename' => '', // Payer's middle name. 25 char max.
		'lastname' => 'Testerson', // Payer's last name. 25 char max.
		'suffix' => ''	// Payer's suffix. 12 char max.
	);

	$BillingAddress = array(
		'street' => '123 Test Ave.', // Required. First street address.
		'street2' => '', // Second street address.
		'city' => 'Kansas City', // Required. Name of City.
		'state' => 'MO', // Required. Name of State or Province.
		'countrycode' => 'US', // Required. Country code.
		'zip' => '64111', // Required. Postal code of payer.
		'phonenum' => '555-555-5555' // Phone Number of payer. 20 char max.
	);

	$ShippingAddress = array(
		'shiptoname' => 'Tester Testerson', // Required if shipping is included. Person's name associated with this address. 32 char max.
		'shiptostreet' => '123 Test Ave.', // Required if shipping is included. First street address. 100 char max.
		'shiptostreet2' => '', // Second street address. 100 char max.
		'shiptocity' => 'Kansas City', // Required if shipping is included. Name of city. 40 char max.
		'shiptostate' => 'MO', // Required if shipping is included. Name of state or province. 40 char max.
		'shiptozip' => '64111', // Required if shipping is included. Postal code of shipping address. 20 char max.
		'shiptocountry' => 'US', // Required if shipping is included. Country code of shipping address. 2 char max.
		'shiptophonenum' => '555-555-5555'	// Phone number for shipping address. 20 char max.
	);

	$PaymentDetails = array(
		'amt' => '100.00', // Required. Total amount of order, including shipping, handling, and tax.
		'currencycode' => 'USD', // Required. Three-letter currency code. Default is USD.
		'itemamt' => '95.00', // Required if you include itemized cart details. (L_AMTn, etc.) Subtotal of items not including S & H, or tax.
		'shippingamt' => '5.00', // Total shipping costs for the order. If you specify shippingamt, you must also specify itemamt.
		'shipdiscamt' => '', // Shipping discount for the order, specified as a negative number.
		'handlingamt' => '', // Total handling costs for the order. If you specify handlingamt, you must also specify itemamt.
		'taxamt' => '', // Required if you specify itemized cart tax details. Sum of tax for all items on the order. Total sales tax.
		'desc' => 'Web Order', // Description of the order the customer is purchasing. 127 char max.
		'custom' => '', // Free-form field for your own use. 256 char max.
		'invnum' => '', // Your own invoice or tracking number
		'notifyurl' => ''	// URL for receiving Instant Payment Notifications. This overrides what your profile is set to use.
	);

	$OrderItems = array();
	$Item	= array(
		'l_name' => 'Test Widget 123', // Item Name. 127 char max.
		'l_desc' => 'The best test widget on the planet!', // Item description. 127 char max.
		'l_amt' => '95.00', // Cost of individual item.
		'l_number' => '123', // Item Number. 127 char max.
		'l_qty' => '1', // Item quantity. Must be any positive integer.
		'l_taxamt' => '', // Item's sales tax amount.
		'l_ebayitemnumber' => '', // eBay auction number of item.
		'l_ebayitemauctiontxnid' => '', // eBay transaction ID of purchased item.
		'l_ebayitemorderid' => '' // eBay order ID for the item.
	);
	array_push($OrderItems, $Item);

	$Secure3D = array(
		'authstatus3d' => '',
		'mpivendor3ds' => '',
		'cavv' => '',
		'eci3ds' => '',
		'xid' => ''
	);

	$PayPalRequestData = array(
		'DPFields' => $DPFields,
		'CCDetails' => $CCDetails,
		'PayerInfo' => $PayerInfo,
		'PayerName' => $PayerName,
		'BillingAddress' => $BillingAddress,
		'ShippingAddress' => $ShippingAddress,
		'PaymentDetails' => $PaymentDetails,
		'OrderItems' => $OrderItems,
		'Secure3D' => $Secure3D
	);

	$PayPalResult = $this->paypal_pro->DoDirectPayment($PayPalRequestData);

	if(!$this->paypal_pro->APICallSuccessful($PayPalResult['ACK']))
	{
		$errors = array('Errors'=>$PayPalResult['ERRORS']);
		$this->view('paypal/samples/error',$errors);
	}
	else
	{
		// Successful call. Load view or whatever you need to do here.
		$data = array('PayPalResult'=>$PayPalResult);
		$this->view('do_direct_payment',$data);
	}
}

As you can see, we’ve simply filled out all of the information with static, test data for demonstration purposes.  You can just as easily populate these parameters with session data, form post data, general PHP variables, etc.

Once all of the data arrays are populated, the following line of code passes it all into the library and processes it with PayPal accordingly.

$PayPalResult = $this->paypal_pro->DoDirectPayment($PayPalRequestData);

Every response parameter that PayPal returns is now available in the PayPalResult array.  The result of the API call is processed, and the correct view is loaded based on the result with the following code.

if(!$this->paypal_pro->APICallSuccessful($PayPalResult[‘ACK’])){
	$errors = array(‘Errors’=>$PayPalResult[‘ERRORS’]);
	$this->view(‘paypal/samples/error’,$errors);
}
else {
	// Successful call. Load view or whatever you need to do here.
	$data = array(‘PayPalResult’=>$PayPalResult);
	$this->view(‘do_direct_payment’,$data);
}

If you remember from earlier, I quickly mentioned that views are stored in /application/views within a CodeIgniter project.  The library includes a number of views to display data for demo purposes.  The code snippet above is passing the name of the view as well as the response data into the CodeIgniter’s load->view() method accordingly.

These views are what we end up seeing displayed on screen when we run this code.  You can get a look at all of this in action at my demo for CodeIgniter PayPal integration.

Conclusion

This was a very quick overview of MVC and CodeIgniter in general, and was written under the assumption that you’re already familiar with it and may have just been looking for a PayPal library.

With that in mind, I hope you’ve found what you’re looking for an can see just how easy it is to integrate virtually every existing PayPal API into any PHP CodeIgniter project.

Happy coding!