Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

import com.checkout.frames.api.PaymentFormMediator;
import com.checkout.frames.api.PaymentFlowHandler;
import com.checkout.frames.screen.paymentform.PaymentFormConfig;
import com.checkout.frames.screen.paymentform.model.PaymentFormConfig;
import com.checkout.frames.style.screen.PaymentFormStyle;
import com.checkout.threedsecure.model.ThreeDSRequest;
import com.checkout.threedsecure.model.ThreeDSResult;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@ import com.checkout.example.frames.paymentformstyling.CustomPaymentFormTheme
import com.checkout.example.frames.ui.utils.ENVIRONMENT
import com.checkout.example.frames.ui.utils.PUBLIC_KEY
import com.checkout.frames.R
import com.checkout.frames.screen.paymentform.PaymentFormConfig
import com.checkout.frames.screen.paymentform.model.PaymentFormConfig
import com.checkout.frames.api.PaymentFormMediator
import com.checkout.frames.style.screen.PaymentFormStyle
import com.checkout.frames.api.PaymentFlowHandler
import com.checkout.frames.screen.paymentform.model.PrefillData
import com.checkout.frames.style.theme.paymentform.PaymentFormStyleProvider
import com.checkout.tokenization.model.TokenDetails

Expand Down Expand Up @@ -71,7 +72,8 @@ fun Navigator(

val customThemingPaymentFormMediator = PaymentFormMediator(
defaultPaymentFormConfig.copy(
style = PaymentFormStyleProvider.provide(CustomPaymentFormTheme.providePaymentFormTheme())
style = PaymentFormStyleProvider.provide(CustomPaymentFormTheme.providePaymentFormTheme()),
prefillData = PrefillData(cardHolderName = "Test Name")
)
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import com.checkout.example.frames.ui.utils.URL_IDENTIFIER
import com.checkout.frames.R
import com.checkout.frames.api.PaymentFlowHandler
import com.checkout.frames.api.PaymentFormMediator
import com.checkout.frames.screen.paymentform.PaymentFormConfig
import com.checkout.frames.screen.paymentform.model.PaymentFormConfig
import com.checkout.frames.style.screen.PaymentFormStyle
import com.checkout.threedsecure.model.ThreeDSRequest
import com.checkout.threedsecure.model.ThreeDSResult
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.platform.ViewCompositionStrategy
import androidx.fragment.app.Fragment
import com.checkout.frames.screen.paymentform.PaymentFormConfig
import com.checkout.frames.screen.paymentform.model.PaymentFormConfig
import com.checkout.frames.screen.paymentform.PaymentFormScreen
import com.checkout.logging.EventLoggerProvider
import com.checkout.threedsecure.Executor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ internal class CardHolderNameViewModel @Inject constructor(
// Needed to prevent validation on focus switch for initial component state
private var wasFocused = false

init {
componentState.cardHolderName.value = paymentStateManager.cardHolderName.value
}

/**
* Make full card number validation, when focus switched to another view.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import com.checkout.frames.screen.countrypicker.CountryPickerViewModel
import com.checkout.frames.screen.paymentdetails.PaymentDetailsViewModel
import com.checkout.frames.screen.paymentform.PaymentFormViewModel
import com.checkout.frames.model.request.InternalCardTokenRequest
import com.checkout.frames.screen.paymentform.model.PrefillData
import com.checkout.logging.Logger
import com.checkout.logging.model.LoggingEvent
import dagger.BindsInstance
Expand Down Expand Up @@ -64,6 +65,9 @@ internal abstract class FramesDIComponent {
@BindsInstance
fun supportedCardSchemes(supportedCardSchemeList: List<CardScheme>): Builder

@BindsInstance
fun prefillData(cardHolderName: PrefillData?): Builder

fun build(): FramesDIComponent
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import com.checkout.frames.screen.paymentdetails.PaymentDetailsViewModel
import com.checkout.frames.screen.paymentform.PaymentFormViewModel
import com.checkout.frames.api.PaymentFlowHandler
import com.checkout.frames.component.cardholdername.CardHolderNameViewModel
import com.checkout.frames.screen.paymentform.model.PrefillData
import com.checkout.frames.usecase.CardTokenizationUseCase
import com.checkout.frames.usecase.ClosePaymentFlowUseCase
import com.checkout.frames.utils.extensions.logEvent
Expand Down Expand Up @@ -54,7 +55,8 @@ internal class FramesInjector(private val component: FramesDIComponent) : Inject
context: Context,
environment: Environment,
paymentFlowHandler: PaymentFlowHandler,
supportedCardSchemeList: List<CardScheme> = emptyList()
supportedCardSchemeList: List<CardScheme> = emptyList(),
prefillData: PrefillData? = null
): Injector {
val logger = EventLoggerProvider.provide().apply {
setup(context, environment, BuildConfig.LOGGING_IDENTIFIER, BuildConfig.PRODUCT_VERSION)
Expand All @@ -73,6 +75,7 @@ internal class FramesInjector(private val component: FramesDIComponent) : Inject
.cardTokenizationUseCase(cardTokenizationUseCase)
.closePaymentFlowUseCase(closePaymentFlowUseCase)
.supportedCardSchemes(supportedCardSchemeList)
.prefillData(prefillData)
.build()
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import com.checkout.frames.di.component.ExpiryDateViewModelSubComponent
import com.checkout.frames.di.screen.PaymentDetailsViewModelSubComponent
import com.checkout.frames.screen.manager.PaymentFormStateManager
import com.checkout.frames.screen.manager.PaymentStateManager
import com.checkout.frames.screen.paymentform.model.PrefillData
import dagger.Module
import dagger.Provides
import javax.inject.Singleton
Expand All @@ -36,8 +37,9 @@ internal class PaymentModule {
@Provides
@Singleton
fun paymentStateManager(
supportedCardSchemes: List<CardScheme>
supportedCardSchemes: List<CardScheme>,
prefillData: PrefillData?
): PaymentStateManager =
PaymentFormStateManager(supportedCardSchemes)
PaymentFormStateManager(supportedCardSchemes, prefillData)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.checkout.frames.screen.manager
import androidx.annotation.VisibleForTesting
import com.checkout.base.model.CardScheme
import com.checkout.frames.screen.billingaddress.billingaddressdetails.models.BillingAddress
import com.checkout.frames.screen.paymentform.model.PrefillData
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.MutableStateFlow
Expand All @@ -11,7 +12,8 @@ import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.stateIn

internal class PaymentFormStateManager(
private val supportedCardSchemes: List<CardScheme>
private val supportedCardSchemes: List<CardScheme>,
paymentFormPrefillData: PrefillData? = null
) : PaymentStateManager {

override val cardNumber: MutableStateFlow<String> = MutableStateFlow("")
Expand All @@ -25,7 +27,7 @@ internal class PaymentFormStateManager(
override val cvv: MutableStateFlow<String> = MutableStateFlow("")
override val isCvvValid: MutableStateFlow<Boolean> = MutableStateFlow(false)

override val cardHolderName: MutableStateFlow<String> = MutableStateFlow("")
override val cardHolderName = MutableStateFlow(paymentFormPrefillData?.cardHolderName ?: "")
override val isCardHolderNameValid: MutableStateFlow<Boolean> = MutableStateFlow(false)

override val billingAddress: MutableStateFlow<BillingAddress> = MutableStateFlow(BillingAddress())
Expand All @@ -44,7 +46,6 @@ internal class PaymentFormStateManager(
isBillingAddressEnabled: Boolean,
) {
cardNumber.value = ""
cardHolderName.value = ""
cardScheme.value = CardScheme.UNKNOWN
isCardNumberValid.value = false
isCardSchemeUpdated.value = false
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import androidx.lifecycle.viewmodel.compose.viewModel
import com.checkout.frames.screen.billingaddress.billingaddressform.BillingAddressFormScreen
import com.checkout.frames.screen.navigation.Screen
import com.checkout.frames.screen.paymentdetails.PaymentDetailsScreen
import com.checkout.frames.screen.paymentform.model.PaymentFormConfig
import com.google.accompanist.navigation.animation.AnimatedNavHost
import com.google.accompanist.navigation.animation.composable
import com.google.accompanist.navigation.animation.rememberAnimatedNavController
Expand All @@ -20,11 +21,12 @@ internal fun PaymentFormScreen(config: PaymentFormConfig) {
val navController = rememberAnimatedNavController()
val viewModel: PaymentFormViewModel = viewModel(
factory = PaymentFormViewModel.Factory(
config.publicKey,
config.context,
config.environment,
config.paymentFlowHandler,
config.supportedCardSchemeList
publicKey = config.publicKey,
context = config.context,
environment = config.environment,
paymentFlowHandler = config.paymentFlowHandler,
supportedCardSchemes = config.supportedCardSchemeList,
prefillData = config.prefillData
)
)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.checkout.frames.screen.paymentform

import android.content.Context
import androidx.annotation.VisibleForTesting
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import com.checkout.base.model.CardScheme
Expand All @@ -9,6 +10,7 @@ import com.checkout.frames.di.base.InjectionClient
import com.checkout.frames.di.base.Injector
import com.checkout.frames.di.injector.FramesInjector
import com.checkout.frames.api.PaymentFlowHandler
import com.checkout.frames.screen.paymentform.model.PrefillData
import javax.inject.Inject

internal class PaymentFormViewModel @Inject internal constructor() : ViewModel() {
Expand All @@ -20,19 +22,20 @@ internal class PaymentFormViewModel @Inject internal constructor() : ViewModel()
private val context: Context,
private val environment: Environment,
private val paymentFlowHandler: PaymentFlowHandler,
private val supportedCardSchemes: List<CardScheme> = emptyList()
private val supportedCardSchemes: List<CardScheme> = emptyList(),
private val prefillData: PrefillData? = null
) : ViewModelProvider.Factory, InjectionClient {

@Inject
lateinit var viewModel: PaymentFormViewModel

private lateinit var injector: Injector
@VisibleForTesting
lateinit var injector: Injector
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's make it internal just for exposing to tests?


@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T {
injector = FramesInjector.create(
publicKey, context, environment,
paymentFlowHandler, supportedCardSchemes
publicKey, context, environment, paymentFlowHandler, supportedCardSchemes, prefillData
)

injector.inject(this)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.checkout.frames.screen.paymentform.model

import com.checkout.tokenization.model.Address
import com.checkout.tokenization.model.Phone

/**
* @param name - represent the cardHolderName in Billing form
* @param address - [Address] represent the payment source owner's billing address in Billing form
* @param phone - [Phone] represent the payment source owner's billing phone in Billing form
*/
public data class BillingFormAddress @JvmOverloads constructor(
val name: String? = null,
val address: Address? = null,
val phone: Phone? = null,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.checkout.frames.screen.paymentform.model

import android.content.Context
import com.checkout.base.model.CardScheme
import com.checkout.base.model.Environment
import com.checkout.frames.style.screen.PaymentFormStyle
import com.checkout.frames.api.PaymentFlowHandler

/**
* @param publicKey - used for client-side authentication in the SDK
* @param context - represent the application context
* @param environment - [Environment] represent the environment for tokenization
* @param style - [PaymentFormStyle] represent the style for PaymentForm
* @param paymentFlowHandler - [PaymentFlowHandler] represent the handler for PaymentForm
* @param supportedCardSchemeList - represent the supported card schemes [CardScheme] in PaymentForm
* @param prefillData - [PrefillData] represent the data for prefill in the PaymentForm
*/
public data class PaymentFormConfig @JvmOverloads constructor(
public val publicKey: String,
public val context: Context,
public val environment: Environment,
public var style: PaymentFormStyle,
public val paymentFlowHandler: PaymentFlowHandler,
public var supportedCardSchemeList: List<CardScheme> = emptyList(),
public val prefillData: PrefillData? = null
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.checkout.frames.screen.paymentform.model

/**
* @param cardHolderName - represent the cardHolderName in PaymentDetail form
* @param billingFormAddress - [BillingFormAddress] represent the payment source owner's full billing address
*/
public data class PrefillData @JvmOverloads constructor(
public val cardHolderName: String? = null,
public val billingFormAddress: BillingFormAddress? = null
)
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ import org.junit.jupiter.api.extension.ExtendWith
internal class AddressSummaryViewModelTest {

@SpyK
var spyPaymentStateManager: PaymentStateManager = PaymentFormStateManager(emptyList())
var spyPaymentStateManager: PaymentStateManager = PaymentFormStateManager(supportedCardSchemes = emptyList())

@SpyK
lateinit var spyComponentStateMapper: Mapper<AddressSummaryComponentStyle, AddressSummaryComponentState>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,7 @@ internal class CardHolderNameViewModelTest {

@BeforeEach
fun setUp() {
viewModel = CardHolderNameViewModel(
spyPaymentStateManager,
spyInputComponentStyleMapper, spyInputComponentStateMapper, style
)
initViewModel()
}

/** Initial state tests **/
Expand Down Expand Up @@ -113,6 +110,19 @@ internal class CardHolderNameViewModelTest {
assertTrue(spyPaymentStateManager.isCardHolderNameValid.value)
}

@Test
fun `when cardHolderName is already updated in paymentStateManager then cardHolderName in componentState is updated`() {
// Given
val expectedCardHolderName = "TestName"
spyPaymentStateManager.cardHolderName.value = expectedCardHolderName

// When
initViewModel()

// Then
assertEquals(expectedCardHolderName, viewModel.componentState.cardHolderName.value)
}

/** Validation related tests **/

@Test
Expand Down Expand Up @@ -182,6 +192,12 @@ internal class CardHolderNameViewModelTest {
}

private fun initPaymentStateManager() {
spyPaymentStateManager = PaymentFormStateManager(emptyList())
spyPaymentStateManager = PaymentFormStateManager(supportedCardSchemes = emptyList())
}

private fun initViewModel() {
viewModel = CardHolderNameViewModel(
spyPaymentStateManager, spyInputComponentStyleMapper, spyInputComponentStateMapper, style
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ internal class CardNumberViewModelTest {
lateinit var spyDynamicImageMapper: ImageStyleToDynamicComposableImageMapper

@SpyK
var spyPaymentStateManager: PaymentStateManager = PaymentFormStateManager(emptyList())
var spyPaymentStateManager: PaymentStateManager = PaymentFormStateManager(supportedCardSchemes = emptyList())

private var style: CardNumberComponentStyle = CardNumberComponentStyle()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ internal class CardSchemeViewModelTest {
lateinit var spyImageStyleToComposableImageMapper: ImageStyleToComposableImageMapper

@SpyK
var spyPaymentStateManager: PaymentStateManager = PaymentFormStateManager(emptyList())
var spyPaymentStateManager: PaymentStateManager = PaymentFormStateManager(supportedCardSchemes = emptyList())

private var style: CardSchemeComponentStyle = CardSchemeComponentStyle()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ internal class CountryViewModelTest {
lateinit var spyInputComponentStateMapper: Mapper<InputComponentStyle, InputComponentState>

@SpyK
var spyPaymentStateManager: PaymentStateManager = PaymentFormStateManager(emptyList())
var spyPaymentStateManager: PaymentStateManager = PaymentFormStateManager(supportedCardSchemes = emptyList())

private lateinit var viewModel: CountryViewModel
private var style = CountryComponentStyle()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ internal class CvvViewModelTest {
lateinit var spyInputComponentStateMapper: Mapper<InputComponentStyle, InputComponentState>

@SpyK
var spyPaymentStateManager: PaymentStateManager = PaymentFormStateManager(listOf())
var spyPaymentStateManager: PaymentStateManager = PaymentFormStateManager(supportedCardSchemes = emptyList())

private var style: CvvComponentStyle = CvvComponentStyle()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ internal class ExpiryDateViewModelTest {
lateinit var spyInputComponentStateMapper: Mapper<InputComponentStyle, InputComponentState>

@SpyK
var spyPaymentStateManager: PaymentStateManager = PaymentFormStateManager(emptyList())
var spyPaymentStateManager: PaymentStateManager = PaymentFormStateManager(supportedCardSchemes = emptyList())

private var style: ExpiryDateComponentStyle = ExpiryDateComponentStyle(InputComponentStyle())

Expand Down
Loading