cardSchemeFromNumber function

CardScheme cardSchemeFromNumber(
  1. String cardNumber
)

Detects card scheme from the first digits of cardNumber. cardNumber can contain spaces; only digits are used.

Implementation

CardScheme cardSchemeFromNumber(String cardNumber) {
  final digits = cardNumber.replaceAll(RegExp(r'\D'), '');
  if (digits.isEmpty) return CardScheme.unknown;
  if (digits.length < 2) {
    if (digits == '4') return CardScheme.visa;
    if (digits == '5' || digits == '6' || digits == '3') return CardScheme.unknown;
    return CardScheme.unknown;
  }

  final first = digits[0];
  final firstTwo = digits.length >= 2 ? digits.substring(0, 2) : '';
  final firstFour = digits.length >= 4 ? digits.substring(0, 4) : '';
  final firstSix = digits.length >= 6 ? int.tryParse(digits.substring(0, 6)) : null;

  // Visa: starts with 4
  if (first == '4') return CardScheme.visa;

  // American Express: 34 or 37
  if (firstTwo == '34' || firstTwo == '37') return CardScheme.amex;

  // Mastercard: 51-55, 2221-2720
  if (first == '5') {
    final two = int.tryParse(firstTwo);
    if (two != null && two >= 51 && two <= 55) return CardScheme.mastercard;
  }
  if (firstFour.isNotEmpty && digits.length >= 4) {
    final n = int.tryParse(firstFour);
    if (n != null && n >= 2221 && n <= 2720) return CardScheme.mastercard;
  }

  // Discover: 6011, 644-649, 65
  if (firstFour == '6011') return CardScheme.discover;
  if (digits.length >= 3) {
    final n = int.tryParse(digits.substring(0, 3));
    if (n != null && n >= 644 && n <= 649) return CardScheme.discover;
  }
  if (firstTwo == '65') return CardScheme.discover;

  // JCB: 3528-3589
  if (firstSix != null && firstSix >= 3528 && firstSix <= 3589) return CardScheme.jcb;

  // Diners Club: 36, 38, 300-305
  if (firstTwo == '36' || firstTwo == '38') return CardScheme.diners;
  if (digits.length >= 3) {
    final n = int.tryParse(digits.substring(0, 3));
    if (n != null && n >= 300 && n <= 305) return CardScheme.diners;
  }

  // Maestro: 5018, 5020, 5038, 5893, 6304, 6759, 6761, 6762, 6763
  const maestroPrefixes = ['5018', '5020', '5038', '5893', '6304', '6759', '6761', '6762', '6763'];
  if (firstFour.length == 4 && maestroPrefixes.contains(firstFour)) return CardScheme.maestro;

  return CardScheme.unknown;
}