原始代碼僅做簡單正則匹配,無法校驗地址碼合法性、出生日期真實性及校驗碼。下面提供生產級驗證函數。
function checkIdNumber(idCard) {
// 1. 非空檢查
if (!idCard) return { valid: false, msg: '身份證號不能為空' };
// 2. 格式正則(15/18 位)
const reg15 = /^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$/;
const reg18 = /^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}[\dXx]$/;
if (!reg15.test(idCard) && !reg18.test(idCard)) {
return { valid: false, msg: '身份證號格式錯誤' };
}
// 3. 統一轉 18 位
if (idCard.length === 15) {
idCard = idCard.slice(0, 6) + '19' + idCard.slice(6);
// 計算校驗碼...
}
// 4. 地址碼校驗(需維護有效地址碼列表)
const addrCode = idCard.slice(0, 6);
if (!validAddrCodes.includes(addrCode)) {
return { valid: false, msg: '地址碼無效' };
}
// 5. 出生日期校驗
const birth = idCard.slice(6, 14);
const year = parseInt(birth.slice(0, 4), 10);
const month = parseInt(birth.slice(4, 6), 10);
const day = parseInt(birth.slice(6, 8), 10);
const date = new Date(year, month - 1, day);
if (date.getFullYear() !== year || date.getMonth() !== month - 1 || date.getDate() !== day) {
return { valid: false, msg: '出生日期不合法' };
}
// 6. 校驗碼算法(ISO 7064:1983.MOD 11-2)
const weights = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
const checkCodes = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];
let sum = 0;
for (let i = 0; i < 17; i++) sum += parseInt(idChar[i]) * weights[i];
const expected = checkCodes[sum % 11];
if (idCard[17].toUpperCase() !== expected) {
return { valid: false, msg: '校驗碼錯誤' };
}
return { valid: true, msg: '驗證通過' };
}
function checkRealName(name) {
if (!name || !/^[\u4e00-\u9fa5]{2,20}$/.test(name)) {
return { valid: false, msg: '姓名必須為 2-20 位中文' };
}
return { valid: true };
}