diff --git a/support-payment-api/src/main/scala/model/Currency.scala b/support-payment-api/src/main/scala/model/Currency.scala index 61b214d58f..23cde2b367 100644 --- a/support-payment-api/src/main/scala/model/Currency.scala +++ b/support-payment-api/src/main/scala/model/Currency.scala @@ -4,6 +4,10 @@ import enumeratum.{CirceEnum, Enum, EnumEntry} import scala.collection.immutable.IndexedSeq +case class Range(min: BigDecimal, max: BigDecimal) { + def contains(amount: BigDecimal): Boolean = (amount >= min) && (amount <= max) +} + // Models currencies supported by the API sealed trait Currency extends EnumEntry @@ -23,13 +27,16 @@ object Currency extends Enum[Currency] with CirceEnum[Currency] { case object NZD extends Currency - def exceedsMaxAmount(amount: BigDecimal, currency: Currency): Boolean = { - val maxAmount = currency match { - case AUD => 16000 - case USD => 10000 - case _ => 2000 - } + def isAmountOutOfBounds(amount: BigDecimal, currency: Currency): Boolean = { // Users can opt in to add 4% to cover the transaction cost - amount > maxAmount * 1.04 + val transactionCostAsPercentage = 1.04 + + val currencyRange = currency match { + case AUD => Range(min = 1, max = 16000 * transactionCostAsPercentage) + case USD => Range(min = 1, max = 10000 * transactionCostAsPercentage) + case _ => Range(min = 1, max = 2000 * transactionCostAsPercentage) + } + + !currencyRange.contains(amount) } } diff --git a/support-payment-api/src/main/scala/services/PaypalService.scala b/support-payment-api/src/main/scala/services/PaypalService.scala index d2f705ea89..8de5d88c39 100644 --- a/support-payment-api/src/main/scala/services/PaypalService.scala +++ b/support-payment-api/src/main/scala/services/PaypalService.scala @@ -25,8 +25,8 @@ trait Paypal { class PaypalService(config: PaypalConfig)(implicit pool: PaypalThreadPool) extends Paypal with StrictLogging { def createPayment(createPaypalPaymentData: CreatePaypalPaymentData): PaypalResult[Payment] = { - if (model.Currency.exceedsMaxAmount(createPaypalPaymentData.amount, createPaypalPaymentData.currency)) { - Left(PaypalApiError.fromString("Amount exceeds the maximum allowed ")).toEitherT[Future] + if (model.Currency.isAmountOutOfBounds(createPaypalPaymentData.amount, createPaypalPaymentData.currency)) { + Left(PaypalApiError.fromString("Amount is outside the allowed range ")).toEitherT[Future] } else { Either .catchNonFatal { diff --git a/support-payment-api/src/main/scala/services/StripeService.scala b/support-payment-api/src/main/scala/services/StripeService.scala index 754dd831b6..375e143a45 100644 --- a/support-payment-api/src/main/scala/services/StripeService.scala +++ b/support-payment-api/src/main/scala/services/StripeService.scala @@ -45,8 +45,8 @@ class SingleAccountStripeService(config: StripeAccountConfig)(implicit pool: Str ).asJava def createCharge(data: LegacyStripeChargeRequest): EitherT[Future, StripeApiError, Charge] = { - if (model.Currency.exceedsMaxAmount(data.paymentData.amount, data.paymentData.currency)) { - Left(StripeApiError.fromString("Amount exceeds the maximum allowed ", Some(config.publicKey))).toEitherT[Future] + if (model.Currency.isAmountOutOfBounds(data.paymentData.amount, data.paymentData.currency)) { + Left(StripeApiError.fromString("Amount is outside the allowed range ", Some(config.publicKey))).toEitherT[Future] } else { Future(Charge.create(getChargeParams(data), requestOptions)).attemptT .bimap( @@ -79,8 +79,8 @@ class SingleAccountStripeService(config: StripeAccountConfig)(implicit pool: Str def createPaymentIntent( data: StripePaymentIntentRequest.CreatePaymentIntent, ): EitherT[Future, StripeApiError, PaymentIntent] = { - if (model.Currency.exceedsMaxAmount(data.paymentData.amount, data.paymentData.currency)) { - Left(StripeApiError.fromString("Amount exceeds the maximum allowed ", Some(config.publicKey))).toEitherT[Future] + if (model.Currency.isAmountOutOfBounds(data.paymentData.amount, data.paymentData.currency)) { + Left(StripeApiError.fromString("Amount is outside the allowed range ", Some(config.publicKey))).toEitherT[Future] } else { Future { diff --git a/support-payment-api/src/test/scala/model/CurrencyTest.scala b/support-payment-api/src/test/scala/model/CurrencyTest.scala new file mode 100644 index 0000000000..8e1303a32d --- /dev/null +++ b/support-payment-api/src/test/scala/model/CurrencyTest.scala @@ -0,0 +1,22 @@ +package model + +import org.scalatest.flatspec.AnyFlatSpec +import org.scalatest.matchers.must.Matchers + +class CurrencyTest extends AnyFlatSpec with Matchers { + "exceedsMaxAmount" should "return true if the amount is greater than the allowed range" in { + Currency.isAmountOutOfBounds(2100, Currency.GBP) mustBe true + } + + it should "return true if the amount is below the allowed range" in { + Currency.isAmountOutOfBounds(0.5, Currency.GBP) mustBe true + } + + it should "return false if the amount is within the allowed range" in { + Currency.isAmountOutOfBounds(100, Currency.GBP) mustBe false + } + + it should "allow the amount to be 4% larger than the nominal max to allow for covering transaction cost" in { + Currency.isAmountOutOfBounds(2080, Currency.GBP) mustBe false + } +} diff --git a/support-payment-api/src/test/scala/services/PaypalServiceSpec.scala b/support-payment-api/src/test/scala/services/PaypalServiceSpec.scala index 2363242394..912386a533 100644 --- a/support-payment-api/src/test/scala/services/PaypalServiceSpec.scala +++ b/support-payment-api/src/test/scala/services/PaypalServiceSpec.scala @@ -114,14 +114,14 @@ class PaypalServiceSpec extends AnyFlatSpec with Matchers with MockitoSugar with it should "return an error if the payment amount exceeds Australia max" in new PaypalServiceTestFixture { val createPaypalPaymentData = CreatePaypalPaymentData(Currency.AUD, 16640.50, "url", "url") whenReady(paypalService.createPayment(createPaypalPaymentData).value) { result => - result mustBe (Left(PaypalApiError.fromString("Amount exceeds the maximum allowed "))) + result mustBe (Left(PaypalApiError.fromString("Amount is outside the allowed range "))) } } it should "return an error if the payment amount exceeds non-Australia max" in new PaypalServiceTestFixture { val createPaypalPaymentData = CreatePaypalPaymentData(Currency.GBP, 2080.50, "url", "url") whenReady(paypalService.createPayment(createPaypalPaymentData).value) { result => - result mustBe (Left(PaypalApiError.fromString("Amount exceeds the maximum allowed "))) + result mustBe (Left(PaypalApiError.fromString("Amount is outside the allowed range "))) } }