// +---------------------------------------------------------------------- namespace App\Services\Api; use App\Models\AcceptorModel; use App\Models\AccountLogModel; use App\Models\BalanceLogModel; use App\Models\MemberBankModel; use App\Models\MemberModel; use App\Models\TradeModel; use App\Services\BaseService; use App\Services\ConfigService; use App\Services\RedisService; use App\Services\WalletService; use Illuminate\Support\Facades\DB; /** * 承兑商服务管理-服务类 * @author laravel开发员 * @since 2020/11/11 * @package App\Services\Api */ class AcceptorService extends BaseService { // 静态对象 protected static $instance = null; /** * 构造函数 * @author laravel开发员 * @since 2020/11/11 * MerchantService constructor. */ public function __construct() { $this->model = new AcceptorModel(); } /** * 静态入口 * @return static|null */ public static function make() { if (!self::$instance) { self::$instance = (new static()); } return self::$instance; } /** * 获取缓存列表 * @param $position * @param int $num * @return array|mixed */ public function getDataList($params, $pageSize = 15, $refresh = false, $field = '') { $page = request()->post('page', 1); $cacheKey = "caches:acceptor:page_{$page}_" . md5(json_encode($params) . $pageSize); $datas = RedisService::get($cacheKey); $data = isset($datas['data']) ? $datas['data'] : []; if ($datas && $data && !$refresh) { return [ 'list' => $data, 'total' => isset($datas['total']) ? $datas['total'] : 0, 'pageSize' => $pageSize ]; } $field = $field ? $field : 'lev_a.*,lev_b.nickname,lev_b.username,lev_b.avatar'; $order = 'lev_a.id desc'; $datas = $this->model->from('acceptor as a') ->leftJoin('member as b', 'b.id', '=', 'a.user_id') ->where(['a.mark' => 1, 'b.mark' => 1]) ->where('a.quota', '>', 0) ->whereIn('a.trade_status', [1, 2]) ->where(function ($query) use ($params) { $kw = isset($params['kw']) ? trim($params['kw']) : ''; if ($kw) { $query->where('a.name', 'like', "%{$kw}%"); } }) ->where(function ($query) use ($params) { // 状态 $status = isset($params['status']) && $params['status'] >= 0 ? intval($params['status']) : 2; if ($status > 0) { $query->where('a.status', $status); } $payType = isset($params['pay_type']) && $params['pay_type'] > 0 ? intval($params['pay_type']) : 0; if ($payType) { $query->where('a.pay_type', $payType); } }) ->selectRaw($field) ->orderByRaw($order) ->paginate($pageSize > 0 ? $pageSize : 9999999); $datas = $datas ? $datas->toArray() : []; if ($datas) { $xdPrice = ConfigService::make()->getConfigByCode('xd_price', 100); $currency = isset($params['currency']) && $params['currency'] ? strtoupper($params['currency']) : 'CNY'; $tradeType = isset($params['trade_type']) && $params['trade_type'] ? intval($params['trade_type']) : 1; $cnyPrice = $this->getRealPrice(1, $currency, $tradeType); foreach ($datas['data'] as &$item) { $item['avatar'] = $item['avatar'] ? get_image_url($item['avatar']) : ''; $item['currency_price'] = $this->getRealPrice(1, $currency, 0); $item['currency_quota'] = $this->getRealPrice(floatval($item['quota']), $currency, 3); $item['currency_rate'] = $currency == 'CNY' ? 1 : WalletService::make()->getRateByCNY($currency); $item['usdt_price'] = moneyFormat(1 / $xdPrice, 2); $item['price'] = $cnyPrice; $item['time'] = $item['time'] > 60 ? intval($item['time'] / 60) : 20; } unset($item); RedisService::set($cacheKey, $datas, rand(3, 5)); } return [ 'list' => isset($datas['data']) ? $datas['data'] : [], 'total' => isset($datas['total']) ? $datas['total'] : 0, 'pageSize' => $pageSize ]; } /** * @param $price * @param $urrency * @param int $tradeType * @return string */ public function getRealPrice($money, $currency = 'CNY', $tradeType = 1) { $usdtPrice = RedisService::get("caches:wallets:usdt_rate"); if ($usdtPrice <= 0) { $usdtCnyPrice = ConfigService::make()->getConfigByCode('usdt_cny_price', 7.2); $usdtPrice = $usdtCnyPrice > 0 && $usdtCnyPrice < 100 ? $usdtCnyPrice : 0; } // 人民币与其他币的汇率价格 $currencyPrice = $currency == 'CNY' ? 1 : WalletService::make()->getRateByCNY($currency); // 买价 $xdPrice = ConfigService::make()->getConfigByCode('xd_price', 100); $buyPrice = moneyFormat($money / $xdPrice, 4); // 星豆价格 $cnyPrice = moneyFormat($buyPrice * $usdtPrice, 4); // 币种价格 if ($tradeType == 1) { $xdBuyPriceRate = ConfigService::make()->getConfigByCode('trade_buy_price_rate', 0); $xdBuyPriceRate = $xdBuyPriceRate > 0 && $xdBuyPriceRate < 100 ? $xdBuyPriceRate : 0; $cnyBuyPrice = moneyFormat($cnyPrice + ($cnyPrice * $xdBuyPriceRate / 100), 4); // 上浮价格 return moneyFormat($cnyBuyPrice * $currencyPrice, 4); // 汇率价格 } else if ($tradeType == 2) { $xdSellPriceRate = ConfigService::make()->getConfigByCode('trade_sell_price_rate', 0); $xdSellPriceRate = $xdSellPriceRate > 0 && $xdSellPriceRate < 100 ? $xdSellPriceRate : 0; $cnyBuyPrice = moneyFormat($cnyPrice - ($cnyPrice * $xdSellPriceRate / 100), 4); // 下浮价格 return moneyFormat($cnyBuyPrice * $currencyPrice, 4); // 汇率价格 } return moneyFormat($cnyPrice * $currencyPrice, 4); // 汇率价格 } /** * 获取信息 * @param $where * @param array $field * @return array|mixed */ public function getInfo($id, $field = [], $userId = 0) { if ($id) { $where = ['a.id' => $id, 'a.mark' => 1]; } else if ($userId) { $where = ['a.user_id' => $userId, 'a.mark' => 1]; } else { return false; } $defaultField = ['a.id', 'a.user_id', 'a.realname', 'a.name', 'a.mobile', 'a.telegram', 'a.quota', 'a.pay_type', 'a.usdt', 'a.status', 'b.nickname', 'b.avatar']; $field = $field ? $field : $defaultField; $info = $this->model->from('acceptor as a') ->leftjoin('member as b', 'b.id', '=', 'a.user_id') ->where($where) ->select($field) ->first(); $info = $info ? $info->toArray() : []; if ($info) { $currency = request()->post('currency', 'CNY'); $tradeType = request()->post('trade_type', 1); $xdPrice = ConfigService::make()->getConfigByCode('xd_price', 100); $cnyPrice = $this->getRealPrice(1, $currency, $tradeType); $info['currency_price'] = $this->getRealPrice(1, $currency, 0); $info['currency_quota'] = $this->getRealPrice(floatval($info['quota']), $currency, 3); $info['currency_rate'] = $currency == 'CNY' ? 1 : WalletService::make()->getRateByCNY($currency); $info['usdt_price'] = moneyFormat(1 / $xdPrice, 2); $info['price'] = $cnyPrice; $info['avatar'] = get_image_url($info['avatar']); } return $info; } /** * 修改信息 * @param $userId * @param $params * @return array|false|int[] */ public function saveInfo($userId, $params) { // 验证是否入驻过和入驻状态 $info = $this->model->where(['user_id' => $userId])->select('id', 'realname', 'trade_status', 'status', 'mark')->first(); $tradeStatus = isset($info['trade_status']) ? $info['trade_status'] : 0; $mark = isset($info['mark']) ? $info['mark'] : 0; $id = isset($info['id']) ? $info['id'] : 0; if ($userId && empty($info)) { $this->error = 2216; return false; } // 是否被冻结 if ($id && $tradeStatus == 4 && $mark) { $this->error = 2202; return false; } // 验证账户是否正常 $userInfo = MemberService::make()->getCacheInfo(['id' => $userId], ['id', 'status']); $status = isset($userInfo['status']) ? $userInfo['status'] : 0; if (empty($userInfo) || $status != 1) { $this->error = 2017; return false; } // 入驻数据 $data = [ 'realname' => isset($params['realname']) ? $params['realname'] : '', 'user_id' => $userId, 'mobile' => isset($params['mobile']) ? $params['mobile'] : '', 'telegram' => isset($params['telegram']) ? $params['telegram'] : '', 'price_float' => isset($params['price_float']) ? $params['price_float'] : '', 'create_time' => time(), 'update_time' => time(), 'mark' => 1, ]; // 写入数据 if ($id) { if ($this->model->where(['id' => $id])->update($data)) { $this->error = 2228; RedisService::keyDel("caches:acceptor:info:temp_{$userId}*"); return ['id' => $id]; } else { $this->error = 2229; return false; } } else { if ($merchId = $this->model->insertGetId($data)) { $this->error = 2228; RedisService::keyDel("caches:acceptor:info:temp_{$userId}*"); return ['id' => $id]; } else { $this->error = 2229; return false; } } } /** * 申请入驻 * @param $userId * @param $params * @return array|false|int[] */ public function apply($userId, $params) { // 验证是否入驻过和入驻状态 $info = $this->model->where(['user_id' => $userId])->select('id', 'name', 'trade_status', 'status', 'mark')->first(); $status = isset($info['status']) ? $info['status'] : 0; $tradeStatus = isset($info['trade_status']) ? $info['trade_status'] : 0; $mark = isset($info['mark']) ? $info['mark'] : 0; $id = isset($info['id']) ? $info['id'] : 0; if ($id && $status == 2 && $mark) { $this->error = 2201; return false; } // 是否被冻结 if ($id && $tradeStatus == 4 && $mark) { $this->error = 2202; return false; } // 验证账户是否正常 $userInfo = MemberService::make()->getCacheInfo(['id' => $userId], ['id', 'status']); $status = isset($userInfo['status']) ? $userInfo['status'] : 0; if (empty($userInfo) || $status != 1) { $this->error = 2017; return false; } // 支付方式验证 $payType = isset($params['pay_type']) && $params['pay_type'] ? intval($params['pay_type']) : 1; $payment = MemberBankModel::where(['user_id' => $userId, 'type' => $payType, 'status' => 1, 'mark' => 1])->value('id'); if ($payment <= 0) { $this->error = 3011; return false; } // 入驻数据 $data = [ 'name' => isset($params['name']) ? $params['name'] : '', 'realname' => isset($params['realname']) ? $params['realname'] : '', 'user_id' => $userId, 'mobile' => isset($params['mobile']) ? $params['mobile'] : '', 'telegram' => isset($params['telegram']) ? $params['telegram'] : '', 'pay_type' => $payType, 'price_float' => isset($params['price_float']) ? $params['price_float'] : '', 'create_time' => time(), 'update_time' => time(), 'quota' => 0, 'trade_status' => 1, 'status' => 1, 'mark' => 1, ]; // 写入数据 if ($id) { if ($this->model->where(['id' => $id])->update($data)) { $this->error = 3012; return ['id' => $id]; } else { $this->error = 3013; return false; } } else { if ($id = $this->model->insertGetId($data)) { $this->error = 3014; return ['id' => $id]; } else { $this->error = 3013; return false; } } } /** * 获取入驻信息 * @param $userId * @return mixed */ public function getApplyInfo($userId) { $info = $this->model->where(['user_id' => $userId, 'mark' => 1]) ->orderBy('id', 'desc') ->first(); $info = $info ? $info->setHidden(['quota', 'update_time', 'mark'])->toArray() : []; if ($info) { $payments = [1 => '微信支付', 2 => '支付宝支付', 3 => '银行卡支付']; $info['pay_name'] = isset($payments[$info['pay_type']]) ? $payments[$info['pay_type']] : ''; } return $info; } /** * 充值交易额度 * @param $userId 用户ID * @param $params * @return array|false */ public function rechargeQuota($userId, $params) { // $acceptId = isset($params['id'])? $params['id'] : 0; $usdt = isset($params['usdt']) ? floatval($params['usdt']) : 0; if ($usdt <= 0) { $this->error = 2031; return false; } $info = $this->model->with(['member'])->where(['user_id' => $userId, 'mark' => 1]) ->select(['id', 'realname', 'mobile', 'usdt', 'quota', 'trade_status', 'status']) ->first(); $quota = isset($info['quota']) ? $info['quota'] : 0; $status = isset($info['status']) ? $info['status'] : 0; $acceptId = isset($info['id']) ? $info['id'] : 0; $userInfo = isset($info['member']) ? $info['member'] : []; if ($userId <= 0 || empty($info) || $status != 2) { $this->error = 2015; return false; } // 充值订单 DB::beginTransaction(); $orderNo = get_order_num('DP'); $xdPrice = ConfigService::make()->getConfigByCode('xd_price', 100); $xdPrice = $xdPrice > 0 && $xdPrice <= 10000 ? $xdPrice : 100; $money = round($xdPrice * $usdt, 2); $data = [ 'order_no' => $orderNo, 'user_id' => $acceptId, 'type' => 1, 'user_type' => 3, 'coin_type' => 6, 'money' => $usdt, 'actual_money' => $money, 'pay_type' => 10, 'pay_status' => 20, 'trc_url' => isset($userInfo['trc_url']) ? $userInfo['trc_url'] : '', 'pay_at' => date('Y-m-d H:i:s'), 'date' => date('Y-m-d'), 'create_time' => time(), 'update_time' => time(), 'status' => 2, 'mark' => 1, ]; if (!$orderId = BalanceLogModel::insertGetId($data)) { $this->error = 2033; DB::rollBack(); return false; } // 扣除usdt余额 $updateData = ['usdt' => DB::raw("usdt - {$usdt}"), 'update_time' => time()]; if (!MemberModel::where(['id' => $userId])->update($updateData)) { $this->error = 2036; DB::rollBack(); return false; } // 用户明细 $userUsdt = isset($userInfo['usdt']) ? $userInfo['usdt'] : 0; $log = [ 'user_id' => $userId, 'source_id' => $acceptId, 'source_order_no' => $data['order_no'], 'user_type' => 1, 'type' => 5, 'coin_type' => 1, 'money' => -$usdt, 'actual_money' => -$usdt, 'balance' => $usdt, 'date' => date('Y-m-d'), 'create_time' => time(), 'remark' => '交易额度充值扣除', 'status' => 1, 'mark' => 1 ]; if (!AccountLogModel::insertGetId($log)) { $this->error = 2029; DB::rollBack(); return false; } // 额度增加 $updateData = ['quota' => DB::raw("quota + {$money}"), 'update_time' => time()]; if (!$this->model->where(['id' => $userId])->update($updateData)) { $this->error = 2036; DB::rollBack(); return false; } // 额度明细 $log = [ 'user_id' => $acceptId, 'source_id' => $userId, 'source_order_no' => $data['order_no'], 'user_type' => 3, 'type' => 5, 'coin_type' => 6, 'money' => $money, 'actual_money' => $money, 'balance' => $quota, 'date' => date('Y-m-d'), 'create_time' => time(), 'remark' => '交易额度充值', 'status' => 1, 'mark' => 1 ]; if (!AccountLogModel::insertGetId($log)) { $this->error = 2029; DB::rollBack(); return false; } // 消息 $dateTime = date('Y-m-d H:i:s'); MessageService::make()->pushMessage($userId, '交易额度充值成功', "您在{$dateTime}(UTC+8)成功支付{$usdt}USDT充值{$money}交易额度", 3); DB::commit(); $this->error = 2037; return ['order_id' => $orderId, 'quota' => moneyFormat($quota + $money, 2), 'usdt' => moneyFormat($userUsdt - $usdt, 2)]; } /** * 交易额度提现处理 * @param $userId 用户 * @param $params * @return bool */ public function withdrawQuota($userId, $params) { $money = isset($params['money']) ? $params['money'] : 0; $coinType = isset($params['coin_type']) ? $params['coin_type'] : 0; if ($money <= 0) { $this->error = 2039; return false; } $info = $this->model->with(['member'])->where(['user_id' => $userId, 'mark' => 1]) ->select(['id', 'user_id', 'realname', 'mobile', 'usdt', 'quota', 'status']) ->first(); $usdt = isset($info['usdt']) ? floatval($info['usdt']) : 0; $quota = isset($info['quota']) ? floatval($info['quota']) : 0; $status = isset($info['status']) ? $info['status'] : 0; $tradeStatus = isset($info['trade_status']) ? $info['trade_status'] : 0; $acceptId = isset($info['accept_id']) ? $info['accept_id'] : 0; $userInfo = isset($info['member']) ? $info['member'] : []; if ($acceptId <= 0 || empty($info) || $status != 2) { $this->error = 2039; return false; } if (in_array($tradeStatus, [2, 4])) { $this->error = 2015; return false; } // 提现账户 $trcUrl = isset($userInfo['trc_url']) ? $userInfo['trc_url'] : ''; if (empty($trcUrl)) { $this->error = 2403; return false; } DB::beginTransaction(); // USDT 提现 $payUsdt = 0; $orderNo = get_order_num('DP'); if ($coinType == 1) { $payUsdt = $money; if ($money > $usdt) { $this->error = lang(2040, ['money' => $usdt]); return false; } $updateData = ['usdt' => DB::raw("usdt - {$money}"), 'update_time' => time()]; if (!$this->model->where(['id' => $acceptId])->update($updateData)) { DB::rollBack(); $this->error = 2042; return false; } // 明细 $log = [ 'user_id' => $acceptId, 'source_id' => $userId, 'source_order_no' => $orderNo, 'user_type' => 3, 'type' => 5, 'coin_type' => 1, 'money' => -$usdt, 'actual_money' => -$usdt, 'balance' => $usdt, 'date' => date('Y-m-d'), 'create_time' => time(), 'remark' => '交易余额提现', 'status' => 1, 'mark' => 1 ]; if (!AccountLogModel::insertGetId($log)) { $this->error = 2029; DB::rollBack(); return false; } } // 额度提现 else if ($coinType == 6) { // 时间限制 $limitTime = ConfigService::make()->getConfigByCode('quota_withdraw_time'); $limitTime = $limitTime >= 0 ? $limitTime : 0; $lockQuota = BalanceLogModel::where(['user_id' => $acceptId, 'user_type' => 3, 'coin_type' => 6, 'status' => 1, 'mark' => 1]) ->where('pay_at', '>=', date('Y-m-d H:i:s', time() - $limitTime * 86400)) ->sum('actual_money'); if ($lockQuota > 0 && $money > ($quota - $lockQuota)) { $this->error = lang(2040, ['money' => ($quota - $lockQuota)]); return false; } $xdPrice = ConfigService::make()->getConfigByCode('xd_price', 100); $xdPrice = $xdPrice > 0 && $xdPrice <= 10000 ? $xdPrice : 100; $payUsdt = round($money / $xdPrice, 4); $updateData = ['quota' => DB::raw("quota - {$money}"), 'update_time' => time()]; if (!$this->model->where(['id' => $acceptId])->update($updateData)) { DB::rollBack(); $this->error = 2042; return false; } // 明细 $log = [ 'user_id' => $acceptId, 'source_id' => $userId, 'source_order_no' => $orderNo, 'user_type' => 3, 'type' => 5, 'coin_type' => 6, 'money' => -$money, 'actual_money' => -$money, 'balance' => $quota, 'date' => date('Y-m-d'), 'create_time' => time(), 'remark' => '交易额度提现', 'status' => 1, 'mark' => 1 ]; if (!AccountLogModel::insertGetId($log)) { $this->error = 2029; DB::rollBack(); return false; } } // 提现记录 $data = [ 'order_no' => $orderNo, 'user_id' => $acceptId, 'type' => 2, 'coin_type' => $coinType, 'user_type' => 3, 'money' => $money, 'actual_money' => $payUsdt, 'balance' => $coinType == 1 ? $usdt : $quota, 'date' => date('Y-m-d'), 'trc_url' => $trcUrl, 'create_time' => time(), 'update_time' => time(), 'status' => 1, 'mark' => 1, ]; if (!$id = BalanceLogModel::insertGetId($data)) { DB::rollBack(); $this->error = 2042; return false; } DB::commit(); // 站内消息 $dateTime = date('Y-m-d H:i:s'); $message = $coinType == 1 ? "您在{$dateTime}(UTC+8)申请提现{$money}USDT交易余额成功,请耐心等候审核!!!" : "您在{$dateTime}(UTC+8)申请提现{$money}交易额度成功,请耐心等候审核!!!"; MessageService::make()->pushMessage($userId, $coinType == 1 ? '交易余额提现申请成功' : '交易额度提现申请成功', $message); // 提现自动审核,低于该金额自动审核 $autoCheckUsdt = ConfigService::make()->getConfigByCode('withdraw_auto_money', 300); $autoCheckUsdt = $autoCheckUsdt > 0 ? $autoCheckUsdt : 0; if ($payUsdt <= $autoCheckUsdt) { // 打款处理 $result = WalletService::make()->usdtTrcTransfer($trcUrl, $payUsdt); $txID = isset($result['txId']) ? $result['txId'] : ''; $payAddress = isset($result['address']) ? $result['address'] : ''; if ($txID && $payAddress) { $updateData = ['hash' => $txID, 'wallet_url' => $payAddress, 'audit_remark' => '自动审核打款', 'status' => 2, 'update_time' => time()]; if (BalanceLogModel::where(['user_id' => $acceptId, 'order_no' => $orderNo])->update($updateData)) { $message = $coinType == 1 ? "您在{$dateTime}(UTC+8)申请提现{$money}USDT交易余额审核成功,请耐心等候打款到账!!!" : "您在{$dateTime}(UTC+8)申请提现{$money}交易额度审核成功,请耐心等候打款到账!!!"; MessageService::make()->pushMessage($userId, $coinType == 1 ? '交易余额提现审核成功' : '交易额度提现审核成功', $message); AccountLogModel::where(['source_order_no' => $orderNo])->update(['hash' => $txID, 'update_time' => time()]); } } } $this->error = 2043; return true; } /** * 余额提现 * @param $userId * @param $params * @return array|false */ public function withdraw($userId, $params) { $money = isset($params['money']) ? floatval($params['money']) : 0; $payPassword = isset($params['pay_password']) ? trim($params['pay_password']) : ''; $userType = isset($params['user_type']) && $params['user_type'] ? intval($params['user_type']) : 1; if ($money <= 0) { $this->error = 2401; return false; } if (!in_array($userType, [1, 2, 3])) { $this->error = 2404; return false; } $acceptor = $this->model->with(['member'])->where(['user_id' => $userId, 'mark' => 1]) ->select(['id', 'user_id', 'realname', 'mobile', 'usdt', 'quota', 'status', 'trade_status']) ->first(); // 获取承兑商信息 $userInfo = isset($acceptor['member']) ? $acceptor['member'] : []; $status = isset($userInfo['status']) ? $userInfo['status'] : 0; $userUsdt = isset($userInfo['usdt']) ? $userInfo['usdt'] : 0; if (isset($userInfo['pay_password'])) { $userPayPassword = $userInfo['pay_password']; } else { $userPayPassword = DB::table('member')->where('id', $userId)->value('pay_password'); } $acceptorUsdt = isset($acceptor['usdt']) ? $acceptor['usdt'] : 0; $acceptorId = isset($acceptor['id']) ? $acceptor['id'] : 0; $acceptorTradeStatus = isset($acceptor['trade_status']) ? $acceptor['trade_status'] : 0; if (empty($userInfo) || $status != 1) { $this->error = 2024; return false; } if ($userType == 3 && (empty($acceptor) || !in_array($acceptorTradeStatus, [1, 2]))) { $this->error = 2024; return false; } // 提现金额验证 $accountUsdt = $userType == 1 ? $userUsdt : $acceptorUsdt; if ($money > $accountUsdt) { $this->error = web_lang(2402, ['money' => $accountUsdt]); return false; } // 提现账户 $trcUrl = isset($userInfo['trc_url']) ? $userInfo['trc_url'] : ''; if (empty($trcUrl)) { $this->error = 2403; return false; } if ($userPayPassword != get_password($payPassword)) { $this->error = 2038; return false; } $cacheKey = "caches:member:withdraw:lock_{$userId}"; if (RedisService::get($cacheKey)) { $this->error = 1034; return false; } DB::beginTransaction(); RedisService::set($cacheKey, $userInfo, rand(2, 3)); // 提现记录 $orderNo = get_order_num('DW'); $feeRate = ConfigService::make()->getConfigByCode('withdraw_fee_rate', 5); $feeRate = $feeRate > 0 && $feeRate < 100 ? moneyFormat($feeRate / 100, 2) : 0; $fee = round($money * $feeRate, 2); $realUsdt = moneyFormat($money - $fee, 2); $data = [ 'order_no' => $orderNo, 'user_id' => $userId, 'type' => 2, 'user_type' => $userType, 'coin_type' => 1, 'money' => $money, 'actual_money' => $realUsdt, 'fee' => $fee, 'trc_url' => $trcUrl, 'pay_type' => 20, 'date' => date('Y-m-d'), 'create_time' => time(), 'update_time' => time(), 'status' => 1, 'mark' => 1, ]; if (!$id = BalanceLogModel::insertGetId($data)) { DB::rollBack(); $this->error = 2405; RedisService::clear($cacheKey); return false; } // 商户扣款 if ($userType == 3) { $updateData = [ 'usdt' => DB::raw("usdt - {$money}"), 'update_time' => time() ]; if (!AcceptorModel::where(['user_id' => $userId, 'mark' => 1])->update($updateData)) { DB::rollBack(); $this->error = 2406; RedisService::clear($cacheKey); return false; } // 明细 $log = [ 'user_id' => $acceptorId, 'source_id' => $userId, 'source_order_no' => $orderNo, 'type' => 5, 'coin_type' => 1, 'user_type' => 2, 'money' => -$money, 'actual_money' => -$money, 'balance' => $acceptorUsdt, 'create_time' => time(), 'update_time' => time(), 'remark' => "承兑商账户余额提现", 'status' => 1, 'mark' => 1, ]; if (!AccountLogModel::insertGetId($log)) { $this->error = 2407; DB::rollBack(); RedisService::clear($cacheKey); return false; } } // 用户扣款 else { $updateData = ['usdt' => DB::raw("usdt - {$money}"), 'update_time' => time()]; if (!MemberModel::where(['id' => $userId, 'mark' => 1])->update($updateData)) { DB::rollBack(); $this->error = 2406; RedisService::clear($cacheKey); return false; } // 明细 $log = [ 'user_id' => $userId, 'source_id' => 0, 'source_order_no' => $orderNo, 'type' => 5, 'coin_type' => 1, 'user_type' => 1, 'money' => -$money, 'actual_money' => -$money, 'balance' => $userUsdt, 'create_time' => time(), 'update_time' => time(), 'remark' => "USDT余额提现", 'status' => 1, 'mark' => 1, ]; if (!AccountLogModel::insertGetId($log)) { $this->error = 2407; DB::rollBack(); RedisService::clear($cacheKey); return false; } } DB::commit(); // 站内消息 $dateTime = date('Y-m-d H:i:s'); $title = $userType == 1 ? 'USDT余额提现申请成功' : '承兑商余额提现申请成功'; $message = $userType == 1 ? "您在{$dateTime}(UTC+8)申请提现{$money}USDT余额成功,请耐心等候审核!!!" : "您在{$dateTime}(UTC+8)申请提现{$money}USDT承兑商余额成功,请耐心等候审核!!!"; MessageService::make()->pushMessage($userId, $title, $message); // 提现自动审核,低于该金额自动审核 $autoCheckUsdt = ConfigService::make()->getConfigByCode('withdraw_auto_money', 300); $autoCheckUsdt = $autoCheckUsdt > 0 ? $autoCheckUsdt : 0; if ($money <= $autoCheckUsdt) { // 打款处理 $result = WalletService::make()->usdtTrcTransfer($trcUrl, $realUsdt); $txID = isset($result['txId']) ? $result['txId'] : ''; $payAddress = isset($result['address']) ? $result['address'] : ''; if ($txID && $payAddress) { $updateData = ['hash' => $txID, 'wallet_url' => $payAddress, 'audit_remark' => '自动审核打款', 'status' => 2, 'update_time' => time()]; if (BalanceLogModel::where(['order_no' => $orderNo, 'user_type' => $userType])->update($updateData)) { $title = $userType == 1 ? 'USDT余额提现审核成功' : '承兑商余额提现审核成功'; $message = $userType == 1 ? "您在{$dateTime}(UTC+8)申请提现{$money}USDT余额审核成功,请耐心等候打款到账!!!" : "您在{$dateTime}(UTC+8)申请提现{$money}USDT承兑商余额审核成功,请耐心等候打款到账!!!"; MessageService::make()->pushMessage($userId, $title, $message, 3); AccountLogModel::where(['source_order_no' => $orderNo])->update(['hash' => $txID, 'update_time' => time()]); // 平台明细 $log = [ 'user_id' => 0, 'source_id' => $userId, 'source_order_no' => $orderNo, 'type' => 5, 'coin_type' => 1, 'user_type' => 4, 'money' => $fee, 'actual_money' => $fee, 'balance' => 0, 'create_time' => time(), 'update_time' => time(), 'hash' => $txID, 'remark' => "USDT余额提现", 'status' => 1, 'mark' => 1, ]; AccountLogModel::insertGetId($log); // 平台流水 FinanceService::make()->saveLog(0, $fee, 1); } } } $this->error = $title; RedisService::clear($cacheKey); return [ 'id' => $id, 'money' => $money, 'user_type' => $userType, ]; } /** * C2C交易-购买 * 1.当前登录用户购买 * 2.承兑商卖 * 用户买,则扣承兑商额度,用户付款,承兑商收款然后把订单交易的豆给用户 * 记录trade记录 * @param $userId * @param $params * @return array|false */ public function buyxd($userId, $params) { $cacheKey = "caches:acceptor:buyxd:lock_{$userId}"; if (RedisService::get($cacheKey)) { $this->error = 1034; return false; } // 购买用户信息 $userInfo = $pointInfo = MemberModel::where(['id' => $userId, 'mark' => 1]) ->select(['id', 'usdt', 'balance', 'member_level', 'wait_score', 'pay_password', 'status']) ->first(); // 承兑商信息 $acceptor = $this->model->with(['member'])->where(['id' => $params['acceptor_id'], 'mark' => 1]) ->select(['id', 'user_id', 'realname', 'mobile', 'usdt', 'quota', 'status', 'trade_status', 'pay_type']) ->first(); if (empty($userInfo) || $userInfo['status'] != 1) { $this->error = 2024; return false; } if ($userInfo['pay_password'] != get_password($params['pay_password'])) { $this->error = 2038; return false; } // C2C交易金豆 $orderNo = get_order_num('C2C'); // 卖家1星豆人民币对比价格 $cnyPrice = $this->getRealPrice(1, 'CNY', 1); $money = moneyFormat($this->getRealPrice($params['quota'], 'CNY', 1), 2, true); if (floatval($params['money']) != $money) { $this->error = 2028; return false; } // 星豆 DB::beginTransaction(); RedisService::set($cacheKey, $userInfo, rand(2, 3)); // 承兑商收款信息 $memberBank = MemberBankModel::where(['user_id' => $acceptor['user_id'], 'type' => $acceptor['pay_type'], 'mark' => 1])->first(); // 兑换usdt费率价格 $xdPrice = ConfigService::make()->getConfigByCode('xd_price', 100); $xdPrice = $xdPrice > 0 && $xdPrice <= 10000 ? $xdPrice : 100; $usdt_rate = round(1 / $xdPrice, 4); // 承兑商额外佣金金豆转u $acceptorCommissionRate = ConfigService::make()->getConfigByCode('acceptor_commission_rate', 100); // 保留4位小数点 $bonus_usdt = round($money * $acceptorCommissionRate * 10000)/1000000; // 添加交易订单记录 $data = [ 'user_id' => $userId, 'acceptor_id' => $params['acceptor_id'], 'acceptor_uid' => $acceptor['user_id'], 'order_no' => $orderNo, 'type' => 1, 'coin_type' => 1, 'price' => $cnyPrice, 'num' => $params['quota'], 'account_id' => isset($memberBank) ? $memberBank['id'] : 0, 'mobile' => $acceptor['mobile'], 'real_name' => $acceptor['realname'], 'total' => $money, 'usdt_rate' => $usdt_rate, 'currency' => $params['currency'], 'pay_type' => $params['pay_type'], 'pay_money' => $params['money'], 'pay_status' => 2, 'pay_time' => now(), 'bonus_usdt' => $bonus_usdt,// 承兑商佣金金豆转u 'pay_img' => '', 'create_time' => now(), 'update_time' => now(), 'is_settle' => 2, 'exception_status' => 0, 'sell_exception_img' => '', 'exception_img' => '', 'exception_remark' => '', 'remark' => '购买下单成功,待支付', 'status' => 1, 'mark' => 1, ]; if (!$orderId = TradeModel::insertGetId($data)) { RedisService::clear($cacheKey); $this->error = 2033; DB::rollBack(); return false; } // 扣除承兑商星豆 $updateData = ['balance' => DB::raw("balance - {$params['quota']}"), 'update_time' => time()]; if (!MemberModel::where(['id' => $acceptor['member']['id']])->update($updateData)) { $this->error = 2036; DB::rollBack(); return false; } // 增加accountLog记录 $log = [ 'user_id' => $userId, 'source_id' => $orderId, 'source_order_no' => $orderNo, 'type' => 100, 'coin_type' => 2, 'user_type' => 1, 'money' => round($params['quota'] / $xdPrice, 4), 'actual_money' => $params['quota'], 'balance' => $userInfo['balance'], 'create_time' => time(), 'update_time' => time(), 'remark' => "C2C交易-购买星豆", 'status' => 2, 'mark' => 1, ]; if (!AccountLogModel::insertGetId($log)) { $this->error = 2407; DB::rollBack(); RedisService::clear($cacheKey); return false; } // 消息 $dateTime = date('Y-m-d H:i:s'); MessageService::make()->pushMessage($userId, '星豆购买下单成功', "您在{$dateTime}(UTC+8)成功下单¥{$money}购买{$params['quota']}星豆,请在20分钟内确认支付,否则订单将失效", 3); DB::commit(); $this->error = 2037; RedisService::clear($cacheKey); return ['trade_id' => $orderId, 'money' => $money]; } /** * C2C交易-卖出 * 1.当前登录用户购买 * 2.承兑商卖 * 用户买,则扣承兑商额度,用户付款,承兑商收款然后把订单交易的豆给用户 * 记录trade记录 * @param $userId * @param $params * @return array|false */ public function sellxd($userId, $params) { $cacheKey = "caches:acceptor:sellxd:lock_{$userId}"; if (RedisService::get($cacheKey)) { $this->error = 1034; return false; } // 卖出用户信息 $userInfo = $pointInfo = MemberModel::where(['id' => $userId, 'mark' => 1]) ->select(['id', 'usdt', 'balance', 'member_level', 'wait_score', 'pay_password', 'status']) ->first(); // 承兑商信息 $acceptor = $this->model->with(['member'])->where(['id' => $params['acceptor_id'], 'mark' => 1]) ->select(['id', 'user_id', 'realname', 'mobile', 'usdt', 'quota', 'status', 'trade_status']) ->first(); if (empty($userInfo) || $userInfo['status'] != 1) { $this->error = 2024; return false; } if ($userInfo['pay_password'] != get_password($params['pay_password'])) { $this->error = 2038; return false; } // C2C交易金豆 $orderNo = get_order_num('C2C'); // 卖家1星豆人民币对比价格 $cnyPrice = $this->getRealPrice(1, 'CNY', 1); $money = moneyFormat($this->getRealPrice($params['quota'], 'CNY', 1), 2, true); // if (floatval($params['money']) != $money) { // $this->error = 2028; // return false; // } // 星豆 DB::beginTransaction(); RedisService::set($cacheKey, $userInfo, rand(2, 3)); // 用户收款信息 $memberBank = MemberBankModel::where(['user_id' => $userId, 'type' => $acceptor['pay_type']])->first(); // 兑换usdt费率价格 $xdPrice = ConfigService::make()->getConfigByCode('xd_price', 100); $xdPrice = $xdPrice > 0 && $xdPrice <= 10000 ? $xdPrice : 100; $usdt_rate = round(1 / $xdPrice, 4); // 承兑商额外佣金金豆转u $acceptorCommissionRate = ConfigService::make()->getConfigByCode('acceptor_commission_rate', 100); $bonus_usdt = round(($money * ($acceptorCommissionRate/100)) * 10000)/10000; // 添加交易订单记录 $data = [ 'user_id' => $userId, 'acceptor_id' => $params['acceptor_id'], 'acceptor_uid' => $acceptor['user_id'], 'order_no' => $orderNo, 'type' => 2, 'coin_type' => 1, 'price' => $cnyPrice, 'num' => $params['quota'], 'account_id' => isset($memberBank) ? $memberBank['id'] : 0, 'mobile' => $acceptor['mobile'], 'real_name' => $acceptor['realname'], 'total' => $money, 'usdt_rate' => $usdt_rate, 'currency' => $params['currency'], 'pay_type' => $params['pay_type'], 'pay_money' => $params['money'], 'pay_status' => 2, 'pay_time' => now(), 'bonus_usdt' => $bonus_usdt,// 承兑商佣金金豆转u 'pay_img' => '', 'create_time' => now(), 'update_time' => now(), 'is_settle' => 2, 'exception_status' => 0, 'sell_exception_img' => '', 'exception_img' => '', 'exception_remark' => '', 'remark' => '卖出下单成功,待支付', 'status' => 1, 'mark' => 1, ]; if (!$orderId = TradeModel::insertGetId($data)) { RedisService::clear($cacheKey); $this->error = 2033; DB::rollBack(); return false; } // 扣除用户星豆 $updateData = ['balance' => DB::raw("balance - {$params['quota']}"), 'update_time' => time()]; if (!MemberModel::where(['id' => $userId])->update($updateData)) { $this->error = 2036; DB::rollBack(); return false; } // 增加accountLog记录 $log = [ 'user_id' => $userId, 'source_id' => $orderId, 'source_order_no' => $orderNo, 'type' => 101, 'coin_type' => 2, 'user_type' => 1, 'money' => round($params['quota'] / $xdPrice, 4), 'actual_money' => $params['quota'], 'balance' => $userInfo['balance'], 'create_time' => time(), 'update_time' => time(), 'remark' => "C2C交易-卖出星豆", 'status' => 2, 'mark' => 1, ]; if (!AccountLogModel::insertGetId($log)) { $this->error = 2407; DB::rollBack(); RedisService::clear($cacheKey); return false; } // 消息 $dateTime = date('Y-m-d H:i:s'); MessageService::make()->pushMessage($userId, '星豆购买下单成功', "您在{$dateTime}(UTC+8)成功下单¥{$money}购买{$params['quota']}星豆,请在20分钟内确认支付,否则订单将失效", 3); DB::commit(); $this->error = 2037; RedisService::clear($cacheKey); return ['trade_id' => $orderId, 'money' => $money]; } }