重新设计状态码规范
This commit is contained in:
@@ -25,7 +25,7 @@ class AuthTokenController extends OpenController
|
||||
public function index(Request $request): Response
|
||||
{
|
||||
if (strtoupper($request->method()) !== 'GET') {
|
||||
return $this->fail('仅支持 GET 请求', ReturnCode::EMPTY_PARAMS);
|
||||
return $this->fail('仅支持 GET 请求', ReturnCode::PARAMS_ERROR);
|
||||
}
|
||||
|
||||
$param = $request->get();
|
||||
@@ -35,27 +35,27 @@ class AuthTokenController extends OpenController
|
||||
$time = trim((string) ($param['time'] ?? ''));
|
||||
|
||||
if ($signature === '' || $secret === '' || $device === '' || $time === '') {
|
||||
return $this->fail('signature、secret、device、time 均为必传且不能为空', ReturnCode::EMPTY_PARAMS);
|
||||
return $this->fail('signature、secret、device、time 均为必传且不能为空', ReturnCode::PARAMS_ERROR);
|
||||
}
|
||||
|
||||
$serverSecret = trim((string) config('api.auth_token_secret', ''));
|
||||
if ($serverSecret === '') {
|
||||
return $this->fail('服务未配置 API_AUTH_TOKEN_SECRET', ReturnCode::EMPTY_PARAMS);
|
||||
return $this->fail('服务未配置 API_AUTH_TOKEN_SECRET', ReturnCode::PARAMS_ERROR);
|
||||
}
|
||||
if ($secret !== $serverSecret) {
|
||||
return $this->fail('密钥错误', ReturnCode::EMPTY_PARAMS);
|
||||
return $this->fail('密钥错误', ReturnCode::FORBIDDEN);
|
||||
}
|
||||
|
||||
$tolerance = (int) config('api.auth_token_time_tolerance', 300);
|
||||
$now = time();
|
||||
$ts = is_numeric($time) ? (int) $time : 0;
|
||||
if ($ts <= 0 || abs($now - $ts) > $tolerance) {
|
||||
return $this->fail('时间戳无效或已过期', ReturnCode::EMPTY_PARAMS);
|
||||
return $this->fail('时间戳无效或已过期', ReturnCode::PARAMS_ERROR);
|
||||
}
|
||||
|
||||
$sign = $this->getAuthToken($device, $serverSecret, $time);
|
||||
if ($sign !== $signature) {
|
||||
return $this->fail('签名验证失败', ReturnCode::EMPTY_PARAMS);
|
||||
return $this->fail('签名验证失败', ReturnCode::FORBIDDEN);
|
||||
}
|
||||
|
||||
$exp = (int) config('api.auth_token_exp', 86400);
|
||||
|
||||
@@ -31,7 +31,7 @@ class GameController extends OpenController
|
||||
$userId = UserLogic::getUserIdFromRequest($request) ?? 0;
|
||||
$count = (int) $request->post('count', 0);
|
||||
if (!in_array($count, [1, 5, 10], true)) {
|
||||
return $this->fail('购买抽奖券错误', ReturnCode::EMPTY_PARAMS);
|
||||
return $this->fail('购买抽奖券错误', ReturnCode::PARAMS_ERROR);
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -45,7 +45,7 @@ class GameController extends OpenController
|
||||
$coin = $player ? (float) $player->coin : 0;
|
||||
return $this->success(['coin' => $coin], $msg);
|
||||
}
|
||||
return $this->fail($msg, ReturnCode::EMPTY_PARAMS);
|
||||
return $this->fail($msg, ReturnCode::BUSINESS_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,16 +72,16 @@ class GameController extends OpenController
|
||||
$userId = UserLogic::getUserIdFromRequest($request) ?? 0;
|
||||
$rediction = $request->post('rediction');
|
||||
if ($rediction === '' || $rediction === null) {
|
||||
return $this->fail('请传递 rediction 参数', ReturnCode::EMPTY_PARAMS);
|
||||
return $this->fail('请传递 rediction 参数', ReturnCode::PARAMS_ERROR);
|
||||
}
|
||||
$direction = (int) $rediction;
|
||||
if (!in_array($direction, [0, 1], true)) {
|
||||
return $this->fail('rediction 必须为 0 或 1', ReturnCode::EMPTY_PARAMS);
|
||||
return $this->fail('rediction 必须为 0 或 1', ReturnCode::PARAMS_ERROR);
|
||||
}
|
||||
|
||||
$player = DicePlayer::find($userId);
|
||||
if (!$player) {
|
||||
return $this->fail('用户不存在', ReturnCode::EMPTY_PARAMS);
|
||||
return $this->fail('用户不存在', ReturnCode::NOT_FOUND);
|
||||
}
|
||||
$minEv = (float) DiceRewardConfig::min('real_ev');
|
||||
$minCoin = abs($minEv + 100);
|
||||
@@ -95,7 +95,7 @@ class GameController extends OpenController
|
||||
$data = $logic->run($userId, $direction);
|
||||
return $this->success($data);
|
||||
} catch (ApiException $e) {
|
||||
return $this->fail($e->getMessage(), ReturnCode::EMPTY_PARAMS);
|
||||
return $this->fail($e->getMessage(), ReturnCode::BUSINESS_ERROR);
|
||||
} catch (\Throwable $e) {
|
||||
$timeoutRecord = null;
|
||||
try {
|
||||
|
||||
@@ -28,7 +28,7 @@ class UserController extends OpenController
|
||||
$phone = $request->post('phone', '');
|
||||
$password = $request->post('password', '');
|
||||
if ($phone === '' || $password === '') {
|
||||
return $this->fail('请填写手机号和密码', ReturnCode::EMPTY_PARAMS);
|
||||
return $this->fail('请填写手机号和密码', ReturnCode::PARAMS_ERROR);
|
||||
}
|
||||
$logic = new UserLogic();
|
||||
$data = $logic->login($phone, $password);
|
||||
@@ -50,7 +50,7 @@ class UserController extends OpenController
|
||||
$password = $request->post('password', '');
|
||||
$nickname = $request->post('nickname');
|
||||
if ($phone === '' || $password === '') {
|
||||
return $this->fail('请填写手机号和密码', ReturnCode::EMPTY_PARAMS);
|
||||
return $this->fail('请填写手机号和密码', ReturnCode::PARAMS_ERROR);
|
||||
}
|
||||
$logic = new UserLogic();
|
||||
$data = $logic->register($phone, $password, $nickname ? (string) $nickname : null);
|
||||
@@ -70,7 +70,7 @@ class UserController extends OpenController
|
||||
{
|
||||
$token = $request->userToken ?? UserLogic::getTokenFromRequest($request);
|
||||
if ($token === '' || !UserLogic::logout($token)) {
|
||||
return $this->fail('退出失败或 token 已失效', ReturnCode::TOKEN_TIMEOUT);
|
||||
return $this->fail('退出失败或 token 已失效', ReturnCode::TOKEN_INVALID);
|
||||
}
|
||||
return $this->success('已退出登录');
|
||||
}
|
||||
@@ -86,7 +86,7 @@ class UserController extends OpenController
|
||||
$userId = UserLogic::getUserIdFromRequest($request) ?? 0;
|
||||
$user = UserLogic::getCachedUser($userId);
|
||||
if (empty($user)) {
|
||||
return $this->fail('用户不存在', ReturnCode::EMPTY_PARAMS);
|
||||
return $this->fail('用户不存在', ReturnCode::NOT_FOUND);
|
||||
}
|
||||
$fields = ['id', 'username', 'phone', 'uid', 'name', 'coin', 'total_draw_count'];
|
||||
$info = [];
|
||||
@@ -108,7 +108,7 @@ class UserController extends OpenController
|
||||
$userId = UserLogic::getUserIdFromRequest($request) ?? 0;
|
||||
$user = UserLogic::getCachedUser($userId);
|
||||
if (empty($user)) {
|
||||
return $this->fail('用户不存在', ReturnCode::EMPTY_PARAMS);
|
||||
return $this->fail('用户不存在', ReturnCode::NOT_FOUND);
|
||||
}
|
||||
$coin = $user['coin'] ?? 0;
|
||||
if (is_string($coin) && is_numeric($coin)) {
|
||||
|
||||
@@ -37,23 +37,23 @@ class CheckAuthTokenMiddleware implements MiddlewareInterface
|
||||
|
||||
$token = $this->getAuthTokenFromRequest($request);
|
||||
if ($token === '') {
|
||||
throw new ApiException('请携带 auth-token', ReturnCode::MISSING_TOKEN);
|
||||
throw new ApiException('请携带 auth-token', ReturnCode::UNAUTHORIZED);
|
||||
}
|
||||
|
||||
if (!$this->looksLikeJwt($token)) {
|
||||
throw new ApiException('auth-token 格式无效', ReturnCode::TOKEN_TIMEOUT);
|
||||
throw new ApiException('auth-token 格式无效', ReturnCode::TOKEN_INVALID);
|
||||
}
|
||||
|
||||
$decoded = $this->verifyAuthToken($token);
|
||||
$extend = $decoded['extend'] ?? [];
|
||||
if (($extend['plat'] ?? '') !== 'api') {
|
||||
throw new ApiException('auth-token 无效(非 API 凭证)', ReturnCode::TOKEN_TIMEOUT);
|
||||
throw new ApiException('auth-token 无效(非 API 凭证)', ReturnCode::TOKEN_INVALID);
|
||||
}
|
||||
|
||||
// 同一设备只允许一个 auth-token 生效,非当前 token 视为已失效
|
||||
$device = (string) ($extend['device'] ?? '');
|
||||
if ($device !== '' && !AuthTokenCache::isCurrentToken($device, $token)) {
|
||||
throw new ApiException('auth-token 已失效(该设备已签发新凭证,请使用新 auth-token)', ReturnCode::TOKEN_TIMEOUT);
|
||||
throw new ApiException('auth-token 已失效(该设备已签发新凭证,请使用新 auth-token)', ReturnCode::TOKEN_INVALID);
|
||||
}
|
||||
|
||||
return $handler($request);
|
||||
@@ -87,13 +87,13 @@ class CheckAuthTokenMiddleware implements MiddlewareInterface
|
||||
return JwtToken::verify(1, $token);
|
||||
} catch (JwtTokenExpiredException $e) {
|
||||
Log::error('auth-token 已过期, 报错信息' . $e);
|
||||
throw new ApiException('auth-token 已过期', ReturnCode::TOKEN_TIMEOUT);
|
||||
throw new ApiException('auth-token 已过期', ReturnCode::TOKEN_INVALID);
|
||||
} catch (JwtTokenException $e) {
|
||||
Log::error('auth-token 无效, 报错信息' . $e);
|
||||
throw new ApiException($e->getMessage() ?: 'auth-token 无效', ReturnCode::TOKEN_TIMEOUT);
|
||||
throw new ApiException($e->getMessage() ?: 'auth-token 无效', ReturnCode::TOKEN_INVALID);
|
||||
} catch (\Throwable $e) {
|
||||
Log::error('auth-token 校验失败, 报错信息' . $e);
|
||||
throw new ApiException('auth-token 校验失败', ReturnCode::TOKEN_TIMEOUT);
|
||||
throw new ApiException('auth-token 校验失败', ReturnCode::TOKEN_INVALID);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,12 +26,12 @@ class CheckUserTokenMiddleware implements MiddlewareInterface
|
||||
}
|
||||
}
|
||||
if (empty($token)) {
|
||||
throw new ApiException('请携带 user-token', ReturnCode::MISSING_TOKEN);
|
||||
throw new ApiException('请携带 user-token', ReturnCode::UNAUTHORIZED);
|
||||
}
|
||||
|
||||
$userId = UserLogic::getUserIdFromToken($token);
|
||||
if ($userId === null) {
|
||||
throw new ApiException('user-token 无效或已过期', ReturnCode::TOKEN_TIMEOUT);
|
||||
throw new ApiException('user-token 无效或已过期', ReturnCode::TOKEN_INVALID);
|
||||
}
|
||||
|
||||
$request->user_id = $userId;
|
||||
|
||||
@@ -4,19 +4,32 @@ declare(strict_types=1);
|
||||
namespace app\api\util;
|
||||
|
||||
/**
|
||||
* API 状态码统一管理
|
||||
* API 统一状态码
|
||||
* 与 HTTP 语义对齐,便于前端与网关处理
|
||||
*/
|
||||
class ReturnCode
|
||||
{
|
||||
/** 200 成功 */
|
||||
public const SUCCESS = 200;
|
||||
|
||||
/** 201 请携带 token(auth-token / user-token) */
|
||||
public const MISSING_TOKEN = 201;
|
||||
/** 400 请求参数错误(缺少参数、参数无效、格式错误等) */
|
||||
public const PARAMS_ERROR = 400;
|
||||
|
||||
/** 202 缺少参数 / 参数错误 / 业务校验不通过(如余额不足、购买抽奖券错误等) */
|
||||
public const EMPTY_PARAMS = 202;
|
||||
/** 401 未授权(未携带 auth-token 或 user-token) */
|
||||
public const UNAUTHORIZED = 401;
|
||||
|
||||
/** 203 token 过期或无效(auth-token / user-token 过期、缓存已过期等) */
|
||||
public const TOKEN_TIMEOUT = 203;
|
||||
/** 402 token 无效或已过期(格式无效、签名错误、过期、非当前有效 token 等) */
|
||||
public const TOKEN_INVALID = 402;
|
||||
|
||||
/** 403 鉴权失败(密钥错误、签名验证失败等) */
|
||||
public const FORBIDDEN = 403;
|
||||
|
||||
/** 404 资源不存在(用户不存在等) */
|
||||
public const NOT_FOUND = 404;
|
||||
|
||||
/** 422 业务逻辑错误(余额不足、购买失败、业务校验不通过等) */
|
||||
public const BUSINESS_ERROR = 422;
|
||||
|
||||
/** 500 服务器内部错误 */
|
||||
public const SERVER_ERROR = 500;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user