PayPal Standard Checkout Integration in PHP

PayPal is one of the most popular payment gateway that allows website owners to accept payment online. In the web application, PayPal is the easiest option to integrate payment gateway and enable online payment on the website. There are various payment methods available that the buyer can choose from with PayPal checkout. PayPal checkout is the quickest way to enable an online payment system on the website.

PayPal Standard Checkout uses JavaScript SDK to integrate payment button in the webpage. The buyer can use this button to make payment with their PayPal account or debit/credit card. Integrate PayPal Standard Checkout system to allow buyers to purchase online and make the payment from the website. In this tutorial, we will show you how to integrate PayPal Standard Checkout in PHP. Here we will provide a step-by-step guide for PayPal checkout integration with JavaScript using PHP.

In this example script, we will go through the following operations to integrate PayPal standard checkout system in the web application using PHP.

  • Define the PayPal button in the HTML.
  • Create an order with PayPal JavaScript SDK and attach it to the payment button.
  • When the buyer clicks the button, the JS library launches the PayPal Checkout experience dialog.
  • The buyer approves the payment.
  • The payment is confirmed by PayPal and finalize transaction.
  • The order info is captured and posted to the backend server for verification.
  • The backend server verifies the transaction using PayPal Orders API.
  • Store transaction data in the database with PHP and MySQL.
  • Show a confirmation message to the buyer.

PayPal REST API Credentials

To get started with the PayPal REST API, you need to create a developer account on the PayPal Developer Dashboard.

PayPal provides two environments, Sandbox and Live. Sandbox environment allows developers to test the PayPal checkout process before making it Live for production usage. You can create sandbox Business and Personal accounts from the Sandbox Accounts section.

In the PayPal Developer Dashboard, you can switch between the Sandbox and Live environment from the toggle button placed at the top-right corner.

Create Sandbox Accounts:

  • Sandbox Merchant Account: Create a sandbox business account with Account type: Business. This merchant account is required to attach at the time of the REST API app.
  • Sandbox Buyer Account: Create a sandbox buyer account with Account type: Personal. This buyer account will be used to test payment.
    • After the sandbox buyer account creation, an email ID and password will be generated. You can use these credentials to log in at the time of testing the PayPal checkout.

Create REST API App:
In the Apps & Credentials section, create a new REST API App with Type: Merchant.

  • Select a business account under the Sandbox Account dropdown.

After the App creation, the Client ID and Secret will be generated.

  • Copy these API credentials to later use in the script.

Live REST API Credentials:
At the top right corner, toggle the switch to Live. Then navigate to the Apps & Credentials section.

  • Create a new REST API App, you will get the credentials (Client ID and Secret) for the Live environment.

Before getting started to develop PayPal standard checkout payment script with PHP, take a look at the file structure.

paypal_standard_checkout_in_php/
├── config.php
├── dbConnect.php
├── index.php
├── PaypalCheckout.class.php
├── paypal_checkout_validate.php
├── payment-status.php
└── css/
    └── style.css

Create Database Table

A table is required to store the transaction info in the database. The following SQL creates a transactions table in the MySQL database that holds the transaction data.

CREATE TABLE `transactions` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `item_number` varchar(50) DEFAULT NULL,
  `item_name` varchar(255) DEFAULT NULL,
  `item_price` float(10,2) DEFAULT NULL,
  `item_price_currency` varchar(10) DEFAULT NULL,
  `payer_id` varchar(50) DEFAULT NULL,
  `payer_name` varchar(50) DEFAULT NULL,
  `payer_email` varchar(50) DEFAULT NULL,
  `payer_country` varchar(20) DEFAULT NULL,
  `merchant_id` varchar(255) DEFAULT NULL,
  `merchant_email` varchar(50) DEFAULT NULL,
  `order_id` varchar(50) NOT NULL,
  `transaction_id` varchar(50) NOT NULL,
  `paid_amount` float(10,2) NOT NULL,
  `paid_amount_currency` varchar(10) NOT NULL,
  `payment_source` varchar(50) DEFAULT NULL,
  `payment_status` varchar(25) NOT NULL,
  `created` datetime NOT NULL,
  `modified` datetime NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

