package com.xmkgsy.utils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
/**
* 验证身份证真实性
*
* @Author: Aow
* @Created: 2024/5/2 10:50
*/
public class IDCardUtils {
public static Boolean verifyIdCard(String idCard) {
if (StringUtils.isEmpty(idCard)) {
return false;
}
// 处理香港身份证有括号
idCard = idCard.replace("(","");
idCard = idCard.replace("(","");
idCard = idCard.replace(")","");
idCard = idCard.replace(")","");
String[] idCardArr = idCard.split("");
if (idCardArr.length == 18) {
// 校验大陆身份证
return verifyIdCard(idCard, idCardArr);
} else if (idCardArr.length == 8) {
// 校验香港身份证
return verifyHKIdCard(idCardArr);
} else if (idCardArr.length == 10) {
// 校验台湾身份证
return verifyTWIdCard(idCard, idCardArr);
}
return false;
}
/**
* 校验大陆身份证
*
* 1、将身份证号码前面的17位数分别乘以不同的系数。从第一位到第十七位的系数分别为:7-9-10-5-8-4-2-1-6-3-7-9-10-5-8-4-2。
* 2、将这17位数字和系数相乘的结果相加。
* 3、用加出来和除以11,取余数。
* 4、余数只可能有0-1-2-3-4-5-6-7-8-9-10这11个数字。其分别对应的最后一位身份证的号码为1-0-X-9-8-7-6-5-4-3-2。
* 5、通过上面计算得知如果余数是3,第18位的校验码就是9。如果余数是2那么对应的校验码就是X,X实际是罗马数字10。
*/
private static Boolean verifyIdCard(String idCard, String[] idCardArr) {
String idCardSub = idCard.substring(0, 17);
if (!NumberUtils.isCreatable(idCardSub)) {
return false;
}
String[] idCardParam = "7-9-10-5-8-4-2-1-6-3-7-9-10-5-8-4-2".split("-");
String[] verifyNum = "1-0-X-9-8-7-6-5-4-3-2".split("-");
int result = 0;
for (int i = 0; i < 17; i++) {
result = result + Integer.parseInt(idCardArr[i]) * Integer.parseInt(idCardParam[i]);
}
int remainder = result % 11;
if (Objects.equals(idCardArr[17], verifyNum[remainder])) {
return true;
}
return false;
}
/**
* 校验香港身份证
*
* 香港身份证号码由三部分组成:一个英文字母;6个数字;括号及0-9中的任一个数字,或者字母A。
* 括号中的数字或字母A,是校验码,用于检验括号前面的号码的逻辑正确性。
* 逻辑关系:
* 先把首位字母改为数字,即A为1,B为2,C为3...Z为26,再乘以8;
* 然后把字母后面的6个数字依次乘以7、6、5、4、3、2;
* 再将以上所有乘积相加的和,除以11,得到余数;
* 如果整除,则括号中的校验码为0,如果余数为1,则校验码为A,如果余数为2~10,则用11减去这个余数的差作校验码。
*/
private static Boolean verifyHKIdCard(String[] idCardArr) {
String alphabet = "A、B、C、D、E、F、G、H、I、J、K、L、M、N、O、P、Q、R、S、T、U、V、W、X、Y、Z";
List<String> alphabetList = Arrays.asList(alphabet.split("、"));
String[] verifyNum = "8765432".split("");
int index = alphabetList.indexOf(idCardArr[0]) + 1;
int result = index * Integer.parseInt(verifyNum[0]);
for (int i = 1; i < 7; i++) {
result = result + Integer.parseInt(idCardArr[i]) * Integer.parseInt(verifyNum[i]);
}
int remainder = result % 11;
if (remainder > 1) {
remainder = 11 - remainder;
}
if (Objects.equals(remainder, Integer.parseInt(idCardArr[7]))) {
return true;
}
return false;
}
/**
* 校验台湾身份证
*
* 地区后面的数字为该字母转换的数字码。
* A-台北市-10 B-台中市-11 C-基隆市-12 D-台南市-13 E-高雄市-14 F-台北县-15
* G-宜兰县-16 H-桃园县-17 I-嘉义市-34 J-新竹县-18 K-苗栗县-19 L-台中县-20
* M-南投县-21 N-彰化县-22 O-新竹市-35 P-云林县-23 Q-嘉义县-24 R-台南县-25
* S-高雄县-26 T-屏东县-27 U-花莲县-28 V-台东县-29 W-金门县-30 X-澎湖县-31
* Y-阳明山-32 Z-连江县-33
* 把前9码所代表的数字列出来,再乘以他的加权数(10-1),再全部加起来,然后总和以10去除,
* 取余数之后以10来减那个余数之后得到的那个数字就是最后一个判别码;
* 第十位数字--验证码的计算规则为: 字母(ABCDEFGHJKLMNPQRSTUVXYWZI0)对应一组数(10--35)
*/
private static Boolean verifyTWIdCard(String idCard, String[] idCardArr) {
String[] idCardParam = "ABCDEFGHJKLMNPQRSTUVXYWZIO".split("");
List<String> idCardParamList = Arrays.asList(idCardParam);
int num = idCardParamList.indexOf(idCardArr[0]) + 10;
idCard = idCard.replace(idCardArr[0], num + "");
idCardArr = idCard.split("");
int result = Integer.parseInt(idCardArr[0]);
for (int i = 1; i < 10; i++){
result = result + Integer.parseInt(idCardArr[i]) * (10-i);
}
int remainder = 10 - result % 10;
if (Objects.equals(remainder, Integer.parseInt(idCardArr[10]))) {
return true;
}
return false;
}
}
大陆、香港、台湾身份证号码真实性校验
最新推荐文章于 2024-05-25 12:01:51 发布