Skip to content

Commit

Permalink
add pay chat
Browse files Browse the repository at this point in the history
  • Loading branch information
sevelinCa committed Jul 19, 2024
1 parent ec77c0f commit da839b9
Show file tree
Hide file tree
Showing 10 changed files with 169 additions and 10 deletions.
30 changes: 24 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"sequelize-typescript": "^2.1.6",
"sinon": "^18.0.0",
"socket.io": "^4.7.5",
"stripe": "^16.2.0",
"supertest": "^7.0.0",
"swagger-jsdoc": "^6.2.8",
"swagger-ui-express": "^5.0.0",
Expand Down
99 changes: 99 additions & 0 deletions src/controllers/Payment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import express, { Request, Response } from "express";
import Stripe from "stripe";
import dotenv from "dotenv";
import { findOrderById, findProductById } from "../services/paymentService";

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;
const order = await findOrderById(orderId);
if (!order) {
return res.status(404).json({ message: "Order not found" });
}
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);
return {
price_data: {
currency: "usd",
product_data: {
name: productDetails?.name,
images: [productDetails?.image[0]],
},
unit_amount: unit_amount,
},
quantity: item.quantity,
};
})
);
console.log(line_items)


const session = await stripe.checkout.sessions.create({
line_items,
mode: "payment",
success_url: process.env.SUCCESS_PAYMENT_URL,
cancel_url: process.env.CANCEL_PAYMENT_URL,
metadata: {
orderId: orderId,
},
});


res.status(200).json({ url: session.url });
} catch (error: any) {
res.status(500).json({ message: error.message });
}
};

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);
return res.status(400).send(`Webhook Error: ${err.message}`);
}

switch (event.type) {
case "checkout.session.completed":
const session = event.data.object;

try {
const lineItems = await stripe.checkout.sessions.listLineItems(
session.id
);

const orderId = session.metadata.orderId;
const order = await findOrderById(orderId);
if (order) {
order.status = "paid";
await order.save();
} else {
console.error("Order not found:", orderId);
}
} catch (err) {
console.error("Error processing session completed event:", err);
}
break;

case "payment_intent.succeeded":
const paymentIntent = event.data.object;
console.log("Payment Intent succeeded: ", paymentIntent);
break;
case "payment_method.attached":
const paymentMethod = event.data.object;
console.log("Payment Method attached: ", paymentMethod);
break;

default:
console.log(`Unhandled event type ${event.type}`);
}
res.json({ received: true });
};
5 changes: 4 additions & 1 deletion src/controllers/cart.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,10 @@ export const getCart = async (req: Request, res: Response) => {
if (!cart) {
return res.status(404).json({ message: "Cart not found" });
}
const cartitem = await CartItem.findAll({ where: { cartId: cart.cartId } });
const cartitem = await CartItem.findAll({ where: { cartId: cart.cartId }, include: {
model: Product,
as: "Product"
} });

return res.status(200).json({ cartitem });
} catch (error: any) {
Expand Down
5 changes: 3 additions & 2 deletions src/controllers/checkout.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { v4 as uuidv4 } from 'uuid';


export const createOrder = async (req: Request, res: Response) => {
const { userId, deliveryAddress, paymentMethod } = req.body;
const { userId, deliveryAddress, paymentMethod,client } = req.body;
if(!userId || !deliveryAddress || !paymentMethod) {
return res.status(400).json({ message: 'All fields are required' })
}
Expand Down Expand Up @@ -37,7 +37,8 @@ export const createOrder = async (req: Request, res: Response) => {
paymentMethod,
status: 'pending',
products: orderItems,
totalAmount: totalAmount
totalAmount: totalAmount,
client
});
await CartItem.destroy({ where: { cartId: cart.cartId } });
res.status(201).json({ message: 'Order placed successfully', order });
Expand Down
4 changes: 4 additions & 0 deletions src/database/models/cartitem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ class CartItem extends Model {
foreignKey: "cartId",
as: "cart",
});
CartItem.belongsTo(models.Product,{
foreignKey: "productId",
as: "Product"
})
}
static initModel(sequelize: Sequelize) {
CartItem.init(
Expand Down
1 change: 1 addition & 0 deletions src/database/models/order.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class Order extends Model {
userId: { type: DataTypes.STRING, allowNull: false },
paymentMethod: { type: DataTypes.INTEGER, allowNull: false },
status: { type: DataTypes.STRING, allowNull: false },
client: { type: DataTypes.STRING, allowNull: false },
products: { type: DataTypes.JSONB, allowNull: false },
totalAmount: {type:DataTypes.INTEGER,allowNull: false},
expectedDeliveryDate: {type: DataTypes.DATE, allowNull: true}
Expand Down
7 changes: 7 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,13 @@ app.use(cors({
}
));
app.use(cookieParser());
app.use((req, res, next) => {
if (req.originalUrl === '/webhook') {
next();
} else {
express.json()(req, res, next);
}
});
app.use(express.urlencoded({ extended: true }));
app.use(
session({
Expand Down
15 changes: 14 additions & 1 deletion src/routes/checkout.router.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,20 @@
import express from 'express'
import express, { Request, Response } from 'express'
import { createOrder } from '../controllers/checkout.controller'
import { checkout, webhook } from '../controllers/Payment';
import { VerifyAccessToken } from '../middleware/verfiyToken';
const router = express.Router()

router.post('/checkout', createOrder)

router.post("/payment/:id", VerifyAccessToken, checkout);

router.post('/webhook', express.raw({ type: 'application/json' }), webhook);

router.get("/success", async(req:Request,res:Response)=>{
res.send("Succesfully")
});
router.get("/cancel", async(req:Request,res:Response)=>{
res.send("Cancel")
});

export default router
12 changes: 12 additions & 0 deletions src/services/paymentService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import Order from "../database/models/order"
import Product from "../database/models/product"


export const findOrderById = async (orderId: any)=>{
const order = await Order.findByPk(orderId)
return order
}
export const findProductById = async (productId:any)=>{
const product = await Product.findByPk(productId)
return product
}

0 comments on commit da839b9

Please sign in to comment.