connect($config['host'], $config['port'], 10); } catch (\Exception $exception) { echo 'redis连接失败'; } if (!empty($config['password'])) { $redis->auth($config['password']); } $redis->select($config['select']); return $redis; } /** * @param string $code // 状态码 * @param string $msg // 提示信息 * @param array $result // 返回结果 * @return array */ public function toData(string $code = '', string $msg = '', array $result = []): array { return [ 'code' => $code, 'message' => $msg, 'data' => $result ]; } // 根据是否是代理 以及用户id 获取where条件 public function getWhereByIsAgentAndUserId($adminId, $where, $userId) { // 判断是否是代理 $isAgent = AdminModel::checkUserIsAgent($adminId); // 不是代理 if (!$isAgent) { if ($userId > 0) { $where[] = ['user_id', '=', $userId]; } return $where; } // 获取管理用户 $userIds = AdminModel::getUserIdsByAgentId($adminId); if (empty($userIds)) { return false; } // 如果用户搜索 if ($userId > 0) { $where[] = ['user_id', 'in', $userIds]; $where[] = ['user_id', '=', $userId]; return $where; } // 没有用户搜索 $where[] = ['user_id', 'in', $userIds]; return $where; } // 校验admin_id 是否可以管理 userId public function checkUserIdInAgent($adminId, $userId) { // 判断是否是代理 $isAgent = AdminModel::checkUserIsAgent($adminId); // 不是代理 if (!$isAgent) { return true; } $userIds = AdminModel::getUserIdsByAgentId($adminId); if (in_array($userId, $userIds)) { return true; } return false; } /** * @param $user_id * @param $account_type * @param $change_usable_num * @param $change_frozen_num * @param $change_type 变动类型:1-充值,2-提现,3-买入,4-卖出,5-冻结,6-解冻,7-账户转出,8-账户转入 ,9-注册返佣,10-开仓返佣 ,11-平仓返佣,12-调账加钱 13-调账减钱 19-基金返息 20-IPO订单退款 */ public function updateUserAsset($user_id, $account_type, $change_type, $change_usable_num, $change_frozen_num = 0, $order_no = "", $change_log_admin_id = 0, $rate = 0) { $prefix = env('database.prefix'); $where['user_id'] = $user_id; switch ($account_type) { case 1: $where['digital_id'] = 'USDT'; $table = $prefix . 'user_digital'; $log_table = $prefix . 'user_digital_log'; $log_data['digital_id'] = 'USDT'; break; case 2: $where['contract_id'] = 'USDT'; $table = $prefix . 'user_contract'; $log_table = $prefix . 'user_contract_log'; $log_data['contract_id'] = 'USDT'; break; case 3: $where['stock_id'] = 'USD'; $table = $prefix . 'user_stock'; $log_table = $prefix . 'user_stock_log'; $log_data['stock_id'] = 'USD'; break; case 4: $where['stock_id'] = 'IDR'; $table = $prefix . 'user_stock_idn'; $log_table = $prefix . 'user_stock_idn_log'; $log_data['stock_id'] = 'IDR'; break; case 5: $where['stock_id'] = 'MYR'; $table = $prefix . 'user_stock_mys'; $log_table = $prefix . 'user_stock_mys_log'; $log_data['stock_id'] = 'MYR'; break; case 6: $where['stock_id'] = 'THB'; $table = $prefix . 'user_stock_tha'; $log_table = $prefix . 'user_stock_tha_log'; $log_data['stock_id'] = 'THB'; break; case 7: $where['stock_id'] = 'INR'; $table = $prefix . 'user_stock_in'; $log_table = $prefix . 'user_stock_in_log'; $log_data['stock_id'] = 'INR'; break; case 8: $where['contract_id'] = 'USDT'; $table = $prefix . 'user_contract_sec'; $log_table = $prefix . 'user_contract_sec_log'; $log_data['contract_id'] = 'USDT'; break; case 9: $where['stock_id'] = 'SGD'; $table = $prefix . 'user_stock_sgd'; $log_table = $prefix . 'user_stock_sgd_log'; $log_data['stock_id'] = 'SGD'; break; case 10: $where['stock_id'] = 'USD'; $table = $prefix . 'user_stock_fund'; $log_table = $prefix . 'user_stock_fund_log'; $log_data['stock_id'] = 'USD'; break; case 11: $where['stock_id'] = 'INR'; $table = $prefix . 'user_stock_option_inr'; $log_table = $prefix . 'user_stock_option_inr_log'; $log_data['stock_id'] = 'INR'; break; case 12: $where['stock_id'] = 'HKD'; $table = $prefix . 'user_stock_hkd'; $log_table = $prefix . 'user_stock_hkd_log'; $log_data['stock_id'] = 'HKD'; break; case 14: $where['stock_id'] = 'GBX'; $table = $prefix . 'user_stock_gbx'; $log_table = $prefix . 'user_stock_gbx_log'; $log_data['stock_id'] = 'GBX'; break; case 15: $where['stock_id'] = 'EUR'; $table = $prefix . 'user_stock_fur'; $log_table = $prefix . 'user_stock_fur_log'; $log_data['stock_id'] = 'EUR'; break; case 16: $where['stock_id'] = 'EUR'; $table = $prefix . 'user_stock_eur'; $log_table = $prefix . 'user_stock_eur_log'; $log_data['stock_id'] = 'EUR'; break; case 17: $where['stock_id'] = 'BRL'; $table = $prefix . 'user_stock_brl'; $log_table = $prefix . 'user_stock_brl_log'; $log_data['stock_id'] = 'BRL'; break; case 18: $where['stock_id'] = 'JPY'; $table = $prefix . 'user_stock_jp'; $log_table = $prefix . 'user_stock_jp_log'; $log_data['stock_id'] = 'JPY'; break; case 19: $where['contract_id'] = 'USD'; $table = $prefix . 'user_forex'; $log_table = $prefix . 'user_forex_log'; $log_data['contract_id'] = 'USD'; break; default: return [ 'status' => 100, 'msg' => '账户类型错误' ]; break; } Db::startTrans(); try { //user_stock USD $account_info = Db::table($table)->where($where)->lock(true)->find(); if (empty($account_info)) { $insert_data = [ 'user_id' => $user_id, 'usable_num' => 0, 'frozen_num' => 0, 'create_time' => date('Y-m-d H:i:s'), 'update_time' => date('Y-m-d H:i:s') ]; if (in_array($account_type, [1, 2, 8,19])) { $insert_data['contract_id'] = $where['contract_id']; } else { $insert_data['stock_id'] = $where['stock_id']; } // 不存在 则新增 Db::table($table)->insert($insert_data); $account_info = Db::table($table)->where($where)->lock(true)->find(); if (empty($account_info)) { Db::rollback(); return [ 'status' => 300, 'msg' => '用户资金账号不存在' ]; } } $last_usable_num = bcadd($account_info['usable_num'], $change_usable_num, 18); $last_frozen_num = bcadd($account_info['frozen_num'], $change_frozen_num, 18); if ($last_usable_num < 0) { Db::rollback(); return [ 'status' => 400, 'msg' => '可用资金不能为负' ]; } if ($change_type == 6) { if ($last_frozen_num < 0 && abs($last_frozen_num) > 0.01) { Db::rollback(); return [ 'status' => 400, 'msg' => '冻结资金不能为负' ]; } elseif (abs($last_frozen_num) < 0.01) { $last_frozen_num = 0; } } else { if ($last_frozen_num < 0) { Db::rollback(); return [ 'status' => 400, 'msg' => '冻结资金不能为负' ]; } } $change_data['usable_num'] = $last_usable_num; $change_data['frozen_num'] = $last_frozen_num; $change_data['update_time'] = date('Y-m-d H:i:s'); $change_bool = Db::table($table)->where($where)->update($change_data); if ($change_bool == 0) { Db::rollback(); return [ 'status' => 100, 'msg' => '账户修改失败' ]; } //echo Db::table($table)->where($where)->getLastSql(); $log_data['user_id'] = $user_id; $log_data['change_type'] = $change_type; $log_data['before_num'] = $account_info['usable_num']; $log_data['change_num'] = $change_usable_num; $log_data['create_time'] = date('Y-m-d H:i:s'); $log_data['update_time'] = date('Y-m-d H:i:s'); if (!empty($order_no)) { $log_data['order_id'] = $order_no; } $log_bool = Db::table($log_table)->insert($log_data); if (!$log_bool) { Db::rollback(); return [ 'status' => 100, 'msg' => '账户流水插入失败' ]; } //后台系统 变更用户余额 //需要录入变更日志 bot_user_balance_change_log if (in_array($change_type, [12, 13]) && $change_log_admin_id > 0 && $rate != 0) { $balance_change_log["user_id"] = $user_id; $balance_change_log["type"] = $account_type; $balance_change_log['before_num'] = bcdiv($account_info['usable_num'], $rate, 18); $balance_change_log["change_num"] = bcdiv($change_usable_num, $rate, 18); $balance_change_log["currency_rate"] = $rate; $balance_change_log["admin_id"] = $change_log_admin_id; $balance_change_log["create_time"] = date('Y-m-d H:i:s'); $balance_log_bool = Db::table('bot_user_balance_change_log')->insert($balance_change_log); if (!$balance_log_bool) { Db::rollback(); return [ 'status' => 100, 'msg' => '上分 - 账户流水插入失败' ]; } } Db::commit(); return [ 'status' => 200, 'msg' => 'ok' ]; } catch (ValidateException|PDOException|\Exception $e) { Db::rollback(); return [ 'status' => 100, 'msg' => $e->getMessage(), 'data'=>[$e->getTrace()] ]; } } public function updateUserAssetNew($user_id,$change_type,$change_usable_num,$change_frozen_num = 0, $order_no = ""){ Db::startTrans(); try{ $account_info = UserMoneyModel::where('user_id',$user_id)->where('stock_id','USD')->lock(true)->find(); if (empty($account_info)) { UserMoneyModel::InsertUserMoneyk([ 'user_id' => $user_id, 'stock_id' => 'USD', 'usable_num' => 0, 'frozen_num' => 0, ]); $account_info = UserMoneyModel::where('user_id', $user_id)->where('stock_id', 'USD')->lock(true)->find(); if (empty($account_info)) { Db::rollback(); return [ 'status' => 300, 'msg' => '用户资金账号不存在' ]; } } $last_usable_num = bcadd($account_info['usable_num'], $change_usable_num, 18); $last_frozen_num = bcadd($account_info['frozen_num'], $change_frozen_num, 18); if ($last_usable_num < 0) { Db::rollback(); return [ 'status' => 400, 'msg' => '可用资金不能为负' ]; } if ($change_type == 6) { if ($last_frozen_num < 0 && abs($last_frozen_num) > 0.01) { Db::rollback(); return [ 'status' => 400, 'msg' => '冻结资金不能为负' ]; } elseif (abs($last_frozen_num) < 0.01) { $last_frozen_num = 0; } } else { if ($last_frozen_num < 0) { Db::rollback(); return [ 'status' => 400, 'msg' => '冻结资金不能为负' ]; } } $res=UserMoneyModel::where('user_id',$user_id)->where('stock_id','USD')->update([ 'usable_num'=>$last_usable_num, 'frozen_num'=>$last_frozen_num, 'update_time'=>date('Y-m-d H:i:s'), ]); if(!$res){ Db::rollback(); return [ 'status' => 400, 'msg' => '资金操作异常' ]; } $log_bool=UserMoneyLogModel::InsertUserBalanceLog([ 'user_id'=>$user_id, 'change_type'=>$change_type, 'stock_id'=>'USD', 'martket_type'=>0, 'before_num'=>$account_info['usable_num'], 'change_num'=>$change_usable_num, 'create_time'=>date('Y-m-d H:i:s'), 'update_time'=>date('Y-m-d H:i:s'), ]); if (!$log_bool) { Db::rollback(); return [ 'status' => 100, 'msg' => '账户流水插入失败' ]; } Db::commit(); return [ 'status' => 200, 'msg' => 'ok' ]; } catch (ValidateException|PDOException|\Exception $e) { Db::rollback(); return [ 'status' => 100, 'msg' => $e->getMessage(), 'data' => [$e->getTrace()] ]; } } // 合约插针缓存 public function initContractHqData() { $now = date('Y-m-d H:i:s'); $list = ContractMarketModel::where('type', 0) ->whereTime('begin_time', '>', $now) ->field('trade_name as selfContractCode,begin_time as BeginTime,step as Step ,end_time as EndTime,max_price as Price') ->order('id', 'desc') ->select(); $rows = []; $redis = $this->getRedis(); if (!$list->isEmpty()) { $rows = $list->toArray(); foreach ($rows as $key => $val) { $keep_decimal = $redis->hget('CONTRACT:LIST:' . $val['selfContractCode'], 'keep_decimal'); $list[$key]['Digits'] = $keep_decimal; } } $reds_key = "contract_hq_setting"; $redis->del($reds_key); $redis->set($reds_key, json_encode($rows)); } // 外汇插针缓存 public function initForexHqData() { $now = date('Y-m-d H:i:s'); $list = ForexMarketModel::where('type', 0) ->whereTime('begin_time', '>', $now) ->field('trade_name as selfContractCode,begin_time as BeginTime,step as Step ,end_time as EndTime,max_price as Price') ->order('id', 'desc') ->select(); $rows = []; $redis = $this->getRedis(); if (!$list->isEmpty()) { $rows = $list->toArray(); foreach ($rows as $key => $val) { $keep_decimal = $redis->hget('FOREX:LIST:' . $val['selfContractCode'], 'keep_decimal'); $list[$key]['Digits'] = $keep_decimal; } } $reds_key = "forex_hq_setting"; $redis->del($reds_key); $redis->set($reds_key, json_encode($rows)); } public function initContractSetting() { $list = ContractSettingModel::getSettingList(); $redis_key = "contract_time_setting"; $redis = $this->getRedis(); $redis->del($redis_key); $redis->set($redis_key, json_encode($list, JSON_NUMERIC_CHECK)); } // 合约自发行情缓存 public function initContractMarketData() { $redis = $this->getRedis(); $now = date('Y-m-d H:i:s'); $list = ContractMarketModel::where('type', 1) ->whereTime('begin_time', '>', $now) ->field('trade_name as selfContractCode,end_time as endTime,max_price as maxPrice') ->order('id', 'desc') ->select(); $rows = []; if (!$list->isEmpty()) { $rows = $list->toArray(); } $key = "contract_market_setting"; $redis->set($key, json_encode($rows)); } public function getBrokerageKey($type) { switch ($type) { case 1: //平仓返佣 $brokerage_key = 'BROKERAGE:SALE:SETTING'; break; case 2: //开仓返佣 $brokerage_key = 'BROKERAGE:BUY:SETTING'; break; default: //注册返佣 $brokerage_key = 'BROKERAGE:REG:SETTING'; break; } return $brokerage_key; } public function getTradeFeeKey($market_type) { switch ($market_type) { case 1: $fee_key = 'TRADE:FEE:DIGITAL'; break; case 2: $fee_key = 'TRADE:FEE:CONTRACT'; break; case 3: $fee_key = 'TRADE:FEE:US_STOCK'; break; case 4: $fee_key = 'TRADE:FEE:IDN_STOCK'; break; case 5: $fee_key = 'TRADE:FEE:MYS_STOCK'; break; case 6: $fee_key = 'TRADE:FEE:THA_STOCK'; break; case 7: $fee_key = 'TRADE:FEE:IN_STOCK'; break; case 8: $fee_key = 'TRADE:FEE:CONTRACT_SEC'; break; case 9: $fee_key = 'TRADE:FEE:SGD_STOCK'; break; case 12: $fee_key = 'TRADE:FEE:HK_STOCK'; break; case 14: $fee_key = 'TRADE:FEE:UK_STOCK'; break; case 15: $fee_key = 'TRADE:FEE:FUR_STOCK'; break; case 16: $fee_key = 'TRADE:FEE:EUR_STOCK'; break; case 17: $fee_key = 'TRADE:FEE:BR_STOCK'; break; case 18: $fee_key = 'TRADE:FEE:JP_STOCK'; break; case 19: $fee_key = 'TRADE:FEE:FOREX'; break; default: $fee_key = ''; break; } return $fee_key; } /** * @param $menus * @param $pid * @param $showParentName * @return array|string */ function getTreeMenu($menus, $pid = 0, $showParentName = false) { $arr = []; if (empty($menus)) { return ''; } if ($showParentName) { for ($i = 0; $i < count($menus); $i++) { $parentId = $menus[$i]['pid']; if ($parentId == '0') { $menus[$i]['parent_name'] = ""; } else { $parent = array_filter($menus, function ($item) use ($parentId) { return $item['id'] == $parentId; }); if ($parent) { $parent = array_values($parent); if ($parent[0]['name']) { $menus[$i]['parent_name'] = $parent[0]['name']; } else if ($parent[0]['title']) { $menus[$i]['parent_name'] = $parent[0]['title']; } } } } } foreach ($menus as $key => $value) { if ($value['pid'] == $pid) { $children = $this->getTreeMenu($menus, $value['id']); if (!empty($children)) { $value['children'] = $children; } //pid=0为顶级菜单,前端不显示 if ($pid == '0') { unset($value['pid']); } $arr[] = $value; } } return $arr; } function getSortTreeMenu($menus, $sort = 'order', $pid = 0) { $menuList = getTreeMenu($menus, $pid = 0); foreach ($menuList as $key => $value) { if (!empty($value['children'])) { $sort = array_column($value['children'], $sort); array_multisort($sort, SORT_DESC, $value['children']); } } return $menuList; } // 给 go 行情 发送 新增的股票 public function sendNewStockToGo($country, $newStockCode, $oldStockCode, $stockName, $tape, $price = 0, $isReal = 1, $intro = '', $source = 0, $numericCode = 0) { try { switch ($country) { case 'India': case 'Thailand': case 'US': case 'HongKong': $price = bcadd($price, 0, 2); break; case 'Indonesia': $price = bcadd($price, 0, 0); break; case 'Malaysia': $price = bcadd($price, 0, 3); break; default: $price = bcadd($price, 0, 2); } $responseArr = [ 'old_ticker' => $oldStockCode, //新的股票代码 'new_ticker' => $newStockCode, //旧的股票代码 (新增的话 ,两个字段都是一样的值) 'token' => 'asdfsnl123jlknl3nksdf32345ln98sdfsfs8891232nsdfsdfsdfsdxcfvbhnfgh', 'locale' => $country, //国家 'yesterday_close' => $price, //价格 'name' => $stockName, //股票name 'primary_exchange' => $tape, //交易所 'is_real' => $isReal, //1正式股票 2测试股票 'intro' => $intro //股票简介 ]; if ($source > 0) { $responseArr['source'] = $source; } if ($country == 'Malaysia') { $responseArr['numeric_code'] = $numericCode . ''; } $client = new Client(); $url = env('QUOTE.BASE_URL') . '/spots/list/new/add'; $response = $client->request("POST", $url, [ 'json' => $responseArr ]); $body = $response->getBody()->getContents(); $res = json_decode($body, true); $responseArr['url'] = $url; trace('---给行情推送数据---' . json_encode([$res, $responseArr]), 'error'); if (isset($res['code']) && $res['code'] == 200) { return true; } trace('---给行情推送数据异常---' . json_encode([$res, $responseArr]), 'error'); return false; } catch (\Exception $exception) { trace('---给行情推送数据异常1---' . $exception->getMessage(), 'error'); } catch (GuzzleException $e) { trace('---给行情推送数据异常2---' . $e->getMessage(), 'error'); } return false; } // 给 go 行情 发送股票小数位数 public function sendDecimalToGo($country, $stockCode, int $decimal) { try { $client = new Client(); $url = env('QUOTE.BASE_URL') . '/spots/update/keep'; $response = $client->request("POST", $url, [ 'json' => [ 'currency' => $country, 'stockCode' => $stockCode, 'keepDecimal' => $decimal, ], ]); $body = $response->getBody()->getContents(); $res = json_decode($body, true); if (isset($res['code']) && $res['code'] == 200) { return true; } Log::error('给行情推送数据异常 ' . json_encode([$res])); return false; } catch (\Exception $exception) { Log::error('给行情推送数据异常1 ' . $exception->getMessage()); } catch (GuzzleException $e) { Log::error('给行情推送数据异常2 ' . $e->getMessage()); } return false; } // 给 go 交易 发送股票小数位数 // $preStockId $marketType $stockCode public function sendStockToGo($preStockId, $stockCode, $marketType) { try { $marketType = $marketType + 0; // 转成数字 $preStockId = $preStockId . ''; $client = new Client(); $url = env('QUOTE.DEAL_BASE_URL') . '/order_sharepre/share_pre_trade'; $response = $client->request("POST", $url, [ 'json' => [ 'code' => $stockCode, 'id' => $preStockId, 'stock' => $marketType, ], ]); $body = $response->getBody()->getContents(); $res = json_decode($body, true); trace('---给交易推送数据---' . json_encode([$res, [ 'url' => $url, 'code' => $stockCode, 'id' => $preStockId, 'stock' => $marketType,]]), 'error'); if (isset($res['code']) && $res['code'] == 200) { return true; } return false; } catch (\Exception $exception) { trace('---通知交易异常1---' . $exception->getMessage(), 'error'); } catch (GuzzleException $e) { trace('---通知交易异常1---' . $e->getMessage(), 'error'); } return false; } public function sendStockToTrade($order_no, $stockCode, $marketType) { try { $marketType = $marketType + 0; // 转成数字 $order_no = $order_no . ''; $client = new Client(); $url = env('QUOTE.DEAL_BASE_URL') . '/order_sharepre/share_pre_trade_by_order_no'; $response = $client->request("POST", $url, [ 'json' => [ 'code' => $stockCode, 'id' => $order_no, 'stock' => $marketType, ], ]); $body = $response->getBody()->getContents(); $res = json_decode($body, true); trace('---单个订单给交易推送数据---' . json_encode([$res, [ 'url' => $url, 'code' => $stockCode, 'id' => $order_no, 'stock' => $marketType,]]), 'error'); if (isset($res['code']) && $res['code'] == 200) { return true; } return false; } catch (\Exception $exception) { trace('---通知交易异常1---' . $exception->getMessage(), 'error'); } catch (GuzzleException $e) { trace('---通知交易异常1---' . $e->getMessage(), 'error'); } return false; } public function sendUpdateCodeGo($newCode, $oldCode, $marketType) { try { $marketType = $marketType + 0; // 转成数字 $client = new Client(); $url = env('QUOTE.DEAL_BASE_URL') . '/order_sharepre/update_stock_id'; $response = $client->request("POST", $url, [ 'json' => [ 'code' => $newCode, 'codeOld' => $oldCode, 'stock' => $marketType, ], ]); $body = $response->getBody()->getContents(); $res = json_decode($body, true); Log::info('给交易推送数据 ' . json_encode([$res, [ 'url' => $url, 'code' => $newCode, 'codeOld' => $oldCode, 'stock' => $marketType,]])); if (isset($res['code']) && $res['code'] == 200) { return true; } return false; } catch (\Exception $exception) { Log::error('给行情推送数据异常1 ' . $exception->getMessage()); } catch (GuzzleException $e) { Log::error('给行情推送数据异常2 ' . $e->getMessage()); } return false; } /** * 给go推送股票指数代码 * @param $code * @param $country * @param $sort * @param $status * @return bool */ public function sendStockIndexToGo($code, $country, $sort, $status) { try { $client = new Client(); $url = env('QUOTE.BASE_URL') . '/spots/index/list/new/add'; $response = $client->request("POST", $url, [ 'json' => [ 'ticker' => $code, 'locale' => $country, 'state' => $status, 'sort' => $sort, ], ]); $body = $response->getBody()->getContents(); $res = json_decode($body, true); Log::info('给交易推送数据 ' . json_encode([$res, [ 'url' => $url, 'ticker' => $code, 'locale' => $country, 'state' => $status, 'sort' => $sort, ]])); if (isset($res['code']) && $res['code'] == 200) { return true; } return false; } catch (\Exception $exception) { Log::error('给行情推送股票指数数据异常1 ' . $exception->getMessage()); } catch (GuzzleException $e) { Log::error('给行情推送股票指数数据异常2 ' . $e->getMessage()); } return false; } }