PayPal Payment Gateway Integration in CodeIgniter

Nowadays the payment gateway is hugely used for the e-commerce business and online service providers. It helps to accept payment online in the web application. Before integrating a payment gateway into the website, you need to choose the best payment gateway service provider to accept online payment without any interruption. PayPal is one of the world’s most popular internet payment solution. If you want to accept payment globally on your website, PayPal is the best choice for integrating the payment gateway into your web project.

PayPal provides an easy way to integrate standard payment gateway in PHP. If your web application built with CodeIgniter, PayPal PHP library and API needs to be integrated in the CodeIgniter application. In this tutorial, we will show you how to integrate PayPal payment gateway in CodeIgniter. Here we will provide the step by step guide on PayPal standard payment gateway integration for CodeIgniter application. Our example code will help you to integrate PayPal payment gateway in CodeIgniter.

In this example script, the following functionality will be implemented to integrate PayPal payment gateway in CodeIgniter application.

  • Fetch products from the database and list them on the web page.
  • Each product will have a Pay with PayPal button that allows the user to purchase the product.
  • The Buy button redirects the user to the PayPal site to make the payment.
  • After the payment on PayPal, the buyer will be redirected back to the website.
  • The transaction will be validated using PayPal IPN (Instant Payment Notification) service and the payment information will be stored in the database.
  • The transaction details and payment status will be shown to the buyer.

Create PayPal Sandbox Account

Before making the PayPal payment gateway live, it needs to be tested whether the payment process is working properly. PayPal provides a Sandbox environment to test the transaction process before accept payment from the buyers.
To test the PayPal payment gateway, you need to create PayPal sandbox account.

  • Go to the PayPal Developer Portal and Log into the Dashboard using your PayPal account credentials. If you don’t have any PayPal account, sign up for a PayPal account first.
  • In the dashboard, click the Accounts under the Sandbox label from the left side menu panel.
    paypal-developer-sandbox-account-codeigniter-codexworld
  • Click the Create Account to create buyer and merchant account. Under the Account type section, select Personal for buyer account or Business for a merchant account.
    create-paypal-sandbox-buyer-business-account-codeigniter-codexworld

Before getting started to integrate PayPal payment gateway in CodeIgniter, take a look at the file structure.

codeigniter_paypal_integration/
├── application/
│   ├── config/
│   │   └── paypal.php
│   ├── controllers/
│   │   ├── Products.php
│   │   └── Paypal.php
│   ├── libraries/
│   │   └── Paypal_lib.php
│   ├── models/
│   │   ├── Product.php
│   │   └── Payment.php
│   ├── views/
│   │   ├── products/
│   │   │   └── index.php
│   │   └── paypal/
│   │       ├── success.php
│   │       └── cancel.php
└── assets/
    └── css/
        ├── bootstrap.min.css
        └── style.css

Create Database Tables

To store product and payment information two tables are required in the database.

The following SQL creates a products table with some basic fields in the MySQL database.

CREATE TABLE `products` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
 `image` varchar(200) COLLATE utf8_unicode_ci NOT NULL,
 `price` float(10,2) NOT NULL,
 `currency` varchar(10) COLLATE utf8_unicode_ci NOT NULL DEFAULT 'USD',
 `status` enum('1','0') COLLATE utf8_unicode_ci NOT NULL DEFAULT '1',
 PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

The following SQL creates a payments table in the MySQL database to store the transaction information provided by PayPal.

CREATE TABLE `payments` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `product_id` int(11) NOT NULL,
 `user_id` int(11) DEFAULT NULL,
 `txn_id` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
 `payment_gross` float(10,2) NOT NULL,
 `currency_code` varchar(5) COLLATE utf8_unicode_ci NOT NULL,
 `payer_name` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
 `payer_email` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
 `status` varchar(20) COLLATE utf8_unicode_ci NOT NULL,
 PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

Config

paypal.php
The configuration variables of the PayPal library are defined in this file.

  • Specify the PayPal environment (sandbox), business email (business), and currency code (paypal_lib_currency_code).
