我想知道如何仅根据信用卡的号码来判断信用卡的类型。有谁知道确定可靠的方法吗?
当前回答
下面是一些用Python编写的布尔函数的示例,如果根据函数名检测到卡片,则返回True。
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
其他回答
压缩javascript版本
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;
}
}
};
信用卡/借记卡号码被称为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范围。
最近我需要这样的功能,我将Zend框架信用卡验证器移植到ruby。 红宝石宝石:https://github.com/Fivell/credit_card_validations zend框架:https://github.com/zendframework/zf2/blob/master/library/Zend/Validator/CreditCard.php
它们都使用INN范围来检测类型。在这里你可以读到关于INN的信息
根据这一点,您可以选择检测信用卡(没有regexp,但声明一些关于前缀和可能长度的规则)
所以我们有关于最常用卡片的下一个规则
######## 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算法(在http://en.wikipedia.org/wiki/Luhn有描述)。
更新
更新的规则列表可以在这里找到https://raw.githubusercontent.com/Fivell/credit_card_validations/master/lib/data/brands.yaml
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";
}
下面是使用Regex, c#检查信用卡类型的函数
只需一点点的勺子喂养:
$("#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");
}
});