From 45bce5558aa91a1dc6df1a49cd1a3df8408c08d1 Mon Sep 17 00:00:00 2001 From: Pritish Budhiraja Date: Thu, 7 Nov 2024 16:37:54 +0530 Subject: [PATCH 1/4] feat: express checkout for paze --- src/CardUtils.res | 1 + src/LoaderController.res | 1 + src/Payments/PaymentRequestButtonElement.res | 23 +++++++++++--------- src/RenderPaymentMethods.res | 1 + src/Types/CardThemeType.res | 4 +++- src/Types/PaymentType.res | 6 +++++ src/Utilities/Utils.res | 11 +++++++++- src/hyper-loader/Elements.res | 1 + 8 files changed, 36 insertions(+), 12 deletions(-) diff --git a/src/CardUtils.res b/src/CardUtils.res index e917851b9..f7880b5b6 100644 --- a/src/CardUtils.res +++ b/src/CardUtils.res @@ -365,6 +365,7 @@ let getCardBrandIcon = (cardType, paymentType) => { | KlarnaElement | ExpressCheckoutElement | PaymentMethodsManagement + | PazeElement | NONE => } diff --git a/src/LoaderController.res b/src/LoaderController.res index b46360cbd..46559e839 100644 --- a/src/LoaderController.res +++ b/src/LoaderController.res @@ -97,6 +97,7 @@ let make = (~children, ~paymentMode, ~setIntegrateErrorError, ~logger, ~initTime | PayPalElement | ApplePayElement | KlarnaElement + | PazeElement | ExpressCheckoutElement | Payment => { let paymentOptions = PaymentType.itemToObjMapper(optionsDict, logger) diff --git a/src/Payments/PaymentRequestButtonElement.res b/src/Payments/PaymentRequestButtonElement.res index e7de70049..72a8e0efe 100644 --- a/src/Payments/PaymentRequestButtonElement.res +++ b/src/Payments/PaymentRequestButtonElement.res @@ -69,6 +69,7 @@ let make = (~sessions, ~walletOptions, ~paymentType) => { let pazeTokenObj = getPaymentSessionObj(sessionObj.sessionsToken, Paze) let {clientSecret} = Recoil.useRecoilValueFromAtom(RecoilAtoms.keys) + let options = Recoil.useRecoilValueFromAtom(RecoilAtoms.optionAtom) let isPaypalSDKFlow = paypalPaymentMethodExperience->Array.includes(InvokeSDK) let isPaypalRedirectFlow = paypalPaymentMethodExperience->Array.includes(RedirectToURL) @@ -140,16 +141,18 @@ let make = (~sessions, ~walletOptions, ~paymentType) => { | PazeWallet => - - {switch pazeTokenObj { - | OtherTokenOptional(optToken) => - switch optToken { - | Some(token) => - | None => React.null - } - | _ => React.null - }} - + + + {switch pazeTokenObj { + | OtherTokenOptional(optToken) => + switch optToken { + | Some(token) => + | None => React.null + } + | _ => React.null + }} + + | NONE => React.null } | None => React.null diff --git a/src/RenderPaymentMethods.res b/src/RenderPaymentMethods.res index 368e64c5a..4efbd2d8d 100644 --- a/src/RenderPaymentMethods.res +++ b/src/RenderPaymentMethods.res @@ -86,6 +86,7 @@ let make = ( | PayPalElement | ApplePayElement | KlarnaElement + | PazeElement | ExpressCheckoutElement | Payment => { | "paymentMethodCollect" => PaymentMethodCollectElement | "klarna" => KlarnaElement | "expressCheckout" => ExpressCheckoutElement + | "paze" => PazeElement | "paymentMethodsManagement" => PaymentMethodsManagement | _ => NONE } diff --git a/src/Types/PaymentType.res b/src/Types/PaymentType.res index 86c0b06c1..11d4b36f4 100644 --- a/src/Types/PaymentType.res +++ b/src/Types/PaymentType.res @@ -95,6 +95,7 @@ type wallets = { googlePay: showType, payPal: showType, klarna: showType, + paze: showType, style: style, } type business = {name: string} @@ -283,6 +284,7 @@ let defaultWallets = { googlePay: Auto, payPal: Auto, klarna: Auto, + paze: Auto, style: defaultStyle, } let defaultBillingAddress = { @@ -830,6 +832,10 @@ let getWallets = (dict, str, logger) => { "options.wallets.klarna", logger, ), + paze: getWarningString(json, "paze", "auto", ~logger)->getShowType( + "options.wallets.paze", + logger, + ), style: getStyle(json, "style", logger), } }) diff --git a/src/Utilities/Utils.res b/src/Utilities/Utils.res index 45c43cc0d..db5e7a187 100644 --- a/src/Utilities/Utils.res +++ b/src/Utilities/Utils.res @@ -1289,11 +1289,19 @@ let getWalletPaymentMethod = (wallets, paymentType: CardThemeType.mode) => { | PayPalElement => wallets->Array.filter(item => item === "paypal") | ApplePayElement => wallets->Array.filter(item => item === "apple_pay") | KlarnaElement => wallets->Array.filter(item => item === "klarna") + | PazeElement => wallets->Array.filter(item => item === "paze") | _ => wallets } } -let expressCheckoutComponents = ["googlePay", "payPal", "applePay", "klarna", "expressCheckout"] +let expressCheckoutComponents = [ + "googlePay", + "payPal", + "applePay", + "klarna", + "paze", + "expressCheckout", +] let spmComponents = ["paymentMethodCollect"]->Array.concat(expressCheckoutComponents) @@ -1315,6 +1323,7 @@ let walletElementPaymentType: array = [ PayPalElement, ApplePayElement, KlarnaElement, + PazeElement, ExpressCheckoutElement, ] diff --git a/src/hyper-loader/Elements.res b/src/hyper-loader/Elements.res index ff44fb7fc..545b2bf7e 100644 --- a/src/hyper-loader/Elements.res +++ b/src/hyper-loader/Elements.res @@ -291,6 +291,7 @@ let make = ( | "applePay" | "klarna" | "expressCheckout" + | "paze" | "paymentMethodsManagement" | "payment" => () | str => manageErrorWarning(UNKNOWN_KEY, ~dynamicStr=`${str} type in create`, ~logger) From 514c7da3d35e0f1a77ced8ece4793626a3331257 Mon Sep 17 00:00:00 2001 From: Pritish Budhiraja Date: Thu, 7 Nov 2024 17:09:54 +0530 Subject: [PATCH 2/4] fix: multiple iframe resolve --- src/Payments/PazeButton.res | 5 +++++ src/Payments/PazeWallet.res | 2 ++ src/Types/ApplePayTypes.res | 16 ++++++++++++++++ src/hyper-loader/Elements.res | 17 ++++++++--------- 4 files changed, 31 insertions(+), 9 deletions(-) diff --git a/src/Payments/PazeButton.res b/src/Payments/PazeButton.res index 411beee9e..755453827 100644 --- a/src/Payments/PazeButton.res +++ b/src/Payments/PazeButton.res @@ -2,6 +2,10 @@ let make = (~token: SessionsType.token) => { open Utils open RecoilAtoms + + let url = RescriptReactRouter.useUrl() + let componentName = CardUtils.getQueryParamsDictforKey(url.search, "componentName") + let {iframeId, publishableKey, clientSecret} = Recoil.useRecoilValueFromAtom(keys) let {themeObj} = Recoil.useRecoilValueFromAtom(configAtom) let options = Recoil.useRecoilValueFromAtom(optionAtom) @@ -26,6 +30,7 @@ let make = (~token: SessionsType.token) => { ( "metadata", [ + ("componentName", componentName->JSON.Encode.string), ("wallet", (token.walletName :> string)->JSON.Encode.string), ("clientId", token.clientId->JSON.Encode.string), ("clientName", token.clientName->JSON.Encode.string), diff --git a/src/Payments/PazeWallet.res b/src/Payments/PazeWallet.res index f815f2ba2..dff042506 100644 --- a/src/Payments/PazeWallet.res +++ b/src/Payments/PazeWallet.res @@ -21,6 +21,7 @@ let make = () => { let emailAddress = metaData->getString("emailAddress", "") let transactionAmount = metaData->getString("transactionAmount", "") let transactionCurrencyCode = metaData->getString("transactionCurrencyCode", "") + let componentName = metaData->getString("componentName", "") let mountPazeSDK = () => { let pazeScriptURL = @@ -100,6 +101,7 @@ let make = () => { ("fullscreen", false->JSON.Encode.bool), ("isPaze", true->JSON.Encode.bool), ("flowExited", "stop"->JSON.Encode.string), + ("componentName", componentName->JSON.Encode.string), ]) resolve() } diff --git a/src/Types/ApplePayTypes.res b/src/Types/ApplePayTypes.res index 983f4962c..f8e07330c 100644 --- a/src/Types/ApplePayTypes.res +++ b/src/Types/ApplePayTypes.res @@ -203,3 +203,19 @@ let handleApplePayIframePostMessage = (msg, componentName, mountedIframeRef) => mountedIframeRef->Window.iframePostMessage(msg) } } + +let handlePazeIframePostMessage = (msg, componentName, eventSource) => { + let isPazePresent = ref(false) + let iframes = Window.querySelectorAll("iframe") + iframes->Array.forEach(iframe => { + let iframeSrc = iframe->Window.getAttribute("src")->Option.getOr("") + if iframeSrc->String.includes(`componentName=${componentName}`) { + iframe->Js.Nullable.return->Window.iframePostMessage(msg) + isPazePresent := true + } + }) + + if !isPazePresent.contents { + eventSource->Window.sendPostMessage(msg) + } +} diff --git a/src/hyper-loader/Elements.res b/src/hyper-loader/Elements.res index 545b2bf7e..c850cab37 100644 --- a/src/hyper-loader/Elements.res +++ b/src/hyper-loader/Elements.res @@ -129,14 +129,13 @@ let make = ( } } - let onPazeCallback = mountedIframeRef => { - (ev: Types.event) => { - let json = ev.data->Identity.anyTypeToJson - let dict = json->getDictFromJson - let isPazeExist = dict->getBool("isPaze", false) - if isPazeExist { - mountedIframeRef->Window.iframePostMessage([("data", json)]->Dict.fromArray) - } + let onPazeCallback = (event: Types.event) => { + let json = event.data->Identity.anyTypeToJson + let dict = json->getDictFromJson + if dict->getBool("isPaze", false) { + let componentName = dict->getString("componentName", "payment") + let msg = [("data", json)]->Dict.fromArray + handlePazeIframePostMessage(msg, componentName, event.source) } } @@ -149,7 +148,7 @@ let make = ( isTaxCalculationEnabled.contents = dict->getDictFromDict("response")->getBool("is_tax_calculation_enabled", false) addSmartEventListener("message", onPlaidCallback(mountedIframeRef), "onPlaidCallback") - addSmartEventListener("message", onPazeCallback(mountedIframeRef), "onPazeCallback") + addSmartEventListener("message", onPazeCallback, "onPazeCallback") let json = dict->getJsonFromDict("response", JSON.Encode.null) let isApplePayPresent = PaymentMethodsRecord.getPaymentMethodTypeFromList( From 8a2aef03b417a741f3157aa2f6c841d4746c5d59 Mon Sep 17 00:00:00 2001 From: Pritish Budhiraja Date: Thu, 7 Nov 2024 17:12:46 +0530 Subject: [PATCH 3/4] refactor: made common function for reusable code --- src/Types/ApplePayTypes.res | 34 ---------------------------------- src/Utilities/Utils.res | 29 +++++++++++++++++++++++++++++ src/hyper-loader/Elements.res | 7 +++---- 3 files changed, 32 insertions(+), 38 deletions(-) diff --git a/src/Types/ApplePayTypes.res b/src/Types/ApplePayTypes.res index f8e07330c..f644e938f 100644 --- a/src/Types/ApplePayTypes.res +++ b/src/Types/ApplePayTypes.res @@ -185,37 +185,3 @@ let getPaymentRequestFromSession = (~sessionObj, ~componentName) => { paymentRequest } - -let handleApplePayIframePostMessage = (msg, componentName, mountedIframeRef) => { - let isApplePayMessageSent = ref(false) - - let iframes = Window.querySelectorAll("iframe") - - iframes->Array.forEach(iframe => { - let iframeSrc = iframe->Window.getAttribute("src")->Option.getOr("") - if iframeSrc->String.includes(`componentName=${componentName}`) { - iframe->Js.Nullable.return->Window.iframePostMessage(msg) - isApplePayMessageSent := true - } - }) - - if !isApplePayMessageSent.contents { - mountedIframeRef->Window.iframePostMessage(msg) - } -} - -let handlePazeIframePostMessage = (msg, componentName, eventSource) => { - let isPazePresent = ref(false) - let iframes = Window.querySelectorAll("iframe") - iframes->Array.forEach(iframe => { - let iframeSrc = iframe->Window.getAttribute("src")->Option.getOr("") - if iframeSrc->String.includes(`componentName=${componentName}`) { - iframe->Js.Nullable.return->Window.iframePostMessage(msg) - isPazePresent := true - } - }) - - if !isPazePresent.contents { - eventSource->Window.sendPostMessage(msg) - } -} diff --git a/src/Utilities/Utils.res b/src/Utilities/Utils.res index db5e7a187..ad9b32ac6 100644 --- a/src/Utilities/Utils.res +++ b/src/Utilities/Utils.res @@ -1439,3 +1439,32 @@ let mergeAndFlattenToTuples = (body, requiredFieldsBody) => ->flattenObject(true) ->mergeTwoFlattenedJsonDicts(requiredFieldsBody) ->getArrayOfTupleFromDict + +let sendMessageToIframe = (~msg, ~componentName, ~eventSource=None, ~mountedIframeRef=None) => { + let isMessageSent = ref(false) + let iframes = Window.querySelectorAll("iframe") + + iframes->Array.forEach(iframe => { + let iframeSrc = iframe->Window.getAttribute("src")->Option.getOr("") + if iframeSrc->String.includes(`componentName=${componentName}`) { + iframe->Js.Nullable.return->Window.iframePostMessage(msg) + isMessageSent := true + } + }) + + if !isMessageSent.contents { + switch (eventSource, mountedIframeRef) { + | (Some(source), _) => source->Window.sendPostMessage(msg) + | (None, Some(ref)) => ref->Window.iframePostMessage(msg) + | (None, None) => () + } + } +} + +let handleApplePayIframePostMessage = (msg, componentName, mountedIframeRef) => { + sendMessageToIframe(~msg, ~componentName, ~mountedIframeRef=Some(mountedIframeRef)) +} + +let handlePazeIframePostMessage = (msg, componentName, eventSource) => { + sendMessageToIframe(~msg, ~componentName, ~eventSource=Some(eventSource)) +} diff --git a/src/hyper-loader/Elements.res b/src/hyper-loader/Elements.res index c850cab37..bd1cedcff 100644 --- a/src/hyper-loader/Elements.res +++ b/src/hyper-loader/Elements.res @@ -3,10 +3,9 @@ open ErrorUtils open Identity open Utils open EventListenerManager -open ApplePayTypes type trustPayFunctions = { - finishApplePaymentV2: (string, paymentRequestData) => promise, + finishApplePaymentV2: (string, ApplePayTypes.paymentRequestData) => promise, executeGooglePayment: (string, GooglePayType.paymentDataRequest) => promise, } @new external trustPayApi: JSON.t => trustPayFunctions = "TrustPayApi" @@ -353,7 +352,7 @@ let make = ( if dict->Dict.get("applePayMounted")->Option.isSome { if wallets.applePay === Auto { - switch sessionForApplePay->Nullable.toOption { + switch ApplePayTypes.sessionForApplePay->Nullable.toOption { | Some(session) => try { if session.canMakePayments() { @@ -938,7 +937,7 @@ let make = ( intermediatePaymentData ->getDictFromJson ->getDictFromDict("shippingAddress") - ->billingContactItemToObjMapper + ->ApplePayTypes.billingContactItemToObjMapper let newShippingAddress = [ ("state", shippingAddress.administrativeArea->JSON.Encode.string), From a00ea8a555b3e1dc47ef38bb28eae894b2ca9e92 Mon Sep 17 00:00:00 2001 From: Pritish Budhiraja Date: Thu, 7 Nov 2024 17:19:31 +0530 Subject: [PATCH 4/4] fix: success case for paze wallet --- src/Payments/PazeWallet.res | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Payments/PazeWallet.res b/src/Payments/PazeWallet.res index dff042506..9008954df 100644 --- a/src/Payments/PazeWallet.res +++ b/src/Payments/PazeWallet.res @@ -85,6 +85,7 @@ let make = () => { messageParentWindow([ ("fullscreen", false->JSON.Encode.bool), ("isPaze", true->JSON.Encode.bool), + ("componentName", componentName->JSON.Encode.string), ( "completeResponse", completeResponse