diff --git a/src/CardUtils.res b/src/CardUtils.res
index f0400b087..203afe4e5 100644
--- a/src/CardUtils.res
+++ b/src/CardUtils.res
@@ -743,13 +743,31 @@ let getCardBrandInvalidError = (~cardBrand, ~localeString: LocaleStringTypes.loc
}
}
-let emitExpiryDate = formattedExpiry =>
- Utils.messageParentWindow([("expiryDate", formattedExpiry->JSON.Encode.string)])
+let emitExpiryDate = (formattedExpiry, ~subscriptionEvents) => {
+ if (
+ subscriptionEvents->Option.isNone ||
+ PaymentEventData.shouldEmitEvent(
+ ~subscribedEvents=subscriptionEvents->Option.getOr([]),
+ ~eventType=PaymentEventTypes.UnknownEvent,
+ )
+ ) {
+ Utils.messageParentWindow([("expiryDate", formattedExpiry->JSON.Encode.string)])
+ }
+}
-let emitIsFormReadyForSubmission = isFormReadyForSubmission =>
- Utils.messageParentWindow([
- ("isFormReadyForSubmission", isFormReadyForSubmission->JSON.Encode.bool),
- ])
+let emitIsFormReadyForSubmission = (isFormReadyForSubmission, ~subscriptionEvents) => {
+ if (
+ subscriptionEvents->Option.isNone ||
+ PaymentEventData.shouldEmitEvent(
+ ~subscribedEvents=subscriptionEvents->Option.getOr([]),
+ ~eventType=PaymentEventTypes.UnknownEvent,
+ )
+ ) {
+ Utils.messageParentWindow([
+ ("isFormReadyForSubmission", isFormReadyForSubmission->JSON.Encode.bool),
+ ])
+ }
+}
let getCardBin = cardNumber =>
cardNumber->CardValidations.clearSpaces->String.substring(~start=0, ~end=6)
diff --git a/src/Components/AccordionContainer.res b/src/Components/AccordionContainer.res
index ffcea383e..7ad67584e 100644
--- a/src/Components/AccordionContainer.res
+++ b/src/Components/AccordionContainer.res
@@ -77,6 +77,14 @@ let make = (
~cardProps,
~expiryProps,
)
+ SubscriptionEventHooks.usePaymentMethodStatus(
+ ~paymentMethodName=selectedOption,
+ ~paymentMethods=paymentMethodListValue.payment_methods,
+ ~isSavedPaymentMethod=false,
+ ~isOneClickWallet=false,
+ )
+
+ SubscriptionEventHooks.useBillingAddress()
let cardOptionDetails =
paymentOptions
diff --git a/src/Components/LoaderPaymentShimmer.res b/src/Components/LoaderPaymentShimmer.res
index 5e2097423..eb441ff01 100644
--- a/src/Components/LoaderPaymentShimmer.res
+++ b/src/Components/LoaderPaymentShimmer.res
@@ -2,6 +2,7 @@
let make = () => {
open RecoilAtoms
let selectedOption = Recoil.useRecoilValueFromAtom(selectedOptionAtom)
- UtilityHooks.useHandlePostMessages(~complete=false, ~empty=false, ~paymentType=selectedOption)
+ SubscriptionEventHooks.useFormStatus(~empty=true, ~complete=false)
+ UtilityHooks.useHandlePostMessages(~complete=false, ~empty=true, ~paymentType=selectedOption)
}
diff --git a/src/Components/SavedCardItem.res b/src/Components/SavedCardItem.res
index f03e9ee86..492aa9796 100644
--- a/src/Components/SavedCardItem.res
+++ b/src/Components/SavedCardItem.res
@@ -99,7 +99,7 @@ let make = (
| None => "debit"
}
let {country, state, pinCode} = PaymentUtils.useNonPiiAddressData()
-
+ let options = Recoil.useRecoilValueFromAtom(RecoilAtoms.optionAtom)
React.useEffect(() => {
open CardUtils
@@ -111,7 +111,7 @@ let make = (
// * Sending card expiry to handle cases where the card expires before the use date.
`${expiryMonth}${String.substring(~start=2, ~end=4, expiryYear)}`
->CardValidations.formatCardExpiryNumber
- ->emitExpiryDate
+ ->emitExpiryDate(~subscriptionEvents=options.subscriptionEvents)
PaymentUtils.emitPaymentMethodInfo(
~paymentMethod=paymentItem.paymentMethod,
@@ -125,13 +125,30 @@ let make = (
~cardLast4,
~cardBin,
~isSavedPaymentMethod=true,
+ ~subscriptionEvents=options.subscriptionEvents,
+ )
+ SubscriptionEventHooks.emitPaymentMethodStatus(
+ ~subscriptionEvents=options.subscriptionEvents,
+ ~paymentMethod=paymentItem.paymentMethod,
+ ~paymentMethodType,
+ ~isSavedPaymentMethod=true,
+ ~isOneClickWallet=false,
+ )
+ SubscriptionEventHooks.emitBillingAddress(
+ ~subscriptionEvents=options.subscriptionEvents,
+ ~country,
+ ~state,
+ ~postalCode=pinCode,
)
}
None
}, (isActive, paymentItem, country, state, pinCode))
React.useEffect(() => {
- CardUtils.emitIsFormReadyForSubmission(isCVCValid->Option.getOr(false))
+ CardUtils.emitIsFormReadyForSubmission(
+ isCVCValid->Option.getOr(false),
+ ~subscriptionEvents=options.subscriptionEvents,
+ )
None
}, [isCVCValid])
diff --git a/src/Components/SavedMethods.res b/src/Components/SavedMethods.res
index 11b3d1940..532194e2e 100644
--- a/src/Components/SavedMethods.res
+++ b/src/Components/SavedMethods.res
@@ -78,6 +78,8 @@ let make = (
let (selectedInstallmentPlan, setSelectedInstallmentPlan) = React.useState(_ => None)
let (showInstallments, setShowInstallments) = React.useState(_ => false)
+ let options = Recoil.useRecoilValueFromAtom(RecoilAtoms.optionAtom)
+
let shouldShowClickToPaySection =
clickToPayConfig.isReady == Some(true) &&
(!groupSavedMethodsWithPaymentMethods || selectedOption == "card")
@@ -153,8 +155,30 @@ let make = (
let paymentMethodType =
customerMethod.paymentMethodType->Option.getOr(customerMethod.paymentMethod)
+ SubscriptionEventHooks.useFormStatus(~empty, ~complete)
+ UtilityHooks.useHandlePostMessages(
+ ~complete,
+ ~empty,
+ ~paymentType=paymentMethodType,
+ ~savedMethod=true,
+ )
- useHandlePostMessages(~complete, ~empty, ~paymentType=paymentMethodType, ~savedMethod=true)
+ // Emit card info for saved card methods
+ React.useEffect(() => {
+ if isCardPaymentMethod && !isUnknownPaymentMethod {
+ let card = customerMethod.card
+ let cardInfo = PaymentEventData.buildCardInfoFromSavedCard(
+ ~bin=card.cardBin,
+ ~last4=card.last4Digits,
+ ~brand=card.scheme->Option.getOr(""),
+ ~expiryMonth=card.expiryMonth,
+ ~expiryYear=card.expiryYear,
+ ~isCvcComplete=complete,
+ )
+ SubscriptionEventHooks.emitCardInfo(~subscriptionEvents=options.subscriptionEvents, ~cardInfo)
+ }
+ None
+ }, (customerMethod, isCardPaymentMethod, isUnknownPaymentMethod, complete))
GooglePayHelpers.useHandleGooglePayResponse(~connectors=[], ~intent, ~isSavedMethodsFlow=true)
diff --git a/src/Hooks/CommonCardProps.res b/src/Hooks/CommonCardProps.res
index a342dffc0..6d2d1c0a9 100644
--- a/src/Hooks/CommonCardProps.res
+++ b/src/Hooks/CommonCardProps.res
@@ -139,13 +139,15 @@ let useCardForm = (~logger, ~paymentType) => {
}
}
+ let options = Recoil.useRecoilValueFromAtom(RecoilAtoms.optionAtom)
+
let changeCardExpiry = ev => {
let val = ReactEvent.Form.target(ev)["value"]
logInputChangeInfo("cardExpiry", logger)
let formattedExpiry = val->CardValidations.formatCardExpiryNumber
if isExipryValid(formattedExpiry) {
handleInputFocus(~currentRef=expiryRef, ~destinationRef=cvcRef)
- emitExpiryDate(formattedExpiry)
+ CardUtils.emitExpiryDate(formattedExpiry, ~subscriptionEvents=options.subscriptionEvents)
}
setExpiryValid(formattedExpiry, setIsExpiryValid)
setCardExpiry(_ => formattedExpiry)
diff --git a/src/Hooks/SubscriptionEventHooks.res b/src/Hooks/SubscriptionEventHooks.res
new file mode 100644
index 000000000..be3b9004f
--- /dev/null
+++ b/src/Hooks/SubscriptionEventHooks.res
@@ -0,0 +1,129 @@
+open SubscriptionEventTypes
+open PaymentEventData
+open PaymentEventTypes
+
+let emitCardInfo = (~subscriptionEvents, ~cardInfo: cardInfo) => {
+ if (
+ subscriptionEvents->Option.isNone ||
+ shouldEmitEvent(
+ ~subscribedEvents=subscriptionEvents->Option.getOr([]),
+ ~eventType=PaymentMethodInfoCard,
+ )
+ ) {
+ let payload = createCardInfoPayload(cardInfo)
+ Utils.messageParentWindow(payload)
+ }
+}
+
+let emitPaymentMethodStatus = (
+ ~subscriptionEvents,
+ ~paymentMethod,
+ ~paymentMethodType,
+ ~isSavedPaymentMethod,
+ ~isOneClickWallet=false,
+) => {
+ if (
+ subscriptionEvents->Option.isNone ||
+ shouldEmitEvent(
+ ~subscribedEvents=subscriptionEvents->Option.getOr([]),
+ ~eventType=PaymentMethodStatus,
+ )
+ ) {
+ let payload = createPaymentMethodStatusPayload(
+ ~paymentMethod,
+ ~paymentMethodType,
+ ~isSavedPaymentMethod,
+ ~isOneClickWallet,
+ )
+ Utils.messageParentWindow(payload)
+ }
+}
+
+let emitBillingAddress = (~subscriptionEvents, ~country, ~state, ~postalCode) => {
+ if (
+ subscriptionEvents->Option.isNone ||
+ shouldEmitEvent(
+ ~subscribedEvents=subscriptionEvents->Option.getOr([]),
+ ~eventType=PaymentMethodInfoBillingAddress,
+ )
+ ) {
+ let payload = createBillingAddressPayload(~country, ~state, ~postalCode)
+ Utils.messageParentWindow(payload)
+ }
+}
+
+let useFormStatus = (~empty: bool, ~complete: bool, ~isOneClickWallet: bool=false) => {
+ let options = Recoil.useRecoilValueFromAtom(RecoilAtoms.optionAtom)
+ let subscriptionEvents = options.subscriptionEvents
+
+ React.useEffect(() => {
+ if !isOneClickWallet {
+ let formStatusValue = computeFormStatus(~isComplete=complete, ~isEmpty=empty)
+ if (
+ subscriptionEvents->Option.isNone ||
+ shouldEmitEvent(
+ ~subscribedEvents=subscriptionEvents->Option.getOr([]),
+ ~eventType=FormStatus,
+ )
+ ) {
+ let payload = SubscriptionEventTypes.createFormStatusPayload(~status=formStatusValue)
+ Utils.messageParentWindow(payload)
+ }
+ }
+ None
+ }, (empty, complete, isOneClickWallet, subscriptionEvents))
+}
+
+let useBillingAddress = () => {
+ let country = Recoil.useRecoilValueFromAtom(RecoilAtoms.userCountry)
+ let state = Recoil.useRecoilValueFromAtom(RecoilAtoms.userAddressState).value
+ let pinCode = Recoil.useRecoilValueFromAtom(RecoilAtoms.userAddressPincode).value
+ let options = Recoil.useRecoilValueFromAtom(RecoilAtoms.optionAtom)
+
+ React.useEffect(() => {
+ emitBillingAddress(
+ ~subscriptionEvents=options.subscriptionEvents,
+ ~country,
+ ~state,
+ ~postalCode=pinCode,
+ )
+
+ None
+ }, (country, state, pinCode, options.subscriptionEvents))
+}
+
+let usePaymentMethodStatus = (
+ ~paymentMethodName: string,
+ ~paymentMethods: array,
+ ~isSavedPaymentMethod: bool,
+ ~isOneClickWallet: bool,
+) => {
+ let loggerState = Recoil.useRecoilValueFromAtom(RecoilAtoms.loggerAtom)
+ let options = Recoil.useRecoilValueFromAtom(RecoilAtoms.optionAtom)
+
+ React.useEffect(() => {
+ switch PaymentUtils.getPaymentMethodAndType(
+ ~paymentMethodName,
+ ~paymentMethods,
+ ~logger=loggerState,
+ ) {
+ | Some((paymentMethod, paymentMethodType)) =>
+ emitPaymentMethodStatus(
+ ~subscriptionEvents=options.subscriptionEvents,
+ ~paymentMethod,
+ ~paymentMethodType,
+ ~isSavedPaymentMethod,
+ ~isOneClickWallet,
+ )
+ | None => ()
+ }
+
+ None
+ }, (
+ paymentMethodName,
+ paymentMethods,
+ isSavedPaymentMethod,
+ isOneClickWallet,
+ options.subscriptionEvents,
+ ))
+}
diff --git a/src/Hooks/UtilityHooks.res b/src/Hooks/UtilityHooks.res
index b0a0faed8..5066b5431 100644
--- a/src/Hooks/UtilityHooks.res
+++ b/src/Hooks/UtilityHooks.res
@@ -25,11 +25,19 @@ let useHandlePostMessages = (~complete, ~empty, ~paymentType, ~savedMethod=false
open RecoilAtoms
let loggerState = Recoil.useRecoilValueFromAtom(loggerAtom)
+ let options = Recoil.useRecoilValueFromAtom(optionAtom)
React.useEffect(() => {
- Utils.handlePostMessageEvents(~complete, ~empty, ~paymentType, ~loggerState, ~savedMethod)
+ Utils.handlePostMessageEvents(
+ ~complete,
+ ~empty,
+ ~paymentType,
+ ~loggerState,
+ ~savedMethod,
+ ~subscriptionEvents=options.subscriptionEvents,
+ )
None
- }, (complete, empty, paymentType))
+ }, (complete, empty, paymentType, options.subscriptionEvents))
}
let useIsCustomerAcceptanceRequired = (
diff --git a/src/Payment.res b/src/Payment.res
index d31e7e61d..8527d69bb 100644
--- a/src/Payment.res
+++ b/src/Payment.res
@@ -12,6 +12,7 @@ let setUserError = message => {
@react.component
let make = (~paymentMode, ~integrateError, ~logger) => {
let {localeString} = Recoil.useRecoilValueFromAtom(configAtom)
+ let options = Recoil.useRecoilValueFromAtom(optionAtom)
let {iframeId} = Recoil.useRecoilValueFromAtom(keys)
let isManualRetryEnabled = Recoil.useRecoilValueFromAtom(isManualRetryEnabled)
let areRequiredFieldsValid = Recoil.useRecoilValueFromAtom(areRequiredFieldsValid)
@@ -39,6 +40,7 @@ let make = (~paymentMode, ~integrateError, ~logger) => {
| (Some(cardValid), Some(expiryValid), Some(cvcValid)) =>
CardUtils.emitIsFormReadyForSubmission(
cardValid && expiryValid && cvcValid && areRequiredFieldsValid,
+ ~subscriptionEvents=options.subscriptionEvents,
)
| _ => ()
}
diff --git a/src/PaymentOptions.res b/src/PaymentOptions.res
index ef8b3129b..fbd6e6869 100644
--- a/src/PaymentOptions.res
+++ b/src/PaymentOptions.res
@@ -122,6 +122,14 @@ let make = (
~expiryProps,
)
+ SubscriptionEventHooks.useBillingAddress()
+ SubscriptionEventHooks.usePaymentMethodStatus(
+ ~paymentMethodName=selectedPaymentOption.paymentMethodName,
+ ~paymentMethods=paymentMethodListValue.payment_methods,
+ ~isSavedPaymentMethod=false,
+ ~isOneClickWallet=false,
+ )
+
let displayIcon = ele => {
ele
}
diff --git a/src/Payments/ACHBankDebit.res b/src/Payments/ACHBankDebit.res
index bc14d311d..122c83eff 100644
--- a/src/Payments/ACHBankDebit.res
+++ b/src/Payments/ACHBankDebit.res
@@ -1,6 +1,5 @@
open RecoilAtoms
open Utils
-open PaymentModeType
@react.component
let make = () => {
@@ -61,7 +60,9 @@ let make = () => {
fullName.value != "" &&
email.isValid->Option.getOr(false) &&
modalData->Option.isSome
- let empty = email.value == "" || fullName.value != ""
+ let empty = email.value == "" || fullName.value == ""
+
+ SubscriptionEventHooks.useFormStatus(~complete, ~empty)
UtilityHooks.useHandlePostMessages(~complete, ~empty, ~paymentType="ach_bank_debit")
diff --git a/src/Payments/ACHBankTransfer.res b/src/Payments/ACHBankTransfer.res
index aa82bbcd0..32dff8de5 100644
--- a/src/Payments/ACHBankTransfer.res
+++ b/src/Payments/ACHBankTransfer.res
@@ -16,7 +16,8 @@ let make = () => {
let complete = email.value != "" && email.isValid->Option.getOr(false)
let empty = email.value == ""
- UtilityHooks.useHandlePostMessages(~complete, ~empty, ~paymentType="bank_transfer")
+ SubscriptionEventHooks.useFormStatus(~empty, ~complete)
+ UtilityHooks.useHandlePostMessages(~complete, ~empty, ~paymentType="ach_bank_transfer")
React.useEffect(() => {
setComplete(_ => complete)
diff --git a/src/Payments/ApplePay.res b/src/Payments/ApplePay.res
index bb4a4b71e..38ea3ec04 100644
--- a/src/Payments/ApplePay.res
+++ b/src/Payments/ApplePay.res
@@ -36,6 +36,12 @@ let make = (~sessionObj: option, ~walletOptions) => {
| _ => 48
}
+ SubscriptionEventHooks.useFormStatus(
+ ~empty=areRequiredFieldsEmpty,
+ ~complete=areRequiredFieldsValid,
+ ~isOneClickWallet=isWallet,
+ )
+
UtilityHooks.useHandlePostMessages(
~complete=areRequiredFieldsValid,
~empty=areRequiredFieldsEmpty,
@@ -236,6 +242,20 @@ let make = (~sessionObj: option, ~walletOptions) => {
~country,
~state,
~pinCode,
+ ~subscriptionEvents=options.subscriptionEvents,
+ )
+ SubscriptionEventHooks.emitPaymentMethodStatus(
+ ~subscriptionEvents=options.subscriptionEvents,
+ ~paymentMethod="wallet",
+ ~paymentMethodType="apple_pay",
+ ~isSavedPaymentMethod=false,
+ ~isOneClickWallet=isWallet,
+ )
+ SubscriptionEventHooks.emitBillingAddress(
+ ~subscriptionEvents=options.subscriptionEvents,
+ ~country,
+ ~state,
+ ~postalCode=pinCode,
)
setApplePayClicked(_ => true)
makeOneClickHandlerPromise(sdkHandleIsThere)
diff --git a/src/Payments/BacsBankDebit.res b/src/Payments/BacsBankDebit.res
index 1d97cb76d..423b77dc1 100644
--- a/src/Payments/BacsBankDebit.res
+++ b/src/Payments/BacsBankDebit.res
@@ -77,6 +77,7 @@ let make = () => {
country.value == "" ||
state.value == ""
+ SubscriptionEventHooks.useFormStatus(~empty, ~complete)
UtilityHooks.useHandlePostMessages(~complete, ~empty, ~paymentType="bacs_bank_debit")
React.useEffect(() => {
diff --git a/src/Payments/BacsBankTransfer.res b/src/Payments/BacsBankTransfer.res
index 08969b570..47a4720e2 100644
--- a/src/Payments/BacsBankTransfer.res
+++ b/src/Payments/BacsBankTransfer.res
@@ -20,7 +20,9 @@ let default = () => {
let paymentMethodType = "bacs"
let paymentMethod = "bank_transfer"
- UtilityHooks.useHandlePostMessages(~complete, ~empty, ~paymentType=paymentMethod)
+ SubscriptionEventHooks.useFormStatus(~empty, ~complete)
+
+ UtilityHooks.useHandlePostMessages(~complete, ~empty, ~paymentType=paymentMethodType)
React.useEffect(() => {
setComplete(_ => complete)
diff --git a/src/Payments/BecsBankDebit.res b/src/Payments/BecsBankDebit.res
index 7ce15d5a2..ad3c76fb8 100644
--- a/src/Payments/BecsBankDebit.res
+++ b/src/Payments/BecsBankDebit.res
@@ -42,6 +42,8 @@ let make = () => {
| None => true
}
+ SubscriptionEventHooks.useFormStatus(~empty, ~complete)
+
UtilityHooks.useHandlePostMessages(~complete, ~empty, ~paymentType="becs_bank_debit")
React.useEffect(() => {
diff --git a/src/Payments/Boleto.res b/src/Payments/Boleto.res
index 24ef3e1ea..42956eb9f 100644
--- a/src/Payments/Boleto.res
+++ b/src/Payments/Boleto.res
@@ -43,6 +43,8 @@ let make = () => {
)
}, [socialSecurityNumber])
+ SubscriptionEventHooks.useFormStatus(~empty, ~complete)
+
UtilityHooks.useHandlePostMessages(~complete, ~empty, ~paymentType="boleto")
React.useEffect(() => {
diff --git a/src/Payments/CardPayment.res b/src/Payments/CardPayment.res
index 481241ac7..94aa30b76 100644
--- a/src/Payments/CardPayment.res
+++ b/src/Payments/CardPayment.res
@@ -136,14 +136,28 @@ let make = (
isInstallmentValid
let empty = cardNumber == "" || cardExpiry == "" || cvcNumber == ""
+
+ SubscriptionEventHooks.useFormStatus(~empty, ~complete=complete && areRequiredFieldsValid)
+ UtilityHooks.useHandlePostMessages(~complete, ~empty, ~paymentType="card")
+
+ React.useEffect(() => {
+ let cardInfo = PaymentEventData.buildCardInfo(
+ ~cardNumber,
+ ~expiry=cardExpiry,
+ ~cvc=cvcNumber,
+ ~brand=cardBrand,
+ )
+
+ SubscriptionEventHooks.emitCardInfo(~subscriptionEvents=options.subscriptionEvents, ~cardInfo)
+ None
+ }, (cardNumber, cardExpiry, cvcNumber, cardBrand))
+
React.useEffect(() => {
setComplete(_ => complete)
setShowPaymentMethodsScreen(_ => true)
None
}, [complete])
- useHandlePostMessages(~complete=complete && areRequiredFieldsValid, ~empty, ~paymentType="card")
-
let isGuestCustomer = useIsGuestCustomer()
let isCvcValidValue = CardUtils.getBoolOptionVal(isCVCValid)
let (cardEmpty, cardComplete, cardInvalid) = CardUtils.useCardDetails(
diff --git a/src/Payments/GPay.res b/src/Payments/GPay.res
index 2c54d529d..610ed203a 100644
--- a/src/Payments/GPay.res
+++ b/src/Payments/GPay.res
@@ -41,7 +41,6 @@ let make = (
let (requiredFieldsBody, setRequiredFieldsBody) = React.useState(_ => Dict.make())
let isWallet = walletOptions->Array.includes("google_pay")
let isTestMode = Recoil.useRecoilValueFromAtom(RecoilAtoms.isTestMode)
-
UtilityHooks.useHandlePostMessages(
~complete=areRequiredFieldsValid,
~empty=areRequiredFieldsEmpty,
@@ -114,6 +113,20 @@ let make = (
~country,
~state,
~pinCode,
+ ~subscriptionEvents=options.subscriptionEvents,
+ )
+ SubscriptionEventHooks.emitPaymentMethodStatus(
+ ~subscriptionEvents=options.subscriptionEvents,
+ ~paymentMethod="wallet",
+ ~paymentMethodType="google_pay",
+ ~isSavedPaymentMethod=false,
+ ~isOneClickWallet=isWallet,
+ )
+ SubscriptionEventHooks.emitBillingAddress(
+ ~subscriptionEvents=options.subscriptionEvents,
+ ~country,
+ ~state,
+ ~postalCode=pinCode,
)
makeOneClickHandlerPromise(isSDKHandleClick)
->then(result => {
diff --git a/src/Payments/InstantBankTransfer.res b/src/Payments/InstantBankTransfer.res
index f7da43909..948cae1b4 100644
--- a/src/Payments/InstantBankTransfer.res
+++ b/src/Payments/InstantBankTransfer.res
@@ -17,11 +17,11 @@ let make = () => {
let paymentMethodType = "instant_bank_transfer"
let paymentMethod = "bank_transfer"
- UtilityHooks.useHandlePostMessages(
- ~complete=areRequiredFieldsValid && !areRequiredFieldsEmpty,
- ~empty=areRequiredFieldsEmpty,
- ~paymentType=paymentMethod,
- )
+ let complete = areRequiredFieldsValid && !areRequiredFieldsEmpty
+ let empty = areRequiredFieldsEmpty
+ SubscriptionEventHooks.useFormStatus(~empty, ~complete)
+
+ UtilityHooks.useHandlePostMessages(~complete, ~empty, ~paymentType=paymentMethod)
let submitCallback = React.useCallback((ev: Window.event) => {
let json = ev.data->safeParse
diff --git a/src/Payments/InstantBankTransferFinland.res b/src/Payments/InstantBankTransferFinland.res
index 10f1985cb..3ae9ffbed 100644
--- a/src/Payments/InstantBankTransferFinland.res
+++ b/src/Payments/InstantBankTransferFinland.res
@@ -17,11 +17,11 @@ let make = () => {
let paymentMethodType = "instant_bank_transfer_finland"
let paymentMethod = "bank_transfer"
- UtilityHooks.useHandlePostMessages(
- ~complete=areRequiredFieldsValid && !areRequiredFieldsEmpty,
- ~empty=areRequiredFieldsEmpty,
- ~paymentType=paymentMethod,
- )
+ let complete = areRequiredFieldsValid && !areRequiredFieldsEmpty
+ let empty = areRequiredFieldsEmpty
+ SubscriptionEventHooks.useFormStatus(~empty, ~complete)
+
+ UtilityHooks.useHandlePostMessages(~complete, ~empty, ~paymentType=paymentMethod)
let submitCallback = React.useCallback((ev: Window.event) => {
let json = ev.data->safeParse
diff --git a/src/Payments/InstantBankTransferPoland.res b/src/Payments/InstantBankTransferPoland.res
index 11367b8f4..40216350e 100644
--- a/src/Payments/InstantBankTransferPoland.res
+++ b/src/Payments/InstantBankTransferPoland.res
@@ -17,11 +17,11 @@ let make = () => {
let paymentMethodType = "instant_bank_transfer_poland"
let paymentMethod = "bank_transfer"
- UtilityHooks.useHandlePostMessages(
- ~complete=areRequiredFieldsValid && !areRequiredFieldsEmpty,
- ~empty=areRequiredFieldsEmpty,
- ~paymentType=paymentMethod,
- )
+ let complete = areRequiredFieldsValid && !areRequiredFieldsEmpty
+ let empty = areRequiredFieldsEmpty
+ SubscriptionEventHooks.useFormStatus(~empty, ~complete)
+
+ UtilityHooks.useHandlePostMessages(~complete, ~empty, ~paymentType=paymentMethod)
let submitCallback = React.useCallback((ev: Window.event) => {
let json = ev.data->safeParse
diff --git a/src/Payments/KlarnaCheckout.res b/src/Payments/KlarnaCheckout.res
index 972b225c3..f764bf9af 100644
--- a/src/Payments/KlarnaCheckout.res
+++ b/src/Payments/KlarnaCheckout.res
@@ -22,6 +22,18 @@ let make = () => {
let (buttonColor, textColor) =
options.wallets.style.theme == Light ? ("#0070ba", "#ffffff") : ("#0b051d", "#000000")
+ SubscriptionEventHooks.useFormStatus(
+ ~empty=!klarnaClicked,
+ ~complete=klarnaClicked,
+ ~isOneClickWallet=true,
+ )
+
+ UtilityHooks.useHandlePostMessages(
+ ~complete=klarnaClicked,
+ ~empty=!klarnaClicked,
+ ~paymentType="klarna_checkout",
+ )
+
let onKlarnaClick = async _ev => {
try {
if isTestMode {
diff --git a/src/Payments/KlarnaSDK.res b/src/Payments/KlarnaSDK.res
index bace399b0..9fcefb6e8 100644
--- a/src/Payments/KlarnaSDK.res
+++ b/src/Payments/KlarnaSDK.res
@@ -41,6 +41,12 @@ let make = (~sessionObj: SessionsType.token) => {
~paymentMethodType="klarna",
)
+ SubscriptionEventHooks.useFormStatus(
+ ~complete=isCompleted,
+ ~empty=!isCompleted,
+ ~isOneClickWallet=true,
+ )
+
UtilityHooks.useHandlePostMessages(
~complete=isCompleted,
~empty=!isCompleted,
@@ -82,6 +88,20 @@ let make = (~sessionObj: SessionsType.token) => {
~country,
~state,
~pinCode,
+ ~subscriptionEvents=options.subscriptionEvents,
+ )
+ SubscriptionEventHooks.emitPaymentMethodStatus(
+ ~subscriptionEvents=options.subscriptionEvents,
+ ~paymentMethod="wallet",
+ ~paymentMethodType="klarna",
+ ~isSavedPaymentMethod=false,
+ ~isOneClickWallet=true,
+ )
+ SubscriptionEventHooks.emitBillingAddress(
+ ~subscriptionEvents=options.subscriptionEvents,
+ ~country,
+ ~state,
+ ~postalCode=pinCode,
)
makeOneClickHandlerPromise(sdkHandleIsThere)->then(
result => {
diff --git a/src/Payments/PayPal.res b/src/Payments/PayPal.res
index f055621ac..ab9cd1c98 100644
--- a/src/Payments/PayPal.res
+++ b/src/Payments/PayPal.res
@@ -42,11 +42,13 @@ let make = (~walletOptions) => {
let isManualRetryEnabled = Recoil.useRecoilValueFromAtom(RecoilAtoms.isManualRetryEnabled)
let intent = PaymentHelpers.usePaymentIntent(Some(loggerState), Paypal)
- UtilityHooks.useHandlePostMessages(
- ~complete=paypalClicked,
- ~empty=!paypalClicked,
- ~paymentType=paymentMethodType,
- )
+
+ let complete = paypalClicked
+ let empty = !paypalClicked
+ SubscriptionEventHooks.useFormStatus(~empty, ~complete, ~isOneClickWallet=isWallet)
+
+ UtilityHooks.useHandlePostMessages(~complete, ~empty, ~paymentType=paymentMethodType)
+
let onPaypalClick = _ev => {
if isTestMode {
Console.warn("PayPal button clicked in test mode - interaction disabled")
@@ -67,6 +69,20 @@ let make = (~walletOptions) => {
~country,
~state,
~pinCode,
+ ~subscriptionEvents=options.subscriptionEvents,
+ )
+ SubscriptionEventHooks.emitPaymentMethodStatus(
+ ~subscriptionEvents=options.subscriptionEvents,
+ ~paymentMethod,
+ ~paymentMethodType,
+ ~isSavedPaymentMethod=false,
+ ~isOneClickWallet=isWallet,
+ )
+ SubscriptionEventHooks.emitBillingAddress(
+ ~subscriptionEvents=options.subscriptionEvents,
+ ~country,
+ ~state,
+ ~postalCode=pinCode,
)
setPaypalClicked(_ => true)
open Promise
diff --git a/src/Payments/PaymentMethodsWrapper.res b/src/Payments/PaymentMethodsWrapper.res
index ad0bfab84..dd4d36ac3 100644
--- a/src/Payments/PaymentMethodsWrapper.res
+++ b/src/Payments/PaymentMethodsWrapper.res
@@ -49,6 +49,8 @@ let make = (~paymentMethodName: string) => {
let empty = areRequiredFieldsEmpty
+ SubscriptionEventHooks.useFormStatus(~empty, ~complete=areRequiredFieldsValid)
+
UtilityHooks.useHandlePostMessages(
~complete=areRequiredFieldsValid,
~empty,
diff --git a/src/Payments/PaypalSDK.res b/src/Payments/PaypalSDK.res
index a09f708cd..a93961617 100644
--- a/src/Payments/PaypalSDK.res
+++ b/src/Payments/PaypalSDK.res
@@ -64,6 +64,11 @@ let make = (~sessionObj: SessionsType.token) => {
~paymentMethod="wallet",
~paymentMethodType="paypal",
)
+ SubscriptionEventHooks.useFormStatus(
+ ~empty=!isCompleted,
+ ~complete=isCompleted,
+ ~isOneClickWallet=true,
+ )
UtilityHooks.useHandlePostMessages(
~complete=isCompleted,
@@ -110,6 +115,7 @@ let make = (~sessionObj: SessionsType.token) => {
~isTestMode,
~nonPiiAdderessData,
~sdkAuthorization,
+ ~subscriptionEvents=options.subscriptionEvents,
)
})
Window.body->Window.appendChild(paypalScript)
diff --git a/src/Payments/PaypalSDKHelpers.res b/src/Payments/PaypalSDKHelpers.res
index 1d679dcc7..eafada960 100644
--- a/src/Payments/PaypalSDKHelpers.res
+++ b/src/Payments/PaypalSDKHelpers.res
@@ -28,6 +28,7 @@ let loadPaypalSDK = (
~isTestMode=false,
~nonPiiAdderessData: PaymentUtils.nonPiiAdderessData,
~sdkAuthorization,
+ ~subscriptionEvents: option>,
) => {
open Promise
@@ -70,6 +71,20 @@ let loadPaypalSDK = (
~country,
~state,
~pinCode,
+ ~subscriptionEvents,
+ )
+ SubscriptionEventHooks.emitPaymentMethodStatus(
+ ~subscriptionEvents,
+ ~paymentMethod="wallet",
+ ~paymentMethodType="paypal",
+ ~isSavedPaymentMethod=false,
+ ~isOneClickWallet=true,
+ )
+ SubscriptionEventHooks.emitBillingAddress(
+ ~subscriptionEvents,
+ ~country,
+ ~state,
+ ~postalCode=pinCode,
)
makeOneClickHandlerPromise(sdkHandleIsThere)->then(result => {
let result = result->JSON.Decode.bool->Option.getOr(false)
diff --git a/src/Payments/PazeButton.res b/src/Payments/PazeButton.res
index dbed84cea..27454cea0 100644
--- a/src/Payments/PazeButton.res
+++ b/src/Payments/PazeButton.res
@@ -18,6 +18,13 @@ let make = (~token: SessionsType.token) => {
let (showLoader, setShowLoader) = React.useState(() => false)
let isTestMode = Recoil.useRecoilValueFromAtom(RecoilAtoms.isTestMode)
let {country, state, pinCode} = PaymentUtils.useNonPiiAddressData()
+ SubscriptionEventHooks.useFormStatus(
+ ~empty=!showLoader,
+ ~complete=showLoader,
+ ~isOneClickWallet=true,
+ )
+
+ UtilityHooks.useHandlePostMessages(~complete=showLoader, ~empty=!showLoader, ~paymentType="paze")
let onClick = _ => {
if isTestMode {
@@ -39,6 +46,20 @@ let make = (~token: SessionsType.token) => {
~country,
~state,
~pinCode,
+ ~subscriptionEvents=options.subscriptionEvents,
+ )
+ SubscriptionEventHooks.emitPaymentMethodStatus(
+ ~subscriptionEvents=options.subscriptionEvents,
+ ~paymentMethod="wallet",
+ ~paymentMethodType="paze",
+ ~isSavedPaymentMethod=false,
+ ~isOneClickWallet=true,
+ )
+ SubscriptionEventHooks.emitBillingAddress(
+ ~subscriptionEvents=options.subscriptionEvents,
+ ~country,
+ ~state,
+ ~postalCode=pinCode,
)
setShowLoader(_ => true)
let metadata =
diff --git a/src/Payments/SamsungPayComponent.res b/src/Payments/SamsungPayComponent.res
index 40dd17242..4cd3c1143 100644
--- a/src/Payments/SamsungPayComponent.res
+++ b/src/Payments/SamsungPayComponent.res
@@ -17,14 +17,18 @@ let make = (~sessionObj: option, ~walletOptions) => {
let intent = PaymentHelpers.usePaymentIntent(Some(loggerState), Samsungpay)
let isTestMode = Recoil.useRecoilValueFromAtom(RecoilAtoms.isTestMode)
let {country, state, pinCode} = PaymentUtils.useNonPiiAddressData()
+ let areRequiredFieldsValid = Recoil.useRecoilValueFromAtom(areRequiredFieldsValid)
+ let areRequiredFieldsEmpty = Recoil.useRecoilValueFromAtom(areRequiredFieldsEmpty)
let (_, _, _, _, heightType) = options.wallets.style.height
let height = switch heightType {
| SamsungPay(val) => val
| _ => 48
}
-
+ let empty = areRequiredFieldsEmpty
+ let complete = areRequiredFieldsValid && !areRequiredFieldsEmpty
SamsungPayHelpers.useHandleSamsungPayResponse(~intent, ~isWallet)
+ SubscriptionEventHooks.useFormStatus(~complete, ~empty, ~isOneClickWallet=true)
let getSamsungPaymentsClient = _ =>
SamsungPayType.samsung({
@@ -51,6 +55,20 @@ let make = (~sessionObj: option, ~walletOptions) => {
~country,
~state,
~pinCode,
+ ~subscriptionEvents=options.subscriptionEvents,
+ )
+ SubscriptionEventHooks.emitPaymentMethodStatus(
+ ~subscriptionEvents=options.subscriptionEvents,
+ ~paymentMethod="wallet",
+ ~paymentMethodType="samsung_pay",
+ ~isSavedPaymentMethod=false,
+ ~isOneClickWallet=true,
+ )
+ SubscriptionEventHooks.emitBillingAddress(
+ ~subscriptionEvents=options.subscriptionEvents,
+ ~country,
+ ~state,
+ ~postalCode=pinCode,
)
SamsungPayHelpers.handleSamsungPayClicked(
~sessionObj=sessionObj->Option.getOr(JSON.Encode.null)->getDictFromJson,
diff --git a/src/Payments/SepaBankDebit.res b/src/Payments/SepaBankDebit.res
index 4b99b164a..b90422c02 100644
--- a/src/Payments/SepaBankDebit.res
+++ b/src/Payments/SepaBankDebit.res
@@ -26,11 +26,11 @@ let make = () => {
let isVerifyPMAuthConnectorConfigured =
displaySavedPaymentMethods && pmAuthMapper->Dict.get(paymentMethodType)->Option.isSome
- UtilityHooks.useHandlePostMessages(
- ~complete=areRequiredFieldsValid,
- ~empty=areRequiredFieldsEmpty,
- ~paymentType="sepa_bank_debit",
- )
+ let empty = areRequiredFieldsEmpty
+ let complete = areRequiredFieldsValid
+ SubscriptionEventHooks.useFormStatus(~empty, ~complete)
+
+ UtilityHooks.useHandlePostMessages(~complete, ~empty, ~paymentType="sepa_bank_debit")
let submitCallback = React.useCallback((ev: Window.event) => {
let json = ev.data->safeParse
diff --git a/src/Payments/SepaBankTransfer.res b/src/Payments/SepaBankTransfer.res
index b98e4eadf..2881c4f3f 100644
--- a/src/Payments/SepaBankTransfer.res
+++ b/src/Payments/SepaBankTransfer.res
@@ -13,11 +13,11 @@ let make = () => {
let (requiredFieldsBody, setRequiredFieldsBody) = React.useState(_ => Dict.make())
- UtilityHooks.useHandlePostMessages(
- ~complete=areRequiredFieldsValid && !areRequiredFieldsEmpty,
- ~empty=areRequiredFieldsEmpty,
- ~paymentType="bank_transfer",
- )
+ let complete = areRequiredFieldsValid && !areRequiredFieldsEmpty
+ let empty = areRequiredFieldsEmpty
+ SubscriptionEventHooks.useFormStatus(~empty, ~complete)
+
+ UtilityHooks.useHandlePostMessages(~complete, ~empty, ~paymentType="sepa_bank_transfer")
let submitCallback = React.useCallback((ev: Window.event) => {
let json = ev.data->safeParse
diff --git a/src/Types/PaymentType.res b/src/Types/PaymentType.res
index 4dc2afd0c..b3c9afea0 100644
--- a/src/Types/PaymentType.res
+++ b/src/Types/PaymentType.res
@@ -207,6 +207,7 @@ type options = {
business: business,
customerPaymentMethods: savedCardsLoadState,
paymentMethodOrder: option>,
+ subscriptionEvents: option>,
displaySavedPaymentMethodsCheckbox: bool,
displaySavedPaymentMethods: bool,
savedPaymentMethodsCheckboxCheckedByDefault: bool,
@@ -385,6 +386,7 @@ let defaultOptions = {
customerPaymentMethods: LoadingSavedCards,
layout: ObjectLayout(defaultLayout),
paymentMethodOrder: None,
+ subscriptionEvents: None,
fields: defaultFields,
displaySavedPaymentMethodsCheckbox: true,
displaySavedPaymentMethods: true,
@@ -1286,6 +1288,7 @@ let itemToObjMapper = (dict, logger: HyperLoggerTypes.loggerMake) => {
layout: getLayout(dict, "layout", logger),
customerPaymentMethods: getCustomerMethods(dict, "customerPaymentMethods"),
paymentMethodOrder: getOptionalStrArray(dict, "paymentMethodOrder"),
+ subscriptionEvents: SubscriptionEventTypes.getSubscriptionEvents(dict, "subscriptionEvents"),
fields: getFields(dict, "fields", logger),
branding: getWarningString(dict, "branding", "auto", ~logger)->getShowType("options.branding"),
displaySavedPaymentMethodsCheckbox: getBoolWithWarning(
diff --git a/src/Types/SubscriptionEventTypes.res b/src/Types/SubscriptionEventTypes.res
new file mode 100644
index 000000000..d0c039e68
--- /dev/null
+++ b/src/Types/SubscriptionEventTypes.res
@@ -0,0 +1,106 @@
+open ErrorUtils
+open PaymentEventTypes
+
+let validSubscriptionEvents = [
+ "PAYMENT_METHOD_INFO_CARD",
+ "PAYMENT_METHOD_STATUS",
+ "FORM_STATUS",
+ "PAYMENT_METHOD_INFO_BILLING_ADDRESS",
+]
+
+let stringToEvent = (str, key) =>
+ switch str {
+ | "PAYMENT_METHOD_INFO_CARD" => PaymentMethodInfoCard
+ | "PAYMENT_METHOD_STATUS" => PaymentMethodStatus
+ | "FORM_STATUS" => FormStatus
+ | "PAYMENT_METHOD_INFO_BILLING_ADDRESS" => PaymentMethodInfoBillingAddress
+ | _ => {
+ str->unknownPropValueWarning(validSubscriptionEvents, key)
+ UnknownEvent
+ }
+ }
+
+let getSubscriptionEvents = (dict, key) => {
+ let context = `options.${key}`
+ let subscriptionList =
+ dict
+ ->Dict.get(key)
+ ->Option.flatMap(JSON.Decode.array)
+ ->Option.getOr([])
+
+ let mappedSubscriptionEvents =
+ subscriptionList
+ ->Array.map(item =>
+ switch JSON.Decode.string(item) {
+ | Some(str) => stringToEvent(str, context)
+ | None => UnknownEvent
+ }
+ )
+ ->Array.filter(opt => opt != UnknownEvent)
+
+ if mappedSubscriptionEvents->Array.length === 0 {
+ None
+ } else {
+ Some(mappedSubscriptionEvents)
+ }
+}
+
+type paymentMethodStatus = {
+ paymentMethod: string,
+ paymentMethodType: string,
+ isSavedPaymentMethod: bool,
+ isOneClickWallet: bool,
+}
+
+type billingAddress = {
+ country: string,
+ state: string,
+ postalCode: string,
+}
+let createCardInfoPayload = (cardInfo: PaymentEventData.cardInfo) => {
+ let payload = PaymentEventData.cardInfoToJson(cardInfo)
+ [
+ ("elementType", "payment"->JSON.Encode.string),
+ ("eventName", PaymentMethodInfoCard->PaymentEventTypes.eventToString->JSON.Encode.string),
+ ("payload", payload),
+ ]
+}
+
+let createFormStatusPayload = (~status) => {
+ let payload = PaymentEventData.formStatusEventToJson(~status)
+ [
+ ("elementType", "payment"->JSON.Encode.string),
+ ("eventName", FormStatus->eventToString->JSON.Encode.string),
+ ("payload", payload),
+ ]
+}
+
+let createPaymentMethodStatusPayload = (
+ ~paymentMethod,
+ ~paymentMethodType,
+ ~isSavedPaymentMethod,
+ ~isOneClickWallet=false,
+) => {
+ let payload = PaymentEventData.paymentMethodStatusEventToJson(
+ ~paymentMethod,
+ ~paymentMethodType,
+ ~isSavedPaymentMethod,
+ ~isOneClickWallet,
+ )
+
+ [
+ ("elementType", "payment"->JSON.Encode.string),
+ ("eventName", PaymentMethodStatus->eventToString->JSON.Encode.string),
+ ("payload", payload),
+ ]
+}
+
+let createBillingAddressPayload = (~country, ~state, ~postalCode) => {
+ let payload = PaymentEventData.paymentMethodInfoAddressToJson(~country, ~state, ~postalCode)
+
+ [
+ ("elementType", "payment"->JSON.Encode.string),
+ ("eventName", PaymentMethodInfoBillingAddress->eventToString->JSON.Encode.string),
+ ("payload", payload),
+ ]
+}
diff --git a/src/Utilities/DynamicFieldsUtils.res b/src/Utilities/DynamicFieldsUtils.res
index ab309e69e..6a90fbc7a 100644
--- a/src/Utilities/DynamicFieldsUtils.res
+++ b/src/Utilities/DynamicFieldsUtils.res
@@ -195,6 +195,7 @@ let useRequiredFieldsEmptyAndValid = (
~cvcNumber,
~isSavedCardFlow,
) => {
+ let options = Recoil.useRecoilValueFromAtom(optionAtom)
let email = Recoil.useRecoilValueFromAtom(userEmailAddress)
let vpaId = Recoil.useRecoilValueFromAtom(userVpaId)
let pixCNPJ = Recoil.useRecoilValueFromAtom(userPixCNPJ)
@@ -379,6 +380,7 @@ let useRequiredFieldsEmptyAndValid = (
| (Some(cardValid), Some(expiryValid), Some(cvcValid)) =>
CardUtils.emitIsFormReadyForSubmission(
cardValid && expiryValid && cvcValid && areRequiredFieldsValid,
+ ~subscriptionEvents=options.subscriptionEvents,
)
| _ => ()
}
diff --git a/src/Utilities/PaymentUtils.res b/src/Utilities/PaymentUtils.res
index 6b46633b2..28d829078 100644
--- a/src/Utilities/PaymentUtils.res
+++ b/src/Utilities/PaymentUtils.res
@@ -611,41 +611,50 @@ let emitPaymentMethodInfo = (
~state="",
~pinCode="",
~isSavedPaymentMethod=false,
+ ~subscriptionEvents,
) => {
- let baseCardsFields = [
- ("cardBrand", cardBrand->CardUtils.getCardStringFromType->JSON.Encode.string),
- ("cardLast4", cardLast4->JSON.Encode.string),
- ("cardBin", cardBin->JSON.Encode.string),
- ("cardExpiryMonth", cardExpiryMonth->JSON.Encode.string),
- ("cardExpiryYear", cardExpiryYear->JSON.Encode.string),
- ]
+ if (
+ subscriptionEvents->Option.isNone ||
+ PaymentEventData.shouldEmitEvent(
+ ~subscribedEvents=subscriptionEvents->Option.getOr([]),
+ ~eventType=PaymentEventTypes.UnknownEvent,
+ )
+ ) {
+ let baseCardsFields = [
+ ("cardBrand", cardBrand->CardUtils.getCardStringFromType->JSON.Encode.string),
+ ("cardLast4", cardLast4->JSON.Encode.string),
+ ("cardBin", cardBin->JSON.Encode.string),
+ ("cardExpiryMonth", cardExpiryMonth->JSON.Encode.string),
+ ("cardExpiryYear", cardExpiryYear->JSON.Encode.string),
+ ]
- let baseAddressFields = [
- ("country", country->JSON.Encode.string),
- ("state", state->JSON.Encode.string),
- ("pincode", pinCode->JSON.Encode.string),
- ]
+ let baseAddressFields = [
+ ("country", country->JSON.Encode.string),
+ ("state", state->JSON.Encode.string),
+ ("pincode", pinCode->JSON.Encode.string),
+ ]
- let baseSavedPaymentField = [("isSavedPaymentMethod", isSavedPaymentMethod->JSON.Encode.bool)]
+ let baseSavedPaymentField = [("isSavedPaymentMethod", isSavedPaymentMethod->JSON.Encode.bool)]
- let basePaymentInfoFields = switch paymentMethod {
- | "card" => [("paymentMethod", paymentMethod->JSON.Encode.string)]
- | _ => [
- ("paymentMethod", paymentMethod->JSON.Encode.string),
- ("paymentMethodType", paymentMethodType->JSON.Encode.string),
- ]
- }
+ let basePaymentInfoFields = switch paymentMethod {
+ | "card" => [("paymentMethod", paymentMethod->JSON.Encode.string)]
+ | _ => [
+ ("paymentMethod", paymentMethod->JSON.Encode.string),
+ ("paymentMethodType", paymentMethodType->JSON.Encode.string),
+ ]
+ }
- let msg = if cardBrand === CardUtils.NOTFOUND || paymentMethod !== "card" {
- [...basePaymentInfoFields, ...baseAddressFields]
- } else {
- [...basePaymentInfoFields, ...baseAddressFields, ...baseCardsFields]
- }
+ let msg = if cardBrand === CardUtils.NOTFOUND || paymentMethod !== "card" {
+ [...basePaymentInfoFields, ...baseAddressFields]
+ } else {
+ [...basePaymentInfoFields, ...baseAddressFields, ...baseCardsFields]
+ }
- let finalMsg =
- msg->Array.filter(((_, value)) => value->JSON.Decode.string->Option.getOr("") != "")
+ let finalMsg =
+ msg->Array.filter(((_, value)) => value->JSON.Decode.string->Option.getOr("") != "")
- emitMessage(finalMsg->Array.concat(baseSavedPaymentField)->Dict.fromArray)
+ emitMessage(finalMsg->Array.concat(baseSavedPaymentField)->Dict.fromArray)
+ }
}
type nonPiiAdderessData = {
@@ -666,6 +675,42 @@ let useNonPiiAddressData = () => {
}
}
+let getPaymentMethodAndType = (
+ ~paymentMethodName: string,
+ ~paymentMethods: array,
+ ~logger: HyperLoggerTypes.loggerMake,
+) => {
+ if paymentMethodName->String.includes("_debit") {
+ Some(("bank_debit", paymentMethodName))
+ } else if paymentMethodName->String.includes("_transfer") {
+ Some(("bank_transfer", paymentMethodName))
+ } else if paymentMethodName === "card" {
+ Some(("card", "debit"))
+ } else {
+ let finalOptionalPaymentMethodTypeValue =
+ paymentMethods
+ ->Array.filter(paymentMethodData =>
+ paymentMethodData.payment_method_types
+ ->Array.filter(paymentMethodType =>
+ paymentMethodType.payment_method_type === paymentMethodName
+ )
+ ->Array.length > 0
+ )
+ ->Array.get(0)
+
+ switch finalOptionalPaymentMethodTypeValue {
+ | Some(finalPaymentMethodType) =>
+ Some((finalPaymentMethodType.payment_method, paymentMethodName))
+ | None =>
+ logger.setLogError(
+ ~value="Payment method type not found",
+ ~eventName=PAYMENT_METHOD_TYPE_DETECTION_FAILED,
+ )
+ None
+ }
+ }
+}
+
let useEmitPaymentMethodInfo = (
~paymentMethodName,
~paymentMethods: array,
@@ -674,6 +719,7 @@ let useEmitPaymentMethodInfo = (
) => {
let loggerState = Recoil.useRecoilValueFromAtom(RecoilAtoms.loggerAtom)
let {country, state, pinCode} = useNonPiiAddressData()
+ let options = Recoil.useRecoilValueFromAtom(RecoilAtoms.optionAtom)
let {cardNumber, cardBrand} = cardProps
let cardBin = cardNumber->CardUtils.getCardBin
@@ -697,49 +743,25 @@ let useEmitPaymentMethodInfo = (
~country,
~state,
~pinCode,
+ ~subscriptionEvents=options.subscriptionEvents,
)
} else {
- emitPaymentMethodInfo(~paymentMethod, ~paymentMethodType, ~country, ~state, ~pinCode)
+ emitPaymentMethodInfo(
+ ~paymentMethod,
+ ~paymentMethodType,
+ ~country,
+ ~state,
+ ~pinCode,
+ ~subscriptionEvents=options.subscriptionEvents,
+ )
}
}
React.useEffect(() => {
- if paymentMethodName->String.includes("_debit") {
- emitPaymentMethodInfoWrapper(
- ~paymentMethod="bank_debit",
- ~paymentMethodType=paymentMethodName,
- )
- } else if paymentMethodName->String.includes("_transfer") {
- emitPaymentMethodInfoWrapper(
- ~paymentMethod="bank_transfer",
- ~paymentMethodType=paymentMethodName,
- )
- } else if paymentMethodName === "card" {
- emitPaymentMethodInfoWrapper(~paymentMethod="card", ~paymentMethodType="debit")
- } else {
- let finalOptionalPaymentMethodTypeValue =
- paymentMethods
- ->Array.filter(paymentMethodData =>
- paymentMethodData.payment_method_types
- ->Array.filter(
- paymentMethodType => paymentMethodType.payment_method_type === paymentMethodName,
- )
- ->Array.length > 0
- )
- ->Array.get(0)
-
- switch finalOptionalPaymentMethodTypeValue {
- | Some(finalPaymentMethodType) =>
- emitPaymentMethodInfoWrapper(
- ~paymentMethod=finalPaymentMethodType.payment_method,
- ~paymentMethodType=paymentMethodName,
- )
- | None =>
- loggerState.setLogError(
- ~value="Payment method type not found",
- ~eventName=PAYMENT_METHOD_TYPE_DETECTION_FAILED,
- )
- }
+ switch getPaymentMethodAndType(~paymentMethodName, ~paymentMethods, ~logger=loggerState) {
+ | Some((paymentMethod, paymentMethodType)) =>
+ emitPaymentMethodInfoWrapper(~paymentMethod, ~paymentMethodType)
+ | None => ()
}
None
diff --git a/src/Utilities/Utils.res b/src/Utilities/Utils.res
index 4d1e7a674..8167018dd 100644
--- a/src/Utilities/Utils.res
+++ b/src/Utilities/Utils.res
@@ -779,19 +779,28 @@ let handlePostMessageEvents = (
~paymentType,
~loggerState: HyperLoggerTypes.loggerMake,
~savedMethod=false,
+ ~subscriptionEvents,
) => {
- if complete && paymentType !== "" {
- let value = `Payment Data Filled: ${savedMethod
- ? "Saved Payment Method"
- : "New Payment Method"}`
- loggerState.setLogInfo(~value, ~eventName=PAYMENT_DATA_FILLED, ~paymentMethod=paymentType)
+ if (
+ subscriptionEvents->Option.isNone ||
+ PaymentEventData.shouldEmitEvent(
+ ~subscribedEvents=subscriptionEvents->Option.getOr([]),
+ ~eventType=PaymentEventTypes.UnknownEvent,
+ )
+ ) {
+ if complete && paymentType !== "" {
+ let value = `Payment Data Filled: ${savedMethod
+ ? "Saved Payment Method"
+ : "New Payment Method"}`
+ loggerState.setLogInfo(~value, ~eventName=PAYMENT_DATA_FILLED, ~paymentMethod=paymentType)
+ }
+ messageParentWindow([
+ ("elementType", "payment"->JSON.Encode.string),
+ ("complete", complete->JSON.Encode.bool),
+ ("empty", empty->JSON.Encode.bool),
+ ("value", [("type", paymentType->JSON.Encode.string)]->getJsonFromArrayOfJson),
+ ])
}
- messageParentWindow([
- ("elementType", "payment"->JSON.Encode.string),
- ("complete", complete->JSON.Encode.bool),
- ("empty", empty->JSON.Encode.bool),
- ("value", [("type", paymentType->JSON.Encode.string)]->getJsonFromArrayOfJson),
- ])
}
let onlyDigits = str => str->String.replaceRegExp(%re(`/\D/g`), "")
@@ -1449,7 +1458,24 @@ let eventHandlerFunc = (
| OneClickConfirmPayment
| Blur =>
switch eventHandler {
- | Some(eH) => eH(Some(ev.data))
+ | Some(eH) => {
+ let data = ev.data->Identity.anyTypeToJson
+ let dataDict = data->getDictFromJson
+
+ // Check if this is a subscription event by looking for eventName key
+ let isSubscriptionEvent = dataDict->Dict.get("eventName")->Option.isSome
+
+ // For subscription events, remove elementType from the data before sending to merchant
+ let sanitizedData = if isSubscriptionEvent {
+ let dataCopy = dataDict->deepCopyDict
+ dataCopy->Dict.delete("elementType")
+ dataCopy->JSON.Encode.object
+ } else {
+ data
+ }
+
+ eH(Some(sanitizedData))
+ }
| None => ()
}
| _ => ()
diff --git a/src/hyper-loader/Elements.res b/src/hyper-loader/Elements.res
index 77bfc7ad7..070bffd77 100644
--- a/src/hyper-loader/Elements.res
+++ b/src/hyper-loader/Elements.res
@@ -401,16 +401,22 @@ let make = (
),
]->Dict.fromArray
- let widgetOptions =
- [
- ("clientSecret", clientSecret->JSON.Encode.string),
- ("sdkAuthorization", sdkAuthorization->JSON.Encode.string),
- ("appearance", appearance),
- ("locale", locale),
- ("loader", loader),
- ("fonts", fonts),
- ("redirectionFlags", redirectionFlagsDict->JSON.Encode.object),
- ]->getJsonFromArrayOfJson
+ let widgetOptions = [
+ ("clientSecret", clientSecret->JSON.Encode.string),
+ ("sdkAuthorization", sdkAuthorization->JSON.Encode.string),
+ ("appearance", appearance),
+ ("locale", locale),
+ ("loader", loader),
+ ("fonts", fonts),
+ ("redirectionFlags", redirectionFlagsDict->JSON.Encode.object),
+ (
+ "subscriptionEvents",
+ newOptions
+ ->getDictFromJson
+ ->Dict.get("subscriptionEvents")
+ ->Option.getOr(JSON.Encode.null),
+ ),
+ ]->getJsonFromArrayOfJson
let message = [
(
"paymentElementCreate",
diff --git a/src/hyper-loader/LoaderPaymentElement.res b/src/hyper-loader/LoaderPaymentElement.res
index 768e5eed3..7b4982b44 100644
--- a/src/hyper-loader/LoaderPaymentElement.res
+++ b/src/hyper-loader/LoaderPaymentElement.res
@@ -101,7 +101,7 @@ let make = (
(ev: Types.event) => {
if ev.key === "Escape" {
switch eventHandler {
- | Some(eH) => eH(Some(ev.data))
+ | Some(eH) => eH(Some(ev.data->Identity.anyTypeToJson))
| None => ()
}
}
diff --git a/src/hyper-loader/Types.res b/src/hyper-loader/Types.res
index 4a901a9c5..30f92130a 100644
--- a/src/hyper-loader/Types.res
+++ b/src/hyper-loader/Types.res
@@ -26,7 +26,7 @@ module This = {
}
type paymentElement = {
- on: (string, option