Appendix A. The Credit Card Validation Library

CreditCardValidation.dll

In the examples in this book, we have used the CreditCardValidation.dll library to build XML Web services that validate credit card numbers. We have taken this approach to concentrate on the subject of each chapter and to simplify the projects that you have created.

In this appendix, we explain how credit card numbers are validated and detail the code statements of the CreditCardValidation.dll library. Reading this appendix is not essential for you to understand the rest of this book. We provide this information for the curious-minded reader.

You might notice that the code we list in this appendix is not optimized; we have striven for clarity over performance. Unlike the rest of this book, we do not provide step-by-step instructions for building this library. Visual Studio .NET projects containing all of the code are included in the sample code, which, if you followed the sample code download and installation steps in the Introduction, can be found at C:XMLWebServicesSBSProjectsAppA

How Card Numbers Are Validated

Validating a credit card number is the process of ensuring that a number meets the criteria used by a card issuer for generating numbers. Validation does not include any of the following, which are usually performed as part of a sales transaction:

  • Ensuring that a provider has issued the credit card number

  • Ensuring that the card holder has sufficient credit to enter into a transaction

  • Ensuring that the card provider has not cancelled the card

  • Ensuring that the card has not expired

Validating card numbers is a two-stage process. First the card number is checked to ensure it has the correct prefix and length for the card type, and then a simple formula (known as the LUHN formula) is applied to the number to ensure that the number is not simply a random sequence of digits. The CreditCardValidation.dll library validates numbers for VISA, MasterCard, and American Express (AMEX) cards.

Prefixes and Lengths

Each type of card number has a different prefix and length requirement, as illustrated in the following table. Checking that the number conforms to these requirements is the first step in validating a card number. For example, all VISA card numbers start with the digit 4 and contain either 13 or 16 digits.

Credit Card Issuer

Valid Prefixes

Valid Lengths

VISA

4

13, 16

MasterCard

51, 52, 53, 54, 55

16

AMEX

34, 37

15

The LUHN Formula

The LUHN formula is a simple checksum that can be applied to the types of credit cards that we support; applying the formula to valid card numbers will always result in a number that ends with a zero. To demonstrate how the LUHN formula is applied to credit card numbers, we will walk though the process using the VISA card number 4921 8352 2155 2042.

  1. Reverse the digits of the credit card number.

    Reversing the digits of the example number gives us: 2402 5512 2538 1294

  2. Add the odd-numbered digits together.

    By odd-numbered, we mean those digits that are at the first, third, fifth (and so on) position in the reversed-order number, which gives us the following sum:

    2 + 0 + 5 + 1 + 2 + 3 + 1 + 9 = 23

  3. Double the value of the even-numbered digits in the reversed-order number, and then add them together.

    If the value of the doubled number is less than 9, we simply add that number to the total for this step. For example, the number 1 is doubled to 2.

    For numbers that produce a doubled value that is more than 9, we add the value of each digit to the total for this step. For example, the digit 9 is doubled to 18, so we add 1 and 8 to the total. This gives us the following sum for our example number. We have indicated where we are adding individual digits in parenthesis: 8 + 4 + (1 + 0) + 4 + (1 + 0) + (1 + 6) + 4 + 8 = 37

  4. Add the totals from the previous two steps; if the card number is valid, the result will end with a zero.

    For our example, we add the result from steps 2 and 3 to get a total of 60. Because this number ends with a zero, the card number is valid. By checking the prefix and length requirements and applying the LUHN formula, we are able to determine that this is a valid VISA card number.

The CreditCardValidation Code

The CreditCardValidator library contains four classes. The main class, named Validator, contains the methods that support validating credit card numbers. The other three classes are all exceptions, which are thrown to indicate problems with the card number that is being validated.

The Exception Classes

We use the exception classes to indicate that the card number does not conform to the prefix and length requirements or that it contains illegal characters. For our purposes, legal characters are the digits 0 to 9 and white space, allowing us to process card numbers in the form 4921835221552042 as well as 4921 8352 2155 2042, which is the way that numbers are usually printed on credit cards. The code statements for the three exceptions are listed below.

CCInvalidPrefixException

The CCInvalidPrefixException is thrown when the card number does not match the prefix requirement for the card type—for example, when a VISA card number does not start with the digit 4.

Example A-1. C#

namespace XMLWebServicesStepByStep.CreditCardValidator {
    // Exception thrown when the candidate number
    // starts with an invalid prefix
    public sealed class CCInvalidPrefixException 
        : System.ApplicationException {

        // Create a new instance of this exception
        // The message that describes the error
        public CCInvalidPrefixException(string p_message) 
            : base(p_message) {
            // do nothing - rely on the base class
        }
    }
}

