关于算法:如何根据号码检测信用卡类型?

How do you detect Credit card type based on number?

我正试图弄清楚如何纯粹根据信用卡的号码来检测它的类型。有人知道一个确定的,可靠的方法来找到这个吗?


信用卡/借记卡号码称为PAN或主帐号。PAN的前六位数字取自开证行的IIN或发卡行识别号(IIN以前称为银行识别号,因此在某些文档中可能会看到对该术语的引用)。这六位数字符合国际标准ISO/IEC 7812,可用于根据数字确定卡的类型。

不幸的是,实际的ISO/IEC 7812数据库并不公开,但是,有一些非官方的列表,包括在维基百科上的商业和免费列表。

无论如何,要从数字中检测类型,您可以使用下面的正则表达式:对原始表达式的引用

VISA:^4[0-9]{6,}$VISA卡号以4开头。

万事达卡:2016年之前,万事达卡号码从51到55开始,但这只会检测万事达卡信用卡;使用万事达卡系统发行的其他卡不属于此IIN范围。2016年,他们将增加范围内的数字(222100-272099)。

美国运通:^3[47][0-9]{5,}$美国运通卡号以34或37开头。

用餐者俱乐部:^3(?:0[0-5]|[68][0-9])[0-9]{4,}$用餐者俱乐部卡号从300到305、36或38开始。用餐者俱乐部卡以5开头,16位数字。这是一个餐厅俱乐部和万事达卡的合资企业,应该像万事达卡一样处理。

发现:^6(?:011|5[0-9]{2})[0-9]{3,}$发现卡号以6011或65开头。

JCB:^(?:2131|1800|35[0-9]{3})[0-9]{3,}$JCB卡从2131、1800或35开始。

不幸的是,有许多用万事达卡系统处理的卡类型不在万事达卡的IIN范围内(数字从51…55开始);最重要的情况是Maestro卡,其中许多卡是从其他银行的IIN范围发行的,因此它们遍布数字空间。因此,最好假设任何不是您接受的其他类型的卡都必须是万事达卡。

重要提示:卡号的长度确实不同;例如,VISA过去发行过13位盘的卡号和16位盘的卡号。目前,Visa的文件表明,它可能发行或可能发行了12到19位数字之间的数字。因此,您不应检查卡号的长度,除非验证它至少有7位(对于完整的IIN加上一个校验位,该校验位应与luhn算法预测的值匹配)。

另一个提示:在处理持卡人的PAN之前,从输入中删除任何空格和标点符号。为什么?因为分组输入数字通常要容易得多,类似于在实际信用卡前面显示数字的方式,即

1
4444 4444 4444 4444

正确进入要比

1
4444444444444444

惩罚用户真的没有好处,因为他们输入了你不希望在这里看到的字符。

这还意味着确保您的输入字段至少有24个字符的空间,否则输入空间的用户将耗尽空间。我建议您使字段足够宽以显示32个字符,并允许最多64个字符;这样可以为扩展留出足够的空间。

下面是一个能提供更多洞察力的图像:

更新(2014年):校验和方法不再是验证卡的真实性的有效方法,如本答案注释中所述。

更新(2016年):万事达卡将实施新的银行标识代码范围,开始每小时支付一次。

Credit Card Verification


JavaScript的:P></

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function detectCardType(number) {
    var re = {
        electron: /^(4026|417500|4405|4508|4844|4913|4917)\d+$/,
        maestro: /^(5018|5020|5038|5612|5893|6304|6759|6761|6762|6763|0604|6390)\d+$/,
        dankort: /^(5019)\d+$/,
        interpayment: /^(636)\d+$/,
        unionpay: /^(62|88)\d+$/,
        visa: /^4[0-9]{12}(?:[0-9]{3})?$/,
        mastercard: /^5[1-5][0-9]{14}$/,
        amex: /^3[47][0-9]{13}$/,
        diners: /^3(?:0[0-5]|[68][0-9])[0-9]{11}$/,
        discover: /^6(?:011|5[0-9]{2})[0-9]{12}$/,
        jcb: /^(?:2131|1800|35\d{3})\d{11}$/
    }

    for(var key in re) {
        if(re[key].test(number)) {
            return key
        }
    }
}

单元测试:P></

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
describe('CreditCard', function() {
    describe('#detectCardType', function() {

        var cards = {
            '8800000000000000': 'UNIONPAY',

            '4026000000000000': 'ELECTRON',
            '4175000000000000': 'ELECTRON',
            '4405000000000000': 'ELECTRON',
            '4508000000000000': 'ELECTRON',
            '4844000000000000': 'ELECTRON',
            '4913000000000000': 'ELECTRON',
            '4917000000000000': 'ELECTRON',

            '5019000000000000': 'DANKORT',

            '5018000000000000': 'MAESTRO',
            '5020000000000000': 'MAESTRO',
            '5038000000000000': 'MAESTRO',
            '5612000000000000': 'MAESTRO',
            '5893000000000000': 'MAESTRO',
            '6304000000000000': 'MAESTRO',
            '6759000000000000': 'MAESTRO',
            '6761000000000000': 'MAESTRO',
            '6762000000000000': 'MAESTRO',
            '6763000000000000': 'MAESTRO',
            '0604000000000000': 'MAESTRO',
            '6390000000000000': 'MAESTRO',

            '3528000000000000': 'JCB',
            '3589000000000000': 'JCB',
            '3529000000000000': 'JCB',

            '6360000000000000': 'INTERPAYMENT',

            '4916338506082832': 'VISA',
            '4556015886206505': 'VISA',
            '4539048040151731': 'VISA',
            '4024007198964305': 'VISA',
            '4716175187624512': 'VISA',

            '5280934283171080': 'MASTERCARD',
            '5456060454627409': 'MASTERCARD',
            '5331113404316994': 'MASTERCARD',
            '5259474113320034': 'MASTERCARD',
            '5442179619690834': 'MASTERCARD',

            '6011894492395579': 'DISCOVER',
            '6011388644154687': 'DISCOVER',
            '6011880085013612': 'DISCOVER',
            '6011652795433988': 'DISCOVER',
            '6011375973328347': 'DISCOVER',

            '345936346788903': 'AMEX',
            '377669501013152': 'AMEX',
            '373083634595479': 'AMEX',
            '370710819865268': 'AMEX',
            '371095063560404': 'AMEX'
        };

        Object.keys(cards).forEach(function(number) {
            it('should detect card ' + number + ' as ' + cards[number], function() {
                Basket.detectCardType(number).should.equal(cards[number]);
            });
        });
    });
});


