Last active
January 7, 2020 21:02
-
-
Save pjambet/cea3d2cb71d0b914d8b0d8cdf4d04003 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
final case class OrderRequest(cardNumber: String) | |
// ... | |
val route = | |
path("order") { | |
post { | |
entity(as[OrderRequest]) { orderRequest => | |
onComplete(PurchaseService.createPurchase(orderRequest.cardNumber)) { | |
case Success(Right(result)) => | |
complete(StatusCodes.Created, result) | |
case Success(Left(error)) => | |
val jsonError = "{\"error\": \"" + error.reason + "\"}" | |
complete(StatusCodes.PaymentRequired, | |
HttpEntity(ContentTypes.`application/json`, jsonError)) | |
case Failure(exception) => | |
// This is where exceptions would ideally be sent to a service like Bugsnag or Sentry | |
system.log.error(exception, "Unexpected error") | |
complete(StatusCodes.InternalServerError, | |
HttpEntity(ContentTypes.`application/json`, | |
"{\"error\": \"Something went wrong.\"}")) | |
} | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
object PurchaseService { | |
final case class Order(orderId: String) | |
final case class PurchaseError(reason: String) | |
def createPurchase(cardNumber: String)( | |
implicit ec: ExecutionContext): Future[Either[PurchaseError, Order]] = { | |
PaymentClient.chargeCard(cardNumber).map { | |
case Right(_) => Right(Order(orderId = UUID.randomUUID().toString)) | |
case Left(error) => Left(PurchaseError(error.declineCode)) | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
object PaymentClient { | |
final case class Charge(chargeId: UUID) | |
final case class ChargeFailure(declineCode: String) | |
final class PaymentException(message: String) extends Exception(message) | |
def chargeCard(cardNumber: String)( | |
implicit ec: ExecutionContext): Future[Either[ChargeFailure, Charge]] = { | |
// Fake an API call | |
Future { | |
if (cardNumber == "valid") { | |
Right(Charge(UUID.randomUUID())) | |
} else if (cardNumber.startsWith("card_error")) { | |
val declineCode = cardNumber.split("_").toList.drop(2).mkString("_") | |
Left(ChargeFailure(declineCode)) | |
} else if (cardNumber == "rate_limit_error") { | |
throw new PaymentException("rate_limit_error") | |
} else if (cardNumber == "invalid_request_error") { | |
throw new PaymentException("invalid_request_error") | |
} else if (cardNumber == "authentication_error") { | |
throw new PaymentException("authentication_error") | |
} else if (cardNumber == "api_connection_error") { | |
throw new PaymentException("api_connection_error") | |
} else { | |
throw new PaymentException("unknown_error") | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment