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 53f5c4604..7eef41b03 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/controllers/SubscriptionController.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/controllers/SubscriptionController.java @@ -527,7 +527,7 @@ public class SubscriptionController { } if (request.level == giftConfiguration.level()) { BigDecimal amountConfigured = giftConfiguration.currencies().get(request.currency.toLowerCase(Locale.ROOT)); - if (amountConfigured == null || !amountConfigured.equals(BigDecimal.valueOf(request.amount))) { + if (amountConfigured == null || !stripeManager.convertConfiguredAmountToStripeAmount(request.currency, amountConfigured).equals(BigDecimal.valueOf(request.amount))) { throw new WebApplicationException(Response.status(Status.CONFLICT).entity(Map.of("error", "level_amount_mismatch")).build()); } } diff --git a/service/src/main/java/org/whispersystems/textsecuregcm/stripe/StripeManager.java b/service/src/main/java/org/whispersystems/textsecuregcm/stripe/StripeManager.java index 40719743d..cd7b00bb2 100644 --- a/service/src/main/java/org/whispersystems/textsecuregcm/stripe/StripeManager.java +++ b/service/src/main/java/org/whispersystems/textsecuregcm/stripe/StripeManager.java @@ -33,6 +33,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.math.BigDecimal; import java.nio.charset.StandardCharsets; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; @@ -383,6 +384,19 @@ public class StripeManager { () -> Lists.newArrayList(invoice.getLines().autoPagingIterable(null, commonOptions())), executor); } + /** + * Takes an amount as configured; for instance USD 4.99 and turns it into an amount as Stripe expects to see it. + * Stripe appears to only support 0 and 2 decimal currencies, but also has some backwards compatibility issues with 0 + * decimal currencies so this is not to any ISO standard but rather directly from Stripe's API doc page. + */ + public BigDecimal convertConfiguredAmountToStripeAmount(String currency, BigDecimal configuredAmount) { + return switch (currency.toLowerCase(Locale.ROOT)) { + // Yuck, but this list was taken from https://stripe.com/docs/currencies?presentment-currency=US + case "bif", "clp", "djf", "gnf", "jpy", "kmf", "krw", "mga", "pyg", "rwf", "vnd", "vuv", "xaf", "xof", "xpf" -> configuredAmount; + default -> configuredAmount.scaleByPowerOfTen(2); + }; + } + /** * We use a client generated idempotency key for subscription updates due to not being able to distinguish between a * call to update to level 2, then back to level 1, then back to level 2. If this all happens within Stripe's