From 1652398fcc3304d294b3d542796734c537da022a Mon Sep 17 00:00:00 2001 From: pricelees Date: Tue, 7 Oct 2025 16:09:51 +0900 Subject: [PATCH] =?UTF-8?q?refactor:=20TosspayClient=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=ED=95=A0=20=EB=B3=84=EB=8F=84=EC=9D=98=20Ext?= =?UTF-8?q?ernalPaymentException=20=EC=A0=95=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../payment/exception/PaymentException.kt | 6 ++++++ .../infrastructure/client/TosspayClient.kt | 10 +++++++-- .../roomescape/payment/TosspayClientTest.kt | 21 ++++++++++--------- 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/service/src/main/kotlin/com/sangdol/roomescape/payment/exception/PaymentException.kt b/service/src/main/kotlin/com/sangdol/roomescape/payment/exception/PaymentException.kt index 3bddd08c..87f7965d 100644 --- a/service/src/main/kotlin/com/sangdol/roomescape/payment/exception/PaymentException.kt +++ b/service/src/main/kotlin/com/sangdol/roomescape/payment/exception/PaymentException.kt @@ -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) diff --git a/service/src/main/kotlin/com/sangdol/roomescape/payment/infrastructure/client/TosspayClient.kt b/service/src/main/kotlin/com/sangdol/roomescape/payment/infrastructure/client/TosspayClient.kt index 49194b30..8840bd20 100644 --- a/service/src/main/kotlin/com/sangdol/roomescape/payment/infrastructure/client/TosspayClient.kt +++ b/service/src/main/kotlin/com/sangdol/roomescape/payment/infrastructure/client/TosspayClient.kt @@ -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 { diff --git a/service/src/test/kotlin/com/sangdol/roomescape/payment/TosspayClientTest.kt b/service/src/test/kotlin/com/sangdol/roomescape/payment/TosspayClientTest.kt index 6ad61b04..c9c54396 100644 --- a/service/src/test/kotlin/com/sangdol/roomescape/payment/TosspayClientTest.kt +++ b/service/src/test/kotlin/com/sangdol/roomescape/payment/TosspayClientTest.kt @@ -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 { + val exception = shouldThrow { 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 { + val exception = shouldThrow { 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) } } }