get_one("select * from tb_pos_device where serialno = '".addslashes($serialno)."'"); $device_id = intval($deviceInfo['id']); // 获取远程地址,即访问的客户端ip地址 $ip = $_SERVER["REMOTE_ADDR"]; $s1 = $json; if(strlen($s1) > 2000) { $s1 = substr($s1, 0, 2000).'..'; } // 插入POS机日志记录 $db->query("insert into tb_pos_device_log set device_id = {$device_id}, serialno = '".addslashes($serialno)."', ip = '".addslashes($ip)."', path = '".addslashes($qs)."', request = '".addslashes($s1)."', response = '', addtime = now() "); $log_id = $db->insert_id(); if(!$deviceInfo) { $db->query("update tb_pos_device_log set response='no_device' where id=".$log_id); exit; } // 从数据记录中获取信息 $company_id = intval($deviceInfo['company_id']); $dining_hall_id = intval($deviceInfo['dining_hall_id']); $channel_id = intval($deviceInfo['channel_id']); // md5编码签名 $sign2 = md5($post['time'].$post['noncestr'].$deviceInfo['cardpwd']); if($sign2 !== $post['sign']) { //签名错误 $db->query("update tb_pos_device_log set response='sign_err' where id=".$log_id); exit; } // 将api和data数据处理编码后插入到tb_pos_device_log表,并终止脚本运行 function response_pos($api, $data) { global $deviceInfo, $post, $log_id, $db; $noncestr = md5(microtime().'_'.rand()); $time = time(); $sign = md5($time.$noncestr.$deviceInfo['cardpwd']); $data['sign'] = $sign; $data['api'] = $api; $data['interval'] = '10000'; $data['transaction_id'] = $post['transaction_id']?$post['transaction_id']:"100"; $json = json_encode($data, JSON_UNESCAPED_UNICODE); $db->query("update tb_pos_device_log set response='".addslashes($json)."' where id=".$log_id); echo $json; exit; } // 向本机地址发送请求,拼接端口号、路径、post参数和header,调用自定义gquery函数 function self_query($path, $post) { return gquery("http://127.0.0.1:".$_SERVER['SERVER_PORT'].$path, $post, array('Host: '.$_SERVER['SERVER_NAME'])); } // 从post参数中获取pay_mode等参数 function pos_check_user() { global $post, $db, $company_id; $pay_mode = $post['params']['pay_mode']; $pay_code = $post['params']['pay_code']; if($pay_mode == '5') { //二维码 $qr_code = trim($post['params']['qr_code']); if(!$qr_code) exit; if(substr($qr_code, 0, 4) != '[st]' || substr($qr_code, -1) != ';') exit; // 截取qr_code,截取第4位到倒数第2位字符 $s = substr($qr_code, 4, -1); // 将字符串分割成数组 $a = explode(",", $s); if(count($a) != 2) exit; $code = $a[0]; $hash = $a[1]; // 关联数组,返回类似json的结构 return array('type' => 'qr', 'code' => $code); } // 搜索父字符串中子字符串的位置,如果pay_code中不以ymzs_开头,则退出 if(strpos($pay_code, 'yzms_') !== 0) exit; $uid = intval(substr($pay_code, 5)); $uInfo = $db->get_one("select * from tb_user where id = '{$uid}' and enabled != '0' and company_id=".$company_id); if(!$uInfo) { $arr = array ( 'result_code' => '2', 'result_msg' => "err", //10寸屏蔽失败时界面显示此内容,result_code=2 'tts' => "用户不存在", //语音播报,为空时不报,TTS语音 'result' => array (), //服务器返回结果数据,查询信息无 'timeout' => '5', //取餐超时时间,秒为单位,注:特殊修改机型才有此功能 'msg' => array (array ('line' => '用户不存在!',)), ); response_pos($post['api'], $arr); } return $uInfo; } // 顶层代码,判断qs中参数 if($qs == 'heartbeat' || $qs == 'addperson' || $qs == 'delperson') { //心跳 // 新增人员 if($qs == 'addperson' && $post['whitelist']) { foreach($post['whitelist'] as $item) { $uid = intval(str_replace('yzms_', '', $item['account_id'])); $rec_id = intval($item['rec_id']); $db->query("update tb_pos_device_user set status=2,rs='".$item['result_code']."' where id = '{$rec_id}' and uid = '{$uid}'"); } } // 删除人员 if($qs == 'delperson' && $post['whitelist']) { foreach($post['whitelist'] as $item) { $uid = intval(str_replace('yzms_', '', $item['account_id'])); $rec_id = intval($item['rec_id']); $db->query("delete from tb_pos_device_user where id = '{$rec_id}' and uid = '{$uid}'"); } } // 心跳 if($qs != 'heartbeat' || (time() - strtotime($deviceInfo['synctime']) > 60)) { //1分钟检测一次用户同步 $db->query("update tb_pos_device set synctime=now() where id = ".$device_id); $userList_s = $db->get_all("select id, username, cellphone, deptname from tb_user where enabled = '1' and company_id = '{$company_id}'"); $userList_d = $db->get_all("select * from tb_pos_device_user where device_id = '{$device_id}'"); $data = $db->get_all("select a.* from tb_user_face a, tb_user b where a.user_id=b.id and b.company_id = '{$company_id}'"); $faceInfo = array(); foreach($data as $item) { if(is_file("../backstage/".$item['path'])) { $faceInfo[$item['user_id']] = $item; } } $data = $db->get_all("select a.* from tb_user_idcard a, tb_user b where a.user_id=b.id and b.company_id = '{$company_id}' and a.state=1 order by a.id"); $cardInfo = array(); foreach($data as $item) { $cardInfo[$item['user_id']] = $item; } foreach($userList_s as $key => $item) { $uid = $item['id']; $info1 = $faceInfo[$uid]; $userList_s[$key]['facecode'] = $info1['facecode'].''; $userList_s[$key]['facepath'] = $info1['path'].''; $info1 = $cardInfo[$uid]; $userList_s[$key]['cardno'] = $info1['cardno'].''; } $sUserInfo = array(); foreach($userList_s as $item) { $sUserInfo[$item['id']] = $item; } $dUserInfo = array(); foreach($userList_d as $item) { $dUserInfo[$item['uid']] = $item; } $row = $db->get_one("select * from tb_config where class = 'HOST'"); $host = $row['value']; $addList = array(); //增加列表 $maxcount = 100; foreach($userList_s as $item) { $uid = $item['id']; if(!$dUserInfo[$uid]) { $addList[] = $item; if(count($addList) >= $maxcount) break; //限制一次20个 continue; } $item2 = $dUserInfo[$uid]; if( ($item2['facecode'].'') !== ($item['facecode'].'') || ($item2['cardno'].'') !== ($item['cardno'].'') || ($item2['username'].'') !== ($item['name'].'') || ($item2['cellphone'].'') !== ($item['cellphone'].'') || ($item2['deptname'].'') !== ($item['deptname'].'') ) { $addList[] = $item; if(count($addList) >= $maxcount) break; continue; } if($item2['status'] == 1 && time()-strtotime($item2['sendtime']) > 300) { //距上次下发5分钟后还没收到确认 $addList[] = $item; if(count($addList) >= $maxcount) break; continue; } } // 增加列表 if($addList) { $whitelist = array(); foreach($addList as $item) { $uid = $item['id']; $face_url = ''; if($item['facepath']) { $face_url = 'https://'.$host.'/backstage/'.$item['facepath']; } $row1 = $db->get_one("select * from tb_pos_device_user where device_id = '".addslashes($device_id)."' and uid = '".addslashes($uid)."'"); $sqlext = " name = '".addslashes($item['username'])."', cellphone = '".addslashes($item['cellphone'])."', deptname = '".addslashes($item['deptname'])."', cardno = '".addslashes($item['cardno'])."', facecode = '".addslashes($item['facecode'])."', sendtime = now(), status = 1, rs = '' "; if(!$row1) { $db->query("insert into tb_pos_device_user set device_id = '".addslashes($device_id)."', uid = '".addslashes($uid)."', {$sqlext}, addtime = now() ", 'SILENT'); $log_id1 = $db->insert_id(); } else { $db->query("update tb_pos_device_user set {$sqlext} where id=".$row1['id']); $log_id1 = $row1['id']; } $whitelist[] = array ( 'rec_id' => $log_id1.'', //可为数据库中的唯一id,可以是字符串,可以是整数,可为空字符 'account_id' => 'yzms_'.$uid, //帐号,唯一,50个字符,必填 'emp_id' => 'emp_'.$uid, //工号,唯一,50个字符,必填 'emp_fname' => $item['username'], //姓名,50个字符,必填 'depart_name' => $item['deptname'], //部门,50个字符,必填 'job_name' => '', //职务,仅10.1寸去向牌门禁机有效 'tel' => $item['cellphone'], //电话,仅10.1寸去向牌门禁机有效 'sex' => '', //性别,可为空字符 'birth_date' => '', //出生日期,可为空字符 'valid_date' => '2099-01-01', //有效日期,必填 'level_id' => '1', //级别,整数,必须是整数,必填,用不到的话填0 'card_sn' => $item['cardno'], //卡序列号,整数,没有时,用空字符,注意:卡号时前面不能有0 'door_right' => '', //门权限, 预留,没有时用空字符 'url' => $face_url, //个人相片的url地址,可为空字符,表示无相片 'groups' => '0', //组别为第3组,长整型,二进制时从最低位开始为1组,0表示无,1表示有,例如第3组的二进制表示0000100,转换为十进制则是4,第3组的groups为4,必填,不需要时填0 'access_pwd' => '1234', //个人密码,整数,4位,不足补0,必填 'state' => '0', //整数,状态:0正常 2挂失(只有刷卡时才会判断,人脸不判断,另离线时才判断,在线由平台判断),为整数,不能非整数,必填 'twins' => '', //注意固定为空!,必填 'retain_photo' => '0', //整数,下载个人相片处理方式, 仅url为空时才有效, = 0默认删除相片 、 =1保留相片还要识别,必填,无相片时统一此值用0,当url有值时按url的值处理,可以固定为0 'begin_date' => '2022-04-01 00:00:00',//开始时间 'end_date' => '2099-01-01 23:59:59', //结束时间 'time' => array (), ); } $arr = array ( 'whitelist' => $whitelist, ); response_pos('addperson', $arr); exit; } $delList = array(); //删除列表 $maxcount = 100; foreach($userList_d as $item) { $uid = $item['uid']; if($item['status'] == 4) { if(time()-strtotime($item['sendtime']) > 300) { //距上次下发删除5分钟后还没收到确认 if($item['err_num'] < 3) { $db->query("update tb_pos_device_user set sendtime = now(), status = 4, rs = '',err_num=err_num+1 where id=".$item['id']); $delList[] = $item; if(count($delList) >= $maxcount) break; //限制一次20个 } else { $db->query("delete from tb_pos_device_user where id=".$item['id']); } } continue; } if(!$sUserInfo[$uid]) { $delList[] = $item; if(count($delList) >= $maxcount) break; //限制一次20个 continue; } } if($delList) { $whitelist = array(); foreach($delList as $item) { $log_id1 = $item['id']; $uid = $item['uid']; $whitelist[] = array ( 'rec_id' => $log_id1.'', //服务器端数据库的唯一id 'account_id' => 'yzms_'.$uid, //帐号 'emp_id' => 'emp_'.$uid, //工号 'only_del_photo' => '0', //=0删除名单 =1名单不删除只删除个人相片 ); } $arr = array ( 'whitelist' => $whitelist, ); response_pos('delperson', $arr); exit; } } $records = $post['records']; $arr = array ( 'setmname' => '', ); if($records) { $records2 = array(); foreach($records as $item) { $records2[] = array('id' => $item['id']); } $arr['records'] = $records2; } response_pos('heartbeat', $arr); } // 在线消费,无消费确认,无查询,直接消费 else if($qs == 'real') { $api = $post['api']; if($api == 'takemeal' || $api == 'takemealok') { //取餐 $uInfo = pos_check_user(); $uid = $uInfo['id']; function get_today_dates($dining_hall_id) { global $db; $data = $db->get_all("select * from tb_date where dining_hall_id={$dining_hall_id} and dc_date = '".date("Y-m-d")."'"); $nowtime = date('H:i'); $all = array(); foreach($data as $item) { $dc_type = $item['dc_type']; $meal_info = $db->get_one("select * from tb_meal_type where status=1 and id=".intval($dc_type)); if( $nowtime >= $meal_info['start_time'] && $nowtime < $meal_info['end_time']) { $all[] = $item; } } return $all; } $dates = get_today_dates($dining_hall_id); $order = ''; for($i = 1; $i <= 2; $i++) { foreach($dates as $date) { $sqlext = " uid = {$uid} "; if($uInfo['type'] == 'qr') { //取餐码 $sqlext = " take_food_code = '".addslashes($uInfo['code'])."' "; } $row = $db->get_one("select * from tb_order where {$sqlext} and date_id=".$date['id']." and state_id =".($i==1?6:3)); if($row) { $order = $row; if($uInfo['type'] == 'qr') { //取餐码 $uInfo = $db->get_one("select * from tb_user where id = '".$order['uid']."'"); if(!$uInfo) exit; $uid = $uInfo['id']; } break; } } if($order) break; } if(!$order) { if($uInfo['type'] == 'qr') { //取餐码 $arr = array ( 'result_code' => '2', 'result_msg' => "err", //10寸屏蔽失败时界面显示此内容,result_code=2 'tts' => "取餐码错误", //语音播报,为空时不报,TTS语音 'result' => array (), //服务器返回结果数据,查询信息无 'msg' => array ( array ( 'line' => '取餐码错误', ), ), 'timeout' => '5', //取餐超时时间,秒为单位,注:特殊修改机型才有此功能 ); } else { $arr = array ( 'result_code' => '2', 'result_msg' => "err", //10寸屏蔽失败时界面显示此内容,result_code=2 'tts' => "没有该时段的订餐记录", //语音播报,为空时不报,TTS语音 'result' => array (), //服务器返回结果数据,查询信息无 'msg' => array ( array ( 'line' => '没有该时段的订餐记录', ), array ( 'line' => '姓名: '.$uInfo['username'], ), array ( 'line' => '手机号: '.$uInfo['cellphone'], ), ), 'timeout' => '5', //取餐超时时间,秒为单位,注:特殊修改机型才有此功能 ); } response_pos($api, $arr); } $s = self_query("/api/order/take", array('take_code' => $order['take_food_code'], 'dining_hall_id' => $dining_hall_id, 'channelid' => $channel_id)); $rs = json_decode($s, true); if($rs['status'] != 1) { $message = '取餐失败'; if($rs['message']) $message = $rs['message']; $arr = array ( 'result_code' => '2', 'result_msg' => "err", //10寸屏蔽失败时界面显示此内容,result_code=2 'tts' => $message, //语音播报,为空时不报,TTS语音 'result' => array (), //服务器返回结果数据,查询信息无 'timeout' => '5', //取餐超时时间,秒为单位,注:特殊修改机型才有此功能 'msg' => array (array ('line' => $message,)), ); response_pos($api, $arr); } $takeInfo = $rs['data']['list'][0]; $detail = array(); foreach($takeInfo['order_detail'] as $item) { $detail[] = array ( 'menu' => $item['dish_name'], 'amount' => $item['dish_amount'], ); } $take_status = $takeInfo['take_status']; $tts = ''; $result_msg = ''; $timeout = '5'; if($take_status == 1) { $tts = ($api == 'takemealok'?($uInfo['username']."取餐成功"):""); $result_msg = ($api == 'takemealok'?"取餐成功":"查询成功"); $timeout = ($api == 'takemealok'?"1":"10"); } else { $tts = '您已取过餐'; $result_msg = '您已取过餐'; $timeout = '5'; } $arr = array ( 'result_code' => ($take_status==1?'0':'1'), //0成功 非0失败,1表示已取餐,也要显示菜品信息,2其它失败 'result_msg' => $result_msg, //10寸屏蔽失败时界面显示此内容,result_code=2 'tts' => $tts, //语音播报,为空时不报,TTS语音 'result' => array (), //服务器返回结果数据,查询信息无 'msg' => array ( array ( 'line' => '订单号:'.$order['code'], ), array ( 'line' => '姓名: '.$uInfo['username'], ), array ( 'line' => '手机号: '.$uInfo['cellphone'], ), ), 'detail' => $detail, 'timeout' => $timeout, //取餐超时时间,秒为单位,注:特殊修改机型才有此功能 ); response_pos($api, $arr); } else if($api == 'infoquery') { //消费前查询用户 $uInfo = pos_check_user(); $uid = $uInfo['id']; $row = $db->get_one("select sum( account ) as c from tb_account where user_id = '{$uid}'"); $arr = array ( 'tts' => '', 'msg' => array (), 'balance' => '', //余额显示测试无效 'query_code' => '0', //注意取餐机时应答为1,消费机时为0 'result_code' => '0', 'result' => array ( array ( 'account_id' => '', 'consume' => '', 'balance' => round($row['c']*100).'', 'sign' => '', 'Corrections' => '', ) ), 'title' => '云中美食', 'emp_fname' => $uInfo['username'], 'result_msg' => '', 'detail' => array (), ); response_pos('infoquery', $arr); } else if($api == 'posonline') { //消费 $uInfo = pos_check_user(); $uid = $uInfo['id']; $amount = intval($post['params']['amount']); if($amount <= 0) exit; $amount = $amount/100; $pay_mode = $post['params']['pay_mode']; // 0人脸 1云卡 2卡序列号 3取餐码 5二维码 $post = array('ftid' => $dining_hall_id, 'channelid' => $channel_id, 'fee' => $amount); if($pay_mode == 0) { //0人脸 $row1 = $db->get_one("select * from tb_user_face where user_id = '{$uid}'"); if(!$row1) exit; $post['type'] = 'face'; $post['code'] = $row1['card']; } else if($pay_mode == 2) { //2卡序列号 $row1 = $db->get_one("select * from tb_user_idcard where user_id = '{$uid}' and state = '1'"); if(!$row1) exit; $post['type'] = 'ic'; $post['code'] = $row1['cardno']; } else if($pay_mode == 5) { //5付款码 if($uInfo['type'] != 'qr') exit; $post['type'] = 'qr'; $post['code'] = $uInfo['code']; } else { exit; } $s = self_query("/api/user/qrpay", $post); $rs = json_decode($s, true); if($rs['status'] != 1) { $message = '付款失败'; if($rs['message']) $message = $rs['message']; $arr = array ( 'result_code' => '2', 'result_msg' => "err", //10寸屏蔽失败时界面显示此内容,result_code=2 'tts' => $message, //语音播报,为空时不报,TTS语音 'result' => array (), //服务器返回结果数据,查询信息无 'timeout' => '5', //取餐超时时间,秒为单位,注:特殊修改机型才有此功能 'msg' => array (array ('line' => $message,)), ); response_pos($api, $arr); } if($uInfo['type'] == 'qr') { $row1 = $db->get_one("select * from tb_payqr where code = '".addslashes($uInfo['code'])."'"); $uid = intval($row1['uid']); $uInfo = $db->get_one("select * from tb_user where id = '".$uid."'"); } $arr = array ( 'result_code' => '0', //0成功,7需要密码消费,消费机出现输入密码的界面,密码输入正确后,消费机再次调用接口,psd_state=1,服务器收到为1时,则消费成功,其它失败 'result_msg' => '', 'result' => array (), 'tts' => $uInfo['username'].' 消费'.$amount.'元成功', 'timeout' => '10', 'msg' => array ( array ( 'line' => '姓名: '.$uInfo['username'], ), array ( 'line' => '消费: '.$amount.'元', ), array ( 'line' => '余额: '.$rs['data']['balance'].'元', ), ), ); response_pos('posonline', $arr); } } else if($qs == 'takephoto') { $arr = array ( 'result_code' => '0', //0成功 'result_msg' => '', 'result' => array (), ); response_pos('takephoto', $arr); }