diff --git a/admin/layout.php b/admin/layout.php index f0a1bc6..be95a47 100644 --- a/admin/layout.php +++ b/admin/layout.php @@ -3,8 +3,8 @@ require_once __DIR__ . '/../db/config.php'; require_once __DIR__ . '/../includes/lang.php'; if (session_status() === PHP_SESSION_NONE) session_start(); -// Force admin to be Chinese -$lang = 'zh'; +// Use site default language +$lang = $_SESSION['lang'] ?? 'en'; // Admin check $admin = null; diff --git a/admin/login.php b/admin/login.php index df4b4d4..263fd21 100644 --- a/admin/login.php +++ b/admin/login.php @@ -21,31 +21,31 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { $username = $_POST['username'] ?? ''; $password = $_POST['password'] ?? ''; - if (empty($username) || empty($password)) { - $error = '请输入账号和密码'; - } else { - $stmt = db()->prepare("SELECT * FROM admins WHERE username = ?"); - $stmt->execute([$username]); - $admin = $stmt->fetch(); - - if ($admin && password_verify($password, $admin['password_hash'])) { - $_SESSION['admin_id'] = $admin['id']; - $_SESSION['admin_username'] = $admin['username']; - $_SESSION['admin_role'] = $admin['role']; - header('Location: /admin/index.php'); - exit; + if (empty($username) || empty($password)) { + $error = __("fill_full_info"); } else { - $error = '管理员账号或密码错误'; + $stmt = db()->prepare("SELECT * FROM admins WHERE username = ?"); + $stmt->execute([$username]); + $admin = $stmt->fetch(); + + if ($admin && password_verify($password, $admin["password_hash"])) { + $_SESSION["admin_id"] = $admin["id"]; + $_SESSION["admin_username"] = $admin["username"]; + $_SESSION["admin_role"] = $admin["role"]; + header("Location: /admin/index.php"); + exit; + } else { + $error = __("invalid_account_pwd"); + } } } -} ?> - + - 管理员登录 - <?= $site_name ?> + <?= __("login") ?> - <?= $site_name ?> @@ -90,7 +90,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { -
后台管理系统
+
@@ -101,14 +101,14 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
- +
- +
- +
diff --git a/api/swap.php b/api/swap.php new file mode 100644 index 0000000..ae15d41 --- /dev/null +++ b/api/swap.php @@ -0,0 +1,126 @@ + false, "error" => __("unauthorized")]); + exit; +} + +$from_coin = $_POST["from_coin"] ?? ""; +$to_coin = $_POST["to_coin"] ?? ""; +$amount = (float)($_POST["amount"] ?? 0); + +if ($amount <= 0 || !$from_coin || !$to_coin || $from_coin === $to_coin) { + echo json_encode(["success" => false, "error" => __("invalid_amount")]); + exit; +} + +/** + * Robust price fetching using OKX as primary and CoinCap as fallback + */ +function getPrice($symbol) { + if ($symbol === "USDT") return 1.0; + + // Primary: OKX + $pair = strtoupper($symbol) . "-USDT"; + $url = "https://www.okx.com/api/v5/market/ticker?instId=" . $pair; + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_TIMEOUT, 5); + curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0"); // OKX might require UA + $response = curl_exec($ch); + curl_close($ch); + + if ($response) { + $data = json_decode($response, true); + if (isset($data["data"][0]["last"])) { + return (float)$data["data"][0]["last"]; + } + } + + // Fallback: CoinCap + $slugMap = [ + "BTC" => "bitcoin", "ETH" => "ethereum", "BNB" => "binance-coin", + "SOL" => "solana", "XRP" => "ripple", "ADA" => "cardano", + "DOGE" => "dogecoin", "DOT" => "polkadot", "MATIC" => "polygon", + "AVAX" => "avalanche", "LINK" => "chainlink", "SHIB" => "shiba-inu", + "TRX" => "tron", "BCH" => "bitcoin-cash", "LTC" => "litecoin", + "UNI" => "uniswap" + ]; + $slug = $slugMap[strtoupper($symbol)] ?? strtolower($symbol); + $url = "https://api.coincap.io/v2/assets/" . $slug; + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_TIMEOUT, 5); + $response = curl_exec($ch); + curl_close($ch); + + if ($response) { + $data = json_decode($response, true); + if (isset($data["data"]["priceUsd"])) { + return (float)$data["data"]["priceUsd"]; + } + } + + return null; +} + +$from_price = getPrice($from_coin); +$to_price = getPrice($to_coin); + +if ($from_price === null || $to_price === null) { + echo json_encode(["success" => false, "error" => "Failed to fetch exchange rate (Provider issue)"]); + exit; +} + +$rate = $from_price / $to_price; +$target_amount = $amount * $rate; + +$db->beginTransaction(); +try { + // Check balance of from_coin + $stmt = $db->prepare("SELECT available FROM user_balances WHERE user_id = ? AND symbol = ?"); + $stmt->execute([$user_id, $from_coin]); + $from_balance = $stmt->fetchColumn() ?: 0; + + if ($from_balance < $amount) { + throw new Exception(__("insufficient_balance")); + } + + // Deduct from_coin + $db->prepare("UPDATE user_balances SET available = available - ? WHERE user_id = ? AND symbol = ?") + ->execute([$amount, $user_id, $from_coin]); + + // Add to_coin + $stmt = $db->prepare("SELECT id FROM user_balances WHERE user_id = ? AND symbol = ?"); + $stmt->execute([$user_id, $to_coin]); + if (!$stmt->fetch()) { + $db->prepare("INSERT INTO user_balances (user_id, symbol, available) VALUES (?, ?, 0)") + ->execute([$user_id, $to_coin]); + } + $db->prepare("UPDATE user_balances SET available = available + ? WHERE user_id = ? AND symbol = ?") + ->execute([$target_amount, $user_id, $to_coin]); + + // Record exchange + $stmt = $db->prepare("INSERT INTO exchange_records (user_id, from_symbol, to_symbol, from_amount, to_amount, rate) VALUES (?, ?, ?, ?, ?, ?)"); + $stmt->execute([$user_id, $from_coin, $to_coin, $amount, $target_amount, $rate]); + + // Record transaction + $db->prepare("INSERT INTO transactions (user_id, type, amount, symbol, status) VALUES (?, 'swap', ?, ?, 'completed')") + ->execute([$user_id, $amount, $from_coin]); + + $db->commit(); + echo json_encode(["success" => true, "target_amount" => $target_amount]); +} catch (Exception $e) { + $db->rollBack(); + echo json_encode(["success" => false, "error" => $e->getMessage()]); +} diff --git a/auth/login.php b/auth/login.php index e461769..b18c333 100644 --- a/auth/login.php +++ b/auth/login.php @@ -69,10 +69,14 @@ include __DIR__ . '/../includes/header.php'; - +
+ + +
-
- +
+ +
diff --git a/includes/header.php b/includes/header.php index 8ca2981..fc0b882 100644 --- a/includes/header.php +++ b/includes/header.php @@ -197,19 +197,59 @@ if (isset($_SESSION['user_id'])) { font-size: 14px; text-decoration: none; color: var(--text); - padding: 10px 20px; - border-radius: 6px; + padding: 8px 16px; + border-radius: 8px; font-weight: 600; + transition: all 0.2s; } .btn-login:hover { - background: #222; + background: rgba(255,255,255,0.05); } .btn-register { background: var(--primary); color: #fff !important; + box-shadow: 0 4px 12px rgba(0, 98, 255, 0.2); } .btn-register:hover { background: #0056e0; + transform: translateY(-1px); + box-shadow: 0 6px 16px rgba(0, 98, 255, 0.3); + } + @media (max-width: 576px) { + .header-right { + gap: 8px; + } + .auth-btns { + background: rgba(255,255,255,0.08); + padding: 3px; + border-radius: 12px; + display: flex; + align-items: center; + gap: 2px; + border: 1px solid rgba(255,255,255,0.1); + } + .auth-btns a { + padding: 7px 14px; + font-size: 13px; + border-radius: 10px; + font-weight: 700; + transition: all 0.3s ease; + } + .btn-login { + background: transparent; + color: rgba(255,255,255,0.8) !important; + } + .btn-login:active { + background: rgba(255,255,255,0.1); + } + .btn-register { + background: var(--primary); + color: #fff !important; + box-shadow: 0 4px 12px rgba(0, 98, 255, 0.3); + } + .lang-switcher span { + display: none; + } } /* User Dropdown */ diff --git a/includes/lang.php b/includes/lang.php index c60a315..3e0fb23 100644 --- a/includes/lang.php +++ b/includes/lang.php @@ -1,7 +1,7 @@ '确 认', 'buy' => '买', 'sell' => '卖', + 'confirm_swap' => '确认兑换', + 'cancel' => '取消', 'approx' => '约等于', 'cookie_policy_title' => '隐私政策', 'cookie_policy_content' => '

1. 什么是隐私数据?

隐私数据是您访问网站时存储在您的计算机或移动设备上的信息。它们广泛用于使网站运行或更高效地运行。

', @@ -576,6 +578,8 @@ $translations = [ 'confirm' => 'Confirm', 'buy' => 'Buy', 'sell' => 'Sell', + 'confirm_swap' => 'Confirm Swap', + 'cancel' => 'Cancel', 'approx' => 'Approx.', 'cookie_policy_title' => 'Cookie Policy', 'cookie_policy_content' => '

1. What are Cookies?

Cookies are small text files stored on your device when you visit a website. They are used to make websites work efficiently.

', diff --git a/swap.php b/swap.php index 2ecfba9..b70df8c 100644 --- a/swap.php +++ b/swap.php @@ -1,13 +1,14 @@ prepare("SELECT available FROM user_balances WHERE user_id = ? AND symbol = 'USDT'"); - $stmt->execute([$user['id']]); - $bal = $stmt->fetch(); - $usdt_balance = $bal['available'] ?? 0; + $stmt = db()->prepare("SELECT symbol, available FROM user_balances WHERE user_id = ?"); + $stmt->execute([$user["id"]]); + while ($row = $stmt->fetch()) { + $balances[$row["symbol"]] = (float)$row["available"]; + } } ?>
@@ -15,28 +16,28 @@ if ($user) {

- +

- - : + + : 0.00