From 756ee622e3269060424923158c13f9d34942330e Mon Sep 17 00:00:00 2001 From: Pritish Budhiraja Date: Wed, 16 Oct 2024 12:05:43 +0530 Subject: [PATCH 01/11] feat: paze integration initial commit --- public/icons/orca.svg | 91 +++++++++++++++++--- src/App.res | 1 + src/Components/Spinner.res | 7 ++ src/Payments/PaymentRequestButtonElement.res | 10 ++- src/Payments/PazeButton.res | 41 +++++++++ src/Payments/PazeTypes.res | 33 +++++++ src/Payments/PazeWallet.res | 81 +++++++++++++++++ src/Types/SessionsType.res | 49 +++++++---- 8 files changed, 280 insertions(+), 33 deletions(-) create mode 100644 src/Components/Spinner.res create mode 100644 src/Payments/PazeButton.res create mode 100644 src/Payments/PazeTypes.res create mode 100644 src/Payments/PazeWallet.res diff --git a/public/icons/orca.svg b/public/icons/orca.svg index 7d6d7eba7..dcdab264b 100644 --- a/public/icons/orca.svg +++ b/public/icons/orca.svg @@ -1014,19 +1014,72 @@ License) - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + diff --git a/src/App.res b/src/App.res index 020d9cd9a..13286856f 100644 --- a/src/App.res +++ b/src/App.res @@ -25,6 +25,7 @@ let make = () => { switch fullscreenMode { | "paymentloader" => | "plaidSDK" => + | "pazeWallet" => | "fullscreen" =>
diff --git a/src/Components/Spinner.res b/src/Components/Spinner.res new file mode 100644 index 000000000..da0e35722 --- /dev/null +++ b/src/Components/Spinner.res @@ -0,0 +1,7 @@ +@react.component +let make = () => { + let {themeObj} = Recoil.useRecoilValueFromAtom(RecoilAtoms.configAtom) +
+ +
+} diff --git a/src/Payments/PaymentRequestButtonElement.res b/src/Payments/PaymentRequestButtonElement.res index dc2514972..a4273fa7c 100644 --- a/src/Payments/PaymentRequestButtonElement.res +++ b/src/Payments/PaymentRequestButtonElement.res @@ -1,4 +1,4 @@ -type wallet = GPayWallet | PaypalWallet | ApplePayWallet | KlarnaWallet | NONE +type wallet = GPayWallet | PaypalWallet | ApplePayWallet | KlarnaWallet | PazeWallet | NONE let paymentMode = str => { switch str { | "gpay" @@ -9,6 +9,7 @@ let paymentMode = str => { | "apple_pay" => ApplePayWallet | "klarna" => KlarnaWallet + | "paze" => PazeWallet | _ => NONE } } @@ -64,7 +65,7 @@ let make = (~sessions, ~walletOptions, ~paymentType) => { Gpay, ) - let klarnaTokenObj = SessionsType.getPaymentSessionObj(sessionObj.sessionsToken, Klarna) + let klarnaTokenObj = getPaymentSessionObj(sessionObj.sessionsToken, Klarna) let {clientSecret} = Recoil.useRecoilValueFromAtom(RecoilAtoms.keys) let isPaypalSDKFlow = paypalPaymentMethodExperience->Array.includes(InvokeSDK) @@ -137,6 +138,10 @@ let make = (~sessions, ~walletOptions, ~paymentType) => { }} + | PazeWallet => + + + | NONE => React.null } | None => React.null @@ -145,6 +150,7 @@ let make = (~sessions, ~walletOptions, ~paymentType) => { }) ->React.array} +
diff --git a/src/Payments/PazeButton.res b/src/Payments/PazeButton.res new file mode 100644 index 000000000..8f86a00ca --- /dev/null +++ b/src/Payments/PazeButton.res @@ -0,0 +1,41 @@ +@react.component +let make = () => { + open Utils + open RecoilAtoms + let {iframeId} = Recoil.useRecoilValueFromAtom(keys) + let {themeObj} = Recoil.useRecoilValueFromAtom(configAtom) + let (isDisabled, setIsDisabled) = React.useState(() => false) + let (showLoader, setShowLoader) = React.useState(() => false) + + let onClick = _ => { + Console.log("Button clicked") + setIsDisabled(_ => true) + setShowLoader(_ => true) + + let metaData = [("isForceSync", true->JSON.Encode.bool)]->getJsonFromArrayOfJson + let message = [ + ("fullscreen", true->JSON.Encode.bool), + ("param", "pazeWallet"->JSON.Encode.string), + ("iframeId", iframeId->JSON.Encode.string), + ("metadata", metaData), + ] + + messageParentWindow(message) + } + + +} diff --git a/src/Payments/PazeTypes.res b/src/Payments/PazeTypes.res new file mode 100644 index 000000000..686ff6856 --- /dev/null +++ b/src/Payments/PazeTypes.res @@ -0,0 +1,33 @@ +type client = { + id: string, + name: string, + profileId: string, +} +type initialize = {client: client} + +type canCheckout = {emailAddress: string} + +type checkout = { + acceptedPaymentCardNetworks: array, + emailAddress: string, + sessionId: string, + actionCode: string, + transactionValue: JSON.t, + shippingPreference: string, +} + +type complete = { + transactionOptions: JSON.t, + transactionId: string, + emailAddress: string, + sessionId: string, + transactionType: string, + transactionValue: JSON.t, +} + +type digitalWalletSdk = { + canCheckout: canCheckout => promise, + checkout: checkout => promise, + complete: complete => promise, + initialize: initialize => promise, +} diff --git a/src/Payments/PazeWallet.res b/src/Payments/PazeWallet.res new file mode 100644 index 000000000..450628cee --- /dev/null +++ b/src/Payments/PazeWallet.res @@ -0,0 +1,81 @@ +@val @scope("window") +external digitalWalletSdk: PazeTypes.digitalWalletSdk = "DIGITAL_WALLET_SDK" + +@react.component +let make = () => { + open Promise + let mountPazeSDK = () => { + let pazeScriptURL = `https://sandbox.digitalwallet.earlywarning.com/web/resources/js/digitalwallet-sdk.js` + + let loadPazeSDK = _ => { + digitalWalletSdk.initialize({ + client: { + id: "YK2L1TY5GL0Y1UYLYM9O13oRBRPaMPqYO20N34ByCkwn-c6Is", + name: "Hyperswitch", + profileId: "Getin", + }, + })->then(val => { + Console.log2("PAZE --- init completed", val) + digitalWalletSdk.canCheckout({ + emailAddress: "returninguser@paze.com", + })->then(consumerPresent => { + Console.log("PAZE --- canCheckout completed") + Console.log2("PAZE --- consumerPresent: ", consumerPresent) + let transactionValue = { + "transactionAmount": "50.21", + "transactionCurrencyCode": "USD", + }->Identity.anyTypeToJson + + let transactionOptions = { + "billingPreference": "ALL", + "merchantCategoryCode": "US", + "payloadTypeIndicator": "PAYMENT", + }->Identity.anyTypeToJson + + digitalWalletSdk.checkout({ + acceptedPaymentCardNetworks: ["VISA", "MASTERCARD"], + // emailAddress: "samraat.bansal@juspay.in", + emailAddress: "returninguser@paze.com", + sessionId: "m206xe0zacyslo1lsj", + actionCode: "START_FLOW", + transactionValue, + shippingPreference: "ALL", + })->then( + checkoutResponse => { + Console.log2("PAZE --- Checkout Response Object: ", checkoutResponse) + digitalWalletSdk.complete({ + transactionOptions, + transactionId: "", + emailAddress: "returninguser@paze.com", + sessionId: "m206xe0zacyslo1lsj", + transactionType: "PURCHASE", + transactionValue, + })->then( + completeResponse => { + Console.log2("PAZE --- Complete Response Object: ", completeResponse) + resolve() + }, + ) + }, + ) + }) + }) + } + + let pazeScript = Window.createElement("script") + pazeScript->Window.elementSrc(pazeScriptURL) + pazeScript->Window.elementOnerror(exn => { + let err = exn->Identity.anyTypeToJson->JSON.stringify + Console.log2("PAZE --- errrorrr", err) + }) + pazeScript->Window.elementOnload(_ => loadPazeSDK()->ignore) + Window.body->Window.appendChild(pazeScript) + } + + React.useEffect(() => { + mountPazeSDK() + None + }, []) + +
+} diff --git a/src/Types/SessionsType.res b/src/Types/SessionsType.res index 1557ddb8d..59c722ffc 100644 --- a/src/Types/SessionsType.res +++ b/src/Types/SessionsType.res @@ -1,5 +1,8 @@ -type wallet = Gpay | Paypal | Klarna | ApplePay | NONE -type tokenCategory = ApplePayObject | GooglePayThirdPartyObject | Others +open Utils + +type wallet = Gpay | Paypal | Klarna | ApplePay | Paze | NONE + +type tokenCategory = ApplePayObject | GooglePayThirdPartyObject | PazeObject | Others type paymentType = Wallet | Others @@ -15,15 +18,21 @@ type token = { shippingAddressParameters: JSON.t, orderDetails: JSON.t, connector: string, + clientId: string, + clientName: string, + clientProfileId: string, } type tokenType = | ApplePayToken(array) | GooglePayThirdPartyToken(array) + | PazeToken(array) | OtherToken(array) + type optionalTokenType = | ApplePayTokenOptional(option) | GooglePayThirdPartyTokenOptional(option) + | PazeTokenOptional(option) | OtherTokenOptional(option) type sessions = { @@ -43,6 +52,9 @@ let defaultToken = { shippingAddressParameters: Dict.make()->JSON.Encode.object, orderDetails: Dict.make()->JSON.Encode.object, connector: "", + clientId: "", + clientName: "", + clientProfileId: "", } let getWallet = str => { switch str { @@ -50,12 +62,12 @@ let getWallet = str => { | "paypal" => Paypal | "klarna" => Klarna | "google_pay" => Gpay + | "paze" => Paze | _ => NONE } } -open Utils -let getSessionsToken = (dict, str) => { +let getSessionsToken = (dict, str) => dict ->Dict.get(str) ->Option.flatMap(JSON.Decode.array) @@ -74,14 +86,15 @@ let getSessionsToken = (dict, str) => { shippingAddressParameters: getJsonObjectFromDict(dict, "shipping_address_parameters"), orderDetails: getJsonObjectFromDict(dict, "order_details"), connector: getString(dict, "connector", ""), + clientId: getString(dict, "client_id", ""), + clientName: getString(dict, "client_name", ""), + clientProfileId: getString(dict, "client_profile_id", ""), } }) }) ->Option.getOr([defaultToken]) -} -let getSessionsTokenJson = (dict, str) => { +let getSessionsTokenJson = (dict, str) => dict->Dict.get(str)->Option.flatMap(JSON.Decode.array)->Option.getOr([]) -} let itemToObjMapper = (dict, returnType) => { switch returnType { @@ -97,6 +110,12 @@ let itemToObjMapper = (dict, returnType) => { sessionsToken: GooglePayThirdPartyToken(getSessionsTokenJson(dict, "session_token")), } + | PazeObject => { + paymentId: getString(dict, "payment_id", ""), + clientSecret: getString(dict, "client_secret", ""), + sessionsToken: PazeToken(getSessionsTokenJson(dict, "session_token")), + } + | Others => { paymentId: getString(dict, "payment_id", ""), clientSecret: getString(dict, "client_secret", ""), @@ -105,27 +124,21 @@ let itemToObjMapper = (dict, returnType) => { } } -let getWalletFromTokenType = (arr, val: wallet) => { - let x = arr->Array.find(item => +let getWalletFromTokenType = (arr, val) => + arr->Array.find(item => item ->JSON.Decode.object - ->Option.flatMap(x => { - x->Dict.get("wallet_name") - }) + ->Option.flatMap(x => x->Dict.get("wallet_name")) ->Option.flatMap(JSON.Decode.string) ->Option.getOr("") ->getWallet === val ) - x -} -let getPaymentSessionObj = (tokenType: tokenType, val: wallet) => { +let getPaymentSessionObj = (tokenType, val) => switch tokenType { | ApplePayToken(arr) => ApplePayTokenOptional(getWalletFromTokenType(arr, val)) - | GooglePayThirdPartyToken(arr) => GooglePayThirdPartyTokenOptional(getWalletFromTokenType(arr, val)) - + | PazeToken(arr) => PazeTokenOptional(getWalletFromTokenType(arr, val)) | OtherToken(arr) => OtherTokenOptional(arr->Array.find(item => item.walletName == val)) } -} From a77c8b96b5d5cbbae6c1a5e9b1b3f3a3961a992e Mon Sep 17 00:00:00 2001 From: Pritish Budhiraja Date: Wed, 16 Oct 2024 13:26:13 +0530 Subject: [PATCH 02/11] fix: post message integration --- src/Payments/PaymentRequestButtonElement.res | 11 ++++++-- src/Payments/PazeButton.res | 20 ++++++++------ src/Payments/PazeWallet.res | 29 ++++++++++++++++++-- 3 files changed, 46 insertions(+), 14 deletions(-) diff --git a/src/Payments/PaymentRequestButtonElement.res b/src/Payments/PaymentRequestButtonElement.res index a4273fa7c..e7de70049 100644 --- a/src/Payments/PaymentRequestButtonElement.res +++ b/src/Payments/PaymentRequestButtonElement.res @@ -66,6 +66,7 @@ let make = (~sessions, ~walletOptions, ~paymentType) => { ) let klarnaTokenObj = getPaymentSessionObj(sessionObj.sessionsToken, Klarna) + let pazeTokenObj = getPaymentSessionObj(sessionObj.sessionsToken, Paze) let {clientSecret} = Recoil.useRecoilValueFromAtom(RecoilAtoms.keys) let isPaypalSDKFlow = paypalPaymentMethodExperience->Array.includes(InvokeSDK) @@ -140,7 +141,14 @@ let make = (~sessions, ~walletOptions, ~paymentType) => { | PazeWallet => - + {switch pazeTokenObj { + | OtherTokenOptional(optToken) => + switch optToken { + | Some(token) => + | None => React.null + } + | _ => React.null + }} | NONE => React.null } @@ -150,7 +158,6 @@ let make = (~sessions, ~walletOptions, ~paymentType) => { }) ->React.array} -
diff --git a/src/Payments/PazeButton.res b/src/Payments/PazeButton.res index 8f86a00ca..dedcbd993 100644 --- a/src/Payments/PazeButton.res +++ b/src/Payments/PazeButton.res @@ -1,5 +1,5 @@ @react.component -let make = () => { +let make = (~token: SessionsType.token) => { open Utils open RecoilAtoms let {iframeId} = Recoil.useRecoilValueFromAtom(keys) @@ -8,19 +8,21 @@ let make = () => { let (showLoader, setShowLoader) = React.useState(() => false) let onClick = _ => { - Console.log("Button clicked") setIsDisabled(_ => true) setShowLoader(_ => true) - - let metaData = [("isForceSync", true->JSON.Encode.bool)]->getJsonFromArrayOfJson - let message = [ + messageParentWindow([ ("fullscreen", true->JSON.Encode.bool), ("param", "pazeWallet"->JSON.Encode.string), ("iframeId", iframeId->JSON.Encode.string), - ("metadata", metaData), - ] - - messageParentWindow(message) + ( + "metadata", + [ + ("clientId", token.clientId->JSON.Encode.string), + ("clientName", token.clientName->JSON.Encode.string), + ("clientProfileId", token.clientProfileId->JSON.Encode.string), + ]->getJsonFromArrayOfJson, + ), + ]) }