<?php  defined('BASEPATH') OR exit('No direct script access allowed'); 

/*
| -------------------------------------------------------------------
|  PayPal API Configuration
| -------------------------------------------------------------------
|
| You will get the API keys from Developers panel of the PayPal account
| Login to PayPal account (https://developer.paypal.com/)
| and navigate to the SANDBOX » Accounts page
| Remember to switch to your live business email in production!
|
|  sandbox                    boolean  PayPal environment, TRUE for Sandbox and FALSE for live
|  business                    string   PayPal business email
|  paypal_lib_currency_code string   Currency code.
*/

$config['sandbox'] = TRUE// FALSE for live environment

$config['business'] = 'Your_PayPal_Email';

$config['paypal_lib_currency_code'] = 'USD';

// Where is the button located at? (optional)
$config['paypal_lib_button_path'] = 'assets/images/';

// If (and where) to log ipn response in a file
$config['paypal_lib_ipn_log'] = FALSE;
$config['paypal_lib_ipn_log_file'] = BASEPATH 'logs/paypal_ipn.log';

Library

PayPal (libraries/Paypal_lib.php)
The Paypal CodeIgniter Library helps to integrate PayPal payment gateway in CodeIgniter 3 application. This library (application/libraries/Paypal_lib.php) has a dependency on a configuration file (application/config/paypal.php).

  • __construct() – Load required helpers, set configure variables and initiate the Paypal_lib class.
  • button() – Set value of the PayPal form submit button.
  • image() – Set image to the PayPal form submit button.
  • add_field() – Add field to PayPal form.
  • paypal_auto_form() – Generate an entire HTML page consisting of a form with hidden elements which is submitted to paypal via the BODY element’s onLoad attribute.
  • paypal_form() – Build PayPal form.
  • validate_ipn() – Validate PayPal IPN request.
<?php defined('BASEPATH') OR exit('No direct script access allowed'); 
/**
 * PayPal Library for CodeIgniter 3.x
 *
 * Library for PayPal payment gateway. It helps to integrate PayPal payment gateway
 * in the CodeIgniter application.
 *
 * It requires PayPal configuration file and it should be placed in the config directory.
 *
 * @package     CodeIgniter
 * @category    Libraries
 * @author      CodexWorld
 * @license     http://www.codexworld.com/license/
 * @link        http://www.codexworld.com
 * @version     2.0
 */

class Paypal_lib
{

    var 
$last_error;            // holds the last error encountered
    
var $ipn_log;                // bool: log IPN results to text file?

    
var $ipn_log_file;            // filename of the IPN log
    
var $ipn_response;            // holds the IPN response from paypal    
    
var $ipn_data = array();    // array contains the POST values for IPN
    
var $fields = array();        // array holds the fields to submit to paypal

    
var $submit_btn '';        // Image/Form button
    
var $button_path '';        // The path of the buttons
    
    
var $CI;
    
    function 
__construct(){
        
$this->CI =& get_instance();
        
$this->CI->load->helper('url');
        
$this->CI->load->helper('form');
        
$this->CI->load->config('paypal');
        
        
$sanbox $this->CI->config->item('sandbox');
        
$this->paypal_url = ($sanbox == TRUE)?'https://www.sandbox.paypal.com/cgi-bin/webscr':'https://www.paypal.com/cgi-bin/webscr';
                
        
$this->last_error '';
        
$this->ipn_response '';

        
$this->ipn_log_file $this->CI->config->item('paypal_lib_ipn_log_file');
        
$this->ipn_log $this->CI->config->item('paypal_lib_ipn_log'); 
        
        
$this->button_path $this->CI->config->item('paypal_lib_button_path');
        
        
// populate $fields array with a few default values.
        // values can be overwritten by the calling script.
        
$businessEmail $this->CI->config->item('business');
        
$this->add_field('business',$businessEmail);
        
$this->add_field('rm','2');    // Return method = POST
        
$this->add_field('cmd','_xclick');

        
$this->add_field('currency_code'$this->CI->config->item('paypal_lib_currency_code'));
        
$this->add_field('quantity''1');
        
$this->button('Pay Now!');
    }

