PayPal Express Checkout with PHP and MySQL
Wall Script
Wall Script
Monday, September 25, 2017

PayPal Express Checkout with PHP and MySQL

Most of the people prefer to shop online which made eCommerce to grow rapidly. But, what makes an excellent eCommerce site for the customers? The answer is - an excellent checkout process. There are several different payment options available in the market today. Out of all, Paypal is the most popular and convenient way to get paid. Making it as easy as possible for your customers to pay is essential for increasing conversions and sales. This is why your checkout page is critical. I have already discussed 2 checkout options in my previous articles BrainTree PayPal using PHP and Payment System which were in most trend till day. Now, a new checkout option has been introduced by Paypal which is Paypal Express Checkout option.

PayPal Express Checkout with PHP and MySQL


Live Demo


Database Design
To build the user order system, you have to create three tables such as Users, Products, and Orders.

PayPal Express Checkout with PHP Design

Users
User table contains all the users registration details.
CREATE TABLE users(
uid int AUTO_INCREMENT PRIMARY KEY,
username varchar(50),
password varchar(300),
name varchar(200),
email varchar(300));

Products
This table contains product details.
CREATE TABLE products(
pid int PRIMARY KEY AUTO_INCREMENT,
product varchar(300),
product_img varchar(300),
price int,
currency varchar(10)
);

Orders
This table contains user order details.
CREATE TABLE orders(
oid int PRIMARY KEY AUTO_INCREMENT,
uid_fk int,
pid_fk int,
payerID varchar(300),
paymentID varchar(300),
token varchar(300),
created int
);

Video Tutorial
PayPal Express Checkout with PHP and MySQL


Getting started with PayPal Express Checkout

Create Sandbox Account
Go to PayPal Developer and create a sandbox account for development.
Getting started with PayPal Express Checkout

Make sure choose account type as bussiness and give some PayPal balanace number.
Getting started with PayPal Express Checkout

Create REST API Application
Now go to PayPal dashboard and scroll down, you will find a REST API apps and click on create app button.
Getting started with PayPal Express Checkout

Give your application name and choose your sandbox account. This only works with PayPal business accounts.
Getting started with PayPal Express Checkout

Application Credentials
Here you will find both Sandbox and Live Client ID and Secret values.
Getting started with PayPal Express Checkout

PHP Development
Project structure.
Getting started with PayPal Express Checkout

config.php
Database and PayPal checkout API configuration file. Here you have to modify PayPal credentials for Sandbox and Live. Function getDB() help you to create a PDO connection with MySQL database.
<?php
//ob_start();
error_reporting(0);
session_start();

/* DATABASE CONFIGURATION */
define('DB_SERVER', 'localhost');
define('DB_USERNAME', 'username');
define('DB_DATABASE', 'database_name');
define('DB_PASSWORD', 'password');
define("BASE_URL", "http://localhost/PHP-PayPal-ExpressCheckout/");
define('PRO_PayPal', 0); // PayPal live change 0 to 1


if(PRO_PayPal){
    define("PayPal_CLIENT_ID", "##Your Production/Live Client ID##");
    define("PayPal_SECRET", "##Your Production/Live Secret ID##");
    define("PayPal_BASE_URL", "https://api.paypal.com/v1/");
}
else{
    define("PayPal_CLIENT_ID", "##Your Sandbox Client ID##");
    define("PayPal_SECRET", "##Your Sandbox Secret ID##");
    define("PayPal_BASE_URL", "https://api.sandbox.paypal.com/v1/");
}

function getDB()
{
    $dbhost=DB_SERVER;
    $dbuser=DB_USERNAME;
    $dbpass=DB_PASSWORD;
    $dbname=DB_DATABASE;
    $dbConnection = new PDO("mysql:host=$dbhost;dbname=$dbname", $dbuser, $dbpass);
    $dbConnection->exec("set names utf8");
    $dbConnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    return $dbConnection;
}
?>


paypalExpress.php
PHP class for all the project operations like user login, getting product details, PayPal backend check etc.
<?php
class paypalExpress
{
    public function userLogin($username,$password)
    {

        $db = getDB();
        $hash_password= hash('sha256', $password);
        $stmt = $db->prepare("SELECT uid FROM users WHERE  username=:username and password=:hash_password");
        $stmt->bindParam("username", $username, PDO::PARAM_STR) ;
        $stmt->bindParam("hash_password", $hash_password, PDO::PARAM_STR) ;
        $stmt->execute();
        $db = null;

        if($stmt->rowCount()==1)
        {
            $data = $stmt->fetch(PDO::FETCH_OBJ);
            $_SESSION['session_uid'] = $data->uid;
            return $data->uid;
        }
        else
        {
            return false;
        }
    }


