前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >.NET Core 如何验证信用卡卡号

.NET Core 如何验证信用卡卡号

作者头像
Edi Wang
发布2020-02-18 23:35:15
3.3K0
发布2020-02-18 23:35:15
举报
文章被收录于专栏:汪宇杰博客汪宇杰博客

导语

最近在家闲的蛋疼需要写点文章。正好我本人在金融科技公司工作,对信用卡业务略有了解。我们看看如何在 .NET Core 里验证一个信用卡的卡号是否合法。

信用卡卡号组成

首先,信用卡的卡号一般为16位,也有少许14或15位的情况。其中,前6-8位用来标识卡片类型和发卡机构,称之为 BIN 码(Bank Identification Number)。有个网站可以查询:https://binlists.com/。万事达(Master Card)以 51-55 开头,例如交行的万事达白金卡 BIN 码为 522964。Visa 卡以 4 开头,例如我司(Green Dot)的 437303。剩余位数由各家发卡机构自己发挥,其中会包含持卡人信息、校验码等,由于不同银行规则不一样,不多介绍。但是,任何卡号都必须满足一个行业内著名的规律:MOD10算法。

Luhn / MOD 10 算法

根据维基百科的描述,Luhn 算法,也叫模10算法,由科学家 Hans Peter Luhn 在1960年发明,广泛用于校验借记卡、信用卡卡号是否正确,其标准为 ISO/IEC 7812-1。它的目的不是用于加密卡号,而是为了防止人为出错。

计算方法如下,比如对于卡号 :

6011000990139424

末尾的数字 4 叫做校验码,剩下的数字为 601100099013942。将他们从右到左排开,得到:

2 4 9 3 1 09 9 0 0 0 1 1 0 6

从第一位 2 开始,相隔一个数字的值 x2,即上面红色标出的奇数位翻倍,得到:

4 4 18 3 2 018 9 0 0 0 1 2 0 12

发现这里面有超过10的两位数,即蓝色标出的18、18、12,对于大于10的数,将其 -9,得到:

4 4 9 3 2 09 9 0 0 0 1 2 0 3

把所有的数加起来,得到:46

将这个结果乘以9,46 x 9 = 414

发现 414个位上的数字 4 和我们在第一步中拿掉的 4 相等,这个就是校验码的作用,相等就对了!最后把校验码也加上,46 + 4 = 50,而 50 % 10 = 0,得出结论 6011000990139424 是一个合法的信用卡卡号。

将这个算法用 C# 代码表示,即:

代码语言:javascript
复制
public static bool IsLuhnValid(int[] digits)
{
    var sum = 0;
    var alt = false;
    for (var i = digits.Length - 1; i >= 0; i--)
    {
        if (alt)
        {
            digits[i] *= 2;
            if (digits[i] > 9)
            {
                digits[i] -= 9;
            }
        }
        sum += digits[i];
        alt = !alt;
    }
    return sum % 10 == 0;
}
对于输入的字符串类型的卡号,也可以用个LINQ技巧一行代码转成 int 数组:
public static int[] GetDigitsArrayFromCardNumber(string cardNumber)
{
    var digits = cardNumber.Select(p => int.Parse(p.ToString())).ToArray();
    return digits;
}

写了个轮子

基于以上的知识,我今天抽空写了个开源库,可用于校验信用卡卡号是否合法,目前还有一些遗漏的场景(比如14、15位信用卡的校验),大家可以参考。

dotnet add package Edi.CreditCardUtils --version 0.1.0-alpha

https://github.com/EdiWang/Edi.CreditCardUtils

这个库的验证步骤为:

  1. 输入的字符串是否为16位数字
  2. 这串数字是否满足 Luhn 算法
  3. 该卡是否为已知的某发行商的BIN (可选参数,也可自己拓展)

验证返回类型为:

代码语言:javascript
复制
public class CreditCardValidationResult
{
    public CreditCardNumberFormat CreditCardNumberFormat { get; set; }
    public string CardType { get; set; }
}
public enum CreditCardNumberFormat
{
    None = 0,
    Valid_LuhnOnly = 100, // 验证通过,仅满足 Luhn
    Valid_BrandTest = 101, // 验证通过,满足 Luhn 并且为已知 BIN
    Invalid_BadStringFormat = 200, // 验证失败,非信用卡卡号格式
    Invalid_LuhnFailure = 201 // 验证失败,不满足 Luhn
}
使用方法可以参考单元测试中的案例,如验证一个卡号 4012888888881881,传入两个已知BIN(Visa、MasterCard)的验证器,会返回是否验证通过以及识别出的卡类型:
var result = CreditCardValidator.ValidCardNumber("4012888888881881", new List<ICreditCardBrandFormatValidator>
{
    new VisaFormatValidator(),
    new MasterCardFormatValidator()
});
Assert.IsTrue(result.CreditCardNumberFormat == CreditCardNumberFormat.Valid_BrandTest && result.CardType == "Visa");
对于自定义的BIN,比如你想写建行的BIN验证器,可以实现 ICreditCardBrandFormatValidator 接口,给个名字和正则就行,就像 Visa 的这个:
public class VisaFormatValidator : ICreditCardBrandFormatValidator
{
    public string BrandName => "Visa";
    public string BrandRegEx => "^4[0-9]{12}(?:[0-9]{3})?$";
}

参考:https://en.wikipedia.org/wiki/Luhn_algorithm

本文参与?腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-02-08,如有侵权请联系?cloudcommunity@tencent.com 删除

本文分享自 汪宇杰博客 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与?腾讯云自媒体分享计划? ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
http://www.vxiaotou.com