in support-payment-api/src/main/scala/backend/StripeBackend.scala [83:166]
def createPaymentIntent(
request: StripePaymentIntentRequest.CreatePaymentIntent,
clientBrowserInfo: ClientBrowserInfo,
): EitherT[Future, StripeApiError, StripePaymentIntentsApiResponse] = {
def isApplePayOrPaymentRequestButton = request.paymentData.stripePaymentMethod match {
case Some(StripeApplePay) | Some(StripePaymentRequestButton) => true
case _ => false
}
def isValidEmail(email: String): Boolean = {
!email.contains(",")
}
// Check the Switch Bypass Recaptcha for Test Stripe account // Apple Pay on Live
// Note that in DEV/CODE there is no Live StripeBackend, so it will never verify Recaptcha
def recaptchaRequired() =
recaptchaEnabled.map {
case true =>
environment match {
case Live if isApplePayOrPaymentRequestButton =>
false
case Live =>
true
case Test =>
false
}
case _ =>
false
}
def createIntent(): EitherT[Future, StripeApiError, StripePaymentIntentsApiResponse] = {
stripeService
.createPaymentIntent(request)
.leftMap(err => {
logger.info(
s"Unable to create Stripe Payment Intent ($request). User-Agent was: ${clientBrowserInfo.userAgent}",
)
cloudWatchService.recordFailedPayment(err, PaymentProvider.Stripe)
err
})
.flatMap { paymentIntent =>
// https://stripe.com/docs/payments/intents#intent-statuses
paymentIntent.getStatus match {
case "requires_action" =>
// 3DS required, return the clientSecret to the client
EitherT.fromEither(Right(StripePaymentIntentsApiResponse.RequiresAction(paymentIntent.getClientSecret)))
case "succeeded" =>
// Payment complete without the need for 3DS - do post-payment tasks and return success to client
EitherT.liftF[Future, StripeApiError, StripePaymentIntentsApiResponse](
paymentIntentSucceeded(request, paymentIntent, clientBrowserInfo),
)
case otherStatus =>
logger.info(s"Unexpected status on Stripe Payment Intent: $otherStatus. Request was $request")
val error =
StripeApiError.fromString(s"Unexpected status on Stripe Payment Intent: $otherStatus", publicKey = None)
cloudWatchService.recordFailedPayment(error, PaymentProvider.Stripe)
EitherT.fromEither(Left(error))
}
}
}
def checkRecaptcha: EitherT[Future, StripeApiError, StripePaymentIntentsApiResponse] = recaptchaRequired().flatMap {
case true =>
recaptchaService
.verify(request.recaptchaToken)
.flatMap { resp =>
if (resp.success) createIntent()
else EitherT.leftT(StripeApiError.fromString(recaptchaErrorText, publicKey = None))
}
case false =>
createIntent()
}
stripeEnabled(request).flatMap {
case true =>
if (isValidEmail(request.paymentData.email.toString())) checkRecaptcha
else EitherT.leftT(StripeApiError.fromString("Invalid email address", publicKey = None))
case false =>
EitherT.leftT(StripeApiError.fromString(stripeDisabledErrorText, publicKey = None))
}
}