diff --git a/src/Utilities/PaymentHelpers.res b/src/Utilities/PaymentHelpers.res index e0c1e47fd..957f0ca11 100644 --- a/src/Utilities/PaymentHelpers.res +++ b/src/Utilities/PaymentHelpers.res @@ -338,7 +338,7 @@ let rec intentCall = ( ) let handleOpenUrl = url => { if isPaymentSession { - Window.Location.replace(url) + Window.replaceRootHref(url) } else { openUrl(url) } diff --git a/src/Window.res b/src/Window.res index 10d4907aa..6b4b754a0 100644 --- a/src/Window.res +++ b/src/Window.res @@ -14,8 +14,6 @@ type style @get external cardCVCElement: window => option = "cardCvc" @get external cardExpiryElement: window => option = "cardExpiry" @get external value: Dom.element => 'a = "value" -@val @scope(("window", "location")) -external replace: string => unit = "replace" @val @scope("document") external createElement: string => Dom.element = "createElement" @set external windowOnload: (window, unit => unit) => unit = "onload" @@ -131,6 +129,9 @@ module Location = { @val @scope(("window", "location")) external hostname: string = "hostname" + @val @scope(("window", "location")) + external href: string = "href" + @val @scope(("window", "location")) external origin: string = "origin" @@ -141,6 +142,28 @@ module Location = { external pathname: string = "pathname" } +module Top = { + module Location = { + @val @scope(("window", "top", "location")) + external replace: string => unit = "replace" + + @val @scope(("window", "top", "location")) + external hostname: string = "hostname" + + @val @scope(("window", "top", "location")) + external href: string = "href" + + @val @scope(("window", "top", "location")) + external origin: string = "origin" + + @val @scope(("window", "top", "location")) + external protocol: string = "protocol" + + @val @scope(("window", "top", "location")) + external pathname: string = "pathname" + } +} + module Element = { @get external clientWidth: Dom.element => int = "clientWidth" } @@ -155,3 +178,56 @@ let isSandbox = Location.hostname === "beta.hyperswitch.io" let isInteg = Location.hostname === "dev.hyperswitch.io" let isProd = Location.hostname === "checkout.hyperswitch.io" + +let isIframed = () => + try { + Location.href !== Top.Location.href + } catch { + | e => { + let default = true + Js.Console.error3( + "Failed to check whether or not document is within an iframe", + e, + `Using "${default->String.make}" as default (due to DOMException)`, + ) + default + } + } + +let getRootHostName = () => + switch isIframed() { + | true => + try { + Top.Location.hostname + } catch { + | e => { + let default = Location.hostname + Js.Console.error3( + "Failed to get root document's hostname", + e, + `Using "${default}" [window.location.hostname] as default`, + ) + default + } + } + | false => Location.hostname + } + +let replaceRootHref = (href: string) => { + switch isIframed() { + | 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) + } +} diff --git a/src/orca-loader/Elements.res b/src/orca-loader/Elements.res index 691372db5..ed28ebfad 100644 --- a/src/orca-loader/Elements.res +++ b/src/orca-loader/Elements.res @@ -68,14 +68,13 @@ let make = ( let componentType = "preMountLoader" let iframeDivHtml = `` + + ` let iframeDiv = Window.createElement("div") iframeDiv->Window.innerHTML(iframeDivHtml) Window.body->Window.appendChild(iframeDiv) @@ -645,7 +644,7 @@ let make = ( let dict = json->getDictFromJson let status = dict->getString("status", "") let returnUrl = dict->getString("return_url", "") - Window.Location.replace( + Window.replaceRootHref( `${returnUrl}?payment_intent_client_secret=${clientSecret}&status=${status}`, ) resolve(JSON.Encode.null) @@ -660,7 +659,7 @@ let make = ( }) ->catch(err => { if redirect.contents === "always" { - Window.Location.replace(url) + Window.replaceRootHref(url) } messageCurrentWindow([ ("submitSuccessful", false->JSON.Encode.bool), diff --git a/src/orca-loader/Hyper.res b/src/orca-loader/Hyper.res index 42cb352eb..c3f5be69c 100644 --- a/src/orca-loader/Hyper.res +++ b/src/orca-loader/Hyper.res @@ -320,10 +320,10 @@ let make = (publishableKey, options: option, analyticsInfo: optionJSON.Decode.bool->Option.getOr(false)) { resolve1(json) } else { - Window.replace(returnUrl) + Window.replaceRootHref(returnUrl) } } else if val->JSON.Decode.bool->Option.getOr(false) && redirect === "always" { - Window.replace(returnUrl) + Window.replaceRootHref(returnUrl) } else if !(val->JSON.Decode.bool->Option.getOr(false)) { resolve1(json) } else { @@ -500,7 +500,7 @@ let make = (publishableKey, options: option, analyticsInfo: optiongetString("return_url", "/") if val->JSON.Decode.bool->Option.getOr(false) && url !== "/" { - Window.replace(url) + Window.replaceRootHref(url) } else { resolve(json) } diff --git a/src/orca-loader/LoaderPaymentElement.res b/src/orca-loader/LoaderPaymentElement.res index 94f7a1c33..028e50132 100644 --- a/src/orca-loader/LoaderPaymentElement.res +++ b/src/orca-loader/LoaderPaymentElement.res @@ -190,7 +190,7 @@ let make = ( switch eventDataObject->getOptionalJsonFromJson("openurl") { | Some(val) => { let url = val->getStringFromJson("") - Window.Location.replace(url) + Window.replaceRootHref(url) } | None => () }