# Credit Card validation (v32)

## Description

Compare Credit Card validation with luhn algorithm

## Setup

``````var ccNum = "4984421209470251";

//Luhn algorithm identifier verification
// https://www.nczonline.net/blog/2009/08/04/computer-science-in-javascript-credit-card-number-validation/
function isValidIdentifier(identifier) {

var sum     = 0,
alt     = false,
i       = identifier.length-1,
num;

if (identifier.length < 13 || identifier.length > 19){
return false;
}

while (i >= 0){

//get the next digit
num = parseInt(identifier.charAt(i), 10);

//if it's not a valid number, abort
if (isNaN(num)){
return false;
}

//if it's an alternate number...
if (alt) {
num *= 2;
if (num > 9){
num = (num % 10) + 1;
}
}

//flip the alternate bit
alt = !alt;

//add to the rest of the sum
sum += num;

//go to next digit
i--;
}

//determine if it's valid
return (sum % 10 == 0);
};

// https://gist.github.com/ondrek/6979558
function ondrekLuhn(luhn) {
var len = luhn.length,
mul = 0,
prodArr = [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 2, 4, 6, 8, 1, 3, 5, 7, 9]],
sum = 0;

while (len--) {
sum += prodArr[mul][parseInt(luhn.charAt(len), 10)];
mul ^= 1;
}

return sum % 10 === 0 && sum > 0;
};

// http://www.breakingpar.com/bkp/home.nsf/0/87256B280015193F87256CC70060A01B
function isValidCreditCard(ccnum) {
// Remove all dashes for the checksum checks to eliminate negative numbers
ccnum = ccnum.split("-").join("");
// Checksum ("Mod 10")
// Add even digits in even length strings or odd digits in odd length strings.
var checksum = 0;
for (var i=(2-(ccnum.length % 2)); i<=ccnum.length; i+=2) {
checksum += parseInt(ccnum.charAt(i-1));
}
// Analyze odd digits in even length strings or even digits in odd length strings.
for (var i=(ccnum.length % 2) + 1; i<ccnum.length; i+=2) {
var digit = parseInt(ccnum.charAt(i-1)) * 2;
if (digit < 10) { checksum += digit; } else { checksum += (digit-9); }
}
if ((checksum % 10) == 0) return true; else return false;
};

// https://gist.github.com/2134376
// Phil Green (ShirtlessKirk)
function luhnChk(luhn) {
var len = luhn.length,
mul = 0,
prodArr = [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 2, 4, 6, 8, 1, 3, 5, 7, 9]],
sum = 0;

while (len--) {
sum += prodArr[mul][parseInt(luhn.charAt(len), 10)];
mul ^= 1;
}

return sum % 10 === 0 && sum > 0;
};

// https://github.com/PawelDecowski/jQuery-CreditCardValidator/
// Pawel Decowski

function is_valid_luhn(number) {
var digit, n, sum, _len, _ref;
sum = 0;
_ref = number.split('').reverse().join('');
for (n = 0, _len = _ref.length; n < _len; n++) {
digit = _ref[n];
digit = +digit;
if (n % 2) {
digit *= 2;
if (digit < 10) {
sum += digit;
} else {
sum += digit - 9;
}
} else {
sum += digit;
}
}
return sum % 10 === 0;
};

// Luhn algorithm validator, by Avraham Plotnitzky. (aviplot at gmail)
function luhnCheckFast(luhn)
{
var ca, sum = 0, mul = 0;
var len = luhn.length;
while (len--)
{
ca = parseInt(luhn.charAt(len),10) << mul;
sum += ca - (-(ca>9))|9
// 1 <--> 0 toggle.
mul = 1 - mul;
};
return (sum%10 === 0) && (sum > 0);
};

function luhnCheckFast2(luhn)
{
var ca, sum = 0, mul = 1;
var len = luhn.length;
while (len--)
{
ca = parseInt(luhn.charAt(len),10) * mul;
sum += ca - (-(ca>9))|9
// 1 <--> 2 toggle.
mul = 3 - mul;
};
return (sum%10 === 0) && (sum > 0);
};

//http://www.notesbit.com/index.php/web-mysql/web-scripts/luhn-algorithm-for-credit-card-check-using-javascript/

function isCreditCard(CC) {
if (CC.length > 19) return (false);

sum = 0;
mul = 1;
l = CC.length;
for (i = 0; i < l; i++) {
digit = CC.substring(l - i - 1, l - i);
tproduct = parseInt(digit, 10) * mul;
if (tproduct >= 10) sum += (tproduct % 10) + 1;
else sum += tproduct;
if (mul == 1) mul++;
else mul--;
}
if ((sum % 10) == 0) return (true);
else return (false);
}

// http://imei.sms.eu.sk/
// Javascript code copyright 2009 by Fiach Reid : www.webtropy.com
// This code may be used freely, as long as this copyright notice is intact.