PayPal API and Database Configuration (config.php)

In the config.php file, constant variables of the Product, PayPal Checkout API and database settings are defined.

Product Information:

  • $itemNumber – Reference number of the product
  • $itemName – Name of the product.
  • $itemPrice – Product price.
  • $currency – Currency code.

PayPal REST API Constants:

  • PAYPAL_SANDBOX – (TRUE/FALSE) Set PayPal environment, Sandbox or Live.
  • PAYPAL_SANDBOX_CLIENT_ID – Client ID of PayPal Sandbox REST API App.
  • PAYPAL_SANDBOX_CLIENT_SECRET – Secret key of PayPal Sandbox REST API App.
  • PAYPAL_PROD_CLIENT_ID – Client ID of PayPal Live REST API App.
  • PAYPAL_PROD_CLIENT_SECRET – Secret key of PayPal Live REST API App.

Database Constants:

  • DB_HOST – Specify the database host.
  • DB_USERNAME – Specify the database username.
  • DB_PASSWORD – Specify the database password.
  • DB_NAME – Specify the database name.
<?php 

// Product Details
$itemNumber "DP12345";
$itemName "Demo Product";
$itemPrice 75
$currency "USD";

/* PayPal REST API configuration
 * You can generate API credentials from the PayPal developer panel.
 * See your keys here: https://developer.paypal.com/dashboard/
 */
define('PAYPAL_SANDBOX'TRUE); //TRUE=Sandbox | FALSE=Production
define('PAYPAL_SANDBOX_CLIENT_ID''Insert_PayPal_Client_ID_For_Sandbox_Here');
define('PAYPAL_SANDBOX_CLIENT_SECRET''Insert_PayPal_Secret_Key_For_Sandbox_Here');
define('PAYPAL_PROD_CLIENT_ID''Insert_Live_PayPal_Client_ID_Here');
define('PAYPAL_PROD_CLIENT_SECRET''Insert_Live_PayPal_Secret_Key_Here');
 
// Database configuration 
define('DB_HOST''localhost'); 
define('DB_USERNAME''root'); 
define('DB_PASSWORD''root'); 
define('DB_NAME''codexworld_db');

?>

Note that: PayPal API Client ID and Secret will be found in the REST API App section of your PayPal Developer Dashboard.

Database Connection (dbConnect.php)

The dbConnect.php file is used to connect the database using PHP and MySQL.

<?php  

// Connect with the database 
$db = new mysqli(DB_HOSTDB_USERNAMEDB_PASSWORDDB_NAME); 
 
// Display error if failed to connect 
if ($db->connect_errno) { 
    
printf("Connect failed: %s\n"$db->connect_error); 
    exit(); 
}

?>

PayPal Checkout Page (index.php)

Add JavaScript SDK and PayPal payment button to accept payment on the web page.

First, include the configuration file to load the product and PayPal API variables.

<?php 
// Include the configuration file 
require_once 'config.php';
?>

PayPal JavaScript SDK Library:
Load the PayPal JS SDK, and pass the Client ID & currency in the query string of the URL.

<script src="https://www.paypal.com/sdk/js?client-id=<?php echo PAYPAL_SANDBOX?PAYPAL_SANDBOX_CLIENT_ID:PAYPAL_PROD_CLIENT_ID?>&currency=<?php echo $currency?>"></script>

PayPal Button:
Initially, the product details are displayed with the PayPal payment button.

  • Define a container element for the PayPal button (paypal-button-container).
<div class="panel">
    <div class="overlay hidden"><div class="overlay-content"><img src="css/loading.gif" alt="Processing..."/></div></div>

    <div class="panel-heading">
        <h3 class="panel-title">Charge <?php echo '$'.$itemPrice?> with PayPal</h3>
        
        <!-- Product Info -->
        <p><b>Item Name:</b> <?php echo $itemName?></p>
        <p><b>Price:</b> <?php echo '$'.$itemPrice.' '.$currency?></p>
    </div>
    <div class="panel-body">
        <!-- Display status message -->
        <div id="paymentResponse" class="hidden"></div>
        
        <!-- Set up a container element for the button -->
        <div id="paypal-button-container"></div>
    </div>