    function 
button($value){
        
// changes the default caption of the submit button
        
$this->submit_btn form_submit('pp_submit'$value);
    }

    function 
image($file){
        
$this->submit_btn '<input type="image" name="add" src="'.base_url(rtrim($this->button_path'/').'/'$file).'" border="0" />';
    }

    function 
add_field($field$value){
        
// adds a key=>value pair to the fields array, which is what will be 
        // sent to paypal as POST variables.  If the value is already in the 
        // array, it will be overwritten.
        
$this->fields[$field] = $value;
    }

    function 
paypal_auto_form(){
        
// this function actually generates an entire HTML page consisting of
        // a form with hidden elements which is submitted to paypal via the 
        // BODY element's onLoad attribute.
        
$this->button('Click here if you\'re not automatically redirected...');

        echo 
'<html>' "\n";
        echo 
'<head><title>Processing Payment...</title></head>' "\n";
        echo 
'<body style="text-align:center;" onLoad="document.forms[\'paypal_auto_form\'].submit();">' "\n";
        echo 
'<p style="text-align:center;">Please wait, your order is being processed and you will be redirected to the PayPal website.</p>' "\n";
        echo 
$this->paypal_form('paypal_auto_form');
        echo 
'</body></html>';
    }

    function 
paypal_form($form_name='paypal_form'){
        
$str '';
        
$str .= '<form method="post" action="'.$this->paypal_url.'" name="'.$form_name.'"/>' "\n";
        foreach (
$this->fields as $name => $value)
            
$str .= form_hidden($name$value) . "\n";
        
$str .= '<p>'$this->submit_btn '</p>';
        
$str .= form_close() . "\n";

        return 
$str;
    }
    
    function 
validate_ipn($paypalReturn){
        
$ipn_response $this->curlPost($this->paypal_url$paypalReturn);
        
        if(
preg_match("/VERIFIED/i"$ipn_response)){
            
// Valid IPN transaction.
            
return true;
        }else{
            
// Invalid IPN transaction.  Check the log for details.
            
$this->last_error 'IPN Validation Failed.';
            
$this->log_ipn_results(false);    
            return 
false;
        }
    }

    function 
log_ipn_results($success){
        if (!
$this->ipn_log) return;  // is logging turned off?

        // Timestamp
        
$text '['.date('m/d/Y g:i A').'] - '

        
// Success or failure being logged?
        
if ($success$text .= "SUCCESS!\n";
        else 
$text .= 'FAIL: '.$this->last_error."\n";

        
// Log the POST variables
        
$text .= "IPN POST Vars from Paypal:\n";
        foreach (
$this->ipn_data as $key=>$value)
            
$text .= "$key=$value, ";

        
// Log the response from the paypal server
        
$text .= "\nIPN Response from Paypal Server:\n ".$this->ipn_response;

        
// Write to log
        
$fp=fopen($this->ipn_log_file,'a');
        
fwrite($fp$text "\n\n"); 

        
fclose($fp);  // close file
    
}

    function 
dump(){
        
// Used for debugging, this function will output all the field/value pairs
        // that are currently defined in the instance of the class using the
        // add_field() function.
        
ksort($this->fields);
        echo 
'<h2>ppal->dump() Output:</h2>' "\n";
        echo 
'<code style="font: 12px Monaco, \'Courier New\', Verdana, Sans-serif;  background: #f9f9f9; border: 1px solid #D0D0D0; color: #002166; display: block; margin: 14px 0; padding: 12px 10px;">' "\n";
        foreach (
$this->fields as $key => $value) echo '<strong>'$key .'</strong>:    'urldecode($value) .'<br/>';
        echo 
"</code>\n";
    }
    
    function 
curlPost($paypal_url$paypal_return_arr){
        
$req 'cmd=_notify-validate';
        foreach(
$paypal_return_arr as $key => $value){
            
$value urlencode(stripslashes($value));
            
$req .= "&$key=$value";
        }
            
        
$ipn_site_url $paypal_url;
        
$ch curl_init();
        
curl_setopt($chCURLOPT_URL$ipn_site_url);
        
curl_setopt($chCURLOPT_HEADERfalse);
        
curl_setopt($chCURLOPT_POST1);
        
curl_setopt($chCURLOPT_RETURNTRANSFERtrue);
        
curl_setopt($chCURLOPT_POSTFIELDS$req);
        
$result curl_exec($ch);
        
curl_close($ch);
    
        return 
$result;
    }

}

Controller

The Products and Paypal controllers will be used to handle the product listing and payment process.

1. Products (controllers/Products.php):
The Products controller handles the product listing and payment request submission process.

