首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 計算身份證校驗碼(第 18 位)標準算法實現

     編輯:PHP 綜合知識

身份證號碼結構(GB 11643-1999)

1-2  省級行政區劃碼
3-4  地級市代碼
5-6  區縣代碼
7-14 出生日期(YYYYMMDD)
15-17 順序碼(奇男偶女)
18   校驗碼(0-9 或 X)

校驗碼算法(ISO 7064:1983.MOD 11-2)

  1. 前 17 位數字分別乘以加權因子 W = [7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2]
  2. 求乘積和 S = Σ(ai × Wi)
  3. 計算模值 Y = S mod 11
  4. 查表映射 Y → 校驗碼:[1,0,X,9,8,7,6,5,4,3,2](索引 0-10)

PHP 完整實現

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 做生日邏輯校驗,構建完整實名驗證鏈路。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved