From f5dd999dc9f12a5e81c7cc7b353a40cfc5386f65 Mon Sep 17 00:00:00 2001 From: Pritish Budhiraja Date: Tue, 12 Nov 2024 19:05:13 +0530 Subject: [PATCH] feat: express checkout for paze (#779) --- src/CardUtils.res | 1 + src/LoaderController.res | 1 + src/Payments/PaymentRequestButtonElement.res | 23 ++++++----- src/Payments/PazeButton.res | 5 +++ src/Payments/PazeWallet.res | 3 ++ src/RenderPaymentMethods.res | 1 + src/Types/ApplePayTypes.res | 18 --------- src/Types/CardThemeType.res | 4 +- src/Types/PaymentType.res | 6 +++ src/Utilities/Utils.res | 40 +++++++++++++++++++- src/hyper-loader/Elements.res | 25 ++++++------ 11 files changed, 84 insertions(+), 43 deletions(-) diff --git a/src/CardUtils.res b/src/CardUtils.res index 9a2453df1..4ed5fe889 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 795c65a30..57b6d4b89 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/Payments/PazeButton.res b/src/Payments/PazeButton.res index 4c0b0772e..e0dcd5cd8 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) @@ -15,6 +19,7 @@ let make = (~token: SessionsType.token) => { setShowLoader(_ => true) let 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..9008954df 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 = @@ -84,6 +85,7 @@ let make = () => { messageParentWindow([ ("fullscreen", false->JSON.Encode.bool), ("isPaze", true->JSON.Encode.bool), + ("componentName", componentName->JSON.Encode.string), ( "completeResponse", completeResponse @@ -100,6 +102,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/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 => { 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) - } -} diff --git a/src/Types/CardThemeType.res b/src/Types/CardThemeType.res index 070443d16..6a0a5592b 100644 --- a/src/Types/CardThemeType.res +++ b/src/Types/CardThemeType.res @@ -1,4 +1,4 @@ -type theme = Default | Brutal | Midnight | Soft | Charcoal| Bubblegum | NONE +type theme = Default | Brutal | Midnight | Soft | Charcoal | Bubblegum | NONE type innerLayout = Spaced | Compressed @@ -15,6 +15,7 @@ type mode = | PayPalElement | ApplePayElement | KlarnaElement + | PazeElement | ExpressCheckoutElement | PaymentMethodsManagement | NONE @@ -105,6 +106,7 @@ let getPaymentMode = val => { | "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 68dd28128..cf1ce327c 100644 --- a/src/Utilities/Utils.res +++ b/src/Utilities/Utils.res @@ -1284,11 +1284,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) @@ -1310,6 +1318,7 @@ let walletElementPaymentType: array = [ PayPalElement, ApplePayElement, KlarnaElement, + PazeElement, ExpressCheckoutElement, ] @@ -1425,3 +1434,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 c49995a96..cb0d26d12 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" @@ -130,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) } } @@ -150,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( @@ -292,6 +290,7 @@ let make = ( | "applePay" | "klarna" | "expressCheckout" + | "paze" | "paymentMethodsManagement" | "payment" => () | str => manageErrorWarning(UNKNOWN_KEY, ~dynamicStr=`${str} type in create`, ~logger) @@ -355,7 +354,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() { @@ -943,7 +942,7 @@ let make = ( intermediatePaymentData ->getDictFromJson ->getDictFromDict("shippingAddress") - ->billingContactItemToObjMapper + ->ApplePayTypes.billingContactItemToObjMapper let newShippingAddress = [ ("state", shippingAddress.administrativeArea->JSON.Encode.string),