Validating Credit Card Input

 

Introduction.  We have already done some work with validating inputs such as social security numbers and e-mail addresses.  Most of this was based on using particular built-in JavaScript string manipulation functions and knowing things about the formats of the desired inputs.  Now we want to move onto something that is probably much more sophisticated than you are aware, validating credit card inputs.

Based on ANSI X4.13, the LUHN formula (also known as the modulus 10 -- or mod 10 -- algorithm ) is used to generate and/or validate and verify the accuracy of credit-card numbers. 

  • Most credit cards contain a check digit, which is the digit at the end of the credit card number. 

  • The first part of the credit-card number identifies the type of credit card (Visa, MasterCard, American Express, etc.), 

  • The middle digits identify the bank and customer. 

Algorithm for Checking Credit Cards.  To generate the check digit, the LUHN formula is applied to the number. To validate the credit-card number, the check digit is figured into the formula. 

Here's how the algorithm works for verifying credit cards; the math is quite simple: 

  1. Starting with the second to last digit and moving left, double the value of all the alternating digits.  
  2. Starting from the left, take all the unaffected digits and add them to the results of all the individual digits from step 1. If the results from any of the numbers from step 1 are double digits, make sure to add the two numbers first (i.e. 18 would yield 1+8). Basically, your equation will look like a regular addition problem that adds every single digit. 
  3. The total from step 2 must end in zero for the credit-card number to be valid. 

The LUHN formula was created in the late 1960s by a group of mathematicians. Shortly thereafter, credit card companies adopted it.  Because the algorithm is in the public domain, it can be used by anyone. 

The LUHN formula is also used to check Canadian Social Insurance Number (SIN) validity. In fact, the LUHN formula is widely used to generate the check digits of many different primary account numbers. Almost all institutions that create and require unique account or identification numbers use the Mod 10 algorithm.

An Example.  Now we are going to work an example for what might actually be a credit card number.  Consider,

6011-0065-7301-3021

 

Which should be somewhat reminiscent of a Discover Card number.  Let's put this number into a table that enumerates the digits.

 

Place 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
Digit 6 0 1 1 0 0 6 5 7 3 0 1 3 0 0 1

 

Doubling 12   2   0   12   14   0   6   0  

 

Single Digit 3   2   0   3   5   0   6   0  

 

Unaffected   0   1   0   5   3   1   0   1

 

Sum = 30 3 0 2 1 0 0 3 5 5 3 0 1 6 0 0 1

 

So this would be a valid credit card number, which is not likely to be something that credit card companies would like to have you be able to generate.

Some More Criteria.  There are also some criteria that need to be checked in order to ensure that certain types of cards have certain lengths and prefixes or leading digits.  The basic criteria are listed in the following table.

 

 

Card Type Length Prefixes
American Express 15 34, 37
Discover 16 6011
Mastercard 16 51, 52, 53, 54, 55
Visa 13 or 16 4

 

Some Code.  Yikes!  So you think it would be a good assignment to have you develop the code to validate this?  Now we are going to develop a form so that you can test the validity of credit card numbers.

The code has three major sections

  1. Obtaining inputs and some preprocessing
  2. Validating the coordination between type, length and prefixes
  3. Testing the Luhn criterion

You should copy the following code into a file called IsCreditCard.html.

 

<html>
<head>
<title>Validating Credit Card Inputs</title>
<script Language="JavaScript">
// JavaScript by ADI Associates, Inc. - public domain 1999
// modified by Dale R. "Zy" Fox - spring 2002
// ---------------------------------------------------------------------

