generated from pricelees/issue-pr-template
[#64] 결제 & 예약 확정 API에서의 트랜잭션 범위 수정 #65
@ -36,14 +36,18 @@ class OrderService(
|
|||||||
) {
|
) {
|
||||||
|
|
||||||
fun confirm(reservationId: Long, paymentConfirmRequest: PaymentConfirmRequest) {
|
fun confirm(reservationId: Long, paymentConfirmRequest: PaymentConfirmRequest) {
|
||||||
val trial = paymentAttemptRepository.countByReservationId(reservationId)
|
var trial: Long = 0
|
||||||
val paymentKey = paymentConfirmRequest.paymentKey
|
val paymentKey = paymentConfirmRequest.paymentKey
|
||||||
|
|
||||||
log.info { "[confirm] 결제 및 예약 확정 시작: reservationId=${reservationId}, paymentKey=${paymentKey}" }
|
log.info { "[confirm] 결제 및 예약 확정 시작: reservationId=${reservationId}, paymentKey=${paymentKey}" }
|
||||||
|
|
||||||
try {
|
try {
|
||||||
transactionExecutionUtil.withNewTransaction(isReadOnly = false) {
|
trial = transactionExecutionUtil.withNewTransaction(isReadOnly = false) {
|
||||||
validateAndMarkInProgress(reservationId)
|
getTrialAfterValidateCanConfirm(reservationId).also {
|
||||||
|
reservationService.markInProgress(reservationId)
|
||||||
|
}
|
||||||
|
} ?: run {
|
||||||
|
log.warn { "[confirm] 모든 paymentAttempts 조회 과정에서의 예상치 못한 null 응답: reservationId=${reservationId}" }
|
||||||
|
throw OrderException(OrderErrorCode.BOOKING_UNEXPECTED_ERROR)
|
||||||
}
|
}
|
||||||
|
|
||||||
val paymentClientResponse: PaymentGatewayResponse =
|
val paymentClientResponse: PaymentGatewayResponse =
|
||||||
@ -61,20 +65,32 @@ class OrderService(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun validateAndMarkInProgress(reservationId: Long) {
|
private fun getTrialAfterValidateCanConfirm(reservationId: Long): Long {
|
||||||
log.info { "[validateAndMarkInProgress] 예약 확정 가능 여부 검증 시작: reservationId=${reservationId}" }
|
log.info { "[validateAndMarkInProgress] 예약 확정 가능 여부 검증 시작: reservationId=${reservationId}" }
|
||||||
val reservation: ReservationStateResponse = reservationService.findStatusWithLock(reservationId)
|
val reservation: ReservationStateResponse = reservationService.findStatusWithLock(reservationId)
|
||||||
val schedule: ScheduleStateResponse = scheduleService.findStateWithLock(reservation.scheduleId)
|
val schedule: ScheduleStateResponse = scheduleService.findStateWithLock(reservation.scheduleId)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
orderValidator.validateCanConfirm(reservation, schedule)
|
orderValidator.validateCanConfirm(reservation, schedule)
|
||||||
|
|
||||||
|
return getTrialIfSuccessAttemptNotExists(reservationId).also {
|
||||||
log.info { "[validateAndMarkInProgress] 예약 확정 가능 여부 검증 완료: reservationId=${reservationId}" }
|
log.info { "[validateAndMarkInProgress] 예약 확정 가능 여부 검증 완료: reservationId=${reservationId}" }
|
||||||
|
}
|
||||||
} catch (e: OrderException) {
|
} catch (e: OrderException) {
|
||||||
val errorCode = OrderErrorCode.NOT_CONFIRMABLE
|
val errorCode = OrderErrorCode.NOT_CONFIRMABLE
|
||||||
throw OrderException(errorCode, e.message)
|
throw OrderException(errorCode, e.message)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
reservationService.markInProgress(reservationId)
|
private fun getTrialIfSuccessAttemptNotExists(reservationId: Long): Long {
|
||||||
|
val paymentAttempts: List<PaymentAttemptEntity> = paymentAttemptRepository.findAllByReservationId(reservationId)
|
||||||
|
|
||||||
|
if (paymentAttempts.any { it.result == AttemptResult.SUCCESS }) {
|
||||||
|
log.info { "[validateCanConfirm] 이미 결제 완료된 예약: id=${reservationId}" }
|
||||||
|
throw OrderException(OrderErrorCode.BOOKING_ALREADY_COMPLETED)
|
||||||
|
}
|
||||||
|
|
||||||
|
return paymentAttempts.size.toLong()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun requestConfirmPayment(
|
private fun requestConfirmPayment(
|
||||||
|
|||||||
@ -16,18 +16,11 @@ import java.time.LocalDateTime
|
|||||||
private val log: KLogger = KotlinLogging.logger {}
|
private val log: KLogger = KotlinLogging.logger {}
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
class OrderValidator(
|
class OrderValidator {
|
||||||
private val paymentAttemptRepository: PaymentAttemptRepository
|
|
||||||
) {
|
|
||||||
fun validateCanConfirm(
|
fun validateCanConfirm(
|
||||||
reservation: ReservationStateResponse,
|
reservation: ReservationStateResponse,
|
||||||
schedule: ScheduleStateResponse
|
schedule: ScheduleStateResponse
|
||||||
) {
|
) {
|
||||||
if (paymentAttemptRepository.isSuccessAttemptExists(reservation.id)) {
|
|
||||||
log.info { "[validateCanConfirm] 이미 결제 완료된 예약: id=${reservation.id}" }
|
|
||||||
throw OrderException(OrderErrorCode.BOOKING_ALREADY_COMPLETED)
|
|
||||||
}
|
|
||||||
|
|
||||||
validateReservationStatus(reservation)
|
validateReservationStatus(reservation)
|
||||||
validateScheduleStatus(schedule)
|
validateScheduleStatus(schedule)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,4 +23,6 @@ interface PaymentAttemptRepository: JpaRepository<PaymentAttemptEntity, Long> {
|
|||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
fun isSuccessAttemptExists(reservationId: Long): Boolean
|
fun isSuccessAttemptExists(reservationId: Long): Boolean
|
||||||
|
|
||||||
|
fun findAllByReservationId(reservationId: Long): List<PaymentAttemptEntity>
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user