Skip to content

Commit 4402995

Browse files
authored
Merge branch 'demo-bn-19-07' into ft-seller-dashboard
2 parents b53cc86 + 0cff03d commit 4402995

16 files changed

+223
-26
lines changed

Diff for: package-lock.json

+23-6
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: package.json

+1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
"sequelize-typescript": "^2.1.6",
4848
"sinon": "^18.0.0",
4949
"socket.io": "^4.7.5",
50+
"stripe": "^16.2.0",
5051
"supertest": "^7.0.0",
5152
"swagger-jsdoc": "^6.2.8",
5253
"swagger-ui-express": "^5.0.0",

Diff for: src/controllers/Payment.ts

+99
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import express, { Request, Response } from "express";
2+
import Stripe from "stripe";
3+
import dotenv from "dotenv";
4+
import { findOrderById, findProductById } from "../services/paymentService";
5+
6+
dotenv.config();
7+
8+
const stripe = new Stripe(`${process.env.STRIPE_SECRET_KEY}`);
9+
export const checkout = async (req: Request, res: Response) => {
10+
try {
11+
const orderId = req.params.id;
12+
const order = await findOrderById(orderId);
13+
if (!order) {
14+
return res.status(404).json({ message: "Order not found" });
15+
}
16+
const line_items: any[] = await Promise.all(
17+
order.products.map(async (item: any) => {
18+
const productDetails:any = await findProductById(item.productId);
19+
const unit_amount = Math.round(productDetails!.price * 100);
20+
return {
21+
price_data: {
22+
currency: "usd",
23+
product_data: {
24+
name: productDetails?.name,
25+
images: [productDetails?.image[0]],
26+
},
27+
unit_amount: unit_amount,
28+
},
29+
quantity: item.quantity,
30+
};
31+
})
32+
);
33+
console.log(line_items)
34+
35+
36+
const session = await stripe.checkout.sessions.create({
37+
line_items,
38+
mode: "payment",
39+
success_url: process.env.SUCCESS_PAYMENT_URL,
40+
cancel_url: process.env.CANCEL_PAYMENT_URL,
41+
metadata: {
42+
orderId: orderId,
43+
},
44+
});
45+
46+
47+
res.status(200).json({ url: session.url });
48+
} catch (error: any) {
49+
res.status(500).json({ message: error.message });
50+
}
51+
};
52+
53+
export const webhook = async (req: Request, res: Response) => {
54+
const sig: any = req.headers["stripe-signature"];
55+
const webhookSecret: any = process.env.WEBHOOK_SECRET_KEY;
56+
let event: any;
57+
try {
58+
event = stripe.webhooks.constructEvent(req.body, sig, webhookSecret);
59+
} catch (err: any) {
60+
console.log(`⚠️ Webhook signature verification failed.`, err.message);
61+
return res.status(400).send(`Webhook Error: ${err.message}`);
62+
}
63+
64+
switch (event.type) {
65+
case "checkout.session.completed":
66+
const session = event.data.object;
67+
68+
try {
69+
const lineItems = await stripe.checkout.sessions.listLineItems(
70+
session.id
71+
);
72+
73+
const orderId = session.metadata.orderId;
74+
const order = await findOrderById(orderId);
75+
if (order) {
76+
order.status = "paid";
77+
await order.save();
78+
} else {
79+
console.error("Order not found:", orderId);
80+
}
81+
} catch (err) {
82+
console.error("Error processing session completed event:", err);
83+
}
84+
break;
85+
86+
case "payment_intent.succeeded":
87+
const paymentIntent = event.data.object;
88+
console.log("Payment Intent succeeded: ", paymentIntent);
89+
break;
90+
case "payment_method.attached":
91+
const paymentMethod = event.data.object;
92+
console.log("Payment Method attached: ", paymentMethod);
93+
break;
94+
95+
default:
96+
console.log(`Unhandled event type ${event.type}`);
97+
}
98+
res.json({ received: true });
99+
};

