Skip to content
Closed
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
1 change: 1 addition & 0 deletions afterpay/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ dependencies {

implementation(libs.androidxCoreKtx)
implementation(libs.androidxAppcompat)
implementation(libs.timber)

testImplementation(libs.junit)
coreLibraryDesugaring(libs.androidToolsDesugarJdk)
Expand Down
24 changes: 24 additions & 0 deletions afterpay/consumer-rules.pro
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,27 @@
-keepclasseswithmembers class com.afterpay.android.** {
kotlinx.serialization.KSerializer serializer(...);
}

# Strip all Timber logging calls from release builds
# Note: Keep these method signatures in sync with Timber APIs used by the SDK
-assumenosideeffects class timber.log.Timber {
public *** d(...);
public *** i(...);
public *** w(...);
public *** e(...);
public *** v(...);
public *** wtf(...);
}
Comment on lines +24 to +31
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this valid to put in library rules? I.e. is R8 smart enough to not strip these if the consuming app is using them directly? I'm not an R8 expert, but it seems like stripping AfterpayLog calls should be sufficient since Timber is only used internally inside AfterpayLog.


# Strip all AfterpayLog logging calls from release builds
# Note: Keep sanitization helpers as they are pure utility functions
-assumenosideeffects class com.afterpay.android.internal.AfterpayLog {
public *** d(...);
public *** i(...);
public *** w(...);
public *** e(...);
public *** apiRequest(...);
public *** apiSuccess(...);
public *** apiError(...);
public *** checkoutEvent(...);
}
12 changes: 11 additions & 1 deletion afterpay/src/main/kotlin/com/afterpay/android/Afterpay.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import com.afterpay.android.cashapp.CashAppSignOrderResult.Failure
import com.afterpay.android.cashapp.CashAppSignOrderResult.Success
import com.afterpay.android.cashapp.CashAppValidationResponse
import com.afterpay.android.internal.AfterpayDrawable
import com.afterpay.android.internal.AfterpayLog
import com.afterpay.android.internal.AfterpayString
import com.afterpay.android.internal.ApiV3
import com.afterpay.android.internal.Brand
Expand Down Expand Up @@ -242,7 +243,16 @@ object Afterpay {
locale = locale.clone() as Locale,
environment = environment,
consumerLocale = consumerLocale,
).also { validateConfiguration(it) }
).also { config ->
AfterpayLog.d { "Setting Afterpay configuration: environment=${config.environment.name}, locale=${config.locale}, currency=${config.currency}, maxAmount=${config.maximumAmount}" }
try {
validateConfiguration(config)
AfterpayLog.d("Configuration validated successfully")
} catch (e: IllegalArgumentException) {
AfterpayLog.e(e, "Configuration validation failed")
throw e
}
}
}

private fun validateConfiguration(configuration: Configuration) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package com.afterpay.android.cashapp

