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 status: PaymentCallbackStatusEnum } export async function PaymentCallbackPage({ lang, userAccessToken, searchParams, status, }: PaymentCallbackPageProps) { const { confirmationNumber } = searchParams if ( !status || !confirmationNumber || typeof confirmationNumber !== "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 ( ) }