PHP校驗15位和18位身份證號

2021-09-11 15:36:11 字數 4669 閱讀 5689

看新公司框架原始碼的時候,發現了這個功能,於是搜尋一番並封裝了一下身份證號校驗的類。

目前大家的身份證號大多是18位的,當然,也不排除有些老人的身份證號是15位的。

如果強制要求是18位的話,會比較好,因為15位的身份證號沒有校驗碼,可以說,只要了解大概結構,隨手都可以造出一系列身份證號碼來。

當然,如果只是單純的程式校驗,18位的身份證號碼也可以偽造,就是需要偽造者花點心思。

最好的還是呼叫相關部門給的介面,進行校驗。

15位:省份(2位) + 地級市(2位) + 縣級市(2位) + 出生年(2位) + 出生月(2位) + 出生日(2位) + 順序號(3位)

18位:省份(2位) + 地級市(2位) + 縣級市(2位) + 出生年(4位) + 出生月(2位) + 出生日(2位) + 順序號(3位) + 校驗位(1位)

相比之下,18位15位多出生年2位、校驗位1位

其中,順序號如果是偶數,則說明是女生,順序號是奇數,則說明是男生。

校驗位的計算:

有17位數字,分別是:

7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2

複製**

分別用身份證的前 17 位乘以上面相應位置的數字,然後相加。

接著用相加的和對 11 取模。

用獲得的值在下面 11 個字元裡查詢對應位置的字元,這個字元就是校驗位。

'1', '0', 'x', '9', '8', '7', '6', '5', '4', '3', '2'

複製**

15位轉18位:

從上述的分析中,可以知道,只要補充上年分和校驗位就可以了。

一般情況下年份補充都是加上19就可以了。

通過分析身份證號的規則,了解到,有幾點是可以做的:

當然,因為可能部分人用的是15位的身份證號,所以需要乙個轉換的方法,不過,這裡還是建議限制需要18位的身份證號。

下面開始實現:

初始化:

class

idcardfilter

// 將 15 位轉換成 18 位

$idcard = $this->fifteen2eighteen($idcard);

// 檢查省是否存在

if (!$this->checkprovince($idcard))

// 檢查生日是否正確

if (!$this->checkbirthday($idcard))

// 檢查校驗碼

return

$this->checkcode($idcard);

}}複製**

上面已經實現了乙個校驗的方法,裡面呼叫了類裡的很多方法,下面一一實現。

檢測是否是身份證號碼:

這一塊的處理比較簡單,乙個正規表示式搞定了。

其中,(^\d$)用於匹配15位身份證號的情況;(^\d(\d|x)$)用於匹配18位身份證號的情況。

const regx = '#(^\d$)|(^\d(\d|x)$)#';

/** * 檢測是否是身份證號碼

* * @param string $idcard

* @return boolean

*/public

function

iscardnumber

($idcard)

複製**

15位轉18位:

邏輯不複雜,先判斷是否是15位,然後判斷需要新增的年份,最終生成校驗碼拼接返回就ok了。

/**

* 15位轉18位

* * @param string $idcard

* @return void

*/public

function

fifteen2eighteen

($idcard)

// 如果身份證順序碼是996 997 998 999,這些是為百歲以上老人的特殊編碼

// $code = array_search(substr($idcard, 12, 3), [996, 997, 998, 999]) !== false ? '18' : '19';

// 一般 19 就夠了

$code = '19';

$idcardbase = substr($idcard, 0, 6) . $code . substr($idcard, 6, 9);

return $idcardbase . $this->gencode($idcardbase);

}複製**

校驗碼的生成:

詳細計算規則見上面,這裡就不做重複的闡述了。

/**

* 生成校驗碼

* * @param string $idcardbase

* @return void

*/final

protected

function

gencode

($idcardbase)

$factor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];

$verifynumbers = ['1', '0', 'x', '9', '8', '7', '6', '5', '4', '3', '2'];

$sum = 0;

for ($i = 0; $i < $idcardlength; $i++)

$index = $sum % 11;

return $verifynumbers[$index];

}複製**

檢查省份是否正確:

protected $provinces = [

11 => "北京", 12 => "天津", 13 => "河北", 14 => "山西", 15 => "內蒙古",

21 => "遼寧", 22 => "吉林", 23 => "黑龍江", 31 => "上海", 32 => "江蘇",

33 => "浙江", 34 => "安徽", 35 => "福建", 36 => "江西", 37 => "山東", 41 => "河南",

42 => "湖北", 43 => "湖南", 44 => "廣東", 45 => "廣西", 46 => "海南", 50 => "重慶",

51 => "四川", 52 => "貴州", 53 => "雲南", 54 => "**", 61 => "陝西", 62 => "甘肅",

63 => "青海", 64 => "寧夏", 65 => "新疆", 71 => "台灣", 81 => "香港", 82 => "澳門", 91 => "國外"

];/**

* 檢查省份是否正確

* * @param string $idcard

* @return void

*/public

function

checkprovince

($idcard)

複製**

檢測生日是否正確:

這裡也是用正則匹配,匹配出年月日的。

/**

* 檢測生日是否正確

* * @param string $idcard

* @return void

*/public

function

checkbirthday

($idcard)

(\d)(\d)(\d)\d[0-9x]$#';

if (!preg_match($regx, $idcard, $matches))

array_shift($matches);

list($year, $month, $day) = $matches;

return checkdate($month, $day, $year);

}複製**

校驗碼比對:

話說,15位18位的都完全不用考慮這個方法了。

/**

* 校驗碼比對

* * @param string $idcard

* @return void

*/public

function

checkcode

($idcard)

複製**

傳送門:idcardfilter

這個功能最多算是新穎吧,畢竟之前沒有接觸過。很開心**片段裡又增加了新的成員。

js 身份證校驗 15位和18位

校驗身份證號碼 function checkidcardno checkobj 校驗身份證號碼 function verifyidcardno idcardno else if idno.length 18 if18idcardno idno return false 15位身份證,只有數字 fun...

身份證15位公升18位

六位數字位址碼 八位數字出生日期碼 三位數字順序碼 順序碼的奇數分給男性,偶數分給女性 一位數字校驗碼 校驗碼是根據前面十七位數字碼,按照iso 7064 1983.mod 11 2校驗碼計算出來的檢驗碼 1 多了年數 第6位開始多了19表示完整的出生日期 2 多了最後一位校驗碼 ai wi mod...

15位身份證補全為18位身份證演算法

一 15位身份證和18位身份證號碼結構介紹 要進行身份證號碼的驗證,首先需要了解我國身份證號碼的編碼規則。我國身份證號碼多由若干位數字或者數字與字母混合組成。早期身份證由15位數字構成,這主要是在1980年以前發放的身份證,後來考慮到千年蟲問題,因為15位的身份證號碼只能為1900年1月1日到199...