import com.afterpay.android.BuildConfig
import com.afterpay.android.internal.AfterpayLog
import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
Expand Down Expand Up @@ -44,12 +45,15 @@ internal object AfterpayCashAppApi {
connection.inputStream.bufferedReader().use { reader ->
val data = reader.readText()
val result = json.decodeFromString<T>(data)
AfterpayLog.d { "Cash App API request successful (HTTP ${connection.responseCode})" }
Result.success(result)
}
} else {
AfterpayLog.w { "Cash App API returned unexpected response code: ${connection.responseCode}" }
throw InvalidObjectException("Unexpected response code: ${connection.responseCode}.")
}
} catch (exception: Exception) {
AfterpayLog.e(exception, "Cash App API request failed")
Result.failure(exception)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package com.afterpay.android.cashapp

import com.afterpay.android.Afterpay
import com.afterpay.android.internal.AfterpayLog
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
Expand All @@ -34,6 +35,7 @@ sealed class CashAppValidationResponse {

object AfterpayCashAppCheckout {
suspend fun performSignPaymentRequest(token: String): CashAppSignOrderResult {
AfterpayLog.d { "Starting Cash App payment signing with token: ${AfterpayLog.sanitizeToken(token)}" }
runCatching {
signPayment(token)
.let { result: Result<AfterpayCashAppSigningResponse> ->
Expand All @@ -48,14 +50,17 @@ object AfterpayCashAppCheckout {
jwt = response.jwtToken,
)

AfterpayLog.d("Cash App payment signing successful")
return CashAppSignOrderResult.Success(cashApp)
}
.onFailure {
return CashAppSignOrderResult.Failure(it)
.onFailure { error ->
AfterpayLog.e(error, "JWT decode failed")
return CashAppSignOrderResult.Failure(error)
}
}
.onFailure {
return CashAppSignOrderResult.Failure(it)
.onFailure { error ->
AfterpayLog.e(error, "Payment signing failed")
return CashAppSignOrderResult.Failure(error)
}
}
}
Expand All @@ -65,6 +70,7 @@ object AfterpayCashAppCheckout {

// TODO stop using this, no need for suspend *and* callback
suspend fun performSignPaymentRequest(token: String, complete: (CashAppSignOrderResult) -> Unit) {
AfterpayLog.d { "Starting Cash App payment signing (callback) with token: ${AfterpayLog.sanitizeToken(token)}" }
runCatching {
signPayment(token)
.onSuccess { response ->
Expand All @@ -78,14 +84,17 @@ object AfterpayCashAppCheckout {
jwt = response.jwtToken,
)

AfterpayLog.d("Cash App payment signing successful (callback)")
complete(CashAppSignOrderResult.Success(cashApp))
}
.onFailure {
complete(CashAppSignOrderResult.Failure(it))
.onFailure { error ->
AfterpayLog.e(error, "JWT decode failed (callback)")
complete(CashAppSignOrderResult.Failure(error))
}
}
.onFailure {
complete(CashAppSignOrderResult.Failure(it))
.onFailure { error ->
AfterpayLog.e(error, "Payment signing failed (callback)")
complete(CashAppSignOrderResult.Failure(error))
}
}
}
Expand Down Expand Up @@ -134,12 +143,19 @@ object AfterpayCashAppCheckout {
response
.onSuccess {
when (it.status) {
"SUCCESS" -> complete(CashAppValidationResponse.Success(it))
else -> complete(CashAppValidationResponse.Failure(Exception("status is ${it.status}")))
"SUCCESS" -> {
AfterpayLog.d("Cash App validation successful")
complete(CashAppValidationResponse.Success(it))
}
else -> {
AfterpayLog.w { "Cash App validation failed with status: ${it.status}" }
complete(CashAppValidationResponse.Failure(Exception("status is ${it.status}")))
}
}
}
.onFailure {
complete(CashAppValidationResponse.Failure(Exception(it.message)))
.onFailure { error ->
AfterpayLog.e(error, "Cash App validation failed")
complete(CashAppValidationResponse.Failure(Exception(error.message)))
}

Unit
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package com.afterpay.android.cashapp

import android.util.Base64
import com.afterpay.android.internal.AfterpayLog
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json

Expand Down Expand Up @@ -49,12 +50,17 @@ data class AfterpayCashAppJwt(
) {
companion object {
fun decode(jwt: String): Result<AfterpayCashAppJwt> {
AfterpayLog.d { "Starting JWT decode for Cash App: ${AfterpayLog.sanitizeToken(jwt)}" }
return runCatching {
val split = jwt.split(".").toTypedArray()
val jwtBody = getJson(split[1])

val json = Json { ignoreUnknownKeys = true }
json.decodeFromString(jwtBody)
val result: AfterpayCashAppJwt = json.decodeFromString(jwtBody)
AfterpayLog.d("JWT decode successful")
result
}.onFailure { error ->
AfterpayLog.e(error, "JWT decode failed")
}
}

Expand Down
Loading