Packages
Validate credit card number format using Luhn Algorithm and allows for checking test card numbers.
Current section
Files
Jump to
Current section
Files
lib/cc_validation.ex
defmodule CcValidation do
@moduledoc """
CcValidation implements methods to verify validity of a credit card number
"""
@doc """
Validate a credit card number using Luhn Algorithm
## Examples
Valid credit card
iex> CcValidation.validate("4716892095589823")
{:ok, true}
Invalid credit card
iex> CcValidation.validate("4024007106963124")
{:error, false}
Test card returns false
iex> CcValidation.validate("4111111111111111")
{:error, false}
### Validate test card numbers when check_test_numbers is true
A valid test card
iex> CcValidation.validate("4111111111111111", true)
{:ok, true, test_number: true}
An invalid test card
iex> CcValidation.validate("4212121212121212", true)
{:error, false, test_number: false}
A valid card when checking for test numbers just passes through
to the validate function but will also return that it is not
a test card
iex> CcValidation.validate("4716892095589823", true)
{:ok, true, test_number: false}
### Card numbers that are of length less than 13 or greater than 19 are
invalid.
iex> CcValidation.validate("123")
{:error, false}
iex> CcValidation.validate("12345678901234567890")
{:error, false}
"""
def validate(number, check_test_numbers \\ false)
def validate(number, true) do
case CcValidation.TestNumbers.exists?(number) do
true ->
{:ok, true, test_number: true}
false ->
Tuple.append(validate(number), test_number: false)
end
end
def validate(number, false)
when byte_size(number) < 13 or byte_size(number) > 19 do
{:error, false}
end
def validate(number, false) do
case CcValidation.TestNumbers.exists?(number) do
true ->
{:error, false}
_ ->
total = number
|> String.codepoints
|> Enum.reverse
|> Stream.with_index
|> Enum.map(fn {num, i} ->
case rem(i + 1, 2) do
0 ->
doubled = String.to_integer(num) * 2
if doubled > 9 do
doubled - 9
else
doubled
end
_ ->
String.to_integer(num)
end
end)
|> Enum.sum
case rem(total, 10) do
0 ->
{:ok, true}
_ ->
{:error, false}
end
end
end
end