// +---------------------------------------------------------------------- namespace App\Services\Common; use App\Models\AccountLogModel; use App\Models\ActionLogModel; use App\Models\BalanceLogModel; use App\Models\MemberModel; use App\Services\Api\FinanceService; use App\Services\BaseService; use App\Services\CregisPayService; use App\Services\RedisService; use App\Services\WalletService; use Illuminate\Support\Facades\DB; /** * 充值提现管理-服务类 * @author laravel开发员 * @since 2020/11/11 * @package App\Services\Common */ class BalanceLogService extends BaseService { // 静态对象 protected static $instance = null; /** * 构造函数 * @author laravel开发员 * @since 2020/11/11 */ public function __construct() { $this->model = new BalanceLogModel(); } /** * 静态入口 * @return static|null */ public static function make() { if (!self::$instance) { self::$instance = (new static()); } return self::$instance; } /** * 获取列表 * @param $params 参数 * @param int $pageSize 分页大小:默认 15 * @return array */ public function getDataList($params, $pageSize = 10, $field = []) { $query = $this->getQuery($params); $list = $query->select($field ? $field : ['a.*', 'b.nickname']) ->orderBy('a.status','asc') ->orderBy('a.create_time','desc') ->orderBy('a.pay_at','desc') ->paginate($pageSize > 0 ? $pageSize : 9999999); $list = $list ? $list->toArray() : []; if ($list) { foreach ($list['data'] as &$item) { $item['create_time'] = datetime($item['create_time'],'Y-m-d H:i:s'); if($item['user_type'] == 1){ $item['uid'] = $item['user_id']; $item['account'] = isset($item['nickname'])&& $item['nickname']? $item['nickname'] : $item['user_id']; } } } return [ 'pageSize' => $pageSize, 'total' => isset($list['total']) ? $list['total'] : 0, 'list' => isset($list['data']) ? $list['data'] : [] ]; } /** * 查询构造 * @param $params * @return \Illuminate\Database\Eloquent\Builder */ public function getQuery($params) { $where = ['a.mark' => 1]; return $this->model->with(['member']) ->from('balance_logs as a') ->leftJoin('member as b', function($join) { $join->on('b.id','=', 'a.user_id')->where('a.user_type',1); }) ->where($where) ->where(function ($query) use ($params) { $kw = isset($params['keyword']) ? trim($params['keyword']) : ''; if ($kw) { $query->where('b.id', '=', $params['keyword']) ->orWhere('b.nickname', 'like', "%{$params['keyword']}%"); } }) ->where(function ($query) use($params){ // 日期 $date = isset($params['date']) ? $params['date'] : []; $start = isset($date[0])? $date[0] : ''; $end = isset($date[1])? $date[1] : ''; $end = $start>=$end? '' : $end; if ($start) { $query->where('a.create_time','>=', strtotime($start)); } if($end){ $query->where('a.create_time','<=', strtotime($end)); } $orderNo = isset($params['order_no'])? trim($params['order_no']) : ''; if($orderNo){ $query->where('a.order_no', 'like', "%{$orderNo}%"); } $walletUrl = isset($params['wallet_url'])? trim($params['wallet_url']) : ''; if($walletUrl){ $query->where('a.wallet_url', '=', $walletUrl); } $ptWalletUrl = isset($params['pt_wallet_url'])? trim($params['pt_wallet_url']) : ''; if($ptWalletUrl){ $query->where('a.pt_wallet_url', '=', $ptWalletUrl); } $hash = isset($params['hash'])? trim($params['hash']) : ''; if($hash){ $query->where('a.hash', '=', $hash); } $userType = isset($params['user_type'])? $params['user_type'] : 0; if ($userType) { $query->where('a.user_type', $userType); } $payType = isset($params['pay_type'])? $params['pay_type'] : 0; if ($payType) { $query->where('a.pay_type', $payType); } $payStatus = isset($params['pay_status'])? $params['pay_status'] : 0; if ($payStatus) { $query->where('a.pay_status', $payStatus); } $type = isset($params['type'])? $params['type'] : 0; if (is_array($type)) { $query->whereIn('a.type', $type); } else if($type){ $query->where('a.type', $type); } $coinType = isset($params['coin_type'])? $params['coin_type'] : 0; if (is_array($coinType)) { $query->whereIn('a.coin_type', $coinType); } else if($coinType){ $query->where('a.coin_type', $coinType); } $status = isset($params['status'])? $params['status'] : 0; if (is_array($status)) { $query->whereIn('a.status', $status); } else if($status){ $query->where('a.status', $status); } }); } /** * 统计 * @param $params * @return array */ public function count($params) { $query = $this->getQuery($params); $count = $query->count('a.id'); $total = $query->sum('a.money'); return [ 'count' => $count, 'total' => $total ]; } /** * 充值订单数量检测 * @return array|false|mixed */ public function checkCount() { $cacheKey = "caches:withdraw:checkCount"; $data = RedisService::get($cacheKey); if($data || RedisService::exists($cacheKey)){ return $data; } $data = $this->model->where(['type'=>2,'status'=>1,'mark'=>1])->count('id'); if($data>=0){ RedisService::set($cacheKey, $data, rand(3,5)); } return $data; } /** * 统计累计质押金额 * @param $userId 用户ID * @return array|false|mixed */ public function getTotalByUser($userId, $type = 1) { $cacheKey = "caches:balanceLog:total_{$userId}_{$type}"; $data = RedisService::get($cacheKey); if($data || RedisService::exists($cacheKey)){ return $data?$data:'0.00'; } // 真实充提 $data = $this->model->where(['user_id'=>$userId,'type'=>$type,'mark'=>1])->whereIn('status',[1,2])->sum('money'); // 上下分 $total = AccountLogModel::where(['user_id'=> $userId,'type'=>$type==1?5:6,'status'=>1,'mark'=>1])->sum('money'); $data = round($total + $data, 2); RedisService::set($cacheKey, $data, rand(5,10)); return $data?$data:'0.00'; } /** * 团队真实/上下分充提数据 * @param $userId 用户ID * @param int $type * @return array|int[]|mixed */ public function getTeamTotalByUser($userId, $type=1) { $cacheKey = "caches:balanceLog:teamTotal_{$userId}_{$type}"; $data = RedisService::get($cacheKey); if($data || RedisService::exists($cacheKey)){ return $data?$data:['recharge'=>0,'withdraw'=>0,'difference'=>0]; } // 真实充提 if($type == 1){ $recharge = $this->model->from('balance_logs as a') ->leftJoin('member as b','a.user_id','b.id') ->where(function($query) use($userId){ $query->whereRaw("FIND_IN_SET({$userId},lev_b.parent_ids)")->orWhere('a.user_id', $userId); }) ->where(['a.type'=>1,'a.mark'=>1,'b.mark'=>1]) ->whereIn('a.status',[1,2]) ->sum('a.money'); $withdraw = $this->model->from('balance_logs as a') ->leftJoin('member as b','a.user_id','b.id') ->where(function($query) use($userId){ $query->whereRaw("FIND_IN_SET({$userId},lev_b.parent_ids)")->orWhere('a.user_id', $userId); }) ->where(['a.type'=>2,'a.mark'=>1,'b.mark'=>1]) ->whereIn('a.status',[1,2]) ->sum('a.money'); $withdraw = abs($withdraw); }else{ // 上下分 $recharge = AccountLogModel::from('account_log as a') ->leftJoin('member as b','a.user_id','b.id') ->where(function($query) use($userId){ $query->whereRaw("FIND_IN_SET({$userId},lev_b.parent_ids)")->orWhere('a.user_id', $userId); }) ->where(['a.type'=>5,'a.status'=>1,'a.mark'=>1,'b.mark'=>1]) ->sum('a.money'); $withdraw = AccountLogModel::from('account_log as a') ->leftJoin('member as b','a.user_id','b.id') ->where(function($query) use($userId){ $query->whereRaw("FIND_IN_SET({$userId},lev_b.parent_ids)")->orWhere('a.user_id', $userId); }) ->where(['a.type'=>6,'a.status'=>1,'a.mark'=>1,'b.mark'=>1]) ->sum('a.money'); $withdraw = abs($withdraw); } $data = ['recharge'=>$recharge,'withdraw'=>$withdraw,'difference'=>round($recharge - $withdraw, 2)]; RedisService::set($cacheKey, $data, rand(5,10)); return $data; } /** * 提现审核 * @param $params * @return bool */ public function withdrawAuth($params) { $id = isset($params['id'])? $params['id'] : 0; $checkStatus = isset($params['status'])? $params['status'] : 0; $remark = isset($params['audit_remark'])? trim($params['audit_remark']) : ''; $payMoney = isset($params['actual_money'])? floatval($params['actual_money']) : 0; if(!in_array($checkStatus,[2,3])){ $this->error = 1073; return false; } $info = $this->model->with(['member'])->where(['id'=> $id,'mark'=>1])->first(); $type = isset($info['type'])? $info['type'] : 0; $coinType = isset($info['coin_type'])? $info['coin_type'] : 0; $accountUserId = isset($info['user_id'])? $info['user_id'] : 0; $money = isset($info['money'])? $info['money'] : 0; $actualMoney = isset($info['actual_money'])? $info['actual_money'] : 0; $fee = isset($info['fee'])? $info['fee'] : 0; $status = isset($info['status'])? $info['status'] : 0; $accountWalletUrl = isset($info['wallet_url'])? $info['wallet_url'] : ''; $orderNo = isset($info['order_no'])? $info['order_no'] : ''; if($id<=0 || empty($info) || $accountUserId<=0 || empty($orderNo) || empty($accountWalletUrl)){ $this->error = 4001; return false; } if($actualMoney<=0 && $payMoney<=0){ $this->error = 4010; return false; } $payMoney = $payMoney? $payMoney : $actualMoney; if($payMoney > $money){ $this->error = 4011; return false; } if($status != 1){ $this->error = 4002; return false; } if($type != 2){ $this->error = 4008; return false; } $cacheKey ="caches:withdraw:lock_{$id}"; if(RedisService::get($cacheKey)){ $this->error = 1034; return false; } // 绑定的用户ID $userId = $accountUserId; $userInfo = isset($info['member'])? $info['member'] : []; if(empty($userInfo)){ $this->error = 4004; return false; } // 审核处理 RedisService::set($cacheKey, true, rand(5, 10)); DB::beginTransaction(); // 审核通过到账处理 $coinName = $coinType==1?'USDT余额':'收益'; if($checkStatus == 2) { // USDT链上打款 $walletUrl = isset($info['wallet_url'])? $info['wallet_url'] : ''; if(empty($walletUrl)){ DB::rollBack(); $this->error = 4005; RedisService::clear($cacheKey); return false; } // 用户钱包和提现地址验证 $walletToken = isset($userInfo['wallet_token'])? $userInfo['wallet_token'] : ''; if($walletUrl!=$accountWalletUrl || $walletToken != make_wallet_token($walletUrl, $userId)){ DB::rollBack(); $this->error = 4009; RedisService::clear($cacheKey); return false; } // 验证是否为有效Sol链地址 // if (!WalletService::make()->checkAddress($walletUrl)) { // DB::rollBack(); // $this->error = CregisPayService::make()->getError(); // RedisService::clear($cacheKey); // return false; // } $updateData = ['status'=>2,'actual_money'=>$payMoney,'audit_remark'=>$remark, 'update_time' => time()]; if(!$this->model->where(['id'=> $id])->update($updateData)){ DB::rollBack(); $this->error = 4006; RedisService::clear($cacheKey); return false; } // U盾出账 try { $payRemark = $coinType == 1 ? 'USDT余额提现' : '佣金收益提现'; $count = 0; while($count < 3){ $result = CregisPayService::make()->withdraw($walletUrl, $payMoney, $orderNo, '1000', '', $payRemark); if($result){ $count++; sleep(1); }else { break; } } // 平台钱包出账 $data = isset($result['data'])? $result['data'] : []; $tradeCid = isset($data['cid']) ? $data['cid'] : ''; if(empty($tradeCid)){ DB::rollBack(); $this->error = CregisPayService::make()->getError(); RedisService::clear($cacheKey); return false; } $updateData = ['trade_cid' => $tradeCid, 'update_time' => time()]; if(!$this->model->where(['id'=> $id])->update($updateData)){ DB::rollBack(); $this->error = 4006; RedisService::clear($cacheKey); return false; } } catch (\Exception $exception){ DB::rollBack(); $this->error = $exception->getMessage(); RedisService::clear($cacheKey); return false; } } // 审核失败驳回退款 else{ $updateData = ['status'=> 3,'audit_remark'=> $remark,'update_time'=> time()]; if(!$this->model->where(['id'=> $id])->update($updateData)){ DB::rollBack(); $this->error = 1072; RedisService::clear($cacheKey); return false; } // 会员:USDT驳回入账 if($coinType == 1){ $balance = isset($userInfo['usdt'])? $userInfo['usdt'] : 0; $updateData = [ 'usdt' => DB::raw("usdt + {$money}"), 'sbt' => DB::raw("sbt + {$fee}"), 'update_time'=>time() ]; if (!MemberModel::where(['id' => $accountUserId])->update($updateData)){ DB::rollBack(); $this->error = 1072; RedisService::clear($cacheKey); return false; } } // 收益退回 else if($coinType == 2){ $balance = isset($userInfo['profit'])? $userInfo['profit'] : 0; $updateData = [ 'profit' => DB::raw("profit + {$money}"), 'sbt' => DB::raw("sbt + {$fee}"), 'update_time'=>time() ]; if (!MemberModel::where(['id' => $accountUserId])->update($updateData)){ DB::rollBack(); $this->error = 1072; RedisService::clear($cacheKey); return false; } } // 账户明细 $log = [ 'user_id' => $accountUserId, 'order_no' => $orderNo, 'type' => 17, 'coin_type' => $coinType==2? 3 : 1, 'user_type'=> 1, 'money' => $money, 'before_money' => $balance, 'create_time' => time(), 'update_time' => date('Y-m-d H:i:s'), 'action_ip' => get_client_ip(), 'remark' => "{$coinName}提现退还", 'status' => 1, 'mark' => 1, ]; if(!AccountLogModel::insertGetId($log)){ DB::rollBack(); $this->error = 2029; RedisService::clear($cacheKey); return false; } } DB::commit(); $this->error = 1071; RedisService::clear($cacheKey); ActionLogModel::setTitle("{$coinName}提现审核"); ActionLogModel::record(); return true; } }