Add failure information for the latest charge on a subscription

This commit is contained in:
Ehren Kret 2022-04-08 11:09:00 -05:00
parent 4b8ebc9a17
commit 12f76c24b1
2 changed files with 61 additions and 14 deletions

View File

@ -9,6 +9,8 @@ import static org.whispersystems.textsecuregcm.metrics.MetricsUtil.name;
import com.codahale.metrics.annotation.Timed; import com.codahale.metrics.annotation.Timed;
import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import com.stripe.model.Invoice; import com.stripe.model.Invoice;
@ -615,6 +617,7 @@ public class SubscriptionController {
private final BigDecimal amount; private final BigDecimal amount;
private final String status; private final String status;
@JsonCreator
public Subscription( public Subscription(
@JsonProperty("level") long level, @JsonProperty("level") long level,
@JsonProperty("billingCycleAnchor") Instant billingCycleAnchor, @JsonProperty("billingCycleAnchor") Instant billingCycleAnchor,
@ -667,17 +670,46 @@ public class SubscriptionController {
} }
} }
public static class ChargeFailure {
private final String code;
private final String message;
@JsonCreator
public ChargeFailure(
@JsonProperty("code") String code,
@JsonProperty("message") String message) {
this.code = code;
this.message = message;
}
public String getCode() {
return code;
}
public String getMessage() {
return message;
}
}
private final Subscription subscription; private final Subscription subscription;
private final ChargeFailure chargeFailure;
@JsonCreator @JsonCreator
public GetSubscriptionInformationResponse( public GetSubscriptionInformationResponse(
@JsonProperty("subscription") Subscription subscription) { @JsonProperty("subscription") Subscription subscription,
@JsonProperty("chargeFailure") ChargeFailure chargeFailure) {
this.subscription = subscription; this.subscription = subscription;
this.chargeFailure = chargeFailure;
} }
public Subscription getSubscription() { public Subscription getSubscription() {
return subscription; return subscription;
} }
@JsonInclude(Include.NON_NULL)
public ChargeFailure getChargeFailure() {
return chargeFailure;
}
} }
@Timed @Timed
@ -692,21 +724,32 @@ public class SubscriptionController {
.thenApply(this::requireRecordFromGetResult) .thenApply(this::requireRecordFromGetResult)
.thenCompose(record -> { .thenCompose(record -> {
if (record.subscriptionId == null) { if (record.subscriptionId == null) {
return CompletableFuture.completedFuture(Response.ok(new GetSubscriptionInformationResponse(null)).build()); return CompletableFuture.completedFuture(Response.ok(new GetSubscriptionInformationResponse(null, null)).build());
} }
return stripeManager.getSubscription(record.subscriptionId).thenCompose(subscription -> return stripeManager.getSubscription(record.subscriptionId).thenCompose(subscription ->
stripeManager.getPriceForSubscription(subscription).thenCompose(price -> stripeManager.getPriceForSubscription(subscription).thenCompose(price ->
stripeManager.getLevelForPrice(price).thenApply(level -> Response.ok( stripeManager.getLevelForPrice(price).thenApply(level -> {
new GetSubscriptionInformationResponse(new GetSubscriptionInformationResponse.Subscription( GetSubscriptionInformationResponse.ChargeFailure chargeFailure = null;
level, if (subscription.getLatestInvoiceObject() != null && subscription.getLatestInvoiceObject().getChargeObject() != null &&
Instant.ofEpochSecond(subscription.getBillingCycleAnchor()), (subscription.getLatestInvoiceObject().getChargeObject().getFailureCode() != null || subscription.getLatestInvoiceObject().getChargeObject().getFailureMessage() != null)) {
Instant.ofEpochSecond(subscription.getCurrentPeriodEnd()), chargeFailure = new GetSubscriptionInformationResponse.ChargeFailure(
Objects.equals(subscription.getStatus(), "active"), subscription.getLatestInvoiceObject().getChargeObject().getFailureCode(),
subscription.getCancelAtPeriodEnd(), subscription.getLatestInvoiceObject().getChargeObject().getFailureMessage());
price.getCurrency().toUpperCase(Locale.ROOT), }
price.getUnitAmountDecimal(), return Response.ok(
subscription.getStatus() new GetSubscriptionInformationResponse(
))).build()))); new GetSubscriptionInformationResponse.Subscription(
level,
Instant.ofEpochSecond(subscription.getBillingCycleAnchor()),
Instant.ofEpochSecond(subscription.getCurrentPeriodEnd()),
Objects.equals(subscription.getStatus(), "active"),
subscription.getCancelAtPeriodEnd(),
price.getCurrency().toUpperCase(Locale.ROOT),
price.getUnitAmountDecimal(),
subscription.getStatus()),
chargeFailure
)).build();
})));
}); });
} }

View File

@ -245,8 +245,12 @@ public class StripeManager {
public CompletableFuture<Subscription> getSubscription(String subscriptionId) { public CompletableFuture<Subscription> getSubscription(String subscriptionId) {
return CompletableFuture.supplyAsync(() -> { return CompletableFuture.supplyAsync(() -> {
SubscriptionRetrieveParams params = SubscriptionRetrieveParams.builder()
.addExpand("latest_invoice")
.addExpand("latest_invoice.charge")
.build();
try { try {
return Subscription.retrieve(subscriptionId, commonOptions()); return Subscription.retrieve(subscriptionId, params, commonOptions());
} catch (StripeException e) { } catch (StripeException e) {
throw new CompletionException(e); throw new CompletionException(e);
} }