diff --git a/apps/web/components/eventtype/EventAdvancedTab.tsx b/apps/web/components/eventtype/EventAdvancedTab.tsx index 94573ce76e..43ede47100 100644 --- a/apps/web/components/eventtype/EventAdvancedTab.tsx +++ b/apps/web/components/eventtype/EventAdvancedTab.tsx @@ -321,6 +321,20 @@ export const EventAdvancedTab = ({ eventType, team }: Pick + +
+ ( + onChange(e)} + checked={value} + /> + )} + /> +
{ metadata, hosts: eventType.hosts, successRedirectUrl: eventType.successRedirectUrl || "", + forwardParamsSuccessRedirect: eventType.forwardParamsSuccessRedirect, users: eventType.users, useEventTypeDestinationCalendarEmail: eventType.useEventTypeDestinationCalendarEmail, secondaryEmailId: eventType?.secondaryEmailId || -1, diff --git a/apps/web/public/static/locales/en/common.json b/apps/web/public/static/locales/en/common.json index 4ce7e49161..914114ee6c 100644 --- a/apps/web/public/static/locales/en/common.json +++ b/apps/web/public/static/locales/en/common.json @@ -2314,6 +2314,7 @@ "redirect_to": "Redirect to", "having_trouble_finding_time": "Having trouble finding a time?", "show_more": "Show more", + "forward_params_redirect": "Forward parameters such as ?email=...&name=.... and more", "assignment_description": "Schedule meetings when everyone is available or rotate through members on your team", "lowest": "lowest", "low": "low", diff --git a/packages/app-store/alby/components/AlbyPaymentComponent.tsx b/packages/app-store/alby/components/AlbyPaymentComponent.tsx index a0117042a7..762d1aeef9 100644 --- a/packages/app-store/alby/components/AlbyPaymentComponent.tsx +++ b/packages/app-store/alby/components/AlbyPaymentComponent.tsx @@ -167,6 +167,7 @@ function PaymentChecker(props: PaymentCheckerProps) { successRedirectUrl: props.eventType.successRedirectUrl, query: params, booking: props.booking, + forwardParamsSuccessRedirect: props.eventType.forwardParamsSuccessRedirect, }); } })(); @@ -180,6 +181,7 @@ function PaymentChecker(props: PaymentCheckerProps) { props.booking.status, props.eventType.id, props.eventType.successRedirectUrl, + props.eventType.forwardParamsSuccessRedirect, props.payment.success, searchParams, t, diff --git a/packages/features/bookings/Booker/components/hooks/useBookings.ts b/packages/features/bookings/Booker/components/hooks/useBookings.ts index fd28433348..8ada139610 100644 --- a/packages/features/bookings/Booker/components/hooks/useBookings.ts +++ b/packages/features/bookings/Booker/components/hooks/useBookings.ts @@ -163,6 +163,10 @@ export const useBookings = ({ event, hashedLink, bookingForm, metadata }: IUseBo successRedirectUrl: event?.data?.successRedirectUrl || "", query, booking: responseData, + forwardParamsSuccessRedirect: + event?.data?.forwardParamsSuccessRedirect === undefined + ? true + : event?.data?.forwardParamsSuccessRedirect, }); }, onError: (err, _, ctx) => { @@ -212,6 +216,10 @@ export const useBookings = ({ event, hashedLink, bookingForm, metadata }: IUseBo successRedirectUrl: event?.data?.successRedirectUrl || "", query, booking, + forwardParamsSuccessRedirect: + event?.data?.forwardParamsSuccessRedirect === undefined + ? true + : event?.data?.forwardParamsSuccessRedirect, }); }, }); diff --git a/packages/features/ee/payments/components/Payment.tsx b/packages/features/ee/payments/components/Payment.tsx index 8581ac6d7f..f91440f96b 100644 --- a/packages/features/ee/payments/components/Payment.tsx +++ b/packages/features/ee/payments/components/Payment.tsx @@ -7,8 +7,7 @@ import type { SyntheticEvent } from "react"; import { useEffect, useState } from "react"; import getStripe from "@calcom/app-store/stripepayment/lib/client"; -import { getBookingRedirectExtraParams, useBookingSuccessRedirect } from "@calcom/lib/bookingSuccessRedirect"; -import { WEBAPP_URL } from "@calcom/lib/constants"; +import { useBookingSuccessRedirect } from "@calcom/lib/bookingSuccessRedirect"; import { useCompatSearchParams } from "@calcom/lib/hooks/useCompatSearchParams"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import { Button, CheckboxField } from "@calcom/ui"; @@ -22,6 +21,7 @@ type Props = { eventType: { id: number; successRedirectUrl: EventType["successRedirectUrl"]; + forwardParamsSuccessRedirect: EventType["forwardParamsSuccessRedirect"]; }; user: { username: string | null; @@ -46,24 +46,6 @@ type States = status: "ok"; }; -const getReturnUrl = (props: Props) => { - if (!props.eventType.successRedirectUrl) { - return `${WEBAPP_URL}/booking/${props.booking.uid}`; - } - - const returnUrl = new URL(props.eventType.successRedirectUrl); - const queryParams = getBookingRedirectExtraParams(props.booking); - - Object.entries(queryParams).forEach(([key, value]) => { - if (value === null || value === undefined) { - return; - } - returnUrl.searchParams.append(key, String(value)); - }); - - return returnUrl.toString(); -}; - const PaymentForm = (props: Props) => { const { user: { username }, @@ -96,6 +78,9 @@ const PaymentForm = (props: Props) => { uid: string; email: string | null; location?: string; + payment_intent?: string; + payment_intent_client_secret?: string; + redirect_status?: string; } = { uid: props.booking.uid, email: searchParams?.get("email"), @@ -103,17 +88,23 @@ const PaymentForm = (props: Props) => { if (paymentOption === "HOLD" && "setupIntent" in props.payment.data) { payload = await stripe.confirmSetup({ elements, - confirmParams: { - return_url: getReturnUrl(props), - }, + redirect: "if_required", }); + if (payload.setupIntent) { + params.payment_intent = payload.setupIntent.id; + params.payment_intent_client_secret = payload.setupIntent.client_secret || undefined; + params.redirect_status = payload.setupIntent.status; + } } else if (paymentOption === "ON_BOOKING") { payload = await stripe.confirmPayment({ elements, - confirmParams: { - return_url: getReturnUrl(props), - }, + redirect: "if_required", }); + if (payload.paymentIntent) { + params.payment_intent = payload.paymentIntent.id; + params.payment_intent_client_secret = payload.paymentIntent.client_secret || undefined; + params.redirect_status = payload.paymentIntent.status; + } } if (payload?.error) { @@ -134,6 +125,7 @@ const PaymentForm = (props: Props) => { successRedirectUrl: props.eventType.successRedirectUrl, query: params, booking: props.booking, + forwardParamsSuccessRedirect: props.eventType.forwardParamsSuccessRedirect, }); } }; diff --git a/packages/features/ee/payments/pages/payment.tsx b/packages/features/ee/payments/pages/payment.tsx index 397d66dbc5..f0fc011bfc 100644 --- a/packages/features/ee/payments/pages/payment.tsx +++ b/packages/features/ee/payments/pages/payment.tsx @@ -79,6 +79,7 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) => price: true, currency: true, successRedirectUrl: true, + forwardParamsSuccessRedirect: true, }, }, }, diff --git a/packages/features/eventtypes/lib/getPublicEvent.ts b/packages/features/eventtypes/lib/getPublicEvent.ts index d9556f34f0..f5c4a5ee5f 100644 --- a/packages/features/eventtypes/lib/getPublicEvent.ts +++ b/packages/features/eventtypes/lib/getPublicEvent.ts @@ -92,6 +92,7 @@ const publicEventSelect = Prisma.validator()({ }, }, successRedirectUrl: true, + forwardParamsSuccessRedirect: true, workflows: { include: { workflow: { diff --git a/packages/features/eventtypes/lib/types.ts b/packages/features/eventtypes/lib/types.ts index 3acb0cad2f..7f1da377dd 100644 --- a/packages/features/eventtypes/lib/types.ts +++ b/packages/features/eventtypes/lib/types.ts @@ -102,5 +102,6 @@ export type FormValues = { users: EventTypeSetup["users"]; assignAllTeamMembers: boolean; useEventTypeDestinationCalendarEmail: boolean; + forwardParamsSuccessRedirect: boolean | null; secondaryEmailId?: number; }; diff --git a/packages/lib/bookingSuccessRedirect.ts b/packages/lib/bookingSuccessRedirect.ts index 9d1095ee2b..6120f3b8a6 100644 --- a/packages/lib/bookingSuccessRedirect.ts +++ b/packages/lib/bookingSuccessRedirect.ts @@ -47,14 +47,20 @@ export const useBookingSuccessRedirect = () => { successRedirectUrl, query, booking, + forwardParamsSuccessRedirect, }: { successRedirectUrl: EventType["successRedirectUrl"]; + forwardParamsSuccessRedirect: EventType["forwardParamsSuccessRedirect"]; query: Record; booking: SuccessRedirectBookingType; }) => { if (successRedirectUrl) { const url = new URL(successRedirectUrl); // Using parent ensures, Embed iframe would redirect outside of the iframe. + if (!forwardParamsSuccessRedirect) { + window.parent.location.href = url.toString(); + return; + } const bookingExtraParams = getBookingRedirectExtraParams(booking); const newSearchParams = getNewSeachParams({ query: { diff --git a/packages/lib/defaultEvents.ts b/packages/lib/defaultEvents.ts index f3fffa7060..53c17a3eee 100644 --- a/packages/lib/defaultEvents.ts +++ b/packages/lib/defaultEvents.ts @@ -72,6 +72,7 @@ const commons = { schedule: null, timeZone: null, successRedirectUrl: "", + forwardParamsSuccessRedirect: true, teamId: null, scheduleId: null, availability: [], diff --git a/packages/lib/event-types/getEventTypeById.ts b/packages/lib/event-types/getEventTypeById.ts index 471783a6aa..13678b02f5 100644 --- a/packages/lib/event-types/getEventTypeById.ts +++ b/packages/lib/event-types/getEventTypeById.ts @@ -113,6 +113,7 @@ export const getEventTypeById = async ({ durationLimits: true, assignAllTeamMembers: true, successRedirectUrl: true, + forwardParamsSuccessRedirect: true, currency: true, bookingFields: true, useEventTypeDestinationCalendarEmail: true, diff --git a/packages/lib/test/builder.ts b/packages/lib/test/builder.ts index 7f8fb00dbf..771fb9f074 100644 --- a/packages/lib/test/builder.ts +++ b/packages/lib/test/builder.ts @@ -117,6 +117,7 @@ export const buildEventType = (eventType?: Partial): EventType => { slotInterval: null, metadata: null, successRedirectUrl: null, + forwardParamsSuccessRedirect: true, bookingFields: [], parentId: null, profileId: null, diff --git a/packages/prisma/migrations/20240327165803_forward_parameters_on_success_redirect/migration.sql b/packages/prisma/migrations/20240327165803_forward_parameters_on_success_redirect/migration.sql new file mode 100644 index 0000000000..77406b316a --- /dev/null +++ b/packages/prisma/migrations/20240327165803_forward_parameters_on_success_redirect/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "EventType" ADD COLUMN "forwardParamsSuccessRedirect" BOOLEAN DEFAULT true; diff --git a/packages/prisma/schema.prisma b/packages/prisma/schema.prisma index 3218b17778..a5ca286b71 100644 --- a/packages/prisma/schema.prisma +++ b/packages/prisma/schema.prisma @@ -125,6 +125,7 @@ model EventType { metadata Json? /// @zod.custom(imports.successRedirectUrl) successRedirectUrl String? + forwardParamsSuccessRedirect Boolean? @default(true) workflows WorkflowsOnEventTypes[] /// @zod.custom(imports.intervalLimitsType) bookingLimits Json? diff --git a/packages/prisma/zod-utils.ts b/packages/prisma/zod-utils.ts index 1942089754..f3e969a480 100644 --- a/packages/prisma/zod-utils.ts +++ b/packages/prisma/zod-utils.ts @@ -624,6 +624,7 @@ export const allManagedEventTypeProps: { [k in keyof Omit