mirror of
https://github.com/signalapp/Signal-Android.git
synced 2025-12-27 22:43:52 +00:00
IAP Resolve and synchronize payment method from subscription object.
This commit is contained in:
@@ -210,7 +210,7 @@ class StripeRepository(
|
||||
}
|
||||
|
||||
StripeIntentAccessor.ObjectType.SETUP_INTENT -> stripeApi.getSetupIntent(stripeIntentAccessor).let {
|
||||
StatusAndPaymentMethodId(stripeIntentAccessor.intentId, it.status, it.paymentMethod)
|
||||
StatusAndPaymentMethodId(stripeIntentAccessor.intentId, it.status, it.paymentMethodId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -352,7 +352,7 @@ class DonateToSignalFragment :
|
||||
R.string.DonateToSignalFragment__your_payment_is_still_being_processed_onetime
|
||||
}
|
||||
} else {
|
||||
if (state.monthlyDonationState.activeSubscription?.paymentMethod == ActiveSubscription.PAYMENT_METHOD_SEPA_DEBIT) {
|
||||
if (state.monthlyDonationState.activeSubscription?.paymentMethod == ActiveSubscription.PaymentMethod.SEPA_DEBIT) {
|
||||
R.string.DonateToSignalFragment__bank_transfers_usually_take_1_business_day_to_process_monthly
|
||||
} else if (state.monthlyDonationState.nonVerifiedMonthlyDonation != null) {
|
||||
R.string.DonateToSignalFragment__your_ideal_payment_is_still_processing
|
||||
|
||||
@@ -86,7 +86,7 @@ data class DonateToSignalState(
|
||||
}
|
||||
|
||||
val isUpdateLongRunning: Boolean
|
||||
get() = monthlyDonationState.activeSubscription?.paymentMethod == ActiveSubscription.PAYMENT_METHOD_SEPA_DEBIT
|
||||
get() = monthlyDonationState.activeSubscription?.paymentMethod == ActiveSubscription.PaymentMethod.SEPA_DEBIT
|
||||
|
||||
data class OneTimeDonationState(
|
||||
val badge: Badge? = null,
|
||||
|
||||
@@ -228,7 +228,7 @@ class InAppPaymentAuthCheckJob private constructor(parameters: Parameters) : Bas
|
||||
val setPaymentMethodResponse = if (inAppPayment.data.paymentMethodType == InAppPaymentData.PaymentMethodType.IDEAL) {
|
||||
AppDependencies.donationsService.setDefaultIdealPaymentMethod(subscriber.subscriberId, stripeSetupIntent.id)
|
||||
} else {
|
||||
AppDependencies.donationsService.setDefaultStripePaymentMethod(subscriber.subscriberId, stripeSetupIntent.paymentMethod)
|
||||
AppDependencies.donationsService.setDefaultStripePaymentMethod(subscriber.subscriberId, stripeSetupIntent.paymentMethodId)
|
||||
}
|
||||
|
||||
when (val result = checkResult(setPaymentMethodResponse)) {
|
||||
@@ -239,6 +239,10 @@ class InAppPaymentAuthCheckJob private constructor(parameters: Parameters) : Bas
|
||||
|
||||
Log.d(TAG, "Set default payment method via Signal service.", true)
|
||||
|
||||
SignalDatabase.inAppPaymentSubscribers.setPaymentMethod(subscriber.subscriberId, inAppPayment.data.paymentMethodType)
|
||||
|
||||
Log.d(TAG, "Wrote default payment method to subscriber database entry.", true)
|
||||
|
||||
val level = inAppPayment.data.level.toString()
|
||||
|
||||
try {
|
||||
|
||||
@@ -235,13 +235,33 @@ class InAppPaymentKeepAliveJob private constructor(
|
||||
SignalStore.inAppPayments.setLastEndOfPeriod(endOfCurrentPeriod.inWholeSeconds)
|
||||
}
|
||||
|
||||
val subscriptionPaymentMethodType: InAppPaymentData.PaymentMethodType = subscription.paymentMethod.toInAppPaymentDataPaymentMethodType()
|
||||
val subscriberPaymentMethodType: InAppPaymentData.PaymentMethodType = subscriber.paymentMethodType
|
||||
|
||||
val newInAppPaymentMethodType: InAppPaymentData.PaymentMethodType = when (subscriptionPaymentMethodType) {
|
||||
InAppPaymentData.PaymentMethodType.CARD -> {
|
||||
if (subscriberPaymentMethodType == InAppPaymentData.PaymentMethodType.GOOGLE_PAY) {
|
||||
InAppPaymentData.PaymentMethodType.GOOGLE_PAY
|
||||
} else {
|
||||
InAppPaymentData.PaymentMethodType.CARD
|
||||
}
|
||||
}
|
||||
InAppPaymentData.PaymentMethodType.UNKNOWN -> {
|
||||
subscriberPaymentMethodType
|
||||
}
|
||||
else -> subscriptionPaymentMethodType
|
||||
}
|
||||
|
||||
info(type, "Resolved payment method type from subscription: $newInAppPaymentMethodType")
|
||||
SignalDatabase.inAppPaymentSubscribers.setPaymentMethod(subscriber.subscriberId, paymentMethodType = newInAppPaymentMethodType)
|
||||
|
||||
val inAppPaymentId = SignalDatabase.inAppPayments.insert(
|
||||
type = type.inAppPaymentType,
|
||||
state = InAppPaymentTable.State.PENDING,
|
||||
subscriberId = subscriber.subscriberId,
|
||||
endOfPeriod = endOfCurrentPeriod,
|
||||
inAppPaymentData = InAppPaymentData(
|
||||
paymentMethodType = subscriber.paymentMethodType,
|
||||
paymentMethodType = newInAppPaymentMethodType,
|
||||
badge = badge,
|
||||
amount = FiatValue(
|
||||
currencyCode = subscription.currency,
|
||||
@@ -298,6 +318,18 @@ class InAppPaymentKeepAliveJob private constructor(
|
||||
Log.w(TAG, "[$type] $message", throwable, true)
|
||||
}
|
||||
|
||||
private fun ActiveSubscription.PaymentMethod.toInAppPaymentDataPaymentMethodType(): InAppPaymentData.PaymentMethodType {
|
||||
return when (this) {
|
||||
ActiveSubscription.PaymentMethod.UNKNOWN -> InAppPaymentData.PaymentMethodType.UNKNOWN
|
||||
ActiveSubscription.PaymentMethod.CARD -> InAppPaymentData.PaymentMethodType.CARD
|
||||
ActiveSubscription.PaymentMethod.PAYPAL -> InAppPaymentData.PaymentMethodType.PAYPAL
|
||||
ActiveSubscription.PaymentMethod.SEPA_DEBIT -> InAppPaymentData.PaymentMethodType.SEPA_DEBIT
|
||||
ActiveSubscription.PaymentMethod.IDEAL -> InAppPaymentData.PaymentMethodType.IDEAL
|
||||
ActiveSubscription.PaymentMethod.GOOGLE_PLAY_BILLING -> InAppPaymentData.PaymentMethodType.GOOGLE_PLAY_BILLING
|
||||
ActiveSubscription.PaymentMethod.APPLE_APP_STORE -> InAppPaymentData.PaymentMethodType.UNKNOWN
|
||||
}
|
||||
}
|
||||
|
||||
override fun serialize(): ByteArray? = JsonJobData.Builder().putInt(DATA_TYPE, type.code).build().serialize()
|
||||
|
||||
override fun getFactoryKey(): String = KEY
|
||||
|
||||
@@ -33,18 +33,19 @@ final class LogSectionBadges implements LogSection {
|
||||
InAppPaymentTable.InAppPayment latestRecurringDonation = SignalDatabase.inAppPayments().getLatestInAppPaymentByType(InAppPaymentType.RECURRING_DONATION);
|
||||
|
||||
if (latestRecurringDonation != null) {
|
||||
return new StringBuilder().append("Badge Count : ").append(Recipient.self().getBadges().size()).append("\n")
|
||||
.append("ExpiredBadge : ").append(SignalStore.inAppPayments().getExpiredBadge() != null).append("\n")
|
||||
.append("LastKeepAliveLaunchTime : ").append(SignalStore.inAppPayments().getLastKeepAliveLaunchTime()).append("\n")
|
||||
.append("LastEndOfPeriod : ").append(SignalStore.inAppPayments().getLastEndOfPeriod()).append("\n")
|
||||
.append("InAppPayment.State : ").append(latestRecurringDonation.getState()).append("\n")
|
||||
.append("InAppPayment.EndOfPeriod : ").append(latestRecurringDonation.getEndOfPeriodSeconds()).append("\n")
|
||||
.append("InAppPaymentData.RedemptionState: ").append(getRedemptionStage(latestRecurringDonation.getData())).append("\n")
|
||||
.append("InAppPaymentData.Error : ").append(getError(latestRecurringDonation.getData())).append("\n")
|
||||
.append("InAppPaymentData.Cancellation : ").append(getCancellation(latestRecurringDonation.getData())).append("\n")
|
||||
.append("DisplayBadgesOnProfile : ").append(SignalStore.inAppPayments().getDisplayBadgesOnProfile()).append("\n")
|
||||
.append("ShouldCancelBeforeNextAttempt : ").append(InAppPaymentsRepository.getShouldCancelSubscriptionBeforeNextSubscribeAttempt(InAppPaymentSubscriberRecord.Type.DONATION)).append("\n")
|
||||
.append("IsUserManuallyCancelledDonation : ").append(SignalStore.inAppPayments().isDonationSubscriptionManuallyCancelled()).append("\n");
|
||||
return new StringBuilder().append("Badge Count : ").append(Recipient.self().getBadges().size()).append("\n")
|
||||
.append("ExpiredBadge : ").append(SignalStore.inAppPayments().getExpiredBadge() != null).append("\n")
|
||||
.append("LastKeepAliveLaunchTime : ").append(SignalStore.inAppPayments().getLastKeepAliveLaunchTime()).append("\n")
|
||||
.append("LastEndOfPeriod : ").append(SignalStore.inAppPayments().getLastEndOfPeriod()).append("\n")
|
||||
.append("InAppPayment.State : ").append(latestRecurringDonation.getState()).append("\n")
|
||||
.append("InAppPayment.EndOfPeriod : ").append(latestRecurringDonation.getEndOfPeriodSeconds()).append("\n")
|
||||
.append("InAppPaymentData.PaymentMethodType: ").append(getPaymentMethod(latestRecurringDonation.getData())).append("\n")
|
||||
.append("InAppPaymentData.RedemptionState : ").append(getRedemptionStage(latestRecurringDonation.getData())).append("\n")
|
||||
.append("InAppPaymentData.Error : ").append(getError(latestRecurringDonation.getData())).append("\n")
|
||||
.append("InAppPaymentData.Cancellation : ").append(getCancellation(latestRecurringDonation.getData())).append("\n")
|
||||
.append("DisplayBadgesOnProfile : ").append(SignalStore.inAppPayments().getDisplayBadgesOnProfile()).append("\n")
|
||||
.append("ShouldCancelBeforeNextAttempt : ").append(InAppPaymentsRepository.getShouldCancelSubscriptionBeforeNextSubscribeAttempt(InAppPaymentSubscriberRecord.Type.DONATION)).append("\n")
|
||||
.append("IsUserManuallyCancelledDonation : ").append(SignalStore.inAppPayments().isDonationSubscriptionManuallyCancelled()).append("\n");
|
||||
|
||||
} else {
|
||||
return new StringBuilder().append("Badge Count : ").append(Recipient.self().getBadges().size()).append("\n")
|
||||
@@ -63,6 +64,10 @@ final class LogSectionBadges implements LogSection {
|
||||
}
|
||||
}
|
||||
|
||||
private @NonNull String getPaymentMethod(@NonNull InAppPaymentData inAppPaymentData) {
|
||||
return inAppPaymentData.paymentMethodType.toString();
|
||||
}
|
||||
|
||||
private @NonNull String getRedemptionStage(@NonNull InAppPaymentData inAppPaymentData) {
|
||||
if (inAppPaymentData.redemption == null) {
|
||||
return "null";
|
||||
|
||||
@@ -14,6 +14,6 @@ data class StripeSetupIntent @JsonCreator constructor(
|
||||
@JsonProperty("id") val id: String,
|
||||
@JsonProperty("client_secret") val clientSecret: String,
|
||||
@JsonProperty("status") val status: StripeIntentStatus,
|
||||
@JsonProperty("payment_method") val paymentMethod: String?,
|
||||
@JsonProperty("payment_method") val paymentMethodId: String?,
|
||||
@JsonProperty("customer") val customer: String?
|
||||
)
|
||||
|
||||
@@ -63,7 +63,7 @@ class StripeSetupIntentTest {
|
||||
|
||||
assertEquals(intent.id, "seti_1LyzgK2eZvKYlo2C3AhgI5IC")
|
||||
assertEquals(intent.clientSecret, "seti_1LyzgK2eZvKYlo2C3AhgI5IC_secret_MiQXAjP1ZBdORqQWNuJOcLqk9570HkA")
|
||||
assertEquals(intent.paymentMethod, "pm_sldalskdjhfalskjdhf")
|
||||
assertEquals(intent.paymentMethodId, "pm_sldalskdjhfalskjdhf")
|
||||
assertEquals(intent.status, StripeIntentStatus.REQUIRES_PAYMENT_METHOD)
|
||||
assertEquals(intent.customer, "cus_Fh6d95jDS2fVSL")
|
||||
}
|
||||
|
||||
@@ -43,6 +43,35 @@ public final class ActiveSubscription {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* As per API documentation
|
||||
*/
|
||||
public enum PaymentMethod {
|
||||
UNKNOWN("UNKNOWN"),
|
||||
CARD("CARD"),
|
||||
PAYPAL("PAYPAL"),
|
||||
SEPA_DEBIT("SEPA_DEBIT"),
|
||||
IDEAL("IDEAL"),
|
||||
GOOGLE_PLAY_BILLING("GOOGLE_PLAY_BILLING"),
|
||||
APPLE_APP_STORE("APPLE_APP_STORE");
|
||||
|
||||
private String code;
|
||||
|
||||
PaymentMethod(String code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
static PaymentMethod fromCode(String code) {
|
||||
for (PaymentMethod method : PaymentMethod.values()) {
|
||||
if (Objects.equals(method.code, code)) {
|
||||
return method;
|
||||
}
|
||||
}
|
||||
|
||||
return PaymentMethod.UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
private enum Status {
|
||||
/**
|
||||
* The subscription is currently in a trial period and it's safe to provision your product for your customer.
|
||||
@@ -153,17 +182,17 @@ public final class ActiveSubscription {
|
||||
}
|
||||
|
||||
public static final class Subscription {
|
||||
private final int level;
|
||||
private final String currency;
|
||||
private final BigDecimal amount;
|
||||
private final long endOfCurrentPeriod;
|
||||
private final boolean isActive;
|
||||
private final long billingCycleAnchor;
|
||||
private final boolean willCancelAtPeriodEnd;
|
||||
private final String status;
|
||||
private final Processor processor;
|
||||
private final String paymentMethod;
|
||||
private final boolean paymentPending;
|
||||
private final int level;
|
||||
private final String currency;
|
||||
private final BigDecimal amount;
|
||||
private final long endOfCurrentPeriod;
|
||||
private final boolean isActive;
|
||||
private final long billingCycleAnchor;
|
||||
private final boolean willCancelAtPeriodEnd;
|
||||
private final String status;
|
||||
private final Processor processor;
|
||||
private final PaymentMethod paymentMethod;
|
||||
private final boolean paymentPending;
|
||||
|
||||
@JsonCreator
|
||||
public Subscription(@JsonProperty("level") int level,
|
||||
@@ -187,7 +216,7 @@ public final class ActiveSubscription {
|
||||
this.willCancelAtPeriodEnd = willCancelAtPeriodEnd;
|
||||
this.status = status;
|
||||
this.processor = Processor.fromCode(processor);
|
||||
this.paymentMethod = paymentMethod;
|
||||
this.paymentMethod = PaymentMethod.fromCode(paymentMethod);
|
||||
this.paymentPending = paymentPending;
|
||||
}
|
||||
|
||||
@@ -243,7 +272,7 @@ public final class ActiveSubscription {
|
||||
return processor;
|
||||
}
|
||||
|
||||
public String getPaymentMethod() {
|
||||
public PaymentMethod getPaymentMethod() {
|
||||
return paymentMethod;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user