</div>

Process Checkout Payment:
The paypal.Buttons() method of PayPal JavaScript SDK is used to process the checkout operations.

  • The button container is attached by the element ID (#paypal-button-container) using the render() method.

createOrder: Sets up the transaction when the payment button is clicked.

  • purchase_units:
    • custom_id: Set the reference ID of the item.
    • description: Set item name.
    • amount:
      • currency_code: Set currency code.
      • value: Set payable amount.
    • items:
      • name: Set item name.
      • description: Set item details.
      • unit_amount:
        • currency_code: Set currency code.
        • value: Set payable amount.
      • category: The item category type (DIGITAL_GOODS / PHYSICAL_GOODS / DONATION ).

onApprove: Finalize the transaction after the payer approves the payment.

  • The order data is POST to the server-side script (paypal_checkout_validate.php) for verification and further processing.
  • If the order and transaction are verified successfully, redirect the user to the payment status page.

The encodeFormData() and setProcessing() are the helper function used in the checkout process.

<script>
paypal.Buttons({
    // Sets up the transaction when a payment button is clicked
    createOrder: (data, actions) => {
        return actions.order.create({
            "purchase_units": [{
                "custom_id": "<?php echo $itemNumber?>",
                "description": "<?php echo $itemName?>",
                "amount": {
                    "currency_code": "<?php echo $currency?>",
                    "value": <?php echo $itemPrice?>,
                    "breakdown": {
                        "item_total": {
                            "currency_code": "<?php echo $currency?>",
                            "value": <?php echo $itemPrice?>
                        }
                    }
                },
                "items": [
                    {
                        "name": "<?php echo $itemName?>",
                        "description": "<?php echo $itemName?>",
                        "unit_amount": {
                            "currency_code": "<?php echo $currency?>",
                            "value": <?php echo $itemPrice?>
                        },
                        "quantity": "1",
                        "category": "DIGITAL_GOODS"
                    },
                ]
            }]
        });
    },
    // Finalize the transaction after payer approval
    onApprove: (data, actions) => {
        return actions.order.capture().then(function(orderData) {
            setProcessing(true);

            var postData = {paypal_order_check: 1, order_id: orderData.id};
            fetch('paypal_checkout_validate.php', {
                method: 'POST',
                headers: {'Accept': 'application/json'},
                body: encodeFormData(postData)
            })
            .then((response) => response.json())
            .then((result) => {
                if(result.status == 1){
                    window.location.href = "payment-status.php?checkout_ref_id="+result.ref_id;
                }else{
                    const messageContainer = document.querySelector("#paymentResponse");
                    messageContainer.classList.remove("hidden");
                    messageContainer.textContent = result.msg;
                    
                    setTimeout(function () {
                        messageContainer.classList.add("hidden");
                        messageText.textContent = "";
                    }, 5000);
                }
                setProcessing(false);
            })
            .catch(error => console.log(error));
        });
    }
}).render('#paypal-button-container');

const encodeFormData = (data) => {
  var form_data = new FormData();

  for ( var key in data ) {
    form_data.append(key, data[key]);
  }
  return form_data;   
}

// Show a loader on payment form processing
const setProcessing = (isProcessing) => {
    if (isProcessing) {
        document.querySelector(".overlay").classList.remove("hidden");
    } else {
        document.querySelector(".overlay").classList.add("hidden");
    }
}    
</script>

PayPal Checkout API Handler Library (PaypalCheckout.class.php)

We will create a custom library to handle PayPal API execution with PHP. This PaypalCheckout library helps to validate transactions and retrieve order details with PayPal Orders REST API using PHP. The cURL method is used to call the PayPal checkout APIs in PHP.

  • validate() – Fetch the access token from PayPal OAuth 2 API.
    • Initialize cURL request to call PayPal checkout API and retrieve order details using PHP.
<?php  
/** 
 * 
 * This PayPal Checkout API handler class is a custom PHP library to handle the PayPal API calls. 
 * 
 * @class   PaypalCheckout 
 * @author  CodexWorld 
 * @link    https://www.codexworld.com 
 * @version 1.0 
 */ 

// Include the configuration file
include_once 'config.php';

class 
PaypalCheckout
    public 
$paypalAuthAPI   PAYPAL_SANDBOX?'https://api-m.sandbox.paypal.com/v1/oauth2/token':'https://api-m.paypal.com/v1/oauth2/token';
    public 
$paypalAPI    PAYPAL_SANDBOX?'https://api-m.sandbox.paypal.com/v2/checkout':'https://api-m.paypal.com/v2/checkout';
    public 
$paypalClientID  PAYPAL_SANDBOX?PAYPAL_SANDBOX_CLIENT_ID:PAYPAL_PROD_CLIENT_ID
    private 
$paypalSecret   PAYPAL_SANDBOX?PAYPAL_SANDBOX_CLIENT_SECRET:PAYPAL_PROD_CLIENT_SECRET
    
    public function 
validate($order_id){
        
$ch curl_init(); 
        
curl_setopt($chCURLOPT_URL$this->paypalAuthAPI); 
        
curl_setopt($chCURLOPT_HEADERfalse); 
        
curl_setopt($chCURLOPT_SSL_VERIFYPEERfalse); 
        
curl_setopt($chCURLOPT_POSTtrue); 
        
curl_setopt($chCURLOPT_RETURNTRANSFERtrue); 
        
curl_setopt($chCURLOPT_USERPWD$this->paypalClientID.":".$this->paypalSecret); 
        
curl_setopt($chCURLOPT_POSTFIELDS"grant_type=client_credentials"); 
        
$auth_response json_decode(curl_exec($ch));
        
$http_code curl_getinfo($chCURLINFO_HTTP_CODE);
        
curl_close($ch); 

        if (
$http_code != 200 && !empty($auth_response->error)) { 
            throw new 
Exception('Error '.$auth_response->error.': '.$auth_response->error_description); 
        }
         
        if(empty(
$auth_response)){
            return 
false
        }else{
            if(!empty(
$auth_response->access_token)){
                
$ch curl_init();
                
curl_setopt($chCURLOPT_URL$this->paypalAPI.'/orders/'.$order_id);
                
curl_setopt($chCURLOPT_RETURNTRANSFER1);
                
curl_setopt($chCURLOPT_SSL_VERIFYPEERFALSE); 
                
curl_setopt($chCURLOPT_HTTPHEADER, array('Content-Type: application/json''Authorization: Bearer '$auth_response->access_token)); 
                
curl_setopt($chCURLOPT_CUSTOMREQUEST'GET');
                
$api_data json_decode(curl_exec($ch), true);
                
$http_code curl_getinfo($chCURLINFO_HTTP_CODE); 
                
curl_close($ch);

                if (
$http_code != 200 && !empty($api_data['error'])) { 
                    throw new 
Exception('Error '.$api_data['error'].': '.$api_data['error_description']); 
                }

                return !empty(
$api_data) && $http_code == 200?$api_data:false;
            }else{
                return 
false;
            }
        }
    }
}

Checkout Payment Verification (paypal_checkout_validate.php)

This server-side script is accessed by the client-side Fetch API defined in onApprove() method to verify orders using PayPal REST API and store transaction details in the database using PHP and MySQL.

  • Include the PaypalCheckout custom PHP library to handle the PayPal REST API operations.
  • Use the validate() function of the PaypalCheckout class to verify the order by reference ID posted from the client-side script.
  • Insert the transaction data in the database using PHP and MySQL.
  • Return Transaction ID in base64 encoded format to the client side.
<?php 
// Include the configuration file
require_once 'config.php';

// Include the database connection file
include_once 'dbConnect.php';

// Include the PayPal API library
require_once 'PaypalCheckout.class.php';
$paypal = new PaypalCheckout;

$response = array('status' => 0'msg' => 'Transaction Failed!');
if(!empty(
$_POST['paypal_order_check']) && !empty($_POST['order_id'])){
    
// Validate and get order details with PayPal API
    
try { 
        
$order $paypal->validate($_POST['order_id']);
    } catch(
Exception $e) { 
        
$api_error $e->getMessage(); 
    }
    
    if(!empty(
$order)){
        
$order_id $order['id'];
        
$intent $order['intent'];
        
$order_status $order['status'];
        
$order_time date("Y-m-d H:i:s"strtotime($order['create_time']));

        if(!empty(
$order['purchase_units'][0])){
            
$purchase_unit $order['purchase_units'][0];

            
$item_number $purchase_unit['custom_id'];
            
$item_name $purchase_unit['description'];
            
            if(!empty(
$purchase_unit['amount'])){
                
$currency_code $purchase_unit['amount']['currency_code'];
                
$amount_value $purchase_unit['amount']['value'];
            }

            if(!empty(
$purchase_unit['payments']['captures'][0])){
                
$payment_capture $purchase_unit['payments']['captures'][0];
                
$transaction_id $payment_capture['id'];
                
$payment_status $payment_capture['status'];
            }

            if(!empty(
$purchase_unit['payee'])){
                
$payee $purchase_unit['payee'];
                
$payee_email_address $payee['email_address'];
                
$merchant_id $payee['merchant_id'];
            }
        }

        
$payment_source '';
        if(!empty(
$order['payment_source'])){
            foreach(
$order['payment_source'] as $key=>$value){
                
$payment_source $key;
            }
        }

        if(!empty(
$order['payer'])){
            
$payer $order['payer'];
            
$payer_id $payer['payer_id'];
            
$payer_name $payer['name'];
            
$payer_given_name = !empty($payer_name['given_name'])?$payer_name['given_name']:'';
            
$payer_surname = !empty($payer_name['surname'])?$payer_name['surname']:'';
            
$payer_full_name trim($payer_given_name.' '.$payer_surname);
            
$payer_full_name filter_var($payer_full_nameFILTER_SANITIZE_STRING,FILTER_FLAG_STRIP_HIGH);

            
$payer_email_address $payer['email_address'];
            
$payer_address $payer['address'];
            
$payer_country_code = !empty($payer_address['country_code'])?$payer_address['country_code']:'';
        }

        if(!empty(
$order_id) && $order_status == 'COMPLETED'){
            
// Check if any transaction data is exists already with the same TXN ID
            
$sqlQ "SELECT id FROM transactions WHERE transaction_id = ?";
            
$stmt $db->prepare($sqlQ); 
            
$stmt->bind_param("s"$transaction_id);
            
$stmt->execute();
            
$stmt->bind_result($row_id);
            
$stmt->fetch();
            
            
$payment_id 0;
            if(!empty(
$row_id)){
                
$payment_id $row_id;
            }else{
                
// Insert transaction data into the database
                
$sqlQ "INSERT INTO transactions (item_number,item_name,item_price,item_price_currency,payer_id,payer_name,payer_email,payer_country,merchant_id,merchant_email,order_id,transaction_id,paid_amount,paid_amount_currency,payment_source,payment_status,created,modified) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,NOW())";
                
$stmt $db->prepare($sqlQ);
                
$stmt->bind_param("ssdsssssssssdssss"$item_number$item_name$itemPrice$currency$payer_id$payer_full_name$payer_email_address$payer_country_code$merchant_id$payee_email_address$order_id$transaction_id$amount_value$currency_code$payment_source$payment_status$order_time);
                
$insert $stmt->execute();
                
                if(
$insert){
                    
$payment_id $stmt->insert_id;
                }
            }

            if(!empty(
$payment_id)){
                
$ref_id_enc base64_encode($transaction_id);
                
$response = array('status' => 1'msg' => 'Transaction completed!''ref_id' => $ref_id_enc);
            }
        }
    }else{
        
$response['msg'] = $api_error;
    }
}
echo 
json_encode($response);
?>

