From 52d5947c0ad8b757aaad7421bf30a43f64cf6869 Mon Sep 17 00:00:00 2001 From: Alex Hart Date: Mon, 30 Mar 2026 14:58:07 -0300 Subject: [PATCH] Treat 409 as successful redemption for recurring donation. Co-authored-by: Greyson Parrelli --- .../jobs/InAppPaymentRecurringContextJob.kt | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/InAppPaymentRecurringContextJob.kt b/app/src/main/java/org/thoughtcrime/securesms/jobs/InAppPaymentRecurringContextJob.kt index 5b062f992c..4cea5c1142 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/InAppPaymentRecurringContextJob.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/InAppPaymentRecurringContextJob.kt @@ -547,7 +547,20 @@ class InAppPaymentRecurringContextJob private constructor( } 409 -> { - warning("Already redeemed this token during new subscription. Failing.", applicationError) + warning("Already redeemed this token during new subscription.", applicationError) + + if (inAppPayment.type == InAppPaymentType.RECURRING_DONATION) { + info("Token already redeemed for recurring donation. Treating as successful redemption.") + SignalDatabase.inAppPayments.update( + inAppPayment = inAppPayment.copy( + state = InAppPaymentTable.State.END, + data = inAppPayment.data.newBuilder().redemption( + redemption = InAppPaymentData.RedemptionState(stage = InAppPaymentData.RedemptionState.Stage.REDEEMED) + ).build() + ) + ) + throw Exception(applicationError) + } // During keep-alive processing, we don't alert the user about redemption failures. if (inAppPayment.type == InAppPaymentType.RECURRING_BACKUP && inAppPayment.data.redemption?.keepAlive != true) {