All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.wix.pay.creditcard.tokenizer.DefaultTokenizerClient.scala Maven / Gradle / Ivy

The newest version!
package com.wix.pay.creditcard.tokenizer


import java.net.{URL, URLEncoder}

import com.google.api.client.http.{ByteArrayContent, GenericUrl, HttpRequestFactory}
import com.wix.pay.creditcard.tokenizer.model.{CreditCardToken, InTransitRequest, TokenizeRequest}
import com.wix.pay.creditcard.{CreditCard, CreditCardOptionalFields}
import com.wix.restaurants.common.protocol.api.{Error, Response}

import scala.concurrent.duration.Duration
import scala.util.{Failure, Success, Try}


object Endpoints {
  val production = "https://pay.wix.com/cards"
}

class DefaultTokenizerClient(requestFactory: HttpRequestFactory,
                             connectTimeout: Option[Duration] = None,
                             readTimeout: Option[Duration] = None,
                             numberOfRetries: Int = 0,
                             endpointUrl: String = Endpoints.production) extends TokenizerClient {
  private val tokenizeRequestParser = new TokenizeRequestParser
  private val responseForTokenizeRequestParser = new ResponseForTokenizeRequestParser
  private val inTransitRequestParser = new InTransitRequestParser
  private val responseForInTransitRequestParser = new ResponseForInTransitRequestParser
  private val exceptionsTranslator = new ExceptionsTranslator

  override def formUrl(params: Option[String] = None): Try[URL] = {
    Try {
      val resource = "/form" + params.map(params => s"?params=${URLEncoder.encode(params, "UTF-8")}").getOrElse("")
      Option(getAndExtractLocationHeader(resource)) match {
        case Some(url) => new URL(url)
        case None => throw TokenizerInternalException("Form endpoint did not return location header")
      }
    }
  }

  override def tokenize(card: CreditCard): Try[CreditCardToken] = {
    Try {
      val request = TokenizeRequest(
        card = card
      )
      val requestJson = tokenizeRequestParser.stringify(request)

      val responseJson = doJsonRequest("/tokenize", requestJson)

      responseForTokenizeRequestParser.parse(responseJson)
    } match {
      case Success(response) => response match {
        case ResponseForTokenizeRequestHasError(error) => Failure(exceptionsTranslator.translateError(error))
        case ResponseForTokenizeRequestHasValue(value) => Success(value)
      }
      case Failure(e) => Failure(new TokenizerInternalException(e.getMessage, e))
    }
  }

  override def inTransit(permanentToken: CreditCardToken,
                         additionalInfo: Option[CreditCardOptionalFields] = None): Try[CreditCardToken] = {
    Try {
      val request = InTransitRequest(
        permanentToken = permanentToken,
        additionalInfo = additionalInfo
      )
      val requestJson = inTransitRequestParser.stringify(request)

      val responseJson = doJsonRequest("/intransit", requestJson)

      responseForInTransitRequestParser.parse(responseJson)
    } match {
      case Success(response) => response match {
        case ResponseForInTransitRequestHasError(error) => Failure(exceptionsTranslator.translateError(error))
        case ResponseForInTransitRequestHasValue(value) => Success(value)
      }
      case Failure(e) => Failure(new TokenizerInternalException(e.getMessage, e))
    }
  }

  private def getAndExtractLocationHeader(resource: String): String = {
    val httpRequest = requestFactory.buildGetRequest(new GenericUrl(endpointUrl + resource))

    connectTimeout foreach (connectTimeout => httpRequest.setConnectTimeout(connectTimeout.toMillis.toInt))
    readTimeout foreach (readTimeout => httpRequest.setReadTimeout(readTimeout.toMillis.toInt))
    httpRequest.setNumberOfRetries(numberOfRetries)

    httpRequest.setFollowRedirects(false)
    httpRequest.setThrowExceptionOnExecuteError(false)

    val httpResponse = httpRequest.execute()
    try {
      httpResponse.getHeaders.getLocation
    } finally {
      httpResponse.ignore()
    }
  }

  private def doJsonRequest(resource: String, requestJson: String): String = {
    val httpRequest = requestFactory.buildPostRequest(
      new GenericUrl(endpointUrl + resource),
      new ByteArrayContent("application/json; charset=utf-8", requestJson.getBytes("UTF-8")))

    connectTimeout foreach (connectTimeout => httpRequest.setConnectTimeout(connectTimeout.toMillis.toInt))
    readTimeout foreach (readTimeout => httpRequest.setReadTimeout(readTimeout.toMillis.toInt))
    httpRequest.setNumberOfRetries(numberOfRetries)

    httpRequest.setThrowExceptionOnExecuteError(false)

    val httpResponse = httpRequest.execute()
    try {
      httpResponse.parseAsString()
    } finally {
      httpResponse.ignore()
    }
  }

}

object ResponseForTokenizeRequestHasValue {
  def unapply(response: Response[CreditCardToken]): Option[CreditCardToken] = response.value
}
object ResponseForTokenizeRequestHasError {
  def unapply(response: Response[CreditCardToken]): Option[Error] = response.error
}

object ResponseForInTransitRequestHasValue {
  def unapply(response: Response[CreditCardToken]): Option[CreditCardToken] = response.value
}
object ResponseForInTransitRequestHasError {
  def unapply(response: Response[CreditCardToken]): Option[Error] = response.error
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy