From 0f04b345e0d8915f92fd82ad0725021807b1ccd1 Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Date: Thu, 7 Nov 2024 13:19:26 +0530 Subject: [PATCH 1/2] feat: aCH debit --- server.js | 61 +- src/hooks/AllPaymentHooks.res | 4 + src/hooks/PMListModifier.res | 14 + src/icons/Icon.res | 2 + src/pages/payment/ACHBankDebit.res | 903 ++++++++++++++++++++++++++++ src/pages/payment/Redirect.res | 616 +++++++++++++++---- src/types/LoggerTypes.res | 1 + src/types/PaymentMethodListType.res | 57 +- src/types/RequiredFieldsTypes.res | 7 +- src/types/SdkTypes.res | 2 + src/types/Types.res | 27 +- 11 files changed, 1553 insertions(+), 141 deletions(-) create mode 100644 src/pages/payment/ACHBankDebit.res diff --git a/server.js b/server.js index 38f8465..2f9fba0 100644 --- a/server.js +++ b/server.js @@ -5,7 +5,7 @@ app.use(cors()); app.use(express.static('./dist')); app.use(express.json()); -require('dotenv').config({path: './.env'}); +require('dotenv').config({ path: './.env' }); try { var hyper = require('@juspay-tech/hyperswitch-node')( @@ -18,10 +18,59 @@ try { app.get('/create-payment-intent', async (req, res) => { try { - var paymentIntent = await hyper.paymentIntents.create({ - amount: 2999, - currency: 'USD', - }); + var paymentIntent = await hyper.paymentIntents.create( + { + amount: 6540, + currency: 'USD', + // confirm: false, + // capture_method: 'automatic', + // capture_on: '2022-09-10T10:11:12Z', + // amount_to_capture: 6540, + customer_id: 'StripeCustomer', + // email: 'guest@example.com', + // name: 'John Doe', + // phone: '999999999', + // profile_id: 'pro_1PEZIEJyHhhZ3WJTVIVM', + // phone_country_code: '+65', + // description: 'Its my first payment request', + // authentication_type: 'three_ds', + // return_url: 'https://duck.com', + profile_id: "pro_E6k4XxWE3fVzTIYDMzJa", + //setup_future_usage: "off_session" + // billing: { + // address: { + // line1: '1467', + // line2: 'Harrison Street', + // line3: 'Harrison Street', + // city: 'San Fransico', + // state: 'California', + // zip: '94122', + // country: 'US', + // first_name: 'PiX', + // }, + // }, + // shipping: { + // address: { + // line1: '1467', + // line2: 'Harrison Street', + // line3: 'Harrison Street', + // city: 'San Fransico', + // state: 'California', + // zip: '94122', + // country: 'US', + // first_name: 'PiX', + // }, + // }, + // request_external_three_ds_authentication: true, + // statement_descriptor_name: 'joseph', + // statement_descriptor_suffix: 'JS', + // metadata: { + // udf1: 'value1', + // new_customer: 'true', + // login_date: '2019-09-10T10:11:12Z', + // } + + }); // Send publishable key and PaymentIntent details to client res.send({ @@ -47,7 +96,7 @@ app.get('/create-ephemeral-key', async (req, res) => { 'Content-Type': 'application/json', 'api-key': process.env.HYPERSWITCH_SECRET_KEY, }, - body: JSON.stringify({customer_id: "hyperswitch_sdk_demo_id"}), + body: JSON.stringify({ customer_id: "hyperswitch_sdk_demo_id" }), }, ); const ephemeralKey = await response.json(); diff --git a/src/hooks/AllPaymentHooks.res b/src/hooks/AllPaymentHooks.res index 60417f9..e429c3b 100644 --- a/src/hooks/AllPaymentHooks.res +++ b/src/hooks/AllPaymentHooks.res @@ -487,6 +487,10 @@ let useRedirectHook = () => { ~errorCallback, ~processor=body, ) + responseCallback( + ~paymentStatus=LoadingContext.ProcessingPayments(None), + ~status={status, message: "", code: "", type_: ""}, + ) } | statusVal => logger( diff --git a/src/hooks/PMListModifier.res b/src/hooks/PMListModifier.res index 69b825c..771b771 100644 --- a/src/hooks/PMListModifier.res +++ b/src/hooks/PMListModifier.res @@ -206,6 +206,20 @@ let useListModifier = () => { />, }) : None + | BANK_DEBIT(achDebitVal) => + let fields = + redirectionList + ->Array.find(l => l.name == achDebitVal.payment_method_type) + ->Option.getOr(Types.defaultRedirectType) + + Some({ + name: fields.text, + componentHoc: (~isScreenFocus, ~setConfirmButtonDataRef) => + , + }) + | CRYPTO(cryptoVal) => let fields = redirectionList diff --git a/src/icons/Icon.res b/src/icons/Icon.res index 8c3656b..7fb5e09 100644 --- a/src/icons/Icon.res +++ b/src/icons/Icon.res @@ -35,6 +35,7 @@ let camera = `` let checkboxclicked = `` let checkboxnotclicked = `` +let achBankDebit = `` type uri = { uri: string, @@ -96,6 +97,7 @@ let make = ( | "checkboxclicked" => checkboxclicked | "checkboxnotclicked" => checkboxnotclicked | "open banking" => openBanking + | "bank debit" => achBankDebit | _ => "" } localName == "" diff --git a/src/pages/payment/ACHBankDebit.res b/src/pages/payment/ACHBankDebit.res new file mode 100644 index 0000000..2e41158 --- /dev/null +++ b/src/pages/payment/ACHBankDebit.res @@ -0,0 +1,903 @@ +// // open ReactNative +// // open PaymentMethodListType +// // open CustomPicker +// // open Redirect +// // //open CustomPicker +// // open UIUtils +// open ReactNative +// open Redirect +// @react.component +// let make = ( +// ~redirectProp: PaymentMethodListType.payment_method, +// ~fields: Types.redirectTypeJson, +// ~isScreenFocus, +// ~setConfirmButtonDataRef: React.element => unit, +// ~sessionObject: SessionsType.sessions=SessionsType.defaultToken, +// ) => { +// let (accountnum, setaccountnum) = React.useState(_ => None) +// let (isaccountnumValid, setisaccountnumValid) = React.useState(_ => None) +// let (routingnum, setroutingnum) = React.useState(_ => None) +// let (isroutingnumValid, setisroutingnumValid) = React.useState(_ => None) +// let (address, setaddress) = React.useState(_ => None) +// let (address2, setaddress2) = React.useState(_ => None) +// let (isAddressValid, setIsAddressValid) = React.useState(_ => None) +// let (isAddress2Valid, setIsAddress2Valid) = React.useState(_ => None) +// let (account, setaccount) = React.useState(_ => None) +// let (isNicknameSelected, setIsNicknameSelected) = React.useState(_ => false) +// //let (AddressIsFocus, setAddressIsFocus) = React.useState(_ => false) + +// let (name, setName) = React.useState(_ => None) +// let (isNameValid, setIsNameValid) = React.useState(_ => None) +// let (nameIsFocus, setNameIsFocus) = React.useState(_ => false) +// let (city, setcity) = React.useState(_ => None) +// let (iscityValid, setIscityValid) = React.useState(_ => None) +// let (nativeProp, _) = React.useContext(NativePropContext.nativePropContext) +// let (country, setCountry) = React.useState(_ => Some(nativeProp.hyperParams.country)) +// let (state, setState) = React.useState(_ => Some(nativeProp.hyperParams.state)) + +// let (blikCode, setBlikCode) = React.useState(_ => None) +// let (postalCode, setpostalCode) = React.useState(_ => None) +// let showAlert = AlertHook.useAlerts() +// let accounts = ["savings", "current"] // Hard Coded The Account_Type Fields in ACHBankDebi + +// let accountTypesList = accounts->Js.Array.sortInPlace + +// let accountItems = Bank.bankNameConverter(accountTypesList) + +// // let accountTypes: array = accountItems->Array.map(item => { +// // { +// // name: item.displayName, +// // value: item.hyperSwitch, +// // } +// // }) +// let (statesJson, setStatesJson) = React.useState(_ => None) + +// React.useEffect0(() => { +// // Dynamically import/download Postal codes and states JSON +// RequiredFieldsTypes.importStates("./../../utility/reusableCodeFromWeb/States.json") +// ->Promise.then(res => { +// setStatesJson(_ => Some(res.states)) +// Promise.resolve() +// }) +// ->Promise.catch(_ => { +// setStatesJson(_ => None) // W1 +// Promise.resolve() +// }) +// ->ignore + +// None +// }) + +// let getStateData = states => { +// states +// ->Utils.getStateNames(country->Option.getOr("")) +// ->Array.map((item): CustomPicker.customPickerType => { +// { +// name: item, +// value: item, +// } +// }) +// } +// let onChangeCountry = val => { +// setCountry(val) +// logger( +// ~logType=INFO, +// ~value=country->Option.getOr(""), +// ~category=USER_EVENT, +// ~eventName=COUNTRY_CHANGED, +// ~paymentMethod, +// ~paymentExperience?, +// (), +// ) +// } +// let onChangeState = val => { +// setState(val) +// logger( +// ~logType=INFO, +// ~value=country->Option.getOr(""), +// ~category=USER_EVENT, +// ~eventName=STATE_CHANGED, +// ~paymentMethod, +// ~paymentExperience?, +// (), +// ) +// } + +// let onChangeBank = val => { +// setSelectedBank(val) +// } +// let onChangeAccountType = val => { +// setaccount(val) +// } + +// // let (accountnum, setaccountnum) = React.useState(_ => None) +// // let (isaccountnumValid, setisaccountnumValid) = React.useState(_ => None) +// // let (routingnum, setroutingnum) = React.useState(_ => None) +// // let (isroutingnumValid, setisroutingnumValid) = React.useState(_ => None) +// // let (address, setaddress) = React.useState(_ => None) +// // let (address2, setaddress2) = React.useState(_ => None) +// // let (isAddressValid, setIsAddressValid) = React.useState(_ => None) +// // let (isAddress2Valid, setIsAddress2Valid) = React.useState(_ => None) +// // //let (account, setaccount) = React.useState(_ => None) +// // let (account, setaccount) = React.useState((): option => None) + +// // let (isNicknameSelected, setIsNicknameSelected) = React.useState(_ => false) +// // let (nativeProp, _) = React.useContext(NativePropContext.nativePropContext) +// // let (country, setCountry) = React.useState(_ => Some(nativeProp.hyperParams.country)) +// // let (postalCode, setpostalCode) = React.useState(_ => None) +// // let (name, setName) = React.useState(_ => None) +// // let (statesJson, setStatesJson) = React.useState(_ => None) +// // let (allApiData, _) = React.useContext(AllApiDataContext.allApiDataContext) +// // let (iscityValid, setIscityValid) = React.useState(_ => None) +// // let (city, setcity) = React.useState(_ => None) + +// // let {component, borderWidth, borderRadius} = ThemebasedStyle.useThemeBasedStyle() + +// // let accounts = ["savings", "current"] // Hard Coded The Account_Type Fields in ACHBankDebi + +// // let accountTypesList = accounts->Js.Array.sortInPlace + +// // let accountItems = Bank.bankNameConverter(accountTypesList) + +// // let accountTypes: array = accountItems->Array.map(item => { +// // { +// // name: item.displayName, +// // value: item.hyperSwitch, +// // } +// // }) + +// // React.useEffect0(() => { +// // // Dynamically import/download Postal codes and states JSON +// // RequiredFieldsTypes.importStates("./../../utility/reusableCodeFromWeb/States.json") +// // ->Promise.then(res => { +// // setStatesJson(_ => Some(res.states)) +// // Promise.resolve() +// // }) +// // ->Promise.catch(_ => { +// // setStatesJson(_ => None) +// // Promise.resolve() +// // }) +// // ->ignore + +// // None +// // }) + +// // let getStateData = states => { +// // states +// // ->Utils.getStateNames(country->Option.getOr("")) +// // ->Array.map((item): CustomPicker.customPickerType => { +// // { +// // name: item, +// // value: item, +// // } +// // }) +// // } + +// // let onChangeAccountType = val => { +// // setaccount(val) +// // } +// // let onChangePostalCode = (val: string) => { +// // let onlyNumerics = val->String.replaceRegExp(%re("/\D+/g"), "") +// // let firstPart = onlyNumerics->String.slice(~start=0, ~end=3) +// // let secondPart = onlyNumerics->String.slice(~start=3, ~end=6) + +// // let finalVal = if onlyNumerics->String.length <= 3 { +// // firstPart +// // } else if onlyNumerics->String.length > 3 && onlyNumerics->String.length <= 6 { +// // `${firstPart}-${secondPart}` +// // } else { +// // onlyNumerics +// // } +// // setpostalCode(_ => Some(finalVal)) +// // } + +// // // let processRequest = ( +// // // ~payment_method_data, +// // // ~payment_method, +// // // ~payment_method_type, +// // // ~payment_experience_type="redirect_to_url", +// // // ~eligible_connectors=?, +// // // (), +// // // ) => { +// // // let body: redirectType = { +// // // client_secret: nativeProp.clientSecret, +// // // return_url: ?Utils.getReturnUrl(nativeProp.hyperParams.appId), +// // // payment_method, +// // // payment_method_type, +// // // payment_experience: payment_experience_type, +// // // connector: ?eligible_connectors, +// // // payment_method_data, +// // // billing: ?nativeProp.configuration.defaultBillingDetails, +// // // shipping: ?nativeProp.configuration.shippingDetails, +// // // setup_future_usage: ?( +// // // allApiData.additionalPMLData.mandateType == NORMAL ? Some("off_session") : None +// // // ), +// // // payment_type: ?allApiData.additionalPMLData.paymentType, +// // // browser_info: { +// // // user_agent: ?nativeProp.hyperParams.userAgent, +// // // language: ?nativeProp.configuration.appearance.locale, +// // // }, +// // // } +// // // } + +// // // let processRequestBankDebit = (prop: payment_method_types_ach_bank_debit) => { +// // // let payment_method_data = +// // // [ +// // // ( +// // // prop.payment_method, +// // // [ +// // // ( +// // // "ach_bank_debit", +// // // [ +// // // ("account_number", accountnum->Option.getOr("")->JSON.Encode.string), +// // // ("routing_number", routingnum->Option.getOr("")->JSON.Encode.string), +// // // // ("name", name->Option.getOr("")->JSON.Encode.string), +// // // ] +// // // ->Dict.fromArray +// // // ->JSON.Encode.object, +// // // ), +// // // ] +// // // ->Dict.fromArray +// // // ->JSON.Encode.object, +// // // ), +// // // ( +// // // "billing", +// // // [ +// // // ( +// // // "address", +// // // [ +// // // ( +// // // "first_name", +// // // switch name { +// // // | Some(text) => text->String.split(" ")->Array.get(0) +// // // | _ => Some("") +// // // } +// // // ->Option.getOr("") +// // // ->JSON.Encode.string, +// // // ), +// // // ( +// // // "last_name", +// // // switch name { +// // // | Some(text) => text->String.split(" ")->Array.get(1) +// // // | _ => Some("") +// // // } +// // // ->Option.getOr("") +// // // ->JSON.Encode.string, +// // // ), +// // // ] +// // // ->Dict.fromArray +// // // ->JSON.Encode.object, +// // // ), +// // // ] +// // // ->Dict.fromArray +// // // ->JSON.Encode.object, +// // // ), +// // // ] +// // // ->Dict.fromArray +// // // ->JSON.Encode.object + +// // // processRequest( +// // // ~payment_method_data, +// // // ~payment_method=prop.payment_method, +// // // ~payment_method_type=prop.payment_method_type, +// // // //setup_future_usage:"off_session", +// // // (), +// // // ) +// // // } +// // let handlecity = text => { +// // let y = if text->String.length >= 3 { +// // Some(true) +// // } else { +// // None +// // } +// // setIscityValid(_ => y) +// // setcity(_ => Some(text)) +// // } +// // let handleAddress1 = text => { +// // let y = if text->String.length >= 5 { +// // Some(true) +// // } else { +// // None +// // } +// // setIsAddressValid(_ => y) +// // setaddress(_ => Some(text)) +// // } +// // let handleAddress2 = text => { +// // let y = if text->String.length >= 5 { +// // Some(true) +// // } else { +// // None +// // } +// // setIsAddress2Valid(_ => y) +// // setaddress2(_ => Some(text)) +// // } +// // let handlePressAccNum = text => { +// // let y = if text->String.length >= 10 { +// // Some(true) +// // } else { +// // None +// // } +// // setisaccountnumValid(_ => y) +// // setaccountnum(_ => Some(text)) +// // } + +// // let handlePressRouNum = number => { +// // let y = if number->String.length >= 9 { +// // Some(true) +// // } else { +// // None +// // } +// // setisroutingnumValid(_ => y) +// // setroutingnum(_ => Some(number)) +// // } + +// // <> +// // +// // +// // String.length > 0}> +// // +// // +// // {<> +// // +// // {fields.fields +// // ->Array.mapWithIndex((field, index) => +// // Int.toString}`}> +// // +// // {switch field { +// // // | "email" => +// // // Option.getOr("")} +// // // setState={handlePressEmail} +// // // placeholder=localeObject.emailLabel +// // // keyboardType=#"email-address" +// // // borderBottomLeftRadius=borderRadius +// // // borderBottomRightRadius=borderRadius +// // // borderTopLeftRadius=borderRadius +// // // borderTopRightRadius=borderRadius +// // // borderTopWidth=borderWidth +// // // borderBottomWidth=borderWidth +// // // borderLeftWidth=borderWidth +// // // borderRightWidth=borderWidth +// // // isValid=isEmailValidForFocus +// // // onFocus={_ => { +// // // setEmailIsFocus(_ => true) +// // // }} +// // // onBlur={_ => { +// // // setEmailIsFocus(_ => false) +// // // }} +// // // textColor=component.color +// // // /> + +// // // | "name" => +// // // Option.getOr("")} +// // // setState={handlePressName} +// // // placeholder=localeObject.fullNameLabel +// // // keyboardType=#default +// // // isValid=isNameValidForFocus +// // // onFocus={_ => { +// // // setNameIsFocus(_ => true) +// // // }} +// // // onBlur={_ => { +// // // setNameIsFocus(_ => false) +// // // }} +// // // textColor=component.color +// // // borderBottomLeftRadius=borderRadius +// // // borderBottomRightRadius=borderRadius +// // // borderTopLeftRadius=borderRadius +// // // borderTopRightRadius=borderRadius +// // // borderTopWidth=borderWidth +// // // borderBottomWidth=borderWidth +// // // borderLeftWidth=borderWidth +// // // borderRightWidth=borderWidth +// // // /> +// // | "Address_Line_1" => +// // Option.getOr("")} +// // setState={handleAddress1} +// // placeholder="Address Line 1" +// // keyboardType=#default +// // // isValid=isAddressValid +// // // onFocus={_ => { +// // // setAddressIsFocus(_ => true) +// // // }} +// // // onBlur={_ => { +// // // setAddressIsFocus(_ => false) +// // // }} +// // textColor=component.color +// // borderBottomLeftRadius=borderRadius +// // borderBottomRightRadius=borderRadius +// // borderTopLeftRadius=borderRadius +// // borderTopRightRadius=borderRadius +// // borderTopWidth=borderWidth +// // borderBottomWidth=borderWidth +// // borderLeftWidth=borderWidth +// // borderRightWidth=borderWidth +// // /> + +// // | "Address_Line_2" => +// // Option.getOr("")} +// // setState={handleAddress2} +// // placeholder="Address Line 2" +// // keyboardType=#default +// // textColor=component.color +// // borderBottomLeftRadius=borderRadius +// // borderBottomRightRadius=borderRadius +// // borderTopLeftRadius=borderRadius +// // borderTopRightRadius=borderRadius +// // borderTopWidth=borderWidth +// // borderBottomWidth=borderWidth +// // borderLeftWidth=borderWidth +// // borderRightWidth=borderWidth +// // /> +// // | "City" => +// // Option.getOr("")} +// // setState={handlecity} +// // placeholder="City" +// // keyboardType=#default +// // textColor=component.color +// // borderBottomLeftRadius=borderRadius +// // borderBottomRightRadius=borderRadius +// // borderTopLeftRadius=borderRadius +// // borderTopRightRadius=borderRadius +// // borderTopWidth=borderWidth +// // borderBottomWidth=borderWidth +// // borderLeftWidth=borderWidth +// // borderRightWidth=borderWidth +// // /> +// // // | "country" => +// // // +// // // | "State" => +// // // switch statesJson { +// // // | Some(states) => +// // // getStateData} +// // // placeholderText=localeObject.stateLabel +// // // /> +// // // | None => React.null +// // // } +// // // | "bank" => +// // // +// // | "account_type" => +// // <> +// // +// // +// // +// // +// // // + +// // +// // +// // +// // // +// // // +// // // +// // // +// // +// // // | "blik_code" => +// // // Option.getOr("")} +// // // setState={onChangeBlikCode} +// // // borderBottomLeftRadius=borderRadius +// // // borderBottomRightRadius=borderRadius +// // // borderBottomWidth=borderWidth +// // // placeholder="000-000" +// // // keyboardType=#numeric +// // // maxLength=Some(7) +// // // /> +// // | "postal_code" => +// // Option.getOr("")} +// // setState={onChangePostalCode} +// // borderBottomLeftRadius=borderRadius +// // borderBottomRightRadius=borderRadius +// // borderBottomWidth=borderWidth +// // placeholder="Postal Code" +// // keyboardType=#numeric +// // maxLength=Some(7) +// // /> + +// // | "account_number" => +// // Option.getOr("")} +// // setState={handlePressAccNum} +// // placeholder="Account Number" +// // borderBottomLeftRadius=borderRadius +// // borderBottomRightRadius=borderRadius +// // borderBottomWidth=borderWidth +// // maxLength=Some(12) +// // keyboardType=#numeric +// // /> +// // | "routing_number" => +// // Option.getOr("")} +// // setState={handlePressRouNum} +// // placeholder="Routing Number" +// // keyboardType=#numeric +// // borderBottomLeftRadius=borderRadius +// // borderBottomRightRadius=borderRadius +// // borderBottomWidth=borderWidth +// // maxLength=Some(9) +// // /> + +// // | _ => React.null +// // }} +// // +// // ) +// // ->React.array} +// // +// // // +// // } +// // +// // +// // +// // } + +// let paymentMethod = switch redirectProp { +// | CARD(prop) => prop.payment_method_type +// | WALLET(prop) => prop.payment_method_type +// | PAY_LATER(prop) => prop.payment_method_type +// | BANK_REDIRECT(prop) => prop.payment_method_type +// | CRYPTO(prop) => prop.payment_method_type +// | OPEN_BANKING(prop) => prop.payment_method_type +// | BANK_DEBIT(prop) => prop.payment_method_type +// } + +// +// +// {switch paymentMethod { +// | "ach" => +// | _ => React.null +// }} +// {<> +// +// String.length > 0}> +// +// +// { +// let isKlarna = true /* or appropriate logic to determine if it's Klarna */ +// KlarnaModule.klarnaReactPaymentView->Option.isSome && fields.name == "klarna" && isKlarna +// ? <> +// +// // +// // +// +// : <> +// {fields.fields +// ->Array.mapWithIndex((field, index) => +// Int.toString}`}> +// +// {switch field { +// | "email" => +// Option.getOr("")} +// setState={handlePressEmail} +// placeholder=localeObject.emailLabel +// keyboardType=#"email-address" +// borderBottomLeftRadius=borderRadius +// borderBottomRightRadius=borderRadius +// borderTopLeftRadius=borderRadius +// borderTopRightRadius=borderRadius +// borderTopWidth=borderWidth +// borderBottomWidth=borderWidth +// borderLeftWidth=borderWidth +// borderRightWidth=borderWidth +// isValid=isEmailValidForFocus +// onFocus={_ => { +// setEmailIsFocus(_ => true) +// }} +// onBlur={_ => { +// setEmailIsFocus(_ => false) +// }} +// textColor=component.color +// /> + +// | "name" => +// Option.getOr("")} +// setState={handlePressName} +// placeholder=localeObject.fullNameLabel +// keyboardType=#default +// isValid=isNameValidForFocus +// onFocus={_ => { +// setNameIsFocus(_ => true) +// }} +// onBlur={_ => { +// setNameIsFocus(_ => false) +// }} +// textColor=component.color +// borderBottomLeftRadius=borderRadius +// borderBottomRightRadius=borderRadius +// borderTopLeftRadius=borderRadius +// borderTopRightRadius=borderRadius +// borderTopWidth=borderWidth +// borderBottomWidth=borderWidth +// borderLeftWidth=borderWidth +// borderRightWidth=borderWidth +// /> + +// | "country" => +// + +// | "State" => +// switch statesJson { +// | Some(states) => +// getStateData} +// placeholderText=localeObject.stateLabel +// /> +// | None => React.null +// } + +// | "bank" => +// + +// | "blik_code" => +// Option.getOr("")} +// setState={onChangeBlikCode} +// borderBottomLeftRadius=borderRadius +// borderBottomRightRadius=borderRadius +// borderBottomWidth=borderWidth +// placeholder="000-000" +// keyboardType=#numeric +// maxLength=Some(7) +// /> +// | "Address_Line_1" => +// Option.getOr("")} +// setState={handleAddress1} +// placeholder="Address Line 1" +// keyboardType=#default +// textColor=component.color +// borderBottomLeftRadius=borderRadius +// borderBottomRightRadius=borderRadius +// borderTopLeftRadius=borderRadius +// borderTopRightRadius=borderRadius +// borderTopWidth=borderWidth +// borderBottomWidth=borderWidth +// borderLeftWidth=borderWidth +// borderRightWidth=borderWidth +// /> + +// | "Address_Line_2" => +// Option.getOr("")} +// setState={handleAddress2} +// placeholder="Address Line 2" +// keyboardType=#default +// textColor=component.color +// borderBottomLeftRadius=borderRadius +// borderBottomRightRadius=borderRadius +// borderTopLeftRadius=borderRadius +// borderTopRightRadius=borderRadius +// borderTopWidth=borderWidth +// borderBottomWidth=borderWidth +// borderLeftWidth=borderWidth +// borderRightWidth=borderWidth +// /> +// | "City" => +// Option.getOr("")} +// setState={handlecity} +// placeholder="City" +// keyboardType=#default +// textColor=component.color +// borderBottomLeftRadius=borderRadius +// borderBottomRightRadius=borderRadius +// borderTopLeftRadius=borderRadius +// borderTopRightRadius=borderRadius +// borderTopWidth=borderWidth +// borderBottomWidth=borderWidth +// borderLeftWidth=borderWidth +// borderRightWidth=borderWidth +// /> +// | "account_type" => +// <> +// +// +// +// +// +// +// +// + +// | "postal_code" => +// Option.getOr("")} +// setState={onChangePostalCode} +// borderBottomLeftRadius=borderRadius +// borderBottomRightRadius=borderRadius +// borderBottomWidth=borderWidth +// placeholder="Postal Code" +// keyboardType=#numeric +// maxLength=Some(120) +// /> + +// | "account_number" => +// Option.getOr("")} +// setState={handlePressAccNum} +// placeholder="Account Number" +// borderBottomLeftRadius=borderRadius +// borderBottomRightRadius=borderRadius +// borderBottomWidth=borderWidth +// maxLength=Some(12) +// keyboardType=#numeric +// /> +// | "routing_number" => +// Option.getOr("")} +// setState={handlePressRouNum} +// placeholder="Routing Number" +// keyboardType=#numeric +// borderBottomLeftRadius=borderRadius +// borderBottomRightRadius=borderRadius +// borderBottomWidth=borderWidth +// maxLength=Some(9) +// /> + +// | _ => React.null +// }} +// +// ) +// ->React.array} +// +// // +// {switch paymentMethod { +// | "ach" => React.null +// | _ => +// }} +// +// } +// +// +// } +// +// } + +// let mandate_data = +// [ +// ( +// "customer_acceptance", +// [ +// ("acceptance_type", "online"->JSON.Encode.string), +// ("accepted_at", Date.now()->Date.fromTime->Date.toISOString->JSON.Encode.string), +// ( +// "online", +// [ +// ( +// "ip_address", +// nativeProp.hyperParams.ip->Option.getOr("0.0.0.0")->JSON.Encode.string, +// ), +// ( +// "user_agent", +// nativeProp.hyperParams.userAgent->Option.getOr("Unknown")->JSON.Encode.string, +// ), +// ] +// ->Dict.fromArray +// ->JSON.Encode.object, +// ), +// ] +// ->Dict.fromArray +// ->JSON.Encode.object, +// ), +// ( +// "mandate_type", +// [ +// ( +// "multi_use", +// [ +// ("amount", 1000->JSON.Encode.int), +// ("currency", "USD"->JSON.Encode.string), +// ("start_date", "2024-04-21T00:00:00Z"->JSON.Encode.string), +// ("end_date", "2024-05-21T00:00:00Z"->JSON.Encode.string), +// ( +// "metadata", +// [("frequency", "13"->JSON.Encode.string)] +// ->Dict.fromArray +// ->JSON.Encode.object, +// ), +// ] +// ->Dict.fromArray +// ->JSON.Encode.object, +// ), +// ] +// ->Dict.fromArray +// ->JSON.Encode.object, +// ), +// ] +// ->Dict.fromArray +// ->JSON.Encode.object +// Console.log2("mandate_data", mandate_data) + diff --git a/src/pages/payment/Redirect.res b/src/pages/payment/Redirect.res index f9928b1..3c44437 100644 --- a/src/pages/payment/Redirect.res +++ b/src/pages/payment/Redirect.res @@ -33,6 +33,23 @@ let make = ( let (isEmailValid, setIsEmailValid) = React.useState(_ => None) let (emailIsFocus, setEmailIsFocus) = React.useState(_ => false) + let (accountnum, setaccountnum) = React.useState(_ => None) + let (isaccountnumValid, setisaccountnumValid) = React.useState(_ => None) + let (routingnum, setroutingnum) = React.useState(_ => None) + let (isroutingnumValid, setisroutingnumValid) = React.useState(_ => None) + let (address, setaddress) = React.useState(_ => None) + let (address2, setaddress2) = React.useState(_ => None) + let (isAddressValid, setIsAddressValid) = React.useState(_ => None) + let (isAddress2Valid, setIsAddress2Valid) = React.useState(_ => None) + let (account, setaccount) = React.useState(_ => None) + let (isNicknameSelected, setIsNicknameSelected) = React.useState(_ => false) + let (state, setState) = React.useState(_ => Some(nativeProp.hyperParams.state)) + let (postalCode, setpostalCode) = React.useState(_ => None) + let (city, setcity) = React.useState(_ => None) + let (iscityValid, setIscityValid) = React.useState(_ => None) + let (statesJson, setStatesJson) = React.useState(_ => None) + //let (AddressIsFocus, setAddressIsFocus) = React.useState(_ => false) + let (name, setName) = React.useState(_ => None) let (isNameValid, setIsNameValid) = React.useState(_ => None) let (nameIsFocus, setNameIsFocus) = React.useState(_ => false) @@ -66,6 +83,7 @@ let make = ( | BANK_REDIRECT(prop) => prop.payment_method_type | CRYPTO(prop) => prop.payment_method_type | OPEN_BANKING(prop) => prop.payment_method_type + | BANK_DEBIT(prop) => prop.payment_method_type } let paymentExperience = switch redirectProp { | CARD(_) => None @@ -88,6 +106,10 @@ let make = ( prop.payment_experience ->Array.get(0) ->Option.map(paymentExperience => paymentExperience.payment_experience_type_decode) + | BANK_DEBIT(prop) => + prop.payment_experience + ->Array.get(0) + ->Option.map(paymentExperience => paymentExperience.payment_experience_type_decode) } let paymentMethodType = switch redirectProp { | BANK_REDIRECT(prop) => prop.payment_method_type @@ -107,6 +129,18 @@ let make = ( value: item.hyperSwitch, } }) + let accounts = ["savings", "current"] // Hard Coded The Account_Type Fields in ACHBankDebi + + let accountTypesList = accounts->Js.Array.sortInPlace + + let accountItems = Bank.bankNameConverter(accountTypesList) + + let accountTypes: array = accountItems->Array.map(item => { + { + name: item.displayName, + value: item.hyperSwitch, + } + }) let countryData: array = Country.country->Array.map(item => { { @@ -116,6 +150,33 @@ let make = ( } }) + React.useEffect0(() => { + // Dynamically import/download Postal codes and states JSON + RequiredFieldsTypes.importStates("./../../utility/reusableCodeFromWeb/States.json") + ->Promise.then(res => { + setStatesJson(_ => Some(res.states)) + Promise.resolve() + }) + ->Promise.catch(_ => { + setStatesJson(_ => None) // W1 + Promise.resolve() + }) + ->ignore + + None + }) + + let getStateData = states => { + states + ->Utils.getStateNames(country->Option.getOr("")) + ->Array.map((item): CustomPicker.customPickerType => { + { + name: item, + value: item, + } + }) + } + let (selectedBank, setSelectedBank) = React.useState(_ => Some( switch bankItems->Array.get(0) { | Some(x) => x.hyperSwitch @@ -137,10 +198,25 @@ let make = ( (), ) } + let onChangeState = val => { + setState(val) + logger( + ~logType=INFO, + ~value=country->Option.getOr(""), + ~category=USER_EVENT, + ~eventName=STATE_CHANGED, + ~paymentMethod, + ~paymentExperience?, + (), + ) + } let onChangeBank = val => { setSelectedBank(val) } + let onChangeAccountType = val => { + setaccount(val) + } let onChangeBlikCode = (val: string) => { let onlyNumerics = val->String.replaceRegExp(%re("/\D+/g"), "") @@ -157,6 +233,11 @@ let make = ( setBlikCode(_ => Some(finalVal)) } + let onChangePostalCode = (val: string) => { + let onlyNumerics = val->String.replaceRegExp(%re("/\D+/g"), "") + setpostalCode(_ => Some(onlyNumerics)) + } + let (error, setError) = React.useState(_ => None) let handleSuccessFailure = AllPaymentHooks.useHandleSuccessFailure() @@ -229,23 +310,35 @@ let make = ( billing: ?nativeProp.configuration.defaultBillingDetails, shipping: ?nativeProp.configuration.shippingDetails, setup_future_usage: ?( - allApiData.additionalPMLData.mandateType != NORMAL ? Some("off_session") : None + // "off_session", + allApiData.additionalPMLData.mandateType == NORMAL ? Some("off_session") : None ), payment_type: ?allApiData.additionalPMLData.paymentType, - // mandate_data: ?( - // allApiData.mandateType != NORMAL - // ? Some({ - // customer_acceptance: { - // acceptance_type: "online", - // accepted_at: Date.now()->Date.fromTime->Date.toISOString, - // online: { - // ip_address: ?nativeProp.hyperParams.ip, - // user_agent: ?nativeProp.hyperParams.userAgent, - // }, - // }, - // }) - // : None - // ), + mandate_data: ?( + allApiData.additionalPMLData.mandateType == NORMAL + ? Some({ + customer_acceptance: { + acceptance_type: "offline", + accepted_at: "1963-05-03T04:07:52.723Z", + online: { + ip_address: "125.0.0.1", + user_agent: "amet irure esse", + }, + }, + mandate_type: { + multi_use: { + amount: 1000, + currency: "USD", + start_date: "2023-04-21T00:00:00Z", + end_date: "2023-05-21T00:00:00Z", + metadata: { + frequency: "13", + }, + }, + }, + }) + : None + ), customer_acceptance: ?( allApiData.additionalPMLData.mandateType->PaymentUtils.checkIfMandate ? Some({ @@ -786,6 +879,69 @@ let make = ( ) } + let processRequestBankDebit = (prop: payment_method_types_ach_bank_debit) => { + let payment_method_data = + [ + ( + prop.payment_method, + [ + ( + "ach_bank_debit", + [ + ("account_number", accountnum->Option.getOr("")->JSON.Encode.string), + ("routing_number", routingnum->Option.getOr("")->JSON.Encode.string), + ] + ->Dict.fromArray + ->JSON.Encode.object, + ), + ] + ->Dict.fromArray + ->JSON.Encode.object, + ), + ( + "billing", + [ + ( + "address", + [ + ( + "first_name", + switch name { + | Some(text) => text->String.split(" ")->Array.get(0) + | _ => Some("") + } + ->Option.getOr("") + ->JSON.Encode.string, + ), + ( + "last_name", + switch name { + | Some(text) => text->String.split(" ")->Array.get(1) + | _ => Some("") + } + ->Option.getOr("") + ->JSON.Encode.string, + ), + ] + ->Dict.fromArray + ->JSON.Encode.object, + ), + ] + ->Dict.fromArray + ->JSON.Encode.object, + ), + ] + ->Dict.fromArray + ->JSON.Encode.object + + processRequest( + ~payment_method_data, + ~payment_method=prop.payment_method, + ~payment_method_type=prop.payment_method_type, + (), + ) + } + let handlePress = _ => { setLoading(ProcessingPayments(None)) switch redirectProp { @@ -797,6 +953,7 @@ let make = ( | CRYPTO(prop) => processRequestCrypto(prop) | WALLET(prop) => processRequestWallet(prop) | OPEN_BANKING(prop) => processRequestOpenBanking(prop) + | BANK_DEBIT(prop) => processRequestBankDebit(prop) | _ => () } } @@ -814,20 +971,84 @@ let make = ( setIsNameValid(_ => y) setName(_ => Some(text)) } + let handlecity = text => { + let y = if text->String.length >= 3 { + Some(true) + } else { + None + } + setIscityValid(_ => y) + setcity(_ => Some(text)) + } + let handleAddress1 = text => { + let y = if text->String.length >= 5 { + Some(true) + } else { + None + } + setIsAddressValid(_ => y) + setaddress(_ => Some(text)) + } + let handleAddress2 = text => { + let y = if text->String.length >= 5 { + Some(true) + } else { + None + } + setIsAddress2Valid(_ => y) + setaddress2(_ => Some(text)) + } + let handlePressAccNum = number => { + let onlyNumerics = number->String.replaceRegExp(%re("/\D+/g"), "") + let y = if number->String.length === 12 { + Some(true) + } else { + None + } + setisaccountnumValid(_ => y) + setaccountnum(_ => Some(onlyNumerics)) + } + + let handlePressRouNum = number => { + let onlyNumerics = number->String.replaceRegExp(%re("/\D+/g"), "") + let y = if number->String.length === 9 { + Some(true) + } else { + None + } + setisroutingnumValid(_ => y) + setroutingnum(_ => Some(onlyNumerics)) + } + let isEmailValidForFocus = { emailIsFocus ? true : isEmailValid->Option.getOr(true) } let isNameValidForFocus = { nameIsFocus ? true : isNameValid->Option.getOr(true) } + // let isAddressValidForFocus = { + // AddressIsFocus ? true : isAddressValid->Option.getOr(true) + // } let hasSomeFields = fields.fields->Array.length > 0 - let isAllValuesValid = React.useMemo3(() => { - ((fields.fields->Array.includes("email") ? isEmailValid->Option.getOr(false) : true) && ( - fields.fields->Array.includes("name") ? isNameValid->Option.getOr(false) : true + // let isAllValuesValid = React.useMemo3(() => { + // ((fields.fields->Array.includes("email") ? isEmailValid->Option.getOr(false) : true) && ( + // fields.fields->Array.includes("name") ? isNameValid->Option.getOr(false) : true + // )) || (fields.name == "klarna" && isKlarna) + // }, (isEmailValid, isNameValid, allApiData.sessions)) + let isAllValuesValid = React.useMemo5(() => { + ((fields.fields->Array.includes("email") ? isEmailValid->Option.getOr(false) : true) && + (fields.fields->Array.includes("name") ? isNameValid->Option.getOr(false) : true) && + (fields.fields->Array.includes("routing_number") + ? isroutingnumValid->Option.getOr(false) + : true) && + (fields.fields->Array.includes("account_number") + ? isaccountnumValid->Option.getOr(false) + : true) && ( + fields.fields->Array.includes("account_type") ? isaccountnumValid->Option.getOr(false) : true )) || (fields.name == "klarna" && isKlarna) - }, (isEmailValid, isNameValid, allApiData.sessions)) + }, (isEmailValid, isNameValid, isaccountnumValid, isroutingnumValid, allApiData.sessions)) React.useEffect(() => { if isScreenFocus { @@ -858,115 +1079,252 @@ let make = ( selectedBank, )) - <> + - - String.length > 0}> - - - {KlarnaModule.klarnaReactPaymentView->Option.isSome && fields.name == "klarna" && isKlarna - ? <> - - - - - : <> - {fields.fields - ->Array.mapWithIndex((field, index) => - Int.toString}`}> - - {switch field { - | "email" => - Option.getOr("")} - setState={handlePressEmail} - placeholder=localeObject.emailLabel - keyboardType=#"email-address" - borderBottomLeftRadius=borderRadius - borderBottomRightRadius=borderRadius - borderTopLeftRadius=borderRadius - borderTopRightRadius=borderRadius - borderTopWidth=borderWidth - borderBottomWidth=borderWidth - borderLeftWidth=borderWidth - borderRightWidth=borderWidth - isValid=isEmailValidForFocus - onFocus={_ => { - setEmailIsFocus(_ => true) - }} - onBlur={_ => { - setEmailIsFocus(_ => false) - }} - textColor=component.color - /> - | "name" => - Option.getOr("")} - setState={handlePressName} - placeholder=localeObject.fullNameLabel - keyboardType=#default - isValid=isNameValidForFocus - onFocus={_ => { - setNameIsFocus(_ => true) - }} - onBlur={_ => { - setNameIsFocus(_ => false) - }} - textColor=component.color - borderBottomLeftRadius=borderRadius - borderBottomRightRadius=borderRadius - borderTopLeftRadius=borderRadius - borderTopRightRadius=borderRadius - borderTopWidth=borderWidth - borderBottomWidth=borderWidth - borderLeftWidth=borderWidth - borderRightWidth=borderWidth - /> - | "country" => - - | "bank" => - - | "blik_code" => - Option.getOr("")} - setState={onChangeBlikCode} - borderBottomLeftRadius=borderRadius - borderBottomRightRadius=borderRadius - borderBottomWidth=borderWidth - placeholder="000-000" - keyboardType=#numeric - maxLength=Some(7) - /> - | _ => React.null - }} - - ) - ->React.array} - - - } - - - + {switch paymentMethod { + | "ach" => + | _ => React.null + }} + {<> + + String.length > 0}> + + + {KlarnaModule.klarnaReactPaymentView->Option.isSome && fields.name == "klarna" && isKlarna + ? <> + + + + + : <> + {fields.fields + ->Array.mapWithIndex((field, index) => + Int.toString}`}> + + {switch field { + | "email" => + Option.getOr("")} + setState={handlePressEmail} + placeholder=localeObject.emailLabel + keyboardType=#"email-address" + borderBottomLeftRadius=borderRadius + borderBottomRightRadius=borderRadius + borderTopLeftRadius=borderRadius + borderTopRightRadius=borderRadius + borderTopWidth=borderWidth + borderBottomWidth=borderWidth + borderLeftWidth=borderWidth + borderRightWidth=borderWidth + isValid=isEmailValidForFocus + onFocus={_ => { + setEmailIsFocus(_ => true) + }} + onBlur={_ => { + setEmailIsFocus(_ => false) + }} + textColor=component.color + /> + | "name" => + Option.getOr("")} + setState={handlePressName} + placeholder=localeObject.fullNameLabel + keyboardType=#default + isValid=isNameValidForFocus + onFocus={_ => { + setNameIsFocus(_ => true) + }} + onBlur={_ => { + setNameIsFocus(_ => false) + }} + textColor=component.color + borderBottomLeftRadius=borderRadius + borderBottomRightRadius=borderRadius + borderTopLeftRadius=borderRadius + borderTopRightRadius=borderRadius + borderTopWidth=borderWidth + borderBottomWidth=borderWidth + borderLeftWidth=borderWidth + borderRightWidth=borderWidth + /> + | "country" => + + + | "State" => + switch statesJson { + | Some(states) => + getStateData} + placeholderText=localeObject.stateLabel + /> + | None => React.null + } + + | "bank" => + + | "blik_code" => + Option.getOr("")} + setState={onChangeBlikCode} + borderBottomLeftRadius=borderRadius + borderBottomRightRadius=borderRadius + borderBottomWidth=borderWidth + placeholder="000-000" + keyboardType=#numeric + maxLength=Some(7) + /> + | "Address_Line_1" => + Option.getOr("")} + setState={handleAddress1} + placeholder="Address Line 1" + keyboardType=#default + textColor=component.color + borderBottomLeftRadius=borderRadius + borderBottomRightRadius=borderRadius + borderTopLeftRadius=borderRadius + borderTopRightRadius=borderRadius + borderTopWidth=borderWidth + borderBottomWidth=borderWidth + borderLeftWidth=borderWidth + borderRightWidth=borderWidth + /> + + | "Address_Line_2" => + Option.getOr("")} + setState={handleAddress2} + placeholder="Address Line 2" + keyboardType=#default + textColor=component.color + borderBottomLeftRadius=borderRadius + borderBottomRightRadius=borderRadius + borderTopLeftRadius=borderRadius + borderTopRightRadius=borderRadius + borderTopWidth=borderWidth + borderBottomWidth=borderWidth + borderLeftWidth=borderWidth + borderRightWidth=borderWidth + /> + | "City" => + Option.getOr("")} + setState={handlecity} + placeholder="City" + keyboardType=#default + textColor=component.color + borderBottomLeftRadius=borderRadius + borderBottomRightRadius=borderRadius + borderTopLeftRadius=borderRadius + borderTopRightRadius=borderRadius + borderTopWidth=borderWidth + borderBottomWidth=borderWidth + borderLeftWidth=borderWidth + borderRightWidth=borderWidth + /> + | "account_type" => + <> + + + + + + + + + + | "postal_code" => + Option.getOr("")} + setState={onChangePostalCode} + borderBottomLeftRadius=borderRadius + borderBottomRightRadius=borderRadius + borderBottomWidth=borderWidth + placeholder="Postal Code" + keyboardType=#numeric + maxLength=Some(120) + /> + + | "account_number" => + Option.getOr("")} + setState={handlePressAccNum} + placeholder="Account Number" + borderBottomLeftRadius=borderRadius + borderBottomRightRadius=borderRadius + borderBottomWidth=borderWidth + maxLength=Some(12) + keyboardType=#numeric + /> + | "routing_number" => + Option.getOr("")} + setState={handlePressRouNum} + placeholder="Routing Number" + keyboardType=#numeric + borderBottomLeftRadius=borderRadius + borderBottomRightRadius=borderRadius + borderBottomWidth=borderWidth + maxLength=Some(9) + /> + + | _ => React.null + }} + + ) + ->React.array} + + {switch paymentMethod { + | "ach" => React.null + | _ => + }} + } + + + } + } diff --git a/src/types/LoggerTypes.res b/src/types/LoggerTypes.res index 935204f..f3f14c3 100644 --- a/src/types/LoggerTypes.res +++ b/src/types/LoggerTypes.res @@ -7,6 +7,7 @@ type eventName = | APP_RENDERED | INACTIVE_SCREEN | COUNTRY_CHANGED + | STATE_CHANGED | SDK_CLOSED | PAYMENT_METHOD_CHANGED | PAYMENT_DATA_FILLED diff --git a/src/types/PaymentMethodListType.res b/src/types/PaymentMethodListType.res index 846e44c..e805fd6 100644 --- a/src/types/PaymentMethodListType.res +++ b/src/types/PaymentMethodListType.res @@ -63,6 +63,14 @@ type payment_method_types_open_banking = { required_field: RequiredFieldsTypes.required_fields, } +type payment_method_types_ach_bank_debit = { + payment_method: string, + payment_method_type: string, + payment_experience: array, // ACHBankDebit + required_field: RequiredFieldsTypes.required_fields, + mandate_data: string, +} + type payment_method = | CARD(payment_method_types_card) | WALLET(payment_method_types_wallet) @@ -70,6 +78,13 @@ type payment_method = | BANK_REDIRECT(payment_method_types_bank_redirect) | CRYPTO(payment_method_types_pay_later) | OPEN_BANKING(payment_method_types_open_banking) + | BANK_DEBIT(payment_method_types_ach_bank_debit) // ACHBankDebit + +type payment_method_type = { + payment_method: string, + payment_method_type: string, + required_field: array, +} type online = { ip_address?: string, @@ -88,7 +103,17 @@ type customer_acceptance = { accepted_at: string, online: online, } -type mandate_data = {customer_acceptance: customer_acceptance} +type mandate_type_meta_data = {frequency: string} +type multi_use = { + amount: int, + currency: string, + start_date: string, + end_date: string, + metadata: mandate_type_meta_data, +} +type mandate_type = {multi_use: multi_use} +type mandate_data = {customer_acceptance: customer_acceptance, mandate_type: mandate_type} + type redirectType = { client_secret: string, return_url?: string, @@ -105,6 +130,7 @@ type redirectType = { setup_future_usage?: string, payment_type?: string, mandate_data?: mandate_data, + mandate_type?: mandate_type, browser_info?: online, customer_acceptance?: customer_acceptance, card_cvc?: string, @@ -227,7 +253,7 @@ let flattenPaymentListArray = (plist, item) => { required_field: dict2->RequiredFieldsTypes.getRequiredFieldsFromDict, })->Js.Array.push(plist) }) - | "open_banking" => + | "open_banking" => payment_method_types_array->Array.map(item2 => { let dict2 = item2->getDictFromJson OPEN_BANKING({ @@ -249,6 +275,29 @@ let flattenPaymentListArray = (plist, item) => { required_field: dict2->RequiredFieldsTypes.getRequiredFieldsFromDict, })->Js.Array.push(plist) }) + | "bank_debit" => + payment_method_types_array->Array.map(item2 => { + let dict2 = item2->getDictFromJson + BANK_DEBIT({ + payment_method: "bank_debit", + mandate_data: dict2->getString("mandate_data", ""), + payment_method_type: dict2->getString("payment_method_type", ""), + payment_experience: dict2 + ->getArray("payment_experience") + ->Array.map(item3 => { + let dict3 = item3->getDictFromJson + { + payment_experience_type: dict3->getString("payment_experience_type", ""), + payment_experience_type_decode: switch dict3->getString("payment_experience_type", "") { + | "redirect_to_url" => REDIRECT_TO_URL + | _ => NONE + }, + eligible_connectors: dict3->getArray("eligible_connectors"), + } + }), + required_field: dict2->RequiredFieldsTypes.getRequiredFieldsFromDict, + })->Js.Array.push(plist) + }) | _ => [] }->ignore @@ -263,6 +312,7 @@ let getPaymentMethodType = pm => { | BANK_REDIRECT(payment_method_type) => payment_method_type.payment_method_type | CRYPTO(payment_method_type) => payment_method_type.payment_method_type | OPEN_BANKING(payment_method_type) => payment_method_type.payment_method_type + | BANK_DEBIT(payment_method_type) => payment_method_type.payment_method_type } } @@ -356,7 +406,8 @@ let getPaymentBody = (body, dynamicFieldsJson) => { } let jsonToSavedPMObj = data => { - let customerSavedPMs = data->Utils.getDictFromJson->Utils.getArrayFromDict("customer_payment_methods", []) + let customerSavedPMs = + data->Utils.getDictFromJson->Utils.getArrayFromDict("customer_payment_methods", []) customerSavedPMs->Array.reduce([], (acc, obj) => { let savedPMData = obj->Utils.getDictFromJson diff --git a/src/types/RequiredFieldsTypes.res b/src/types/RequiredFieldsTypes.res index 78606da..ebba706 100644 --- a/src/types/RequiredFieldsTypes.res +++ b/src/types/RequiredFieldsTypes.res @@ -24,6 +24,8 @@ type paymentMethodsFields = | AddressState | AddressCountry(array) | BlikCode + | AccountNumber + | RoutingNumber | Currency(array) type requiredField = @@ -223,8 +225,7 @@ let checkIsValid = ( switch text->ValidationFunctions.isValidEmail { | Some(false) => Some(localeObject.emailInvalidText) | Some(true) => None - | None => - Some(localeObject.emailEmptyText) + | None => Some(localeObject.emailEmptyText) } | _ => None } @@ -290,6 +291,8 @@ let useGetPlaceholder = ( | AddressCountry(_) => localeObject.countryLabel | Currency(_) => localeObject.currencyLabel | InfoElement + | AccountNumber + | RoutingNumber | SpecialField(_) | UnKnownField(_) | PhoneNumber diff --git a/src/types/SdkTypes.res b/src/types/SdkTypes.res index 0c92bcf..451b97e 100644 --- a/src/types/SdkTypes.res +++ b/src/types/SdkTypes.res @@ -296,6 +296,7 @@ type hyperParams = { confirm: bool, appId?: string, country: string, + state: string, disableBranding: bool, ip: option, userAgent: option, @@ -913,6 +914,7 @@ let nativeJsonToRecord = (jsonFromNative, rootTag) => { hyperParams: { appId: ?getOptionString(hyperParams, "appId"), country: getString(hyperParams, "country", ""), + state: getString(hyperParams, "state", ""), disableBranding: getBool(hyperParams, "disableBranding", true), ip: getOptionString(hyperParams, "ip"), userAgent: getOptionString(hyperParams, "user-agent"), diff --git a/src/types/Types.res b/src/types/Types.res index 18d3348..eb80987 100644 --- a/src/types/Types.res +++ b/src/types/Types.res @@ -20,7 +20,15 @@ type config = { let defaultConfig = { priorityArr: { - let priorityArr = ["card", "klarna", "afterpay_clearpay", "crypto", "paypal", "google_pay"] + let priorityArr = [ + "card", + "klarna", + "afterpay_clearpay", + "ach", + "crypto", + "paypal", + "google_pay", + ] priorityArr->Array.reverse priorityArr }, @@ -97,6 +105,23 @@ let defaultConfig = { header: "", fields: [], }, + { + name: "ach", + text: "Bank Debit", + header: "", + fields: [ + "name", + "routing_number", + "account_number", + "account_type", + "Address_Line_1", + "Address_Line_2", + "country", + "State", + "City", + "postal_code", + ], + }, // { // name: "google_pay", // text: "Google Pay", From 6427ad92ad5b0bfd6c5101f7a632d260bf5111ce Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Date: Thu, 7 Nov 2024 15:10:28 +0530 Subject: [PATCH 2/2] refactor(server): modified server --- server.js | 51 +- src/pages/payment/ACHBankDebit.res | 903 ----------------------------- 2 files changed, 4 insertions(+), 950 deletions(-) delete mode 100644 src/pages/payment/ACHBankDebit.res diff --git a/server.js b/server.js index 2f9fba0..ba6d068 100644 --- a/server.js +++ b/server.js @@ -22,57 +22,14 @@ app.get('/create-payment-intent', async (req, res) => { { amount: 6540, currency: 'USD', - // confirm: false, - // capture_method: 'automatic', - // capture_on: '2022-09-10T10:11:12Z', - // amount_to_capture: 6540, + customer_id: 'StripeCustomer', - // email: 'guest@example.com', - // name: 'John Doe', - // phone: '999999999', - // profile_id: 'pro_1PEZIEJyHhhZ3WJTVIVM', - // phone_country_code: '+65', - // description: 'Its my first payment request', - // authentication_type: 'three_ds', - // return_url: 'https://duck.com', - profile_id: "pro_E6k4XxWE3fVzTIYDMzJa", - //setup_future_usage: "off_session" - // billing: { - // address: { - // line1: '1467', - // line2: 'Harrison Street', - // line3: 'Harrison Street', - // city: 'San Fransico', - // state: 'California', - // zip: '94122', - // country: 'US', - // first_name: 'PiX', - // }, - // }, - // shipping: { - // address: { - // line1: '1467', - // line2: 'Harrison Street', - // line3: 'Harrison Street', - // city: 'San Fransico', - // state: 'California', - // zip: '94122', - // country: 'US', - // first_name: 'PiX', - // }, - // }, - // request_external_three_ds_authentication: true, - // statement_descriptor_name: 'joseph', - // statement_descriptor_suffix: 'JS', - // metadata: { - // udf1: 'value1', - // new_customer: 'true', - // login_date: '2019-09-10T10:11:12Z', - // } + + profile_id: process.env.HYPERSWITCH_PROFILE_ID, }); - // Send publishable key and PaymentIntent details to client + res.send({ publishableKey: process.env.HYPERSWITCH_PUBLISHABLE_KEY, clientSecret: paymentIntent.client_secret, diff --git a/src/pages/payment/ACHBankDebit.res b/src/pages/payment/ACHBankDebit.res deleted file mode 100644 index 2e41158..0000000 --- a/src/pages/payment/ACHBankDebit.res +++ /dev/null @@ -1,903 +0,0 @@ -// // open ReactNative -// // open PaymentMethodListType -// // open CustomPicker -// // open Redirect -// // //open CustomPicker -// // open UIUtils -// open ReactNative -// open Redirect -// @react.component -// let make = ( -// ~redirectProp: PaymentMethodListType.payment_method, -// ~fields: Types.redirectTypeJson, -// ~isScreenFocus, -// ~setConfirmButtonDataRef: React.element => unit, -// ~sessionObject: SessionsType.sessions=SessionsType.defaultToken, -// ) => { -// let (accountnum, setaccountnum) = React.useState(_ => None) -// let (isaccountnumValid, setisaccountnumValid) = React.useState(_ => None) -// let (routingnum, setroutingnum) = React.useState(_ => None) -// let (isroutingnumValid, setisroutingnumValid) = React.useState(_ => None) -// let (address, setaddress) = React.useState(_ => None) -// let (address2, setaddress2) = React.useState(_ => None) -// let (isAddressValid, setIsAddressValid) = React.useState(_ => None) -// let (isAddress2Valid, setIsAddress2Valid) = React.useState(_ => None) -// let (account, setaccount) = React.useState(_ => None) -// let (isNicknameSelected, setIsNicknameSelected) = React.useState(_ => false) -// //let (AddressIsFocus, setAddressIsFocus) = React.useState(_ => false) - -// let (name, setName) = React.useState(_ => None) -// let (isNameValid, setIsNameValid) = React.useState(_ => None) -// let (nameIsFocus, setNameIsFocus) = React.useState(_ => false) -// let (city, setcity) = React.useState(_ => None) -// let (iscityValid, setIscityValid) = React.useState(_ => None) -// let (nativeProp, _) = React.useContext(NativePropContext.nativePropContext) -// let (country, setCountry) = React.useState(_ => Some(nativeProp.hyperParams.country)) -// let (state, setState) = React.useState(_ => Some(nativeProp.hyperParams.state)) - -// let (blikCode, setBlikCode) = React.useState(_ => None) -// let (postalCode, setpostalCode) = React.useState(_ => None) -// let showAlert = AlertHook.useAlerts() -// let accounts = ["savings", "current"] // Hard Coded The Account_Type Fields in ACHBankDebi - -// let accountTypesList = accounts->Js.Array.sortInPlace - -// let accountItems = Bank.bankNameConverter(accountTypesList) - -// // let accountTypes: array = accountItems->Array.map(item => { -// // { -// // name: item.displayName, -// // value: item.hyperSwitch, -// // } -// // }) -// let (statesJson, setStatesJson) = React.useState(_ => None) - -// React.useEffect0(() => { -// // Dynamically import/download Postal codes and states JSON -// RequiredFieldsTypes.importStates("./../../utility/reusableCodeFromWeb/States.json") -// ->Promise.then(res => { -// setStatesJson(_ => Some(res.states)) -// Promise.resolve() -// }) -// ->Promise.catch(_ => { -// setStatesJson(_ => None) // W1 -// Promise.resolve() -// }) -// ->ignore - -// None -// }) - -// let getStateData = states => { -// states -// ->Utils.getStateNames(country->Option.getOr("")) -// ->Array.map((item): CustomPicker.customPickerType => { -// { -// name: item, -// value: item, -// } -// }) -// } -// let onChangeCountry = val => { -// setCountry(val) -// logger( -// ~logType=INFO, -// ~value=country->Option.getOr(""), -// ~category=USER_EVENT, -// ~eventName=COUNTRY_CHANGED, -// ~paymentMethod, -// ~paymentExperience?, -// (), -// ) -// } -// let onChangeState = val => { -// setState(val) -// logger( -// ~logType=INFO, -// ~value=country->Option.getOr(""), -// ~category=USER_EVENT, -// ~eventName=STATE_CHANGED, -// ~paymentMethod, -// ~paymentExperience?, -// (), -// ) -// } - -// let onChangeBank = val => { -// setSelectedBank(val) -// } -// let onChangeAccountType = val => { -// setaccount(val) -// } - -// // let (accountnum, setaccountnum) = React.useState(_ => None) -// // let (isaccountnumValid, setisaccountnumValid) = React.useState(_ => None) -// // let (routingnum, setroutingnum) = React.useState(_ => None) -// // let (isroutingnumValid, setisroutingnumValid) = React.useState(_ => None) -// // let (address, setaddress) = React.useState(_ => None) -// // let (address2, setaddress2) = React.useState(_ => None) -// // let (isAddressValid, setIsAddressValid) = React.useState(_ => None) -// // let (isAddress2Valid, setIsAddress2Valid) = React.useState(_ => None) -// // //let (account, setaccount) = React.useState(_ => None) -// // let (account, setaccount) = React.useState((): option => None) - -// // let (isNicknameSelected, setIsNicknameSelected) = React.useState(_ => false) -// // let (nativeProp, _) = React.useContext(NativePropContext.nativePropContext) -// // let (country, setCountry) = React.useState(_ => Some(nativeProp.hyperParams.country)) -// // let (postalCode, setpostalCode) = React.useState(_ => None) -// // let (name, setName) = React.useState(_ => None) -// // let (statesJson, setStatesJson) = React.useState(_ => None) -// // let (allApiData, _) = React.useContext(AllApiDataContext.allApiDataContext) -// // let (iscityValid, setIscityValid) = React.useState(_ => None) -// // let (city, setcity) = React.useState(_ => None) - -// // let {component, borderWidth, borderRadius} = ThemebasedStyle.useThemeBasedStyle() - -// // let accounts = ["savings", "current"] // Hard Coded The Account_Type Fields in ACHBankDebi - -// // let accountTypesList = accounts->Js.Array.sortInPlace - -// // let accountItems = Bank.bankNameConverter(accountTypesList) - -// // let accountTypes: array = accountItems->Array.map(item => { -// // { -// // name: item.displayName, -// // value: item.hyperSwitch, -// // } -// // }) - -// // React.useEffect0(() => { -// // // Dynamically import/download Postal codes and states JSON -// // RequiredFieldsTypes.importStates("./../../utility/reusableCodeFromWeb/States.json") -// // ->Promise.then(res => { -// // setStatesJson(_ => Some(res.states)) -// // Promise.resolve() -// // }) -// // ->Promise.catch(_ => { -// // setStatesJson(_ => None) -// // Promise.resolve() -// // }) -// // ->ignore - -// // None -// // }) - -// // let getStateData = states => { -// // states -// // ->Utils.getStateNames(country->Option.getOr("")) -// // ->Array.map((item): CustomPicker.customPickerType => { -// // { -// // name: item, -// // value: item, -// // } -// // }) -// // } - -// // let onChangeAccountType = val => { -// // setaccount(val) -// // } -// // let onChangePostalCode = (val: string) => { -// // let onlyNumerics = val->String.replaceRegExp(%re("/\D+/g"), "") -// // let firstPart = onlyNumerics->String.slice(~start=0, ~end=3) -// // let secondPart = onlyNumerics->String.slice(~start=3, ~end=6) - -// // let finalVal = if onlyNumerics->String.length <= 3 { -// // firstPart -// // } else if onlyNumerics->String.length > 3 && onlyNumerics->String.length <= 6 { -// // `${firstPart}-${secondPart}` -// // } else { -// // onlyNumerics -// // } -// // setpostalCode(_ => Some(finalVal)) -// // } - -// // // let processRequest = ( -// // // ~payment_method_data, -// // // ~payment_method, -// // // ~payment_method_type, -// // // ~payment_experience_type="redirect_to_url", -// // // ~eligible_connectors=?, -// // // (), -// // // ) => { -// // // let body: redirectType = { -// // // client_secret: nativeProp.clientSecret, -// // // return_url: ?Utils.getReturnUrl(nativeProp.hyperParams.appId), -// // // payment_method, -// // // payment_method_type, -// // // payment_experience: payment_experience_type, -// // // connector: ?eligible_connectors, -// // // payment_method_data, -// // // billing: ?nativeProp.configuration.defaultBillingDetails, -// // // shipping: ?nativeProp.configuration.shippingDetails, -// // // setup_future_usage: ?( -// // // allApiData.additionalPMLData.mandateType == NORMAL ? Some("off_session") : None -// // // ), -// // // payment_type: ?allApiData.additionalPMLData.paymentType, -// // // browser_info: { -// // // user_agent: ?nativeProp.hyperParams.userAgent, -// // // language: ?nativeProp.configuration.appearance.locale, -// // // }, -// // // } -// // // } - -// // // let processRequestBankDebit = (prop: payment_method_types_ach_bank_debit) => { -// // // let payment_method_data = -// // // [ -// // // ( -// // // prop.payment_method, -// // // [ -// // // ( -// // // "ach_bank_debit", -// // // [ -// // // ("account_number", accountnum->Option.getOr("")->JSON.Encode.string), -// // // ("routing_number", routingnum->Option.getOr("")->JSON.Encode.string), -// // // // ("name", name->Option.getOr("")->JSON.Encode.string), -// // // ] -// // // ->Dict.fromArray -// // // ->JSON.Encode.object, -// // // ), -// // // ] -// // // ->Dict.fromArray -// // // ->JSON.Encode.object, -// // // ), -// // // ( -// // // "billing", -// // // [ -// // // ( -// // // "address", -// // // [ -// // // ( -// // // "first_name", -// // // switch name { -// // // | Some(text) => text->String.split(" ")->Array.get(0) -// // // | _ => Some("") -// // // } -// // // ->Option.getOr("") -// // // ->JSON.Encode.string, -// // // ), -// // // ( -// // // "last_name", -// // // switch name { -// // // | Some(text) => text->String.split(" ")->Array.get(1) -// // // | _ => Some("") -// // // } -// // // ->Option.getOr("") -// // // ->JSON.Encode.string, -// // // ), -// // // ] -// // // ->Dict.fromArray -// // // ->JSON.Encode.object, -// // // ), -// // // ] -// // // ->Dict.fromArray -// // // ->JSON.Encode.object, -// // // ), -// // // ] -// // // ->Dict.fromArray -// // // ->JSON.Encode.object - -// // // processRequest( -// // // ~payment_method_data, -// // // ~payment_method=prop.payment_method, -// // // ~payment_method_type=prop.payment_method_type, -// // // //setup_future_usage:"off_session", -// // // (), -// // // ) -// // // } -// // let handlecity = text => { -// // let y = if text->String.length >= 3 { -// // Some(true) -// // } else { -// // None -// // } -// // setIscityValid(_ => y) -// // setcity(_ => Some(text)) -// // } -// // let handleAddress1 = text => { -// // let y = if text->String.length >= 5 { -// // Some(true) -// // } else { -// // None -// // } -// // setIsAddressValid(_ => y) -// // setaddress(_ => Some(text)) -// // } -// // let handleAddress2 = text => { -// // let y = if text->String.length >= 5 { -// // Some(true) -// // } else { -// // None -// // } -// // setIsAddress2Valid(_ => y) -// // setaddress2(_ => Some(text)) -// // } -// // let handlePressAccNum = text => { -// // let y = if text->String.length >= 10 { -// // Some(true) -// // } else { -// // None -// // } -// // setisaccountnumValid(_ => y) -// // setaccountnum(_ => Some(text)) -// // } - -// // let handlePressRouNum = number => { -// // let y = if number->String.length >= 9 { -// // Some(true) -// // } else { -// // None -// // } -// // setisroutingnumValid(_ => y) -// // setroutingnum(_ => Some(number)) -// // } - -// // <> -// // -// // -// // String.length > 0}> -// // -// // -// // {<> -// // -// // {fields.fields -// // ->Array.mapWithIndex((field, index) => -// // Int.toString}`}> -// // -// // {switch field { -// // // | "email" => -// // // Option.getOr("")} -// // // setState={handlePressEmail} -// // // placeholder=localeObject.emailLabel -// // // keyboardType=#"email-address" -// // // borderBottomLeftRadius=borderRadius -// // // borderBottomRightRadius=borderRadius -// // // borderTopLeftRadius=borderRadius -// // // borderTopRightRadius=borderRadius -// // // borderTopWidth=borderWidth -// // // borderBottomWidth=borderWidth -// // // borderLeftWidth=borderWidth -// // // borderRightWidth=borderWidth -// // // isValid=isEmailValidForFocus -// // // onFocus={_ => { -// // // setEmailIsFocus(_ => true) -// // // }} -// // // onBlur={_ => { -// // // setEmailIsFocus(_ => false) -// // // }} -// // // textColor=component.color -// // // /> - -// // // | "name" => -// // // Option.getOr("")} -// // // setState={handlePressName} -// // // placeholder=localeObject.fullNameLabel -// // // keyboardType=#default -// // // isValid=isNameValidForFocus -// // // onFocus={_ => { -// // // setNameIsFocus(_ => true) -// // // }} -// // // onBlur={_ => { -// // // setNameIsFocus(_ => false) -// // // }} -// // // textColor=component.color -// // // borderBottomLeftRadius=borderRadius -// // // borderBottomRightRadius=borderRadius -// // // borderTopLeftRadius=borderRadius -// // // borderTopRightRadius=borderRadius -// // // borderTopWidth=borderWidth -// // // borderBottomWidth=borderWidth -// // // borderLeftWidth=borderWidth -// // // borderRightWidth=borderWidth -// // // /> -// // | "Address_Line_1" => -// // Option.getOr("")} -// // setState={handleAddress1} -// // placeholder="Address Line 1" -// // keyboardType=#default -// // // isValid=isAddressValid -// // // onFocus={_ => { -// // // setAddressIsFocus(_ => true) -// // // }} -// // // onBlur={_ => { -// // // setAddressIsFocus(_ => false) -// // // }} -// // textColor=component.color -// // borderBottomLeftRadius=borderRadius -// // borderBottomRightRadius=borderRadius -// // borderTopLeftRadius=borderRadius -// // borderTopRightRadius=borderRadius -// // borderTopWidth=borderWidth -// // borderBottomWidth=borderWidth -// // borderLeftWidth=borderWidth -// // borderRightWidth=borderWidth -// // /> - -// // | "Address_Line_2" => -// // Option.getOr("")} -// // setState={handleAddress2} -// // placeholder="Address Line 2" -// // keyboardType=#default -// // textColor=component.color -// // borderBottomLeftRadius=borderRadius -// // borderBottomRightRadius=borderRadius -// // borderTopLeftRadius=borderRadius -// // borderTopRightRadius=borderRadius -// // borderTopWidth=borderWidth -// // borderBottomWidth=borderWidth -// // borderLeftWidth=borderWidth -// // borderRightWidth=borderWidth -// // /> -// // | "City" => -// // Option.getOr("")} -// // setState={handlecity} -// // placeholder="City" -// // keyboardType=#default -// // textColor=component.color -// // borderBottomLeftRadius=borderRadius -// // borderBottomRightRadius=borderRadius -// // borderTopLeftRadius=borderRadius -// // borderTopRightRadius=borderRadius -// // borderTopWidth=borderWidth -// // borderBottomWidth=borderWidth -// // borderLeftWidth=borderWidth -// // borderRightWidth=borderWidth -// // /> -// // // | "country" => -// // // -// // // | "State" => -// // // switch statesJson { -// // // | Some(states) => -// // // getStateData} -// // // placeholderText=localeObject.stateLabel -// // // /> -// // // | None => React.null -// // // } -// // // | "bank" => -// // // -// // | "account_type" => -// // <> -// // -// // -// // -// // -// // // - -// // -// // -// // -// // // -// // // -// // // -// // // -// // -// // // | "blik_code" => -// // // Option.getOr("")} -// // // setState={onChangeBlikCode} -// // // borderBottomLeftRadius=borderRadius -// // // borderBottomRightRadius=borderRadius -// // // borderBottomWidth=borderWidth -// // // placeholder="000-000" -// // // keyboardType=#numeric -// // // maxLength=Some(7) -// // // /> -// // | "postal_code" => -// // Option.getOr("")} -// // setState={onChangePostalCode} -// // borderBottomLeftRadius=borderRadius -// // borderBottomRightRadius=borderRadius -// // borderBottomWidth=borderWidth -// // placeholder="Postal Code" -// // keyboardType=#numeric -// // maxLength=Some(7) -// // /> - -// // | "account_number" => -// // Option.getOr("")} -// // setState={handlePressAccNum} -// // placeholder="Account Number" -// // borderBottomLeftRadius=borderRadius -// // borderBottomRightRadius=borderRadius -// // borderBottomWidth=borderWidth -// // maxLength=Some(12) -// // keyboardType=#numeric -// // /> -// // | "routing_number" => -// // Option.getOr("")} -// // setState={handlePressRouNum} -// // placeholder="Routing Number" -// // keyboardType=#numeric -// // borderBottomLeftRadius=borderRadius -// // borderBottomRightRadius=borderRadius -// // borderBottomWidth=borderWidth -// // maxLength=Some(9) -// // /> - -// // | _ => React.null -// // }} -// // -// // ) -// // ->React.array} -// // -// // // -// // } -// // -// // -// // -// // } - -// let paymentMethod = switch redirectProp { -// | CARD(prop) => prop.payment_method_type -// | WALLET(prop) => prop.payment_method_type -// | PAY_LATER(prop) => prop.payment_method_type -// | BANK_REDIRECT(prop) => prop.payment_method_type -// | CRYPTO(prop) => prop.payment_method_type -// | OPEN_BANKING(prop) => prop.payment_method_type -// | BANK_DEBIT(prop) => prop.payment_method_type -// } - -// -// -// {switch paymentMethod { -// | "ach" => -// | _ => React.null -// }} -// {<> -// -// String.length > 0}> -// -// -// { -// let isKlarna = true /* or appropriate logic to determine if it's Klarna */ -// KlarnaModule.klarnaReactPaymentView->Option.isSome && fields.name == "klarna" && isKlarna -// ? <> -// -// // -// // -// -// : <> -// {fields.fields -// ->Array.mapWithIndex((field, index) => -// Int.toString}`}> -// -// {switch field { -// | "email" => -// Option.getOr("")} -// setState={handlePressEmail} -// placeholder=localeObject.emailLabel -// keyboardType=#"email-address" -// borderBottomLeftRadius=borderRadius -// borderBottomRightRadius=borderRadius -// borderTopLeftRadius=borderRadius -// borderTopRightRadius=borderRadius -// borderTopWidth=borderWidth -// borderBottomWidth=borderWidth -// borderLeftWidth=borderWidth -// borderRightWidth=borderWidth -// isValid=isEmailValidForFocus -// onFocus={_ => { -// setEmailIsFocus(_ => true) -// }} -// onBlur={_ => { -// setEmailIsFocus(_ => false) -// }} -// textColor=component.color -// /> - -// | "name" => -// Option.getOr("")} -// setState={handlePressName} -// placeholder=localeObject.fullNameLabel -// keyboardType=#default -// isValid=isNameValidForFocus -// onFocus={_ => { -// setNameIsFocus(_ => true) -// }} -// onBlur={_ => { -// setNameIsFocus(_ => false) -// }} -// textColor=component.color -// borderBottomLeftRadius=borderRadius -// borderBottomRightRadius=borderRadius -// borderTopLeftRadius=borderRadius -// borderTopRightRadius=borderRadius -// borderTopWidth=borderWidth -// borderBottomWidth=borderWidth -// borderLeftWidth=borderWidth -// borderRightWidth=borderWidth -// /> - -// | "country" => -// - -// | "State" => -// switch statesJson { -// | Some(states) => -// getStateData} -// placeholderText=localeObject.stateLabel -// /> -// | None => React.null -// } - -// | "bank" => -// - -// | "blik_code" => -// Option.getOr("")} -// setState={onChangeBlikCode} -// borderBottomLeftRadius=borderRadius -// borderBottomRightRadius=borderRadius -// borderBottomWidth=borderWidth -// placeholder="000-000" -// keyboardType=#numeric -// maxLength=Some(7) -// /> -// | "Address_Line_1" => -// Option.getOr("")} -// setState={handleAddress1} -// placeholder="Address Line 1" -// keyboardType=#default -// textColor=component.color -// borderBottomLeftRadius=borderRadius -// borderBottomRightRadius=borderRadius -// borderTopLeftRadius=borderRadius -// borderTopRightRadius=borderRadius -// borderTopWidth=borderWidth -// borderBottomWidth=borderWidth -// borderLeftWidth=borderWidth -// borderRightWidth=borderWidth -// /> - -// | "Address_Line_2" => -// Option.getOr("")} -// setState={handleAddress2} -// placeholder="Address Line 2" -// keyboardType=#default -// textColor=component.color -// borderBottomLeftRadius=borderRadius -// borderBottomRightRadius=borderRadius -// borderTopLeftRadius=borderRadius -// borderTopRightRadius=borderRadius -// borderTopWidth=borderWidth -// borderBottomWidth=borderWidth -// borderLeftWidth=borderWidth -// borderRightWidth=borderWidth -// /> -// | "City" => -// Option.getOr("")} -// setState={handlecity} -// placeholder="City" -// keyboardType=#default -// textColor=component.color -// borderBottomLeftRadius=borderRadius -// borderBottomRightRadius=borderRadius -// borderTopLeftRadius=borderRadius -// borderTopRightRadius=borderRadius -// borderTopWidth=borderWidth -// borderBottomWidth=borderWidth -// borderLeftWidth=borderWidth -// borderRightWidth=borderWidth -// /> -// | "account_type" => -// <> -// -// -// -// -// -// -// -// - -// | "postal_code" => -// Option.getOr("")} -// setState={onChangePostalCode} -// borderBottomLeftRadius=borderRadius -// borderBottomRightRadius=borderRadius -// borderBottomWidth=borderWidth -// placeholder="Postal Code" -// keyboardType=#numeric -// maxLength=Some(120) -// /> - -// | "account_number" => -// Option.getOr("")} -// setState={handlePressAccNum} -// placeholder="Account Number" -// borderBottomLeftRadius=borderRadius -// borderBottomRightRadius=borderRadius -// borderBottomWidth=borderWidth -// maxLength=Some(12) -// keyboardType=#numeric -// /> -// | "routing_number" => -// Option.getOr("")} -// setState={handlePressRouNum} -// placeholder="Routing Number" -// keyboardType=#numeric -// borderBottomLeftRadius=borderRadius -// borderBottomRightRadius=borderRadius -// borderBottomWidth=borderWidth -// maxLength=Some(9) -// /> - -// | _ => React.null -// }} -// -// ) -// ->React.array} -// -// // -// {switch paymentMethod { -// | "ach" => React.null -// | _ => -// }} -// -// } -// -// -// } -// -// } - -// let mandate_data = -// [ -// ( -// "customer_acceptance", -// [ -// ("acceptance_type", "online"->JSON.Encode.string), -// ("accepted_at", Date.now()->Date.fromTime->Date.toISOString->JSON.Encode.string), -// ( -// "online", -// [ -// ( -// "ip_address", -// nativeProp.hyperParams.ip->Option.getOr("0.0.0.0")->JSON.Encode.string, -// ), -// ( -// "user_agent", -// nativeProp.hyperParams.userAgent->Option.getOr("Unknown")->JSON.Encode.string, -// ), -// ] -// ->Dict.fromArray -// ->JSON.Encode.object, -// ), -// ] -// ->Dict.fromArray -// ->JSON.Encode.object, -// ), -// ( -// "mandate_type", -// [ -// ( -// "multi_use", -// [ -// ("amount", 1000->JSON.Encode.int), -// ("currency", "USD"->JSON.Encode.string), -// ("start_date", "2024-04-21T00:00:00Z"->JSON.Encode.string), -// ("end_date", "2024-05-21T00:00:00Z"->JSON.Encode.string), -// ( -// "metadata", -// [("frequency", "13"->JSON.Encode.string)] -// ->Dict.fromArray -// ->JSON.Encode.object, -// ), -// ] -// ->Dict.fromArray -// ->JSON.Encode.object, -// ), -// ] -// ->Dict.fromArray -// ->JSON.Encode.object, -// ), -// ] -// ->Dict.fromArray -// ->JSON.Encode.object -// Console.log2("mandate_data", mandate_data) -