    // Other functions
}
?>

index.php
Here index is a user login page. Using $paypalExpress->userLogin() function, verifing the user login details.
<?php
require 'config.php';
require 'class/paypalExpress.php';

$errorMsgLogin ='';
if (!empty($_POST['loginSubmit']))
{
    $usernameEmail=$_POST['username'];
    $password=$_POST['password'];
    if(strlen(trim($usernameEmail))>1 && strlen(trim($password))>1 )
    {
        $paypalExpress = new paypalExpress();
        $uid=$paypalExpress->userLogin($usernameEmail,$password);
        if($uid)
        {
            header("Location:home.php"); // Page redirecting to home.php
        }
        else
        {
            $errorMsgLogin="Please check login details.";
        }
    }
}
?>
<form action="" method="post">
    <label>Username</label>
    <input type="text" value="" name="username" class="input" />
    <label>Password</label>
    <input type="password" value="" name="password"  class="input" />
    <div>
    <input type="submit" value=" Log In" name="loginSubmit" />
    </div>
    <div> <?php echo $errorMsgLogin ?></div>
</form>

home.php
Displaying all of the product details. Clicking on order button this will redirect to checkout page for actual payment process.
<?php
require 'config.php';
require 'session.php';
require 'class/paypalExpress.php';
$paypalExpress = new paypalExpress();
$getAllProducts = $paypalExpress->getAllProducts();
?>
//Logout link
<a href="logout.php" class="logout">Logout</a>
<table>
<?php foreach($getAllProducts as $product){ ?>
<tr>
      <td >
      <img src="img/<?php echo $product->product_img; ?>" />
      </td>
      <td>$<?php echo $product->price; ?></td>
       <td >
      <a href="<?php echo BASE_URL.'checkout.php?pid='.$product->pid; ?>" class="wallButton">Order</a></td>
        </tr>
      <?php } ?>
</table>

getProducts
Getting all of the products.
public function getAllProducts()
    {
        $db = getDB();
        $stmt = $db->prepare("SELECT * FROM products");
        $stmt->bindParam("pid", $pid, PDO::PARAM_INT) ;
        $stmt->execute();
        $data = $stmt->fetchAll(PDO::FETCH_OBJ);
        $db=null;
        return $data;
}

checkout.php
Product information displaying here based on the product id. Here paypalButton.php file contains PayPal express API JavaScript client code.
<?php
require 'config.php';
require 'session.php';
require 'class/paypalExpress.php';
if(!empty($_GET['pid']) && $_GET['pid']>0){
    $paypalExpress = new paypalExpress();
    $product = $paypalExpress->getProduct($_GET['pid']);
}
else{
   header("Location:home.php");
}
?>
<table>
<tr>
<td >
<img src="img/<?php echo $product->product_img; ?>" />
</td>
<td >$<?php echo $product->price; ?> </td>
<td width="20%">
<?php require 'paypalButton.php'; ?>
</td>
</tr>
</table>

paypalButton.php
Dynamicly changing the product price details with PHP defined configuration values. You can control this file from config.php, like to swithing between Sandbox and Live. Once payment is successful, this will send payment information to the process.php file for cross checking.
<div id="paypal-button-container"></div>
<script src="https://www.paypalobjects.com/api/checkout.js"></script>
<script>
paypal.Button.render({
<?php if(PRO_PayPal) { ?>
      env: 'production',
<?php } else {?>
       env: 'sandbox',
<?php } ?>

client: {
     sandbox:    '<?php echo PayPal_CLIENT_ID; ?>',
     production: '<?php echo PayPal_CLIENT_ID; ?>'
},

// Show the buyer a 'Pay Now' button in the checkout flow
commit: true,

// payment() is called when the button is clicked
payment: function(data, actions) {

   // Make a call to the REST api to create the payment
   return actions.payment.create({
   payment: {
        transactions: [
       {
        amount: {
        total: '<?php echo $product->price ?>',
       currency: '<?php echo $product->currency ?>'
        }
        } ]
        }
        });
        },

        // onAuthorize() is called when the buyer approves the payment
         onAuthorize: function(data, actions) {
                // Make a call to the REST api to execute the payment
                return actions.payment.execute().then(function() {
                console.log('Payment Complete!');

                window.location = "<?php echo BASE_URL ?>process.php?paymentID="+data.paymentID+"&payerID="+data.payerID+"&token="+data.paymentToken+"&pid=<?php echo $product->pid  ?>";

                });
            }
        }, '#paypal-button-container');
