Created
August 23, 2024 14:36
-
-
Save brasizza/549a162bb0ffaafdaa7fa5cedfc96e27 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Supported card types | |
enum CreditCardType { | |
visa, | |
amex, | |
discover, | |
mastercard, | |
dinersclub, | |
jcb, | |
unionpay, | |
maestro, | |
elo, | |
mir, | |
hiper, | |
hipercard, | |
unknown, | |
} | |
const Map<CreditCardType, Set<List<String>>> cardNumPatterns = { | |
CreditCardType.visa: { | |
['4'], | |
}, | |
CreditCardType.amex: { | |
['34'], | |
['37'], | |
}, | |
CreditCardType.discover: { | |
['6011'], | |
['644', '649'], | |
['65'], | |
}, | |
CreditCardType.mastercard: { | |
['51', '55'], | |
['2221', '2229'], | |
['223', '229'], | |
['23', '26'], | |
['270', '271'], | |
['2720'], | |
}, | |
CreditCardType.dinersclub: { | |
['300', '305'], | |
['36'], | |
['38'], | |
['39'], | |
}, | |
CreditCardType.jcb: { | |
['3528', '3589'], | |
['2131'], | |
['1800'], | |
}, | |
CreditCardType.unionpay: { | |
['620'], | |
['624', '626'], | |
['62100', '62182'], | |
['62184', '62187'], | |
['62185', '62197'], | |
['62200', '62205'], | |
['622010', '622999'], | |
['622018'], | |
['622019', '622999'], | |
['62207', '62209'], | |
['622126', '622925'], | |
['623', '626'], | |
['6270'], | |
['6272'], | |
['6276'], | |
['627700', '627779'], | |
['627781', '627799'], | |
['6282', '6289'], | |
['6291'], | |
['6292'], | |
['810'], | |
['8110', '8131'], | |
['8132', '8151'], | |
['8152', '8163'], | |
['8164', '8171'], | |
}, | |
CreditCardType.maestro: { | |
['493698'], | |
['500000', '506698'], | |
['506779', '508999'], | |
['56', '59'], | |
['63'], | |
['67'], | |
}, | |
CreditCardType.elo: { | |
['401178'], | |
['401179'], | |
['438935'], | |
['457631'], | |
['457632'], | |
['431274'], | |
['451416'], | |
['457393'], | |
['504175'], | |
['506699', '506778'], | |
['509000', '509999'], | |
['627780'], | |
['636297'], | |
['636368'], | |
['650031', '650033'], | |
['650035', '650051'], | |
['650405', '650439'], | |
['650485', '650538'], | |
['650541', '650598'], | |
['650700', '650718'], | |
['650720', '650727'], | |
['650901', '650978'], | |
['651652', '651679'], | |
['655000', '655019'], | |
['655021', '655058'], | |
}, | |
CreditCardType.mir: { | |
['2200', '2204'], | |
}, | |
CreditCardType.hiper: { | |
['637095'], | |
['637568'], | |
['637599'], | |
['637609'], | |
['637612'], | |
['63743358'], | |
['63737423'], | |
}, | |
CreditCardType.hipercard: { | |
['606282'], | |
} | |
}; | |
/// Finds non numeric characters | |
RegExp _nonNumeric = RegExp(r'\D+'); | |
/// Finds whitespace in any form | |
RegExp _whiteSpace = RegExp(r'\s+\b|\b\s'); | |
/// This function determines the CC type based on the cardPatterns | |
CreditCardType detectCCType(String ccNumStr) { | |
CreditCardType cardType = CreditCardType.unknown; | |
ccNumStr = ccNumStr.replaceAll(_whiteSpace, ''); | |
if (ccNumStr.isEmpty) { | |
return cardType; | |
} | |
// Check that only numerics are in the string | |
if (_nonNumeric.hasMatch(ccNumStr)) { | |
return cardType; | |
} | |
cardNumPatterns.forEach( | |
(CreditCardType type, Set<List<String>> patterns) { | |
for (List<String> patternRange in patterns) { | |
// Remove any spaces | |
String ccPatternStr = ccNumStr; | |
int rangeLen = patternRange[0].length; | |
// Trim the CC number str to match the pattern prefix length | |
if (rangeLen < ccNumStr.length) { | |
ccPatternStr = ccPatternStr.substring(0, rangeLen); | |
} | |
if (patternRange.length > 1) { | |
// Convert the prefix range into numbers then make sure the | |
// CC num is in the pattern range. | |
// Because Strings don't have '>=' type operators | |
int ccPrefixAsInt = int.parse(ccPatternStr); | |
int startPatternPrefixAsInt = int.parse(patternRange[0]); | |
int endPatternPrefixAsInt = int.parse(patternRange[1]); | |
if (ccPrefixAsInt >= startPatternPrefixAsInt && | |
ccPrefixAsInt <= endPatternPrefixAsInt) { | |
// Found a match | |
cardType = type; | |
break; | |
} | |
} else { | |
// Just compare the single pattern prefix with the CC prefix | |
if (ccPatternStr == patternRange[0]) { | |
// Found a match | |
cardType = type; | |
break; | |
} | |
} | |
} | |
}, | |
); | |
return cardType; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment