предисловие
Когда я просмотрел исходный код нового фреймворка компании, я нашел эту функцию, поэтому я искал и инкапсулировал класс для проверки идентификационного номера.
В настоящее время большинство идентификационных номеров18
Конечно, не исключено, что идентификационные номера некоторых пожилых людей15
немного.
Если обязательное требование18
бит, было бы лучше, потому что15
Бит ID номер не проверяет код, мы можем сказать, если мы можем понять структуру, мы можем легко создать серию номер удостоверения личности.
Конечно, если это простая проверка программы,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
{
/**
* 身份证号码校验
*
* @param string $idCard
* @return bool
*/
public function vaild($idCard)
{
// 基础的校验,校验身份证格式是否正确
if (!$this->isCardNumber($idCard)) {
return false;
}
// 将 15 位转换成 18 位
$idCard = $this->fifteen2Eighteen($idCard);
// 检查省是否存在
if (!$this->checkProvince($idCard)) {
return false;
}
// 检查生日是否正确
if (!$this->checkBirthday($idCard)) {
return false;
}
// 检查校验码
return $this->checkCode($idCard);
}
}
Выше был реализован метод проверки, который вызывает множество методов в классе, следующие реализованы один за другим.
Проверьте, является ли это идентификационным номером:
Обработка этой части относительно проста, и выполняется регулярное выражение.
в,(^\d{15}$)
для сопоставления15位
номер удостоверения личности;(^\d{17}(\d|X)$)
для сопоставления18位
Идентификационный номер.
const REGX = '#(^\d{15}$)|(^\d{17}(\d|X)$)#';
/**
* 检测是否是身份证号码
*
* @param string $idCard
* @return boolean
*/
public function isCardNumber($idCard)
{
return preg_match(self::REGX, $idCard);
}
15-бит на 18-бит:
Логика несложная: сначала определите, 15 ли это цифр, затем определите год, который нужно добавить, и, наконец, сгенерируйте контрольный код, и вставка его обратно будет в порядке.
/**
* 15位转18位
*
* @param string $idCard
* @return void
*/
public function fifteen2Eighteen($idCard)
{
if (strlen($idCard) != 15) {
return $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)
{
$idCardLength = strlen($idCardBase);
if ($idCardLength != 17) {
return false;
}
$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++) {
$sum += substr($idCardBase, $i, 1) * $factor[$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)
{
$provinceNumber = substr($idCard, 0, 2);
return isset($this->provinces[$provinceNumber]);
}
Проверьте правильность дня рождения:
Здесь также используется регулярное сопоставление для соответствия году, месяцу и дню.
/**
* 检测生日是否正确
*
* @param string $idCard
* @return void
*/
public function checkBirthday($idCard)
{
$regx = '#^\d{6}(\d{4})(\d{2})(\d{2})\d{3}[0-9X]$#';
if (!preg_match($regx, $idCard, $matches)) {
return false;
}
array_shift($matches);
list($year, $month, $day) = $matches;
return checkdate($month, $day, $year);
}
Проверить сравнение кода:
Сказать,15位
изменять18位
Этот метод вообще не нужно рассматривать.
/**
* 校验码比对
*
* @param string $idCard
* @return void
*/
public function checkCode($idCard)
{
$idCardBase = substr($idCard, 0, 17);
$code = $this->genCode($idCardBase);
return $idCard == ($idCardBase . $code);
}
полный код
Портал:IDCardFilter
Наконец
Эта функция в лучшем случае новая, в конце концов, ее раньше никто не трогал. Я очень рад, что во фрагмент кода добавлен новый участник.
-- ЭОФ -- Эта статья воспроизведена изIMJCWОригинальная ссылка:PHP проверяет 15-значный и 18-значный идентификационный номер