diff --git a/app/src/main/java/org/thoughtcrime/securesms/badges/gifts/flow/GiftFlowRepository.kt b/app/src/main/java/org/thoughtcrime/securesms/badges/gifts/flow/GiftFlowRepository.kt index d066cd5ad4..faa0650606 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/badges/gifts/flow/GiftFlowRepository.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/badges/gifts/flow/GiftFlowRepository.kt @@ -8,7 +8,7 @@ import org.thoughtcrime.securesms.badges.models.Badge import org.thoughtcrime.securesms.components.settings.app.subscription.getGiftBadgeAmounts import org.thoughtcrime.securesms.components.settings.app.subscription.getGiftBadges import org.thoughtcrime.securesms.dependencies.ApplicationDependencies -import org.whispersystems.signalservice.internal.push.DonationsConfiguration +import org.whispersystems.signalservice.internal.push.SubscriptionsConfiguration import java.util.Currency import java.util.Locale @@ -28,7 +28,7 @@ class GiftFlowRepository { .getDonationsConfiguration(Locale.getDefault()) } .flatMap { it.flattenResult() } - .map { DonationsConfiguration.GIFT_LEVEL to it.getGiftBadges().first() } + .map { SubscriptionsConfiguration.GIFT_LEVEL to it.getGiftBadges().first() } .subscribeOn(Schedulers.io()) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/DonationsConfigurationExtensions.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/DonationsConfigurationExtensions.kt index 85aa56820a..54f1f27265 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/DonationsConfigurationExtensions.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/DonationsConfigurationExtensions.kt @@ -4,11 +4,11 @@ import org.signal.core.util.money.FiatMoney import org.signal.core.util.money.PlatformCurrencyUtil import org.thoughtcrime.securesms.badges.Badges import org.thoughtcrime.securesms.badges.models.Badge -import org.whispersystems.signalservice.internal.push.DonationsConfiguration -import org.whispersystems.signalservice.internal.push.DonationsConfiguration.BOOST_LEVEL -import org.whispersystems.signalservice.internal.push.DonationsConfiguration.GIFT_LEVEL -import org.whispersystems.signalservice.internal.push.DonationsConfiguration.LevelConfiguration -import org.whispersystems.signalservice.internal.push.DonationsConfiguration.SUBSCRIPTION_LEVELS +import org.whispersystems.signalservice.internal.push.SubscriptionsConfiguration +import org.whispersystems.signalservice.internal.push.SubscriptionsConfiguration.BOOST_LEVEL +import org.whispersystems.signalservice.internal.push.SubscriptionsConfiguration.GIFT_LEVEL +import org.whispersystems.signalservice.internal.push.SubscriptionsConfiguration.LevelConfiguration +import org.whispersystems.signalservice.internal.push.SubscriptionsConfiguration.SUBSCRIPTION_LEVELS import java.math.BigDecimal import java.util.Currency @@ -26,7 +26,7 @@ private const val SEPA_DEBIT = "SEPA_DEBIT" * @param level The subscription level to get amounts for * @param paymentMethodAvailability Predicate object which checks whether different payment methods are availble. */ -fun DonationsConfiguration.getSubscriptionAmounts( +fun SubscriptionsConfiguration.getSubscriptionAmounts( level: Int, paymentMethodAvailability: PaymentMethodAvailability = DefaultPaymentMethodAvailability ): Set { @@ -41,7 +41,7 @@ fun DonationsConfiguration.getSubscriptionAmounts( /** * Currently, we only support a single gift badge at level GIFT_LEVEL */ -fun DonationsConfiguration.getGiftBadges(): List { +fun SubscriptionsConfiguration.getGiftBadges(): List { val configuration = levels[GIFT_LEVEL] return listOfNotNull(configuration?.badge?.let { Badges.fromServiceBadge(it) }) } @@ -49,7 +49,7 @@ fun DonationsConfiguration.getGiftBadges(): List { /** * Currently, we only support a single gift badge amount per currency */ -fun DonationsConfiguration.getGiftBadgeAmounts(paymentMethodAvailability: PaymentMethodAvailability = DefaultPaymentMethodAvailability): Map { +fun SubscriptionsConfiguration.getGiftBadgeAmounts(paymentMethodAvailability: PaymentMethodAvailability = DefaultPaymentMethodAvailability): Map { return getFilteredCurrencies(paymentMethodAvailability).filter { it.value.oneTime[GIFT_LEVEL]?.isNotEmpty() == true }.mapKeys { @@ -62,12 +62,12 @@ fun DonationsConfiguration.getGiftBadgeAmounts(paymentMethodAvailability: Paymen /** * Currently, we only support a single boost badge at level BOOST_LEVEL */ -fun DonationsConfiguration.getBoostBadges(): List { +fun SubscriptionsConfiguration.getBoostBadges(): List { val configuration = levels[BOOST_LEVEL] return listOfNotNull(configuration?.badge?.let { Badges.fromServiceBadge(it) }) } -fun DonationsConfiguration.getBoostAmounts(paymentMethodAvailability: PaymentMethodAvailability = DefaultPaymentMethodAvailability): Map> { +fun SubscriptionsConfiguration.getBoostAmounts(paymentMethodAvailability: PaymentMethodAvailability = DefaultPaymentMethodAvailability): Map> { return getFilteredCurrencies(paymentMethodAvailability).filter { it.value.oneTime[BOOST_LEVEL]?.isNotEmpty() == true }.mapKeys { @@ -77,12 +77,12 @@ fun DonationsConfiguration.getBoostAmounts(paymentMethodAvailability: PaymentMet } } -fun DonationsConfiguration.getBadge(level: Int): Badge { +fun SubscriptionsConfiguration.getBadge(level: Int): Badge { require(level == GIFT_LEVEL || level == BOOST_LEVEL || SUBSCRIPTION_LEVELS.contains(level)) return Badges.fromServiceBadge(levels[level]!!.badge) } -fun DonationsConfiguration.getSubscriptionLevels(): Map { +fun SubscriptionsConfiguration.getSubscriptionLevels(): Map { return levels.filterKeys { SUBSCRIPTION_LEVELS.contains(it) }.toSortedMap() } @@ -90,17 +90,17 @@ fun DonationsConfiguration.getSubscriptionLevels(): Map * Get a map describing the minimum donation amounts per currency. * This returns only the currencies available to the user. */ -fun DonationsConfiguration.getMinimumDonationAmounts(paymentMethodAvailability: PaymentMethodAvailability = DefaultPaymentMethodAvailability): Map { +fun SubscriptionsConfiguration.getMinimumDonationAmounts(paymentMethodAvailability: PaymentMethodAvailability = DefaultPaymentMethodAvailability): Map { return getFilteredCurrencies(paymentMethodAvailability) .mapKeys { Currency.getInstance(it.key.uppercase()) } .mapValues { FiatMoney(it.value.minimum, it.key) } } -fun DonationsConfiguration.getAvailablePaymentMethods(currencyCode: String): Set { +fun SubscriptionsConfiguration.getAvailablePaymentMethods(currencyCode: String): Set { return currencies[currencyCode.lowercase()]?.supportedPaymentMethods ?: emptySet() } -private fun DonationsConfiguration.getFilteredCurrencies(paymentMethodAvailability: PaymentMethodAvailability): Map { +private fun SubscriptionsConfiguration.getFilteredCurrencies(paymentMethodAvailability: PaymentMethodAvailability): Map { val userPaymentMethods = paymentMethodAvailability.toSet() val availableCurrencyCodes = PlatformCurrencyUtil.getAvailableCurrencyCodes() return currencies.filter { (code, config) -> diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/donate/gateway/GatewaySelectorRepository.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/donate/gateway/GatewaySelectorRepository.kt index 981098c416..5244d3cc95 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/donate/gateway/GatewaySelectorRepository.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/donate/gateway/GatewaySelectorRepository.kt @@ -5,7 +5,7 @@ import org.signal.core.util.money.FiatMoney import org.thoughtcrime.securesms.components.settings.app.subscription.getAvailablePaymentMethods import org.thoughtcrime.securesms.payments.currency.CurrencyUtil import org.whispersystems.signalservice.api.services.DonationsService -import org.whispersystems.signalservice.internal.push.DonationsConfiguration +import org.whispersystems.signalservice.internal.push.SubscriptionsConfiguration import java.util.Locale class GatewaySelectorRepository( @@ -18,10 +18,10 @@ class GatewaySelectorRepository( .map { configuration -> val available = configuration.getAvailablePaymentMethods(currencyCode).map { when (it) { - DonationsConfiguration.PAYPAL -> listOf(GatewayResponse.Gateway.PAYPAL) - DonationsConfiguration.CARD -> listOf(GatewayResponse.Gateway.CREDIT_CARD, GatewayResponse.Gateway.GOOGLE_PAY) - DonationsConfiguration.SEPA_DEBIT -> listOf(GatewayResponse.Gateway.SEPA_DEBIT) - DonationsConfiguration.IDEAL -> listOf(GatewayResponse.Gateway.IDEAL) + SubscriptionsConfiguration.PAYPAL -> listOf(GatewayResponse.Gateway.PAYPAL) + SubscriptionsConfiguration.CARD -> listOf(GatewayResponse.Gateway.CREDIT_CARD, GatewayResponse.Gateway.GOOGLE_PAY) + SubscriptionsConfiguration.SEPA_DEBIT -> listOf(GatewayResponse.Gateway.SEPA_DEBIT) + SubscriptionsConfiguration.IDEAL -> listOf(GatewayResponse.Gateway.IDEAL) else -> listOf() } }.flatten().toSet() diff --git a/app/src/test/java/org/thoughtcrime/securesms/components/settings/app/subscription/DonationsConfigurationExtensionsKtTest.kt b/app/src/test/java/org/thoughtcrime/securesms/components/settings/app/subscription/SubscriptionsConfigurationExtensionsKtTest.kt similarity index 91% rename from app/src/test/java/org/thoughtcrime/securesms/components/settings/app/subscription/DonationsConfigurationExtensionsKtTest.kt rename to app/src/test/java/org/thoughtcrime/securesms/components/settings/app/subscription/SubscriptionsConfigurationExtensionsKtTest.kt index 01f2cfa9f7..6b0902ea89 100644 --- a/app/src/test/java/org/thoughtcrime/securesms/components/settings/app/subscription/DonationsConfigurationExtensionsKtTest.kt +++ b/app/src/test/java/org/thoughtcrime/securesms/components/settings/app/subscription/SubscriptionsConfigurationExtensionsKtTest.kt @@ -12,20 +12,20 @@ import org.junit.runner.RunWith import org.robolectric.RobolectricTestRunner import org.robolectric.annotation.Config import org.thoughtcrime.securesms.dependencies.ApplicationDependencies -import org.whispersystems.signalservice.internal.push.DonationsConfiguration +import org.whispersystems.signalservice.internal.push.SubscriptionsConfiguration import org.whispersystems.signalservice.internal.util.JsonUtil import java.util.Currency @RunWith(RobolectricTestRunner::class) @Config(application = Application::class) -class DonationsConfigurationExtensionsKtTest { +class SubscriptionsConfigurationExtensionsKtTest { private val testData: String = javaClass.classLoader!!.getResourceAsStream("donations_configuration_test_data.json").bufferedReader().readText() - private val testSubject = JsonUtil.fromJson(testData, DonationsConfiguration::class.java) + private val testSubject = JsonUtil.fromJson(testData, SubscriptionsConfiguration::class.java) @Test fun `Given all methods are available, when I getSubscriptionAmounts, then I expect all currencies`() { - val subscriptionPrices = testSubject.getSubscriptionAmounts(DonationsConfiguration.SUBSCRIPTION_LEVELS.first(), AllPaymentMethodsAvailability) + val subscriptionPrices = testSubject.getSubscriptionAmounts(SubscriptionsConfiguration.SUBSCRIPTION_LEVELS.first(), AllPaymentMethodsAvailability) assertEquals(3, subscriptionPrices.size) assertTrue(subscriptionPrices.map { it.currency.currencyCode }.containsAll(setOf("JPY", "BIF", "USD"))) @@ -33,7 +33,7 @@ class DonationsConfigurationExtensionsKtTest { @Test fun `Given only PayPal available, when I getSubscriptionAmounts, then I expect BIF and JPY`() { - val subscriptionPrices = testSubject.getSubscriptionAmounts(DonationsConfiguration.SUBSCRIPTION_LEVELS.first(), PayPalOnly) + val subscriptionPrices = testSubject.getSubscriptionAmounts(SubscriptionsConfiguration.SUBSCRIPTION_LEVELS.first(), PayPalOnly) assertEquals(2, subscriptionPrices.size) assertTrue(subscriptionPrices.map { it.currency.currencyCode }.containsAll(setOf("JPY", "BIF"))) @@ -41,7 +41,7 @@ class DonationsConfigurationExtensionsKtTest { @Test fun `Given only Card available, when I getSubscriptionAmounts, then I expect BIF and USD`() { - val subscriptionPrices = testSubject.getSubscriptionAmounts(DonationsConfiguration.SUBSCRIPTION_LEVELS.first(), CardOnly) + val subscriptionPrices = testSubject.getSubscriptionAmounts(SubscriptionsConfiguration.SUBSCRIPTION_LEVELS.first(), CardOnly) assertEquals(2, subscriptionPrices.size) assertTrue(subscriptionPrices.map { it.currency.currencyCode }.containsAll(setOf("USD", "BIF"))) @@ -76,7 +76,7 @@ class DonationsConfigurationExtensionsKtTest { val subscriptionLevels = testSubject.getSubscriptionLevels() assertEquals(3, subscriptionLevels.size) - assertEquals(DonationsConfiguration.SUBSCRIPTION_LEVELS, subscriptionLevels.keys) + assertEquals(SubscriptionsConfiguration.SUBSCRIPTION_LEVELS, subscriptionLevels.keys) subscriptionLevels.keys.fold(0) { acc, i -> assertTrue(acc < i) i @@ -165,7 +165,7 @@ class DonationsConfigurationExtensionsKtTest { fun `Given GIFT_LEVEL, When I getBadge, then I expect the gift badge`() { mockkStatic(ApplicationDependencies::class) { every { ApplicationDependencies.getApplication() } returns ApplicationProvider.getApplicationContext() - val badge = testSubject.getBadge(DonationsConfiguration.GIFT_LEVEL) + val badge = testSubject.getBadge(SubscriptionsConfiguration.GIFT_LEVEL) assertTrue(badge.isGift()) } @@ -175,7 +175,7 @@ class DonationsConfigurationExtensionsKtTest { fun `Given BOOST_LEVEL, When I getBadge, then I expect the boost badge`() { mockkStatic(ApplicationDependencies::class) { every { ApplicationDependencies.getApplication() } returns ApplicationProvider.getApplicationContext() - val badge = testSubject.getBadge(DonationsConfiguration.BOOST_LEVEL) + val badge = testSubject.getBadge(SubscriptionsConfiguration.BOOST_LEVEL) assertTrue(badge.isBoost()) } @@ -185,7 +185,7 @@ class DonationsConfigurationExtensionsKtTest { fun `Given a sub level, When I getBadge, then I expect a sub badge`() { mockkStatic(ApplicationDependencies::class) { every { ApplicationDependencies.getApplication() } returns ApplicationProvider.getApplicationContext() - val badge = testSubject.getBadge(DonationsConfiguration.SUBSCRIPTION_LEVELS.first()) + val badge = testSubject.getBadge(SubscriptionsConfiguration.SUBSCRIPTION_LEVELS.first()) assertTrue(badge.isSubscription()) } diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/services/DonationsService.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/services/DonationsService.java index 922c168dac..09721453d4 100644 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/services/DonationsService.java +++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/services/DonationsService.java @@ -19,7 +19,7 @@ import org.whispersystems.signalservice.internal.ServiceResponse; import org.whispersystems.signalservice.internal.configuration.SignalServiceConfiguration; import org.whispersystems.signalservice.internal.push.BankMandate; import org.whispersystems.signalservice.internal.push.DonationProcessor; -import org.whispersystems.signalservice.internal.push.DonationsConfiguration; +import org.whispersystems.signalservice.internal.push.SubscriptionsConfiguration; import org.whispersystems.signalservice.internal.push.PushServiceSocket; import java.io.IOException; @@ -42,8 +42,8 @@ public class DonationsService { private final PushServiceSocket pushServiceSocket; - private final AtomicReference> donationsConfigurationCache = new AtomicReference<>(null); - private final AtomicReference> sepaBankMandateCache = new AtomicReference<>(null); + private final AtomicReference> donationsConfigurationCache = new AtomicReference<>(null); + private final AtomicReference> sepaBankMandateCache = new AtomicReference<>(null); private static class CacheEntry { private final T cachedValue; @@ -111,7 +111,7 @@ public class DonationsService { return wrapInServiceResponse(() -> new Pair<>(pushServiceSocket.submitBoostReceiptCredentials(paymentIntentId, receiptCredentialRequest, processor), 200)); } - public ServiceResponse getDonationsConfiguration(Locale locale) { + public ServiceResponse getDonationsConfiguration(Locale locale) { return getCachedValue( locale, donationsConfigurationCache, diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/PushServiceSocket.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/PushServiceSocket.java index 36a050d34f..1f274f8edf 100644 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/PushServiceSocket.java +++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/PushServiceSocket.java @@ -1348,11 +1348,11 @@ public class PushServiceSocket { /** * Get the DonationsConfiguration pointed at by /v1/subscriptions/configuration */ - public DonationsConfiguration getDonationsConfiguration(Locale locale) throws IOException { + public SubscriptionsConfiguration getDonationsConfiguration(Locale locale) throws IOException { Map headers = Collections.singletonMap("Accept-Language", locale.getLanguage() + "-" + locale.getCountry()); String result = makeServiceRequestWithoutAuthentication(DONATIONS_CONFIGURATION, "GET", null, headers, NO_HANDLER); - return JsonUtil.fromJson(result, DonationsConfiguration.class); + return JsonUtil.fromJson(result, SubscriptionsConfiguration.class); } /** diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/DonationsConfiguration.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/SubscriptionsConfiguration.java similarity index 90% rename from libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/DonationsConfiguration.java rename to libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/SubscriptionsConfiguration.java index 52a5fc81b2..8cc0d6792b 100644 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/DonationsConfiguration.java +++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/SubscriptionsConfiguration.java @@ -14,7 +14,7 @@ import java.util.Set; /** * Response JSON for a call to /v1/subscriptions/configuration */ -public class DonationsConfiguration { +public class SubscriptionsConfiguration { public static final String PAYPAL = "PAYPAL"; public static final String CARD = "CARD"; @@ -44,6 +44,9 @@ public class DonationsConfiguration { @JsonProperty("subscription") private Map subscription; + @JsonProperty("backupSubscription") + private Map backupSubscription; + @JsonProperty("supportedPaymentMethods") private Set supportedPaymentMethods; @@ -59,6 +62,10 @@ public class DonationsConfiguration { return subscription; } + public Map getBackupSubscription() { + return backupSubscription; + } + public Set getSupportedPaymentMethods() { return supportedPaymentMethods; }