Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: handle redirections for iframed content #557

Merged
merged 7 commits into from
Sep 10, 2024
2 changes: 1 addition & 1 deletion src/Utilities/PaymentHelpers.res
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ let rec intentCall = (
)
let handleOpenUrl = url => {
if isPaymentSession {
Window.Location.replace(url)
Window.replaceRootHref(url)
} else {
openUrl(url)
}
Expand Down
80 changes: 78 additions & 2 deletions src/Window.res
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ type style
@get external cardCVCElement: window => option<window> = "cardCvc"
@get external cardExpiryElement: window => option<window> = "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"
Expand Down Expand Up @@ -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"

Expand All @@ -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"
}
Expand All @@ -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(
seekshiva marked this conversation as resolved.
Show resolved Hide resolved
"Failed to redirect root document",
e,
`Using [window.location.replace] for redirection`,
)
Location.replace(href)
}
}
| false => Location.replace(href)
}
}
19 changes: 9 additions & 10 deletions src/orca-loader/Elements.res
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,13 @@ let make = (
let componentType = "preMountLoader"
let iframeDivHtml = `<div id="orca-element-${localSelectorString}" style= "height: 0px; width: 0px; display: none;" class="${componentType}">
<div id="orca-fullscreen-iframeRef-${localSelectorString}"></div>
<iframe
id ="orca-payment-element-iframeRef-${localSelectorString}"
name="orca-payment-element-iframeRef-${localSelectorString}"
src="${ApiEndpoint.sdkDomainUrl}/index.html?fullscreenType=${componentType}&publishableKey=${publishableKey}&clientSecret=${clientSecret}&sessionId=${sdkSessionId}&endpoint=${endpoint}&merchantHostname=${merchantHostname}&customPodUri=${customPodUri}"
allow="*"
name="orca-payment"
></iframe>
</div>`
<iframe
id="orca-payment-element-iframeRef-${localSelectorString}"
name="orca-payment-element-iframeRef-${localSelectorString}"
src="${ApiEndpoint.sdkDomainUrl}/index.html?fullscreenType=${componentType}&publishableKey=${publishableKey}&clientSecret=${clientSecret}&sessionId=${sdkSessionId}&endpoint=${endpoint}&merchantHostname=${merchantHostname}&customPodUri=${customPodUri}" allow="*"
name="orca-payment"
></iframe>
</div>`
let iframeDiv = Window.createElement("div")
iframeDiv->Window.innerHTML(iframeDivHtml)
Window.body->Window.appendChild(iframeDiv)
Expand Down Expand Up @@ -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)
Expand All @@ -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),
Expand Down
6 changes: 3 additions & 3 deletions src/orca-loader/Hyper.res
Original file line number Diff line number Diff line change
Expand Up @@ -320,10 +320,10 @@ let make = (publishableKey, options: option<JSON.t>, analyticsInfo: option<JSON.
if !(val->JSON.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 {
Expand Down Expand Up @@ -500,7 +500,7 @@ let make = (publishableKey, options: option<JSON.t>, analyticsInfo: option<JSON.
)
let url = decodedData->getString("return_url", "/")
if val->JSON.Decode.bool->Option.getOr(false) && url !== "/" {
Window.replace(url)
Window.replaceRootHref(url)
} else {
resolve(json)
}
Expand Down
2 changes: 1 addition & 1 deletion src/orca-loader/LoaderPaymentElement.res
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ let make = (
switch eventDataObject->getOptionalJsonFromJson("openurl") {
| Some(val) => {
let url = val->getStringFromJson("")
Window.Location.replace(url)
Window.replaceRootHref(url)
}
| None => ()
}
Expand Down
Loading