引言
- 需求背景: 进件风险控制强化(IOS)
通过身份证号码提取法人出生年月日,与当前日进行比较,如<18周岁, 则提示“法人未满18周岁,禁止进件!”
- 处理流程:
如果符合身份证规则,再进一步判断是否大于等于18岁,如<18周岁, 则提示“法人未满18周岁,禁止进件!”
I 定义工具类 IdentityCardTool进行身份证校验
【校验年龄、校验是否符合身份证号生成规则】
1.1 身份证号判断
- 中国大陆个人身份证号验证 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];
}
1.2 根据身份证获取生日
// 根据身份证获取生日
+ (NSString *)birthdayStrFromIdentityCard:(NSString *)numberStr{
NSMutableString *result = [NSMutableString stringWithCapacity:0];
NSString *year = nil;
NSString *month = nil;
BOOL isAllNumber = YES;
NSString *day = nil;
if([numberStr length]<14)
return result;
if ([numberStr length]==18) {
//**从第6位开始 截取8个数
NSString *fontNumer = [numberStr substringWithRange:NSMakeRange(6, 8)];
//**检测前12位否全都是数字;
const char *str = [fontNumer UTF8String];
const char *p = str;
while (*p!='\0') {
if(!(*p>='0'&&*p<='9'))
isAllNumber = NO;
p++;
}
if(!isAllNumber)
return result;
// year = [NSString stringWithFormat:@"19%@",[numberStr substringWithRange:NSMakeRange(8, 2)]];
year = [numberStr substringWithRange:NSMakeRange(6, 4)];
NSLog(@"year ==%@",year);
month = [numberStr substringWithRange:NSMakeRange(10, 2)];
// NSLog(@"month ==%@",month);
day = [numberStr substringWithRange:NSMakeRange(12,2)];
// NSLog(@"day==%@",day);
[result appendString:year];
[result appendString:@"-"];
[result appendString:month];
[result appendString:@"-"];
[result appendString:day];
// NSLog(@"result===%@",result);
return result;
}else{
NSString *fontNumer = [numberStr substringWithRange:NSMakeRange(0, 11)];
//**检测前14位否全都是数字;
const char *str = [fontNumer UTF8String];
const char *p = str;
while (*p!='\0') {
if(!(*p>='0'&&*p<='9'))
isAllNumber = NO;
p++;
}
if(!isAllNumber)
return result;
year = [numberStr substringWithRange:NSMakeRange(6, 2)];
month = [numberStr substringWithRange:NSMakeRange(8, 2)];
day = [numberStr substringWithRange:NSMakeRange(10,2)];
NSString* resultAll = [NSString stringWithFormat:@"19%@-%@-%@",year,month,day];
return resultAll;
}
}
//根据身份证号获取生日
+(NSString *)birthdayStrFromIdentityCard18:(NSString *)numberStr
{
NSMutableString *result = [NSMutableString stringWithCapacity:0];
NSString *year = nil;
NSString *month = nil;
BOOL isAllNumber = YES;
NSString *day = nil;
if([numberStr length]<14)
return result;
//**截取前14位
NSString *fontNumer = [numberStr substringWithRange:NSMakeRange(0, 13)];
//**检测前14位否全都是数字;
const char *str = [fontNumer UTF8String];
const char *p = str;
while (*p!='\0') {
if(!(*p>='0'&&*p<='9'))
isAllNumber = NO;
p++;
}
if(!isAllNumber)
return result;
year = [numberStr substringWithRange:NSMakeRange(6, 4)];
month = [numberStr substringWithRange:NSMakeRange(10, 2)];
day = [numberStr substringWithRange:NSMakeRange(12,2)];
[result appendString:year];
[result appendString:@"-"];
[result appendString:month];
[result appendString:@"-"];
[result appendString:day];
return result;
}
1.3 从生日上获取年龄
/**
从身份证上获取年龄
*/
+ (NSString *)getIdentityCardAge:(NSString *)numberStr {
NSDateFormatter *formatterTow = [[NSDateFormatter alloc]init];
[formatterTow setDateFormat:@"yyyy-MM-dd"];
NSString* birthday = [self birthdayStrFromIdentityCard:numberStr];
NSLog(@"birthday :%@",birthday);
NSDate *bsyDate = [formatterTow dateFromString:birthday];
NSTimeInterval dateDiff = [bsyDate timeIntervalSinceNow];
int age = trunc(dateDiff/(60*60*24))/365;
return [NSString stringWithFormat:@"%d",-age];
}
1.4 判断是否小于18岁
+ (BOOL )isAgeLower18:(NSString *)numberStr {
NSString *age = [CRMIdentityCardTool getIdentityCardAge:numberStr];
NSLog(@"%@", [NSString stringWithFormat:@"%@%@",@"校验年龄",age]);
if(age.doubleValue< 18){
return YES;
}
return NO;
}
II 应用
2.1 用法举例
if (![CRMIdentityCardTool validateIdentityCard:_frCardTextF.text] ) {
return [SVProgressHUD showInfoWithStatus:@"请输入正确的法人证件号码"];
}// 如果符合身份证规则,再进一步判断是否大于等于18岁,如<18周岁, 则提示“法人未满18周岁,禁止进件!”
else{
if([CRMIdentityCardTool isAgeLower18:_frCardTextF.text]){
return [SVProgressHUD showInfoWithStatus:@"法人未满18周岁,禁止进件!"];
}
}
2.2 测试验证
11010120050307505X
110101200503070371
110101200503078170
110101200503074815
110101200503075754
see also
iOS 银行卡号有效性校验Luhn算法 (银行卡号码校验算法) & 身份证校验:【校验年龄、校验是否符合身份证号生成规则】