diff --git a/packages/features/webhooks/lib/constants.ts b/packages/features/webhooks/lib/constants.ts index c91d7c4388..157d8650b3 100644 --- a/packages/features/webhooks/lib/constants.ts +++ b/packages/features/webhooks/lib/constants.ts @@ -7,6 +7,7 @@ export const WEBHOOK_TRIGGER_EVENTS_GROUPED_BY_APP = { WebhookTriggerEvents.BOOKING_CANCELLED, WebhookTriggerEvents.BOOKING_CREATED, WebhookTriggerEvents.BOOKING_RESCHEDULED, + WebhookTriggerEvents.BOOKING_PAID, WebhookTriggerEvents.MEETING_ENDED, WebhookTriggerEvents.BOOKING_REQUESTED, WebhookTriggerEvents.BOOKING_REJECTED, diff --git a/packages/prisma/migrations/20230513235419_add_booking_webhooks/migration.sql b/packages/prisma/migrations/20230513235419_add_booking_webhooks/migration.sql new file mode 100644 index 0000000000..4e2318b888 --- /dev/null +++ b/packages/prisma/migrations/20230513235419_add_booking_webhooks/migration.sql @@ -0,0 +1,9 @@ +-- AlterEnum +-- This migration adds more than one value to an enum. +-- With PostgreSQL versions 11 and earlier, this is not possible +-- in a single migration. This can be worked around by creating +-- multiple migrations, each migration adding only one value to +-- the enum. + + +ALTER TYPE "WebhookTriggerEvents" ADD VALUE 'BOOKING_PAID'; diff --git a/packages/prisma/schema.prisma b/packages/prisma/schema.prisma index 4fabeb25ac..9adfd7067b 100644 --- a/packages/prisma/schema.prisma +++ b/packages/prisma/schema.prisma @@ -498,6 +498,7 @@ enum PaymentOption { enum WebhookTriggerEvents { BOOKING_CREATED + BOOKING_PAID BOOKING_RESCHEDULED BOOKING_REQUESTED BOOKING_CANCELLED diff --git a/packages/trpc/server/routers/viewer/payments.tsx b/packages/trpc/server/routers/viewer/payments.tsx index ec4766e85a..282dcad5af 100644 --- a/packages/trpc/server/routers/viewer/payments.tsx +++ b/packages/trpc/server/routers/viewer/payments.tsx @@ -3,7 +3,9 @@ import { z } from "zod"; import appStore from "@calcom/app-store"; import dayjs from "@calcom/dayjs"; import { sendNoShowFeeChargedEmail } from "@calcom/emails"; +import getWebhooks from "@calcom/features/webhooks/lib/getWebhooks"; import { getTranslation } from "@calcom/lib/server/i18n"; +import sendPayload from "@calcom/lib/server/webhooks/sendPayload"; import type { CalendarEvent } from "@calcom/types/Calendar"; import { TRPCError } from "@trpc/server"; @@ -33,11 +35,13 @@ export const paymentsRouter = router({ }, }); + const payment = booking.payment[0]; + if (!booking) { throw new Error("Booking not found"); } - if (booking.payment[0].success) { + if (payment.success) { throw new TRPCError({ code: "BAD_REQUEST", message: `The no show fee for ${booking.id} has already been charged.`, @@ -77,16 +81,16 @@ export const paymentsRouter = router({ }, attendees: attendeesList, paymentInfo: { - amount: booking.payment[0].amount, - currency: booking.payment[0].currency, - paymentOption: booking.payment[0].paymentOption, + amount: payment.amount, + currency: payment.currency, + paymentOption: payment.paymentOption, }, }; const paymentCredential = await prisma.credential.findFirst({ where: { userId: ctx.user.id, - appId: booking.payment[0].appId, + appId: payment.appId, }, include: { app: true, @@ -107,12 +111,32 @@ export const paymentsRouter = router({ const paymentInstance = new PaymentService(paymentCredential); try { - const paymentData = await paymentInstance.chargeCard(booking.payment[0]); + const paymentData = await paymentInstance.chargeCard(payment); if (!paymentData) { throw new TRPCError({ code: "NOT_FOUND", message: `Could not generate payment data` }); } + const subscriberOptions = { + userId: ctx.user.id || 0, + eventTypeId: booking.eventTypeId || 0, + triggerEvent: WebhookTriggerEvents.BOOKING_PAID, + }; + + const subscribers = await getWebhooks(subscriberOptions); + + await Promise.all( + subscribers.map(async (subscriber) => { + sendPayload(subscriber.secret, WebhookTriggerEvents.BOOKING_PAID, { + ...evt, + bookingId: booking.id, + paymentId: payment.id, + paymentData, + eventTypeId: subscriberOptions.eventTypeId, + }); + }) + ); + await sendNoShowFeeChargedEmail(attendeesListPromises[0], evt); return paymentData;