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

com.wix.pay.creditcard.networks.Networks.scala Maven / Gradle / Ivy

The newest version!
/*      __ __ _____  __                                              *\
**     / // // /_/ |/ /          Wix                                 **
**    / // // / /|   /           (c) 2006-2015, Wix LTD.             **
**   / // // / //   |            http://www.wix.com/                 **
**   \__/|__/_//_/| |                                                **
\*                |/                                                 */
package com.wix.pay.creditcard.networks


import scala.language.experimental.macros
import scala.reflect.macros.blackbox.Context


/** Credit Card Network.
  * Identifies a credit card's Network based on its (full) number, and according to
  * [[http://en.wikipedia.org/wiki/Bank_card_number]] and [[https://www.bindb.com/bin-database.html]].
  * In addition, exposes all supported Networks (via the {{{Networks.all()}}} method).
  *
  * @author Raz, Ohad
  */
object Networks {
  val amex = "amex"
  val dankort = "dankort"
  val diners = "diners"
  val discover = "discover"
  val isracard = "isracard"
  val jcb = "jcb"
  val maestro = "maestro"
  val masterCard = "mastercard"
  val unionPay = "unionpay"
  val visa = "visa"


  private val amexRegex = """^3([47]\d{3}|[23]\d{3})\d{10}$""".r
  private val dankortRegex = """^5019(34)\d{10}$""".r
  private val dinersRegex = """^3(0[0-59]|[689]\d)\d{11}$""".r
  private val discoverRegex = """^(6011\d{2}|65\d{4}|64[4-9]\d{3}|601300|3[123689]\d{4}|309\d{3})\d{10}$""".r
  private val isracardRegex = """^\d{8,9}$""".r
  private val jcbRegex = """^35(?:2[89]|[3-8]\d)\d{12}$""".r
  private val maestroRegex =
    """^(50[^1]\d{3}|501[^9]\d{2}|5019[^3]\d|50193[^4]|5[6789]\d{4}|6[^0245]\d{4}|62[79]\d{3}|628[01]\d{2}|626257|62292[78]|62293[^4]|62294[^14]|62299\d|62298[02369]|62297[^0]|62296[^4569]|62295[^68]|62212[^6789]|62211\d|6220\d{2}|621[^4]\d{2}|6214[^8]\d|62148[^3]|620\d{3}|64[0-3]\d{3}|60[2-7]\d{3}|601[^13]\d{2}|6013[^0]\d|60130[^0]|600\d{3})\d{6,13}$""".r
  private val masterCardRegex = """^5[1-5]\d{14}$""".r
  private val unionPayRegex = """^(62[345]\d{3}|628[2-8]\d{2}|626[^2]\d{2}|6262[^5]\d|62625[^7]|622[^019]|6229[01]\d|62298[14578]|622970|62296[4569]|62295[68]|62294[14]|622934|62292[^78]|622[2-8]\d{2}|6221[^12]|62212[6-9]|621483)\d{10,13}$""".r
  private val visaRegex = """^4\d{12}(\d{3})?$""".r


  def all(): Seq[String] = macro generateAll

  def generateAll(ctx: Context)(): ctx.Expr[Seq[String]] = {
    import ctx.universe._

    val cls = Networks.getClass
    val fields = typeOf[Networks.type].termSymbol.typeSignature.decls.collect {
      case f: MethodSymbol
        if f.isPublic && f.isStatic && f.isAccessor && f.returnType.typeSymbol == weakTypeOf[String].typeSymbol =>
          cls.getMethod(f.name.decodedName.toString).invoke(Networks).toString
    }

    ctx.Expr(q"""Seq(..$fields)""")
  }


  /** According to [[http://en.wikipedia.org/wiki/Bank_card_number]] and [[https://www.bindb.com/bin-database.html]].
    *
    * @param creditCardNumber
    *                         the credit number for which a Network will be resolved.
    * @return
    *         The resolved Network, or {{{None}}} if failed to resolve one.
    */
  def apply(creditCardNumber: String): Option[String] = {
    creditCardNumber match {
      case amexRegex(_*) => Some(Networks.amex)
      case dankortRegex(_*) => Some(Networks.dankort)
      case dinersRegex(_*) => Some(Networks.diners)
      case discoverRegex(_*) => Some(Networks.discover)
      case isracardRegex(_*) => Some(Networks.isracard)
      case jcbRegex(_*) => Some(Networks.jcb)
      case maestroRegex(_*) => Some(Networks.maestro)
      case masterCardRegex(_*) => Some(Networks.masterCard)
      case unionPayRegex(_*) => Some(Networks.unionPay)
      case visaRegex(_*) => Some(Networks.visa)
      case _ => None
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy