E-Commerce Platform Integration Guide
This tutorial walks through implementing a complete e-commerce flow using our API platform, from product discovery to checkout.
Table of Contents
- Overview
- Initial Setup
- Product Listing
- Cart Management
- Checkout Process
- Complete Integration Example
- Best Practices
Overview
Our e-commerce APIs provide all the necessary endpoints to build a complete shopping experience:
- Browse products
- Create and manage a shopping cart
- Checkout and payment processing
This guide demonstrates how to integrate these features into your application with proper state management.
React Exclusive Content
All examples, code snippets, and patterns in this documentation are specifically designed for React applications. If you're using another framework, please refer to our general API documentation.
Initial Setup
First, set up your API client and state management:
// api.ts
import axios from "axios";
const api = axios.create({
baseURL: "https://dev-sfapi.unisouk.com",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${YOUR_API_TOKEN}`,
"x-store-id": "YOUR_STORE_ID",
},
});
export default api;
// cartStore.ts - using Zustand
import create from "zustand";
import { persist } from "zustand/middleware";
interface CartState {
cartId: string | null;
setCartId: (id: string) => void;
clearCartId: () => void;
}
const useCartStore = create<CartState>()(
persist(
(set) => ({
cartId: null,
setCartId: (id) => set({ cartId: id }),
clearCartId: () => set({ cartId: null }),
}),
{
name: "cart-storage",
}
)
);
export default useCartStore;
Product Listing
Fetch and display products:
// productList.ts
import { useState, useEffect } from "react";
import api from "./api";
interface Product {
id: string;
name: string;
price: number;
description: string;
imageUrl: string;
}
export const ProductList = () => {
const [products, setProducts] = useState<Product[]>([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
const fetchProducts = async () => {
try {
setLoading(true);
const response = await api.get("/product?limit=100");
setProducts(response.data.data);
} catch (error) {
console.error("Error fetching products:", error);
} finally {
setLoading(false);
}
};
fetchProducts();
}, []);
// Render your product list here
};
Cart Management
Creating a Cart
Always check if a cart exists before creating a new one:
import api from "./api";
import useCartStore from "./cartStore";
export const useCart = () => {
const { cartId, setCartId } = useCartStore();
const ensureCart = async (customerId: string) => {
// If we already have a cartId, use it
if (cartId) return cartId;
// Otherwise create a new cart
try {
const response = await api.post("/cart", {
customerId: customerId,
});
const newCartId = response.data.data.id;
setCartId(newCartId);
return newCartId;
} catch (error) {
console.error("Error creating cart:", error);
throw error;
}
};
return { cartId, ensureCart };
};
Adding Items
Add products to the cart:
export const addToCart = async (cartId: string, product: Product, quantity: number) => {
try {
const response = await api.post("/cart/item", {
cartId: cartId,
variantId: product.id,
quantity: quantity,
price: product.price,
});
return response.data;
} catch (error) {
console.error("Error adding item to cart:", error);
throw error;
}
};
Retrieving Cart Details
Get the current cart contents:
export const getCartDetails = async (cartId: string) => {
try {
const response = await api.get(`/cart/${cartId}`);
return response.data.data;
} catch (error) {
console.error("Error fetching cart details:", error);
throw error;
}
};
Removing Items
Remove a specific item from the cart:
export const removeCartItem = async (cartId: string, variantId: string) => {
try {
const response = await api.delete("/cart/item", {
data: {
cartId: cartId,
variantId: variantId,
},
});
return response.data;
} catch (error) {
console.error("Error removing item from cart:", error);
throw error;
}
};
Deleting a Cart
Clear the entire cart:
import useCartStore from "./cartStore";
export const deleteCart = async () => {
const { cartId, clearCartId } = useCartStore();
if (!cartId) return;
try {
await api.delete(`/cart/${cartId}`);
clearCartId(); // Remove from state/localStorage
} catch (error) {
console.error("Error deleting cart:", error);
throw error;
}
};
Checkout Process
Handle the checkout flow:
export const createOrder = async (cartId: string, customerInfo: any, shippingInfo: any) => {
try {
const orderPayload = {
cartId: cartId,
customerId: customerInfo.id,
channelType: "DEFAULT",
paymentMethod: "CVS",
buyerInfo: customerInfo,
shippingDetail: shippingInfo,
address: shippingInfo.address,
extraData: {},
};
const response = await api.post("/order", orderPayload);
return response.data.data;
} catch (error) {
console.error("Error creating order:", error);
throw error;
}
};
const handleCheckout = async (e: React.FormEvent) => {
e.preventDefault();
console.log("handle Submit");
const orderId = await createOrder(cartId, customerInfo, shippingInfo);
console.log("orderId", orderId);
await razorpay_fn(orderId); // calling razorpay apis
};
this is further explained in Razorpay Payment Integration
Complete Integration Example
Here's how to put everything together in a React component:
import React, { useEffect, useState } from "react";
import api from "./api";
import useCartStore from "./cartStore";
import { useCart, addToCart, getCartDetails, removeCartItem, deleteCart, checkout } from "./cartActions";
interface Product {
id: string;
name: string;
price: number;
}
const ShoppingApp: React.FC = () => {
const [products, setProducts] = useState<Product[]>([]);
const [cart, setCart] = useState<any>(null);
const [loading, setLoading] = useState(true);
const { cartId, ensureCart } = useCart();
const customerId = "customer_123"; // In a real app, get from auth
// Fetch products on load
useEffect(() => {
const fetchProducts = async () => {
try {
const response = await api.get("/product?limit=100");
setProducts(response.data.data);
} catch (error) {
console.error("Error fetching products:", error);
}
};
fetchProducts();
}, []);
// Ensure we have a cart and fetch cart details when cartId changes
useEffect(() => {
const initCart = async () => {
try {
setLoading(true);
await ensureCart(customerId);
if (cartId) {
const cartDetails = await getCartDetails(cartId);
setCart(cartDetails);
}
} catch (error) {
console.error("Error initializing cart:", error);
} finally {
setLoading(false);
}
};
initCart();
}, [cartId, ensureCart, customerId]);
const handleAddToCart = async (product: Product) => {
try {
if (!cartId) {
const newCartId = await ensureCart(customerId);
await addToCart(newCartId, product, 1);
} else {
await addToCart(cartId, product, 1);
}
// Refresh cart
if (cartId) {
const cartDetails = await getCartDetails(cartId);
setCart(cartDetails);
}
} catch (error) {
console.error("Error adding to cart:", error);
}
};
const handleRemoveItem = async (variantId: string) => {
try {
if (cartId) {
await removeCartItem(cartId, variantId);
// Refresh cart
const cartDetails = await getCartDetails(cartId);
setCart(cartDetails);
}
} catch (error) {
console.error("Error removing item:", error);
}
};
const handleCheckout = async () => {
try {
if (!cartId) return;
const customerInfo = {
id: customerId,
name: "John Doe",
email: "john@example.com",
};
const shippingInfo = {
method: "Standard",
address: {
street: "123 Main St",
city: "Anytown",
state: "CA",
zipCode: "12345",
},
};
const orderData = await checkout(cartId, customerInfo, shippingInfo);
console.log("Order created:", orderData);
// Proceed to payment integration here
// For example, call Razorpay as shown in your previous example
// After successful payment
await deleteCart();
} catch (error) {
console.error("Error during checkout:", error);
}
};
if (loading) return <div>Loading...</div>;
return (
<div>
<h1>Product Catalog</h1>
<div className='product-grid'>
{products.map((product) => (
<div key={product.id} className='product-card'>
<h3>{product.name}</h3>
<p>${product.price}</p>
<button onClick={() => handleAddToCart(product)}>Add to Cart</button>
</div>
))}
</div>
{cart && (
<div className='cart-summary'>
<h2>Your Cart</h2>
{cart.items?.length > 0 ? (
<>
{cart.items.map((item: any) => (
<div key={item.variantId} className='cart-item'>
<span>{item.variantId}</span>
<span>Qty: {item.quantity}</span>
<span>${item.price * item.quantity}</span>
<button onClick={() => handleRemoveItem(item.variantId)}>Remove</button>
</div>
))}
<div className='cart-total'>
<strong>Total: ${cart.totalAmount}</strong>
</div>
<button onClick={handleCheckout}>Checkout</button>
</>
) : (
<p>Your cart is empty</p>
)}
</div>
)}
</div>
);
};
export default ShoppingApp;
Best Practices
-
Always check for existing cart before creating a new one: This prevents cart duplication and improves user experience.
-
Persist cart ID: Store the cart ID in localStorage or a state management solution to maintain the cart across page refreshes.
-
Error handling: Implement proper error handling for all API calls, with user-friendly error messages.
-
Loading states: Show loading indicators during API calls to improve user experience.
-
Cart synchronization: Keep the cart state synchronized between the server and client by refreshing cart details after modifications.
-
Clean up on logout: Delete the cart or clear the cart ID when a user logs out.
-
Separate concerns: Split your cart logic from UI components for better maintainability.
-
Validate responses: Always validate API responses before updating the UI to prevent errors.