diff --git a/service/src/main/kotlin/com/sangdol/roomescape/payment/business/PaymentService.kt b/service/src/main/kotlin/com/sangdol/roomescape/payment/business/PaymentService.kt index 654346f9..5bbea39f 100644 --- a/service/src/main/kotlin/com/sangdol/roomescape/payment/business/PaymentService.kt +++ b/service/src/main/kotlin/com/sangdol/roomescape/payment/business/PaymentService.kt @@ -1,6 +1,8 @@ package com.sangdol.roomescape.payment.business import com.sangdol.common.persistence.TransactionExecutionUtil +import com.sangdol.roomescape.payment.business.domain.PaymentClientError +import com.sangdol.roomescape.payment.exception.ExternalPaymentException import com.sangdol.roomescape.payment.exception.PaymentErrorCode import com.sangdol.roomescape.payment.exception.PaymentException import com.sangdol.roomescape.payment.infrastructure.client.PaymentClientCancelResponse @@ -24,27 +26,39 @@ class PaymentService( private val paymentWriter: PaymentWriter, private val transactionExecutionUtil: TransactionExecutionUtil, ) { - fun confirm(reservationId: Long, request: PaymentConfirmRequest): PaymentCreateResponse { - val clientConfirmResponse: PaymentClientConfirmResponse = paymentClient.confirm( - paymentKey = request.paymentKey, - orderId = request.orderId, - amount = request.amount, - ) + fun requestConfirm(request: PaymentConfirmRequest): PaymentClientConfirmResponse { + try { + return paymentClient.confirm(request.paymentKey, request.orderId, request.amount) + } catch (e: ExternalPaymentException) { + val errorCode = if (e.httpStatusCode in 400..<500) { + PaymentErrorCode.PAYMENT_CLIENT_ERROR + } else { + PaymentErrorCode.PAYMENT_PROVIDER_ERROR + } - return transactionExecutionUtil.withNewTransaction(isReadOnly = false) { - val payment: PaymentEntity = paymentWriter.createPayment( - reservationId = reservationId, - paymentClientConfirmResponse = clientConfirmResponse - ) - val detail: PaymentDetailEntity = paymentWriter.createDetail(clientConfirmResponse, payment.id) + val message = if (PaymentClientError.contains(e.errorCode)) { + "${errorCode.message}(${e.message})" + } else { + errorCode.message + } - PaymentCreateResponse(paymentId = payment.id, detailId = detail.id) - } ?: run { - log.warn { "[confirm] 결제 확정 중 예상치 못한 null 반환" } - throw PaymentException(PaymentErrorCode.PAYMENT_UNEXPECTED_ERROR) + throw PaymentException(errorCode, message) } } + fun savePayment( + reservationId: Long, + paymentConfirmResponse: PaymentClientConfirmResponse + ): PaymentCreateResponse { + val payment: PaymentEntity = paymentWriter.createPayment( + reservationId = reservationId, + paymentClientConfirmResponse = paymentConfirmResponse + ) + val detail: PaymentDetailEntity = paymentWriter.createDetail(paymentConfirmResponse, payment.id) + + return PaymentCreateResponse(paymentId = payment.id, detailId = detail.id) + } + fun cancel(userId: Long, request: PaymentCancelRequest) { val payment: PaymentEntity = findByReservationIdOrThrow(request.reservationId) diff --git a/service/src/main/kotlin/com/sangdol/roomescape/payment/docs/PaymentAPI.kt b/service/src/main/kotlin/com/sangdol/roomescape/payment/docs/PaymentAPI.kt index 171df140..c79b1cb7 100644 --- a/service/src/main/kotlin/com/sangdol/roomescape/payment/docs/PaymentAPI.kt +++ b/service/src/main/kotlin/com/sangdol/roomescape/payment/docs/PaymentAPI.kt @@ -4,16 +4,15 @@ import com.sangdol.common.types.web.CommonApiResponse import com.sangdol.roomescape.auth.web.support.User import com.sangdol.roomescape.auth.web.support.UserOnly import com.sangdol.roomescape.common.types.CurrentUserContext +import com.sangdol.roomescape.payment.infrastructure.client.PaymentClientConfirmResponse import com.sangdol.roomescape.payment.web.PaymentCancelRequest import com.sangdol.roomescape.payment.web.PaymentConfirmRequest -import com.sangdol.roomescape.payment.web.PaymentCreateResponse import io.swagger.v3.oas.annotations.Operation import io.swagger.v3.oas.annotations.responses.ApiResponse import io.swagger.v3.oas.annotations.responses.ApiResponses import jakarta.validation.Valid import org.springframework.http.ResponseEntity import org.springframework.web.bind.annotation.RequestBody -import org.springframework.web.bind.annotation.RequestParam interface PaymentAPI { @@ -21,9 +20,8 @@ interface PaymentAPI { @Operation(summary = "결제 승인") @ApiResponses(ApiResponse(responseCode = "200", useReturnTypeSchema = true)) fun confirmPayment( - @RequestParam(required = true) reservationId: Long, @Valid @RequestBody request: PaymentConfirmRequest - ): ResponseEntity> + ): ResponseEntity> @Operation(summary = "결제 취소") @ApiResponses(ApiResponse(responseCode = "200", useReturnTypeSchema = true)) diff --git a/service/src/main/kotlin/com/sangdol/roomescape/payment/web/PaymentController.kt b/service/src/main/kotlin/com/sangdol/roomescape/payment/web/PaymentController.kt index f4830f20..e4c1e6f1 100644 --- a/service/src/main/kotlin/com/sangdol/roomescape/payment/web/PaymentController.kt +++ b/service/src/main/kotlin/com/sangdol/roomescape/payment/web/PaymentController.kt @@ -5,6 +5,7 @@ import com.sangdol.roomescape.auth.web.support.User import com.sangdol.roomescape.common.types.CurrentUserContext import com.sangdol.roomescape.payment.business.PaymentService import com.sangdol.roomescape.payment.docs.PaymentAPI +import com.sangdol.roomescape.payment.infrastructure.client.PaymentClientConfirmResponse import jakarta.validation.Valid import org.springframework.http.ResponseEntity import org.springframework.web.bind.annotation.* @@ -15,12 +16,11 @@ class PaymentController( private val paymentService: PaymentService ) : PaymentAPI { - @PostMapping + @PostMapping("/confirm") override fun confirmPayment( - @RequestParam(required = true) reservationId: Long, @Valid @RequestBody request: PaymentConfirmRequest - ): ResponseEntity> { - val response = paymentService.confirm(reservationId, request) + ): ResponseEntity> { + val response = paymentService.requestConfirm(request) return ResponseEntity.ok(CommonApiResponse(response)) }