95 lines
3.7 KiB
TypeScript
95 lines
3.7 KiB
TypeScript
// 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;
|
|
};
|