function CheckCC()
{
// ---------------------------------------------------------------------
// get the inputs from the form
// ---------------------------------------------------------------------
// obtaining the number

CC_Num = window.document.CCInput.txtCCNumber.value;

// obtaining the type of Credit Card
if (window.document.CCInput.rbCCType[0].checked == true) { 
var CC_Type = window.document.CCInput.rbCCType[0].value; }

if (window.document.CCInput.rbCCType[1].checked == true) {
var CC_Type = window.document.CCInput.rbCCType[1].value; }

if (window.document.CCInput.rbCCType[2].checked == true) {
var CC_Type = window.document.CCInput.rbCCType[2].value; }

if (window.document.CCInput.rbCCType[3].checked == true) {
var CC_Type = window.document.CCInput.rbCCType[3].value; }



// ---------------------------------------------------------------------
// CCN_digits stores just the digits from the Credit Card Number
// ---------------------------------------------------------------------

var CCN_digits = "";

// ---------------------------------------------------------------------
// get the digits from the entered Card Number
// Note - the isNaN (Not a Number) function is not used 
// because it is not supported by JavaScript 1.0
// ---------------------------------------------------------------------

for (var i = 0; i < CC_Num.length; i++)
{

if ((CC_Num.charAt(i) == "0") || 
(CC_Num.charAt(i) == "1") ||
(CC_Num.charAt(i) == "2") || 
(CC_Num.charAt(i) == "3") || 
(CC_Num.charAt(i) == "4") || 
(CC_Num.charAt(i) == "5") || 
(CC_Num.charAt(i) == "6") || 
(CC_Num.charAt(i) == "7") || 
(CC_Num.charAt(i) == "8") || 
(CC_Num.charAt(i) == "9"))

{
CCN_digits = CCN_digits + CC_Num.charAt(i);
}

}

// ---------------------------------------------------------------------
// validcard is the true/false indicator for a valid card 
// - the funbction can be modified so it is returned to the calling routine.
// ---------------------------------------------------------------------

var validcard = false;

// ---------------------------------------------------------------------
// msgind is used to communicate the type of alert to 
// post in case of a problem
// 1=invalid prefix (prefix does not match card type)
// 2=invalid number of digits in card number 
// for the card type selected
// ---------------------------------------------------------------------

var msgind = 0;

// ---------------------------------------------------------------------
// Check the card for having a valid prefix and number of 
// digits (length) for the card type.


if (CC_Type == "AmericanExpress")

if (CCN_digits.length == 15)

if ((CCN_digits.substring (0, 2) == "34") || 
(CCN_digits.substring (0, 2) == "37"))

validcard = true;

else

msgind = 1;

else

msgind = 2;

else if (CC_Type == "Discover")

if (CCN_digits.length == 16)

if (CCN_digits.substring (0, 4) == "6011")

validcard = true;

else

msgind = 1;

else 

msgind = 2;

else if (CC_Type == "MasterCard")

if (CCN_digits.length == 16)

if ((CCN_digits.substring (0, 2) >= "51") && (CCN_digits.substring (0, 2) <= "55"))

validcard = true;

else

msgind = 1;

else 

msgind = 2;

else if (CC_Type == "Visa")

if ((CCN_digits.length == 16) || (CCN_digits.length ==13))

if (CCN_digits.substring (0, 1) == "4")

validcard = true;

else

msgind = 1;

else 

msgind = 2;

else

// ---------------------------------------------------------------------
// Invalid card type - this should be impossible to reach as 
// long as all valid card types are in the list above
// not really an option if someone selects a radio button
// ---------------------------------------------------------------------

alert ("Sorry, "+ CC_Type + " is not currently being accepted - please contact us by phone or email.");

if (!validcard)
{

if (msgind == 1)

// ---------------------------------------------------------------------
// Invalid prefix
// ---------------------------------------------------------------------

alert ("The Card Number ("+CC_Num + ") and the Card Type (" + CC_Type + ") do not match.");

else if (msgind == 2)

// ---------------------------------------------------------------------
// Invalid number of digits (length)
// ---------------------------------------------------------------------

alert ("The Card Number ("+CC_Num + ") is not the right length for the Card Type (" + CC_Type + ").");

}

if (validcard) alert("The card number and card type match");

// ---------------------------------------------------------------------
// Perform the mod10 check sum routine on the 
// digits in the card number
// 1) Go through the Credit Card Number digits, starting on 
// the RIGHT.
// If the position is odd
// add the digit to the checksum tally. 
// If the position is even
// multiply the digit by 2
// if the result is greater than 9
// divide the result by 10 
// and add the remainder 
// to the checksum tally
// add 1 to the checksum tally
// if the result is 9 or less
// add the result to the checksum tally
// Repeat for each digit.
// 2) Divide the checksum tally by 10
// 3) If there is a remainder
// the Credit Card Number is not valid.
// ---------------------------------------------------------------------

var CheckSum = 0;
// ---------------------------------------------------------------------
// for loop to look at the Credit Card Number
// ---------------------------------------------------------------------

for (var x = 1; x <= CCN_digits.length; x++)
{

// ---------------------------------------------------------------------
// x is subtracted from the length of the CCN 
// to point at the digits from RIGHT to LEFT
// ---------------------------------------------------------------------

var CurrentDigit = CCN_digits.charAt(CCN_digits.length - x);
if (x % 2 == 0)
{

// ---------------------------------------------------------------------
// even position in credit card number 
// (2nd, 4th, etc. from RIGHT of Credit Card Number)
// ---------------------------------------------------------------------

var WorkDigit = CurrentDigit * 2; 

if (WorkDigit > 9)

CheckSum = CheckSum + (1 - 0);
CheckSum = CheckSum + (WorkDigit % 10);

}
else
{

CheckSum = CheckSum + (WorkDigit - 0);

}
else
{

// ---------------------------------------------------------------------
// odd position in credit card number 
// (1st, 3rd, etc. from RIGHT of Credit Card Number)
// ---------------------------------------------------------------------

CheckSum = CheckSum + (CurrentDigit - 0);

}

}
// ---------------------------------------------------------------------
// end for loop
// ---------------------------------------------------------------------


if (CheckSum % 10) 

// ---------------------------------------------------------------------
// The CheckSum does not divide evenly by 10
// ---------------------------------------------------------------------

validcard = false; 
alert ("I'm sorry, the Card Number ("+ CC_Num +") is not correct - perhaps there is a typo or two numbers are reversed?"); 


if (validcard) alert("Your card number passes the Luhn Criteria"); 
}
// ---------------------------------------------------------------------
// end function 
// ---------------------------------------------------------------------

