1 /** 2 * Copyright © DiamondMVC 2019 3 * License: MIT (https://github.com/DiamondMVC/Diamond/blob/master/LICENSE) 4 * Author: Jacob Jensen (bausshf) 5 */ 6 module diamond.security.validation.creditcard; 7 8 /** 9 * Validates a credit-card number using luhn's algorithm. 10 * Params: 11 * creditCardNumber = The number of the credit card. 12 * allowedDigits = The allowed length of digits. If it's null it allows credit card numbers to be any length. 13 * Returns: 14 * True if the credit card number is valid according to the allowed digits and luhn's algorithm, false otherwise. 15 */ 16 bool isValidCreditCard(string creditCardNumber, size_t[] allowedDigits = null) 17 { 18 import std.conv : to; 19 import std.algorithm : map, canFind; 20 21 import diamond.errors.checks; 22 23 import diamond.security.validation.types : isValidNumber; 24 25 enforce(creditCardNumber && creditCardNumber.length, "A credit card number must be specified."); 26 enforce(isValidNumber(creditCardNumber), "The credit card number must be numeric"); 27 28 if (allowedDigits) 29 { 30 if (!allowedDigits.canFind(creditCardNumber.length)) 31 { 32 return false; 33 } 34 } 35 36 size_t sum; 37 38 foreach (digit; creditCardNumber.map!(d => to!string(d))) 39 { 40 auto value = to!size_t(digit); 41 42 if (value % 2 == 0) 43 { 44 value *= 2; 45 46 if (value > 9) 47 { 48 value = 1 + (value % 10); 49 } 50 } 51 52 sum += value; 53 } 54 55 return (sum % 10) == 0; 56 }