feat: 차세대세외수입개별시스템 연계API 4종 v1.0

dev
minkyu1128 2 years ago
parent ee776a5553
commit 369c95f001

37
.gitignore vendored

@ -0,0 +1,37 @@
HELP.md
.gradle
build/
!gradle/wrapper/gradle-wrapper.jar
!**/src/main/**/build/
!**/src/test/**/build/
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
bin/
!**/src/main/**/bin/
!**/src/test/**/bin/
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
out/
!**/src/main/**/out/
!**/src/test/**/out/
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
### VS Code ###
.vscode/

@ -1,2 +1,17 @@
# xit-ntri
세외수입 개별시스템 연계 API
### 빌드 방법
jar 파일로 빌드 하기
* 커맨드 이용
```shell
gradle clean build -Pprofile=prod
```
* IntelliJ 이용
![img.png](img.png)
### 빌드 파일 경로
```text
~/build/libs
```

@ -0,0 +1,46 @@
# 시작하기
***
배포환경에 따라 WAS 및 JDK 버전이 각기 다르며
이로인해 발생 할 수 있는 각종 오류들에 대한 원인을 파악하는데 있어
datasource 접속가능여부 및 기타 정보를 확인할 수 있는 jsp 파일을 제공 한다.
### 버전관리
|버전|작성일|작성자|내용|
|---|---|---|---|
|v0.1|2022.12.29|박민규|최초작성|
## 1. 배포하기
1. [**Tomcat 다운로드**](https://tomcat.apache.org/)
* 원하는 버전의 zip 파일 다운로드
2. **다운로드 파일 unzip**
3. **서버 기동하기** - *~/bin/startup.bat* 파일 실행
<mark>**\[ JDK 오류발생 시 처리방법 \]**</mark>
+ *~/bin* 경로에 **setenv.bat 파일 생성**
+ setenv.bat 파일에 **JAVA_HOME 작성**
+ set JAVA_HOME=[JDK 설치 경로]
+ ex) set JAVA_HOME=C:\XIT\java\corretto-11.0.15
4. **정상기동 여부 확인** - http://localhost:8080 으로 접속
+ 고양이 그림이 있는 Apache Tomcat 화면이 뜨면 성공
5. *~/webapps* 경로에 **"check" 디렉토리 복사**
6. **서버 재기동** - ~/bin/shutdown.bat & ~/bin/startup.bat
## 2. 테스트
1. 페이지 호출
+ http://localhost:8080/[파일명] //부록-파일 설명 참고
+ ex) http://localhost:8080/javaenv.jsp
<u>*DB 접속 테스트(datasource.jsp) 시*에는 ~/lib 경로에 *jdbc 라이브러리 파일(.jar)을 추가*</u>해야 한다.
# 부록
***
### 파일 설명
|File Name|Description|
|---|---|
|datasource.jsp|DB 접속 테스트|
|fontinfo.jsp|현재 플랫폼에서 사용가능한 폰트 목록 확인|
|hostname.jsp|호스트명 확인|
|javaenv.jsp|java 시스템 등록정보|
|urlcheck.jsp|URL 호출 테스트|

@ -0,0 +1,293 @@
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>
<%@ page import="java.sql.*, javax.sql.*, javax.naming.*" %>
<%
request.setCharacterEncoding("UTF-8"); //2020.09.25. 박민규- 캐릭터셋 설정
String uri = request.getRequestURI();
String type = request.getParameter("type");
String dsNm = request.getParameter("dsNm");
String driver = request.getParameter("driver");
String url = request.getParameter("url");
String user = request.getParameter("user");
String password = request.getParameter("password");
String sql = request.getParameter("sql");
if( type == null || type.equalsIgnoreCase("null") ) type = "";
if( dsNm == null || dsNm.equalsIgnoreCase("null") ) dsNm = "";
if( driver == null || driver.equalsIgnoreCase("null") ) driver = "";
if( url == null || url.equalsIgnoreCase("null") ) url = "";
if( user == null || user.equalsIgnoreCase("null") ) user = "";
if( password == null || password.equalsIgnoreCase("null") ) password = "";
if( sql == null || sql.equalsIgnoreCase("null") ) sql = "";
String msg = "";
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
%>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>DataSource 확인</title>
<style>
body { font-family:sans-serif, arial; font-size:9pt; }
table { font-family:sans-serif, arial; font-size:9pt; }
</style>
<script language="JavaScript">
<!--
function setField() {
var check = document.dbinfo.type.value;
if( check == "direct" ) {
document.all["nondirect"].style.visibility = "hidden";
document.all["direct1"].style.visibility = "visible";
document.all["direct2"].style.visibility = "visible";
document.all["direct3"].style.visibility = "visible";
document.all["direct4"].style.visibility = "visible";
}
else {
document.all["nondirect"].style.visibility = "visible";
document.all["direct1"].style.visibility = "hidden";
document.all["direct2"].style.visibility = "hidden";
document.all["direct3"].style.visibility = "hidden";
document.all["direct4"].style.visibility = "hidden";
}
}
function checkFiled() {
if( document.dbinfo.type.value == "direct" ) {
if(document.dbinfo.driver.value == "") {
alert("Plaese Input Driver Name.(ex : oracle.jdbc.driver.OracleDriver)");
document.dbinfo.driver.focus();
return false;
}
else if(document.dbinfo.url.value == "") {
alert("Please Input DB URL.(ex : jdbc:oracle:thin:@dbip:dbport:dbsid)");
document.dbinfo.url.focus();
return false;
}
else document.dbinfo.submit();
}
else {
if(document.dbinfo.dsNm.value == "") {
alert("Please Input DataSource Name.(ex : jdbc/demo)");
document.dbinfo.dsNm.focus();
return false;
}
else document.dbinfo.submit();
}
}
function checkFiled2() {
if( document.dbinfo.sql.value == "" ) {
alert("Plaese Input SQL statment.");
document.dbinfo.sql.focus();
return false;
}
else {
document.dbinfo.submit();
}
}
//-->
</script>
</head>
<body style="margin:10" onload="setField()">
<h2>Check DataSource<h2>
<form name="dbinfo" method="post" action="<%= uri %>">
<table width="585" border="1" cellspacing="0" cellpadding="0" bordercolor="#808080" bordercolorlight="#C0C0C0" bordercolordark="#F6F6F6">
<tr height="20">
<td align="center" bgcolor="#C0C0C0" width="100">WAS 유형</td>
<td align="center" width="192">
<select name="type" onchange="setField()">
<option value="lookup" <%= type.equals("lookup")?"selected":"" %>>lookup</option>
<option value="nonlookup" <%= type.equals("nonlookup")?"selected":"" %>>nonlookup</option>
<option value="direct" <%= type.equals("direct")?"selected":"" %>>direct</option>
</select>
</td>
<td align="center" bgcolor="#C0C0C0" width="100">DataSource</td>
<td align="center" width="192">
<div id="nondirect" style="visibility:">
<input type="text" name="dsNm" size="20" value="<%= dsNm %>">
</div>
</td>
</tr>
<tr height="20">
<td align="center" bgcolor="#C0C0C0" width="100">Driver</td>
<td align="center">
<div id="direct1" style="visibility:hidden">
<input type="text" name="driver" size="20" value="<%= driver %>">
</div>
</td>
<td align="center" bgcolor="#C0C0C0" width="100">URL</td>
<td align="center">
<div id="direct2" style="visibility:hidden">
<input type="text" name="url" size="20" value="<%= url %>">
</div>
</td>
</tr>
<tr height="20">
<td align="center" bgcolor="#C0C0C0" width="100">User</td>
<td align="center">
<div id="direct3" style="visibility:hidden">
<input type="text" name="user" size="20" value="<%= user %>">
</div>
</td>
<td align="center" bgcolor="#C0C0C0" width="100">Password</td>
<td align="center">
<div id="direct4" style="visibility:hidden">
<input type="text" name="password" size="20" value="<%= password %>">
</div>
</td>
</tr>
</table>
<table width="585" border="0" cellspacing="0" cellpadding="0" bordercolor="#808080" bordercolorlight="#C0C0C0" bordercolordark="#F6F6F6">
<tr height="30">
<td align="center">
<input type="button" value="DB Connect Test" onclick="checkFiled()">
</td>
</tr>
</table>
<%
if( type.equals("lookup") || type.equals("nonlookup") || type.equals("direct") ) {
try {
if( type.equals("lookup") ) { //lookup type (Tomcat, resin, Jrun ...)
Context ctx = new InitialContext();
Context env = (Context)ctx.lookup("java:comp/env");
DataSource ds = (DataSource)env.lookup(dsNm);
conn = ds.getConnection();
}
else if( type.equals("nonlookup") ) { //nonlookup type (Jeus, WebLogic, WebSphere ...)
Context ctx = new InitialContext();
DataSource ds = (DataSource)ctx.lookup(dsNm);
conn = ds.getConnection();
}
else { //direct
Class.forName(driver);
conn = DriverManager.getConnection(url, user, password);
}
if( conn == null ) msg = "Connection Fail!!!";
else msg = "Connection Success!!!";
}
catch(Exception e) {
msg = e.getMessage();
}
finally {
%>
<table width="585" border="1" cellspacing="0" cellpadding="0" bordercolor="#808080" bordercolorlight="#C0C0C0" bordercolordark="#F6F6F6">
<tr height="20">
<td align="center" bgcolor="#C0C0C0">Result(<%= type %>)</td>
</tr>
<tr height="50">
<td align="center" valign="middle"><%= msg %></td>
</tr>
</table>
<%
if( conn != null ) {
%>
<br>
<table width="585" border="1" cellspacing="0" cellpadding="0" bordercolor="#808080" bordercolorlight="#C0C0C0" bordercolordark="#F6F6F6">
<tr height="20">
<td align="center" bgcolor="#C0C0C0">SQL</td>
</tr>
<tr height="50">
<td>
<textarea name="sql" rows="8" cols="80"><%= sql %></textarea>
</td>
</tr>
</table>
<table width="585" border="0" cellspacing="0" cellpadding="0" bordercolor="#808080" bordercolorlight="#C0C0C0" bordercolordark="#F6F6F6">
<tr height="30">
<td align="center">
<input type="button" value="Data View" onclick="checkFiled2()">
</td>
</tr>
</table>
<%
if( sql != null && !sql.equals("") ) {
%>
<table width="585" border="1" cellspacing="0" cellpadding="0" bordercolor="#808080" bordercolorlight="#C0C0C0" bordercolordark="#F6F6F6">
<%
try {
ps = conn.prepareStatement(sql);
rs = ps.executeQuery();
ResultSetMetaData rsmd = rs.getMetaData();
int cnt = rsmd.getColumnCount();
out.println("<tr>");
for(int i = 0; i <= cnt; i++) {
if( i == 0 ) out.println("<td bgcolor=\"#C0C0C0\" align=\"center\">No</td>");
else out.println("<td bgcolor=\"#C0C0C0\" align=\"center\">" + rsmd.getColumnLabel(i) + "</td>");
}
int row_cnt = 0;
while( rs.next() ) {
out.println("<tr>");
for(int i = 0; i <= cnt; i++) {
if( i == 0 ) out.println("<td align=\"center\">" + ++row_cnt + "</td>");
else out.println("<td align=\"center\">" + rs.getString(i) + "</td>");
}
out.println("</tr>");
}
if( row_cnt == 0 ) {
out.println("<tr height=\"100\"><td align=\"center\" colspan=\"" + (cnt + 1) + "\">조회 내역이 없습니다.</td></tr>");
}
}
catch(Exception ee) {
out.println("<tr><td bgcolor=\"#C0C0C0\" align=\"center\">Error Message</td></tr>");
out.println("<tr height=\"100\"><td align=\"left\" valign=\"top\">" + ee.getMessage() + "</td></tr>");
}
%>
</table>
<%
}
if( rs != null ) try{ rs.close(); rs = null; } catch (Exception ex) {}
if( ps != null ) try{ ps.close(); ps = null; } catch (Exception ex) {}
if( conn != null ) try { conn.close(); conn = null; } catch(Exception e) {}
}
}
}
%>
</form>
</body>
</html>

@ -0,0 +1,24 @@
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>
<%@ page import="java.awt.*" %>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Font 정보</title>
<style>
body { font-family:sans-serif, arial; font-size:9pt; }
table { font-family:sans-serif, arial; font-size:9pt; }
</style>
<body>
<%
//System.setProperty("sun.java2d.fontpath", "font_location_path");
// System.setProperty("java.awt.headless", "true");
String[] fontNames = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
for (int i=0; i<fontNames.length; i++)
{
out.println(fontNames[i]+"<br>");
}
%>
</body>
</html>

@ -0,0 +1,19 @@
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>
<%@ page import="java.net.*" %>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Hostname 확인</title>
<style>
body { font-family:sans-serif, arial; font-size:9pt; }
</style>
</head>
<body style="margin:10">
<h2>Hostname Check</h2>
Hostname : [<%= InetAddress.getLocalHost().getHostName() %>]<br>
AppPath : [<%= getServletContext().getRealPath("/") %>]
</body>
</html>

@ -0,0 +1,26 @@
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Java Environment 확인</title>
<style>
body {
font-size:10pt;
font-family: Arial;
color: #000000;
line-height:18px;
}
</style>
<body>
<%
java.util.Enumeration e = System.getProperties().propertyNames();
while(e.hasMoreElements()) {
String key = (String)e.nextElement();
if( key.indexOf("class.path") != -1 || key.indexOf("loader") != -1 ) out.print("<li><font color='red'>" + key + " : " + System.getProperty(key) + "</font></li>");
else out.print("<li>" + key + " : " + System.getProperty(key) + "<br>");
}
%>
</body>
</html>

@ -0,0 +1,134 @@
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>
<%@ page import="java.net.*, java.io.*" %>
<%
String NL = System.getProperty("line.separator");
String sReqType = request.getParameter("req_type");
String sUrl = request.getParameter("url");
if( sReqType == null || sReqType.equalsIgnoreCase("null") ) {
sReqType = "GET";
}
if( sUrl == null || sUrl.equalsIgnoreCase("null") ) {
sUrl = "";
}
StringBuffer contents = new StringBuffer();
if( !sUrl.equals("") ) {
try {
URL url = new URL(sUrl);
contents.append(">> URL(" + sUrl + ") Connecting...").append(NL);
HttpURLConnection uc = (HttpURLConnection)url.openConnection();
uc.setDoOutput(true);
uc.setDoInput(true);
uc.setUseCaches(false);
uc.setRequestMethod(sReqType);
StringBuffer sb = new StringBuffer();
InputStream is = uc.getInputStream();
contents.append(">> Reading Contents...").append(NL);
BufferedReader in = new BufferedReader(new InputStreamReader(is));
int buffSize = 1024 * 8;
char[] buff;
int insize = 0;
while ((insize = in.read(buff = new char[buffSize], 0, buffSize)) != -1) {
sb.append((new String(buff, 0, insize)));
}
String receivestr = sb.toString().trim();
contents.append(">> Contents").append(NL);
contents.append("------------------------------------------").append(NL);
contents.append(sb.toString().trim()).append(NL);
contents.append("------------------------------------------").append(NL);
contents.append(">> End").append(NL);
}
catch(FileNotFoundException fnfe){
contents.append(">> FileNotFoundException").append(NL);
contents.append("------------------------------------------").append(NL);
contents.append(fnfe.getMessage()).append(NL);
contents.append("------------------------------------------").append(NL);
contents.append(">> End").append(NL);
fnfe.printStackTrace();
}
catch(Exception e){
contents.append(">> Exception").append(NL);
contents.append("------------------------------------------").append(NL);
contents.append(e.getMessage()).append(NL);
contents.append("------------------------------------------").append(NL);
contents.append(">> End").append(NL);
e.printStackTrace();
}
}
%>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>URL 확인</title>
<style>
body { font-family:sans-serif, arial; font-size:9pt; }
table { font-family:sans-serif, arial; font-size:9pt; }
</style>
<script language="JavaScript">
<!--
function checkURL() {
if(document.urlcheck.url.value == "") {
alert("Please Input URL(ex : http://localhost:8080)");
document.urlcheck.url.focus();
return false;
}
else document.urlcheck.submit();
}
//-->
</script>
</head>
<body style="margin:10">
<h2>Check URL<h2>
<form name='urlcheck' method='post' action='./urlcheck.jsp'>
<table width="585" border="1" cellspacing="0" cellpadding="0" bordercolor="#808080" bordercolorlight="#C0C0C0" bordercolordark="#F6F6F6">
<tr height="20">
<td align="center" bgcolor="#C0C0C0" width="100" style='padding:3px'>REQ TYPE</td>
<td align="left" style='padding:3px; padding-left:6px;'' >
<select name="req_type">
<option value="GET" <%= sReqType.equals("GET")?"selected":"" %>>GET</option>
<option value="POST" <%= sReqType.equals("POST")?"selected":"" %>>POST</option>
</select>
</td>
</tr>
<tr height="20">
<td align="center" bgcolor="#C0C0C0" width="100" style='padding:3px'>URL</td>
<td align="center" style='padding:3px'>
<input type="text" name="url" size="70" value="<%= sUrl %>">
</td>
</tr>
</table>
<table width="585" border="0" cellspacing="0" cellpadding="0" bordercolor="#808080" bordercolorlight="#C0C0C0" bordercolordark="#F6F6F6">
<tr height="30">
<td align="center">
<input type="button" value="URL CHECK" onclick="checkURL()">
</td>
</tr>
</table>
</form>
Result<br>
<textarea name="sql" rows="20" cols="84"><%= contents.toString() %></textarea>
</body>
</html>

