kopia lustrzana https://github.com/ryukoposting/Signal-Android
Add support and tracking of ChargeFailure in ActiveSubscription.
rodzic
159d67ec59
commit
115f7063d5
|
@ -25,7 +25,7 @@ class SubscriptionsRepository(private val donationsService: DonationsService) {
|
||||||
donationsService.getSubscription(localSubscription.subscriberId)
|
donationsService.getSubscription(localSubscription.subscriberId)
|
||||||
.flatMap(ServiceResponse<ActiveSubscription>::flattenResult)
|
.flatMap(ServiceResponse<ActiveSubscription>::flattenResult)
|
||||||
} else {
|
} else {
|
||||||
Single.just(ActiveSubscription(null))
|
Single.just(ActiveSubscription.EMPTY)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -148,7 +148,7 @@ class SubscribeViewModel(
|
||||||
.getActiveSubscription()
|
.getActiveSubscription()
|
||||||
.subscribeBy(
|
.subscribeBy(
|
||||||
onSuccess = { activeSubscriptionSubject.onNext(it) },
|
onSuccess = { activeSubscriptionSubject.onNext(it) },
|
||||||
onError = { activeSubscriptionSubject.onNext(ActiveSubscription(null)) }
|
onError = { activeSubscriptionSubject.onNext(ActiveSubscription.EMPTY) }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,6 +167,7 @@ class SubscribeViewModel(
|
||||||
SignalStore.donationsValues().setLastEndOfPeriod(0L)
|
SignalStore.donationsValues().setLastEndOfPeriod(0L)
|
||||||
SignalStore.donationsValues().clearLevelOperations()
|
SignalStore.donationsValues().clearLevelOperations()
|
||||||
SignalStore.donationsValues().shouldCancelSubscriptionBeforeNextSubscribeAttempt = false
|
SignalStore.donationsValues().shouldCancelSubscriptionBeforeNextSubscribeAttempt = false
|
||||||
|
SignalStore.donationsValues().setUnexpectedSubscriptionCancelationChargeFailure(null)
|
||||||
SignalStore.donationsValues().unexpectedSubscriptionCancelationReason = null
|
SignalStore.donationsValues().unexpectedSubscriptionCancelationReason = null
|
||||||
SignalStore.donationsValues().unexpectedSubscriptionCancelationTimestamp = 0L
|
SignalStore.donationsValues().unexpectedSubscriptionCancelationTimestamp = 0L
|
||||||
MultiDeviceSubscriptionSyncRequestJob.enqueue()
|
MultiDeviceSubscriptionSyncRequestJob.enqueue()
|
||||||
|
@ -185,6 +186,7 @@ class SubscribeViewModel(
|
||||||
SignalStore.donationsValues().setLastEndOfPeriod(0L)
|
SignalStore.donationsValues().setLastEndOfPeriod(0L)
|
||||||
SignalStore.donationsValues().clearLevelOperations()
|
SignalStore.donationsValues().clearLevelOperations()
|
||||||
SignalStore.donationsValues().markUserManuallyCancelled()
|
SignalStore.donationsValues().markUserManuallyCancelled()
|
||||||
|
SignalStore.donationsValues().setUnexpectedSubscriptionCancelationChargeFailure(null)
|
||||||
SignalStore.donationsValues().unexpectedSubscriptionCancelationReason = null
|
SignalStore.donationsValues().unexpectedSubscriptionCancelationReason = null
|
||||||
SignalStore.donationsValues().unexpectedSubscriptionCancelationTimestamp = 0L
|
SignalStore.donationsValues().unexpectedSubscriptionCancelationTimestamp = 0L
|
||||||
refreshActiveSubscription()
|
refreshActiveSubscription()
|
||||||
|
|
|
@ -97,6 +97,7 @@ public class SubscriptionKeepAliveJob extends BaseJob {
|
||||||
|
|
||||||
if (activeSubscription.isFailedPayment()) {
|
if (activeSubscription.isFailedPayment()) {
|
||||||
Log.i(TAG, "User has a subscription with a failed payment. Marking the payment failure. Status message: " + activeSubscription.getActiveSubscription().getStatus(), true);
|
Log.i(TAG, "User has a subscription with a failed payment. Marking the payment failure. Status message: " + activeSubscription.getActiveSubscription().getStatus(), true);
|
||||||
|
SignalStore.donationsValues().setUnexpectedSubscriptionCancelationChargeFailure(activeSubscription.getChargeFailure());
|
||||||
SignalStore.donationsValues().setUnexpectedSubscriptionCancelationReason(activeSubscription.getActiveSubscription().getStatus());
|
SignalStore.donationsValues().setUnexpectedSubscriptionCancelationReason(activeSubscription.getActiveSubscription().getStatus());
|
||||||
SignalStore.donationsValues().setUnexpectedSubscriptionCancelationTimestamp(activeSubscription.getActiveSubscription().getEndOfCurrentPeriod());
|
SignalStore.donationsValues().setUnexpectedSubscriptionCancelationTimestamp(activeSubscription.getActiveSubscription().getEndOfCurrentPeriod());
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -138,13 +138,20 @@ public class SubscriptionReceiptRequestResponseJob extends BaseJob {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doRun() throws Exception {
|
private void doRun() throws Exception {
|
||||||
ActiveSubscription.Subscription subscription = getLatestSubscriptionInformation();
|
ActiveSubscription activeSubscription = getLatestSubscriptionInformation();
|
||||||
|
ActiveSubscription.Subscription subscription = activeSubscription.getActiveSubscription();
|
||||||
|
|
||||||
if (subscription == null) {
|
if (subscription == null) {
|
||||||
Log.w(TAG, "Subscription is null.", true);
|
Log.w(TAG, "Subscription is null.", true);
|
||||||
throw new RetryableException();
|
throw new RetryableException();
|
||||||
} else if (subscription.isFailedPayment()) {
|
} else if (subscription.isFailedPayment()) {
|
||||||
|
ActiveSubscription.ChargeFailure chargeFailure = activeSubscription.getChargeFailure();
|
||||||
|
if (chargeFailure != null) {
|
||||||
|
Log.w(TAG, "Subscription payment charge failure code: " + chargeFailure.getCode() + ", message: " + chargeFailure.getMessage(), true);
|
||||||
|
}
|
||||||
|
|
||||||
Log.w(TAG, "Subscription payment failure in active subscription response (status = " + subscription.getStatus() + ").", true);
|
Log.w(TAG, "Subscription payment failure in active subscription response (status = " + subscription.getStatus() + ").", true);
|
||||||
onPaymentFailure(subscription.getStatus(), subscription.getEndOfCurrentPeriod());
|
onPaymentFailure(subscription.getStatus(), chargeFailure, subscription.getEndOfCurrentPeriod());
|
||||||
throw new Exception("Subscription has a payment failure: " + subscription.getStatus());
|
throw new Exception("Subscription has a payment failure: " + subscription.getStatus());
|
||||||
} else if (!subscription.isActive()) {
|
} else if (!subscription.isActive()) {
|
||||||
Log.w(TAG, "Subscription is not yet active. Status: " + subscription.getStatus(), true);
|
Log.w(TAG, "Subscription is not yet active. Status: " + subscription.getStatus(), true);
|
||||||
|
@ -184,13 +191,13 @@ public class SubscriptionReceiptRequestResponseJob extends BaseJob {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private @Nullable ActiveSubscription.Subscription getLatestSubscriptionInformation() throws Exception {
|
private @NonNull ActiveSubscription getLatestSubscriptionInformation() throws Exception {
|
||||||
ServiceResponse<ActiveSubscription> activeSubscription = ApplicationDependencies.getDonationsService()
|
ServiceResponse<ActiveSubscription> activeSubscription = ApplicationDependencies.getDonationsService()
|
||||||
.getSubscription(subscriberId)
|
.getSubscription(subscriberId)
|
||||||
.blockingGet();
|
.blockingGet();
|
||||||
|
|
||||||
if (activeSubscription.getResult().isPresent()) {
|
if (activeSubscription.getResult().isPresent()) {
|
||||||
return activeSubscription.getResult().get().getActiveSubscription();
|
return activeSubscription.getResult().get();
|
||||||
} else if (activeSubscription.getApplicationError().isPresent()) {
|
} else if (activeSubscription.getApplicationError().isPresent()) {
|
||||||
Log.w(TAG, "Unrecoverable error getting the user's current subscription. Failing.", activeSubscription.getApplicationError().get(), true);
|
Log.w(TAG, "Unrecoverable error getting the user's current subscription. Failing.", activeSubscription.getApplicationError().get(), true);
|
||||||
DonationError.routeDonationError(context, DonationError.genericBadgeRedemptionFailure(getErrorSource()));
|
DonationError.routeDonationError(context, DonationError.genericBadgeRedemptionFailure(getErrorSource()));
|
||||||
|
@ -234,7 +241,7 @@ public class SubscriptionReceiptRequestResponseJob extends BaseJob {
|
||||||
throw new Exception(response.getApplicationError().get());
|
throw new Exception(response.getApplicationError().get());
|
||||||
case 402:
|
case 402:
|
||||||
Log.w(TAG, "Subscription payment failure in credential response.", response.getApplicationError().get(), true);
|
Log.w(TAG, "Subscription payment failure in credential response.", response.getApplicationError().get(), true);
|
||||||
onPaymentFailure(null, 0L);
|
onPaymentFailure(null, null, 0L);
|
||||||
throw new Exception(response.getApplicationError().get());
|
throw new Exception(response.getApplicationError().get());
|
||||||
case 403:
|
case 403:
|
||||||
Log.w(TAG, "SubscriberId password mismatch or account auth was present.", response.getApplicationError().get(), true);
|
Log.w(TAG, "SubscriberId password mismatch or account auth was present.", response.getApplicationError().get(), true);
|
||||||
|
@ -253,11 +260,12 @@ public class SubscriptionReceiptRequestResponseJob extends BaseJob {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onPaymentFailure(@Nullable String status, long timestamp) {
|
private void onPaymentFailure(@Nullable String status, @Nullable ActiveSubscription.ChargeFailure chargeFailure, long timestamp) {
|
||||||
SignalStore.donationsValues().setShouldCancelSubscriptionBeforeNextSubscribeAttempt(true);
|
SignalStore.donationsValues().setShouldCancelSubscriptionBeforeNextSubscribeAttempt(true);
|
||||||
if (status == null) {
|
if (status == null) {
|
||||||
DonationError.routeDonationError(context, DonationError.genericPaymentFailure(getErrorSource()));
|
DonationError.routeDonationError(context, DonationError.genericPaymentFailure(getErrorSource()));
|
||||||
} else {
|
} else {
|
||||||
|
SignalStore.donationsValues().setUnexpectedSubscriptionCancelationChargeFailure(chargeFailure);
|
||||||
SignalStore.donationsValues().setUnexpectedSubscriptionCancelationReason(status);
|
SignalStore.donationsValues().setUnexpectedSubscriptionCancelationReason(status);
|
||||||
SignalStore.donationsValues().setUnexpectedSubscriptionCancelationTimestamp(timestamp);
|
SignalStore.donationsValues().setUnexpectedSubscriptionCancelationTimestamp(timestamp);
|
||||||
MultiDeviceSubscriptionSyncRequestJob.enqueue();
|
MultiDeviceSubscriptionSyncRequestJob.enqueue();
|
||||||
|
|
|
@ -11,8 +11,10 @@ import org.thoughtcrime.securesms.database.model.databaseprotos.BadgeList
|
||||||
import org.thoughtcrime.securesms.payments.currency.CurrencyUtil
|
import org.thoughtcrime.securesms.payments.currency.CurrencyUtil
|
||||||
import org.thoughtcrime.securesms.subscription.LevelUpdateOperation
|
import org.thoughtcrime.securesms.subscription.LevelUpdateOperation
|
||||||
import org.thoughtcrime.securesms.subscription.Subscriber
|
import org.thoughtcrime.securesms.subscription.Subscriber
|
||||||
|
import org.whispersystems.signalservice.api.subscriptions.ActiveSubscription
|
||||||
import org.whispersystems.signalservice.api.subscriptions.IdempotencyKey
|
import org.whispersystems.signalservice.api.subscriptions.IdempotencyKey
|
||||||
import org.whispersystems.signalservice.api.subscriptions.SubscriberId
|
import org.whispersystems.signalservice.api.subscriptions.SubscriberId
|
||||||
|
import org.whispersystems.signalservice.internal.util.JsonUtil
|
||||||
import java.util.Currency
|
import java.util.Currency
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
@ -34,6 +36,7 @@ internal class DonationsValues internal constructor(store: KeyValueStore) : Sign
|
||||||
private const val DISPLAY_BADGES_ON_PROFILE = "donation.display.badges.on.profile"
|
private const val DISPLAY_BADGES_ON_PROFILE = "donation.display.badges.on.profile"
|
||||||
private const val SUBSCRIPTION_REDEMPTION_FAILED = "donation.subscription.redemption.failed"
|
private const val SUBSCRIPTION_REDEMPTION_FAILED = "donation.subscription.redemption.failed"
|
||||||
private const val SHOULD_CANCEL_SUBSCRIPTION_BEFORE_NEXT_SUBSCRIBE_ATTEMPT = "donation.should.cancel.subscription.before.next.subscribe.attempt"
|
private const val SHOULD_CANCEL_SUBSCRIPTION_BEFORE_NEXT_SUBSCRIBE_ATTEMPT = "donation.should.cancel.subscription.before.next.subscribe.attempt"
|
||||||
|
private const val SUBSCRIPTION_CANCELATION_CHARGE_FAILURE = "donation.subscription.cancelation.charge.failure"
|
||||||
private const val SUBSCRIPTION_CANCELATION_REASON = "donation.subscription.cancelation.reason"
|
private const val SUBSCRIPTION_CANCELATION_REASON = "donation.subscription.cancelation.reason"
|
||||||
private const val SUBSCRIPTION_CANCELATION_TIMESTAMP = "donation.subscription.cancelation.timestamp"
|
private const val SUBSCRIPTION_CANCELATION_TIMESTAMP = "donation.subscription.cancelation.timestamp"
|
||||||
private const val SUBSCRIPTION_CANCELATION_WATERMARK = "donation.subscription.cancelation.watermark"
|
private const val SUBSCRIPTION_CANCELATION_WATERMARK = "donation.subscription.cancelation.watermark"
|
||||||
|
@ -233,6 +236,23 @@ internal class DonationsValues internal constructor(store: KeyValueStore) : Sign
|
||||||
putBoolean(SUBSCRIPTION_REDEMPTION_FAILED, false)
|
putBoolean(SUBSCRIPTION_REDEMPTION_FAILED, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun setUnexpectedSubscriptionCancelationChargeFailure(chargeFailure: ActiveSubscription.ChargeFailure?) {
|
||||||
|
if (chargeFailure == null) {
|
||||||
|
remove(SUBSCRIPTION_CANCELATION_CHARGE_FAILURE)
|
||||||
|
} else {
|
||||||
|
putString(SUBSCRIPTION_CANCELATION_CHARGE_FAILURE, JsonUtil.toJson(chargeFailure))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getUnexpectedSubscriptionCancelationChargeFailure(): ActiveSubscription.ChargeFailure? {
|
||||||
|
val json = getString(SUBSCRIPTION_CANCELATION_CHARGE_FAILURE, null)
|
||||||
|
return if (json.isNullOrEmpty()) {
|
||||||
|
null
|
||||||
|
} else {
|
||||||
|
JsonUtil.fromJson(json, ActiveSubscription.ChargeFailure::class.java)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var unexpectedSubscriptionCancelationReason: String? by stringValue(SUBSCRIPTION_CANCELATION_REASON, null)
|
var unexpectedSubscriptionCancelationReason: String? by stringValue(SUBSCRIPTION_CANCELATION_REASON, null)
|
||||||
var unexpectedSubscriptionCancelationTimestamp: Long by longValue(SUBSCRIPTION_CANCELATION_TIMESTAMP, 0L)
|
var unexpectedSubscriptionCancelationTimestamp: Long by longValue(SUBSCRIPTION_CANCELATION_TIMESTAMP, 0L)
|
||||||
var unexpectedSubscriptionCancelationWatermark: Long by longValue(SUBSCRIPTION_CANCELATION_WATERMARK, 0L)
|
var unexpectedSubscriptionCancelationWatermark: Long by longValue(SUBSCRIPTION_CANCELATION_WATERMARK, 0L)
|
||||||
|
|
|
@ -11,6 +11,8 @@ import java.util.Set;
|
||||||
|
|
||||||
public final class ActiveSubscription {
|
public final class ActiveSubscription {
|
||||||
|
|
||||||
|
public static final ActiveSubscription EMPTY = new ActiveSubscription(null, null);
|
||||||
|
|
||||||
private enum Status {
|
private enum Status {
|
||||||
/**
|
/**
|
||||||
* The subscription is currently in a trial period and it's safe to provision your product for your customer.
|
* The subscription is currently in a trial period and it's safe to provision your product for your customer.
|
||||||
|
@ -35,7 +37,7 @@ public final class ActiveSubscription {
|
||||||
INCOMPLETE_EXPIRED("incomplete_expired"),
|
INCOMPLETE_EXPIRED("incomplete_expired"),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Payment on the latest invoice either failed or wasn't attempted.
|
* Payment on the latest invoice either failed or wasn't attempted.
|
||||||
*/
|
*/
|
||||||
PAST_DUE("past_due"),
|
PAST_DUE("past_due"),
|
||||||
|
|
||||||
|
@ -78,17 +80,25 @@ public final class ActiveSubscription {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Subscription activeSubscription;
|
private final Subscription activeSubscription;
|
||||||
|
private final ChargeFailure chargeFailure;
|
||||||
|
|
||||||
@JsonCreator
|
@JsonCreator
|
||||||
public ActiveSubscription(@JsonProperty("subscription") Subscription activeSubscription) {
|
public ActiveSubscription(@JsonProperty("subscription") Subscription activeSubscription,
|
||||||
|
@JsonProperty("chargeFailure") ChargeFailure chargeFailure)
|
||||||
|
{
|
||||||
this.activeSubscription = activeSubscription;
|
this.activeSubscription = activeSubscription;
|
||||||
|
this.chargeFailure = chargeFailure;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Subscription getActiveSubscription() {
|
public Subscription getActiveSubscription() {
|
||||||
return activeSubscription;
|
return activeSubscription;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ChargeFailure getChargeFailure() {
|
||||||
|
return chargeFailure;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isActive() {
|
public boolean isActive() {
|
||||||
return activeSubscription != null && activeSubscription.isActive();
|
return activeSubscription != null && activeSubscription.isActive();
|
||||||
}
|
}
|
||||||
|
@ -98,7 +108,7 @@ public final class ActiveSubscription {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isFailedPayment() {
|
public boolean isFailedPayment() {
|
||||||
return activeSubscription != null && !isActive() && activeSubscription.isFailedPayment();
|
return chargeFailure != null || (activeSubscription != null && !isActive() && activeSubscription.isFailedPayment());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class Subscription {
|
public static final class Subscription {
|
||||||
|
@ -199,4 +209,75 @@ public final class ActiveSubscription {
|
||||||
return Objects.hash(level, currency, amount, endOfCurrentPeriod, isActive, billingCycleAnchor, willCancelAtPeriodEnd, status);
|
return Objects.hash(level, currency, amount, endOfCurrentPeriod, isActive, billingCycleAnchor, willCancelAtPeriodEnd, status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static final class ChargeFailure {
|
||||||
|
private final String code;
|
||||||
|
private final String message;
|
||||||
|
private final String outcomeNetworkStatus;
|
||||||
|
private final String outcomeNetworkReason;
|
||||||
|
private final String outcomeType;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public ChargeFailure(@JsonProperty("code") String code,
|
||||||
|
@JsonProperty("message") String message,
|
||||||
|
@JsonProperty("outcomeNetworkStatus") String outcomeNetworkStatus,
|
||||||
|
@JsonProperty("outcomeNetworkReason") String outcomeNetworkReason,
|
||||||
|
@JsonProperty("outcomeType") String outcomeType)
|
||||||
|
{
|
||||||
|
this.code = code;
|
||||||
|
this.message = message;
|
||||||
|
this.outcomeNetworkStatus = outcomeNetworkStatus;
|
||||||
|
this.outcomeNetworkReason = outcomeNetworkReason;
|
||||||
|
this.outcomeType = outcomeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Error code explaining reason for charge failure if available (see the errors section for a list of codes).
|
||||||
|
* <p>
|
||||||
|
* See: <a href="https://stripe.com/docs/api/charges/object#charge_object-failure_code">https://stripe.com/docs/api/charges/object#charge_object-failure_code</a>
|
||||||
|
*/
|
||||||
|
public String getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Message to user further explaining reason for charge failure if available.
|
||||||
|
* <p>
|
||||||
|
* See: <a href="https://stripe.com/docs/api/charges/object#charge_object-failure_message">https://stripe.com/docs/api/charges/object#charge_object-failure_message</a>
|
||||||
|
*/
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Possible values are approved_by_network, declined_by_network, not_sent_to_network, and reversed_after_approval.
|
||||||
|
* The value reversed_after_approval indicates the payment was blocked by Stripe after bank authorization,
|
||||||
|
* and may temporarily appear as “pending” on a cardholder’s statement.
|
||||||
|
* <p>
|
||||||
|
* See: <a href="https://stripe.com/docs/api/charges/object#charge_object-outcome-network_status">https://stripe.com/docs/api/charges/object#charge_object-outcome-network_status</a>
|
||||||
|
*/
|
||||||
|
public String getOutcomeNetworkStatus() {
|
||||||
|
return outcomeNetworkStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An enumerated value providing a more detailed explanation of the outcome’s type. Charges blocked by Radar’s default block rule have the value
|
||||||
|
* highest_risk_level. Charges placed in review by Radar’s default review rule have the value elevated_risk_level. Charges authorized, blocked, or placed
|
||||||
|
* in review by custom rules have the value rule. See understanding declines for more details.
|
||||||
|
* <p>
|
||||||
|
* See: <a href="https://stripe.com/docs/api/charges/object#charge_object-outcome-reason">https://stripe.com/docs/api/charges/object#charge_object-outcome-reason</a>
|
||||||
|
*/
|
||||||
|
public String getOutcomeNetworkReason() {
|
||||||
|
return outcomeNetworkReason;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Possible values are authorized, manual_review, issuer_declined, blocked, and invalid. See understanding declines and Radar reviews for details.
|
||||||
|
* <p>
|
||||||
|
* See: <a href="https://stripe.com/docs/api/charges/object#charge_object-outcome-type">https://stripe.com/docs/api/charges/object#charge_object-outcome-type</a>
|
||||||
|
*/
|
||||||
|
public String getOutcomeType() {
|
||||||
|
return outcomeType;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,6 +64,6 @@ public class DonationsServiceTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
private ActiveSubscription getActiveSubscription() {
|
private ActiveSubscription getActiveSubscription() {
|
||||||
return new ActiveSubscription(null);
|
return ActiveSubscription.EMPTY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Ładowanie…
Reference in New Issue