From a1cb33d9c48b8308b8e5eeafe8604a09b4b00726 Mon Sep 17 00:00:00 2001 From: winter0123 Date: Fri, 19 Jul 2024 10:15:31 +0900 Subject: [PATCH] =?UTF-8?q?[Orders]=20=EC=B9=B4=EC=B9=B4=EC=98=A4=20?= =?UTF-8?q?=EA=B2=B0=EC=A0=9C=20=ED=99=98=EB=B6=88=20(#106)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/BaseResponseMessage.java | 2 + .../greenplate/config/SecurityConfig.java | 30 +-- .../orders/controller/OrdersController.java | 36 ++-- .../orders/model/entity/Orders.java | 1 + .../response/OrderUserSearchDetailRes.java | 2 + .../model/response/OrderUserSearchRes.java | 2 + .../orders/service/OrdersService.java | 181 ++++++++++++++---- .../src/main/resources/application.yml | 24 +-- .../src/main/resources/static/pay.html | 4 +- 9 files changed, 200 insertions(+), 82 deletions(-) diff --git a/green-plate/src/main/java/com/team404x/greenplate/common/BaseResponseMessage.java b/green-plate/src/main/java/com/team404x/greenplate/common/BaseResponseMessage.java index e469509..fcc603a 100644 --- a/green-plate/src/main/java/com/team404x/greenplate/common/BaseResponseMessage.java +++ b/green-plate/src/main/java/com/team404x/greenplate/common/BaseResponseMessage.java @@ -79,6 +79,8 @@ public enum BaseResponseMessage { ORDERS_CREATED_FAIL(false, 5401, "주문 실패하였습니다."), ORDERS_CREATED_FAIL_STOCK(false, 5401, "상품재고가 부족합니다."), ORDERS_SEARCH_FAIL_ORDERED(false, 5111, "해당주문을 찾을 수 없습니다."), + ORDERS_CANCEL_SUCCESS_KAKAO(false, 5500, "카카오페이 결제 취소되었습니다."), + ORDERS_CANCEL_FAIL_KAKAO(false, 5501, "카카오페이 결제 취소 실패하였습니다."), USER_CREATE_SUCCESS(true, 3200, "상품 등록이 완료되었습니다"), USER_CREATE_FAIL(false,3201,"상품을 등록하는데 실패했습니다"), diff --git a/green-plate/src/main/java/com/team404x/greenplate/config/SecurityConfig.java b/green-plate/src/main/java/com/team404x/greenplate/config/SecurityConfig.java index 4d25ad3..8c6a774 100644 --- a/green-plate/src/main/java/com/team404x/greenplate/config/SecurityConfig.java +++ b/green-plate/src/main/java/com/team404x/greenplate/config/SecurityConfig.java @@ -37,21 +37,21 @@ public AuthenticationManager authenticationManager(AuthenticationConfiguration a } // 카카오페이 테스트시 필요하여 넣음 -// @Bean -// public CorsFilter corsFilter() { -// CorsConfiguration config = new CorsConfiguration(); -// -// config.addAllowedOrigin("http://localhost:63342"); // 허용할 출처 -// config.addAllowedOrigin("http://localhost:8080"); // 허용할 출처 -// config.addAllowedMethod("*"); // 허용할 메서드 (GET, POST, PUT 등) -// config.addAllowedHeader("*"); // 허용할 헤더 -// config.setAllowCredentials(true); // 자격 증명 허용 -// -// UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); -// source.registerCorsConfiguration("/**", config); -// -// return new CorsFilter(source); -// } + @Bean + public CorsFilter corsFilter() { + CorsConfiguration config = new CorsConfiguration(); + + config.addAllowedOrigin("http://localhost:63342"); // 허용할 출처 + config.addAllowedOrigin("http://localhost:8080"); // 허용할 출처 + config.addAllowedMethod("*"); // 허용할 메서드 (GET, POST, PUT 등) + config.addAllowedHeader("*"); // 허용할 헤더 + config.setAllowCredentials(true); // 자격 증명 허용 + + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + source.registerCorsConfiguration("/**", config); + + return new CorsFilter(source); + } @Bean public SecurityFilterChain filterChain (HttpSecurity http) throws Exception { diff --git a/green-plate/src/main/java/com/team404x/greenplate/orders/controller/OrdersController.java b/green-plate/src/main/java/com/team404x/greenplate/orders/controller/OrdersController.java index de1dfaf..0519c4a 100644 --- a/green-plate/src/main/java/com/team404x/greenplate/orders/controller/OrdersController.java +++ b/green-plate/src/main/java/com/team404x/greenplate/orders/controller/OrdersController.java @@ -13,6 +13,7 @@ import com.team404x.greenplate.orders.service.OrdersService; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; import java.io.IOException; @@ -94,24 +95,27 @@ public BaseResponse inputInvoice(@RequestBody OrderInvoiceReq orderInvoiceReq) { //String impUid /** kakao pay 결제 **/ - @PostMapping(value = "/kakao") - public ResponseEntity kakao(@RequestBody OrderCreateReq orderCreateReq) throws IamportResponseException, IOException { - - System.out.println(orderCreateReq.getUserId()); - System.out.println(orderCreateReq.getTotalPrice()); - + @PostMapping(value = "/kakaoPay") + public ResponseEntity kakaoPay(@RequestBody OrderCreateReq orderCreateReq) throws IamportResponseException, IOException { IamportResponse info = ordersService.getPaymentInfo(orderCreateReq.getImpUid()); - BaseResponse result = ordersService.createOrder(orderCreateReq); - - //if(resultPay) { + System.out.println(orderCreateReq.getImpUid()); + Boolean payCheck = ordersService.payCheck(orderCreateReq,info); + if(payCheck) { System.out.println("ok"); - + BaseResponse resultPay = ordersService.createOrder(orderCreateReq); return ResponseEntity.ok("ok"); - //} -// else { -// System.out.println("error"); -// //paymentService.refund(impUid, info); -// return ResponseEntity.ok("error"); -// } + } + else { + System.out.println("error"); + ordersService.refund(orderCreateReq, info); + return ResponseEntity.ok("error"); + } + } + + /** kakao pay 결제 **/ + @PostMapping(value = "/kakaoRefund") + public BaseResponse kakaoRefund(@RequestBody OrderCancelReq orderCancelReq) throws IamportResponseException, IOException { + BaseResponse result = ordersService.kakaoPayRefund(orderCancelReq); + return result; } } diff --git a/green-plate/src/main/java/com/team404x/greenplate/orders/model/entity/Orders.java b/green-plate/src/main/java/com/team404x/greenplate/orders/model/entity/Orders.java index 7ee4029..742074d 100644 --- a/green-plate/src/main/java/com/team404x/greenplate/orders/model/entity/Orders.java +++ b/green-plate/src/main/java/com/team404x/greenplate/orders/model/entity/Orders.java @@ -46,6 +46,7 @@ public class Orders { private String addressDetail; private String phoneNum; private String invoice; + private String impUid; @ColumnDefault("false") private Boolean delYn; diff --git a/green-plate/src/main/java/com/team404x/greenplate/orders/model/response/OrderUserSearchDetailRes.java b/green-plate/src/main/java/com/team404x/greenplate/orders/model/response/OrderUserSearchDetailRes.java index 8dc2401..4af4e3b 100644 --- a/green-plate/src/main/java/com/team404x/greenplate/orders/model/response/OrderUserSearchDetailRes.java +++ b/green-plate/src/main/java/com/team404x/greenplate/orders/model/response/OrderUserSearchDetailRes.java @@ -1,10 +1,12 @@ package com.team404x.greenplate.orders.model.response; +import lombok.Builder; import lombok.Data; import java.time.LocalDateTime; @Data +@Builder public class OrderUserSearchDetailRes { private Long order_id; private Long orderDetail_id; diff --git a/green-plate/src/main/java/com/team404x/greenplate/orders/model/response/OrderUserSearchRes.java b/green-plate/src/main/java/com/team404x/greenplate/orders/model/response/OrderUserSearchRes.java index d8705bd..81b13fe 100644 --- a/green-plate/src/main/java/com/team404x/greenplate/orders/model/response/OrderUserSearchRes.java +++ b/green-plate/src/main/java/com/team404x/greenplate/orders/model/response/OrderUserSearchRes.java @@ -1,10 +1,12 @@ package com.team404x.greenplate.orders.model.response; +import lombok.Builder; import lombok.Data; import java.time.LocalDateTime; @Data +@Builder public class OrderUserSearchRes { private Long order_id; private LocalDateTime order_date; diff --git a/green-plate/src/main/java/com/team404x/greenplate/orders/service/OrdersService.java b/green-plate/src/main/java/com/team404x/greenplate/orders/service/OrdersService.java index 38efafe..5ed6d3f 100644 --- a/green-plate/src/main/java/com/team404x/greenplate/orders/service/OrdersService.java +++ b/green-plate/src/main/java/com/team404x/greenplate/orders/service/OrdersService.java @@ -1,11 +1,12 @@ package com.team404x.greenplate.orders.service; import com.google.gson.Gson; -import com.google.gson.internal.LinkedTreeMap; +import com.google.gson.JsonObject; import com.querydsl.jpa.impl.JPAQueryFactory; import com.siot.IamportRestClient.IamportClient; import com.siot.IamportRestClient.exception.IamportResponseException; import com.siot.IamportRestClient.request.CancelData; +import com.siot.IamportRestClient.response.AccessToken; import com.siot.IamportRestClient.response.IamportResponse; import com.siot.IamportRestClient.response.Payment; import com.team404x.greenplate.common.BaseResponse; @@ -29,14 +30,21 @@ import jakarta.persistence.EntityNotFoundException; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.client.RestTemplate; + +import javax.net.ssl.HttpsURLConnection; +import java.io.BufferedWriter; +import java.net.URL; import java.time.LocalDateTime; import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Optional; +import java.util.*; import static com.team404x.greenplate.common.BaseResponseMessage.*; @@ -56,6 +64,11 @@ public class OrdersService { JPAQueryFactory queryFactory; + @Value("${imp.imp_key}") + private String impKey; + @Value("${imp.imp_secret}") + private String impSecret; + @Transactional public BaseResponse chosePayment(OrderCreateReq orderCreateReq) { @@ -108,6 +121,7 @@ public BaseResponse createOrder(OrderCreateReq orderCreateReq) { .addressDetail(orderCreateReq.getAddressDetail()) .phoneNum(orderCreateReq.getPhoneNum()) .refundYn(false) + .impUid(orderCreateReq.getImpUid()) .build(); orders = ordersRepository.save(orders); @@ -132,7 +146,6 @@ public BaseResponse createOrder(OrderCreateReq orderCreateReq) { } return new BaseResponse<>(ORDERS_CREATED_SUCCESS); - } //유저 주문 상품 목록 조회 @@ -147,14 +160,15 @@ public BaseResponse> searchForUser(Long userId) { List orderUserSearchResList = new ArrayList(); List orders = ordersRepository.findAllByUser(user.get()); for(Orders order : orders){ - OrderUserSearchRes orderUserSearchRes = new OrderUserSearchRes(); - orderUserSearchRes.setOrder_id(order.getId()); - orderUserSearchRes.setOrder_state(order.getOrderState()); - orderUserSearchRes.setTotal_price(order.getTotalPrice()); - orderUserSearchRes.setTotal_cnt(order.getTotalQuantity()); - orderUserSearchRes.setRefund_yn(order.getRefundYn()); - orderUserSearchRes.setOrder_date(order.getOrderDate()); - orderUserSearchResList.add(orderUserSearchRes); + OrderUserSearchRes res = OrderUserSearchRes.builder() + .order_id(order.getId()) + .order_state(order.getOrderState()) + .total_price(order.getTotalPrice()) + .total_cnt(order.getTotalQuantity()) + .refund_yn(order.getRefundYn()) + .order_date(order.getOrderDate()) + .build(); + orderUserSearchResList.add(res); } return new BaseResponse<>(orderUserSearchResList); } @@ -175,14 +189,18 @@ public BaseResponse> searchForUserDetail(Long use List orderUserSearchResList = new ArrayList(); for(OrderDetail orderDetail : orderDetailList){ - OrderUserSearchDetailRes orderUserSearchDetailRes = new OrderUserSearchDetailRes(); - orderUserSearchDetailRes.setOrder_id(orders2.getId()); - orderUserSearchDetailRes.setOrder_state(orders2.getOrderState()); - orderUserSearchDetailRes.setPrice(orderDetail.getPrice()); - orderUserSearchDetailRes.setCnt(orderDetail.getCnt()); - orderUserSearchDetailRes.setRefund_yn(orders2.getRefundYn()); - orderUserSearchDetailRes.setOrder_date(orders2.getOrderDate()); - orderUserSearchResList.add(orderUserSearchDetailRes); + + OrderUserSearchDetailRes res = OrderUserSearchDetailRes.builder() + .order_id(orders2.getId()) + .orderDetail_id(orderDetail.getId()) + .order_state(orders2.getOrderState()) + .price(orderDetail.getPrice()) + .cnt(orderDetail.getCnt()) + .refund_yn(orders2.getRefundYn()) + .order_date(orders2.getOrderDate()) + .build(); + orderUserSearchResList.add(res); + } return new BaseResponse<>(orderUserSearchResList); } @@ -212,20 +230,7 @@ public BaseResponse> searchForCompanyDetail(Long com return new BaseResponse<>(ordersList); } - //주문취소 - @Transactional - public BaseResponse cancelOrder(OrderCancelReq orderCancelReq) { - Optional orders = ordersRepository.findById(orderCancelReq.getOrderId()); - if (!orders.isPresent()) { - return new BaseResponse<>(ORDERS_SEARCH_FAIL_ORDERED); - }else{ - Orders orders2 = orders.get(); - orders2.refundOrder(); - ordersRepository.save(orders2); - } - return new BaseResponse<>(ORDERS_CANCEL_SUCCESS); - } //사업자 배송 상태 변경 @Transactional @@ -264,15 +269,117 @@ public BaseResponse inputInvoice(OrderInvoiceReq orderInvoiceReq) { return new BaseResponse<>(ORDERS_UPDATE_SUCCESS_INVOICE); } - public IamportResponse getPaymentInfo(String impUid) throws IamportResponseException, IOException { - + //카카오페이 결제금액 체크 + public Boolean payCheck(OrderCreateReq orderCreateReq, IamportResponse iamportResponse) { + Long amount = iamportResponse.getResponse().getAmount().longValue(); + if (amount != orderCreateReq.getTotalPrice()){ + return false; + }else{ + return true; + } + } + public IamportResponse getPaymentInfo(String impUid) throws IamportResponseException, IOException { return iamportClient.paymentByImpUid(impUid); } + //카카오페이 결제중 환불 public IamportResponse refund(OrderCreateReq orderCreateReq, IamportResponse info) throws IamportResponseException, IOException { CancelData cancelData = new CancelData(orderCreateReq.getImpUid(), true, info.getResponse().getAmount()); return iamportClient.cancelPaymentByImpUid(cancelData); } + //카카오페이 결제 완료 후 환불 + public BaseResponse kakaoPayRefund(OrderCancelReq orderCancelReq) { + Optional orders = ordersRepository.findById(orderCancelReq.getOrderId()); + if (!orders.isPresent()) { + return new BaseResponse<>(ORDERS_SEARCH_FAIL_ORDERED); + } + + String accessToken = getAccessToken(); //토큰 요청 + if(requestsRefun(accessToken, orders.get())){ //카카오페이 결제 취소 + cancelOrder(orderCancelReq); //주문취소 데이터 저장 + return new BaseResponse<>(ORDERS_CANCEL_FAIL_KAKAO); + }; + + return new BaseResponse<>(ORDERS_CANCEL_SUCCESS_KAKAO); + } + + //카카오페이 결제 취소용 TOKEN + public String getAccessToken() { + HttpHeaders headers = new HttpHeaders(); + headers.add(HttpHeaders.CONTENT_TYPE, "application/json"); + headers.add(HttpHeaders.ACCEPT, "application/json"); + + Gson gson = new Gson(); + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("imp_key", impKey); + jsonObject.addProperty("imp_secret", impSecret); + String jsonStr = gson.toJson(jsonObject); + + + HttpEntity request = new HttpEntity<>(jsonStr, headers); + RestTemplate restTemplate = new RestTemplate(); + ResponseEntity response = restTemplate.exchange( + "https://api.iamport.kr/users/getToken", + HttpMethod.POST, + request, + String.class + ); + + Map result = gson.fromJson(response.getBody(), Map.class); + Map data = (Map) result.get("response"); + String access_token = (String) data.get("access_token"); + return access_token; + } + + //pg사 kakao 결제 취소 요청 + public Boolean requestsRefun(String accessToken, Orders orders){ + HttpHeaders headers = new HttpHeaders(); + try{ + headers.add(HttpHeaders.CONTENT_TYPE, "application/json"); + headers.add(HttpHeaders.ACCEPT, "application/json"); + headers.add(HttpHeaders.AUTHORIZATION, accessToken); + + Gson gson = new Gson(); + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("reason", "결제 정보가 이상합니다."); + jsonObject.addProperty("imp_uid", orders.getImpUid()); + jsonObject.addProperty("amount", orders.getTotalPrice()); + String jsonStr = gson.toJson(jsonObject); + + HttpEntity request = new HttpEntity<>(jsonStr, headers); + RestTemplate restTemplate = new RestTemplate(); + ResponseEntity response = restTemplate.exchange( + "https://api.iamport.kr/payments/cancel", + HttpMethod.POST, + request, + String.class + ); + + Map result = gson.fromJson(response.getBody(), Map.class); + System.out.println(result); + }catch(Exception e){ + return false; + } + + return true; + } + + //주문취소 데이터 저장 + @Transactional + public BaseResponse cancelOrder(OrderCancelReq orderCancelReq) { + Optional orders = ordersRepository.findById(orderCancelReq.getOrderId()); + + if (!orders.isPresent()) { + return new BaseResponse<>(ORDERS_SEARCH_FAIL_ORDERED); + }else{ + Orders orders2 = orders.get(); + orders2.refundOrder(); + ordersRepository.save(orders2); + } + return new BaseResponse<>(ORDERS_CANCEL_SUCCESS); + } + + } diff --git a/green-plate/src/main/resources/application.yml b/green-plate/src/main/resources/application.yml index ffc04cc..570f7d5 100644 --- a/green-plate/src/main/resources/application.yml +++ b/green-plate/src/main/resources/application.yml @@ -29,18 +29,18 @@ spring: timeout: 5000 writetimeout: 5000 -cloud: - aws: - s3: - bucket: ${BUCKET} - credentials: - access-key: ${ACCESS_KEY} - secret-key: ${SECRET_KEY} - region: - static: ${REGION_STATIC} - auto: false - stack: - auto: false +#cloud: +# aws: +# s3: +# bucket: ${BUCKET} +# credentials: +# access-key: ${ACCESS_KEY} +# secret-key: ${SECRET_KEY} +# region: +# static: ${REGION_STATIC} +# auto: false +# stack: +# auto: false imp: imp_key: ${IPM_KEY} diff --git a/green-plate/src/main/resources/static/pay.html b/green-plate/src/main/resources/static/pay.html index 0d1e565..1cae6f5 100644 --- a/green-plate/src/main/resources/static/pay.html +++ b/green-plate/src/main/resources/static/pay.html @@ -19,7 +19,7 @@ IMP.request_pay( { pg: "kakaopay.TC0ONETIME", - merchant_uid: "order_no_064", + merchant_uid: "order_no_070", name: "order_test", amount: 20, buyer_email: "test01@test.com", @@ -52,7 +52,7 @@ } // 백엔드로 주문 생성 요청 - axios.post("http://localhost:8080/orders/kakao", orderCreateReq).then((response) => { + axios.post("http://localhost:8080/orders/kakaoPay", orderCreateReq).then((response) => { console.log(response.data); if (response.data === "ok") { alert('success');