@ -0,0 +1,113 @@
# 시작하기
***
세외수입개별시스템(Non-Tax Revenue Individual System) 은 \
과태료 부과에 대한 실시간 API 4종(부과결과/부과취소/수납정보/감액정보)을 지원 하며, \
API 4종의 데이터는 세외수입시스템측에서 제공 한다.
* 출발지: 세외수입시스템
* 목적지: 개별시스템(ntri)
### 버전관리
|버전|작성일|작성자|내용|
|---|---|---|---|
|v0.1|2022.12.20|박민규|최초작성|
|v0.2|2022.12.21|박민규|"2. SSL 인증서 발급" 내용 수정( 발급방식 변경: 스크립트 -> 실행파일(.bat) )|
|v0.2|2022.12.21|박민규|%NTRI_APP_HOME%/bin/setenv.bat 파일의 <mark>"DB/SSL설정" 수정</mark><mark>VM옵션" 환경변수 추가</mark>|
|v0.3|2022.12.22|박민규|연계표준지침(v1.2.1) 전문구조 변경에 의한 "API 테스트" 데이터 수정(%NTRI_APP_HOME%/bin/test/*.json)|
|v0.3.1|2022.12.23|박민규|"1. 배포하기"에 NTRI_JAVA_HOME 설정에 대한 내용 추가 및 실행 환경 JDBC 내용추가|
|v0.3.2|2022.12.27|박민규|"부록-실행 환경"의 JDBC 수정(ojdbc8.jar -> ojdbc6.jar). 사유: 일부 서버에서 Java.sql.SQLRecoverableException 발생|
|v0.3.3|2022.12.27|박민규|문서내용 수정. "부록-실행 환경" `삭제`. "부록-구현 스펙" `추가`|
|v0.4|2022.12.27|박민규|연계표준지침(v1.2.1 -> v1.?.?) 전문구조 변경에 의한 "API 테스트" 데이터 수정(%NTRI_APP_HOME%/bin/test/*.json). reqVo 필드타입 수정(단건 -> 다건)|
|v0.4.1|2022.12.29|박민규|curl프로그램 변경 및 프로그램 위치 변경(%NTRI_APP_HOME% -> %NTRI_APP_HOME%/bin/test). "부록-디렉토리 구성"에서 내용 삭제|
|v0.5|2023.01.02|박민규|연계대상코드(linkTrgtCd) 설정 추가. (어플리케이션 수정 및 setenv.bat 환경변수 NTRI_APP_LINKTRGTCD 추가)|
## 1. 배포하기
1. **원하는 경로에 ntri.zip 압축파일을 unzip** 한다.
* [원하는 경로]/ntri -> **<mark>%NTRI_APP_HOME%</mark>**
2. *%NTRI_APP_HOME%/bin/setenv.bat* 파일을 열어 **배포환경에 맞게 환경변수를 수정** 한다.
* NTRI_JAVA_HOME 및 SSL/DB 설정 등..
**\[ NTRI_JAVA_HOME 설정 참고 \]**
* PC에 JDK가 설치(install)된 경우
* JDK버전이 11 이상이면 -> %JAVA_HOME% 작성
* JDK버전이 11 미만이면 -> [JDK11(Amazon Corretto) 다운로드(.zip)](https://docs.aws.amazon.com/ko_kr/corretto/latest/corretto-11-ug/downloads-list.html) 및 Unzip 한 path 작성
* PC에 JDK가 미설치(no install)된 경우(unzip 또는 install 中 택1)
* [JDK11(Amazon Corretto) 다운로드(.zip)](https://docs.aws.amazon.com/ko_kr/corretto/latest/corretto-11-ug/downloads-list.html) 및 Unzip 한 path 작성
* [JDK11(Amazon Corretto) 다운로드(.msi)](https://docs.aws.amazon.com/ko_kr/corretto/latest/corretto-11-ug/downloads-list.html) 및 Install 후 %JAVA_HOME% 작성
<mark>※JDK 설치 확인 방법:</mark> cmd 창에서 `java -version` 입력
<mark>※JAVA_HOME 설정 확인 방법:</mark> 시스템 -> 정보 -> 고급 시스템 설정 -> 환경 변수(N)... -> 시스템 변수(S)
3. *%NTRI_APP_HOME%/bin/service-regist.bat* 파일을 **"관리자권한" 으로 실행**
4. *%NTRI_APP_HOME%/webapp* 디렉토리에 **"ntri-0.0.1-SNAPSHOT.jar" 파일 복사**
5. *%NTRI_APP_HOME%/bin/service-start.bat* 파일을 실행하여 "서비스 시작"
* 서비스 실행 오류가 발생할 경우 *%NTRI_APP_HOME%/logs/stderr.log* 내용 확인
6. *%NTRI_APP_HOME%/bin/service-logprint.bat* 파일을 실행하여 "서비스 실시간 로그" 확인
## 2. SSL 인증서 발급
1. [OpenSSL 다운로드](https://sourceforge.net/projects/openssl)
* openssl-1.0.2j-fips-x86_64/openssl-1.0.2j-fips-x86_64.zip
2. 다운로드한 압축파일을 unzip 후 **OpenSSL 디렉토리를 C드라이브(C:/) 밑으로 복사**
3. *%NTRI_APP_HOME%/ssl/bin* 디렉토리의 **"generate-ssl-cert-new.bat" 파일 실행**
**\[ 파일 설명 \]**
* 신규 발급: *generate-ssl-cert-new.bat*
* 인증서파일 `모두` 발급(key, csr, crt)
* 재발급: *generate-ssl-cert-refresh.bat*
* 인증서파일 `일부`만 발급(csr, crt)
4. *%NTRI_APP_HOME%/ssl/cert* 디렉토리에 **인증서파일(key,csr,crt) 이 생성**되었는지 **확인**
## 3. API 테스트
1. **"~/bin/test"** 디렉토리로 이동
2. 테스트 배치파일(.bat) 실행하여 API 호출
* 일괄: *curl-all.bat*
* 부과취소: *curl-LevyCancel.bat*
* 부과결과: *curl-LevyResult.bat*
* 수납정보: *curl-RcivInfo.bat*
* 감액정보: *curl-RdcamtInfo.bat*
# 부록
***
### 디렉토리 구성
|Directory|Description|
|---|---|
|%NTRI_APP_HOME%/webapp|어플리케이션 jar 파일이 위치한 디렉토리|
|%NTRI_APP_HOME%/bin|서버기동과 관련한 배치파일(.bat)이 위치한 디렉토리|
|%NTRI_APP_HOME%/bin/test|API 테스트 배치파일(.bat)이 위치한 디렉토리|
|%NTRI_APP_HOME%/bin/logs|어플리케이션 로그파일(.log)이 저장되는 디렉토리(startup.bat 직접 호출 시)|
|%NTRI_APP_HOME%/logs|어플리케이션 로그파일(.log)이 저장되는 디렉토리(윈도우 서비스 사용 시)|
|%NTRI_APP_HOME%/ssl/bin|SSL 인증서 신규/재발급을 위한 배치파일(.bat)이 위치한 디렉토리|
|%NTRI_APP_HOME%/ssl/cert|발급된 SSL 인증서가 저장되는 디렉토리|
|%NTRI_APP_HOME%/ssl/cert/backup|SSL 인증서 신규/재발급 시마다 발급된 인증서가 백업되는 디렉토리|
### 파일 설명
|File Name|Description|
|---|---|
|setenv.bat|`환경변수` 설정|
|service-regist.bat|서비스 `등록`|
|service-edit.bat|등록한 서비스정보 `수정`|
|service-delete.bat|등록한 서비스 `삭제`|
|service-start.bat|등록한 서비스 `실행`|
|service-stop.bat|등록한 서비스 `중지`|
|service-status.bat|등록한 서비스 실행 `상태` 확인|
|service-logprint.bat|등록한 서비스 `실시간 로그` 출력|
|startup.bat|서버 `기동`|
|shutdown.bat|서버 `종료`|
|logprint.bat|`실시간 로그` 출력|
### 구현 스펙
+ Back-End
+ SpringBoot 2.7.5
+ Tomcat 9.0.68
+ JDK11
+ gradle
+ JPA
+ DB
+ Oracle 11g
+ mariaDB 10.6.5
+ mysql
+ JDBC Libray
+ ojdbc6.jar
+ mariadb-java-client-2.7.5.jar
+ mysql-connector-java-8.0.30.jar

@ -0,0 +1,202 @@
<!DOCTYPE html []>
<html>
<head>
<meta charset="UTF-8" />
<meta name="author" content="MarkdownViewer++" />
<title>README.md</title>
<style type="text/css">
/* Avoid page breaks inside the most common attributes, especially for exports (i.e. PDF) */
td, h1, h2, h3, h4, h5, p, ul, ol, li {
page-break-inside: avoid;
}
</style>
</head>
<body>
<h1 id="section">시작하기</h1>
<hr />
<p>세외수입개별시스템(Non-Tax Revenue Individual System) 은 <br />
과태료 부과에 대한 실시간 API 4종(부과결과/부과취소/수납정보/감액정보)을 지원 하며, <br />
API 4종의 데이터는 세외수입시스템측에서 제공 한다.</p>
<ul>
<li>출발지: 세외수입시스템</li>
<li>목적지: 개별시스템(ntri)</li>
</ul>
<h3 id="section-1">버전관리</h3>
<table>
<thead>
<tr>
<th>버전</th>
<th>작성일</th>
<th>작성자</th>
<th>내용</th>
</tr>
</thead>
<tbody>
<tr>
<td>v0.1</td>
<td>2022.12.20</td>
<td>박민규</td>
<td>최초작성</td>
</tr>
</tbody>
</table>
<h2 id="section-2">1. 배포하기</h2>
<ol>
<li>
<strong>원하는 경로에 ntri.zip 압축파일을 unzip</strong> 한다.</li>
<li>
<em>%NTRI_APP_HOME%/bin/setenv.bat</em> 파일을 열어 <strong>배포환경에 맞게 환경변수를 수정</strong> 한다.
<ul><li>NTRI_JAVA_HOME 및 SSL/DB 설정 등..</li></ul></li>
<li>
<em>%NTRI_APP_HOME%/bin/service-regist.bat</em> 파일을 <strong>"관리자권한" 으로 실행</strong></li>
<li>
<em>%NTRI_APP_HOME%/webapp</em> 디렉토리에 <strong>"ntri-0.0.1-SNAPSHOT.jar" 파일 복사</strong></li>
<li>
<em>%NTRI_APP_HOME%/bin/service-start.bat</em> 파일을 실행하여 "서비스 시작"
<ul><li>서비스 실행 오류가 발생할 경우 <em>%NTRI_APP_HOME%/logs/stderr.log</em> 내용 확인</li></ul></li>
<li>
<em>%NTRI_APP_HOME%/bin/service-logprint.bat</em> 파일을 실행하여 "서비스 실시간 로그" 확인</li>
</ol>
<h2 id="ssl">2. SSL 인증서 발급</h2>
<ol>
<li>OpenSSL 다운로드(<a href="https://sourceforge.net/projects/openssl">https://sourceforge.net/projects/openssl</a>)
<ul><li>openssl-1.0.2j-fips-x86_64/openssl-1.0.2j-fips-x86_64.zip</li></ul></li>
<li>다운로드한 압축파일을 unzip 후 <strong>OpenSSL 디렉토리를 C드라이브(C:/) 밑으로 이동</strong></li>
<li>
<strong>관리자 권한</strong>으로 cmd창 열기</li>
<li>cd 커맨드로 <em>C:\OpenSSL\bin</em> 디렉토리로 이동</li>
</ol>
<pre>
<code class="language-PowerShell">cd C:\Openssl\bin
</code>
</pre>
<ol start="5">
<li>인증서 발급 커맨드 실행</li>
</ol>
<pre>
<code class="language-PowerShell">openssl req -config ./openssl.cnf -x509 -sha256 -nodes -newkey rsa:2048 -keyout private.key -out public.pem -days 3650
-&gt; 커맨드 종료시까지 엔터키(Enter) 입력
openssl pkcs12 -export -inKey private.key -in public.pem -name alias_name -out certificate.p12
-&gt; 인증서 패스워드 `xit5811807` 입력
※ openssl.cnf 관련 오류 발생 시 openssl.cnf 파일을 C:/OpenSSL 밑으로 복사
</code>
</pre>
<ol start="6">
<li>생성된 <em>certificate.p12</em> 파일을 <strong>"%NTRI_APP_HOME%/ssl/cert" 디렉토리로 복사</strong></li>
</ol>
<h2 id="api">3. API 테스트</h2>
<ol>
<li>
<strong>"~/bin/test"</strong> 디렉토리로 이동</li>
<li>테스트 배치파일(.bat) 실행하여 API 호출
<ul><li>일괄: <em>curl-all.bat</em></li><li>부과취소: <em>curl-LevyCancel.bat</em></li><li>부과결과: <em>curl-LevyResult.bat</em></li><li>수납정보: <em>curl-RcivInfo.bat</em></li><li>감액정보: <em>curl-RdcamtInfo.bat</em></li></ul></li>
</ol>
<h1 id="section-3">부록</h1>
<hr />
<h3 id="section-4">디렉토리 구성</h3>
<table>
<thead>
<tr>
<th>Directory</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>%NTRI_APP_HOME%/webapp</td>
<td>어플리케이션 jar 파일이 위치한 디렉토리</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/bin</td>
<td>서버기동과 관련한 배치파일(.bat)이 위치한 디렉토리</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/bin/test</td>
<td>API 테스트 배치파일(.bat) 파일이 위치한 디렉토리</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/bin/logs</td>
<td>어플리케이션 로그파일(.log)이 저장되는 디렉토리(startup.bat 직접 호출 시)</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/logs</td>
<td>어플리케이션 로그파일(.log)이 저장되는 디렉토리(윈도우 서비스 사용 시)</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/ssl</td>
<td>SSL 인증 관련 파일이 위치한 디렉토리</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/curl-7.86.0_2-win64-mingw</td>
<td>curl 커맨드를 사용하기 위한 실행프로그램</td>
</tr>
</tbody>
</table>
<h3 id="section-5">파일 설명</h3>
<table>
<thead>
<tr>
<th>File Name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>setenv.bat</td>
<td>
<code>환경변수</code> 설정</td>
</tr>
<tr>
<td>service-regist.bat</td>
<td>서비스 <code>등록</code></td>
</tr>
<tr>
<td>service-edit.bat</td>
<td>등록한 서비스정보 <code>수정</code></td>
</tr>
<tr>
<td>service-delete.bat</td>
<td>등록한 서비스 <code>삭제</code></td>
</tr>
<tr>
<td>service-start.bat</td>
<td>등록한 서비스 <code>실행</code></td>
</tr>
<tr>
<td>service-stop.bat</td>
<td>등록한 서비스 <code>중지</code></td>
</tr>
<tr>
<td>service-status.bat</td>
<td>등록한 서비스 실행 <code>상태</code> 확인</td>
</tr>
<tr>
<td>service-logprint.bat</td>
<td>등록한 서비스 <code>실시간 로그</code> 출력</td>
</tr>
<tr>
<td>startup.bat</td>
<td>서버 <code>기동</code></td>
</tr>
<tr>
<td>shutdown.bat</td>
<td>서버 <code>종료</code></td>
</tr>
<tr>
<td>logprint.bat</td>
<td>
<code>실시간 로그</code> 출력</td>
</tr>
</tbody>
</table>
<h3 id="section-6">실행 환경</h3>
<ul>
<li>Java 버전: JDK11 이상</li>
<li>Tomcat 버전: Tomcat9 이상</li>
<li>JDBC: ojdbc8.jar</li>
</ul>
</body>
</html>

@ -0,0 +1,204 @@
<!DOCTYPE html []>
<html>
<head>
<meta charset="UTF-8" />
<meta name="author" content="MarkdownViewer++" />
<title>README.md</title>
<style type="text/css">
/* Avoid page breaks inside the most common attributes, especially for exports (i.e. PDF) */
td, h1, h2, h3, h4, h5, p, ul, ol, li {
page-break-inside: avoid;
}
</style>
</head>
<body>
<h1 id="section">시작하기</h1>
<hr />
<p>세외수입개별시스템(Non-Tax Revenue Individual System) 은 <br />
과태료 부과에 대한 실시간 API 4종(부과결과/부과취소/수납정보/감액정보)을 지원 하며, <br />
API 4종의 데이터는 세외수입시스템측에서 제공 한다.</p>
<ul>
<li>출발지: 세외수입시스템</li>
<li>목적지: 개별시스템(ntri)</li>
</ul>
<h3 id="section-1">버전관리</h3>
<table>
<thead>
<tr>
<th>버전</th>
<th>작성일</th>
<th>작성자</th>
<th>내용</th>
</tr>
</thead>
<tbody>
<tr>
<td>v0.1</td>
<td>2022.12.20</td>
<td>박민규</td>
<td>최초작성</td>
</tr>
<tr>
<td>v0.2</td>
<td>2022.12.21</td>
<td>박민규</td>
<td>"2. SSL 인증서 발급" 내용 수정( 발급방식 변경: 스크립트 -&gt; 실행파일(.bat) )</td>
</tr>
<tr>
<td>v0.2</td>
<td>2022.12.21</td>
<td>박민규</td>
<td>%NTRI_APP_HOME%/bin/setenv.bat 파일의 <mark>"DB/SSL설정" 수정</mark><mark>VM옵션" 환경변수 추가</mark></td>
</tr>
</tbody>
</table>
<h2 id="section-2">1. 배포하기</h2>
<ol>
<li>
<strong>원하는 경로에 ntri.zip 압축파일을 unzip</strong> 한다.</li>
<li>
<em>%NTRI_APP_HOME%/bin/setenv.bat</em> 파일을 열어 <strong>배포환경에 맞게 환경변수를 수정</strong> 한다.
<ul><li>NTRI_JAVA_HOME 및 SSL/DB 설정 등..</li></ul></li>
<li>
<em>%NTRI_APP_HOME%/bin/service-regist.bat</em> 파일을 <strong>"관리자권한" 으로 실행</strong></li>
<li>
<em>%NTRI_APP_HOME%/webapp</em> 디렉토리에 <strong>"ntri-0.0.1-SNAPSHOT.jar" 파일 복사</strong></li>
<li>
<em>%NTRI_APP_HOME%/bin/service-start.bat</em> 파일을 실행하여 "서비스 시작"
<ul><li>서비스 실행 오류가 발생할 경우 <em>%NTRI_APP_HOME%/logs/stderr.log</em> 내용 확인</li></ul></li>
<li>
<em>%NTRI_APP_HOME%/bin/service-logprint.bat</em> 파일을 실행하여 "서비스 실시간 로그" 확인</li>
</ol>
<h2 id="ssl">2. SSL 인증서 발급</h2>
<ol>
<li>OpenSSL 다운로드(<a href="https://sourceforge.net/projects/openssl">https://sourceforge.net/projects/openssl</a>)
<ul><li>openssl-1.0.2j-fips-x86_64/openssl-1.0.2j-fips-x86_64.zip</li></ul></li>
<li>다운로드한 압축파일을 unzip 후 <strong>OpenSSL 디렉토리를 C드라이브(C:/) 밑으로 복사</strong></li>
<li>
<em>%NTRI_APP_HOME%/ssl/bin</em> 디렉토리의 <strong>"generate-ssl-cert-new.bat" 파일 실행</strong><br /><strong>[ 파일 설명 ]</strong><ul><li>신규 발급: <em>generate-ssl-cert-new.bat</em><ul><li>인증서파일 <code>모두</code> 발급(key, csr, crt)</li></ul></li><li>재발급: <em>generate-ssl-cert-refresh.bat</em><ul><li>인증서파일 <code>일부</code>만 발급(csr, crt)</li></ul></li></ul></li>
<li>
<em>%NTRI_APP_HOME%/ssl/cert</em> 디렉토리에 <strong>인증서파일(key,csr,crt) 이 생성</strong>되었는지 <strong>확인</strong></li>
</ol>
<h2 id="api">3. API 테스트</h2>
<ol>
<li>
<strong>"~/bin/test"</strong> 디렉토리로 이동</li>
<li>테스트 배치파일(.bat) 실행하여 API 호출
<ul><li>일괄: <em>curl-all.bat</em></li><li>부과취소: <em>curl-LevyCancel.bat</em></li><li>부과결과: <em>curl-LevyResult.bat</em></li><li>수납정보: <em>curl-RcivInfo.bat</em></li><li>감액정보: <em>curl-RdcamtInfo.bat</em></li></ul></li>
</ol>
<h1 id="section-3">부록</h1>
<hr />
<h3 id="section-4">디렉토리 구성</h3>
<table>
<thead>
<tr>
<th>Directory</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>%NTRI_APP_HOME%/webapp</td>
<td>어플리케이션 jar 파일이 위치한 디렉토리</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/bin</td>
<td>서버기동과 관련한 배치파일(.bat)이 위치한 디렉토리</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/bin/test</td>
<td>API 테스트 배치파일(.bat)이 위치한 디렉토리</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/bin/logs</td>
<td>어플리케이션 로그파일(.log)이 저장되는 디렉토리(startup.bat 직접 호출 시)</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/logs</td>
<td>어플리케이션 로그파일(.log)이 저장되는 디렉토리(윈도우 서비스 사용 시)</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/ssl/bin</td>
<td>SSL 인증서 신규/재발급을 위한 배치파일(.bat)이 위치한 디렉토리</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/ssl/cert</td>
<td>발급된 SSL 인증서가 저장되는 디렉토리</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/ssl/cert/backup</td>
<td>SSL 인증서 신규/재발급 시마다 발급된 인증서가 백업되는 디렉토리</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/curl-7.86.0_2-win64-mingw</td>
<td>curl 커맨드를 사용하기 위한 실행프로그램</td>
</tr>
</tbody>
</table>
<h3 id="section-5">파일 설명</h3>
<table>
<thead>
<tr>
<th>File Name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>setenv.bat</td>
<td>
<code>환경변수</code> 설정</td>
</tr>
<tr>
<td>service-regist.bat</td>
<td>서비스 <code>등록</code></td>
</tr>
<tr>
<td>service-edit.bat</td>
<td>등록한 서비스정보 <code>수정</code></td>
</tr>
<tr>
<td>service-delete.bat</td>
<td>등록한 서비스 <code>삭제</code></td>
</tr>
<tr>
<td>service-start.bat</td>
<td>등록한 서비스 <code>실행</code></td>
</tr>
<tr>
<td>service-stop.bat</td>
<td>등록한 서비스 <code>중지</code></td>
</tr>
<tr>
<td>service-status.bat</td>
<td>등록한 서비스 실행 <code>상태</code> 확인</td>
</tr>
<tr>
<td>service-logprint.bat</td>
<td>등록한 서비스 <code>실시간 로그</code> 출력</td>
</tr>
<tr>
<td>startup.bat</td>
<td>서버 <code>기동</code></td>
</tr>
<tr>
<td>shutdown.bat</td>
<td>서버 <code>종료</code></td>
</tr>
<tr>
<td>logprint.bat</td>
<td>
<code>실시간 로그</code> 출력</td>
</tr>
</tbody>
</table>
<h3 id="section-6">실행 환경</h3>
<ul>
<li>Java 버전: JDK11 이상</li>
<li>Tomcat 버전: Tomcat9 이상</li>
<li>JDBC: ojdbc8.jar</li>
</ul>
</body>
</html>

@ -0,0 +1,243 @@
<!DOCTYPE html []>
<html>
<head>
<meta charset="UTF-8" />
<meta name="author" content="MarkdownViewer++" />
<title>README.md</title>
<style type="text/css">
/* Avoid page breaks inside the most common attributes, especially for exports (i.e. PDF) */
td, h1, h2, h3, h4, h5, p, ul, ol, li {
page-break-inside: avoid;
}
</style>
</head>
<body>
<h1 id="section">시작하기</h1>
<hr />
<p>세외수입개별시스템(Non-Tax Revenue Individual System) 은 <br />
과태료 부과에 대한 실시간 API 4종(부과결과/부과취소/수납정보/감액정보)을 지원 하며, <br />
API 4종의 데이터는 세외수입시스템측에서 제공 한다.</p>
<ul>
<li>출발지: 세외수입시스템</li>
<li>목적지: 개별시스템(ntri)</li>
</ul>
<h3 id="section-1">버전관리</h3>
<table>
<thead>
<tr>
<th>버전</th>
<th>작성일</th>
<th>작성자</th>
<th>내용</th>
</tr>
</thead>
<tbody>
<tr>
<td>v0.1</td>
<td>2022.12.20</td>
<td>박민규</td>
<td>최초작성</td>
</tr>
<tr>
<td>v0.2</td>
<td>2022.12.21</td>
<td>박민규</td>
<td>"2. SSL 인증서 발급" 내용 수정( 발급방식 변경: 스크립트 -&gt; 실행파일(.bat) )</td>
</tr>
<tr>
<td>v0.2</td>
<td>2022.12.21</td>
<td>박민규</td>
<td>%NTRI_APP_HOME%/bin/setenv.bat 파일의 <mark>"DB/SSL설정" 수정</mark><mark>VM옵션" 환경변수 추가</mark></td>
</tr>
<tr>
<td>v0.3</td>
<td>2022.12.22</td>
<td>박민규</td>
<td>연계표준지침(v1.2.1) 전문구조 변경에 의한 "API 테스트" 데이터 수정(%NTRI_APP_HOME%/bin/test/*.json)</td>
</tr>
<tr>
<td>v0.3.1</td>
<td>2022.12.23</td>
<td>박민규</td>
<td>"1. 배포하기"에 NTRI_JAVA_HOME 설정에 대한 내용 추가 및 실행 환경 JDBC 내용추가</td>
</tr>
</tbody>
</table>
<h2 id="section-2">1. 배포하기</h2>
<ol>
<li>
<p>
<strong>원하는 경로에 ntri.zip 압축파일을 unzip</strong> 한다.</p>
<ul>
<li>[원하는 경로]/ntri -&gt; <strong><mark>%NTRI_APP_HOME%</mark></strong></li>
</ul>
</li>
<li>
<p>
<em>%NTRI_APP_HOME%/bin/setenv.bat</em> 파일을 열어 <strong>배포환경에 맞게 환경변수를 수정</strong> 한다.</p>
<ul>
<li>NTRI_JAVA_HOME 및 SSL/DB 설정 등..<br /><strong>[ NTRI_JAVA_HOME 설정 참고 ]</strong><ul><li>PC에 JDK가 설치(install)된 경우
<ul><li>JDK버전이 11 이상이면 -&gt; %JAVA_HOME% 작성</li><li>JDK버전이 11 미만이면 -&gt; <a href="https://docs.aws.amazon.com/ko_kr/corretto/latest/corretto-11-ug/downloads-list.html">JDK11(Amazon Corretto) 다운로드(.zip)</a> 및 Unzip 한 path 작성</li></ul></li><li>PC에 JDK가 미설치(no install)된 경우(unzip 또는 install 中 택1)
<ul><li><a href="https://docs.aws.amazon.com/ko_kr/corretto/latest/corretto-11-ug/downloads-list.html">JDK11(Amazon Corretto) 다운로드(.zip)</a> 및 Unzip 한 path 작성</li><li><a href="https://docs.aws.amazon.com/ko_kr/corretto/latest/corretto-11-ug/downloads-list.html">JDK11(Amazon Corretto) 다운로드(.msi)</a> 및 Install 후 %JAVA_HOME% 작성</li></ul></li></ul></li>
</ul>
<p>
<mark>※JDK 설치 확인 방법:</mark> cmd 창에서 <code>java -version</code> 입력<br /><mark>※JAVA_HOME 설정 확인 방법:</mark> 시스템 -&gt; 정보 -&gt; 고급 시스템 설정 -&gt; 환경 변수(N)... -&gt; 시스템 변수(S)</p>
</li>
<li>
<p>
<em>%NTRI_APP_HOME%/bin/service-regist.bat</em> 파일을 <strong>"관리자권한" 으로 실행</strong></p>
</li>
<li>
<p>
<em>%NTRI_APP_HOME%/webapp</em> 디렉토리에 <strong>"ntri-0.0.1-SNAPSHOT.jar" 파일 복사</strong></p>
</li>
<li>
<p>
<em>%NTRI_APP_HOME%/bin/service-start.bat</em> 파일을 실행하여 "서비스 시작"</p>
<ul>
<li>서비스 실행 오류가 발생할 경우 <em>%NTRI_APP_HOME%/logs/stderr.log</em> 내용 확인</li>
</ul>
</li>
<li>
<p>
<em>%NTRI_APP_HOME%/bin/service-logprint.bat</em> 파일을 실행하여 "서비스 실시간 로그" 확인</p>
</li>
</ol>
<h2 id="ssl">2. SSL 인증서 발급</h2>
<ol>
<li>
<a href="https://sourceforge.net/projects/openssl">OpenSSL 다운로드</a>
<ul>
<li>openssl-1.0.2j-fips-x86_64/openssl-1.0.2j-fips-x86_64.zip</li>
</ul>
</li>
<li>다운로드한 압축파일을 unzip 후 <strong>OpenSSL 디렉토리를 C드라이브(C:/) 밑으로 복사</strong></li>
<li>
<em>%NTRI_APP_HOME%/ssl/bin</em> 디렉토리의 <strong>"generate-ssl-cert-new.bat" 파일 실행</strong><br /><strong>[ 파일 설명 ]</strong><ul><li>신규 발급: <em>generate-ssl-cert-new.bat</em><ul><li>인증서파일 <code>모두</code> 발급(key, csr, crt)</li></ul></li><li>재발급: <em>generate-ssl-cert-refresh.bat</em><ul><li>인증서파일 <code>일부</code>만 발급(csr, crt)</li></ul></li></ul></li>
<li>
<em>%NTRI_APP_HOME%/ssl/cert</em> 디렉토리에 <strong>인증서파일(key,csr,crt) 이 생성</strong>되었는지 <strong>확인</strong></li>
</ol>
<h2 id="api">3. API 테스트</h2>
<ol>
<li>
<strong>"~/bin/test"</strong> 디렉토리로 이동</li>
<li>테스트 배치파일(.bat) 실행하여 API 호출
<ul><li>일괄: <em>curl-all.bat</em></li><li>부과취소: <em>curl-LevyCancel.bat</em></li><li>부과결과: <em>curl-LevyResult.bat</em></li><li>수납정보: <em>curl-RcivInfo.bat</em></li><li>감액정보: <em>curl-RdcamtInfo.bat</em></li></ul></li>
</ol>
<h1 id="section-3">부록</h1>
<hr />
<h3 id="section-4">디렉토리 구성</h3>
<table>
<thead>
<tr>
<th>Directory</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>%NTRI_APP_HOME%/webapp</td>
<td>어플리케이션 jar 파일이 위치한 디렉토리</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/bin</td>
<td>서버기동과 관련한 배치파일(.bat)이 위치한 디렉토리</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/bin/test</td>
<td>API 테스트 배치파일(.bat)이 위치한 디렉토리</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/bin/logs</td>
<td>어플리케이션 로그파일(.log)이 저장되는 디렉토리(startup.bat 직접 호출 시)</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/logs</td>
<td>어플리케이션 로그파일(.log)이 저장되는 디렉토리(윈도우 서비스 사용 시)</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/ssl/bin</td>
<td>SSL 인증서 신규/재발급을 위한 배치파일(.bat)이 위치한 디렉토리</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/ssl/cert</td>
<td>발급된 SSL 인증서가 저장되는 디렉토리</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/ssl/cert/backup</td>
<td>SSL 인증서 신규/재발급 시마다 발급된 인증서가 백업되는 디렉토리</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/curl-7.86.0_2-win64-mingw</td>
<td>curl 커맨드를 사용하기 위한 실행프로그램</td>
</tr>
</tbody>
</table>
<h3 id="section-5">파일 설명</h3>
<table>
<thead>
<tr>
<th>File Name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>setenv.bat</td>
<td>
<code>환경변수</code> 설정</td>
</tr>
<tr>
<td>service-regist.bat</td>
<td>서비스 <code>등록</code></td>
</tr>
<tr>
<td>service-edit.bat</td>
<td>등록한 서비스정보 <code>수정</code></td>
</tr>
<tr>
<td>service-delete.bat</td>
<td>등록한 서비스 <code>삭제</code></td>
</tr>
<tr>
<td>service-start.bat</td>
<td>등록한 서비스 <code>실행</code></td>
</tr>
<tr>
<td>service-stop.bat</td>
<td>등록한 서비스 <code>중지</code></td>
</tr>
<tr>
<td>service-status.bat</td>
<td>등록한 서비스 실행 <code>상태</code> 확인</td>
</tr>
<tr>
<td>service-logprint.bat</td>
<td>등록한 서비스 <code>실시간 로그</code> 출력</td>
</tr>
<tr>
<td>startup.bat</td>
<td>서버 <code>기동</code></td>
</tr>
<tr>
<td>shutdown.bat</td>
<td>서버 <code>종료</code></td>
</tr>
<tr>
<td>logprint.bat</td>
<td>
<code>실시간 로그</code> 출력</td>
</tr>
</tbody>
</table>
<h3 id="section-6">실행 환경</h3>
<ul>
<li>Java 버전: JDK11 이상</li>
<li>Tomcat 버전: Tomcat9 이상</li>
<li>JDBC: ojdbc8.jar, mariadb-java-client-2.7.5.jar, mysql-connector-java-8.0.30.jar</li>
</ul>
</body>
</html>

@ -0,0 +1,249 @@
<!DOCTYPE html []>
<html>
<head>
<meta charset="UTF-8" />
<meta name="author" content="MarkdownViewer++" />
<title>README.md</title>
<style type="text/css">
/* Avoid page breaks inside the most common attributes, especially for exports (i.e. PDF) */
td, h1, h2, h3, h4, h5, p, ul, ol, li {
page-break-inside: avoid;
}
</style>
</head>
<body>
<h1 id="section">시작하기</h1>
<hr />
<p>세외수입개별시스템(Non-Tax Revenue Individual System) 은 <br />
과태료 부과에 대한 실시간 API 4종(부과결과/부과취소/수납정보/감액정보)을 지원 하며, <br />
API 4종의 데이터는 세외수입시스템측에서 제공 한다.</p>
<ul>
<li>출발지: 세외수입시스템</li>
<li>목적지: 개별시스템(ntri)</li>
</ul>
<h3 id="section-1">버전관리</h3>
<table>
<thead>
<tr>
<th>버전</th>
<th>작성일</th>
<th>작성자</th>
<th>내용</th>
</tr>
</thead>
<tbody>
<tr>
<td>v0.1</td>
<td>2022.12.20</td>
<td>박민규</td>
<td>최초작성</td>
</tr>
<tr>
<td>v0.2</td>
<td>2022.12.21</td>
<td>박민규</td>
<td>"2. SSL 인증서 발급" 내용 수정( 발급방식 변경: 스크립트 -&gt; 실행파일(.bat) )</td>
</tr>
<tr>
<td>v0.2</td>
<td>2022.12.21</td>
<td>박민규</td>
<td>%NTRI_APP_HOME%/bin/setenv.bat 파일의 <mark>"DB/SSL설정" 수정</mark><mark>VM옵션" 환경변수 추가</mark></td>
</tr>
<tr>
<td>v0.3</td>
<td>2022.12.22</td>
<td>박민규</td>
<td>연계표준지침(v1.2.1) 전문구조 변경에 의한 "API 테스트" 데이터 수정(%NTRI_APP_HOME%/bin/test/*.json)</td>
</tr>
<tr>
<td>v0.3.1</td>
<td>2022.12.23</td>
<td>박민규</td>
<td>"1. 배포하기"에 NTRI_JAVA_HOME 설정에 대한 내용 추가 및 실행 환경 JDBC 내용추가</td>
</tr>
<tr>
<td>v0.3.2</td>
<td>2022.12.27</td>
<td>박민규</td>
<td>"부록-실행 환경"의 JDBC 수정(ojdbc8.jar -&gt; ojdbc6.jar). 사유: 일부 서버에서 Java.sql.SQLRecoverableException 발생</td>
</tr>
</tbody>
</table>
<h2 id="section-2">1. 배포하기</h2>
<ol>
<li>
<p>
<strong>원하는 경로에 ntri.zip 압축파일을 unzip</strong> 한다.</p>
<ul>
<li>[원하는 경로]/ntri -&gt; <strong><mark>%NTRI_APP_HOME%</mark></strong></li>
</ul>
</li>
<li>
<p>
<em>%NTRI_APP_HOME%/bin/setenv.bat</em> 파일을 열어 <strong>배포환경에 맞게 환경변수를 수정</strong> 한다.</p>
<ul>
<li>NTRI_JAVA_HOME 및 SSL/DB 설정 등..<br /><strong>[ NTRI_JAVA_HOME 설정 참고 ]</strong><ul><li>PC에 JDK가 설치(install)된 경우
<ul><li>JDK버전이 11 이상이면 -&gt; %JAVA_HOME% 작성</li><li>JDK버전이 11 미만이면 -&gt; <a href="https://docs.aws.amazon.com/ko_kr/corretto/latest/corretto-11-ug/downloads-list.html">JDK11(Amazon Corretto) 다운로드(.zip)</a> 및 Unzip 한 path 작성</li></ul></li><li>PC에 JDK가 미설치(no install)된 경우(unzip 또는 install 中 택1)
<ul><li><a href="https://docs.aws.amazon.com/ko_kr/corretto/latest/corretto-11-ug/downloads-list.html">JDK11(Amazon Corretto) 다운로드(.zip)</a> 및 Unzip 한 path 작성</li><li><a href="https://docs.aws.amazon.com/ko_kr/corretto/latest/corretto-11-ug/downloads-list.html">JDK11(Amazon Corretto) 다운로드(.msi)</a> 및 Install 후 %JAVA_HOME% 작성</li></ul></li></ul></li>
</ul>
<p>
<mark>※JDK 설치 확인 방법:</mark> cmd 창에서 <code>java -version</code> 입력<br /><mark>※JAVA_HOME 설정 확인 방법:</mark> 시스템 -&gt; 정보 -&gt; 고급 시스템 설정 -&gt; 환경 변수(N)... -&gt; 시스템 변수(S)</p>
</li>
<li>
<p>
<em>%NTRI_APP_HOME%/bin/service-regist.bat</em> 파일을 <strong>"관리자권한" 으로 실행</strong></p>
</li>
<li>
<p>
<em>%NTRI_APP_HOME%/webapp</em> 디렉토리에 <strong>"ntri-0.0.1-SNAPSHOT.jar" 파일 복사</strong></p>
</li>
<li>
<p>
<em>%NTRI_APP_HOME%/bin/service-start.bat</em> 파일을 실행하여 "서비스 시작"</p>
<ul>
<li>서비스 실행 오류가 발생할 경우 <em>%NTRI_APP_HOME%/logs/stderr.log</em> 내용 확인</li>
</ul>
</li>
<li>
<p>
<em>%NTRI_APP_HOME%/bin/service-logprint.bat</em> 파일을 실행하여 "서비스 실시간 로그" 확인</p>
</li>
</ol>
<h2 id="ssl">2. SSL 인증서 발급</h2>
<ol>
<li>
<a href="https://sourceforge.net/projects/openssl">OpenSSL 다운로드</a>
<ul>
<li>openssl-1.0.2j-fips-x86_64/openssl-1.0.2j-fips-x86_64.zip</li>
</ul>
</li>
<li>다운로드한 압축파일을 unzip 후 <strong>OpenSSL 디렉토리를 C드라이브(C:/) 밑으로 복사</strong></li>
<li>
<em>%NTRI_APP_HOME%/ssl/bin</em> 디렉토리의 <strong>"generate-ssl-cert-new.bat" 파일 실행</strong><br /><strong>[ 파일 설명 ]</strong><ul><li>신규 발급: <em>generate-ssl-cert-new.bat</em><ul><li>인증서파일 <code>모두</code> 발급(key, csr, crt)</li></ul></li><li>재발급: <em>generate-ssl-cert-refresh.bat</em><ul><li>인증서파일 <code>일부</code>만 발급(csr, crt)</li></ul></li></ul></li>
<li>
<em>%NTRI_APP_HOME%/ssl/cert</em> 디렉토리에 <strong>인증서파일(key,csr,crt) 이 생성</strong>되었는지 <strong>확인</strong></li>
</ol>
<h2 id="api">3. API 테스트</h2>
<ol>
<li>
<strong>"~/bin/test"</strong> 디렉토리로 이동</li>
<li>테스트 배치파일(.bat) 실행하여 API 호출
<ul><li>일괄: <em>curl-all.bat</em></li><li>부과취소: <em>curl-LevyCancel.bat</em></li><li>부과결과: <em>curl-LevyResult.bat</em></li><li>수납정보: <em>curl-RcivInfo.bat</em></li><li>감액정보: <em>curl-RdcamtInfo.bat</em></li></ul></li>
</ol>
<h1 id="section-3">부록</h1>
<hr />
<h3 id="section-4">디렉토리 구성</h3>
<table>
<thead>
<tr>
<th>Directory</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>%NTRI_APP_HOME%/webapp</td>
<td>어플리케이션 jar 파일이 위치한 디렉토리</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/bin</td>
<td>서버기동과 관련한 배치파일(.bat)이 위치한 디렉토리</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/bin/test</td>
<td>API 테스트 배치파일(.bat)이 위치한 디렉토리</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/bin/logs</td>
<td>어플리케이션 로그파일(.log)이 저장되는 디렉토리(startup.bat 직접 호출 시)</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/logs</td>
<td>어플리케이션 로그파일(.log)이 저장되는 디렉토리(윈도우 서비스 사용 시)</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/ssl/bin</td>
<td>SSL 인증서 신규/재발급을 위한 배치파일(.bat)이 위치한 디렉토리</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/ssl/cert</td>
<td>발급된 SSL 인증서가 저장되는 디렉토리</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/ssl/cert/backup</td>
<td>SSL 인증서 신규/재발급 시마다 발급된 인증서가 백업되는 디렉토리</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/curl-7.86.0_2-win64-mingw</td>
<td>curl 커맨드를 사용하기 위한 실행프로그램</td>
</tr>
</tbody>
</table>
<h3 id="section-5">파일 설명</h3>
<table>
<thead>
<tr>
<th>File Name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>setenv.bat</td>
<td>
<code>환경변수</code> 설정</td>
</tr>
<tr>
<td>service-regist.bat</td>
<td>서비스 <code>등록</code></td>
</tr>
<tr>
<td>service-edit.bat</td>
<td>등록한 서비스정보 <code>수정</code></td>
</tr>
<tr>
<td>service-delete.bat</td>
<td>등록한 서비스 <code>삭제</code></td>
</tr>
<tr>
<td>service-start.bat</td>
<td>등록한 서비스 <code>실행</code></td>
</tr>
<tr>
<td>service-stop.bat</td>
<td>등록한 서비스 <code>중지</code></td>
</tr>
<tr>
<td>service-status.bat</td>
<td>등록한 서비스 실행 <code>상태</code> 확인</td>
</tr>
<tr>
<td>service-logprint.bat</td>
<td>등록한 서비스 <code>실시간 로그</code> 출력</td>
</tr>
<tr>
<td>startup.bat</td>
<td>서버 <code>기동</code></td>
</tr>
<tr>
<td>shutdown.bat</td>
<td>서버 <code>종료</code></td>
</tr>
<tr>
<td>logprint.bat</td>
<td>
<code>실시간 로그</code> 출력</td>
</tr>
</tbody>
</table>
<h3 id="section-6">실행 환경</h3>
<ul>
<li>Java 버전: JDK11 이상</li>
<li>Tomcat 버전: Tomcat9 이상</li>
<li>JDBC: ojdbc6.jar, mariadb-java-client-2.7.5.jar, mysql-connector-java-8.0.30.jar</li>
</ul>
</body>
</html>

@ -0,0 +1,258 @@
<!DOCTYPE html []>
<html>
<head>
<meta charset="UTF-8" />
<meta name="author" content="MarkdownViewer++" />
<title>README.md</title>
<style type="text/css">
/* Avoid page breaks inside the most common attributes, especially for exports (i.e. PDF) */
td, h1, h2, h3, h4, h5, p, ul, ol, li {
page-break-inside: avoid;
}
</style>
</head>
<body>
<h1 id="section">시작하기</h1>
<hr />
<p>세외수입개별시스템(Non-Tax Revenue Individual System) 은 <br />
과태료 부과에 대한 실시간 API 4종(부과결과/부과취소/수납정보/감액정보)을 지원 하며, <br />
API 4종의 데이터는 세외수입시스템측에서 제공 한다.</p>
<ul>
<li>출발지: 세외수입시스템</li>
<li>목적지: 개별시스템(ntri)</li>
</ul>
<h3 id="section-1">버전관리</h3>
<table>
<thead>
<tr>
<th>버전</th>
<th>작성일</th>
<th>작성자</th>
<th>내용</th>
</tr>
</thead>
<tbody>
<tr>
<td>v0.1</td>
<td>2022.12.20</td>
<td>박민규</td>
<td>최초작성</td>
</tr>
<tr>
<td>v0.2</td>
<td>2022.12.21</td>
<td>박민규</td>
<td>"2. SSL 인증서 발급" 내용 수정( 발급방식 변경: 스크립트 -&gt; 실행파일(.bat) )</td>
</tr>
<tr>
<td>v0.2</td>
<td>2022.12.21</td>
<td>박민규</td>
<td>%NTRI_APP_HOME%/bin/setenv.bat 파일의 <mark>"DB/SSL설정" 수정</mark><mark>VM옵션" 환경변수 추가</mark></td>
</tr>
<tr>
<td>v0.3</td>
<td>2022.12.22</td>
<td>박민규</td>
<td>연계표준지침(v1.2.1) 전문구조 변경에 의한 "API 테스트" 데이터 수정(%NTRI_APP_HOME%/bin/test/*.json)</td>
</tr>
<tr>
<td>v0.3.1</td>
<td>2022.12.23</td>
<td>박민규</td>
<td>"1. 배포하기"에 NTRI_JAVA_HOME 설정에 대한 내용 추가 및 실행 환경 JDBC 내용추가</td>
</tr>
<tr>
<td>v0.3.2</td>
<td>2022.12.27</td>
<td>박민규</td>
<td>"부록-실행 환경"의 JDBC 수정(ojdbc8.jar -&gt; ojdbc6.jar). 사유: 일부 서버에서 Java.sql.SQLRecoverableException 발생</td>
</tr>
<tr>
<td>v0.3.3</td>
<td>2022.12.27</td>
<td>박민규</td>
<td>문서내용 수정. "부록-실행 환경" <code>삭제</code>. "부록-구현 스펙" <code>추가</code></td>
</tr>
</tbody>
</table>
<h2 id="section-2">1. 배포하기</h2>
<ol>
<li>
<p>
<strong>원하는 경로에 ntri.zip 압축파일을 unzip</strong> 한다.</p>
<ul>
<li>[원하는 경로]/ntri -&gt; <strong><mark>%NTRI_APP_HOME%</mark></strong></li>
</ul>
</li>
<li>
<p>
<em>%NTRI_APP_HOME%/bin/setenv.bat</em> 파일을 열어 <strong>배포환경에 맞게 환경변수를 수정</strong> 한다.</p>
<ul>
<li>NTRI_JAVA_HOME 및 SSL/DB 설정 등..<br /><strong>[ NTRI_JAVA_HOME 설정 참고 ]</strong><ul><li>PC에 JDK가 설치(install)된 경우
<ul><li>JDK버전이 11 이상이면 -&gt; %JAVA_HOME% 작성</li><li>JDK버전이 11 미만이면 -&gt; <a href="https://docs.aws.amazon.com/ko_kr/corretto/latest/corretto-11-ug/downloads-list.html">JDK11(Amazon Corretto) 다운로드(.zip)</a> 및 Unzip 한 path 작성</li></ul></li><li>PC에 JDK가 미설치(no install)된 경우(unzip 또는 install 中 택1)
<ul><li><a href="https://docs.aws.amazon.com/ko_kr/corretto/latest/corretto-11-ug/downloads-list.html">JDK11(Amazon Corretto) 다운로드(.zip)</a> 및 Unzip 한 path 작성</li><li><a href="https://docs.aws.amazon.com/ko_kr/corretto/latest/corretto-11-ug/downloads-list.html">JDK11(Amazon Corretto) 다운로드(.msi)</a> 및 Install 후 %JAVA_HOME% 작성</li></ul></li></ul></li>
</ul>
<p>
<mark>※JDK 설치 확인 방법:</mark> cmd 창에서 <code>java -version</code> 입력<br /><mark>※JAVA_HOME 설정 확인 방법:</mark> 시스템 -&gt; 정보 -&gt; 고급 시스템 설정 -&gt; 환경 변수(N)... -&gt; 시스템 변수(S)</p>
</li>
<li>
<p>
<em>%NTRI_APP_HOME%/bin/service-regist.bat</em> 파일을 <strong>"관리자권한" 으로 실행</strong></p>
</li>
<li>
<p>
<em>%NTRI_APP_HOME%/webapp</em> 디렉토리에 <strong>"ntri-0.0.1-SNAPSHOT.jar" 파일 복사</strong></p>
</li>
<li>
<p>
<em>%NTRI_APP_HOME%/bin/service-start.bat</em> 파일을 실행하여 "서비스 시작"</p>
<ul>
<li>서비스 실행 오류가 발생할 경우 <em>%NTRI_APP_HOME%/logs/stderr.log</em> 내용 확인</li>
</ul>
</li>
<li>
<p>
<em>%NTRI_APP_HOME%/bin/service-logprint.bat</em> 파일을 실행하여 "서비스 실시간 로그" 확인</p>
</li>
</ol>
<h2 id="ssl">2. SSL 인증서 발급</h2>
<ol>
<li>
<a href="https://sourceforge.net/projects/openssl">OpenSSL 다운로드</a>
<ul>
<li>openssl-1.0.2j-fips-x86_64/openssl-1.0.2j-fips-x86_64.zip</li>
</ul>
</li>
<li>다운로드한 압축파일을 unzip 후 <strong>OpenSSL 디렉토리를 C드라이브(C:/) 밑으로 복사</strong></li>
<li>
<em>%NTRI_APP_HOME%/ssl/bin</em> 디렉토리의 <strong>"generate-ssl-cert-new.bat" 파일 실행</strong><br /><strong>[ 파일 설명 ]</strong><ul><li>신규 발급: <em>generate-ssl-cert-new.bat</em><ul><li>인증서파일 <code>모두</code> 발급(key, csr, crt)</li></ul></li><li>재발급: <em>generate-ssl-cert-refresh.bat</em><ul><li>인증서파일 <code>일부</code>만 발급(csr, crt)</li></ul></li></ul></li>
<li>
<em>%NTRI_APP_HOME%/ssl/cert</em> 디렉토리에 <strong>인증서파일(key,csr,crt) 이 생성</strong>되었는지 <strong>확인</strong></li>
</ol>
<h2 id="api">3. API 테스트</h2>
<ol>
<li>
<strong>"~/bin/test"</strong> 디렉토리로 이동</li>
<li>테스트 배치파일(.bat) 실행하여 API 호출
<ul><li>일괄: <em>curl-all.bat</em></li><li>부과취소: <em>curl-LevyCancel.bat</em></li><li>부과결과: <em>curl-LevyResult.bat</em></li><li>수납정보: <em>curl-RcivInfo.bat</em></li><li>감액정보: <em>curl-RdcamtInfo.bat</em></li></ul></li>
</ol>
<h1 id="section-3">부록</h1>
<hr />
<h3 id="section-4">디렉토리 구성</h3>
<table>
<thead>
<tr>
<th>Directory</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>%NTRI_APP_HOME%/webapp</td>
<td>어플리케이션 jar 파일이 위치한 디렉토리</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/bin</td>
<td>서버기동과 관련한 배치파일(.bat)이 위치한 디렉토리</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/bin/test</td>
<td>API 테스트 배치파일(.bat)이 위치한 디렉토리</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/bin/logs</td>
<td>어플리케이션 로그파일(.log)이 저장되는 디렉토리(startup.bat 직접 호출 시)</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/logs</td>
<td>어플리케이션 로그파일(.log)이 저장되는 디렉토리(윈도우 서비스 사용 시)</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/ssl/bin</td>
<td>SSL 인증서 신규/재발급을 위한 배치파일(.bat)이 위치한 디렉토리</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/ssl/cert</td>
<td>발급된 SSL 인증서가 저장되는 디렉토리</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/ssl/cert/backup</td>
<td>SSL 인증서 신규/재발급 시마다 발급된 인증서가 백업되는 디렉토리</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/curl-7.86.0_2-win64-mingw</td>
<td>curl 커맨드를 사용하기 위한 실행프로그램</td>
</tr>
</tbody>
</table>
<h3 id="section-5">파일 설명</h3>
<table>
<thead>
<tr>
<th>File Name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>setenv.bat</td>
<td>
<code>환경변수</code> 설정</td>
</tr>
<tr>
<td>service-regist.bat</td>
<td>서비스 <code>등록</code></td>
</tr>
<tr>
<td>service-edit.bat</td>
<td>등록한 서비스정보 <code>수정</code></td>
</tr>
<tr>
<td>service-delete.bat</td>
<td>등록한 서비스 <code>삭제</code></td>
</tr>
<tr>
<td>service-start.bat</td>
<td>등록한 서비스 <code>실행</code></td>
</tr>
<tr>
<td>service-stop.bat</td>
<td>등록한 서비스 <code>중지</code></td>
</tr>
<tr>
<td>service-status.bat</td>
<td>등록한 서비스 실행 <code>상태</code> 확인</td>
</tr>
<tr>
<td>service-logprint.bat</td>
<td>등록한 서비스 <code>실시간 로그</code> 출력</td>
</tr>
<tr>
<td>startup.bat</td>
<td>서버 <code>기동</code></td>
</tr>
<tr>
<td>shutdown.bat</td>
<td>서버 <code>종료</code></td>
</tr>
<tr>
<td>logprint.bat</td>
<td>
<code>실시간 로그</code> 출력</td>
</tr>
</tbody>
</table>
<h3 id="section-6">구현 스펙</h3>
<ul>
<li>Back-End
<ul><li>SpringBoot 2.7.5</li><li>Tomcat 9.0.68</li><li>JDK11</li><li>gradle</li><li>JPA</li></ul></li>
<li>DB
<ul><li>Oracle 11g</li><li>mariaDB 10.6.5</li><li>mysql</li></ul></li>
<li>JDBC Libray
<ul><li>ojdbc6.jar</li><li>mariadb-java-client-2.7.5.jar</li><li>mysql-connector-java-8.0.30.jar</li></ul></li>
</ul>
</body>
</html>

@ -0,0 +1,211 @@
<!DOCTYPE html []>
<html>
<head>
<meta charset="UTF-8" />
<meta name="author" content="MarkdownViewer++" />
<title>README.md</title>
<style type="text/css">
/* Avoid page breaks inside the most common attributes, especially for exports (i.e. PDF) */
td, h1, h2, h3, h4, h5, p, ul, ol, li {
page-break-inside: avoid;
}
</style>
</head>
<body>
<h1 id="section">시작하기</h1>
<hr />
<p>세외수입개별시스템(Non-Tax Revenue Individual System) 은 <br />
과태료 부과에 대한 실시간 API 4종(부과결과/부과취소/수납정보/감액정보)을 지원 하며, <br />
API 4종의 데이터는 세외수입시스템측에서 제공 한다.</p>
<ul>
<li>출발지: 세외수입시스템</li>
<li>목적지: 개별시스템(ntri)</li>
</ul>
<h3 id="section-1">버전관리</h3>
<table>
<thead>
<tr>
<th>버전</th>
<th>작성일</th>
<th>작성자</th>
<th>내용</th>
</tr>
</thead>
<tbody>
<tr>
<td>v0.1</td>
<td>2022.12.20</td>
<td>박민규</td>
<td>최초작성</td>
</tr>
<tr>
<td>v0.2</td>
<td>2022.12.21</td>
<td>박민규</td>
<td>"2. SSL 인증서 발급" 내용 수정( 발급방식 변경: 스크립트 -&gt; 실행파일(.bat) )</td>
</tr>
<tr>
<td>v0.2</td>
<td>2022.12.21</td>
<td>박민규</td>
<td>%NTRI_APP_HOME%/bin/setenv.bat 파일의 <mark>"DB/SSL설정" 수정</mark><mark>VM옵션" 환경변수 추가</mark></td>
</tr>
<tr>
<td>v0.3</td>
<td>2022.12.22</td>
<td>박민규</td>
<td>연계표준지침(v1.2.1) 전문구조 변경에 의한 "API 테스트" 데이터 수정(%NTRI_APP_HOME%/bin/test/*.json)</td>
</tr>
</tbody>
</table>
<h2 id="section-2">1. 배포하기</h2>
<ol>
<li>
<strong>원하는 경로에 ntri.zip 압축파일을 unzip</strong> 한다.
<ul><li>[원하는 경로]/ntri -&gt; <strong><mark>%NTRI_APP_HOME%</mark></strong></li></ul></li>
<li>
<em>%NTRI_APP_HOME%/bin/setenv.bat</em> 파일을 열어 <strong>배포환경에 맞게 환경변수를 수정</strong> 한다.
<ul><li>NTRI_JAVA_HOME 및 SSL/DB 설정 등..</li></ul></li>
<li>
<em>%NTRI_APP_HOME%/bin/service-regist.bat</em> 파일을 <strong>"관리자권한" 으로 실행</strong></li>
<li>
<em>%NTRI_APP_HOME%/webapp</em> 디렉토리에 <strong>"ntri-0.0.1-SNAPSHOT.jar" 파일 복사</strong></li>
<li>
<em>%NTRI_APP_HOME%/bin/service-start.bat</em> 파일을 실행하여 "서비스 시작"
<ul><li>서비스 실행 오류가 발생할 경우 <em>%NTRI_APP_HOME%/logs/stderr.log</em> 내용 확인</li></ul></li>
<li>
<em>%NTRI_APP_HOME%/bin/service-logprint.bat</em> 파일을 실행하여 "서비스 실시간 로그" 확인</li>
</ol>
<h2 id="ssl">2. SSL 인증서 발급</h2>
<ol>
<li>OpenSSL 다운로드(<a href="https://sourceforge.net/projects/openssl">https://sourceforge.net/projects/openssl</a>)
<ul><li>openssl-1.0.2j-fips-x86_64/openssl-1.0.2j-fips-x86_64.zip</li></ul></li>
<li>다운로드한 압축파일을 unzip 후 <strong>OpenSSL 디렉토리를 C드라이브(C:/) 밑으로 복사</strong></li>
<li>
<em>%NTRI_APP_HOME%/ssl/bin</em> 디렉토리의 <strong>"generate-ssl-cert-new.bat" 파일 실행</strong><br /><strong>[ 파일 설명 ]</strong><ul><li>신규 발급: <em>generate-ssl-cert-new.bat</em><ul><li>인증서파일 <code>모두</code> 발급(key, csr, crt)</li></ul></li><li>재발급: <em>generate-ssl-cert-refresh.bat</em><ul><li>인증서파일 <code>일부</code>만 발급(csr, crt)</li></ul></li></ul></li>
<li>
<em>%NTRI_APP_HOME%/ssl/cert</em> 디렉토리에 <strong>인증서파일(key,csr,crt) 이 생성</strong>되었는지 <strong>확인</strong></li>
</ol>
<h2 id="api">3. API 테스트</h2>
<ol>
<li>
<strong>"~/bin/test"</strong> 디렉토리로 이동</li>
<li>테스트 배치파일(.bat) 실행하여 API 호출
<ul><li>일괄: <em>curl-all.bat</em></li><li>부과취소: <em>curl-LevyCancel.bat</em></li><li>부과결과: <em>curl-LevyResult.bat</em></li><li>수납정보: <em>curl-RcivInfo.bat</em></li><li>감액정보: <em>curl-RdcamtInfo.bat</em></li></ul></li>
</ol>
<h1 id="section-3">부록</h1>
<hr />
<h3 id="section-4">디렉토리 구성</h3>
<table>
<thead>
<tr>
<th>Directory</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>%NTRI_APP_HOME%/webapp</td>
<td>어플리케이션 jar 파일이 위치한 디렉토리</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/bin</td>
<td>서버기동과 관련한 배치파일(.bat)이 위치한 디렉토리</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/bin/test</td>
<td>API 테스트 배치파일(.bat)이 위치한 디렉토리</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/bin/logs</td>
<td>어플리케이션 로그파일(.log)이 저장되는 디렉토리(startup.bat 직접 호출 시)</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/logs</td>
<td>어플리케이션 로그파일(.log)이 저장되는 디렉토리(윈도우 서비스 사용 시)</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/ssl/bin</td>
<td>SSL 인증서 신규/재발급을 위한 배치파일(.bat)이 위치한 디렉토리</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/ssl/cert</td>
<td>발급된 SSL 인증서가 저장되는 디렉토리</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/ssl/cert/backup</td>
<td>SSL 인증서 신규/재발급 시마다 발급된 인증서가 백업되는 디렉토리</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/curl-7.86.0_2-win64-mingw</td>
<td>curl 커맨드를 사용하기 위한 실행프로그램</td>
</tr>
</tbody>
</table>
<h3 id="section-5">파일 설명</h3>
<table>
<thead>
<tr>
<th>File Name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>setenv.bat</td>
<td>
<code>환경변수</code> 설정</td>
</tr>
<tr>
<td>service-regist.bat</td>
<td>서비스 <code>등록</code></td>
</tr>
<tr>
<td>service-edit.bat</td>
<td>등록한 서비스정보 <code>수정</code></td>
</tr>
<tr>
<td>service-delete.bat</td>
<td>등록한 서비스 <code>삭제</code></td>
</tr>
<tr>
<td>service-start.bat</td>
<td>등록한 서비스 <code>실행</code></td>
</tr>
<tr>
<td>service-stop.bat</td>
<td>등록한 서비스 <code>중지</code></td>
</tr>
<tr>
<td>service-status.bat</td>
<td>등록한 서비스 실행 <code>상태</code> 확인</td>
</tr>
<tr>
<td>service-logprint.bat</td>
<td>등록한 서비스 <code>실시간 로그</code> 출력</td>
</tr>
<tr>
<td>startup.bat</td>
<td>서버 <code>기동</code></td>
</tr>
<tr>
<td>shutdown.bat</td>
<td>서버 <code>종료</code></td>
</tr>
<tr>
<td>logprint.bat</td>
<td>
<code>실시간 로그</code> 출력</td>
</tr>
</tbody>
</table>
<h3 id="section-6">실행 환경</h3>
<ul>
<li>Java 버전: JDK11 이상</li>
<li>Tomcat 버전: Tomcat9 이상</li>
<li>JDBC: ojdbc8.jar</li>
</ul>
</body>
</html>

@ -0,0 +1,266 @@
<!DOCTYPE html []>
<html>
<head>
<meta charset="UTF-8" />
<meta name="author" content="MarkdownViewer++" />
<title>README.md</title>
<style type="text/css">
/* Avoid page breaks inside the most common attributes, especially for exports (i.e. PDF) */
td, h1, h2, h3, h4, h5, p, ul, ol, li {
page-break-inside: avoid;
}
</style>
</head>
<body>
<h1 id="section">시작하기</h1>
<hr />
<p>세외수입개별시스템(Non-Tax Revenue Individual System) 은 <br />
과태료 부과에 대한 실시간 API 4종(부과결과/부과취소/수납정보/감액정보)을 지원 하며, <br />
API 4종의 데이터는 세외수입시스템측에서 제공 한다.</p>
<ul>
<li>출발지: 세외수입시스템</li>
<li>목적지: 개별시스템(ntri)</li>
</ul>
<h3 id="section-1">버전관리</h3>
<table>
<thead>
<tr>
<th>버전</th>
<th>작성일</th>
<th>작성자</th>
<th>내용</th>
</tr>
</thead>
<tbody>
<tr>
<td>v0.1</td>
<td>2022.12.20</td>
<td>박민규</td>
<td>최초작성</td>
</tr>
<tr>
<td>v0.2</td>
<td>2022.12.21</td>
<td>박민규</td>
<td>"2. SSL 인증서 발급" 내용 수정( 발급방식 변경: 스크립트 -&gt; 실행파일(.bat) )</td>
</tr>
<tr>
<td>v0.2</td>
<td>2022.12.21</td>
<td>박민규</td>
<td>%NTRI_APP_HOME%/bin/setenv.bat 파일의 <mark>"DB/SSL설정" 수정</mark><mark>VM옵션" 환경변수 추가</mark></td>
</tr>
<tr>
<td>v0.3</td>
<td>2022.12.22</td>
<td>박민규</td>
<td>연계표준지침(v1.2.1) 전문구조 변경에 의한 "API 테스트" 데이터 수정(%NTRI_APP_HOME%/bin/test/*.json)</td>
</tr>
<tr>
<td>v0.3.1</td>
<td>2022.12.23</td>
<td>박민규</td>
<td>"1. 배포하기"에 NTRI_JAVA_HOME 설정에 대한 내용 추가 및 실행 환경 JDBC 내용추가</td>
</tr>
<tr>
<td>v0.3.2</td>
<td>2022.12.27</td>
<td>박민규</td>
<td>"부록-실행 환경"의 JDBC 수정(ojdbc8.jar -&gt; ojdbc6.jar). 사유: 일부 서버에서 Java.sql.SQLRecoverableException 발생</td>
</tr>
<tr>
<td>v0.3.3</td>
<td>2022.12.27</td>
<td>박민규</td>
<td>문서내용 수정. "부록-실행 환경" <code>삭제</code>. "부록-구현 스펙" <code>추가</code></td>
</tr>
<tr>
<td>v0.4</td>
<td>2022.12.27</td>
<td>박민규</td>
<td>연계표준지침(v1.2.1 -&gt; v1.?.?) 전문구조 변경에 의한 "API 테스트" 데이터 수정(%NTRI_APP_HOME%/bin/test/*.json). reqVo 필드타입 수정(단건 -&gt; 다건)</td>
</tr>
<tr>
<td>v0.4.1</td>
<td>2022.12.29</td>
<td>박민규</td>
<td>curl프로그램 변경 및 프로그램 위치 변경(%NTRI_APP_HOME% -&gt; %NTRI_APP_HOME%/bin/test). "부록-디렉토리 구성"에서 내용 삭제</td>
</tr>
</tbody>
</table>
<h2 id="section-2">1. 배포하기</h2>
<ol>
<li>
<p>
<strong>원하는 경로에 ntri.zip 압축파일을 unzip</strong> 한다.</p>
<ul>
<li>[원하는 경로]/ntri -&gt; <strong><mark>%NTRI_APP_HOME%</mark></strong></li>
</ul>
</li>
<li>
<p>
<em>%NTRI_APP_HOME%/bin/setenv.bat</em> 파일을 열어 <strong>배포환경에 맞게 환경변수를 수정</strong> 한다.</p>
<ul>
<li>NTRI_JAVA_HOME 및 SSL/DB 설정 등..<br /><strong>[ NTRI_JAVA_HOME 설정 참고 ]</strong><ul><li>PC에 JDK가 설치(install)된 경우
<ul><li>JDK버전이 11 이상이면 -&gt; %JAVA_HOME% 작성</li><li>JDK버전이 11 미만이면 -&gt; <a href="https://docs.aws.amazon.com/ko_kr/corretto/latest/corretto-11-ug/downloads-list.html">JDK11(Amazon Corretto) 다운로드(.zip)</a> 및 Unzip 한 path 작성</li></ul></li><li>PC에 JDK가 미설치(no install)된 경우(unzip 또는 install 中 택1)
<ul><li><a href="https://docs.aws.amazon.com/ko_kr/corretto/latest/corretto-11-ug/downloads-list.html">JDK11(Amazon Corretto) 다운로드(.zip)</a> 및 Unzip 한 path 작성</li><li><a href="https://docs.aws.amazon.com/ko_kr/corretto/latest/corretto-11-ug/downloads-list.html">JDK11(Amazon Corretto) 다운로드(.msi)</a> 및 Install 후 %JAVA_HOME% 작성</li></ul></li></ul></li>
</ul>
<p>
<mark>※JDK 설치 확인 방법:</mark> cmd 창에서 <code>java -version</code> 입력<br /><mark>※JAVA_HOME 설정 확인 방법:</mark> 시스템 -&gt; 정보 -&gt; 고급 시스템 설정 -&gt; 환경 변수(N)... -&gt; 시스템 변수(S)</p>
</li>
<li>
<p>
<em>%NTRI_APP_HOME%/bin/service-regist.bat</em> 파일을 <strong>"관리자권한" 으로 실행</strong></p>
</li>
<li>
<p>
<em>%NTRI_APP_HOME%/webapp</em> 디렉토리에 <strong>"ntri-0.0.1-SNAPSHOT.jar" 파일 복사</strong></p>
</li>
<li>
<p>
<em>%NTRI_APP_HOME%/bin/service-start.bat</em> 파일을 실행하여 "서비스 시작"</p>
<ul>
<li>서비스 실행 오류가 발생할 경우 <em>%NTRI_APP_HOME%/logs/stderr.log</em> 내용 확인</li>
</ul>
</li>
<li>
<p>
<em>%NTRI_APP_HOME%/bin/service-logprint.bat</em> 파일을 실행하여 "서비스 실시간 로그" 확인</p>
</li>
</ol>
<h2 id="ssl">2. SSL 인증서 발급</h2>
<ol>
<li>
<a href="https://sourceforge.net/projects/openssl">OpenSSL 다운로드</a>
<ul>
<li>openssl-1.0.2j-fips-x86_64/openssl-1.0.2j-fips-x86_64.zip</li>
</ul>
</li>
<li>다운로드한 압축파일을 unzip 후 <strong>OpenSSL 디렉토리를 C드라이브(C:/) 밑으로 복사</strong></li>
<li>
<em>%NTRI_APP_HOME%/ssl/bin</em> 디렉토리의 <strong>"generate-ssl-cert-new.bat" 파일 실행</strong><br /><strong>[ 파일 설명 ]</strong><ul><li>신규 발급: <em>generate-ssl-cert-new.bat</em><ul><li>인증서파일 <code>모두</code> 발급(key, csr, crt)</li></ul></li><li>재발급: <em>generate-ssl-cert-refresh.bat</em><ul><li>인증서파일 <code>일부</code>만 발급(csr, crt)</li></ul></li></ul></li>
<li>
<em>%NTRI_APP_HOME%/ssl/cert</em> 디렉토리에 <strong>인증서파일(key,csr,crt) 이 생성</strong>되었는지 <strong>확인</strong></li>
</ol>
<h2 id="api">3. API 테스트</h2>
<ol>
<li>
<strong>"~/bin/test"</strong> 디렉토리로 이동</li>
<li>테스트 배치파일(.bat) 실행하여 API 호출
<ul><li>일괄: <em>curl-all.bat</em></li><li>부과취소: <em>curl-LevyCancel.bat</em></li><li>부과결과: <em>curl-LevyResult.bat</em></li><li>수납정보: <em>curl-RcivInfo.bat</em></li><li>감액정보: <em>curl-RdcamtInfo.bat</em></li></ul></li>
</ol>
<h1 id="section-3">부록</h1>
<hr />
<h3 id="section-4">디렉토리 구성</h3>
<table>
<thead>
<tr>
<th>Directory</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>%NTRI_APP_HOME%/webapp</td>
<td>어플리케이션 jar 파일이 위치한 디렉토리</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/bin</td>
<td>서버기동과 관련한 배치파일(.bat)이 위치한 디렉토리</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/bin/test</td>
<td>API 테스트 배치파일(.bat)이 위치한 디렉토리</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/bin/logs</td>
<td>어플리케이션 로그파일(.log)이 저장되는 디렉토리(startup.bat 직접 호출 시)</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/logs</td>
<td>어플리케이션 로그파일(.log)이 저장되는 디렉토리(윈도우 서비스 사용 시)</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/ssl/bin</td>
<td>SSL 인증서 신규/재발급을 위한 배치파일(.bat)이 위치한 디렉토리</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/ssl/cert</td>
<td>발급된 SSL 인증서가 저장되는 디렉토리</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/ssl/cert/backup</td>
<td>SSL 인증서 신규/재발급 시마다 발급된 인증서가 백업되는 디렉토리</td>
</tr>
</tbody>
</table>
<h3 id="section-5">파일 설명</h3>
<table>
<thead>
<tr>
<th>File Name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>setenv.bat</td>
<td>
<code>환경변수</code> 설정</td>
</tr>
<tr>
<td>service-regist.bat</td>
<td>서비스 <code>등록</code></td>
</tr>
<tr>
<td>service-edit.bat</td>
<td>등록한 서비스정보 <code>수정</code></td>
</tr>
<tr>
<td>service-delete.bat</td>
<td>등록한 서비스 <code>삭제</code></td>
</tr>
<tr>
<td>service-start.bat</td>
<td>등록한 서비스 <code>실행</code></td>
</tr>
<tr>
<td>service-stop.bat</td>
<td>등록한 서비스 <code>중지</code></td>
</tr>
<tr>
<td>service-status.bat</td>
<td>등록한 서비스 실행 <code>상태</code> 확인</td>
</tr>
<tr>
<td>service-logprint.bat</td>
<td>등록한 서비스 <code>실시간 로그</code> 출력</td>
</tr>
<tr>
<td>startup.bat</td>
<td>서버 <code>기동</code></td>
</tr>
<tr>
<td>shutdown.bat</td>
<td>서버 <code>종료</code></td>
</tr>
<tr>
<td>logprint.bat</td>
<td>
<code>실시간 로그</code> 출력</td>
</tr>
</tbody>
</table>
<h3 id="section-6">구현 스펙</h3>
<ul>
<li>Back-End
<ul><li>SpringBoot 2.7.5</li><li>Tomcat 9.0.68</li><li>JDK11</li><li>gradle</li><li>JPA</li></ul></li>
<li>DB
<ul><li>Oracle 11g</li><li>mariaDB 10.6.5</li><li>mysql</li></ul></li>
<li>JDBC Libray
<ul><li>ojdbc6.jar</li><li>mariadb-java-client-2.7.5.jar</li><li>mysql-connector-java-8.0.30.jar</li></ul></li>
</ul>
</body>
</html>

@ -0,0 +1,264 @@
<!DOCTYPE html []>
<html>
<head>
<meta charset="UTF-8" />
<meta name="author" content="MarkdownViewer++" />
<title>README.md</title>
<style type="text/css">
/* Avoid page breaks inside the most common attributes, especially for exports (i.e. PDF) */
td, h1, h2, h3, h4, h5, p, ul, ol, li {
page-break-inside: avoid;
}
</style>
</head>
<body>
<h1 id="section">시작하기</h1>
<hr />
<p>세외수입개별시스템(Non-Tax Revenue Individual System) 은 <br />
과태료 부과에 대한 실시간 API 4종(부과결과/부과취소/수납정보/감액정보)을 지원 하며, <br />
API 4종의 데이터는 세외수입시스템측에서 제공 한다.</p>
<ul>
<li>출발지: 세외수입시스템</li>
<li>목적지: 개별시스템(ntri)</li>
</ul>
<h3 id="section-1">버전관리</h3>
<table>
<thead>
<tr>
<th>버전</th>
<th>작성일</th>
<th>작성자</th>
<th>내용</th>
</tr>
</thead>
<tbody>
<tr>
<td>v0.1</td>
<td>2022.12.20</td>
<td>박민규</td>
<td>최초작성</td>
</tr>
<tr>
<td>v0.2</td>
<td>2022.12.21</td>
<td>박민규</td>
<td>"2. SSL 인증서 발급" 내용 수정( 발급방식 변경: 스크립트 -&gt; 실행파일(.bat) )</td>
</tr>
<tr>
<td>v0.2</td>
<td>2022.12.21</td>
<td>박민규</td>
<td>%NTRI_APP_HOME%/bin/setenv.bat 파일의 <mark>"DB/SSL설정" 수정</mark><mark>VM옵션" 환경변수 추가</mark></td>
</tr>
<tr>
<td>v0.3</td>
<td>2022.12.22</td>
<td>박민규</td>
<td>연계표준지침(v1.2.1) 전문구조 변경에 의한 "API 테스트" 데이터 수정(%NTRI_APP_HOME%/bin/test/*.json)</td>
</tr>
<tr>
<td>v0.3.1</td>
<td>2022.12.23</td>
<td>박민규</td>
<td>"1. 배포하기"에 NTRI_JAVA_HOME 설정에 대한 내용 추가 및 실행 환경 JDBC 내용추가</td>
</tr>
<tr>
<td>v0.3.2</td>
<td>2022.12.27</td>
<td>박민규</td>
<td>"부록-실행 환경"의 JDBC 수정(ojdbc8.jar -&gt; ojdbc6.jar). 사유: 일부 서버에서 Java.sql.SQLRecoverableException 발생</td>
</tr>
<tr>
<td>v0.3.3</td>
<td>2022.12.27</td>
<td>박민규</td>
<td>문서내용 수정. "부록-실행 환경" <code>삭제</code>. "부록-구현 스펙" <code>추가</code></td>
</tr>
<tr>
<td>v0.4</td>
<td>2022.12.27</td>
<td>박민규</td>
<td>연계표준지침(v1.2.1 -&gt; v1.?.?) 전문구조 변경에 의한 "API 테스트" 데이터 수정(%NTRI_APP_HOME%/bin/test/*.json). reqVo 필드타입 수정(단건 -&gt; 다건)</td>
</tr>
</tbody>
</table>
<h2 id="section-2">1. 배포하기</h2>
<ol>
<li>
<p>
<strong>원하는 경로에 ntri.zip 압축파일을 unzip</strong> 한다.</p>
<ul>
<li>[원하는 경로]/ntri -&gt; <strong><mark>%NTRI_APP_HOME%</mark></strong></li>
</ul>
</li>
<li>
<p>
<em>%NTRI_APP_HOME%/bin/setenv.bat</em> 파일을 열어 <strong>배포환경에 맞게 환경변수를 수정</strong> 한다.</p>
<ul>
<li>NTRI_JAVA_HOME 및 SSL/DB 설정 등..<br /><strong>[ NTRI_JAVA_HOME 설정 참고 ]</strong><ul><li>PC에 JDK가 설치(install)된 경우
<ul><li>JDK버전이 11 이상이면 -&gt; %JAVA_HOME% 작성</li><li>JDK버전이 11 미만이면 -&gt; <a href="https://docs.aws.amazon.com/ko_kr/corretto/latest/corretto-11-ug/downloads-list.html">JDK11(Amazon Corretto) 다운로드(.zip)</a> 및 Unzip 한 path 작성</li></ul></li><li>PC에 JDK가 미설치(no install)된 경우(unzip 또는 install 中 택1)
<ul><li><a href="https://docs.aws.amazon.com/ko_kr/corretto/latest/corretto-11-ug/downloads-list.html">JDK11(Amazon Corretto) 다운로드(.zip)</a> 및 Unzip 한 path 작성</li><li><a href="https://docs.aws.amazon.com/ko_kr/corretto/latest/corretto-11-ug/downloads-list.html">JDK11(Amazon Corretto) 다운로드(.msi)</a> 및 Install 후 %JAVA_HOME% 작성</li></ul></li></ul></li>
</ul>
<p>
<mark>※JDK 설치 확인 방법:</mark> cmd 창에서 <code>java -version</code> 입력<br /><mark>※JAVA_HOME 설정 확인 방법:</mark> 시스템 -&gt; 정보 -&gt; 고급 시스템 설정 -&gt; 환경 변수(N)... -&gt; 시스템 변수(S)</p>
</li>
<li>
<p>
<em>%NTRI_APP_HOME%/bin/service-regist.bat</em> 파일을 <strong>"관리자권한" 으로 실행</strong></p>
</li>
<li>
<p>
<em>%NTRI_APP_HOME%/webapp</em> 디렉토리에 <strong>"ntri-0.0.1-SNAPSHOT.jar" 파일 복사</strong></p>
</li>
<li>
<p>
<em>%NTRI_APP_HOME%/bin/service-start.bat</em> 파일을 실행하여 "서비스 시작"</p>
<ul>
<li>서비스 실행 오류가 발생할 경우 <em>%NTRI_APP_HOME%/logs/stderr.log</em> 내용 확인</li>
</ul>
</li>
<li>
<p>
<em>%NTRI_APP_HOME%/bin/service-logprint.bat</em> 파일을 실행하여 "서비스 실시간 로그" 확인</p>
</li>
</ol>
<h2 id="ssl">2. SSL 인증서 발급</h2>
<ol>
<li>
<a href="https://sourceforge.net/projects/openssl">OpenSSL 다운로드</a>
<ul>
<li>openssl-1.0.2j-fips-x86_64/openssl-1.0.2j-fips-x86_64.zip</li>
</ul>
</li>
<li>다운로드한 압축파일을 unzip 후 <strong>OpenSSL 디렉토리를 C드라이브(C:/) 밑으로 복사</strong></li>
<li>
<em>%NTRI_APP_HOME%/ssl/bin</em> 디렉토리의 <strong>"generate-ssl-cert-new.bat" 파일 실행</strong><br /><strong>[ 파일 설명 ]</strong><ul><li>신규 발급: <em>generate-ssl-cert-new.bat</em><ul><li>인증서파일 <code>모두</code> 발급(key, csr, crt)</li></ul></li><li>재발급: <em>generate-ssl-cert-refresh.bat</em><ul><li>인증서파일 <code>일부</code>만 발급(csr, crt)</li></ul></li></ul></li>
<li>
<em>%NTRI_APP_HOME%/ssl/cert</em> 디렉토리에 <strong>인증서파일(key,csr,crt) 이 생성</strong>되었는지 <strong>확인</strong></li>
</ol>
<h2 id="api">3. API 테스트</h2>
<ol>
<li>
<strong>"~/bin/test"</strong> 디렉토리로 이동</li>
<li>테스트 배치파일(.bat) 실행하여 API 호출
<ul><li>일괄: <em>curl-all.bat</em></li><li>부과취소: <em>curl-LevyCancel.bat</em></li><li>부과결과: <em>curl-LevyResult.bat</em></li><li>수납정보: <em>curl-RcivInfo.bat</em></li><li>감액정보: <em>curl-RdcamtInfo.bat</em></li></ul></li>
</ol>
<h1 id="section-3">부록</h1>
<hr />
<h3 id="section-4">디렉토리 구성</h3>
<table>
<thead>
<tr>
<th>Directory</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>%NTRI_APP_HOME%/webapp</td>
<td>어플리케이션 jar 파일이 위치한 디렉토리</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/bin</td>
<td>서버기동과 관련한 배치파일(.bat)이 위치한 디렉토리</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/bin/test</td>
<td>API 테스트 배치파일(.bat)이 위치한 디렉토리</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/bin/logs</td>
<td>어플리케이션 로그파일(.log)이 저장되는 디렉토리(startup.bat 직접 호출 시)</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/logs</td>
<td>어플리케이션 로그파일(.log)이 저장되는 디렉토리(윈도우 서비스 사용 시)</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/ssl/bin</td>
<td>SSL 인증서 신규/재발급을 위한 배치파일(.bat)이 위치한 디렉토리</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/ssl/cert</td>
<td>발급된 SSL 인증서가 저장되는 디렉토리</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/ssl/cert/backup</td>
<td>SSL 인증서 신규/재발급 시마다 발급된 인증서가 백업되는 디렉토리</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/curl-7.86.0_2-win64-mingw</td>
<td>curl 커맨드를 사용하기 위한 실행프로그램</td>
</tr>
</tbody>
</table>
<h3 id="section-5">파일 설명</h3>
<table>
<thead>
<tr>
<th>File Name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>setenv.bat</td>
<td>
<code>환경변수</code> 설정</td>
</tr>
<tr>
<td>service-regist.bat</td>
<td>서비스 <code>등록</code></td>
</tr>
<tr>
<td>service-edit.bat</td>
<td>등록한 서비스정보 <code>수정</code></td>
</tr>
<tr>
<td>service-delete.bat</td>
<td>등록한 서비스 <code>삭제</code></td>
</tr>
<tr>
<td>service-start.bat</td>
<td>등록한 서비스 <code>실행</code></td>
</tr>
<tr>
<td>service-stop.bat</td>
<td>등록한 서비스 <code>중지</code></td>
</tr>
<tr>
<td>service-status.bat</td>
<td>등록한 서비스 실행 <code>상태</code> 확인</td>
</tr>
<tr>
<td>service-logprint.bat</td>
<td>등록한 서비스 <code>실시간 로그</code> 출력</td>
</tr>
<tr>
<td>startup.bat</td>
<td>서버 <code>기동</code></td>
</tr>
<tr>
<td>shutdown.bat</td>
<td>서버 <code>종료</code></td>
</tr>
<tr>
<td>logprint.bat</td>
<td>
<code>실시간 로그</code> 출력</td>
</tr>
</tbody>
</table>
<h3 id="section-6">구현 스펙</h3>
<ul>
<li>Back-End
<ul><li>SpringBoot 2.7.5</li><li>Tomcat 9.0.68</li><li>JDK11</li><li>gradle</li><li>JPA</li></ul></li>
<li>DB
<ul><li>Oracle 11g</li><li>mariaDB 10.6.5</li><li>mysql</li></ul></li>
<li>JDBC Libray
<ul><li>ojdbc6.jar</li><li>mariadb-java-client-2.7.5.jar</li><li>mysql-connector-java-8.0.30.jar</li></ul></li>
</ul>
</body>
</html>

@ -0,0 +1,272 @@
<!DOCTYPE html []>
<html>
<head>
<meta charset="UTF-8" />
<meta name="author" content="MarkdownViewer++" />
<title>README.md</title>
<style type="text/css">
/* Avoid page breaks inside the most common attributes, especially for exports (i.e. PDF) */
td, h1, h2, h3, h4, h5, p, ul, ol, li {
page-break-inside: avoid;
}
</style>
</head>
<body>
<h1 id="section">시작하기</h1>
<hr />
<p>세외수입개별시스템(Non-Tax Revenue Individual System) 은 <br />
과태료 부과에 대한 실시간 API 4종(부과결과/부과취소/수납정보/감액정보)을 지원 하며, <br />
API 4종의 데이터는 세외수입시스템측에서 제공 한다.</p>
<ul>
<li>출발지: 세외수입시스템</li>
<li>목적지: 개별시스템(ntri)</li>
</ul>
<h3 id="section-1">버전관리</h3>
<table>
<thead>
<tr>
<th>버전</th>
<th>작성일</th>
<th>작성자</th>
<th>내용</th>
</tr>
</thead>
<tbody>
<tr>
<td>v0.1</td>
<td>2022.12.20</td>
<td>박민규</td>
<td>최초작성</td>
</tr>
<tr>
<td>v0.2</td>
<td>2022.12.21</td>
<td>박민규</td>
<td>"2. SSL 인증서 발급" 내용 수정( 발급방식 변경: 스크립트 -&gt; 실행파일(.bat) )</td>
</tr>
<tr>
<td>v0.2</td>
<td>2022.12.21</td>
<td>박민규</td>
<td>%NTRI_APP_HOME%/bin/setenv.bat 파일의 <mark>"DB/SSL설정" 수정</mark><mark>VM옵션" 환경변수 추가</mark></td>
</tr>
<tr>
<td>v0.3</td>
<td>2022.12.22</td>
<td>박민규</td>
<td>연계표준지침(v1.2.1) 전문구조 변경에 의한 "API 테스트" 데이터 수정(%NTRI_APP_HOME%/bin/test/*.json)</td>
</tr>
<tr>
<td>v0.3.1</td>
<td>2022.12.23</td>
<td>박민규</td>
<td>"1. 배포하기"에 NTRI_JAVA_HOME 설정에 대한 내용 추가 및 실행 환경 JDBC 내용추가</td>
</tr>
<tr>
<td>v0.3.2</td>
<td>2022.12.27</td>
<td>박민규</td>
<td>"부록-실행 환경"의 JDBC 수정(ojdbc8.jar -&gt; ojdbc6.jar). 사유: 일부 서버에서 Java.sql.SQLRecoverableException 발생</td>
</tr>
<tr>
<td>v0.3.3</td>
<td>2022.12.27</td>
<td>박민규</td>
<td>문서내용 수정. "부록-실행 환경" <code>삭제</code>. "부록-구현 스펙" <code>추가</code></td>
</tr>
<tr>
<td>v0.4</td>
<td>2022.12.27</td>
<td>박민규</td>
<td>연계표준지침(v1.2.1 -&gt; v1.?.?) 전문구조 변경에 의한 "API 테스트" 데이터 수정(%NTRI_APP_HOME%/bin/test/*.json). reqVo 필드타입 수정(단건 -&gt; 다건)</td>
</tr>
<tr>
<td>v0.4.1</td>
<td>2022.12.29</td>
<td>박민규</td>
<td>curl프로그램 변경 및 프로그램 위치 변경(%NTRI_APP_HOME% -&gt; %NTRI_APP_HOME%/bin/test). "부록-디렉토리 구성"에서 내용 삭제</td>
</tr>
<tr>
<td>v0.5</td>
<td>2023.01.02</td>
<td>박민규</td>
<td>연계대상코드(linkTrgtCd) 설정 추가. (어플리케이션 수정 및 setenv.bat 환경변수 NTRI_APP_LINKTRGTCD 추가)</td>
</tr>
</tbody>
</table>
<h2 id="section-2">1. 배포하기</h2>
<ol>
<li>
<p>
<strong>원하는 경로에 ntri.zip 압축파일을 unzip</strong> 한다.</p>
<ul>
<li>[원하는 경로]/ntri -&gt; <strong><mark>%NTRI_APP_HOME%</mark></strong></li>
</ul>
</li>
<li>
<p>
<em>%NTRI_APP_HOME%/bin/setenv.bat</em> 파일을 열어 <strong>배포환경에 맞게 환경변수를 수정</strong> 한다.</p>
<ul>
<li>NTRI_JAVA_HOME 및 SSL/DB 설정 등..<br /><strong>[ NTRI_JAVA_HOME 설정 참고 ]</strong><ul><li>PC에 JDK가 설치(install)된 경우
<ul><li>JDK버전이 11 이상이면 -&gt; %JAVA_HOME% 작성</li><li>JDK버전이 11 미만이면 -&gt; <a href="https://docs.aws.amazon.com/ko_kr/corretto/latest/corretto-11-ug/downloads-list.html">JDK11(Amazon Corretto) 다운로드(.zip)</a> 및 Unzip 한 path 작성</li></ul></li><li>PC에 JDK가 미설치(no install)된 경우(unzip 또는 install 中 택1)
<ul><li><a href="https://docs.aws.amazon.com/ko_kr/corretto/latest/corretto-11-ug/downloads-list.html">JDK11(Amazon Corretto) 다운로드(.zip)</a> 및 Unzip 한 path 작성</li><li><a href="https://docs.aws.amazon.com/ko_kr/corretto/latest/corretto-11-ug/downloads-list.html">JDK11(Amazon Corretto) 다운로드(.msi)</a> 및 Install 후 %JAVA_HOME% 작성</li></ul></li></ul></li>
</ul>
<p>
<mark>※JDK 설치 확인 방법:</mark> cmd 창에서 <code>java -version</code> 입력<br /><mark>※JAVA_HOME 설정 확인 방법:</mark> 시스템 -&gt; 정보 -&gt; 고급 시스템 설정 -&gt; 환경 변수(N)... -&gt; 시스템 변수(S)</p>
</li>
<li>
<p>
<em>%NTRI_APP_HOME%/bin/service-regist.bat</em> 파일을 <strong>"관리자권한" 으로 실행</strong></p>
</li>
<li>
<p>
<em>%NTRI_APP_HOME%/webapp</em> 디렉토리에 <strong>"ntri-0.0.1-SNAPSHOT.jar" 파일 복사</strong></p>
</li>
<li>
<p>
<em>%NTRI_APP_HOME%/bin/service-start.bat</em> 파일을 실행하여 "서비스 시작"</p>
<ul>
<li>서비스 실행 오류가 발생할 경우 <em>%NTRI_APP_HOME%/logs/stderr.log</em> 내용 확인</li>
</ul>
</li>
<li>
<p>
<em>%NTRI_APP_HOME%/bin/service-logprint.bat</em> 파일을 실행하여 "서비스 실시간 로그" 확인</p>
</li>
</ol>
<h2 id="ssl">2. SSL 인증서 발급</h2>
<ol>
<li>
<a href="https://sourceforge.net/projects/openssl">OpenSSL 다운로드</a>
<ul>
<li>openssl-1.0.2j-fips-x86_64/openssl-1.0.2j-fips-x86_64.zip</li>
</ul>
</li>
<li>다운로드한 압축파일을 unzip 후 <strong>OpenSSL 디렉토리를 C드라이브(C:/) 밑으로 복사</strong></li>
<li>
<em>%NTRI_APP_HOME%/ssl/bin</em> 디렉토리의 <strong>"generate-ssl-cert-new.bat" 파일 실행</strong><br /><strong>[ 파일 설명 ]</strong><ul><li>신규 발급: <em>generate-ssl-cert-new.bat</em><ul><li>인증서파일 <code>모두</code> 발급(key, csr, crt)</li></ul></li><li>재발급: <em>generate-ssl-cert-refresh.bat</em><ul><li>인증서파일 <code>일부</code>만 발급(csr, crt)</li></ul></li></ul></li>
<li>
<em>%NTRI_APP_HOME%/ssl/cert</em> 디렉토리에 <strong>인증서파일(key,csr,crt) 이 생성</strong>되었는지 <strong>확인</strong></li>
</ol>
<h2 id="api">3. API 테스트</h2>
<ol>
<li>
<strong>"~/bin/test"</strong> 디렉토리로 이동</li>
<li>테스트 배치파일(.bat) 실행하여 API 호출
<ul><li>일괄: <em>curl-all.bat</em></li><li>부과취소: <em>curl-LevyCancel.bat</em></li><li>부과결과: <em>curl-LevyResult.bat</em></li><li>수납정보: <em>curl-RcivInfo.bat</em></li><li>감액정보: <em>curl-RdcamtInfo.bat</em></li></ul></li>
</ol>
<h1 id="section-3">부록</h1>
<hr />
<h3 id="section-4">디렉토리 구성</h3>
<table>
<thead>
<tr>
<th>Directory</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>%NTRI_APP_HOME%/webapp</td>
<td>어플리케이션 jar 파일이 위치한 디렉토리</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/bin</td>
<td>서버기동과 관련한 배치파일(.bat)이 위치한 디렉토리</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/bin/test</td>
<td>API 테스트 배치파일(.bat)이 위치한 디렉토리</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/bin/logs</td>
<td>어플리케이션 로그파일(.log)이 저장되는 디렉토리(startup.bat 직접 호출 시)</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/logs</td>
<td>어플리케이션 로그파일(.log)이 저장되는 디렉토리(윈도우 서비스 사용 시)</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/ssl/bin</td>
<td>SSL 인증서 신규/재발급을 위한 배치파일(.bat)이 위치한 디렉토리</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/ssl/cert</td>
<td>발급된 SSL 인증서가 저장되는 디렉토리</td>
</tr>
<tr>
<td>%NTRI_APP_HOME%/ssl/cert/backup</td>
<td>SSL 인증서 신규/재발급 시마다 발급된 인증서가 백업되는 디렉토리</td>
</tr>
</tbody>
</table>
<h3 id="section-5">파일 설명</h3>
<table>
<thead>
<tr>
<th>File Name</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>setenv.bat</td>
<td>
<code>환경변수</code> 설정</td>
</tr>
<tr>
<td>service-regist.bat</td>
<td>서비스 <code>등록</code></td>
</tr>
<tr>
<td>service-edit.bat</td>
<td>등록한 서비스정보 <code>수정</code></td>
</tr>
<tr>
<td>service-delete.bat</td>
<td>등록한 서비스 <code>삭제</code></td>
</tr>
<tr>
<td>service-start.bat</td>
<td>등록한 서비스 <code>실행</code></td>
</tr>
<tr>
<td>service-stop.bat</td>
<td>등록한 서비스 <code>중지</code></td>
</tr>
<tr>
<td>service-status.bat</td>
<td>등록한 서비스 실행 <code>상태</code> 확인</td>
</tr>
<tr>
<td>service-logprint.bat</td>
<td>등록한 서비스 <code>실시간 로그</code> 출력</td>
</tr>
<tr>
<td>startup.bat</td>
<td>서버 <code>기동</code></td>
</tr>
<tr>
<td>shutdown.bat</td>
<td>서버 <code>종료</code></td>
</tr>
<tr>
<td>logprint.bat</td>
<td>
<code>실시간 로그</code> 출력</td>
</tr>
</tbody>
</table>
<h3 id="section-6">구현 스펙</h3>
<ul>
<li>Back-End
<ul><li>SpringBoot 2.7.5</li><li>Tomcat 9.0.68</li><li>JDK11</li><li>gradle</li><li>JPA</li></ul></li>
<li>DB
<ul><li>Oracle 11g</li><li>mariaDB 10.6.5</li><li>mysql</li></ul></li>
<li>JDBC Libray
<ul><li>ojdbc6.jar</li><li>mariadb-java-client-2.7.5.jar</li><li>mysql-connector-java-8.0.30.jar</li></ul></li>
</ul>
</body>
</html>

@ -0,0 +1,125 @@
plugins {
id 'org.springframework.boot' version '2.7.5'
id 'io.spring.dependency-management' version '1.0.15.RELEASE'
id 'org.asciidoctor.convert' version '1.5.8'
id 'java'
}
group = 'cokr.xit.ntri'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
repositories {
mavenCentral()
}
ext {
set('snippetsDir', file("build/generated-snippets"))
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-configuration-processor'
runtimeOnly 'com.oracle.database.jdbc:ojdbc8'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc'
/*====================================================================================
* Springdoc - swagger
====================================================================================*/
implementation 'org.springdoc:springdoc-openapi-ui:1.6.3'
/*====================================================================================
* lombok
====================================================================================*/
implementation 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
/*====================================================================================
* commons-io
====================================================================================*/
implementation 'org.apache.commons:commons-io:1.3.2'
/*====================================================================================
* jdbc library
====================================================================================*/
implementation 'org.mariadb.jdbc:mariadb-java-client:2.7.5'
implementation 'mysql:mysql-connector-java:8.0.30'
//TODO: "java.sql.SQLException: 지원되지 않는 문자 집합(클래스 경로에 orai18n.jar 추가): KO16MSWIN949"
implementation 'com.oracle.ojdbc:orai18n:19.3.0.0'
/*====================================================================================
* external library
====================================================================================*/
implementation fileTree(dir: 'libs', includes: ['*.jar'])
// implementation files("libs/ojdbc8.jar")
}
//processResources {
// filesMatching('**/application.yml') {
// expand(project.properties)
// }
//}
//import org.apache.tools.ant.filters.ReplaceTokens
//processResources {
// with copySpec {
// from 'src/main/resources'
// include '**/application.yml'
//// include '**/application*.yaml'
//// include '**/application*.properties'
// project.properties.findAll().each {
// prop ->
// if (prop.value != null) {
// filter(ReplaceTokens, tokens: [ (prop.key): prop.value])
// filter(ReplaceTokens, tokens: [ ('project.' + prop.key): prop.value])
// }
// }
// }
//}
ext {
index = '1'
string = "gradleString"
}
ext.profile = (!project.hasProperty('profile') || !profile) ? 'dev' : profile
ext.springProfilesActive = System.properties['spring.profiles.active']
sourceSets {
println("springProfilesActive:::::: $springProfilesActive")
println("\$profile:::::: $profile")
println("project.profile:::::: " + project.profile)
println("\$project.profile:::::: $project.profile")
println("\$project.ext.profile:::::: $project.ext.profile")
main {
resources {
srcDirs "src/main/resources", "src/main/resources-env/${profile}"
}
}
}
tasks {
processResources {
// filesMatching('**/application.yml') {
// expand(project.properties)
// }
duplicatesStrategy = org.gradle.api.file.DuplicatesStrategy.EXCLUDE
}
}
tasks.named('test') {
outputs.dir snippetsDir
useJUnitPlatform()
}
tasks.named('asciidoctor') {
inputs.dir snippetsDir
dependsOn test
}
tasks.named('compileJava') {
inputs.files(tasks.named('processResources'))
}

Binary file not shown.

@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

240
gradlew vendored

@ -0,0 +1,240 @@
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_NAME="Gradle"
APP_BASE_NAME=${0##*/}
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"

91
gradlew.bat vendored

@ -0,0 +1,91 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

@ -0,0 +1 @@
rootProject.name = 'ntri'

@ -0,0 +1,44 @@
package cokr.xit.ntri;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.ApplicationPidFileWriter;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.ComponentScan;
@Slf4j
@ComponentScan(basePackages = "cokr.xit")
@SpringBootApplication
public class NtriApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
// SpringApplication.run(NtriApplication.class, args);
Long begin = System.currentTimeMillis();
// PID Setting ...
SpringApplication application = new SpringApplication(NtriApplication.class);
application.addListeners(new ApplicationPidFileWriter()); //PID(Process ID 작성)
application.run(args);
log.info("=========================================================================================");
log.info("========== NTRI Application load Complete :: active profiles - {} ==========", System.getProperty("spring.profiles.active"));
log.info("=========================================================================================");
Long end = System.currentTimeMillis();
System.out.println("====================================================");
System.out.println("기동 소요시간: " + (end - begin) + "ms");
System.out.println("====================================================");
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(NtriApplication.class);
}
}

@ -0,0 +1,27 @@
package cokr.xit.ntri.api.recv.code;
import cokr.xit.ntri.support.code.CodeMapperType;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
/**
*
*/
@RequiredArgsConstructor
public enum LinkRstCd implements CodeMapperType {
ok("정상", "000")
, internalFail("내부오류", "002");
@Getter
private final String codeNm;
@Getter
private final String extCode;
@Override
public String getCode() {
return this.name();
}
}

@ -0,0 +1,48 @@
package cokr.xit.ntri.api.recv.entity;
import cokr.xit.ntri.api.recv.code.LinkRstCd;
import cokr.xit.ntri.support.entity.BaseEntity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.SuperBuilder;
import javax.persistence.Column;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.MappedSuperclass;
@Getter
@Setter
@MappedSuperclass
@SuperBuilder
@NoArgsConstructor
public class RecvBaseEntity extends BaseEntity {
@Setter
@Schema(required = false, title = "자치단체코드", example = " ", description = " ")
@Column(name = "rsp_sgb_cd", length = 7)
private String rspSgbCd;
@Setter
@Schema(required = false, title = "연계대상코드", example = " ", description = " ")
@Column(name = "rsp_link_trgt_cd", length = 15)
private String rspLinkTrgtCd;
@Setter
@Schema(required = false, title = "연계관리키", example = " ", description = " ")
@Column(name = "rsp_link_mng_key", length = 50)
private String rspLinkMngKey;
@Setter
@Schema(required = false, title = "연계결과코드", example = " ", description = " ")
@Column(name = "rsp_link_rst_cd", length = 30)
@Enumerated(EnumType.STRING)
private LinkRstCd rspLinkRstCd;
@Setter
@Schema(required = false, title = "연계결과메시지", example = " ", description = " ")
@Column(name = "rsp_link_rst_msg", length = 200)
private String rspLinkRstMsg;
}

@ -0,0 +1,55 @@
package cokr.xit.ntri.api.recv.entity;
import cokr.xit.ntri.support.entity.BaseEntity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;
import lombok.experimental.SuperBuilder;
import javax.persistence.*;
@Getter
@ToString
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(schema = "", name = "ntri_recv_error")
@Schema(name = "RecvError", title = "수신오류(실시간)", description = "세외수입시스템으로 수신한 데이터 처리 중 Exception이 발생한 데이터를 기록한다.")
public class RecvError extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id", nullable = false)
private Long id;
@Schema(required = false, title = "자치단체코드", example = " ", description = "행정표준코드관리시스템의 자치단체코드")
@Column(name = "sgb_cd", nullable = true)
private String sgbCd;
@Schema(required = false, title = "인터페이스ID", example = " ", description = "세외수입에서 정의한 연계 인터페이스ID")
@Column(name = "if_id", nullable = true)
private String ifId;
@Schema(required = false, title = "연계관리키", example = " ", description = "연계대상 기관에서 관리하는 유일키")
@Column(name = "link_mng_key", nullable = true)
private String linkMngKey;
@Schema(required = false, title = "연계대상코드", example = " ", description = "세외수입에서 부여한 15자리 코드 조합. format: 연계기관코드(7)+연계시스템코드(3)+연계일련번호(5)")
@Column(name = "link_trgt_cd", nullable = true)
private String linkTrgtCd;
@Schema(required = false, title = "header raw 데이터", example = " ", description = "")
@Column(name = "raw_header", nullable = true)
@Lob
private String rawDataHeader;
@Schema(required = false, title = "요청데이터", example = " ", description = "세외수입에서 전송한 데이터")
@Lob
@Column(name = "req_data")
private String reqData;
@Schema(required = false, title = "에러메시지", example = " ", description = "에러메시지")
@Column(name = "err_msg", nullable = true)
private String errMsg;
@Schema(required = false, title = "에러메시지 상세", example = " ", description = "Runtime Error 메시지")
@Lob
@Column(name = "err_detail", nullable = true)
private String errDetail;
}

@ -0,0 +1,57 @@
package cokr.xit.ntri.api.recv.entity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;
import lombok.experimental.SuperBuilder;
import javax.persistence.*;
@Getter
@ToString
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(schema = "", name = "ntri_recv_levy_cancel")
@Schema(name = "RecvLevyCancel", title = "부과취소정보(실시간)", description = "세외수입시스템으로 부과자료 연계 후 부과자료 삭제 시 삭제정보 실시간 제공(재 부과 연계시 부과연계관리키는 변경하여 제공)")
public class RecvLevyCancel extends RecvBaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id", nullable = false)
private Long id;
@Schema(required = false, title = "자치단체코드", example = " ", description = "행정표준코드관리시스템의 자치단체코드")
@Column(name = "sgb_cd", length = 7)
private String sgbCd;
@Schema(required = false, title = "연계관리키", example = " ", description = "연계대상 기관에서 관리하는 유일키")
@Column(name = "link_mng_key", length = 50)
private String linkMngKey;
@Schema(required = false, title = "과세번호", example = " ", description = "과세자료의 유일한 번호. 개별자료인 경우")
@Column(name = "taxn_no", length = 31)
private String taxnNo;
@Schema(required = false, title = "부과취소일자", example = " ", description = " ")
@Column(name = "lvy_rtrcn_ymd", length = 8)
private String lvyRtrcnYmd;
@Schema(required = false, title = "삭제사유내용", example = " ", description = " ")
@Column(name = "del_rsn_cn", length = 4000)
private String delRsnCn;
@Schema(required = false, title = "예비항목1", example = " ", description = " ")
@Column(name = "rsve_item1", length = 200)
private String rsveItem1;
@Schema(required = false, title = "예비항목2", example = " ", description = " ")
@Column(name = "rsve_item2", length = 200)
private String rsveItem2;
@Schema(required = false, title = "예비항목3", example = " ", description = " ")
@Column(name = "rsve_item3", length = 200)
private String rsveItem3;
@Schema(required = false, title = "예비항목4", example = " ", description = " ")
@Column(name = "rsve_item4", length = 200)
private String rsveItem4;
@Schema(required = false, title = "예비항목5", example = " ", description = " ")
@Column(name = "rsve_item5", length = 200)
private String rsveItem5;
}

@ -0,0 +1,201 @@
package cokr.xit.ntri.api.recv.entity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;
import lombok.experimental.SuperBuilder;
import javax.persistence.*;
@Getter
@ToString
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(schema = "", name = "ntri_recv_levy_result")
@Schema(name = "RecvLevyResult", title = "부과결과정보(실시간)", description = "세외수입시스템으로 부과자료 연계 후 결의처리 시 전자납부번호 및 가상계좌번호 실시간 제공")
public class RecvLevyResult extends RecvBaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id", nullable = false)
private Long id;
@Schema(required = false, title = "자치단체코드", example = " ", description = "행정표준코드관리시스템의 자치단체코드")
@Column(name = "sgb_cd", length = 7)
private String sgbCd;
@Schema(required = false, title = "연계관리키", example = " ", description = "연계대상 기관에서 관리하는 유일키")
@Column(name = "link_mng_key", length = 50)
private String linkMngKey;
@Schema(required = false, title = "과세번호", example = " ", description = "과세자료의 유일한 번호. 개별자료인 경우")
@Column(name = "taxn_no", length = 31)
private String taxnNo;
@Schema(required = false, title = "통합과세번호", example = " ", description = "과세자료(과세번호)의 통합관리번호. 통합자료인 경우")
@Column(name = "unty_taxn_no", length = 31)
private String untyTaxnNo;
@Schema(required = false, title = "부서코드", example = " ", description = "행정표준코드관리시스템의 부서코드")
@Column(name = "dpt_cd", length = 7)
private String dptCd;
@Schema(required = false, title = "특별회계사업코드", example = " ", description = " ")
@Column(name = "spcl_fis_biz_cd", length = 4)
private String spclFisBizCd;
@Schema(required = false, title = "회계연도", example = " ", description = " ")
@Column(name = "fyr", length = 4)
private String fyr;
@Schema(required = false, title = "회계구분코드", example = " ", description = "16:국세, 31:시도세, 41:시군구세, 51:특별회계시도세, 61:특별회계시군구세")
@Column(name = "act_se_cd", length = 2)
private String actSeCd;
@Schema(required = false, title = "대표세입과목코드", example = " ", description = " ")
@Column(name = "rprs_txm_cd", length = 6)
private String rprsTxmCd;
@Schema(required = false, title = "운영항목코드", example = " ", description = " ")
@Column(name = "oper_item_cd", length = 3)
private String operItemCd;
@Schema(required = false, title = "부과번호", example = " ", description = " ")
@Column(name = "lvy_no", length = 6)
private String lvyNo;
@Schema(required = false, title = "분납번호", example = " ", description = " ")
@Column(name = "itm_no", length = 2)
private String itmNo;
@Schema(required = false, title = "전자납부번호", example = " ", description = " ")
@Column(name = "epay_no", length = 19)
private String epayNo;
@Schema(required = false, title = "통합가상계좌은행명1", example = " ", description = " ")
@Column(name = "vtlac_bank_nm1", length = 100)
private String vtlacBankNm1;
@Schema(required = false, title = "통합가상계좌은행명2", example = " ", description = " ")
@Column(name = "vtlac_bank_nm2", length = 100)
private String vtlacBankNm2;
@Schema(required = false, title = "통합가상계좌은행명3", example = " ", description = " ")
@Column(name = "vtlac_bank_nm3", length = 100)
private String vtlacBankNm3;
@Schema(required = false, title = "통합가상계좌은행명4", example = " ", description = " ")
@Column(name = "vtlac_bank_nm4", length = 100)
private String vtlacBankNm4;
@Schema(required = false, title = "통합가상계좌은행명5", example = " ", description = " ")
@Column(name = "vtlac_bank_nm5", length = 100)
private String vtlacBankNm5;
@Schema(required = false, title = "통합가상계좌은행명6", example = " ", description = " ")
@Column(name = "vtlac_bank_nm6", length = 100)
private String vtlacBankNm6;
@Schema(required = false, title = "통합가상계좌은행명7", example = " ", description = " ")
@Column(name = "vtlac_bank_nm7", length = 100)
private String vtlacBankNm7;
@Schema(required = false, title = "통합가상계좌은행명8", example = " ", description = " ")
@Column(name = "vtlac_bank_nm8", length = 100)
private String vtlacBankNm8;
@Schema(required = false, title = "통합가상계좌은행명9", example = " ", description = " ")
@Column(name = "vtlac_bank_nm9", length = 100)
private String vtlacBankNm9;
@Schema(required = false, title = "통합가상계좌은행명10", example = " ", description = " ")
@Column(name = "vtlac_bank_nm10", length = 100)
private String vtlacBankNm10;
@Schema(required = false, title = "통합가상계좌은행명11", example = " ", description = " ")
@Column(name = "vtlac_bank_nm11", length = 100)
private String vtlacBankNm11;
@Schema(required = false, title = "통합가상계좌은행명12", example = " ", description = " ")
@Column(name = "vtlac_bank_nm12", length = 100)
private String vtlacBankNm12;
@Schema(required = false, title = "통합가상계좌은행명13", example = " ", description = " ")
@Column(name = "vtlac_bank_nm13", length = 100)
private String vtlacBankNm13;
@Schema(required = false, title = "통합가상계좌은행명14", example = " ", description = " ")
@Column(name = "vtlac_bank_nm14", length = 100)
private String vtlacBankNm14;
@Schema(required = false, title = "통합가상계좌은행명15", example = " ", description = " ")
@Column(name = "vtlac_bank_nm15", length = 100)
private String vtlacBankNm15;
@Schema(required = false, title = "통합가상계좌은행명16", example = " ", description = " ")
@Column(name = "vtlac_bank_nm16", length = 100)
private String vtlacBankNm16;
@Schema(required = false, title = "통합가상계좌은행명17", example = " ", description = " ")
@Column(name = "vtlac_bank_nm17", length = 100)
private String vtlacBankNm17;
@Schema(required = false, title = "통합가상계좌은행명18", example = " ", description = " ")
@Column(name = "vtlac_bank_nm18", length = 100)
private String vtlacBankNm18;
@Schema(required = false, title = "통합가상계좌은행명19", example = " ", description = " ")
@Column(name = "vtlac_bank_nm19", length = 100)
private String vtlacBankNm19;
@Schema(required = false, title = "통합가상계좌은행명20", example = " ", description = " ")
@Column(name = "vtlac_bank_nm20", length = 100)
private String vtlacBankNm20;
@Schema(required = false, title = "통합가상계좌번호1", example = " ", description = " ")
@Column(name = "vr_actno1", length = 20)
private String vrActno1;
@Schema(required = false, title = "통합가상계좌번호2", example = " ", description = " ")
@Column(name = "vr_actno2", length = 20)
private String vrActno2;
@Schema(required = false, title = "통합가상계좌번호3", example = " ", description = " ")
@Column(name = "vr_actno3", length = 20)
private String vrActno3;
@Schema(required = false, title = "통합가상계좌번호4", example = " ", description = " ")
@Column(name = "vr_actno4", length = 20)
private String vrActno4;
@Schema(required = false, title = "통합가상계좌번호5", example = " ", description = " ")
@Column(name = "vr_actno5", length = 20)
private String vrActno5;
@Schema(required = false, title = "통합가상계좌번호6", example = " ", description = " ")
@Column(name = "vr_actno6", length = 20)
private String vrActno6;
@Schema(required = false, title = "통합가상계좌번호7", example = " ", description = " ")
@Column(name = "vr_actno7", length = 20)
private String vrActno7;
@Schema(required = false, title = "통합가상계좌번호8", example = " ", description = " ")
@Column(name = "vr_actno8", length = 20)
private String vrActno8;
@Schema(required = false, title = "통합가상계좌번호9", example = " ", description = " ")
@Column(name = "vr_actno9", length = 20)
private String vrActno9;
@Schema(required = false, title = "통합가상계좌번호10", example = " ", description = " ")
@Column(name = "vr_actno10", length = 20)
private String vrActno10;
@Schema(required = false, title = "통합가상계좌번호11", example = " ", description = " ")
@Column(name = "vr_actno11", length = 20)
private String vrActno11;
@Schema(required = false, title = "통합가상계좌번호12", example = " ", description = " ")
@Column(name = "vr_actno12", length = 20)
private String vrActno12;
@Schema(required = false, title = "통합가상계좌번호13", example = " ", description = " ")
@Column(name = "vr_actno13", length = 20)
private String vrActno13;
@Schema(required = false, title = "통합가상계좌번호14", example = " ", description = " ")
@Column(name = "vr_actno14", length = 20)
private String vrActno14;
@Schema(required = false, title = "통합가상계좌번호15", example = " ", description = " ")
@Column(name = "vr_actno15", length = 20)
private String vrActno15;
@Schema(required = false, title = "통합가상계좌번호16", example = " ", description = " ")
@Column(name = "vr_actno16", length = 20)
private String vrActno16;
@Schema(required = false, title = "통합가상계좌번호17", example = " ", description = " ")
@Column(name = "vr_actno17", length = 20)
private String vrActno17;
@Schema(required = false, title = "통합가상계좌번호18", example = " ", description = " ")
@Column(name = "vr_actno18", length = 20)
private String vrActno18;
@Schema(required = false, title = "통합가상계좌번호19", example = " ", description = " ")
@Column(name = "vr_actno19", length = 20)
private String vrActno19;
@Schema(required = false, title = "통합가상계좌번호20", example = " ", description = " ")
@Column(name = "vr_actno20", length = 20)
private String vrActno20;
@Schema(required = false, title = "예비항목1", example = " ", description = " ")
@Column(name = "rsve_item1", length = 200)
private String rsveItem1;
@Schema(required = false, title = "예비항목2", example = " ", description = " ")
@Column(name = "rsve_item2", length = 200)
private String rsveItem2;
@Schema(required = false, title = "예비항목3", example = " ", description = " ")
@Column(name = "rsve_item3", length = 200)
private String rsveItem3;
@Schema(required = false, title = "예비항목4", example = " ", description = " ")
@Column(name = "rsve_item4", length = 200)
private String rsveItem4;
@Schema(required = false, title = "예비항목5", example = " ", description = " ")
@Column(name = "rsve_item5", length = 200)
private String rsveItem5;
}

@ -0,0 +1,139 @@
package cokr.xit.ntri.api.recv.entity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;
import lombok.experimental.SuperBuilder;
import javax.persistence.*;
@Getter
@ToString
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(schema = "", name = "ntri_recv_rciv_info")
@Schema(name = "RecvRcivInfo", title = "수납정보(실시간)", description = "세외수입시스템으로 부과자료 연계 후 수납처리 시 실시간 제공")
public class RecvRcivInfo extends RecvBaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id", nullable = false)
private Long id;
@Schema(required = false, title = "자치단체코드", example = " ", description = "행정표준코드관리시스템의 자치단체코드")
@Column(name = "sgb_cd", length = 7)
private String sgbCd;
@Schema(required = false, title = "자치단체명", example = " ", description = "자치단체코드의 명")
@Column(name = "sgb_nm", length = 60)
private String sgbNm;
@Schema(required = false, title = "연계관리키", example = " ", description = "연계대상 기관에서 관리하는 유일키")
@Column(name = "link_mng_key", length = 50)
private String linkMngKey;
@Schema(required = false, title = "과세번호", example = " ", description = "과세자료의 유일한 번호. 개별자료인 경우")
@Column(name = "taxn_no", length = 31)
private String taxnNo;
@Schema(required = false, title = "통합과세번호", example = " ", description = "과세자료(과세번호)의 통합관리번호. 통합자료인 경우")
@Column(name = "unty_taxn_no", length = 31)
private String untyTaxnNo;
@Schema(required = false, title = "부서코드", example = " ", description = "행정표준코드관리시스템의 부서코드")
@Column(name = "dpt_cd", length = 7)
private String dptCd;
@Schema(required = false, title = "부서명", example = " ", description = "행정표준코드관리시스템의 부서코드의 명")
@Column(name = "dpt_nm", length = 200)
private String dptNm;
@Schema(required = false, title = "특별회계사업코드", example = " ", description = " ")
@Column(name = "spcl_fis_biz_cd", length = 4)
private String spclFisBizCd;
@Schema(required = false, title = "특별회계사업명", example = " ", description = " ")
@Column(name = "spcl_fis_biz_nm", length = 100)
private String spclFisBizNm;
@Schema(required = false, title = "회계연도", example = " ", description = " ")
@Column(name = "fyr", length = 4)
private String fyr;
@Schema(required = false, title = "회계구분코드", example = " ", description = "16:국세, 31:시도세, 41:시군구세, 51:특별회계시도세, 61:특별회계시군구세")
@Column(name = "act_se_cd", length = 2)
private String actSeCd;
@Schema(required = false, title = "회계구분명", example = " ", description = " ")
@Column(name = "act_se_nm", length = 100)
private String actSeNm;
@Schema(required = false, title = "대표세입과목코드", example = " ", description = " ")
@Column(name = "rprs_txm_cd", length = 6)
private String rprsTxmCd;
@Schema(required = false, title = "대표세입과목명", example = " ", description = " ")
@Column(name = "rprs_txm_nm", length = 100)
private String rprsTxmNm;
@Schema(required = false, title = "운영항목코드", example = " ", description = " ")
@Column(name = "oper_item_cd", length = 3)
private String operItemCd;
@Schema(required = false, title = "운영항목명", example = " ", description = " ")
@Column(name = "oper_item_nm", length = 100)
private String operItemNm;
@Schema(required = false, title = "부과번호", example = " ", description = " ")
@Column(name = "lvy_no", length = 6)
private String lvyNo;
@Schema(required = false, title = "분납번호", example = " ", description = "제도에 따른 부과자료 분납순번 01~89, 일부납부 신청에 따른 부과자료 순번 90~99")
@Column(name = "itm_no", length = 2)
private String itmNo;
@Schema(required = false, title = "전자납부번호", example = " ", description = " ")
@Column(name = "epay_no", length = 19)
private String epayNo;
@Schema(required = false, title = "수납번호", example = " ", description = "수납순번")
@Column(name = "rcvmt_no", length = 2)
private String rcvmtNo;
@Schema(required = false, title = "수납구분코드", example = " ", description = "01:완납, 02:이중수납, 03:분납, 04:과납, 05:오납, 06:일부수납")
@Column(name = "rcvmt_se_cd", length = 2)
private String rcvmtSeCd;
@Schema(required = false, title = "수납구분명", example = " ", description = "수납구분코드명(일부납부, 완납 등)")
@Column(name = "rcvmt_se_nm", length = 100)
private String rcvmtSeNm;
@Schema(required = false, title = "수납일자", example = " ", description = " ")
@Column(name = "rcvmt_ymd", length = 8)
private String rcvmtYmd;
@Schema(required = false, title = "회계일자", example = " ", description = " ")
@Column(name = "act_ymd", length = 8)
private String actYmd;
@Schema(required = false, title = "이체일자", example = " ", description = " ")
@Column(name = "tsf_ymd", length = 8)
private String tsfYmd;
@Schema(required = false, title = "수납본세금액", example = " ", description = "수납본세")
@Column(name = "rcvmt_pct_amt", length = 15)
private String rcvmtPctAmt;
@Schema(required = false, title = "수납가산금액", example = " ", description = "수납가산금")
@Column(name = "rcvmt_adtn_amt", length = 15)
private String rcvmtAdtnAmt;
@Schema(required = false, title = "수납이자금액", example = " ", description = "수납이자")
@Column(name = "rcvmt_intr_amt", length = 15)
private String rcvmtIntrAmt;
@Schema(required = false, title = "은행명", example = " ", description = " ")
@Column(name = "bank_nm", length = 30)
private String bankNm;
@Schema(required = false, title = "수납유형코드", example = " ", description = "01:OCR수납, 02:수기수납, 03:계좌이체, 04:세입정정, 05:배당")
@Column(name = "rcvmt_ty_cd", length = 2)
private String rcvmtTyCd;
@Schema(required = false, title = "수납유형", example = " ", description = "납부매체정보(계좌이체, 신용카드결제, 가상계좌수납 등)")
@Column(name = "rcvmt_ty", length = 300)
private String rcvmtTy;
@Schema(required = false, title = "예비항목1", example = " ", description = " ")
@Column(name = "rsve_item1", length = 200)
private String rsveItem1;
@Schema(required = false, title = "예비항목2", example = " ", description = " ")
@Column(name = "rsve_item2", length = 200)
private String rsveItem2;
@Schema(required = false, title = "예비항목3", example = " ", description = " ")
@Column(name = "rsve_item3", length = 200)
private String rsveItem3;
@Schema(required = false, title = "예비항목4", example = " ", description = " ")
@Column(name = "rsve_item4", length = 200)
private String rsveItem4;
@Schema(required = false, title = "예비항목5", example = " ", description = " ")
@Column(name = "rsve_item5", length = 200)
private String rsveItem5;
}

@ -0,0 +1,116 @@
package cokr.xit.ntri.api.recv.entity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;
import lombok.experimental.SuperBuilder;
import javax.persistence.*;
@Getter
@ToString
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(schema = "", name = "ntri_recv_rdcamt_info")
@Schema(name = "RecvRdcamtInfo", title = "감액정보(실시간)", description = "세외수입시스템으로 부과자료 연계 후 감액자료 발생 시 실시간 제공")
public class RecvRdcamtInfo extends RecvBaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id", nullable = false)
private Long id;
@Schema(required = false, title = "자치단체코드", example = " ", description = "행정표준코드관리시스템의 자치단체코드")
@Column(name = "sgb_cd", length = 7)
private String sgbCd;
@Schema(required = false, title = "자치단체명", example = " ", description = "자치단체코드의 명")
@Column(name = "sgb_nm", length = 60)
private String sgbNm;
@Schema(required = false, title = "연계관리키", example = " ", description = "연계대상 기관에서 관리하는 유일키")
@Column(name = "link_mng_key", length = 50)
private String linkMngKey;
@Schema(required = false, title = "과세번호", example = " ", description = "과세자료의 유일한 번호. 개별자료인 경우")
@Column(name = "taxn_no", length = 31)
private String taxnNo;
@Schema(required = false, title = "통합과세번호", example = " ", description = "과세자료(과세번호)의 통합관리번호. 통합자료인 경우")
@Column(name = "unty_taxn_no", length = 31)
private String untyTaxnNo;
@Schema(required = false, title = "부서코드", example = " ", description = "행정표준코드관리시스템의 부서코드")
@Column(name = "dpt_cd", length = 7)
private String dptCd;
@Schema(required = false, title = "부서명", example = " ", description = "행정표준코드관리시스템의 부서코드의 명")
@Column(name = "dpt_nm", length = 200)
private String dptNm;
@Schema(required = false, title = "특별회계사업코드", example = " ", description = " ")
@Column(name = "spcl_fis_biz_cd", length = 4)
private String spclFisBizCd;
@Schema(required = false, title = "특별회계사업명", example = " ", description = " ")
@Column(name = "spcl_fis_biz_nm", length = 100)
private String spclFisBizNm;
@Schema(required = false, title = "회계연도", example = " ", description = " ")
@Column(name = "fyr", length = 4)
private String fyr;
@Schema(required = false, title = "회계구분코드", example = " ", description = "16:국세, 31:시도세, 41:시군구세, 51:특별회계시도세, 61:특별회계시군구세")
@Column(name = "act_se_cd", length = 2)
private String actSeCd;
@Schema(required = false, title = "회계구분명", example = " ", description = " ")
@Column(name = "act_se_nm", length = 100)
private String actSeNm;
@Schema(required = false, title = "대표세입과목코드", example = " ", description = " ")
@Column(name = "rprs_txm_cd", length = 6)
private String rprsTxmCd;
@Schema(required = false, title = "대표세입과목명", example = " ", description = " ")
@Column(name = "rprs_txm_nm", length = 100)
private String rprsTxmNm;
@Schema(required = false, title = "운영항목코드", example = " ", description = " ")
@Column(name = "oper_item_cd", length = 3)
private String operItemCd;
@Schema(required = false, title = "운영항목명", example = " ", description = " ")
@Column(name = "oper_item_nm", length = 100)
private String operItemNm;
@Schema(required = false, title = "부과번호", example = " ", description = " ")
@Column(name = "lvy_no", length = 6)
private String lvyNo;
@Schema(required = false, title = "분납번호", example = " ", description = " ")
@Column(name = "itm_no", length = 2)
private String itmNo;
@Schema(required = false, title = "감액일자", example = " ", description = " ")
@Column(name = "rdc_ymd", length = 8)
private String rdcYmd;
@Schema(required = false, title = "감액본세금액", example = " ", description = "감액금액")
@Column(name = "rdc_pct_amt", length = 15)
private String rdcPctAmt;
@Schema(required = false, title = "금액가산금액", example = " ", description = "감액가산금")
@Column(name = "rdc_adtn_amt", length = 15)
private String rdcAdtnAmt;
@Schema(required = false, title = "감액이자금액", example = " ", description = "감액이자")
@Column(name = "rdc_intr_amt", length = 15)
private String rdcIntrAmt;
@Schema(required = false, title = "감액금액", example = " ", description = "감액총금액")
@Column(name = "rdc_amt", length = 15)
private String rdcAmt;
@Schema(required = false, title = "감액사유내용", example = " ", description = "감액사유내용(세액오류감액, 행정기관착오 등")
@Column(name = "rdc_rsn_cn", length = 255)
private String rdcRsnCn;
@Schema(required = false, title = "예비항목1", example = " ", description = " ")
@Column(name = "rsve_item1", length = 200)
private String rsveItem1;
@Schema(required = false, title = "예비항목2", example = " ", description = " ")
@Column(name = "rsve_item2", length = 200)
private String rsveItem2;
@Schema(required = false, title = "예비항목3", example = " ", description = " ")
@Column(name = "rsve_item3", length = 200)
private String rsveItem3;
@Schema(required = false, title = "예비항목4", example = " ", description = " ")
@Column(name = "rsve_item4", length = 200)
private String rsveItem4;
@Schema(required = false, title = "예비항목5", example = " ", description = " ")
@Column(name = "rsve_item5", length = 200)
private String rsveItem5;
}

@ -0,0 +1,7 @@
package cokr.xit.ntri.api.recv.entity.repository;
import cokr.xit.ntri.api.recv.entity.RecvError;
import org.springframework.data.jpa.repository.JpaRepository;
public interface RecvErrorRepository extends JpaRepository<RecvError, Long> {
}

@ -0,0 +1,7 @@
package cokr.xit.ntri.api.recv.entity.repository;
import cokr.xit.ntri.api.recv.entity.RecvLevyCancel;
import org.springframework.data.jpa.repository.JpaRepository;
public interface RecvLevyCancelRepository extends JpaRepository<RecvLevyCancel, Long> {
}

@ -0,0 +1,7 @@
package cokr.xit.ntri.api.recv.entity.repository;
import cokr.xit.ntri.api.recv.entity.RecvLevyResult;
import org.springframework.data.jpa.repository.JpaRepository;
public interface RecvLevyResultRepository extends JpaRepository<RecvLevyResult, Long> {
}

@ -0,0 +1,7 @@
package cokr.xit.ntri.api.recv.entity.repository;
import cokr.xit.ntri.api.recv.entity.RecvRcivInfo;
import org.springframework.data.jpa.repository.JpaRepository;
public interface RecvRcivInfoRepository extends JpaRepository<RecvRcivInfo, Long> {
}

@ -0,0 +1,7 @@
package cokr.xit.ntri.api.recv.entity.repository;
import cokr.xit.ntri.api.recv.entity.RecvRdcamtInfo;
import org.springframework.data.jpa.repository.JpaRepository;
public interface RecvRdcamtInfoRepository extends JpaRepository<RecvRdcamtInfo, Long> {
}

@ -0,0 +1,26 @@
package cokr.xit.ntri.api.recv.model;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Builder;
import lombok.Data;
@Data
@Builder
public class RecvResponseVO {
@Schema(required = false, title = "자치단체코드", example = " ", description = " ")
private String sgbCd;
@Schema(required = false, title = "연계대상코드", example = " ", description = " ")
private String linkTrgtCd;
@Schema(required = false, title = "연계관리키", example = " ", description = " ")
private String linkMngKey;
@Schema(required = false, title = "연계결과코드", example = " ", description = " ")
private String linkRstCd;
@Schema(required = false, title = "연계결과메시지", example = " ", description = " ")
private String linkRstMsg;
}

@ -0,0 +1,176 @@
package cokr.xit.ntri.api.recv.presentation;
import cokr.xit.ntri.api.recv.entity.repository.*;
import cokr.xit.ntri.api.recv.service.RecvApiSpec;
import cokr.xit.ntri.api.recv.service.impl.LevyCancel;
import cokr.xit.ntri.api.recv.service.impl.LevyResult;
import cokr.xit.ntri.api.recv.service.impl.RcivInfo;
import cokr.xit.ntri.api.recv.service.impl.RdcamtInfo;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.ExampleObject;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
@Slf4j
@RequiredArgsConstructor
@RestController
@Tag(name = "NtriRecvApi", description = "차세대 세외수입 개별시스템 연계")
public class NtriRecvApi {
@Value("${app.response.linkTrgtCd}")
private String LINK_TRGT_CD;
private final RecvErrorRepository recvErrorRepository;
private final RecvLevyCancelRepository recvLevyCancelRepository;
private final RecvLevyResultRepository recvLevyResultRepository;
private final RecvRcivInfoRepository recvRcivInfoRepository;
private final RecvRdcamtInfoRepository recvRdcamtInfoRepository;
private ObjectMapper mapper = new ObjectMapper();
@io.swagger.v3.oas.annotations.parameters.RequestBody(required = true, content = {
@Content(mediaType = "application/json", examples = {
@ExampleObject(name = "Example..."
, summary = "부과결과정보 전송", description = "세외수입시스템 -> 개별시스템을 호출하여 데이터를 전송 한다."
, value = "{\"header\":{\"ifDate\":\"20210412103022\",\"ifMsgKey\":\"Z211103155123435-e7def4c1652a478e9c77525ab5b3ebda\",\"ifId\":\"ERR_Z000001DCP_1741000NIS_0001\",\"source\":\"3820000DCP\",\"target\":\"1741000NIS\",\"ifType\":\"S\",\"ifFormat\":\"J\",\"retName\":\"\",\"retCode\":\"200\"},\"body\":{\"reqVo\":[{\"registDt\":null,\"lastUpdtDt\":null,\"rspSgbCd\":null,\"rspLinkTrgtCd\":null,\"rspLinkMngKey\":null,\"rspLinkRstCd\":null,\"rspLinkRstMsg\":null,\"id\":null,\"sgbCd\":null,\"linkMngKey\":null,\"taxnNo\":null,\"untyTaxnNo\":null,\"dptCd\":null,\"spclFisBizCd\":null,\"fyr\":null,\"actSeCd\":null,\"rprsTxmCd\":null,\"operItemCd\":null,\"lvyNo\":null,\"itmNo\":null,\"epayNo\":null,\"vtlacBankNm1\":null,\"vtlacBankNm2\":null,\"vtlacBankNm3\":null,\"vtlacBankNm4\":null,\"vtlacBankNm5\":null,\"vtlacBankNm6\":null,\"vtlacBankNm7\":null,\"vtlacBankNm8\":null,\"vtlacBankNm9\":null,\"vtlacBankNm10\":null,\"vtlacBankNm11\":null,\"vtlacBankNm12\":null,\"vtlacBankNm13\":null,\"vtlacBankNm14\":null,\"vtlacBankNm15\":null,\"vtlacBankNm16\":null,\"vtlacBankNm17\":null,\"vtlacBankNm18\":null,\"vtlacBankNm19\":null,\"vtlacBankNm20\":null,\"vrActno1\":null,\"vrActno2\":null,\"vrActno3\":null,\"vrActno4\":null,\"vrActno5\":null,\"vrActno6\":null,\"vrActno7\":null,\"vrActno8\":null,\"vrActno9\":null,\"vrActno10\":null,\"vrActno11\":null,\"vrActno12\":null,\"vrActno13\":null,\"vrActno14\":null,\"vrActno15\":null,\"vrActno16\":null,\"vrActno17\":null,\"vrActno18\":null,\"vrActno19\":null,\"vrActno20\":null,\"rsveItem1\":null,\"rsveItem2\":null,\"rsveItem3\":null,\"rsveItem4\":null,\"rsveItem5\":null}]}}")
})
})
@PostMapping(value = "/recv/levy/result", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "부과결과정보(실시간)", description = "세외수입시스템으로 부과자료 연계 후 결의처리 시 전자납부번호 및 가상계좌번호 실시간 제공")
public ResponseEntity levyResult(@RequestBody String jParam) throws Exception {
//저장
RecvApiSpec recv = LevyResult.builder()
.jpaRepository(recvLevyResultRepository)
.jParam(jParam)
.recvErrorRepository(recvErrorRepository)
.linkTrgtCd(LINK_TRGT_CD)
.build();
// Map<String, Object> resultInfo = this.execute(recv, jParam);
recv.execute();
Map<String, Object> resultInfo = (Map<String, Object>) recv.getResponse();
return new ResponseEntity(resultInfo, HttpStatus.OK);
}
@io.swagger.v3.oas.annotations.parameters.RequestBody(required = true, content = {
@Content(mediaType = "application/json", examples = {
@ExampleObject(name = "Example..."
, summary = "부과취소정보 전송", description = "세외수입시스템 -> 개별시스템을 호출하여 데이터를 전송 한다."
, value = "{\"header\":{\"ifDate\":\"20210412103022\",\"ifMsgKey\":\"Z211103155123435-e7def4c1652a478e9c77525ab5b3ebda\",\"ifId\":\"ERR_Z000001DCP_1741000NIS_0002\",\"source\":\"3820000DCP\",\"target\":\"1741000NIS\",\"ifType\":\"S\",\"ifFormat\":\"J\",\"retName\":\"\",\"retCode\":\"200\"},\"body\":{\"reqVo\":[{\"registDt\":null,\"lastUpdtDt\":null,\"rspSgbCd\":null,\"rspLinkTrgtCd\":null,\"rspLinkMngKey\":null,\"rspLinkRstCd\":null,\"rspLinkRstMsg\":null,\"id\":null,\"sgbCd\":null,\"linkMngKey\":null,\"taxnNo\":null,\"lvyRtrcnYmd\":null,\"delRsnCn\":null,\"rsveItem1\":null,\"rsveItem2\":null,\"rsveItem3\":null,\"rsveItem4\":null,\"rsveItem5\":null}]}}")
})
})
@PostMapping(value = "/recv/levy/cancel", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "부과취소정보(실시간)", description = "세외수입시스템으로 부과자료 연계 후 부과자료 삭제 시 삭제정보 실시간 제공(재 부과 연계시 부과연계관리키는 변경하여 제공)")
public ResponseEntity levyCancel(@RequestBody String jParam) throws Exception {
//저장
RecvApiSpec recv = LevyCancel.builder()
.jpaRepository(recvLevyCancelRepository)
.jParam(jParam)
.recvErrorRepository(recvErrorRepository)
.linkTrgtCd(LINK_TRGT_CD)
.build();
// Map<String, Object> resultInfo = this.execute(recv, jParam);
recv.execute();
Map<String, Object> resultInfo = (Map<String, Object>) recv.getResponse();
return new ResponseEntity(resultInfo, HttpStatus.OK);
}
@io.swagger.v3.oas.annotations.parameters.RequestBody(required = true, content = {
@Content(mediaType = "application/json", examples = {
@ExampleObject(name = "Example..."
, summary = "수납정보 전송", description = "세외수입시스템 -> 개별시스템을 호출하여 데이터를 전송 한다."
, value = "{\"header\":{\"ifDate\":\"20210412103022\",\"ifMsgKey\":\"Z211103155123435-e7def4c1652a478e9c77525ab5b3ebda\",\"ifId\":\"ERR_Z000001DCP_1741000NIS_0003\",\"source\":\"3820000DCP\",\"target\":\"1741000NIS\",\"ifType\":\"S\",\"ifFormat\":\"J\",\"retName\":\"\",\"retCode\":\"200\"},\"body\":{\"reqVo\":[{\"registDt\":null,\"lastUpdtDt\":null,\"rspSgbCd\":null,\"rspLinkTrgtCd\":null,\"rspLinkMngKey\":null,\"rspLinkRstCd\":null,\"rspLinkRstMsg\":null,\"id\":null,\"sgbCd\":null,\"sgbNm\":null,\"linkMngKey\":null,\"taxnNo\":null,\"untyTaxnNo\":null,\"dptCd\":null,\"dptNm\":null,\"spclFisBizCd\":null,\"spclFisBizNm\":null,\"fyr\":null,\"actSeCd\":null,\"actSeNm\":null,\"rprsTxmCd\":null,\"rprsTxmNm\":null,\"operItemCd\":null,\"operItemNm\":null,\"lvyNo\":null,\"itmNo\":null,\"epayNo\":null,\"rcvmtNo\":null,\"rcvmtSeCd\":null,\"rcvmtSeNm\":null,\"rcvmtYmd\":null,\"actYmd\":null,\"tsfYmd\":null,\"rcvmtPctAmt\":null,\"rcvmtAdtnAmt\":null,\"rcvmtIntrAmt\":null,\"bankNm\":null,\"rcvmtTyCd\":null,\"rcvmtTy\":null,\"rsveItem1\":null,\"rsveItem2\":null,\"rsveItem3\":null,\"rsveItem4\":null,\"rsveItem5\":null}]}}")
})
})
@PostMapping(value = "/recv/rciv/info", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "수납정보(실시간)", description = "세외수입시스템으로 부과자료 연계 후 수납처리 시 실시간 제공")
public ResponseEntity rcivInfo(@RequestBody String jParam) throws Exception {
//저장
RecvApiSpec recv = RcivInfo.builder()
.jpaRepository(recvRcivInfoRepository)
.jParam(jParam)
.recvErrorRepository(recvErrorRepository)
.linkTrgtCd(LINK_TRGT_CD)
.build();
// Map<String, Object> resultInfo = this.execute(recv, jParam);
recv.execute();
Map<String, Object> resultInfo = (Map<String, Object>) recv.getResponse();
return new ResponseEntity(resultInfo, HttpStatus.OK);
}
@io.swagger.v3.oas.annotations.parameters.RequestBody(required = true, content = {
@Content(mediaType = "application/json", examples = {
@ExampleObject(name = "Example..."
, summary = "감액정보 전송", description = "세외수입시스템 -> 개별시스템을 호출하여 데이터를 전송 한다."
, value = "{\"header\":{\"ifDate\":\"20210412103022\",\"ifMsgKey\":\"Z211103155123435-e7def4c1652a478e9c77525ab5b3ebda\",\"ifId\":\"ERR_Z000001DCP_1741000NIS_0004\",\"source\":\"3820000DCP\",\"target\":\"1741000NIS\",\"ifType\":\"S\",\"ifFormat\":\"J\",\"retName\":\"\",\"retCode\":\"200\"},\"body\":{\"reqVo\":[{\"registDt\":null,\"lastUpdtDt\":null,\"rspSgbCd\":null,\"rspLinkTrgtCd\":null,\"rspLinkMngKey\":null,\"rspLinkRstCd\":null,\"rspLinkRstMsg\":null,\"id\":null,\"sgbCd\":null,\"sgbNm\":null,\"linkMngKey\":null,\"taxnNo\":null,\"untyTaxnNo\":null,\"dptCd\":null,\"dptNm\":null,\"spclFisBizCd\":null,\"spclFisBizNm\":null,\"fyr\":null,\"actSeCd\":null,\"actSeNm\":null,\"rprsTxmCd\":null,\"rprsTxmNm\":null,\"operItemCd\":null,\"operItemNm\":null,\"lvyNo\":null,\"itmNo\":null,\"rdcYmd\":null,\"rdcPctAmt\":null,\"rdcAdtnAmt\":null,\"rdcIntrAmt\":null,\"rdcAmt\":null,\"rdcRsnCn\":null,\"rsveItem1\":null,\"rsveItem2\":null,\"rsveItem3\":null,\"rsveItem4\":null,\"rsveItem5\":null}]}}")
})
})
@PostMapping(value = "/recv/rdcamt/info", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "감액정보(실시간)", description = "세외수입시스템으로 부과자료 연계 후 감액자료 발생 시 실시간 제공")
public ResponseEntity rdcamtInfo(@RequestBody String jParam) throws Exception {
//저장
RecvApiSpec recv = RdcamtInfo.builder()
.jpaRepository(recvRdcamtInfoRepository)
.jParam(jParam)
.recvErrorRepository(recvErrorRepository)
.linkTrgtCd(LINK_TRGT_CD)
.build();
// Map<String, Object> resultInfo = this.execute(recv, jParam);
recv.execute();
Map<String, Object> resultInfo = (Map<String, Object>) recv.getResponse();
return new ResponseEntity(resultInfo, HttpStatus.OK);
}
private Map<String, Object> execute(RecvApiSpec recv, String jParam) {
Map<String, Object> resultInfo = null;
Map<String, Object> header = null;
Map<String, Object> body = null;
try {
//parsing
resultInfo = (Map<String, Object>) mapper.readValue(jParam, Map.class);
header = (Map<String, Object>) resultInfo.get("header");
body = (Map<String, Object>) resultInfo.get("body");
//excute
recv.execute();
//result SET
header.put("retCode", "200");
header.put("retName", "성공");
body.put("resVo", recv.getResponse());
resultInfo.put("header", header);
resultInfo.put("body", body);
} catch (JsonProcessingException e) {
if (header != null) {
header.put("retCode", "500");
header.put("retName", "실패. 사유: Parameter Parsing Fail!! " + e.getMessage());
resultInfo.put("header", header);
}
} catch (Exception e) {
if (header != null) {
header.put("retCode", "500");
header.put("retName", "실패. 사유: " + e.getMessage());
resultInfo.put("header", header);
}
}
return resultInfo;
}
}

@ -0,0 +1,54 @@
package cokr.xit.ntri.api.recv.presentation;
import cokr.xit.ntri.core.config.IFConfig;
import cokr.xit.ntri.core.config.IFConfigManager;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;
@Slf4j
@RequiredArgsConstructor
@RestController
@Tag(name = "NtriTransferApi", description = "차세대 세외수입 개별시스템 API 수신 경유")
public class NtriTransferApi {
private final IFConfigManager ifConfigManager;
@PostMapping(value = "/recv", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "수신경유", description = "세외수입으로 부터 수신에 대하여 Interface ID를 확인 후 URL을 분기한다.")
public void recvtransfer(@RequestBody Map<String, Object> param, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
Map<String, Object> header = (Map<String, Object>) param.get("header");
if (header == null) {
response.getWriter().println("{\"error_code\":\"INVALID_VALUE\", \"error_message\":\"not exists 'header' in param\"}");
throw new RuntimeException("not exists 'header' in param");
}
String ifId = (String) header.get("ifId");
if (ifId == null) {
response.getWriter().println("{\"error_code\":\"INVALID_VALUE\", \"error_message\":\"not exists 'ifId' in header\"}");
throw new RuntimeException("not exists 'ifId' in header");
}
IFConfig ifConfig = ifConfigManager.getEnvironment().get(ifId);
if (ifConfig == null) {
response.getWriter().println("{\"error_code\":\"INVALID_REQUEST\", \"error_message\":\"not found IF!!\"}");
throw new RuntimeException("not found IF!!");
}
RequestDispatcher rd = request.getRequestDispatcher(ifConfig.getUrl());
rd.forward(request, response);
}
}

@ -0,0 +1,18 @@
package cokr.xit.ntri.api.recv.service;
import com.fasterxml.jackson.core.JsonProcessingException;
public interface RecvApiSpec<RT> {
void execute() throws Exception;
void parsing() throws JsonProcessingException;
void mapping();
void save();
RT getResponse();
}

@ -0,0 +1,194 @@
package cokr.xit.ntri.api.recv.service;
import cokr.xit.ntri.api.recv.code.LinkRstCd;
import cokr.xit.ntri.api.recv.entity.RecvError;
import cokr.xit.ntri.api.recv.entity.repository.RecvErrorRepository;
import cokr.xit.ntri.api.recv.model.RecvResponseVO;
import cokr.xit.ntri.support.utils.CmmnUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.orm.jpa.JpaSystemException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@RequiredArgsConstructor
public abstract class RecvApiSupport<DATA, E> implements RecvApiSpec<Map<String, Object>> {
protected final String jParam;
protected final JpaRepository jpaRepository;
private final RecvErrorRepository recvErrorRepository;
protected final String linkTrgtCd;
protected ObjectMapper mapper = new ObjectMapper();
private Map<String, String> header;
private Map<String, Object> body;
private List<DATA> datas;
private DATA data;
private E entity;
private RecvResponseVO recvResponseVO;
private String sgbCd;
private String linkMngKey;
@Override
public void execute() throws Exception {
String phase = null;
List<Map<String, String>> fails = new ArrayList<>();
try {
phase = "내부오류. 연계대상코드(linkTrgtCd) 미설정";
if (linkTrgtCd == null || "".equals(linkTrgtCd) || " ".equals(linkTrgtCd) || "unknown".equals(linkTrgtCd))
throw new RuntimeException();
phase = "Parameter 파싱 실패";
parsing();
for (DATA data : datas) {
try {
this.data = data;
phase = "파싱 데이터 객체 매핑 실패";
mapping();
phase = "데이터 저장 실패";
save();
phase = "결과 저장 실패";
this.entity = setResult(this.entity);
save();
} catch (JpaSystemException e) {
Map<String, String> fail = this.genFail(String.format("%s. 표준연계지침의 메시지전문구성 필드의 타입과 사이즈가 다를 경우 DB에 저장 할 수 없습니다.", phase), e);
fails.add(fail);
} catch (Exception e) {
Map<String, String> fail = this.genFail(phase, e);
fails.add(fail);
Exception ex = new RuntimeException(phase, e);
this.entity = setResult(this.entity, ex);
save();
}
}
if (CmmnUtil.isEmpty(fails))
this.setResponse(LinkRstCd.ok, LinkRstCd.ok.getCodeNm());
else {
if (fails.size() == 1)
this.setResponse(LinkRstCd.internalFail, String.format("%s. [식별키 %s]", fails.get(0).get("errMsg"), fails.get(0).get("linkMngKey")));
else
this.setResponse(LinkRstCd.internalFail, String.format("처리에 실패 했습니다. [식별키 %s] 외 %d 건", fails.get(0).get("linkMngKey"), fails.size() - 1));
}
} catch (JsonProcessingException e) {
this.setResponse(LinkRstCd.internalFail, "처리에 실패 했습니다.", true, String.format("정상적인 요청전문이 아닙니다. %s", e.getMessage()));
} catch (Exception e) {
this.setResponse(LinkRstCd.internalFail, "처리에 실패 했습니다.", true, phase);
} finally {
if (fails.size() > 0) {
final String rawDataHeader = mapper.writeValueAsString(this.header);
recvErrorRepository.saveAll(fails.stream()
.map(fail -> RecvError.builder()
.sgbCd(fail.get("sgbCd"))
.ifId(this.header.get("ifId"))
.linkTrgtCd(this.linkTrgtCd)
.linkMngKey(fail.get("linkMngKey"))
.rawDataHeader(rawDataHeader)
.reqData(fail.get("reqData"))
.errMsg(fail.get("errMsg"))
.errDetail(fail.get("errDetail"))
.build())
.collect(Collectors.toList())
);
}
}
}
private Map<String, String> genFail(String errMsg, Exception e) throws JsonProcessingException {
Map<String, String> fail = new HashMap<>();
fail.put("sgbCd", this.sgbCd);
fail.put("linkMngKey", this.linkMngKey);
fail.put("reqData", CmmnUtil.isEmpty(this.data) ? null : mapper.writeValueAsString(this.data));
fail.put("errMsg", errMsg);
fail.put("errDetail", CmmnUtil.printStackTraceToString(e));
return fail;
}
protected abstract Map<String, String> parsingHeader(String jParam) throws JsonProcessingException;
protected abstract Map<String, Object> parsingBody(String jParam) throws JsonProcessingException;
protected abstract List<DATA> parsingData(Map<String, Object> body);
@Override
public void parsing() throws JsonProcessingException {
String phase = "";
try {
phase = "header parsing fail";
this.header = parsingHeader(this.jParam);
if (this.header == null) throw new RuntimeException();
phase = "body parsing fail";
this.body = parsingBody(this.jParam);
if (this.body == null) throw new RuntimeException();
phase = "data parsing fail";
this.datas = parsingData(this.body);
if (this.datas == null) throw new RuntimeException();
} catch (Exception e) {
throw new JsonMappingException(phase);
}
}
protected abstract E mapping(DATA m);
@Override
public void mapping() {
this.entity = mapping(data);
this.sgbCd = getSgbCd(this.entity);
this.linkMngKey = getLinkMngKey(this.entity);
}
protected abstract String getSgbCd(E e);
protected abstract String getLinkMngKey(E e);
@Override
public void save() {
this.jpaRepository.save(entity);
}
protected abstract E setResult(E entity);
protected abstract E setResult(E entity, Exception e);
private void setResponse(LinkRstCd linkRstCd, String linkRstMsg) {
this.setResponse(linkRstCd, linkRstMsg, false, null);
}
private void setResponse(LinkRstCd linkRstCd, String linkRstMsg, boolean hasException, String headerErrMsg) {
if (this.header == null) this.header = new HashMap<>();
if (this.body == null) this.body = new HashMap<>();
if (hasException) {
this.header.put("retCode", "500");
this.header.put("retName", headerErrMsg);
} else {
this.header.put("retCode", "200");
this.header.put("retName", "성공");
}
this.recvResponseVO = RecvResponseVO.builder()
.sgbCd(this.sgbCd)
.linkTrgtCd(this.linkTrgtCd)
.linkMngKey(this.linkMngKey)
.linkRstCd(linkRstCd.getExtCode())
.linkRstMsg(linkRstMsg)
.build();
}
@Override
public Map<String, Object> getResponse() {
Map<String, Object> response = new HashMap<>();
response.put("header", this.header);
this.body.put("resVo", this.recvResponseVO);
response.put("body", this.body);
return response;
}
}

@ -0,0 +1,84 @@
package cokr.xit.ntri.api.recv.service.impl;
import cokr.xit.ntri.api.recv.code.LinkRstCd;
import cokr.xit.ntri.api.recv.entity.RecvLevyCancel;
import cokr.xit.ntri.api.recv.entity.repository.RecvErrorRepository;
import cokr.xit.ntri.api.recv.service.RecvApiSupport;
import com.fasterxml.jackson.core.JsonProcessingException;
import lombok.Builder;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
import java.util.Map;
public class LevyCancel extends RecvApiSupport<Map<String, String>, RecvLevyCancel> {
@Builder(builderClassName = "builder")
public LevyCancel(String jParam, JpaRepository jpaRepository, RecvErrorRepository recvErrorRepository, String linkTrgtCd) {
super(jParam, jpaRepository, recvErrorRepository, linkTrgtCd);
}
@Override
protected Map<String, String> parsingHeader(String jParam) throws JsonProcessingException {
return (Map<String, String>) mapper.readValue(jParam, Map.class).get("header");
}
@Override
protected Map<String, Object> parsingBody(String jParam) throws JsonProcessingException {
return (Map<String, Object>) mapper.readValue(jParam, Map.class).get("body");
}
@Override
protected List<Map<String, String>> parsingData(Map<String, Object> body) {
return (List<Map<String, String>>) body.get("reqVo");
}
@Override
protected RecvLevyCancel mapping(Map<String, String> m) {
return RecvLevyCancel.builder()
.sgbCd(m.get("sgbCd"))
.linkMngKey(m.get("linkMngKey"))
.taxnNo(m.get("taxnNo"))
.lvyRtrcnYmd(m.get("lvyRtrcnYmd"))
.delRsnCn(m.get("delRsnCn"))
.rsveItem1(m.get("rsveItem1"))
.rsveItem2(m.get("rsveItem2"))
.rsveItem3(m.get("rsveItem3"))
.rsveItem4(m.get("rsveItem4"))
.rsveItem5(m.get("rsveItem5"))
.build();
}
@Override
protected String getSgbCd(RecvLevyCancel recvLevyCancel) {
return recvLevyCancel.getSgbCd();
}
@Override
protected String getLinkMngKey(RecvLevyCancel recvLevyCancel) {
return recvLevyCancel.getLinkMngKey();
}
@Override
protected RecvLevyCancel setResult(RecvLevyCancel entity) {
entity.setRspSgbCd(entity.getSgbCd());
entity.setRspLinkTrgtCd(super.linkTrgtCd);
entity.setRspLinkMngKey(entity.getLinkMngKey());
entity.setRspLinkRstCd(LinkRstCd.ok);
entity.setRspLinkRstMsg(LinkRstCd.ok.getCodeNm());
return entity;
}
@Override
protected RecvLevyCancel setResult(RecvLevyCancel entity, Exception e) {
if (entity == null)
entity = RecvLevyCancel.builder().build();
entity.setRspSgbCd(entity.getSgbCd());
entity.setRspLinkTrgtCd(super.linkTrgtCd);
entity.setRspLinkMngKey(entity.getLinkMngKey());
entity.setRspLinkRstCd(LinkRstCd.internalFail);
entity.setRspLinkRstMsg(e.getMessage());
return entity;
}
}

@ -0,0 +1,132 @@
package cokr.xit.ntri.api.recv.service.impl;
import cokr.xit.ntri.api.recv.code.LinkRstCd;
import cokr.xit.ntri.api.recv.entity.RecvLevyResult;
import cokr.xit.ntri.api.recv.entity.repository.RecvErrorRepository;
import cokr.xit.ntri.api.recv.service.RecvApiSupport;
import com.fasterxml.jackson.core.JsonProcessingException;
import lombok.Builder;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
import java.util.Map;
public class LevyResult extends RecvApiSupport<Map<String, String>, RecvLevyResult> {
@Builder(builderClassName = "builder")
public LevyResult(String jParam, JpaRepository jpaRepository, RecvErrorRepository recvErrorRepository, String linkTrgtCd) {
super(jParam, jpaRepository, recvErrorRepository, linkTrgtCd);
}
@Override
protected Map<String, String> parsingHeader(String jParam) throws JsonProcessingException {
return (Map<String, String>) mapper.readValue(jParam, Map.class).get("header");
}
@Override
protected Map<String, Object> parsingBody(String jParam) throws JsonProcessingException {
return (Map<String, Object>) mapper.readValue(jParam, Map.class).get("body");
}
@Override
protected List<Map<String, String>> parsingData(Map<String, Object> body) {
return (List<Map<String, String>>) body.get("reqVo");
}
@Override
protected RecvLevyResult mapping(Map<String, String> m) {
return RecvLevyResult.builder()
.sgbCd(m.get("sgbCd"))
.linkMngKey(m.get("linkMngKey"))
.taxnNo(m.get("taxnNo"))
.untyTaxnNo(m.get("untyTaxnNo"))
.dptCd(m.get("dptCd"))
.spclFisBizCd(m.get("spclFisBizCd"))
.fyr(m.get("fyr"))
.actSeCd(m.get("actSeCd"))
.rprsTxmCd(m.get("rprsTxmCd"))
.operItemCd(m.get("operItemCd"))
.lvyNo(m.get("lvyNo"))
.itmNo(m.get("itmNo"))
.epayNo(m.get("epayNo"))
.vtlacBankNm1(m.get("vtlacBankNm1"))
.vtlacBankNm2(m.get("vtlacBankNm2"))
.vtlacBankNm3(m.get("vtlacBankNm3"))
.vtlacBankNm4(m.get("vtlacBankNm4"))
.vtlacBankNm5(m.get("vtlacBankNm5"))
.vtlacBankNm6(m.get("vtlacBankNm6"))
.vtlacBankNm7(m.get("vtlacBankNm7"))
.vtlacBankNm8(m.get("vtlacBankNm8"))
.vtlacBankNm9(m.get("vtlacBankNm9"))
.vtlacBankNm10(m.get("vtlacBankNm10"))
.vtlacBankNm11(m.get("vtlacBankNm11"))
.vtlacBankNm12(m.get("vtlacBankNm12"))
.vtlacBankNm13(m.get("vtlacBankNm13"))
.vtlacBankNm14(m.get("vtlacBankNm14"))
.vtlacBankNm15(m.get("vtlacBankNm15"))
.vtlacBankNm16(m.get("vtlacBankNm16"))
.vtlacBankNm17(m.get("vtlacBankNm17"))
.vtlacBankNm18(m.get("vtlacBankNm18"))
.vtlacBankNm19(m.get("vtlacBankNm19"))
.vtlacBankNm20(m.get("vtlacBankNm20"))
.vrActno1(m.get("vrActno1"))
.vrActno2(m.get("vrActno2"))
.vrActno3(m.get("vrActno3"))
.vrActno4(m.get("vrActno4"))
.vrActno5(m.get("vrActno5"))
.vrActno6(m.get("vrActno6"))
.vrActno7(m.get("vrActno7"))
.vrActno8(m.get("vrActno8"))
.vrActno9(m.get("vrActno9"))
.vrActno10(m.get("vrActno10"))
.vrActno11(m.get("vrActno11"))
.vrActno12(m.get("vrActno12"))
.vrActno13(m.get("vrActno13"))
.vrActno14(m.get("vrActno14"))
.vrActno15(m.get("vrActno15"))
.vrActno16(m.get("vrActno16"))
.vrActno17(m.get("vrActno17"))
.vrActno18(m.get("vrActno18"))
.vrActno19(m.get("vrActno19"))
.vrActno20(m.get("vrActno20"))
.rsveItem1(m.get("rsveItem1"))
.rsveItem2(m.get("rsveItem2"))
.rsveItem3(m.get("rsveItem3"))
.rsveItem4(m.get("rsveItem4"))
.rsveItem5(m.get("rsveItem5"))
.build();
}
@Override
protected String getSgbCd(RecvLevyResult recvLevyResult) {
return recvLevyResult.getSgbCd();
}
@Override
protected String getLinkMngKey(RecvLevyResult recvLevyResult) {
return recvLevyResult.getLinkMngKey();
}
@Override
protected RecvLevyResult setResult(RecvLevyResult entity) {
entity.setRspSgbCd(entity.getSgbCd());
entity.setRspLinkTrgtCd(super.linkTrgtCd);
entity.setRspLinkMngKey(entity.getLinkMngKey());
entity.setRspLinkRstCd(LinkRstCd.ok);
entity.setRspLinkRstMsg(LinkRstCd.ok.getCodeNm());
return entity;
}
@Override
protected RecvLevyResult setResult(RecvLevyResult entity, Exception e) {
if (entity == null)
entity = RecvLevyResult.builder().build();
entity.setRspSgbCd(entity.getSgbCd());
entity.setRspLinkTrgtCd(super.linkTrgtCd);
entity.setRspLinkMngKey(entity.getLinkMngKey());
entity.setRspLinkRstCd(LinkRstCd.internalFail);
entity.setRspLinkRstMsg(e.getMessage());
return entity;
}
}

@ -0,0 +1,110 @@
package cokr.xit.ntri.api.recv.service.impl;
import cokr.xit.ntri.api.recv.code.LinkRstCd;
import cokr.xit.ntri.api.recv.entity.RecvRcivInfo;
import cokr.xit.ntri.api.recv.entity.repository.RecvErrorRepository;
import cokr.xit.ntri.api.recv.service.RecvApiSupport;
import com.fasterxml.jackson.core.JsonProcessingException;
import lombok.Builder;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
import java.util.Map;
public class RcivInfo extends RecvApiSupport<Map<String, String>, RecvRcivInfo> {
@Builder(builderClassName = "builder")
public RcivInfo(String jParam, JpaRepository jpaRepository, RecvErrorRepository recvErrorRepository, String linkTrgtCd) {
super(jParam, jpaRepository, recvErrorRepository, linkTrgtCd);
}
@Override
protected Map<String, String> parsingHeader(String jParam) throws JsonProcessingException {
return (Map<String, String>) mapper.readValue(jParam, Map.class).get("header");
}
@Override
protected Map<String, Object> parsingBody(String jParam) throws JsonProcessingException {
return (Map<String, Object>) mapper.readValue(jParam, Map.class).get("body");
}
@Override
protected List<Map<String, String>> parsingData(Map<String, Object> body) {
return (List<Map<String, String>>) body.get("reqVo");
}
@Override
protected RecvRcivInfo mapping(Map<String, String> m) {
return RecvRcivInfo.builder()
.sgbCd(m.get("sgbCd"))
.sgbNm(m.get("sgbNm"))
.linkMngKey(m.get("linkMngKey"))
.taxnNo(m.get("taxnNo"))
.untyTaxnNo(m.get("untyTaxnNo"))
.dptCd(m.get("dptCd"))
.dptNm(m.get("dptNm"))
.spclFisBizCd(m.get("spclFisBizCd"))
.spclFisBizNm(m.get("spclFisBizNm"))
.fyr(m.get("fyr"))
.actSeCd(m.get("actSeCd"))
.actSeNm(m.get("actSeNm"))
.rprsTxmCd(m.get("rprsTxmCd"))
.rprsTxmNm(m.get("rprsTxmNm"))
.operItemCd(m.get("operItemCd"))
.operItemNm(m.get("operItemNm"))
.lvyNo(m.get("lvyNo"))
.itmNo(m.get("itmNo"))
.epayNo(m.get("epayNo"))
.rcvmtNo(m.get("rcvmtNo"))
.rcvmtSeCd(m.get("rcvmtSeCd"))
.rcvmtSeNm(m.get("rcvmtSeNm"))
.rcvmtYmd(m.get("rcvmtYmd"))
.actYmd(m.get("actYmd"))
.tsfYmd(m.get("tsfYmd"))
.rcvmtPctAmt(m.get("rcvmtPctAmt"))
.rcvmtAdtnAmt(m.get("rcvmtAdtnAmt"))
.rcvmtIntrAmt(m.get("rcvmtIntrAmt"))
.bankNm(m.get("bankNm"))
.rcvmtTyCd(m.get("rcvmtTyCd"))
.rcvmtTy(m.get("rcvmtTy"))
.rsveItem1(m.get("rsveItem1"))
.rsveItem2(m.get("rsveItem2"))
.rsveItem3(m.get("rsveItem3"))
.rsveItem4(m.get("rsveItem4"))
.rsveItem5(m.get("rsveItem5"))
.build();
}
@Override
protected String getSgbCd(RecvRcivInfo recvRcivInfo) {
return recvRcivInfo.getSgbCd();
}
@Override
protected String getLinkMngKey(RecvRcivInfo recvRcivInfo) {
return recvRcivInfo.getLinkMngKey();
}
@Override
protected RecvRcivInfo setResult(RecvRcivInfo entity) {
entity.setRspSgbCd(entity.getSgbCd());
entity.setRspLinkTrgtCd(super.linkTrgtCd);
entity.setRspLinkMngKey(entity.getLinkMngKey());
entity.setRspLinkRstCd(LinkRstCd.ok);
entity.setRspLinkRstMsg(LinkRstCd.ok.getCodeNm());
return entity;
}
@Override
protected RecvRcivInfo setResult(RecvRcivInfo entity, Exception e) {
if (entity == null)
entity = RecvRcivInfo.builder().build();
entity.setRspSgbCd(entity.getSgbCd());
entity.setRspLinkTrgtCd(super.linkTrgtCd);
entity.setRspLinkMngKey(entity.getLinkMngKey());
entity.setRspLinkRstCd(LinkRstCd.internalFail);
entity.setRspLinkRstMsg(e.getMessage());
return entity;
}
}

@ -0,0 +1,103 @@
package cokr.xit.ntri.api.recv.service.impl;
import cokr.xit.ntri.api.recv.code.LinkRstCd;
import cokr.xit.ntri.api.recv.entity.RecvRdcamtInfo;
import cokr.xit.ntri.api.recv.entity.repository.RecvErrorRepository;
import cokr.xit.ntri.api.recv.service.RecvApiSupport;
import com.fasterxml.jackson.core.JsonProcessingException;
import lombok.Builder;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
import java.util.Map;
public class RdcamtInfo extends RecvApiSupport<Map<String, String>, RecvRdcamtInfo> {
@Builder(builderClassName = "builder")
public RdcamtInfo(String jParam, JpaRepository jpaRepository, RecvErrorRepository recvErrorRepository, String linkTrgtCd) {
super(jParam, jpaRepository, recvErrorRepository, linkTrgtCd);
}
@Override
protected Map<String, String> parsingHeader(String jParam) throws JsonProcessingException {
return (Map<String, String>) mapper.readValue(jParam, Map.class).get("header");
}
@Override
protected Map<String, Object> parsingBody(String jParam) throws JsonProcessingException {
return (Map<String, Object>) mapper.readValue(jParam, Map.class).get("body");
}
@Override
protected List<Map<String, String>> parsingData(Map<String, Object> body) {
return (List<Map<String, String>>) body.get("reqVo");
}
@Override
protected RecvRdcamtInfo mapping(Map<String, String> m) {
return RecvRdcamtInfo.builder()
.sgbCd(m.get("sgbCd"))
.sgbNm(m.get("sgbNm"))
.linkMngKey(m.get("linkMngKey"))
.taxnNo(m.get("taxnNo"))
.untyTaxnNo(m.get("untyTaxnNo"))
.dptCd(m.get("dptCd"))
.dptNm(m.get("dptNm"))
.spclFisBizCd(m.get("spclFisBizCd"))
.spclFisBizNm(m.get("spclFisBizNm"))
.fyr(m.get("fyr"))
.actSeCd(m.get("actSeCd"))
.actSeNm(m.get("actSeNm"))
.rprsTxmCd(m.get("rprsTxmCd"))
.rprsTxmNm(m.get("rprsTxmNm"))
.operItemCd(m.get("operItemCd"))
.operItemNm(m.get("operItemNm"))
.lvyNo(m.get("lvyNo"))
.itmNo(m.get("itmNo"))
.rdcYmd(m.get("rdcYmd"))
.rdcPctAmt(m.get("rdcPctAmt"))
.rdcAdtnAmt(m.get("rdcAdtnAmt"))
.rdcIntrAmt(m.get("rdcIntrAmt"))
.rdcAmt(m.get("rdcAmt"))
.rdcRsnCn(m.get("rdcRsnCn"))
.rsveItem1(m.get("rsveItem1"))
.rsveItem2(m.get("rsveItem2"))
.rsveItem3(m.get("rsveItem3"))
.rsveItem4(m.get("rsveItem4"))
.rsveItem5(m.get("rsveItem5"))
.build();
}
@Override
protected String getSgbCd(RecvRdcamtInfo recvRdcamtInfo) {
return recvRdcamtInfo.getSgbCd();
}
@Override
protected String getLinkMngKey(RecvRdcamtInfo recvRdcamtInfo) {
return recvRdcamtInfo.getLinkMngKey();
}
@Override
protected RecvRdcamtInfo setResult(RecvRdcamtInfo entity) {
entity.setRspSgbCd(entity.getSgbCd());
entity.setRspLinkTrgtCd(super.linkTrgtCd);
entity.setRspLinkMngKey(entity.getLinkMngKey());
entity.setRspLinkRstCd(LinkRstCd.ok);
entity.setRspLinkRstMsg(LinkRstCd.ok.getCodeNm());
return entity;
}
@Override
protected RecvRdcamtInfo setResult(RecvRdcamtInfo entity, Exception e) {
if (entity == null)
entity = RecvRdcamtInfo.builder().build();
entity.setRspSgbCd(entity.getSgbCd());
entity.setRspLinkTrgtCd(super.linkTrgtCd);
entity.setRspLinkMngKey(entity.getLinkMngKey());
entity.setRspLinkRstCd(LinkRstCd.internalFail);
entity.setRspLinkRstMsg(e.getMessage());
return entity;
}
}

@ -0,0 +1,174 @@
package cokr.xit.ntri.core.aop;
import cokr.xit.ntri.core.aop.entity.AccessLog;
import cokr.xit.ntri.core.aop.entity.repository.AccessLogRepository;
import cokr.xit.ntri.support.utils.CmmnUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Slf4j
@Component
@Aspect
@RequiredArgsConstructor
public class AccessLogAspect {
private final AccessLogRepository accessLogRepository;
private final String ACCESS_TOKEN_NAME = "Authorization";
@Pointcut("execution(* cokr.xit..presentation.*Controller.*(..)) || execution(* cokr.xit..presentation.*Api.*(..))")
public void presentationLayer() {
}
@Pointcut("execution(* cokr.xit..service.*Impl.*(..))")
public void serviceLayer() {
}
@Pointcut("execution(* cokr.xit..domain.*Repository.*(..))")
public void persistenceLayer() {
}
@Around("presentationLayer()")
public Object addLogOfRequestAndResponse(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
long start = System.currentTimeMillis();
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
Object result = null;
AccessLog accessLog = null;
try {
accessLog = this.setRequestInfo(request);
accessLogRepository.save(accessLog);
result = proceedingJoinPoint.proceed(proceedingJoinPoint.getArgs());
this.setResponseInfo(accessLog, result);
this.setResponseInfo(accessLog, result);
accessLogRepository.save(accessLog);
} catch (Exception e) {
log.error(String.format("[%s ERROR] : %s", "Unknown", e.getMessage()), e);
accessLog.setResponseFail(String.format("%s: %s", "Unknown", CmmnUtil.printStackTraceToString(e)));
accessLogRepository.save(accessLog);
} finally {
long end = System.currentTimeMillis();
log.info("Request: {} {}: {}. request Ajax: {} ({}ms)", request.getMethod(), request.getRequestURL(), paramMapToString(request.getParameterMap()), isAjax(request), end - start);
}
return result;
}
private String paramMapToString(Map<String, String[]> paramMap) {
return paramMap.entrySet()
.stream()
.map(entry -> String.format("%s : %s",
entry.getKey(), Arrays.toString(entry.getValue())))
.collect(Collectors.joining(", "));
}
private String paramMapToJsonString(Map<String, String[]> paramMap) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
return mapper.writeValueAsString(paramMap);
}
private String requestBodyToString(HttpServletRequest request) {
StringBuffer body = new StringBuffer();
String line = null;
try {
BufferedReader reader = request.getReader();
while ((line = reader.readLine()) != null) {
body.append(line);
}
} catch (Exception e) {
log.info("Error reading JSON string: " + e.toString());
}
return body.toString();
}
@SuppressWarnings("deprecation")
private AccessLog setRequestInfo(HttpServletRequest request) throws JsonProcessingException {
String sessionId = request.getSession().getId();
String param = null;
try {
param = this.requestBodyToString(request);
if (StringUtils.isEmpty(param)) //request body에 param 이 없으면..
param = this.paramMapToJsonString(request.getParameterMap());
} catch (Exception e) {
param = String.format("[요청 parameter 변환 실패]: %s", e.getMessage());
}
return AccessLog.reqBuilder()
.accessToken(request.getHeader(ACCESS_TOKEN_NAME))
.sessionId(sessionId)
.ip(this.getClientIpAddr(request))
.httpMethod(request.getMethod())
.url(request.getRequestURL().toString())
.uri(request.getRequestURI())
.param(param)
.build();
}
private void setResponseInfo(AccessLog accessLog, Object result) {
String response = null;
if (result instanceof String)
response = (String) result;
else if (result instanceof List)
response = result.toString();
else if (result instanceof Map)
response = result.toString();
else
response = String.valueOf(result);
accessLog.setResponseCompleted(response);
}
private String getClientIpAddr(HttpServletRequest request) {
String ip = request.getHeader("X-Forwarded-For");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return ip;
}
private boolean isAjax(HttpServletRequest request) {
if ("XMLHttpRequest".equals(request.getHeader("X-Requested-With")))
return true;
return false;
}
}

@ -0,0 +1,24 @@
package cokr.xit.ntri.core.aop.code;
import cokr.xit.ntri.support.code.CodeMapperType;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
public enum AccessStatusCd implements CodeMapperType {
noAuth("권한없음")
,req("요청완료")
,cmplt("처리완료")
,fail("처리실패")
;
@Getter
private final String codeNm;
@Override
public String getCode() {
return this.name();
}
}

@ -0,0 +1,91 @@
package cokr.xit.ntri.core.aop.entity;
import cokr.xit.ntri.core.aop.code.AccessStatusCd;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Builder;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;
import javax.persistence.*;
import java.time.LocalDateTime;
@Entity
@Getter
@RequiredArgsConstructor
@Table(name = "ntri_access_log", schema = "", catalog = "")
@Schema(name = "AccessLog", description = "접근 로그")
public class AccessLog {
/* ====================================
* @GeneratedValue 4
* -.AUTO(default): JPA IDENTITIY/SEQUENCE/TABLE .
* -.IDENTITY: . ex) MySQL AUTO INCREMENT .(MySQL, PostgresSQL, Server, DB2)
* -.SEQUENCE: 퀀 .(Oracle, PostgresSQL, Db2, H2)
* -.TABLE: .
==================================== */
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long logId; //로그ID
@Column(length = 2000)
private String accessToken; //엑세스토큰
private String sessionId; //세션 ID
private String ip; //접근자 IP
private String httpMethod; //요청 Method
private String url; //요청 URL
private String uri; //요청 URI
@Lob
private String param; //요청 parameter(json format String)
@Lob
private String response; //응답
@Enumerated(EnumType.STRING)
private AccessStatusCd status; //상태
@Lob
private String errorMsg; //에러 메시지
@CreationTimestamp
private LocalDateTime startDt; //시작 일시
@UpdateTimestamp
private LocalDateTime endDt; //종료 일지
@Builder(builderClassName = "reqBuilder", builderMethodName = "reqBuilder")
public AccessLog(String accessToken, String sessionId, String ip, String httpMethod, String url, String uri, String param) {
this.accessToken = accessToken;
this.sessionId = sessionId;
this.ip = ip;
this.httpMethod = httpMethod;
this.url = url;
this.uri = uri;
this.param = param;
this.status = AccessStatusCd.req;
}
public void setResponseCompleted(String response) {
this.status = AccessStatusCd.cmplt;
this.response = response;
}
public void setResponseFail(String errorMsg) {
this.status = AccessStatusCd.fail;
this.errorMsg = errorMsg;
}
public void setResponseNoAuth(String errorMsg) {
this.status = AccessStatusCd.noAuth;
this.errorMsg = errorMsg;
}
}

@ -0,0 +1,8 @@
package cokr.xit.ntri.core.aop.entity.repository;
import cokr.xit.ntri.core.aop.entity.AccessLog;
import org.springframework.data.jpa.repository.JpaRepository;
public interface AccessLogRepository extends JpaRepository<AccessLog, Long> {
}

@ -0,0 +1,10 @@
package cokr.xit.ntri.core.config;
import lombok.Data;
@Data
public class IFConfig {
private String name;
private String url;
}

@ -0,0 +1,17 @@
package cokr.xit.ntri.core.config;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;
@Configuration
@ConfigurationProperties("app.service.recv.interface")
@Getter
@Setter
public class IFConfigManager {
Map<String, IFConfig> environment = new HashMap<>();
}

@ -0,0 +1,9 @@
package cokr.xit.ntri.core.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
@Configuration
@EnableJpaRepositories(basePackages = "cokr.xit.ntri")
public class JpaConfig {
}

@ -0,0 +1,27 @@
package cokr.xit.ntri.core.config;
import cokr.xit.ntri.core.filter.RequestWrapperFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.json.MappingJackson2JsonView;
import java.util.Arrays;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Bean(name = "jsonView")
public MappingJackson2JsonView jsonView() {
return new MappingJackson2JsonView();
}
@SuppressWarnings({"rawtypes", "unchecked"})
@Bean
public FilterRegistrationBean requestWrapperFilter() {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new RequestWrapperFilter());
filterRegistrationBean.setUrlPatterns(Arrays.asList("/*"));
return filterRegistrationBean;
}
}

