IdentifyUtils.php 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. <?php
  2. /**
  3. * IdentifyUtils.php UTF-8
  4. *
  5. *
  6. * @date : 2018/4/27 17:59
  7. *
  8. * @license 这不是一个自由软件,未经授权不许任何使用和传播。
  9. * @author : wuyonghong <wyh@huosdk.com>
  10. * @version : HUOSDK 8.0
  11. */
  12. namespace huolib\utils;
  13. use huolib\constant\IdentifyConst;
  14. use huolib\status\IdentifyStatus;
  15. class IdentifyUtils {
  16. CONST ID_CARD_MIN_LEN = 4;
  17. CONST ID_CARD_MAX_LEN = 32;
  18. CONST REAL_NAME_MIN_LEN = 1;
  19. CONST REAL_NAME_MAX_LEN = 32;
  20. /**
  21. * 校验认证
  22. *
  23. * @param string $type
  24. * @param string $real_name
  25. * @param string $id_card
  26. *
  27. * @return int
  28. */
  29. public static function checkIdentify($type = '', $real_name = '', $id_card = '') {
  30. if (empty($type)) {
  31. return IdentifyStatus::TYPE_EMPTY;
  32. }
  33. if (empty($real_name)) {
  34. return IdentifyStatus::REALNAME_EMPTY;
  35. }
  36. if (empty($id_card)) {
  37. return IdentifyStatus::IDCARD_EMPTY;
  38. }
  39. if (false == IdentifyConst::getMsg($type)) {
  40. return IdentifyStatus::TYPE_ERROR;
  41. }
  42. if (strlen($real_name) > self::REAL_NAME_MAX_LEN) {
  43. return IdentifyStatus::REALNAME_TOO_LONG;
  44. }
  45. if (strlen($real_name) < self::REAL_NAME_MIN_LEN) {
  46. return IdentifyStatus::REALNAME_TOO_SHORT;
  47. }
  48. if (strlen($id_card) > self::ID_CARD_MAX_LEN) {
  49. return IdentifyStatus::IDCARD_TOO_LONG;
  50. }
  51. if (strlen($id_card) < self::ID_CARD_MIN_LEN) {
  52. return IdentifyStatus::IDCARD_TOO_SHORT;
  53. }
  54. if (IdentifyConst::ITYPE_MAINLAND == $type && false == self::validateIDCard($id_card)) {
  55. return IdentifyStatus::IDCARD_ERROR;
  56. }
  57. return IdentifyStatus::NO_ERROR;
  58. }
  59. /**
  60. * 验证身份证是否有效
  61. *
  62. * @param $id_card
  63. *
  64. * @return bool
  65. */
  66. public static function validateIDCard($id_card) {
  67. $_id_card = $id_card;
  68. if (strlen($_id_card) == 18) {
  69. return self::check18IDCard($_id_card);
  70. } elseif ((strlen($_id_card) == 15)) {
  71. $_id_card = self::convertIDCard15to18($_id_card);
  72. return self::check18IDCard($_id_card);
  73. } else {
  74. return false;
  75. }
  76. }
  77. /**
  78. * 计算身份证的最后一位验证码,根据国家标准GB 11643-1999
  79. *
  80. * @param $id_card_body
  81. *
  82. * @return bool|mixed
  83. */
  84. public static function calcIDCardCode($id_card_body) {
  85. if (!is_numeric($id_card_body)) {
  86. /* 必须为数字 */
  87. return -1;
  88. }
  89. $_id_card_body = $id_card_body;
  90. if (strlen($_id_card_body) != 17) {
  91. return false;
  92. }
  93. //加权因子
  94. $_factor = array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2);
  95. //校验码对应值
  96. $_code = array('1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2');
  97. $_check_sum = 0;
  98. for ($_i = 0; $_i < strlen($_id_card_body); $_i++) {
  99. $_check_sum += substr($_id_card_body, $_i, 1) * $_factor[$_i];
  100. }
  101. return $_code[$_check_sum % 11];
  102. }
  103. /**
  104. * 将15位身份证升级到18位
  105. *
  106. * @param $id_card
  107. *
  108. * @return bool|string
  109. */
  110. public static function convertIDCard15to18($id_card) {
  111. $_id_card = $id_card;
  112. if (15 != strlen($_id_card)) {
  113. return false;
  114. } else {
  115. // 如果身份证顺序码是996 997 998 999,这些是为百岁以上老人的特殊编码
  116. if (array_search(substr($_id_card, 12, 3), array('996', '997', '998', '999')) !== false) {
  117. $_id_card = substr($_id_card, 0, 6).'18'.substr($_id_card, 6, 9);
  118. } else {
  119. $_id_card = substr($_id_card, 0, 6).'19'.substr($_id_card, 6, 9);
  120. }
  121. }
  122. $_id_card = $_id_card.self::calcIDCardCode($_id_card);
  123. return $_id_card;
  124. }
  125. /**
  126. * 18位身份证校验码有效性检查
  127. *
  128. * @param $id_card
  129. *
  130. * @return bool
  131. */
  132. public static function check18IDCard($id_card) {
  133. $_id_card = $id_card;
  134. if (18 != strlen($_id_card)) {
  135. return false;
  136. }
  137. $_id_card_body = substr($_id_card, 0, 17); //身份证主体
  138. $_id_card_code = strtoupper(substr($_id_card, 17, 1)); //身份证最后一位的验证码
  139. if (self::calcIDCardCode($_id_card_body) != $_id_card_code) {
  140. return false;
  141. } else {
  142. return true;
  143. }
  144. }
  145. /**
  146. * 从身份证号码获取生日
  147. *
  148. * @param string $id_card 身份证号码
  149. * @param string $glue 连接符
  150. *
  151. * @return string : string
  152. */
  153. public static function getBirthday($id_card, $glue = '') {
  154. if (empty($id_card)) {
  155. return '';
  156. }
  157. $_date = strlen($id_card) == 15 ? ('19'.substr($id_card, 6, 6)) : substr($id_card, 6, 8);
  158. $_year = substr($_date, 0, 4);
  159. $_moth = substr($_date, 4, 2);
  160. $_day = substr($_date, 6, 2);
  161. $_birthday = implode($glue, [$_year, $_moth, $_day]);
  162. return $_birthday;
  163. }
  164. /**
  165. * 根据身份证号获取年龄(周岁)
  166. *
  167. * @param string $id_card 身份证号
  168. *
  169. * @return int
  170. */
  171. public static function getAgeById($id_card) {
  172. $_birthday = self::getBirthday($id_card, '-');
  173. $_age = self::getAge($_birthday);
  174. return $_age;
  175. }
  176. /**
  177. * 根据身份证号码计算年龄
  178. *
  179. * @param string $birthday 出生年月日
  180. *
  181. * @return int $age
  182. */
  183. public static function getAge($birthday) {
  184. if (empty($birthday)) {
  185. return 0;
  186. }
  187. $_birthday = date('Y-m-d', strtotime($birthday));
  188. list($_birth_year, $_birth_month, $_birth_day) = explode('-', $_birthday);
  189. list($_current_year, $_current_month, $_current_day) = explode('-', date('Y-m-d'));
  190. $_age = $_current_year - $_birth_year - 1;
  191. if ($_current_month > $_birth_month
  192. || ($_current_month == $_birth_month && $_current_day >= $_birth_day)) {
  193. $_age++;
  194. }
  195. return $_age;
  196. }
  197. }