티켓 예매 사이트 - 3

토스 결제 인증부터 Spring Boot 예매 확정

  • 가예약 생성

  • 토스 결제창 호출

  • 사용자 결제 인증

  • 백엔드에 결제 승인 요청

  • 토스 승인 성공

  • DB 예약·좌석 확정

  • 프론트에 성공 응답

결제 전에 가예약을 생성한다

POST /api/schedules/{scheduleId}/reservations/simple
  {
    "seatNumbers": ["A1", "A2"]
  }

백엔드는 선택한 좌석을 확인하고 DB에 저장된 공연 가격으로 총금액을 계산한다. 주문 번호와 주문명도 이 단계에서 만든다.

String orderId = "ORDER-" + UUID.randomUUID()
          .toString()
          .replace("-", "")
          .substring(0, 12)
          .toUpperCase();
  String orderName = schedule.getPerformance().getTitle()
          + " " + seats.size() + "매 ("
          + String.join(", ", seatNumbers) + ")";

orderId는 주문을 구분하는 번호이고, orderName은 결제창에 보여줄 주문 이름이다.


가예약 응답으로 토스 결제창을 연다

응답에 담긴 주문 번호, 주문명, 금액을 토스 SDK에 전달한다.

  orderId: data.orderId,
  orderName: data.orderName,
  amount: {
    currency: "KRW",
    value: data.amount,
  },

성공 페이지에서 백엔드에 승인을 요청한다

await api.post("/api/payments/confirm", {
    paymentKey,
    orderId,
    amount: Number(amount),
  });

Spring 컨트롤러는 다음과 같이 요청을 받는다.

  @Valid @RequestBody PaymentConfirmRequest request

@RequestBody는 JSON 본문을 자바 객체로 변환하고, @Valid는 DTO에 선언한 검증 조건을 검사한다.

검증을 통과하면 PaymentService가 토스 서버의 승인 API를 호출한다. 이때 백엔드의 시크릿 키로 인증하고, paymentKey, orderId, amount를 전달한다.

토스 승인이 성공하면 DB를 변경한다

PaymentService는 토스 승인 성공 후 PaymentCompleteService를 호출한다.

  return paymentCompleteService.completeReservationAndSeats(
          request.orderId(),
          request.paymentKey(),
          request.amount()
  );

DB 커밋 이후 프론트에 성공 응답을 보낸다

PaymentConfirmResponse response =
          paymentService.confirmPayment(request);
  return ResponseEntity.ok(response);

이때 HTTP 응답이 프론트로 전달된다. 프론트는 응답을 받은 뒤 예매 완료 화면을 표시한다.

결과물

image.png
image.png

다음에는 동시성, N+1오류를 개선해보려한다.

댓글 0

댓글을 불러오는 중입니다.