Integrate Cashfree Payments' Payment Gateway in Your Django App Effortlessly
In this tutorial, we'll integrate Cashfree Payments' payment gateway into a basic e-commerce application built with Django.
/guides/assets/images/og.png
In this tutorial, we'll integrate Cashfree Payments' payment gateway into a basic e-commerce application built with Django. This tutorial will walk you through the steps to set up the application, create orders, and handle payments using the Cashfree Python SDK.
We'll use a basic e-commerce app as our example, which you can find in the GitHub repository for your reference.
Our e-commerce app has the following features:
Try Cashfree Dev Studio: Cashfree offers an SDK & API playground for developers. You can freely explore, experiment, and play with various APIs and SDKs offered by Cashfree Payments.
First, ensure you have Django installed. If not, install it using pip:
1link$pip install django
Create a new Django project and app:
1link$django-admin startproject ecommerce
2link$cd ecommerce
3link$django-admin startapp shop
Install the Cashfree Python SDK using pip:
1link$pip install cashfree_pg
Create a file named cashfree_config.py
in your Django app directory (shop
) and add the following configuration:
1link# shop/cashfree_config.py
2linkfrom cashfree_pg.api_client import Cashfree
3link
4linkCashfree.XClientId = 'YOUR_CLIENT_ID'
5linkCashfree.XClientSecret = 'YOUR_CLIENT_SECRET'
6linkCashfree.XEnvironment = Cashfree.SANDBOX # Use Cashfree.PRODUCTION for live environment
7link
Replace 'YOUR_CLIENT_ID'
and 'YOUR_CLIENT_SECRET'
with your actual Cashfree credentials. You can find the Client ID and Secret from the Developers section of the Cashfree Payments’ Merchant Dashboard.
In views.py
, add the necessary imports and views to handle creating orders and processing payments.
1link# shop/views.py
2linkimport requests
3linkfrom django.shortcuts import render, redirect
4linkfrom django.http import JsonResponse
5linkfrom cashfree_pg.models.create_order_request import CreateOrderRequest
6linkfrom cashfree_pg.api_client import Cashfree
7linkfrom cashfree_pg.models.customer_details import CustomerDetails
8linkfrom cashfree_pg.models.order_meta import OrderMeta
9linkfrom django.views.decorators.csrf import csrf_exempt
10linkimport json
11link
12link# Import Cashfree configuration
13linkfrom .cashfree_config import Cashfree
14link
15linkdef landing_page(request):
16link response = requests.get('<https://fakestoreapi.com/products>')
17link products = response.json()
18link return render(request, 'shop/landing_page.html', {'products': products})
19link
20linkdef cart_page(request):
21link cart = request.session.get('cart', {})
22link cart_items = []
23link for product_id, details in cart.items():
24link cart_items.append({
25link 'id': product_id,
26link 'title': details.get('title', 'No Title'),
27link 'description': details.get('description', ''),
28link 'image': details.get('image', '<https://via.placeholder.com/80>'), # Default placeholder image
29link 'price': details.get('price', 0.0),
30link 'quantity': details.get('quantity', 1)
31link })
32link return render(request, 'shop/cart_page.html', {'cart_items': cart_items})
33link
34link@csrf_exempt
35linkdef create_order(request):
36link if request.method == 'POST':
37link cart_data = request.POST.get('cart')
38link if not cart_data:
39link return JsonResponse({'status': 'error', 'message': 'Cart is empty'})
40link
41link try:
42link cart = json.loads(cart_data)
43link except json.JSONDecodeError:
44link return JsonResponse({'status': 'error', 'message': 'Invalid cart data'})
45link
46link total_amount = 0.0
47link for item in cart.values():
48link try:
49link price = float(item['price'])
50link quantity = int(item['quantity'])
51link total_amount += price * quantity
52link except ValueError as e:
53link return JsonResponse({'status': 'error', 'message': f"Error parsing price or quantity for item {item['id']}"})
54link
55link if total_amount < 1:
56link return JsonResponse({'status': 'error', 'message': 'Total amount must be at least 1'})
57link
58link customer_details = CustomerDetails(customer_id="123", customer_phone="9999999999")
59link create_order_request = CreateOrderRequest(order_amount=total_amount, order_currency="INR", customer_details=customer_details)
60link order_meta = OrderMeta(return_url="<http://localhost:8000/successfull/>")
61link create_order_request.order_meta = order_meta
62link
63link try:
64link api_response = Cashfree().PGCreateOrder("2023-08-01", create_order_request, None, None)
65link payment_session_id = api_response.data.payment_session_id
66link return JsonResponse({'status': 'success', 'payment_session_id': payment_session_id})
67link except Exception as e:
68link return JsonResponse({'status': 'error', 'message': f'Error creating order: {str(e)}'})
69link
70link return JsonResponse({'status': 'error', 'message': 'Invalid request method'})
71link
72linkdef success_page(request):
73link cart = request.session.get('cart', {})
74link cart_items = []
75link for product_id, details in cart.items():
76link cart_items.append({
77link 'id': product_id,
78link 'title': details.get('title', 'No Title'),
79link 'price': details.get('price', 0.0),
80link 'quantity': details.get('quantity', 1)
81link })
82link request.session['cart'] = {}
83link return render(request, 'shop/successfull.html', {'cart_items': cart_items})
landing_page
: Fetches and displays products from the API.cart_page
: Displays the items in the cart.create_order
: Creates an order using the Cashfree API and returns the payment session ID. This method is hit when the "Pay Now" button is clicked.CustomerDetails
, and using CreateOrderRequest
to make an API call to Cashfree.order_meta
is used to set a return URL that Cashfree will redirect to after payment.PGCreateOrder
is called to create the order, and the payment_session_id
is obtained from the response.success_page
: Displays the success message and order details, and clears the cart after successful order completion.Create the necessary HTML templates to handle the cart, payment, and success pages.
landing_page.html
1link<!-- shop/templates/shop/landing_page.html -->
2linkload static %}
3link<!DOCTYPE html>
4link<html lang="en">
5link <head>
6link <meta charset="UTF-8" />
7link <meta name="viewport" content="width=device-width, initial-scale=1.0" />
8link <title>Landing Page</title>
9link <link rel="stylesheet" type="text/css" href=" static 'css/styles.css' %}" />
10link <script src="<https://code.jquery.com/jquery-3.6.0.min.js>"></script>
11link </head>
12link <body>
13link <div class="navbar">
14link <div class="logo">Fakeazon</div>
15link <a href=" url 'cart_page' %}" class="cart">Cart (<span id="cart-count">0</span>)</a>
16link </div>
17link <div class="container">
18link <div class="header">
19link <h1>Get Inspired</h1>
20link <p>
21link Browsing for your next long-haul trip, everyday journey, or just fancy a look at what's new? From community favourites to about-to-sell-out items, see
22link them all here.
23link </p>
24link </div>
25link <div class="filters">
26link <select>
27link <option>All Categories</option>
28link </select>
29link <select>
30link <option>All Colors</option>
31link </select>
32link <select>
33link <option>All Features</option>
34link </select>
35link <select>
36link <option>From ₹0 - ₹1000</option>
37link </select>
38link <select>
39link <option>New In</option>
40link </select>
41link </div>
42link <div class="product-grid">
43link for product in products %}
44link <div class="product-item">
45link <img src="{{ product.image }}" alt="{{ product.title }}" />
46link <h2>{{ product.title }}</h2>
47link <p>₹{{ product.price }}</p>
48link <div class="product-actions">
49link <button
50link class="add-to-cart"
51link data-id="{{ product.id }}"
52link data-title="{{ product.title }}"
53link data-description="{{ product.description }}"
54link data-image="{{ product.image }}"
55link data-price="{{ product.price }}"
56link >
57link Add to cart
58link </button>
59link <div class="quantity-selector" data-id="{{ product.id }}" style="display: none;">
60link <button class="decrease" data-id="{{ product.id }}">-</button>
61link <span class="quantity" data-id="{{ product.id }}">1</span>
62link <button class="increase" data-id="{{ product.id }}">+</button>
63link </div>
64link </div>
65link </div>
66link endfor %}
67link </div>
68link </div>
69link <script>
70link let cart = JSON.parse(localStorage.getItem("cart")) || {};
71link
72link function updateCartCount() {
73link let count = 0;
74link for (let id in cart) {
75link count += cart[id].quantity;
76link }
77link
78link $("#cart-count").text(count);
79link }
80link
81link function updateQuantity(productId, quantity) {
82link if (quantity <= 0) {
83link delete cart[productId];
84link $(`.product-item .add-to-cart[data-id=${productId}]`).show();
85link $(`.product-item .quantity-selector[data-id=${productId}]`).hide();
86link } else {
87link cart[productId].quantity = quantity;
88link $(`.product-item .quantity[data-id=${productId}]`).text(quantity);
89link }
90link localStorage.setItem("cart", JSON.stringify(cart));
91link updateCartCount();
92link }
93link
94link $(document).ready(function () {
95link // Update cart count on page load
96link updateCartCount();
97link
98link $(".add-to-cart").click(function () {
99link const productId = $(this).data("id");
100link const title = $(this).data("title");
101link const description = $(this).data("description");
102link const image = $(this).data("image");
103link const price = $(this).data("price");
104link
105link if (!cart[productId]) {
106link cart[productId] = { id: productId, title, description, image, price, quantity: 1 };
107link }
108link
109link localStorage.setItem("cart", JSON.stringify(cart));
110link updateCartCount();
111link
112link $(this).hide();
113link $(`.product-item .quantity-selector[data-id=${productId}]`).show();
114link });
115link
116link $(".increase").click(function () {
117link const productId = $(this).data("id");
118link const quantity = cart[productId].quantity + 1;
119link updateQuantity(productId, quantity);
120link });
121link
122link $(".decrease").click(function () {
123link const productId = $(this).data("id");
124link const quantity = cart[productId].quantity - 1;
125link updateQuantity(productId, quantity);
126link });
127link });
128link </script>
129link </body>
130link</html>
This template displays a list of products. It handles adding products to the cart and updating quantities.
cart_page.html
1link<!-- shop/templates/shop/cart_page.html -->
2linkload static %}
3link<!DOCTYPE html>
4link<html lang="en">
5link <head>
6link <meta charset="UTF-8" />
7link <meta name="viewport" content="width=device-width, initial-scale=1.0" />
8link <title>Cart Page</title>
9link <link rel="stylesheet" type="text/css" href=" static 'css/styles.css' %}" />
10link <script src="<https://code.jquery.com/jquery-3.6.0.min.js>"></script>
11link <script src="<https://sdk.cashfree.com/js/v3/cashfree.js>"></script>
12link </head>
13link
14link <body>
15link <div class="navbar">
16link <div class="logo">Fakeazon</div>
17link <a href=" url 'cart_page' %}" class="cart">Cart (<span id="cart-count">0</span>)</a>
18link </div>
19link <div class="container">
20link <div class="cart-container">
21link <div class="cart-header">
22link <a href=" url 'landing_page' %}">Continue Shopping</a>
23link <h1>Shopping Cart</h1>
24link </div>
25link <div class="cart-items">
26link <!-- Cart items will be dynamically loaded here -->
27link </div>
28link <form>
29link csrf_token %}
30link <div class="cart-total">
31link <div class="total-amount">Total: ₹<span id="total-amount">0.00</span></div>
32link <button type="button" class="pay-now" disabled>Pay Now</button>
33link </div>
34link </form>
35link </div>
36link </div>
37link <script>
38link const cashfree = Cashfree({
39link mode: "sandbox",
40link });
41link
42link let cart = JSON.parse(localStorage.getItem("cart")) || {};
43link
44link function updateCartCount() {
45link let count = 0;
46link for (let id in cart) {
47link count += cart[id].quantity;
48link }
49link $("#cart-count").text(count);
50link }
51link
52link function updateTotalAmount() {
53link let total = 0;
54link for (let id in cart) {
55link total += parseFloat(cart[id].price) * parseInt(cart[id].quantity);
56link }
57link $("#total-amount").text(total.toFixed(2));
58link if (total > 0) {
59link $(".pay-now").prop("disabled", false);
60link } else {
61link $(".pay-now").prop("disabled", true);
62link }
63link }
64link
65link function updateQuantity(productId, quantity) {
66link if (quantity <= 0) {
67link delete cart[productId];
68link $(`.cart-item[data-id=${productId}]`).remove();
69link } else {
70link cart[productId].quantity = quantity;
71link $(`.cart-item .quantity[data-id=${productId}]`).text(quantity);
72link }
73link localStorage.setItem("cart", JSON.stringify(cart));
74link updateCartCount();
75link updateTotalAmount();
76link }
77link
78link function loadCartItems() {
79link const cartContainer = $(".cart-items");
80link cartContainer.empty();
81link
82link for (let id in cart) {
83link const item = cart[id];
84link const cartItemHtml = `
85link <div class="cart-item" data-id="${item.id}">
86link <img src="${item.image}" alt="${item.title}">
87link <div class="cart-item-details">
88link <h2>${item.title}</h2>
89link <p>${item.description}</p>
90link </div>
91link <div class="cart-item-actions">
92link <button class="decrease" data-id="${item.id}">-</button>
93link <span class="quantity" data-id="${item.id}">${item.quantity}</span>
94link <button class="increase" data-id="${item.id}">+</button>
95link <span class="price">₹${item.price}</span>
96link <button class="delete" data-id="${item.id}">🗑</button>
97link </div>
98link </div>
99link `;
100link cartContainer.append(cartItemHtml);
101link }
102link }
103link
104link $(document).ready(function () {
105link // Load cart items on page load
106link loadCartItems();
107link updateCartCount();
108link updateTotalAmount();
109link
110link // Handle increase and decrease buttons
111link $(document).on("click", ".increase", function () {
112link const productId = $(this).data("id");
113link const quantity = cart[productId].quantity + 1;
114link updateQuantity(productId, quantity);
115link });
116link
117link $(document).on("click", ".decrease", function () {
118link const productId = $(this).data("id");
119link const quantity = cart[productId].quantity - 1;
120link updateQuantity(productId, quantity);
121link });
122link
123link // Handle delete button
124link $(document).on("click", ".delete", function () {
125link const productId = $(this).data("id");
126link updateQuantity(productId, 0);
127link });
128link
129link // Handle Pay Now button click
130link $(".pay-now").click(function () {
131link const csrftoken = $('input[name="csrfmiddlewaretoken"]').val();
132link const cartData = JSON.stringify(cart);
133link console.log("Cart data being sent:", cart);
134link $.ajax({
135link url: "/create-order/",
136link method: "POST",
137link headers: { "X-CSRFToken": csrftoken },
138link data: { cart: cartData },
139link success: function (response) {
140link if (response.status === "success") {
141link const paymentSessionId = response.payment_session_id;
142link const checkoutOptions = {
143link paymentSessionId: paymentSessionId,
144link redirectTarget: "_self",
145link };
146link cashfree.checkout(checkoutOptions);
147link } else {
148link alert("Failed to create order: " + response.message);
149link }
150link },
151link error: function () {
152link alert("Failed to create order. Please try again.");
153link },
154link });
155link });
156link });
157link </script>
158link </body>
159link</html>
This template includes the necessary JavaScript to handle cart operations and initiate the payment process. On clicking the "Pay Now" button, it creates an order and opens the Cashfree checkout page.
success_page.html
1link<!-- shop/templates/shop/successfull.html -->
2linkload static %}
3link<!DOCTYPE html>
4link<html lang="en">
5link <head>
6link <meta charset="UTF-8" />
7link <meta name="viewport" content="width=device-width, initial-scale=1.0" />
8link <title>Order Successful</title>
9link <link rel="stylesheet" type="text/css" href=" static 'css/styles.css' %}" />
10link </head>
11link <body>
12link <div class="container">
13link <div class="success-container">
14link <h1>Order Successful</h1>
15link <p>Thank you for your purchase! Here are your order details:</p>
16link <ul>
17link for item in cart_items %}
18link <li>{{ item.title }} - Quantity: {{ item.quantity }} - Price: ₹{{ item.price }}</li>
19link endfor %}
20link </ul>
21link <p>Redirecting to the landing page in <span id="countdown">10</span> seconds...</p>
22link </div>
23link </div>
24link <script>
25link let countdown = 10;
26link const countdownElement = document.getElementById("countdown");
27link
28link setInterval(() => {
29link countdown -= 1;
30link countdownElement.textContent = countdown;
31link if (countdown <= 0) {
32link localStorage.removeItem("cart");
33link window.location.href = "/";
34link }
35link }, 1000);
36link </script>
37link </body>
38link</html>
This template shows the order success details and redirects the user back to the landing page after 10 seconds, clearing the cart.
To style your e-commerce application, you can use the provided CSS file. Ensure you create a styles.css
file in your static folder and link it to your HTML templates. Here is how you can do it:
styles.css
in the static/css
directory of your Django project.<head>
section:1link<link rel="stylesheet" type="text/css" href="static 'css/styles.css' %}" />
For a detailed CSS styling reference, you can check the styles.css
file in the GitHub repository.
This CSS file will include styles for:
Ensure your Django settings are correctly configured to serve static files during development by including STATICFILES_DIRS
in your settings.py
.
1linkSTATICFILES_DIRS = [
2link os.path.join(BASE_DIR, 'shop/static'),
3link]
In this tutorial, we've walked through the integration of Cashfree Payments' payment gateway into a Django e-commerce application. By following these steps, you can seamlessly handle payments in your Django projects using the Cashfree Python SDK.
You can find the complete source code for this project in the GitHub repository. Feel free to clone it and use it as a reference for your projects.
If you have any questions or run into issues, refer to the Cashfree Documentation for more details or join the Discord community for developer support.