From cc7bb8b5494b8529318e691bf1aaa3212e3d8755 Mon Sep 17 00:00:00 2001 From: Ravi Khadiwala Date: Mon, 2 Dec 2024 13:33:56 -0600 Subject: [PATCH] Map stripe idempotency errors to 400 --- .../controllers/SubscriptionController.java | 11 +++++++ .../subscriptions/StripeManager.java | 29 +++++++++---------- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/controllers/SubscriptionController.java b/service/src/main/java/org/whispersystems/textsecuregcm/controllers/SubscriptionController.java index f98627ed1..b9ae7dd26 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/controllers/SubscriptionController.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/controllers/SubscriptionController.java @@ -343,9 +343,14 @@ public class SubscriptionController { public record Error(SetSubscriptionLevelErrorResponse.Error.Type type, String message) { public enum Type { + // The requested level was invalid UNSUPPORTED_LEVEL, + // The requested currency was invalid UNSUPPORTED_CURRENCY, + // The card could not be charged PAYMENT_REQUIRES_ACTION, + // The request arguments were invalid representing a programmer error + INVALID_ARGUMENTS } } } @@ -391,6 +396,12 @@ public class SubscriptionController { SetSubscriptionLevelErrorResponse.Error.Type.PAYMENT_REQUIRES_ACTION, null)))) .build()); })) + .exceptionally(ExceptionUtils.exceptionallyHandler(SubscriptionException.InvalidArguments.class, e -> { + throw new BadRequestException(Response.status(Response.Status.BAD_REQUEST) + .entity(new SetSubscriptionLevelErrorResponse(List.of(new SetSubscriptionLevelErrorResponse.Error( + SetSubscriptionLevelErrorResponse.Error.Type.INVALID_ARGUMENTS, e.getMessage())))) + .build()); + })) .thenApply(unused -> Response.ok(new SetSubscriptionLevelSuccessResponse(level)).build()); } diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/subscriptions/StripeManager.java b/service/src/main/java/org/whispersystems/textsecuregcm/subscriptions/StripeManager.java index d3589f935..2f217d667 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/subscriptions/StripeManager.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/subscriptions/StripeManager.java @@ -9,6 +9,7 @@ import com.google.common.base.Strings; import com.google.common.collect.Lists; import com.stripe.StripeClient; import com.stripe.exception.CardException; +import com.stripe.exception.IdempotencyException; import com.stripe.exception.StripeException; import com.stripe.model.Charge; import com.stripe.model.Customer; @@ -292,14 +293,13 @@ public class StripeManager implements CustomerAwareSubscriptionPaymentProcessor // create a subscription, we want to ensure only one gets created. return stripeClient.subscriptions() .create(params, commonOptions(generateIdempotencyKeyForCreateSubscription( - customerId, lastSubscriptionCreatedAt))); + customerId, lastSubscriptionCreatedAt))); + } catch (IdempotencyException e) { + throw ExceptionUtils.wrap(new SubscriptionException.InvalidArguments(e.getStripeError().getMessage())); + } catch (CardException e) { + throw new CompletionException( + new SubscriptionException.ProcessorException(getProvider(), createChargeFailureFromCardException(e))); } catch (StripeException e) { - - if (e instanceof CardException ce) { - throw new CompletionException( - new SubscriptionException.ProcessorException(getProvider(), createChargeFailureFromCardException(e, ce))); - } - throw new CompletionException(e); } }, executor) @@ -347,15 +347,14 @@ public class StripeManager implements CustomerAwareSubscriptionPaymentProcessor return stripeClient.subscriptions().update(subscription.getId(), params, commonOptions( generateIdempotencyKeyForSubscriptionUpdate(subscription.getCustomer(), idempotencyKey))); + } catch (IdempotencyException e) { + throw ExceptionUtils.wrap(new SubscriptionException.InvalidArguments(e.getStripeError().getMessage())); + } catch (CardException e) { + throw ExceptionUtils.wrap( + new SubscriptionException.ProcessorException(getProvider(), createChargeFailureFromCardException(e))); } catch (StripeException e) { - - if (e instanceof CardException ce) { - throw ExceptionUtils.wrap( - new SubscriptionException.ProcessorException(getProvider(), createChargeFailureFromCardException(e, ce))); - } throw ExceptionUtils.wrap(e); } - }, executor) .thenApply(subscription1 -> new SubscriptionId(subscription1.getId())); } @@ -534,9 +533,9 @@ public class StripeManager implements CustomerAwareSubscriptionPaymentProcessor outcome != null ? outcome.getType() : null); } - private static ChargeFailure createChargeFailureFromCardException(StripeException e, CardException ce) { + private static ChargeFailure createChargeFailureFromCardException(CardException e) { return new ChargeFailure( - StringUtils.defaultIfBlank(ce.getDeclineCode(), ce.getCode()), + StringUtils.defaultIfBlank(e.getDeclineCode(), e.getCode()), e.getStripeError().getMessage(), null, null,