// +---------------------------------------------------------------------- namespace App\Services\Api; use App\Models\AccountLogModel; use App\Models\MemberBankModel; use App\Models\MemberModel; use App\Models\TradeModel; use App\Models\VideoCollectModel; use App\Models\VideoModel; use App\Services\BaseService; use App\Services\ConfigService; use App\Services\RedisService; use Illuminate\Support\Facades\DB; /** * 承兑商交易管理-服务类 * @author laravel开发员 * @since 2020/11/11 * @package App\Services\Api */ class TradeService extends BaseService { // 静态对象 protected static $instance = null; /** * 构造函数 * @author laravel开发员 * @since 2020/11/11 * GoodsService constructor. */ public function __construct() { $this->model = new TradeModel(); } /** * 静态入口 * @return static|null */ 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 = 18, $field = '', $userId = 0) { $where = ['a.mark' => 1, 'b.mark' => 1]; $field = $field ? $field : 'lev_a.*'; $order = 'lev_a.id desc'; $list = $this->model->with(['member', 'acceptor'])->from('trade as a') ->leftJoin('member as b', 'b.id', '=', 'a.user_id') ->where($where) ->where(function ($query) use ($params, $userId) { $type = isset($params['type']) ? $params['type'] : 0; if ($type > 0) { $query->where('a.type', $type); } $uid = isset($params['user_id']) ? $params['user_id'] : 0; if ($uid > 0) { $query->where('a.user_id', $uid); } $appectorUid = isset($params['acceptor_uid']) ? $params['acceptor_uid'] : 0; if ($appectorUid > 0) { $query->where('a.acceptor_uid', $appectorUid); } $appectorId = isset($params['acceptor_id']) ? $params['acceptor_id'] : 0; if ($appectorId > 0) { $query->where('a.acceptor_id', $appectorId); } }) ->where(function ($query) use ($params) { $keyword = isset($params['kw']) ? $params['kw'] : ''; if ($keyword) { $query->where('a.order_no', 'like', "%{$keyword}%") ->orWhere('b.nickname', 'like', "%{$keyword}%") ->orWhere('b.id', '=', "%{$keyword}%"); } }) ->selectRaw($field) ->orderByRaw($order) ->paginate($pageSize > 0 ? $pageSize : 9999999); $list = $list ? $list->toArray() : []; if ($list && $list['data']) { foreach ($list['data'] as &$item) { $item['time_text'] = isset($item['create_time']) ? dateFormat($item['create_time'], 'Y-m-d H:i') : ''; $member = isset($item['member']) ? $item['member'] : []; if ($member) { $member['avatar'] = isset($member['avatar']) && $member['avatar'] ? get_image_url($member['avatar']) : get_image_url('/images/member/logo.png'); } $item['member'] = $member; } } return [ 'pageSize' => $pageSize, 'total' => isset($list['total']) ? $list['total'] : 0, 'list' => isset($list['data']) ? $list['data'] : [] ]; } /** * 详情 * @param $id * @return array */ public function getInfo($id, $userId = 0, $field = []) { $field = $field ? $field : ['a.*']; $info = $this->model->with(['member', 'acceptor'])->from('trade as a') ->leftJoin('member as b', 'b.id', '=', 'a.user_id') ->where(['a.id' => $id, 'a.mark' => 1, 'b.mark' => 1]) ->select($field) ->first(); $info = $info ? $info->toArray() : []; if ($info) { $member = isset($info['member']) ? $info['member'] : []; if ($member) { $member['avatar'] = isset($member['avatar']) && $member['avatar'] ? get_image_url($member['avatar']) : get_image_url('/images/member/logo.png'); } $info['member'] = $member; $info['time_text'] = isset($info['create_time']) ? dateFormat($info['create_time'], 'Y-m-d H:i') : ''; $info['memberBank'] = MemberBankModel::where(['id' => $info['account_id']])->first(); if (isset($info['memberBank'])) { $info['memberBank']['qrcode'] = get_image_url($info['memberBank']['qrcode']); } } return $info; } /** * 卖出 * @param $goodsId * @return bool */ public function sell($userId, $params, $request) { $goodsId = isset($params['goods_id']) ? intval($params['goods_id']) : 0; $type = isset($params['type']) ? intval($params['type']) : 2; $userInfo = MemberModel::where(['id' => $userId, 'mark' => 1]) ->select(['id', 'nickname', 'status']) ->first(); $status = isset($userInfo['status']) ? $userInfo['status'] : 0; $nickname = isset($userInfo['nickname']) ? $userInfo['nickname'] : ''; if (empty($userInfo) || $status != 1) { $this->error = 2017; return false; } $thumb = isset($params['thumb']) ? trim($params['thumb']) : ''; if ($thumb) { $result = upload_base64($thumb); $thumb = isset($result['file_path']) ? $result['file_path'] : ''; if (empty($thumb)) { $this->error = 2208; return false; } } // 音乐 $musicUrl = isset($params['music_url']) ? trim($params['music_url']) : ''; if ($musicUrl) { $result = upload_remote_image($musicUrl, 'mp3', 'music'); $musicUrl = isset($result['file_path']) ? $result['file_path'] : ''; if (empty($musicUrl)) { $this->error = 2209; return false; } } // 视频 $fileUrl = isset($params['file_url']) ? trim($params['file_url']) : ''; $albums = isset($params['album_urls']) ? json_decode($params['album_urls'], true) : []; if ($type == 1) { if ($fileUrl) { $result = upload_video($request, 'video'); $data = isset($result['data']) ? $result['data'] : []; $fileUrl = isset($data['file_path']) ? $data['file_path'] : ''; if (empty($fileUrl)) { $this->error = 2212; return false; } } else { $this->error = 2213; return false; } } // 相册 else if ($type == 2) { if (empty($albums) || !is_array($albums)) { $this->error = 2211; return false; } $albums = get_format_images($albums); } $title = isset($params['title']) && $params['title'] ? trim($params['title']) : "{$nickname} 发布的短视频"; $description = isset($params['description']) && $params['description'] ? trim($params['description']) : "{$nickname} 发布的短视频"; $publishCheck = ConfigService::make()->getConfigByCode('video_publish_check', 0); $publishCheck = $publishCheck > 0 ? $publishCheck : 0; $tags = isset($params['tags']) && $params['tags'] ? $params['tags'] : ''; $data = [ 'user_id' => $userId, 'title' => $title, 'type' => $type, 'description' => $description, 'tags' => $tags && is_array($tags) ? implode(',', $tags) : $tags, 'file_url' => $fileUrl, 'thumb' => $thumb, 'albums' => $albums ? $albums : '', 'music_hash' => isset($params['music_hash']) ? trim($params['music_hash']) : '', 'music_name' => isset($params['music_name']) ? trim($params['music_name']) : '', 'music_url' => $musicUrl, 'goods_id' => $goodsId, 'visible_type' => isset($params['visible_type']) ? intval($params['visible_type']) : 1, 'is_comment' => isset($params['is_comment']) ? intval($params['is_comment']) : 1, 'status' => $publishCheck ? 1 : 2, 'mark' => 1, 'publish_at' => date('Y-m-d H:i:s'), 'create_time' => time(), ]; RedisService::set('caches:videos:publish', ['params' => $params, 'data' => $data], 600); if ($id = $this->model->insertGetId($data)) { $this->error = 1023; // 发布视频任务处理 TaskService::make()->updateTask($userId, 5, $id); return ['id' => $id]; } $this->error = 1024; return false; } /** * 状态设置 * @return bool */ public function status() { $id = request()->post('id', 0); $status = request()->post('status', 1); if ($id && !$this->model->where(['id' => $id, 'mark' => 1])->value('id')) { $this->error = 2981; return false; } if ($this->model->where(['id' => $id, 'mark' => 1])->update(['status' => $status, 'update_time' => time()])) { $this->error = 1002; return true; } $this->error = 1003; return true; } /** * 删除 * @return bool */ public function delete() { // 参数 $param = request()->all(); $id = getter($param, "id"); if (empty($id)) { $this->error = 2014; return false; } if (!$this->model->where(['id' => $id])->value('id')) { $this->error = 1039; return false; } if ($this->model->where(['id' => $id])->update(['mark' => 0, 'update_time' => time()])) { $this->model->where(['mark' => 0])->where('update_time', '<=', time() - 3 * 86400)->delete(); $this->error = 1025; return true; } else { $this->error = 1026; return false; } } /** * C2C交易,确认 * @param $userId * @param $params * @return array|false */ public function confirm($userId, $params) { $cacheKey = "caches:trade:sellxd:lock_{$userId}"; $role = isset($params['role']) ? trim($params['role']) : ''; if (RedisService::get($cacheKey)) { $this->error = 1034; return false; } // 交易订单记录 $info = $this->getInfo($params['id']); if (!in_array($info['status'], [1, 2])) { $this->error = 1003; return false; } $confirmUser = ''; // 购买 确认付款是用户user_id 确认完成是承兑商acceptor_uid // 卖出 确认付款是承兑商acceptor_uid 确认完成是用户user_id if (($info['type'] == 1 && $info['status'] == 1) || ($info['type'] == 2 && $info['status'] == 2)) { $confirmUser = $info['user_id']; } if (($info['type'] == 1 && $info['status'] == 2) || ($info['type'] == 2 && $info['status'] == 1)) { $confirmUser = $info['user_id']; } if ($info['type'] == 1) { if ($info['status'] == 1) { $confirmUser = $info['acceptor_uid']; } if ($info['status'] == 2) { $confirmUser = $info['acceptor_uid']; } } // 卖出, 确认收款主体是用户 $member = MemberModel::where(['id' => $confirmUser])->first(); if (empty($member)) { $this->error = 1003; return false; } // 确认密码 $payPassword = isset($params['pay_password']) ? trim($params['pay_password']) : ''; if ($member['pay_password'] != get_password($payPassword)) { $this->error = 2038; return false; } // 星豆 DB::beginTransaction(); RedisService::set($cacheKey, $info, rand(2, 3)); // 买入 // 更新trade状态 // 更新account 状态 // 更新member.balance if ($info['status'] == 1) { TradeModel::where(['id' => $info['id']])->update(['update_time' => time(), 'remark' => ($info['type'] == 1 ? '购买' : '卖出') . '金豆,订单已付款', 'status' => 2]); // 消息 if ($info['type'] == 1) { MessageService::make()->pushMessage($userId, '星豆购买已确认', "您在{$info['create_time']}(UTC+8)下单¥{$info['total']}购买{$info['num']}星豆,已确认付款", 3); } else { MessageService::make()->pushMessage($userId, '星豆卖出已确认', "您在{$info['create_time']}(UTC+8)下单¥{$info['total']}卖出{$info['num']}星豆,已确认付款", 3); } } // 订单已完成,放币 if ($info['status'] == 2) { TradeModel::where(['id' => $info['id']])->update(['update_time' => time(), 'remark' => ($info['type'] == 1 ? '购买' : '卖出') . '金豆,订单完成', 'status' => 3]); AccountLogModel::where(['source_id' => $info['id']])->update(['update_time' => time(), 'status' => 1]); if ($info['type'] == 1) { $updateData = ['balance' => DB::raw("balance + {$info['num']}"), 'update_time' => time()]; if (!MemberModel::where(['id' => $info['user_id']])->update($updateData)) { $this->error = 2036; DB::rollBack(); return false; } } else { $updateData = ['balance' => DB::raw("balance + {$info['num']}"), 'update_time' => time()]; if (!MemberModel::where(['id' => $info['acceptor_uid']])->update($updateData)) { $this->error = 2036; DB::rollBack(); return false; } } // 承兑商佣金添加 $updateData = ['usdt' => DB::raw("usdt + {$info['bonus_usdt']}"), 'update_time' => time()]; if (!MemberModel::where(['id' => $info['acceptor_uid']])->update($updateData)) { $this->error = 2036; DB::rollBack(); return false; } // 佣金明细 $acceptorUserInfo = MemberModel::where(['id'=>$info['acceptor_uid']])->first(); // 增加accountLog记录 $log = [ 'user_id' => $info['acceptor_uid'], 'source_id' => $info['id'], 'source_order_no' => $info['order_no'], 'type' => 10, 'coin_type' => 1, 'user_type' => 3, 'money' => $acceptorUserInfo['usdt'] + round($info['bonus_usdt'], 4), 'actual_money' => round($info['bonus_usdt'], 4), 'balance' => $acceptorUserInfo['usdt'], 'create_time' => time(), 'update_time' => time(), 'remark' => "C2C交易-承兑商佣金", 'status' => 1, 'mark' => 1, ]; if (!AccountLogModel::insertGetId($log)) { $this->error = 2407; DB::rollBack(); RedisService::clear($cacheKey); return false; } // 用户交易获取待返积分 $c2cRewardPoints = ConfigService::make()->getConfigByCode('c2c_reward_points', 100); $poins = round($c2cRewardPoints * $info['total'] * 10000)/10000; $updateData = ['wait_score' => DB::raw("wait_score + {$poins}"), 'update_time' => time()]; if (!MemberModel::where(['id' => $info['user_id']])->update($updateData)) { $this->error = 2036; DB::rollBack(); return false; } $userInfo = MemberModel::where(['id'=>$info['user_id']])->first(); // 增加accountLog记录 $log = [ 'user_id' => $info['user_id'], 'source_id' => $info['id'], 'source_order_no' => $info['order_no'], 'type' => 102, 'coin_type' => 4, 'user_type' => 1, 'money' => $userInfo['usdt'], 'actual_money' => $poins, 'balance' => $userInfo['wait_score'], 'create_time' => time(), 'update_time' => time(), 'remark' => "C2C交易-用户待返积分", 'status' => 1, 'mark' => 1, ]; if (!AccountLogModel::insertGetId($log)) { $this->error = 2407; DB::rollBack(); RedisService::clear($cacheKey); return false; } // 消息 if ($info['type'] == 1) { MessageService::make()->pushMessage($userId, '星豆购买已完成', "您在{$info['create_time']}(UTC+8)下单¥{$info['total']}购买{$info['num']}星豆,已成功到账", 3); } else { MessageService::make()->pushMessage($userId, '星豆卖出已完成', "您在{$info['create_time']}(UTC+8)下单¥{$info['total']}卖出{$info['num']}星豆,已成功扣减", 3); } } DB::commit(); $this->error = 2037; RedisService::clear($cacheKey); return ['trade_id' => $info['id']]; } }