Fix crash loop when writing invalid currency .

This commit is contained in:
Alex Hart 2024-06-13 18:03:20 -03:00 committed by GitHub
parent 71979b34db
commit cb171092cf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 63 additions and 40 deletions

View file

@ -47,6 +47,7 @@ import org.whispersystems.signalservice.api.push.ServiceId.ACI
import org.whispersystems.signalservice.api.push.ServiceId.PNI import org.whispersystems.signalservice.api.push.ServiceId.PNI
import org.whispersystems.signalservice.api.subscriptions.SubscriberId import org.whispersystems.signalservice.api.subscriptions.SubscriberId
import java.io.ByteArrayInputStream import java.io.ByteArrayInputStream
import java.util.Currency
import java.util.UUID import java.util.UUID
import kotlin.random.Random import kotlin.random.Random
@ -253,7 +254,7 @@ class BackupTest {
SignalDatabase.recipients.setProfileName(self.id, ProfileName.fromParts("Peter", "Parker")) SignalDatabase.recipients.setProfileName(self.id, ProfileName.fromParts("Peter", "Parker"))
SignalDatabase.recipients.setProfileAvatar(self.id, "https://example.com/") SignalDatabase.recipients.setProfileAvatar(self.id, "https://example.com/")
InAppPaymentsRepository.setSubscriber(InAppPaymentSubscriberRecord(SubscriberId.generate(), "USD", InAppPaymentSubscriberRecord.Type.DONATION, false, InAppPaymentData.PaymentMethodType.UNKNOWN)) InAppPaymentsRepository.setSubscriber(InAppPaymentSubscriberRecord(SubscriberId.generate(), Currency.getInstance("USD"), InAppPaymentSubscriberRecord.Type.DONATION, false, InAppPaymentData.PaymentMethodType.UNKNOWN))
SignalStore.donationsValues().setDisplayBadgesOnProfile(false) SignalStore.donationsValues().setDisplayBadgesOnProfile(false)
SignalStore.phoneNumberPrivacy().phoneNumberDiscoverabilityMode = PhoneNumberPrivacyValues.PhoneNumberDiscoverabilityMode.NOT_DISCOVERABLE SignalStore.phoneNumberPrivacy().phoneNumberDiscoverabilityMode = PhoneNumberPrivacyValues.PhoneNumberDiscoverabilityMode.NOT_DISCOVERABLE

View file

@ -14,6 +14,7 @@ import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.testing.assertIs import org.thoughtcrime.securesms.testing.assertIs
import org.thoughtcrime.securesms.testing.assertIsNotNull import org.thoughtcrime.securesms.testing.assertIsNotNull
import org.whispersystems.signalservice.api.subscriptions.SubscriberId import org.whispersystems.signalservice.api.subscriptions.SubscriberId
import java.util.Currency
@RunWith(AndroidJUnit4::class) @RunWith(AndroidJUnit4::class)
class SubscriberIdMigrationJobTest { class SubscriberIdMigrationJobTest {
@ -35,7 +36,7 @@ class SubscriberIdMigrationJobTest {
@Test @Test
fun givenUSDSubscriber_whenIRunSubscriberIdMigrationJob_thenIExpectASingleEntry() { fun givenUSDSubscriber_whenIRunSubscriberIdMigrationJob_thenIExpectASingleEntry() {
val subscriberId = SubscriberId.generate() val subscriberId = SubscriberId.generate()
SignalStore.donationsValues().setSubscriberCurrency("USD", InAppPaymentSubscriberRecord.Type.DONATION) SignalStore.donationsValues().setSubscriberCurrency(Currency.getInstance("USD"), InAppPaymentSubscriberRecord.Type.DONATION)
SignalStore.donationsValues().setSubscriber("USD", subscriberId) SignalStore.donationsValues().setSubscriber("USD", subscriberId)
SignalStore.donationsValues().setSubscriptionPaymentSourceType(PaymentSourceType.PayPal) SignalStore.donationsValues().setSubscriptionPaymentSourceType(PaymentSourceType.PayPal)
SignalStore.donationsValues().shouldCancelSubscriptionBeforeNextSubscribeAttempt = true SignalStore.donationsValues().shouldCancelSubscriptionBeforeNextSubscribeAttempt = true
@ -48,7 +49,7 @@ class SubscriberIdMigrationJobTest {
actual!!.subscriberId.bytes assertIs subscriberId.bytes actual!!.subscriberId.bytes assertIs subscriberId.bytes
actual.paymentMethodType assertIs InAppPaymentData.PaymentMethodType.PAYPAL actual.paymentMethodType assertIs InAppPaymentData.PaymentMethodType.PAYPAL
actual.requiresCancel assertIs true actual.requiresCancel assertIs true
actual.currencyCode assertIs "USD" actual.currency assertIs Currency.getInstance("USD")
actual.type assertIs InAppPaymentSubscriberRecord.Type.DONATION actual.type assertIs InAppPaymentSubscriberRecord.Type.DONATION
} }
} }

View file

@ -29,6 +29,7 @@ import org.whispersystems.signalservice.api.push.UsernameLinkComponents
import org.whispersystems.signalservice.api.storage.StorageRecordProtoUtil.defaultAccountRecord import org.whispersystems.signalservice.api.storage.StorageRecordProtoUtil.defaultAccountRecord
import org.whispersystems.signalservice.api.subscriptions.SubscriberId import org.whispersystems.signalservice.api.subscriptions.SubscriberId
import org.whispersystems.signalservice.api.util.UuidUtil import org.whispersystems.signalservice.api.util.UuidUtil
import java.util.Currency
import kotlin.jvm.optionals.getOrNull import kotlin.jvm.optionals.getOrNull
object AccountDataProcessor { object AccountDataProcessor {
@ -51,7 +52,7 @@ object AccountDataProcessor {
subscriptionManuallyCancelled = InAppPaymentsRepository.isUserManuallyCancelled(InAppPaymentSubscriberRecord.Type.DONATION), subscriptionManuallyCancelled = InAppPaymentsRepository.isUserManuallyCancelled(InAppPaymentSubscriberRecord.Type.DONATION),
username = self.username.getOrNull(), username = self.username.getOrNull(),
subscriberId = subscriber?.subscriberId?.bytes?.toByteString() ?: defaultAccountRecord.subscriberId, subscriberId = subscriber?.subscriberId?.bytes?.toByteString() ?: defaultAccountRecord.subscriberId,
subscriberCurrencyCode = subscriber?.currencyCode ?: defaultAccountRecord.subscriberCurrencyCode, subscriberCurrencyCode = subscriber?.currency?.currencyCode ?: defaultAccountRecord.subscriberCurrencyCode,
accountSettings = AccountData.AccountSettings( accountSettings = AccountData.AccountSettings(
storyViewReceiptsEnabled = SignalStore.storyValues().viewedReceiptsEnabled, storyViewReceiptsEnabled = SignalStore.storyValues().viewedReceiptsEnabled,
typingIndicators = TextSecurePreferences.isTypingIndicatorsEnabled(context), typingIndicators = TextSecurePreferences.isTypingIndicatorsEnabled(context),
@ -108,7 +109,7 @@ object AccountDataProcessor {
val subscriber = InAppPaymentSubscriberRecord( val subscriber = InAppPaymentSubscriberRecord(
remoteSubscriberId, remoteSubscriberId,
accountData.subscriberCurrencyCode, Currency.getInstance(accountData.subscriberCurrencyCode),
InAppPaymentSubscriberRecord.Type.DONATION, InAppPaymentSubscriberRecord.Type.DONATION,
localSubscriber?.requiresCancel ?: false, localSubscriber?.requiresCancel ?: false,
InAppPaymentsRepository.getLatestPaymentMethodType(InAppPaymentSubscriberRecord.Type.DONATION) InAppPaymentsRepository.getLatestPaymentMethodType(InAppPaymentSubscriberRecord.Type.DONATION)

View file

@ -115,7 +115,7 @@ class RecurringInAppPaymentRepository(private val donationsService: DonationsSer
InAppPaymentsRepository.setSubscriber( InAppPaymentsRepository.setSubscriber(
InAppPaymentSubscriberRecord( InAppPaymentSubscriberRecord(
subscriberId = subscriberId, subscriberId = subscriberId,
currencyCode = SignalStore.donationsValues().getSubscriptionCurrency(subscriberType).currencyCode, currency = SignalStore.donationsValues().getSubscriptionCurrency(subscriberType),
type = subscriberType, type = subscriberType,
requiresCancel = false, requiresCancel = false,
paymentMethodType = InAppPaymentData.PaymentMethodType.UNKNOWN paymentMethodType = InAppPaymentData.PaymentMethodType.UNKNOWN
@ -193,7 +193,7 @@ class RecurringInAppPaymentRepository(private val donationsService: DonationsSer
AppDependencies.donationsService.updateSubscriptionLevel( AppDependencies.donationsService.updateSubscriptionLevel(
subscriber.subscriberId, subscriber.subscriberId,
subscriptionLevel, subscriptionLevel,
subscriber.currencyCode, subscriber.currency.currencyCode,
levelUpdateOperation.idempotencyKey.serialize(), levelUpdateOperation.idempotencyKey.serialize(),
subscriberType subscriberType
) )

View file

@ -50,7 +50,7 @@ class SetCurrencyViewModel(
InAppPaymentsRepository.setSubscriber( InAppPaymentsRepository.setSubscriber(
InAppPaymentSubscriberRecord( InAppPaymentSubscriberRecord(
subscriberId = SubscriberId.generate(), subscriberId = SubscriberId.generate(),
currencyCode = currency.currencyCode, currency = currency,
type = inAppPaymentType.requireSubscriberType(), type = inAppPaymentType.requireSubscriberType(),
requiresCancel = false, requiresCancel = false,
paymentMethodType = InAppPaymentData.PaymentMethodType.UNKNOWN paymentMethodType = InAppPaymentData.PaymentMethodType.UNKNOWN

View file

@ -392,7 +392,7 @@ class DonateToSignalViewModel(
if (selectedCurrency !in priceCurrencies) { if (selectedCurrency !in priceCurrencies) {
Log.w(TAG, "Unsupported currency selection. Defaulting to USD. $selectedCurrency isn't supported.") Log.w(TAG, "Unsupported currency selection. Defaulting to USD. $selectedCurrency isn't supported.")
val usd = PlatformCurrencyUtil.USD val usd = PlatformCurrencyUtil.USD
val newSubscriber = InAppPaymentsRepository.getSubscriber(usd, InAppPaymentSubscriberRecord.Type.DONATION) ?: InAppPaymentSubscriberRecord(SubscriberId.generate(), usd.currencyCode, InAppPaymentSubscriberRecord.Type.DONATION, false, InAppPaymentData.PaymentMethodType.UNKNOWN) val newSubscriber = InAppPaymentsRepository.getSubscriber(usd, InAppPaymentSubscriberRecord.Type.DONATION) ?: InAppPaymentSubscriberRecord(SubscriberId.generate(), usd, InAppPaymentSubscriberRecord.Type.DONATION, false, InAppPaymentData.PaymentMethodType.UNKNOWN)
InAppPaymentsRepository.setSubscriber(newSubscriber) InAppPaymentsRepository.setSubscriber(newSubscriber)
subscriptionsRepository.syncAccountRecord().subscribe() subscriptionsRepository.syncAccountRecord().subscribe()
} }

View file

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

View file

@ -25,6 +25,7 @@ import org.thoughtcrime.securesms.database.model.InAppPaymentSubscriberRecord
import org.thoughtcrime.securesms.database.model.databaseprotos.InAppPaymentData import org.thoughtcrime.securesms.database.model.databaseprotos.InAppPaymentData
import org.thoughtcrime.securesms.keyvalue.SignalStore import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.whispersystems.signalservice.api.subscriptions.SubscriberId import org.whispersystems.signalservice.api.subscriptions.SubscriberId
import java.util.Currency
/** /**
* A table matching up SubscriptionIds to currency codes and type * A table matching up SubscriptionIds to currency codes and type
@ -77,7 +78,7 @@ class InAppPaymentSubscriberTable(
* This is a destructive, mutating operation. For setting specific values, prefer the alternative setters available on this table class. * This is a destructive, mutating operation. For setting specific values, prefer the alternative setters available on this table class.
*/ */
fun insertOrReplace(inAppPaymentSubscriberRecord: InAppPaymentSubscriberRecord) { fun insertOrReplace(inAppPaymentSubscriberRecord: InAppPaymentSubscriberRecord) {
Log.i(TAG, "Setting subscriber for currency ${inAppPaymentSubscriberRecord.currencyCode}", Exception(), true) Log.i(TAG, "Setting subscriber for currency ${inAppPaymentSubscriberRecord.currency.currencyCode}", Exception(), true)
writableDatabase.withinTransaction { db -> writableDatabase.withinTransaction { db ->
db.insertInto(TABLE_NAME) db.insertInto(TABLE_NAME)
@ -85,7 +86,7 @@ class InAppPaymentSubscriberTable(
.run(conflictStrategy = SQLiteDatabase.CONFLICT_REPLACE) .run(conflictStrategy = SQLiteDatabase.CONFLICT_REPLACE)
SignalStore.donationsValues().setSubscriberCurrency( SignalStore.donationsValues().setSubscriberCurrency(
inAppPaymentSubscriberRecord.currencyCode, inAppPaymentSubscriberRecord.currency,
inAppPaymentSubscriberRecord.type inAppPaymentSubscriberRecord.type
) )
} }
@ -137,7 +138,7 @@ class InAppPaymentSubscriberTable(
override fun serialize(data: InAppPaymentSubscriberRecord): ContentValues { override fun serialize(data: InAppPaymentSubscriberRecord): ContentValues {
return contentValuesOf( return contentValuesOf(
SUBSCRIBER_ID to data.subscriberId.serialize(), SUBSCRIBER_ID to data.subscriberId.serialize(),
CURRENCY_CODE to data.currencyCode.uppercase(), CURRENCY_CODE to data.currency.currencyCode.uppercase(),
TYPE to TypeSerializer.serialize(data.type), TYPE to TypeSerializer.serialize(data.type),
REQUIRES_CANCEL to data.requiresCancel, REQUIRES_CANCEL to data.requiresCancel,
PAYMENT_METHOD_TYPE to data.paymentMethodType.value PAYMENT_METHOD_TYPE to data.paymentMethodType.value
@ -145,11 +146,13 @@ class InAppPaymentSubscriberTable(
} }
override fun deserialize(input: Cursor): InAppPaymentSubscriberRecord { override fun deserialize(input: Cursor): InAppPaymentSubscriberRecord {
val type = TypeSerializer.deserialize(input.requireInt(TYPE))
val currencyCode = input.requireNonNullString(CURRENCY_CODE).takeIf { it.isNotEmpty() }
return InAppPaymentSubscriberRecord( return InAppPaymentSubscriberRecord(
subscriberId = SubscriberId.deserialize(input.requireNonNullString(SUBSCRIBER_ID)), subscriberId = SubscriberId.deserialize(input.requireNonNullString(SUBSCRIBER_ID)),
currencyCode = input.requireNonNullString(CURRENCY_CODE), currency = currencyCode?.let { Currency.getInstance(it) } ?: SignalStore.donationsValues().getSubscriptionCurrency(type),
type = TypeSerializer.deserialize(input.requireInt(TYPE)), type = type,
requiresCancel = input.requireBoolean(REQUIRES_CANCEL), requiresCancel = input.requireBoolean(REQUIRES_CANCEL) || currencyCode.isNullOrBlank(),
paymentMethodType = InAppPaymentData.PaymentMethodType.fromValue(input.requireInt(PAYMENT_METHOD_TYPE)) ?: InAppPaymentData.PaymentMethodType.UNKNOWN paymentMethodType = InAppPaymentData.PaymentMethodType.fromValue(input.requireInt(PAYMENT_METHOD_TYPE)) ?: InAppPaymentData.PaymentMethodType.UNKNOWN
) )
} }

View file

@ -8,6 +8,7 @@ package org.thoughtcrime.securesms.database.model
import org.thoughtcrime.securesms.database.InAppPaymentTable import org.thoughtcrime.securesms.database.InAppPaymentTable
import org.thoughtcrime.securesms.database.model.databaseprotos.InAppPaymentData import org.thoughtcrime.securesms.database.model.databaseprotos.InAppPaymentData
import org.whispersystems.signalservice.api.subscriptions.SubscriberId import org.whispersystems.signalservice.api.subscriptions.SubscriberId
import java.util.Currency
/** /**
* Represents a SubscriberId and metadata that can be used for a recurring * Represents a SubscriberId and metadata that can be used for a recurring
@ -15,7 +16,7 @@ import org.whispersystems.signalservice.api.subscriptions.SubscriberId
*/ */
data class InAppPaymentSubscriberRecord( data class InAppPaymentSubscriberRecord(
val subscriberId: SubscriberId, val subscriberId: SubscriberId,
val currencyCode: String, val currency: Currency,
val type: Type, val type: Type,
val requiresCancel: Boolean, val requiresCancel: Boolean,
val paymentMethodType: InAppPaymentData.PaymentMethodType val paymentMethodType: InAppPaymentData.PaymentMethodType

View file

@ -164,7 +164,7 @@ class ExternalLaunchDonationJob private constructor(
val updateSubscriptionLevelResponse = AppDependencies.donationsService.updateSubscriptionLevel( val updateSubscriptionLevelResponse = AppDependencies.donationsService.updateSubscriptionLevel(
subscriber.subscriberId, subscriber.subscriberId,
subscriptionLevel, subscriptionLevel,
subscriber.currencyCode, subscriber.currency.currencyCode,
levelUpdateOperation.idempotencyKey.serialize(), levelUpdateOperation.idempotencyKey.serialize(),
subscriber.type subscriber.type
) )

View file

@ -233,7 +233,7 @@ class InAppPaymentAuthCheckJob private constructor(parameters: Parameters) : Bas
val updateLevelResponse = AppDependencies.donationsService.updateSubscriptionLevel( val updateLevelResponse = AppDependencies.donationsService.updateSubscriptionLevel(
subscriber.subscriberId, subscriber.subscriberId,
level, level,
subscriber.currencyCode, subscriber.currency.currencyCode,
updateOperation.idempotencyKey.serialize(), updateOperation.idempotencyKey.serialize(),
subscriber.type subscriber.type
) )

View file

@ -250,7 +250,7 @@ class InAppPaymentKeepAliveJob private constructor(
inAppPaymentData = InAppPaymentData( inAppPaymentData = InAppPaymentData(
badge = badge, badge = badge,
amount = FiatValue( amount = FiatValue(
currencyCode = subscriber.currencyCode, currencyCode = subscriber.currency.currencyCode,
amount = subscription.amount.toDecimalValue() amount = subscription.amount.toDecimalValue()
), ),
error = null, error = null,

View file

@ -29,6 +29,7 @@ import org.whispersystems.signalservice.api.subscriptions.ActiveSubscription.Cha
import org.whispersystems.signalservice.api.subscriptions.ActiveSubscription.Subscription import org.whispersystems.signalservice.api.subscriptions.ActiveSubscription.Subscription
import org.whispersystems.signalservice.internal.ServiceResponse import org.whispersystems.signalservice.internal.ServiceResponse
import java.io.IOException import java.io.IOException
import java.util.Currency
import kotlin.time.Duration.Companion.days import kotlin.time.Duration.Companion.days
import kotlin.time.Duration.Companion.milliseconds import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.seconds import kotlin.time.Duration.Companion.seconds
@ -288,10 +289,15 @@ class InAppPaymentRecurringContextJob private constructor(
} }
private fun handlePaymentFailure(inAppPayment: InAppPaymentTable.InAppPayment, subscription: Subscription, chargeFailure: ChargeFailure?) { private fun handlePaymentFailure(inAppPayment: InAppPaymentTable.InAppPayment, subscription: Subscription, chargeFailure: ChargeFailure?) {
val subscriber = SignalDatabase.inAppPaymentSubscribers.getBySubscriberId(inAppPayment.subscriberId!!) SignalDatabase.inAppPaymentSubscribers.insertOrReplace(
if (subscriber != null) { InAppPaymentSubscriberRecord(
InAppPaymentsRepository.setShouldCancelSubscriptionBeforeNextSubscribeAttempt(subscriber, true) subscriberId = inAppPayment.subscriberId!!,
} currency = Currency.getInstance(inAppPayment.data.amount!!.currencyCode),
type = inAppPayment.type.requireSubscriberType(),
requiresCancel = true,
paymentMethodType = inAppPayment.data.paymentMethodType
)
)
if (inAppPayment.data.redemption?.keepAlive == true) { if (inAppPayment.data.redemption?.keepAlive == true) {
info("Cancellation occurred during keep-alive. Setting cancellation state.") info("Cancellation occurred during keep-alive. Setting cancellation state.")

View file

@ -245,7 +245,7 @@ internal class DonationsValues internal constructor(store: KeyValueStore) : Sign
} else { } else {
InAppPaymentSubscriberRecord( InAppPaymentSubscriberRecord(
SubscriberId.fromBytes(subscriberIdBytes), SubscriberId.fromBytes(subscriberIdBytes),
currencyCode, currency,
InAppPaymentSubscriberRecord.Type.DONATION, InAppPaymentSubscriberRecord.Type.DONATION,
shouldCancelSubscriptionBeforeNextSubscribeAttempt, shouldCancelSubscriptionBeforeNextSubscribeAttempt,
getSubscriptionPaymentSourceType().toPaymentMethodType() getSubscriptionPaymentSourceType().toPaymentMethodType()
@ -253,19 +253,19 @@ internal class DonationsValues internal constructor(store: KeyValueStore) : Sign
} }
} }
fun setSubscriberCurrency(currencyCode: String, type: InAppPaymentSubscriberRecord.Type) { fun setSubscriberCurrency(currency: Currency, type: InAppPaymentSubscriberRecord.Type) {
if (type == InAppPaymentSubscriberRecord.Type.DONATION) { if (type == InAppPaymentSubscriberRecord.Type.DONATION) {
store.beginWrite() store.beginWrite()
.putString(KEY_DONATION_SUBSCRIPTION_CURRENCY_CODE, currencyCode) .putString(KEY_DONATION_SUBSCRIPTION_CURRENCY_CODE, currency.currencyCode)
.apply() .apply()
recurringDonationCurrencyPublisher.onNext(Currency.getInstance(currencyCode)) recurringDonationCurrencyPublisher.onNext(currency)
} else { } else {
store.beginWrite() store.beginWrite()
.putString(KEY_BACKUPS_SUBSCRIPTION_CURRENCY_CODE, currencyCode) .putString(KEY_BACKUPS_SUBSCRIPTION_CURRENCY_CODE, currency.currencyCode)
.apply() .apply()
recurringBackupCurrencyPublisher.onNext(Currency.getInstance(currencyCode)) recurringBackupCurrencyPublisher.onNext(currency)
} }
} }

View file

@ -37,7 +37,7 @@ internal class SubscriberIdMigrationJob(
SignalDatabase.inAppPaymentSubscribers.insertOrReplace( SignalDatabase.inAppPaymentSubscribers.insertOrReplace(
InAppPaymentSubscriberRecord( InAppPaymentSubscriberRecord(
subscriber.subscriberId, subscriber.subscriberId,
subscriber.currencyCode, subscriber.currency,
InAppPaymentSubscriberRecord.Type.DONATION, InAppPaymentSubscriberRecord.Type.DONATION,
SignalStore.donationsValues().shouldCancelSubscriptionBeforeNextSubscribeAttempt, SignalStore.donationsValues().shouldCancelSubscriptionBeforeNextSubscribeAttempt,
SignalStore.donationsValues().getSubscriptionPaymentSourceType().toPaymentMethodType() SignalStore.donationsValues().getSubscriptionPaymentSourceType().toPaymentMethodType()

View file

@ -18,6 +18,7 @@ import org.thoughtcrime.securesms.database.model.RecipientRecord;
import org.thoughtcrime.securesms.database.model.databaseprotos.InAppPaymentData; import org.thoughtcrime.securesms.database.model.databaseprotos.InAppPaymentData;
import org.thoughtcrime.securesms.groups.GroupId; import org.thoughtcrime.securesms.groups.GroupId;
import org.thoughtcrime.securesms.keyvalue.PhoneNumberPrivacyValues; import org.thoughtcrime.securesms.keyvalue.PhoneNumberPrivacyValues;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.Recipient;
import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import org.whispersystems.signalservice.api.storage.SignalAccountRecord; import org.whispersystems.signalservice.api.storage.SignalAccountRecord;
@ -32,6 +33,7 @@ import org.whispersystems.signalservice.internal.storage.protos.AccountRecord;
import org.whispersystems.signalservice.internal.storage.protos.ContactRecord.IdentityState; import org.whispersystems.signalservice.internal.storage.protos.ContactRecord.IdentityState;
import org.whispersystems.signalservice.internal.storage.protos.GroupV2Record; import org.whispersystems.signalservice.internal.storage.protos.GroupV2Record;
import java.util.Currency;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -281,24 +283,32 @@ public final class StorageSyncModels {
if (subscriber == null) { if (subscriber == null) {
return new SignalAccountRecord.Subscriber(null, null); return new SignalAccountRecord.Subscriber(null, null);
} else { } else {
return new SignalAccountRecord.Subscriber(subscriber.getCurrencyCode(), subscriber.getSubscriberId().getBytes()); return new SignalAccountRecord.Subscriber(subscriber.getCurrency().getCurrencyCode(), subscriber.getSubscriberId().getBytes());
} }
} }
/**
* TODO - We need to store the subscriber type.
*/
public static @Nullable InAppPaymentSubscriberRecord remoteToLocalSubscriber( public static @Nullable InAppPaymentSubscriberRecord remoteToLocalSubscriber(
@NonNull SignalAccountRecord.Subscriber subscriber, @NonNull SignalAccountRecord.Subscriber subscriber,
@NonNull InAppPaymentSubscriberRecord.Type type @NonNull InAppPaymentSubscriberRecord.Type type
) { ) {
if (subscriber.getId().isPresent()) { if (subscriber.getId().isPresent()) {
SubscriberId subscriberId = SubscriberId.fromBytes(subscriber.getId().get()); SubscriberId subscriberId = SubscriberId.fromBytes(subscriber.getId().get());
InAppPaymentSubscriberRecord localSubscriberRecord = SignalDatabase.inAppPaymentSubscribers().getBySubscriberId(subscriberId); InAppPaymentSubscriberRecord localSubscriberRecord = SignalDatabase.inAppPaymentSubscribers().getBySubscriberId(subscriberId);
boolean requiresCancel = localSubscriberRecord != null && localSubscriberRecord.getRequiresCancel(); boolean requiresCancel = localSubscriberRecord != null && localSubscriberRecord.getRequiresCancel();
InAppPaymentData.PaymentMethodType paymentMethodType = localSubscriberRecord != null ? localSubscriberRecord.getPaymentMethodType() : InAppPaymentData.PaymentMethodType.UNKNOWN; InAppPaymentData.PaymentMethodType paymentMethodType = localSubscriberRecord != null ? localSubscriberRecord.getPaymentMethodType() : InAppPaymentData.PaymentMethodType.UNKNOWN;
return new InAppPaymentSubscriberRecord(subscriberId, subscriber.getCurrencyCode().get(), type, requiresCancel, paymentMethodType); Currency currency;
if (subscriber.getCurrencyCode().isEmpty()) {
return null;
} else {
try {
currency = Currency.getInstance(subscriber.getCurrencyCode().get());
} catch (IllegalArgumentException e) {
return null;
}
}
return new InAppPaymentSubscriberRecord(subscriberId, currency, type, requiresCancel, paymentMethodType);
} else { } else {
return null; return null;
} }