Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fx notifications for the checkout #100

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 65 additions & 11 deletions src/controllers/Payment.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,61 @@
import express, { Request, Response } from "express";
import Stripe from "stripe";
import dotenv from "dotenv";
import { findOrderById, findProductById } from "../services/paymentService";
import {
findOrderById,
findProductById,
findUserById,
} from "../services/paymentService";
import { sendOrderConfirmation } from "../services/emailService";

dotenv.config();

const stripe = new Stripe(`${process.env.STRIPE_SECRET_KEY}`);

export const checkout = async (req: Request, res: Response) => {
try {
const orderId = req.params.id;

// Validate orderId
if (!orderId) {
return res.status(400).json({ message: "Order ID is required" });
}

const order = await findOrderById(orderId);

if (!order) {
return res.status(404).json({ message: "Order not found" });
}

// Validate order.products
if (!order.products || !Array.isArray(order.products)) {
return res.status(400).json({ message: "Order products are not valid" });
}

const line_items: any[] = await Promise.all(
order.products.map(async (item: any) => {
const productDetails:any = await findProductById(item.productId);
const unit_amount = Math.round(productDetails!.price * 100);
const productDetails: any = await findProductById(item.productId);

if (!productDetails) {
console.error(`Product with ID ${item.productId} not found`);
throw new Error("Product not found");
}

const unit_amount = Math.round(productDetails.price * 100);

return {
price_data: {
currency: "usd",
product_data: {
name: productDetails?.name,
images: [productDetails?.image[0]],
name: productDetails.name,
images: [productDetails.image[0]],
},
unit_amount: unit_amount,
},
quantity: item.quantity,
};
})
);


const session = await stripe.checkout.sessions.create({
line_items,
Expand All @@ -42,9 +67,9 @@ export const checkout = async (req: Request, res: Response) => {
},
});


res.status(200).json({ url: session.url });
} catch (error: any) {
console.error("Error during checkout process:", error);
res.status(500).json({ message: error.message });
}
};
Expand All @@ -53,27 +78,54 @@ export const webhook = async (req: Request, res: Response) => {
const sig: any = req.headers["stripe-signature"];
const webhookSecret: any = process.env.WEBHOOK_SECRET_KEY;
let event: any;

try {
event = stripe.webhooks.constructEvent(req.body, sig, webhookSecret);
} catch (err: any) {
console.log(`⚠️ Webhook signature verification failed.`, err.message);
console.error(`⚠️ Webhook signature verification failed: ${err.message}`);
return res.status(400).send(`Webhook Error: ${err.message}`);
}

switch (event.type) {
case "checkout.session.completed":
const session = event.data.object;
const session: any = event.data.object as Stripe.Checkout.Session;

// Log session details
console.log("Checkout Session Completed Event:");
console.log("Session ID:", session.id);
console.log("Session Metadata:", session.metadata);
console.log("Session Object:", session);

try {
// Fetch line items to get more order details
const lineItems = await stripe.checkout.sessions.listLineItems(
session.id
);
console.log("Line Items:", lineItems);

const orderId = session.metadata.orderId;

if (!orderId) {
console.error("Order ID not found in session metadata");
return res.status(400).json({ message: "Order ID not found" });
}

const order = await findOrderById(orderId);
console.log("Order:", order);

if (order) {
order.status = "paid";
await order.save();

// Fetch user details and log them
const user = await findUserById(order.userId);
console.log("User:", user);

if (user) {
await sendOrderConfirmation(user, order);
} else {
console.error("User not found for order:", orderId);
}
} else {
console.error("Order not found:", orderId);
}
Expand All @@ -83,16 +135,18 @@ export const webhook = async (req: Request, res: Response) => {
break;

case "payment_intent.succeeded":
const paymentIntent = event.data.object;
const paymentIntent = event.data.object as Stripe.PaymentIntent;
console.log("Payment Intent succeeded: ", paymentIntent);
break;

case "payment_method.attached":
const paymentMethod = event.data.object;
const paymentMethod = event.data.object as Stripe.PaymentMethod;
console.log("Payment Method attached: ", paymentMethod);
break;

default:
console.log(`Unhandled event type ${event.type}`);
}

res.json({ received: true });
};
112 changes: 67 additions & 45 deletions src/controllers/checkout.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,59 +2,81 @@ import Order from "../database/models/order";
import Cart from "../database/models/cart";
import CartItem from "../database/models/cartitem";
import { Request, Response } from "express";
import { v4 as uuidv4 } from 'uuid';
import { v4 as uuidv4 } from "uuid";
import Product from "../database/models/product";

import {
findOrderById,
findProductById,
findUserById,
} from "../services/paymentService";
import { sendOrderConfirmation } from "../services/emailService";
import { notifyVendorsOfSale } from "../services/emailService";

export const createOrder = async (req: Request, res: Response) => {
const { userId, deliveryAddress, paymentMethod,client } = req.body;
if(!userId || !deliveryAddress || !paymentMethod) {
return res.status(400).json({ message: 'All fields are required' })
const { userId, deliveryAddress, paymentMethod, client } = req.body;
if (!userId || !deliveryAddress || !paymentMethod) {
return res.status(400).json({ message: "All fields are required" });
}
try {
const cart = await Cart.findOne({ where: { userId } });
if (!cart) {
return res.status(404).json({ message: "Cart not found" });
}
try {
const cart = await Cart.findOne({ where: { userId } });
if (!cart) {
return res.status(404).json({ message: 'Cart not found' });
}

const cartItems = await CartItem.findAll({ where: { cartId: cart.cartId } });
if (cartItems.length === 0) {
return res.status(400).json({ message: "Your cart is empty" });
}
const cartItems = await CartItem.findAll({
where: { cartId: cart.cartId },
});
if (cartItems.length === 0) {
return res.status(400).json({ message: "Your cart is empty" });
}

const orderItems = cartItems.map(item => ({
productId: item.productId,
quantity: item.quantity,
price: item.price,
status:"pending"
}));
const orderItems = cartItems.map((item) => ({
productId: item.productId,
quantity: item.quantity,
price: item.price,
status: "pending",
}));

const totalAmount = orderItems.reduce((total, item) => total + (item.price * item.quantity), 0);
console.log(orderItems)
const totalAmount = orderItems.reduce(
(total, item) => total + item.price * item.quantity,
0
);
console.log(orderItems);

const order = await Order.create({
orderId: uuidv4(),
deliveryAddress,
userId,
paymentMethod,
status: 'pending',
products: orderItems,
totalAmount: totalAmount,
client
});
for (const item of orderItems) {
const product = await Product.findOne({ where: { productId: item.productId } });
if (product) {
product.quantity -= item.quantity;
if (product.quantity < 0) {
return res.status(400).json({ message: `Not enough stock for product ${product.productId}` });
}
await product.save();
}
const order = await Order.create({
orderId: uuidv4(),
deliveryAddress,
userId,
paymentMethod,
status: "pending",
products: orderItems,
totalAmount: totalAmount,
client,
});
for (const item of orderItems) {
const product = await Product.findOne({
where: { productId: item.productId },
});
if (product) {
product.quantity -= item.quantity;
if (product.quantity < 0) {
return res.status(400).json({
message: `Not enough stock for product ${product.productId}`,
});
}
await CartItem.destroy({ where: { cartId: cart.cartId } });
res.status(201).json({ message: 'Order placed successfully', order });
} catch (error: any) {
res.status(500).json({ message: error.message });
await product.save();
}
}
await CartItem.destroy({ where: { cartId: cart.cartId } });
const user = await findUserById(order.userId);
if (user) {
await sendOrderConfirmation(user, order);
await notifyVendorsOfSale(order);
} else {
console.error("User not found for order:");
}
res.status(201).json({ message: "Order placed successfully", order });
} catch (error: any) {
res.status(500).json({ message: error.message });
}
};
6 changes: 2 additions & 4 deletions src/controllers/orderController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export const getAllOrders = async (req: Request, res: Response) => {

let orders: any;

orders = await Order.findAll({ where: { userId }})
orders = await Order.findAll({ where: { userId } });

return res.status(200).json(orders);
} catch (error: any) {
Expand Down Expand Up @@ -105,8 +105,6 @@ export const getOrder = async (req: Request, res: Response) => {
}
};



export const getSellerOrder = async (req: Request, res: Response) => {
try {
const vendorId = req.params.vendorId;
Expand All @@ -127,7 +125,7 @@ export const getSellerOrder = async (req: Request, res: Response) => {
}
}

console.log("products_____:", products)
console.log("products_____:", products);

res.status(200).send(products);
} catch (error) {
Expand Down
Loading
Loading