From 76352d45b7262dcabc15ce48f161fbbb385a2cb9 Mon Sep 17 00:00:00 2001 From: Vitalii Vanziak Date: Wed, 22 Oct 2025 18:23:29 +0300 Subject: [PATCH 1/3] Apply CardTokenizationContent and style to DC --- .../screen/CardTokenizationScreen.kt | 2 +- .../PODynamicCheckoutConfiguration.kt | 6 +- .../checkout/screen/DynamicCheckoutScreen.kt | 84 +++++++++++++++---- 3 files changed, 72 insertions(+), 20 deletions(-) diff --git a/ui/src/main/kotlin/com/processout/sdk/ui/card/tokenization/screen/CardTokenizationScreen.kt b/ui/src/main/kotlin/com/processout/sdk/ui/card/tokenization/screen/CardTokenizationScreen.kt index 0455af145..436612c35 100644 --- a/ui/src/main/kotlin/com/processout/sdk/ui/card/tokenization/screen/CardTokenizationScreen.kt +++ b/ui/src/main/kotlin/com/processout/sdk/ui/card/tokenization/screen/CardTokenizationScreen.kt @@ -189,7 +189,7 @@ internal object CardTokenizationScreen { } ?: colors.icon.disabled ) - private val defaultScanButton: POButton.Style + val defaultScanButton: POButton.Style @Composable get() = POButton.secondary2.let { it.copy( normal = it.normal.copy( diff --git a/ui/src/main/kotlin/com/processout/sdk/ui/checkout/PODynamicCheckoutConfiguration.kt b/ui/src/main/kotlin/com/processout/sdk/ui/checkout/PODynamicCheckoutConfiguration.kt index 2237bac6d..14c09df78 100644 --- a/ui/src/main/kotlin/com/processout/sdk/ui/checkout/PODynamicCheckoutConfiguration.kt +++ b/ui/src/main/kotlin/com/processout/sdk/ui/checkout/PODynamicCheckoutConfiguration.kt @@ -10,8 +10,6 @@ import com.google.android.gms.wallet.WalletConstants import com.processout.sdk.api.model.request.POContact import com.processout.sdk.api.model.request.POInvoiceRequest import com.processout.sdk.ui.card.scanner.POCardScannerConfiguration -import com.processout.sdk.ui.card.tokenization.POCardTokenizationConfiguration.PreferredSchemeConfiguration -import com.processout.sdk.ui.checkout.PODynamicCheckoutConfiguration.GooglePayConfiguration.Environment import com.processout.sdk.ui.core.annotation.ProcessOutInternalApi import com.processout.sdk.ui.core.shared.image.PODrawableImage import com.processout.sdk.ui.core.style.* @@ -334,6 +332,7 @@ data class PODynamicCheckoutConfiguration( * @param[label] Field label style. * @param[field] Field style. * @param[codeField] Code field style. + * @param[radioField] Radio field style. * @param[radioButton] Radio button style. * @param[checkbox] Checkbox style. * @param[dropdownMenu] Dropdown menu style. @@ -357,7 +356,8 @@ data class PODynamicCheckoutConfiguration( val label: POTextStyle? = null, val field: POFieldStyle? = null, val codeField: POFieldStyle? = null, - val radioButton: PORadioButtonStyle? = null, + val radioField: PORadioFieldStyle? = null, + val radioButton: PORadioButtonStyle? = null, // TODO: remove val checkbox: POCheckboxStyle? = null, val dropdownMenu: PODropdownMenuStyle? = null, val bodyText: POTextStyle? = null, diff --git a/ui/src/main/kotlin/com/processout/sdk/ui/checkout/screen/DynamicCheckoutScreen.kt b/ui/src/main/kotlin/com/processout/sdk/ui/checkout/screen/DynamicCheckoutScreen.kt index e22a85732..4e1211c22 100644 --- a/ui/src/main/kotlin/com/processout/sdk/ui/checkout/screen/DynamicCheckoutScreen.kt +++ b/ui/src/main/kotlin/com/processout/sdk/ui/checkout/screen/DynamicCheckoutScreen.kt @@ -23,6 +23,7 @@ import androidx.compose.ui.graphics.Shape import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow @@ -31,6 +32,9 @@ import coil.compose.AsyncImage import com.google.pay.button.PayButton import com.processout.sdk.api.model.response.POColor import com.processout.sdk.api.model.response.POImageResource +import com.processout.sdk.ui.card.tokenization.CardTokenizationEvent +import com.processout.sdk.ui.card.tokenization.screen.CardTokenizationContent +import com.processout.sdk.ui.card.tokenization.screen.CardTokenizationScreen import com.processout.sdk.ui.checkout.DynamicCheckoutEvent import com.processout.sdk.ui.checkout.DynamicCheckoutEvent.* import com.processout.sdk.ui.checkout.DynamicCheckoutViewModelState @@ -47,17 +51,18 @@ import com.processout.sdk.ui.checkout.screen.DynamicCheckoutScreen.ShortAnimatio import com.processout.sdk.ui.checkout.screen.DynamicCheckoutScreen.SuccessImageHeight import com.processout.sdk.ui.checkout.screen.DynamicCheckoutScreen.SuccessImageWidth import com.processout.sdk.ui.checkout.screen.DynamicCheckoutScreen.animatedBackgroundColor +import com.processout.sdk.ui.checkout.screen.DynamicCheckoutScreen.cardTokenizationStyle import com.processout.sdk.ui.checkout.screen.DynamicCheckoutScreen.toButtonStyle import com.processout.sdk.ui.core.R import com.processout.sdk.ui.core.component.* import com.processout.sdk.ui.core.component.POButton.HighlightedStyle import com.processout.sdk.ui.core.component.POButton.StateStyle -import com.processout.sdk.ui.core.component.POText.Style import com.processout.sdk.ui.core.component.field.POField import com.processout.sdk.ui.core.component.field.checkbox.POCheckbox import com.processout.sdk.ui.core.component.field.code.POCodeField import com.processout.sdk.ui.core.component.field.dropdown.PODropdownField import com.processout.sdk.ui.core.component.field.radio.PORadioButton +import com.processout.sdk.ui.core.component.field.radio.PORadioField import com.processout.sdk.ui.core.component.field.radio.PORadioGroup import com.processout.sdk.ui.core.component.field.radio.PORadioGroup.toRadioButtonStyle import com.processout.sdk.ui.core.state.POActionState @@ -469,11 +474,11 @@ private fun RegularPaymentContent( ) } when (payment.content) { - is Card -> CardTokenization( - id = payment.id, + is Card -> CardTokenizationContent( state = payment.content.state, - onEvent = onEvent, - style = style + onEvent = { onEvent(it.map(paymentMethodId = payment.id)) }, + style = style.cardTokenizationStyle(), + withActionsContainer = false ) is NativeAlternativePayment -> NativeAlternativePayment( id = payment.id, @@ -660,6 +665,27 @@ private fun Success( } } +private fun CardTokenizationEvent.map( + paymentMethodId: String +): DynamicCheckoutEvent = when (this) { + is CardTokenizationEvent.FieldValueChanged -> FieldValueChanged( + paymentMethodId = paymentMethodId, + fieldId = id, + value = value + ) + is CardTokenizationEvent.FieldFocusChanged -> FieldFocusChanged( + paymentMethodId = paymentMethodId, + fieldId = id, + isFocused = isFocused + ) + is CardTokenizationEvent.Action -> Action( + actionId = id, + paymentMethodId = paymentMethodId + ) + is CardTokenizationEvent.CardScannerResult -> CardScannerResult(card = card) + is CardTokenizationEvent.Dismiss -> Dismiss(failure = failure) +} + internal object DynamicCheckoutScreen { @Immutable @@ -671,7 +697,8 @@ internal object DynamicCheckoutScreen { val label: POText.Style, val field: POField.Style, val codeField: POField.Style, - val radioGroup: PORadioGroup.Style, + val radioField: PORadioField.Style, + val radioGroup: PORadioGroup.Style, // TODO: remove val checkbox: POCheckbox.Style, val dropdownMenu: PODropdownField.MenuStyle, val bodyText: AndroidTextView.Style, @@ -720,22 +747,28 @@ internal object DynamicCheckoutScreen { regularPayment = custom?.regularPayment?.custom() ?: defaultRegularPayment, label = custom?.label?.let { POText.custom(style = it) - } ?: POText.label1, + } ?: POText.Style( + color = colors.text.primary, + textStyle = typography.s14(FontWeight.Medium) + ), field = custom?.field?.let { POField.custom(style = it) - } ?: POField.default, + } ?: POField.default2, codeField = custom?.codeField?.let { POField.custom(style = it) } ?: POCodeField.default, + radioField = custom?.radioField?.let { + PORadioField.custom(style = it) + } ?: PORadioField.default, radioGroup = custom?.radioButton?.let { PORadioGroup.custom(style = it) } ?: PORadioGroup.default, checkbox = custom?.checkbox?.let { POCheckbox.custom(style = it) - } ?: POCheckbox.default, + } ?: POCheckbox.default2, dropdownMenu = custom?.dropdownMenu?.let { PODropdownField.custom(style = it) - } ?: PODropdownField.defaultMenu, + } ?: PODropdownField.defaultMenu2, bodyText = custom?.bodyText?.let { style -> val controlsTintColor = custom.controlsTintColorResId?.let { colorResource(id = it) } AndroidTextView.custom( @@ -745,7 +778,10 @@ internal object DynamicCheckoutScreen { } ?: AndroidTextView.default, errorText = custom?.errorText?.let { POText.custom(style = it) - } ?: POText.errorLabel, + } ?: POText.Style( + color = colors.text.error, + textStyle = typography.s14() + ), messageBox = custom?.messageBox?.let { POMessageBox.custom(style = it) } ?: POMessageBox.error, @@ -754,10 +790,10 @@ internal object DynamicCheckoutScreen { } ?: PODialog.default, scanCardButton = custom?.scanCardButton?.let { POButton.custom(style = it) - } ?: POButton.secondary, + } ?: CardTokenizationScreen.defaultScanButton, actionsContainer = custom?.actionsContainer?.let { POActionsContainer.custom(style = it) - } ?: POActionsContainer.default, + } ?: POActionsContainer.default2, backgroundColor = custom?.backgroundColorResId?.let { colorResource(id = it) } ?: colors.surface.default, @@ -782,7 +818,7 @@ internal object DynamicCheckoutScreen { private val defaultRegularPayment: RegularPaymentStyle @Composable get() { - val description = Style( + val description = POText.Style( color = colors.text.muted, textStyle = typography.body2 ) @@ -827,7 +863,7 @@ internal object DynamicCheckoutScreen { private val defaultPaymentSuccess: PaymentSuccessStyle @Composable get() = PaymentSuccessStyle( - message = Style( + message = POText.Style( color = colors.text.success, textStyle = typography.body1 ), @@ -897,7 +933,7 @@ internal object DynamicCheckoutScreen { borderColor: Color, backgroundColor: Color ) = StateStyle( - text = Style( + text = POText.Style( color = textColor, textStyle = POText.custom(type = text.type) ), @@ -925,6 +961,22 @@ internal object DynamicCheckoutScreen { ) ).value + fun Style.cardTokenizationStyle() = CardTokenizationScreen.Style( + title = regularPayment.title, + sectionTitle = label, + field = field, + radioField = radioField, + dropdownMenu = dropdownMenu, + checkbox = checkbox, + dialog = dialog, + errorMessage = errorText, + scanButton = scanCardButton, + actionsContainer = actionsContainer, + backgroundColor = Color.Unspecified, + dividerColor = Color.Unspecified, + dragHandleColor = Color.Unspecified + ) + val ShortAnimationDurationMillis = 300 val LongAnimationDurationMillis = 600 val CrossfadeAnimationDurationMillis = 400 From 6cd1dd5636a96fe8b9f141a9451922cef418e25a Mon Sep 17 00:00:00 2001 From: Vitalii Vanziak Date: Wed, 22 Oct 2025 18:24:48 +0300 Subject: [PATCH 2/3] Remove legacy CardTokenization UI from DC --- .../ui/checkout/screen/CardTokenization.kt | 374 ------------------ 1 file changed, 374 deletions(-) delete mode 100644 ui/src/main/kotlin/com/processout/sdk/ui/checkout/screen/CardTokenization.kt diff --git a/ui/src/main/kotlin/com/processout/sdk/ui/checkout/screen/CardTokenization.kt b/ui/src/main/kotlin/com/processout/sdk/ui/checkout/screen/CardTokenization.kt deleted file mode 100644 index 7ff69d0b9..000000000 --- a/ui/src/main/kotlin/com/processout/sdk/ui/checkout/screen/CardTokenization.kt +++ /dev/null @@ -1,374 +0,0 @@ -package com.processout.sdk.ui.checkout.screen - -import androidx.annotation.DrawableRes -import androidx.compose.animation.* -import androidx.compose.foundation.layout.* -import androidx.compose.runtime.* -import androidx.compose.ui.Modifier -import androidx.compose.ui.focus.FocusRequester -import androidx.compose.ui.focus.focusRequester -import androidx.compose.ui.focus.onFocusChanged -import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.platform.LocalFocusManager -import androidx.compose.ui.text.input.TextFieldValue -import androidx.compose.ui.unit.dp -import androidx.lifecycle.Lifecycle -import com.processout.sdk.ui.card.tokenization.CardTokenizationViewModelState -import com.processout.sdk.ui.card.tokenization.CardTokenizationViewModelState.Item -import com.processout.sdk.ui.card.tokenization.CardTokenizationViewModelState.Section -import com.processout.sdk.ui.card.tokenization.CardTokenizationViewModelState.SectionId.CARD_INFORMATION -import com.processout.sdk.ui.card.tokenization.CardTokenizationViewModelState.SectionId.FUTURE_PAYMENTS -import com.processout.sdk.ui.card.tokenization.CardTokenizationViewModelState.SectionId.PREFERRED_SCHEME -import com.processout.sdk.ui.checkout.DynamicCheckoutEvent -import com.processout.sdk.ui.checkout.DynamicCheckoutEvent.* -import com.processout.sdk.ui.core.component.* -import com.processout.sdk.ui.core.component.field.POField -import com.processout.sdk.ui.core.component.field.checkbox.POCheckbox -import com.processout.sdk.ui.core.component.field.dropdown.PODropdownField -import com.processout.sdk.ui.core.component.field.radio.PORadioGroup -import com.processout.sdk.ui.core.component.field.text.POTextField -import com.processout.sdk.ui.core.state.POImmutableList -import com.processout.sdk.ui.core.theme.ProcessOutTheme.dimensions -import com.processout.sdk.ui.core.theme.ProcessOutTheme.spacing -import com.processout.sdk.ui.shared.component.rememberLifecycleEvent -import com.processout.sdk.ui.shared.state.FieldState - -@Composable -internal fun CardTokenization( - id: String, - state: CardTokenizationViewModelState, - onEvent: (DynamicCheckoutEvent) -> Unit, - style: DynamicCheckoutScreen.Style -) { - if (state.focusedFieldId == null) { - LocalFocusManager.current.clearFocus(force = true) - } - state.cardScannerAction?.let { action -> - POButton( - state = action, - onClick = { - onEvent( - Action( - actionId = it, - paymentMethodId = id - ) - ) - }, - modifier = Modifier - .fillMaxWidth() - .requiredHeightIn(min = dimensions.buttonIconSizeSmall) - .padding(bottom = spacing.small), - style = style.scanCardButton, - iconSize = dimensions.iconSizeSmall - ) - } - val lifecycleEvent = rememberLifecycleEvent() - state.sections.elements.forEach { section -> - Section( - id = id, - section = section, - onEvent = onEvent, - lifecycleEvent = lifecycleEvent, - focusedFieldId = state.focusedFieldId, - isPrimaryActionEnabled = state.primaryAction?.enabled == true && !state.primaryAction.loading, - style = style - ) - } -} - -@Composable -private fun Section( - id: String, - section: Section, - onEvent: (DynamicCheckoutEvent) -> Unit, - lifecycleEvent: Lifecycle.Event, - focusedFieldId: String?, - isPrimaryActionEnabled: Boolean, - style: DynamicCheckoutScreen.Style -) { - val paddingTop = when (section.id) { - CARD_INFORMATION -> 0.dp - PREFERRED_SCHEME -> if (section.title == null) spacing.small else spacing.extraLarge - FUTURE_PAYMENTS -> spacing.small - else -> spacing.extraLarge - } - Column( - modifier = Modifier.padding(top = paddingTop), - verticalArrangement = Arrangement.spacedBy(spacing.small) - ) { - section.title?.let { - with(style.label) { - POText( - text = it, - color = color, - style = textStyle - ) - } - } - section.items?.elements?.forEach { item -> - Item( - id = id, - item = item, - onEvent = onEvent, - lifecycleEvent = lifecycleEvent, - focusedFieldId = focusedFieldId, - isPrimaryActionEnabled = isPrimaryActionEnabled, - style = style, - modifier = Modifier.fillMaxWidth() - ) - } - } - POExpandableText( - text = section.errorMessage, - style = style.errorText, - modifier = Modifier - .fillMaxWidth() - .padding(top = spacing.small) - ) - var currentSubsection by remember { mutableStateOf(Section(id = String())) } - currentSubsection = section.subsection ?: currentSubsection - AnimatedVisibility( - visible = section.subsection != null, - enter = expandVertically() + fadeIn(), - exit = shrinkVertically() + fadeOut() - ) { - Section( - id = id, - section = currentSubsection, - onEvent = onEvent, - lifecycleEvent = lifecycleEvent, - focusedFieldId = focusedFieldId, - isPrimaryActionEnabled = isPrimaryActionEnabled, - style = style - ) - } -} - -@Composable -private fun Item( - id: String, - item: Item, - onEvent: (DynamicCheckoutEvent) -> Unit, - lifecycleEvent: Lifecycle.Event, - focusedFieldId: String?, - isPrimaryActionEnabled: Boolean, - style: DynamicCheckoutScreen.Style, - modifier: Modifier = Modifier -) { - when (item) { - is Item.TextField -> TextField( - id = id, - state = item.state, - onEvent = onEvent, - lifecycleEvent = lifecycleEvent, - focusedFieldId = focusedFieldId, - isPrimaryActionEnabled = isPrimaryActionEnabled, - style = style.field, - modifier = modifier - ) - is Item.RadioField -> RadioField( - id = id, - state = item.state, - onEvent = onEvent, - style = style.radioGroup, - modifier = modifier - ) - is Item.DropdownField -> DropdownField( - id = id, - state = item.state, - onEvent = onEvent, - fieldStyle = style.field, - menuStyle = style.dropdownMenu, - modifier = modifier - ) - is Item.CheckboxField -> CheckboxField( - id = id, - state = item.state, - onEvent = onEvent, - style = style.checkbox, - modifier = modifier - ) - is Item.Group -> Row( - horizontalArrangement = Arrangement.spacedBy(spacing.small) - ) { - item.items.elements.forEach { groupItem -> - Item( - id = id, - item = groupItem, - onEvent = onEvent, - lifecycleEvent = lifecycleEvent, - focusedFieldId = focusedFieldId, - isPrimaryActionEnabled = isPrimaryActionEnabled, - style = style, - modifier = Modifier.weight(1f) - ) - } - } - } -} - -@Composable -private fun TextField( - id: String, - state: FieldState, - onEvent: (DynamicCheckoutEvent) -> Unit, - lifecycleEvent: Lifecycle.Event, - focusedFieldId: String?, - isPrimaryActionEnabled: Boolean, - style: POField.Style, - modifier: Modifier = Modifier -) { - val focusRequester = remember { FocusRequester() } - POTextField( - value = state.value, - onValueChange = { - onEvent( - FieldValueChanged( - paymentMethodId = id, - fieldId = state.id, - value = state.inputFilter?.filter(it) ?: it - ) - ) - }, - modifier = modifier - .focusRequester(focusRequester) - .onFocusChanged { - onEvent( - FieldFocusChanged( - paymentMethodId = id, - fieldId = state.id, - isFocused = it.isFocused - ) - ) - }, - style = style, - enabled = state.enabled, - isError = state.isError, - forceTextDirectionLtr = state.forceTextDirectionLtr, - placeholder = state.placeholder, - trailingIcon = { state.iconResId?.let { AnimatedFieldIcon(id = it) } }, - visualTransformation = state.visualTransformation, - keyboardOptions = state.keyboardOptions, - keyboardActions = POField.keyboardActions( - imeAction = state.keyboardOptions.imeAction, - actionId = state.keyboardActionId, - enabled = isPrimaryActionEnabled, - onClick = { - onEvent( - Action( - actionId = it, - paymentMethodId = id - ) - ) - } - ) - ) - if (state.id == focusedFieldId && lifecycleEvent == Lifecycle.Event.ON_RESUME) { - PORequestFocus(focusRequester, lifecycleEvent) - } -} - -@Composable -private fun RadioField( - id: String, - state: FieldState, - onEvent: (DynamicCheckoutEvent) -> Unit, - style: PORadioGroup.Style, - modifier: Modifier = Modifier -) { - PORadioGroup( - value = state.value.text, - onValueChange = { - if (state.enabled) { - onEvent( - FieldValueChanged( - paymentMethodId = id, - fieldId = state.id, - value = TextFieldValue(text = it) - ) - ) - } - }, - availableValues = state.availableValues ?: POImmutableList(emptyList()), - modifier = modifier, - style = style - ) -} - -@Composable -private fun DropdownField( - id: String, - state: FieldState, - onEvent: (DynamicCheckoutEvent) -> Unit, - fieldStyle: POField.Style, - menuStyle: PODropdownField.MenuStyle, - modifier: Modifier = Modifier -) { - PODropdownField( - value = state.value, - onValueChange = { - onEvent( - FieldValueChanged( - paymentMethodId = id, - fieldId = state.id, - value = it - ) - ) - }, - availableValues = state.availableValues ?: POImmutableList(emptyList()), - modifier = modifier - .onFocusChanged { - onEvent( - FieldFocusChanged( - paymentMethodId = id, - fieldId = state.id, - isFocused = it.isFocused - ) - ) - }, - fieldStyle = fieldStyle, - menuStyle = menuStyle, - enabled = state.enabled, - isError = state.isError, - placeholder = state.placeholder - ) -} - -@Composable -private fun CheckboxField( - id: String, - state: FieldState, - onEvent: (DynamicCheckoutEvent) -> Unit, - style: POCheckbox.Style, - modifier: Modifier = Modifier -) { - POCheckbox( - text = state.label ?: String(), - checked = state.value.text.toBooleanStrictOrNull() ?: false, - onCheckedChange = { - if (state.enabled) { - onEvent( - FieldValueChanged( - paymentMethodId = id, - fieldId = state.id, - value = TextFieldValue(text = it.toString()) - ) - ) - } - }, - modifier = modifier, - style = style, - isError = state.isError - ) -} - -@Composable -private fun AnimatedFieldIcon(@DrawableRes id: Int) { - POAnimatedImage( - id = id, - modifier = Modifier - .requiredHeight(dimensions.formComponentMinHeight) - .padding(POField.contentPadding), - contentScale = ContentScale.FillHeight - ) -} From 55cc702ed86fb626956bd9f64bee3d0ac51d616c Mon Sep 17 00:00:00 2001 From: Vitalii Vanziak Date: Thu, 23 Oct 2025 16:25:46 +0300 Subject: [PATCH 3/3] Continue to edit in case of failure when card is not tokenized --- .../sdk/ui/card/tokenization/CardTokenizationViewModel.kt | 2 ++ .../processout/sdk/ui/checkout/DynamicCheckoutInteractor.kt | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/ui/src/main/kotlin/com/processout/sdk/ui/card/tokenization/CardTokenizationViewModel.kt b/ui/src/main/kotlin/com/processout/sdk/ui/card/tokenization/CardTokenizationViewModel.kt index e712bb494..dc67b6dc6 100644 --- a/ui/src/main/kotlin/com/processout/sdk/ui/card/tokenization/CardTokenizationViewModel.kt +++ b/ui/src/main/kotlin/com/processout/sdk/ui/card/tokenization/CardTokenizationViewModel.kt @@ -89,6 +89,8 @@ internal class CardTokenizationViewModel private constructor( fun onEvent(event: CardTokenizationEvent) = interactor.onEvent(event) + fun isTokenized() = interactor.state.value.tokenizedCard != null + private fun map(state: CardTokenizationInteractorState) = with(configuration) { CardTokenizationViewModelState( title = title ?: app.getString(R.string.po_card_tokenization_title), diff --git a/ui/src/main/kotlin/com/processout/sdk/ui/checkout/DynamicCheckoutInteractor.kt b/ui/src/main/kotlin/com/processout/sdk/ui/checkout/DynamicCheckoutInteractor.kt index d0379d8fb..fd7c6b5f2 100644 --- a/ui/src/main/kotlin/com/processout/sdk/ui/checkout/DynamicCheckoutInteractor.kt +++ b/ui/src/main/kotlin/com/processout/sdk/ui/checkout/DynamicCheckoutInteractor.kt @@ -1077,7 +1077,8 @@ internal class DynamicCheckoutInteractor( coroutineScope = interactorScope ) { request -> interactorScope.launch { - eventDispatcher.send(request.toResponse(shouldContinue = false)) + val shouldContinue = !cardTokenization.isTokenized() + eventDispatcher.send(request.toResponse(shouldContinue)) } } eventDispatcher.subscribeForRequest(