feat: NICE CI 소켓 통신 추가

dev
Jonguk. Lim 2 months ago
parent 6771f69594
commit dca46fa392

@ -1,19 +1,14 @@
package cokr.xit.ens.core.config; package cokr.xit.ens.core.config;
import java.util.Arrays; import java.util.*;
import java.util.List;
import org.springdoc.core.GroupedOpenApi; import org.springdoc.core.*;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.*;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.*;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.*;
import io.swagger.v3.oas.models.info.Contact; import io.swagger.v3.oas.models.info.*;
import io.swagger.v3.oas.models.info.Info; import io.swagger.v3.oas.models.servers.*;
import io.swagger.v3.oas.models.info.License;
import io.swagger.v3.oas.models.servers.Server;
@Configuration @Configuration
public class SpringDocConfig { public class SpringDocConfig {
@ -188,6 +183,14 @@ public class SpringDocConfig {
.build(); .build();
} }
@Profile({"local", "prod", "dev"})
@Bean
public GroupedOpenApi niceApiDoc() {
return GroupedOpenApi.builder()
.group("전자고지-NICE 인증톡")
.pathsToMatch("/nice/talk/**")
.build();
}
// @Bean // @Bean
// public GroupedOpenApi adminApiDoc() { // public GroupedOpenApi adminApiDoc() {

@ -15,6 +15,7 @@ import lombok.extern.slf4j.*;
@Slf4j @Slf4j
public class DateUtil { public class DateUtil {
private static final String DEFAULT_YMD_DT_FMT ="yyyy-MM-dd HH:mm:ss";
/** /**
* <pre> : (: milliesecond) .</pre> * <pre> : (: milliesecond) .</pre>

@ -2,7 +2,6 @@ package cokr.xit.ens.modules.nice.cmm;
import java.io.*; import java.io.*;
import java.nio.charset.*; import java.nio.charset.*;
import java.util.concurrent.atomic.*;
import org.apache.commons.lang3.*; import org.apache.commons.lang3.*;
@ -138,8 +137,8 @@ public class NiceCiUtils {
strRtnText.append(strText.charAt(i)); strRtnText.append(strText.charAt(i));
continue; continue;
} }
char c = strText.charAt(i);
if (strText.charAt(i) > 127) if (c > 127 || c == '\n' || c == '\t')
skipIdx += 2; skipIdx += 2;
else else
skipIdx++; skipIdx++;
@ -163,20 +162,30 @@ public class NiceCiUtils {
*/ */
public static String getStringKr(String strText, int iBytes) { public static String getStringKr(String strText, int iBytes) {
StringBuilder strRtnText = new StringBuilder(); StringBuilder strRtnText = new StringBuilder();
AtomicInteger iByte = new AtomicInteger(); int iByte = 0;
strText.chars().limit(iBytes).forEach(c -> { // 문자열을 문자 배열로 변환하여 반복문을 통해 처리
strRtnText.append((char) c); for (int i = 0; i < strText.length(); i++) {
iByte.addAndGet((c > 127) ? 2 : 1); char c = strText.charAt(i);
if (iByte.get() >= iBytes) return; strRtnText.append(c);
}); // 한글 등의 2바이트 문자 처리
if(c > 127 || c == '\n' || c == '\t') {
iByte += 2;
}else{
iByte++;
}
// 지정된 바이트 수를 넘으면 반복 종료
if (iByte >= iBytes) {
break; // for 루프 종료
}
}
return strRtnText.toString(); return strRtnText.toString();
} }
public static int lengthKr(String strText) { public static int lengthKr(String strText) {
return strText.chars() return strText.chars()
.map(ch -> ch > 127 ? 2 : 1) // 한글(또는 다른 비 ASCII 문자)인 경우 2바이트, 아니면 1바이트 .map(ch -> (ch > 127 || ch == '\n' || ch == '\t') ? 2 : 1) // 한글(또는 다른 비 ASCII 문자)인 경우 2바이트, 아니면 1바이트
.sum(); .sum();
} }
@ -203,6 +212,13 @@ public class NiceCiUtils {
.readLine(); .readLine();
} }
// 특수 문자를 2바이트로 간주하는 메서드
private static boolean isToByte(char c) {
// 추가적으로 2바이트로 계산할 특수 문자 정의
// 필요에 따라 추가 가능
return "\t\n".indexOf(c) >= 0;
}
public static void main(String[] args) throws IOException { public static void main(String[] args) throws IOException {
final String tgt = new String("123ab한글이ㅂa들어있다열자ㅁ".getBytes(), StandardCharsets.UTF_8); final String tgt = new String("123ab한글이ㅂa들어있다열자ㅁ".getBytes(), StandardCharsets.UTF_8);
final String tgt2 = new String("123ab한글이ㅂa들어있다열자ㅁ".getBytes(), StandardCharsets.ISO_8859_1); final String tgt2 = new String("123ab한글이ㅂa들어있다열자ㅁ".getBytes(), StandardCharsets.ISO_8859_1);
@ -224,8 +240,6 @@ public class NiceCiUtils {
System.out.println(substringKr("gks한글이시작되는데", 8)); System.out.println(substringKr("gks한글이시작되는데", 8));
System.out.println(substringKr("한글로abcdefgh계속", 12)); System.out.println(substringKr("한글로abcdefgh계속", 12));
System.out.println(substringKr("1한글2ㅇ ab", 10)); System.out.println(substringKr("1한글2ㅇ ab", 10));
//System.out.println(substringKor(tgt, 11));
;
System.out.println(leftKr(tgt, 18)); System.out.println(leftKr(tgt, 18));
System.out.println(leftKr(tgt2, 18)); System.out.println(leftKr(tgt2, 18));

@ -89,7 +89,7 @@ public class NiceCiCommon {
* </pre> * </pre>
*/ */
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "단말기구분(3자리)", example = "503") @Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "단말기구분(3자리)", example = "503")
@Size(min = 1, max = 1, message = "단말기 구분은 3자리 입니다.") @Size(min = 3, max = 3, message = "단말기 구분은 3자리 입니다.")
private String deviceClassification = "503"; private String deviceClassification = "503";
public void setDeviceClassification(String deviceClassification) { public void setDeviceClassification(String deviceClassification) {
this.deviceClassification = StringUtils.rightPad(nvl(deviceClassification), 3, StringUtils.SPACE); this.deviceClassification = StringUtils.rightPad(nvl(deviceClassification), 3, StringUtils.SPACE);
@ -111,7 +111,7 @@ public class NiceCiCommon {
* </pre> * </pre>
*/ */
@Schema(title = "응답코드(4자리)", example = " ") @Schema(title = "응답코드(4자리)", example = " ")
@Pattern(regexp = "^$|^[P|E|S][\\d]{3}$", message = "응답코드(4자리)는 4자리 입니다") @Pattern(regexp = "^\\s{4}$|$|^[P|E|S][\\d]{3}$", message = "응답코드(4자리)는 4자리 입니다")
private String rsltCode = StringUtils.rightPad(StringUtils.EMPTY, 4, StringUtils.SPACE); private String rsltCode = StringUtils.rightPad(StringUtils.EMPTY, 4, StringUtils.SPACE);
public void setRsltCode(String rsltCode) { public void setRsltCode(String rsltCode) {
this.rsltCode = StringUtils.rightPad(nvl(rsltCode), 4, StringUtils.SPACE); this.rsltCode = StringUtils.rightPad(nvl(rsltCode), 4, StringUtils.SPACE);

@ -48,8 +48,8 @@ public class NiceCiDTO {
* set * set
* </pre> * </pre>
*/ */
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "TR Code", example = " ") //@Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "TR Code", example = " ")
@Size(min = 10, max = 10, message = "트랜잭션 코드는 10자리 입니다.") //@Size(min = 10, max = 10, message = "트랜잭션 코드는 10자리 입니다.")
private String trCode = StringUtils.EMPTY; private String trCode = StringUtils.EMPTY;
public void setTrCode(String trCode) { public void setTrCode(String trCode) {
this.trCode = StringUtils.leftPad(nvl(trCode), 10, StringUtils.SPACE); this.trCode = StringUtils.leftPad(nvl(trCode), 10, StringUtils.SPACE);
@ -94,6 +94,7 @@ public class NiceCiDTO {
*/ */
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "조회사유", example = " ") @Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "조회사유", example = " ")
@Size(min = 2, max = 2, message = "조회사유는 2자리 입니다") @Size(min = 2, max = 2, message = "조회사유는 2자리 입니다")
//@Pattern(regexp = "^\\s{2}$|s{1,2}", message = "조회사유는 2자리 입니다")
private String queryReason = StringUtils.rightPad(StringUtils.EMPTY, 2, StringUtils.SPACE); private String queryReason = StringUtils.rightPad(StringUtils.EMPTY, 2, StringUtils.SPACE);
public void setQueryReason(String queryReason) { public void setQueryReason(String queryReason) {
this.queryReason = StringUtils.rightPad(nvl(queryReason), 2, StringUtils.SPACE); this.queryReason = StringUtils.rightPad(nvl(queryReason), 2, StringUtils.SPACE);
@ -106,7 +107,7 @@ public class NiceCiDTO {
* </pre> * </pre>
*/ */
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "조회요청건수", example = " ") @Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "조회요청건수", example = " ")
@Max(value = 48, message = "조회요청 최대건수는 48입니다") @Pattern(regexp = "^\\s{2}$|\\d{1,2}", message = "조회요청 최대건수는 48입니다(2자리)")
private String queryReqCnt = StringUtils.rightPad(StringUtils.EMPTY, 2, StringUtils.SPACE); private String queryReqCnt = StringUtils.rightPad(StringUtils.EMPTY, 2, StringUtils.SPACE);
public void setQueryReqCnt(Integer queryReqCnt) { public void setQueryReqCnt(Integer queryReqCnt) {
this.queryReqCnt = StringUtils.rightPad(nvl(queryReqCnt == null? "": queryReqCnt.toString()), 2, StringUtils.SPACE); this.queryReqCnt = StringUtils.rightPad(nvl(queryReqCnt == null? "": queryReqCnt.toString()), 2, StringUtils.SPACE);
@ -124,7 +125,7 @@ public class NiceCiDTO {
*/ */
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "SMS발송요청구분코드", example = " ", allowableValues = {"0", "1", "2", "3"}) @Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "SMS발송요청구분코드", example = " ", allowableValues = {"0", "1", "2", "3"})
@Pattern(regexp = "[0-3]", message = "SMS발송요청구분코드 0 ~ 3 입니다(1자리)") @Pattern(regexp = "[0-3]", message = "SMS발송요청구분코드 0 ~ 3 입니다(1자리)")
private String smsSndReqCode = StringUtils.SPACE;; private String smsSndReqCode = "1";
/** /**
* <pre> * <pre>
@ -133,7 +134,7 @@ public class NiceCiDTO {
* </pre> * </pre>
*/ */
@Schema(title = "SMS 발송메세지", example = " ") @Schema(title = "SMS 발송메세지", example = " ")
@Pattern(regexp = "^$|[\\s]{10,2000}", message = "SMS발송메세지는 10 ~ 2000자리 입니다") @Pattern(regexp = "^[\\s\\S]{10,2000}$", message = "SMS발송메세지는 10 ~ 2000자리 입니다")
private String sndMessage = StringUtils.rightPad(StringUtils.EMPTY, 2000, StringUtils.SPACE); private String sndMessage = StringUtils.rightPad(StringUtils.EMPTY, 2000, StringUtils.SPACE);
public void setSndMessage(String sndMessage) { public void setSndMessage(String sndMessage) {
this.sndMessage = NiceCiUtils.rightPadKr(nvl(sndMessage), 2000, StringUtils.SPACE); this.sndMessage = NiceCiUtils.rightPadKr(nvl(sndMessage), 2000, StringUtils.SPACE);
@ -146,7 +147,7 @@ public class NiceCiDTO {
* </pre> * </pre>
*/ */
@Schema(title = "SMS 발신번호", example = " ") @Schema(title = "SMS 발신번호", example = " ")
@Pattern(regexp = "^$|[\\d]{3,12}", message = "SMS 발신번호는 3 ~ 12자리 입니다") @Pattern(regexp = "^\\s{12}$|[\\d]{3,12}", message = "SMS 발신번호는 3 ~ 12자리 입니다")
private String sndPhoneNo = StringUtils.rightPad(StringUtils.EMPTY, 12, StringUtils.SPACE); private String sndPhoneNo = StringUtils.rightPad(StringUtils.EMPTY, 12, StringUtils.SPACE);
public void setSndPhoneNo(String sndPhoneNo) { public void setSndPhoneNo(String sndPhoneNo) {
this.sndPhoneNo = StringUtils.rightPad(nvl(sndPhoneNo), 12, StringUtils.SPACE); this.sndPhoneNo = StringUtils.rightPad(nvl(sndPhoneNo), 12, StringUtils.SPACE);
@ -196,10 +197,10 @@ public class NiceCiDTO {
* </pre> * </pre>
*/ */
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "버튼요청건수", example = " ") @Schema(requiredMode = Schema.RequiredMode.REQUIRED, title = "버튼요청건수", example = " ")
@Max(value = 5, message = "버튼요청건수는 1자리 입니다") @Pattern(regexp = "^ |[0-5]$", message = "버튼요청건수는 1자리로 최대 5 입니다.")
private String btnReqCnt = StringUtils.SPACE; private String btnReqCnt = StringUtils.SPACE;
public void setBtnReqCnt(Integer btnReqCnt) { public void setBtnReqCnt(Integer btnReqCnt) {
this.btnReqCnt = StringUtils.rightPad(nvl(btnReqCnt == null ? "" : btnReqCnt.toString()), 2, StringUtils.SPACE); this.btnReqCnt = StringUtils.rightPad(nvl(btnReqCnt == null ? "" : btnReqCnt.toString()), 1, StringUtils.SPACE);
} }
/** /**
@ -464,11 +465,12 @@ public class NiceCiDTO {
// return sb.toString(); // return sb.toString();
// } // }
public static Response parse(String tgtStr) { public static Response parse(String tgtString) {
final int repeatLength = 110; final int repeatLength = 110;
final int[] parseLength = { final int[] parseLength = {
10, // tr-code 10, // tr-code
83, // 공통부 83, // 공통부
// FIXME: spec과 상이 - 확인 필요 : "1"이 들어오고 있다
17, // 공란 17, // 공란
2, // 응답건수 2, // 응답건수
1, // SMS발송요청구분코드 1, // SMS발송요청구분코드
@ -478,9 +480,10 @@ public class NiceCiDTO {
84, // 공란 84, // 공란
}; };
// FIXME: 인코딩확인후 적용 // FIXME: 인코딩확인후 적용
String tgtString = NiceCiUtils.covertCharset(tgtStr, "EUC-KR"); //String tgtString = NiceCiUtils.covertCharset(tgtStr, "EUC-KR");
if (StringUtils.isNotBlank(tgtString) && tgtString.length() >= 2319) { //if (StringUtils.isNotBlank(tgtString) && NiceCiUtils.lengthKr(tgtString) >= 2210) {
if (StringUtils.isNotBlank(tgtString)) {
Response response = new Response(); Response response = new Response();
int idx = 0; int idx = 0;
response.setTrCode(StringUtils.left(tgtString, parseLength[idx])); response.setTrCode(StringUtils.left(tgtString, parseLength[idx]));
@ -510,12 +513,13 @@ public class NiceCiDTO {
response.setPrivateEmptyField(StringUtils.left(tgtString, parseLength[idx])); response.setPrivateEmptyField(StringUtils.left(tgtString, parseLength[idx]));
tgtString = tgtString.substring(parseLength[idx]); tgtString = tgtString.substring(parseLength[idx]);
if(tgtString.length() % repeatLength == 0){ if(NiceCiUtils.lengthKr(tgtString) % repeatLength == 0){
int repeat = tgtString.length() / repeatLength; int repeat = NiceCiUtils.lengthKr(tgtString) / repeatLength;
String finalTgtString = tgtString; String finalTgtString = tgtString;
List<NiceCiResult> resResults = IntStream.range(0, repeat) List<NiceCiResult> resResults = IntStream.range(0, repeat)
.mapToObj(i -> { .mapToObj(i -> {
String currentString = finalTgtString.substring(i * repeatLength, (i + 1) * repeatLength); String currentString = NiceCiUtils.substringKr(finalTgtString, i * repeatLength);
//String currentString = finalTgtString.substring(i * repeatLength, (i + 1) * repeatLength);
return NiceCiResult.parse(currentString); return NiceCiResult.parse(currentString);
}) })
.collect(Collectors.toList()); .collect(Collectors.toList());

@ -268,7 +268,7 @@ public class NiceCiResult {
15, // 공란 15, // 공란
}; };
if (StringUtils.isNotBlank(tgtString) && tgtString.length()%110 == 0) { if (StringUtils.isNotBlank(tgtString) && NiceCiUtils.lengthKr(tgtString)%110 == 0) {
NiceCiResult result = new NiceCiResult(); NiceCiResult result = new NiceCiResult();
int idx = 0; int idx = 0;

@ -4,13 +4,11 @@ import java.io.*;
import java.net.*; import java.net.*;
import java.nio.charset.*; import java.nio.charset.*;
import org.apache.commons.lang.*; public class TestSocketServer {
public class Server {
public static void main(String[] args) { public static void main(String[] args) {
try (ServerSocket serverSocket = new ServerSocket(12345)) { // 포트 12345에서 서버 소켓 열기 try (ServerSocket serverSocket = new ServerSocket(10002)) { // 포트 12345에서 서버 소켓 열기
System.out.println("서버가 시작되었습니다."); System.out.println("서버가 시작되었습니다.");
while (true) { while (true) {
@ -23,33 +21,46 @@ public class Server {
} }
private static void handleClient(Socket clientSocket) { private static void handleClient(Socket clientSocket) {
final String res = "trCode " + final String niceCiRes = "0000002310NICEIF 021031896N503P000Z755400 000000010320240919 466241822620240919160011 1013민자도로 관리지원센터에서 김해찬님께 발송한 미납통행료 고지서가 도착했습니다.\n"
// NiceCommon + "\n"
"NICEIF 020031895B503rsltorgId orgMngNo orgSndDt niceMngNo niceSndDt" + + "민자도로 미납통행료 고지서\n"
" "+ + "\n"
// 개별응답부 + "□ 차량번호 : 19너0914\n"
"241~~~~~~~~~~~~~~~~~~~~~~~ 010 1 "+ + "□ 미납발생 노선 : 서울-문산\n"
// 응답반복부 + "□ 미납발생 기간 : 2021년 04월 12일~2023년 08월 30일\n"
"18401011449211name2 001 "+ + "□ 납부금액 : 819,500원(42건)\n"
"19412341234567이름2 1 "; + "□ 납부기한 : 2024년10월01일\n"
+ "□ 납부방법 : \n"
+ "① 하단의 (납부하기) 클릭\n"
+ "② 가상계좌 납부\n"
+ "-(가상계좌) : 농협은행 792000-36-986609\n"
+ "국민은행 731190-72-253083\n"
+ "우리은행 283752-73-918780\n"
+ "신한은행 562146-27-470101\n"
+ "\n"
+ "※ 알림톡 수신 시 종이고지서는 발송되지 않습니다.\n"
+ "\n"
+ "문의처 : 044-211-3377 0442113377 3 18912111020220김해찬 01084289916 0010108428991620240919160011 ";
try (BufferedReader in = new BufferedReader( try (BufferedReader in = new BufferedReader(
new InputStreamReader(clientSocket.getInputStream(), Charset.forName("EUC-KR"))); new InputStreamReader(clientSocket.getInputStream(), Charset.forName("EUC-KR")));
// new InputStreamReader(clientSocket.getInputStream(), Charset.forName("UTF-8")));
BufferedWriter out = new BufferedWriter( BufferedWriter out = new BufferedWriter(
new OutputStreamWriter(clientSocket.getOutputStream(), Charset.forName("EUC-KR")))) { new OutputStreamWriter(clientSocket.getOutputStream(), Charset.forName("EUC-KR")))) {
// 클라이언트로부터 메시지 읽기 // 클라이언트로부터 메시지 읽기
String message; String message;
StringBuffer sb = new StringBuffer(); StringBuffer sb = new StringBuffer();
while((message = in.readLine()) != null && !(message.length() >= 10 && StringUtils.isEmpty(message.trim()))) { // 빈 줄이 들어올 때까지 읽기 while((message = in.readLine()) != null) {
sb.append(message); if("EXIT".equals(message)) break;
sb.append(message).append("\n");
}; };
System.out.println("=============>>>클라이언트로부터 받은 메시지<<<===================================="); System.out.println("=============>>>클라이언트로부터 받은 메시지<<<====================================");
System.out.println(sb.toString()); System.out.println(sb.toString());
System.out.println("=============>>>클라이언트로부터 받은 메시지<<<===================================="); System.out.println("=============>>>클라이언트로부터 받은 메시지<<<====================================");
// 응답 메시지 작성 및 전송 // 응답 메시지 작성 및 전송
out.write(res); out.write(niceCiRes);
out.newLine(); out.newLine();
out.flush(); out.flush();
} catch (IOException e) { } catch (IOException e) {

@ -0,0 +1,37 @@
package cokr.xit.ens.modules.nice.presentation;
import org.springframework.http.*;
import org.springframework.web.bind.annotation.*;
import cokr.xit.ens.modules.nice.service.*;
import io.swagger.v3.oas.annotations.*;
import io.swagger.v3.oas.annotations.tags.*;
import lombok.*;
/**
* <pre>
* description :
* packageName : cokr.xit.ens.modules.nice.presentation
* fileName : NiceCiController
* author : limju
* date : 2024 9 27
* ======================================================================
*
* ----------------------------------------------------------------------
* 2024 9 27 limju
*
* </pre>
*/
@Tag(name = "NiceCiController", description = "NICE CI 인증톡")
@RestController
@RequiredArgsConstructor
@RequestMapping(value = "/nice/talk")
public class NiceCiController {
private final NiceCiService niceCiService;
@Operation(summary = "(대량)전송요청")
@PostMapping(value = "/send/bulk", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> sendBulk() {
return new ResponseEntity<>(niceCiService.requestSendBulk(), HttpStatus.OK);
}
}

@ -0,0 +1,104 @@
package cokr.xit.ens.modules.nice.service;
import org.apache.commons.lang3.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.*;
import cokr.xit.ens.core.aop.*;
import cokr.xit.ens.modules.nice.cmm.*;
import cokr.xit.ens.modules.nice.model.*;
import cokr.xit.ens.modules.nice.service.support.*;
import lombok.*;
import lombok.extern.slf4j.*;
/**
* <pre>
* description :
* packageName : cokr.xit.ens.modules.nice.service
* fileName : NiceCiService
* author : limju
* date : 2024 9 27
* ======================================================================
*
* ----------------------------------------------------------------------
* 2024 9 27 limju
*
* </pre>
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class NiceCiService {
@Value("${contract.niceCi.orgId}")
private String ORG_ID;
@Value("${contract.niceCi.clientId}")
private String CLIENT_ID;
private final NiceCiApiService niceCiApiService;
final String msg = "민자도로 관리지원센터에서 김해찬님께 발송한 미납통행료 고지서가 도착했습니다.\n"
+ "\n"
+ "민자도로 미납통행료 고지서\n"
+ "\n"
+ "□ 차량번호 : 19너0914\n"
+ "□ 미납발생 노선 : 서울-문산\n"
+ "□ 미납발생 기간 : 2021년 04월 12일~2023년 08월 30일\n"
+ "□ 납부금액 : 819,500원(42건)\n"
+ "□ 납부기한 : 2024년10월01일\n"
+ "□ 납부방법 : \n"
+ "① 하단의 (납부하기) 클릭\n"
+ "② 가상계좌 납부\n"
+ "-(가상계좌) : 농협은행 792000-36-986609\n"
+ "국민은행 731190-72-253083\n"
+ "우리은행 283752-73-918780\n"
+ "신한은행 562146-27-470101\n"
+ "\n"
+ "※ 알림톡 수신 시 종이고지서는 발송되지 않습니다.\n"
+ "\n"
+ "문의처 : 044-211-3377";
public EnsResponseVO<?> requestSendBulk() {
NiceCiDTO.Request ciRequest = new NiceCiDTO.Request();
//ciRequest.setTrCode("0000006150");
// // 공통부
//
// // 개별요청부
// nr.setQueryReason(StringUtils.EMPTY);
// nr.setQueryReqCnt(46);
// nr.setSmsSndReqCode("1");
String tmp = NiceCiUtils.rightPadKr(msg, 2000, StringUtils.SPACE);
System.out.println(
String.format("[%s] kr length - %d, utf-8 length - %d", tmp, NiceCiUtils.lengthKr(tmp), tmp.length()));
ciRequest.setSndMessage(msg);
// nr.setSndPhoneNo("010");
// nr.setContactSearchCode("1");
// 공통부
NiceCiCommon nc = new NiceCiCommon();
// nc.setGrpCode("grpCode");
//nc.setTrType("Type");
nc.setTrClassification("31895"); // 거래구분
nc.setOrgId(ORG_ID); // 참가기관Id - property 에서
nc.setOrgMngNo("0000000103"); // 기관관리번호
nc.setOrgSndDt("20240919");
NiceCiDTO.QueryRequest qr = new NiceCiDTO.QueryRequest();
NiceCiDTO.ButtonRequest br = new NiceCiDTO.ButtonRequest();
ciRequest.setNiceCommon(nc);
ciRequest.getQueryRequests().add(qr);
ciRequest.getButtonRequests().add(br);
// nc.setNiceMngNo(StringUtils.EMPTY);
// nc.setNiceSndDt(StringUtils.EMPTY);
String ciTxt = ciRequest.ofString();
String ft = String.format("%s%s", StringUtils.leftPad(String.valueOf(NiceCiUtils.lengthKr(ciTxt)), 10, "0"),
ciTxt);
System.out.println(
String.format("[%s] kr length - %d, utf-8 length - %d", ft, NiceCiUtils.lengthKr(ft), ft.length()));
// String rtnMsg = niceCiApiService.requestSendBulk(ciRequest);
// NiceCiDTO.Response resDTO = NiceCiDTO.Response.parse(rtnMsg);
return niceCiApiService.requestSendBulk(ciRequest);
}
}

@ -0,0 +1,127 @@
package cokr.xit.ens.modules.nice.service.support;
import java.io.*;
import java.net.*;
import java.nio.charset.*;
import java.util.*;
import java.util.stream.*;
import javax.validation.*;
import org.apache.commons.lang3.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.*;
import cokr.xit.ens.core.aop.*;
import cokr.xit.ens.core.exception.*;
import cokr.xit.ens.core.exception.code.*;
import cokr.xit.ens.modules.nice.cmm.*;
import cokr.xit.ens.modules.nice.model.*;
import lombok.*;
import lombok.extern.slf4j.*;
/**
* <pre>
* description :
* packageName : cokr.xit.ens.modules.nice.service.support
* fileName : NiceCiService
* author : limju
* date : 2024 9 27
* ======================================================================
*
* ----------------------------------------------------------------------
* 2024 9 27 limju
*
* </pre>
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class NiceCiApiService {
@Value("${contract.niceCi.host}")
private String HOST;
@Value("${contract.niceCi.port}")
private int PORT;
@Value("${contract.niceCi.timeout}")
private int TIMEOUT;
private static final Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
public EnsResponseVO<?> requestSendBulk(final NiceCiDTO.Request reqDTO) {
List<String> errors = new ArrayList<>();
final Set<ConstraintViolation<NiceCiDTO.Request>> list = validator.validate(reqDTO);
if (!list.isEmpty()) {
errors.addAll(list.stream()
.map(row -> String.format("%s=%s", row.getPropertyPath(), row.getMessageTemplate()))
.collect(Collectors.toList())
);
}
if(!errors.isEmpty()){
return EnsResponseVO.errBuilder()
.errCode(EnsErrCd.INVALID_DATA)
.errMsg(errors.toString())
.build();
}
String ciTxt = reqDTO.ofString();
String ft = String.format("%s%s", StringUtils.leftPad(String.valueOf(NiceCiUtils.lengthKr(ciTxt)), 10, "0"),
ciTxt);
log.info("[{}] kr length - {}, utf-8 length - {}", ft, NiceCiUtils.lengthKr(ft), ft.length());
final String rtnMsg;
try {
rtnMsg = sendNiceCiSocket(ft);
} catch (Exception e) {
return EnsResponseVO.errBuilder()
.errCode(EnsErrCd.API_COMM_ERROR)
.errMsg(e.getMessage())
.build();
}
NiceCiDTO.Response resDTO = NiceCiDTO.Response.parse(rtnMsg);
return EnsResponseVO.okBuilder()
.resultInfo(resDTO)
.build();
}
private String sendNiceCiSocket(final String binTxt) {
String rtnMsg = "";
try (Socket socket = new Socket(HOST, PORT); // 서버에 연결
BufferedWriter out = new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream(), Charset.forName("EUC-KR")));
//new OutputStreamWriter(socket.getOutputStream()));
BufferedReader in = new BufferedReader(
new InputStreamReader(socket.getInputStream(), Charset.forName("EUC-KR")))) {
socket.setSoTimeout(TIMEOUT); // 읽기 타임아웃 설정
out.write(binTxt);
// FIXME: 테스트 소켓서버 통신을 위해 임시로 추가 : 테스트 완료후 제거
out.write("\nEXIT");
out.newLine();
out.flush();
String message;
StringBuffer sb = new StringBuffer();
while((message = in.readLine()) != null) {
sb.append(message);
};
rtnMsg = sb.toString();
System.out.println("=============>>>서버 응답(EUC-KR로 읽어온 값)<<<====================================");
System.out.println(rtnMsg);
System.out.println("=============>>>서버 응답(EUC-KR로 읽어온 값)<<<====================================");
} catch (SocketTimeoutException e) {
// 타임아웃 발생 시 처리
log.error("NICE CI Socket 서버 응답 시간 초과: " + e.getMessage());
throw BizRuntimeException.create("NICE CI Socket 서버 응답 시간 초과로 인해 통신이 종료되었습니다.");
} catch (IOException e) {
throw BizRuntimeException.create(e.getMessage());
}
return rtnMsg;
}
}

@ -2,7 +2,7 @@ app:
access: access:
auth: auth:
exclude: exclude:
uri: ${xit.app.ctx}/example/.*, ${xit.app.ctx}/kko/mydoc/.*, ${xit.app.ctx}/kko/talk/.*, ${xit.app.ctx}/kko/alimtalk/.*, ${xit.app.ctx}/nv/signtalk/.*, ${xit.app.ctx}/kt/signtalk/.*, ${xit.app.ctx}/kt/gibis/.*, ${xit.app.ctx}/api/msg/result, ${xit.app.ctx}/iup/.*, ${xit.app.ctx}/traffic/.*, ${xit.app.ctx}/sys/mng/.*, ${xit.app.ctx}/sys/util/.*, ${xit.app.ctx}/intgrn/noti/.*, ${xit.app.ctx}/cmft/.*, ${xit.app.ctx}/bill/.* uri: ${xit.app.ctx}/example/.*, ${xit.app.ctx}/kko/mydoc/.*, ${xit.app.ctx}/kko/talk/.*, ${xit.app.ctx}/nice/talk/.*, ${xit.app.ctx}/kko/alimtalk/.*, ${xit.app.ctx}/nv/signtalk/.*, ${xit.app.ctx}/kt/signtalk/.*, ${xit.app.ctx}/kt/gibis/.*, ${xit.app.ctx}/api/msg/result, ${xit.app.ctx}/iup/.*, ${xit.app.ctx}/traffic/.*, ${xit.app.ctx}/sys/mng/.*, ${xit.app.ctx}/sys/util/.*, ${xit.app.ctx}/intgrn/noti/.*, ${xit.app.ctx}/cmft/.*, ${xit.app.ctx}/bill/.*
pallel: pallel:
thread: thread:
basic: basic:

@ -135,8 +135,11 @@ contract:
read: /api/msg/read read: /api/msg/read
niceCi: niceCi:
ip: 10.1.1.55 host: 127.0.0.1
#host: 10.1.1.5
port: 10002 port: 10002
# ms
timeout: 3000
orgId: Z755400 orgId: Z755400
# 개발 # 개발
clientId: 0027370001 clientId: 0027370001

@ -46,11 +46,4 @@
<setting name="aggressiveLazyLoading" value="true" /> <setting name="aggressiveLazyLoading" value="true" />
</settings> </settings>
<!-- Type Aliases 설정-->
<!-- <typeAliases>-->
<!-- <typeAlias alias="egovMap" type="org.egovframe.rte.psl.dataaccess.util.EgovMap" />-->
<!-- <typeAlias alias="ComDefaultCodeVO" type="egovframework.com.cmm.model.ComDefaultCodeVO" />-->
<!-- <typeAlias alias="comDefaultVO" type="egovframework.com.cmm.model.ComDefaultVO" />-->
<!-- </typeAliases>-->
</configuration> </configuration>

Loading…
Cancel
Save