i've managed to create a working shopping cart and my next concern is security. Mostly about the arcitechture and session security.
Thanks in advance! All help is appreciated. Also, if anyone find this cart useful, feel free to use it. : )
session.php
// Check if session is created. If not, then create.
if (session_status() == PHP_SESSION_NONE) {
session_start();
}
db_connect.php
$host = "localhost";
$db_name = "xx";
$username = "xx";
$password = "xx";
try {
$con = new PDO("mysql:host={$host};dbname={$db_name}", $username, $password);
$con->exec("set names utf8");
}
//to handle connection error
catch(PDOException $exception){
echo "Connection error: " . $exception->getMessage();
}
products.php
<?php
$query = "SELECT id, name, price, image FROM shoes ORDER BY id";
$stmt = $con->prepare( $query );
$stmt->execute();
$num = $stmt->rowCount();
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)){
extract($row);
echo "
<div class=\"item\">
<div class=\"product-id\">{$id}</div>
<div class=\"category\">shoes</div>
<div class=\"image\"> <img src=\"images/{$image}\" class=\"product-image\" alt=\"product\"/> </div>
<div class=\"name\"> {$name} </div>
<div class=\"price\"> {$price}</div>
<div class=\"quantity\"><input type=\"text\" value=\"1\" class=\"maara\" /></div>
<input type=\"button\" class=\"lisaa\" value=\"Lisää\"/>
</div>
";
}
?>
ajax.js
function add() {
$(".lisaa").click(function(e) {
var id = $(this).closest(".item").find(".product-id").text();
var category = $(this).closest(".item").find('.category').text();
var quantity = $(this).closest(".item").find('.maara').val();
var action = "add";
$.ajax({
url: 'add_to_cart.php',
type: 'POST',
data: {'id': id, 'category': category, 'quantity': quantity, 'action': action},
beforeSend: function() {
$("#wait").show();
},
complete: function() {
$("#wait").hide();
},
success: function(data) {
if(data.indexOf("error") >= 0) {
$(".success, .errors").hide();
$(".errors").html(data).slideDown();
}
else {
$(".shoppingcart-container").load("cart.php");
$(".errors, .success").hide();
$(".success").html(data).slideDown();
}
},
error: function(request, status, error) {
alert("error!");
}
});
});
}
add_to_cart.php
// Check server request method
if ($_SERVER["REQUEST_METHOD"] == "POST") {
// Check if action is set
if(isset($_POST['action']) ? $_POST['action'] : "") {
// Check if action is "add"
if($_POST['action'] == "add") {
// Error variable.
$error = "";
// Success variable.
$success = "";
// VALIDATE ID
if (isset($_POST['id']) ? $_POST['id'] : "") {
// clean input
$id = test_input($_POST["id"]);
// Check if id is numerical
if (!is_numeric($id)) {
// Show invalid ID as a return data
echo "error: Invalid ID. Not numerical.";
// Add a value to error variable
$error = "Error";
// Exit php
exit;
}
}
// If id doesn't exist
else {
// Show invalid ID as a return data
echo "error: Invalid ID. Empty id.";
// Add a value to error variable
$error = "Error";
// Exit php
exit;
}
// VALIDATE Category
if (isset($_POST['category']) ? $_POST['category'] : "") {
// clean input
$category = test_input($_POST["category"]);
// Category must match your product categories
if(!preg_match('[shoes|shirts]', $category)) {
// Show invalid category as a return data
echo "error: invalid category.";
// Add a value to error variable
$error = "Error";
// Exit php
exit;
}
}
// If category doesn't exist
else {
// Show invalid category as a return data
echo "error: Invalid category.";
// Add a value to error variable
$error = "Error";
// Exit php
exit;
}
// VALIDATE Quantity
if (isset($_POST['quantity']) ? $_POST['quantity'] : "") {
// clean input
$quantity = test_input($_POST["quantity"]);
// Check if quantity is numerical
if (!is_numeric($quantity)) {
// Show invalid category as a return data
echo "error: Invalid quantity format.";
// Add a value to error variable
$error = "Error";
// Exit php
exit;
}
}
// Check if errors are false
if ($error == false) {
// Connect to database and select row from table, which matches category variable
$query = "SELECT id, name, price, image FROM {$category} WHERE id={$id}";
$stmt = $con->prepare( $query );
$stmt->execute();
}
else {
// Show error as return data
echo "error: errors occurred with db.";
// Add a value to error variable
$error = "Error";
// Exit php
exit;
}
// Check if query contains a row
if($stmt->rowCount() <= 0) {
// Add a value to error variable
$error = "Error";
// exit php
exit;
}
// Get values of the item, which matched our database search
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)){
$name = $row['name'];
$price = $row['price'];
$image = $row['image'];
}
// Check if session variable "cart" exists. If not, then create.
if (!isset($_SESSION['cart']) || empty($_SESSION['cart']))
{
$_SESSION['cart'] = array();
}
// Check if array is set
if(isset($_SESSION['cart']['id'])) {
// If array is set, check if our product id exists in cart already
if(in_array($id, $_SESSION['cart']['id'])) {
foreach($_SESSION['cart']['id'] as $key => $val)
{
if ($val == $id ) {
// Update product quantity
$_SESSION['cart']['quantity'][$key] = $quantity + $_SESSION['cart']['quantity'][$key];
// Show succesfull quantity update message as return data
echo "{$name} x {$quantity} quantity added";
// Add a value to success variable
$success = "{$name} x {$quantity} quantity added";
// Exit php
exit;
}
}
}
}
// If product doesn't exist in cart and errors are false, add new item to cart
if ($error == false) {
$_SESSION['cart']['id'][] = $id;
$_SESSION['cart']['category'][] = $category;
$_SESSION['cart']['name'][] = $name;
$_SESSION['cart']['price'][] = $price;
$_SESSION['cart']['quantity'][] = $quantity;
$_SESSION['cart']['image'][] = $image;
// Show succesfully added message as return data
echo "{$name} x {$quantity} succesfully added";
// Add a value to success variable
$success = "{$name} x {$quantity} succesfully added";
// exit php
exit;
}
}
}
}
cart.php
function showcart() {
// If cart variable is not empty, then do the following
if(!empty($_SESSION['cart'])) {
// Few variables, to collect total amount of items and total price
$total = "";
$counter = "";
// Start shoppingcart div
echo "<div class=\"shoppingcart\">";
// Loop through cart items
foreach ($_SESSION['cart']['id'] as $key => $value) {
// Add product's price into variable
$singleproduct = $_SESSION['cart']['price'][$key];
// Add product's quantity into variable
$quantityproduct = $_SESSION['cart']['quantity'][$key];
// Replace , with . to make calculations
$singleformat = str_replace(',' , '.' , $singleproduct);
// Count product's amount x quantity
$multipleproducts = $singleformat * $quantityproduct;
// Change number formatting
$multipleformat = number_format($multipleproducts, 2, ","," ");
// Create html output, which contains the product information
echo "<div class=\"shoppingcart-items\">";
echo("<div class=\"shoppingcart-image\"><img src=\"images/{$_SESSION['cart']['image'][$key]}\" class=\"shoppingcart-image\"/></div>");
echo("<div class=\"shoppingcart-itemname\">{$_SESSION['cart']['name'][$key]}</div>");
echo("<div class=\"shoppingcart-quantity\"> {$_SESSION['cart']['quantity'][$key]} x </div>");
echo("<div class=\"shoppingcart-price\"> {$multipleformat} €<br /> <span class=\"singleproduct-price\"> ({$singleproduct} / kpl)</span></div>");
// Calculate total price of products
$total += $singleformat * $quantityproduct;
// Calculate total items amount
$counter += $quantityproduct;
// Change total price number format
$totalsum = number_format($total, 2, ","," ");
echo "</div>";
// End foreach loop
}
// End shopping cart div
echo "</div>";
// Create bottom for shopping cart, which contains total amount of items and total price
echo "<div class=\"shoppingcart-bottom\">
<div class=\"summa\"><a href=\"lomake.php\">Kori</a></div>
<div class=\"tuotteiden-maara\">{$counter} tuotetta <br />{$totalsum} €</div>
</div>";
}
// if cart variable is empty, then show the following
else {
echo "<div class=\"shoppingcart\">";
echo "ostoskori on tyhjä";
echo "</div>";
}
}
test_input function
function test_input($data)
{
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
Your Shopping cart cannot be just secured by keeping your session intact, you need to follow PCI compliance in order to make sure your Shopping cart is secured. Some of the possible way of securing the cart flow and meeting PCI Compliance would be :