// Credit Card Validation
// 
// Overview
// 
// The following technique will allow you to catch over 90% of all credit card number keying errors. This will be accomplished by validating the card number using the Mod 10 rule, and applying additional card type validations. The benefits of using this technique are:
// 
// ¨ You will catch most keying errors at the client. This reduces server load and gives the user more immediate feedback.
// ¨ You will catch ALL single-digit keying errors.
// ¨ You will catch over 97% of all two-digit transposition errors.
// ¨ The user will not have to select the credit card type.
// 
// It is important to note that this method will NOT provide any additional security. Anyone who is trying to fake a credit card number can easily generate a number that passes the Mod 10 check. So dont let this validation give you a false sense of security. 
//  
// 
// Purpose
// 
// When you ask a user to enter a credit card number on your website, you have likely reached the final step of converting him from a user to a customer. You have done everything necessary to bring him to this point. You have created a marketable product or service; you have built a web site to promote it; you have drawn this user to the site; you have convinced him that he wants/needs your product or service. But bad things can happen when your potential customer is sitting in the comfort of his home, hundreds of miles away from you. You dont have his undivided attention like you would if he was a customer in your physical store. His spouse/children/pets could distract him. The telephone could ring. The length of time that it takes to complete the purchase directly affects the percentage of completed purchases. It is therefore crucial that you speed your customer through the billing process as quickly as possible.
// 
// The Mod 10 rule
// 
// The card numbers for all of the major credit card types are designed to pass a modified digit checksum known as the Mod 10 rule. You start by setting the checksum to the last digit of the card. Next, multiply the second-to-last digit of the card by two, and add the sum of the resulting digits to the checksum. Next, add the third-to-last digit of the card to the checksum. Next, multiply the fourth-to-last digit of the card by two, and add the sum of the resulting digits to the checksum. Repeat this pattern through the remaining digits. To pass the Mod 10 check, the modified checksum must be evenly divisible by 10.
// 
// Example
// 
// Compute the modified checksum for the six digits 987654:
// 
// ¨ Start the checksum with the last digit: 4
// ¨ Multiply the second-to-last digit by two, and add sum of digits: 5 x 2 = 10; 1 + 0 = 1; checksum: 4 + 1 = 5
// ¨ Add the third-to-last digit: 5 + 6 = 11
// ¨ Multiply: 7 x 2 = 14; 1 + 4 = 5; checksum: 11 + 5 = 16
// ¨ Add: 16 + 8 = 24
// ¨ Multiply: 9 x 2 = 18; 1 + 8 = 9; checksum: 24 + 9 = 33
// ¨ Result: 33 is not evenly divisible by 10: number does not pass Mod 10 check.
// 
// Card Types
// 
// Every card type also has designated prefixes that are only used for that card. For example: all VISA cards must start with the digit 4, and all Discover cards must start with the digits 6011. Also, each card type has one or more valid lengths. For example: all VISA cards must be either 13 or 16 digits long, and all Discover cards must be 16 digits long. Because of this, it is not necessary to ask the user to select the credit card type  you can determine this from the number they enter. It may not seem to make much difference, but you want to make the process as simple and quick as possible.
// 
// Implementation
// 
// The user may enter the card number with dashes or spaces to indicate the groupings of the digits on the card. You could check for non-numeric characters and ask the user to enter the number without them, but it is better to just ignore them. The extractDigits function (JavaScript), below, will return a string that contains only the digits from the given string.

function extractDigits(mixedString) {
   var digitsOnly = '';
   var thisDigit = '';
   for (var i = 0; i < mixedString.length; i++) {
      thisDigit = mixedString.charAt(i);
      if (thisDigit >= '0' && thisDigit <= '9')
         digitsOnly = digitsOnly + thisDigit;
   }
   return digitsOnly;
}
 

// This implementation of the Mod 10 rule uses a few shortcuts. Rather than compute the sum of the digits of the doubled values every time they are needed, the function uses a string to map the digit to the pre-computed result of the operation. For example, 5 is the seventh character in the string (zero relative). This is the result of the computation 7 * 2 = 14; 1 + 4 = 5. The boolean value of the translateFlag variable determines whether the next digit needs to be translated. It is initialized based on whether the credit card number has an odd or even number of digits. This allows the function to process the string left-to-right. Following is the code for the checkMod10 function:

function checkMod10(ccNumber) {
   var translateMap = '0246813579';
   var digitSum = 0;
   var translateFlag = ((ccNumber.length % 2) == 0);
   for (var i = 0; i < ccNumber.length; i++) {
       digitSum += parseInt(translateFlag ?
            translateMap.charAt(ccNumber.charAt(i)) :
            ccNumber.charAt(i) , 10)
      translateFlag = !translateFlag;
   }
   return (digitSum % 10) == 0;
}
 

// The validCardType function, below, will determine if the card number prefix and length matches one of the known card types. To change the card types recognized by the function, add or remove the appropriate value pairs to the cardLengths and cardDigits array declarations. The code is fairly straightforward: it matches the card number against one of the valid prefixes, and then determines if the length is valid for the card type determined by that prefix.

function validCardType(ccNumber) {
   var cardLengths = new Array (
         'v', 13, 'v', 16, 'm', 16,
         'a', 15, 'c', 14, 'd', 16);
   var cardDigits = new Array (
         'v', '4', 'm', '51', 'm', '52', 'm', '53' ,
         'm', '54', 'm', '55', 'a', '34', 'a', '37',
         'c', '300', 'c', '301', 'c', '302', 'c', '303',
         'c', '304', 'c', '305', 'c', '36', 'c', '38',
         'd', '6011');
   var validCard = false;
   var correctLength = false;
   var cardType = '' ;
   for (var i = 0; i < cardDigits.length - 1; i += 2) {
      if (cardDigits[i + 1] == ccNumber.substr(0, cardDigits[i + 1].length)) {
         validCard = true;
         cardType = cardDigits[i];
         break;
      }
   }
   if (validCard) {
      var cardLen = ccNumber.length;
      for (var i = 0; i < cardLengths.length - 1; i += 2) {
         if ((cardType == cardLengths[i]) && (cardLen == cardLengths[i + 1])) {
            correctLength = true;
            break;
         }
      }
      validCard = correctLength;
   }
   return validCard;
}
 

// Combining the validations yields the ccCheck function, which displays a message indicating the validity of the card number. In practice, you will need to modify the action taken for a valid card to submit the form.

function ccCheck(ccNumber) {
   var ccDigits = extractDigits(ccNumber);
   if (checkMod10(ccDigits) && validCardType(ccDigits)) {
      alert('Card number valid.');
   } else {
      alert('Invalid credit card number'); 
   }
}
 

// You can test the function with the following HTML:
// 
//
//
//
// <script language="JavaScript" src="ccCheck.js"></script_> // Note added _ to allow embedding this in script file
// <body>
// 
// <form name="ccValid">
// <input type="text" name="ccNum">
// <input type="button" value="Validate" onClick="ccCheck(this.form.ccNum.value)">
// </form>
// 
// Conclusion
// 
// By applying the above functions to your client-side credit card validation routines, you can speed the process of collecting billing information from your customer, and reduce the number of input errors that make it to your server-side validation routines.

