iOS小知识:银行卡号有效性校验

1,461 阅读2分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

前言

  1. iOS 银行卡号有效性校验Luhn算法 (银行卡号码校验算法)

应用场景:提款卡号校验( 结算账户类型是对公的时候,不验证卡号规则)

当然你也可以借助第三方进行校验,比如ccdcapi.alipay.com/validateAnd…

在这里插入图片描述

  1. 身份证校验:【校验年龄、校验是否符合身份证号生成规则】

进件风险控制强化: 通过身份证号码提取法人出生年月日,与当前日进行比较,如<18周岁, 则提示“法人未满18周岁,禁止进件!”

I 、银行卡号有效性校验

  • Luhn算法(又叫模10算法)

算法原理:将每个奇数加倍和使它变为单个的数字,如果必要的话通过减去9和在每个偶数上加上这些值。如果此卡要有效,那么,结果必须是10的倍数

应用场景:提款卡的卡号校验

  • 用法
    if(![QCT_Common bankCardluhmCheckWithCardNo:_jskhTextF.text]){
        
        [SVProgressHUD showInfoWithStatus:@"请输入正确的结算卡号"];

        
        return ;
        
        
    }
    


  • 银行卡号有效性问题Luhn算法
/** 银行卡号有效性问题Luhn算法
 *  现行 16 位银联卡现行卡号开头 6 位是 622126~622925 之间的,7 到 15 位是银行自定义的,
 *  可能是发卡分行,发卡网点,发卡序号,第 16 位是校验码。
 *  16 位卡号校验位采用 Luhm 校验方法计算:
 *  1,将未带校验位的 15 位卡号从右依次编号 1 到 15,位于奇数位号上的数字乘以 2
 *  2,将奇位乘积的个十位全部相加,再加上所有偶数位上的数字
 *  3,将加法和加上校验位能被 10 整除。
 */
