95 lines
2.5 KiB
TypeScript
95 lines
2.5 KiB
TypeScript
|
import type { NextApiRequest, NextApiResponse } from "next";
|
||
|
import z from "zod";
|
||
|
|
||
|
import Paypal from "@calcom/app-store/paypal/lib/Paypal";
|
||
|
import { findPaymentCredentials } from "@calcom/features/ee/payments/api/paypal-webhook";
|
||
|
import { IS_PRODUCTION } from "@calcom/lib/constants";
|
||
|
import { getErrorFromUnknown } from "@calcom/lib/errors";
|
||
|
import prisma from "@calcom/prisma";
|
||
|
|
||
|
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||
|
try {
|
||
|
// Look if it's get
|
||
|
if (req.method !== "GET") {
|
||
|
throw new Error("Invalid method");
|
||
|
}
|
||
|
|
||
|
// Look if bookingUid it's provided in query params using zod
|
||
|
const parseRequest = captureRequestSchema.safeParse(req.query);
|
||
|
if (!parseRequest.success) {
|
||
|
throw new Error("Request is malformed");
|
||
|
}
|
||
|
|
||
|
// Get bookingUid and token from query params
|
||
|
const { bookingUid, token } = parseRequest.data;
|
||
|
|
||
|
// Get booking credentials
|
||
|
const booking = await prisma.booking.findUnique({
|
||
|
where: {
|
||
|
uid: bookingUid,
|
||
|
},
|
||
|
select: {
|
||
|
id: true,
|
||
|
userId: true,
|
||
|
},
|
||
|
});
|
||
|
|
||
|
if (!booking) {
|
||
|
throw new Error("Booking not found");
|
||
|
}
|
||
|
|
||
|
const credentials = await findPaymentCredentials(booking?.id);
|
||
|
|
||
|
if (!credentials) {
|
||
|
throw new Error("Credentials not found");
|
||
|
}
|
||
|
|
||
|
// Get paypal instance
|
||
|
const paypalClient = new Paypal(credentials);
|
||
|
|
||
|
// capture payment
|
||
|
const capture = await paypalClient.captureOrder(token);
|
||
|
|
||
|
if (!capture) {
|
||
|
res.redirect(`/booking/${bookingUid}?paypalPaymentStatus=failed`);
|
||
|
}
|
||
|
if (IS_PRODUCTION) {
|
||
|
res.redirect(`/booking/${bookingUid}?paypalPaymentStatus=success`);
|
||
|
} else {
|
||
|
// For cal.dev, paypal sandbox doesn't send webhooks
|
||
|
const updateBooking = prisma.booking.update({
|
||
|
where: {
|
||
|
uid: bookingUid,
|
||
|
},
|
||
|
data: {
|
||
|
paid: true,
|
||
|
},
|
||
|
});
|
||
|
const updatePayment = prisma.payment.update({
|
||
|
where: {
|
||
|
id: booking?.id,
|
||
|
},
|
||
|
data: {
|
||
|
success: true,
|
||
|
},
|
||
|
});
|
||
|
await Promise.all([updateBooking, updatePayment]);
|
||
|
res.redirect(`/booking/${bookingUid}?paypalPaymentStatus=success`);
|
||
|
}
|
||
|
return;
|
||
|
} catch (_err) {
|
||
|
const err = getErrorFromUnknown(_err);
|
||
|
|
||
|
res.status(200).send({
|
||
|
message: err.message,
|
||
|
stack: IS_PRODUCTION ? undefined : err.stack,
|
||
|
});
|
||
|
res.redirect(`/booking/${req.query.bookingUid}?paypalPaymentStatus=failed`);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
const captureRequestSchema = z.object({
|
||
|
bookingUid: z.string(),
|
||
|
token: z.string(),
|
||
|
});
|