From d62bd444f1f6f433d261ff5164c9a210e17b973d Mon Sep 17 00:00:00 2001 From: pricelees Date: Sun, 7 Sep 2025 21:27:44 +0900 Subject: [PATCH] =?UTF-8?q?refactor:=20payment=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EB=82=B4=20=EC=9D=BC=EB=B6=80=20DTO=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20=EB=B0=8F=20Tosspayment=20->=20Tosspay=20=EC=A0=91?= =?UTF-8?q?=EB=91=90=EC=82=AC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../infrastructure/client/PaymentConfig.kt | 2 +- ...aymentCancelDTO.kt => TosspayCancelDTO.kt} | 17 ++---- ...osspaymentClientV2.kt => TosspayClient.kt} | 58 +++++++++++++------ ...mentConfirmDTO.kt => TosspayConfirmDTO.kt} | 28 ++++----- .../client/TosspayErrorResponse.kt | 6 ++ 5 files changed, 62 insertions(+), 49 deletions(-) rename src/main/kotlin/roomescape/payment/infrastructure/client/{v2/TosspaymentCancelDTO.kt => TosspayCancelDTO.kt} (82%) rename src/main/kotlin/roomescape/payment/infrastructure/client/{v2/TosspaymentClientV2.kt => TosspayClient.kt} (71%) rename src/main/kotlin/roomescape/payment/infrastructure/client/{v2/TosspaymentConfirmDTO.kt => TosspayConfirmDTO.kt} (79%) create mode 100644 src/main/kotlin/roomescape/payment/infrastructure/client/TosspayErrorResponse.kt diff --git a/src/main/kotlin/roomescape/payment/infrastructure/client/PaymentConfig.kt b/src/main/kotlin/roomescape/payment/infrastructure/client/PaymentConfig.kt index b19c1062..ea8e2b18 100644 --- a/src/main/kotlin/roomescape/payment/infrastructure/client/PaymentConfig.kt +++ b/src/main/kotlin/roomescape/payment/infrastructure/client/PaymentConfig.kt @@ -15,7 +15,7 @@ import java.util.* class PaymentConfig { @Bean - fun tossPaymentClientBuilder( + fun tosspayClientBuilder( paymentProperties: PaymentProperties, ): RestClient.Builder { val settings: ClientHttpRequestFactorySettings = ClientHttpRequestFactorySettings.defaults().also { diff --git a/src/main/kotlin/roomescape/payment/infrastructure/client/v2/TosspaymentCancelDTO.kt b/src/main/kotlin/roomescape/payment/infrastructure/client/TosspayCancelDTO.kt similarity index 82% rename from src/main/kotlin/roomescape/payment/infrastructure/client/v2/TosspaymentCancelDTO.kt rename to src/main/kotlin/roomescape/payment/infrastructure/client/TosspayCancelDTO.kt index 57d440e2..551e7ae5 100644 --- a/src/main/kotlin/roomescape/payment/infrastructure/client/v2/TosspaymentCancelDTO.kt +++ b/src/main/kotlin/roomescape/payment/infrastructure/client/TosspayCancelDTO.kt @@ -1,22 +1,15 @@ -package roomescape.payment.infrastructure.client.v2 +package roomescape.payment.infrastructure.client import com.fasterxml.jackson.core.JsonParser import com.fasterxml.jackson.databind.DeserializationContext -import com.fasterxml.jackson.databind.JsonDeserializer import com.fasterxml.jackson.databind.JsonNode import com.fasterxml.jackson.databind.annotation.JsonDeserialize import roomescape.payment.infrastructure.common.PaymentStatus -import roomescape.payment.infrastructure.persistence.v2.CanceledPaymentEntityV2 +import roomescape.payment.infrastructure.persistence.CanceledPaymentEntity import java.time.LocalDateTime import java.time.OffsetDateTime -data class PaymentCancelRequestV2( - val paymentKey: String, - val amount: Int, - val cancelReason: String -) - -data class PaymentCancelResponseV2( +data class PaymentClientCancelResponse( val status: PaymentStatus, @JsonDeserialize(using = CancelDetailDeserializer::class) val cancels: CancelDetail, @@ -36,7 +29,7 @@ fun CancelDetail.toEntity( paymentId: Long, canceledBy: Long, cancelRequestedAt: LocalDateTime -) = CanceledPaymentEntityV2( +) = CanceledPaymentEntity( id = id, canceledAt = this.canceledAt, requestedAt = cancelRequestedAt, @@ -49,7 +42,7 @@ fun CancelDetail.toEntity( easypayDiscountAmount = this.easyPayDiscountAmount ) -class CancelDetailDeserializer : JsonDeserializer() { +class CancelDetailDeserializer : com.fasterxml.jackson.databind.JsonDeserializer() { override fun deserialize( p: JsonParser, ctxt: DeserializationContext diff --git a/src/main/kotlin/roomescape/payment/infrastructure/client/v2/TosspaymentClientV2.kt b/src/main/kotlin/roomescape/payment/infrastructure/client/TosspayClient.kt similarity index 71% rename from src/main/kotlin/roomescape/payment/infrastructure/client/v2/TosspaymentClientV2.kt rename to src/main/kotlin/roomescape/payment/infrastructure/client/TosspayClient.kt index 35816231..f1c4298b 100644 --- a/src/main/kotlin/roomescape/payment/infrastructure/client/v2/TosspaymentClientV2.kt +++ b/src/main/kotlin/roomescape/payment/infrastructure/client/TosspayClient.kt @@ -1,4 +1,4 @@ -package roomescape.payment.infrastructure.client.v2 +package roomescape.payment.infrastructure.client import com.fasterxml.jackson.databind.ObjectMapper import io.github.oshai.kotlinlogging.KLogger @@ -12,31 +12,40 @@ import org.springframework.web.client.ResponseErrorHandler import org.springframework.web.client.RestClient import roomescape.payment.exception.PaymentErrorCode import roomescape.payment.exception.PaymentException -import roomescape.payment.infrastructure.client.TossPaymentErrorResponse import java.net.URI private val log: KLogger = KotlinLogging.logger {} @Component -class TosspaymentClientV2( +class TosspaymentClient( objectMapper: ObjectMapper, tossPaymentClientBuilder: RestClient.Builder ) { private val confirmClient = ConfirmClient(objectMapper, tossPaymentClientBuilder.build()) private val cancelClient = CancelClient(objectMapper, tossPaymentClientBuilder.build()) - fun confirm(request: PaymentConfirmRequest): PaymentConfirmResponse { - log.info { "[TossPaymentClientV2.confirm] 결제 승인 요청: request=$request" } + fun confirm( + paymentKey: String, + orderId: String, + amount: Int, + ): PaymentClientConfirmResponse { + log.info { "[TossPaymentClient.confirm] 결제 승인 요청: paymentKey=$paymentKey, orderId=$orderId, amount=$amount" } + + return confirmClient.request(paymentKey, orderId, amount) + .also { + log.info { "[TossPaymentClient.confirm] 결제 승인 완료: response=$it" } + } - return confirmClient.request(request).also { - log.info { "[TossPaymentClientV2.confirm] 결제 승인 완료: response=$it" } - } } - fun cancel(request: PaymentCancelRequestV2): PaymentCancelResponseV2 { - log.info { "[TossPaymentClient.cancel] 결제 취소 요청: request=$request" } + fun cancel( + paymentKey: String, + amount: Int, + cancelReason: String + ): PaymentClientCancelResponse { + log.info { "[TossPaymentClient.cancel] 결제 취소 요청: paymentKey=$paymentKey, amount=$amount, cancelReason=$cancelReason" } - return cancelClient.request(request).also { + return cancelClient.request(paymentKey, amount, cancelReason).also { log.info { "[TossPaymentClient.cancel] 결제 취소 완료: response=$it" } } } @@ -52,13 +61,20 @@ private class ConfirmClient( private val errorHandler: TosspayErrorHandler = TosspayErrorHandler(objectMapper) - fun request(request: PaymentConfirmRequest): PaymentConfirmResponse = client.post() + fun request(paymentKey: String, orderId: String, amount: Int): PaymentClientConfirmResponse = client.post() .uri(CONFIRM_URI) .contentType(MediaType.APPLICATION_JSON) - .body(request) + .body( + mapOf( + "paymentKey" to paymentKey, + "orderId" to orderId, + "amount" to amount + ) + ) .retrieve() .onStatus(errorHandler) - .body(PaymentConfirmResponse::class.java) ?: run { + .body(PaymentClientConfirmResponse::class.java) + ?: run { log.error { "[TossPaymentConfirmClient.request] 응답 바디 변환 실패" } throw PaymentException(PaymentErrorCode.PAYMENT_UNEXPECTED_ERROR) } @@ -74,17 +90,21 @@ private class CancelClient( private val errorHandler: TosspayErrorHandler = TosspayErrorHandler(objectMapper) - fun request(request: PaymentCancelRequestV2): PaymentCancelResponseV2 = client.post() - .uri(CANCEL_URI, request.paymentKey) + fun request( + paymentKey: String, + amount: Int, + cancelReason: String + ): PaymentClientCancelResponse = client.post() + .uri(CANCEL_URI, paymentKey) .body( mapOf( - "cancelReason" to request.cancelReason, - "cancelAmount" to request.amount, + "cancelReason" to cancelReason, + "cancelAmount" to amount, ) ) .retrieve() .onStatus(errorHandler) - .body(PaymentCancelResponseV2::class.java) + .body(PaymentClientCancelResponse::class.java) ?: run { log.error { "[TossPaymentClient] 응답 바디 변환 실패" } throw PaymentException(PaymentErrorCode.PAYMENT_UNEXPECTED_ERROR) diff --git a/src/main/kotlin/roomescape/payment/infrastructure/client/v2/TosspaymentConfirmDTO.kt b/src/main/kotlin/roomescape/payment/infrastructure/client/TosspayConfirmDTO.kt similarity index 79% rename from src/main/kotlin/roomescape/payment/infrastructure/client/v2/TosspaymentConfirmDTO.kt rename to src/main/kotlin/roomescape/payment/infrastructure/client/TosspayConfirmDTO.kt index 0c5a3ce8..ebe0ef20 100644 --- a/src/main/kotlin/roomescape/payment/infrastructure/client/v2/TosspaymentConfirmDTO.kt +++ b/src/main/kotlin/roomescape/payment/infrastructure/client/TosspayConfirmDTO.kt @@ -1,21 +1,15 @@ -package roomescape.payment.infrastructure.client.v2 +package roomescape.payment.infrastructure.client import roomescape.payment.exception.PaymentErrorCode import roomescape.payment.exception.PaymentException import roomescape.payment.infrastructure.common.* -import roomescape.payment.infrastructure.persistence.v2.PaymentBankTransferDetailEntity -import roomescape.payment.infrastructure.persistence.v2.PaymentCardDetailEntity -import roomescape.payment.infrastructure.persistence.v2.PaymentEasypayPrepaidDetailEntity -import roomescape.payment.infrastructure.persistence.v2.PaymentEntityV2 +import roomescape.payment.infrastructure.persistence.PaymentBankTransferDetailEntity +import roomescape.payment.infrastructure.persistence.PaymentCardDetailEntity +import roomescape.payment.infrastructure.persistence.PaymentEasypayPrepaidDetailEntity +import roomescape.payment.infrastructure.persistence.PaymentEntity import java.time.OffsetDateTime -data class PaymentConfirmRequest( - val paymentKey: String, - val orderId: String, - val amount: Int, -) - -data class PaymentConfirmResponse( +data class PaymentClientConfirmResponse( val paymentKey: String, val status: PaymentStatus, val totalAmount: Int, @@ -29,12 +23,12 @@ data class PaymentConfirmResponse( val approvedAt: OffsetDateTime, ) -fun PaymentConfirmResponse.toEntity( +fun PaymentClientConfirmResponse.toEntity( id: Long, reservationId: Long, orderId: String, paymentType: PaymentType -) = PaymentEntityV2( +) = PaymentEntity( id = id, reservationId = reservationId, paymentKey = this.paymentKey, @@ -58,7 +52,7 @@ data class CardDetail( val installmentPlanMonths: Int ) -fun PaymentConfirmResponse.toCardDetailEntity(id: Long, paymentId: Long): PaymentCardDetailEntity { +fun PaymentClientConfirmResponse.toCardDetailEntity(id: Long, paymentId: Long): PaymentCardDetailEntity { val cardDetail = this.card ?: throw PaymentException(PaymentErrorCode.PAYMENT_UNEXPECTED_ERROR) return PaymentCardDetailEntity( @@ -85,7 +79,7 @@ data class EasyPayDetail( val discountAmount: Int, ) -fun PaymentConfirmResponse.toEasypayPrepaidDetailEntity( +fun PaymentClientConfirmResponse.toEasypayPrepaidDetailEntity( id: Long, paymentId: Long ): PaymentEasypayPrepaidDetailEntity { @@ -107,7 +101,7 @@ data class TransferDetail( val settlementStatus: String, ) -fun PaymentConfirmResponse.toTransferDetailEntity( +fun PaymentClientConfirmResponse.toTransferDetailEntity( id: Long, paymentId: Long ): PaymentBankTransferDetailEntity { diff --git a/src/main/kotlin/roomescape/payment/infrastructure/client/TosspayErrorResponse.kt b/src/main/kotlin/roomescape/payment/infrastructure/client/TosspayErrorResponse.kt new file mode 100644 index 00000000..cbfc2d4b --- /dev/null +++ b/src/main/kotlin/roomescape/payment/infrastructure/client/TosspayErrorResponse.kt @@ -0,0 +1,6 @@ +package roomescape.payment.infrastructure.client + +data class TossPaymentErrorResponse( + val code: String, + val message: String +) \ No newline at end of file