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

_

点击上方蓝字关注“汪宇杰博客”

导语

最近在家闲的蛋疼需要写点文章。正好我本人在金融科技公司工作,对信用卡业务略有了解。我们看看如何在 .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# 代码表示,即:

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 (可选参数,也可自己拓展)

验证返回类型为:

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/311849.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python统计文件中每个单词出现的次数_python统计文本中每个单词出现的次数

.python统计文本中每个单词出现的次数&#xff1a; #codingutf-8 __author__ ‘zcg‘ import collections import os with open(‘abc.txt‘) as file1:#打开文本文件 str1file1.read().split(‘ ‘)#将文章按照空格划分开 print "原文本:\n %s"% str1 print "…

AcWing 1101. 献给阿尔吉侬的花束

阿尔吉侬是一只聪明又慵懒的小白鼠&#xff0c;它最擅长的就是走各种各样的迷宫。 今天它要挑战一个非常大的迷宫&#xff0c;研究员们为了鼓励阿尔吉侬尽快到达终点&#xff0c;就在终点放了一块阿尔吉侬最喜欢的奶酪。 现在研究员们想知道&#xff0c;如果阿尔吉侬足够聪明…

数据结构---关键路径

数据结构—关键路径 原理&#xff1a;参考趣学数据结构 代码&#xff1a; #include<stdio.h> #include<stdlib.h> #include "stack.h" #define typeNode int //每个头结点的标识数据类型 #define N 100 //最大结点数 int degree[N];//结点入度数,通过…

Kubernetes AIOps解决方案商 Carbon Relay获6300万美元A轮融资

每10家企业中就有4家报告说他们正在使用Kubernetes&#xff0c;Kubernetes是开放源代码容器编排框架&#xff0c;用于在生产环境中自动化应用程序的部署&#xff0c;扩展和管理。但是&#xff0c;诸如管理复杂性&#xff0c;部署时间和无法预料的错误之类的挑战可能会降低生产率…

python结束线程_2018-01-02 如何优雅地终止python线程

前言 零 我们知道&#xff0c;在python里面要终止一个线程&#xff0c;常规的做法就是设置/检查 --->标志或者锁方式来实现的。 这种方式好不好呢&#xff1f; 应该是不大好的&#xff01;因为在所有的程序语言里面&#xff0c;突然地终止一个线程&#xff0c;这无论如何都…

AcWing 1113. 红与黑

有一间长方形的房子&#xff0c;地上铺了红色、黑色两种颜色的正方形瓷砖。 你站在其中一块黑色的瓷砖上&#xff0c;只能向相邻&#xff08;上下左右四个方向&#xff09;的黑色瓷砖移动。 请写一个程序&#xff0c;计算你总共能够到达多少块黑色的瓷砖。 输入格式 输入包括…

SkyWalking学习笔记(Window环境 本地环境)

基于 Windows 环境使用 SkyAPM-dotnet 来介绍一下 SkyWalking&#xff0c; SkyAPM-dotnet 是 SkyWalking 的 .NET Agent环境要求JDK8Elasticsearch8080,9200,10800,11800,12800 端口不被占用Elasticsearch安装Elasticsearch下载安装 参考官方教程.Elasticsearch下载安装官方教程…

word List16

word List16 如果存在什么问题&#xff0c;欢迎批评指正&#xff01;谢谢&#xff01;

python二分法求方程的根_Python查找函数f(x)=0根的解决方法

线性代数分享方程f(x)0的根 函数F(x)0的重根与F(x)0的根有什么关系&#xff1f;有些人一旦错过了&#xff0c;就是一辈子不再主动联系&#xff0c;不愿打扰你的生活&#xff0c;连偶尔的寒暄都没有&#xff0c;成长就是这样的&#xff0c;不断的告别&#xff0c;不断的遇见。 请…

[蓝桥杯2015决赛]穿越雷区-bfs