最新:2016年六月十五(as an currently终极解决方案)P></

Please笔记,甚至给投票上顶voted is for the one,but to使它清楚的知道这些作品是regexps恩thousands of real仓与测试代码。最重要的是使用strings to start()其他虚假的结果将给它在真正的世界!P></

JCB ^(?:2131|1800|35)[0-9]{0,}$start with:1800(3528,2131,3589 - 35)P></

美国运通:34,37 ^3[47][0-9]{0,}$start withP></

大来俱乐部^3(?:0[0-59]{1}|[689])[0-9]{0,}$start with:300~305—309,36,38,39P></

签证:4 ^4[0-9]{0,}$start withP></

万事达^(5[1-5]|222[1-9]|22[3-9]|2[3-6]|27[01]|2720)[0-9]{0,}$start with:2720 2221 - 51 - 55P></

大师大师总是在成长^(5[06789]|6)[0-9]{0,}$范围:60至69,not something else with /开始启动,but must be as万事达啊5编码。在主卡detected must be the end of the队列因为some of the范围内有人在60 - 69。Please look at the队列。P></

发现很难发现^(6011|65|64[4-9]|62212[6-9]|6221[3-9]|622[2-8]|6229[01]|62292[0-5])[0-9]{0,}$to start with那么队列:6011,622126 - 622925,644~649,65P></

在使用这个JavaScript函数。this is good when u en to an event和assign onkeyup恩给结果尽快possible。P></

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
function cc_brand_id(cur_val) {
  // the regular expressions check for possible matches as you type, hence the OR operators based on the number of chars
  // regexp string length {0} provided for soonest detection of beginning of the card numbers this way it could be used for BIN CODE detection also

  //JCB
  jcb_regex = new RegExp('^(?:2131|1800|35)[0-9]{0,}$'); //2131, 1800, 35 (3528-3589)
  // American Express
  amex_regex = new RegExp('^3[47][0-9]{0,}$'); //34, 37
  // Diners Club
  diners_regex = new RegExp('^3(?:0[0-59]{1}|[689])[0-9]{0,}$'); //300-305, 309, 36, 38-39
  // Visa
  visa_regex = new RegExp('^4[0-9]{0,}$'); //4
  // MasterCard
  mastercard_regex = new RegExp('^(5[1-5]|222[1-9]|22[3-9]|2[3-6]|27[01]|2720)[0-9]{0,}$'); //2221-2720, 51-55
  maestro_regex = new RegExp('^(5[06789]|6)[0-9]{0,}$'); //always growing in the range: 60-69, started with / not something else, but starting 5 must be encoded as mastercard anyway
  //Discover
  discover_regex = new RegExp('^(6011|65|64[4-9]|62212[6-9]|6221[3-9]|622[2-8]|6229[01]|62292[0-5])[0-9]{0,}$');
  ////6011, 622126-622925, 644-649, 65


  // get rid of anything but numbers
  cur_val = cur_val.replace(/\D/g, '');

  // checks per each, as their could be multiple hits
  //fix: ordering matter in detection, otherwise can give false results in rare cases
  var sel_brand ="unknown";
  if (cur_val.match(jcb_regex)) {
    sel_brand ="jcb";
  } else if (cur_val.match(amex_regex)) {
    sel_brand ="amex";
  } else if (cur_val.match(diners_regex)) {
    sel_brand ="diners_club";
  } else if (cur_val.match(visa_regex)) {
    sel_brand ="visa";
  } else if (cur_val.match(mastercard_regex)) {
    sel_brand ="mastercard";
  } else if (cur_val.match(discover_regex)) {
    sel_brand ="discover";
  } else if (cur_val.match(maestro_regex)) {
    if (cur_val[0] == '5') { //started 5 must be mastercard
      sel_brand ="mastercard";
    } else {
      sel_brand ="maestro"; //maestro is all 60-69 which is not something else, thats why this condition in the end
    }
  }

  return sel_brand;
}

你可以用它来播放:P></

http:/ / / / / jsfiddle.net upn3l 69P></

for PHP函数使用this,this detects some Visa卡:MC亚/太P></

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
    /**
 * Obtain a brand constant from a PAN
 *
 * @param type $pan               Credit card number
 * @param type $include_sub_types Include detection of sub visa brands
 * @return string
 */
