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 5bbea39f..f2f0010d 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,15 +1,19 @@ 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.business.domain.UserFacingPaymentErrorCode +import com.sangdol.roomescape.payment.dto.PaymentCancelRequest 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 -import com.sangdol.roomescape.payment.infrastructure.client.PaymentClientConfirmResponse +import com.sangdol.roomescape.payment.dto.PaymentGatewayCancelResponse +import com.sangdol.roomescape.payment.dto.PaymentConfirmRequest +import com.sangdol.roomescape.payment.dto.PaymentCreateResponse +import com.sangdol.roomescape.payment.dto.PaymentGatewayResponse +import com.sangdol.roomescape.payment.dto.PaymentResponse import com.sangdol.roomescape.payment.infrastructure.client.TosspayClient import com.sangdol.roomescape.payment.infrastructure.persistence.* -import com.sangdol.roomescape.payment.web.* +import com.sangdol.roomescape.payment.mapper.toResponse import io.github.oshai.kotlinlogging.KLogger import io.github.oshai.kotlinlogging.KotlinLogging import org.springframework.stereotype.Service @@ -26,7 +30,7 @@ class PaymentService( private val paymentWriter: PaymentWriter, private val transactionExecutionUtil: TransactionExecutionUtil, ) { - fun requestConfirm(request: PaymentConfirmRequest): PaymentClientConfirmResponse { + fun requestConfirm(request: PaymentConfirmRequest): PaymentGatewayResponse { try { return paymentClient.confirm(request.paymentKey, request.orderId, request.amount) } catch (e: ExternalPaymentException) { @@ -36,7 +40,7 @@ class PaymentService( PaymentErrorCode.PAYMENT_PROVIDER_ERROR } - val message = if (PaymentClientError.contains(e.errorCode)) { + val message = if (UserFacingPaymentErrorCode.contains(e.errorCode)) { "${errorCode.message}(${e.message})" } else { errorCode.message @@ -48,13 +52,13 @@ class PaymentService( fun savePayment( reservationId: Long, - paymentConfirmResponse: PaymentClientConfirmResponse + paymentGatewayResponse: PaymentGatewayResponse ): PaymentCreateResponse { val payment: PaymentEntity = paymentWriter.createPayment( reservationId = reservationId, - paymentClientConfirmResponse = paymentConfirmResponse + paymentGatewayResponse = paymentGatewayResponse ) - val detail: PaymentDetailEntity = paymentWriter.createDetail(paymentConfirmResponse, payment.id) + val detail: PaymentDetailEntity = paymentWriter.createDetail(paymentGatewayResponse, payment.id) return PaymentCreateResponse(paymentId = payment.id, detailId = detail.id) } @@ -62,7 +66,7 @@ class PaymentService( fun cancel(userId: Long, request: PaymentCancelRequest) { val payment: PaymentEntity = findByReservationIdOrThrow(request.reservationId) - val clientCancelResponse: PaymentClientCancelResponse = paymentClient.cancel( + val clientCancelResponse: PaymentGatewayCancelResponse = paymentClient.cancel( paymentKey = payment.paymentKey, amount = payment.totalAmount, cancelReason = request.cancelReason @@ -81,16 +85,16 @@ class PaymentService( } @Transactional(readOnly = true) - fun findDetailByReservationId(reservationId: Long): PaymentWithDetailResponse? { + fun findDetailByReservationId(reservationId: Long): PaymentResponse? { log.info { "[findDetailByReservationId] 예약 결제 정보 조회 시작: reservationId=$reservationId" } val payment: PaymentEntity? = findByReservationIdOrNull(reservationId) val paymentDetail: PaymentDetailEntity? = payment?.let { findDetailByPaymentIdOrNull(it.id) } val cancelDetail: CanceledPaymentEntity? = payment?.let { findCancelByPaymentIdOrNull(it.id) } - return payment?.toDetailResponse( - detail = paymentDetail?.toPaymentDetailResponse(), - cancel = cancelDetail?.toCancelDetailResponse() + return payment?.toResponse( + detail = paymentDetail?.toResponse(), + cancel = cancelDetail?.toResponse() ) } diff --git a/service/src/main/kotlin/com/sangdol/roomescape/payment/business/PaymentWriter.kt b/service/src/main/kotlin/com/sangdol/roomescape/payment/business/PaymentWriter.kt index a8f14a9f..948e9b4b 100644 --- a/service/src/main/kotlin/com/sangdol/roomescape/payment/business/PaymentWriter.kt +++ b/service/src/main/kotlin/com/sangdol/roomescape/payment/business/PaymentWriter.kt @@ -3,8 +3,13 @@ package com.sangdol.roomescape.payment.business import com.sangdol.common.persistence.IDGenerator import com.sangdol.roomescape.payment.exception.PaymentErrorCode import com.sangdol.roomescape.payment.exception.PaymentException -import com.sangdol.roomescape.payment.infrastructure.client.* -import com.sangdol.roomescape.payment.infrastructure.common.PaymentMethod +import com.sangdol.roomescape.payment.business.domain.PaymentMethod +import com.sangdol.roomescape.payment.dto.PaymentGatewayCancelResponse +import com.sangdol.roomescape.payment.dto.PaymentGatewayResponse +import com.sangdol.roomescape.payment.mapper.toCardDetailEntity +import com.sangdol.roomescape.payment.mapper.toEasypayPrepaidDetailEntity +import com.sangdol.roomescape.payment.mapper.toEntity +import com.sangdol.roomescape.payment.mapper.toTransferDetailEntity import com.sangdol.roomescape.payment.infrastructure.persistence.* import io.github.oshai.kotlinlogging.KLogger import io.github.oshai.kotlinlogging.KotlinLogging @@ -23,31 +28,31 @@ class PaymentWriter( fun createPayment( reservationId: Long, - paymentClientConfirmResponse: PaymentClientConfirmResponse + paymentGatewayResponse: PaymentGatewayResponse ): PaymentEntity { - log.info { "[PaymentWriterV2.createPayment] 결제 승인 및 결제 정보 저장 시작: reservationId=${reservationId}, paymentKey=${paymentClientConfirmResponse.paymentKey}" } + log.info { "[PaymentWriterV2.createPayment] 결제 승인 및 결제 정보 저장 시작: reservationId=${reservationId}, paymentKey=${paymentGatewayResponse.paymentKey}" } - return paymentClientConfirmResponse.toEntity(id = idGenerator.create(), reservationId = reservationId).also { + return paymentGatewayResponse.toEntity(id = idGenerator.create(), reservationId = reservationId).also { paymentRepository.save(it) log.info { "[PaymentWriterV2.createPayment] 결제 승인 및 결제 정보 저장 완료: reservationId=${reservationId}, payment.id=${it.id}" } } } fun createDetail( - paymentResponse: PaymentClientConfirmResponse, + paymentGatewayResponse: PaymentGatewayResponse, paymentId: Long, ): PaymentDetailEntity { - val method: PaymentMethod = paymentResponse.method + val method: PaymentMethod = paymentGatewayResponse.method val id = idGenerator.create() if (method == PaymentMethod.TRANSFER) { - return paymentDetailRepository.save(paymentResponse.toTransferDetailEntity(id, paymentId)) + return paymentDetailRepository.save(paymentGatewayResponse.toTransferDetailEntity(id, paymentId)) } - if (method == PaymentMethod.EASY_PAY && paymentResponse.card == null) { - return paymentDetailRepository.save(paymentResponse.toEasypayPrepaidDetailEntity(id, paymentId)) + if (method == PaymentMethod.EASY_PAY && paymentGatewayResponse.card == null) { + return paymentDetailRepository.save(paymentGatewayResponse.toEasypayPrepaidDetailEntity(id, paymentId)) } - if (paymentResponse.card != null) { - return paymentDetailRepository.save(paymentResponse.toCardDetailEntity(id, paymentId)) + if (paymentGatewayResponse.card != null) { + return paymentDetailRepository.save(paymentGatewayResponse.toCardDetailEntity(id, paymentId)) } throw PaymentException(PaymentErrorCode.NOT_SUPPORTED_PAYMENT_TYPE) } @@ -56,7 +61,7 @@ class PaymentWriter( userId: Long, payment: PaymentEntity, requestedAt: Instant, - cancelResponse: PaymentClientCancelResponse + cancelResponse: PaymentGatewayCancelResponse ): CanceledPaymentEntity { log.debug { "[PaymentWriterV2.cancelPayment] 결제 취소 정보 저장 시작: payment.id=${payment.id}" } diff --git a/service/src/main/kotlin/com/sangdol/roomescape/payment/infrastructure/common/PaymentTypes.kt b/service/src/main/kotlin/com/sangdol/roomescape/payment/business/domain/PaymentDefinitions.kt similarity index 99% rename from service/src/main/kotlin/com/sangdol/roomescape/payment/infrastructure/common/PaymentTypes.kt rename to service/src/main/kotlin/com/sangdol/roomescape/payment/business/domain/PaymentDefinitions.kt index 5fd64a1d..c642d12c 100644 --- a/service/src/main/kotlin/com/sangdol/roomescape/payment/infrastructure/common/PaymentTypes.kt +++ b/service/src/main/kotlin/com/sangdol/roomescape/payment/business/domain/PaymentDefinitions.kt @@ -1,4 +1,4 @@ -package com.sangdol.roomescape.payment.infrastructure.common +package com.sangdol.roomescape.payment.business.domain import com.fasterxml.jackson.annotation.JsonCreator import com.sangdol.roomescape.payment.exception.PaymentErrorCode diff --git a/service/src/main/kotlin/com/sangdol/roomescape/payment/business/domain/PaymentClientError.kt b/service/src/main/kotlin/com/sangdol/roomescape/payment/business/domain/UserFacingPaymentErrorCode.kt similarity index 96% rename from service/src/main/kotlin/com/sangdol/roomescape/payment/business/domain/PaymentClientError.kt rename to service/src/main/kotlin/com/sangdol/roomescape/payment/business/domain/UserFacingPaymentErrorCode.kt index fb064ad1..346ba486 100644 --- a/service/src/main/kotlin/com/sangdol/roomescape/payment/business/domain/PaymentClientError.kt +++ b/service/src/main/kotlin/com/sangdol/roomescape/payment/business/domain/UserFacingPaymentErrorCode.kt @@ -1,6 +1,6 @@ package com.sangdol.roomescape.payment.business.domain -enum class PaymentClientError { +enum class UserFacingPaymentErrorCode { ALREADY_PROCESSED_PAYMENT, EXCEED_MAX_CARD_INSTALLMENT_PLAN, NOT_ALLOWED_POINT_USE, 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 c79b1cb7..5f7160b8 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,9 +4,9 @@ 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.dto.PaymentGatewayResponse +import com.sangdol.roomescape.payment.dto.PaymentCancelRequest +import com.sangdol.roomescape.payment.dto.PaymentConfirmRequest import io.swagger.v3.oas.annotations.Operation import io.swagger.v3.oas.annotations.responses.ApiResponse import io.swagger.v3.oas.annotations.responses.ApiResponses @@ -21,7 +21,7 @@ interface PaymentAPI { @ApiResponses(ApiResponse(responseCode = "200", useReturnTypeSchema = true)) fun confirmPayment( @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/dto/PaymentClientDTO.kt b/service/src/main/kotlin/com/sangdol/roomescape/payment/dto/PaymentClientDTO.kt new file mode 100644 index 00000000..87670ff9 --- /dev/null +++ b/service/src/main/kotlin/com/sangdol/roomescape/payment/dto/PaymentClientDTO.kt @@ -0,0 +1,59 @@ +package com.sangdol.roomescape.payment.dto + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize +import com.sangdol.roomescape.payment.business.domain.* +import com.sangdol.roomescape.payment.infrastructure.client.CancelDetailDeserializer +import java.time.OffsetDateTime + +data class PaymentGatewayResponse( + val paymentKey: String, + val orderId: String, + val type: PaymentType, + val status: PaymentStatus, + val totalAmount: Int, + val vat: Int, + val suppliedAmount: Int, + val method: PaymentMethod, + val card: CardDetailResponse?, + val easyPay: EasyPayDetailResponse?, + val transfer: TransferDetailResponse?, + val requestedAt: OffsetDateTime, + val approvedAt: OffsetDateTime, +) + +data class PaymentGatewayCancelResponse( + val status: PaymentStatus, + @JsonDeserialize(using = CancelDetailDeserializer::class) + val cancels: CancelDetail, +) + +data class CardDetailResponse( + val issuerCode: CardIssuerCode, + val number: String, + val amount: Int, + val cardType: CardType, + val ownerType: CardOwnerType, + val isInterestFree: Boolean, + val approveNo: String, + val installmentPlanMonths: Int +) + +data class EasyPayDetailResponse( + val provider: EasyPayCompanyCode, + val amount: Int, + val discountAmount: Int, +) + +data class TransferDetailResponse( + val bankCode: BankCode, + val settlementStatus: String, +) + +data class CancelDetail( + val cancelAmount: Int, + val cardDiscountAmount: Int, + val transferDiscountAmount: Int, + val easyPayDiscountAmount: Int, + val canceledAt: OffsetDateTime, + val cancelReason: String +) diff --git a/service/src/main/kotlin/com/sangdol/roomescape/payment/dto/PaymentFindDTO.kt b/service/src/main/kotlin/com/sangdol/roomescape/payment/dto/PaymentFindDTO.kt new file mode 100644 index 00000000..504662ac --- /dev/null +++ b/service/src/main/kotlin/com/sangdol/roomescape/payment/dto/PaymentFindDTO.kt @@ -0,0 +1,49 @@ +package com.sangdol.roomescape.payment.dto + +import com.sangdol.roomescape.payment.business.domain.PaymentStatus +import java.time.Instant + +data class PaymentResponse( + val orderId: String, + val totalAmount: Int, + val method: String, + val status: PaymentStatus, + val requestedAt: Instant, + val approvedAt: Instant, + val detail: PaymentDetailResponse?, + val cancel: PaymentCancelDetailResponse?, +) + +sealed class PaymentDetailResponse { + data class CardDetailResponse( + val type: String = "CARD", + val issuerCode: String, + val cardType: String, + val ownerType: String, + val cardNumber: String, + val amount: Int, + val approvalNumber: String, + val installmentPlanMonths: Int, + val easypayProviderName: String?, + val easypayDiscountAmount: Int?, + ) : PaymentDetailResponse() + + data class BankTransferDetailResponse( + val type: String = "BANK_TRANSFER", + val bankName: String, + ) : PaymentDetailResponse() + + data class EasyPayPrepaidDetailResponse( + val type: String = "EASYPAY_PREPAID", + val providerName: String, + val amount: Int, + val discountAmount: Int, + ) : PaymentDetailResponse() +} + +data class PaymentCancelDetailResponse( + val cancellationRequestedAt: Instant, + val cancellationApprovedAt: Instant?, + val cancelReason: String, + val canceledBy: Long, +) diff --git a/service/src/main/kotlin/com/sangdol/roomescape/payment/dto/PaymentWriteDTO.kt b/service/src/main/kotlin/com/sangdol/roomescape/payment/dto/PaymentWriteDTO.kt new file mode 100644 index 00000000..2d89c07c --- /dev/null +++ b/service/src/main/kotlin/com/sangdol/roomescape/payment/dto/PaymentWriteDTO.kt @@ -0,0 +1,20 @@ +package com.sangdol.roomescape.payment.dto + +import java.time.Instant + +data class PaymentConfirmRequest( + val paymentKey: String, + val orderId: String, + val amount: Int, +) + +data class PaymentCreateResponse( + val paymentId: Long, + val detailId: Long +) + +data class PaymentCancelRequest( + val reservationId: Long, + val cancelReason: String, + val requestedAt: Instant = Instant.now() +) diff --git a/service/src/main/kotlin/com/sangdol/roomescape/payment/infrastructure/client/TosspayCancelDTO.kt b/service/src/main/kotlin/com/sangdol/roomescape/payment/infrastructure/client/TosspayCancelDTO.kt deleted file mode 100644 index 2ba4f6a1..00000000 --- a/service/src/main/kotlin/com/sangdol/roomescape/payment/infrastructure/client/TosspayCancelDTO.kt +++ /dev/null @@ -1,67 +0,0 @@ -package com.sangdol.roomescape.payment.infrastructure.client - -import com.fasterxml.jackson.core.JsonParser -import com.fasterxml.jackson.databind.DeserializationContext -import com.fasterxml.jackson.databind.JsonNode -import com.fasterxml.jackson.databind.annotation.JsonDeserialize -import com.sangdol.roomescape.payment.infrastructure.common.PaymentStatus -import com.sangdol.roomescape.payment.infrastructure.persistence.CanceledPaymentEntity -import java.time.Instant -import java.time.OffsetDateTime - -data class PaymentClientCancelResponse( - val status: PaymentStatus, - @JsonDeserialize(using = CancelDetailDeserializer::class) - val cancels: CancelDetail, -) - -data class CancelDetail( - val cancelAmount: Int, - val cardDiscountAmount: Int, - val transferDiscountAmount: Int, - val easyPayDiscountAmount: Int, - val canceledAt: OffsetDateTime, - val cancelReason: String -) - -fun CancelDetail.toEntity( - id: Long, - paymentId: Long, - canceledBy: Long, - cancelRequestedAt: Instant -) = CanceledPaymentEntity( - id = id, - canceledAt = this.canceledAt.toInstant(), - requestedAt = cancelRequestedAt, - paymentId = paymentId, - canceledBy = canceledBy, - cancelReason = this.cancelReason, - cancelAmount = this.cancelAmount, - cardDiscountAmount = this.cardDiscountAmount, - transferDiscountAmount = this.transferDiscountAmount, - easypayDiscountAmount = this.easyPayDiscountAmount -) - -class CancelDetailDeserializer : com.fasterxml.jackson.databind.JsonDeserializer() { - override fun deserialize( - p: JsonParser, - ctxt: DeserializationContext - ): CancelDetail? { - val node: JsonNode = p.codec.readTree(p) ?: return null - - val targetNode = when { - node.isArray && !node.isEmpty -> node[0] - node.isObject -> node - else -> return null - } - - return CancelDetail( - cancelAmount = targetNode.get("cancelAmount").asInt(), - cardDiscountAmount = targetNode.get("cardDiscountAmount").asInt(), - transferDiscountAmount = targetNode.get("transferDiscountAmount").asInt(), - easyPayDiscountAmount = targetNode.get("easyPayDiscountAmount").asInt(), - canceledAt = OffsetDateTime.parse(targetNode.get("canceledAt").asText()), - cancelReason = targetNode.get("cancelReason").asText() - ) - } -} 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 8840bd20..f296fc38 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,8 @@ package com.sangdol.roomescape.payment.infrastructure.client import com.fasterxml.jackson.databind.ObjectMapper +import com.sangdol.roomescape.payment.dto.PaymentGatewayCancelResponse +import com.sangdol.roomescape.payment.dto.PaymentGatewayResponse import com.sangdol.roomescape.payment.exception.ExternalPaymentException import com.sangdol.roomescape.payment.exception.PaymentErrorCode import com.sangdol.roomescape.payment.exception.PaymentException @@ -29,7 +31,7 @@ class TosspayClient( paymentKey: String, orderId: String, amount: Int, - ): PaymentClientConfirmResponse { + ): PaymentGatewayResponse { val startTime = System.currentTimeMillis() log.info { "[TosspayClient.confirm] 결제 승인 요청: paymentKey=$paymentKey, orderId=$orderId, amount=$amount" } @@ -43,7 +45,7 @@ class TosspayClient( paymentKey: String, amount: Int, cancelReason: String - ): PaymentClientCancelResponse { + ): PaymentGatewayCancelResponse { val startTime = System.currentTimeMillis() log.info { "[TosspayClient.cancel] 결제 취소 요청: paymentKey=$paymentKey, amount=$amount, cancelReason=$cancelReason" } @@ -63,7 +65,7 @@ private class ConfirmClient( private val errorHandler: TosspayErrorHandler = TosspayErrorHandler(objectMapper) - fun request(paymentKey: String, orderId: String, amount: Int): PaymentClientConfirmResponse { + fun request(paymentKey: String, orderId: String, amount: Int): PaymentGatewayResponse { val response = client.post() .uri(CONFIRM_URI) .contentType(MediaType.APPLICATION_JSON) @@ -84,7 +86,7 @@ private class ConfirmClient( log.debug { "[TosspayClient.confirm] 응답 수신: json = $response" } - return objectMapper.readValue(response, PaymentClientConfirmResponse::class.java) + return objectMapper.readValue(response, PaymentGatewayResponse::class.java) } } @@ -102,7 +104,7 @@ private class CancelClient( paymentKey: String, amount: Int, cancelReason: String - ): PaymentClientCancelResponse { + ): PaymentGatewayCancelResponse { val response = client.post() .uri(CANCEL_URI, paymentKey) .body( @@ -120,7 +122,7 @@ private class CancelClient( } log.debug { "[TosspayClient.cancel] 응답 수신: json = $response" } - return objectMapper.readValue(response, PaymentClientCancelResponse::class.java) + return objectMapper.readValue(response, PaymentGatewayCancelResponse::class.java) } } diff --git a/service/src/main/kotlin/com/sangdol/roomescape/payment/infrastructure/client/TosspayResponseDeserializer.kt b/service/src/main/kotlin/com/sangdol/roomescape/payment/infrastructure/client/TosspayResponseDeserializer.kt new file mode 100644 index 00000000..1ff0d091 --- /dev/null +++ b/service/src/main/kotlin/com/sangdol/roomescape/payment/infrastructure/client/TosspayResponseDeserializer.kt @@ -0,0 +1,32 @@ +package com.sangdol.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.sangdol.roomescape.payment.dto.CancelDetail +import java.time.OffsetDateTime + +class CancelDetailDeserializer : JsonDeserializer() { + override fun deserialize( + p: JsonParser, + ctxt: DeserializationContext + ): CancelDetail? { + val node: JsonNode = p.codec.readTree(p) ?: return null + + val targetNode = when { + node.isArray && !node.isEmpty -> node[0] + node.isObject -> node + else -> return null + } + + return CancelDetail( + cancelAmount = targetNode.get("cancelAmount").asInt(), + cardDiscountAmount = targetNode.get("cardDiscountAmount").asInt(), + transferDiscountAmount = targetNode.get("transferDiscountAmount").asInt(), + easyPayDiscountAmount = targetNode.get("easyPayDiscountAmount").asInt(), + canceledAt = OffsetDateTime.parse(targetNode.get("canceledAt").asText()), + cancelReason = targetNode.get("cancelReason").asText() + ) + } +} diff --git a/service/src/main/kotlin/com/sangdol/roomescape/payment/infrastructure/persistence/PaymentDetailEntity.kt b/service/src/main/kotlin/com/sangdol/roomescape/payment/infrastructure/persistence/PaymentDetailEntity.kt index 0e06f775..666a7ff0 100644 --- a/service/src/main/kotlin/com/sangdol/roomescape/payment/infrastructure/persistence/PaymentDetailEntity.kt +++ b/service/src/main/kotlin/com/sangdol/roomescape/payment/infrastructure/persistence/PaymentDetailEntity.kt @@ -1,7 +1,11 @@ package com.sangdol.roomescape.payment.infrastructure.persistence import com.sangdol.common.persistence.PersistableBaseEntity -import com.sangdol.roomescape.payment.infrastructure.common.* +import com.sangdol.roomescape.payment.business.domain.BankCode +import com.sangdol.roomescape.payment.business.domain.CardIssuerCode +import com.sangdol.roomescape.payment.business.domain.CardOwnerType +import com.sangdol.roomescape.payment.business.domain.CardType +import com.sangdol.roomescape.payment.business.domain.EasyPayCompanyCode import jakarta.persistence.* @Entity diff --git a/service/src/main/kotlin/com/sangdol/roomescape/payment/infrastructure/persistence/PaymentEntity.kt b/service/src/main/kotlin/com/sangdol/roomescape/payment/infrastructure/persistence/PaymentEntity.kt index 1571e15e..9db97096 100644 --- a/service/src/main/kotlin/com/sangdol/roomescape/payment/infrastructure/persistence/PaymentEntity.kt +++ b/service/src/main/kotlin/com/sangdol/roomescape/payment/infrastructure/persistence/PaymentEntity.kt @@ -1,9 +1,9 @@ package com.sangdol.roomescape.payment.infrastructure.persistence import com.sangdol.common.persistence.PersistableBaseEntity -import com.sangdol.roomescape.payment.infrastructure.common.PaymentMethod -import com.sangdol.roomescape.payment.infrastructure.common.PaymentStatus -import com.sangdol.roomescape.payment.infrastructure.common.PaymentType +import com.sangdol.roomescape.payment.business.domain.PaymentMethod +import com.sangdol.roomescape.payment.business.domain.PaymentStatus +import com.sangdol.roomescape.payment.business.domain.PaymentType import jakarta.persistence.Entity import jakarta.persistence.EnumType import jakarta.persistence.Enumerated diff --git a/service/src/main/kotlin/com/sangdol/roomescape/payment/infrastructure/client/TosspayConfirmDTO.kt b/service/src/main/kotlin/com/sangdol/roomescape/payment/mapper/PaymentClientDTOMappingExtensions.kt similarity index 58% rename from service/src/main/kotlin/com/sangdol/roomescape/payment/infrastructure/client/TosspayConfirmDTO.kt rename to service/src/main/kotlin/com/sangdol/roomescape/payment/mapper/PaymentClientDTOMappingExtensions.kt index 55258c22..cc2979a8 100644 --- a/service/src/main/kotlin/com/sangdol/roomescape/payment/infrastructure/client/TosspayConfirmDTO.kt +++ b/service/src/main/kotlin/com/sangdol/roomescape/payment/mapper/PaymentClientDTOMappingExtensions.kt @@ -1,31 +1,13 @@ -package com.sangdol.roomescape.payment.infrastructure.client +package com.sangdol.roomescape.payment.mapper +import com.sangdol.roomescape.payment.dto.CancelDetail +import com.sangdol.roomescape.payment.dto.PaymentGatewayResponse import com.sangdol.roomescape.payment.exception.PaymentErrorCode import com.sangdol.roomescape.payment.exception.PaymentException -import com.sangdol.roomescape.payment.infrastructure.common.* -import com.sangdol.roomescape.payment.infrastructure.persistence.PaymentBankTransferDetailEntity -import com.sangdol.roomescape.payment.infrastructure.persistence.PaymentCardDetailEntity -import com.sangdol.roomescape.payment.infrastructure.persistence.PaymentEasypayPrepaidDetailEntity -import com.sangdol.roomescape.payment.infrastructure.persistence.PaymentEntity -import java.time.OffsetDateTime +import com.sangdol.roomescape.payment.infrastructure.persistence.* +import java.time.Instant -data class PaymentClientConfirmResponse( - val paymentKey: String, - val orderId: String, - val type: PaymentType, - val status: PaymentStatus, - val totalAmount: Int, - val vat: Int, - val suppliedAmount: Int, - val method: PaymentMethod, - val card: CardDetail?, - val easyPay: EasyPayDetail?, - val transfer: TransferDetail?, - val requestedAt: OffsetDateTime, - val approvedAt: OffsetDateTime, -) - -fun PaymentClientConfirmResponse.toEntity( +fun PaymentGatewayResponse.toEntity( id: Long, reservationId: Long, ) = PaymentEntity( @@ -41,18 +23,7 @@ fun PaymentClientConfirmResponse.toEntity( status = this.status, ) -data class CardDetail( - val issuerCode: CardIssuerCode, - val number: String, - val amount: Int, - val cardType: CardType, - val ownerType: CardOwnerType, - val isInterestFree: Boolean, - val approveNo: String, - val installmentPlanMonths: Int -) - -fun PaymentClientConfirmResponse.toCardDetailEntity(id: Long, paymentId: Long): PaymentCardDetailEntity { +fun PaymentGatewayResponse.toCardDetailEntity(id: Long, paymentId: Long): PaymentCardDetailEntity { val cardDetail = this.card ?: throw PaymentException(PaymentErrorCode.PAYMENT_UNEXPECTED_ERROR) return PaymentCardDetailEntity( @@ -73,13 +44,7 @@ fun PaymentClientConfirmResponse.toCardDetailEntity(id: Long, paymentId: Long): ) } -data class EasyPayDetail( - val provider: EasyPayCompanyCode, - val amount: Int, - val discountAmount: Int, -) - -fun PaymentClientConfirmResponse.toEasypayPrepaidDetailEntity( +fun PaymentGatewayResponse.toEasypayPrepaidDetailEntity( id: Long, paymentId: Long ): PaymentEasypayPrepaidDetailEntity { @@ -96,12 +61,7 @@ fun PaymentClientConfirmResponse.toEasypayPrepaidDetailEntity( ) } -data class TransferDetail( - val bankCode: BankCode, - val settlementStatus: String, -) - -fun PaymentClientConfirmResponse.toTransferDetailEntity( +fun PaymentGatewayResponse.toTransferDetailEntity( id: Long, paymentId: Long ): PaymentBankTransferDetailEntity { @@ -116,3 +76,21 @@ fun PaymentClientConfirmResponse.toTransferDetailEntity( settlementStatus = transferDetail.settlementStatus ) } + +fun CancelDetail.toEntity( + id: Long, + paymentId: Long, + canceledBy: Long, + cancelRequestedAt: Instant +) = CanceledPaymentEntity( + id = id, + canceledAt = this.canceledAt.toInstant(), + requestedAt = cancelRequestedAt, + paymentId = paymentId, + canceledBy = canceledBy, + cancelReason = this.cancelReason, + cancelAmount = this.cancelAmount, + cardDiscountAmount = this.cardDiscountAmount, + transferDiscountAmount = this.transferDiscountAmount, + easypayDiscountAmount = this.easyPayDiscountAmount +) diff --git a/service/src/main/kotlin/com/sangdol/roomescape/payment/mapper/PaymentFindDTOMappingExtensions.kt b/service/src/main/kotlin/com/sangdol/roomescape/payment/mapper/PaymentFindDTOMappingExtensions.kt new file mode 100644 index 00000000..a95ec88d --- /dev/null +++ b/service/src/main/kotlin/com/sangdol/roomescape/payment/mapper/PaymentFindDTOMappingExtensions.kt @@ -0,0 +1,70 @@ +package com.sangdol.roomescape.payment.mapper + +import com.sangdol.roomescape.payment.dto.PaymentCancelDetailResponse +import com.sangdol.roomescape.payment.dto.PaymentDetailResponse +import com.sangdol.roomescape.payment.dto.PaymentResponse +import com.sangdol.roomescape.payment.exception.PaymentErrorCode +import com.sangdol.roomescape.payment.exception.PaymentException +import com.sangdol.roomescape.payment.infrastructure.persistence.* + +fun PaymentEntity.toResponse( + detail: PaymentDetailResponse?, + cancel: PaymentCancelDetailResponse? +): PaymentResponse { + return PaymentResponse( + orderId = this.orderId, + totalAmount = this.totalAmount, + method = this.method.koreanName, + status = this.status, + requestedAt = this.requestedAt, + approvedAt = this.approvedAt, + detail = detail, + cancel = cancel + ) +} + +fun PaymentDetailEntity.toResponse(): PaymentDetailResponse { + return when (this) { + is PaymentCardDetailEntity -> this.toResponse() + is PaymentBankTransferDetailEntity -> this.toResponse() + is PaymentEasypayPrepaidDetailEntity -> this.toResponse() + else -> throw PaymentException(PaymentErrorCode.NOT_SUPPORTED_PAYMENT_TYPE) + } +} + +fun PaymentCardDetailEntity.toResponse(): PaymentDetailResponse.CardDetailResponse { + return PaymentDetailResponse.CardDetailResponse( + issuerCode = this.issuerCode.koreanName, + cardType = this.cardType.koreanName, + ownerType = this.ownerType.koreanName, + cardNumber = this.cardNumber, + amount = this.amount, + approvalNumber = this.approvalNumber, + installmentPlanMonths = this.installmentPlanMonths, + easypayProviderName = this.easypayProviderCode?.koreanName, + easypayDiscountAmount = this.easypayDiscountAmount + ) +} + +fun PaymentBankTransferDetailEntity.toResponse(): PaymentDetailResponse.BankTransferDetailResponse { + return PaymentDetailResponse.BankTransferDetailResponse( + bankName = this.bankCode.koreanName + ) +} + +fun PaymentEasypayPrepaidDetailEntity.toResponse(): PaymentDetailResponse.EasyPayPrepaidDetailResponse { + return PaymentDetailResponse.EasyPayPrepaidDetailResponse( + providerName = this.easypayProviderCode.koreanName, + amount = this.amount, + discountAmount = this.discountAmount + ) +} + +fun CanceledPaymentEntity.toResponse(): PaymentCancelDetailResponse { + return PaymentCancelDetailResponse( + cancellationRequestedAt = this.requestedAt, + cancellationApprovedAt = this.canceledAt, + cancelReason = this.cancelReason, + canceledBy = this.canceledBy + ) +} 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 e4c1e6f1..9f2f36b2 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,7 +5,9 @@ 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 com.sangdol.roomescape.payment.dto.PaymentCancelRequest +import com.sangdol.roomescape.payment.dto.PaymentConfirmRequest +import com.sangdol.roomescape.payment.dto.PaymentGatewayResponse import jakarta.validation.Valid import org.springframework.http.ResponseEntity import org.springframework.web.bind.annotation.* @@ -19,7 +21,7 @@ class PaymentController( @PostMapping("/confirm") override fun confirmPayment( @Valid @RequestBody request: PaymentConfirmRequest - ): ResponseEntity> { + ): ResponseEntity> { val response = paymentService.requestConfirm(request) return ResponseEntity.ok(CommonApiResponse(response)) diff --git a/service/src/main/kotlin/com/sangdol/roomescape/payment/web/PaymentDTO.kt b/service/src/main/kotlin/com/sangdol/roomescape/payment/web/PaymentDTO.kt deleted file mode 100644 index bb94d916..00000000 --- a/service/src/main/kotlin/com/sangdol/roomescape/payment/web/PaymentDTO.kt +++ /dev/null @@ -1,134 +0,0 @@ -package com.sangdol.roomescape.payment.web - -import com.sangdol.roomescape.payment.exception.PaymentErrorCode -import com.sangdol.roomescape.payment.exception.PaymentException -import com.sangdol.roomescape.payment.infrastructure.common.PaymentStatus -import com.sangdol.roomescape.payment.infrastructure.common.PaymentType -import com.sangdol.roomescape.payment.infrastructure.persistence.* -import com.sangdol.roomescape.payment.web.PaymentDetailResponse.* -import java.time.Instant - -data class PaymentConfirmRequest( - val paymentKey: String, - val orderId: String, - val amount: Int, -) - -data class PaymentCreateResponse( - val paymentId: Long, - val detailId: Long -) - -data class PaymentCancelRequest( - val reservationId: Long, - val cancelReason: String, - val requestedAt: Instant = Instant.now() -) - -data class PaymentWithDetailResponse( - val orderId: String, - val totalAmount: Int, - val method: String, - val status: PaymentStatus, - val requestedAt: Instant, - val approvedAt: Instant, - val detail: PaymentDetailResponse?, - val cancel: PaymentCancelDetailResponse?, -) - -fun PaymentEntity.toDetailResponse( - detail: PaymentDetailResponse?, - cancel: PaymentCancelDetailResponse? -): PaymentWithDetailResponse { - return PaymentWithDetailResponse( - orderId = this.orderId, - totalAmount = this.totalAmount, - method = this.method.koreanName, - status = this.status, - requestedAt = this.requestedAt, - approvedAt = this.approvedAt, - detail = detail, - cancel = cancel - ) -} - -sealed class PaymentDetailResponse { - - data class CardDetailResponse( - val type: String = "CARD", - val issuerCode: String, - val cardType: String, - val ownerType: String, - val cardNumber: String, - val amount: Int, - val approvalNumber: String, - val installmentPlanMonths: Int, - val easypayProviderName: String?, - val easypayDiscountAmount: Int?, - ) : PaymentDetailResponse() - - data class BankTransferDetailResponse( - val type: String = "BANK_TRANSFER", - val bankName: String, - ) : PaymentDetailResponse() - - data class EasyPayPrepaidDetailResponse( - val type: String = "EASYPAY_PREPAID", - val providerName: String, - val amount: Int, - val discountAmount: Int, - ) : PaymentDetailResponse() -} - -fun PaymentDetailEntity.toPaymentDetailResponse(): PaymentDetailResponse { - return when (this) { - is PaymentCardDetailEntity -> this.toCardDetailResponse() - is PaymentBankTransferDetailEntity -> this.toBankTransferDetailResponse() - is PaymentEasypayPrepaidDetailEntity -> this.toEasyPayPrepaidDetailResponse() - else -> throw PaymentException(PaymentErrorCode.NOT_SUPPORTED_PAYMENT_TYPE) - } -} - -fun PaymentCardDetailEntity.toCardDetailResponse(): CardDetailResponse { - return CardDetailResponse( - issuerCode = this.issuerCode.koreanName, - cardType = this.cardType.koreanName, - ownerType = this.ownerType.koreanName, - cardNumber = this.cardNumber, - amount = this.amount, - approvalNumber = this.approvalNumber, - installmentPlanMonths = this.installmentPlanMonths, - easypayProviderName = this.easypayProviderCode?.koreanName, - easypayDiscountAmount = this.easypayDiscountAmount - ) -} - -fun PaymentBankTransferDetailEntity.toBankTransferDetailResponse(): BankTransferDetailResponse { - return BankTransferDetailResponse( - bankName = this.bankCode.koreanName - ) -} - -fun PaymentEasypayPrepaidDetailEntity.toEasyPayPrepaidDetailResponse(): EasyPayPrepaidDetailResponse { - return EasyPayPrepaidDetailResponse( - providerName = this.easypayProviderCode.koreanName, - amount = this.amount, - discountAmount = this.discountAmount - ) -} - -data class PaymentCancelDetailResponse( - val cancellationRequestedAt: Instant, - val cancellationApprovedAt: Instant?, - val cancelReason: String, - val canceledBy: Long, -) - -fun CanceledPaymentEntity.toCancelDetailResponse(): PaymentCancelDetailResponse { - return PaymentCancelDetailResponse( - cancellationRequestedAt = this.requestedAt, - cancellationApprovedAt = this.canceledAt, - cancelReason = this.cancelReason, - canceledBy = this.canceledBy - ) -} diff --git a/service/src/main/kotlin/com/sangdol/roomescape/reservation/business/ReservationService.kt b/service/src/main/kotlin/com/sangdol/roomescape/reservation/business/ReservationService.kt index a7537a06..6be365ad 100644 --- a/service/src/main/kotlin/com/sangdol/roomescape/reservation/business/ReservationService.kt +++ b/service/src/main/kotlin/com/sangdol/roomescape/reservation/business/ReservationService.kt @@ -3,7 +3,7 @@ package com.sangdol.roomescape.reservation.business import com.sangdol.common.persistence.IDGenerator import com.sangdol.roomescape.common.types.CurrentUserContext import com.sangdol.roomescape.payment.business.PaymentService -import com.sangdol.roomescape.payment.web.PaymentWithDetailResponse +import com.sangdol.roomescape.payment.dto.PaymentResponse import com.sangdol.roomescape.reservation.dto.PendingReservationCreateRequest import com.sangdol.roomescape.reservation.dto.PendingReservationCreateResponse import com.sangdol.roomescape.reservation.dto.ReservationCancelRequest @@ -132,7 +132,7 @@ class ReservationService( val reservation: ReservationEntity = findOrThrow(id) val user: UserContactResponse = userService.findContactById(reservation.userId) - val paymentDetail: PaymentWithDetailResponse? = paymentService.findDetailByReservationId(id) + val paymentDetail: PaymentResponse? = paymentService.findDetailByReservationId(id) return reservation.toAdditionalResponse( user = user, diff --git a/service/src/main/kotlin/com/sangdol/roomescape/reservation/dto/ReservationFindDTO.kt b/service/src/main/kotlin/com/sangdol/roomescape/reservation/dto/ReservationFindDTO.kt index 380c8e4c..7244a70f 100644 --- a/service/src/main/kotlin/com/sangdol/roomescape/reservation/dto/ReservationFindDTO.kt +++ b/service/src/main/kotlin/com/sangdol/roomescape/reservation/dto/ReservationFindDTO.kt @@ -1,6 +1,6 @@ package com.sangdol.roomescape.reservation.dto -import com.sangdol.roomescape.payment.web.PaymentWithDetailResponse +import com.sangdol.roomescape.payment.dto.PaymentResponse import com.sangdol.roomescape.reservation.infrastructure.persistence.ReservationStatus import com.sangdol.roomescape.user.dto.UserContactResponse import java.time.Instant @@ -22,7 +22,7 @@ data class ReservationAdditionalResponse( val reserver: ReserverInfo, val user: UserContactResponse, val applicationDateTime: Instant, - val payment: PaymentWithDetailResponse?, + val payment: PaymentResponse?, ) data class ReserverInfo( diff --git a/service/src/main/kotlin/com/sangdol/roomescape/reservation/mapper/ReservationMappingExtensions.kt b/service/src/main/kotlin/com/sangdol/roomescape/reservation/mapper/ReservationMappingExtensions.kt index 1699b2a4..052fffd4 100644 --- a/service/src/main/kotlin/com/sangdol/roomescape/reservation/mapper/ReservationMappingExtensions.kt +++ b/service/src/main/kotlin/com/sangdol/roomescape/reservation/mapper/ReservationMappingExtensions.kt @@ -1,6 +1,6 @@ package com.sangdol.roomescape.reservation.mapper -import com.sangdol.roomescape.payment.web.PaymentWithDetailResponse +import com.sangdol.roomescape.payment.dto.PaymentResponse import com.sangdol.roomescape.reservation.dto.PendingReservationCreateRequest import com.sangdol.roomescape.reservation.dto.ReservationAdditionalResponse import com.sangdol.roomescape.reservation.dto.ReservationOverviewResponse @@ -40,7 +40,7 @@ fun ReservationEntity.toOverviewResponse( fun ReservationEntity.toAdditionalResponse( user: UserContactResponse, - payment: PaymentWithDetailResponse?, + payment: PaymentResponse?, ): ReservationAdditionalResponse { return ReservationAdditionalResponse( id = this.id, diff --git a/service/src/test/kotlin/com/sangdol/data/DefaultDataInitializer.kt b/service/src/test/kotlin/com/sangdol/data/DefaultDataInitializer.kt index e4b1f55c..4faa0a6e 100644 --- a/service/src/test/kotlin/com/sangdol/data/DefaultDataInitializer.kt +++ b/service/src/test/kotlin/com/sangdol/data/DefaultDataInitializer.kt @@ -6,7 +6,14 @@ import com.sangdol.common.utils.KoreaDateTime import com.sangdol.roomescape.admin.infrastructure.persistence.AdminEntity import com.sangdol.roomescape.admin.infrastructure.persistence.AdminPermissionLevel import com.sangdol.roomescape.admin.infrastructure.persistence.AdminType -import com.sangdol.roomescape.payment.infrastructure.common.* +import com.sangdol.roomescape.payment.business.domain.BankCode +import com.sangdol.roomescape.payment.business.domain.CardIssuerCode +import com.sangdol.roomescape.payment.business.domain.CardOwnerType +import com.sangdol.roomescape.payment.business.domain.CardType +import com.sangdol.roomescape.payment.business.domain.EasyPayCompanyCode +import com.sangdol.roomescape.payment.business.domain.PaymentMethod +import com.sangdol.roomescape.payment.business.domain.PaymentStatus +import com.sangdol.roomescape.payment.business.domain.PaymentType import com.sangdol.roomescape.reservation.infrastructure.persistence.ReservationStatus import com.sangdol.roomescape.schedule.infrastructure.persistence.ScheduleStatus import com.sangdol.roomescape.store.infrastructure.persistence.StoreEntity diff --git a/service/src/test/kotlin/com/sangdol/roomescape/payment/PaymentAPITest.kt b/service/src/test/kotlin/com/sangdol/roomescape/payment/PaymentAPITest.kt index c18fce21..c980ad28 100644 --- a/service/src/test/kotlin/com/sangdol/roomescape/payment/PaymentAPITest.kt +++ b/service/src/test/kotlin/com/sangdol/roomescape/payment/PaymentAPITest.kt @@ -11,7 +11,7 @@ //import com.sangdol.roomescape.payment.infrastructure.client.TransferDetail //import com.sangdol.roomescape.payment.infrastructure.common.* //import com.sangdol.roomescape.payment.infrastructure.persistence.* -//import com.sangdol.roomescape.payment.web.PaymentConfirmRequest +//import com.sangdol.roomescape.payment.dto.PaymentConfirmRequest //import com.sangdol.roomescape.payment.web.PaymentCreateResponse //import com.sangdol.roomescape.supports.* //import io.kotest.matchers.shouldBe diff --git a/service/src/test/kotlin/com/sangdol/roomescape/payment/PaymentTypeTest.kt b/service/src/test/kotlin/com/sangdol/roomescape/payment/PaymentTypeTest.kt index 5f3c95ff..ca6ca244 100644 --- a/service/src/test/kotlin/com/sangdol/roomescape/payment/PaymentTypeTest.kt +++ b/service/src/test/kotlin/com/sangdol/roomescape/payment/PaymentTypeTest.kt @@ -1,8 +1,15 @@ package com.sangdol.roomescape.payment +import com.sangdol.roomescape.payment.business.domain.BankCode +import com.sangdol.roomescape.payment.business.domain.CardIssuerCode +import com.sangdol.roomescape.payment.business.domain.CardOwnerType +import com.sangdol.roomescape.payment.business.domain.CardType +import com.sangdol.roomescape.payment.business.domain.EasyPayCompanyCode +import com.sangdol.roomescape.payment.business.domain.PaymentMethod +import com.sangdol.roomescape.payment.business.domain.PaymentStatus +import com.sangdol.roomescape.payment.business.domain.PaymentType import com.sangdol.roomescape.payment.exception.PaymentErrorCode import com.sangdol.roomescape.payment.exception.PaymentException -import com.sangdol.roomescape.payment.infrastructure.common.* import io.kotest.assertions.assertSoftly import io.kotest.core.spec.style.FunSpec import io.kotest.matchers.shouldBe 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 c9c54396..84c6cbec 100644 --- a/service/src/test/kotlin/com/sangdol/roomescape/payment/TosspayClientTest.kt +++ b/service/src/test/kotlin/com/sangdol/roomescape/payment/TosspayClientTest.kt @@ -2,12 +2,10 @@ 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 -import com.sangdol.roomescape.payment.infrastructure.client.PaymentClientConfirmResponse +import com.sangdol.roomescape.payment.dto.PaymentGatewayCancelResponse +import com.sangdol.roomescape.payment.dto.PaymentGatewayResponse import com.sangdol.roomescape.payment.infrastructure.client.TosspayClient -import com.sangdol.roomescape.payment.infrastructure.common.PaymentStatus +import com.sangdol.roomescape.payment.business.domain.PaymentStatus import io.kotest.assertions.assertSoftly import io.kotest.assertions.throwables.shouldThrow import io.kotest.core.spec.style.FunSpec @@ -116,7 +114,7 @@ class TosspayClientTest( .createResponse(it) } - val cancelResponse: PaymentClientCancelResponse = client.cancel( + val cancelResponse: PaymentGatewayCancelResponse = client.cancel( SampleTosspayConstant.PAYMENT_KEY, SampleTosspayConstant.AMOUNT, SampleTosspayConstant.CANCEL_REASON @@ -162,13 +160,13 @@ class TosspayClientTest( } fun runConfirmTest() { - val paymentResponse: PaymentClientConfirmResponse = client.confirm( + val paymentGatewayResponse: PaymentGatewayResponse = client.confirm( SampleTosspayConstant.PAYMENT_KEY, SampleTosspayConstant.ORDER_ID, SampleTosspayConstant.AMOUNT ) - assertSoftly(paymentResponse) { + assertSoftly(paymentGatewayResponse) { this.paymentKey shouldBe SampleTosspayConstant.PAYMENT_KEY this.totalAmount shouldBe SampleTosspayConstant.AMOUNT } diff --git a/service/src/test/kotlin/com/sangdol/roomescape/reservation/ReservationApiTest.kt b/service/src/test/kotlin/com/sangdol/roomescape/reservation/ReservationApiTest.kt index 4f8fc9d7..d29cc9d4 100644 --- a/service/src/test/kotlin/com/sangdol/roomescape/reservation/ReservationApiTest.kt +++ b/service/src/test/kotlin/com/sangdol/roomescape/reservation/ReservationApiTest.kt @@ -5,9 +5,9 @@ import com.sangdol.common.types.web.HttpStatus import com.sangdol.common.utils.KoreaDate import com.sangdol.common.utils.KoreaTime import com.sangdol.roomescape.auth.exception.AuthErrorCode -import com.sangdol.roomescape.payment.infrastructure.common.BankCode -import com.sangdol.roomescape.payment.infrastructure.common.CardIssuerCode -import com.sangdol.roomescape.payment.infrastructure.common.EasyPayCompanyCode +import com.sangdol.roomescape.payment.business.domain.BankCode +import com.sangdol.roomescape.payment.business.domain.CardIssuerCode +import com.sangdol.roomescape.payment.business.domain.EasyPayCompanyCode import com.sangdol.roomescape.payment.infrastructure.persistence.PaymentDetailRepository import com.sangdol.roomescape.reservation.exception.ReservationErrorCode import com.sangdol.roomescape.reservation.infrastructure.persistence.CanceledReservationRepository diff --git a/service/src/test/kotlin/com/sangdol/roomescape/supports/DummyInitializer.kt b/service/src/test/kotlin/com/sangdol/roomescape/supports/DummyInitializer.kt index 3d4e17b4..e40bb5a8 100644 --- a/service/src/test/kotlin/com/sangdol/roomescape/supports/DummyInitializer.kt +++ b/service/src/test/kotlin/com/sangdol/roomescape/supports/DummyInitializer.kt @@ -1,32 +1,27 @@ package com.sangdol.roomescape.supports import com.sangdol.roomescape.payment.business.PaymentWriter -import com.sangdol.roomescape.payment.infrastructure.client.CardDetail -import com.sangdol.roomescape.payment.infrastructure.client.EasyPayDetail -import com.sangdol.roomescape.payment.infrastructure.client.TransferDetail -import com.sangdol.roomescape.payment.infrastructure.common.PaymentMethod +import com.sangdol.roomescape.payment.business.domain.PaymentMethod +import com.sangdol.roomescape.payment.dto.* import com.sangdol.roomescape.payment.infrastructure.persistence.CanceledPaymentEntity import com.sangdol.roomescape.payment.infrastructure.persistence.PaymentEntity import com.sangdol.roomescape.payment.infrastructure.persistence.PaymentRepository -import com.sangdol.roomescape.payment.web.PaymentConfirmRequest -import com.sangdol.roomescape.payment.web.PaymentWithDetailResponse -import com.sangdol.roomescape.payment.web.toDetailResponse -import com.sangdol.roomescape.payment.web.toPaymentDetailResponse +import com.sangdol.roomescape.payment.mapper.toResponse +import com.sangdol.roomescape.reservation.dto.PendingReservationCreateRequest import com.sangdol.roomescape.reservation.infrastructure.persistence.ReservationEntity import com.sangdol.roomescape.reservation.infrastructure.persistence.ReservationRepository import com.sangdol.roomescape.reservation.infrastructure.persistence.ReservationStatus -import com.sangdol.roomescape.reservation.dto.PendingReservationCreateRequest import com.sangdol.roomescape.reservation.mapper.toEntity +import com.sangdol.roomescape.schedule.dto.ScheduleCreateRequest import com.sangdol.roomescape.schedule.infrastructure.persistence.ScheduleEntity import com.sangdol.roomescape.schedule.infrastructure.persistence.ScheduleRepository import com.sangdol.roomescape.schedule.infrastructure.persistence.ScheduleStatus -import com.sangdol.roomescape.schedule.dto.ScheduleCreateRequest import com.sangdol.roomescape.store.infrastructure.persistence.StoreEntity import com.sangdol.roomescape.store.infrastructure.persistence.StoreRepository import com.sangdol.roomescape.store.infrastructure.persistence.StoreStatus +import com.sangdol.roomescape.theme.dto.ThemeCreateRequest import com.sangdol.roomescape.theme.infrastructure.persistence.ThemeEntity import com.sangdol.roomescape.theme.infrastructure.persistence.ThemeRepository -import com.sangdol.roomescape.theme.dto.ThemeCreateRequest import com.sangdol.roomescape.theme.mapper.toEntity import com.sangdol.roomescape.user.infrastructure.persistence.UserEntity import org.springframework.data.repository.findByIdOrNull @@ -164,10 +159,10 @@ class DummyInitializer( fun createPayment( reservationId: Long, request: PaymentConfirmRequest = PaymentFixture.confirmRequest, - cardDetail: CardDetail? = null, - easyPayDetail: EasyPayDetail? = null, - transferDetail: TransferDetail? = null, - ): PaymentWithDetailResponse { + cardDetail: CardDetailResponse? = null, + easyPayDetail: EasyPayDetailResponse? = null, + transferDetail: TransferDetailResponse? = null, + ): PaymentResponse { val method = if (easyPayDetail != null) { PaymentMethod.EASY_PAY } else if (cardDetail != null) { @@ -190,12 +185,12 @@ class DummyInitializer( val payment = paymentWriter.createPayment( reservationId = reservationId, - paymentClientConfirmResponse = clientConfirmResponse + paymentGatewayResponse = clientConfirmResponse ) val detail = paymentWriter.createDetail(clientConfirmResponse, payment.id) - return payment.toDetailResponse(detail = detail.toPaymentDetailResponse(), cancel = null) + return payment.toResponse(detail = detail.toResponse(), cancel = null) } fun cancelPayment( diff --git a/service/src/test/kotlin/com/sangdol/roomescape/supports/Fixtures.kt b/service/src/test/kotlin/com/sangdol/roomescape/supports/Fixtures.kt index b7fe117e..821517f8 100644 --- a/service/src/test/kotlin/com/sangdol/roomescape/supports/Fixtures.kt +++ b/service/src/test/kotlin/com/sangdol/roomescape/supports/Fixtures.kt @@ -6,10 +6,22 @@ import com.sangdol.common.utils.KoreaDateTime import com.sangdol.roomescape.admin.infrastructure.persistence.AdminEntity import com.sangdol.roomescape.admin.infrastructure.persistence.AdminPermissionLevel import com.sangdol.roomescape.admin.infrastructure.persistence.AdminType -import com.sangdol.roomescape.payment.infrastructure.client.* -import com.sangdol.roomescape.payment.infrastructure.common.* -import com.sangdol.roomescape.payment.web.PaymentCancelRequest -import com.sangdol.roomescape.payment.web.PaymentConfirmRequest +import com.sangdol.roomescape.payment.business.domain.BankCode +import com.sangdol.roomescape.payment.business.domain.CardIssuerCode +import com.sangdol.roomescape.payment.business.domain.CardOwnerType +import com.sangdol.roomescape.payment.business.domain.CardType +import com.sangdol.roomescape.payment.business.domain.EasyPayCompanyCode +import com.sangdol.roomescape.payment.business.domain.PaymentMethod +import com.sangdol.roomescape.payment.business.domain.PaymentStatus +import com.sangdol.roomescape.payment.business.domain.PaymentType +import com.sangdol.roomescape.payment.dto.CancelDetail +import com.sangdol.roomescape.payment.dto.CardDetailResponse +import com.sangdol.roomescape.payment.dto.EasyPayDetailResponse +import com.sangdol.roomescape.payment.dto.PaymentGatewayCancelResponse +import com.sangdol.roomescape.payment.dto.PaymentGatewayResponse +import com.sangdol.roomescape.payment.dto.TransferDetailResponse +import com.sangdol.roomescape.payment.dto.PaymentCancelRequest +import com.sangdol.roomescape.payment.dto.PaymentConfirmRequest import com.sangdol.roomescape.reservation.dto.PendingReservationCreateRequest import com.sangdol.roomescape.schedule.infrastructure.persistence.ScheduleEntity import com.sangdol.roomescape.schedule.infrastructure.persistence.ScheduleEntityFactory @@ -254,7 +266,7 @@ object PaymentFixture { cardType: CardType = CardType.entries.random(), ownerType: CardOwnerType = CardOwnerType.entries.random(), installmentPlanMonths: Int = 0, - ): CardDetail = CardDetail( + ): CardDetailResponse = CardDetailResponse( issuerCode = issuerCode, number = "${(400000..500000).random()}*********", amount = amount, @@ -269,12 +281,12 @@ object PaymentFixture { amount: Int, provider: EasyPayCompanyCode = EasyPayCompanyCode.entries.random(), discountAmount: Int = 0 - ): EasyPayDetail = EasyPayDetail(provider, amount, discountAmount) + ): EasyPayDetailResponse = EasyPayDetailResponse(provider, amount, discountAmount) fun transferDetail( bankCode: BankCode = BankCode.entries.random(), settlementStatus: String = "COMPLETED" - ): TransferDetail = TransferDetail( + ): TransferDetailResponse = TransferDetailResponse( bankCode = bankCode, settlementStatus = settlementStatus ) @@ -283,11 +295,11 @@ object PaymentFixture { paymentKey: String, amount: Int, method: PaymentMethod, - cardDetail: CardDetail?, - easyPayDetail: EasyPayDetail?, - transferDetail: TransferDetail?, + cardDetail: CardDetailResponse?, + easyPayDetail: EasyPayDetailResponse?, + transferDetail: TransferDetailResponse?, orderId: String = randomString(25), - ) = PaymentClientConfirmResponse( + ) = PaymentGatewayResponse( paymentKey = paymentKey, status = PaymentStatus.DONE, orderId = orderId, @@ -309,7 +321,7 @@ object PaymentFixture { transferDiscountAmount: Int = 0, easypayDiscountAmount: Int = 0, cancelReason: String = "cancelReason" - ) = PaymentClientCancelResponse( + ) = PaymentGatewayCancelResponse( status = PaymentStatus.CANCELED, cancels = CancelDetail( cancelAmount = amount,