首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何根据号码检测信用卡类型?

如何根据号码检测信用卡类型?
EN

Stack Overflow用户
提问于 2008-09-16 14:16:43
回答 27查看 540.2K关注 0票数 584

我正试图找出如何纯粹根据信用卡的号码来检测信用卡的类型。有没有人知道找到这件事的确切可靠的方法?

EN

回答 27

Stack Overflow用户

回答已采纳

发布于 2008-09-16 14:18:30

信用卡/借记卡号码称为PAN,或主帐户号。PAN的前六位数字来自于开证行的IIN,或发证者识别号(IINs以前被称为BIN -银行识别号,因此您可能在某些文档中看到对该术语的引用)。这六位数字受国际标准ISO/IEC 7812的约束,并可用于从数字中确定卡的类型。

不幸的是,实际的ISO/IEC 7812数据库是不可公开的,然而,有非官方的名单,包括商业和免费的,包括维基百科

无论如何,要从数字中检测类型,可以使用一个正则表达式,如下所示:原表达式的信用

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

MasterCard : ^5[1-5][0-9]{5,}|222[1-9][0-9]{3,}|22[3-9][0-9]{4,}|2[3-6][0-9]{5,}|27[01][0-9]{4,}|2720[0-9]{3,}$在2016年之前,MasterCard号码从51到55开始,,但这只能检测MasterCard信用卡;还有其他使用MasterCard系统发行的信用卡不属于这个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位数。这是食客俱乐部和MasterCard的合资公司,应该像MasterCard一样处理。

发现: ^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开始。

不幸的是,使用MasterCard系统处理的许多卡类型并不存在于万事达卡的IIN范围内(号码从51.55开始);最重要的情况是大师卡,其中许多卡是从其他银行的IIN范围发出的,因此位于整个数字空间。因此,最好假设任何不是您接受的其他类型的卡都必须是MasterCard

:卡号确实有不同的长度;例如,Visa过去曾发行过13位数的卡片和带有16位数的盘的卡。Visa目前的文件显示,它可能签发或可能已经签发了12至19位数的数字。因此,不应该检查卡号的长度,而是验证它至少有7位(对于一个完整的IIN加上一个校验数字,这应该与Luhn算法预测的值相匹配)。

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

代码语言:javascript
复制
4444 4444 4444 4444

正确地输入比正确地输入要容易得多

代码语言:javascript
复制
4444444444444444

惩罚用户是没有好处的,因为他们已经输入了您在这里不想看到的字符。

这也意味着确保您的输入字段至少有容纳的空间--至少 24字符,否则进入空格的用户将耗尽空间。--我建议您将字段设置得足够宽,显示32个字符,最多允许64个字符;这就为扩展提供了足够的空间。

以下是一幅能给出更多洞察力的图片:

更新(2016年): Mastercard将实现新的BIN范围,启动Ach支付

票数 864
EN

Stack Overflow用户

发布于 2013-10-02 14:04:21

在javascript中:

代码语言:javascript
复制
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
        }
    }
}

单元测试:

代码语言:javascript
复制
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]);
            });
        });
    });
});
票数 91
EN

Stack Overflow用户

发布于 2014-02-07 01:21:26

更新:2016年6月15日(目前作为最终解决方案)

请注意,我甚至放弃投票的一个是顶部投票,但为了清楚地表明,这些是实际工作,我用数以千计的真正的BIN代码测试它。最重要的是使用开始字符串(^),否则它将在现实世界中产生错误的结果!

JCB ^(?:2131|1800|35)[0-9]{0,}$开头:2131,1800,35 (3528-3589)

美国运通 ^3[47][0-9]{0,}$开始:34,37

食客俱乐部 ^3(?:0[0-59]{1}|[689])[0-9]{0,}$起价:300-305,309,36,38-39

Visa ^4[0-9]{0,}$开头:4

MasterCard ^(5[1-5]|222[1-9]|22[3-9]|2[3-6]|27[01]|2720)[0-9]{0,}$开头:2221-2720,51-55

大师 ^(5[06789]|6)[0-9]{0,}$大师总是在范围内成长:60-69,开头是/不是其他东西,但是开始5必须被编码为万事达卡。必须在代码末尾检测到大师卡,因为其他一些卡的范围在60-69之间。请看代码。

Discover ^(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开始

javascript中,我使用这个函数。当您将其分配给onkeyup事件并尽快给出结果时,这是很好的。

代码语言:javascript
复制
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;
}

在这里你可以玩它:

http://jsfiddle.net/upN3L/69/

For PHP使用此功能,这也检测到一些子签证/MC卡:

代码语言:javascript
复制
/**
  * Obtain a brand constant from a PAN
  *
  * @param string $pan               Credit card number
  * @param bool   $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
}
票数 53
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72768

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档