Example A-2. Visual Basic .NET

Namespace XMLWebServicesStepByStep.CreditCardValidator

    Public Class CCInvalidPrefixException
        Inherits ApplicationException

        Public Sub New(ByVal p_message As String)
            MyBase.New(p_message)
        End Sub

    End Class
End Namespace

CCInvalidLengthException

The CCInvalidLengthException is thrown when the card number does not match the length requirement for the card type—for example, when a MasterCard card number does not contain 16 digits.

Example A-3. C#

namespace XMLWebServicesStepByStep.CreditCardValidator {
    // Exception thrown when the candidate number 
    // contains the wrong number of characters
    public sealed class CCInvalidLengthException 
        : System.ApplicationException {

        // Create a new instance of this exception
        // The message that describes the error
        public CCInvalidLengthException(string p_message) 
            : base(p_message) {
            // do nothing - rely on the base class
        }
    }
}

Example A-4. Visual Basic .NET

Namespace XMLWebServicesStepByStep.CreditCardValidator
    Public Class CCInvalidLengthException
        Inherits ApplicationException

        Public Sub New(ByVal p_message As String)
            MyBase.New(p_message)
        End Sub

    End Class
End Namespace

CCIllegalCharacterException

The CCIllegalCharacterException is thrown when the card number contains a character that is neither white space nor the digits 0 to 9.

Example A-5. C#

namespace XMLWebServicesStepByStep.CreditCardValidator {
    // Exception thrown when the candidate number 
    // contains an illegal character
    public sealed class CCIllegalCharacterException 
       : System.ApplicationException {

        // Create a new instance of this exception
        // The message that describes the error
        public CCIllegalCharacterException(string p_message) 
            : base(p_message) {
            // do nothing - rely on the base class
        }
    }
}

Example A-6. Visual Basic .NET

Namespace XMLWebServicesStepByStep.CreditCardValidator
    Public Class CCIllegalCharacterException
        Inherits ApplicationException

        Public Sub New(ByVal p_message As String)
            MyBase.New(p_message)
        End Sub

    End Class
End Namespace

The Validator Class

The Validator class contains the methods that are used to validate credit card numbers. Three methods are public (one for each type of card that we support), and two are private utility methods. Each method is described and listed in the following sections.

The formatCreditCardNumber Method

We process card numbers as strings of characters. The formatCreditCardNumber method is a private method that checks for illegal characters and removes any white space. Although we allow card numbers to contain spaces and tabs, we remove them to simplify the validation process. If an illegal character is found, a CCIllegalCharacterException is thrown. Otherwise, the method returns a string containing only the numeric characters from the card number string.

Example A-7. C#