@ -0,0 +1,82 @@
package cokr.xit.ntri.core.filter;
import org.apache.commons.io.IOUtils;
import org.springframework.util.StringUtils;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
/**
* <ul>
* <li> : RequestWrapper </li>
* <li> : getInputStream() .</li>
* <li>: 2021. 11. 30. 11:22:09
* </ul>
*
* @author
*/
public class RequestWrapper extends HttpServletRequestWrapper {
private final Charset encoding;
private byte[] rawData;
@SuppressWarnings("deprecation")
public RequestWrapper(HttpServletRequest request) throws IOException {
super(request);
String characterEncoding = request.getCharacterEncoding();
if (StringUtils.isEmpty(characterEncoding)) {
characterEncoding = StandardCharsets.UTF_8.name();
}
this.encoding = Charset.forName(characterEncoding);
try {
InputStream inputStream = request.getInputStream(); //getInputStream()은 한번만 사용 가능. 이후 getInputStream 호출 시 "getInputStream() has already been called for this request" 오류 발생
this.rawData = IOUtils.toByteArray(inputStream); //재사용이 가능하도록 byte[] rawData변수에 저장 후 getInputStream()를 오버라이딩하여 rawData 반환
} catch (IOException e) {
throw e;
}
}
@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(this.rawData);
ServletInputStream servletInputStream = new ServletInputStream() {
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {
}
public int read() throws IOException {
return byteArrayInputStream.read();
}
};
return servletInputStream;
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(this.getInputStream(), this.encoding));
}
@Override
public ServletRequest getRequest() {
return super.getRequest();
}
}