Diff for: src/controllers/cart.controller.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,11 @@ export const getCart = async (req: Request, res: Response) => {
6666
if (!cart) {
6767
return res.status(404).json({ message: "Cart not found" });
6868
}
69-
const cartitem = await CartItem.findAll({ where: { cartId: cart.cartId }, include: {model: Product,as:"Product"}},);
69+
const cartitem = await CartItem.findAll({ where: { cartId: cart.cartId }, include: {
70+
model: Product,
71+
as: "Product"
72+
} });
73+
7074

7175
return res.status(200).json({ cartitem });
7276
} catch (error: any) {

Diff for: src/controllers/checkout.controller.ts

-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import { v4 as uuidv4 } from 'uuid';
77

88
export const createOrder = async (req: Request, res: Response) => {
99
const { userId, deliveryAddress, paymentMethod,client } = req.body;
10-
1110
if(!userId || !deliveryAddress || !paymentMethod) {
1211
return res.status(400).json({ message: 'All fields are required' })
1312
}

Diff for: src/controllers/orderController.ts

+32-5
Original file line numberDiff line numberDiff line change
@@ -69,15 +69,34 @@ export const modifyOrderStatus = async (req: Request, res: Response) => {
6969
export const getAllOrders = async (req: Request, res: Response) => {
7070
try {
7171
const userId = (req as any).token.id;
72-
const vendor = await findVendorByUserId(userId);
72+
const vendorId = req.params.vendorId;
73+
74+
let orders: any;
75+
76+
if(vendorId){
77+
const allOrders: any = await Order.findAll({
78+
include: [{ model: Product, as: 'products' }]
79+
});
7380

74-
let orders;
81+
if(allOrders.length === 0){
82+
return res.status(404).json({ message: "No orders found" });
83+
}
7584

76-
orders = await Order.findAll({ where: { userId }})
85+
orders = allOrders.filter(order =>
86+
order.products.some(product => product.vendorId === vendorId)
87+
)
88+
89+
90+
} else {
91+
orders = await Order.findAll({ where: { userId }})
7792

93+
}
94+
95+
7896
return res.status(200).json(orders);
79-
} catch (error: any) {
80-
return res.status(500).json({ error: error.message });
97+
} catch(error: any){
98+
console.error(error);
99+
return res.status(500).json({ error: error.message})
81100
}
82101
};
83102

@@ -105,6 +124,14 @@ export const getOrder = async (req: Request, res: Response) => {
105124
}
106125
};
107126

127+
export const getSellerOrder = async (req: Request, res: Response) => {
128+
try {
129+
const vendorId = req.params.vendorId;
130+
const orders: any = await Order.findAll();
131+
if (!orders) {
132+
return res.status(404).json({ message: "No order found" });
133+
}
134+
108135
export const getSellerOrder = async (req: Request, res: Response) => {
109136
try {
110137
const vendorId = req.params.vendorId;

Diff for: src/database/config/config.js

-1
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,3 @@ const config = {
2929
};
3030

3131
module.exports = config;
32-

Diff for: src/database/models/cartitem.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class CartItem extends Model {
1616
});
1717
CartItem.belongsTo(models.Product,{
1818
foreignKey: "productId",
19-
as:"Product"
19+
as: "Product"
2020
})
2121
}
2222
static initModel(sequelize: Sequelize) {

Diff for: src/database/models/order.ts

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ class Order extends Model {
2525
client: { type: DataTypes.STRING, allowNull: false },
2626
paymentMethod: { type: DataTypes.INTEGER, allowNull: false },
2727
status: { type: DataTypes.STRING, allowNull: false },
28+
client: { type: DataTypes.STRING, allowNull: false },
2829
products: { type: DataTypes.JSONB, allowNull: false },
2930
totalAmount: { type: DataTypes.INTEGER, allowNull: false },
3031
expectedDeliveryDate: { type: DataTypes.DATE, allowNull: true },

Diff for: src/database/seeders/20240522075149-seed-orders.js

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ module.exports = {
1313

1414
const [products] = await queryInterface.sequelize.query(`
1515
SELECT "productId","name","image","price" FROM "Products"
16+
1617
LIMIT 3;
1718
`);
1819

Diff for: src/helpers/generateToken.ts

+22-4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
12
import jwt from "jsonwebtoken";
23
import User from "../database/models/user";
34
import dotenv from "dotenv";
@@ -7,10 +8,27 @@ import { where } from "sequelize";
78
dotenv.config();
89

910
const generateToken = async (userData: User) => {
10-
const vendor = await Vendor.findOne({
11-
where: { userId: userData?.userId },
12-
});
13-
const vendorId = vendor ? vendor.vendorId : null;
11+
const vendor = await Vendor.findOne({
12+
where: { userId: userData?.userId },
13+
});
14+
const vendorId = vendor ? vendor.vendorId : null;
15+
16+
return jwt.sign(
17+
{
18+
role: userData.role,
19+
email: userData.email,
20+
id: userData.userId,
21+
vendor: vendorId,
22+
password: userData.password,
23+
},
24+
"crafters1234",
25+
{
26+
expiresIn: "1d",
27+
}
28+
);
29+
};
30+
31+
export { generateToken };
1432

1533
return jwt.sign(
1634
{

Diff for: src/index.ts

+7
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,13 @@ app.use(
5959
);
6060

6161
app.use(cookieParser());
62+
app.use((req, res, next) => {
63+
if (req.originalUrl === '/webhook') {
64+
next();
65+
} else {
66+
express.json()(req, res, next);
67+
}
68+
});
6269
app.use(express.urlencoded({ extended: true }));
6370
app.use(
6471
session({

Diff for: src/routes/checkout.router.ts

+14-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,20 @@
1-
import express from 'express'
1+
import express, { Request, Response } from 'express'
22
import { createOrder } from '../controllers/checkout.controller'
3+
import { checkout, webhook } from '../controllers/Payment';
4+
import { VerifyAccessToken } from '../middleware/verfiyToken';
35
const router = express.Router()
46

57
router.post('/checkout', createOrder)
68

9+
router.post("/payment/:id", VerifyAccessToken, checkout);
10+
11+
router.post('/webhook', express.raw({ type: 'application/json' }), webhook);
12+
13+
router.get("/success", async(req:Request,res:Response)=>{
14+
res.send("Succesfully")
15+
});
16+
router.get("/cancel", async(req:Request,res:Response)=>{
17+
res.send("Cancel")
18+
});
19+
720
export default router

0 commit comments

Comments
 (0)