

결제 완료 시 payment_tb에 데이터 Insert 후 payment/success로 redirect
필요(출력) 데이터
| 페이지 데이터 | table / column | 조회할 데이터 | 
| 포스터 이미지 | movie / posterUrls | moviePosterUrl | 
| 예매번호 | payment / bookingNumber | bookingNumber | 
| 상영 일시(시작/종료시간) | showtime / startedAt | showtime/endtime | 
| 상영관 (영화관&상영관 이름) | screen / name | cinemaName/screenName | 
| 관람 인원 (예매한 인원 수) | x | people | 
| 좌석 번호 | seat / seatNumber | seatNumbers | 
| 결제 금액 | x | totalPrice | 
| 할인금액 / 관람권 or 할인권 | payment / mycoupon , point | discount(현재는 0원 고정) | 
| 총 결제 금액 (결제 금액 - 할인 금액) | payment / price | payPrice | 
관련 레이어 및 코드
1. PaymentController
- 결제 성공 후 payment/success페이지로 이동
@GetMapping("/api/payment/success")
public String paymentSuccess(HttpSession session, Model model) {
    // 세션에서 예약 ID와 총 결제 금액 가져오기
    Long sessionReservationId = (Long) session.getAttribute("sessionReservationId");
    Double sessionTotalPrice = (Double) session.getAttribute("sessionTotalPrice");
    if (sessionReservationId == null || sessionTotalPrice == null) {
        throw new ExceptionApi404("Reservation or Price data is missing.");
    }
    // 예약 정보와 결제 정보를 한 번에 조회
    PaymentResponse.PaymentViewDTO paymentData = paymentService.getPaymentViewData(sessionReservationId);
    // 할인 금액은 0으로 고정 (추후 쿠폰 및 할인 적용 시 수정 가능)
    int discount = 0;
    double payPrice = sessionTotalPrice - discount;
    // 8자리 예매번호 생성
    String bookingNumber = paymentService.generateBookingNumber();
    // 모델에 paymentData 객체 전체 추가
    model.addAttribute("paymentData", paymentData);
    model.addAttribute("mTotalPrice", sessionTotalPrice);  // 총 금액
    model.addAttribute("discount", discount);  // 할인 금액
    model.addAttribute("payPrice", payPrice);  // 최종 결제 금액
    model.addAttribute("bookingNumber", bookingNumber); // 8자리 예매번호
    return "payment/success";
}- 세션에서 reservationId와totalPrice를 가져와paymentService를 통해 결제 데이터 조회
- 결제 정보, 할인금액(0원), 최종 결제 금액을 계산하여 model에 담아payment/success페이지에 전달
2. PaymentService
- PaymentViewDto객체 생성해서 필요 데이터 조회 및 전달
public PaymentResponse.PaymentViewDTO getPaymentViewData(Long reservationId) {
    Reservation reservation = reservationRepository.findById(reservationId)
            .orElseThrow(() -> new ExceptionApi404("예약 정보를 찾을 수 없습니다."));
    Showtime showtime = reservation.getTickets().getFirst().getShowtime();
    int runtimeMinutes = showtime.getMovie().getRuntime();  // 영화 런타임 (분 단위)
    Timestamp startedAt = Timestamp.valueOf(showtime.getStartedAt().toLocalDateTime());  // 상영 시작 시간
    String startTime = convertTimeStampToString(startedAt, "yyyy.MM.dd HH:mm");  // 시작 시간 포맷팅
    String endTime = calculateEndTime(startedAt, runtimeMinutes);  // 종료 시간 계산
    return new PaymentResponse.PaymentViewDTO(
        reservationId,
        reservation.getUser().getUsername(),
        reservation.getUser().getEmail(),
        reservation.getUser().getPhone(),
        showtime.getMovie().getPosterUrls().get(0).getUrl(),
        showtime.getMovie().getMovieNm(),
        startTime,  // 시작 시간
        endTime,    // 종료 시간
        showtime.getScreen().getCinema().getName(),
        showtime.getScreen().getName(),
        reservation.getTickets().size(),
        reservation.getTickets().stream()
            .map(ticket -> ticket.getSeat().getSeatNumber())
            .collect(Collectors.toList()),
        reservation.getTickets().size() * showtime.getPrice(),
        reservation.getTickets().size() * showtime.getPrice()
    );
}
- getPaymentViewData메소드는- reservationId를 기반으로 데이터 조회. 영화 정보, 좌석 정보, 결제 금액등을 포함한 DTO 반환
3. payment/success.mustache
- 받아온 데이터 출력
<div class="info_row">
    <span class="info_label">예매번호</span>
    <span>{{bookingNumber}}</span>
</div>
<div class="info_row">
    <span class="info_label">상영 일시</span>
    <span>{{paymentData.showtime}} ~ {{paymentData.endtime}}</span>  <!-- 시작 시간 ~ 종료 시간 -->
</div>
<div class="info_row">
    <span class="info_label">상영관</span>
    <span>{{paymentData.cinemaName}} {{paymentData.screenName}}</span>
</div>
<div class="info_row">
    <span class="info_label">관람 인원</span>
    <span>{{paymentData.people}}</span>
</div>
<div class="info_row">
    <span class="info_label">좌석</span>
    <span>{{#paymentData.seatNumbers}}{{.}} {{/paymentData.seatNumbers}}</span>
</div>
<div class="bottom_section">
    <span>주문 금액</span> <strong>{{paymentData.price}}원</strong>
</div>
<div class="bottom_section middle">
    <span>할인 금액</span> <strong>{{discount}}원</strong>
</div>
<div class="bottom_section">
    <span>총 결제 금액</span> <strong>{{paymentData.totalPrice}}원</strong>
</div>
예약 - 좌석 선택 - 결제 로직 시연영상
Share article