Int.toString}px`}
+ id="google-pay-button"
+ className={`w-full flex flex-row justify-center rounded-md`}
+ />
+
+ } else {
+
-
+ }
}
let default = make
diff --git a/src/Payments/GPay.resi b/src/Payments/GPay.resi
index d03d071d4..11bfe1246 100644
--- a/src/Payments/GPay.resi
+++ b/src/Payments/GPay.resi
@@ -2,4 +2,6 @@
let default: (
~sessionObj: option
,
~thirdPartySessionObj: option,
+ ~walletOptions: array,
+ ~paymentType: CardThemeType.mode,
) => React.element
diff --git a/src/Payments/PaymentMethodsRecord.res b/src/Payments/PaymentMethodsRecord.res
index 1d3855e32..338ffb5f9 100644
--- a/src/Payments/PaymentMethodsRecord.res
+++ b/src/Payments/PaymentMethodsRecord.res
@@ -802,6 +802,7 @@ type paymentMethodList = {
mandate_payment: option,
payment_type: payment_type,
merchant_name: string,
+ collect_billing_details_from_wallets: bool,
}
let defaultPaymentMethodType = {
@@ -823,6 +824,7 @@ let defaultList = {
mandate_payment: None,
payment_type: NONE,
merchant_name: "",
+ collect_billing_details_from_wallets: true,
}
let getMethod = str => {
switch str {
@@ -1030,6 +1032,11 @@ let itemToObjMapper = dict => {
mandate_payment: getMandate(dict, "mandate_payment"),
payment_type: getString(dict, "payment_type", "")->paymentTypeMapper,
merchant_name: getString(dict, "merchant_name", ""),
+ collect_billing_details_from_wallets: getBool(
+ dict,
+ "collect_billing_details_from_wallets",
+ true,
+ ),
}
}
diff --git a/src/Payments/PaymentRequestButtonElement.res b/src/Payments/PaymentRequestButtonElement.res
index 2814f9901..f78578493 100644
--- a/src/Payments/PaymentRequestButtonElement.res
+++ b/src/Payments/PaymentRequestButtonElement.res
@@ -77,9 +77,15 @@ let make = (~sessions, ~walletOptions, ~paymentType) => {
switch googlePayThirdPartyToken {
| GooglePayThirdPartyTokenOptional(googlePayThirdPartyOptToken) =>
+ | _ =>
+
- | _ =>
}
| _ => React.null
}}
@@ -97,7 +103,8 @@ let make = (~sessions, ~walletOptions, ~paymentType) => {
| ApplePayWallet =>
switch applePayToken {
- | ApplePayTokenOptional(optToken) =>
+ | ApplePayTokenOptional(optToken) =>
+
| _ => React.null
}
| KlarnaWallet =>
diff --git a/src/Utilities/ApplePayHelpers.res b/src/Utilities/ApplePayHelpers.res
index 624f0f4eb..667b39682 100644
--- a/src/Utilities/ApplePayHelpers.res
+++ b/src/Utilities/ApplePayHelpers.res
@@ -142,6 +142,8 @@ let useHandleApplePayResponse = (
~syncPayment=() => (),
~isInvokeSDKFlow=true,
~isSavedMethodsFlow=false,
+ ~isWallet=true,
+ ~requiredFieldsBody=Dict.make(),
) => {
let options = Recoil.useRecoilValueFromAtom(RecoilAtoms.optionAtom)
let {publishableKey} = Recoil.useRecoilValueFromAtom(RecoilAtoms.keys)
@@ -187,8 +189,18 @@ let useHandleApplePayResponse = (
~isSavedMethodsFlow,
)
+ let bodyArr = if isWallet {
+ applePayBody
+ } else {
+ applePayBody
+ ->getJsonFromArrayOfJson
+ ->flattenObject(true)
+ ->mergeTwoFlattenedJsonDicts(requiredFieldsBody)
+ ->getArrayOfTupleFromDict
+ }
+
processPayment(
- ~bodyArr=applePayBody,
+ ~bodyArr,
~isThirdPartyFlow=false,
~isGuestCustomer,
~paymentMethodListValue,
@@ -199,7 +211,7 @@ let useHandleApplePayResponse = (
)
} else if dict->Dict.get("showApplePayButton")->Option.isSome {
setApplePayClicked(_ => false)
- if isSavedMethodsFlow {
+ if isSavedMethodsFlow || !isWallet {
postFailedSubmitResponse(~errortype="server_error", ~message="Something went wrong")
}
} else if dict->Dict.get("applePaySyncPayment")->Option.isSome {
@@ -216,7 +228,14 @@ let useHandleApplePayResponse = (
Window.removeEventListener("message", handleApplePayMessages)
},
)
- }, (isInvokeSDKFlow, processPayment, stateJson, isManualRetryEnabled))
+ }, (
+ isInvokeSDKFlow,
+ processPayment,
+ stateJson,
+ isManualRetryEnabled,
+ isWallet,
+ requiredFieldsBody,
+ ))
}
let handleApplePayButtonClicked = (~sessionObj, ~componentName) => {
@@ -227,3 +246,30 @@ let handleApplePayButtonClicked = (~sessionObj, ~componentName) => {
]
handlePostMessage(message)
}
+
+let useSubmitCallback = (~isWallet, ~sessionObj, ~componentName) => {
+ let areRequiredFieldsValid = Recoil.useRecoilValueFromAtom(RecoilAtoms.areRequiredFieldsValid)
+ let areRequiredFieldsEmpty = Recoil.useRecoilValueFromAtom(RecoilAtoms.areRequiredFieldsEmpty)
+ let options = Recoil.useRecoilValueFromAtom(RecoilAtoms.optionAtom)
+ let {localeString} = Recoil.useRecoilValueFromAtom(RecoilAtoms.configAtom)
+
+ React.useCallback((ev: Window.event) => {
+ if !isWallet {
+ let json = ev.data->JSON.parseExn
+ let confirm = json->getDictFromJson->ConfirmType.itemToObjMapper
+ if confirm.doSubmit && areRequiredFieldsValid && !areRequiredFieldsEmpty {
+ options.readOnly ? () : handleApplePayButtonClicked(~sessionObj, ~componentName)
+ } else if areRequiredFieldsEmpty {
+ postFailedSubmitResponse(
+ ~errortype="validation_error",
+ ~message=localeString.enterFieldsText,
+ )
+ } else if !areRequiredFieldsValid {
+ postFailedSubmitResponse(
+ ~errortype="validation_error",
+ ~message=localeString.enterValidDetailsText,
+ )
+ }
+ }
+ }, (areRequiredFieldsValid, areRequiredFieldsEmpty, isWallet, sessionObj, componentName))
+}
diff --git a/src/Utilities/DynamicFieldsUtils.res b/src/Utilities/DynamicFieldsUtils.res
index 02bf1ae1d..35dee4224 100644
--- a/src/Utilities/DynamicFieldsUtils.res
+++ b/src/Utilities/DynamicFieldsUtils.res
@@ -580,20 +580,22 @@ let useRequiredFieldsBody = (
| FullName => getName(item, fullName)
| _ => item.field_type->getFieldValueFromFieldType
}
- if (
- isSavedCardFlow &&
- (item.field_type === BillingName || item.field_type === FullName) &&
- item.display_name === "card_holder_name" &&
- item.required_field === "payment_method_data.card.card_holder_name"
- ) {
- if !isAllStoredCardsHaveName {
- acc->Dict.set(
- "payment_method_data.card_token.card_holder_name",
- value->JSON.Encode.string,
- )
+ if value != "" {
+ if (
+ isSavedCardFlow &&
+ (item.field_type === BillingName || item.field_type === FullName) &&
+ item.display_name === "card_holder_name" &&
+ item.required_field === "payment_method_data.card.card_holder_name"
+ ) {
+ if !isAllStoredCardsHaveName {
+ acc->Dict.set(
+ "payment_method_data.card_token.card_holder_name",
+ value->JSON.Encode.string,
+ )
+ }
+ } else {
+ acc->Dict.set(item.required_field, value->JSON.Encode.string)
}
- } else {
- acc->Dict.set(item.required_field, value->JSON.Encode.string)
}
acc
})
@@ -822,22 +824,6 @@ let usePaymentMethodTypeFromList = (
}, (paymentMethodListValue, paymentMethod, paymentMethodType))
}
-let useAreAllRequiredFieldsPrefilled = (
- ~paymentMethodListValue,
- ~paymentMethod,
- ~paymentMethodType,
-) => {
- let paymentMethodTypes = usePaymentMethodTypeFromList(
- ~paymentMethodListValue,
- ~paymentMethod,
- ~paymentMethodType,
- )
-
- paymentMethodTypes.required_fields->Array.reduce(true, (acc, requiredField) => {
- acc && requiredField.value != ""
- })
-}
-
let removeRequiredFieldsDuplicates = (
requiredFields: array,
) => {
diff --git a/src/Utilities/GooglePayHelpers.res b/src/Utilities/GooglePayHelpers.res
index f9a756caf..b8bb45ab2 100644
--- a/src/Utilities/GooglePayHelpers.res
+++ b/src/Utilities/GooglePayHelpers.res
@@ -81,7 +81,13 @@ let processPayment = (
)
}
-let useHandleGooglePayResponse = (~connectors, ~intent, ~isSavedMethodsFlow=false) => {
+let useHandleGooglePayResponse = (
+ ~connectors,
+ ~intent,
+ ~isSavedMethodsFlow=false,
+ ~isWallet=true,
+ ~requiredFieldsBody=Dict.make(),
+) => {
let options = Recoil.useRecoilValueFromAtom(RecoilAtoms.optionAtom)
let {publishableKey} = Recoil.useRecoilValueFromAtom(RecoilAtoms.keys)
let isManualRetryEnabled = Recoil.useRecoilValueFromAtom(RecoilAtoms.isManualRetryEnabled)
@@ -118,8 +124,19 @@ let useHandleGooglePayResponse = (~connectors, ~intent, ~isSavedMethodsFlow=fals
~stateJson,
~isSavedMethodsFlow,
)
+
+ let googlePayBody = if isWallet {
+ body
+ } else {
+ body
+ ->getJsonFromArrayOfJson
+ ->flattenObject(true)
+ ->mergeTwoFlattenedJsonDicts(requiredFieldsBody)
+ ->getArrayOfTupleFromDict
+ }
+
processPayment(
- ~body,
+ ~body=googlePayBody,
~isThirdPartyFlow=false,
~intent,
~options: PaymentType.options,
@@ -129,14 +146,14 @@ let useHandleGooglePayResponse = (~connectors, ~intent, ~isSavedMethodsFlow=fals
}
if dict->Dict.get("gpayError")->Option.isSome {
handlePostMessage([("fullscreen", false->JSON.Encode.bool)])
- if isSavedMethodsFlow {
+ if isSavedMethodsFlow || !isWallet {
postFailedSubmitResponse(~errortype="server_error", ~message="Something went wrong")
}
}
}
Window.addEventListener("message", handle)
Some(() => {Window.removeEventListener("message", handle)})
- }, (paymentMethodTypes, stateJson, isManualRetryEnabled))
+ }, (paymentMethodTypes, stateJson, isManualRetryEnabled, requiredFieldsBody, isWallet))
}
let handleGooglePayClicked = (~sessionObj, ~componentName, ~iframeId, ~readOnly) => {
@@ -153,3 +170,38 @@ let handleGooglePayClicked = (~sessionObj, ~componentName, ~iframeId, ~readOnly)
])
}
}
+
+let useSubmitCallback = (~isWallet, ~sessionObj, ~componentName) => {
+ let areRequiredFieldsValid = Recoil.useRecoilValueFromAtom(RecoilAtoms.areRequiredFieldsValid)
+ let areRequiredFieldsEmpty = Recoil.useRecoilValueFromAtom(RecoilAtoms.areRequiredFieldsEmpty)
+ let options = Recoil.useRecoilValueFromAtom(RecoilAtoms.optionAtom)
+ let {localeString} = Recoil.useRecoilValueFromAtom(RecoilAtoms.configAtom)
+ let {iframeId} = Recoil.useRecoilValueFromAtom(RecoilAtoms.keys)
+
+ React.useCallback((ev: Window.event) => {
+ if !isWallet {
+ let json = ev.data->JSON.parseExn
+ let confirm = json->getDictFromJson->ConfirmType.itemToObjMapper
+ if confirm.doSubmit && areRequiredFieldsValid && !areRequiredFieldsEmpty {
+ handleGooglePayClicked(~sessionObj, ~componentName, ~iframeId, ~readOnly=options.readOnly)
+ } else if areRequiredFieldsEmpty {
+ postFailedSubmitResponse(
+ ~errortype="validation_error",
+ ~message=localeString.enterFieldsText,
+ )
+ } else if !areRequiredFieldsValid {
+ postFailedSubmitResponse(
+ ~errortype="validation_error",
+ ~message=localeString.enterValidDetailsText,
+ )
+ }
+ }
+ }, (
+ areRequiredFieldsValid,
+ areRequiredFieldsEmpty,
+ isWallet,
+ sessionObj,
+ componentName,
+ iframeId,
+ ))
+}
diff --git a/src/Utilities/PaymentUtils.res b/src/Utilities/PaymentUtils.res
index 92096fef2..735ad4d57 100644
--- a/src/Utilities/PaymentUtils.res
+++ b/src/Utilities/PaymentUtils.res
@@ -7,6 +7,10 @@ let paymentListLookupNew = (
~isShowKlarnaOneClick,
~isKlarnaSDKFlow,
~paymentMethodListValue: PaymentMethodsRecord.paymentMethodList,
+ ~areAllApplePayRequiredFieldsPrefilled,
+ ~areAllGooglePayRequiredFieldsPrefilled,
+ ~isApplePayReady,
+ ~isGooglePayReady,
) => {
let pmList = list->PaymentMethodsRecord.buildFromPaymentList
let walletsList = []
@@ -29,6 +33,22 @@ let paymentListLookupNew = (
]
let otherPaymentList = []
+ if (
+ !paymentMethodListValue.collect_billing_details_from_wallets &&
+ !areAllApplePayRequiredFieldsPrefilled &&
+ isApplePayReady
+ ) {
+ walletToBeDisplayedInTabs->Array.push("apple_pay")
+ }
+
+ if (
+ !paymentMethodListValue.collect_billing_details_from_wallets &&
+ !areAllGooglePayRequiredFieldsPrefilled &&
+ isGooglePayReady
+ ) {
+ walletToBeDisplayedInTabs->Array.push("google_pay")
+ }
+
pmList->Array.forEach(item => {
if walletToBeDisplayedInTabs->Array.includes(item.paymentMethodName) {
otherPaymentList->Array.push(item.paymentMethodName)->ignore
@@ -303,6 +323,23 @@ let useGetPaymentMethodList = (~paymentOptions, ~paymentType, ~sessions) => {
let isKlarnaSDKFlow = getIsKlarnaSDKFlow(sessions)
+ let paymentMethodListValue = Recoil.useRecoilValueFromAtom(paymentMethodListValue)
+
+ let areAllApplePayRequiredFieldsPrefilled = useAreAllRequiredFieldsPrefilled(
+ ~paymentMethodListValue,
+ ~paymentMethod="wallet",
+ ~paymentMethodType="apple_pay",
+ )
+
+ let areAllGooglePayRequiredFieldsPrefilled = useAreAllRequiredFieldsPrefilled(
+ ~paymentMethodListValue,
+ ~paymentMethod="wallet",
+ ~paymentMethodType="google_pay",
+ )
+
+ let isApplePayReady = Recoil.useRecoilValueFromAtom(RecoilAtoms.isApplePayReady)
+ let isGooglePayReady = Recoil.useRecoilValueFromAtom(RecoilAtoms.isGooglePayReady)
+
React.useMemo(() => {
switch methodslist {
| Loaded(paymentlist) =>
@@ -316,6 +353,10 @@ let useGetPaymentMethodList = (~paymentOptions, ~paymentType, ~sessions) => {
~isShowKlarnaOneClick=optionAtomValue.wallets.klarna === Auto,
~isKlarnaSDKFlow,
~paymentMethodListValue=plist,
+ ~areAllApplePayRequiredFieldsPrefilled,
+ ~areAllGooglePayRequiredFieldsPrefilled,
+ ~isApplePayReady,
+ ~isGooglePayReady,
)
let klarnaPaymentMethodExperience = PaymentMethodsRecord.getPaymentExperienceTypeFromPML(
@@ -353,6 +394,10 @@ let useGetPaymentMethodList = (~paymentOptions, ~paymentType, ~sessions) => {
optionAtomValue.wallets.klarna,
paymentType,
isKlarnaSDKFlow,
+ areAllApplePayRequiredFieldsPrefilled,
+ areAllGooglePayRequiredFieldsPrefilled,
+ isApplePayReady,
+ isGooglePayReady,
))
}