@ -0,0 +1,17 @@
package cokr.xit.ntri.core.filter;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
public class RequestWrapperFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
RequestWrapper readableRequestWrapper = new RequestWrapper((HttpServletRequest) request); //RequestWrapper 클래스로 wrapping
chain.doFilter(readableRequestWrapper, response);
}
}

@ -0,0 +1,22 @@
package cokr.xit.ntri.support.code;
import cokr.xit.ntri.support.code.sample.SampleCd;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.LinkedHashMap;
@Configuration
public class CodeMapperConfig {
@Bean
public CodeMapperFactory codeMapperFactory() {
//CodeMapperFactory 초기화
CodeMapperFactory codeMapperFactory = new CodeMapperFactory(new LinkedHashMap<>());
//Enum 추가
codeMapperFactory.put(SampleCd.class);
return codeMapperFactory;
}
}

@ -0,0 +1,72 @@
package cokr.xit.ntri.support.code;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Getter
@AllArgsConstructor
public class CodeMapperFactory {
private Map<String, List<CodeMapperValue>> factory;
/**
* <pre> : CodeMapperType Enum Factory </pre>
* @param e void
* @author:
* @date: 2021. 10. 28.
*/
public void put(Class<? extends CodeMapperType> e) {
this.put(e.getSimpleName(), e);
}
/**
* <pre> : CodeMapperType Enum Factory </pre>
* @param key
* @param e void
* @author:
* @date: 2021. 10. 28.
*/
public void put(String key, Class<? extends CodeMapperType> e) {
factory.put(key, this.toEnumValue(e));
}
/**
* <pre> : Factory Enum </pre>
* @param e
* @return List<CodeMapperValue>
* @author:
* @date: 2021. 10. 28.
*/
public List<CodeMapperValue> get(Class<? extends CodeMapperType> e){
return this.get(e.getSimpleName());
}
/**
* <pre> : Factory Enum </pre>
* @param key
* @return List<CodeMapperValue>
* @author:
* @date: 2021. 10. 28.
*/
public List<CodeMapperValue> get(String key){
return factory.get(key);
}
/**
* <pre> : Enum List </pre>
* @param e
* @return List<CodeMapperValue>
* @author:
* @date: 2021. 10. 28.
*/
private List<CodeMapperValue> toEnumValue(Class<? extends CodeMapperType> e){
return Arrays.stream(e.getEnumConstants()) //CodeMapperType을 구현한 열거형 상수(code/codeNm SET)코드를
.map(CodeMapperValue::new) //CodeMapperValue 클래스로 생성하여
.collect(Collectors.toList()); //List<CodeMapperValue>로 반환
}
}

