diff --git a/mens-api/src/main/java/kr/xit/ens/support/kakao/service/AsyncKkopayEltrcDocService.java b/mens-api/src/main/java/kr/xit/ens/support/kakao/service/AsyncKkopayEltrcDocService.java index 0cd4386..2fbccb5 100644 --- a/mens-api/src/main/java/kr/xit/ens/support/kakao/service/AsyncKkopayEltrcDocService.java +++ b/mens-api/src/main/java/kr/xit/ens/support/kakao/service/AsyncKkopayEltrcDocService.java @@ -13,7 +13,6 @@ import javax.validation.Validator; import kr.xit.biz.ens.model.kakao.KkopayDocAttrDTO.DocumentBinderUuid; import kr.xit.biz.ens.model.kakao.KkopayDocAttrDTO.Receiver; -import kr.xit.biz.ens.model.kakao.KkopayDocBulkDTO; import kr.xit.biz.ens.model.kakao.KkopayDocBulkDTO.BulkSendRequests; import kr.xit.biz.ens.model.kakao.KkopayDocBulkDTO.BulkSendResponses; import kr.xit.biz.ens.model.kakao.KkopayDocBulkDTO.BulkStatusRequests; @@ -24,6 +23,7 @@ import kr.xit.biz.ens.model.kakao.KkopayDocDTO.SendRequest; import kr.xit.biz.ens.model.kakao.KkopayDocDTO.SendResponse; import kr.xit.biz.ens.model.kakao.KkopayDocDTO.ValidTokenRequest; import kr.xit.biz.ens.model.kakao.KkopayDocDTO.ValidTokenResponse; +import kr.xit.core.spring.util.ApiWebClientUtil; import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpMethod; @@ -33,7 +33,6 @@ import org.springframework.stereotype.Component; import kr.xit.core.exception.BizRuntimeException; import kr.xit.core.model.ApiResponseDTO; import kr.xit.core.spring.annotation.TraceLogging; -import kr.xit.core.spring.util.ApiWebClient; import kr.xit.core.support.utils.Checks; import kr.xit.core.support.utils.JsonUtils; import lombok.RequiredArgsConstructor; @@ -59,22 +58,22 @@ import lombok.extern.slf4j.Slf4j; @Component public class AsyncKkopayEltrcDocService extends EgovAbstractServiceImpl implements IAsyncKkopayEltrcDocService { - @Value("${contract.provider.kakao.host}") + @Value("${contract.kakao.host}") private String HOST; - @Value("#{'${contract.provider.kakao.api.send}'.split(';')}") + @Value("#{'${contract.kakao.api.send}'.split(';')}") private String[] API_SEND; - @Value("#{'${contract.provider.kakao.api.validToken}'.split(';')}") + @Value("#{'${contract.kakao.api.validToken}'.split(';')}") private String[] API_VALID_TOKEN; - @Value("#{'${contract.provider.kakao.api.modifyStatus}'.split(';')}") + @Value("#{'${contract.kakao.api.modifyStatus}'.split(';')}") private String[] API_MODIFY_STATUS; - @Value("#{'${contract.provider.kakao.api.findStatus}'.split(';')}") + @Value("#{'${contract.kakao.api.findStatus}'.split(';')}") private String[] API_STATUS; - @Value("#{'${contract.provider.kakao.api.bulksend}'.split(';')}") + @Value("#{'${contract.kakao.api.bulksend}'.split(';')}") private String[] API_BULKSEND; - @Value("#{'${contract.provider.kakao.api.bulkstatus}'.split(';')}") + @Value("#{'${contract.kakao.api.bulkstatus}'.split(';')}") private String[] API_BULKSTATUS; - private final ApiWebClient webClient; + private final ApiWebClientUtil webClient; private static final Validator validator = Validation.buildDefaultValidatorFactory().getValidator(); private static final CharSequence DOCUMENT_BINDER_UUID = "{document_binder_uuid}"; @@ -111,7 +110,7 @@ public class AsyncKkopayEltrcDocService extends EgovAbstractServiceImpl implemen if(Objects.requireNonNull(errors).size() > 0) throw BizRuntimeException.create(errors.toString()); return CompletableFuture.supplyAsync(() -> - webClient.exchange(HOST + API_SEND[0], HttpMethod.valueOf(API_SEND[1]), JsonUtils.toJson(reqDTO), SendResponse.class)) + webClient.exchangeKko(HOST + API_SEND[0], HttpMethod.valueOf(API_SEND[1]), JsonUtils.toJson(reqDTO), SendResponse.class)) .handle((r, e) -> { if(e != null){ return webClient.sendError(e); @@ -138,7 +137,7 @@ public class AsyncKkopayEltrcDocService extends EgovAbstractServiceImpl implemen .replace("{tokens}", reqDTO.getToken()); return CompletableFuture.supplyAsync(() -> - webClient.exchange(url, HttpMethod.valueOf(API_VALID_TOKEN[1]), null, ValidTokenResponse.class)) + webClient.exchangeKko(url, HttpMethod.valueOf(API_VALID_TOKEN[1]), null, ValidTokenResponse.class)) .handle((r, e) -> { if(e != null){ return webClient.sendError(e); @@ -168,7 +167,7 @@ public class AsyncKkopayEltrcDocService extends EgovAbstractServiceImpl implemen String url = HOST + API_MODIFY_STATUS[0].replace(DOCUMENT_BINDER_UUID, reqDTO.getDocument_binder_uuid()); return CompletableFuture.supplyAsync(() -> - webClient.exchange(url, HttpMethod.valueOf(API_MODIFY_STATUS[1]), body, Void.class)) + webClient.exchangeKko(url, HttpMethod.valueOf(API_MODIFY_STATUS[1]), body, Void.class)) .handle((r, e) -> { if(e != null){ return webClient.sendError(e); @@ -197,7 +196,7 @@ public class AsyncKkopayEltrcDocService extends EgovAbstractServiceImpl implemen String url = HOST + API_STATUS[0].replace(DOCUMENT_BINDER_UUID, reqDTO.getDocument_binder_uuid()); return CompletableFuture.supplyAsync(() -> - webClient.exchange(url, HttpMethod.valueOf(API_STATUS[1]), null, DocStatusResponse.class)) + webClient.exchangeKko(url, HttpMethod.valueOf(API_STATUS[1]), null, DocStatusResponse.class)) .handle((r, e) -> { if(e != null){ return webClient.sendError(e); @@ -219,7 +218,7 @@ public class AsyncKkopayEltrcDocService extends EgovAbstractServiceImpl implemen @Async("asyncExecutor") public CompletableFuture> requestSendBulk(final BulkSendRequests reqDTO) { return CompletableFuture.supplyAsync(() -> - webClient.exchange(HOST + API_BULKSEND[0], HttpMethod.valueOf(API_BULKSEND[1]), JsonUtils.toJson(reqDTO), BulkSendResponses.class)) + webClient.exchangeKko(HOST + API_BULKSEND[0], HttpMethod.valueOf(API_BULKSEND[1]), JsonUtils.toJson(reqDTO), BulkSendResponses.class)) .handle((r, e) -> { if(e != null){ return webClient.sendError(e); @@ -258,7 +257,7 @@ public class AsyncKkopayEltrcDocService extends EgovAbstractServiceImpl implemen } return CompletableFuture.supplyAsync(() -> - webClient.exchange(HOST + API_BULKSTATUS[0], HttpMethod.valueOf(API_BULKSTATUS[1]), JsonUtils.toJson(reqDTO), BulkStatusResponses.class)) + webClient.exchangeKko(HOST + API_BULKSTATUS[0], HttpMethod.valueOf(API_BULKSTATUS[1]), JsonUtils.toJson(reqDTO), BulkStatusResponses.class)) .handle((r, e) -> { if(e != null){ return webClient.sendError(e); diff --git a/mens-api/src/main/java/kr/xit/ens/support/kakao/service/KkopayEltrcDocService.java b/mens-api/src/main/java/kr/xit/ens/support/kakao/service/KkopayEltrcDocService.java index 485bbc0..5ba6f38 100644 --- a/mens-api/src/main/java/kr/xit/ens/support/kakao/service/KkopayEltrcDocService.java +++ b/mens-api/src/main/java/kr/xit/ens/support/kakao/service/KkopayEltrcDocService.java @@ -8,7 +8,6 @@ import java.util.stream.Collectors; import kr.xit.biz.ens.model.kakao.KkopayDocAttrDTO.DocumentBinderUuid; import kr.xit.biz.ens.model.kakao.KkopayDocAttrDTO.Receiver; -import kr.xit.biz.ens.model.kakao.KkopayDocBulkDTO; import kr.xit.biz.ens.model.kakao.KkopayDocBulkDTO.BulkSendReq; import kr.xit.biz.ens.model.kakao.KkopayDocBulkDTO.BulkSendRequests; import kr.xit.biz.ens.model.kakao.KkopayDocBulkDTO.BulkSendResponses; @@ -26,7 +25,7 @@ import kr.xit.core.exception.BizRuntimeException; import kr.xit.core.model.ApiResponseDTO; import kr.xit.core.model.ErrorDTO; import kr.xit.core.spring.annotation.TraceLogging; -import kr.xit.core.spring.util.ApiWebClient; +import kr.xit.core.spring.util.ApiWebClientUtil; import kr.xit.core.support.utils.Checks; import kr.xit.core.support.utils.JsonUtils; @@ -62,22 +61,22 @@ import javax.validation.Validator; @Component public class KkopayEltrcDocService extends EgovAbstractServiceImpl implements IKkopayEltrcDocService { - @Value("${contract.provider.kakao.host}") + @Value("${contract.kakao.host}") private String HOST; - @Value("#{'${contract.provider.kakao.api.send}'.split(';')}") + @Value("#{'${contract.kakao.api.send}'.split(';')}") private String[] API_SEND; - @Value("#{'${contract.provider.kakao.api.validToken}'.split(';')}") + @Value("#{'${contract.kakao.api.validToken}'.split(';')}") private String[] API_VALID_TOKEN; - @Value("#{'${contract.provider.kakao.api.modifyStatus}'.split(';')}") + @Value("#{'${contract.kakao.api.modifyStatus}'.split(';')}") private String[] API_MODIFY_STATUS; - @Value("#{'${contract.provider.kakao.api.findStatus}'.split(';')}") + @Value("#{'${contract.kakao.api.findStatus}'.split(';')}") private String[] API_STATUS; - @Value("#{'${contract.provider.kakao.api.bulksend}'.split(';')}") + @Value("#{'${contract.kakao.api.bulksend}'.split(';')}") private String[] API_BULKSEND; - @Value("#{'${contract.provider.kakao.api.bulkstatus}'.split(';')}") + @Value("#{'${contract.kakao.api.bulkstatus}'.split(';')}") private String[] API_BULKSTATUS; - private final ApiWebClient webClient; + private final ApiWebClientUtil webClient; private static final Validator validator = Validation.buildDefaultValidatorFactory().getValidator(); private static final CharSequence DOCUMENT_BINDER_UUID = "{document_binder_uuid}"; @@ -111,7 +110,7 @@ public class KkopayEltrcDocService extends EgovAbstractServiceImpl implements IK if(Checks.isEmpty(receiver.getBirthday())) Objects.requireNonNull(errors).add("receiver.birthday=받는이 생년월일은 필수입니다."); } if(Objects.requireNonNull(errors).size() > 0) throw BizRuntimeException.create(errors.toString()); - return webClient.exchange(HOST + API_SEND[0], HttpMethod.valueOf(API_SEND[1]), JsonUtils.toJson(reqDTO), SendResponse.class); + return webClient.exchangeKko(HOST + API_SEND[0], HttpMethod.valueOf(API_SEND[1]), JsonUtils.toJson(reqDTO), SendResponse.class); } /** @@ -129,7 +128,7 @@ public class KkopayEltrcDocService extends EgovAbstractServiceImpl implements IK String url = HOST + API_VALID_TOKEN[0].replace(DOCUMENT_BINDER_UUID, reqDTO.getDocument_binder_uuid()) .replace("{tokens}", reqDTO.getToken()); - return webClient.exchange(url, HttpMethod.valueOf(API_VALID_TOKEN[1]), null, ValidTokenResponse.class); + return webClient.exchangeKko(url, HttpMethod.valueOf(API_VALID_TOKEN[1]), null, ValidTokenResponse.class); } /** @@ -150,7 +149,7 @@ public class KkopayEltrcDocService extends EgovAbstractServiceImpl implements IK String body = "{\"document\": {\"is_detail_read\": true} }"; String url = HOST + API_MODIFY_STATUS[0].replace(DOCUMENT_BINDER_UUID, reqDTO.getDocument_binder_uuid()); - webClient.exchange(url, HttpMethod.valueOf(API_MODIFY_STATUS[1]), body, Void.class); + webClient.exchangeKko(url, HttpMethod.valueOf(API_MODIFY_STATUS[1]), body, Void.class); } /** @@ -171,7 +170,7 @@ public class KkopayEltrcDocService extends EgovAbstractServiceImpl implements IK validate(reqDTO, null); String url = HOST + API_STATUS[0].replace(DOCUMENT_BINDER_UUID, reqDTO.getDocument_binder_uuid()); - return webClient.exchange(url, HttpMethod.valueOf(API_STATUS[1]), null, DocStatusResponse.class); + return webClient.exchangeKko(url, HttpMethod.valueOf(API_STATUS[1]), null, DocStatusResponse.class); } /** @@ -229,7 +228,7 @@ public class KkopayEltrcDocService extends EgovAbstractServiceImpl implements IK throw BizRuntimeException.create(errors.toString()); } - return webClient.exchange(HOST + API_BULKSEND[0], HttpMethod.valueOf(API_BULKSEND[1]), JsonUtils.toJson(reqDTO), BulkSendResponses.class); + return webClient.exchangeKko(HOST + API_BULKSEND[0], HttpMethod.valueOf(API_BULKSEND[1]), JsonUtils.toJson(reqDTO), BulkSendResponses.class); } /** @@ -259,13 +258,9 @@ public class KkopayEltrcDocService extends EgovAbstractServiceImpl implements IK if(errors.size() > 0) { throw BizRuntimeException.create(errors.toString()); } - return webClient.exchange(HOST + API_BULKSTATUS[0], HttpMethod.valueOf(API_BULKSTATUS[1]), JsonUtils.toJson(reqDTO), BulkStatusResponses.class); + return webClient.exchangeKko(HOST + API_BULKSTATUS[0], HttpMethod.valueOf(API_BULKSTATUS[1]), JsonUtils.toJson(reqDTO), BulkStatusResponses.class); } - - - - @Override public ApiResponseDTO findMyDocReadyAndMblPage(OneTimeToken reqDTO) { @@ -273,7 +268,7 @@ public class KkopayEltrcDocService extends EgovAbstractServiceImpl implements IK .replace("{tokens}", reqDTO.getToken()); // 유효성 검증 - ValidTokenResponse validTokenRes = webClient.exchange(url, HttpMethod.valueOf(API_VALID_TOKEN[1]), null, + ValidTokenResponse validTokenRes = webClient.exchangeKko(url, HttpMethod.valueOf(API_VALID_TOKEN[1]), null, ValidTokenResponse.class); if(!"USED".equals(validTokenRes.getToken_status())){ @@ -286,7 +281,7 @@ public class KkopayEltrcDocService extends EgovAbstractServiceImpl implements IK // 정상 : HttpStatus.NO_CONTENT(204) return // error : body에 error_code, error_message return - ErrorDTO errorDTO = webClient.exchange(url2, HttpMethod.valueOf(API_MODIFY_STATUS[1]), body, ErrorDTO.class); + ErrorDTO errorDTO = webClient.exchangeKko(url2, HttpMethod.valueOf(API_MODIFY_STATUS[1]), body, ErrorDTO.class); if(errorDTO != null){ return ApiResponseDTO.error(errorDTO.getErrorCode(), errorDTO.getErrorMessage()); } diff --git a/mens-api/src/main/java/kr/xit/ens/support/kakao/web/KkopayEltrcDocController.java b/mens-api/src/main/java/kr/xit/ens/support/kakao/web/KkopayEltrcDocController.java index b1ca232..1a9de67 100644 --- a/mens-api/src/main/java/kr/xit/ens/support/kakao/web/KkopayEltrcDocController.java +++ b/mens-api/src/main/java/kr/xit/ens/support/kakao/web/KkopayEltrcDocController.java @@ -39,7 +39,7 @@ import lombok.extern.slf4j.Slf4j; @RestController @RequestMapping(value = "/api/kakaopay/v1") public class KkopayEltrcDocController { - @Value("${contract.provider.kakao.token}") + @Value("${contract.kakao.token}") private String accessToken; private final IKkopayEltrcDocService service; diff --git a/mens-api/src/main/resources/config/application-ens.yml b/mens-api/src/main/resources/config/application-ens.yml index c444fdb..47ddce3 100644 --- a/mens-api/src/main/resources/config/application-ens.yml +++ b/mens-api/src/main/resources/config/application-ens.yml @@ -2,26 +2,36 @@ # application 설정 #----------------------------------------------------------------------- contract: - provider: - # milisecond - connection: - timeout: 30000 - readTimeout: 30000 - thread: - # 동시 실행 스레드 개수 - corePoolSize: 5 - # 스레드 풀에서 사용할 수 있는 최대 개수 - maxPoolSize: 10 - kakao: - bulk-max-cnt: 10 - host: https://docs-gw.kakaopay.com - #host: https://dummy.restapiexample.com - token: dd394da7f66211eb9cbe46e139ceffc2 - uuid: CON-41ef0535f67211ebbdedd2e6ed332381 - api: - send: /v1/documents;POST - validToken: /v1/{document_binder_uuid}/tokens/{tokens};GET - modifyStatus: /v1/documents/{document_binder_uuid};POST - findStatus: /v1/documents/{document_binder_uuid}/status;GET - bulksend: /v1/documents/bulk;POST - bulkstatus: /v1/documents/bulk/status;POST + # milisecond + connection: + timeout: 30000 + readTimeout: 30000 + thread: + # 동시 실행 스레드 개수 + corePoolSize: 5 + # 스레드 풀에서 사용할 수 있는 최대 개수 + maxPoolSize: 10 + kakao: + bulk-max-cnt: 10 + host: https://docs-gw.kakaopay.com + #host: https://dummy.restapiexample.com + token: dd394da7f66211eb9cbe46e139ceffc2 + uuid: CON-41ef0535f67211ebbdedd2e6ed332381 + api: + send: /v1/documents;POST + validToken: /v1/{document_binder_uuid}/tokens/{tokens};GET + modifyStatus: /v1/documents/{document_binder_uuid};POST + findStatus: /v1/documents/{document_binder_uuid}/status;GET + bulksend: /v1/documents/bulk;POST + bulkstatus: /v1/documents/bulk/status;POST + nice: + #host: http://parking.cheonan.go.kr + host: https://svc.niceapi.co.kr:22001 + client-id: "6c3eb1ff-530d-458a-9a6e-e02e3346f679" + client-secret: "960f204ec45bb312b7ad2d6b54b984d9c353b8" + api: + generate-token: /digital/niceid/oauth/oauth/token + revoke-token: /digital/niceid/oauth/oauth/token/revokeById + publickey: /digital/niceid/api/v1.0/common/crypto/publickey + symmetrickey: /digital/niceid/api/v1.0/common/crypto/symmetrickey + ci: /digital/niceid/cert/v1.0/ipin/addinfo/ci diff --git a/mens-batch/src/main/java/kr/xit/biz/ens/service/EnsBatchService.java b/mens-batch/src/main/java/kr/xit/biz/ens/service/EnsBatchService.java index 41af809..2ae6160 100644 --- a/mens-batch/src/main/java/kr/xit/biz/ens/service/EnsBatchService.java +++ b/mens-batch/src/main/java/kr/xit/biz/ens/service/EnsBatchService.java @@ -2,7 +2,6 @@ package kr.xit.biz.ens.service; import java.io.*; import java.util.*; -import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; import egovframework.com.cmm.util.EgovDateUtil; @@ -17,7 +16,7 @@ import kr.xit.biz.ens.model.kakao.KkopayDocBulkDTO.BulkStatusRequests; import kr.xit.biz.ens.model.kakao.KkopayDocBulkDTO.BulkStatusResponses; import kr.xit.biz.ens.model.kakao.KkopayDocBulkDTO.PropertyBulk; import kr.xit.biz.sms.service.ISmsMessageService; -import kr.xit.core.spring.util.ApiWebClient; +import kr.xit.core.spring.util.ApiWebClientUtil; import kr.xit.core.support.utils.DateUtils; import kr.xit.core.support.utils.JsonUtils; import org.apache.commons.collections4.ListUtils; @@ -62,14 +61,14 @@ import javax.validation.Validator; @RequiredArgsConstructor @Service public class EnsBatchService extends EgovAbstractServiceImpl implements IEnsBatchService { - @Value("${contract.provider.kakao.host}") + @Value("${contract.kakao.host}") private String apiHost; - @Value("${contract.provider.kakao.api.bulksend}") + @Value("${contract.kakao.api.bulksend}") private String apiBulkSend; - @Value("${contract.provider.kakao.api.bulkstatus}") + @Value("${contract.kakao.api.bulkstatus}") private String apiBulkStatus; - private final ApiWebClient apiWebClient; + private final ApiWebClientUtil apiWebClient; private final IEnsBatchMapper mapper; private final EgovPasswordEncoder encryptor; private final ISmsMessageService smsService; @@ -77,7 +76,7 @@ public class EnsBatchService extends EgovAbstractServiceImpl implements IEnsBatc private static final Validator validator = Validation.buildDefaultValidatorFactory() .getValidator(); - @Value("${contract.provider.kakao.bulk-max-cnt}") + @Value("${contract.kakao.bulk-max-cnt}") private int bulkMaxCnt; @Value("${file.cmm.upload.root}") @@ -463,7 +462,7 @@ public class EnsBatchService extends EgovAbstractServiceImpl implements IEnsBatc List> apiResults = partitions.stream() .map(bulkSendList -> ApiResponseDTO.success( - apiWebClient.exchange( + apiWebClient.exchangeKko( url.toString(), HttpMethod.POST, JsonUtils.toJson(BulkSendRequests.builder() @@ -862,7 +861,7 @@ public class EnsBatchService extends EgovAbstractServiceImpl implements IEnsBatc List> apiResults = partitions.stream() .map(uuids -> ApiResponseDTO.success( - apiWebClient.exchange( + apiWebClient.exchangeKko( url.toString(), HttpMethod.POST, JsonUtils.toJson(BulkStatusRequests.builder() diff --git a/mens-batch/src/main/java/kr/xit/biz/ens/web/ApiCallTestController.java b/mens-batch/src/main/java/kr/xit/biz/ens/web/ApiCallTestController.java index 255ef50..42fc56f 100644 --- a/mens-batch/src/main/java/kr/xit/biz/ens/web/ApiCallTestController.java +++ b/mens-batch/src/main/java/kr/xit/biz/ens/web/ApiCallTestController.java @@ -4,15 +4,12 @@ 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 java.util.Map; import kr.xit.biz.ens.model.kakao.KkopayDocBulkDTO.BulkSendRequests; -import kr.xit.biz.ens.model.kakao.KkopayDocBulkDTO.BulkSendResponses; import kr.xit.biz.ens.model.kakao.KkopayDocBulkDTO.BulkStatusRequests; import kr.xit.biz.ens.model.kakao.KkopayDocDTO.SendRequest; -import kr.xit.biz.ens.model.kakao.KkopayDocDTO.SendResponse; import kr.xit.biz.ens.service.IEnsBatchService; import kr.xit.core.model.ApiResponseDTO; -import kr.xit.core.spring.util.ApiWebClient; +import kr.xit.core.spring.util.ApiWebClientUtil; import kr.xit.core.support.utils.JsonUtils; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; @@ -43,14 +40,14 @@ import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping(value = "/batch/ens/test/v1") public class ApiCallTestController { - @Value("${contract.provider.kakao.host}") + @Value("${contract.kakao.host}") private String apiHost; - @Value("${contract.provider.kakao.api.bulksend}") + @Value("${contract.kakao.api.bulksend}") private String apiBulkSend; - @Value("${contract.provider.kakao.api.bulkstatus}") + @Value("${contract.kakao.api.bulkstatus}") private String apiBulkStatus; - private final ApiWebClient apiWebClient; + private final ApiWebClientUtil apiWebClient; private static final String SNDNG_PROCESS_STTUS = "sndngProcessSttus"; private final IEnsBatchService service; @@ -102,7 +99,7 @@ public class ApiCallTestController { .append("/api/kakaopay/v1/documents"); return - apiWebClient.exchange(url.toString(), + apiWebClient.exchangeKko(url.toString(), HttpMethod.POST, JsonUtils.toJson(reqDTO), ApiResponseDTO.class); @@ -156,7 +153,7 @@ public class ApiCallTestController { ) { final String url = apiHost + apiBulkSend; - return apiWebClient.exchange( + return apiWebClient.exchangeKko( url, HttpMethod.POST, JsonUtils.toJson(reqDTO), @@ -190,7 +187,7 @@ public class ApiCallTestController { ) { final String url = apiHost + apiBulkStatus;; - return apiWebClient.exchange( + return apiWebClient.exchangeKko( url, HttpMethod.POST, JsonUtils.toJson(reqDTO), diff --git a/mens-core/src/main/java/kr/xit/biz/common/ApiConstants.java b/mens-core/src/main/java/kr/xit/biz/common/ApiConstants.java index b8c9c48..e24c981 100644 --- a/mens-core/src/main/java/kr/xit/biz/common/ApiConstants.java +++ b/mens-core/src/main/java/kr/xit/biz/common/ApiConstants.java @@ -6,12 +6,12 @@ package kr.xit.biz.common; * * packageName : kr.xit.ens.support.common * fileName : KakaoConstants - * author : xitdev + * author : limju * date : 2023-05-04 * ====================================================================== * 변경일 변경자 변경 내용 * ---------------------------------------------------------------------- - * 2023-05-04 xitdev 최초 생성 + * 2023-05-04 limju 최초 생성 * * */ diff --git a/mens-core/src/main/java/kr/xit/biz/ens/model/kakao/KkopayDocAttrDTO.java b/mens-core/src/main/java/kr/xit/biz/ens/model/kakao/KkopayDocAttrDTO.java index b7ee3ab..0cb4f61 100644 --- a/mens-core/src/main/java/kr/xit/biz/ens/model/kakao/KkopayDocAttrDTO.java +++ b/mens-core/src/main/java/kr/xit/biz/ens/model/kakao/KkopayDocAttrDTO.java @@ -19,12 +19,12 @@ import lombok.experimental.SuperBuilder; * * packageName : kr.xit.biz.ens.model.kakao * fileName : KkopayDocAttrDTO - * author : xitdev + * author : limju * date : 2023-05-03 * ====================================================================== * 변경일 변경자 변경 내용 * ---------------------------------------------------------------------- - * 2023-05-03 xitdev 최초 생성 + * 2023-05-03 limju 최초 생성 * * */ diff --git a/mens-core/src/main/java/kr/xit/biz/ens/model/kakao/KkopayDocDTO.java b/mens-core/src/main/java/kr/xit/biz/ens/model/kakao/KkopayDocDTO.java index 24c89de..1c6eaed 100644 --- a/mens-core/src/main/java/kr/xit/biz/ens/model/kakao/KkopayDocDTO.java +++ b/mens-core/src/main/java/kr/xit/biz/ens/model/kakao/KkopayDocDTO.java @@ -20,12 +20,12 @@ import org.hibernate.validator.constraints.Length; * * packageName : kr.xit.ens.model.kakao * fileName : KkopayDocDTO - * author : xitdev + * author : limju * date : 2023-05-03 * ====================================================================== * 변경일 변경자 변경 내용 * ---------------------------------------------------------------------- - * 2023-05-03 xitdev 최초 생성 + * 2023-05-03 limju 최초 생성 * * */ diff --git a/mens-core/src/main/java/kr/xit/core/consts/Constants.java b/mens-core/src/main/java/kr/xit/core/consts/Constants.java index da1a9ac..b959db1 100644 --- a/mens-core/src/main/java/kr/xit/core/consts/Constants.java +++ b/mens-core/src/main/java/kr/xit/core/consts/Constants.java @@ -1,6 +1,7 @@ package kr.xit.core.consts; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; +import org.springframework.http.HttpHeaders; /** *
@@ -102,7 +103,7 @@ public class Constants {
      * 카카오페이 전자문서 요청 헤더 필드명
      */
     public enum HeaderName {
-        TOKEN("Authorization"),	 //Token
+        TOKEN(HttpHeaders.AUTHORIZATION),	 //Token
         UUID("Contract-Uuid"),   //Contract-Uuid
         ;     // TOKEN
 
diff --git a/mens-core/src/main/java/kr/xit/core/spring/config/AsyncExecutorConfig.java b/mens-core/src/main/java/kr/xit/core/spring/config/AsyncExecutorConfig.java
index c335d3a..12c9b96 100644
--- a/mens-core/src/main/java/kr/xit/core/spring/config/AsyncExecutorConfig.java
+++ b/mens-core/src/main/java/kr/xit/core/spring/config/AsyncExecutorConfig.java
@@ -35,10 +35,10 @@ import kr.xit.core.spring.config.support.CustomAsyncExceptionHandler;
 @EnableAsync
 public class AsyncExecutorConfig extends AsyncConfigurerSupport {
 
-    @Value("${contract.provider.connection.thread.corePoolSize:5}")
+    @Value("${contract.connection.thread.corePoolSize:5}")
     private int corePoolSize;
 
-    @Value("${contract.provider.connection.thread.maxPoolSize:10}")
+    @Value("${contract.connection.thread.maxPoolSize:10}")
     private int maxPoolSize;
 
     /**
diff --git a/mens-core/src/main/java/kr/xit/core/spring/config/support/PropertiesConfig.java b/mens-core/src/main/java/kr/xit/core/spring/config/support/PropertiesConfig.java
index e562cd9..ff55d4a 100644
--- a/mens-core/src/main/java/kr/xit/core/spring/config/support/PropertiesConfig.java
+++ b/mens-core/src/main/java/kr/xit/core/spring/config/support/PropertiesConfig.java
@@ -17,12 +17,12 @@ import lombok.extern.slf4j.Slf4j;
  *
  * packageName : kr.xit.core.spring.config.support
  * fileName    : PropertiesConfig
- * author      : xitdev
+ * author      : limju
  * date        : 2023-05-01
  * ======================================================================
  * 변경일         변경자        변경 내용
  * ----------------------------------------------------------------------
- * 2023-05-01    xitdev       최초 생성
+ * 2023-05-01    limju       최초 생성
  *
  * 
*/ diff --git a/mens-core/src/main/java/kr/xit/core/spring/config/support/WebClientConfig.java b/mens-core/src/main/java/kr/xit/core/spring/config/support/WebClientConfig.java new file mode 100644 index 0000000..e6ad12a --- /dev/null +++ b/mens-core/src/main/java/kr/xit/core/spring/config/support/WebClientConfig.java @@ -0,0 +1,138 @@ +package kr.xit.core.spring.config.support; + +import io.netty.channel.ChannelOption; +import io.netty.handler.timeout.ReadTimeoutHandler; +import io.netty.handler.timeout.WriteTimeoutHandler; +import java.time.Duration; +import java.util.concurrent.TimeUnit; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.client.reactive.ReactorClientHttpConnector; +import org.springframework.http.codec.LoggingCodecSupport; +import org.springframework.web.reactive.function.client.ExchangeFilterFunction; +import org.springframework.web.reactive.function.client.ExchangeStrategies; +import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.web.util.DefaultUriBuilderFactory; +import reactor.core.publisher.Mono; +import reactor.netty.http.client.HttpClient; +import reactor.netty.resources.ConnectionProvider; + +/** + *
+ * description : WebClient configuration
+ *
+ * packageName : kr.xit.core.spring.config.support
+ * fileName    : WebClientConfig
+ * author      : julim
+ * date        : 2023-09-06
+ * ======================================================================
+ * 변경일         변경자        변경 내용
+ * ----------------------------------------------------------------------
+ * 2023-09-06    julim       최초 생성
+ *
+ * 
+ */ +@Slf4j +@Configuration +public class WebClientConfig { + + @Value("${contract.connection.timeout:5000}") + private int connectTimeout; + @Value("${contract.connection.readTimeout:5000}") + private int readTimeout; + + DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(); + + // HttpClient 총 연결 시간 + HttpClient httpClient = HttpClient.create() + .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, connectTimeout) + .responseTimeout(Duration.ofMillis(this.connectTimeout)) + .doOnConnected(conn -> + conn.addHandlerLast(new ReadTimeoutHandler(readTimeout, TimeUnit.MILLISECONDS)) + .addHandlerLast(new WriteTimeoutHandler(readTimeout, TimeUnit.MILLISECONDS))); + + + /** + * setEncodingMode : GET 요청의 파라미터 셋팅을 하기 위한 URI 템플릿의 인코딩을 위한 설정 + * @return + */ + @Bean + public WebClient webClient() { + // 256KB 보다 큰 HTTP 메시지를 처리 시도 → DataBufferLimitException 에러 발생 방어 + ExchangeStrategies es = ExchangeStrategies.builder() + .codecs(configurer -> { + configurer.defaultCodecs().maxInMemorySize(2 * 1024 * 1024); + //configurer.customCodecs().register(new Jackson2JsonDecoder()); + //configurer.customCodecs().register(new Jackson2JsonEncoder()); + }) + .build(); + + //FIXME::rest call async 로깅 + // ExchangeStrategies를 통해 setEnableLoggingRequestDetails(true)로 설정 + // boot에서 로깅 org.springframework.web.reactive.function.client.ExchangeFunctions: DEBUG 하여 활성 + es.messageWriters() + .stream() + .filter(LoggingCodecSupport .class::isInstance) + .forEach(writer -> ((LoggingCodecSupport)writer).setEnableLoggingRequestDetails(true)); + + + + factory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.VALUES_ONLY); + return WebClient.builder() + .uriBuilderFactory(factory) + .clientConnector(new ReactorClientHttpConnector(httpClient)) + .codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(2 * 1024 * 1024)) + .exchangeStrategies(es) + .filters(exchangeFilterFunctions -> { + exchangeFilterFunctions.add(logRequest()); + exchangeFilterFunctions.add(logResponse()); + //TODO::에러발생시 점검필요 + //exchangeFilterFunctions.add(errorHandler()); + }) + .build(); + } + + /** + * maxConnections : connection pool의 갯수 + * pendingAcquireTimeout : 커넥션 풀에서 커넥션을 얻기 위해 기다리는 최대 시간 + * pendingAcquireMaxCount : 커넥션 풀에서 커넥션을 가져오는 시도 횟수 (-1: no limit) + * maxIdleTime : 커넥션 풀에서 idle 상태의 커넥션을 유지하는 시간 + * @return + */ + @Bean + public ConnectionProvider connectionProvider() { + return ConnectionProvider.builder("http-pool") + .maxConnections(100) + .pendingAcquireTimeout(Duration.ofMillis(0)) + .pendingAcquireMaxCount(-1) + .maxIdleTime(Duration.ofMillis(1000L)) + .build(); + } + + + private ExchangeFilterFunction logRequest() { + return ExchangeFilterFunction.ofRequestProcessor(clientRequest -> { + if (log.isDebugEnabled()) { + StringBuilder sb = new StringBuilder("\n>>>>>>>>>> Http Rest Request <<<<<<<<<<<<<\n"); + clientRequest + .headers() + .forEach((name, values) -> values.forEach(value -> sb.append(name).append(": ").append(value).append("\n"))); + log.debug(sb.toString()); + } + return Mono.just(clientRequest); + }); + } + + private ExchangeFilterFunction logResponse() { + return ExchangeFilterFunction.ofResponseProcessor(clientResponse -> { + StringBuilder sb = new StringBuilder("\n>>>>>>>>>> Http Rest Response <<<<<<<<<<<<<\n"); + clientResponse.headers() + .asHttpHeaders() + .forEach((name, values) -> values.forEach(value -> sb.append(name).append(": ").append(value).append("\n"))); + log.debug(sb.toString()); + return Mono.just(clientResponse); + }); + } +} diff --git a/mens-core/src/main/java/kr/xit/core/spring/util/ApiWebClient.java b/mens-core/src/main/java/kr/xit/core/spring/util/ApiWebClient.java deleted file mode 100644 index ed86c39..0000000 --- a/mens-core/src/main/java/kr/xit/core/spring/util/ApiWebClient.java +++ /dev/null @@ -1,262 +0,0 @@ -package kr.xit.core.spring.util; - -import java.time.Duration; -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; - -import org.apache.commons.lang3.StringUtils; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatus; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.client.reactive.ReactorClientHttpConnector; -import org.springframework.http.codec.LoggingCodecSupport; -import org.springframework.stereotype.Component; -import org.springframework.web.reactive.function.client.ExchangeFilterFunction; -import org.springframework.web.reactive.function.client.ExchangeStrategies; -import org.springframework.web.reactive.function.client.WebClient; -import org.springframework.web.reactive.function.client.WebClientRequestException; - -import io.netty.channel.ChannelOption; -import io.netty.channel.ConnectTimeoutException; -import io.netty.handler.timeout.ReadTimeoutException; -import io.netty.handler.timeout.ReadTimeoutHandler; -import io.netty.handler.timeout.WriteTimeoutHandler; -import kr.xit.core.consts.Constants; -import kr.xit.core.exception.BizRuntimeException; -import kr.xit.core.model.ApiResponseDTO; -import kr.xit.core.model.ErrorDTO; -import kr.xit.core.spring.util.error.ClientError; -import kr.xit.core.spring.util.error.ErrorParse; -import kr.xit.core.spring.util.error.ServerError; -import kr.xit.core.support.utils.Checks; -import kr.xit.core.support.utils.JsonUtils; -import lombok.extern.slf4j.Slf4j; -import reactor.core.publisher.Mono; -import reactor.netty.http.client.HttpClient; - -/** - *
- * description : react Restfull Util
- *
- * packageName : kr.xit.core.spring.util
- * fileName    : ApiWebClient
- * author      : julim
- * date        : 2023-04-28
- * ======================================================================
- * 변경일         변경자        변경 내용
- * ----------------------------------------------------------------------
- * 2023-04-28    julim       최초 생성
- *
- * 
- * @see kr.xit.core.spring.config.AsyncExecutorConfig - * @see ClientError - * @see ServerError - */ -@Slf4j -@Component -public class ApiWebClient { - private final WebClient webClient; - - - public ApiWebClient( - @Value("${contract.provider.kakao.token:}") - String accessToken, - @Value("${contract.provider.kakao.uuid:}") - String contractUuid, - @Value("${contract.provider.connection.timeout:5000}") - int connectionTimeout, - @Value("${contract.provider.connection.readTimeout:5000}") - int readTimeout - ) { - ExchangeStrategies es = ExchangeStrategies.builder() - .codecs(configurer -> { - configurer.defaultCodecs().maxInMemorySize(2 * 1024 * 1024); - //configurer.customCodecs().register(new Jackson2JsonDecoder()); - //configurer.customCodecs().register(new Jackson2JsonEncoder()); - }) - .build(); - - //FIXME::rest call async 로깅 - // ExchangeStrategies를 통해 setEnableLoggingRequestDetails(true)로 설정 - // boot에서 로깅 org.springframework.web.reactive.function.client.ExchangeFunctions: DEBUG 하여 활성 - es.messageWriters() - .stream() - .filter(LoggingCodecSupport.class::isInstance) - .forEach(writer -> ((LoggingCodecSupport)writer).setEnableLoggingRequestDetails(true)); - - - this.webClient = WebClient.builder() - .clientConnector(httpClient(connectionTimeout, readTimeout)) - .baseUrl("http://localhost:8081") // (1) 외부 API Base URl - .defaultHeaders((headers)->{ - headers.setContentType(new MediaType(MediaType.APPLICATION_JSON, Constants.CHARSET_UTF8)); - headers.set(Constants.HeaderName.TOKEN.getCode(), String.format("%s %s", Constants.JwtToken.GRANT_TYPE.getCode(), accessToken)); - headers.set(Constants.HeaderName.UUID.getCode(), contractUuid); - - }) - .exchangeStrategies(es) - .filters(exchangeFilterFunctions -> { - exchangeFilterFunctions.add(logRequest()); - exchangeFilterFunctions.add(logResponse()); - //TODO::에러발생시 점검필요 - //exchangeFilterFunctions.add(errorHandler()); - }) - .build(); - } - - //TODO:: ApiResponseDTO로 return 하도록 해야할 듯 - // CompletableFuture.supplyAsync().handle() / exceptionally() 사용을 위해 - /** - *
-     * Async call - Response Entity(상태정보등) 가 필요한 경우
-     * @param url call url
-     * @param method POST|GET
-     * @param body JSON String type
-     * @param rtnClzz rtnClzz return type class
-     *        (ex: new KkopayDocDTO.DocStatusResponse().getClass())
-     * @return T rtnClzz return DTO
-     * 
- */ - public T exchange(String url, HttpMethod method, Object body, Class rtnClzz) { - - return webClient.method(method) - .uri(url) - .bodyValue(Objects.requireNonNullElse(body, "")) - .exchangeToMono(res -> res.bodyToMono(rtnClzz)) - .block(); - } - - public T exchange2(String url, HttpMethod method, Object body, Class rtnClzz) { - - return webClient.method(method) - .uri(url) - - .bodyValue(Objects.requireNonNullElse(body, "")) - .exchangeToMono(res -> res.bodyToMono(rtnClzz)) - - .block(); - } - - public ApiResponseDTO sendError(Throwable e) { - - Map map = ErrorParse.extractError(e.getCause()); - return ApiResponseDTO.error(String.valueOf(map.get("code")), String.valueOf(map.get("message")), (HttpStatus)map.get("httpStatus")); - } - - - /** - *
-     * Async call - body 만 필요한 경우
-     * @param url call url
-     * @param method POST|GET
-     * @param body JSON String type
-     * @param rtnClzz rtnClzz return type class
-     *        (ex: new KkopayDocDTO.DocStatusResponse().getClass())
-     * @return T rtnClzz return DTO
-     * 
- */ - public T retrive(String url, HttpMethod method, Object body, Class rtnClzz) { - - return webClient.mutate() - .build() - .method(method) - .uri(url) - .bodyValue(Objects.requireNonNullElse(body, "")) - .retrieve() - .onStatus( - status -> status.is4xxClientError() || status.is5xxServerError(), - res -> res.bodyToMono(String.class).map(BizRuntimeException::create)) - .bodyToMono(rtnClzz) - .block(); - - } - - - - - private ReactorClientHttpConnector httpClient(int connectTimeout, int readTimeout){ - return new ReactorClientHttpConnector( - HttpClient.create() - .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, connectTimeout) - .responseTimeout(Duration.ofMillis(connectTimeout)) - .doOnConnected(conn -> - conn.addHandlerLast(new ReadTimeoutHandler(readTimeout, TimeUnit.MILLISECONDS)) - .addHandlerLast(new WriteTimeoutHandler(readTimeout, TimeUnit.MILLISECONDS))) - ); - } - - - ExchangeFilterFunction logRequest() { - return ExchangeFilterFunction.ofRequestProcessor(clientRequest -> { - if (log.isDebugEnabled()) { - StringBuilder sb = new StringBuilder("\n>>>>>>>>>> Http Rest Request <<<<<<<<<<<<<\n"); - clientRequest - .headers() - .forEach((name, values) -> values.forEach(value -> sb.append(name).append(": ").append(value).append("\n"))); - log.debug(sb.toString()); - } - return Mono.just(clientRequest); - }); - } - - ExchangeFilterFunction logResponse() { - return ExchangeFilterFunction.ofResponseProcessor(clientResponse -> { - StringBuilder sb = new StringBuilder("\n>>>>>>>>>> Http Rest Response <<<<<<<<<<<<<\n"); - clientResponse.headers() - .asHttpHeaders() - .forEach((name, values) -> values.forEach(value -> sb.append(name).append(": ").append(value).append("\n"))); - log.debug(sb.toString()); - return Mono.just(clientResponse); - }); - } - - ExchangeFilterFunction errorHandler() { - return ExchangeFilterFunction.ofResponseProcessor(clientResponse -> { - HttpStatus status = clientResponse.statusCode(); - - if (clientResponse.statusCode().is4xxClientError()) { - return clientResponse.bodyToMono(String.class) - .flatMap(errorBody -> Mono.error(new ClientError(status, errorBody))); - - } else if (clientResponse.statusCode().is5xxServerError()) { - return clientResponse.bodyToMono(String.class) - .flatMap(errorBody -> Mono.error(new ServerError(status, errorBody))); - - } - return Mono.just(clientResponse); - }); - } - - - public T exchange3(String url, HttpMethod method, Object body, Class rtnClzz) { - CountDownLatch cdl = new CountDownLatch(1); - AtomicReference result = new AtomicReference<>(); - - webClient.mutate() - .build() - .method(method) - .uri(url) - .bodyValue(body) - .exchangeToMono(res -> res.bodyToMono(rtnClzz)) - .onErrorContinue((e, i) -> { - log.error("{}", e); - }) - .doOnTerminate(() -> cdl.countDown()) - .subscribe(data -> result.set(data)); - try { - cdl.await(); - } catch (InterruptedException e) { - // thread pool에 에러상태 set - Thread.currentThread().interrupt(); - throw new RuntimeException(e); - } - return result.get(); - } - -} diff --git a/mens-core/src/main/java/kr/xit/core/spring/util/ApiWebClientUtil.java b/mens-core/src/main/java/kr/xit/core/spring/util/ApiWebClientUtil.java new file mode 100644 index 0000000..5ceb62a --- /dev/null +++ b/mens-core/src/main/java/kr/xit/core/spring/util/ApiWebClientUtil.java @@ -0,0 +1,145 @@ +package kr.xit.core.spring.util; + +import java.net.URI; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import kr.xit.core.consts.Constants; +import kr.xit.core.exception.BizRuntimeException; +import kr.xit.core.model.ApiResponseDTO; +import kr.xit.core.spring.config.support.WebClientConfig; +import kr.xit.core.spring.util.error.ClientError; +import kr.xit.core.spring.util.error.ErrorParse; +import kr.xit.core.spring.util.error.ServerError; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Component; +import org.springframework.web.reactive.function.client.ExchangeFilterFunction; +import org.springframework.web.util.UriComponentsBuilder; +import reactor.core.publisher.Mono; + +/** + *
+ * description : react Restfull Util
+ *
+ * packageName : kr.xit.core.spring.util
+ * fileName    : ApiWebClientUtil
+ * author      : julim
+ * date        : 2023-09-06
+ * ======================================================================
+ * 변경일         변경자        변경 내용
+ * ----------------------------------------------------------------------
+ * 2023-09-06    julim       최초 생성
+ *
+ * 
+ * @see kr.xit.core.spring.config.AsyncExecutorConfig + * @see ClientError + * @see ServerError + */ +@Component +@RequiredArgsConstructor +public class ApiWebClientUtil { + @Value("${contract.kakao.token:}") + private String kkoAccessToken; + @Value("${contract.kakao.uuid:}") + private String kkoContractUuid; + + private final WebClientConfig webClientConfig; + + public T get(final String url, final Class responseDtoClass, Map headerMap) { + return webClientConfig.webClient().method(HttpMethod.GET) + .uri(url) + .headers(httpHeaders -> getHeaders(httpHeaders, headerMap)) + .retrieve() + .onStatus( + status -> status.is4xxClientError() || status.is5xxServerError(), + res -> res.bodyToMono(String.class).map(BizRuntimeException::create)) + .bodyToMono(responseDtoClass) + .block(); + } + + public T post(final String url, final V requestDto, final Class responseDtoClass, Map headerMap) { + return webClientConfig.webClient().method(HttpMethod.POST) + .uri(url) + .headers(httpHeaders -> getHeaders(httpHeaders, headerMap)) + .bodyValue(requestDto) + .retrieve() + .onStatus( + status -> status.is4xxClientError() || status.is5xxServerError(), + res -> res.bodyToMono(String.class).map(BizRuntimeException::create)) + .bodyToMono(responseDtoClass) + .block(); + } + + public T exchangeKko(final String url, final HttpMethod method, final Object body, final Class rtnClzz) { + Map map = new HashMap<>(); + map.put(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); + map.put(HttpHeaders.AUTHORIZATION, + String.format("%s %s", Constants.JwtToken.GRANT_TYPE.getCode(), kkoAccessToken)); + map.put(Constants.HeaderName.UUID.getCode(), kkoContractUuid); + + return exchange(url, method, body, rtnClzz, map); + } + + /** + *
+     * Async call - Response Entity(상태정보등) 가 필요한 경우
+     * @param url call url
+     * @param method POST|GET
+     * @param body JSON String type
+     * @param rtnClzz rtnClzz return type class
+     *        (ex: new KkopayDocDTO.DocStatusResponse().getClass())
+     * @return T rtnClzz return DTO
+     * 
+ */ + public T exchange(final String url, final HttpMethod method, final Object body, final Class rtnClzz, final Map headerMap) { + + return webClientConfig.webClient() + .method(method) + .uri(url) + .headers(httpHeaders -> getHeaders(httpHeaders, headerMap)) + .bodyValue(Objects.requireNonNullElse(body, "")) + .exchangeToMono(res -> res.bodyToMono(rtnClzz)) + .block(); + } + + public ApiResponseDTO sendError(final Throwable e) { + + Map map = ErrorParse.extractError(e.getCause()); + return ApiResponseDTO.error(String.valueOf(map.get("code")), String.valueOf(map.get("message")), (HttpStatus)map.get("httpStatus")); + } + + private URI createUrl(final String endPoint, final String... value) { + return UriComponentsBuilder.fromUriString(endPoint) + .build(value); + } + + private HttpHeaders getHeaders(final HttpHeaders headers, final Map map) { + + for(Map.Entry e : map.entrySet()){ + headers.add(e.getKey(), e.getValue()); + } + return headers; + } + + ExchangeFilterFunction errorHandler() { + return ExchangeFilterFunction.ofResponseProcessor(clientResponse -> { + HttpStatus status = clientResponse.statusCode(); + + if (clientResponse.statusCode().is4xxClientError()) { + return clientResponse.bodyToMono(String.class) + .flatMap(errorBody -> Mono.error(new ClientError(status, errorBody))); + + } else if (clientResponse.statusCode().is5xxServerError()) { + return clientResponse.bodyToMono(String.class) + .flatMap(errorBody -> Mono.error(new ServerError(status, errorBody))); + + } + return Mono.just(clientResponse); + }); + } +} diff --git a/xit-init/pom.xml b/xit-init/pom.xml index e3095d1..1a3726e 100644 --- a/xit-init/pom.xml +++ b/xit-init/pom.xml @@ -76,6 +76,7 @@ +