refactor: TosspayClient에서 사용할 별도의 ExternalPaymentException 정의

This commit is contained in:
이상진 2025-10-07 16:09:51 +09:00
parent b22d587757
commit 1652398fcc
3 changed files with 25 additions and 12 deletions

View File

@ -6,3 +6,9 @@ class PaymentException(
override val errorCode: PaymentErrorCode,
override val message: String = errorCode.message
) : RoomescapeException(errorCode, message)
class ExternalPaymentException(
val httpStatusCode: Int,
val errorCode: String,
override val message: String
) : RuntimeException(message)

View File

@ -1,6 +1,7 @@
package com.sangdol.roomescape.payment.infrastructure.client
import com.fasterxml.jackson.databind.ObjectMapper
import com.sangdol.roomescape.payment.exception.ExternalPaymentException
import com.sangdol.roomescape.payment.exception.PaymentErrorCode
import com.sangdol.roomescape.payment.exception.PaymentException
import io.github.oshai.kotlinlogging.KLogger
@ -138,9 +139,14 @@ private class TosspayErrorHandler(
response: ClientHttpResponse
): Nothing {
val requestType: String = paymentRequestType(url)
log.warn { "[TosspayClient] $requestType 요청 실패: response: ${parseResponse(response)}" }
val errorResponse: TosspayErrorResponse = parseResponse(response)
log.warn { "[TosspayClient] $requestType 요청 실패: response: $errorResponse" }
throw PaymentException(paymentErrorCode(response.statusCode))
throw ExternalPaymentException(
httpStatusCode = response.statusCode.value(),
errorCode = errorResponse.code,
message = errorResponse.message
)
}
private fun paymentRequestType(url: URI): String {

View File

@ -1,6 +1,7 @@
package com.sangdol.roomescape.payment
import com.ninjasquad.springmockk.MockkBean
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
@ -67,7 +68,7 @@ class TosspayClientTest(
}
context("실패 응답") {
fun runTest(httpStatus: HttpStatus, expectedError: PaymentErrorCode) {
fun runTest(httpStatus: HttpStatus) {
commonAction().andRespond {
withStatus(httpStatus)
.contentType(MediaType.APPLICATION_JSON)
@ -75,7 +76,7 @@ class TosspayClientTest(
.createResponse(it)
}
val exception = shouldThrow<PaymentException> {
val exception = shouldThrow<ExternalPaymentException> {
client.confirm(
SampleTosspayConstant.PAYMENT_KEY,
SampleTosspayConstant.ORDER_ID,
@ -83,15 +84,15 @@ class TosspayClientTest(
)
}
exception.errorCode shouldBe expectedError
exception.errorCode shouldBe "ERROR_CODE"
}
test("결제 서버에서 4XX 응답 시") {
runTest(HttpStatus.BAD_REQUEST, PaymentErrorCode.PAYMENT_CLIENT_ERROR)
runTest(HttpStatus.BAD_REQUEST)
}
test("결제 서버에서 5XX 응답 시") {
runTest(HttpStatus.INTERNAL_SERVER_ERROR, PaymentErrorCode.PAYMENT_PROVIDER_ERROR)
runTest(HttpStatus.INTERNAL_SERVER_ERROR)
}
}
}
@ -131,7 +132,7 @@ class TosspayClientTest(
}
context("실패 응답") {
fun runTest(httpStatus: HttpStatus, expectedError: PaymentErrorCode) {
fun runTest(httpStatus: HttpStatus) {
commonAction().andRespond {
withStatus(httpStatus)
.contentType(MediaType.APPLICATION_JSON)
@ -139,22 +140,22 @@ class TosspayClientTest(
.createResponse(it)
}
val exception = shouldThrow<PaymentException> {
val exception = shouldThrow<ExternalPaymentException> {
client.cancel(
SampleTosspayConstant.PAYMENT_KEY,
SampleTosspayConstant.AMOUNT,
SampleTosspayConstant.CANCEL_REASON
)
}
exception.errorCode shouldBe expectedError
exception.errorCode shouldBe "ERROR_CODE"
}
test("결제 서버에서 4XX 응답 시") {
runTest(HttpStatus.BAD_REQUEST, PaymentErrorCode.PAYMENT_CLIENT_ERROR)
runTest(HttpStatus.BAD_REQUEST)
}
test("결제 서버에서 5XX 응답 시") {
runTest(HttpStatus.INTERNAL_SERVER_ERROR, PaymentErrorCode.PAYMENT_PROVIDER_ERROR)
runTest(HttpStatus.INTERNAL_SERVER_ERROR)
}
}
}