  • __construct() – Loads the PayPal library and Product model.
  • index()
    • Retrieve the products data from the database using getRows() function of the Product model.
    • Pass data to the view and load the view file to list the products.
  • buy()
    • Fetch the product data from the database based on the selected product ID.
    • Generate the PayPal form with HTML variables and submit on the fly using add_field() and paypal_auto_form() methods of the PayPal library.
    • Render PayPal form and redirect buyer to the PayPal site for payment.
<?php defined('BASEPATH') OR exit('No direct script access allowed'); 

class 
Products extends CI_Controller{
    
    function  
__construct(){
        
parent::__construct();
        
        
// Load paypal library
        
$this->load->library('paypal_lib');
        
        
// Load product model
        
$this->load->model('product');
    }
    
    function 
index(){
        
$data = array();
        
        
// Get products from the database
        
$data['products'] = $this->product->getRows();
        
        
// Pass product data to the view
        
$this->load->view('products/index'$data);
    }
    
    function 
buy($id){
        
// Set variables for paypal form
        
$returnURL base_url().'paypal/success'//payment success url
        
$cancelURL base_url().'paypal/cancel'//payment cancel url
        
$notifyURL base_url().'paypal/ipn'//ipn url
        
        // Get product data from the database
        
$product $this->product->getRows($id);
        
        
// Get current user ID from the session (optional)
        
$userID = !empty($_SESSION['userID'])?$_SESSION['userID']:1;
        
        
// Add fields to paypal form
        
$this->paypal_lib->add_field('return'$returnURL);
        
$this->paypal_lib->add_field('cancel_return'$cancelURL);
        
$this->paypal_lib->add_field('notify_url'$notifyURL);
        
$this->paypal_lib->add_field('item_name'$product['name']);
        
$this->paypal_lib->add_field('custom'$userID);
        
$this->paypal_lib->add_field('item_number',  $product['id']);
        
$this->paypal_lib->add_field('amount',  $product['price']);
        
        
// Render paypal form
        
$this->paypal_lib->paypal_auto_form();
    }
}

2. Paypal (controllers/Paypal.php):
The Paypal controller handles the transaction and the IPN validation process.

