ASP (VBScript)
As mentioned previously, we will use a Luhn function to determine base level
validity of the credit card number. This function doesn't determine if the
credit card number actually exists, but rather that it could mathematically
exist:
Function CheckCCNumLuhn(ccnumber)
Dim i, w, x, y
y = 0
ccnumber
= Replace(Replace(Replace(CStr(ccnumber), "-", ""),
" ", ""), ".", "")
Initially we accept the credit card number and then strip any extraneous
information from the passed value.
w =
2 * (Len(ccnumber) Mod 2)
For
i = Len(ccnumber) - 1 To 1 Step -1
x
= Mid(ccnumber, i, 1)
if
IsNumeric(x) Then
Select Case (i Mod 2) + w
Case 0, 3
y = y + CInt(x)
Case 1, 2
x = CInt(x) * 2
if x > 9 Then
y = y + (x \ 10) + (x - 10)
Else
y = y + x
End if
End Select
End
if
Next
To verify the number, it needs to be stepped through, from right to left
and have a number of mathematic operations processed against it.
y =
10 - (y Mod 10)
if
y > 9 Then y = 0
CheckCC
= (CStr(y) = Right(ccnumber, 1))
End function
Finally we determine whether the integer value computed is equivalent to
the final digit of the credit card number. If it is, then the function returns
true. This indicates
the number is a possible credit card number.
PHP
One of the "requirement" strings in our validation script (validate.inc) is "ccnumber" (which
we've added to the original PHP validation code we created in Usable Forms for the Web). This means that we need to
look for this string as a substring of each field name in the form we're validating,
and if we've found it, a variable named $ccnumber
has been set to TRUE.
If it is, then we know we need to try to validate the current field as credit
card information.
First, we get rid of any spaces or dashes the user might have typed in, then
test the result to see if it's a numeric value ($not_int
is the regular expression /\D/, which matches any non-digit characters in a string):
$value = preg_replace("[
-]+","",$value);
if( $value!="" && preg_match($not_int, $value
) )
{
If we find any non-digits in the value, we add an appropriate error message
onto the value of the variable $err_msg,
and set our validation flag $validated
to FALSE:
$err_msg .= "The <b>$field_name</b> should
contain only
the
digits 0-9.<br />\n";
$validated = FALSE;
}
else
{
Otherwise, we check to see if the user has selected a credit card type:
if( isset($HTTP_POST_VARS["Credit0Card0Type_required"])
)
{
If so, we get that type as the variable $cc_type,
the value in the Card Number field as $cc_number, and the length of that value as
$cc_length:
$cc_type = $HTTP_POST_VARS["Credit0Card0Type_required"];
$cc_number =
$HTTP_POST_VARS["Credit0Card0Number_ccnumber_required"];
$cc_length = strlen($cc_number);
Now we test the length of the number against what's correct for its type,
setting $validated to TRUE or FALSE accordingly:
switch($cc_type)
{
case "MasterCard":
$validated = $cc_length == 16;
break;
case "Visa":
$validated = ($cc_length == 13 ||
$cc_length == 16);
break;
case "American
Express":
$validated = $cc_length == 15;
break;
}
If $validated is FALSE, the number has the wrong number of digits for
the type of card indicated:
if(!$validated)
$err_msg .=
"Wrong number of digits for $cc_type.<br >\n";
else
{
Otherwise, we check to the if the number has the
correct prefix for that type:
switch($cc_type)
{
case "MasterCard":
$prefix = substr($cc_number,
0, 2);
$validated = $validated &&
($prefix > 50 && $prefix < 56);
break;
case "Visa":
$prefix = substr($cc_number,
0, 1);
$validated = $validated &&
($prefix == 4);
break;
case "American
Express":
$prefix = substr($cc_number,
0, 2);
$validated = $validated &&
($prefix == 34 || $prefix == 37);
break;
}
if(!$validated)
$err_msg .=
"Invalid prefix for $cc_type number.<br />\n";
else
{
If the number has met all of the preceding conditions, then we perform the
checksum test using the Luhn formula. First we make a copy of the number,
reversing the order of the digits, since it's easier to count them from left
to right, and store it in a variable named $copy:
$copy = strrev($cc_number);
Then we store its length as $length
and we initialise a running total $sum
to zero:
$length = strlen($cc_number);
$sum = 0;
for($c =
0; $c < $length; $c++)
{
As we add up the digits, we'll want to double every other digit starting
with the second one from the left, since we've reversed their order. Since
the first digit the first digit has the index 0, this means we'll be doubling
the odd-numbered ones. The first digit can be obtained as substr($digit,0,1), the second one as substr($digit,1,1), and so on through
substr($digit,$length-1,1):
$digit = substr($copy,$c,1);
if($c %
2 == 1)
{
If the digit has an odd-numbered index in the string, we double it:
Then we determine if the result is greater than 10. If it is, then it has
two digits (the highest possible value being 2 * 9 = 18), once again using
the substr()
function:
if($digit
> 9)
{
$first = substr($digit,0,1);
$second = substr($digit,1,1);
$digit = $first + $second;
}
}
Now we increment the running total by the value of $digit
(which hasn't changed if the digit had an even-numbered index), and repeat
the process with the next digit until we've gone through all the digits in
$copy:
Now we determine if the final value of $sum
is evenly divisible by 10. If it isn't, we know there was an error in the
number somewhere; we alert the customer accordingly and set the error flag
to FALSE:
if($sum %
10 != 0)
{
$err_msg .=
"The $cc_type number failed to validate.
Please check the number
on your card.<br />\n";
$validated = FALSE;
}
else
{
Finally, if the number's passed all of the above tests, we perform a check
on the expiration date indicated by the user to ensure that he hasn't given
us a date in the past. We obtain the number 1-12 for the current month and
the four-digit current year using date() and compare these to the values selected
in the form:
$thismonth = date("n");
$thisyear = date("Y");
if( $HTTP_POST_VARS["Expiration0Year_required"]
== $thisyear
&&
$HTTP_POST_VARS["Expiration0Month_required"]
< $thismonth )
{
If the year is the same as the current year but the month is previous to
the current month, then we know we've got a problem, and we respond appropriately:
$err_msg .=
"Invalid expiration date
(date indicated is in
the past).<br />\n";
$validated = FALSE;
}
}
}
}
}
}
}
If we've passed through all of the tests in these code blocks, then we assume
that the customer has given us the correct card number and expiration date.
Comments
Be the first to write a comment
You must me logged in to write a comment.