The credit card mod 10 validation algorithm is quite straightforward. Easy enough for me to have a go at writing with LINQ. This example is written as an extension method validator. Let me know if you can make this even more concise.
public ValidationProperty IsCreditCard() { value.Label(label).IsNumeric().WithLengthRange(13.To(18)); var numbers = value.Trim().Reverse().Select(c => int.Parse(c.ToString())); int oddSum = numbers.AtOddPositions().Sum(); int doubleEvenSum = numbers.AtEvenPositions().SelectMany(i => new int[] { (i * 2) % 10, (i * 2) / 10 }).Sum(); if ((oddSum + doubleEvenSum) % 10 != 0) { throw new ValidationException("{0} is not a valid credit card number".With(label)); } return this; }
Here are the AtOddPositions and AtEvenPositions extension methods:
public static IEnumerable<T> AtOddPositions<T>(this IEnumerable<T> list) { bool odd = false; // 0th position is even foreach (T item in list) { odd = !odd; if (odd) { yield return item; } } } public static IEnumerable<T> AtEvenPositions<T>(this IEnumerable<T> list) { bool even = true; // 0th position is even foreach (T item in list) { even = !even; if (even) { yield return item; } } }
Am I going extension method crazy??
Here's another implementation.
ReplyDelete