1-2 省級行政區劃碼 3-4 地級市代碼 5-6 區縣代碼 7-14 出生日期(YYYYMMDD) 15-17 順序碼(奇男偶女) 18 校驗碼(0-9 或 X)
W = [7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2]S = Σ(ai × Wi)Y = S mod 11Y → 校驗碼:[1,0,X,9,8,7,6,5,4,3,2](索引 0-10)function calculateIdCardChecksum(string $id17): string {
// 1. 輸入驗證
if (strlen($id17) !== 17 || !ctype_digit($id17)) {
throw new InvalidArgumentException('身份證前 17 位必須為 17 位純數字');
}
// 2. 加權因子(固定)
$weights = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
// 3. 校驗碼映射表(索引 = Y 值)
$checkmap = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];
// 4. 計算加權和
$sum = 0;
for ($i = 0; $i < 17; $i++) {
$sum += (int)$id17[$i] * $weights[$i];
}
// 5. 模 11 取模
$mod = $sum % 11;
// 6. 返回校驗碼
return $checkmap[$mod];
}
// 使用示例
$id17 = '44010220000101001'; // 廣州市,2000-01-01 出生,順序碼 001
$check = calculateIdCardChecksum($id17);
echo "完整身份證號: {$id17}{$check}"; // 440102200001010019
function idCardChecksum(string $id17): string {
static $w = [7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2];
static $m = ['1','0','X','9','8','7','6','5','4','3','2'];
$sum = array_sum(array_map(fn($i) => (int)$id17[$i] * $w[$i], range(0,16)));
return $m[$sum % 11];
}
function validateIdCard(string $id18): bool {
// 1. 格式正則
if (!preg_match('/^[1-9]\d{5}(19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dX]$/i', $id18)) {
return false;
}
// 2. 地址碼校驗(需維護最新行政區劃碼庫)
$addrCode = substr($id18, 0, 6);
if (!in_array($addrCode, getValidAddrCodes())) { // 需實現數據源
return false;
}
// 3. 生日合法性
$birth = substr($id18, 6, 8);
$date = DateTime::createFromFormat('Ymd', $birth);
if (!$date || $date->format('Ymd') !== $birth) {
return false;
}
// 可選:年齡合理性(如 18-100 歲)
$age = (new DateTime())->diff($date)->y;
if ($age < 18 || $age > 100) return false;
// 4. 校驗碼
return calculateIdCardChecksum(substr($id18, 0, 17)) === strtoupper($id18[17]);
}
| 場景 | 用法 |
|---|---|
| 用戶註冊實名認證 | 前端輸入 18 位 → 後端 validateIdCard() 驗證 |
| 批量生成測試數據 | 隨機前 17 位 → calculateIdCardChecksum() 補全 |
| 舊系統 15 位升級 | 15 位無校驗碼,需補齊出生年千百位 + 重新計算校驗碼 |
| OCR 識別糾錯 | 識別結果校驗碼不匹配時,嘗試修正相似字符(8↔B, 0↔O, 1↔I) |
身份證校驗碼算法是 ISO 7064 MOD 11-2 標準在中國的具體應用。PHP 實現僅需 10 行核心代碼,關鍵在於:加權因子表固定、校驗碼映射表固定、模 11 運算。生產環境建議封裝為 IdCardValidator 類,引入行政區劃碼數據庫(定期更新),並配合 DateTime 做生日邏輯校驗,構建完整實名驗證鏈路。