/** * Generated by API Builder - https://www.apibuilder.io * Service version: 0.0.0-slava * User agent: apibuilder app.apibuilder.io/hbc/api-fraud/0.0.0-slava/async_http_2_5_client */ package com.hbc.api.fraud.v0.models { /** * Envelope data */ final case class AdditionalData( inAuthId: _root_.java.util.UUID ) /** * General address model */ final case class Address( name: String, streetLineOne: String, streetLineTwo: _root_.scala.Option[String] = None, city: String, state: String, zip: String, country: String ) /** * A customer's complete credit card information * * @param expiryDate MM-YY that the credit card expires * @param authCode CVV code on the back of the card * @param avsResponse Address Verification System response, Codes are available here: * https://www.chasepaymentech.com/address_verification_service.html */ final case class CreditCard( nameOnCard: String, billingAddress: com.hbc.api.fraud.v0.models.Address, cardType: String, cardNumber: String, authorizedAmount: BigDecimal, fullAmount: BigDecimal, expiryDate: String, authCode: String, responseCode: Int, merchantId: _root_.scala.Option[Int] = None, registerNumber: _root_.scala.Option[String] = None, transactionNumber: String, avsResponse: String ) /** * Customer model */ final case class Customer( customerType: com.hbc.api.fraud.v0.models.CustomerType, accountId: String, creationDate: _root_.org.joda.time.LocalDate, firstName: String, lastName: String, emailAddress: String ) /** * Response model to OMS containing the transaction they've sent and the decision * we've made * * @param createdDate Date this record was first created within the database */ final case class DBRecord( transactionId: String, lastModifiedDate: _root_.scala.Option[_root_.org.joda.time.LocalDate] = None, createdDate: _root_.scala.Option[_root_.org.joda.time.LocalDate] = None, transaction: com.hbc.api.fraud.v0.models.Transaction, decision: com.hbc.api.fraud.v0.models.Decision ) /** * Defines decision information */ final case class Decision( transactionId: String, recommendationCode: com.hbc.api.fraud.v0.models.RecommendationCode, crossReference: _root_.scala.Option[_root_.java.util.UUID] = None, rulesTripped: _root_.scala.Option[String] = None, totalScore: Int, remarks: _root_.scala.Option[String] = None ) /** * Error response model * * @param message Error description message * @param error Error code */ final case class Error( message: String, error: String ) /** * Single item * * @param svsNumber Product style number (parent number) * @param skuNumber HBC internally generated number for items (alias SKN) * @param upcNumber The number on the barcode that could be used across different retailers * @param classNumber Signifies business category of an item (pants, tops, shirts, etc.) * @param price Price of single item * @param extendedPrice Total price of all items ordered */ final case class Item( svsNumber: Int, skuNumber: Int, upcNumber: _root_.scala.Option[Int] = None, classNumber: _root_.scala.Option[Int] = None, color: _root_.scala.Option[String] = None, size: _root_.scala.Option[String] = None, currentStatus: String, department: Int, signOnDelivery: _root_.scala.Option[String] = None, giftWrapped: _root_.scala.Option[Boolean] = None, costAmount: _root_.scala.Option[BigDecimal] = None, marginAmount: _root_.scala.Option[BigDecimal] = None, description: String, price: BigDecimal, extendedPrice: BigDecimal, quantity: Int, groupNumber: Int, shippingAddress: com.hbc.api.fraud.v0.models.Address, shippingMethod: String, shippingCountry: String ) /** * Promotion model * * @param promotionAmount Dollar amount discounted by the promotion */ final case class Promo( promotionCode: String, promotionAmount: BigDecimal ) /** * Defines data expected to come in from OMS describing a transaction * * @param source Order source (web, store, etc) * @param additionalData Additional `envelope` data sent through our system to f-s, should include * InAuthId */ final case class Transaction( orderId: String, groupId: String, orderTotal: BigDecimal, shippingCost: BigDecimal, currencyCode: String, storeNumber: Int, salesRep: _root_.scala.Option[String] = None, lastModifiedDate: _root_.scala.Option[_root_.org.joda.time.LocalDate] = None, banner: com.hbc.api.fraud.v0.models.Banner, creditCard: com.hbc.api.fraud.v0.models.CreditCard, promos: _root_.scala.Option[Seq[com.hbc.api.fraud.v0.models.Promo]] = None, items: Seq[com.hbc.api.fraud.v0.models.Item], ipAddress: _root_.scala.Option[String] = None, source: String, customer: com.hbc.api.fraud.v0.models.Customer, additionalData: _root_.scala.Option[com.hbc.api.fraud.v0.models.AdditionalData] = None ) /** * Our lovely store chains */ sealed trait Banner extends _root_.scala.Product with _root_.scala.Serializable object Banner { case object Lat extends Banner { override def toString = "lat" } case object S5a extends Banner { override def toString = "s5a" } case object O5a extends Banner { override def toString = "o5a" } case object Bay extends Banner { override def toString = "bay" } /** * UNDEFINED captures values that are sent either in error or * that were added by the server after this library was * generated. We want to make it easy and obvious to users of * this library to handle this case gracefully. * * We use all CAPS for the variable name to avoid collisions * with the camel cased values above. */ final case class UNDEFINED(override val toString: String) extends Banner /** * all returns a list of all the valid, known values. We use * lower case to avoid collisions with the camel cased values * above. */ val all: scala.List[Banner] = scala.List(Lat, S5a, O5a, Bay) private val byName: Map[String, Banner] = all.map(x => x.toString.toLowerCase -> x).toMap def apply(value: String): Banner = fromString(value).getOrElse(UNDEFINED(value)) def fromString(value: String): _root_.scala.Option[Banner] = byName.get(value.toLowerCase) } /** * Possible types of customers */ sealed trait CustomerType extends _root_.scala.Product with _root_.scala.Serializable object CustomerType { case object Guest extends CustomerType { override def toString = "guest" } case object Registered extends CustomerType { override def toString = "registered" } case object Employee extends CustomerType { override def toString = "employee" } /** * UNDEFINED captures values that are sent either in error or * that were added by the server after this library was * generated. We want to make it easy and obvious to users of * this library to handle this case gracefully. * * We use all CAPS for the variable name to avoid collisions * with the camel cased values above. */ final case class UNDEFINED(override val toString: String) extends CustomerType /** * all returns a list of all the valid, known values. We use * lower case to avoid collisions with the camel cased values * above. */ val all: scala.List[CustomerType] = scala.List(Guest, Registered, Employee) private val byName: Map[String, CustomerType] = all.map(x => x.toString.toLowerCase -> x).toMap def apply(value: String): CustomerType = fromString(value).getOrElse(UNDEFINED(value)) def fromString(value: String): _root_.scala.Option[CustomerType] = byName.get(value.toLowerCase) } /** * Enum describing the possible responses */ sealed trait RecommendationCode extends _root_.scala.Product with _root_.scala.Serializable object RecommendationCode { case object Reject extends RecommendationCode { override def toString = "reject" } case object Review extends RecommendationCode { override def toString = "review" } case object Accept extends RecommendationCode { override def toString = "accept" } /** * UNDEFINED captures values that are sent either in error or * that were added by the server after this library was * generated. We want to make it easy and obvious to users of * this library to handle this case gracefully. * * We use all CAPS for the variable name to avoid collisions * with the camel cased values above. */ final case class UNDEFINED(override val toString: String) extends RecommendationCode /** * all returns a list of all the valid, known values. We use * lower case to avoid collisions with the camel cased values * above. */ val all: scala.List[RecommendationCode] = scala.List(Reject, Review, Accept) private val byName: Map[String, RecommendationCode] = all.map(x => x.toString.toLowerCase -> x).toMap def apply(value: String): RecommendationCode = fromString(value).getOrElse(UNDEFINED(value)) def fromString(value: String): _root_.scala.Option[RecommendationCode] = byName.get(value.toLowerCase) } } package com.hbc.api.fraud.v0.models { package object json { import play.api.libs.json.__ import play.api.libs.json.JsString import play.api.libs.json.Writes import play.api.libs.functional.syntax._ import com.hbc.api.fraud.v0.models.json._ private[v0] implicit val jsonReadsUUID: play.api.libs.json.Reads[_root_.java.util.UUID] = __.read[String].map { str => _root_.java.util.UUID.fromString(str) } private[v0] implicit val jsonWritesUUID: play.api.libs.json.Writes[_root_.java.util.UUID] = (x: _root_.java.util.UUID) => play.api.libs.json.JsString(x.toString) private[v0] implicit val jsonReadsJodaDateTime: play.api.libs.json.Reads[_root_.org.joda.time.DateTime] = __.read[String].map { str => _root_.org.joda.time.format.ISODateTimeFormat.dateTimeParser.parseDateTime(str) } private[v0] implicit val jsonWritesJodaDateTime: play.api.libs.json.Writes[_root_.org.joda.time.DateTime] = (x: _root_.org.joda.time.DateTime) => { play.api.libs.json.JsString(_root_.org.joda.time.format.ISODateTimeFormat.dateTime.print(x)) } private[v0] implicit val jsonReadsJodaLocalDate: play.api.libs.json.Reads[_root_.org.joda.time.LocalDate] = __.read[String].map { str => _root_.org.joda.time.format.ISODateTimeFormat.dateTimeParser.parseLocalDate(str) } private[v0] implicit val jsonWritesJodaLocalDate: play.api.libs.json.Writes[_root_.org.joda.time.LocalDate] = (x: _root_.org.joda.time.LocalDate) => { play.api.libs.json.JsString(_root_.org.joda.time.format.ISODateTimeFormat.date.print(x)) } implicit val jsonReadsApiFraudBanner: play.api.libs.json.Reads[com.hbc.api.fraud.v0.models.Banner] = new play.api.libs.json.Reads[com.hbc.api.fraud.v0.models.Banner] { def reads(js: play.api.libs.json.JsValue): play.api.libs.json.JsResult[com.hbc.api.fraud.v0.models.Banner] = { js match { case v: play.api.libs.json.JsString => play.api.libs.json.JsSuccess(com.hbc.api.fraud.v0.models.Banner(v.value)) case _ => { (js \ "value").validate[String] match { case play.api.libs.json.JsSuccess(v, _) => play.api.libs.json.JsSuccess(com.hbc.api.fraud.v0.models.Banner(v)) case _: play.api.libs.json.JsError => (js \ "Banner").validate[String] match { case play.api.libs.json.JsSuccess(v, _) => play.api.libs.json.JsSuccess(com.hbc.api.fraud.v0.models.Banner(v)) case err: play.api.libs.json.JsError => err } } } } } } def jsonWritesApiFraudBanner(obj: com.hbc.api.fraud.v0.models.Banner) = { play.api.libs.json.JsString(obj.toString) } def jsObjectBanner(obj: com.hbc.api.fraud.v0.models.Banner) = { play.api.libs.json.Json.obj("value" -> play.api.libs.json.JsString(obj.toString)) } implicit def jsonWritesApiFraudBanner: play.api.libs.json.Writes[Banner] = { (obj: com.hbc.api.fraud.v0.models.Banner) => { com.hbc.api.fraud.v0.models.json.jsonWritesApiFraudBanner(obj) } } implicit val jsonReadsApiFraudCustomerType: play.api.libs.json.Reads[com.hbc.api.fraud.v0.models.CustomerType] = new play.api.libs.json.Reads[com.hbc.api.fraud.v0.models.CustomerType] { def reads(js: play.api.libs.json.JsValue): play.api.libs.json.JsResult[com.hbc.api.fraud.v0.models.CustomerType] = { js match { case v: play.api.libs.json.JsString => play.api.libs.json.JsSuccess(com.hbc.api.fraud.v0.models.CustomerType(v.value)) case _ => { (js \ "value").validate[String] match { case play.api.libs.json.JsSuccess(v, _) => play.api.libs.json.JsSuccess(com.hbc.api.fraud.v0.models.CustomerType(v)) case _: play.api.libs.json.JsError => (js \ "CustomerType").validate[String] match { case play.api.libs.json.JsSuccess(v, _) => play.api.libs.json.JsSuccess(com.hbc.api.fraud.v0.models.CustomerType(v)) case err: play.api.libs.json.JsError => err } } } } } } def jsonWritesApiFraudCustomerType(obj: com.hbc.api.fraud.v0.models.CustomerType) = { play.api.libs.json.JsString(obj.toString) } def jsObjectCustomerType(obj: com.hbc.api.fraud.v0.models.CustomerType) = { play.api.libs.json.Json.obj("value" -> play.api.libs.json.JsString(obj.toString)) } implicit def jsonWritesApiFraudCustomerType: play.api.libs.json.Writes[CustomerType] = { (obj: com.hbc.api.fraud.v0.models.CustomerType) => { com.hbc.api.fraud.v0.models.json.jsonWritesApiFraudCustomerType(obj) } } implicit val jsonReadsApiFraudRecommendationCode: play.api.libs.json.Reads[com.hbc.api.fraud.v0.models.RecommendationCode] = new play.api.libs.json.Reads[com.hbc.api.fraud.v0.models.RecommendationCode] { def reads(js: play.api.libs.json.JsValue): play.api.libs.json.JsResult[com.hbc.api.fraud.v0.models.RecommendationCode] = { js match { case v: play.api.libs.json.JsString => play.api.libs.json.JsSuccess(com.hbc.api.fraud.v0.models.RecommendationCode(v.value)) case _ => { (js \ "value").validate[String] match { case play.api.libs.json.JsSuccess(v, _) => play.api.libs.json.JsSuccess(com.hbc.api.fraud.v0.models.RecommendationCode(v)) case _: play.api.libs.json.JsError => (js \ "RecommendationCode").validate[String] match { case play.api.libs.json.JsSuccess(v, _) => play.api.libs.json.JsSuccess(com.hbc.api.fraud.v0.models.RecommendationCode(v)) case err: play.api.libs.json.JsError => err } } } } } } def jsonWritesApiFraudRecommendationCode(obj: com.hbc.api.fraud.v0.models.RecommendationCode) = { play.api.libs.json.JsString(obj.toString) } def jsObjectRecommendationCode(obj: com.hbc.api.fraud.v0.models.RecommendationCode) = { play.api.libs.json.Json.obj("value" -> play.api.libs.json.JsString(obj.toString)) } implicit def jsonWritesApiFraudRecommendationCode: play.api.libs.json.Writes[RecommendationCode] = { (obj: com.hbc.api.fraud.v0.models.RecommendationCode) => { com.hbc.api.fraud.v0.models.json.jsonWritesApiFraudRecommendationCode(obj) } } implicit def jsonReadsApiFraudAdditionalData: play.api.libs.json.Reads[com.hbc.api.fraud.v0.models.AdditionalData] = { (__ \ "inAuthId").read[_root_.java.util.UUID].map { x => AdditionalData(inAuthId = x) } } def jsObjectAdditionalData(obj: com.hbc.api.fraud.v0.models.AdditionalData): play.api.libs.json.JsObject = { play.api.libs.json.Json.obj( "inAuthId" -> play.api.libs.json.JsString(obj.inAuthId.toString) ) } implicit def jsonWritesApiFraudAdditionalData: play.api.libs.json.Writes[AdditionalData] = { (obj: com.hbc.api.fraud.v0.models.AdditionalData) => { com.hbc.api.fraud.v0.models.json.jsObjectAdditionalData(obj) } } implicit def jsonReadsApiFraudAddress: play.api.libs.json.Reads[com.hbc.api.fraud.v0.models.Address] = { for { name <- (__ \ "name").read[String] streetLineOne <- (__ \ "streetLineOne").read[String] streetLineTwo <- (__ \ "streetLineTwo").readNullable[String] city <- (__ \ "city").read[String] state <- (__ \ "state").read[String] zip <- (__ \ "zip").read[String] country <- (__ \ "country").read[String] } yield Address(name, streetLineOne, streetLineTwo, city, state, zip, country) } def jsObjectAddress(obj: com.hbc.api.fraud.v0.models.Address): play.api.libs.json.JsObject = { play.api.libs.json.Json.obj( "name" -> play.api.libs.json.JsString(obj.name), "streetLineOne" -> play.api.libs.json.JsString(obj.streetLineOne), "city" -> play.api.libs.json.JsString(obj.city), "state" -> play.api.libs.json.JsString(obj.state), "zip" -> play.api.libs.json.JsString(obj.zip), "country" -> play.api.libs.json.JsString(obj.country) ) ++ (obj.streetLineTwo match { case None => play.api.libs.json.Json.obj() case Some(x) => play.api.libs.json.Json.obj("streetLineTwo" -> play.api.libs.json.JsString(x)) }) } implicit def jsonWritesApiFraudAddress: play.api.libs.json.Writes[Address] = { (obj: com.hbc.api.fraud.v0.models.Address) => { com.hbc.api.fraud.v0.models.json.jsObjectAddress(obj) } } implicit def jsonReadsApiFraudCreditCard: play.api.libs.json.Reads[com.hbc.api.fraud.v0.models.CreditCard] = { for { nameOnCard <- (__ \ "nameOnCard").read[String] billingAddress <- (__ \ "billingAddress").read[com.hbc.api.fraud.v0.models.Address] cardType <- (__ \ "cardType").read[String] cardNumber <- (__ \ "cardNumber").read[String] authorizedAmount <- (__ \ "authorizedAmount").read[BigDecimal] fullAmount <- (__ \ "fullAmount").read[BigDecimal] expiryDate <- (__ \ "expiryDate").read[String] authCode <- (__ \ "authCode").read[String] responseCode <- (__ \ "responseCode").read[Int] merchantId <- (__ \ "merchantId").readNullable[Int] registerNumber <- (__ \ "registerNumber").readNullable[String] transactionNumber <- (__ \ "transactionNumber").read[String] avsResponse <- (__ \ "avsResponse").read[String] } yield CreditCard(nameOnCard, billingAddress, cardType, cardNumber, authorizedAmount, fullAmount, expiryDate, authCode, responseCode, merchantId, registerNumber, transactionNumber, avsResponse) } def jsObjectCreditCard(obj: com.hbc.api.fraud.v0.models.CreditCard): play.api.libs.json.JsObject = { play.api.libs.json.Json.obj( "nameOnCard" -> play.api.libs.json.JsString(obj.nameOnCard), "billingAddress" -> com.hbc.api.fraud.v0.models.json.jsObjectAddress(obj.billingAddress), "cardType" -> play.api.libs.json.JsString(obj.cardType), "cardNumber" -> play.api.libs.json.JsString(obj.cardNumber), "authorizedAmount" -> play.api.libs.json.JsNumber(obj.authorizedAmount), "fullAmount" -> play.api.libs.json.JsNumber(obj.fullAmount), "expiryDate" -> play.api.libs.json.JsString(obj.expiryDate), "authCode" -> play.api.libs.json.JsString(obj.authCode), "responseCode" -> play.api.libs.json.JsNumber(obj.responseCode), "transactionNumber" -> play.api.libs.json.JsString(obj.transactionNumber), "avsResponse" -> play.api.libs.json.JsString(obj.avsResponse) ) ++ (obj.merchantId match { case None => play.api.libs.json.Json.obj() case Some(x) => play.api.libs.json.Json.obj("merchantId" -> play.api.libs.json.JsNumber(x)) }) ++ (obj.registerNumber match { case None => play.api.libs.json.Json.obj() case Some(x) => play.api.libs.json.Json.obj("registerNumber" -> play.api.libs.json.JsString(x)) }) } implicit def jsonWritesApiFraudCreditCard: play.api.libs.json.Writes[CreditCard] = { (obj: com.hbc.api.fraud.v0.models.CreditCard) => { com.hbc.api.fraud.v0.models.json.jsObjectCreditCard(obj) } } implicit def jsonReadsApiFraudCustomer: play.api.libs.json.Reads[com.hbc.api.fraud.v0.models.Customer] = { for { customerType <- (__ \ "customerType").read[com.hbc.api.fraud.v0.models.CustomerType] accountId <- (__ \ "accountId").read[String] creationDate <- (__ \ "creationDate").read[_root_.org.joda.time.LocalDate] firstName <- (__ \ "firstName").read[String] lastName <- (__ \ "lastName").read[String] emailAddress <- (__ \ "emailAddress").read[String] } yield Customer(customerType, accountId, creationDate, firstName, lastName, emailAddress) } def jsObjectCustomer(obj: com.hbc.api.fraud.v0.models.Customer): play.api.libs.json.JsObject = { play.api.libs.json.Json.obj( "customerType" -> play.api.libs.json.JsString(obj.customerType.toString), "accountId" -> play.api.libs.json.JsString(obj.accountId), "creationDate" -> play.api.libs.json.JsString(_root_.org.joda.time.format.ISODateTimeFormat.date.print(obj.creationDate)), "firstName" -> play.api.libs.json.JsString(obj.firstName), "lastName" -> play.api.libs.json.JsString(obj.lastName), "emailAddress" -> play.api.libs.json.JsString(obj.emailAddress) ) } implicit def jsonWritesApiFraudCustomer: play.api.libs.json.Writes[Customer] = { (obj: com.hbc.api.fraud.v0.models.Customer) => { com.hbc.api.fraud.v0.models.json.jsObjectCustomer(obj) } } implicit def jsonReadsApiFraudDBRecord: play.api.libs.json.Reads[com.hbc.api.fraud.v0.models.DBRecord] = { for { transactionId <- (__ \ "transactionId").read[String] lastModifiedDate <- (__ \ "lastModifiedDate").readNullable[_root_.org.joda.time.LocalDate] createdDate <- (__ \ "createdDate").readNullable[_root_.org.joda.time.LocalDate] transaction <- (__ \ "transaction").read[com.hbc.api.fraud.v0.models.Transaction] decision <- (__ \ "decision").read[com.hbc.api.fraud.v0.models.Decision] } yield DBRecord(transactionId, lastModifiedDate, createdDate, transaction, decision) } def jsObjectDBRecord(obj: com.hbc.api.fraud.v0.models.DBRecord): play.api.libs.json.JsObject = { play.api.libs.json.Json.obj( "transactionId" -> play.api.libs.json.JsString(obj.transactionId), "transaction" -> com.hbc.api.fraud.v0.models.json.jsObjectTransaction(obj.transaction), "decision" -> com.hbc.api.fraud.v0.models.json.jsObjectDecision(obj.decision) ) ++ (obj.lastModifiedDate match { case None => play.api.libs.json.Json.obj() case Some(x) => play.api.libs.json.Json.obj("lastModifiedDate" -> play.api.libs.json.JsString(_root_.org.joda.time.format.ISODateTimeFormat.date.print(x))) }) ++ (obj.createdDate match { case None => play.api.libs.json.Json.obj() case Some(x) => play.api.libs.json.Json.obj("createdDate" -> play.api.libs.json.JsString(_root_.org.joda.time.format.ISODateTimeFormat.date.print(x))) }) } implicit def jsonWritesApiFraudDBRecord: play.api.libs.json.Writes[DBRecord] = { (obj: com.hbc.api.fraud.v0.models.DBRecord) => { com.hbc.api.fraud.v0.models.json.jsObjectDBRecord(obj) } } implicit def jsonReadsApiFraudDecision: play.api.libs.json.Reads[com.hbc.api.fraud.v0.models.Decision] = { for { transactionId <- (__ \ "transactionId").read[String] recommendationCode <- (__ \ "recommendationCode").read[com.hbc.api.fraud.v0.models.RecommendationCode] crossReference <- (__ \ "crossReference").readNullable[_root_.java.util.UUID] rulesTripped <- (__ \ "rulesTripped").readNullable[String] totalScore <- (__ \ "totalScore").read[Int] remarks <- (__ \ "remarks").readNullable[String] } yield Decision(transactionId, recommendationCode, crossReference, rulesTripped, totalScore, remarks) } def jsObjectDecision(obj: com.hbc.api.fraud.v0.models.Decision): play.api.libs.json.JsObject = { play.api.libs.json.Json.obj( "transactionId" -> play.api.libs.json.JsString(obj.transactionId), "recommendationCode" -> play.api.libs.json.JsString(obj.recommendationCode.toString), "totalScore" -> play.api.libs.json.JsNumber(obj.totalScore) ) ++ (obj.crossReference match { case None => play.api.libs.json.Json.obj() case Some(x) => play.api.libs.json.Json.obj("crossReference" -> play.api.libs.json.JsString(x.toString)) }) ++ (obj.rulesTripped match { case None => play.api.libs.json.Json.obj() case Some(x) => play.api.libs.json.Json.obj("rulesTripped" -> play.api.libs.json.JsString(x)) }) ++ (obj.remarks match { case None => play.api.libs.json.Json.obj() case Some(x) => play.api.libs.json.Json.obj("remarks" -> play.api.libs.json.JsString(x)) }) } implicit def jsonWritesApiFraudDecision: play.api.libs.json.Writes[Decision] = { (obj: com.hbc.api.fraud.v0.models.Decision) => { com.hbc.api.fraud.v0.models.json.jsObjectDecision(obj) } } implicit def jsonReadsApiFraudError: play.api.libs.json.Reads[com.hbc.api.fraud.v0.models.Error] = { for { message <- (__ \ "message").read[String] error <- (__ \ "error").read[String] } yield Error(message, error) } def jsObjectError(obj: com.hbc.api.fraud.v0.models.Error): play.api.libs.json.JsObject = { play.api.libs.json.Json.obj( "message" -> play.api.libs.json.JsString(obj.message), "error" -> play.api.libs.json.JsString(obj.error) ) } implicit def jsonWritesApiFraudError: play.api.libs.json.Writes[Error] = { (obj: com.hbc.api.fraud.v0.models.Error) => { com.hbc.api.fraud.v0.models.json.jsObjectError(obj) } } implicit def jsonReadsApiFraudItem: play.api.libs.json.Reads[com.hbc.api.fraud.v0.models.Item] = { for { svsNumber <- (__ \ "svsNumber").read[Int] skuNumber <- (__ \ "skuNumber").read[Int] upcNumber <- (__ \ "upcNumber").readNullable[Int] classNumber <- (__ \ "classNumber").readNullable[Int] color <- (__ \ "color").readNullable[String] size <- (__ \ "size").readNullable[String] currentStatus <- (__ \ "currentStatus").read[String] department <- (__ \ "department").read[Int] signOnDelivery <- (__ \ "signOnDelivery").readNullable[String] giftWrapped <- (__ \ "giftWrapped").readNullable[Boolean] costAmount <- (__ \ "costAmount").readNullable[BigDecimal] marginAmount <- (__ \ "marginAmount").readNullable[BigDecimal] description <- (__ \ "description").read[String] price <- (__ \ "price").read[BigDecimal] extendedPrice <- (__ \ "extendedPrice").read[BigDecimal] quantity <- (__ \ "quantity").read[Int] groupNumber <- (__ \ "groupNumber").read[Int] shippingAddress <- (__ \ "shippingAddress").read[com.hbc.api.fraud.v0.models.Address] shippingMethod <- (__ \ "shippingMethod").read[String] shippingCountry <- (__ \ "shippingCountry").read[String] } yield Item(svsNumber, skuNumber, upcNumber, classNumber, color, size, currentStatus, department, signOnDelivery, giftWrapped, costAmount, marginAmount, description, price, extendedPrice, quantity, groupNumber, shippingAddress, shippingMethod, shippingCountry) } def jsObjectItem(obj: com.hbc.api.fraud.v0.models.Item): play.api.libs.json.JsObject = { play.api.libs.json.Json.obj( "svsNumber" -> play.api.libs.json.JsNumber(obj.svsNumber), "skuNumber" -> play.api.libs.json.JsNumber(obj.skuNumber), "currentStatus" -> play.api.libs.json.JsString(obj.currentStatus), "department" -> play.api.libs.json.JsNumber(obj.department), "description" -> play.api.libs.json.JsString(obj.description), "price" -> play.api.libs.json.JsNumber(obj.price), "extendedPrice" -> play.api.libs.json.JsNumber(obj.extendedPrice), "quantity" -> play.api.libs.json.JsNumber(obj.quantity), "groupNumber" -> play.api.libs.json.JsNumber(obj.groupNumber), "shippingAddress" -> com.hbc.api.fraud.v0.models.json.jsObjectAddress(obj.shippingAddress), "shippingMethod" -> play.api.libs.json.JsString(obj.shippingMethod), "shippingCountry" -> play.api.libs.json.JsString(obj.shippingCountry) ) ++ (obj.upcNumber match { case None => play.api.libs.json.Json.obj() case Some(x) => play.api.libs.json.Json.obj("upcNumber" -> play.api.libs.json.JsNumber(x)) }) ++ (obj.classNumber match { case None => play.api.libs.json.Json.obj() case Some(x) => play.api.libs.json.Json.obj("classNumber" -> play.api.libs.json.JsNumber(x)) }) ++ (obj.color match { case None => play.api.libs.json.Json.obj() case Some(x) => play.api.libs.json.Json.obj("color" -> play.api.libs.json.JsString(x)) }) ++ (obj.size match { case None => play.api.libs.json.Json.obj() case Some(x) => play.api.libs.json.Json.obj("size" -> play.api.libs.json.JsString(x)) }) ++ (obj.signOnDelivery match { case None => play.api.libs.json.Json.obj() case Some(x) => play.api.libs.json.Json.obj("signOnDelivery" -> play.api.libs.json.JsString(x)) }) ++ (obj.giftWrapped match { case None => play.api.libs.json.Json.obj() case Some(x) => play.api.libs.json.Json.obj("giftWrapped" -> play.api.libs.json.JsBoolean(x)) }) ++ (obj.costAmount match { case None => play.api.libs.json.Json.obj() case Some(x) => play.api.libs.json.Json.obj("costAmount" -> play.api.libs.json.JsNumber(x)) }) ++ (obj.marginAmount match { case None => play.api.libs.json.Json.obj() case Some(x) => play.api.libs.json.Json.obj("marginAmount" -> play.api.libs.json.JsNumber(x)) }) } implicit def jsonWritesApiFraudItem: play.api.libs.json.Writes[Item] = { (obj: com.hbc.api.fraud.v0.models.Item) => { com.hbc.api.fraud.v0.models.json.jsObjectItem(obj) } } implicit def jsonReadsApiFraudPromo: play.api.libs.json.Reads[com.hbc.api.fraud.v0.models.Promo] = { for { promotionCode <- (__ \ "promotionCode").read[String] promotionAmount <- (__ \ "promotionAmount").read[BigDecimal] } yield Promo(promotionCode, promotionAmount) } def jsObjectPromo(obj: com.hbc.api.fraud.v0.models.Promo): play.api.libs.json.JsObject = { play.api.libs.json.Json.obj( "promotionCode" -> play.api.libs.json.JsString(obj.promotionCode), "promotionAmount" -> play.api.libs.json.JsNumber(obj.promotionAmount) ) } implicit def jsonWritesApiFraudPromo: play.api.libs.json.Writes[Promo] = { (obj: com.hbc.api.fraud.v0.models.Promo) => { com.hbc.api.fraud.v0.models.json.jsObjectPromo(obj) } } implicit def jsonReadsApiFraudTransaction: play.api.libs.json.Reads[com.hbc.api.fraud.v0.models.Transaction] = { for { orderId <- (__ \ "orderId").read[String] groupId <- (__ \ "groupId").read[String] orderTotal <- (__ \ "orderTotal").read[BigDecimal] shippingCost <- (__ \ "shippingCost").read[BigDecimal] currencyCode <- (__ \ "currencyCode").read[String] storeNumber <- (__ \ "storeNumber").read[Int] salesRep <- (__ \ "salesRep").readNullable[String] lastModifiedDate <- (__ \ "lastModifiedDate").readNullable[_root_.org.joda.time.LocalDate] banner <- (__ \ "banner").read[com.hbc.api.fraud.v0.models.Banner] creditCard <- (__ \ "creditCard").read[com.hbc.api.fraud.v0.models.CreditCard] promos <- (__ \ "promos").readNullable[Seq[com.hbc.api.fraud.v0.models.Promo]] items <- (__ \ "items").read[Seq[com.hbc.api.fraud.v0.models.Item]] ipAddress <- (__ \ "ipAddress").readNullable[String] source <- (__ \ "source").read[String] customer <- (__ \ "customer").read[com.hbc.api.fraud.v0.models.Customer] additionalData <- (__ \ "additionalData").readNullable[com.hbc.api.fraud.v0.models.AdditionalData] } yield Transaction(orderId, groupId, orderTotal, shippingCost, currencyCode, storeNumber, salesRep, lastModifiedDate, banner, creditCard, promos, items, ipAddress, source, customer, additionalData) } def jsObjectTransaction(obj: com.hbc.api.fraud.v0.models.Transaction): play.api.libs.json.JsObject = { play.api.libs.json.Json.obj( "orderId" -> play.api.libs.json.JsString(obj.orderId), "groupId" -> play.api.libs.json.JsString(obj.groupId), "orderTotal" -> play.api.libs.json.JsNumber(obj.orderTotal), "shippingCost" -> play.api.libs.json.JsNumber(obj.shippingCost), "currencyCode" -> play.api.libs.json.JsString(obj.currencyCode), "storeNumber" -> play.api.libs.json.JsNumber(obj.storeNumber), "banner" -> play.api.libs.json.JsString(obj.banner.toString), "creditCard" -> com.hbc.api.fraud.v0.models.json.jsObjectCreditCard(obj.creditCard), "items" -> play.api.libs.json.Json.toJson(obj.items), "source" -> play.api.libs.json.JsString(obj.source), "customer" -> com.hbc.api.fraud.v0.models.json.jsObjectCustomer(obj.customer) ) ++ (obj.salesRep match { case None => play.api.libs.json.Json.obj() case Some(x) => play.api.libs.json.Json.obj("salesRep" -> play.api.libs.json.JsString(x)) }) ++ (obj.lastModifiedDate match { case None => play.api.libs.json.Json.obj() case Some(x) => play.api.libs.json.Json.obj("lastModifiedDate" -> play.api.libs.json.JsString(_root_.org.joda.time.format.ISODateTimeFormat.date.print(x))) }) ++ (obj.promos match { case None => play.api.libs.json.Json.obj() case Some(x) => play.api.libs.json.Json.obj("promos" -> play.api.libs.json.Json.toJson(x)) }) ++ (obj.ipAddress match { case None => play.api.libs.json.Json.obj() case Some(x) => play.api.libs.json.Json.obj("ipAddress" -> play.api.libs.json.JsString(x)) }) ++ (obj.additionalData match { case None => play.api.libs.json.Json.obj() case Some(x) => play.api.libs.json.Json.obj("additionalData" -> com.hbc.api.fraud.v0.models.json.jsObjectAdditionalData(x)) }) } implicit def jsonWritesApiFraudTransaction: play.api.libs.json.Writes[Transaction] = { (obj: com.hbc.api.fraud.v0.models.Transaction) => { com.hbc.api.fraud.v0.models.json.jsObjectTransaction(obj) } } } } package com.hbc.api.fraud.v0 { import org.asynchttpclient.{AsyncCompletionHandler, AsyncHttpClient, Realm, Request, RequestBuilder, Response, DefaultAsyncHttpClient, DefaultAsyncHttpClientConfig} object Constants { val BaseUrl = "http://fraud-frozone" val Namespace = "com.hbc.api.fraud.v0" val UserAgent = "apibuilder app.apibuilder.io/hbc/api-fraud/0.0.0-slava/async_http_2_5_client" val Version = "0.0.0-slava" val VersionMajor = 0 } class Client( val baseUrl: String = "http://fraud-frozone", auth: scala.Option[com.hbc.api.fraud.v0.Authorization] = None, defaultHeaders: Seq[(String, String)] = Nil, asyncHttpClient: AsyncHttpClient = Client.defaultAsyncHttpClient ) extends interfaces.Client { import org.slf4j.{Logger, LoggerFactory} import com.hbc.api.fraud.v0.models.json._ def closeAsyncHttpClient(): Unit = { asyncHttpClient.close() } val logger = LoggerFactory.getLogger(getClass) def decisions: Decisions = Decisions def transactions: Transactions = Transactions object Decisions extends Decisions { override def post( decision: com.hbc.api.fraud.v0.models.Decision, requestHeaders: Seq[(String, String)] = Nil )(implicit ec: scala.concurrent.ExecutionContext): scala.concurrent.Future[Unit] = { val payload = play.api.libs.json.Json.toJson(decision) _executeRequest("POST", s"/decision", body = Some(payload), requestHeaders = requestHeaders).map { case r if r.getStatusCode == 200 => () case r if r.getStatusCode == 400 => throw com.hbc.api.fraud.v0.errors.ErrorsResponse(r) case r => throw com.hbc.api.fraud.v0.errors.FailedRequest(r.getStatusCode, s"Unsupported response code[${r.getStatusCode}]. Expected: 200, 400", requestUri = Some(r.getUri.toJavaNetURI)) } } } object Transactions extends Transactions { override def post( transaction: com.hbc.api.fraud.v0.models.Transaction, requestHeaders: Seq[(String, String)] = Nil )(implicit ec: scala.concurrent.ExecutionContext): scala.concurrent.Future[com.hbc.api.fraud.v0.models.Decision] = { val payload = play.api.libs.json.Json.toJson(transaction) _executeRequest("POST", s"/transaction", body = Some(payload), requestHeaders = requestHeaders).map { case r if r.getStatusCode == 200 => _root_.com.hbc.api.fraud.v0.Client.parseJson("com.hbc.api.fraud.v0.models.Decision", r, _.validate[com.hbc.api.fraud.v0.models.Decision]) case r if r.getStatusCode == 400 => throw com.hbc.api.fraud.v0.errors.ErrorsResponse(r) case r => throw com.hbc.api.fraud.v0.errors.FailedRequest(r.getStatusCode, s"Unsupported response code[${r.getStatusCode}]. Expected: 200, 400", requestUri = Some(r.getUri.toJavaNetURI)) } } } def _logRequest(request: Request): Unit = { if (logger.isInfoEnabled) { logger.info("_logRequest: " + request) } } def _logResponse(response: Response): Unit = { if (logger.isInfoEnabled) { logger.info("_logResponse: status=" + response.getStatusCode + ", responseBody: " + response.getResponseBody(java.nio.charset.Charset.forName("UTF-8"))) } } def _requestBuilder(method: String, path: String, requestHeaders: Seq[(String, String)]): RequestBuilder = { val builder = new RequestBuilder(method) .setUrl(baseUrl + path) .addHeader("User-Agent", Constants.UserAgent) .addHeader("X-Apidoc-Version", Constants.Version) .addHeader("X-Apidoc-Version-Major", Constants.VersionMajor.toString) defaultHeaders.foreach { h => builder.addHeader(h._1, h._2) } requestHeaders.foreach { h => builder.addHeader(h._1, h._2) } auth.fold(builder) { case Authorization.Basic(username, passwordOpt) => { builder.setRealm( new Realm.Builder(username, passwordOpt.getOrElse("")) .setUsePreemptiveAuth(true) .setScheme(Realm.AuthScheme.BASIC) .build() ) } case a => sys.error("Invalid authorization scheme[" + a.getClass + "]") } } def _executeRequest( method: String, path: String, queryParameters: Seq[(String, String)] = Nil, requestHeaders: Seq[(String, String)] = Nil, body: Option[play.api.libs.json.JsValue] = None )(implicit ec: scala.concurrent.ExecutionContext): scala.concurrent.Future[org.asynchttpclient.Response] = { val allHeaders = body match { case None => requestHeaders case Some(_) => _withJsonContentType(requestHeaders) } val request = _requestBuilder(method, path, allHeaders) queryParameters.foreach { pair => request.addQueryParam(pair._1, pair._2) } val requestWithParamsAndBody = body.fold(request) { b => val serialized = play.api.libs.json.Json.stringify(b) request.setBody(serialized) } val finalRequest = requestWithParamsAndBody.build() _logRequest(finalRequest) val result = scala.concurrent.Promise[org.asynchttpclient.Response]() asyncHttpClient.executeRequest(finalRequest, new AsyncCompletionHandler[Unit]() { override def onCompleted(r: org.asynchttpclient.Response) = { _logResponse(r) result.success(r) } override def onThrowable(t: Throwable) = result.failure(t) } ) result.future } /** * Adds a Content-Type: application/json header unless the specified requestHeaders * already contain a Content-Type header */ def _withJsonContentType(headers: Seq[(String, String)]): Seq[(String, String)] = { headers.find { _._1.toUpperCase == "CONTENT-TYPE" } match { case None => headers ++ Seq(("Content-Type" -> "application/json; charset=UTF-8")) case Some(_) => headers } } } object Client { private lazy val defaultAsyncHttpClient = { new DefaultAsyncHttpClient( new DefaultAsyncHttpClientConfig.Builder().build() ) } def parseJson[T]( className: String, r: _root_.org.asynchttpclient.Response, f: (play.api.libs.json.JsValue => play.api.libs.json.JsResult[T]) ): T = { f(play.api.libs.json.Json.parse(r.getResponseBody(java.nio.charset.Charset.forName("UTF-8")))) match { case play.api.libs.json.JsSuccess(x, _) => x case play.api.libs.json.JsError(errors) => { throw com.hbc.api.fraud.v0.errors.FailedRequest(r.getStatusCode, s"Invalid json for class[" + className + "]: " + errors.mkString(" "), requestUri = Some(r.getUri.toJavaNetURI)) } } } } sealed trait Authorization extends _root_.scala.Product with _root_.scala.Serializable object Authorization { final case class Basic(username: String, password: Option[String] = None) extends Authorization } package interfaces { trait Client { def baseUrl: String def decisions: com.hbc.api.fraud.v0.Decisions def transactions: com.hbc.api.fraud.v0.Transactions } } trait Decisions { /** * Consumes the decision about a transaction (usually meant for manual review) and * triggers OMS to process/cancel the order */ def post( decision: com.hbc.api.fraud.v0.models.Decision, requestHeaders: Seq[(String, String)] = Nil )(implicit ec: scala.concurrent.ExecutionContext): scala.concurrent.Future[Unit] } trait Transactions { /** * Provides decision about a transaction by supplying order or other information */ def post( transaction: com.hbc.api.fraud.v0.models.Transaction, requestHeaders: Seq[(String, String)] = Nil )(implicit ec: scala.concurrent.ExecutionContext): scala.concurrent.Future[com.hbc.api.fraud.v0.models.Decision] } package errors { import com.hbc.api.fraud.v0.models.json._ final case class ErrorsResponse( response: _root_.org.asynchttpclient.Response, message: Option[String] = None ) extends Exception(message.getOrElse(s"${response.getStatusCode}: ${response.getResponseBody(java.nio.charset.Charset.forName("UTF-8"))}")) { lazy val errors = _root_.com.hbc.api.fraud.v0.Client.parseJson("Seq[com.hbc.api.fraud.v0.models.Error]", response, _.validate[Seq[com.hbc.api.fraud.v0.models.Error]]) } final case class FailedRequest(responseCode: Int, message: String, requestUri: Option[_root_.java.net.URI] = None) extends _root_.java.lang.Exception(s"HTTP $responseCode: $message") } object PathSegment { // See https://github.com/playframework/playframework/blob/2.3.x/framework/src/play/src/main/scala/play/utils/UriEncoding.scala def encode(s: String, inputCharset: String): String = { val in = s.getBytes(inputCharset) val out = new java.io.ByteArrayOutputStream() for (b <- in) { val allowed = segmentChars.get(b & 0xFF) if (allowed) { out.write(b) } else { out.write('%') out.write(upperHex((b >> 4) & 0xF)) out.write(upperHex(b & 0xF)) } } out.toString("US-ASCII") } private def upperHex(x: Int): Int = { // Assume 0 <= x < 16 if (x < 10) (x + '0') else (x - 10 + 'A') } private val segmentChars: java.util.BitSet = membershipTable(pchar) private def pchar: Seq[Char] = { val alphaDigit = for ((min, max) <- Seq(('a', 'z'), ('A', 'Z'), ('0', '9')); c <- min to max) yield c val unreserved = alphaDigit ++ Seq('-', '.', '_', '~') val subDelims = Seq('!', '$', '&', '\'', '(', ')', '*', '+', ',', ';', '=') unreserved ++ subDelims ++ Seq(':', '@') } private def membershipTable(chars: Seq[Char]): java.util.BitSet = { val bits = new java.util.BitSet(256) for (c <- chars) { bits.set(c.toInt) } bits } } }