103 lines
3.8 KiB
TypeScript
103 lines
3.8 KiB
TypeScript
// 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<User>({ 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<Group>({ 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;
|
|
};
|