</script>

process.php
Here is the most important process happen to create an user order.
<?php
require 'config.php';
require 'session.php';
require 'class/paypalExpress.php';
if(!empty($_GET['paymentID']) && !empty($_GET['payerID']) && !empty($_GET['token']) && !empty($_GET['pid']) ){
    $paypalExpress = new paypalExpress();
    $paymentID = $_GET['paymentID'];
    $payerID = $_GET['payerID'];
    $token = $_GET['token'];
    $pid = $_GET['pid'];

    $paypalCheck=$paypalExpress->paypalCheck($paymentID, $pid, $payerID, $token);
    if($paypalCheck){
        header('Location:orders.php'); // Success redirect to orders
    }
}
else{
    header('Location:home.php'); // Fail
}
?>

paypalCheck function
This contains a PHP curl functionality and in backend this will communicate with PayPal API for order cofirmation. Here it again cross verifies with package price and currency to avoid any bad payments.
<?php
public function paypalCheck($paymentID, $pid, $payerID, $paymentToken){

    $ch = curl_init();
    $clientId = PayPal_CLIENT_ID;
    $secret = PayPal_SECRET;
    curl_setopt($ch, CURLOPT_URL, PayPal_BASE_URL.'oauth2/token');
    curl_setopt($ch, CURLOPT_HEADER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_USERPWD, $clientId . ":" . $secret);
    curl_setopt($ch, CURLOPT_POSTFIELDS, "grant_type=client_credentials");
    $result = curl_exec($ch);
    $accessToken = null;


    if (empty($result)){
        return false;
    }

    else {
        $json = json_decode($result);
        $accessToken = $json->access_token;
        $curl = curl_init(PayPal_BASE_URL.'payments/payment/' . $paymentID);
        curl_setopt($curl, CURLOPT_POST, false);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($curl, CURLOPT_HEADER, false);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_HTTPHEADER, array(
        'Authorization: Bearer ' . $accessToken,
        'Accept: application/json',
        'Content-Type: application/xml'
        ));
        $response = curl_exec($curl);
        $result = json_decode($response);


        $state = $result->state;
        $total = $result->transactions[0]->amount->total;
        $currency = $result->transactions[0]->amount->currency;
        $subtotal = $result->transactions[0]->amount->details->subtotal;
        $recipient_name = $result->transactions[0]->item_list->shipping_address->recipient_name;
        curl_close($ch);
        curl_close($curl);

        $product = $this->getProduct($pid);

        if($state == 'approved' && $currency == $product->currency && $product->price ==  $subtotal){
            $this->updateOrder($pid, $payerID, $paymentID, $paymentToken);
            return true;
 
        }
        else{
 
            return false;
        }

    }

}
?>

orders.php
Displaying all of the orders based on user session id.
<?php
require 'config.php';
require 'session.php';
require 'class/paypalExpress.php';
$paypalExpress = new paypalExpress();
$orders = $paypalExpress->orders();
?>
<?php if($orders) { ?>
<table>
<?php foreach($orders as $order){  ?>
<tr>
   <td>ORDER - <?php echo $order->oid; ?></td>
   <td><?php echo $order->product; ?></td>
   <td><?php echo $order->price.' '.$order->currency; ?></td>
   <td><?php echo $paypalExpress->timeFormat($order->created); ?></td>
</tr>
<?php } ?>
</table>
<?php }  else { ?>
<div> No Orders</div>
<?php } ?>


logout.php
Clearing user session.
<?php
$_SESSION['session_uid'] = '';
$sesson_uid = '';
session_destroy();
if(empty($_SESSION['session_uid']) &&  empty($sesson_uid)){
    header('Location:index.php');
}
?>


sessions.php
Common session code, you have to include this in all of the pages. If the user session is not found, this will redirect to index/login page.
<?php
$sesson_uid = '';
if(!empty($_SESSION['session_uid'] )){
    $sesson_uid = $_SESSION['session_uid'] ;
}
else{
    header('Location:index.php');
}
?>

