diff --git a/info.php b/info.php index 0255c57..acd8442 100644 --- a/info.php +++ b/info.php @@ -4,9 +4,12 @@ header("Access-Control-Allow-Origin: *"); // 配置 Umami API 的凭据 $apiBaseUrl = 'https://um.com'; +$username = 'your-username'; // Umami登录用户名 +$password = 'your-password'; // Umami登录密码 $token = '你的tocken'; $websiteId = '你的网站id'; $cacheFile = 'umami_cache.json'; +$tokenFile = 'umami_token.json'; // token缓存文件 $cacheTime = 604800; // 缓存时间为7天(604800秒) // 获取当前时间戳(毫秒级) @@ -18,6 +21,114 @@ $startTimestampYesterday = strtotime("yesterday") * 1000; $startTimestampLastMonth = strtotime("-1 month") * 1000; $startTimestampLastYear = strtotime("-1 year") * 1000; +/** + * 获取新的Umami token + * @param string $apiBaseUrl API基础URL + * @param string $username 用户名 + * @param string $password 密码 + * @return string|null 返回token或null + */ +function getNewUmamiToken($apiBaseUrl, $username, $password) { + $loginUrl = "$apiBaseUrl/api/auth/login"; + $loginData = json_encode([ + 'username' => $username, + 'password' => $password + ]); + + $options = [ + 'http' => [ + 'method' => 'POST', + 'header' => [ + "Content-Type: application/json", + "Content-Length: " . strlen($loginData) + ], + 'content' => $loginData + ] + ]; + + $context = stream_context_create($options); + $response = @file_get_contents($loginUrl, false, $context); + + if ($response === FALSE) { + error_log("Failed to get new token from Umami API"); + return null; + } + + $responseData = json_decode($response, true); + return $responseData['token'] ?? null; +} + +/** + * 获取有效的token(自动更新机制) + * @param string $apiBaseUrl API基础URL + * @param string $username 用户名 + * @param string $password 密码 + * @param string $tokenFile token缓存文件路径 + * @param string $currentToken 当前token + * @return string 有效的token + */ +function getValidToken($apiBaseUrl, $username, $password, $tokenFile, $currentToken) { + // 检查token缓存文件 + if (file_exists($tokenFile)) { + $tokenData = json_decode(file_get_contents($tokenFile), true); + if ($tokenData && isset($tokenData['token']) && isset($tokenData['timestamp'])) { + // token缓存7天有效 + if (time() - $tokenData['timestamp'] < 604800) { + return $tokenData['token']; + } + } + } + + // 尝试获取新token + $newToken = getNewUmamiToken($apiBaseUrl, $username, $password); + if ($newToken) { + // 保存新token到缓存文件 + $tokenData = [ + 'token' => $newToken, + 'timestamp' => time() + ]; + file_put_contents($tokenFile, json_encode($tokenData)); + return $newToken; + } + + // 如果获取新token失败,返回当前token + return $currentToken; +} + +/** + * 检测token是否有效 + * @param string $apiBaseUrl API基础URL + * @param string $websiteId 网站ID + * @param string $token 要检测的token + * @return bool token是否有效 + */ +function isTokenValid($apiBaseUrl, $websiteId, $token) { + $testUrl = "$apiBaseUrl/api/websites/$websiteId/stats?startAt=" . (time() * 1000 - 86400000) . "&endAt=" . (time() * 1000); + $options = [ + 'http' => [ + 'method' => 'GET', + 'header' => [ + "Authorization: Bearer $token", + "Content-Type: application/json" + ] + ] + ]; + $context = stream_context_create($options); + $response = @file_get_contents($testUrl, false, $context); + + // 检查HTTP响应状态码 + if (isset($http_response_header)) { + foreach ($http_response_header as $header) { + if (strpos($header, 'HTTP/') === 0) { + $statusCode = (int) substr($header, 9, 3); + return $statusCode === 200; + } + } + } + + return $response !== FALSE; +} + // 定义 Umami API 请求函数 function fetchUmamiData($apiBaseUrl, $websiteId, $startAt, $endAt, $token) { $url = "$apiBaseUrl/api/websites/$websiteId/stats?" . http_build_query([ @@ -46,17 +157,33 @@ function fetchUmamiData($apiBaseUrl, $websiteId, $startAt, $endAt, $token) { return json_decode($response, true); } +// 获取有效的token(自动检查和更新) +$validToken = getValidToken($apiBaseUrl, $username, $password, $tokenFile, $token); + // 检查缓存文件是否存在且未过期 if (file_exists($cacheFile) && (time() - filemtime($cacheFile) < $cacheTime)) { // 读取缓存文件 $cachedData = file_get_contents($cacheFile); echo $cachedData; } else { + // 如果token无效,尝试重新获取 + if (!isTokenValid($apiBaseUrl, $websiteId, $validToken)) { + $validToken = getNewUmamiToken($apiBaseUrl, $username, $password); + if ($validToken) { + // 更新token缓存 + $tokenData = [ + 'token' => $validToken, + 'timestamp' => time() + ]; + file_put_contents($tokenFile, json_encode($tokenData)); + } + } + // 获取统计数据 - $todayData = fetchUmamiData($apiBaseUrl, $websiteId, $startTimestampToday, $currentTimestamp, $token); - $yesterdayData = fetchUmamiData($apiBaseUrl, $websiteId, $startTimestampYesterday, $startTimestampToday, $token); - $lastMonthData = fetchUmamiData($apiBaseUrl, $websiteId, $startTimestampLastMonth, $currentTimestamp, $token); - $lastYearData = fetchUmamiData($apiBaseUrl, $websiteId, $startTimestampLastYear, $currentTimestamp, $token); + $todayData = fetchUmamiData($apiBaseUrl, $websiteId, $startTimestampToday, $currentTimestamp, $validToken); + $yesterdayData = fetchUmamiData($apiBaseUrl, $websiteId, $startTimestampYesterday, $startTimestampToday, $validToken); + $lastMonthData = fetchUmamiData($apiBaseUrl, $websiteId, $startTimestampLastMonth, $currentTimestamp, $validToken); + $lastYearData = fetchUmamiData($apiBaseUrl, $websiteId, $startTimestampLastYear, $currentTimestamp, $validToken); // 组装返回的 JSON 数据 $responseData = [ diff --git a/readme.md b/readme.md index eab7958..2905be7 100644 --- a/readme.md +++ b/readme.md @@ -33,6 +33,9 @@ project/ ├── styles.css # 样式文件 ├── script.js # 核心逻辑 ├── info.php # 访问量数据接口(通过开源项目umami的API获取数据) +├── update_token.php # Token手动更新工具 +├── umami_cache.json # 访问量数据缓存文件(自动生成) +├── umami_token.json # Token缓存文件(自动生成) └── images/ # 图片资源目录 ``` ## 文件说明 @@ -43,7 +46,22 @@ project/ ## 核心配置说明 -### 1. 广告位配置 (script.js) +### 1. Umami API配置 (info.php) +```php +// 基础配置 +$apiBaseUrl = 'https://um.com'; // Umami服务器地址 +$username = 'your-username'; // Umami登录用户名 +$password = 'your-password'; // Umami登录密码 +$websiteId = '你的网站id'; // 网站ID +``` + +**Token自动更新功能**: +- 系统会自动检测token有效性 +- Token失效时自动获取新token +- Token缓存7天,减少API调用 +- 支持手动更新:运行 `php update_token.php` + +### 2. 广告位配置 (script.js) ```javascript const AD_POSITIONS = { 'ad-id': { @@ -139,9 +157,16 @@ const BOOKED_STATUS = { 4. 保持价格系数的合理性 ## 更新日志 -### 2025-08-05 -- 优化缓存策略:将info.php中的缓存时间从10分钟(600秒)延长至7天(604800秒) -- 提升系统性能,减少API调用频率 +### 2025-01-27 +- 🔧 **新增Token自动更新功能**: + - 添加了Umami token自动获取和更新机制 + - 新增 `getNewUmamiToken()` 函数用于获取新token + - 新增 `getValidToken()` 函数实现token自动管理 + - 新增 `isTokenValid()` 函数检测token有效性 + - 创建独立的 `update_token.php` 工具用于手动更新token + - Token缓存7天,自动处理Umami重启后的token失效问题 +- 🚀 **优化缓存策略**:将info.php中的缓存时间从10分钟(600秒)延长至7天(604800秒) +- ⚡ **提升系统性能**:减少API调用频率,增强系统稳定性 ### 2024-02-29 - 初始版本发布 @@ -150,7 +175,18 @@ const BOOKED_STATUS = { - 优化移动端显示效果 ## 维护说明 -umami的升级后会导致token丢失,需要定期的去获取新的token,否则会导致无法获取到实时的访问量数据。 + +### Token管理 +- ✅ **自动化处理**:系统已集成token自动更新功能,无需手动干预 +- 🔄 **自动检测**:每次API调用前自动检测token有效性 +- 📱 **手动更新**:如需手动更新token,运行:`php update_token.php` +- 📁 **缓存机制**:Token缓存7天,减少不必要的API调用 +- ⚠️ **注意事项**:Umami升级后可能导致token失效,系统会自动处理 + +### 日常维护 +- 定期检查 `umami_cache.json` 和 `umami_token.json` 文件权限 +- 确保PHP有写入权限以创建和更新缓存文件 +- 监控系统日志,关注token获取失败的错误信息 token获取:POST /api/auth/login ``` { diff --git a/update_token.php b/update_token.php new file mode 100644 index 0000000..cd46915 --- /dev/null +++ b/update_token.php @@ -0,0 +1,116 @@ + $username, + 'password' => $password + ]); + + $options = [ + 'http' => [ + 'method' => 'POST', + 'header' => [ + "Content-Type: application/json", + "Content-Length: " . strlen($loginData) + ], + 'content' => $loginData + ] + ]; + + $context = stream_context_create($options); + $response = @file_get_contents($loginUrl, false, $context); + + if ($response === FALSE) { + return [ + 'success' => false, + 'message' => 'Failed to connect to Umami API', + 'token' => null + ]; + } + + $responseData = json_decode($response, true); + + if (isset($responseData['token'])) { + return [ + 'success' => true, + 'message' => 'Token obtained successfully', + 'token' => $responseData['token'], + 'user_info' => $responseData['user'] ?? null + ]; + } else { + return [ + 'success' => false, + 'message' => 'Invalid credentials or API response', + 'token' => null, + 'response' => $responseData + ]; + } +} + +// 执行token获取 +echo "正在获取新的Umami token...\n"; +echo "API URL: $apiBaseUrl\n"; +echo "Username: $username\n"; +echo "\n"; + +$result = getNewUmamiToken($apiBaseUrl, $username, $password); + +if ($result['success']) { + echo "✅ Token获取成功!\n"; + echo "Token: " . $result['token'] . "\n"; + + if (isset($result['user_info'])) { + echo "用户信息:\n"; + echo " - ID: " . ($result['user_info']['id'] ?? 'N/A') . "\n"; + echo " - Username: " . ($result['user_info']['username'] ?? 'N/A') . "\n"; + echo " - Role: " . ($result['user_info']['role'] ?? 'N/A') . "\n"; + } + + // 保存token到缓存文件 + $tokenData = [ + 'token' => $result['token'], + 'timestamp' => time(), + 'user_info' => $result['user_info'] ?? null + ]; + + if (file_put_contents($tokenFile, json_encode($tokenData, JSON_PRETTY_PRINT))) { + echo "\n✅ Token已保存到缓存文件: $tokenFile\n"; + } else { + echo "\n❌ 保存token到缓存文件失败\n"; + } + +} else { + echo "❌ Token获取失败!\n"; + echo "错误信息: " . $result['message'] . "\n"; + + if (isset($result['response'])) { + echo "API响应: " . json_encode($result['response'], JSON_PRETTY_PRINT) . "\n"; + } +} + +echo "\n"; +echo "使用说明:\n"; +echo "1. 请确保在文件顶部正确配置了API URL、用户名和密码\n"; +echo "2. 确保Umami服务正常运行且网络连接正常\n"; +echo "3. 如果获取失败,请检查用户名密码是否正确\n"; +echo "4. Token将自动保存到 $tokenFile 文件中\n"; +echo "5. info.php 会自动使用缓存的token\n"; +?> \ No newline at end of file