我想知道如何仅根据信用卡的号码来判断信用卡的类型。有谁知道确定可靠的方法吗?


当前回答

斯威夫特 5+

extension String {
    
    func isMatch(_ Regex: String) -> Bool {
        
        do {
            let regex = try NSRegularExpression(pattern: Regex)
            let results = regex.matches(in: self, range: NSRange(self.startIndex..., in: self))
            return results.map {
                String(self[Range($0.range, in: self)!])
            }.count > 0
        } catch {
            return false
        }
        
    }
    
    func getCreditCardType() -> String? {
        
        let VISA_Regex = "^4[0-9]{6,}$"
        let MasterCard_Regex = "^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,}$"
        let AmericanExpress_Regex = "^3[47][0-9]{5,}$"
        let DinersClub_Regex = "^3(?:0[0-5]|[68][0-9])[0-9]{4,}$"
        let Discover_Regex = "^6(?:011|5[0-9]{2})[0-9]{3,}$"
        let JCB_Regex = "^(?:2131|1800|35[0-9]{3})[0-9]{3,}$"
        
        if self.isMatch(VISA_Regex) {
            return "VISA"
        } else if self.isMatch(MasterCard_Regex) {
            return "MasterCard"
        } else if self.isMatch(AmericanExpress_Regex) {
            return "AmericanExpress"
        } else if self.isMatch(DinersClub_Regex) {
            return "DinersClub"
        } else if self.isMatch(Discover_Regex) {
            return "Discover"
        } else if self.isMatch(JCB_Regex) {
            return "JCB"
        } else {
            return nil
        }
        
    }
    
}

使用。

"1234123412341234".getCreditCardType()

其他回答

我用jQuery的解决方案:

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,则未检测到信用卡类型。

“creditcard”类应该添加到creditcard输入字段中。

看看这个:

http://www.breakingpar.com/bkp/home.nsf/0/87256B280015193F87256CC70060A01B

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;
}

信用卡/借记卡号码被称为PAN,或主要帐户号码。PAN的前六位数字取自属于开证行的IIN(或发证人识别号码)(IIN以前称为BIN -银行识别号码-因此您可能会在一些文件中看到该术语的引用)。这六位数字符合国际标准ISO/IEC 7812,可用于从数字中确定卡片的类型。

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

无论如何,为了从数字中检测类型,您可以使用如下所示的正则表达式

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

万事达卡:^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年之前,万事达卡号码从数字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位pan和16位pan卡。Visa目前的文件显示,它可能发行或可能已经发行了12到19位数的数字。因此,您不应该检查卡号的长度,而应该验证它至少有7位数字(对于一个完整的IIN加上一个检查数字,它应该与Luhn算法预测的值匹配)。

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

4444 4444 4444 4444

比正确输入容易得多吗

4444444444444444

因为用户输入了您不希望看到的字符而惩罚用户实际上没有任何好处。

这也意味着要确保输入字段至少有24个字符的空间,否则输入空格的用户将会耗尽空间。我建议你设置足够宽的字段以显示32个字符,并允许最多64个字符;这为扩张提供了充足的空间。

下面这张图可以让我们更深入地了解:

更新(2016):万事达卡将从Ach支付开始实施新的BIN范围。

试试kotlin。添加Regex并添加到when语句中。

private fun getCardType(number: String): String {

        val visa = Regex("^4[0-9]{12}(?:[0-9]{3})?$")
        val mastercard = Regex("^5[1-5][0-9]{14}$")
        val amx = Regex("^3[47][0-9]{13}$")

        return when {
            visa.matches(number) -> "Visa"
            mastercard.matches(number) -> "Mastercard"
            amx.matches(number) -> "American Express"
            else -> "Unknown"
        }
    }

在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
        }
    }
}

单元测试:

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]);
            });
        });
    });
});