The easiest way to pre-verify a credit card value is entered correctly is to use the Luhn algorithm to check for mistakes. This is commonly referred to as a mod-10, mod10 or mod 10 check. It’s always important when handling user data to ensure it validates not only on the client, saving a trip to the server, but also server side should the client not support JavaScript. For that reason, we test on both ends.
There are more “elegant” implementations of this algorithm – see the Wikipedia entry referenced above – but they will likely be more difficult for a novice developer to understand. Further, the functions provided here are tolerant of common data entry conventions, such as using spaces and dashes to delimit blocks of numbers as is common with credit card numbers.
function mod10_check(val){ var nondigits = new RegExp(/[^0-9]+/g); var number = val.replace(nondigits,''); var pos, digit, i, sub_total, sum = 0; var strlen = number.length; if(strlen < 13){ return false; } for(i=0;i<strlen;i++){ pos = strlen - i; digit = parseInt(number.substring(pos - 1, pos)); if(i % 2 == 1){ sub_total = digit * 2; if(sub_total > 9){ sub_total = 1 + (sub_total - 10); } } else { sub_total = digit; } sum += sub_total; } if(sum > 0 && sum % 10 == 0){ return true; } return false; } |
You can use the JavaScript version to validate a field on any javascript event. The following snippet illustrates how you might use the onblur event to notify the user the card number appears to be invalid with jQuery.
... <input type="text" name="cc_number" onblur="if(mod10_check(this.value)){$('#cc_error').hide(); } else { $('#cc_error').show(); }" value="" /> <span id="cc_error" style="display:none;">The card number is invalid.</span> ... |
You can then use the following test in PHP to validate the data once it gets to your server.
function mod10_check($val){ $number = preg_replace('/[^0-9]+/', '', $val); $sum = 0; $strlen = strlen($number); if($strlen < 13){ return false; } for($i=0;$i<$strlen;$i++){ $digit = substr($number, $strlen - $i - 1, 1); if($i % 2 == 1){ $sub_total = $digit * 2; if($sub_total > 9){ $sub_total = 1 + ($sub_total - 10); } } else { $sub_total = $digit; } $sum += $sub_total; } if($sum > 0 && $sum % 10 == 0){ return true; } return false; } |
You can see the JavaScript implementation in action here. The only difference from the above example is the addition of an onkeyup event and the inclusion of a valid card message.
Some card numbers you can use to test the code.
1234-5678-9012-3456 - Invalid 4111 1111 1111 1111 - Valid (MC/Visa Like) 3111 111111 11117 - Valid (Amex Like) 6011111111111117 - Valid (Discover Like)