我想知道如何仅根据信用卡的号码来判断信用卡的类型。有谁知道确定可靠的方法吗?
当前回答
信用卡/借记卡号码被称为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范围。
其他回答
另一个api解决方案在rapidapi银行卡位数检查有250K+发行卡类型。
只有一个GET rest api请求,并获得发卡机构信息,如:
{ "bin_number": 535177, "bank": "Finansbank A.S.", "scheme": "MASTERCARD", "type": "Debit", "country": "Turkey" }
匹配对应卡供应商的正则表达式规则:
(4\d{12}(?:\d{3})?) (5[1-5]\d{14}) (3[47]\d{13})为美国运通。 ((?: 5020 | 5038 | 6304 | 6579 | 6761) \ d {12} (?: \ \ d) ?)大师。 (3(?:0[0-5]|[68][0-9])[0-9]{11}) (6(?:011|5[0-9]{2})[0-9]{12})用于发现。 (35[2-8][89]\d\d\d{10})
看看这个:
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;
}
在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]);
});
});
});
});
在swift中,您可以创建一个枚举来检测信用卡类型。
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 enum值。