Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package demo.tool;
- import java.text.ParseException;
- import java.text.SimpleDateFormat;
- import java.util.Date;
- import java.util.HashMap;
- import java.util.Map;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import demo.constants.Gender;
- import demo.exception.InvalidParameterException;
- import demo.entity.IDCertNoValidateResult;
- public class IDCertNoTool {
- private static final Logger LOGGER = LoggerFactory.getLogger(IDCertNoTool.class);
- public static final String INVALID_FIELD_NAME_CERT_NO = "certNo";
- public static final String INVALID_FIELD_NAME_AREA_CODE = "areaCode";
- public static final String INVALID_FIELD_NAME_BIRTHDAY = "birthday";
- public static final String INVALID_FIELD_NAME_CHECK_CHAR = "checkChar";
- public static final String INVALID_FIELD_NAME_GENDER = "gender";
- private final static char[] PARITYBIT = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'};
- private final static int[] POWER_LIST = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
- private final static SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyyMMddHHmmssSSS") {
- private static final long serialVersionUID = 1L;
- {
- this.setLenient(false);
- }
- };
- private final static String BIRTHDAY_PADDING = "000000000";
- private final static Map<String, String> ZONE_NUMBER = new HashMap<String, String>() {
- private static final long serialVersionUID = 1L;
- {
- this.put("11", "北京");
- this.put("12", "天津");
- this.put("13", "河北");
- this.put("14", "山西");
- this.put("15", "内蒙古");
- this.put("21", "辽宁");
- this.put("22", "吉林");
- this.put("23", "黑龙江");
- this.put("31", "上海");
- this.put("32", "江苏");
- this.put("33", "浙江");
- this.put("34", "安徽");
- this.put("35", "福建");
- this.put("36", "江西");
- this.put("37", "山东");
- this.put("41", "河南");
- this.put("42", "湖北");
- this.put("43", "湖南");
- this.put("44", "广东");
- this.put("45", "广西");
- this.put("46", "海南");
- this.put("50", "重庆");
- this.put("51", "四川");
- this.put("52", "贵州");
- this.put("53", "云南");
- this.put("54", "西藏");
- this.put("61", "陕西");
- this.put("62", "甘肃");
- this.put("63", "青海");
- this.put("64", "宁夏");
- this.put("65", "新疆");
- this.put("71", "台湾");
- this.put("81", "香港");
- this.put("82", "澳门");
- this.put("91", "外国");
- }
- };
- public static enum IDCertNoType {
- OLD(15),
- NEW(18);
- private int length;
- private IDCertNoType(int length) {
- this.length = length;
- }
- public int getLength() {
- return length;
- }
- public static IDCertNoType resolve(int length) {
- for (IDCertNoType role : values()) {
- if (role.getLength() == length) {
- return role;
- }
- }
- throw new IllegalArgumentException("unknown cert number type for length: " + length);
- }
- }
- /**
- * 身份证验证,验证通过,返回性别和出生日期
- *
- * @param certNo 号码内容
- * @return 身份证中包含的性别和生日信息
- */
- public static IDCertNoValidateResult validate(String certNo) throws InvalidParameterException {
- char[] chars = certNo.toCharArray();
- int certNoLength = chars.length;
- IDCertNoType certNoType = null;
- try {
- certNoType = IDCertNoType.resolve(certNoLength);
- } catch (Exception e) {
- String msg = "invalid cert number length: " + certNoLength;
- LOGGER.error(msg);
- Map<String, String> errorDesc = new HashMap<>();
- errorDesc.put(INVALID_FIELD_NAME_CERT_NO, msg);
- throw new InvalidParameterException(errorDesc);
- }
- switch (certNoType) {
- case OLD:
- return validateOldCertNo(chars);
- case NEW:
- return validateNewCertNo(chars);
- default: {
- String msg = "unsupported IDCertNoType: " + certNoType;
- LOGGER.error(msg);
- Map<String, String> errorDesc = new HashMap<>();
- errorDesc.put(INVALID_FIELD_NAME_CERT_NO, msg);
- throw new InvalidParameterException(errorDesc);
- }
- }
- }
- private static IDCertNoValidateResult validateNewCertNo(char[] chars) throws InvalidParameterException {
- checkAreaCode(chars, 0, 6);
- String birthdayStr = new String(chars, 6, 8) + BIRTHDAY_PADDING;
- Date birthday = parseBirthday(birthdayStr);
- Gender gender = parseGender(chars[16]);
- validateCheckChar(chars);
- return new IDCertNoValidateResult(gender, birthday);
- }
- /**
- * 校验旧版身份证号,这里在处理年龄时,会根据年龄位进行判断,若是"0x"则补充为"200x",否则补充为"19xx"。
- *
- * @param certNo 旧版身份证号
- * @return
- * @throws InvalidParameterException
- */
- private static IDCertNoValidateResult validateOldCertNo(char[] chars) throws InvalidParameterException {
- checkAreaCode(chars, 0, 6);
- StringBuilder birthdayBuilder = new StringBuilder();
- char firstBirthdayChar = chars[6];
- switch (firstBirthdayChar) {
- case '0':
- birthdayBuilder.append("20").append(chars, 6, 6).append(BIRTHDAY_PADDING);
- break;
- default:
- birthdayBuilder.append("19").append(chars, 6, 6).append(BIRTHDAY_PADDING);
- break;
- }
- Date birthday = parseBirthday(birthdayBuilder.toString());
- Gender gender = parseGender(chars[14]);
- return new IDCertNoValidateResult(gender, birthday);
- }
- private static void checkAreaCode(char[] chars, int startIndex, int length)
- throws InvalidParameterException {
- String areaCode = new String(chars, startIndex, 2);
- if (!ZONE_NUMBER.containsKey(areaCode)) {
- String msg = "parse area code failed: " + areaCode;
- LOGGER.error(msg);
- Map<String, String> errorDesc = new HashMap<>();
- errorDesc.put(INVALID_FIELD_NAME_AREA_CODE, msg);
- throw new InvalidParameterException(errorDesc);
- }
- }
- private static Date parseBirthday(String birthdayStr) throws InvalidParameterException {
- Date birthday = null;
- try {
- birthday = DATE_FORMAT.parse(birthdayStr);
- } catch (ParseException e) {
- String msg = "parse birthday failed: " + birthdayStr;
- LOGGER.error(msg);
- Map<String, String> errorDesc = new HashMap<>();
- errorDesc.put(INVALID_FIELD_NAME_BIRTHDAY, msg);
- throw new InvalidParameterException(errorDesc);
- }
- return birthday;
- }
- private static Gender parseGender(char genderChar) throws InvalidParameterException {
- if ((genderChar < '0') || (genderChar > '9')) {
- String msg = "parse gender failed: " + genderChar;
- LOGGER.error(msg);
- Map<String, String> errorDesc = new HashMap<>();
- errorDesc.put(INVALID_FIELD_NAME_GENDER, msg);
- throw new InvalidParameterException(errorDesc);
- }
- if (((genderChar - '0') & 1) == 0) {
- return Gender.F;
- } else {
- return Gender.M;
- }
- }
- private static void validateCheckChar(char[] chars) throws InvalidParameterException {
- char computedCheckChar = computeCheckChar(chars, 0, 17);
- char targetCheckChar = chars[17];
- if (computedCheckChar != targetCheckChar) {
- String msg = "validate check char failed: " + targetCheckChar;
- LOGGER.error(msg);
- Map<String, String> errorDesc = new HashMap<>();
- errorDesc.put(INVALID_FIELD_NAME_CHECK_CHAR, msg);
- throw new InvalidParameterException(errorDesc);
- }
- }
- private static char computeCheckChar(char[] chars, int startIndex, int length) {
- int checkSum = 0;
- for (int i = 0; i < length; i++) {
- char c = chars[startIndex + i];
- checkSum += (c - '0') * POWER_LIST[i];
- }
- int checkCharIndex = checkSum % 11;
- char checkChar = PARITYBIT[checkCharIndex];
- return checkChar;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement