Realize the conversion from 15-digit to 18-digit ID numbers, and verify the Mainland China Resident ID Card, Hong Kong Resident ID Card, Macau ID Card and Taiwan ID Card.
- /**
- * ID card tools
- *
- * @author Tongle Xu 2013-6-6
- * @copyright Copyright (c) 2003-2103 tintsoft.com
- * @license http://www .tintsoft.com
- * @version $Id$
- */
- class Utils_Idcard {
- /**
- * Minimum length of Chinese citizen ID number.
- */
- const CHINA_ID_MIN_LENGTH = 15;
-
- /**
- * Maximum length of Chinese citizen ID number .
- */
- const CHINA_ID_MAX_LENGTH = 18;
-
- /**
- * Minimum years
- */
- const MIN = 1930;
-
- /**
- *Province and municipality code table
- */
- public static $cityCode = array ("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" );
-
- /**
- * Weighting factor per bit
- */
- public static $power = array (7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2 );
-
- /**
- * The 18th digit of the check code
- */
- public static $verifyCode = array ("1","0","X","9","8","7","6","5","4","3","2" );
- /**
- *Domestic ID card verification
- */
- public static $cityCodes = array ('11' => '北京' );
-
- /**
- * Convert 15-digit ID number to 18 digits
- *
- * @param idCard 15-digit identity code
- * @return 18-digit identity code
- */
- public static function conver15CardTo18($idCard) {
- $idCard18 = "";
- if (strlen ( $idCard ) != self::CHINA_ID_MIN_LENGTH) {
- return null;
- }
- if (self::isNum ( $idCard )) {
- // 获取出生年月日
- $sYear = '19' . substr ( $idCard, 6, 2 );
- $idCard18 = substr ( $idCard, 0, 6 ) . $sYear . substr ( $idCard, 8 );
- // 转换字符数组
- $iArr = str_split ( $idCard18 );
- if ($iArr != null) {
- $iSum17 = self::getPowerSum ( $iArr );
- // 获取校验位
- $sVal = self::getCheckCode18 ( $iSum17 );
- if (strlen ( $sVal ) > 0) {
- $idCard18 .= $sVal;
- } else {
- return null;
- }
- }
- } else {
- return null;
- }
- return $idCard18;
- }
-
- /**
- * Verify whether the ID card is legal
- */
- public static function validateCard($idCard) {
- $card = trim ( $idCard );
- if (self::validateIdCard18 ( $card )) {
- return true;
- }
- if (self::validateIdCard15 ( $card )) {
- return true;
- }
- return false;
- }
-
- /**
- * Verify whether the 18-digit identity code is legal
- *
- * @param int $idCard identity code
- * @return boolean whether it is legal
- */
- public static function validateIdCard18($idCard) {
- $bTrue = false;
- if (strlen ( $idCard ) == self::CHINA_ID_MAX_LENGTH) {
- // 前17位
- $code17 = substr ( $idCard, 0, 17 );
- // 第18位
- $code18 = substr ( $idCard, 17, 1 );
- if (self::isNum ( $code17 )) {
- $iArr = str_split ( $code17 );
- if ($iArr != null) {
- $iSum17 = self::getPowerSum ( $iArr );
- // 获取校验位
- $val = self::getCheckCode18 ( $iSum17 );
- if (strlen ( $val ) > 0 && $val == $code18) {
- $bTrue = true;
- }
- }
- }
- }
- return $bTrue;
- }
-
- /**
- * Verify whether the 15-digit identity code is legal
- *
- * @param string $idCard identity code
- * @return boolean whether it is legal
- */
- public static function validateIdCard15($idCard) {
- if (strlen ( $idCard ) != self::CHINA_ID_MIN_LENGTH) {
- return false;
- }
- if (self::isNum ( $idCard )) {
- $proCode = substr ( $idCard, 0, 2 );
- if (! isset ( self::$cityCodes [$proCode] )) {
- return false;
- }
- //升到18位
- $idCard = self::conver15CardTo18($idCard);
- return self::validateIdCard18($idCard);
- } else {
- return false;
- }
- return true;
- }
-
- /**
- * Get age based on ID number
- *
- * @param string idCard ID number
- * @return age
- */
- public static function getAgeByIdCard($idCard) {
- $iAge = 0;
- if (strlen ( $idCard ) == self::CHINA_ID_MIN_LENGTH) {
- $idCard = self::conver15CardTo18 ( $idCard );
- }
- $year = substr ( $idCard, 6, 4 );
- $iCurrYear = date ( 'Y', time () );
- $iAge = $iCurrYear - $year;
- return $iAge;
- }
-
- /**
- * Get the birthday based on the identity number
- *
- * @param string $idCard identity number
- * @return NULL string
- */
- public static function getDateByIdCard($idCard) {
- $len = strlen ( $idCard );
- if ($len < self::CHINA_ID_MIN_LENGTH) {
- return null;
- } else if ($len == CHINA_ID_MIN_LENGTH) {
- $idCard = self::conver15CardTo18 ( $idCard );
- }
- return substr ( $idCard, 12, 2 );
- }
- /**
- * Get gender based on identity number
- *
- * @param string $idCard identity number
- * @return gender (M-male, F-female, N-unknown)
- */
- public static function getGenderByIdCard($idCard) {
- $sGender = "N";
- if (strlen ( $idCard ) == self::CHINA_ID_MIN_LENGTH) {
- $idCard = self::conver15CardTo18 ( $idCard );
- }
- $sCardNum = substr ( $idCard, 16, 1 );
- if (( int ) $sCardNum % 2 != 0) {
- $sGender = "M";
- } else {
- $sGender = "F";
- }
- return $sGender;
- }
- /**
- * Get the province of household registration based on the identity number
- *
- * @param string $idCard identity number
- * @return string
- */
- public static function getProvinceByIdCard($idCard) {
- $len = strlen ( $idCard );
- $sProvince = null;
- $sProvinNum = "";
- if ($len == self::CHINA_ID_MIN_LENGTH || $len == self::CHINA_ID_MAX_LENGTH) {
- $sProvinNum = substr ( $idCard, 0, 2 );
- }
- $sProvince = self::$cityCodes [$sProvinNum];
- return $sProvince;
- }
- /**
- *Number verification
- *
- * @param int $val
- */
- public static function isNum($val) {
- return $val == null || $val == "" ? false : 0 < preg_match ( '/^[0-9]*$/', $val );
- }
- /**
- * Verify whether a date smaller than the current date is valid
- *
- * @param int $iYear Date to be verified (year)
- * @param int $iMonth Date to be verified (month 1-12)
- * @param int $iDate Date to be verified ( Day)
- * @return Is it valid
- */
- public static function valiDate($iYear, $iMonth, $iDate) {
- $year = date ( 'Y', time () );
- if ($iYear < self::MIN || $iYear >= $year) {
- return false;
- }
- if ($iMonth < 1 || $iMonth > 12) {
- return false;
- }
- switch ($iMonth) {
- case 4 :
- case 6 :
- case 9 :
- case 11 :
- $datePerMonth = 30;
- break;
- case 2 :
- $dm = (($iYear % 4 == 0 && $iYear % 100 != 0) || ($iYear % 400 == 0)) && ($iYear > self::MIN && $iYear < $year);
- $datePerMonth = $dm ? 29 : 28;
- break;
- default :
- $datePerMonth = 31;
- }
- return ($iDate >= 1) && ($iDate <= $datePerMonth);
- }
-
- /**
- * After multiplying each bit of the ID card and the weighting factor of the corresponding bit, the sum value is obtained
- *
- * @param array $iArr
- * @return ID code.
- */
- private static function getPowerSum($iArr) {
- $iSum = 0;
- $power_len = count ( self::$power );
- $iarr_len = count ( $iArr );
- if ($power_len == $iarr_len) {
- for($i = 0; $i < $iarr_len; $i ++) {
- for($j = 0; $j < $power_len; $j ++) {
- if ($i == $j) {
- $iSum = $iSum + $iArr [$i] * self::$power [$j];
- }
- }
- }
- }
- return $iSum;
- }
-
- /**
- * Take the power sum value modulo 11 to get the remainder for check digit judgment
- *
- * @param int $iSum
- * @return check digit
- */
- private static function getCheckCode18($iSum) {
- $sCode = "";
- switch ($iSum % 11) {
- case 10 :
- $sCode = "2";
- break;
- case 9 :
- $sCode = "3";
- break;
- case 8 :
- $sCode = "4";
- break;
- case 7 :
- $sCode = "5";
- break;
- case 6 :
- $sCode = "6";
- break;
- case 5 :
- $sCode = "7";
- break;
- case 4 :
- $sCode = "8";
- break;
- case 3 :
- $sCode = "9";
- break;
- case 2 :
- $sCode = "x";
- break;
- case 1 :
- $sCode = "0";
- break;
- case 0 :
- $sCode = "1";
- break;
- }
- return $sCode;
- }
- }
复制代码
- /**
- * ID card tools
- *
- * @author Tongle Xu 2013-6-6
- * @copyright Copyright (c) 2003-2103 tintsoft.com
- * @license http://www .tintsoft.com
- * @version $Id$
- */
- class Utils_Idcard {
- /**
- * Minimum length of Chinese citizen ID number.
- */
- const CHINA_ID_MIN_LENGTH = 15;
-
- /**
- * Maximum length of Chinese citizen ID number .
- */
- const CHINA_ID_MAX_LENGTH = 18;
-
- /**
- * Minimum years
- */
- const MIN = 1930;
-
- /**
- *Province and municipality code table
- */
- public static $cityCode = array ("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" );
-
- /**
- * Weighting factor per bit
- */
- public static $power = array (7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2 );
-
- /**
- * The 18th digit of the check code
- */
- public static $verifyCode = array ("1","0","X","9","8","7","6","5","4","3","2" );
- /**
- *Domestic ID card verification
- */
- public static $cityCodes = array ('11' => 'Beijing','12' => 'Tianjin','13' => 'Hebei','14' => 'Shanxi','15' => 'Inner Mongolia','21' => 'Liaoning','22' => 'Jilin','23' => 'Heilongjiang','31' => 'Shanghai','32' => 'Jiangsu','33' => 'Zhejiang','34' => 'Anhui','35' => 'Fujian','36' => 'Jiangxi','37' => 'Shandong','41' => 'Henan','42' => 'Hubei','43' => 'Hunan','44' => 'Guangdong','45' => 'Guangxi',
- '46' => 'Hainan','50' => 'Chongqing','51' => 'Sichuan','52 ' => 'Guizhou','53' => 'Yunnan','54' => 'Tibet','61' => 'Shaanxi','62' => 'Gansu','15 ' => 'Inner Mongolia','21' => 'Liaoning','22' => 'Jilin','23' => 'Heilongjiang','31' => 'Shanghai','32 ' => 'Jiangsu','33' => 'Zhejiang','34' => 'Anhui','35' => 'Fujian','36' => 'Jiangxi','37 ' => 'Shandong','41' => 'Henan','42' => 'Hubei','43' => 'Hunan',
- '44' => 'Guangdong',' 45' => 'Guangxi','46' => 'Hainan','50' => 'Chongqing','51' => 'Sichuan','52' => 'Guizhou',' 53' => 'Yunnan','54' => 'Tibet','61' => 'Shaanxi','62' => 'Gansu','63' => 'Qinghai',' 64' => 'Ningxia','65' => 'Xinjiang','71' => 'Taiwan','81' => 'Hong Kong','82' => 'Macau',' 91' => 'Overseas','63' => 'Qinghai','64' => 'Ningxia','65' => 'Xinjiang','71' => 'Taiwan',' 81' => 'Hong Kong',
- '82' => 'Macau','91' => 'Abroad' );
-
- /**
- *Taiwan ID card verification
- *
- * @var array
- */
- public static $twFirstCode = array (' A' => 10,'B' => 11,'C' => 12,'D' => 13,'E' => 14,'F' => 15,'G' => 16,'H' => 17,'J' => 18,'K' => 19,'L' => 20,'M' => 21,'N' => ; 22,'P' => 23,'Q' => 24,'R' => 25,'S' => 26,'T' => 27,'U' => 28 ,'V' => 29,'X' => 30,'Y' => 31,'W' => 32,'Z' => 33,'I' => 34,' O' => 35 );
-
- /**
- * Hong Kong ID card verification
- */
- public static $hkFirstCode = array ('A' => 1,'B' => 2,'C' => 3, 'R' => 18,'U' => 21,'Z' => 26,'X' => 24,'W' => 23,'O' => 15,'N ' => 14 );
-
- /**
- * Convert 15-digit ID number to 18 digits
- *
- * @param idCard 15-digit identity code
- * @return 18-digit identity code
- */
- public static function conver15CardTo18($idCard) {
- $idCard18 = "";
- if (strlen ( $idCard ) != self::CHINA_ID_MIN_LENGTH) {
- return null;
- }
- if (self::isNum ( $idCard )) {
- // Get the year, month and day of birth
- $sYear = '19' . substr ( $idCard, 6, 2 );
- $idCard18 = substr ( $idCard, 0, 6 ) . $sYear . substr ( $idCard, 8 );
- // Convert character array
- $iArr = str_split ( $idCard18 );
- if ($iArr != null) {
- $iSum17 = self::getPowerSum ( $iArr );
- // Get the check digit
- $sVal = self::getCheckCode18 ( $iSum17 );
- if (strlen ( $sVal ) > 0) {
- $idCard18 .= $sVal;
- } else {
- return null;
- }
- }
- } else {
- return null;
- }
- return $idCard18;
- }
-
- /**
- * Verify whether the ID card is legal
- */
- public static function validateCard($idCard) {
- $card = trim ( $idCard );
- if (self::validateIdCard18 ( $card )) {
- return true;
- }
- if (self::validateIdCard15 ( $card )) {
- return true;
- }
- $cardval = self::validateIdCard10 ( $card );
- if ($cardval != null) {
- if ($cardval [2] == "true") {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Verify whether the 18-digit identity code is legal
- *
- * @param int $idCard identity code
- * @return boolean whether it is legal
- */
- public static function validateIdCard18($idCard) {
- $bTrue = false;
- if (strlen ( $idCard ) == self::CHINA_ID_MAX_LENGTH) {
- // 前17位
- $code17 = substr ( $idCard, 0, 17 );
- // 第18位
- $code18 = substr ( $idCard, 17, 1 );
- if (self::isNum ( $code17 )) {
- $iArr = str_split ( $code17 );
- if ($iArr != null) {
- $iSum17 = self::getPowerSum ( $iArr );
- // 获取校验位
- $val = self::getCheckCode18 ( $iSum17 );
- if (strlen ( $val ) > 0 && $val == $code18) {
- $bTrue = true;
- }
- }
- }
- }
- return $bTrue;
- }
-
- /**
- * Verify whether the 15-digit identity code is legal
- *
- * @param string $idCard identity code
- * @return boolean whether it is legal
- */
- public static function validateIdCard15($idCard) {
- if (strlen ( $idCard ) != self::CHINA_ID_MIN_LENGTH) {
- return false;
- }
- if (self::isNum ( $idCard )) {
- $proCode = substr ( $idCard, 0, 2 );
- if (! isset ( self::$cityCodes [$proCode] )) {
- return false;
- }
- // 升到18位
- $idCard = self::conver15CardTo18 ( $idCard );
- return self::validateIdCard18 ( $idCard );
- } else {
- return false;
- }
- return true;
- }
-
- /**
- * Verify whether the 10-digit identity code is legal
- *
- * @param idCard identity code
- * @return ID card information array
- * [0] - Taiwan, Macau, Hong Kong [1] - Gender (Male M, Female F, unknown N) [2] - Is it legal (legal true, not legal false)
- * If it is not an ID number, return null
- *
- */
- public static function validateIdCard10($idCard) {
- $info = array ();
- $card = str_replace ( "[\(|\)]", "", $card );
- $len = strlen ( $card );
- if ($len != 8 && $len != 9 && $len != 10) {
- return null;
- }
- if (0 < preg_match ( "/^[a-zA-Z][0-9]{9}$/", $idCard )) { // 台湾
- $info [0] = "台湾";
- $char2 = substr ( $idCard, 1, 1 );
- if ($char2 == "1") {
- $info [1] = "M";
- } else if ($char2 == "2") {
- $info [1] = "F";
- } else {
- $info [1] = "N";
- $info [2] = "false";
- return $info;
- }
- $info [2] = self::validateTWCard ( $idCard ) ? "true" : "false";
- } else if (0 < preg_match ( "/^[1|5|7][0-9]{6}\(?[0-9A-Z]\)?$/", $idCard )) { // 澳门
- $info [0] = "澳门";
- $info [1] = "N";
- // TODO
- } else if (0 < preg_match ( "/^[A-Z]{1,2}[0-9]{6}\(?[0-9A]\)?$/", $idCard )) { // 香港
- $info [0] = "香港";
- $info [1] = "N";
- $info [2] = self::validateHKCard ( $idCard ) ? "true" : "false";
- } else {
- return null;
- }
- return info;
- }
-
- /**
- * Verify Taiwan ID card number
- *
- * @param string idCard ID card number
- * @return Verification code is consistent
- */
- public static function validateTWCard($idCard) {
- $start = substr ( $idCard, 0, 1 );
- $mid = substr ( $idCard, 1, 8 );
- $end = substr ( $idCard, 9, 1 );
- $iStart = self::$twFirstCode ['start'];
- $sum = $iStart / 10 + ($iStart % 10) * 9;
- $chars = str_split ( $mid );
- $iflag = 8;
- foreach ( $chars as $c ) {
- $sum = $sum + $c + "" * $iflag;
- $iflag --;
- }
- return ($sum % 10 == 0 ? 0 : (10 - $sum % 10)) == $end ? true : false;
- }
-
- /**
- * Verify Hong Kong ID card number (there is a bug, some special ID cards cannot be checked)
- *
- * The first 2 digits of the ID card are English characters. If only one English character appears, it means the first digit is a space. Corresponding to the number 58, the first two English characters A-Z correspond to the numbers 10-35
- respectively * The last digit of the check code is 0-9 plus the character "A", "A" represents 10
- *
- *
* @return Whether the verification code matches
- */
- public static function validateHKCard($idCard) {
- $card = str_replace ( "[\(|\)]", "", $card );
- $sum = 0;
- if (strlen ( $card ) == 9) {
- $card0_arr = str_split ( strtoupper ( substr ( $card, 0, 1 ) ) );
- $card1_arr = str_split ( strtoupper ( substr ( $card, 1, 1 ) ) );
- $sum = ($card0_arr [0] - 55) * 9 . ($card1_arr [0] - 55) * 8;
- $card = substr ( $card, 1, 8 );
- } else {
- $card0_arr = str_split ( strtoupper ( substr ( $card, 0, 1 ) ) );
- $sum = 522 + ($card0_arr [0] - 55) * 8;
- }
- $mid = substr ( $card, 1, 6 );
- $end = substr ( $card, 7, 1 );
- $chars = str_split ( $mid );
- $iflag = 7;
- foreach ( $chars as $c ) {
- $sum = $sum + $c + "" * $iflag;
- $iflag --;
- }
- if (strtoupper ( $end ) == "A") {
- $sum = $sum + 10;
- } else {
- $sum = $sum + $end;
- }
- return ($sum % 11 == 0) ? true : false;
- }
-
- /**
- * Get age based on ID number
- *
- * @param string idCard ID number
- * @return age
- */
- public static function getAgeByIdCard($idCard) {
- $iAge = 0;
- if (strlen ( $idCard ) == self::CHINA_ID_MIN_LENGTH) {
- $idCard = self::conver15CardTo18 ( $idCard );
- }
- $year = substr ( $idCard, 6, 4 );
- $iCurrYear = date ( 'Y', time () );
- $iAge = $iCurrYear - $year;
- return $iAge;
- }
-
- /**
- * Get the birthday based on the identity number
- *
- * @param string $idCard identity number
- * @return NULL string
- */
- public static function getDateByIdCard($idCard) {
- $len = strlen ( $idCard );
- if ($len < self::CHINA_ID_MIN_LENGTH) {
- return null;
- } else if ($len == CHINA_ID_MIN_LENGTH) {
- $idCard = self::conver15CardTo18 ( $idCard );
- }
- return substr ( $idCard, 12, 2 );
- }
- /**
- * Get gender based on identity number
- *
- * @param string $idCard identity number
- * @return gender (M-male, F-female, N-unknown)
- */
- public static function getGenderByIdCard($idCard) {
- $sGender = "N";
- if (strlen ( $idCard ) == self::CHINA_ID_MIN_LENGTH) {
- $idCard = self::conver15CardTo18 ( $idCard );
- }
- $sCardNum = substr ( $idCard, 16, 1 );
- if (( int ) $sCardNum % 2 != 0) {
- $sGender = "M";
- } else {
- $sGender = "F";
- }
- return $sGender;
- }
- /**
- * Get the province of household registration based on the identity number
- *
- * @param string $idCard identity number
- * @return string
- */
- public static function getProvinceByIdCard($idCard) {
- $len = strlen ( $idCard );
- $sProvince = null;
- $sProvinNum = "";
- if ($len == self::CHINA_ID_MIN_LENGTH || $len == self::CHINA_ID_MAX_LENGTH) {
- $sProvinNum = substr ( $idCard, 0, 2 );
- }
- $sProvince = self::$cityCodes [$sProvinNum];
- return $sProvince;
- }
- /**
- *Number verification
- *
- * @param int $val
- */
- public static function isNum($val) {
- return $val == null || $val == "" ? false : 0 < preg_match ( '/^[0-9]*$/', $val );
- }
- /**
- * Verify whether a date smaller than the current date is valid
- *
- * @param int $iYear Date to be verified (year)
- * @param int $iMonth Date to be verified (month 1-12)
- * @param int $iDate Date to be verified ( Day)
- * @return Is it valid
- */
- public static function valiDate($iYear, $iMonth, $iDate) {
- $year = date ( 'Y', time () );
- if ($iYear < self::MIN || $iYear >= $year) {
- return false;
- }
- if ($iMonth < 1 || $iMonth > 12) {
- return false;
- }
- switch ($iMonth) {
- case 4 :
- case 6 :
- case 9 :
- case 11 :
- $datePerMonth = 30;
- break;
- case 2 :
- $dm = (($iYear % 4 == 0 && $iYear % 100 != 0) || ($iYear % 400 == 0)) && ($iYear > self::MIN && $iYear < $year);
- $datePerMonth = $dm ? 29 : 28;
- break;
- default :
- $datePerMonth = 31;
- }
- return ($iDate >= 1) && ($iDate <= $datePerMonth);
- }
-
- /**
- * 将身份证的每位和对应位的加权因子相乘之后,再得到和值
- *
- * @param array $iArr
- * @return 身份证编码。
- */
- private static function getPowerSum($iArr) {
- $iSum = 0;
- $power_len = count ( self::$power );
- $iarr_len = count ( $iArr );
- if ($power_len == $iarr_len) {
- for($i = 0; $i < $iarr_len; $i ++) {
- for($j = 0; $j < $power_len; $j ++) {
- if ($i == $j) {
- $iSum = $iSum + $iArr [$i] * self::$power [$j];
- }
- }
- }
- }
- return $iSum;
- }
-
- /**
- * Take the power sum value modulo 11 to get the remainder for check digit judgment
- *
- * @param int $iSum
- * @return check digit
- */
- private static function getCheckCode18($iSum) {
- $sCode = "";
- switch ($iSum % 11) {
- case 10 :
- $sCode = "2";
- break;
- case 9 :
- $sCode = "3";
- break;
- case 8 :
- $sCode = "4";
- break;
- case 7 :
- $sCode = "5";
- break;
- case 6 :
- $sCode = "6";
- break;
- case 5 :
- $sCode = "7";
- break;
- case 4 :
- $sCode = "8";
- break;
- case 3 :
- $sCode = "9";
- break;
- case 2 :
- $sCode = "x";
- break;
- case 1 :
- $sCode = "0";
- break;
- case 0 :
- $sCode = "1";
- break;
- }
- return $sCode;
- }
- }
复制代码
|