diff --git a/apps/partner-sas/app/[lang]/hotelreservation/(payment-callback)/payment-callback/page.tsx b/apps/partner-sas/app/[lang]/hotelreservation/(payment-callback)/payment-callback/page.tsx index e079fa300..c8f0a8f00 100644 --- a/apps/partner-sas/app/[lang]/hotelreservation/(payment-callback)/payment-callback/page.tsx +++ b/apps/partner-sas/app/[lang]/hotelreservation/(payment-callback)/payment-callback/page.tsx @@ -1,4 +1,26 @@ -export default async function PaymentCallbackPage() { - // eslint-disable-next-line formatjs/no-literal-string-in-jsx - return
payment-callback
+import { PaymentCallbackPage as PaymentCallbackPagePrimitive } from "@scandic-hotels/booking-flow/pages/PaymentCallbackPage" +import { logger } from "@scandic-hotels/common/logger" + +import type { LangParams, PageArgs } from "@/types/params" + +export default async function PaymentCallbackPage(props: PageArgs) { + const searchParams = await props.searchParams + const params = await props.params + logger.debug(`[payment-callback] callback started`) + const lang = params.lang + + let userAccessToken = null + // TODO fix when auth is implemented + // const session = await auth() + // if (isValidSession(session)) { + // userAccessToken = session.token.access_token + // } + + return ( + + ) } diff --git a/apps/scandic-web/app/[lang]/(live)/(public)/hotelreservation/(payment-callback)/payment-callback/page.tsx b/apps/scandic-web/app/[lang]/(live)/(public)/hotelreservation/(payment-callback)/payment-callback/page.tsx index ab97df53e..ab4d47d21 100644 --- a/apps/scandic-web/app/[lang]/(live)/(public)/hotelreservation/(payment-callback)/payment-callback/page.tsx +++ b/apps/scandic-web/app/[lang]/(live)/(public)/hotelreservation/(payment-callback)/payment-callback/page.tsx @@ -1,23 +1,11 @@ -import { notFound } from "next/navigation" - -import { HandleErrorCallback } from "@scandic-hotels/booking-flow/components/EnterDetails/Payment/PaymentCallback/HandleErrorCallback" -import { HandleSuccessCallback } from "@scandic-hotels/booking-flow/components/EnterDetails/Payment/PaymentCallback/HandleSuccessCallback" -import { PaymentCallbackStatusEnum } from "@scandic-hotels/common/constants/paymentCallbackStatusEnum" -import { - bookingConfirmation, - details, -} from "@scandic-hotels/common/constants/routes/hotelReservation" +import { PaymentCallbackPage as PaymentCallbackPagePrimitive } from "@scandic-hotels/booking-flow/pages/PaymentCallbackPage" import { logger } from "@scandic-hotels/common/logger" -import { getServiceToken } from "@scandic-hotels/common/tokenManager" -import { BookingErrorCodeEnum } from "@scandic-hotels/trpc/enums/bookingErrorCode" -import { getBooking } from "@scandic-hotels/trpc/routers/booking/utils" -import { encrypt } from "@scandic-hotels/trpc/utils/encryption" import { isValidSession } from "@scandic-hotels/trpc/utils/session" -import { serverClient } from "@/lib/trpc/server" - import { auth } from "@/auth" +import type { PaymentCallbackStatusEnum } from "@scandic-hotels/common/constants/paymentCallbackStatusEnum" + import type { LangParams, PageArgs } from "@/types/params" export default async function PaymentCallbackPage( @@ -26,7 +14,6 @@ export default async function PaymentCallbackPage( { status?: PaymentCallbackStatusEnum confirmationNumber?: string - hotel?: string } > ) { @@ -34,121 +21,18 @@ export default async function PaymentCallbackPage( const params = await props.params logger.debug(`[payment-callback] callback started`) const lang = params.lang - const status = searchParams.status - const confirmationNumber = searchParams.confirmationNumber - if (!status || !confirmationNumber) { - logger.error( - `[payment-callback] missing status or confirmationNumber in search params` - ) - notFound() - } - - const returnUrl = details(lang) - const searchObject = new URLSearchParams() - let errorMessage = undefined - - if (status === PaymentCallbackStatusEnum.Cancel) { - searchObject.set("errorCode", BookingErrorCodeEnum.TransactionCancelled) - return ( - - ) - } - - let token = "" + let userAccessToken = null const session = await auth() if (isValidSession(session)) { - token = session.token.access_token - } else { - const serviceToken = await getServiceToken() - if (serviceToken) { - token = serviceToken.access_token - } - } - - if (!token) { - logger.error( - `[payment-callback] no token found for user, cannot fetch booking` - ) - notFound() - } - - const booking = await getBooking(confirmationNumber, params.lang, token) - - const refId = booking?.refId - - if ( - status === PaymentCallbackStatusEnum.Success && - confirmationNumber && - refId - ) { - const expire = Math.floor(Date.now() / 1000) + 60 - const sig = encrypt(expire.toString()) - const confirmationUrl = `${bookingConfirmation(lang)}?RefId=${encodeURIComponent(refId)}` - logger.debug( - `[payment-callback] rendering success callback with confirmation number: ${confirmationNumber}` - ) - - return ( - - ) - } - - if (refId) { - try { - const caller = await serverClient() - const bookingStatus = await caller.booking.status({ - refId, - }) - - const { booking } = bookingStatus - - // TODO: how to handle errors for multiple rooms? - const error = booking.errors.find((e) => e.errorCode) - - errorMessage = - error?.description ?? - `No error message found for booking ${confirmationNumber}, status: ${status}` - - searchObject.set( - "errorCode", - error - ? error.errorCode.toString() - : BookingErrorCodeEnum.TransactionFailed - ) - } catch { - logger.error( - `[payment-callback] failed to get booking status for ${confirmationNumber}, status: ${status}` - ) - searchObject.set("errorCode", BookingErrorCodeEnum.TransactionFailed) - errorMessage = `Failed to get booking status for ${confirmationNumber}, status: ${status}` - } - } - - if (status === PaymentCallbackStatusEnum.Error) { - logger.error( - `[payment-callback] error status received for ${confirmationNumber}, status: ${status}` - ) - searchObject.set("errorCode", BookingErrorCodeEnum.TransactionFailed) - errorMessage = `Failed to get booking status for ${confirmationNumber}, status: ${status}` + userAccessToken = session.token.access_token } return ( - ) } diff --git a/packages/booking-flow/lib/pages/PaymentCallbackPage.tsx b/packages/booking-flow/lib/pages/PaymentCallbackPage.tsx new file mode 100644 index 000000000..709b83dc9 --- /dev/null +++ b/packages/booking-flow/lib/pages/PaymentCallbackPage.tsx @@ -0,0 +1,151 @@ +import { notFound } from "next/navigation" + +import { PaymentCallbackStatusEnum } from "@scandic-hotels/common/constants/paymentCallbackStatusEnum" +import { + bookingConfirmation, + details, +} from "@scandic-hotels/common/constants/routes/hotelReservation" +import { logger } from "@scandic-hotels/common/logger" +import { getServiceToken } from "@scandic-hotels/common/tokenManager" +import { BookingErrorCodeEnum } from "@scandic-hotels/trpc/enums/bookingErrorCode" +import { getBooking } from "@scandic-hotels/trpc/routers/booking/utils" +import { encrypt } from "@scandic-hotels/trpc/utils/encryption" + +import { HandleErrorCallback } from "../components/EnterDetails/Payment/PaymentCallback/HandleErrorCallback" +import { HandleSuccessCallback } from "../components/EnterDetails/Payment/PaymentCallback/HandleSuccessCallback" +import { serverClient } from "../trpc" + +import type { Lang } from "@scandic-hotels/common/constants/language" + +import type { NextSearchParams } from "../types" + +type PaymentCallbackPageProps = { + lang: Lang + searchParams: NextSearchParams + userAccessToken: string | null +} +export async function PaymentCallbackPage({ + lang, + userAccessToken, + searchParams, +}: PaymentCallbackPageProps) { + const { status, confirmationNumber } = searchParams + + if ( + !status || + !confirmationNumber || + typeof confirmationNumber !== "string" || + typeof status !== "string" + ) { + logger.error( + `[payment-callback] missing status or confirmationNumber in search params` + ) + notFound() + } + + const returnUrl = details(lang) + const searchObject = new URLSearchParams() + let errorMessage = undefined + + if (status === PaymentCallbackStatusEnum.Cancel) { + searchObject.set("errorCode", BookingErrorCodeEnum.TransactionCancelled) + return ( + + ) + } + + let token = userAccessToken + if (!token) { + const serviceToken = await getServiceToken() + if (serviceToken) { + token = serviceToken.access_token + } + } + + if (!token) { + logger.error( + `[payment-callback] no token found for user, cannot fetch booking` + ) + notFound() + } + + const booking = await getBooking(confirmationNumber, lang, token) + + const refId = booking?.refId + + if ( + status === PaymentCallbackStatusEnum.Success && + confirmationNumber && + refId + ) { + const expire = Math.floor(Date.now() / 1000) + 60 + const sig = encrypt(expire.toString()) + const confirmationUrl = `${bookingConfirmation(lang)}?RefId=${encodeURIComponent(refId)}` + logger.debug( + `[payment-callback] rendering success callback with confirmation number: ${confirmationNumber}` + ) + + return ( + + ) + } + + if (refId) { + try { + const caller = await serverClient() + const bookingStatus = await caller.booking.status({ + refId, + }) + + const { booking } = bookingStatus + + // TODO: how to handle errors for multiple rooms? + const error = booking.errors.find((e) => e.errorCode) + + errorMessage = + error?.description ?? + `No error message found for booking ${confirmationNumber}, status: ${status}` + + searchObject.set( + "errorCode", + error + ? error.errorCode.toString() + : BookingErrorCodeEnum.TransactionFailed + ) + } catch { + logger.error( + `[payment-callback] failed to get booking status for ${confirmationNumber}, status: ${status}` + ) + searchObject.set("errorCode", BookingErrorCodeEnum.TransactionFailed) + errorMessage = `Failed to get booking status for ${confirmationNumber}, status: ${status}` + } + } + + if (status === PaymentCallbackStatusEnum.Error) { + logger.error( + `[payment-callback] error status received for ${confirmationNumber}, status: ${status}` + ) + searchObject.set("errorCode", BookingErrorCodeEnum.TransactionFailed) + errorMessage = `Failed to get booking status for ${confirmationNumber}, status: ${status}` + } + + return ( + + ) +} diff --git a/packages/booking-flow/package.json b/packages/booking-flow/package.json index e661dac8c..c1431bdc6 100644 --- a/packages/booking-flow/package.json +++ b/packages/booking-flow/package.json @@ -61,7 +61,6 @@ "./pages/*": "./lib/pages/*.tsx", "./providers/BookingConfirmationProvider": "./lib/providers/BookingConfirmationProvider.tsx", "./searchType": "./lib/misc/searchType.ts", - "./stores/booking-confirmation": "./lib/stores/booking-confirmation/index.ts", "./stores/bookingCode-filter": "./lib/stores/bookingCode-filter.ts", "./stores/enter-details": "./lib/stores/enter-details/index.ts", "./stores/enter-details/types": "./lib/stores/enter-details/types.ts", diff --git a/packages/common/package.json b/packages/common/package.json index 45c42cc7a..2aeb71a8d 100644 --- a/packages/common/package.json +++ b/packages/common/package.json @@ -27,6 +27,7 @@ "./constants/rateType": "./constants/rateType.ts", "./constants/routes/*": "./constants/routes/*.ts", "./constants/signatureHotels": "./constants/signatureHotels.ts", + "./constants/paymentCallbackStatus": "./constants/paymentCallbackStatus.ts", "./dataCache": "./dataCache/index.ts", "./dt": "./dt/dt.ts", "./dt/utils/hasOverlappingDates": "./dt/utils/hasOverlappingDates.ts",