remove HTTP layer exceptions from Stripe/Braintree managers
This commit is contained in:
parent
50bd30fb1f
commit
237d0fd4e2
|
@ -182,7 +182,6 @@ import org.whispersystems.textsecuregcm.mappers.RateLimitExceededExceptionMapper
|
|||
import org.whispersystems.textsecuregcm.mappers.RegistrationServiceSenderExceptionMapper;
|
||||
import org.whispersystems.textsecuregcm.mappers.ServerRejectedExceptionMapper;
|
||||
import org.whispersystems.textsecuregcm.mappers.SubscriptionExceptionMapper;
|
||||
import org.whispersystems.textsecuregcm.mappers.SubscriptionProcessorExceptionMapper;
|
||||
import org.whispersystems.textsecuregcm.metrics.MessageMetrics;
|
||||
import org.whispersystems.textsecuregcm.metrics.MetricsApplicationEventListener;
|
||||
import org.whispersystems.textsecuregcm.metrics.MetricsHttpChannelListener;
|
||||
|
@ -1217,7 +1216,6 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
|
|||
new ImpossiblePhoneNumberExceptionMapper(),
|
||||
new NonNormalizedPhoneNumberExceptionMapper(),
|
||||
new RegistrationServiceSenderExceptionMapper(),
|
||||
new SubscriptionProcessorExceptionMapper(),
|
||||
new SubscriptionExceptionMapper(),
|
||||
new JsonMappingExceptionMapper()
|
||||
).forEach(exceptionMapper -> {
|
||||
|
|
|
@ -5,17 +5,48 @@
|
|||
|
||||
package org.whispersystems.textsecuregcm.mappers;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import io.dropwizard.jersey.errors.ErrorMessage;
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.ext.ExceptionMapper;
|
||||
import org.whispersystems.textsecuregcm.storage.SubscriptionException;
|
||||
import java.util.Map;
|
||||
|
||||
public class SubscriptionExceptionMapper implements ExceptionMapper<SubscriptionException> {
|
||||
@VisibleForTesting
|
||||
public static final int PROCESSOR_ERROR_STATUS_CODE = 440;
|
||||
|
||||
@Override
|
||||
public Response toResponse(final SubscriptionException exception) {
|
||||
|
||||
// Some exceptions have specific error body formats
|
||||
if (exception instanceof SubscriptionException.AmountTooSmall e) {
|
||||
return Response
|
||||
.status(Response.Status.BAD_REQUEST)
|
||||
.entity(Map.of("error", "amount_too_small"))
|
||||
.type(MediaType.APPLICATION_JSON_TYPE)
|
||||
.build();
|
||||
}
|
||||
if (exception instanceof SubscriptionException.ProcessorException e) {
|
||||
return Response.status(PROCESSOR_ERROR_STATUS_CODE)
|
||||
.entity(Map.of(
|
||||
"processor", e.getProcessor().name(),
|
||||
"chargeFailure", e.getChargeFailure()
|
||||
))
|
||||
.type(MediaType.APPLICATION_JSON_TYPE)
|
||||
.build();
|
||||
}
|
||||
if (exception instanceof SubscriptionException.ChargeFailurePaymentRequired e) {
|
||||
return Response
|
||||
.status(Response.Status.PAYMENT_REQUIRED)
|
||||
.entity(Map.of("chargeFailure", e.getChargeFailure()))
|
||||
.type(MediaType.APPLICATION_JSON_TYPE)
|
||||
.build();
|
||||
}
|
||||
|
||||
// Otherwise, we'll return a generic error message WebApplicationException, with a detailed error if one is provided
|
||||
final Response.Status status = (switch (exception) {
|
||||
case SubscriptionException.NotFound e -> Response.Status.NOT_FOUND;
|
||||
case SubscriptionException.Forbidden e -> Response.Status.FORBIDDEN;
|
||||
|
@ -36,5 +67,6 @@ public class SubscriptionExceptionMapper implements ExceptionMapper<Subscription
|
|||
.fromResponse(wae.getResponse())
|
||||
.type(MediaType.APPLICATION_JSON_TYPE)
|
||||
.entity(new ErrorMessage(wae.getResponse().getStatus(), wae.getLocalizedMessage())).build();
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
/*
|
||||
* Copyright 2023 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.whispersystems.textsecuregcm.mappers;
|
||||
|
||||
import java.util.Map;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.ext.ExceptionMapper;
|
||||
import org.whispersystems.textsecuregcm.subscriptions.SubscriptionProcessorException;
|
||||
|
||||
public class SubscriptionProcessorExceptionMapper implements ExceptionMapper<SubscriptionProcessorException> {
|
||||
|
||||
public static final int EXTERNAL_SERVICE_ERROR_STATUS_CODE = 440;
|
||||
|
||||
@Override
|
||||
public Response toResponse(final SubscriptionProcessorException exception) {
|
||||
return Response.status(EXTERNAL_SERVICE_ERROR_STATUS_CODE)
|
||||
.entity(Map.of(
|
||||
"processor", exception.getProcessor().name(),
|
||||
"chargeFailure", exception.getChargeFailure()
|
||||
))
|
||||
.build();
|
||||
}
|
||||
}
|
|
@ -6,6 +6,8 @@ package org.whispersystems.textsecuregcm.storage;
|
|||
|
||||
import java.util.Optional;
|
||||
import javax.annotation.Nullable;
|
||||
import org.whispersystems.textsecuregcm.subscriptions.ChargeFailure;
|
||||
import org.whispersystems.textsecuregcm.subscriptions.PaymentProvider;
|
||||
|
||||
public class SubscriptionException extends Exception {
|
||||
|
||||
|
@ -53,39 +55,91 @@ public class SubscriptionException extends Exception {
|
|||
}
|
||||
|
||||
public static class InvalidLevel extends InvalidArguments {
|
||||
|
||||
public InvalidLevel() {
|
||||
super(null, null);
|
||||
}
|
||||
}
|
||||
|
||||
public static class AmountTooSmall extends InvalidArguments {
|
||||
|
||||
public AmountTooSmall() {
|
||||
super(null, null);
|
||||
}
|
||||
}
|
||||
|
||||
public static class PaymentRequiresAction extends InvalidArguments {
|
||||
|
||||
public PaymentRequiresAction(String message) {
|
||||
super(message, null);
|
||||
}
|
||||
|
||||
public PaymentRequiresAction() {
|
||||
super(null, null);
|
||||
}
|
||||
}
|
||||
|
||||
public static class PaymentRequired extends SubscriptionException {
|
||||
|
||||
public PaymentRequired() {
|
||||
super(null, null);
|
||||
}
|
||||
|
||||
public PaymentRequired(String message) {
|
||||
super(null, message);
|
||||
}
|
||||
}
|
||||
|
||||
public static class ChargeFailurePaymentRequired extends SubscriptionException {
|
||||
|
||||
private final ChargeFailure chargeFailure;
|
||||
|
||||
public ChargeFailurePaymentRequired(final ChargeFailure chargeFailure) {
|
||||
super(null, null);
|
||||
this.chargeFailure = chargeFailure;
|
||||
}
|
||||
|
||||
public ChargeFailure getChargeFailure() {
|
||||
return chargeFailure;
|
||||
}
|
||||
}
|
||||
|
||||
public static class ProcessorException extends SubscriptionException {
|
||||
|
||||
private final PaymentProvider processor;
|
||||
private final ChargeFailure chargeFailure;
|
||||
|
||||
public ProcessorException(final PaymentProvider processor, final ChargeFailure chargeFailure) {
|
||||
super(null, null);
|
||||
this.processor = processor;
|
||||
this.chargeFailure = chargeFailure;
|
||||
}
|
||||
|
||||
public PaymentProvider getProcessor() {
|
||||
return processor;
|
||||
}
|
||||
|
||||
public ChargeFailure getChargeFailure() {
|
||||
return chargeFailure;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempted to retrieve a receipt for a subscription that hasn't yet been charged or the invoice is in the open state
|
||||
* Attempted to retrieve a receipt for a subscription that hasn't yet been charged or the invoice is in the open
|
||||
* state
|
||||
*/
|
||||
public static class ReceiptRequestedForOpenPayment extends SubscriptionException {
|
||||
|
||||
public ReceiptRequestedForOpenPayment() {
|
||||
super(null, null);
|
||||
}
|
||||
}
|
||||
|
||||
public static class ProcessorConflict extends SubscriptionException {
|
||||
public ProcessorConflict() {
|
||||
super(null, null);
|
||||
}
|
||||
|
||||
public ProcessorConflict(final String message) {
|
||||
super(null, message);
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import com.google.cloud.pubsub.v1.PublisherInterface;
|
|||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.pubsub.v1.PubsubMessage;
|
||||
import io.micrometer.core.instrument.Metrics;
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
|
@ -39,9 +40,6 @@ import java.util.concurrent.CompletionException;
|
|||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.ws.rs.ClientErrorException;
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
import javax.ws.rs.core.Response;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.whispersystems.textsecuregcm.configuration.CircuitBreakerConfiguration;
|
||||
|
@ -199,8 +197,7 @@ public class BraintreeManager implements CustomerAwareSubscriptionPaymentProcess
|
|||
);
|
||||
|
||||
if (search.getMaximumSize() == 0) {
|
||||
return CompletableFuture.failedFuture(
|
||||
new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR));
|
||||
return CompletableFuture.failedFuture(ExceptionUtils.wrap(new IOException()));
|
||||
}
|
||||
|
||||
final Transaction successfulTx = search.getFirst();
|
||||
|
@ -214,13 +211,12 @@ public class BraintreeManager implements CustomerAwareSubscriptionPaymentProcess
|
|||
return switch (unsuccessfulTx.getProcessorResponseCode()) {
|
||||
case GENERIC_DECLINED_PROCESSOR_CODE, PAYPAL_FUNDING_INSTRUMENT_DECLINED_PROCESSOR_CODE ->
|
||||
CompletableFuture.failedFuture(
|
||||
new SubscriptionProcessorException(getProvider(), createChargeFailure(unsuccessfulTx)));
|
||||
new SubscriptionException.ProcessorException(getProvider(), createChargeFailure(unsuccessfulTx)));
|
||||
|
||||
default -> {
|
||||
logger.info("PayPal charge unexpectedly failed: {}", unsuccessfulTx.getProcessorResponseCode());
|
||||
|
||||
yield CompletableFuture.failedFuture(
|
||||
new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR));
|
||||
yield CompletableFuture.failedFuture(ExceptionUtils.wrap(new IOException()));
|
||||
}
|
||||
};
|
||||
}, executor));
|
||||
|
@ -391,7 +387,7 @@ public class BraintreeManager implements CustomerAwareSubscriptionPaymentProcess
|
|||
return getDefaultPaymentMethod(customerId)
|
||||
.thenCompose(paymentMethod -> {
|
||||
if (paymentMethod == null) {
|
||||
throw new ClientErrorException(Response.Status.CONFLICT);
|
||||
throw ExceptionUtils.wrap(new SubscriptionException.ProcessorConflict());
|
||||
}
|
||||
|
||||
final Optional<Subscription> maybeExistingSubscription = paymentMethod.getSubscriptions().stream()
|
||||
|
@ -426,7 +422,7 @@ public class BraintreeManager implements CustomerAwareSubscriptionPaymentProcess
|
|||
if (result.getTarget() != null) {
|
||||
completionException = result.getTarget().getTransactions().stream().findFirst()
|
||||
.map(transaction -> new CompletionException(
|
||||
new SubscriptionProcessorException(getProvider(), createChargeFailure(transaction))))
|
||||
new SubscriptionException.ProcessorException(getProvider(), createChargeFailure(transaction))))
|
||||
.orElseGet(() -> new CompletionException(new BraintreeException(result.getMessage())));
|
||||
} else {
|
||||
completionException = new CompletionException(new BraintreeException(result.getMessage()));
|
||||
|
@ -460,9 +456,8 @@ public class BraintreeManager implements CustomerAwareSubscriptionPaymentProcess
|
|||
return cancelSubscriptionAtEndOfCurrentPeriod(subscription)
|
||||
.thenCompose(ignored -> {
|
||||
|
||||
final Transaction transaction = getLatestTransactionForSubscription(subscription).orElseThrow(
|
||||
() -> new ClientErrorException(
|
||||
Response.Status.CONFLICT));
|
||||
final Transaction transaction = getLatestTransactionForSubscription(subscription)
|
||||
.orElseThrow(() -> ExceptionUtils.wrap(new SubscriptionException.ProcessorConflict()));
|
||||
|
||||
final Customer customer = transaction.getCustomer();
|
||||
|
||||
|
@ -615,10 +610,7 @@ public class BraintreeManager implements CustomerAwareSubscriptionPaymentProcess
|
|||
if (subscriptionStatus.equals(SubscriptionStatus.ACTIVE) || subscriptionStatus.equals(SubscriptionStatus.PAST_DUE)) {
|
||||
throw ExceptionUtils.wrap(new SubscriptionException.ReceiptRequestedForOpenPayment());
|
||||
}
|
||||
|
||||
throw new WebApplicationException(Response.status(Response.Status.PAYMENT_REQUIRED)
|
||||
.entity(Map.of("chargeFailure", createChargeFailure(transaction)))
|
||||
.build());
|
||||
throw ExceptionUtils.wrap(new SubscriptionException.ChargeFailurePaymentRequired(createChargeFailure(transaction)));
|
||||
}
|
||||
|
||||
final Instant paidAt = transaction.getSubscriptionDetails().getBillingPeriodStartDate().toInstant();
|
||||
|
|
|
@ -40,6 +40,7 @@ import com.stripe.param.SubscriptionRetrieveParams;
|
|||
import com.stripe.param.SubscriptionUpdateParams;
|
||||
import com.stripe.param.SubscriptionUpdateParams.BillingCycleAnchor;
|
||||
import com.stripe.param.SubscriptionUpdateParams.ProrationBehavior;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
@ -55,6 +56,7 @@ import java.util.List;
|
|||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CompletionException;
|
||||
|
@ -64,12 +66,6 @@ import javax.annotation.Nonnull;
|
|||
import javax.annotation.Nullable;
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import javax.ws.rs.ClientErrorException;
|
||||
import javax.ws.rs.InternalServerErrorException;
|
||||
import javax.ws.rs.NotFoundException;
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -201,7 +197,8 @@ public class StripeManager implements CustomerAwareSubscriptionPaymentProcessor
|
|||
}
|
||||
|
||||
/**
|
||||
* Creates a payment intent. May throw a 400 WebApplicationException if the amount is too small.
|
||||
* Creates a payment intent. May throw a
|
||||
* {@link SubscriptionException.AmountTooSmall} if the amount is too small.
|
||||
*/
|
||||
public CompletableFuture<PaymentIntent> createPaymentIntent(final String currency,
|
||||
final long amount,
|
||||
|
@ -223,10 +220,7 @@ public class StripeManager implements CustomerAwareSubscriptionPaymentProcessor
|
|||
return stripeClient.paymentIntents().create(builder.build(), commonOptions());
|
||||
} catch (StripeException e) {
|
||||
if ("amount_too_small".equalsIgnoreCase(e.getCode())) {
|
||||
throw new WebApplicationException(Response
|
||||
.status(Status.BAD_REQUEST)
|
||||
.entity(Map.of("error", "amount_too_small"))
|
||||
.build());
|
||||
throw ExceptionUtils.wrap(new SubscriptionException.AmountTooSmall());
|
||||
} else {
|
||||
throw new CompletionException(e);
|
||||
}
|
||||
|
@ -303,7 +297,7 @@ public class StripeManager implements CustomerAwareSubscriptionPaymentProcessor
|
|||
|
||||
if (e instanceof CardException ce) {
|
||||
throw new CompletionException(
|
||||
new SubscriptionProcessorException(getProvider(), createChargeFailureFromCardException(e, ce)));
|
||||
new SubscriptionException.ProcessorException(getProvider(), createChargeFailureFromCardException(e, ce)));
|
||||
}
|
||||
|
||||
throw new CompletionException(e);
|
||||
|
@ -356,10 +350,10 @@ public class StripeManager implements CustomerAwareSubscriptionPaymentProcessor
|
|||
} catch (StripeException e) {
|
||||
|
||||
if (e instanceof CardException ce) {
|
||||
throw new CompletionException(
|
||||
new SubscriptionProcessorException(getProvider(), createChargeFailureFromCardException(e, ce)));
|
||||
throw ExceptionUtils.wrap(
|
||||
new SubscriptionException.ProcessorException(getProvider(), createChargeFailureFromCardException(e, ce)));
|
||||
}
|
||||
throw new CompletionException(e);
|
||||
throw ExceptionUtils.wrap(e);
|
||||
}
|
||||
|
||||
}, executor)
|
||||
|
@ -385,8 +379,7 @@ public class StripeManager implements CustomerAwareSubscriptionPaymentProcessor
|
|||
public CompletableFuture<Void> cancelAllActiveSubscriptions(String customerId) {
|
||||
return getCustomer(customerId).thenCompose(customer -> {
|
||||
if (customer == null) {
|
||||
throw new InternalServerErrorException(
|
||||
"no customer record found for id " + customerId);
|
||||
throw ExceptionUtils.wrap(new IOException("no customer record found for id " + customerId));
|
||||
}
|
||||
return listNonCanceledSubscriptions(customer);
|
||||
}).thenCompose(subscriptions -> {
|
||||
|
@ -617,14 +610,15 @@ public class StripeManager implements CustomerAwareSubscriptionPaymentProcessor
|
|||
ExceptionUtils.wrap(new SubscriptionException.ReceiptRequestedForOpenPayment()));
|
||||
}
|
||||
if (!StringUtils.equalsIgnoreCase("paid", latestSubscriptionInvoice.getStatus())) {
|
||||
final Response.ResponseBuilder responseBuilder = Response.status(Status.PAYMENT_REQUIRED);
|
||||
if (latestSubscriptionInvoice.getChargeObject() != null) {
|
||||
final Charge charge = latestSubscriptionInvoice.getChargeObject();
|
||||
if (charge.getFailureCode() != null || charge.getFailureMessage() != null) {
|
||||
responseBuilder.entity(Map.of("chargeFailure", createChargeFailure(charge)));
|
||||
}
|
||||
}
|
||||
throw new WebApplicationException(responseBuilder.build());
|
||||
return CompletableFuture.failedFuture(ExceptionUtils.wrap(Optional
|
||||
.ofNullable(latestSubscriptionInvoice.getChargeObject())
|
||||
|
||||
// If the charge object has a failure reason we can present to the user, create a detailed exception
|
||||
.filter(charge -> charge.getFailureCode() != null || charge.getFailureMessage() != null)
|
||||
.<SubscriptionException> map(charge -> new SubscriptionException.ChargeFailurePaymentRequired(createChargeFailure(charge)))
|
||||
|
||||
// Otherwise, return a generic payment required error
|
||||
.orElseGet(() -> new SubscriptionException.PaymentRequired())));
|
||||
}
|
||||
|
||||
return getInvoiceLineItemsForInvoice(latestSubscriptionInvoice).thenCompose(invoiceLineItems -> {
|
||||
|
@ -688,15 +682,15 @@ public class StripeManager implements CustomerAwareSubscriptionPaymentProcessor
|
|||
// This usually indicates that the client has made requests out of order, either by not confirming
|
||||
// the SetupIntent or not having the user authorize the transaction.
|
||||
logger.debug("setupIntent {} missing expected fields", setupIntentId);
|
||||
throw new ClientErrorException(Status.CONFLICT);
|
||||
throw ExceptionUtils.wrap(new SubscriptionException.ProcessorConflict());
|
||||
}
|
||||
return setupIntent.getLatestAttemptObject().getPaymentMethodDetails().getIdeal().getGeneratedSepaDebit();
|
||||
} catch (StripeException e) {
|
||||
if (e.getStatusCode() == 404) {
|
||||
throw new NotFoundException();
|
||||
throw ExceptionUtils.wrap(new SubscriptionException.NotFound());
|
||||
}
|
||||
logger.error("unexpected error from Stripe when retrieving setupIntent {}", setupIntentId, e);
|
||||
throw new CompletionException(e);
|
||||
throw ExceptionUtils.wrap(e);
|
||||
}
|
||||
}, executor);
|
||||
}
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
/*
|
||||
* Copyright 2023 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.whispersystems.textsecuregcm.subscriptions;
|
||||
|
||||
public class SubscriptionProcessorException extends Exception {
|
||||
|
||||
private final PaymentProvider processor;
|
||||
private final ChargeFailure chargeFailure;
|
||||
|
||||
public SubscriptionProcessorException(final PaymentProvider processor,
|
||||
final ChargeFailure chargeFailure) {
|
||||
this.processor = processor;
|
||||
this.chargeFailure = chargeFailure;
|
||||
}
|
||||
|
||||
public PaymentProvider getProcessor() {
|
||||
return processor;
|
||||
}
|
||||
|
||||
public ChargeFailure getChargeFailure() {
|
||||
return chargeFailure;
|
||||
}
|
||||
}
|
|
@ -76,10 +76,10 @@ import org.whispersystems.textsecuregcm.entities.Badge;
|
|||
import org.whispersystems.textsecuregcm.entities.BadgeSvg;
|
||||
import org.whispersystems.textsecuregcm.mappers.CompletionExceptionMapper;
|
||||
import org.whispersystems.textsecuregcm.mappers.SubscriptionExceptionMapper;
|
||||
import org.whispersystems.textsecuregcm.mappers.SubscriptionProcessorExceptionMapper;
|
||||
import org.whispersystems.textsecuregcm.storage.IssuedReceiptsManager;
|
||||
import org.whispersystems.textsecuregcm.storage.OneTimeDonationsManager;
|
||||
import org.whispersystems.textsecuregcm.storage.PaymentTime;
|
||||
import org.whispersystems.textsecuregcm.storage.SubscriptionException;
|
||||
import org.whispersystems.textsecuregcm.storage.SubscriptionManager;
|
||||
import org.whispersystems.textsecuregcm.storage.Subscriptions;
|
||||
import org.whispersystems.textsecuregcm.subscriptions.BankMandateTranslator;
|
||||
|
@ -93,7 +93,6 @@ import org.whispersystems.textsecuregcm.subscriptions.PaymentStatus;
|
|||
import org.whispersystems.textsecuregcm.subscriptions.ProcessorCustomer;
|
||||
import org.whispersystems.textsecuregcm.subscriptions.StripeManager;
|
||||
import org.whispersystems.textsecuregcm.subscriptions.PaymentProvider;
|
||||
import org.whispersystems.textsecuregcm.subscriptions.SubscriptionProcessorException;
|
||||
import org.whispersystems.textsecuregcm.subscriptions.CustomerAwareSubscriptionPaymentProcessor;
|
||||
import org.whispersystems.textsecuregcm.tests.util.AuthHelper;
|
||||
import org.whispersystems.textsecuregcm.util.MockUtils;
|
||||
|
@ -133,7 +132,6 @@ class SubscriptionControllerTest {
|
|||
.addProperty(ServerProperties.UNWRAP_COMPLETION_STAGE_IN_WRITER_ENABLE, Boolean.TRUE)
|
||||
.addProvider(AuthHelper.getAuthFilter())
|
||||
.addProvider(CompletionExceptionMapper.class)
|
||||
.addProvider(SubscriptionProcessorExceptionMapper.class)
|
||||
.addProvider(new AuthValueFactoryProvider.Binder<>(AuthenticatedDevice.class))
|
||||
.addProvider(SubscriptionExceptionMapper.class)
|
||||
.setMapper(SystemMapper.jsonMapper())
|
||||
|
@ -340,7 +338,7 @@ class SubscriptionControllerTest {
|
|||
|
||||
when(BRAINTREE_MANAGER.captureOneTimePayment(anyString(), anyString(), anyString(), anyString(), anyLong(),
|
||||
anyLong(), any()))
|
||||
.thenReturn(CompletableFuture.failedFuture(new SubscriptionProcessorException(PaymentProvider.BRAINTREE,
|
||||
.thenReturn(CompletableFuture.failedFuture(new SubscriptionException.ProcessorException(PaymentProvider.BRAINTREE,
|
||||
new ChargeFailure("2046", "Declined", null, null, null))));
|
||||
|
||||
final Response response = RESOURCE_EXTENSION.target("/v1/subscription/boost/paypal/confirm")
|
||||
|
@ -351,7 +349,7 @@ class SubscriptionControllerTest {
|
|||
"currency", "usd",
|
||||
"amount", 123)));
|
||||
|
||||
assertThat(response.getStatus()).isEqualTo(SubscriptionProcessorExceptionMapper.EXTERNAL_SERVICE_ERROR_STATUS_CODE);
|
||||
assertThat(response.getStatus()).isEqualTo(SubscriptionExceptionMapper.PROCESSOR_ERROR_STATUS_CODE);
|
||||
|
||||
final Map responseMap = response.readEntity(Map.class);
|
||||
assertThat(responseMap.get("processor")).isEqualTo("BRAINTREE");
|
||||
|
@ -419,7 +417,7 @@ class SubscriptionControllerTest {
|
|||
@Test
|
||||
void createSubscriptionProcessorDeclined() {
|
||||
when(STRIPE_MANAGER.createSubscription(any(), any(), anyLong(), anyLong()))
|
||||
.thenReturn(CompletableFuture.failedFuture(new SubscriptionProcessorException(PaymentProvider.STRIPE,
|
||||
.thenReturn(CompletableFuture.failedFuture(new SubscriptionException.ProcessorException(PaymentProvider.STRIPE,
|
||||
new ChargeFailure("card_declined", "Insufficient funds", null, null, null))));
|
||||
|
||||
final String level = String.valueOf(levelId);
|
||||
|
@ -429,8 +427,7 @@ class SubscriptionControllerTest {
|
|||
.request()
|
||||
.put(Entity.json(""));
|
||||
|
||||
assertThat(response.getStatus()).isEqualTo(
|
||||
SubscriptionProcessorExceptionMapper.EXTERNAL_SERVICE_ERROR_STATUS_CODE);
|
||||
assertThat(response.getStatus()).isEqualTo(SubscriptionExceptionMapper.PROCESSOR_ERROR_STATUS_CODE);
|
||||
|
||||
final Map responseMap = response.readEntity(Map.class);
|
||||
assertThat(responseMap.get("processor")).isEqualTo("STRIPE");
|
||||
|
|
Loading…
Reference in New Issue