// Next.js API route support: https://nextjs.org/docs/api-routes/introduction import type {NextApiRequest, NextApiResponse} from "next"; import {app} from "@/firebase"; import {getFirestore, collection, getDocs, setDoc, doc, getDoc, query, where} from "firebase/firestore"; 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"; const db = getFirestore(app); 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; console.log("WEBHOOK: ", JSON.stringify(transactionResult)); if (!transactionResult.transaction.success) return res.status(200).json({ok: false}); const {userID, duration, duration_unit} = transactionResult.intention.extras.creation_extras as { userID: string; duration: number; duration_unit: DurationUnit; }; const userSnapshot = await getDoc(doc(db, "users", userID as string)); if (!userSnapshot.exists() || !duration || !duration_unit) return res.status(404).json({ok: false}); const user = {...userSnapshot.data(), id: userSnapshot.id} as User; 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).toISOString(); await setDoc(userSnapshot.ref, {subscriptionExpirationDate: updatedSubscriptionExpirationDate}, {merge: true}); await setDoc(doc(db, "paypalpayments", 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 groupsSnapshot = await getDocs(query(collection(db, "groups"), where("admin", "==", user.id))); const groups = groupsSnapshot.docs.map((g) => ({...g.data(), id: g.id})) as Group[]; const participants = (await Promise.all( groups.flatMap((x) => x.participants).map(async (x) => ({...(await getDoc(doc(db, "users", x))).data(), id: x})), )) as User[]; const sameExpiryDateParticipants = participants.filter((x) => x.subscriptionExpirationDate === subscriptionExpirationDate); for (const participant of sameExpiryDateParticipants) { await setDoc(doc(db, "users", participant.id), {subscriptionExpirationDate: updatedSubscriptionExpirationDate}, {merge: true}); } } 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; };