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: refactor PreMountLoader #583

Merged
merged 6 commits into from
Nov 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
233 changes: 103 additions & 130 deletions src/Payments/PreMountLoader.res
Original file line number Diff line number Diff line change
@@ -1,166 +1,139 @@
@react.component
let make = (
~sessionId,
~publishableKey,
~clientSecret,
~endpoint,
~ephemeralKey,
~hyperComponentName: Types.hyperComponentName,
~merchantHostname,
~customPodUri,
) => {
open Utils
let (paymentMethodsResponseSent, setPaymentMethodsResponseSent) = React.useState(_ => false)
let (
customerPaymentMethodsResponseSent,
setCustomerPaymentMethodsResponseSent,
) = React.useState(_ => false)
let (savedPaymentMethodsResponseSent, setSavedPaymentMethodsResponseSent) = React.useState(_ =>
false
)
let (sessionTokensResponseSent, setSessionTokensResponseSent) = React.useState(_ => false)
let logger = HyperLogger.make(
~sessionId,
~source=Loader,
~merchantId=publishableKey,
~clientSecret,
)
let sendPromiseData = (promise, key) => {
open Promise
promise
->then(res => resolve(res))
->catch(_ => resolve(JSON.Encode.null))
->thenResolve(response => {
Utils.messageParentWindow([("response", response), ("data", key->JSON.Encode.string)])
})
->ignore
}

let (
paymentMethodsResponse,
customerPaymentMethodsResponse,
sessionTokensResponse,
savedPaymentMethodsResponse,
) = React.useMemo0(() => {
let paymentMethodsResponse = switch hyperComponentName {
| Elements =>
PaymentHelpers.fetchPaymentMethodList(
let useMessageHandler = getPromisesAndMessageHandler => {
React.useEffect0(() => {
let (promises, messageHandler) = getPromisesAndMessageHandler()

open Promise
Promise.all(promises)
->thenResolve(_ => {
Utils.messageParentWindow([("preMountLoaderIframeUnMount", true->JSON.Encode.bool)])
Window.removeEventListener("message", messageHandler)
})
->ignore

Utils.messageParentWindow([("preMountLoaderIframeMountedCallback", true->JSON.Encode.bool)])
Window.addEventListener("message", messageHandler)
Some(() => Window.removeEventListener("message", messageHandler))
})
}

module PreMountLoaderForElements = {
@react.component
let make = (
~logger,
~publishableKey,
~clientSecret,
~endpoint,
~merchantHostname,
~customPodUri,
) => {
useMessageHandler(() => {
let paymentMethodsPromise = PaymentHelpers.fetchPaymentMethodList(
~clientSecret,
~publishableKey,
~logger,
~customPodUri,
~endpoint,
)
| _ => JSON.Encode.null->Promise.resolve
}

let customerPaymentMethodsResponse = switch hyperComponentName {
| Elements =>
PaymentHelpers.fetchCustomerPaymentMethodList(
let customerPaymentMethodsPromise = PaymentHelpers.fetchCustomerPaymentMethodList(
~clientSecret,
~publishableKey,
~optLogger=Some(logger),
~customPodUri,
~endpoint,
)
| _ => JSON.Encode.null->Promise.resolve
}

let sessionTokensResponse = switch hyperComponentName {
| Elements =>
PaymentHelpers.fetchSessions(
let sessionTokensPromise = PaymentHelpers.fetchSessions(
~clientSecret,
~publishableKey,
~optLogger=Some(logger),
~customPodUri,
~endpoint,
~merchantHostname,
)
| _ => JSON.Encode.null->Promise.resolve
}

let savedPaymentMethodsResponse = switch hyperComponentName {
| PaymentMethodsManagementElements =>
PaymentHelpers.fetchSavedPaymentMethodList(
let messageHandler = (ev: Window.event) => {
open Utils
let dict = ev.data->safeParse->getDictFromJson
if dict->isKeyPresentInDict("sendPaymentMethodsResponse") {
paymentMethodsPromise->sendPromiseData("payment_methods")
} else if dict->isKeyPresentInDict("sendCustomerPaymentMethodsResponse") {
customerPaymentMethodsPromise->sendPromiseData("customer_payment_methods")
} else if dict->isKeyPresentInDict("sendSessionTokensResponse") {
sessionTokensPromise->sendPromiseData("session_tokens")
}
}

let promises = [paymentMethodsPromise, customerPaymentMethodsPromise, sessionTokensPromise]
(promises, messageHandler)
})

React.null
}
}

module PreMountLoaderForPMMElements = {
@react.component
let make = (~logger, ~endpoint, ~ephemeralKey, ~customPodUri) => {
useMessageHandler(() => {
let savedPaymentMethodsPromise = PaymentHelpers.fetchSavedPaymentMethodList(
~ephemeralKey,
~optLogger=Some(logger),
~customPodUri,
~endpoint,
)
| _ => JSON.Encode.null->Promise.resolve
}

(
paymentMethodsResponse,
customerPaymentMethodsResponse,
sessionTokensResponse,
savedPaymentMethodsResponse,
)
})

let sendPromiseData = (promise, key) => {
open Promise
promise
->then(res => {
messageParentWindow([("response", res), ("data", key->JSON.Encode.string)])
switch key {
| "payment_methods" => setPaymentMethodsResponseSent(_ => true)
| "session_tokens" => setSessionTokensResponseSent(_ => true)
| "customer_payment_methods" => setCustomerPaymentMethodsResponseSent(_ => true)
| "saved_payment_methods" => setSavedPaymentMethodsResponseSent(_ => true)
| _ => ()
let messageHandler = (ev: Window.event) => {
open Utils
let dict = ev.data->safeParse->getDictFromJson
if dict->isKeyPresentInDict("sendSavedPaymentMethodsResponse") {
savedPaymentMethodsPromise->sendPromiseData("saved_payment_methods")
}
}
resolve()
})
->catch(_err => {
messageParentWindow([("response", JSON.Encode.null), ("data", key->JSON.Encode.string)])
resolve()

let promises = [savedPaymentMethodsPromise]
(promises, messageHandler)
})
->ignore
}

let handle = (ev: Window.event) => {
let json = ev.data->safeParse
let dict = json->Utils.getDictFromJson
if dict->Dict.get("sendPaymentMethodsResponse")->Option.isSome {
paymentMethodsResponse->sendPromiseData("payment_methods")
} else if dict->Dict.get("sendCustomerPaymentMethodsResponse")->Option.isSome {
customerPaymentMethodsResponse->sendPromiseData("customer_payment_methods")
} else if dict->Dict.get("sendSessionTokensResponse")->Option.isSome {
sessionTokensResponse->sendPromiseData("session_tokens")
} else if dict->Dict.get("sendSavedPaymentMethodsResponse")->Belt.Option.isSome {
savedPaymentMethodsResponse->sendPromiseData("saved_payment_methods")
}
React.null
}
}

React.useEffect0(() => {
Window.addEventListener("message", handle)
messageParentWindow([("preMountLoaderIframeMountedCallback", true->JSON.Encode.bool)])
Some(
() => {
Window.removeEventListener("message", handle)
},
)
})

React.useEffect4(() => {
let handleUnmount = () => {
messageParentWindow([("preMountLoaderIframeUnMount", true->JSON.Encode.bool)])
Window.removeEventListener("message", handle)
}

switch hyperComponentName {
| Elements =>
if (
paymentMethodsResponseSent &&
customerPaymentMethodsResponseSent &&
sessionTokensResponseSent
) {
handleUnmount()
}
| PaymentMethodsManagementElements =>
if savedPaymentMethodsResponseSent {
handleUnmount()
}
}

None
}, (
paymentMethodsResponseSent,
customerPaymentMethodsResponseSent,
sessionTokensResponseSent,
savedPaymentMethodsResponseSent,
))
@react.component
let make = (
~sessionId,
~publishableKey,
~clientSecret,
~endpoint,
~ephemeralKey,
~hyperComponentName: Types.hyperComponentName,
~merchantHostname,
~customPodUri,
) => {
let logger = HyperLogger.make(
~sessionId,
~source=Loader,
~merchantId=publishableKey,
~clientSecret,
)

React.null
switch hyperComponentName {
| Elements =>
<PreMountLoaderForElements
logger publishableKey clientSecret endpoint merchantHostname customPodUri
/>
| PaymentMethodsManagementElements =>
<PreMountLoaderForPMMElements logger endpoint ephemeralKey customPodUri />
}
}
1 change: 1 addition & 0 deletions src/Utilities/Utils.res
Original file line number Diff line number Diff line change
Expand Up @@ -1419,6 +1419,7 @@ let getFirstAndLastNameFromFullName = fullName => {
(firstName, lastNameJson)
}

let isKeyPresentInDict = (dict, key) => dict->Dict.get(key)->Option.isSome
let checkIsTestCardWildcard = val => ["1111222233334444"]->Array.includes(val)

let minorUnitToString = val => (val->Int.toFloat /. 100.)->Float.toString
Loading