PayPal Standard Payment Gateway Integration in PHP

PayPal is an American international e-commerce business allowing payments and money transfers to be made through the Internet. PayPal is the most popular payment gateway to send and receive payment worldwide. PayPal is a widely used payment gateway to accept payment in the web application. PayPal payment gateway is the easiest option for the web developer to implement a payment system on the website.

PayPal Standard Payment Gateway is the quickest way to accept payment online. The buyer can make the payment from the website to purchase an item online. In this tutorial, we will show you how to integrate PayPal standard payment gateway in PHP and store the transaction data in the database using PayPal IPN. Our step-by-step guide on PayPal payment gateway integration in PHP helps you to easily integrate the online payment feature in your web project.

Since the PayPal Standard payment is on the Legacy version, we recommended integrating PayPal Standard Checkout for the new payment gateway integration.

In the example script, we will implement the following functionality to demonstrate the PayPal Payment Gateway integration process.

  • Fetch the products from the database and listed on the web page with the PayPal Buy button.
  • The Buy button redirects the buyer to the PayPal site to complete the payment.
  • After the payment, the buyer will redirect back to the website and the payment details will be shown.
  • The transaction data is stored in the database through the PayPal IPN.

Before getting started to integrate PayPal payment gateway API in PHP, take a look at the files structure.

paypal_integration_php/
├── config.php
├── dbConnect.php
├── index.php
├── success.php
├── cancel.php
├── ipn.php
├── css/
│   └── style.css
└── images/

PayPal has two environments such as Sandbox and Real Time. PayPal Sandbox allows developers to do their test transaction before the project go live. The real-time environment is used after the project is live on the production server. Once the PayPal payment process is working properly on the Sandbox environment, you can set the PayPal payment gateway for Real-Time environment.

Create PayPal Sandbox Account

Before start accepting payment from buyers via PayPal, the payment gateway needs to be tested. To test the transaction process you need to create a PayPal sandbox account.

  • Go to the PayPal Developer page and log in to your PayPal account. If you don’t have any PayPal account, register for a PayPal account first.
  • After logging in you would be redirected to the developer homepage. Now click on the Dashboard link from the top navigation menu.
  • Click on the Accounts link under the Sandbox label from the left menu panel.
  • Create a buyer account and a merchant account from the Create Account link. For buyer account, you need to select Personal radio button under the Account type section or select Business radio button for a merchant account.

You may follow the detailed guide on creating a PayPal Sandbox account from this tutorial – Creating PayPal Sandbox Test Account and Website Payments Pro Account

Create Database Tables

To store product and payment information two tables needs to be created in the database.

The following SQL creates a products table in the MySQL database to store the product data.

CREATE TABLE `products` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `name` varchar(200) COLLATE utf8_unicode_ci NOT NULL,
 `image` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
 `price` float(10,2) NOT NULL,
 `status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '1=Active | 0=Inactive',
 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 data provided by PayPal.

CREATE TABLE `payments` (
 `payment_id` int(11) NOT NULL AUTO_INCREMENT,
 `item_number` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
 `txn_id` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
 `payment_gross` float(10,2) NOT NULL,
 `currency_code` varchar(5) COLLATE utf8_unicode_ci NOT NULL,
 `payment_status` varchar(20) COLLATE utf8_unicode_ci NOT NULL,
 PRIMARY KEY (`payment_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

PayPal Settings and Database Configuration (config.php)

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

PayPal Constants:

  • PAYPAL_ID – Specify the email of the PayPal Business account.
  • PAYPAL_SANDBOX – Specify whether you use Sandbox environment (TRUE/FALSE).
  • PAYPAL_RETURN_URL – Specify the URL where the buyer will be redirected after payment.
  • PAYPAL_CANCEL_URL – Specify the URL where the buyer will be redirected after payment cancellation.
  • PAYPAL_NOTIFY_URL – Specify the URL where the transaction data will be sent for verification through PayPal IPN.
  • PAYPAL_CURRENCY – Specify the currency code.

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 
/*
 * PayPal and database configuration
 */
 
