Should I use Microsoft's CreditCardAttribute to validate credit card numbers like so?
[Required, CreditCard]
public string CreditCardNumber { get; set; }
Or should I let the payment gateway handle it, or do something else? I ask this after discovering some customers have been unable to submit payment with their credit card information. Fortunately, I was able to work with one of these customers, and found that their Visa card was processed without a problem after removing the CreditCardAttribute
.
In part, this question is rhetorical, but I would like to benefit from other developer's thoughts and experiences, and make other developers aware of the risks of using the CreditCardAttribute
by asking the question.
I think the best way to find this out is to simply test it:
using System;
using System.Linq;
using System.Text;
using System.IO;
namespace SO
{
class Program
{
static void Main(string[] args)
{
string[] cards = new string[] {
//http://www.paypalobjects.com/en_US/vhelp/paypalmanager_help/credit_card_numbers.htm
"378282246310005", // American Express
"4012888888881881", // Visa
"6011111111111117", // Discover
"4222222222222", // Visa
"76009244561", // Dankort (PBS)
"5019717010103742", // Dakort (PBS)
"6331101999990016", // Switch/Solo (Paymentech)
"30569309025904", // Diners Club
//http://www.getcreditcardnumbers.com/
"5147004213414803", // Mastercard
"6011491706918120", // Discover
"379616680189541", // American Express
"4916111026621797", // Visa
};
foreach (string card in cards)
{
Console.WriteLine(IsValid(card));
}
Console.ReadLine();
}
public static bool IsValid(object value)
{
if (value == null)
{
return true;
}
string ccValue = value as string;
if (ccValue == null)
{
return false;
}
ccValue = ccValue.Replace("-", "");
ccValue = ccValue.Replace(" ", "");
int checksum = 0;
bool evenDigit = false;
// http://www.beachnet.com/~hstiles/cardtype.html
foreach (char digit in ccValue.Reverse())
{
if (digit < '0' || digit > '9')
{
return false;
}
int digitValue = (digit - '0') * (evenDigit ? 2 : 1);
evenDigit = !evenDigit;
while (digitValue > 0)
{
checksum += digitValue % 10;
digitValue /= 10;
}
}
return (checksum % 10) == 0;
}
}
}
The IsValid method is from the original C# CreditCardAttribute class. 1 out of the 12 numbers failed:
True
True
True
True
False //"76009244561", // Dankort (PBS)
True
True
True
True
True
True
True
So, should you use it? No, obviously it doesn't detect all numbers. Although you can take their code and improve it!