So I am making a webapp integrating the razorpay’s payment gateway,
I am not able to identify why is the order being when I click these
This is Cancel Button on the Razorpay’s popup
This is the button to Confirm Cancel the Payment
when I click here technically the payment is unsuccessful but still the order is being sent, which I could not find a solution for.
especially, when a payment is unsuccessful or cancelled order should not placed.
I tried For the Payment status but still could not achieve the feature to actually not send the order details until the payment is done or successful.
This is how my order controller looks
const placeOrder = async (req, res) => {
try {
const { userId, items, amount, address, color } = req.body
const orderData = {
userId,
items,
address,
amount,
paymentMethod: "COD",
payment: false,
date: Date.now()
}
console.log(orderData)
const newOrder = new orderModel(orderData)
await newOrder.save()
await userModel.findByIdAndUpdate(userId, { cartData: {} })
res.json({ success: true, message: "Order Placed" })
} catch (error) {
console.log(error)
res.json({ success: false, message: error.message })
}
}
// Create Razorpay Order
const placeOrderRazorpay = async (req, res) => {
try {
const { userId, items, amount, address } = req.body;
const newOrder = new orderModel({
userId,
items,
address,
amount,
paymentMethod: "Razorpay",
payment: false, // Payment status is false initially
date: Date.now(),
});
await newOrder.save();
const options = {
amount: amount * 100, // Amount in paise (Razorpay expects paise)
currency: "INR",
receipt: newOrder._id.toString(), // This will be used later to identify the order
};
razorpayInstance.orders.create(options, (err, order) => {
if (err) {
console.log(err);
return res.json({ success: false, message: "Failed to create Razorpay order" });
}
res.json({ success: true, order });
});
} catch (error) {
console.log(error);
res.json({ success: false, message: error.message });
}
};
// Verify Razorpay Payment
const verifyRazorpay = async (req, res) => {
try {
const { razorpay_order_id, razorpay_payment_id, razorpay_signature, userId } = req.body;
// Generate the Razorpay signature from the server-side
const generated_signature = crypto
.createHmac("sha256", process.env.RAZORPAY_KEY_SECRET)
.update(razorpay_order_id + "|" + razorpay_payment_id)
.digest("hex");
// Check if the signature matches
if (generated_signature !== razorpay_signature) {
return res.json({ success: false, message: "Invalid signature" });
}
// Update the order to indicate payment has been completed
const updatedOrder = await orderModel.findByIdAndUpdate(
razorpay_order_id,
{ payment: true }, // Mark payment as true
{ new: true }
);
if (!updatedOrder) {
return res.json({ success: false, message: "Order not found" });
}
// Clear the user's cart data upon successful payment
await userModel.findByIdAndUpdate(userId, { cartData: {} });
res.json({ success: true, message: "Payment verified successfully" });
} catch (error) {
console.log(error);
res.json({ success: false, message: error.message });
}
};
This is how I am handling the verify payment in my frontend
const Verify = () => {
const {
navigate,
token,
backendUrl,
user,
setCartItems,
} = useContext(ShopContext);
const [searchParams] = useSearchParams();
const razorpay_order_id = searchParams.get("order_id");
const razorpay_payment_id = searchParams.get("razorpay_payment_id");
const razorpay_signature = searchParams.get("razorpay_signature");
const [loading, setLoading] = useState(false);
const verifyPayment = async () => {
if (!razorpay_order_id || !razorpay_payment_id || !razorpay_signature || !user._id) {
toast.error("Payment details are incomplete.");
setTimeout(() => navigate("/place-order"), 5000);
return;
}
try {
setLoading(true); // Start loading
const res = await axios.post(
`${backendUrl}/api/order/verifyRazorpay`,
{
razorpay_order_id,
razorpay_payment_id,
razorpay_signature,
userId: user._id,
},
{
headers: { token },
}
);
if (res.data.success) {
toast.success("Payment successful!");
setCartItems({}); // Clear cart after successful payment
setTimeout(() => navigate("/cart"), 3000); // Navigate to cart page after success
} else {
toast.error("Payment failed. If money was deducted, contact support.");
setTimeout(() => navigate("/place-order"), 7000); // Redirect back to place order page if payment fails
}
} catch (err) {
console.log(err);
toast.error("Verification error. Try again.");
setTimeout(() => navigate("/place-order"), 7000); // Redirect back to place order page in case of an error
} finally {
setLoading(false); // Stop loading
}
};
useEffect(() => {
if (razorpay_payment_id && razorpay_signature && razorpay_order_id && token) {
verifyPayment(); // Verify payment if the necessary params are present
} else {
toast.error("Payment not completed.");
setTimeout(() => navigate("/place-order"), 5000); // Redirect if payment details are not valid
}
}, [razorpay_payment_id, razorpay_signature, razorpay_order_id, token]);
Any help regrading this is really appreciated Thank you.