generated from pricelees/issue-pr-template
refactor: payment 내 DTO / mapper 패키지 분리 및 클래스명 수정
This commit is contained in:
parent
1caa9d3f3d
commit
1902fc6f7c
@ -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()
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@ -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}" }
|
||||
|
||||
|
||||
@ -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
|
||||
@ -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,
|
||||
@ -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<CommonApiResponse<PaymentClientConfirmResponse>>
|
||||
): ResponseEntity<CommonApiResponse<PaymentGatewayResponse>>
|
||||
|
||||
@Operation(summary = "결제 취소")
|
||||
@ApiResponses(ApiResponse(responseCode = "200", useReturnTypeSchema = true))
|
||||
|
||||
@ -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
|
||||
)
|
||||
@ -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,
|
||||
)
|
||||
@ -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()
|
||||
)
|
||||
@ -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<CancelDetail>() {
|
||||
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()
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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<CancelDetail>() {
|
||||
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()
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
)
|
||||
@ -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
|
||||
)
|
||||
}
|
||||
@ -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<CommonApiResponse<PaymentClientConfirmResponse>> {
|
||||
): ResponseEntity<CommonApiResponse<PaymentGatewayResponse>> {
|
||||
val response = paymentService.requestConfirm(request)
|
||||
|
||||
return ResponseEntity.ok(CommonApiResponse(response))
|
||||
|
||||
@ -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
|
||||
)
|
||||
}
|
||||
@ -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,
|
||||
|
||||
@ -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(
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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(
|
||||
|
||||
@ -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,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user