commit 2a7444b1fb0a1d744ca028ca0f9642713c4a455e Author: mjkhan21 Date: Thu Feb 13 16:42:06 2025 +0900 최초 커밋 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..37cf787 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +/.classpath +/.factorypath +/.project +/.settings/ +/logs/ +/target/ diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..87d5e5b --- /dev/null +++ b/pom.xml @@ -0,0 +1,140 @@ + + 4.0.0 + + cokr.xit.interfaces + xit-postplus + 23.04.01-SNAPSHOT + jar + + xit-postplus + http://maven.apache.org + + + UTF-8 + + 17 + ${java.version} + ${java.version} + + + + + + mvn2s + https://repo1.maven.org/maven2/ + + true + + + true + + + + egovframe + https://maven.egovframe.go.kr/maven/ + + true + + + false + + + + maven-public + https://nas.xit.co.kr:8888/repository/maven-public/ + + + + + + + cokr.xit.interfaces + xit-filejob + 23.04.01-SNAPSHOT + + + + + install + ${basedir}/target + ${artifactId}-${version} + + + ${basedir}/src/main/resources + + + ${basedir}/src/test/resources + ${basedir}/src/main/resources + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.3.0 + + + **/*.class + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.0.0 + + true + xml + + **/Abstract*.java + **/*Suite.java + + + **/*Test.java + + + + + org.codehaus.mojo + emma-maven-plugin + true + + + org.apache.maven.plugins + maven-source-plugin + 2.2 + + + attach-sources + + jar + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.9.1 + + + + + + + + + maven-snapshot + https://nas.xit.co.kr:8888/repository/maven-snapshots/ + + + + maven-release + https://nas.xit.co.kr:8888/repository/maven-releases/ + + + + \ No newline at end of file diff --git a/src/main/java/cokr/xit/interfaces/postplus/Postplus.java b/src/main/java/cokr/xit/interfaces/postplus/Postplus.java new file mode 100644 index 0000000..8796050 --- /dev/null +++ b/src/main/java/cokr/xit/interfaces/postplus/Postplus.java @@ -0,0 +1,70 @@ +package cokr.xit.interfaces.postplus; + +import java.util.Collections; +import java.util.Map; + +import org.springframework.core.io.ClassPathResource; + +import cokr.xit.foundation.AbstractComponent; +import cokr.xit.foundation.data.JSON; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class Postplus extends AbstractComponent { + public static enum Service { + PST("PST"), SMS("SMS"), KKO("KKO"); + + private String code; + + private Service(String code) { + this.code = code; + } + + public String getCode() { + return this.code; + } + } + + private static Postplus conf; + + public static Postplus get() { + if (conf == null) + try { + ClassPathResource res = new ClassPathResource("intf-conf/xit-postplus.conf"); + conf = new JSON().parse(res.getInputStream(), Postplus.class); + } catch (Exception e) { + throw runtimeException(e); + } + return conf; + } + + private String + host, + version; + private boolean test; + private Map + urls, + apiKeys; + + public String getTest() { + return test ? "Y" : "N"; + } + + public String apiKey(String key) { + return !isEmpty(apiKeys) ? apiKeys.get(key) : null; + } + + private Map urls() { + return ifEmpty(urls, Collections::emptyMap); + } + + public String requestProductionURL() { + return getHost() + urls().getOrDefault("requestProduction", "/po/api/postplusPstMsrApi.do"); + } + + public String productionStatusURL() { + return getHost() + urls().getOrDefault("productionStatus", "/po/api/postplusPstStatusApi.do"); + } +} \ No newline at end of file diff --git a/src/main/java/cokr/xit/interfaces/postplus/post/PostController.java b/src/main/java/cokr/xit/interfaces/postplus/post/PostController.java new file mode 100644 index 0000000..edaebca --- /dev/null +++ b/src/main/java/cokr/xit/interfaces/postplus/post/PostController.java @@ -0,0 +1,59 @@ +package cokr.xit.interfaces.postplus.post; + +import java.io.InputStream; +import java.util.List; + +import javax.annotation.Resource; + +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.multipart.MultipartFile; + +import cokr.xit.foundation.data.Named; +import cokr.xit.foundation.web.AbstractController; +import cokr.xit.interfaces.postplus.post.service.PostService; +import cokr.xit.interfaces.postplus.post.service.StatusResponse; + +@RequestMapping(name = "포스트플러스 우편연계", value = "/intf/postplus/post", produces = MediaType.APPLICATION_JSON_VALUE) +public class PostController extends AbstractController { + @Resource(name = "postService") + private PostService postService; + + /**우편제작 신청정보를 전송한다. + * @param apiID apiKey의 식별자 + * @param master 마스터 정보 + * @param details 상세 정보 + * @param attachments 첨부파일 + * @return 신청결과 + */ + @PostMapping(name = "우편제작 신청", value = "/request") + public PostResponse requestProduction( + String apiID, + PstMsr.Master master, + List details, + @RequestParam(required = false) List attachments + ) { + List> uploads = !isEmpty(attachments) ? attachments.stream() + .map(attached -> { + try { + return new Named(attached.getOriginalFilename(), attached.getInputStream()); + } catch (Exception e) { + throw runtimeException(e); + } + }) + .toList() : null; + return postService.requestProduction(apiID, master, details, uploads); + } + + /**지정하는 연계식별키의 우편제작 상태를 조회한다. + * @param apiID apiKey의 식별자 + * @param intfID 우편제작 요청 연계식별키 + * @return 우편제작상태 + */ + @PostMapping(name = "신청우편 상태 조회", value = "/status") + public List getProductionStatus(String apiID, String intfID) { + return postService.getProductionStatus(apiID, intfID); + } +} \ No newline at end of file diff --git a/src/main/java/cokr/xit/interfaces/postplus/post/PostResponse.java b/src/main/java/cokr/xit/interfaces/postplus/post/PostResponse.java new file mode 100644 index 0000000..402944b --- /dev/null +++ b/src/main/java/cokr/xit/interfaces/postplus/post/PostResponse.java @@ -0,0 +1,15 @@ +package cokr.xit.interfaces.postplus.post; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class PostResponse { + @JsonProperty("결과") + private String result; + @JsonProperty("비고") + private String remark; +} \ No newline at end of file diff --git a/src/main/java/cokr/xit/interfaces/postplus/post/PstMsr.java b/src/main/java/cokr/xit/interfaces/postplus/post/PstMsr.java new file mode 100644 index 0000000..f124bfa --- /dev/null +++ b/src/main/java/cokr/xit/interfaces/postplus/post/PstMsr.java @@ -0,0 +1,548 @@ +package cokr.xit.interfaces.postplus.post; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.util.List; + +import cokr.xit.foundation.AbstractComponent; +import cokr.xit.foundation.data.DataObject; +import cokr.xit.foundation.data.Named; +import cokr.xit.interfaces.postplus.Postplus; + +/**우편제작 신청 정보 + * @author mjkhan + */ +public class PstMsr extends AbstractComponent { + /**우편제작 신청 마스터 정보 + * @author mjkhan + */ + public static class Master { + private static final List cols = List.of(new String[] { + "버전", "테스트여부", "서비스", "연계식별키", "봉투", + "봉투창", "흑백칼라", "단면양면", "배달", "템플릿코드", + "템플릿출력여부", "수취인수", "여백생성유무", "주소페이지유무", "맞춤자제유무", + "메일머지유무", "동봉물유무", "반송여부", "스테이플러유무", "로고파일", + "발송인명", "발송인우편번호", "발송인주소", "발송인상세주소", "발송인전화번호" + }); + + /** 버전 */ + private String version; + /** 테스트여부 */ + private String testYN; + /** 서비스 */ + private String service; + /** 연계식별키 */ + private String intfID; + /** 봉투 */ + private String envelop; + /** 봉투창 */ + private String envelopWindow; + /** 흑백칼라 */ + private String bwColor; + /** 단면양면 */ + private String faceType; + /** 배달 */ + private String delivery; + /** 템플릿코드 */ + private String templateCode; + /** 템플릿출력여부 */ + private String templatePrint; + /** 수취인수 */ + private String recipientCount; + /** 여백생성유무 */ + private String marginYN; + /** 주소페이지유무 */ + private String addressPageYN; + /** 맞춤자제유무 */ + private String orderYN; + /** 메일머지유무 */ + private String mailMergeYN; + /** 동봉물유무 */ + private String enclosedYN; + /** 반송여부 */ + private String returnYN; + /** 스테이플러유무 */ + private String staplerYN; + /** 로고파일 */ + private String logoFile; + /** 발송인명 */ + private String senderName; + /** 발송인우편번호 */ + private String senderZipcode; + /** 발송인주소 */ + private String senderAddress; + /** 발송인상세주소 */ + private String senderDetailAddress; + /** 발송인전화번호 */ + private String senderPhoneNo; + + /**버전을 설정한다. + * @param version 버전 + * @return 현재 Master + */ + public Master setVersion(String version) { + this.version = version; + return this; + } + + /**테스트 여부를 설정한다. + * @param testYN 테스트 여부 + * @return 현재 Master + */ + public Master setTestYN(String testYN) { + this.testYN = testYN; + return this; + } + + /**서비스를 설정한다. + * @param service 서비스 + * @return 현재 Master + */ + public Master setService(String service) { + this.service = service; + return this; + } + + /**연계식별키를 설정한다. + * @param intfID 연계식별키 + * @return 현재 Master + */ + public Master setIntfID(String intfID) { + this.intfID = intfID; + return this; + } + + /**봉투를 설정한다. + * @param envelop 봉투 + * @return 현재 Master + */ + public Master setEnvelop(String envelop) { + this.envelop = envelop; + return this; + } + + /**봉투창을 설정한다. + * @param envelopWindow 봉투창 + * @return 현재 Master + */ + public Master setEnvelopWindow(String envelopWindow) { + this.envelopWindow = envelopWindow; + return this; + } + + /**흑백칼라를 설정한다. + * @param bwColor 흑백칼라 + * @return 현재 Master + */ + public Master setBwColor(String bwColor) { + this.bwColor = bwColor; + return this; + } + + /**단면양면을 설정한다. + * @param faceType 단면양면 + * @return 현재 Master + */ + public Master setFaceType(String faceType) { + this.faceType = faceType; + return this; + } + + /**배달을 설정한다. + * @param delivery 배달 + * @return 현재 Master + */ + public Master setDelivery(String delivery) { + this.delivery = delivery; + return this; + } + + /**템플릿코드를 설정한다. + * @param templateCode 템플릿코드 + * @return 현재 Master + */ + public Master setTemplateCode(String templateCode) { + this.templateCode = templateCode; + return this; + } + + /**템플릿출력여부를 설정한다. + * @param templatePrint 템플릿출력여부 + * @return 현재 Master + */ + public Master setTemplatePrint(String templatePrint) { + this.templatePrint = templatePrint; + return this; + } + + /**수취인수를 설정한다. + * @param recipientCount 수취인수 + * @return 현재 Master + */ + public Master setRecipientCount(String recipientCount) { + this.recipientCount = recipientCount; + return this; + } + + /**여백생성유무를 설정한다. + * @param marginYN 여백생성유무 + * @return 현재 Master + */ + public Master setMarginYN(String marginYN) { + this.marginYN = marginYN; + return this; + } + + /**주소페이지유무를 설정한다. + * @param addressPageYN 주소페이지유무 + * @return 현재 Master + */ + public Master setAddressPageYN(String addressPageYN) { + this.addressPageYN = addressPageYN; + return this; + } + + /**맞춤자제유무를 설정한다. + * @param orderYN 맞춤자제유무 + * @return 현재 Master + */ + public Master setOrderYN(String orderYN) { + this.orderYN = orderYN; + return this; + } + + /**메일머지유무를 설정한다. + * @param mailMergeYN 메일머지유무 + * @return 현재 Master + */ + public Master setMailMergeYN(String mailMergeYN) { + this.mailMergeYN = mailMergeYN; + return this; + } + + /**동봉물유무를 설정한다. + * @param enclosedYN 동봉물유무 + * @return 현재 Master + */ + public Master setEnclosedYN(String enclosedYN) { + this.enclosedYN = enclosedYN; + return this; + } + + /**반송여부를 설정한다. + * @param returnYN 반송여부 + * @return 현재 Master + */ + public Master setReturnYN(String returnYN) { + this.returnYN = returnYN; + return this; + } + + /**스테이플러유무를 설정한다. + * @param staplerYN 스테이플러유무 + * @return 현재 Master + */ + public Master setStaplerYN(String staplerYN) { + this.staplerYN = staplerYN; + return this; + } + + /**로고파일을 설정한다. + * @param logoFile 로고파일 + * @return 현재 Master + */ + public Master setLogoFile(String logoFile) { + this.logoFile = logoFile; + return this; + } + + /**발송인명을 설정한다. + * @param senderName 발송인명 + * @return 현재 Master + */ + public Master setSenderName(String senderName) { + this.senderName = senderName; + return this; + } + + /**발송인우편번호를 설정한다. + * @param senderZipcode 발송인우편번호 + * @return 현재 Master + */ + public Master setSenderZipcode(String senderZipcode) { + this.senderZipcode = senderZipcode; + return this; + } + + /**발송인주소를 설정한다. + * @param senderAddress 발송인주소 + * @return 현재 Master + */ + public Master setSenderAddress(String senderAddress) { + this.senderAddress = senderAddress; + return this; + } + + /**발송인상세주소를 설정한다. + * @param senderDetailAddress 발송인상세주소 + * @return 현재 Master + */ + public Master setSenderDetailAddress(String senderDetailAddress) { + this.senderDetailAddress = senderDetailAddress; + return this; + } + + /**발송인전화번호를 설정한다. + * @param senderPhoneNo 발송인전화번호 + * @return 현재 Master + */ + public Master setSenderPhoneNo(String senderPhoneNo) { + this.senderPhoneNo = senderPhoneNo; + return this; + } + + /**마스터 정보를 신청 포맷으로 변환한다. + * @return 마스터 정보의 신청 포맷 + */ + public DataObject toRequest() { + List row = List.of(new String[] { + ifEmpty(version, Postplus.get()::getVersion), + ifEmpty(testYN, Postplus.get()::getTest), + ifEmpty(service, Postplus.Service.PST::getCode), + blankIfEmpty(intfID), + blankIfEmpty(envelop), + blankIfEmpty(envelopWindow), + blankIfEmpty(bwColor), + blankIfEmpty(faceType), + blankIfEmpty(delivery), + blankIfEmpty(templateCode), + blankIfEmpty(templatePrint), + blankIfEmpty(recipientCount), + blankIfEmpty(marginYN), + blankIfEmpty(addressPageYN), + blankIfEmpty(orderYN), + blankIfEmpty(mailMergeYN), + blankIfEmpty(enclosedYN), + blankIfEmpty(returnYN), + blankIfEmpty(staplerYN), + blankIfEmpty(logoFile), + blankIfEmpty(senderName), + blankIfEmpty(senderZipcode), + blankIfEmpty(senderAddress), + blankIfEmpty(senderDetailAddress), + blankIfEmpty(senderPhoneNo) + }); + + return new DataObject() + .set("cols", cols) + .set("rows", row); + } + } + + /**우편제작 신청 상세정보 + * @author mjkhan + */ + public static class Detail { + private static final List cols = List.of(new String[] { + "순번", "이름", "우편번호", "주소", "상세주소", + "전화번호", "첨부파일", "가변1", "가변2", "가변3", "가변4" + }); + + public static DataObject toRequest(List details) { + List> rows = details.stream() + .map(Detail::toRow) + .toList(); + return new DataObject() + .set("cols", cols) + .set("rows", rows); + } + + /** 순번 */ + private String seq; + /** 이름 */ + private String name; + /** 우편번호 */ + private String zipcode; + /** 주소 */ + private String address; + /** 상세주소 */ + private String detailAddress; + /** 전화번호 */ + private String phoneNo; + /** 첨부파일 */ + private String attachment; + /** 가변1 */ + private String reserved1; + /** 가변2 */ + private String reserved2; + /** 가변3 */ + private String reserved3; + /** 가변4 */ + private String reserved4; + + /**순번을 설정한다. + * @param seq 순번 + * @return 현재 Detail + */ + public Detail setSeq(String seq) { + this.seq = seq; + return this; + } + + /**이름을 설정한다. + * @param name 이름 + * @return 현재 Detail + */ + public Detail setName(String name) { + this.name = name; + return this; + } + + /**우편번호를 설정한다. + * @param zipcode 우편번호 + * @return 현재 Detail + */ + public Detail setZipcode(String zipcode) { + this.zipcode = zipcode; + return this; + } + + /**주소를 설정한다. + * @param address 주소 + * @return 현재 Detail + */ + public Detail setAddress(String address) { + this.address = address; + return this; + } + + /**상세주소를 설정한다. + * @param detailAddress 상세주소 + * @return 현재 Detail + */ + public Detail setDetailAddress(String detailAddress) { + this.detailAddress = detailAddress; + return this; + } + + /**전화번호를 설정한다. + * @param phoneNo 전화번호 + * @return 현재 Detail + */ + public Detail setPhoneNo(String phoneNo) { + this.phoneNo = phoneNo; + return this; + } + + /**첨부파일을 설정한다. + * @param attachment 첨부파일 + * @return 현재 Detail + */ + public Detail setAttachment(String attachment) { + this.attachment = attachment; + return this; + } + + /**가변1을 설정한다. + * @param reserved1 가변1 + * @return 현재 Detail + */ + public Detail setReserved1(String reserved1) { + this.reserved1 = reserved1; + return this; + } + + /**가변2를 설정한다. + * @param reserved2 가변2 + * @return 현재 Detail + */ + public Detail setReserved2(String reserved2) { + this.reserved2 = reserved2; + return this; + } + + /**가변3을 설정한다. + * @param reserved3 가변3 + * @return 현재 Detail + */ + public Detail setReserved3(String reserved3) { + this.reserved3 = reserved3; + return this; + } + + /**가변4를 설정한다. + * @param reserved4 가변4 + * @return 현재 Detail + */ + public Detail setReserved4(String reserved4) { + this.reserved4 = reserved4; + return this; + } + + /**상세정보를 신청포맷으로 변환한다. + * @return 상세정보의 신청포맷 + */ + public List toRow() { + return List.of(new String[] { + blankIfEmpty(seq), + blankIfEmpty(name), + blankIfEmpty(zipcode), + blankIfEmpty(address), + blankIfEmpty(detailAddress), + blankIfEmpty(phoneNo), + blankIfEmpty(attachment), + blankIfEmpty(reserved1), + blankIfEmpty(reserved2), + blankIfEmpty(reserved3), + blankIfEmpty(reserved4) + }); + } + } + + /**주어진 파일을 {@code Named}으로 변환한다. + * @param file 파일 + * @return {@code Named} + */ + public static Named toNamedInputStream(File file) { + try { + return new Named(file.getName(), new FileInputStream(file)); + } catch (Exception e) { + throw runtimeException(e); + } + } + + private Master master; + private List details; + + /**우편제작 신청 마스터정보를 설정한다. + * @param master 우편제작 신청 마스터정보 + * @return 현재 PstMsr + */ + public PstMsr setMaster(Master master) { + this.master = master; + return this; + } + + /**우편제작 신청 상세정보를 설정한다. + * @param details 우편제작 신청 상세정보 + * @return 현재 PstMsr + */ + public PstMsr setDetails(List details) { + int size = details != null ? details.size() : 0; + for (int i = 0; i < size; ++i) + details.get(i).setSeq(Integer.toString(i + 1)); + + this.details = details; + return this; + } + + /**우편제작 정보를 신청포맷으로 변환한다. + * @return 우편제작 정보의 신청포맷 + */ + public DataObject toRequest() { + return new DataObject() + .set("master", master.toRequest()) + .set("detail", Detail.toRequest(details)); + } +} \ No newline at end of file diff --git a/src/main/java/cokr/xit/interfaces/postplus/post/service/PostService.java b/src/main/java/cokr/xit/interfaces/postplus/post/service/PostService.java new file mode 100644 index 0000000..04abb35 --- /dev/null +++ b/src/main/java/cokr/xit/interfaces/postplus/post/service/PostService.java @@ -0,0 +1,29 @@ +package cokr.xit.interfaces.postplus.post.service; + +import java.io.InputStream; +import java.util.List; + +import cokr.xit.foundation.data.Named; +import cokr.xit.interfaces.postplus.post.PostResponse; +import cokr.xit.interfaces.postplus.post.PstMsr; + +/**포스트플러스의 우편 서비스 연계를 제공하는 서비스 + * @author mjkhan + */ +public interface PostService { + /**우편제작 신청정보를 전송한다. + * @param apiID apiKey의 식별자 + * @param master 마스터 정보 + * @param details 상세 정보 + * @param attachments 첨부파일 + * @return 신청결과 + */ + PostResponse requestProduction(String apiID, PstMsr.Master master, List details, List> attachments); + + /**지정하는 연계식별키의 우편제작 상태를 조회한다. + * @param apiID apiKey의 식별자 + * @param intfID 우편제작 요청 연계식별키 + * @return 우편제작상태 + */ + List getProductionStatus(String apiID, String intfID); +} \ No newline at end of file diff --git a/src/main/java/cokr/xit/interfaces/postplus/post/service/StatusResponse.java b/src/main/java/cokr/xit/interfaces/postplus/post/service/StatusResponse.java new file mode 100644 index 0000000..e780dd2 --- /dev/null +++ b/src/main/java/cokr/xit/interfaces/postplus/post/service/StatusResponse.java @@ -0,0 +1,37 @@ +package cokr.xit.interfaces.postplus.post.service; + +import java.util.List; +import java.util.Map; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import cokr.xit.interfaces.postplus.post.PostResponse; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class StatusResponse extends PostResponse { + @JsonProperty("신청일자") + private String reqDate; + @JsonProperty("봉투") + private String envelop; + @JsonProperty("배달") + private String delivery; + @JsonProperty("흑백칼라") + private String bwColor; + @JsonProperty("단면양면") + private String faceType; + @JsonProperty("발송건수") + private String sendCount; + @JsonProperty("상태") + private String status; + @JsonProperty("시작등기번호") + private String startRegNo; + @JsonProperty("종료등기번호") + private String endRegNo; + @JsonProperty("연계식별키") + private String intfID; + @JsonProperty("순번등기번호") + private List> sortedRegNos; +} \ No newline at end of file diff --git a/src/main/java/cokr/xit/interfaces/postplus/post/service/bean/PostServiceBean.java b/src/main/java/cokr/xit/interfaces/postplus/post/service/bean/PostServiceBean.java new file mode 100644 index 0000000..4414707 --- /dev/null +++ b/src/main/java/cokr/xit/interfaces/postplus/post/service/bean/PostServiceBean.java @@ -0,0 +1,83 @@ +package cokr.xit.interfaces.postplus.post.service.bean; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.net.http.HttpResponse; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.springframework.stereotype.Service; + +import com.fasterxml.jackson.core.type.TypeReference; + +import cokr.xit.foundation.component.AbstractServiceBean; +import cokr.xit.foundation.data.DataObject; +import cokr.xit.foundation.data.JSON; +import cokr.xit.foundation.data.Named; +import cokr.xit.foundation.web.WebClient; +import cokr.xit.interfaces.postplus.Postplus; +import cokr.xit.interfaces.postplus.post.PostResponse; +import cokr.xit.interfaces.postplus.post.PstMsr; +import cokr.xit.interfaces.postplus.post.service.PostService; +import cokr.xit.interfaces.postplus.post.service.StatusResponse; + +@Service("postService") +public class PostServiceBean extends AbstractServiceBean implements PostService { + private static String apiKey(String apiID) { + return Postplus.get().apiKey(apiID); + } + + private JSON json = new JSON(); + + @Override + public PostResponse requestProduction(String apiID, PstMsr.Master master, List details, List> attachments) { + DataObject pstMsr = new PstMsr() + .setMaster(master) + .setDetails(details) + .toRequest(); + + String str = json.stringify(pstMsr, true); + log().debug("production request:\n{}", str); + Named pstFile = new Named<>("pstFile.json", new ByteArrayInputStream(str.getBytes(StandardCharsets.UTF_8))); + + ArrayList> files = new ArrayList<>(); + files.add(pstFile); + files.addAll(ifEmpty(attachments, Collections::emptyList)); + + try { + HttpResponse hresp = new WebClient().upload(req -> + req.uri(Postplus.get().requestProductionURL()) + .data("apiKey", apiKey(apiID)) + .data("pstFile", files) + ); + String body = hresp.body(); + log().debug("response:\n{}", body); + + return json.parse(body, PostResponse.class); + } finally { + files.forEach(file -> { + try { + file.getValue().close(); + } catch (Exception e) { + throw runtimeException(e); + } + }); + } + } + + @Override + public List getProductionStatus(String apiID, String intfID) { + HttpResponse hresp = new WebClient().post(req -> + req.uri(Postplus.get().productionStatusURL()) + .json(json) + .data("apiKey", apiKey(apiID)) + .data("inputCode", intfID) + ); + String body = hresp.body(); + log().debug("response:\n{}", body); + + return json.parse(body, new TypeReference>() {}); + } +} \ No newline at end of file diff --git a/src/main/resources/intf-conf/xit-postplus.conf b/src/main/resources/intf-conf/xit-postplus.conf new file mode 100644 index 0000000..93cf75f --- /dev/null +++ b/src/main/resources/intf-conf/xit-postplus.conf @@ -0,0 +1,15 @@ +{ + "host": "https://t.postplus.co.kr", /* API 서비스 호스트 */ + "version": "v1.10", + /* API 키 */ + "apiKeys": { + "site0": "00197D16F7FE4A84E9C97F55033339FBE07C8850882FFA26F3E538E0DDF0DB1EFEEC3DB451AE1EE011776DEB1505120A556942FA98240AADD3A73F085313AF693545931B338D1B92365F5B1A8AEBC939E33" + } +/* + , "test": true + "urls": { // 지정하지 않으면 디폴트 URL 사용 + "requestProduction": "우편제작 신청 URL", + "productionStatus": "신청우편 상태조회 URL" + } +*/ +} \ No newline at end of file diff --git a/src/main/sql/xit-postplus-mariadb.sql b/src/main/sql/xit-postplus-mariadb.sql new file mode 100644 index 0000000..e69de29 diff --git a/src/test/java/cokr/xit/interfaces/postplus/post/service/PostServiceTest.java b/src/test/java/cokr/xit/interfaces/postplus/post/service/PostServiceTest.java new file mode 100644 index 0000000..2fd46bd --- /dev/null +++ b/src/test/java/cokr/xit/interfaces/postplus/post/service/PostServiceTest.java @@ -0,0 +1,90 @@ +package cokr.xit.interfaces.postplus.post.service; + +import java.util.List; + +import javax.annotation.Resource; + +import org.junit.jupiter.api.Test; + +import cokr.xit.foundation.test.TestSupport; +import cokr.xit.interfaces.postplus.Postplus; +import cokr.xit.interfaces.postplus.post.PostResponse; +import cokr.xit.interfaces.postplus.post.PstMsr; + +public class PostServiceTest extends TestSupport { + @Resource(name = "postService") + private PostService postService; + private String apiID = "site0"; + + @Test + void postplus() { + Postplus conf = Postplus.get(); + System.out.println("host: " + conf.getHost()); + System.out.println("apiKeys: " + conf.getApiKeys()); + System.out.println("version: " + conf.getVersion()); + System.out.println("test: " + conf.getTest()); + + System.out.println("requestProductionURL: " + conf.requestProductionURL()); + System.out.println("productionStatusURL: " + conf.productionStatusURL()); + } + + @Test + void requestProduction() { + PstMsr.Master master = new PstMsr.Master() + .setTestYN("Y") + .setIntfID("POST20230428_000001") + .setEnvelop("소봉투") + .setEnvelopWindow("이중창") + .setBwColor("흑백") + .setFaceType("단면") + .setDelivery("일반") + .setTemplateCode("") + .setTemplatePrint("N") + .setRecipientCount("2") + .setMarginYN("N") + .setAddressPageYN("N") + .setOrderYN("N") + .setMailMergeYN("N") + .setEnclosedYN("N") + .setReturnYN("N") + .setStaplerYN("N") + .setLogoFile("N") + .setSenderName("포스토피아") + .setSenderZipcode("5048") + .setSenderAddress("서울특별시 광진구 강변역로2") + .setSenderDetailAddress("서울광진우체국 B동 4층") + .setSenderPhoneNo("1577-8114"); + + List details = List.of( + new PstMsr.Detail() + .setName("홍길동1") + .setZipcode("31010") + .setAddress("서울특별시 광진구 강변역로2") + .setDetailAddress("서울광진우체국 B동 1층") + .setPhoneNo("1012341234") + .setAttachment("pstFile.pdf") + .setReserved1("24926737") + .setReserved2("2021-09-02") + .setReserved3("대출(고정)") + .setReserved4("31,000,000"), + new PstMsr.Detail() + .setName("홍길동2") + .setZipcode("08394") + .setAddress("서울특별시 광진구 강변역로2") + .setDetailAddress("서울광진우체국 B동 2층") + .setPhoneNo("01012341234") + .setAttachment("pstFile.pdf") + .setReserved1("25685047") + .setReserved2("2021-09-02") + .setReserved3("대출B(고정)") + .setReserved4("421,000,000") + ); + + PostResponse resp = postService.requestProduction(apiID, master, details, null); + } + + @Test + void productionStatus() { + + } +} \ No newline at end of file diff --git a/src/test/resources/spring/context-common.xml b/src/test/resources/spring/context-common.xml new file mode 100644 index 0000000..3d075d1 --- /dev/null +++ b/src/test/resources/spring/context-common.xml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + classpath:message/message-common + classpath:message/authentication-message + classpath:org/egovframe/rte/fdl/property/messages/properties + + + + + 60 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/spring/context-datasource.xml b/src/test/resources/spring/context-datasource.xml new file mode 100644 index 0000000..6714e41 --- /dev/null +++ b/src/test/resources/spring/context-datasource.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + oracle + mariadb + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/sql/mapper/base/test-mapper.xml b/src/test/resources/sql/mapper/base/test-mapper.xml new file mode 100644 index 0000000..d674130 --- /dev/null +++ b/src/test/resources/sql/mapper/base/test-mapper.xml @@ -0,0 +1,13 @@ + + + + +${sql} + +${sql} + +${sql} + +COMMIT + + \ No newline at end of file diff --git a/src/test/resources/sql/mybatis-config.xml b/src/test/resources/sql/mybatis-config.xml new file mode 100644 index 0000000..44b3157 --- /dev/null +++ b/src/test/resources/sql/mybatis-config.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file