Skip to content

Commit

Permalink
Move google pay into PaymentMethodMetadata. (#8829)
Browse files Browse the repository at this point in the history
  • Loading branch information
jaynewstrom-stripe authored Jul 19, 2024
1 parent 3624057 commit 4aa391f
Show file tree
Hide file tree
Showing 31 changed files with 85 additions and 162 deletions.
24 changes: 0 additions & 24 deletions paymentsheet/api/paymentsheet.api
Original file line number Diff line number Diff line change
Expand Up @@ -1890,30 +1890,6 @@ public final class com/stripe/android/paymentsheet/state/CustomerState$Permissio
public synthetic fun newArray (I)[Ljava/lang/Object;
}

public final class com/stripe/android/paymentsheet/state/GooglePayState$Available$Creator : android/os/Parcelable$Creator {
public fun <init> ()V
public final fun createFromParcel (Landroid/os/Parcel;)Lcom/stripe/android/paymentsheet/state/GooglePayState$Available;
public synthetic fun createFromParcel (Landroid/os/Parcel;)Ljava/lang/Object;
public final fun newArray (I)[Lcom/stripe/android/paymentsheet/state/GooglePayState$Available;
public synthetic fun newArray (I)[Ljava/lang/Object;
}

public final class com/stripe/android/paymentsheet/state/GooglePayState$Indeterminate$Creator : android/os/Parcelable$Creator {
public fun <init> ()V
public final fun createFromParcel (Landroid/os/Parcel;)Lcom/stripe/android/paymentsheet/state/GooglePayState$Indeterminate;
public synthetic fun createFromParcel (Landroid/os/Parcel;)Ljava/lang/Object;
public final fun newArray (I)[Lcom/stripe/android/paymentsheet/state/GooglePayState$Indeterminate;
public synthetic fun newArray (I)[Ljava/lang/Object;
}

public final class com/stripe/android/paymentsheet/state/GooglePayState$NotAvailable$Creator : android/os/Parcelable$Creator {
public fun <init> ()V
public final fun createFromParcel (Landroid/os/Parcel;)Lcom/stripe/android/paymentsheet/state/GooglePayState$NotAvailable;
public synthetic fun createFromParcel (Landroid/os/Parcel;)Ljava/lang/Object;
public final fun newArray (I)[Lcom/stripe/android/paymentsheet/state/GooglePayState$NotAvailable;
public synthetic fun newArray (I)[Ljava/lang/Object;
}

public final class com/stripe/android/paymentsheet/state/LinkState$Creator : android/os/Parcelable$Creator {
public fun <init> ()V
public final fun createFromParcel (Landroid/os/Parcel;)Lcom/stripe/android/paymentsheet/state/LinkState;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,10 @@ internal class DefaultCustomerSheetLoader(
preferredNetworks = configuration.preferredNetworks,
)

val isGooglePayReadyAndEnabled = configuration.googlePayEnabled && googlePayRepositoryFactory(
if (isLiveModeProvider()) GooglePayEnvironment.Production else GooglePayEnvironment.Test
).isReady().first()

val metadata = PaymentMethodMetadata(
stripeIntent = elementsSession.stripeIntent,
billingDetailsCollectionConfiguration = billingDetailsCollectionConfig,
Expand All @@ -145,6 +149,7 @@ internal class DefaultCustomerSheetLoader(
sharedDataSpecs = sharedDataSpecs,
financialConnectionsAvailable = isFinancialConnectionsAvailable(),
externalPaymentMethodSpecs = emptyList(),
isGooglePayReady = isGooglePayReadyAndEnabled,
)

ElementsSessionWithMetadata(elementsSession = elementsSession, metadata = metadata)
Expand Down Expand Up @@ -194,10 +199,6 @@ internal class DefaultCustomerSheetLoader(
}
}

val isGooglePayReadyAndEnabled = configuration.googlePayEnabled && googlePayRepositoryFactory(
if (isLiveModeProvider()) GooglePayEnvironment.Production else GooglePayEnvironment.Test
).isReady().first()

val elementsSession = elementsSessionWithMetadata.elementsSession
val metadata = elementsSessionWithMetadata.metadata

Expand All @@ -211,7 +212,6 @@ internal class DefaultCustomerSheetLoader(
paymentMethodMetadata = metadata,
supportedPaymentMethods = validSupportedPaymentMethods,
customerPaymentMethods = paymentMethods,
isGooglePayReady = isGooglePayReadyAndEnabled,
paymentSelection = paymentSelection,
validationError = elementsSession.stripeIntent.validate(),
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ internal sealed interface CustomerSheetState {
val paymentMethodMetadata: PaymentMethodMetadata,
val customerPaymentMethods: List<PaymentMethod>,
val supportedPaymentMethods: List<SupportedPaymentMethod>,
val isGooglePayReady: Boolean,
val paymentSelection: PaymentSelection?,
val validationError: Throwable?,
) : CustomerSheetState
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,6 @@ internal class CustomerSheetViewModel(
private val _result = MutableStateFlow<InternalCustomerSheetResult?>(null)
val result: StateFlow<InternalCustomerSheetResult?> = _result

private var isGooglePayReadyAndEnabled: Boolean = false
private var paymentLauncher: PaymentLauncher? = null

private var previouslySelectedPaymentMethod: SupportedPaymentMethod? = null
Expand Down Expand Up @@ -322,7 +321,6 @@ internal class CustomerSheetViewModel(
supportedPaymentMethods.addAll(state.supportedPaymentMethods)

originalPaymentSelection = state.paymentSelection
isGooglePayReadyAndEnabled = state.isGooglePayReady
paymentMethodMetadata = state.paymentMethodMetadata

transitionToInitialScreen(
Expand All @@ -345,7 +343,7 @@ internal class CustomerSheetViewModel(
paymentSelection: PaymentSelection?,
cbcEligibility: CardBrandChoiceEligibility,
) {
if (paymentMethods.isEmpty() && !isGooglePayReadyAndEnabled) {
if (paymentMethods.isEmpty() && paymentMethodMetadata?.isGooglePayReady == false) {
transitionToAddPaymentMethod(
isFirstPaymentMethod = true,
cbcEligibility = cbcEligibility,
Expand Down Expand Up @@ -625,7 +623,7 @@ internal class CustomerSheetViewModel(
}
}

if (newSavedPaymentMethods.isEmpty() && !isGooglePayReadyAndEnabled) {
if (newSavedPaymentMethods.isEmpty() && paymentMethodMetadata?.isGooglePayReady == false) {
transitionToAddPaymentMethod(isFirstPaymentMethod = true)
}
}
Expand Down Expand Up @@ -1215,7 +1213,7 @@ internal class CustomerSheetViewModel(
isLiveMode = isLiveModeProvider(),
isProcessing = false,
isEditing = false,
isGooglePayEnabled = isGooglePayReadyAndEnabled,
isGooglePayEnabled = paymentMethodMetadata?.isGooglePayReady == true,
primaryButtonVisible = false,
primaryButtonLabel = resources.getString(R.string.stripe_paymentsheet_confirm),
errorMessage = null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ internal data class PaymentMethodMetadata(
val sharedDataSpecs: List<SharedDataSpec>,
val externalPaymentMethodSpecs: List<ExternalPaymentMethodSpec>,
val hasCustomerConfiguration: Boolean,
val isGooglePayReady: Boolean,
val financialConnectionsAvailable: Boolean = DefaultIsFinancialConnectionsAvailable(),
) : Parcelable {
fun hasIntentToSetup(): Boolean {
Expand Down Expand Up @@ -194,6 +195,7 @@ internal data class PaymentMethodMetadata(
configuration: PaymentSheet.Configuration,
sharedDataSpecs: List<SharedDataSpec>,
externalPaymentMethodSpecs: List<ExternalPaymentMethodSpec>,
isGooglePayReady: Boolean,
): PaymentMethodMetadata {
return PaymentMethodMetadata(
stripeIntent = elementsSession.stripeIntent,
Expand All @@ -211,7 +213,8 @@ internal data class PaymentMethodMetadata(
shippingDetails = configuration.shippingDetails,
hasCustomerConfiguration = configuration.customer != null,
sharedDataSpecs = sharedDataSpecs,
externalPaymentMethodSpecs = externalPaymentMethodSpecs
externalPaymentMethodSpecs = externalPaymentMethodSpecs,
isGooglePayReady = isGooglePayReady,
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import com.stripe.android.paymentsheet.navigation.PaymentSheetScreen
import com.stripe.android.paymentsheet.navigation.PaymentSheetScreen.AddFirstPaymentMethod
import com.stripe.android.paymentsheet.navigation.PaymentSheetScreen.SelectSavedPaymentMethods
import com.stripe.android.paymentsheet.repositories.CustomerRepository
import com.stripe.android.paymentsheet.state.GooglePayState
import com.stripe.android.paymentsheet.state.WalletsProcessingState
import com.stripe.android.paymentsheet.state.WalletsState
import com.stripe.android.paymentsheet.ui.DefaultAddPaymentMethodInteractor
Expand Down Expand Up @@ -99,12 +98,12 @@ internal class PaymentOptionsViewModel @Inject constructor(
linkConfigurationCoordinator.emailFlow,
buttonsEnabled,
paymentMethodMetadata.mapAsStateFlow { it?.supportedPaymentMethodTypes().orEmpty() },
googlePayState,
) { isLinkAvailable, linkEmail, buttonsEnabled, paymentMethodTypes, googlePayState ->
paymentMethodMetadata.mapAsStateFlow { it?.isGooglePayReady == true },
) { isLinkAvailable, linkEmail, buttonsEnabled, paymentMethodTypes, isGooglePayReady ->
WalletsState.create(
isLinkAvailable = isLinkAvailable,
linkEmail = linkEmail,
googlePayState = googlePayState,
isGooglePayReady = isGooglePayReady,
buttonsEnabled = buttonsEnabled,
paymentMethodTypes = paymentMethodTypes,
googlePayLauncherConfig = null,
Expand Down Expand Up @@ -138,14 +137,6 @@ internal class PaymentOptionsViewModel @Inject constructor(
init {
SessionSavedStateHandler.attachTo(this, savedStateHandle)

savedStateHandle[SAVE_GOOGLE_PAY_STATE] = if (args.state.isGooglePayReady) {
GooglePayState.Available
} else {
GooglePayState.NotAvailable
}

val linkState = args.state.linkState

viewModelScope.launch {
linkHandler.processingState.collect { processingState ->
handleLinkProcessingState(processingState)
Expand All @@ -155,7 +146,7 @@ internal class PaymentOptionsViewModel @Inject constructor(
// This is bad, but I don't think there's a better option
PaymentSheet.FlowController.linkHandler = linkHandler

linkHandler.setupLink(linkState)
linkHandler.setupLink(args.state.linkState)

// After recovering from don't keep activities the paymentMethodMetadata will be saved,
// calling setPaymentMethodMetadata would require the repository be initialized, which
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ import com.stripe.android.paymentsheet.paymentdatacollection.bacs.BacsMandateCon
import com.stripe.android.paymentsheet.paymentdatacollection.bacs.BacsMandateConfirmationResult
import com.stripe.android.paymentsheet.paymentdatacollection.bacs.BacsMandateData
import com.stripe.android.paymentsheet.repositories.CustomerRepository
import com.stripe.android.paymentsheet.state.GooglePayState
import com.stripe.android.paymentsheet.state.PaymentSheetLoader
import com.stripe.android.paymentsheet.state.PaymentSheetState
import com.stripe.android.paymentsheet.state.WalletsProcessingState
Expand Down Expand Up @@ -218,14 +217,14 @@ internal class PaymentSheetViewModel @Inject internal constructor(
override val walletsState: StateFlow<WalletsState?> = combineAsStateFlow(
linkHandler.isLinkEnabled,
linkConfigurationCoordinator.emailFlow,
googlePayState,
paymentMethodMetadata.mapAsStateFlow { it?.isGooglePayReady == true },
buttonsEnabled,
paymentMethodMetadata.mapAsStateFlow { it?.supportedPaymentMethodTypes().orEmpty() },
) { isLinkAvailable, linkEmail, googlePayState, buttonsEnabled, paymentMethodTypes ->
) { isLinkAvailable, linkEmail, isGooglePayReady, buttonsEnabled, paymentMethodTypes ->
WalletsState.create(
isLinkAvailable = isLinkAvailable,
linkEmail = linkEmail,
googlePayState = googlePayState,
isGooglePayReady = isGooglePayReady,
buttonsEnabled = buttonsEnabled,
paymentMethodTypes = paymentMethodTypes,
googlePayLauncherConfig = googlePayLauncherConfig,
Expand Down Expand Up @@ -373,17 +372,9 @@ internal class PaymentSheetViewModel @Inject internal constructor(

updateSelection(state.paymentSelection)

savedStateHandle[SAVE_GOOGLE_PAY_STATE] = if (state.isGooglePayReady) {
GooglePayState.Available
} else {
GooglePayState.NotAvailable
}

setPaymentMethodMetadata(state.paymentMethodMetadata)

val linkState = state.linkState

linkHandler.setupLink(linkState)
linkHandler.setupLink(state.linkState)

val pendingFailedPaymentResult = awaitPaymentResult() as? InternalPaymentResult.Failed
val errorMessage = pendingFailedPaymentResult?.throwable?.stripeErrorMessage()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import com.stripe.android.paymentsheet.navigation.NavigationHandler
import com.stripe.android.paymentsheet.navigation.PaymentSheetScreen
import com.stripe.android.paymentsheet.repositories.CustomerRepository
import com.stripe.android.paymentsheet.state.CustomerState
import com.stripe.android.paymentsheet.state.GooglePayState
import com.stripe.android.paymentsheet.ui.DefaultAddPaymentMethodInteractor
import com.stripe.android.paymentsheet.ui.EditPaymentMethodViewInteractor
import com.stripe.android.paymentsheet.ui.ModifiableEditPaymentMethodViewInteractor
Expand Down Expand Up @@ -43,7 +42,7 @@ internal class SavedPaymentMethodMutator(
private val updateSelection: (PaymentSelection?) -> Unit,
private val isLiveModeProvider: () -> Boolean,
isCbcEligible: () -> Boolean,
googlePayState: StateFlow<GooglePayState>,
isGooglePayReady: StateFlow<Boolean>,
isLinkEnabled: StateFlow<Boolean?>,
isNotPaymentFlow: Boolean,
) {
Expand All @@ -66,7 +65,7 @@ internal class SavedPaymentMethodMutator(
private val paymentOptionsItemsMapper: PaymentOptionsItemsMapper by lazy {
PaymentOptionsItemsMapper(
paymentMethods = paymentMethods,
googlePayState = googlePayState,
isGooglePayReady = isGooglePayReady,
isLinkEnabled = isLinkEnabled,
isNotPaymentFlow = isNotPaymentFlow,
nameProvider = providePaymentMethodName,
Expand Down Expand Up @@ -297,7 +296,7 @@ internal class SavedPaymentMethodMutator(
isCbcEligible = {
viewModel.paymentMethodMetadata.value?.cbcEligibility is CardBrandChoiceEligibility.Eligible
},
googlePayState = viewModel.googlePayState,
isGooglePayReady = viewModel.paymentMethodMetadata.mapAsStateFlow { it?.isGooglePayReady == true },
isLinkEnabled = viewModel.linkHandler.isLinkEnabled,
isNotPaymentFlow = !viewModel.isCompleteFlow,
isLiveModeProvider = { requireNotNull(viewModel.paymentMethodMetadata.value).stripeIntent.isLiveMode }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ internal class DefaultPaymentSelectionUpdater @Inject constructor() : PaymentSel
code in allowedTypes && paymentMethod in (state.customer?.paymentMethods ?: emptyList())
}
is PaymentSelection.GooglePay -> {
state.isGooglePayReady
state.paymentMethodMetadata.isGooglePayReady
}
is PaymentSelection.Link -> {
state.linkState != null
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -96,19 +96,18 @@ internal class DefaultPaymentSheetLoader @Inject constructor(
defaultPaymentMethodId = savedPaymentMethodSelection?.id,
).getOrThrow()

val isGooglePayReady = isGooglePayReady(paymentSheetConfiguration, elementsSession)

val metadata = createPaymentMethodMetadata(
paymentSheetConfiguration = paymentSheetConfiguration,
elementsSession = elementsSession,
isGooglePayReady = isGooglePayReady
)

val isGooglePayReady = async {
isGooglePayReady(paymentSheetConfiguration, elementsSession)
}

val savedSelection = async {
retrieveSavedSelection(
config = paymentSheetConfiguration,
isGooglePayReady = isGooglePayReady.await(),
isGooglePayReady = isGooglePayReady,
elementsSession = elementsSession
)
}
Expand Down Expand Up @@ -147,9 +146,7 @@ internal class DefaultPaymentSheetLoader @Inject constructor(
val state = PaymentSheetState.Full(
config = paymentSheetConfiguration,
customer = customer.await(),
isGooglePayReady = isGooglePayReady.await(),
linkState = linkState.await(),
isEligibleForCardBrandChoice = elementsSession.isEligibleForCardBrandChoice,
paymentSelection = initialPaymentSelection.await(),
validationError = stripeIntent.validate(),
paymentMethodMetadata = metadata,
Expand Down Expand Up @@ -182,6 +179,7 @@ internal class DefaultPaymentSheetLoader @Inject constructor(
private fun createPaymentMethodMetadata(
paymentSheetConfiguration: PaymentSheet.Configuration,
elementsSession: ElementsSession,
isGooglePayReady: Boolean,
): PaymentMethodMetadata {
val sharedDataSpecsResult = lpmRepository.getSharedDataSpecs(
stripeIntent = elementsSession.stripeIntent,
Expand All @@ -205,7 +203,8 @@ internal class DefaultPaymentSheetLoader @Inject constructor(
elementsSession = elementsSession,
configuration = paymentSheetConfiguration,
sharedDataSpecs = sharedDataSpecsResult.sharedDataSpecs,
externalPaymentMethodSpecs = externalPaymentMethodSpecs
externalPaymentMethodSpecs = externalPaymentMethodSpecs,
isGooglePayReady = isGooglePayReady,
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,13 @@ internal sealed interface PaymentSheetState : Parcelable {
data class Full(
val config: PaymentSheet.Configuration,
val customer: CustomerState?,
val isGooglePayReady: Boolean,
val linkState: LinkState?,
val isEligibleForCardBrandChoice: Boolean,
val paymentSelection: PaymentSelection?,
val validationError: PaymentSheetLoadingException?,
val paymentMethodMetadata: PaymentMethodMetadata,
) : PaymentSheetState {
val showSavedPaymentMethods: Boolean
get() = (customer != null && customer.paymentMethods.isNotEmpty()) || isGooglePayReady
get() = (customer != null && customer.paymentMethods.isNotEmpty()) || paymentMethodMetadata.isGooglePayReady

val stripeIntent: StripeIntent
get() = paymentMethodMetadata.stripeIntent
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ internal data class WalletsState(
fun create(
isLinkAvailable: Boolean?,
linkEmail: String?,
googlePayState: GooglePayState,
isGooglePayReady: Boolean,
googlePayButtonType: GooglePayButtonType,
buttonsEnabled: Boolean,
paymentMethodTypes: List<String>,
Expand Down Expand Up @@ -60,7 +60,7 @@ internal data class WalletsState(
isPhoneNumberRequired = it.billingAddressConfig.isPhoneNumberRequired,
)
},
).takeIf { googlePayState.isReadyForUse }
).takeIf { isGooglePayReady }

return if (link != null || googlePay != null) {
WalletsState(
Expand Down
Loading

0 comments on commit 4aa391f

Please sign in to comment.