Link Round-Up for 9/20/07Introduction to My.Computer.Network

How To Do Credit Card Validation in VB.NET

September 20th, 2007

Pick a card, any cardWhen you’re depending on human interaction to enter a credit card number often you’ll find the user has accidentally typed in the wrong number. That’s why credit card number validation is a common operation in e-commerce web apps and some point-of-sale or order taking desktop apps. By pre-validating the card number a costly round trip to the credit card processor’s system can be avoided.

In this code example we will build a simple validation class that will tell us if a user entered credit card is valid and what type of card it is. I’ll also being using some techniques taken from a few of my recent tutorial articles.

The Luhn Algorithm

Credit card numbers are validated using the Luhn algorithm. This algorithm performs a simple Mod 10 checksum that’s intended to detect accidental errors in a sequence of numbers. For more on this algorithm see the Wikipedia link.

Credit Card Number Format and Test Values

In addition to validating according to Luhn algorithm, credit cards begin with certain numbers and have a certain length. Here are the formats for the four credit card types we’ll be looking at in this example:

  • Visa: 13 or 16 digit numbers starting with 4
  • MasterCard: 16 digit numbers starting with 5
  • Discover: 16 digit numbers starting with 6011 or 65
  • AMEX: 15 digit numbers starting with 34 or 37

For testing purposes you can use these values:

  • 13 Digit Visa: 4222222222222
  • 16 Digit Visa: 4111-1111-1111-1111
  • MasterCard: 5431-1111-1111-1111
  • Discover: 6011-6011-6011-6611
  • AMEX: 341-1111-1111-1111

Coding the Routine

After defining the class, we define an Enum for the credit cards in our example:

Public Class CreditCard

    Public Enum CreditCardTypes
        Invalid = 1
    End Enum

Notice that we’re going to use the first element as a placeholder for any invalid values. If you wanted to add more cards to the validation routine, just add them at the end of the enum.

Next, we’re going to define a list of regular expression patterns for our supported credit cards. Note that this is a private shared variable.

