From 2ad9c439eab0af729e5c4b391546f19f7d3cfe33 Mon Sep 17 00:00:00 2001 From: woody35545 Date: Tue, 14 May 2024 15:34:40 +0900 Subject: [PATCH 01/53] =?UTF-8?q?modify:=20`PaymentController`=20-=20?= =?UTF-8?q?=EC=9D=BC=EB=B6=80=20uri=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/PaymentController.java | 65 +++++++++---------- 1 file changed, 29 insertions(+), 36 deletions(-) diff --git a/src/main/java/com/t3t/frontserver/payments/controller/PaymentController.java b/src/main/java/com/t3t/frontserver/payments/controller/PaymentController.java index 420c5692..f8e0600b 100644 --- a/src/main/java/com/t3t/frontserver/payments/controller/PaymentController.java +++ b/src/main/java/com/t3t/frontserver/payments/controller/PaymentController.java @@ -1,51 +1,44 @@ - package com.t3t.frontserver.payments.controller; +package com.t3t.frontserver.payments.controller; - import org.springframework.beans.factory.annotation.Value; - import org.springframework.stereotype.Controller; - import org.springframework.ui.Model; - import org.springframework.web.bind.annotation.*; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.*; - import javax.servlet.http.HttpServletRequest; +@Controller +public class PaymentController { + @Value("${t3t.feignClient.url}") + private String feignClientUrl; + @GetMapping("/payment") + public String paymentCheckoutView(Model model) { - @Controller - public class PaymentController { + model.addAttribute("amount", 50000); - @Value("${t3t.feignClient.url}") - private String feignClientUrl; - - @GetMapping("/payments") - public String index(HttpServletRequest request , - Model model) throws Exception { + return "main/payments/checkout"; + } - model.addAttribute("amount", 50000); - return "main/payments/checkout"; - } + + @GetMapping("/payment/success") + public String paymentRequest(Model model, @RequestParam String paymentKey, @RequestParam String orderId, @RequestParam String amount) { - @GetMapping("payments/success") - public String paymentRequest(@RequestParam String paymentKey, - @RequestParam String orderId, - @RequestParam String amount, - Model model) throws Exception { - model.addAttribute("feignClientUrl", feignClientUrl); - model.addAttribute("paymentKey", paymentKey); - model.addAttribute("orderId", orderId); - model.addAttribute("amount", amount); - return "main/payments/success"; - } + model.addAttribute("feignClientUrl", feignClientUrl); + model.addAttribute("paymentKey", paymentKey); + model.addAttribute("orderId", orderId); + model.addAttribute("amount", amount); + return "main/payments/success"; + } - @GetMapping("payments/fail") - public String failPayment(@RequestParam String failCode, - @RequestParam String failMessage, - Model model) throws Exception { - model.addAttribute("code", failCode); - model.addAttribute("message", failMessage); - return "main/payments/fail"; - } + @GetMapping("/payment/fail") + public String failPayment(Model model, @RequestParam String failCode, @RequestParam String failMessage) { + model.addAttribute("code", failCode); + model.addAttribute("message", failMessage); + return "main/payments/fail"; } +} From 2987c995b4a0299210b58f43bbdd38b986b2ef58 Mon Sep 17 00:00:00 2001 From: woody35545 Date: Tue, 14 May 2024 15:35:25 +0900 Subject: [PATCH 02/53] =?UTF-8?q?modify:=20=ED=8C=A8=ED=82=A4=EC=A7=80?= =?UTF-8?q?=EB=AA=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../t3t/frontserver/{payments => payment}/config/MvcConfig.java | 2 +- .../{payments => payment}/controller/PaymentController.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename src/main/java/com/t3t/frontserver/{payments => payment}/config/MvcConfig.java (93%) rename src/main/java/com/t3t/frontserver/{payments => payment}/controller/PaymentController.java (96%) diff --git a/src/main/java/com/t3t/frontserver/payments/config/MvcConfig.java b/src/main/java/com/t3t/frontserver/payment/config/MvcConfig.java similarity index 93% rename from src/main/java/com/t3t/frontserver/payments/config/MvcConfig.java rename to src/main/java/com/t3t/frontserver/payment/config/MvcConfig.java index b1e3d20a..c123dfae 100644 --- a/src/main/java/com/t3t/frontserver/payments/config/MvcConfig.java +++ b/src/main/java/com/t3t/frontserver/payment/config/MvcConfig.java @@ -1,4 +1,4 @@ -package com.t3t.frontserver.payments.config; +package com.t3t.frontserver.payment.config; import org.springframework.context.annotation.Configuration; import org.springframework.http.CacheControl; diff --git a/src/main/java/com/t3t/frontserver/payments/controller/PaymentController.java b/src/main/java/com/t3t/frontserver/payment/controller/PaymentController.java similarity index 96% rename from src/main/java/com/t3t/frontserver/payments/controller/PaymentController.java rename to src/main/java/com/t3t/frontserver/payment/controller/PaymentController.java index f8e0600b..73c44f12 100644 --- a/src/main/java/com/t3t/frontserver/payments/controller/PaymentController.java +++ b/src/main/java/com/t3t/frontserver/payment/controller/PaymentController.java @@ -1,4 +1,4 @@ -package com.t3t.frontserver.payments.controller; +package com.t3t.frontserver.payment.controller; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Controller; From 48ebafcbd344b341b3ef140040431cc4d41bb5c7 Mon Sep 17 00:00:00 2001 From: woody35545 Date: Tue, 14 May 2024 15:50:28 +0900 Subject: [PATCH 03/53] =?UTF-8?q?feat:=20#96=20`PaymentProviderType`=20-?= =?UTF-8?q?=20=EA=B2=B0=EC=A0=9C=20=EC=84=9C=EB=B9=84=EC=8A=A4=20=EC=A0=9C?= =?UTF-8?q?=EA=B3=B5=EC=9E=90=EC=9D=98=20=EC=A2=85=EB=A5=98=EB=A5=BC=20?= =?UTF-8?q?=EB=82=98=ED=83=80=EB=82=B4=EB=8A=94=20enum?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../payment/constant/PaymentProviderType.java | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 src/main/java/com/t3t/frontserver/payment/constant/PaymentProviderType.java diff --git a/src/main/java/com/t3t/frontserver/payment/constant/PaymentProviderType.java b/src/main/java/com/t3t/frontserver/payment/constant/PaymentProviderType.java new file mode 100644 index 00000000..693a78b2 --- /dev/null +++ b/src/main/java/com/t3t/frontserver/payment/constant/PaymentProviderType.java @@ -0,0 +1,10 @@ +package com.t3t.frontserver.payment.constant; + +/** + * 결제 서비스 제공자의 종류를 나타내는 enum
+ * + * @author woody35545(구건모) + */ +public enum PaymentProviderType { + TOSS, NAVER +} From 61eef877c84d95ad761d877a3013b7294a15f9f4 Mon Sep 17 00:00:00 2001 From: woody35545 Date: Tue, 14 May 2024 15:53:37 +0900 Subject: [PATCH 04/53] =?UTF-8?q?feat:=20#98=20`MemberOrderPreparationRequ?= =?UTF-8?q?est`=20-=20=EA=B2=B0=EC=A0=9C=20=EB=8C=80=EA=B8=B0=20=EC=83=81?= =?UTF-8?q?=ED=83=9C=EC=9D=98=20=EC=A3=BC=EB=AC=B8=20=EC=83=9D=EC=84=B1=20?= =?UTF-8?q?=EC=9A=94=EC=B2=AD=EC=97=90=20=EB=8C=80=ED=95=9C=20DTO=20?= =?UTF-8?q?=ED=81=B4=EB=9E=98=EC=8A=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MemberOrderPreparationRequest.java | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 src/main/java/com/t3t/frontserver/order/model/request/MemberOrderPreparationRequest.java diff --git a/src/main/java/com/t3t/frontserver/order/model/request/MemberOrderPreparationRequest.java b/src/main/java/com/t3t/frontserver/order/model/request/MemberOrderPreparationRequest.java new file mode 100644 index 00000000..ccbe37dd --- /dev/null +++ b/src/main/java/com/t3t/frontserver/order/model/request/MemberOrderPreparationRequest.java @@ -0,0 +1,89 @@ +package com.t3t.frontserver.order.model.request; + +import com.t3t.frontserver.payment.constant.PaymentProviderType; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.lang.Nullable; + +import javax.validation.constraints.*; +import java.time.LocalDate; +import java.util.List; + +/** + * 결제 대기 상태의 주문 생성 요청에 대한 DTO 클래스 + * + * @auhtor woody35545(구건모) + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class MemberOrderPreparationRequest { + + /** + * 회원 정보 + */ + @NotNull(message = "주문인의 회원 식별자가 누락되었습니다.") + private Long memberId; // 주문인 + + /** + * 결제 정보 + */ + @NotNull(message = "결제 제공자가 누락되었습니다.") + private PaymentProviderType paymentProviderType; // 결제 제공자 + + /** + * 주문 상세 정보 (상품, 수량, 포장 정보) + */ + @NotEmpty(message = "주문 상세 정보가 누락되었습니다.") + private List orderDetailInfoList; // 주문 상세 정보 + + /** + * 배송 정보 + */ + @Nullable + private Integer addressNumber; // 배송 우편 주소 + + @Nullable + private String roadnameAddress; // 배송 도로명 주소 + + @NotNull(message = "배송 상세 주소가 누락되었습니다.") + private String detailAddress; // 배송 상세 주소 + + @NotNull(message = "희망 배송 일자가 누락되었습니다.") + @Future(message = "희망 배송 일자는 현재 날짜보다 이후 날짜여야 합니다.") + private LocalDate deliveryDate; // 희망 배송 일자 + + @NotBlank(message = "수령인 이름이 누락되었습니다.") + private String recipientName; // 배송 수령인 이름 + + @NotBlank(message = "수령인 전화번호가 누락되었습니다.") + @Pattern(regexp = "^\\d{3}-\\d{4}-\\d{4}$", message = "올바른 전화번호 형식이 아닙니다. (예시: 010-1234-5678)") + private String recipientPhoneNumber; // 배송 수령인 전화번호 + + @AssertTrue(message = "우편 주소와 도로명 주소 중 하나는 반드시 입력되어야 합니다.") + private boolean isEitherAddressNotNull() { + return addressNumber != null || roadnameAddress != null; + } + + /** + * 주문 상세 생성에 필요한 정보
+ * 주문 상품, 수량, 포장 정보를 가지고 있다. + * + * @auhtor woody35545(구건모) + */ + @Data + @Builder + @AllArgsConstructor + @NoArgsConstructor + public static class OrderDetailInfo { + @NotNull(message = "책 식별자가 누락되었습니다.") + private Long bookId; // 책 식별자 + @NotNull(message = "수량이 누락되었습니다.") + private Integer quantity; // 주문 수량 + @Nullable + private Long packagingId; // 포장 식별자 + } +} \ No newline at end of file From 8f3fb9fd3c3ae5961e1fa8325c755f6c5b9870c5 Mon Sep 17 00:00:00 2001 From: woody35545 Date: Tue, 14 May 2024 15:56:13 +0900 Subject: [PATCH 05/53] =?UTF-8?q?feat:=20#98=20`MemberOrderPreparationResp?= =?UTF-8?q?onse`=20-=20=ED=9A=8C=EC=9B=90=20=EC=9E=84=EC=8B=9C=20=EC=A3=BC?= =?UTF-8?q?=EB=AC=B8=20=EC=83=9D=EC=84=B1=EC=97=90=20=EB=8C=80=ED=95=9C=20?= =?UTF-8?q?=EC=9D=91=EB=8B=B5=20=EA=B0=9D=EC=B2=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MemberOrderPreparationResponse.java | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 src/main/java/com/t3t/frontserver/order/model/response/MemberOrderPreparationResponse.java diff --git a/src/main/java/com/t3t/frontserver/order/model/response/MemberOrderPreparationResponse.java b/src/main/java/com/t3t/frontserver/order/model/response/MemberOrderPreparationResponse.java new file mode 100644 index 00000000..23e5907d --- /dev/null +++ b/src/main/java/com/t3t/frontserver/order/model/response/MemberOrderPreparationResponse.java @@ -0,0 +1,41 @@ +package com.t3t.frontserver.order.model.response; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; + +/** + * 회원 임시 주문 생성에 대한 응답 객체 + * + * @auhtor woody35545(구건모) + */ + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MemberOrderPreparationResponse { + /** + * 회원 정보 + */ + private Long memberId; // 회원 식별자 + + /** + * 생성된 주문 정보 + */ + private Long orderId; // 주문 식별자 + + /** + * 결제 관련 정보 + */ + private String providerOrderId; // 결제 제공자측에서 사용할 주문 식별자 + private BigDecimal totalPrice; // 총 결제해야 할 금액 + + /** + * 배송 정보 + */ + private Long deliveryId; // 배송 정보 식별자 +} \ No newline at end of file From 4dc60498020058635ed7cdf8a6fc3d7e8e0fa619 Mon Sep 17 00:00:00 2001 From: woody35545 Date: Tue, 14 May 2024 15:59:58 +0900 Subject: [PATCH 06/53] =?UTF-8?q?feat:=20#48=20`OrderApiClientException`?= =?UTF-8?q?=20-=20=EC=A3=BC=EB=AC=B8=20API=20=ED=81=B4=EB=9D=BC=EC=9D=B4?= =?UTF-8?q?=EC=96=B8=ED=8A=B8=20=ED=98=B8=EC=B6=9C=20=EC=A4=91=20=EB=B0=9C?= =?UTF-8?q?=EC=83=9D=ED=95=98=EB=8A=94=20=EC=98=88=EC=99=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../exception/OrderApiClientException.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 src/main/java/com/t3t/frontserver/order/exception/OrderApiClientException.java diff --git a/src/main/java/com/t3t/frontserver/order/exception/OrderApiClientException.java b/src/main/java/com/t3t/frontserver/order/exception/OrderApiClientException.java new file mode 100644 index 00000000..4526b428 --- /dev/null +++ b/src/main/java/com/t3t/frontserver/order/exception/OrderApiClientException.java @@ -0,0 +1,18 @@ +package com.t3t.frontserver.order.exception; + +/** + * 주문 API 클라이언트 호출 중 발생하는 예외 + * + * @auhtor woody35545(구건모) + */ +public class OrderApiClientException extends RuntimeException { + private static final String DEFAULT_MESSAGE = "주문 API 클라이언트 호출 중 예외 발생"; + + public OrderApiClientException() { + super(DEFAULT_MESSAGE); + } + + public OrderApiClientException(String reason) { + super(DEFAULT_MESSAGE + " " + reason); + } +} \ No newline at end of file From 406cd669ef00ca98921682199e73a97932eb00bc Mon Sep 17 00:00:00 2001 From: woody35545 Date: Tue, 14 May 2024 16:00:11 +0900 Subject: [PATCH 07/53] =?UTF-8?q?feat:=20#98=20`OrderApiClient`=20-=20?= =?UTF-8?q?=ED=9A=8C=EC=9B=90=20=EC=A3=BC=EB=AC=B8=20=EC=83=9D=EC=84=B1=20?= =?UTF-8?q?API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../order/client/OrderApiClient.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 src/main/java/com/t3t/frontserver/order/client/OrderApiClient.java diff --git a/src/main/java/com/t3t/frontserver/order/client/OrderApiClient.java b/src/main/java/com/t3t/frontserver/order/client/OrderApiClient.java new file mode 100644 index 00000000..0dc3dec8 --- /dev/null +++ b/src/main/java/com/t3t/frontserver/order/client/OrderApiClient.java @@ -0,0 +1,23 @@ +package com.t3t.frontserver.order.client; + +import com.t3t.frontserver.model.response.BaseResponse; +import com.t3t.frontserver.order.model.request.MemberOrderPreparationRequest; +import com.t3t.frontserver.order.model.response.MemberOrderPreparationResponse; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; + +@FeignClient(name = "OrderApiClient", url = "${t3t.feignClient.url}") +public interface OrderApiClient { + + /** + * 회원 주문 생성 API
+ * 결제 대기 상태의 주문을 생성한다. + * + * @author woody35545(구건모) + */ + @PostMapping(value = "/t3t/bookstore/orders/member") + ResponseEntity> createMemberOrder(@RequestBody MemberOrderPreparationRequest memberOrderPreparationRequest); + +} \ No newline at end of file From 1024b4ac70c7f45eb2a24b1239cff4a93fee071c Mon Sep 17 00:00:00 2001 From: woody35545 Date: Tue, 14 May 2024 16:03:29 +0900 Subject: [PATCH 08/53] =?UTF-8?q?feat:=20#98=20`OrderAdaptor`=20-=20?= =?UTF-8?q?=ED=9A=8C=EC=9B=90=20=EC=A3=BC=EB=AC=B8=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../order/adaptor/OrderAdaptor.java | 35 +++++++++++++++++++ .../exception/OrderApiClientException.java | 2 +- 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/t3t/frontserver/order/adaptor/OrderAdaptor.java diff --git a/src/main/java/com/t3t/frontserver/order/adaptor/OrderAdaptor.java b/src/main/java/com/t3t/frontserver/order/adaptor/OrderAdaptor.java new file mode 100644 index 00000000..b536b5a0 --- /dev/null +++ b/src/main/java/com/t3t/frontserver/order/adaptor/OrderAdaptor.java @@ -0,0 +1,35 @@ +package com.t3t.frontserver.order.adaptor; + +import com.t3t.frontserver.model.response.BaseResponse; +import com.t3t.frontserver.order.client.OrderApiClient; +import com.t3t.frontserver.order.exception.OrderApiClientException; +import com.t3t.frontserver.order.model.request.MemberOrderPreparationRequest; +import com.t3t.frontserver.order.model.response.MemberOrderPreparationResponse; +import com.t3t.frontserver.util.FeignClientUtils; +import feign.FeignException; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.Optional; + +@Component +@RequiredArgsConstructor +public class OrderAdaptor { + private final OrderApiClient orderApiClient; + + /** + * 회원 주문 생성 + * 결제 대기 상태의 주문을 생성한다. + * + * @author woody35545(구건모) + */ + public MemberOrderPreparationResponse createMemberOrder(MemberOrderPreparationRequest request) { + try { + return Optional.ofNullable(orderApiClient.createMemberOrder(request).getBody()) + .map(BaseResponse::getData) + .orElseThrow(RuntimeException::new); + } catch (FeignException e) { + throw new OrderApiClientException("주문 생성에 실패하였습니다. " + FeignClientUtils.getMessageFromFeignException(e)); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/t3t/frontserver/order/exception/OrderApiClientException.java b/src/main/java/com/t3t/frontserver/order/exception/OrderApiClientException.java index 4526b428..9504eeed 100644 --- a/src/main/java/com/t3t/frontserver/order/exception/OrderApiClientException.java +++ b/src/main/java/com/t3t/frontserver/order/exception/OrderApiClientException.java @@ -6,7 +6,7 @@ * @auhtor woody35545(구건모) */ public class OrderApiClientException extends RuntimeException { - private static final String DEFAULT_MESSAGE = "주문 API 클라이언트 호출 중 예외 발생"; + private static final String DEFAULT_MESSAGE = "주문 API 호출에 실패하였습니다."; public OrderApiClientException() { super(DEFAULT_MESSAGE); From 6cf5d0ae49de1243221ac1e0ea6deec3224cf643 Mon Sep 17 00:00:00 2001 From: woody35545 Date: Tue, 14 May 2024 16:04:33 +0900 Subject: [PATCH 09/53] =?UTF-8?q?feat:=20#98=20`OrderService`=20-=20?= =?UTF-8?q?=ED=9A=8C=EC=9B=90=20=EC=A3=BC=EB=AC=B8=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../order/service/OrderService.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 src/main/java/com/t3t/frontserver/order/service/OrderService.java diff --git a/src/main/java/com/t3t/frontserver/order/service/OrderService.java b/src/main/java/com/t3t/frontserver/order/service/OrderService.java new file mode 100644 index 00000000..0d8cea9e --- /dev/null +++ b/src/main/java/com/t3t/frontserver/order/service/OrderService.java @@ -0,0 +1,24 @@ +package com.t3t.frontserver.order.service; + + +import com.t3t.frontserver.order.adaptor.OrderAdaptor; +import com.t3t.frontserver.order.model.request.MemberOrderPreparationRequest; +import com.t3t.frontserver.order.model.response.MemberOrderPreparationResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class OrderService { + private final OrderAdaptor orderAdaptor; + + /** + * 회원 주문 생성 + * 결제 대기 상태의 주문을 생성한다. + * + * @author woody35545(구건모) + */ + public MemberOrderPreparationResponse createMemberOrder(MemberOrderPreparationRequest memberOrderPreparationRequest) { + return orderAdaptor.createMemberOrder(memberOrderPreparationRequest); + } +} \ No newline at end of file From fa0c78dc05b02f9b66eb82c6312d8070c3c83e28 Mon Sep 17 00:00:00 2001 From: woody35545 Date: Tue, 14 May 2024 16:06:09 +0900 Subject: [PATCH 10/53] =?UTF-8?q?modify:=20`detail.html`=20-=20=EC=A3=BC?= =?UTF-8?q?=EB=AC=B8=ED=95=98=EA=B8=B0=20=EB=A7=81=ED=81=AC=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/templates/main/page/detail.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/templates/main/page/detail.html b/src/main/resources/templates/main/page/detail.html index 2d0049ae..c0b48d81 100644 --- a/src/main/resources/templates/main/page/detail.html +++ b/src/main/resources/templates/main/page/detail.html @@ -107,7 +107,7 @@

Book Name포장 선택이 불가능합니다.

- From 51da8e361571c1991ed40396f19fc336fb7594f9 Mon Sep 17 00:00:00 2001 From: woody35545 Date: Tue, 14 May 2024 16:07:47 +0900 Subject: [PATCH 11/53] =?UTF-8?q?feat:=20#98=20`OrderCheckoutViewDto`=20-?= =?UTF-8?q?=20=EC=A3=BC=EB=AC=B8=20=ED=8E=98=EC=9D=B4=EC=A7=80=EC=97=90=20?= =?UTF-8?q?=ED=95=84=EC=9A=94=ED=95=9C=20=EC=A0=95=EB=B3=B4=EB=A5=BC=20?= =?UTF-8?q?=EB=8B=B4=EB=8A=94=20DTO?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../order/model/dto/OrderCheckoutViewDto.java | 126 ++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 src/main/java/com/t3t/frontserver/order/model/dto/OrderCheckoutViewDto.java diff --git a/src/main/java/com/t3t/frontserver/order/model/dto/OrderCheckoutViewDto.java b/src/main/java/com/t3t/frontserver/order/model/dto/OrderCheckoutViewDto.java new file mode 100644 index 00000000..f676d1ec --- /dev/null +++ b/src/main/java/com/t3t/frontserver/order/model/dto/OrderCheckoutViewDto.java @@ -0,0 +1,126 @@ +package com.t3t.frontserver.order.model.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.lang.Nullable; + +import java.math.BigDecimal; +import java.util.List; + +/** + * 주문 페이지에 필요한 정보를 담는 DTO + * + * @author woody35545(구건모) + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class OrderCheckoutViewDto { + + /** + * 주문인 정보 + * 비회원의 경우 null 이 될 수 있다. + */ + @Nullable + private Long memberId; // 주문인의 회원 식별자 + @Nullable + private String memberName; // 주문인 이름 + @Nullable + private String memberPhoneNumber; // 주문인 휴대전화 번호 + + /** + * 사용자 배송 주소록 정보 + * 사용자가 어떠한 주소도 등록하지 않은 경우 null 또는 empty 가 될 수 있다. + */ + @Nullable + private List addressInfoList; // 회원이 등록한 주소 리스트 + + /** + * 주문 관련 정보 + * 단건의 상품을 구매하더라도 List 로 받아서 처리한다. + */ + private List orderDetailInfoList; // 주문 상세 정보 + + + /** + * 지불 금액 관련 정보 + * 사용자가 선택한 상품, 포장, 쿠폰 등에 따라 적절히 계산되어 설정된다. + */ + private BigDecimal totalOrderPrice; // 상품 총 주문 금액 + private BigDecimal totalPackagingPrice; // 포장 금액 + private BigDecimal deliveryPrice; // 배송료 + private BigDecimal totalDiscountPrice; // 총 할인 금액 + private BigDecimal totalPaymentPrice; // 결제 총액(남은 결제 금액) + + /** + * 회원 주소 정보 + */ + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class MemberAddressInfo { + private Long id; // MemberAddress 식별자 + private String roadNameAddress; // 도로명 주소 + private String addressDetail; // 상세 주소 + private String nickName; // 주소 별칭 + private Boolean isDefault; // 기본 주소 여부 + } + + /** + * 주문 상세 정보 + */ + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class OrderDetailInfo { + + /** + * 상품 정보 + */ + private Long bookId; // 책 식별자 + private String bookName; // 책 이름 + private String publisher; // 출판사 이름 + private Integer quantity; // 책 수량 + private BigDecimal price; // 책 가격 + private BigDecimal discountedPrice; // 확인 필요) + private BigDecimal discountRate; // 책 할인율 + private BigDecimal totalPrice; // 책 총 가격 + + /** + * 포장 정보 + * 포장지를 사용하지 않을 경우 포장지 관련 필드는 null 이 될 수 있다. + */ + @Nullable + private Long packagingId; // 포장지 식별자 + @Nullable + private String packagingName; // 포장지 이름 + @Nullable + private BigDecimal packagingPrice; // 포장지 가격 + } + + /** + * 쿠폰 정보 + * 아직 쿠폰이 구현되지 않은 상태이므로 임의로 구성하였다. + * 따라서 추후에 변경될 수 있다. + * 쿠폰을 사용하지 않을 경우 null 이 될 수 있다. + */ + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class CouponInfo { + @Nullable + private Long couponId; // 쿠폰 식별자 + @Nullable + private String couponName; // 쿠폰 이름 + @Nullable + private BigDecimal discountPrice; // 할인 금액 + @Nullable + private BigDecimal discountRate; // 할인율 + } +} \ No newline at end of file From 109a56f52ed2b3b68de3b39312dfb6b4de23fac5 Mon Sep 17 00:00:00 2001 From: woody35545 Date: Tue, 14 May 2024 16:20:14 +0900 Subject: [PATCH 12/53] =?UTF-8?q?feat:=20`BookApiClientException`=20-=20Bo?= =?UTF-8?q?okApiClient=20=EB=A1=9C=20=EB=8F=84=EC=84=9C=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20API=20=ED=98=B8=EC=B6=9C=20=EC=8B=A4=ED=8C=A8?= =?UTF-8?q?=EC=8B=9C=20=EB=B0=9C=EC=83=9D=ED=95=98=EB=8A=94=20=EC=98=88?= =?UTF-8?q?=EC=99=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../book/exception/BookApiClientException.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 src/main/java/com/t3t/frontserver/book/exception/BookApiClientException.java diff --git a/src/main/java/com/t3t/frontserver/book/exception/BookApiClientException.java b/src/main/java/com/t3t/frontserver/book/exception/BookApiClientException.java new file mode 100644 index 00000000..5239c1b4 --- /dev/null +++ b/src/main/java/com/t3t/frontserver/book/exception/BookApiClientException.java @@ -0,0 +1,12 @@ +package com.t3t.frontserver.book.exception; + +/** + * BookApiClient 로 도서 관련 API 호출 실패시 발생하는 예외 + * + * @author woody35545(구건모) + */ +public class BookApiClientException extends RuntimeException { + public BookApiClientException(String message) { + super(message); + } +} \ No newline at end of file From 27b8b1ae835fa403e01f68d3ec5626c9238951c0 Mon Sep 17 00:00:00 2001 From: woody35545 Date: Wed, 15 May 2024 12:37:27 +0900 Subject: [PATCH 13/53] =?UTF-8?q?update:=20#98=20`MemberOrderPreparationRe?= =?UTF-8?q?quest`=20-=20=ED=9A=8C=EC=9B=90=20=EC=A3=BC=EC=86=8C=20?= =?UTF-8?q?=EC=8B=9D=EB=B3=84=EC=9E=90=20=ED=95=84=EB=93=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../order/model/request/MemberOrderPreparationRequest.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/t3t/frontserver/order/model/request/MemberOrderPreparationRequest.java b/src/main/java/com/t3t/frontserver/order/model/request/MemberOrderPreparationRequest.java index ccbe37dd..0c642d8e 100644 --- a/src/main/java/com/t3t/frontserver/order/model/request/MemberOrderPreparationRequest.java +++ b/src/main/java/com/t3t/frontserver/order/model/request/MemberOrderPreparationRequest.java @@ -43,6 +43,9 @@ public class MemberOrderPreparationRequest { /** * 배송 정보 */ + @Nullable + private Long memberAddressId; // 회원 주소록에서 주소를 선택한 경우 회원 주소 식별자 + @Nullable private Integer addressNumber; // 배송 우편 주소 @@ -65,7 +68,7 @@ public class MemberOrderPreparationRequest { @AssertTrue(message = "우편 주소와 도로명 주소 중 하나는 반드시 입력되어야 합니다.") private boolean isEitherAddressNotNull() { - return addressNumber != null || roadnameAddress != null; + return memberAddressId != null || addressNumber != null || roadnameAddress != null; } /** From b46602dfd3b02b1006537a66ea7d1e9d60409430 Mon Sep 17 00:00:00 2001 From: woody35545 Date: Wed, 15 May 2024 13:15:47 +0900 Subject: [PATCH 14/53] =?UTF-8?q?modify:=20`GlobalExceptionHandler`=20-=20?= =?UTF-8?q?=EC=98=88=EC=99=B8=20=EB=B0=9C=EC=83=9D=20=EC=8B=9C=20=EC=98=88?= =?UTF-8?q?=EC=99=B8=EC=97=90=20=EB=8C=80=ED=95=9C=20=EC=A0=95=EB=B3=B4?= =?UTF-8?q?=EB=A5=BC=20=EC=A0=9C=EA=B3=B5=ED=95=98=EB=8A=94=20=ED=95=B8?= =?UTF-8?q?=EB=93=A4=EB=9F=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../exception/GlobalExceptionHandler.java | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/t3t/frontserver/common/exception/GlobalExceptionHandler.java b/src/main/java/com/t3t/frontserver/common/exception/GlobalExceptionHandler.java index 4878003c..02392dd6 100644 --- a/src/main/java/com/t3t/frontserver/common/exception/GlobalExceptionHandler.java +++ b/src/main/java/com/t3t/frontserver/common/exception/GlobalExceptionHandler.java @@ -10,26 +10,25 @@ import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletResponse; +import java.util.Optional; @Slf4j @ControllerAdvice public class GlobalExceptionHandler { + /** + * 예외 발생 시 예외에 대한 정보를 제공하는 핸들러 + * + * @author 구건모(woody35545) + */ @ExceptionHandler(Exception.class) public String handleException(RedirectAttributes redirectAttributes, Exception e) { - redirectAttributes.addAttribute("message", e.getMessage()); + + redirectAttributes.addAttribute("message", + Optional.ofNullable(e.getMessage()).orElse("오류가 발생하였습니다. 잠시 후 다시 시도해주세요.")); + return "redirect:/message"; } -/* @ExceptionHandler(RestApiClientException.class) - public String handleUnAuthorizedException(Model model, RestApiClientException e, HttpServletResponse response) { - Cookie cookie = new Cookie("t3t", null); - cookie.setMaxAge(0); - cookie.setPath("/"); - SecurityContextHolder.clearContext(); - response.addCookie(cookie); - return "redirect:/login"; - }*/ - @ExceptionHandler(FeignException.Unauthorized.class) public String handleLogoutException(Model model, FeignException.Unauthorized e, HttpServletResponse response) { Cookie cookie = new Cookie("t3t", null); From 3079f5c69a1dabd5229555a525343d578a550220 Mon Sep 17 00:00:00 2001 From: woody35545 Date: Wed, 15 May 2024 14:01:26 +0900 Subject: [PATCH 15/53] =?UTF-8?q?modify:=20#96=20=EA=B2=B0=EC=A0=9C=20?= =?UTF-8?q?=EA=B4=80=EB=A0=A8=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=ED=8C=A8?= =?UTF-8?q?=ED=82=A4=EC=A7=80=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../templates/main/{payments => payment}/fail.html | 6 ++---- .../templates/main/{payments => payment}/success.html | 7 +++---- 2 files changed, 5 insertions(+), 8 deletions(-) rename src/main/resources/templates/main/{payments => payment}/fail.html (86%) rename src/main/resources/templates/main/{payments => payment}/success.html (92%) diff --git a/src/main/resources/templates/main/payments/fail.html b/src/main/resources/templates/main/payment/fail.html similarity index 86% rename from src/main/resources/templates/main/payments/fail.html rename to src/main/resources/templates/main/payment/fail.html index b15667e4..c46517de 100644 --- a/src/main/resources/templates/main/payments/fail.html +++ b/src/main/resources/templates/main/payment/fail.html @@ -8,10 +8,8 @@

- + 결제 실패

diff --git a/src/main/resources/templates/main/payments/success.html b/src/main/resources/templates/main/payment/success.html similarity index 92% rename from src/main/resources/templates/main/payments/success.html rename to src/main/resources/templates/main/payment/success.html index 5df23469..9c2883de 100644 --- a/src/main/resources/templates/main/payments/success.html +++ b/src/main/resources/templates/main/payment/success.html @@ -8,12 +8,11 @@

- + 결제 성공

+

From 300a57d10c40719f1981c031ecdeca57fd6b2b79 Mon Sep 17 00:00:00 2001 From: woody35545 Date: Wed, 15 May 2024 14:02:02 +0900 Subject: [PATCH 16/53] =?UTF-8?q?feat:=20#96=20=ED=86=A0=EC=8A=A4=20?= =?UTF-8?q?=EA=B2=B0=EC=A0=9C=20=EC=A0=95=EC=B1=85=20=EB=B3=80=EA=B2=BD?= =?UTF-8?q?=EC=97=90=20=EB=94=B0=EB=A5=B8=20=EA=B2=B0=EC=A0=9C=20=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../templates/main/payment/checkout.html | 25 ++++++++ .../templates/main/payments/checkout.html | 58 ------------------- 2 files changed, 25 insertions(+), 58 deletions(-) create mode 100644 src/main/resources/templates/main/payment/checkout.html delete mode 100644 src/main/resources/templates/main/payments/checkout.html diff --git a/src/main/resources/templates/main/payment/checkout.html b/src/main/resources/templates/main/payment/checkout.html new file mode 100644 index 00000000..3b54db84 --- /dev/null +++ b/src/main/resources/templates/main/payment/checkout.html @@ -0,0 +1,25 @@ + + + + + + + \ No newline at end of file diff --git a/src/main/resources/templates/main/payments/checkout.html b/src/main/resources/templates/main/payments/checkout.html deleted file mode 100644 index 3fd64b48..00000000 --- a/src/main/resources/templates/main/payments/checkout.html +++ /dev/null @@ -1,58 +0,0 @@ - - - - - -
-
- - -
- -
- -
- -
-
-
-
> - - - From eda778d1395ed0aec5f2ad2a5c66726301f05120 Mon Sep 17 00:00:00 2001 From: woody35545 Date: Wed, 15 May 2024 14:03:09 +0900 Subject: [PATCH 17/53] =?UTF-8?q?feat:=20#96=20`PaymentController`=20-=20?= =?UTF-8?q?=08=EC=9E=84=EC=8B=9C=20=EC=A3=BC=EB=AC=B8=20=EC=83=9D=EC=84=B1?= =?UTF-8?q?=20=EB=B0=8F=20=EA=B2=B0=EC=A0=9C=20=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../payment/controller/PaymentController.java | 61 +++++++++++++++++-- 1 file changed, 55 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/t3t/frontserver/payment/controller/PaymentController.java b/src/main/java/com/t3t/frontserver/payment/controller/PaymentController.java index 73c44f12..934a44a7 100644 --- a/src/main/java/com/t3t/frontserver/payment/controller/PaymentController.java +++ b/src/main/java/com/t3t/frontserver/payment/controller/PaymentController.java @@ -1,25 +1,70 @@ package com.t3t.frontserver.payment.controller; +import com.t3t.frontserver.auth.util.SecurityContextUtils; +import com.t3t.frontserver.order.model.request.MemberOrderPreparationRequest; +import com.t3t.frontserver.order.model.response.MemberOrderPreparationResponse; +import com.t3t.frontserver.order.service.OrderService; +import com.t3t.frontserver.payment.constant.PaymentProviderType; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestParam; +import java.time.LocalDate; + +@Slf4j @Controller +@RequiredArgsConstructor public class PaymentController { @Value("${t3t.feignClient.url}") private String feignClientUrl; - @GetMapping("/payment") - public String paymentCheckoutView(Model model) { + private final OrderService orderService; + + /** + * 결제 대기상태의 주문을 생성하고, 사용자가 결제를 진행할 수 있도록 결제 페이지를 반환한다. + * + * @author woody35545(구건모) + */ + @PostMapping("/payment") + public String paymentCheckoutView(Model model, @ModelAttribute MemberOrderPreparationRequest memberOrderPreparationRequest) { + + if (!SecurityContextUtils.isLoggedIn()) { + return "redirect:/login"; + } + + // 날짜 선택 관련 UI 적용 전까지 배송날짜 임시로 설정 + memberOrderPreparationRequest.setPaymentProviderType(PaymentProviderType.TOSS); + memberOrderPreparationRequest.setDeliveryDate(LocalDate.now().plusDays(3)); + log.info("memberOrderPreparationRequest => {}", memberOrderPreparationRequest); - model.addAttribute("amount", 50000); + // 결제 대기 상태의 주문 생성 + MemberOrderPreparationResponse memberOrderPreparationResponse = + orderService.createMemberOrder(memberOrderPreparationRequest); + log.info("memberOrderPreparationResponse => {}", memberOrderPreparationResponse); + + // 총 결제해야할 금액 + model.addAttribute("amount", memberOrderPreparationResponse.getTotalPrice()); + + // 결제 제공처에서 사용할 주문 식별자 + model.addAttribute("orderId", memberOrderPreparationResponse.getProviderOrderId()); return "main/payments/checkout"; } - + + /** + * 결제 페이지에서 결제 과정이 성공적으로 수행된 경우 이동되는 페이지로, + * 북스토어 백엔드측에 결제가 유효한지 검증을 요청하고 결제 대기 상태의 주문을 확정한다. + * + * @author woody35545(구건모) + */ @GetMapping("/payment/success") public String paymentRequest(Model model, @RequestParam String paymentKey, @RequestParam String orderId, @RequestParam String amount) { @@ -31,7 +76,11 @@ public String paymentRequest(Model model, @RequestParam String paymentKey, @Requ return "main/payments/success"; } - + /** + * 결제 실패시 이동하는 페이지로 사용자에게 결제 실패 사유에 대한 메시지를 제공한다. + * + * @author woody35545(구건모) + */ @GetMapping("/payment/fail") public String failPayment(Model model, @RequestParam String failCode, @RequestParam String failMessage) { From 55400e9bf3ed171b4dbc11250135b690f37f1dd5 Mon Sep 17 00:00:00 2001 From: woody35545 Date: Wed, 15 May 2024 14:04:35 +0900 Subject: [PATCH 18/53] =?UTF-8?q?feat:=20#48=20`orderCheckout.html`=20-=20?= =?UTF-8?q?=EC=A3=BC=EB=AC=B8=EC=84=9C=20=EC=9E=91=EC=84=B1=20=EB=B7=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../templates/main/page/orderCheckout.html | 230 ++++++++++++++++++ 1 file changed, 230 insertions(+) create mode 100644 src/main/resources/templates/main/page/orderCheckout.html diff --git a/src/main/resources/templates/main/page/orderCheckout.html b/src/main/resources/templates/main/page/orderCheckout.html new file mode 100644 index 00000000..6f65c83e --- /dev/null +++ b/src/main/resources/templates/main/page/orderCheckout.html @@ -0,0 +1,230 @@ + + + + + +
+
+ + + +

주문 상품 정보

+ + + + + + + + + + + + + + + + + + + + + +
상품명출판사주문 수량총금액
+
+ +

배송 정보

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
주문인 + + +
휴대전화번호 + + + + +
배송지 선택 +
+ + +
+
+ + +
+
주소 + +
받으시는 분 + + + + + +
+
+ +

추가 할인 받기

+
+
+ 보유 쿠폰 2 장
+ +

+ 할인 금액: 0 원 +
+
+
+ +

결제 내역 확인

+ + + + + + + + + + + + + + +
주문상품금액정보
+ 주문 금액:
+ 포장 금액:
+ 배송료:
+ 결제 총액:
+
+ 도서 할인 금액:
+ 쿠폰 할인 금액: 원 +
+ 남은 결제 금액:
+
+
+ +

결제 수단

+ + + + + + + + + +
+
+ + +
+
+
+ + +
+
+
+ + + +
+
+
+
+ +
+ From 88899a7abacf337bc7039fc0482edb96aec32bfa Mon Sep 17 00:00:00 2001 From: woody35545 Date: Wed, 15 May 2024 14:04:56 +0900 Subject: [PATCH 19/53] =?UTF-8?q?feat:=20#98=20`OrderController`=20-=20?= =?UTF-8?q?=ED=9A=8C=EC=9B=90=20=EB=B0=94=EB=A1=9C=20=EC=A3=BC=EB=AC=B8=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../order/controller/OrderController.java | 121 ++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 src/main/java/com/t3t/frontserver/order/controller/OrderController.java diff --git a/src/main/java/com/t3t/frontserver/order/controller/OrderController.java b/src/main/java/com/t3t/frontserver/order/controller/OrderController.java new file mode 100644 index 00000000..0ab813c5 --- /dev/null +++ b/src/main/java/com/t3t/frontserver/order/controller/OrderController.java @@ -0,0 +1,121 @@ +package com.t3t.frontserver.order.controller; + +import com.t3t.frontserver.auth.util.SecurityContextUtils; +import com.t3t.frontserver.book.client.BookApiClient; +import com.t3t.frontserver.book.exception.BookApiClientException; +import com.t3t.frontserver.book.model.response.BookDetailResponse; +import com.t3t.frontserver.index.OrderFormRequest; +import com.t3t.frontserver.member.model.dto.MemberAddressDto; +import com.t3t.frontserver.member.model.response.MemberInfoResponse; +import com.t3t.frontserver.member.service.MemberService; +import com.t3t.frontserver.model.response.BaseResponse; +import com.t3t.frontserver.order.model.dto.OrderCheckoutViewDto; +import com.t3t.frontserver.order.model.request.MemberOrderPreparationRequest; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PostMapping; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +@Slf4j +@Controller +@RequiredArgsConstructor +public class OrderController { + + private final MemberService memberService; + private final BookApiClient bookApiClient; + + /** + * 상품 상세에서 바로 주문할 때의 주문 정보 작성 및 확인 페이지 + * + * @author woody35545 + */ + @PostMapping("/order/checkout") + public String orderCheckoutView(@ModelAttribute OrderFormRequest request, Model model) { + + + MemberInfoResponse memberInfoResponse = new MemberInfoResponse(); + List memberAddressDtoList = new ArrayList<>(); + List memberAddressInfoList = new ArrayList<>(); + + log.info("[*] memberInfoResponse => {}", memberInfoResponse); + log.info("[*] memberAddressDtoList => {}", memberAddressDtoList); + log.info("[*] memberAddressInfoList => {}", memberAddressInfoList); + + if (SecurityContextUtils.isLoggedIn()) { + memberInfoResponse = memberService.getMemberInfoResponseById(SecurityContextUtils.getMemberId()); + memberAddressDtoList = memberService.getMemberAddressDtoListByMemberId(SecurityContextUtils.getMemberId()); + memberAddressInfoList = memberService.getMemberAddressDtoListByMemberId(SecurityContextUtils.getMemberId()) + .stream() + .map(addressDto -> OrderCheckoutViewDto.MemberAddressInfo.builder() + .id(addressDto.getId()) + .roadNameAddress(addressDto.getRoadNameAddress()) + .addressDetail(addressDto.getAddressDetail()) + .nickName(addressDto.getAddressNickname()) + .isDefault(addressDto.getIsDefaultAddress()) + .build()).collect(Collectors.toList()); + } + + + BookDetailResponse bookDetailResponse = Optional.ofNullable(bookApiClient.getBook(request.getBookId()).getBody()) + .map(BaseResponse::getData) + .orElseThrow(() -> new BookApiClientException("책 정보 조회 실패")); + + BigDecimal totalOrderPrice = BigDecimal.ZERO; // 상품 총 주문 금액 + BigDecimal totalPackagingPrice = BigDecimal.ZERO; // 포장 금액 + BigDecimal deliveryPrice = new BigDecimal("3000");// 배송료 (추후 변경 예정) + BigDecimal totalDiscountPrice = BigDecimal.ZERO; // 총 할인 금액 + BigDecimal totalPaymentPrice = BigDecimal.ZERO; // 결제 총액(남은 결제 금액) + + totalOrderPrice = totalOrderPrice.add( + bookDetailResponse.getPrice().multiply(BigDecimal.valueOf(request.getOrderQuantity()))); + + totalDiscountPrice = totalDiscountPrice.add( + bookDetailResponse.getPrice().subtract(bookDetailResponse.getDiscountedPrice()).multiply(BigDecimal.valueOf(request.getOrderQuantity()))); + + totalPaymentPrice = totalPaymentPrice.add( + totalOrderPrice.add(totalPackagingPrice).add(deliveryPrice).subtract(totalDiscountPrice)); + + log.info("[*] bookDetailResponse => {}", bookDetailResponse); + + OrderCheckoutViewDto.OrderDetailInfo orderDetailInfo = OrderCheckoutViewDto.OrderDetailInfo.builder() + .bookId(bookDetailResponse.getId()) + .bookName(bookDetailResponse.getBookName()) + .publisher(bookDetailResponse.getPublisherName()) + .price(bookDetailResponse.getPrice()) + .discountedPrice(bookDetailResponse.getDiscountedPrice()) + .discountRate(bookDetailResponse.getDiscountRate()) + .quantity(request.getOrderQuantity()) + .totalPrice(bookDetailResponse.getDiscountedPrice().multiply(BigDecimal.valueOf(request.getOrderQuantity()))) + .build(); + + log.info("[*] orderDetailInfo => {}", orderDetailInfo); + + OrderCheckoutViewDto orderCheckoutViewDto = OrderCheckoutViewDto.builder() + .memberId(memberInfoResponse.getMemberId()) + .memberName(memberInfoResponse.getName()) + .memberPhoneNumber(memberInfoResponse.getPhone()) + .addressInfoList(memberAddressInfoList) + .orderDetailInfoList(List.of(orderDetailInfo)) + .totalPackagingPrice(totalPackagingPrice) + .totalOrderPrice(totalOrderPrice) + .totalPaymentPrice(totalPaymentPrice) + .totalDiscountPrice(totalDiscountPrice) + .deliveryPrice(deliveryPrice) + .build(); + + log.info("[*] orderCheckoutViewDto => {}", orderCheckoutViewDto); + + model.addAttribute("orderCheckoutViewDto", orderCheckoutViewDto); + model.addAttribute("memberOrderPreparationRequest", new MemberOrderPreparationRequest()); + + return "main/page/orderCheckout"; + } +} \ No newline at end of file From b6fdff2300e471c72165b1b51360741031c03dd7 Mon Sep 17 00:00:00 2001 From: woody35545 Date: Wed, 15 May 2024 14:08:59 +0900 Subject: [PATCH 20/53] =?UTF-8?q?feat:=20#101=20`OrderConfirmRequest`=20-?= =?UTF-8?q?=20=EC=A3=BC=EB=AC=B8=20=EC=8A=B9=EC=9D=B8=20=EC=9A=94=EC=B2=AD?= =?UTF-8?q?=20=EA=B0=9D=EC=B2=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../model/request/OrderConfirmRequest.java | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/main/java/com/t3t/frontserver/order/model/request/OrderConfirmRequest.java diff --git a/src/main/java/com/t3t/frontserver/order/model/request/OrderConfirmRequest.java b/src/main/java/com/t3t/frontserver/order/model/request/OrderConfirmRequest.java new file mode 100644 index 00000000..68c79e3f --- /dev/null +++ b/src/main/java/com/t3t/frontserver/order/model/request/OrderConfirmRequest.java @@ -0,0 +1,33 @@ +package com.t3t.frontserver.order.model.request; + +import com.t3t.frontserver.payment.constant.PaymentProviderType; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; + +/** + * 주문 승인 요청 객체 + * + * @Author woody35545(구건모) + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class OrderConfirmRequest { + @NotNull(message = "주문 식별자가 누락되었습니다.") + private Long orderId; // 주문 식별자 + @NotNull(message = "결제 제공처가 누락되었습니다.") + private PaymentProviderType paymentProviderType; // 결제 제공처 + @NotBlank(message = "결제 제공처의 결제 키가 누락되었습니다.") + private String paymentKey; // 결제 제공처의 결제 키 + @NotBlank(message = "결제 제공처의 주문 식별자가 누락되었습니다.") + private String paymentOrderId; // 결제 제공처의 주문 식별자 + @NotBlank(message = "결제 금액 정보가 누락되었습니다.") + private BigDecimal paidAmount; // 사용자가 결제한 금액 +} From d64e069c7d9e8909a913dbe72a44b3a08d435cb7 Mon Sep 17 00:00:00 2001 From: woody35545 Date: Wed, 15 May 2024 14:10:38 +0900 Subject: [PATCH 21/53] =?UTF-8?q?feat:=20#101=20`OrderApiClient`=20-=20?= =?UTF-8?q?=EC=A3=BC=EB=AC=B8=EC=97=90=20=EB=8C=80=ED=95=9C=20=EA=B2=B0?= =?UTF-8?q?=EC=A0=9C=20=EA=B2=80=EC=A6=9D=20=EB=B0=8F=20=EC=A3=BC=EB=AC=B8?= =?UTF-8?q?=20=EC=8A=B9=EC=9D=B8=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../t3t/frontserver/order/client/OrderApiClient.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main/java/com/t3t/frontserver/order/client/OrderApiClient.java b/src/main/java/com/t3t/frontserver/order/client/OrderApiClient.java index 0dc3dec8..9ead6afb 100644 --- a/src/main/java/com/t3t/frontserver/order/client/OrderApiClient.java +++ b/src/main/java/com/t3t/frontserver/order/client/OrderApiClient.java @@ -2,11 +2,14 @@ import com.t3t.frontserver.model.response.BaseResponse; import com.t3t.frontserver.order.model.request.MemberOrderPreparationRequest; +import com.t3t.frontserver.order.model.request.OrderConfirmRequest; import com.t3t.frontserver.order.model.response.MemberOrderPreparationResponse; import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.ResponseStatus; @FeignClient(name = "OrderApiClient", url = "${t3t.feignClient.url}") public interface OrderApiClient { @@ -20,4 +23,13 @@ public interface OrderApiClient { @PostMapping(value = "/t3t/bookstore/orders/member") ResponseEntity> createMemberOrder(@RequestBody MemberOrderPreparationRequest memberOrderPreparationRequest); + + /** + * 주문에 대한 결제 검증 및 주문 승인 API + * + * @author woody35545(구건모) + */ + @PostMapping("/orders/confirm") + @ResponseStatus(HttpStatus.OK) + ResponseEntity> confirmOrder(OrderConfirmRequest orderConfirmRequest); } \ No newline at end of file From 3e41a54051737c6b9e6d70d5e07f661cae299783 Mon Sep 17 00:00:00 2001 From: woody35545 Date: Wed, 15 May 2024 15:12:45 +0900 Subject: [PATCH 22/53] =?UTF-8?q?fix:=20`OrderApiClient`=20-=20`@RequestBo?= =?UTF-8?q?dy`=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/t3t/frontserver/order/client/OrderApiClient.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/t3t/frontserver/order/client/OrderApiClient.java b/src/main/java/com/t3t/frontserver/order/client/OrderApiClient.java index 9ead6afb..99aeda42 100644 --- a/src/main/java/com/t3t/frontserver/order/client/OrderApiClient.java +++ b/src/main/java/com/t3t/frontserver/order/client/OrderApiClient.java @@ -29,7 +29,6 @@ public interface OrderApiClient { * * @author woody35545(구건모) */ - @PostMapping("/orders/confirm") - @ResponseStatus(HttpStatus.OK) - ResponseEntity> confirmOrder(OrderConfirmRequest orderConfirmRequest); + @PostMapping("/t3t/bookstore/orders/confirm") + ResponseEntity> confirmOrder(@RequestBody OrderConfirmRequest orderConfirmRequest); } \ No newline at end of file From 03cbccf7793521eb4b05e6dde07b5f9aaf494245 Mon Sep 17 00:00:00 2001 From: woody35545 Date: Wed, 15 May 2024 15:13:02 +0900 Subject: [PATCH 23/53] =?UTF-8?q?feat:=20#101=20`OrderAdaptor`=20-=20?= =?UTF-8?q?=EC=A3=BC=EB=AC=B8=EC=97=90=20=EB=8C=80=ED=95=9C=20=EA=B2=B0?= =?UTF-8?q?=EC=A0=9C=20=EA=B2=80=EC=A6=9D=20=EB=B0=8F=20=EC=A3=BC=EB=AC=B8?= =?UTF-8?q?=20=EC=8A=B9=EC=9D=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../frontserver/order/adaptor/OrderAdaptor.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/main/java/com/t3t/frontserver/order/adaptor/OrderAdaptor.java b/src/main/java/com/t3t/frontserver/order/adaptor/OrderAdaptor.java index b536b5a0..94d552be 100644 --- a/src/main/java/com/t3t/frontserver/order/adaptor/OrderAdaptor.java +++ b/src/main/java/com/t3t/frontserver/order/adaptor/OrderAdaptor.java @@ -4,6 +4,7 @@ import com.t3t.frontserver.order.client.OrderApiClient; import com.t3t.frontserver.order.exception.OrderApiClientException; import com.t3t.frontserver.order.model.request.MemberOrderPreparationRequest; +import com.t3t.frontserver.order.model.request.OrderConfirmRequest; import com.t3t.frontserver.order.model.response.MemberOrderPreparationResponse; import com.t3t.frontserver.util.FeignClientUtils; import feign.FeignException; @@ -32,4 +33,17 @@ public MemberOrderPreparationResponse createMemberOrder(MemberOrderPreparationRe throw new OrderApiClientException("주문 생성에 실패하였습니다. " + FeignClientUtils.getMessageFromFeignException(e)); } } + + /** + * 주문에 대한 결제 검증 및 주문 승인 + * + * @author woody35545(구건모) + */ + public void confirmOrder(OrderConfirmRequest request) { + try { + orderApiClient.confirmOrder(request); + } catch (FeignException e) { + throw new OrderApiClientException("주문에 대한 결제 검증에 실패하였습니다. " + FeignClientUtils.getMessageFromFeignException(e)); + } + } } \ No newline at end of file From ff62f7b1ac8a99c3041787d0a32a7735b843e53b Mon Sep 17 00:00:00 2001 From: woody35545 Date: Wed, 15 May 2024 15:15:54 +0900 Subject: [PATCH 24/53] =?UTF-8?q?feat:=20#101=20`OrderService`=20-=20?= =?UTF-8?q?=EC=A3=BC=EB=AC=B8=EC=97=90=20=EB=8C=80=ED=95=9C=20=EA=B2=B0?= =?UTF-8?q?=EC=A0=9C=20=EA=B2=80=EC=A6=9D=20=EB=B0=8F=20=EC=A3=BC=EB=AC=B8?= =?UTF-8?q?=20=EC=8A=B9=EC=9D=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../t3t/frontserver/order/service/OrderService.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/com/t3t/frontserver/order/service/OrderService.java b/src/main/java/com/t3t/frontserver/order/service/OrderService.java index 0d8cea9e..8ec03d48 100644 --- a/src/main/java/com/t3t/frontserver/order/service/OrderService.java +++ b/src/main/java/com/t3t/frontserver/order/service/OrderService.java @@ -3,6 +3,7 @@ import com.t3t.frontserver.order.adaptor.OrderAdaptor; import com.t3t.frontserver.order.model.request.MemberOrderPreparationRequest; +import com.t3t.frontserver.order.model.request.OrderConfirmRequest; import com.t3t.frontserver.order.model.response.MemberOrderPreparationResponse; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -21,4 +22,13 @@ public class OrderService { public MemberOrderPreparationResponse createMemberOrder(MemberOrderPreparationRequest memberOrderPreparationRequest) { return orderAdaptor.createMemberOrder(memberOrderPreparationRequest); } + + /** + * 주문에 대한 결제 검증 및 주문 승인 + * + * @author woody35545(구건모) + */ + public void confirmOrder(OrderConfirmRequest request) { + orderAdaptor.confirmOrder(request); + } } \ No newline at end of file From 50edc0c6fbdfa660939623fa60e34f3c725664ec Mon Sep 17 00:00:00 2001 From: woody35545 Date: Wed, 15 May 2024 15:16:28 +0900 Subject: [PATCH 25/53] =?UTF-8?q?modify:=20#101=20`PaymentController`=20-?= =?UTF-8?q?=20=EA=B2=B0=EC=A0=9C=20=EC=84=B1=EA=B3=B5=EC=8B=9C=20=EC=84=9C?= =?UTF-8?q?=EB=B9=84=EC=8A=A4=EC=97=90=EC=84=9C=20=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=ED=95=98=EB=8A=94=20=EC=A3=BC=EB=AC=B8=20=EC=8B=9D=EB=B3=84?= =?UTF-8?q?=EC=9E=90=EB=8F=84=20=EC=A0=84=EB=8B=AC=ED=95=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../payment/controller/PaymentController.java | 35 +++++++++++++++---- 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/t3t/frontserver/payment/controller/PaymentController.java b/src/main/java/com/t3t/frontserver/payment/controller/PaymentController.java index 934a44a7..856aa6c8 100644 --- a/src/main/java/com/t3t/frontserver/payment/controller/PaymentController.java +++ b/src/main/java/com/t3t/frontserver/payment/controller/PaymentController.java @@ -2,6 +2,7 @@ import com.t3t.frontserver.auth.util.SecurityContextUtils; import com.t3t.frontserver.order.model.request.MemberOrderPreparationRequest; +import com.t3t.frontserver.order.model.request.OrderConfirmRequest; import com.t3t.frontserver.order.model.response.MemberOrderPreparationResponse; import com.t3t.frontserver.order.service.OrderService; import com.t3t.frontserver.payment.constant.PaymentProviderType; @@ -15,6 +16,7 @@ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; +import java.math.BigDecimal; import java.time.LocalDate; @Slf4j @@ -52,10 +54,13 @@ public String paymentCheckoutView(Model model, @ModelAttribute MemberOrderPrepar // 총 결제해야할 금액 model.addAttribute("amount", memberOrderPreparationResponse.getTotalPrice()); + // 북스토에서 사용하는 주문 식별자 + model.addAttribute("orderId", memberOrderPreparationResponse.getOrderId()); + // 결제 제공처에서 사용할 주문 식별자 - model.addAttribute("orderId", memberOrderPreparationResponse.getProviderOrderId()); + model.addAttribute("providerOrderId", memberOrderPreparationResponse.getProviderOrderId()); - return "main/payments/checkout"; + return "main/payment/checkout"; } @@ -66,14 +71,32 @@ public String paymentCheckoutView(Model model, @ModelAttribute MemberOrderPrepar * @author woody35545(구건모) */ @GetMapping("/payment/success") - public String paymentRequest(Model model, @RequestParam String paymentKey, @RequestParam String orderId, @RequestParam String amount) { + public String paymentRequest(Model model, + @RequestParam Long serviceOrderId, + @RequestParam String paymentKey, + @RequestParam("orderId") String providerOrderId, + @RequestParam String amount) { + + log.info("serviceOrderId => {}", serviceOrderId); + + OrderConfirmRequest orderConfirmRequest = OrderConfirmRequest.builder() + .paymentOrderId(providerOrderId) + .orderId(serviceOrderId) + .paymentKey(paymentKey) + .paymentProviderType(PaymentProviderType.TOSS) + .paidAmount(new BigDecimal(amount)).build(); + + log.info("[*] orderConfirmRequest => {}", orderConfirmRequest); + + log.info("[*] confirmOrder request ... "); + orderService.confirmOrder(orderConfirmRequest); model.addAttribute("feignClientUrl", feignClientUrl); model.addAttribute("paymentKey", paymentKey); - model.addAttribute("orderId", orderId); + model.addAttribute("orderId", providerOrderId); model.addAttribute("amount", amount); - return "main/payments/success"; + return "main/payment/success"; } /** @@ -87,7 +110,7 @@ public String failPayment(Model model, @RequestParam String failCode, @RequestPa model.addAttribute("code", failCode); model.addAttribute("message", failMessage); - return "main/payments/fail"; + return "main/payment/fail"; } } From 46d2c8a9001afe7e05db28f8d24310e3b12a60ac Mon Sep 17 00:00:00 2001 From: woody35545 Date: Wed, 15 May 2024 15:16:54 +0900 Subject: [PATCH 26/53] =?UTF-8?q?modify:=20`checkout.html`=20-=20=EC=84=9C?= =?UTF-8?q?=EB=B9=84=EC=8A=A4=20=EB=82=B4=EC=97=90=EC=84=9C=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=ED=95=98=EB=8A=94=20=EC=A3=BC=EB=AC=B8=20=EC=8B=9D?= =?UTF-8?q?=EB=B3=84=EC=9E=90=20=EC=A0=84=EB=8B=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/templates/main/payment/checkout.html | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/resources/templates/main/payment/checkout.html b/src/main/resources/templates/main/payment/checkout.html index 3b54db84..3fb4f64c 100644 --- a/src/main/resources/templates/main/payment/checkout.html +++ b/src/main/resources/templates/main/payment/checkout.html @@ -9,15 +9,16 @@ let type = '카드' let amount = [[${amount}]] let orderId = [[${orderId}]] + let providerOrderId = [[${providerOrderId}]] let tossPayments = TossPayments(clientKey); tossPayments.requestPayment(type, { amount: amount, - orderId: orderId, + orderId: providerOrderId, orderName: '상품 주문', customerName: ' ', - successUrl: window.location.origin + "/payment/success", + successUrl: window.location.origin + "/payment/success?serviceOrderId=" + orderId, failUrl: window.location.origin + "/payment/fail", }) From c42e62f98b003063b3d22628ba15ba89f01e0d5f Mon Sep 17 00:00:00 2001 From: woody35545 Date: Wed, 15 May 2024 22:39:22 +0900 Subject: [PATCH 27/53] =?UTF-8?q?feat:=20#104=20`OrderInfoResponse`=20-=20?= =?UTF-8?q?=EC=A3=BC=EB=AC=B8=20=EA=B4=80=EB=A0=A8=20=EC=A0=95=EB=B3=B4?= =?UTF-8?q?=EC=97=90=20=EB=8C=80=ED=95=9C=20=EC=9D=91=EB=8B=B5=20=EA=B0=9D?= =?UTF-8?q?=EC=B2=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../model/response/OrderInfoResponse.java | 101 ++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 src/main/java/com/t3t/frontserver/order/model/response/OrderInfoResponse.java diff --git a/src/main/java/com/t3t/frontserver/order/model/response/OrderInfoResponse.java b/src/main/java/com/t3t/frontserver/order/model/response/OrderInfoResponse.java new file mode 100644 index 00000000..8fad5cd6 --- /dev/null +++ b/src/main/java/com/t3t/frontserver/order/model/response/OrderInfoResponse.java @@ -0,0 +1,101 @@ +package com.t3t.frontserver.order.model.response; + +import com.t3t.frontserver.payment.constant.PaymentProviderType; +import lombok.*; +import org.springframework.lang.Nullable; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; + +/** + * 주문 관련 정보에 대한 응답 객체 + * + * @author woody35545(구건모) + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor(access = AccessLevel.PRIVATE) +public class OrderInfoResponse { + + /** + * 주문 정보 + */ + private Long orderId; + private LocalDateTime orderCreatedAt; + + /** + * 주문에 포함된 주문 상세 정보 + */ + private List orderDetailInfoList; + + + /** + * 주문 회원 정보
+ * 비회원의 경우 null 이 될 수 있다. + */ + @Nullable + private Long memberId; + + /** + * 결제 정보 + */ + private Long paymentId; + private Long paymentProviderId; + private PaymentProviderType paymentProviderType; + private BigDecimal paymentTotalAmount; + private LocalDateTime paymentCreatedAt; + + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor(access = AccessLevel.PRIVATE) + public static class OrderDetailInfo { + private Long orderDetailId; // 주문 상세 식별자 + private Integer quantity; // 주문 수량 + /** + * price
+ * 주문 상세 항목 단건에 대한 최종 가격 + * (= 책 가격 * 할인율 + 포장지 가격) + */ + private BigDecimal price; // 상품 최종 결제 금액 + + private LocalDateTime createdAt; // 주문 상세 생성 일시 + /** + * order + */ + private Long orderId; // 주문 상세 항목이 속한 주문 정보 식별자 + /** + * book + */ + private Long bookId; // 주문한 책 식별자 + private String bookName; // 주문한 책 이름 + private String bookPublisherName; // 주문한 책 출판사 이름 + + /** + * packaging + */ + private Long packagingId; // 주문 상세 항목에 사용된 포장지 식별자 + private String packagingName; // 주문 상세 항목에 사용된 포장지 이름 + private BigDecimal packagingPrice; // 주문 상세 항목에 사용된 포장지 가격 + + /** + * orderStatus + */ + private String orderStatusName; // 주문 상태 이름 + + /** + * delivery + */ + private Long deliveryId; // 배송 식별자 + private BigDecimal deliveryPrice; // 배송비 + private int addressNumber; // 우편 주소 + private String roadnameAddress; // 도로명 주소 + private String detailAddress; // 상세 주소 + private LocalDate deliveryDate; // 배송 예정 일자(희망 배송 일자) + private String recipientName; // 수령인 이름 + private String recipientPhoneNumber; // 수령인 연락처 + } +} \ No newline at end of file From a61a6922c91d5fb147b54cd546df9204ca1a6799 Mon Sep 17 00:00:00 2001 From: woody35545 Date: Thu, 16 May 2024 01:07:56 +0900 Subject: [PATCH 28/53] =?UTF-8?q?modify:=20#104=20`OrderInfoResponse`=20-?= =?UTF-8?q?=20=EC=9D=BC=EB=B6=80=20=ED=95=84=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../frontserver/order/model/response/OrderInfoResponse.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/t3t/frontserver/order/model/response/OrderInfoResponse.java b/src/main/java/com/t3t/frontserver/order/model/response/OrderInfoResponse.java index 8fad5cd6..e5c4f051 100644 --- a/src/main/java/com/t3t/frontserver/order/model/response/OrderInfoResponse.java +++ b/src/main/java/com/t3t/frontserver/order/model/response/OrderInfoResponse.java @@ -47,6 +47,7 @@ public class OrderInfoResponse { private PaymentProviderType paymentProviderType; private BigDecimal paymentTotalAmount; private LocalDateTime paymentCreatedAt; + private String paymentProviderOrderId; @Data @Builder @@ -54,6 +55,8 @@ public class OrderInfoResponse { @AllArgsConstructor(access = AccessLevel.PRIVATE) public static class OrderDetailInfo { private Long orderDetailId; // 주문 상세 식별자 + private LocalDateTime createdAt; // 주문 상세 생성 일시 + private Integer quantity; // 주문 수량 /** * price
@@ -62,17 +65,18 @@ public static class OrderDetailInfo { */ private BigDecimal price; // 상품 최종 결제 금액 - private LocalDateTime createdAt; // 주문 상세 생성 일시 /** * order */ private Long orderId; // 주문 상세 항목이 속한 주문 정보 식별자 + /** * book */ private Long bookId; // 주문한 책 식별자 private String bookName; // 주문한 책 이름 private String bookPublisherName; // 주문한 책 출판사 이름 + private String bookImageUrl; // 책 이미지 URL /** * packaging From 5490d2948dd2b38620aa7369d0dd2750a6758d6b Mon Sep 17 00:00:00 2001 From: woody35545 Date: Thu, 16 May 2024 01:08:26 +0900 Subject: [PATCH 29/53] =?UTF-8?q?feat:=20#104=20`OrderApiClient`=20-=20?= =?UTF-8?q?=EC=A3=BC=EB=AC=B8=20=EC=A0=95=EB=B3=B4=20=ED=8A=B9=EC=A0=95=20?= =?UTF-8?q?=ED=9A=8C=EC=9B=90=EC=9D=98=20=EB=AA=A8=EB=93=A0=20=EC=A3=BC?= =?UTF-8?q?=EB=AC=B8=20=EA=B4=80=EB=A0=A8=20=EC=A0=95=EB=B3=B4=EB=A5=BC=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=95=EC=9D=84=20=ED=86=B5=ED=95=B4=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=ED=95=98=EB=8A=94=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../frontserver/order/client/OrderApiClient.java | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/t3t/frontserver/order/client/OrderApiClient.java b/src/main/java/com/t3t/frontserver/order/client/OrderApiClient.java index 99aeda42..b4929c16 100644 --- a/src/main/java/com/t3t/frontserver/order/client/OrderApiClient.java +++ b/src/main/java/com/t3t/frontserver/order/client/OrderApiClient.java @@ -1,15 +1,17 @@ package com.t3t.frontserver.order.client; import com.t3t.frontserver.model.response.BaseResponse; +import com.t3t.frontserver.model.response.PageResponse; import com.t3t.frontserver.order.model.request.MemberOrderPreparationRequest; import com.t3t.frontserver.order.model.request.OrderConfirmRequest; import com.t3t.frontserver.order.model.response.MemberOrderPreparationResponse; +import com.t3t.frontserver.order.model.response.OrderInfoResponse; import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.*; @FeignClient(name = "OrderApiClient", url = "${t3t.feignClient.url}") public interface OrderApiClient { @@ -31,4 +33,12 @@ public interface OrderApiClient { */ @PostMapping("/t3t/bookstore/orders/confirm") ResponseEntity> confirmOrder(@RequestBody OrderConfirmRequest orderConfirmRequest); + + /** + * 특정 회원의 모든 주문 관련 정보를 페이징을 통해 조회 + * + * @author woody35545(구건모) + */ + @GetMapping("/t3t/bookstore/members/{memberId}/orders") + ResponseEntity>> getMemberOrderInfoListByMemberId(@PathVariable("memberId") Long memberId, Pageable pageable); } \ No newline at end of file From d3a96f1355b649ff2f8eed23bd183d591e5fd420 Mon Sep 17 00:00:00 2001 From: woody35545 Date: Thu, 16 May 2024 01:08:39 +0900 Subject: [PATCH 30/53] =?UTF-8?q?feat:=20#104=20`OrderAdaptor`=20-=20?= =?UTF-8?q?=ED=8A=B9=EC=A0=95=20=ED=9A=8C=EC=9B=90=EC=9D=98=20=EB=AA=A8?= =?UTF-8?q?=EB=93=A0=20=EC=A3=BC=EB=AC=B8=20=EA=B4=80=EB=A0=A8=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=EB=A5=BC=20=ED=8E=98=EC=9D=B4=EC=A7=95=EC=9D=84=20?= =?UTF-8?q?=ED=86=B5=ED=95=B4=20=EC=A1=B0=ED=9A=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../order/adaptor/OrderAdaptor.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/main/java/com/t3t/frontserver/order/adaptor/OrderAdaptor.java b/src/main/java/com/t3t/frontserver/order/adaptor/OrderAdaptor.java index 94d552be..574cab65 100644 --- a/src/main/java/com/t3t/frontserver/order/adaptor/OrderAdaptor.java +++ b/src/main/java/com/t3t/frontserver/order/adaptor/OrderAdaptor.java @@ -1,18 +1,23 @@ package com.t3t.frontserver.order.adaptor; import com.t3t.frontserver.model.response.BaseResponse; +import com.t3t.frontserver.model.response.PageResponse; import com.t3t.frontserver.order.client.OrderApiClient; import com.t3t.frontserver.order.exception.OrderApiClientException; import com.t3t.frontserver.order.model.request.MemberOrderPreparationRequest; import com.t3t.frontserver.order.model.request.OrderConfirmRequest; import com.t3t.frontserver.order.model.response.MemberOrderPreparationResponse; +import com.t3t.frontserver.order.model.response.OrderInfoResponse; import com.t3t.frontserver.util.FeignClientUtils; import feign.FeignException; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Component; import java.util.Optional; +@Slf4j @Component @RequiredArgsConstructor public class OrderAdaptor { @@ -46,4 +51,19 @@ public void confirmOrder(OrderConfirmRequest request) { throw new OrderApiClientException("주문에 대한 결제 검증에 실패하였습니다. " + FeignClientUtils.getMessageFromFeignException(e)); } } + + /** + * 특정 회원의 모든 주문 관련 정보를 페이징을 통해 조회 + * + * @author woody35545(구건모) + */ + public PageResponse getMemberOrderInfoListByMemberId(Long memberId, Pageable pageable) { + try { + return Optional.ofNullable(orderApiClient.getMemberOrderInfoListByMemberId(memberId, pageable).getBody()) + .map(BaseResponse::getData) + .orElseThrow(RuntimeException::new); + } catch (FeignException e) { + throw new OrderApiClientException("주문 정보 조회에 실패하였습니다. " + FeignClientUtils.getMessageFromFeignException(e)); + } + } } \ No newline at end of file From 910b34cb2daf54104276c04b2d0276f24694b70c Mon Sep 17 00:00:00 2001 From: woody35545 Date: Thu, 16 May 2024 01:09:14 +0900 Subject: [PATCH 31/53] =?UTF-8?q?feat:=20#104=20`OrderService`=20-=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=95=EB=90=9C=20=EC=A3=BC=EB=AC=B8=20?= =?UTF-8?q?=EA=B4=80=EB=A0=A8=20=EC=A0=95=EB=B3=B4=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../t3t/frontserver/order/service/OrderService.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/main/java/com/t3t/frontserver/order/service/OrderService.java b/src/main/java/com/t3t/frontserver/order/service/OrderService.java index 8ec03d48..1e8cf61c 100644 --- a/src/main/java/com/t3t/frontserver/order/service/OrderService.java +++ b/src/main/java/com/t3t/frontserver/order/service/OrderService.java @@ -1,11 +1,15 @@ package com.t3t.frontserver.order.service; +import com.t3t.frontserver.model.response.PageResponse; import com.t3t.frontserver.order.adaptor.OrderAdaptor; import com.t3t.frontserver.order.model.request.MemberOrderPreparationRequest; import com.t3t.frontserver.order.model.request.OrderConfirmRequest; import com.t3t.frontserver.order.model.response.MemberOrderPreparationResponse; +import com.t3t.frontserver.order.model.response.OrderInfoResponse; import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; @Service @@ -31,4 +35,13 @@ public MemberOrderPreparationResponse createMemberOrder(MemberOrderPreparationRe public void confirmOrder(OrderConfirmRequest request) { orderAdaptor.confirmOrder(request); } + + /** + * 특정 회원의 모든 주문 관련 정보를 페이징을 통해 조회 + * + * @author woody35545(구건모) + */ + public PageResponse getMemberOrderInfoListByMemberId(Long memberId, Pageable pageable) { + return orderAdaptor.getMemberOrderInfoListByMemberId(memberId, pageable); + } } \ No newline at end of file From 3857b39b0d5f0207e3db917ca47b2ae1d780186d Mon Sep 17 00:00:00 2001 From: woody35545 Date: Thu, 16 May 2024 01:10:19 +0900 Subject: [PATCH 32/53] =?UTF-8?q?feat:=20#104=20`MyPageController`=20-=20?= =?UTF-8?q?=EB=A7=88=EC=9D=B4=ED=8E=98=EC=9D=B4=EC=A7=80=20=ED=9A=8C?= =?UTF-8?q?=EC=9B=90=20=EC=A3=BC=EB=AC=B8=20=EB=82=B4=EC=97=AD=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/controller/MyPageController.java | 42 ++++++++++++++++++- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/t3t/frontserver/member/controller/MyPageController.java b/src/main/java/com/t3t/frontserver/member/controller/MyPageController.java index 7aca1395..7b9d5d8e 100644 --- a/src/main/java/com/t3t/frontserver/member/controller/MyPageController.java +++ b/src/main/java/com/t3t/frontserver/member/controller/MyPageController.java @@ -6,19 +6,29 @@ import com.t3t.frontserver.member.model.dto.MyPageInfoViewDto; import com.t3t.frontserver.member.model.response.MemberInfoResponse; import com.t3t.frontserver.member.service.MemberService; +import com.t3t.frontserver.model.response.PageResponse; +import com.t3t.frontserver.order.model.response.OrderInfoResponse; +import com.t3t.frontserver.order.service.OrderService; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; +import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; +@Slf4j @Controller @RequiredArgsConstructor public class MyPageController { private final MemberService memberService; + private final OrderService orderService; /** * 마이페이지 - 회원 기본 정보 관리 뷰 @@ -155,11 +165,39 @@ public String gradeView(Model model) { /** * 마이페이지 - 회원 주문 페이지 뷰 + * * @author woody35545(구건모) */ @GetMapping("/mypage/order") - public String orderView() { + public String orderView(Model model, + @RequestParam(value = "pageNo", defaultValue = "0", required = false) int pageNo, + @RequestParam(value = "pageSize", defaultValue = "3", required = false) int pageSize) { + + if (!SecurityContextUtils.isLoggedIn()) { + return "redirect:/login"; + } + + PageResponse orderInfoResponsePageResponse = + orderService.getMemberOrderInfoListByMemberId(SecurityContextUtils.getMemberId(), + Pageable.ofSize(pageSize).withPage(pageNo)); + + List orderInfoResponseList = new ArrayList<>(); + + if (orderInfoResponsePageResponse != null) { + orderInfoResponseList = orderInfoResponsePageResponse.getContent(); + + int blockLimit = 5; + int nextPage = orderInfoResponsePageResponse.getPageNo() + 1; + int startPage = Math.max(nextPage - blockLimit, 1); + int endPage = Math.min(nextPage + blockLimit, orderInfoResponsePageResponse.getTotalPages()); + + model.addAttribute("nextPage", nextPage); + model.addAttribute("startPage", startPage); + model.addAttribute("endPage", endPage); + } + + model.addAttribute("orderInfoResponseList", orderInfoResponseList); + return "main/page/mypageOrder"; } - } From 57fa8ca16a2a01f297ab096298588501e2a09a92 Mon Sep 17 00:00:00 2001 From: woody35545 Date: Thu, 16 May 2024 01:10:41 +0900 Subject: [PATCH 33/53] =?UTF-8?q?feat:=20#104=20`mypageOrder.html`=20-=20?= =?UTF-8?q?=ED=9A=8C=EC=9B=90=20=EC=A3=BC=EB=AC=B8=20=EB=82=B4=EC=97=AD=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EB=B7=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../templates/main/page/mypageOrder.html | 197 +++++++++++++----- 1 file changed, 146 insertions(+), 51 deletions(-) diff --git a/src/main/resources/templates/main/page/mypageOrder.html b/src/main/resources/templates/main/page/mypageOrder.html index 86195679..9b73b5eb 100644 --- a/src/main/resources/templates/main/page/mypageOrder.html +++ b/src/main/resources/templates/main/page/mypageOrder.html @@ -6,67 +6,162 @@

주문 목록

-
-
-
주문번호: 111-1250912120
-
- -
-
-
- 상품 이미지 -
-
-
-
배송 중 (배송 예정일: 2024-05-01)
-

상품명: 상품 A

-

상품 가격: 10,000원

-
- - - -
-
-
-
-
+ + -
-
-
주문번호: 111-1250912120
-
- +
+
+
+
+ 주문번호: + -
-
-
- 상품 이미지 -
-
-
-
배송 중 (배송 예정일: 2024-05-01)
-

상품명: 상품 A

-

상품 가격: 10,000원

-
- - - + +
+ +
+ + +
+ +
+
+
+
+ 상품 이미지 +
+
+
+
+
+ + (배송 예정일: + + + + + + ) + +
+

+

+
+ 상품명 +
+
+ +
+ +
+ 구매 수량 +
+
+ +
+ +
+ 결제 금액 +
+
+ +
+ +
+ 결제 일시 +
+
+ + + + +
+
+

+ + +
+ + + + + + + + + + + +
+
+
+ +
+ + From 86c8c2797ad345db497eeb93c72741c316e91254 Mon Sep 17 00:00:00 2001 From: woody35545 Date: Thu, 16 May 2024 05:32:53 +0900 Subject: [PATCH 34/53] =?UTF-8?q?feat:=20#107=20`RedisProperties`=20-=20Re?= =?UTF-8?q?dis=20=EC=84=9C=EB=B2=84=20=EC=A0=91=EC=86=8D=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=EB=A5=BC=20=EB=8B=B4=EB=8A=94=20=ED=94=84=EB=A1=9C?= =?UTF-8?q?=ED=8D=BC=ED=8B=B0=20=ED=81=B4=EB=9E=98=EC=8A=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../frontserver/property/RedisProperties.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 src/main/java/com/t3t/frontserver/property/RedisProperties.java diff --git a/src/main/java/com/t3t/frontserver/property/RedisProperties.java b/src/main/java/com/t3t/frontserver/property/RedisProperties.java new file mode 100644 index 00000000..2bda4b89 --- /dev/null +++ b/src/main/java/com/t3t/frontserver/property/RedisProperties.java @@ -0,0 +1,18 @@ +package com.t3t.frontserver.property; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * Redis 서버 접속 정보를 담는 프로퍼티 클래스 + * + * @author woody35545(구건모) + */ +@Data +@ConfigurationProperties(prefix = "t3t.redis") +public class RedisProperties { + private String redisServerIpAddress; + private String redisServerPassword; + private String redisServerPort; + private Integer redisDatabase; +} From d4863096cb4141f5acbcba1e2dc4339045f1e14d Mon Sep 17 00:00:00 2001 From: woody35545 Date: Thu, 16 May 2024 05:33:17 +0900 Subject: [PATCH 35/53] =?UTF-8?q?feat:=20#107=20`RedisConfig`=20-=20Redis?= =?UTF-8?q?=20=EA=B4=80=EB=A0=A8=20=EB=B9=88=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../t3t/frontserver/config/RedisConfig.java | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 src/main/java/com/t3t/frontserver/config/RedisConfig.java diff --git a/src/main/java/com/t3t/frontserver/config/RedisConfig.java b/src/main/java/com/t3t/frontserver/config/RedisConfig.java new file mode 100644 index 00000000..387cd9f3 --- /dev/null +++ b/src/main/java/com/t3t/frontserver/config/RedisConfig.java @@ -0,0 +1,48 @@ +package com.t3t.frontserver.config; + +import com.t3t.frontserver.property.RedisProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.connection.RedisStandaloneConfiguration; +import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.repository.configuration.EnableRedisRepositories; +import org.springframework.data.redis.serializer.StringRedisSerializer; + + +@Configuration +@EnableRedisRepositories +public class RedisConfig { + + /** + * RedisConnectionFactory 빈 설정 + * + * @author woody35545(구건모) + */ + @Bean + public RedisConnectionFactory redisConnectionFactory(RedisProperties redisProperties) { + RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(); + redisStandaloneConfiguration.setHostName(redisProperties.getRedisServerIpAddress()); + redisStandaloneConfiguration.setPort(Integer.parseInt(redisProperties.getRedisServerPort())); + redisStandaloneConfiguration.setPassword(redisProperties.getRedisServerPassword()); + redisStandaloneConfiguration.setDatabase(redisProperties.getRedisDatabase()); + System.out.println("redisProperties.getRedisServerIpAddress() = " + redisProperties.getRedisServerIpAddress()); + return new LettuceConnectionFactory(redisStandaloneConfiguration); + } + + /** + * RedisTemplate 빈 설정 + * + * @author woody35545(구건모) + */ + @Bean + public RedisTemplate redisTemplate(RedisProperties redisProperties) { + RedisTemplate redisTemplate = new RedisTemplate<>(); + redisTemplate.setConnectionFactory(redisConnectionFactory(redisProperties)); + redisTemplate.setKeySerializer(new StringRedisSerializer()); + redisTemplate.setValueSerializer(new StringRedisSerializer()); + return redisTemplate; + } + +} From d4f61249d0ef6c19cc627e8c5952c700b12f3dde Mon Sep 17 00:00:00 2001 From: woody35545 Date: Thu, 16 May 2024 05:34:09 +0900 Subject: [PATCH 36/53] =?UTF-8?q?feat:=20#107=20`ShoppingCart`=20-=20?= =?UTF-8?q?=EB=A0=88=EB=94=94=EC=8A=A4=EC=97=90=20=EC=A0=80=EC=9E=A5?= =?UTF-8?q?=EB=90=A0=20=EC=9E=A5=EB=B0=94=EA=B5=AC=EB=8B=88=20=EA=B0=9D?= =?UTF-8?q?=EC=B2=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../model/entity/ShoppingCart.java | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 src/main/java/com/t3t/frontserver/shoppingcart/model/entity/ShoppingCart.java diff --git a/src/main/java/com/t3t/frontserver/shoppingcart/model/entity/ShoppingCart.java b/src/main/java/com/t3t/frontserver/shoppingcart/model/entity/ShoppingCart.java new file mode 100644 index 00000000..55b79165 --- /dev/null +++ b/src/main/java/com/t3t/frontserver/shoppingcart/model/entity/ShoppingCart.java @@ -0,0 +1,54 @@ +package com.t3t.frontserver.shoppingcart.model.entity; + +import lombok.*; +import org.springframework.data.annotation.Id; +import org.springframework.data.redis.core.RedisHash; + +import java.math.BigDecimal; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * 레디스에 저장될 장바구니 정보 + * @author woody35545(구건모) + */ +@Getter +@Builder +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@RedisHash(value = "shoppingCart", timeToLive = 60 * 60 * 24) +public class ShoppingCart { + + /** + * 회원의 경우 memberId, 비회원의 경우 임의의 UUID + */ + @Id + private String id; + private Map shoppingCartItemMap = new LinkedHashMap<>(); + + @Getter + @Builder + @AllArgsConstructor(access = AccessLevel.PRIVATE) + @NoArgsConstructor(access = AccessLevel.PROTECTED) + public static class ShoppingCartItem { + private String bookId; + private String bookName; + private String bookImageUrl; + private String bookPublisherName; + private Integer quantity; + private Long packagingId; + private String packagingName; + private BigDecimal price; + } + + public void updateQuantity(String bookId, int quantityToUpdate) { + + if(!shoppingCartItemMap.containsKey(bookId)) { + return ; + } + + ShoppingCartItem shoppingCartItem = shoppingCartItemMap.get(bookId); + shoppingCartItem.quantity = quantityToUpdate; + } + +} From c8a915e6b73c43908c0ac6101946fd7d90cf04ff Mon Sep 17 00:00:00 2001 From: woody35545 Date: Thu, 16 May 2024 05:34:39 +0900 Subject: [PATCH 37/53] =?UTF-8?q?chore:=20#107=20`application.yml`=20-=20?= =?UTF-8?q?=EB=A0=88=EB=94=94=EC=8A=A4=20=EA=B4=80=EB=A0=A8=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 5314b307..4cb20fc6 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -34,4 +34,10 @@ eureka: t3t: feignClient: - url: http://localhost:9090 \ No newline at end of file + url: http://localhost:9090 + + redis: + redisServerIpAddress: ${redisServerIpAddress} + redisServerPassword: ${redisServerPassword} + redisServerPort: ${redisServerPort} + redisDatabase: ${redisDatabase} \ No newline at end of file From 44a7af43c541a2d3cdbd76fc5fd8cd81a5c6c42f Mon Sep 17 00:00:00 2001 From: woody35545 Date: Thu, 16 May 2024 05:35:04 +0900 Subject: [PATCH 38/53] =?UTF-8?q?feat:=20=20#107=20`ShoppingCartRepository?= =?UTF-8?q?`=20=20-=20=EC=9E=A5=EB=B0=94=EA=B5=AC=EB=8B=88=20=EB=A0=88?= =?UTF-8?q?=EB=94=94=EC=8A=A4=20CrudRepository?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../shoppingcart/repository/ShoppingCartRepository.java | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 src/main/java/com/t3t/frontserver/shoppingcart/repository/ShoppingCartRepository.java diff --git a/src/main/java/com/t3t/frontserver/shoppingcart/repository/ShoppingCartRepository.java b/src/main/java/com/t3t/frontserver/shoppingcart/repository/ShoppingCartRepository.java new file mode 100644 index 00000000..8061575e --- /dev/null +++ b/src/main/java/com/t3t/frontserver/shoppingcart/repository/ShoppingCartRepository.java @@ -0,0 +1,7 @@ +package com.t3t.frontserver.shoppingcart.repository; + +import com.t3t.frontserver.shoppingcart.model.entity.ShoppingCart; +import org.springframework.data.repository.CrudRepository; + +public interface ShoppingCartRepository extends CrudRepository { +} From b8773a0ace8df6909bb7e528842eeca1c6b33694 Mon Sep 17 00:00:00 2001 From: woody35545 Date: Thu, 16 May 2024 05:36:00 +0900 Subject: [PATCH 39/53] =?UTF-8?q?feat:=20#107=20`AddShoppingCartItemReques?= =?UTF-8?q?t`=20-=20=EC=9E=A5=EB=B0=94=EA=B5=AC=EB=8B=88=EC=97=90=20?= =?UTF-8?q?=ED=95=AD=EB=AA=A9=20=EC=B6=94=EA=B0=80=20=EC=9A=94=EC=B2=AD=20?= =?UTF-8?q?=EA=B0=9D=EC=B2=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../request/AddShoppingCartItemRequest.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/main/java/com/t3t/frontserver/shoppingcart/model/request/AddShoppingCartItemRequest.java diff --git a/src/main/java/com/t3t/frontserver/shoppingcart/model/request/AddShoppingCartItemRequest.java b/src/main/java/com/t3t/frontserver/shoppingcart/model/request/AddShoppingCartItemRequest.java new file mode 100644 index 00000000..ca52ddeb --- /dev/null +++ b/src/main/java/com/t3t/frontserver/shoppingcart/model/request/AddShoppingCartItemRequest.java @@ -0,0 +1,25 @@ +package com.t3t.frontserver.shoppingcart.model.request; + +import lombok.*; + +import java.math.BigDecimal; + +/** + * 장바구니 항목 추가 요청 객체 + * @author woody35545(구건모) + */ +@Getter +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +public class AddShoppingCartItemRequest { + private String shoppingCartId; + private String bookId; + private String bookName; + private String bookImageUrl; + private String bookPublisherName; + private Integer quantity; + private Long packagingId; + private String packagingName; + private BigDecimal price; +} From 50b3ba1d5c260eead9b727aff9f2808839b37c30 Mon Sep 17 00:00:00 2001 From: woody35545 Date: Thu, 16 May 2024 05:37:38 +0900 Subject: [PATCH 40/53] =?UTF-8?q?update:=20#107=20`topbar.html`=20-=20?= =?UTF-8?q?=EC=9E=A5=EB=B0=94=EA=B5=AC=EB=8B=88=20=EB=A7=81=ED=81=AC=20?= =?UTF-8?q?=EC=A7=80=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/templates/main/fragment/topbar.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/templates/main/fragment/topbar.html b/src/main/resources/templates/main/fragment/topbar.html index b781bd2d..7dbe879b 100644 --- a/src/main/resources/templates/main/fragment/topbar.html +++ b/src/main/resources/templates/main/fragment/topbar.html @@ -13,7 +13,7 @@
- + From 6384a452fc38d7834997bb799169d815c345c688 Mon Sep 17 00:00:00 2001 From: woody35545 Date: Thu, 16 May 2024 05:38:07 +0900 Subject: [PATCH 41/53] =?UTF-8?q?update:=20`FrontServerApplication`=20-=20?= =?UTF-8?q?ConfigurationPropertiesScan=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/t3t/frontserver/FrontServerApplication.java | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/t3t/frontserver/FrontServerApplication.java b/src/main/java/com/t3t/frontserver/FrontServerApplication.java index 00300d78..c5c725c5 100644 --- a/src/main/java/com/t3t/frontserver/FrontServerApplication.java +++ b/src/main/java/com/t3t/frontserver/FrontServerApplication.java @@ -2,16 +2,14 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.cloud.client.discovery.EnableDiscoveryClient; -import org.springframework.cloud.netflix.eureka.EnableEurekaClient; -import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.boot.context.properties.ConfigurationPropertiesScan; -@EnableDiscoveryClient +@ConfigurationPropertiesScan @SpringBootApplication public class FrontServerApplication { - public static void main(String[] args) { - SpringApplication.run(FrontServerApplication.class, args); - } + public static void main(String[] args) { + SpringApplication.run(FrontServerApplication.class, args); + } } From cdf73ac2a92ed7cd68c8d50892a353be23b2cde3 Mon Sep 17 00:00:00 2001 From: woody35545 Date: Thu, 16 May 2024 05:39:08 +0900 Subject: [PATCH 42/53] =?UTF-8?q?feat:=20#107=20=20`ShoppingCartService`?= =?UTF-8?q?=20-=20=EC=9E=A5=EB=B0=94=EA=B5=AC=EB=8B=88=20=ED=95=AD?= =?UTF-8?q?=EB=AA=A9=20=EC=A1=B0=ED=9A=8C,=20=EC=B6=94=EA=B0=80,=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C=20=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/ShoppingCartService.java | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 src/main/java/com/t3t/frontserver/shoppingcart/service/ShoppingCartService.java diff --git a/src/main/java/com/t3t/frontserver/shoppingcart/service/ShoppingCartService.java b/src/main/java/com/t3t/frontserver/shoppingcart/service/ShoppingCartService.java new file mode 100644 index 00000000..33abc8a2 --- /dev/null +++ b/src/main/java/com/t3t/frontserver/shoppingcart/service/ShoppingCartService.java @@ -0,0 +1,90 @@ +package com.t3t.frontserver.shoppingcart.service; + +import com.t3t.frontserver.shoppingcart.model.entity.ShoppingCart; +import com.t3t.frontserver.shoppingcart.model.request.AddShoppingCartItemRequest; +import com.t3t.frontserver.shoppingcart.repository.ShoppingCartRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Map; +import java.util.Optional; + +@Service +@RequiredArgsConstructor +public class ShoppingCartService { + + private final ShoppingCartRepository shoppingCartRepository; + + /** + * 장바구니에 담긴 항목 리스트을 조회한다. + * + * @auhtor woody35545(구건모) + */ + public List getShoppingCartItemList(String shoppingCartId) { + + if (!shoppingCartRepository.existsById(shoppingCartId)) { + shoppingCartRepository.save(ShoppingCart.builder() + .id(shoppingCartId) + .build()); + } + + return shoppingCartRepository.findById(shoppingCartId) + .map(ShoppingCart::getShoppingCartItemMap) + .map(Map::values) + .map(List::copyOf) + .orElseThrow(() -> new IllegalArgumentException("장바구니를 찾을 수 없습니다.")); + } + + /** + * 장바구니에 항목을 추가한다. + * + * @author woody35545(구건모) + */ + public void addShoppingCartItem(AddShoppingCartItemRequest request) { + + if (!shoppingCartRepository.existsById(request.getShoppingCartId())) { + shoppingCartRepository.save(ShoppingCart.builder() + .id(request.getShoppingCartId()) + .build()); + } + + ShoppingCart shoppingCart = shoppingCartRepository.findById(request.getShoppingCartId()) + .orElseThrow(() -> new IllegalArgumentException("장바구니를 찾을 수 없습니다.")); + + if (shoppingCart.getShoppingCartItemMap().containsKey(request.getBookId())) { + shoppingCart.updateQuantity(request.getBookId(), + shoppingCart.getShoppingCartItemMap().get(request.getBookId()).getQuantity() + request.getQuantity()); + } else { + shoppingCart.getShoppingCartItemMap().put(request.getBookId(), ShoppingCart.ShoppingCartItem.builder() + .bookId(request.getBookId()) + .quantity(request.getQuantity()) + .bookImageUrl(request.getBookImageUrl()) + .bookName(request.getBookName()) + .bookPublisherName(request.getBookPublisherName()) + .packagingId(request.getPackagingId()) + .packagingName(request.getPackagingName()) + .price(request.getPrice()) + .build()); + } + + shoppingCartRepository.save(shoppingCart); + + } + + + /** + * 장바구니에서 특정 항목을 삭제한다. + * + * @author woody35545(구건모) + */ + public void deleteShoppingCartItem(String shoppingCartId, String bookId) { + Optional shoppingCart = shoppingCartRepository.findById(shoppingCartId); + + if (shoppingCart.isPresent()) { + shoppingCart.get().getShoppingCartItemMap().remove(bookId); + shoppingCartRepository.save(shoppingCart.get()); + } + } + +} From d6e26938c73775f1e250554ed322e39657eb2f8e Mon Sep 17 00:00:00 2001 From: woody35545 Date: Thu, 16 May 2024 05:41:26 +0900 Subject: [PATCH 43/53] =?UTF-8?q?feat:=20#107=20`detail.html`=20-=20?= =?UTF-8?q?=EC=9E=A5=EB=B0=94=EA=B5=AC=EB=8B=88=20=EC=B6=94=EA=B0=80?= =?UTF-8?q?=EC=8B=9C=20=ED=95=84=EC=9A=94=ED=95=9C=20=EC=A0=95=EB=B3=B4=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/templates/main/page/detail.html | 102 ++++++++++++------ 1 file changed, 70 insertions(+), 32 deletions(-) diff --git a/src/main/resources/templates/main/page/detail.html b/src/main/resources/templates/main/page/detail.html index c0b48d81..f86b065d 100644 --- a/src/main/resources/templates/main/page/detail.html +++ b/src/main/resources/templates/main/page/detail.html @@ -19,10 +19,13 @@