package com.ruoyi.common.utils; import java.util.regex.Pattern; /** * 身份证号校验工具类 * * @author ruoyi */ public class IdCardUtil { /** * 18位身份证号正则表达式 */ private static final Pattern ID_CARD_PATTERN = Pattern.compile( "^[1-9]\\d{5}(18|19|20)\\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\\d|3[01])\\d{3}[\\dXx]$" ); /** * 身份证号加权因子 */ private static final int[] ID_CARD_WEIGHT = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2}; /** * 身份证号校验码对应值 */ private static final char[] ID_CARD_CHECK_CODE = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'}; /** * 校验身份证号格式 * * @param idCard 身份证号 * @return 是否有效 */ public static boolean isValid(String idCard) { if (StringUtils.isEmpty(idCard)) { return false; } // 基本格式校验 if (!ID_CARD_PATTERN.matcher(idCard).matches()) { return false; } // 校验码验证 return checkVerifyCode(idCard); } /** * 校验身份证校验码 * * @param idCard 身份证号 * @return 校验码是否正确 */ private static boolean checkVerifyCode(String idCard) { char[] chars = idCard.toCharArray(); int sum = 0; // 计算前17位与加权因子的乘积之和 for (int i = 0; i < 17; i++) { sum += (chars[i] - '0') * ID_CARD_WEIGHT[i]; } // 取模得到校验码索引 int checkCodeIndex = sum % 11; char expectedCheckCode = ID_CARD_CHECK_CODE[checkCodeIndex]; // 比较校验码(不区分大小写) return Character.toUpperCase(chars[17]) == expectedCheckCode; } /** * 获取校验错误信息 * * @param idCard 身份证号 * @return 错误信息,如果正确返回null */ public static String getErrorMessage(String idCard) { if (StringUtils.isEmpty(idCard)) { return "身份证号不能为空"; } if (idCard.length() != 18) { return "身份证号长度必须为18位"; } if (!ID_CARD_PATTERN.matcher(idCard).matches()) { return "身份证号格式不正确"; } if (!checkVerifyCode(idCard)) { return "身份证号校验码不正确"; } return null; } }