Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public ResponseEntity<PagedResponse<CommentPageWrapperDto>> readAll(@PathVariabl
@RequestParam("page") int page,
@RequestParam("pageSize") int pageSize) {
int correctPage = Math.max(page, 1);
int correctPageSize = Math.max(1, Math.max(pageSize, pageSizeLimit));
int correctPageSize = Math.max(1, Math.min(pageSize, pageSizeLimit));
CommentPageResponseDto commentsInfo = commentService.readAll(lessonId, correctPage, correctPageSize);
CommentPageWrapperDto comments = CommentMapper.toCommentPageWrapperDto(commentsInfo);
return PagedResponse.ok("댓글 조회 성공", comments, commentsInfo.getCount(), HttpStatus.OK);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,41 @@
package com.threestar.trainus.domain.payment.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.threestar.trainus.domain.payment.dto.CancelPaymentRequest;
import com.threestar.trainus.domain.payment.dto.ConfirmPaymentRequest;
import com.threestar.trainus.domain.payment.dto.CancelPaymentRequestDto;
import com.threestar.trainus.domain.payment.dto.ConfirmPaymentRequestDto;
import com.threestar.trainus.domain.payment.dto.PaymentClient;
import com.threestar.trainus.domain.payment.dto.PaymentRequestDto;
import com.threestar.trainus.domain.payment.dto.PaymentResponseDto;
import com.threestar.trainus.domain.payment.dto.SaveAmountRequest;
import com.threestar.trainus.domain.payment.dto.SaveAmountRequestDto;
import com.threestar.trainus.domain.payment.dto.TossPaymentResponseDto;
import com.threestar.trainus.domain.payment.dto.failure.FailurePaymentResponseDto;
import com.threestar.trainus.domain.payment.dto.failure.PaymentFailureHistoryPageDto;
import com.threestar.trainus.domain.payment.dto.failure.PaymentFailurePageWrapperDto;
import com.threestar.trainus.domain.payment.dto.success.PaymentSuccessHistoryPageDto;
import com.threestar.trainus.domain.payment.dto.success.PaymentSuccessPageWrapperDto;
import com.threestar.trainus.domain.payment.dto.success.SuccessfulPaymentResponseDto;
import com.threestar.trainus.domain.payment.mapper.PaymentMapper;
import com.threestar.trainus.domain.payment.service.PaymentService;
import com.threestar.trainus.global.unit.BaseResponse;
import com.threestar.trainus.global.unit.PagedResponse;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpSession;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Tag(name = "결제 API", description = "결제, 검증, 취소 API")
@Slf4j
@RestController
@RequestMapping("/api/v1/payments")
Expand All @@ -31,48 +45,94 @@ public class PaymentController {
private final PaymentClient tossPaymentClient;
private final PaymentService paymentService;

@Value("${spring.page.size.limit}")
private int pageSizeLimit;

@PostMapping("/prepare")
@Operation(summary = "결제 준비", description = "실제 결제 전 최종 가격 적용 후 결제 준비")
public ResponseEntity<BaseResponse<PaymentResponseDto>> preparePayment(HttpSession session,
@RequestBody PaymentRequestDto request) {
Long userId = (Long)session.getAttribute("LOGIN_USER");
PaymentResponseDto response = paymentService.preparePayment(request, userId);
//여기에서 쿠폰 가격 정해서 답변 내보내고 이를 통해 아래 호출
return BaseResponse.ok("결제 정보 준비 완료", response, HttpStatus.OK);
}

@PostMapping("/saveAmount")
public ResponseEntity<BaseResponse<Void>> saveAmount(HttpSession session, @RequestBody SaveAmountRequest request) {
session.setAttribute(request.getOrderId(), request.getAmount());
@Operation(summary = "결제 검증 데이터 저장", description = "결제 무결성 검증을 위한 데이터 저장")
public ResponseEntity<BaseResponse<Void>> saveAmount(HttpSession session,
@RequestBody SaveAmountRequestDto request) {
session.setAttribute(request.orderId(), request.amount());
return BaseResponse.ok("Payment temp save Successful", null, HttpStatus.OK);
}

@PostMapping("/verifyAmount")
@Operation(summary = "결제 검증 데이터 확인", description = "결제 무결성 검증을 위한 데이터 확인")
public ResponseEntity<BaseResponse<Void>> verifyAmount(HttpSession session,
@RequestBody SaveAmountRequest request) {
Integer amount = (Integer)session.getAttribute(request.getOrderId());
log.info("amount = {}", amount);

@RequestBody SaveAmountRequestDto request) {
Integer amount = (Integer)session.getAttribute(request.orderId());
try {
if (amount == null || !amount.equals(request.getAmount())) {
if (amount == null || !amount.equals(request.amount())) {
return BaseResponse.error("결제 금액 정보가 유효하지 않습니다", null, HttpStatus.BAD_REQUEST);
}
return BaseResponse.ok("Payment is valid", null, HttpStatus.OK);
} finally {
session.removeAttribute(request.getOrderId());
session.removeAttribute(request.orderId());
}
}

@PostMapping("/confirm")
public ResponseEntity<BaseResponse<Void>> confirm(@RequestBody ConfirmPaymentRequest request) {
@Operation(summary = "결제 진행", description = "결제 진행")
public ResponseEntity<BaseResponse<SuccessfulPaymentResponseDto>> confirm(
@RequestBody ConfirmPaymentRequestDto request) {
TossPaymentResponseDto tossResponse = tossPaymentClient.confirmPayment(request);
paymentService.processConfirm(tossResponse);
return BaseResponse.ok("결제 성공", null, HttpStatus.OK);
SuccessfulPaymentResponseDto payResult = paymentService.processConfirm(tossResponse);
return BaseResponse.ok("결제 성공", payResult, HttpStatus.OK);
}

@PostMapping("/cancel")
public ResponseEntity<BaseResponse<Void>> cancel(@RequestBody CancelPaymentRequest request) {
@Operation(summary = "결제 취소", description = "결제 취소")
public ResponseEntity<BaseResponse<FailurePaymentResponseDto>> cancel(
@RequestBody CancelPaymentRequestDto request) {
TossPaymentResponseDto tossResponse = tossPaymentClient.cancelPayment(request);
paymentService.processCancel(tossResponse);
return BaseResponse.ok("결제 취소 성공", null, HttpStatus.OK);
FailurePaymentResponseDto payResult = paymentService.processCancel(tossResponse, request.cancelReason());
return BaseResponse.ok("결제 취소 성공", payResult, HttpStatus.OK);
}

@GetMapping("/view/success")
@Operation(summary = "완료 결제 조회", description = "완료된 결제 내역 조회")
public ResponseEntity<PagedResponse<PaymentSuccessPageWrapperDto>> readAll(HttpSession session,
@RequestParam("page") int page,
@RequestParam("pageSize") int pageSize) {
Long userId = (Long)session.getAttribute("LOGIN_USER");
int correctPage = Math.max(page, 1);
int correctPageSize = Math.max(1, Math.min(pageSize, pageSizeLimit));
PaymentSuccessHistoryPageDto paymentSuccessHistoryPageDto = paymentService.viewAllSuccessTransaction(userId,
correctPage, correctPageSize);
PaymentSuccessPageWrapperDto payments = PaymentMapper.toPaymentSuccessPageWrapperDto(
paymentSuccessHistoryPageDto);
return PagedResponse.ok("성공 결제 조회 성공", payments, paymentSuccessHistoryPageDto.count(), HttpStatus.OK);
}

@GetMapping("/view/cancel")
@Operation(summary = "취소 결제 조회", description = "취소된 결제 내역 조회")
public ResponseEntity<PagedResponse<PaymentFailurePageWrapperDto>> readAllFailure(HttpSession session,
@RequestParam("page") int page,
@RequestParam("pageSize") int pageSize) {
Long userId = (Long)session.getAttribute("LOGIN_USER");
int correctPage = Math.max(page, 1);
int correctPageSize = Math.max(1, Math.min(pageSize, pageSizeLimit));
PaymentFailureHistoryPageDto paymentFailureHistoryPageDto = paymentService.viewAllFailureTransaction(userId,
correctPage, correctPageSize);
PaymentFailurePageWrapperDto payments = PaymentMapper.toPaymentFailurePageWrapperDto(
paymentFailureHistoryPageDto);
return PagedResponse.ok("취소 결제 조회 성공", payments, paymentFailureHistoryPageDto.count(), HttpStatus.OK);
}

@GetMapping("/{paymentKey}")
@Operation(summary = "상세 결제 조회", description = "상세 결제 내역 조회")
public ResponseEntity<BaseResponse<TossPaymentResponseDto>> readDetailPayment(
@PathVariable("paymentKey") String paymentKey) {
return BaseResponse.ok("상세 결제 조회 완료", tossPaymentClient.viewDetailPayment(paymentKey), HttpStatus.OK);
}

}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.threestar.trainus.domain.payment.dto;

import jakarta.validation.constraints.NotNull;

public record CancelPaymentRequestDto(
@NotNull(message = "필수 값입니다.")
String paymentKey,
@NotNull(message = "실패 원인은 필수입니다.")
String cancelReason
) {
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.threestar.trainus.domain.payment.dto;

import jakarta.validation.constraints.NotNull;

public record ConfirmPaymentRequestDto(
int amount,
@NotNull(message = "필수 값입니다.")
String orderId,
@NotNull(message = "필수 값입니다.")
String paymentKey
) {

}
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,12 @@ public PaymentClient(PaymentProperties paymentProperties) {
}

private String createPaymentAuthHeader(PaymentProperties paymentProperties) {
log.info("secret-key : {}, url ={} baseUrl = {}, baseUrl2 = {}", paymentProperties.getSecretKey(),
paymentProperties.getBaseUrl(), paymentProperties.getConfirmEndPoint(),
paymentProperties.getCancelEndPoint());
byte[] encodedBytes = Base64.getEncoder()
.encode((paymentProperties.getSecretKey() + BASIC_DELIMITER).getBytes(StandardCharsets.UTF_8));
log.info("new Header = {}", AUTH_HEADER_PREFIX + new String(encodedBytes));
return AUTH_HEADER_PREFIX + new String(encodedBytes);
}

public TossPaymentResponseDto confirmPayment(ConfirmPaymentRequest request) {
log.info("Sending Toss confirm request: orderId={}, amount={}, paymentKey={}",
request.getOrderId(), request.getAmount(), request.getPaymentKey());
public TossPaymentResponseDto confirmPayment(ConfirmPaymentRequestDto request) {

return restClient.post()
.uri(paymentProperties.getConfirmEndPoint())
Expand All @@ -56,9 +50,9 @@ public TossPaymentResponseDto confirmPayment(ConfirmPaymentRequest request) {
.body(TossPaymentResponseDto.class);
}

public TossPaymentResponseDto cancelPayment(CancelPaymentRequest request) {
public TossPaymentResponseDto cancelPayment(CancelPaymentRequestDto request) {
return restClient.post()
.uri(String.format(paymentProperties.getCancelEndPoint(), request.getPaymentKey()))
.uri(String.format(paymentProperties.getCancelEndPoint(), request.paymentKey()))
.contentType(MediaType.APPLICATION_JSON)
.body(request)
.retrieve()
Expand All @@ -68,4 +62,14 @@ public TossPaymentResponseDto cancelPayment(CancelPaymentRequest request) {
.body(TossPaymentResponseDto.class);
}

public TossPaymentResponseDto viewDetailPayment(String paymentKey) {
return restClient.get()
.uri(paymentProperties.getViewEndPoint() + "/" + paymentKey)
.retrieve()
.onStatus(HttpStatusCode::isError, (req, res) -> {
throw new BusinessException(ErrorCode.INVALID_PAYMENT);
})
.body(TossPaymentResponseDto.class);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ public class PaymentProperties {
private String baseUrl;
private String confirmEndPoint;
private String cancelEndPoint;
private String viewEndPoint;
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
package com.threestar.trainus.domain.payment.dto;

import com.threestar.trainus.domain.payment.entity.PaymentMethod;
import jakarta.validation.constraints.NotNull;

import lombok.Data;

@Data
public class PaymentRequestDto {
private Long lessonId;
private Long userCouponId;
private PaymentMethod paymentMethod;
public record PaymentRequestDto(
@NotNull(message = "필수 값입니다.")
Long lessonId,
Long userCouponId
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,14 @@
import com.threestar.trainus.domain.payment.entity.PaymentMethod;

import lombok.Builder;
import lombok.Data;

@Builder
@Data
public class PaymentResponseDto {
private String orderId;
private String lessonTitle;
private Integer originPrice;
private Integer payPrice;
private PaymentMethod paymentMethod;
private LocalDateTime expiredAt;
public record PaymentResponseDto(
String orderId,
String lessonTitle,
Integer originPrice,
Integer payPrice,
PaymentMethod paymentMethod,
LocalDateTime expiredAt
) {
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.threestar.trainus.domain.payment.dto;

public record SaveAmountRequestDto(
String orderId,
int amount
) {
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,13 @@
package com.threestar.trainus.domain.payment.dto;

import java.time.LocalDateTime;

import com.threestar.trainus.domain.payment.entity.PaymentStatus;

import lombok.Getter;

@Getter
public class TossPaymentResponseDto {
private String paymentKey;
private String orderId;
private String orderName;
private String status;
private String requestedAt;
private String approvedAt;
private int totalAmount;
private String method;
public record TossPaymentResponseDto(
String paymentKey,
String orderId,
String orderName,
String status,
String requestedAt,
String approvedAt,
int totalAmount,
String method
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.threestar.trainus.domain.payment.dto.failure;

import java.time.LocalDateTime;

import lombok.Builder;

@Builder
public record FailurePaymentResponseDto(
String lessonName,
String cancelReason,
LocalDateTime startAt,
LocalDateTime endAt,
LocalDateTime paymentCancelledAt,
int payPrice
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.threestar.trainus.domain.payment.dto.failure;

import java.util.List;

import lombok.Builder;

@Builder
public record PaymentFailureHistoryPageDto(
Integer count,
List<PaymentFailureHistoryResponseDto> failureHistory
) {
}
Loading