// Next.js API route support: https://nextjs.org/docs/api-routes/introduction import type {NextApiRequest, NextApiResponse} from "next"; import {withIronSessionApiRoute} from "iron-session/next"; import {sessionOptions} from "@/lib/session"; import {Group, User} from "@/interfaces/user"; import {DurationUnit, Package, Payment} from "@/interfaces/paypal"; import {v4} from "uuid"; import ShortUniqueId from "short-unique-id"; import axios from "axios"; import {IntentionResult, PaymentIntention, TransactionResult} from "@/interfaces/paymob"; import moment from "moment"; import client from "@/lib/mongodb"; const db = client.db(process.env.MONGODB_DB); export default async function handler(req: NextApiRequest, res: NextApiResponse) { if (req.method === "POST") await post(req, res); } async function post(req: NextApiRequest, res: NextApiResponse) { const transactionResult = req.body as TransactionResult; const authToken = await authenticatePaymob(); console.log("WEBHOOK: ", transactionResult); if (!checkTransaction(authToken, transactionResult.transaction.order.id)) return res.status(404).json({ok: false}); if (!transactionResult.transaction.success) return res.status(400).json({ok: false}); const {userID, duration, duration_unit} = transactionResult.intention.extras.creation_extras as { userID: string; duration: number; duration_unit: DurationUnit; }; const user = await db.collection("users").findOne({ id: userID as string }); if (!user || !duration || !duration_unit) return res.status(404).json({ok: false}); const subscriptionExpirationDate = user.subscriptionExpirationDate; if (!subscriptionExpirationDate) return res.status(200).json({ok: false}); const initialDate = moment(subscriptionExpirationDate).isAfter(moment()) ? moment(subscriptionExpirationDate) : moment(); const updatedSubscriptionExpirationDate = moment(initialDate).add(duration, duration_unit).endOf("day").subtract(2, "hours").toISOString(); await db.collection("users").updateOne( { id: userID as string }, { $set: {subscriptionExpirationDate: updatedSubscriptionExpirationDate, status: "active"} } ); await db.collection("paypalpayments").insertOne({ id: v4(), createdAt: new Date().toISOString(), currency: transactionResult.transaction.currency, orderId: transactionResult.transaction.id, status: "COMPLETED", subscriptionDuration: duration, subscriptionDurationUnit: duration_unit, subscriptionExpirationDate: updatedSubscriptionExpirationDate, userId: userID, value: transactionResult.transaction.amount_cents / 1000, }); if (user.type === "corporate") { const groups = await db.collection("groups").find({ admin: user.id }).toArray(); const participants = (await Promise.all( groups.flatMap((x) => x.participants).map(async (x) => ({...(await db.collection("users").findOne({ id: x}))})), )) as User[]; const sameExpiryDateParticipants = participants.filter( (x) => x.subscriptionExpirationDate === subscriptionExpirationDate && x.status !== "disabled", ); for (const participant of sameExpiryDateParticipants) { await db.collection("users").updateOne( { id: participant.id }, { $set: {subscriptionExpirationDate: updatedSubscriptionExpirationDate, status: "active"} } ); } } res.status(200).json({ ok: true, }); } const authenticatePaymob = async () => { const response = await axios.post<{token: string}>( "https://oman.paymob.com/api/auth/tokens", { api_key: process.env.PAYMOB_API_KEY, }, {headers: {Authorization: `Bearer ${process.env.PAYMOB_SECRET_KEY}`}}, ); return response.data.token; }; const checkTransaction = async (token: string, orderID: number) => { const response = await axios.post("https://oman.paymob.com/api/ecommerce/orders/transaction_inquiry", {auth_token: token, order_id: orderID}); return response.status === 200; };