题目描述 X星的坦克战车很奇怪&#xff0c;它必须交替地穿越正能量辐射区和负能量辐射区才能保持正常运转&#xff0c;否则将报废。 某坦克需要从A区到B区去&#xff08;A&#xff0c;B区本身是安全区&#xff0c;没有正能量或负能量特征&#xff09;&#xff0c;怎样走才能路径…

word List 17

word List 17 如果存在什么问题&#xff0c;欢迎批评指正&#xff01;谢谢&#xff01;

pb 如何导出csv_如何计算指数温度?

指数温度的高低与价格高低没有必然的联系&#xff0c;指数温度的高低反映的是在历史中低于指数当前估值出现的概率。温度越低说明在历史上低于当前估值的概率越小&#xff0c;指数的价值越被低估&#xff0c;上涨的概率越大&#xff1b;温度越高说明在历史上低于当前估值的概率…

[蓝桥杯]地宫取宝

X 国王有一个地宫宝库&#xff0c;是 nm 个格子的矩阵&#xff0c;每个格子放一件宝贝&#xff0c;每个宝贝贴着价值标签。 地宫的入口在左上角&#xff0c;出口在右下角。 小明被带到地宫的入口&#xff0c;国王要求他只能向右或向下行走。 走过某个格子时&#xff0c;如果…

算法问题---两艘船是否有最大承载量

算法问题—两艘船是否有最大承载量 代码&#xff1a; 栈代码&#xff1a; #pragma once #include<stdio.h> #define maxSize 100 typedef struct stack {int * base;int * top; }stack; bool init(stack & Stack) {//栈的初始化Stack.base new int[maxSize];if (…

python标准库time_Python 标准库之时间篇

写在之前 大家好&#xff0c;这是首发在我公众号「Python空间」的第 69 篇文章&#xff0c;欢迎关注&#xff0c;期待和你的交流。 在昨天的文章&#xff08;Python 标准库之日期&#xff09;中我们学习了 Python 标准库中「日期 & 时间」中的「日期」&#xff0c;本来想昨…

《ASP.NET Core 微服务实战》-- 读书笔记(第12章)

第 12 章 设计汇总微服务开发并不是要学习 C#、Java 或者 Go 编程--而是要学习如何开发应用以适应并充分利用弹性伸缩环境的优势&#xff0c;它们对托管环境没有偏好&#xff0c;并能瞬间启停换句话说&#xff0c;我们要学习如何开发云原生应用识别并解决反模式我们既然已经学习…

[蓝桥杯2017初赛]纸牌三角形-枚举permutation+数论

题目描述 A,2,3,4,5,6,7,8,9 共9张纸牌排成一个正三角形&#xff08;A按1计算&#xff09;。要求每个边的和相等。 下图就是一种排法这样的排法可能会有很多。 如果考虑旋转、镜像后相同的算同一种&#xff0c;一共有多少种不同的排法呢&#xff1f; 输出 输出一个整数表示答…

算法----最大承载量下的最大价值问题

算法----最大承载量下的最大价值问题 代码&#xff1a; 栈代码&#xff1a;&#xff08;存储哪些是需要的价值物&#xff09; #pragma once #include<stdio.h> #define maxSize 100 typedef struct stack {int * base;int * top; }stack; bool init(stack & Stack…

oracle多条件分组统计_多条件统计,就必须用Ifs系列函数,绝对的高能!

数据统计&#xff0c;我们并不陌生&#xff0c;但是在实际的工作或应用中&#xff0c;数据统计都是附加条件的&#xff0c;而且大多情况下是“多条件”的&#xff0c;此时&#xff0c;我们必须掌握“Ifs”系列函数。一、多条件判断&#xff1a;Ifs函数。功能&#xff1a;判断指…

AcWing 895. 最长上升子序列

给定一个长度为N的数列&#xff0c;求数值严格单调递增的子序列的长度最长是多少。 输入格式 第一行包含整数N。 第二行包含N个整数&#xff0c;表示完整序列。 输出格式 输出一个整数&#xff0c;表示最大长度。 数据范围 1≤N≤1000&#xff0c; −10^9≤数列中的数≤ 10…