How To Do Credit Card Validation in VB.NET
September 20th, 2007
When 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
Visa
Mastercard
Discover
Amex
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() { _
"^(4d{12})|(4d{15})$", _
"^5[1-5]d{14}$", _
"(^(6011)d{12}$)|(^(65)d{14}$)", _
"^3[47]d{13}$"})
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
Else
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
Array.Reverse(Digits)
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
Next
_cardNumber = String.Empty
If Sum Mod 10 = 0 Then
Return CardType
Else
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"
Else
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.
Entry Filed under: Code Examples
Rate This Article:












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}$)”, _
“^3[47]d{13}$”})
“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
Some HTML allowed:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>
Trackback this post | Subscribe to the comments via RSS Feed