PayPal is the most popular online payment system that helps to easily integrate payment gateway on the website. PayPal payments standard is the most simple way to implement the payment system to your website and accept payment from the buyers online. With the PayPal standard payment gateway, a buy now button is provided that allows the buyer to purchase a single item at a time. If you want to allow the buyer to purchase multiple items at a time, PayPal Add to Cart button is the easiest option to accept payment for one or more items with a single checkout flow. In this tutorial, we’ll show how to integrate PayPal standard payment gateway in PHP for sending multiple items to PayPal checkout.
In the example script, we will implement the following functionality to demonstrate the PayPal Cart Payment Gateway integration in PHP.
Before getting started to integrate PayPal shopping cart payment gateway in PHP, take a look at the file structure.
paypal_shopping_cart_with_php/ ├── config.php ├── dbConnect.php ├── index.php ├── success.php ├── cancel.php ├── paypal_ipn.php ├── css/ │ └── style.css └── images/
Before making the payment gateway live, the payment process needs to be tested. PayPal sandbox environment allows you to test PayPal payment gateway on your website without real payment. If you don’t have a PayPal sandbox account, create a sandbox account first.
To store product, order, and payment information 4 tables are required in the database.
The following SQL creates a products
table in the MySQL database to store the product information.
CREATE TABLE `products` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) 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,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
The following SQL creates a orders
table in the MySQL database to store the order information.
CREATE TABLE `orders` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`total_qty` int(11) NOT NULL,
`total_amount` float(10,2) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
The following SQL creates a order_items
table in the MySQL database to store the information about order items.
CREATE TABLE `order_items` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`order_id` int(11) NOT NULL,
`product_id` int(11) NOT NULL,
`quantity` int(5) NOT NULL,
`gross_amount` float(10,2) NOT NULL,
PRIMARY KEY (`id`),
KEY `order_id` (`order_id`),
KEY `product_id` (`product_id`),
CONSTRAINT `order_items_ibfk_1` FOREIGN KEY (`order_id`) REFERENCES `orders` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION,
CONSTRAINT `order_items_ibfk_2` FOREIGN KEY (`product_id`) REFERENCES `products` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
The following SQL creates a payments
table in the MySQL database to store the payment information.
CREATE TABLE `payments` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`order_id` int(11) NOT NULL,
`payer_name` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
`payer_email` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
`txn_id` varchar(255) 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(25) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`id`),
KEY `order_id` (`order_id`),
CONSTRAINT `payments_ibfk_1` FOREIGN KEY (`order_id`) REFERENCES `orders` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
In the config.php
file, constant variables of PayPal and database settings are defined.
PayPal Constants:
Database Constants:
<?php
// PayPal configuration
define('PAYPAL_ID', 'Insert_PayPal_Business_Email');
define('PAYPAL_SANDBOX', TRUE); //TRUE or FALSE
define('CONTINUE_SHOPPING_URL', 'http://www.example.com/index.php');
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/paypal_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");
The dbConnect.php file is used to connect the database using PHP and MySQL.
<?php
// Connect with the database
$db = new mysqli(DB_HOST, DB_USERNAME, DB_PASSWORD, DB_NAME);
// Display error if failed to connect
if ($db->connect_errno) {
printf("Connect failed: %s\n", $db->connect_error);
exit();
}
Initially, all the products are fetched from the database and listed on the webpage.
<?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");
while($row = $results->fetch_assoc()){
?>
<div class="pro-box">
<img src="images/<?php echo $row['image']; ?>"/>
<p>Name: <?php echo $row['name']; ?></p>
<p>Price: $<?php echo $row['price']; ?></p>
<form target="_self" 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 PayPal Shopping Cart Add to Cart button. -->
<input type="hidden" name="cmd" value="_cart">
<input type="hidden" name="add" value="1">
<!-- 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="shopping_url" value="<?php echo CONTINUE_SHOPPING_URL; ?>">
<input type="hidden" name="cancel_return" value="<?php echo PAYPAL_CANCEL_URL; ?>">
<input type="hidden" name="return" value="<?php echo PAYPAL_RETURN_URL; ?>">
<input type="hidden" name="notify_url" value="<?php echo PAYPAL_NOTIFY_URL; ?>">
<!-- Display the payment button. -->
<input type="image" name="submit" src="https://www.paypalobjects.com/webstatic/en_US/i/btn/png/btn_addtocart_120x26.png" alt="Add to Cart">
<img alt="" width="1" height="1" src="https://www.paypalobjects.com/en_US/i/scr/pixel.gif">
</form>
</div>
<?php } ?>
</div>
After the payment is successful on PayPal, the buyer will be redirected to this page.
<?php
// Include configuration file
include_once 'config.php';
// Include database connection file
include_once 'dbConnect.php';
$paymentData = '';
if(!empty($_GET['tx']) && !empty($_GET['amt']) && $_GET['st'] == 'Completed'){
// Get transaction information from URL
$txn_id = $_GET['tx'];
$payment_gross = $_GET['amt'];
$currency_code = $_GET['cc'];
$payment_status = $_GET['st'];
// 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){
// Get subscription info from database
$paymentData = $prevPaymentResult->fetch_assoc();
// Order details
$orderResult = $db->query("SELECT * FROM orders WHERE id = ".$paymentData['order_id']);
$orderData = $orderResult->fetch_assoc();
// Order items
$orderItemsResult = $db->query("SELECT i.*,pr.name FROM payments as p LEFT JOIN order_items as i ON i.order_id=p.order_id LEFT JOIN products as pr ON pr.id = i.product_id WHERE p.id = ".$paymentData['id']);
}
}
?>
<div class="status">
<?php if(!empty($paymentData)){ ?>
<h1 class="success">Your Payment has been Successful!</h1>
<h4>Order Information</h4>
<p><b>Order ID:</b> <?php echo $orderData['id']; ?></p>
<p><b>Total Items:</b> <?php echo $orderData['total_qty']; ?></p>
<p><b>Order Total:</b> <?php echo $orderData['total_amount']; ?></p>
<h4>Payment Information</h4>
<p><b>Reference Number:</b> <?php echo $paymentData['id']; ?></p>
<p><b>Transaction ID:</b> <?php echo $paymentData['txn_id']; ?></p>
<p><b>Paid Amount:</b> <?php echo $paymentData['payment_gross'].' '.$paymentData['currency_code']; ?></p>
<p><b>Payment Status:</b> <?php echo $paymentData['payment_status']; ?></p>
<h4>Order Items</h4>
<?php if($orderItemsResult->num_rows > 0){ ?>
<table>
<tr>
<th>#</th>
<th>Product Name</th>
<th>Quantity</th>
<th>Gross Amount</th>
</tr>
<?php $i=0; while($item = $orderItemsResult->fetch_assoc()){ $i++; ?>
<tr>
<td align="center"><?php echo $i; ?></td>
<td align="center"><?php echo $item['name']; ?></td>
<td align="center"><?php echo $item['quantity']; ?></td>
<td align="center"><?php echo '$'.$item['gross_amount']; ?></td>
</tr>
<?php } ?>
</table>
<?php } ?>
<?php }else{ ?>
<h1 class="error">Your payment was unsuccessful, please try again.</h1>
<?php } ?>
</div>
Note that: The transaction data is validated and inserted into the database using the IPN script.
If the buyer wishes to cancel payment at the PayPal checkout page, they will be 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>
The PayPal IPN feature is used to validate the transaction and store the payment information in the database.
http://www.example.com/paypal_ipn.php
).<?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($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
curl_setopt($ch, CURLOPT_SSLVERSION, 6);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
// Set TCP timeout to 30 seconds
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_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") == 0 || strcasecmp($res, "VERIFIED") == 0) {
// Retrieve transaction data from PayPal
$paypalInfo = $_POST;
$txn_id = !empty($paypalInfo['txn_id'])?$paypalInfo['txn_id']:'';
$payment_gross = !empty($paypalInfo['mc_gross'])?$paypalInfo['mc_gross']:0;
$currency_code = $paypalInfo['mc_currency'];
$payment_status = !empty($paypalInfo['payment_status'])?$paypalInfo['payment_status']:'';
$payerFirstName = !empty($_POST['first_name'])?$_POST['first_name']:'';
$payer_name = !empty($_POST['last_name'])?$payerFirstName.' '.$_POST['last_name']:$payerFirstName;
$payer_name = filter_var($payer_name,FILTER_SANITIZE_STRING,FILTER_FLAG_STRIP_HIGH);
$payer_email = $paypalInfo['payer_email'];
$num_cart_items = $_POST['num_cart_items'];
if(!empty($txn_id)){
// Check if transaction data exists with the same TXN ID
$prevPayment = $db->query("SELECT id FROM payments WHERE txn_id = '".$txn_id."'");
if($prevPayment->num_rows > 0){
exit();
}else{
// Insert order data into the database
$insertOrder = $db->query("INSERT INTO orders(total_qty,total_amount) VALUES($num_cart_items,'".$payment_gross."')");
if($insertOrder){
$order_id = $db->insert_id;
// Insert tansaction data into the database
$insertPayment = $db->query("INSERT INTO payments(order_id,payer_name,payer_email,txn_id,payment_gross,currency_code,payment_status) VALUES($order_id,'".$payer_name."','".$payer_email."','".$txn_id."','".$payment_gross."','".$currency_code."','".$payment_status."')");
if($insertPayment){
$payment_id = $db->insert_id;
// Insert order items into the database
for($i=1;$i<=$num_cart_items;$i++){
$order_item_number = $_POST['item_number'.$i];
$order_item_quantity = $_POST['quantity'.$i];
$order_item_gross_amount = $_POST['mc_gross_'.$i];
$insertOrderItem = $db->query("INSERT INTO order_items(order_id,product_id,quantity,gross_amount) VALUES('".$order_id."','".$order_item_number."','".$order_item_quantity."','".$order_item_gross_amount."')");
}
}
}
}
}
}
die;
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.
The IPN option must be enabled in the PayPal account. See the step-by-step guide to enable IPN feature in PayPal.
When the application payment flow is working properly with the Sandbox account, you should make the PayPal payment gateway live.
In the config.php
file,
PAYPAL_ID
.PAYPAL_SANDBOX
to FALSE.PayPal Pro Payment Gateway Integration in PHP
Do you want to get implementation help, or enhance the functionality of this script? Click here to Submit Service Request
Dear
Can you please send me code for multiple items first added to my checkout page and then total item i go with paypal payment….not going on paypal payment page and clicking add more items
How can I create subscription payment so that monthly amount deducted from customer account automatically using AIM in php?? Please help me I am really facing problem..Thank You
See this tutorial to integrate PayPal subscriptions payment gateway in PHP – https://www.codexworld.com/paypal-subscriptions-payment-gateway-integration-php/
Hi,
How can implement it so i am redirected to the Paypal checkout instead of the annoying cart? also can you add multiple items in the same form?
Thanks
I tried to did this same example. But after completing process of payment I get
Your payment has failed.
in Success.php
One more confusion is that in .zip file it’s ipn.php and in configuration it show paypal_ipn.php in notify_url
Should I use just ipn.php or I have to use paypal_ipn.php
Please Help.. Really Need
@Krishna Please follow our step-by-step guide. If you specify
ipn.php
in notify_url, your IPN script should be placed into theipn.php
file.