Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
3 changes: 3 additions & 0 deletions apps/flipcash/core/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,9 @@
<string name="error_title_onrampTimeout">Payment Timed Out</string>
<string name="error_description_onrampTimeout">The payment session took too long to respond. Please try again.</string>

<string name="error_title_onrampPaymentSheetTimeout">Purchase Timed Out</string>
<string name="error_description_onrampPaymentSheetTimeout">Purchases must be authorized within 60 seconds</string>

<string name="error_title_onrampTransactionSendFailed">Something Went Wrong</string>
<string name="error_description_onrampTransactionSendFailed">We are working with the Coinbase team to resolve the issue. Your card will be refunded in the meantime. Please try again later</string>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,5 +140,12 @@ private fun showOnRampFailure(resources: Resources, error: CoinbaseOnRampWebErro
message = resources.getString(R.string.error_description_onrampInternal),
)
}

is CoinbaseOnRampWebError.PaymentSheetTimeout -> {
BottomBarManager.showInfo(
title = resources.getString(R.string.error_title_onrampPaymentSheetTimeout),
message = resources.getString(R.string.error_description_onrampPaymentSheetTimeout),
)
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.flipcash.app.onramp

import android.annotation.SuppressLint
import android.app.Activity
import android.content.Intent
import android.webkit.CookieManager
import android.webkit.JavascriptInterface
import android.webkit.WebChromeClient
Expand Down Expand Up @@ -77,10 +79,12 @@ private fun WebView.configureForCoinbaseOnRamp(

var initialTimeoutRunnable: Runnable? = null
var interEventTimeoutRunnable: Runnable? = null
var paymentSheetTimeoutRunnable: Runnable? = null

fun cancelAllTimeouts() {
initialTimeoutRunnable?.let { removeCallbacks(it) }
interEventTimeoutRunnable?.let { removeCallbacks(it) }
paymentSheetTimeoutRunnable?.let { removeCallbacks(it) }
}

val timeoutAction = Runnable {
Expand Down Expand Up @@ -125,8 +129,30 @@ private fun WebView.configureForCoinbaseOnRamp(
post { cancelAllTimeouts(); scheduleInterEventTimeout() }
}

val paymentSheetTimeoutAction = Runnable {
if (terminalEventReceived.compareAndSet(false, true)) {
trace(tag = "CoinbaseOnRamp", message = "Payment sheet timeout fired (60s)")
cancelAllTimeouts()
// The Google Pay sheet is a GMS Activity sitting on top of ours
// in the task stack. Relaunching our Activity with CLEAR_TOP
// finishes everything above it, dismissing the sheet.
(context as? Activity)?.let { activity ->
val intent = Intent(activity, activity::class.java).apply {
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP)
}
activity.startActivity(intent)
}
onPaymentFailure(CoinbaseOnRampWebError.PaymentSheetTimeout())
}
}

val pauseWatchdog: () -> Unit = {
post { cancelAllTimeouts() }
post {
cancelAllTimeouts()
val runnable = Runnable { paymentSheetTimeoutAction.run() }
paymentSheetTimeoutRunnable = runnable
postDelayed(runnable, PAYMENT_SHEET_TIMEOUT_MS)
}
}

settings.javaScriptEnabled = true
Expand Down Expand Up @@ -213,8 +239,13 @@ private fun WebView.configureForCoinbaseOnRamp(
CookieManager.getInstance().setAcceptThirdPartyCookies(this, true)
}

return { cancelAllTimeouts() }
return {
cancelAllTimeouts()
(parent as? android.view.ViewGroup)?.removeView(this@configureForCoinbaseOnRamp)
destroy()
}
}

private const val INITIAL_TIMEOUT_MS = 30_000L
private const val INTER_EVENT_TIMEOUT_MS = 22_000L
private const val INTER_EVENT_TIMEOUT_MS = 22_000L
private const val PAYMENT_SHEET_TIMEOUT_MS = 60_000L
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@ sealed class CoinbaseOnRampWebError(val data: String? = null): Throwable() {
class Internal(data: String? = null) : CoinbaseOnRampWebError(data), NotifiableError
class GooglePayButtonNotFound(data: String? = null) : CoinbaseOnRampWebError(data), NotifiableError
class WebViewTimeout(data: String? = null) : CoinbaseOnRampWebError(data), NotifiableError
class PaymentSheetTimeout(data: String? = null) : CoinbaseOnRampWebError(data)

companion object {
fun fromErrorCode(errorCode: String, data: String? = null): CoinbaseOnRampWebError {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -241,4 +241,10 @@ class CoinbaseOnRampWebErrorTest {
assertIs<NotifiableError>(error)
assertIs<Throwable>(error)
}

@Test
fun paymentSheetTimeoutIsNotNotifiable() {
val error = CoinbaseOnRampWebError.PaymentSheetTimeout()
assertFalse(error is NotifiableError)
}
}
Loading