Skip to content

Commit

Permalink
Add Stripe payment gateway
Browse files Browse the repository at this point in the history
  • Loading branch information
elyse502 committed Nov 21, 2024
1 parent b9cfbaf commit 1d4774d
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 2 deletions.
90 changes: 88 additions & 2 deletions backend/controllers/orderController.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
import orderModel from "../models/orderModel.js";
import userModel from "../models/userModel.js";
import Stripe from "stripe";

// global variables
const currency = "USD";
const deliveryCharge = 10;

// gateway initialize
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);

// Placing orders using COD Method
const placeOrder = async (req, res) => {
Expand Down Expand Up @@ -29,7 +37,78 @@ const placeOrder = async (req, res) => {
};

// Placing orders using Stripe Method
const placeOrderStripe = async (req, res) => {};
const placeOrderStripe = async (req, res) => {
try {
const { userId, items, amount, address } = req.body;
const { origin } = req.headers;

const orderData = {
userId,
items,
address,
amount,
paymentMethod: "Stripe",
payment: false,
date: Date.now(),
};

const newOrder = new orderModel(orderData);
await newOrder.save();

const line_items = items.map((item) => ({
price_data: {
currency: currency,
product_data: {
name: item.name,
},
unit_amount: item.price * 100,
},
quantity: item.quantity,
}));

line_items.push({
price_data: {
currency: currency,
product_data: {
name: "Delivery Charges",
},
unit_amount: deliveryCharge * 100,
},
quantity: 1,
});

const session = await stripe.checkout.sessions.create({
success_url: `${origin}/verify?success=true&orderId=${newOrder._id}`,
cancel_url: `${origin}/verify?success=false&orderId=${newOrder._id}`,
line_items,
mode: "payment",
});

res.json({ success: true, session_url: session.url });
} catch (error) {
console.log(error);
res.json({ success: false, message: error.message });
}
};

// Verify Stripe
const verifyStripe = async (req, res) => {
const { orderId, success, userId } = req.body;

try {
if (success === "true") {
await orderModel.findByIdAndUpdate(orderId, { payment: true });
await userModel.findByIdAndUpdate(userId, { cartData: {} });
res.json({ success: true });
} else {
await orderModel.findByIdAndDelete(orderId);
res.json({ success: false });
}
} catch (error) {
console.log(error);
res.json({ success: false, message: error.message });
}
};

// All Orders data for Admin Panel
const allOrders = async (req, res) => {
Expand Down Expand Up @@ -68,4 +147,11 @@ const updateStatus = async (req, res) => {
}
};

export { placeOrder, placeOrderStripe, allOrders, userOrders, updateStatus };
export {
verifyStripe,
placeOrder,
placeOrderStripe,
allOrders,
userOrders,
updateStatus,
};
4 changes: 4 additions & 0 deletions backend/routes/orderRoute.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
allOrders,
userOrders,
updateStatus,
verifyStripe,
} from "../controllers/orderController.js";
import adminAuth from "../middleware/adminAuth.js";
import authUser from "../middleware/auth.js";
Expand All @@ -22,4 +23,7 @@ orderRouter.post("/stripe", authUser, placeOrderStripe);
// user Feature
orderRouter.post("/userorders", authUser, userOrders);

// verify payment
orderRouter.post("/verifyStripe", authUser, verifyStripe);

export default orderRouter;
2 changes: 2 additions & 0 deletions frontend/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import Footer from "./components/Footer";
import SearchBar from "./components/SearchBar";
import { ToastContainer, toast } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
import Verify from "./pages/Verify";

const App = () => {
return (
Expand All @@ -31,6 +32,7 @@ const App = () => {
<Route path="/login" element={<Login />} />
<Route path="/place-order" element={<PlaceOrder />} />
<Route path="/orders" element={<Orders />} />
<Route path="/verify" element={<Verify />} />
</Routes>
<Footer />
</div>
Expand Down
15 changes: 15 additions & 0 deletions frontend/src/pages/PlaceOrder.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,21 @@ const PlaceOrder = () => {
}
break;

// API Calls for Stripe
case "stripe":
const responseStripe = await axios.post(
backendUrl + "/api/order/stripe",
orderData,
{ headers: { token } }
);
if (responseStripe.data.success) {
const { session_url } = responseStripe.data;
window.location.replace(session_url);
} else {
toast.error(responseStripe.data.message);
}
break;

default:
break;
}
Expand Down
49 changes: 49 additions & 0 deletions frontend/src/pages/Verify.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import React, { useContext, useEffect } from "react";
import { ShopContext } from "../context/ShopContext";
import { useSearchParams } from "react-router-dom";
import axios from "axios";
import { toast } from "react-toastify";

const Verify = () => {
const { navigate, token, setCartItems, backendUrl } = useContext(ShopContext);
const [searchParams, setSearchParams] = useSearchParams();

const success = searchParams.get("success");
const orderId = searchParams.get("orderId");

const verifyPayment = async () => {
try {
if (!token) {
return null;
}

const response = await axios.post(
backendUrl + "/api/order/verifyStripe",
{ success, orderId },
{ headers: { token } }
);

if (response.data.success) {
setCartItems({});
navigate("/orders");
} else {
navigate("/cart");
}
} catch (error) {
console.log(error);
toast.error(error.message);
}
};

useEffect(() => {
verifyPayment();
}, [token]);

return (
<div>
{/* Verify */}
</div>
)
};

export default Verify;

0 comments on commit 1d4774d

Please sign in to comment.