Skip to content

Commit

Permalink
Merge branch 'main' of github.com:juspay/hyperswitch-web into catch-b…
Browse files Browse the repository at this point in the history
…lock-handling
  • Loading branch information
PritishBudhiraja committed Jan 21, 2025
2 parents d44ddcc + 63bf97e commit 902d8a7
Show file tree
Hide file tree
Showing 17 changed files with 177 additions and 75 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
# [0.108.0](https://github.com/juspay/hyperswitch-web/compare/v0.107.9...v0.108.0) (2025-01-20)


### Features

* add functionality for removing any beforeunload listeners once payment form is submitted ([#860](https://github.com/juspay/hyperswitch-web/issues/860)) ([e889a53](https://github.com/juspay/hyperswitch-web/commit/e889a5364a7d6eecc6196ececee2c192576e2bd7))

## [0.107.9](https://github.com/juspay/hyperswitch-web/compare/v0.107.8...v0.107.9) (2025-01-16)


Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "orca-payment-page",
"version": "0.107.9",
"version": "0.108.0",
"main": "index.js",
"private": true,
"dependencies": {
Expand Down
28 changes: 18 additions & 10 deletions src/Hooks/UtilityHooks.res
Original file line number Diff line number Diff line change
Expand Up @@ -62,16 +62,24 @@ let useSendEventsToParent = eventsToSendToParent => {
})
}

let useUpdateShouldUseTopRedirection = () => {
let setShouldUseTopRedirection = Recoil.useSetRecoilState(RecoilAtoms.shouldUseTopRedirectionAtom)
let updateTopRedirectionAtom = paymentOptions => {
paymentOptions
->Dict.get("shouldUseTopRedirection")
->Option.flatMap(JSON.Decode.bool)
->Option.map(useTop => {
setShouldUseTopRedirection(_ => useTop)
let useUpdateRedirectionFlags = () => {
let setRedirectionFlags = Recoil.useSetRecoilState(RecoilAtoms.redirectionFlagsAtom)
let updateRedirectionFlagsAtom = paymentOptions => {
let topRedirection =
paymentOptions
->Dict.get("shouldUseTopRedirection")
->Option.flatMap(JSON.Decode.bool)
let removeBeforeUnloadEvents =
paymentOptions
->Dict.get("shouldRemoveBeforeUnloadEvents")
->Option.flatMap(JSON.Decode.bool)

setRedirectionFlags(cv => {
shouldUseTopRedirection: topRedirection->Option.getOr(cv.shouldUseTopRedirection),
shouldRemoveBeforeUnloadEvents: removeBeforeUnloadEvents->Option.getOr(
cv.shouldRemoveBeforeUnloadEvents,
),
})
->ignore
}
updateTopRedirectionAtom
updateRedirectionFlagsAtom
}
6 changes: 3 additions & 3 deletions src/LoaderController.res
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ let make = (~children, ~paymentMode, ~setIntegrateErrorError, ~logger, ~initTime
}
}

let updateShouldUseTopRedirection = UtilityHooks.useUpdateShouldUseTopRedirection()
let updateRedirectionFlags = UtilityHooks.useUpdateRedirectionFlags()

React.useEffect0(() => {
messageParentWindow([("iframeMounted", true->JSON.Encode.bool)])
Expand Down Expand Up @@ -281,7 +281,7 @@ let make = (~children, ~paymentMode, ~setIntegrateErrorError, ~logger, ~initTime
logger.setClientSecret(clientSecret)

// Update top redirection atom
updateShouldUseTopRedirection(paymentOptions)
updateRedirectionFlags(paymentOptions)

switch getThemePromise(paymentOptions) {
| Some(promise) =>
Expand Down Expand Up @@ -338,7 +338,7 @@ let make = (~children, ~paymentMode, ~setIntegrateErrorError, ~logger, ~initTime
logger.setClientSecret(clientSecret)

// Update top redirection atom
updateShouldUseTopRedirection(paymentOptions)
updateRedirectionFlags(paymentOptions)

switch getThemePromise(paymentOptions) {
| Some(promise) =>
Expand Down
27 changes: 27 additions & 0 deletions src/Types/RecoilAtomTypes.res
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,30 @@ type paymentToken = {
paymentToken: string,
customerId: string,
}

type redirectionFlags = {
shouldUseTopRedirection: bool,
shouldRemoveBeforeUnloadEvents: bool,
}

let decodeRedirectionFlags = (json: JSON.t, default: redirectionFlags): redirectionFlags => {
json
->JSON.Decode.object
->Option.flatMap(obj => {
let shouldUseTopRedirection =
obj
->Dict.get("shouldUseTopRedirection")
->Option.flatMap(JSON.Decode.bool)
->Option.getOr(default.shouldUseTopRedirection)
let shouldRemoveBeforeUnloadEvents =
obj
->Dict.get("shouldRemoveBeforeUnloadEvents")
->Option.flatMap(JSON.Decode.bool)
->Option.getOr(default.shouldRemoveBeforeUnloadEvents)
Some({
shouldRemoveBeforeUnloadEvents,
shouldUseTopRedirection,
})
})
->Option.getOr(default)
}
30 changes: 14 additions & 16 deletions src/Utilities/PaymentHelpers.res
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ let rec intentCall = (
~isPaymentSession=false,
~isCallbackUsedVal=?,
~componentName="payment",
~shouldUseTopRedirection,
~redirectionFlags,
) => {
open Promise
let isConfirm = uri->String.includes("/confirm")
Expand Down Expand Up @@ -327,7 +327,7 @@ let rec intentCall = (
)
let handleOpenUrl = url => {
if isPaymentSession {
Window.replaceRootHref(url, shouldUseTopRedirection)
Utils.replaceRootHref(url, redirectionFlags)
} else {
openUrl(url)
}
Expand Down Expand Up @@ -454,7 +454,7 @@ let rec intentCall = (
~sdkHandleOneClickConfirmPayment,
~counter=counter + 1,
~componentName,
~shouldUseTopRedirection,
~redirectionFlags,
)
->then(
res => {
Expand Down Expand Up @@ -885,7 +885,7 @@ let rec intentCall = (
~counter=counter + 1,
~isPaymentSession,
~componentName,
~shouldUseTopRedirection,
~redirectionFlags,
)
->then(
res => {
Expand Down Expand Up @@ -917,7 +917,7 @@ let usePaymentSync = (optLogger: option<HyperLogger.loggerMake>, paymentType: pa
let keys = Recoil.useRecoilValueFromAtom(keys)
let isCallbackUsedVal = Recoil.useRecoilValueFromAtom(RecoilAtoms.isCompleteCallbackUsed)
let customPodUri = Recoil.useRecoilValueFromAtom(customPodUri)
let shouldUseTopRedirection = Recoil.useRecoilValueFromAtom(shouldUseTopRedirectionAtom)
let redirectionFlags = Recoil.useRecoilValueFromAtom(redirectionFlagsAtom)
let setIsManualRetryEnabled = Recoil.useSetRecoilState(isManualRetryEnabled)
(~handleUserError=false, ~confirmParam: ConfirmType.confirmParams, ~iframeId="") => {
switch keys.clientSecret {
Expand Down Expand Up @@ -945,7 +945,7 @@ let usePaymentSync = (optLogger: option<HyperLogger.loggerMake>, paymentType: pa
~sdkHandleOneClickConfirmPayment=keys.sdkHandleOneClickConfirmPayment,
~counter=0,
~isCallbackUsedVal,
~shouldUseTopRedirection,
~redirectionFlags,
)->ignore
}
switch paymentMethodList {
Expand Down Expand Up @@ -993,7 +993,7 @@ let usePaymentIntent = (optLogger, paymentType) => {
let paymentMethodList = Recoil.useRecoilValueFromAtom(paymentMethodList)
let keys = Recoil.useRecoilValueFromAtom(keys)
let isCallbackUsedVal = Recoil.useRecoilValueFromAtom(RecoilAtoms.isCompleteCallbackUsed)
let shouldUseTopRedirection = Recoil.useRecoilValueFromAtom(shouldUseTopRedirectionAtom)
let redirectionFlags = Recoil.useRecoilValueFromAtom(redirectionFlagsAtom)

let setIsManualRetryEnabled = Recoil.useSetRecoilState(isManualRetryEnabled)
(
Expand Down Expand Up @@ -1093,7 +1093,7 @@ let usePaymentIntent = (optLogger, paymentType) => {
~counter=0,
~isCallbackUsedVal,
~componentName,
~shouldUseTopRedirection,
~redirectionFlags,
)
->then(val => {
intentCallback(val)
Expand Down Expand Up @@ -1180,7 +1180,7 @@ let useCompleteAuthorize = (optLogger: option<HyperLogger.loggerMake>, paymentTy
let setIsManualRetryEnabled = Recoil.useSetRecoilState(isManualRetryEnabled)
let url = RescriptReactRouter.useUrl()
let isCallbackUsedVal = Recoil.useRecoilValueFromAtom(RecoilAtoms.isCompleteCallbackUsed)
let shouldUseTopRedirection = Recoil.useRecoilValueFromAtom(shouldUseTopRedirectionAtom)
let redirectionFlags = Recoil.useRecoilValueFromAtom(redirectionFlagsAtom)
let paymentTypeFromUrl =
CardUtils.getQueryParamsDictforKey(url.search, "componentName")->CardThemeType.getPaymentMode
(
Expand Down Expand Up @@ -1225,7 +1225,7 @@ let useCompleteAuthorize = (optLogger: option<HyperLogger.loggerMake>, paymentTy
~sdkHandleOneClickConfirmPayment=keys.sdkHandleOneClickConfirmPayment,
~counter=0,
~isCallbackUsedVal,
~shouldUseTopRedirection,
~redirectionFlags,
)->ignore
}
switch paymentMethodList {
Expand Down Expand Up @@ -1618,7 +1618,7 @@ let paymentIntentForPaymentSession = (
~clientSecret,
~logger,
~customPodUri,
~shouldUseTopRedirection,
~redirectionFlags,
) => {
let confirmParams =
payload
Expand Down Expand Up @@ -1675,7 +1675,7 @@ let paymentIntentForPaymentSession = (
~sdkHandleOneClickConfirmPayment=false,
~counter=0,
~isPaymentSession=true,
~shouldUseTopRedirection,
~redirectionFlags,
)
}

Expand Down Expand Up @@ -2112,9 +2112,7 @@ let usePostSessionTokens = (
let customPodUri = Recoil.useRecoilValueFromAtom(customPodUri)
let paymentMethodList = Recoil.useRecoilValueFromAtom(paymentMethodList)
let keys = Recoil.useRecoilValueFromAtom(keys)
let shouldUseTopRedirection = Recoil.useRecoilValueFromAtom(
RecoilAtoms.shouldUseTopRedirectionAtom,
)
let redirectionFlags = Recoil.useRecoilValueFromAtom(RecoilAtoms.redirectionFlagsAtom)

let setIsManualRetryEnabled = Recoil.useSetRecoilState(isManualRetryEnabled)
(
Expand Down Expand Up @@ -2206,7 +2204,7 @@ let usePostSessionTokens = (
~customPodUri,
~sdkHandleOneClickConfirmPayment=keys.sdkHandleOneClickConfirmPayment,
~counter=0,
~shouldUseTopRedirection,
~redirectionFlags
)
->then(val => {
intentCallback(val)
Expand Down
7 changes: 6 additions & 1 deletion src/Utilities/RecoilAtoms.res
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ let sessionId = Recoil.atom("sessionId", "")
let isConfirmBlocked = Recoil.atom("isConfirmBlocked", false)
let customPodUri = Recoil.atom("customPodUri", "")
let selectedOptionAtom = Recoil.atom("selectedOption", "")
let shouldUseTopRedirectionAtom = Recoil.atom("shouldUseTopRedirection", false)
let paymentTokenAtom = Recoil.atom(
"paymentToken",
{
Expand Down Expand Up @@ -100,3 +99,9 @@ let areOneClickWalletsRendered = Recoil.atom(
"areOneClickWalletsBtnRendered",
defaultAreOneClickWalletsRendered,
)

let defaultRedirectionFlags: redirectionFlags = {
shouldUseTopRedirection: false,
shouldRemoveBeforeUnloadEvents: false,
}
let redirectionFlagsAtom = Recoil.atom("redirectionFlags", defaultRedirectionFlags)
30 changes: 30 additions & 0 deletions src/Utilities/Utils.res
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ let handleOnConfirmPostMessage = (~targetOrigin="*", ~isOneClick=false) => {
let message = isOneClick ? "oneClickConfirmTriggered" : "confirmTriggered"
messageParentWindow([(message, true->JSON.Encode.bool)], ~targetOrigin)
}

let handleBeforeRedirectPostMessage = (~targetOrigin="*") => {
messageTopWindow([("disableBeforeUnloadEventListener", true->JSON.Encode.bool)], ~targetOrigin)
}

let getOptionString = (dict, key) => {
dict->Dict.get(key)->Option.flatMap(JSON.Decode.string)
}
Expand Down Expand Up @@ -1457,3 +1462,28 @@ let isDigitLimitExceeded = (val, ~digit) => {
| None => false
}
}

/* Redirect Handling */
let replaceRootHref = (href: string, redirectionFlags: RecoilAtomTypes.redirectionFlags) => {
if redirectionFlags.shouldRemoveBeforeUnloadEvents {
handleBeforeRedirectPostMessage()
}
switch redirectionFlags.shouldUseTopRedirection {
| true =>
try {
setTimeout(() => {
Window.Top.Location.replace(href)
}, 100)->ignore
} catch {
| e => {
Js.Console.error3(
"Failed to redirect root document",
e,
`Using [window.location.replace] for redirection`,
)
Window.Location.replace(href)
}
}
| false => Window.Location.replace(href)
}
}
20 changes: 0 additions & 20 deletions src/Window.res
Original file line number Diff line number Diff line change
Expand Up @@ -203,23 +203,3 @@ let getRootHostName = () =>
}
| false => Location.hostname
}

/* Redirect Handling */
let replaceRootHref = (href: string, shouldUseTopRedirection: bool) => {
switch shouldUseTopRedirection {
| true =>
try {
Top.Location.replace(href)
} catch {
| e => {
Js.Console.error3(
"Failed to redirect root document",
e,
`Using [window.location.replace] for redirection`,
)
Location.replace(href)
}
}
| false => Location.replace(href)
}
}
Loading

0 comments on commit 902d8a7

Please sign in to comment.