Private Shared CreditCardPatterns As New List(Of String) _
              (New String() { _
              "^(4\d{12})|(4\d{15})$", _
              "^5[1-5]\d{14}$", _
              "(^(6011)\d{12}$)|(^(65)\d{14}$)", _

Private Shared _cardNumber As String

As you can see, we’re using a little trick here to initialize our generic list using a string array. Also note that our list matches up with the enum except of the invalid value. This makes it easy to look up our values in the list. Add any new values to the end of the list and make sure the pattern corresponds to the enum.

The Visa regular expression used here is rather simple and you may need more validation to handle all the variations of this card. More complex validation regular expressions can be found at RegExLib.

We will be storing the credit card number at the module level so that we can have access to it in our Predicate function we’ll be using later.

Now, let’s start our Validation routine. In it you’ll see that we’re passing in the card number as a string and returning the card type. Our first order of business is to strip out everything but the digits from our number and declare and initialize our variables.

Public Shared Function Validate(ByVal cardNumber As String) As CreditCardTypes
    Dim CardType As CreditCardTypes = CreditCardTypes.Invalid
    _cardNumber = Regex.Replace(cardNumber, "[^\d]", String.Empty)
    CardType = CType(CreditCardPatterns.FindIndex(AddressOf FindPattern), CreditCardTypes)
    If CardType = CreditCardTypes.Invalid Then
        _cardNumber = String.Empty
        Return CreditCardTypes.Invalid
    End If

Here we see the default return value being set and then our module level variable for the card number being set by using regular expressions to remove all but the numeric values from the string. Next we search for a match to our number by search our pattern list with a Predicate function called FindPattern. Here’s what the Predicate looks like

Private Shared Function FindPattern(ByVal value As String) As Boolean
    If Regex.IsMatch(_cardNumber, value) Then
        Return True
        Return False
    End If
End Function

As you can see, we use regular expression matching to check our stripped card number value against the pattern. A true or false is returned that the FindIndex function uses to determine if the matching pattern has been found. If the pattern is found, the value is set to the matching enum while it is not, a -1 is returned which matches the invalid enum value.

Now, if we don’t have a match, we return with at this point. If there is a matching pattern, we move on to the Luhn algorithm to test this value further.

    Dim Digits As Char() = _cardNumber.ToCharArray
    _cardNumber = String.Empty
    Dim Digit As Integer
    Dim Sum As Integer = 0
    Dim Alt As Boolean = False
    For Each Value As Char In Digits
        Digit = Integer.Parse(Value)
        If Alt Then
            Digit *= 2
            If Digit > 9 Then
                Digit -= 9
            End If
        End If
        Sum += Digit
        Alt = Not Alt
    _cardNumber = String.Empty
    If Sum Mod 10 = 0 Then
        Return CardType
        Return CreditCardTypes.Invalid
    End If
End Function

First, we convert our card number string to a character array and initialize our variables and clear out our working variable. Next, we reverse the array. This allows us to use a cleaner For Each method to loop through the array rather than working through it backwards using a counter variable.

Now, we apply the Luhn algorithm to each digit in the array by convert it from a char to an integer and applying the logic to it. After the loop we check the Mod of the Sum and either pass back the card type on True or that it’s an invalid card if False.

That’s all there is to the class, let’s take a look at how it might be called in a button click:

Private Sub btnProcessOrder_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnProcessOrder.Click
    Dim CardType As CreditCard.CreditCardTypes = CreditCard.Validate(txtCreditCardNumber.Text)
    If CardType = CreditCard.CreditCardTypes.Invalid Then
        lblStatus.Text = "Not a valid credit card number"
        lblStatus.Text = String.Concat("Valid ", [Enum].GetName(GetType(CreditCard.CreditCardTypes), CardType), " Credit Card")
    End If
End Sub

Notice that we’re using the [Enum].GetName function to get the text value for our returned enum value.

You can download the code for this example here

Adding to It

There are a number of ways to add to this class. First, it’s implemented as a shared function library. You might want to flesh it out to a full credit card class that would include making calls to a processing service and providing other functionality. Also, you may want to consider some changes to make it thread safe or you might want to add secure string functionality to it. You can also add additional cards or more checking for various card types like I mentioned about the Visa card. Remember this is just a basic example so if you use it you’ll want to adapt it to your situation.

Let me know if you found this example helpful or if I made any mistakes in it or if you have any other observations or questions by leaving me a comment.

Share This Article: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • Reddit
  • StumbleUpon
  • Technorati
  • DotNetKicks
  • DZone

Entry Filed under: Code Examples

Rate This Article:

Not That GoodCould Be BetterOKGoodGreat (6 votes, average: 3.83 out of 5)
Loading ... Loading ...

5 Comments Add your own

  • 1. Validación de números d&hellip  |  December 20th, 2007 at 3:53 pm

    [...] En esta página hay unas clases muy buenas para su manejo: How To Do Credit Card Validation in VB.NET [...]

  • 2. Rajkumar  |  January 31st, 2008 at 6:13 am

    I am having error in following code
    Private Shared CreditCardPatterns As New List(Of String) _
    (New String() { _
    “^(4d{12})|(4d{15})$”, _
    “^5[1-5]d{14}$”, _
    “(^(6011)d{12}$)|(^(65)d{14}$)”, _

    “List is not declared” error. Please help me

  • 3. Nir  |  February 4th, 2008 at 7:06 am

    Thanks for the info.
    Do you know how does a Visa with 13 digits looks like xxxx-xxxx-xxxx-x
    how it displays the dashes?

  • 4. buy beats  |  February 12th, 2008 at 11:25 pm

    Thanks for the info. I’ve been trying to find this for a while.

  • 5. maxamed  |  April 9th, 2008 at 1:41 am

    iwnt to help me in credit card

Leave a Comment


Required, hidden

Some HTML allowed:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Trackback this post  |  Subscribe to the comments via RSS Feed

Visit Me At My New Site, Programming In C#

Most Popular Articles

Highest Rated Articles


Most Recent Articles


 Subscribe in a reader

To subscribe by e-mail
Enter your address here

Delivered by FeedBurner

VB Opportunities