Implement initial support for IAP data.

This commit is contained in:
Alex Hart
2024-12-19 16:34:29 -04:00
committed by Greyson Parrelli
parent f537fa6436
commit f2b4bd0585
35 changed files with 957 additions and 241 deletions

View File

@@ -450,14 +450,10 @@ object InAppPaymentsRepository {
@Suppress("DEPRECATION")
@SuppressLint("DiscouragedApi")
@WorkerThread
fun getSubscriber(currency: Currency, type: InAppPaymentSubscriberRecord.Type): InAppPaymentSubscriberRecord? {
val subscriber = SignalDatabase.inAppPaymentSubscribers.getByCurrencyCode(currency.currencyCode, type)
fun getRecurringDonationSubscriber(currency: Currency): InAppPaymentSubscriberRecord? {
val subscriber = SignalDatabase.inAppPaymentSubscribers.getByCurrencyCode(currency.currencyCode)
return if (subscriber == null && type == InAppPaymentSubscriberRecord.Type.DONATION) {
SignalStore.inAppPayments.getSubscriber(currency)
} else {
subscriber
}
return subscriber ?: SignalStore.inAppPayments.getSubscriber(currency)
}
/**
@@ -466,10 +462,14 @@ object InAppPaymentsRepository {
@JvmStatic
@WorkerThread
fun getSubscriber(type: InAppPaymentSubscriberRecord.Type): InAppPaymentSubscriberRecord? {
val currency = SignalStore.inAppPayments.getSubscriptionCurrency(type)
if (type == InAppPaymentSubscriberRecord.Type.BACKUP) {
return SignalDatabase.inAppPaymentSubscribers.getBackupsSubscriber()
}
val currency = SignalStore.inAppPayments.getRecurringDonationCurrency()
Log.d(TAG, "Attempting to retrieve subscriber of type $type for ${currency.currencyCode}")
return getSubscriber(currency, type)
return getRecurringDonationSubscriber(currency)
}
/**

View File

@@ -27,6 +27,7 @@ import org.thoughtcrime.securesms.storage.StorageSyncHelper
import org.thoughtcrime.securesms.subscription.LevelUpdate
import org.thoughtcrime.securesms.subscription.LevelUpdateOperation
import org.thoughtcrime.securesms.subscription.Subscription
import org.whispersystems.signalservice.api.storage.IAPSubscriptionId
import org.whispersystems.signalservice.api.subscriptions.ActiveSubscription
import org.whispersystems.signalservice.api.subscriptions.IdempotencyKey
import org.whispersystems.signalservice.api.subscriptions.SubscriberId
@@ -109,7 +110,7 @@ object RecurringInAppPaymentRepository {
return cancelCompletable.andThen(ensureSubscriberId(subscriberType, isRotation = true))
}
fun ensureSubscriberId(subscriberType: InAppPaymentSubscriberRecord.Type, isRotation: Boolean = false): Completable {
fun ensureSubscriberId(subscriberType: InAppPaymentSubscriberRecord.Type, isRotation: Boolean = false, iapSubscriptionId: IAPSubscriptionId? = null): Completable {
return Single.fromCallable {
Log.d(TAG, "Ensuring SubscriberId for type $subscriberType exists on Signal service {isRotation?$isRotation}...", true)
@@ -131,10 +132,19 @@ object RecurringInAppPaymentRepository {
InAppPaymentsRepository.setSubscriber(
InAppPaymentSubscriberRecord(
subscriberId = subscriberId,
currency = SignalStore.inAppPayments.getSubscriptionCurrency(subscriberType),
currency = if (subscriberType == InAppPaymentSubscriberRecord.Type.DONATION) {
SignalStore.inAppPayments.getRecurringDonationCurrency()
} else {
null
},
type = subscriberType,
requiresCancel = false,
paymentMethodType = InAppPaymentData.PaymentMethodType.UNKNOWN
paymentMethodType = if (subscriberType == InAppPaymentSubscriberRecord.Type.BACKUP) {
InAppPaymentData.PaymentMethodType.GOOGLE_PLAY_BILLING
} else {
InAppPaymentData.PaymentMethodType.UNKNOWN
},
iapSubscriptionId = iapSubscriptionId
)
)
@@ -214,7 +224,7 @@ object RecurringInAppPaymentRepository {
AppDependencies.donationsService.updateSubscriptionLevel(
subscriber.subscriberId,
subscriptionLevel,
subscriber.currency.currencyCode,
subscriber.currency!!.currencyCode,
levelUpdateOperation.idempotencyKey.serialize(),
subscriberType.lock
)

View File

@@ -24,7 +24,7 @@ class SetCurrencyViewModel(
private val store = Store(
SetCurrencyState(
selectedCurrencyCode = if (inAppPaymentType.recurring) {
SignalStore.inAppPayments.getSubscriptionCurrency(inAppPaymentType.requireSubscriberType()).currencyCode
SignalStore.inAppPayments.getRecurringDonationCurrency().currencyCode
} else {
SignalStore.inAppPayments.getOneTimeCurrency().currencyCode
},
@@ -34,6 +34,10 @@ class SetCurrencyViewModel(
)
)
init {
check(inAppPaymentType != InAppPaymentType.RECURRING_BACKUP) { "Setting currency is unsupported for backups." }
}
val state: LiveData<SetCurrencyState> = store.stateLiveData
fun setSelectedCurrency(selectedCurrencyCode: String) {
@@ -43,7 +47,7 @@ class SetCurrencyViewModel(
SignalStore.inAppPayments.setOneTimeCurrency(Currency.getInstance(selectedCurrencyCode))
} else {
val currency = Currency.getInstance(selectedCurrencyCode)
val subscriber = InAppPaymentsRepository.getSubscriber(currency, inAppPaymentType.requireSubscriberType())
val subscriber = InAppPaymentsRepository.getRecurringDonationSubscriber(currency)
if (subscriber != null) {
InAppPaymentsRepository.setSubscriber(subscriber)
@@ -54,7 +58,8 @@ class SetCurrencyViewModel(
currency = currency,
type = inAppPaymentType.requireSubscriberType(),
requiresCancel = false,
paymentMethodType = InAppPaymentData.PaymentMethodType.UNKNOWN
paymentMethodType = InAppPaymentData.PaymentMethodType.UNKNOWN,
iapSubscriptionId = null
)
)
}

View File

@@ -6,7 +6,6 @@ import org.thoughtcrime.securesms.badges.models.Badge
import org.thoughtcrime.securesms.components.settings.app.subscription.InAppDonations
import org.thoughtcrime.securesms.components.settings.app.subscription.boost.Boost
import org.thoughtcrime.securesms.components.settings.app.subscription.manage.NonVerifiedMonthlyDonation
import org.thoughtcrime.securesms.database.model.InAppPaymentSubscriberRecord
import org.thoughtcrime.securesms.database.model.databaseprotos.PendingOneTimeDonation
import org.thoughtcrime.securesms.database.model.isLongRunning
import org.thoughtcrime.securesms.database.model.isPending
@@ -114,7 +113,7 @@ data class DonateToSignalState(
}
data class MonthlyDonationState(
val selectedCurrency: Currency = SignalStore.inAppPayments.getSubscriptionCurrency(InAppPaymentSubscriberRecord.Type.DONATION),
val selectedCurrency: Currency = SignalStore.inAppPayments.getRecurringDonationCurrency(),
val subscriptions: List<Subscription> = emptyList(),
private val _activeSubscription: ActiveSubscription? = null,
val selectedSubscription: Subscription? = null,

View File

@@ -388,17 +388,18 @@ class DonateToSignalViewModel(
onSuccess = { subscriptions ->
if (subscriptions.isNotEmpty()) {
val priceCurrencies = subscriptions[0].prices.map { it.currency }
val selectedCurrency = SignalStore.inAppPayments.getSubscriptionCurrency(InAppPaymentSubscriberRecord.Type.DONATION)
val selectedCurrency = SignalStore.inAppPayments.getRecurringDonationCurrency()
if (selectedCurrency !in priceCurrencies) {
Log.w(TAG, "Unsupported currency selection. Defaulting to USD. $selectedCurrency isn't supported.")
val usd = PlatformCurrencyUtil.USD
val newSubscriber = InAppPaymentsRepository.getSubscriber(usd, InAppPaymentSubscriberRecord.Type.DONATION) ?: InAppPaymentSubscriberRecord(
val newSubscriber = InAppPaymentsRepository.getRecurringDonationSubscriber(usd) ?: InAppPaymentSubscriberRecord(
subscriberId = SubscriberId.generate(),
currency = usd,
type = InAppPaymentSubscriberRecord.Type.DONATION,
requiresCancel = false,
paymentMethodType = InAppPaymentData.PaymentMethodType.UNKNOWN
paymentMethodType = InAppPaymentData.PaymentMethodType.UNKNOWN,
iapSubscriptionId = null
)
InAppPaymentsRepository.setSubscriber(newSubscriber)
RecurringInAppPaymentRepository.syncAccountRecord().subscribe()

View File

@@ -240,7 +240,7 @@ class InternalConversationSettingsFragment : DSLSettingsFragment(
// TODO [alex] - DB on main thread!
val subscriber: InAppPaymentSubscriberRecord? = InAppPaymentsRepository.getSubscriber(InAppPaymentSubscriberRecord.Type.DONATION)
val summary = if (subscriber != null) {
"""currency code: ${subscriber.currency.currencyCode}
"""currency code: ${subscriber.currency!!.currencyCode}
|subscriber id: ${subscriber.subscriberId.serialize()}
""".trimMargin()
} else {