Payment Status (payment-status.php)

Based on the status return by the order.capture(), the buyer is redirected to this page.

  • Fetch transaction data from the database using PHP and MySQL.
  • Display transaction details on the web page.
<?php 
// Include the configuration file 
require_once 'config.php';

// Include the database connection file 
require_once 'dbConnect.php';

$payment_ref_id $statusMsg '';
$status 'error';

// Check whether the payment ID is not empty
if(!empty($_GET['checkout_ref_id'])){
    
$payment_txn_id  base64_decode($_GET['checkout_ref_id']);
    
    
// Fetch transaction data from the database
    
$sqlQ "SELECT id,payer_id,payer_name,payer_email,payer_country,order_id,transaction_id,paid_amount,paid_amount_currency,payment_source,payment_status,created FROM transactions WHERE transaction_id = ?";
    
$stmt $db->prepare($sqlQ); 
    
$stmt->bind_param("s"$payment_txn_id);
    
$stmt->execute();
    
$stmt->store_result();

    if(
$stmt->num_rows 0){
        
// Get transaction details
        
$stmt->bind_result($payment_ref_id$payer_id$payer_name$payer_email$payer_country$order_id$transaction_id$paid_amount$paid_amount_currency$payment_source$payment_status$created);
        
$stmt->fetch();
        
        
$status 'success';
        
$statusMsg 'Your Payment has been Successful!';
    }else{
        
$statusMsg "Transaction has been failed!";
    }
}else{
    
header("Location: index.php");
    exit;
}
?> <?php if(!empty($payment_ref_id)){ ?> <h1 class="<?php echo $status?>"><?php echo $statusMsg?></h1> <h4>Payment Information</h4> <p><b>Reference Number:</b> <?php echo $payment_ref_id?></p> <p><b>Order ID:</b> <?php echo $order_id?></p> <p><b>Transaction ID:</b> <?php echo $transaction_id?></p> <p><b>Paid Amount:</b> <?php echo $paid_amount.' '.$paid_amount_currency?></p> <p><b>Payment Status:</b> <?php echo $payment_status?></p> <p><b>Date:</b> <?php echo $created?></p> <h4>Payer Information</h4> <p><b>ID:</b> <?php echo $payer_id?></p> <p><b>Name:</b> <?php echo $payer_name?></p> <p><b>Email:</b> <?php echo $payer_email?></p> <p><b>Country:</b> <?php echo $payer_country?></p> <h4>Product Information</h4> <p><b>Name:</b> <?php echo $itemName?></p> <p><b>Price:</b> <?php echo $itemPrice.' '.$currency?></p> <?php }else{ ?> <h1 class="error">Your Payment been failed!</h1> <p class="error"><?php echo $statusMsg?></p> <?php }?>

