Files
calendar/packages/app-store/hitpay/api/callback.ts
T
Anik Dhabal BabuGitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
a3fc17bc75 fix: add team installation support for HitPay payment integration (#24738)
- Add teamId support to HitPay add.ts installation handler
- Update callback.ts to fetch credentials by teamId for team bookings
- Update webhook.ts to fetch credentials by teamId for team bookings
- Update setup page to accept and handle teamId from query params
- Add permission checks using throwIfNotHaveAdminAccessToTeam
- Ensure credentials are created with teamId for team installs, userId for user installs

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2025-11-12 21:58:17 +05:30

100 lines
2.4 KiB
TypeScript

import type { NextApiRequest, NextApiResponse } from "next";
import qs from "qs";
import { z } from "zod";
import { HttpError as HttpCode } from "@calcom/lib/http-error";
import prisma from "@calcom/prisma";
const PaymentDataSchema = z.object({
id: z.string(),
url: z.string(),
defaultLink: z.string(),
email: z.string(),
});
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
const { reference, status } = req.query;
if (!reference) {
throw new HttpCode({ statusCode: 204, message: "Reference not found" });
}
const payment = await prisma.payment.findFirst({
where: {
externalId: reference as string,
},
select: {
id: true,
amount: true,
bookingId: true,
data: true,
booking: {
select: {
uid: true,
userId: true,
user: {
select: {
email: true,
username: true,
},
},
responses: true,
eventType: {
select: {
slug: true,
teamId: true,
},
},
},
},
},
});
if (!payment) {
throw new HttpCode({ statusCode: 204, message: "Payment not found" });
}
const credential = await prisma.credential.findFirst({
where: {
type: "hitpay_payment",
...(payment.booking?.eventType?.teamId
? { teamId: payment.booking.eventType.teamId }
: { userId: payment.booking?.userId }),
},
});
const key = credential?.key;
if (!key) {
throw new HttpCode({ statusCode: 204, message: "Credential not found" });
}
if (!payment.booking || !payment.booking.user || !payment.booking.eventType) {
throw new HttpCode({ statusCode: 204, message: "Booking not correct" });
}
if (status !== "completed") {
await prisma.booking.update({
where: {
id: payment.bookingId,
},
data: {
status: "CANCELLED",
},
});
const url = `/${payment.booking.user.username}/${payment.booking.eventType.slug}`;
return res.redirect(url);
}
const parsedData = PaymentDataSchema.parse(payment.data);
const queryParams = {
"flag.coep": false,
isSuccessBookingPage: true,
email: parsedData.email,
eventTypeSlug: payment.booking.eventType.slug,
};
const query = qs.stringify(queryParams);
const url = `/booking/${payment.booking.uid}?${query}`;
return res.redirect(url);
}