diff --git a/packages/app-store/paypal/api/add.ts b/packages/app-store/paypal/api/add.ts index bab1b9390c..79a044786b 100644 --- a/packages/app-store/paypal/api/add.ts +++ b/packages/app-store/paypal/api/add.ts @@ -1,42 +1,40 @@ import type { NextApiRequest, NextApiResponse } from "next"; +import Paypal from "@calcom/app-store/paypal/lib/Paypal"; +import { defaultHandler } from "@calcom/lib/server"; import prisma from "@calcom/prisma"; import config from "../config.json"; -export default async function handler(req: NextApiRequest, res: NextApiResponse) { - if (!req.session?.user?.id) { +async function getHandler(req: NextApiRequest, res: NextApiResponse) { + const teamId = Number(req.query?.teamId); + const userId = req.session?.user?.id; + if (!userId) { return res.status(401).json({ message: "You must be logged in to do this" }); } - const appType = config.type; try { - const alreadyInstalled = await prisma.credential.findFirst({ - where: { - type: appType, - userId: req.session.user.id, - }, - }); - if (alreadyInstalled) { - throw new Error("Already installed"); - } - const installation = await prisma.credential.create({ - data: { - type: appType, - key: {}, - userId: req.session.user.id, - appId: "paypal", - }, - }); + const alreadyInstalled = + (await prisma.credential.count({ + where: { + appId: config.slug, + ...(Boolean(teamId) ? { AND: [{ userId: userId }, { teamId }] } : { userId: userId }), + }, + })) > 0; - if (!installation) { - throw new Error("Unable to create user credential for Paypal"); + if (alreadyInstalled) { + throw new Error("App is already installed"); } + const paypalClient = new Paypal(); + const onboardingLink = await paypalClient.getOnboardingLink(userId); + return res.status(200).json({ url: onboardingLink }); } catch (error: unknown) { if (error instanceof Error) { return res.status(500).json({ message: error.message }); } return res.status(500); } - - return res.status(200).json({ url: "/apps/paypal/setup" }); } + +export default defaultHandler({ + GET: Promise.resolve({ default: getHandler }), +}); diff --git a/packages/app-store/paypal/api/callback.ts b/packages/app-store/paypal/api/callback.ts new file mode 100644 index 0000000000..47879f57ba --- /dev/null +++ b/packages/app-store/paypal/api/callback.ts @@ -0,0 +1,65 @@ +import getInstalledAppPath from "_utils/getInstalledAppPath"; +import type { NextApiRequest, NextApiResponse } from "next"; +import { stringify } from "querystring"; +import { z } from "zod"; + +import { defaultHandler } from "@calcom/lib/server"; +import prisma from "@calcom/prisma"; + +import config from "../config.json"; + +const createCredentials = async (userId: number, merchantIdInPayPal: string) => { + const appType = config.type; + const credentials = await prisma.credential.create({ + data: { + type: appType, + key: { merchantIdInPayPal }, + userId: userId, + appId: "paypal", + }, + }); + + if (!credentials) { + throw new Error("Unable to create user credential for Paypal"); + } +}; + +const queryParametersSchema = z.object({ + merchantId: z.string(), + merchantIdInPayPal: z.string(), + permissionsGranted: z.coerce.boolean(), + accountStatus: z.string().optional(), + consentStatus: z.coerce.boolean(), + productIntentId: z.string(), + isEmailConfirmed: z.coerce.boolean(), + returnMessage: z.string().optional(), + riskStatus: z.string().optional(), +}); + +async function getHandler(req: NextApiRequest, res: NextApiResponse) { + if (!req.session?.user?.id) { + return res.status(401).json({ message: "You must be logged in to do this" }); + } + + try { + const { merchantIdInPayPal, permissionsGranted } = queryParametersSchema.parse(req.query); + if (!permissionsGranted && !merchantIdInPayPal) { + const query = stringify({ + error: "Paypal Onboarding Error", + error_description: "Paypal Onboarding was not fully completed", + }); + res.redirect(`/apps/installed?${query}`); + } + await createCredentials(req.session?.user.id, merchantIdInPayPal); + return res.status(200).json({ url: getInstalledAppPath({ variant: "payment", slug: "paypal" }) }); + } catch (error: unknown) { + if (error instanceof Error) { + return res.status(500).json({ message: error.message }); + } + return res.status(500); + } +} + +export default defaultHandler({ + GET: Promise.resolve({ default: getHandler }), +});