1、基础知识git
银行卡校验规则(Luhn算法)算法
Luhn检验数字算法 (Luhn Check Digit Algorithm),也叫作模数10公式,是一种简单的算法,用于验证银行卡、信用卡号码的有效性的算法。对全部大型信用卡公司发行的信用卡都起做用, 这些公司包括美国Express、护照、万事达卡、Discover和用餐者俱乐部等。这种算法最初是在20世纪60年代由一组数学家制定,如今Luhn 检验数字算法属于大众,任何人均可以使用它。
算法原理:将每一个奇数加倍和使它变为单个的数字,若是必要的话经过减去9和在每一个偶数上加上这些值。若是此卡要有效,那么,结果必须是10的倍数。数组
好比上图的卡号为3759 8765 4321 001 (15位),从最高位开始全部的奇数位相加,偶数为乘以2相加(偶数乘以2后若是大于10则两位数相加),把这些奇数和偶数都加在一块儿获得57.
(57+3)%10 ==0 若是此卡知足被10整除,则有效位一定为3。
针对目前提现成功(clear_success)的记录里面,统计卡号的位数和数量关系以下:
卡号位数数量
<13 3038+
14 538
15 476
16 10884
17 68
18 4395
19 38070
>20 504+
说明:
位数少于14的卡号基本是外资银行,或小银行。
***496748*** ** HSBC HSBCHKHHHKH
***430259*** ** HSBC HSBCHKHHHKH
***51878018*** ** Bank of East Asia Limited BEASHKHHXXX
位数多于23的卡号大可能是卡号包含字母或空格。
62270014 **** 0045 *** CHINA CONSTRUCTION BANK **
601382700 **** 9077 ** BANK OF CHINA FOSHAN BRANCH **
若是是国内的主流银行(中、农、工、建、招、交等)基本都是基于16位或者19位的卡号。
来看看提现成功(clear_success)里面的卡有多少知足Luhn规则
针对16位美圆我的用户 准确率:99.84%
正确的卡号数量:3105 不正确的卡号数量 :14
卡号45806509689007** is NOT valid
卡号48620375555016** is NOT valid
卡号54202100231152** is NOT valid
卡号58890201075786** is NOT valid
卡号62106200000456** is NOT valid
卡号62129986037235** is NOT valid
卡号62252017026526** is NOT valid
.....
针对19位美圆我的用户 准确率:99.96%
正确的卡号数量:10574 不正确的卡号数量 :13 其中3笔发生退票
卡号60138214000567721** is NOT valid
卡号60138217000662109** is NOT valid
卡号60138220005824282** is NOT valid
卡号60138220006014219** is NOT valid
卡号60220001386050410** is NOT valid
卡号62161132000004484** is NOT valid
卡号62220212082154900** is NOT valid
卡号62220836020035821** is NOT valid
卡号63214140980000000** is NOT valid
以上都是提现成功的卡号,能够看到基本都严格知足Luhn算法。
卡号位数数量
15 1
16 149
17 4
18 64
19 502
20 3
正确的卡号数量:622
不正确的卡号数量:29 + 1 +4+64+3
14%卡填写违法了Luhn算法,也就是这部分卡号都是能够提早经过Luhn校验发现的。
结论是咱们能够在填写收款帐户的时候,添加一种Luth算法的JS脚本检查用户填写的卡号存在问题。固然即时用户填写的卡号违法了该规则,咱们仍然运行用户填写,但给出相应的警示内容(可能填错)。
目前在收银台页面(Checkout.vm)针对信用卡的交易,校验的JS :isValidCardfunction函数就包含了Luth校验规则,必须严格按照该规则的卡才能提交表单。函数
2、iOS判断银行帐号spa
方法一:
.net
- (BOOL) checkCardNo:(NSString*) cardNo{
int oddsum = 0; //奇数求和
int evensum = 0; //偶数求和
int allsum = 0;
int cardNoLength = (int)[cardNo length];
int lastNum = [[cardNo substringFromIndex:cardNoLength-1] intValue];
cardNo = [cardNo substringToIndex:cardNoLength - 1];
for (int i = cardNoLength -1 ; i>=1;i--) {
NSString *tmpString = [cardNo substringWithRange:NSMakeRange(i-1, 1)];
int tmpVal = [tmpString intValue];
if (cardNoLength % 2 ==1 ) {
if((i % 2) == 0){
tmpVal *= 2;
if(tmpVal>=10)
tmpVal -= 9;
evensum += tmpVal;
}else{
oddsum += tmpVal;
}
}else{
if((i % 2) == 1){
tmpVal *= 2;
if(tmpVal>=10)
tmpVal -= 9;
evensum += tmpVal;
}else{
oddsum += tmpVal;
}
}
}
allsum = oddsum + evensum;
allsum += lastNum;
if((allsum % 10) == 0)
return YES;
else
return NO;
}
blog
方法二ci
@interface NSString (Luhm)数学
- (BOOL)luhmCheck;string
@end
@implementation NSString (Luhm)
- (BOOL)luhmCheck{
NSString * lastNum = [[selfsubstringFromIndex:(self.length-1)]copy];//取出最后一位
NSString * forwardNum = [[selfsubstringToIndex:(self.length -1)]copy];//前15或18位
NSMutableArray * forwardArr = [[NSMutableArrayalloc] initWithCapacity:0];
for (int i=0; i<forwardNum.length; i++) {
NSString * subStr = [forwardNumsubstringWithRange:NSMakeRange(i,1)];
[forwardArr addObject:subStr];
}
NSMutableArray * forwardDescArr = [[NSMutableArrayalloc] initWithCapacity:0];
for (int i =(forwardArr.count-1); i> -1; i--) {//前15位或者前18位倒序存进数组
[forwardDescArr addObject:forwardArr[i]];
}
NSMutableArray * arrOddNum = [[NSMutableArrayalloc] initWithCapacity:0];//奇数位*2的积 < 9
NSMutableArray * arrOddNum2 = [[NSMutableArrayalloc] initWithCapacity:0];//奇数位*2的积 > 9
NSMutableArray * arrEvenNum = [[NSMutableArrayalloc] initWithCapacity:0];//偶数位数组
for (int i=0; i< forwardDescArr.count; i++) {
NSInteger num = [forwardDescArr[i]intValue];
if (i%2) {//偶数位
[arrEvenNum addObject:[NSNumber numberWithInt:num]];
}else{//奇数位
if (num *2 < 9) {
[arrOddNum addObject:[NSNumber numberWithInt:num *2]];
}else{
NSInteger decadeNum = (num *2) / 10;
NSInteger unitNum = (num *2) % 10;
[arrOddNum2 addObject:[NSNumber numberWithInt:unitNum]];
[arrOddNum2 addObject:[NSNumber numberWithInt:decadeNum]];
}
}
}
__block NSInteger sumOddNumTotal = 0;
[arrOddNum enumerateObjectsUsingBlock:^(NSNumber * obj,NSUInteger idx, BOOL *stop) {
sumOddNumTotal += [obj integerValue];
}];
__block NSInteger sumOddNum2Total = 0;
[arrOddNum2 enumerateObjectsUsingBlock:^(NSNumber * obj,NSUInteger idx, BOOL *stop) {
sumOddNum2Total += [obj integerValue];
}];
__block NSInteger sumEvenNumTotal =0 ;
[arrEvenNum enumerateObjectsUsingBlock:^(NSNumber * obj,NSUInteger idx, BOOL *stop) {
sumEvenNumTotal += [obj integerValue];
}];
NSInteger lastNumber = [lastNumintegerValue];
NSInteger luhmTotal = lastNumber + sumEvenNumTotal + sumOddNum2Total + sumOddNumTotal;
return (luhmTotal%10 ==0)?YES:NO;
}
@end
参考连接
1.http://blog.csdn.net/lixianyue1991/article/details/44938309
2.http://blog.csdn.net/hmxiao_1983/article/details/29845911