1. Introduction
1.绪论
In this article, we’ll learn how to identify a credit card type from a credit card number using regex.
在这篇文章中,我们将学习如何使用regex从信用卡号码中识别信用卡类型。
Then, we’ll learn about the Luhn algorithm and how we can use this to check whether a credit card number is valid.
然后,我们将了解卢恩算法,以及我们如何利用它来检查信用卡号码是否有效。
2. What Do the Leading Digits of a Card Number Tell Us?
2.卡片号码的前几位告诉我们什么?
The Primary Account Number (PAN) is another name for a credit card number.
主账户号码(PAN)是信用卡号码的另一个名称。
The PAN is typically 16 digits long, although the number of digits can vary depending on the card issuer.
PAN通常有16位数字,尽管数字的数量可能因发卡机构而异。
Currently, the Issuer Identification Number (IIN) is the first six digits of a PAN. It’s made up of one leading digit, followed by five digits.
目前,发行人识别码(IIN)是PAN的前六位数字。它由一个前导数字组成,后面是五个数字。
It’s important to emphasize that this is the current situation because it’s likely to change in the future. Work began as early as 2015 to increase the IIN to the first eight digits.
需要强调的是,这是目前的情况,因为未来可能会发生变化。早在2015年就开始工作,将国际投资银行的数字增加到前八位。
Let’s see how we can determine the type of credit card just by looking at the IIN.
让我们来看看如何仅通过查看IIN就能确定信用卡的类型。
2.1. What Does the Leading Digit Tell Us?
2.1.前导数字告诉我们什么?
The Major Industry Identifier is the first digit of a card number.
主要行业标识符是卡号的第一个数字。。
As the name suggests, we can look at the first digit of the card number to determine the industry to which the card belongs:
顾名思义,我们可以通过查看卡号的第一个数字来确定该卡所属的行业。
- 1, 2 – Airlines (among others)
- 3 – Travel and Entertainment
- 4, 5 – Banking
- 6 – Retail and Banking
- 7 – Fuel Industry
- 8 – Healthcare and Telecommunications
- 9 – National Authorities
- 0 – Other, Reserved for the future
Now, let’s take a look at how we’d identify the card issuer using the IIN.
现在,让我们来看看我们如何利用IIN来识别发卡机构。
2.2. How Do We Determine the Card Type From the IIN?
2.2.我们如何从IIN中确定卡片类型?
Since 1989, there has been an international standard defining how PANs should be allocated. The official register of IINs is not publicly available.
自1989年以来,一直有国际标准界定PAN应该如何分配。IINs的官方登记册是不公开的。
Fortunately, the majority of leading card issuers have widely known IIN ranges, so we can use regex to match the IIN to a card issuer.
幸运的是,大多数主要的发卡机构都有广为人知的IIN范围,所以我们可以使用regex将IIN与发卡机构相匹配。
Before we look at the regex, let’s remember that the list of IIN ranges is constantly changing.
在我们看这个词条之前,让我们记住, IIN范围的列表是不断变化的。
If we’re writing an application to do this, we’ll need to consider how we plan to keep it up-to-date.
如果我们要写一个应用程序来做这件事,我们就需要考虑我们打算如何保持它的最新状态。
Alternatively, we could choose to import one of several available open source libraries, which contain more card types and are more thoroughly tested than we are likely to be able to manage ourselves. For example, using the Stripe API would mean card processing is managed for us.
另外,我们可以选择导入几个可用的开源库中的一个,这些库包含更多的卡类型,并且经过了更全面的测试,而我们自己可能无法管理。例如,使用Stripe API将意味着为我们管理卡片处理。
2.3. Identifying the Card Issuer By Using Regex
2.3.通过使用Regex识别发卡机构
Let’s try and identify a Visa card.
让我们试着识别一张Visa卡。
Visa card numbers start with a 4, so a simple regex to identify a Visa card would be ^4[0-9]{0,}$
.
Visa卡的号码以4开头,所以识别Visa卡的简单重码是^4[0-9]{0,}$
。
Note that in our example, we’ve not checked the length of the number. So far, we’ve assumed that the card number is valid, so the length is not something we’re validating here.
请注意,在我们的例子中,我们没有检查号码的长度。到目前为止,我们已经假定卡号是有效的,所以长度不是我们在此验证的东西。
A similar pattern can be applied to identify other card issuers. For example, American Express cards begin with a 34 or a 37, so we can detect them using ^3[47][0-9]{0,}$
.
类似的模式可以应用于识别其他发卡机构。例如,美国运通卡以34或37开头,所以我们可以用^3[47][0-9]{0,}$
检测它们。
Some card issuers have wider IIN ranges.
一些发卡机构有更广泛的国际IN范围。
We find that Mastercard’s cards typically start with 51-55, however, within the last decade, they’ve introduced cards within the BIN range 222100-272099.
我们发现,万事达卡的卡片通常以51-55开头,然而在过去十年内,他们推出了BIN范围为222100-272099的卡片。
This gives us a regex of ^(5[1-5]|222[1-9]|22[3-9]|2[3-6]|27[01]|2720)[0-9]{0,}$
.
这给了我们一个^(5[1-5]|222[1-9]|22[3-9]|2[3-6]|27[01]|2720)[0-9]{0,}$
的词条。
We can use a similar pattern to identify cards from any card issuer whose range of IINs is known.
我们可以用类似的模式来识别任何发卡机构的卡片,这些发卡机构的IIN范围是已知的。
3. What Do the Middle Digits of a Card Number Tell Us?
3.卡片号码的中间数字告诉我们什么?
The full PAN consists of 3 parts: the Issue Identification Number (IIN), an Individual Account Identification Number, and a checksum digit.
完整的PAN由三部分组成:问题识别码(IIN)、个人账户识别码和一个校验码。
Between the IIN and the final digit, we have the Individual Account Identification Number.
在IIN和最后一位数字之间,我们有个人账户识别号。
The issuer defines what these middle digits mean, so they’ll have different meanings across different issuers.
发行人定义了这些中间数字的含义,所以它们在不同的发行人之间会有不同的含义。
They indicate information like the type of account linked to the card number.
它们表明了与卡号相连的账户类型等信息。
4. What Does the Final Digit of a Card Number Tell Us?
4.卡片号码的最后一位数字告诉我们什么?
The checksum digit is the final digit of a card number.
校验码是卡号的最后一位数字。。
Helpfully, the checksum digit allows us to use the Luhn algorithm to quickly identify an invalid card number.
有用的是,校验码允许我们使用Luhn算法来快速识别无效的卡号。
Hans Peter Luhn developed the Luhn algorithm in the late 1950s.
汉斯-彼得-卢恩在20世纪50年代末开发了卢恩算法。
It’s used to generate every modern credit card number that we use today, ensuring that every card number shares a particular property.
它被用来生成我们今天使用的每一个现代信用卡号码,确保每个卡号都有一个特定的属性。
The Luhn algorithm uses every digit in a card number, meaning we can use it to easily determine when a given card number is invalid – even if just a single digit was entered incorrectly.
卢恩算法使用卡号中的每一个数字,这意味着我们可以用它来轻松地确定某个卡号是无效的–即使只是一个数字输入错误。
Doing this means we can limit the number of unnecessary card processing functions. This is particularly important if we are charged per transaction we request!
这样做意味着我们可以限制不必要的卡处理功能的数量。如果我们要求每笔交易都要收费,这一点就特别重要
Let’s see how we can use the Luhn algorithm in a Java application.
让我们看看如何在一个Java应用程序中使用卢恩算法。
4.1. How Can We Use the Luhn Algorithm to Validate a Card Number?
4.1.我们如何使用卢恩算法来验证一个卡号?
Let’s run through the steps involved in using the Luhn algorithm to validate a given card number.
让我们运行一下使用卢恩算法验证给定卡号的步骤。
We’ll need to take the full credit card number, including the IIN.
我们需要记下完整的信用卡号码,包括IIN。
Starting from the rightmost digit, we’ll add all the digits together, performing a special step for every second digit.
从最右边的数字开始,我们将所有的数字相加,每隔一个数字进行一个特殊的步骤。
As we’re starting from the right, we’ll need to cycle backward through the card number, identifying every second digit:
由于我们从右边开始,我们需要向后循环查看卡号,识别每一个第二位数字。
for (int i = cardNumber.length() - 1; i >= 0; i--) {
int digit = Integer.parseInt(cardNumber.substring(i, i + 1));
if ((cardNumber.length() - i) % 2 == 0) {
digit = doubleAndSumDigits(digit);
}
sum += digit;
}
For every second digit, we must double it, and then sum the remaining digits.
对于每一个第二位数字,我们必须将其翻倍,然后将剩下的数字相加。。
Let’s see how this works for a short example of 4 digits (instead of the usual 16 digits) – let’s check whether the number 8642 would be a valid card number.
让我们看看这对一个4位数(而不是通常的16位数)的短例子是如何工作的–让我们检查一下数字8642是否会是一个有效的卡号。
Starting with the rightmost digit, we’re going to double every second digit:
从最右边的数字开始,我们要把每两个数字翻倍。
- So for 2 (the first digit from the right), there is no change.
- Next, we double the second digit, 4, to get 8.
- After that, the third digit, 6, for which there is no change.
- Lastly, we double the fourth digit, 8, to get 16.
If doubling the digit results in a two-digit number, then we need to do an extra step to get back down to a single digit – we’re going to add those digits together to produce a single-digit number, so for 16, this would be 1+6=7.
如果数字翻倍的结果是两位数,那么我们需要做一个额外的步骤来回到个位数–我们要把这些数字加在一起,产生一个个位数,所以对于16,这将是1+6=7。
This step is the same as subtracting 9, so we can implement it in the code as:
这一步与减去9相同,所以我们可以在代码中实现它。
private static int doubleAndSumDigits(int digit) {
int ret = digit * 2;
if (ret > 9) {
ret = digit - 9;
}
return ret;
}
Finally, to complete our example, let’s add each number together: 2 + 8 + 6 + 7 = 23.
最后,为了完成我们的例子,让我们把每个数字加在一起:2 + 8 + 6 + 7 = 23。
If the result of the Luhn algorithm is divisible by 10, then the card number is possibly valid.
如果卢恩算法的结果能被10整除,那么该卡号就可能是有效的。
We’ll return this as the result of our check:
我们将返回这个作为我们的检查结果。
return sum % 10 == 0;
In our case, 23 is not divisible by 10, so 8642 is not a valid card number.
在我们的案例中,23不能被10整除,所以8642不是一个有效的卡号。
In our example, the final digit, 2, would be the checksum digit.
在我们的例子中,最后一个数字,2,将是校验码。
For real card numbers, the checksum digit is calculated using the Luhn algorithm.
对于真实的卡号,校验码是用卢恩算法计算的。
For example, if we change the checksum digit to a 9 to give 8649, then the result of the Luhn algorithm is 30, which is divisible by 10, so 8649 would pass our Luhn check above.
例如,如果我们将校验码改为9,得到8649,那么卢恩算法的结果是30,它可以被10整除,所以8649可以通过我们上面的卢恩检查。
4.2. Are There Any Limitations of the Luhn Algorithm?
4.2.卢恩算法有什么局限性吗?
Of course, our check does not imply that 8649 is definitely a valid card number. Although it passes our check, it may not have been issued as an actual card by the relevant card issuer.
当然,我们的检查并不意味着8649肯定是一个有效的卡号。虽然它通过了我们的检查,但它可能没有被相关发卡机构作为实际的卡片发放。
The only way we can definitively confirm a card number is real is by asking the card issuer.
我们能够明确确认一个卡号是否真实的唯一方法是询问发卡机构。
The Luhn algorithm still provides us with a useful way to confirm when a given card number is definitely not valid.
卢恩算法仍然为我们提供了一个有用的方法来确认何时给定的卡号肯定是无效的。
However, there are a few edge cases where our Luhn check would fail to detect a typo in a card number.
然而,有一些边缘情况,我们的Luhn检查将无法检测到卡号中的错别字。
Fortunately, these edge cases are rare enough that we’re unlikely to ever come across one in real life.
幸运的是,这些边缘案例非常罕见,我们不太可能在现实生活中遇到这种情况。
Finally, the Luhn algorithm does not consider the length of the card number.
最后,卢恩算法不考虑卡号的长度。
In reality, we know that even though 8649 passes our Luhn check, it is too short to be a real credit card number.
在现实中,我们知道,即使8649通过了我们的Luhn检查,但它太短了,不可能是一个真正的信用卡号码。
We can implement an extra check on the length of the card number but must remember that each card issuer’s numbers can vary in length.
我们可以对卡号的长度实施额外的检查,但必须记住,每个发卡机构的卡号长度都可能不同。
5. Conclusion
5.总结
In this article, we looked at what each part of the card number can tell us about a credit card account.
在这篇文章中,我们看了卡号的每个部分可以告诉我们关于信用卡账户的情况。
Firstly, we learned how to identify card issuers by matching regex patterns on the leading digits. Next, we saw that we would need issuer-specific information to understand what the middle of a card number tells us about the account. Finally, we looked at how the Luhn algorithm works and implemented some code to validate a given card number.
首先,我们学习了如何通过匹配前导数字的重码模式来识别发卡机构。接下来,我们看到我们需要发卡机构的特定信息,以了解卡号中间的部分告诉我们关于该账户的信息。最后,我们研究了卢恩算法是如何工作的,并实现了一些代码来验证一个给定的卡号。
As always, the example project is available over on GitHub.
一如既往,该示例项目可在GitHub上获得。