feat(umami): 新增token自动更新功能并优化缓存策略
- 添加Umami token自动获取和更新机制 - 实现token有效性检测和自动管理 - 新增update_token.php用于手动更新token - 延长缓存时间至7天减少API调用 - 优化系统稳定性和维护性
This commit is contained in:
135
info.php
135
info.php
@@ -4,9 +4,12 @@ header("Access-Control-Allow-Origin: *");
|
|||||||
|
|
||||||
// 配置 Umami API 的凭据
|
// 配置 Umami API 的凭据
|
||||||
$apiBaseUrl = 'https://um.com';
|
$apiBaseUrl = 'https://um.com';
|
||||||
|
$username = 'your-username'; // Umami登录用户名
|
||||||
|
$password = 'your-password'; // Umami登录密码
|
||||||
$token = '你的tocken';
|
$token = '你的tocken';
|
||||||
$websiteId = '你的网站id';
|
$websiteId = '你的网站id';
|
||||||
$cacheFile = 'umami_cache.json';
|
$cacheFile = 'umami_cache.json';
|
||||||
|
$tokenFile = 'umami_token.json'; // token缓存文件
|
||||||
$cacheTime = 604800; // 缓存时间为7天(604800秒)
|
$cacheTime = 604800; // 缓存时间为7天(604800秒)
|
||||||
|
|
||||||
// 获取当前时间戳(毫秒级)
|
// 获取当前时间戳(毫秒级)
|
||||||
@@ -18,6 +21,114 @@ $startTimestampYesterday = strtotime("yesterday") * 1000;
|
|||||||
$startTimestampLastMonth = strtotime("-1 month") * 1000;
|
$startTimestampLastMonth = strtotime("-1 month") * 1000;
|
||||||
$startTimestampLastYear = strtotime("-1 year") * 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 请求函数
|
// 定义 Umami API 请求函数
|
||||||
function fetchUmamiData($apiBaseUrl, $websiteId, $startAt, $endAt, $token) {
|
function fetchUmamiData($apiBaseUrl, $websiteId, $startAt, $endAt, $token) {
|
||||||
$url = "$apiBaseUrl/api/websites/$websiteId/stats?" . http_build_query([
|
$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);
|
return json_decode($response, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取有效的token(自动检查和更新)
|
||||||
|
$validToken = getValidToken($apiBaseUrl, $username, $password, $tokenFile, $token);
|
||||||
|
|
||||||
// 检查缓存文件是否存在且未过期
|
// 检查缓存文件是否存在且未过期
|
||||||
if (file_exists($cacheFile) && (time() - filemtime($cacheFile) < $cacheTime)) {
|
if (file_exists($cacheFile) && (time() - filemtime($cacheFile) < $cacheTime)) {
|
||||||
// 读取缓存文件
|
// 读取缓存文件
|
||||||
$cachedData = file_get_contents($cacheFile);
|
$cachedData = file_get_contents($cacheFile);
|
||||||
echo $cachedData;
|
echo $cachedData;
|
||||||
} else {
|
} 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);
|
$todayData = fetchUmamiData($apiBaseUrl, $websiteId, $startTimestampToday, $currentTimestamp, $validToken);
|
||||||
$yesterdayData = fetchUmamiData($apiBaseUrl, $websiteId, $startTimestampYesterday, $startTimestampToday, $token);
|
$yesterdayData = fetchUmamiData($apiBaseUrl, $websiteId, $startTimestampYesterday, $startTimestampToday, $validToken);
|
||||||
$lastMonthData = fetchUmamiData($apiBaseUrl, $websiteId, $startTimestampLastMonth, $currentTimestamp, $token);
|
$lastMonthData = fetchUmamiData($apiBaseUrl, $websiteId, $startTimestampLastMonth, $currentTimestamp, $validToken);
|
||||||
$lastYearData = fetchUmamiData($apiBaseUrl, $websiteId, $startTimestampLastYear, $currentTimestamp, $token);
|
$lastYearData = fetchUmamiData($apiBaseUrl, $websiteId, $startTimestampLastYear, $currentTimestamp, $validToken);
|
||||||
|
|
||||||
// 组装返回的 JSON 数据
|
// 组装返回的 JSON 数据
|
||||||
$responseData = [
|
$responseData = [
|
||||||
|
46
readme.md
46
readme.md
@@ -33,6 +33,9 @@ project/
|
|||||||
├── styles.css # 样式文件
|
├── styles.css # 样式文件
|
||||||
├── script.js # 核心逻辑
|
├── script.js # 核心逻辑
|
||||||
├── info.php # 访问量数据接口(通过开源项目umami的API获取数据)
|
├── info.php # 访问量数据接口(通过开源项目umami的API获取数据)
|
||||||
|
├── update_token.php # Token手动更新工具
|
||||||
|
├── umami_cache.json # 访问量数据缓存文件(自动生成)
|
||||||
|
├── umami_token.json # Token缓存文件(自动生成)
|
||||||
└── images/ # 图片资源目录
|
└── 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
|
```javascript
|
||||||
const AD_POSITIONS = {
|
const AD_POSITIONS = {
|
||||||
'ad-id': {
|
'ad-id': {
|
||||||
@@ -139,9 +157,16 @@ const BOOKED_STATUS = {
|
|||||||
4. 保持价格系数的合理性
|
4. 保持价格系数的合理性
|
||||||
|
|
||||||
## 更新日志
|
## 更新日志
|
||||||
### 2025-08-05
|
### 2025-01-27
|
||||||
- 优化缓存策略:将info.php中的缓存时间从10分钟(600秒)延长至7天(604800秒)
|
- 🔧 **新增Token自动更新功能**:
|
||||||
- 提升系统性能,减少API调用频率
|
- 添加了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
|
### 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
|
token获取:POST /api/auth/login
|
||||||
```
|
```
|
||||||
{
|
{
|
||||||
|
116
update_token.php
Normal file
116
update_token.php
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Umami Token 更新工具
|
||||||
|
* 用于手动更新或测试token获取功能
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 配置信息(请根据实际情况修改)
|
||||||
|
$apiBaseUrl = 'https://um.com';
|
||||||
|
$username = 'your-username'; // 请替换为实际的用户名
|
||||||
|
$password = 'your-password'; // 请替换为实际的密码
|
||||||
|
$tokenFile = 'umami_token.json';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取新的Umami token
|
||||||
|
* @param string $apiBaseUrl API基础URL
|
||||||
|
* @param string $username 用户名
|
||||||
|
* @param string $password 密码
|
||||||
|
* @return array 包含token和状态信息的数组
|
||||||
|
*/
|
||||||
|
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) {
|
||||||
|
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";
|
||||||
|
?>
|
Reference in New Issue
Block a user