// 환경 변수 const SEDP_API_BASE_URL = process.env.SEDP_API_BASE_URL || 'http://sedpwebapi.ship.samsung.co.kr/api'; const SEDP_API_USER_ID = process.env.SEDP_API_USER_ID || 'EVCPUSER'; const SEDP_API_PASSWORD = process.env.SEDP_API_PASSWORD || 'evcpusr@2025'; /** * SEDP API에서 인증 토큰을 가져옵니다. * 매 호출 시마다 새로운 토큰을 발급받습니다. */ export async function getSEDPToken(): Promise { try { const response = await fetch( `${SEDP_API_BASE_URL}/Security/RequestTokenWithMembership`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'accept': '*/*' }, body: JSON.stringify({ UserID: SEDP_API_USER_ID, Password: SEDP_API_PASSWORD }) } ); if (!response.ok) { throw new Error(`SEDP 토큰 요청 실패: ${response.status} ${response.statusText}`); } // 응답이 직접 토큰 문자열인 경우 const tokenData = await response.text(); // 응답이 JSON 형식이면 파싱 try { const jsonData = JSON.parse(tokenData); if (typeof jsonData === 'string') { return jsonData; // JSON 문자열이지만 내용물이 토큰 문자열인 경우 } else if (jsonData.Token) { return jsonData.Token; // { Token: "..." } 형태인 경우 } else { console.warn('예상치 못한 토큰 응답 형식:', jsonData); // 가장 가능성 있는 필드를 찾아봄 for (const key of ['token', 'accessToken', 'access_token', 'Token', 'jwt']) { if (jsonData[key]) return jsonData[key]; } // 그래도 없으면 문자열로 변환 return JSON.stringify(jsonData); } } catch (e) { // 파싱 실패 = 응답이 JSON이 아닌 순수 토큰 문자열 return tokenData.trim(); } } catch (error) { console.error('SEDP 토큰 가져오기 실패:', error); throw error; } } /** * SEDP API에 인증된 요청을 보냅니다. */ export async function fetchSEDP(endpoint: string, options: RequestInit = {}): Promise { try { // 토큰 가져오기 const token = await getSEDPToken(); // 헤더 준비 const headers = { 'Content-Type': 'application/json', 'accept': '*/*', 'ApiKey': token, ...(options.headers || {}) }; // 요청 보내기 const response = await fetch(`${SEDP_API_BASE_URL}${endpoint}`, { ...options, headers }); if (!response.ok) { throw new Error(`SEDP API 요청 실패 (${endpoint}): ${response.status} ${response.statusText}`); } return response.json(); } catch (error) { console.error(`SEDP API 오류 (${endpoint}):`, error); throw error; } }