Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate PaymentController to PaymentLauncher within PaymentSheet components. #4159

Merged
merged 16 commits into from
Sep 3, 2021
Merged
Show file tree
Hide file tree
Changes from 8 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
9 changes: 8 additions & 1 deletion payments-core/api/payments-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -5047,6 +5047,13 @@ public abstract class com/stripe/android/networking/StripeRequest {
protected final fun getQuery ()Ljava/lang/String;
}

public final class com/stripe/android/payments/PaymentFlowFailureMessageFactory {
skyler-stripe marked this conversation as resolved.
Show resolved Hide resolved
public static final field $stable I
public fun <init> (Landroid/content/Context;)V
public final fun create (Lcom/stripe/android/model/StripeIntent;)Ljava/lang/String;
public final fun create (Lcom/stripe/android/model/StripeIntent;I)Ljava/lang/String;
}

public abstract class com/stripe/android/payments/PaymentFlowResult {
public static final field $stable I
}
Expand Down Expand Up @@ -5575,7 +5582,7 @@ public final class com/stripe/android/payments/paymentlauncher/PaymentResult$Fai
public fun writeToParcel (Landroid/os/Parcel;I)V
}

public final class com/stripe/android/payments/paymentlauncher/StripePaymentLauncher : com/stripe/android/payments/core/injection/Injector, com/stripe/android/payments/paymentlauncher/PaymentLauncher {
public class com/stripe/android/payments/paymentlauncher/StripePaymentLauncher : com/stripe/android/payments/core/injection/Injector, com/stripe/android/payments/paymentlauncher/PaymentLauncher {
public static final field $stable I
public fun confirm (Lcom/stripe/android/model/ConfirmPaymentIntentParams;)V
public fun confirm (Lcom/stripe/android/model/ConfirmSetupIntentParams;)V
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,30 @@
package com.stripe.android.payments

import android.content.Context
import androidx.annotation.RestrictTo
import com.stripe.android.R
import com.stripe.android.StripeIntentResult
import com.stripe.android.model.PaymentIntent
import com.stripe.android.model.SetupIntent
import com.stripe.android.model.StripeIntent

internal class PaymentFlowFailureMessageFactory(
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
skyler-stripe marked this conversation as resolved.
Show resolved Hide resolved
class PaymentFlowFailureMessageFactory(
private val context: Context
) {
fun create(
intent: StripeIntent,
@StripeIntentResult.Outcome outcome: Int
) = when {
outcome == StripeIntentResult.Outcome.TIMEDOUT -> {
) = when (outcome) {
StripeIntentResult.Outcome.TIMEDOUT -> {
context.resources.getString(R.string.stripe_failure_reason_timed_out)
}
else -> create(intent)
}

fun create(
intent: StripeIntent,
) = when {
(intent.status == StripeIntent.Status.RequiresPaymentMethod) ||
(intent.status == StripeIntent.Status.RequiresAction) -> {
when (intent) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import kotlin.coroutines.CoroutineContext
* handle next actions for intents.
*/
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
class StripePaymentLauncher @AssistedInject internal constructor(
open class StripePaymentLauncher @AssistedInject internal constructor(
@Assisted(PUBLISHABLE_KEY) publishableKeyProvider: () -> String,
@Assisted(STRIPE_ACCOUNT_ID) stripeAccountIdProvider: () -> String?,
@Assisted private val hostActivityLauncher: ActivityResultLauncher<PaymentLauncherContract.Args>,
Expand Down
6 changes: 3 additions & 3 deletions paymentsheet/api/paymentsheet.api
Original file line number Diff line number Diff line change
Expand Up @@ -271,11 +271,11 @@ public abstract interface class com/stripe/android/paymentsheet/PaymentSheetResu
}

public final class com/stripe/android/paymentsheet/PaymentSheetViewModel_Factory : dagger/internal/Factory {
public fun <init> (Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;)V
public static fun create (Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;)Lcom/stripe/android/paymentsheet/PaymentSheetViewModel_Factory;
public fun <init> (Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;)V
public static fun create (Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;Ljavax/inject/Provider;)Lcom/stripe/android/paymentsheet/PaymentSheetViewModel_Factory;
public fun get ()Lcom/stripe/android/paymentsheet/PaymentSheetViewModel;
public synthetic fun get ()Ljava/lang/Object;
public static fun newInstance (Landroid/app/Application;Lcom/stripe/android/paymentsheet/PaymentSheetContract$Args;Lcom/stripe/android/paymentsheet/analytics/EventReporter;Ldagger/Lazy;Lcom/stripe/android/paymentsheet/repositories/StripeIntentRepository;Lcom/stripe/android/paymentsheet/model/StripeIntentValidator;Lcom/stripe/android/paymentsheet/repositories/CustomerRepository;Ljavax/inject/Provider;Lcom/stripe/android/paymentsheet/PrefsRepository;Lcom/stripe/android/PaymentController;Lcom/stripe/android/googlepaylauncher/GooglePayPaymentMethodLauncherFactory;Lcom/stripe/android/Logger;Lkotlin/coroutines/CoroutineContext;)Lcom/stripe/android/paymentsheet/PaymentSheetViewModel;
public static fun newInstance (Landroid/app/Application;Lcom/stripe/android/paymentsheet/PaymentSheetContract$Args;Lcom/stripe/android/paymentsheet/analytics/EventReporter;Ldagger/Lazy;Lcom/stripe/android/paymentsheet/repositories/StripeIntentRepository;Lcom/stripe/android/paymentsheet/model/StripeIntentValidator;Lcom/stripe/android/paymentsheet/repositories/CustomerRepository;Lcom/stripe/android/paymentsheet/PrefsRepository;Lcom/stripe/android/payments/paymentlauncher/StripePaymentLauncherAssistedFactory;Lcom/stripe/android/googlepaylauncher/GooglePayPaymentMethodLauncherFactory;Lcom/stripe/android/Logger;Lkotlin/coroutines/CoroutineContext;)Lcom/stripe/android/paymentsheet/PaymentSheetViewModel;
}

public final class com/stripe/android/paymentsheet/address/AddressFieldElementRepository_Factory : dagger/internal/Factory {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import com.stripe.android.paymentsheet.model.PaymentSheetViewState
import com.stripe.android.paymentsheet.ui.AnimationConstants
import com.stripe.android.paymentsheet.ui.BaseSheetActivity
import com.stripe.android.paymentsheet.viewmodels.BaseSheetViewModel
import com.stripe.android.view.AuthActivityStarterHost
import kotlinx.coroutines.launch

internal class PaymentSheetActivity : BaseSheetActivity<PaymentSheetResult>() {
Expand Down Expand Up @@ -145,10 +144,7 @@ internal class PaymentSheetActivity : BaseSheetActivity<PaymentSheetResult>() {
val confirmParams = event.getContentIfNotHandled()
if (confirmParams != null) {
lifecycleScope.launch {
viewModel.confirmStripeIntent(
AuthActivityStarterHost.create(this@PaymentSheetActivity),
confirmParams
)
viewModel.confirmStripeIntent(confirmParams)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,22 @@ import androidx.lifecycle.distinctUntilChanged
import androidx.lifecycle.viewModelScope
import com.stripe.android.Logger
import com.stripe.android.PaymentConfiguration
import com.stripe.android.PaymentController
import com.stripe.android.StripeIntentResult
import com.stripe.android.exception.APIConnectionException
import com.stripe.android.googlepaylauncher.GooglePayEnvironment
import com.stripe.android.googlepaylauncher.GooglePayPaymentMethodLauncher
import com.stripe.android.googlepaylauncher.GooglePayPaymentMethodLauncherContract
import com.stripe.android.googlepaylauncher.GooglePayPaymentMethodLauncherFactory
import com.stripe.android.model.ConfirmPaymentIntentParams
import com.stripe.android.model.ConfirmSetupIntentParams
import com.stripe.android.model.ConfirmStripeIntentParams
import com.stripe.android.model.PaymentIntent
import com.stripe.android.model.PaymentMethod
import com.stripe.android.model.StripeIntent
import com.stripe.android.networking.ApiRequest
import com.stripe.android.payments.PaymentFlowResult
import com.stripe.android.payments.PaymentFlowResultProcessor
import com.stripe.android.payments.PaymentFlowFailureMessageFactory
import com.stripe.android.payments.core.injection.IOContext
import com.stripe.android.payments.paymentlauncher.PaymentLauncher
import com.stripe.android.payments.paymentlauncher.PaymentLauncherContract
import com.stripe.android.payments.paymentlauncher.PaymentResult
import com.stripe.android.payments.paymentlauncher.StripePaymentLauncherAssistedFactory
import com.stripe.android.paymentsheet.analytics.EventReporter
import com.stripe.android.paymentsheet.injection.DaggerPaymentSheetViewModelComponent
import com.stripe.android.paymentsheet.model.ConfirmStripeIntentParamsFactory
Expand All @@ -41,13 +42,10 @@ import com.stripe.android.paymentsheet.repositories.CustomerRepository
import com.stripe.android.paymentsheet.repositories.StripeIntentRepository
import com.stripe.android.paymentsheet.ui.PrimaryButton
import com.stripe.android.paymentsheet.viewmodels.BaseSheetViewModel
import com.stripe.android.view.AuthActivityStarterHost
import dagger.Lazy
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import javax.inject.Inject
import javax.inject.Provider
import javax.inject.Singleton
import kotlin.coroutines.CoroutineContext

Expand Down Expand Up @@ -77,10 +75,8 @@ internal class PaymentSheetViewModel @Inject internal constructor(
private val stripeIntentRepository: StripeIntentRepository,
private val stripeIntentValidator: StripeIntentValidator,
customerRepository: CustomerRepository,
private val paymentFlowResultProcessorProvider:
Provider<PaymentFlowResultProcessor<out StripeIntent, StripeIntentResult<StripeIntent>>>,
prefsRepository: PrefsRepository,
private val paymentController: PaymentController,
private val paymentLauncherFactory: StripePaymentLauncherAssistedFactory,
private val googlePayPaymentMethodLauncherFactory: GooglePayPaymentMethodLauncherFactory,
private val logger: Logger,
@IOContext workContext: CoroutineContext
Expand Down Expand Up @@ -155,26 +151,15 @@ internal class PaymentSheetViewModel @Inject internal constructor(
}
}

internal var paymentLauncher: PaymentLauncher? = null

init {
eventReporter.onInit(config)
if (googlePayLauncherConfig == null) {
_isGooglePayReady.value = false
}
}

private fun apiThrowableToString(throwable: Throwable): String? {
return when (throwable) {
is APIConnectionException -> {
getApplication<Application>().resources.getString(
R.string.stripe_failure_connection_error
)
}
else -> {
throwable.localizedMessage
}
}
}

fun setupGooglePay(
lifecycleScope: CoroutineScope,
activityResultLauncher: ActivityResultLauncher<GooglePayPaymentMethodLauncherContract.Args>
Expand Down Expand Up @@ -301,29 +286,30 @@ internal class PaymentSheetViewModel @Inject internal constructor(
}
}

suspend fun confirmStripeIntent(
authActivityStarterHost: AuthActivityStarterHost,
confirmStripeIntentParams: ConfirmStripeIntentParams
) {
paymentController.startConfirmAndAuth(
authActivityStarterHost,
confirmStripeIntentParams,
ApiRequest.Options(
lazyPaymentConfig.get().publishableKey,
lazyPaymentConfig.get().stripeAccountId
)
)
fun confirmStripeIntent(confirmStripeIntentParams: ConfirmStripeIntentParams) {
when (confirmStripeIntentParams) {
is ConfirmPaymentIntentParams -> {
paymentLauncher?.confirm(confirmStripeIntentParams)
skyler-stripe marked this conversation as resolved.
Show resolved Hide resolved
}
is ConfirmSetupIntentParams -> {
paymentLauncher?.confirm(confirmStripeIntentParams)
}
}
}

fun registerFromActivity(activityResultCaller: ActivityResultCaller) {
paymentController.registerLaunchersWithActivityResultCaller(
activityResultCaller,
::onPaymentFlowResult
paymentLauncher = paymentLauncherFactory.create(
{ lazyPaymentConfig.get().publishableKey },
{ lazyPaymentConfig.get().stripeAccountId },
activityResultCaller.registerForActivityResult(
PaymentLauncherContract(),
::onPaymentResult
)
)
}

fun unregisterFromActivity() {
paymentController.unregisterLaunchers()
paymentLauncher = null
}

private fun confirmPaymentSelection(paymentSelection: PaymentSelection?) {
Expand All @@ -340,16 +326,28 @@ internal class PaymentSheetViewModel @Inject internal constructor(
}
}

private fun onStripeIntentResult(
stripeIntentResult: StripeIntentResult<StripeIntent>
) {
when (stripeIntentResult.outcome) {
StripeIntentResult.Outcome.SUCCEEDED -> {
@VisibleForTesting
fun onPaymentResult(paymentResult: PaymentResult) {
viewModelScope.launch {
runCatching {
stripeIntentRepository.get(args.clientSecret)
skyler-stripe marked this conversation as resolved.
Show resolved Hide resolved
}.fold(
onSuccess = {
processPayment(it, paymentResult)
},
onFailure = ::onFatal
)
}
}

private fun processPayment(stripeIntent: StripeIntent, paymentResult: PaymentResult) {
when (paymentResult) {
PaymentResult.Completed -> {
eventReporter.onPaymentSuccess(selection.value)

// SavedSelection needs to happen after new cards have been saved.
when (selection.value) {
is PaymentSelection.New -> stripeIntentResult.intent.paymentMethod?.let {
is PaymentSelection.New -> stripeIntent.paymentMethod?.let {
PaymentSelection.Saved(it)
}
PaymentSelection.GooglePay -> selection.value
Expand All @@ -367,11 +365,11 @@ internal class PaymentSheetViewModel @Inject internal constructor(
eventReporter.onPaymentFailure(selection.value)

runCatching {
stripeIntentValidator.requireValid(stripeIntentResult.intent)
stripeIntentValidator.requireValid(stripeIntent)
}.fold(
onSuccess = {
resetViewState(
stripeIntentResult.failureMessage
PaymentFlowFailureMessageFactory(getApplication()).create(stripeIntent)
skyler-stripe marked this conversation as resolved.
Show resolved Hide resolved
)
},
onFailure = ::onFatal
Expand Down Expand Up @@ -399,29 +397,6 @@ internal class PaymentSheetViewModel @Inject internal constructor(
}
}

fun onPaymentFlowResult(paymentFlowResult: PaymentFlowResult.Unvalidated) {
viewModelScope.launch {
runCatching {
withContext(workContext) {
paymentFlowResultProcessorProvider.get().processResult(
paymentFlowResult
)
}
}.fold(
onSuccess = {
onStripeIntentResult(it)
},
onFailure = { error ->
selection.value?.let {
eventReporter.onPaymentFailure(it)
}

resetViewState(apiThrowableToString(error))
}
)
}
}

override fun onFatal(throwable: Throwable) {
logger.error("Payment Sheet error", throwable)
_fatal.value = throwable
Expand Down
Loading