3000, 'H0' => 3000, 'QTY' => 1] * @param int $tenantId 테넌트 ID * @return array 성공 시 API 응답, 실패 시 ['success' => false, 'error' => '...'] */ public function calculateBom(string $finishedGoodsCode, array $variables, int $tenantId): array { try { $apiKey = config('api-explorer.default_environments.0.api_key') ?: env('FLOW_TESTER_API_KEY', ''); // Bearer token: ApiTokenService로 세션 토큰 확인, 만료 시 재발급 $bearerToken = $this->resolveApiToken($tenantId); $headers = [ 'Host' => 'api.sam.kr', 'Accept' => 'application/json', 'Content-Type' => 'application/json', 'X-API-KEY' => $apiKey, 'X-TENANT-ID' => (string) $tenantId, ]; $http = Http::timeout(30)->withoutVerifying()->withHeaders($headers); if ($bearerToken) { $http = $http->withToken($bearerToken); } // API의 QuoteBomCalculateRequest는 W0, H0, QTY 등을 최상위 레벨에서 기대 $payload = array_merge( ['finished_goods_code' => $finishedGoodsCode], $variables // W0, H0, QTY 등을 풀어서 전송 ); $response = $http->post('https://nginx/api/v1/quotes/calculate/bom', $payload); if ($response->successful()) { $json = $response->json(); // ApiResponse::handle()는 {success, message, data} 구조로 래핑 return $json['data'] ?? $json; } Log::warning('FormulaApiService: API 호출 실패', [ 'status' => $response->status(), 'body' => $response->body(), 'code' => $finishedGoodsCode, ]); return [ 'success' => false, 'error' => 'API 응답 오류: HTTP ' . $response->status(), ]; } catch (\Exception $e) { Log::error('FormulaApiService: 예외 발생', [ 'message' => $e->getMessage(), 'code' => $finishedGoodsCode, ]); return [ 'success' => false, 'error' => '수식 계산 서버 연결 실패: ' . $e->getMessage(), ]; } } /** * API Bearer token 확보 (세션 토큰 → 만료/미존재 시 재발급) */ private function resolveApiToken(int $tenantId): ?string { $tokenService = new ApiTokenService; // 세션에 유효한 토큰이 있으면 사용 if (! $tokenService->isTokenExpired()) { return $tokenService->getSessionToken(); } // 토큰 만료 또는 미존재 → 교환 시도 $userId = auth()->id(); if (! $userId) { Log::warning('[FormulaApiService] 인증된 사용자 없음 - API 토큰 교환 불가'); return null; } $result = $tokenService->exchangeToken($userId, $tenantId); if ($result['success']) { $tokenService->storeTokenInSession( $result['data']['access_token'], $result['data']['expires_in'] ); return $result['data']['access_token']; } Log::warning('[FormulaApiService] API 토큰 교환 실패', [ 'error' => $result['error'] ?? '', ]); return null; } }