Make PayPal Standard Checkout Payment Gateway Live

Once the integration is completed and the payment process is working properly, follow the below steps to make PayPal checkout live.
1. Go to the PayPal Developer Dashboard Stripe account.

  • Switch to the Live environment using the toggle button at the top-right corner.
  • Navigate to the Apps & Credentials section and collect the REST API credentials (Client ID and Secret) for the Live environment.

2. In the config.php file,

  • Set the PAYPAL_SANDBOX to FALSE.
  • Specify the REST API keys (Client ID and Secret key) in PAYPAL_PROD_CLIENT_ID and PAYPAL_PROD_CLIENT_SECRET variables.
define('PAYPAL_SANDBOX'FALSE); 

define('PAYPAL_PROD_CLIENT_ID''Insert_Live_PayPal_Client_ID_Here');
define('PAYPAL_PROD_CLIENT_SECRET''Insert_Live_PayPal_Secret_Key_Here');

Stripe Payment Gateway Integration in PHP

Conclusion

Previously, the PayPal Standard payment gateway was used to accept payment with PayPal form variables. The PayPal standard checkout is the replacement of it and introduced with advanced features and security. The PayPal checkout provides a smooth UI experience on both desktop and mobile devices. So, you don’t need to worry about the payment checkout UI on the website. Use our example script to integrate the PayPal checkout system on the website with JavaScript and accept payment online instantly.

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

7 Comments

  1. Andreas Said...
  2. Ulrich Said...
    • CodexWorld Said...
  3. Bon Said...
  4. Yianni Said...
  5. Yianni Said...
  6. Nico Said...

Leave a reply

keyboard_double_arrow_up