You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

758 lines
25 KiB

  1. <?php
  2. /**
  3. * Function Description:api通用方法类
  4. * Function Name: Util
  5. * ${PARAM_DOC}
  6. *
  7. * @return ${TYPE_HINT}
  8. * ${THROWS_DOC}
  9. *
  10. * @author 娄梦宁
  11. */
  12. namespace backend\modules\api\util;
  13. use backend\modules\api\models\LvmamaOrderConnect;
  14. use backend\modules\api\models\OperaProduct;
  15. use backend\modules\api\models\OrderMain;
  16. use backend\modules\api\models\OrderTitle;
  17. use common\models\Msg;
  18. use common\models\Utils;
  19. use Yii;
  20. class Util
  21. {
  22. private static $base_url = 'http://api.lvmama.com/distributorApi/2.0/api/';//驴妈妈api环境地址
  23. private static $appKey = 'ZHIZHUCHUXING';//驴妈妈对应的分销商编号
  24. private static $secret = '45b12b93ac5d699c41f9e89b62fb9678';
  25. // private static $appKey = 'ZHIZHUXING';//驴妈妈对应的分销商编号
  26. // private static $secret = 'b80e9a9de0acbefc6f4d652f6f726c11';
  27. private static $secretZyb = 'TESTFX';
  28. private static $base_url_zyb = 'http://zyb-zff.sendinfo.com.cn/boss/service/code.htm';//智游宝api环境地址
  29. /**
  30. * Function Description:驴妈妈对接签名
  31. * Function Name: SingForLvmama
  32. * @param $time
  33. *
  34. * @return string
  35. *
  36. * @author 娄梦宁
  37. */
  38. public static function SingForLvmama($time)
  39. {
  40. $secret = self::$secret;
  41. $result = md5($secret . $time . $secret);
  42. return $result;
  43. }
  44. /*
  45. * 获取私有静态属性
  46. */
  47. public function __get($name)
  48. {
  49. return $this->$name;
  50. }
  51. public static function getBaseUrl()
  52. {
  53. return self::$base_url;
  54. }
  55. public static function getAppKey()
  56. {
  57. return self::$appKey;
  58. }
  59. public static function getSecret()
  60. {
  61. return self::$secret;
  62. }
  63. public static function getBaseUrlZyb()
  64. {
  65. return self::$base_url_zyb;
  66. }
  67. /*
  68. * 处理xml中的cdada标签
  69. */
  70. public static function doCdada($str)
  71. {
  72. $a = strrpos($str, "[") + 1;
  73. $b = strpos($str, "]");
  74. $c = substr($str, $a, $b - $a);
  75. return $c;
  76. }
  77. /**
  78. * Function Description:数组转换成xml
  79. * Function Name: arrayToXml
  80. * @param $array
  81. * @param $key
  82. * @return string
  83. *
  84. * @author 娄梦宁
  85. */
  86. public static function arrayToXml($array, $key = '')
  87. {
  88. $string = '';
  89. if (count($array) == 0) {
  90. return '';
  91. }
  92. foreach ($array as $k => $v) {
  93. if (is_array($v) && isset($v['0'])) {
  94. $string .= self::arrayToXml($v, $k);//是数组或者对像就的递归调用
  95. } else {
  96. if ($key != '') {
  97. $k = $key;
  98. }
  99. $string .= '<' . $k . '>';
  100. if (is_array($v) || is_object($v)) {//判断是否是数组,或者,对像
  101. $string .= self::arrayToXml($v);//是数组或者对像就的递归调用
  102. } elseif (is_numeric($v)) {
  103. $string .= $v;
  104. } elseif ($v != '') {
  105. $string .= '<![CDATA[' . $v . ']]>';
  106. } else {
  107. $string .= '';
  108. }
  109. $string .= '</' . $k . '>';
  110. }
  111. }
  112. return $string;
  113. }
  114. public static function arrayToXmlForLvmama($array)
  115. {
  116. $string = '';
  117. foreach ($array as $k => $v) {
  118. $string .= '<' . $k . '>';
  119. if (is_array($v) || is_object($v)) {//判断是否是数组,或者,对像
  120. $string .= self::arrayToXmlForLvmama($v);//是数组或者对像就的递归调用
  121. } elseif (is_numeric($v)) {
  122. $string .= $v;
  123. } else {
  124. $string .= $v;
  125. }
  126. $string .= '</' . $k . '>';
  127. }
  128. return $string;
  129. }
  130. /**
  131. * Function Description:xml转换成json
  132. * Function Name: xmlToJson
  133. * @param $source
  134. *
  135. * @return string
  136. *
  137. * @author 娄梦宁
  138. */
  139. public static function xmlToJson($source)
  140. {
  141. if (is_file($source)) { //传的是文件,还是xml的string的判断
  142. $xml_array = simplexml_load_file($source);
  143. } else {
  144. $xml_array = simplexml_load_string(trim($source));
  145. }
  146. $json = json_encode($xml_array, true);
  147. return $json;
  148. }
  149. /**
  150. * Function Description:xml转换成array
  151. * Function Name: xmlToArray
  152. * @param $source
  153. *
  154. * @return mixed
  155. *
  156. * @author 娄梦宁
  157. */
  158. public static function xmlToArray($source)
  159. {
  160. libxml_disable_entity_loader(true);
  161. $getResult = json_decode(json_encode(simplexml_load_string(trim($source), 'SimpleXMLElement', LIBXML_NOCDATA)), true);
  162. return $getResult;
  163. }
  164. /**
  165. * Function Description:智游宝签名算法
  166. * Function Name: SingForZyb
  167. * @param $xmlMsg
  168. *
  169. * @return string
  170. *
  171. * @author 娄梦宁
  172. */
  173. public static function SingForZyb($xmlMsg)
  174. {
  175. $secret = self::$secretZyb;
  176. $result = md5("xmlMsg=" . $xmlMsg . $secret);
  177. $result = strtolower($result);
  178. return $result;
  179. }
  180. /**
  181. * Function Description:根据驴妈妈的规则换算退款截止日期
  182. * Function Name: countRefundTime
  183. * @param $num
  184. *
  185. * @return array
  186. *
  187. * @author 娄梦宁
  188. */
  189. public static function countRefundTime($num)
  190. {
  191. if ($num > 0) {
  192. $day = floor(($num / 60) / 24) + 1;
  193. $time = 24 - ($num / 60) % 24;
  194. } else {
  195. $num = -$num;
  196. $day = 0 - floor(($num / 60) / 24);
  197. $time = ($num / 60) % 24;
  198. }
  199. if ($time == 0 or $time == 24) {
  200. $time = '23:59';
  201. } else {
  202. $time = $time . ':00';
  203. }
  204. return ['day' => $day, 'time' => $time];
  205. }
  206. /**
  207. * Function Description:驴妈妈创建订单接口
  208. * Function Name: CreateOrderForLvmama
  209. * @param $partnerOrderNo
  210. * 蜘蛛子订单id
  211. * @param $orderAmount
  212. *订单总额
  213. * @param $productId
  214. *产品id 对应蜘蛛主产品code
  215. * @param $goodsId
  216. * 商品id 对应蜘蛛子产品code
  217. * @param $quantity
  218. * 订单人数
  219. * @param $visitDate
  220. * 订单出发日期
  221. * @param $sellPrice
  222. * 蜘蛛付给驴妈妈的结算价,对应订单成本价
  223. * @param $name
  224. * @param $mobile
  225. * @param $credentials
  226. *
  227. * @return mixed
  228. *
  229. * @author 娄梦宁
  230. */
  231. public static function CreateOrderForLvmama($partnerOrderNo, $orderAmount, $productId, $goodsId, $quantity, $visitDate, $sellPrice, $name, $mobile, $credentials, $credentialsType)
  232. {
  233. //请求参数构建
  234. $time = time();
  235. $appKey = self::getAppKey();
  236. $sign = self::SingForLvmama($time);
  237. $order_info = [
  238. 'request' => [
  239. 'orderInfo' => [
  240. 'partnerOrderNo' => $partnerOrderNo,
  241. 'orderAmount' => $orderAmount,
  242. 'product' => [
  243. 'productId' => $productId,
  244. 'goodsId' => $goodsId,
  245. 'quantity' => $quantity,
  246. 'visitDate' => $visitDate,
  247. 'sellPrice' => $sellPrice
  248. ],
  249. 'booker' => [
  250. 'name' => $name,
  251. 'mobile' => $mobile,
  252. ],
  253. 'travellers' => [
  254. 'traveller' => [
  255. 'name' => $name,
  256. 'credentialsType' => $credentialsType,
  257. 'credentials' => $credentials,
  258. 'mobile' => $mobile,
  259. ],
  260. ]
  261. ]]];
  262. $order_info = self::arrayToXmlForLvmama($order_info);
  263. $get_data = array(
  264. "appKey" => $appKey,
  265. 'messageFormat' => 'Xml',
  266. 'timestamp' => $time,
  267. 'sign' => $sign,
  268. 'request' => $order_info,
  269. );
  270. $url_param = http_build_query($get_data);
  271. file_put_contents(__DIR__ . '/../log/lvmama/' . date("Y-m-d") . '.log', date("Y-m-d H:i:s") . '下单记录:请求地址 ' . self::getBaseUrl() . 'ticket/createOrder?' . $url_param . PHP_EOL, FILE_APPEND);
  272. $result = file_get_contents(self::getBaseUrl() . 'ticket/createOrder?' . $url_param);
  273. $result = self::xmlToJson($result);
  274. file_put_contents(__DIR__ . '/../log/lvmama/' . date("Y-m-d") . '.log', date("Y-m-d H:i:s") . '下单记录 ' . $result . PHP_EOL, FILE_APPEND);
  275. return json_decode($result, true);
  276. }
  277. /**
  278. * Function Description:驴妈妈支付订单
  279. * Function Name: OrderPayment
  280. * @param $partnerOrderNo
  281. * 蜘蛛订单号
  282. * @param $orderId
  283. * 驴妈妈订单号
  284. * @param $serialNum
  285. *支付流水号
  286. * @return mixed
  287. *
  288. * @author 娄梦宁
  289. */
  290. public static function OrderPayment($partnerOrderNo, $orderId, $serialNum)
  291. {
  292. $util = new Util();
  293. //请求参数构建
  294. $time = time();
  295. $appKey = $util->getAppKey();
  296. $sign = $util::SingForLvmama($time);
  297. $order = [
  298. 'request' => [
  299. 'order' => [
  300. 'partnerOrderNo' => $partnerOrderNo,
  301. 'orderId' => $orderId,
  302. 'serialNum' => $serialNum
  303. ]
  304. ]
  305. ];
  306. $order = $util::arrayToXmlForLvmama($order);
  307. // $url = $util->getBaseUrl() . 'order/orderPayment' . "?appKey=" . $appKey . "&messageFormat=Xml&timestamp=" . $timestamp . "&sign=" . $sign . "&request=" . $order;
  308. $get_data = array(
  309. "appKey" => $appKey,
  310. 'messageFormat' => 'Xml',
  311. 'timestamp' => $time,
  312. 'sign' => $sign,
  313. 'request' => $order,
  314. );
  315. $url_param = http_build_query($get_data);
  316. $result = file_get_contents($util->getBaseUrl() . 'order/orderPayment?' . $url_param);
  317. $result = self::xmlToJson($result);
  318. return json_decode($result, true);
  319. }
  320. /**
  321. * Function Description:申请退款接口
  322. * Function Name: actionOrderCancel
  323. *
  324. *
  325. * @author 娄梦宁
  326. */
  327. public static function OrderCancelForLvmama($PartnerOrderNo, $orderId)
  328. {
  329. $util = new Util();
  330. //请求参数构建
  331. $time = time();
  332. $appKey = $util->getAppKey();
  333. $timestamp = $time;
  334. $sign = $util::SingForLvmama($time);
  335. $url = $util->getBaseUrl() . '/ticket/orderCancel' . "?appKey=" . $appKey . "&messageFormat=json&timestamp=" . $timestamp . "&sign=" . $sign . "&PartnerOrderNo=" . $PartnerOrderNo . "&orderId=" . $orderId;
  336. $result = Utils::httpRequest($url);
  337. $result = json_decode($result, true);
  338. return $result;
  339. // if ($result['state']['code'] == '1000') {
  340. // if ($result['order']['requestStatus'] == 'PASS') {
  341. // return '已退款';
  342. // } elseif ($result['order']['requestStatus'] == 'REVIEWING') {
  343. // return '审核中';
  344. // } else {
  345. // return '申请驳回 ' . $result['order']['refundInfo'];
  346. // }
  347. // }
  348. }
  349. /**
  350. * Function Description:门票产品下单后判断是否是驴妈妈,是驴妈妈则去驴妈妈下单
  351. * Function Name: LvmamaOrderCheck
  352. * @param $order_id
  353. *
  354. * @return bool
  355. *
  356. * @author 娄梦宁
  357. */
  358. public function LvmamaOrderCheck($order_id)
  359. {
  360. $order_main = new OrderMain();
  361. //查看是否是驴妈妈产品
  362. $org_id = $order_main::find()->select('a.base_price,b.prod_code,b.org_id')->from('order_main a')->
  363. leftJoin('opera_product as b', 'a.prod_id=b.prod_id')->where(['a.order_id' => $order_id])->asArray()->one();
  364. if ($org_id['org_id'] != 1369) {//非驴妈妈产品,不处理
  365. return true;
  366. }
  367. $lvmama_order_connect = new LvmamaOrderConnect();
  368. $lvmama_order_info_select = [
  369. 'partnerOrderNo' => 'order_id',
  370. 'cnt' => 'count(prod_id)',
  371. 'visitDate' => 'run_date',
  372. 'sellPrice' => 'base_price',
  373. 'name' => 'customer_name',
  374. 'mobile' => 'customer_mobile',
  375. 'credentials' => 'customer_id_no',
  376. 'goodsId' => '(select prod_code from opera_product where prod_id=a.prod_id)',
  377. 'orderAmount' => '(count(prod_id)*base_price)',
  378. 'customer_id_type'
  379. ];
  380. $lvmama_order_info = $order_main::find()->select($lvmama_order_info_select)
  381. ->from('order_main a')
  382. ->where(['and', ['=', 'parent_order_id', $order_id], ['=', 'cancel_flag', 0]])
  383. ->groupBy('prod_id')
  384. ->asArray()
  385. ->all();
  386. $memo = '';
  387. $error_code = 0;
  388. foreach ($lvmama_order_info as $key => $val) {
  389. if ($val['customer_id_type'] == 153) {
  390. $credentialsType = 'HUZHAO';
  391. } else {
  392. $credentialsType = 'ID_CARD';
  393. }
  394. $orderAmount = (int)$val['sellPrice'] * $val['cnt'];
  395. $org_result = $this::CreateOrderForLvmama($val['partnerOrderNo'], $orderAmount, $org_id['prod_code'], $val['goodsId'], $val['cnt'], $val['visitDate'], $val['sellPrice'],
  396. $val['name'], $val['mobile'], $val['credentials'], $credentialsType);
  397. if ($org_result['state']['code'] != 1000) {
  398. $memo .= $val['prod_name'] . $org_result['state']['message'] . $org_result['state']['solution'] . ' ';
  399. $error_code = 1;
  400. } else {
  401. $lvmama_order_connect->istConnect($order_id, $val['partnerOrderNo'], $org_result['order']['orderId']);
  402. $memo .= '驴妈妈订单号:' . $org_result['order']['orderId'] . ' ';
  403. //去驴妈妈支付该订单
  404. $serialNum = $org_result['order']['orderId'] . '-' . time();
  405. $pay_lvmama = Util::OrderPayment($val['partnerOrderNo'], $org_result['order']['orderId'], $serialNum);
  406. if ($pay_lvmama['state']['code'] != 1000) {
  407. $memo .= '驴妈妈支付异常' . $pay_lvmama['state']['message'] . $pay_lvmama['state']['solution'] . ' ';
  408. $error_code = 1;
  409. }
  410. }
  411. }
  412. //驴妈妈下单或者支付失败预警短信
  413. if ($error_code == 1) {
  414. $content = "预警:驴妈妈后台直连门票下单失败,订单号({$order_id}),请及时处理。";
  415. $phone_arr = [
  416. '13757163513',
  417. '18317023071',
  418. '13564184647',
  419. '15088913683',
  420. // '18106523772',//该手机号已经取消 modify nizf
  421. ];
  422. foreach ($phone_arr as $phone) {
  423. Msg::sendTelMsg($phone, $content);
  424. }
  425. }
  426. $result = $order_main::updateAll(['CUSTOMER_MEMO' => $memo], ['=', 'order_id', $order_id]);
  427. if ($result > 0) {
  428. return true;
  429. } else {
  430. return false;
  431. }
  432. }
  433. /**
  434. * Des:调用蜘蛛出行接口
  435. * Name: interfaceZzcx
  436. * @param $order_id int 订单id
  437. * @param $order_type int 订单类型 1:车 ,2:门票 ,3 酒店 ,4 :巴士自由行
  438. * @return array
  439. * @author 娄梦宁
  440. */
  441. public static function interfaceZzcx($order_id, $order_type)
  442. {
  443. #1、获取org_id 渠道ID
  444. if (in_array($order_type, [1, 2, 3])) {
  445. $orderTab = new OrderMain();
  446. $org_id = $orderTab->getOutsideSaleOrgId($order_id);
  447. } elseif ($order_type == 4) {
  448. $orderTab = new OrderTitle();
  449. $info = $orderTab->getTitleInfoById($order_id);
  450. $org_id = $info['outside_sale_org_id'];
  451. } else {
  452. return ['code' => 1, 'info' => '类型错误'];
  453. }
  454. if (empty($org_id)) {
  455. return ['code' => 1, 'info' => '非需要通知的渠道'];
  456. }
  457. #2、获取渠道ID对应的通知地址
  458. $config = Yii::$app->params;
  459. if (empty($config['wechat_notice_list'][$org_id])) {
  460. return ['code' => 0, 'info' => '订单无需通知'];
  461. }
  462. $host = $config['wechat_notice_list'][$org_id];
  463. #3、发送请求
  464. $time = time();
  465. $data = [
  466. 'time' => $time,
  467. 'order_id' => $order_id,
  468. 'type' => $order_type,
  469. ];//当前服务器时间 校验60秒后失效
  470. $param = [
  471. 'code' => self::authCode(http_build_query($data), 'ENCODE'),//对数据进行加密
  472. 'time' => $time
  473. ];
  474. $wechat_url = $host . '/zzcx/interfaces/cs/cancel-order';
  475. $result = Utils::httpRequest($wechat_url, $param);
  476. return json_decode($result, true);
  477. }
  478. /**
  479. * Des:通知微信确认酒店订单
  480. * Name: interfaceZzcx
  481. * @param $order_id int 订单id
  482. * @return array
  483. * @author 娄梦宁
  484. */
  485. public static function confirmHotelOrder($order_id)
  486. {
  487. $time = time();
  488. $data = [
  489. 'time' => $time,
  490. 'order_id' => $order_id,
  491. ];//当前服务器时间 校验60秒后失效
  492. $param = [
  493. 'code' => self::authCode(http_build_query($data), 'ENCODE'),//对数据进行加密
  494. 'time' => $time
  495. ];
  496. $wechat_url = Yii::$app->params['wechat_url'] . '/zzcx/interfaces/cs/confirm-hotel-order';
  497. $result = Utils::httpRequest($wechat_url, $param);
  498. return json_decode($result, true);
  499. }
  500. /** Function Description:加密解密函数
  501. * Function Name: authCode
  502. * @param $string
  503. * @param string $operation
  504. * @param int $expiry
  505. * @return string
  506. * @author 倪宗锋
  507. */
  508. static function authCode($string, $operation = 'DECODE', $expiry = 0)
  509. {
  510. $key = 'udM5A8S50eg8veH15dd0m601de7073N8Bcn7d1I8Res7C7o7z274D6y342I4C7t7';
  511. $ckey_length = 4; // 随机密钥长度 取值 0-32;
  512. // 加入随机密钥,可以令密文无任何规律,即便是原文和密钥完全相同,加密结果也会每次不同,增大破解难度。
  513. // 取值越大,密文变动规律越大,密文变化 = 16 的 $ckey_length 次方
  514. // 当此值为 0 时,则不产生随机密钥
  515. $key = md5($key);
  516. $keya = md5(substr($key, 0, 16));
  517. $keyb = md5(substr($key, 16, 16));
  518. $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length) : substr(md5(microtime()), -$ckey_length)) : '';
  519. $cryptkey = $keya . md5($keya . $keyc);
  520. $key_length = strlen($cryptkey);
  521. $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0) . substr(md5($string . $keyb), 0, 16) . $string;
  522. $string_length = strlen($string);
  523. $result = '';
  524. $box = range(0, 255);
  525. $rndkey = array();
  526. for ($i = 0; $i <= 255; $i++) {
  527. $rndkey[$i] = ord($cryptkey[$i % $key_length]);
  528. }
  529. for ($j = $i = 0; $i < 256; $i++) {
  530. $j = ($j + $box[$i] + $rndkey[$i]) % 256;
  531. $tmp = $box[$i];
  532. $box[$i] = $box[$j];
  533. $box[$j] = $tmp;
  534. }
  535. for ($a = $j = $i = 0; $i < $string_length; $i++) {
  536. $a = ($a + 1) % 256;
  537. $j = ($j + $box[$a]) % 256;
  538. $tmp = $box[$a];
  539. $box[$a] = $box[$j];
  540. $box[$j] = $tmp;
  541. $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
  542. }
  543. if ($operation == 'DECODE') {
  544. if ((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26) . $keyb), 0, 16)) {
  545. return substr($result, 26);
  546. } else {
  547. return '';
  548. }
  549. } else {
  550. return $keyc . str_replace('=', '', base64_encode($result));
  551. }
  552. }
  553. /**
  554. * Function Description:自由行产品检查特定日期产品是否已过预订时间
  555. * Function Name: checkBookTime
  556. * @param $pre_days
  557. * @param $pre_time
  558. * @param $date
  559. *
  560. * @return bool
  561. *
  562. * @author 娄梦宁
  563. */
  564. public static function checkBookTime($pre_days, $pre_time, $date)
  565. {
  566. $tmp_date = date('Y-m-d', strtotime($date) - 3600 * 24 * $pre_days);
  567. $tmp_date_time = $tmp_date . ' ' . $pre_time;
  568. if (strtotime($tmp_date_time) > time()) {
  569. return true;
  570. } else {
  571. return false;
  572. }
  573. }
  574. /**
  575. * Function Description:返回成功数组数据
  576. * Function Name: returnArrSu
  577. * @param string $msg 提示信息
  578. * @param string|array $data 需要传递的数据
  579. * @param string $code 错误码
  580. *
  581. * @return array
  582. *
  583. * @author 倪宗锋
  584. */
  585. public static function returnArrSu($msg = '', $data = '', $code = '')
  586. {
  587. $return = array();
  588. $return['flag'] = true;
  589. $return['msg'] = $msg;
  590. $return['code'] = $code;
  591. $return['data'] = $data;
  592. return $return;
  593. }
  594. /**
  595. * Function Description:返回错误数组数据
  596. * Function Name: returnArrEr
  597. * @param string $msg 提示信息
  598. * @param string|array $data 需要传递的数据
  599. * @param string $code 错误码
  600. *
  601. * @return array
  602. *
  603. * @author 倪宗锋
  604. */
  605. public static function returnArrEr($msg = '', $data = '', $code = '')
  606. {
  607. $return = array();
  608. $return['flag'] = false;
  609. $return['msg'] = $msg;
  610. $return['code'] = $code;
  611. $return['data'] = $data;
  612. return $return;
  613. }
  614. /**
  615. * Function Description:返回身份证相关信息
  616. * Function Name: getIDCardInfo
  617. * @param string $IDCard 身份证号
  618. * @param string $datestr 指定日期
  619. * @return array
  620. *
  621. * @author 倪宗锋
  622. */
  623. //得到身份证相关信息
  624. //$datestr 指定日期 (结果为指定日期与出生日期之间的年龄s)
  625. public static function getIDCardInfo($IDCard, $datestr = '')
  626. {
  627. $datestr = $datestr == '' ? date('Y-m-d') : $datestr;
  628. $tdate = '';
  629. $msg = [
  630. 0 => '未知错误',
  631. 1 => '身份证格式错误',
  632. 2 => '身份证合法'
  633. ];
  634. $result['code'] = 0;//0:未知错误,1:身份证格式错误,2:无错误
  635. $result['msg'] = '未知错误';
  636. $result['birthday'] = '';//生日,格式如:2012-11-15
  637. if (!preg_match("/^[1-9]([0-9a-zA-Z]{17}|[0-9a-zA-Z]{14})$/", $IDCard)) {
  638. $result['code'] = 1;
  639. $result['msg'] = $msg[$result['code']];
  640. return $result;
  641. } else {
  642. if (strlen($IDCard) == 18) {
  643. $tyear = intval(substr($IDCard, 6, 4));
  644. $tmonth = intval(substr($IDCard, 10, 2));
  645. $tday = intval(substr($IDCard, 12, 2));
  646. if ($tyear > date("Y") || $tyear < (date("Y") - 100)) {
  647. // $flag=0;
  648. } elseif ($tmonth < 0 || $tmonth > 12) {
  649. // $flag=0;
  650. } elseif ($tday < 0 || $tday > 31) {
  651. // $flag=0;
  652. } else {
  653. $tmonth = $tmonth >= 10 ? $tmonth : '0' . $tmonth;
  654. $tday = $tday >= 10 ? $tday : '0' . $tday;
  655. $tdate = $tyear . "-" . $tmonth . "-" . $tday;
  656. if ((time() - mktime(0, 0, 0, $tmonth, $tday, $tyear)) > 18 * 365 * 24 * 60 * 60) {
  657. // $flag=0;
  658. } else {
  659. // $flag=1;
  660. }
  661. }
  662. } elseif (strlen($IDCard) == 15) {
  663. $tyear = intval("19" . substr($IDCard, 6, 2));
  664. $tmonth = intval(substr($IDCard, 8, 2));
  665. $tday = intval(substr($IDCard, 10, 2));
  666. if ($tyear > date("Y") || $tyear < (date("Y") - 100)) {
  667. // $flag=0;
  668. } elseif ($tmonth < 0 || $tmonth > 12) {
  669. // $flag=0;
  670. } elseif ($tday < 0 || $tday > 31) {
  671. // $flag=0;
  672. } else {
  673. $tmonth = $tmonth >= 10 ? $tmonth : '0' . $tmonth;
  674. $tday = $tday >= 10 ? $tday : '0' . $tday;
  675. $tdate = $tyear . "-" . $tmonth . "-" . $tday;
  676. if ((time() - mktime(0, 0, 0, $tmonth, $tday, $tyear)) > 18 * 365 * 24 * 60 * 60) {
  677. // $flag=0;
  678. } else {
  679. // $flag=1;
  680. }
  681. }
  682. }
  683. }
  684. $sex = substr($IDCard, 16, 1) / 2 ? '男' : '女';
  685. $result['code'] = 2;//0:未知错误,1:身份证格式错误,2:无错误
  686. $result['msg'] = $msg[$result['code']];
  687. $result['sex'] = $sex;
  688. $result['cardId'] = $IDCard;
  689. $result['birthday'] = $tdate;//生日日期
  690. $result['old'] = static::yearMinus($tdate, $datestr);
  691. return $result;
  692. }
  693. public static function yearMinus($startDate, $endDate)
  694. {
  695. $y1 = date('Y', strtotime($startDate));
  696. $m1 = date('m', strtotime($startDate));
  697. $d1 = date('d', strtotime($startDate));
  698. $y2 = date('Y', strtotime($endDate));
  699. $m2 = date('m', strtotime($endDate));
  700. $d2 = date('d', strtotime($endDate));
  701. $year = $y2 - $y1;
  702. if ($m1 > $m2) {
  703. $year--;
  704. } else if ($m1 === $m2) {
  705. if ($d1 > $d2) {
  706. $year--;
  707. }
  708. } else {
  709. }
  710. return $year;
  711. }
  712. }