// PayPal configuration
define('PAYPAL_ID''Insert_PayPal_Business_Email');
define('PAYPAL_SANDBOX'TRUE); //TRUE or FALSE

define('PAYPAL_RETURN_URL''http://www.example.com/success.php');
define('PAYPAL_CANCEL_URL''http://www.example.com/cancel.php');
define('PAYPAL_NOTIFY_URL''http://www.example.com/ipn.php');
define('PAYPAL_CURRENCY''USD');

// Database configuration
define('DB_HOST''MySQL_Database_Host');
define('DB_USERNAME''MySQL_Database_Username');
define('DB_PASSWORD''MySQL_Database_Password');
define('DB_NAME''MySQL_Database_Name');

// Change not required
define('PAYPAL_URL', (PAYPAL_SANDBOX == true)?"https://www.sandbox.paypal.com/cgi-bin/webscr":"https://www.paypal.com/cgi-bin/webscr");

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();
}

Products (index.php)

Initially, all the products are fetched from the database and listed on the webpage.

  • A PayPal Buy Now button is placed with each product.
  • To use PayPal standard payment gateway, you need to submit a form with some predefined PayPal HTML form field variable.
  • Follow the comment tags (<!– –>) to know about the form hidden fields.
<?php 
// Include configuration file
include_once 'config.php';

// Include database connection file
include_once 'dbConnect.php';
?> <div class="container">     <?php
        
// Fetch products from the database
        