Express Checkout gives your buyers a simplified checkout experience that keeps them local to your website or mobile app throughout the payment authorization process and lets them use their PayPal balance, bank account or credit card to pay without sharing or entering any sensitive information on your site. An order is stored immediately after payment is completed and this happens while the customer is actively engaged on your website. When payment is complete, the customer is redirected to your website, but your website is immediately informed by PayPal whether the transaction was successful or not. The Express Checkout flow keeps the buyer on your web page or mobile app throughout the entire checkout flow. All this process makes the buyer details more secured and also the process is fast. Hope you all like to integrate this PayPal Express Checkout process in your website and provide a good feel for the buyers to buy on the website.
web notification

30 comments:

  1. Nice tutorial SIR. Are you asking? Sure will definitely integrate this system.. Wanna also know if it will work in Nigeria?

    ReplyDelete
  2. logout button does not working, redirect to home page instead of index page

    ReplyDelete
  3. Hello Sir,

    I follow above step and create my own page and it's works fine but if i replace our PayPal_CLIENT_ID and PayPal_SECRET to my then it not work.It was redirect successfully bit give "Things don’t appear to be working at the moment.".
    Please advice me.

    ReplyDelete
  4. Thanks for such important information...
    I must say that these kind of works that your are doing is really hard to find.

    ReplyDelete
  5. It was such a nice article i amluv it
    keep on sharing

    ReplyDelete
  6. Very useful and simple to understand...Pls keep sharing the knowledge!

    ReplyDelete
  7. Got error: "Return to Merchant" button. What's the problem?

    ReplyDelete
  8. Hello Sir,

    First thanks for this great tutorial.but sir one query in my case,when i click on paynow button then not insert data in order table but i get successfully this type of link http://localhost/codexworld/process.php?paymentID=PAY-95S14932HU8449514LOFX2VA&payerID=4P2XR6DFTDZVN&token=EC-4HG95871KT966201S&pid=79

    sir please help me why not insert successfully data in order table.

    Thanks again.

    ReplyDelete
  9. Hi nice article..I am having some issues in integration of express checkout in my site. I have an Indian merchant account. When I pay with us PayPal personal account, it becomes successful. But I am unable to pay with Indian PayPal account or credit/debit card. Could you please help? Do I need to change the currency for every country user or anything else?

    ReplyDelete
  10. Showing index.php blank? what's the reason?

    ReplyDelete
  11. Hi. Your code works perfect. Except i want to add new Column to Orders and Products called lets say Credits and fill Credits corresponding to Products. When buyer pay lets say for pid 1 it should add to Orders Credits corresponding to that pid, if he choose pid 2 - same. How can i achieve that? Becouse I am strugelling with that few weeks now and it always fill Column Credits with NULL. Thanks in advence

    ReplyDelete
    Replies
    1. Are you talking about group products? Right now this is a single product checkout

      Delete
    2. No. It is like your original code. Buyer can only choose 1 product and then goes to checkout with that 1 product. My problem is i made 4 products and i made additional Column called Credits in Orders and Products Tables. I fill in Product Table Credits to all Products, so when buyer choose product with pid 1 it goes to checkout with pid=1, after complette payment all rows are filled with Data except that last New one Credits. If he choose product 2 he goes to checkout with pid=2, he should get than Credits for purchase product 2 and so on. I hope i explained what I mean.

      Delete
    3. Hi. I have readed about IF and CASE Statements. Can we some how implement it here? Like buyer purchased product with pid=1 then IF pid=1 then INSERT INTO orders credits=100 , IF pid=2 then credits=200 and so on? Or you have better idea?

      Delete
  12. hey sir can you like help me add like a reservation here that when after paying it will save the reservation date with the payment info in database

    ReplyDelete
  13. Please post article on paypal checkout recurring payments

    ReplyDelete
  14. The script works perfectly, good job!
    However:
    1) The paymentID field of the orders table does not record the real N ° of the Paypal transaction ...
    For example I get an id: PAYID-L3GCUBQ1GV06768289022607
    while the actual transaction number in the Paypal account is: transaction: 37Y72759N0610714S
    It is therefore impossible to search for a specific order in the Paypal account without the real transaction number.
    This is particularly useful in the case of a refund.

    2) The recurring problem with Paypal is that from a mobile phone it is impossible to make a payment by bank card without having a Paypal account.
    To correct this problem, just modify the script in checkout.php:
    style: {
    shape: 'rect',
    color: 'gold', // or 'blue', 'silver', 'black',
    layout: 'vertical',
    label: 'paypal',
    },

    This displays a Paypal button and below the Visa, Mastercard etc. buttons.
    These card buttons refer directly to the Paypal page Payment by card ... !!
    (The browser needs to be properly refreshed after reloading checkout.php)

    ReplyDelete

mailxengine Youtueb channel
Make in India
X