| @@ -0,0 +1,157 @@ | |||
| <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); | |||
| /* | |||
| |-------------------------------------------------------------------------- | |||
| | File and Directory Modes | |||
| |-------------------------------------------------------------------------- | |||
| | | |||
| | These prefs are used when checking and setting modes when working | |||
| | with the file system. The defaults are fine on servers with proper | |||
| | security, but you may wish (or even need) to change the values in | |||
| | certain environments (Apache running a separate process for each | |||
| | user, PHP under CGI with Apache suEXEC, etc.). Octal values should | |||
| | always be used to set the mode correctly. | |||
| | | |||
| */ | |||
| define('FILE_READ_MODE', 0644); | |||
| define('FILE_WRITE_MODE', 0666); | |||
| define('DIR_READ_MODE', 0755); | |||
| define('DIR_WRITE_MODE', 0777); | |||
| /* | |||
| |-------------------------------------------------------------------------- | |||
| | File Stream Modes | |||
| |-------------------------------------------------------------------------- | |||
| | | |||
| | These modes are used when working with fopen()/popen() | |||
| | | |||
| */ | |||
| define('FOPEN_READ', 'rb'); | |||
| define('FOPEN_READ_WRITE', 'r+b'); | |||
| define('FOPEN_WRITE_CREATE_DESTRUCTIVE', 'wb'); // truncates existing file data, use with care | |||
| define('FOPEN_READ_WRITE_CREATE_DESTRUCTIVE', 'w+b'); // truncates existing file data, use with care | |||
| define('FOPEN_WRITE_CREATE', 'ab'); | |||
| define('FOPEN_READ_WRITE_CREATE', 'a+b'); | |||
| define('FOPEN_WRITE_CREATE_STRICT', 'xb'); | |||
| define('FOPEN_READ_WRITE_CREATE_STRICT', 'x+b'); | |||
| /*end*/ | |||
| // user define | |||
| // define('DEBUG_MODE', true); | |||
| define('APP_BASE', '/home/bigbang/apps/parkings/'); // 應用系統根路徑 | |||
| define('FILE_BASE', '/home/data/parkings/'); // 檔案存取根路徑 | |||
| define('CAR_PIC', FILE_BASE.'cars/pics/'); // 車輛照片存檔路徑 | |||
| define('PKS_PIC', FILE_BASE.'pks/pics/'); // 車輛入車格照片存檔路徑 | |||
| define('EXPORT_BASE', '/home/data/export/'); // 檔案匯出根路徑 | |||
| define('STATION_NAME', '未設定'); // 本場站名稱 | |||
| define('STATION_NO', 54321); // 本場站編號 | |||
| define('STATION_IP', '192.168.0.201'); // 本場站IP | |||
| define('STATION_URL', 'http://'.STATION_IP.'/'); // 本場站URL | |||
| define('PHPLIBS_BASE', '/home/bigbang/libs/phplibs/'); // phplibs 根路徑 | |||
| define('ALTOB_SYNC_FILE', PHPLIBS_BASE.'Altob.Sync.Integration.php'); // ALTOB (同步) | |||
| define('ALTOB_CRYPT_FILE', PHPLIBS_BASE.'Altob.Crypt.Integration.php'); // ALTOB (資料加解密) | |||
| define('ALTOB_BILL_FILE', PHPLIBS_BASE.'Altob.Payment.Integration.php'); // ALTOB (金流: 費率) | |||
| define('ALTOB_TWGC_FILE', PHPLIBS_BASE.'Altob.TWGC.Integration.php'); // ALTOB (歐Pa卡: TWGC) | |||
| define('ALTOB_CTBC_FILE', PHPLIBS_BASE.'ctbcbank/Altob.CTBC.Bank.Integration.php'); // 中國信託 (金流) | |||
| define('ALLPAY_FILE', PHPLIBS_BASE.'AllPay.Payment.Integration.php'); // 歐付寶 (金流) | |||
| define('ALLPAY_INVOICE_FILE', PHPLIBS_BASE.'AllPay_Invoice.php'); // 歐付寶 (電子發票) | |||
| define('MQ_CLASS_FILE', PHPLIBS_BASE.'phpMQTT.php'); // MQTT: class file name | |||
| define('MQ_HOST', '192.168.0.202'); // MQTT: host | |||
| define('MQ_PORT', 1883); // MQTT: port (default:1883) | |||
| define('MQ_TOPIC_SUBLEVEL', 'SUBLEVEL'); // MQTT TOPIC: 樓層在席顯示 | |||
| define('MQ_TOPIC_SUBTEXT', 'SUBTEXT'); // MQTT TOPIC: 出入口字幕機 | |||
| define('MQ_TOPIC_OPEN_DOOR', 'OPEN_DOOR'); // MQTT TOPIC: 出入口開門 | |||
| define('MQ_TOPIC_ALTOB', 'altob.com.tw.mqtt'); // MQTT TOPIC: common mqtt topic | |||
| define('MQ_ALTOB_MSG', 'msg'); // MQTT TOPIC: cmd: msg | |||
| define('MQ_ALTOB_MSG_END_TAG', ',altob'); // MQTT TOPIC: cmd: msg end tag | |||
| define('MQ_ALTOB_888', '888'); // MQTT TOPIC: cmd: 888 | |||
| define('MQ_ALTOB_888_END_TAG', ',altob'); // MQTT TOPIC: cmd: 888 end tag | |||
| define('MEMCACHE_HOST', 'localhost'); // memcache host | |||
| define('MEMCACHE_PORT', 11211); // memcache post no (default:11211) | |||
| // Date.timezone | |||
| //date_default_timezone_set("Asia/Taipei"); // <-- TODO: php.ini 無效 ????????????????????????????????????????????? | |||
| /* | |||
| |-------------------------------------------------------------------------- | |||
| | 自定義連結 - 共用設定 | |||
| |-------------------------------------------------------------------------- | |||
| */ | |||
| define("ALTOB_PAYMENT_TXDATA_URL", "http://localhost/txdata.html"); // 費率 ServiceURL | |||
| /* | |||
| |-------------------------------------------------------------------------- | |||
| | LOG檔名 - 共用設定 | |||
| |-------------------------------------------------------------------------- | |||
| */ | |||
| define("MEMBER_LOG_TITLE", 'member-log://'); // 會員資料記錄 | |||
| define("TX_LOG_TITLE", 'tx-log://'); // 交易資料記錄 | |||
| define("ADMIN_LOG_TITLE", 'admin-log://'); // 管理操作記錄 | |||
| define("EXPORT_LOG_TITLE", 'export-log://'); // 檔案匯出記錄 | |||
| /* | |||
| |-------------------------------------------------------------------------- | |||
| | 資料庫欄位 - 共用設定 | |||
| |-------------------------------------------------------------------------- | |||
| */ | |||
| // member_tx.verify_state | |||
| define("MEMBER_TX_VERIFY_STATE_NONE", 0); // 0: 未審核 | |||
| define("MEMBER_TX_VERIFY_STATE_OK", 1); // 1: 人工審核完成 | |||
| define("MEMBER_TX_VERIFY_STATE_GG", 99); // 99: 審核不通過 | |||
| // member_tx.tx_state | |||
| define("MEMBER_TX_TX_STATE_NONE", 0); // 0: 無 | |||
| define("MEMBER_TX_TX_STATE_STOP", 4); // 4: 已退租 | |||
| define("MEMBER_TX_TX_STATE_CANCEL", 44); // 44: 交易取消 | |||
| // member_tx_bill.invoice_state | |||
| define("MEMBER_TX_BILL_INVOICE_STATE_NONE", 0); // 0: 無 | |||
| define("MEMBER_TX_BILL_INVOICE_STATE_MORE", 1); // 1: 待補開 | |||
| define("MEMBER_TX_BILL_INVOICE_STATE_ALLOWANCE", 2); // 2: 待折讓 | |||
| define("MEMBER_TX_BILL_INVOICE_STATE_MORE_DONE", 91); // 91: 補開完成 | |||
| define("MEMBER_TX_BILL_INVOICE_STATE_ALLOWANCE_DONE", 92); // 92: 折讓完成 | |||
| // member_refund.refund_state | |||
| define("MEMBER_REFUND_STATE_NONE", 0); // 0: 無 | |||
| define("MEMBER_REFUND_STATE_MORE_INVOICE", 1); // 1: 待補開 | |||
| define("MEMBER_REFUND_STATE_LESS_INVOICE", 2); // 2: 待折讓 | |||
| define("MEMBER_REFUND_STATE_DONE", 100); // 100: 已完成 | |||
| // member_refund.dismiss_state | |||
| define("MEMBER_REFUND_DISMISS_STATE_NONE", 0); // 0: 無 | |||
| define("MEMBER_REFUND_DISMISS_STATE_TRANSFERRED", 1); // 1: 已轉租 | |||
| define("MEMBER_REFUND_DISMISS_STATE_KEEP_DEPOSIT", 10); // 10: 押金未退 | |||
| define("MEMBER_REFUND_DISMISS_STATE_DONE", 100); // 100: 已結清 | |||
| // tx_bill_ats.status | |||
| define("TX_BILL_ATS_STATUS_NONE", 0); // 0: 剛建立 | |||
| define("TX_BILL_ATS_STATUS_PAID", 1); // 1: 結帳完成 | |||
| define("TX_BILL_ATS_STATUS_INVOICE_VOID", 104); // 104: 發票已作廢 | |||
| define("TX_BILL_ATS_STATUS_INVOICE_ALLOWANCE", 105); // 105: 發票已折讓 | |||
| // tx_bill.status | |||
| define("TX_BILL_STATUS_NONE", 0); // 0: 剛建立 | |||
| define("TX_BILL_STATUS_PAID", 1); // 1: 結帳完成 | |||
| define("TX_BILL_STATUS_ERROR_AMT", 2); // 2: 錢沒對上 | |||
| define("TX_BILL_STATUS_ERROR_INVOICE", 3); // 3: 發票沒建立 | |||
| define("TX_BILL_STATUS_HAND_MODE", 4); // 4: 手動調整 | |||
| define("TX_BILL_STATUS_TIME_OUT", 99); // 99: 訂單逾期作廢 | |||
| define("TX_BILL_STATUS_PROCESSING", 100); // 100: 交易進行中 | |||
| define("TX_BILL_STATUS_FAIL", 101); // 101: 交易失敗 | |||
| define("TX_BILL_STATUS_DONE", 111); // 111: 產品已領取 | |||
| /* End of file constants.php */ | |||
| /* Location: ./application/config/constants.php */ | |||
| @@ -0,0 +1,215 @@ | |||
| <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); | |||
| /* | |||
| file: Acer_service.php 與 acer 介接相關都放這支 | |||
| */ | |||
| // ----- 定義常數(路徑, cache秒數) ----- | |||
| define('APP_VERSION', '100'); // 版本號 | |||
| define('MAX_AGE', 604800); // cache秒數, 此定義1個月 | |||
| define('APP_NAME', 'acer_service'); // 應用系統名稱 | |||
| define('PAGE_PATH', APP_BASE.'ci_application/views/'.APP_NAME.'/'); // path of views | |||
| define('SERVER_URL', 'http://'.(isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : 'localhost').'/'); // URL | |||
| define('APP_URL', SERVER_URL.APP_NAME.'.html/'); // controller路徑 | |||
| define('WEB_URL', SERVER_URL.APP_NAME.'/'); // 網頁路徑 | |||
| define('WEB_LIB', SERVER_URL.'/libs/'); // 網頁lib | |||
| define('BOOTSTRAPS', WEB_LIB.'bootstrap_sb/'); // bootstrap lib | |||
| define('LOG_PATH', FILE_BASE.APP_NAME.'/logs/'); // log path name | |||
| define('LOG_FILE', FILE_BASE.APP_NAME.'/logs/acer_service.'); // log file name | |||
| class Acer_service extends CI_Controller | |||
| { | |||
| var $vars = array(); | |||
| function __construct() | |||
| { | |||
| parent::__construct(); | |||
| $method_name = $this->router->fetch_method(); | |||
| if (in_array($method_name, array('cmd_101', 'cmd_102'))) | |||
| { | |||
| ob_end_clean(); | |||
| ignore_user_abort(); | |||
| ob_start(); | |||
| 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 | |||
| $this->load->model('acer_service_model'); | |||
| $this->acer_service_model->init($this->vars); | |||
| // 阻檔未知的 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; | |||
| } | |||
| } | |||
| // 發生錯誤時集中在此處理 | |||
| 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 '<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body><pre style="white-space: pre-wrap;">'; | |||
| echo '<html lang="zh-TW"><body><pre style="white-space: pre-wrap;">'; | |||
| 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 '</pre></body></html>'; | |||
| } | |||
| // 票卡入場訊號,供 ALTOB 登記 | |||
| public function cmd_001() | |||
| { | |||
| $card_no = $this->input->post('card_no', true); | |||
| $cario_no = $this->input->post('cario_no', true); | |||
| $card_type = $this->input->post('card_type', true); | |||
| trigger_error(__FUNCTION__ . ", card_no:{$card_no}, cario_no:{$cario_no}, card_type:{$card_type}"); | |||
| $data = $this->acer_service_model->cmd_001($card_no, $cario_no, $card_type); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // 票卡離場訊號,供 ALTOB 登記 | |||
| public function cmd_002() | |||
| { | |||
| $card_no = $this->input->post('card_no', true); | |||
| $pay_time = $this->input->post('pay_time', true); | |||
| $card_type = $this->input->post('card_type', true); | |||
| trigger_error(__FUNCTION__ . ", card_no:{$card_no}, pay_time:{$pay_time}, card_type:{$card_type}"); | |||
| $data = $this->acer_service_model->cmd_002($card_no, $pay_time, $card_type); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // 票號離場訊號,回傳若成功觸發 ACER 開門 | |||
| public function cmd_003() | |||
| { | |||
| $ticket_no = $this->input->post('ticket_no', true); | |||
| trigger_error(__FUNCTION__ . ", ticket_no:{$ticket_no}"); | |||
| $data = $this->acer_service_model->cmd_003($ticket_no); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // 車辨入場訊號,觸發 ACER 開門 | |||
| public function cmd_101() | |||
| { | |||
| $cario_no = $this->input->post('cario_no', true); | |||
| $in_time = $this->input->post('in_time', true); | |||
| $ticket_no = $this->input->post('ticket_no', true); | |||
| $lpr = $this->input->post('lpr', true); | |||
| $ivs_no = $this->input->post('ivs_no', true); | |||
| trigger_error(__FUNCTION__ . ", cario_no:{$cario_no}, in_time:{$in_time}, ticket_no:{$ticket_no}, lpr:{$lpr}, ivs_no:{$ivs_no}"); | |||
| $data = $this->acer_service_model->cmd_101($cario_no, $in_time, $ticket_no, $lpr, $ivs_no); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // 車辨離場訊號,觸發 ACER 開門 (若入場編號為 0, 表示車辨失敗) | |||
| public function cmd_102() | |||
| { | |||
| $cario_no = $this->input->post('cario_no', true); | |||
| $ivs_no = $this->input->post('ivs_no', true); | |||
| $msg_code = $this->input->post('msg_code', true); | |||
| /* msg_code: | |||
| 1 離場車辨失敗 | |||
| 2 離場會員鎖車 | |||
| 5 會員車離場 | |||
| 6 臨停車離場 (時間內離場, 已繳費) | |||
| 7 臨停車離場 (超過離場時限, 歐pa卡繳費) | |||
| 8 臨停車未付款 (時間內離場, 無繳費) | |||
| 9 臨停車未付款 (超過離場時限, 非歐pa卡會員) | |||
| 10 會員車離場 (無入場資料) | |||
| 12 臨停車未付款 (超過離場時限, 歐pa卡餘額不足) | |||
| 13 無入場記錄 | |||
| 16 時段月租戶超時(月租) | |||
| */ | |||
| trigger_error(__FUNCTION__ . ", cario_no:{$cario_no}, ivs_no:{$ivs_no}, msg_code:{$msg_code}"); | |||
| $data = $this->acer_service_model->cmd_102($cario_no, $ivs_no, $msg_code); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // 測試 acer cmd 101 | |||
| public function test_acer_cmd_101() | |||
| { | |||
| // input | |||
| $cario_no = '1234567890'; // 入場編號: 10 碼 | |||
| $in_time = '2017-04-25 15:15:15'; // 入場時間: 19碼 | |||
| $ticket_no = '123456'; // 六碼數字 | |||
| $lpr = 'ABC123'; | |||
| $ivsno = 1; // 車道編號 | |||
| $data = $this->acer_service_model->cmd_101($cario_no, $in_time, $ticket_no, $lpr, $ivsno); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // 測試 acer cmd 102 | |||
| public function test_acer_cmd_102() | |||
| { | |||
| // input | |||
| $cario_no = '1234567890'; // 入場編號: 10 碼 | |||
| $ivsno = 1; // 車道編號 | |||
| $data = $this->acer_service_model->cmd_102($cario_no, $ivsno); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| } | |||
| @@ -0,0 +1,574 @@ | |||
| <?php | |||
| /* | |||
| file: Allpa_service.php (歐Pa卡) | |||
| */ | |||
| if ( ! defined('BASEPATH')) exit('No direct script access allowed'); | |||
| class Allpa_service extends CI_Controller | |||
| { | |||
| var $vars = array(); // 共用變數 | |||
| function __construct() | |||
| { | |||
| parent::__construct(); | |||
| $method_name = $this->router->fetch_method(); | |||
| if ($method_name == 'allpa_consume_handler') | |||
| { | |||
| ob_end_clean(); | |||
| ignore_user_abort(); | |||
| ob_start(); | |||
| header('Connection: close'); | |||
| header('Content-Length: ' . ob_get_length()); | |||
| ob_end_flush(); | |||
| flush(); | |||
| } | |||
| // ----- 程式開發階段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 | |||
| /* | |||
| // 共用記憶體 | |||
| $this->vars['mcache'] = new Memcache; | |||
| $this->vars['mcache']->connect(MEMCACHE_HOST, MEMCACHE_PORT) or die ('Could not connect memcache'); | |||
| // mqtt subscribe | |||
| $this->vars['mqtt'] = new phpMQTT(MQ_HOST, MQ_PORT, uniqid()); | |||
| if(!$this->vars['mqtt']->connect()){ die ('Could not connect mqtt'); } | |||
| */ | |||
| // ----- 定義常數(路徑, cache秒數) ----- | |||
| define('APP_VERSION', '100'); // 版本號 | |||
| define('MAX_AGE', 604800); // cache秒數, 此定義1個月 | |||
| define('APP_NAME', 'allpa_service'); // 應用系統名稱 | |||
| define('PAGE_PATH', APP_BASE.'ci_application/views/'.APP_NAME.'/'); // path of views | |||
| define('SERVER_URL', 'http://'.(isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : 'localhost').'/'); // URL | |||
| define('APP_URL', SERVER_URL.APP_NAME.'.html/'); // controller路徑 | |||
| define('WEB_URL', SERVER_URL.APP_NAME.'/'); // 網頁路徑 | |||
| define('WEB_LIB', SERVER_URL.'libs/'); // 網頁lib | |||
| define('BOOTSTRAPS', WEB_LIB.'bootstrap_sb/'); // bootstrap lib | |||
| define('LOG_PATH', FILE_BASE.APP_NAME.'/logs/'); // log path | |||
| $this->load->model('allpa_service_model'); // 歐Pa卡 | |||
| $this->load->model('allpay_invoice_model'); // 歐付寶電子發票 | |||
| // ----- 中國信託金流 ----- | |||
| $this->load->model('ctbcbank_model'); // 中國信託金流 | |||
| define('CTBC_AuthResURL', APP_URL."return_ok/"); // 從收單行端取得授權碼後,要導回的網址,請勿填入特殊字元@、#、%、?、&等。 | |||
| // ----- 中國信託金流 (end) ----- | |||
| // ----- 頁面 ----- | |||
| define('MAIN_PAGE', "main_page"); | |||
| define('RESULT_PAGE', "result_page"); | |||
| define('ERROR_PAGE', "error_page"); | |||
| define('ADMIN_PAGE', "admin_page"); | |||
| define('ADMIN_LOGIN_PAGE', "admin_login_page"); | |||
| define('ADMIN_RESULT_PAGE', "admin_result_page"); | |||
| // ----- 頁面 ----- | |||
| // [START] 2016/06/08 登入 | |||
| $this->load->model('user_model'); | |||
| // load library | |||
| $this->load->library(array('form_validation','session')); | |||
| // load helpers | |||
| $this->load->helper(array('form')); | |||
| // ajax code | |||
| define('RESULT_SUCCESS', 'ok'); | |||
| define('RESULT_FORM_VALIDATION_FAIL', '-1'); | |||
| define('RESULE_FAIL', 'gg'); | |||
| // [END] 2016/06/08 登入 | |||
| } | |||
| // 發生錯誤時集中在此處理 | |||
| public function error_handler($errno, $errstr, $errfile, $errline, $errcontext) | |||
| { | |||
| $str = date('H:i:s')."|{$errstr}|{$errfile}|{$errline}|{$errno}\n"; | |||
| //error_log($str, 3, $log_file . '.' . date('Ymd').'.log.txt'); // 3代表參考後面的檔名 | |||
| //echo "whoami: ".`whoami`; | |||
| //echo "<br/>".$str; | |||
| error_log($str, 3, LOG_PATH.APP_NAME . '.' . date('Ymd').'.log.txt'); // 3代表參考後面的檔名 | |||
| } | |||
| // 顯示靜態網頁(html檔) | |||
| protected function show_page($page_name, &$data = null) | |||
| { | |||
| $page_file = PAGE_PATH.$page_name.'.php'; | |||
| $last_modified_time = filemtime($page_file); | |||
| // 若檔案修改時間沒有異動, 或版本無異動, 通知瀏覽器使用cache, 不再下傳網頁 | |||
| // header('Cache-Control:max-age='.MAX_AGE); // cache 1個月 | |||
| header('Last-Modified: '.gmdate('D, d M Y H:i:s', $last_modified_time).' GMT'); | |||
| header('Etag: '. APP_VERSION); | |||
| header('Cache-Control: public'); | |||
| if (!empty($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] == APP_VERSION && @strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) == $last_modified_time) | |||
| { | |||
| header('HTTP/1.1 304 Not Modified'); | |||
| } | |||
| else | |||
| { | |||
| $this->load->view(APP_NAME.'/'.$page_name, $data); | |||
| } | |||
| } | |||
| // [START] 2016/06/08 | |||
| // ADMIN.1 管理者頁面 | |||
| public function admin() | |||
| { | |||
| if($this->session->userdata('logged_in')) | |||
| { | |||
| $session_data = $this->session->userdata('logged_in'); | |||
| $data['username'] = $session_data['username']; | |||
| $data['type'] = $session_data['type']; | |||
| if($data['type'] == 'admin') | |||
| { | |||
| $this->show_page('NOT_READY___', $data); // 進階管理者介面 (TODO) | |||
| } | |||
| else | |||
| { | |||
| $this->show_page(ADMIN_PAGE, $data); // 一般 | |||
| } | |||
| } | |||
| else | |||
| { | |||
| $this->show_page(ADMIN_LOGIN_PAGE); | |||
| } | |||
| } | |||
| // ADMIN.2.a 管理者頁面登入 | |||
| public function user_login() | |||
| { | |||
| // form_validation | |||
| $this->form_validation->set_rules('login_name', 'login_name', 'trim|required'); | |||
| $this->form_validation->set_rules('pswd', 'pswd', 'trim|required'); | |||
| if($this->form_validation->run() == FALSE) | |||
| { | |||
| return RESULT_FORM_VALIDATION_FAIL; | |||
| } | |||
| // go model | |||
| $data = array | |||
| ( | |||
| 'login_name' => $this->input->post('login_name', true), | |||
| 'pswd' => $this->input->post('pswd', true) | |||
| ); | |||
| $result = $this->user_model->user_login($data); | |||
| if($result) | |||
| { | |||
| $sess_array = array(); | |||
| foreach($result as $row) | |||
| { | |||
| $sess_array = array | |||
| ( | |||
| 'username' => $row->login_name , | |||
| 'type' => $row->user_type | |||
| ); | |||
| $this->session->set_userdata('logged_in', $sess_array); | |||
| } | |||
| echo RESULT_SUCCESS; | |||
| } | |||
| else | |||
| { | |||
| return RESULE_FAIL; | |||
| } | |||
| } | |||
| // ADMIN.2.b 管理者頁面登出 | |||
| public function user_logout() | |||
| { | |||
| if(!$this->session->userdata('logged_in')){echo json_encode(null, JSON_UNESCAPED_UNICODE);return;} // 沒登入就回傳null | |||
| $this->session->unset_userdata('logged_in'); | |||
| session_destroy(); | |||
| return RESULT_SUCCESS; | |||
| } | |||
| // ADMIN.3.a 管理者產品列表 | |||
| // http://203.75.167.89/allpa_service.html/get_allpa_admin_products | |||
| public function get_allpa_admin_products() | |||
| { | |||
| if(!$this->session->userdata('logged_in')){echo json_encode(null, JSON_UNESCAPED_UNICODE);return;} // 沒登入就回傳null | |||
| $data = $this->allpa_service_model->get_allpa_admin_products(); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // ADMIN.3.b 產品列表 - 購買管理者產品 | |||
| public function purchase_admin_products() | |||
| { | |||
| if(!$this->session->userdata('logged_in')){echo json_encode(null, JSON_UNESCAPED_UNICODE);return;} // 沒登入就回傳null | |||
| $product_id = $this->input->post('product_id', true); | |||
| $data = $this->allpa_service_model->create_admin_bill($product_id); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // ADMIN.3.c 管理者結帳 | |||
| public function transfer_money_admin() | |||
| { | |||
| if(!$this->session->userdata('logged_in')){echo json_encode(null, JSON_UNESCAPED_UNICODE);return;} // 沒登入就回傳null | |||
| $lpr = strtoupper($this->uri->segment(3)); // 車牌號碼 | |||
| $order_no = strtoupper($this->uri->segment(4)); // 交易序號 | |||
| $invoice_receiver = urldecode($this->uri->segment(5)); // 載具編號 (可有可無) | |||
| $company_no = urldecode($this->uri->segment(6)); // 載具編號 (可有可無) | |||
| $email_base64 = $this->uri->segment(7); // 電子信箱 | |||
| $mobile = $this->uri->segment(8); // 手機號碼 | |||
| // decode email | |||
| if(strlen($email_base64) > 0){ | |||
| $email = base64_decode($email_base64.'='); // base64字串尾端的'='還原 | |||
| }else{ | |||
| $email = email_base64; | |||
| } | |||
| $data = $this->allpa_service_model->pay_bill($lpr, $order_no, $invoice_receiver, $company_no, $email, $mobile); // 記錄訂單設定 | |||
| // 管理員結帳流程 | |||
| if (!empty($data)){ | |||
| $data = $this->allpa_service_model->get_product_bill($order_no); | |||
| if (!empty($data)){ | |||
| $order_no = $data['order_no']; | |||
| $lpr = $data['lpr']; | |||
| $amt = $data['amt']; | |||
| $status = $data['status']; | |||
| switch($status){ | |||
| case 100: // 狀態: 0:剛建立, 1:結帳完成, 2:錢沒對上, 3:發票沒建立, 4:手動調整, 99:訂單逾期作廢, 100:交易進行中, 101: 交易失敗, 111:產品已領取 | |||
| // 先記錄 | |||
| $this->allpa_service_model->transfer_money_done($order_no); | |||
| // 開立歐付寶電子發票 | |||
| $this->allpay_invoice_model->invoice_issue_for_product_bill($order_no, $amt); | |||
| // 直接開卡 | |||
| $this->allpa_service_model->activate_bill_for_new_register($order_no); | |||
| // 交易成功 | |||
| $this->show_page(ADMIN_RESULT_PAGE); | |||
| break; | |||
| default: | |||
| // 對方多傳一次時?? | |||
| trigger_error(__FUNCTION__.', order_no=>' . $order_no.'<br>'.'status != 100'); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| // [END] 2016/06/08 | |||
| // 首頁 | |||
| public function index() | |||
| { | |||
| $this->show_page(MAIN_PAGE); | |||
| } | |||
| // 管理 | |||
| /* | |||
| public function admin() | |||
| { | |||
| $this->show_page(ADMIN_PAGE); | |||
| } | |||
| */ | |||
| // A.1 查詢, 用戶歐Pa卡資訊 | |||
| // http://203.75.167.89/allpa_service.html/get_allpa_info | |||
| public function get_allpa_info() | |||
| { | |||
| $user_lpr = strtoupper($this->input->post('user_lpr', true)); | |||
| $data = $this->allpa_service_model->get_allpa_info($user_lpr); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // A.2 卡片查詢 (API) | |||
| public function get_barcode_info() | |||
| { | |||
| $barcode = $this->input->post('barcode', true); | |||
| $result = $this->allpa_service_model->get_barcode_info($barcode); | |||
| echo json_encode($result, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // A.3 卡片記名 (API) | |||
| public function card_register() | |||
| { | |||
| $lpr = strtoupper($this->input->post('lpr', true)); | |||
| $barcode = $this->input->post('barcode', true); | |||
| $result = $this->allpa_service_model->card_register($lpr, $barcode); | |||
| echo json_encode($result, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // B.1 啟用, 產品 | |||
| public function activate_bill() | |||
| { | |||
| $order_no = $this->input->post('order_no', true); | |||
| $data = $this->allpa_service_model->activate_bill($order_no); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // B.2 儲值 | |||
| public function allpa_reload() | |||
| { | |||
| $order_no = $this->input->post('order_no', true); | |||
| $reload_pin = $this->input->post('reload_pin', true); | |||
| $pin_check_id = $this->input->post('pin_check_id', true); | |||
| $data = $this->allpa_service_model->allpa_reload($order_no, $reload_pin, $pin_check_id); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // B.3 扣款 | |||
| public function allpa_pay_bill() | |||
| { | |||
| $order_no = $this->input->post('order_no', true); | |||
| $data = $this->allpa_service_model->allpa_pay_bill($order_no); | |||
| if(! $data["result_code"]){ | |||
| $data = $this->allpa_service_model->get_allpa_info($data["lpr"]); | |||
| } | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // C.1 產品列表 | |||
| // http://203.75.167.89/allpa_service.html/get_allpa_products | |||
| public function get_allpa_products() | |||
| { | |||
| $data = $this->allpa_service_model->get_allpa_products(); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // C.2 產品列表 - 購買 | |||
| public function purchase() | |||
| { | |||
| $product_id = $this->input->post('product_id', true); | |||
| $data = $this->allpa_service_model->create_bill($product_id); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // C.3 付款 | |||
| public function transfer_money() | |||
| { | |||
| $lpr = strtoupper($this->uri->segment(3)); // 車牌號碼 | |||
| $order_no = strtoupper($this->uri->segment(4)); // 交易序號 | |||
| $invoice_receiver = urldecode($this->uri->segment(5)); // 載具編號 (可有可無) | |||
| $company_no = urldecode($this->uri->segment(6)); // 載具編號 (可有可無) | |||
| $email_base64 = $this->uri->segment(7); // 電子信箱 | |||
| $mobile = $this->uri->segment(8); // 手機號碼 | |||
| // decode email | |||
| if(strlen($email_base64) > 0){ | |||
| $email = base64_decode($email_base64.'='); // base64字串尾端的'='還原 | |||
| }else{ | |||
| $email = email_base64; | |||
| } | |||
| $data = $this->allpa_service_model->pay_bill($lpr, $order_no, $invoice_receiver, $company_no, $email, $mobile); // 記錄訂單設定 | |||
| if (!empty($data)){ | |||
| $this->ctbcbank_model->transfer_money_ctbc($data, CTBC_AuthResURL); // 中國信託 | |||
| } | |||
| } | |||
| // C.4 收單行端取得授權碼後,要導回的網址 (call by CTBC) | |||
| public function return_ok() | |||
| { | |||
| /** | |||
| =======ALL_REQUEST====== | |||
| URLResEnc: AF2100C51A9E844A1E820B953EA512BE49286403253FF9373474F6AE4A5877B084DD4D9B20F03AF0F34DB3D42A9C583938FE5DC1B60C53384864D9581EE997F92552A2F516B04F2FB2FE3E5C10D61CE84C5B63B87379F1048E16AC430AE94989724D8B0087734F73BF40CE904A05D555F526E5A93462C42931A0A7EC1E6AFF8BC39E641A8F5EE8882BD5B02F838BC217A87533AB9FE98CE1DD558B3CC345FC77D06C1783067F75DF94C58B55A826CD33B32355439BF3C9F17A4596138942B4457B66EB8FA09749C246D5B91799FB3942EC90138033272D89861B8698398FF4F3010628C0D11C7D88FB7A5F85CC59717D9F8D5CADBA5A1231E0396AE344B1DA139BA84F9D477E53A73A376BFCC92B52619E3B396BB28ABE7C4CEE3D3ED2CA1BEEF466F2D645C5CBF1C678C5747BA2A048F2F0FC2B86CAE379DE7A7F144D07C31A | |||
| merID: 10063 | |||
| ----------------------------END | |||
| */ | |||
| // 取得回傳資訊 | |||
| foreach ($_REQUEST as $key => $value) { | |||
| switch ($key){ | |||
| case "URLResEnc": $resenc = $value; break; | |||
| case "merID": $merid = $value; break; | |||
| } | |||
| } | |||
| if(! empty($resenc)){ | |||
| $return_data = $this->ctbcbank_model->ctbcbank_return_handler($resenc, $merid); | |||
| $ctbc_lidm = $return_data['lidm']; | |||
| $ctbc_authamt = $return_data['authamt']; | |||
| $ctbc_status = $return_data['status']; | |||
| if($ctbc_status != 0){ | |||
| // 金流處理失敗 | |||
| $this->allpa_service_model->transfer_money_done_with_tx_error($order_no); | |||
| }else if(! empty($ctbc_lidm)) { | |||
| $data = $this->allpa_service_model->get_product_bill($ctbc_lidm); | |||
| if (! empty($data)) { | |||
| $order_no = $data['order_no']; | |||
| $lpr = $data['lpr']; | |||
| $amt = $data['amt']; | |||
| $status = $data['status']; | |||
| switch($status){ | |||
| case 100: // 狀態: 0:剛建立, 1:結帳完成, 2:錢沒對上, 3:發票沒建立, 4:手動調整, 99:訂單逾期作廢, 100:交易進行中, 101: 交易失敗, 111:產品已領取 | |||
| // 印發票流程 | |||
| if($ctbc_authamt == $amt){ | |||
| // 先記錄 | |||
| $this->allpa_service_model->transfer_money_done($order_no); | |||
| // 開立歐付寶電子發票 | |||
| $this->allpay_invoice_model->invoice_issue_for_product_bill($order_no, $amt); | |||
| // 直接開卡 | |||
| $this->allpa_service_model->activate_bill_for_new_register($order_no); | |||
| // 交易成功 | |||
| $this->show_page(RESULT_PAGE); | |||
| return; | |||
| }else{ | |||
| // 錢沒對上 | |||
| $this->allpa_service_model->transfer_money_done_with_amt_error($order_no); | |||
| } | |||
| break; | |||
| default: | |||
| // 對方多傳一次時?? | |||
| trigger_error(__FUNCTION__.', order_no=>' . $order_no.'<br>'.'status != 100'); | |||
| } | |||
| }else{ | |||
| // 我們自己找不到記錄時?? | |||
| trigger_error(__FUNCTION__.', order_no=>' . $order_no.'<br>'.' NOT FOUND !!'); | |||
| } | |||
| }else{ | |||
| // 回傳沒有資料 lidm | |||
| trigger_error(__FUNCTION__.', ERROR ..lidm=>' . $ctbc_lidm); | |||
| } | |||
| }else{ | |||
| // 回傳沒有資料 resenc | |||
| trigger_error(__FUNCTION__.', ERROR ..resenc=>' . $resenc); | |||
| } | |||
| // 交易失敗 | |||
| $this->show_page(ERROR_PAGE); | |||
| } | |||
| // L.1 歐Pa卡 - 開門 (限制存取) | |||
| // http://203.75.167.89/allpa_service.html/allpa_go/1458699630/QQQ/12112/5dfe0856f3cdf67772710c3e7e805b80 | |||
| // http://203.75.167.89/allpa_service.html/allpa_go/1458714030/EEE/12112/19dd4f6692057ad897dc4e0290183a58 | |||
| // http://203.75.167.89/allpa_service.html/allpa_go/1458714030/YYY/12112/efb076ad1c1d615e6db8c718c116d2d2 | |||
| // http://203.75.167.89/allpa_service.html/allpa_go/1458714030/MMM/12112/4da21617852b4b43b86f8ac36f9db3e5 | |||
| // http://203.75.167.89/allpa_service.html/allpa_go/1458714030/BBB/12112/335f61a2a90ba3277cfe0f4cd1a07e26 // KO | |||
| // http://203.75.167.89/allpa_service.html/allpa_go/1458897030/KKK/12112/b72332e2939a1a3152aa9d31ef945952 | |||
| // http://203.75.167.89/allpa_service.html/allpa_go/1459078230/SAYLXXX/12112/5dd8036423fa8eeb7115cd4249327e08 | |||
| public function allpa_go() | |||
| { | |||
| $in_time = $this->uri->segment(3); // 進場時間 | |||
| $lpr = $this->uri->segment(4); // 車牌號碼 | |||
| $station_no = $this->uri->segment(5); // 場站編號 | |||
| $check_mac = $this->uri->segment(6); // 驗証欄位 | |||
| ob_end_clean(); | |||
| ignore_user_abort(); | |||
| ob_start(); | |||
| $data = $this->allpa_service_model->allpa_go($in_time, $lpr, $station_no, $check_mac); // 開門 | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| header('Connection: close'); | |||
| header('Content-Length: ' . ob_get_length()); | |||
| ob_end_flush(); | |||
| flush(); | |||
| // 呼叫: 非同步扣款流程 | |||
| if(!$data["result_code"]){ | |||
| file_get_contents(APP_URL."allpa_consume_handler/{$data["order_no"]}"); | |||
| } | |||
| } | |||
| // L.2 歐Pa卡 - 非同步扣款 (限制存取) | |||
| public function allpa_consume_handler() | |||
| { | |||
| $order_no = $this->uri->segment(3); // 訂單編號 | |||
| $this->allpa_service_model->allpa_pay_bill($order_no); // 扣款 | |||
| //sleep(5); // test delay | |||
| exit(); | |||
| } | |||
| // L.3 歐Pa卡 - 判斷有效用戶 (限制存取) | |||
| public function get_allpa_valid_user() | |||
| { | |||
| $lpr = $this->uri->segment(3); // 車牌號碼 | |||
| $check_mac = $this->uri->segment(4); // 驗証欄位 | |||
| ob_end_clean(); | |||
| ignore_user_abort(); | |||
| ob_start(); | |||
| $data = $this->allpa_service_model->get_allpa_valid_user($lpr, $check_mac); // check user | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| header('Connection: close'); | |||
| header('Content-Length: ' . ob_get_length()); | |||
| ob_end_flush(); | |||
| flush(); | |||
| } | |||
| // only test | |||
| public function gen_test_link() | |||
| { | |||
| $in_time = strtotime("2016-03-29 16:50:00"); | |||
| $lpr = "SAYLXXX"; | |||
| $station_no = "12112"; | |||
| echo "TEST: ".APP_URL."allpa_go/{$in_time}/{$lpr}/{$station_no}/".md5($in_time.$lpr.$station_no); | |||
| echo "<br/>"; | |||
| echo "TEST: ".APP_URL."get_allpa_valid_user/{$lpr}/".md5($lpr); | |||
| header('Connection: close'); | |||
| header('Content-Length: ' . ob_get_length()); | |||
| ob_end_flush(); | |||
| flush(); | |||
| } | |||
| } | |||
| @@ -0,0 +1,260 @@ | |||
| <?php | |||
| /* | |||
| file: Allpay_invoice.php 歐付寶電子發票 | |||
| */ | |||
| if ( ! defined('BASEPATH')) exit('No direct script access allowed'); | |||
| // ----- 定義常數(路徑, cache秒數) ----- | |||
| define('APP_VERSION', '100'); // 版本號 | |||
| define('MAX_AGE', 604800); // cache秒數, 此定義1個月 | |||
| define('APP_NAME', 'allpay_invoice'); // 應用系統名稱 | |||
| define('PAGE_PATH', APP_BASE.'ci_application/views/'.APP_NAME.'/'); // path of views | |||
| define('SERVER_URL', 'http://'.$_SERVER['HTTP_HOST'].'/'); // URL | |||
| define('WEB_SERVICE', 'http://'.$_SERVER['SERVER_NAME'].':60133/?'); // web service port:60133 | |||
| define('WEB_LIB', SERVER_URL.'libs/'); // 網頁lib | |||
| define('BOOTSTRAPS', WEB_LIB.'bootstrap_sb/'); // bootstrap lib | |||
| define('APP_URL', SERVER_URL.APP_NAME.'.html/'); // controller路徑 | |||
| define('WEB_URL', SERVER_URL.APP_NAME.'/'); // 網頁路徑 | |||
| define('LOG_PATH', FILE_BASE.APP_NAME.'/logs/'); // log path | |||
| class Allpay_invoice extends CI_Controller | |||
| { | |||
| var $vars = array(); // 共用變數 | |||
| function __construct() | |||
| { | |||
| parent::__construct(); | |||
| // ----- 程式開發階段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 | |||
| // 費率 | |||
| $this->load->model('allpay_invoice_model'); | |||
| } | |||
| // 發生錯誤時集中在此處理 | |||
| public function error_handler($errno, $errstr, $errfile, $errline, $errcontext) | |||
| { | |||
| // ex: car_err://message.... | |||
| $log_msg = explode('://', $errstr); | |||
| if (count($log_msg) > 1) | |||
| { | |||
| $log_file = LOG_PATH.$log_msg[0]; | |||
| $str = date('H:i:s')."|{$log_msg[1]}|{$errfile}|{$errline}|{$errno}\n"; | |||
| } | |||
| else | |||
| { | |||
| $log_file = LOG_PATH.APP_NAME; | |||
| $str = date('H:i:s')."|{$errstr}|{$errfile}|{$errline}|{$errno}\n"; | |||
| } | |||
| $str = date('H:i:s')."|{$errstr}|{$errfile}|{$errline}|{$errno}\n"; | |||
| error_log($str, 3, $log_file . '.' . date('Ymd').'.log.txt'); // 3代表參考後面的檔名 | |||
| } | |||
| // 顯示靜態網頁(html檔) | |||
| protected function show_page($page_name, &$data = null) | |||
| { | |||
| $page_file = PAGE_PATH.$page_name.'.php'; | |||
| $last_modified_time = filemtime($page_file); | |||
| /* | |||
| // Cross-Origin Resource Sharing Header(允許跨網域連線) | |||
| header('Access-Control-Allow-Origin: ' . SERVER_URL); | |||
| header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS'); | |||
| header('Access-Control-Allow-Headers: X-Requested-With, Content-Type, Accept'); | |||
| */ | |||
| // 若檔案修改時間沒有異動, 或版本無異動, 通知瀏覽器使用cache, 不再下傳網頁 | |||
| // header('Cache-Control:max-age='.MAX_AGE); // cache 1個月 | |||
| header('Last-Modified: '.gmdate('D, d M Y H:i:s', $last_modified_time).' GMT'); | |||
| header('Etag: '. APP_VERSION); | |||
| header('Cache-Control: public'); | |||
| if (!empty($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] == APP_VERSION && @strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) == $last_modified_time) | |||
| { | |||
| header('HTTP/1.1 304 Not Modified'); | |||
| } | |||
| else | |||
| { | |||
| $this->load->view(APP_NAME.'/'.$page_name, $data); | |||
| } | |||
| } | |||
| public function index() | |||
| { | |||
| $this->show_page('main_page'); | |||
| } | |||
| /* | |||
| // step 1: 建立待開記錄 | |||
| public function test_step1() | |||
| { | |||
| $station_no = 54321; | |||
| $tx_bill_no = 12; | |||
| $amt = 1600; | |||
| $data = $this->allpay_invoice_model->test_step1_init_bill($station_no, $tx_bill_no, $amt); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // step 2: 開立發票參數 | |||
| public function test_step2() | |||
| { | |||
| $order_no = '14906858560000000012'; | |||
| $company_no = 0; | |||
| $email = 'saylxxx@gmail.com'; | |||
| $mobile = '0953034986'; | |||
| $invoice_receiver = 0; | |||
| $data = $this->allpay_invoice_model->test_step2_submit_purchase($order_no, $company_no, $email, $mobile, $invoice_receiver); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // step 1: 建立待開記錄與參數 | |||
| public function test_step1_step2_submit() | |||
| { | |||
| $station_no = 54321; | |||
| $tx_bill_no = 12; | |||
| $amt = 1600; | |||
| $company_no = 0; | |||
| $email = 'saylxxx@gmail.com'; | |||
| $mobile = '0953034986'; | |||
| $invoice_receiver = 0; | |||
| $data = $this->allpay_invoice_model->test_step1_step2_submit( | |||
| $station_no, $tx_bill_no, $amt, | |||
| $company_no, $email, $mobile, $invoice_receiver); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // step 3: 開立發票 | |||
| public function test_step3() | |||
| { | |||
| $order_no = '14906866680000000012'; | |||
| $amt = 1600; | |||
| $data = $this->allpay_invoice_model->invoice_issue_for_tx_bill_ats($order_no, $amt); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // 測試:M.1 建立月租系統發票待開記錄 | |||
| public function test_create_member_tx_bill_record() | |||
| { | |||
| $station_no = 54321; | |||
| $tx_bill_no = 12; | |||
| $amt = 1600; | |||
| $company_no = 0; | |||
| $email = 'saylxxx@gmail.com'; | |||
| $mobile = '0953034986'; | |||
| $data = $this->allpay_invoice_model->create_member_tx_bill_record($station_no, $tx_bill_no, $amt, $company_no, $email, $mobile); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| // 回傳, 要記下 order_no | |||
| // {"invoice_remark":"停車費用帳單","order_no":"14906884740000000012","station_no":54321,"amt":1600,"email":"saylxxx@gmail.com","mobile":"0953034986","status":1,"tx_time":"2017\/03\/28 16:07:54","tx_type":100} | |||
| } | |||
| // 測試:M.2 開立月租系統待開發票 | |||
| public function test_create_member_tx_bill_invoice() | |||
| { | |||
| $order_no = '14906884740000000012'; | |||
| $amt = 1600; | |||
| $data = $this->allpay_invoice_model->create_member_tx_bill_invoice($order_no, $amt); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| // 回傳 | |||
| // {"invoice_no":"TM00012802","result_code":"OK","result_msg":"成功"} | |||
| } | |||
| // 測試:作廢發票 | |||
| public function test_invoice_void() | |||
| { | |||
| $invoice_no = 'TM00012665'; | |||
| $reason_str = 'test'; | |||
| $data = $this->allpay_invoice_model->invoice_void($invoice_no, $reason_str); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // 測試:作廢月租系統發票 | |||
| public function test_void_member_tx_bill_invoice() | |||
| { | |||
| $station_no = "54321"; | |||
| $order_no = "14906958880000000025"; | |||
| $invoice_no = "TM00012805"; | |||
| $data = $this->allpay_invoice_model->void_member_tx_bill_invoice($station_no, $order_no, $invoice_no); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // 測試:開立折讓 | |||
| public function test_invoice_allowance() | |||
| { | |||
| $invoice_no = 'TM00012665'; | |||
| $allowance_amt = 1600; | |||
| $data = $this->allpay_invoice_model->invoice_allowance($invoice_no, $allowance_amt); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| */ | |||
| public function test_curl() | |||
| { | |||
| $station_no = 54321; | |||
| $tx_bill_no = 25; | |||
| $amt = 2640; | |||
| $company_no = 0; | |||
| $email = 'saylxxx@gmail.com'; | |||
| $mobile = '0953034986'; | |||
| $data = $this->allpay_invoice_model->test_curl($station_no, $tx_bill_no, $amt, $company_no, $email, $mobile); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // 開立月租系統發票 | |||
| public function create_member_tx_bill_invoice() | |||
| { | |||
| $station_no = $this->input->post('station_no', true); // 場站編號 | |||
| $tx_bill_no = $this->input->post('tx_bill_no', true); // 會員交易帳單代號 | |||
| $amt = $this->input->post('amt', true); // 金額 | |||
| $member_company_no = $this->input->post('member_company_no', true); // 買方統編 | |||
| $company_no = $this->input->post('company_no', true); // 賣方統編 | |||
| $email = $this->input->post('email', true); // 通知信箱 | |||
| $mobile = $this->input->post('mobile', true); // 通知簡訊 | |||
| $lpr = $this->input->post('lpr', true); // 車牌號碼 | |||
| $data = $this->allpay_invoice_model->create_member_tx_bill_invoice($station_no, $tx_bill_no, $amt, $member_company_no, $company_no, $email, $mobile, $lpr); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // 作廢月租系統發票 | |||
| public function void_member_tx_bill_invoice() | |||
| { | |||
| $station_no = $this->input->post('station_no', true); // 場站編號 | |||
| $order_no = $this->input->post('order_no', true); // 訂單編號 | |||
| $invoice_no = $this->input->post('invoice_no', true); // 發票號碼 | |||
| $data = $this->allpay_invoice_model->void_member_tx_bill_invoice($station_no, $order_no, $invoice_no); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // 折讓月租系統發票 | |||
| public function allowance_member_tx_bill_invoice() | |||
| { | |||
| $station_no = $this->input->post('station_no', true); // 場站編號 | |||
| $invoice_no = $this->input->post('invoice_no', true); // 發票號碼 | |||
| $allowance_amt = $this->input->post('allowance_amt', true); // 折讓金額 | |||
| $data = $this->allpay_invoice_model->allowance_member_tx_bill_invoice($station_no, $invoice_no, $allowance_amt); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // 測試:作廢折讓 | |||
| public function test_allowance_void() | |||
| { | |||
| $invoice_no = 'TM00012665'; | |||
| $allowance_no = '2017032814257398'; | |||
| $reason_str = 'test'; | |||
| $data = $this->allpay_invoice_model->allowance_void($invoice_no, $allowance_no, $reason_str); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| } | |||
| @@ -0,0 +1,413 @@ | |||
| <?php | |||
| /* | |||
| file: Allpay_payment.php 付費系統 (歐付寶) | |||
| */ | |||
| if (!defined('BASEPATH')) exit('No direct script access allowed'); | |||
| require_once(ALLPAY_FILE); | |||
| class Allpay_payment extends CI_Controller | |||
| { | |||
| var $vars = array(); // 共用變數 | |||
| function __construct() | |||
| { | |||
| parent::__construct(); | |||
| // ----- 程式開發階段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 | |||
| // ----- 定義常數(路徑, cache秒數) ----- | |||
| define('APP_VERSION', '100'); // 版本號 | |||
| define('MAX_AGE', 604800); // cache秒數, 此定義1個月 | |||
| define('APP_NAME', 'allpay_payment'); // 應用系統名稱 | |||
| define('PAGE_PATH', APP_BASE.'ci_application/views/'.APP_NAME.'/'); // path of views | |||
| define('SERVER_URL', 'http://'.(isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : 'localhost').'/'); // URL | |||
| define('APP_URL', SERVER_URL.APP_NAME.'.html/'); // controller路徑 | |||
| define('WEB_URL', SERVER_URL.APP_NAME.'/'); // 網頁路徑 | |||
| define('WEB_LIB', SERVER_URL.'libs/'); // 網頁lib | |||
| define('BOOTSTRAPS', WEB_LIB.'bootstrap_sb/'); // bootstrap lib | |||
| define('LOG_PATH', FILE_BASE.APP_NAME.'/logs/'); // log path | |||
| $this->load->model('allpay_payment_model'); | |||
| $this->load->model('payment_model'); // 一般臨停帳單 (tx_bill) | |||
| $this->load->model('payment_ats_model'); // 月租繳費機帳單 (tx_bill_ats) | |||
| /* | |||
| // ----- 正式環境 ----- | |||
| define('ALLPAY_ServiceURL', "https://payment.ecpay.com.tw/Cashier/AioCheckOut"); // 您要呼叫的服務位址 (綠界) | |||
| //define('ALLPAY_ServiceURL', "https://payment.allpay.com.tw/Cashier/AioCheckOut"); // 您要呼叫的服務位址 | |||
| define('ALLPAY_HashKey', "tLBnwUiKlbB0e6sS"); // AllPay提供給您的Hash Key | |||
| define('ALLPAY_HashIV', "bMhtNluToYSYoJBw"); // AllPay提供給您的Hash IV | |||
| define('ALLPAY_MerchantID', "1148391"); // AllPay提供給您的特店編號 | |||
| // ----- 正式環境(end) ----- | |||
| */ | |||
| // ----- 測試環境 ----- | |||
| define('ALLPAY_ServiceURL', "http://payment-stage.allpay.com.tw/Cashier/AioCheckOut"); // 您要呼叫的服務位址 | |||
| define('ALLPAY_HashKey', "5294y06JbISpM5x9"); // AllPay提供給您的Hash Key | |||
| define('ALLPAY_HashIV', "v77hoKGq4kWxNNIS"); // AllPay提供給您的Hash IV | |||
| define('ALLPAY_MerchantID', "2000132"); // AllPay提供給您的特店編號 | |||
| // ----- 測試環境(end) ----- | |||
| } | |||
| // 發生錯誤時集中在此處理 | |||
| public function error_handler($errno, $errstr, $errfile, $errline, $errcontext) | |||
| { | |||
| $str = date('H:i:s')."|{$errstr}|{$errfile}|{$errline}|{$errno}\n"; | |||
| //error_log($str, 3, $log_file . '.' . date('Ymd').'.log.txt'); // 3代表參考後面的檔名 | |||
| error_log($str, 3, LOG_PATH.APP_NAME . '.' . date('Ymd').'.log.txt'); // 3代表參考後面的檔名 | |||
| } | |||
| // 付款 (tx_bill) | |||
| public function transfer_money_tx_bill() | |||
| { | |||
| $order_no = $this->uri->segment(3); // 序號 | |||
| try{ | |||
| // 0. check tx_bill | |||
| $data = $this->payment_model->get_tx_bill($order_no); | |||
| if (! empty($data)) | |||
| { | |||
| $status = $data['status']; | |||
| switch($status){ | |||
| case 100: // 狀態: 0:剛建立, 1:結帳完成, 2:錢沒對上, 3:發票沒建立, 4:手動調整, 99:訂單逾期作廢, 100:交易進行中 | |||
| $oPayment = new AllInOne(); | |||
| $oPayment->ServiceURL = ALLPAY_ServiceURL; | |||
| $oPayment->HashKey = ALLPAY_HashKey; | |||
| $oPayment->HashIV = ALLPAY_HashIV; | |||
| $oPayment->MerchantID = ALLPAY_MerchantID; | |||
| /* 基本參數 */ | |||
| $oPayment->Send['ReturnURL'] = STATION_URL.APP_NAME.'.html/tx_bill_finished/'; // 您要收到付款完成通知的伺服器端網址(server) | |||
| $oPayment->Send['ClientBackURL'] = $data['client_back_url']; // 您要歐付寶返回按鈕導向的瀏覽器端網址"; | |||
| $oPayment->Send['OrderResultURL'] = $data['order_result_url']; // 您要收到付款完成通知的瀏覽器端網址(browser) ps. WebATM大部份銀行都回不來; | |||
| $oPayment->Send['MerchantTradeNo'] = $data['order_no']; // 您此筆訂單交易編號 | |||
| $oPayment->Send['MerchantTradeDate'] = date('Y/m/d H:i:s', strtotime($data['tx_time'])); // 交易時間 | |||
| $oPayment->Send['TotalAmount'] = (int) $data['amt']; // 您此筆訂單的交易總金額 | |||
| $oPayment->Send['TradeDesc'] = $data['invoice_remark']; // 您該筆訂單的描述 | |||
| $oPayment->Send['ChoosePayment'] = PaymentMethod::ALL; // PaymentMethod::WebATM; | |||
| $oPayment->Send['Remark'] = ""; | |||
| $oPayment->Send['ChooseSubPayment'] = PaymentMethodItem::None; | |||
| $oPayment->Send['NeedExtraPaidInfo'] = ExtraPaymentInfo::No; | |||
| $oPayment->Send['DeviceSource'] = DeviceType::Mobile; //DeviceType::PC; | |||
| //$oPayment->Send['IgnorePayment'] = "Alipay#Tenpay"; //"<<您不要顯示的付款方式>>"; // 例(排除支付寶與財富通): Alipay#Tenpay | |||
| // 加入選購商品資料。 | |||
| array_push($oPayment->Send['Items'], | |||
| array( | |||
| 'Name' => "結算", | |||
| 'Price' => (int)$data['amt'], | |||
| 'Currency' => "元", | |||
| 'Quantity' => (int) "1", | |||
| 'URL' => "http://www.altob.com.tw" // 網址是做什麼用的 ? | |||
| ) | |||
| ); | |||
| /* 產生訂單 */ | |||
| $oPayment->CheckOut(); | |||
| /* 產生訂單 Html Code 的方法 */ | |||
| $szHtml = $oPayment->CheckOutString(); | |||
| default: | |||
| $sMsg = 'status != 100'; | |||
| trigger_error(APP_NAME.', '._FUNCTION_.', order_no=>' . $order_no.'<br>'.$sMsg); | |||
| echo $sMsg; | |||
| } | |||
| } | |||
| }catch (Exception $e){ | |||
| // 例外錯誤處理。 | |||
| $sMsg = $e->getMessage(); | |||
| trigger_error(APP_NAME.', '._FUNCTION_.', order_no=>' . $order_no.'<br>'.$sMsg); | |||
| echo $sMsg; | |||
| } | |||
| } | |||
| // 付款 (tx_bill_ats) | |||
| public function transfer_money_tx_bill_ats() | |||
| { | |||
| $order_no = $this->uri->segment(3); // 序號 | |||
| try{ | |||
| // 0. check tx_bill | |||
| $data = $this->payment_ats_model->get_tx_bill($order_no); | |||
| if (! empty($data)) | |||
| { | |||
| $status = $data['status']; | |||
| switch($status){ | |||
| case 100: // 狀態: 0:剛建立, 1:結帳完成, 2:錢沒對上, 3:發票沒建立, 4:手動調整, 99:訂單逾期作廢, 100:交易進行中 | |||
| $oPayment = new AllInOne(); | |||
| $oPayment->ServiceURL = ALLPAY_ServiceURL; | |||
| $oPayment->HashKey = ALLPAY_HashKey; | |||
| $oPayment->HashIV = ALLPAY_HashIV; | |||
| $oPayment->MerchantID = ALLPAY_MerchantID; | |||
| /* 基本參數 */ | |||
| $oPayment->Send['ReturnURL'] = STATION_URL.APP_NAME.'.html/tx_bill_ats_finished/'; // 您要收到付款完成通知的伺服器端網址(server) | |||
| $oPayment->Send['ClientBackURL'] = $data['client_back_url']; // 您要歐付寶返回按鈕導向的瀏覽器端網址"; | |||
| $oPayment->Send['OrderResultURL'] = $data['order_result_url']; // 您要收到付款完成通知的瀏覽器端網址(browser) ps. WebATM大部份銀行都回不來; | |||
| $oPayment->Send['MerchantTradeNo'] = $data['order_no']; // 您此筆訂單交易編號 | |||
| $oPayment->Send['MerchantTradeDate'] = date('Y/m/d H:i:s', strtotime($data['tx_time'])); // 交易時間 | |||
| $oPayment->Send['TotalAmount'] = (int) $data['amt']; // 您此筆訂單的交易總金額 | |||
| $oPayment->Send['TradeDesc'] = $data['invoice_remark']; // 您該筆訂單的描述 | |||
| $oPayment->Send['ChoosePayment'] = PaymentMethod::WebATM; //PaymentMethod::ALL;; | |||
| $oPayment->Send['Remark'] = ""; | |||
| $oPayment->Send['ChooseSubPayment'] = PaymentMethodItem::None; | |||
| $oPayment->Send['NeedExtraPaidInfo'] = ExtraPaymentInfo::No; | |||
| $oPayment->Send['DeviceSource'] = DeviceType::PC; //DeviceType::Mobile; | |||
| //$oPayment->Send['IgnorePayment'] = "Alipay#Tenpay"; //"<<您不要顯示的付款方式>>"; // 例(排除支付寶與財富通): Alipay#Tenpay | |||
| // 加入選購商品資料。 | |||
| array_push($oPayment->Send['Items'], | |||
| array( | |||
| 'Name' => "結算", | |||
| 'Price' => (int)$data['amt'], | |||
| 'Currency' => "元", | |||
| 'Quantity' => (int) "1", | |||
| 'URL' => "http://www.altob.com.tw" // 網址是做什麼用的 ? | |||
| ) | |||
| ); | |||
| /* 產生訂單 */ | |||
| $oPayment->CheckOut(); | |||
| /* 產生訂單 Html Code 的方法 */ | |||
| $szHtml = $oPayment->CheckOutString(); | |||
| default: | |||
| $sMsg = 'status != 100'; | |||
| trigger_error(APP_NAME.', '._FUNCTION_.', order_no=>' . $order_no.'<br>'.$sMsg); | |||
| echo $sMsg; | |||
| } | |||
| } | |||
| }catch (Exception $e){ | |||
| // 例外錯誤處理。 | |||
| $sMsg = $e->getMessage(); | |||
| trigger_error(APP_NAME.', '._FUNCTION_.', order_no=>' . $order_no.'<br>'.$sMsg); | |||
| echo $sMsg; | |||
| } | |||
| } | |||
| // 付款完成 (tx_bill) | |||
| public function tx_bill_finished() | |||
| { | |||
| ob_end_clean(); | |||
| ignore_user_abort(); | |||
| ob_start(); | |||
| try{ | |||
| $oPayment = new AllInOne(); | |||
| /* 服務參數 */ | |||
| $oPayment->HashKey = ALLPAY_HashKey; | |||
| $oPayment->HashIV = ALLPAY_HashIV; | |||
| $oPayment->MerchantID = ALLPAY_MerchantID; | |||
| /* 取得回傳參數 */ | |||
| $arFeedback = $oPayment->CheckOutFeedback(); | |||
| /* 檢核與變更訂單狀態 */ | |||
| if (sizeof($arFeedback) > 0){ | |||
| foreach ($arFeedback as $key => $value){ | |||
| switch ($key){ | |||
| /* 支付後的回傳的基本參數 */ | |||
| case "MerchantID": $szMerchantID = $value; break; | |||
| case "MerchantTradeNo": $szMerchantTradeNo = $value; break; | |||
| case "PaymentDate": $szPaymentDate = $value; break; | |||
| case "PaymentType": $szPaymentType = $value; break; | |||
| case "PaymentTypeChargeFee": $szPaymentTypeChargeFee = $value; break; | |||
| case "RtnCode": $szRtnCode = $value; break; | |||
| case "RtnMsg": $szRtnMsg = $value; break; | |||
| case "SimulatePaid": $szSimulatePaid = $value; break; | |||
| case "TradeAmt": $szTradeAmt = $value; break; | |||
| case "TradeDate": $szTradeDate = $value; break; | |||
| case "TradeNo": $szTradeNo = $value; break; | |||
| default: break; | |||
| } | |||
| } | |||
| // 一律記錄log。 | |||
| $data = array( | |||
| 'merchant_id' => $szMerchantID, | |||
| 'merchant_trade_no' => $szMerchantTradeNo, | |||
| 'payment_date' => $szPaymentDate, | |||
| 'payment_type' => $szPaymentType, | |||
| 'payment_type_charge_fee' => $szPaymentTypeChargeFee, | |||
| 'rtn_code' => $szRtnCode, | |||
| 'rtn_msg' => $szRtnMsg, | |||
| 'simulate_paid' => $szSimulatePaid, | |||
| 'trade_amt' => $szTradeAmt, | |||
| 'trade_date' => $szTradeDate, | |||
| 'trade_no' => $szTradeNo | |||
| ); | |||
| $this->allpay_payment_model->create_allpay_feedback_log($data); | |||
| print '1|OK'; //先回傳ok | |||
| header('Connection: close'); | |||
| header('Content-Length: ' . ob_get_length()); | |||
| ob_end_flush(); | |||
| flush(); | |||
| // 此筆交易為成功 | |||
| if($szRtnCode == '1') | |||
| { | |||
| $data = $this->payment_model->get_tx_bill($szMerchantTradeNo); | |||
| if (! empty($data)) | |||
| { | |||
| $order_no = $data['order_no']; | |||
| $amt = $data['amt']; | |||
| $status = $data['status']; | |||
| switch($status){ | |||
| case 100: // 狀態: 0:剛建立, 1:結帳完成, 2:錢沒對上, 3:發票沒建立, 4:手動調整, 99:訂單逾期作廢, 100:交易進行中 | |||
| // 印發票流程 | |||
| if($szTradeAmt == $amt){ | |||
| // 先記錄 | |||
| $this->payment_model->transfer_money_done($order_no); | |||
| if(! empty($data["service_url"])){ | |||
| file_get_contents($data["service_url"]."/{$order_no}"); // 執行指定的結帳呼叫 | |||
| }else{ | |||
| // 找不到付款成功服務位址 | |||
| trigger_error(APP_NAME.', '._FUNCTION_.', order_no=>' . $order_no.'<br>'.'service_url not found..'); | |||
| } | |||
| }else{ | |||
| // 錢沒對上 | |||
| $this->payment_model->transfer_money_done_with_amt_error($szMerchantTradeNo); | |||
| } | |||
| break; | |||
| default: | |||
| // 對方多傳一次時?? | |||
| trigger_error(APP_NAME.', '._FUNCTION_.', order_no=>' . $order_no.'<br>'.'tx_bill.status != 100'); | |||
| } | |||
| }else{ | |||
| // 我們自己找不到記錄時?? | |||
| trigger_error(APP_NAME.', '._FUNCTION_.', order_no=>' . $order_no.'<br>'.'tx_bill NOT FOUND !!'); | |||
| } | |||
| } | |||
| }else{ | |||
| print '0|Fail'; | |||
| } | |||
| }catch (Exception $e){ | |||
| // 例外錯誤處理。 | |||
| print '0|' . $e->getMessage(); | |||
| } | |||
| exit(); | |||
| } | |||
| // 付款完成 (tx_bill_ats) | |||
| public function tx_bill_ats_finished() | |||
| { | |||
| ob_end_clean(); | |||
| ignore_user_abort(); | |||
| ob_start(); | |||
| try{ | |||
| $oPayment = new AllInOne(); | |||
| /* 服務參數 */ | |||
| $oPayment->HashKey = ALLPAY_HashKey; | |||
| $oPayment->HashIV = ALLPAY_HashIV; | |||
| $oPayment->MerchantID = ALLPAY_MerchantID; | |||
| /* 取得回傳參數 */ | |||
| $arFeedback = $oPayment->CheckOutFeedback(); | |||
| /* 檢核與變更訂單狀態 */ | |||
| if (sizeof($arFeedback) > 0){ | |||
| foreach ($arFeedback as $key => $value){ | |||
| switch ($key){ | |||
| /* 支付後的回傳的基本參數 */ | |||
| case "MerchantID": $szMerchantID = $value; break; | |||
| case "MerchantTradeNo": $szMerchantTradeNo = $value; break; | |||
| case "PaymentDate": $szPaymentDate = $value; break; | |||
| case "PaymentType": $szPaymentType = $value; break; | |||
| case "PaymentTypeChargeFee": $szPaymentTypeChargeFee = $value; break; | |||
| case "RtnCode": $szRtnCode = $value; break; | |||
| case "RtnMsg": $szRtnMsg = $value; break; | |||
| case "SimulatePaid": $szSimulatePaid = $value; break; | |||
| case "TradeAmt": $szTradeAmt = $value; break; | |||
| case "TradeDate": $szTradeDate = $value; break; | |||
| case "TradeNo": $szTradeNo = $value; break; | |||
| default: break; | |||
| } | |||
| } | |||
| // 一律記錄log。 | |||
| $data = array( | |||
| 'merchant_id' => $szMerchantID, | |||
| 'merchant_trade_no' => $szMerchantTradeNo, | |||
| 'payment_date' => $szPaymentDate, | |||
| 'payment_type' => $szPaymentType, | |||
| 'payment_type_charge_fee' => $szPaymentTypeChargeFee, | |||
| 'rtn_code' => $szRtnCode, | |||
| 'rtn_msg' => $szRtnMsg, | |||
| 'simulate_paid' => $szSimulatePaid, | |||
| 'trade_amt' => $szTradeAmt, | |||
| 'trade_date' => $szTradeDate, | |||
| 'trade_no' => $szTradeNo | |||
| ); | |||
| $this->allpay_payment_model->create_allpay_feedback_log($data); | |||
| print '1|OK'; //先回傳ok | |||
| header('Connection: close'); | |||
| header('Content-Length: ' . ob_get_length()); | |||
| ob_end_flush(); | |||
| flush(); | |||
| // 此筆交易為成功 | |||
| if($szRtnCode == '1') | |||
| { | |||
| $data = $this->payment_ats_model->get_tx_bill($szMerchantTradeNo); | |||
| if (! empty($data)) | |||
| { | |||
| $order_no = $data['order_no']; | |||
| $amt = $data['amt']; | |||
| $status = $data['status']; | |||
| switch($status){ | |||
| case 100: // 狀態: 0:剛建立, 1:結帳完成, 2:錢沒對上, 3:發票沒建立, 4:手動調整, 99:訂單逾期作廢, 100:交易進行中 | |||
| // 印發票流程 | |||
| if($szTradeAmt == $amt){ | |||
| // 先記錄 | |||
| $this->payment_ats_model->transfer_money_done($order_no); | |||
| if(! empty($data["service_url"])){ | |||
| file_get_contents($data["service_url"]."/{$order_no}"); // 執行指定的結帳呼叫 | |||
| }else{ | |||
| // 找不到付款成功服務位址 | |||
| trigger_error(APP_NAME.', '._FUNCTION_.', order_no=>' . $order_no.'<br>'.' service_url not found..'); | |||
| } | |||
| }else{ | |||
| // 錢沒對上 | |||
| $this->payment_ats_model->transfer_money_done_with_amt_error($szMerchantTradeNo); | |||
| } | |||
| break; | |||
| default: | |||
| // 對方多傳一次時?? | |||
| trigger_error(APP_NAME.', '._FUNCTION_.', order_no=>' . $order_no.'<br>'.' status != 100'); | |||
| } | |||
| }else{ | |||
| // 我們自己找不到記錄時?? | |||
| trigger_error(APP_NAME.', '._FUNCTION_.', order_no=>' . $order_no.'<br>'.' NOT FOUND !!'); | |||
| } | |||
| } | |||
| }else{ | |||
| print '0|Fail'; | |||
| } | |||
| }catch (Exception $e){ | |||
| // 例外錯誤處理。 | |||
| print '0|' . $e->getMessage(); | |||
| } | |||
| exit(); | |||
| } | |||
| } | |||
| @@ -0,0 +1,872 @@ | |||
| <?php | |||
| /* | |||
| file: carpark.php 停車管理 | |||
| */ | |||
| if ( ! defined('BASEPATH')) exit('No direct script access allowed'); | |||
| require_once(MQ_CLASS_FILE); | |||
| // ----- 定義常數(路徑, cache秒數) ----- | |||
| define('APP_VERSION', '100'); // 版本號 | |||
| define('MAX_AGE', 604800); // cache秒數, 此定義1個月 | |||
| define('APP_NAME', 'carpark'); // 應用系統名稱 | |||
| define('PAGE_PATH', APP_BASE.'ci_application/views/'.APP_NAME.'/'); // path of views | |||
| define('SERVER_URL', 'http://'.(isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : 'localhost').'/'); // URL | |||
| define('APP_URL', SERVER_URL.APP_NAME.'.html/'); // controller路徑 | |||
| define('WEB_URL', SERVER_URL.APP_NAME.'/'); // 網頁路徑 | |||
| define('WEB_LIB', SERVER_URL.'libs/'); // 網頁lib | |||
| define('BOOTSTRAPS', WEB_LIB.'bootstrap_sb/'); // bootstrap lib | |||
| define('LOG_PATH', FILE_BASE.APP_NAME.'/logs/'); // log path | |||
| class Carpark extends CI_Controller | |||
| { | |||
| var $vars = array(); // 共用變數 | |||
| function __construct() | |||
| { | |||
| parent::__construct(); | |||
| // ----- 程式開發階段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 | |||
| // 共用記憶體 | |||
| $this->vars['mcache'] = new Memcache; | |||
| $this->vars['mcache']->connect(MEMCACHE_HOST, MEMCACHE_PORT) or die ('Could not connect memcache'); | |||
| // mqtt subscribe | |||
| $this->vars['mqtt'] = new phpMQTT(MQ_HOST, MQ_PORT, uniqid()); | |||
| //if(!$this->vars['mqtt']->connect()){ die ('Could not connect mqtt'); } | |||
| $this->vars['mqtt']->connect(); | |||
| $this->load->model('carpark_model'); | |||
| $this->carpark_model->init($this->vars); | |||
| // 微調剩餘車位數 | |||
| $this->load->model('sync_data_model'); | |||
| $this->sync_data_model->init($this->vars); | |||
| // 產生 excel 報表 | |||
| $this->load->model('excel_model'); | |||
| $this->excel_model->init($this->vars); | |||
| // [START] 2016/06/03 登入 | |||
| $this->load->model('user_model'); | |||
| // load library | |||
| $this->load->library(array('form_validation','session')); | |||
| // load helpers | |||
| $this->load->helper(array('form')); | |||
| // ajax code | |||
| define('RESULT_SUCCESS', 'ok'); | |||
| define('RESULT_FORM_VALIDATION_FAIL', '-1'); | |||
| define('RESULE_FAIL', 'gg'); | |||
| // [START] 2016/06/03 登入 | |||
| } | |||
| // 發生錯誤時集中在此處理 | |||
| public function error_handler($errno, $errstr, $errfile, $errline, $errcontext) | |||
| { | |||
| // ex: car_err://message.... | |||
| $log_msg = explode('://', $errstr); | |||
| if (count($log_msg) > 1) | |||
| { | |||
| $log_file = LOG_PATH.$log_msg[0]; | |||
| $str = date('H:i:s')."|{$log_msg[1]}|{$errfile}|{$errline}|{$errno}\n"; | |||
| } | |||
| else | |||
| { | |||
| $log_file = LOG_PATH.APP_NAME; | |||
| $str = date('H:i:s')."|{$errstr}|{$errfile}|{$errline}|{$errno}\n"; | |||
| } | |||
| //$str = date('H:i:s')."|{$errstr}|{$errfile}|{$errline}|{$errno}\n"; | |||
| error_log($str, 3, $log_file . '.' . date('Ymd').'.log.txt'); // 3代表參考後面的檔名 | |||
| } | |||
| // 顯示靜態網頁(html檔) | |||
| protected function show_page($page_name, &$data = null) | |||
| { | |||
| $page_file = PAGE_PATH.$page_name.'.php'; | |||
| $last_modified_time = filemtime($page_file); | |||
| // 若檔案修改時間沒有異動, 或版本無異動, 通知瀏覽器使用cache, 不再下傳網頁 | |||
| // header('Cache-Control:max-age='.MAX_AGE); // cache 1個月 | |||
| header('Last-Modified: '.gmdate('D, d M Y H:i:s', $last_modified_time).' GMT'); | |||
| header('Etag: '. APP_VERSION); | |||
| header('Cache-Control: public'); | |||
| // 20170921 | |||
| header("cache-Control: no-store, no-cache, must-revalidate"); | |||
| header("cache-Control: post-check=0, pre-check=0", false); | |||
| header("Pragma: no-cache"); | |||
| header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); | |||
| if (!empty($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] == APP_VERSION && @strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) == $last_modified_time) | |||
| { | |||
| header('HTTP/1.1 304 Not Modified'); | |||
| } | |||
| else | |||
| { | |||
| $this->load->view(APP_NAME.'/'.$page_name, $data); | |||
| } | |||
| } | |||
| // ------------------------------------------------ | |||
| // | |||
| // 接收端 (START) | |||
| // | |||
| // ------------------------------------------------ | |||
| // [設定檔] 取得設定 | |||
| public function station_setting_query() | |||
| { | |||
| $reload = $this->input->post('reload', true); | |||
| if(isset($reload) && $reload > 0) | |||
| { | |||
| $station_setting = $this->sync_data_model->station_setting_query(true); // 強制重新載入 | |||
| trigger_error(__FUNCTION__ . '..station_setting: '. print_r($station_setting, true)); | |||
| if(!$station_setting) | |||
| { | |||
| echo json_encode('fail', JSON_UNESCAPED_UNICODE); | |||
| exit; // 中斷 | |||
| } | |||
| $info = array('station_no_arr' => $station_setting['station_no']); | |||
| usleep(300000); // 0.3 sec delay | |||
| // 費率資料同步 | |||
| $result = $this->sync_data_model->sync_price_plan($info); | |||
| trigger_error(__FUNCTION__ . '..sync_price_plan: '. $result); | |||
| usleep(300000); // 0.3 sec delay | |||
| // 會員資料同步 | |||
| $result = $this->sync_data_model->sync_members($info); | |||
| trigger_error(__FUNCTION__ . '..sync_members: '. $result); | |||
| usleep(300000); // 0.3 sec delay | |||
| // 在席資料同步 | |||
| $result = $this->sync_data_model->sync_pks_groups_reload($station_setting); | |||
| trigger_error(__FUNCTION__ . '..sync_pks_groups_reload: '. $result); | |||
| } | |||
| else | |||
| { | |||
| $station_setting = $this->sync_data_model->station_setting_query(false); | |||
| if(!$station_setting) | |||
| { | |||
| echo json_encode('fail', JSON_UNESCAPED_UNICODE); | |||
| exit; // 中斷 | |||
| } | |||
| } | |||
| echo json_encode($station_setting, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // [排程 or 強制] 同步場站資訊 | |||
| public function sync_station_data() | |||
| { | |||
| trigger_error(__FUNCTION__ . '..from..'. $this->my_ip() .'..network..'); // IP 會浮動? | |||
| $switch_lpr_arr = array(); // 換車牌 | |||
| $meta = $this->input->post('meta', true); | |||
| if(!empty($meta)) | |||
| { | |||
| trigger_error( __FUNCTION__ . '..meta_arr..' . $meta); | |||
| $meta_arr = explode('@@@', $meta); | |||
| foreach($meta_arr as $raw) | |||
| { | |||
| if(empty($raw)) | |||
| continue; | |||
| $data = json_decode($raw, true); | |||
| if($data['key'] == 'switch_lpr') | |||
| { | |||
| array_push($switch_lpr_arr, $data['value']); | |||
| } | |||
| } | |||
| } | |||
| // 0. 取得場站設定 | |||
| $station_setting = $this->sync_data_model->station_setting_query(false); | |||
| trigger_error(__FUNCTION__ . '..station_setting: '. print_r($station_setting, true)); | |||
| $station_no_arr = array('station_no_arr' => $station_setting['station_no']); | |||
| // 1. 月租系統 | |||
| $result = $this->sync_data_model->sync_members($station_no_arr); | |||
| trigger_error(__FUNCTION__ . '..sync_members: '. $result); | |||
| // 2. 同步車牌更換 | |||
| if(!empty($switch_lpr_arr)) | |||
| { | |||
| $this->sync_data_model->sync_switch_lpr($switch_lpr_arr); | |||
| } | |||
| } | |||
| // [API] 取得最新未結清 | |||
| public function get_last_unbalanced_cario() | |||
| { | |||
| trigger_error(__FUNCTION__ . '..from..'. $this->my_ip() .'..network..'); // IP 會浮動? | |||
| $lpr = $this->input->post('lpr', true); | |||
| $station_no = $this->input->post('station_no', true); | |||
| $c_s = $this->input->post('c_s', true); | |||
| // 確認正確性 | |||
| if(empty($c_s) || $c_s != md5('altob'.$lpr.'botla'.$station_no)) | |||
| { | |||
| trigger_error(__FUNCTION__ . "..{$lpr}|".$station_no."|{$c_s}..check fail.."); | |||
| echo 'fail'; | |||
| exit; | |||
| } | |||
| $data = $this->carpark_model->get_last_unbalanced_cario($lpr, $station_no); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // [API] 更新未結清 (行動支付) | |||
| public function sync_m2payed() | |||
| { | |||
| trigger_error(__FUNCTION__ . '..from..'. $this->my_ip() .'..network..'); // IP 會浮動? | |||
| $lpr = $this->input->post('lpr', true); | |||
| $amt = $this->input->post('amt', true); | |||
| $station_no = $this->input->post('station_no', true); | |||
| $cario_no = $this->input->post('cario_no', true); | |||
| $c_s = $this->input->post('c_s', true); | |||
| // 確認正確性 | |||
| if(empty($c_s) || $c_s != md5($lpr.$amt.'altob'.$station_no.'botla'.$cario_no)) | |||
| { | |||
| trigger_error(__FUNCTION__ . "..{$lpr}|{$amt}|{$station_no}|{$cario_no}|{$c_s}..check fail.."); | |||
| echo 'fail'; | |||
| exit; | |||
| } | |||
| // 臨停繳費 | |||
| $this->load->model('carpayment_model'); | |||
| echo $this->carpayment_model->p2payed(array('seqno' => $cario_no, 'lpr' => $lpr, 'amt' => $amt), true); | |||
| exit; | |||
| //echo 'ok'; | |||
| } | |||
| // 驗証 IP | |||
| function is_ip_valid() | |||
| { | |||
| $client_ip = $this->my_ip(); | |||
| if(!in_array($client_ip, array('61.219.172.11', '61.219.172.82'))) | |||
| { | |||
| trigger_error('..block..from:'.$client_ip.'..unknown network..'); | |||
| return false; | |||
| } | |||
| return true; | |||
| } | |||
| // 取得 IP | |||
| function my_ip() | |||
| { | |||
| if (getenv('HTTP_X_FORWARDED_FOR')) | |||
| { | |||
| $ip = getenv('HTTP_X_FORWARDED_FOR'); | |||
| } | |||
| elseif (getenv('HTTP_X_REAL_IP')) | |||
| { | |||
| $ip = getenv('HTTP_X_REAL_IP'); | |||
| } | |||
| else { | |||
| $ip = $_SERVER['REMOTE_ADDR']; | |||
| } | |||
| return $ip; | |||
| } | |||
| // 同步 (由排程呼叫) | |||
| public function sync_minutely() | |||
| { | |||
| $this->sync_data_model->sync_pks_groups(); // 同步在席現況 | |||
| } | |||
| // 20170816 手動新增入場資料 | |||
| public function gen_carin() | |||
| { | |||
| trigger_error(__FUNCTION__ . '..from..'. $this->my_ip() .'..network..'); // IP 會浮動? | |||
| $lpr = $this->input->post('lpr', true); | |||
| $station_no = $this->input->post('station_no', true); | |||
| $c_s = $this->input->post('c_s', true); | |||
| // 確認正確性 | |||
| if(empty($c_s) || $c_s != md5($lpr.'altob'.$station_no.'botla'. __FUNCTION__ )) | |||
| { | |||
| trigger_error(__FUNCTION__ . "..{$lpr}|{$station_no}|{$c_s}..check fail.."); | |||
| echo 'fail'; | |||
| exit; | |||
| } | |||
| $parms = array( | |||
| 'sno' => $station_no, | |||
| 'lpr' => $lpr, | |||
| 'etag' => 'NONE', | |||
| 'io' => 'CI', | |||
| 'ivsno' => 0 | |||
| ); | |||
| $this->carpark_model->gen_carin($parms); | |||
| echo 'ok'; | |||
| } | |||
| // ------------------------------------------------ | |||
| // | |||
| // 接收端 (END) | |||
| // | |||
| // ------------------------------------------------ | |||
| // [START] 2016/06/03 登入 | |||
| public function index() | |||
| { | |||
| if($this->session->userdata('logged_in')) | |||
| { | |||
| $session_data = $this->session->userdata('logged_in'); | |||
| $data['username'] = $session_data['username']; | |||
| $data['type'] = $session_data['type']; | |||
| if($data['type'] == 'admin') | |||
| { | |||
| $this->show_page('admin_page', $data); // 進階管理者介面 | |||
| } | |||
| else | |||
| { | |||
| $this->show_page('main_page', $data); // 一般 | |||
| } | |||
| } | |||
| else | |||
| { | |||
| //If no session, redirect to login page | |||
| //redirect('login', 'refresh'); | |||
| $this->show_page('login_page'); | |||
| } | |||
| } | |||
| // 登入 | |||
| public function user_login() | |||
| { | |||
| // form_validation | |||
| $this->form_validation->set_rules('login_name', 'login_name', 'trim|required'); | |||
| $this->form_validation->set_rules('pswd', 'pswd', 'trim|required'); | |||
| if($this->form_validation->run() == FALSE) | |||
| { | |||
| return RESULT_FORM_VALIDATION_FAIL; | |||
| } | |||
| // go model | |||
| $data = array | |||
| ( | |||
| 'login_name' => $this->input->post('login_name', true), | |||
| 'pswd' => $this->input->post('pswd', true) | |||
| ); | |||
| $result = $this->user_model->user_login($data); | |||
| if($result) | |||
| { | |||
| $sess_array = array(); | |||
| foreach($result as $row) | |||
| { | |||
| $sess_array = array | |||
| ( | |||
| 'username' => $row->login_name , | |||
| 'type' => $row->user_type | |||
| ); | |||
| $this->session->set_userdata('logged_in', $sess_array); | |||
| } | |||
| echo RESULT_SUCCESS; | |||
| } | |||
| else | |||
| { | |||
| return RESULE_FAIL; | |||
| } | |||
| } | |||
| // 登出 | |||
| public function user_logout() | |||
| { | |||
| $this->session->unset_userdata('logged_in'); | |||
| session_destroy(); | |||
| return RESULT_SUCCESS; | |||
| } | |||
| // [END] 2016/06/03 登入 | |||
| // response http | |||
| protected function http_return($return_code, $type) | |||
| { | |||
| if ($type == 'text') echo $return_code; | |||
| else echo json_encode($return_code, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // 送出html code | |||
| public function get_html() | |||
| { | |||
| /* | |||
| $data = array | |||
| ( | |||
| 'company_no' => $this->input->post('company_no', true), // 場站統編 | |||
| 'hq_company_no' => '80682490' | |||
| ); | |||
| $this->load->view(APP_NAME.'/'.$this->input->post('tag_name', true), $data); | |||
| */ | |||
| $this->load->view(APP_NAME.'/'.$this->input->post('tag_name', true), array()); | |||
| } | |||
| // 讀取cookie內容 | |||
| protected function get_cookie($cookie_name) | |||
| { | |||
| if (empty($_COOKIE[$cookie_name])) return array(); | |||
| return(json_decode($_COOKIE[$cookie_name], true)); | |||
| } | |||
| // 儲存cookie內容 | |||
| protected function save_cookie($cookie_name, $cookie_info) | |||
| { | |||
| return setcookie($cookie_name, json_encode($cookie_info, JSON_UNESCAPED_UNICODE), 0, '/'); | |||
| } | |||
| // 月租資料同步 | |||
| public function rent_sync() | |||
| { | |||
| $station_no = $this->input->post('station_no', true); | |||
| $start_date = $this->input->post('start_date', true); | |||
| $end_date = $this->input->post('end_date', true); | |||
| // $data = $this->carpark_model->rent_sync($station_no, $start_date, $end_date); | |||
| // print_r($data); | |||
| } | |||
| // 重設剩餘車位數 | |||
| public function available_set() | |||
| { | |||
| $data = $this->carpark_model->available_set(); | |||
| $this->http_return($data, 'json'); | |||
| } | |||
| // 剩餘車位數更新 | |||
| public function available_update() | |||
| { | |||
| $station_no = $this->input->get_post('station_no', true); | |||
| $data['name'] = $this->input->get_post('st_name', true); | |||
| $data['tot_pkg'] = $this->input->get_post('tot_pkg', true); | |||
| $data['ava_pkg'] = $this->input->get_post('ava_pkg', true); | |||
| $this->http_return($this->carpark_model->available_update($station_no, $data), 'json'); | |||
| } | |||
| // 剩餘車位數查核 | |||
| public function available_check() | |||
| { | |||
| $time_point = $this->input->get_post('time_point', true); | |||
| $this->http_return($this->carpark_model->available_check($time_point), 'json'); | |||
| } | |||
| // 顯示logs | |||
| public function show_logs() | |||
| { | |||
| $lines = $this->uri->segment(3); // 顯示行數 | |||
| if (empty($lines)) $lines = 140; // 無行數參數, 預設為40行 | |||
| if($lines > 1000) $lines = 1000; // 最多 1000行 | |||
| // echo '<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body><pre style="white-space: pre-wrap;">'; | |||
| echo '<html lang="zh-TW"><body><pre style="white-space: pre-wrap;">'; | |||
| 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 '</pre></body></html>'; | |||
| } | |||
| // 顯示logs (cars grep 888) | |||
| public function show_888_logs() | |||
| { | |||
| $lines = $this->uri->segment(3); // 顯示行數 | |||
| if (empty($lines)) $lines = 1000; // 無行數參數, 預設為1000行 | |||
| if($lines > 20000) $lines = 20000; // 最多 20000行 | |||
| $grep_str = ' |grep 888'; | |||
| $target_str = LOG_PATH.APP_NAME . '.' . date('Ymd').'.log.txt'. $grep_str; | |||
| // echo '<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body><pre style="white-space: pre-wrap;">'; | |||
| echo '<html lang="zh-TW"><body><pre style="white-space: pre-wrap;">'; | |||
| passthru('/usr/bin/tail -n ' . $lines . ' ' . $target_str); // 利用linux指令顯示倒數幾行的logs內容 | |||
| echo "\n----- " . $target_str . ' -----'; | |||
| echo '</pre></body></html>'; | |||
| } | |||
| // 新增月租資料 | |||
| public function member_add() | |||
| { | |||
| $data = array | |||
| ( | |||
| 'member_no' => $this->input->post('member_no', true), | |||
| 'station_no' => $this->input->post('station_no', true), | |||
| 'lpr' => strtoupper($this->input->post('lpr', true)), | |||
| 'old_lpr' => strtoupper($this->input->post('old_lpr', true)), | |||
| 'etag' => strtoupper($this->input->post('etag', true)), | |||
| 'start_date' => $this->input->post('start_date', true), | |||
| 'end_date' => $this->input->post('end_date', true), | |||
| 'member_name' => $this->input->post('member_name', true), | |||
| 'member_nick_name' => $this->input->post('member_name', true), | |||
| 'mobile_no' => $this->input->post('mobile_no', true), | |||
| 'member_id' => $this->input->post('member_id', true), | |||
| 'contract_no' => $this->input->post('contract_no', true), | |||
| 'amt' => $this->input->post('amt', true), | |||
| 'tel_h' => $this->input->post('tel_h', true), | |||
| 'tel_o' => $this->input->post('tel_o', true), | |||
| 'addr' => $this->input->post('addr', true) | |||
| ); | |||
| trigger_error("add:".print_r($data, true)); | |||
| if ($data['member_no'] == 0 || $data['old_lpr'] != $data['lpr']) | |||
| { | |||
| if ($this->carpark_model->check_lpr($data['lpr']) > 0) | |||
| { | |||
| echo '車牌重複, 請查明再輸入'; | |||
| exit; | |||
| } | |||
| } | |||
| $this->carpark_model->member_add($data); | |||
| echo 'ok'; | |||
| } | |||
| // 查詢月租資料 | |||
| public function member_query() | |||
| { | |||
| $data = $this->carpark_model->member_query(); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // 刪除月租資料 | |||
| public function member_delete() | |||
| { | |||
| $member_no = $this->input->post('member_no', true); | |||
| $this->carpark_model->member_delete($member_no); | |||
| echo 'ok'; | |||
| } | |||
| // 進出場現況表 | |||
| public function cario_list() | |||
| { | |||
| $data = $this->carpark_model->cario_list(); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // 進出場事件即時顯示 | |||
| public function cario_event() | |||
| { | |||
| set_time_limit(0); | |||
| while(true) | |||
| { | |||
| } | |||
| } | |||
| // 顯示圖檔(http://url/carpark.html/pics/lpr_ABY8873_O_0_0_C_20150919210022) | |||
| public function pics() | |||
| { | |||
| // ??? | |||
| readfile(CAR_PIC.$this->uri->segment(3).'/'.str_replace('/', '', $this->uri->segment(4)).'.jpg'); | |||
| } | |||
| // 汽車開門 | |||
| public function opendoors() | |||
| { | |||
| $ivsno = $this->uri->segment(3); | |||
| $lanes = array | |||
| ( | |||
| 0 => array ('devno' => 0, 'temp' => 0, 'member' => 1), // 1號入口, temp:臨停, member:月租 | |||
| // 1 => array ('devno' => 0, 'temp' => 2, 'member' => 3), // 2號調撥入口 | |||
| 1 => array ('devno' => 1, 'temp' => 0, 'member' => 1), // 3號調撥出口 | |||
| 2 => array ('devno' => 1, 'temp' => 0, 'member' => 1), // 3號調撥出口 | |||
| 3 => array ('devno' => 1, 'temp' => 2, 'member' => 3) // 4號出口 | |||
| ); | |||
| $url = 'http://admin:99999999@192.168.10.53/cgi-bin/basic_setting.cgi?ID=1&'; | |||
| $member_tag = 'member'; // member:月租會員 | |||
| // 短路開柵欄 | |||
| @get_headers("{$url}OUTDEV={$lanes[$ivsno]['devno']}&OUTCH={$lanes[$ivsno][$member_tag]}&OUTSTATUS=1"); | |||
| usleep(400000); // 暫停0.4秒 | |||
| // 斷路, 車過關柵欄 | |||
| @get_headers("{$url}OUTDEV={$lanes[$ivsno]['devno']}&OUTCH={$lanes[$ivsno][$member_tag]}&OUTSTATUS=0"); | |||
| } | |||
| // 調撥車道查詢 | |||
| public function reversible_lane_query() | |||
| { | |||
| $max_lane = 4; // 共幾個車道數 | |||
| for ($idx = 0; $idx < $max_lane; ++$idx) | |||
| { | |||
| $data[$idx] = file_get_contents("http://192.168.10.51:8090/cgi-bin/switcher.cgi?id={$idx}&action=9"); | |||
| } | |||
| // $data = array(1, 1, 0, 1); | |||
| echo json_encode($data); | |||
| } | |||
| // 車號入場查詢 | |||
| public function carin_lpr_query() | |||
| { | |||
| $lpr = $this->uri->segment(3); | |||
| $data = $this->carpark_model->carin_lpr_query($lpr); | |||
| echo json_encode($data); | |||
| } | |||
| // 以時間查詢入場資訊 | |||
| public function carin_time_query() | |||
| { | |||
| $time_query = $this->input->post('time_query', true); | |||
| $minutes_range = $this->input->post('minutes_range', true); | |||
| $data = $this->carpark_model->carin_time_query($time_query, $minutes_range); | |||
| echo json_encode($data); | |||
| } | |||
| // 調撥車道設定 | |||
| public function reversible_lane_set() | |||
| { | |||
| $lane_no = $this->input->post('lane_no', true); | |||
| $actions = $this->input->post('actions', true); | |||
| $data = file_get_contents("http://192.168.10.51:8090/cgi-bin/switcher.cgi?id={$lane_no}&action={$actions}"); | |||
| echo "{$lane_no}|{$actions}|{$data}"; | |||
| } | |||
| // 在席車位檢查未有入場資料清單 | |||
| public function pks_check_list() | |||
| { | |||
| $max_rows = $this->uri->segment(3, 100); // 一次讀取筆數, 預設為100筆 | |||
| $data = $this->carpark_model->pks_check_list($max_rows); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // 重設在席查核 | |||
| public function reset_pks_check() | |||
| { | |||
| $data = $this->carpark_model->reset_pks_check(); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // 更正在席車號 | |||
| public function correct_pks_lpr() | |||
| { | |||
| $pksno = $this->uri->segment(3, 0); // 車格號碼 | |||
| $lpr = $this->uri->segment(4, 'NONE'); // 車號 | |||
| if ($pksno == 0 || $lpr == 'NONE') | |||
| { | |||
| echo json_encode(array('err' => 1, 'cario_no' => 0), JSON_UNESCAPED_UNICODE); | |||
| } | |||
| else | |||
| { | |||
| $data = $this->carpark_model->correct_pks_lpr($pksno, $lpr); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| } | |||
| // 入場車號查核在席無資料清單 | |||
| public function carin_check_list() | |||
| { | |||
| $max_rows = $this->uri->segment(3, 20); // 一次讀取筆數, 預設為100筆 | |||
| $data = $this->carpark_model->carin_check_list($max_rows); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // 更正入場車號 | |||
| public function correct_carin_lpr() | |||
| { | |||
| $cario_no = $this->uri->segment(3, 0); // 車格號碼 | |||
| $lpr = $this->uri->segment(4, 'NONE'); // 車號 | |||
| $in_time = urldecode($this->uri->segment(5, '')); // 入場時間 | |||
| $data = $this->carpark_model->correct_carin_lpr($cario_no, $lpr, $in_time); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // 查詢行動支付記錄 | |||
| public function tx_bill_query() | |||
| { | |||
| $data = $this->carpark_model->tx_bill_query(); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // 查詢月租繳款機記錄 | |||
| public function tx_bill_ats_query() | |||
| { | |||
| $data = $this->carpark_model->tx_bill_ats_query(); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // 查詢樓層在席群組 | |||
| public function pks_group_query() | |||
| { | |||
| $data = $this->carpark_model->pks_group_query(); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // 微調剩餘車位數 | |||
| public function pks_availables_update() | |||
| { | |||
| $group_id = $this->uri->segment(3); // id | |||
| $value = $this->uri->segment(4, 0); // value | |||
| $station_no = $this->uri->segment(5); // station_no | |||
| $data = $this->sync_data_model->pks_availables_update($group_id, $value, true, $station_no); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // 進出場觸發 888 呼叫 | |||
| /* | |||
| public function sync_888() | |||
| { | |||
| $io = $this->uri->segment(3); // CI, CO, MI, MO | |||
| if(empty($io)) | |||
| { | |||
| echo 'io_not_found'; | |||
| exit; | |||
| } | |||
| $parms = array('io' => $io, 'etag' => __FUNCTION__, 'lpr' => __FUNCTION__); | |||
| echo $this->sync_data_model->sync_888($parms); | |||
| exit; | |||
| } | |||
| */ | |||
| public function test() | |||
| { | |||
| //echo `whoami`; | |||
| //echo phpinfo(); | |||
| } | |||
| // 博辰測試用 | |||
| // http://localhost/carpark.html/test_8068_002/APK7310 | |||
| public function test_8068_002() | |||
| { | |||
| $lpr_in = $this->uri->segment(3); | |||
| $seqno = '00001'; | |||
| $cmd = '002'; | |||
| $token = '000000000'; | |||
| $lpr = str_pad($lpr_in, 7, '%', STR_PAD_LEFT); | |||
| $in_time = '2000/01/01 00:00:00'; | |||
| $error_str = ''; | |||
| $service_port = 8068; | |||
| $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 | |||
| ); | |||
| $out = ''; | |||
| echo "socket_write:"; | |||
| echo "{$in}<br/><br/>"; | |||
| if(!socket_write($socket, $in, strlen($in))) | |||
| { | |||
| echo('<p>Write failed</p>'); | |||
| $error_str .= "socket_write() failed: reason: " . socket_strerror(socket_last_error($socket)) . "\n"; | |||
| } | |||
| echo "socket_write..OK.."; | |||
| echo "<br/><br/>socket_read:"; | |||
| $out = socket_read($socket, 2048) or die("Could not read server responsen"); | |||
| //while ($out = socket_read($socket, 2048)) { | |||
| // echo $out; | |||
| //} | |||
| echo "{$out}<br/><br/>"; | |||
| echo "Closing socket..."; | |||
| socket_close($socket); | |||
| echo "OK.\n\n"; | |||
| trigger_error($error_str); | |||
| exit; | |||
| } | |||
| // test | |||
| public function test_phpexcel() | |||
| { | |||
| $query_year = 2017; | |||
| $query_month = 3; | |||
| //$this->excel_model->export_cario_data($query_year, $query_month); | |||
| $this->excel_model->export_members(); | |||
| } | |||
| } | |||
| @@ -0,0 +1,238 @@ | |||
| <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); | |||
| /* | |||
| file: Carpayment.php 停車計費 | |||
| http://192.168.10.201/carpayment.html/query_in/ (查詢入場時間) | |||
| http://192.168.10.201/carpayment.html/p2payed/ | |||
| */ | |||
| // ----- 定義常數(路徑, cache秒數) ----- | |||
| define('APP_VERSION', '100'); // 版本號 | |||
| define('MAX_AGE', 604800); // cache秒數, 此定義1個月 | |||
| define('APP_NAME', 'carpayment'); // 應用系統名稱 | |||
| define('PAGE_PATH', APP_BASE.'ci_application/views/'.APP_NAME.'/'); // path of views | |||
| define('SERVER_URL', 'http://'.(isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : 'localhost').'/'); // URL | |||
| define('APP_URL', SERVER_URL.APP_NAME.'.html/'); // controller路徑 | |||
| define('WEB_URL', SERVER_URL.APP_NAME.'/'); // 網頁路徑 | |||
| define('WEB_LIB', SERVER_URL.'/libs/'); // 網頁lib | |||
| define('BOOTSTRAPS', WEB_LIB.'bootstrap_sb/'); // bootstrap lib | |||
| define('LOG_PATH', FILE_BASE.APP_NAME.'/logs/'); // log path name | |||
| define('LOG_FILE', FILE_BASE.APP_NAME.'/logs/carpayment.'); // log file name | |||
| class Carpayment extends CI_Controller | |||
| { | |||
| var $vars = array(); | |||
| function __construct() | |||
| { | |||
| // $this->time_start = microtime(true); | |||
| parent::__construct(); | |||
| 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 | |||
| /* | |||
| // 共用記憶體 | |||
| $this->vars['mcache'] = new Memcache; | |||
| $this->vars['mcache']->pconnect(MEMCACHE_HOST, MEMCACHE_POST) or die ('Could not connect memcache'); | |||
| // mqtt subscribe | |||
| $this->vars['mqtt'] = new phpMQTT(MQ_HOST, MQ_PORT, uniqid()); | |||
| if(!$this->vars['mqtt']->connect()){ die ('Could not connect mqtt'); } | |||
| */ | |||
| $this->load->model('carpayment_model'); | |||
| $this->carpayment_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 '<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body><pre style="white-space: pre-wrap;">'; | |||
| echo '<html lang="zh-TW"><body><pre style="white-space: pre-wrap;">'; | |||
| 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 '</pre></body></html>'; | |||
| } | |||
| // http://localhost/carpayment.html/p2payed/ (post method) | |||
| // 可用$this->input->is_cli_request()判斷是否在cli之下執行 | |||
| // 博辰aps已付款 | |||
| public function p2payed() | |||
| { | |||
| $parms['ticket_no'] = $this->input->post('ticket_no', true); | |||
| $parms['lpr'] = trim($this->input->post('lpr', true)); | |||
| $parms['in_time'] = $this->input->post('in_time', true); | |||
| $parms['pay_time'] = $this->input->post('pay_time', true); | |||
| $parms['pay_type'] = $this->input->post('pay_type', true); | |||
| trigger_error('博辰付款參數:' . print_r($parms, true)); | |||
| $this->carpayment_model->p2payed($parms); | |||
| } | |||
| /* | |||
| 月租繳款完成 | |||
| http://203.75.167.89/carpayment.html/memberpayed/12345/ABC1234/120/12112/1/2016-01-31/1f3870be274f6c49b3e31a0c6728957f | |||
| http://203.75.167.89/carpayment.html/memberpayed/會員號碼/車牌/金額/場站編號/月繳/本期到期日/md5 | |||
| md5(會員號碼.車牌.金額.場站編號.月繳.本期到期日) | |||
| public function memberpayed() | |||
| { | |||
| $parms['member_no'] = $lines = $this->uri->segment(3); | |||
| $parms['lpr'] = $lines = $this->uri->segment(4); | |||
| $parms['amt'] = $lines = $this->uri->segment(5); | |||
| $parms['station_no'] = $lines = $this->uri->segment(6); | |||
| $parms['period_type'] = $lines = $this->uri->segment(7); | |||
| $parms['expire_date'] = $lines = $this->uri->segment(8); | |||
| $md5 = $this->uri->segment(9); | |||
| if (md5($parms['member_no'].$parms['lpr'].$parms['amt'].$parms['station_no'].$parms['seqno'].$parms['period_type'].$parms['expire_date']) === $md5) | |||
| { | |||
| $this->carpayment_model->memberpayed($parms); | |||
| } | |||
| } | |||
| */ | |||
| // 繳費機告知已付款 (new 2016/07/15) | |||
| // http://localhost/carpayment.html/ats2payed/車牌/金額/場站編號/序號/MD5 | |||
| // md5(車牌.金額.場站編號.序號) | |||
| public function ats2payed() | |||
| { | |||
| $result = []; | |||
| $parms['lpr'] = $lines = $this->uri->segment(3); | |||
| $parms['amt'] = $lines = $this->uri->segment(4); | |||
| $parms['station_no'] = $lines = $this->uri->segment(5); | |||
| $parms['order_no'] = $lines = $this->uri->segment(6); | |||
| $md5 = $this->uri->segment(7); | |||
| if (md5($parms['lpr'].$parms['amt'].$parms['station_no'].$parms['order_no']) === $md5) | |||
| { | |||
| $this->carpayment_model->ats2payed($parms); | |||
| } | |||
| } | |||
| // 行動支付, 手機告知已付款 | |||
| // http://203.75.167.89/carpayment.html/m2payed/ABC1234/120/12112/12345/1f3870be274f6c49b3e31a0c6728957f | |||
| // http://203.75.167.89/carpayment.html/m2payed/車牌/金額/場站編號/序號/MD5 | |||
| // md5(車牌.金額.場站編號.序號) | |||
| public function m2payed() | |||
| { | |||
| $parms['lpr'] = $lines = $this->uri->segment(3); | |||
| $parms['amt'] = $lines = $this->uri->segment(4); | |||
| $parms['station_no'] = $lines = $this->uri->segment(5); | |||
| $parms['seqno'] = $lines = $this->uri->segment(6); | |||
| $md5 = $this->uri->segment(7); | |||
| echo $this->carpayment_model->m2payed($parms); | |||
| /* | |||
| $seqno = !empty($_SESSION['seqno']) ? $_SESSION['seqno'] : 0; | |||
| unset($_SESSION['seqno']); | |||
| if ($parms['seqno'] != 0 && $parms['seqno'] == $seqno && md5($parms['lpr'].$parms['amt'].$parms['station_no'].$parms['seqno']) === $md5) | |||
| { | |||
| echo $this->carpayment_model->m2payed($parms); | |||
| } | |||
| else | |||
| echo 'fail'; | |||
| */ | |||
| } | |||
| // 查詢入場時間 | |||
| public function query_in() | |||
| { | |||
| $lpr = $this->input->post('lpr', true); | |||
| $data = $this->carpayment_model->query_in($lpr); | |||
| echo json_encode($data); | |||
| } | |||
| // 查詢入場時間 (fuzzy) | |||
| public function query_in_fuzzy() | |||
| { | |||
| $lpr = $this->input->post('lpr', true); | |||
| $data = $this->carpayment_model->query_in_fuzzy($lpr); | |||
| echo json_encode($data); | |||
| } | |||
| // 行動設備查詢入場時間 | |||
| // http://203.75.167.89/carpayment.html/m2query_in/ABC1234/12112/1f3870be274f6c49b3e31a0c6728957f | |||
| // http://203.75.167.89/carpayment.html/m2query_in/車牌/場站編號/MD5 | |||
| // 回傳0: 失敗, 成功: 12345,60(第一欄位非0數字代表成功, 第二欄位為金額), 此值在付款時必需傳回, 否則視為非法 | |||
| public function m2query_in() | |||
| { | |||
| $parms['lpr'] = $lines = $this->uri->segment(3); | |||
| $parms['station_no'] = $lines = $this->uri->segment(4); | |||
| $md5 = $this->uri->segment(5); | |||
| // 驗證md5 | |||
| if (md5($parms['lpr'].$parms['station_no']) === $md5) | |||
| { | |||
| $data = $this->carpayment_model->m2query_in($parms); | |||
| } | |||
| else | |||
| { | |||
| $data = 0; | |||
| } | |||
| $_SESSEION['seqno'] = $data; | |||
| echo $data; | |||
| } | |||
| // 測試:回傳 seat_no | |||
| // http://192.168.0.199/carpayment.html/test_seat_no/B2/123 | |||
| public function test_seat_no() | |||
| { | |||
| $rows['group_id'] = $this->uri->segment(3); | |||
| $rows['pksno'] = $this->uri->segment(4); | |||
| //echo substr($rows['group_id'], 0, 1); | |||
| echo (substr($rows['group_id'], 0, 1) == 'B' ? '-' : '0') . substr($rows['group_id'], 1, 1) . '_' . substr($rows['pksno'], -3); | |||
| } | |||
| } | |||
| @@ -0,0 +1,234 @@ | |||
| <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); | |||
| /* | |||
| file: cars.php 車輛進出場處理(板車版含感應線圈) | |||
| URL: | |||
| http://192.168.10.201/cars.html/ipcam/sno/12119/ivsno/0/io/O/type/C/lpr/4750YC/color/NULL/sq/0/ts/1441051995/sq2/0/etag/ABCD123456789/ant/1 | |||
| javascript/html從server讀取key/value方式 | |||
| http://61.220.179.128/jsid.i/ip=ip&uniqid=clientid&mqtt_ip=mqtt_ip | |||
| 例如: | |||
| <script src="http://61.220.179.128/jsid.i/ip=ip&uniqid=clientid&mqtt_ip=mqtt_ip"></script> | |||
| response: | |||
| var ip='66.249.82.183';var clientid='565162cb67dfb';var mqtt_ip='192.168.51.11'; | |||
| */ | |||
| // ----- 定義常數(路徑, cache秒數) ----- | |||
| define('APP_VERSION', '100'); // 版本號 | |||
| define('MAX_AGE', 604800); // cache秒數, 此定義1個月 | |||
| define('APP_NAME', 'cars'); // 應用系統名稱 | |||
| define('PAGE_PATH', APP_BASE.'ci_application/views/'.APP_NAME.'/'); // path of views | |||
| define('SERVER_URL', 'http://'.(isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : 'localhost').'/'); // URL | |||
| define('APP_URL', SERVER_URL.APP_NAME.'.html/'); // controller路徑 | |||
| define('WEB_URL', SERVER_URL.APP_NAME.'/'); // 網頁路徑 | |||
| define('WEB_LIB', SERVER_URL.'/libs/'); // 網頁lib | |||
| define('BOOTSTRAPS', WEB_LIB.'bootstrap_sb/'); // bootstrap lib | |||
| define('LOG_PATH', FILE_BASE.APP_NAME.'/logs/'); // log path name | |||
| define('LOG_FILE', FILE_BASE.APP_NAME.'/logs/cario.'); // log file name | |||
| require_once(MQ_CLASS_FILE); | |||
| class Cars extends CI_Controller | |||
| { | |||
| var $vars = array(); | |||
| function __construct() | |||
| { | |||
| // $this->time_start = microtime(true); | |||
| parent::__construct(); | |||
| ignore_user_abort(); // 接受client斷線, 繼續run | |||
| $method_name = $this->router->fetch_method(); | |||
| if ($method_name == 'ipcam' || $method_name == 'check_lpr_etag') | |||
| { | |||
| ob_end_clean(); | |||
| ignore_user_abort(); | |||
| ob_start(); | |||
| header('Connection: close'); | |||
| header('Content-Length: ' . ob_get_length()); | |||
| ob_end_flush(); | |||
| flush(); | |||
| } | |||
| else if($method_name == 'opendoor') | |||
| { | |||
| ob_end_clean(); | |||
| ignore_user_abort(); | |||
| ob_start(); | |||
| echo 'ok'; | |||
| header('Connection: close'); | |||
| header('Content-Length: ' . ob_get_length()); | |||
| ob_end_flush(); | |||
| flush(); | |||
| } | |||
| $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 | |||
| // 共用記憶體 | |||
| $this->vars['mcache'] = new Memcache; | |||
| $this->vars['mcache']->pconnect(MEMCACHE_HOST, MEMCACHE_PORT) or die ('Could not connect memcache'); | |||
| // mqtt subscribe | |||
| $this->vars['mqtt'] = new phpMQTT(MQ_HOST, MQ_PORT, uniqid()); | |||
| //if(!$this->vars['mqtt']->connect()){ die ('Could not connect mqtt'); } | |||
| if(!$this->vars['mqtt']->connect()){ trigger_error('..Could not connect mqtt..go on..'); } | |||
| $this->load->model('cars_model'); | |||
| $this->cars_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 = 140; // 無行數參數, 預設為40行 | |||
| // echo '<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body><pre style="white-space: pre-wrap;">'; | |||
| echo '<html lang="zh-TW"><body><pre style="white-space: pre-wrap;">'; | |||
| 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 '</pre></body></html>'; | |||
| } | |||
| /* | |||
| 出入口 | |||
| 說明: 與ipcam相同判斷邏輯, 但不做任何資料更改 | |||
| */ | |||
| public function opendoor() | |||
| { | |||
| $parms = $this->uri->uri_to_assoc(3); | |||
| $parms['lpr'] = urldecode($parms['lpr']); // 中文車牌 | |||
| $this->cars_model->opendoor_lprio($parms); | |||
| } | |||
| // IVS -> 車號, 影像 | |||
| /* | |||
| 鼎高IVS傳送車號及影像檔 | |||
| http://192.168.10.201/cars.html/ipcam/sno/12119/ivsno/0/io/O/type/C/lpr/4750YC/color/NULL/sq/0/ts/1441051995/sq2/0/etag/ABCD123456789/ant/1 | |||
| sno: 場站編號(光興國小:12119) | |||
| ivsno: ivs編號, 每一支都是獨立編號(序號) | |||
| io: i:進場, o:出場 | |||
| type: C:汽車, H:重機, M:機車 | |||
| lpr: ABC-1234(車號) | |||
| color: red(紅色), 若無請用NULL(4個字) | |||
| sq: 序號(參考用) | |||
| sq2: 暫不用 | |||
| etag: eTag ID | |||
| ant: eTag | |||
| http設定說明: | |||
| method: POST | |||
| 上傳圖檔名英數字, 副檔名為gif/jpg/png均可 | |||
| 上傳圖檔欄位名稱為cars | |||
| */ | |||
| public function ipcam() | |||
| { | |||
| $parms = $this->uri->uri_to_assoc(3); | |||
| $parms['lpr'] = urldecode($parms['lpr']); // 中文車牌 | |||
| // 同步並送出一次出入口 888 | |||
| $this->load->model('sync_data_model'); | |||
| $this->sync_data_model->init($this->vars); | |||
| $this->sync_data_model->sync_888($parms); | |||
| $pic_folder = CAR_PIC.$this->vars['date_num'].'/'; // 今日資料夾名(yyyymmdd) | |||
| if (!file_exists($pic_folder)) mkdir($pic_folder); // 如果資料夾不存在, 建立日期資料夾 | |||
| $config['upload_path'] = $pic_folder; | |||
| // $config['allowed_types'] = 'gif|jpg|png'; | |||
| $config['allowed_types'] = '*'; | |||
| // ex. lpr_1625AB_I_1_152_C_1_2015080526.jpg -> car_交易序號_進出_順序_車號_時間.jpg | |||
| $config['file_name'] = "lpr-{$parms['lpr']}-{$parms['io']}-{$parms['ivsno']}-{$parms['sq']}-{$parms['type']}-{$parms['sq2']}-{$this->vars['time_num']}.jpg"; | |||
| if (!isset($_FILES['cars'])) | |||
| { | |||
| $status = 'error'; // 顯示上傳錯誤 | |||
| trigger_error('[ERROR] cars not found: ' . print_r($_FILES, true)); | |||
| } | |||
| else | |||
| { | |||
| $this->load->library('upload', $config); | |||
| if(!$this->upload->do_upload('cars')){ | |||
| $status = 'error'; // 顯示上傳錯誤 | |||
| trigger_error($this->upload->display_errors()); | |||
| } | |||
| else | |||
| { | |||
| // 若無錯誤,則上傳檔案 | |||
| $file = $this->upload->data('cars'); | |||
| $status = 'ok'; | |||
| } | |||
| } | |||
| $parms['obj_type'] = 1; // 車牌類 | |||
| $parms['curr_time_str'] = $this->vars['date_time']; // 現在時間, 例2015-09-21 15:36:47 | |||
| $parms['pic_name'] = $config['file_name']; // 圖片檔名 | |||
| $this->cars_model->lprio($parms); // 測試eTag | |||
| } | |||
| // 用車牌與eTag, 檢查資料庫 | |||
| public function check_lpr_etag() | |||
| { | |||
| $lpr = $this->uri->segment(3); | |||
| $etag = $this->uri->segment(4); | |||
| $this->cars_model->check_lpr_etag($lpr, $etag); | |||
| exit; | |||
| } | |||
| public function test_now() | |||
| { | |||
| echo date('Y-m-d H:i:s'); | |||
| } | |||
| public function test_phpinfo() | |||
| { | |||
| phpinfo(); | |||
| } | |||
| } | |||
| @@ -0,0 +1,218 @@ | |||
| <?php | |||
| /* | |||
| file: Ctbcbank.php 中國信託介接 | |||
| */ | |||
| if ( ! defined('BASEPATH')) exit('No direct script access allowed'); | |||
| class Ctbcbank extends CI_Controller | |||
| { | |||
| var $vars = array(); // 共用變數 | |||
| function __construct() | |||
| { | |||
| parent::__construct(); | |||
| // ----- 程式開發階段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 | |||
| /* | |||
| // 共用記憶體 | |||
| $this->vars['mcache'] = new Memcache; | |||
| $this->vars['mcache']->connect(MEMCACHE_HOST, MEMCACHE_PORT) or die ('Could not connect memcache'); | |||
| // mqtt subscribe | |||
| $this->vars['mqtt'] = new phpMQTT(MQ_HOST, MQ_PORT, uniqid()); | |||
| if(!$this->vars['mqtt']->connect()){ die ('Could not connect mqtt'); } | |||
| */ | |||
| // ----- 定義常數(路徑, cache秒數) ----- | |||
| define('APP_VERSION', '100'); // 版本號 | |||
| define('MAX_AGE', 604800); // cache秒數, 此定義1個月 | |||
| define('APP_NAME', 'ctbcbank'); // 應用系統名稱 | |||
| define('PAGE_PATH', APP_BASE.'ci_application/views/'.APP_NAME.'/'); // path of views | |||
| define('SERVER_URL', 'http://'.(isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : 'localhost').'/'); // URL | |||
| define('APP_URL', SERVER_URL.APP_NAME.'.html/'); // controller路徑 | |||
| define('WEB_URL', SERVER_URL.APP_NAME.'/'); // 網頁路徑 | |||
| define('WEB_LIB', SERVER_URL.'libs/'); // 網頁lib | |||
| define('BOOTSTRAPS', WEB_LIB.'bootstrap_sb/'); // bootstrap lib | |||
| define('LOG_PATH', FILE_BASE.APP_NAME.'/logs/'); // log path | |||
| //$this->load->model('twgc_model'); | |||
| // $this->parkingquery_model->init($this->vars); | |||
| $this->load->model('payment_model'); // 帳單 | |||
| $this->load->model('ctbcbank_model');// 中國信託金流 | |||
| $this->load->model('allpay_invoice_model'); // 歐付寶電子發票 | |||
| define('CTBC_AuthResURL', APP_URL."return_ok/"); // 從收單行端取得授權碼後,要導回的網址,請勿填入特殊字元@、#、%、?、&等。 | |||
| define('MAIN_PAGE', "main_page"); | |||
| define('RESULT_PAGE', "result_page"); | |||
| define('ERROR_PAGE', "error_page"); | |||
| // ----- 回傳訊息 ----- | |||
| define('RESULT_CODE_OK', "OK"); | |||
| define('RESULT_CODE_UNKNOWN_ERROR', "-99"); | |||
| define('RESULT_MSG_UNKNOWN_ERROR', "發生未預期錯誤"); | |||
| // ----- 回傳訊息 (END) ----- | |||
| } | |||
| // 發生錯誤時集中在此處理 | |||
| public function error_handler($errno, $errstr, $errfile, $errline, $errcontext) | |||
| { | |||
| $str = date('H:i:s')."|{$errstr}|{$errfile}|{$errline}|{$errno}\n"; | |||
| //error_log($str, 3, $log_file . '.' . date('Ymd').'.log.txt'); // 3代表參考後面的檔名 | |||
| //echo $str; | |||
| error_log($str, 3, LOG_PATH.APP_NAME . '.' . date('Ymd').'.log.txt'); // 3代表參考後面的檔名 | |||
| } | |||
| // 顯示靜態網頁(html檔) | |||
| protected function show_page($page_name, &$data = null) | |||
| { | |||
| $page_file = PAGE_PATH.$page_name.'.php'; | |||
| $last_modified_time = filemtime($page_file); | |||
| // 若檔案修改時間沒有異動, 或版本無異動, 通知瀏覽器使用cache, 不再下傳網頁 | |||
| // header('Cache-Control:max-age='.MAX_AGE); // cache 1個月 | |||
| header('Last-Modified: '.gmdate('D, d M Y H:i:s', $last_modified_time).' GMT'); | |||
| header('Etag: '. APP_VERSION); | |||
| header('Cache-Control: public'); | |||
| if (!empty($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] == APP_VERSION && @strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) == $last_modified_time) | |||
| { | |||
| header('HTTP/1.1 304 Not Modified'); | |||
| } | |||
| else | |||
| { | |||
| $this->load->view(APP_NAME.'/'.$page_name, $data); | |||
| } | |||
| } | |||
| // 首頁 | |||
| public function index() | |||
| { | |||
| $this->show_page(MAIN_PAGE); // http://203.75.167.89/ctbcbank.html | |||
| } | |||
| // 查車付款 - 1.查車拿帳單 | |||
| public function payment_lpr() | |||
| { | |||
| $payment_lpr = $this->input->post('payment_lpr', true); | |||
| $data = $this->payment_model->create_cario_bill($payment_lpr); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // 查車付款 - 2.確定繳交帳單 | |||
| public function transfer_money() | |||
| { | |||
| $order_no = strtoupper($this->uri->segment(3)); // 交易序號 | |||
| $invoice_receiver = urldecode($this->uri->segment(4)); // 載具編號 (可有可無) | |||
| $company_no = urldecode($this->uri->segment(5)); // 載具編號 (可有可無) | |||
| $email_base64 = $this->uri->segment(6); // 電子信箱 | |||
| $mobile = $this->uri->segment(7); // 手機號碼 | |||
| // decode email | |||
| if(strlen($email_base64) > 0){ | |||
| $email = base64_decode($email_base64.'='); // base64字串尾端的'='還原 | |||
| }else{ | |||
| $email = email_base64; | |||
| } | |||
| $data = $this->payment_model->pay_bill($order_no, $invoice_receiver, $company_no, $email, $mobile); // 繳交帳單 | |||
| if (!empty($data)){ | |||
| $this->ctbcbank_model->transfer_money_ctbc($data, CTBC_AuthResURL); // 中國信託 | |||
| } | |||
| } | |||
| // C.4 收單行端取得授權碼後,要導回的網址 (call by CTBC) | |||
| public function return_ok() | |||
| { | |||
| /** | |||
| =======ALL_REQUEST====== | |||
| URLResEnc: AF2100C51A9E844A1E820B953EA512BE49286403253FF9373474F6AE4A5877B084DD4D9B20F03AF0F34DB3D42A9C583938FE5DC1B60C53384864D9581EE997F92552A2F516B04F2FB2FE3E5C10D61CE84C5B63B87379F1048E16AC430AE94989724D8B0087734F73BF40CE904A05D555F526E5A93462C42931A0A7EC1E6AFF8BC39E641A8F5EE8882BD5B02F838BC217A87533AB9FE98CE1DD558B3CC345FC77D06C1783067F75DF94C58B55A826CD33B32355439BF3C9F17A4596138942B4457B66EB8FA09749C246D5B91799FB3942EC90138033272D89861B8698398FF4F3010628C0D11C7D88FB7A5F85CC59717D9F8D5CADBA5A1231E0396AE344B1DA139BA84F9D477E53A73A376BFCC92B52619E3B396BB28ABE7C4CEE3D3ED2CA1BEEF466F2D645C5CBF1C678C5747BA2A048F2F0FC2B86CAE379DE7A7F144D07C31A | |||
| merID: 10063 | |||
| ----------------------------END | |||
| */ | |||
| // 取得回傳資訊 | |||
| foreach ($_REQUEST as $key => $value) { | |||
| switch ($key){ | |||
| case "URLResEnc": $resenc = $value; break; | |||
| case "merID": $merid = $value; break; | |||
| } | |||
| } | |||
| if(! empty($resenc)){ | |||
| $return_data = $this->ctbcbank_model->ctbcbank_return_handler($resenc, $merid); | |||
| $ctbc_lidm = $return_data['lidm']; | |||
| $ctbc_authamt = $return_data['authamt']; | |||
| $ctbc_status = $return_data['status']; | |||
| if($ctbc_status != 0){ | |||
| // 金流處理失敗 | |||
| trigger_error(__FUNCTION__.', ctbc_status GG ..lidm=>' . $ctbc_lidm); | |||
| }else if(! empty($ctbc_lidm)) { | |||
| $data = $this->payment_model->get_tx_bill($ctbc_lidm); | |||
| if (! empty($data)) { | |||
| $order_no = $data['order_no']; | |||
| $lpr = $data['lpr']; | |||
| $amt = $data['amt']; | |||
| $status = $data['status']; | |||
| switch($status){ | |||
| case 100: // 狀態: 0:剛建立, 1:結帳完成, 2:錢沒對上, 3:發票沒建立, 4:手動調整, 99:訂單逾期作廢, 100:交易進行中, 101: 交易失敗, 111:產品已領取 | |||
| // 印發票流程 | |||
| if($ctbc_authamt == $amt){ | |||
| // 先記錄 | |||
| $this->payment_model->transfer_money_done($order_no); | |||
| // 開立歐付寶電子發票 | |||
| //$this->allpay_invoice_model->invoice_issue_for_product_bill($order_no, $amt); | |||
| // 交易成功 | |||
| $this->show_page(RESULT_PAGE); | |||
| return; | |||
| }else{ | |||
| // 錢沒對上 | |||
| $this->payment_model->transfer_money_done_with_error_2($order_no); | |||
| } | |||
| break; | |||
| default: | |||
| // 對方多傳一次時?? | |||
| trigger_error(__FUNCTION__.', order_no=>' . $order_no.'<br>'.'status != 100'); | |||
| } | |||
| }else{ | |||
| // 我們自己找不到記錄時?? | |||
| trigger_error(__FUNCTION__.', order_no=>' . $order_no.'<br>'.' NOT FOUND !!'); | |||
| } | |||
| }else{ | |||
| // 回傳沒有資料 lidm | |||
| trigger_error(__FUNCTION__.', ERROR ..lidm=>' . $ctbc_lidm); | |||
| } | |||
| }else{ | |||
| // 回傳沒有資料 resenc | |||
| trigger_error(__FUNCTION__.', ERROR ..resenc=>' . $resenc); | |||
| } | |||
| // 交易失敗 | |||
| $this->show_page(ERROR_PAGE); | |||
| } | |||
| } | |||
| @@ -0,0 +1,163 @@ | |||
| <?php | |||
| /* | |||
| file: carpark.php 停車管理 | |||
| */ | |||
| if ( ! defined('BASEPATH')) exit('No direct script access allowed'); | |||
| // require_once(MQ_CLASS_FILE); | |||
| class Parkingquery extends CI_Controller | |||
| { | |||
| var $vars = array(); // 共用變數 | |||
| function __construct() | |||
| { | |||
| parent::__construct(); | |||
| // ----- 程式開發階段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 | |||
| /* | |||
| // 共用記憶體 | |||
| $this->vars['mcache'] = new Memcache; | |||
| $this->vars['mcache']->connect(MEMCACHE_HOST, MEMCACHE_PORT) or die ('Could not connect memcache'); | |||
| // mqtt subscribe | |||
| $this->vars['mqtt'] = new phpMQTT(MQ_HOST, MQ_PORT, uniqid()); | |||
| if(!$this->vars['mqtt']->connect()){ die ('Could not connect mqtt'); } | |||
| */ | |||
| // ----- 定義常數(路徑, cache秒數) ----- | |||
| define('APP_VERSION', '100'); // 版本號 | |||
| define('MAX_AGE', 604800); // cache秒數, 此定義1個月 | |||
| define('APP_NAME', 'parkingquery'); // 應用系統名稱 | |||
| define('PAGE_PATH', APP_BASE.'ci_application/views/'.APP_NAME.'/'); // path of views | |||
| define('SERVER_URL', 'http://'.(isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : 'localhost').'/'); // URL | |||
| define('APP_URL', SERVER_URL.APP_NAME.'.html/'); // controller路徑 | |||
| define('WEB_URL', SERVER_URL.APP_NAME.'/'); // 網頁路徑 | |||
| define('WEB_LIB', SERVER_URL.'libs/'); // 網頁lib | |||
| define('BOOTSTRAPS', WEB_LIB.'bootstrap_sb/'); // bootstrap lib | |||
| define('LOG_PATH', FILE_BASE.APP_NAME.'/logs/'); // log path | |||
| $this->load->model('parkingquery_model'); | |||
| $this->load->model('security_model'); // 鎖車 | |||
| // $this->parkingquery_model->init($this->vars); | |||
| } | |||
| // 發生錯誤時集中在此處理 | |||
| public function error_handler($errno, $errstr, $errfile, $errline, $errcontext) | |||
| { | |||
| $str = date('H:i:s')."|{$errstr}|{$errfile}|{$errline}|{$errno}\n"; | |||
| //error_log($str, 3, $log_file . '.' . date('Ymd').'.log.txt'); // 3代表參考後面的檔名 | |||
| error_log($str, 3, LOG_PATH.APP_NAME . '.' . date('Ymd').'.log.txt'); // 3代表參考後面的檔名 | |||
| } | |||
| // 顯示靜態網頁(html檔) | |||
| protected function show_page($page_name, &$data = null) | |||
| { | |||
| $page_file = PAGE_PATH.$page_name.'.php'; | |||
| $last_modified_time = filemtime($page_file); | |||
| // 若檔案修改時間沒有異動, 或版本無異動, 通知瀏覽器使用cache, 不再下傳網頁 | |||
| header('Cache-Control:max-age='.MAX_AGE); // cache 1個月 | |||
| header('Last-Modified: '.gmdate('D, d M Y H:i:s', $last_modified_time).' GMT'); | |||
| header('Etag: '. APP_VERSION); | |||
| header('Cache-Control: public'); | |||
| if (!empty($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] == APP_VERSION && @strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) == $last_modified_time) | |||
| { | |||
| header('HTTP/1.1 304 Not Modified'); | |||
| } | |||
| else | |||
| { | |||
| $this->load->view(APP_NAME.'/'.$page_name, $data); | |||
| } | |||
| } | |||
| // response http | |||
| protected function http_return($return_code, $type) | |||
| { | |||
| if ($type == 'text') echo $return_code; | |||
| else echo json_encode($return_code, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // 查詢各樓層剩餘車位 | |||
| // http://203.75.167.89/parkingquery.html/check_space/12345 | |||
| public function check_space() | |||
| { | |||
| $seqno = $this->uri->segment(3); | |||
| $data = $this->parkingquery_model->check_space($seqno); | |||
| $data['result']['num'] = $seqno; | |||
| $data['result_code'] = 'OK'; | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // 停車位置查詢(板橋好停車) | |||
| // http://203.75.167.89/parkingquery.html/check_location/ABC1234 | |||
| public function check_location() | |||
| { | |||
| $lpr = $this->uri->segment(3); | |||
| $data = $this->parkingquery_model->check_location($lpr); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // 空車位導引 | |||
| // http://203.75.167.89/parkingquery.html/get_valid_seat | |||
| public function get_valid_seat() | |||
| { | |||
| $pksno = $this->uri->segment(3, 0); // 從某一個車位開始, 若無則設0 | |||
| $data = $this->parkingquery_model->get_valid_seat($pksno); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // 緊急求救 | |||
| // http://203.75.167.89/parkingquery.html/send_sos/B2/111/123 | |||
| public function send_sos() | |||
| { | |||
| $floor = $this->uri->segment(3); | |||
| $x = $this->uri->segment(4); | |||
| $y = $this->uri->segment(5); | |||
| get_headers("http://localhost/sos/set_sos.php?floor={$floor}&x={$x}&y={$y}"); | |||
| $data = $this->parkingquery_model->send_sos($floor, $x, $y); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // 防盜鎖車 | |||
| // http://203.75.167.89/parkingquery.html/security_action/ABC1234/pswd/2 | |||
| public function security_action() | |||
| { | |||
| $lpr = $this->uri->segment(3); | |||
| $pswd = $this->uri->segment(4); | |||
| $action = $this->uri->segment(5); | |||
| $data = $this->security_model->security_action($lpr, $pswd, $action); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // 警急求救地圖 | |||
| public function floor_map() | |||
| { | |||
| $this->show_page("floor_map"); | |||
| } | |||
| } | |||
| @@ -0,0 +1,204 @@ | |||
| <?php | |||
| /* | |||
| file: Payment.php 付費系統 | |||
| */ | |||
| if (!defined('BASEPATH')) exit('No direct script access allowed'); | |||
| class Payment extends CI_Controller | |||
| { | |||
| var $vars = array(); // 共用變數 | |||
| function __construct() | |||
| { | |||
| parent::__construct(); | |||
| // ----- 程式開發階段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 | |||
| // ----- 定義常數(路徑, cache秒數) ----- | |||
| define('APP_VERSION', '100'); // 版本號 | |||
| define('MAX_AGE', 604800); // cache秒數, 此定義1個月 | |||
| define('APP_NAME', 'payment'); // 應用系統名稱 | |||
| define('PAGE_PATH', APP_BASE.'ci_application/views/'.APP_NAME.'/'); // path of views | |||
| define('SERVER_URL', 'http://'.(isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : 'localhost').'/'); // URL | |||
| define('APP_URL', SERVER_URL.APP_NAME.'.html/'); // controller路徑 | |||
| define('WEB_URL', SERVER_URL.APP_NAME.'/'); // 網頁路徑 | |||
| define('WEB_LIB', SERVER_URL.'libs/'); // 網頁lib | |||
| define('BOOTSTRAPS', WEB_LIB.'bootstrap_sb/'); // bootstrap lib | |||
| define('LOG_PATH', FILE_BASE.APP_NAME.'/logs/'); // log path | |||
| $this->load->model('payment_model'); // 臨停繳費 | |||
| $this->load->model('allpay_invoice_model'); // 歐付寶電子發票 | |||
| $this->load->model('security_model'); // 鎖車 | |||
| define('MAIN_PAGE', "main_page"); | |||
| define('RESULT_PAGE', "result_page"); | |||
| // ----- 行動支付, 手機告知已付款 ----- | |||
| define('ALTOB_M2PAYED', "http://localhost/carpayment.html/m2payed"); | |||
| // ----- 行動支付, 手機告知已付款 (end) ----- | |||
| // ----- 歐付寶金流 ----- | |||
| define('ALLPAY_PAYMENT_TX_BILL', SERVER_URL."allpay_payment.html/transfer_money_tx_bill"); // 歐付寶付款系統連結 | |||
| define('ALLPAY_ClientBackURL', APP_URL."client_back/"); // 您要歐付寶返回按鈕導向的瀏覽器端網址"; | |||
| define('ALLPAY_OrderResultURL', APP_URL."order_result/"); // 您要收到付款完成通知的瀏覽器端網址(browser) ps. WebATM大部份銀行都回不來; | |||
| define('ALLPAY_AltobServiceURL', APP_URL."payment_completed_handler/"); // 付款完成後被通知的位址 | |||
| // ----- 歐付寶金流 (end) ----- | |||
| } | |||
| // 發生錯誤時集中在此處理 | |||
| public function error_handler($errno, $errstr, $errfile, $errline, $errcontext) | |||
| { | |||
| $str = date('H:i:s')."|{$errstr}|{$errfile}|{$errline}|{$errno}\n"; | |||
| //error_log($str, 3, $log_file . '.' . date('Ymd').'.log.txt'); // 3代表參考後面的檔名 | |||
| error_log($str, 3, LOG_PATH.APP_NAME . '.' . date('Ymd').'.log.txt'); // 3代表參考後面的檔名 | |||
| } | |||
| // 顯示靜態網頁(html檔) | |||
| protected function show_page($page_name, $data = null) | |||
| { | |||
| $page_file = PAGE_PATH.$page_name.'.php'; | |||
| $last_modified_time = filemtime($page_file); | |||
| // 若檔案修改時間沒有異動, 或版本無異動, 通知瀏覽器使用cache, 不再下傳網頁 | |||
| // header('Cache-Control:max-age='.MAX_AGE); // cache 1個月 | |||
| header('Last-Modified: '.gmdate('D, d M Y H:i:s', $last_modified_time).' GMT'); | |||
| header('Etag: '. APP_VERSION); | |||
| header('Cache-Control: public'); | |||
| if (!empty($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] == APP_VERSION && @strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) == $last_modified_time) | |||
| { | |||
| header('HTTP/1.1 304 Not Modified'); | |||
| } | |||
| else | |||
| { | |||
| $this->load->view(APP_NAME.'/'.$page_name, $data); | |||
| } | |||
| } | |||
| // 首頁 | |||
| public function index() | |||
| { | |||
| $this->show_page(MAIN_PAGE); | |||
| } | |||
| // 查車付款 - 1.查車拿帳單 | |||
| public function payment_lpr() | |||
| { | |||
| $payment_lpr = $this->input->post('payment_lpr', true); | |||
| $data = $this->payment_model->create_cario_bill($payment_lpr); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // 查車付款 - 2.確定繳交帳單 | |||
| public function transfer_money() | |||
| { | |||
| $order_no = strtoupper($this->uri->segment(3)); // 交易序號 | |||
| $invoice_receiver = urldecode($this->uri->segment(4)); // 載具編號 (可有可無) | |||
| $company_no = urldecode($this->uri->segment(5)); // 公司統編 (可有可無) | |||
| $email_base64 = $this->uri->segment(6); // 電子信箱 | |||
| $mobile = $this->uri->segment(7); // 手機號碼 | |||
| // decode email | |||
| if(strlen($email_base64) > 0){ | |||
| $email = base64_decode($email_base64.'='); // base64字串尾端的'='還原 | |||
| }else{ | |||
| $email = email_base64; | |||
| } | |||
| $this->payment_model-> // 開始進行繳交帳單 | |||
| pay_bill($order_no, $invoice_receiver, $company_no, $email, $mobile, | |||
| ALLPAY_ClientBackURL, | |||
| ALLPAY_OrderResultURL, | |||
| ALLPAY_AltobServiceURL, | |||
| 50); // 交易種類: 0:未定義, 1:現金, 40:博辰人工模組, 41:博辰自動繳費機, 50:歐付寶轉址刷卡, 51:歐付寶APP, 52:歐付寶轉址WebATM, 60:中國信託刷卡轉址 | |||
| // 轉址歐付寶付款系統 | |||
| echo file_get_contents(ALLPAY_PAYMENT_TX_BILL."/{$order_no}"); | |||
| } | |||
| // L.1 付款完成 (限制存取) | |||
| public function payment_completed_handler() | |||
| { | |||
| $order_no = $this->uri->segment(3); // 交易序號 | |||
| $data = $this->payment_model->get_tx_bill($order_no); | |||
| if (! empty($data)) | |||
| { | |||
| $cario_no = $data['cario_no']; | |||
| $station_no = $data['station_no']; | |||
| $lpr = $data['lpr']; | |||
| $amt = $data['amt']; | |||
| $status = $data['status']; | |||
| switch($status){ | |||
| case 1: // 狀態: 0:剛建立, 1:結帳完成, 2:錢沒對上, 3:發票沒建立, 4:手動調整, 99:訂單逾期作廢, 100:交易進行中, 111:產品已領取 | |||
| // 開立歐付寶電子發票 | |||
| $this->allpay_invoice_model->invoice_issue_for_tx_bill($order_no, $amt); | |||
| // 記錄為已領取 | |||
| $this->payment_model->transfer_money_done_and_finished($order_no); | |||
| // 行動支付, 手機告知已付款 | |||
| // http://203.75.167.89/carpayment.html/m2payed/車牌/金額/場站編號/序號/MD5 | |||
| // md5(車牌.金額.場站編號.序號) | |||
| $md5 = md5($lpr.$amt.$station_no.$cario_no); | |||
| file_get_contents(ALTOB_M2PAYED."/{$lpr}/{$amt}/{$station_no}/{$cario_no}/{$md5}"); | |||
| default: | |||
| // 尚未結帳完成, 或是已領取 | |||
| trigger_error(APP_NAME.', '.__FUNCTION__.', order_no=>' . $order_no.'<br>'.'tx_bill.status != 1'); | |||
| } | |||
| } | |||
| } | |||
| // 歐付寶返回按鈕導向的瀏覽器端網址 | |||
| public function client_back() | |||
| { | |||
| $this->show_page(MAIN_PAGE); | |||
| } | |||
| // 收到付款完成通知的瀏覽器端網址(browser) ps. WebATM大部份銀行都回不來 | |||
| public function order_result() | |||
| { | |||
| $this->show_page(RESULT_PAGE); | |||
| } | |||
| // 其它功能 1: 更改會員密碼 | |||
| public function change_pswd() | |||
| { | |||
| $lpr = $this->input->post('lpr', true); | |||
| $new_pswd = $this->input->post('new_pswd', true); | |||
| $data = $this->security_model->change_pswd($lpr, $new_pswd); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // 其它功能 2: 防盜鎖車 | |||
| public function security_action() | |||
| { | |||
| $lpr = $this->uri->segment(3); | |||
| $pswd = $this->uri->segment(4); | |||
| $action = $this->uri->segment(5); | |||
| $data = $this->security_model->security_action($lpr, $pswd, $action); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // show image | |||
| public function pics() | |||
| { | |||
| readfile(PKS_PIC. $this->uri->segment(3).'.jpg'); | |||
| } | |||
| } | |||
| @@ -0,0 +1,198 @@ | |||
| <?php | |||
| /* | |||
| file: Payment_ats.php 繳費機 | |||
| */ | |||
| if (!defined('BASEPATH')) exit('No direct script access allowed'); | |||
| class Payment_ats extends CI_Controller | |||
| { | |||
| var $vars = array(); // 共用變數 | |||
| function __construct() | |||
| { | |||
| parent::__construct(); | |||
| // ----- 程式開發階段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 | |||
| // ----- 定義常數(路徑, cache秒數) ----- | |||
| define('APP_VERSION', '100'); // 版本號 | |||
| define('MAX_AGE', 604800); // cache秒數, 此定義1個月 | |||
| define('APP_NAME', 'payment_ats'); // 應用系統名稱 | |||
| define('PAGE_PATH', APP_BASE.'ci_application/views/'.APP_NAME.'/'); // path of views | |||
| define('SERVER_URL', 'http://'.(isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : 'localhost').'/'); // URL | |||
| define('APP_URL', SERVER_URL.APP_NAME.'.html/'); // controller路徑 | |||
| define('WEB_URL', SERVER_URL.APP_NAME.'/'); // 網頁路徑 | |||
| define('WEB_LIB', SERVER_URL.'libs/'); // 網頁lib | |||
| define('BOOTSTRAPS', WEB_LIB.'bootstrap_sb/'); // bootstrap lib | |||
| define('LOG_PATH', FILE_BASE.APP_NAME.'/logs/'); // log path | |||
| $this->load->model('payment_ats_model'); // 臨停繳費 | |||
| $this->load->model('allpay_invoice_model'); // 歐付寶電子發票 | |||
| define('MAIN_PAGE', "main_page"); | |||
| define('RESULT_PAGE', "result_page"); | |||
| // ----- 行動支付, 繳費機告知已付款 ----- | |||
| define('ALTOB_ATS2PAYED', "http://localhost/carpayment.html/ats2payed"); | |||
| // ----- 行動支付, 繳費機告知已付款 (end) ----- | |||
| // ----- 歐付寶金流 ----- | |||
| define('ALLPAY_PAYMENT_TX_BILL_ATS', SERVER_URL."allpay_payment.html/transfer_money_tx_bill_ats"); // 歐付寶付款系統連結 | |||
| define('ALLPAY_ClientBackURL', APP_URL."client_back/"); // 您要歐付寶返回按鈕導向的瀏覽器端網址"; | |||
| define('ALLPAY_OrderResultURL', APP_URL."order_result/"); // 您要收到付款完成通知的瀏覽器端網址(browser) ps. WebATM大部份銀行都回不來; | |||
| define('ALLPAY_AltobServiceURL', APP_URL."payment_completed_handler/"); // 付款完成後被通知的位址 | |||
| // ----- 歐付寶金流 (end) ----- | |||
| } | |||
| // 發生錯誤時集中在此處理 | |||
| public function error_handler($errno, $errstr, $errfile, $errline, $errcontext) | |||
| { | |||
| $str = date('H:i:s')."|{$errstr}|{$errfile}|{$errline}|{$errno}\n"; | |||
| //error_log($str, 3, $log_file . '.' . date('Ymd').'.log.txt'); // 3代表參考後面的檔名 | |||
| error_log($str, 3, LOG_PATH.APP_NAME . '.' . date('Ymd').'.log.txt'); // 3代表參考後面的檔名 | |||
| } | |||
| // 顯示靜態網頁(html檔) | |||
| protected function show_page($page_name, $data = null) | |||
| { | |||
| $page_file = PAGE_PATH.$page_name.'.php'; | |||
| $last_modified_time = filemtime($page_file); | |||
| // 若檔案修改時間沒有異動, 或版本無異動, 通知瀏覽器使用cache, 不再下傳網頁 | |||
| // header('Cache-Control:max-age='.MAX_AGE); // cache 1個月 | |||
| header('Last-Modified: '.gmdate('D, d M Y H:i:s', $last_modified_time).' GMT'); | |||
| header('Etag: '. APP_VERSION); | |||
| header('Cache-Control: public'); | |||
| if (!empty($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] == APP_VERSION && @strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) == $last_modified_time) | |||
| { | |||
| header('HTTP/1.1 304 Not Modified'); | |||
| } | |||
| else | |||
| { | |||
| $this->load->view(APP_NAME.'/'.$page_name, $data); | |||
| } | |||
| } | |||
| // 首頁 | |||
| public function index() | |||
| { | |||
| $this->show_page(MAIN_PAGE); | |||
| } | |||
| // 查車付款 - 1.查車拿帳單 | |||
| public function payment_lpr() | |||
| { | |||
| $payment_lpr = $this->input->post('payment_lpr', true); | |||
| $data = $this->payment_ats_model->create_member_bill($payment_lpr); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // 查車付款 - 2.確定繳交帳單 | |||
| public function transfer_money() | |||
| { | |||
| $order_no = strtoupper($this->uri->segment(3)); // 交易序號 | |||
| $invoice_receiver = urldecode($this->uri->segment(4)); // 載具編號 (可有可無) | |||
| $company_no = urldecode($this->uri->segment(5)); // 公司統編 (可有可無) | |||
| $email_base64 = $this->uri->segment(6); // 電子信箱 | |||
| $mobile = $this->uri->segment(7); // 手機號碼 | |||
| // decode email | |||
| if(strlen($email_base64) > 0){ | |||
| $email = base64_decode($email_base64.'='); // base64字串尾端的'='還原 | |||
| }else{ | |||
| $email = email_base64; | |||
| } | |||
| $this->payment_ats_model-> // 開始進行繳交帳單 | |||
| pay_bill($order_no, $invoice_receiver, $company_no, $email, $mobile, | |||
| ALLPAY_ClientBackURL, | |||
| ALLPAY_OrderResultURL, | |||
| ALLPAY_AltobServiceURL, | |||
| 50); // 交易種類: 0:未定義, 1:現金, 40:博辰人工模組, 41:博辰自動繳費機, 50:歐付寶轉址刷卡, 51:歐付寶APP, 52:歐付寶轉址WebATM, 60:中國信託刷卡轉址 | |||
| // 轉址歐付寶付款系統 | |||
| echo file_get_contents(ALLPAY_PAYMENT_TX_BILL_ATS."/{$order_no}"); | |||
| } | |||
| // L.1 付款完成 (限制存取) | |||
| public function payment_completed_handler() | |||
| { | |||
| $order_no = $this->uri->segment(3); // 交易序號 | |||
| $data = $this->payment_ats_model->get_tx_bill($order_no); | |||
| if (! empty($data)) | |||
| { | |||
| $order_no = $data['order_no']; | |||
| $station_no = $data['station_no']; | |||
| $lpr = $data['lpr']; | |||
| $amt = $data['amt']; | |||
| $status = $data['status']; | |||
| switch($status){ | |||
| case 1: // 狀態: 0:剛建立, 1:結帳完成, 2:錢沒對上, 3:發票沒建立, 4:手動調整, 99:訂單逾期作廢, 100:交易進行中, 111:產品已領取 | |||
| // 開立歐付寶電子發票 | |||
| $this->allpay_invoice_model->invoice_issue_for_tx_bill_ats($order_no, $amt); | |||
| // 記錄為已領取 | |||
| $this->payment_ats_model->transfer_money_done_and_finished($order_no); | |||
| // 繳費機告知已付款 | |||
| // http://localhost/carpayment.html/ats2payed/車牌/金額/場站編號/序號/MD5 | |||
| // md5(車牌.金額.場站編號.序號) | |||
| $md5 = md5($lpr.$amt.$station_no.$order_no); | |||
| file_get_contents(ALTOB_ATS2PAYED."/{$lpr}/{$amt}/{$station_no}/{$order_no}/{$md5}"); | |||
| default: | |||
| // 尚未結帳完成, 或是已領取 | |||
| trigger_error(APP_NAME.', '.__FUNCTION__.', order_no=>' . $order_no.'<br>'.' status != 1'); | |||
| } | |||
| } | |||
| } | |||
| // 歐付寶返回按鈕導向的瀏覽器端網址 | |||
| public function client_back() | |||
| { | |||
| $this->show_page(MAIN_PAGE); | |||
| } | |||
| // 收到付款完成通知的瀏覽器端網址(browser) ps. WebATM大部份銀行都回不來 | |||
| public function order_result() | |||
| { | |||
| $this->show_page(RESULT_PAGE); | |||
| } | |||
| // 其它功能 1: 更改會員密碼 | |||
| public function change_pswd() | |||
| { | |||
| $lpr = $this->input->post('lpr', true); | |||
| $new_pswd = $this->input->post('new_pswd', true); | |||
| $data = $this->security_model->change_pswd($lpr, $new_pswd); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // 其它功能 2: 防盜鎖車 | |||
| public function security_action() | |||
| { | |||
| $lpr = $this->uri->segment(3); | |||
| $pswd = $this->uri->segment(4); | |||
| $action = $this->uri->segment(5); | |||
| $data = $this->security_model->security_action($lpr, $pswd, $action); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| } | |||
| @@ -0,0 +1,268 @@ | |||
| <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); | |||
| /* | |||
| file: pks.php 車位在席模組 | |||
| IVS -> 車號, 影像 | |||
| 鼎高IVS傳送車號及影像檔 | |||
| http://203.75.167.89/pks.html/cameras/sno/12112/ivsno/3/pksno/2016/io/KI/type/C/lpr/ABC1234/color/red/sq/5236 | |||
| http://203.75.167.89/pks.html/cameras/sno/12119/ivsno/3/pksno/195/io/KO/type/C/lpr/NONE/color/red/sq/5236 | |||
| sno: 場站編號(新北市圖書館:12118) | |||
| ivsno: ivs編號, 每一支都是獨立編號(序號) | |||
| pksno: 車位編號 | |||
| io: KI:進車格, KO:出車格, KL:車牌 | |||
| type: C:汽車, H:重機, M:機車 | |||
| lpr: ABC1234(車號), 無:NONE | |||
| color: red(紅色), 若無請用NONE(4個字) | |||
| sq: 序號(查詢時參考用) | |||
| http設定說明: | |||
| method: POST | |||
| 上傳圖檔名英數字, 副檔名為gif/jpg/png均可 | |||
| 上傳圖檔欄位名稱為cars | |||
| */ | |||
| require_once(MQ_CLASS_FILE); | |||
| class Pks extends CI_Controller | |||
| { | |||
| var $vars = array(); // 共用變數 | |||
| function __construct() | |||
| { | |||
| // $this->time_start = microtime(true); | |||
| parent::__construct(); | |||
| ignore_user_abort(); // 接受client斷線, 繼續run | |||
| $method_name = $this->router->fetch_method(); | |||
| if ($method_name == 'cameras') | |||
| { | |||
| ob_end_clean(); | |||
| ignore_user_abort(); | |||
| ob_start(); | |||
| header('Connection: close'); | |||
| header('Content-Length: ' . ob_get_length()); | |||
| ob_end_flush(); | |||
| flush(); | |||
| } | |||
| $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; // 本站編號 | |||
| // ----- 程式開發階段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 | |||
| // mqtt subscribe | |||
| $this->vars['mqtt'] = new phpMQTT(MQ_HOST, MQ_PORT, uniqid()); | |||
| if(!$this->vars['mqtt']->connect()){ die ('Could not connect mqtt'); } | |||
| // ----- 定義常數(路徑, cache秒數) ----- | |||
| define('APP_VERSION', '100'); // 版本號 | |||
| define('MAX_AGE', 604800); // cache秒數, 此定義1個月 | |||
| define('APP_NAME', 'pks'); // 應用系統名稱 | |||
| define('PAGE_PATH', APP_BASE.'ci_application/views/'.APP_NAME.'/'); // path of views | |||
| define('SERVER_URL', 'http://'.(isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : 'localhost').'/'); // URL | |||
| define('APP_URL', SERVER_URL.APP_NAME.'.html/'); // controller路徑 | |||
| define('WEB_URL', SERVER_URL.APP_NAME.'/'); // 網頁路徑 | |||
| define('WEB_LIB', SERVER_URL.'/libs/'); // 網頁lib | |||
| define('BOOTSTRAPS', WEB_LIB.'bootstrap_sb/'); // bootstrap lib | |||
| define('LOG_PATH', FILE_BASE.APP_NAME.'/logs/'); // log path name | |||
| define('LOG_FILE', FILE_BASE.APP_NAME.'/logs/pks.'); // log file name | |||
| $this->load->model('pks_model'); | |||
| $this->pks_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代表參考後面的檔名 | |||
| } | |||
| // 顯示靜態網頁(html檔) | |||
| protected function show_page($page_name, &$data = null) | |||
| { | |||
| $page_file = PAGE_PATH.$page_name.'.php'; | |||
| $last_modified_time = filemtime($page_file); | |||
| // 若檔案修改時間沒有異動, 或版本無異動, 通知瀏覽器使用cache, 不再下傳網頁 | |||
| // header('Cache-Control:max-age='.MAX_AGE); // cache 1個月 | |||
| header('Last-Modified: '.gmdate('D, d M Y H:i:s', $last_modified_time).' GMT'); | |||
| header('Etag: '. APP_VERSION); | |||
| header('Cache-Control: public'); | |||
| if (!empty($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] == APP_VERSION && @strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) == $last_modified_time) | |||
| { | |||
| header('HTTP/1.1 304 Not Modified'); | |||
| } | |||
| else | |||
| { | |||
| $this->load->view(APP_NAME.'/'.$page_name, $data); | |||
| } | |||
| } | |||
| public function parked() | |||
| { | |||
| $data['group_id'] = $this->uri->segment(3); | |||
| $data['init_value'] = $this->uri->segment(4); | |||
| // $data['client_id'] = uniqid(); | |||
| // $data['mqtt_ip'] = '192.168.10.201'; | |||
| // $data['port_no'] = 8000; | |||
| $this->load->view(APP_NAME.'/parked', $data); | |||
| } | |||
| // 樓層平面圖 | |||
| // http://203.75.167.89/parkingquery.html/floor_map | |||
| public function floor_map() | |||
| { | |||
| /* | |||
| header('Access-Control-Allow-Origin: *'); | |||
| header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS'); | |||
| header('Access-Control-Allow-Headers: X-Requested-With, Content-Type, Accept'); | |||
| */ | |||
| $this->load->view("parkingquery/floor_map"); | |||
| } | |||
| // response http | |||
| protected function http_return($return_code, $type) | |||
| { | |||
| if ($type == 'text') echo $return_code; | |||
| else echo json_encode($return_code, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // 顯示logs | |||
| public function show_logs() | |||
| { | |||
| $lines = $this->uri->segment(3); // 顯示行數 | |||
| if (empty($lines)) $lines = 40; // 無行數參數, 預設為40行 | |||
| // echo '<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body><pre style="white-space: pre-wrap;">'; | |||
| echo '<html lang="zh-TW"><body><pre style="white-space: pre-wrap;">'; | |||
| if (PHP_OS == 'Linux') | |||
| passthru('/usr/bin/tail -n ' . $lines . ' ' . LOG_FILE); // 利用linux指令顯示倒數幾行的logs內容 | |||
| else | |||
| passthru('d:/afiles/bin/unix_cmd/tail.exe -n ' . $lines . ' ' . LOG_FILE); | |||
| echo "\n----- " . LOG_FILE . ' -----'; | |||
| echo '</pre></body></html>'; | |||
| } | |||
| // IVS -> 車號, 影像 | |||
| /* | |||
| IVS -> 車號, 影像 | |||
| 鼎高IVS傳送車號及影像檔 | |||
| http://203.75.167.89/pks.html/cameras/sno/12119/ivsno/3/pksno/102/io/KI/type/C/lpr/ABC1234/color/red/sq/5236 | |||
| sno: 場站編號(新北市圖書館:12118) | |||
| ivsno: ivs編號, 每一支都是獨立編號(序號) | |||
| pksno: 車位編號 | |||
| io: KI:進車格, KO:出車格, KL:車牌辨識 | |||
| type: C:汽車, H:重機, M:機車 | |||
| lpr: ABC1234(車號) | |||
| color: red(紅色), 若無請用NONE(4個字) | |||
| sq: 序號(查詢時參考用) | |||
| http設定說明: | |||
| method: POST | |||
| 上傳圖檔名英數字, 副檔名為gif/jpg/png均可 | |||
| 上傳圖檔欄位名稱為cars | |||
| */ | |||
| public function cameras() | |||
| { | |||
| $parms = $this->uri->uri_to_assoc(3); | |||
| trigger_error('在席參數傳入:'.print_r($parms, true)); | |||
| // array_map('unlink', glob(PKS_PIC."pks-{$parms['pksno']}-*")); | |||
| /* | |||
| // 車入格後的車牌辨識(lpr), 傅送圖檔 | |||
| if ($parms['io'] == 'KL') | |||
| { | |||
| array_map('unlink', glob(PKS_PIC."pks-{$parms['pksno']}-*.jpg")); // 刪除舊照片 | |||
| $config['upload_path'] = PKS_PIC; | |||
| $config['allowed_types'] = 'gif|jpg|png'; | |||
| // ex. pks-2016-1625AB-1-2015080526.jpg -> pks-車位編號-車號-設備編號-時間.jpg | |||
| $config['file_name'] = "pks-{$parms['pksno']}-{$parms['lpr']}-{$parms['ivsno']}-{$this->vars['time_num']}.jpg"; | |||
| $this->load->library('upload', $config); | |||
| $parms['pic_name'] = $config['file_name']; | |||
| if($this->upload->do_upload('cars')) | |||
| { | |||
| // 若無錯誤,則上傳檔案 | |||
| $file = $this->upload->data('cars'); | |||
| } | |||
| else | |||
| { | |||
| trigger_error('入席傳檔錯誤:'. print_r($parms, true)); | |||
| } | |||
| } | |||
| */ | |||
| $this->pks_model->pksio($parms); // 車輛進出車格資料庫處理 | |||
| exit; | |||
| } | |||
| // 重新計算 | |||
| // http://203.75.167.89/pks.html/reculc/ | |||
| public function reculc() | |||
| { | |||
| $this->pks_model->reculc(); | |||
| } | |||
| // 取得所有車位狀態資訊 | |||
| // http://203.75.167.89/pks.html/query_station_status/12112 | |||
| public function query_station_status() | |||
| { | |||
| $station_no = $this->uri->segment(3); | |||
| $data = $this->pks_model->query_station_status($station_no); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // 取得車位資訊 | |||
| // http://203.75.167.89/pks.html/query_station_pks/12112/2021 | |||
| public function query_station_pks(){ | |||
| $station_no = $this->uri->segment(3); | |||
| $pksno = $this->uri->segment(4); | |||
| $data = $this->pks_model->query_station_pks($station_no, $pksno); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // 車位狀態資訊圖 | |||
| // http://203.75.167.89/pks.html/status_map | |||
| public function status_map() | |||
| { | |||
| $this->show_page("status_map"); | |||
| } | |||
| } | |||
| @@ -0,0 +1,242 @@ | |||
| <?php | |||
| /* | |||
| file: qcar.php 查車系統 | |||
| */ | |||
| if (!defined('BASEPATH')) exit('No direct script access allowed'); | |||
| class Qcar extends CI_Controller | |||
| { | |||
| var $vars = array(); // 共用變數 | |||
| function __construct() | |||
| { | |||
| parent::__construct(); | |||
| // ----- 程式開發階段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 | |||
| /* | |||
| // 共用記憶體 | |||
| $this->vars['mcache'] = new Memcache; | |||
| $this->vars['mcache']->connect(MEMCACHE_HOST, MEMCACHE_POST) or die ('Could not connect memcache'); | |||
| // mqtt subscribe | |||
| $this->vars['mqtt'] = new phpMQTT(MQ_HOST, MQ_POST, 'cario'); | |||
| if(!$this->vars['mqtt']->connect()){ die ('Could not connect mqtt'); } | |||
| */ | |||
| // ----- 定義常數(路徑, cache秒數) ----- | |||
| define('APP_VERSION', '100'); // 版本號 | |||
| define('MAX_AGE', 604800); // cache秒數, 此定義1個月 | |||
| define('APP_NAME', 'qcar'); // 應用系統名稱 | |||
| define('PAGE_PATH', APP_BASE.'ci_application/views/'.APP_NAME.'/'); // path of views | |||
| define('SERVER_URL', 'http://'.(isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : 'localhost').'/'); // URL | |||
| define('APP_URL', SERVER_URL.APP_NAME.'.html/'); // controller路徑 | |||
| define('WEB_URL', SERVER_URL.APP_NAME.'/'); // 網頁路徑 | |||
| define('WEB_LIB', SERVER_URL.'libs/'); // 網頁lib | |||
| define('BOOTSTRAPS', WEB_LIB.'bootstrap_sb/'); // bootstrap lib | |||
| define('LOG_PATH', FILE_BASE.APP_NAME.'/logs/'); // log path | |||
| $this->load->model('qcar_model'); | |||
| $this->load->model('payment_ats_model'); // 繳費 | |||
| $this->load->model('allpay_invoice_model'); // 歐付寶電子發票 | |||
| define('MAIN_PAGE', "main_page"); | |||
| define('RESULT_PAGE', "result_page"); | |||
| // ----- 行動支付, 繳費機告知已付款 ----- | |||
| define('ALTOB_ATS2PAYED', "http://localhost/carpayment.html/ats2payed"); | |||
| // ----- 行動支付, 繳費機告知已付款 (end) ----- | |||
| // ----- 歐付寶金流 ----- | |||
| define('ALLPAY_PAYMENT_TX_BILL_ATS', SERVER_URL."allpay_payment.html/transfer_money_tx_bill_ats"); // 歐付寶付款系統連結 | |||
| define('ALLPAY_ClientBackURL', APP_URL."client_back/"); // 您要歐付寶返回按鈕導向的瀏覽器端網址"; | |||
| define('ALLPAY_OrderResultURL', APP_URL."order_result/"); // 您要收到付款完成通知的瀏覽器端網址(browser) ps. WebATM大部份銀行都回不來; | |||
| define('ALLPAY_AltobServiceURL', APP_URL."payment_completed_handler/"); // 付款完成後被通知的位址 | |||
| // ----- 歐付寶金流 (end) ----- | |||
| } | |||
| // 發生錯誤時集中在此處理 | |||
| public function error_handler($errno, $errstr, $errfile, $errline, $errcontext) | |||
| { | |||
| // ex: car_err://message.... | |||
| //$log_msg = explode('://', $errstr); | |||
| /* | |||
| if (count($log_msg) > 1) | |||
| { | |||
| $log_file = LOG_PATH.$log_msg[0]; | |||
| $str = date('H:i:s')."|{$log_msg[1]}|{$errfile}|{$errline}|{$errno}\n"; | |||
| } | |||
| else | |||
| { | |||
| $log_file = LOG_PATH.APP_NAME; | |||
| $str = date('H:i:s')."|{$errstr}|{$errfile}|{$errline}|{$errno}\n"; | |||
| } | |||
| */ | |||
| $str = date('H:i:s')."|{$errstr}|{$errfile}|{$errline}|{$errno}\n"; | |||
| //error_log($str, 3, $log_file . '.' . date('Ymd').'.log.txt'); // 3代表參考後面的檔名 | |||
| error_log($str, 3, LOG_PATH.APP_NAME . '.' . date('Ymd').'.log.txt'); // 3代表參考後面的檔名 | |||
| } | |||
| // 顯示靜態網頁(html檔) | |||
| protected function show_page($page_name, $data = null) | |||
| { | |||
| $page_file = PAGE_PATH.$page_name.'.php'; | |||
| $last_modified_time = filemtime($page_file); | |||
| // 若檔案修改時間沒有異動, 或版本無異動, 通知瀏覽器使用cache, 不再下傳網頁 | |||
| header('Cache-Control:max-age='.MAX_AGE); // cache 1個月 | |||
| header('Last-Modified: '.gmdate('D, d M Y H:i:s', $last_modified_time).' GMT'); | |||
| header('Etag: '. APP_VERSION); | |||
| header('Cache-Control: public'); | |||
| if (!empty($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] == APP_VERSION && @strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) == $last_modified_time) | |||
| { | |||
| header('HTTP/1.1 304 Not Modified'); | |||
| } | |||
| else | |||
| { | |||
| $this->load->view(APP_NAME.'/'.$page_name, $data); | |||
| } | |||
| } | |||
| public function index() | |||
| { | |||
| $this->show_page('main_page'); | |||
| } | |||
| // 顯示logs | |||
| public function show_logs() | |||
| { | |||
| $lines = $this->uri->segment(3); // 顯示行數 | |||
| if (empty($lines)) $lines = 40; // 無行數參數, 預設為40行 | |||
| // echo '<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body><pre style="white-space: pre-wrap;">'; | |||
| echo '<html lang="zh-TW"><body><pre style="white-space: pre-wrap;">'; | |||
| passthru('/usr/bin/tail -n ' . $lines . ' ' . LOG_FILE); // 利用linux指令顯示倒數幾行的logs內容 | |||
| echo "\n----- " . LOG_FILE . ' -----'; | |||
| echo '</pre></body></html>'; | |||
| } | |||
| // 付款 - 1.繳月租 | |||
| public function payment_lpr() | |||
| { | |||
| $payment_lpr = $this->input->post('payment_lpr', true); | |||
| $data = $this->payment_ats_model->create_member_bill($payment_lpr); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // 付款 - 2.確定繳費 | |||
| public function transfer_money() | |||
| { | |||
| $order_no = strtoupper($this->uri->segment(3)); // 交易序號 | |||
| $invoice_receiver = urldecode($this->uri->segment(4)); // 載具編號 (可有可無) | |||
| $company_no = urldecode($this->uri->segment(5)); // 公司統編 (可有可無) | |||
| $email_base64 = $this->uri->segment(6); // 電子信箱 | |||
| $mobile = $this->uri->segment(7); // 手機號碼 | |||
| // decode email | |||
| if(strlen($email_base64) > 0){ | |||
| $email = base64_decode($email_base64.'='); // base64字串尾端的'='還原 | |||
| }else{ | |||
| $email = email_base64; | |||
| } | |||
| $this->payment_ats_model-> // 開始進行繳交帳單 | |||
| pay_bill($order_no, $invoice_receiver, $company_no, $email, $mobile, | |||
| ALLPAY_ClientBackURL, | |||
| ALLPAY_OrderResultURL, | |||
| ALLPAY_AltobServiceURL, | |||
| 52); // 交易種類: 0:未定義, 1:現金, 40:博辰人工模組, 41:博辰自動繳費機, 50:歐付寶轉址刷卡, 51:歐付寶APP, 52:歐付寶轉址WebATM, 60:中國信託刷卡轉址 | |||
| // 轉址歐付寶付款系統 | |||
| echo file_get_contents(ALLPAY_PAYMENT_TX_BILL_ATS."/{$order_no}"); | |||
| } | |||
| // L.1 付款完成 (限制存取) | |||
| public function payment_completed_handler() | |||
| { | |||
| $order_no = $this->uri->segment(3); // 交易序號 | |||
| $data = $this->payment_ats_model->get_tx_bill($order_no); | |||
| if (! empty($data)) | |||
| { | |||
| $order_no = $data['order_no']; | |||
| $station_no = $data['station_no']; | |||
| $lpr = $data['lpr']; | |||
| $amt = $data['amt']; | |||
| $status = $data['status']; | |||
| switch($status){ | |||
| case 1: // 狀態: 0:剛建立, 1:結帳完成, 2:錢沒對上, 3:發票沒建立, 4:手動調整, 99:訂單逾期作廢, 100:交易進行中, 111:產品已領取 | |||
| // 開立歐付寶電子發票 | |||
| $this->allpay_invoice_model->invoice_issue_for_tx_bill_ats($order_no, $amt); | |||
| // 記錄為已領取 | |||
| $this->payment_ats_model->transfer_money_done_and_finished($order_no); | |||
| // 繳費機告知已付款 | |||
| // http://localhost/carpayment.html/ats2payed/車牌/金額/場站編號/序號/MD5 | |||
| // md5(車牌.金額.場站編號.序號) | |||
| $md5 = md5($lpr.$amt.$station_no.$order_no); | |||
| file_get_contents(ALTOB_ATS2PAYED."/{$lpr}/{$amt}/{$station_no}/{$order_no}/{$md5}"); | |||
| default: | |||
| // 尚未結帳完成, 或是已領取 | |||
| trigger_error(APP_NAME.', '.__FUNCTION__.', order_no=>' . $order_no.'<br>'.' status != 1'); | |||
| } | |||
| } | |||
| } | |||
| // 歐付寶返回按鈕導向的瀏覽器端網址 | |||
| public function client_back() | |||
| { | |||
| $this->show_page(MAIN_PAGE); | |||
| } | |||
| // 收到付款完成通知的瀏覽器端網址(browser) ps. WebATM大部份銀行都回不來 | |||
| public function order_result() | |||
| { | |||
| $this->show_page(RESULT_PAGE); | |||
| } | |||
| // 車位查詢 | |||
| public function q_pks() | |||
| { | |||
| $lpr = $this->input->post('lpr', true); | |||
| $data = $this->qcar_model->q_pks($lpr); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // 取得進場資訊 (模糊比對) | |||
| public function q_fuzzy_pks() | |||
| { | |||
| $input = $this->input->post('fuzzy_input', true); | |||
| $data = $this->qcar_model->q_fuzzy_pks($input); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| } | |||
| @@ -0,0 +1,104 @@ | |||
| <?php | |||
| /* | |||
| file: Txdata.php 交易資訊系統 | |||
| */ | |||
| if ( ! defined('BASEPATH')) exit('No direct script access allowed'); | |||
| class Txdata extends CI_Controller | |||
| { | |||
| var $vars = array(); // 共用變數 | |||
| function __construct() | |||
| { | |||
| parent::__construct(); | |||
| // ----- 程式開發階段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 | |||
| /* | |||
| // 共用記憶體 | |||
| $this->vars['mcache'] = new Memcache; | |||
| $this->vars['mcache']->connect(MEMCACHE_HOST, MEMCACHE_PORT) or die ('Could not connect memcache'); | |||
| // mqtt subscribe | |||
| $this->vars['mqtt'] = new phpMQTT(MQ_HOST, MQ_PORT, uniqid()); | |||
| if(!$this->vars['mqtt']->connect()){ die ('Could not connect mqtt'); } | |||
| */ | |||
| // ----- 定義常數(路徑, cache秒數) ----- | |||
| define('APP_VERSION', '100'); // 版本號 | |||
| define('MAX_AGE', 604800); // cache秒數, 此定義1個月 | |||
| define('APP_NAME', 'txdata'); // 應用系統名稱 | |||
| define('PAGE_PATH', APP_BASE.'ci_application/views/'.APP_NAME.'/'); // path of views | |||
| define('SERVER_URL', 'http://'.(isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : 'localhost').'/'); // URL | |||
| define('APP_URL', SERVER_URL.APP_NAME.'.html/'); // controller路徑 | |||
| define('WEB_URL', SERVER_URL.APP_NAME.'/'); // 網頁路徑 | |||
| define('WEB_LIB', SERVER_URL.'libs/'); // 網頁lib | |||
| define('BOOTSTRAPS', WEB_LIB.'bootstrap_sb/'); // bootstrap lib | |||
| define('LOG_PATH', FILE_BASE.APP_NAME.'/logs/'); // log path | |||
| $this->load->model('txdata_model'); | |||
| // $this->parkingquery_model->init($this->vars); | |||
| } | |||
| // 發生錯誤時集中在此處理 | |||
| public function error_handler($errno, $errstr, $errfile, $errline, $errcontext) | |||
| { | |||
| $str = date('H:i:s')."|{$errstr}|{$errfile}|{$errline}|{$errno}\n"; | |||
| //error_log($str, 3, $log_file . '.' . date('Ymd').'.log.txt'); // 3代表參考後面的檔名 | |||
| error_log($str, 3, LOG_PATH.APP_NAME . '.' . date('Ymd').'.log.txt'); // 3代表參考後面的檔名 | |||
| } | |||
| // 顯示靜態網頁(html檔) | |||
| protected function show_page($page_name, &$data = null) | |||
| { | |||
| $page_file = PAGE_PATH.$page_name.'.php'; | |||
| $last_modified_time = filemtime($page_file); | |||
| // 若檔案修改時間沒有異動, 或版本無異動, 通知瀏覽器使用cache, 不再下傳網頁 | |||
| // header('Cache-Control:max-age='.MAX_AGE); // cache 1個月 | |||
| header('Last-Modified: '.gmdate('D, d M Y H:i:s', $last_modified_time).' GMT'); | |||
| header('Etag: '. APP_VERSION); | |||
| header('Cache-Control: public'); | |||
| if (!empty($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] == APP_VERSION && @strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) == $last_modified_time) | |||
| { | |||
| header('HTTP/1.1 304 Not Modified'); | |||
| } | |||
| else | |||
| { | |||
| $this->load->view(APP_NAME.'/'.$page_name, $data); | |||
| } | |||
| } | |||
| // 取得場站費率設定 | |||
| // http://203.75.167.89/txdata.html/get_price_plan/12112/0 | |||
| public function get_price_plan() | |||
| { | |||
| $station_no = $this->uri->segment(3); | |||
| $tx_type = $this->uri->segment(4); | |||
| $data = $this->txdata_model->get_price_plan($station_no, $tx_type); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // 取得特殊日期設定 | |||
| // http://203.75.167.89/txdata.html/get_date_plan/12345678/23456789 | |||
| public function get_date_plan() | |||
| { | |||
| $inTime = $this->uri->segment(3); | |||
| $balanceTime = $this->uri->segment(4); | |||
| $data = $this->txdata_model->get_date_plan($inTime, $balanceTime); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| } | |||
| @@ -0,0 +1,353 @@ | |||
| <?php | |||
| /* | |||
| file: vip.php 交通局VIP管理系統 | |||
| */ | |||
| if ( ! defined('BASEPATH')) exit('No direct script access allowed'); | |||
| require_once(MQ_CLASS_FILE); | |||
| session_start(); //we need to call PHP's session object to access it through CI | |||
| class Vip extends CI_Controller | |||
| { | |||
| var $vars = array(); // 共用變數 | |||
| function __construct() | |||
| { | |||
| parent::__construct(); | |||
| // ----- 程式開發階段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 | |||
| /** | |||
| // 共用記憶體 | |||
| $this->vars['mcache'] = new Memcache; | |||
| $this->vars['mcache']->connect(MEMCACHE_HOST, MEMCACHE_POST) or die ('Could not connect memcache'); | |||
| // mqtt subscribe | |||
| $this->vars['mqtt'] = new phpMQTT(MQ_HOST, MQ_POST, 'cario'); | |||
| if(!$this->vars['mqtt']->connect()){ die ('Could not connect mqtt'); } | |||
| **/ | |||
| // ----- 定義常數(路徑, cache秒數) ----- | |||
| define('APP_VERSION', '100'); // 版本號 | |||
| define('MAX_AGE', 604800); // cache秒數, 此定義1個月 | |||
| define('APP_NAME', 'vip'); // 應用系統名稱 | |||
| define('PAGE_PATH', APP_BASE.'ci_application/views/'.APP_NAME.'/'); // path of views | |||
| define('SERVER_URL', 'http://'.(isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : 'localhost').'/'); // URL | |||
| define('APP_URL', SERVER_URL.APP_NAME.'.html/'); // controller路徑 | |||
| define('WEB_URL', SERVER_URL.APP_NAME.'/'); // 網頁路徑 | |||
| define('WEB_LIB', SERVER_URL.'libs/'); // 網頁lib | |||
| define('BOOTSTRAPS', WEB_LIB.'bootstrap_sb/'); // bootstrap lib | |||
| define('LOG_PATH', FILE_BASE.APP_NAME.'/logs/'); // log path | |||
| $this->load->model('vip_model'); | |||
| $this->vip_model->init($this->vars); | |||
| // load library | |||
| $this->load->library(array('form_validation','session')); | |||
| // load helpers | |||
| $this->load->helper(array('form')); | |||
| // ajax code | |||
| define('RESULT_SUCCESS', 'ok'); | |||
| define('RESULT_FORM_VALIDATION_FAIL', '-1'); | |||
| define('RESULE_FAIL', 'gg'); | |||
| } | |||
| // 發生錯誤時集中在此處理 | |||
| public function error_handler($errno, $errstr, $errfile, $errline, $errcontext) | |||
| { | |||
| // ex: car_err://message.... | |||
| //$log_msg = explode('://', $errstr); | |||
| /* | |||
| if (count($log_msg) > 1) | |||
| { | |||
| $log_file = LOG_PATH.$log_msg[0]; | |||
| $str = date('H:i:s')."|{$log_msg[1]}|{$errfile}|{$errline}|{$errno}\n"; | |||
| } | |||
| else | |||
| { | |||
| $log_file = LOG_PATH.APP_NAME; | |||
| $str = date('H:i:s')."|{$errstr}|{$errfile}|{$errline}|{$errno}\n"; | |||
| } | |||
| */ | |||
| $str = date('H:i:s')."|{$errstr}|{$errfile}|{$errline}|{$errno}\n"; | |||
| //error_log($str, 3, $log_file . '.' . date('Ymd').'.log.txt'); // 3代表參考後面的檔名 | |||
| error_log($str, 3, LOG_PATH.APP_NAME . '.' . date('Ymd').'.log.txt'); // 3代表參考後面的檔名 | |||
| } | |||
| // 顯示靜態網頁(html檔) | |||
| protected function show_page($page_name, &$data = null) | |||
| { | |||
| $page_file = PAGE_PATH.$page_name.'.php'; | |||
| $last_modified_time = filemtime($page_file); | |||
| // 若檔案修改時間沒有異動, 或版本無異動, 通知瀏覽器使用cache, 不再下傳網頁 | |||
| // header('Cache-Control:max-age='.MAX_AGE); // cache 1個月 | |||
| header('Last-Modified: '.gmdate('D, d M Y H:i:s', $last_modified_time).' GMT'); | |||
| header('Etag: '. APP_VERSION); | |||
| header('Cache-Control: public'); | |||
| if (!empty($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] == APP_VERSION && @strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) == $last_modified_time) | |||
| { | |||
| header('HTTP/1.1 304 Not Modified'); | |||
| } | |||
| else | |||
| { | |||
| $this->load->view(APP_NAME.'/'.$page_name, $data); | |||
| } | |||
| } | |||
| public function index() | |||
| { | |||
| if($this->session->userdata('logged_in')) | |||
| { | |||
| $session_data = $this->session->userdata('logged_in'); | |||
| $data['username'] = $session_data['username']; | |||
| $data['type'] = $session_data['type']; | |||
| if($data['type'] == 'ma') | |||
| { | |||
| $this->show_page('admin_page', $data); // 進階管理者介面 | |||
| } | |||
| else | |||
| { | |||
| $this->show_page('main_page', $data); // 一般管理者介面 | |||
| } | |||
| } | |||
| else | |||
| { | |||
| //If no session, redirect to login page | |||
| //redirect('login', 'refresh'); | |||
| $this->show_page('login_page'); | |||
| } | |||
| } | |||
| // 登入 | |||
| public function user_login() | |||
| { | |||
| // form_validation | |||
| $this->form_validation->set_rules('login_name', 'login_name', 'trim|required|xss_clean'); | |||
| $this->form_validation->set_rules('pswd', 'pswd', 'trim|required|xss_clean'); | |||
| if($this->form_validation->run() == FALSE) | |||
| { | |||
| return RESULT_FORM_VALIDATION_FAIL; | |||
| } | |||
| // go model | |||
| $data = array | |||
| ( | |||
| 'login_name' => $this->input->post('login_name', true), | |||
| 'pswd' => $this->input->post('pswd', true) | |||
| ); | |||
| $result = $this->vip_model->user_login($data); | |||
| if($result) | |||
| { | |||
| $sess_array = array(); | |||
| foreach($result as $row) | |||
| { | |||
| $sess_array = array | |||
| ( | |||
| 'username' => $row->login_name , | |||
| 'type' => $row->type | |||
| ); | |||
| $this->session->set_userdata('logged_in', $sess_array); | |||
| } | |||
| echo RESULT_SUCCESS; | |||
| } | |||
| else | |||
| { | |||
| return RESULE_FAIL; | |||
| } | |||
| } | |||
| // 登出 | |||
| public function user_logout() | |||
| { | |||
| $this->session->unset_userdata('logged_in'); | |||
| session_destroy(); | |||
| return RESULT_SUCCESS; | |||
| } | |||
| // 新增與修改 | |||
| public function member_add() | |||
| { | |||
| // form_validation (required) | |||
| $this->form_validation->set_rules('member_no', 'member_no', 'trim|required|xss_clean'); | |||
| $this->form_validation->set_rules('station_no', 'station_no', 'trim|required|xss_clean'); | |||
| $this->form_validation->set_rules('lpr', 'lpr', 'trim|required|xss_clean|alpha_numeric'); | |||
| $this->form_validation->set_rules('start_date', 'start_date', 'trim|required|xss_clean'); | |||
| $this->form_validation->set_rules('end_date', 'end_date', 'trim|required|xss_clean'); | |||
| $this->form_validation->set_rules('member_name', 'member_name', 'trim|required|xss_clean'); | |||
| $this->form_validation->set_rules('mobile_no', 'mobile_no', 'trim|required|xss_clean'); | |||
| // form_validation (basic) | |||
| $this->form_validation->set_rules('remarks', 'remarks', 'trim|xss_clean'); | |||
| if($this->form_validation->run() == FALSE) | |||
| { | |||
| return RESULT_FORM_VALIDATION_FAIL; | |||
| } | |||
| // go model | |||
| $data = array | |||
| ( | |||
| 'member_no' => $this->input->post('member_no', true), | |||
| 'station_no' => $this->input->post('station_no', true), | |||
| 'lpr' => strtoupper($this->input->post('lpr', true)), | |||
| 'start_date' => $this->input->post('start_date', true), | |||
| 'end_date' => $this->input->post('end_date', true), | |||
| 'member_name' => $this->input->post('member_name', true), | |||
| 'member_nick_name' => $this->input->post('member_name', true), | |||
| 'mobile_no' => $this->input->post('mobile_no', true), | |||
| 'remarks' => $this->input->post('remarks', true) | |||
| ); | |||
| $this->vip_model->vip_add($data); | |||
| echo RESULT_SUCCESS; | |||
| } | |||
| // 查詢 | |||
| public function member_query() | |||
| { | |||
| $data = $this->vip_model->vip_query(); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // 刪除 | |||
| public function member_delete() | |||
| { | |||
| // form_validation | |||
| $this->form_validation->set_rules('member_no', 'member_no', 'trim|required|xss_clean'); | |||
| if($this->form_validation->run() == FALSE) | |||
| { | |||
| return RESULE_FAIL; | |||
| } | |||
| // go model | |||
| $member_no = $this->input->post('member_no', true); | |||
| $this->vip_model->member_delete($member_no); | |||
| echo RESULT_SUCCESS; | |||
| } | |||
| // 管理者新增與修改 | |||
| public function user_add() | |||
| { | |||
| // 判斷target_name分流insert or update | |||
| $this->form_validation->set_rules('target_name', 'target_name', 'trim|xss_clean'); | |||
| // form_validation (basic) | |||
| $this->form_validation->set_rules('type', 'type', 'trim|required|xss_clean'); | |||
| $this->form_validation->set_rules('user_name', 'user_name', 'trim|xss_clean'); | |||
| $this->form_validation->set_rules('email', 'email', 'trim|xss_clean'); | |||
| $this->form_validation->set_rules('mobile_no', 'mobile_no', 'trim|xss_clean'); | |||
| $this->form_validation->set_rules('tel', 'tel', 'trim|xss_clean'); | |||
| $this->form_validation->set_rules('car_plate', 'car_plate', 'trim|xss_clean'); | |||
| if($this->form_validation->run() == FALSE) | |||
| { | |||
| return RESULT_FORM_VALIDATION_FAIL; | |||
| } | |||
| $target_name = $this->input->post('target_name', true); | |||
| if($target_name == '') | |||
| { | |||
| // insert 流程 | |||
| // form_validation (required) | |||
| $this->form_validation->set_rules('login_name', 'login_name', 'trim|required|xss_clean'); | |||
| $this->form_validation->set_rules('pswd', 'pswd', 'trim|required|xss_clean'); | |||
| if($this->form_validation->run() == FALSE) | |||
| { | |||
| return RESULT_FORM_VALIDATION_FAIL; | |||
| } | |||
| // go model | |||
| $data = array | |||
| ( | |||
| 'type' => $this->input->post('type', true), | |||
| 'login_name' => $this->input->post('login_name', true), | |||
| 'pswd' => MD5($this->input->post('pswd', true)), | |||
| 'user_name' => $this->input->post('user_name', true), | |||
| 'email' => $this->input->post('email', true), | |||
| 'mobile_no' => $this->input->post('mobile_no', true), | |||
| 'tel' => $this->input->post('tel', true), | |||
| 'car_plate' => strtoupper($this->input->post('car_plate', true)) | |||
| ); | |||
| $this->vip_model->user_insert($data); | |||
| echo RESULT_SUCCESS; | |||
| } | |||
| else | |||
| { | |||
| // update 流程 | |||
| // go model | |||
| $data = array | |||
| ( | |||
| 'type' => $this->input->post('type', true), | |||
| 'user_name' => $this->input->post('user_name', true), | |||
| 'email' => $this->input->post('email', true), | |||
| 'mobile_no' => $this->input->post('mobile_no', true), | |||
| 'tel' => $this->input->post('tel', true), | |||
| 'car_plate' => strtoupper($this->input->post('car_plate', true)) | |||
| ); | |||
| $this->vip_model->user_update($data, $target_name); | |||
| echo RESULT_SUCCESS; | |||
| } | |||
| } | |||
| // 管理者查詢 | |||
| public function user_query() | |||
| { | |||
| $data = $this->vip_model->user_query(); | |||
| echo json_encode($data, JSON_UNESCAPED_UNICODE); | |||
| } | |||
| // 管理者刪除 | |||
| public function user_delete() | |||
| { | |||
| // form_validation | |||
| $this->form_validation->set_rules('login_name', 'login_name', 'trim|required|xss_clean'); | |||
| if($this->form_validation->run() == FALSE) | |||
| { | |||
| return RESULE_FAIL; | |||
| } | |||
| // go model | |||
| $login_name = $this->input->post('login_name', true); | |||
| $this->vip_model->user_delete($login_name); | |||
| echo RESULT_SUCCESS; | |||
| } | |||
| } | |||
| @@ -0,0 +1,109 @@ | |||
| <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); | |||
| /* | |||
| file: vip_parked.php VIP車位 | |||
| http://192.168.10.201/vip_parked.html/pages/1 | |||
| 舊版: | |||
| file:///C:/altob/vip/javascript_mqtt/vip_parked.html | |||
| */ | |||
| require_once(MQ_CLASS_FILE); | |||
| class Vip_parked extends CI_Controller | |||
| { | |||
| var $vars = array(); | |||
| function __construct() | |||
| { | |||
| parent::__construct(); | |||
| $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; // 本站編號 | |||
| /* | |||
| // cameras or etagio直接release連線(即斷線), 但繼續處理邏輯 | |||
| $method_name = $this->router->fetch_method(); | |||
| if ($method_name == 'cameras' || $method_name == 'etagio') | |||
| { | |||
| ob_end_clean(); | |||
| ignore_user_abort(); | |||
| ob_start(); | |||
| header('Connection: close'); | |||
| header('Content-Length: ' . ob_get_length()); | |||
| ob_end_flush(); | |||
| flush(); | |||
| } | |||
| */ | |||
| // ----- 程式開發階段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 | |||
| // mqtt subscribe | |||
| $this->vars['mqtt'] = new phpMQTT(MQ_HOST, MQ_PORT, uniqid()); | |||
| if(!$this->vars['mqtt']->connect()){ die ('Could not connect mqtt'); } | |||
| // ----- 定義常數(路徑, cache秒數) ----- | |||
| define('APP_VERSION', '100'); // 版本號 | |||
| define('MAX_AGE', 604800); // cache秒數, 此定義1個月 | |||
| define('APP_NAME', 'vip_parked'); // 應用系統名稱 | |||
| define('PAGE_PATH', APP_BASE.'ci_application/views/'.APP_NAME.'/'); // path of views | |||
| define('SERVER_URL', 'http://'.(isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : 'localhost').'/'); // URL | |||
| define('APP_URL', SERVER_URL.APP_NAME.'.html/'); // controller路徑 | |||
| define('WEB_URL', SERVER_URL.APP_NAME.'/'); // 網頁路徑 | |||
| define('WEB_LIB', SERVER_URL.'/libs/'); // 網頁lib | |||
| define('BOOTSTRAPS', WEB_LIB.'bootstrap_sb/'); // bootstrap lib | |||
| define('LOG_PATH', FILE_BASE.APP_NAME.'/logs/'); // log path name | |||
| define('LOG_FILE', FILE_BASE.APP_NAME.'/logs/cario.'); // log file name | |||
| } | |||
| // 發生錯誤時集中在此處理 | |||
| 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代表參考後面的檔名 | |||
| } | |||
| public function pages() | |||
| { | |||
| $data['vip_no'] = $this->uri->segment(3); // vip no | |||
| $data['mqtt_ip'] = '192.168.51.11'; | |||
| $this->load->view(APP_NAME.'/main_page', $data); | |||
| } | |||
| public function vip_welcome() | |||
| { | |||
| $this->load->view(APP_NAME.'/vip_welcome'); | |||
| } | |||
| public function parked() | |||
| { | |||
| $this->load->view(APP_NAME.'/vip_welcome'); | |||
| } | |||
| } | |||
| @@ -0,0 +1,11 @@ | |||
| <!DOCTYPE html> | |||
| <html> | |||
| <head> | |||
| <title>403 Forbidden</title> | |||
| </head> | |||
| <body> | |||
| <p>Directory access is forbidden.</p> | |||
| </body> | |||
| </html> | |||
| @@ -0,0 +1,250 @@ | |||
| <?php | |||
| require_once '/home/bigbang/libs/Workerman/Autoloader.php'; | |||
| use Workerman\Worker; | |||
| Worker::$logFile = '/dev/null'; // 不記錄log file | |||
| //Worker::$pidFile = '/tmp/run/'.basename(__FILE__).'.pid'; | |||
| //Worker::$logFile = __DIR__ . '/../acer2server.log'; | |||
| // 場站共用設定檔 | |||
| require_once '/home/bigbang/apps/coworker/station.config.php'; | |||
| define('APP_NAME', 'acer'); // application name | |||
| define('WORKERMAN_DEBUG', 1); | |||
| if (WORKERMAN_DEBUG) | |||
| { | |||
| ini_set('display_errors', '1'); | |||
| error_reporting(E_ALL); | |||
| set_error_handler('error_handler', E_ALL); | |||
| } | |||
| /////////////////////////////// | |||
| // | |||
| // 回傳代碼定義 | |||
| // | |||
| /////////////////////////////// | |||
| // 結果代碼 | |||
| define('ALTOB_RESULT_CODE_SUCCESS', 'OK'); // 成功 | |||
| define('ALTOB_RESULT_CODE_FAIL', 'GG'); // 失敗 | |||
| // 錯誤碼 | |||
| define('ALTOB_ERROR_CODE_NONE', '0000'); // 預設值 (成功帶這個) | |||
| define('ALTOB_ERROR_CODE_UNKNOWN_INPUT', '1001'); // 未知的 輸入 | |||
| define('ALTOB_ERROR_CODE_UNKNOWN_CMD', '1002'); // 未知的 CMD | |||
| define('ALTOB_ERROR_CODE_UNDEFINED', '9999'); // 未定義的錯誤 | |||
| define('ALTOB_ERROR_CODE_ACER_RESULT_FAIL', '2001'); // ACER 回傳處理錯誤 | |||
| /////////////////////////////// | |||
| // | |||
| // 主程式 | |||
| // | |||
| /////////////////////////////// | |||
| // 傳送主機資料 | |||
| $ch = curl_init(); | |||
| curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); | |||
| curl_setopt($ch, CURLOPT_POST, true); // 啟用POST | |||
| // 建立一個Worker監聽8033埠,不使用任何應用層協定 | |||
| $tcp_worker = new Worker("tcp://0.0.0.0:8033"); | |||
| // 啟動N個進程對外提供服務 | |||
| $tcp_worker->count = 4; | |||
| $tcp_worker->onConnect = function($connection) | |||
| { | |||
| echo "New Connection\n"; | |||
| }; | |||
| $tcp_worker->onClose = function($connection) | |||
| { | |||
| echo "Connection closed\n"; | |||
| }; | |||
| // 當用戶端發來數據(主程式) | |||
| $tcp_worker->onMessage = function($connection, $tcp_in) | |||
| { | |||
| global $ch; | |||
| $explode_tcp_in = explode(chr(28), $tcp_in); // 0x1C tcp欄位分隔 | |||
| $send_data = null; | |||
| if(empty($explode_tcp_in) || count($explode_tcp_in) != 5) | |||
| { | |||
| trigger_error(".. unknown tcp_in|". print_r($explode_tcp_in, true) .'|'); | |||
| $send_data = gen_error_result(ALTOB_ERROR_CODE_UNKNOWN_INPUT); | |||
| } | |||
| else | |||
| { | |||
| list(, $seq, $cmd, $data, ) = $explode_tcp_in; | |||
| $seq = 1; | |||
| switch($cmd) | |||
| { | |||
| // 票卡入場訊號,供 ALTOB 登記 | |||
| case '001': | |||
| //(傳入:卡號、入場編號、是否月租卡; 回傳:成功、入場編號) | |||
| list($card_no, $cario_no, $card_type) = explode(chr(31), $data); // 0x1F data欄位分隔 | |||
| trigger_error("cmd:{$cmd}, card_no:{$card_no}, cario_no:{$cario_no}, card_type:{$card_type}"); | |||
| // 呼叫 cmd_001 | |||
| $data = array('card_no' => $card_no, 'cario_no' => $cario_no, 'card_type' => $card_type); | |||
| curl_setopt($ch, CURLOPT_URL, 'http://localhost/acer_service.html/cmd_001/'); | |||
| curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data)); | |||
| $jdata = curl_exec($ch); | |||
| $result = json_decode($jdata, true); | |||
| trigger_error("{$cmd}|{$card_no}|{$cario_no}|{$card_type}|result|" . print_r($result, true)); | |||
| $send_data = gen_cario_result($seq, $cmd, | |||
| $result['result_code'], | |||
| $result['result']['cario_no'], | |||
| $result['result']['error_code']); | |||
| break; | |||
| // 票卡離場訊號,供 ALTOB 登記 | |||
| case '002': | |||
| //(傳入:卡號、繳費時間、是否月租卡; 回傳:成功、入場編號) | |||
| list($card_no, $pay_time, $card_type) = explode(chr(31), $data); // 0x1F data欄位分隔 | |||
| trigger_error("cmd:{$cmd}, card_no:{$card_no}, pay_time:{$pay_time}, card_type:{$card_type}"); | |||
| // 呼叫 cmd_002 | |||
| $data = array('card_no' => $card_no, 'pay_time' => $pay_time, 'card_type' => $card_type); | |||
| curl_setopt($ch, CURLOPT_URL, 'http://localhost/acer_service.html/cmd_002/'); | |||
| curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data)); | |||
| $jdata = curl_exec($ch); | |||
| $result = json_decode($jdata, true); | |||
| trigger_error("{$cmd}|{$card_no}|{$pay_time}|{$card_type}|result|" . print_r($result, true)); | |||
| $send_data = gen_cario_result($seq, $cmd, | |||
| $result['result_code'], | |||
| $result['result']['cario_no'], | |||
| $result['result']['error_code']); | |||
| break; | |||
| // 票號離場訊號,回傳若成功觸發 ACER 開門 | |||
| case '003': | |||
| // (傳入:6 碼數字; 回傳:入場編號、成功與否代號) | |||
| list($ticket_no) = explode(chr(31), $data); // 0x1F data欄位分隔 | |||
| trigger_error("cmd:{$cmd}, ticket_no:{$ticket_no}"); | |||
| // 呼叫 cmd_003 | |||
| $data = array('ticket_no' => $ticket_no); | |||
| curl_setopt($ch, CURLOPT_URL, 'http://localhost/acer_service.html/cmd_003/'); | |||
| curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data)); | |||
| $jdata = curl_exec($ch); | |||
| $result = json_decode($jdata, true); | |||
| trigger_error("{$cmd}|{$ticket_no}|result|" . print_r($result, true)); | |||
| $send_data = gen_cario_result($seq, $cmd, | |||
| $result['result_code'], | |||
| $result['result']['cario_no'], | |||
| $result['result']['error_code'], | |||
| $result['result']['msg_code']); | |||
| break; | |||
| default: | |||
| trigger_error(".. unknown cmd | {$seq}, {$cmd}, {$data}|"); | |||
| $send_data = gen_error_result(ALTOB_ERROR_CODE_UNKNOWN_CMD); | |||
| break; | |||
| } | |||
| } | |||
| // 未定義的錯誤 | |||
| if(empty($send_data)) | |||
| { | |||
| $send_data = gen_error_result(ALTOB_ERROR_CODE_UNDEFINED); | |||
| } | |||
| $connection->close($send_data); | |||
| }; | |||
| // 執行worker | |||
| Worker::runAll(); | |||
| // 產生錯誤回傳 | |||
| function gen_error_result($error_code) | |||
| { | |||
| return gen_cario_result(0, 0, ALTOB_RESULT_CODE_FAIL, 0, $error_code); | |||
| } | |||
| // 產生 cario_no 回傳 | |||
| function gen_cario_result($seq, $cmd, $result_code, $cario_no, $error_code, $msg_code=0) | |||
| { | |||
| $send_data = ''; | |||
| $seq_pad = str_pad($seq, 5, '0', STR_PAD_LEFT); // 序號: 5 碼 (左邊補 0) | |||
| $cmd_pad = str_pad($cmd, 3, '0', STR_PAD_LEFT); // 指令: 3 碼 (左邊補 0) | |||
| $cario_no_pad = str_pad($cario_no, 10, '0', STR_PAD_LEFT); // 入場編號: 10 碼 (左邊補 0) | |||
| $error_code_pad = str_pad($error_code, 4, '0', STR_PAD_LEFT); // 錯誤碼: 4 碼 (左邊補 0) | |||
| $msg_code_pad = str_pad($msg_code, 5, '0', STR_PAD_LEFT); // 離場代碼: 5 碼 (左邊補 0) | |||
| trigger_error(__FUNCTION__ . "..{$seq_pad}|{$cmd_pad}|{$cario_no_pad}|{$error_code_pad}|{$msg_code_pad}.."); | |||
| if(empty($msg_code)) | |||
| { | |||
| $packformat = "a2Ca10Ca4"; | |||
| $data = pack($packformat, | |||
| // Data:內容除分隔符號為0x1F,其他全為ASCII碼0x20 ~ 0x7F內 | |||
| $result_code, 0x1f, $cario_no_pad, 0x1f, $error_code_pad | |||
| ); | |||
| $data_len = strlen($data); | |||
| $socket_len = $data_len + 16; | |||
| //trigger_error(".. TEST socket_len | {$socket_len}, {$data_len}|". intval($socket_len / 0x0100). '_'. intval($socket_len % 0x0100)); | |||
| $send_data = pack("Ca2Ca5Ca3C{$packformat}CCC", | |||
| 0x02, // STX:封包起始碼(0x02) | |||
| $socket_len, 0x1c, // 封包長度:從STX到ETX的位元數 | |||
| $seq_pad, 0x1c, // 封包流水號:5碼ASCII數字(不足5碼時左補”0”補滿5碼) | |||
| $cmd_pad, 0x1c, // CmdID:命令ID | |||
| // Data:內容除分隔符號為0x1F,其他全為ASCII碼0x20 ~ 0x7F內 | |||
| $result_code, 0x1f, $cario_no_pad, 0x1f, $error_code_pad, | |||
| 0x1c, | |||
| 0x80, // CRC:封包檢查碼 | |||
| 0x03 // ETX:封包結束碼(0x03) | |||
| ); | |||
| } | |||
| else | |||
| { | |||
| $packformat = "a2Ca10Ca4Ca5"; | |||
| $data = pack($packformat, | |||
| // Data:內容除分隔符號為0x1F,其他全為ASCII碼0x20 ~ 0x7F內 | |||
| $result_code, 0x1f, $cario_no_pad, 0x1f, $error_code_pad, 0x1f, $msg_code_pad | |||
| ); | |||
| $data_len = strlen($data); | |||
| $socket_len = $data_len + 16; | |||
| //trigger_error(".. TEST socket_len | {$socket_len}, {$data_len}|". intval($socket_len / 0x0100). '_'. intval($socket_len % 0x0100)); | |||
| $send_data = pack("Ca2Ca5Ca3C{$packformat}CCC", | |||
| 0x02, // STX:封包起始碼(0x02) | |||
| $socket_len, 0x1c, // 封包長度:從STX到ETX的位元數 | |||
| $seq_pad, 0x1c, // 封包流水號:5碼ASCII數字(不足5碼時左補”0”補滿5碼) | |||
| $cmd_pad, 0x1c, // CmdID:命令ID | |||
| // Data:內容除分隔符號為0x1F,其他全為ASCII碼0x20 ~ 0x7F內 | |||
| $result_code, 0x1f, $cario_no_pad, 0x1f, $error_code_pad, 0x1f, $msg_code_pad, | |||
| 0x1c, | |||
| 0x80, // CRC:封包檢查碼 | |||
| 0x03 // ETX:封包結束碼(0x03) | |||
| ); | |||
| } | |||
| return $send_data; | |||
| } | |||
| // 發生錯誤時集中在此處理 | |||
| 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代表參考後面的檔名 | |||
| } | |||
| @@ -0,0 +1,322 @@ | |||
| <?php | |||
| // 博辰設備對接 | |||
| // php //home/bigbang/apps/coworker/parktron2server.php | |||
| require_once '/home/bigbang/libs/Workerman/Autoloader.php'; | |||
| use Workerman\Worker; | |||
| Worker::$logFile = '/dev/null'; // 不記錄log file | |||
| //Worker::$pidFile = '/tmp/run/'.basename(__FILE__).'.pid'; | |||
| // 傳送主機資料 | |||
| $ch = curl_init(); | |||
| curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); | |||
| curl_setopt($ch, CURLOPT_POST, true); // 啟用POST | |||
| // 建立一個Worker監聽8068埠,不使用任何應用層協定 | |||
| $tcp_worker = new Worker("tcp://0.0.0.0:8068"); | |||
| // 啟動N個進程對外提供服務 | |||
| $tcp_worker->count = 6; | |||
| $tcp_worker->onConnect = function($connection) | |||
| { | |||
| echo "New Connection\n"; | |||
| }; | |||
| $tcp_worker->onClose = function($connection) | |||
| { | |||
| echo "Connection closed\n"; | |||
| }; | |||
| // 當用戶端發來數據(主程式) | |||
| $tcp_worker->onMessage = function($connection, $tcp_in) | |||
| { | |||
| global $ch, $last_lpr; | |||
| // echo 'start time:'.date('Y-m-d H:i:s'); | |||
| list(, $seq, $cmd, $data) = explode(chr(28), $tcp_in); // 0x1C tcp欄位分隔 | |||
| // echo "data_in:[{$seq}|{$cmd}|{$data}|]\n"; | |||
| switch($cmd) | |||
| { | |||
| case '001': // 車輛入場 | |||
| list($devno, $token, $lpr, $in_time, $last_field) = explode(chr(31), $data); // 0x1F data欄位分隔 | |||
| $type = substr($last_field, 0, -2); | |||
| echo "{$devno}|{$token}|{$lpr}|{$in_time}|{$type}|\n"; | |||
| $connection->send('OK'); | |||
| break; | |||
| case '002': // APS詢問車牌入場時間 | |||
| list($token, $lpr, $last_field) = explode(chr(31), $data); // 0x1F data欄位分隔 | |||
| $lpr = str_replace('%', '', $lpr); | |||
| $last_lpr = $lpr; | |||
| $in_time = substr($last_field, 0, -2); | |||
| // echo "cmd_002:[{$token}|{$lpr}|{$in_time}|]/n"; | |||
| $data = array('lpr' => $lpr); | |||
| curl_setopt($ch, CURLOPT_URL, 'http://localhost/carpayment.html/query_in_fuzzy/'); | |||
| curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data)); | |||
| $jdata = curl_exec($ch); | |||
| $results = json_decode($jdata, true); | |||
| $connection->send(tcp_data_fuzzy($results['count'], $results['results'], '001', '002')); | |||
| break; | |||
| case '003': // 繳費完成 | |||
| list($ticket_no, $lpr, $in_time, $pay_time, $last_field) = explode(chr(31), $data); // 0x1F data欄位分隔 | |||
| $pay_type = substr($last_field, 0, -2); | |||
| // echo "{$ticket_no}|{$lpr}|{$in_time}|{$pay_time}|{$pay_type}|/n"; | |||
| $connection->send('OK'); | |||
| //if ($lpr == '*******') {$lpr = $last_lpr; $err_lpr = '***';} | |||
| if ($lpr == '*******') {$err_lpr = '***';} | |||
| else | |||
| { $err_lpr = '+++';} | |||
| // 傳送繳費資料 | |||
| $data = array | |||
| ( | |||
| 'ticket_no' => $ticket_no, // 票卡號碼 | |||
| 'lpr' => $lpr, // 車號 | |||
| 'in_time' => $in_time, // 入場時間 | |||
| 'pay_time' => $pay_time, // 繳款時間 | |||
| 'pay_type' => $pay_type // 繳款方式(0:現金, 1:月票, 2:多卡通) | |||
| ); | |||
| curl_setopt($ch, CURLOPT_URL, 'http://localhost/carpayment.html/p2payed/'); | |||
| curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data)); | |||
| $results = curl_exec($ch); | |||
| file_put_contents('/tmp/aps.log.txt', date('Y-m-d H:i:s').":{$err_lpr}\n".print_r($data, true)."\n\n", FILE_APPEND); | |||
| break; | |||
| } | |||
| // echo 'end_time:'.date('Y-m-d H:i:s'); | |||
| }; | |||
| function tcp_data_fuzzy($records_count, $records, $seq, $cmdid) | |||
| { | |||
| $seq = '00001'; | |||
| $cmdid = '002'; | |||
| $packformat = 'aC'; | |||
| // 0 筆 | |||
| if($records_count == 0) | |||
| { | |||
| $count = 0; | |||
| $data = pack($packformat, | |||
| "{$count}", 0x1f | |||
| ); | |||
| $data_len = strlen($data); | |||
| $socket_len = $data_len + 16; | |||
| $send_data = pack("CCCCa5Ca3C{$packformat}CC", | |||
| 0x02, | |||
| $socket_len / 0x0100, $socket_len % 0x0100, 0x1c, $seq, 0x1c, $cmdid, 0x1c, | |||
| "{$count}", 0x1f, | |||
| 0x80, 0x03); | |||
| return $send_data; | |||
| } | |||
| // 1. create data | |||
| foreach ($records as $idx => $rows) | |||
| { | |||
| $pathlen = strlen($rows['in_pic_name']); | |||
| $packformat = $packformat."A7Ca7CaCa19Ca{$pathlen}Ca19Ca10Ca10Ca5Ca5C"; | |||
| } | |||
| if(count($records) == 1) | |||
| { | |||
| $count = 1; | |||
| $data = pack($packformat, | |||
| "{$count}", 0x1f, | |||
| $records[0]['lpr'], 0x1f, $records[0]['seat_no'], 0x1f, $records[0]['ticket'], 0x1f, $records[0]['in_time'], 0x1f, $records[0]['in_pic_name'], 0x1f, $records[0]['pay_time'], 0x1f, $records[0]['start_date'], 0x1f, $records[0]['end_date'], 0x1f, $records[0]['start_time'], 0x1f, $records[0]['end_time'], 0x1f | |||
| ); | |||
| $data_len = strlen($data); | |||
| $socket_len = $data_len + 16; | |||
| $send_data = pack("CCCCa5Ca3C{$packformat}CC", | |||
| 0x02, | |||
| $socket_len / 0x0100, $socket_len % 0x0100, 0x1c, $seq, 0x1c, $cmdid, 0x1c, | |||
| "{$count}", 0x1f, | |||
| $records[0]['lpr'], 0x1f, $records[0]['seat_no'], 0x1f, $records[0]['ticket'], 0x1f, $records[0]['in_time'], 0x1f, $records[0]['in_pic_name'], 0x1f, $records[0]['pay_time'], 0x1f, $records[0]['start_date'], 0x1f, $records[0]['end_date'], 0x1f, $records[0]['start_time'], 0x1f, $records[0]['end_time'], 0x1f, | |||
| 0x80, 0x03); | |||
| } | |||
| else if(count($records) == 2) | |||
| { | |||
| $count = 2; | |||
| $data = pack($packformat, | |||
| "{$count}", 0x1f, | |||
| $records[0]['lpr'], 0x1f, $records[0]['seat_no'], 0x1f, $records[0]['ticket'], 0x1f, $records[0]['in_time'], 0x1f, $records[0]['in_pic_name'], 0x1f, $records[0]['pay_time'], 0x1f, $records[0]['start_date'], 0x1f, $records[0]['end_date'], 0x1f, $records[0]['start_time'], 0x1f, $records[0]['end_time'], 0x1f, | |||
| $records[1]['lpr'], 0x1f, $records[1]['seat_no'], 0x1f, $records[1]['ticket'], 0x1f, $records[1]['in_time'], 0x1f, $records[1]['in_pic_name'], 0x1f, $records[1]['pay_time'], 0x1f, $records[1]['start_date'], 0x1f, $records[1]['end_date'], 0x1f, $records[1]['start_time'], 0x1f, $records[1]['end_time'], 0x1f | |||
| ); | |||
| $data_len = strlen($data); | |||
| $socket_len = $data_len + 16; | |||
| $send_data = pack("CCCCa5Ca3C{$packformat}CC", | |||
| 0x02, | |||
| $socket_len / 0x0100, $socket_len % 0x0100, 0x1c, $seq, 0x1c, $cmdid, 0x1c, | |||
| "{$count}", 0x1f, | |||
| $records[0]['lpr'], 0x1f, $records[0]['seat_no'], 0x1f, $records[0]['ticket'], 0x1f, $records[0]['in_time'], 0x1f, $records[0]['in_pic_name'], 0x1f, $records[0]['pay_time'], 0x1f, $records[0]['start_date'], 0x1f, $records[0]['end_date'], 0x1f, $records[0]['start_time'], 0x1f, $records[0]['end_time'], 0x1f, | |||
| $records[1]['lpr'], 0x1f, $records[1]['seat_no'], 0x1f, $records[1]['ticket'], 0x1f, $records[1]['in_time'], 0x1f, $records[1]['in_pic_name'], 0x1f, $records[1]['pay_time'], 0x1f, $records[1]['start_date'], 0x1f, $records[1]['end_date'], 0x1f, $records[1]['start_time'], 0x1f, $records[1]['end_time'], 0x1f, | |||
| 0x80, 0x03); | |||
| } | |||
| else if(count($records) == 3) | |||
| { | |||
| $count = 3; | |||
| $data = pack($packformat, | |||
| "{$count}", 0x1f, | |||
| $records[0]['lpr'], 0x1f, $records[0]['seat_no'], 0x1f, $records[0]['ticket'], 0x1f, $records[0]['in_time'], 0x1f, $records[0]['in_pic_name'], 0x1f, $records[0]['pay_time'], 0x1f, $records[0]['start_date'], 0x1f, $records[0]['end_date'], 0x1f, $records[0]['start_time'], 0x1f, $records[0]['end_time'], 0x1f, | |||
| $records[1]['lpr'], 0x1f, $records[1]['seat_no'], 0x1f, $records[1]['ticket'], 0x1f, $records[1]['in_time'], 0x1f, $records[1]['in_pic_name'], 0x1f, $records[1]['pay_time'], 0x1f, $records[1]['start_date'], 0x1f, $records[1]['end_date'], 0x1f, $records[1]['start_time'], 0x1f, $records[1]['end_time'], 0x1f, | |||
| $records[2]['lpr'], 0x1f, $records[2]['seat_no'], 0x1f, $records[2]['ticket'], 0x1f, $records[2]['in_time'], 0x1f, $records[2]['in_pic_name'], 0x1f, $records[2]['pay_time'], 0x1f, $records[2]['start_date'], 0x1f, $records[2]['end_date'], 0x1f, $records[2]['start_time'], 0x1f, $records[2]['end_time'], 0x1f | |||
| ); | |||
| $data_len = strlen($data); | |||
| $socket_len = $data_len + 16; | |||
| $send_data = pack("CCCCa5Ca3C{$packformat}CC", | |||
| 0x02, | |||
| $socket_len / 0x0100, $socket_len % 0x0100, 0x1c, $seq, 0x1c, $cmdid, 0x1c, | |||
| "{$count}", 0x1f, | |||
| $records[0]['lpr'], 0x1f, $records[0]['seat_no'], 0x1f, $records[0]['ticket'], 0x1f, $records[0]['in_time'], 0x1f, $records[0]['in_pic_name'], 0x1f, $records[0]['pay_time'], 0x1f, $records[0]['start_date'], 0x1f, $records[0]['end_date'], 0x1f, $records[0]['start_time'], 0x1f, $records[0]['end_time'], 0x1f, | |||
| $records[1]['lpr'], 0x1f, $records[1]['seat_no'], 0x1f, $records[1]['ticket'], 0x1f, $records[1]['in_time'], 0x1f, $records[1]['in_pic_name'], 0x1f, $records[1]['pay_time'], 0x1f, $records[1]['start_date'], 0x1f, $records[1]['end_date'], 0x1f, $records[1]['start_time'], 0x1f, $records[1]['end_time'], 0x1f, | |||
| $records[2]['lpr'], 0x1f, $records[2]['seat_no'], 0x1f, $records[2]['ticket'], 0x1f, $records[2]['in_time'], 0x1f, $records[2]['in_pic_name'], 0x1f, $records[2]['pay_time'], 0x1f, $records[2]['start_date'], 0x1f, $records[2]['end_date'], 0x1f, $records[2]['start_time'], 0x1f, $records[2]['end_time'], 0x1f, | |||
| 0x80, 0x03); | |||
| } | |||
| else if(count($records) == 4) | |||
| { | |||
| $count = 4; | |||
| $data = pack($packformat, | |||
| "{$count}", 0x1f, | |||
| $records[0]['lpr'], 0x1f, $records[0]['seat_no'], 0x1f, $records[0]['ticket'], 0x1f, $records[0]['in_time'], 0x1f, $records[0]['in_pic_name'], 0x1f, $records[0]['pay_time'], 0x1f, $records[0]['start_date'], 0x1f, $records[0]['end_date'], 0x1f, $records[0]['start_time'], 0x1f, $records[0]['end_time'], 0x1f, | |||
| $records[1]['lpr'], 0x1f, $records[1]['seat_no'], 0x1f, $records[1]['ticket'], 0x1f, $records[1]['in_time'], 0x1f, $records[1]['in_pic_name'], 0x1f, $records[1]['pay_time'], 0x1f, $records[1]['start_date'], 0x1f, $records[1]['end_date'], 0x1f, $records[1]['start_time'], 0x1f, $records[1]['end_time'], 0x1f, | |||
| $records[2]['lpr'], 0x1f, $records[2]['seat_no'], 0x1f, $records[2]['ticket'], 0x1f, $records[2]['in_time'], 0x1f, $records[2]['in_pic_name'], 0x1f, $records[2]['pay_time'], 0x1f, $records[2]['start_date'], 0x1f, $records[2]['end_date'], 0x1f, $records[2]['start_time'], 0x1f, $records[2]['end_time'], 0x1f, | |||
| $records[3]['lpr'], 0x1f, $records[3]['seat_no'], 0x1f, $records[3]['ticket'], 0x1f, $records[3]['in_time'], 0x1f, $records[3]['in_pic_name'], 0x1f, $records[3]['pay_time'], 0x1f, $records[3]['start_date'], 0x1f, $records[3]['end_date'], 0x1f, $records[3]['start_time'], 0x1f, $records[3]['end_time'], 0x1f | |||
| ); | |||
| $data_len = strlen($data); | |||
| $socket_len = $data_len + 16; | |||
| $send_data = pack("CCCCa5Ca3C{$packformat}CC", | |||
| 0x02, | |||
| $socket_len / 0x0100, $socket_len % 0x0100, 0x1c, $seq, 0x1c, $cmdid, 0x1c, | |||
| "{$count}", 0x1f, | |||
| $records[0]['lpr'], 0x1f, $records[0]['seat_no'], 0x1f, $records[0]['ticket'], 0x1f, $records[0]['in_time'], 0x1f, $records[0]['in_pic_name'], 0x1f, $records[0]['pay_time'], 0x1f, $records[0]['start_date'], 0x1f, $records[0]['end_date'], 0x1f, $records[0]['start_time'], 0x1f, $records[0]['end_time'], 0x1f, | |||
| $records[1]['lpr'], 0x1f, $records[1]['seat_no'], 0x1f, $records[1]['ticket'], 0x1f, $records[1]['in_time'], 0x1f, $records[1]['in_pic_name'], 0x1f, $records[1]['pay_time'], 0x1f, $records[1]['start_date'], 0x1f, $records[1]['end_date'], 0x1f, $records[1]['start_time'], 0x1f, $records[1]['end_time'], 0x1f, | |||
| $records[2]['lpr'], 0x1f, $records[2]['seat_no'], 0x1f, $records[2]['ticket'], 0x1f, $records[2]['in_time'], 0x1f, $records[2]['in_pic_name'], 0x1f, $records[2]['pay_time'], 0x1f, $records[2]['start_date'], 0x1f, $records[2]['end_date'], 0x1f, $records[2]['start_time'], 0x1f, $records[2]['end_time'], 0x1f, | |||
| $records[3]['lpr'], 0x1f, $records[3]['seat_no'], 0x1f, $records[3]['ticket'], 0x1f, $records[3]['in_time'], 0x1f, $records[3]['in_pic_name'], 0x1f, $records[3]['pay_time'], 0x1f, $records[3]['start_date'], 0x1f, $records[3]['end_date'], 0x1f, $records[3]['start_time'], 0x1f, $records[3]['end_time'], 0x1f, | |||
| 0x80, 0x03); | |||
| } | |||
| else if(count($records) == 5) | |||
| { | |||
| $count = 5; | |||
| $data = pack($packformat, | |||
| "{$count}", 0x1f, | |||
| $records[0]['lpr'], 0x1f, $records[0]['seat_no'], 0x1f, $records[0]['ticket'], 0x1f, $records[0]['in_time'], 0x1f, $records[0]['in_pic_name'], 0x1f, $records[0]['pay_time'], 0x1f, $records[0]['start_date'], 0x1f, $records[0]['end_date'], 0x1f, $records[0]['start_time'], 0x1f, $records[0]['end_time'], 0x1f, | |||
| $records[1]['lpr'], 0x1f, $records[1]['seat_no'], 0x1f, $records[1]['ticket'], 0x1f, $records[1]['in_time'], 0x1f, $records[1]['in_pic_name'], 0x1f, $records[1]['pay_time'], 0x1f, $records[1]['start_date'], 0x1f, $records[1]['end_date'], 0x1f, $records[1]['start_time'], 0x1f, $records[1]['end_time'], 0x1f, | |||
| $records[2]['lpr'], 0x1f, $records[2]['seat_no'], 0x1f, $records[2]['ticket'], 0x1f, $records[2]['in_time'], 0x1f, $records[2]['in_pic_name'], 0x1f, $records[2]['pay_time'], 0x1f, $records[2]['start_date'], 0x1f, $records[2]['end_date'], 0x1f, $records[2]['start_time'], 0x1f, $records[2]['end_time'], 0x1f, | |||
| $records[3]['lpr'], 0x1f, $records[3]['seat_no'], 0x1f, $records[3]['ticket'], 0x1f, $records[3]['in_time'], 0x1f, $records[3]['in_pic_name'], 0x1f, $records[3]['pay_time'], 0x1f, $records[3]['start_date'], 0x1f, $records[3]['end_date'], 0x1f, $records[3]['start_time'], 0x1f, $records[3]['end_time'], 0x1f, | |||
| $records[4]['lpr'], 0x1f, $records[4]['seat_no'], 0x1f, $records[4]['ticket'], 0x1f, $records[4]['in_time'], 0x1f, $records[4]['in_pic_name'], 0x1f, $records[4]['pay_time'], 0x1f, $records[4]['start_date'], 0x1f, $records[4]['end_date'], 0x1f, $records[4]['start_time'], 0x1f, $records[4]['end_time'], 0x1f | |||
| ); | |||
| $data_len = strlen($data); | |||
| $socket_len = $data_len + 16; | |||
| $send_data = pack("CCCCa5Ca3C{$packformat}CC", | |||
| 0x02, | |||
| $socket_len / 0x0100, $socket_len % 0x0100, 0x1c, $seq, 0x1c, $cmdid, 0x1c, | |||
| "{$count}", 0x1f, | |||
| $records[0]['lpr'], 0x1f, $records[0]['seat_no'], 0x1f, $records[0]['ticket'], 0x1f, $records[0]['in_time'], 0x1f, $records[0]['in_pic_name'], 0x1f, $records[0]['pay_time'], 0x1f, $records[0]['start_date'], 0x1f, $records[0]['end_date'], 0x1f, $records[0]['start_time'], 0x1f, $records[0]['end_time'], 0x1f, | |||
| $records[1]['lpr'], 0x1f, $records[1]['seat_no'], 0x1f, $records[1]['ticket'], 0x1f, $records[1]['in_time'], 0x1f, $records[1]['in_pic_name'], 0x1f, $records[1]['pay_time'], 0x1f, $records[1]['start_date'], 0x1f, $records[1]['end_date'], 0x1f, $records[1]['start_time'], 0x1f, $records[1]['end_time'], 0x1f, | |||
| $records[2]['lpr'], 0x1f, $records[2]['seat_no'], 0x1f, $records[2]['ticket'], 0x1f, $records[2]['in_time'], 0x1f, $records[2]['in_pic_name'], 0x1f, $records[2]['pay_time'], 0x1f, $records[2]['start_date'], 0x1f, $records[2]['end_date'], 0x1f, $records[2]['start_time'], 0x1f, $records[2]['end_time'], 0x1f, | |||
| $records[3]['lpr'], 0x1f, $records[3]['seat_no'], 0x1f, $records[3]['ticket'], 0x1f, $records[3]['in_time'], 0x1f, $records[3]['in_pic_name'], 0x1f, $records[3]['pay_time'], 0x1f, $records[3]['start_date'], 0x1f, $records[3]['end_date'], 0x1f, $records[3]['start_time'], 0x1f, $records[3]['end_time'], 0x1f, | |||
| $records[4]['lpr'], 0x1f, $records[4]['seat_no'], 0x1f, $records[4]['ticket'], 0x1f, $records[4]['in_time'], 0x1f, $records[4]['in_pic_name'], 0x1f, $records[4]['pay_time'], 0x1f, $records[4]['start_date'], 0x1f, $records[4]['end_date'], 0x1f, $records[4]['start_time'], 0x1f, $records[4]['end_time'], 0x1f, | |||
| 0x80, 0x03); | |||
| } | |||
| else if(count($records) == 6) | |||
| { | |||
| $count = 6; | |||
| $data = pack($packformat, | |||
| "{$count}", 0x1f, | |||
| $records[0]['lpr'], 0x1f, $records[0]['seat_no'], 0x1f, $records[0]['ticket'], 0x1f, $records[0]['in_time'], 0x1f, $records[0]['in_pic_name'], 0x1f, $records[0]['pay_time'], 0x1f, $records[0]['start_date'], 0x1f, $records[0]['end_date'], 0x1f, $records[0]['start_time'], 0x1f, $records[0]['end_time'], 0x1f, | |||
| $records[1]['lpr'], 0x1f, $records[1]['seat_no'], 0x1f, $records[1]['ticket'], 0x1f, $records[1]['in_time'], 0x1f, $records[1]['in_pic_name'], 0x1f, $records[1]['pay_time'], 0x1f, $records[1]['start_date'], 0x1f, $records[1]['end_date'], 0x1f, $records[1]['start_time'], 0x1f, $records[1]['end_time'], 0x1f, | |||
| $records[2]['lpr'], 0x1f, $records[2]['seat_no'], 0x1f, $records[2]['ticket'], 0x1f, $records[2]['in_time'], 0x1f, $records[2]['in_pic_name'], 0x1f, $records[2]['pay_time'], 0x1f, $records[2]['start_date'], 0x1f, $records[2]['end_date'], 0x1f, $records[2]['start_time'], 0x1f, $records[2]['end_time'], 0x1f, | |||
| $records[3]['lpr'], 0x1f, $records[3]['seat_no'], 0x1f, $records[3]['ticket'], 0x1f, $records[3]['in_time'], 0x1f, $records[3]['in_pic_name'], 0x1f, $records[3]['pay_time'], 0x1f, $records[3]['start_date'], 0x1f, $records[3]['end_date'], 0x1f, $records[3]['start_time'], 0x1f, $records[3]['end_time'], 0x1f, | |||
| $records[4]['lpr'], 0x1f, $records[4]['seat_no'], 0x1f, $records[4]['ticket'], 0x1f, $records[4]['in_time'], 0x1f, $records[4]['in_pic_name'], 0x1f, $records[4]['pay_time'], 0x1f, $records[4]['start_date'], 0x1f, $records[4]['end_date'], 0x1f, $records[4]['start_time'], 0x1f, $records[4]['end_time'], 0x1f, | |||
| $records[5]['lpr'], 0x1f, $records[5]['seat_no'], 0x1f, $records[5]['ticket'], 0x1f, $records[5]['in_time'], 0x1f, $records[5]['in_pic_name'], 0x1f, $records[5]['pay_time'], 0x1f, $records[5]['start_date'], 0x1f, $records[5]['end_date'], 0x1f, $records[5]['start_time'], 0x1f, $records[5]['end_time'], 0x1f | |||
| ); | |||
| $data_len = strlen($data); | |||
| $socket_len = $data_len + 16; | |||
| $send_data = pack("CCCCa5Ca3C{$packformat}CC", | |||
| 0x02, | |||
| $socket_len / 0x0100, $socket_len % 0x0100, 0x1c, $seq, 0x1c, $cmdid, 0x1c, | |||
| "{$count}", 0x1f, | |||
| $records[0]['lpr'], 0x1f, $records[0]['seat_no'], 0x1f, $records[0]['ticket'], 0x1f, $records[0]['in_time'], 0x1f, $records[0]['in_pic_name'], 0x1f, $records[0]['pay_time'], 0x1f, $records[0]['start_date'], 0x1f, $records[0]['end_date'], 0x1f, $records[0]['start_time'], 0x1f, $records[0]['end_time'], 0x1f, | |||
| $records[1]['lpr'], 0x1f, $records[1]['seat_no'], 0x1f, $records[1]['ticket'], 0x1f, $records[1]['in_time'], 0x1f, $records[1]['in_pic_name'], 0x1f, $records[1]['pay_time'], 0x1f, $records[1]['start_date'], 0x1f, $records[1]['end_date'], 0x1f, $records[1]['start_time'], 0x1f, $records[1]['end_time'], 0x1f, | |||
| $records[2]['lpr'], 0x1f, $records[2]['seat_no'], 0x1f, $records[2]['ticket'], 0x1f, $records[2]['in_time'], 0x1f, $records[2]['in_pic_name'], 0x1f, $records[2]['pay_time'], 0x1f, $records[2]['start_date'], 0x1f, $records[2]['end_date'], 0x1f, $records[2]['start_time'], 0x1f, $records[2]['end_time'], 0x1f, | |||
| $records[3]['lpr'], 0x1f, $records[3]['seat_no'], 0x1f, $records[3]['ticket'], 0x1f, $records[3]['in_time'], 0x1f, $records[3]['in_pic_name'], 0x1f, $records[3]['pay_time'], 0x1f, $records[3]['start_date'], 0x1f, $records[3]['end_date'], 0x1f, $records[3]['start_time'], 0x1f, $records[3]['end_time'], 0x1f, | |||
| $records[4]['lpr'], 0x1f, $records[4]['seat_no'], 0x1f, $records[4]['ticket'], 0x1f, $records[4]['in_time'], 0x1f, $records[4]['in_pic_name'], 0x1f, $records[4]['pay_time'], 0x1f, $records[4]['start_date'], 0x1f, $records[4]['end_date'], 0x1f, $records[4]['start_time'], 0x1f, $records[4]['end_time'], 0x1f, | |||
| $records[5]['lpr'], 0x1f, $records[5]['seat_no'], 0x1f, $records[5]['ticket'], 0x1f, $records[5]['in_time'], 0x1f, $records[5]['in_pic_name'], 0x1f, $records[5]['pay_time'], 0x1f, $records[5]['start_date'], 0x1f, $records[5]['end_date'], 0x1f, $records[5]['start_time'], 0x1f, $records[5]['end_time'], 0x1f, | |||
| 0x80, 0x03); | |||
| } | |||
| return $send_data; | |||
| } | |||
| function tcp_data($arr, $seq, $cmdid) | |||
| { | |||
| $crc = pack('C', 'X'); // 起始值 | |||
| $seq = '00001'; | |||
| $cmdid = '002'; | |||
| $pathlen = strlen($arr['pic_name']); | |||
| $packformat = "aCA7Ca7CaCa19Ca{$pathlen}Ca19Ca10Ca10Ca5Ca5C"; | |||
| // $packformat = "aCA7Ca7CaCa19Ca71Ca19Ca10Ca10Ca5Ca5C"; | |||
| $data = pack($packformat, | |||
| $arr['nth'], 0x1f, | |||
| $arr['lpr'], 0x1f, | |||
| $arr['seat_no'], 0x1f, | |||
| $arr['ticket'], 0x1f, | |||
| $arr['start_time'], 0x1f, | |||
| $arr['pic_name'], 0x1f, | |||
| $arr['pay_time'], 0x1f, | |||
| $arr['ticket_start_date'], 0x1f, | |||
| $arr['ticket_end_date'], 0x1f, | |||
| $arr['ticket_start_time'], 0x1f, | |||
| $arr['ticket_end_time'], 0x1f); | |||
| $data_len = strlen($data); | |||
| $socket_len = $data_len + 16; | |||
| // echo "len data[{$data_len}] socket[{$socket_len}] data[{$data}]"; | |||
| $send_data = pack("CCCCa5Ca3C{$packformat}CC", | |||
| 0x02, | |||
| $socket_len / 0x0100, $socket_len % 0x0100, 0x1c, $seq, 0x1c, $cmdid, 0x1c, | |||
| $arr['nth'], 0x1f, | |||
| $arr['lpr'], 0x1f, | |||
| $arr['seat_no'], 0x1f, | |||
| $arr['ticket'], 0x1f, | |||
| $arr['start_time'], 0x1f, | |||
| $arr['pic_name'], 0x1f, | |||
| $arr['pay_time'], 0x1f, | |||
| $arr['ticket_start_date'], 0x1f, | |||
| $arr['ticket_end_date'], 0x1f, | |||
| $arr['ticket_start_time'], 0x1f, | |||
| $arr['ticket_end_time'], 0x1f, | |||
| 0x80, 0x03); | |||
| // echo 'len:[' . $socket_len. '] send_data:['. $send_data .']'; | |||
| // file_put_contents('/tmp/aps.log.txt', date('Y-m-d H:i:s')."\n".$send_data ."\n\n", FILE_APPEND); | |||
| return $send_data; | |||
| } | |||
| // 執行worker | |||
| Worker::runAll(); | |||
| @@ -0,0 +1,15 @@ | |||
| <?php | |||
| /* | |||
| file: station.config.php 資料庫設定帳密設定 | |||
| */ | |||
| define('MEMCACHE_HOST', 'localhost'); // memcache host | |||
| define('MEMCACHE_PORT', 11211); // memcache post no (default:11211) | |||
| define('LOG_PATH', '/home/data/logs/'); | |||
| $dbs['host'] = 'localhost'; | |||
| $dbs['dbname'] = 'master_db'; | |||
| $dbs['user_name'] = 'altob'; | |||
| $dbs['password'] = '0227057716'; | |||
| $dbs['dsn'] = "mysql:host={$dbs['host']};dbname={$dbs['dbname']};charset=utf8"; | |||
| @@ -0,0 +1,439 @@ | |||
| <?php | |||
| /* | |||
| ----- | |||
| file: station_services.php 場站應用系統服務程式 | |||
| workerman執行: | |||
| /usr/bin/php /home/bigbang/apps/coworker/station_services.php start -d | |||
| workerman停止 | |||
| /usr/bin/php /home/bigbang/apps/coworker/station_services.php stop | |||
| ----- | |||
| */ | |||
| require_once '/home/bigbang/libs/Workerman/Autoloader.php'; | |||
| use Workerman\Worker; | |||
| Worker::$logFile = '/dev/null'; // 不記錄log file | |||
| //Worker::$pidFile = '/home/bigbang/libs/Workerman/' .basename(__FILE__).'.pid'; | |||
| // 場站共用設定檔 | |||
| require_once '/home/bigbang/apps/coworker/station.config.php'; | |||
| define('APP_NAME', 'stations'); // application name | |||
| // 序號檔路徑 | |||
| define('SEQNO_PATH', '/home/data/seqno/'); | |||
| define('WORKERMAN_DEBUG', 1); | |||
| if (WORKERMAN_DEBUG) | |||
| { | |||
| ini_set('display_errors', '1'); | |||
| error_reporting(E_ALL); | |||
| set_error_handler('error_handler', E_ALL); | |||
| } | |||
| // 每月最後一日 | |||
| $last_date_month = array | |||
| ( | |||
| 1 => 31, | |||
| 2 => 28, | |||
| 3 => 31, | |||
| 4 => 30, | |||
| 5 => 31, | |||
| 6 => 30, | |||
| 7 => 31, | |||
| 8 => 31, | |||
| 9 => 30, | |||
| 10 => 31, | |||
| 11 => 30, | |||
| 12 => 31 | |||
| ); | |||
| $xvars = array(); // 共用變數 | |||
| // 共用記憶體 | |||
| $mem = new Memcache; | |||
| if (! $mem->pconnect(MEMCACHE_HOST, MEMCACHE_PORT)) | |||
| { | |||
| echo 'Could not connect memcache'; | |||
| Worker::stopAll(); | |||
| } | |||
| // 連接總管理處資料庫 | |||
| $pdo = new PDO($dbs['dsn'], $dbs['user_name'], $dbs['password']); | |||
| // 讀取info場站共用資訊 | |||
| $sql_info = 'select station_no, station_name, station_full_name, company_no, station_ip, hq_url, origin_url, period_name, park_time,member_attr_list, period_list from info where seqno = 1'; | |||
| $info_arr = $pdo->query($sql_info)->fetch(PDO::FETCH_ASSOC); | |||
| // global variable | |||
| $pdo = null; | |||
| $query_syncs = null; | |||
| $query_sync2hq_ok = null; | |||
| // 未同步者批次同步至總管理處 | |||
| $sql_syncs = 'select st_sync_no, station_no, act, hq_tname, st_tname, st_seqno, sync_data from syncs where synced = 0 and st_sync_no = ?'; | |||
| // $query_syncs = $pdo->prepare($sql_syncs); | |||
| // 同步成功 | |||
| $sql_sync2hq_ok = 'update syncs set synced = 1, hq_sync_no = ? where st_sync_no = ?'; | |||
| // $query_sync2hq_ok = $pdo->prepare($sql_sync2hq_ok); | |||
| // 預設curl參數 | |||
| $curl_ch = curl_init(); | |||
| $curl_options = array | |||
| ( | |||
| CURLOPT_URL => $info_arr['hq_url'], | |||
| CURLOPT_HEADER => 0, | |||
| CURLOPT_RETURNTRANSFER => 1, // 返回值不顯示, 只做變數用 | |||
| CURLOPT_POST => 1, | |||
| CURLOPT_CONNECTTIMEOUT => 5, | |||
| CURLOPT_TIMEOUT => 5 | |||
| ); | |||
| init_station_xvars(); | |||
| // 建立一個Worker監聽60133埠,不使用任何應用層協定 | |||
| $worker = new Worker("http://0.0.0.0:60133"); | |||
| // 啟動N個進程對外提供服務 | |||
| $worker->count = 4; | |||
| // ----- program start ----- | |||
| // 當用戶端發來數據(主程式) | |||
| $worker->onMessage = function($connection, $msg_in) | |||
| { | |||
| global $dbs, $pdo, $sql_syncs, $sql_sync2hq_ok, $query_syncs, $query_sync2hq_ok; | |||
| // 無連線或status != Localhost via UNIX socket, 重連線之 | |||
| if (empty($pdo) || preg_match('/socket$/', $pdo->getAttribute(PDO::ATTR_CONNECTION_STATUS)) != 1 ) | |||
| { | |||
| $pdo = new PDO($dbs['dsn'], $dbs['user_name'], $dbs['password'], array(PDO::ATTR_PERSISTENT => true)); | |||
| $query_syncs = $pdo->prepare($sql_syncs); | |||
| $query_sync2hq_ok = $pdo->prepare($sql_sync2hq_ok); | |||
| trigger_error('new pdo'); | |||
| } | |||
| if (!empty($_REQUEST['cmd'])) | |||
| { | |||
| trigger_error('worker.onMessage: ' . print_r($_REQUEST, true)); | |||
| $funcs = @$_REQUEST['cmd']; | |||
| $funcs($connection); | |||
| } | |||
| }; | |||
| // 執行worker | |||
| Worker::runAll(); | |||
| // ----- end of program ----- | |||
| // 同步化, 場站 -> 總管理處 , 參數: | |||
| // http://hq_ip:60133/?cmd=st_syncs&station_no=12110&act=U&tname=members&key=member_no&kval=12110101&jdata=json_str&ck=str32 | |||
| function st_syncs($connection) | |||
| { | |||
| global $pdo_hq, $query_hq_sync; | |||
| // 暫不驗證 | |||
| $syncs_sql = parms2sql($_REQUEST); | |||
| // exec:傳回筆數, query:傳回資料 | |||
| $rows_affected = $pdo_hq->exec($syncs_sql); | |||
| // 如果新增資料, 回傳insert ID | |||
| if ($_REQUEST['act'] == 'A') $rows_affected = $pdo_hq->lastInsertId(); | |||
| @$connection->send($rows_affected); // 回應當前序號或筆數 | |||
| $confirms = $rows_affected > 0 ? 1 : 0; | |||
| $query_hq_sync->execute(array($_REQUEST['station_no'], $_REQUEST['act'], $_REQUEST['tname'], $_REQUEST['data'], $confirms)); | |||
| } | |||
| // 讀取序號 | |||
| // http://localhost:60133/?cmd=seqno&seqname=members&init_no=1025 | |||
| function seqno($connection) | |||
| { | |||
| $seqno_fname = SEQNO_PATH . "{$_REQUEST['seqname']}.txt"; | |||
| $fp = fopen($seqno_fname, 'r+'); | |||
| // lock, 讀入序號, 加1寫回, close | |||
| if ($fp) | |||
| { | |||
| flock($fp, LOCK_EX); | |||
| $seqno = fread($fp, 80); | |||
| $next_no = $seqno + 1; | |||
| rewind($fp); | |||
| fwrite($fp, $next_no); | |||
| flock($fp, LOCK_UN); | |||
| fclose($fp); | |||
| } | |||
| else // 如無此序號檔, 新建之, 並傳回初始值 | |||
| { | |||
| $seqno = empty($_REQUEST['init_no']) ? 1 : $_REQUEST['init_no']; | |||
| $next_no = $seqno + 1; | |||
| file_put_contents($seqno_fname, $next_no, FILE_APPEND); | |||
| } | |||
| @$connection->send($seqno); // 回應當前序號 | |||
| } | |||
| // 檢查是否有連線 ? | |||
| function check_connect($connection) | |||
| { | |||
| $connected = @fsockopen($_REQUEST['ip'], $_REQUEST['port'], $errno, $errstr, $_REQUEST['timeout']); | |||
| if ($connected) | |||
| { | |||
| fclose($connected); | |||
| $is_connected = 1; //action when connected | |||
| } | |||
| else | |||
| { | |||
| $is_connected = 0; //action in connection failure | |||
| } | |||
| return $is_connected; | |||
| } | |||
| // 取得下一租期期最後一日 | |||
| function last_date_next($connection) | |||
| { | |||
| @cross_header(); | |||
| @$connection->send(last_date_next_period($_REQUEST['last_date_curr'], $_REQUEST['fee_period'])); // 參數:本期截止日,繳期 | |||
| } | |||
| // 取得下一租期期最後一日, 參數: 本期截止日, 繳期 | |||
| function last_date_next_period($last_date_curr, $fee_period) | |||
| { | |||
| global $last_date_month; | |||
| $arr = explode('-', $last_date_curr); | |||
| $yy = (int) $arr[0]; // 取年份 | |||
| $mm = (int) $arr[1]; // 取月份 | |||
| $mm += $fee_period; | |||
| if ($mm > 12) // 超過12月, 年度+1, 折算明年度月份 | |||
| { | |||
| ++$yy; | |||
| $mm -= 12; | |||
| } | |||
| $dd = $mm == 2 && ($yy % 4) == 0 ? 29 : $last_date_month[$mm]; | |||
| if ($mm < 10) $mm = "0{$mm}"; // 個位數前面補0 | |||
| return "{$yy}-{$mm}-{$dd}"; | |||
| } | |||
| // web跨網域header設定 | |||
| function cross_header() | |||
| { | |||
| global $info_arr; | |||
| \Workerman\Protocols\Http::header('Access-Control-Allow-Origin: ' . "{$info_arr['origin_url']}"); | |||
| \Workerman\Protocols\Http::header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS'); | |||
| \Workerman\Protocols\Http::header('Access-Control-Allow-Headers: X-Requested-With, Content-Type, Accept'); | |||
| } | |||
| // 將參數轉成sql命令字串 | |||
| function parms2sql($parms) | |||
| { | |||
| $act = $parms['act']; | |||
| switch($act) | |||
| { | |||
| case 'U': // 更新場站資料庫 ???? | |||
| $sql = "update {$parms['tname']} set {$parms['data']} where {$parms['key']} = '{$parms['kval']}';"; | |||
| break; | |||
| case 'A': // 新增資料 | |||
| $fields_str = implode(',', array_keys($data)); | |||
| $values_str = "'".implode("',", array_values($data))."'"; | |||
| $sql = "insert into {$parms['tname']} ({$fields_str}) values({$values_str});"; | |||
| break; | |||
| case 'D': // 刪除資料 | |||
| $sql = "delete {$parms['tname']} where {$parms['key']} = '{$parms['kval']}';"; | |||
| break; | |||
| } | |||
| } | |||
| // 場站初始化參數 | |||
| function init_station_xvars() | |||
| { | |||
| global $mem, $info_arr, $xvars; | |||
| $data = array | |||
| ( | |||
| 'cmd' => 'init_station', | |||
| 'station_no' => $info_arr['station_no'], | |||
| 'park_time' => $info_arr['park_time'] | |||
| ); | |||
| $jdata = worker_tx($data); | |||
| if(empty($jdata)) | |||
| { | |||
| trigger_error('中控已斷線, 建立預設值..'.print_r($jdata, true)); | |||
| // 中控已斷線, 建立預設值 | |||
| $xvars = array(); | |||
| $xvars['info']['period_name'] = array(1 => "月繳", 2 => "雙月繳", 3 => "季繳", 6 => "雙季繳", 12 => "四季繳"); | |||
| $xvars['info']['member_attr'] = array(1 => "一般", 2 => "里民", 3 => "身障", 4 => "員工", 5 => "里長", 250 => "VIP"); | |||
| $xvars['pt'] = | |||
| array( | |||
| 'RE' => array( | |||
| 'seqno' => 1000, | |||
| 'timex' => array( | |||
| '0' => array('type' => 1, 'w_start' => 0, 'w_end' => 6, 'time_start' => '00:00:00', 'time_end' => '23:59:59') | |||
| ), | |||
| 'remarks' => '全天全時段' | |||
| ), | |||
| 'NF' => array( | |||
| 'seqno' => 1010, | |||
| 'timex' => array( | |||
| '0' => array('type' => 1, 'w_start' => 1, 'w_end' => 5, 'time_start' => '18:00:00', 'time_end' => '23:59:59'), | |||
| '1' => array('type' => 1, 'w_start' => 1, 'w_end' => 5, 'time_start' => '00:00:00', 'time_end' => '07:59:59') | |||
| ), | |||
| 'remarks' => '週一至週五: 00:00:00 - 07:59:59 <br/>週一至週五: 18:00:00 - 23:59:59' | |||
| ), | |||
| 'WK66' => array( | |||
| 'seqno' => 1026, | |||
| 'timex' => array( | |||
| '0' => array('type' => 1, 'w_start' => 1, 'w_end' => 5, 'time_start' => '06:00:00', 'time_end' => '17:59:59') | |||
| ), | |||
| 'remarks' => '週一至週五: 06:00:00 - 17:59:59' | |||
| ), | |||
| 'WK' => array( | |||
| 'seqno' => 1020, | |||
| 'timex' => array( | |||
| '0' => array('type' => 1, 'w_start' => 1, 'w_end' => 5, 'time_start' => '07:30:00', 'time_end' => '18:29:59') | |||
| ), | |||
| 'remarks' => '週一至週五: 07:30:00 - 18:29:59' | |||
| ), | |||
| 'HO' => array( | |||
| 'seqno' => 1030, | |||
| 'timex' => array( | |||
| '0' => array('type' => 1, 'w_start' => 6, 'w_end' => 6, 'time_start' => '00:00:00', 'time_end' => '23:59:59'), | |||
| '1' => array('type' => 1, 'w_start' => 0, 'w_end' => 0, 'time_start' => '00:00:00', 'time_end' => '23:59:59') | |||
| ), | |||
| 'remarks' => '週六日全時段' | |||
| ) | |||
| ); | |||
| } | |||
| else | |||
| { | |||
| $xvars = json_decode($jdata, true); | |||
| // 篩選繳期名稱 | |||
| $arr = array(); | |||
| $arr_list = explode(',', $info_arr['period_list']); | |||
| foreach($arr_list as $idx) $arr[$idx] = $xvars['info']['period_name'][$idx]; | |||
| $xvars['info']['period_name'] = $arr; | |||
| // 篩選會員身份 | |||
| $arr = array(); | |||
| $arr_list = explode(',', $info_arr['member_attr_list']); | |||
| foreach($arr_list as $idx) $arr[$idx] = $xvars['info']['member_attr'][$idx]; | |||
| $xvars['info']['member_attr'] = $arr; | |||
| } | |||
| $mem->set('st_info', $info_arr); | |||
| $mem->set('info', $xvars['info']); | |||
| $mem->set('pt', $xvars['pt']); | |||
| trigger_error('st_info: '.print_r($info_arr, true)); | |||
| trigger_error('xvars: '.print_r($xvars, true)); | |||
| } | |||
| // 顯示場站初始化參數 | |||
| function show_all_vars($connection) | |||
| { | |||
| global $info_arr, $xvars; | |||
| $connection->send(json_encode($xvars, JSON_UNESCAPED_UNICODE)); | |||
| } | |||
| // 場站初始化參數 | |||
| function get_var($connection) | |||
| { | |||
| global $xvars; | |||
| $str = gettype($xvars[$_REQUEST['var']]) == 'array' ? json_encode($xvars[$_REQUEST['var']], JSON_UNESCAPED_UNICODE) : $xvars[$_REQUEST['var']]; | |||
| $connection->send($str); | |||
| } | |||
| // 顯示場站初始化參數 | |||
| function set_var($connection) | |||
| { | |||
| global $xvars; | |||
| $xvars[$_REQUEST['var']] = $_REQUEST['val']; | |||
| $connection->send('1'); | |||
| } | |||
| // 批次同步資料表至總管理處 | |||
| function sync_batch($connection) | |||
| { | |||
| global $query_syncs, $query_sync2hq_ok; | |||
| //trigger_error(__FUNCTION__ . '..start..'); | |||
| $connection->close(); // 先斷線再繼續處理 | |||
| foreach(explode(',', $_REQUEST['sync_seqnos']) as $st_sync_no) | |||
| { | |||
| if(empty($st_sync_no)) continue; | |||
| $query_syncs->execute(array($st_sync_no)); | |||
| $rows_syncs = $query_syncs->fetch(PDO::FETCH_ASSOC); | |||
| $tx = $rows_syncs; | |||
| if(empty($tx)) continue; | |||
| $tx['cmd'] = 'sync_st2hq'; // 場站同步至總管理處 | |||
| $hq_sync_no = worker_tx($tx); | |||
| //trigger_error(__FUNCTION__ . '| 1. st_sync_no: ' . $st_sync_no . ', 2. rows_syncs: ' . $rows_syncs . ', 3. hq_sync_no: ' . $hq_sync_no); | |||
| // 同步成功, 記錄之 ( note: 總管理處的 hq_sync 記錄完成就視為完成,各場站 sync.synced = 1 ) | |||
| if ($hq_sync_no > 0) | |||
| { | |||
| $query_sync2hq_ok->execute(array($hq_sync_no, $st_sync_no)); | |||
| } | |||
| else | |||
| { | |||
| trigger_error('sync err:'.json_encode($tx, JSON_UNESCAPED_UNICODE)); // TODO: sync 失敗的處理方式 | |||
| } | |||
| } | |||
| //trigger_error(__FUNCTION__ . '..end..'); | |||
| } | |||
| // 月租金額計算 | |||
| function calculate_rents_amt($connection) | |||
| { | |||
| $_REQUEST['rents_amt1'] = 100; | |||
| $_REQUEST['rents_amt2'] = 200; | |||
| cross_header(); | |||
| $connection->send(json_encode($_REQUEST, JSON_UNESCAPED_UNICODE)); | |||
| } | |||
| // worker connect至總管理處 | |||
| function worker_tx($data) | |||
| { | |||
| global $curl_ch, $curl_options; | |||
| $curl_options[CURLOPT_POSTFIELDS] = $data; | |||
| trigger_error('curl:'. print_r($curl_options, true)); | |||
| curl_setopt_array($curl_ch, $curl_options); | |||
| return(curl_exec($curl_ch)); | |||
| } | |||
| // 發生錯誤時集中在此處理 | |||
| 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代表參考後面的檔名 | |||
| } | |||
| @@ -0,0 +1,38 @@ | |||
| <?php | |||
| /* | |||
| file: call_sync_daily.php 每日自動呼叫 | |||
| */ | |||
| // 場站共用設定檔 | |||
| require_once '/home/bigbang/apps/coworker/station.config.php'; | |||
| define('APP_NAME', 'sync_hq_daily'); // application name | |||
| // 發生錯誤時集中在此處理 | |||
| 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代表參考後面的檔名 | |||
| } | |||
| set_error_handler('error_handler', E_ALL); | |||
| trigger_error('..start..'); | |||
| try | |||
| { | |||
| $ch = curl_init(); | |||
| curl_setopt($ch, CURLOPT_URL, "http://localhost/admins_station.html/do_sync_batch_100"); | |||
| curl_setopt($ch, CURLOPT_HEADER, FALSE); | |||
| curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); | |||
| curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); | |||
| curl_setopt($ch, CURLOPT_POST, FALSE); | |||
| $output = curl_exec($ch); | |||
| curl_close($ch); | |||
| } | |||
| catch(Exception $e) | |||
| { | |||
| trigger_error('ERROR: ' . $e->getMessage()); | |||
| } | |||
| trigger_error('..completed..'); | |||
| @@ -0,0 +1,38 @@ | |||
| <?php | |||
| /* | |||
| file: sync minutely 自動呼叫 | |||
| */ | |||
| // 場站共用設定檔 | |||
| require_once '/home/bigbang/apps/coworker/station.config.php'; | |||
| define('APP_NAME', 'sync_minutely'); // application name | |||
| // 發生錯誤時集中在此處理 | |||
| 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代表參考後面的檔名 | |||
| } | |||
| set_error_handler('error_handler', E_ALL); | |||
| trigger_error('..start..'); | |||
| try | |||
| { | |||
| $ch = curl_init(); | |||
| curl_setopt($ch, CURLOPT_URL, "http://localhost/carpark.html/sync_minutely"); | |||
| curl_setopt($ch, CURLOPT_HEADER, FALSE); | |||
| curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); | |||
| curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); | |||
| curl_setopt($ch, CURLOPT_POST, FALSE); | |||
| $output = curl_exec($ch); | |||
| curl_close($ch); | |||
| } | |||
| catch(Exception $e) | |||
| { | |||
| trigger_error('ERROR: ' . $e->getMessage()); | |||
| } | |||
| trigger_error('..completed..'); | |||
| @@ -0,0 +1,342 @@ | |||
| <?php | |||
| /* | |||
| file: acer_servicemodel.php | |||
| */ | |||
| class Acer_service_model extends CI_Model | |||
| { | |||
| var $vars = array(); | |||
| var $now_str; | |||
| function __construct() | |||
| { | |||
| parent::__construct(); | |||
| $this->load->database(); | |||
| $this->now_str = date('Y-m-d H:i:s'); | |||
| // ACER 連線設定 (測試環境) | |||
| //define('ACER_SERVICE_IP', '220.130.199.142'); | |||
| //define('ACER_SERVICE_PORT', 60833); | |||
| // ACER 連線設定 (測試環境 - 現場呼叫) | |||
| //define('ACER_SERVICE_IP', '220.130.199.142'); | |||
| //define('ACER_SERVICE_PORT', 8033); | |||
| // ACER 連線設定 (正式環境 - 現場呼叫) | |||
| define('ACER_SERVICE_IP', '192.168.10.221'); | |||
| define('ACER_SERVICE_PORT', 8033); | |||
| // 結果代碼 | |||
| define('ALTOB_RESULT_CODE_SUCCESS', 'OK'); // 成功 | |||
| define('ALTOB_RESULT_CODE_FAIL', 'GG'); // 失敗 | |||
| // 錯誤碼 | |||
| define('ALTOB_ERROR_CODE_NONE', '0000'); // 預設值 (成功帶這個) | |||
| define('ALTOB_ERROR_CODE_UNKNOWN_INPUT', '1001'); // 未知的 輸入 | |||
| define('ALTOB_ERROR_CODE_UNKNOWN_CMD', '1002'); // 未知的 CMD | |||
| define('ALTOB_ERROR_CODE_NOT_FOUND', '1003'); // 查無記錄 | |||
| define('ALTOB_ERROR_CODE_ERROR', '1004'); // 交易失敗 | |||
| define('ALTOB_ERROR_CODE_UNDEFINED', '9999'); // 未定義的錯誤 | |||
| define('ALTOB_ERROR_CODE_ACER_RESULT_FAIL', '2001'); // ACER 回傳處理錯誤 | |||
| } | |||
| // acer socket | |||
| function acer_socket($in) | |||
| { | |||
| trigger_error(__FUNCTION__ . "..socket input|{$in}"); | |||
| $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, ACER_SERVICE_IP, ACER_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 登記 | |||
| //(傳入:卡號、入場編號、是否月租卡; 回傳:結果代碼、入場編號、錯誤碼) | |||
| public function cmd_001($card_no, $cario_no, $card_type) | |||
| { | |||
| // 票號查詢最近一筆入場資料 | |||
| $rows_cario = $this->db | |||
| ->select('cario_no, lpr, in_time, pay_time, out_before_time') | |||
| ->from('cario') | |||
| ->where(array( | |||
| 'in_out' => 'CI', 'err' => 0, 'finished' => 0, | |||
| 'cario_no' => $cario_no, | |||
| 'in_time > DATE_SUB(CURRENT_TIMESTAMP, INTERVAL 1 DAY)' => null)) | |||
| ->limit(1) | |||
| ->get() | |||
| ->row_array(); | |||
| trigger_error(__FUNCTION__ . '..cario..' . print_r($rows_cario, true)); | |||
| $cario_no = 0; // 進出碼 | |||
| $error_code = ALTOB_ERROR_CODE_NONE; // 錯誤碼 | |||
| if (!empty($rows_cario['cario_no'])) | |||
| { | |||
| $cario_no = $rows_cario['cario_no']; | |||
| // 更新入場資訊 | |||
| $this->db->where(array('cario_no' => $cario_no))->update('cario', array('remarks' => "{$card_no}")); | |||
| if (!$this->db->affected_rows()) | |||
| { | |||
| trigger_error(__FUNCTION__ . '..fail..' . $this->db->last_query()); | |||
| $error_code = ALTOB_ERROR_CODE_ERROR; | |||
| } | |||
| } | |||
| else | |||
| { | |||
| // 查無入場記錄 | |||
| $error_code = ALTOB_ERROR_CODE_NOT_FOUND; | |||
| } | |||
| $data = array(); | |||
| $data['result_code'] = ALTOB_RESULT_CODE_SUCCESS; | |||
| $data['result']['cario_no'] = $cario_no; | |||
| $data['result']['error_code'] = $error_code; | |||
| return $data; | |||
| } | |||
| // 票卡離場訊號,供 ALTOB 登記 | |||
| //(傳入:卡號、繳費時間、是否月租卡; 回傳:結果代碼、入場編號、錯誤碼) | |||
| public function cmd_002($card_no, $pay_time, $card_type) | |||
| { | |||
| // 卡號查詢最近一筆入場資料 | |||
| $rows_cario = $this->db | |||
| ->select('cario_no, lpr, in_time, pay_time, out_before_time') | |||
| ->from('cario') | |||
| ->where(array( | |||
| 'in_out' => 'CI', 'err' => 0, 'finished' => 0, | |||
| 'remarks' => $card_no, | |||
| 'in_time > DATE_SUB(CURRENT_TIMESTAMP, INTERVAL 5 DAY)' => null)) | |||
| ->order_by('cario_no', 'desc') | |||
| ->limit(1) | |||
| ->get() | |||
| ->row_array(); | |||
| trigger_error(__FUNCTION__ . '..cario..' . print_r($rows_cario, true)); | |||
| $cario_no = 0; // 進出碼 | |||
| $error_code = ALTOB_ERROR_CODE_NONE; // 錯誤碼 | |||
| if (!empty($rows_cario['cario_no'])) | |||
| { | |||
| $cario_no = $rows_cario['cario_no']; | |||
| // 暫不處理 | |||
| } | |||
| else | |||
| { | |||
| // 查無入場記錄 | |||
| $error_code = ALTOB_ERROR_CODE_NOT_FOUND; | |||
| } | |||
| $data = array(); | |||
| $data['result_code'] = ALTOB_RESULT_CODE_SUCCESS; | |||
| $data['result']['cario_no'] = $cario_no; | |||
| $data['result']['error_code'] = $error_code; | |||
| return $data; | |||
| } | |||
| // 票號離場訊號,回傳若成功觸發 ACER 開門 | |||
| // (傳入:6 碼數字; 回傳:結果代碼、入場編號、錯誤碼、離場代碼) | |||
| public function cmd_003($ticket_no) | |||
| { | |||
| // 票號查詢最近一筆入場資料 (只能查 5天 內) | |||
| $rows_cario = $this->db | |||
| ->select('cario_no, payed, in_time, pay_time, out_before_time') | |||
| ->from('cario') | |||
| ->where(array( | |||
| 'ticket_no' => $ticket_no, 'err' => 0, | |||
| 'in_time > DATE_SUB(CURRENT_TIMESTAMP, INTERVAL 5 DAY)' => null) | |||
| ) | |||
| ->order_by('cario_no', 'desc') | |||
| ->limit(1) | |||
| ->get() | |||
| ->row_array(); | |||
| trigger_error(__FUNCTION__ . '..cario..' . print_r($rows_cario, true)); | |||
| $cario_no = 0; // 進出碼 | |||
| $error_code = ALTOB_ERROR_CODE_NONE; // 錯誤碼 | |||
| $msg_code = 0; // 離場碼 | |||
| if (!empty($rows_cario['cario_no'])) | |||
| { | |||
| $cario_no = $rows_cario['cario_no']; | |||
| if(strtotime($rows_cario['out_before_time']) >= time()) | |||
| { | |||
| if ($rows_cario['payed']) | |||
| { | |||
| // CO.B.1 臨停車已付款 | |||
| $msg_code = 6; | |||
| } | |||
| else | |||
| { | |||
| // CO.B.2 臨停車未付款 | |||
| $msg_code = 8; | |||
| } | |||
| } | |||
| else | |||
| { | |||
| // CO.C.1 其它付款方式 | |||
| $msg_code = 9; | |||
| } | |||
| } | |||
| else | |||
| { | |||
| // CO.Z.Z 無入場資料 | |||
| $cario_no = 0; | |||
| $msg_code = 13; | |||
| } | |||
| $data = array(); | |||
| $data['result_code'] = ALTOB_RESULT_CODE_SUCCESS; | |||
| $data['result']['cario_no'] = $cario_no; | |||
| $data['result']['error_code'] = $error_code; | |||
| $data['result']['msg_code'] = $msg_code; | |||
| return $data; | |||
| } | |||
| // 呼叫 acer (cmd: 101) | |||
| // (傳入:入場編號、進場時間、 6 碼數字、車牌號碼、出入口編號; 回傳:結果代碼、入場編號、錯誤碼) | |||
| public function cmd_101($cario_no, $in_time, $ticket_no, $lpr, $ivs_no) | |||
| { | |||
| $seq = '00001'; | |||
| $cmd = '101'; | |||
| $cario_no_pad = str_pad($cario_no, 10, '0', STR_PAD_LEFT); // 入場編號: 10 碼 (左邊補 0) | |||
| $lpr_pad = str_pad($lpr, 10, '*', STR_PAD_LEFT); // 車牌號碼: 10 碼 (左邊補 *) | |||
| $ivs_no_pad = str_pad($ivs_no, 2, '0', STR_PAD_LEFT); // 車道編號: 2 碼 (左邊補 0) | |||
| // 建立封包 | |||
| $packformat = "a10Ca19Ca6Ca10Ca2"; | |||
| $data = pack($packformat, | |||
| // Data:內容除分隔符號為0x1F,其他全為ASCII碼0x20 ~ 0x7F內 | |||
| $cario_no_pad, 0x1f, $in_time, 0x1f, $ticket_no, 0x1f, $lpr_pad, 0x1f, $ivs_no_pad | |||
| ); | |||
| $data_len = strlen($data); | |||
| $socket_len = $data_len + 16; | |||
| $in = pack("Ca2Ca5Ca3C{$packformat}CCC", | |||
| 0x02, // STX:封包起始碼(0x02) | |||
| $socket_len, 0x1c, // 封包長度:從STX到ETX的位元數 | |||
| $seq, 0x1c, // 封包流水號:5碼ASCII數字(不足5碼時左補”0”補滿5碼) | |||
| $cmd, 0x1c, // CmdID:命令ID | |||
| // Data:內容除分隔符號為0x1F,其他全為ASCII碼0x20 ~ 0x7F內 | |||
| $cario_no_pad, 0x1f, $in_time, 0x1f, $ticket_no, 0x1f, $lpr_pad, 0x1f, $ivs_no_pad, | |||
| 0x1c, | |||
| 0x80, // CRC:封包檢查碼 | |||
| 0x03 // ETX:封包結束碼(0x03) | |||
| ); | |||
| // 連線 | |||
| $out = $this->acer_socket($in); | |||
| if(!empty($out)) | |||
| { | |||
| list($front, $seq, $cmd, $data) = explode(chr(28), $out); | |||
| list($result_code, $cario_no, $error_code) = explode(chr(31), $data); | |||
| trigger_error(__FUNCTION__ . "..socket return explode|{$front}, {$seq}, {$cmd}, {$result_code}, {$cario_no}, {$error_code}"); | |||
| if(!empty($result_code) && ALTOB_RESULT_CODE_SUCCESS == $result_code) | |||
| { | |||
| $data = array(); | |||
| $data['result_code'] = ALTOB_RESULT_CODE_SUCCESS; | |||
| $data['result']['cario_no'] = $cario_no; | |||
| return $data; | |||
| } | |||
| } | |||
| $data = array(); | |||
| $data['result_code'] = ALTOB_RESULT_CODE_FAIL; | |||
| $data['result']['error_code'] = ALTOB_ERROR_CODE_ACER_RESULT_FAIL; | |||
| return $data; | |||
| } | |||
| // 呼叫 acer (cmd: 102) | |||
| // (傳入:入場編號、出入口編號、離場代碼; 回傳:結果代碼、入場編號、錯誤碼) | |||
| public function cmd_102($cario_no, $ivs_no, $msg_code) | |||
| { | |||
| $seq = '00001'; | |||
| $cmd = '102'; | |||
| $cario_no_pad = str_pad($cario_no, 10, '0', STR_PAD_LEFT); // 入場編號: 10 碼 (左邊補 0) | |||
| $ivs_no_pad = str_pad($ivs_no, 2, '0', STR_PAD_LEFT); // 車道編號: 2 碼 (左邊補 0) | |||
| $msg_code_pad = str_pad($msg_code, 5, '0', STR_PAD_LEFT); // 離場代碼: 5 碼 (左邊補 0) | |||
| // 建立封包 | |||
| $packformat = "a10Ca2Ca5"; | |||
| $data = pack($packformat, | |||
| // Data:內容除分隔符號為0x1F,其他全為ASCII碼0x20 ~ 0x7F內 | |||
| $cario_no_pad, 0x1f, $ivs_no_pad, 0x1f, $msg_code_pad | |||
| ); | |||
| $data_len = strlen($data); | |||
| $socket_len = $data_len + 16; | |||
| $in = pack("Ca2Ca5Ca3C{$packformat}CCC", | |||
| 0x02, // STX:封包起始碼(0x02) | |||
| $socket_len, 0x1c, // 封包長度:從STX到ETX的位元數 | |||
| $seq, 0x1c, // 封包流水號:5碼ASCII數字(不足5碼時左補”0”補滿5碼) | |||
| $cmd, 0x1c, // CmdID:命令ID | |||
| // Data:內容除分隔符號為0x1F,其他全為ASCII碼0x20 ~ 0x7F內 | |||
| $cario_no_pad, 0x1f, $ivs_no_pad, 0x1f, $msg_code_pad, | |||
| 0x1c, | |||
| 0x80, // CRC:封包檢查碼 | |||
| 0x03 // ETX:封包結束碼(0x03) | |||
| ); | |||
| // 連線 | |||
| $out = $this->acer_socket($in); | |||
| if(!empty($out)) | |||
| { | |||
| list($front, $seq, $cmd, $data) = explode(chr(28), $out); | |||
| list($result_code, $cario_no, $error_code) = explode(chr(31), $data); | |||
| trigger_error(__FUNCTION__ . "..socket return explode|{$front}, {$seq}, {$cmd}, {$result_code}, {$cario_no}, {$error_code}"); | |||
| if(!empty($result_code) && ALTOB_RESULT_CODE_SUCCESS == $result_code) | |||
| { | |||
| $data = array(); | |||
| $data['result_code'] = ALTOB_RESULT_CODE_SUCCESS; | |||
| $data['result']['cario_no'] = $cario_no; | |||
| return $data; | |||
| } | |||
| } | |||
| $data = array(); | |||
| $data['result_code'] = ALTOB_RESULT_CODE_FAIL; | |||
| $data['result']['error_code'] = ALTOB_ERROR_CODE_ACER_RESULT_FAIL; | |||
| return $data; | |||
| } | |||
| } | |||
| @@ -0,0 +1,896 @@ | |||
| <?php | |||
| /* | |||
| file: Admins_model.php | |||
| */ | |||
| class Admins_model extends CI_Model | |||
| { | |||
| var $vars = array(); | |||
| function __construct() | |||
| { | |||
| parent::__construct(); | |||
| $this->load->database(); | |||
| $this->now_str = date('Y-m-d H:i:s'); | |||
| $this->default_valid_time = date('Y-m-d H:i:s', strtotime("{$this->now_str} + 2 days")); // 2016/12/15 新增有效期限 (預設為兩天) | |||
| } | |||
| public function init($vars) | |||
| { | |||
| $this->vars = $vars; | |||
| } | |||
| // 付款 | |||
| public function login_verify($login_name, $login_pswd) | |||
| { | |||
| $rows = $this->db->select('count(*) as ok') | |||
| ->from('staffs') | |||
| ->where(array('login_name' => $login_name, 'pswd' => md5($login_pswd))) | |||
| ->get() | |||
| ->row_array(); | |||
| return $rows['ok']; | |||
| } | |||
| // 讀出各初始值至web | |||
| public function get_init_vars() | |||
| { | |||
| $st_info = $this->vars['mcache']->get('st_info'); | |||
| // 路徑初始值 | |||
| $str = "var APP_URL = '". APP_URL . "';\n". | |||
| "var WEB_LIB = '" . WEB_LIB . "';\n". | |||
| "var BOOTSTRAPS = '" . BOOTSTRAPS . "';\n". | |||
| "var WEB_SERVICE = '" . WEB_SERVICE . "';\n". | |||
| "var station_no ={$st_info['station_no']};\n". | |||
| "var company_no = {$st_info['company_no']};\n". | |||
| "var xvars = new Array();\n". | |||
| "xvars['ck'] = 'NOLOGIN';\n"; | |||
| // 讀出場站資訊 | |||
| $str .= "var st = new Array();\n"; | |||
| $str .= "st[" . STATION_NO . "]=\"" . STATION_NAME . "\";\n"; | |||
| /* | |||
| $results = $this->db->select('station_no, short_name') | |||
| ->from('stations') | |||
| ->order_by('station_no', 'asc') | |||
| ->get() | |||
| ->result_array(); | |||
| $str .= "var st = new Array();\n"; | |||
| foreach($results as $rows) | |||
| { | |||
| $str .= "st[{$rows['station_no']}]=\"{$rows['short_name']}\";\n"; | |||
| } | |||
| */ | |||
| // 讀出時段表資訊 | |||
| $str .= "var pt = new Array();\n"; // park_time | |||
| foreach($this->vars['mcache']->get('pt') as $key => $rows) | |||
| { | |||
| $str .= "pt['{$key}']={'seqno':{$rows['seqno']},'remarks':'{$rows['remarks']}'};\n"; | |||
| } | |||
| /* | |||
| // 讀取繳期名稱 | |||
| $rows = $this->db->select('period_name') | |||
| ->from('info') | |||
| ->where('seqno', 1) | |||
| ->get() | |||
| ->row_array(); | |||
| $str .= "var period_name=Array();\nperiod_name={$rows['period_name']};\n"; | |||
| */ | |||
| // 篩選會員身份及繳期資訊 | |||
| $info = $this->vars['mcache']->get('info'); | |||
| $str .= "var period_name=Array();\n"; | |||
| foreach($info['period_name'] as $idx => $rows) | |||
| { | |||
| $str .= "period_name[{$idx}]=\"{$rows}\";\n"; | |||
| } | |||
| $str .= "var mem_attr = new Array();\n"; | |||
| foreach($info['member_attr'] as $idx => $rows) | |||
| { | |||
| $str .= "mem_attr[{$idx}]=\"{$rows}\";\n"; | |||
| } | |||
| return $str; | |||
| } | |||
| /* | |||
| // 停車時段資訊 | |||
| public function park_time() | |||
| { | |||
| $data = array(); | |||
| $idx = 0; | |||
| // $results = $this->db->select('time_id, seqno, park_type, week_start, week_end, daytime_start, daytime_end, remarks') | |||
| $results = $this->db->select('time_id, seqno, timex, remarks') | |||
| ->from('park_time') | |||
| ->order_by('seqno', 'asc') | |||
| ->get() | |||
| ->result_array(); | |||
| foreach($results as $rows) | |||
| { | |||
| $data[$idx] = array | |||
| ( | |||
| 'time_id' => $rows['time_id'], | |||
| 'seqno' => $rows['time_id'], | |||
| 'remarks' => $rows['remarks'] | |||
| ); | |||
| ++$idx; | |||
| } | |||
| return $results; | |||
| } | |||
| // 停車時段資訊單筆刪除 | |||
| public function park_time_delete($time_id) | |||
| { | |||
| $this->db->delete('park_time', array('time_id' => $time_id)); | |||
| return true; | |||
| } | |||
| */ | |||
| // 會員清單 | |||
| public function member_query_all() | |||
| { | |||
| $sql = " | |||
| SELECT | |||
| MIN(CONCAT(member_tx.tx_no, member_tx.verify_state)) as tx_order, | |||
| members.member_no, | |||
| members.lpr, | |||
| members.etag, | |||
| members.member_name, | |||
| members.mobile_no, | |||
| members.start_date, | |||
| members.end_date, | |||
| members.fee_period, | |||
| members.member_attr, | |||
| members.suspended, | |||
| members.contract_no, | |||
| members.amt, | |||
| member_tx.tx_no, | |||
| member_tx.verify_state, | |||
| member_tx.valid_time, | |||
| member_tx.remarks | |||
| FROM member_tx | |||
| LEFT JOIN members ON member_tx.member_no = members.member_no | |||
| WHERE | |||
| members.member_no IS NOT NULL | |||
| GROUP BY member_tx.member_no | |||
| ORDER BY members.lpr ASC | |||
| "; | |||
| $results = $this->db->query($sql)->result_array(); | |||
| return $results; | |||
| } | |||
| // 待審核清單 | |||
| public function member_tx_check() | |||
| { | |||
| $sql = " | |||
| SELECT | |||
| members.lpr as current_lpr, | |||
| member_tx.lpr, | |||
| member_tx.tx_no, | |||
| member_tx.station_no, | |||
| member_tx.member_no, | |||
| member_tx.fee_period, | |||
| member_tx.fee_period_last, | |||
| member_tx.amt1, | |||
| member_tx.amt, | |||
| member_tx.amt_last, | |||
| member_tx.deposit, | |||
| date_format(member_tx.start_date,'%Y-%m-%d') as start_date, | |||
| date_format(member_tx.end_date,'%Y-%m-%d') as end_date, | |||
| date_format(member_tx.start_date_last,'%Y-%m-%d') as start_date_last, | |||
| date_format(member_tx.end_date_last,'%Y-%m-%d') as end_date_last, | |||
| member_tx.member_company_no, | |||
| member_tx.company_no, | |||
| member_tx.acc_date, | |||
| member_tx.invoice_no, | |||
| member_tx.invoice_amt, | |||
| member_tx.invoice_track, | |||
| member_tx.invoice_time, | |||
| member_tx.invoice_type, | |||
| member_tx.verify_state, | |||
| member_tx.valid_time, | |||
| member_tx.remarks | |||
| FROM member_tx | |||
| LEFT JOIN members ON (member_tx.member_no = members.member_no AND members.station_no = member_tx.station_no) | |||
| WHERE member_tx.verify_state != 1 | |||
| ORDER BY member_tx.valid_time ASC | |||
| "; | |||
| $results = $this->db->query($sql)->result_array(); | |||
| return $results; | |||
| } | |||
| // 會員查詢 | |||
| public function member_query($station_no, $q_item, $q_str) | |||
| { | |||
| $where_station = $station_no == 0 ? '' : " station_no = {$station_no} and "; // 如為0, 則全部塲站讀取 | |||
| switch($q_item) | |||
| { | |||
| case 'end_date': | |||
| $items = "{$q_item} <="; | |||
| $q_str .= ' 23:59:59'; | |||
| break; | |||
| case 'lpr': | |||
| $items = "{$q_item} like "; | |||
| $q_str = strtoupper($q_str).'%'; | |||
| break; | |||
| default: | |||
| $items = "{$q_item} like "; | |||
| $q_str .= '%'; | |||
| break; | |||
| } | |||
| $sql = "select | |||
| station_no, | |||
| member_no, | |||
| lpr, | |||
| member_name, | |||
| mobile_no, | |||
| date_format(demonth_start_date,'%Y-%m-%d') as demonth_start_date, | |||
| date_format(demonth_end_date,'%Y-%m-%d') as demonth_end_date, | |||
| date_format(start_date,'%Y-%m-%d') as start_date, | |||
| date_format(end_date,'%Y-%m-%d') as end_date, | |||
| date_format(rent_start_date,'%Y-%m-%d') as rent_start_date, | |||
| contract_no, | |||
| coalesce(etag, '') as etag, | |||
| fee_period1, | |||
| fee_period, | |||
| amt1, | |||
| amt, | |||
| if(member_company_no > 0, member_company_no, '') as member_company_no, | |||
| if(company_no > 0, company_no, '') as company_no, | |||
| coalesce(member_attr, 1) as member_attr, | |||
| deposit, | |||
| park_time, | |||
| coalesce(member_id, '') as member_id, | |||
| coalesce(tel_o, '') as tel_o, | |||
| coalesce(tel_h, '') as tel_h, | |||
| coalesce(addr, '') as addr, | |||
| suspended | |||
| from members | |||
| where {$where_station} {$items} '{$q_str}'"; | |||
| $results = $this->db->query($sql)->result_array(); | |||
| return $results; | |||
| } | |||
| // 交易查詢 | |||
| public function member_tx_query($station_no, $member_no) | |||
| { | |||
| $sql = "select | |||
| tx_no, station_no, | |||
| member_no, | |||
| lpr, | |||
| fee_period, | |||
| fee_period_last, | |||
| amt1, | |||
| amt, | |||
| amt_last, | |||
| deposit, | |||
| date_format(start_date,'%Y-%m-%d') as start_date, | |||
| date_format(end_date,'%Y-%m-%d') as end_date, | |||
| date_format(start_date_last,'%Y-%m-%d') as start_date_last, | |||
| date_format(end_date_last,'%Y-%m-%d') as end_date_last, | |||
| member_company_no, | |||
| company_no, | |||
| acc_date, | |||
| invoice_no, | |||
| invoice_amt, | |||
| invoice_track, | |||
| invoice_time, | |||
| invoice_type, | |||
| verify_state, | |||
| valid_time, | |||
| remarks | |||
| from member_tx | |||
| where station_no = {$station_no} and member_no = {$member_no} | |||
| order by tx_no desc"; | |||
| $results = $this->db->query($sql)->result_array(); | |||
| return $results; | |||
| } | |||
| // 審核完成 | |||
| public function member_tx_confirmed($parms) | |||
| { | |||
| $this->try_sync_batch($parms['station_no']); // 同步未同步記錄 | |||
| $altob_admin_submit = $this->input->post('altob_admin_submit', true); // 取得 admin 參數 | |||
| if($altob_admin_submit !== $this->gen_admin_ck($parms['station_no'])) | |||
| { | |||
| trigger_error(__FUNCTION__ . '..altob_admin_submit error..' . print_r($parms, true)); | |||
| return 'admin_error'; // 中斷 | |||
| } | |||
| $data_tx = array('verify_state' => $parms['verify_state'], 'valid_time' => $parms['valid_time'], 'remarks' => $parms['remarks']); | |||
| // [A.開始] | |||
| $this->db->trans_start(); | |||
| $this->db->update('member_tx', $data_tx, array('station_no' => $parms['station_no'], 'tx_no' => $parms['tx_no'])); // t1. 更新 member_tx.verify_state, member_tx.valid_time, member_tx.remarks | |||
| // [B.建立同步檔] | |||
| $sync_seqnos = $this->prepare_sync2hq('U', $parms['station_no'], 'member_tx', $parms['tx_no'], $data_tx); // t2. 準備同步檔 (member_tx) | |||
| // [C.完成] | |||
| $this->db->trans_complete(); | |||
| if ($this->db->trans_status() === FALSE) | |||
| { | |||
| trigger_error(__FUNCTION__ . '|'.print_r($data_tx, true) . '..trans_error..'); | |||
| return 'fail'; // 中斷 | |||
| } | |||
| $this->worker_tx('sync_batch', array('sync_seqnos' => $sync_seqnos)); | |||
| return 'ok'; | |||
| } | |||
| // 刪除月租會員 | |||
| public function member_delete($station_no, $member_no) | |||
| { | |||
| $this->try_sync_batch($station_no); // 同步未同步記錄 | |||
| // [A.開始] | |||
| $this->db->trans_start(); | |||
| $this->db->delete('members', array('station_no' => $station_no, 'member_no' => $member_no, 'suspended' => 0)); // t1. 刪除 members | |||
| $this->db->delete('member_car', array('station_no' => $station_no, 'member_no' => $member_no)); // t2. 刪除 member_car | |||
| // [B.建立同步檔] | |||
| $sync_seqnos = $this->prepare_sync2hq('D', $station_no, 'members', $member_no, array()); // t3. 準備同步檔 (members) | |||
| // [C.完成] | |||
| $this->db->trans_complete(); | |||
| if ($this->db->trans_status() === FALSE) | |||
| { | |||
| trigger_error(__FUNCTION__ . ": {$station_no}, {$member_no}, trans_error.."); | |||
| return 'trans_error'; | |||
| } | |||
| // 同步至總管理處 | |||
| $this->worker_tx('sync_batch', array('sync_seqnos' => $sync_seqnos)); | |||
| return 'ok'; | |||
| } | |||
| // 月租會員加入 | |||
| public function member_add($data) | |||
| { | |||
| $data['lpr'] = preg_replace('/\s+/', '', $data['lpr']); // 移除空白 | |||
| $check_member_no = $data['member_no']; | |||
| $station_no = $data['station_no']; | |||
| $tx_no = 0; | |||
| $this->try_sync_batch($station_no); // 同步未同步記錄 | |||
| // 會員車輛基本資料檔 | |||
| $start_date = (empty($data['demonth_start_date']) ? $data['start_date'] : $data['demonth_start_date']); | |||
| $data['rent_start_date'] = $data['start_date']; | |||
| $data['rent_end_date'] = $data['end_date']; | |||
| $data['start_date'] = "{$start_date} 00:00:00"; | |||
| $data['end_date'] = "{$data['end_date']} 23:59:59"; | |||
| $old_lpr = $data['old_lpr']; | |||
| unset($data['old_lpr']); | |||
| $data_car = array | |||
| ( | |||
| 'lpr' => $data['lpr'], | |||
| 'lpr_correct' => $data['lpr'], | |||
| 'etag' => $data['etag'], | |||
| 'station_no' => $station_no, | |||
| 'start_time' => $data['start_date'], | |||
| 'end_time' => $data['end_date'] | |||
| ); | |||
| if ($check_member_no == 0) // 新增一筆會員資料 | |||
| { | |||
| unset($data['member_no']); | |||
| $data['payed_date'] = substr($this->now_str, 0, 10); | |||
| $data['login_id'] = $data['lpr']; | |||
| $data['passwd'] = $data['lpr']; | |||
| $action_code = 'A'; | |||
| // [A.開始] | |||
| $this->db->trans_start(); | |||
| $this->db->insert('members', $data); // t1 新增 members | |||
| $members_insert_id = $this->db->insert_id(); | |||
| $data_car['member_no'] = $members_insert_id; // t2. 新增 member_car | |||
| $this->db->insert('member_car', $data_car); | |||
| $data['member_no'] = $members_insert_id; | |||
| $data_bill = array( | |||
| 'member_no' => $members_insert_id, // 會員編號 | |||
| 'station_no' => $station_no, // 場站編號 | |||
| 'lpr' => $data['lpr'], // 車牌號碼 | |||
| 'amt_accrued' => $data['amt_accrued'], // 應收租金 | |||
| 'amt_tot' => $data['amt_tot'], // 實收租金 | |||
| 'deposit' => $data['deposit'], // 押金 | |||
| 'amt' => $data['amt'], // 本期租金 | |||
| 'fee_period' => $data['fee_period'], // 本期繳期 | |||
| 'start_date' => $data['rent_start_date'], // 本期開始日 | |||
| 'end_date' => $data['rent_end_date'], // 本期結束日 | |||
| 'amt1' => $data['amt1'], // 首期租金 | |||
| 'amt_last' => $data['amt1'], // 上期租金 | |||
| 'fee_period_last' => $data['fee_period1'], // 上期繳期 | |||
| 'start_date_last' => $data['demonth_start_date'], // 上期開始日 | |||
| 'end_date_last' => $data['demonth_end_date'] // 上期結束日 | |||
| ); | |||
| $this->db->insert('member_bill', $data_bill); // t3 新增 member_bill | |||
| $bill_no = $this->db->insert_id(); // 帳單序號 | |||
| $data_tx = array( | |||
| 'bill_no' => $bill_no, // 帳單序號 | |||
| 'member_no' => $members_insert_id, // 會員編號 | |||
| 'station_no' => $station_no, // 場站編號 | |||
| 'sync_no' => 0, // 預設同步編號 | |||
| 'lpr' => $data['lpr'], // 車牌號碼 | |||
| 'amt_accrued' => $data['amt_accrued'], // 應收租金 | |||
| 'amt_tot' => $data['amt_tot'], // 實收租金 | |||
| 'deposit' => $data['deposit'], // 押金 | |||
| 'amt' => $data['amt'], // 本期租金 | |||
| // todo: 2016/12/23 只要超過季繳金額就拆開, 後續再由待開發票開立 | |||
| 'fee_period' => $data['fee_period'], // 本期繳期 | |||
| 'start_date' => $data['rent_start_date'], // 本期開始日 | |||
| 'end_date' => $data['rent_end_date'], // 本期結束日 | |||
| 'amt1' => $data['amt1'], // 首期租金 | |||
| 'amt_last' => $data['amt1'], // 上期租金 | |||
| 'fee_period_last' => $data['fee_period1'], // 上期繳期 | |||
| 'start_date_last' => $data['demonth_start_date'], // 上期開始日 | |||
| 'end_date_last' => $data['demonth_end_date'], // 上期結束日 | |||
| 'member_company_no' => $data['member_company_no'], // 買方統編 | |||
| 'company_no' => $data['company_no'], // 賣方統編 | |||
| 'acc_date' => $data['payed_date'], // 入帳日(暫定) | |||
| 'valid_time' => $this->default_valid_time // 有效期限 | |||
| ); | |||
| $this->db->insert('member_tx', $data_tx); // t4 新增 member_tx | |||
| $tx_no = $this->db->insert_id(); // 交易序號 | |||
| $data_tx['tx_no'] = $tx_no; | |||
| // [B.建立同步檔] | |||
| $sync_seqnos = $this->prepare_sync2hq($action_code, $station_no, 'members', $members_insert_id, $data); // t5 準備同步檔 (members) | |||
| $sync_seqnos .= ',' . $this->prepare_sync2hq($action_code, $station_no, 'member_bill', $bill_no, $data_bill); // t6 準備同步檔 (member_bill) | |||
| $sync_seqnos .= ',' . $this->prepare_sync2hq($action_code, $station_no, 'member_tx', $tx_no, $data_tx); // t7 準備同步檔 (member_tx) | |||
| // [C.完成] | |||
| $this->db->trans_complete(); | |||
| if ($this->db->trans_status() === FALSE) | |||
| { | |||
| trigger_error(__FUNCTION__ . '..trans_error..' . print_r($data, true)); | |||
| return 'trans_error'; | |||
| } | |||
| // 同步至總管理處 | |||
| $this->worker_tx('sync_batch', array('sync_seqnos' => $sync_seqnos)); | |||
| } | |||
| else | |||
| { | |||
| $altob_admin_submit = $this->input->post('altob_admin_submit', true); // 取得 admin 參數 | |||
| if($altob_admin_submit == $this->gen_admin_ck($station_no)) | |||
| { | |||
| trigger_error("admin: " + $altob_admin_submit); | |||
| //unset($data['contract_no']); // 合約號 | |||
| //unset($data['park_time']); // 停車時段 | |||
| unset($data['rent_start_date']); | |||
| unset($data['rent_end_date']); | |||
| unset($data['start_date']); | |||
| unset($data['end_date']); | |||
| unset($data['demonth_start_date']); | |||
| unset($data['demonth_end_date']); | |||
| unset($data['member_attr']); | |||
| unset($data['deposit']); | |||
| unset($data['amt_tot']); | |||
| unset($data['amt_accrued']); | |||
| unset($data['fee_period1']); | |||
| unset($data['amt1']); | |||
| //unset($data['fee_period']); // 例行繳期 | |||
| //unset($data['amt']); // 例行租金 | |||
| } | |||
| else | |||
| { | |||
| // 一般情況下, 時段與費率都不能在這個流程修改 | |||
| //unset($data['contract_no']); // 合約號 | |||
| unset($data['park_time']); | |||
| unset($data['rent_start_date']); | |||
| unset($data['rent_end_date']); | |||
| unset($data['start_date']); | |||
| unset($data['end_date']); | |||
| unset($data['demonth_start_date']); | |||
| unset($data['demonth_end_date']); | |||
| unset($data['member_attr']); | |||
| unset($data['deposit']); | |||
| unset($data['amt_tot']); | |||
| unset($data['amt_accrued']); | |||
| unset($data['fee_period1']); | |||
| unset($data['amt1']); | |||
| unset($data['fee_period']); | |||
| unset($data['amt']); | |||
| } | |||
| $action_code = 'U'; | |||
| // [A.開始] | |||
| $this->db->trans_start(); | |||
| $this->db->update('members', $data, array('station_no' => $station_no, 'member_no' => $check_member_no)); // t1. 更新 members | |||
| // 沒有異動到車牌, 使用update, 否則重建一筆 | |||
| if ($old_lpr == $data['lpr']) // t2. 更新 member_car | |||
| { | |||
| unset($data_car['lpr']); | |||
| unset($data_car['lpr_correct']); | |||
| $this->db->update('member_car', $data_car, array('station_no' => $station_no, 'member_no' => $check_member_no)); | |||
| } | |||
| else | |||
| { | |||
| $this->db->delete('member_car', array('station_no' => $station_no, 'member_no' => $check_member_no)); | |||
| $data_car['member_no'] = $check_member_no; | |||
| $this->db->insert('member_car', $data_car); | |||
| } | |||
| // [B.建立同步檔] | |||
| $sync_seqnos = $this->prepare_sync2hq($action_code, $station_no, 'members', $check_member_no, $data); // t3. 準備同步檔 (members) | |||
| // [C.完成] | |||
| $this->db->trans_complete(); | |||
| if ($this->db->trans_status() === FALSE) | |||
| { | |||
| trigger_error(__FUNCTION__ . '..trans_error..' . print_r($data, true)); | |||
| return 'trans_error'; | |||
| } | |||
| // 同步至總管理處 | |||
| $this->worker_tx('sync_batch', array('sync_seqnos' => $sync_seqnos)); | |||
| } | |||
| return array( | |||
| 'station_no' => $station_no, | |||
| 'company_no' => $data['company_no'], | |||
| 'member_no' => $data['member_no'], | |||
| 'start_date' => $start_date, | |||
| 'msg' => 'ok', | |||
| 'action_code' => $action_code, | |||
| 'tx_no' => $tx_no); | |||
| } | |||
| // 查詢車牌是否重複 | |||
| public function check_lpr($lpr) | |||
| { | |||
| $rows = $this->db->select('count(*) as counts') | |||
| ->from('members') | |||
| ->where(array('lpr' => $lpr)) | |||
| ->get() | |||
| ->row_array(); | |||
| return $rows['counts']; | |||
| } | |||
| // 取得交易發票 | |||
| public function get_tx_invoice_no($tx_no) | |||
| { | |||
| $rows = $this->db->select('invoice_no') | |||
| ->from('member_tx') | |||
| ->where(array('tx_no' => $tx_no)) | |||
| ->get() | |||
| ->row_array(); | |||
| return $rows['invoice_no']; | |||
| } | |||
| // 更新月租發票記錄 | |||
| public function set_tx_invoice_no($parms) | |||
| { | |||
| $data = array | |||
| ( | |||
| 'member_company_no' => $parms['member_company_no'], | |||
| 'company_no' => $parms['company_no'], | |||
| 'invoice_track' => $parms['invoice_track'], | |||
| 'invoice_no' => $parms['invoice_no'], | |||
| 'invoice_amt' => $parms['invoice_amt'], | |||
| 'invoice_time' => $parms['invoice_time'] | |||
| ); | |||
| if(array_key_exists('invoice_type', $parms)) | |||
| { | |||
| $data['invoice_type'] = $parms['invoice_type']; // 發票種類 | |||
| } | |||
| // [A.開始] | |||
| $this->db->trans_start(); | |||
| $this->db->update('member_tx', $data, array('station_no' => $parms['station_no'], 'tx_no' => $parms['tx_no'])); // t1. 更新 member_tx | |||
| // [B.建立同步檔] | |||
| $sync_seqnos = $this->prepare_sync2hq('U', $parms['station_no'], 'member_tx', $parms['tx_no'], $data); // t2. 準備同步檔 | |||
| // [C.完成] | |||
| $this->db->trans_complete(); | |||
| if ($this->db->trans_status() === FALSE) | |||
| { | |||
| trigger_error(__FUNCTION__ . '|'.print_r($data, true) . '..trans_error..'); | |||
| return 'fail'; // 中斷 | |||
| } | |||
| // 同步至總管理處 | |||
| $this->worker_tx('sync_batch', array('sync_seqnos' => $sync_seqnos)); | |||
| return 'ok'; | |||
| } | |||
| // 首期月租付款交易 | |||
| public function first_rents_payment($parms) | |||
| { | |||
| $this->try_sync_batch($parms['station_no']); // 同步未同步記錄 | |||
| // 確認交易記錄 | |||
| $rows = $this->db->select('count(*) as counts') | |||
| ->from('member_tx') | |||
| ->where(array('tx_no' => $parms['tx_no'], | |||
| 'station_no' => $parms['station_no'], 'member_no' => $parms['member_no'], | |||
| 'amt' => $parms['amt'], 'amt1' => $parms['amt1'])) | |||
| ->get() | |||
| ->row_array(); | |||
| if(empty($rows) || $rows['counts'] != 1) | |||
| { | |||
| trigger_error(__FUNCTION__ . '..tx gg..' . print_r($parms, true)); | |||
| return 'tx_error'; // 中斷 | |||
| } | |||
| // 印發票 | |||
| $parms['invoice_amt'] = $parms['amt'] + $parms['amt1']; // 例行租金 + 首期租金 | |||
| if(array_key_exists('invoice_track', $parms) && array_key_exists('invoice_no', $parms)) | |||
| { | |||
| $parms['invoice_time'] = date('Y-m-d H:i:s'); // 目前時間 | |||
| } | |||
| else | |||
| { | |||
| $invoice_result = $this->print_invoice($parms); | |||
| if(!empty($invoice_result) && array_key_exists('einvoice_no', $invoice_result)) | |||
| { | |||
| $parms['invoice_track'] = $invoice_result['einvoice_track']; // 發票字軌 | |||
| $parms['invoice_no'] = $invoice_result['einvoice_no']; // 發票號碼 | |||
| $parms['invoice_time'] = date('Y-m-d H:i:s'); // 目前時間 | |||
| } | |||
| } | |||
| if(empty($parms['invoice_no']) || empty($parms['invoice_track'])) | |||
| { | |||
| trigger_error(__FUNCTION__ . '..invoice gg..' . print_r($parms, true)); | |||
| return 'invoice_fail'; // 中斷 | |||
| } | |||
| // 更新月租發票記錄 | |||
| echo $this->set_tx_invoice_no($parms); | |||
| } | |||
| // 新增月租付款交易 | |||
| public function rents_payment($parms) | |||
| { | |||
| $this->try_sync_batch($parms['station_no']); // 同步未同步記錄 | |||
| //$parms['start_date'] = $parms['start_date_last']; | |||
| // 印發票 | |||
| $parms['invoice_amt'] = $parms['amt']; // 例行租金 | |||
| if(array_key_exists('invoice_track', $parms) && array_key_exists('invoice_no', $parms)) | |||
| { | |||
| $parms['invoice_time'] = date('Y-m-d H:i:s'); // 目前時間 | |||
| } | |||
| else | |||
| { | |||
| $invoice_result = $this->print_invoice($parms); | |||
| if(!empty($invoice_result) && array_key_exists('einvoice_no', $invoice_result)) | |||
| { | |||
| $parms['invoice_track'] = $invoice_result['einvoice_track']; // 發票字軌 | |||
| $parms['invoice_no'] = $invoice_result['einvoice_no']; // 發票號碼 | |||
| $parms['invoice_time'] = date('Y-m-d H:i:s'); // 目前時間 | |||
| } | |||
| if(empty($parms['invoice_no']) || empty($parms['invoice_track'])) | |||
| { | |||
| trigger_error(__FUNCTION__ . '..invoice gg..' . print_r($parms, true)); | |||
| //return 'invoice_fail'; | |||
| } | |||
| } | |||
| $parms['sync_no'] = 0; // 預設同步編號 | |||
| $parms['fee_period_last'] = $parms['fee_period']; // 上期繳期 | |||
| $parms['start_date'] = date('Y-m-d', strtotime("{$parms['end_date_last']} first day of next month")); // 本期開始日:上期結束日之次月首日 | |||
| $parms['acc_date'] = date('Y-m-d'); // 入帳日(暫定) | |||
| $parms['valid_time'] = $this->default_valid_time; // 有效期限 | |||
| // [A.開始] | |||
| $this->db->trans_start(); | |||
| $this->db->insert('member_tx', $parms); // t1. 新增 member_tx | |||
| $tx_no = $this->db->insert_id(); // 交易序號 | |||
| $data = $parms; | |||
| $data['tx_no'] = $tx_no; | |||
| $data_member = array( | |||
| 'fee_period' => $parms['fee_period'], | |||
| 'payed_date' => substr($parms['invoice_time'], 0, 10), | |||
| 'start_date' => "{$parms['start_date_last']} 00:00:00", // 開始日:由上期繼續延續下去 | |||
| 'end_date' => "{$parms['end_date']} 23:59:59" // 結束日 | |||
| ); | |||
| $this->db->update('members', $data_member, array('station_no' => $parms['station_no'], 'member_no' => $parms['member_no'])); // t2. 更新 members | |||
| $this->db->update('member_car', // t5. 更新 member_car | |||
| array('start_time' => "{$data_member['start_date']} 00:00:00", 'end_time' => "{$data_member['end_date']} 23:59:59"), | |||
| array('station_no' => $parms['station_no'], 'member_no' => $parms['member_no'])); | |||
| // [B.準備同步檔] | |||
| $sync_seqnos = $this->prepare_sync2hq('A', $parms['station_no'], 'member_tx', $tx_no, $data); // t2. 準備同步檔 | |||
| $sync_seqnos .= ',' . $this->prepare_sync2hq('U', $parms['station_no'], 'members', $parms['member_no'], $data_member); // t4. 準備同步檔 | |||
| // [c.完成] | |||
| $this->db->trans_complete(); | |||
| if ($this->db->trans_status() === FALSE) | |||
| { | |||
| trigger_error(__FUNCTION__ . '|'.print_r($data, true) . '..trans_error..'); | |||
| return 'fail'; // 中斷 | |||
| } | |||
| // 同步至總管理處 | |||
| $this->worker_tx('sync_batch', array('sync_seqnos' => $sync_seqnos)); | |||
| return 'ok'; | |||
| } | |||
| // 停權或啟動 | |||
| public function suspended($parms) | |||
| { | |||
| $this->try_sync_batch($parms['station_no']); // 同步未同步記錄 | |||
| $altob_admin_submit = $this->input->post('altob_admin_submit', true); // 取得 admin 參數 | |||
| if($altob_admin_submit !== $this->gen_admin_ck($parms['station_no'])) | |||
| { | |||
| trigger_error(__FUNCTION__ . '..altob_admin_submit error..' . print_r($parms, true)); | |||
| return 'admin_error'; // 中斷 | |||
| } | |||
| $data = array('suspended' => $parms['suspended']); | |||
| // [A.開始] | |||
| $this->db->trans_start(); | |||
| $this->db->update('members', $data, array('station_no' => $parms['station_no'], 'member_no' => $parms['member_no'])); // t1. 更新 member.suspended | |||
| // [B.準備同步檔] | |||
| $sync_seqnos = $this->prepare_sync2hq('U', $parms['station_no'], 'members', $parms['member_no'], $data); // t2. 準備同步檔 | |||
| // [C.完成] | |||
| $this->db->trans_complete(); | |||
| if ($this->db->trans_status() === FALSE) | |||
| { | |||
| trigger_error(__FUNCTION__ . '|'.print_r($data, true) . '..trans_error..'); | |||
| return 'fail'; // 中斷 | |||
| } | |||
| // 同步至總管理處 | |||
| $this->worker_tx('sync_batch', array('sync_seqnos' => $sync_seqnos)); | |||
| return 'ok'; | |||
| } | |||
| // 同步未同步記錄 | |||
| public function try_sync_batch($station_no, $limit=5) | |||
| { | |||
| $sql = "select st_sync_no | |||
| from syncs | |||
| where synced = 0 and erred = 0 and station_no = {$station_no} | |||
| order by st_sync_no ASC | |||
| limit {$limit}"; | |||
| $results = $this->db->query($sql)->result_array(); | |||
| if(empty($results)) return false; // do nothing | |||
| $sync_seqnos = ''; | |||
| foreach($results as $rows) | |||
| { | |||
| $sync_seqnos .= ',' . $rows['st_sync_no']; | |||
| } | |||
| $sync_seqnos = ltrim($sync_seqnos, ','); | |||
| trigger_error(__FUNCTION__ . '|' . $sync_seqnos); | |||
| // 同步至總管理處 | |||
| $this->worker_tx('sync_batch', array('sync_seqnos' => $sync_seqnos)); | |||
| } | |||
| // 同步至總公司 | |||
| function prepare_sync2hq($act, $station_no, $st_tname, $st_seqno, $data) | |||
| { | |||
| $data_syncs = array | |||
| ( | |||
| 'station_no' => $station_no, | |||
| 'synced' => 0, // 尚未同步 | |||
| 'erred' => 0, | |||
| 'act' => $act, // A:新增, U:修改, D:刪除 | |||
| 'hq_tname' => 'hq_'.$st_tname, | |||
| 'st_tname' => $st_tname, // 場站資料表 | |||
| 'st_seqno' => $st_seqno, // 場站交易序號 | |||
| 'sync_data' => json_encode($data, JSON_UNESCAPED_UNICODE) | |||
| ); | |||
| $this->db->insert('syncs', $data_syncs); | |||
| return $this->db->insert_id(); | |||
| } | |||
| // curl送收資料 | |||
| function worker_tx($cmd, $data) | |||
| { | |||
| try | |||
| { | |||
| $ch = curl_init(); | |||
| $curl_options = array | |||
| ( | |||
| CURLOPT_URL => "http://localhost:60133/?cmd={$cmd}", | |||
| CURLOPT_HEADER => 0, | |||
| CURLOPT_RETURNTRANSFER => 1, // 返回值不顯示, 只做變數用 | |||
| CURLOPT_POST => 1, | |||
| CURLOPT_POSTFIELDS => $data | |||
| ); | |||
| curl_setopt_array($ch, $curl_options); | |||
| curl_exec($ch); | |||
| curl_close($ch); | |||
| } | |||
| catch (Exception $e) | |||
| { | |||
| trigger_error("{$cmd} error: ".$e->getMessage()); | |||
| } | |||
| } | |||
| // 管理員參數 | |||
| function gen_admin_ck($station_no) | |||
| { | |||
| return md5(date("m \a\l\t\o\b d").$station_no.date("i \z\z\z H")); | |||
| } | |||
| // 印發票 | |||
| public function print_invoice($parms) | |||
| { | |||
| $result = array(); | |||
| try | |||
| { | |||
| // 印發票 | |||
| $ch = curl_init(); | |||
| $curl_options = array | |||
| ( | |||
| CURLOPT_URL => "http://localhost:60134/", | |||
| CURLOPT_HEADER => 0, | |||
| CURLOPT_RETURNTRANSFER => 1, | |||
| CURLOPT_CONNECTTIMEOUT => 2, | |||
| CURLOPT_TIMEOUT => 2, | |||
| CURLOPT_POST => 1, | |||
| CURLOPT_POSTFIELDS => array( | |||
| 'cmd' => 'printInvoice', | |||
| 'company_no' => $parms['company_no'], | |||
| 'vCUS_COMP_CODE'=> $parms['member_company_no'], | |||
| 'vAmount' => $parms['invoice_amt'], | |||
| 'vPLU_MEMO' => 'parking:50:3', | |||
| 'vTAIL_MESSAGE' => 'Rental' | |||
| ) | |||
| ); | |||
| curl_setopt_array($ch, $curl_options); | |||
| $ch_response = curl_exec($ch); | |||
| trigger_error(__FUNCTION__ . '|' . print_r($ch_response, true)); | |||
| curl_close($ch); | |||
| $result = json_decode($ch_response, true); | |||
| } | |||
| catch (Exception $e) | |||
| { | |||
| trigger_error(__FUNCTION__ .$e->getMessage()); | |||
| } | |||
| //測試用 | |||
| //$result['einvoice_track'] = 'AB'; // 發票字軌 | |||
| //$result['einvoice_no'] = '12345678'; // 發票號碼 | |||
| return $result; | |||
| } | |||
| } | |||
| @@ -0,0 +1,20 @@ | |||
| <?php | |||
| /* | |||
| file: Allpay_payment_model.php 付費系統 (歐付寶) | |||
| */ | |||
| class Allpay_payment_model extends CI_Model | |||
| { | |||
| function __construct() | |||
| { | |||
| parent::__construct(); | |||
| $this->load->database(); | |||
| } | |||
| // 記錄 (歐付寶付費) | |||
| public function create_allpay_feedback_log($data) | |||
| { | |||
| $this->db->insert('allpay_feedback_log', $data); | |||
| return true; | |||
| } | |||
| } | |||
| @@ -0,0 +1,596 @@ | |||
| <?php | |||
| /* | |||
| file: carpark_model.php 停車管理系統 | |||
| */ | |||
| class Carpark_model extends CI_Model | |||
| { | |||
| var $vars = array(); | |||
| function __construct() | |||
| { | |||
| parent::__construct(); | |||
| $this->load->database(); | |||
| } | |||
| public function init($vars) | |||
| { | |||
| $this->vars = $vars; | |||
| } | |||
| // 月租會員加入 | |||
| public function member_add($data) | |||
| { | |||
| // 會員車輛基本資料檔 | |||
| // $data['start_date'] = "{$data['start_date']} 00:00:00"; | |||
| // $data['end_date'] = "{$data['end_date']} 23:59:59"; | |||
| $old_lpr = $data['old_lpr']; | |||
| unset($data['old_lpr']); | |||
| $data_car = array | |||
| ( | |||
| 'lpr' => $data['lpr'], | |||
| 'lpr_correct' => $data['lpr'], | |||
| 'etag' => $data['etag'], | |||
| 'station_no' => $data['station_no'], | |||
| 'start_time' => $data['start_date'], | |||
| 'end_time' => $data['end_date'] | |||
| ); | |||
| $check_member_no = $data['member_no']; | |||
| unset($data['member_no']); | |||
| trigger_error("members:".print_r($data, true)."car:".print_r($data_car, true)); | |||
| if ($check_member_no == 0) // 新增一筆會員資料 | |||
| { | |||
| $this->db->insert('members', $data); | |||
| $data_car['member_no'] = $this->db->insert_id(); | |||
| $this->db->insert('member_car', $data_car); | |||
| } | |||
| else // update會員資料 | |||
| { | |||
| $this->db->update('members', $data, array('member_no' => $check_member_no)); | |||
| if ($old_lpr == $data['lpr']) // 沒有異動到車牌, 使用update, 否則重建一筆 | |||
| { | |||
| unset($data_car['lpr']); | |||
| unset($data_car['lpr_correct']); | |||
| $this->db->update('member_car', $data_car, array('member_no' => $check_member_no)); | |||
| } | |||
| else | |||
| { | |||
| $this->db->delete('member_car', array('member_no' => $check_member_no)); | |||
| $data_car['member_no'] = $check_member_no; | |||
| $this->db->insert('member_car', $data_car); | |||
| } | |||
| } | |||
| return true; | |||
| } | |||
| // 查詢車牌是否重複 | |||
| public function check_lpr($lpr) | |||
| { | |||
| $rows = $this->db->select('count(*) as counts') | |||
| ->from('members') | |||
| ->where(array('lpr' => $lpr)) | |||
| ->get() | |||
| ->row_array(); | |||
| return $rows['counts']; | |||
| } | |||
| // 月租會員查詢 | |||
| public function member_query() | |||
| { | |||
| $results = $this->db->select('member_no, lpr, etag, member_name, mobile_no, start_date, end_date, contract_no, amt, member_id, tel_h, tel_o, addr, valid_time, station_no') | |||
| ->from('members') | |||
| ->order_by('station_no, lpr', 'asc') | |||
| ->get() | |||
| ->result_array(); | |||
| return $results; | |||
| } | |||
| // 刪除月租會員 | |||
| public function member_delete($member_no) | |||
| { | |||
| $this->db->delete('members', array('member_no' => $member_no)); | |||
| $this->db->delete('member_car', array('member_no' => $member_no)); | |||
| return true; | |||
| } | |||
| // 進出場現況表 | |||
| public function cario_list() | |||
| { | |||
| /* | |||
| $data_cario = $this->db | |||
| ->select('c.cario_no, c.in_out, in_lane, out_lane, c.in_time, c.out_time, c.minutes, c.obj_id as lpr, c.etag, c.in_pic_name, c.out_pic_name, m.member_name as owner') | |||
| ->from('cario c') | |||
| ->join('members m', 'c.member_no = m.member_no', 'left') | |||
| ->where(array('c.err' => 0)) | |||
| ->order_by('c.update_time', 'desc') | |||
| ->limit(10) | |||
| ->get() | |||
| ->result_array(); | |||
| */ | |||
| $sql = '(select c.cario_no, c.in_out, in_lane, out_lane, c.in_time, c.out_time, c.minutes, c.obj_id as lpr, c.etag, c.in_pic_name, c.out_pic_name, m.member_name as owner, c.in_time as time_order | |||
| from cario c left join members m on c.obj_id = m.lpr | |||
| where c.err = 0 and c.out_time is null) | |||
| union | |||
| (select c.cario_no, c.in_out, in_lane, out_lane, c.in_time, c.out_time, c.minutes, c.obj_id as lpr, c.etag, c.in_pic_name, c.out_pic_name, m.member_name as owner, c.out_time as time_order | |||
| from cario c left join members m on c.obj_id = m.lpr | |||
| where c.err = 0 and c.out_time is not null) | |||
| order by time_order desc limit 10;'; | |||
| $data_cario = $this->db->query($sql)->result_array(); | |||
| // $lane_arr = array(0 => '入1', 1 => '入2', 3 => '出3', 3 => '出4'); | |||
| $idx = 0; | |||
| foreach($data_cario as $rows) | |||
| { | |||
| ++$rows['in_lane']; | |||
| ++$rows['out_lane']; | |||
| //$lane_no = $rows['in_out'] == 'CI' ? "入{$rows['in_lane']}" : "入{$rows['in_lane']} -> 出{$rows['out_lane']}"; | |||
| $lane_no = empty($rows['out_time']) ? "入{$rows['in_lane']}" : "入{$rows['in_lane']} -> 出{$rows['out_lane']}"; // 2016/08/22 有離場時間就顯示 | |||
| $pic_name = str_replace('.jpg', '', empty($rows['out_pic_name']) ? $rows['in_pic_name'] : $rows['out_pic_name']); | |||
| $arr = explode('-', $pic_name); | |||
| $pic_path = APP_URL.'pics/'.substr($arr[7], 0, 8).'/'.$pic_name; | |||
| $data[$idx] = array | |||
| ( | |||
| // 'io_name' => $io_name[$rows['in_out']], | |||
| 'io_name' => $lane_no, | |||
| 'lpr' => $rows['lpr'], | |||
| // 'etag' => $rows['etag'], | |||
| 'etag' => $rows['etag'], | |||
| 'owner' => $rows['owner'], | |||
| 'io_time' => empty($rows['out_time']) ? $rows['in_time'] : "{$rows['in_time']}(入)<br>{$rows['out_time']}(出)<br>{$rows['minutes']}分(停留時間)", | |||
| 'pic_name' => $pic_path | |||
| ); | |||
| ++$idx; | |||
| } | |||
| return $data; | |||
| } | |||
| // 模糊比對 | |||
| function getLevenshteinSQLStatement($word, $target) | |||
| { | |||
| $words = array(); | |||
| if(strlen($word) >= 5) | |||
| { | |||
| for ($i = 0; $i < strlen($word); $i++) { | |||
| // insertions | |||
| $words[] = substr($word, 0, $i) . '_' . substr($word, $i); | |||
| // deletions | |||
| $words[] = substr($word, 0, $i) . substr($word, $i + 1); | |||
| // substitutions | |||
| //$words[] = substr($word, 0, $i) . '_' . substr($word, $i + 1); | |||
| } | |||
| } | |||
| else | |||
| { | |||
| for ($i = 0; $i < strlen($word); $i++) { | |||
| // insertions | |||
| $words[] = substr($word, 0, $i) . '_' . substr($word, $i); | |||
| } | |||
| } | |||
| // last insertion | |||
| $words[] = $word . '_'; | |||
| //return $words; | |||
| $fuzzy_statement = ' ('; | |||
| foreach ($words as $idx => $word) | |||
| { | |||
| $fuzzy_statement .= " {$target} LIKE '%{$word}%' OR "; | |||
| } | |||
| $last_or_pos = strrpos($fuzzy_statement, 'OR'); | |||
| if($last_or_pos !== false) | |||
| { | |||
| $fuzzy_statement = substr_replace($fuzzy_statement, ')', $last_or_pos, strlen('OR')); | |||
| } | |||
| return $fuzzy_statement; | |||
| } | |||
| // 車號入場查詢 | |||
| public function carin_lpr_query($word) | |||
| { | |||
| // updated 2016/09/09 fuzzy search | |||
| if(empty($word) || strlen($word) < 4 || strlen($word) > 10) | |||
| { | |||
| return array(); | |||
| } | |||
| $fuzzy_statement = $this->getLevenshteinSQLStatement($word, 'c.obj_id'); | |||
| trigger_error("模糊比對 {$word} where: {$fuzzy_statement}"); | |||
| $sql = "SELECT c.cario_no, c.in_out, in_lane, out_lane, c.in_time, c.out_time, c.minutes, c.obj_id as lpr, c.etag, c.in_pic_name, c.out_pic_name, m.member_name as owner | |||
| FROM cario c | |||
| LEFT JOIN members m ON c.obj_id = m.lpr | |||
| WHERE {$fuzzy_statement} AND c.err = 0 AND c.obj_type = 1 | |||
| ORDER BY c.update_time DESC | |||
| LIMIT 50"; | |||
| $data_cario = $this->db->query($sql)->result_array(); | |||
| /* | |||
| $data_cario = $this->db | |||
| ->select('c.cario_no, c.in_out, in_lane, out_lane, c.in_time, c.out_time, c.minutes, c.obj_id as lpr, c.etag, c.in_pic_name, c.out_pic_name, m.member_name as owner') | |||
| ->from('cario c') | |||
| ->join('members m', 'c.member_no = m.member_no', 'left') | |||
| ->where(array('c.obj_type' => 1, 'obj_id' => $lpr)) | |||
| ->order_by('c.update_time', 'desc') | |||
| ->get() | |||
| ->result_array(); | |||
| */ | |||
| $data = array(); | |||
| $idx = 0; | |||
| foreach($data_cario as $rows) | |||
| { | |||
| ++$rows['in_lane']; | |||
| ++$rows['out_lane']; | |||
| $lane_no = empty($rows['out_time']) ? "入{$rows['in_lane']}" : "入{$rows['in_lane']} -> 出{$rows['out_lane']}"; | |||
| $io_time = empty($rows['out_time']) ? $rows['in_time'] : "{$rows['in_time']}(入)<br>{$rows['out_time']}(出)<br>{$rows['minutes']}分(停留時間)"; | |||
| $pic_name = str_replace('.jpg', '', empty($rows['out_pic_name']) ? $rows['in_pic_name'] : $rows['out_pic_name']); | |||
| $arr = explode('-', $pic_name); | |||
| $pic_path = APP_URL.'pics/'.substr($arr[7], 0, 8).'/'.$pic_name; | |||
| $data[$idx++] = array | |||
| ( | |||
| 'io_name' => $lane_no, | |||
| 'lpr' => $rows['lpr'], | |||
| 'etag' => $rows['etag'], | |||
| 'owner' => empty($rows['owner']) ? '' : $rows['owner'], | |||
| 'io_time' => $io_time, | |||
| 'pic_name' => $pic_path | |||
| ); | |||
| } | |||
| return $data; | |||
| } | |||
| // 車號入場查詢 | |||
| public function carin_time_query($time_query, $minutes_range) | |||
| { | |||
| $curr_time = date('Y-m-d H:i:s'); | |||
| $start_time = date('Y-m-d H:i:s', strtotime("{$time_query} - {$minutes_range} minutes")); | |||
| $end_time = date('Y-m-d H:i:s', strtotime("{$time_query} + {$minutes_range} minutes")); | |||
| $data_cario = $this->db | |||
| ->select('c.cario_no, c.in_out, in_lane, out_lane, c.in_time, c.out_time, c.minutes, c.obj_id as lpr, c.etag, c.in_pic_name, c.out_pic_name, m.member_name as owner') | |||
| ->from('cario c') | |||
| ->join('members m', 'c.obj_id = m.lpr', 'left') | |||
| ->where(array('c.obj_type' => 1, 'c.in_time >=' => $start_time, 'c.in_time <=' => $end_time)) | |||
| ->order_by('c.update_time', 'desc') | |||
| ->get() | |||
| ->result_array(); | |||
| $data = array(); | |||
| $idx = 0; | |||
| foreach($data_cario as $rows) | |||
| { | |||
| ++$rows['in_lane']; | |||
| ++$rows['out_lane']; | |||
| $lane_no = empty($rows['out_time']) ? "入{$rows['in_lane']}" : "入{$rows['in_lane']} -> 出{$rows['out_lane']}"; | |||
| $io_time = empty($rows['out_time']) ? $rows['in_time'] : "{$rows['in_time']}(入)<br>{$rows['out_time']}(出)<br>{$rows['minutes']}分(停留時間)"; | |||
| $pic_name = str_replace('.jpg', '', empty($rows['out_pic_name']) ? $rows['in_pic_name'] : $rows['out_pic_name']); | |||
| $arr = explode('-', $pic_name); | |||
| $pic_path = APP_URL.'pics/'.substr($arr[7], 0, 8).'/'.$pic_name; | |||
| $data[$idx++] = array | |||
| ( | |||
| 'io_name' => $lane_no, | |||
| 'lpr' => $rows['lpr'], | |||
| 'etag' => $rows['etag'], | |||
| 'owner' => empty($rows['owner']) ? '' : $rows['owner'], | |||
| 'io_time' => $io_time, | |||
| 'pic_name' => $pic_path | |||
| ); | |||
| } | |||
| return $data; | |||
| } | |||
| // 時間長度轉成日時分秒 | |||
| public function time2str($d1, $d2) | |||
| { | |||
| $time = strtotime($d2) - strtotime($d1); | |||
| $day_str = floor($time/3600/24); | |||
| $day_str = $day_str ? $day_str .= '天 ' : ''; | |||
| $hour_str = floor($time%(24*3600)/3600); | |||
| $hour_str = $hour_str ? $hour_str .= '小時 ' : ''; | |||
| $minute_str = floor($time%3600/60); | |||
| $minute_str = $minute_str ? $minute_str .= '分' : ''; | |||
| /* | |||
| $second_str = $time%3600%60; | |||
| $second_str = $second_str ? $second_str .= ' seconds ' : ''; | |||
| $n_time = floor($time/3600/24)."days".floor($time%(24*3600)/3600)."Hour".floor($time%3600/60)."Minute".($time%3600%60)."Second"; | |||
| */ | |||
| $n_time = $day_str . $hour_str . $minute_str; | |||
| return $n_time; | |||
| } | |||
| // 在席車位檢查未有入場資料清單 | |||
| public function pks_check_list($max_rows) | |||
| { | |||
| $data = array(); | |||
| $data = $this->db | |||
| ->select('pksno, lpr, in_time, pic_name') | |||
| ->from('pks') | |||
| ->where(array('status' => 'LR', 'cario_no' => 0, 'confirms' => 0, 'station_no' => STATION_NO)) | |||
| ->order_by('in_time', 'desc') | |||
| ->limit($max_rows) | |||
| ->get() | |||
| ->result_array(); | |||
| return $data; | |||
| } | |||
| // 重設在席查核 | |||
| public function reset_pks_check() | |||
| { | |||
| // 讀出未查核過的資料 | |||
| $data_pks = $this->db | |||
| ->select('pksno, lpr, in_time') | |||
| ->from('pks') | |||
| ->where(array('status' => 'LR', 'cario_no' => 0, 'station_no' => STATION_NO)) | |||
| ->get() | |||
| ->result_array(); | |||
| // $tot = $this->db->num_rows(); // 總筆數 | |||
| $tot = count($data_pks); // 總筆數 | |||
| $num_cario = 0; // 入場資料筆數 | |||
| foreach($data_pks as $rows) | |||
| { | |||
| $lpr = $rows['lpr']; | |||
| if ($lpr == 'NONE') continue; // 車辨失敗者不處理 | |||
| $pksno = $rows['pksno']; | |||
| $pks_in_time = $rows['in_time']; | |||
| // 讀取進場時間, 如讀不到資料, 以目前時間取代(add by TZUSS 2016-02-23) | |||
| $rows_cario = $this->db | |||
| ->select('cario_no, in_time') | |||
| ->from('cario') | |||
| ->where(array('in_out' => 'CI', 'obj_id' => $lpr, 'finished' => 0, 'err' => 0, 'station_no' => STATION_NO)) | |||
| ->order_by('cario_no', 'desc') | |||
| ->limit(1) | |||
| ->get() | |||
| ->row_array(); | |||
| // if ($this->db->num_rows() == 1) // 有入場資料 | |||
| if (!empty($rows_cario['cario_no'])) // 有入cario_no場資料 | |||
| { | |||
| $cario_no = $rows_cario['cario_no']; // 入場序號 | |||
| $in_time = $rows_cario['in_time']; | |||
| // 在席與入場資料相符, 分別在cario與pks記錄之 | |||
| $data = array | |||
| ( | |||
| 'pksno' => $pksno, | |||
| 'pks_time' => $pks_in_time | |||
| ); | |||
| $this->db->update('cario', $data, array('cario_no' => $cario_no, 'station_no' => STATION_NO)); | |||
| $data = array | |||
| ( | |||
| 'cario_no' => $cario_no, | |||
| 'in_time' => $in_time | |||
| ); | |||
| // 車號及照片檔名填入資料庫內 | |||
| $this->db->update('pks', $data, array('pksno' => $pksno, 'station_no' => STATION_NO)); | |||
| ++$num_cario; | |||
| } | |||
| } | |||
| return array('tot' => $tot, 'tot_correct' => $num_cario); | |||
| } | |||
| // 更正在席車號 | |||
| public function correct_pks_lpr($pksno, $lpr) | |||
| { | |||
| // 讀取進場時間, 如讀不到資料, 以目前時間取代(add by TZUSS 2016-02-23) | |||
| $rows_cario = $this->db | |||
| ->select('cario_no, in_time') | |||
| ->from('cario') | |||
| ->where(array('in_out' => 'CI', 'obj_id' => $lpr, 'finished' => 0, 'err' => 0, 'station_no' => STATION_NO)) | |||
| ->order_by('cario_no', 'desc') | |||
| ->limit(1) | |||
| ->get() | |||
| ->row_array(); | |||
| if (!empty($rows_cario['cario_no'])) // 有cario_no入場資料 | |||
| { | |||
| $cario_no = $rows_cario['cario_no']; // 入場序號 | |||
| $in_time = $rows_cario['in_time']; | |||
| // 在席與入場資料相符, 分別在cario與pks記錄之 | |||
| $data = array | |||
| ( | |||
| 'pksno' => $pksno, | |||
| 'pks_time' => $in_time | |||
| ); | |||
| $this->db->update('cario', $data, array('cario_no' => $cario_no, 'station_no' => STATION_NO)); | |||
| $data = array | |||
| ( | |||
| 'confirms' => 1, | |||
| 'cario_no' => $cario_no, | |||
| 'lpr' => $lpr, | |||
| 'in_time' => $in_time | |||
| ); | |||
| // 車號及照片檔名填入資料庫內 | |||
| $this->db->update('pks', $data, array('pksno' => $pksno, 'station_no' => STATION_NO)); | |||
| $results = array | |||
| ( | |||
| 'err' => 0, | |||
| 'cario_no' => $cario_no | |||
| ); | |||
| } | |||
| else // 無入場資料 | |||
| { | |||
| $data = array | |||
| ( | |||
| 'confirms' => 1, | |||
| 'lpr' => $lpr | |||
| ); | |||
| $this->db->update('pks', $data, array('pksno' => $pksno, 'station_no' => STATION_NO)); | |||
| $results = array | |||
| ( | |||
| 'err' => 0, | |||
| 'cario_no' => 0 // 車號查無入場資料 | |||
| ); | |||
| } | |||
| return $results; | |||
| } | |||
| // 入場車號查核在席無資料清單 | |||
| public function carin_check_list($max_rows) | |||
| { | |||
| $data = array(); | |||
| $rows_cario = $this->db | |||
| ->select('cario_no, obj_id as lpr, in_time, member_no, in_pic_name') | |||
| ->from('cario') | |||
| ->where('in_out', 'CI') | |||
| ->where(array('pksno' => 0, 'finished' => 0, 'err' => 0, 'confirms' => 0, 'station_no' => STATION_NO, 'in_time <=' => 'date_sub(now(), interval 20 minute)'), null, false) | |||
| ->order_by('cario_no', 'desc') | |||
| ->limit($max_rows) | |||
| ->get() | |||
| ->result_array(); | |||
| $idx = 0; | |||
| foreach($rows_cario as $rows) | |||
| { | |||
| $data[$idx++] = array | |||
| ( | |||
| 'cario_no' => $rows['cario_no'], | |||
| 'lpr' => $rows['lpr'], | |||
| 'in_time' => $rows['in_time'], | |||
| 'type' => $rows['member_no'] == 0 ? '' : '月租', | |||
| 'pic_name' => str_replace('-', '', substr($rows['in_time'], 0, 10)) . '/' . $rows['in_pic_name'] | |||
| ); | |||
| } | |||
| return $data; | |||
| } | |||
| // 更正入場車號 | |||
| public function correct_carin_lpr($cario_no, $lpr, $in_time) | |||
| { | |||
| $rows = $this->db | |||
| ->select('pksno, cario_no, in_time') | |||
| ->from('pks') | |||
| ->where(array('status' => 'LR', 'lpr' => $lpr, 'confirms' => 0, 'station_no' => STATION_NO)) | |||
| ->limit(1) | |||
| ->get() | |||
| ->row_array(); | |||
| // 如果在席資料相符 | |||
| if (!empty($rows['pksno'])) | |||
| { | |||
| $pksno = $rows['pksno']; | |||
| $data = array | |||
| ( | |||
| 'cario_no' => $cario_no, | |||
| 'in_time' => $in_time | |||
| ); | |||
| $this->db->update('pks', $data, array('pksno' => $pksno, 'station_no' => STATION_NO)); | |||
| $data_cario = array | |||
| ( | |||
| 'obj_id' => $lpr, | |||
| 'pksno' => $pksno, | |||
| 'pks_time' => $in_time, | |||
| 'confirms' => 1 | |||
| ); | |||
| } | |||
| else // 無在席資料 | |||
| { | |||
| $data_cario = array | |||
| ( | |||
| 'obj_id' => $lpr, | |||
| 'pksno' => 0, | |||
| 'confirms' => 1 | |||
| ); | |||
| } | |||
| $this->db->update('cario', $data_cario, array('cario_no' => $cario_no, 'station_no' => STATION_NO)); | |||
| return(array('pksno' => $data_cario['pksno'])); | |||
| } | |||
| // 查詢行動支付記錄 | |||
| public function tx_bill_query() | |||
| { | |||
| $sql = "SELECT | |||
| tx_bill.order_no as order_no, tx_bill.lpr as lpr, tx_bill.invoice_no as invoice_no, tx_bill.in_time as in_time, tx_bill.balance_time as balance_time, tx_bill.company_no as company_no, tx_bill.email as email, tx_bill.mobile as mobile, tx_bill.amt as amt, tx_bill.tx_time as tx_time, | |||
| allpay_feedback_log.rtn_msg as rtn_msg, allpay_feedback_log.payment_type as payment_type, | |||
| cario.out_before_time as out_before_time | |||
| FROM tx_bill | |||
| LEFT JOIN cario ON tx_bill.cario_no = cario.cario_no | |||
| LEFT JOIN allpay_feedback_log ON tx_bill.order_no = allpay_feedback_log.merchant_trade_no | |||
| WHERE tx_bill.status = 111 | |||
| ORDER BY tx_bill.tx_time DESC"; | |||
| return $this->db->query($sql)->result_array(); | |||
| } | |||
| // 查詢月租繳款機記錄 | |||
| public function tx_bill_ats_query() | |||
| { | |||
| $sql = "SELECT | |||
| tx_bill_ats.order_no as order_no, tx_bill_ats.lpr as lpr, tx_bill_ats.invoice_no as invoice_no, | |||
| tx_bill_ats.end_time as end_time, tx_bill_ats.next_start_time as next_start_time, tx_bill_ats.next_end_time as next_end_time, | |||
| tx_bill_ats.company_no as company_no, tx_bill_ats.email as email, tx_bill_ats.mobile as mobile, tx_bill_ats.amt as amt, | |||
| tx_bill_ats.remarks as remarks, tx_bill_ats.member_name as member_name, tx_bill_ats.tx_time as tx_time, | |||
| allpay_feedback_log.rtn_msg as rtn_msg, allpay_feedback_log.payment_type as payment_type | |||
| FROM tx_bill_ats | |||
| LEFT JOIN allpay_feedback_log ON tx_bill_ats.order_no = allpay_feedback_log.merchant_trade_no | |||
| WHERE tx_bill_ats.status = 111 | |||
| ORDER BY tx_bill_ats.tx_time DESC"; | |||
| return $this->db->query($sql)->result_array(); | |||
| } | |||
| // 查詢樓層在席群組 | |||
| public function pks_group_query() | |||
| { | |||
| $sql = "SELECT | |||
| pks_groups.station_no, pks_groups.group_name as group_name, pks_groups.tot as tot, pks_groups.parked as parked, pks_groups.availables as availables, pks_groups.group_id as group_id, pks_groups.renum as renum | |||
| FROM pks_groups | |||
| ORDER BY pks_groups.group_id DESC"; | |||
| return $this->db->query($sql)->result_array(); | |||
| } | |||
| // 送出至message queue(目前用mqtt) | |||
| public function mq_send($topic, $msg) | |||
| { | |||
| $this->vars['mqtt']->publish($topic, $msg, 0); | |||
| trigger_error("mqtt:{$topic}|{$msg}"); | |||
| } | |||
| } | |||
| @@ -0,0 +1,653 @@ | |||
| <?php | |||
| /* | |||
| file: carpayment_model.php | |||
| */ | |||
| require_once(ALTOB_SYNC_FILE) ; | |||
| class Carpayment_model extends CI_Model | |||
| { | |||
| var $vars = array(); | |||
| var $io_name = array('I' => '車入', 'O' => '車出', 'MI' => '機入', 'MO' => '機出', 'FI' => '樓入', 'FO' => '樓出'); | |||
| var $now_str; | |||
| function __construct() | |||
| { | |||
| parent::__construct(); | |||
| $this->load->database(); | |||
| $this->now_str = date('Y-m-d H:i:s'); | |||
| } | |||
| public function init($vars) | |||
| { | |||
| $this->vars = $vars; | |||
| } | |||
| // 博辰通知付款完成 | |||
| public function p2payed($parms, $opay=false) | |||
| { | |||
| $result = $this->db->select("in_time, cario_no, station_no") | |||
| ->from('cario') | |||
| ->where(array('obj_type' => 1, 'obj_id' => $parms['lpr'], 'finished' => 0, 'err' => 0)) | |||
| ->order_by('cario_no', 'desc') | |||
| ->limit(1) | |||
| ->get() | |||
| ->row_array(); | |||
| // 查不到車號才找備援碼 | |||
| if(!isset($result['in_time']) && is_numeric($parms['lpr']) && strlen($parms['lpr']) == 6) | |||
| { | |||
| $result = $this->db->select("in_time, cario_no, station_no") | |||
| ->from('cario') | |||
| ->where(array('obj_type' => 1, 'ticket_no' => $parms['lpr'], 'finished' => 0, 'err' => 0)) | |||
| ->order_by('cario_no', 'desc') | |||
| ->limit(1) | |||
| ->get() | |||
| ->row_array(); | |||
| // 找不到記錄 | |||
| if(!isset($result['in_time'])) | |||
| { | |||
| trigger_error(__FUNCTION__ . '..not found..' . print_r($parms, true)); | |||
| return false; | |||
| } | |||
| $in_time = new DateTime($result['in_time']); | |||
| $pay_time = new DateTime($parms['pay_time']); | |||
| // 若間隔小於 15 分鐘, 拿現在時間來當付款時間 | |||
| $parms['pay_time'] = (($pay_time->getTimestamp() - $in_time->getTimestamp()) / 60 < 15) ? $this->now_str : $parms['pay_time']; | |||
| if($opay) | |||
| { | |||
| // A. (備援碼)歐付寶 | |||
| $parms2 = array('seqno' => $result['cario_no'], 'amt' => $parms['amt'], 'lpr' => $parms['lpr']); | |||
| return $this->m2payed($parms2); | |||
| } | |||
| else | |||
| { | |||
| // B. (備援碼)一般繳費機 | |||
| $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(array('cario_no' => $result['cario_no']))->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']}"); | |||
| return 'ok'; | |||
| } | |||
| } | |||
| // A. 歐付寶 | |||
| if($opay) | |||
| { | |||
| $parms2 = array('seqno' => $result['cario_no'], 'amt' => $parms['amt'], 'lpr' => $parms['lpr']); | |||
| $result = $this->m2payed($parms2); | |||
| if($result != 'ok') | |||
| return $result; | |||
| } | |||
| else | |||
| { | |||
| // B. 一般繳費機 | |||
| $in_time = new DateTime($result['in_time']); | |||
| $pay_time = new DateTime($parms['pay_time']); | |||
| // 若間隔小於 15 分鐘, 拿現在時間來當付款時間 | |||
| $parms['pay_time'] = (($pay_time->getTimestamp() - $in_time->getTimestamp()) / 60 < 15) ? $this->now_str : $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(array('obj_type' => 1, 'obj_id' => $parms['lpr'], 'finished' => 0, 'err' => 0)) | |||
| ->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'; | |||
| } | |||
| // 繳費機告知已付款 (new 2016/07/15) | |||
| // http://localhost/carpayment.html/ats2payed/車牌/金額/場站編號/序號/MD5 | |||
| // md5(車牌.金額.場站編號.序號) | |||
| public function ats2payed($parms) | |||
| { | |||
| $order_no = $parms['order_no']; | |||
| $bill_result = $this->db->from('tx_bill_ats') | |||
| ->where(array('order_no' => $order_no, 'status' => 111)) | |||
| ->limit(1) | |||
| ->get() | |||
| ->row_array(); | |||
| if(!empty($bill_result)){ | |||
| $member_no = $bill_result['member_no']; | |||
| $station_no = $bill_result['station_no']; | |||
| $next_start_time = $bill_result['next_start_time']; | |||
| $next_end_time = $bill_result['next_end_time']; | |||
| $data = array( | |||
| 'end_date' => $bill_result['next_end_time'] // TODO: 有被任何一筆序號蓋資料的可能 | |||
| ); | |||
| $this->db | |||
| ->where(array('member_no' => $member_no, 'station_no' => $station_no)) | |||
| ->update('members', $data); | |||
| if ($this->db->affected_rows()) | |||
| { | |||
| trigger_error("繳費機更新會員資料完成,{$parms['lpr']},金額:{$parms['amt']},序號:{$parms['order_no']}"); | |||
| return 'ok'; | |||
| } | |||
| else | |||
| { | |||
| trigger_error("繳費機更新會員資料失敗,{$parms['lpr']},金額:{$parms['amt']},序號:{$parms['order_no']}"); | |||
| return 'fail'; | |||
| } | |||
| } | |||
| } | |||
| // 行動支付, 手機告知已付款 | |||
| // http://203.75.167.89/carpayment.html/m2payed/ABC1234/120/12112/12345/1f3870be274f6c49b3e31a0c6728957f | |||
| // http://203.75.167.89/carpayment.html/m2payed/車牌/金額/場站編號/序號/MD5 | |||
| // md5(車牌.金額.場站編號.序號) | |||
| public function m2payed($parms) | |||
| { | |||
| $data = array | |||
| ( | |||
| 'out_before_time' => date('Y-m-d H:i:s', strtotime(" + 15 minutes")), | |||
| 'pay_time' => date('Y-m-d H:i:s'), | |||
| 'pay_type' => 4, // 歐付寶行動支付 | |||
| 'payed' => 1 | |||
| ); | |||
| $this->db | |||
| ->where(array('cario_no' => $parms['seqno'])) | |||
| ->update('cario', $data); | |||
| if ($this->db->affected_rows()) | |||
| { | |||
| trigger_error("歐付寶行動支付成功,{$parms['lpr']}金額:{$parms['amt']},序號:{$parms['seqno']}"); | |||
| return 'ok'; | |||
| } | |||
| else | |||
| { | |||
| trigger_error("歐付寶行動支付失敗,{$parms['lpr']}金額:{$parms['amt']},序號:{$parms['seqno']}"); | |||
| return 'fail'; | |||
| } | |||
| } | |||
| /* | |||
| 月租繳款完成 | |||
| http://203.75.167.89/carpayment.html/memberpayed/12345/ABC1234/120/12112/1/2016-01-31/1f3870be274f6c49b3e31a0c6728957f | |||
| http://203.75.167.89/carpayment.html/memberpayed/會員號碼/車牌/金額/場站編號/月繳/本期到期日/md5 | |||
| md5(會員號碼.車牌.金額.場站編號.月繳.本期到期日) | |||
| public function memberpayed($parms) | |||
| { | |||
| // update members (???) | |||
| } | |||
| */ | |||
| // 模糊比對 | |||
| function getLevenshteinSQLStatement($word, $target) | |||
| { | |||
| $words = array(); | |||
| if(strlen($word) >= 5) | |||
| { | |||
| for ($i = 0; $i < strlen($word); $i++) { | |||
| // insertions | |||
| $words[] = substr($word, 0, $i) . '_' . substr($word, $i); | |||
| // deletions | |||
| $words[] = substr($word, 0, $i) . substr($word, $i + 1); | |||
| // substitutions | |||
| //$words[] = substr($word, 0, $i) . '_' . substr($word, $i + 1); | |||
| } | |||
| } | |||
| else | |||
| { | |||
| for ($i = 0; $i < strlen($word); $i++) { | |||
| // insertions | |||
| $words[] = substr($word, 0, $i) . '_' . substr($word, $i); | |||
| } | |||
| } | |||
| // last insertion | |||
| $words[] = $word . '_'; | |||
| //return $words; | |||
| $fuzzy_statement = ' ('; | |||
| foreach ($words as $idx => $word) | |||
| { | |||
| $fuzzy_statement .= " {$target} LIKE '%{$word}%' OR "; | |||
| } | |||
| $last_or_pos = strrpos($fuzzy_statement, 'OR'); | |||
| if($last_or_pos !== false) | |||
| { | |||
| $fuzzy_statement = substr_replace($fuzzy_statement, ')', $last_or_pos, strlen('OR')); | |||
| } | |||
| return $fuzzy_statement; | |||
| } | |||
| // 取得進場資訊 (模糊比對) | |||
| function q_fuzzy_pks($word) | |||
| { | |||
| if(empty($word) || strlen($word) < 4 || strlen($word) > 10) | |||
| { | |||
| return null; | |||
| } | |||
| // 備援數字使用 | |||
| else if(is_numeric($word) && strlen($word) == 6) | |||
| { | |||
| trigger_error(__FUNCTION__ . '..備援查詢: ' . $word); | |||
| $sql = "SELECT obj_id as lpr, ticket_no | |||
| FROM cario | |||
| WHERE finished = 0 AND err = 0 | |||
| AND out_before_time > DATE_SUB(CURRENT_TIMESTAMP, INTERVAL 5 DAY) | |||
| AND ticket_no = {$word} | |||
| ORDER BY out_before_time DESC"; | |||
| $retults = $this->db->query($sql)->result_array(); | |||
| return $retults; | |||
| } | |||
| $fuzzy_statement = $this->getLevenshteinSQLStatement($word, 'obj_id'); | |||
| //trigger_error("模糊比對 {$word} where: {$fuzzy_statement}"); | |||
| $sql = "SELECT obj_id as lpr, ticket_no | |||
| FROM cario | |||
| WHERE {$fuzzy_statement} AND finished = 0 AND err = 0 | |||
| AND out_before_time > DATE_SUB(CURRENT_TIMESTAMP, INTERVAL 5 DAY) | |||
| GROUP BY obj_id | |||
| ORDER BY out_before_time DESC"; | |||
| $retults = $this->db->query($sql)->result_array(); | |||
| return $retults; | |||
| } | |||
| // 建立博辰查詢入場時間資料 (by ticket_no) | |||
| function gen_query_data_type4($ticket_no) | |||
| { | |||
| $data = array(); | |||
| // s2. 完整車牌號碼: 右邊補空格補滿7碼 | |||
| $data['lpr'] = $ticket_no; | |||
| // s3. 塔號_車格號碼: 該車牌相關車輛所停車的停車塔號或樓層號碼, | |||
| // 地下室部分為負值例如B1為-1,平面停車場為1,二樓為2 (左邊補 ‘0’ 補滿2碼), | |||
| // 停車格號4碼(左邊補 ‘0’ 補滿4碼), | |||
| // 樓層和停車格號中間以 ‘_’ 分隔,例如:”01_0101” | |||
| $data['seat_no'] = 'XX_XXXX'; | |||
| $data['ticket'] = 0; | |||
| $data['start_date'] = '2000/01/01'; | |||
| $data['end_date'] = '2000/01/01'; | |||
| $data['start_time'] = '00:00'; | |||
| $data['end_time'] = '00:00'; | |||
| $result = $this->db->select("in_time, date_format(pay_time, '%Y/%m/%d %T') as pay_time, in_pic_name, member_no") | |||
| ->from('cario') | |||
| ->where(array('obj_type' => 1, 'ticket_no' => $ticket_no, 'finished' => 0, 'err' => 0)) | |||
| ->order_by('cario_no', 'desc') | |||
| ->limit(1) | |||
| ->get() | |||
| ->row_array(); | |||
| if (!empty($result['in_time'])) | |||
| { | |||
| // s5. 入場時間: 格式為"yyyy/MM/dd HH:mm:ss",時間為24小時制,若無紀錄秒數秒數部分可填”00” | |||
| $data['in_time'] = $result['in_time']; | |||
| // s6. 入場車牌圖片路徑: 貴公司的絕對路徑,我方使用網路芳鄰或FTP下載 | |||
| $pic_name_arr = explode('-', $result['in_pic_name']); | |||
| $date_num = substr($pic_name_arr[7], 0, 8); | |||
| $data['in_pic_name'] = "\\\\192.168.10.201\\pics\\{$date_num}\\{$result['in_pic_name']}"; | |||
| // s7. 繳費時間: 無繳費時間時為"2000/01/01 00:00:00",格式為"yyyy/MM/dd HH:mm:ss",時間為24小時制,若無紀錄秒數秒數部分可填”00” | |||
| $data['pay_time'] = !empty($result['pay_time']) ? $result['pay_time'] : '2000/01/01 00:00:00'; | |||
| } | |||
| else | |||
| { | |||
| $data['in_time'] = ''; | |||
| $data['in_pic_name'] = ''; | |||
| $data['pay_time'] = '2000/01/01 00:00:00'; | |||
| } | |||
| return $data; | |||
| } | |||
| // 建立博辰查詢入場時間資料 | |||
| function gen_query_data($lpr) | |||
| { | |||
| $data = array(); | |||
| // s2. 完整車牌號碼: 右邊補空格補滿7碼 | |||
| $data['lpr'] = $lpr; //str_pad($lpr, 7, ' ', STR_PAD_RIGHT); | |||
| // s3. 塔號_車格號碼: 該車牌相關車輛所停車的停車塔號或樓層號碼, | |||
| // 地下室部分為負值例如B1為-1,平面停車場為1,二樓為2 (左邊補 ‘0’ 補滿2碼), | |||
| // 停車格號4碼(左邊補 ‘0’ 補滿4碼), | |||
| // 樓層和停車格號中間以 ‘_’ 分隔,例如:”01_0101” | |||
| $sql = "select p.pksno, m.group_id | |||
| from pks p, pks_group_member m, pks_groups g | |||
| where p.pksno = m.pksno | |||
| and m.group_id = g.group_id | |||
| and g.group_type = 1 | |||
| and p.lpr = '{$lpr}' | |||
| limit 1"; | |||
| $rows = $this->db->query($sql)->row_array(); | |||
| if (!empty($rows['pksno'])) | |||
| { | |||
| $data['seat_no'] = ($rows['group_id'] == 'B1' ? '-1' : '0' . substr($rows['group_id'], -1)) . '_0' . substr($rows['pksno'], -3); | |||
| } | |||
| else | |||
| { | |||
| $data['seat_no'] = 'XX_XXXX'; // '-1_0028'; | |||
| } | |||
| // 查詢是否月租會員 | |||
| $result = $this->db->select("date_format(start_date, '%Y/%m/%d') as start_date, date_format(end_date,'%Y/%m/%d') as end_date") | |||
| ->from('members') | |||
| ->where(array( | |||
| 'lpr' => $lpr, | |||
| 'start_date <' => $this->vars['date_time'], | |||
| 'end_date >=' => $this->vars['date_time']) | |||
| , false) | |||
| ->limit(1) | |||
| ->get() | |||
| ->row_array(); | |||
| if (!empty($result['start_date'])) // 月租會員 | |||
| { | |||
| $data['ticket'] = 1; // s4. 是否為月票: 0:非月票, 1:月票 | |||
| $data['start_date'] = $result['start_date'];// s8. 有效起始時間: 非月票時為"2000/01/01", 格式為"yyyy/MM/dd" | |||
| $data['end_date'] = $result['end_date']; // s9. 有效截止日期: 非月票時為"2000/01/01", 格式為"yyyy/MM/dd" | |||
| $data['start_time'] = '00:00'; // s10. 使用起始時段: 非月票時為"00:00", 格式為"HH:mm" | |||
| $data['end_time'] = '23:59'; // s11. 使用結束時段: 非月票時為"00:00", 格式為"HH:mm" | |||
| } | |||
| else // 臨停車 | |||
| { | |||
| $data['ticket'] = 0; | |||
| $data['start_date'] = '2000/01/01'; | |||
| $data['end_date'] = '2000/01/01'; | |||
| $data['start_time'] = '00:00'; | |||
| $data['end_time'] = '00:00'; | |||
| } | |||
| $result = $this->db->select("in_time, date_format(pay_time, '%Y/%m/%d %T') as pay_time, in_pic_name, member_no") | |||
| ->from('cario') | |||
| ->where(array('obj_type' => 1, 'obj_id' => $lpr, 'finished' => 0, 'err' => 0)) | |||
| ->order_by('cario_no', 'desc') | |||
| ->limit(1) | |||
| ->get() | |||
| ->row_array(); | |||
| if (!empty($result['in_time'])) | |||
| { | |||
| // s5. 入場時間: 格式為"yyyy/MM/dd HH:mm:ss",時間為24小時制,若無紀錄秒數秒數部分可填”00” | |||
| $data['in_time'] = $result['in_time']; | |||
| // s6. 入場車牌圖片路徑: 貴公司的絕對路徑,我方使用網路芳鄰或FTP下載 | |||
| $pic_name_arr = explode('-', $result['in_pic_name']); | |||
| $date_num = substr($pic_name_arr[7], 0, 8); | |||
| $data['in_pic_name'] = "\\\\192.168.10.201\\pics\\{$date_num}\\{$result['in_pic_name']}"; | |||
| // s7. 繳費時間: 無繳費時間時為"2000/01/01 00:00:00",格式為"yyyy/MM/dd HH:mm:ss",時間為24小時制,若無紀錄秒數秒數部分可填”00” | |||
| $data['pay_time'] = !empty($result['pay_time']) ? $result['pay_time'] : '2000/01/01 00:00:00'; | |||
| } | |||
| else | |||
| { | |||
| $data['in_time'] = ''; | |||
| $data['in_pic_name'] = ''; | |||
| $data['pay_time'] = '2000/01/01 00:00:00'; | |||
| } | |||
| return $data; | |||
| } | |||
| // 博辰查詢入場時間 (fuzzy) | |||
| public function query_in_fuzzy($lpr) | |||
| { | |||
| $fuzzy_result = $this->q_fuzzy_pks($lpr); | |||
| if(!empty($fuzzy_result) && count($fuzzy_result) > 0) | |||
| { | |||
| $data = array(); | |||
| // s2 ~ s11 的資料會因模糊比對筆數增加或減少而增減 | |||
| foreach ($fuzzy_result as $idx => $rows) | |||
| { | |||
| $lpr = $rows['lpr']; | |||
| $ticket_no = $rows['ticket_no']; | |||
| if($lpr == 'NONE') | |||
| { | |||
| $tmp_data = $this->gen_query_data_type4($ticket_no); // 備緩搜尋 | |||
| } | |||
| else | |||
| { | |||
| $tmp_data = $this->gen_query_data($lpr); // 模糊搜尋 | |||
| } | |||
| if($tmp_data['in_time'] == '') | |||
| { | |||
| // 若查無入場時間, 直接乎略這筆 | |||
| trigger_error("查無入場時間, 直接乎略這筆[{$lpr}]:".print_r($rows, true)); | |||
| } | |||
| else | |||
| { | |||
| $data['results'][$idx] = $tmp_data; | |||
| } | |||
| } | |||
| $data['count'] = count($fuzzy_result); | |||
| } | |||
| else | |||
| { | |||
| $data_0 = array(); | |||
| $data_0['lpr'] = str_pad($lpr, 7, ' ', STR_PAD_RIGHT); | |||
| $data_0['seat_no'] = 'XX_XXXX'; | |||
| $data_0['ticket'] = 0; | |||
| $data_0['start_date'] = '2000/01/01'; | |||
| $data_0['end_date'] = '2000/01/01'; | |||
| $data_0['start_time'] = '00:00'; | |||
| $data_0['end_time'] = '00:00'; | |||
| $data_0['in_time'] = ''; | |||
| $data_0['pay_time'] = '2000/01/01 00:00:00'; | |||
| $data_0['in_pic_name'] = ''; | |||
| $data = array(); | |||
| $data['results'][0] = $data_0; | |||
| $data['count'] = 0; | |||
| } | |||
| trigger_error("fuzzy aps查詢入場時間[{$lpr}]:".print_r($data, true)); | |||
| return $data; | |||
| } | |||
| // 博辰查詢入場時間 | |||
| public function query_in($lpr) | |||
| { | |||
| $data = array(); | |||
| // 讀取樓層數, group_type = 2為樓層 | |||
| $sql = "select p.pksno, m.group_id | |||
| from pks p, pks_group_member m, pks_groups g | |||
| where p.pksno = m.pksno | |||
| and m.group_id = g.group_id | |||
| and g.group_type = 1 | |||
| and p.lpr = '{$lpr}' | |||
| limit 1"; | |||
| $rows = $this->db->query($sql)->row_array(); | |||
| if (!empty($rows['pksno'])) | |||
| { | |||
| $data['seat_no'] = ($rows['group_id'] == 'B1' ? '-1' : '0' . substr($rows['group_id'], -1)) . '_' . substr($rows['pksno'], -3); | |||
| } | |||
| else | |||
| { | |||
| $data['seat_no'] = 'XX_XXXX'; | |||
| } | |||
| // 查詢是否月租會員 | |||
| $result = $this->db->select("date_format(start_date, '%Y/%m/%d') as start_date, date_format(end_date,'%Y/%m/%d') as end_date") | |||
| ->from('members') | |||
| ->where(array('lpr' => $lpr, 'end_date >=' => $this->vars['date_time']), false) | |||
| ->limit(1) | |||
| ->get() | |||
| ->row_array(); | |||
| if (!empty($result['start_date'])) // 月租會員 | |||
| { | |||
| $data['ticket'] = 1; | |||
| $data['start_date'] = $result['start_date']; | |||
| $data['end_date'] = $result['end_date']; | |||
| $data['start_time'] = '00:00'; | |||
| $data['end_time'] = '23:59'; | |||
| } | |||
| else // 臨停車 | |||
| { | |||
| $data['ticket'] = 0; | |||
| $data['start_date'] = '2000/01/01'; | |||
| $data['end_date'] = '2000/01/01'; | |||
| $data['start_time'] = '00:00'; | |||
| $data['end_time'] = '00:00'; | |||
| } | |||
| $result = $this->db->select("in_time, date_format(pay_time, '%Y/%m/%d %T') as pay_time, in_pic_name, member_no") | |||
| ->from('cario') | |||
| ->where(array('obj_type' => 1, 'obj_id' => $lpr, 'finished' => 0, 'err' => 0)) | |||
| ->order_by('cario_no', 'desc') | |||
| ->limit(1) | |||
| ->get() | |||
| ->row_array(); | |||
| if (!empty($result['in_time'])) | |||
| { | |||
| trigger_error("aps查詢入場時間|{$lpr}|{$result['in_time']}|{$result['in_pic_name']}"); | |||
| $data['in_time'] = $result['in_time']; | |||
| $data['pay_time'] = !empty($result['pay_time']) ? $result['pay_time'] : '2000/01/01 00:00:00'; | |||
| $pic_name_arr = explode('-', $result['in_pic_name']); | |||
| $date_num = substr($pic_name_arr[7], 0, 8); | |||
| //$data['in_pic_name'] = "\\\\192.168.10.201\\pics\\{$date_num}\\{$result['in_pic_name']}"; // 2016/07/25 update | |||
| //$data['in_pic_name'] = "D:/altob/home/data/parkings/cars/pics/{$date_num}/{$result['in_pic_name']}"; // 2016/07/25 update | |||
| $data['in_pic_name'] = "\\\\192.168.10.201\\pics\\{$date_num}\\{$result['in_pic_name']}"; // 2016/07/25 update | |||
| // $data['in_pic_name'] = "{$date_num}/{$result['in_pic_name']}"; | |||
| $data['records'] = 1; | |||
| } | |||
| else | |||
| { | |||
| $data['in_time'] = ''; | |||
| $data['pay_time'] = '2000/01/01 00:00:00'; | |||
| $data['in_pic_name'] = ''; | |||
| $data['records'] = 0; | |||
| } | |||
| trigger_error("aps查詢入場時間[{$lpr}]:".print_r($data, true)); | |||
| // return array('in_time' => '', 'in_pic_name' => '', 'records' => 0, 'ticket' => 0, 'seat_no' => 'XX_XXXX'); | |||
| return $data; | |||
| } | |||
| // 行動設備查詢入場時間 | |||
| // http://203.75.167.89/carpayment.html/m2query_in/ABC1234/12112/1f3870be274f6c49b3e31a0c6728957f | |||
| // http://203.75.167.89/carpayment.html/m2query_in/車牌/場站編號/MD5 | |||
| // 回傳0: 失敗, 成功: 12345,60(第一欄位非0數字代表成功, 第二欄位為金額), 此值在付款時必需傳回, 否則視為非法 | |||
| public function m2query_in($parms) | |||
| { | |||
| $result = $this->db->select('cario_no, out_before_time') | |||
| ->from('cario') | |||
| ->where(array('obj_type' => 1, 'obj_id' => $parms['lpr'], 'station_no' => $parms['station_no'], 'finished' => 0, 'err' => 0)) | |||
| ->order_by('cario_no', 'desc') | |||
| ->limit(1) | |||
| ->get() | |||
| ->row_array(); | |||
| if (!empty($result['cario_no'])) | |||
| { | |||
| trigger_error("行動設備查詢入場時間成功|{$lpr}|{$result['cario_no']}|{$result['in_time']}"); | |||
| // call計費模組 | |||
| $amt = 10; | |||
| } | |||
| else | |||
| { | |||
| $result['cario_no'] = 0; | |||
| $amt = 0; | |||
| trigger_error('行動設備查詢入場時間失敗'.print_r($parms, true)); | |||
| } | |||
| return "{$result['cario_no']},{$amt}"; | |||
| } | |||
| // 臨停未結清單 | |||
| public function cario_temp_not_finished_query_all($station_no, $q_item, $q_str) | |||
| { | |||
| $where_station = $station_no == 0 ? '' : " station_no = {$station_no} and "; // 如為0, 則全部場站讀取 | |||
| switch($q_item) | |||
| { | |||
| case 'in_time': | |||
| $items = "{$q_item} >="; | |||
| $q_str .= ' 23:59:59'; | |||
| break; | |||
| case 'lpr': | |||
| $items = "{$q_item} like "; | |||
| $q_str = strtoupper($q_str).'%'; | |||
| break; | |||
| default: | |||
| $items = "{$q_item} like "; | |||
| $q_str .= '%'; | |||
| break; | |||
| } | |||
| $sql = " | |||
| SELECT | |||
| cario_no, | |||
| station_no, | |||
| obj_id as lpr, | |||
| in_time, | |||
| out_before_time, | |||
| pay_time | |||
| FROM cario | |||
| WHERE | |||
| {$where_station} {$items} '{$q_str}' | |||
| and obj_type = 1 and finished = 0 and err = 0 and confirms = 0 | |||
| and member_no = 0 | |||
| and out_time is null | |||
| ORDER BY cario.cario_no asc | |||
| "; | |||
| //trigger_error(__FUNCTION__ . "test sql: {$sql}"); | |||
| $results = $this->db->query($sql)->result_array(); | |||
| return $results; | |||
| } | |||
| } | |||
| @@ -0,0 +1,185 @@ | |||
| <?php | |||
| /* | |||
| file: Ctbcbank_model.php 付費系統 (CTBC 中國信託) | |||
| */ | |||
| class Ctbcbank_model extends CI_Model | |||
| { | |||
| function __construct() | |||
| { | |||
| parent::__construct(); | |||
| $this->load->database(); | |||
| /* | |||
| // ----- 中國信託 - 測試環境 ----- | |||
| define('CTBC_SSLAuthUI', "https://testepos.ctbcbank.com/auth/SSLAuthUI.jsp"); // URL授權介面 | |||
| define('CTBC_TYPE1_merID', "10063"); // 特店編號 (交易類型:一般授權) | |||
| define('CTBC_TYPE1_MerchantID', "8220276806667"); // 銀行所授與的特店代號,純數字,固定 13 碼。 | |||
| define('CTBC_TYPE1_TerminalID', "90008466"); // 銀行所授與的終端機代號,純數字,固定 8 碼。 | |||
| define('CTBC_TYPE1_Key', "ZQFsGRIzb7NqsPcWOLKOL3sj"); // 壓碼 (可由後台重新產生) | |||
| define('CTBC_TYPE2_merID', "10064"); // 特店編號 (交易類型:分期付款) | |||
| define('CTBC_TYPE2_MerchantID', "8220878791047"); | |||
| define('CTBC_TYPE2_TerminalID', "91001008"); | |||
| define('CTBC_TYPE3_merID', "10065"); // 特店編號 (交易類型:紅利折抵) | |||
| define('CTBC_TYPE3_MerchantID', "8220800211437"); | |||
| define('CTBC_TYPE3_TerminalID', "92000235"); | |||
| // ----- 中國信託 - 測試環境 (END) ----- | |||
| */ | |||
| // ----- 中國信託 - 正式環境 ----- | |||
| define('CTBC_SSLAuthUI', "https://epos.chinatrust.com.tw/auth/SSLAuthUI.jsp"); // URL授權介面 | |||
| define('CTBC_TYPE1_merID', "10012"); // 特店編號 (交易類型:一般授權) | |||
| define('CTBC_TYPE1_MerchantID', "8220131400023"); // 銀行所授與的特店代號,純數字,固定 13 碼。 | |||
| define('CTBC_TYPE1_TerminalID', "99810789"); // 銀行所授與的終端機代號,純數字,固定 8 碼。 | |||
| define('CTBC_TYPE1_Key', "4qH0cNXhsmk6jKdTT4hjwYCX"); // 壓碼 (可由後台重新產生) | |||
| // ----- 中國信託 - 正式環境 (END) ----- | |||
| } | |||
| // 3.中國信託 | |||
| public function transfer_money_ctbc($data, $return_url) | |||
| { | |||
| try{ | |||
| $lidm = $data['order_no']; // 訂單編號 (<=19 碼) | |||
| $purchAmt = $data['amt']; | |||
| $txType = "0"; // 交易方式,長度為一碼數字。(一般交易:0, 分期交易:1, 紅利折抵一般交易:2, 紅利折抵分期交易:4) | |||
| $debug = "0"; // 預設(進行交易時)請填0,偵錯時請填1。 | |||
| // 使用 CTBCAgent | |||
| include_once(ALTOB_CTBC_FILE); | |||
| $oCTBCAgent = new CTBCAgent(); | |||
| $oCTBCAgent->MerchantID = CTBC_TYPE1_MerchantID; | |||
| $oCTBCAgent->TerminalID = CTBC_TYPE1_TerminalID; | |||
| $oCTBCAgent->AuthResURL = $return_url;// 從收單行端取得授權碼後,要導回的網址,請勿填入特殊字元@、#、%、?、&等。 | |||
| $oCTBCAgent->SSLAuthUI = CTBC_SSLAuthUI; // URL授權介面 | |||
| $oCTBCAgent->Option = "1"; // 一般交易請填「1」。 , 分期交易請填一到兩碼的分期期數。, 紅利交易請填固定兩碼的產品代碼。, 紅利分期交易請填第一至二碼固定為產品代碼,第三碼或三至四碼為分期期數。 | |||
| $oCTBCAgent->Key = CTBC_TYPE1_Key; | |||
| $oCTBCAgent->MerchantName = iconv("UTF-8", "big5", "歐特儀停車場"); | |||
| $oCTBCAgent->OrderDetail = iconv("UTF-8", "big5", "歐Pa卡"); | |||
| $oCTBCAgent->AutoCap = "1"; // (0–不自動請款, 1–自動請款) | |||
| $oCTBCAgent->Customize = "1"; // 設定刷卡頁顯示特定語系或客制化頁面。(1–繁體中文, 2–簡體中文, 3–英文, 5–客制化頁面) | |||
| $data = array( | |||
| 'merID' => CTBC_TYPE1_merID, | |||
| 'lidm' => $lidm, | |||
| 'purchAmt' => $purchAmt, | |||
| 'txType' => $txType, | |||
| 'debug' => $debug, | |||
| 'target' => "_self" | |||
| ); | |||
| $oCTBCAgent->CheckOut($data); | |||
| }catch (Exception $e){ | |||
| // 例外錯誤處理。 | |||
| throw $e; | |||
| } | |||
| } | |||
| // 3.中國信託 - 回傳 | |||
| public function ctbcbank_return_handler($resenc, $merid) | |||
| { | |||
| try{ | |||
| // 使用 CTBCAgent | |||
| include_once(ALTOB_CTBC_FILE); | |||
| $oCTBCAgent = new CTBCAgent(); | |||
| $oCTBCAgent->Key = CTBC_TYPE1_Key; | |||
| $debug = "0"; | |||
| // 解密 | |||
| $data = array( | |||
| 'encRes' => $resenc, | |||
| 'debug' => $debug | |||
| ); | |||
| $EncArray = $oCTBCAgent->Decrypt($data); | |||
| /* | |||
| foreach($EncArray AS $name => $val){ | |||
| echo $name ."=>". urlencode(trim($val,"\x00..\x08")) ."\n"; | |||
| } | |||
| */ | |||
| $errdesc = isset($EncArray['errdesc']) ? $EncArray['errdesc'] : ""; | |||
| $authresurl = isset($EncArray['authresurl']) ? $EncArray['authresurl'] : ""; | |||
| $xid = isset($EncArray['xid']) ? $EncArray['xid'] : ""; | |||
| $awardedpoint = isset($EncArray['awardedpoint']) ? $EncArray['awardedpoint'] : ""; | |||
| $status = isset($EncArray['status']) ? $EncArray['status'] : ""; | |||
| $errcode = isset($EncArray['errcode']) ? $EncArray['errcode'] : ""; | |||
| $authcode = isset($EncArray['authcode']) ? $EncArray['authcode'] : ""; | |||
| $authamt = isset($EncArray['authamt']) ? $EncArray['authamt'] : ""; | |||
| $lidm = isset($EncArray['lidm']) ? $EncArray['lidm'] : ""; | |||
| $offsetamt = isset($EncArray['offsetamt']) ? $EncArray['offsetamt'] : ""; | |||
| $originalamt = isset($EncArray['originalamt']) ? $EncArray['originalamt'] : ""; | |||
| $utilizedpoint = isset($EncArray['utilizedpoint']) ? $EncArray['utilizedpoint'] : ""; | |||
| $numberofpay = isset($EncArray['numberofpay']) ? $EncArray['numberofpay'] : ""; // option: 一般交易, 分期交易 | |||
| $prodcode = isset($EncArray['prodcode']) ? $EncArray['prodcode'] : ""; // option: 紅利交易 | |||
| $last4digitpan = isset($EncArray['last4digitpan']) ? $EncArray['last4digitpan'] : ""; | |||
| $pidresult= isset($EncArray['pidresult']) ? $EncArray['pidresult'] : ""; | |||
| $cardnumber = isset($EncArray['cardnumber']) ? $EncArray['cardnumber'] : ""; | |||
| $outmac = isset($EncArray['outmac']) ? $EncArray['outmac'] : ""; | |||
| $data = array( | |||
| 'status' => $status, | |||
| 'errcode' => $errcode, | |||
| 'authcode' => $authcode, | |||
| 'authamt' => $authamt, | |||
| 'lidm' => $lidm, | |||
| 'offsetamt' => $offsetamt, | |||
| 'originalamt' => $originalamt, | |||
| 'utilizedpoint' => $utilizedpoint, | |||
| 'numberofpay' => $numberofpay, | |||
| 'prodcode' => $prodcode, | |||
| 'last4digitpan' => $last4digitpan, | |||
| 'debug' => $debug | |||
| ); | |||
| // 取得 check mac | |||
| $MACString = $oCTBCAgent->CheckMac($data); | |||
| //echo "checkm=$MACString\n"; | |||
| //echo "outmac=$outmac\n"; | |||
| // 驗証內容正確性 | |||
| if(strcmp($MACString, $outmac) == 0){ | |||
| $data = array( | |||
| 'errdesc' => $errdesc, | |||
| 'authresurl' => $authresurl, | |||
| 'xid' => $xid, | |||
| 'awardedpoint' => $awardedpoint, | |||
| 'prodcode' => $prodcode, | |||
| 'merid' => $merid, | |||
| 'status' => $status, | |||
| 'errcode' => $errcode, | |||
| 'authcode' => $authcode, | |||
| 'authamt' => $authamt, | |||
| 'lidm' => $lidm, | |||
| 'offsetamt' => $offsetamt, | |||
| 'originalamt' => $originalamt, | |||
| 'utilizedpoint' => $utilizedpoint, | |||
| 'numberofpay' => $numberofpay, | |||
| 'last4digitpan' => $last4digitpan, | |||
| 'pidresult' => $pidresult, | |||
| 'cardnumber' => $cardnumber, | |||
| 'outmac' => $outmac | |||
| ); | |||
| }else{ | |||
| // CHECK MAC FAIL | |||
| $data = array( | |||
| 'errdesc' => "[CHECK MAC FAIL] MACString=$MACString", | |||
| 'merid' => $merid, | |||
| 'outmac' => $outmac | |||
| ); | |||
| } | |||
| $this->db->insert('ctbc_feedback_log', $data); // 記錄 log | |||
| return $data; | |||
| }catch (Exception $e){ | |||
| // 例外錯誤處理。 | |||
| trigger_error(__FUNCTION__.$e->getMessage()); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,265 @@ | |||
| <?php | |||
| /* | |||
| file: Excel_model.php 匯出報表專用 | |||
| */ | |||
| class Excel_model extends CI_Model | |||
| { | |||
| function __construct() | |||
| { | |||
| parent::__construct(); | |||
| $this->load->database(); | |||
| $this->now_str = date('Y-m-d H:i:s'); | |||
| ini_set('max_execution_time','300'); | |||
| ini_set('memory_limit','512M'); | |||
| } | |||
| public function init($vars) | |||
| { | |||
| $this->vars = $vars; | |||
| } | |||
| // 會員名單報表 | |||
| public function export_members() | |||
| { | |||
| trigger_error(EXPORT_LOG_TITLE. '..start..' . __FUNCTION__); | |||
| // 讀入廠站資料 | |||
| $sql = " | |||
| select | |||
| members.member_name as member_name, | |||
| members.lpr as lpr, | |||
| members.contract_no as contract_no, | |||
| members.start_date as start_date, | |||
| members.end_date as end_date, | |||
| members.amt as amt, | |||
| members.update_time as update_time, | |||
| members.member_attr, | |||
| members.fee_period, | |||
| members.mobile_no, | |||
| members.deposit, | |||
| members.suspended, | |||
| members.locked, | |||
| members.valid_time | |||
| from members | |||
| ORDER BY update_time DESC | |||
| "; | |||
| $results = $this->db->query($sql)->result_array(); | |||
| if(empty($results)) | |||
| { | |||
| trigger_error(EXPORT_LOG_TITLE.'..no data..' . $this->db->last_query()); | |||
| return false; | |||
| } | |||
| //$total_count = $this->db->query($sql)->num_rows(); | |||
| // 產生 Excel | |||
| $this->load->library('excel'); | |||
| $objPHPExcel = new PHPExcel(); | |||
| $objPHPExcel->setActiveSheetIndex(0); | |||
| $col_A_mapping = array('col_name' => 'A', 'col_title' => '會員名稱', 'col_type' => PHPExcel_Cell_DataType::TYPE_STRING); | |||
| $col_B_mapping = array('col_name' => 'B', 'col_title' => '車牌號碼', 'col_type' => PHPExcel_Cell_DataType::TYPE_STRING); | |||
| $col_C_mapping = array('col_name' => 'C', 'col_title' => '合約代碼', 'col_type' => PHPExcel_Cell_DataType::TYPE_STRING); | |||
| $col_D_mapping = array('col_name' => 'D', 'col_title' => '開始時間', 'col_type' => PHPExcel_Cell_DataType::TYPE_STRING); | |||
| $col_E_mapping = array('col_name' => 'E', 'col_title' => '結束時間', 'col_type' => PHPExcel_Cell_DataType::TYPE_STRING); | |||
| $col_F_mapping = array('col_name' => 'F', 'col_title' => '租金', 'col_type' => PHPExcel_Cell_DataType::TYPE_STRING); | |||
| $col_G_mapping = array('col_name' => 'G', 'col_title' => '最後更新時間', 'col_type' => PHPExcel_Cell_DataType::TYPE_STRING); | |||
| $col_H_mapping = array('col_name' => 'H', 'col_title' => '身份', 'col_type' => PHPExcel_Cell_DataType::TYPE_STRING); | |||
| $col_I_mapping = array('col_name' => 'I', 'col_title' => '繳期', 'col_type' => PHPExcel_Cell_DataType::TYPE_STRING); | |||
| $col_J_mapping = array('col_name' => 'J', 'col_title' => '電話', 'col_type' => PHPExcel_Cell_DataType::TYPE_STRING); | |||
| $col_K_mapping = array('col_name' => 'K', 'col_title' => '押金', 'col_type' => PHPExcel_Cell_DataType::TYPE_STRING); | |||
| $col_L_mapping = array('col_name' => 'L', 'col_title' => '停權 (營管操作)', 'col_type' => PHPExcel_Cell_DataType::TYPE_STRING); | |||
| $col_M_mapping = array('col_name' => 'M', 'col_title' => '鎖車 (會員操作)', 'col_type' => PHPExcel_Cell_DataType::TYPE_STRING); | |||
| $col_N_mapping = array('col_name' => 'N', 'col_title' => '有效期限 (審核後更新)', 'col_type' => PHPExcel_Cell_DataType::TYPE_STRING); | |||
| $raw_index = 1; | |||
| $objPHPExcel->getActiveSheet()->setTitle('下載'); | |||
| $objPHPExcel->getActiveSheet()->setCellValue($col_A_mapping['col_name'].$raw_index, $col_A_mapping['col_title']); | |||
| $objPHPExcel->getActiveSheet()->setCellValue($col_B_mapping['col_name'].$raw_index, $col_B_mapping['col_title']); | |||
| $objPHPExcel->getActiveSheet()->setCellValue($col_C_mapping['col_name'].$raw_index, $col_C_mapping['col_title']); | |||
| $objPHPExcel->getActiveSheet()->setCellValue($col_D_mapping['col_name'].$raw_index, $col_D_mapping['col_title']); | |||
| $objPHPExcel->getActiveSheet()->setCellValue($col_E_mapping['col_name'].$raw_index, $col_E_mapping['col_title']); | |||
| $objPHPExcel->getActiveSheet()->setCellValue($col_F_mapping['col_name'].$raw_index, $col_F_mapping['col_title']); | |||
| $objPHPExcel->getActiveSheet()->setCellValue($col_G_mapping['col_name'].$raw_index, $col_G_mapping['col_title']); | |||
| $objPHPExcel->getActiveSheet()->setCellValue($col_H_mapping['col_name'].$raw_index, $col_H_mapping['col_title']); | |||
| $objPHPExcel->getActiveSheet()->setCellValue($col_I_mapping['col_name'].$raw_index, $col_I_mapping['col_title']); | |||
| $objPHPExcel->getActiveSheet()->setCellValue($col_J_mapping['col_name'].$raw_index, $col_J_mapping['col_title']); | |||
| $objPHPExcel->getActiveSheet()->setCellValue($col_K_mapping['col_name'].$raw_index, $col_K_mapping['col_title']); | |||
| $objPHPExcel->getActiveSheet()->setCellValue($col_L_mapping['col_name'].$raw_index, $col_L_mapping['col_title']); | |||
| $objPHPExcel->getActiveSheet()->setCellValue($col_M_mapping['col_name'].$raw_index, $col_M_mapping['col_title']); | |||
| $objPHPExcel->getActiveSheet()->setCellValue($col_N_mapping['col_name'].$raw_index, $col_N_mapping['col_title']); | |||
| $warning_style = array( | |||
| //'alignment' => array('horizontal' => PHPExcel_Style_Alignment::HORIZONTAL_CENTER), | |||
| 'font' => array( | |||
| 'bold' => true, | |||
| 'color' => array('rgb' => 'FF0000'), | |||
| 'size' => 16, | |||
| 'name' => 'Verdana' | |||
| ) | |||
| ); | |||
| $hq_info = $this->vars['mcache']->get('info'); | |||
| $count = 0; | |||
| foreach($results as $rows) | |||
| { | |||
| $raw_index += 1; | |||
| $member_name = $rows['member_name']; | |||
| $lpr = $rows['lpr']; | |||
| $contract_no = $rows['contract_no'] ? $rows['contract_no'] : ''; | |||
| $start_date = $rows['start_date']; | |||
| $end_date = $rows['end_date']; | |||
| $amt = $rows['amt'] ? $rows['amt'] : '0'; | |||
| $update_time = $rows['update_time']; | |||
| $member_attr = ( empty($hq_info['member_attr']) || empty($rows['member_attr']) || empty($hq_info['member_attr'][$rows['member_attr']]) ) ? '無' : $hq_info['member_attr'][$rows['member_attr']]; | |||
| $fee_period = ( empty($hq_info['period_name']) || empty($rows['fee_period']) || empty($hq_info['period_name'][$rows['fee_period']]) ) ? '無' : $hq_info['period_name'][$rows['fee_period']]; | |||
| $mobile_no = $rows['mobile_no']; | |||
| $deposit = $rows['deposit']; | |||
| $suspended = (empty($rows['suspended'])) ? '無' : '已停權'; | |||
| $locked = (empty($rows['locked'])) ? '無' : '已鎖車'; | |||
| $valid_time = $rows['valid_time']; | |||
| $count++; | |||
| $objPHPExcel->getActiveSheet()->setCellValueExplicit($col_A_mapping['col_name'].$raw_index, $member_name, $col_A_mapping['col_type']); | |||
| $objPHPExcel->getActiveSheet()->setCellValueExplicit($col_B_mapping['col_name'].$raw_index, $lpr, $col_B_mapping['col_type']); | |||
| $objPHPExcel->getActiveSheet()->setCellValueExplicit($col_C_mapping['col_name'].$raw_index, $contract_no, $col_C_mapping['col_type']); | |||
| $objPHPExcel->getActiveSheet()->setCellValueExplicit($col_D_mapping['col_name'].$raw_index, $start_date, $col_D_mapping['col_type']); | |||
| $objPHPExcel->getActiveSheet()->setCellValueExplicit($col_E_mapping['col_name'].$raw_index, $end_date, $col_E_mapping['col_type']); | |||
| $objPHPExcel->getActiveSheet()->setCellValueExplicit($col_F_mapping['col_name'].$raw_index, $amt, $col_F_mapping['col_type']); | |||
| $objPHPExcel->getActiveSheet()->setCellValueExplicit($col_G_mapping['col_name'].$raw_index, $update_time, $col_G_mapping['col_type']); | |||
| $objPHPExcel->getActiveSheet()->setCellValueExplicit($col_H_mapping['col_name'].$raw_index, $member_attr, $col_H_mapping['col_type']); | |||
| $objPHPExcel->getActiveSheet()->setCellValueExplicit($col_I_mapping['col_name'].$raw_index, $fee_period, $col_I_mapping['col_type']); | |||
| $objPHPExcel->getActiveSheet()->setCellValueExplicit($col_J_mapping['col_name'].$raw_index, $mobile_no, $col_J_mapping['col_type']); | |||
| $objPHPExcel->getActiveSheet()->setCellValueExplicit($col_K_mapping['col_name'].$raw_index, $deposit, $col_K_mapping['col_type']); | |||
| $objPHPExcel->getActiveSheet()->setCellValueExplicit($col_L_mapping['col_name'].$raw_index, $suspended, $col_L_mapping['col_type']); | |||
| $objPHPExcel->getActiveSheet()->setCellValueExplicit($col_M_mapping['col_name'].$raw_index, $locked, $col_M_mapping['col_type']); | |||
| $objPHPExcel->getActiveSheet()->setCellValueExplicit($col_N_mapping['col_name'].$raw_index, $valid_time, $col_N_mapping['col_type']); | |||
| // 設定 style | |||
| if($valid_time != $end_date) | |||
| { | |||
| $objPHPExcel->getActiveSheet()->getStyle($col_N_mapping['col_name'].$raw_index)->applyFromArray($warning_style); | |||
| } | |||
| } | |||
| // 網站下載 | |||
| $filename_prefix = iconv('UTF-8', 'Big5', '會員資料 - '. STATION_NAME); | |||
| $filename_postfix = iconv('UTF-8', 'Big5', '(現況)'); | |||
| $objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007'); | |||
| header('Content-Type: application/vnd.ms-excel'); | |||
| header('Content-Disposition: attachment;filename="' . $filename_prefix. ' - ' . $filename_postfix . '.xlsx'); | |||
| header('Cache-Control: max-age=0'); | |||
| $objWriter->save('php://output'); | |||
| trigger_error(EXPORT_LOG_TITLE . '..completed..' . __FUNCTION__ . '|count:' . $count); | |||
| return true; | |||
| } | |||
| // 進出記錄報表 | |||
| public function export_cario_data($query_year, $query_month) | |||
| { | |||
| ini_set('max_execution_time','300'); | |||
| ini_set('memory_limit','512M'); | |||
| trigger_error(EXPORT_LOG_TITLE. '..start..' . __FUNCTION__ . "|{$query_year},{$query_month}"); | |||
| // 讀入廠站資料 | |||
| $sql = " | |||
| SELECT | |||
| cario.obj_id AS plate_no, | |||
| cario.in_time as in_time, | |||
| cario.out_time as out_time, | |||
| members.member_name as member_name, | |||
| CONCAT( FLOOR(HOUR(TIMEDIFF(cario.in_time, cario.out_time)) / 24), ' 日 ', | |||
| MOD(HOUR(TIMEDIFF(cario.in_time, cario.out_time)), 24), ' 時 ', | |||
| MINUTE(TIMEDIFF(cario.in_time, cario.out_time)), ' 分') as time_period | |||
| FROM cario | |||
| left join members on cario.member_no = members.member_no | |||
| WHERE cario.err = 0 and cario.obj_id != 'NONE' | |||
| and YEAR(cario.in_time) = {$query_year} and MONTH(cario.in_time) = {$query_month} | |||
| and cario.out_time is not null | |||
| ORDER BY cario.in_time ASC | |||
| "; | |||
| $results = $this->db->query($sql)->result_array(); | |||
| if(empty($results)) | |||
| { | |||
| trigger_error(EXPORT_LOG_TITLE.'..no data..' . $this->db->last_query()); | |||
| return false; | |||
| } | |||
| //$total_count = $this->db->query($sql)->num_rows(); | |||
| // 產生 Excel | |||
| $this->load->library('excel'); | |||
| $objPHPExcel = new PHPExcel(); | |||
| $objPHPExcel->setActiveSheetIndex(0); | |||
| $col_A_mapping = array('col_name' => 'A', 'col_title' => '車牌號碼', 'col_type' => PHPExcel_Cell_DataType::TYPE_STRING); | |||
| $col_B_mapping = array('col_name' => 'B', 'col_title' => '進場時間', 'col_type' => PHPExcel_Cell_DataType::TYPE_STRING); | |||
| $col_C_mapping = array('col_name' => 'C', 'col_title' => '離場日期', 'col_type' => PHPExcel_Cell_DataType::TYPE_STRING); | |||
| $col_D_mapping = array('col_name' => 'D', 'col_title' => '停車時數', 'col_type' => PHPExcel_Cell_DataType::TYPE_STRING); | |||
| $col_E_mapping = array('col_name' => 'E', 'col_title' => '場站名稱', 'col_type' => PHPExcel_Cell_DataType::TYPE_STRING); | |||
| $col_F_mapping = array('col_name' => 'F', 'col_title' => '會員名稱', 'col_type' => PHPExcel_Cell_DataType::TYPE_STRING); | |||
| $raw_index = 1; | |||
| $objPHPExcel->getActiveSheet()->setTitle('下載'); | |||
| $objPHPExcel->getActiveSheet()->setCellValue($col_A_mapping['col_name'].$raw_index, $col_A_mapping['col_title']); | |||
| $objPHPExcel->getActiveSheet()->setCellValue($col_B_mapping['col_name'].$raw_index, $col_B_mapping['col_title']); | |||
| $objPHPExcel->getActiveSheet()->setCellValue($col_C_mapping['col_name'].$raw_index, $col_C_mapping['col_title']); | |||
| $objPHPExcel->getActiveSheet()->setCellValue($col_D_mapping['col_name'].$raw_index, $col_D_mapping['col_title']); | |||
| $objPHPExcel->getActiveSheet()->setCellValue($col_E_mapping['col_name'].$raw_index, $col_E_mapping['col_title']); | |||
| $objPHPExcel->getActiveSheet()->setCellValue($col_F_mapping['col_name'].$raw_index, $col_F_mapping['col_title']); | |||
| $count = 0; | |||
| foreach($results as $rows) | |||
| { | |||
| $raw_index += 1; | |||
| $plate_no = $rows['plate_no']; | |||
| $in_time = $rows['in_time']; | |||
| $out_time = $rows['out_time']; | |||
| $time_period = $rows['time_period']; | |||
| $member_name = $rows['member_name'] ? $rows['member_name'] : '臨停'; | |||
| $count++; | |||
| $objPHPExcel->getActiveSheet()->setCellValueExplicit($col_A_mapping['col_name'].$raw_index, $plate_no, $col_A_mapping['col_type']); | |||
| $objPHPExcel->getActiveSheet()->setCellValueExplicit($col_B_mapping['col_name'].$raw_index, $in_time, $col_B_mapping['col_type']); | |||
| $objPHPExcel->getActiveSheet()->setCellValueExplicit($col_C_mapping['col_name'].$raw_index, $out_time, $col_C_mapping['col_type']); | |||
| $objPHPExcel->getActiveSheet()->setCellValueExplicit($col_D_mapping['col_name'].$raw_index, $time_period, $col_D_mapping['col_type']); | |||
| $objPHPExcel->getActiveSheet()->setCellValueExplicit($col_E_mapping['col_name'].$raw_index, STATION_NAME, $col_E_mapping['col_type']); | |||
| $objPHPExcel->getActiveSheet()->setCellValueExplicit($col_F_mapping['col_name'].$raw_index, $member_name, $col_F_mapping['col_type']); | |||
| } | |||
| // 儲存檔案 | |||
| /* | |||
| $filename_prefix = iconv('UTF-8', 'Big5', '車牌號碼進出記錄 - '. STATION_NAME); | |||
| $filename_postfix = iconv('UTF-8', 'Big5', $query_year . '年' .$query_month.'月份'); | |||
| $objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007'); | |||
| $objWriter->save(EXPORT_BASE.$filename_prefix.' - '.$filename_postfix.'.xlsx'); | |||
| */ | |||
| // 網站下載 | |||
| $filename_prefix = iconv('UTF-8', 'Big5', '車牌號碼進出記錄 - '. STATION_NAME); | |||
| $filename_postfix = iconv('UTF-8', 'Big5', $query_year . '年' .$query_month.'月份'); | |||
| $objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007'); | |||
| header('Content-Type: application/vnd.ms-excel'); | |||
| header('Content-Disposition: attachment;filename="' . $filename_prefix. ' - ' . $filename_postfix . '.xlsx'); | |||
| header('Cache-Control: max-age=0'); | |||
| $objWriter->save('php://output'); | |||
| trigger_error(EXPORT_LOG_TITLE . '..completed..' . __FUNCTION__ . '|count:' . $count); | |||
| return true; | |||
| } | |||
| } | |||
| @@ -0,0 +1,60 @@ | |||
| <?php | |||
| /* | |||
| file: Landb_model.php 撈區網資料庫 | |||
| */ | |||
| class Landb_model extends CI_Model | |||
| { | |||
| function __construct() | |||
| { | |||
| parent::__construct(); | |||
| // 資料庫連線 | |||
| //$dsn_old_db = 'mysqli://root:HISHARP@192.168.0.2:3306/parking'; | |||
| //$this->dsn_old_db = $this->load->database($dsn_old_db, true); | |||
| $this->now_str = date('Y-m-d H:i:s'); | |||
| } | |||
| // test | |||
| public function test($lpr) | |||
| { | |||
| $result = $lpr.' @ '. $this->now_str.' @ '; | |||
| $sql = "SELECT ParkingNum as pksno, LPR as lpr | |||
| FROM table_carpark where lpr = 'xxx'"; | |||
| $dsn_old_db = $this->load->database('old_db', true); | |||
| /* | |||
| $config['hostname'] = '192.168.0.2'; | |||
| $config['port'] = "3306"; | |||
| $config['username'] = 'root'; | |||
| $config['password'] = 'HISHARP'; | |||
| $config['database'] = 'parking'; | |||
| $config['dbdriver'] = 'mysqli'; | |||
| $config['dbprefix'] = ''; | |||
| $config['pconnect'] = FALSE; | |||
| $config['db_debug'] = TRUE; | |||
| $config['cache_on'] = FALSE; | |||
| $config['cachedir'] = ''; | |||
| $config['char_set'] = 'utf8'; | |||
| $config['dbcollat'] = 'utf8_general_ci'; | |||
| $dsn_old_db = $this->load->database($config, true); | |||
| */ | |||
| $retults = $dsn_old_db->query($sql)->result_array(); | |||
| //$retults = $this->dsn_old_db->query($sql)->result_array(); | |||
| $seat_no = ''; | |||
| if(!empty($retults[0])) | |||
| { | |||
| $seat_no = '-'.substr($retults[0]['pksno'], 0, 1).'_'.substr($retults[0]['pksno'], 1); | |||
| } | |||
| return | |||
| 'result >>>>>' . $result . '@' . '<br/>'. | |||
| $sql . '<br/>'. | |||
| json_encode($retults, true).'<br/>'. | |||
| $seat_no; | |||
| } | |||
| } | |||
| @@ -0,0 +1,194 @@ | |||
| <?php | |||
| /* | |||
| file: Parkingquery_model.php 停車管理系統(提供資策會使用) | |||
| */ | |||
| class Parkingquery_model extends CI_Model | |||
| { | |||
| function __construct() | |||
| { | |||
| parent::__construct(); | |||
| $this->load->database(); | |||
| } | |||
| public function init($vars) | |||
| { | |||
| // do nothing | |||
| } | |||
| // 查詢各樓層剩餘車位 | |||
| // http://203.75.167.89/parkingquery.html/check_space/12345 | |||
| public function check_space($seqno) | |||
| { | |||
| $data = array(); | |||
| $results = $this->db->select('group_id, availables, tot') | |||
| ->from('pks_groups') | |||
| ->where('group_type', 1) | |||
| ->get() | |||
| ->result_array(); | |||
| foreach($results as $idx => $rows) | |||
| { | |||
| $data['result']['floor'][$idx] = array | |||
| ( | |||
| 'floor_name' => $rows['group_id'], | |||
| 'valid_count' => $rows['availables'], | |||
| 'total_count' => $rows['tot'] | |||
| ); | |||
| } | |||
| return $data; | |||
| } | |||
| // 停車位置查詢(板橋好停車) | |||
| // http://203.75.167.89/parkingquery.html/check_location/ABC1234 | |||
| public function check_location($lpr) | |||
| { | |||
| $lpr = strtoupper($lpr); // 一律轉大寫 | |||
| $data = array(); | |||
| $rows = $this->db->select('pksno, pic_name') | |||
| ->from('pks') | |||
| ->where('lpr', $lpr) | |||
| ->limit(1) | |||
| ->get() | |||
| ->row_array(); | |||
| if (!empty($rows['pksno'])) | |||
| { | |||
| $data['result']['num'] = $lpr; | |||
| $data['result']['location_no'] = "{$rows['pksno']}"; | |||
| $data['result_code'] = 'OK'; | |||
| $data['result']['pic_name'] = $rows['pic_name']; | |||
| } | |||
| else // 查無資料, 啟用模糊比對 | |||
| { | |||
| // 讀取最近一筆入場資料 | |||
| $rows_cario = $this->db | |||
| ->select('cario_no') | |||
| ->from('cario') | |||
| ->where(array('in_out' => 'CI', 'obj_id' => $lpr, 'finished' => 0, 'err' => 0, 'out_time IS NULL' => null)) | |||
| ->order_by('cario_no', 'desc') | |||
| ->limit(1) | |||
| ->get() | |||
| ->row_array(); | |||
| // 有入場記錄, 直接猜在頂樓 | |||
| if (!empty($rows_cario['cario_no'])) | |||
| { | |||
| $data['result']['num'] = $lpr; | |||
| $data['result']['location_no'] = "7000"; | |||
| $data['result_code'] = 'OK'; | |||
| } | |||
| else | |||
| { | |||
| $data['result']['num'] = $lpr; | |||
| $data['result']['location_no'] = '0'; | |||
| $data['result_code'] = 'FAIL'; | |||
| } | |||
| } | |||
| return $data; | |||
| } | |||
| // 空車位導引 | |||
| // http://203.75.167.89/parkingquery.html/get_valid_seat | |||
| // 註記現在時間, 並保留10分鐘 | |||
| public function get_valid_seat($pksno) | |||
| { | |||
| $data = array(); | |||
| $this->db->trans_start(); | |||
| if ($pksno > 0) // 限制從某一個車位開始指派車位 | |||
| { | |||
| $sql = "select pksno from pks where status = 'VA' and pksno >= {$pksno} and prioritys != 0 and (book_time is null or book_time <= now()) order by prioritys asc limit 1 for update;"; | |||
| } | |||
| else | |||
| { | |||
| $sql = "select pksno from pks where status = 'VA' and prioritys != 0 and (book_time is null or book_time <= now()) order by prioritys asc limit 1 for update;"; | |||
| } | |||
| $rows = $this->db->query($sql)->row_array(); | |||
| if (!empty($rows['pksno'])) | |||
| { | |||
| $data['result']['location_no'] = "{$rows['pksno']}"; | |||
| $data['result_code'] = 'OK'; | |||
| $sql = "update pks set book_time = addtime(now(), '00:10:00') where pksno = {$rows['pksno']};"; | |||
| $this->db->query($sql); | |||
| } | |||
| else | |||
| { | |||
| $data['result']['location_no'] = '0'; | |||
| $data['result_code'] = 'FAIL'; | |||
| } | |||
| $this->db->trans_complete(); | |||
| return $data; | |||
| } | |||
| // 緊急求救 | |||
| // http://203.75.167.89/parkingquery.html/send_sos/B2/111/123 | |||
| public function send_sos($floor, $x, $y) | |||
| { | |||
| $data = array | |||
| ( | |||
| 'result' => array('send_from' => array('floor' => $floor, 'x' => $x, 'y' => $y)), | |||
| 'result_code' => 'OK' | |||
| ); | |||
| return $data; | |||
| } | |||
| // 防盜鎖車 | |||
| // http://203.75.167.89/parkingquery.html/security_action/ABC1234/pswd/2 | |||
| public function security_action($lpr, $pswd, $action) | |||
| { | |||
| $data = array(); | |||
| /* | |||
| $rows = $this->db->select('member_no, passwd, locked') | |||
| ->from('members') | |||
| ->where(array('lpr' => $lpr, 'passwd' => $pswd)) | |||
| ->limit(1) | |||
| ->get() | |||
| ->row_array(); | |||
| trigger_error('防盜鎖車:'.$this->db->last_query()); | |||
| // 無資料或密碼錯誤 | |||
| if (empty($rows['member_no'])) | |||
| { | |||
| $data['result_code'] = 'FAIL'; | |||
| return($data); | |||
| } | |||
| */ | |||
| $rows = $this->db->select('member_no, passwd, locked') | |||
| ->from('members') | |||
| ->where(array('lpr' => $lpr)) | |||
| ->limit(1) | |||
| ->get() | |||
| ->row_array(); | |||
| trigger_error('防盜鎖車:'.$this->db->last_query()); | |||
| // 無資料或密碼錯誤 | |||
| if (empty($rows['member_no']) || md5($rows['passwd']) != $pswd) | |||
| { | |||
| $data['result_code'] = 'FAIL'; | |||
| return($data); | |||
| } | |||
| $data['result_code'] = 'OK'; | |||
| // 查詢防盜狀態 | |||
| if ($action == 2) | |||
| { | |||
| $data['result']['action'] = 'CHECK_SECURITY'; | |||
| $data['result'][0]['num'] = $lpr; | |||
| $data['result'][0]['result'] = $rows['locked'] ? 'ON' : 'OFF'; | |||
| return $data; | |||
| } | |||
| $this->db | |||
| ->where('member_no', $rows['member_no']) | |||
| ->update('members', array('locked' => $action)); | |||
| $data['result']['action'] = $action == 1 ? 'ON' : 'OFF'; | |||
| return $data; | |||
| } | |||
| } | |||
| @@ -0,0 +1,167 @@ | |||
| <?php | |||
| /* | |||
| file: Payment_ats_model.php 繳費機 | |||
| */ | |||
| class Payment_ats_model extends CI_Model | |||
| { | |||
| function __construct() | |||
| { | |||
| parent::__construct(); | |||
| $this->load->database(); | |||
| define('PAYMENT_ATS_INVOICE_REMARK', '繳費機帳單'); | |||
| define('TABLE_NAME_TX_BILL_ATS', 'tx_bill_ats'); | |||
| } | |||
| // 狀態: 結帳完成 | |||
| public function transfer_money_done($order_no) | |||
| { | |||
| $data = array(); | |||
| $data['status'] = 1; // 狀態: 0:剛建立, 1:結帳完成, 2:錢沒對上, 3:發票沒建立, 4:手動調整, 99:訂單逾期作廢, 100:交易進行中, 101: 交易失敗, 111:產品已領取 | |||
| $this->db->update(TABLE_NAME_TX_BILL_ATS, $data, array('order_no' => $order_no)); | |||
| return true; | |||
| } | |||
| // 狀態: 錢沒對上 | |||
| public function transfer_money_done_with_amt_error($order_no) | |||
| { | |||
| $data = array(); | |||
| $data['status'] = 2; // 狀態: 0:剛建立, 1:結帳完成, 2:錢沒對上, 3:發票沒建立, 4:手動調整, 99:訂單逾期作廢, 100:交易進行中, 101: 交易失敗, 111:產品已領取 | |||
| $this->db->update(TABLE_NAME_TX_BILL_ATS, $data, array('order_no' => $order_no)); | |||
| return true; | |||
| } | |||
| // 狀態: 發票沒建立 | |||
| public function transfer_money_set_invoice_error($order_no) | |||
| { | |||
| $data = array(); | |||
| $data['status'] = 3; // 狀態: 0:剛建立, 1:結帳完成, 2:錢沒對上, 3:發票沒建立, 4:手動調整, 99:訂單逾期作廢, 100:交易進行中, 101: 交易失敗, 111:產品已領取 | |||
| $this->db->update(TABLE_NAME_TX_BILL_ATS, $data, array('order_no' => $order_no)); | |||
| return true; | |||
| } | |||
| // 狀態: 訂單逾期作廢 | |||
| public function transfer_money_timeout($order_no) | |||
| { | |||
| $data = array(); | |||
| $data['status'] = 99; // 狀態: 0:剛建立, 1:結帳完成, 2:錢沒對上, 3:發票沒建立, 4:手動調整, 99:訂單逾期作廢, 100:交易進行中, 101: 交易失敗, 111:產品已領取 | |||
| $this->db->update(TABLE_NAME_TX_BILL_ATS, $data, array('order_no' => $order_no)); | |||
| return true; | |||
| } | |||
| // 狀態: 交易失敗 | |||
| public function transfer_money_done_with_tx_error($order_no) | |||
| { | |||
| $data = array(); | |||
| $data['status'] = 101; // 狀態: 0:剛建立, 1:結帳完成, 2:錢沒對上, 3:發票沒建立, 4:手動調整, 99:訂單逾期作廢, 100:交易進行中, 101: 交易失敗, 111:產品已領取 | |||
| $this->db->update(TABLE_NAME_TX_BILL_ATS, $data, array('order_no' => $order_no)); | |||
| return true; | |||
| } | |||
| // 狀態: 產品已領取 | |||
| public function transfer_money_done_and_finished($order_no) | |||
| { | |||
| $data = array(); | |||
| $data['status'] = 111; // 狀態: 0:剛建立, 1:結帳完成, 2:錢沒對上, 3:發票沒建立, 4:手動調整, 99:訂單逾期作廢, 100:交易進行中, 101: 交易失敗, 111:產品已領取 | |||
| $this->db->update(TABLE_NAME_TX_BILL_ATS, $data, array('order_no' => $order_no)); | |||
| return true; | |||
| } | |||
| // 建立帳單 (會員) | |||
| public function create_member_bill($lpr) | |||
| { | |||
| $result = $this->db->select("station_no, member_no, member_name, date_format(end_date, '%Y-%m-%d') as end_date, amt, remarks, | |||
| date_add(date_format(end_date, '%Y-%m-%d'), INTERVAL 1 day) as next_start, | |||
| date_add(date_format(end_date, '%Y-%m-%d'), INTERVAL 1 MONTH) as next_end", false) | |||
| ->from('members') | |||
| ->where('lpr', $lpr) | |||
| ->get() | |||
| ->row_array(); | |||
| if(empty($result['member_no'])){ | |||
| // 查無會員資料 | |||
| $data = array(); | |||
| $data['member_no'] = 0; | |||
| return $data; | |||
| } | |||
| else | |||
| { | |||
| // 建立會員帳單 | |||
| $data = array(); | |||
| $data['invoice_remark'] = PAYMENT_ATS_INVOICE_REMARK; | |||
| $data['order_no'] = $result['member_no'].time(); // 交易序號 | |||
| $data['station_no'] = $result['station_no']; // 場站編號 | |||
| $data['member_no'] = $result['member_no']; // 會員編號 | |||
| $data['member_name'] = $result['member_name']; // 車主姓名 | |||
| //$data['amt'] = 10; // 租金金額 (test only) | |||
| $data['amt'] = $result['amt']; // 租金金額 | |||
| $data['remarks'] = $result['remarks']; // 備註 | |||
| $data['end_time'] = $result['end_date'] . ' 23:59:59'; // 到期日 | |||
| $data['next_start_time'] = $result['next_start']. ' 00:00:00'; // 次期起始日 | |||
| $data['next_end_time'] = $result['next_end'] . ' 23:59:59'; // 次期到期日 | |||
| $data['lpr'] = strtoupper($lpr); // 車牌號碼 | |||
| $data['balance_time_limit'] = date("Y-m-d H:i:s", strtotime('+ 15 minutes')); // 帳單有效期限 15 min | |||
| $this->db->insert(TABLE_NAME_TX_BILL_ATS, $data); | |||
| return $data; | |||
| } | |||
| trigger_error(APP_NAME.', '.__FUNCTION__.', order_no=>' . $order_no."|{$lpr}|無資料"); | |||
| } | |||
| // 繳交帳單 (帳單) | |||
| public function pay_bill($order_no, $invoice_receiver, $company_no, $email, $mobile, $clientBackUrl, $orderResultUrl, $serviceUrl, $tx_type=0) | |||
| { | |||
| $data = $this->get_tx_bill($order_no); | |||
| if (!empty($data)) | |||
| { | |||
| if($data['status'] != 0){ | |||
| trigger_error(APP_NAME.', '.__FUNCTION__.', order_no=>' . $order_no."|error status: ". $data['status']); | |||
| return null; | |||
| } | |||
| if(strlen($invoice_receiver) >= 7){ // 手機載具編號 | |||
| $data['invoice_receiver'] = '/'.$invoice_receiver; | |||
| } | |||
| if(strlen($company_no) >= 8){ // 公司統編 | |||
| $data['company_no'] = $company_no; | |||
| $data['company_receiver'] = "公司名稱"; | |||
| $data['company_address'] = "公司地址"; | |||
| } | |||
| if(strlen($email) >= 5){ // a@b.c | |||
| $data['email'] = $email; | |||
| } | |||
| if(strlen($mobile) >= 10){ // 手機 | |||
| $data['mobile'] = $mobile; | |||
| } | |||
| $txTime = time(); // 產生交易時間 | |||
| if(strtotime($data['balance_time_limit']) - $txTime > 0){ | |||
| $data['status'] = 100; //狀態: 0:剛建立, 1:結帳完成, 2:錢沒對上, 3:發票沒建立, 4:手動調整, 99:訂單逾期作廢, 100:交易進行中 | |||
| $data['tx_time'] = date('Y/m/d H:i:s', $txTime); | |||
| $data['tx_type'] = $tx_type; // 交易種類: 0:未定義, 1:現金, 40:博辰人工模組, 41:博辰自動繳費機, 50:歐付寶轉址刷卡, 51:歐付寶APP, 52:歐付寶轉址WebATM, 60:中國信託刷卡轉址 | |||
| $data['client_back_url'] = $clientBackUrl; | |||
| $data['order_result_url'] = $orderResultUrl; | |||
| $data['service_url'] = $serviceUrl; | |||
| $this->db->update(TABLE_NAME_TX_BILL_ATS, $data, array('order_no' => $order_no)); | |||
| return $data; | |||
| } | |||
| $this->transfer_money_timeout($order_no); // 訂單逾期作廢 | |||
| return null; | |||
| } | |||
| trigger_error(APP_NAME.', '.__FUNCTION__.', order_no=>' . $order_no."|無帳單資料"); | |||
| } | |||
| // 取得帳單資料 | |||
| public function get_tx_bill($order_no) | |||
| { | |||
| $result = $this->db | |||
| ->from(TABLE_NAME_TX_BILL_ATS) | |||
| ->where(array('order_no' => $order_no)) | |||
| ->limit(1) | |||
| ->get() | |||
| ->row_array(); | |||
| return $result; | |||
| } | |||
| } | |||
| @@ -0,0 +1,185 @@ | |||
| <?php | |||
| /* | |||
| file: Payment_model.php 付費系統 (臨停) | |||
| */ | |||
| class Payment_model extends CI_Model | |||
| { | |||
| function __construct() | |||
| { | |||
| parent::__construct(); | |||
| $this->load->database(); | |||
| define("PAYMENT_INVOICE_REMARK", "臨停繳交帳單"); | |||
| } | |||
| // 狀態: 結帳完成 | |||
| public function transfer_money_done($order_no) | |||
| { | |||
| $data = array(); | |||
| $data['status'] = TX_BILL_STATUS_PAID; | |||
| $this->db->update('tx_bill', $data, array('order_no' => $order_no)); | |||
| return true; | |||
| } | |||
| // 狀態: 錢沒對上 | |||
| public function transfer_money_done_with_amt_error($order_no) | |||
| { | |||
| $data = array(); | |||
| $data['status'] = TX_BILL_STATUS_ERROR_AMT; | |||
| $this->db->update('tx_bill', $data, array('order_no' => $order_no)); | |||
| return true; | |||
| } | |||
| // 狀態: 發票沒建立 | |||
| public function transfer_money_set_invoice_error($order_no) | |||
| { | |||
| $data = array(); | |||
| $data['status'] = TX_BILL_STATUS_ERROR_INVOICE; | |||
| $this->db->update('tx_bill', $data, array('order_no' => $order_no)); | |||
| return true; | |||
| } | |||
| // 狀態: 訂單逾期作廢 | |||
| public function transfer_money_timeout($order_no) | |||
| { | |||
| $data = array(); | |||
| $data['status'] = TX_BILL_STATUS_TIME_OUT; | |||
| $this->db->update('tx_bill', $data, array('order_no' => $order_no)); | |||
| return true; | |||
| } | |||
| // 狀態: 交易失敗 | |||
| public function transfer_money_done_with_tx_error($order_no) | |||
| { | |||
| $data = array(); | |||
| $data['status'] = TX_BILL_STATUS_FAIL; | |||
| $this->db->update('tx_bill', $data, array('order_no' => $order_no)); | |||
| return true; | |||
| } | |||
| // 狀態: 產品已領取 | |||
| public function transfer_money_done_and_finished($order_no) | |||
| { | |||
| $data = array(); | |||
| $data['status'] = TX_BILL_STATUS_DONE; | |||
| $this->db->update('tx_bill', $data, array('order_no' => $order_no)); | |||
| return true; | |||
| } | |||
| // 建立帳單 (臨停) | |||
| public function create_cario_bill($lpr) | |||
| { | |||
| $result = $this->db->select('station_no, cario_no, in_time, pay_time, out_time, out_before_time, member_no') | |||
| ->from('cario') | |||
| ->where(array('obj_type' => 1, 'obj_id' => $lpr, 'finished' => 0, 'err' => 0)) | |||
| ->order_by('cario_no', 'desc') | |||
| ->limit(1) | |||
| ->get() | |||
| ->row_array(); | |||
| if(!empty($result['member_no'])){ | |||
| // 會員不算臨停帳單 | |||
| $data = array(); | |||
| $data['member_no'] = $result['member_no']; | |||
| return $data; | |||
| } | |||
| else if (!empty($result['out_before_time'])) | |||
| { | |||
| $inTime = $result['out_before_time']; // 進場時間認這個欄位 | |||
| $balanceTime = date('Y-m-d H:i:s'); | |||
| $stationNo = $result['station_no']; | |||
| require_once(ALTOB_BILL_FILE); // 臨停費率 | |||
| $oPayment = new AltobPayment(); | |||
| $oPayment->ServiceURL = ALTOB_PAYMENT_TXDATA_URL; | |||
| $bill = $oPayment->getBill($inTime, $balanceTime, $stationNo); | |||
| // create tx_bill | |||
| $data = array(); | |||
| $data['invoice_remark'] = PAYMENT_INVOICE_REMARK; | |||
| $data['order_no'] = $result['cario_no'].time(); // 交易序號 | |||
| $data['cario_no'] = $result['cario_no']; // 進出場序號 (金流結束後開門使用) | |||
| //$data['amt'] = ($bill[BillResultKey::price] > 0) ? 10 : 0; // 測試用 | |||
| $data['amt'] = $bill[BillResultKey::price]; | |||
| $data['balance_time_limit'] = date("Y-m-d H:i:s", strtotime('+ 15 minutes')); // 15 min | |||
| $data['balance_time'] = $balanceTime; | |||
| $data['in_time'] = $inTime; | |||
| $data['lpr'] = strtoupper($lpr); | |||
| $data['station_no'] = $stationNo; | |||
| if($bill[BillResultKey::price] > 0){ | |||
| // 有費用才建立到tx_bill | |||
| $this->db->insert('tx_bill', $data); | |||
| }else{ | |||
| trigger_error(APP_NAME.', '.__FUNCTION__.', order_no=>' . $order_no."|{$lpr}|尚未產生款項"); | |||
| } | |||
| // return data | |||
| $data['bill_days'] = $bill[BillResultKey::days]; | |||
| $data['bill_hours'] = $bill[BillResultKey::hours]; | |||
| $data['bill_mins'] = $bill[BillResultKey::mins]; | |||
| $data['price_detail'] = $bill[BillResultKey::price_detail]; | |||
| return $data; | |||
| } | |||
| trigger_error(APP_NAME.', '.__FUNCTION__.', order_no=>' . $order_no."|{$lpr}|無車牌帳單資料"); | |||
| } | |||
| // 繳交帳單 (帳單) | |||
| public function pay_bill($order_no, $invoice_receiver, $company_no, $email, $mobile, $clientBackUrl, $orderResultUrl, $serviceUrl, $tx_type=0) | |||
| { | |||
| $data = $this->get_tx_bill($order_no); | |||
| if (!empty($data)) | |||
| { | |||
| if($data['status'] != 0){ | |||
| trigger_error(APP_NAME.', '.__FUNCTION__.', order_no=>' . $order_no."|error status: ". $data['status']); | |||
| return null; | |||
| } | |||
| if(strlen($invoice_receiver) >= 7){ // 手機載具編號 | |||
| $data['invoice_receiver'] = '/'.$invoice_receiver; | |||
| } | |||
| if(strlen($company_no) >= 8){ // 公司統編 | |||
| $data['company_no'] = $company_no; | |||
| $data['company_receiver'] = "公司名稱"; | |||
| $data['company_address'] = "公司地址"; | |||
| } | |||
| if(strlen($email) >= 5){ // a@b.c | |||
| $data['email'] = $email; | |||
| } | |||
| if(strlen($mobile) >= 10){ // 手機 | |||
| $data['mobile'] = $mobile; | |||
| } | |||
| $txTime = time(); // 產生交易時間 | |||
| if(strtotime($data['balance_time_limit']) - $txTime > 0){ | |||
| $data['status'] = TX_BILL_STATUS_PROCESSING; | |||
| $data['tx_time'] = date('Y/m/d H:i:s', $txTime); | |||
| $data['tx_type'] = $tx_type; // 交易種類: 0:未定義, 1:現金, 40:博辰人工模組, 41:博辰自動繳費機, 50:歐付寶轉址刷卡, 51:歐付寶APP, 52:歐付寶轉址WebATM, 60:中國信託刷卡轉址 | |||
| $data['client_back_url'] = $clientBackUrl; | |||
| $data['order_result_url'] = $orderResultUrl; | |||
| $data['service_url'] = $serviceUrl; | |||
| $this->db->update('tx_bill', $data, array('order_no' => $order_no)); | |||
| return $data; | |||
| } | |||
| $this->transfer_money_timeout($order_no); // 訂單逾期作廢 | |||
| return null; | |||
| } | |||
| trigger_error(APP_NAME.', '.__FUNCTION__.', order_no=>' . $order_no."|無帳單資料"); | |||
| } | |||
| // 取得臨停帳單資料 | |||
| public function get_tx_bill($order_no) | |||
| { | |||
| $result = $this->db | |||
| ->from('tx_bill') | |||
| ->where(array('order_no' => $order_no)) | |||
| ->limit(1) | |||
| ->get() | |||
| ->row_array(); | |||
| return $result; | |||
| } | |||
| } | |||
| @@ -0,0 +1,356 @@ | |||
| <?php | |||
| /* | |||
| file: pks_model.php 車位在席資料庫處理模組 | |||
| */ | |||
| class Pks_model extends CI_Model | |||
| { | |||
| var $vars = array(); | |||
| function __construct() | |||
| { | |||
| parent::__construct(); | |||
| $this->load->database(); | |||
| } | |||
| public function init($vars) | |||
| { | |||
| $this->vars = $vars; | |||
| } | |||
| // 車輛進出傳入車牌號碼 | |||
| public function pksio($parms) | |||
| { | |||
| switch($parms['io']) | |||
| { | |||
| case 'KL': // 車輛入席車辨(lpr)及圖檔 | |||
| if ($parms['lpr'] == 'NONE') // 在席車辨失敗, 不處理 | |||
| { | |||
| trigger_error('在席車辨失敗' . print_r($parms, true)); | |||
| return false; | |||
| } | |||
| // 讀取在席資料(pks) | |||
| $rows_pks = $this->db | |||
| ->select('cario_no, lpr, status, confirms') | |||
| ->from('pks') | |||
| ->where(array('pksno' => $parms['pksno'], 'station_no' => $this->vars['station_no'])) | |||
| ->limit(1) | |||
| ->get() | |||
| ->row_array(); | |||
| trigger_error('KL read pks:'.print_r($rows_pks, true)); | |||
| // 如果已經人工確認或之前已比對有入場資料者, 則重覆再送來的車辨不予理會 | |||
| if ($rows_pks['confirms'] == 1 || $rows_pks['lpr'] == $parms['lpr']) | |||
| { | |||
| trigger_error('KL ignored:'.$rows_pks['lpr']); | |||
| return false; | |||
| } | |||
| /* | |||
| if ($rows_pks['cario_no'] != 0 || $rows_pks['confirms'] == 1 || $rows_pks['lpr'] == $parms['lpr']) | |||
| { | |||
| trigger_error('人工已確認或車號相同不更新pks:'.$rows_pks['lpr']); | |||
| return false; | |||
| } | |||
| */ | |||
| // 讀取進場時間, 如讀不到資料, 以目前時間取代(add by TZUSS 2016-02-23) | |||
| $rows_cario = $this->db | |||
| ->select('cario_no, in_time') | |||
| ->from('cario') | |||
| ->where(array('in_out' => 'CI', 'obj_id' => $parms['lpr'], 'finished' => 0, 'err' => 0, 'station_no' => $this->vars['station_no'])) | |||
| ->order_by('cario_no', 'desc') | |||
| ->limit(1) | |||
| ->get() | |||
| ->row_array(); | |||
| if (!empty($rows_cario['cario_no'])) // 有入場資料 | |||
| { | |||
| $cario_no = $rows_cario['cario_no']; // 入場序號 | |||
| $in_time = $rows_cario['in_time']; | |||
| // 在席與入場資料相符, 分別在cario與pks記錄之 | |||
| $data_cario = array | |||
| ( | |||
| 'pksno' => $parms['pksno'], | |||
| 'pks_time' => date('Y-m-d H:i:s') | |||
| ); | |||
| $this->db->update('cario', $data_cario, array('cario_no' => $cario_no, 'station_no' => $this->vars['station_no'])); | |||
| } | |||
| else // 查無入場資料, 即時通知 | |||
| { | |||
| $cario_no = 0; | |||
| $in_time = date('Y-m-d H:i:s'); | |||
| $jdata = json_encode(array | |||
| ( | |||
| 'pksno' => $parms['pksno'], | |||
| 'lpr' => $parms['lpr'], | |||
| 'in_time' => $in_time, | |||
| 'pic_name' => $parms['pic_name'] | |||
| ), JSON_UNESCAPED_UNICODE); | |||
| // $this->vars['mqtt']-lish('PKS_WITHOUT_IN', "{$jdata}", 0); // 待web完成 ??? | |||
| trigger_error('在席無進場資料:'. print_r($parms, true)); | |||
| } | |||
| // 車入格後的車牌辨識(lpr), 傅送圖檔 | |||
| array_map('unlink', glob(PKS_PIC."pks-{$parms['pksno']}-*.jpg")); // 刪除舊照片 | |||
| $config['upload_path'] = PKS_PIC; | |||
| $config['allowed_types'] = 'gif|jpg|png'; | |||
| // ex. pks-2016-1625AB-1-2015080526.jpg -> pks-車位編號-車號-設備編號-時間.jpg | |||
| $config['file_name'] = "pks-{$parms['pksno']}-{$parms['lpr']}-{$parms['ivsno']}-{$this->vars['time_num']}.jpg"; | |||
| $this->load->library('upload', $config); | |||
| $parms['pic_name'] = $config['file_name']; | |||
| if($this->upload->do_upload('cars')) | |||
| { | |||
| // 若無錯誤,則上傳檔案 | |||
| $file = $this->upload->data('cars'); | |||
| } | |||
| else | |||
| { | |||
| trigger_error('入席傳檔錯誤:'. print_r($parms, true)); | |||
| } | |||
| $data = array | |||
| ( | |||
| 'cario_no' => $cario_no, | |||
| 'lpr' => $parms['lpr'], | |||
| 'status' => 'LR', // 車格佔用並有車號 | |||
| 'confirms' => 0, // 預設人工未確認 | |||
| 'pic_name' => $parms['pic_name'], | |||
| 'in_time' => $in_time | |||
| ); | |||
| // 車號及照片檔名填入資料庫內 | |||
| $this->db->update('pks', $data, array('pksno' => $parms['pksno'], 'station_no' => $this->vars['station_no'])); | |||
| break; | |||
| case 'KI': // 車輛入席, 各區空車位與佔位各加減1 | |||
| $rows = $this->db->select('status') | |||
| ->from('pks') | |||
| ->where(array('pksno' => $parms['pksno'], 'station_no' => $this->vars['station_no'])) | |||
| ->get() | |||
| ->row_array(); | |||
| // if (!empty($rows['status']) && $rows['status'] == 'LR') break; // 仍有車在席, 不應再有KI, ignore | |||
| if (!empty($rows['status']) && $rows['status'] == 'LR') return true; // 仍有車在席, 不應再有KI, ignore | |||
| $data = array | |||
| ( | |||
| 'cario_no' => 0, | |||
| 'lpr' => '', | |||
| 'status' => 'OC', // 車格佔用但尚無車號 | |||
| 'confirms' => 0, | |||
| 'pic_name' => '', | |||
| 'in_time' => null | |||
| ); | |||
| $this->db->update('pks', $data, array('pksno' => $parms['pksno'], 'station_no' => $this->vars['station_no'])); | |||
| break; | |||
| case 'KO': // 車輛離席, 各區空車位與佔位各加減1 | |||
| $data = array | |||
| ( | |||
| 'cario_no' => 0, | |||
| 'lpr' => '', | |||
| 'status' => 'VA', // 車格佔用但尚無車號 | |||
| 'confirms' => 0, | |||
| 'pic_name' => '', | |||
| 'in_time' => null | |||
| ); | |||
| $this->db->update('pks', $data, array('pksno' => $parms['pksno'], 'station_no' => $this->vars['station_no'])); | |||
| break; | |||
| } | |||
| /* | |||
| // 找出與與此車位相關的群組 | |||
| $sql = "select group_id, tot, renum | |||
| from pks_groups | |||
| where group_id in | |||
| (select group_id from pks_group_member where station_no = {$this->vars['station_no']} and pksno = {$parms['pksno']})"; | |||
| $retults = $this->db->query($sql)->result_array(); | |||
| foreach ($retults as $rows) | |||
| { | |||
| // 計算群組異動後的空車位數, 先讀出已停車位數 | |||
| $sql = "select count(*) as parked from pks where status != 'VA' and pksno in (select pksno from pks_group_member where group_id = '{$rows['group_id']}')"; | |||
| $row_group = $this->db->query($sql)->row_array(); | |||
| $group_va = $rows['tot'] + $rows['renum'] - $row_group['parked']; // 群組空車位數 | |||
| $this->db->update('pks_groups', array('parked' => $row_group['parked'], 'availables' => $group_va), array('group_id' => $rows['group_id'])); | |||
| get_headers("http://192.168.51.15/set_num.php?group_id={$rows['group_id']}&num={$group_va}"); | |||
| // $this->vars['mqtt']->publish("VA-{$rows['group_id']}", "{$group_va}", 0); // 送出剩餘車位數給字幕機 | |||
| // 總車位數暫無需處理 | |||
| } | |||
| */ | |||
| // 找出與與此車位相關的群組 | |||
| $sql = "select group_id, tot, renum, availables | |||
| from pks_groups | |||
| where group_id in | |||
| (select group_id from pks_group_member where station_no = {$this->vars['station_no']} and pksno = {$parms['pksno']})"; | |||
| $retults = $this->db->query($sql)->result_array(); | |||
| foreach ($retults as $rows) | |||
| { | |||
| // 計算群組異動後的空車位數, 先讀出已停車位數 | |||
| $sql = "select count(*) as parked from pks where status != 'VA' and pksno in (select pksno from pks_group_member where group_id = '{$rows['group_id']}')"; | |||
| $row_group = $this->db->query($sql)->row_array(); | |||
| $group_va = $rows['tot'] + $rows['renum'] - $row_group['parked']; // 群組空車位數 | |||
| // 有變動才處理更新 | |||
| if($rows['availables'] != $group_va) | |||
| { | |||
| // 防止負值 | |||
| if($group_va < 0){ | |||
| $group_va = 0; | |||
| } | |||
| $group_va_pad = str_pad($group_va, 3, '0', STR_PAD_LEFT); // 補零 | |||
| $this->db->update('pks_groups', array('parked' => $row_group['parked'], 'availables' => $group_va), array('group_id' => $rows['group_id'])); | |||
| $this->vars['mqtt']->publish(MQ_TOPIC_SUBLEVEL, "{$rows['group_id']},{$group_va_pad}", 0); // 送出剩餘車位數給字幕機 | |||
| // 總車位數暫無需處理 | |||
| // 七樓無在席, 手動或用猜的 | |||
| /* | |||
| $f7_total = 74; | |||
| $sql = "select renum from pks_groups where group_id = 'F7'"; | |||
| $row_group = $this->db->query($sql)->row_array(); | |||
| $f7_renum = $row_group['renum']; | |||
| $total_parked_sql = "select count(cario_no) as parked | |||
| from cario where | |||
| cario.in_time > DATE_SUB(CURRENT_TIMESTAMP, INTERVAL 5 DAY) | |||
| and cario.finished = 0 | |||
| and cario.err = 0 | |||
| and cario.in_out = 'CI' | |||
| and cario.out_time is null"; | |||
| $total_parked_row_group = $this->db->query($total_parked_sql)->row_array(); | |||
| $sql = "select count(pksno) as parked from pks where status != 'VA'"; | |||
| $row_group = $this->db->query($sql)->row_array(); | |||
| $f7_mqtt = $total_parked_row_group['parked'] - $row_group['parked']; | |||
| if($f7_mqtt > $f7_total){ | |||
| $f7_mqtt = $f7_total; | |||
| }else if($f7_mqtt <= 0){ | |||
| $f7_mqtt = 0; | |||
| } | |||
| $this->db->update('pks_groups', array('parked' => $f7_mqtt, 'availables' => $f7_total - $f7_mqtt + $f7_renum), array('group_id' => 'F7')); | |||
| $f7_mqtt_pad = str_pad($f7_total - $f7_mqtt + $f7_renum, 3, '0', STR_PAD_LEFT); | |||
| $this->vars['mqtt']->publish(MQ_TOPIC_SUBLEVEL, "F7,{$f7_mqtt_pad}", 0); // F7 MQTT | |||
| */ | |||
| } | |||
| } | |||
| } | |||
| // 重新計算 | |||
| public function reculc() | |||
| { | |||
| // 找出與與此車位相關的群組 | |||
| $sql = "select group_id, tot, renum | |||
| from pks_groups"; | |||
| $retults = $this->db->query($sql)->result_array(); | |||
| foreach ($retults as $rows) | |||
| { | |||
| // 計算群組異動後的空車位數, 先讀出已停車位數 | |||
| $sql = "select count(*) as parked from pks where status != 'VA' and pksno in (select pksno from pks_group_member where group_id = '{$rows['group_id']}')"; | |||
| $row_group = $this->db->query($sql)->row_array(); | |||
| $group_va = $rows['tot'] + $rows['renum'] - $row_group['parked']; // 群組空車位數 | |||
| $this->db->update('pks_groups', array('parked' => $row_group['parked'], 'availables' => $group_va), array('group_id' => $rows['group_id'])); | |||
| // $this->vars['mqtt']->publish("VA-{$rows['group_id']}", "{$group_va}", 0); // 送出剩餘車位數給字幕機 | |||
| get_headers("http://192.168.51.15/set_num.php?group_id={$rows['group_id']}&num={$group_va}"); | |||
| echo "group_id:{$rows['group_id']}, tot:{$rows['tot']}, availables:{$group_va}, parked:{$row_group['parked']}, renum:{$rows['renum']}<br />"; | |||
| } | |||
| } | |||
| // 取得所有車位使用狀態 | |||
| public function query_station_status($station_no) | |||
| { | |||
| /* 沒有group_id, pks不能直接用, 要多撈兩張表 | |||
| $sql = "select pksno, posx, posy, in_time | |||
| FROM pks | |||
| WHERE station_no = '".$station_no."' and lpr != ''"; | |||
| */ | |||
| $sql = "SELECT pks.pksno AS pksno, pks.posx AS posx, pks.posy AS posy, pks.in_time AS in_time, | |||
| pks_groups.group_id AS group_id | |||
| FROM pks | |||
| LEFT JOIN pks_group_member ON pks.pksno = pks_group_member.pksno AND pks.station_no = pks_group_member.station_no | |||
| LEFT JOIN pks_groups ON pks_group_member.group_id = pks_groups.group_id | |||
| WHERE pks.lpr != '' AND pks.station_no = '".$station_no."' AND pks_groups.group_type = '1' "; | |||
| $retults = $this->db->query($sql)->result_array(); | |||
| $currentTime = new DateTime("now"); | |||
| foreach ($retults as $idx => $rows) | |||
| { | |||
| $startTime = new DateTime($rows['in_time']); // 進場時間 | |||
| $interval = $startTime->diff($currentTime); | |||
| $status = $this->gen_pks_s($interval); // 一般:0, 隔日:1, 超過3日:3, 隔週:7, 隔20日:20 | |||
| $data['result'][$idx] = array | |||
| ( | |||
| 'g'=> $rows['group_id'], | |||
| 'id'=> $rows['pksno'], | |||
| 'x' => $rows['posx'], | |||
| 'y' => $rows['posy'], | |||
| 's' => $status | |||
| ); | |||
| } | |||
| return $data; | |||
| } | |||
| // 取得車位狀態 | |||
| private function gen_pks_s($interval) | |||
| { | |||
| $status = 0; // 一般:0, 隔日:1, 超過3日:3, 隔週:7, 隔20日:20 | |||
| if($interval->y > 0 || $interval->m > 0 || $interval->d >= 20){ | |||
| $status = 20; | |||
| }else if($interval->d >= 7){ | |||
| $status = 7; | |||
| }else if($interval->d >= 3){ | |||
| $status = 3; | |||
| }else if($interval->d >= 1){ | |||
| $status = 1; | |||
| } | |||
| return $status; | |||
| } | |||
| // 取得指定車位使用狀態 | |||
| public function query_station_pks($station_no, $pksno) | |||
| { | |||
| $sql = "SELECT pks.pksno AS pksno, pks.lpr AS lpr, pks.in_time AS in_time, pks.station_no AS station_no, | |||
| pks_groups.group_id AS group_id, pks_groups.group_name AS group_name, pks_groups.group_type AS type | |||
| FROM pks | |||
| LEFT JOIN pks_group_member ON pks.pksno = pks_group_member.pksno AND pks.station_no = pks_group_member.station_no | |||
| LEFT JOIN pks_groups ON pks_group_member.group_id = pks_groups.group_id | |||
| WHERE pks.pksno = '".$pksno."' AND pks.station_no = '".$station_no."' AND pks_groups.group_type = '1' "; | |||
| $retults = $this->db->query($sql)->result_array(); | |||
| $currentTime = new DateTime("now"); | |||
| foreach ($retults as $idx => $rows) | |||
| { | |||
| $startTime = new DateTime($rows['in_time']); // 進場時間 | |||
| $interval = $startTime->diff($currentTime); | |||
| $status = $this->gen_pks_s($interval); // 一般:0, 隔日:1, 超過3日:3, 隔週:7, 隔20日:20 | |||
| $data['result'][$idx] = array | |||
| ( | |||
| 'pksno'=> $rows['pksno'], | |||
| 'lpr' => $rows['lpr'], | |||
| 'time' => $rows['in_time'], | |||
| 'station_no' => $rows['station_no'], | |||
| 'group_id' => $rows['group_id'], | |||
| 'group_name' => $rows['group_name'], | |||
| 'status' => $status | |||
| ); | |||
| } | |||
| return $data; | |||
| } | |||
| } | |||
| @@ -0,0 +1,349 @@ | |||
| <?php | |||
| /* | |||
| file: Qcar_model.php 停車管理系統 | |||
| */ | |||
| class Qcar_model extends CI_Model | |||
| { | |||
| function __construct() | |||
| { | |||
| parent::__construct(); | |||
| $this->load->database(); | |||
| } | |||
| // 查車 | |||
| public function q_pks($lpr) | |||
| { | |||
| $sql = "select p.pksno, p.pic_name, p.update_time, p.in_time, p.posx, p.posy, m.group_id, g.group_name, g.floors | |||
| from pks p, pks_group_member m, pks_groups g | |||
| where p.pksno = m.pksno | |||
| and m.group_id = g.group_id | |||
| and g.group_type = 1 | |||
| and p.lpr = '{$lpr}' | |||
| limit 1"; | |||
| $rows = $this->db->query($sql)->row_array(); | |||
| /* | |||
| if (!empty($rows['pic_name'])) | |||
| { | |||
| // $rows['pic_name'] = str_replace('.jpg', '', $rows['pic_name']); | |||
| $rows['pic_name'] = $rows['pic_name']; | |||
| } | |||
| else // 查無資料, 啟用模糊比對 | |||
| { | |||
| $len = strlen($lpr); | |||
| if ($len >= 5) // 檢查車牌號碼長度 | |||
| { | |||
| $arr = explode(';', file_get_contents("http://192.168.11.253:8090/cgi-bin/parking_status.cgi?CMD=QUERY_SEAT&LPR={$lpr}")); | |||
| $pksno = $arr[0]; | |||
| } | |||
| else | |||
| { | |||
| $pksno = 0; // 車牌號碼長度錯誤 | |||
| } | |||
| trigger_error("電腦查詢模糊比對:[{$lpr}]:" . print_r($arr, true)); | |||
| if ($pksno != 0) // 模糊比對成功 | |||
| { | |||
| $sql = "select p.pic_name, p.update_time, p.in_time, p.posx, p.posy, m.group_id, g.group_name, g.floors | |||
| from pks p, pks_group_member m, pks_groups g | |||
| where p.pksno = m.pksno | |||
| and m.group_id = g.group_id | |||
| and g.group_type = 1 | |||
| and p.pksno = {$pksno} | |||
| limit 1"; | |||
| $rows_pks = $this->db->query($sql)->row_array(); | |||
| $rows['pksno'] = $pksno; | |||
| // $rows['pic_name'] = str_replace('.jpg', '', $rows_pks['pic_name']); | |||
| $rows['pic_name'] = $rows_pks['pic_name']; | |||
| $rows['update_time'] = $rows_pks['update_time']; | |||
| $rows['in_time'] = $rows_pks['in_time']; | |||
| $rows['floors'] = $rows_pks['floors']; | |||
| $rows['posx'] = $rows_pks['posx']; | |||
| $rows['posy'] = $rows_pks['posy']; | |||
| $rows['group_id'] = $rows_pks['group_id']; | |||
| $rows['group_name'] = $rows_pks['group_name']; | |||
| } | |||
| else // 模糊比對仍是失敗 | |||
| { | |||
| $rows['pksno'] = '0'; // 無該筆資料 | |||
| } | |||
| } | |||
| */ | |||
| return $rows; | |||
| } | |||
| // 月租會員加入 | |||
| public function q_rents($lpr) | |||
| { | |||
| $rows = $this->db->select("station_no, member_no, member_name, date_format(end_date, '%Y-%m-%d') as end_date, amt , date_add(date_format(end_date, '%Y-%m-%d'), INTERVAL 1 day) as next_start, date_add(date_format(end_date, '%Y-%m-%d'), INTERVAL 1 MONTH) as next_end", false) | |||
| ->from('members') | |||
| ->where('lpr', $lpr) | |||
| ->get() | |||
| ->row_array(); | |||
| if (empty($rows['member_no'])) $rows['member_no'] = 0; // 無此資料 | |||
| return $rows; | |||
| } | |||
| // 新增月租轉帳資料 | |||
| public function transfer_money_create($data) | |||
| { | |||
| $this->db->insert('tx_money', $data); | |||
| } | |||
| // 更新月租轉帳資料 (已結帳) | |||
| public function transfer_money_done($order_no) | |||
| { | |||
| $data = array(); | |||
| $data['status'] = 1; //狀態,0:剛建立, 1:已結帳, 2:錢沒對上 | |||
| $this->db->update('tx_money', $data, array('order_no' => $order_no)); | |||
| return true; | |||
| } | |||
| // 更新發票號碼 | |||
| public function transfer_money_set_invoice($order_no, $invoice_no) | |||
| { | |||
| $data = array(); | |||
| $data['invoice_no'] = $invoice_no; | |||
| $this->db->update('tx_money', $data, array('order_no' => $order_no)); | |||
| return true; | |||
| } | |||
| // 找不到POS機 | |||
| public function transfer_money_done_with_error_10($order_no) | |||
| { | |||
| $data = array(); | |||
| $data['status'] = 10; //狀態,0:剛建立, 1:已結帳, 2:錢沒對上, 3:發票沒拿到, 4:手動調整, 10:找不到POS機 | |||
| $this->db->update('tx_money', $data, array('order_no' => $order_no)); | |||
| return true; | |||
| } | |||
| // 更新發票號碼失敗 | |||
| public function transfer_money_set_invoice_error_4($order_no) | |||
| { | |||
| $data = array(); | |||
| $data['status'] = 3; //狀態,0:剛建立, 1:已結帳, 2:錢沒對上, 3:發票沒拿到 | |||
| $this->db->update('tx_money', $data, array('order_no' => $order_no)); | |||
| return true; | |||
| } | |||
| // 更新月租轉帳資料 (錢沒對上) | |||
| public function transfer_money_done_with_error_2($order_no) | |||
| { | |||
| $data = array(); | |||
| $data['status'] = 2; //狀態,0:剛建立, 1:已結帳, 2:錢沒對上 | |||
| $this->db->update('tx_money', $data, array('order_no' => $order_no)); | |||
| return true; | |||
| } | |||
| // 取得月租轉帳資料 | |||
| public function get_tx_money($order_no) | |||
| { | |||
| $result = $this->db | |||
| ->from('tx_money') | |||
| ->where(array('order_no' => $order_no)) | |||
| ->get() | |||
| ->result_array(); | |||
| return $result; | |||
| } | |||
| // 歐付寶記錄 | |||
| public function create_allpay_feedback_log($data) | |||
| { | |||
| $this->db->insert('allpay_feedback_log', $data); | |||
| return true; | |||
| } | |||
| // 將發票號碼加入資料庫 | |||
| public function update_invoice_no($order_no, $invoice_no) | |||
| { | |||
| $this->db->where(array('order_no' => $order_no)) | |||
| ->update('tx_money', array('invoice_no' => $invoice_no)); | |||
| } | |||
| // 新增發票記錄 | |||
| public function invoice_log_create($data) | |||
| { | |||
| $this->db->insert('tx_invoice_log', $data); | |||
| } | |||
| // 新增發票記錄回傳 | |||
| public function invoice_log_set_response($response_code, $invoice_no, $seqno) | |||
| { | |||
| $data = array(); | |||
| $data['response_code'] = $response_code; | |||
| $this->db->update('tx_invoice_log', $data, array('invoice_no' => $invoice_no, 'seqno' => $seqno)); | |||
| return true; | |||
| } | |||
| // 取得POS機資訊 | |||
| public function get_tx_pos($pos_id) | |||
| { | |||
| $result = $this->db | |||
| ->from('tx_pos') | |||
| ->where(array('pos_id' => $pos_id)) | |||
| ->get() | |||
| ->result_array(); | |||
| return $result; | |||
| } | |||
| // 取得POS機資訊 by lan_ip | |||
| public function get_tx_pos_by_lan_ip($lan_ip) | |||
| { | |||
| $result = $this->db | |||
| ->from('tx_pos') | |||
| ->where(array('lan_ip' => $lan_ip)) | |||
| ->get() | |||
| ->result_array(); | |||
| return $result; | |||
| } | |||
| // 模糊比對 | |||
| function getLevenshteinSQLStatement($word, $target) | |||
| { | |||
| $words = array(); | |||
| if(strlen($word) >= 5) | |||
| { | |||
| for ($i = 0; $i < strlen($word); $i++) { | |||
| // insertions | |||
| $words[] = substr($word, 0, $i) . '_' . substr($word, $i); | |||
| // deletions | |||
| $words[] = substr($word, 0, $i) . substr($word, $i + 1); | |||
| // substitutions | |||
| //$words[] = substr($word, 0, $i) . '_' . substr($word, $i + 1); | |||
| } | |||
| } | |||
| else | |||
| { | |||
| for ($i = 0; $i < strlen($word); $i++) { | |||
| // insertions | |||
| $words[] = substr($word, 0, $i) . '_' . substr($word, $i); | |||
| } | |||
| } | |||
| // last insertion | |||
| $words[] = $word . '_'; | |||
| //return $words; | |||
| $fuzzy_statement = ' ('; | |||
| foreach ($words as $idx => $word) | |||
| { | |||
| $fuzzy_statement .= " {$target} LIKE '%{$word}%' OR "; | |||
| } | |||
| $last_or_pos = strrpos($fuzzy_statement, 'OR'); | |||
| if($last_or_pos !== false) | |||
| { | |||
| $fuzzy_statement = substr_replace($fuzzy_statement, ')', $last_or_pos, strlen('OR')); | |||
| } | |||
| return $fuzzy_statement; | |||
| } | |||
| // 取得進場資訊 (模糊比對) | |||
| public function q_fuzzy_pks($word) | |||
| { | |||
| if(empty($word) || strlen($word) <= 0 || strlen($word) > 10) | |||
| { | |||
| return null; | |||
| } | |||
| $sql = "SELECT station_no, lpr, in_time, pic_name as pks_pic_name | |||
| FROM pks | |||
| WHERE {$this->getLevenshteinSQLStatement($word, 'lpr')} | |||
| ORDER BY lpr ASC"; | |||
| $retults = $this->db->query($sql)->result_array(); | |||
| if(count($retults) > 0) | |||
| { | |||
| foreach ($retults as $idx => $rows) | |||
| { | |||
| $pks_pic_path = ''; | |||
| if(!empty($rows['pks_pic_name'])) | |||
| { | |||
| //$pks_pic_path = APP_URL.'pks_pics/'.str_replace('.jpg', '', $rows['pks_pic_name']); | |||
| $pks_pic_path = SERVER_URL.'pkspic/'.$rows['pks_pic_name']; | |||
| } | |||
| $data['result'][$idx] = array | |||
| ( | |||
| 'lpr'=> $rows['lpr'], | |||
| 'pks_pic_path' => $pks_pic_path, | |||
| 'station_no' => $rows['station_no'], | |||
| 'in_time' => $rows['in_time'] | |||
| ); | |||
| } | |||
| } | |||
| else | |||
| { | |||
| // 讀取入場資料 | |||
| $sql = "SELECT cario.station_no as station_no, cario.obj_id as lpr, cario.in_time as in_time, cario.in_pic_name as pks_pic_name | |||
| FROM cario | |||
| WHERE {$this->getLevenshteinSQLStatement($word, 'obj_id')} | |||
| AND in_out = 'CI' AND finished = 0 AND err = 0 AND out_time IS NULL | |||
| ORDER BY lpr ASC"; | |||
| // AND in_time > DATE_SUB(CURRENT_TIMESTAMP, INTERVAL 5 DAY) | |||
| $retults = $this->db->query($sql)->result_array(); | |||
| if(count($retults) > 0) | |||
| { | |||
| foreach ($retults as $idx => $rows) | |||
| { | |||
| $pks_pic_path = ''; | |||
| if(!empty($rows['pks_pic_name'])) | |||
| { | |||
| $pic_name = str_replace('.jpg', '', $rows['pks_pic_name']); | |||
| $arr = explode('-', $pic_name); | |||
| $pks_pic_path = SERVER_URL.'carspic/'.substr($arr[7], 0, 8).'/'.$pic_name.'.jpg'; | |||
| } | |||
| $data['result'][$idx] = array | |||
| ( | |||
| 'lpr'=> $rows['lpr'], | |||
| 'pks_pic_path' => $pks_pic_path, | |||
| 'station_no' => $rows['station_no'], | |||
| 'in_time' => $rows['in_time'] | |||
| ); | |||
| } | |||
| } | |||
| } | |||
| return $data; | |||
| /* | |||
| foreach ($retults as $idx => $rows) | |||
| { | |||
| $pks_pic_path = ''; | |||
| if(!empty($rows['pks_pic_name'])) | |||
| { | |||
| //$pks_pic_path = APP_URL.'pks_pics/'.str_replace('.jpg', '', $rows['pks_pic_name']); | |||
| $pks_pic_path = SERVER_URL.'pkspic/'.$rows['pks_pic_name']; | |||
| } | |||
| $data['result'][$idx] = array | |||
| ( | |||
| 'lpr'=> $rows['lpr'], | |||
| 'pks_pic_path' => $pks_pic_path, | |||
| 'station_no' => $rows['station_no'], | |||
| 'in_time' => $rows['in_time'] | |||
| ); | |||
| } | |||
| */ | |||
| } | |||
| } | |||
| @@ -0,0 +1,84 @@ | |||
| <?php | |||
| /* | |||
| file: Security_model.php 停車管理系統 (鎖車) | |||
| */ | |||
| class Security_model extends CI_Model | |||
| { | |||
| function __construct() | |||
| { | |||
| parent::__construct(); | |||
| $this->load->database(); | |||
| } | |||
| // 更改會員密碼 | |||
| public function change_pswd($lpr, $new_pswd) | |||
| { | |||
| $data = array('passwd' => $new_pswd); | |||
| $this->db->update('members', $data, array('lpr' => $lpr)); | |||
| return 'ok'; | |||
| } | |||
| // 防盜鎖車 | |||
| // http://203.75.167.89/parkingquery.html/security_action/ABC1234/pswd/2 | |||
| public function security_action($lpr, $pswd, $action) | |||
| { | |||
| $data = array(); | |||
| /* | |||
| $rows = $this->db->select('member_no, passwd, locked') | |||
| ->from('members') | |||
| ->where(array('lpr' => $lpr, 'passwd' => $pswd)) | |||
| ->limit(1) | |||
| ->get() | |||
| ->row_array(); | |||
| trigger_error('防盜鎖車:'.$this->db->last_query()); | |||
| // 無資料或密碼錯誤 | |||
| if (empty($rows['member_no'])) | |||
| { | |||
| $data['result_code'] = 'FAIL'; | |||
| return($data); | |||
| } | |||
| */ | |||
| $rows = $this->db->select('member_no, passwd, locked, lpr') | |||
| ->from('members') | |||
| ->where(array('lpr' => $lpr)) | |||
| ->limit(1) | |||
| ->get() | |||
| ->row_array(); | |||
| trigger_error('防盜鎖車:'.$this->db->last_query()); | |||
| // 無資料或密碼錯誤 | |||
| if (empty($rows['member_no']) || md5($rows['passwd']) != $pswd) | |||
| { | |||
| // 密碼未設定且輸入密碼為車牌號碼 | |||
| if(empty($rows['passwd']) && md5($rows['lpr']) == $pswd){ | |||
| // do nothing | |||
| }else{ | |||
| $data['result_code'] = 'FAIL'; | |||
| return($data); | |||
| } | |||
| } | |||
| $data['result_code'] = 'OK'; | |||
| // 查詢防盜狀態 | |||
| if ($action == 2) | |||
| { | |||
| $data['result']['action'] = 'CHECK_SECURITY'; | |||
| $data['result'][0]['num'] = $lpr; | |||
| $data['result'][0]['result'] = $rows['locked'] ? 'ON' : 'OFF'; | |||
| return $data; | |||
| } | |||
| $this->db | |||
| ->where('member_no', $rows['member_no']) | |||
| ->update('members', array('locked' => $action)); | |||
| $data['result']['action'] = $action == 1 ? 'ON' : 'OFF'; | |||
| return $data; | |||
| } | |||
| } | |||
| @@ -0,0 +1,715 @@ | |||
| <?php | |||
| /* | |||
| file: Sync_data_model.php 資料同步相關 | |||
| */ | |||
| define('SYNC_DATA_LOG_TITLE', 'sync://'); // LOG (sync) | |||
| define('SYNC_PKS_GROUP_ID_CI', 'C888'); // 汽車 888 | |||
| define('SYNC_PKS_GROUP_ID_MI', 'M888'); // 機車 888 | |||
| define('SYNC_API_URL', 'http://61.219.172.11:60123/admins_station.html/'); | |||
| define('SYNC_DELIMITER_ST_NAME', ' & '); // (拆分) 場站名稱 | |||
| define('SYNC_DELIMITER_ST_NO', ','); // (拆分) 場站編號 | |||
| define('SYNC_DELIMITER_ST_INFO', '|'); // (拆分) 其它 | |||
| define('MCACHE_STATION_NO_STR', 'station_no_str'); | |||
| define('MCACHE_STATION_NAME_STR', 'station_name_str'); | |||
| define('MCACHE_STATION_IP_STR', 'station_ip_str'); | |||
| define('MCACHE_STATION_888_STR', 'station_888_str'); | |||
| define('MCACHE_SYNC_888_TMP_LOG', 'sync_888_tmp_log'); // 暫存 888 進出 | |||
| class Sync_data_model extends CI_Model | |||
| { | |||
| var $vars = array(); | |||
| function __construct() | |||
| { | |||
| parent::__construct(); | |||
| $this->load->database(); | |||
| } | |||
| public function init($vars) | |||
| { | |||
| $this->vars = $vars; | |||
| } | |||
| // 送出至message queue(目前用mqtt) | |||
| public function mq_send($topic, $msg) | |||
| { | |||
| $this->vars['mqtt']->publish($topic, $msg, 0); | |||
| trigger_error("mqtt:{$topic}|{$msg}"); | |||
| } | |||
| // ------------------------------------------------ | |||
| // | |||
| // 在席系統同步 (START) | |||
| // | |||
| // ------------------------------------------------ | |||
| // 同步 888 | |||
| public function sync_888($parms) | |||
| { | |||
| $result = -888; | |||
| if(!isset($parms['lpr']) || !isset($parms['etag']) || !isset($parms['io']) || | |||
| ($parms['lpr'] == 'NONE' && $parms['etag'] == 'NONE') | |||
| ) | |||
| { | |||
| trigger_error(__FUNCTION__ . '..NONE..'. print_r($parms, true)); | |||
| return $result; | |||
| } | |||
| trigger_error(__FUNCTION__ . "..{$parms['sno']}|{$parms['io']}|{$parms['lpr']}|{$parms['etag']}.."); | |||
| // [START] 擋相同車號進出 | |||
| $skip_or_not = false; | |||
| $new_cars_tmp = array | |||
| ( | |||
| 'timestamp' => time(), | |||
| 'sno_io' => $parms['sno'] . $parms['io'], | |||
| 'lpr' => $parms['lpr'], | |||
| 'etag' => $parms['etag'] | |||
| ); | |||
| $cars_tmp_log_arr = $this->vars['mcache']->get(MCACHE_SYNC_888_TMP_LOG); | |||
| if(empty($cars_tmp_log_arr)) | |||
| { | |||
| $cars_tmp_log_arr = array(); | |||
| } | |||
| if(isset($cars_tmp_log_arr[$new_cars_tmp['sno_io']])) | |||
| { | |||
| $last_cars_tmp = $cars_tmp_log_arr[$new_cars_tmp['sno_io']]; | |||
| // 判斷是否跳過 (記錄於一小時內, 相同場站進出 lpr 或 etag) | |||
| if( ( ($last_cars_tmp['lpr'] == $new_cars_tmp['lpr'] && $last_cars_tmp['lpr'] != 'NONE') || | |||
| ($last_cars_tmp['etag'] == $new_cars_tmp['etag'] && $last_cars_tmp['etag'] != 'NONE') ) && $last_cars_tmp['timestamp'] > $new_cars_tmp['timestamp'] - 3600 | |||
| ) | |||
| $skip_or_not = true; | |||
| } | |||
| // 更新 | |||
| $cars_tmp_log_arr[$new_cars_tmp['sno_io']] = $new_cars_tmp; | |||
| $this->vars['mcache']->set(MCACHE_SYNC_888_TMP_LOG, $cars_tmp_log_arr); | |||
| trigger_error(__FUNCTION__ . '..upd ' . MCACHE_SYNC_888_TMP_LOG . " |s:{$skip_or_not}|" . print_r($cars_tmp_log_arr, true)); | |||
| // 跳過 | |||
| if($skip_or_not) | |||
| { | |||
| trigger_error(__FUNCTION__ . '..skip..'); | |||
| return false; | |||
| } | |||
| // [END] 擋相同車號進出 | |||
| switch($parms['io']) | |||
| { | |||
| // 入場 | |||
| case 'CI': | |||
| $result = $this->pks_availables_update(SYNC_PKS_GROUP_ID_CI, -1, false, $parms['sno']); | |||
| break; | |||
| case 'MI': | |||
| $result = $this->pks_availables_update(SYNC_PKS_GROUP_ID_MI, -1, false, $parms['sno']); | |||
| break; | |||
| // 出場 | |||
| case 'CO': | |||
| $result = $this->pks_availables_update(SYNC_PKS_GROUP_ID_CI, 1, false, $parms['sno']); | |||
| break; | |||
| case 'MO': | |||
| $result = $this->pks_availables_update(SYNC_PKS_GROUP_ID_MI, 1, false, $parms['sno']); | |||
| break; | |||
| } | |||
| return $result; | |||
| } | |||
| // 微調剩餘車位數 | |||
| public function pks_availables_update($group_id, $value, $is_renum=true, $station_no=STATION_NO) | |||
| { | |||
| $where_group_arr = array('group_id' => $group_id, 'station_no' => $station_no); | |||
| $rows = $this->db->select('renum, parked, tot') | |||
| ->from('pks_groups') | |||
| ->where($where_group_arr) | |||
| ->limit(1) | |||
| ->get() | |||
| ->row_array(); | |||
| $renum = $rows['renum']; | |||
| $parked = $rows['parked']; | |||
| $tot = $rows['tot']; | |||
| trigger_error("更新車位數|{$group_id}|{$value}|{$is_renum}|".print_r($rows, true)); | |||
| if($is_renum) | |||
| { | |||
| // 一般微調 | |||
| if($value == 0) | |||
| { | |||
| $this->db->where($where_group_arr) | |||
| ->update('pks_groups', array('renum' => 0, 'parked' => 0, 'availables' => $tot)); | |||
| trigger_error(__FUNCTION__ . '..reset everything and exit..'); | |||
| return true; // 中斷 | |||
| } | |||
| else if($value >= 1) | |||
| { | |||
| // 增加 | |||
| $renum = $renum + 1; | |||
| } | |||
| else | |||
| { | |||
| // 減少 | |||
| $renum = $renum - 1; | |||
| } | |||
| $availables = $tot - $parked + $renum; | |||
| // 防止負值 | |||
| if($availables <= 0) | |||
| { | |||
| $availables = 0; | |||
| $parked = $tot; | |||
| $renum = 0; | |||
| trigger_error(__FUNCTION__ . '..ava < 0..auto set (ava = 0, parked = tot, renum = 0)..'); | |||
| } | |||
| else if($availables >= $tot) | |||
| { | |||
| $availables = $tot; | |||
| $parked = 0; | |||
| $renum = 0; | |||
| trigger_error(__FUNCTION__ . '..ava > tot..auto set (ava = tot, parked = 0, renum = 0)..'); | |||
| } | |||
| // 更新 db | |||
| $this->db->where($where_group_arr) | |||
| ->update('pks_groups', array('parked' => $parked, 'availables' => $availables, 'renum' => $renum)); | |||
| } | |||
| else | |||
| { | |||
| // 進出場 | |||
| if($value == 0) | |||
| { | |||
| trigger_error(__FUNCTION__ . '..??? exit..'); | |||
| return true; // 中斷 | |||
| } | |||
| else if($value >= 1) | |||
| { | |||
| // 已停車位數減少, 空車位數增加 | |||
| $parked = $parked - 1; | |||
| } | |||
| else | |||
| { | |||
| // 已停車位數增加, 空車位數減少 | |||
| $parked = $parked + 1; | |||
| } | |||
| /* | |||
| // 防止負值 | |||
| if($parked < 0) | |||
| { | |||
| $parked = 0; | |||
| $renum = 0; // 自動重設 renum | |||
| trigger_error(__FUNCTION__ . '..parked < 0..set (parked = 0, renum = 0)..'); | |||
| } | |||
| else if($parked >= $tot) | |||
| { | |||
| $parked = $tot; | |||
| $renum = 0; // 自動重設 renum | |||
| trigger_error(__FUNCTION__ . '..parked > tot.. = tot..set (parked = tot, renum = 0)..'); | |||
| } | |||
| */ | |||
| $availables = $tot - $parked + $renum; | |||
| // 防止負值 | |||
| if($availables <= 0) | |||
| { | |||
| $availables = 0; | |||
| $parked = $tot; | |||
| $renum = 0; | |||
| trigger_error(__FUNCTION__ . '..ava < 0..auto set (ava = 0, parked = tot, renum = 0)..'); | |||
| } | |||
| else if($availables >= $tot) | |||
| { | |||
| $availables = $tot; | |||
| $parked = 0; | |||
| $renum = 0; | |||
| trigger_error(__FUNCTION__ . '..ava > tot..auto set (ava = tot, parked = 0, renum = 0)..'); | |||
| } | |||
| // 更新 db | |||
| $this->db->where($where_group_arr) | |||
| ->update('pks_groups', array('parked' => $parked, 'availables' => $availables, 'renum' => $renum)); | |||
| } | |||
| // 送出即時訊號 | |||
| if($group_id == SYNC_PKS_GROUP_ID_CI) | |||
| { | |||
| $this->mq_send(MQ_TOPIC_ALTOB, MQ_ALTOB_888 . ",1,{$availables}" . MQ_ALTOB_888_END_TAG); // 送出 888 (汽車) | |||
| } | |||
| else if($group_id == SYNC_PKS_GROUP_ID_MI) | |||
| { | |||
| $this->mq_send(MQ_TOPIC_ALTOB, MQ_ALTOB_888 . ",2,{$availables}" . MQ_ALTOB_888_END_TAG); // 送出 888 (機車) | |||
| } | |||
| else | |||
| { | |||
| $availables_pad = str_pad($availables, 3, '0', STR_PAD_LEFT); // 補零 | |||
| $this->mq_send(MQ_TOPIC_SUBLEVEL, "{$group_id},{$availables_pad}"); // 送出剩餘車位數給字幕機 | |||
| } | |||
| return $this->db->affected_rows(); | |||
| } | |||
| // ------------------------------------------------ | |||
| // | |||
| // 在席系統同步 (END) | |||
| // | |||
| // ------------------------------------------------ | |||
| // ------------------------------------------------ | |||
| // | |||
| // 中控接收端 (START) | |||
| // | |||
| // ------------------------------------------------ | |||
| // 同步場站會員 (功能: 會員同步) | |||
| public function sync_members($info_arr=array('station_no_arr' => STATION_NO)) | |||
| { | |||
| $data_member_arr = array(); | |||
| $data_car_arr = array(); | |||
| try{ | |||
| // 查現況 | |||
| $ch = curl_init(); | |||
| curl_setopt($ch, CURLOPT_URL, SYNC_API_URL . 'member_query_all_in_one'); | |||
| 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 ,10); | |||
| curl_setopt($ch, CURLOPT_TIMEOUT, 10); //timeout in seconds | |||
| curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($info_arr)); | |||
| $data = curl_exec($ch); | |||
| curl_close($ch); | |||
| }catch (Exception $e){ | |||
| trigger_error('error msg:'.$e->getMessage()); | |||
| trigger_error(SYNC_DATA_LOG_TITLE . $e->getMessage()); | |||
| } | |||
| $data_member_arr = json_decode($data, true); | |||
| if (sizeof($data_member_arr) <= 0) | |||
| { | |||
| trigger_error(SYNC_DATA_LOG_TITLE . '.. empty ..'); // 忽略完全沒會員的情況 | |||
| return 'empty'; | |||
| } | |||
| else | |||
| { | |||
| foreach($data_member_arr as $data) | |||
| { | |||
| // create member_car | |||
| $data_car = array | |||
| ( | |||
| 'station_no' => $data['station_no'], | |||
| 'member_no' => $data['member_no'], | |||
| 'lpr' => $data['lpr'], | |||
| 'lpr_correct' => $data['lpr'], | |||
| 'etag' => $data['etag'], | |||
| 'start_time' => $data['start_date'], | |||
| 'end_time' => $data['end_date'] | |||
| ); | |||
| array_push($data_car_arr, $data_car); | |||
| } | |||
| } | |||
| //trigger_error(SYNC_DATA_LOG_TITLE . '.. test ..' . print_r($data_member_arr, true)); | |||
| $this->db->trans_start(); | |||
| // 清空 | |||
| $this->db->empty_table('members'); | |||
| $this->db->empty_table('member_car'); | |||
| // 建立 members | |||
| $this->db->insert_batch('members', $data_member_arr); | |||
| // 建立 member_car | |||
| $this->db->insert_batch('member_car', $data_car_arr); | |||
| $this->db->trans_complete(); | |||
| if ($this->db->trans_status() === FALSE) | |||
| { | |||
| trigger_error(SYNC_DATA_LOG_TITLE . '.. sync fail ..'. '| last_query: ' . $this->db->last_query()); | |||
| return 'fail'; | |||
| } | |||
| trigger_error(SYNC_DATA_LOG_TITLE . '.. sync completed ..'); | |||
| return 'ok'; | |||
| } | |||
| // 同步車牌更換 (功能: 換車牌同步) | |||
| public function sync_switch_lpr($switch_lpr_arr) | |||
| { | |||
| trigger_error( __FUNCTION__ . '..' . print_r($switch_lpr_arr, true)); | |||
| $this->db->trans_start(); | |||
| foreach($switch_lpr_arr as $data) | |||
| { | |||
| $station_no = $data['station_no']; | |||
| $member_no = $data['member_no']; | |||
| $old_lpr = $data['old_lpr']; | |||
| $new_lpr = $data['new_lpr']; | |||
| $new_data = array('lpr' => $new_lpr, 'lpr_correct' => $new_lpr, 'member_no' => $member_no); | |||
| $this->db->update('etag_lpr', $new_data, array('lpr_correct' => $old_lpr)); | |||
| $affect_rows = $this->db->affected_rows(); | |||
| trigger_error(SYNC_DATA_LOG_TITLE . "換車牌更新 etag_lpr 共[{$affect_rows}]筆..".print_r($data, true)); | |||
| /* | |||
| if($station_no == STATION_NO) | |||
| { | |||
| $new_data = array('lpr' => $new_lpr, 'lpr_correct' => $new_lpr, 'member_no' => $member_no); | |||
| $this->db->update('etag_lpr', $new_data, array('lpr_correct' => $old_lpr)); | |||
| $affect_rows = $this->db->affected_rows(); | |||
| trigger_error(SYNC_DATA_LOG_TITLE . "換車牌更新 etag_lpr 共[{$affect_rows}]筆..".print_r($data, true)); | |||
| } | |||
| else | |||
| { | |||
| trigger_error(SYNC_DATA_LOG_TITLE . __FUNCTION__ . "..資料異常..".print_r($data, true)); | |||
| } | |||
| */ | |||
| } | |||
| $this->db->trans_complete(); | |||
| if ($this->db->trans_status() === FALSE) | |||
| { | |||
| trigger_error(SYNC_DATA_LOG_TITLE . '.. sync fail ..'. '| last_query: ' . $this->db->last_query()); | |||
| return 'fail'; | |||
| } | |||
| trigger_error(SYNC_DATA_LOG_TITLE . '.. sync completed ..'); | |||
| return 'ok'; | |||
| } | |||
| // 同步場站費率 | |||
| public function sync_price_plan($info_arr=array('station_no_arr' => STATION_NO)) | |||
| { | |||
| try{ | |||
| // 查另一台主機 | |||
| $ch = curl_init(); | |||
| curl_setopt($ch, CURLOPT_URL, SYNC_API_URL . 'price_plan_query_all_in_one'); | |||
| 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 ,5); | |||
| curl_setopt($ch, CURLOPT_TIMEOUT, 5); //timeout in seconds | |||
| curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($info_arr)); | |||
| $data = curl_exec($ch); | |||
| curl_close($ch); | |||
| }catch (Exception $e){ | |||
| trigger_error('error msg:'.$e->getMessage()); | |||
| } | |||
| $decode_result = json_decode($data, true); | |||
| if (sizeof($decode_result) <= 0) return "empty"; | |||
| $this->db->trans_start(); | |||
| foreach ($decode_result as $key => $value) | |||
| { | |||
| $station_no = $value["station_no"]; | |||
| $tx_price_plan_id = $value["txid"]; | |||
| $tx_type = $value["tx_type"]; | |||
| $price_plan_data = array | |||
| ( | |||
| 'station_no' => $station_no, | |||
| 'tx_type' => $tx_type, | |||
| 'remarks' => $value['remarks'], | |||
| 'price_plan' => $value['price_plan'], | |||
| 'start_time' => $value['start_time'], | |||
| 'valid_time' => $value['valid_time'] | |||
| ); | |||
| // 刪除 | |||
| $this->db->delete('tx_price_plan', array('station_no' => $station_no, 'tx_type' => $tx_type)); | |||
| // 新增 | |||
| $this->db->insert('tx_price_plan', $price_plan_data); | |||
| } | |||
| $this->db->trans_complete(); | |||
| return "ok"; | |||
| } | |||
| // 取得最新未結清 (功能: 行動支付) | |||
| public function get_last_unbalanced_cario($lpr) | |||
| { | |||
| $sql = "SELECT station_no, cario_no, in_time, pay_time, out_time, out_before_time, member_no | |||
| FROM cario | |||
| WHERE | |||
| obj_id = '{$lpr}' AND finished = 0 AND err = 0 | |||
| ORDER BY cario_no DESC | |||
| LIMIT 1 | |||
| "; | |||
| $results = $this->db->query($sql)->result_array(); | |||
| if(isset($results[0])) | |||
| return $results[0]; | |||
| return false; | |||
| } | |||
| // 同步車位現況 (功能: 888 同步, 在席同步) | |||
| public function sync_pks_groups_reload($station_setting) | |||
| { | |||
| $info = array(); | |||
| $station_no_arr = explode(SYNC_DELIMITER_ST_NO, $station_setting['station_no']); | |||
| $station_name_arr = explode(SYNC_DELIMITER_ST_NAME, $station_setting['station_name']); | |||
| $station_888_arr = explode(SYNC_DELIMITER_ST_INFO, $station_setting['station_888']); | |||
| foreach($station_no_arr as $key => $station_no) | |||
| { | |||
| if($station_888_arr[$key] == 1) // 啟用 | |||
| array_push($info, array('station_no' => $station_no_arr[$key], 'station_name' => $station_name_arr[$key])); | |||
| else if($station_888_arr[$key] == 4) // 關閉 | |||
| { | |||
| // 清除 888 | |||
| $this->db->delete('pks_groups', array('station_no' => $station_no_arr[$key])); | |||
| } | |||
| else | |||
| { | |||
| trigger_error(__FUNCTION__ . '..unknown station_888:' . $station_888_arr[$key]); | |||
| } | |||
| } | |||
| if(empty($info)) | |||
| return 'none'; | |||
| return $this->sync_pks_groups($info, true); | |||
| } | |||
| // 同步車位現況 (功能: 888 同步, 在席同步) | |||
| public function sync_pks_groups($info_arr=array(array('station_no' => STATION_NO, 'station_name' => STATION_NAME)), $reload=false) | |||
| { | |||
| if($reload) | |||
| { | |||
| // 確認應該要有的 pks_groups | |||
| $pks_groups_arr = array(); | |||
| $pks_groups_name_arr = array(); | |||
| foreach($info_arr as $data) | |||
| { | |||
| $pks_key = $data['station_no'] . SYNC_DELIMITER_ST_INFO . SYNC_PKS_GROUP_ID_CI; | |||
| array_push($pks_groups_arr, $pks_key); // 汽車 888 | |||
| $pks_key = $data['station_no'] . SYNC_DELIMITER_ST_INFO . SYNC_PKS_GROUP_ID_MI; | |||
| array_push($pks_groups_arr, $pks_key); // 機車 888 | |||
| $pks_groups_name_arr[$data['station_no']] = $data['station_name']. '(888)'; // 群組名稱 | |||
| } | |||
| // 過濾已存在的部份 | |||
| $sql = "SELECT station_no, group_id FROM pks_groups"; | |||
| $current_pks_group = $this->db->query($sql)->result_array(); | |||
| foreach($current_pks_group as $data) | |||
| { | |||
| $pks_key = $data['station_no'] . SYNC_DELIMITER_ST_INFO . $data['group_id']; | |||
| $key = array_search($pks_key, $pks_groups_arr); | |||
| if($key !== false) | |||
| unset($pks_groups_arr[$key]); | |||
| } | |||
| // 建立缺少的部份 | |||
| if(!empty($pks_groups_arr)) | |||
| { | |||
| // [A.開始] | |||
| $this->db->trans_start(); | |||
| foreach($pks_groups_arr as $new_data) | |||
| { | |||
| $pks_info = explode(SYNC_DELIMITER_ST_INFO, $new_data); | |||
| $new_pks_groups_data = array( | |||
| 'station_no' => $pks_info[0], | |||
| 'group_id' => $pks_info[1], | |||
| 'tot' => 100, // 預設車位數 | |||
| 'availables' => 100, // 預設車位數 | |||
| 'floors' => 'TOT', | |||
| 'group_name' => $pks_groups_name_arr[$pks_info[0]] | |||
| ); | |||
| $this->db->insert('pks_groups', $new_pks_groups_data); | |||
| trigger_error(__FUNCTION__ . '..insert pks_groups..'. print_r($new_pks_groups_data, true)); | |||
| } | |||
| // [C.完成] | |||
| $this->db->trans_complete(); | |||
| if ($this->db->trans_status() === FALSE) | |||
| { | |||
| trigger_error(__FUNCTION__ . '..trans_error..' . '| last_query: ' . $this->db->last_query()); | |||
| return 'fail'; // 中斷 | |||
| } | |||
| } | |||
| } | |||
| $sql = "SELECT pks_groups.station_no, | |||
| pks_groups.group_name as group_name, pks_groups.tot as tot, pks_groups.parked as parked, pks_groups.availables as availables, pks_groups.group_id as group_id, pks_groups.renum as renum | |||
| FROM pks_groups | |||
| ORDER BY pks_groups.group_id DESC"; | |||
| $pks_group_query_data = $this->db->query($sql)->result_array(); | |||
| //trigger_error(__FUNCTION__ . '..sync..' . print_r($pks_group_query_data, true)); | |||
| // 同步 | |||
| require_once(ALTOB_SYNC_FILE); | |||
| $sync_agent = new AltobSyncAgent(); | |||
| $sync_agent->init(STATION_NO); // 已帶上的資料場站編號為主 | |||
| $sync_result = $sync_agent->upd_pks_groups(json_encode($pks_group_query_data, JSON_UNESCAPED_UNICODE)); | |||
| trigger_error( SYNC_DATA_LOG_TITLE . '..'. __FUNCTION__ . "..upd_pks_groups.." . $sync_result); | |||
| } | |||
| // 重新載入場站設定 | |||
| public function reload_station_setting() | |||
| { | |||
| try{ | |||
| // 查現況 | |||
| $ch = curl_init(); | |||
| curl_setopt($ch, CURLOPT_URL, SYNC_API_URL . 'station_setting_query'); | |||
| 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 ,10); | |||
| curl_setopt($ch, CURLOPT_TIMEOUT, 10); //timeout in seconds | |||
| curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(array())); | |||
| $return_result = curl_exec($ch); | |||
| curl_close($ch); | |||
| }catch (Exception $e){ | |||
| trigger_error('error msg:'.$e->getMessage()); | |||
| } | |||
| $station_setting_result = json_decode($return_result, true); | |||
| if(!isset($station_setting_result['results']) || sizeof($station_setting_result['results']) <= 0) | |||
| { | |||
| trigger_error(__FUNCTION__ . '..fail..' . print_r($return_result, true)); | |||
| return 'fail'; | |||
| } | |||
| $station_ip_str = $station_setting_result['station_ip']; // 場站目前對外IP | |||
| $station_setting_arr = $station_setting_result['results']; | |||
| $station_no_arr = array(); | |||
| $station_name_arr = array(); | |||
| $station_888_arr = array(); | |||
| foreach($station_setting_arr as $data) | |||
| { | |||
| array_push($station_no_arr, $data['station_no']); | |||
| array_push($station_name_arr, $data['short_name']); | |||
| array_push($station_888_arr, $data['station_888']); | |||
| } | |||
| $station_no_str = implode(SYNC_DELIMITER_ST_NO, $station_no_arr); // 取值時會用到 | |||
| $station_name_str = implode(SYNC_DELIMITER_ST_NAME, $station_name_arr); // 純顯示 | |||
| $station_888_str = implode(SYNC_DELIMITER_ST_INFO, $station_888_arr); // 場站888設定 | |||
| // 設定到 mcache | |||
| $this->vars['mcache']->set(MCACHE_STATION_NO_STR, $station_no_str); | |||
| $this->vars['mcache']->set(MCACHE_STATION_NAME_STR, $station_name_str); | |||
| $this->vars['mcache']->set(MCACHE_STATION_IP_STR, $station_ip_str); | |||
| $this->vars['mcache']->set(MCACHE_STATION_888_STR, $station_888_str); | |||
| return 'ok'; | |||
| } | |||
| // 取得目前場站設定 | |||
| public function station_setting_query($reload=false) | |||
| { | |||
| $station_no_str = $this->vars['mcache']->get(MCACHE_STATION_NO_STR); | |||
| $station_name_str = $this->vars['mcache']->get(MCACHE_STATION_NAME_STR); | |||
| $station_ip_str = $this->vars['mcache']->get(MCACHE_STATION_IP_STR); | |||
| $station_888_str = $this->vars['mcache']->get(MCACHE_STATION_888_STR); | |||
| if($reload || empty($station_no_str) || empty($station_name_str) || empty($station_ip_str) || empty($station_888_str)) | |||
| { | |||
| $result = $this->reload_station_setting(); | |||
| if($result == 'ok') | |||
| { | |||
| $station_no_str = $this->vars['mcache']->get(MCACHE_STATION_NO_STR); | |||
| $station_name_str = $this->vars['mcache']->get(MCACHE_STATION_NAME_STR); | |||
| $station_ip_str = $this->vars['mcache']->get(MCACHE_STATION_IP_STR); | |||
| $station_888_str = $this->vars['mcache']->get(MCACHE_STATION_888_STR); | |||
| } | |||
| else | |||
| { | |||
| /* | |||
| $station_setting = array(); | |||
| $station_setting['station_no'] = STATION_NO; | |||
| $station_setting['station_name'] = STATION_NAME; | |||
| $station_setting['station_ip'] = STATION_IP; | |||
| return $station_setting; | |||
| */ | |||
| return false; | |||
| } | |||
| } | |||
| $station_setting = array(); | |||
| $station_setting['station_no'] = $station_no_str; | |||
| $station_setting['station_name'] = $station_name_str; | |||
| $station_setting['station_ip'] = $station_ip_str; | |||
| $station_setting['station_888'] = $station_888_str; | |||
| return $station_setting; | |||
| } | |||
| // ------------------------------------------------ | |||
| // | |||
| // 中控接收端 (END) | |||
| // | |||
| // ------------------------------------------------ | |||
| // ------------------------------------------------ | |||
| // | |||
| // 其它 (START) | |||
| // | |||
| // ------------------------------------------------ | |||
| // 手動新增入場資料 | |||
| public function gen_carin($parms) | |||
| { | |||
| $in_time = date('Y-m-d H:i:s'); | |||
| $data = array( | |||
| 'station_no' => $parms['sno'], | |||
| 'obj_type' => 1, | |||
| 'obj_id' => $parms['lpr'], | |||
| 'etag' => '', | |||
| 'in_out' => $parms['io'], | |||
| 'finished' => 0, | |||
| 'in_time' => $in_time, | |||
| 'in_lane' => $parms['ivsno'], | |||
| 'out_before_time' => $in_time | |||
| ); | |||
| $this->db->insert('cario', $data); | |||
| trigger_error("新增入場資料:".print_r($parms, true)); | |||
| require_once(ALTOB_SYNC_FILE); | |||
| // 傳送進場記錄 | |||
| $sync_agent = new AltobSyncAgent(); | |||
| $sync_agent->init($parms['sno'], $in_time); | |||
| $sync_agent->cario_no = $this->db->insert_id(); // 進出編號 | |||
| $sync_result = $sync_agent->sync_st_in($parms); | |||
| trigger_error( SYNC_DATA_LOG_TITLE . '..'. __FUNCTION__ . "..sync_st_in.." . $sync_result); | |||
| } | |||
| // ------------------------------------------------ | |||
| // | |||
| // 其它 (END) | |||
| // | |||
| // ------------------------------------------------ | |||
| } | |||
| @@ -0,0 +1,127 @@ | |||
| <?php | |||
| /* | |||
| file: Txdata_model.php 交易資訊系統 | |||
| */ | |||
| class Txdata_model extends CI_Model | |||
| { | |||
| var $mcache; | |||
| var $mqtt; | |||
| function __construct() | |||
| { | |||
| parent::__construct(); | |||
| $this->load->database(); | |||
| $this->now_str = date('Y-m-d H:i:s'); | |||
| } | |||
| public function init($vars) | |||
| { | |||
| $this->mcache = $vars['mcache']; | |||
| $this->mqtt = $vars['mqtt']; | |||
| } | |||
| // 取得所有場站有效費率 | |||
| public function get_all_valid_price_plan($station_no) | |||
| { | |||
| $result = $this->db->select('tx_price_plan_id as txid, tx_type, station_no, remarks, price_plan, start_time, valid_time, create_time') | |||
| ->from('tx_price_plan') | |||
| ->where(array( | |||
| 'start_time <= ' => $this->now_str, | |||
| 'valid_time > ' => $this->now_str, | |||
| 'station_no' => $station_no | |||
| )) | |||
| ->get() | |||
| ->result_array(); | |||
| return $result; | |||
| } | |||
| // 取得場站費率設定 | |||
| // http://203.75.167.89/txdata.html/get_price_plan/12112/0 | |||
| public function get_price_plan($station_no, $tx_type) | |||
| { | |||
| $result = $this->db->select('price_plan') | |||
| ->from('tx_price_plan') | |||
| ->where(array( | |||
| 'start_time <= ' => $this->now_str, | |||
| 'valid_time > ' => $this->now_str, | |||
| 'station_no' => $station_no, | |||
| 'tx_type' => $tx_type | |||
| )) | |||
| ->get() | |||
| ->result_array(); | |||
| return $result; | |||
| } | |||
| // 取得特殊日期設定 | |||
| // http://203.75.167.89/txdata.html/get_date_plan/12345678/23456789 | |||
| public function get_date_plan($inTime, $balanceTime) | |||
| { | |||
| $inDateTimestamp = strtotime(date("Y-m-d", $inTime)); | |||
| $balanceDateTimestamp = strtotime(date("Y-m-d", $balanceTime)); | |||
| $result = $this->db->select('p_type, p_date') | |||
| ->from('tx_date_plan') | |||
| ->where("p_date BETWEEN FROM_UNIXTIME({$inDateTimestamp}) AND FROM_UNIXTIME({$balanceDateTimestamp})") | |||
| //->where("p_date BETWEEN '{$inDate}' AND '{$outDate}'") | |||
| ->get() | |||
| ->result_array(); | |||
| return $result; | |||
| } | |||
| // 同步場站費率 | |||
| public function sync_price_plan() | |||
| { | |||
| try{ | |||
| $param = array('station_no' => STATION_NO); | |||
| // 查另一台主機 | |||
| $ch = curl_init(); | |||
| curl_setopt($ch, CURLOPT_URL, 'http://61.219.172.11:60123/admins.html/price_plan_query'); | |||
| 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 ,5); | |||
| curl_setopt($ch, CURLOPT_TIMEOUT, 5); //timeout in seconds | |||
| curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($param)); | |||
| $data = curl_exec($ch); | |||
| curl_close($ch); | |||
| }catch (Exception $e){ | |||
| trigger_error('error msg:'.$e->getMessage()); | |||
| } | |||
| $decode_result = json_decode($data, true); | |||
| if (sizeof($decode_result) <= 0) return "empty"; | |||
| $this->db->trans_start(); | |||
| foreach ($decode_result as $key => $value) | |||
| { | |||
| $station_no = $value["station_no"]; | |||
| $tx_price_plan_id = $value["txid"]; | |||
| $tx_type = $value["tx_type"]; | |||
| $price_plan_data = array | |||
| ( | |||
| 'station_no' => $station_no, | |||
| 'tx_type' => $tx_type, | |||
| 'remarks' => $value['remarks'], | |||
| 'price_plan' => $value['price_plan'], | |||
| 'start_time' => $value['start_time'], | |||
| 'valid_time' => $value['valid_time'] | |||
| ); | |||
| // 刪除 | |||
| $this->db->delete('tx_price_plan', array('station_no' => $station_no, 'tx_type' => $tx_type)); | |||
| // 新增 | |||
| $this->db->insert('tx_price_plan', $price_plan_data); | |||
| } | |||
| $this->db->trans_complete(); | |||
| return "ok"; | |||
| } | |||
| } | |||
| @@ -0,0 +1,76 @@ | |||
| <?php | |||
| /* | |||
| file: User_model.php 管理登入系統 | |||
| */ | |||
| class User_model extends CI_Model | |||
| { | |||
| function __construct() | |||
| { | |||
| parent::__construct(); | |||
| $this->load->database(); | |||
| } | |||
| // 登入 | |||
| public function user_login($data) | |||
| { | |||
| $login_name = $data['login_name']; | |||
| $pswd = $data['pswd']; | |||
| $this -> db -> select('login_name, user_type, status'); | |||
| $this -> db -> from('users'); | |||
| $this -> db -> where('login_name', $login_name); | |||
| $this -> db -> where('pswd', MD5($pswd)); | |||
| $this -> db -> where('status', 1); // '狀態, 1:正常, 2:暫時停權, 3:永久停權' | |||
| $this -> db -> limit(1); | |||
| $query = $this -> db -> get(); | |||
| if($query -> num_rows() == 1) | |||
| { | |||
| return $query->result(); | |||
| } | |||
| else | |||
| { | |||
| return false; | |||
| } | |||
| } | |||
| // 新增 | |||
| public function user_insert($data) | |||
| { | |||
| $data['status'] = 1; // '狀態, 1:正常, 2:暫時停權, 3:永久停權' | |||
| $this->db->insert('users', $data); | |||
| return true; | |||
| } | |||
| // 修改 | |||
| public function user_update($data, $target_name) | |||
| { | |||
| $this->db->update('users', $data, array('login_name' => $target_name)); | |||
| return true; | |||
| } | |||
| // 查詢 | |||
| public function user_query() | |||
| { | |||
| $results = $this->db->select('login_name, user_name, status, modify_time, user_type') | |||
| ->from('users') | |||
| ->where(array('user_type' => 'user')) // 'admin:最高管理者, user:用戶' | |||
| ->order_by('modify_time', 'desc') | |||
| ->get() | |||
| ->result_array(); | |||
| return $results; | |||
| } | |||
| // 刪除 | |||
| public function user_delete($login_name) | |||
| { | |||
| $this->db->delete('users', array('login_name' => $login_name)); | |||
| return true; | |||
| } | |||
| } | |||
| @@ -0,0 +1,11 @@ | |||
| <!DOCTYPE html> | |||
| <html> | |||
| <head> | |||
| <title>403 Forbidden</title> | |||
| </head> | |||
| <body> | |||
| <p>Directory access is forbidden.</p> | |||
| </body> | |||
| </html> | |||