@ -0,0 +1,20 @@
package cokr.xit.ntri.support.code;
public interface CodeMapperType {
/**
* <pre> : Enum </pre>
* @return String
* @author:
* @date: 2021. 10. 28.
*/
String getCode();
/**
* <pre> : Enum </pre>
* @return String
* @author:
* @date: 2021. 10. 28.
*/
String getCodeNm();
}

@ -0,0 +1,15 @@
package cokr.xit.ntri.support.code;
import lombok.Getter;
@Getter
public class CodeMapperValue {
private String code;
private String codeNm;
public CodeMapperValue(CodeMapperType codeMapperType) {
this.code = codeMapperType.getCode();
this.codeNm = codeMapperType.getCodeNm();
}
}

@ -0,0 +1,22 @@
package cokr.xit.ntri.support.code.sample;
import cokr.xit.ntri.support.code.CodeMapperType;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
public enum SampleCd implements CodeMapperType {
CODE1("코드1")
,CODE2("코드2");
@Getter
private final String codeNm;
@Override
public String getCode() {
return this.name();
}
}

@ -0,0 +1,21 @@
package cokr.xit.ntri.support.code.sample;
import cokr.xit.ntri.support.code.CodeMapperFactory;
import cokr.xit.ntri.support.code.CodeMapperValue;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.List;
@Slf4j
@Component
@RequiredArgsConstructor
public class SampleCdUse {
private final CodeMapperFactory codeMapperFactory;
public void printSampleCds() {
List<CodeMapperValue> sampleCdList = codeMapperFactory.get("SampleCd");
sampleCdList.stream().forEach(row -> log.info("{} {}", row.getCode(), row.getCodeNm()));
}
}

