From 85b35819b91ef9f28b16978312f22dfdfa982824 Mon Sep 17 00:00:00 2001 From: Arush Date: Thu, 4 Apr 2024 14:38:40 +0530 Subject: [PATCH] feat: added One Click Widgets (ApplePay, GooglePay, PayPal) --- src/CardTheme.res | 3 + src/CardUtils.res | 3 + src/LoaderController.res | 3 + src/PaymentElementRenderer.res | 9 ++- src/RenderPaymentMethods.res | 7 +- src/Types/CardThemeType.res | 3 + src/Utilities/Utils.res | 25 ++++++++ src/WalletElementRenderer.res | 81 ++++++++++++++++++++++++ src/orca-loader/Elements.res | 18 +++++- src/orca-loader/LoaderPaymentElement.res | 4 +- 10 files changed, 148 insertions(+), 8 deletions(-) create mode 100644 src/WalletElementRenderer.res diff --git a/src/CardTheme.res b/src/CardTheme.res index 25245d06f..cd7a39dcc 100644 --- a/src/CardTheme.res +++ b/src/CardTheme.res @@ -39,6 +39,9 @@ let getPaymentMode = val => { | "cardNumber" => CardNumberElement | "cardExpiry" => CardExpiryElement | "cardCvc" => CardCVCElement + | "googlePay" => GooglePayElement + | "payPal" => PayPalElement + | "applePay" => ApplePayElement | _ => NONE } } diff --git a/src/CardUtils.res b/src/CardUtils.res index b77f1d6a1..b299b6281 100644 --- a/src/CardUtils.res +++ b/src/CardUtils.res @@ -338,6 +338,9 @@ let getCardBrandIcon = (cardType, paymentType) => { | CardNumberElement | CardExpiryElement | CardCVCElement + | GooglePayElement + | PayPalElement + | ApplePayElement | NONE => } diff --git a/src/LoaderController.res b/src/LoaderController.res index 60e1430a5..5ac379ef0 100644 --- a/src/LoaderController.res +++ b/src/LoaderController.res @@ -79,6 +79,9 @@ let make = (~children, ~paymentMode, ~setIntegrateErrorError, ~logger, ~initTime | CardCVCElement | Card => setOptions(_ => ElementType.itemToObjMapper(optionsDict, logger)) + | GooglePayElement + | PayPalElement + | ApplePayElement | Payment => { let paymentOptions = PaymentType.itemToObjMapper(optionsDict, logger) setOptionsPayment(_ => paymentOptions) diff --git a/src/PaymentElementRenderer.res b/src/PaymentElementRenderer.res index df02ca75b..0cba1f89b 100644 --- a/src/PaymentElementRenderer.res +++ b/src/PaymentElementRenderer.res @@ -16,9 +16,14 @@ let make = ( switch (sessions, list) { | (_, Loading) => - + {paymentType->Utils.isWalletElementPaymentType + ? + : } - | _ => + | _ => + paymentType->Utils.isWalletElementPaymentType + ? + : } } diff --git a/src/RenderPaymentMethods.res b/src/RenderPaymentMethods.res index 4e207cb39..7149c1aa8 100644 --- a/src/RenderPaymentMethods.res +++ b/src/RenderPaymentMethods.res @@ -80,10 +80,15 @@ let make = ( paymentType cardProps expiryProps cvcProps zipProps handleElementFocus isFocus /> + | GooglePayElement + | PayPalElement + | ApplePayElement | Payment => - + {paymentType->Utils.isWalletElementPaymentType + ? + : } }> diff --git a/src/Types/CardThemeType.res b/src/Types/CardThemeType.res index 633a94650..7b1e52d26 100644 --- a/src/Types/CardThemeType.res +++ b/src/Types/CardThemeType.res @@ -9,6 +9,9 @@ type mode = | CardNumberElement | CardExpiryElement | CardCVCElement + | GooglePayElement + | PayPalElement + | ApplePayElement | NONE type label = Above | Floating | Never type themeClass = { diff --git a/src/Utilities/Utils.res b/src/Utilities/Utils.res index af84cfe38..1d7449423 100644 --- a/src/Utilities/Utils.res +++ b/src/Utilities/Utils.res @@ -1234,3 +1234,28 @@ let makeOneClickHandlerPromise = sdkHandleOneClickConfirmPayment => { } }) } + +let getWalletPaymentMethod = (wallets, paymentType: CardThemeType.mode) => { + switch paymentType { + | GooglePayElement => wallets->Js.Array2.filter(item => item === "google_pay") + | PayPalElement => wallets->Js.Array2.filter(item => item === "paypal") + | ApplePayElement => wallets->Js.Array2.filter(item => item === "apple_pay") + | _ => wallets + } +} + +let isComponentTypeForPaymentElementCreate = componentType => { + componentType === "payment" || + componentType === "googlePay" || + componentType === "payPal" || + componentType === "applePay" +} + +let isWalletElementPaymentType = (paymentType: CardThemeType.mode) => { + switch paymentType { + | GooglePayElement + | PayPalElement + | ApplePayElement => true + | _ => false + } +} diff --git a/src/WalletElementRenderer.res b/src/WalletElementRenderer.res new file mode 100644 index 000000000..a1dbe52ff --- /dev/null +++ b/src/WalletElementRenderer.res @@ -0,0 +1,81 @@ +open PaymentType +open RecoilAtoms + +@react.component +let make = (~paymentType: CardThemeType.mode) => { + let sessionsObj = Recoil.useRecoilValueFromAtom(sessions) + let {paymentMethodOrder} = Recoil.useRecoilValueFromAtom(optionAtom) + let isApplePayReady = Recoil.useRecoilValueFromAtom(isApplePayReady) + let isGooglePayReady = Recoil.useRecoilValueFromAtom(isGooglePayReady) + let methodslist = Recoil.useRecoilValueFromAtom(list) + let paymentOrder = paymentMethodOrder->Utils.getOptionalArr->Utils.removeDuplicate + let (sessions, setSessions) = React.useState(_ => Dict.make()->JSON.Encode.object) + let (walletOptions, setWalletOptions) = React.useState(_ => []) + + let (list, setList) = React.useState(_ => PaymentMethodsRecord.defaultList) + + let areAllGooglePayRequiredFieldsPrefilled = DynamicFieldsUtils.useAreAllRequiredFieldsPrefilled( + ~list, + ~paymentMethod="wallet", + ~paymentMethodType="google_pay", + ) + + let areAllApplePayRequiredFieldsPrefilled = DynamicFieldsUtils.useAreAllRequiredFieldsPrefilled( + ~list, + ~paymentMethod="wallet", + ~paymentMethodType="apple_pay", + ) + + let walletList = React.useMemo(() => { + switch methodslist { + | Loaded(paymentlist) => + let paymentOrder = + paymentOrder->Array.length > 0 ? paymentOrder : PaymentModeType.defaultOrder + let plist = paymentlist->Utils.getDictFromJson->PaymentMethodsRecord.itemToObjMapper + let (wallets, _) = + plist->PaymentUtils.paymentListLookupNew( + ~order=paymentOrder, + ~showApplePay=isApplePayReady, + ~showGooglePay=isGooglePayReady, + ~areAllGooglePayRequiredFieldsPrefilled, + ~areAllApplePayRequiredFieldsPrefilled, + ) + wallets->Utils.removeDuplicate->Utils.getWalletPaymentMethod(paymentType) + | _ => [] + } + }, ( + methodslist, + paymentMethodOrder, + isApplePayReady, + isGooglePayReady, + areAllGooglePayRequiredFieldsPrefilled, + areAllApplePayRequiredFieldsPrefilled, + )) + + React.useEffect(() => { + switch methodslist { + | Loaded(paymentlist) => + let plist = paymentlist->Utils.getDictFromJson->PaymentMethodsRecord.itemToObjMapper + + setWalletOptions(_ => walletList) + setList(_ => plist) + | _ => () + } + None + }, (methodslist, walletList)) + React.useEffect(() => { + switch sessionsObj { + | Loaded(ssn) => setSessions(_ => ssn) + | _ => () + } + None + }, [sessionsObj]) + + Array.length > 0}> +
+ + + +
+
+} diff --git a/src/orca-loader/Elements.res b/src/orca-loader/Elements.res index 75aaac4fa..902850729 100644 --- a/src/orca-loader/Elements.res +++ b/src/orca-loader/Elements.res @@ -212,6 +212,9 @@ let make = ( | "cardNumber" | "cardExpiry" | "cardCvc" + | "googlePay" + | "payPal" + | "applePay" | "payment" => () | str => manageErrorWarning(UNKNOWN_KEY, ~dynamicStr=`${str} type in create`, ~logger, ()) } @@ -235,7 +238,10 @@ let make = ( ->JSON.Encode.object let message = [ - ("paymentElementCreate", (componentType == "payment")->JSON.Encode.bool), + ( + "paymentElementCreate", + componentType->Utils.isComponentTypeForPaymentElementCreate->JSON.Encode.bool, + ), ("otherElements", otherElements->JSON.Encode.bool), ("options", newOptions), ("componentType", componentType->JSON.Encode.string), @@ -440,7 +446,10 @@ let make = ( }) ->then(res => { let (json, applePayPresent, googlePayPresent) = res - if componentType === "payment" && applePayPresent->Option.isSome { + if ( + componentType->Utils.isComponentTypeForPaymentElementCreate && + applePayPresent->Option.isSome + ) { //do operations here let processPayment = (token: JSON.t) => { //let body = PaymentBody.applePayBody(~token) @@ -639,7 +648,10 @@ let make = ( addSmartEventListener("message", handleApplePayMessages.contents, "onApplePayMessages") } - if componentType === "payment" && googlePayPresent->Option.isSome { + if ( + componentType->Utils.isComponentTypeForPaymentElementCreate && + googlePayPresent->Option.isSome + ) { let dict = json->getDictFromJson let sessionObj = SessionsType.itemToObjMapper(dict, Others) let gPayToken = SessionsType.getPaymentSessionObj(sessionObj.sessionsToken, Gpay) diff --git a/src/orca-loader/LoaderPaymentElement.res b/src/orca-loader/LoaderPaymentElement.res index 0e3e2cd9e..b79470512 100644 --- a/src/orca-loader/LoaderPaymentElement.res +++ b/src/orca-loader/LoaderPaymentElement.res @@ -293,10 +293,10 @@ let make = (componentType, options, setIframeRef, iframeRef, mountPostMessage) = let oElement = Window.querySelector(selector) let classesBase = optionsDict->getClasses("base") - let additionalIframeStyle = componentType->Utils.isOtherElements ? "height: 2rem;" : "" + let additionalIframeStyle = componentType->Utils.isOtherElements ? "height: 2rem;" : "height: 0;" switch oElement->Nullable.toOption { | Some(elem) => { - let iframeDiv = `
+ let iframeDiv = `