query("SELECT symbol FROM cryptocurrencies WHERE is_active = 1"); $symbols = $stmt->fetchAll(PDO::FETCH_COLUMN); } catch (Exception $e) { $symbols = ['BTCUSDT', 'ETHUSDT', 'BNBUSDT', 'SOLUSDT', 'DOGEUSDT']; } if (empty($symbols)) $symbols = ['BTCUSDT']; // Use Binance 24hr ticker for comprehensive data $symbols_json = json_encode($symbols); $url = "https://api.binance.com/api/v3/ticker/24hr?symbols=" . urlencode($symbols_json); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_TIMEOUT, 10); curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'); // Disable SSL verification if needed for some environments, but prefer keeping it // curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); $response = curl_exec($ch); $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); $prices = []; if ($http_code == 200 && $response) { $data = json_decode($response, true); if (is_array($data)) { foreach ($data as $item) { if (isset($item['symbol'])) { $prices[$item['symbol']] = [ 'price' => $item['lastPrice'], 'change' => $item['priceChangePercent'], 'high' => $item['highPrice'], 'low' => $item['lowPrice'], 'volume' => $item['quoteVolume'], 'ts' => time() ]; } } } } // Fallback: If 24hr fails, try simpler price-only endpoint if (empty($prices)) { $url_simple = "https://api.binance.com/api/v3/ticker/price"; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url_simple); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_TIMEOUT, 5); $resp_simple = curl_exec($ch); curl_close($ch); if ($resp_simple) { $data_simple = json_decode($resp_simple, true); if (is_array($data_simple)) { foreach ($data_simple as $item) { if (in_array($item['symbol'], $symbols)) { $prices[$item['symbol']] = [ 'price' => $item['price'], 'change' => '0.00', 'high' => $item['price'], 'low' => $item['price'], 'volume' => '0', 'ts' => time() ]; } } } } } if (!empty($prices)) { // Only update file if we have new data @file_put_contents($cache_file, json_encode($prices)); } else if (file_exists($cache_file)) { // Last resort: return expired cache return json_decode(file_get_contents($cache_file), true); } return $prices; } if ($action === 'market_data') { $real_prices = get_real_prices(); try { $stmt = db()->query("SELECT * FROM cryptocurrencies WHERE is_active = 1 ORDER BY id ASC"); $coins = $stmt->fetchAll(); } catch (Exception $e) { $coins = []; } $updated_coins = []; foreach ($coins as $coin) { $symbol = $coin['symbol']; if (isset($real_prices[$symbol])) { $coin['price'] = (string)$real_prices[$symbol]['price']; // Keep as string for precision $coin['change'] = (float)$real_prices[$symbol]['change']; $coin['high'] = (string)$real_prices[$symbol]['high']; $coin['low'] = (string)$real_prices[$symbol]['low']; $coin['volume'] = (float)$real_prices[$symbol]['volume']; if ($coin['manual_price'] > 0) { $coin['price'] = (string)$coin['manual_price']; } // Sync to DB occasionally (logic can be improved, but this is current) $upd = db()->prepare("UPDATE cryptocurrencies SET current_price = ?, change_24h = ? WHERE id = ?"); $upd->execute([$coin['price'], $coin['change'], $coin['id']]); } else { $coin['price'] = (string)$coin['current_price']; $coin['change'] = (float)$coin['change_24h']; $coin['high'] = (string)($coin['current_price'] * 1.01); $coin['low'] = (string)($coin['current_price'] * 0.99); $coin['volume'] = 0; } $updated_coins[] = $coin; } header('Content-Type: application/json'); echo json_encode($updated_coins); exit; } if ($action === 'submit_order') { check_auth(); $data = json_decode(file_get_contents('php://input'), true); if (!$data) { echo json_encode(['status' => 'error', 'message' => '无效请求数据']); exit; } $user_id = $_SESSION['user_id']; $account = get_account($user_id); $symbol = $data['symbol'] ?? 'BTCUSDT'; $side = $data['side'] ?? 'BUY'; $trade_type = strtoupper($data['trade_type'] ?? 'SPOT'); $amount = (float)($data['amount'] ?? 0); $leverage = (int)($data['leverage'] ?? 1); if ($amount <= 0) { echo json_encode(['status' => 'error', 'message' => '请输入有效数量']); exit; } $real_prices = get_real_prices(); $stmt = db()->prepare("SELECT * FROM cryptocurrencies WHERE symbol = ?"); $stmt->execute([$symbol]); $coin = $stmt->fetch(); if (!$coin) { echo json_encode(['status' => 'error', 'message' => '不支持该币种']); exit; } if ($coin['manual_price'] > 0) { $current_price = (float)$coin['manual_price']; } elseif (isset($real_prices[$symbol])) { $current_price = (float)$real_prices[$symbol]['price']; } else { $current_price = (float)$coin['current_price']; } if ($current_price <= 0) { echo json_encode(['status' => 'error', 'message' => '价格获取失败,请重试']); exit; } try { $db = db(); $db->beginTransaction(); if ($trade_type === 'SPOT') { if ($side === 'BUY') { $total_cost = $amount * $current_price; if ($account['balance'] < $total_cost) { throw new Exception('余额不足 (需要 ' . number_format($total_cost, 2) . ' USDT)'); } $stmt = $db->prepare("UPDATE accounts SET balance = balance - ? WHERE id = ?"); $stmt->execute([$total_cost, $account['id']]); $currency = str_replace('USDT', '', $symbol); $stmt = $db->prepare("INSERT INTO assets (account_id, currency, balance) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE balance = balance + ?"); $stmt->execute([$account['id'], $currency, $amount, $amount]); } else { // SELL $currency = str_replace('USDT', '', $symbol); $stmt = $db->prepare("SELECT balance FROM assets WHERE account_id = ? AND currency = ?"); $stmt->execute([$account['id'], $currency]); $asset = $stmt->fetch(); if (!$asset || $asset['balance'] < $amount) { throw new Exception('资产余额不足'); } $stmt = $db->prepare("UPDATE assets SET balance = balance - ? WHERE account_id = ? AND currency = ?"); $stmt->execute([$amount, $account['id'], $currency]); $total_gain = $amount * $current_price; $stmt = $db->prepare("UPDATE accounts SET balance = balance + ? WHERE id = ?"); $stmt->execute([$total_gain, $account['id']]); } $stmt = $db->prepare("INSERT INTO orders (account_id, symbol, trade_type, side, order_type, price, amount, total_usdt, status) VALUES (?, ?, 'SPOT', ?, 'MARKET', ?, ?, ?, 'FILLED')"); $stmt->execute([$account['id'], $symbol, $side, $current_price, $amount, $amount * $current_price]); } else if ($trade_type === 'CONTRACT') { $contract_value = 100; $total_value = $amount * $contract_value; $margin = $total_value / $leverage; if ($account['balance'] < $margin) { throw new Exception('保证金不足 (需要 ' . number_format($margin, 2) . ' USDT)'); } $stmt = $db->prepare("UPDATE accounts SET balance = balance - ? WHERE id = ?"); $stmt->execute([$margin, $account['id']]); $stmt = $db->prepare("INSERT INTO positions (account_id, symbol, side, leverage, entry_price, lots, margin) VALUES (?, ?, ?, ?, ?, ?, ?)"); $stmt->execute([$account['id'], $symbol, ($side === 'BUY' ? 'LONG' : 'SHORT'), $leverage, $current_price, $amount, $margin]); $stmt = $db->prepare("INSERT INTO orders (account_id, symbol, trade_type, side, order_type, price, amount, leverage, status) VALUES (?, ?, 'CONTRACT', ?, 'MARKET', ?, ?, ?, 'FILLED')"); $stmt->execute([$account['id'], $symbol, $side, $current_price, $amount, $leverage]); } $db->commit(); echo json_encode(['status' => 'success', 'message' => '交易成功']); } catch (Exception $e) { $db->rollBack(); echo json_encode(['status' => 'error', 'message' => $e->getMessage()]); } exit; } if ($action === 'positions') { check_auth(); $user_id = $_SESSION['user_id']; $account = get_account($user_id); $stmt = db()->prepare("SELECT * FROM positions WHERE account_id = ? AND is_active = 1"); $stmt->execute([$account['id']]); $positions = $stmt->fetchAll(); $real_prices = get_real_prices(); foreach ($positions as &$pos) { $symbol = $pos['symbol']; $stmt = db()->prepare("SELECT manual_price, current_price FROM cryptocurrencies WHERE symbol = ?"); $stmt->execute([$symbol]); $coin = $stmt->fetch(); if ($coin && $coin['manual_price'] > 0) { $current_price = (float)$coin['manual_price']; } elseif (isset($real_prices[$symbol])) { $current_price = (float)$real_prices[$symbol]['price']; } else { $current_price = (float)$pos['entry_price']; } $pos['current_price'] = $current_price; if ($pos['side'] === 'LONG') { $pos['pnl'] = (($current_price - $pos['entry_price']) / $pos['entry_price']) * $pos['margin'] * $pos['leverage']; } else { $pos['pnl'] = (($pos['entry_price'] - $current_price) / $pos['entry_price']) * $pos['margin'] * $pos['leverage']; } if ($account['win_loss_control'] == 1 && $pos['pnl'] < 0) { $pos['pnl'] = abs($pos['pnl']) * 0.2; } else if ($account['win_loss_control'] == -1 && $pos['pnl'] > 0) { $pos['pnl'] = -abs($pos['pnl']) * 1.5; } } echo json_encode($positions); exit; } if ($action === 'close_position') { check_auth(); $data = json_decode(file_get_contents('php://input'), true); $pos_id = $data['id'] ?? 0; $user_id = $_SESSION['user_id']; $account = get_account($user_id); try { $db = db(); $db->beginTransaction(); $stmt = $db->prepare("SELECT * FROM positions WHERE id = ? AND account_id = ? AND is_active = 1"); $stmt->execute([$pos_id, $account['id']]); $pos = $stmt->fetch(); if (!$pos) throw new Exception('仓位不存在'); $symbol = $pos['symbol']; $real_prices = get_real_prices(); $stmt = db()->prepare("SELECT manual_price, current_price FROM cryptocurrencies WHERE symbol = ?"); $stmt->execute([$symbol]); $coin = $stmt->fetch(); if ($coin && $coin['manual_price'] > 0) { $current_price = (float)$coin['manual_price']; } elseif (isset($real_prices[$symbol])) { $current_price = (float)$real_prices[$symbol]['price']; } else { $current_price = (float)$pos['entry_price']; } if ($pos['side'] === 'LONG') { $pnl = (($current_price - $pos['entry_price']) / $pos['entry_price']) * $pos['margin'] * $pos['leverage']; } else { $pnl = (($pos['entry_price'] - $current_price) / $pos['entry_price']) * $pos['margin'] * $pos['leverage']; } if ($account['win_loss_control'] == 1) { if ($pnl < 0) $pnl = abs($pnl) * 0.1; } else if ($account['win_loss_control'] == -1) { if ($pnl > 0) $pnl = -abs($pnl) * 1.2; } $payout = $pos['margin'] + $pnl; if ($payout < 0) $payout = 0; $stmt = $db->prepare("UPDATE accounts SET balance = balance + ? WHERE id = ?"); $stmt->execute([$payout, $account['id']]); $stmt = $db->prepare("UPDATE positions SET is_active = 0 WHERE id = ?"); $stmt->execute([$pos_id]); $db->commit(); echo json_encode(['status' => 'success', 'message' => '平仓成功']); } catch (Exception $e) { $db->rollBack(); echo json_encode(['status' => 'error', 'message' => $e->getMessage()]); } exit; } ?>