@ -0,0 +1,26 @@
package cokr.xit.ntri.support.entity;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;
import javax.persistence.Column;
import javax.persistence.MappedSuperclass;
import java.time.LocalDateTime;
@Getter
@MappedSuperclass
@SuperBuilder
@NoArgsConstructor
public class BaseEntity {
@CreationTimestamp
@Column(name = "regist_dt", nullable = true)
private LocalDateTime registDt;
@UpdateTimestamp
@Column(name = "last_updt_dt", nullable = true)
private LocalDateTime lastUpdtDt;
}

@ -0,0 +1,128 @@
package cokr.xit.ntri.support.utils;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.List;
import java.util.Map;
@Slf4j
public class CmmnUtil {
// private final static Logger logger = LoggerFactory.getLogger(CmmnUtil.class);
/**
* <pre> : Json String .</pre>
*
* @param obj
* @return String
* @author:
* @date: 2021. 8. 5.
*/
public static String toJsonString(Object obj) {
return toJsonString(obj, JsonInclude.Include.ALWAYS);
}
/**
* <pre> : Json String .</pre>
*
* @param obj
* @param type JsonInclude.Include
* <pre>
* [type ]
* ALWAYS:
* NON_NULL: null
* NON_ABSENT: null
* NON_EMPTY: null/absent/isEmpty()==true/lenth==0
* NON_DEFAULT: empty .primitive . (int / Integer : 0 , boolean / Boolean : false )
* </pre>
* @return String
* @author:
* @date: 2021. 8. 5.
*/
public static String toJsonString(Object obj, JsonInclude.Include type) {
String result = null;
try {
ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(type); //직렬화 타입 설정
result = mapper.writeValueAsString(obj);
} catch (JsonProcessingException e) {
// throw new CustomException(RESP_CODE.INTERNAL_SERVER_ERROR, String.format("obj -> jsonString converting fail:: %s", e.getMessage()));
throw new RuntimeException(String.format("obj -> jsonString converting fail:: %s", e.getMessage()), e);
}
return result;
}
/**
* <pre> : jsonString Object </pre>
*
* @param clz
* @param jsonStr
* @return Object
* @author:
* @date: 2021. 12. 23.
*/
public static Object jsonStringtoObj(Class clz, String jsonStr) {
Object result = null;
try {
ObjectMapper mapper = new ObjectMapper();
result = mapper.readValue(jsonStr, clz.getClass());
} catch (JsonProcessingException e) {
throw new RuntimeException(String.format("jsonString -> obj converting fail:: %s", e.getMessage()), e);
}
return result;
}
public static boolean isEmpty(Object obj) {
if (obj == null) return true;
if ((obj instanceof String) && (((String) obj).trim().length() == 0)) {
return true;
}
if (obj instanceof Map) {
return ((Map<?, ?>) obj).isEmpty();
}
if (obj instanceof Map) {
return ((Map<?, ?>) obj).isEmpty();
}
if (obj instanceof List) {
return ((List<?>) obj).isEmpty();
}
if (obj instanceof Object[]) {
return (((Object[]) obj).length == 0);
}
return false;
}
public static String getServerUrl() {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
return String.format("%s://%s:%s", request.getScheme(), request.getServerName(), request.getServerPort());
}
public static String printStackTraceToString(Exception e) {
try {
StringWriter errors = new StringWriter();
e.printStackTrace(new PrintWriter(errors));
return errors.toString();
} catch (Exception ex) {
return "printStackTrace 변환에 실패 했습니다. " + ex.getMessage();
}
}
}