  • __construct() – Loads the PayPal library, Product & Payment model.
  • success()
    • Retrieve the transaction data from the query string of the URL.
    • Check if transaction data exists in the database with the same transaction ID.
    • Pass the payment data to the view and load the view file.
  • cancel() – Load the payment failed notification view.
  • ipn() – This method is called by the PayPal IPN (Instant Payment Notification).
    • Validate the transaction using validate_ipn() method of PayPal library.
    • Insert the payment information in the database using insertTransaction() function of Payment model.
<?php defined('BASEPATH') OR exit('No direct script access allowed'); 

class 
Paypal extends CI_Controller{
    
     function  
__construct(){
        
parent::__construct();
        
        
// Load paypal library
        
$this->load->library('paypal_lib');
        
        
// Load product model
        
$this->load->model('product');
        
        
// Load payment model
        
$this->load->model('payment');
     }
     
    function 
success(){
        
// Get the transaction data
        
$paypalInfo $this->input->get();
        
        
$productData $paymentData = array();
        if(!empty(
$paypalInfo['item_number']) && !empty($paypalInfo['tx']) && !empty($paypalInfo['amt']) && !empty($paypalInfo['cc']) && !empty($paypalInfo['st'])){
            
$item_name $paypalInfo['item_name'];
            
$item_number $paypalInfo['item_number'];
            
$txn_id $paypalInfo["tx"];
            
$payment_amt $paypalInfo["amt"];
            
$currency_code $paypalInfo["cc"];
            
$status $paypalInfo["st"];
            
            
// Get product info from the database
            
$productData $this->product->getRows($item_number);
            
            
// Check if transaction data exists with the same TXN ID
            
$paymentData $this->payment->getPayment(array('txn_id' => $txn_id));
        }
        
        
// Pass the transaction data to view
        
$data['product'] = $productData;
        
$data['payment'] = $paymentData;
        
$this->load->view('paypal/success'$data);
    }
     
     function 
cancel(){
        
// Load payment failed view
        
$this->load->view('paypal/cancel');
     }
     
     function 
ipn(){
        
// Retrieve transaction data from PayPal IPN POST
        
$paypalInfo $this->input->post();
        
        if(!empty(
$paypalInfo)){
            
// Validate and get the ipn response
            
$ipnCheck $this->paypal_lib->validate_ipn($paypalInfo);

            
// Check whether the transaction is valid
            
if($ipnCheck){
                
// Check whether the transaction data is exists
                
$prevPayment $this->payment->getPayment(array('txn_id' => $paypalInfo["txn_id"]));
                if(!
$prevPayment){
                    
// Insert the transaction data in the database
                    
$data['user_id']    = $paypalInfo["custom"];
                    
$data['product_id']    = $paypalInfo["item_number"];
                    
$data['txn_id']    = $paypalInfo["txn_id"];
                    
$data['payment_gross']    = $paypalInfo["mc_gross"];
                    
$data['currency_code']    = $paypalInfo["mc_currency"];
                    
$data['payer_name']    = trim($paypalInfo["first_name"].' '.$paypalInfo["last_name"], ' ');
                    
$data['payer_email']    = $paypalInfo["payer_email"];
                    
$data['status'] = $paypalInfo["payment_status"];
    
                    
$this->payment->insertTransaction($data);
                }
            }
        }
    }
}

Setup PayPal Instant Payment Notification (IPN):
The ipn() function of the Paypal controller verifies each transaction and inserts the payment data into the database. The PayPal IPN must be enabled in PayPal business account to make the IPN working. You need to specify the IPN URL (http://www.example.com/paypal/ipn/) in the Notification URL field where the PayPal will send the IPN messages.

Follow this step-by-step guide to enable IPN in PayPal – How to enable PayPal Instant Payment Notification

Note that: The transaction data will not be inserted in the database without PayPal IPN setup.

Model

The Product and Payment models handle the database related operations (fetch and insert).

1. Product (models/Product.php)

  • __construct() – Defines the database table name.
  • getRows() – Fetch the records from the products table and returns as an array.
    • If a specific ID is mentioned, return data of a single product.
<?php defined('BASEPATH') OR exit('No direct script access allowed'); 

class 
Product extends CI_Model{
    
    function 
__construct() {
        
$this->proTable   'products';
    }
    
    
/*
     * Fetch products data from the database
     * @param id returns a single record if specified, otherwise all records
     */
    
public function getRows($id ''){
        
$this->db->select('*');
        
$this->db->from($this->proTable);
        
$this->db->where('status''1');
        if(
$id){
            
$this->db->where('id'$id);
            
$query $this->db->get();
            
$result $query->row_array();
        }else{
            
$this->db->order_by('name''asc');
            
$query $this->db->get();
            
$result $query->result_array();
        }
        
        
// return fetched data
        
return !empty($result)?$result:false;
    }
    
}

2. Payment (models/Payment.php)

  • __construct() – Defines the database table name.
  • getPayment() – Fetch the record from the payments table and returns as an array.
  • insertTransaction() – Insert transaction data in the payments table.
<?php defined('BASEPATH') OR exit('No direct script access allowed'); 

class 
Payment extends CI_Model{
    
    function 
__construct() {
        
$this->transTable 'payments';
    }
    
    
/*
     * Fetch payment data from the database
     * @param id returns a single record if specified, otherwise all records
     */
    
public function getPayment($conditions = array()){
        
$this->db->select('*');
        
$this->db->from($this->transTable);
        
        if(!empty(
$conditions)){
            foreach(
$conditions as $key=>$val){
                
$this->db->where($key$val);
            }
        }
        
        
$result $this->db->get();
        return (
$result->num_rows() > 0)?$result->row_array():false;
    }
    
    
/*
     * Insert payment data in the database
     * @param data array
     */
    
public function insertTransaction($data){
        
$insert $this->db->insert($this->transTable,$data);
        return 
$insert?true:false;
    }
    
}

View

The products and paypal directories hold the view files of Products and Paypal controllers.

1. views/products/
1.1. index.php
In this view, all the products are displayed on the web page with the Buy button.

<!-- List all products -->
<?php if(!empty($products)){ foreach($products as $row){ ?>
    <div class="card">
        <img src="<?php echo base_url('assets/images/'.$row['image']); ?>" />
        <div class="card-body">
            <h5 class="card-title"><?php echo $row['name']; ?></h5>
            <p class="card-text">Lorem Ipsum is simply dummy text of the printing and typesetting industry.</p>
            <h6>$<?php echo $row['price'].' '.$row['currency']; ?></h6>
            <a href="<?php echo base_url('products/buy/'.$row['id']); ?>" class="btn"><img src="<?php echo base_url('assets/images/paypal-btn.png'); ?>" /></a>
        </div>
    </div>
<?php } }else{ ?>
    <p>Product(s) not found...</p>
<?php ?>

2. views/paypal/
2.1. success.php
In this view, the payment status and transaction details are displayed after the payment on PayPal.

<?php if(!empty($payment)){ ?>
    <h1 class="success">Your Payment has been Successful!</h1>
    <h4>Payment Information</h4>
    <p><b>Reference Number:</b> #<?php echo $payment['id']; ?></p>
    <p><b>Transaction ID:</b> <?php echo $payment['txn_id']; ?></p>
    <p><b>Paid Amount:</b> <?php echo $payment['payment_gross'].' '.$payment['currency_code']; ?></p>
    <p><b>Payment Status:</b> <?php echo $payment['status']; ?></p>
	
    <h4>Payer Information</h4>
    <p><b>Name:</b> <?php echo $payment['payer_name']; ?></p>
    <p><b>Email:</b> <?php echo $payment['payer_email']; ?></p>
	
    <h4>Product Information</h4>
    <p><b>Name:</b> <?php echo $product['name']; ?></p>
    <p><b>Price:</b> <?php echo $product['price'].' '.$product['currency']; ?></p>
<?php }else{ ?>
    <h1 class="error">Transaction has been failed!</h1>
<?php ?>

2.2. cancel.php
If the user cancels the payment, the transaction failed notification is displayed.

<div class="status">
    <h1 class="error">Your transaction was canceled!</h1>
</div>

Test PayPal Transaction

  • Open the Products controller URL (http://example.com/application_folder/products) on the browser.
  • The products will be listed with the Pay with PayPal button.
  • The Pay with PayPal button will redirect you to the PayPal site for the payment.
  • Log into the PayPal with your Sandbox personal account and complete the payment.
  • On payment success, you will be redirected back to the website’s payment success page and the transaction details will be shown.

Make PayPal Payment Gateway Live

When the payment flow testing process is completed with a sandbox account, do the following changes to make the PayPal payment gateway live.
In the application/config/paypal.php file, specify the PayPal environment and business email.

  • Set sandbox to FALSE for live environment.
    $config['sandbox'] = FALSE;
  • Specify your live PayPal business email.
    $config['business'] = 'live_paypal@email.com';

PayPal Express Checkout Integration in PHP

Do you want to get implementation help, or enhance the functionality of this script? Click here to Submit Service Request

122 Comments

  1. Shashi Said...
  2. Sandy Said...
  3. Abubakkar Tahir Khan Said...
1 2 3

Leave a reply

keyboard_double_arrow_up