function Calculate(Luhn) {
var sum = 0;
for (i = 0; i < Luhn.length; i++) {
sum += parseInt(Luhn.substring(i, i + 1));
}
var delta = new Array(0, 1, 2, 3, 4, -4, -3, -2, -1, 0);
for (i = Luhn.length - 1; i >= 0; i -= 2) {
var deltaIndex = parseInt(Luhn.substring(i, i + 1));
var deltaValue = delta[deltaIndex];
sum += deltaValue;
}
var mod10 = sum % 10;
mod10 = 10 - mod10;
if (mod10 == 10) {
mod10 = 0;
}
return mod10;
}

function Validate(Luhn) {
var LuhnDigit = parseInt(Luhn.substring(Luhn.length - 1, Luhn.length));
var LuhnLess = Luhn.substring(0, Luhn.length - 1);
if (Calculate(LuhnLess) == parseInt(LuhnDigit)) {
return true;
}
return false;
}

//http://www.brainjar.com/js/validation/default2.asp

function checkCC(s) {
var i, n, c, r, t;
// First, reverse the string and remove any non-numeric characters.
r = "";
for (i = 0; i < s.length; i++) {
c = parseInt(s.charAt(i), 10);
if (c >= 0 && c <= 9)
r = c + r;
}

// Check for a bad string.
if (r.length <= 1)
return false;
// Now run through each single digit to create a new string. Even digits
// are multiplied by two, odd digits are left alone.
t = "";
for (i = 0; i < r.length; i++) {
c = parseInt(r.charAt(i), 10);
if (i % 2 != 0)
c *= 2;
t = t + c;
}

// Finally, add up all the single digits in this string.
n = 0;
for (i = 0; i < t.length; i++) {
c = parseInt(t.charAt(i), 10);
n = n + c;
}

// If the resulting sum is an even multiple of ten (but not zero), the
// card number is good.
if (n != 0 && n % 10 == 0)
return true;
else return false;
}

// Combination of ShirtlessKirk and Plotnitzky
function luhnCheckV1(str)
{
var luhnArr = [0, 2, 4, 6, 8, 1, 3, 5, 7, 9];
var ca, sum = 0;
var len = str.length;
var mul = (len&1);
while (len--)
{
ca = parseInt(str.charAt(len),10);
sum += (mul^=1) ? luhnArr[ca] : ca;
};
return (sum%10 === 0) && (sum > 0);
};

function luhnCheckV2(str)
{
var ca, sum = 0;
var len = str.length;
var mul = len&1;
while (len--)
{
ca = parseInt(str.charAt(len),10);
sum += mul ? ca : ca < 9 ? ca*2%9 : 9;
mul ^= 1; // 1 or 0 swich.
};
return (sum%10 === 0) && (sum > 0);
};

// http://www.breakingpar.com/bkp/home.nsf/0/87256B280015193F87256CC70060A01B
var messyCardValidation = function(ccnum){
ccnum = ccnum.split("-").join("");
// Checksum ("Mod 10")
// Add even digits in even length strings or odd digits in odd length strings.
var checksum = 0;
for (var i=(2-(ccnum.length % 2)); i<=ccnum.length; i+=2) {
checksum += parseInt(ccnum.charAt(i-1));
}
// Analyze odd digits in even length strings or even digits in odd length strings.
for (var i=(ccnum.length % 2) + 1; i<ccnum.length; i+=2) {
var digit = parseInt(ccnum.charAt(i-1)) * 2;
if (digit < 10) { checksum += digit; } else { checksum += (digit-9); }
}
if ((checksum % 10) == 0) return true; else return false;
};

// https://gist.github.com/ondrek/6979558
function ondrekLuhn(luhn) {
var len = luhn.length,
mul = 0,
prodArr = [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 2, 4, 6, 8, 1, 3, 5, 7, 9]],
sum = 0;

while (len--) {
sum += prodArr[mul][parseInt(luhn.charAt(len), 10)];
mul ^= 1;
}

return sum % 10 === 0 && sum > 0;
};``````

## Test runner

Testing in
TestOps/sec
1. notesbit
``isCreditCard(ccNum);``
2. webtropy
``Validate(ccNum);``
3. brainjar
``checkCC(ccNum);``
4. plotnitzky
``luhnCheckFast(ccNum);``
5. plotnitzky variant
``luhnCheckFast2(ccNum);``
6. decowski plugin
``is_valid_luhn(ccNum);``
7. ShirtlessKirk
``luhnChk(ccNum);``
8. ShirtlessKirk variant
``luhnCheckV1(ccNum);``
9. ShirtlessKirk variant
``luhnCheckV2(ccNum);``
``isValidCreditCard(ccNum)``
``ondrekLuhn(ccNum);``
``isValidIdentifier(ccNum);``