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

Update PaymentMethodsActivity result and PaymentSession.handlePaymentData() logic #1820

Merged
merged 2 commits into from
Nov 13, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
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 @@ -58,8 +58,7 @@ class PaymentSessionActivity : AppCompatActivity() {
errorDialogHandler = ErrorDialogHandler(this)

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

val localBroadcastManager = LocalBroadcastManager.getInstance(this)
broadcastReceiver = object : BroadcastReceiver() {
Expand Down Expand Up @@ -117,7 +116,8 @@ class PaymentSessionActivity : AppCompatActivity() {
// Optionally specify the `PaymentMethod.Type` values to use.
// Defaults to `PaymentMethod.Type.Card`
.setPaymentMethodTypes(listOf(PaymentMethod.Type.Card))
.build())
.build()
)
if (paymentSessionInitialized) {
paymentSession.setCartTotal(2000L)
}
Expand Down
47 changes: 26 additions & 21 deletions stripe/src/main/java/com/stripe/android/PaymentSession.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ class PaymentSession @VisibleForTesting internal constructor(
ActivityStarter<PaymentMethodsActivity, PaymentMethodsActivityStarter.Args>,
private val paymentFlowActivityStarter:
ActivityStarter<PaymentFlowActivity, PaymentFlowActivityStarter.Args>,
paymentSessionData: PaymentSessionData,
private val paymentSessionPrefs: PaymentSessionPrefs
private val paymentSessionPrefs: PaymentSessionPrefs,
paymentSessionData: PaymentSessionData = PaymentSessionData()
) {
/**
* @return the data associated with the instance of this class.
*/
var paymentSessionData: PaymentSessionData = PaymentSessionData()
var paymentSessionData: PaymentSessionData = paymentSessionData
private set
private var paymentSessionListener: PaymentSessionListener? = null
private var config: PaymentSessionConfig = PaymentSessionConfig.EMPTY
Expand All @@ -50,7 +50,6 @@ class PaymentSession @VisibleForTesting internal constructor(
CustomerSession.getInstance(),
PaymentMethodsActivityStarter(activity),
PaymentFlowActivityStarter(activity),
PaymentSessionData(),
PaymentSessionPrefs.create(activity)
)

Expand All @@ -59,14 +58,9 @@ class PaymentSession @VisibleForTesting internal constructor(
CustomerSession.getInstance(),
PaymentMethodsActivityStarter(fragment),
PaymentFlowActivityStarter(fragment),
PaymentSessionData(),
PaymentSessionPrefs.create(fragment.requireActivity())
)

init {
this.paymentSessionData = paymentSessionData
}

/**
* Notify this payment session that it is complete
*/
Expand All @@ -92,19 +86,18 @@ class PaymentSession @VisibleForTesting internal constructor(

when (resultCode) {
Activity.RESULT_CANCELED -> {
fetchCustomer()
if (requestCode == PaymentMethodsActivityStarter.REQUEST_CODE) {
// If resultCode of `PaymentMethodsActivity` is `Activity.RESULT_CANCELED`,
// the user tapped back via the toolbar or device back button.
onPaymentMethodResult(data)
} else {
fetchCustomer()
}
return false
}
Activity.RESULT_OK -> when (requestCode) {
PaymentMethodsActivityStarter.REQUEST_CODE -> {
val result =
PaymentMethodsActivityStarter.Result.fromIntent(data)
val paymentMethod = result?.paymentMethod
persistPaymentMethod(paymentMethod)
paymentSessionData.paymentMethod = paymentMethod
paymentSessionData.updateIsPaymentReadyToCharge(config)
paymentSessionListener?.onPaymentSessionDataChanged(paymentSessionData)
paymentSessionListener?.onCommunicatingStateChanged(false)
onPaymentMethodResult(data)
return true
}
PaymentFlowActivityStarter.REQUEST_CODE -> {
Expand All @@ -123,10 +116,24 @@ class PaymentSession @VisibleForTesting internal constructor(
}
}

private fun onPaymentMethodResult(data: Intent) {
val paymentMethod: PaymentMethod? =
PaymentMethodsActivityStarter.Result.fromIntent(data)?.paymentMethod
persistPaymentMethod(paymentMethod)
dispatchUpdates()
}

private fun dispatchUpdates() {
paymentSessionData.updateIsPaymentReadyToCharge(config)
paymentSessionListener?.onPaymentSessionDataChanged(paymentSessionData)
paymentSessionListener?.onCommunicatingStateChanged(false)
}

private fun persistPaymentMethod(paymentMethod: PaymentMethod?) {
customerSession.cachedCustomer?.id?.let { customerId ->
paymentSessionPrefs.saveSelectedPaymentMethodId(customerId, paymentMethod?.id)
}
paymentSessionData.paymentMethod = paymentMethod
}

/**
Expand Down Expand Up @@ -283,9 +290,7 @@ class PaymentSession @VisibleForTesting internal constructor(
customerSession.retrieveCurrentCustomer(
object : CustomerSession.CustomerRetrievalListener {
override fun onCustomerRetrieved(customer: Customer) {
paymentSessionData.updateIsPaymentReadyToCharge(config)
paymentSessionListener?.onPaymentSessionDataChanged(paymentSessionData)
paymentSessionListener?.onCommunicatingStateChanged(false)
dispatchUpdates()
}

override fun onError(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ class PaymentMethodsActivity : AppCompatActivity() {
payment_methods_recycler.adapter = adapter
payment_methods_recycler.listener = object : PaymentMethodsRecyclerView.Listener {
override fun onPaymentMethodSelected(paymentMethod: PaymentMethod) {
setSelectionAndFinish(paymentMethod)
finishWithPaymentMethod(paymentMethod)
}
}

Expand All @@ -119,7 +119,7 @@ class PaymentMethodsActivity : AppCompatActivity() {
}

override fun onSupportNavigateUp(): Boolean {
setSelectionAndFinish(adapter.selectedPaymentMethod)
finishWithPaymentMethod(adapter.selectedPaymentMethod, Activity.RESULT_CANCELED)
return true
}

Expand Down Expand Up @@ -163,7 +163,7 @@ class PaymentMethodsActivity : AppCompatActivity() {
}

override fun onBackPressed() {
setSelectionAndFinish(adapter.selectedPaymentMethod)
finishWithPaymentMethod(adapter.selectedPaymentMethod, Activity.RESULT_CANCELED)
}

private fun fetchCustomerPaymentMethods() {
Expand All @@ -186,14 +186,12 @@ class PaymentMethodsActivity : AppCompatActivity() {
}
}

@JvmSynthetic
internal fun setSelectionAndFinish(paymentMethod: PaymentMethod?) {
finishWithPaymentMethod(paymentMethod)
}

private fun finishWithPaymentMethod(paymentMethod: PaymentMethod?) {
private fun finishWithPaymentMethod(
paymentMethod: PaymentMethod?,
resultCode: Int = Activity.RESULT_OK
) {
setResult(
Activity.RESULT_OK,
resultCode,
Intent().also {
if (paymentMethod != null) {
it.putExtras(PaymentMethodsActivityStarter.Result(paymentMethod).toBundle())
Expand Down
38 changes: 23 additions & 15 deletions stripe/src/test/java/com/stripe/android/PaymentSessionTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import com.nhaarman.mockitokotlin2.KArgumentCaptor
import com.nhaarman.mockitokotlin2.any
import com.nhaarman.mockitokotlin2.argumentCaptor
import com.nhaarman.mockitokotlin2.eq
import com.nhaarman.mockitokotlin2.verify
import com.stripe.android.model.Customer
import com.stripe.android.model.CustomerFixtures
import com.stripe.android.model.PaymentMethod
Expand Down Expand Up @@ -38,7 +39,6 @@ import org.mockito.Mockito.doAnswer
import org.mockito.Mockito.mock
import org.mockito.Mockito.never
import org.mockito.Mockito.reset
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
import org.robolectric.RobolectricTestRunner

Expand Down Expand Up @@ -111,11 +111,11 @@ class PaymentSessionTest {

val paymentSession = PaymentSession(activity)
paymentSession.init(paymentSessionListener, PaymentSessionConfig.Builder().build())
verify<PaymentSession.PaymentSessionListener>(paymentSessionListener)
verify(paymentSessionListener)
.onCommunicatingStateChanged(eq(true))
verify<PaymentSession.PaymentSessionListener>(paymentSessionListener)
verify(paymentSessionListener)
.onPaymentSessionDataChanged(any())
verify<PaymentSession.PaymentSessionListener>(paymentSessionListener)
verify(paymentSessionListener)
.onCommunicatingStateChanged(eq(false))
}

Expand All @@ -129,7 +129,7 @@ class PaymentSessionTest {
paymentSession.init(paymentSessionListener, PaymentSessionConfig.Builder().build())
paymentSession.setCartTotal(500L)

verify<PaymentSession.PaymentSessionListener>(paymentSessionListener)
verify(paymentSessionListener)
.onPaymentSessionDataChanged(paymentSessionDataArgumentCaptor.capture())
val data = paymentSessionDataArgumentCaptor.firstValue
assertNotNull(data)
Expand All @@ -144,15 +144,15 @@ class PaymentSessionTest {
paymentSession.init(paymentSessionListener, PaymentSessionConfig.Builder().build())

// We have already tested the functionality up to here.
reset<PaymentSession.PaymentSessionListener>(paymentSessionListener)
reset(paymentSessionListener)

val result = PaymentMethodsActivityStarter.Result(PaymentMethodFixtures.CARD_PAYMENT_METHOD)
val handled = paymentSession.handlePaymentData(
PaymentMethodsActivityStarter.REQUEST_CODE, RESULT_OK,
Intent().putExtras(result.toBundle()))
assertTrue(handled)

verify<PaymentSession.PaymentSessionListener>(paymentSessionListener)
verify(paymentSessionListener)
.onPaymentSessionDataChanged(paymentSessionDataArgumentCaptor.capture())
val data = paymentSessionDataArgumentCaptor.firstValue
assertNotNull(data)
Expand Down Expand Up @@ -280,7 +280,7 @@ class PaymentSessionTest {
val loggingTokens = customerSession.productUsageTokens
assertEquals(2, loggingTokens.size)

reset<PaymentSession.PaymentSessionListener>(paymentSessionListener)
reset(paymentSessionListener)

paymentSession.onCompleted()
assertTrue(customerSession.productUsageTokens.isEmpty())
Expand All @@ -297,7 +297,7 @@ class PaymentSessionTest {

paymentSession.setCartTotal(300L)

verify<PaymentSession.PaymentSessionListener>(paymentSessionListener)
verify(paymentSessionListener)
.onPaymentSessionDataChanged(paymentSessionDataArgumentCaptor.capture())
val bundle = Bundle()
paymentSession.savePaymentSessionInstanceState(bundle)
Expand All @@ -307,7 +307,7 @@ class PaymentSessionTest {
mock(PaymentSession.PaymentSessionListener::class.java)

paymentSession.init(secondListener, PaymentSessionConfig.Builder().build(), bundle)
verify<PaymentSession.PaymentSessionListener>(secondListener)
verify(secondListener)
.onPaymentSessionDataChanged(paymentSessionDataArgumentCaptor.capture())

val secondPaymentSessionData = paymentSessionDataArgumentCaptor.firstValue
Expand All @@ -321,15 +321,23 @@ class PaymentSessionTest {
fun handlePaymentData_withInvalidRequestCode_aborts() {
val paymentSession = createPaymentSession()
assertFalse(paymentSession.handlePaymentData(-1, RESULT_CANCELED, Intent()))
verify<CustomerSession>(customerSession, never()).retrieveCurrentCustomer(any())
verify(customerSession, never()).retrieveCurrentCustomer(any())
}

@Test
fun handlePaymentData_withValidRequestCodeAndCanceledResult_retrievesCustomer() {
fun handlePaymentData_withPaymentMethodsActivityRequestCodeAndCanceledResult_doesNotRetrieveCustomer() {
val paymentSession = createPaymentSession()
assertFalse(paymentSession.handlePaymentData(PaymentMethodsActivityStarter.REQUEST_CODE,
RESULT_CANCELED, Intent()))
verify<CustomerSession>(customerSession).retrieveCurrentCustomer(any())
verify(customerSession, never()).retrieveCurrentCustomer(any())
}

@Test
fun handlePaymentData_withPaymentFlowActivityRequestCodeAndCanceledResult_retrievesCustomer() {
val paymentSession = createPaymentSession()
assertFalse(paymentSession.handlePaymentData(PaymentFlowActivityStarter.REQUEST_CODE,
RESULT_CANCELED, Intent()))
verify(customerSession).retrieveCurrentCustomer(any())
}

private fun createPaymentSession(): PaymentSession {
Expand All @@ -338,8 +346,8 @@ class PaymentSessionTest {
customerSession,
paymentMethodsActivityStarter,
paymentFlowActivityStarter,
paymentSessionData,
paymentSessionPrefs
paymentSessionPrefs,
paymentSessionData
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,9 +193,7 @@ class PaymentMethodsActivityTest : BaseViewTest<PaymentMethodsActivity>(PaymentM
paymentMethodsAdapter.selectedPaymentMethodId =
PaymentMethodFixtures.CARD_PAYMENT_METHODS[0].id

paymentMethodsActivity.setSelectionAndFinish(
PaymentMethodFixtures.CARD_PAYMENT_METHODS[0]
)
paymentMethodsActivity.onBackPressed()

// Now it should be gone.
assertEquals(View.GONE, progressBar.visibility)
Expand Down