mirror of
https://github.com/signalapp/Signal-Android.git
synced 2025-12-24 04:58:45 +00:00
Update local inapppayment cancelation state to match that of the activesubscription when we discover it.
This commit is contained in:
committed by
jeffrey-signal
parent
7301dda5d1
commit
9d545412a5
@@ -255,7 +255,7 @@ class BackupStateObserver(
|
||||
val purchaseResult = AppDependencies.billingApi.queryPurchases()
|
||||
Log.d(TAG, "[getNetworkBackupState][subscriptionStateMismatchDetected] queryPurchase result: $purchaseResult")
|
||||
|
||||
val hasActiveGooglePlayBillingSubscription = when (purchaseResult) {
|
||||
val googlePlayBillingSubscriptionIsActiveAndWillRenew = when (purchaseResult) {
|
||||
is BillingPurchaseResult.Success -> {
|
||||
Log.d(TAG, "[getNetworkBackupState][subscriptionStateMismatchDetected] Found a purchase: $purchaseResult")
|
||||
purchaseResult.isAcknowledged && purchaseResult.isAutoRenewing
|
||||
@@ -267,7 +267,7 @@ class BackupStateObserver(
|
||||
}
|
||||
} || SignalStore.backup.backupTierInternalOverride == MessageBackupTier.PAID
|
||||
|
||||
Log.d(TAG, "[getNetworkBackupState][subscriptionStateMismatchDetected] hasActiveGooglePlayBillingSubscription: $hasActiveGooglePlayBillingSubscription")
|
||||
Log.d(TAG, "[getNetworkBackupState][subscriptionStateMismatchDetected] googlePlayBillingSubscriptionIsActiveAndWillRenew: $googlePlayBillingSubscriptionIsActiveAndWillRenew")
|
||||
|
||||
val activeSubscriptionResult = withContext(Dispatchers.IO) {
|
||||
RecurringInAppPaymentRepository.getActiveSubscriptionSync(InAppPaymentSubscriberRecord.Type.BACKUP)
|
||||
@@ -278,26 +278,29 @@ class BackupStateObserver(
|
||||
Log.w(TAG, "[getNetworkBackupState][subscriptionStateMismatchDetected] Failed to load active subscription due to an application error.", activeSubscriptionResult.getCause(), true)
|
||||
return getStateOnError()
|
||||
}
|
||||
|
||||
is NetworkResult.NetworkError<ActiveSubscription> -> {
|
||||
Log.w(TAG, "[getNetworkBackupState][subscriptionStateMismatchDetected] Failed to load active subscription due to a network error.", activeSubscriptionResult.getCause(), true)
|
||||
return getStateOnError()
|
||||
}
|
||||
|
||||
is NetworkResult.StatusCodeError<ActiveSubscription> -> {
|
||||
Log.i(TAG, "[getNetworkBackupState][subscriptionStateMismatchDetected] Failed to load active subscription due to a status code error.", activeSubscriptionResult.getCause(), true)
|
||||
null
|
||||
}
|
||||
|
||||
is NetworkResult.Success<ActiveSubscription> -> {
|
||||
Log.i(TAG, "[getNetworkBackupState][subscriptionStateMismatchDetected] Successfully loaded active subscription.", true)
|
||||
activeSubscriptionResult.result
|
||||
}
|
||||
}
|
||||
|
||||
val hasActiveSignalSubscription = activeSubscription?.isActive == true
|
||||
val signalServiceSubscriptionIsActiveAndWillRenew = activeSubscription?.isActive == true && (!activeSubscription.isCanceled || activeSubscription.willCancelAtPeriodEnd())
|
||||
|
||||
Log.d(TAG, "[getNetworkBackupState][subscriptionStateMismatchDetected] hasActiveSignalSubscription: $hasActiveSignalSubscription")
|
||||
Log.d(TAG, "[getNetworkBackupState][subscriptionStateMismatchDetected] signalServiceSubscriptionIsActiveAndWillRenew: $signalServiceSubscriptionIsActiveAndWillRenew")
|
||||
|
||||
when {
|
||||
hasActiveSignalSubscription && !hasActiveGooglePlayBillingSubscription -> {
|
||||
signalServiceSubscriptionIsActiveAndWillRenew && !googlePlayBillingSubscriptionIsActiveAndWillRenew -> {
|
||||
val type = buildPaidTypeFromSubscription(activeSubscription.activeSubscription)
|
||||
|
||||
if (type == null) {
|
||||
@@ -312,12 +315,12 @@ class BackupStateObserver(
|
||||
)
|
||||
}
|
||||
|
||||
hasActiveSignalSubscription && hasActiveGooglePlayBillingSubscription -> {
|
||||
signalServiceSubscriptionIsActiveAndWillRenew && googlePlayBillingSubscriptionIsActiveAndWillRenew -> {
|
||||
Log.d(TAG, "[getNetworkBackupState][subscriptionMismatchDetected] Found active signal subscription and active google play subscription. Clearing mismatch.")
|
||||
SignalStore.backup.subscriptionStateMismatchDetected = false
|
||||
}
|
||||
|
||||
!hasActiveSignalSubscription && !hasActiveGooglePlayBillingSubscription -> {
|
||||
!signalServiceSubscriptionIsActiveAndWillRenew && !googlePlayBillingSubscriptionIsActiveAndWillRenew -> {
|
||||
Log.d(TAG, "[getNetworkBackupState][subscriptionMismatchDetected] Found inactive signal subscription and inactive google play subscription. Clearing mismatch.")
|
||||
SignalStore.backup.subscriptionStateMismatchDetected = false
|
||||
}
|
||||
@@ -393,6 +396,8 @@ class BackupStateObserver(
|
||||
when {
|
||||
(subscription.isCanceled || subscription.willCancelAtPeriodEnd()) && subscription.isActive -> {
|
||||
Log.d(TAG, "[getPaidBackupState] Found a canceled subscription.")
|
||||
InAppPaymentsRepository.updateBackupInAppPaymentWithCancelation(activeSubscription.successOrThrow())
|
||||
|
||||
BackupState.Canceled(
|
||||
messageBackupsType = subscriberType,
|
||||
renewalTime = subscription.endOfCurrentPeriod.seconds
|
||||
@@ -401,6 +406,7 @@ class BackupStateObserver(
|
||||
|
||||
subscription.isActive -> {
|
||||
Log.d(TAG, "[getPaidBackupState] Found an active subscription.")
|
||||
InAppPaymentsRepository.clearCancelation(activeSubscription.successOrThrow())
|
||||
BackupState.ActivePaid(
|
||||
messageBackupsType = subscriberType,
|
||||
price = FiatMoney.fromSignalNetworkAmount(subscription.amount, Currency.getInstance(subscription.currency)),
|
||||
|
||||
@@ -75,6 +75,73 @@ object InAppPaymentsRepository {
|
||||
|
||||
private val temporaryErrorProcessor = PublishProcessor.create<Pair<InAppPaymentTable.InAppPaymentId, Throwable>>()
|
||||
|
||||
/**
|
||||
* Updates the latest payment object for the given subscription with cancelation information as necessary.
|
||||
*
|
||||
* This operation will only be performed if we find a latest payment for the given subscriber id in the END state without cancelation data
|
||||
*/
|
||||
fun updateBackupInAppPaymentWithCancelation(activeSubscription: ActiveSubscription) {
|
||||
if (activeSubscription.isCanceled || activeSubscription.willCancelAtPeriodEnd()) {
|
||||
val subscriber = getSubscriber(InAppPaymentSubscriberRecord.Type.BACKUP) ?: return
|
||||
val latestPayment = SignalDatabase.inAppPayments.getLatestBySubscriberId(subscriber.subscriberId) ?: return
|
||||
if (latestPayment.state == InAppPaymentTable.State.END && latestPayment.data.cancellation == null) {
|
||||
synchronized(subscriber.type.lock) {
|
||||
val payment = SignalDatabase.inAppPayments.getLatestBySubscriberId(subscriber.subscriberId) ?: return
|
||||
val chargeFailure: ActiveSubscription.ChargeFailure? = activeSubscription.chargeFailure
|
||||
|
||||
Log.i(TAG, "Recording cancelation in the database. (has charge failure? ${chargeFailure != null})")
|
||||
SignalDatabase.inAppPayments.update(
|
||||
payment.copy(
|
||||
data = payment.data.newBuilder()
|
||||
.cancellation(
|
||||
InAppPaymentData.Cancellation(
|
||||
reason = if (chargeFailure != null) InAppPaymentData.Cancellation.Reason.PAST_DUE else InAppPaymentData.Cancellation.Reason.CANCELED,
|
||||
chargeFailure = chargeFailure?.let {
|
||||
InAppPaymentData.ChargeFailure(
|
||||
code = it.code,
|
||||
message = it.message,
|
||||
outcomeType = it.outcomeType,
|
||||
outcomeNetworkReason = it.outcomeNetworkReason ?: "",
|
||||
outcomeNetworkStatus = it.outcomeNetworkStatus
|
||||
)
|
||||
}
|
||||
)
|
||||
)
|
||||
.build()
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the latest payment object clearing cancelation information as necessary.
|
||||
*
|
||||
* This operation will only be performed if we find a latest payment for the given subscriber id in the END state with cancelation data
|
||||
*/
|
||||
fun clearCancelation(activeSubscription: ActiveSubscription) {
|
||||
if (!activeSubscription.isCanceled && !activeSubscription.willCancelAtPeriodEnd()) {
|
||||
val subscriber = getSubscriber(InAppPaymentSubscriberRecord.Type.BACKUP) ?: return
|
||||
|
||||
val latestPayment = SignalDatabase.inAppPayments.getLatestBySubscriberId(subscriber.subscriberId) ?: return
|
||||
if (latestPayment.data.cancellation != null && latestPayment.state == InAppPaymentTable.State.END) {
|
||||
synchronized(subscriber.type.lock) {
|
||||
val payment = SignalDatabase.inAppPayments.getLatestBySubscriberId(subscriber.subscriberId) ?: return
|
||||
|
||||
Log.i(TAG, "Clearing cancelation in the database.")
|
||||
SignalDatabase.inAppPayments.update(
|
||||
payment.copy(
|
||||
data = payment.data.newBuilder()
|
||||
.cancellation(null)
|
||||
.build()
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps an in-app-payment update in a completable.
|
||||
*/
|
||||
|
||||
@@ -258,6 +258,7 @@ class BackupSubscriptionCheckJob private constructor(parameters: Parameters) : C
|
||||
if (backupExpiration != null) {
|
||||
Log.i(TAG, "Marking subscription failed or canceled.")
|
||||
SignalStore.backup.setDownloadNotifierToTriggerAtHalfwayPoint(backupExpiration)
|
||||
InAppPaymentsRepository.updateBackupInAppPaymentWithCancelation(activeSubscription)
|
||||
BackupStateObserver.notifyBackupStateChanged()
|
||||
} else {
|
||||
Log.w(TAG, "Failed to mark, no entitlement was found on WhoAmIResponse")
|
||||
@@ -267,6 +268,8 @@ class BackupSubscriptionCheckJob private constructor(parameters: Parameters) : C
|
||||
if (response.getCause() != null) {
|
||||
Log.w(TAG, "Failed to get WhoAmI from service.", response.getCause())
|
||||
}
|
||||
} else if (activeSubscription != null) {
|
||||
InAppPaymentsRepository.clearCancelation(activeSubscription)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user