@ -0,0 +1,82 @@
app:
name: ntri
#=================
# Server
#=================
server:
port: ${app.server.port:18080}
error:
include-exception: true #?? ??? Exception ?? ??
include-stacktrace: never #?? ??? stacktrace ?? ??
path: '/error' #http://~/error ??
whitelabel:
enabled: true #?? ?? ??? ????? ??? ?? ??? ?? ??
servlet:
context-path: /
spring:
config:
activate:
on-profile: dev
# ===================================================================================================================================
# Procsss ID
# ===================================================================================================================================
pid:
file: ${app.name}.pid
# ===================================================================================================================================
# Database
# ===================================================================================================================================
sql:
init:
continue-on-error: false # ???? ? SQL ?? ?? ? ???? ??
jpa:
database-platform: org.hibernate.dialect.Oracle10gDialect
hibernate:
ddl-auto: update # create / create-drop / update / validate / none
properties:
hibernate:
format_sql: true
use_sql_comments: true
show-sql: true
datasource:
driver-class-name: oracle.jdbc.OracleDriver
url: jdbc:oracle:thin:@211.119.124.117:1521:ora11g
username: xit_traffic
password: traffic5
hikari:
auto-commit: false
minimum-idle: 10
maximum-pool-size: 50
connection-test-query: SELECT 1 FROM DUAL
transaction-isolation: TRANSACTION_READ_COMMITTED
pool-name: pool-${app.name}
hikari:
driver-class-name: ${spring.datasource.driver-class-name}
jdbc-url: ${spring.datasource.url}
username: ${spring.datasource.username}
password: ${spring.datasource.password}
# ===================================================================================================================================
# Logging
# ===================================================================================================================================
logging:
charset:
console: utf-8
file: utf-8
level:
root: info
exception-conversion-word: '%wEx'
pattern:
console: '%d{yyyy-MM-dd HH:mm:ss.SSS} %clr(${LOG_LEVEL_PATTERN:-%5p}){green} %clr([%18thread]){magenta} %clr(%-40.40logger{39}%line){cyan} %clr(: %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}){faint}'
file:
name: ./logs/${app.name}/logback.log
logback:
rollingpolicy:
file-name-pattern: ${LOG_FILE}.%d{yyyy-MM-dd}-%i.log
max-history: 30 #????
max-file-size: 100MB #????

