Are you working for
e-commerce project? Then you should have a better and secure payment
system. I suggest you setup you project with BrainTree API, it is very
powerful and quick. This is accepting most commonly used Cards, PayPal,
Android Pay and etc. This post will explain you how to design a cart and
order system with BrainTree payment process using PHP and MySQL. Take a
quick look the live demo and try demo transaction.
Download Script Live Demo
Database Design
To build the eCommerce system, you have to create four basic tables such as Users, Producs, Orders and Cart.
User Table
User table contains all the users registration details.
CREATE TABLE Users(
user_id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50),
password VARCHAR(100),
email VARCHAR(100)
);
Products Table
This contains all of the product details.
CREATE TABLE Products(
product_id INT PRIMARY KEY AUTO_INCREMENT,
product_name VARCHAR(200),
product_desc TEXT,
price FLOAT
);
Orders Table
User successful orders store here with BrainTree status code.
CREATE TABLE Orders(
order_id INT PRIMARY KEY AUTO_INCREMENT,
user_id_fk INT,
created INT,
price FLOAT,
FOREIGN KEY(user_id_fk) REFERENCES Users(user_id)
);
Cart Table
This table contains all the user cart details. Cart
order_id_fk is a foreign key, it references to Orders
order_id. This will update once the user Order is successful.
CREATE TABLE Cart(
cart_id INT PRIMARY KEY AUTO_INCREMENT,
product_id_fk INT,
user_id_fk INT,
order_id_fk INT,
cart_status enum('0','1') DEFAULT '0',
FOREIGN KEY(product_id_fk) REFERENCES Products(product_id),
FOREIGN KEY(user_id_fk) REFERENCES Users(user_id),
FOREIGN KEY(order_id_fk) REFERENCES Orders(order_id)
);
Payment Form & System Design
This project contains three folders called
js,
includes and
uploads with PHP files.
braintree
-- braintree.php //BrainTree library file
js
-- jquery.min.js
-- jquery.creditCardValidator.js
index.php
cardProcess.php
functions.php
db.php
Payment form contains Card Number, Card Name, Expiry Date and CVV(Secure Number).
HTML5 Code
Simple HTML5 code
<form method="post" id="paymentForm">
Payment details
<ul>
<li>
<label>Card Number </label>
<input type="text" name="card_number" id="card_number" maxlength="20" placeholder="1234 5678 9012 3456"/>
</li>
<li>
<label>Name on Card</label>
<input type="text" name="card_name" id="card_name" placeholder="Srinivas Tamada"/>
</li>
<li class="vertical">
<ul>
<li>
<label>Expires</label>
<input type="text" name="expiry_month" id="expiry_month" maxlength="2" placeholder="MM" />
<input type="text" name="expiry_year" id="expiry_year" maxlength="2" placeholder="YY" />
</li>
<li>
<label>CVV</label>
<input type="text" name="cvv" id="cvv" maxlength="3" placeholder="123" />
</li>
</ul>
</li>
<li>
<input type="submit" id="paymentButton" value="Proceed" disabled="true" class="disable">
</li>
</ul>
</form>
<div id="orderInfo"></div>
CSS Code
*{margin: 0px; padding:0px;}
ul {list-style: none;}
label{padding:8px 0px 8px 0px;}
#paymentForm label
{
color: #555;
display: block;
font-size: 14px;
font-weight: 400;
}
#paymentForm input[type=text]
{
background-color: #FFFFFF;
border: 1px solid #E5E5E5;
color: #333333;
display: block;
font-size: 18px;
height: 32px;
padding: 0 5px;
width: 275px;
}
#paymentForm li {margin: 8px 0;}
#orderInfo{display:none}
.disable{opacity: 0.2}
.vertical li
{
float: left;
width: 140px;
}
JavaScript
Validating the payment form using Regular Expressions.
<script src="js/jquery.min.js"></script>
<script src="js/jquery.creditCardValidator.js"></script>
<script>
$(document).ready(function()
{
/* Form Validation */
$("#paymentForm input[type=text]").on("keyup",function()
{
var cardValid=$("#card_number").attr('rel');
var C=$("#card_name").val();
var M=$("#expiry_month").val();
var Y=$("#expiry_year").val();
var CVV=$("#cvv").val();
var expName =/^[a-z ,.'-]+$/i;
var expMonth = /^01|02|03|04|05|06|07|08|09|10|11|12$/;
var expYear = /^16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31$/;
var expCVV=/^[0-9]{3,3}$/;
if(cardValid>0 && expName.test(C) && expMonth.test(M) && expYear.test(Y)
&& expCVV.test(CVV) && parseInt(cardCheck)>0)
{
$('#paymentButton').prop('disabled', false);
$('#paymentButton').removeClass('disable');
}
else
{
$('#paymentButton').prop('disabled', true);
$('#paymentButton').addClass('disable');
}
});
/* Card Validation */
cardValidate();
/*Payment Form */
$("#paymentForm").submit(function()
{
//.......
});
});
</script>
Card Validation
Credit Card Validation using
jquery.validateCreditCard plugin.
/* Credit Card Type Check */
function cardValidate()
{
$('#card_number').validateCreditCard(function(result)
{
var N=$(this).val();
var C=$(this).attr("class");
$(this).attr("class","");
if(result && N.length>0)
{
$(this).addClass(result.card_type.name);
if(result.valid && result.length_valid && result.luhn_valid)
{
$(this).addClass('valid');
$(this).attr("rel","1");
}
else
{
$(this).attr("rel","1");
}
}
else
{
$(this).removeClass(C);
}
});
}
Ajax Payment Process
BrainTree Payment process with Jquery Ajax, here
$(this).serialize() get all the form input values and posting to
cardProcess.php. Once order is successful, use will get the Order status message.
/*Payment Form */
$("#paymentForm").submit(function()
{
var datastring = $(this).serialize();
$.ajax({
type: "POST",
url: "cardProcess.php",
data: datastring,
dataType: "json",
beforeSend: function(){ $("#paymentButton").val('Processing..') },
success: function(data)
{
$.each(data.OrderStatus, function(i,data)
{
var HTML;
if(data)
{
$("#paymentGrid").slideUp("slow");
$("#orderInfo").fadeIn("slow");
if(data.status == '1')
{
HTML="Order <span>"+data.orderID+"</span> has been created successfully.";
}
else if(data.status == '2')
{
HTML="Transaction has been failed, please use other card.";
}
else
{
HTML="Card number is not valid, please use other card.";
}
$("#orderInfo").html(HTML);
}
});
},
error: function(){ alert('Network Error'); }
});
return false;
});
BrainTree Integration
Create a sandbox account at
sandbox.braintreegateway.com for testing process.
Go to
Account ->
My User scroll down you will find API keys.
You will find
merchantId,
publicKey and
privateKey
cardProcess.php
Here you have to modify with your BrainTree merchandID, pulicKey and
privateKey. This is update Orders table, once the transaction is
successful. Always maintain/store
cart total price value in session. Once testing is done, you can modify environment value from
sandbox to
production.
<?php
include 'db.php';
include 'functions.php';
$session_price =$_SESSION['session_price']; //Cart Total Price
if($_SERVER["REQUEST_METHOD"] == "POST" )
{
$card_number=str_replace("+","",$_POST['card_number']);
$card_name=$_POST['card_number'];
$expiry_month=$_POST['expiry_month'];
$expiry_year=$_POST['expiry_year'];
$cvv=$_POST['cvv'];
$expirationDate=$expiry_month.'/'.$expiry_year;
require_once 'braintree/Braintree.php';
Braintree_Configuration::environment('sandbox'); // Change to production
Braintree_Configuration::merchantId('Merchant_ID');
Braintree_Configuration::publicKey('Public_Key');
Braintree_Configuration::privateKey('Private_Key');
//BrainTree payment process
$result = Braintree_Transaction::sale(array(
'amount' => $price,
'creditCard' => array(
'number' => $card_number,
'cardholderName' => $card_name,
'expirationDate' => $expirationDate,
'cvv' => $cvv
)
));
if ($result->success)
{
if($result->transaction->id)
{
$braintreeCode=$result->transaction->id;
updateUserOrder($braintreeCode,$session_user_id,$session_price); //Order table update.
}
}
else if ($result->transaction)
{
echo '{"OrderStatus": [{"status":"2"}]}';
}
else
{
echo '{"OrderStatus": [{"status":"0"}]}';
}
}
?>
Update User Order
This will update orders table, based on the BrainTree status code. Cart table status will change
0 to
1 with order id.
<?php
function updateUserOrder($braintreeCode,$session_user_id,$session_price)
{
$db = getDB();
$sql = "INSERT INTO Orders(user_id_fk,created,braintreeCode)VALUES(:user_id,:created,:braintreeCode)";
$stmt = $db->prepare($sql);
$stmt->bindParam("user_id", $session_user_id);
$time=time();
$stmt->bindParam("created", $time);
$stmt->bindParam("braintreeCode", $braintreeCode);
$stmt->execute();
$sql1 = "SELECT order_id FROM Orders WHERE user_id_fk=:user_id ORDER BY order_id DESC LIMIT 1";
$stmt1 = $db-> prepare($sql1);
$stmt1-> bindParam("user_id", $session_user_id);
$stmt1-> execute();
$OrderDetails = $stmt1->fetchAll(PDO::FETCH_OBJ);
$order_id=$OrderDetails[0]->order_id;
$sql2 = "UPDATE Cart SET order_id_fk=:order_id,cart_status='1',price=:price WHERE cart_status='0' AND user_id_fk=:user_id";
$stmt2 = $db-> prepare($sql2);
$stmt2-> bindParam("user_id", $session_user_id);
$stmt2-> bindParam("order_id", $order_id);
$stmt2-> bindParam("price", $session_price);
$stmt2-> execute();
$db = null;
echo '{"OrderStatus": [{"status":"1", "orderID":"'.$order_id.'"}]}';
}
?>
Get User Cart Details
Getting card details based on user session id.
<?php
function getUserCartDetails($session_user_id)
{
$db = getDB();
$sql = "SELECT P.product_name,P.price FROM
Users U, Cart C, Products P WHERE U.user_id=C.user_id_fk AND
P.product_id = C.product_id_fk AND C.user_id_fk=:user_id AND C.cart_status='0'";
$stmt = $db->prepare($sql);
$stmt->bindParam("user_id", $session_user_id);
$stmt->execute();
$getUserCartDetails = $stmt->fetchAll(PDO::FETCH_OBJ);
$db = null;
return $getUserCartDetails;
}
?>
Live Demo
db.php
You have to modify username, password and databaseName values. Make sure enable
PDO extension in PHP.ini.
<?php
function getDB() {
$dbhost="localhost";
$dbuser="username";
$dbpass="password";
$dbname="databaseName";
$dbConnection = new PDO("mysql:host=$dbhost;dbname=$dbname", $dbuser, $dbpass);
$dbConnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $dbConnection;
}
/* User Sessions */
session_start();
$session_user_id=$_SESSION['user_id'];