diff --git a/package.json b/package.json index 7feea4b47..3e55324fb 100644 --- a/package.json +++ b/package.json @@ -66,6 +66,7 @@ "@monaco-editor/react": "^4.4.5", "@rescript/core": "^0.6.0", "@rescript/react": "^0.12.0", + "apexcharts": "^3.28.3", "bs-fetch": "^0.6.2", "csvjson-csv2json": "^5.0.6", "csvjson-json2csv": "^1.0.3", @@ -84,7 +85,6 @@ "monaco-editor": "^0.34.1", "nprogress": "^0.2.0", "react": "^18.2.0", - "apexcharts": "^3.28.3", "react-apexcharts": "^1.4.1", "react-beautiful-dnd": "^13.1.0", "react-color": "^2.19.3", diff --git a/public/.DS_Store b/public/.DS_Store index b27094d69..2d5f46143 100644 Binary files a/public/.DS_Store and b/public/.DS_Store differ diff --git a/public/hyperswitch/wasm/euclid.js b/public/hyperswitch/wasm/euclid.js index a285850f1..06a7d9d37 100644 --- a/public/hyperswitch/wasm/euclid.js +++ b/public/hyperswitch/wasm/euclid.js @@ -774,6 +774,13 @@ function __wbg_get_imports() { const ret = new Object(); return addHeapObject(ret); }; + imports.wbg.__wbg_new_16b304a2cfa7ff4a = function() { + const ret = new Array(); + return addHeapObject(ret); + }; + imports.wbg.__wbg_set_d4638f722068f043 = function(arg0, arg1, arg2) { + getObject(arg0)[arg1 >>> 0] = takeObject(arg2); + }; imports.wbg.__wbindgen_is_object = function(arg0) { const val = getObject(arg0); const ret = typeof(val) === 'object' && val !== null; @@ -866,13 +873,6 @@ function __wbg_get_imports() { const ret = arg0; return addHeapObject(ret); }; - imports.wbg.__wbg_new_16b304a2cfa7ff4a = function() { - const ret = new Array(); - return addHeapObject(ret); - }; - imports.wbg.__wbg_set_d4638f722068f043 = function(arg0, arg1, arg2) { - getObject(arg0)[arg1 >>> 0] = takeObject(arg2); - }; imports.wbg.__wbg_new_d9bc3a0147634640 = function() { const ret = new Map(); return addHeapObject(ret); diff --git a/public/hyperswitch/wasm/euclid_bg.wasm b/public/hyperswitch/wasm/euclid_bg.wasm index 7636dbedf..2da74433a 100644 Binary files a/public/hyperswitch/wasm/euclid_bg.wasm and b/public/hyperswitch/wasm/euclid_bg.wasm differ diff --git a/src/screens/Connectors/ConnectPayPalFlow/ConnectPayPal.res b/src/screens/Connectors/ConnectPayPalFlow/ConnectPayPal.res index 07270eec6..bab9dbce3 100644 --- a/src/screens/Connectors/ConnectPayPalFlow/ConnectPayPal.res +++ b/src/screens/Connectors/ConnectPayPalFlow/ConnectPayPal.res @@ -470,8 +470,6 @@ let make = ( ConnectorUtils.getConnectorNameTypeFromString()} selectedConnector isLabelNested=false diff --git a/src/screens/Connectors/ConnectorAccountDetailsHelper.res b/src/screens/Connectors/ConnectorAccountDetailsHelper.res index 33dbb535e..4dc2d3adb 100644 --- a/src/screens/Connectors/ConnectorAccountDetailsHelper.res +++ b/src/screens/Connectors/ConnectorAccountDetailsHelper.res @@ -1,5 +1,3 @@ -let metaDataInputKeysToIgnore = ["google_pay", "apple_pay", "zen_apple_pay"] - let connectorsWithIntegrationSteps: array = [ Processors(ADYEN), Processors(CHECKOUT), @@ -46,77 +44,6 @@ let multiValueInput = (~label, ~fieldName1, ~fieldName2) => { ) } -let getCurrencyOption: CurrencyUtils.currencyCode => SelectBox.dropdownOption = currencyType => { - open CurrencyUtils - { - label: currencyType->getCurrencyCodeStringFromVariant, - value: currencyType->getCurrencyCodeStringFromVariant, - } -} - -let currencyField = ( - ~name, - ~options=CurrencyUtils.currencyList, - ~disableSelect=false, - ~toolTipText="", - (), -) => - FormRenderer.makeFieldInfo( - ~label="Currency", - ~isRequired=true, - ~name, - ~description=toolTipText, - ~customInput=InputFields.selectInput( - ~deselectDisable=true, - ~disableSelect, - ~customStyle="max-h-48", - ~options=options->Array.map(getCurrencyOption), - ~buttonText="Select Currency", - (), - ), - (), - ) - -let dropDownfield = ( - ~name, - ~label, - ~buttonText="Select", - ~disableSelect=false, - ~toolTipText="", - ~options=[], - (), -) => { - FormRenderer.makeFieldInfo( - ~label, - ~isRequired=true, - ~name, - ~description=toolTipText, - ~customInput=InputFields.selectInput( - ~deselectDisable=true, - ~disableSelect, - ~customStyle="max-h-48", - ~options=options->Array.map((item): SelectBox.dropdownOption => { - { - label: item, - value: item, - } - }), - ~buttonText, - (), - ), - (), - ) -} - -let toggleField = (~name) => { - FormRenderer.makeFieldInfo( - ~name, - ~label="Pull Mechanism Enabled", - ~customInput=InputFields.boolInput(~isDisabled=false, ~boolCustomClass="rounded-lg", ()), - (), - ) -} - let inputField = ( ~name, ~field, @@ -192,12 +119,7 @@ module RenderConnectorInputFields = { keys ->Array.mapWithIndex((field, i) => { - let label = switch field { - | "pull_mechanism_for_external_3ds_enabled" => "Pull Mechanism Enabled" - | "klarna_region" => "Region of your Klarna Merchant Account" - - | _ => details->getString(field, "") - } + let label = details->getString(field, "") let formName = isLabelNested ? `${name}.${field}` : name isNonEmptyString} key={i->Int.toString}> @@ -206,19 +128,6 @@ module RenderConnectorInputFields = { - currencyField(~name=formName, ()) - - | (ThreeDsAuthenticator(THREEDSECUREIO), "pull_mechanism_for_external_3ds_enabled") => - toggleField(~name=formName) - | (Processors(KLARNA), "klarna_region") => - dropDownfield( - ~name=formName, - ~label, - ~buttonText="Select Region", - ~options=details->getStrArrayFromDict(field, []), - (), - ) | (Processors(PAYPAL), "key1") => multiValueInput( ~label, @@ -300,8 +209,8 @@ module CashToCodeSelectBox = {
{opts - ->Array.map(country => { -
+ ->Array.mapWithIndex((country, index) => { +
Int.toString} className="flex items-center gap-2 break-words p-2">
selectedCountry(country)}> isSelected} />
@@ -408,21 +317,12 @@ module ConnectorConfigurationFields = { - + { + open ApplePayIntegrationHelper + open ApplePayIntegrationTypes + let formState: ReactFinalForm.formState = ReactFinalForm.useFormState( + ReactFinalForm.useFormSubscription(["values"])->Nullable.make, + ) + let form = ReactFinalForm.useForm() + let onSubmit = () => { + open LogicUtils + + let data = + formState.values + ->getDictFromJsonObject + ->getDictfromDict("metadata") + ->getDictfromDict("apple_pay_combined") + let applePayData = ApplePayIntegrationUtils.applePay( + data, + ~applePayIntegrationType=Some(appleIntegrationType), + (), + ) + switch applePayData { + | ApplePayCombined(data) => + form.change( + "metadata.apple_pay_combined", + data.apple_pay_combined->Identity.genericTypeToJson, + ) + | _ => () + } + + let metadata = + formState.values->getDictFromJsonObject->getDictfromDict("metadata")->JSON.Encode.object + + let _ = update(metadata) + setShowWalletConfigurationModal(_ => false) + } + <> +
+

{" Web Domains"->React.string}

+ {verifiedDomainList + ->Array.mapWithIndex((domainUrl, index) => { +
setApplePayIntegrationType(_ => #manual)}> +
+
+
+ {domainUrl->String.length > 0 ? domainUrl->React.string : "Default"->React.string} +
+
+ {switch appleIntegrationType { + | #simplified => + + | #manual => + setApplePayIntegrationSteps(_ => Configure)} + name={"arrow-right"} + size={15} + /> + }} +
+
+
+
+ }) + ->React.array} +
+
+
+ + } +} + +module Landing = { + @react.component + let make = ( + ~connector, + ~appleIntegrationType, + ~closeModal, + ~setApplePayIntegrationSteps, + ~setApplePayIntegrationType, + ) => { + open ApplePayIntegrationTypes + open WalletHelper + <> + {switch connector->ConnectorUtils.getConnectorNameTypeFromString() { + | Processors(STRIPE) + | Processors(BANKOFAMERICA) + | Processors(CYBERSOURCE) => +
setApplePayIntegrationType(_ => #simplified)}> + +
+ {"Get Apple Pay enabled on your web domains by hosting a verification file, that’s it."->React.string} +
+
+ + +
+
+
+ | _ => React.null + }} +
setApplePayIntegrationType(_ => #manual)}> + +
+ +
+
+ + +
+
+
+
+
+ + } +} + +@react.component +let make = (~connector, ~setShowWalletConfigurationModal, ~update, ~onCloseClickCustomFun) => { + open APIUtils + open LogicUtils + open WalletHelper + open ApplePayIntegrationTypes + + let getURL = useGetURL() + let fetchDetails = useGetMethod() + let (appleIntegrationType, setApplePayIntegrationType) = React.useState(_ => #manual) + let (applePayIntegrationStep, setApplePayIntegrationSteps) = React.useState(_ => Landing) + let (merchantBusinessCountry, setMerchantBusinessCountry) = React.useState(_ => []) + let (screenState, setScreenState) = React.useState(_ => PageLoaderWrapper.Success) + let (verifiedDomainList, setVefifiedDomainList) = React.useState(_ => []) + let applePayFields = React.useMemo1(() => { + try { + if connector->isNonEmptyString { + let dict = + Window.getConnectorConfig(connector) + ->getDictFromJsonObject + ->getDictfromDict("metadata") + ->getArrayFromDict("apple_pay", []) + + dict + } else { + [] + } + } catch { + | Exn.Error(e) => { + Js.log2("FAILED TO LOAD CONNECTOR CONFIG", e) + [] + } + } + }, [connector]) + + let getProcessorDetails = async () => { + try { + setScreenState(_ => Loading) + let paymentMethoConfigUrl = getURL(~entityName=PAYMENT_METHOD_CONFIG, ~methodType=Get, ()) + let res = await fetchDetails( + `${paymentMethoConfigUrl}?connector=${connector}&paymentMethodType=apple_pay`, + ) + let countries = + res + ->getDictFromJsonObject + ->getArrayFromDict("countries", []) + ->Array.map(item => { + let dict = item->getDictFromJsonObject + let a: SelectBox.dropdownOption = { + label: dict->getString("name", ""), + value: dict->getString("code", ""), + } + a + }) + + setMerchantBusinessCountry(_ => countries) + setScreenState(_ => Success) + } catch { + | _ => setScreenState(_ => Success) + } + } + + let closeModal = () => { + onCloseClickCustomFun() + setShowWalletConfigurationModal(_ => false) + } + + React.useEffect1(() => { + if connector->String.length > 0 { + switch connector->ConnectorUtils.getConnectorNameTypeFromString() { + | Processors(STRIPE) + | Processors(BANKOFAMERICA) + | Processors(CYBERSOURCE) => + setApplePayIntegrationType(_ => #simplified) + + | _ => setApplePayIntegrationType(_ => #manual) + } + + getProcessorDetails()->ignore + } + None + }, [connector]) + + +
+ +
+
} + sectionHeight="!h-screen"> +
+ + {switch connector->ConnectorUtils.getConnectorNameTypeFromString() { + | Processors(ZEN) => + + | _ => + switch applePayIntegrationStep { + | Landing => + + | Configure => + switch appleIntegrationType { + | #simplified => + + | #manual => + + } + | Verify => + + } + }} +
+ + +} diff --git a/src/screens/Connectors/ConnectorMetaData/ApplePay/ApplePayIntegrationHelper.res b/src/screens/Connectors/ConnectorMetaData/ApplePay/ApplePayIntegrationHelper.res new file mode 100644 index 000000000..37ed3f26a --- /dev/null +++ b/src/screens/Connectors/ConnectorMetaData/ApplePay/ApplePayIntegrationHelper.res @@ -0,0 +1,104 @@ +open ApplePayIntegrationTypes +module SimplifiedHelper = { + @react.component + let make = ( + ~customElement: option, + ~heading="", + ~stepNumber="1", + ~subText=None, + ) => { + let {globalUIConfig: {backgroundColor, font: {textColor}}} = React.useContext( + ThemeProvider.themeContext, + ) + let bgColor = "bg-white" + let stepColor = `${backgroundColor} text-white py-px px-2` + +
+
+
+
+

{stepNumber->React.string}

+
+
+

+ {heading->React.string} +

+ Option.isSome}> +

+ {subText->Option.getOr("")->React.string} +

+
+ {switch customElement { + | Some(element) => element + | _ => React.null + }} +
+
+
+
+ } +} + +module HostURL = { + @react.component + let make = (~prefix="") => { + let fieldInputVal = ReactFinalForm.useField(`${prefix}`).input + let fieldInput = switch fieldInputVal.value->JSON.Decode.string { + | Some(val) => val->LogicUtils.isNonEmptyString ? val : "domain_name" + | None => "domain_name" + } + +

+ {`${fieldInput}/.well-known/apple-developer-merchantid-domain-association`->React.string} +

+ } +} + +module CustomTag = { + @react.component + let make = (~tagText="", ~tagSize=5, ~tagLeftIcon=None, ~tagCustomStyle="") => { +
+ {switch tagLeftIcon { + | Some(icon) => +
+ +
+ | None => React.null + }} +
+ {tagText->React.string} +
+
+ } +} + +module InfoCard = { + @react.component + let make = (~children, ~customInfoStyle="") => { +
+ +
{children}
+
+ } +} + +let applePayValueInput = ( + ~applePayField: CommonMetaDataTypes.inputField, + ~integrationType: option=None, + (), +) => { + open CommonMetaDataHelper + let {\"type", name} = applePayField + let formName = ApplePayIntegrationUtils.applePayNameMapper(~name, ~integrationType) + + { + switch \"type" { + | Text => textInput(~field={applePayField}, ~formName) + | Select => selectInput(~field={applePayField}, ~formName, ()) + | MultiSelect => multiSelectInput(~field={applePayField}, ~formName) + | _ => textInput(~field={applePayField}, ~formName) + } + } +} diff --git a/src/screens/Connectors/ConnectorMetaData/ApplePay/ApplePayIntegrationTypes.res b/src/screens/Connectors/ConnectorMetaData/ApplePay/ApplePayIntegrationTypes.res new file mode 100644 index 000000000..52970c575 --- /dev/null +++ b/src/screens/Connectors/ConnectorMetaData/ApplePay/ApplePayIntegrationTypes.res @@ -0,0 +1,64 @@ +type sessionTokenData = { + initiative: option, + certificate: option, + display_name: option, + certificate_keys: option, + initiative_context: option, + merchant_identifier: option, + merchant_business_country: option, + payment_processing_details_at: option, + payment_processing_certificate: option, + payment_processing_certificate_key: option, +} + +type sessionTokenSimplified = { + initiative_context: option, + merchant_business_country: option, +} + +type paymentRequestData = { + label: string, + supported_networks: array, + merchant_capabilities: array, +} + +type manual = { + session_token_data: sessionTokenData, + payment_request_data: paymentRequestData, +} + +type simplified = { + session_token_data: sessionTokenSimplified, + payment_request_data: paymentRequestData, +} + +type applePayIntegrationType = [#manual | #simplified] +type applePayConfig = [#manual(manual) | #simplified(simplified)] +type applePayIntegrationSteps = Landing | Configure | Verify +type simplifiedApplePayIntegartionTypes = EnterUrl | DownloadFile | HostUrl + +type applePayCombined = {apple_pay_combined: Js.Json.t} +type zenConfig = { + terminal_uuid: option, + pay_wall_secret: option, +} + +type applePay = ApplePayCombined(applePayCombined) | Zen(zenConfig) +type verifyApplePay = { + domain_names: array, + merchant_connector_account_id: string, +} + +type paymentProcessingState = [#Connector | #Hyperswitch] +type initiativeState = [#web | #ios] + +type inputType = Text | Toggle | Select + +type inputField = { + name: string, + label: string, + placeholder: string, + required: bool, + options: array, + \"type": inputType, +} diff --git a/src/screens/Connectors/ConnectorMetaData/ApplePay/ApplePayIntegrationUtils.res b/src/screens/Connectors/ConnectorMetaData/ApplePay/ApplePayIntegrationUtils.res new file mode 100644 index 000000000..72c1b871f --- /dev/null +++ b/src/screens/Connectors/ConnectorMetaData/ApplePay/ApplePayIntegrationUtils.res @@ -0,0 +1,241 @@ +open ApplePayIntegrationTypes +open LogicUtils +let paymentRequest = (dict, integrationType) => { + let paymentRequestDict = + dict + ->getDictfromDict((integrationType: applePayIntegrationType :> string)) + ->getDictfromDict("payment_request_data") + let sessionTokenDict = + dict + ->getDictfromDict((integrationType: applePayIntegrationType :> string)) + ->getDictfromDict("session_token_data") + { + label: sessionTokenDict->getString("display_name", "apple"), + supported_networks: paymentRequestDict->getStrArrayFromDict( + "supported_networks", + ["visa", "masterCard", "amex", "discover"], + ), + merchant_capabilities: paymentRequestDict->getStrArrayFromDict( + "merchant_capabilities", + ["supports3DS"], + ), + } +} + +let sessionToken = (dict): sessionTokenData => { + let sessionTokenDict = + dict + ->getDictfromDict((#manual: applePayIntegrationType :> string)) + ->getDictfromDict("session_token_data") + { + initiative: sessionTokenDict->getOptionString("initiative"), + certificate: sessionTokenDict->getOptionString("certificate"), + display_name: sessionTokenDict->getOptionString("display_name"), + certificate_keys: sessionTokenDict->getOptionString("certificate_keys"), + initiative_context: sessionTokenDict->getOptionString("initiative_context"), + merchant_identifier: sessionTokenDict->getOptionString("merchant_identifier"), + merchant_business_country: sessionTokenDict->getOptionString("merchant_business_country"), + payment_processing_details_at: sessionTokenDict->getOptionString( + "payment_processing_details_at", + ), + payment_processing_certificate: sessionTokenDict->getOptionString( + "payment_processing_certificate", + ), + payment_processing_certificate_key: sessionTokenDict->getOptionString( + "payment_processing_certificate_key", + ), + } +} + +let sessionTokenSimplified = (dict): sessionTokenSimplified => { + let sessionTokenDict = + dict + ->getDictfromDict((#simplified: applePayIntegrationType :> string)) + ->getDictfromDict("session_token_data") + { + initiative_context: sessionTokenDict->getOptionString("initiative_context"), + merchant_business_country: sessionTokenDict->getOptionString("merchant_business_country"), + } +} +let manual = (dict): manual => { + { + session_token_data: dict->sessionToken, + payment_request_data: dict->paymentRequest(#manual), + } +} + +let simplified = (dict): simplified => { + { + session_token_data: dict->sessionTokenSimplified, + payment_request_data: dict->paymentRequest(#simplified), + } +} + +let zenApplePayConfig = dict => { + { + terminal_uuid: dict->getOptionString("terminal_uuid"), + pay_wall_secret: dict->getOptionString("pay_wall_secret"), + } +} + +let applePayCombined = (dict, applePayIntegrationType) => { + let data: applePayConfig = switch applePayIntegrationType { + | #manual => #manual(dict->manual) + | #simplified => #simplified(dict->simplified) + } + + let dict = Dict.make() + let _ = switch data { + | #manual(data) => + dict->Dict.set((#manual: applePayIntegrationType :> string), data->Identity.genericTypeToJson) + | #simplified(data) => + dict->Dict.set( + (#simplified: applePayIntegrationType :> string), + data->Identity.genericTypeToJson, + ) + } + + dict +} + +let applePay = ( + dict, + ~connector: string="", + ~applePayIntegrationType: option=None, + (), +): applePay => { + open ConnectorUtils + open ConnectorTypes + switch connector->getConnectorNameTypeFromString() { + | Processors(ZEN) => Zen(dict->zenApplePayConfig) + | _ => { + let integrationType = applePayIntegrationType->Option.getOr(#manual) + let data = { + apple_pay_combined: applePayCombined(dict, integrationType)->JSON.Encode.object, + } + ApplePayCombined(data) + } + } +} + +let applePayNameMapper = (~name, ~integrationType: option) => { + switch name { + | `terminal_uuid` => `metadata.apple_pay.${name}` + | `pay_wall_secret` => `metadata.apple_pay.${name}` + | _ => + `metadata.apple_pay_combined.${(integrationType->Option.getOr( + #manual, + ): applePayIntegrationType :> string)}.session_token_data.${name}` + } +} + +let paymentProcessingMapper = state => { + switch state->String.toLowerCase { + | "connector" => #Connector + | "hyperswitch" => #Hyperswitch + | _ => #Connector + } +} + +let initiativeMapper = state => { + switch state->String.toLowerCase { + | "ios" => #ios + | "web" => #web + | _ => #web + } +} + +let applePayIntegrationTypeMapper = state => { + switch state->String.toLowerCase { + | "manual" => #manual + | "simplified" => #simplified + | _ => #manual + } +} + +let ignoreFieldsonSimplified = [ + "certificate", + "certificate_keys", + "merchant_identifier", + "display_name", + "initiative", + "payment_processing_details_at", +] + +let validateZenFlow = values => { + let data = + values + ->getDictFromJsonObject + ->getDictfromDict("metadata") + ->getDictfromDict("apple_pay") + ->zenApplePayConfig + data.terminal_uuid->Option.isSome && data.pay_wall_secret->Option.isSome + ? Button.Normal + : Button.Disabled +} + +let validateInitiative = data => { + switch data.initiative { + | Some(value) => value->initiativeMapper == #web ? data.initiative_context->Option.isSome : true + | None => false + } +} + +let validatePaymentProcessingDetailsAt = data => { + switch data.payment_processing_details_at { + | Some(value) => + value->paymentProcessingMapper == #Hyperswitch + ? data.payment_processing_certificate->Option.isSome && + data.payment_processing_certificate_key->Option.isSome + : true + | None => false + } +} + +let validateManualFlow = values => { + let data = + values + ->getDictFromJsonObject + ->getDictfromDict("metadata") + ->getDictfromDict("apple_pay_combined") + ->sessionToken + data->validateInitiative && + data.certificate->Option.isSome && + data.display_name->Option.isSome && + data.merchant_identifier->Option.isSome && + data->validatePaymentProcessingDetailsAt + ? Button.Normal + : Button.Disabled +} + +let validateSimplifedFlow = values => { + let data = + values + ->getDictFromJsonObject + ->getDictfromDict("metadata") + ->getDictfromDict("apple_pay_combined") + ->sessionTokenSimplified + data.initiative_context->Option.isSome && data.merchant_business_country->Option.isSome + ? Button.Normal + : Button.Disabled +} + +let constructVerifyApplePayReq = (values, connectorID) => { + let context = + values + ->getDictFromJsonObject + ->getDictfromDict("metadata") + ->getDictfromDict("apple_pay_combined") + ->sessionTokenSimplified + let domainName = context.initiative_context->Option.getOr("") + let data = { + domain_names: [domainName], + merchant_connector_account_id: connectorID, + }->JSON.stringifyAny + + let body = switch data { + | Some(val) => val->LogicUtils.safeParse + | None => Dict.make()->JSON.Encode.object + } + body +} diff --git a/src/screens/Connectors/ConnectorMetaData/ApplePay/ApplePayManualFlow.res b/src/screens/Connectors/ConnectorMetaData/ApplePay/ApplePayManualFlow.res new file mode 100644 index 000000000..7bfad8eaa --- /dev/null +++ b/src/screens/Connectors/ConnectorMetaData/ApplePay/ApplePayManualFlow.res @@ -0,0 +1,295 @@ +open ApplePayIntegrationTypes + +module PaymentProcessingDetailsAt = { + @react.component + let make = (~applePayField) => { + open LogicUtils + open ApplePayIntegrationUtils + let form = ReactFinalForm.useForm() + let formState: ReactFinalForm.formState = ReactFinalForm.useFormState( + ReactFinalForm.useFormSubscription(["values"])->Nullable.make, + ) + let initalFormValue = + formState.values + ->getDictFromJsonObject + ->getDictfromDict("metadata") + ->getDictfromDict("apple_pay_combined") + ->manual + + let initalProcessingAt = + initalFormValue.session_token_data.payment_processing_details_at + ->Option.getOr((#Connector: paymentProcessingState :> string)) + ->paymentProcessingMapper + let {globalUIConfig: {font: {textColor}}} = React.useContext(ThemeProvider.themeContext) + let (processingAt, setProcessingAt) = React.useState(_ => initalProcessingAt) + + let onChangeItem = (event: ReactEvent.Form.t) => { + let value = + event->Identity.formReactEventToString->ApplePayIntegrationUtils.paymentProcessingMapper + setProcessingAt(_ => value) + if value === #Connector { + form.change( + `${ApplePayIntegrationUtils.applePayNameMapper( + ~name="payment_processing_certificate", + ~integrationType=Some(#manual), + )}`, + JSON.Encode.null, + ) + form.change( + `${ApplePayIntegrationUtils.applePayNameMapper( + ~name="payment_processing_certificate_key", + ~integrationType=Some(#manual), + )}`, + JSON.Encode.null, + ) + } + } + + <> + + {switch processingAt { + | #Hyperswitch => +
+ + +
+ | _ => React.null + }} + + } +} + +module Initiative = { + @react.component + let make = (~applePayField) => { + open LogicUtils + open ApplePayIntegrationUtils + let form = ReactFinalForm.useForm() + let formState: ReactFinalForm.formState = ReactFinalForm.useFormState( + ReactFinalForm.useFormSubscription(["values"])->Nullable.make, + ) + let initalFormValue = + formState.values + ->getDictFromJsonObject + ->getDictfromDict("metadata") + ->getDictfromDict("apple_pay_combined") + ->manual + + let initalInitiative = + initalFormValue.session_token_data.initiative + ->Option.getOr((#ios: initiativeState :> string)) + ->initiativeMapper + let (initiative, setInitiative) = React.useState(_ => initalInitiative) + + let onChangeItem = (event: ReactEvent.Form.t) => { + let value = event->Identity.formReactEventToString->initiativeMapper + setInitiative(_ => value) + if value === #ios { + form.change( + `${ApplePayIntegrationUtils.applePayNameMapper( + ~name="initiative_context", + ~integrationType=Some(#manual), + )}`, + JSON.Encode.null, + ) + } + } + let domainValues = [ + [("label", "IOS/WEB"->JSON.Encode.string), ("value", "web"->JSON.Encode.string)] + ->Dict.fromArray + ->JSON.Encode.object, + [("label", "IOS"->JSON.Encode.string), ("value", "ios"->JSON.Encode.string)] + ->Dict.fromArray + ->JSON.Encode.object, + ] + let initiativeOptions = domainValues->Array.map(item => { + let dict = item->getDictFromJsonObject + let a: SelectBox.dropdownOption = { + label: dict->getString("label", ""), + value: dict->getString("value", ""), + } + a + }) + <> + + {switch initiative { + | #web => + + | _ => React.null + }} + + } +} + +@react.component +let make = ( + ~applePayFields, + ~merchantBusinessCountry, + ~setApplePayIntegrationSteps, + ~setVefifiedDomainList, +) => { + open LogicUtils + open ApplePayIntegrationUtils + open ApplePayIntegrationHelper + let form = ReactFinalForm.useForm() + let formState: ReactFinalForm.formState = ReactFinalForm.useFormState( + ReactFinalForm.useFormSubscription(["values"])->Nullable.make, + ) + let initalFormValue = + formState.values + ->getDictFromJsonObject + ->getDictfromDict("metadata") + ->getDictfromDict("apple_pay_combined") + let setFormData = () => { + let value = applePayCombined(initalFormValue, #manual) + form.change("metadata.apple_pay_combined", value->Identity.genericTypeToJson) + } + + React.useEffect0(() => { + let _ = setFormData() + None + }) + let onSubmit = () => { + let data = + formState.values + ->getDictFromJsonObject + ->getDictfromDict("metadata") + ->getDictfromDict("apple_pay_combined") + ->manual + let domainName = data.session_token_data.initiative_context->Option.getOr("") + + setVefifiedDomainList(_ => [domainName]) + setApplePayIntegrationSteps(_ => ApplePayIntegrationTypes.Verify) + Nullable.null->Promise.resolve + } + let applePayManualFields = + applePayFields + ->Array.mapWithIndex((field, index) => { + let applePayField = field->convertMapObjectToDict->CommonMetaDataUtils.inputFieldMapper + let {name} = applePayField +
Int.toString}> + {switch name { + | "payment_processing_details_at" => + | "initiative" => + | "initiative_context" => React.null + | "merchant_business_country" => + + | _ => + + }} +
+ }) + ->React.array + <> + {applePayManualFields} +
+
+ + +} diff --git a/src/screens/Connectors/ConnectorMetaData/ApplePay/ApplePaySimplifiedFlow.res b/src/screens/Connectors/ConnectorMetaData/ApplePay/ApplePaySimplifiedFlow.res new file mode 100644 index 000000000..acac24979 --- /dev/null +++ b/src/screens/Connectors/ConnectorMetaData/ApplePay/ApplePaySimplifiedFlow.res @@ -0,0 +1,182 @@ +open ApplePayIntegrationTypes +@react.component +let make = ( + ~applePayFields, + ~merchantBusinessCountry, + ~setApplePayIntegrationSteps, + ~setVefifiedDomainList, +) => { + open LogicUtils + open APIUtils + open ApplePayIntegrationHelper + open ApplePayIntegrationUtils + let getURL = useGetURL() + let updateAPIHook = useUpdateMethod(~showErrorToast=false, ()) + let fetchApi = AuthHooks.useApiFetcher() + let showToast = ToastState.useShowToast() + + let url = RescriptReactRouter.useUrl() + let form = ReactFinalForm.useForm() + let connectorID = HSwitchUtils.getConnectorIDFromUrl(url.path->List.toArray, "") + let merchantDetailsValue = HSwitchUtils.useMerchantDetailsValue() + let merchantId = merchantDetailsValue.merchant_id + let formState: ReactFinalForm.formState = ReactFinalForm.useFormState( + ReactFinalForm.useFormSubscription(["values"])->Nullable.make, + ) + let initalFormValue = + formState.values + ->getDictFromJsonObject + ->getDictfromDict("metadata") + ->getDictfromDict("apple_pay_combined") + let setFormData = () => { + let value = applePayCombined(initalFormValue, #simplified) + form.change("metadata.apple_pay_combined", value->Identity.genericTypeToJson) + } + + React.useEffect0(() => { + let _ = setFormData() + None + }) + let onSubmit = async () => { + try { + let body = formState.values->constructVerifyApplePayReq(connectorID) + let verifyAppleUrl = getURL(~entityName=VERIFY_APPLE_PAY, ~methodType=Post, ()) + let _ = await updateAPIHook(`${verifyAppleUrl}/${merchantId}`, body, Post, ()) + + let data = + formState.values + ->getDictFromJsonObject + ->getDictfromDict("metadata") + ->getDictfromDict("apple_pay_combined") + ->simplified + let domainName = data.session_token_data.initiative_context->Option.getOr("") + + setVefifiedDomainList(_ => [domainName]) + setApplePayIntegrationSteps(_ => ApplePayIntegrationTypes.Verify) + } catch { + | _ => showToast(~message="Failed to Verify", ~toastType=ToastState.ToastError, ()) + } + Nullable.null + } + + let downloadApplePayCert = () => { + open Promise + let downloadURL = Window.env.applePayCertificateUrl->Option.getOr("") + fetchApi(downloadURL, ~method_=Get, ()) + ->then(Fetch.Response.blob) + ->then(content => { + DownloadUtils.download( + ~fileName=`apple-developer-merchantid-domain-association`, + ~content, + ~fileType="text/plain", + ) + showToast(~toastType=ToastSuccess, ~message="File download complete", ()) + + resolve() + }) + ->catch(_ => { + showToast( + ~toastType=ToastError, + ~message="Oops, something went wrong with the download. Please try again.", + (), + ) + resolve() + }) + ->ignore + } + + let downloadAPIKey = +
+
+ + let applePaySimplifiedFields = + applePayFields + ->Array.filter(field => { + let typedData = field->convertMapObjectToDict->CommonMetaDataUtils.inputFieldMapper + !(ignoreFieldsonSimplified->Array.includes(typedData.name)) + }) + ->Array.mapWithIndex((field, index) => { + let applePayField = field->convertMapObjectToDict->CommonMetaDataUtils.inputFieldMapper +
Int.toString}> + {switch applePayField.name { + | "merchant_business_country" => + + | _ => + + }} +
+ }) + ->React.array + <> + +
+ +
+ , + ) + /> +
+
+ + +} diff --git a/src/screens/Connectors/ConnectorMetaData/ApplePay/ApplePayZen.res b/src/screens/Connectors/ConnectorMetaData/ApplePay/ApplePayZen.res new file mode 100644 index 000000000..e9cd096dc --- /dev/null +++ b/src/screens/Connectors/ConnectorMetaData/ApplePay/ApplePayZen.res @@ -0,0 +1,67 @@ +@react.component +let make = (~applePayFields, ~update, ~closeModal, ~setShowWalletConfigurationModal) => { + open LogicUtils + open ApplePayIntegrationUtils + open ApplePayIntegrationHelper + let form = ReactFinalForm.useForm() + + let formState: ReactFinalForm.formState = ReactFinalForm.useFormState( + ReactFinalForm.useFormSubscription(["values"])->Nullable.make, + ) + let initalFormValue = + formState.values + ->getDictFromJsonObject + ->getDictfromDict("metadata") + ->getDictfromDict("apple_pay") + + let setFormData = () => { + let value = zenApplePayConfig(initalFormValue) + form.change("metadata.apple_pay", value->Identity.genericTypeToJson) + } + + React.useEffect0(() => { + let _ = setFormData() + None + }) + + let onSubmit = () => { + let metadata = + formState.values->getDictFromJsonObject->getDictfromDict("metadata")->JSON.Encode.object + let _ = update(metadata) + setShowWalletConfigurationModal(_ => false) + Nullable.null->Promise.resolve + } + let applePayManualFields = + applePayFields + ->Array.mapWithIndex((field, index) => { + let applePayField = field->convertMapObjectToDict->CommonMetaDataUtils.inputFieldMapper +
Int.toString}> + +
+ }) + ->React.array + <> + {applePayManualFields} +
+
+ +} diff --git a/src/screens/Connectors/ConnectorMetaData/Common/CommonMetaDataHelper.res b/src/screens/Connectors/ConnectorMetaData/Common/CommonMetaDataHelper.res new file mode 100644 index 000000000..e150d560c --- /dev/null +++ b/src/screens/Connectors/ConnectorMetaData/Common/CommonMetaDataHelper.res @@ -0,0 +1,148 @@ +let textInput = (~field: CommonMetaDataTypes.inputField, ~formName) => { + let {placeholder, label, required} = field + FormRenderer.makeFieldInfo( + ~label, + ~name={formName}, + ~placeholder, + ~customInput=InputFields.textInput(), + ~isRequired=required, + (), + ) +} + +let selectInput = ( + ~field: CommonMetaDataTypes.inputField, + ~formName, + ~opt=None, + ~onItemChange: option unit>=?, + (), +) => { + let {label, required} = field + let options = switch opt { + | Some(value) => value + | None => field.options->SelectBox.makeOptions + } + + FormRenderer.makeFieldInfo( + ~label={label}, + ~isRequired=required, + ~name={formName}, + ~customInput=(~input, ~placeholder as _) => + InputFields.selectInput( + ~customStyle="max-h-48", + ~options={options}, + ~buttonText="Select Value", + (), + )( + ~input={ + ...input, + onChange: event => { + let _ = switch onItemChange { + | Some(func) => func(event) + | _ => () + } + input.onChange(event) + }, + }, + ~placeholder="", + ), + (), + ) +} + +let multiSelectInput = (~field: CommonMetaDataTypes.inputField, ~formName) => { + let {label, required, options} = field + FormRenderer.makeFieldInfo( + ~label, + ~isRequired=required, + ~name={formName}, + ~customInput=InputFields.multiSelectInput( + ~showSelectionAsChips=false, + ~customStyle="max-h-48", + ~customButtonStyle="pr-3", + ~options={options->SelectBox.makeOptions}, + ~buttonText="Select Value", + (), + ), + (), + ) +} + +let toggleInput = (~field: CommonMetaDataTypes.inputField, ~formName) => { + let {label} = field + FormRenderer.makeFieldInfo( + ~name={formName}, + ~label, + ~customInput=InputFields.boolInput(~isDisabled=false, ~boolCustomClass="rounded-lg", ()), + (), + ) +} + +let radioInput = ( + ~field: CommonMetaDataTypes.inputField, + ~formName, + ~onItemChange: option unit>=?, + ~fill="", + (), +) => { + let {label, required, options} = field + + FormRenderer.makeFieldInfo( + ~label={label}, + ~isRequired=required, + ~name={formName}, + ~customInput=(~input, ~placeholder as _) => + InputFields.radioInput( + ~customStyle="cursor-pointer gap-2", + ~isHorizontal=true, + ~options=options->SelectBox.makeOptions, + ~buttonText="", + ~fill, + (), + )( + ~input={ + ...input, + onChange: event => { + let _ = switch onItemChange { + | Some(func) => func(event) + | _ => () + } + input.onChange(event) + }, + }, + ~placeholder="", + ), + (), + ) +} + +let getCurrencyOption: CurrencyUtils.currencyCode => SelectBox.dropdownOption = currencyType => { + open CurrencyUtils + { + label: currencyType->getCurrencyCodeStringFromVariant, + value: currencyType->getCurrencyCodeStringFromVariant, + } +} + +let currencyField = ( + ~name, + ~options=CurrencyUtils.currencyList, + ~disableSelect=false, + ~toolTipText="", + (), +) => + FormRenderer.makeFieldInfo( + ~label="Currency", + ~isRequired=true, + ~name, + ~description=toolTipText, + ~customInput=InputFields.selectInput( + ~deselectDisable=true, + ~disableSelect, + ~customStyle="max-h-48", + ~options=options->Array.map(getCurrencyOption), + ~buttonText="Select Currency", + (), + ), + (), + ) diff --git a/src/screens/Connectors/ConnectorMetaData/Common/CommonMetaDataTypes.res b/src/screens/Connectors/ConnectorMetaData/Common/CommonMetaDataTypes.res new file mode 100644 index 000000000..bb94d5107 --- /dev/null +++ b/src/screens/Connectors/ConnectorMetaData/Common/CommonMetaDataTypes.res @@ -0,0 +1,10 @@ +type inputType = Text | Toggle | Radio | Select | MultiSelect + +type inputField = { + name: string, + label: string, + placeholder: string, + required: bool, + options: array, + \"type": inputType, +} diff --git a/src/screens/Connectors/ConnectorMetaData/Common/CommonMetaDataUtils.res b/src/screens/Connectors/ConnectorMetaData/Common/CommonMetaDataUtils.res new file mode 100644 index 000000000..ae3c878db --- /dev/null +++ b/src/screens/Connectors/ConnectorMetaData/Common/CommonMetaDataUtils.res @@ -0,0 +1,22 @@ +open CommonMetaDataTypes +let inputTypeMapperr = ipType => { + switch ipType { + | "Text" => Text + | "Toggle" => Toggle + | "Select" => Select + | "MultiSelect" => MultiSelect + | _ => Text + } +} + +let inputFieldMapper = dict => { + open LogicUtils + { + name: dict->getString("name", ""), + label: dict->getString("label", ""), + placeholder: dict->getString("placeholder", ""), + required: dict->getBool("required", true), + options: dict->getStrArray("options"), + \"type": dict->getString("type", "")->inputTypeMapperr, + } +} diff --git a/src/screens/Connectors/ConnectorMetaData/ConnectorMetaData.res b/src/screens/Connectors/ConnectorMetaData/ConnectorMetaData.res new file mode 100644 index 000000000..e2de24461 --- /dev/null +++ b/src/screens/Connectors/ConnectorMetaData/ConnectorMetaData.res @@ -0,0 +1,28 @@ +@react.component +let make = (~connectorMetaDataFields) => { + open LogicUtils + open ConnectorMetaDataUtils + + let keys = + connectorMetaDataFields + ->Dict.keysToArray + ->Array.filter(ele => !Array.includes(metaDataInputKeysToIgnore, ele)) + <> + {keys + ->Array.mapWithIndex((field, index) => { + let fields = + connectorMetaDataFields + ->getDictfromDict(field) + ->JSON.Encode.object + ->convertMapObjectToDict + ->CommonMetaDataUtils.inputFieldMapper +
Int.toString}> + +
+ }) + ->React.array} + +} diff --git a/src/screens/Connectors/ConnectorMetaData/ConnectorMetaDataUtils.res b/src/screens/Connectors/ConnectorMetaData/ConnectorMetaDataUtils.res new file mode 100644 index 000000000..bae8d184a --- /dev/null +++ b/src/screens/Connectors/ConnectorMetaData/ConnectorMetaDataUtils.res @@ -0,0 +1,23 @@ +let metaDataInputKeysToIgnore = ["google_pay", "apple_pay", "zen_apple_pay"] +let connectorMetaDataNameMapper = name => { + switch name { + | _ => `metadata.${name}` + } +} + +let connectorMetaDataValueInput = (~connectorMetaDataFields: CommonMetaDataTypes.inputField) => { + open CommonMetaDataHelper + let {\"type", name} = connectorMetaDataFields + let formName = connectorMetaDataNameMapper(name) + + { + switch (\"type", name) { + | (Select, "merchant_config_currency") => currencyField(~name=formName, ()) + | (Text, _) => textInput(~field={connectorMetaDataFields}, ~formName) + | (Select, _) => selectInput(~field={connectorMetaDataFields}, ~formName, ()) + | (Toggle, _) => toggleInput(~field={connectorMetaDataFields}, ~formName) + | (MultiSelect, _) => multiSelectInput(~field={connectorMetaDataFields}, ~formName) + | _ => textInput(~field={connectorMetaDataFields}, ~formName) + } + } +} diff --git a/src/screens/Connectors/ConnectorMetaData/GooglePay/GooglePayIntegration.res b/src/screens/Connectors/ConnectorMetaData/GooglePay/GooglePayIntegration.res new file mode 100644 index 000000000..3ce7e4fad --- /dev/null +++ b/src/screens/Connectors/ConnectorMetaData/GooglePay/GooglePayIntegration.res @@ -0,0 +1,84 @@ +@react.component +let make = (~connector, ~setShowWalletConfigurationModal, ~update, ~onCloseClickCustomFun) => { + open LogicUtils + open GooglePayUtils + let googlePayFields = React.useMemo1(() => { + try { + if connector->isNonEmptyString { + let dict = + Window.getConnectorConfig(connector) + ->getDictFromJsonObject + ->getDictfromDict("metadata") + ->getArrayFromDict("google_pay", []) + + dict + } else { + [] + } + } catch { + | Exn.Error(e) => { + Js.log2("FAILED TO LOAD CONNECTOR CONFIG", e) + [] + } + } + }, [connector]) + let formState: ReactFinalForm.formState = ReactFinalForm.useFormState( + ReactFinalForm.useFormSubscription(["values"])->Nullable.make, + ) + let initialGooglePayDict = React.useMemo0(() => { + formState.values->getDictFromJsonObject->getDictfromDict("metadata") + }) + + let form = ReactFinalForm.useForm() + React.useEffect1(() => { + if connector->isNonEmptyString { + let value = googlePay(initialGooglePayDict->getDictfromDict("google_pay"), connector) + switch value { + | Zen(data) => form.change("metadata.google_pay", data->Identity.genericTypeToJson) + | Standard(data) => form.change("metadata.google_pay", data->Identity.genericTypeToJson) + } + } + None + }, [connector]) + let onSubmit = () => { + let metadata = + formState.values->getDictFromJsonObject->getDictfromDict("metadata")->JSON.Encode.object + setShowWalletConfigurationModal(_ => false) + let _ = update(metadata) + Nullable.null->Promise.resolve + } + + let closeModal = () => { + onCloseClickCustomFun() + setShowWalletConfigurationModal(_ => false) + } + <> + {googlePayFields + ->Array.mapWithIndex((field, index) => { + let googlePayField = field->convertMapObjectToDict->CommonMetaDataUtils.inputFieldMapper +
Int.toString}> + +
+ }) + ->React.array} +
+
+ +} diff --git a/src/screens/Connectors/ConnectorMetaData/GooglePay/GooglePayIntegrationTypes.res b/src/screens/Connectors/ConnectorMetaData/GooglePay/GooglePayIntegrationTypes.res new file mode 100644 index 000000000..c31c03bf9 --- /dev/null +++ b/src/screens/Connectors/ConnectorMetaData/GooglePay/GooglePayIntegrationTypes.res @@ -0,0 +1,41 @@ +type merchantInfo = { + merchant_id: option, + merchant_name: option, +} +type allowedPaymentMethodsParameters = { + allowed_auth_methods: array, + allowed_card_networks: array, +} +type tokenizationSpecificationParameters = { + gateway: string, + gateway_merchant_id?: string, + \"stripe:version"?: string, + \"stripe:publishableKey"?: string, +} +type tokenSpecification = { + \"type": string, + parameters: tokenizationSpecificationParameters, +} +type allowedMethod = { + \"type": string, + parameters: allowedPaymentMethodsParameters, + tokenization_specification: tokenSpecification, +} +type allowedPaymentMethods = array +type zenGooglepay = { + terminal_uuid: string, + pay_wall_secret: string, +} +type googlePay = {merchant_info: merchantInfo, allowed_payment_methods: allowedPaymentMethods} +type googlePayConfig = Zen(zenGooglepay) | Standard(googlePay) + +type inputType = Text | Toggle | Select + +type inputField = { + name: string, + label: string, + placeholder: string, + required: bool, + options: array, + \"type": inputType, +} diff --git a/src/screens/Connectors/ConnectorMetaData/GooglePay/GooglePayUtils.res b/src/screens/Connectors/ConnectorMetaData/GooglePay/GooglePayUtils.res new file mode 100644 index 000000000..a61aeb5e7 --- /dev/null +++ b/src/screens/Connectors/ConnectorMetaData/GooglePay/GooglePayUtils.res @@ -0,0 +1,111 @@ +open GooglePayIntegrationTypes +open LogicUtils +let allowedAuthMethod = ["PAN_ONLY", "CRYPTOGRAM_3DS"] +let allowedCardNetworks = ["AMEX", "DISCOVER", "INTERAC", "JCB", "MASTERCARD", "VISA"] +let allowedPaymentMethodparameters = { + allowed_auth_methods: allowedAuthMethod, + allowed_card_networks: allowedCardNetworks, +} + +let getCustomGateWayName = connector => { + open ConnectorUtils + open ConnectorTypes + switch connector->getConnectorNameTypeFromString() { + | Processors(CHECKOUT) => "checkoutltd" + | Processors(NUVEI) => "nuveidigital" + | Processors(AUTHORIZEDOTNET) => "authorizenet" + | Processors(GLOBALPAY) => "globalpayments" + | Processors(BANKOFAMERICA) | Processors(CYBERSOURCE) => "cybersource" + | _ => connector + } +} + +let tokenizationSpecificationParameters = (dict, connector) => { + open ConnectorUtils + open ConnectorTypes + let tokenizationSpecificationDict = + dict->getDictfromDict("tokenization_specification")->getDictfromDict("parameters") + switch connector->getConnectorNameTypeFromString() { + | Processors(STRIPE) => { + gateway: connector, + \"stripe:version": tokenizationSpecificationDict->getString("stripe:version", "2018-10-31"), + \"stripe:publishableKey": tokenizationSpecificationDict->getString( + "stripe:publishableKey", + "", + ), + } + | _ => { + gateway: connector->getCustomGateWayName, + gateway_merchant_id: tokenizationSpecificationDict->getString("gateway_merchant_id", ""), + } + } +} +let merchantInfo = dict => { + { + merchant_id: dict->getOptionString("merchant_id"), + merchant_name: dict->getOptionString("merchant_name"), + } +} +let tokenizationSpecification = (dict, connector) => { + \"type": "PAYMENT_GATEWAY", + parameters: dict->tokenizationSpecificationParameters(connector), +} + +let allowedPaymentMethod = (dict, connector) => { + \"type": "CARD", + parameters: allowedPaymentMethodparameters, + tokenization_specification: dict->tokenizationSpecification(connector), +} + +let zenGooglePayConfig = dict => { + { + terminal_uuid: dict->getString("terminal_uuid", ""), + pay_wall_secret: dict->getString("pay_wall_secret", ""), + } +} + +let googlePay = (dict, connector: string) => { + open ConnectorUtils + open ConnectorTypes + let merchantInfoDict = dict->getDictfromDict("merchant_info") + let allowedPaymentMethodDict = + dict + ->getArrayFromDict("allowed_payment_methods", []) + ->Array.get(0) + ->Option.getOr(Dict.make()->JSON.Encode.object) + ->getDictFromJsonObject + let standGooglePayConfig = { + merchant_info: merchantInfoDict->merchantInfo, + allowed_payment_methods: [allowedPaymentMethodDict->allowedPaymentMethod(connector)], + } + switch connector->getConnectorNameTypeFromString() { + | Processors(ZEN) => Zen(dict->zenGooglePayConfig) + | _ => Standard(standGooglePayConfig) + } +} + +let googlePayNameMapper = name => { + switch name { + | "merchant_id" => `metadata.google_pay.merchant_info.${name}` + | "merchant_name" => `metadata.google_pay.merchant_info.${name}` + | "terminal_uuid" => `metadata.google_pay.${name}` + | "pay_wall_secret" => `metadata.google_pay.${name}` + | _ => + `metadata.google_pay.allowed_payment_methods[0].tokenization_specification.parameters.${name}` + } +} + +let googlePayValueInput = (~googlePayField: CommonMetaDataTypes.inputField) => { + open CommonMetaDataHelper + let {\"type", name} = googlePayField + let formName = googlePayNameMapper(name) + + { + switch \"type" { + | Text => textInput(~field={googlePayField}, ~formName) + | Select => selectInput(~field={googlePayField}, ~formName, ()) + | MultiSelect => multiSelectInput(~field={googlePayField}, ~formName) + | _ => textInput(~field={googlePayField}, ~formName) + } + } +} diff --git a/src/screens/Connectors/ConnectorPaymentMethod.res b/src/screens/Connectors/ConnectorPaymentMethod.res index 98fe2b19d..d66476ef8 100644 --- a/src/screens/Connectors/ConnectorPaymentMethod.res +++ b/src/screens/Connectors/ConnectorPaymentMethod.res @@ -64,7 +64,6 @@ let make = ( payment_methods_enabled: paymentMethodsEnabled, metadata: metaData, } - let body = constructConnectorRequestBody(obj, initialValues)->ignoreFields( connectorID->Option.getOr(""), @@ -101,37 +100,39 @@ let make = ( } -
-
-
- String.toUpperCase} /> -

- {connector->getDisplayNameForConnector->React.string} -

-
-
-
-
-
-
-

- - {"NOTE:"->React.string} - - {"Please verify if the payment methods are turned on at the processor end as well."->React.string} -

- +
+
+

+ + {"NOTE:"->React.string} + + {"Please verify if the payment methods are turned on at the processor end as well."->React.string} +

+ +
-
+ +
} diff --git a/src/screens/Connectors/ConnectorUIUtils/PaymentMethod.res b/src/screens/Connectors/ConnectorUIUtils/PaymentMethod.res index 554e92c2c..b52e156a8 100644 --- a/src/screens/Connectors/ConnectorUIUtils/PaymentMethod.res +++ b/src/screens/Connectors/ConnectorUIUtils/PaymentMethod.res @@ -27,10 +27,16 @@ module CardRenderer = { ~paymentMethod, ~provider: array, ~_showAdvancedConfiguration, - ~metaData, ~setMetaData, ~connector, ) => { + let formState: ReactFinalForm.formState = ReactFinalForm.useFormState( + ReactFinalForm.useFormSubscription(["values"])->Nullable.make, + ) + let form = ReactFinalForm.useForm() + let initalFormValue = React.useMemo0(() => { + formState.values->getDictFromJsonObject->getDictfromDict("metadata") + }) let {globalUIConfig: {font: {textColor}}} = React.useContext(ThemeProvider.themeContext) let (showWalletConfigurationModal, setShowWalletConfigurationModal) = React.useState(_ => false) let (selectedWallet, setSelectedWallet) = React.useState(_ => Dict.make()->itemProviderMapper) @@ -147,6 +153,7 @@ module CardRenderer = { let p2RegularTextStyle = `${HSwitchUtils.getTextClass((P2, Medium))} text-grey-700 opacity-50` let removeSelectedWallet = () => { + form.change("metadata", initalFormValue->Identity.genericTypeToJson) setSelectedWallet(_ => Dict.make()->itemProviderMapper) } @@ -251,7 +258,6 @@ module CardRenderer = { childClass={""}> , ~updateDetails, - ~metaData, ~setMetaData, ~isPayoutFlow, ) => { @@ -303,7 +308,6 @@ module PaymentMethodsRender = { provider paymentMethod={value} _showAdvancedConfiguration=false - metaData setMetaData connector /> @@ -316,7 +320,6 @@ module PaymentMethodsRender = { paymentMethod={value} provider _showAdvancedConfiguration=false - metaData setMetaData connector /> diff --git a/src/screens/Connectors/ConnectorUtils.res b/src/screens/Connectors/ConnectorUtils.res index 7fa48464b..d2b7fee7a 100644 --- a/src/screens/Connectors/ConnectorUtils.res +++ b/src/screens/Connectors/ConnectorUtils.res @@ -987,22 +987,6 @@ let getWebHookRequiredFields = (connector: connectorTypes, fieldName: string) => } } -let getMetaDataRequiredFields = (connector: connectorTypes, fieldName: string) => { - switch (connector, fieldName) { - | (Processors(BLUESNAP), "merchant_id") => false - | (Processors(CHECKOUT), "acquirer_bin") - | (Processors(NMI), "acquirer_bin") - | (Processors(CYBERSOURCE), "acquirer_bin") => false - | (Processors(CHECKOUT), "acquirer_merchant_id") - | (Processors(NMI), "acquirer_merchant_id") - | (Processors(CYBERSOURCE), "acquirer_merchant_id") => false - | (Processors(PAYPAL), "paypal_sdk") => false - | (Processors(CYBERSOURCE), "acquirer_country_code") => false - | (ThreeDsAuthenticator(THREEDSECUREIO), "pull_mechanism_for_external_3ds_enabled") => false - | _ => true - } -} - let getAuthKeyMapFromConnectorAccountFields = connectorAccountFields => { open LogicUtils let authKeyMap = @@ -1076,19 +1060,30 @@ let validateConnectorRequiredFields = ( } }) } - connectorMetaDataFields - ->Dict.keysToArray - ->Array.forEach(fieldName => { - let walletType = fieldName->getPaymentMethodTypeFromString - if walletType !== GooglePay && walletType !== ApplePay { - let key = `metadata.${fieldName}` - let errorKey = connectorMetaDataFields->getString(fieldName, "") - let value = valuesFlattenJson->getString(`metadata.${fieldName}`, "") - if value->String.length === 0 && connector->getMetaDataRequiredFields(fieldName) { - Dict.set(newDict, key, `Please enter ${errorKey}`->JSON.Encode.string) + let keys = + connectorMetaDataFields + ->Dict.keysToArray + ->Array.filter(ele => !Array.includes(ConnectorMetaDataUtils.metaDataInputKeysToIgnore, ele)) + + { + keys->Array.forEach(field => { + let {\"type", name, required, label} = + connectorMetaDataFields + ->getDictfromDict(field) + ->JSON.Encode.object + ->convertMapObjectToDict + ->CommonMetaDataUtils.inputFieldMapper + let key = `metadata.${name}` + let value = switch \"type" { + | Text | Select => valuesFlattenJson->getString(`${key}`, "") + | Toggle => valuesFlattenJson->getBool(`${key}`, false)->getStringFromBool + | _ => "" } - } - }) + if value->String.length === 0 && required { + Dict.set(newDict, key, `Please enter ${label}`->JSON.Encode.string) + } + }) + } connectorWebHookDetails ->Dict.keysToArray diff --git a/src/screens/Connectors/Wallets/ApplePayWalletIntegration.res b/src/screens/Connectors/Wallets/ApplePayWalletIntegration.res deleted file mode 100644 index 1c9e09d93..000000000 --- a/src/screens/Connectors/Wallets/ApplePayWalletIntegration.res +++ /dev/null @@ -1,707 +0,0 @@ -module HostURL = { - @react.component - let make = (~prefix="") => { - let fieldInputVal = ReactFinalForm.useField(`${prefix}`).input - let fieldInput = switch fieldInputVal.value->JSON.Decode.string { - | Some(val) => val->LogicUtils.isNonEmptyString ? val : "domain_name" - | None => "domain_name" - } - -

- {`${fieldInput}/.well-known/apple-developer-merchantid-domain-association`->React.string} -

- } -} - -module MerchantBussinessCountry = { - @react.component - let make = (~fieldsArray: array, ~options) => { - let defaultInput: ReactFinalForm.fieldRenderProps = { - input: ReactFinalForm.makeInputRecord(""->JSON.Encode.string, _e => ()), - meta: ReactFinalForm.makeCustomError(None), - } - let operator = (fieldsArray->Array.get(0)->Option.getOr(defaultInput)).input - let input: ReactFinalForm.fieldRenderPropsInput = { - name: "string", - onBlur: _ev => (), - onChange: ev => { - let value = ev->Identity.formReactEventToString - operator.onChange(value->Identity.anyTypeToReactEvent) - }, - onFocus: _ev => (), - value: operator.value, - checked: true, - } - - - } -} - -let renderCountryInp = options => (fieldsArray: array) => { - -} - -let countryInput = (~id, ~options) => { - open FormRenderer - makeMultiInputFieldInfoOld( - ~label="Merchant Business Country", - ~comboCustomInput=renderCountryInp(options), - ~inputFields=[ - makeInputFieldInfo(~name=`${id}`, ()), - makeInputFieldInfo(~name=`${id}.default`, ()), - ], - ~isRequired=true, - (), - ) -} - -module Simplified = { - @react.component - let make = ( - ~metaData, - ~metadataInputs, - ~update, - ~setApplePayIntegrationSteps, - ~setVefifiedDomainList, - ~merchantBusinessCountry, - ) => { - open WalletHelper - open APIUtils - open ApplePayWalletIntegrationUtils - let getURL = useGetURL() - let url = RescriptReactRouter.useUrl() - let updateAPIHook = useUpdateMethod(~showErrorToast=false, ()) - let showToast = ToastState.useShowToast() - let fetchApi = AuthHooks.useApiFetcher() - let connectorID = HSwitchUtils.getConnectorIDFromUrl(url.path->List.toArray, "") - let merchantDetailsValue = HSwitchUtils.useMerchantDetailsValue() - let merchantId = merchantDetailsValue.merchant_id - let namePrefix = `apple_pay_combined.simplified.session_token_data` - let inputField = - [ - , - , - ]->React.array - let downloadApplePayCert = () => { - open Promise - let downloadURL = Window.env.applePayCertificateUrl->Option.getOr("") - fetchApi(downloadURL, ~method_=Get, ()) - ->then(res => res->Fetch.Response.blob) - ->then(content => { - DownloadUtils.download( - ~fileName=`apple-developer-merchantid-domain-association`, - ~content, - ~fileType="text/plain", - ) - showToast(~toastType=ToastSuccess, ~message="File download complete", ()) - - resolve() - }) - ->catch(_ => { - showToast( - ~toastType=ToastError, - ~message="Oops, something went wrong with the download. Please try again.", - (), - ) - resolve() - }) - ->ignore - } - - let downloadAPIKey = -
-
- - let onSubmit = async (values, _) => { - try { - let (body, domainName) = values->constructVerifyApplePayReq(connectorID) - let verifyAppleUrl = getURL( - ~entityName=VERIFY_APPLE_PAY, - ~methodType=Post, - ~id=Some(merchantId), - (), - ) - let _ = await updateAPIHook(verifyAppleUrl, body, Post, ()) - - let updatedValue = values->constructApplePayMetadata(metadataInputs, #simplified) - update(updatedValue) - setVefifiedDomainList(_ => [domainName]) - setApplePayIntegrationSteps(_ => ApplePayWalletIntegrationTypes.Verify) - } catch { - | _ => showToast(~message="Failed to Verify", ~toastType=ToastState.ToastError, ()) - } - Nullable.null - } - -
- validate(values, ["initiative_context", "merchant_business_country"], #simplified)} - onSubmit - initialValues={metaData}> - -
- -
- ) - /> -
-
- - - } -} -module Fields = { - @react.component - let make = (~configurationFields, ~merchantBusinessCountry, ~metaData) => { - open FormRenderer - open LogicUtils - let form = ReactFinalForm.useForm() - let {globalUIConfig: {font: {textColor}}} = React.useContext(ThemeProvider.themeContext) - let processingAt = - metaData - ->getDictFromJsonObject - ->getDictfromDict("apple_pay_combined") - ->getDictfromDict("manual") - ->getDictfromDict("session_token_data") - ->getString("payment_processing_details_at", "") - ->ApplePayWalletIntegrationUtils.paymentProcessingMapper - - let namePrefix = `apple_pay_combined.manual.session_token_data` - let domainValues = [ - [("label", "IOS/WEB"->JSON.Encode.string), ("value", "web"->JSON.Encode.string)] - ->Dict.fromArray - ->JSON.Encode.object, - [("label", "IOS"->JSON.Encode.string), ("value", "ios"->JSON.Encode.string)] - ->Dict.fromArray - ->JSON.Encode.object, - ] - let initiativeOptions = domainValues->Array.map(item => { - let dict = item->getDictFromJsonObject - let a: SelectBox.dropdownOption = { - label: dict->getString("label", ""), - value: dict->getString("value", ""), - } - a - }) - let initiative = - metaData - ->getDictFromJsonObject - ->getDictfromDict("apple_pay_combined") - ->getDictfromDict("manual") - ->getDictfromDict("session_token_data") - ->getString("initiative", "") - ->ApplePayWalletIntegrationUtils.initiativeMapper - let (processingAt, setProcessingAt) = React.useState(_ => processingAt) - let (initiative, setInitiative) = React.useState(_ => initiative) - - let fields = { - configurationFields - ->Dict.keysToArray - ->Array.mapWithIndex((field, index) => { -
Int.toString}> - {switch field->ApplePayWalletIntegrationUtils.customApplePlayFields { - | #merchant_business_country => -
- -
- | #initiative => -
- - {switch initiative { - | #web => - - | _ => React.null - }} -
- | #initiative_context => React.null - | #payment_processing_details_at => -
- string), - (#Hyperswitch: ApplePayWalletIntegrationUtils.paymentProcessingState :> string), - ], - ~setProcessingAt, - ~form, - ~textColor={textColor.primaryNormal}, - )} - /> - {switch processingAt { - | #Hyperswitch => -
- - -
- | _ => React.null - }} -
- | _ => { - let label = configurationFields->getString(field, "") -
Int.toString}> - snakeToTitle}`}, - ~customInput=InputFields.textInput(), - ~isRequired=true, - (), - )} - /> -
- } - }} -
- }) - ->React.array - } - <> {fields} - } -} - -module Manual = { - @react.component - let make = ( - ~metadataInputs, - ~metaData, - ~update, - ~setApplePayIntegrationSteps, - ~setVefifiedDomainList, - ~merchantBusinessCountry, - ) => { - open WalletHelper - open LogicUtils - open ApplePayWalletIntegrationUtils - - // Need to refactor - let _ = ConnectorUtils.updateMetaData(~metaData) - // - let configurationFields = - metadataInputs - ->getDictfromDict("apple_pay") - ->getDictfromDict("session_token_data") - ->JSON.Encode.object - ->Identity.jsonToAnyType - ->convertMapObjectToDict - - let onSubmit = (values, _) => { - let domainName = values->getSessionTokenDict(#manual)->getString("initiative_context", "") - let updatedValue = values->constructApplePayMetadata(metadataInputs, #manual) - update(updatedValue) - setVefifiedDomainList(_ => [domainName]) - setApplePayIntegrationSteps(_ => ApplePayWalletIntegrationTypes.Verify) - Nullable.null->Promise.resolve - } - -
- -

- {"Follow our"->React.string} - - {" Apple Pay Setup Guide "->React.string} - - {"to get help with filling the details below"->React.string} -

-
-
- validate( - values, - configurationFields - ->Dict.keysToArray - ->getUniqueArray - ->Array.filter(ele => !Array.includes(["initiative_context"], ele)), - #manual, - )} - onSubmit - initialValues={metaData}> - -
-
- - -
- } -} - -module Landing = { - open WalletHelper - @react.component - let make = ( - ~connector, - ~setApplePayIntegrationType, - ~appleIntegrationType, - ~setShowWalletConfigurationModal, - ~setApplePayIntegrationSteps, - ) => { - open ApplePayWalletIntegrationTypes - <> - {switch connector->ConnectorUtils.getConnectorNameTypeFromString() { - | Processors(STRIPE) | Processors(BANKOFAMERICA) | Processors(CYBERSOURCE) => -
setApplePayIntegrationType(_ => #simplified)}> - -
- {"Get Apple Pay enabled on your web domains by hosting a verification file, that’s it."->React.string} -
-
- - -
-
-
- | _ => React.null - }} -
setApplePayIntegrationType(_ => #manual)}> - -
- -
-
- - -
-
-
-
-
- - } -} - -module Verified = { - @react.component - let make = ( - ~verifiedDomainList, - ~setApplePayIntegrationType, - ~appleIntegrationType, - ~setApplePayIntegrationSteps, - ~setShowWalletConfigurationModal, - ~onCloseClickCustomFun, - ) => { - open WalletHelper - open ApplePayWalletIntegrationTypes - <> -
-

{" Web Domains"->React.string}

- {verifiedDomainList - ->Array.mapWithIndex((domainUrl, index) => { -
setApplePayIntegrationType(_ => #manual)}> -
-
-
- {domainUrl->String.length > 0 ? domainUrl->React.string : "Default"->React.string} -
-
- {switch appleIntegrationType { - | #simplified => - - | #manual => - setApplePayIntegrationSteps(_ => Configure)} - name={"arrow-right"} - size={15} - /> - }} -
-
-
-
- }) - ->React.array} -
-
-
- - } -} - -@react.component -let make = ( - ~metadataInputs, - ~update, - ~metaData, - ~setShowWalletConfigurationModal, - ~connector, - ~onCloseClickCustomFun, -) => { - open ApplePayWalletIntegrationTypes - open APIUtils - open WalletHelper - let getURL = useGetURL() - let (appleIntegrationType, setApplePayIntegrationType) = React.useState(_ => #manual) - let (applePayIntegrationStep, setApplePayIntegrationSteps) = React.useState(_ => Landing) - let (verifiedDomainList, setVefifiedDomainList) = React.useState(_ => []) - let (merchantBusinessCountry, setMerchantBusinessCountry) = React.useState(_ => []) - let (screenState, setScreenState) = React.useState(_ => PageLoaderWrapper.Success) - let fetchDetails = useGetMethod() - let getProcessorDetails = async () => { - open LogicUtils - try { - setScreenState(_ => Loading) - let paymentMethoConfigUrl = getURL(~entityName=PAYMENT_METHOD_CONFIG, ~methodType=Get, ()) - let res = await fetchDetails( - `${paymentMethoConfigUrl}?connector=${connector}&paymentMethodType=apple_pay`, - ) - let countries = - res - ->getDictFromJsonObject - ->getArrayFromDict("countries", []) - ->Array.map(item => { - let dict = item->getDictFromJsonObject - let a: SelectBox.dropdownOption = { - label: dict->getString("name", ""), - value: dict->getString("code", ""), - } - a - }) - - setMerchantBusinessCountry(_ => countries) - setScreenState(_ => Success) - } catch { - | _ => setScreenState(_ => Success) - } - } - - React.useEffect1(() => { - // Need to refactor - if connector->String.length > 0 { - { - switch connector->ConnectorUtils.getConnectorNameTypeFromString() { - | Processors(STRIPE) - | Processors(BANKOFAMERICA) - | Processors(CYBERSOURCE) => - setApplePayIntegrationType(_ => #simplified) - | _ => setApplePayIntegrationType(_ => #manual) - } - } - - getProcessorDetails()->ignore - } - None - }, [connector]) - -
- -
-
} - sectionHeight="!h-screen"> -
- - {switch applePayIntegrationStep { - | Landing => - - | Configure => - switch appleIntegrationType { - | #simplified => - - | #manual => - - } - | Verify => - - }} -
- -} diff --git a/src/screens/Connectors/Wallets/ApplePayWalletIntegrationTypes.res b/src/screens/Connectors/Wallets/ApplePayWalletIntegrationTypes.res deleted file mode 100644 index e3438d581..000000000 --- a/src/screens/Connectors/Wallets/ApplePayWalletIntegrationTypes.res +++ /dev/null @@ -1,9 +0,0 @@ -type applePayIntegrationType = [#manual | #simplified] - -type applePayIntegrationSteps = Landing | Configure | Verify -type simplifiedApplePayIntegartionTypes = EnterUrl | DownloadFile | HostUrl - -type verifyApplePay = { - domain_names: array, - merchant_connector_account_id: string, -} diff --git a/src/screens/Connectors/Wallets/ApplePayWalletIntegrationUtils.res b/src/screens/Connectors/Wallets/ApplePayWalletIntegrationUtils.res deleted file mode 100644 index 1997d8857..000000000 --- a/src/screens/Connectors/Wallets/ApplePayWalletIntegrationUtils.res +++ /dev/null @@ -1,228 +0,0 @@ -open ApplePayWalletIntegrationTypes -type paymentProcessingState = [#Connector | #Hyperswitch] -type initiative = [#ios | #web | #invalid] - -let paymentProcessingMapper = state => { - switch state->String.toLowerCase { - | "connector" => #Connector - | "hyperswitch" => #Hyperswitch - | _ => #Connector - } -} -let initiativeMapper = state => { - switch state->String.toLowerCase { - | "ios" => #ios - | "web" => #web - | _ => #invalid - } -} -let getSessionTokenDict = (values: JSON.t, applePayIntegrationType: applePayIntegrationType) => { - open LogicUtils - values - ->getDictFromJsonObject - ->getDictfromDict("apple_pay_combined") - ->getDictfromDict((applePayIntegrationType :> string)) - ->getDictfromDict("session_token_data") -} - -let validate = ( - values: JSON.t, - mandateKeys: array, - integrationType: ApplePayWalletIntegrationTypes.applePayIntegrationType, -) => { - open LogicUtils - let dict = values->getSessionTokenDict(integrationType) - let errorDict = Dict.make() - mandateKeys->Array.forEach(key => { - let value = dict->getString(key, "") - if value->isEmptyString { - errorDict->Dict.set(key, `${key} cannot be empty!`->JSON.Encode.string) - } - }) - let processingAt = dict->getString("payment_processing_details_at", "")->paymentProcessingMapper - - let initiative = dict->getString("initiative", "")->initiativeMapper - - if processingAt === #Hyperswitch { - let processingCertificate = dict->getString("payment_processing_certificate", "") - let processingCertificateKey = dict->getString("payment_processing_certificate_key", "") - if processingCertificate->isEmptyString { - errorDict->Dict.set( - "payment_processing_certificate", - `Processing Certificate cannot be empty!`->JSON.Encode.string, - ) - } - if processingCertificateKey->isEmptyString { - errorDict->Dict.set( - "payment_processing_certificate_key", - `Processing Certificate Key cannot be empty!`->JSON.Encode.string, - ) - } - } - - if initiative == #web { - let domainName = dict->getString("initiative_context", "") - if domainName->isEmptyString { - errorDict->Dict.set("initiative_context", `Domain Name Cannot be Empty`->JSON.Encode.string) - } - } - - errorDict->JSON.Encode.object -} - -let constructApplePayMetadata = ( - values: JSON.t, - metadataInputs, - integrationType: applePayIntegrationType, -) => { - open LogicUtils - let paymentRequestData = - metadataInputs->getDictfromDict("apple_pay")->getDictfromDict("payment_request_data") - // Need to refactor - switch integrationType { - | #manual => { - let label = - values - ->getDictFromJsonObject - ->getDictfromDict("apple_pay_combined") - ->getDictfromDict((#manual: applePayIntegrationType :> string)) - ->getDictfromDict("session_token_data") - ->getString("display_name", "apple") - paymentRequestData->Dict.set("label", label->JSON.Encode.string) - } - - | _ => () - } - - let dict = values->getDictFromJsonObject - let applePayDict = - dict - ->getDictfromDict("apple_pay_combined") - ->getDictfromDict((integrationType: applePayIntegrationType :> string)) - // 1.remove existing apple_pay_combined - // 2.At given time either #manual or #simplified can exists - dict->Dict.set("apple_pay_combined", Dict.make()->JSON.Encode.object)->ignore - - applePayDict->Dict.set("payment_request_data", paymentRequestData->JSON.Encode.object)->ignore - - dict - ->Dict.set( - "apple_pay_combined", - Dict.fromArray([ - ((integrationType: applePayIntegrationType :> string), applePayDict->JSON.Encode.object), - ])->JSON.Encode.object, - ) - ->ignore - dict->JSON.Encode.object -} - -let constructVerifyApplePayReq = (values, connectorID) => { - open LogicUtils - let domainName = values->getSessionTokenDict(#simplified)->getString("initiative_context", "") - let data = { - domain_names: [domainName], - merchant_connector_account_id: connectorID, - }->JSON.stringifyAny - - let body = switch data { - | Some(val) => val->LogicUtils.safeParse - | None => Dict.make()->JSON.Encode.object - } - (body, domainName) -} - -type customApplePayFields = [ - | #merchant_business_country - | #payment_processing_details_at - | #initiative - | #initiative_context - | #other -] - -let customApplePlayFields = field => { - switch field { - | "merchant_business_country" => #merchant_business_country - | "payment_processing_details_at" => #payment_processing_details_at - | "initiative" => #initiative - | "initiative_context" => #initiative_context - - | _ => #other - } -} - -let paymentProcessingAtField = ( - ~name, - ~label, - ~options, - ~setProcessingAt, - ~form: ReactFinalForm.formApi, - ~textColor, -) => { - FormRenderer.makeFieldInfo( - ~name, - ~label, - ~customInput=(~input, ~placeholder) => - InputFields.radioInput( - ~options=options->SelectBox.makeOptions, - ~buttonText="", - ~isHorizontal=true, - ~customStyle="cursor-pointer gap-2", - ~fill={`${textColor}`}, - (), - )( - ~input={ - ...input, - onChange: event => { - let value = event->Identity.formReactEventToString->paymentProcessingMapper - setProcessingAt(_ => value) - if value === #Connector { - form.change( - "apple_pay_combined.manual.session_token_data.payment_processing_certificate", - JSON.Encode.null, - ) - form.change( - "apple_pay_combined.manual.session_token_data.payment_processing_certificate_key", - JSON.Encode.null, - ) - } - input.onChange(event) - }, - }, - ~placeholder, - ), - (), - ) -} - -let initiativeField = (~name, ~label, ~options, ~setInitiative, ~form: ReactFinalForm.formApi) => { - FormRenderer.makeFieldInfo( - ~name, - ~label, - ~customInput=(~input, ~placeholder as _) => - InputFields.selectInput( - ~options, - ~buttonText="Select Value", - ~customStyle="cursor-pointer gap-2", - (), - )( - ~input={ - ...input, - onChange: event => { - let value = event->Identity.formReactEventToString->initiativeMapper - setInitiative(_ => value) - if value === #ios { - form.change( - "apple_pay_combined.manual.session_token_data.initiative_context", - JSON.Encode.null, - ) - } - input.onChange(event) - }, - }, - // ~isHorizontal=true, - - ~placeholder="", - ), - (), - ) -} diff --git a/src/screens/Connectors/Wallets/Wallet.res b/src/screens/Connectors/Wallets/Wallet.res index 623b40b18..933203d3e 100644 --- a/src/screens/Connectors/Wallets/Wallet.res +++ b/src/screens/Connectors/Wallets/Wallet.res @@ -1,25 +1,9 @@ -let getConfigurationFields = (metadataInputs, method, connector) => { - open ConnectorUtils - open LogicUtils - switch method->getPaymentMethodTypeFromString { - | GooglePay => metadataInputs->getDictfromDict("google_pay") - - | ApplePay => - switch connector->getConnectorNameTypeFromString() { - | Processors(ZEN) => metadataInputs->getDictfromDict("apple_pay") - | _ => metadataInputs->getDictfromDict("apple_pay")->getDictfromDict("session_token_data") - } - - | _ => Dict.make() - } -} module Wallets = { open ConnectorTypes open ConnectorUtils @react.component let make = ( ~method, - ~metaData, ~setMetaData, ~setShowWalletConfigurationModal, ~updateDetails, @@ -28,126 +12,24 @@ module Wallets = { ~onCloseClickCustomFun, ) => { open LogicUtils + let connector = UrlUtils.useGetFilterDictFromUrl("")->getString("name", "") - let metadataInputs = React.useMemo1(() => { - try { - Window.getConnectorConfig(connector)->getDictFromJsonObject->getDictfromDict("metadata") - } catch { - | _error => Dict.make() - } - }, [connector]) let update = json => { setMetaData(_ => json) paymentMethodsEnabled->addMethod(paymentMethod, method)->updateDetails } - let onSubmit = (values, _) => { - let json = switch method.payment_method_type->getPaymentMethodTypeFromString { - | GooglePay => values - | ApplePay => - switch connector->getConnectorNameTypeFromString() { - | Processors(ZEN) => values - - | _ => { - let paymentRequestData = - metadataInputs->getDictfromDict("apple_pay")->getDictfromDict("payment_request_data") - - let _ = - values - ->getDictFromJsonObject - ->getDictfromDict("apple_pay") - ->Dict.set("payment_request_data", paymentRequestData->JSON.Encode.object) - values - } - } - - | _ => Dict.make()->JSON.Encode.object - } - - let _ = update(json) - setShowWalletConfigurationModal(_ => false) - - Nullable.null->Promise.resolve - } - - let configurationFields = getConfigurationFields( - metadataInputs, - method.payment_method_type, - connector, - ) - - let validate = values => { - let dict = - values->getDictFromJsonObject->getConfigurationFields(method.payment_method_type, connector) - let mandateKyes = configurationFields->Dict.keysToArray->getUniqueArray - let errorDict = Dict.make() - mandateKyes->Array.forEach(key => { - if dict->getString(key, "")->isEmptyString { - errorDict->Dict.set(key, `${key} cannot be empty!`->JSON.Encode.string) - } - }) - errorDict->JSON.Encode.object - } - - let name = switch method.payment_method_type->getPaymentMethodTypeFromString { - | GooglePay => `google_pay` - - | ApplePay => - switch connector->getConnectorNameTypeFromString() { - | Processors(ZEN) => `apple_pay` - | _ => `apple_pay.session_token_data` - } - - | _ => `` - } - - let fields = { - configurationFields - ->Dict.keysToArray - ->Array.mapWithIndex((field, index) => { - let label = configurationFields->getString(field, "") -
Int.toString}> - snakeToTitle}`}, - ~customInput=InputFields.textInput(), - ~isRequired=true, - (), - )} - /> -
- }) - ->React.array - }
{switch method.payment_method_type->getPaymentMethodTypeFromString { | ApplePay => - - | GooglePay => - Dict.keysToArray->Array.length > 0}> -
- {fields} - - - -
+ | _ => React.null }}
diff --git a/src/screens/Home/CommonConnectorFlow/SetupConnector.res b/src/screens/Home/CommonConnectorFlow/SetupConnector.res index 7efb8d658..6d0d73042 100644 --- a/src/screens/Home/CommonConnectorFlow/SetupConnector.res +++ b/src/screens/Home/CommonConnectorFlow/SetupConnector.res @@ -157,7 +157,6 @@ module ConfigureProcessor = { checkboxText="" /> - } } @@ -212,12 +211,17 @@ module SelectPaymentMethods = { let onSubmitMain = async () => { setButtonState(_ => Loading) try { + open LogicUtils let obj: ConnectorTypes.wasmRequest = { connector: connectorName, payment_methods_enabled: paymentMethodsEnabled, metadata: metaData, } let body = constructConnectorRequestBody(obj, initialValues) + // Need to refactor + let metaData = body->getDictFromJsonObject->getDictfromDict("metadata")->JSON.Encode.object + let _ = ConnectorUtils.updateMetaData(~metaData) + // let connectorUrl = getURL(~entityName=CONNECTOR, ~methodType=Post, ~id=None, ()) let response = await updateAPIHook(connectorUrl, body, Post, ()) @@ -274,15 +278,17 @@ module SelectPaymentMethods = { onClick={_ => setConnectorConfigureState(_ => Configure_keys)} buttonSize=Small />}> - +
+ + + } } diff --git a/src/screens/StripePlusPaypal/StripePlusPaypalUIUtils.res b/src/screens/StripePlusPaypal/StripePlusPaypalUIUtils.res index e559a6abd..3cc64b1c8 100644 --- a/src/screens/StripePlusPaypal/StripePlusPaypalUIUtils.res +++ b/src/screens/StripePlusPaypal/StripePlusPaypalUIUtils.res @@ -147,7 +147,6 @@ module SelectPaymentMethods = { paymentMethodsEnabled updateDetails setMetaData - metaData isPayoutFlow=false /> diff --git a/src/screens/WooCommerce/WooCommerceUIUtils.res b/src/screens/WooCommerce/WooCommerceUIUtils.res index 10100fce7..59261b391 100644 --- a/src/screens/WooCommerce/WooCommerceUIUtils.res +++ b/src/screens/WooCommerce/WooCommerceUIUtils.res @@ -171,7 +171,6 @@ module SelectPaymentMethods = { paymentMethodsEnabled updateDetails setMetaData - metaData isPayoutFlow=false /> diff --git a/src/utils/LogicUtils.res b/src/utils/LogicUtils.res index f174e668a..451924eea 100644 --- a/src/utils/LogicUtils.res +++ b/src/utils/LogicUtils.res @@ -66,7 +66,7 @@ let getDictFromJsonObject = json => { } } -let convertMapObjectToDict = genericTypeMapVal => { +let convertMapObjectToDict = (genericTypeMapVal: JSON.t) => { try { open MapTypes let map = create(genericTypeMapVal) @@ -74,7 +74,7 @@ let convertMapObjectToDict = genericTypeMapVal => { let dict = object.fromEntries(mapIterator)->getDictFromJsonObject dict } catch { - | _ => genericTypeMapVal + | _ => Dict.make() } }