Validating credit card numbers
Do your
applications collect credit card information? If so, you eventually have to do something with it. How do you know if the number the user has typed in is a valid number? One way, of course is to submit it for payment, but not everywhere you put a credit card number are you intending to pay something right at that moment.
It turns out that the digits on credit card numbers, while they look random, are not. The numbers are built so you can do some simple math on them and verify that you have a correctly-input number. Or, at least a valid one...there's no way to know if it's the right one without submitting it.
The math is actually quite simple. Here's how it works:
To verify a credit card number, start with the rightmost digit and multiply it by 1. Take the next digit and multiply it by 2. Take the third digit and multiply it by 1 again. Repeat the process all the way along the number from right to left multiplying them alternatively by 1 and 2.
So, let's say you've entered the number 1234-5678-9012-3456 on my web site. I multiply 6 x 1, 5 x 2, 4 x 1, and so on, ending up with this list of numbers:
6 10 4 6 2 2 0 18 8 14 6 10 4 6 2 2
Now, take all the digits of all these products and add them up. In other words, if you have a two-digit number like 12, add the digits: 1 + 2. For my example here, the math would be:
6 + 1 + 0 + 4 + 6 + 2 + 2 + 0 + 1 + 8 + 8 + 14 + 6 + 1 + 0 + 4 + 6 + 2 + 2 = 73
If the sum of all the digits of all the products is a number that ends in zero (10, 20, 30, 40, etc.), then that's a valid number. Since mine ends in 3, it's invalid.
Checking numbers like this is reasonably straightforward. In LotusScript, you'd do something like this:
Dim s As New NotesSession
Dim db As NotesDatabase
Dim w As New NotesUIWorkspace
Dim uidoc As NotesUIDocument
Dim doc As NotesDocument
Set db = s.CurrentDatabase
Set uidoc = w.CurrentDocument
Set doc = uidoc.Document
CardNumber = doc.AccountNumber(0)
multiplier = 1
sum = 0
For i = Len(CardNumber) To 1 Step -1
char = Mid(CardNumber, i, 1)
If char Like "*[0-9]*" Then
product = Cint(char) * multiplier
If product > 9 Then
sum = sum + ((product - (product Mod 10)) / 10) + (product Mod 10)
Else
sum = sum + product
End If
multiplier = 3 - multiplier
End If
Next
If (sum Mod 10) <> 0 Then
Messagebox("The account number you have entered is invalid. Please try again.")
Else
Messagebox("The account number is OK.")
End If
This assumes you have a field on your form called AccountNumber which you're trying to check. In the code are a few things you may not be familiar with. First, you can use negative step values in For loops:
For i = Len(CardNumber) To 1 Step -1
What's that doing? Well, Len(CardNumber) is the number of characters in the card number. You can't hard-code the number length. American Express cards have 15 character, Visa have 16. Plus, you don't know how they typed it in. Did they leave out all the spaces or put hyphens in like I did in my example number? The length varies, so you have to figure it out and start at the right end.
Most of the time you write For statements they don't have the "Step" word at the end of them. Usually, they look like this:
For i = 1 To 10
Next
By not specifying a Step, the For loop automatically steps by +1 each time. But it doesn't have to. If you say "Step 2," i will be 1 then 3 then 5 then 7 then 9, and then quit. If you say "Step 5" it will be 1, then 6, then quit. And, finally, if you use a negative number as is being used in the formula above, it will step backward by however large an increment you've specified.
So, "Step -1" is how you get it to increment through the numbers from right to left.
Immediately after the For is this:
char = Mid(CardNumber, i, 1)
That extracts the character at position "i." Simple enough. But then there's something else interesting:
If char Like "*[0-9]*" Then
This is doing pattern searching. The asterisks indicate I don't care what's before or after the number in question. The "[0-9]" part says I'm only looking for the digits between zero and 9; nothing else. In this way, the code can ignore any separators I may have put into the number. In essence, it doesn't care which of these ways I entered the number:
1234-5678-9012-3456
1234567890123456
1234 5678 9012 3456
1234/5678/9012/3456
1234/abcdef/5678/ghijkl/9012/mnopq/3456
Any of them will work because it's only doing math on the numerical digits. (Yes, you could argue that's really not a good test because you have have such weird numbers. I sharing ideas here...work it out to your satisfaction.)
The last little bit of interest is this:
If product > 9 Then
sum = sum + ((product - (product Mod 10)) / 10) + (product Mod 10)
Else...
Do you know "Mod"? No? It's a useful little function. Mod gives you the remainder of a division formula. In other words...
18 Mod 10 = 8
8 is the remainder of the division formula 18/10. You can get one 10 out of 18, leaving 8. Remember that what we're trying to do here is add up the digits of the number. The digits for the number 18, for instance should be added as 1 + 8 = 9, then added to the prior sum. That's what's going on in the Mod formula:
((product - (product Mod 10)) / 10) + (product Mod 10)
((18 - (18 Mod 10)) / 10 + (18 Mod 10)
((18 - (8)) / 10 + (8)
(10 / 10) + 8
1 + 8 = 9
Mod is used again in the final If statement to check to see if the final result is a good or bad credit card number:
If (sum Mod 10) <> 0 Then...
If there is a remainder of any kind, this isn't a number divisible by 10 and, therefore, isn't a valid credit card number.
Who knew there was math in those numbers? Not me!

