public static function getCardBrand($pan, $include_sub_types = false)
{
    //maximum length is not fixed now, there are growing number of CCs has more numbers in length, limiting can give false negatives atm

    //these regexps accept not whole cc numbers too
    //visa        
    $visa_regex ="/^4[0-9]{0,}$/";
    $vpreca_regex ="/^428485[0-9]{0,}$/";
    $postepay_regex ="/^(402360|402361|403035|417631|529948){0,}$/";
    $cartasi_regex ="/^(432917|432930|453998)[0-9]{0,}$/";
    $entropay_regex ="/^(406742|410162|431380|459061|533844|522093)[0-9]{0,}$/";
    $o2money_regex ="/^(422793|475743)[0-9]{0,}$/";

    // MasterCard
    $mastercard_regex ="/^(5[1-5]|222[1-9]|22[3-9]|2[3-6]|27[01]|2720)[0-9]{0,}$/";
    $maestro_regex ="/^(5[06789]|6)[0-9]{0,}$/";
    $kukuruza_regex ="/^525477[0-9]{0,}$/";
    $yunacard_regex ="/^541275[0-9]{0,}$/";

    // American Express
    $amex_regex ="/^3[47][0-9]{0,}$/";

    // Diners Club
    $diners_regex ="/^3(?:0[0-59]{1}|[689])[0-9]{0,}$/";

    //Discover
    $discover_regex ="/^(6011|65|64[4-9]|62212[6-9]|6221[3-9]|622[2-8]|6229[01]|62292[0-5])[0-9]{0,}$/";

    //JCB
    $jcb_regex ="/^(?:2131|1800|35)[0-9]{0,}$/";

    //ordering matter in detection, otherwise can give false results in rare cases
    if (preg_match($jcb_regex, $pan)) {
        return"jcb";
    }

    if (preg_match($amex_regex, $pan)) {
        return"amex";
    }

    if (preg_match($diners_regex, $pan)) {
        return"diners_club";
    }

    //sub visa/mastercard cards
    if ($include_sub_types) {
        if (preg_match($vpreca_regex, $pan)) {
            return"v-preca";
        }
        if (preg_match($postepay_regex, $pan)) {
            return"postepay";
        }
        if (preg_match($cartasi_regex, $pan)) {
            return"cartasi";
        }
        if (preg_match($entropay_regex, $pan)) {
            return"entropay";
        }
        if (preg_match($o2money_regex, $pan)) {
            return"o2money";
        }
        if (preg_match($kukuruza_regex, $pan)) {
            return"kukuruza";
        }
        if (preg_match($yunacard_regex, $pan)) {
            return"yunacard";
        }
    }

    if (preg_match($visa_regex, $pan)) {
        return"visa";
    }

    if (preg_match($mastercard_regex, $pan)) {
        return"mastercard";
    }

    if (preg_match($discover_regex, $pan)) {
        return"discover";
    }

    if (preg_match($maestro_regex, $pan)) {
        if ($pan[0] == '5') {//started 5 must be mastercard
            return"mastercard";
        }
            return"maestro"; //maestro is all 60-69 which is not something else, thats why this condition in the end

    }

    return"unknown"; //unknown for this system
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
  public string GetCreditCardType(string CreditCardNumber)
    {
        Regex regVisa = new Regex("^4[0-9]{12}(?:[0-9]{3})?$");
        Regex regMaster = new Regex("^5[1-5][0-9]{14}$");
        Regex regExpress = new Regex("^3[47][0-9]{13}$");
        Regex regDiners = new Regex("^3(?:0[0-5]|[68][0-9])[0-9]{11}$");
        Regex regDiscover = new Regex("^6(?:011|5[0-9]{2})[0-9]{12}$");
        Regex regJCB= new Regex("^(?:2131|1800|35\\d{3})\\d{11}$");


        if(regVisa.IsMatch(CreditCardNumber))
            return"VISA";
       else if (regMaster.IsMatch(CreditCardNumber))
            return"MASTER";
      else  if (regExpress.IsMatch(CreditCardNumber))
            return"AEXPRESS";
       else if (regDiners.IsMatch(CreditCardNumber))
            return"DINERS";
       else if (regDiscover.IsMatch(CreditCardNumber))
            return"DISCOVERS";
       else   if (regJCB.IsMatch(CreditCardNumber))
            return"JCB";
       else
        return"invalid";
    }

here is the function to check型信用卡使用正则表达式,C #P></


看看这个:P></

www.breakingpar.com http:/ / / / / / 0 87256b280015193f87256cc70060a01b BKP home.nsfP></

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
function isValidCreditCard(type, ccnum) {
/* Visa: length 16, prefix 4, dashes optional.
Mastercard: length 16, prefix 51-55, dashes optional.
Discover: length 16, prefix 6011, dashes optional.
American Express: length 15, prefix 34 or 37.
Diners: length 14, prefix 30, 36, or 38. */

  var re = new Regex({"visa":"/^4\d{3}-?\d{4}-?\d{4}-?\d",
                      "mc":"/^5[1-5]\d{2}-?\d{4}-?\d{4}-?\d{4}$/",
                      "disc":"/^6011-?\d{4}-?\d{4}-?\d{4}$/",
                      "amex":"/^3[47]\d{13}$/",
                      "diners":"/^3[068]\d{12}$/"}[type.toLowerCase()])

   if (!re.test(ccnum)) return false;
   // Remove all dashes for the checksum checks to eliminate negative numbers
   ccnum = ccnum.split("-").join("");
   // Checksum ("Mod 10")
   // Add even digits in even length strings or odd digits in odd length strings.
   var checksum = 0;
   for (var i=(2-(ccnum.length % 2)); i<=ccnum.length; i+=2) {
      checksum += parseInt(ccnum.charAt(i-1));
   }
   // Analyze odd digits in even length strings or even digits in odd length strings.
   for (var i=(ccnum.length % 2) + 1; i<ccnum.length; i+=2) {
      var digit = parseInt(ccnum.charAt(i-1)) * 2;
      if (digit < 10) { checksum += digit; } else { checksum += (digit-9); }
   }
   if ((checksum % 10) == 0) return true; else return false;
}

这里有完整的C或VB代码,用于codeproject上与CC相关的所有类型的事情。

  • ISvalidNumber编号
  • getcardtypefromnumber(从数字开始)
  • getcardtestnumber(getcardtestnumber)
  • 通过测试
  • 小精灵

    这篇文章已经发表了几年,没有任何负面评论。


    我需要这样的功能性recently porting Zend框架,为信用卡验证器的红宝石。宝石:红宝石github.com HTTPS:/ / /信用卡fivell _ _ validationsZend框架:HTTPS:/ / / / / github.com zendframework zf2 BLOB /硕士/图书馆/ / / creditcard.php Zend验证器P></

    他们都使用酒店提供的探测靶道型。在这里你可以阅读关于酒店P></

    你可以根据这个信用卡(没有regexps alternatively探明,但declaring some rules and possible prefixes length about)P></

    我知道我们有一个规则卡used for mostP></

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    ########  most used brands #########

        visa: [
            {length: [13, 16], prefixes: ['4']}
        ],
        mastercard: [
            {length: [16], prefixes: ['51', '52', '53', '54', '55']}
        ],

        amex: [
            {length: [15], prefixes: ['34', '37']}
        ],
        ######## other brands ########
        diners: [
            {length: [14], prefixes: ['300', '301', '302', '303', '304', '305', '36', '38']},
        ],

        #There are Diners Club (North America) cards that begin with 5. These are a joint venture between Diners Club and MasterCard, and are processed like a MasterCard
        # will be removed in next major version

        diners_us: [
            {length: [16], prefixes: ['54', '55']}
        ],

        discover: [
            {length: [16], prefixes: ['6011', '644', '645', '646', '647', '648',
                                      '649', '65']}
        ],

        jcb: [
            {length: [16], prefixes: ['3528', '3529', '353', '354', '355', '356', '357', '358', '1800', '2131']}
        ],


        laser: [
            {length: [16, 17, 18, 19], prefixes: ['6304', '6706', '6771']}
        ],

        solo: [
            {length: [16, 18, 19], prefixes: ['6334', '6767']}
        ],

        switch: [
            {length: [16, 18, 19], prefixes: ['633110', '633312', '633304', '633303', '633301', '633300']}

        ],

        maestro: [
            {length: [12, 13, 14, 15, 16, 17, 18, 19], prefixes: ['5010', '5011', '5012', '5013', '5014', '5015', '5016', '5017', '5018',
                                                                  '502', '503', '504', '505', '506', '507', '508',
                                                                  '6012', '6013', '6014', '6015', '6016', '6017', '6018', '6019',
                                                                  '602', '603', '604', '605', '6060',
                                                                  '677', '675', '674', '673', '672', '671', '670',
                                                                  '6760', '6761', '6762', '6763', '6764', '6765', '6766', '6768', '6769']}
        ],

        # Luhn validation are skipped for union pay cards because they have unknown generation algoritm
        unionpay: [
            {length: [16, 17, 18, 19], prefixes: ['622', '624', '625', '626', '628'], skip_luhn: true}
        ],

        dankrot: [
            {length: [16], prefixes: ['5019']}
        ],

        rupay: [
            {length: [16], prefixes: ['6061', '6062', '6063', '6064', '6065', '6066', '6067', '6068', '6069', '607', '608'], skip_luhn: true}
        ]

    }

    模式搜索前缀长度,那么你可以探明和?比较信用卡品牌。也不要忘记luhn算法(en is about here描述http:////luhn维基百科en.wikipedia.org)。P></


    紧凑的JavaScript版本P></

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
        var getCardType = function (number) {
            var cards = {
                visa: /^4[0-9]{12}(?:[0-9]{3})?$/,
                mastercard: /^5[1-5][0-9]{14}$/,
                amex: /^3[47][0-9]{13}$/,
                diners: /^3(?:0[0-5]|[68][0-9])[0-9]{11}$/,
                discover: /^6(?:011|5[0-9]{2})[0-9]{12}$/,
                jcb: /^(?:2131|1800|35\d{3})\d{11}$/
            };
            for (var card in cards) {
                if (cards[card].test(number)) {
                    return card;
                }
            }
        };

    Anatoliy的PHP答案:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
     public static function detectCardType($num)
     {
        $re = array(
           "visa"       =>"/^4[0-9]{12}(?:[0-9]{3})?$/",
           "mastercard" =>"/^5[1-5][0-9]{14}$/",
           "amex"       =>"/^3[47][0-9]{13}$/",
           "discover"   =>"/^6(?:011|5[0-9]{2})[0-9]{12}$/",
        );

        if (preg_match($re['visa'],$num))
        {
            return 'visa';
        }
        else if (preg_match($re['mastercard'],$num))
        {
            return 'mastercard';
        }
        else if (preg_match($re['amex'],$num))
        {
            return 'amex';
        }
        else if (preg_match($re['discover'],$num))
        {
            return 'discover';
        }
        else
        {
            return false;
        }
     }


    这里是PHP函数返回舱ccnumber cctype模式。本代码validates or not not the only luhn算法运行卡信用卡尝试to find this page table中基于型。基本uses ccnumber确定长度和cccard字头的cccard型。P></

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
        <?php class CreditcardType
        {
       public static $creditcardTypes = array(
                array('Name'=>'American Express','cardLength'=>array(15),'cardPrefix'=>array('34', '37'))
                ,array('Name'=>'Maestro','cardLength'=>array(12, 13, 14, 15, 16, 17, 18, 19),'cardPrefix'=>array('5018', '5020', '5038', '6304', '6759', '6761', '6763'))
                ,array('Name'=>'Mastercard','cardLength'=>array(16),'cardPrefix'=>array('51', '52', '53', '54', '55'))
                ,array('Name'=>'Visa','cardLength'=>array(13,16),'cardPrefix'=>array('4'))
                ,array('Name'=>'JCB','cardLength'=>array(16),'cardPrefix'=>array('3528', '3529', '353', '354', '355', '356', '357', '358'))
                ,array('Name'=>'Discover','cardLength'=>array(16),'cardPrefix'=>array('6011', '622126', '622127', '622128', '622129', '62213',
                                            '62214', '62215', '62216', '62217', '62218', '62219',
                                            '6222', '6223', '6224', '6225', '6226', '6227', '6228',
                                            '62290', '62291', '622920', '622921', '622922', '622923',
                                            '622924', '622925', '644', '645', '646', '647', '648',
                                            '649', '65'))
                ,array('Name'=>'Solo','cardLength'=>array(16, 18, 19),'cardPrefix'=>array('6334', '6767'))
                ,array('Name'=>'Unionpay','cardLength'=>array(16, 17, 18, 19),'cardPrefix'=>array('622126', '622127', '622128', '622129', '62213', '62214',
                                            '62215', '62216', '62217', '62218', '62219', '6222', '6223',
                                            '6224', '6225', '6226', '6227', '6228', '62290', '62291',
                                            '622920', '622921', '622922', '622923', '622924', '622925'))
                ,array('Name'=>'Diners Club','cardLength'=>array(14),'cardPrefix'=>array('300', '301', '302', '303', '304', '305', '36'))
                ,array('Name'=>'Diners Club US','cardLength'=>array(16),'cardPrefix'=>array('54', '55'))
                ,array('Name'=>'Diners Club Carte Blanche','cardLength'=>array(14),'cardPrefix'=>array('300','305'))
                ,array('Name'=>'Laser','cardLength'=>array(16, 17, 18, 19),'cardPrefix'=>array('6304', '6706', '6771', '6709'))
        );    
            private function __construct() {}    
            public static function getType($CCNumber)
            {
                $CCNumber= trim($CCNumber);
                $type='Unknown';
                foreach (CreditcardType::$creditcardTypes as $card){
                    if (! in_array(strlen($CCNumber),$card['cardLength'])) {
                        continue;
                    }
                    $prefixes = '/^('.implode('|',$card['cardPrefix']).')/';            
                    if(preg_match($prefixes,$CCNumber) == 1 ){
                        $type= $card['Name'];
                        break;
                    }
                }
                return $type;
            }
        } ?>

    信用卡的第一个号码可用于近似供应商:

    • 签证:49、44或47
    • VISA电子:42、45、48、49
    • 万事达卡:51
    • 美国运通:34
    • 用餐者:30、36、38
    • JCB:35分
    • 小精灵


      试图探明Do not as part of处理信用卡付款的A型。你是risking of declining有效交易。P></

      如果你需要提供你的支付信息(信用卡,贝宝,例如处理器对象的name……to guess the卡型),然后EN from the最小信息可用,例如P></

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      $credit_card['pan'] = preg_replace('/[^0-9]/', '', $credit_card['pan']);
      $inn = (int) mb_substr($credit_card['pan'], 0, 2);

      // @see http://en.wikipedia.org/wiki/List_of_Bank_Identification_Numbers#Overview
      if ($inn >= 40 && $inn <= 49) {
          $type = 'visa';
      } else if ($inn >= 51 && $inn <= 55) {
          $type = 'mastercard';
      } else if ($inn >= 60 && $inn <= 65) {
          $type = 'discover';
      } else if ($inn >= 34 && $inn <= 37) {
          $type = 'amex';
      } else {
          throw new \UnexpectedValueException('Unsupported card type.');
      }

      执行(using the first only this is to两位数)来确定足够的专业和paypal' of the s of the支卡的房屋)的方案。事实上,你可能想跳过默认的数据库altogether & the most to the流行的卡型。支付网关处理器,让告诉你/ if there is a确认误差响应你的请求。P></

      is that the真人does not about你的支付网关提供价值你昂贵的茶。P></


      在卡范围识别(CRR)中,使用一系列regex或其他硬编码范围的算法的一个缺点是,在我的经验中,bin/iins确实会随着时间的推移而改变。卡片的联合品牌化是一个持续的复杂问题。不同的卡收单机构/商户可能需要您根据地理位置等不同对待同一张卡。

      此外,在过去几年中,如银联卡的流通范围更广,现有的模式无法应对新的范围,这些范围有时会与它们取代的范围更广的范围交错。了解您的系统需要覆盖的地理位置可能会有所帮助,因为某些范围仅限于在特定国家使用。例如,范围62包括美国的一些AAA子范围,但如果您的商户基地在美国以外,您可以将所有62个都视为银联。您还可能被要求根据商户位置对卡进行不同的处理。例如,在国内将某些英国卡视为借记卡,但在国际上视为信用卡。

      一家主要的收购银行维护着一套非常有用的规则。例如:https://www.barclaycard.co.uk/business/files/bin-rules-eire.pdf和https://www.barclaycard.co.uk/business/files/bin-rules-uk.pdf。(截至2017年6月的有效链接,感谢提供更新参考链接的用户。)但请注意,尽管这些CRR规则可能代表发卡领域,因为它适用于该实体收购的商户,但不包括例如识别为CUP/UPI的范围。

      这些注释适用于磁条(磁条)或PKE(泛密钥输入)场景。在ICC/EMV世界,情况又不同了。

      更新:这个页面(以及链接的维基百科页面)上的其他答案都有16长的JCB。但是,在我的公司,我们有一个专门的工程师团队,他们在多个收购银行和地区认证我们的POS设备和软件。这个团队从JCB那里得到的最新的认证包,有一个19长的盘的通行证。


      USMAN Y答案的Swift 2.1版本。使用print语句验证某个字符串值的so调用

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      print(self.validateCardType(self.creditCardField.text!))

      func validateCardType(testCard: String) -> String {

          let regVisa ="^4[0-9]{12}(?:[0-9]{3})?$"
          let regMaster ="^5[1-5][0-9]{14}$"
          let regExpress ="^3[47][0-9]{13}$"
          let regDiners ="^3(?:0[0-5]|[68][0-9])[0-9]{11}$"
          let regDiscover ="^6(?:011|5[0-9]{2})[0-9]{12}$"
          let regJCB ="^(?:2131|1800|35\\d{3})\\d{11}$"


          let regVisaTest = NSPredicate(format:"SELF MATCHES %@", regVisa)
          let regMasterTest = NSPredicate(format:"SELF MATCHES %@", regMaster)
          let regExpressTest = NSPredicate(format:"SELF MATCHES %@", regExpress)
          let regDinersTest = NSPredicate(format:"SELF MATCHES %@", regDiners)
          let regDiscoverTest = NSPredicate(format:"SELF MATCHES %@", regDiscover)
          let regJCBTest = NSPredicate(format:"SELF MATCHES %@", regJCB)


          if regVisaTest.evaluateWithObject(testCard){
              return"Visa"
          }
          else if regMasterTest.evaluateWithObject(testCard){
              return"MasterCard"
          }

          else if regExpressTest.evaluateWithObject(testCard){
              return"American Express"
          }

          else if regDinersTest.evaluateWithObject(testCard){
              return"Diners Club"
          }

          else if regDiscoverTest.evaluateWithObject(testCard){
              return"Discover"
          }

          else if regJCBTest.evaluateWithObject(testCard){
              return"JCB"
          }

          return""

      }


      我的解决方案:与jQueryP></

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      function detectCreditCardType() {
          var type = new Array;
          type[1] = '^4[0-9]{12}(?:[0-9]{3})?$';      // visa
          type[2] = '^5[1-5][0-9]{14}$';              // mastercard
          type[3] = '^6(?:011|5[0-9]{2})[0-9]{12}$';  // discover
          type[4] = '^3[47][0-9]{13}$';               // amex

          var ccnum = $('.creditcard').val().replace(/[^\d.]/g, '');
          var returntype = 0;

          $.each(type, function(idx, re) {
              var regex = new RegExp(re);
              if(regex.test(ccnum) && idx>0) {
                  returntype = idx;
              }
          });

          return returntype;
      }

      房子是在0型信用卡undetected returned,is。P></

      "信用卡"级should be added to the输入信用卡领域。P></


      Stripe为卡方案检测提供了这个出色的javascript库。让我添加一些代码片段,并向您展示如何使用它。

      首先将其作为

      1
      <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery.payment/1.2.3/jquery.payment.js">

      其次,使用功能cardtype检测卡方案。

      1
      2
      3
      4
      $(document).ready(function() {              
                  var type = $.payment.cardType("4242 4242 4242 4242"); //test card number
                  console.log(type);                                  
      });

      以下是更多示例和演示的参考链接。

    • jquery.payment.js的条纹博客
    • Github存储库

    • 我到处找了很多关于信用卡格式和电话号码格式的信息。找到了很多很好的提示,但没有什么真正适合我的确切愿望,所以我创建了这段代码。您可以这样使用它:

      1
      2
      var sf = smartForm.formatCC(myInputString);
      var cardType = sf.cardType;


      在swift中,您可以创建一个枚举来检测信用卡类型。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      enum CreditCardType: Int { // Enum which encapsulates different card types and method to find the type of card.

      case Visa
      case Master
      case Amex
      case Discover

      func validationRegex() -> String {
          var regex =""
          switch self {
          case .Visa:
              regex ="^4[0-9]{6,}$"

          case .Master:
              regex ="^5[1-5][0-9]{5,}$"

          case .Amex:
              regex ="^3[47][0-9]{13}$"

          case .Discover:
              regex ="^6(?:011|5[0-9]{2})[0-9]{12}$"
          }

          return regex
      }

      func validate(cardNumber: String) -> Bool {
          let predicate = NSPredicate(format:"SELF MATCHES %@", validationRegex())
          return predicate.evaluateWithObject(cardNumber)
      }

      // Method returns the credit card type for given card number
      static func cardTypeForCreditCardNumber(cardNumber: String) -> CreditCardType?  {
          var creditCardType: CreditCardType?

          var index = 0
          while let cardType = CreditCardType(rawValue: index) {
              if cardType.validate(cardNumber) {
                  creditCardType = cardType
                  break
              } else {
                  index++
              }
          }
          return creditCardType
        }
      }

      调用方法creditcardtype.cardtypeforcreditcardnumber("卡号"),该方法返回creditcardtype枚举值。


      食性:只是一个小勺子P></

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      $("#CreditCardNumber").focusout(function () {


              var regVisa = /^4[0-9]{12}(?:[0-9]{3})?$/;
              var regMasterCard = /^5[1-5][0-9]{14}$/;
              var regAmex = /^3[47][0-9]{13}$/;
              var regDiscover = /^6(?:011|5[0-9]{2})[0-9]{12}$/;

              if (regVisa.test($(this).val())) {
                  $("#CCImage").html("<img height='40px' src='@Url.Content("~/images/visa.png")'>");          

              }

              else if (regMasterCard.test($(this).val())) {
              $("#CCImage").html("<img height='40px' src='@Url.Content("~/images/mastercard.png")'>");

              }

              else if (regAmex.test($(this).val())) {

                 $("#CCImage").html("<img height='40px' src='@Url.Content("~/images/amex.png")'>");

              }
               else if (regDiscover.test($(this).val())) {

                 $("#CCImage").html("<img height='40px' src='@Url.Content("~/images/discover.png")'>");

              }
              else {
              $("#CCImage").html("NA");

              }

          });


      下面是用python编写的一些布尔函数的示例,如果根据函数名检测到卡,则返回True

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      74
      75
      76
      77
      78
      79
      80
      81
      82
      83
      84
      85
      86
      87
      88
      89
      90
      91
      92
      93
      94
      95
      96
      97
      98
      99
      100
      def is_american_express(cc_number):
         """Checks if the card is an american express. If us billing address country code, & is_amex, use vpos
          https://en.wikipedia.org/wiki/Bank_card_number#cite_note-GenCardFeatures-3
          :param cc_number: unicode card number
         """
          return bool(re.match(r'^3[47][0-9]{13}$', cc_number))


      def is_visa(cc_number):
         """Checks if the card is a visa, begins with 4 and 12 or 15 additional digits.
          :param cc_number: unicode card number
         """

          # Standard Visa is 13 or 16, debit can be 19
          if bool(re.match(r'^4', cc_number)) and len(cc_number) in [13, 16, 19]:
              return True

          return False


      def is_mastercard(cc_number):
         """Checks if the card is a mastercard. Begins with 51-55 or 2221-2720 and 16 in length.
          :param cc_number: unicode card number
         """
          if len(cc_number) == 16 and cc_number.isdigit():  # Check digit, before cast to int
              return bool(re.match(r'^5[1-5]', cc_number)) or int(cc_number[:4]) in range(2221, 2721)
          return False


      def is_discover(cc_number):
         """Checks if the card is discover, re would be too hard to maintain. Not a supported card.
          :param cc_number: unicode card number
         """
          if len(cc_number) == 16:
              try:
                  # return bool(cc_number[:4] == '6011' or cc_number[:2] == '65' or cc_number[:6] in range(622126, 622926))
                  return bool(cc_number[:4] == '6011' or cc_number[:2] == '65' or 622126 <= int(cc_number[:6]) <= 622925)
              except ValueError:
                  return False
          return False


      def is_jcb(cc_number):
         """Checks if the card is a jcb. Not a supported card.
          :param cc_number: unicode card number
         """
          # return bool(re.match(r'^(?:2131|1800|35\d{3})\d{11}$', cc_number))  # wikipedia
          return bool(re.match(r'^35(2[89]|[3-8][0-9])[0-9]{12}$', cc_number))  # PawelDecowski


      def is_diners_club(cc_number):
         """Checks if the card is a diners club. Not a supported card.
          :param cc_number: unicode card number
         """
          return bool(re.match(r'^3(?:0[0-6]|[68][0-9])[0-9]{11}$', cc_number))  # 0-5 = carte blance, 6 = international


      def is_laser(cc_number):
         """Checks if the card is laser. Not a supported card.
          :param cc_number: unicode card number
         """
          return bool(re.match(r'^(6304|670[69]|6771)', cc_number))


      def is_maestro(cc_number):
         """Checks if the card is maestro. Not a supported card.
          :param cc_number: unicode card number
         """
          possible_lengths = [12, 13, 14, 15, 16, 17, 18, 19]
          return bool(re.match(r'^(50|5[6-9]|6[0-9])', cc_number)) and len(cc_number) in possible_lengths


      # Child cards

      def is_visa_electron(cc_number):
         """Child of visa. Checks if the card is a visa electron. Not a supported card.
          :param cc_number: unicode card number
         """
          return bool(re.match(r'^(4026|417500|4508|4844|491(3|7))', cc_number)) and len(cc_number) == 16


      def is_total_rewards_visa(cc_number):
         """Child of visa. Checks if the card is a Total Rewards Visa. Not a supported card.
          :param cc_number: unicode card number
         """
          return bool(re.match(r'^41277777[0-9]{8}$', cc_number))


      def is_diners_club_carte_blanche(cc_number):
         """Child card of diners. Checks if the card is a diners club carte blance. Not a supported card.
          :param cc_number: unicode card number
         """
          return bool(re.match(r'^30[0-5][0-9]{11}$', cc_number))  # github PawelDecowski, jquery-creditcardvalidator


      def is_diners_club_carte_international(cc_number):
         """Child card of diners. Checks if the card is a diners club international. Not a supported card.
          :param cc_number: unicode card number
         """
          return bool(re.match(r'^36[0-9]{12}$', cc_number))  # jquery-creditcardvalidator


      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      74
      75
      76
      77
      78
      79
      80
      81
      82
      83
      84
      85
      86
      87
      88
      // abobjects.com, parvez ahmad ab bulk mailer
      use below script

      function isValidCreditCard2(type, ccnum) {
             if (type =="Visa") {
                // Visa: length 16, prefix 4, dashes optional.
                var re = /^4\d{3}?\d{4}?\d{4}?\d{4}$/;
             } else if (type =="MasterCard") {
                // Mastercard: length 16, prefix 51-55, dashes optional.
                var re = /^5[1-5]\d{2}?\d{4}?\d{4}?\d{4}$/;
             } else if (type =="Discover") {
                // Discover: length 16, prefix 6011, dashes optional.
                var re = /^6011?\d{4}?\d{4}?\d{4}$/;
             } else if (type =="AmEx") {
                // American Express: length 15, prefix 34 or 37.
                var re = /^3[4,7]\d{13}$/;
             } else if (type =="Diners") {
                // Diners: length 14, prefix 30, 36, or 38.
                var re = /^3[0,6,8]\d{12}$/;
             }
             if (!re.test(ccnum)) return false;
             return true;
             /*
             // Remove all dashes for the checksum checks to eliminate negative numbers
             ccnum = ccnum.split("-").join("");
             // Checksum ("Mod 10")
             // Add even digits in even length strings or odd digits in odd length strings.
             var checksum = 0;
             for (var i=(2-(ccnum.length % 2)); i<=ccnum.length; i+=2) {
                checksum += parseInt(ccnum.charAt(i-1));
             }
             // Analyze odd digits in even length strings or even digits in odd length strings.
             for (var i=(ccnum.length % 2) + 1; i<ccnum.length; i+=2) {
                var digit = parseInt(ccnum.charAt(i-1)) * 2;
                if (digit < 10) { checksum += digit; } else { checksum += (digit-9); }
             }
             if ((checksum % 10) == 0) return true; else return false;
             */

          }
      jQuery.validator.addMethod("isValidCreditCard", function(postalcode, element) {
          return isValidCreditCard2($("#cardType").val(), $("#cardNum").val());

      },"credit card is invalid");


           Type</td>
                                                <td class="text">&nbsp; <form:select path="cardType" cssclass="fields" style="border: 1px solid #D5D5D5;padding: 0px 0px 0px 0px;width: 130px;height: 22px;">
                                                    <option value="SELECT">SELECT</option>
                                                    <option value="MasterCard">Mastercard</option>
                                                    <option value="Visa">Visa</option>
                                                     <option value="AmEx">American Express</option>
                                                    <option value="Discover">Discover</option>
                                                  </form:select> <font color="#FF0000">*</font>

      $("#signupForm").validate({

          rules:{
             companyName:{required: true},
             address1:{required: true},
             city:{required: true},
             state:{required: true},
             zip:{required: true},
             country:{required: true},
             chkAgree:{required: true},
             confPassword:{required: true},
             lastName:{required: true},
             firstName:{required: true},
             ccAddress1:{required: true},
             ccZip:{        
                 postalcode : true
             },
             phone:{required: true},
             email:{
                 required: true,
                 email: true
                 },
             userName:{
                 required: true,
                 minlength: 6
                 },
             password:{
                 required: true,
                 minlength: 6
                 },          
             cardNum:{          
                  isValidCreditCard : true
             },


      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      follow Luhn’s algorithm

       private  boolean validateCreditCardNumber(String str) {

              int[] ints = new int[str.length()];
              for (int i = 0; i < str.length(); i++) {
                  ints[i] = Integer.parseInt(str.substring(i, i + 1));
              }
              for (int i = ints.length - 2; i >= 0; i = i - 2) {
                  int j = ints[i];
                  j = j * 2;
                  if (j > 9) {
                      j = j % 10 + 1;
                  }
                  ints[i] = j;
              }
              int sum = 0;
              for (int i = 0; i < ints.length; i++) {
                  sum += ints[i];
              }
              if (sum % 10 == 0) {
                 return true;
              } else {
                  return false;
              }


          }

      then call this method

      Edittext mCreditCardNumberEt;

       mCreditCardNumberEt.addTextChangedListener(new TextWatcher() {
                  @Override
                  public void beforeTextChanged(CharSequence s, int start, int count, int after) {

                  }

                  @Override
                  public void onTextChanged(CharSequence s, int start, int before, int count) {

                   int cardcount=   s.toString().length();
                       if(cardcount>=16) {
                          boolean cardnumbervalid=   validateCreditCardNumber(s.toString());
                          if(cardnumbervalid) {
                              cardvalidtesting.setText("Valid Card");
                              cardvalidtesting.setTextColor(ContextCompat.getColor(context,R.color.green));
                          }
                          else {
                              cardvalidtesting.setText("Invalid Card");
                              cardvalidtesting.setTextColor(ContextCompat.getColor(context,R.color.red));
                          }
                      }
                     else if(cardcount>0 &&cardcount<16) {
                           cardvalidtesting.setText("Invalid Card");
                           cardvalidtesting.setTextColor(ContextCompat.getColor(context,R.color.red));
                      }

                      else {
                          cardvalidtesting.setText("");

                      }


                      }

                  @Override
                  public void afterTextChanged(Editable s) {

                  }
              });

      The first six digits of a card number (including the initial MII
      digit) are known as the issuer identification number (IIN). These
      identify the card issuing institution that issued the card to the card
      holder. The rest of the number is allocated by the card issuer. The
      card number's length is its number of digits. Many card issuers print
      the entire IIN and account number on their card.

      基于以上事实,我想保留一个Java代码片段来识别卡品牌。

      Sample card types

      1
      2
      3
      4
      5
      6
      7
      public static final String AMERICAN_EXPRESS ="American Express";
      public static final String DISCOVER ="Discover";
      public static final String JCB ="JCB";
      public static final String DINERS_CLUB ="Diners Club";
      public static final String VISA ="Visa";
      public static final String MASTERCARD ="MasterCard";
      public static final String UNKNOWN ="Unknown";

      Card Prefixes

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      // Based on http://en.wikipedia.org/wiki/Bank_card_number#Issuer_identification_number_.28IIN.29
      public static final String[] PREFIXES_AMERICAN_EXPRESS = {"34","37"};
      public static final String[] PREFIXES_DISCOVER = {"60","62","64","65"};
      public static final String[] PREFIXES_JCB = {"35"};
      public static final String[] PREFIXES_DINERS_CLUB = {"300","301","302","303","304","305","309","36","38","39"};
      public static final String[] PREFIXES_VISA = {"4"};
      public static final String[] PREFIXES_MASTERCARD = {
             "2221","2222","2223","2224","2225","2226","2227","2228","2229",
             "223","224","225","226","227","228","229",
             "23","24","25","26",
             "270","271","2720",
             "50","51","52","53","54","55"
          };

      Check to see if the input number has any of the given prefixes.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      public String getBrand(String number) {

      String evaluatedType;
      if (StripeTextUtils.hasAnyPrefix(number, PREFIXES_AMERICAN_EXPRESS)) {
          evaluatedType = AMERICAN_EXPRESS;
      } else if (StripeTextUtils.hasAnyPrefix(number, PREFIXES_DISCOVER)) {
          evaluatedType = DISCOVER;
      } else if (StripeTextUtils.hasAnyPrefix(number, PREFIXES_JCB)) {
          evaluatedType = JCB;
      } else if (StripeTextUtils.hasAnyPrefix(number, PREFIXES_DINERS_CLUB)) {
          evaluatedType = DINERS_CLUB;
      } else if (StripeTextUtils.hasAnyPrefix(number, PREFIXES_VISA)) {
          evaluatedType = VISA;
      } else if (StripeTextUtils.hasAnyPrefix(number, PREFIXES_MASTERCARD)) {
          evaluatedType = MASTERCARD;
      } else {
          evaluatedType = UNKNOWN;
      }
          return evaluatedType;
      }

      Finally, The Utility method

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      /**
        * Check to see if the input number has any of the given prefixes.
        *
        * @param number the number to test
        * @param prefixes the prefixes to test against
        * @return {@code true} if number begins with any of the input prefixes
      */

      public static boolean hasAnyPrefix(String number, String... prefixes) {
        if (number == null) {
             return false;
        }
         for (String prefix : prefixes) {
             if (number.startsWith(prefix)) {
             return true;
          }
        }
           return false;
      }

      参考

      • 条纹卡生成器
      • 小精灵


        我使用https://github.com/bendrucker/creditcards-types/从数字中检测信用卡类型。我遇到的一个问题是发现测试编号6011 1111 1111 1117

        来自https://www.cybersource.com/developers/other_resources/quick_references/test_cc_numbers/我们可以看到它是一个发现号,因为它从6011开始。但我从信用卡类型中得到的结果是"大师"。我把这个问题向作者公开了。他很快给了我答复,并提供了这个PDF文档https://www.discovernetwork.com/downloads/ipp_var_compliance.pdf。从文档中我们可以清楚地看到,6011111111111117不属于Discover信用卡的范围。


        试试这个。为了斯威夫特。

        1
        2
        3
        4
        5
        6
        7
        8
        func checkCardValidation(number : String) -> Bool
        {
            let reversedInts = number.characters.reversed().map { Int(String($0)) }
                return reversedInts.enumerated().reduce(0, {(sum, val) in
                    let odd = val.offset % 2 == 1
                    return sum + (odd ? (val.element! == 9 ? 9 : (val.element! * 2) % 9) : val.element!)
                }) % 10 == 0
        }

        使用。

        1
        2
        3
        4
        5
        if (self.checkCardValidation(number:"yourNumber") == true) {
             print("Card Number valid")
        }else{
             print("Card Number not valid")
        }


        the expression that the rules匹配正则vendors respective卡:P></

        • (4\d{12}(?:\d{3})?)for签证。
        • (5[1-5]\d{14})for万事达卡。
        • (3[47]\d{13})换公司。
        • ((?:5020|5038|6304|6579|6761)\d{12}(?:\d\d)?)换老师。
        • (3(?:0[0-5]|[68][0-9])[0-9]{11})for大来俱乐部。
        • (6(?:011|5[0-9]{2})[0-9]{12})for发现。
        • (35[2-8][89]\d\d\d{10})for JCB。