PHP实现中国公民身份证号码有效性验证示例代码
本文将使用Java实现中国公民(15位或者18位)身份证号码的相关验证,功能如下:
- 身份证号有效性验证
- 分析详细身份证信息
- 生成一个虚拟的省份证号码。
身份证号码验证
1、号码的结构公民身份号码是特征组合码,由十七位数字本体码和一位校验码组成。排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。
2、地址码(前六位数)
表示编码对象常住户口所在县(市、旗、区)的行政区划代码,按GB/T2260的规定执行。
3、出生日期码(第七位至十四位)
表示编码对象出生的年、月、日,按GB/T7408的规定执行,年、月、日代码之间不用分隔符。
4、顺序码(第十五位至十七位)
表示在同一地址码所标识的区域范围内,对同年、同月、同日出生的人编定的顺序号,顺序码的奇数分配给男性,偶数分配给女性。
5、校验码(第十八位数)
(1)十七位数字本体码加权求和公式S=Sum(Ai*Wi),i=0,…,16,先对前17位数字的权求和
Ai:表示第i位置上的身份证号码数字值
Wi:表示第i位置上的加权因子Wi:7910584216379105842
(2)计算模Y=mod(S,11)
(3)通过模得到对应的校验码Y:012345678910校验码:10X98765432
IDValidator.php
checkArg($id);
if($code===false){
returnfalse;
}
//查询cache
if(isset(self::$cache[$id])&&self::$cache[$id]['valid']!==false){
returnself::$cache[$id]['valid'];
}else{
if(!isset(self::$cache[$id])){
self::$cache[$id]=array();
}
}
$addr=substr($code['body'],0,6);
$birth=$code['type']===18?substr($code['body'],6,8):
substr($code['body'],6,6);
$order=substr($code['body'],-3);
if(!(self::$util->checkAddr($addr)&&self::$util->checkBirth($birth)&&
self::$util->checkOrder($order))){
self::$cache[$id]['valid']=false;
returnfalse;
}
//15位不含校验码,到此已结束
if($code['type']===15){
self::$cache[$id]['valid']=true;
returntrue;
}
/*校验位部分*/
//位置加权
$posWeight=array();
for($i=18;$i>1;$i--){
$wei=self::$util->weight($i);
$posWeight[$i]=$wei;
}
//累加body部分与位置加权的积
$bodySum=0;
$bodyArr=str_split($code['body']);
for($j=0;$j10){
$checkBit=$checkBit%11;
}
//检查校验码
if($checkBit!=$code['checkBit']){
self::$cache[$id]['valid']=false;
returnfalse;
}else{
self::$cache[$id]['valid']=true;
returntrue;
}
}
//分析详细信息
functiongetInfo($id){
//号码必须有效
if($this->isValid($id)===false){
returnfalse;
}
//TODO复用此部分
$code=self::$util->checkArg($id);
//查询cache
//到此时通过isValid已经有了cache记录
if(isset(self::$cache[$id])&&isset(self::$cache[$id]['info'])){
returnself::$cache[$id]['info'];
}
$addr=substr($code['body'],0,6);
$birth=($code['type']===18?substr($code['body'],6,8):
substr($code['body'],6,6));
$order=substr($code['body'],-3);
$info=array();
$info['addrCode']=$addr;
if(self::$GB2260!==null){
$info['addr']=self::$util->getAddrInfo($addr);
}
$info['birth']=($code['type']===18?(substr($birth,0,4).'-'.substr($birth,4,2).'-'.substr($birth,-2)):('19'.substr($birth,0,2).'-'.substr($birth,2,2).'-'.substr($birth,-2)));
$info['sex']=($order%2===0?0:1);
$info['length']=$code['type'];
if($code['type']===18){
$info['checkBit']=$code['checkBit'];
}
//记录cache
self::$cache[$id]['info']=$info;
return$info;
}
//仿造一个号
functionmakeID($isFifteen=false){
//地址码
$addr=null;
if(self::$GB2260!==null){
$loopCnt=0;
while($addr===null){
//防止死循环
if($loopCnt>50){
$addr=110101;
break;
}
$prov=self::$util->str_pad(self::$util->rand(66),2,'0');
$city=self::$util->str_pad(self::$util->rand(20),2,'0');
$area=self::$util->str_pad(self::$util->rand(20),2,'0');
$addrTest=$prov.$city.$area;
if(isset(self::$GB2260[$addrTest])){
$addr=$addrTest;
break;
}
$loopCnt++;
}
}else{
$addr=110101;
}
//出生年
$yr=self::$util->str_pad(self::$util->rand(99,50),2,'0');
$mo=self::$util->str_pad(self::$util->rand(12,1),2,'0');
$da=self::$util->str_pad(self::$util->rand(28,1),2,'0');
if($isFifteen){
return$addr.$yr.$mo.$da
.self::$util->str_pad(self::$util->rand(999,1),3,'1');
}
$yr='19'.$yr;
$body=$addr.$yr.$mo.$da.self::$util->str_pad(self::$util->rand(999,1),3,'1');
//位置加权
$posWeight=array();
for($i=18;$i>1;$i--){
$wei=self::$util->weight($i);
$posWeight[$i]=$wei;
}
//累加body部分与位置加权的积
$bodySum=0;
$bodyArr=str_split($body);
for($j=0;$j10){
$checkBit=$checkBit%11;
}
return($body.$checkBit);
}
}
调用
makeID();
//获取身份证信息
$info=$v->getInfo($id);
var_dump($info);
//生成一个15位身份证号
$id=$v->makeID(true);
$info=$v->getInfo($id);
var_dump($info);
//验证身份证号是否正确
var_dump($v->isValid("123456789012345678"));
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。