Skip to content

Commit

Permalink
Simplify PaymentSession state and lifecycle management (#2165)
Browse files Browse the repository at this point in the history
Summary
- Create `PaymentSessionViewModel` and integrate in `PaymentSession`
- Remove `savedInstanceState` argument from `PaymentSession#init()`
- Remove `PaymentSession#savePaymentSessionInstanceState()`
- Remove `PaymentSession#onDestroy()` - the `listener` instance
  is now released automatically
- In `PaymentSession#init()`, immediately call the `listener` when
  `shouldPrefetchCustomer` is false
- Move `CustomerSession` initialization in example app to
  `Application` subclass

Motivation
Simplify `PaymentSession` state management and API. It is
no longer necessary to pass a state `Bundle` and manage
lifecycle events.

Testing
Add unit tests
Manually verify with both `Activity` and `Fragment`
  • Loading branch information
mshafrir-stripe authored Feb 11, 2020
1 parent 80a704c commit b5db815
Show file tree
Hide file tree
Showing 9 changed files with 348 additions and 224 deletions.
13 changes: 5 additions & 8 deletions example/src/main/java/com/stripe/example/ExampleApplication.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@ import android.os.StrictMode
import androidx.multidex.MultiDexApplication
import com.facebook.stetho.Stetho
import com.stripe.android.CustomerSession
import com.stripe.android.EphemeralKeyProvider
import com.stripe.android.EphemeralKeyUpdateListener
import com.stripe.android.PaymentConfiguration
import com.stripe.example.service.ExampleEphemeralKeyProvider
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
Expand Down Expand Up @@ -38,12 +37,10 @@ class ExampleApplication : MultiDexApplication() {
Stetho.initializeWithDefaults(this@ExampleApplication)
}

// initialize empty CustomerSession
CustomerSession.initCustomerSession(this,
object : EphemeralKeyProvider {
override fun createEphemeralKey(apiVersion: String, keyUpdateListener: EphemeralKeyUpdateListener) {
}
}
CustomerSession.initCustomerSession(
this,
ExampleEphemeralKeyProvider(this),
false
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import com.stripe.android.model.Customer
import com.stripe.android.model.PaymentMethod
import com.stripe.android.view.PaymentMethodsActivityStarter
import com.stripe.example.R
import com.stripe.example.service.ExampleEphemeralKeyProvider
import kotlinx.android.synthetic.main.activity_customer_session.*

/**
Expand All @@ -28,11 +27,6 @@ class CustomerSessionActivity : AppCompatActivity() {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_customer_session)
setTitle(R.string.customer_payment_data_example)
CustomerSession.initCustomerSession(
this,
ExampleEphemeralKeyProvider(this),
false
)

progress_bar.visibility = View.VISIBLE
CustomerSession.getInstance().retrieveCurrentCustomer(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import com.stripe.example.R
import com.stripe.example.StripeFactory
import com.stripe.example.module.BackendApiFactory
import com.stripe.example.service.BackendApi
import com.stripe.example.service.ExampleEphemeralKeyProvider
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.schedulers.Schedulers
Expand All @@ -50,8 +49,8 @@ class FragmentExamplesActivity : AppCompatActivity() {

val newFragment = LauncherFragment()

val ft = supportFragmentManager.beginTransaction()
ft.add(R.id.root, newFragment, LauncherFragment::class.java.simpleName)
supportFragmentManager.beginTransaction()
.replace(R.id.root, newFragment, LauncherFragment::class.java.simpleName)
.commit()
}

Expand Down Expand Up @@ -275,10 +274,6 @@ class FragmentExamplesActivity : AppCompatActivity() {
}

private fun createCustomerSession(): CustomerSession {
CustomerSession.initCustomerSession(
requireContext(),
ExampleEphemeralKeyProvider(requireContext())
)
val customerSession = CustomerSession.getInstance()
customerSession.retrieveCurrentCustomer(
object : CustomerSession.CustomerRetrievalListener {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import com.stripe.android.view.BillingAddressFields
import com.stripe.android.view.PaymentUtils
import com.stripe.android.view.ShippingInfoWidget
import com.stripe.example.R
import com.stripe.example.service.ExampleEphemeralKeyProvider
import kotlinx.android.synthetic.main.activity_payment_session.*
import java.util.Currency
import java.util.Locale
Expand All @@ -45,9 +44,7 @@ class PaymentSessionActivity : AppCompatActivity() {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_payment_session)

progress_bar.visibility = View.VISIBLE

paymentSession = createPaymentSession(savedInstanceState)
paymentSession = createPaymentSession(savedInstanceState == null)

btn_select_payment_method.setOnClickListener {
paymentSession.presentPaymentMethodSelection()
Expand All @@ -57,21 +54,17 @@ class PaymentSessionActivity : AppCompatActivity() {
}
}

private fun createCustomerSession(): CustomerSession {
CustomerSession.initCustomerSession(
this,
ExampleEphemeralKeyProvider(this),
false
)
return CustomerSession.getInstance()
}

private fun createPaymentSession(
savedInstanceState: Bundle?,
shouldPrefetchCustomer: Boolean = true
shouldPrefetchCustomer: Boolean = false
): PaymentSession {
if (shouldPrefetchCustomer) {
disableUi()
} else {
enableUi()
}

// CustomerSession only needs to be initialized once per app.
val customerSession = createCustomerSession()
val customerSession = CustomerSession.getInstance()

val paymentSession = PaymentSession(
activity = this,
Expand All @@ -96,8 +89,7 @@ class PaymentSessionActivity : AppCompatActivity() {
.build()
)
paymentSession.init(
listener = PaymentSessionListenerImpl(this, customerSession),
savedInstanceState = savedInstanceState
listener = PaymentSessionListenerImpl(this, customerSession)
)
paymentSession.setCartTotal(2000L)

Expand Down Expand Up @@ -159,22 +151,12 @@ class PaymentSessionActivity : AppCompatActivity() {
paymentSession.handlePaymentData(requestCode, resultCode, data ?: Intent())
}

override fun onDestroy() {
paymentSession.onDestroy()
super.onDestroy()
}

override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
paymentSession.savePaymentSessionInstanceState(outState)
}

private fun onPaymentSessionDataChanged(
customerSession: CustomerSession,
data: PaymentSessionData
) {
paymentSessionData = data
progress_bar.visibility = View.VISIBLE
disableUi()
customerSession.retrieveCurrentCustomer(
PaymentSessionChangeCustomerRetrievalListener(this)
)
Expand All @@ -186,6 +168,12 @@ class PaymentSessionActivity : AppCompatActivity() {
btn_start_payment_flow.isEnabled = true
}

private fun disableUi() {
progress_bar.visibility = View.VISIBLE
btn_select_payment_method.isEnabled = false
btn_start_payment_flow.isEnabled = false
}

private fun onCustomerRetrieved() {
enableUi()

Expand Down Expand Up @@ -239,10 +227,10 @@ class PaymentSessionActivity : AppCompatActivity() {
BackgroundTaskTracker.onStart()
}

listenerActivity?.progress_bar?.visibility = if (isCommunicating) {
View.VISIBLE
if (isCommunicating) {
listenerActivity?.disableUi()
} else {
View.INVISIBLE
listenerActivity?.enableUi()
}
}

Expand Down
Loading

0 comments on commit b5db815

Please sign in to comment.