-
Notifications
You must be signed in to change notification settings - Fork 2
Feat#213 : iamport로 결제 기능 구현 #214
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
a883df7
f5a0c41
45b9f73
77966e3
05f697c
7265f3f
e409b7a
c15c1ab
837dc75
ebc3f68
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| package friend.spring.apiPayload.handler; | ||
|
|
||
| import friend.spring.apiPayload.GeneralException; | ||
| import friend.spring.apiPayload.code.BaseErrorCode; | ||
|
|
||
| public class PaymentHandler extends GeneralException { | ||
| public PaymentHandler(BaseErrorCode code) { | ||
| super(code); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| package friend.spring.config; | ||
|
|
||
| import com.siot.IamportRestClient.IamportClient; | ||
| import org.springframework.beans.factory.annotation.Value; | ||
| import org.springframework.context.annotation.Bean; | ||
| import org.springframework.context.annotation.Configuration; | ||
|
|
||
| @Configuration | ||
| public class IamportConfig { | ||
| // iamportclient를 빈으로 등록해줍니다. | ||
|
|
||
| @Value("${iamport.api_key}") | ||
| private String apiKey; | ||
|
|
||
| @Value("${iamport.api_secret}") | ||
| private String apiSecret; | ||
|
|
||
| @Bean | ||
| public IamportClient iamportClient() { | ||
| return new IamportClient(apiKey, apiSecret); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| package friend.spring.domain; | ||
|
|
||
| import friend.spring.domain.common.BaseEntity; | ||
| import friend.spring.domain.enums.Product; | ||
| import lombok.*; | ||
|
|
||
| import javax.persistence.*; | ||
| import java.math.BigDecimal; | ||
|
|
||
| @Entity | ||
| @Getter | ||
| @Builder | ||
| @AllArgsConstructor | ||
| @NoArgsConstructor(access = AccessLevel.PROTECTED) | ||
|
|
||
| public class Order extends BaseEntity { | ||
|
|
||
| @Id | ||
| @GeneratedValue(strategy = GenerationType.IDENTITY) | ||
| private Long id; | ||
|
|
||
| @Enumerated(EnumType.STRING) | ||
| private Product product; // POINT_1000, POINT_2000 일단 두개 설정해놨습니다. | ||
|
|
||
| @Column(nullable = false) | ||
| private BigDecimal price; | ||
|
|
||
| @Column(nullable = false) | ||
| private String orderUid; | ||
|
|
||
| @ManyToOne(fetch = FetchType.LAZY) | ||
| @JoinColumn(name = "user_id", nullable = false) | ||
| private User user; | ||
|
|
||
| @OneToOne(fetch = FetchType.LAZY) | ||
| @JoinColumn(name = "payment_id") | ||
| private Payment payment; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,35 +1,38 @@ | ||
| //package friend.spring.domain; | ||
| // | ||
| //import friend.spring.domain.common.BaseEntity; | ||
| //import friend.spring.domain.enums.PaymentState; | ||
| //import lombok.*; | ||
| // | ||
| //import javax.persistence.*; | ||
| //import java.math.BigDecimal; | ||
| // | ||
| //@Entity | ||
| //@Getter | ||
| //@Builder | ||
| //@AllArgsConstructor | ||
| //@NoArgsConstructor(access = AccessLevel.PROTECTED) | ||
| //public class Payment extends BaseEntity { | ||
| // | ||
| // @Id | ||
| // @GeneratedValue(strategy = GenerationType.IDENTITY) | ||
| // private Long id; | ||
| // | ||
| // @Column(nullable = false) | ||
| // private BigDecimal amount; | ||
| // | ||
| // //주문 고유 번호 | ||
| // private String merchantUid; | ||
| // | ||
| // //결제 상태 | ||
| // @Enumerated(EnumType.STRING) | ||
| // | ||
| // private PaymentState paymentState; | ||
| // | ||
| // | ||
| // | ||
| // | ||
| //} | ||
| package friend.spring.domain; | ||
|
|
||
| import friend.spring.domain.common.BaseEntity; | ||
| import friend.spring.domain.enums.PaymentState; | ||
| import lombok.*; | ||
|
|
||
| import javax.persistence.*; | ||
| import java.math.BigDecimal; | ||
|
|
||
| @Entity | ||
| @Getter | ||
| @Builder | ||
| @AllArgsConstructor | ||
| @NoArgsConstructor(access = AccessLevel.PROTECTED) | ||
| public class Payment extends BaseEntity { | ||
|
|
||
| @Id | ||
| @GeneratedValue(strategy = GenerationType.IDENTITY) | ||
| private Long id; | ||
|
|
||
| @Column(nullable = false) | ||
| private BigDecimal price; | ||
|
|
||
| //결제 상태 | ||
| @Enumerated(EnumType.STRING) | ||
| private PaymentState paymentState; | ||
|
|
||
| //주문 고유 번호 | ||
| private String paymentUid; | ||
|
|
||
|
|
||
| // 상태 변경 메서드 | ||
| public void changePaymentBySuccess(PaymentState paymentState, String paymentUid) { | ||
| this.paymentState = paymentState; | ||
| this.paymentUid = paymentUid; | ||
| } | ||
|
|
||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,5 @@ | ||
| //package friend.spring.domain.enums; | ||
| // | ||
| //public enum PaymentState { | ||
| // READY, PAID, FAILED, CANCEL | ||
| //} | ||
| package friend.spring.domain.enums; | ||
|
|
||
| public enum PaymentState { | ||
| READY, ING, PAID, CANCEL | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| package friend.spring.domain.enums; | ||
|
|
||
| public enum Product { | ||
| // 물건 가격 임시로 설정 ( 추후에 pm 님과 상의 후 fix ) | ||
| POINT_1000, POINT_2000 | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| package friend.spring.repository; | ||
|
|
||
| import friend.spring.domain.Order; | ||
| import org.springframework.data.jpa.repository.JpaRepository; | ||
| import org.springframework.data.jpa.repository.Query; | ||
| import org.springframework.data.repository.query.Param; | ||
|
|
||
| import java.util.Optional; | ||
|
|
||
| public interface OrderRepository extends JpaRepository<Order, Long> { | ||
| @Query("SELECT o FROM Order o " + "LEFT JOIN FETCH o.payment p " + "LEFT JOIN FETCH o.user m " + "WHERE o.orderUid = :orderUid") | ||
| Optional<Order> findOrderAndPaymentAndMember(@Param("orderUid") String orderUid); | ||
|
Comment on lines
+11
to
+12
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 중요한 건 아니고 그냥 궁금한 건데 여쭤봅니다! 제 생각에는 한 라인으로 표현한다면 그냥 하나의
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 복잡해서 보기 쉽게 끊어서 작성하였는데 수정하겠습니다!! |
||
|
|
||
| @Query("SELECT o FROM Order o " + "LEFT JOIN FETCH o.payment p " + "WHERE o.orderUid = :orderUid") | ||
| Optional<Order> findOrderAndPayment(@Param("orderUid") String orderUid); | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| package friend.spring.repository; | ||
|
|
||
| import friend.spring.domain.Payment; | ||
| import org.springframework.data.jpa.repository.JpaRepository; | ||
|
|
||
| public interface PaymentRepository extends JpaRepository<Payment, Long> { | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| package friend.spring.service; | ||
|
|
||
| import friend.spring.domain.Order; | ||
| import friend.spring.web.dto.OrderRequestDTO; | ||
|
|
||
| import javax.servlet.http.HttpServletRequest; | ||
|
|
||
| public interface OrderService { | ||
|
|
||
| Long createOrder(OrderRequestDTO orderRequestDTO, HttpServletRequest request); | ||
|
|
||
| Order checkOrder(Long orderId); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| package friend.spring.service; | ||
|
|
||
| import friend.spring.apiPayload.code.status.ErrorStatus; | ||
| import friend.spring.apiPayload.handler.PaymentHandler; | ||
| import friend.spring.apiPayload.handler.UserHandler; | ||
| import friend.spring.domain.Order; | ||
| import friend.spring.domain.Payment; | ||
| import friend.spring.domain.User; | ||
| import friend.spring.domain.enums.PaymentState; | ||
| import friend.spring.domain.enums.Product; | ||
| import friend.spring.repository.OrderRepository; | ||
| import friend.spring.repository.PaymentRepository; | ||
| import friend.spring.repository.UserRepository; | ||
| import friend.spring.security.JwtTokenProvider; | ||
| import friend.spring.web.dto.OrderRequestDTO; | ||
| import lombok.RequiredArgsConstructor; | ||
| import org.springframework.stereotype.Service; | ||
|
|
||
| import javax.servlet.http.HttpServletRequest; | ||
| import java.math.BigDecimal; | ||
| import java.util.UUID; | ||
|
|
||
| @Service | ||
| @RequiredArgsConstructor | ||
| public class OrderServiceImpl implements OrderService{ | ||
|
|
||
| private final JwtTokenProvider jwtTokenProvider; | ||
| private final UserRepository userRepository; | ||
| private final PaymentRepository paymentRepository; | ||
| private final OrderRepository orderRepository; | ||
|
|
||
|
|
||
| public Long createOrder(OrderRequestDTO orderRequestDTO, HttpServletRequest request) { | ||
| Product product = null; | ||
| long price = 0L; | ||
|
|
||
| if(orderRequestDTO.getItemName().equals("POINT_1000")) { | ||
| product = Product.POINT_1000; | ||
| price = 1000L; | ||
| } else if (orderRequestDTO.getItemName().equals("POINT_2000")) { | ||
| product = Product.POINT_2000; | ||
| price = 2000L; | ||
| } | ||
| else { | ||
| throw new PaymentHandler(ErrorStatus.ORDER_PRODUCT_NOT_FOUND); | ||
| } | ||
|
|
||
| Long userId = jwtTokenProvider.getCurrentUser(request); | ||
| User user = userRepository.findById(userId).orElseThrow(() -> { | ||
| throw new UserHandler(ErrorStatus.USER_NOT_FOUND); | ||
| }); | ||
|
|
||
| Payment payment = Payment.builder() | ||
| .price(BigDecimal.valueOf(price)) | ||
| .paymentState(PaymentState.ING) | ||
| .build(); | ||
|
|
||
| paymentRepository.save(payment); | ||
|
|
||
| Order order = Order.builder() | ||
| .user(user) | ||
| .price(BigDecimal.valueOf(price)) | ||
| .product(product) | ||
| .orderUid(UUID.randomUUID().toString()) | ||
| .payment(payment) | ||
| .build(); | ||
|
|
||
| Order result = orderRepository.save(order); | ||
|
|
||
| return result.getId(); | ||
| } | ||
|
|
||
| // 주문 체크 및 조회 | ||
| @Override | ||
| public Order checkOrder(Long orderId) { | ||
| return orderRepository.findById(orderId).orElseThrow(() -> { | ||
| throw new PaymentHandler(ErrorStatus.ORDER_NOT_FOUND); | ||
| }); | ||
| } | ||
|
|
||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| package friend.spring.service; | ||
|
|
||
| import com.siot.IamportRestClient.response.IamportResponse; | ||
|
|
||
| import com.siot.IamportRestClient.response.Payment; | ||
| import friend.spring.web.dto.PaymentCallback; | ||
| import friend.spring.web.dto.PaymentResponseDTO; | ||
|
|
||
| public interface PaymentService { | ||
|
|
||
| String previewOrderUid(Long orderId); | ||
|
|
||
| PaymentResponseDTO previewOrderResponse(String orderUid); | ||
|
|
||
| IamportResponse<Payment> paymentByCallBack(PaymentCallback paymentCallback); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BigDecimal타입을 처음 봐서 찾아봤는데 돈을 나타내는 자료형으로는BigDecimal타입이 미세한 숫자의 변동을 허용하지 않아서 더 안전하군요. 덕분에 배워갑니다!There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
😃