membership-attribute-service/app/services/zuora/payment/SetPaymentCard.scala (49 lines of code) (raw):
package services.zuora.payment
import com.gu.memsub.Subscription.AccountId
import com.gu.memsub.{CardUpdateFailure, CardUpdateSuccess, PaymentCard, PaymentCardDetails, PaymentCardUpdateResult}
import com.gu.monitoring.SafeLogger.LogPrefix
import com.gu.stripe.Stripe
import com.gu.zuora.ZuoraSoapService
import scalaz.Monad
import services.stripe.StripeService
import utils.SimpleEitherT
import utils.SimpleEitherT.SimpleEitherT
import scala.concurrent.{ExecutionContext, Future}
class SetPaymentCard(zuoraService: ZuoraSoapService, stripeServiceEither: Either[String, StripeService])(implicit
ec: ExecutionContext,
m: Monad[Future],
) {
def setPaymentCard(useStripePaymentMethod: Boolean, accountId: AccountId, stripeCardIdentifier: String)(implicit
logPrefix: LogPrefix,
): SimpleEitherT[PaymentCardUpdateResult] = {
for {
stripeService <- SimpleEitherT.fromEither(stripeServiceEither)
result <- SimpleEitherT.rightT(setPaymentCard(useStripePaymentMethod, stripeService)(accountId, stripeCardIdentifier))
} yield result
}
private def setPaymentCard(
useStripePaymentMethod: Boolean,
stripeService: StripeService,
)(accountId: AccountId, stripeCardIdentifier: String)(implicit logPrefix: LogPrefix): Future[PaymentCardUpdateResult] = {
val createCustomerFunction =
if (useStripePaymentMethod)
stripeService.createCustomerWithStripePaymentMethod(_)
else
stripeService.createCustomer(_)
(for {
customer <- createCustomerFunction(stripeCardIdentifier)
_ <- zuoraService
.createCreditCardPaymentMethod(accountId, customer, stripeService.paymentIntentsGateway)
} yield {
CardUpdateSuccess(
PaymentCard(
isReferenceTransaction = true,
cardType = Some(customer.card.`type`),
paymentCardDetails = Some(PaymentCardDetails(customer.card.last4, customer.card.exp_month, customer.card.exp_year)),
),
)
}).recover { case error: Stripe.Error =>
CardUpdateFailure(error.`type`, error.message.getOrElse(""), error.code.getOrElse("unknown"))
}
}
}