Packages

Library for categorizing and validating credit card numbers.

Current section

Files

Jump to
cnum lib cnum.ex
Raw

lib/cnum.ex

defmodule Cnum do
@moduledoc """
Cnum provides categorization and verification methods for a credit card number.
"""
alias Cnum.{Brands, Validator}
@doc """
Returns the brand of a given card number.
Currently supported brands:
- AmericanExpress
- DinersClub
- Discover
- Jcb
- Maestro
- MasterCard
- Visa
- VisaElectron
## Parameters
- pan: Integer or String that represents the primary account number on a payment card.
## Examples
iex> Cnum.type(4111111111111111)
"visa"
iex> Cnum.type("3400 0000 0000 009")
"amex"
iex> Cnum.type("1404 0092 0000 0004")
"unknown"
"""
@spec type(any()) :: binary()
def type(pan) when is_binary(pan) do
first_digits = clean(pan) |> String.slice(0..5)
bin_search(first_digits)
end
def type(pan) do
try do Integer.to_string(pan) |> type()
rescue _ -> "unknown" end
end
@doc """
Returns true if the given card number is valid or if the number is a test card number.
Test credit card numbers are valid by default.
## Parameters
- pan: Integer or String that represents the primary account number on a payment card.
## Examples
iex> Cnum.valid?("3400 0000 0000 009")
true
iex> Cnum.valid?(55555555555544)
false
iex> Cnum.valid?("")
false
"""
@spec valid?(any()) :: boolean()
def valid?(pan) when is_integer(pan) do
Validator.validate(pan)
end
def valid?(pan) do
try do String.to_integer(clean(pan)) |> valid?()
rescue _ -> false end
end
# -------------------------------------------------- #
defp clean(pan) do
Regex.replace(~r/\D/, pan, "")
end
defp bin_search(""), do: "unknown"
defp bin_search(digits) do
case Brands.get(digits) do
nil -> bin_search(String.slice(digits, 0..-2))
brand -> brand
end
end
end