Support changing just the currency of an existing subscription
This commit is contained in:
parent
e8978ef91c
commit
dd98f7f043
|
@ -516,16 +516,19 @@ public class SubscriptionController {
|
|||
// and needs to call create_payment_method to create a customer for the given payment method
|
||||
new ClientErrorException(Status.CONFLICT));
|
||||
|
||||
final String subscriptionTemplateId = getSubscriptionTemplateId(level, currency, processorCustomer.processor());
|
||||
final String subscriptionTemplateId = getSubscriptionTemplateId(level, currency,
|
||||
processorCustomer.processor());
|
||||
|
||||
final SubscriptionProcessorManager manager = getManagerForProcessor(processorCustomer.processor());
|
||||
|
||||
return Optional.ofNullable(record.subscriptionId)
|
||||
.map(subId -> {
|
||||
// we already have a subscription in our records so let's check the level and change it if needed
|
||||
return Optional.ofNullable(record.subscriptionId).map(subId -> {
|
||||
// we already have a subscription in our records so let's check the level and currency,
|
||||
// and only change it if needed
|
||||
return manager.getSubscription(subId).thenCompose(
|
||||
subscription -> manager.getLevelForSubscription(subscription).thenCompose(existingLevel -> {
|
||||
if (level == existingLevel) {
|
||||
subscription -> manager.getLevelAndCurrencyForSubscription(subscription)
|
||||
.thenCompose(existingLevelAndCurrency -> {
|
||||
if (existingLevelAndCurrency.equals(new SubscriptionProcessorManager.LevelAndCurrency(level,
|
||||
currency.toLowerCase(Locale.ROOT)))) {
|
||||
return CompletableFuture.completedFuture(subscription);
|
||||
}
|
||||
return manager.updateSubscription(
|
||||
|
@ -541,9 +544,6 @@ public class SubscriptionController {
|
|||
record.subscriptionCreatedAt != null ? record.subscriptionCreatedAt.getEpochSecond() : 0;
|
||||
|
||||
// we don't have a subscription yet so create it and then record the subscription id
|
||||
//
|
||||
// this relies on stripe's idempotency key to avoid creating more than one subscription if the client
|
||||
// retries this request
|
||||
return manager.createSubscription(processorCustomer.customerId(),
|
||||
subscriptionTemplateId,
|
||||
level,
|
||||
|
|
|
@ -358,11 +358,13 @@ public class BraintreeManager implements SubscriptionProcessorManager {
|
|||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Long> getLevelForSubscription(Object subscriptionObj) {
|
||||
public CompletableFuture<LevelAndCurrency> getLevelAndCurrencyForSubscription(Object subscriptionObj) {
|
||||
final Subscription subscription = getSubscription(subscriptionObj);
|
||||
|
||||
return findPlan(subscription.getPlanId())
|
||||
.thenApply(this::getLevelForPlan);
|
||||
.thenApply(
|
||||
plan -> new LevelAndCurrency(getLevelForPlan(plan), plan.getCurrencyIsoCode().toLowerCase(Locale.ROOT)));
|
||||
|
||||
}
|
||||
|
||||
private CompletableFuture<Plan> findPlan(String planId) {
|
||||
|
|
|
@ -246,6 +246,8 @@ public class StripeManager implements SubscriptionProcessorManager {
|
|||
@Override
|
||||
public CompletableFuture<SubscriptionId> createSubscription(String customerId, String priceId, long level,
|
||||
long lastSubscriptionCreatedAt) {
|
||||
// this relies on Stripe's idempotency key to avoid creating more than one subscription if the client
|
||||
// retries this request
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
SubscriptionCreateParams params = SubscriptionCreateParams.builder()
|
||||
.setCustomer(customerId)
|
||||
|
@ -274,9 +276,7 @@ public class StripeManager implements SubscriptionProcessorManager {
|
|||
public CompletableFuture<SubscriptionId> updateSubscription(
|
||||
Object subscriptionObj, String priceId, long level, String idempotencyKey) {
|
||||
|
||||
if (!(subscriptionObj instanceof final Subscription subscription)) {
|
||||
throw new IllegalArgumentException("invalid subscription object: " + subscriptionObj.getClass().getName());
|
||||
}
|
||||
final Subscription subscription = getSubscription(subscriptionObj);
|
||||
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
List<SubscriptionUpdateParams.Item> items = new ArrayList<>();
|
||||
|
@ -400,12 +400,12 @@ public class StripeManager implements SubscriptionProcessorManager {
|
|||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Long> getLevelForSubscription(Object subscriptionObj) {
|
||||
if (!(subscriptionObj instanceof final Subscription subscription)) {
|
||||
public CompletableFuture<LevelAndCurrency> getLevelAndCurrencyForSubscription(Object subscriptionObj) {
|
||||
final Subscription subscription = getSubscription(subscriptionObj);
|
||||
|
||||
throw new IllegalArgumentException("Invalid subscription object: " + subscriptionObj.getClass().getName());
|
||||
}
|
||||
return getProductForSubscription(subscription).thenApply(this::getLevelForProduct);
|
||||
return getProductForSubscription(subscription).thenApply(
|
||||
product -> new LevelAndCurrency(getLevelForProduct(product), subscription.getCurrency().toLowerCase(
|
||||
Locale.ROOT)));
|
||||
}
|
||||
|
||||
public CompletableFuture<Long> getLevelForPrice(Price price) {
|
||||
|
|
|
@ -47,7 +47,11 @@ public interface SubscriptionProcessorManager {
|
|||
CompletableFuture<SubscriptionId> updateSubscription(
|
||||
Object subscription, String templateId, long level, String idempotencyKey);
|
||||
|
||||
CompletableFuture<Long> getLevelForSubscription(Object subscription);
|
||||
/**
|
||||
* @param subscription
|
||||
* @return the subscription’s current level and lower-case currency code
|
||||
*/
|
||||
CompletableFuture<LevelAndCurrency> getLevelAndCurrencyForSubscription(Object subscription);
|
||||
|
||||
CompletableFuture<Void> cancelAllActiveSubscriptions(String customerId);
|
||||
|
||||
|
@ -160,4 +164,8 @@ public interface SubscriptionProcessorManager {
|
|||
|
||||
}
|
||||
|
||||
record LevelAndCurrency(long level, String currency) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -72,7 +72,6 @@ import org.whispersystems.textsecuregcm.subscriptions.StripeManager;
|
|||
import org.whispersystems.textsecuregcm.subscriptions.SubscriptionProcessor;
|
||||
import org.whispersystems.textsecuregcm.subscriptions.SubscriptionProcessorManager;
|
||||
import org.whispersystems.textsecuregcm.tests.util.AuthHelper;
|
||||
import org.whispersystems.textsecuregcm.util.Pair;
|
||||
import org.whispersystems.textsecuregcm.util.SystemMapper;
|
||||
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
|
||||
|
||||
|
@ -548,7 +547,8 @@ class SubscriptionControllerTest {
|
|||
when(BRAINTREE_MANAGER.getSubscription(any()))
|
||||
.thenReturn(CompletableFuture.completedFuture(subscriptionObj));
|
||||
when(BRAINTREE_MANAGER.getLevelAndCurrencyForSubscription(subscriptionObj))
|
||||
.thenReturn(CompletableFuture.completedFuture(new Pair<>(existingLevel, existingCurrency)));
|
||||
.thenReturn(CompletableFuture.completedFuture(
|
||||
new SubscriptionProcessorManager.LevelAndCurrency(existingLevel, existingCurrency)));
|
||||
final String updatedSubscriptionId = "updatedSubscriptionId";
|
||||
|
||||
if (expectUpdate) {
|
||||
|
|
Loading…
Reference in New Issue