private string formatCreditCardNumber(string p_card_number) {
    // define a string builder to use in composing the response
    StringBuilder x_builder = new StringBuilder();
    // iterate through the characters and check them for validity
    foreach (char x_char in p_card_number.ToCharArray()) {
        if (Char.IsDigit(x_char)) {
            // append this to the result
            x_builder.Append(x_char);
        } else if (Char.IsWhiteSpace(x_char)) {
            // ignore this character - we will allow the
            // user to supply credit card numbers that 
            // contain whitespace
        } else {
            // if the character is not a digit and is not
            // whitespace, then it is illegal for our purposes
            throw new CCIllegalCharacterException("Character "" 
                + x_char + "" cannot be processed.");
        }
    }
    // return the contents of the string builder
    return x_builder.ToString();
}

Example A-8. Visual Basic .NET

Private Function _
    formatCreditCardNumber(ByVal p_card_number As String) As String
    ’define a string builder to compose the result
    Dim x_string_builder As New StringBuilder()
    ’ iterate through the characters of the card 
    Dim x_char As Char
    For Each x_char In p_card_number.ToCharArray()
        If (Char.IsDigit(x_char)) Then
            ’ add this number to the string builder
            x_string_builder.Append(x_char)
        ElseIf (Char.IsWhiteSpace(x_char)) Then
            ’ ignore this character - we will allow the
            ’ user to supply credit card numbers that 
            ’ contain whitespace
        Else
            ’ if the character is not a digit and is not
            ’ whitespace, then it is illegal for our purposes
            Dim x_msg As String = String.Format _
            ("Character {0} cannot be processed", x_char)
            Throw New CCIllegalCharacterException(x_msg)
        End If
    Next
    Return x_string_builder.ToString()
End Function

The checkLUHN method

The private checkLUHN method applies the LUHN formula to the card number, which is passed to the method as a string argument. This method works on the basis that any whitespace characters have already been removed from the argument string using the formatCreditCardNumber method. The checkLUHN method returns true if the LUHN formula results in a valid card number and false otherwise.

Example A-9. C#

private bool checkLUHN(string p_card_number) {

    // reverse the credit card number
    char[] x_chars = p_card_number.ToCharArray();
    Array.Reverse(x_chars);
    p_card_number = new String(x_chars);

    // define an int to hold the result
    int x_total = 0;

    for (int i = 0; i < p_card_number.Length; i+= 2) {
        // simply add the first digit to the total
        x_total += Int32.Parse(new string(p_card_number[i], 1));

        // we need to double the value of the even digit, if 
        // there is one. Note: we need to check the length because
        // AMEX uses an odd number of characters (13)
        if (p_card_number.Length > i + 1) {
            // get an integer value that is twice that of the 
            // next digit
            int x_second = Int32.Parse(
                new string(p_card_number[i + 1], 1)) * 2;
            // if the value is >= 10, we need to add the value
            // of the tens and units together, so that 15 is
            // treated as 1 + 5 = 6.
            if (x_second > 9) {
                x_total += x_second/10 + (x_second % 10);
            } else {
                // the digit value is 9 or less, and so
                // can be directly added to the total 
                x_total += x_second;   
            }                 
        }
    }
    // end of for loop

    // check that the total is divisible by 10
    if (x_total % 10 == 0) {
        // the total is divisible by 10 without
        // leaving a remainder - this is a valid
        // result from the LUHN formula
        return true;
    } else {
        // the number leaves a remainder when divided
        // by 10 - this is not a valid result from the
        // LUHN formula
        return false;
    }
}

Example A-10. Visual Basic .NET

Private Function checkLUHN(ByVal p_card_number As String) _
    As Boolean
    Dim x_arr As Char() = p_card_number.ToCharArray()
    ’ reverse the contents of the array
    Array.Reverse(x_arr)
    ’ reformulate the string
    p_card_number = New String(x_arr)

    ’ define the total for the checksum
    Dim x_total As Integer
    ’define the integer for the loop
    Dim i As Integer

    For i = 0 To p_card_number.Length - 1 Step 2
        x_total += Integer.Parse( _
            New String(p_card_number.Chars(i), 1))
        If (p_card_number.Length > i + 1) Then
            Dim x_second As Integer
            x_second = Integer.Parse( _
                New String(p_card_number.Chars(i + 1), 1)) * 2

            ’ if the value is >= 10, we need to add the value 
            ’ of the tens and units together, so that 15 
            ’ is treated as 1 + 5 = 6
            If (x_second > 9) Then
                x_total += Int(x_second / 10) + x_second Mod 10
            Else
                ’ simply add the value to the total
                x_total += x_second
            End If
        End If
    Next i

    If (x_total Mod 10 = 0) Then
        ’ the credit card number is valid
        Return True
    Else
        ’ the credit card number is not valid
        Return False
    End If
End Function

The ValidateAMEX, ValidateMasterCard, and ValidateVISA Methods

These three public methods are used to validate a card number. Each method calls the formatCreditCardNumber method, checks the length and prefix requirements for the type of card that the method supports, and then calls the checkLUHN method to validate the number itself. If the number does not conform to the prefix or length requirements, a CCInvalidPrefixException or CCInvalidLengthException will be thrown; otherwise the result of the checkLUHN method will be returned to the caller.

Example A-11. C#

public bool ValidateAMEX(string p_card_number) {
    // format the number to remove whitespace
    p_card_number = formatCreditCardNumber(p_card_number);
    // AMEX cards are always 15 digits long 
    // and start with either "34" or "37"
    if (p_card_number.Length == 15) {
        // the card number contains the correct 
        // number of digits
        if (p_card_number.StartsWith("34") 
            || p_card_number.StartsWith("37")) {
            // the card has the required prefix
            // - we can move on to check the number
            return checkLUHN(p_card_number);
        } else {
            // the card does not have a valid prefix
            throw new CCInvalidPrefixException(
                "AMEX card numbers " + 
                "are prefixed with either "34" or "37".");
        }
    } else {
        // the card does not have the required
        // number of digits
        throw new CCInvalidLengthException(
            "AMEX cards contain 15 digits.");                
    }
}

public bool ValidateVisa(string p_card_number) {
    // format the number to remove whitespace
    p_card_number = formatCreditCardNumber(p_card_number);
    // VISA cards are either 13 or 16 digits long and
    // start with "4"
    if (p_card_number.Length == 13 || p_card_number.Length == 16) {
        if (p_card_number.StartsWith("4")) {
            // the card has the required prefix
            // - we can move on to check the number itself
            return checkLUHN(p_card_number);
        } else {
            // the card number does not have a valid prefix
            throw new CCInvalidPrefixException(
                "VISA cards are prefixed with "4".");
        }
    } else {
        // the card does not have the required number of digits
        throw new CCInvalidLengthException(
            "VISA card numbers contain either 13 or 16 digits."); 
    }
}

public bool ValidateMasterCard(string p_card_number) {
    // format the number to remove whitespace
    p_card_number = formatCreditCardNumber(p_card_number);
    // MasterCard numbers are 16 digits long and start 
    // with the range 51-55
    if (p_card_number.Length == 16) {
        // the card number has the required number of digits
        int x_second_digit = 
            Int32.Parse(p_card_number[1].ToString());
        if (p_card_number.StartsWith("5") && 
            x_second_digit >= 1 &&
            x_second_digit <= 5) {
            return checkLUHN(p_card_number);
        } else {
            // the card does not have a valid prefix
            throw new CCInvalidPrefixException(
                "MasterCard numbers start with 51 through " +
                "55 inclusive.");
        }
    } else {
        // the card number does not have the right number of digits
        throw new CCInvalidLengthException(
            "MasterCard numbers contain 16 digits");
    }
}

Example A-12. Visual Basic .NET

Public Function ValidateAMEX(ByVal p_card_number As String) _
    As Boolean
    ’ format the number to remove whitespace and check for
    ’ illegal chars
    p_card_number = formatCreditCardNumber(p_card_number)
    ’AMEX cards are always 15 digits long and start with
    ’ either "34" or "37"
    If (p_card_number.Length = 15) Then
        ’ this number is the right length for AMEX
        If (p_card_number.StartsWith("34") Or _
            p_card_number.StartsWith("37")) Then
            ’ this card is the right length and has a valid prefix
            ’ - we can move on to check the validity 
            ’ of the number itself
            Return checkLUHN(p_card_number)
        Else
            ’ this card number does not have the correct prefix,
            ’ and so is not a valid AMEX card
            Throw New CCInvalidPrefixException( _
                "AMEX card numbers are prefixed with either" + _
                "34 or 37.")

        End If
    Else
        ’ this number  has the wrong number of digits
        Throw New CCInvalidLengthException( _
            "AMEX cards contain 15 digits.")
    End If
End Function

Public Function ValidateVisa(ByVal p_card_number As String) _
    As Boolean
    ’ format the number to remove whitespace and check for 
    ’ illegal chars
    p_card_number = formatCreditCardNumber(p_card_number)
    ’ VISA cards are either 13 or 16 digits long and start with "4"
    If (p_card_number.Length = 13 _
        Or p_card_number.Length = 16) Then
        If (p_card_number.StartsWith("4")) Then
            ’ the number has a valid prefix
            ’ - we can now move on to check the validity 
            ’ of the number itselt
            Return checkLUHN(p_card_number)
        Else
            ’ this card number does not have a valid prefix
            Throw New CCInvalidPrefixException( _
                "VISA cards are prefixed with 4.")
        End If
    Else
        ’ this card number does not have the right number of digits
        Throw New CCInvalidLengthException( _
            "VISA card numbers contain either 13 or 16 digits.")
    End If
End Function

Public Function ValidateMasterCard(ByVal p_card_number As String) _
    As Boolean
    ’ format the number to remove whitespace and check for 
    ’ illegal chars
    p_card_number = formatCreditCardNumber(p_card_number)
    ’ MasterCard numbers are 16 digits long and 
    ’ start with the range 51-55
    If (p_card_number.Length = 16) Then
        Dim x_second_digit As Integer = Val(p_card_number.Chars(1))
        If (p_card_number.StartsWith("5") _
            And x_second_digit >= 1 And x_second_digit <= 5) Then
            ’ the number has a valid prefix
            ’ - we can now move on to check the number itself
            Return checkLUHN(p_card_number)
        Else
            ’ the number does not have the required prefix
            Throw New CCInvalidPrefixException( _
                "MasterCard numbers start with 51 through " + _
                "55 inclusive.")
        End If
    Else
        ’ this card number does not have the right number of digits
        Throw New CCInvalidLengthException( _
            "MasterCard numbers contain 16 digits")
    End If
End Function

Summary

In this appendix, we have described credit card number validation code that we have used throughout this book to build XML Web services. It is not essential to understand all of the code statements and techniques used in the example. We have treated this functionality as a backdrop to create XML Web services that you can use and test.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.222.53.26