Merged in fix/STAY-67-redirect-to-webview-after-gla (pull request #2795)
fix(STAY-67): redirect to webview after guarantee on my stay * fix(STAY-67): redirect to webview after guarantee on my stay * fix(STAY-67): add callback page for guarantee on webview Approved-by: Linus Flood
This commit is contained in:
@@ -1,15 +1,11 @@
|
|||||||
import { notFound } from "next/navigation"
|
import { notFound } from "next/navigation"
|
||||||
|
|
||||||
import { PaymentCallbackStatusEnum } from "@scandic-hotels/common/constants/paymentCallbackStatusEnum"
|
|
||||||
import { myStay } from "@scandic-hotels/common/constants/routes/myStay"
|
import { myStay } from "@scandic-hotels/common/constants/routes/myStay"
|
||||||
import { logger } from "@scandic-hotels/common/logger"
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
import { LoadingSpinner } from "@scandic-hotels/design-system/LoadingSpinner"
|
|
||||||
import { BookingErrorCodeEnum } from "@scandic-hotels/trpc/enums/bookingErrorCode"
|
|
||||||
|
|
||||||
import { serverClient } from "@/lib/trpc/server"
|
import GuaranteeCallbackPage from "@/components/GuaranteeCallback"
|
||||||
|
|
||||||
import GuaranteeCallback from "@/components/HotelReservation/MyStay/Ancillaries/GuaranteeCallback"
|
import type { PaymentCallbackStatusEnum } from "@scandic-hotels/common/constants/paymentCallbackStatusEnum"
|
||||||
import TrackGuarantee from "@/components/HotelReservation/MyStay/TrackGuarantee"
|
|
||||||
|
|
||||||
import type { LangParams, PageArgs } from "@/types/params"
|
import type { LangParams, PageArgs } from "@/types/params"
|
||||||
|
|
||||||
@@ -34,77 +30,16 @@ export default async function GuaranteePaymentCallbackPage(
|
|||||||
if (!status || !confirmationNumber || !refId) {
|
if (!status || !confirmationNumber || !refId) {
|
||||||
notFound()
|
notFound()
|
||||||
}
|
}
|
||||||
const isAncillaryFlow = searchParams.ancillary
|
|
||||||
|
|
||||||
const myStayUrl = `${myStay[lang]}?RefId=${encodeURIComponent(refId)}`
|
const myStayUrl = `${myStay[lang]}?RefId=${encodeURIComponent(refId)}`
|
||||||
const searchObject = new URLSearchParams()
|
|
||||||
|
|
||||||
if (status === PaymentCallbackStatusEnum.Success && confirmationNumber) {
|
return (
|
||||||
if (isAncillaryFlow) {
|
<GuaranteeCallbackPage
|
||||||
return (
|
status={status}
|
||||||
<GuaranteeCallback
|
confirmationNumber={confirmationNumber}
|
||||||
returnUrl={myStayUrl}
|
refId={refId}
|
||||||
refId={refId}
|
myStayUrl={myStayUrl}
|
||||||
confirmationNumber={confirmationNumber}
|
lang={lang}
|
||||||
lang={lang}
|
isAncillaryFlow={!!searchParams.ancillary}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
|
||||||
logger.debug(`[gla-payment-callback] redirecting to: ${myStayUrl}`)
|
|
||||||
return <TrackGuarantee status={status} redirectUrl={myStayUrl} />
|
|
||||||
}
|
|
||||||
|
|
||||||
let errorMessage = undefined
|
|
||||||
|
|
||||||
if (refId) {
|
|
||||||
try {
|
|
||||||
const caller = await serverClient()
|
|
||||||
const bookingStatus = await caller.booking.status({
|
|
||||||
refId,
|
|
||||||
})
|
|
||||||
|
|
||||||
const { booking } = bookingStatus
|
|
||||||
|
|
||||||
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(
|
|
||||||
`[gla-payment-callback] failed to get booking status for ${confirmationNumber}, status: ${status}`
|
|
||||||
)
|
|
||||||
if (status === PaymentCallbackStatusEnum.Cancel) {
|
|
||||||
searchObject.set("errorCode", BookingErrorCodeEnum.TransactionCancelled)
|
|
||||||
} else if (status === PaymentCallbackStatusEnum.Error) {
|
|
||||||
searchObject.set("errorCode", BookingErrorCodeEnum.TransactionFailed)
|
|
||||||
errorMessage = `Failed to get booking status for ${confirmationNumber}, status: ${status}`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (errorMessage) {
|
|
||||||
logger.error(errorMessage)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isAncillaryFlow) {
|
|
||||||
searchObject.set("ancillary", "ancillary")
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<TrackGuarantee
|
|
||||||
status={status}
|
|
||||||
isAncillaryFlow={!!isAncillaryFlow}
|
|
||||||
redirectUrl={`${myStayUrl}&${searchObject.toString()}`}
|
|
||||||
errorMessage={errorMessage}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return <LoadingSpinner />
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
import { notFound } from "next/navigation"
|
||||||
|
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
|
|
||||||
|
import { myStay } from "@/constants/routes/webviews"
|
||||||
|
|
||||||
|
import GuaranteeCallbackPage from "@/components/GuaranteeCallback"
|
||||||
|
|
||||||
|
import type { PaymentCallbackStatusEnum } from "@scandic-hotels/common/constants/paymentCallbackStatusEnum"
|
||||||
|
|
||||||
|
import type { LangParams, PageArgs } from "@/types/params"
|
||||||
|
|
||||||
|
export default async function GuaranteePaymentWebViewCallbackPage(
|
||||||
|
props: PageArgs<
|
||||||
|
LangParams,
|
||||||
|
{
|
||||||
|
status?: PaymentCallbackStatusEnum
|
||||||
|
RefId?: string
|
||||||
|
confirmationNumber?: string
|
||||||
|
ancillary?: string
|
||||||
|
}
|
||||||
|
>
|
||||||
|
) {
|
||||||
|
const searchParams = await props.searchParams
|
||||||
|
const params = await props.params
|
||||||
|
logger.debug(`[gla-payment-callback] callback started`)
|
||||||
|
const lang = params.lang
|
||||||
|
const status = searchParams.status
|
||||||
|
const confirmationNumber = searchParams.confirmationNumber
|
||||||
|
const refId = searchParams.RefId
|
||||||
|
if (!status || !confirmationNumber || !refId) {
|
||||||
|
notFound()
|
||||||
|
}
|
||||||
|
const myStayUrl = `${myStay[lang]}?RefId=${encodeURIComponent(refId)}`
|
||||||
|
|
||||||
|
return (
|
||||||
|
<GuaranteeCallbackPage
|
||||||
|
status={status}
|
||||||
|
confirmationNumber={confirmationNumber}
|
||||||
|
refId={refId}
|
||||||
|
myStayUrl={myStayUrl}
|
||||||
|
lang={lang}
|
||||||
|
isAncillaryFlow={!!searchParams.ancillary}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
100
apps/scandic-web/components/GuaranteeCallback/index.tsx
Normal file
100
apps/scandic-web/components/GuaranteeCallback/index.tsx
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
import { PaymentCallbackStatusEnum } from "@scandic-hotels/common/constants/paymentCallbackStatusEnum"
|
||||||
|
import { logger } from "@scandic-hotels/common/logger"
|
||||||
|
import { LoadingSpinner } from "@scandic-hotels/design-system/LoadingSpinner"
|
||||||
|
import { BookingErrorCodeEnum } from "@scandic-hotels/trpc/enums/bookingErrorCode"
|
||||||
|
|
||||||
|
import { serverClient } from "@/lib/trpc/server"
|
||||||
|
|
||||||
|
import GuaranteeCallback from "@/components/HotelReservation/MyStay/Ancillaries/GuaranteeCallback"
|
||||||
|
import TrackGuarantee from "@/components/HotelReservation/MyStay/TrackGuarantee"
|
||||||
|
|
||||||
|
import type { Lang } from "@scandic-hotels/common/constants/language"
|
||||||
|
|
||||||
|
type GuaranteeMyStayCallbackProps = {
|
||||||
|
lang: Lang
|
||||||
|
myStayUrl: string
|
||||||
|
refId: string
|
||||||
|
status: PaymentCallbackStatusEnum
|
||||||
|
confirmationNumber?: string
|
||||||
|
isAncillaryFlow?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export default async function GuaranteeCallbackPage({
|
||||||
|
lang,
|
||||||
|
myStayUrl,
|
||||||
|
refId,
|
||||||
|
status,
|
||||||
|
confirmationNumber,
|
||||||
|
isAncillaryFlow,
|
||||||
|
}: GuaranteeMyStayCallbackProps) {
|
||||||
|
const searchObject = new URLSearchParams()
|
||||||
|
|
||||||
|
if (status === PaymentCallbackStatusEnum.Success && confirmationNumber) {
|
||||||
|
if (isAncillaryFlow) {
|
||||||
|
return (
|
||||||
|
<GuaranteeCallback
|
||||||
|
returnUrl={myStayUrl}
|
||||||
|
refId={refId}
|
||||||
|
confirmationNumber={confirmationNumber}
|
||||||
|
lang={lang}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
logger.debug(`[gla-payment-callback] redirecting to: ${myStayUrl}`)
|
||||||
|
return <TrackGuarantee status={status} redirectUrl={myStayUrl} />
|
||||||
|
}
|
||||||
|
|
||||||
|
let errorMessage = undefined
|
||||||
|
|
||||||
|
if (refId) {
|
||||||
|
try {
|
||||||
|
const caller = await serverClient()
|
||||||
|
const bookingStatus = await caller.booking.status({
|
||||||
|
refId,
|
||||||
|
})
|
||||||
|
|
||||||
|
const { booking } = bookingStatus
|
||||||
|
|
||||||
|
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(
|
||||||
|
`[gla-payment-callback] failed to get booking status for ${confirmationNumber}, status: ${status}`
|
||||||
|
)
|
||||||
|
if (status === PaymentCallbackStatusEnum.Cancel) {
|
||||||
|
searchObject.set("errorCode", BookingErrorCodeEnum.TransactionCancelled)
|
||||||
|
} else if (status === PaymentCallbackStatusEnum.Error) {
|
||||||
|
searchObject.set("errorCode", BookingErrorCodeEnum.TransactionFailed)
|
||||||
|
errorMessage = `Failed to get booking status for ${confirmationNumber}, status: ${status}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errorMessage) {
|
||||||
|
logger.error(errorMessage)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isAncillaryFlow) {
|
||||||
|
searchObject.set("ancillary", "ancillary")
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TrackGuarantee
|
||||||
|
status={status}
|
||||||
|
isAncillaryFlow={!!isAncillaryFlow}
|
||||||
|
redirectUrl={`${myStayUrl}&${searchObject.toString()}`}
|
||||||
|
errorMessage={errorMessage}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return <LoadingSpinner />
|
||||||
|
}
|
||||||
@@ -18,6 +18,7 @@ import { Typography } from "@scandic-hotels/design-system/Typography"
|
|||||||
import { trpc } from "@scandic-hotels/trpc/client"
|
import { trpc } from "@scandic-hotels/trpc/client"
|
||||||
import { BreakfastPackageEnum } from "@scandic-hotels/trpc/enums/breakfast"
|
import { BreakfastPackageEnum } from "@scandic-hotels/trpc/enums/breakfast"
|
||||||
|
|
||||||
|
import { isWebview } from "@/constants/routes/webviews"
|
||||||
import { env } from "@/env/client"
|
import { env } from "@/env/client"
|
||||||
import {
|
import {
|
||||||
AncillaryStepEnum,
|
AncillaryStepEnum,
|
||||||
@@ -80,7 +81,7 @@ export default function AddAncillaryFlowModal({
|
|||||||
const pathname = usePathname()
|
const pathname = usePathname()
|
||||||
|
|
||||||
const [isPriceDetailsOpen, setIsPriceDetailsOpen] = useState(false)
|
const [isPriceDetailsOpen, setIsPriceDetailsOpen] = useState(false)
|
||||||
const guaranteeRedirectUrl = `${env.NEXT_PUBLIC_NODE_ENV === "development" ? `http://localhost:${env.NEXT_PUBLIC_PORT}` : ""}${guaranteeCallback(lang)}`
|
const guaranteeRedirectUrl = `${env.NEXT_PUBLIC_NODE_ENV === "development" ? `http://localhost:${env.NEXT_PUBLIC_PORT}` : ""}${guaranteeCallback(lang, isWebview(pathname))}`
|
||||||
const deliveryTimeOptions = generateDeliveryOptions()
|
const deliveryTimeOptions = generateDeliveryOptions()
|
||||||
|
|
||||||
const defaultDeliveryTime = deliveryTimeOptions[0].value
|
const defaultDeliveryTime = deliveryTimeOptions[0].value
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
"use client"
|
"use client"
|
||||||
import { zodResolver } from "@hookform/resolvers/zod"
|
import { zodResolver } from "@hookform/resolvers/zod"
|
||||||
|
import { usePathname } from "next/navigation"
|
||||||
import { FormProvider, useForm } from "react-hook-form"
|
import { FormProvider, useForm } from "react-hook-form"
|
||||||
import { useIntl } from "react-intl"
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
@@ -19,6 +20,7 @@ import { LoadingSpinner } from "@scandic-hotels/design-system/LoadingSpinner"
|
|||||||
import { toast } from "@scandic-hotels/design-system/Toast"
|
import { toast } from "@scandic-hotels/design-system/Toast"
|
||||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||||
|
|
||||||
|
import { isWebview } from "@/constants/routes/webviews"
|
||||||
import { env } from "@/env/client"
|
import { env } from "@/env/client"
|
||||||
import { useMyStayStore } from "@/stores/my-stay"
|
import { useMyStayStore } from "@/stores/my-stay"
|
||||||
|
|
||||||
@@ -34,6 +36,7 @@ import styles from "./form.module.css"
|
|||||||
export default function Form() {
|
export default function Form() {
|
||||||
const intl = useIntl()
|
const intl = useIntl()
|
||||||
const lang = useLang()
|
const lang = useLang()
|
||||||
|
const pathname = usePathname()
|
||||||
|
|
||||||
const { confirmationNumber, currencyCode, hotelId, refId, savedCreditCards } =
|
const { confirmationNumber, currencyCode, hotelId, refId, savedCreditCards } =
|
||||||
useMyStayStore((state) => ({
|
useMyStayStore((state) => ({
|
||||||
@@ -56,7 +59,7 @@ export default function Form() {
|
|||||||
resolver: zodResolver(paymentSchema),
|
resolver: zodResolver(paymentSchema),
|
||||||
})
|
})
|
||||||
|
|
||||||
const guaranteeRedirectUrl = `${env.NEXT_PUBLIC_NODE_ENV === "development" ? `http://localhost:${env.NEXT_PUBLIC_PORT}` : ""}${guaranteeCallback(lang)}`
|
const guaranteeRedirectUrl = `${env.NEXT_PUBLIC_NODE_ENV === "development" ? `http://localhost:${env.NEXT_PUBLIC_PORT}` : ""}${guaranteeCallback(lang, isWebview(pathname))}`
|
||||||
|
|
||||||
const { guaranteeBooking, isLoading, handleGuaranteeError } =
|
const { guaranteeBooking, isLoading, handleGuaranteeError } =
|
||||||
useGuaranteeBooking(refId, false, hotelId)
|
useGuaranteeBooking(refId, false, hotelId)
|
||||||
@@ -93,6 +96,7 @@ export default function Form() {
|
|||||||
savedCreditCard ? savedCreditCard.type : PaymentMethodEnum.card,
|
savedCreditCard ? savedCreditCard.type : PaymentMethodEnum.card,
|
||||||
!!savedCreditCard
|
!!savedCreditCard
|
||||||
)
|
)
|
||||||
|
|
||||||
guaranteeBooking.mutate({
|
guaranteeBooking.mutate({
|
||||||
refId,
|
refId,
|
||||||
language: lang,
|
language: lang,
|
||||||
|
|||||||
@@ -8,6 +8,10 @@ export function hotelreservation(lang: Lang) {
|
|||||||
return `/${lang}/hotelreservation`
|
return `/${lang}/hotelreservation`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function webviewHotelreservation(lang: Lang) {
|
||||||
|
return `/${lang}/webview/hotelreservation`
|
||||||
|
}
|
||||||
|
|
||||||
export function bookingConfirmation(lang: Lang) {
|
export function bookingConfirmation(lang: Lang) {
|
||||||
return `${hotelreservation(lang)}/booking-confirmation`
|
return `${hotelreservation(lang)}/booking-confirmation`
|
||||||
}
|
}
|
||||||
@@ -41,6 +45,8 @@ export function alternativeHotelsMap(lang: Lang) {
|
|||||||
return `${hotelreservation(lang)}/alternative-hotels/map`
|
return `${hotelreservation(lang)}/alternative-hotels/map`
|
||||||
}
|
}
|
||||||
|
|
||||||
export function guaranteeCallback(lang: Lang) {
|
export function guaranteeCallback(lang: Lang, isWebview: boolean) {
|
||||||
return `${hotelreservation(lang)}/gla-payment-callback`
|
return isWebview
|
||||||
|
? `${webviewHotelreservation(lang)}/gla-payment-callback`
|
||||||
|
: `${hotelreservation(lang)}/gla-payment-callback`
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user