query("SELECT setting_key, setting_value FROM settings")->fetchAll(PDO::FETCH_KEY_PAIR); foreach ($settings as $k => $v) { if (strpos($k, 'lubansms_apikey') !== false) { $db_apikey = trim($v); break; } } } catch (Exception $e) { // Log error } $api = new LubanSMS($db_apikey); $action = $_GET['action'] ?? ''; header('Content-Type: application/json; charset=utf-8'); // Basic Auth check if (!isset($_SESSION['user_id']) && $action !== 'login') { echo json_encode(['code' => 401, 'msg' => '未登录或登录已过期']); exit; } function check_trc20_payment($address, $target_amount, $order_time) { if (!$address || $address == 'TEm1B...TRC20_ADDRESS_HERE') return false; // TronScan API to check transactions $url = "https://apilist.tronscan.org/api/token_trc20/transfers?limit=20&start=0&direction=1&address=" . urlencode($address); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_TIMEOUT, 15); 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'); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); $response = curl_exec($ch); curl_close($ch); if (!$response) return false; $data = json_decode($response, true); if (!isset($data['token_transfers'])) return false; foreach ($data['token_transfers'] as $tx) { if ($tx['symbol'] !== 'USDT') continue; $amount = (float)$tx['quant'] / pow(10, $tx['tokenInfo']['tokenDecimal']); $tx_time = (int)($tx['block_ts'] / 1000); $order_ts = strtotime($order_time); if (abs($amount - $target_amount) < 0.01 && $tx_time > $order_ts) { return $tx['transaction_id']; } } return false; } try { switch ($action) { case 'get_balance': $stmt = $pdo->prepare("SELECT balance FROM users WHERE id = ?"); $stmt->execute([$_SESSION['user_id']]); $balance = $stmt->fetchColumn(); echo json_encode(['code' => 0, 'balance' => number_format((float)$balance, 2)]); break; case 'get_countries': if (!$db_apikey) { echo json_encode(['code' => 500, 'msg' => '加载失败: API Key not configured in DB (Debug: key is null)'], JSON_UNESCAPED_UNICODE); break; } $res = $api->getCountries(); if ($res && (int)($res['code'] ?? -1) === 0) { $data = $res['msg'] ?? $res['data'] ?? []; echo json_encode(['code' => 0, 'data' => $data], JSON_UNESCAPED_UNICODE); } else { echo json_encode($res ?: ['code' => 500, 'msg' => 'API接口响应异常'], JSON_UNESCAPED_UNICODE); } break; case 'get_services': if (!$db_apikey) { echo json_encode(['code' => 500, 'msg' => '加载行情失败: API Key not configured in DB'], JSON_UNESCAPED_UNICODE); break; } $country = $_GET['country'] ?? ''; $service = $_GET['service'] ?? ''; $res = $api->getServices($country, $service); if ($res && (int)($res['code'] ?? -1) === 0) { $data = $res['msg'] ?? $res['data'] ?? []; if (!is_array($data)) $data = []; foreach ($data as &$item) { if (isset($item['cost'])) { $item['cost'] = round((float)$item['cost'] * PRICE_MULTIPLIER, 2); } } echo json_encode(['code' => 0, 'data' => $data], JSON_UNESCAPED_UNICODE); } else { echo json_encode($res ?: ['code' => 500, 'msg' => '获取项目列表失败'], JSON_UNESCAPED_UNICODE); } break; case 'get_number': if (!$db_apikey) { echo json_encode(['code' => 500, 'msg' => 'API Key not configured in DB'], JSON_UNESCAPED_UNICODE); break; } $service_id = $_GET['service_id'] ?? ''; $country_name = $_GET['country_name'] ?? '未知国家'; $service_name = $_GET['service_name'] ?? '未知项目'; $price = (float)($_GET['price'] ?? 0); if (!$service_id) { echo json_encode(['code' => 400, 'msg' => 'Service ID is required']); break; } $stmt = $pdo->prepare("SELECT balance FROM users WHERE id = ?"); $stmt->execute([$_SESSION['user_id']]); $balance = (float)$stmt->fetchColumn(); if ($balance < $price) { echo json_encode(['code' => 400, 'msg' => '余额不足,请先充值']); break; } $res = $api->getNumber($service_id); if ($res && (int)($res['code'] ?? -1) === 0) { $pdo->beginTransaction(); try { $stmt = $pdo->prepare("UPDATE users SET balance = balance - ? WHERE id = ?"); $stmt->execute([$price, $_SESSION['user_id']]); $stmt = $pdo->prepare("INSERT INTO sms_orders (user_id, request_id, number, service_name, country_name, cost, status, expire_at) VALUES (?, ?, ?, ?, ?, ?, 'pending', DATE_ADD(NOW(), INTERVAL 10 MINUTE))"); $stmt->execute([$_SESSION['user_id'], $res['request_id'], $res['number'], $service_name, $country_name, $price]); $pdo->commit(); echo json_encode($res, JSON_UNESCAPED_UNICODE); } catch (Exception $e) { $pdo->rollBack(); echo json_encode(['code' => 500, 'msg' => '数据库事务错误'], JSON_UNESCAPED_UNICODE); } } else { echo json_encode($res ?: ['code' => 500, 'msg' => 'API获取号码失败'], JSON_UNESCAPED_UNICODE); } break; case 'check_sms': $request_id = $_GET['request_id'] ?? ''; if (!$request_id) { echo json_encode(['code' => 400, 'msg' => 'Request ID is required']); break; } $res = $api->getSms($request_id); if ($res && (int)($res['code'] ?? -1) === 0 && (string)($res['msg'] ?? '') === 'success') { $stmt = $pdo->prepare("UPDATE sms_orders SET sms_content = ?, status = 'received' WHERE request_id = ?"); $stmt->execute([$res['sms_code'], $request_id]); } echo json_encode($res ?: ['code' => 500, 'msg' => 'API Error'], JSON_UNESCAPED_UNICODE); break; case 'release_number': $request_id = $_GET['request_id'] ?? ''; $stmt = $pdo->prepare("SELECT created_at, status FROM sms_orders WHERE request_id = ? AND user_id = ?"); $stmt->execute([$request_id, $_SESSION['user_id']]); $order = $stmt->fetch(); if (!$order) { echo json_encode(['code' => 404, 'msg' => '未找到该订单']); break; } if ($order['status'] !== 'pending') { echo json_encode(['code' => 400, 'msg' => '订单状态不符合释放条件']); break; } $createdAt = strtotime($order['created_at']); if (time() - $createdAt < 120) { echo json_encode(['code' => 400, 'msg' => '获取号码不足2分钟,暂时无法手动释放。']); break; } $res = $api->setStatus($request_id, 'reject'); if ($res && (int)($res['code'] ?? -1) === 0) { $stmt = $pdo->prepare("UPDATE sms_orders SET status = 'canceled' WHERE request_id = ?"); $stmt->execute([$request_id]); } echo json_encode($res ?: ['code' => 500, 'msg' => 'API释放失败'], JSON_UNESCAPED_UNICODE); break; case 'get_active_orders': // Auto expire old orders $stmt = $pdo->prepare("UPDATE sms_orders SET status = 'expired' WHERE status = 'pending' AND expire_at < NOW()"); $stmt->execute(); $stmt = $pdo->prepare("SELECT * FROM sms_orders WHERE user_id = ? AND status = 'pending' ORDER BY created_at DESC"); $stmt->execute([$_SESSION['user_id']]); echo json_encode(['code' => 0, 'data' => $stmt->fetchAll()], JSON_UNESCAPED_UNICODE); break; case 'create_recharge': $amount = (float)($_POST['amount'] ?? 0); if ($amount < 10) { echo json_encode(['code' => 400, 'msg' => '最低充值金额为 10 USDT']); break; } $base = floor($amount); $random_decimal = rand(1, 99) / 100; $final_amount = $base + $random_decimal; $stmt = $pdo->prepare("INSERT INTO recharges (user_id, amount, txid, status) VALUES (?, ?, 'Auto-Detect', 'pending')"); $stmt->execute([$_SESSION['user_id'], $final_amount]); echo json_encode(['code' => 0, 'recharge_id' => $pdo->lastInsertId(), 'amount' => $final_amount], JSON_UNESCAPED_UNICODE); break; case 'check_recharge_status': $recharge_id = $_GET['recharge_id'] ?? ''; if (!$recharge_id) { echo json_encode(['code' => 400, 'msg' => 'Recharge ID is required']); break; } $stmt = $pdo->prepare("SELECT * FROM recharges WHERE id = ? AND user_id = ?"); $stmt->execute([$recharge_id, $_SESSION['user_id']]); $recharge = $stmt->fetch(); if (!$recharge) { echo json_encode(['code' => 404, 'msg' => '未找到充值订单']); break; } if ($recharge['status'] === 'completed') { echo json_encode(['code' => 0, 'status' => 'completed']); exit; } // Try Auto-Detection $settings = $pdo->query("SELECT setting_key, setting_value FROM settings")->fetchAll(PDO::FETCH_KEY_PAIR); $trc20_address = $settings['usdt_trc20_address'] ?? ''; $txid = check_trc20_payment($trc20_address, $recharge['amount'], $recharge['created_at']); if ($txid) { $pdo->beginTransaction(); try { $stmt = $pdo->prepare("UPDATE recharges SET status = 'completed', txid = ? WHERE id = ?"); $stmt->execute([$txid, $recharge_id]); $stmt = $pdo->prepare("UPDATE users SET balance = balance + ? WHERE id = ?"); $stmt->execute([$recharge['amount'], $recharge['user_id']]); $pdo->commit(); echo json_encode(['code' => 0, 'status' => 'completed']); } catch (Exception $e) { $pdo->rollBack(); echo json_encode(['code' => 500, 'msg' => '自动入账失败'], JSON_UNESCAPED_UNICODE); } } else { echo json_encode(['code' => 0, 'status' => 'pending']); } break; case 'send_message': $message = trim($_POST['message'] ?? ''); $target_user_id = $_POST['user_id'] ?? $_SESSION['user_id']; if (!$message) { echo json_encode(['code' => 400, 'msg' => '消息内容不能为空']); break; } // Check sender role $stmt = $pdo->prepare("SELECT role FROM users WHERE id = ?"); $stmt->execute([$_SESSION['user_id']]); $role = $stmt->fetchColumn(); $sender = ($role === 'admin') ? 'admin' : 'user'; $stmt = $pdo->prepare("INSERT INTO support_messages (user_id, sender, message, is_read) VALUES (?, ?, ?, 0)"); $stmt->execute([$target_user_id, $sender, $message]); echo json_encode(['code' => 0, 'msg' => '已发送'], JSON_UNESCAPED_UNICODE); break; case 'get_messages': $target_user_id = $_GET['user_id'] ?? $_SESSION['user_id']; $stmt = $pdo->prepare("SELECT role FROM users WHERE id = ?"); $stmt->execute([$_SESSION['user_id']]); $currentUserRole = $stmt->fetchColumn(); $isAdmin = ($currentUserRole === 'admin'); if (!$isAdmin && (int)$target_user_id !== (int)$_SESSION['user_id']) { echo json_encode(['code' => 403, 'msg' => '无权查看他人消息']); break; } // Mark as read if ($isAdmin && (int)$target_user_id !== (int)$_SESSION['user_id']) { $stmt = $pdo->prepare("UPDATE support_messages SET is_read = 1 WHERE user_id = ? AND sender = 'user'"); $stmt->execute([$target_user_id]); } else if (!$isAdmin) { $stmt = $pdo->prepare("UPDATE support_messages SET is_read = 1 WHERE user_id = ? AND sender = 'admin'"); $stmt->execute([$_SESSION['user_id']]); } $stmt = $pdo->prepare("SELECT * FROM support_messages WHERE user_id = ? ORDER BY created_at ASC"); $stmt->execute([$target_user_id]); echo json_encode(['code' => 0, 'data' => $stmt->fetchAll()], JSON_UNESCAPED_UNICODE); break; case 'get_chat_users': $stmt = $pdo->prepare("SELECT role FROM users WHERE id = ?"); $stmt->execute([$_SESSION['user_id']]); if ($stmt->fetchColumn() !== 'admin') { echo json_encode(['code' => 403, 'msg' => 'Forbidden']); break; } $stmt = $pdo->query(" SELECT u.id, u.username, m.message as last_message, m.created_at as last_time, (SELECT COUNT(*) FROM support_messages WHERE user_id = u.id AND sender = 'user' AND is_read = 0) as unread_count FROM users u JOIN ( SELECT user_id, MAX(created_at) as max_time FROM support_messages GROUP BY user_id ) last_msg ON u.id = last_msg.user_id JOIN support_messages m ON m.user_id = u.id AND m.created_at = last_msg.max_time ORDER BY m.created_at DESC "); echo json_encode(['code' => 0, 'data' => $stmt->fetchAll()], JSON_UNESCAPED_UNICODE); break; case 'check_new_messages': $stmt = $pdo->prepare("SELECT role FROM users WHERE id = ?"); $stmt->execute([$_SESSION['user_id']]); if ($stmt->fetchColumn() !== 'admin') { echo json_encode(['code' => 403, 'msg' => 'Forbidden']); break; } $stmt = $pdo->query("SELECT COUNT(*) FROM support_messages WHERE sender = 'user' AND is_read = 0"); $count = $stmt->fetchColumn(); echo json_encode(['code' => 0, 'unread_total' => $count]); break; default: echo json_encode(['code' => 404, 'msg' => '未知请求']); break; } } catch (Exception $e) { echo json_encode(['code' => 500, 'msg' => '系统处理异常: ' . $e->getMessage()], JSON_UNESCAPED_UNICODE); }