// +---------------------------------------------------------------------- namespace App\Services\Common; use App\Models\AccountLogModel; use App\Models\ActionLogModel; use App\Models\BalanceLogModel; use App\Models\DriverModel; use App\Models\FreightPackageModel; use App\Models\MemberModel; use App\Services\Api\MessageService; use App\Services\Api\PaymentService; use App\Services\BaseService; use App\Services\RedisService; use Illuminate\Support\Facades\DB; /** * 余额账户管理-服务类 * @author laravel开发员 * @since 2020/11/11 * Class BalanceLogService * @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(); } /** * 静态入口 */ public static function make() { if (!self::$instance) { self::$instance = new static(); } return self::$instance; } /** * 列表 * @param $params * @param int $pageSize * @return array */ public function getDataList($params, $pageSize = 10) { $where = ['a.mark' => 1]; $list = $this->model->from('balance_logs as a') ->leftJoin('member as b','b.id','=','a.user_id') ->leftJoin('driver as c','c.id','=','a.user_id') ->where($where) ->where(function ($query) use($params){ $userType = isset($params['user_type'])? $params['user_type'] : 0; if($userType == 1){ $query->where('a.user_type', $userType); $keyword = isset($params['keyword'])? $params['keyword'] : ''; if($keyword){ $query->where(function($query) use($keyword){ $query->where('a.order_no','like',"%{$keyword}%")->orWhere('b.nickname','like',"%{$keyword}%")->orWhere('b.mobile','like',"%{$keyword}%"); }); } }else if ($userType == 2){ $query->where('a.user_type', $userType); $keyword = isset($params['keyword'])? $params['keyword'] : ''; if($keyword){ $query->where(function($query) use($keyword){ $query->where('a.order_no','like',"%{$keyword}%")->orWhere('c.realname','like',"%{$keyword}%")->orWhere('c.mobile','like',"%{$keyword}%"); }); } } }) ->where(function ($query) use($params){ $status = isset($params['status'])? $params['status'] : 0; if($status>0 && is_array($status)){ $query->whereIn('a.status', $status); }else if($status){ $query->where('a.status', $status); } $type = isset($params['type'])? $params['type'] : 0; if($type>0){ $query->where('a.type', $type); } }) ->select(['a.*','b.nickname as user_nickname','b.realname as user_realname','b.mobile as user_mobile','c.realname as driver_name','c.mobile as driver_mobile','c.realname as driver_realname']) ->orderBy('a.create_time','desc') ->orderBy('a.id','desc') ->paginate($pageSize > 0 ? $pageSize : 9999999); $list = $list? $list->toArray() :[]; if($list){ foreach($list['data'] as &$item){ $item['create_time'] = $item['create_time']? datetime($item['create_time'],'Y-m-d H.i.s') : ''; $item['qrcode'] = $item['qrcode']? get_image_url($item['qrcode']) : ''; $item['account'] = $item['account']? json_decode($item['account'], true) : []; $item['username'] = $item['user_nickname']? $item['user_nickname'].($item['user_mobile']?'-'.$item['user_mobile']:'') : ''; $item['driver'] = $item['driver_name']? $item['driver_name'].($item['driver_mobile']?'-'.$item['driver_mobile']:'') : ''; if($item['user_type'] == 2){ $item['realname'] = $item['realname']? $item['realname'] : $item['driver_realname']; }else{ $item['realname'] = $item['realname']? $item['realname'] : $item['user_realname']; } } } return [ 'pageSize'=> $pageSize, 'total'=>isset($list['total'])? $list['total'] : 0, 'list'=> isset($list['data'])? $list['data'] : [] ]; } /** * 统计 * @param $params * @return array */ public function getCount($params) { $where = ['a.mark' => 1]; $model = $this->model->from('balance_logs as a') ->leftJoin('member as b','b.id','=','a.user_id') ->leftJoin('driver as c','c.id','=','a.user_id') ->where($where) ->where(function ($query) use($params){ $userType = isset($params['user_type'])? $params['user_type'] : 0; if($userType == 1){ $query->where('a.user_type', $userType); $keyword = isset($params['keyword'])? $params['keyword'] : ''; if($keyword){ $query->where(function($query) use($keyword){ $query->where('a.order_no','like',"%{$keyword}%")->orWhere('b.nickname','like',"%{$keyword}%")->orWhere('b.mobile','like',"%{$keyword}%"); }); } }else if ($userType == 2){ $query->where('a.user_type', $userType); $keyword = isset($params['keyword'])? $params['keyword'] : ''; if($keyword){ $query->where(function($query) use($keyword){ $query->where('a.order_no','like',"%{$keyword}%")->orWhere('c.realname','like',"%{$keyword}%")->orWhere('c.mobile','like',"%{$keyword}%"); }); } } }) ->where(function ($query) use($params){ $status = isset($params['status'])? $params['status'] : 0; if($status>0 && is_array($status)){ $query->whereIn('a.status', $status); }else if($status){ $query->where('a.status', $status); } $type = isset($params['type'])? $params['type'] : 0; if($type>0){ $query->where('a.type', $type); } }); $counts = [ 'count'=> $model->count('a.id'), 'total'=> $model->sum('a.money'), ]; return $counts; } /** * 统计用户充值/提现金额 * @param int $status * @param int $type 类型:1-充值,2-提现 * @return mixed */ public function getTotalByStatus($userType=1,$status=2, $type=2) { $where = ['mark' => 1]; return $this->model->where($where)->where(function($query) use($userType,$type,$status){ if($userType){ $query->where('user_type',$userType); } if($status){ $query->where('status',$status); } if($type){ $query->where('type',$type); } })->sum('money'); } /** * 统计用户提现数量 * @param int $userType 用户类型:1-用户,2-司机 * @return mixed */ public function getCountByType($userType=1) { $where = ['mark' => 1,'status'=>2]; return $this->model->where($where)->where(function($query) use($userType){ if($userType){ $query->where('user_type',$userType); } })->count('user_id'); } /** * 编辑 * @return array */ public function edit() { $params = request()->post(); $id = isset($params['id'])? $params['id'] : 0; $data = [ 'id'=> $id, 'actual_money'=> isset($params['actual_money'])? floatval($params['actual_money']) : 0, 'audit_remark'=> isset($params['audit_remark'])? trim($params['audit_remark']) : '', 'status'=> isset($params['status'])? $params['status'] : 0, 'update_time'=> time(), ]; if($data['status'] == 2){ $data['pay_status'] = 20; } if($data['actual_money']<=0){ $data['actual_money'] = isset($params['money'])? floatval($params['money']) : 0; } return parent::edit($data); } /** * 审核 * @return array */ public function auth() { $params = request()->post(); $id = isset($params['id'])? $params['id'] : 0; $paStatus = isset($params['pay_status'])? $params['pay_status'] : 10; $cacheKey = "caches:members:withdraw:auth_lock_{$id}"; if(RedisService::get($cacheKey)){ return message('请不要频繁操作',false); } $data = [ 'id'=> $id, 'actual_money'=> isset($params['actual_money'])? floatval($params['actual_money']) : 0, 'audit_remark'=> isset($params['audit_remark'])? trim($params['audit_remark']) : '', 'status'=> isset($params['status'])? $params['status'] : 0, 'update_time'=> time(), ]; if($data['actual_money']<=0){ $data['actual_money'] = isset($params['money'])? floatval($params['money']) : 0; } $info = $this->model->with(['member','driver'])->where(['id'=> $id,'mark'=>1])->first(); if($id<=0 || empty($info)){ return message('提现记录不存在',false); } $status = isset($info['status'])? $info['status'] : 0; if($status != 1){ return message('当前状态不可操作',false); } $data['pay_status'] = $paStatus; // 处理 RedisService::set($cacheKey, $info, rand(2,3)); DB::beginTransaction(); $result = parent::edit($data); $success = isset($result['success'])? $result['success'] : ''; if($success != true){ DB::rollBack(); RedisService::clear($cacheKey); return message('审核失败',false); } // 消息通知 $orderNo = isset($info['order_no'])? $info['order_no'] : ''; if($data['status'] == 2){ // 打款 $payOrderId = ''; $payType = isset($info['pay_type'])? $info['pay_type'] : 0; $account = isset($info['account']) && $info['account']? json_decode($info['account'], true) : []; $openid = isset($account['openid'])? $account['openid'] : ''; $realname = isset($account['realname'])? $account['realname'] : ''; $account = isset($account['account'])? $account['account'] : ''; if($paStatus == 20 && in_array($payType,[10,20])){ if($payType == 20 && empty($account)){ DB::rollBack(); RedisService::clear($cacheKey); return message('该用户未设置支付宝收款账号,打款失败',false); } else if($payType == 10 && empty($openid)){ DB::rollBack(); RedisService::clear($cacheKey); return message('该用户未授权绑定微信,打款失败',false); } $order = [ 'order_no'=> $orderNo, 'pay_money'=> $data['actual_money'], 'real_name'=> $realname, 'account'=> $payType == 10? $openid : $account, 'body'=> '余额提现', ]; $scene = $info['user_type']==1? 'withdraw' : 'driverWithdraw'; if(!$payResult = PaymentService::make()->transfer($order,$scene, $payType)){ DB::rollBack(); RedisService::clear($cacheKey); return message(PaymentService::make()->getError(),false); } $orderId = isset($payResult['order_id'])? $payResult['order_id'] : ''; if($orderId){ $this->model->where(['id'=> $id])->update(['transaction_id'=> $orderId,'update_time'=> time()]); } } // 退钱给用户 if($info['user_type'] == 1){ $userInfo = isset($info['member'])?$info['member']:[]; $balance = isset($userInfo['balance'])?$userInfo['balance']: 0; $updateData = [ 'withdraw_total'=> DB::raw("withdraw_total + {$info['money']}"), 'update_time'=> time(), ]; if(!MemberModel::where(['id'=> $info['user_id'],'mark'=>1],)->update($updateData)){ DB::rollBack(); RedisService::clear($cacheKey); return message('提现审核处理失败',false); } // 明细 $log = [ 'user_id' => $info['user_id'], 'source_id' => 0, 'source_order_no' => isset($info['order_no'])? $info['order_no'] :'', 'type' => 8, // 提现退还 'coin_type' => 4, 'user_type'=> 1, 'money' => -$info['money'], 'balance' => $balance, 'create_time' => time(), 'update_time' => time(), 'remark' => '提现成功', 'status' => 1, 'mark' => 1, ]; }else if($info['user_type'] == 2){ $userInfo = isset($info['driver'])?$info['driver']:[]; $balance = isset($userInfo['balance'])?$userInfo['balance']: 0; $updateData = [ 'withdraw_total'=> DB::raw("withdraw_total + {$info['money']}"), 'update_time'=> time(), ]; if(!DriverModel::where(['id'=> $info['user_id'],'mark'=>1],)->update($updateData)){ DB::rollBack(); RedisService::clear($cacheKey); return message('提现审核处理失败',false); } // 明细 $log = [ 'user_id' => $info['user_id'], 'source_id' => 0, 'source_order_no' => isset($info['order_no'])? $info['order_no'] :'', 'type' => 8, // 提现退还 'coin_type' => 4, 'user_type'=> 2, 'money' => -$info['money'], 'balance' => $balance, 'create_time' => time(), 'update_time' => time(), 'remark' => '提现成功', 'status' => 1, 'mark' => 1, ]; }else{ DB::rollBack(); RedisService::clear($cacheKey); return message('类型错误',false); } if ($log && !AccountLogModel::insertGetId($log)) { DB::rollBack(); RedisService::clear($cacheKey); return message('提现审核账户处理失败',false); } $params = [ 'title' => "余额提现审核成功通知", 'description' => "您的余额提现订单【{$orderNo}】已审核通过,请及时查看订单进度", 'type' => 3, // 1-公告通知,2-订单通知,3-交易通知,4-其他 'content' => json_encode([ 'order_no' => ['name' => '订单号', 'text' => $orderNo], 'catch_time' => ['name' => '审核时间', 'text' => date('Y-m-d H:i:s')], 'money' => ['name' => '提现金额', 'text' => $info['money']], 'actual_money' => ['name' => '到账金额', 'text' => $data['actual_money']], 'remark' => ['name' => '审核备注', 'text' => $data['audit_remark']], 'status' => ['name' => '状态', 'text' => '审核通过'], ], 256), 'bind_id' => $id, ]; // 推送消息给用户处理 MessageService::make()->pushMessage($info['user_id'], $params, $info['user_type']); } // 审核失败 else if ($data['status'] == 3){ // 退钱给用户 $balance = 0; if($info['user_type'] == 1){ $userInfo = isset($info['member'])?$info['member']:[]; $balance = isset($userInfo['balance'])?$userInfo['balance']: 0; $updateData = [ 'balance'=> DB::raw("balance + {$info['money']}"), 'update_time'=> time(), ]; if(!MemberModel::where(['id'=> $info['user_id'],'mark'=>1],)->update($updateData)){ DB::rollBack(); RedisService::clear($cacheKey); return message('提现审核处理失败',false); } }else if($info['user_type'] == 2){ $userInfo = isset($info['driver'])?$info['driver']:[]; $balance = isset($userInfo['balance'])?$userInfo['balance']: 0; $updateData = [ 'balance'=> DB::raw("balance + {$info['money']}"), 'update_time'=> time(), ]; if(!DriverModel::where(['id'=> $info['user_id'],'mark'=>1],)->update($updateData)){ DB::rollBack(); RedisService::clear($cacheKey); return message('提现审核处理失败',false); } }else{ DB::rollBack(); RedisService::clear($cacheKey); return message('类型错误',false); } // 明细 $log = [ 'user_id' => $info['user_id'], 'source_id' => 0, 'source_order_no' => isset($info['order_no'])? $info['order_no'] :'', 'type' => 8, // 提现退还 'coin_type' => 4, 'user_type'=> $info['user_type'], 'money' => $info['money'], 'balance' => $balance, 'create_time' => time(), 'update_time' => time(), 'remark' => '提现失败退还', 'status' => 1, 'mark' => 1, ]; if (!AccountLogModel::insertGetId($log)) { DB::rollBack(); RedisService::clear($cacheKey); return message('提现审核账户处理失败',false); } $params = [ 'title' => "余额提现审核失败通知", 'description' => "您的余额提现订单【{$orderNo}】已审核失败,请及时查看订单进度", 'type' => 3, // 1-公告通知,2-订单通知,3-交易通知,4-其他 'content' => json_encode([ 'order_no' => ['name' => '订单号', 'text' => $orderNo], 'catch_time' => ['name' => '审核时间', 'text' => date('Y-m-d H:i:s')], 'money' => ['name' => '提现金额', 'text' => $info['money']], 'actual_money' => ['name' => '退还金额', 'text' => $info['money']], 'remark' => ['name' => '审核备注', 'text' => $data['audit_remark']], 'status' => ['name' => '状态', 'text' => '审核失败'], ], 256), 'bind_id' => $id, ]; // 推送消息给用户处理 MessageService::make()->pushMessage($info['user_id'], $params, $info['user_type']); } // 设置日志标题 ActionLogModel::setTitle("提现审核"); ActionLogModel::record(); DB::commit(); return $result; } /** * 车型选项 * @param int $num * @return array|mixed */ public function getOptions($type=0, $num = 20) { $cacheKey = "caches:index:freight_package_{$type}"; $datas = RedisService::get($cacheKey); if($datas){ return $datas; } $where = ['status'=>1,'mark'=>1]; $datas = $this->model->where($where) ->where(function($query) use($type){ if($type){ $query->whereIn('type',[0, $type]); } }) ->select(['id','name','type','status']) ->limit($num) ->orderBy('sort','desc') ->orderBy('id','asc') ->get(); $datas = $datas? $datas->toArray() : []; if($datas){ RedisService::set($cacheKey, $datas, rand(5, 10)); } return $datas; } }