Credit Card Validation and Verification

This chapter goes through credit card validation and verification, such as is vital during the checkout procedure of an online shopping application. The chapter as a whole covers all aspects of the checkout procedure in detail.

This sample is taken from Chapter 7: "Credit Card Validation and Verification" of the Glasshaus title "Usable Shopping Carts"

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.

if($ccnumber)

      {

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:

                    $digit *= 2;

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:

                  $sum += $digit;

                }

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.

George Petrov

George PetrovGeorge Petrov is a renowned software writer and developer whose extensive skills brought numerous extensions, articles and knowledge to the DMXzone- the online community for professional Adobe Dreamweaver users. The most popular for its over high-quality Dreamweaver extensions and templates.

George is also the founder of Wappler.io - the most Advanced Web & App Builder

See All Postings From George Petrov >>

Comments

Be the first to write a comment

You must me logged in to write a comment.