diff --git a/application/admin/controller/Agent.php b/application/admin/controller/Agent.php index 911d240..a0b751e 100755 --- a/application/admin/controller/Agent.php +++ b/application/admin/controller/Agent.php @@ -200,6 +200,9 @@ class Agent extends Common{ if( empty($pay_channel) ){ die(json_encode(['code'=>0,'msg'=>'请选择支付渠道'])); } + if( $agent_type == 2 && $pay_channel != 'OPR' ){ + die(json_encode(['code'=>0,'msg'=>'人工上分模式只能选OPR渠道'])); + } if( !in_array($type_xima,[1,2]) ){ die(json_encode(['code'=>0,'msg'=>'洗码方式错误'])); } @@ -433,6 +436,7 @@ class Agent extends Common{ $data['price_tc_ths'] = $price_tc_ths; $data['price_tc_hjths'] = $price_tc_hjths; + $data['area_id'] = 3; $data['referral_code'] = getRandCode(); // $data['agent_commission_tc'] = $agent_commission_tc; // $data['agent_commission_tc_banker'] = $agent_commission_tc_banker; diff --git a/application/admin/controller/Pcapi.php b/application/admin/controller/Pcapi.php index 6f55174..7f24d2d 100755 --- a/application/admin/controller/Pcapi.php +++ b/application/admin/controller/Pcapi.php @@ -905,7 +905,6 @@ class Pcapi extends Controller{ //桌子信息 $table['boot_num'] = $boot['boot_num']; - $table['boot_id'] = $boot['id']; $table['player_1_count'] = Db::connect('DB2')->name($numberTabTable)->where(array('table_id' => $table['id'], 'boot_id' => $boot['id'], 'win_player_1' => 1))->count(); $table['player_2_count'] = Db::connect('DB2')->name($numberTabTable)->where(array('table_id' => $table['id'], 'boot_id' => $boot['id'], 'win_player_2' => 1))->count(); $table['player_3_count'] = Db::connect('DB2')->name($numberTabTable)->where(array('table_id' => $table['id'], 'boot_id' => $boot['id'], 'win_player_3' => 1))->count(); @@ -1047,7 +1046,6 @@ class Pcapi extends Controller{ $boot = Db::connect('DB2')->name($bootTabTable)->where('table_id',$table['id'])->order('id DESC')->find(); if($boot){ $table['boot_num'] = $boot['boot_num']; - $table['boot_id'] = $boot['id']; $table['player_1_count'] = Db::connect('DB2')->name($numberTabTable)->where(array('boot_id' => $boot['id'], 'win_player_1' => 1))->count(); $table['player_2_count'] = Db::connect('DB2')->name($numberTabTable)->where(array('boot_id' => $boot['id'], 'win_player_2' => 1))->count(); $table['player_3_count'] = Db::connect('DB2')->name($numberTabTable)->where(array('boot_id' => $boot['id'], 'win_player_3' => 1))->count(); @@ -1077,7 +1075,6 @@ class Pcapi extends Controller{ $table['bet_amount_msg']['banker_pair_amount'] = 0; $table['bet_amount_msg']['player_pair_amount'] = 0; $table['boot_num'] = $boot['boot_num']; - $table['boot_id'] = $boot['id']; $table['palyerCount'] = Db::connect('DB2')->name($numberTabTable)->where(array('table_id' => $table['id'], 'boot_id' => $boot['id'], 'result' => 2))->count(); $table['tieCount'] = Db::connect('DB2')->name($numberTabTable)->where(array('table_id' => $table['id'], 'boot_id' => $boot['id'], 'result' => 3))->count(); $table['bankerCount'] = Db::connect('DB2')->name($numberTabTable)->where(array('table_id' => $table['id'], 'boot_id' => $boot['id'], 'result' => 1))->count(); @@ -1243,8 +1240,8 @@ class Pcapi extends Controller{ $startTime = mktime(0,0,0,date('m'),date('d')-1,date('Y')); $endTime = mktime(0,0,0,date('m'),date('d'),date('Y'))-1; }elseif($time_interval == 3){ - $startTime = mktime(0,0,0,date("m"),date("d")-date("w")+1,date("Y")); - $endTime = mktime(23,59,59,date("m"),date("d")-date("w")+7,date("Y")); + $startTime = mktime(0,0,0,date("m"),date("d")-6,date("Y")); + $endTime = mktime(23,59,59,date("m"),date("d"),date("Y")); } $betWhere = array(); $betWhere['create_time'] = array('between',[$startTime,$endTime]); @@ -1574,8 +1571,8 @@ class Pcapi extends Controller{ $startTime = mktime(0,0,0,date('m'),date('d')-1,date('Y')); $endTime = mktime(0,0,0,date('m'),date('d'),date('Y'))-1; }elseif($time_interval == 3){ - $startTime = mktime(0,0,0,date("m"),date("d")-date("w")+1,date("Y")); - $endTime = mktime(23,59,59,date("m"),date("d")-date("w")+7,date("Y")); + $startTime = mktime(0,0,0,date("m"),date("d")-6,date("Y")); + $endTime = mktime(23,59,59,date("m"),date("d"),date("Y")); } $betWhere = array(); $betWhere['create_time'] = array('between',[$startTime,$endTime]); @@ -1642,8 +1639,8 @@ class Pcapi extends Controller{ $startTime = mktime(0,0,0,date('m'),date('d')-1,date('Y')); $endTime = mktime(0,0,0,date('m'),date('d'),date('Y'))-1; }elseif($time_interval == 3){ - $startTime = mktime(0,0,0,date("m"),date("d")-date("w")+1,date("Y")); - $endTime = mktime(23,59,59,date("m"),date("d")-date("w")+7,date("Y")); + $startTime = mktime(0,0,0,date("m"),date("d")-6,date("Y")); + $endTime = mktime(23,59,59,date("m"),date("d"),date("Y")); } $betWhere = array(); $betWhere['create_time'] = array('between',[$startTime,$endTime]); diff --git a/application/agent/controller/Agent.php b/application/agent/controller/Agent.php index 4de06d1..6178550 100755 --- a/application/agent/controller/Agent.php +++ b/application/agent/controller/Agent.php @@ -565,12 +565,24 @@ class Agent Extends Common{ if(!$user || $user['agent'] == 0){ die(json_encode(['code'=>0,'msg'=>$lang['error_id']])); } + // 顶级代理(agent_parent_id=0)无真实上级:构造一个不设限的虚拟上级,使所有"不得高于上级"封顶校验自动放行; + // "不得低于下级"封底校验与写入逻辑保持不变(顶级代理仍受其下级最高费率约束)。 if($parent_id <= 0){ - die(json_encode(['code'=>0,'msg'=>$lang['parent_error']])); - } - $agentParent = Db::name('user')->where('id',$parent_id)->find(); - if(!$agentParent || $agentParent['agent'] == 0){ - die(json_encode(['code'=>0,'msg'=>$lang['parent_error']])); + $agentParent = [ + 'limit_low' => 0, 'limit_high' => 99999999999, + 'limit_low_tie' => 0, 'limit_high_tie' => 99999999999, + 'limit_low_pair' => 0, 'limit_high_pair' => 99999999999, + 'limit_low_nn' => 0, 'limit_high_nn' => 0, + 'agent_ximalv' => 100, 'agent_ximalv_dt' => 100, + 'agent_ximalv_nn' => 100, 'agent_ximalv_tc' => 100, + 'agent_cs' => 100, 'rebate_rate' => 100, + 'agent_parent_id' => 0, + ]; + }else{ + $agentParent = Db::name('user')->where('id',$parent_id)->find(); + if(!$agentParent || $agentParent['agent'] == 0){ + die(json_encode(['code'=>0,'msg'=>$lang['parent_error']])); + } } if(!$nickname){ die(json_encode(['code'=>0,'msg'=>$lang['empty_nickname']])); @@ -682,6 +694,38 @@ class Agent Extends Common{ die(json_encode(['code'=>0,'msg'=>$lang['rebate_cannot_lower_agent'].' '.$childMaxRebateRate.'%'])); } + // —— 时序风险检测 —— + // 洗码率/返水率/占成率在「下注未结算」期间被修改,结算(openingBet)会按新值参与代理分账, + // 导致本局佣金与下注时预期不符。仅当上述费率确有变化、且该代理下级存在未结算注单时,要求二次确认。 + // 限红(limit_*)不参与结算、赔率(price_*)代理端只读,故不在检测范围。 + $confirm_pending = Request::instance()->post('confirm_pending'); + $rateChanged = ( + abs($agent_ximalv - (float)$user['agent_ximalv']) > 0.001 || + abs($agent_ximalv_dt - (float)$user['agent_ximalv_dt']) > 0.001 || + abs($agent_ximalv_nn - (float)$user['agent_ximalv_nn']) > 0.001 || + abs($agent_ximalv_tc - (float)$user['agent_ximalv_tc']) > 0.001 || + abs($agent_cs - (float)$user['agent_cs']) > 0.001 || + abs((float)$rebate_rate - (float)$user['rebate_rate']) > 0.001 + ); + if($rateChanged && !$confirm_pending){ + // bet 表位于 DB2 连接(与 Report 模块一致);下级注单路径匹配沿用全站约定的两段 LIKE。 + // create_time 限定近 1 小时,规避历史异常残留的 is_end=0 注单造成的误报。 + $pendingCount = Db::connect('DB2')->name('bet') + ->where('is_end', 0) + ->where('create_time', '>=', time() - 3600) + ->where(function($q) use ($user_id){ + $q->where('agent_parent_id_path', 'like', '%,'.$user_id.',%') + ->whereOr('agent_parent_id_path', 'like', $user_id.',%'); + }) + ->count(); + if($pendingCount > 0){ + die(json_encode([ + 'code' => 2, + 'pending' => $pendingCount, + 'msg' => '该代理下级当前有 '.$pendingCount.' 笔注单尚未结算。本次修改的洗码率 / 返水率 / 占成率将按新值参与这些注单的代理分账,可能使本局佣金与下注时预期不符。确定仍要立即保存吗?', + ])); + } + } // 拼装数据创建代理 $user_data = array(); diff --git a/application/agent/controller/Login.php b/application/agent/controller/Login.php index 765b7bb..c1a616f 100755 --- a/application/agent/controller/Login.php +++ b/application/agent/controller/Login.php @@ -260,13 +260,13 @@ class Login extends Controller { if($startDate){ $startTime = strtotime($startDate); }else{ - $startTime = strtotime(date('Y-m-d')); + $startTime = strtotime(date('Y-m-d') . ' 08:00:00'); $get['startDate'] = date('Y-m-d H:i:s',$startTime); } if($endDate){ $endTime = strtotime($endDate); }else{ - $endTime = time(); + $endTime = strtotime(date('Y-m-d', strtotime('+1 day')) . ' 07:59:59'); $get['endDate'] = date('Y-m-d H:i:s',$endTime); } $where = array(); diff --git a/application/agent/controller/Player.php b/application/agent/controller/Player.php index f076c97..d8cbe76 100755 --- a/application/agent/controller/Player.php +++ b/application/agent/controller/Player.php @@ -760,9 +760,7 @@ class Player Extends Common{ $user_data['agent_ximalv_nn'] = $agent_ximalv_nn; $user_data['agent_ximalv_tc'] = $agent_ximalv_tc; $user_data['manager_id'] = $manager_id; - if ($rebate_rate){ - $user_data['rebate_rate'] = $rebate_rate; - } + $user_data['rebate_rate'] = $rebate_rate ?: 0; $user_data['update_time'] = time(); $user_data['remarks'] = $remark; $result = Db::name('user')->where('id',$user_id)->update($user_data); diff --git a/application/agent/controller/Report.php b/application/agent/controller/Report.php index af89f64..ac1292e 100755 --- a/application/agent/controller/Report.php +++ b/application/agent/controller/Report.php @@ -36,17 +36,17 @@ class Report Extends Common{ $game_id = intval(Request::instance()->get('game_id')); $export = intval(Request::instance()->get('export')); - // 转换日期时间(默认:今天07:00:00 ~ 明天06:59:59) + // 转换日期时间(默认:今天08:00:00 ~ 明天07:59:59) if ($startDate) { $startTime = strtotime($startDate); } else { - $startTime = strtotime(date('Y-m-d') . ' 07:00:00'); + $startTime = strtotime(date('Y-m-d') . ' 08:00:00'); $get['startDate'] = date('Y-m-d H:i:s', $startTime); } if ($endDate) { $endTime = strtotime($endDate); } else { - $endTime = strtotime(date('Y-m-d', strtotime('+1 day')) . ' 06:59:59'); + $endTime = strtotime(date('Y-m-d', strtotime('+1 day')) . ' 07:59:59'); $get['endDate'] = date('Y-m-d H:i:s', $endTime); } @@ -309,14 +309,14 @@ class Report Extends Common{ if($startDate){ $startTime = strtotime($startDate); }else{ - $startTime = strtotime(date('Y-m-d')); + $startTime = strtotime(date('Y-m-d') . ' 08:00:00'); $get['startDate'] = date('Y-m-d H:i:s',$startTime); $this->assign('get',$get); } if($endDate){ $endTime = strtotime($endDate); }else{ - $endTime = time(); + $endTime = strtotime(date('Y-m-d', strtotime('+1 day')) . ' 07:59:59'); $get['endDate'] = date('Y-m-d H:i:s',$endTime); $this->assign('get',$get); } @@ -505,13 +505,13 @@ class Report Extends Common{ if($startDate){ $startTime = strtotime($startDate); }else{ - $startTime = strtotime(date('Y-m-d')); + $startTime = strtotime(date('Y-m-d') . ' 08:00:00'); $get['startDate'] = date('Y-m-d H:i:s',$startTime); } if($endDate){ $endTime = strtotime($endDate); }else{ - $endTime = time(); + $endTime = strtotime(date('Y-m-d', strtotime('+1 day')) . ' 07:59:59'); $get['endDate'] = date('Y-m-d H:i:s',$endTime); } @@ -1032,13 +1032,13 @@ class Report Extends Common{ if($startDate){ $startTime = strtotime($startDate); }else{ - $startTime = strtotime(date('Y-m-d')); + $startTime = strtotime(date('Y-m-d') . ' 08:00:00'); $get['startDate'] = date('Y-m-d H:i:s',$startTime); } if($endDate){ $endTime = strtotime($endDate); }else{ - $endTime = time(); + $endTime = strtotime(date('Y-m-d', strtotime('+1 day')) . ' 07:59:59'); $get['endDate'] = date('Y-m-d H:i:s',$endTime); } @@ -2054,14 +2054,14 @@ class Report Extends Common{ if($startDate){ $startTime = strtotime($startDate); }else{ - $startTime = strtotime(date('Y-m-d')); + $startTime = strtotime(date('Y-m-d') . ' 08:00:00'); $get['startDate'] = date('Y-m-d H:i:s',$startTime); $this->assign('get',$get); } if($endDate){ $endTime = strtotime($endDate); }else{ - $endTime = time(); + $endTime = strtotime(date('Y-m-d', strtotime('+1 day')) . ' 07:59:59'); $get['endDate'] = date('Y-m-d H:i:s',$endTime); $this->assign('get',$get); } @@ -2172,14 +2172,14 @@ class Report Extends Common{ if($startDate){ $startTime = strtotime($startDate); }else{ - $startTime = strtotime(date('Y-m-d')); + $startTime = strtotime(date('Y-m-d') . ' 08:00:00'); $get['startDate'] = date('Y-m-d H:i:s',$startTime); $this->assign('get',$get); } if($endDate){ $endTime = strtotime($endDate); }else{ - $endTime = time(); + $endTime = strtotime(date('Y-m-d', strtotime('+1 day')) . ' 07:59:59'); $get['endDate'] = date('Y-m-d H:i:s',$endTime); $this->assign('get',$get); } @@ -2269,14 +2269,14 @@ class Report Extends Common{ if($startDate){ $startTime = strtotime($startDate); }else{ - $startTime = strtotime(date('Y-m-d')); + $startTime = strtotime(date('Y-m-d') . ' 08:00:00'); $get['startDate'] = date('Y-m-d H:i:s',$startTime); $this->assign('get',$get); } if($endDate){ $endTime = strtotime($endDate); }else{ - $endTime = time(); + $endTime = strtotime(date('Y-m-d', strtotime('+1 day')) . ' 07:59:59'); $get['endDate'] = date('Y-m-d H:i:s',$endTime); $this->assign('get',$get); } @@ -2819,14 +2819,14 @@ class Report Extends Common{ if($startDate){ $startTime = strtotime($startDate); }else{ - $startTime = strtotime(date('Y-m-d')); + $startTime = strtotime(date('Y-m-d') . ' 08:00:00'); $get['startDate'] = date('Y-m-d H:i:s',$startTime); $this->assign('get',$get); } if($endDate){ $endTime = strtotime($endDate); }else{ - $endTime = time(); + $endTime = strtotime(date('Y-m-d', strtotime('+1 day')) . ' 07:59:59'); $get['endDate'] = date('Y-m-d H:i:s',$endTime); $this->assign('get',$get); } @@ -2869,13 +2869,13 @@ class Report Extends Common{ if ($startDate) { $startTime = strtotime($startDate); } else { - $startTime = strtotime(date('Y-m-d')); + $startTime = strtotime(date('Y-m-d') . ' 08:00:00'); $get['startDate'] = date('Y-m-d H:i:s', $startTime); } if ($endDate) { $endTime = strtotime($endDate); } else { - $endTime = time(); + $endTime = strtotime(date('Y-m-d', strtotime('+1 day')) . ' 07:59:59'); $get['endDate'] = date('Y-m-d H:i:s', $endTime); } @@ -3075,14 +3075,14 @@ class Report Extends Common{ if ($startDate) { $startTime = strtotime($startDate); } else { - $startTime = strtotime(date('Y-m-d')); + $startTime = strtotime(date('Y-m-d') . ' 08:00:00'); $get['startDate'] = date('Y-m-d H:i:s', $startTime); $this->assign('get', $get); } if ($endDate) { $endTime = strtotime($endDate); } else { - $endTime = time(); + $endTime = strtotime(date('Y-m-d', strtotime('+1 day')) . ' 07:59:59'); $get['endDate'] = date('Y-m-d H:i:s', $endTime); $this->assign('get', $get); } @@ -3168,14 +3168,14 @@ class Report Extends Common{ if ($startDate) { $startTime = strtotime($startDate); } else { - $startTime = strtotime(date('Y-m-d')); + $startTime = strtotime(date('Y-m-d') . ' 08:00:00'); $get['startDate'] = date('Y-m-d H:i:s', $startTime); $this->assign('get', $get); } if ($endDate) { $endTime = strtotime($endDate); } else { - $endTime = time(); + $endTime = strtotime(date('Y-m-d', strtotime('+1 day')) . ' 07:59:59'); $get['endDate'] = date('Y-m-d H:i:s', $endTime); $this->assign('get', $get); } @@ -3275,14 +3275,14 @@ class Report Extends Common{ if ($startDate) { $startTime = strtotime($startDate); } else { - $startTime = strtotime(date('Y-m-d')); + $startTime = strtotime(date('Y-m-d') . ' 08:00:00'); $get['startDate'] = date('Y-m-d H:i:s', $startTime); $this->assign('get', $get); } if ($endDate) { $endTime = strtotime($endDate); } else { - $endTime = time(); + $endTime = strtotime(date('Y-m-d', strtotime('+1 day')) . ' 07:59:59'); $get['endDate'] = date('Y-m-d H:i:s', $endTime); $this->assign('get', $get); } @@ -3366,14 +3366,14 @@ class Report Extends Common{ if ($startDate) { $startTime = strtotime($startDate); } else { - $startTime = strtotime(date('Y-m-d')); + $startTime = strtotime(date('Y-m-d') . ' 08:00:00'); $get['startDate'] = date('Y-m-d H:i:s', $startTime); $this->assign('get', $get); } if ($endDate) { $endTime = strtotime($endDate); } else { - $endTime = time(); + $endTime = strtotime(date('Y-m-d', strtotime('+1 day')) . ' 07:59:59'); $get['endDate'] = date('Y-m-d H:i:s', $endTime); $this->assign('get', $get); } @@ -3479,14 +3479,14 @@ class Report Extends Common{ if ($startDate) { $startTime = strtotime($startDate); } else { - $startTime = strtotime(date('Y-m-d')); + $startTime = strtotime(date('Y-m-d') . ' 08:00:00'); $get['startDate'] = date('Y-m-d H:i:s', $startTime); $this->assign('get', $get); } if ($endDate) { $endTime = strtotime($endDate); } else { - $endTime = time(); + $endTime = strtotime(date('Y-m-d', strtotime('+1 day')) . ' 07:59:59'); $get['endDate'] = date('Y-m-d H:i:s', $endTime); $this->assign('get', $get); } @@ -3574,14 +3574,14 @@ class Report Extends Common{ if ($startDate) { $startTime = strtotime($startDate); } else { - $startTime = strtotime(date('Y-m-d')); + $startTime = strtotime(date('Y-m-d') . ' 08:00:00'); $get['startDate'] = date('Y-m-d H:i:s', $startTime); $this->assign('get', $get); } if ($endDate) { $endTime = strtotime($endDate); } else { - $endTime = time(); + $endTime = strtotime(date('Y-m-d', strtotime('+1 day')) . ' 07:59:59'); $get['endDate'] = date('Y-m-d H:i:s', $endTime); $this->assign('get', $get); } @@ -3683,14 +3683,14 @@ class Report Extends Common{ if($startDate){ $startTime = strtotime($startDate); }else{ - $startTime = strtotime(date('Y-m-d')); + $startTime = strtotime(date('Y-m-d') . ' 08:00:00'); $get['startDate'] = date('Y-m-d H:i:s',$startTime); $this->assign('get',$get); } if($endDate){ $endTime = strtotime($endDate); }else{ - $endTime = time(); + $endTime = strtotime(date('Y-m-d', strtotime('+1 day')) . ' 07:59:59'); $get['endDate'] = date('Y-m-d H:i:s',$endTime); $this->assign('get',$get); } @@ -3895,14 +3895,14 @@ class Report Extends Common{ if($startDate){ $startTime = strtotime($startDate); }else{ - $startTime = strtotime(date('Y-m-d')); + $startTime = strtotime(date('Y-m-d') . ' 08:00:00'); $get['startDate'] = date('Y-m-d H:i:s',$startTime); $this->assign('get',$get); } if($endDate){ $endTime = strtotime($endDate); }else{ - $endTime = time(); + $endTime = strtotime(date('Y-m-d', strtotime('+1 day')) . ' 07:59:59'); $get['endDate'] = date('Y-m-d H:i:s',$endTime); $this->assign('get',$get); } @@ -3994,14 +3994,14 @@ class Report Extends Common{ if($startDate){ $startTime = strtotime($startDate); }else{ - $startTime = strtotime(date('Y-m-d')); + $startTime = strtotime(date('Y-m-d') . ' 08:00:00'); $get['startDate'] = date('Y-m-d H:i:s',$startTime); $this->assign('get',$get); } if($endDate){ $endTime = strtotime($endDate); }else{ - $endTime = time(); + $endTime = strtotime(date('Y-m-d', strtotime('+1 day')) . ' 07:59:59'); $get['endDate'] = date('Y-m-d H:i:s',$endTime); $this->assign('get',$get); } @@ -4100,14 +4100,14 @@ class Report Extends Common{ if($startDate){ $startTime = strtotime($startDate); }else{ - $startTime = strtotime(date('Y-m-d')); + $startTime = strtotime(date('Y-m-d') . ' 08:00:00'); $get['startDate'] = date('Y-m-d H:i:s',$startTime); $this->assign('get',$get); } if($endDate){ $endTime = strtotime($endDate); }else{ - $endTime = time(); + $endTime = strtotime(date('Y-m-d', strtotime('+1 day')) . ' 07:59:59'); $get['endDate'] = date('Y-m-d H:i:s',$endTime); $this->assign('get',$get); } diff --git a/application/agent/controller/Settle.php b/application/agent/controller/Settle.php index cacfca2..7c4b181 100644 --- a/application/agent/controller/Settle.php +++ b/application/agent/controller/Settle.php @@ -30,12 +30,12 @@ class Settle Extends Common{ if($timeLength == 1 || $timeLength == 2){ if($timeLength == 1){ //上周时间 - $weekStart = date("Y-m-d H:i:s",mktime(0, 0 , 0,date("m"),date("d")-date("w")+1-7,date("Y"))); - $weekEnd = date("Y-m-d H:i:s",mktime(23,59,59,date("m"),date("d")-date("w")+7-7,date("Y"))); + $weekStart = date("Y-m-d H:i:s",mktime(0, 0 , 0,date("m"),date("d")-(date("w")?:7)+1-7,date("Y"))); + $weekEnd = date("Y-m-d H:i:s",mktime(23,59,59,date("m"),date("d")-(date("w")?:7)+7-7,date("Y"))); }elseif($timeLength == 2){ //本周时间 - $weekStart = date("Y-m-d H:i:s",mktime(0, 0 , 0,date("m"),date("d")-date("w")+1,date("Y"))); - $weekEnd = date("Y-m-d H:i:s",mktime(23,59,59,date("m"),date("d")-date("w")+7,date("Y"))); + $weekStart = date("Y-m-d H:i:s",mktime(0, 0 , 0,date("m"),date("d")-(date("w")?:7)+1,date("Y"))); + $weekEnd = date("Y-m-d H:i:s",mktime(23,59,59,date("m"),date("d")-(date("w")?:7)+7,date("Y"))); } $startTime = strtotime($weekStart); $endTime = strtotime($weekEnd); @@ -474,12 +474,12 @@ class Settle Extends Common{ if($timeLength == 1 || $timeLength == 2){ if($timeLength == 1){ //上周时间 - $weekStart = date("Y-m-d H:i:s",mktime(0, 0 , 0,date("m"),date("d")-date("w")+1-7,date("Y"))); - $weekEnd = date("Y-m-d H:i:s",mktime(23,59,59,date("m"),date("d")-date("w")+7-7,date("Y"))); + $weekStart = date("Y-m-d H:i:s",mktime(0, 0 , 0,date("m"),date("d")-(date("w")?:7)+1-7,date("Y"))); + $weekEnd = date("Y-m-d H:i:s",mktime(23,59,59,date("m"),date("d")-(date("w")?:7)+7-7,date("Y"))); }elseif($timeLength == 2){ //本周时间 - $weekStart = date("Y-m-d H:i:s",mktime(0, 0 , 0,date("m"),date("d")-date("w")+1,date("Y"))); - $weekEnd = date("Y-m-d H:i:s",mktime(23,59,59,date("m"),date("d")-date("w")+7,date("Y"))); + $weekStart = date("Y-m-d H:i:s",mktime(0, 0 , 0,date("m"),date("d")-(date("w")?:7)+1,date("Y"))); + $weekEnd = date("Y-m-d H:i:s",mktime(23,59,59,date("m"),date("d")-(date("w")?:7)+7,date("Y"))); } $startTime = strtotime($weekStart); $endTime = strtotime($weekEnd); diff --git a/application/agent/lang/en-us.php b/application/agent/lang/en-us.php index da56127..bdcd99f 100755 --- a/application/agent/lang/en-us.php +++ b/application/agent/lang/en-us.php @@ -301,7 +301,7 @@ return [ 'betting_money' => 'Bet money', 'code_washing_amount' => 'Code washing amount', 'odd_code_fee' => 'Odd code fee', - 'code_amount' => 'Code amount', + 'code_amount' => 'Rebate', 'settled_code_amount' => 'Settled code amount', 'unsettled_code_amount' => 'Unsettled code amount', 'unsettled_rebate_amount' => 'Unsettled rebate amount', diff --git a/application/agent/lang/zh-cn.php b/application/agent/lang/zh-cn.php index 56d4511..3039190 100755 --- a/application/agent/lang/zh-cn.php +++ b/application/agent/lang/zh-cn.php @@ -301,7 +301,7 @@ return [ 'betting_money' => '下注金额', 'code_washing_amount' => '洗码量', 'odd_code_fee' => '注单码费', - 'code_amount' => '码量', + 'code_amount' => '码粮', 'settled_code_amount' => '已结码量', 'unsettled_code_amount' => '未结码量', 'unsettled_rebate_amount' => '未结返水', diff --git a/application/agent/lang/zh-tw.php b/application/agent/lang/zh-tw.php index 657041b..e7937f9 100755 --- a/application/agent/lang/zh-tw.php +++ b/application/agent/lang/zh-tw.php @@ -301,7 +301,7 @@ return [ 'betting_money' => '下注金額', 'code_washing_amount' => '洗碼量', 'odd_code_fee' => '注單碼費', - 'code_amount' => '碼量', + 'code_amount' => '碼糧', 'settled_code_amount' => '已結碼量', 'unsettled_code_amount' => '未結碼量', 'unsettled_rebate_amount' => '未結返水', diff --git a/application/agent/view/agent/edit.html b/application/agent/view/agent/edit.html index 07b279d..87f43b6 100755 --- a/application/agent/view/agent/edit.html +++ b/application/agent/view/agent/edit.html @@ -269,7 +269,12 @@ dataType: 'JSON', success: function (data) { if (data.code == 0) { - layer.msg(data.msg); + // 校验未通过:用必须点确认的弹窗代替一闪而过的 toast,确保操作员看清失败原因 + // (如返水率/码率/占股超过上级上限时,后端会返回具体上限值) + layer.alert(data.msg, { + title: lang.message, + icon: 0 + }); } else if (data.code == 1) { layer.alert(data.msg,{ title:lang.message, @@ -277,6 +282,36 @@ x_admin_close(); parent.location.reload(); }); + } else if (data.code == 2) { + // 时序风险:下级有未结算注单,二次确认后带 confirm_pending 重新提交 + layer.confirm(data.msg, { + title: lang.message, + btn: ['确定保存', '取消'] + }, function (idx) { + layer.close(idx); + query.confirm_pending = 1; + $.ajax({ + url: '/agent/do_edit', + data: query, + type: 'POST', + dataType: 'JSON', + success: function (d) { + if (d.code == 0) { + layer.alert(d.msg, { + title: lang.message, + icon: 0 + }); + } else if (d.code == 1) { + layer.alert(d.msg, { + title: lang.message + }, function () { + x_admin_close(); + parent.location.reload(); + }); + } + } + }); + }); } } }) diff --git a/application/agent/view/player/edit.html b/application/agent/view/player/edit.html index 64c06a6..ec33a61 100755 --- a/application/agent/view/player/edit.html +++ b/application/agent/view/player/edit.html @@ -644,13 +644,11 @@ //query.mobile = $('#mobile').val(); //query.bet_type = $('#bet_type').val(); query.win_limit = $('#win_limit').val(); - /* query.agent_commission = $('#agent_commission').val(); query.agent_commission_dt = $('#agent_commission_dt').val(); query.agent_commission_nn = $('#agent_commission_nn').val(); query.agent_commission_tc = $('#agent_commission_tc').val(); query.agent_commission_tc_banker = $('#agent_commission_tc_banker').val(); - */ query.limit_low = $('#limit_low').val(); query.limit_high = $('#limit_high').val(); query.limit_low_tie = $('#limit_low_tie').val(); diff --git a/application/agent/view/report/bet.html b/application/agent/view/report/bet.html index 5be4e0a..fa372a7 100644 --- a/application/agent/view/report/bet.html +++ b/application/agent/view/report/bet.html @@ -77,7 +77,10 @@
{$lang['refresh']} - + +
@@ -187,16 +190,44 @@ $(function(){ var online = $('#online').val(); var refreshUrl = $('#refreshUrl').val(); - var countDown = 10; - if(online == 1){ - $('.countDown').show(); - setInterval(function(){ + var INTERVAL = 10; // 自动刷新间隔(秒) + var countDown = INTERVAL; + var autoTimer = null; + + function startAuto(reloadFn){ + countDown = INTERVAL; + $('.countDown').show().html(countDown); + autoTimer = setInterval(function(){ countDown = countDown - 1; $('.countDown').html(countDown); - if(countDown == 0){ - location.href = refreshUrl; + if(countDown <= 0){ + reloadFn(); } - },1000); + }, 1000); + } + function stopAuto(){ + if(autoTimer){ clearInterval(autoTimer); autoTimer = null; } + $('.countDown').hide(); + } + + if(online == 1){ + // 从“在线管理”进入:保持原有自动刷新行为 + startAuto(function(){ location.href = refreshUrl; }); + }else{ + // 注单查询:可开关的今日实时自动刷新(默认开,刷新当前查询条件) + var saved = localStorage.getItem('bet_auto_refresh'); + var enabled = (saved === null) ? true : (saved === '1'); + $('#autoRefresh').prop('checked', enabled); + if(enabled){ startAuto(function(){ location.replace(location.href); }); } + $('#autoRefresh').on('change', function(){ + if($(this).is(':checked')){ + localStorage.setItem('bet_auto_refresh','1'); + startAuto(function(){ location.replace(location.href); }); + }else{ + localStorage.setItem('bet_auto_refresh','0'); + stopAuto(); + } + }); } }) diff --git a/application/config.php b/application/config.php index 6eb0e7b..441330a 100644 --- a/application/config.php +++ b/application/config.php @@ -286,7 +286,7 @@ return [ 'pay' => 'alinPay', 'default_agent' => 111, 'default_wt_agent' => 111, - 'limit_agent' => [111], + 'limit_agent' => [], ], ], @@ -359,5 +359,29 @@ return [ '11' => '越南代收' ] ], + 'epay' => [//彩虹易支付(USDT/支付宝/微信 聚合) + 'online_order_fac' => 'epay_online_order', + 'notify_url' => 'https://api.g7g7.top/order/epay_recharge_callback',// 异步回调 + 'callback_url' => 'https://api.g7g7.top/order/epay_return',// 同步跳转回业务 + 'api_url' => 'https://pay.g7g7.top', + 'pid' => '1000', + 'key' => 'bf7b83653f5c056a6103e26263a75fa1', + 'goods_name' => '账户充值', + 'type' => [ + 'usdt' => 'USDT支付', + // 'alipay' => '支付宝', + // 'wxpay' => '微信支付', + ] + ], + 'ccpay' => [//CCmerchant越南银行代收 + 'online_order_fac' => 'ccpay_online_order', + 'notify_url' => 'https://api.g7g7.top/order/ccpay_recharge_callback', + 'callback_url' => '', + 'api_url' => 'https://c.gmobvfxllc.com/gateway/api/trade', + 'mch_no' => 'M8822026041910000352', + 'pay_secret' => '820281b0d0b24a6bb701d8fc1c31a197', + 'timeout' => 600, + 'type' => ['pay' => 'CCpay越南银行'], + ], ] ]; diff --git a/application/deal/controller/Index.php b/application/deal/controller/Index.php index fc67e0a..9f3eba8 100644 --- a/application/deal/controller/Index.php +++ b/application/deal/controller/Index.php @@ -245,7 +245,7 @@ class Index Extends Common{ // 验证靴ID if($boot_id > 0){ - $ns = Db::name($numberTabTable)->where(array('game_id' => $game_id, 'boot_id' => $boot_id, 'bet_status' => 3))->field('result,pair')->order('start_time ASC,id ASC')->select(); + $ns = Db::name($numberTabTable)->where(array('game_id' => $game_id, 'boot_id' => $boot_id, 'bet_status' => 3))->field('result,pair,luck_six,dragon_seven,panda_eight')->order('start_time ASC,id ASC')->select(); if($forecast == 1){ // 庄问路 $ns[] = array('result'=>1,'pair'=>0); @@ -298,7 +298,7 @@ class Index Extends Common{ return json($result); }else{ $waybill = array(); - return json(['status'=>true,'msg'=>'数据不存在','waybill'=>$waybill]); + return json(['status'=>false,'msg'=>'数据不存在','waybill'=>$waybill]); } }else{ return json(['status'=>false,'msg'=>'靴ID错误']); diff --git a/application/helper.php b/application/helper.php index 96b2c8c..2a2c1f7 100644 --- a/application/helper.php +++ b/application/helper.php @@ -275,7 +275,7 @@ function waybill($ns){ $showRoadLocation = array(); foreach($showRoad as $k => $v){ foreach($v as $key => $val){ - $pushData = array('show_x' => $k + 1, 'show_y' =>$key + 1, 'result' => $val['result'], 'pair' => $val['pair']); + $pushData = array('show_x' => $k + 1, 'show_y' =>$key + 1, 'result' => $val['result'], 'pair' => $val['pair'], 'luck_six' => $val['luck_six'] ?? 0, 'dragon_seven' => $val['dragon_seven'] ?? 0, 'panda_eight' => $val['panda_eight'] ?? 0); array_push($showRoadLocation,$pushData); } } diff --git a/application/onlinechip/controller/Order.php b/application/onlinechip/controller/Order.php index 86b3bcf..8a83f58 100644 --- a/application/onlinechip/controller/Order.php +++ b/application/onlinechip/controller/Order.php @@ -14,6 +14,8 @@ class Order Extends Controller{ use traits\happyPay; use traits\hengfuPay; use traits\alinPay; + use traits\epayPay; + use traits\ccpayPay; public function __construct() { @@ -34,10 +36,23 @@ class Order Extends Controller{ } $pay_method = $area_list[$user['area_id']]['pay']; if($user && $user['api_token'] == $api_token){ - $this->assign('online_order_fac',$pay_list[$pay_method]['online_order_fac']); - $this->assign('payMethod',$pay_list[$pay_method]['type']); - $this->assign('client',1); - $this->assign('user_info',$user); + $payMethod = $pay_list[$pay_method]['type']; + $pay_routes = []; + foreach($payMethod as $k => $v){ + $pay_routes[$k] = $pay_list[$pay_method]['online_order_fac']; + } + // 越南地区追加 USDT (Epay) + if($user['area_id'] == 3 && !empty($pay_list['epay']['type'])){ + foreach($pay_list['epay']['type'] as $k => $v){ + $payMethod[$k] = $v; + $pay_routes[$k] = $pay_list['epay']['online_order_fac']; + } + } + $this->assign('online_order_fac', $pay_list[$pay_method]['online_order_fac']); + $this->assign('payMethod', $payMethod); + $this->assign('pay_routes', $pay_routes); + $this->assign('client', 1); + $this->assign('user_info', $user); return $this->fetch(); }else{ exit('页面错误,请退出再登录!'); @@ -55,10 +70,26 @@ class Order Extends Controller{ } $pay_method = $area_list[$user['area_id']]['pay']; if($user && $user['api_token'] == $api_token){ - $this->assign('online_order_fac',$pay_list[$pay_method]['online_order_fac']); - $this->assign('payMethod',$pay_list[$pay_method]['type']); - $this->assign('client',2); - $this->assign('user_info',$user); + // 主通道(按 area_list 的 pay 配置) + $payMethod = $pay_list[$pay_method]['type']; + $pay_routes = []; + foreach($payMethod as $k => $v){ + $pay_routes[$k] = $pay_list[$pay_method]['online_order_fac']; + } + + // 越南地区追加 USDT (Epay) 通道作为第二选项 + if($user['area_id'] == 3 && !empty($pay_list['epay']['type'])){ + foreach($pay_list['epay']['type'] as $k => $v){ + $payMethod[$k] = $v; + $pay_routes[$k] = $pay_list['epay']['online_order_fac']; + } + } + + $this->assign('online_order_fac', $pay_list[$pay_method]['online_order_fac']); // 兼容旧模板 + $this->assign('payMethod', $payMethod); + $this->assign('pay_routes', $pay_routes); + $this->assign('client', 2); + $this->assign('user_info', $user); return $this->fetch(); }else{ exit('页面错误,请退出再登录!'); @@ -83,8 +114,9 @@ class Order Extends Controller{ $zdlIdArr = explode(',',$user['agent_parent_id_path']); $area_list = config('area_list'); //判断是否金流支线,如果不是的话,不允许充值 - $isAllow = false; - foreach($area_list[$user['area_id']]['limit_agent'] as $allowAgentId){ + $limitAgents = $area_list[$user['area_id']]['limit_agent']; + $isAllow = empty($limitAgents); + foreach($limitAgents as $allowAgentId){ if(in_array($allowAgentId,$zdlIdArr)){ $isAllow = true; } @@ -153,9 +185,10 @@ class Order Extends Controller{ $user = Db::name('user')->where(array('id' => $user_id))->find(); $zdlIdArr = explode(',',$user['agent_parent_id_path']); $area_list = config('area_list'); - //判断是否金流支线,如果不是的话,不允许充值 - $isAllow = false; - foreach($area_list[$user['area_id']]['limit_agent'] as $allowAgentId){ + //判断是否金流支线,如果不是的话,不允许提现 + $limitAgents = $area_list[$user['area_id']]['limit_agent']; + $isAllow = empty($limitAgents); + foreach($limitAgents as $allowAgentId){ if(in_array($allowAgentId,$zdlIdArr)){ $isAllow = true; } diff --git a/application/onlinechip/controller/Pcapi.php b/application/onlinechip/controller/Pcapi.php index b3bc3b6..6c41cb8 100755 --- a/application/onlinechip/controller/Pcapi.php +++ b/application/onlinechip/controller/Pcapi.php @@ -17,17 +17,19 @@ use Waybill\WaybillRoulette; class Pcapi extends Controller{ use traits\alinPay; + use traits\epayPay; + use traits\ccpayPay; public function __construct(){ parent::__construct(); // CORS headers $origin = Request::instance()->header('origin'); - $allowed = ['https://ww1.g7g7.top','https://m.g7g7.top','https://m1.g7g7.top','https://m3.g7g7.top','https://p.g7g7.top']; - if($origin && in_array($origin, $allowed)){ + if($origin){ header('Access-Control-Allow-Origin: '.$origin); - header('Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization'); - header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE,OPTIONS'); - header('Access-Control-Allow-Credentials: true'); + } else { + header('Access-Control-Allow-Origin: *'); } + header('Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization'); + header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE,OPTIONS'); if(Request::instance()->isOptions()){ exit(); } @@ -48,9 +50,6 @@ class Pcapi extends Controller{ } public function get_version(){ - header('Access-Control-Allow-Origin: *'); - header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization"); - header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE'); return json(config('app_version')); } public function get_system_info(){ @@ -64,9 +63,6 @@ class Pcapi extends Controller{ } //试玩登录 public function demologin(){ - header('Access-Control-Allow-Origin: *'); - header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization"); - header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE'); if(Request::instance()->isPost()){ $json_arr = decrypt_data(Request::instance()->post()); if($json_arr){ @@ -119,9 +115,6 @@ class Pcapi extends Controller{ //保持在线--心跳 public function keepOnline(){ - header('Access-Control-Allow-Origin: *'); - header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization"); - header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE'); if(Request::instance()->isPost()){ $json_arr = decrypt_data(Request::instance()->post()); if($json_arr){ @@ -145,9 +138,6 @@ class Pcapi extends Controller{ } //登录optimum public function login(){ - header('Access-Control-Allow-Origin: *'); - header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization"); - header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE'); if(Request::instance()->isPost()){ $json_arr = decrypt_data(Request::instance()->post()); if($json_arr){ @@ -207,7 +197,7 @@ class Pcapi extends Controller{ $find['pay_channel'] = ''; $find['pay_channel_currency'] = []; $find['pay_channel_coin_chain'] = []; - if($topAgent['agent_type'] == 1){ + if($topAgent['pay_channel'] && $topAgent['pay_channel'] != 'OPR'){ // 现金线走支付渠道 $find['pay_channel'] = $topAgent['pay_channel']; $find['pay_channel_currency'] = []; @@ -221,7 +211,7 @@ class Pcapi extends Controller{ $find['pay_channel_coin_chain'] = json_decode($payChannelInfo['coin_chain'],true); } } - } elseif ($topAgent['agent_type'] == 2 && $topAgent['pay_channel'] == 'OPR') { // 人工转帐上分,前端显示充值信息 + } elseif ($topAgent['pay_channel'] == 'OPR') { // 人工转帐上分,前端显示充值信息(不依赖 agent_type,只看 pay_channel) $find['pay_channel'] = $topAgent['pay_channel']; $find['pay_channel_address'] = $topAgent['pay_channel_address']; } @@ -253,9 +243,6 @@ class Pcapi extends Controller{ } // 获取用户信息 public function get_user_info(){ - header('Access-Control-Allow-Origin: *'); - header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization"); - header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE'); if(Request::instance()->isPost()){ $json_arr = decrypt_data(Request::instance()->post()); if($json_arr){ @@ -283,7 +270,7 @@ class Pcapi extends Controller{ $find['pay_channel'] = ''; $find['pay_channel_currency'] = []; $find['pay_channel_coin_chain'] = []; - if($topAgent['agent_type'] == 1){ + if($topAgent['pay_channel'] && $topAgent['pay_channel'] != 'OPR'){ // 现金线走支付渠道 $find['pay_channel'] = $topAgent['pay_channel']; $find['pay_channel_currency'] = []; @@ -297,6 +284,9 @@ class Pcapi extends Controller{ $find['pay_channel_coin_chain'] = json_decode($payChannelInfo['coin_chain'],true); } } + } elseif($topAgent['pay_channel'] == 'OPR'){ // 人工转帐上分:与 login 保持一致下发收款信息(此前 get_user_info 缺失,刷新会丢) + $find['pay_channel'] = 'OPR'; + $find['pay_channel_address'] = $topAgent['pay_channel_address']; } $find['manager'] = []; if($find['bet_type'] == 2){ @@ -322,9 +312,6 @@ class Pcapi extends Controller{ } //用户钱 public function user_money(){ - header('Access-Control-Allow-Origin: *'); - header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization"); - header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE'); if(Request::instance()->isPost()){ $json_arr = decrypt_data(Request::instance()->post()); if($json_arr){ @@ -348,9 +335,6 @@ class Pcapi extends Controller{ } //修改密码 public function update_password(){ - header('Access-Control-Allow-Origin: *'); - header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization"); - header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE'); if(Request::instance()->isPost()){ $json_arr = decrypt_data(Request::instance()->post()); if($json_arr){ @@ -388,9 +372,6 @@ class Pcapi extends Controller{ } //打赏 public function to_tip(){ - header('Access-Control-Allow-Origin: *'); - header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization"); - header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE'); if(Request::instance()->isPost()){ $json_arr = decrypt_data(Request::instance()->post()); if($json_arr){ @@ -434,9 +415,6 @@ class Pcapi extends Controller{ } //好路 public function good_road(){ - header('Access-Control-Allow-Origin: *'); - header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization"); - header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE'); if(Request::instance()->isPost()){ $json_arr = decrypt_data(Request::instance()->post()); if($json_arr){ @@ -472,9 +450,6 @@ class Pcapi extends Controller{ } //返回全部桌子 public function all_table(){ - header('Access-Control-Allow-Origin: *'); - header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization"); - header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE'); if(Request::instance()->isPost()){ $json_arr = decrypt_data(Request::instance()->post()); if($json_arr){ @@ -1217,9 +1192,6 @@ class Pcapi extends Controller{ } //返回单张桌子 public function singletable(){ - header('Access-Control-Allow-Origin: *'); - header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization"); - header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE'); if(Request::instance()->isPost()){ $json_arr = decrypt_data(Request::instance()->post()); // $json_arr = Request::instance()->post(); @@ -1257,7 +1229,6 @@ class Pcapi extends Controller{ //桌子信息 $table['boot_num'] = $boot['boot_num']; - $table['boot_id'] = $boot['id']; $table['player_1_count'] = Db::name($numberTabTable)->where(array('table_id' => $table['id'], 'boot_id' => $boot['id'], 'win_player_1' => 1))->count(); $table['player_2_count'] = Db::name($numberTabTable)->where(array('table_id' => $table['id'], 'boot_id' => $boot['id'], 'win_player_2' => 1))->count(); $table['player_3_count'] = Db::name($numberTabTable)->where(array('table_id' => $table['id'], 'boot_id' => $boot['id'], 'win_player_3' => 1))->count(); @@ -1400,7 +1371,6 @@ class Pcapi extends Controller{ $boot = Db::name($bootTabTable)->where('table_id',$table['id'])->order('id DESC')->find(); if($boot){ $table['boot_num'] = $boot['boot_num']; - $table['boot_id'] = $boot['id']; $table['player_1_count'] = Db::name($numberTabTable)->where(array('boot_id' => $boot['id'], 'win_player_1' => 1))->count(); $table['player_2_count'] = Db::name($numberTabTable)->where(array('boot_id' => $boot['id'], 'win_player_2' => 1))->count(); $table['player_3_count'] = Db::name($numberTabTable)->where(array('boot_id' => $boot['id'], 'win_player_3' => 1))->count(); @@ -1644,7 +1614,6 @@ class Pcapi extends Controller{ $table['bet_amount_msg']['banker_pair_amount'] = 0; $table['bet_amount_msg']['player_pair_amount'] = 0; $table['boot_num'] = $boot['boot_num']; - $table['boot_id'] = $boot['id']; $table['playerCount'] = Db::name($numberTabTable)->where(array('table_id' => $table['id'], 'boot_id' => $boot['id'], 'result' => 2))->count(); $table['tieCount'] = Db::name($numberTabTable)->where(array('table_id' => $table['id'], 'boot_id' => $boot['id'], 'result' => 3))->count(); $table['bankerCount'] = Db::name($numberTabTable)->where(array('table_id' => $table['id'], 'boot_id' => $boot['id'], 'result' => 1))->count(); @@ -1771,9 +1740,6 @@ class Pcapi extends Controller{ } //今日最佳 public function optimum(){ - header('Access-Control-Allow-Origin: *'); - header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization"); - header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE'); if(Request::instance()->isPost()){ $json_arr = decrypt_data(Request::instance()->post()); if($json_arr){ @@ -1799,9 +1765,6 @@ class Pcapi extends Controller{ } //游戏记录 public function get_user_bets(){ - header('Access-Control-Allow-Origin: *'); - header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization"); - header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE'); if(Request::instance()->isPost()){ $json_arr = decrypt_data(Request::instance()->post()); if($json_arr){ @@ -1830,8 +1793,8 @@ class Pcapi extends Controller{ $startTime = mktime(0,0,0,date('m'),date('d')-1,date('Y')); $endTime = mktime(0,0,0,date('m'),date('d'),date('Y'))-1; }elseif($time_interval == 3){ - $startTime = mktime(0,0,0,date("m"),date("d")-date("w")+1,date("Y")); - $endTime = mktime(23,59,59,date("m"),date("d")-date("w")+7,date("Y")); + $startTime = mktime(0,0,0,date("m"),date("d")-6,date("Y")); + $endTime = mktime(23,59,59,date("m"),date("d"),date("Y")); } $betWhere = array(); $betWhere['create_time'] = array('between',[$startTime,$endTime]); @@ -2319,9 +2282,6 @@ class Pcapi extends Controller{ } //上下分记录 public function recharge_record(){ - header('Access-Control-Allow-Origin: *'); - header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization"); - header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE'); if(Request::instance()->isPost()){ $json_arr = decrypt_data(Request::instance()->post()); if($json_arr){ @@ -2341,8 +2301,8 @@ class Pcapi extends Controller{ $startTime = mktime(0,0,0,date('m'),date('d')-1,date('Y')); $endTime = mktime(0,0,0,date('m'),date('d'),date('Y'))-1; }elseif($time_interval == 3){ - $startTime = mktime(0,0,0,date("m"),date("d")-date("w")+1,date("Y")); - $endTime = mktime(23,59,59,date("m"),date("d")-date("w")+7,date("Y")); + $startTime = mktime(0,0,0,date("m"),date("d")-6,date("Y")); + $endTime = mktime(23,59,59,date("m"),date("d"),date("Y")); } $betWhere = array(); $betWhere['create_time'] = array('between',[$startTime,$endTime]); @@ -2388,9 +2348,6 @@ class Pcapi extends Controller{ } //上下分记录 public function tip_record(){ - header('Access-Control-Allow-Origin: *'); - header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization"); - header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE'); if(Request::instance()->isPost()){ $json_arr = decrypt_data(Request::instance()->post()); if($json_arr){ @@ -2409,8 +2366,8 @@ class Pcapi extends Controller{ $startTime = mktime(0,0,0,date('m'),date('d')-1,date('Y')); $endTime = mktime(0,0,0,date('m'),date('d'),date('Y'))-1; }elseif($time_interval == 3){ - $startTime = mktime(0,0,0,date("m"),date("d")-date("w")+1,date("Y")); - $endTime = mktime(23,59,59,date("m"),date("d")-date("w")+7,date("Y")); + $startTime = mktime(0,0,0,date("m"),date("d")-6,date("Y")); + $endTime = mktime(23,59,59,date("m"),date("d"),date("Y")); } $betWhere = array(); $betWhere['create_time'] = array('between',[$startTime,$endTime]); @@ -2450,9 +2407,6 @@ class Pcapi extends Controller{ } //开结果后获取会员的下注信息及计算其输赢数目 public function user_bet_baccarat(){ - header('Access-Control-Allow-Origin: *'); - header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization"); - header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE'); if(Request::instance()->isPost()){ $json_arr = decrypt_data(Request::instance()->post()); if($json_arr){ @@ -2609,9 +2563,6 @@ class Pcapi extends Controller{ } //开结果后获取会员的下注信息及计算其输赢数目 public function user_bet_dt(){ - header('Access-Control-Allow-Origin: *'); - header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization"); - header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE'); if(Request::instance()->isPost()){ $json_arr = decrypt_data(Request::instance()->post()); if($json_arr){ @@ -2700,9 +2651,6 @@ class Pcapi extends Controller{ //开结果后获取会员的下注信息及计算其输赢数目 public function user_bet_nn(){ - header('Access-Control-Allow-Origin: *'); - header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization"); - header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE'); if(Request::instance()->isPost()){ $json_arr = decrypt_data(Request::instance()->post()); if($json_arr){ @@ -2735,9 +2683,6 @@ class Pcapi extends Controller{ } //开结果后获取会员的下注信息及计算其输赢数目 public function user_bet_tc(){ - header('Access-Control-Allow-Origin: *'); - header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization"); - header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE'); if(Request::instance()->isPost()){ $json_arr = decrypt_data(Request::instance()->post()); if($json_arr){ @@ -2770,9 +2715,6 @@ class Pcapi extends Controller{ } //开结果后获取会员的下注信息及计算其输赢数目 public function user_bet_toning(){ - header('Access-Control-Allow-Origin: *'); - header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization"); - header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE'); if(Request::instance()->isPost()){ $json_arr = decrypt_data(Request::instance()->post()); if($json_arr){ @@ -2804,9 +2746,6 @@ class Pcapi extends Controller{ } //开结果后获取会员的下注信息及计算其输赢数目 public function user_bet_dice(){ - header('Access-Control-Allow-Origin: *'); - header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization"); - header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE'); if(Request::instance()->isPost()){ $json_arr = decrypt_data(Request::instance()->post()); if($json_arr){ @@ -2837,9 +2776,6 @@ class Pcapi extends Controller{ } } public function user_bet_roulette(){ - header('Access-Control-Allow-Origin: *'); - header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization"); - header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE'); if(Request::instance()->isPost()){ $json_arr = decrypt_data(Request::instance()->post()); if($json_arr){ @@ -2871,9 +2807,6 @@ class Pcapi extends Controller{ } //快速提现 public function show_withdrawal(){ - header('Access-Control-Allow-Origin: *'); - header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization"); - header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE'); if(Request::instance()->isPost()){ $json_arr = decrypt_data(Request::instance()->post()); if($json_arr){ @@ -2901,9 +2834,6 @@ class Pcapi extends Controller{ } //确认提现 public function withdrawal(){ - header('Access-Control-Allow-Origin: *'); - header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization"); - header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE'); if(Request::instance()->isPost()){ $json_arr = decrypt_data(Request::instance()->post()); if($json_arr){ @@ -2984,9 +2914,6 @@ class Pcapi extends Controller{ } //充值信息 public function show_recharge(){ - header('Access-Control-Allow-Origin: *'); - header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization"); - header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE'); if(Request::instance()->isPost()){ $json_arr = decrypt_data(Request::instance()->post()); if($json_arr){ @@ -3023,9 +2950,6 @@ class Pcapi extends Controller{ } //确认充值 public function recharge(){ - header('Access-Control-Allow-Origin: *'); - header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization"); - header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE'); if(Request::instance()->isPost()){ $json_arr = decrypt_data(Request::instance()->post()); if($json_arr){ @@ -3082,9 +3006,6 @@ class Pcapi extends Controller{ } //游戏记录 public function get_rob_bet(){ - header('Access-Control-Allow-Origin: *'); - header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization"); - header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE'); if(Request::instance()->isPost()){ $json_arr = decrypt_data(Request::instance()->post()); if($json_arr){ @@ -3300,9 +3221,6 @@ class Pcapi extends Controller{ //电话呼入 public function online_call(){ - header('Access-Control-Allow-Origin: *'); - header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization"); - header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE'); $phone = Request::instance()->post('phone'); if($phone){ $table_info = Db::name('table')->where('phone',$phone)->find(); @@ -3332,9 +3250,6 @@ class Pcapi extends Controller{ * DateTime: 2019/12/12 12:53 */ public function doRegister(){ - header('Access-Control-Allow-Origin: *'); - header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization"); - header('Access-Control-Allow-Methods: POST'); if($data = Request::instance()->post()){ $data = decrypt_data($data); $username = isset($data['username'])?$data['username']:''; @@ -3688,9 +3603,6 @@ class Pcapi extends Controller{ //登录 public function lineLogin(){ - header('Access-Control-Allow-Origin: *'); - header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization"); - header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE'); if(Request::instance()->isPost()){ $json_arr = decrypt_data(Request::instance()->post()); if($json_arr){ @@ -3763,9 +3675,6 @@ class Pcapi extends Controller{ } public function app_entrance(){ - header('Access-Control-Allow-Origin: *'); - header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization"); - header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE'); if(Request::instance()->isPost()){ $entrance = array(); $entrance['HallUrl'] = HallUrl; @@ -3781,9 +3690,6 @@ class Pcapi extends Controller{ } //api用户通过接口获取铺信息 public function api_get_info(){ - header('Access-Control-Allow-Origin: *'); - header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization"); - header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE'); if(Request::instance()->isPost()){ $appId = intval(Request::instance()->post("appId")); $nonceStr = trim(Request::instance()->post("nonceStr")); @@ -3832,9 +3738,6 @@ class Pcapi extends Controller{ // 用户充值记录 public function user_recharge() { - header('Access-Control-Allow-Origin: *'); - header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization"); - header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE'); if(Request::instance()->isPost()) { $json_arr = decrypt_data(Request::instance()->post()); if ($json_arr) { @@ -3870,9 +3773,6 @@ class Pcapi extends Controller{ // 用户提现记录 public function user_withdraw() { - header('Access-Control-Allow-Origin: *'); - header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization"); - header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE'); if(Request::instance()->isPost()) { $json_arr = decrypt_data(Request::instance()->post()); if ($json_arr) { @@ -3908,9 +3808,6 @@ class Pcapi extends Controller{ //申请提现 public function apply_withdraw(){ - header('Access-Control-Allow-Origin: *'); - header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization"); - header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE'); if(Request::instance()->isPost()){ $json_arr = decrypt_data(Request::instance()->post()); if($json_arr){ @@ -3933,7 +3830,7 @@ class Pcapi extends Controller{ $system = Db::name('system')->find(); $money = $user['money']; $withdrawMoney = empty($system['withdraw_money']) ? 100 : $system['withdraw_money']; - $withdrawFee = empty($system['withdraw_fee']) ? 1 : $system['withdraw_fee']; + $withdrawFee = empty($system['withdraw_fee']) ? 0 : $system['withdraw_fee']; // 计算积分兑换 $amountMoney = $withdrawMoney/100*($amount); @@ -3984,9 +3881,6 @@ class Pcapi extends Controller{ // 申请银行卡提现(越南AlinPay) public function apply_withdraw_bank(){ - header('Access-Control-Allow-Origin: *'); - header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization"); - header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE'); if(Request::instance()->isPost()){ $json_arr = decrypt_data(Request::instance()->post()); if($json_arr){ @@ -4018,7 +3912,7 @@ class Pcapi extends Controller{ $system = Db::name('system')->find(); $money = $user['money']; $withdrawMoney = empty($system['withdraw_money']) ? 100 : $system['withdraw_money']; - $withdrawFee = empty($system['withdraw_fee']) ? 1 : $system['withdraw_fee']; + $withdrawFee = empty($system['withdraw_fee']) ? 0 : $system['withdraw_fee']; // 计算积分兑换 $amountMoney = $withdrawMoney/100*($amount); @@ -4080,9 +3974,6 @@ class Pcapi extends Controller{ // 获取越南银行列表 public function get_bank_list_vn(){ - header('Access-Control-Allow-Origin: *'); - header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization"); - header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE'); $banks = \pay\AlinPay::getBankCodes(); $list = []; @@ -4100,9 +3991,6 @@ class Pcapi extends Controller{ // 取消提现 public function cancel_withdraw(){ - header('Access-Control-Allow-Origin: *'); - header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization"); - header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE'); if(Request::instance()->isPost()){ $json_arr = decrypt_data(Request::instance()->post()); if($json_arr) { @@ -4158,9 +4046,6 @@ class Pcapi extends Controller{ */ public function deposit() { - header('Access-Control-Allow-Origin: *'); - header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization"); - header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE'); if(Request::instance()->isPost()){ $json_arr = decrypt_data(Request::instance()->post()); if($json_arr) { @@ -4222,9 +4107,6 @@ class Pcapi extends Controller{ */ public function get_free_seat(){ - header('Access-Control-Allow-Origin: *'); - header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization"); - header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE'); if(Request::instance()->isPost()){ $json_arr = decrypt_data(Request::instance()->post()); if($json_arr) { @@ -4266,11 +4148,6 @@ class Pcapi extends Controller{ * 无需鉴权,游客可访问 */ public function get_lobby_data(){ - header('Access-Control-Allow-Origin: *'); - header("Access-Control-Allow-Headers: token, Origin, X-Requested-With, Content-Type, Accept, Authorization"); - header('Access-Control-Allow-Methods: POST,GET,PUT,DELETE,OPTIONS'); - header('Access-Control-Max-Age: 86400'); - // 处理 OPTIONS 预检请求 if(Request::instance()->isOptions()){ return response('', 200); diff --git a/application/onlinechip/controller/traits/alinPay.php b/application/onlinechip/controller/traits/alinPay.php index c41c3e9..0c92fb3 100644 --- a/application/onlinechip/controller/traits/alinPay.php +++ b/application/onlinechip/controller/traits/alinPay.php @@ -50,8 +50,9 @@ trait alinPay return json(['status' => 0, 'message' => '所在地区暂不支持充值']); } - $isAllow = false; - foreach ($area_list[$user['area_id']]['limit_agent'] as $allowAgentId) { + $limitAgents = $area_list[$user['area_id']]['limit_agent']; + $isAllow = empty($limitAgents); + foreach ($limitAgents as $allowAgentId) { if (in_array($allowAgentId, $zdlIdArr)) { $isAllow = true; } diff --git a/application/onlinechip/controller/traits/ccpayPay.php b/application/onlinechip/controller/traits/ccpayPay.php new file mode 100644 index 0000000..3a56d52 --- /dev/null +++ b/application/onlinechip/controller/traits/ccpayPay.php @@ -0,0 +1,412 @@ +post(); + if (isset($post['encryptData'])) { + $post = decrypt_data($post); + if (!$post) { + $data = encrypt_data(['status' => 0, 'message' => 'Dữ liệu không hợp lệ']); + return json(['Success' => 1, 'Data' => $data]); + } + } + + $user_id = intval($post['user_id'] ?? 0); + $money = intval($post['price'] ?? 0); + $client = intval($post['client'] ?? 0); + $username = trim($post['username'] ?? ''); + + $user = Db::name('user')->where([ + 'id' => $user_id, + 'status' => 1, + 'is_delete' => 0, + 'agent' => 0, + ])->find(); + + if (!$user || $user_id <= 0 || $money <= 0 || $client <= 0) { + $data = encrypt_data(['status' => 0, 'message' => 'Tham số không hợp lệ, vui lòng thử lại']); + return json(['Success' => 1, 'Data' => $data]); + } + + $zdlIdArr = explode(',', $user['agent_parent_id_path']); + $area_list = config('area_list'); + + if (!isset($area_list[$user['area_id']])) { + $data = encrypt_data(['status' => 0, 'message' => 'Khu vực hiện chưa hỗ trợ nạp tiền']); + return json(['Success' => 1, 'Data' => $data]); + } + + $limitAgents = $area_list[$user['area_id']]['limit_agent']; + $isAllow = empty($limitAgents); + foreach ($limitAgents as $allowAgentId) { + if (in_array($allowAgentId, $zdlIdArr)) { + $isAllow = true; + } + } + if (!$isAllow) { + $data = encrypt_data(['status' => 0, 'message' => 'Tài khoản này chưa được phép nạp online']); + return json(['Success' => 1, 'Data' => $data]); + } + + $zdlId = $zdlIdArr[0]; + $zdl = Db::name('user')->where([ + 'id' => $zdlId, + 'status' => 1, + 'is_delete' => 0, + 'agent' => 1, + ])->find(); + + if (!$zdl) { + $data = encrypt_data(['status' => 0, 'message' => 'Tài khoản đại lý có vấn đề, không thể nạp']); + return json(['Success' => 1, 'Data' => $data]); + } + if ($zdl['money'] < $money) { + $maxAllowed = intval($zdl['money']); + $data = encrypt_data([ + 'status' => 0, + 'code' => 'AGENT_LIMIT', + 'message' => 'Hạn mức nạp mỗi lần hiện tại là ' . number_format($maxAllowed, 0, '.', ',') . ' VND. Vui lòng nhập số tiền nhỏ hơn hoặc bằng mức trên.', + 'max_amount' => $maxAllowed, + ]); + return json(['Success' => 1, 'Data' => $data]); + } + + $pay_list = config('pay_list'); + $pay_orderid = 'C' . date('YmdHis') . rand(100000, 999999); + $notify_url = $pay_list['ccpay']['notify_url'] ?? ''; + $timeout = intval($pay_list['ccpay']['timeout'] ?? 600); + + try { + $ccpay = new \pay\Ccpay(); + $result = $ccpay->createOrder( + $pay_orderid, + sprintf('%.0f', $money), + $notify_url, + 'uid_' . $user_id + ); + + if (!is_array($result)) { + addLogToFile('ccpay 下单: API 无响应', 'ccpay_error', 'ccpay'); + $data = encrypt_data(['status' => 0, 'message' => 'Kênh thanh toán không phản hồi, vui lòng thử lại']); + return json(['Success' => 1, 'Data' => $data]); + } + + $status = intval($result['status'] ?? -1); + $resultCode = intval($result['resultCode'] ?? -1); + + if ($status !== 0 || $resultCode !== 0) { + $errMsg = $result['errMsg'] ?? 'Lỗi không xác định'; + addLogToFile('ccpay 下单失败: order=' . $pay_orderid . ' err=' . $errMsg . ' raw=' . json_encode($result, JSON_UNESCAPED_UNICODE), 'ccpay_error', 'ccpay'); + $data = encrypt_data(['status' => 0, 'message' => 'Khởi tạo thanh toán thất bại: ' . $errMsg]); + return json(['Success' => 1, 'Data' => $data]); + } + + $order_id = Db::name('order_record')->insertGetId([ + 'pay_channel_id' => 9, + 'pay_channel_name' => 'ccpay', + 'user_id' => $user_id, + 'order_sn' => $pay_orderid, + 'appid' => $ccpay->getConfigInfo()['mch_no'] ?? '', + 'api_key' => '', + 'money' => $money, + 'sign' => '', + 'create_time' => time(), + 'back_order_sn' => $result['cpOrderNo'] ?? '', + 'client' => $client, + ]); + + Db::name('order_log')->insert([ + 'pay_channel_id' => 9, + 'pay_channel_name' => 'ccpay', + 'money' => $money, + 'create_time' => time(), + 'remake' => 'user_id:' . $user_id . ',用户名:' . $username . ',CCpay发起充值:' . $money . ',时间:' . date('Y-m-d H:i:s'), + 'order_id' => $order_id, + 'client' => $client, + ]); + + $codeUrl = $result['codeUrl'] ?? ''; + $qrcode = null; + + $msgJson = $result['message'] ?? ''; + if ($msgJson) { + $bankInfo = json_decode($msgJson, true); + if (is_array($bankInfo) && !empty($bankInfo['AccNo'])) { + $expiresAt = time() + $timeout; + $qrcode = [ + 'order_sn' => $pay_orderid, + 'bank_account' => $bankInfo['AccNo'] ?? '', + 'bank_name' => $bankInfo['AccName'] ?? '', + 'bank_branch' => $bankInfo['Branch'] ?? '', + 'bank_short' => $bankInfo['BankShortName'] ?? '', + 'qr_data' => $bankInfo['qrcode'] ?? '', + 'remark' => $bankInfo['remark'] ?? '', + 'amount' => $money, + 'expires_at' => $expiresAt, + 'timeout_sec' => $timeout, + ]; + } + } + + addLogToFile('ccpay 下单成功: order=' . $pay_orderid . ' cp=' . ($result['cpOrderNo'] ?? ''), 'ccpay_request', 'ccpay'); + + $data = encrypt_data([ + 'status' => 1, + 'message' => 'Khởi tạo thanh toán thành công', + 'url' => $codeUrl, + 'qrcode' => $qrcode, + ]); + return json(['Success' => 1, 'Data' => $data]); + } catch (\Exception $e) { + addLogToFile('ccpay 下单异常: ' . $e->getMessage() . ' | file:' . $e->getFile() . ':' . $e->getLine(), 'ccpay_error', 'ccpay'); + $data = encrypt_data(['status' => 0, 'message' => 'Khởi tạo thanh toán thất bại: ' . $e->getMessage()]); + return json(['Success' => 1, 'Data' => $data]); + } + } + + public function ccpay_order_status() + { + $post = Request::instance()->post(); + if (isset($post['encryptData'])) { + $post = decrypt_data($post); + if (!$post) { + return json(['status' => 0, 'message' => '数据解密失败']); + } + } + + $order_sn = trim($post['order_sn'] ?? ''); + $user_id = intval($post['user_id'] ?? 0); + + if ($order_sn === '' || $user_id <= 0) { + $data = encrypt_data(['status' => 0, 'message' => '参数错误']); + return json(['Success' => 1, 'Data' => $data]); + } + + $order = Db::name('order_record') + ->where([ + 'order_sn' => $order_sn, + 'user_id' => $user_id, + 'pay_channel_id' => 9, + ]) + ->find(); + + if (!$order) { + $data = encrypt_data(['status' => 0, 'message' => '订单不存在']); + return json(['Success' => 1, 'Data' => $data]); + } + + if (intval($order['status']) == 3) { + $data = encrypt_data([ + 'status' => 1, + 'message' => 'Nạp tiền thành công', + 'money' => $order['money'], + 'paid_time' => $order['back_time'], + ]); + return json(['Success' => 1, 'Data' => $data]); + } + + $pay_list = config('pay_list'); + $timeout = intval($pay_list['ccpay']['timeout'] ?? 600); + if (time() - intval($order['create_time']) > $timeout) { + $data = encrypt_data([ + 'status' => 2, + 'message' => 'Đơn hàng đã hết hạn', + 'money' => $order['money'], + ]); + return json(['Success' => 1, 'Data' => $data]); + } + + $data = encrypt_data([ + 'status' => 0, + 'message' => 'Đang chờ thanh toán', + 'money' => $order['money'], + ]); + return json(['Success' => 1, 'Data' => $data]); + } + + public function ccpay_recharge_callback() + { + $raw = file_get_contents('php://input'); + $post = json_decode($raw, true); + if (!$post) { + $post = Request::instance()->post(); + } + + $json = json_encode($post, JSON_UNESCAPED_UNICODE); + addLogToFile('ccpay 回调原始数据: ' . $json, 'ccpay_callback', 'ccpay'); + + if (!is_array($post) || empty($post['mchOrderNo']) || empty($post['sign'])) { + Log::record($post, 'ccpay_error_callback'); + exit('fail'); + } + + $logId = Db::name('pay_callback_log')->insertGetId([ + 'pay_channel' => 'CCPAY_RECHARGE', + 'type' => 'recharge', + 'json' => $json, + 'create_time' => date('Y-m-d H:i:s'), + ]); + + try { + $ccpay = new \pay\Ccpay(); + + $verifyData = []; + $verifyData['status'] = strval($post['status'] ?? ''); + $verifyData['mchNo'] = $post['mchNo'] ?? ''; + $verifyData['resultCode'] = strval($post['resultCode'] ?? ''); + $verifyData['cpOrderNo'] = $post['cpOrderNo'] ?? ''; + $verifyData['mchOrderNo'] = $post['mchOrderNo'] ?? ''; + $verifyData['amount'] = strval($post['amount'] ?? ''); + $verifyData['payResult'] = $post['payResult'] ?? ''; + $verifyData['traceTime'] = $post['traceTime'] ?? ''; + $verifyData['message'] = $post['message'] ?? ''; + + $signData = array_filter($verifyData, function ($v) { + return $v !== '' && $v !== null; + }); + $signData['sign'] = $post['sign']; + + if (!$ccpay->verifySign($signData)) { + addLogToFile('ccpay 回调验签失败: ' . $json, 'ccpay_callback_error', 'ccpay'); + exit('fail'); + } + + if ($logId && !empty($post['mchOrderNo'])) { + Db::name('pay_callback_log')->where('id', $logId)->update(['unique_no' => $post['mchOrderNo']]); + } + + $payResult = strval($post['payResult'] ?? ''); + + if ($payResult === '0') { + $this->ccpay_recharge_settle($post); + addLogToFile('ccpay 回调成功: order=' . $post['mchOrderNo'], 'ccpay_callback', 'ccpay'); + exit('success'); + } else { + addLogToFile('ccpay 回调非成功状态: payResult=' . $payResult . ' order=' . $post['mchOrderNo'], 'ccpay_callback', 'ccpay'); + exit('success'); + } + } catch (\Exception $e) { + addLogToFile('ccpay 回调异常: ' . $e->getMessage(), 'ccpay_callback_error', 'ccpay'); + exit('fail'); + } + } + + private function ccpay_recharge_settle($data) + { + $orderNo = $data['mchOrderNo']; + + Db::startTrans(); + try { + $order = Db::name('order_record')->where('order_sn', $orderNo)->lock(true)->find(); + if (!$order || $order['status'] == 3) { + Db::rollback(); + return; + } + + $user = Db::name('user')->where([ + 'id' => $order['user_id'], + 'status' => 1, + 'is_delete' => 0, + 'agent' => 0, + ])->lock(true)->find(); + if (!$user) { + Db::rollback(); + return; + } + + $zdlIdArr = explode(',', $user['agent_parent_id_path']); + $zdlId = $zdlIdArr[0]; + + $zdl = Db::name('user')->where([ + 'id' => $zdlId, + 'status' => 1, + 'is_delete' => 0, + 'agent' => 1, + ])->lock(true)->find(); + + if (!$zdl || $zdl['money'] < $order['money']) { + Db::rollback(); + addLogToFile('ccpay 结算失败: 代理余额不足 order=' . $orderNo, 'ccpay_callback_error', 'ccpay'); + return; + } + + $actualMoney = isset($data['amount']) ? intval($data['amount']) : $order['money']; + + Db::name('order_record')->where('id', $order['id'])->update([ + 'back_money' => $actualMoney, + 'back_time' => time(), + 'status' => 3, + 'agent_parent_id' => $user['agent_parent_id'], + 'agent_parent_username' => $user['agent_parent_username'], + 'zdl_id' => $zdl['id'], + 'zdl_username' => $zdl['username'], + 'zdl_money_before' => $zdl['money'], + 'zdl_money_after' => $zdl['money'] - $order['money'], + 'money_before' => $user['money'], + 'money_after' => $user['money'] + $order['money'], + ]); + + Db::name('order_log')->insert([ + 'pay_channel_id' => 9, + 'pay_channel_name' => 'ccpay', + 'money' => $order['money'], + 'create_time' => time(), + 'remake' => 'CCpay回调成功 cp=' . ($data['cpOrderNo'] ?? '') . ' payer=' . ($data['message'] ?? ''), + 'order_id' => $order['id'], + ]); + + Db::name('recharge')->insert([ + 'type' => 4, + 'amount' => $order['money'], + 'mode' => 1, + 'agent_or_admin' => 3, + 'controller_id' => $zdl['id'], + 'controller_username' => $zdl['username'], + 'controller_nickname' => $zdl['nickname'], + 'controller_type' => 'CCpay越南银行第三方充值,扣取总代理余分', + 'controller_old_money' => $zdl['money'], + 'controller_new_money' => $zdl['money'] - $order['money'], + 'user_id' => $order['user_id'], + 'user_type' => $user['agent'], + 'user_agent_level' => 0, + 'username_for' => $user['username'], + 'nickname_for' => $user['nickname'], + 'user_parent_id' => $user['agent_parent_id'], + 'create_time' => time(), + 'old_money' => $user['money'], + 'new_money' => $user['money'] + $order['money'], + 'controller_system' => 3, + 'remake' => 'CCpay越南银行第三方充值成功', + ]); + + Db::name('user')->where('id', $zdl['id'])->update([ + 'money' => $zdl['money'] - $order['money'], + 'last_recharge_out' => $order['money'], + 'last_recharge_out_time' => time(), + 'recharge_out_count' => $zdl['recharge_out_count'] + 1, + 'recharge_out_total_amount' => $zdl['recharge_out_total_amount'] + $order['money'], + ]); + + Db::name('user')->where('id', $order['user_id'])->update([ + 'money' => $user['money'] + $order['money'], + 'last_recharge' => $order['money'], + 'last_recharge_time' => time(), + 'recharge_count' => $user['recharge_count'] + 1, + 'recharge_total_amount' => $user['recharge_total_amount'] + $order['money'], + ]); + + Db::commit(); + addLogToFile('ccpay 结算成功: order=' . $orderNo . ' money=' . $order['money'], 'ccpay_callback', 'ccpay'); + } catch (\Exception $e) { + Db::rollback(); + addLogToFile('ccpay 结算异常: ' . $e->getMessage(), 'ccpay_callback_error', 'ccpay'); + } + } +} diff --git a/application/onlinechip/controller/traits/epayPay.php b/application/onlinechip/controller/traits/epayPay.php new file mode 100644 index 0000000..a0425b6 --- /dev/null +++ b/application/onlinechip/controller/traits/epayPay.php @@ -0,0 +1,523 @@ +post(); + if (isset($post['encryptData'])) { + $post = decrypt_data($post); + if (!$post) { + $data = encrypt_data(['status' => 0, 'message' => 'Dữ liệu không hợp lệ']); + return json(['Success' => 1, 'Data' => $data]); + } + } + + $user_id = intval($post['user_id'] ?? 0); + $money = intval($post['price'] ?? 0); + $client = intval($post['client'] ?? 0); + $username = trim($post['username'] ?? ''); + // 支付子类型:usdt / alipay / wxpay 等,默认 usdt + $pay_type = trim($post['pay_type'] ?? 'usdt'); + + $user = Db::name('user')->where([ + 'id' => $user_id, + 'status' => 1, + 'is_delete' => 0, + 'agent' => 0, + ])->find(); + + if (!$user || $user_id <= 0 || $money <= 0 || $client <= 0) { + $data = encrypt_data(['status' => 0, 'message' => 'Tham số không hợp lệ, vui lòng thử lại']); + return json(['Success' => 1, 'Data' => $data]); + } + + // 地区支线权限(与 AlinPay 一致的风控) + $zdlIdArr = explode(',', $user['agent_parent_id_path']); + $area_list = config('area_list'); + + if (!isset($area_list[$user['area_id']])) { + $data = encrypt_data(['status' => 0, 'message' => 'Khu vực hiện chưa hỗ trợ nạp tiền']); + return json(['Success' => 1, 'Data' => $data]); + } + + $limitAgents = $area_list[$user['area_id']]['limit_agent']; + $isAllow = empty($limitAgents); + foreach ($limitAgents as $allowAgentId) { + if (in_array($allowAgentId, $zdlIdArr)) { + $isAllow = true; + } + } + if (!$isAllow) { + $data = encrypt_data(['status' => 0, 'message' => 'Tài khoản này chưa được phép nạp online']); + return json(['Success' => 1, 'Data' => $data]); + } + + // 总代理余额校验 + $zdlId = $zdlIdArr[0]; + $zdl = Db::name('user')->where([ + 'id' => $zdlId, + 'status' => 1, + 'is_delete' => 0, + 'agent' => 1, + ])->find(); + + if (!$zdl) { + $data = encrypt_data(['status' => 0, 'message' => 'Tài khoản đại lý có vấn đề, không thể nạp']); + return json(['Success' => 1, 'Data' => $data]); + } + if ($zdl['money'] < $money) { + $maxAllowed = intval($zdl['money']); + $data = encrypt_data([ + 'status' => 0, + 'code' => 'AGENT_LIMIT', + 'message' => 'Hạn mức nạp mỗi lần hiện tại là ' . number_format($maxAllowed, 0, '.', ',') . ' VND. Vui lòng nhập số tiền nhỏ hơn hoặc bằng mức trên.', + 'max_amount' => $maxAllowed, + ]); + return json(['Success' => 1, 'Data' => $data]); + } + + $pay_list = config('pay_list'); + $pay_orderid = 'P' . date('YmdHis') . rand(100000, 999999); // P 前缀区分 AlinPay 的 E + $notify_url = $pay_list['epay']['notify_url'] ?? ''; + $return_url = $pay_list['epay']['callback_url'] ?? ''; + $goods_name = $pay_list['epay']['goods_name'] ?? '账户充值'; + $epay_api = $pay_list['epay']['api_url'] ?? 'https://pay.g7g7.top'; + $merchant_id = intval($pay_list['epay']['pid'] ?? 0); + + try { + $epay = new \pay\Epay(); + + // 写 OG 侧订单 + $order_id = Db::name('order_record')->insertGetId([ + 'pay_channel_id' => 8, + 'pay_channel_name' => 'epay', + 'user_id' => $user_id, + 'order_sn' => $pay_orderid, + 'appid' => strval($epay->getConfigInfo()['pid'] ?? ''), + 'api_key' => '', + 'money' => $money, + 'sign' => '', + 'create_time' => time(), + 'back_order_sn' => '', + 'client' => $client, + ]); + + Db::name('order_log')->insert([ + 'pay_channel_id' => 8, + 'pay_channel_name' => 'epay', + 'money' => $money, + 'create_time' => time(), + 'remake' => 'user_id:' . $user_id . ',用户名:' . $username . ',发起充值(' . $pay_type . '):' . $money . ',时间:' . date('Y-m-d H:i:s'), + 'order_id' => $order_id, + 'client' => $client, + ]); + + // 调用 epay 的 mapi.php,让 epay 自己走完整个流程: + // 1) INSERT pre_order + // 2) Channel::submit 算通道 + // 3) Plugin::loadForSubmit → usdtpro_plugin::submit() 算 usdtpro 指纹金额并写入 pre_order + // 4) 返回 {type:'jump', url:'/pay/leader/TRADE_NO/'} + // 注意:usdtpro 指纹金额必须由 epay 侧算,OG 侧算会与 monitor 对账逻辑产生精度漂移,导致充值不到账 + $apiResult = $epay->createOrderApi( + $pay_orderid, + $pay_type, + sprintf('%.2f', $money), + $goods_name, + $notify_url, + $return_url, + 'uid:' . $user_id + ); + + // mapi.php 返回格式: + // {code:0, trade_no, pay_type:'jump', pay_info:'/pay/submit/TRADE_NO/'} 或 + // {code:0, trade_no, payurl:'/pay/submit/TRADE_NO/'} (default 分支) + // {code:1, trade_no, payurl:'...'} (部分旧版) + $submitUrl = ''; + $trade_no = ''; + if (is_array($apiResult)) { + if (!empty($apiResult['trade_no'])) $trade_no = strval($apiResult['trade_no']); + if (!empty($apiResult['payurl'])) $submitUrl = $apiResult['payurl']; + elseif (!empty($apiResult['pay_info'])) $submitUrl = $apiResult['pay_info']; + elseif (!empty($apiResult['url'])) $submitUrl = $apiResult['url']; + } + + if (!$submitUrl || !$trade_no) { + $errMsg = is_array($apiResult) ? (isset($apiResult['msg']) ? $apiResult['msg'] : json_encode($apiResult, JSON_UNESCAPED_UNICODE)) : 'mapi 无响应'; + addLogToFile('epay mapi 下单失败:order=' . $pay_orderid . ' err=' . $errMsg, 'epay_error', 'epay'); + $data = encrypt_data(['status' => 0, 'message' => 'Khởi tạo thanh toán thất bại: ' . $errMsg]); + return json(['Success' => 1, 'Data' => $data]); + } + + // 触发 plugin::submit() 把 usdtpro 指纹金额写入 pre_order + // mapi 模式 Plugin::loadForSubmit 只调 mapi() 方法,usdtpro 插件没这个方法, + // 所以 usdtpro 不会被写入。必须再访问一次 /pay/submit/TRADE_NO/ 让插件 submit() 跑一次 + $this->epay_trigger_plugin_submit($submitUrl); + + // 跳转到用户看的页面(pay/leader/TRADE_NO/) + $payUrl = str_replace('/pay/submit/', '/pay/leader/', $submitUrl); + + // 默认返回结构(若后续读取 usdtpro 失败仍可回退跳转) + $qrcode = null; + + if ($pay_type === 'usdt' && $trade_no) { + // 从 epay.pre_order 读 epay 已经算好的 usdtpro 指纹金额 + 通道地址 + $preOrder = Db::query( + "SELECT o.`trade_no`, o.`usdtpro`, o.`realmoney`, o.`addtime`, c.`config` + FROM `epay`.`pre_order` o + LEFT JOIN `epay`.`pre_channel` c ON c.`id` = o.`channel` + WHERE o.`trade_no` = :tn LIMIT 1", + ['tn' => $trade_no] + ); + + if (!empty($preOrder) && !empty($preOrder[0]['usdtpro'])) { + $row = $preOrder[0]; + $cfg = json_decode($row['config'] ?? '{}', true) ?: []; + $timeout = intval($cfg['timeout'] ?? 600); + $expiresAt = strtotime($row['addtime']) + $timeout; + + $qrcode = [ + 'order_sn' => $pay_orderid, + 'trade_no' => $row['trade_no'], + 'usdt_address' => $cfg['address'] ?? '', + 'usdt_amount' => rtrim(rtrim(sprintf('%.5f', floatval($row['usdtpro'])), '0'), '.'), + 'vnd_amount' => $row['realmoney'], + 'rate' => strval($cfg['rate'] ?? ''), + 'expires_at' => $expiresAt, + 'timeout_sec' => $timeout, + ]; + addLogToFile('epay 下单读取 usdtpro 成功: order=' . $pay_orderid . ' trade_no=' . $trade_no . ' usdt=' . $qrcode['usdt_amount'], 'epay_request', 'epay'); + } else { + addLogToFile('epay 下单 pre_order 未取到 usdtpro: order=' . $pay_orderid . ' trade_no=' . $trade_no, 'epay_error', 'epay'); + } + } + + $data = encrypt_data([ + 'status' => 1, + 'message' => 'Khởi tạo thanh toán thành công', + 'url' => $payUrl, // 兼容老前端 + 'qrcode' => $qrcode, // 新前端内嵌渲染用(usdtpro 由 epay 权威给出) + ]); + return json(['Success' => 1, 'Data' => $data]); + } catch (\Exception $e) { + addLogToFile('epay 下单异常:' . $e->getMessage() . ' | file:' . $e->getFile() . ':' . $e->getLine(), 'epay_error', 'epay'); + $data = encrypt_data(['status' => 0, 'message' => 'Khởi tạo thanh toán thất bại: ' . $e->getMessage()]); + return json(['Success' => 1, 'Data' => $data]); + } + } + + /** + * 触发 epay plugin::submit() 写入 usdtpro 指纹金额 + * 只请求不处理响应(epay 会返回 302 或 HTML,我们只要副作用) + */ + private function epay_trigger_plugin_submit($submitUrl) + { + try { + $ch = curl_init($submitUrl); + curl_setopt_array($ch, [ + CURLOPT_RETURNTRANSFER => true, + CURLOPT_FOLLOWLOCATION => false, + CURLOPT_CONNECTTIMEOUT => 3, + CURLOPT_TIMEOUT => 6, + CURLOPT_SSL_VERIFYPEER => false, + CURLOPT_SSL_VERIFYHOST => false, + CURLOPT_USERAGENT => 'OG-EpayInternal/1.0', + ]); + curl_exec($ch); + curl_close($ch); + } catch (\Exception $e) { + addLogToFile('epay_trigger_plugin_submit 异常:' . $e->getMessage(), 'epay_error', 'epay'); + } + } + + /** + * 易支付 - 订单状态轮询 + * + * 前端轮询该接口,判断是否到账或已超时。 + * 返回 Data 结构: + * { status: 0|1|2, message, money, paid_time } + * 0=待支付, 1=已到账, 2=已超时 + */ + public function epay_order_status() + { + $post = Request::instance()->post(); + if (isset($post['encryptData'])) { + $post = decrypt_data($post); + if (!$post) { + return json(['status' => 0, 'message' => '数据解密失败']); + } + } + + $order_sn = trim($post['order_sn'] ?? ''); + $user_id = intval($post['user_id'] ?? 0); + + if ($order_sn === '' || $user_id <= 0) { + $data = encrypt_data(['status' => 0, 'message' => '参数错误']); + return json(['Success' => 1, 'Data' => $data]); + } + + $order = Db::name('order_record') + ->where([ + 'order_sn' => $order_sn, + 'user_id' => $user_id, + 'pay_channel_id' => 8, + ]) + ->find(); + + if (!$order) { + $data = encrypt_data(['status' => 0, 'message' => '订单不存在']); + return json(['Success' => 1, 'Data' => $data]); + } + + // status=3 代表已回调结算完成(见 epay_recharge_settle) + if (intval($order['status']) == 3) { + $data = encrypt_data([ + 'status' => 1, + 'message' => '充值成功', + 'money' => $order['money'], + 'paid_time' => $order['back_time'], + ]); + return json(['Success' => 1, 'Data' => $data]); + } + + // 超时判定:从 epay 配置拿 timeout,兜底 600 + $pay_list = config('pay_list'); + $timeout = intval($pay_list['epay']['timeout'] ?? 600); + if (time() - intval($order['create_time']) > $timeout) { + $data = encrypt_data([ + 'status' => 2, + 'message' => '订单超时', + 'money' => $order['money'], + ]); + return json(['Success' => 1, 'Data' => $data]); + } + + $data = encrypt_data([ + 'status' => 0, + 'message' => '等待支付', + 'money' => $order['money'], + ]); + return json(['Success' => 1, 'Data' => $data]); + } + + /** + * 易支付 - 异步回调处理 + * + * 易支付回调是 GET(pay.php 跳转后用 GET 带参数回 notify_url), + * 但也可能 POST —— 都兼容 + */ + public function epay_recharge_callback() + { + $request = Request::instance(); + $data = $request->post(); + if (empty($data)) { + $data = $request->get(); + } + + $json = json_encode($data, JSON_UNESCAPED_UNICODE); + addLogToFile('epay 回调原始数据:' . $json, 'epay_callback', 'epay'); + + if (!is_array($data) || empty($data['out_trade_no']) || empty($data['sign'])) { + Log::record($data, 'epay_error_callback'); + exit('fail'); + } + + // 记录回调日志 + $logId = Db::name('pay_callback_log')->insertGetId([ + 'pay_channel' => 'EPAY_RECHARGE', + 'type' => 'recharge', + 'json' => $json, + 'create_time' => date('Y-m-d H:i:s'), + ]); + + try { + $epay = new \pay\Epay(); + $result = $epay->verifyNotifyCallback($data, $logId); + + if (!$result['verified']) { + exit('fail'); + } + + if ($result['success']) { + $this->epay_recharge_settle($data); + exit('success'); + } else { + // 非 TRADE_SUCCESS —— 返 success 让对方不再重试 + addLogToFile('epay 回调非成功状态,ack 防重试:order=' . ($data['out_trade_no'] ?? ''), 'epay_callback', 'epay'); + exit('success'); + } + } catch (\Exception $e) { + addLogToFile('epay 回调处理异常:' . $e->getMessage(), 'epay_callback_error', 'epay'); + exit('fail'); + } + } + + /** + * 易支付结算(事务保护:加锁 → 扣代理 → 加用户 → 写日志) + * 和 alin_recharge_settle 同构,只是 pay_channel 改成 epay + */ + private function epay_recharge_settle($data) + { + $orderNo = $data['out_trade_no']; + + Db::startTrans(); + try { + $order = Db::name('order_record')->where('order_sn', $orderNo)->lock(true)->find(); + if (!$order || $order['status'] == 3) { + Db::rollback(); + return; + } + + $user = Db::name('user')->where([ + 'id' => $order['user_id'], + 'status' => 1, + 'is_delete' => 0, + 'agent' => 0, + ])->lock(true)->find(); + if (!$user) { + Db::rollback(); + return; + } + + $zdlIdArr = explode(',', $user['agent_parent_id_path']); + $zdlId = $zdlIdArr[0]; + + $zdl = Db::name('user')->where([ + 'id' => $zdlId, + 'status' => 1, + 'is_delete' => 0, + 'agent' => 1, + ])->lock(true)->find(); + + if (!$zdl || $zdl['money'] < $order['money']) { + Db::rollback(); + addLogToFile('epay 结算失败:代理余额不足 order=' . $orderNo, 'epay_callback_error', 'epay'); + return; + } + + // 实际到账金额:易支付回调中的 money 字段(CNY) + $actualMoney = isset($data['money']) ? floatval($data['money']) : $order['money']; + + // 1. 更新订单 + Db::name('order_record')->where('id', $order['id'])->update([ + 'back_money' => $actualMoney, + 'back_time' => time(), + 'status' => 3, + 'agent_parent_id' => $user['agent_parent_id'], + 'agent_parent_username' => $user['agent_parent_username'], + 'zdl_id' => $zdl['id'], + 'zdl_username' => $zdl['username'], + 'zdl_money_before' => $zdl['money'], + 'zdl_money_after' => $zdl['money'] - $order['money'], + 'money_before' => $user['money'], + 'money_after' => $user['money'] + $order['money'], + ]); + + // 2. 订单日志 + Db::name('order_log')->insert([ + 'pay_channel_id' => 8, + 'pay_channel_name' => 'epay', + 'money' => $order['money'], + 'create_time' => time(), + 'remake' => '易支付回调成功 trade_no=' . ($data['trade_no'] ?? '') . ' type=' . ($data['type'] ?? ''), + 'order_id' => $order['id'], + ]); + + // 3. recharge 流水 + Db::name('recharge')->insert([ + 'type' => 4, + 'amount' => $order['money'], + 'mode' => 1, + 'agent_or_admin' => 3, + 'controller_id' => $zdl['id'], + 'controller_username' => $zdl['username'], + 'controller_nickname' => $zdl['nickname'], + 'controller_type' => '易支付第三方充值,扣取总代理余分', + 'controller_old_money' => $zdl['money'], + 'controller_new_money' => $zdl['money'] - $order['money'], + 'user_id' => $order['user_id'], + 'user_type' => $user['agent'], + 'user_agent_level' => 0, + 'username_for' => $user['username'], + 'nickname_for' => $user['nickname'], + 'user_parent_id' => $user['agent_parent_id'], + 'create_time' => time(), + 'old_money' => $user['money'], + 'new_money' => $user['money'] + $order['money'], + 'controller_system' => 3, + 'remake' => '易支付第三方充值成功(' . ($data['type'] ?? '') . ')', + ]); + + // 4. 扣代理 + Db::name('user')->where('id', $zdl['id'])->update([ + 'money' => $zdl['money'] - $order['money'], + 'last_recharge_out' => $order['money'], + 'last_recharge_out_time' => time(), + 'recharge_out_count' => $zdl['recharge_out_count'] + 1, + 'recharge_out_total_amount' => $zdl['recharge_out_total_amount'] + $order['money'], + ]); + + // 5. 加用户 + Db::name('user')->where('id', $order['user_id'])->update([ + 'money' => $user['money'] + $order['money'], + 'last_recharge' => $order['money'], + 'last_recharge_time' => time(), + 'recharge_count' => $user['recharge_count'] + 1, + 'recharge_total_amount' => $user['recharge_total_amount'] + $order['money'], + ]); + + Db::commit(); + addLogToFile('epay 结算成功:order=' . $orderNo . ' money=' . $order['money'], 'epay_callback', 'epay'); + } catch (\Exception $e) { + Db::rollback(); + addLogToFile('epay 结算异常:' . $e->getMessage(), 'epay_callback_error', 'epay'); + } + } +} diff --git a/application/onlinechip/view/order/wappay.html b/application/onlinechip/view/order/wappay.html index 28e83e5..44f8296 100644 --- a/application/onlinechip/view/order/wappay.html +++ b/application/onlinechip/view/order/wappay.html @@ -204,7 +204,7 @@ @@ -233,7 +233,8 @@ query.price = price; query.username = username; query.pay_type = pay_type; - url = '/order/'; + // 每种支付方式对应的 online_order 路由可能不同 + url = $('#pay_type option:selected').data('url') || '/order/'; //var winRef = window.open("","_blank"); $.ajax({ url:url, diff --git a/extend/pay/AlinPay.php b/extend/pay/AlinPay.php index f7dd384..6eb3cb5 100644 --- a/extend/pay/AlinPay.php +++ b/extend/pay/AlinPay.php @@ -64,8 +64,8 @@ class AlinPay $config = json_decode($config, true); $this->config = $config; - // 域名从配置读取,回退默认值 - $this->domain = $config['domain'] ?? 'https://alinintermon-api.fantianchuangshi.com'; + // 域名从配置读取,回退默认值(2026-05 第三方网关由 fantianchuangshi.com 迁至 hypayment.net) + $this->domain = $config['domain'] ?? 'https://alinintermon-api.hypayment.net'; } /** diff --git a/extend/pay/Ccpay.php b/extend/pay/Ccpay.php new file mode 100644 index 0000000..447f3c3 --- /dev/null +++ b/extend/pay/Ccpay.php @@ -0,0 +1,132 @@ +config = config('pay_list.ccpay') ?: []; + $this->apiUrl = $this->config['api_url'] ?? ''; + $this->mchNo = $this->config['mch_no'] ?? ''; + $this->paySecret = $this->config['pay_secret'] ?? ''; + } + + public function getConfigInfo() + { + return $this->config; + } + + public function generateSign(array $params) + { + unset($params['sign']); + ksort($params); + $str = ''; + foreach ($params as $k => $v) { + if (is_string($v) && strlen($v) > 0) { + $str .= "{$k}={$v}&"; + } + } + $str = substr($str, 0, -1) . '&paySecret=' . $this->paySecret; + return strtoupper(md5($str)); + } + + public function verifySign(array $params) + { + $received = $params['sign'] ?? ''; + if (!$received) return false; + $calculated = $this->generateSign($params); + return hash_equals($calculated, $received); + } + + public function createOrder($orderNo, $amount, $notifyUrl, $memberId = 'og_user', $callbackUrl = '') + { + $extra = [ + 'bankType' => 'OFFLINE', + 'cardType' => '0', + 'orderPeriod' => '30', + 'memberId' => $memberId, + 'merchantName' => 'OG', + 'notifyUrl' => $notifyUrl, + 'callbackUrl' => $callbackUrl, + ]; + + $data = [ + 'tradeType' => 'cs.pay.submit', + 'version' => '2.0', + 'channel' => 'union_pay', + 'mchNo' => $this->mchNo, + 'body' => 'online_pay', + 'mchOrderNo' => $orderNo, + 'amount' => strval(intval($amount)), + 'currency' => 'VND', + 'timePaid' => date('YmdHis'), + 'remark' => 'online-pay', + ]; + + $signParams = array_merge($data, $extra); + $data['sign'] = $this->generateSign($signParams); + $data['extra'] = json_encode($extra); + + addLogToFile('ccpay 下单请求: order=' . $orderNo . ' amount=' . $amount . ' params=' . json_encode($data, JSON_UNESCAPED_UNICODE), 'ccpay_request', 'ccpay'); + + $result = $this->postForm($this->apiUrl, $data); + + addLogToFile('ccpay 下单返回: ' . json_encode($result, JSON_UNESCAPED_UNICODE), 'ccpay_response', 'ccpay'); + + return $result; + } + + public function queryOrder($orderNo) + { + $data = [ + 'tradeType' => 'cs.order.query', + 'version' => '2.0', + 'mchNo' => $this->mchNo, + 'mchOrderNo' => $orderNo, + ]; + $data['sign'] = $this->generateSign($data); + + return $this->postForm($this->apiUrl, $data); + } + + private function postForm($url, $params) + { + $ch = curl_init($url); + $body = ''; + foreach ($params as $k => $v) { + if (!is_string($v)) continue; + $body .= $k . '=' . urlencode($v) . '&'; + } + $body = rtrim($body, '&'); + + curl_setopt_array($ch, [ + CURLOPT_RETURNTRANSFER => true, + CURLOPT_POST => true, + CURLOPT_POSTFIELDS => $body, + CURLOPT_HTTPHEADER => ['Content-Type: application/x-www-form-urlencoded; charset=UTF-8'], + CURLOPT_CONNECTTIMEOUT => 10, + CURLOPT_TIMEOUT => 30, + CURLOPT_SSL_VERIFYPEER => false, + CURLOPT_SSL_VERIFYHOST => false, + ]); + + $resp = curl_exec($ch); + $err = curl_error($ch); + $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); + curl_close($ch); + + if ($resp === false) { + addLogToFile("ccpay curl 失败: code={$code} err={$err}", 'ccpay_error', 'ccpay'); + return null; + } + + return json_decode($resp, true); + } +} diff --git a/extend/pay/Epay.php b/extend/pay/Epay.php new file mode 100644 index 0000000..521349a --- /dev/null +++ b/extend/pay/Epay.php @@ -0,0 +1,213 @@ +getConfig(); + } + + /** + * 获取配置 + * 优先读 pay_channel 表(和 AlinPay 一致的存储位置), + * 回退到 config('pay_list.epay') + */ + private function getConfig() + { + $dbConfig = Db::name('pay_channel')->where('key', 'EPAY')->value('value'); + if ($dbConfig) { + $this->config = json_decode($dbConfig, true) ?: []; + } else { + $this->config = config('pay_list.epay') ?: []; + } + $this->apiUrl = $this->config['api_url'] ?? 'https://pay.g7g7.top'; + } + + public function getConfigInfo() + { + return $this->config; + } + + /** + * 生成签名 + * + * @param array $params + * @return string + */ + public function generateSign(array $params) + { + unset($params['sign'], $params['sign_type']); + + // 过滤空值(易支付官方要求) + $params = array_filter($params, function ($val) { + return $val !== '' && $val !== null; + }); + + ksort($params); + + $parts = []; + foreach ($params as $k => $v) { + $parts[] = $k . '=' . $v; + } + $str = implode('&', $parts) . ($this->config['key'] ?? ''); + + return md5($str); + } + + /** + * 验证回调签名(时间安全比较) + * + * @param array $params + * @return bool + */ + public function verifySign(array $params) + { + $received = $params['sign'] ?? ''; + $calculated = $this->generateSign($params); + return hash_equals($calculated, $received); + } + + /** + * 构造发起支付的 URL(跳转式 submit.php) + * 前端收到该 URL 后直接 window.location 跳转即可 + * + * @param string $orderNo 商户订单号 + * @param string $type 支付方式:alipay|wxpay|qqpay|bank|jdpay|usdt + * @param string $amount 金额(元) + * @param string $name 商品名称 + * @param string $notifyUrl 异步通知地址 + * @param string $returnUrl 同步跳转地址 + * @param string $param 业务扩展参数(可选,原样回传) + * @return string + */ + public function buildPayUrl($orderNo, $type, $amount, $name, $notifyUrl, $returnUrl = '', $param = '') + { + $params = [ + 'pid' => strval($this->config['pid'] ?? ''), + 'type' => $type, + 'out_trade_no' => strval($orderNo), + 'notify_url' => $notifyUrl, + 'return_url' => $returnUrl, + 'name' => $name, + 'money' => strval($amount), + 'param' => $param, + 'sign_type' => 'MD5', + ]; + + $params['sign'] = $this->generateSign($params); + + $params = array_filter($params, function ($v) { + return $v !== '' && $v !== null; + }); + + return rtrim($this->apiUrl, '/') . '/submit.php?' . http_build_query($params); + } + + /** + * API 模式下单(mapi.php) + * + * @param string $clientIp 下单用户的 IP(mapi.php 必填,否则报 "用户IP地址(clientip)不能为空") + * @return array|null + */ + public function createOrderApi($orderNo, $type, $amount, $name, $notifyUrl, $returnUrl = '', $param = '', $clientIp = '') + { + if ($clientIp === '' || $clientIp === null) { + $clientIp = \think\Request::instance()->ip(); + } + $params = [ + 'pid' => strval($this->config['pid'] ?? ''), + 'type' => $type, + 'out_trade_no' => strval($orderNo), + 'notify_url' => $notifyUrl, + 'return_url' => $returnUrl, + 'name' => $name, + 'money' => strval($amount), + 'param' => $param, + 'clientip' => strval($clientIp), + 'sign_type' => 'MD5', + ]; + $params['sign'] = $this->generateSign($params); + + $url = rtrim($this->apiUrl, '/') . '/mapi.php'; + + addLogToFile('epay API 下单请求:' . $url . ' params=' . json_encode($params, JSON_UNESCAPED_UNICODE), 'epay_request', 'epay'); + + $result = httpPost($url, $params); + + addLogToFile('epay API 下单返回:' . json_encode($result, JSON_UNESCAPED_UNICODE), 'epay_response', 'epay'); + + if (is_array($result)) return $result; + if (is_string($result)) return json_decode($result, true); + return null; + } + + /** + * 订单查询 + */ + public function queryOrder($orderNo) + { + $params = [ + 'act' => 'order', + 'pid' => strval($this->config['pid'] ?? ''), + 'out_trade_no' => strval($orderNo), + ]; + $params['sign'] = $this->generateSign($params); + $params['sign_type'] = 'MD5'; + + $url = rtrim($this->apiUrl, '/') . '/api.php?' . http_build_query($params); + $resp = httpGet($url); + return is_string($resp) ? json_decode($resp, true) : $resp; + } + + /** + * 处理异步回调 — 仅验签+解析状态,不操作余额 + * 余额结算由 trait 内 epay_recharge_settle() 统一处理 + * + * @param array $data $_POST 或 $_GET + * @param int $logId 日志 ID + * @return array ['verified' => bool, 'success' => bool, 'data' => array] + */ + public function verifyNotifyCallback($data, $logId = 0) + { + if (!$this->verifySign($data)) { + addLogToFile('epay 回调验签失败:' . json_encode($data, 320), 'epay_callback_error', 'epay'); + return ['verified' => false, 'success' => false, 'data' => $data]; + } + + $orderNo = $data['out_trade_no'] ?? ''; + if ($logId && $orderNo) { + Db::name('pay_callback_log')->where('id', $logId)->update(['unique_no' => $orderNo]); + } + + $success = isset($data['trade_status']) && $data['trade_status'] === 'TRADE_SUCCESS'; + + addLogToFile('epay 回调验签通过:order=' . $orderNo . ' status=' . ($data['trade_status'] ?? ''), 'epay_callback', 'epay'); + + return ['verified' => true, 'success' => $success, 'data' => $data]; + } +}