</script>
</head>

<body bgcolor = "#000044" text="#DDAAFF">
<p align="center"><b><font size="5" color="#BBBB88">Validating Credit Card
Inputs</font></b>
<p>&nbsp;</p>
<p>&nbsp;</p>

<form name = "CCInput">
<div align="center">
<center>
<table width=715>
<tr>
<td align="right" width="334"><font size=4><b>Please enter the credit card number:</b></font></td>
<td width="367"><input type="text" width="25" name = "txtCCNumber" </td size="24" style="font-size: 14pt">
</tr>
<tr>
<td align="right" width="334">&nbsp; </td>
<td width="367">&nbsp; 
</tr>
<tr>
<td align="right" width="334"><b><font size="4" color="#DDAAFF">Check the credit card type:</font></b></td>
<td width="367"><input type="radio" name="rbCCType" value="AmericanExpress"> <font size="4" color="#DDDDDD">American Express</font>
<p><input type="radio" name="rbCCType" value="Discover"> <font size="4" color="#DDDDDD">Discover</font></p>
<p><input type="radio" name="rbCCType" value="MasterCard"> <font size="4" color="#DDDDDD">MasterCard</font></p>
<p><input type="radio" name="rbCCType" value="Visa"> <font size="4" color="#DDDDDD">Visa</font>
</tr>
<tr>
<td align="right" width="334"></td>
<td width="367">
</tr>
<tr>
<td colspan ="2" width="707" align="center"><input type="button" value="Validate" name="cmdValidate" style="font-size: 14pt; font-weight: bold" onClick="CheckCC();"></td>
</tr>
</table>
</center>
</div>
</form>
</body>

</html>

 

There are a few alert( ) functions in the code to give you feedback about what has happened at particular steps.

After uploading and accessing this page and entering your name, you should see something like the following at some step in the process.