+ (BOOL)bankCardluhmCheckWithCardNo:(NSString*)CardNo{
    
    
    if([NSStringQCTtoll isBlankString:CardNo]){
        return NO;
        
    }
    if(CardNo.length<3 ){
        return NO;
        
    }

    
    
    NSString * lastNum = [[CardNo substringFromIndex:(CardNo.length-1)] copy];//取出最后一位
    NSString * forwardNum = [[CardNo substringToIndex:(CardNo.length -1)] copy];//前15或18位
    
    
    
    NSMutableArray * forwardArr = [[NSMutableArray alloc] initWithCapacity:0];
    for (int i=0; i<forwardNum.length; i++) {
        NSString * subStr = [forwardNum substringWithRange:NSMakeRange(i, 1)];
        [forwardArr addObject:subStr];
    }
    
    NSMutableArray * forwardDescArr = [[NSMutableArray alloc] initWithCapacity:0];
    for (int i = (int)(forwardArr.count-1); i> -1; i--) {//前15位或者前18位倒序存进数组
        [forwardDescArr addObject:forwardArr[i]];
    }
    
    NSMutableArray * arrOddNum = [[NSMutableArray alloc] initWithCapacity:0];//奇数位*2的积 < 9
    NSMutableArray * arrOddNum2 = [[NSMutableArray alloc] initWithCapacity:0];//奇数位*2的积 > 9
    NSMutableArray * arrEvenNum = [[NSMutableArray alloc] initWithCapacity:0];//偶数位数组
    
    for (int i=0; i< forwardDescArr.count; i++) {
        NSInteger num = [forwardDescArr[i] intValue];
        if (i%2) {//偶数位
            [arrEvenNum addObject:[NSNumber numberWithInteger:num]];
        }else{//奇数位
            if (num * 2 < 9) {
                [arrOddNum addObject:[NSNumber numberWithInteger:num * 2]];
            }else{
                NSInteger decadeNum = (num * 2) / 10;
                NSInteger unitNum = (num * 2) % 10;
                [arrOddNum2 addObject:[NSNumber numberWithInteger:unitNum]];
                [arrOddNum2 addObject:[NSNumber numberWithInteger: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 = [lastNum integerValue];
    
    NSInteger luhmTotal = lastNumber + sumEvenNumTotal + sumOddNum2Total + sumOddNumTotal;
    
    return (luhmTotal%10 ==0)?YES:NO;
}

II、身份证校验

  • 需求背景: 进件风险控制强化(IOS)

通过身份证号码提取法人出生年月日,与当前日进行比较,如<18周岁, 则提示“法人未满18周岁,禁止进件!”

  • 处理流程:

如果符合身份证规则,再进一步判断是否大于等于18岁,如<18周岁, 则提示“法人未满18周岁,禁止进件!”

  • 文章地址:

kunnan.blog.csdn.net/article/det…

  • 中国大陆个人身份证号验证 Chinese Mainland Personal ID Card Validation
/**
 身份证号:加权因子
 中国大陆个人身份证号验证 Chinese Mainland Personal ID Card Validation

 */
+ (BOOL)CRM_validate_Personal_Identity_Card:(NSString *)identityCard
{
    
    if (identityCard.length != 18) return NO;
    // 正则表达式判断基本 身份证号是否满足格式
    NSString *regex2 = @"^(^[1-9]\\d{7}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}$)|(^[1-9]\\d{5}[1-9]\\d{3}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])((\\d{4})|\\d{3}[Xx])$)$";
    NSPredicate *identityStringPredicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",regex2];
    //如果通过该验证,说明身份证格式正确,但准确性还需计算
    if(![identityStringPredicate evaluateWithObject:identityCard]) return NO;
    
    //** 开始进行校验 *//
    
    //将前17位加权因子保存在数组里
    NSArray *idCardWiArray = @[@"7", @"9", @"10", @"5", @"8", @"4", @"2", @"1", @"6", @"3", @"7", @"9", @"10", @"5", @"8", @"4", @"2"];
    
    //这是除以11后,可能产生的11位余数、验证码,也保存成数组
    NSArray *idCardYArray = @[@"1", @"0", @"10", @"9", @"8", @"7", @"6", @"5", @"4", @"3", @"2"];
    
    //用来保存前17位各自乖以加权因子后的总和
    NSInteger idCardWiSum = 0;
    for(int i = 0;i < 17;i++) {
        NSInteger subStrIndex = [[identityCard substringWithRange:NSMakeRange(i, 1)] integerValue];
        NSInteger idCardWiIndex = [[idCardWiArray objectAtIndex:i] integerValue];
        idCardWiSum+= subStrIndex * idCardWiIndex;
    }
    
    //计算出校验码所在数组的位置
    NSInteger idCardMod=idCardWiSum%11;
    //得到最后一位身份证号码
    NSString *idCardLast= [identityCard substringWithRange:NSMakeRange(17, 1)];
    //如果等于2,则说明校验码是10,身份证号码最后一位应该是X
    if(idCardMod==2) {
        if(![idCardLast isEqualToString:@"X"]||[idCardLast isEqualToString:@"x"]) {
            return NO;
        }
    }
    else{
        //用计算出的验证码与最后一位身份证号码匹配,如果一致,说明通过,否则是无效的身份证号码
        if(![idCardLast isEqualToString: [idCardYArray objectAtIndex:idCardMod]]) {
            return NO;
        }
    }
    return YES;
    
//    BOOL flag;
//    if (identityCard.length <= 0) {
//        flag = NO;
//        return flag;
//    }
//    NSString *regex2 = @"^(\\d{14}|\\d{17})(\\d|[xX])$";
//    NSPredicate *identityCardPredicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",regex2];
//    return [identityCardPredicate evaluateWithObject:identityCard];
}


see also

更多资讯和服务请关注#小程序:iOS逆向,只为你呈现有价值的信息,专注于移动端技术研究领域。