Shopping Cart with PayPal Integration in PHP

In previous tutorial you have learned how to create shopping cart with Ajax, PHP and MySQL to add items to the cart using Ajax. But its still needs further steps to handle payment of the cart items. So in this tutorial, you will learn how to integrate PayPal payment gateway into shopping cart to handle payment. We will use same shopping cart example to add payment functionality. As in previous shopping cart example, we have already handled to show cart detail to checkout and review cart details before placing order with payable amount. So now we will handle to get customer shipping details and then handle payment with PayPal gateway.

Also, read:

Step1: Create PayPal Sandbox Account
As we will learn to integrate PayPal payment gateway, so we need to test it before live. For this we will need to create PayPal sandbox account to test PayPal payment gateway on your website without real payment. So if you have not PayPal sandbox account then create it.

Step2: Create Database Tables
We will use following MySQL database tables to handle entire shopping cart.

the product details are stored into the shop_products table.


CREATE TABLE `shop_products` (
  `id` int(11) NOT NULL,
  `product_name` varchar(60) NOT NULL,
  `product_desc` text NOT NULL,
  `product_code` varchar(60) NOT NULL,
  `product_image` varchar(60) NOT NULL,
  `product_price` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

the order details will be stored in shop_order table.

CREATE TABLE `shop_order` (
  `id` int(11) NOT NULL,
  `member_id` int(11) NOT NULL,
  `name` varchar(100) NOT NULL,
  `address` varchar(100) NOT NULL,
  `mobile` int(11) NOT NULL,
  `email` varchar(100) NOT NULL,
  `order_status` varchar(255) NOT NULL,
  `order_at` datetime NOT NULL,
  `payment_type` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

the order item details will be stored in shop_order_item table.

CREATE TABLE `shop_order_item` (
  `id` int(11) NOT NULL,
  `order_id` int(11) NOT NULL,
  `product_id` int(11) NOT NULL,
  `item_price` double NOT NULL,
  `quantity` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

and the paymen details will be stored in shop_payment table.

CREATE TABLE `shop_payment` (
  `id` int(11) NOT NULL,
  `order_id` int(11) NOT NULL,
  `payment_status` varchar(255) NOT NULL,
  `payment_response` text NOT NULL,
  `create_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

Step3: Customer Shipping Details
As we have already covered product add to cart, checkout and review order details before placing order. So now we will place order and get customer shipping details. We will design HTML form in user.php file to ask customer to enter shipping details to save before making payment. Then the form will take to payment page to handle payment.

<h2>Customer Shipping Details</h2>	
<div class="col-md-8">						
	<form class="form-horizontal" method="post" enctype="multipart/form-data" action="payment.php">
		<div class="form-group">
			<div class="col-sm-6"> 
				<input type="text" class="form-control" placeholder="First Name" name="firstName" required />
			</div>
		</div>
		<div class="form-group">
			<div class="col-sm-6"> 
				<input type="text" class="form-control" placeholder="Last Name" name="lastName" required />
			</div>
		</div>
		<div class="form-group">
			<div class="col-sm-6"> 
				<textarea class="form-control" rows="5" placeholder="Address" name="address" required ></textarea>
			</div>
		</div>
		<div class="form-group">
			<div class="col-sm-8"> 
				<input type="number" class="form-control" min="9" placeholder="Contact number" name="contactNumber" required />
			</div>
		</div>
		<div class="form-group">
			<div class="col-sm-6"> 
				<input type="email" class="form-control" placeholder="Email" name="emailAddress" required />
			</div>
		</div>
		<div class="form-group">
			<div class="col-sm-4"> 
				<input class="btn btn-primary" type="submit" name="proceedPayment" value="Proceed to payment"/>
			</div>
		</div>
	</form>					
</div>		

Step4: Save Order Details
Now we will handle functionality to save order details into table shop_order with customer shipping details.


<?php
if(!empty($_POST["proceedPayment"])) {
	$firstName = $_POST ['firstName'];
	$lastName = $_POST ['lastName'];
    $address = $_POST ['address'];
    $contactNumber = $_POST ['contactNumber'];
    $emailAddress = $_POST ['emailAddress'];	
	$insertOrderSQL = "INSERT INTO shop_order(member_id, name, address, mobile, email, order_status,
 order_at, payment_type)
VALUES('".$member_id."', '".$firstName." ".$lastName."', '".$address."',
 '".$contactNumber."', '".$emailAddress."', 'PENDING',
 '".date("Y-m-d H:i:s")."', 'PAYPAL')";
	mysqli_query($conn, $insertOrderSQL) or die("database error:". mysqli_error($conn));	
	$order_id = mysqli_insert_id($conn);	
}
?>

we will also save order item details into table shop_order_item.

<?php
if($order_id) {	
	if(isset($_SESSION["products"]) && count($_SESSION["products"])>0) { 
		foreach($_SESSION["products"] as $product){	
			$insertOrderItem = "INSERT INTO shop_order_item(order_id, product_id, item_price, quantity)
VALUES('".$order_id."', '".$product["product_code"]."',  '". $product["product_price"]."', 
'".$product["product_qty"]."')";
			mysqli_query($conn, $insertOrderItem) or die("database error:". mysqli_error($conn));	
		}
	}
}?>

Step5: Handle Order Place
Now in payment.php, we will handle order place functionality to handle payment with PayPal. We will pass required value like item_numer, amount, currency_code, notify_url, return_url and more to sent to the PayPal to handle payment.

<form class="form-horizontal" action="https://www.sandbox.paypal.com/cgi-bin/webscr" method="POST">
<input type='hidden' name='business' value='Your Business Email Address'>
<input type='hidden' name='item_name' value='<?php echo $_SESSION["cartItems"]; ?>'> 
<input type='hidden' name='item_number' value="<?php echo $order_id; ?>">
<input type='hidden' name='amount' value='<?php echo $_SESSION["payableAmount"]; ?>'> 
<input type='hidden' name='currency_code' value='USD'> 
<input type='hidden' name='notify_url' value='http://yourdomain.com/shopping-cart-with-paypal-integration/notify.php'>
<input type='hidden' name='return' value='http://yourdomain.com/shopping-cart-with-paypal-integration/success.php'>
<input type="hidden" name="cmd" value="_xclick"> 
<input type="hidden" name="order" value="<?php echo $_SESSION["orderNumber"]; ?>">
<br>
<div class="form-group">
	<div class="col-sm-2"> 
		 <input type="submit" class="btn btn-lg btn-block btn-danger" name="continue_payment" value="Pay Now">				 
	</div>
</div>
</form>

Step6: Process Payment
When Pay Now button clicked, the buyer redirected to PayPal payment page to pay for his order. After successful payment, the notify_url notify.php file called to notify about payment status. The payment verified with PayPal in notify.php and payment updated with order status update.

<?php
include_once("../db_connect.php");
$postData = file_get_contents('php://input');
$postArray = explode('&', $postData);
$postValue = array();
foreach ($postArray as $value) {
	$value = explode ('=', $value);
	if (count($value) == 2)
		$postValue[$value[0]] = urldecode($value[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 ($postValue 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";
}
// The post IPN data back to PayPal to validate the IPN data  
$ch = curl_init("https://www.sandbox.paypal.com/cgi-bin/webscr");
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_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLINFO_HEADER_OUT, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close'));
$res = curl_exec($ch);
if (curl_errno($ch) != 0) {
	error_log(date('[Y-m-d H:i e] '). "Can't connect to PayPal to validate IPN message: " . curl_error($ch) . PHP_EOL, 3, 'app.log');
	curl_close($ch);
	exit;
} else {
	error_log(date('[Y-m-d H:i e] '). "HTTP request of validation request:". curl_getinfo($ch, CURLINFO_HEADER_OUT) ." for IPN payload: $req" . PHP_EOL, 3, 'app.log');
	error_log(date('[Y-m-d H:i e] '). "HTTP response of validation request: $res" . PHP_EOL, 3, 'app.log');
	curl_close($ch);
}
// Inspect IPN validation result and act accordingly
$payment_response = $res;
$tokens = explode("\r\n\r\n", trim($res));
$res = trim(end($tokens));
if (strcmp ($res, "VERIFIED") == 0) {
	$item_name = $_POST['item_name'];
	$item_number = $_POST['item_number'];
	$payment_status = $_POST['payment_status'];
	$payment_amount = $_POST['mc_gross'];
	$payment_currency = $_POST['mc_currency'];
	$txn_id = $_POST['txn_id'];
	$receiver_email = $_POST['receiver_email'];
	$payer_email = $_POST['payer_email'];	
	$isPaymentCompleted = false;
	if($payment_status == "Completed") {
		$isPaymentCompleted = true;
	}
	// insert payment details
	$insertPayment = "INSERT INTO shop_payment(order_id, payment_status, payment_response)VALUES('".$order_id."', '".$payment_status."', '".$payment_response."')";
	mysqli_query($conn, $insertPayment) or die("database error:". mysqli_error($conn));	
	// update order status after payment	
	$updateOrder = "UPDATE shop_order set order_status = 'PAID' WHERE id = '".$item_number."'";
	mysqli_query($conn, $updateOrder) or die("database error:". mysqli_error($conn));	
	error_log(date('[Y-m-d H:i e] '). "Verified IPN: $req ". PHP_EOL, 3, 'app.log');	
} else if (strcmp ($res, "INVALID") == 0) {
	error_log(date('[Y-m-d H:i e] '). "Invalid IPN: $req" . PHP_EOL, 3, 'app.log');
}
?>

Step7: Payment Success
After successful payment at PayPal, it return to success page success.php. We can get basic payment details from PayPal using $_GET method like transaction ID, gross payment amount, currency code, and payment status. You can cross check payment details with stored payment details to display order payment success page.

You may also like:


You can view the live demo from the Demo link and can download the script from the Download link below.
Demo Download

9 thoughts on “Shopping Cart with PayPal Integration in PHP

  1. how to solve this ……….. Sorry, we can’t complete your purchase at this time
    Please return to the merchant and choose another way to pay

    1. Thanks for comment!. It seems you have not provided valid PayPal account details to integrate it. Please provide us source code.

    1. its working correctly at my end. Please provide your script to debug issue.

  2. Everything works until succes.php
    the error is:
    Demo – Shopping Cart with PayPal Integration in PHP

    Notice: Undefined index: tx in C:\xampp\htdocs\shopping-cart-with-paypal-integration-in-php\success.php on line 14

    Notice: Undefined index: amt in C:\xampp\htdocs\shopping-cart-with-paypal-integration-in-php\success.php on line 15

    Notice: Undefined index: cc in C:\xampp\htdocs\shopping-cart-with-paypal-integration-in-php\success.php on line 16

    Notice: Undefined index: st in C:\xampp\htdocs\shopping-cart-with-paypal-integration-in-php\success.php on line 17
    Your order payment has been successful!

    I used your pack, I only edit the email and links

    Thx

  3. Hello, I get this error:-

    Notice: Undefined index: orderNumber in
    …\payment.php on line 49 Call Stack #TimeMemoryFunctionLocation 10.0006409840{main}( )…\payment.php:0 “>

    looks like is missing and replacing it with orderID (which does exist) something happens- It looks as if some piece of code is missing from the download no?

Comments are closed.