1.优化getPlayerInfo接口

This commit is contained in:
2026-05-13 10:15:49 +08:00
parent 6a1fd639a4
commit 52b5ccb8e4
4 changed files with 85 additions and 7 deletions

View File

@@ -238,6 +238,17 @@ class UserCache
return (int) config('api.player_cache_ttl', 300);
}
/** /api/v1/getPlayerInfo 快照 key 前缀 */
private static function playerInfoSnapshotPrefix(): string
{
return config('api.player_info_snapshot_prefix', 'api:v1:player_info:');
}
private static function playerInfoSnapshotTtl(): int
{
return (int) config('api.player_info_snapshot_ttl', 180);
}
/**
* 按 username 缓存玩家信息(仅 id + username供中间件注入 request->player 后使用)
* 登录/信息变更时需调用 deletePlayerByUsername 失效
@@ -280,6 +291,54 @@ class UserCache
return false;
}
$key = self::playerCachePrefix() . $username;
return Cache::delete($key);
$r1 = Cache::delete($key);
$snapKey = self::playerInfoSnapshotPrefix() . $username;
$r2 = Cache::delete($snapKey);
return $r1 || $r2;
}
/**
* 读取 getPlayerInfo 接口用的玩家公开信息快照(未命中返回 null
* @return array<string, mixed>|null
*/
public static function getPlayerInfoSnapshotByUsername(string $username): ?array
{
if ($username === '') {
return null;
}
if (self::playerInfoSnapshotTtl() <= 0) {
return null;
}
$key = self::playerInfoSnapshotPrefix() . $username;
$val = Cache::get($key);
if ($val === null || $val === '') {
return null;
}
$data = json_decode((string) $val, true);
if (!is_array($data) || !array_key_exists('username', $data)) {
return null;
}
return $data;
}
/**
* 写入 getPlayerInfo 返回体快照(已脱敏数组)
* @param array<string, mixed> $info
*/
public static function setPlayerInfoSnapshotByUsername(string $username, array $info): bool
{
if ($username === '' || empty($info)) {
return false;
}
$ttl = self::playerInfoSnapshotTtl();
if ($ttl <= 0) {
return true;
}
$key = self::playerInfoSnapshotPrefix() . $username;
$payload = json_encode($info, JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE);
if ($payload === false) {
return false;
}
return Cache::set($key, $payload, $ttl);
}
}

View File

@@ -44,6 +44,14 @@ class GameController extends BaseController
'sort',
];
/** getPlayerInfo 仅查询需返回的列,减轻 IO敏感/内部字段不入库查询) */
private const PLAYER_INFO_DB_FIELDS = [
'id', 'username', 'phone', 'uid', 'name', 'status', 'coin', 'is_up', 'admin_id',
'total_ticket_count', 'paid_ticket_count', 'free_ticket_count', 'free_ticket',
'total_win_coin',
'create_time', 'update_time',
];
/**
* 获取游戏列表
* POST 参数lang可选zh/en默认 zh
@@ -130,24 +138,31 @@ class GameController extends BaseController
/**
* 获取用户信息
* POST 参数username
* 返回 DicePlayer 中非敏感信息
* 参数usernamePOST JSON / 表单 / Query 均可input 合并读取降低偶发空参)
* 返回 DicePlayer 中非敏感信息;短期 Redis 快照 + 窄字段查询降低延迟
*/
public function getPlayerInfo(Request $request): Response
{
$username = trim((string) ($request->post('username', '')));
$usernameRaw = $request->input('username', '');
$username = is_string($usernameRaw) ? trim($usernameRaw) : '';
if ($username === '') {
return $this->fail('username is required', ReturnCode::PARAMS_ERROR);
}
$player = DicePlayer::where('username', $username)->find();
$cached = UserCache::getPlayerInfoSnapshotByUsername($username);
if ($cached !== null) {
return $this->success($cached);
}
$player = DicePlayer::field(self::PLAYER_INFO_DB_FIELDS)->where('username', $username)->find();
if (!$player) {
return $this->fail('User not found', ReturnCode::NOT_FOUND);
}
$hidden = ['password', 'lottery_config_id', 't1_weight', 't2_weight', 't3_weight', 't4_weight', 't5_weight', 'delete_time'];
$info = $player->hidden($hidden)->toArray();
UserCache::setPlayerInfoSnapshotByUsername($username, $info);
return $this->success($info);
}

View File

@@ -47,8 +47,9 @@ class AuthTokenMiddleware implements MiddlewareInterface
throw new ApiException('auth-token invalid', ReturnCode::TOKEN_INVALID);
}
$currentToken = AuthTokenCache::getTokenByAgentId($agentId);
if ($currentToken === null || $currentToken !== $token) {
// 单次 Redistoken → agent_id与 JWT 内 agent_id 一致即有效(减少一次按 agent 取当前 token 的往返)
$agentIdFromStore = AuthTokenCache::getAgentIdByToken($token);
if ($agentIdFromStore === null || $agentIdFromStore !== $agentId) {
throw new ApiException('auth-token invalid or expired', ReturnCode::TOKEN_INVALID);
}