normalizePath($request->path()); if ($path === '') { return; } $noInsert = config('nl.log.no_insert', []); if (is_array($noInsert)) { $full = 'api/' . $path; if (in_array($path, $noInsert, true) || in_array($full, $noInsert, true) || in_array('/' . $full, $noInsert, true) ) { return; } } $methodCode = $this->mapMethod($request->method()); $endpoint = ApiEndpointModel::where('url', $path) ->where('deleted_at', 0) ->where('status', 1) ->where('is_log', 1) ->where(function ($q) use ($methodCode) { $q->where('method', 0)->orWhere('method', $methodCode); }) ->orderByDesc('method') ->first(); if (!$endpoint) { return; } $userId = $this->resolveUserId($request); $body = $response->getContent(); $result = json_decode((string) $body, true); if (!is_array($result)) { $result = ['raw' => mb_substr((string) $body, 0, 2000)]; } $code = $result['code'] ?? null; $type = ((int) $code === 0) ? 0 : 1; $ua = UserAgentService::getInstance(); ApiOpLogModel::insert([ 'user_id' => $userId, 'url' => $path, 'method' => $methodCode, 'controller' => (string) ($endpoint->controller ?? ''), 'ip' => (string) get_ip(), 'param' => json_encode($this->collectParams($request), JSON_UNESCAPED_UNICODE), 'result' => json_encode($result, JSON_UNESCAPED_UNICODE), 'type' => $type, 'result_code' => (string) ($code ?? ''), 'platform_type' => 0, 'belong_id' => 0, 'user_type' => 0, 'equipment' => $ua->parseEquipment(), 'browser' => $ua->parseBrowser(), 'created_at' => time(), ]); } catch (\Throwable $e) { // 日志失败不影响主流程 } } /** * 规范化路径:去掉 api/ 前缀 */ private function normalizePath(string $path): string { $path = trim($path, '/'); if (str_starts_with($path, 'api/')) { $path = substr($path, 4); } return trim($path, '/'); } /** * HTTP 方法映射:GET=1 POST=2 其他=0 */ private function mapMethod(string $method): int { return match (strtoupper($method)) { 'GET' => 1, 'POST' => 2, default => 0, }; } /** * 从 Bearer JWT 解析 user_id;失败返回 0(不抛鉴权异常) */ private function resolveUserId(Request $request): int { try { $token = $request->bearerToken(); if (empty($token)) { return 0; } $secret = (string) config('nl.jwt.secret', ''); if (strlen($secret) < 32) { $secret = hash('sha256', $secret !== '' ? $secret : 'nl_admin_jwt_fallback_secret'); } $decoded = JWT::decode($token, new Key($secret, 'HS256')); return (int) ($decoded->data->id ?? 0); } catch (\Throwable $e) { return 0; } } /** * 收集请求参数并脱敏密码类字段 * * @return array */ private function collectParams(Request $request): array { $all = array_merge($request->query(), $request->request->all()); $maskKeys = [ 'password', 'old_password', 'new_password', 'confirm_password', 'access_key', 'secret_key', 'api_key', 'token', ]; foreach ($maskKeys as $k) { if (array_key_exists($k, $all) && $all[$k] !== '' && $all[$k] !== null) { $all[$k] = '******'; } } return $all; } }