From 23da9cda15aed4237e114b07d6ce893bd84be18f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=9C=EC=98=A8=ED=8C=8C=ED=8C=8C?= Date: Sun, 6 Mar 2022 14:36:02 +0900 Subject: [PATCH] =?UTF-8?q?=EC=A3=BC=EB=AF=BC=EB=B2=88=ED=98=B8=20CI=20?= =?UTF-8?q?=EB=B3=80=ED=99=98=20=EC=8B=9C=EC=8A=A4=ED=85=9C=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=EA=B5=AC=ED=98=84=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 13 + libs/VNOInterop.jar | Bin 0 -> 7424 bytes .../java/cokr/xit/ci/IndexController.java | 21 ++ src/main/java/cokr/xit/ci/api/code/ErrCd.java | 58 ++++ .../cokr/xit/ci/api/model/ResponseVO.java | 15 + .../ci/api/presentation/NiceCiController.java | 48 +++ .../xit/ci/api/service/NiceCiService.java | 111 ++++++ .../xit/ci/api/service/suport/Interop.java | 97 ++++++ src/main/resources/application.properties | 1 - src/main/resources/application.yml | 36 ++ src/main/webapp/WEB-INF/jsp/index.jsp | 326 ++++++++++++++++++ src/main/webapp/WEB-INF/jsp/nav.jsp | 24 ++ .../resource/css/file-drag-and-drop.css | 18 + src/main/webapp/resource/css/style.css | 31 ++ .../webapp/resource/js/file-drag-and-drop.js | 73 ++++ 15 files changed, 871 insertions(+), 1 deletion(-) create mode 100644 libs/VNOInterop.jar create mode 100644 src/main/java/cokr/xit/ci/IndexController.java create mode 100644 src/main/java/cokr/xit/ci/api/code/ErrCd.java create mode 100644 src/main/java/cokr/xit/ci/api/model/ResponseVO.java create mode 100644 src/main/java/cokr/xit/ci/api/presentation/NiceCiController.java create mode 100644 src/main/java/cokr/xit/ci/api/service/NiceCiService.java create mode 100644 src/main/java/cokr/xit/ci/api/service/suport/Interop.java delete mode 100644 src/main/resources/application.properties create mode 100644 src/main/resources/application.yml create mode 100644 src/main/webapp/WEB-INF/jsp/index.jsp create mode 100644 src/main/webapp/WEB-INF/jsp/nav.jsp create mode 100644 src/main/webapp/resource/css/file-drag-and-drop.css create mode 100644 src/main/webapp/resource/css/style.css create mode 100644 src/main/webapp/resource/js/file-drag-and-drop.js diff --git a/build.gradle b/build.gradle index d6c4770..09af3be 100644 --- a/build.gradle +++ b/build.gradle @@ -21,10 +21,23 @@ repositories { dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-devtools' + implementation 'org.apache.tomcat.embed:tomcat-embed-jasper' + compileOnly 'org.projectlombok:lombok' + annotationProcessor 'org.projectlombok:lombok' + providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat' + testImplementation 'org.springframework.boot:spring-boot-starter-test' + + + /* =================================================================================== */ + /* External Jar.. */ + /* =================================================================================== */ + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation 'com.google.code.gson:gson:2.9.0' } tasks.named('test') { diff --git a/libs/VNOInterop.jar b/libs/VNOInterop.jar new file mode 100644 index 0000000000000000000000000000000000000000..d46f04b5cc21bf8ad40a9b95402a626680c4d773 GIT binary patch literal 7424 zcmZ{pbx@p5w#IRSy95secM0z9?h-7x69@#i;DZnDI=H(9hY2JMo)Fw6zzj|Xa+BS? z`+d80@9BEGx~rb2`<(O7TU|eGHDnZGglE5pM5v}F!ruY|0R=%rL0^VbMN^Uc350dJKf19QM%S`-R@o%$+jHZgBf}TE?hT^5h^e1&SPA&+J8YkQ5=`XFi zJPZ7rd){2C8XPJb5Z@XUjO@ebW0bjUjwo6CtatWIWP4;rq*>+rr0o9tj3-VoZ>Tro zKN4YczSdLvea)ZmPa>HANa`-gN#!4le@%b#Ra4RXU4s_)U#gG(|5+>c-&BU0|5X07 zD`Nju7}b9%f2&p8eeAqFJh^OLt>3=wH^K1FSX`7mST`9^XPU}VVVXh+r+a4Il8SrSR`))(FroPaKs>|QQ%K;4)gA~~oac*H@V%}{{{Wgsp4o%~Q0rlg)H_Q&!tl4q!MU?$3n`3*N$ z`vhP;g^OVBs8%_11wdqwQ*P=5NC$4t3M=gB0}2Ek=ZVYNCudhGz$%7? zu4O^kc-HYi{#S+0WwM2pbZSFBi{23chYNLbSRAH3Yj*wq)RKP^U@gCl&Pb*(B8Z*L zQG8j^&K%^GIzA>?IKgbvJ*xPr+5Fih3CFB|i78W}c#U~E)CQ1c+`TZ)e94-rrzw)P z5NgQP3f1N6gitgzc~^{oa`j=GU^Q-lVz!U7QP%GRoihv!8#*9N4cgjeiZupkz7)$Y zec!-1V8;%?w?%{>-$5T;_Ff4dmkye}uLmIY;UX2)6i(hJZ(kPN(k;P*Q-HfTY}xCZJc~%#a!xGXm@(A-E3i$9z~2m8~hUjC*uG z4Pp0ah2_-zZWtn}gUP)s`?*!ilF$NBXt~~Io2@bmW>w6+ixsu>(DU%9D-zGzT-Vav z-CPYZGnqI4I!l+lCB+nI=k~r8B2xO3qqLUgGE>2~NY+S4Wa%tD)?LA5CmwXR6U)_c zu9V$f(-8vjOT0nmXent4`a!;zrw-loZEpwet%HtP^yV-dJ43z?CtH=C?GI>sD1>Sm z6mw4Qf+R;eXN+d|u-eE3q65T`ekAZTTO&K5Waw=9D-fjHvw$;=6l(#%D#e-1cURFJ z`ggJ+m2c#9POyAYkOvwr5>=ub_+|-RuSdWW<&?Q-p$UVwX7a$<{)OcO?i}=13QN57 zm8Pq%mSI{$CJIT8Ml-z=w+7Y`_;-+vAay2y9ZbQNXJjDw%E)Mmt>SYAnjJ)iafZa; z6FX)9jLWB*Wqn1{)~32>)$`owZ%wug&g_b^?cL2_v$*$cY{0oFHvrqoCko2t#aH?u zG@J>QR|`hZZIFVf3G(_it`#jY1f7qLFVJOc;mGQlW7OeE+N|l*g{_%W`nXwEjEmHW zp>CnK_Mwf-o!wXzKlefW*pY3gIBEy##GSF!aH8g)eGsZWWwTx>fdC}kR%R-88bL^y z?JhaSR;M(F%LK6(h~pOB^s(PMFMEYqhKlliKj-Y`#<%lxG0FQHjLf@pr+vE6bR}lt z0oeSL3%|N})e>p!L*R{3F54U{#q?b!=Tqiq&#s(&q7SaYD_?L1q+Oa;g*nKFmq@iS z8U(@mkCv;u0k1l`8>?y=M%ylG-5f{c50uOjBWWbpI>xO+JrY7qVnjcwxVW6uAiW6n zXkxbXZJp;nWEHbeT3$U;L=|H1G8l44?PTq;7%ISwCjMTw`MRet?)1u{=Zofsp66f$ zI`OGqljTq(CN2wk<cW_vK#EouwWkap(AGke1yxyQ$KRvwvyz03kB z?eFP!zre0<9?)RTDw4~Z3_kcKJnJSkP;s#$tw!FN#H5wuBCAo!5y_3uWEWgw!Il6f zBSV9gd)a|!i{mwzAKLe%{l989&gzIget2@Ok|K0RF?ns^SjBL~2eO9KXWn$S-v|D< z!j|~7%V+vij@lyC(4%Rd_E1=@K-=B$R-9tf#I()Q0Zc?~?+Lmyw2UwYS#~J&(d6 z&ctkB^-13s#C({Cf&sA9zqcvFY*~8Sz(8`K=rxHo@G*@L+CTaYVlwB(>_CpU}c(%#<2FQ5IO z_(6#z@c0n7gI-|X+19zd1J8aV?)LOWKlm~5zV}^#0d>BJnQRG-mW&MK`!>9E`~AJb z2dv8jGLkD))A$b5h#BhC#LMfgb#X77)l9cF+aIUn`G}z)D-F5!f^#|X`@k!4Z~wLu z-j%r{JcUk>fI(POM_qgSa2n> zGx|^)<;X*43-+en2lXdhThoHzG;%Db1mUx+GM&wwEa?}XWfMd z)Q8Z(mLQ4E5z-wl_LV}v{Tzq=_7?%~ANwt~Mm-eBB)(OAqjkh{gIZb857{5k(n0T= z;&&L}#lTR<10{o9nmyXD_Y>f?$x{^j&mf=&{N6=rG6fH zd(-6(JgOjcSjymn|IJ-Z&3Mf>J6}|*h=`qhvFOla!6L+E`LD%aHs+G8ut5v_Y+d;& z=GO%AZ*r-+aTRgOG{y@Aw-!Gb0ZjT0wM~1lCpPW1&rv*WXW7C&T^&3Yz0JDMe3Ts%$C*MTdEq87*4c3MqcHE~5uyym7mddzckfp8}S-kWHe zL#%s9O5%rW`rdx(wWr*qhK3}`5&sI&VRpd$8tK+$PO5L>YcwJ%!nzmLN~xB%lgo2Q zKd!4+OierP0zSz)kJgBE4Ywyv`mxx<+|IC0yy)tM3D~Yj+AqqSOS3|NTcAvyM_!G% zY$}Hz&!l2-egwyNEZ#_SZFMh2Z(R63mK286wJo1VGVqmJVr`zUkh(hQ-i&gdEGoy1 zizGc~k+3h$j#hyDeBu2gs%WY|o`D{3AN5y^p77@*`;jA-)t-l+__xBYJ)*;^tVA4W zA<__vEuOpesMO+Dlw=rvtKr;5KYZORiNn}lDg4?WP_7hXE{#&CdAlf&BT&##;sRY1 z2KZb{GF4L2VLXuTQrhn3(QQyMY#`k)k>9VT_)Sbkrg$Wz-bxQhC=MXQ3V2}_DKR#? zy)QP17(&ru{k*W(@C!DfacWP^qO@P(*= z=$Da{P<#g3Xt;7BTy8RXd{Qa`zC(V`JDEH&sU`iSk_gwEluAe~ih{qjrLLacYDK*h zC=V^cDWdmD4UAgh#7pr^Kz_OQ;DA24yCfwcZQuDch1k+{os5^VSRd*WCeZmbgc$$! z#Dj(|&rB*HYjFgU@9aHfnyG|pZJV{b0Vk!=c1?n3{EU=S^R!ZjEJ0?|O`Se_>bR|bH zgGkIw9*4yeC!Wiz7X8d@z7oeZxwUT1c`l;!vg!P3n@ils-GZ@oa-fr5vu{jc8xdgX zhoiWkdhL6?X7{hwU!7KRnB9$#&(gdPR}8Yf@Y=O_Xerc9zGp5=lB(4xQ;k3 z1(oLNz$nt-I5L3T#JZ%sUY@s-WA4N$--Z-LK3Y`7q4V{!ld4RBmV)X59Z)S5Oqn_? zmNIN4?MJP9ZC`#EtPHU(-+!w-)0q-6aoFoR#LPJm{8i?sKc=n<=u4-vG#WlGyDBr1 z&8O#;b&krFlrNrF5;=S0W$oMNnkHN`MiO_b(NK!sxZ9suyBM8}< z%JQ>gmP|`-^yEvWNorfP1OcVtXL~Gb>pEn0RRa2`CdO$68oO5fc68NMEkOGgMfVPf zc~TXjX7Pu7d6GIk3Fdjl{1(o9)n#wdwU1oiX3`y>pwVdz>(AtIz9N0WQ8w|3H@xYIIlKuzh=N31F7C>Uw8a;yLzk3SE!{QEhObIR z7E6UfPZmBYM+YN_MMAORLehzqCT76D#E&IJu|Y&?#t*-s!%x7EWqdZu`fOAerIach zBu|(50-qf}7Pz@9H3w-jo0;D_Rgw2D@xqBV(a$utiyJTOlFLYD@B3(Lt0f+Ida7cj zMIV^9Qr61+HFeW#Gb_T9EinI7#a63F%pqz&fDpUp9b?#?eK+ApK)@wk#gDm_>Kt@d z#Ec&TS&nkW{tD}ZzRtydy^x7GPEP@lkgyI2v6ViQ!RR~_cJ-jQDXXCAFA{1#W zfrTg|*BD6#4EjG*0B4*eM%RZoX-Y;1-i)?H&T(UG%#!Oa>i4I!{E~DTCgvUNlue#`naT}Xl z!&Bql56D#nv_fn+b=9}xm*a_zy0(26*%b`*)sFGI85kIq5~&GxGC;hpp17(p%9n2r zi!$ub6p%Qpl->~3kDoj}FAK_C=K~KyISgQ~5RmE?5H)&T*=ry{G|cy9SK)MDu7G>7 zzk9j-jV@nfh5l=$oFFzkXh7}|r6Z|FxkwPj9_&c}n03-`YBmN0s94V_ClR_)ug?TmVlyJdlcQy|?p{q$Lr$ zV7KA^rGkA~G-e%Q08jiyA2QRJumPpq)`D01r*9CR!!|~l;eORnsfy3%VC)brd+1NT zEU8pfSunkfcOky_08b>BW!zjvophVbG=0#4a9R2L6bjwy=F7ZF4aQ8lw#p;Adg>Bi z8vN;M4P5Q%faLu-^T}`=-g3y@dKO#@gN1 z-qS*q9Sz!j(wJ~o#Vnpq;d~|q#LY}%1LV$Z;^*WR=7M7Ytfg+(B)}G*LtS<)W+We# zHCP#-8$JI4qKgAoj?<2ww?nq3SZLBsUAG>?>ZCW5T&1+Q1IhT@6Y+a4oOyB(M2Z)~ z4r?ZnkRulsfN?*Vp8Ju$a}{7+SMxS)(wHq`ZCPBtz%~Np(PswK9QRR(u9(_|orU%k_GiS;R$dxB`Bc87|$yctoA@z-S zJtlj5$gx#9UGpgik;~*Z}X=0KIMRXwj?vV^Y%isj0@^D z@PYbiuX9JhQx3N#Mh$lz@CNB*CnrL7*91e*_t0$+23AhK)i? zrIcPrNGcyQW>*zDs3k^u=T>gEvQ5NI7{7I@l)M#;|Fl51E@R)l96QWjxpQ7lq#PN@ z{j#+ywr<;IZcK>9!d#JmbkB!=m&%KT$shPSL0u?DeVkqD9^VbKs@fx4khVP2t5M5K zqUZM;nc~d88_UIqAjcjs!1UGDE;-<3w-Ts*G@83tW{&FV1)tbAacB&vUxm7hlVPDG z%_sZw#mmFm0>OF*J(bclF$t9z5LV3Ks;zH03sRSTK^z0IdXki|x&&9Pj=O|>zec?9 z!-XsM)>x$Tpi+W&?Act|^R}7hW4eMkb1zr)-9%O7tt(#G`-QtY-f{opkm~ENwsmg@ zzxz*+@AQELoE`LARMX1LJiDkM4VHQ?D!LYa<5!--pW`wP6v3DDd-q#>-yV_1UQEUF zy#pK#u$wDZD!%%>$5TVbcGEk#mojqYYm#Qers7+H|id+UV$?|roqS>ut@jl zs1KqpM^{8Wr^89Y1V;Ldfo6G>#gsnu$Q;v<9HTq!fWnlZH7k;ZDa^D_tf=pg`>S&z|}p)=W&Km?e3**)ElC3 z`GT(Ei^ASF1*`rr5$LyZD0QVrRC2HPVudq7RyBkF{o&DIUWm|W4?5WtQ8}feHa&*) za_$_6rU~1nPL=4$-SMi7F|+q5`bEHl6s7eHzC|>Fr(6D$2ku*WoOEG%U}0PD)V6Bi zX!=ukDxai~?)dNabTL~5k5{D09rFPOSo!zj`0@;Q_Jk}0v@@sJOaQAg?M13allEV^ zzJ!I;Ql*G#zoz2`ZX~vCpxkr4FA74~lew3>x6RN3JM3O62F8oWld0sI+h$aODHCB# z??+jZ!OMv-xBC)!wqah>l)b8Sj&rU}u3&(eghudYPo9_9nyQ!Z&Aa@hmtK@2qXii+ zq8&RvcBcEsk|xOMv(l6}Ls{wxq)Iurd5;OSW<|D{eNyk9Tf7L-#7nT8rQBxKB-6T_ z+BPz0EZjnaa(Iw@frj}Pejys%QX9nz0^V`DCv8Awp!C0t`$o0mHg@d%P#U|Xwi*30 zk~e`jJ^lt%grOu_u|lKi+ZxciyBL3+KF-$!=drhAz1wn7ZfNzLG$yp9Ek3ziBZz}& zlv$UoXoy>a563S0rN1SZs2qd0Nx5?Y|AW7X);EF#`EGI=uE=Y?ocQeWDbu4g9B)GS zS7Z;(%o9kjiT#wJ2sLl+i(VeEVGd{Klt`>W(s$NN{Q7Q~jY(`a$tQNZxIR*bjj$)7 zDO4EgQEKOuLabGFpHX3=aOTuw3stH)Qz%^)L!kl8s~eM`9yplc8++n>A8`fFYKmYW z-(fL?c6_JX$f6_|ncu7OPFI;EO*iPsb#0l+c-fh)YgaYJ*sHGh=A(d|dxda7!FsH@ zFS@5g^x99CAs*`=M36e{bYqq3cs^b&xC-^EvoXaiw7?` zFB0QouUM+z4;h-uTA<=1Z|g!=3ay_>(l3(wj5N>Fj?~}3nh5a(pZ9_lJC0hZVn-GTa zKW=vUGO};*D;^UM1ko!+I$`qcnnpy?>-LWV!PGn!QY6_WLWmX*0h=$^(DUm&&@>@t zVL1Wpo;7Fan)9n+CIMoeJp-uz5$lNgB}It&)qY4?3%y~jSMHmx5(v{vksn0@@Mh~h zQ1=h}KbrUBWmm<7-3LfDNpGO#*A`)LEOa6#Tp?ODhmd*}N|O1fy?(|4NeH{Vw%J4q zrtvHZA)GDCLLfW33{SX5{mA$rYgJu{EN;Sm(cpbvHT_2P*4j;KCMALS_d{|dkj0mF zM%v9Ax?9`VYy3#?Iyi_<^`Mr;%}6J}QsGFHgwaCbNQXgH4Zu=hD}MwcsBlSSv3Mh2 z{XKThok8{YX3a(Zi1$3i)CW$RR!N~0NFr&HcTwF_$X$UGMD4aKli{bsT({2m6n^UQ z3+oScgLC&==}{mc%yIvLU5H4;2>%J~{+G!8fp-5H|E6$%5Z>Rde~{hZ8QLFY_g6^# zUjEzqH-Pu&1WbhgpSAsU!uapyU*zpC*Z;-d{&JoE&Gk_ literal 0 HcmV?d00001 diff --git a/src/main/java/cokr/xit/ci/IndexController.java b/src/main/java/cokr/xit/ci/IndexController.java new file mode 100644 index 0000000..7efc53c --- /dev/null +++ b/src/main/java/cokr/xit/ci/IndexController.java @@ -0,0 +1,21 @@ +package cokr.xit.ci; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; + +@Slf4j +@Controller +@RequiredArgsConstructor +public class IndexController { + + @GetMapping("/") + public String index(){ + log.info("Welcome to the CI system"); + + return "index"; + } + + +} diff --git a/src/main/java/cokr/xit/ci/api/code/ErrCd.java b/src/main/java/cokr/xit/ci/api/code/ErrCd.java new file mode 100644 index 0000000..9906ad6 --- /dev/null +++ b/src/main/java/cokr/xit/ci/api/code/ErrCd.java @@ -0,0 +1,58 @@ +package cokr.xit.ci.api.code; + +public enum ErrCd { + + OK("정상") + + /* ======================================================================= + * 공통(4xx: Client, 5xx: Server, 6xx: LinkService, 9xx: Etc..) + ======================================================================= */ + //클라이언트 요청 오류 + , ERR401("필수 파라미터가 없습니다.") + , ERR402("파라미터 유효성 검증 오류") + , ERR403("잘못된 파라미터 입니다.") + , ERR404("일치하는 자료가 없습니다.") + , ERR405("잘못된 요청 값.") + , ERR411("잘못된 JSON 포맷 문자열") + //서버 오류 + , ERR501("HttpServer 오류") + , ERR502("HttpClient 오류") + , ERR503("RestClient 오류") + , ERR504("요청 데이터 Json 파싱 오류") + , ERR505("응답 데이터 Json 파싱 오류") + , ERR506("Hash 생성 오류") + , ERR511("JSON 형식으로 변환 실패") + , ERR520("통신오류") + , ERR521("방화벽 설정 오류") + //외부서비스 오류 + , ERR600("API서버 요청 오류") + , ERR601("API서버 응답 오류") + , ERR602("API서버 내부 오류") + , ERR603("유효하지 않은 토큰(OTT) 값") + , ERR610("응답 데이터에 필수값이 없음") + , ERR620("API Response Error") + //기타오류 + , ERR999("기타 오류") + , ERR901("권한 없음") + , ERR902("유효하지 않은 데이터") + , ERR903("처리 완료된 데이터") + ; + + + + + private final String code; //코드 + private final String codeNm; //코드명 + ErrCd(String codeNm) { + this.code = this.name(); + this.codeNm = codeNm; + } + + public String getCode() { + return this.code; + } + + public String getCodeNm() { + return this.codeNm; + } +} diff --git a/src/main/java/cokr/xit/ci/api/model/ResponseVO.java b/src/main/java/cokr/xit/ci/api/model/ResponseVO.java new file mode 100644 index 0000000..33f9200 --- /dev/null +++ b/src/main/java/cokr/xit/ci/api/model/ResponseVO.java @@ -0,0 +1,15 @@ +package cokr.xit.ci.api.model; + +import cokr.xit.ci.api.code.ErrCd; +import lombok.*; + +@Builder +@Getter +@ToString +@EqualsAndHashCode +public class ResponseVO { + private ErrCd errCode; + private String errMsg; + private Object resultInfo; + +} diff --git a/src/main/java/cokr/xit/ci/api/presentation/NiceCiController.java b/src/main/java/cokr/xit/ci/api/presentation/NiceCiController.java new file mode 100644 index 0000000..8c7fb46 --- /dev/null +++ b/src/main/java/cokr/xit/ci/api/presentation/NiceCiController.java @@ -0,0 +1,48 @@ +package cokr.xit.ci.api.presentation; + +import cokr.xit.ci.api.code.ErrCd; +import cokr.xit.ci.api.model.ResponseVO; +import cokr.xit.ci.api.service.NiceCiService; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.google.gson.Gson; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.ui.ModelMap; +import org.springframework.util.StringUtils; +import org.springframework.web.bind.annotation.*; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@RestController +@RequiredArgsConstructor +public class NiceCiController { + + private final NiceCiService diCiService; + + @Value("${nice.api.ci.site-code}") + private String SITE_CODE; + @Value("${nice.api.ci.site-pw}") + private String SITE_PW; + + @SuppressWarnings("deprecation") + @PostMapping("/nice/ci") +// public ResponseEntity ci(@RequestBody Map mParam) { + public ResponseEntity ci(@RequestBody String param) { + Gson gson = new Gson(); + List> params = gson.fromJson(param, ArrayList.class); + List jids = params.stream() + .map(row -> row.get("jid")) + .collect(Collectors.toList()); + + ResponseVO respVO = diCiService.findAllByJid(SITE_CODE, SITE_PW, jids); + + return new ResponseEntity(respVO, HttpStatus.OK); + } +} diff --git a/src/main/java/cokr/xit/ci/api/service/NiceCiService.java b/src/main/java/cokr/xit/ci/api/service/NiceCiService.java new file mode 100644 index 0000000..2cad255 --- /dev/null +++ b/src/main/java/cokr/xit/ci/api/service/NiceCiService.java @@ -0,0 +1,111 @@ +package cokr.xit.ci.api.service; + +import cokr.xit.ci.api.code.ErrCd; +import cokr.xit.ci.api.model.ResponseVO; +import cokr.xit.ci.api.service.suport.Interop; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; + +import java.io.IOException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@Slf4j +@Component +@RequiredArgsConstructor +public class NiceCiService { + + /** + * 주민번호로 CI를 취득 한다. + * -.CI: 연계정보(Connecting Information) + * -.국가표준 규격에 따라 사용자의 주민번호를 암호화한 개인 식별값. + * -.서비스에 상관없이 값이 일정 함. + * -.주민번호 -> 해쉬 -> CI 값 (88 byte) + * @param siteCode + * @param sitePw + * @param jids + * @return + */ + public ResponseVO findAllByJid(String siteCode, String sitePw, List jids) { + return ResponseVO.builder() + .errCode(ErrCd.OK) + .errMsg(ErrCd.OK.getCodeNm()) + .resultInfo( + jids.stream() +// jids.parallelStream() + .map(jid -> { + ResponseVO responseVO = null; + try { + /* ======================== + * validate + ======================== */ + if(StringUtils.isEmpty(siteCode)){ + responseVO = ResponseVO.builder().errCode(ErrCd.ERR401).errMsg("사이트코드(은)는 필수조건 입니다.").build(); + throw new RuntimeException(responseVO.getErrMsg()); + } + if(StringUtils.isEmpty(sitePw)){ + responseVO = ResponseVO.builder().errCode(ErrCd.ERR401).errMsg("사이트 패스워드(은)는 필수조건 입니다.").build(); + throw new RuntimeException(responseVO.getErrMsg()); + } + if(StringUtils.isEmpty(jid)){ + responseVO = ResponseVO.builder().errCode(ErrCd.ERR401).errMsg("서비스 구분값(주민번호:JID)(은)는 필수조건 입니다.").build(); + throw new RuntimeException(responseVO.getErrMsg()); + } + + /* ======================== + * api call + ======================== */ + responseVO = Interop.getCI(siteCode, sitePw, jid); + + } catch (Exception e){ + log.error(e.getMessage()); + } finally { + /* ======================== + * result set + ======================== */ + Map m = new HashMap<>(); + m.put("key", jid); + m.put("value", responseVO); + return m; + } + + }) + .collect(Collectors.toMap(m -> String.valueOf(m.get("key")), m -> m.get("value"), (k1, k2)->k1))) + .build(); + } + + + + /** + * sha256 암호화 + * @param text + * @return + * @throws IOException + * @throws NoSuchAlgorithmException + */ + public static String hexSha256(String text) throws IOException, NoSuchAlgorithmException{ + StringBuffer sbuf = new StringBuffer(); + + MessageDigest mDigest = MessageDigest.getInstance("SHA-256"); + mDigest.update(text.getBytes()); + + byte[] msgStr = mDigest.digest() ; + + for(int i=0; i < msgStr.length; i++){ + byte tmpStrByte = msgStr[i]; + String tmpEncTxt = Integer.toString((tmpStrByte & 0xff) + 0x100, 16).substring(1); + + sbuf.append(tmpEncTxt) ; + } + + return sbuf.toString(); + } + + +} diff --git a/src/main/java/cokr/xit/ci/api/service/suport/Interop.java b/src/main/java/cokr/xit/ci/api/service/suport/Interop.java new file mode 100644 index 0000000..6bb887c --- /dev/null +++ b/src/main/java/cokr/xit/ci/api/service/suport/Interop.java @@ -0,0 +1,97 @@ +package cokr.xit.ci.api.service.suport; + + +import KISINFO.VNO.VNOInterop; +import cokr.xit.ci.api.code.ErrCd; +import cokr.xit.ci.api.model.ResponseVO; + +public class Interop +{ + public Interop() + { + + } + + public static ResponseVO getCI(String siteCode, String sitePw, String jumin) { + + final String sSiteCode = siteCode; // NICE평가정보에서 발급한 서비스 사이트코드 + final String sSitePw = sitePw; // NICE평가정보에서 발급한 서비스 사이트패스워드 + final String sJumin = jumin.replaceAll("[^0-9]", ""); // 주민등록번호 13자리 + final String sFlag = "JID"; // 서비스 구분값 (JID:주민번호 이용) + + + + int iRtnCI = -1; + ErrCd errCode = null; + String errMsg = null; + String ci = null; + try { + // 모듈 객체 생성 + VNOInterop vnoInterop = new VNOInterop(); + + /* ──── CI 값을 추출하기 위한 부분 Start */ + // 인증요청처리 + iRtnCI = vnoInterop.fnRequestConnInfo(sSiteCode, sSitePw, sJumin, sFlag); + System.out.println("======================================================================="); + System.out.println("JID=" + sJumin); + System.out.println("iRtnCI=" + iRtnCI); + + // 인증결과코드에 따른 처리 + if (iRtnCI == 1) { + // CI 값 추출 (연계정보 확인값, 88Byte) + String sConnInfo = vnoInterop.getConnInfo(); + System.out.println("CONNINFO=[" + sConnInfo + "]"); + + // 결과설정 + errCode = ErrCd.OK; + errMsg = String.format("[%s]\n(응답코드 %s)", ErrCd.OK.getCodeNm(), iRtnCI); + ci = sConnInfo; + } else if (iRtnCI == 3) { + System.out.println("[사용자 정보와 서비스 구분값 매핑 오류]"); + System.out.println("사용자 정보와 서비스 구분값이 서로 일치하도록 매핑하여 주시기 바랍니다."); + + // 결과설정 + errCode = ErrCd.ERR405; + errMsg = String.format("[사용자 정보와 서비스 구분값 매핑 오류]\n사용자 정보와 서비스 구분값이 서로 일치하도록 매핑하여 주시기 바랍니다.\n(응답코드 %s)", iRtnCI); + } else if (iRtnCI == -9) { + System.out.println("[입력값 오류]"); + System.out.println("fnRequestConnInfo 함수 처리시, 필요한 4개의 파라미터값의 정보를 정확하게 입력해 주시기 바랍니다."); + + // 결과설정 + errCode = ErrCd.ERR403; + errMsg = String.format("[입력값 오류]\nfnRequestConnInfo 함수 처리시, 필요한 4개의 파라미터값의 정보를 정확하게 입력해 주시기 바랍니다.\n(응답코드 %s)", iRtnCI); + } else if (iRtnCI == -21 || iRtnCI == -31 || iRtnCI == -34) { + System.out.println("[통신오류]"); + System.out.println("방화벽 이용 시 아래 IP와 Port(총 5개)를 등록해주셔야 합니다."); + System.out.println("IP : 203.234.219.72 / Port : 81, 82, 83, 84, 85"); + + // 결과설정 + errCode = ErrCd.ERR521; + errMsg = String.format("[통신오류]\n방화벽 이용 시 아래 IP와 Port(총 5개)를 등록해주셔야 합니다.\nIP : 203.234.219.72 / Port : 81, 82, 83, 84, 85.\n(응답코드 %s)", iRtnCI); + } else { + System.out.println("[기타오류]"); + System.out.println("iRtnCI 값 확인 후 NICE평가정보 전산 담당자에게 문의"); + + // 결과설정 + errCode = ErrCd.ERR999; + errMsg = String.format("[기타오류]\niRtnCI 값 확인 후 NICE평가정보 전산 담당자에게 문의.\n(응답코드 %s)", iRtnCI); + } + /* ──── CI 값을 추출하기 위한 부분 End */ + + } catch (Exception e) { + // 결과설정 + errCode = ErrCd.ERR602; + errMsg = String.format("[나이스API 오류]\n%s\n(응답코드 %s)", e.getMessage(), iRtnCI); + } finally { + return ResponseVO.builder() + .errCode(errCode) + .errMsg(errMsg) + .resultInfo(ci) + .build(); + } + } + + + + +} \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties deleted file mode 100644 index 8b13789..0000000 --- a/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..b4fdabc --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,36 @@ + +spring: + profiles: + active: prod + mvc: + view: + prefix: /WEB-INF/jsp/ + suffix: .jsp + devtools: + livereload: + enabled: true #JSP ?? ? ?? ??? ?? ?? ?? + pid: + file: joa.pid + + logging: + file: + name: ./logs/logback.log + logback: + rollingpolicy: + file-name-pattern: ${LOG_FILE}.%d{yyyy-MM-dd}-%i.log + max-history: 30 #30??? ?? + max-file-size: + 100MB #????(100MB) + level: + root: info + '[org.hibernate.sql]': info + + +# ===================================================== +# NICE ???? +# ===================================================== +nice: + api: + ci: + site-code: + site-pw: diff --git a/src/main/webapp/WEB-INF/jsp/index.jsp b/src/main/webapp/WEB-INF/jsp/index.jsp new file mode 100644 index 0000000..3dc7272 --- /dev/null +++ b/src/main/webapp/WEB-INF/jsp/index.jsp @@ -0,0 +1,326 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" + pageEncoding="UTF-8"%> + + + + +CI 변환 시스템 + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+
+

CI 변환

+
+ 메뉴 세부정보 +
    +
  • 주민번호에 대한 CI 를 취득 합니다.
  • +
  • 첨부파일은 엑셀문서(xls,xlsx)만 가능하며, 시트에는 `A열:성명, B:주민번호` 가 작성되어 있어야 합니다.
  • + 시트 작성 +
      +
    • 1행: 컬럼명(A열:성명, B열:주민번호)
    • +
    • 2~xxx행: 데이터
    • +
    +
+
+
+
+ +
+

첨부파일(xls,xlsx)을 이곳에 올려주세요

+
+ + + + + + + + +
+
+ +
+ +
+
+
+ + + + + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/jsp/nav.jsp b/src/main/webapp/WEB-INF/jsp/nav.jsp new file mode 100644 index 0000000..43b585a --- /dev/null +++ b/src/main/webapp/WEB-INF/jsp/nav.jsp @@ -0,0 +1,24 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" + pageEncoding="UTF-8"%> + + + + + + + + + + + +
+ +
+ + + + \ No newline at end of file diff --git a/src/main/webapp/resource/css/file-drag-and-drop.css b/src/main/webapp/resource/css/file-drag-and-drop.css new file mode 100644 index 0000000..f421b3a --- /dev/null +++ b/src/main/webapp/resource/css/file-drag-and-drop.css @@ -0,0 +1,18 @@ + +.file-drag-and-drop{ + outline: 2px dashed #92b0b3 ; + outline-offset:-10px; + text-align: center; + transition: all .15s ease-in-out; + width: 300px; + height: 100px; + background-color: gray; + + display: flex; + flex-direction: row; + align-items: flex-start; + justify-content: center; + align-content: center; + flex-wrap: wrap; +} + diff --git a/src/main/webapp/resource/css/style.css b/src/main/webapp/resource/css/style.css new file mode 100644 index 0000000..ca11915 --- /dev/null +++ b/src/main/webapp/resource/css/style.css @@ -0,0 +1,31 @@ + +html{ + font-size: 15px; +} +div.app-container{ + display: flex; + flex-direction: row; + flex-wrap: wrap; +} +div.app-item.nav{ + padding: 10px; + background-color: burlywood; + width: 14rem; + flex-grow: 0; + +} +div.app-item.article{ + padding: 10px; + background-color: whitesmoke; + width: 50%; + flex-grow: 1; + +} + +details { + margin: 10px; +} +details > summary:hover { + cursor: pointer; + color: blue; +} diff --git a/src/main/webapp/resource/js/file-drag-and-drop.js b/src/main/webapp/resource/js/file-drag-and-drop.js new file mode 100644 index 0000000..c5b0e1b --- /dev/null +++ b/src/main/webapp/resource/js/file-drag-and-drop.js @@ -0,0 +1,73 @@ +const stateDragAndDrop = { + callback: ()=>{}, + attchFileCnt: 1 +} + + +$('.file-drag-and-drop') + .on("dragover", dragOver) + .on("dragleave", dragOver) + .on("drop", uploadFiles); + +// function dragOver(e){ +// e.stopPropagation(); +// e.preventDefault(); +// } +function dragOver(e) { + e.stopPropagation(); + e.preventDefault(); + if (e.type == "dragover") { + $(e.target).css({ + "background-color": "black", + "outline-offset": "-20px" + }); + } else { + $(e.target).css({ + "background-color": "gray", + "outline-offset": "-10px" + }); + } +} + + + +// function uploadFiles(e){ +// e.stopPropagation(); +// e.preventDefault(); +// } + +function uploadFiles(e) { + e.stopPropagation(); + e.preventDefault(); + dragOver(e); //1 + + e.dataTransfer = e.originalEvent.dataTransfer; //2 + let files = e.target.files || e.dataTransfer.files; + + if (files.length > stateDragAndDrop.attchFileCnt) { + alert('파일은 '+stateDragAndDrop.attchFileCnt+'개만 올리세요.'); + return; + } + + if (files[0].type.match(/image.*/)) { + $(e.target).css({ + "background-image": "url(" + window.URL.createObjectURL(files[0]) + ")", + "outline": "none", + "background-size": "100% 100%" + }); + }else{ + // alert('이미지가 아닙니다.'); + // return; + // debugger; + let event = { + target: { + files: files + } + } + // excelExportCommon(event, handleExcelDataAll); + stateDragAndDrop.callback(event); + } + +} + +