VM暫存
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

Carpayment_model.php 30KB

8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
8年前
7年前
8年前
7年前
7年前
8年前
8年前
8年前
7年前
8年前
7年前
7年前
7年前
8年前
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878
  1. <?php
  2. /*
  3. file: carpayment_model.php
  4. */
  5. require_once(ALTOB_SYNC_FILE) ;
  6. class Carpayment_model extends CI_Model
  7. {
  8. var $vars = array();
  9. var $io_name = array('I' => '車入', 'O' => '車出', 'MI' => '機入', 'MO' => '機出', 'FI' => '樓入', 'FO' => '樓出');
  10. var $now_str;
  11. function __construct()
  12. {
  13. parent::__construct();
  14. $this->load->database();
  15. $this->now_str = date('Y-m-d H:i:s');
  16. }
  17. public function init($vars)
  18. {
  19. $this->vars = $vars;
  20. }
  21. ////////////////////////////////////////
  22. //
  23. // 付款後, 付款資訊建檔
  24. //
  25. ////////////////////////////////////////
  26. // [付款完成] 付款後續流程
  27. function payed_finished($cario_no, $lpr, $etag, $in_time)
  28. {
  29. $LOG_TAG = 'set_payed://';
  30. $LOG_TAG_FATAL = 'set_payed_fatal://';
  31. trigger_error(__FUNCTION__ . "|$cario_no 付款完成|$lpr, $etag, $in_time|");
  32. $trim_finished_cario_no_arr = array(); // 需處理的進場索引
  33. $in_time_value = strtotime($in_time);
  34. $in_time_1 = date('Y-m-d H:i:s', $in_time_value + 1); // +1 sec
  35. $in_time_2 = date('Y-m-d H:i:s', $in_time_value - 1); // -1 sec
  36. $in_time_3 = date('Y-m-d H:i:s', $in_time_value + 2); // +2 sec
  37. $in_time_4 = date('Y-m-d H:i:s', $in_time_value - 2); // -2 sec
  38. // 挑出已付款入場記錄, 入場時間附近 2 秒內, 但尚未結清之入場記錄
  39. $sql = "SELECT cario_no, obj_id as lpr, etag, in_time
  40. FROM cario
  41. WHERE in_time in ('$in_time', '$in_time_1', '$in_time_2', '$in_time_3', '$in_time_4')
  42. AND cario_no != $cario_no
  43. AND finished = 0
  44. AND payed = 0
  45. AND err = 0
  46. ";
  47. $in_time_retults = $this->db->query($sql)->result_array();
  48. if(!empty($in_time_retults) && count($in_time_retults) > 0)
  49. {
  50. $data = array();
  51. foreach ($in_time_retults as $idx => $rows)
  52. {
  53. $result_cario_no = $rows['cario_no'];
  54. $result_lpr = $rows['lpr'];
  55. $result_etag = $rows['etag'];
  56. $result_in_time = $rows['in_time'];
  57. if(empty($result_lpr) || $result_lpr == 'NONE')
  58. {
  59. if(strlen($result_etag) > 20 && $result_etag == $etag)
  60. {
  61. trigger_error($LOG_TAG . "$cario_no, $lpr, $etag, $in_time|無車牌|ETAG吻合|$result_cario_no, $result_lpr, $result_etag, $result_in_time|待註銷|skip");
  62. //array_push($trim_finished_cario_no_arr, $result_cario_no);
  63. }
  64. }
  65. else
  66. {
  67. $levenshtein_value = levenshtein($result_lpr, $lpr);
  68. if( $levenshtein_value == 0 || $levenshtein_value == 1)
  69. {
  70. trigger_error($LOG_TAG . "$cario_no, $lpr, $etag, $in_time|車牌 差0-1碼|$result_cario_no, $result_lpr, $result_etag, $result_in_time|待註銷");
  71. array_push($trim_finished_cario_no_arr, $result_cario_no);
  72. }
  73. else if($levenshtein_value == 2)
  74. {
  75. if(strlen($result_etag) > 20 && $result_etag == $etag)
  76. {
  77. trigger_error($LOG_TAG . "$cario_no, $lpr, $etag, $in_time|車牌 差2碼|ETAG吻合|$result_cario_no, $result_lpr, $result_etag, $result_in_time|待註銷|skip");
  78. //array_push($trim_finished_cario_no_arr, $result_cario_no);
  79. }
  80. }
  81. else
  82. {
  83. if(strlen($result_etag) > 20 && $result_etag == $etag)
  84. {
  85. trigger_error($LOG_TAG . "$cario_no, $lpr, $etag, $in_time|車牌不合|ETAG吻合|$result_cario_no, $result_lpr, $result_etag, $result_in_time|??");
  86. trigger_error($LOG_TAG_FATAL . "$cario_no, $lpr, $etag, $in_time|車牌不合|ETAG吻合|$result_cario_no, $result_lpr, $result_etag, $result_in_time|??");
  87. }
  88. }
  89. }
  90. }
  91. }
  92. // 執行註銷
  93. if(!empty($trim_finished_cario_no_arr))
  94. {
  95. $this->db->where_in('cario_no', $trim_finished_cario_no_arr)->update('cario', array('err' => 2))->limit(5);
  96. if (!$this->db->affected_rows())
  97. {
  98. trigger_error($LOG_TAG . "註銷失敗|" . $this->db->last_query());
  99. return 'fail';
  100. }
  101. trigger_error($LOG_TAG . "註銷成功|" . $this->db->last_query());
  102. trigger_error(__FUNCTION__ . '..trim_finished_cario_no_arr..' . print_r($trim_finished_cario_no_arr, true));
  103. }
  104. return 'ok';
  105. }
  106. // 通知付款完成
  107. public function p2payed($parms, $opay=false, $finished=false)
  108. {
  109. $result = $this->db->select("obj_id as lpr, in_time, cario_no, station_no, etag, obj_id as lpr")
  110. ->from('cario')
  111. ->where(array('obj_type' => 1, 'obj_id' => $parms['lpr'], 'finished' => 0, 'err' => 0))
  112. ->or_where(array('obj_type' => 1, 'ticket_no' => $parms['ticket_no'], 'finished' => 0, 'err' => 0))
  113. ->order_by('cario_no', 'desc')
  114. ->limit(1)
  115. ->get()
  116. ->row_array();
  117. // 找不到記錄
  118. if(!isset($result['cario_no']))
  119. {
  120. trigger_error(__FUNCTION__ . '..not found..' . print_r($parms, true));
  121. return false;
  122. }
  123. if($opay)
  124. {
  125. $pay_time = $this->now_str;
  126. $out_before_time = date('Y-m-d H:i:s', strtotime(" + 15 minutes"));
  127. $pay_type = 4;
  128. $data = array
  129. (
  130. 'out_before_time' => $out_before_time,
  131. 'pay_time' => $pay_time,
  132. 'pay_type' => 4, // 歐付寶行動支付
  133. 'payed' => 1
  134. );
  135. // 是否註記完結
  136. if($finished)
  137. $data['finished'] = 1;
  138. $this->db->where(array('cario_no' => $result['cario_no']))->update('cario', $data);
  139. if (!$this->db->affected_rows())
  140. {
  141. trigger_error("歐付寶行動支付失敗,{$parms['lpr']}金額:{$parms['amt']},序號:{$parms['seqno']}");
  142. return 'fail';
  143. }
  144. trigger_error("歐付寶行動支付成功,{$parms['lpr']}金額:{$parms['amt']},序號:{$parms['seqno']}");
  145. }
  146. else
  147. {
  148. // 若間隔小於 15 分鐘, 拿現在時間來當付款時間
  149. $pay_time = ((strtotime($parms['pay_time']) - strtotime($result['in_time'])) / 60 < 15) ? $this->now_str : $parms['pay_time'];
  150. // 限時離場時間
  151. $out_before_time = date('Y-m-d H:i:s', strtotime("{$pay_time} + 15 minutes"));
  152. // 付款方式
  153. $pay_type = $parms['pay_type'];
  154. // B. 一般繳費機
  155. $data = array
  156. (
  157. 'out_before_time' => $out_before_time,
  158. 'pay_time' => $pay_time,
  159. 'pay_type' => $pay_type,
  160. 'payed' => 1
  161. );
  162. // 是否註記完結
  163. if($finished)
  164. $data['finished'] = 1;
  165. if($parms['ticket_no'] == '000000000')
  166. {
  167. $this->db->where(array('cario_no' => $result['cario_no']))->update('cario', $data);
  168. trigger_error("付款後更新時間:{$parms['lpr']}|{$data['out_before_time']}|". print_r($data, true));
  169. }
  170. else
  171. {
  172. // 快速進場之類會帶票卡號
  173. $this->db
  174. ->where(array('obj_type' => 1, 'ticket_no' => $parms['ticket_no'], 'finished' => 0, 'err' => 0))
  175. ->update('cario', $data);
  176. // 取得車牌號碼
  177. $cario_result = $this->db->select("obj_id as lpr")
  178. ->from('cario')
  179. ->where(array('obj_type' => 1, 'ticket_no' => $parms['ticket_no'], 'finished' => 0, 'err' => 0))
  180. ->order_by('cario_no', 'desc')
  181. ->limit(1)
  182. ->get()
  183. ->row_array();
  184. $parms['lpr'] = $cario_result['lpr'];
  185. trigger_error("[票卡] 付款後更新時間:{$parms['ticket_no']}|{$data['out_before_time']}|rows:{$this->db->affected_rows()}");
  186. // 若車牌為空, 改為 NONE
  187. if(empty($parms['lpr']))
  188. {
  189. $parms['lpr'] = 'NONE';
  190. }
  191. }
  192. if (!$this->db->affected_rows())
  193. {
  194. $this->mq_send(MQ_TOPIC_ALTOB, MQ_ALTOB_POS.",1,{$parms['ticket_no']},{$parms['lpr']},{$parms['pay_time']},{$parms['in_time']}".MQ_ALTOB_POS_END_TAG);
  195. trigger_error("付款失敗:{$parms['lpr']}|{$data['out_before_time']}");
  196. return 'fail';
  197. }
  198. else
  199. {
  200. $this->mq_send(MQ_TOPIC_ALTOB, MQ_ALTOB_POS.",2,{$parms['ticket_no']},{$parms['lpr']},{$parms['pay_time']},{$parms['in_time']}".MQ_ALTOB_POS_END_TAG);
  201. }
  202. }
  203. // 付款後續流程
  204. $this->payed_finished($result['cario_no'], $parms['lpr'], $result['etag'], $result['in_time']);
  205. // 傳送付款更新記錄
  206. $sync_agent = new AltobSyncAgent();
  207. $sync_agent->init($result['station_no'], $result['in_time']);
  208. $sync_agent->cario_no = $result['cario_no']; // 進出編號
  209. $sync_result = $sync_agent->sync_st_pay($parms['lpr'], $pay_time, $pay_type, $out_before_time, $finished);
  210. trigger_error( "..sync_st_pay.." . $sync_result);
  211. return 'ok';
  212. }
  213. // 行動支付, 手機告知已付款
  214. // http://203.75.167.89/carpayment.html/m2payed/ABC1234/120/12112/12345/1f3870be274f6c49b3e31a0c6728957f
  215. // http://203.75.167.89/carpayment.html/m2payed/車牌/金額/場站編號/序號/MD5
  216. // md5(車牌.金額.場站編號.序號)
  217. public function m2payed($parms, $finished=false)
  218. {
  219. $data = array
  220. (
  221. 'out_before_time' => date('Y-m-d H:i:s', strtotime(" + 15 minutes")),
  222. 'pay_time' => date('Y-m-d H:i:s'),
  223. 'pay_type' => 4, // 歐付寶行動支付
  224. 'payed' => 1
  225. );
  226. // 是否註記完結
  227. if($finished)
  228. $data['finished'] = 1;
  229. $this->db->where(array('cario_no' => $parms['seqno']))->update('cario', $data);
  230. if ($this->db->affected_rows())
  231. {
  232. trigger_error("歐付寶行動支付成功,{$parms['lpr']}金額:{$parms['amt']},序號:{$parms['seqno']}");
  233. return 'ok';
  234. }
  235. else
  236. {
  237. trigger_error("歐付寶行動支付失敗,{$parms['lpr']}金額:{$parms['amt']},序號:{$parms['seqno']}");
  238. return 'fail';
  239. }
  240. }
  241. ////////////////////////////////////////
  242. //
  243. // 付款前, 入場資訊查找
  244. //
  245. ////////////////////////////////////////
  246. // 博辰票卡進場通知 (UPDATED 2016/08/23)
  247. public function parktron001($parms)
  248. {
  249. // 車道與裝置對應關係
  250. $lanes = array
  251. (
  252. 11 => array ('in_lane' => '0'), // 入口 1
  253. 12 => array ('in_lane' => '1') // 入口 2
  254. );
  255. if(!array_key_exists($parms['devno'], $lanes))
  256. {
  257. trigger_error("[ERROR] 未知的裝置 | {$parms['devno']}");
  258. return false;
  259. }
  260. if($parms['token'] == '000000000')
  261. {
  262. trigger_error("[ERROR] 無卡號 | {$parms['devno']}");
  263. return false;
  264. }
  265. // 由設備編號對應攝影機編號, 再對應進場記錄
  266. $result = $this->db->select("cario_no, in_time, obj_id as lpr")
  267. ->from('cario')
  268. ->where(array(
  269. 'in_out' => 'CI', 'finished' => 0, 'err' => 0, 'obj_type' => 1, 'member_no' => 0,
  270. 'in_time > ' => date("Y-m-d H:i:s", strtotime('- 1 minutes')), // 限時
  271. 'ticket_dev' => '',
  272. 'in_lane' => $lanes[$parms['devno']]['in_lane']
  273. ))
  274. ->order_by('cario_no', 'desc')
  275. ->limit(1)
  276. ->get()
  277. ->row_array();
  278. //trigger_error("[test] 車道 {$lanes[$parms['devno']]['in_lane']} test|".print_r($result, true));
  279. if (empty($result['cario_no']))
  280. {
  281. trigger_error("[ERROR] 車道 {$lanes[$parms['devno']]['in_lane']} 查無進場記錄|".print_r($parms, true));
  282. return false;
  283. }
  284. $data = array
  285. (
  286. 'ticket_dev' => $parms['devno'],
  287. 'ticket_no' => $parms['token'],
  288. 'ticket_type' => $parms['type']
  289. );
  290. $this->db
  291. ->where(array('cario_no' => $result['cario_no']))
  292. ->update('cario', $data);
  293. trigger_error("博辰票卡進場更新記錄|{$result['lpr']}|{$result['in_time']}|{$result['cario_no']}|{$parms['token']}|rows:{$this->db->affected_rows()}");
  294. }
  295. // 模糊比對
  296. function getLevenshteinSQLStatement($word, $target)
  297. {
  298. $words = array();
  299. if(strlen($word) >= 5)
  300. {
  301. for ($i = 0; $i < strlen($word); $i++) {
  302. // insertions
  303. $words[] = substr($word, 0, $i) . '_' . substr($word, $i);
  304. // deletions
  305. $words[] = substr($word, 0, $i) . substr($word, $i + 1);
  306. // substitutions
  307. //$words[] = substr($word, 0, $i) . '_' . substr($word, $i + 1);
  308. }
  309. }
  310. else
  311. {
  312. for ($i = 0; $i < strlen($word); $i++) {
  313. // insertions
  314. $words[] = substr($word, 0, $i) . '_' . substr($word, $i);
  315. }
  316. }
  317. // last insertion
  318. $words[] = $word . '_';
  319. //return $words;
  320. $fuzzy_statement = ' (';
  321. foreach ($words as $idx => $word)
  322. {
  323. $fuzzy_statement .= " {$target} LIKE '%{$word}%' OR ";
  324. }
  325. $last_or_pos = strrpos($fuzzy_statement, 'OR');
  326. if($last_or_pos !== false)
  327. {
  328. $fuzzy_statement = substr_replace($fuzzy_statement, ')', $last_or_pos, strlen('OR'));
  329. }
  330. return $fuzzy_statement;
  331. }
  332. // 取得進場資訊 (模糊比對)
  333. function q_fuzzy_pks($word)
  334. {
  335. if(empty($word) || strlen($word) < 4 || strlen($word) > 10)
  336. {
  337. return null;
  338. }
  339. /*
  340. // 備援數字使用
  341. else if(is_numeric($word) && strlen($word) == 6)
  342. {
  343. trigger_error(__FUNCTION__ . '..備援查詢: ' . $word);
  344. $sql = "SELECT obj_id as lpr, ticket_no
  345. FROM cario
  346. WHERE finished = 0 AND err = 0
  347. AND out_before_time > DATE_SUB(CURRENT_TIMESTAMP, INTERVAL 5 DAY)
  348. AND ticket_no = {$word}
  349. ORDER BY out_before_time DESC";
  350. $retults = $this->db->query($sql)->result_array();
  351. return $retults;
  352. }
  353. */
  354. $fuzzy_statement = $this->getLevenshteinSQLStatement($word, 'obj_id');
  355. //trigger_error("模糊比對 {$word} where: {$fuzzy_statement}");
  356. $sql = "SELECT obj_id as lpr, ticket_no
  357. FROM cario
  358. WHERE {$fuzzy_statement} AND finished = 0 AND err = 0
  359. AND out_before_time > DATE_SUB(CURRENT_TIMESTAMP, INTERVAL 5 DAY)
  360. GROUP BY obj_id
  361. ORDER BY out_before_time DESC";
  362. $retults = $this->db->query($sql)->result_array();
  363. return $retults;
  364. }
  365. // 建立博辰查詢入場時間資料 (by ticket_no)
  366. function gen_query_data_type4($ticket_no)
  367. {
  368. $data = array();
  369. // s2. 完整車牌號碼: 右邊補空格補滿7碼
  370. $data['lpr'] = $ticket_no;
  371. // s3. 塔號_車格號碼: 該車牌相關車輛所停車的停車塔號或樓層號碼,
  372. // 地下室部分為負值例如B1為-1,平面停車場為1,二樓為2 (左邊補 ‘0’ 補滿2碼),
  373. // 停車格號4碼(左邊補 ‘0’ 補滿4碼),
  374. // 樓層和停車格號中間以 ‘_’ 分隔,例如:”01_0101”
  375. $data['seat_no'] = 'XX_XXXX';
  376. $data['ticket'] = 0;
  377. $data['start_date'] = '2000/01/01';
  378. $data['end_date'] = '2000/01/01';
  379. $data['start_time'] = '00:00';
  380. $data['end_time'] = '00:00';
  381. $result = $this->db->select("in_time, date_format(pay_time, '%Y/%m/%d %T') as pay_time, in_pic_name, member_no, in_lane, in_out, station_no")
  382. ->from('cario')
  383. ->where(array('obj_type' => 1, 'ticket_no' => $ticket_no, 'finished' => 0, 'err' => 0))
  384. ->order_by('cario_no', 'desc')
  385. ->limit(1)
  386. ->get()
  387. ->row_array();
  388. if (!empty($result['in_time']))
  389. {
  390. // s5. 入場時間: 格式為"yyyy/MM/dd HH:mm:ss",時間為24小時制,若無紀錄秒數秒數部分可填”00”
  391. $data['in_time'] = $result['in_time'];
  392. // s6. 入場車牌圖片路徑: 貴公司的絕對路徑,我方使用網路芳鄰或FTP下載
  393. $data['in_pic_name'] = $this->gen_in_pic_path($result);
  394. // s7. 繳費時間: 無繳費時間時為"2000/01/01 00:00:00",格式為"yyyy/MM/dd HH:mm:ss",時間為24小時制,若無紀錄秒數秒數部分可填”00”
  395. $data['pay_time'] = !empty($result['pay_time']) ? $result['pay_time'] : '2000/01/01 00:00:00';
  396. // s12. 停車位置區域代碼: 從 1 開始
  397. $data['area_code'] = $this->gen_area_code($result);
  398. }
  399. else
  400. {
  401. $data['in_time'] = '';
  402. $data['in_pic_name'] = '';
  403. $data['pay_time'] = '2000/01/01 00:00:00';
  404. $data['area_code'] = 1;
  405. }
  406. return $data;
  407. }
  408. // 取得圖檔路徑
  409. function gen_in_pic_path($cario)
  410. {
  411. // 北車西上特例
  412. $station_local_ip = ($cario['station_no'] == 12304)? '192.168.10.203' : STATION_LOCAL_IP;
  413. //科博館新建特例
  414. $station_local_ip = ($cario['station_no'] == 40709)? '192.168.9.201' : STATION_LOCAL_IP;
  415. if(!empty($cario['in_pic_name']))
  416. {
  417. $pic_name_arr = explode('-', $cario['in_pic_name']);
  418. $date_num = substr($pic_name_arr[7], 0, 8);
  419. return "\\\\" . $station_local_ip . "\\pics\\{$date_num}\\{$cario['in_pic_name']}";
  420. }
  421. else if(file_exists(CAR_PIC . 'lpr-404.jpg'))
  422. {
  423. return "\\\\" . $station_local_ip . "\\pics\\lpr-404.jpg"; // 預設圖片
  424. }
  425. return '';
  426. }
  427. // 產生區域代碼 (判斷 in_out, in_lane, station_no)
  428. function gen_area_code($cario)
  429. {
  430. // 1: 北車西上 (一般車)
  431. // 2: 北車西上 (機車)
  432. // 3: 北車西下 (一般車)
  433. // 4: 北車西下 (計程車)
  434. // 北車西下
  435. if($cario['station_no'] == 12303)
  436. {
  437. if($cario['in_lane'] == 0)
  438. {
  439. return 4; // 4: 北車西下 (計程車)
  440. }
  441. else
  442. {
  443. return 3; // 3: 北車西下 (一般車)
  444. }
  445. }
  446. // 北車西上
  447. else if($cario['station_no'] == 12304)
  448. {
  449. if(substr($cario['in_out'], 0, 1) === 'C')
  450. {
  451. return 1; // 1: 北車西上 (一般車)
  452. }
  453. else
  454. {
  455. return 2; // 2: 北車西上 (機車)
  456. }
  457. }
  458. return 1; // 預設值
  459. }
  460. // 建立博辰查詢入場時間資料
  461. function gen_query_data($lpr)
  462. {
  463. $data = array();
  464. // s2. 完整車牌號碼: 右邊補空格補滿7碼
  465. $data['lpr'] = $lpr; //str_pad($lpr, 7, ' ', STR_PAD_RIGHT);
  466. // s3. 塔號_車格號碼: 該車牌相關車輛所停車的停車塔號或樓層號碼,
  467. // 地下室部分為負值例如B1為-1,平面停車場為1,二樓為2 (左邊補 ‘0’ 補滿2碼),
  468. // 停車格號4碼(左邊補 ‘0’ 補滿4碼),
  469. // 樓層和停車格號中間以 ‘_’ 分隔,例如:”01_0101”
  470. $sql = "select p.pksno, m.group_id
  471. from pks p, pks_group_member m, pks_groups g
  472. where p.pksno = m.pksno
  473. and m.group_id = g.group_id
  474. and g.group_type = 1
  475. and p.lpr = '{$lpr}'
  476. limit 1";
  477. $rows = $this->db->query($sql)->row_array();
  478. if (!empty($rows['pksno']))
  479. {
  480. //$data['seat_no'] = ($rows['group_id'] == 'B1' ? '-1' : '0' . substr($rows['group_id'], -1)) . '_0' . substr($rows['pksno'], -3);
  481. $group_floor_type = preg_replace( '/[^A-Z]/', '', $rows['group_id']);
  482. $group_floor_num = preg_replace( '/[^1-9]/', '', $rows['group_id']);
  483. if($group_floor_type == 'B')
  484. {
  485. $data['seat_no'] = '-' . $group_floor_num . '_0' . substr($rows['pksno'], -3);
  486. }
  487. else
  488. {
  489. $group_floor_num = str_pad($group_floor_num, 2, '0', STR_PAD_LEFT);
  490. $data['seat_no'] = $group_floor_num . '_0' . substr($rows['pksno'], -3);
  491. }
  492. }
  493. else
  494. {
  495. $data['seat_no'] = 'XX_XXXX'; // '-1_0028';
  496. }
  497. // 查詢是否月租會員
  498. $result = $this->db->select("date_format(start_date, '%Y/%m/%d') as start_date, date_format(end_date,'%Y/%m/%d') as end_date")
  499. ->from('members')
  500. ->where(array(
  501. 'lpr' => $lpr,
  502. 'start_date <' => $this->vars['date_time'],
  503. 'end_date >=' => $this->vars['date_time'])
  504. , false)
  505. ->limit(1)
  506. ->get()
  507. ->row_array();
  508. if (!empty($result['start_date'])) // 月租會員
  509. {
  510. $data['ticket'] = 1; // s4. 是否為月票: 0:非月票, 1:月票
  511. $data['start_date'] = $result['start_date'];// s8. 有效起始時間: 非月票時為"2000/01/01", 格式為"yyyy/MM/dd"
  512. $data['end_date'] = $result['end_date']; // s9. 有效截止日期: 非月票時為"2000/01/01", 格式為"yyyy/MM/dd"
  513. $data['start_time'] = '00:00'; // s10. 使用起始時段: 非月票時為"00:00", 格式為"HH:mm"
  514. $data['end_time'] = '23:59'; // s11. 使用結束時段: 非月票時為"00:00", 格式為"HH:mm"
  515. }
  516. else // 臨停車
  517. {
  518. $data['ticket'] = 0;
  519. $data['start_date'] = '2000/01/01';
  520. $data['end_date'] = '2000/01/01';
  521. $data['start_time'] = '00:00';
  522. $data['end_time'] = '00:00';
  523. }
  524. $result = $this->db->select("in_time, date_format(pay_time, '%Y/%m/%d %T') as pay_time, in_pic_name, member_no, in_lane, in_out, station_no")
  525. ->from('cario')
  526. //->where(array('obj_type' => 1, 'obj_id' => $lpr, 'finished' => 0, 'err' => 0))
  527. ->where(array('obj_type' => 1, 'obj_id' => $lpr, 'finished' => 0, 'err' => 0, 'ticket_type' => 0)) // 20180130 刷卡進的跳過
  528. ->order_by('cario_no', 'desc')
  529. ->limit(1)
  530. ->get()
  531. ->row_array();
  532. if (!empty($result['in_time']))
  533. {
  534. // s5. 入場時間: 格式為"yyyy/MM/dd HH:mm:ss",時間為24小時制,若無紀錄秒數秒數部分可填”00”
  535. $data['in_time'] = $result['in_time'];
  536. // s6. 入場車牌圖片路徑: 貴公司的絕對路徑,我方使用網路芳鄰或FTP下載
  537. $data['in_pic_name'] = $this->gen_in_pic_path($result);
  538. // s7. 繳費時間: 無繳費時間時為"2000/01/01 00:00:00",格式為"yyyy/MM/dd HH:mm:ss",時間為24小時制,若無紀錄秒數秒數部分可填”00”
  539. $data['pay_time'] = !empty($result['pay_time']) ? $result['pay_time'] : '2000/01/01 00:00:00';
  540. // s12. 停車位置區域代碼: 從 1 開始
  541. $data['area_code'] = $this->gen_area_code($result);
  542. }
  543. else
  544. {
  545. $data['in_time'] = '';
  546. $data['in_pic_name'] = '';
  547. $data['pay_time'] = '2000/01/01 00:00:00';
  548. $data['area_code'] = 1;
  549. }
  550. return $data;
  551. }
  552. // 博辰查詢入場時間 (fuzzy)
  553. public function query_in_fuzzy($lpr)
  554. {
  555. $fuzzy_result = $this->q_fuzzy_pks($lpr);
  556. $data_count = 0;
  557. if(!empty($fuzzy_result) && count($fuzzy_result) > 0)
  558. {
  559. $data = array();
  560. // s2 ~ s11 的資料會因模糊比對筆數增加或減少而增減
  561. foreach ($fuzzy_result as $idx => $rows)
  562. {
  563. $result_lpr = $rows['lpr'];
  564. $ticket_no = $rows['ticket_no'];
  565. if($result_lpr == 'NONE')
  566. {
  567. $tmp_data = $this->gen_query_data_type4($ticket_no); // 備緩搜尋
  568. }
  569. else
  570. {
  571. $tmp_data = $this->gen_query_data($result_lpr); // 模糊搜尋
  572. }
  573. if($tmp_data['ticket'] == 1)
  574. {
  575. trigger_error("月租車, 直接乎略這筆[{$result_lpr}]:".print_r($rows, true));
  576. }
  577. else if($tmp_data['in_time'] == '')
  578. {
  579. // 若查無入場時間, 直接乎略這筆
  580. trigger_error("查無入場時間, 直接乎略這筆[{$result_lpr}]:".print_r($rows, true));
  581. }
  582. else
  583. {
  584. $data['results'][$idx] = $tmp_data;
  585. $data_count++;
  586. }
  587. }
  588. $data['count'] = $data_count;
  589. }
  590. // 查無資料
  591. if($data_count == 0)
  592. {
  593. $data_0 = array();
  594. $data_0['lpr'] = str_pad($lpr, 7, ' ', STR_PAD_RIGHT);
  595. $data_0['seat_no'] = 'XX_XXXX';
  596. $data_0['ticket'] = 0;
  597. $data_0['start_date'] = '2000/01/01';
  598. $data_0['end_date'] = '2000/01/01';
  599. $data_0['start_time'] = '00:00';
  600. $data_0['end_time'] = '00:00';
  601. $data_0['in_time'] = '';
  602. $data_0['pay_time'] = '2000/01/01 00:00:00';
  603. $data_0['in_pic_name'] = '';
  604. $data_0['area_code'] = 1;
  605. $data = array();
  606. $data['results'][0] = $data_0;
  607. $data['count'] = 0;
  608. }
  609. trigger_error("fuzzy aps查詢入場時間[{$lpr}]:".print_r($data, true));
  610. return $data;
  611. }
  612. // 博辰查詢入場時間
  613. public function query_in($lpr)
  614. {
  615. $data = array();
  616. // 讀取樓層數, group_type = 2為樓層
  617. $sql = "select p.pksno, m.group_id
  618. from pks p, pks_group_member m, pks_groups g
  619. where p.pksno = m.pksno
  620. and m.group_id = g.group_id
  621. and g.group_type = 1
  622. and p.lpr = '{$lpr}'
  623. limit 1";
  624. $rows = $this->db->query($sql)->row_array();
  625. if (!empty($rows['pksno']))
  626. {
  627. //$data['seat_no'] = ($rows['group_id'] == 'B1' ? '-1' : '0' . substr($rows['group_id'], -1)) . '_' . substr($rows['pksno'], -3);
  628. $group_floor_type = preg_replace( '/[^A-Z]/', '', $rows['group_id']);
  629. $group_floor_num = preg_replace( '/[^1-9]/', '', $rows['group_id']);
  630. if($group_floor_type == 'B')
  631. {
  632. $data['seat_no'] = '-' . $group_floor_num . '_0' . substr($rows['pksno'], -3);
  633. }
  634. else
  635. {
  636. $group_floor_num = str_pad($group_floor_num, 2, '0', STR_PAD_LEFT);
  637. $data['seat_no'] = $group_floor_num . '_0' . substr($rows['pksno'], -3);
  638. }
  639. }
  640. else
  641. {
  642. $data['seat_no'] = 'XX_XXXX';
  643. }
  644. // 查詢是否月租會員
  645. $result = $this->db->select("date_format(start_date, '%Y/%m/%d') as start_date, date_format(end_date,'%Y/%m/%d') as end_date")
  646. ->from('members')
  647. ->where(array('lpr' => $lpr, 'end_date >=' => $this->vars['date_time']), false)
  648. ->limit(1)
  649. ->get()
  650. ->row_array();
  651. if (!empty($result['start_date'])) // 月租會員
  652. {
  653. $data['ticket'] = 1;
  654. $data['start_date'] = $result['start_date'];
  655. $data['end_date'] = $result['end_date'];
  656. $data['start_time'] = '00:00';
  657. $data['end_time'] = '23:59';
  658. }
  659. else // 臨停車
  660. {
  661. $data['ticket'] = 0;
  662. $data['start_date'] = '2000/01/01';
  663. $data['end_date'] = '2000/01/01';
  664. $data['start_time'] = '00:00';
  665. $data['end_time'] = '00:00';
  666. }
  667. $result = $this->db->select("in_time, date_format(pay_time, '%Y/%m/%d %T') as pay_time, in_pic_name, member_no, station_no")
  668. ->from('cario')
  669. ->where(array('obj_type' => 1, 'obj_id' => $lpr, 'finished' => 0, 'err' => 0))
  670. ->order_by('cario_no', 'desc')
  671. ->limit(1)
  672. ->get()
  673. ->row_array();
  674. if (!empty($result['in_time']))
  675. {
  676. trigger_error("aps查詢入場時間|{$lpr}|{$result['in_time']}|{$result['in_pic_name']}");
  677. $data['in_time'] = $result['in_time'];
  678. $data['pay_time'] = !empty($result['pay_time']) ? $result['pay_time'] : '2000/01/01 00:00:00';
  679. $data['in_pic_name'] = $this->gen_in_pic_path($result);
  680. $data['records'] = 1;
  681. }
  682. else
  683. {
  684. $data['in_time'] = '';
  685. $data['pay_time'] = '2000/01/01 00:00:00';
  686. $data['in_pic_name'] = '';
  687. $data['records'] = 0;
  688. }
  689. trigger_error("aps查詢入場時間[{$lpr}]:".print_r($data, true));
  690. // return array('in_time' => '', 'in_pic_name' => '', 'records' => 0, 'ticket' => 0, 'seat_no' => 'XX_XXXX');
  691. return $data;
  692. }
  693. // 行動設備查詢入場時間
  694. // http://203.75.167.89/carpayment.html/m2query_in/ABC1234/12112/1f3870be274f6c49b3e31a0c6728957f
  695. // http://203.75.167.89/carpayment.html/m2query_in/車牌/場站編號/MD5
  696. // 回傳0: 失敗, 成功: 12345,60(第一欄位非0數字代表成功, 第二欄位為金額), 此值在付款時必需傳回, 否則視為非法
  697. public function m2query_in($parms)
  698. {
  699. $result = $this->db->select('cario_no, out_before_time')
  700. ->from('cario')
  701. ->where(array('obj_type' => 1, 'obj_id' => $parms['lpr'], 'station_no' => $parms['station_no'], 'finished' => 0, 'err' => 0))
  702. ->order_by('cario_no', 'desc')
  703. ->limit(1)
  704. ->get()
  705. ->row_array();
  706. if (!empty($result['cario_no']))
  707. {
  708. trigger_error("行動設備查詢入場時間成功|{$lpr}|{$result['cario_no']}|{$result['in_time']}");
  709. // call計費模組
  710. $amt = 10;
  711. }
  712. else
  713. {
  714. $result['cario_no'] = 0;
  715. $amt = 0;
  716. trigger_error('行動設備查詢入場時間失敗'.print_r($parms, true));
  717. }
  718. return "{$result['cario_no']},{$amt}";
  719. }
  720. // 臨停未結清單
  721. public function cario_temp_not_finished_query_all($station_no, $q_item, $q_str)
  722. {
  723. $where_station = $station_no == 0 ? '' : " station_no = {$station_no} and "; // 如為0, 則全部場站讀取
  724. switch($q_item)
  725. {
  726. case 'in_time':
  727. $items = "{$q_item} >=";
  728. $q_str .= ' 23:59:59';
  729. break;
  730. case 'lpr':
  731. $items = "{$q_item} like ";
  732. $q_str = strtoupper($q_str).'%';
  733. break;
  734. default:
  735. $items = "{$q_item} like ";
  736. $q_str .= '%';
  737. break;
  738. }
  739. $sql = "
  740. SELECT
  741. cario_no,
  742. station_no,
  743. obj_id as lpr,
  744. in_time,
  745. out_before_time,
  746. pay_time
  747. FROM cario
  748. WHERE
  749. {$where_station} {$items} '{$q_str}'
  750. and obj_type = 1 and finished = 0 and err = 0 and confirms = 0
  751. and member_no = 0
  752. and out_time is null
  753. ORDER BY cario.cario_no asc
  754. ";
  755. //trigger_error(__FUNCTION__ . "test sql: {$sql}");
  756. $results = $this->db->query($sql)->result_array();
  757. return $results;
  758. }
  759. // 送出至message queue(目前用mqtt)
  760. public function mq_send($topic, $msg)
  761. {
  762. $this->vars['mqtt']->publish($topic, $msg, 0);
  763. trigger_error("mqtt:{$topic}|{$msg}");
  764. usleep(100000); // delay 0.1 sec (避免漏訊號)
  765. }
  766. }