Skip to content

Commit

Permalink
Fix logic for entering 3DS2 challenge flow (#1587)
Browse files Browse the repository at this point in the history
`Stripe3ds2AuthResutl.Ares.transStatus` should be used to determine
whether the 3DS2 challenge flow should be entered.

ANDROID-418
  • Loading branch information
mshafrir-stripe authored Sep 19, 2019
1 parent 6849ef0 commit 2dc6ab5
Show file tree
Hide file tree
Showing 5 changed files with 355 additions and 332 deletions.
4 changes: 2 additions & 2 deletions stripe/src/main/java/com/stripe/android/PaymentController.kt
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ internal open class PaymentController @VisibleForTesting constructor(

@VisibleForTesting
fun getClientSecret(data: Intent): String {
return data.getStringExtra(StripeIntentResultExtras.CLIENT_SECRET)
return requireNotNull(data.getStringExtra(StripeIntentResultExtras.CLIENT_SECRET))
}

/**
Expand Down Expand Up @@ -438,7 +438,7 @@ internal open class PaymentController @VisibleForTesting constructor(
override fun onSuccess(result: Stripe3ds2AuthResult) {
val ares = result.ares
if (ares != null) {
if (ares.shouldChallenge()) {
if (ares.isChallenge) {
startChallengeFlow(ares)
} else {
startFrictionlessFlow()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package com.stripe.android.model

import com.stripe.android.ObjectBuilder
import com.stripe.android.model.StripeJsonUtils.optString
import java.util.HashMap
import org.json.JSONArray
import org.json.JSONException
import org.json.JSONObject
Expand Down Expand Up @@ -91,9 +90,10 @@ internal data class Stripe3ds2AuthResult constructor(
private val messageExtension: List<MessageExtension>?,
private val messageType: String?,
private val messageVersion: String?,
private val sdkTransId: String?
private val sdkTransId: String?,
private val transStatus: String?
) {
fun shouldChallenge() = VALUE_YES == acsChallengeMandated
val isChallenge = VALUE_CHALLENGE == transStatus

internal class Builder : ObjectBuilder<Ares> {
private var threeDSServerTransId: String? = null
Expand All @@ -107,6 +107,7 @@ internal data class Stripe3ds2AuthResult constructor(
private var messageType: String? = null
private var messageVersion: String? = null
private var sdkTransId: String? = null
private var transStatus: String? = null

fun setThreeDSServerTransId(threeDSServerTransId: String?): Builder {
this.threeDSServerTransId = threeDSServerTransId
Expand Down Expand Up @@ -163,11 +164,17 @@ internal data class Stripe3ds2AuthResult constructor(
return this
}

fun setTransStatus(transStatus: String?): Builder {
this.transStatus = transStatus
return this
}

override fun build(): Ares {
return Ares(threeDSServerTransId, acsChallengeMandated,
acsSignedContent, acsTransId, acsUrl, authenticationType,
cardholderInfo, messageExtension, messageType, messageVersion,
sdkTransId)
return Ares(
threeDSServerTransId, acsChallengeMandated, acsSignedContent, acsTransId,
acsUrl, authenticationType, cardholderInfo, messageExtension, messageType,
messageVersion, sdkTransId, transStatus
)
}
}

Expand All @@ -182,9 +189,10 @@ internal data class Stripe3ds2AuthResult constructor(
private const val FIELD_MESSAGE_TYPE = "messageType"
private const val FIELD_MESSAGE_VERSION = "messageVersion"
private const val FIELD_SDK_TRANS_ID = "sdkTransID"
private const val FIELD_TRANS_STATUS = "transStatus"
private const val FIELD_THREE_DS_SERVER_TRANS_ID = "threeDSServerTransID"

internal const val VALUE_YES = "Y"
internal const val VALUE_CHALLENGE = "C"

@JvmStatic
@Throws(JSONException::class)
Expand All @@ -202,6 +210,7 @@ internal data class Stripe3ds2AuthResult constructor(
.setMessageType(aresJson.getString(FIELD_MESSAGE_TYPE))
.setMessageVersion(aresJson.getString(FIELD_MESSAGE_VERSION))
.setSdkTransId(optString(aresJson, FIELD_SDK_TRANS_ID))
.setTransStatus(optString(aresJson, FIELD_TRANS_STATUS))
.setMessageExtension(MessageExtension.fromJson(
aresJson.optJSONArray(FIELD_MESSAGE_EXTENSION)))
.build()
Expand Down Expand Up @@ -277,14 +286,15 @@ internal data class Stripe3ds2AuthResult constructor(

@Throws(JSONException::class)
private fun fromJson(json: JSONObject): MessageExtension {
val data = HashMap<String, String>()
val dataJson = json.optJSONObject(FIELD_DATA)
if (dataJson != null) {
val keys = dataJson.keys()
while (keys.hasNext()) {
val key = keys.next()
data[key] = dataJson.getString(key)
}
val data = if (dataJson != null) {
val keys = dataJson.names() ?: JSONArray()
(0 until keys.length())
.map { idx -> keys.getString(idx) }
.map { key -> mapOf(key to dataJson.getString(key)) }
.reduce { acc, map -> acc.plus(map) }
} else {
emptyMap()
}

return MessageExtension(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ internal object Stripe3ds2AuthResultFixtures {
@JvmField
val ARES_CHALLENGE_FLOW = Stripe3ds2AuthResult.Builder()
.setAres(Stripe3ds2AuthResult.Ares.Builder()
.setAcsChallengeMandated(Stripe3ds2AuthResult.Ares.VALUE_YES)
.setAcsChallengeMandated("Y")
.setAcsTransId(UUID.randomUUID().toString())
.setSdkTransId(UUID.randomUUID().toString())
.setThreeDSServerTransId(UUID.randomUUID().toString())
.setTransStatus(Stripe3ds2AuthResult.Ares.VALUE_CHALLENGE)
.setMessageVersion("2.1.0")
.setMessageType("ARes")
.build())
Expand Down
Loading

0 comments on commit 2dc6ab5

Please sign in to comment.