Skip to content

Commit

Permalink
Add advancedFraudSignalsEnabled property (#2436)
Browse files Browse the repository at this point in the history
This allows you to control whether the Stripe SDK is collecting
additional device data for fraud prevention.

For more details on the information we collect, visit
https://stripe.com/docs/disputes/prevention/advanced-fraud-detection
  • Loading branch information
mshafrir-stripe authored Apr 28, 2020
1 parent eb27d25 commit e15ef74
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,33 +32,37 @@ internal interface FingerprintDataRepository {
)

override fun refresh() {
handler.post {
val liveData = store.get()
// LiveData observation must occur on the main thread
liveData.observeForever(object : Observer<FingerprintData> {
override fun onChanged(localFingerprintData: FingerprintData) {
if (localFingerprintData.isExpired(timestampSupplier())) {
fingerprintRequestExecutor.execute(
request = fingerprintRequestFactory.create(
localFingerprintData.guid
)
) { remoteFingerprintData ->
remoteFingerprintData?.let {
save(it)
if (Stripe.advancedFraudSignalsEnabled) {
handler.post {
val liveData = store.get()
// LiveData observation must occur on the main thread
liveData.observeForever(object : Observer<FingerprintData> {
override fun onChanged(localFingerprintData: FingerprintData) {
if (localFingerprintData.isExpired(timestampSupplier())) {
fingerprintRequestExecutor.execute(
request = fingerprintRequestFactory.create(
localFingerprintData.guid
)
) { remoteFingerprintData ->
remoteFingerprintData?.let {
save(it)
}
liveData.removeObserver(this)
}
} else {
cachedFingerprintData = localFingerprintData
liveData.removeObserver(this)
}
} else {
cachedFingerprintData = localFingerprintData
liveData.removeObserver(this)
}
}
})
})
}
}
}

override fun get(): FingerprintData? {
return cachedFingerprintData
return cachedFingerprintData.takeIf {
Stripe.advancedFraudSignalsEnabled
}
}

override fun save(fingerprintData: FingerprintData) {
Expand Down
13 changes: 13 additions & 0 deletions stripe/src/main/java/com/stripe/android/Stripe.kt
Original file line number Diff line number Diff line change
Expand Up @@ -1612,5 +1612,18 @@ class Stripe internal constructor(
*/
@JvmStatic
var appInfo: AppInfo? = null

/**
* [advancedFraudSignalsEnabled] determines whether additional device data is sent to Stripe
* for fraud prevention. By default, this property is set to `true`.
*
* Disabling this setting will reduce Stripe's ability to protect your business from
* fraudulent payments.
*
* For more details on the information we collect, visit
* https://stripe.com/docs/disputes/prevention/advanced-fraud-detection
*/
@JvmStatic
var advancedFraudSignalsEnabled: Boolean = true
}
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
package com.stripe.android

import android.content.Context
import android.os.Handler
import androidx.test.core.app.ApplicationProvider
import com.google.common.truth.Truth.assertThat
import com.nhaarman.mockitokotlin2.KArgumentCaptor
import com.nhaarman.mockitokotlin2.any
import com.nhaarman.mockitokotlin2.argumentCaptor
import com.nhaarman.mockitokotlin2.doNothing
import com.nhaarman.mockitokotlin2.mock
import com.nhaarman.mockitokotlin2.never
import com.nhaarman.mockitokotlin2.verify
import com.nhaarman.mockitokotlin2.whenever
import java.util.Calendar
import java.util.UUID
import java.util.concurrent.TimeUnit
import kotlin.test.AfterTest
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
Expand All @@ -24,6 +27,11 @@ class FingerprintDataRepositoryTest {
private val fingerprintRequestExecutor: FingerprintRequestExecutor = mock()
private val requestExecutorCallback: KArgumentCaptor<(FingerprintData?) -> Unit> = argumentCaptor()

@AfterTest
fun after() {
Stripe.advancedFraudSignalsEnabled = true
}

@Test
fun roundtrip_shouldReturnOriginalObject() {
val expectedFingerprintData = createFingerprintData(elapsedTime = -5L)
Expand Down Expand Up @@ -77,6 +85,26 @@ class FingerprintDataRepositoryTest {
).isTrue()
}

@Test
fun refresh_whenAdvancedFraudSignalsDisabled_shouldNotFetchFingerprintData() {
Stripe.advancedFraudSignalsEnabled = false

val store: FingerprintDataStore = mock()
val fingerprintRequestFactory: FingerprintRequestFactory = mock()
val handler: Handler = mock()
val repository = FingerprintDataRepository.Default(
store = store,
fingerprintRequestFactory = fingerprintRequestFactory,
fingerprintRequestExecutor = fingerprintRequestExecutor
)
repository.refresh()

verify(store, never()).save(any())
verify(handler, never()).post(any())
verify(fingerprintRequestFactory, never()).create(any())
verify(fingerprintRequestExecutor, never()).execute(any(), any())
}

private companion object {
fun createFingerprintData(elapsedTime: Long = 0L): FingerprintData {
return FingerprintData(
Expand Down

0 comments on commit e15ef74

Please sign in to comment.