UNPKG

opendata-api

Version:

정책자금, 서민대출 등 공공데이터 API 래퍼

284 lines (281 loc) 11.9 kB
// src/opendata-api.ts import axios from "axios"; import { XMLParser } from "fast-xml-parser"; import iconv from "iconv-lite"; import util2 from "util"; // src/opendata-util.ts import util from "util"; var OpendataUtil = class { /** * 현재 한국 기준 연도, 월, 일과 yyyymmdd 형식을 반환합니다. * @returns {{ year: string, month: string, day: string, yyyymmdd: string }} */ static getKoreanDateInfo() { const now = /* @__PURE__ */ new Date(); const utc = now.getTime() + now.getTimezoneOffset() * 6e4; const koreaTime = new Date(utc + 9 * 60 * 6e4); const year = koreaTime.getFullYear().toString(); const month = (koreaTime.getMonth() + 1).toString().padStart(2, "0"); const day = koreaTime.getDate().toString().padStart(2, "0"); return { year, month, day, yyyymmdd: `${year}${month}${day}` }; } static unwrapIfWrapped(payload) { var _a, _b, _c; if (payload && typeof payload === "object" && "data" in payload) { return payload.data; } if ((_c = (_b = (_a = payload == null ? void 0 : payload.response) == null ? void 0 : _a.body) == null ? void 0 : _b.items) == null ? void 0 : _c.item) { return payload.response.body.items.item; } return payload; } static extractFromXml(xmlObj) { var _a, _b, _c; const items = (_c = (_b = (_a = xmlObj == null ? void 0 : xmlObj.response) == null ? void 0 : _a.body) == null ? void 0 : _b.items) == null ? void 0 : _c.item; if (items) return items; throw new Error(util.inspect(xmlObj, { depth: null })); } }; var opendata_util_default = OpendataUtil; // src/opendata-api.ts var OpenAPIClass = class { /** * OpenAPI 인스턴스를 생성합니다. * @param serviceKey 공공데이터 포털에서 발급받은 서비스 키 */ constructor(serviceKey) { this.serviceKey = serviceKey; } /** * 지원사업 공고 정보를 조회합니다. * * @param {string} [supt_biz_clsfc] 지원 분야 (선택 사항, 미입력 시 전체 조회) * @returns {Promise<SupportProjectApiResponse>} 지원사업 공고 정보 * * @typedef {Object} SupportProjectApiResponse * @property {number} currentCount 현재 카운트 * @property {SupportProjectApi_SuccessResponseType[]} data 지원사업 공고 목록 * * @typedef {Object} SupportProjectApi_SuccessResponseType * @property {string|null} aply_excl_trgt_ctnt 신청 제외 대상 내용 * @property {string|null} aply_mthd_eml_rcpt_istc 이메일 접수 방식 * @property {string|null} aply_mthd_etc_istc 기타 접수 방식 * @property {string|null} aply_mthd_fax_rcpt_istc 팩스 접수 방식 * @property {string|null} aply_mthd_onli_rcpt_istc 온라인 접수 방식 * @property {string|null} aply_mthd_pssr_rcpt_istc 우편 접수 방식 * @property {string|null} aply_mthd_vst_rcpt_istc 방문 접수 방식 * @property {string} aply_trgt 신청 대상 * @property {string} aply_trgt_ctnt 신청 대상 내용 * @property {string|null} biz_aply_url 사업 신청 URL * @property {string} biz_enyy 사업 경영 연한 * @property {string} biz_gdnc_url 사업 안내 URL * @property {string} biz_pbanc_nm 사업 공고명 * @property {string} biz_prch_dprt_nm 사업 주관 부서명 * @property {string} biz_trgt_age 사업 대상 연령 * @property {string} detl_pg_url 상세 페이지 URL * @property {number} id 고유 ID * @property {string} intg_pbanc_biz_nm 통합공고 사업명 * @property {string} intg_pbanc_yn 통합공고 여부 * @property {string} pbanc_ctnt 공고 내용 * @property {string} pbanc_ntrp_nm 공고 기업명 * @property {string} pbanc_rcpt_bgng_dt 접수 시작일 (YYYYMMDD) * @property {string} pbanc_rcpt_end_dt 접수 종료일 (YYYYMMDD) * @property {number} pbanc_sn 공고 일련번호 * @property {string} prch_cnpl_no 연락처 * @property {string|null} prfn_matr 제출 서류 * @property {string} rcrt_prgs_yn 모집 진행 여부 * @property {string} sprv_inst 주관 기관 * @property {string} supt_biz_clsfc 지원사업 분류 * @property {string} supt_regin 지원 지역 */ async getSupportBizInfoList(supt_biz_clsfc = "") { const { yyyymmdd } = opendata_util_default.getKoreanDateInfo(); const url = `https://apis.data.go.kr/B552735/kisedKstartupService01/getAnnouncementInformation01?serviceKey=${this.serviceKey}&page=1&perPage=10000&cond[supt_regin::LIKE]=${supt_biz_clsfc}&cond[pbanc_rcpt_bgng_dt::GTE]=${yyyymmdd}&cond[rcrt_prgs_yn::EQ]=Y&returnType=json`; return this.fetchAndExtract(url); } /** * 통합공고 지원사업 정보를 조회합니다. * * @returns {Promise<IntegratedApiResponse>} 통합공고 지원사업 정보 * * @typedef {Object} IntegratedApiResponse * @property {number} currentCount 현재 카운트 * @property {IntegratedApi_SuccessResponseType[]} data 지원사업 목록 * * @typedef {Object} IntegratedApi_SuccessResponseType * @property {string} biz_category_cd 사업 카테고리 코드 * @property {string} biz_supt_bdgt_info 예산현황 및 지원규모 * @property {string} biz_supt_ctnt 지원 내용 * @property {string} biz_supt_trgt_info 지원 대상 정보 * @property {number} biz_yr 사업 연도 * @property {string} detl_pg_url 상세 페이지 URL * @property {number} id 고유 ID * @property {string} supt_biz_chrct 지원사업 특성 * @property {string} supt_biz_intrd_info 지원사업 소개 * @property {string} supt_biz_titl_nm 지원사업 제목 */ async getIntegratedSupportInfoList() { const { year } = opendata_util_default.getKoreanDateInfo(); const url = `https://apis.data.go.kr/B552735/kisedKstartupService01/getBusinessInformation01?serviceKey=${this.serviceKey}&page=1&perPage=10000&returnType=json&cond[biz_yr::EQ]=${year}`; return this.fetchAndExtract(url); } /** * 서민 대출상품한눈에 정보조회 서비스 * @returns {Promise<LoanApiResponse[]>} 서민 대출상품 목록 * * @typedef {Object} LoanApiResponse * @property {number} seq * @property {string} finprdnm 금융상품명 * @property {number} lnlmt 대출한도 * @property {string} lnlmt1000abnml * @property {string} lnlmt2000abnml * @property {string} lnlmt3000abnml * @property {string} lnlmt5000abnml * @property {string} lnlmt10000abnml * @property {string} irtCtg 금리 구분 * @property {string} irt 금리 * @property {string} maxtotlntrm 최대 총 대출기간 * @property {string} maxdfrmtrm 최대 거치기간 * @property {string} maxrdpttrm 최대 상환기간 * @property {string} rdptmthd 상환 방법 * @property {string} usge 용도 * @property {string} trgt 대상 * @property {string} instCtg 기관 구분 * @property {string} ofrinstnm 제공 기관명 * @property {string} rsdAreaPamtEqltIstm * @property {string} suprtgtdtlcond 지원 대상 상세 조건 * @property {string} age 나이 조건 * @property {string} age39blw * @property {string} age40abnml * @property {string} age60abnml * @property {string} incm 소득 조건 * @property {string} incmcndy * @property {string} incmcndn * @property {string} incmcnd * @property {string} rsdarea 거주 지역 * @property {string} crdtsc 신용 점수 조건 * @property {string} crdtsc1 * @property {string} crdtsc2 * @property {string} crdtsc3 * @property {string} crdtsc4 * @property {string} crdtsc5 * @property {string} crdtsc6 * @property {string} crdtsc7 * @property {string} crdtsc8 * @property {string} crdtsc9 * @property {string} crdtsc0 * @property {string} anin * @property {string} housholdcnt * @property {string} housar * @property {string} lntgthous * @property {string} rfrccnpl 참조 연락처 * @property {string} grninst 보증 기관 * @property {string} jnmthd 접수 방법 * @property {string} rpymdcfe 상환 수수료 * @property {string} lnicdcst 대출 비용 * @property {string} ovitryr 초과 이자율 * @property {string} prftaddirtcond 추가 혜택 조건 * @property {string} etcrefsbjc 기타 참고사항 * @property {string} hdlinst 주관 기관 * @property {string} cnpl 연락처 * @property {string} rltsite 관련 사이트 * @property {string} crdtsc15 * @property {string} crdtsc60 * @property {string} tgtFltr 대상 필터 * @property {string} hdlinstdtlvw 주관 기관 상세 보기 * @property {string} prdCtg 상품 카테고리 * @property {string} prdoprprid 상품 운영 기간 * @property {string} kinfaprdyn 기간 무관 여부 * @property {string} kinfaprdetc 기간 무관 상세 */ async getAffordableLoanInfoList() { const url = `https://apis.data.go.kr/B553701/LoanProductSearchingInfo/LoanProductSearchingInfo/getLoanProductSearchingInfo?serviceKey=${this.serviceKey}&pageNo=1&numOfRows=10000&type=json`; return this._fetchAndExtract(url); } /** * 공통 fetch 및 응답 처리 로직 * @param {string} url 요청 URL * @returns {Promise<any>} 응답 데이터 */ async fetchAndExtract(url) { var _a; try { const res = await axios.get(url); if ((_a = res == null ? void 0 : res.data) == null ? void 0 : _a.data) { return res.data.data; } const parser = new XMLParser({ ignoreAttributes: false, trimValues: true }); const xmlObj = parser.parse(res.data); throw new Error(util2.inspect(xmlObj, { depth: null })); } catch (error) { if (axios.isAxiosError(error)) { throw new Error(`Network Error: ${error.message}`); } throw error; } } /** * 공통 fetch 및 응답 처리 로직 (EUC-KR 대응) * @param url 요청 URL * @returns 응답 데이터 */ async _fetchAndExtract(url) { var _a, _b, _c, _d; try { const res = await axios.get(url, { responseType: "arraybuffer", // 원본 바이트 decompress: true, timeout: 3e4, headers: { Accept: "application/json, text/plain, */*" } // transformResponse: [(d) => d], // (선택) axios의 자동 파싱 완전 차단 }); const buf = Buffer.from(res.data); const contentType = String(res.headers["content-type"] || "").toLowerCase(); let textUtf8 = null; try { textUtf8 = buf.toString("utf-8"); return opendata_util_default.unwrapIfWrapped(JSON.parse(textUtf8)); } catch (_) { } let textKr = null; try { const charset = (((_a = contentType.match(/charset=([^;]+)/i)) == null ? void 0 : _a[1]) || "").toLowerCase(); const guess = charset && charset !== "utf-8" ? charset : "euc-kr"; textKr = iconv.decode(buf, guess); return opendata_util_default.unwrapIfWrapped(JSON.parse(textKr)); } catch (_) { } const parser = new XMLParser({ ignoreAttributes: false, trimValues: true }); try { const xmlObj = parser.parse(textUtf8 != null ? textUtf8 : buf.toString("utf-8")); return opendata_util_default.extractFromXml(xmlObj); } catch (_) { const xmlObj = parser.parse(textKr != null ? textKr : iconv.decode(buf, "euc-kr")); return opendata_util_default.extractFromXml(xmlObj); } } catch (error) { if ((_c = (_b = axios).isAxiosError) == null ? void 0 : _c.call(_b, error)) { const status = (_d = error.response) == null ? void 0 : _d.status; throw new Error(`Network Error${status ? ` (${status})` : ""}: ${error.message}`); } throw error; } } }; export { OpenAPIClass, opendata_util_default as OpendataUtil };