From 82497ec13a89ac1bfb039bb5b052743194c78c0a Mon Sep 17 00:00:00 2001 From: Michael Shafrir <45020849+mshafrir-stripe@users.noreply.github.com> Date: Tue, 24 Nov 2020 14:36:59 -0500 Subject: [PATCH] Upgrade 3DS2 SDK to 4.1.2 (#3083) Add `sdkTransactionId` and update tests Fixes #3081 --- CHANGELOG.md | 1 + stripe/build.gradle | 2 +- .../stripe/android/StripePaymentController.kt | 15 ++++++++---- .../networking/AnalyticsDataFactory.kt | 2 +- .../android/StripePaymentControllerTest.kt | 24 +++++++++++++------ .../android/model/Stripe3ds2Fixtures.kt | 21 +++++++++------- 6 files changed, 43 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6394688f456..f5a0e7453b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ * [#3046](https://github.com/stripe/stripe-android/pull/3046) Upgrade Gradle to `6.7.1` * [#3056](https://github.com/stripe/stripe-android/pull/3056) Upgrade Kotlin to `1.4.20` * [#3058](https://github.com/stripe/stripe-android/pull/3058) Migrate to Kotlin Parcelize plugin +* [#3083](https://github.com/stripe/stripe-android/pull/3083) Upgrade `stripe-3ds2-android` to `4.1.2` ## 16.1.0 - 2020-11-06 * [#2930](https://github.com/stripe/stripe-android/pull/2930) Upgrade Android Gradle Plugin to `4.1.0` diff --git a/stripe/build.gradle b/stripe/build.gradle index 82013d3ff44..7e7a72db81e 100644 --- a/stripe/build.gradle +++ b/stripe/build.gradle @@ -37,7 +37,7 @@ dependencies { // Api for this import because we use reflection to alter TextInputLayout api "com.google.android.material:material:$materialVersion" - implementation "com.stripe:stripe-3ds2-android:4.1.1" + implementation "com.stripe:stripe-3ds2-android:4.1.2" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinCoroutinesVersion" diff --git a/stripe/src/main/java/com/stripe/android/StripePaymentController.kt b/stripe/src/main/java/com/stripe/android/StripePaymentController.kt index d964c5b96e7..2dcc69d47e4 100644 --- a/stripe/src/main/java/com/stripe/android/StripePaymentController.kt +++ b/stripe/src/main/java/com/stripe/android/StripePaymentController.kt @@ -31,6 +31,7 @@ import com.stripe.android.stripe3ds2.transaction.CompletionEvent import com.stripe.android.stripe3ds2.transaction.MessageVersionRegistry import com.stripe.android.stripe3ds2.transaction.ProtocolErrorEvent import com.stripe.android.stripe3ds2.transaction.RuntimeErrorEvent +import com.stripe.android.stripe3ds2.transaction.SdkTransactionId import com.stripe.android.stripe3ds2.transaction.Stripe3ds2ActivityStarterHost import com.stripe.android.stripe3ds2.transaction.StripeChallengeStatusReceiver import com.stripe.android.stripe3ds2.transaction.Transaction @@ -826,7 +827,8 @@ internal class StripePaymentController internal constructor( activity, stripe3ds2Fingerprint.directoryServerName, false, - config.stripe3ds2Config.uiCustomization.uiCustomization + config.stripe3ds2Config.uiCustomization.uiCustomization, + transaction.sdkTransactionId ) CoroutineScope(workContext).launch { @@ -837,7 +839,7 @@ internal class StripePaymentController internal constructor( stripe3ds2Fingerprint.source, areqParams.sdkAppId, areqParams.sdkReferenceNumber, - areqParams.sdkTransactionId, + areqParams.sdkTransactionId.value, areqParams.deviceData, areqParams.sdkEphemeralPublicKey, areqParams.messageVersion, @@ -1202,7 +1204,8 @@ internal class StripePaymentController internal constructor( context: Context, directoryServerName: String, cancelable: Boolean, - uiCustomization: StripeUiCustomization + uiCustomization: StripeUiCustomization, + sdkTransactionId: SdkTransactionId ) class Default : ChallengeProgressActivityStarter { @@ -1210,13 +1213,15 @@ internal class StripePaymentController internal constructor( context: Context, directoryServerName: String, cancelable: Boolean, - uiCustomization: StripeUiCustomization + uiCustomization: StripeUiCustomization, + sdkTransactionId: SdkTransactionId ) { ChallengeProgressActivity.show( context, directoryServerName, cancelable, - uiCustomization + uiCustomization, + sdkTransactionId ) } } diff --git a/stripe/src/main/java/com/stripe/android/networking/AnalyticsDataFactory.kt b/stripe/src/main/java/com/stripe/android/networking/AnalyticsDataFactory.kt index 8dde5a497dc..8710af14719 100644 --- a/stripe/src/main/java/com/stripe/android/networking/AnalyticsDataFactory.kt +++ b/stripe/src/main/java/com/stripe/android/networking/AnalyticsDataFactory.kt @@ -111,7 +111,7 @@ internal class AnalyticsDataFactory @VisibleForTesting internal constructor( val errorMessage = protocolErrorEvent.errorMessage val errorData = mapOf( "type" to "protocol_error_event", - "sdk_trans_id" to protocolErrorEvent.sdkTransactionId, + "sdk_trans_id" to protocolErrorEvent.sdkTransactionId?.value, "error_code" to errorMessage.errorCode, "error_description" to errorMessage.errorDescription, "error_details" to errorMessage.errorDetails, diff --git a/stripe/src/test/java/com/stripe/android/StripePaymentControllerTest.kt b/stripe/src/test/java/com/stripe/android/StripePaymentControllerTest.kt index f7edee8a86d..6f3896661ad 100644 --- a/stripe/src/test/java/com/stripe/android/StripePaymentControllerTest.kt +++ b/stripe/src/test/java/com/stripe/android/StripePaymentControllerTest.kt @@ -45,6 +45,7 @@ import com.stripe.android.stripe3ds2.transaction.ErrorMessage import com.stripe.android.stripe3ds2.transaction.MessageVersionRegistry import com.stripe.android.stripe3ds2.transaction.ProtocolErrorEvent import com.stripe.android.stripe3ds2.transaction.RuntimeErrorEvent +import com.stripe.android.stripe3ds2.transaction.SdkTransactionId import com.stripe.android.stripe3ds2.transaction.Stripe3ds2ActivityStarterHost import com.stripe.android.stripe3ds2.transaction.Transaction import com.stripe.android.utils.ParcelUtils @@ -58,6 +59,7 @@ import kotlinx.coroutines.test.runBlockingTest import kotlinx.coroutines.test.setMain import org.junit.runner.RunWith import org.robolectric.RobolectricTestRunner +import java.util.UUID import kotlin.test.BeforeTest import kotlin.test.Test @@ -67,7 +69,13 @@ internal class StripePaymentControllerTest { private val activity: Activity = mock() private val threeDs2Service: StripeThreeDs2Service = mock() - private val transaction: Transaction = mock() + private val sdkTransactionId = mock().also { + whenever(it.value).thenReturn(UUID.randomUUID().toString()) + } + private val transaction: Transaction = mock().also { + whenever(it.sdkTransactionId) + .thenReturn(sdkTransactionId) + } private val paymentAuthResultCallback: ApiResultCallback = mock() private val setupAuthResultCallback: ApiResultCallback = mock() private val sourceCallback: ApiResultCallback = mock() @@ -98,7 +106,7 @@ internal class StripePaymentControllerTest { Dispatchers.setMain(testDispatcher) runBlocking { whenever(transaction.createAuthenticationRequestParameters()) - .thenReturn(Stripe3ds2Fixtures.AREQ_PARAMS) + .thenReturn(Stripe3ds2Fixtures.createAreqParams(sdkTransactionId)) } whenever(activity.applicationContext) .thenReturn(context) @@ -145,7 +153,8 @@ internal class StripePaymentControllerTest { eq(activity), eq("mastercard"), eq(false), - any() + any(), + eq(sdkTransactionId) ) verify(analyticsRequestExecutor) @@ -198,7 +207,8 @@ internal class StripePaymentControllerTest { eq(activity), eq("american_express"), eq(false), - any() + any(), + eq(sdkTransactionId) ) } @@ -312,7 +322,7 @@ internal class StripePaymentControllerTest { @Test fun test3ds2Receiver_whenCompleted_shouldFireAnalyticsRequest() { val completionEvent = CompletionEvent( - sdkTransactionId = "8dd3413f-0b45-4234-bc45-6cc40fb1b0f1", + sdkTransactionId = sdkTransactionId, transactionStatus = "C" ) @@ -440,7 +450,7 @@ internal class StripePaymentControllerTest { @Test fun test3ds2Receiver_whenProtocolError_shouldFireAnalyticsRequest() { val protocolErrorEvent = ProtocolErrorEvent( - sdkTransactionId = "8dd3413f-0b45-4234-bc45-6cc40fb1b0f1", + sdkTransactionId = sdkTransactionId, errorMessage = ErrorMessage( errorCode = "201", errorDescription = "Required element missing", @@ -475,7 +485,7 @@ internal class StripePaymentControllerTest { mapOf( "type" to "protocol_error_event", "error_code" to "201", - "sdk_trans_id" to "8dd3413f-0b45-4234-bc45-6cc40fb1b0f1", + "sdk_trans_id" to sdkTransactionId.value, "error_description" to "Required element missing", "error_details" to "eci", "trans_id" to "047f76a6-d1d4-48a2-aa65-786abb6f7f46" diff --git a/stripe/src/test/java/com/stripe/android/model/Stripe3ds2Fixtures.kt b/stripe/src/test/java/com/stripe/android/model/Stripe3ds2Fixtures.kt index 620d604d4bd..f8cad26133f 100644 --- a/stripe/src/test/java/com/stripe/android/model/Stripe3ds2Fixtures.kt +++ b/stripe/src/test/java/com/stripe/android/model/Stripe3ds2Fixtures.kt @@ -1,6 +1,7 @@ package com.stripe.android.model import com.stripe.android.stripe3ds2.transaction.AuthenticationRequestParameters +import com.stripe.android.stripe3ds2.transaction.SdkTransactionId import java.util.UUID internal object Stripe3ds2Fixtures { @@ -12,12 +13,16 @@ internal object Stripe3ds2Fixtures { private const val SDK_REFERENCE_NUMBER = "3DS_LOA_SDK_STIN_12345" private const val SDK_EPHEMERAL_PUBLIC_KEY = "{\"kty\":\"EC\",\"use\":\"sig\",\"crv\":\"P-256\",\"kid\":\"b23da28b-d611-46a8-93af-44ad57ce9c9d\",\"x\":\"hSwyaaAp3ppSGkpt7d9G8wnp3aIXelsZVo05EPpqetg\",\"y\":\"OUVOv9xPh5RYWapla0oz3vCJWRRXlDmppy5BGNeSl-A\"}" - val AREQ_PARAMS = AuthenticationRequestParameters( - deviceData = DEVICE_DATA, - messageVersion = MESSAGE_VERSION, - sdkAppId = SDK_APP_ID, - sdkEphemeralPublicKey = SDK_EPHEMERAL_PUBLIC_KEY, - sdkReferenceNumber = SDK_REFERENCE_NUMBER, - sdkTransactionId = SDK_TRANSACTION_ID - ) + fun createAreqParams( + sdkTransactionId: SdkTransactionId + ): AuthenticationRequestParameters { + return AuthenticationRequestParameters( + deviceData = DEVICE_DATA, + messageVersion = MESSAGE_VERSION, + sdkAppId = SDK_APP_ID, + sdkEphemeralPublicKey = SDK_EPHEMERAL_PUBLIC_KEY, + sdkReferenceNumber = SDK_REFERENCE_NUMBER, + sdkTransactionId = sdkTransactionId + ) + } }