From 3874d578cedd68cb9f1e32de09daad6b2c2ef1f1 Mon Sep 17 00:00:00 2001 From: hl3470 Date: Mon, 30 Sep 2024 09:33:06 +0900 Subject: [PATCH 1/7] =?UTF-8?q?refactor:=20=EA=B8=B0=EC=A1=B4=20Stock=20?= =?UTF-8?q?=EB=8F=84=EB=A9=94=EC=9D=B8=20DomesticStock=EC=9C=BC=EB=A1=9C?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/scheduling/SchedulingService.java | 6 +-- .../domains/autoTrade/AutoTradeService.java | 16 +++---- ...ller.java => DomesticStockController.java} | 42 +++++++++---------- .../{StockDTO.java => DomesticStockDTO.java} | 4 +- ...Service.java => DomesticStockService.java} | 30 ++++++------- 5 files changed, 49 insertions(+), 49 deletions(-) rename backend/src/main/java/kakaobootcamp/backend/domains/stock/controller/{StockController.java => DomesticStockController.java} (84%) rename backend/src/main/java/kakaobootcamp/backend/domains/stock/dto/{StockDTO.java => DomesticStockDTO.java} (99%) rename backend/src/main/java/kakaobootcamp/backend/domains/stock/service/{StockService.java => DomesticStockService.java} (91%) diff --git a/backend/src/main/java/kakaobootcamp/backend/common/scheduling/SchedulingService.java b/backend/src/main/java/kakaobootcamp/backend/common/scheduling/SchedulingService.java index acd6d44..a892fd0 100644 --- a/backend/src/main/java/kakaobootcamp/backend/common/scheduling/SchedulingService.java +++ b/backend/src/main/java/kakaobootcamp/backend/common/scheduling/SchedulingService.java @@ -5,7 +5,7 @@ import org.springframework.transaction.annotation.Transactional; import kakaobootcamp.backend.domains.autoTrade.AutoTradeService; -import kakaobootcamp.backend.domains.stock.service.StockService; +import kakaobootcamp.backend.domains.stock.service.DomesticStockService; import lombok.RequiredArgsConstructor; @RequiredArgsConstructor @@ -13,7 +13,7 @@ public class SchedulingService { private final AutoTradeService autoTradeService; - private final StockService stockService; + private final DomesticStockService domesticStockService; @Async @Scheduled(cron = "0 0 11 * * MON-FRI") @@ -24,6 +24,6 @@ public void doAutoTrade() { @Async @Scheduled(cron = "0 0 20 * * MON-SAT") public void updateSuggestedKeywords() { - stockService.updateDomesticStocks(); + domesticStockService.updateDomesticStocks(); } } diff --git a/backend/src/main/java/kakaobootcamp/backend/domains/autoTrade/AutoTradeService.java b/backend/src/main/java/kakaobootcamp/backend/domains/autoTrade/AutoTradeService.java index 40cb8e6..6e20863 100644 --- a/backend/src/main/java/kakaobootcamp/backend/domains/autoTrade/AutoTradeService.java +++ b/backend/src/main/java/kakaobootcamp/backend/domains/autoTrade/AutoTradeService.java @@ -15,10 +15,10 @@ import kakaobootcamp.backend.domains.member.MemberService; import kakaobootcamp.backend.domains.member.domain.AutoTradeState; import kakaobootcamp.backend.domains.member.domain.Member; -import kakaobootcamp.backend.domains.stock.dto.StockDTO.GetStockBalanceResponse; -import kakaobootcamp.backend.domains.stock.dto.StockDTO.GetStockBalanceResponse.Output1; -import kakaobootcamp.backend.domains.stock.dto.StockDTO.OrderStockRequest; -import kakaobootcamp.backend.domains.stock.service.StockService; +import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.GetStockBalanceResponse; +import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.GetStockBalanceResponse.Output1; +import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.OrderStockRequest; +import kakaobootcamp.backend.domains.stock.service.DomesticStockService; import kakaobootcamp.backend.domains.transaction.TransactionService; import kakaobootcamp.backend.domains.transaction.domain.Transaction; import lombok.RequiredArgsConstructor; @@ -29,7 +29,7 @@ public class AutoTradeService { private final AiServerService aiServerService; - private final StockService stockService; + private final DomesticStockService domesticStockService; private final TransactionService transactionService; private final MemberService memberService; private final BrokerService brokerService; @@ -52,7 +52,7 @@ private void executeAutoTradeForTransaction(Transaction transaction) { } // 현재 보유 주식량 및 예수금 조회 - GetStockBalanceResponse stockBalanceResponse = stockService.getStockBalance(member, "", ""); + GetStockBalanceResponse stockBalanceResponse = domesticStockService.getStockBalance(member, "", ""); // 거래 가능 금액 계산 int availableBalance = calculateAvailableBalance( @@ -127,9 +127,9 @@ private void placeOrder(Member member, String productNumber, int quantity, boole .build(); if (isBuy) { - stockService.orderStock(member, request); + domesticStockService.orderStock(member, request); } else { - stockService.sellStock(member, request); + domesticStockService.sellStock(member, request); } } } diff --git a/backend/src/main/java/kakaobootcamp/backend/domains/stock/controller/StockController.java b/backend/src/main/java/kakaobootcamp/backend/domains/stock/controller/DomesticStockController.java similarity index 84% rename from backend/src/main/java/kakaobootcamp/backend/domains/stock/controller/StockController.java rename to backend/src/main/java/kakaobootcamp/backend/domains/stock/controller/DomesticStockController.java index 93658bb..518283b 100644 --- a/backend/src/main/java/kakaobootcamp/backend/domains/stock/controller/StockController.java +++ b/backend/src/main/java/kakaobootcamp/backend/domains/stock/controller/DomesticStockController.java @@ -25,31 +25,31 @@ import kakaobootcamp.backend.common.dto.ErrorResponse; import kakaobootcamp.backend.common.util.memberLoader.MemberLoader; import kakaobootcamp.backend.domains.member.domain.Member; -import kakaobootcamp.backend.domains.stock.dto.StockDTO.FindDomesticStockPopularChartResponse; -import kakaobootcamp.backend.domains.stock.dto.StockDTO.FindDomesticStockPriceChartResponse; -import kakaobootcamp.backend.domains.stock.dto.StockDTO.FindSuggestedKeywordResponse; -import kakaobootcamp.backend.domains.stock.dto.StockDTO.GetStockBalanceRealizedProfitAndLossResponse; -import kakaobootcamp.backend.domains.stock.dto.StockDTO.GetStockBalanceResponse; -import kakaobootcamp.backend.domains.stock.dto.StockDTO.GetStockPriceResponse; -import kakaobootcamp.backend.domains.stock.dto.StockDTO.OrderStockRequest; -import kakaobootcamp.backend.domains.stock.service.StockService; +import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.FindDomesticStockPopularChartResponse; +import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.FindStockPriceChartResponse; +import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.FindSuggestedKeywordResponse; +import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.GetStockBalanceRealizedProfitAndLossResponse; +import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.GetStockBalanceResponse; +import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.GetStockPriceResponse; +import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.OrderStockRequest; +import kakaobootcamp.backend.domains.stock.service.DomesticStockService; import lombok.RequiredArgsConstructor; -@Tag(name = "STOCK API", description = "주식에 대한 API입니다.") +@Tag(name = "DOMESTIC STOCK API", description = "국내 주식에 대한 API입니다.") @RestController -@RequestMapping("/api/stocks") +@RequestMapping("/api/stocks/domestic") @RequiredArgsConstructor -public class StockController { +public class DomesticStockController { private final MemberLoader memberLoader; - private final StockService stockService; + private final DomesticStockService domesticStockService; // 삭제될 API @PostMapping("/buy") public ResponseEntity> buyStock(OrderStockRequest request) { Member member = memberLoader.getMember(); - stockService.orderStock(member, request); + domesticStockService.orderStock(member, request); return ResponseEntity.ok(DataResponse.ok()); } @@ -58,7 +58,7 @@ public ResponseEntity> buyStock(OrderStockRequest request) { public ResponseEntity> sellStock(OrderStockRequest request) { Member member = memberLoader.getMember(); - stockService.sellStock(member, request); + domesticStockService.sellStock(member, request); return ResponseEntity.ok(DataResponse.ok()); } @@ -122,7 +122,7 @@ public ResponseEntity> getStockBalance( @RequestParam(name = "CTX_AREA_NK100", defaultValue = "") String nk) { Member member = memberLoader.getMember(); - GetStockBalanceResponse response = stockService.getStockBalance(member, fk, nk); + GetStockBalanceResponse response = domesticStockService.getStockBalance(member, fk, nk); return ResponseEntity.ok(DataResponse.from(response)); } @@ -158,7 +158,7 @@ public ResponseEntity> getStockBalance( public ResponseEntity> getBalanceRealizedProfitAndLoss() { Member member = memberLoader.getMember(); - GetStockBalanceRealizedProfitAndLossResponse response = stockService + GetStockBalanceRealizedProfitAndLossResponse response = domesticStockService .getBalanceRealizedProfitAndLoss(member); return ResponseEntity.ok(DataResponse.from(response)); @@ -195,7 +195,7 @@ public ResponseEntity> getStockPrice( @RequestParam("productNumber") String productNumber) { Member member = memberLoader.getMember(); - GetStockPriceResponse response = stockService.getStockPrice(member, productNumber); + GetStockPriceResponse response = domesticStockService.getStockPrice(member, productNumber); return ResponseEntity.ok(DataResponse.from(response)); } @@ -229,14 +229,14 @@ public ResponseEntity> getStockPrice( ) public ResponseEntity>> findSuggestedKeywords( @RequestParam("keyword") String keyword) { - List responses = stockService.findSuggestedKeywords(keyword); + List responses = domesticStockService.findSuggestedKeywords(keyword); return ResponseEntity.ok(DataResponse.from(responses)); } @GetMapping("/update/removed") public ResponseEntity updateRemovedStocks() { - stockService.updateDomesticStocks(); + domesticStockService.updateDomesticStocks(); return ResponseEntity.ok().build(); } @@ -269,12 +269,12 @@ public ResponseEntity updateRemovedStocks() { ) } ) - public ResponseEntity> findDomesticStockPriceChart( + public ResponseEntity> findStockPriceChart( @RequestParam("productNumber") String productNumber, @Pattern(regexp = "D|W|M|Y", message = "periodCode는 D, W, M, Y 중 하나여야 합니다.") @RequestParam("periodCode") String periodCode) { Member member = memberLoader.getMember(); - FindDomesticStockPriceChartResponse response = stockService.findDomesticStockPriceChart(member, productNumber, + FindStockPriceChartResponse response = domesticStockService.findStockPriceChart(member, productNumber, periodCode); return ResponseEntity.ok(DataResponse.from(response)); diff --git a/backend/src/main/java/kakaobootcamp/backend/domains/stock/dto/StockDTO.java b/backend/src/main/java/kakaobootcamp/backend/domains/stock/dto/DomesticStockDTO.java similarity index 99% rename from backend/src/main/java/kakaobootcamp/backend/domains/stock/dto/StockDTO.java rename to backend/src/main/java/kakaobootcamp/backend/domains/stock/dto/DomesticStockDTO.java index cd74910..4504392 100644 --- a/backend/src/main/java/kakaobootcamp/backend/domains/stock/dto/StockDTO.java +++ b/backend/src/main/java/kakaobootcamp/backend/domains/stock/dto/DomesticStockDTO.java @@ -14,7 +14,7 @@ import lombok.NoArgsConstructor; import lombok.Setter; -public class StockDTO { +public class DomesticStockDTO { @Getter @Setter @@ -411,7 +411,7 @@ public static FindSuggestedKeywordResponse from(DomesticStock domesticStock) { @Getter @NoArgsConstructor(access = AccessLevel.PRIVATE) - public static class FindDomesticStockPriceChartResponse extends KisBaseResponse { + public static class FindStockPriceChartResponse extends KisBaseResponse { private Output1 output1; // 응답 상세 private List output2; // 일별 데이터 배열 diff --git a/backend/src/main/java/kakaobootcamp/backend/domains/stock/service/StockService.java b/backend/src/main/java/kakaobootcamp/backend/domains/stock/service/DomesticStockService.java similarity index 91% rename from backend/src/main/java/kakaobootcamp/backend/domains/stock/service/StockService.java rename to backend/src/main/java/kakaobootcamp/backend/domains/stock/service/DomesticStockService.java index bf5f28d..6e8f485 100644 --- a/backend/src/main/java/kakaobootcamp/backend/domains/stock/service/StockService.java +++ b/backend/src/main/java/kakaobootcamp/backend/domains/stock/service/DomesticStockService.java @@ -25,17 +25,17 @@ import kakaobootcamp.backend.domains.member.MemberService; import kakaobootcamp.backend.domains.member.domain.Member; import kakaobootcamp.backend.domains.stock.domain.DomesticStock; -import kakaobootcamp.backend.domains.stock.dto.StockDTO.FindDomesticStockPriceChartResponse; -import kakaobootcamp.backend.domains.stock.dto.StockDTO.FindSuggestedKeywordResponse; -import kakaobootcamp.backend.domains.stock.dto.StockDTO.GetStockBalanceRealizedProfitAndLossResponse; -import kakaobootcamp.backend.domains.stock.dto.StockDTO.GetStockBalanceResponse; -import kakaobootcamp.backend.domains.stock.dto.StockDTO.GetStockPriceResponse; -import kakaobootcamp.backend.domains.stock.dto.StockDTO.GetSuggestedKeywordsDTO; -import kakaobootcamp.backend.domains.stock.dto.StockDTO.GetSuggestedKeywordsDTO.Response.Body.Items.Item; -import kakaobootcamp.backend.domains.stock.dto.StockDTO.KisBaseResponse; -import kakaobootcamp.backend.domains.stock.dto.StockDTO.KisOrderStockRequest; -import kakaobootcamp.backend.domains.stock.dto.StockDTO.OrderStockRequest; -import kakaobootcamp.backend.domains.stock.dto.StockDTO.OrderStockResponse; +import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.FindStockPriceChartResponse; +import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.FindSuggestedKeywordResponse; +import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.GetStockBalanceRealizedProfitAndLossResponse; +import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.GetStockBalanceResponse; +import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.GetStockPriceResponse; +import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.GetSuggestedKeywordsDTO; +import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.GetSuggestedKeywordsDTO.Response.Body.Items.Item; +import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.KisBaseResponse; +import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.KisOrderStockRequest; +import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.OrderStockRequest; +import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.OrderStockResponse; import kakaobootcamp.backend.domains.stock.repository.DomesticStockRepository; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -43,7 +43,7 @@ @Slf4j @Service @RequiredArgsConstructor -public class StockService { +public class DomesticStockService { private final KisProperties kisProperties; private final KisAccessTokenService kisAccessTokenService; @@ -312,7 +312,7 @@ private DomesticStock findDomesticStockByProductNumber(String productNumber) { } // 국내 주식 기간별 시세 조회 - public FindDomesticStockPriceChartResponse findDomesticStockPriceChart(Member member, String productNumber, + public FindStockPriceChartResponse findStockPriceChart(Member member, String productNumber, String periodCode) { String uri = "/uapi/domestic-stock/v1/quotations/inquire-daily-itemchartprice"; LocalDate today = LocalDate.now(); @@ -331,11 +331,11 @@ public FindDomesticStockPriceChartResponse findDomesticStockPriceChart(Member me params.add("FID_PERIOD_DIV_CODE", periodCode); params.add("FID_ORG_ADJ_PRC", "1"); - FindDomesticStockPriceChartResponse response = webClientUtil.getFromKis( + FindStockPriceChartResponse response = webClientUtil.getFromKis( headers, uri, params, - FindDomesticStockPriceChartResponse.class); + FindStockPriceChartResponse.class); checkResponse(response); From 1f9cbf8f83754ffc890d04546ded96be8981d7fc Mon Sep 17 00:00:00 2001 From: hl3470 Date: Mon, 30 Sep 2024 16:21:18 +0900 Subject: [PATCH 2/7] =?UTF-8?q?refactor:=20=EC=BD=94=EB=93=9C=20=EB=A6=AC?= =?UTF-8?q?=ED=8C=A9=ED=84=B0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit get -> find로 변경 buy와 order 메서드 order로 통일 --- .../common/properties/KisProperties.java | 8 +- .../domains/autoTrade/AutoTradeService.java | 10 +-- .../controller/DomesticStockController.java | 26 +++---- .../domains/stock/dto/DomesticStockDTO.java | 28 +------ .../stock/service/DomesticStockService.java | 74 ++++++++----------- 5 files changed, 57 insertions(+), 89 deletions(-) diff --git a/backend/src/main/java/kakaobootcamp/backend/common/properties/KisProperties.java b/backend/src/main/java/kakaobootcamp/backend/common/properties/KisProperties.java index fc37d05..059dd29 100644 --- a/backend/src/main/java/kakaobootcamp/backend/common/properties/KisProperties.java +++ b/backend/src/main/java/kakaobootcamp/backend/common/properties/KisProperties.java @@ -11,10 +11,10 @@ public class KisProperties { private String url; - private String orderTrId; + private String buyTrId; private String sellTrId; - private String getBalanceTrId; - private String getBalanceRealizedProfitAndLossTrId; - private String getPriceTrId; + private String findBalanceTrId; + private String findBalanceRealizedProfitAndLossTrId; + private String findPriceTrId; private String findDomesticStockPriceChartId; } diff --git a/backend/src/main/java/kakaobootcamp/backend/domains/autoTrade/AutoTradeService.java b/backend/src/main/java/kakaobootcamp/backend/domains/autoTrade/AutoTradeService.java index 6e20863..9e04b2d 100644 --- a/backend/src/main/java/kakaobootcamp/backend/domains/autoTrade/AutoTradeService.java +++ b/backend/src/main/java/kakaobootcamp/backend/domains/autoTrade/AutoTradeService.java @@ -15,8 +15,8 @@ import kakaobootcamp.backend.domains.member.MemberService; import kakaobootcamp.backend.domains.member.domain.AutoTradeState; import kakaobootcamp.backend.domains.member.domain.Member; -import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.GetStockBalanceResponse; -import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.GetStockBalanceResponse.Output1; +import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.FindStockBalanceResponse; +import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.FindStockBalanceResponse.Output1; import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.OrderStockRequest; import kakaobootcamp.backend.domains.stock.service.DomesticStockService; import kakaobootcamp.backend.domains.transaction.TransactionService; @@ -52,7 +52,7 @@ private void executeAutoTradeForTransaction(Transaction transaction) { } // 현재 보유 주식량 및 예수금 조회 - GetStockBalanceResponse stockBalanceResponse = domesticStockService.getStockBalance(member, "", ""); + FindStockBalanceResponse stockBalanceResponse = domesticStockService.findStockBalance(member, "", ""); // 거래 가능 금액 계산 int availableBalance = calculateAvailableBalance( @@ -127,9 +127,9 @@ private void placeOrder(Member member, String productNumber, int quantity, boole .build(); if (isBuy) { - domesticStockService.orderStock(member, request); + domesticStockService.orderStock(member, request, true); } else { - domesticStockService.sellStock(member, request); + domesticStockService.orderStock(member, request, false); } } } diff --git a/backend/src/main/java/kakaobootcamp/backend/domains/stock/controller/DomesticStockController.java b/backend/src/main/java/kakaobootcamp/backend/domains/stock/controller/DomesticStockController.java index 518283b..e2cd4ce 100644 --- a/backend/src/main/java/kakaobootcamp/backend/domains/stock/controller/DomesticStockController.java +++ b/backend/src/main/java/kakaobootcamp/backend/domains/stock/controller/DomesticStockController.java @@ -26,11 +26,11 @@ import kakaobootcamp.backend.common.util.memberLoader.MemberLoader; import kakaobootcamp.backend.domains.member.domain.Member; import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.FindDomesticStockPopularChartResponse; +import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.FindStockBalanceRealizedProfitAndLossResponse; +import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.FindStockBalanceResponse; import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.FindStockPriceChartResponse; +import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.FindStockPriceResponse; import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.FindSuggestedKeywordResponse; -import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.GetStockBalanceRealizedProfitAndLossResponse; -import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.GetStockBalanceResponse; -import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.GetStockPriceResponse; import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.OrderStockRequest; import kakaobootcamp.backend.domains.stock.service.DomesticStockService; import lombok.RequiredArgsConstructor; @@ -49,7 +49,7 @@ public class DomesticStockController { public ResponseEntity> buyStock(OrderStockRequest request) { Member member = memberLoader.getMember(); - domesticStockService.orderStock(member, request); + domesticStockService.orderStock(member, request, true); return ResponseEntity.ok(DataResponse.ok()); } @@ -58,13 +58,13 @@ public ResponseEntity> buyStock(OrderStockRequest request) { public ResponseEntity> sellStock(OrderStockRequest request) { Member member = memberLoader.getMember(); - domesticStockService.sellStock(member, request); + domesticStockService.orderStock(member, request, false); return ResponseEntity.ok(DataResponse.ok()); } @GetMapping("/recommendations") - public ResponseEntity>> getStockRecommendations( + public ResponseEntity>> findStockRecommendations( @RequestParam("size") @Min(value = 1, message = "size는 1이상이어야 합니다.") @Max(value = 10, message = "size는 10이하이어야 합니다.") int size, @RequestParam("page") @Min(value = 0, message = "page는 0이상이어야 합니다.") int page) { Pageable pageable = PageRequest.of(page, size); @@ -117,12 +117,12 @@ public ResponseEntity>> ) } ) - public ResponseEntity> getStockBalance( + public ResponseEntity> findStockBalance( @RequestParam(name = "CTX_AREA_FK100", defaultValue = "") String fk, @RequestParam(name = "CTX_AREA_NK100", defaultValue = "") String nk) { Member member = memberLoader.getMember(); - GetStockBalanceResponse response = domesticStockService.getStockBalance(member, fk, nk); + FindStockBalanceResponse response = domesticStockService.findStockBalance(member, fk, nk); return ResponseEntity.ok(DataResponse.from(response)); } @@ -155,11 +155,11 @@ public ResponseEntity> getStockBalance( ) } ) - public ResponseEntity> getBalanceRealizedProfitAndLoss() { + public ResponseEntity> findBalanceRealizedProfitAndLoss() { Member member = memberLoader.getMember(); - GetStockBalanceRealizedProfitAndLossResponse response = domesticStockService - .getBalanceRealizedProfitAndLoss(member); + FindStockBalanceRealizedProfitAndLossResponse response = domesticStockService + .findBalanceRealizedProfitAndLoss(member); return ResponseEntity.ok(DataResponse.from(response)); } @@ -191,11 +191,11 @@ public ResponseEntity ) } ) - public ResponseEntity> getStockPrice( + public ResponseEntity> findStockPrice( @RequestParam("productNumber") String productNumber) { Member member = memberLoader.getMember(); - GetStockPriceResponse response = domesticStockService.getStockPrice(member, productNumber); + FindStockPriceResponse response = domesticStockService.findStockPrice(member, productNumber); return ResponseEntity.ok(DataResponse.from(response)); } diff --git a/backend/src/main/java/kakaobootcamp/backend/domains/stock/dto/DomesticStockDTO.java b/backend/src/main/java/kakaobootcamp/backend/domains/stock/dto/DomesticStockDTO.java index 4504392..5295724 100644 --- a/backend/src/main/java/kakaobootcamp/backend/domains/stock/dto/DomesticStockDTO.java +++ b/backend/src/main/java/kakaobootcamp/backend/domains/stock/dto/DomesticStockDTO.java @@ -16,26 +16,6 @@ public class DomesticStockDTO { - @Getter - @Setter - @NoArgsConstructor(access = AccessLevel.PRIVATE) - @Builder - @AllArgsConstructor(access = AccessLevel.PRIVATE) - public static class OrderStockRequest { - - @JsonProperty("PDNO") - private String PDNO; // 종목코드 (6자리, 최대 12자리) - - @JsonProperty("ORD_DVSN") - private String ORD_DVSN; // 주문구분 (2자리) - - @JsonProperty("ORD_QTY") - private String ORD_QTY; // 주문수량 (최대 10자리) - - @JsonProperty("ORD_UNPR") - private String ORD_UNPR; // 주문단가 (최대 19자리) - } - @Getter @NoArgsConstructor(access = AccessLevel.PRIVATE) public static class KisBaseResponse { @@ -50,7 +30,7 @@ public static class KisBaseResponse { @NoArgsConstructor(access = AccessLevel.PRIVATE) @AllArgsConstructor(access = AccessLevel.PRIVATE) @Builder - public static class KisOrderStockRequest { + public static class OrderStockRequest { @JsonProperty("CANO") private String CANO; // 종합계좌번호 (8자리) @@ -94,7 +74,7 @@ public static class Output { @Getter @NoArgsConstructor(access = AccessLevel.PRIVATE) - public static class GetStockBalanceResponse extends KisBaseResponse { + public static class FindStockBalanceResponse extends KisBaseResponse { private String ctx_area_fk100; // 연속조회검색조건100 private String ctx_area_nk100; // 연속조회키100 @@ -164,7 +144,7 @@ public static class Output2 { @Getter @NoArgsConstructor(access = AccessLevel.PRIVATE) - public static class GetStockBalanceRealizedProfitAndLossResponse extends KisBaseResponse { + public static class FindStockBalanceRealizedProfitAndLossResponse extends KisBaseResponse { private List output1; // 응답상세1 (Object Array) private List output2; // 응답상세2 (Object) @@ -233,7 +213,7 @@ public static class Output2 { @Getter @NoArgsConstructor(access = AccessLevel.PRIVATE) - public static class GetStockPriceResponse extends KisBaseResponse { + public static class FindStockPriceResponse extends KisBaseResponse { private Output output; // 응답상세 diff --git a/backend/src/main/java/kakaobootcamp/backend/domains/stock/service/DomesticStockService.java b/backend/src/main/java/kakaobootcamp/backend/domains/stock/service/DomesticStockService.java index 6e8f485..13ed109 100644 --- a/backend/src/main/java/kakaobootcamp/backend/domains/stock/service/DomesticStockService.java +++ b/backend/src/main/java/kakaobootcamp/backend/domains/stock/service/DomesticStockService.java @@ -27,13 +27,12 @@ import kakaobootcamp.backend.domains.stock.domain.DomesticStock; import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.FindStockPriceChartResponse; import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.FindSuggestedKeywordResponse; -import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.GetStockBalanceRealizedProfitAndLossResponse; -import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.GetStockBalanceResponse; -import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.GetStockPriceResponse; +import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.FindStockBalanceRealizedProfitAndLossResponse; +import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.FindStockBalanceResponse; +import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.FindStockPriceResponse; import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.GetSuggestedKeywordsDTO; import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.GetSuggestedKeywordsDTO.Response.Body.Items.Item; import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.KisBaseResponse; -import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.KisOrderStockRequest; import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.OrderStockRequest; import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.OrderStockResponse; import kakaobootcamp.backend.domains.stock.repository.DomesticStockRepository; @@ -75,51 +74,40 @@ private void checkResponse(KisBaseResponse response) { } } - // 주식 사기 - public void orderStock(Member member, OrderStockRequest request) { - String uri = "/uapi/domestic-stock/v1/trading/order-cash"; - - // 헤더 설정 - Map headers = makeHeaders(member, kisProperties.getOrderTrId()); - - // 본문 설정 - KisOrderStockRequest kisOrderStockRequest = makeKisOrderStockRequestFromOrderStockRequestAndMember(member, - request); - - OrderStockResponse response = webClientUtil.postFromKis( - headers, - uri, - kisOrderStockRequest, - OrderStockResponse.class); - - checkResponse(response); + // TrId 조회 + private String getTrId(boolean isBuy) { + if (isBuy) { + return kisProperties.getBuyTrId(); + } else { + return kisProperties.getSellTrId(); + } } - // 주식 팔기 - public void sellStock(Member member, OrderStockRequest request) { + // 주식 매매 + public void orderStock(Member member, OrderStockRequest request, boolean isBuy) { String uri = "/uapi/domestic-stock/v1/trading/order-cash"; + String trId = getTrId(isBuy); // 헤더 설정 - Map headers = makeHeaders(member, kisProperties.getSellTrId()); + Map headers = makeHeaders(member, trId); // 본문 설정 - KisOrderStockRequest kisOrderStockRequest = makeKisOrderStockRequestFromOrderStockRequestAndMember(member, - request - ); + OrderStockRequest orderStockRequest = makeKisOrderStockRequestFromOrderStockRequestAndMember(member, + request); OrderStockResponse response = webClientUtil.postFromKis( headers, uri, - kisOrderStockRequest, + orderStockRequest, OrderStockResponse.class); checkResponse(response); } // KisOrderStockRequest를 OrderStockRequest와 Member로 만들어주는 메서드 - private KisOrderStockRequest makeKisOrderStockRequestFromOrderStockRequestAndMember(Member member, + private OrderStockRequest makeKisOrderStockRequestFromOrderStockRequestAndMember(Member member, OrderStockRequest request) { - return KisOrderStockRequest.builder() + return OrderStockRequest.builder() .CANO(member.getComprehensiveAccountNumber()) .ACNT_PRDT_CD(member.getAccountProductCode()) .PDNO(request.getPDNO()) @@ -130,11 +118,11 @@ private KisOrderStockRequest makeKisOrderStockRequestFromOrderStockRequestAndMem } // 주식 잔고 조회 - public GetStockBalanceResponse getStockBalance(Member member, String fk, String nk) { + public FindStockBalanceResponse findStockBalance(Member member, String fk, String nk) { String uri = "/uapi/domestic-stock/v1/trading/inquire-balance"; // 헤더 설정 - Map headers = makeHeaders(member, kisProperties.getGetBalanceTrId()); + Map headers = makeHeaders(member, kisProperties.getFindBalanceTrId()); // 파라미터 설정 MultiValueMap params = new LinkedMultiValueMap<>(); @@ -150,11 +138,11 @@ public GetStockBalanceResponse getStockBalance(Member member, String fk, String params.add("CTX_AREA_FK100", fk); // 연속 조회 검색 조건 100 (최초 조회 시 공란) params.add("CTX_AREA_NK100", nk); // 연속 조회 키 100 (최초 조회 시 공란) - GetStockBalanceResponse response = webClientUtil.getFromKis( + FindStockBalanceResponse response = webClientUtil.getFromKis( headers, uri, params, - GetStockBalanceResponse.class); + FindStockBalanceResponse.class); checkResponse(response); @@ -162,11 +150,11 @@ public GetStockBalanceResponse getStockBalance(Member member, String fk, String } // 주식잔고조회_실현손익 - public GetStockBalanceRealizedProfitAndLossResponse getBalanceRealizedProfitAndLoss(Member member) { + public FindStockBalanceRealizedProfitAndLossResponse findBalanceRealizedProfitAndLoss(Member member) { String uri = "/uapi/domestic-stock/v1/trading/inquire-balance-rlz-pl"; // 헤더 설정 - Map headers = makeHeaders(member, kisProperties.getGetBalanceRealizedProfitAndLossTrId()); + Map headers = makeHeaders(member, kisProperties.getFindBalanceRealizedProfitAndLossTrId()); headers.put("custtype", "P"); // 고객타입(P: 개인, B: 기업) // 파라미터 설정 @@ -184,11 +172,11 @@ public GetStockBalanceRealizedProfitAndLossResponse getBalanceRealizedProfitAndL params.add("CTX_AREA_FK100", ""); // 연속조회검색조건100 (최초 조회시 공란) params.add("CTX_AREA_NK100", ""); // 연속조회키100 (최초 조회시 공란) - GetStockBalanceRealizedProfitAndLossResponse response = webClientUtil.getFromKis( + FindStockBalanceRealizedProfitAndLossResponse response = webClientUtil.getFromKis( headers, uri, params, - GetStockBalanceRealizedProfitAndLossResponse.class); + FindStockBalanceRealizedProfitAndLossResponse.class); checkResponse(response); @@ -196,22 +184,22 @@ public GetStockBalanceRealizedProfitAndLossResponse getBalanceRealizedProfitAndL } // 주식 현재가 조회 - public GetStockPriceResponse getStockPrice(Member member, String productNumber) { + public FindStockPriceResponse findStockPrice(Member member, String productNumber) { String uri = "/uapi/domestic-stock/v1/quotations/inquire-price"; // 헤더 설정 - Map headers = makeHeaders(member, kisProperties.getGetPriceTrId()); + Map headers = makeHeaders(member, kisProperties.getFindPriceTrId()); // 파라미터 설정 MultiValueMap params = new LinkedMultiValueMap<>(); params.add("FID_COND_MRKT_DIV_CODE", "J"); // 'J': 주식, ETF, ETN / 'W': ELW params.add("FID_INPUT_ISCD", productNumber); // FID 입력 종목코드: 6자리 종목번호 또는 ETN의 경우 'Q'로 시작하는 코드 - GetStockPriceResponse response = webClientUtil.getFromKis( + FindStockPriceResponse response = webClientUtil.getFromKis( headers, uri, params, - GetStockPriceResponse.class); + FindStockPriceResponse.class); checkResponse(response); From 22f100b56d931dcc228a80d84dcc862c7e1165b8 Mon Sep 17 00:00:00 2001 From: hl3470 Date: Mon, 30 Sep 2024 16:30:50 +0900 Subject: [PATCH 3/7] =?UTF-8?q?feature:=20=EA=B5=AD=EB=82=B4=EC=99=80=20?= =?UTF-8?q?=ED=95=B4=EC=99=B8=20=EC=A3=BC=EC=8B=9D=20properties=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/properties/KisProperties.java | 30 +++++++++++++++---- .../stock/service/DomesticStockService.java | 16 +++++----- 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/backend/src/main/java/kakaobootcamp/backend/common/properties/KisProperties.java b/backend/src/main/java/kakaobootcamp/backend/common/properties/KisProperties.java index 059dd29..40215e8 100644 --- a/backend/src/main/java/kakaobootcamp/backend/common/properties/KisProperties.java +++ b/backend/src/main/java/kakaobootcamp/backend/common/properties/KisProperties.java @@ -11,10 +11,28 @@ public class KisProperties { private String url; - private String buyTrId; - private String sellTrId; - private String findBalanceTrId; - private String findBalanceRealizedProfitAndLossTrId; - private String findPriceTrId; - private String findDomesticStockPriceChartId; + private Domestic domestic; + private International international; + + @Getter + @Setter + public static class Domestic { + private String buyTrId; + private String sellTrId; + private String findBalanceTrId; + private String findBalanceRealizedProfitAndLossTrId; + private String findPriceTrId; + private String findDomesticStockPriceChartId; + } + + @Getter + @Setter + public static class International { + private String buyTrId; + private String sellTrId; + private String findBalanceTrId; + private String findBalanceRealizedProfitAndLossTrId; + private String findPriceTrId; + private String findDomesticStockPriceChartId; + } } diff --git a/backend/src/main/java/kakaobootcamp/backend/domains/stock/service/DomesticStockService.java b/backend/src/main/java/kakaobootcamp/backend/domains/stock/service/DomesticStockService.java index 13ed109..7b2d15d 100644 --- a/backend/src/main/java/kakaobootcamp/backend/domains/stock/service/DomesticStockService.java +++ b/backend/src/main/java/kakaobootcamp/backend/domains/stock/service/DomesticStockService.java @@ -54,8 +54,8 @@ public class DomesticStockService { // 헤더 설정 private Map makeHeaders(Member member, String trId) { - KisAccessToken kisAccessToken = kisAccessTokenService.findKisAccessToken(member.getId()). - orElseThrow(() -> ApiException.from(KIS_ACCESS_TOKEN_NOT_FOUND)); + KisAccessToken kisAccessToken = kisAccessTokenService.findKisAccessToken(member.getId()) + .orElseThrow(() -> ApiException.from(KIS_ACCESS_TOKEN_NOT_FOUND)); String accessToken = kisAccessToken.getAccessToken(); Map headers = new HashMap<>(); @@ -77,9 +77,9 @@ private void checkResponse(KisBaseResponse response) { // TrId 조회 private String getTrId(boolean isBuy) { if (isBuy) { - return kisProperties.getBuyTrId(); + return kisProperties.getDomestic().getBuyTrId(); } else { - return kisProperties.getSellTrId(); + return kisProperties.getDomestic().getSellTrId(); } } @@ -122,7 +122,7 @@ public FindStockBalanceResponse findStockBalance(Member member, String fk, Strin String uri = "/uapi/domestic-stock/v1/trading/inquire-balance"; // 헤더 설정 - Map headers = makeHeaders(member, kisProperties.getFindBalanceTrId()); + Map headers = makeHeaders(member, kisProperties.getDomestic().getFindBalanceTrId()); // 파라미터 설정 MultiValueMap params = new LinkedMultiValueMap<>(); @@ -154,7 +154,7 @@ public FindStockBalanceRealizedProfitAndLossResponse findBalanceRealizedProfitAn String uri = "/uapi/domestic-stock/v1/trading/inquire-balance-rlz-pl"; // 헤더 설정 - Map headers = makeHeaders(member, kisProperties.getFindBalanceRealizedProfitAndLossTrId()); + Map headers = makeHeaders(member, kisProperties.getDomestic().getFindBalanceRealizedProfitAndLossTrId()); headers.put("custtype", "P"); // 고객타입(P: 개인, B: 기업) // 파라미터 설정 @@ -188,7 +188,7 @@ public FindStockPriceResponse findStockPrice(Member member, String productNumber String uri = "/uapi/domestic-stock/v1/quotations/inquire-price"; // 헤더 설정 - Map headers = makeHeaders(member, kisProperties.getFindPriceTrId()); + Map headers = makeHeaders(member, kisProperties.getDomestic().getFindPriceTrId()); // 파라미터 설정 MultiValueMap params = new LinkedMultiValueMap<>(); @@ -308,7 +308,7 @@ public FindStockPriceChartResponse findStockPriceChart(Member member, String pro String endDate = makeDateToString(today); // 헤더 설정 - Map headers = makeHeaders(member, kisProperties.getFindDomesticStockPriceChartId()); + Map headers = makeHeaders(member, kisProperties.getDomestic().getFindDomesticStockPriceChartId()); // 파라미터 설정 MultiValueMap params = new LinkedMultiValueMap<>(); From cceb560696eac65e4b18583f03e958b14e78ec4b Mon Sep 17 00:00:00 2001 From: hl3470 Date: Mon, 30 Sep 2024 16:58:20 +0900 Subject: [PATCH 4/7] =?UTF-8?q?fix:=20kisOrderStockRequest=EC=99=80=20Orde?= =?UTF-8?q?rStockRequest=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domains/stock/dto/DomesticStockDTO.java | 20 +++++++++++++++- .../stock/service/DomesticStockService.java | 24 +++++++------------ 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/backend/src/main/java/kakaobootcamp/backend/domains/stock/dto/DomesticStockDTO.java b/backend/src/main/java/kakaobootcamp/backend/domains/stock/dto/DomesticStockDTO.java index 5295724..f8718a7 100644 --- a/backend/src/main/java/kakaobootcamp/backend/domains/stock/dto/DomesticStockDTO.java +++ b/backend/src/main/java/kakaobootcamp/backend/domains/stock/dto/DomesticStockDTO.java @@ -26,11 +26,29 @@ public static class KisBaseResponse { } @Getter - @Setter @NoArgsConstructor(access = AccessLevel.PRIVATE) @AllArgsConstructor(access = AccessLevel.PRIVATE) @Builder public static class OrderStockRequest { + @JsonProperty("PDNO") + private String PDNO; // 종목코드 (6자리, 최대 12자리) + + @JsonProperty("ORD_DVSN") + private String ORD_DVSN; // 주문구분 (2자리) + + @JsonProperty("ORD_QTY") + private String ORD_QTY; // 주문수량 (최대 10자리) + + @JsonProperty("ORD_UNPR") + private String ORD_UNPR; // 주문단가 (최대 19자리) + } + + @Getter + @Setter + @NoArgsConstructor(access = AccessLevel.PRIVATE) + @AllArgsConstructor(access = AccessLevel.PRIVATE) + @Builder + public static class KisOrderStockRequest { @JsonProperty("CANO") private String CANO; // 종합계좌번호 (8자리) diff --git a/backend/src/main/java/kakaobootcamp/backend/domains/stock/service/DomesticStockService.java b/backend/src/main/java/kakaobootcamp/backend/domains/stock/service/DomesticStockService.java index 7b2d15d..bb6349c 100644 --- a/backend/src/main/java/kakaobootcamp/backend/domains/stock/service/DomesticStockService.java +++ b/backend/src/main/java/kakaobootcamp/backend/domains/stock/service/DomesticStockService.java @@ -1,6 +1,7 @@ package kakaobootcamp.backend.domains.stock.service; import static kakaobootcamp.backend.common.exception.ErrorCode.*; +import static kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.*; import java.time.DayOfWeek; import java.time.LocalDate; @@ -25,16 +26,7 @@ import kakaobootcamp.backend.domains.member.MemberService; import kakaobootcamp.backend.domains.member.domain.Member; import kakaobootcamp.backend.domains.stock.domain.DomesticStock; -import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.FindStockPriceChartResponse; -import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.FindSuggestedKeywordResponse; -import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.FindStockBalanceRealizedProfitAndLossResponse; -import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.FindStockBalanceResponse; -import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.FindStockPriceResponse; -import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.GetSuggestedKeywordsDTO; import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.GetSuggestedKeywordsDTO.Response.Body.Items.Item; -import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.KisBaseResponse; -import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.OrderStockRequest; -import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.OrderStockResponse; import kakaobootcamp.backend.domains.stock.repository.DomesticStockRepository; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -92,22 +84,22 @@ public void orderStock(Member member, OrderStockRequest request, boolean isBuy) Map headers = makeHeaders(member, trId); // 본문 설정 - OrderStockRequest orderStockRequest = makeKisOrderStockRequestFromOrderStockRequestAndMember(member, + KisOrderStockRequest kisOrderStockRequest = makeKisOrderStockRequestFromOrderStockRequestAndMember(member, request); OrderStockResponse response = webClientUtil.postFromKis( headers, uri, - orderStockRequest, + kisOrderStockRequest, OrderStockResponse.class); checkResponse(response); } // KisOrderStockRequest를 OrderStockRequest와 Member로 만들어주는 메서드 - private OrderStockRequest makeKisOrderStockRequestFromOrderStockRequestAndMember(Member member, + private KisOrderStockRequest makeKisOrderStockRequestFromOrderStockRequestAndMember(Member member, OrderStockRequest request) { - return OrderStockRequest.builder() + return KisOrderStockRequest.builder() .CANO(member.getComprehensiveAccountNumber()) .ACNT_PRDT_CD(member.getAccountProductCode()) .PDNO(request.getPDNO()) @@ -154,7 +146,8 @@ public FindStockBalanceRealizedProfitAndLossResponse findBalanceRealizedProfitAn String uri = "/uapi/domestic-stock/v1/trading/inquire-balance-rlz-pl"; // 헤더 설정 - Map headers = makeHeaders(member, kisProperties.getDomestic().getFindBalanceRealizedProfitAndLossTrId()); + Map headers = makeHeaders(member, + kisProperties.getDomestic().getFindBalanceRealizedProfitAndLossTrId()); headers.put("custtype", "P"); // 고객타입(P: 개인, B: 기업) // 파라미터 설정 @@ -308,7 +301,8 @@ public FindStockPriceChartResponse findStockPriceChart(Member member, String pro String endDate = makeDateToString(today); // 헤더 설정 - Map headers = makeHeaders(member, kisProperties.getDomestic().getFindDomesticStockPriceChartId()); + Map headers = makeHeaders(member, + kisProperties.getDomestic().getFindDomesticStockPriceChartId()); // 파라미터 설정 MultiValueMap params = new LinkedMultiValueMap<>(); From cceb5f609e9b87e964c67aae72d6d76a5b298ff8 Mon Sep 17 00:00:00 2001 From: hl3470 Date: Mon, 30 Sep 2024 17:14:48 +0900 Subject: [PATCH 5/7] =?UTF-8?q?refactor:=20KisBaseResponse=20=EB=B3=84?= =?UTF-8?q?=EB=8F=84=EC=9D=98=20=ED=81=B4=EB=9E=98=EC=8A=A4=EB=A1=9C=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domains/stock/dto/DomesticStockDTO.java | 9 --------- .../backend/domains/stock/dto/KisBaseResponse.java | 14 ++++++++++++++ .../stock/service/DomesticStockService.java | 1 + 3 files changed, 15 insertions(+), 9 deletions(-) create mode 100644 backend/src/main/java/kakaobootcamp/backend/domains/stock/dto/KisBaseResponse.java diff --git a/backend/src/main/java/kakaobootcamp/backend/domains/stock/dto/DomesticStockDTO.java b/backend/src/main/java/kakaobootcamp/backend/domains/stock/dto/DomesticStockDTO.java index f8718a7..6ed74fd 100644 --- a/backend/src/main/java/kakaobootcamp/backend/domains/stock/dto/DomesticStockDTO.java +++ b/backend/src/main/java/kakaobootcamp/backend/domains/stock/dto/DomesticStockDTO.java @@ -16,15 +16,6 @@ public class DomesticStockDTO { - @Getter - @NoArgsConstructor(access = AccessLevel.PRIVATE) - public static class KisBaseResponse { - - private String rt_cd; // 응답 코드 - private String msg_cd; // 메시지 코드 - private String msg1; // 메시지 내용 - } - @Getter @NoArgsConstructor(access = AccessLevel.PRIVATE) @AllArgsConstructor(access = AccessLevel.PRIVATE) diff --git a/backend/src/main/java/kakaobootcamp/backend/domains/stock/dto/KisBaseResponse.java b/backend/src/main/java/kakaobootcamp/backend/domains/stock/dto/KisBaseResponse.java new file mode 100644 index 0000000..6abc578 --- /dev/null +++ b/backend/src/main/java/kakaobootcamp/backend/domains/stock/dto/KisBaseResponse.java @@ -0,0 +1,14 @@ +package kakaobootcamp.backend.domains.stock.dto; + +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class KisBaseResponse { + + private String rt_cd; // 응답 코드 + private String msg_cd; // 메시지 코드 + private String msg1; // 메시지 내용 +} diff --git a/backend/src/main/java/kakaobootcamp/backend/domains/stock/service/DomesticStockService.java b/backend/src/main/java/kakaobootcamp/backend/domains/stock/service/DomesticStockService.java index bb6349c..b2508a7 100644 --- a/backend/src/main/java/kakaobootcamp/backend/domains/stock/service/DomesticStockService.java +++ b/backend/src/main/java/kakaobootcamp/backend/domains/stock/service/DomesticStockService.java @@ -27,6 +27,7 @@ import kakaobootcamp.backend.domains.member.domain.Member; import kakaobootcamp.backend.domains.stock.domain.DomesticStock; import kakaobootcamp.backend.domains.stock.dto.DomesticStockDTO.GetSuggestedKeywordsDTO.Response.Body.Items.Item; +import kakaobootcamp.backend.domains.stock.dto.KisBaseResponse; import kakaobootcamp.backend.domains.stock.repository.DomesticStockRepository; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; From dc2233ebb999035819babafba00d7f87e5f1686f Mon Sep 17 00:00:00 2001 From: hl3470 Date: Mon, 30 Sep 2024 17:48:37 +0900 Subject: [PATCH 6/7] =?UTF-8?q?refactor:=20NoArgs=EC=9D=98=20private=20?= =?UTF-8?q?=EC=A0=91=EA=B7=BC=EC=9E=90=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/domains/stock/dto/KisBaseResponse.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/backend/src/main/java/kakaobootcamp/backend/domains/stock/dto/KisBaseResponse.java b/backend/src/main/java/kakaobootcamp/backend/domains/stock/dto/KisBaseResponse.java index 6abc578..75e0b69 100644 --- a/backend/src/main/java/kakaobootcamp/backend/domains/stock/dto/KisBaseResponse.java +++ b/backend/src/main/java/kakaobootcamp/backend/domains/stock/dto/KisBaseResponse.java @@ -1,11 +1,8 @@ package kakaobootcamp.backend.domains.stock.dto; -import lombok.AccessLevel; import lombok.Getter; -import lombok.NoArgsConstructor; @Getter -@NoArgsConstructor(access = AccessLevel.PRIVATE) public class KisBaseResponse { private String rt_cd; // 응답 코드 From ac69ff64f422d75dfc26fdddc3d54507060b39d9 Mon Sep 17 00:00:00 2001 From: hl3470 Date: Mon, 30 Sep 2024 17:49:32 +0900 Subject: [PATCH 7/7] =?UTF-8?q?feat:=20=ED=95=B4=EC=99=B8=20=EC=A3=BC?= =?UTF-8?q?=EC=8B=9D=20=EA=B5=AC=EB=A7=A4=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../InternationalStockController.java | 43 ++++++++++ .../stock/dto/InternationalStockDTO.java | 67 ++++++++++++++++ .../service/InternationalStockService.java | 80 +++++++++++++++++++ 3 files changed, 190 insertions(+) create mode 100644 backend/src/main/java/kakaobootcamp/backend/domains/stock/controller/InternationalStockController.java create mode 100644 backend/src/main/java/kakaobootcamp/backend/domains/stock/dto/InternationalStockDTO.java create mode 100644 backend/src/main/java/kakaobootcamp/backend/domains/stock/service/InternationalStockService.java diff --git a/backend/src/main/java/kakaobootcamp/backend/domains/stock/controller/InternationalStockController.java b/backend/src/main/java/kakaobootcamp/backend/domains/stock/controller/InternationalStockController.java new file mode 100644 index 0000000..839c44a --- /dev/null +++ b/backend/src/main/java/kakaobootcamp/backend/domains/stock/controller/InternationalStockController.java @@ -0,0 +1,43 @@ +package kakaobootcamp.backend.domains.stock.controller; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import io.swagger.v3.oas.annotations.tags.Tag; +import kakaobootcamp.backend.common.dto.DataResponse; +import kakaobootcamp.backend.common.util.memberLoader.MemberLoader; +import kakaobootcamp.backend.domains.member.domain.Member; +import kakaobootcamp.backend.domains.stock.dto.InternationalStockDTO.InternationalOrderStockRequest; +import kakaobootcamp.backend.domains.stock.service.InternationalStockService; +import lombok.RequiredArgsConstructor; + +@Tag(name = "INTERNATIONAL STOCK API", description = "해외 주식에 대한 API입니다.") +@RestController +@RequestMapping("/api/stock/international") +@RequiredArgsConstructor +public class InternationalStockController { + + private final MemberLoader memberLoader; + private final InternationalStockService internationalStockService; + + // 삭제될 API + @PostMapping("/buy") + public ResponseEntity> buyStock(InternationalOrderStockRequest request) { + Member member = memberLoader.getMember(); + + internationalStockService.orderStock(member, request, true); + + return ResponseEntity.ok(DataResponse.ok()); + } + + @PostMapping("/sell") + public ResponseEntity> sellStock(InternationalOrderStockRequest request) { + Member member = memberLoader.getMember(); + + internationalStockService.orderStock(member, request, false); + + return ResponseEntity.ok(DataResponse.ok()); + } +} diff --git a/backend/src/main/java/kakaobootcamp/backend/domains/stock/dto/InternationalStockDTO.java b/backend/src/main/java/kakaobootcamp/backend/domains/stock/dto/InternationalStockDTO.java new file mode 100644 index 0000000..93daedb --- /dev/null +++ b/backend/src/main/java/kakaobootcamp/backend/domains/stock/dto/InternationalStockDTO.java @@ -0,0 +1,67 @@ +package kakaobootcamp.backend.domains.stock.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.Getter; +import lombok.NoArgsConstructor; + +public class InternationalStockDTO { + + @Data + @AllArgsConstructor(access = AccessLevel.PRIVATE) + @Builder + public static class InternationalOrderStockRequest { + + @JsonProperty("CANO") + private String CANO; // 고객계좌번호 + + @JsonProperty("ACNT_PRDT_CD") + private String ACNT_PRDT_CD; // 계좌상품코드 + + @JsonProperty("OVRS_EXCG_CD") + private String OVRS_EXCG_CD; // 해외거래소코드 + + @JsonProperty("PDNO") + private String PDNO; // 종목코드 (6자리, 최대 12자리) + + @JsonProperty("ORD_QTY") + private String ORD_QTY; // 주문수량 (최대 10자리) + + @JsonProperty("OVRS_ORD_UNPR") + private String OVRS_ORD_UNPR; // 해외주문단가 (최대 10자리) + + @JsonProperty("SLL_TYPE") + private final String SLL_TYPE; + + @JsonProperty("ORD_SVR_DVSN_CD") + private final String ORD_SVR_DVSN_CD; + + @JsonProperty("ORD_DVSN") + private String ORD_DVSN; + } + + @Getter + @NoArgsConstructor(access = AccessLevel.PRIVATE) + public static class OrderStockResponse extends KisBaseResponse { + // 출력 데이터 + private Output output; + + @Getter + @NoArgsConstructor(access = AccessLevel.PRIVATE) + public static class Output { + + // KRX 전달 주문 원본 번호 + private String KRX_FWDG_ORD_ORGNO; + + // 주문 번호 + private String ODNO; + + // 주문 시간 + private String ORD_TMD; + } + } +} diff --git a/backend/src/main/java/kakaobootcamp/backend/domains/stock/service/InternationalStockService.java b/backend/src/main/java/kakaobootcamp/backend/domains/stock/service/InternationalStockService.java new file mode 100644 index 0000000..d8b1684 --- /dev/null +++ b/backend/src/main/java/kakaobootcamp/backend/domains/stock/service/InternationalStockService.java @@ -0,0 +1,80 @@ +package kakaobootcamp.backend.domains.stock.service; + +import static kakaobootcamp.backend.common.exception.ErrorCode.*; + +import java.util.HashMap; +import java.util.Map; + +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Service; + +import kakaobootcamp.backend.common.exception.ApiException; +import kakaobootcamp.backend.common.properties.KisProperties; +import kakaobootcamp.backend.common.util.webClient.WebClientUtil; +import kakaobootcamp.backend.domains.broker.KisAccessToken; +import kakaobootcamp.backend.domains.broker.service.KisAccessTokenService; +import kakaobootcamp.backend.domains.member.MemberService; +import kakaobootcamp.backend.domains.member.domain.Member; +import kakaobootcamp.backend.domains.stock.dto.InternationalStockDTO.InternationalOrderStockRequest; +import kakaobootcamp.backend.domains.stock.dto.InternationalStockDTO.OrderStockResponse; +import kakaobootcamp.backend.domains.stock.dto.KisBaseResponse; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class InternationalStockService { + + private final KisProperties kisProperties; + private final KisAccessTokenService kisAccessTokenService; + private final MemberService memberService; + private final WebClientUtil webClientUtil; + + // 헤더 설정 + private Map makeHeaders(Member member, String trId) { + KisAccessToken kisAccessToken = kisAccessTokenService.findKisAccessToken(member.getId()) + .orElseThrow(() -> ApiException.from(KIS_ACCESS_TOKEN_NOT_FOUND)); + String accessToken = kisAccessToken.getAccessToken(); + + Map headers = new HashMap<>(); + headers.put("authorization", accessToken); + headers.put("appkey", memberService.getDecryptedAppKey(member)); + headers.put("appsecret", memberService.getDecryptedSecretKey(member)); + headers.put("tr_id", trId); + + return headers; + } + + // 응답 확인 + private void checkResponse(KisBaseResponse response) { + if (!response.getRt_cd().equals("0")) { + throw ApiException.of(HttpStatus.BAD_REQUEST, response.getMsg1()); + } + } + + // TrId 조회 + private String getTrId(boolean isBuy) { + if (isBuy) { + return kisProperties.getInternational().getBuyTrId(); + } else { + return kisProperties.getInternational().getSellTrId(); + } + } + + // 주식 사기 + public void orderStock(Member member, InternationalOrderStockRequest request, boolean isBuy) { + String uri = "/uapi/overseas-stock/v1/trading/order"; + String trId = getTrId(isBuy); + + // 헤더 설정 + Map headers = makeHeaders(member, trId); + + // 본문 설정 + OrderStockResponse response = webClientUtil.postFromKis( + headers, + uri, + request, + OrderStockResponse.class); + + checkResponse(response); + } +}