@ -0,0 +1,124 @@
app:
name: ntri
service:
recv:
interface:
environment:
ERR_1741000NIS_Z000001LGE_0001 :
name: '부과결과정보(실시간)'
url: '/recv/levy/result'
ERR_1741000NIS_Z000001LGE_0002:
name: '부과취소정보(실시간)'
url: '/recv/levy/cancel'
ERR_1741000NIS_Z000001LGE_0003 :
name: '수납정보(실시간)'
url: '/recv/rciv/info'
ERR_1741000NIS_Z000001LGE_0004 :
name: '감액정보(실시간)'
url: '/recv/rdcamt/info'
#=================
# Server
#=================
server:
port: ${app.server.port:18080}
error:
include-exception: true #?? ??? Exception ?? ??
include-stacktrace: never #?? ??? stacktrace ?? ??
path: '/error' #http://~/error ??
whitelabel:
enabled: true #?? ?? ??? ????? ??? ?? ??? ?? ??
servlet:
context-path: /
#====================================================================
# SSL
# -.Ref Site
# : OpenSSL Download(https://sourceforge.net/projects/openssl)
# : Generate SSL Cert(https://deeplify.dev/back-end/spring/tomcat-openssl)
# -.Command
# 1. openssl req -config ./openssl.cnf -x509 -sha256 -nodes -newkey rsa:2048 -keyout private.key -out public.pem -days 3650
# 2. openssl pkcs12 -export -inKey private.key -in public.pem -name alias_name -out certificate.p12
# -.Command-2
# 1.서버개인키(private key) 생성
# : openssl genrsa -out server.key 2048 //2048비트 길이의 개인키 생성
# 2.인증서 세부정보 파일 생성, "-config" 옵션은 생략가능
# : openssl req -new -key server.key -out server.csr -config ./openssl.cnf //openssl.cnf 를 참조하여 인증서신청서 생성
# 3.서버인증서 생성
# : openssl req -new -x509 -days 3650 -in server.csr -key server.key -out server.crt //서버인증서 발급
#====================================================================
ssl:
enabled: ${app.ssl.enabled:true}
#key-alias: ${app.ssl.key-alias:alias_name}
#key-store: ${app.ssl.key-store:classpath}
#key-store-type: ${app.ssl.key-store-type}
#key-store-password: ${app.ssl.key-store-password}
certificate-private-key: ${app.ssl.private-key}
certificate: ${app.ssl.cert}
spring:
config:
activate:
on-profile: prod
# ===================================================================================================================================
# Procsss ID
# ===================================================================================================================================
pid:
file: ${app.name}.pid
# ===================================================================================================================================
# Database
# ===================================================================================================================================
sql:
init:
continue-on-error: false # ???? ? SQL ?? ?? ? ???? ??
jpa:
# Oracle: Oracle10gDialect, Maria: MariaDB106Dialect, Mysql: MySQL5InnoDBDialect
database-platform: org.hibernate.dialect.${app.datasource.platform:Oracle10gDialect}
hibernate:
ddl-auto: update # create / create-drop / update / validate / none
properties:
hibernate:
format_sql: true
use_sql_comments: true
show-sql: false
datasource:
driver-class-name: ${app.datasource.driver:oracle.jdbc.OracleDriver}
# url: jdbc:oracle:thin:@${app.datasource.ip:211.119.124.117}:${app.datasource.port:1521}:${app.datasource.sid:ora11g}
url: ${app.datasource.url:'jdbc:oracle:thin:@211.119.124.117:1521:ora11g'}
username: ${app.datasource.username:xit_traffic}
password: ${app.datasource.password:traffic5}
hikari:
auto-commit: false
minimum-idle: 10
maximum-pool-size: 50
connection-test-query: SELECT 1 FROM DUAL
transaction-isolation: TRANSACTION_READ_COMMITTED
pool-name: pool-${app.name}
hikari:
driver-class-name: ${spring.datasource.driver-class-name}
jdbc-url: ${spring.datasource.url}
username: ${spring.datasource.username}
password: ${spring.datasource.password}
# ===================================================================================================================================
# Logging
# ===================================================================================================================================
logging:
charset:
console: utf-8
file: utf-8
level:
root: info
exception-conversion-word: '%wEx'
pattern:
console: '%d{yyyy-MM-dd HH:mm:ss.SSS} %clr(${LOG_LEVEL_PATTERN:-%5p}){green} %clr([%18thread]){magenta} %clr(%-40.40logger{39}%line){cyan} %clr(: %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}){faint}'
file:
name: ./logs/${app.name}/logback.log
logback:
rollingpolicy:
file-name-pattern: ${LOG_FILE}.%d{yyyy-MM-dd}-%i.log
max-history: 30 #????
max-file-size: 100MB #????

@ -0,0 +1,136 @@
app:
name: ntri
response:
linkTrgtCd: ${app.resp.linkTrgtCd:unknown}
service:
recv:
interface:
environment:
ERR_Z000001DCP_1741000NIS_0001 :
name: '부과결과정보(실시간)'
url: '/recv/levy/result'
ERR_Z000001DCP_1741000NIS_0002:
name: '부과취소정보(실시간)'
url: '/recv/levy/cancel'
ERR_Z000001DCP_1741000NIS_0003 :
name: '수납정보(실시간)'
url: '/recv/rciv/info'
ERR_Z000001DCP_1741000NIS_0004 :
name: '감액정보(실시간)'
url: '/recv/rdcamt/info'
#=================
# Server
#=================
server:
port: 18080
error:
include-exception: true #?? ??? Exception ?? ??
include-stacktrace: never #?? ??? stacktrace ?? ??
path: '/error' #http://~/error ??
whitelabel:
enabled: true #?? ?? ??? ????? ??? ?? ??? ?? ??
servlet:
context-path: /
spring:
profiles:
# active: '@spring.profiles.active@'
# active: ${spring.profiles.active}
# active: dev
# active: ${ext.string}
active: '@springProfilesActive@'
# ===================================================================================================================================
# Procsss ID
# ===================================================================================================================================
pid:
file: ${app.name}.pid
# ===================================================================================================================================
# Database
# ===================================================================================================================================
sql:
init:
continue-on-error: false # ???? ? SQL ?? ?? ? ???? ??
jpa:
database-platform: org.hibernate.dialect.Oracle10gDialect
generate-ddl: false
hibernate:
ddl-auto: update # create / create-drop / update / validate / none
properties:
hibernate:
format_sql: true
use_sql_comments: true
show-sql: true
datasource:
driver-class-name: oracle.jdbc.OracleDriver
url: jdbc:oracle:thin:@211.119.124.117:1521:ora11g
username: xit_traffic
password: traffic5
hikari:
auto-commit: false
minimum-idle: 10
maximum-pool-size: 50
connection-test-query: SELECT 1 FROM DUAL
transaction-isolation: TRANSACTION_READ_COMMITTED
pool-name: pool-${app.name}
# data-source-properties:
# rewriteBatchedStatments: true #???? insert ??? ??? ??
hikari:
driver-class-name: ${spring.datasource.driver-class-name}
jdbc-url: ${spring.datasource.url}
username: ${spring.datasource.username}
password: ${spring.datasource.password}
# ===================================================================================================================================
# Logging
# ===================================================================================================================================
logging:
charset:
console: utf-8
file: utf-8
level:
root: info
# '[org.hibernate.type.descriptor.sql]': trace #jpa "?" ??(binding ????) ??
# '[org.springframework.orm.jpa]': debug
# '[org.springframework.transaction]': debug
# '[org.springframework.transaction.interceptor]': trace
# '[org.springframework.jdbc.core]': off
# '[org.springframework.orm]': off
# '[org.springframework.orm.hibernate5]': off
# '[com.p6spy.engine.logging]': off
# '[com.p6spy]': off
# '[org.hibernate]': off
# '[org.hibernate.sql]': off
# '[org.hibernate.jpa]': off
exception-conversion-word: '%wEx'
pattern:
console: '%d{yyyy-MM-dd HH:mm:ss.SSS} %clr(${LOG_LEVEL_PATTERN:-%5p}){green} %clr([%18thread]){magenta} %clr(%-40.40logger{39}%line){cyan} %clr(: %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}){faint}'
file:
name: ./logs/${app.name}/logback.log
logback:
rollingpolicy:
file-name-pattern: ${LOG_FILE}.%d{yyyy-MM-dd}-%i.log
max-history: 30 #????
max-file-size: 100MB #????
# '[org.hibernate.type.descriptor.sql]': trace
# '[org.springframework]': debug
# '[org.hibernate]': info
# ===================================================================================================================================
# Springdoc
# ===================================================================================================================================
springdoc:
swagger-ui:
path: /swagger-ui.html
group-configs:
- group: 실시간 수신
paths-to-match:
- /recv/**

@ -0,0 +1,36 @@
[ req ]
default_bits = 2048
default_md = sha1
default_keyfile = private.key
distinguished_name = req_distinguished_name
extensions = v3_ca
req_extensions = v3_ca
[ v3_ca ]
basicConstraints = critical, CA:TRUE, pathlen:0
subjectKeyIdentifier = hash
##authorityKeyIdentifier = keyid:always, issuer:always
keyUsage = keyCertSign, cRLSign
nsCertType = sslCA, emailCA, objCA
[req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = KR
countryName_min = 2
countryName_max = 2
# 회사명 입력
organizationName = Organization Name (eg, company)
organizationName_default = XIT Co.
# 부서 입력
organizationalUnitName = Organizational Unit Name (eg, section)
organizationalUnitName_default = Tech Support Team
# SSL 서비스할 domain 명 입력
commonName = Common Name (eg, your name or your servers hostname)
#commonName_default = indienote Self Signed CA
commonName_default = www.xit-ntri.co.kr
commonName_max = 64
# 이메일주소
emailAddress_default = minkyu1128@xit.co.kr

@ -0,0 +1,60 @@
package cokr.xit.ntri;
import cokr.xit.ntri.api.recv.entity.RecvLevyCancel;
import cokr.xit.ntri.api.recv.entity.RecvLevyResult;
import cokr.xit.ntri.api.recv.entity.RecvRcivInfo;
import cokr.xit.ntri.api.recv.entity.RecvRdcamtInfo;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
public class Example {
@Test
public void toJsonString() throws JsonProcessingException {
RecvLevyCancel recvLevyCancel = RecvLevyCancel.builder().build();
RecvLevyResult recvLevyResult = RecvLevyResult.builder().build();
RecvRcivInfo rcivInfo = RecvRcivInfo.builder().build();
RecvRdcamtInfo recvRdcamtInfo = RecvRdcamtInfo.builder().build();
ObjectMapper mapper = new ObjectMapper();
System.out.println(mapper.writeValueAsString(recvLevyCancel));
System.out.println(mapper.writeValueAsString(recvLevyResult));
System.out.println(mapper.writeValueAsString(rcivInfo));
System.out.println(mapper.writeValueAsString(recvRdcamtInfo));
}
@Test
public void staticField() {
ExampleVO vo1 = new ExampleVO();
ExampleVO vo2 = new ExampleVO();
System.out.println("==========================================");
System.out.println("Test - static field getter/setter ( setter 를 호출하여 static 필드에 값 설정 )");
System.out.println("==========================================");
vo1.setStaticQuery("select * from dual");
System.out.println("vo1.staticQuery = " + vo1.getStaticQuery());
System.out.println("vo2.staticQuery = " + vo2.getStaticQuery());
System.out.println("ExampleVO.staticQuery = " + ExampleVO.staticQuery);
System.out.println("==========================================");
System.out.println("Test - static field getter/setter ( static 필드에 직접 값 설정 )");
System.out.println("==========================================");
ExampleVO.staticQuery = "delete from dual";
System.out.println("vo1.staticQuery = " + vo1.getStaticQuery());
System.out.println("vo2.staticQuery = " + vo2.getStaticQuery());
System.out.println("ExampleVO.staticQuery = " + ExampleVO.staticQuery);
System.out.println("==========================================");
System.out.println("Test - private field getter/setter ");
System.out.println("==========================================");
vo1.setQuery("select count(1) from dual");
System.out.println("vo1.query = " + vo1.getQuery());
System.out.println("vo2.query = " + vo2.getQuery());
}
}

@ -0,0 +1,23 @@
package cokr.xit.ntri;
public class ExampleVO {
static String staticQuery;
private String query;
public void setStaticQuery(String query) {
ExampleVO.staticQuery = query;
}
public String getStaticQuery() {
return staticQuery;
}
public void setQuery(String query) {
this.query = query;
}
public String getQuery() {
return this.query;
}
}

@ -0,0 +1,13 @@
package cokr.xit.ntri;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class NtriApplicationTests {
@Test
void contextLoads() {
}
}
Loading…
Cancel
Save