PageRenderTime 54ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/Scorpio/Sco/IdentityCard/ROC.php

https://github.com/bluelovers/Scophp
PHP | 192 lines | 136 code | 31 blank | 25 comment | 15 complexity | 2b777924ac8b5d1afb0b481e89980062 MD5 | raw file
  1. <?php
  2. /**
  3. * @author bluelovers
  4. * @copyright 2012
  5. */
  6. /**
  7. * 中華民國國民身分證(驗證 / 生成)
  8. *
  9. * @see http://zh.wikipedia.org/zh-hant/%E4%B8%AD%E8%8F%AF%E6%B0%91%E5%9C%8B%E5%9C%8B%E6%B0%91%E8%BA%AB%E5%88%86%E8%AD%89#cite_note-8
  10. * @see http://people.debian.org/~paulliu/ROCid.html
  11. * @see http://www.wretch.cc/blog/gump1002/7459167
  12. * @see http://www.blueshop.com.tw/download/show.asp?pgmcde=PGM200602051851008IX&extcde=PGMLSTCAT
  13. * @see http://doublekai.org/blog/?p=51
  14. */
  15. class Sco_IdentityCard_ROC implements Sco_IdentityCard_Interface
  16. {
  17. static $_city_point = array(
  18. 'A' => 10,
  19. 'B' => 11,
  20. 'C' => 12,
  21. 'D' => 13,
  22. 'E' => 14,
  23. 'F' => 15,
  24. 'G' => 16,
  25. 'H' => 17,
  26. 'J' => 18,
  27. 'K' => 19,
  28. 'L' => 20,
  29. 'M' => 21,
  30. 'N' => 22,
  31. 'P' => 23,
  32. 'Q' => 24,
  33. 'R' => 25,
  34. 'S' => 26,
  35. 'T' => 27,
  36. 'U' => 28,
  37. 'V' => 29,
  38. 'W' => 30,
  39. 'X' => 31,
  40. 'Y' => 32,
  41. 'Z' => 33,
  42. 'I' => 34,
  43. 'O' => 35,
  44. );
  45. static $_city_point2 = array(
  46. 'A' => 1,
  47. 'B' => 10,
  48. 'C' => 19,
  49. 'D' => 28,
  50. 'E' => 37,
  51. 'F' => 46,
  52. 'G' => 55,
  53. 'H' => 64,
  54. 'J' => 73,
  55. 'K' => 82,
  56. 'L' => 2,
  57. 'M' => 11,
  58. 'N' => 20,
  59. 'P' => 29,
  60. 'Q' => 38,
  61. 'R' => 47,
  62. 'S' => 56,
  63. 'T' => 65,
  64. 'U' => 74,
  65. 'V' => 83,
  66. 'W' => 3,
  67. 'X' => 12,
  68. 'Y' => 21,
  69. 'Z' => 30,
  70. 'I' => 39,
  71. 'O' => 48,
  72. );
  73. const GENDER_MALE = 1;
  74. const GENDER_FEMALE = 2;
  75. const REGEX = '/^[a-zA-Z][1-2][0-9]{8}$/';
  76. const REGEX_FILTER = '/([a-zA-Z][1-2][0-9]{8})/';
  77. public function generate($city = null, $gender = null)
  78. {
  79. if ($city === null)
  80. {
  81. // 取得隨機字母分數
  82. $city = array_rand(self::$_city_point);
  83. }
  84. else
  85. {
  86. $city = strtoupper($city);
  87. }
  88. if ($gender === null)
  89. {
  90. $gender = mt_rand(1, 2);
  91. }
  92. //建立隨機身份證碼
  93. $id = $city . $gender . array_pop(explode('.', uniqid(rand(), true)));
  94. return substr_replace($id, self::_check_ssn_end_code($id), 9);
  95. }
  96. public function valid($id, $city = null, $gender = null)
  97. {
  98. if (preg_match(self::REGEX, $id))
  99. {
  100. $city_code = strtoupper(substr($id, 0, 1));
  101. $gender_code = substr($id, 1, 1);
  102. if ((!$n0 = self::$_city_point2[$city_code]) || ($city !== null && (string )$city !== $city_code) || ($gender !== null && (string )$gender !== $gender_code) || !($gender_code === (string )self::GENDER_MALE || $gender_code === (string )self::GENDER_FEMALE))
  103. {
  104. return false;
  105. }
  106. $n = array();
  107. /*
  108. $n[] = 0;
  109. $n[] = substr($n0, 0, 1);
  110. $n[] = substr($n0, 1, 1);
  111. */
  112. $i = 3;
  113. for ($j = 1; $j < strlen($id); $j++)
  114. {
  115. $n[$i++] = substr($id, $j, 1);
  116. }
  117. //$vaild = (bool)(0 === (($n[1] + ($n[2] * 9) + ($n[3] * 8) + ($n[4] * 7) + ($n[5] * 6) + ($n[6] * 5) + ($n[7] * 4) + ($n[8] * 3) + ($n[9] * 2) + $n[10] + $n[11]) % 10));
  118. if (0 === (($n0 + ($n[3] * 8) + ($n[4] * 7) + ($n[5] * 6) + ($n[6] * 5) + ($n[7] * 4) + ($n[8] * 3) + ($n[9] * 2) + $n[10] + $n[11]) % 10))
  119. {
  120. return array(
  121. true,
  122. $city_code,
  123. $gender_code);
  124. }
  125. }
  126. return false;
  127. }
  128. protected function _check_ssn_end_code($ssn)
  129. {
  130. /*
  131. $d1 = self::$_city_point[substr($ssn, 0, 1)];
  132. $n1 = substr($d1, 0, 1) + (substr($d1, 1, 1) * 9);
  133. */
  134. $n1 = self::$_city_point2[substr($ssn, 0, 1)];
  135. $n2 = 0;
  136. for ($j = 1; $j < 9; $j++)
  137. {
  138. $n2 = $n2 + substr($ssn, $j, 1) * (9 - $j);
  139. }
  140. $ssn = ((($a = 10 - ($n1 + $n2) % 10) == 10) ? 0 : $a);
  141. return $ssn;
  142. }
  143. protected function _city_point2()
  144. {
  145. $arr = array();
  146. foreach (self::$_city_point as $city => $d1)
  147. {
  148. $n1 = substr($d1, 0, 1) + (substr($d1, 1, 1) * 9);
  149. $arr[$city] = $n1;
  150. }
  151. return $arr;
  152. }
  153. public function filter($value)
  154. {
  155. if (preg_match(self::REGEX_FILTER, $value, $m))
  156. {
  157. return strtoupper($m[0]);
  158. }
  159. return null;
  160. }
  161. }