def createPaymentIntent()

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))
    }
  }