If you have ever developed an application that accepts or processes Credit Card numbers, then LUHN’s formula for Mod 10 validation of primary account numbers would come naturally to you. If you want to know the logic behind Mod 10 validation for Credit Card numbers, here’s a very good reference.

I today implemented the LUHN’s Mod 10 validation logic in javascript, and thought of sharing it. Here’s a javascript method that accepts a string (of numbers) and returns true or false depending upon whether Mod 10 validation succeeds or not:

 

{syntaxhighlighter brush: jscript;fontsize: 100; first-line: 1; }var fnMod10 = function(number) {
var doubled = [];
for (var i = number.length – 2; i >= 0; i = i – 2) {
doubled.push(2 * number[i]);
}
var total = 0;
for (var i = ((number.length % 2) == 0 ? 1 : 0); i < number.length; i = i + 2) {
total += parseInt(number[i]);
}
for (var i = 0; i < doubled.length; i++) {
var num = doubled[i];
var digit;
while (num != 0) {
digit = num % 10;
num = parseInt(num / 10);
total += digit;
}
}

if (total % 10 == 0) {
return (true);
} else {
return (false);
}
}{/syntaxhighlighter}

Mod 10 validation essentially consists of doubling every second digit from right, and adding individual digits of the doubles to the reminaing digits in the original string and checking that the total is divisible by 10. For details, see this link as referenced above.

In the above code, we first collect all doubles for alternate digits starting from second right in an array, total the remaining digits in the original string, adding to this total the individual digits of each of the doubled figure and finally checking if the total is divisible by 10.

To make the topic of Credit Card validation a bit more complete, here’s a method that checks the validity of Visa, Master Card and American Express credit card numbers in javascript. If all validations for a specific card type succeed, the method returns true, otherwise it returns a string describing the particular validation that failed.

 

{syntaxhighlighter brush: jscript;fontsize: 100; first-line: 1; }validateCreditCardNumber = function(ccnum) {
var ccMsg = ‘Credit Card Number should be of format: XXNNNNNNNNNNNNNNNN” where XX is the 2 character Credit Card code, i.e. VI for Visa, MC for MasterCard, and AX for American Express. For example VI4500000000000006. The minimum allowed length is 15.’;

var ccFormat = ‘XXNNNNNNNNNNNNNNNN’;
if (ccnum.length < 15) {
return (ccMsg);
}
var lowered = ccnum.toLowerCase();

var cctype = lowered.substr(0, 2);
var match = cctype.match(/[a-zA-Z]{2}/);
if (!match) {
return (ccMsg);
}

var number = lowered.substr(2);
match = number.match(/[^0-9]/);
if (match) {
return (ccMsg);
}

var fnMod10 = function(number) {
var doubled = [];
for (var i = number.length – 2; i >= 0; i = i – 2) {
doubled.push(2 * number[i]);
}
var total = 0;
for (var i = ((number.length % 2) == 0 ? 1 : 0); i < number.length; i = i + 2) {
total += parseInt(number[i]);
}
for (var i = 0; i < doubled.length; i++) {
var num = doubled[i];
var digit;
while (num != 0) {
digit = num % 10;
num = parseInt(num / 10);
total += digit;
}
}

if (total % 10 == 0) {
return (true);
} else {
return (false);
}
}

switch (cctype) {
case ‘vi’:
case ‘mc’:
case ‘ax’:
//Mod 10 check
if (!fnMod10(number)) {
return (‘Credit Card Number seems to be invalid.’);
}
break;
}
switch (cctype) {
case ‘vi’:
if (number[0] != ‘4’ || (number.length != 13 && number.length != 16)) {
return (‘Visa Credit Cards should start with “4” and should be 13 or 16 numbers long.’);
}
break;

case ‘mc’:
if (number[0] != ‘5’ || (number.length != 16)) {
return (‘MasterCard Credit Cards should start with “5” and should be 16 numbers long.’);
}
break;

case ‘ax’:
if (number[0] != ‘3’ || (number.length != 15)) {
return (‘American Express Credit Cards should start with “3” and should be 15 numbers long.’);
}
break;

default:
return (‘Card Type not recognized.’);
break;
}

return (true);
}{/syntaxhighlighter}

The function accepts a string where the first 2 characters are expected to be the prefix for the Credit Card provider (VI, MC or AX etc.), and the rest is expected to be a numeric string of atleast length 13.

Apart from Mod 10 validation, some additional card-type validations are also performed and a string describing the error (if any) is returned. In no error, true is returned.

You can enforce some more validations on the number depending upon card type (e.g. the second number for American Express cards can only be 4 or 7), but we already had extensive Credit Card validations server-side (including a direct hook-up to the card provider services for debits), and so were happy with some basic checks in javascript.