generated from pricelees/issue-pr-template
feat: Payment 도메인의 커스텀 예외 추가 및 서비스 코드 수정
This commit is contained in:
parent
52bc1940f1
commit
498340f173
@ -1,10 +1,9 @@
|
|||||||
package roomescape.payment.business
|
package roomescape.payment.business
|
||||||
|
|
||||||
import org.springframework.http.HttpStatus
|
|
||||||
import org.springframework.stereotype.Service
|
import org.springframework.stereotype.Service
|
||||||
import org.springframework.transaction.annotation.Transactional
|
import org.springframework.transaction.annotation.Transactional
|
||||||
import roomescape.common.exception.ErrorType
|
import roomescape.payment.exception.PaymentErrorCode
|
||||||
import roomescape.common.exception.RoomescapeException
|
import roomescape.payment.exception.PaymentException
|
||||||
import roomescape.payment.infrastructure.client.PaymentApproveResponse
|
import roomescape.payment.infrastructure.client.PaymentApproveResponse
|
||||||
import roomescape.payment.infrastructure.persistence.CanceledPaymentEntity
|
import roomescape.payment.infrastructure.persistence.CanceledPaymentEntity
|
||||||
import roomescape.payment.infrastructure.persistence.CanceledPaymentRepository
|
import roomescape.payment.infrastructure.persistence.CanceledPaymentRepository
|
||||||
@ -24,44 +23,45 @@ class PaymentService(
|
|||||||
) {
|
) {
|
||||||
@Transactional
|
@Transactional
|
||||||
fun createPayment(
|
fun createPayment(
|
||||||
paymentResponse: PaymentApproveResponse,
|
approveResponse: PaymentApproveResponse,
|
||||||
reservation: ReservationEntity
|
reservation: ReservationEntity
|
||||||
): PaymentCreateResponse = PaymentEntity(
|
): PaymentCreateResponse {
|
||||||
orderId = paymentResponse.orderId,
|
val payment = PaymentEntity(
|
||||||
paymentKey = paymentResponse.paymentKey,
|
orderId = approveResponse.orderId,
|
||||||
totalAmount = paymentResponse.totalAmount,
|
paymentKey = approveResponse.paymentKey,
|
||||||
reservation = reservation,
|
totalAmount = approveResponse.totalAmount,
|
||||||
approvedAt = paymentResponse.approvedAt
|
reservation = reservation,
|
||||||
).also {
|
approvedAt = approveResponse.approvedAt
|
||||||
paymentRepository.save(it)
|
)
|
||||||
}.toCreateResponse()
|
|
||||||
|
return paymentRepository.save(payment).toCreateResponse()
|
||||||
|
}
|
||||||
|
|
||||||
@Transactional(readOnly = true)
|
@Transactional(readOnly = true)
|
||||||
fun isReservationPaid(
|
fun isReservationPaid(reservationId: Long): Boolean = paymentRepository.existsByReservationId(reservationId)
|
||||||
reservationId: Long
|
|
||||||
): Boolean = paymentRepository.existsByReservationId(reservationId)
|
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
fun createCanceledPayment(
|
fun createCanceledPayment(
|
||||||
cancelInfo: PaymentCancelResponse,
|
cancelInfo: PaymentCancelResponse,
|
||||||
approvedAt: OffsetDateTime,
|
approvedAt: OffsetDateTime,
|
||||||
paymentKey: String
|
paymentKey: String
|
||||||
): CanceledPaymentEntity = CanceledPaymentEntity(
|
): CanceledPaymentEntity {
|
||||||
paymentKey = paymentKey,
|
val canceledPayment = CanceledPaymentEntity(
|
||||||
cancelReason = cancelInfo.cancelReason,
|
paymentKey = paymentKey,
|
||||||
cancelAmount = cancelInfo.cancelAmount,
|
cancelReason = cancelInfo.cancelReason,
|
||||||
approvedAt = approvedAt,
|
cancelAmount = cancelInfo.cancelAmount,
|
||||||
canceledAt = cancelInfo.canceledAt
|
approvedAt = approvedAt,
|
||||||
).also { canceledPaymentRepository.save(it) }
|
canceledAt = cancelInfo.canceledAt
|
||||||
|
)
|
||||||
|
|
||||||
|
return canceledPaymentRepository.save(canceledPayment)
|
||||||
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
fun createCanceledPaymentByReservationId(reservationId: Long): PaymentCancelRequest {
|
fun createCanceledPaymentByReservationId(reservationId: Long): PaymentCancelRequest {
|
||||||
val paymentKey: String = paymentRepository.findPaymentKeyByReservationId(reservationId)
|
val paymentKey: String = paymentRepository.findPaymentKeyByReservationId(reservationId)
|
||||||
?: throw RoomescapeException(
|
?: throw PaymentException(PaymentErrorCode.PAYMENT_NOT_FOUND)
|
||||||
ErrorType.PAYMENT_NOT_FOUND,
|
|
||||||
"[reservationId: $reservationId]",
|
|
||||||
HttpStatus.NOT_FOUND
|
|
||||||
)
|
|
||||||
// 취소 시간은 현재 시간으로 일단 생성한 뒤, 결제 취소 완료 후 해당 시간으로 변경합니다.
|
// 취소 시간은 현재 시간으로 일단 생성한 뒤, 결제 취소 완료 후 해당 시간으로 변경합니다.
|
||||||
val canceled: CanceledPaymentEntity = cancelPayment(paymentKey)
|
val canceled: CanceledPaymentEntity = cancelPayment(paymentKey)
|
||||||
|
|
||||||
@ -73,23 +73,19 @@ class PaymentService(
|
|||||||
cancelReason: String = "고객 요청",
|
cancelReason: String = "고객 요청",
|
||||||
canceledAt: OffsetDateTime = OffsetDateTime.now()
|
canceledAt: OffsetDateTime = OffsetDateTime.now()
|
||||||
): CanceledPaymentEntity {
|
): CanceledPaymentEntity {
|
||||||
val paymentEntity: PaymentEntity = paymentRepository.findByPaymentKey(paymentKey)
|
val payment: PaymentEntity = paymentRepository.findByPaymentKey(paymentKey)
|
||||||
?.also { paymentRepository.delete(it) }
|
?.also { paymentRepository.delete(it) }
|
||||||
?: throw RoomescapeException(
|
?: throw PaymentException(PaymentErrorCode.PAYMENT_NOT_FOUND)
|
||||||
ErrorType.PAYMENT_NOT_FOUND,
|
|
||||||
"[paymentKey: $paymentKey]",
|
|
||||||
HttpStatus.NOT_FOUND
|
|
||||||
)
|
|
||||||
|
|
||||||
return CanceledPaymentEntity(
|
val canceledPayment = CanceledPaymentEntity(
|
||||||
paymentKey = paymentKey,
|
paymentKey = paymentKey,
|
||||||
cancelReason = cancelReason,
|
cancelReason = cancelReason,
|
||||||
cancelAmount = paymentEntity.totalAmount,
|
cancelAmount = payment.totalAmount,
|
||||||
approvedAt = paymentEntity.approvedAt,
|
approvedAt = payment.approvedAt,
|
||||||
canceledAt = canceledAt
|
canceledAt = canceledAt
|
||||||
).also {
|
)
|
||||||
canceledPaymentRepository.save(it)
|
|
||||||
}
|
return canceledPaymentRepository.save(canceledPayment)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
@ -97,12 +93,8 @@ class PaymentService(
|
|||||||
paymentKey: String,
|
paymentKey: String,
|
||||||
canceledAt: OffsetDateTime
|
canceledAt: OffsetDateTime
|
||||||
) {
|
) {
|
||||||
canceledPaymentRepository.findByPaymentKey(paymentKey)?.let {
|
canceledPaymentRepository.findByPaymentKey(paymentKey)
|
||||||
it.canceledAt = canceledAt
|
?.apply { this.canceledAt = canceledAt }
|
||||||
} ?: throw RoomescapeException(
|
?: throw PaymentException(PaymentErrorCode.PAYMENT_NOT_FOUND)
|
||||||
ErrorType.PAYMENT_NOT_FOUND,
|
|
||||||
"[paymentKey: $paymentKey]",
|
|
||||||
HttpStatus.NOT_FOUND
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,16 @@
|
|||||||
|
package roomescape.payment.exception
|
||||||
|
|
||||||
|
import org.springframework.http.HttpStatus
|
||||||
|
import roomescape.common.exception.ErrorCode
|
||||||
|
|
||||||
|
enum class PaymentErrorCode(
|
||||||
|
override val httpStatus: HttpStatus,
|
||||||
|
override val errorCode: String,
|
||||||
|
override val message: String
|
||||||
|
) : ErrorCode {
|
||||||
|
PAYMENT_NOT_FOUND(HttpStatus.NOT_FOUND, "P001", "결제 정보를 찾을 수 없어요."),
|
||||||
|
CANCELED_PAYMENT_NOT_FOUND(HttpStatus.NOT_FOUND, "P002", "취소된 결제 정보를 찾을 수 없어요."),
|
||||||
|
PAYMENT_CLIENT_ERROR(HttpStatus.BAD_REQUEST, "P003", "결제에 실패했어요. 결제 수단을 확인한 후 다시 시도해주세요."),
|
||||||
|
|
||||||
|
PAYMENT_PROVIDER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "P999", "시스템에 일시적인 오류가 발생했어요. 잠시 후 다시 시도해주세요.")
|
||||||
|
}
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
package roomescape.payment.exception
|
||||||
|
|
||||||
|
import roomescape.common.exception.RoomescapeExceptionV2
|
||||||
|
|
||||||
|
class PaymentException(
|
||||||
|
override val errorCode: PaymentErrorCode,
|
||||||
|
override val message: String = errorCode.message
|
||||||
|
) : RoomescapeExceptionV2(errorCode, message)
|
||||||
@ -11,6 +11,8 @@ import io.mockk.runs
|
|||||||
import org.springframework.http.HttpStatus
|
import org.springframework.http.HttpStatus
|
||||||
import roomescape.common.exception.ErrorType
|
import roomescape.common.exception.ErrorType
|
||||||
import roomescape.common.exception.RoomescapeException
|
import roomescape.common.exception.RoomescapeException
|
||||||
|
import roomescape.payment.exception.PaymentErrorCode
|
||||||
|
import roomescape.payment.exception.PaymentException
|
||||||
import roomescape.payment.infrastructure.persistence.CanceledPaymentRepository
|
import roomescape.payment.infrastructure.persistence.CanceledPaymentRepository
|
||||||
import roomescape.payment.infrastructure.persistence.PaymentRepository
|
import roomescape.payment.infrastructure.persistence.PaymentRepository
|
||||||
import roomescape.payment.web.PaymentCancelRequest
|
import roomescape.payment.web.PaymentCancelRequest
|
||||||
@ -23,19 +25,15 @@ class PaymentServiceTest : FunSpec({
|
|||||||
|
|
||||||
val paymentService = PaymentService(paymentRepository, canceledPaymentRepository)
|
val paymentService = PaymentService(paymentRepository, canceledPaymentRepository)
|
||||||
|
|
||||||
context("cancelPaymentByAdmin") {
|
context("createCanceledPaymentByReservationId") {
|
||||||
val reservationId = 1L
|
val reservationId = 1L
|
||||||
test("reservationId로 paymentKey를 찾을 수 없으면 예외를 던진다.") {
|
test("reservationId로 paymentKey를 찾을 수 없으면 예외를 던진다.") {
|
||||||
every { paymentRepository.findPaymentKeyByReservationId(reservationId) } returns null
|
every { paymentRepository.findPaymentKeyByReservationId(reservationId) } returns null
|
||||||
|
|
||||||
val exception = shouldThrow<RoomescapeException> {
|
val exception = shouldThrow<PaymentException> {
|
||||||
paymentService.createCanceledPaymentByReservationId(reservationId)
|
paymentService.createCanceledPaymentByReservationId(reservationId)
|
||||||
}
|
}
|
||||||
|
exception.errorCode shouldBe PaymentErrorCode.PAYMENT_NOT_FOUND
|
||||||
assertSoftly(exception) {
|
|
||||||
this.errorType shouldBe ErrorType.PAYMENT_NOT_FOUND
|
|
||||||
this.httpStatus shouldBe HttpStatus.NOT_FOUND
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
context("reservationId로 paymentKey를 찾고난 후") {
|
context("reservationId로 paymentKey를 찾고난 후") {
|
||||||
@ -50,14 +48,10 @@ class PaymentServiceTest : FunSpec({
|
|||||||
paymentRepository.findByPaymentKey(paymentKey)
|
paymentRepository.findByPaymentKey(paymentKey)
|
||||||
} returns null
|
} returns null
|
||||||
|
|
||||||
val exception = shouldThrow<RoomescapeException> {
|
val exception = shouldThrow<PaymentException> {
|
||||||
paymentService.createCanceledPaymentByReservationId(reservationId)
|
paymentService.createCanceledPaymentByReservationId(reservationId)
|
||||||
}
|
}
|
||||||
|
exception.errorCode shouldBe PaymentErrorCode.PAYMENT_NOT_FOUND
|
||||||
assertSoftly(exception) {
|
|
||||||
this.errorType shouldBe ErrorType.PAYMENT_NOT_FOUND
|
|
||||||
this.httpStatus shouldBe HttpStatus.NOT_FOUND
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test("해당 paymentKey로 paymentEntity를 찾고, cancelPaymentEntity를 저장한다.") {
|
test("해당 paymentKey로 paymentEntity를 찾고, cancelPaymentEntity를 저장한다.") {
|
||||||
@ -76,6 +70,7 @@ class PaymentServiceTest : FunSpec({
|
|||||||
} returns PaymentFixture.createCanceled(
|
} returns PaymentFixture.createCanceled(
|
||||||
id = 1L,
|
id = 1L,
|
||||||
paymentKey = paymentKey,
|
paymentKey = paymentKey,
|
||||||
|
cancelReason = "Test",
|
||||||
cancelAmount = paymentEntity.totalAmount,
|
cancelAmount = paymentEntity.totalAmount,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -84,7 +79,7 @@ class PaymentServiceTest : FunSpec({
|
|||||||
assertSoftly(result) {
|
assertSoftly(result) {
|
||||||
this.paymentKey shouldBe paymentKey
|
this.paymentKey shouldBe paymentKey
|
||||||
this.amount shouldBe paymentEntity.totalAmount
|
this.amount shouldBe paymentEntity.totalAmount
|
||||||
this.cancelReason shouldBe "고객 요청"
|
this.cancelReason shouldBe "Test"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -99,14 +94,10 @@ class PaymentServiceTest : FunSpec({
|
|||||||
canceledPaymentRepository.findByPaymentKey(paymentKey)
|
canceledPaymentRepository.findByPaymentKey(paymentKey)
|
||||||
} returns null
|
} returns null
|
||||||
|
|
||||||
val exception = shouldThrow<RoomescapeException> {
|
val exception = shouldThrow<PaymentException> {
|
||||||
paymentService.updateCanceledTime(paymentKey, canceledAt)
|
paymentService.updateCanceledTime(paymentKey, canceledAt)
|
||||||
}
|
}
|
||||||
|
exception.errorCode shouldBe PaymentErrorCode.PAYMENT_NOT_FOUND
|
||||||
assertSoftly(exception) {
|
|
||||||
this.errorType shouldBe ErrorType.PAYMENT_NOT_FOUND
|
|
||||||
this.httpStatus shouldBe HttpStatus.NOT_FOUND
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test("paymentKey로 canceledPaymentEntity를 찾고, canceledAt을 업데이트한다.") {
|
test("paymentKey로 canceledPaymentEntity를 찾고, canceledAt을 업데이트한다.") {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user