$results $db->query("SELECT * FROM products WHERE status = 1");
        while(
$row $results->fetch_assoc()){
    
?> <div class="pro-box"> <img src="images/<?php echo $row['image']; ?>"/> <div class="body"> <h5><?php echo $row['name']; ?></h5> <h6>Price: <?php echo '$'.$row['price'].' '.PAYPAL_CURRENCY?></h6> <!-- PayPal payment form for displaying the buy button --> <form action="<?php echo PAYPAL_URL; ?>" method="post"> <!-- Identify your business so that you can collect the payments. --> <input type="hidden" name="business" value="<?php echo PAYPAL_ID; ?>"> <!-- Specify a Buy Now button. --> <input type="hidden" name="cmd" value="_xclick"> <!-- Specify details about the item that buyers will purchase. --> <input type="hidden" name="item_name" value="<?php echo $row['name']; ?>"> <input type="hidden" name="item_number" value="<?php echo $row['id']; ?>"> <input type="hidden" name="amount" value="<?php echo $row['price']; ?>"> <input type="hidden" name="currency_code" value="<?php echo PAYPAL_CURRENCY?>"> <!-- Specify URLs --> <input type="hidden" name="return" value="<?php echo PAYPAL_RETURN_URL?>"> <input type="hidden" name="cancel_return" value="<?php echo PAYPAL_CANCEL_URL?>"> <!-- Display the payment button. --> <input type="image" name="submit" border="0" src="https://www.paypalobjects.com/en_US/i/btn/btn_buynow_LG.gif"> </form> </div> </div> <?php ?> </div>

Payment Success (success.php)

After successful payment on PayPal, the buyer is redirected to this page.

  • The transaction data is retrieved from the URL using PHP $_GET method.
  • Insert/Update payment information in the database based on the transaction ID.
  • The payment details are displayed on the webpage.
<?php 
// Include configuration file
include_once 'config.php';

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

// If transaction data is available in the URL
if(!empty($_GET['item_number']) && !empty($_GET['tx']) && !empty($_GET['amt']) && !empty($_GET['cc']) && !empty($_GET['st'])){
    
// Get transaction information from URL
    
$item_number $_GET['item_number']; 
    
$txn_id $_GET['tx'];
    
$payment_gross $_GET['amt'];
    
$currency_code $_GET['cc'];
    
$payment_status $_GET['st'];
    
    
// Get product info from the database
    
$productResult $db->query("SELECT * FROM products WHERE id = ".$item_number);
    
$productRow $productResult->fetch_assoc();
    
    
// Check if transaction data exists with the same TXN ID.
    
$prevPaymentResult $db->query("SELECT * FROM payments WHERE txn_id = '".$txn_id."'");

    if(
$prevPaymentResult->num_rows 0){
        
$paymentRow $prevPaymentResult->fetch_assoc();
        
$payment_id $paymentRow['payment_id'];
        
$payment_gross $paymentRow['payment_gross'];
        
$payment_status $paymentRow['payment_status'];
    }else{
        
// Insert tansaction data into the database
        
$insert $db->query("INSERT INTO payments(item_number,txn_id,payment_gross,currency_code,payment_status) VALUES('".$item_number."','".$txn_id."','".$payment_gross."','".$currency_code."','".$payment_status."')");
        
$payment_id $db->insert_id;
    }
}
?> <div class="container"> <div class="status"> <?php if(!empty($payment_id)){ ?> <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 $txn_id?></p> <p><b>Paid Amount:</b> <?php echo $payment_gross?></p> <p><b>Payment Status:</b> <?php echo $payment_status?></p> <h4>Product Information</h4> <p><b>Name:</b> <?php echo $productRow['name']; ?></p> <p><b>Price:</b> <?php echo $productRow['price']; ?></p> <?php }else{ ?> <h1 class="error">Your Payment has Failed</h1> <?php ?> </div> <a href="index.php" class="btn-link">Back to Products</a> </div>

Payment Cancellation (cancel.php)

If the buyer wishes to cancel payment at the PayPal payment page, the buyer is redirected to this page.

<div class="container">
    <div class="status">
        <h1 class="error">Your PayPal Transaction has been Canceled</h1>
    </div>
    <a href="index.php" class="btn-link">Back to Products</a>
</div>

Configure PayPal Auto Return and Payment Data Transfer

Make sure you have configured Auto Return for Website Payments on your PayPal business account. Otherwise, you’ll not get the transaction information from PayPal in the success.php file. See the following guide to enable Auto Return, Payment Data Transfer and set Return URL on your PayPal account.

Setup PayPal Instant Payment Notification (IPN)

To make the PayPal Standard Payment secure, validate the transaction with PayPal Instant Payment Notification (IPN). Follow the below steps to setup IPN in PayPal standard payment gateway integration.

Enable IPN:
To use this feature, IPN must be enabled in the PayPal account. We’ve already published a step-by-step guide to enable IPN in PayPal, please see the below tutorial.

Add Notify URL in PayPal Form:
Add the following input field (notify_url) HTML along with the other PayPal HTML Variables.

<input type="hidden" name="notify_url" value="<?php echo PAYPAL_NOTIFY_URL?>">

Validate Transaction:
Once IPN is enabled, PayPal will send the transaction data to the Notify URL (http://www.example.com/ipn.php). Place the following code in the ipn.php file to validate the transaction and insert payment information into the database.

<?php 
// Include configuration file
include_once 'config.php';

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

/*
 * Read POST data
 * reading posted data directly from $_POST causes serialization
 * issues with array data in POST.
 * Reading raw POST data from input stream instead.
 */        
$raw_post_data file_get_contents('php://input');
$raw_post_array explode('&'$raw_post_data);
$myPost = array();
foreach (
$raw_post_array as $keyval) {
    
$keyval explode ('='$keyval);
    if (
count($keyval) == 2)
        
$myPost[$keyval[0]] = urldecode($keyval[1]);
}

// Read the post from PayPal system and add 'cmd'
$req 'cmd=_notify-validate';
if(
function_exists('get_magic_quotes_gpc')) {
    
$get_magic_quotes_exists true;
}
foreach (
$myPost as $key => $value) {
    if(
$get_magic_quotes_exists == true && get_magic_quotes_gpc() == 1) {
        
$value urlencode(stripslashes($value));
    } else {
        
$value urlencode($value);
    }
    
$req .= "&$key=$value";
}

/*
 * Post IPN data back to PayPal to validate the IPN data is genuine
 * Without this step anyone can fake IPN data
 */
$paypalURL PAYPAL_URL;
$ch curl_init($paypalURL);
if (
$ch == FALSE) {
    return 
FALSE;
}
curl_setopt($chCURLOPT_HTTP_VERSIONCURL_HTTP_VERSION_1_1);
curl_setopt($chCURLOPT_POST1);
curl_setopt($chCURLOPT_RETURNTRANSFER,1);
curl_setopt($chCURLOPT_POSTFIELDS$req);
curl_setopt($chCURLOPT_SSLVERSION6);
curl_setopt($chCURLOPT_SSL_VERIFYPEER1);
curl_setopt($chCURLOPT_SSL_VERIFYHOST2);
curl_setopt($chCURLOPT_FORBID_REUSE1);

// Set TCP timeout to 30 seconds
curl_setopt($chCURLOPT_CONNECTTIMEOUT30);
curl_setopt($chCURLOPT_HTTPHEADER, array('Connection: Close''User-Agent: company-name'));
$res curl_exec($ch);

/*
 * Inspect IPN validation result and act accordingly
 * Split response headers and payload, a better way for strcmp
 */ 
$tokens explode("\r\n\r\n"trim($res));
$res trim(end($tokens));
if (
strcmp($res"VERIFIED") == || strcasecmp($res"VERIFIED") == 0) {
    
    
// Retrieve transaction info from PayPal
    
$item_number    $_POST['item_number'];
    
$txn_id         $_POST['txn_id'];
    
$payment_gross     $_POST['mc_gross'];
    
$currency_code     $_POST['mc_currency'];
    
$payment_status $_POST['payment_status'];
    
    
// Check if transaction data exists with the same TXN ID
    
$prevPayment $db->query("SELECT payment_id FROM payments WHERE txn_id = '".$txn_id."'");
    if(
$prevPayment->num_rows 0){
        exit();
    }else{
        
// Insert transaction data into the database
        
$insert $db->query("INSERT INTO payments(item_number,txn_id,payment_gross,currency_code,payment_status) VALUES('".$item_number."','".$txn_id."','".$payment_gross."','".$currency_code."','".$payment_status."')");
    }

}
?>

Note that: Once the PayPal IPN setup is completed, the database insertion code is not required in the success.php file.

Make PayPal Payment Gateway Live

When the application payment flow testing is completed, you should make the PayPal payment gateway live.

In the config.php file,

  • Specify the email of the PayPal business account in PAYPAL_ID.
  • Set PAYPAL_SANDBOX to FALSE.
define('PAYPAL_ID''Insert_PayPal_Business_Email'); 
define('PAYPAL_SANDBOX'FALSE);

PayPal Pro Payment Gateway Integration in PHP

Conclusion

PayPal standard payment gateway is the easiest way to accept payment on the web application. With our example script, you can easily integrate the PayPal payment API on the website. To make the payment process user-friendly, you can integrate PayPal Express Checkout for the online payment.

Are you want to get implementation help, or modify or enhance the functionality of this script? Click Here to Submit Service Request

If you have any questions about this script, submit it to our QA community - Ask Question

115 Comments

  1. Jeffrey Ault Said...
  2. Manoj Said...
  3. Ivan Said...
  4. Muthukumaran Said...
  5. Leo Said...
  6. Cristian Said...
  7. Vishal Rana Said...
  8. Vinay Said...
  9. 0day1337 Said...
  10. Aria Sanat Said...
  11. Charly Said...
  12. Muyin Uddin Said...
  13. Havikk Said...
    • CodexWorld Said...
  14. Lydo Said...
  15. Dhruv Said...
  16. Hassan Zaidi Said...
  17. Christine Said...
  18. Sakshi Said...
  19. Mitesh Shah Said...
  20. Vanitha Said...
  21. Newbie Said...
  22. Solace Said...
    • CodexWorld Said...
  23. Solace Said...
    • CodexWorld Said...
  24. Haider Said...
  25. MDB Said...
  26. Mohammad Huzaifa Umair Said...
  27. Mohammad Huzaifa Umair Said...
  28. Somnath Said...
    • CodexWorld Said...
  29. Héctor Said...
  30. Héctor Said...
  31. RickH Said...
  32. Héctor Said...
  33. Piyush Said...
    • CodexWorld Said...
  34. Raisinejoe Said...
  35. Ijaz Said...

Leave a reply

keyboard_double_arrow_up