diff --git a/controllers/Carpayment.php b/controllers/Carpayment.php index 40ec137..92f21b5 100644 --- a/controllers/Carpayment.php +++ b/controllers/Carpayment.php @@ -115,6 +115,41 @@ class Carpayment extends CI_Controller $this->carpayment_model->p2payed($parms); } + + // MITAC 付款 + public function mitac2payed() + { + $cario_no = $this->input->post('cario_no', true); // 通訊序號 + $lpr = $this->input->post('lpr', true); // 車牌 + $amt = $this->input->post('amt', true); // 金額 + $amt_discount = $this->input->post('amt_discount', true); // 折扣 + $amt_real = $this->input->post('amt_real', true); // 實收 + $in_time = $this->input->post('in_time', true); // 入場時間 + $pay_time = $this->input->post('pay_time', true); // 付款時間 + $ck = $this->input->post('ck', true); // 驗証碼 + + // 通訊內容 + $parms = array( + 'cario_no' => $cario_no, + 'lpr' => $lpr, + 'amt' => $amt, + 'amt_discount' => $amt_discount, + 'amt_real' => $amt_real, + 'in_time' => $in_time, + 'pay_time' => $pay_time); + + if($ck != md5($parms['cario_no']. 'a' . date('dmh') . 'l' . $parms['lpr'] . 't'. $parms['amt']. 'o'. $parms['amt_discount'] . 'b'. $parms['amt_real'] . __FUNCTION__)) + { + trigger_error(__FUNCTION__ . '..ck_error..' . print_r($parms, true)); + exit; // 中斷 + } + + $parms['pay_type'] = 93; // MITAC 專用 + + trigger_error('MITAC 付款:' . print_r($parms, true)); + //$this->carpayment_model->mitac2payed($parms); + $this->carpayment_model->p2payed($parms); + } /* 月租繳款完成 diff --git a/controllers/Mitac_service.php b/controllers/Mitac_service.php new file mode 100644 index 0000000..15693fa --- /dev/null +++ b/controllers/Mitac_service.php @@ -0,0 +1,274 @@ +router->fetch_method(); + if (in_array($method_name, array('parking_fee_altob', 'deduct_result'))) + { + ob_end_clean(); + ignore_user_abort(); + ob_start(); + + echo 'ok'; + + header('Connection: close'); + header('Content-Length: ' . ob_get_length()); + ob_end_flush(); + flush(); + } + + ignore_user_abort(); // 接受client斷線, 繼續run + + $this->vars['date_time'] = date('Y-m-d H:i:s'); // 格式化時間(2015-10-12 14:36:21) + $this->vars['time_num'] = str_replace(array('-', ':', ' '), '', $this->vars['date_time']); //數字化時間(20151012143621) + $this->vars['date_num'] = substr($this->vars['time_num'], 0, 8); // 數字化日期(20151012) + $this->vars['station_no'] = STATION_NO; // 本站編號 + + // session_id(ip2long($_SERVER['REMOTE_ADDR'])); // 設定同一device為同一個session + session_start(); + + // ----- 程式開發階段log設定 ----- + if (@ENVIRONMENT == 'development') + { + ini_set('display_errors', '1'); + //error_reporting(E_ALL ^ E_NOTICE); + error_reporting(E_ALL); + } + set_error_handler(array($this, 'error_handler'), E_ALL); // 資料庫異動需做log + + // 阻檔未知的 IP + if(!in_array($_SERVER['HTTP_X_REAL_IP'], array('127.0.0.1'))) + { + trigger_error('refused://from:'.$_SERVER['HTTP_X_REAL_IP'].'..refused..'); + exit; + } + + // MITAC 模組 + $this->load->model('mitac_service_model'); + $this->mitac_service_model->init($this->vars); + } + + + // 發生錯誤時集中在此處理 + public function error_handler($errno, $errstr, $errfile, $errline, $errcontext) + { + $log_msg = explode('://', $errstr); + if (count($log_msg) > 1) + { + $log_file = $log_msg[0]; + $str = date('H:i:s')."|{$log_msg[1]}|{$errfile}|{$errline}|{$errno}\n"; + } + else + { + $log_file = APP_NAME; + $str = date('H:i:s')."|{$errstr}|{$errfile}|{$errline}|{$errno}\n"; + } + + error_log($str, 3, LOG_PATH.$log_file . '.' . date('Ymd').'.log.txt'); // 3代表參考後面的檔名 + } + + + // 顯示logs + public function show_logs() + { + $lines = $this->uri->segment(3); // 顯示行數 + if (empty($lines)) $lines = 100; // 無行數參數, 預設為40行 + + // echo '
'; + echo ''; + + passthru('/usr/bin/tail -n ' . $lines . ' ' . LOG_PATH.APP_NAME . '.' . date('Ymd').'.log.txt'); // 利用linux指令顯示倒數幾行的logs內容 + echo "\n----- " . LOG_PATH.APP_NAME . '.' . date('Ymd').'.log.txt' . ' -----'; + echo ''; + } + + // 要求扣款 (ALTOB to MITAC) + public function parking_fee_altob() + { + $seqno = $this->input->post('seqno', true); // 通訊序號 + $lpr = $this->input->post('lpr', true); // 車牌 + $in_time = $this->input->post('in_time', true); // 進場時間 + $out_time = $this->input->post('out_time', true); // 出場時間 + $gate_id = $this->input->post('gate_id', true); // 驗票機編號 + $ck = $this->input->post('ck', true); // 驗証碼 + + // 通訊內容 + $parms = array( + 'seqno' => $seqno, + 'lpr' => $lpr, + 'in_time' => $in_time, + 'out_time' => $out_time, + 'gate_id' => $gate_id); + + if($ck != md5($parms['seqno']. 'a' . date('dmh') . 'l' . $parms['lpr'] . 't'. $parms['in_time']. 'o'. $parms['out_time'] . 'b'. $parms['gate_id'] . __FUNCTION__)) + { + trigger_error(__FUNCTION__ . '..ck_error..' . print_r($parms, true)); + exit; // 中斷 + } + + trigger_error(__FUNCTION__ . '..' . print_r($parms, true)); + $this->mitac_service_model->parking_fee_altob($parms); + exit; + } + + // 回應扣款成功 (MITAC to ALTOB) + public function deduct_result() + { + $seqno = $this->input->post('seqno', true); + $lpr = $this->input->post('lpr', true); + $in_time = $this->input->post('in_time', true); + $out_time = $this->input->post('out_time', true); + $gate_id = $this->input->post('gate_id', true); + $amt = $this->input->post('amt', true); + $amt_discount = $this->input->post('amt_discount', true); + $amt_real = $this->input->post('amt_real', true); + $ck = $this->input->post('ck', true); + + // 通訊內容 + $parms = array( + 'seqno' => $seqno, + 'lpr' => $lpr, + 'in_time' => $in_time, + 'out_time' => $out_time, + 'gate_id' => $gate_id, + 'amt' => $amt, + 'amt_discount' => $amt_discount, + 'amt_real' => $amt_real); + + if($ck != md5($parms['seqno']. 'a' . date('dmh') . 'l' . $parms['lpr'] . 't'. $parms['amt']. 'o'. $parms['amt_discount'] . 'b'. $parms['amt_real'] . __FUNCTION__)) + { + trigger_error(__FUNCTION__ . '..ck_error..' . print_r($parms, true)); + exit; // 中斷 + } + + trigger_error(__FUNCTION__ . '..' . print_r($parms, true)); + $this->mitac_service_model->deduct_result($parms); + exit; + } + + // http://localhost/mitac_service.html/test_parking_fee_altob + public function test_parking_fee_altob() + { + $function_name = 'parking_fee_altob'; + $seqno = '20161004_101010'; + $lpr = 'AA1234'; + $in_time = '2017-11-11 16:40:02'; + $out_time = '2017-11-11 16:58:36'; + $gate_id = 1; + + // 通訊內容 + $parms = array( + 'seqno' => $seqno, + 'lpr' => $lpr, + 'in_time' => $in_time, + 'out_time' => $out_time, + 'gate_id' => $gate_id); + + // 驗証碼 + $parms['ck'] = md5($parms['seqno']. 'a' . date('dmh') . 'l' . $parms['lpr'] . 't'. $parms['in_time']. 'o'. $parms['out_time'] . 'b'. $parms['gate_id'] . $function_name); + + // 測試呼叫 + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, "http://localhost/mitac_service.html/{$function_name}"); + curl_setopt($ch, CURLOPT_HEADER, FALSE); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); + curl_setopt($ch, CURLOPT_POST, TRUE); + curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($parms)); + $rs = curl_exec($ch); + curl_close($ch); + + echo $rs; + exit; + } + + // http://localhost/mitac_service.html/test_49993/ + public function test_49993() + { + $seqno = '201711111_027771'; + $lpr = 'TEST1111B'; + $in_time = '20171111_190048'; + $out_time = '20171111_190048'; + $gate_id = 0; + $amt = 66; + $amt_discount = 10; + $amt_real = 56; + $msg = implode(',', ['Altob', 'DeductResult', $seqno, $lpr, $in_time, $out_time, $gate_id, $amt, $amt_discount, $amt_real]); + + $error_str = ''; + $service_port = 49993; + $address = "192.168.10.201"; + + /* Create a TCP/IP socket. */ + $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); + if ($socket === false) { + echo "socket_create() failed: reason: " . socket_strerror(socket_last_error()) . "\n"; + $error_str .= "socket_create() failed: reason: " . socket_strerror(socket_last_error()) . "\n"; + } else { + echo "OK.\n"; + } + + echo "Attempting to connect to '{$address}' on port '{$service_port}'..."; + $result = socket_connect($socket, $address, $service_port); + if ($result === false) { + echo "socket_connect() failed.\nReason: ({$result}) " . socket_strerror(socket_last_error($socket)) . "\n"; + $error_str .= "socket_connect() failed: reason: " . socket_strerror(socket_last_error($socket)) . "\n"; + } else { + echo "OK.\n"; + } + + /* + $in = pack('Ca5Ca3Ca9Ca7Ca19', 0x1c, $seqno, 0x1c, $cmd, 0x1c, + $token, 0x1f, $lpr, 0x1f, $in_time + ); + */ + $in = $msg; + $out = ''; + echo "socket_write:"; + echo "{$in}
"; + + if(!socket_write($socket, $in, strlen($in))) + { + echo('Write failed
'); + $error_str .= "socket_write() failed: reason: " . socket_strerror(socket_last_error($socket)) . "\n"; + } + echo "socket_write..OK.."; + + echo "
socket_read:"; + $out = socket_read($socket, 2048) or die("Could not read server responsen"); + //while ($out = socket_read($socket, 2048)) { + // echo $out; + //} + echo "{$out}
"; + + echo "Closing socket..."; + socket_close($socket); + echo "OK.\n\n"; + + trigger_error($error_str); + exit; + } + +} diff --git a/coworker/mitac2server.php b/coworker/mitac2server.php new file mode 100644 index 0000000..3123f21 --- /dev/null +++ b/coworker/mitac2server.php @@ -0,0 +1,115 @@ +count = 4; + +$tcp_worker->onConnect = function($connection) +{ + echo APP_NAME . "..New Connection\n"; +}; + +$tcp_worker->onClose = function($connection) +{ + echo APP_NAME . "..Connection closed\n"; +}; + +$tcp_worker->onMessage = function($connection, $tcp_in) +{ + global $ch; + + $explode_tcp_in = explode(',', $tcp_in); + $send_data = null; + + if(empty($explode_tcp_in) || count($explode_tcp_in) != 10) + { + trigger_error(".. unknown tcp_in|". print_r($explode_tcp_in, true) .'|'); + $connection->close($send_data); + } + else if($explode_tcp_in[0] != 'Altob') + { + // 判斷 receiver_name + trigger_error(".. unknown receiver_name|". print_r($explode_tcp_in, true) .'|'); + } + else if($explode_tcp_in[1] != 'DeductResult') + { + // 判斷 cmd + trigger_error(".. unknown cmd|". print_r($explode_tcp_in, true) .'|'); + $connection->close($send_data); + } + else + { + // 回應扣款成功 (MITAC to ALTOB) 目前只有這支 + $function_name = 'deduct_result'; + $seqno = $explode_tcp_in[2]; + $lpr = $explode_tcp_in[3]; + $in_time = $explode_tcp_in[4]; + $out_time = $explode_tcp_in[5]; + $gate_id = $explode_tcp_in[6]; + $amt = $explode_tcp_in[7]; + $amt_discount = $explode_tcp_in[8]; + $amt_real = $explode_tcp_in[9]; + + // 建立通訊內容 + $parms = array( + 'seqno' => $seqno, + 'lpr' => $lpr, + 'in_time' => $in_time, + 'out_time' => $out_time, + 'gate_id' => $gate_id, + 'amt' => $amt, + 'amt_discount' => $amt_discount, + 'amt_real' => $amt_real); + + // 加驗証 + $parms['ck'] = md5($parms['seqno']. 'a' . date('dmh') . 'l' . $parms['lpr'] . 't'. $parms['amt']. 'o'. $parms['amt_discount'] . 'b'. $parms['amt_real'] . $function_name); + + curl_setopt($ch, CURLOPT_URL, "http://localhost/mitac_service.html/{$function_name}/"); + curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($parms)); + $send_data = curl_exec($ch); + trigger_error(".. curl {$function_name}|{$send_data} ..".print_r($parms, true)); + } + + $connection->close($send_data); +}; + +// 執行worker +Worker::runAll(); + +// 發生錯誤時集中在此處理 +function error_handler($errno, $errstr, $errfile, $errline, $errcontext) +{ + $str = date('H:i:s')."|{$errstr}|{$errfile}|{$errline}|{$errno}\n"; + error_log($str, 3, LOG_PATH.APP_NAME . '.' . date('Ymd').'.log.txt'); // 3代表參考後面的檔名 +} diff --git a/models/Carpayment_model.php b/models/Carpayment_model.php index dbd6f5a..b700a50 100644 --- a/models/Carpayment_model.php +++ b/models/Carpayment_model.php @@ -22,8 +22,54 @@ class Carpayment_model extends CI_Model { $this->vars = $vars; } + + /* + // MITAC 通知付款完成 + public function mitac2payed($parms) + { + $where_arr = array('obj_type' => 1, 'cario_no' => $parms['cario_no'], 'obj_id' => $parms['lpr'], 'finished' => 0, 'err' => 0); + $result = $this->db->select("in_time, cario_no, station_no") + ->from('cario') + ->where($where_arr) + ->limit(1) + ->get() + ->row_array(); + + $in_time = new DateTime($result['in_time']); + $pay_time = new DateTime($parms['pay_time']); + + $data = array + ( + 'out_before_time' => date('Y-m-d H:i:s', strtotime("{$parms['pay_time']} + 15 minutes")), + 'pay_time' => $parms['pay_time'], + 'pay_type' => $parms['pay_type'], + 'payed' => 1 + ); + + // 更新 + $this->db->where($where_arr)->update('cario', $data); + + if (!$this->db->affected_rows()) + { + trigger_error("付款失敗:{$parms['lpr']}|{$data['out_before_time']}"); + return 'fail'; + } + + trigger_error("付款後更新時間:{$parms['lpr']}|{$data['out_before_time']}"); + + // 傳送付款更新記錄 + $sync_agent = new AltobSyncAgent(); + $sync_agent->init($result['station_no'], $result['in_time']); + $sync_agent->cario_no = $result['cario_no']; // 進出編號 + $sync_result = $sync_agent->sync_st_pay($parms['lpr'], $parms['pay_time'], $parms['pay_type'], + date('Y-m-d H:i:s', strtotime("{$parms['pay_time']} + 15 minutes"))); + trigger_error( "..sync_st_pay.." . $sync_result); + + return 'ok'; + } + */ - // 博辰通知付款完成 + // 通知付款完成 public function p2payed($parms, $opay=false) { $result = $this->db->select("in_time, cario_no, station_no") diff --git a/models/Cars_model.php b/models/Cars_model.php index 3f569d2..49a0d69 100644 --- a/models/Cars_model.php +++ b/models/Cars_model.php @@ -546,6 +546,10 @@ class Cars_model extends CI_Model $sync_agent->in_time = $rows_cario['in_time']; // 入場時間 $sync_result = $sync_agent->sync_st_out($parms); trigger_error( "..sync_st_out.." . $sync_result); + + // [mitac] 要求 mitac 扣款 START + $this->call_mitac_pay($parms['lpr'], $parms['ivsno'], $rows_cario); + // [mitac] 要求 mitac 扣款 END } } break; @@ -630,6 +634,10 @@ class Cars_model extends CI_Model $sync_agent->in_time = $rows_cario['in_time']; // 入場時間 $sync_result = $sync_agent->sync_st_out($parms); trigger_error( "..sync_st_out.." . $sync_result); + + // [mitac] 要求 mitac 扣款 START + $this->call_mitac_pay($parms['lpr'], $parms['ivsno'], $rows_cario); + // [mitac] 要求 mitac 扣款 END } break; } @@ -1291,5 +1299,56 @@ class Cars_model extends CI_Model } } + // =============================================== + // mitac cmd + // =============================================== + + // 要求 mitac 扣款 + function call_mitac_pay($lpr, $ivsno, $rows_cario) + { + $function_name = 'parking_fee_altob'; + $seqno = $rows_cario['cario_no']; + $lpr = $lpr; + $in_time = $rows_cario['out_before_time']; + $out_time = $this->now_str; + $gate_id = $ivsno; + + // 通訊內容 + $parms = array( + 'seqno' => $seqno, + 'lpr' => $lpr, + 'in_time' => $in_time, + 'out_time' => $out_time, + 'gate_id' => $gate_id); + + // 驗証碼 + $parms['ck'] = md5($parms['seqno']. 'a' . date('dmh') . 'l' . $parms['lpr'] . 't'. $parms['in_time']. 'o'. $parms['out_time'] . 'b'. $parms['gate_id'] . $function_name); + + // 呼叫 + try{ + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, "http://localhost/mitac_service.html/{$function_name}"); + curl_setopt($ch, CURLOPT_HEADER, FALSE); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); + curl_setopt($ch, CURLOPT_POST, TRUE); + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT ,3); + curl_setopt($ch, CURLOPT_TIMEOUT, 3); //timeout in seconds + curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($parms)); + $data = curl_exec($ch); + + if(curl_errno($ch)) + { + trigger_error(__FUNCTION__ . ', curl error: '. curl_error($ch)); + } + + curl_close($ch); + + trigger_error(__FUNCTION__ . '..'. $data); + + }catch (Exception $e){ + trigger_error(__FUNCTION__ . 'error:'.$e->getMessage()); + } + } } diff --git a/models/Mitac_service_model.php b/models/Mitac_service_model.php new file mode 100644 index 0000000..77cb9d9 --- /dev/null +++ b/models/Mitac_service_model.php @@ -0,0 +1,144 @@ +load->database(); + $this->now_str = date('Y-m-d H:i:s'); + + // MITAC 連線設定 (測試環境) + //define('MITAC_SERVICE_IP', '220.130.199.142'); + //define('MITAC_SERVICE_PORT', 49990); + + // MITAC 連線設定 (正式環境 - 現場呼叫) + define('MITAC_SERVICE_IP', '192.168.10.221'); + define('MITAC_SERVICE_PORT', 49990); + } + + // mitac socket + function mitac_socket($in) + { + trigger_error(__FUNCTION__ . "..socket input|{$in}"); + return 'ok'; + + + + $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); + if ($socket === false) { + trigger_error(__FUNCTION__ . "..socket_create() failed: reason: " . socket_strerror(socket_last_error())); + } + + $result = socket_connect($socket, MITAC_SERVICE_IP, MITAC_SERVICE_PORT); + if ($result === false) { + trigger_error(__FUNCTION__ . "..socket_connect() failed.\nReason: ({$result}) " . socket_strerror(socket_last_error($socket))); + return false; // 中斷 + } + + if(!socket_write($socket, $in, strlen($in))) + { + trigger_error(__FUNCTION__ . '..Write failed..'); + } + + $out = socket_read($socket, 64); + socket_shutdown($socket); + socket_close($socket); + trigger_error(__FUNCTION__ . "..socket output|{$out}"); + + return $out; + } + + public function init($vars) + { + $this->vars = $vars; + } + + // 要求扣款 (ALTOB to MITAC) + public function parking_fee_altob($parms) + { + // 轉換成對方要的格式 + $seqno = date('Ymd') . '_' . str_pad($parms['seqno'], 6, '0', STR_PAD_LEFT); + $lpr = $parms['lpr']; + $in_time = date('Ymd_His', strtotime($parms['in_time'])); + $out_time = date('Ymd_His', strtotime($parms['out_time'])); + $gate_id = $parms['gate_id']; + + // 產生通訊內容 + $msg = iconv("UTF-8", "ISO-8859-1", implode(',', ['Mitac', 'ParkingFee_Altob', $seqno, $lpr, $in_time, $out_time, $gate_id])); + $result = $this->mitac_socket($msg); + + trigger_error(__FUNCTION__ . "..{$msg}..|{$result}"); + return 'ok'; + } + + // 回應扣款成功 (MITAC to ALTOB) + public function deduct_result($parms) + { + $seqno_arr = explode('_', $parms['seqno']); + $in_time_arr = explode('_', $parms['in_time']); + $out_time_arr = explode('_', $parms['out_time']); + + // 解出我方要的資訊 + $cario_no = intval(preg_replace( '/[^0-9]/', '', $seqno_arr[1])); + $lpr = $parms['lpr']; + $amt = intval(preg_replace( '/[^0-9]/', '', $parms['amt'])); + $amt_discount = intval(preg_replace( '/[^0-9]/', '', $parms['amt_discount'])); + $amt_real = intval(preg_replace( '/[^0-9]/', '', $parms['amt_real'])); + $in_time = substr($in_time_arr[0], 0, 4). '-' . substr($in_time_arr[0], 4, 2) . '-' . substr($in_time_arr[0], 6, 2) . ' ' . + substr($in_time_arr[1], 0, 2). ':' . substr($in_time_arr[1], 2, 2) . ':' . substr($in_time_arr[1], 4, 2); + $pay_time = $this->now_str; + + // 通訊內容 + $parms = array( + 'cario_no' => $cario_no, + 'lpr' => $lpr, + 'amt' => $amt, + 'amt_discount' => $amt_discount, + 'amt_real' => $amt_real, + 'in_time' => $in_time, + 'pay_time' => $pay_time); + + $function_name = 'mitac2payed'; + + trigger_error(__FUNCTION__ . "..call {$function_name}.." . print_r($parms, true)); + + // 驗証碼 + $parms['ck'] = md5($parms['cario_no']. 'a' . date('dmh') . 'l' . $parms['lpr'] . 't'. $parms['amt']. 'o'. $parms['amt_discount'] . 'b'. $parms['amt_real'] . $function_name); + + // 呼叫 + try{ + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, "http://localhost/carpayment.html/{$function_name}"); + curl_setopt($ch, CURLOPT_HEADER, FALSE); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); + curl_setopt($ch, CURLOPT_POST, TRUE); + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT ,3); + curl_setopt($ch, CURLOPT_TIMEOUT, 3); //timeout in seconds + curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($parms)); + $data = curl_exec($ch); + + if(curl_errno($ch)) + { + trigger_error(__FUNCTION__ . ', curl error: '. curl_error($ch)); + } + + curl_close($ch); + + trigger_error(__FUNCTION__ . '..'. $data); + + }catch (Exception $e){ + trigger_error(__FUNCTION__ . 'error:'.$e->getMessage()); + } + + return 'ok'; + } + +}