Payment System with BrainTree PayPal using PHP

Course- PHP Tutorial >

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.

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

 

Payment System User Table


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

 

Payment System Products Table


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

 

Payment System Orders Table

 

Payment System with BrainTree PayPal User table design


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 System Cart Table

 

Payment System with BrainTree PayPal cart database design

 

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).

Payment System with BrainTree PayPal cart database design


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.

Payment System with BrainTree PayPal using PHP


Go to Account -> My User scroll down you will find API keys.

Payment System with BrainTree PayPal using PHP


You will find merchantId, publicKey and privateKey

Payment System with BrainTree PayPal using PHP

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;
}
?>

 

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'];


Note: Once your testing is done, create a BrainTree production account and modify the key details.