Files
leonapp/api.php
2025-09-20 22:20:08 +08:00

573 lines
17 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* App Store API
* 版本: 2.0
* 支持的端点:
* - /api.php?t=getallapps - 获取所有APP列表
* - /api.php?t=getappinfo&id={appid} - 获取APP信息
* - /api.php?t=getalltags - 获取所有标签
* - /api.php?t=gettagapp&id={tagid} - 获取某标签里的APP列表
* - /api.php?t=getdeveloperapp&id={developerid} - 获取某开发者的APP列表
* - /api.php?t=getdeveloperinfo&id={developerid} - 获取开发者信息
* - /api.php?t=getacc - 获取所有公告
* - /api.php?t=getcount - 获取计数信息
*/
// 关闭错误显示(生产环境)
ini_set('display_errors', 0);
error_reporting(E_ALL);
// 包含配置文件
require_once 'config.php';
// 设置JSON响应头
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type');
// 处理OPTIONS请求
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
http_response_code(200);
exit;
}
// 检查数据库连接
if (!$conn) {
sendErrorResponse('数据库连接失败', 500);
exit;
}
// 获取API类型参数
$apiType = isset($_GET['t']) ? trim($_GET['t']) : '';
// 根据API类型调用对应处理函数
switch ($apiType) {
case 'getallapps':
getAllApps();
break;
case 'getappinfo':
getAppInfo();
break;
case 'getalltags':
getAllTags();
break;
case 'gettagapp':
getTagApps();
break;
case 'getdeveloperapp':
getDeveloperApps();
break;
case 'getdeveloperinfo':
getDeveloperInfo();
break;
case 'getacc':
getAllAnnouncements();
break;
case 'getcount':
getCountInfo();
break;
default:
showApiEndpoints();
break;
}
/**
* 发送成功响应
* @param mixed $data 要返回的数据
*/
function sendSuccessResponse($data) {
$response = [
'status' => 'success',
'data' => $data
];
echo json_encode($response, JSON_UNESCAPED_UNICODE);
exit;
}
/**
* 发送错误响应
* @param string $message 错误消息
* @param int $statusCode HTTP状态码
*/
function sendErrorResponse($message, $statusCode = 400) {
http_response_code($statusCode);
$response = [
'status' => 'error',
'message' => $message
];
echo json_encode($response, JSON_UNESCAPED_UNICODE);
exit;
}
/**
* 显示所有API端点信息
*/
function showApiEndpoints() {
$endpoints = [
'/api.php?t=getallapps' => '获取所有APP列表',
'/api.php?t=getappinfo&id={appid}' => '获取APP信息',
'/api.php?t=getalltags' => '获取所有标签',
'/api.php?t=gettagapp&id={tagid}' => '获取某标签里的APP列表',
'/api.php?t=getdeveloperapp&id={developerid}' => '获取某开发者的APP列表',
'/api.php?t=getdeveloperinfo&id={developerid}' => '获取开发者信息',
'/api.php?t=getacc' => '获取所有公告',
'/api.php?t=getcount' => '获取计数信息如所有APP的数量、开发者的数量等'
];
$response = [
'status' => 'success',
'message' => 'App Store API v2.0',
'endpoints' => $endpoints,
'example' => '/api.php?t=getallapps'
];
echo json_encode($response, JSON_UNESCAPED_UNICODE);
exit;
}
/**
* 获取所有APP列表
*/
function getAllApps() {
global $conn;
// 获取分页参数
$page = isset($_GET['page']) ? max(1, intval($_GET['page'])) : 1;
$limit = isset($_GET['limit']) ? min(100, max(1, intval($_GET['limit']))) : 20;
$offset = ($page - 1) * $limit;
// 获取总数量
$countSql = "SELECT COUNT(*) as total FROM apps WHERE status = 'approved' AND is_approved = 1";
$countResult = $conn->query($countSql);
$total = $countResult->fetch_assoc()['total'] ?? 0;
$totalPages = ceil($total / $limit);
// 获取应用列表
$sql = "SELECT apps.id, apps.name, apps.description, apps.age_rating, apps.version,
AVG(reviews.rating) as avg_rating, SUM(app_versions.download_count) as total_downloads
FROM apps
LEFT JOIN reviews ON apps.id = reviews.app_id
LEFT JOIN app_versions ON apps.id = app_versions.app_id
WHERE apps.status = 'approved' AND apps.is_approved = 1
GROUP BY apps.id, apps.name, apps.description, apps.age_rating, apps.version
ORDER BY apps.created_at DESC
LIMIT ?, ?";
$stmt = $conn->prepare($sql);
$stmt->bind_param("ii", $offset, $limit);
$stmt->execute();
$result = $stmt->get_result();
$apps = [];
while ($row = $result->fetch_assoc()) {
// 格式化JSON字段
if (isset($row['platforms']) && !empty($row['platforms'])) {
$row['platforms'] = json_decode($row['platforms'], true);
}
$apps[] = $row;
}
$response = [
'apps' => $apps,
'pagination' => [
'total' => $total,
'page' => $page,
'limit' => $limit,
'totalPages' => $totalPages
]
];
sendSuccessResponse($response);
}
/**
* 获取指定APP的详细信息
*/
function getAppInfo() {
global $conn;
// 检查是否提供了app_id参数
if (!isset($_GET['id']) || !is_numeric($_GET['id'])) {
sendErrorResponse('请提供有效的应用ID', 400);
}
$appId = intval($_GET['id']);
// 获取应用基本信息
$sqlApp = "SELECT apps.*, AVG(reviews.rating) as avg_rating, SUM(app_versions.download_count) as total_downloads
FROM apps
LEFT JOIN reviews ON apps.id = reviews.app_id
LEFT JOIN app_versions ON apps.id = app_versions.app_id
WHERE apps.id = ? AND apps.status = 'approved' AND apps.is_approved = 1
GROUP BY apps.id";
$stmtApp = $conn->prepare($sqlApp);
$stmtApp->bind_param("i", $appId);
$stmtApp->execute();
$resultApp = $stmtApp->get_result();
if ($resultApp->num_rows === 0) {
sendErrorResponse('未找到该应用', 404);
}
$app = $resultApp->fetch_assoc();
// 格式化JSON字段
if (isset($app['platforms']) && !empty($app['platforms'])) {
$app['platforms'] = json_decode($app['platforms'], true);
}
// 获取版本信息
$sqlVersions = "SELECT id, version, changelog, file_path, download_count, created_at
FROM app_versions
WHERE app_id = ?
ORDER BY created_at DESC";
$stmtVersions = $conn->prepare($sqlVersions);
$stmtVersions->bind_param("i", $appId);
$stmtVersions->execute();
$resultVersions = $stmtVersions->get_result();
$versions = [];
while ($version = $resultVersions->fetch_assoc()) {
$versions[] = $version;
}
$app['versions'] = $versions;
// 获取图片信息
$sqlImages = "SELECT id, image_path FROM app_images WHERE app_id = ?";
$stmtImages = $conn->prepare($sqlImages);
$stmtImages->bind_param("i", $appId);
$stmtImages->execute();
$resultImages = $stmtImages->get_result();
$images = [];
while ($image = $resultImages->fetch_assoc()) {
$images[] = $image;
}
$app['images'] = $images;
// 获取标签信息
$sqlTags = "SELECT tags.id, tags.name FROM app_tags
JOIN tags ON app_tags.tag_id = tags.id
WHERE app_tags.app_id = ?";
$stmtTags = $conn->prepare($sqlTags);
$stmtTags->bind_param("i", $appId);
$stmtTags->execute();
$resultTags = $stmtTags->get_result();
$tags = [];
while ($tag = $resultTags->fetch_assoc()) {
$tags[] = $tag;
}
$app['tags'] = $tags;
sendSuccessResponse($app);
}
/**
* 获取所有标签
*/
function getAllTags() {
global $conn;
$sql = "SELECT id, name FROM tags ORDER BY name ASC";
$result = $conn->query($sql);
$tags = [];
while ($row = $result->fetch_assoc()) {
$tags[] = $row;
}
sendSuccessResponse($tags);
}
/**
* 获取指定标签下的应用列表
*/
function getTagApps() {
global $conn;
// 检查是否提供了tag_id参数
if (!isset($_GET['id']) || !is_numeric($_GET['id'])) {
sendErrorResponse('请提供有效的标签ID', 400);
}
$tagId = intval($_GET['id']);
// 获取分页参数
$page = isset($_GET['page']) ? max(1, intval($_GET['page'])) : 1;
$limit = isset($_GET['limit']) ? min(100, max(1, intval($_GET['limit']))) : 20;
$offset = ($page - 1) * $limit;
// 获取标签信息
$sqlTag = "SELECT name FROM tags WHERE id = ?";
$stmtTag = $conn->prepare($sqlTag);
$stmtTag->bind_param("i", $tagId);
$stmtTag->execute();
$resultTag = $stmtTag->get_result();
if ($resultTag->num_rows === 0) {
sendErrorResponse('未找到该标签', 404);
}
$tagInfo = $resultTag->fetch_assoc();
// 获取总数量
$countSql = "SELECT COUNT(DISTINCT apps.id) as total
FROM apps
JOIN app_tags ON apps.id = app_tags.app_id
WHERE app_tags.tag_id = ? AND apps.status = 'approved' AND apps.is_approved = 1";
$countStmt = $conn->prepare($countSql);
$countStmt->bind_param("i", $tagId);
$countStmt->execute();
$countResult = $countStmt->get_result();
$total = $countResult->fetch_assoc()['total'] ?? 0;
$totalPages = ceil($total / $limit);
// 获取应用列表
$sql = "SELECT apps.id, apps.name, apps.description, apps.age_rating, apps.version,
AVG(reviews.rating) as avg_rating
FROM apps
JOIN app_tags ON apps.id = app_tags.app_id
LEFT JOIN reviews ON apps.id = reviews.app_id
WHERE app_tags.tag_id = ? AND apps.status = 'approved' AND apps.is_approved = 1
GROUP BY apps.id, apps.name, apps.description, apps.age_rating, apps.version
ORDER BY apps.created_at DESC
LIMIT ?, ?";
$stmt = $conn->prepare($sql);
$stmt->bind_param("iii", $tagId, $offset, $limit);
$stmt->execute();
$result = $stmt->get_result();
$apps = [];
while ($row = $result->fetch_assoc()) {
$apps[] = $row;
}
$response = [
'tag' => $tagInfo,
'apps' => $apps,
'pagination' => [
'total' => $total,
'page' => $page,
'limit' => $limit,
'totalPages' => $totalPages
]
];
sendSuccessResponse($response);
}
/**
* 获取指定开发者的应用列表
*/
function getDeveloperApps() {
global $conn;
// 检查是否提供了developer_id参数
if (!isset($_GET['id']) || !is_numeric($_GET['id'])) {
sendErrorResponse('请提供有效的开发者ID', 400);
}
$developerId = intval($_GET['id']);
// 获取分页参数
$page = isset($_GET['page']) ? max(1, intval($_GET['page'])) : 1;
$limit = isset($_GET['limit']) ? min(100, max(1, intval($_GET['limit']))) : 20;
$offset = ($page - 1) * $limit;
// 获取开发者邮箱用于关联apps表
$sqlDeveloper = "SELECT email FROM developers WHERE id = ?";
$stmtDeveloper = $conn->prepare($sqlDeveloper);
$stmtDeveloper->bind_param("i", $developerId);
$stmtDeveloper->execute();
$resultDeveloper = $stmtDeveloper->get_result();
if ($resultDeveloper->num_rows === 0) {
sendErrorResponse('未找到该开发者', 404);
}
$developerInfo = $resultDeveloper->fetch_assoc();
$developerEmail = $developerInfo['email'];
// 获取总数量
$countSql = "SELECT COUNT(*) as total FROM apps WHERE developer_email = ? AND status = 'approved' AND is_approved = 1";
$countStmt = $conn->prepare($countSql);
$countStmt->bind_param("s", $developerEmail);
$countStmt->execute();
$countResult = $countStmt->get_result();
$total = $countResult->fetch_assoc()['total'] ?? 0;
$totalPages = ceil($total / $limit);
// 获取应用列表
$sql = "SELECT apps.id, apps.name, apps.description, apps.age_rating, apps.version,
AVG(reviews.rating) as avg_rating, SUM(app_versions.download_count) as total_downloads
FROM apps
LEFT JOIN reviews ON apps.id = reviews.app_id
LEFT JOIN app_versions ON apps.id = app_versions.app_id
WHERE apps.developer_email = ? AND apps.status = 'approved' AND apps.is_approved = 1
GROUP BY apps.id, apps.name, apps.description, apps.age_rating, apps.version
ORDER BY apps.created_at DESC
LIMIT ?, ?";
$stmt = $conn->prepare($sql);
$stmt->bind_param("sii", $developerEmail, $offset, $limit);
$stmt->execute();
$result = $stmt->get_result();
$apps = [];
while ($row = $result->fetch_assoc()) {
$apps[] = $row;
}
$response = [
'developer_id' => $developerId,
'apps' => $apps,
'pagination' => [
'total' => $total,
'page' => $page,
'limit' => $limit,
'totalPages' => $totalPages
]
];
sendSuccessResponse($response);
}
/**
* 获取开发者信息
*/
function getDeveloperInfo() {
global $conn;
// 检查是否提供了developer_id参数
if (!isset($_GET['id']) || !is_numeric($_GET['id'])) {
sendErrorResponse('请提供有效的开发者ID', 400);
}
$developerId = intval($_GET['id']);
// 获取开发者信息(不包含密码等敏感信息)
$sql = "SELECT id, username, email, created_at, is_verified, verified_at
FROM developers
WHERE id = ?";
$stmt = $conn->prepare($sql);
$stmt->bind_param("i", $developerId);
$stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows === 0) {
sendErrorResponse('未找到该开发者', 404);
}
$developer = $result->fetch_assoc();
// 获取开发者的应用数量
$appCountSql = "SELECT COUNT(*) as app_count
FROM apps
WHERE developer_email = ? AND status = 'approved' AND is_approved = 1";
$appCountStmt = $conn->prepare($appCountSql);
$appCountStmt->bind_param("s", $developer['email']);
$appCountStmt->execute();
$appCountResult = $appCountStmt->get_result();
$appCount = $appCountResult->fetch_assoc()['app_count'] ?? 0;
$developer['app_count'] = $appCount;
sendSuccessResponse($developer);
}
/**
* 获取所有公告
*/
function getAllAnnouncements() {
global $conn;
// 获取分页参数
$page = isset($_GET['page']) ? max(1, intval($_GET['page'])) : 1;
$limit = isset($_GET['limit']) ? min(100, max(1, intval($_GET['limit']))) : 20;
$offset = ($page - 1) * $limit;
// 获取总数量
$countSql = "SELECT COUNT(*) as total FROM announcements";
$countResult = $conn->query($countSql);
$total = $countResult->fetch_assoc()['total'] ?? 0;
$totalPages = ceil($total / $limit);
// 获取公告列表
$sql = "SELECT id, title, content, created_at, admin_id
FROM announcements
ORDER BY created_at DESC
LIMIT ?, ?";
$stmt = $conn->prepare($sql);
$stmt->bind_param("ii", $offset, $limit);
$stmt->execute();
$result = $stmt->get_result();
$announcements = [];
while ($row = $result->fetch_assoc()) {
$announcements[] = $row;
}
$response = [
'announcements' => $announcements,
'pagination' => [
'total' => $total,
'page' => $page,
'limit' => $limit,
'totalPages' => $totalPages
]
];
sendSuccessResponse($response);
}
/**
* 获取计数信息
*/
function getCountInfo() {
global $conn;
// 应用总数
$appCountSql = "SELECT COUNT(*) as count FROM apps WHERE status = 'approved' AND is_approved = 1";
$appCountResult = $conn->query($appCountSql);
$appCount = $appCountResult->fetch_assoc()['count'] ?? 0;
// 开发者总数
$developerCountSql = "SELECT COUNT(*) as count FROM developers";
$developerCountResult = $conn->query($developerCountSql);
$developerCount = $developerCountResult->fetch_assoc()['count'] ?? 0;
// 标签总数
$tagCountSql = "SELECT COUNT(*) as count FROM tags";
$tagCountResult = $conn->query($tagCountSql);
$tagCount = $tagCountResult->fetch_assoc()['count'] ?? 0;
// 公告总数
$announcementCountSql = "SELECT COUNT(*) as count FROM announcements";
$announcementCountResult = $conn->query($announcementCountSql);
$announcementCount = $announcementCountResult->fetch_assoc()['count'] ?? 0;
// 总下载量
$downloadCountSql = "SELECT SUM(download_count) as count FROM app_versions";
$downloadCountResult = $conn->query($downloadCountSql);
$downloadCount = $downloadCountResult->fetch_assoc()['count'] ?? 0;
$counts = [
'total_apps' => $appCount,
'total_developers' => $developerCount,
'total_tags' => $tagCount,
'total_announcements' => $announcementCount,
'total_downloads' => $downloadCount
];
sendSuccessResponse($counts);
}
// 关闭数据库连接
$conn->close();
?>