Skip to content

Instantly share code, notes, and snippets.

@bjcull
Created November 4, 2010 03:04
Show Gist options
  • Save bjcull/662078 to your computer and use it in GitHub Desktop.
Save bjcull/662078 to your computer and use it in GitHub Desktop.
Credit Card Validator Attribute for ASP.NET MVC 3
/// ASP.NET MVC 3 Credit Card Validator Attribute
/// by Ben Cull - 4 November 2010
///
/// With special thanks to:
/// Thomas @ Orb of Knowledge - http://orb-of-knowledge.blogspot.com/2009/08/extremely-fast-luhn-function-for-c.html
/// For the Extremely fast Luhn algorithm implementation
///
/// And Paul Ingles - http://www.codeproject.com/KB/validation/creditcardvalidator.aspx
/// For a timeless blog post on credit card validation
public class CreditCardAttribute : ValidationAttribute
{
private CardType _cardTypes;
public CardType AcceptedCardTypes
{
get { return _cardTypes; }
set { _cardTypes = value; }
}
public CreditCardAttribute()
{
_cardTypes = CardType.All;
}
public CreditCardAttribute(CardType AcceptedCardTypes)
{
_cardTypes = AcceptedCardTypes;
}
public override bool IsValid(object value)
{
var number = Convert.ToString(value);
if (String.IsNullOrEmpty(number))
return true;
return IsValidType(number, _cardTypes) && IsValidNumber(number);
}
public override string FormatErrorMessage(string name)
{
return "The " + name + " field contains an invalid credit card number.";
}
public enum CardType
{
Unknown = 1,
Visa = 2,
MasterCard = 4,
Amex = 8,
Diners = 16,
All = CardType.Visa | CardType.MasterCard | CardType.Amex | CardType.Diners,
AllOrUnknown = CardType.Unknown | CardType.Visa | CardType.MasterCard | CardType.Amex | CardType.Diners
}
private bool IsValidType(string cardNumber, CardType cardType)
{
// Visa
if (Regex.IsMatch(cardNumber, "^(4)")
&& ((cardType & CardType.Visa) != 0))
return cardNumber.Length == 13 || cardNumber.Length == 16;
// MasterCard
if (Regex.IsMatch(cardNumber, "^(51|52|53|54|55)")
&& ((cardType & CardType.MasterCard) != 0))
return cardNumber.Length == 16;
// Amex
if (Regex.IsMatch(cardNumber, "^(34|37)")
&& ((cardType & CardType.Amex) != 0))
return cardNumber.Length == 15;
// Diners
if (Regex.IsMatch(cardNumber, "^(300|301|302|303|304|305|36|38)")
&& ((cardType & CardType.Diners) != 0))
return cardNumber.Length == 14;
//Unknown
if ((cardType & CardType.Unknown) != 0)
return true;
return false;
}
private bool IsValidNumber(string number)
{
int[] DELTAS = new int[] { 0, 1, 2, 3, 4, -4, -3, -2, -1, 0 };
int checksum = 0;
char[] chars = number.ToCharArray();
for (int i = chars.Length - 1; i > -1; i--)
{
int j = ((int)chars[i]) - 48;
checksum += j;
if (((i - chars.Length) % 2) == 0)
checksum += DELTAS[j];
}
return ((checksum % 10) == 0);
}
}
@bjcull
Copy link
Author

bjcull commented Nov 16, 2010

Just added a check to make sure empty values wont fail validation. A required attribute should be used to check for that.

@ruan00151
Copy link

Muito bom aprovado

@polkamraju
Copy link

The Master card validation is nor working for failing for Valid Numbers: 5114496353984312, 5114496353984312.
The VISA card Validation is also failing for Valid Numbers: 4155279860457, 4155279860457, 4155279860457201.

Please recheck the code once again.

Or send valid Master Card and VISA card numbers with which this code is working.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment