backup: 线上最终版本全量备份

包含所有线上运行的改动:
- 代理编辑功能修复(码率/占成/返水率保存)
- CORS跨域修复(Pcapi构造函数统一Origin)
- 支付通道(ccpay/epay新增)
- 代理报表洗码量显示
- AlinPay金额调整
- 代理/会员编辑页面优化
- 多语言更新
This commit is contained in:
OG Backup
2026-06-14 14:19:49 +08:00
parent 490df4c4c5
commit 171f8fce5c
25 changed files with 1570 additions and 247 deletions
+46 -13
View File
@@ -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;
}
+21 -144
View File
@@ -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);
@@ -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;
}
@@ -0,0 +1,412 @@
<?php
namespace app\onlinechip\controller\traits;
use think\Db;
use think\Log;
use think\Request;
trait ccpayPay
{
public function ccpay_online_order()
{
$post = Request::instance()->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');
}
}
}
@@ -0,0 +1,523 @@
<?php
namespace app\onlinechip\controller\traits;
use think\Db;
use think\Log;
use think\Request;
/**
* 彩虹易支付 Trait
*
* 业务定位:
* - 作为 AlinPay(越南银行卡)之外的第二个充值通道,走易支付接 USDT/支付宝/微信 等
* - 当前主要用于 USDT TRC20 收款
*
* 对接文件:
* - extend/pay/Epay.php
* - 支付站点:https://pay.g7g7.top
*
* 公开方法:
* - epay_online_order() 发起充值,前端拿到 url 后跳转易支付
* - epay_recharge_callback() 接收易支付异步回调,验签后结算
*
* 通道编号:
* - pay_channel_id = 8AlinPay 是 7,本通道顺延)
* - 名称标识:epay
*/
trait epayPay
{
/**
* 易支付 - 发起充值下单(内嵌二维码模式)
*
* 直接跨库写 epay.pre_order + 计算 usdtpro 指纹金额,
* 前端内嵌渲染二维码,无需跳转 pay.g7g7.top。
*
* 返回的 Data 结构:
* {
* status: 1|0
* message: 文案
* url: 兼容字段(老前端仍可 window.open 跳转 /pay/leader/trade_no/
* qrcode: { 新字段,前端内嵌渲染
* order_sn: OG 侧订单号(用于轮询)
* usdt_address: TRC20 收款地址
* usdt_amount: 含指纹尾数的精确金额(如 10.0003)
* vnd_amount: VND 原始金额
* rate: 汇率
* expires_at: 订单超时绝对时间戳
* timeout_sec: 总超时秒数
* }
* }
*/
public function epay_online_order()
{
// 兼容加密请求(Pcapi)和明文请求(Order)
$post = Request::instance()->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]);
}
/**
* 易支付 - 异步回调处理
*
* 易支付回调是 GETpay.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');
}
}
}