* 即可调用,与存客宝内部接口完全兼容。 */ class OpenAuthController extends Controller { /** * 获取 JWT Token * POST /v1/open/auth/token * * 请求参数: * apiKey - 账号专属 API Key(ck_users.apiKey) * account - 登录账号(ck_users.account),参与签名 * timestamp - 秒级时间戳 * sign - 签名值,算法见签名文档 * * 成功响应: * { code: 200, message: "success", data: { token: "xxx", expires_in: 7200 } } */ public function getToken() { try { $params = $this->request->param(); // ── 1. 必填参数校验 ───────────────────────────────────────── if (empty($params['apiKey'])) { return $this->fail('apiKey不能为空', 400); } if (empty($params['account'])) { return $this->fail('account不能为空', 400); } if (empty($params['sign'])) { return $this->fail('sign不能为空', 400); } if (empty($params['timestamp'])) { return $this->fail('timestamp不能为空', 400); } // ── 2. 时间戳时效校验(±5 分钟)────────────────────────────── if (abs(time() - intval($params['timestamp'])) > 300) { return $this->fail('请求已过期', 400); } // ── 3. 用 apiKey 找账号,并校验 account 一致性 ─────────────── $user = UserApiKeyService::findUserByKey($params['apiKey']); if (!$user) { return $this->fail('无效的apiKey', 401); } if ($user['account'] !== $params['account']) { return $this->fail('无效的apiKey', 401); } // ── 4. 验签(account + timestamp + apiKey)──────────────────── if (!UserApiKeyService::validateSign( $params['account'], (string)$params['timestamp'], $params['apiKey'], $params['sign'] )) { return $this->fail('签名验证失败', 401); } // ── 5. 签发 JWT(2 小时有效期)──────────────────────────────── $expireSeconds = 7200; $token = JwtUtil::createToken([ 'id' => (int)$user['id'], 'account' => $user['account'] ?? '', 'username' => $user['username'] ?? '', 'phone' => $user['phone'] ?? '', 'companyId' => (int)$user['companyId'], 'typeId' => (int)$user['typeId'], 'isAdmin' => (int)($user['isAdmin'] ?? 0), 'via' => 'open_api', // 标记来源,方便日志区分 ], $expireSeconds); Log::info('[OpenAuth] 对外接口登录成功', [ 'userId' => $user['id'], 'account' => $user['account'], 'ip' => $this->request->ip(), ]); return json([ 'code' => 200, 'message' => 'success', 'data' => [ 'token' => $token, 'expires_in' => $expireSeconds, ], ]); } catch (\Exception $e) { Log::error('[OpenAuth] getToken 异常:' . $e->getMessage()); return $this->fail('系统错误: ' . $e->getMessage(), 500); } } private function fail(string $message, int $code = 400) { return json(['code' => $code, 'message' => $message, 'data' => null]); } }