From 025c5c8291e5a1a4d0b09e03ac902ab8ade6e6a1 Mon Sep 17 00:00:00 2001 From: Tobias Johansson Date: Wed, 23 Oct 2024 11:51:44 +0000 Subject: [PATCH] Merged in feat/SW-659-payment-send-query-params (pull request #727) feat(SW-659): Receive query params from Planet callbacks * feat(SW-659): read confirmation number from url and update callback url if dev * fix(SW-659): moved callback url into env variable Approved-by: Simon.Emanuelsson --- .../booking-confirmation/page.tsx | 6 ++- .../payment-callback/[lang]/[status]/route.ts | 16 ++++++-- .../EnterDetails/Payment/index.tsx | 39 +++++++++++-------- constants/booking.ts | 2 +- env/client.ts | 4 ++ 5 files changed, 44 insertions(+), 23 deletions(-) diff --git a/app/[lang]/(live)/(public)/hotelreservation/(confirmation)/booking-confirmation/page.tsx b/app/[lang]/(live)/(public)/hotelreservation/(confirmation)/booking-confirmation/page.tsx index 23b5270d4..ef7e818c4 100644 --- a/app/[lang]/(live)/(public)/hotelreservation/(confirmation)/booking-confirmation/page.tsx +++ b/app/[lang]/(live)/(public)/hotelreservation/(confirmation)/booking-confirmation/page.tsx @@ -22,9 +22,11 @@ import type { LangParams, PageArgs } from "@/types/params" export default async function BookingConfirmationPage({ params, -}: PageArgs) { + searchParams, +}: PageArgs) { + const confirmationNumber = searchParams.confirmationNumber const booking = await serverClient().booking.confirmation({ - confirmationNumber: "991697377", + confirmationNumber, }) if (!booking) { diff --git a/app/api/web/payment-callback/[lang]/[status]/route.ts b/app/api/web/payment-callback/[lang]/[status]/route.ts index 4154aff14..baa8e4b8a 100644 --- a/app/api/web/payment-callback/[lang]/[status]/route.ts +++ b/app/api/web/payment-callback/[lang]/[status]/route.ts @@ -1,6 +1,6 @@ import { NextRequest, NextResponse } from "next/server" -import { env } from "process" +import { BOOKING_CONFIRMATION_NUMBER } from "@/constants/booking" import { Lang } from "@/constants/languages" import { bookingConfirmation, @@ -17,14 +17,24 @@ export async function GET( console.log(`[payment-callback] callback started`) const lang = params.lang as Lang const status = params.status - const returnUrl = new URL(`${publicURL}/${payment[lang]}`) - if (status === "success") { + const queryParams = request.nextUrl.searchParams + const confirmationNumber = queryParams.get(BOOKING_CONFIRMATION_NUMBER) + + if (status === "success" && confirmationNumber) { const confirmationUrl = new URL(`${publicURL}/${bookingConfirmation[lang]}`) + confirmationUrl.searchParams.set( + BOOKING_CONFIRMATION_NUMBER, + confirmationNumber + ) + console.log(`[payment-callback] redirecting to: ${confirmationUrl}`) return NextResponse.redirect(confirmationUrl) } + const returnUrl = new URL(`${publicURL}/${payment[lang]}`) + returnUrl.search = queryParams.toString() + if (status === "cancel") { returnUrl.searchParams.set("cancel", "true") } diff --git a/components/HotelReservation/EnterDetails/Payment/index.tsx b/components/HotelReservation/EnterDetails/Payment/index.tsx index 5ad6bdaf9..0da2b79e2 100644 --- a/components/HotelReservation/EnterDetails/Payment/index.tsx +++ b/components/HotelReservation/EnterDetails/Payment/index.tsx @@ -1,14 +1,13 @@ "use client" import { zodResolver } from "@hookform/resolvers/zod" -import { useRouter } from "next/navigation" -import { useEffect, useState } from "react" +import { useRouter, useSearchParams } from "next/navigation" +import { useEffect, useMemo, useState } from "react" import { Label as AriaLabel } from "react-aria-components" import { FormProvider, useForm } from "react-hook-form" import { useIntl } from "react-intl" import { - BOOKING_CONFIRMATION_NUMBER, BookingStatusEnum, PAYMENT_METHOD_TITLES, PaymentMethodEnum, @@ -17,7 +16,9 @@ import { bookingTermsAndConditions, privacyPolicy, } from "@/constants/currentWebHrefs" +import { env } from "@/env/client" import { trpc } from "@/lib/trpc/client" +import { useEnterDetailsStore } from "@/stores/enter-details" import LoadingSpinner from "@/components/LoadingSpinner" import Button from "@/components/TempDesignSystem/Button" @@ -51,6 +52,9 @@ export default function Payment({ const router = useRouter() const lang = useLang() const intl = useIntl() + const queryParams = useSearchParams() + const { firstName, lastName, email, phoneNumber, countryCode } = + useEnterDetailsStore((state) => state.data) const [confirmationNumber, setConfirmationNumber] = useState("") const methods = useForm({ @@ -90,14 +94,15 @@ export default function Payment({ ) useEffect(() => { - if (confirmationNumber && bookingStatus?.data?.paymentUrl) { - // Planet doesn't support query params so we have to store values in session storage - sessionStorage.setItem(BOOKING_CONFIRMATION_NUMBER, confirmationNumber) + if (bookingStatus?.data?.paymentUrl) { router.push(bookingStatus.data.paymentUrl) } - }, [confirmationNumber, bookingStatus, router]) + }, [bookingStatus, router]) function handleSubmit(data: PaymentFormData) { + const allQueryParams = + queryParams.size > 0 ? `?${queryParams.toString()}` : "" + // set payment method to card if saved card is submitted const paymentMethod = isPaymentMethodEnum(data.paymentMethod) ? data.paymentMethod @@ -118,13 +123,13 @@ export default function Payment({ rateCode: "SAVEEU", roomTypeCode: "QC", guest: { - title: "Mr", - firstName: "Test", - lastName: "User", - email: "test.user@scandichotels.com", - phoneCountryCodePrefix: "string", - phoneNumber: "string", - countryCode: "string", + title: "Mr", // TODO: do we need title? + firstName, + lastName, + email, + phoneCountryCodePrefix: phoneNumber.slice(0, 3), + phoneNumber: phoneNumber.slice(3), + countryCode, }, packages: { breakfast: true, @@ -150,9 +155,9 @@ export default function Payment({ phoneCountryCode: "", phoneSubscriber: "", }, - success: `api/web/payment-callback/${lang}/success`, - error: `api/web/payment-callback/${lang}/error`, - cancel: `api/web/payment-callback/${lang}/cancel`, + success: `${env.NEXT_PUBLIC_PAYMENT_CALLBACK_URL}/${lang}/success`, + error: `${env.NEXT_PUBLIC_PAYMENT_CALLBACK_URL}/${lang}/error${allQueryParams}`, + cancel: `${env.NEXT_PUBLIC_PAYMENT_CALLBACK_URL}/${lang}/cancel${allQueryParams}`, }, }) } diff --git a/constants/booking.ts b/constants/booking.ts index 81e23cd23..8f5acb120 100644 --- a/constants/booking.ts +++ b/constants/booking.ts @@ -11,7 +11,7 @@ export enum BedTypeEnum { Unknown = "Unknown", } -export const BOOKING_CONFIRMATION_NUMBER = "bookingConfirmationNumber" +export const BOOKING_CONFIRMATION_NUMBER = "confirmationNumber" export enum PaymentMethodEnum { card = "card", diff --git a/env/client.ts b/env/client.ts index 467100c01..4eafd5592 100644 --- a/env/client.ts +++ b/env/client.ts @@ -5,10 +5,14 @@ export const env = createEnv({ client: { NEXT_PUBLIC_NODE_ENV: z.enum(["development", "test", "production"]), NEXT_PUBLIC_PORT: z.string().default("3000"), + NEXT_PUBLIC_PAYMENT_CALLBACK_URL: z + .string() + .default("/api/web/payment-callback"), }, emptyStringAsUndefined: true, runtimeEnv: { NEXT_PUBLIC_NODE_ENV: process.env.NODE_ENV, NEXT_PUBLIC_PORT: process.env.NEXT_PUBLIC_PORT, + NEXT_PUBLIC_PAYMENT_CALLBACK_URL: `${process.env.NODE_ENV === "development" ? `http://localhost:${process.env.NEXT_PUBLIC_PORT}` : ""}/api/web/payment-callback`, }, })