generated from pricelees/issue-pr-template
[#56] 예약 & 결제 프로세스 및 패키지 구조 재정의 #57
@ -1,15 +1,19 @@
|
|||||||
package com.sangdol.roomescape.payment.business
|
package com.sangdol.roomescape.payment.business
|
||||||
|
|
||||||
import com.sangdol.common.persistence.TransactionExecutionUtil
|
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.ExternalPaymentException
|
||||||
import com.sangdol.roomescape.payment.exception.PaymentErrorCode
|
import com.sangdol.roomescape.payment.exception.PaymentErrorCode
|
||||||
import com.sangdol.roomescape.payment.exception.PaymentException
|
import com.sangdol.roomescape.payment.exception.PaymentException
|
||||||
import com.sangdol.roomescape.payment.infrastructure.client.PaymentClientCancelResponse
|
import com.sangdol.roomescape.payment.dto.PaymentGatewayCancelResponse
|
||||||
import com.sangdol.roomescape.payment.infrastructure.client.PaymentClientConfirmResponse
|
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.client.TosspayClient
|
||||||
import com.sangdol.roomescape.payment.infrastructure.persistence.*
|
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.KLogger
|
||||||
import io.github.oshai.kotlinlogging.KotlinLogging
|
import io.github.oshai.kotlinlogging.KotlinLogging
|
||||||
import org.springframework.stereotype.Service
|
import org.springframework.stereotype.Service
|
||||||
@ -26,7 +30,7 @@ class PaymentService(
|
|||||||
private val paymentWriter: PaymentWriter,
|
private val paymentWriter: PaymentWriter,
|
||||||
private val transactionExecutionUtil: TransactionExecutionUtil,
|
private val transactionExecutionUtil: TransactionExecutionUtil,
|
||||||
) {
|
) {
|
||||||
fun requestConfirm(request: PaymentConfirmRequest): PaymentClientConfirmResponse {
|
fun requestConfirm(request: PaymentConfirmRequest): PaymentGatewayResponse {
|
||||||
try {
|
try {
|
||||||
return paymentClient.confirm(request.paymentKey, request.orderId, request.amount)
|
return paymentClient.confirm(request.paymentKey, request.orderId, request.amount)
|
||||||
} catch (e: ExternalPaymentException) {
|
} catch (e: ExternalPaymentException) {
|
||||||
@ -36,7 +40,7 @@ class PaymentService(
|
|||||||
PaymentErrorCode.PAYMENT_PROVIDER_ERROR
|
PaymentErrorCode.PAYMENT_PROVIDER_ERROR
|
||||||
}
|
}
|
||||||
|
|
||||||
val message = if (PaymentClientError.contains(e.errorCode)) {
|
val message = if (UserFacingPaymentErrorCode.contains(e.errorCode)) {
|
||||||
"${errorCode.message}(${e.message})"
|
"${errorCode.message}(${e.message})"
|
||||||
} else {
|
} else {
|
||||||
errorCode.message
|
errorCode.message
|
||||||
@ -48,13 +52,13 @@ class PaymentService(
|
|||||||
|
|
||||||
fun savePayment(
|
fun savePayment(
|
||||||
reservationId: Long,
|
reservationId: Long,
|
||||||
paymentConfirmResponse: PaymentClientConfirmResponse
|
paymentGatewayResponse: PaymentGatewayResponse
|
||||||
): PaymentCreateResponse {
|
): PaymentCreateResponse {
|
||||||
val payment: PaymentEntity = paymentWriter.createPayment(
|
val payment: PaymentEntity = paymentWriter.createPayment(
|
||||||
reservationId = reservationId,
|
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)
|
return PaymentCreateResponse(paymentId = payment.id, detailId = detail.id)
|
||||||
}
|
}
|
||||||
@ -62,7 +66,7 @@ class PaymentService(
|
|||||||
fun cancel(userId: Long, request: PaymentCancelRequest) {
|
fun cancel(userId: Long, request: PaymentCancelRequest) {
|
||||||
val payment: PaymentEntity = findByReservationIdOrThrow(request.reservationId)
|
val payment: PaymentEntity = findByReservationIdOrThrow(request.reservationId)
|
||||||
|
|
||||||
val clientCancelResponse: PaymentClientCancelResponse = paymentClient.cancel(
|
val clientCancelResponse: PaymentGatewayCancelResponse = paymentClient.cancel(
|
||||||
paymentKey = payment.paymentKey,
|
paymentKey = payment.paymentKey,
|
||||||
amount = payment.totalAmount,
|
amount = payment.totalAmount,
|
||||||
cancelReason = request.cancelReason
|
cancelReason = request.cancelReason
|
||||||
@ -81,16 +85,16 @@ class PaymentService(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Transactional(readOnly = true)
|
@Transactional(readOnly = true)
|
||||||
fun findDetailByReservationId(reservationId: Long): PaymentWithDetailResponse? {
|
fun findDetailByReservationId(reservationId: Long): PaymentResponse? {
|
||||||
log.info { "[findDetailByReservationId] 예약 결제 정보 조회 시작: reservationId=$reservationId" }
|
log.info { "[findDetailByReservationId] 예약 결제 정보 조회 시작: reservationId=$reservationId" }
|
||||||
|
|
||||||
val payment: PaymentEntity? = findByReservationIdOrNull(reservationId)
|
val payment: PaymentEntity? = findByReservationIdOrNull(reservationId)
|
||||||
val paymentDetail: PaymentDetailEntity? = payment?.let { findDetailByPaymentIdOrNull(it.id) }
|
val paymentDetail: PaymentDetailEntity? = payment?.let { findDetailByPaymentIdOrNull(it.id) }
|
||||||
val cancelDetail: CanceledPaymentEntity? = payment?.let { findCancelByPaymentIdOrNull(it.id) }
|
val cancelDetail: CanceledPaymentEntity? = payment?.let { findCancelByPaymentIdOrNull(it.id) }
|
||||||
|
|
||||||
return payment?.toDetailResponse(
|
return payment?.toResponse(
|
||||||
detail = paymentDetail?.toPaymentDetailResponse(),
|
detail = paymentDetail?.toResponse(),
|
||||||
cancel = cancelDetail?.toCancelDetailResponse()
|
cancel = cancelDetail?.toResponse()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,8 +3,13 @@ package com.sangdol.roomescape.payment.business
|
|||||||
import com.sangdol.common.persistence.IDGenerator
|
import com.sangdol.common.persistence.IDGenerator
|
||||||
import com.sangdol.roomescape.payment.exception.PaymentErrorCode
|
import com.sangdol.roomescape.payment.exception.PaymentErrorCode
|
||||||
import com.sangdol.roomescape.payment.exception.PaymentException
|
import com.sangdol.roomescape.payment.exception.PaymentException
|
||||||
import com.sangdol.roomescape.payment.infrastructure.client.*
|
import com.sangdol.roomescape.payment.business.domain.PaymentMethod
|
||||||
import com.sangdol.roomescape.payment.infrastructure.common.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 com.sangdol.roomescape.payment.infrastructure.persistence.*
|
||||||
import io.github.oshai.kotlinlogging.KLogger
|
import io.github.oshai.kotlinlogging.KLogger
|
||||||
import io.github.oshai.kotlinlogging.KotlinLogging
|
import io.github.oshai.kotlinlogging.KotlinLogging
|
||||||
@ -23,31 +28,31 @@ class PaymentWriter(
|
|||||||
|
|
||||||
fun createPayment(
|
fun createPayment(
|
||||||
reservationId: Long,
|
reservationId: Long,
|
||||||
paymentClientConfirmResponse: PaymentClientConfirmResponse
|
paymentGatewayResponse: PaymentGatewayResponse
|
||||||
): PaymentEntity {
|
): 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)
|
paymentRepository.save(it)
|
||||||
log.info { "[PaymentWriterV2.createPayment] 결제 승인 및 결제 정보 저장 완료: reservationId=${reservationId}, payment.id=${it.id}" }
|
log.info { "[PaymentWriterV2.createPayment] 결제 승인 및 결제 정보 저장 완료: reservationId=${reservationId}, payment.id=${it.id}" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createDetail(
|
fun createDetail(
|
||||||
paymentResponse: PaymentClientConfirmResponse,
|
paymentGatewayResponse: PaymentGatewayResponse,
|
||||||
paymentId: Long,
|
paymentId: Long,
|
||||||
): PaymentDetailEntity {
|
): PaymentDetailEntity {
|
||||||
val method: PaymentMethod = paymentResponse.method
|
val method: PaymentMethod = paymentGatewayResponse.method
|
||||||
val id = idGenerator.create()
|
val id = idGenerator.create()
|
||||||
|
|
||||||
if (method == PaymentMethod.TRANSFER) {
|
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) {
|
if (method == PaymentMethod.EASY_PAY && paymentGatewayResponse.card == null) {
|
||||||
return paymentDetailRepository.save(paymentResponse.toEasypayPrepaidDetailEntity(id, paymentId))
|
return paymentDetailRepository.save(paymentGatewayResponse.toEasypayPrepaidDetailEntity(id, paymentId))
|
||||||
}
|
}
|
||||||
if (paymentResponse.card != null) {
|
if (paymentGatewayResponse.card != null) {
|
||||||
return paymentDetailRepository.save(paymentResponse.toCardDetailEntity(id, paymentId))
|
return paymentDetailRepository.save(paymentGatewayResponse.toCardDetailEntity(id, paymentId))
|
||||||
}
|
}
|
||||||
throw PaymentException(PaymentErrorCode.NOT_SUPPORTED_PAYMENT_TYPE)
|
throw PaymentException(PaymentErrorCode.NOT_SUPPORTED_PAYMENT_TYPE)
|
||||||
}
|
}
|
||||||
@ -56,7 +61,7 @@ class PaymentWriter(
|
|||||||
userId: Long,
|
userId: Long,
|
||||||
payment: PaymentEntity,
|
payment: PaymentEntity,
|
||||||
requestedAt: Instant,
|
requestedAt: Instant,
|
||||||
cancelResponse: PaymentClientCancelResponse
|
cancelResponse: PaymentGatewayCancelResponse
|
||||||
): CanceledPaymentEntity {
|
): CanceledPaymentEntity {
|
||||||
log.debug { "[PaymentWriterV2.cancelPayment] 결제 취소 정보 저장 시작: payment.id=${payment.id}" }
|
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.fasterxml.jackson.annotation.JsonCreator
|
||||||
import com.sangdol.roomescape.payment.exception.PaymentErrorCode
|
import com.sangdol.roomescape.payment.exception.PaymentErrorCode
|
||||||
@ -1,6 +1,6 @@
|
|||||||
package com.sangdol.roomescape.payment.business.domain
|
package com.sangdol.roomescape.payment.business.domain
|
||||||
|
|
||||||
enum class PaymentClientError {
|
enum class UserFacingPaymentErrorCode {
|
||||||
ALREADY_PROCESSED_PAYMENT,
|
ALREADY_PROCESSED_PAYMENT,
|
||||||
EXCEED_MAX_CARD_INSTALLMENT_PLAN,
|
EXCEED_MAX_CARD_INSTALLMENT_PLAN,
|
||||||
NOT_ALLOWED_POINT_USE,
|
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.User
|
||||||
import com.sangdol.roomescape.auth.web.support.UserOnly
|
import com.sangdol.roomescape.auth.web.support.UserOnly
|
||||||
import com.sangdol.roomescape.common.types.CurrentUserContext
|
import com.sangdol.roomescape.common.types.CurrentUserContext
|
||||||
import com.sangdol.roomescape.payment.infrastructure.client.PaymentClientConfirmResponse
|
import com.sangdol.roomescape.payment.dto.PaymentGatewayResponse
|
||||||
import com.sangdol.roomescape.payment.web.PaymentCancelRequest
|
import com.sangdol.roomescape.payment.dto.PaymentCancelRequest
|
||||||
import com.sangdol.roomescape.payment.web.PaymentConfirmRequest
|
import com.sangdol.roomescape.payment.dto.PaymentConfirmRequest
|
||||||
import io.swagger.v3.oas.annotations.Operation
|
import io.swagger.v3.oas.annotations.Operation
|
||||||
import io.swagger.v3.oas.annotations.responses.ApiResponse
|
import io.swagger.v3.oas.annotations.responses.ApiResponse
|
||||||
import io.swagger.v3.oas.annotations.responses.ApiResponses
|
import io.swagger.v3.oas.annotations.responses.ApiResponses
|
||||||
@ -21,7 +21,7 @@ interface PaymentAPI {
|
|||||||
@ApiResponses(ApiResponse(responseCode = "200", useReturnTypeSchema = true))
|
@ApiResponses(ApiResponse(responseCode = "200", useReturnTypeSchema = true))
|
||||||
fun confirmPayment(
|
fun confirmPayment(
|
||||||
@Valid @RequestBody request: PaymentConfirmRequest
|
@Valid @RequestBody request: PaymentConfirmRequest
|
||||||
): ResponseEntity<CommonApiResponse<PaymentClientConfirmResponse>>
|
): ResponseEntity<CommonApiResponse<PaymentGatewayResponse>>
|
||||||
|
|
||||||
@Operation(summary = "결제 취소")
|
@Operation(summary = "결제 취소")
|
||||||
@ApiResponses(ApiResponse(responseCode = "200", useReturnTypeSchema = true))
|
@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
|
package com.sangdol.roomescape.payment.infrastructure.client
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper
|
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.ExternalPaymentException
|
||||||
import com.sangdol.roomescape.payment.exception.PaymentErrorCode
|
import com.sangdol.roomescape.payment.exception.PaymentErrorCode
|
||||||
import com.sangdol.roomescape.payment.exception.PaymentException
|
import com.sangdol.roomescape.payment.exception.PaymentException
|
||||||
@ -29,7 +31,7 @@ class TosspayClient(
|
|||||||
paymentKey: String,
|
paymentKey: String,
|
||||||
orderId: String,
|
orderId: String,
|
||||||
amount: Int,
|
amount: Int,
|
||||||
): PaymentClientConfirmResponse {
|
): PaymentGatewayResponse {
|
||||||
val startTime = System.currentTimeMillis()
|
val startTime = System.currentTimeMillis()
|
||||||
log.info { "[TosspayClient.confirm] 결제 승인 요청: paymentKey=$paymentKey, orderId=$orderId, amount=$amount" }
|
log.info { "[TosspayClient.confirm] 결제 승인 요청: paymentKey=$paymentKey, orderId=$orderId, amount=$amount" }
|
||||||
|
|
||||||
@ -43,7 +45,7 @@ class TosspayClient(
|
|||||||
paymentKey: String,
|
paymentKey: String,
|
||||||
amount: Int,
|
amount: Int,
|
||||||
cancelReason: String
|
cancelReason: String
|
||||||
): PaymentClientCancelResponse {
|
): PaymentGatewayCancelResponse {
|
||||||
val startTime = System.currentTimeMillis()
|
val startTime = System.currentTimeMillis()
|
||||||
log.info { "[TosspayClient.cancel] 결제 취소 요청: paymentKey=$paymentKey, amount=$amount, cancelReason=$cancelReason" }
|
log.info { "[TosspayClient.cancel] 결제 취소 요청: paymentKey=$paymentKey, amount=$amount, cancelReason=$cancelReason" }
|
||||||
|
|
||||||
@ -63,7 +65,7 @@ private class ConfirmClient(
|
|||||||
|
|
||||||
private val errorHandler: TosspayErrorHandler = TosspayErrorHandler(objectMapper)
|
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()
|
val response = client.post()
|
||||||
.uri(CONFIRM_URI)
|
.uri(CONFIRM_URI)
|
||||||
.contentType(MediaType.APPLICATION_JSON)
|
.contentType(MediaType.APPLICATION_JSON)
|
||||||
@ -84,7 +86,7 @@ private class ConfirmClient(
|
|||||||
|
|
||||||
log.debug { "[TosspayClient.confirm] 응답 수신: json = $response" }
|
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,
|
paymentKey: String,
|
||||||
amount: Int,
|
amount: Int,
|
||||||
cancelReason: String
|
cancelReason: String
|
||||||
): PaymentClientCancelResponse {
|
): PaymentGatewayCancelResponse {
|
||||||
val response = client.post()
|
val response = client.post()
|
||||||
.uri(CANCEL_URI, paymentKey)
|
.uri(CANCEL_URI, paymentKey)
|
||||||
.body(
|
.body(
|
||||||
@ -120,7 +122,7 @@ private class CancelClient(
|
|||||||
}
|
}
|
||||||
|
|
||||||
log.debug { "[TosspayClient.cancel] 응답 수신: json = $response" }
|
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
|
package com.sangdol.roomescape.payment.infrastructure.persistence
|
||||||
|
|
||||||
import com.sangdol.common.persistence.PersistableBaseEntity
|
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.*
|
import jakarta.persistence.*
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
package com.sangdol.roomescape.payment.infrastructure.persistence
|
package com.sangdol.roomescape.payment.infrastructure.persistence
|
||||||
|
|
||||||
import com.sangdol.common.persistence.PersistableBaseEntity
|
import com.sangdol.common.persistence.PersistableBaseEntity
|
||||||
import com.sangdol.roomescape.payment.infrastructure.common.PaymentMethod
|
import com.sangdol.roomescape.payment.business.domain.PaymentMethod
|
||||||
import com.sangdol.roomescape.payment.infrastructure.common.PaymentStatus
|
import com.sangdol.roomescape.payment.business.domain.PaymentStatus
|
||||||
import com.sangdol.roomescape.payment.infrastructure.common.PaymentType
|
import com.sangdol.roomescape.payment.business.domain.PaymentType
|
||||||
import jakarta.persistence.Entity
|
import jakarta.persistence.Entity
|
||||||
import jakarta.persistence.EnumType
|
import jakarta.persistence.EnumType
|
||||||
import jakarta.persistence.Enumerated
|
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.PaymentErrorCode
|
||||||
import com.sangdol.roomescape.payment.exception.PaymentException
|
import com.sangdol.roomescape.payment.exception.PaymentException
|
||||||
import com.sangdol.roomescape.payment.infrastructure.common.*
|
import com.sangdol.roomescape.payment.infrastructure.persistence.*
|
||||||
import com.sangdol.roomescape.payment.infrastructure.persistence.PaymentBankTransferDetailEntity
|
import java.time.Instant
|
||||||
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
|
|
||||||
|
|
||||||
data class PaymentClientConfirmResponse(
|
fun PaymentGatewayResponse.toEntity(
|
||||||
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(
|
|
||||||
id: Long,
|
id: Long,
|
||||||
reservationId: Long,
|
reservationId: Long,
|
||||||
) = PaymentEntity(
|
) = PaymentEntity(
|
||||||
@ -41,18 +23,7 @@ fun PaymentClientConfirmResponse.toEntity(
|
|||||||
status = this.status,
|
status = this.status,
|
||||||
)
|
)
|
||||||
|
|
||||||
data class CardDetail(
|
fun PaymentGatewayResponse.toCardDetailEntity(id: Long, paymentId: Long): PaymentCardDetailEntity {
|
||||||
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 {
|
|
||||||
val cardDetail = this.card ?: throw PaymentException(PaymentErrorCode.PAYMENT_UNEXPECTED_ERROR)
|
val cardDetail = this.card ?: throw PaymentException(PaymentErrorCode.PAYMENT_UNEXPECTED_ERROR)
|
||||||
|
|
||||||
return PaymentCardDetailEntity(
|
return PaymentCardDetailEntity(
|
||||||
@ -73,13 +44,7 @@ fun PaymentClientConfirmResponse.toCardDetailEntity(id: Long, paymentId: Long):
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
data class EasyPayDetail(
|
fun PaymentGatewayResponse.toEasypayPrepaidDetailEntity(
|
||||||
val provider: EasyPayCompanyCode,
|
|
||||||
val amount: Int,
|
|
||||||
val discountAmount: Int,
|
|
||||||
)
|
|
||||||
|
|
||||||
fun PaymentClientConfirmResponse.toEasypayPrepaidDetailEntity(
|
|
||||||
id: Long,
|
id: Long,
|
||||||
paymentId: Long
|
paymentId: Long
|
||||||
): PaymentEasypayPrepaidDetailEntity {
|
): PaymentEasypayPrepaidDetailEntity {
|
||||||
@ -96,12 +61,7 @@ fun PaymentClientConfirmResponse.toEasypayPrepaidDetailEntity(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
data class TransferDetail(
|
fun PaymentGatewayResponse.toTransferDetailEntity(
|
||||||
val bankCode: BankCode,
|
|
||||||
val settlementStatus: String,
|
|
||||||
)
|
|
||||||
|
|
||||||
fun PaymentClientConfirmResponse.toTransferDetailEntity(
|
|
||||||
id: Long,
|
id: Long,
|
||||||
paymentId: Long
|
paymentId: Long
|
||||||
): PaymentBankTransferDetailEntity {
|
): PaymentBankTransferDetailEntity {
|
||||||
@ -116,3 +76,21 @@ fun PaymentClientConfirmResponse.toTransferDetailEntity(
|
|||||||
settlementStatus = transferDetail.settlementStatus
|
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.common.types.CurrentUserContext
|
||||||
import com.sangdol.roomescape.payment.business.PaymentService
|
import com.sangdol.roomescape.payment.business.PaymentService
|
||||||
import com.sangdol.roomescape.payment.docs.PaymentAPI
|
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 jakarta.validation.Valid
|
||||||
import org.springframework.http.ResponseEntity
|
import org.springframework.http.ResponseEntity
|
||||||
import org.springframework.web.bind.annotation.*
|
import org.springframework.web.bind.annotation.*
|
||||||
@ -19,7 +21,7 @@ class PaymentController(
|
|||||||
@PostMapping("/confirm")
|
@PostMapping("/confirm")
|
||||||
override fun confirmPayment(
|
override fun confirmPayment(
|
||||||
@Valid @RequestBody request: PaymentConfirmRequest
|
@Valid @RequestBody request: PaymentConfirmRequest
|
||||||
): ResponseEntity<CommonApiResponse<PaymentClientConfirmResponse>> {
|
): ResponseEntity<CommonApiResponse<PaymentGatewayResponse>> {
|
||||||
val response = paymentService.requestConfirm(request)
|
val response = paymentService.requestConfirm(request)
|
||||||
|
|
||||||
return ResponseEntity.ok(CommonApiResponse(response))
|
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.common.persistence.IDGenerator
|
||||||
import com.sangdol.roomescape.common.types.CurrentUserContext
|
import com.sangdol.roomescape.common.types.CurrentUserContext
|
||||||
import com.sangdol.roomescape.payment.business.PaymentService
|
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.PendingReservationCreateRequest
|
||||||
import com.sangdol.roomescape.reservation.dto.PendingReservationCreateResponse
|
import com.sangdol.roomescape.reservation.dto.PendingReservationCreateResponse
|
||||||
import com.sangdol.roomescape.reservation.dto.ReservationCancelRequest
|
import com.sangdol.roomescape.reservation.dto.ReservationCancelRequest
|
||||||
@ -132,7 +132,7 @@ class ReservationService(
|
|||||||
|
|
||||||
val reservation: ReservationEntity = findOrThrow(id)
|
val reservation: ReservationEntity = findOrThrow(id)
|
||||||
val user: UserContactResponse = userService.findContactById(reservation.userId)
|
val user: UserContactResponse = userService.findContactById(reservation.userId)
|
||||||
val paymentDetail: PaymentWithDetailResponse? = paymentService.findDetailByReservationId(id)
|
val paymentDetail: PaymentResponse? = paymentService.findDetailByReservationId(id)
|
||||||
|
|
||||||
return reservation.toAdditionalResponse(
|
return reservation.toAdditionalResponse(
|
||||||
user = user,
|
user = user,
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
package com.sangdol.roomescape.reservation.dto
|
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.reservation.infrastructure.persistence.ReservationStatus
|
||||||
import com.sangdol.roomescape.user.dto.UserContactResponse
|
import com.sangdol.roomescape.user.dto.UserContactResponse
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
@ -22,7 +22,7 @@ data class ReservationAdditionalResponse(
|
|||||||
val reserver: ReserverInfo,
|
val reserver: ReserverInfo,
|
||||||
val user: UserContactResponse,
|
val user: UserContactResponse,
|
||||||
val applicationDateTime: Instant,
|
val applicationDateTime: Instant,
|
||||||
val payment: PaymentWithDetailResponse?,
|
val payment: PaymentResponse?,
|
||||||
)
|
)
|
||||||
|
|
||||||
data class ReserverInfo(
|
data class ReserverInfo(
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
package com.sangdol.roomescape.reservation.mapper
|
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.PendingReservationCreateRequest
|
||||||
import com.sangdol.roomescape.reservation.dto.ReservationAdditionalResponse
|
import com.sangdol.roomescape.reservation.dto.ReservationAdditionalResponse
|
||||||
import com.sangdol.roomescape.reservation.dto.ReservationOverviewResponse
|
import com.sangdol.roomescape.reservation.dto.ReservationOverviewResponse
|
||||||
@ -40,7 +40,7 @@ fun ReservationEntity.toOverviewResponse(
|
|||||||
|
|
||||||
fun ReservationEntity.toAdditionalResponse(
|
fun ReservationEntity.toAdditionalResponse(
|
||||||
user: UserContactResponse,
|
user: UserContactResponse,
|
||||||
payment: PaymentWithDetailResponse?,
|
payment: PaymentResponse?,
|
||||||
): ReservationAdditionalResponse {
|
): ReservationAdditionalResponse {
|
||||||
return ReservationAdditionalResponse(
|
return ReservationAdditionalResponse(
|
||||||
id = this.id,
|
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.AdminEntity
|
||||||
import com.sangdol.roomescape.admin.infrastructure.persistence.AdminPermissionLevel
|
import com.sangdol.roomescape.admin.infrastructure.persistence.AdminPermissionLevel
|
||||||
import com.sangdol.roomescape.admin.infrastructure.persistence.AdminType
|
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.reservation.infrastructure.persistence.ReservationStatus
|
||||||
import com.sangdol.roomescape.schedule.infrastructure.persistence.ScheduleStatus
|
import com.sangdol.roomescape.schedule.infrastructure.persistence.ScheduleStatus
|
||||||
import com.sangdol.roomescape.store.infrastructure.persistence.StoreEntity
|
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.client.TransferDetail
|
||||||
//import com.sangdol.roomescape.payment.infrastructure.common.*
|
//import com.sangdol.roomescape.payment.infrastructure.common.*
|
||||||
//import com.sangdol.roomescape.payment.infrastructure.persistence.*
|
//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.payment.web.PaymentCreateResponse
|
||||||
//import com.sangdol.roomescape.supports.*
|
//import com.sangdol.roomescape.supports.*
|
||||||
//import io.kotest.matchers.shouldBe
|
//import io.kotest.matchers.shouldBe
|
||||||
|
|||||||
@ -1,8 +1,15 @@
|
|||||||
package com.sangdol.roomescape.payment
|
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.PaymentErrorCode
|
||||||
import com.sangdol.roomescape.payment.exception.PaymentException
|
import com.sangdol.roomescape.payment.exception.PaymentException
|
||||||
import com.sangdol.roomescape.payment.infrastructure.common.*
|
|
||||||
import io.kotest.assertions.assertSoftly
|
import io.kotest.assertions.assertSoftly
|
||||||
import io.kotest.core.spec.style.FunSpec
|
import io.kotest.core.spec.style.FunSpec
|
||||||
import io.kotest.matchers.shouldBe
|
import io.kotest.matchers.shouldBe
|
||||||
|
|||||||
@ -2,12 +2,10 @@ package com.sangdol.roomescape.payment
|
|||||||
|
|
||||||
import com.ninjasquad.springmockk.MockkBean
|
import com.ninjasquad.springmockk.MockkBean
|
||||||
import com.sangdol.roomescape.payment.exception.ExternalPaymentException
|
import com.sangdol.roomescape.payment.exception.ExternalPaymentException
|
||||||
import com.sangdol.roomescape.payment.exception.PaymentErrorCode
|
import com.sangdol.roomescape.payment.dto.PaymentGatewayCancelResponse
|
||||||
import com.sangdol.roomescape.payment.exception.PaymentException
|
import com.sangdol.roomescape.payment.dto.PaymentGatewayResponse
|
||||||
import com.sangdol.roomescape.payment.infrastructure.client.PaymentClientCancelResponse
|
|
||||||
import com.sangdol.roomescape.payment.infrastructure.client.PaymentClientConfirmResponse
|
|
||||||
import com.sangdol.roomescape.payment.infrastructure.client.TosspayClient
|
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.assertSoftly
|
||||||
import io.kotest.assertions.throwables.shouldThrow
|
import io.kotest.assertions.throwables.shouldThrow
|
||||||
import io.kotest.core.spec.style.FunSpec
|
import io.kotest.core.spec.style.FunSpec
|
||||||
@ -116,7 +114,7 @@ class TosspayClientTest(
|
|||||||
.createResponse(it)
|
.createResponse(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
val cancelResponse: PaymentClientCancelResponse = client.cancel(
|
val cancelResponse: PaymentGatewayCancelResponse = client.cancel(
|
||||||
SampleTosspayConstant.PAYMENT_KEY,
|
SampleTosspayConstant.PAYMENT_KEY,
|
||||||
SampleTosspayConstant.AMOUNT,
|
SampleTosspayConstant.AMOUNT,
|
||||||
SampleTosspayConstant.CANCEL_REASON
|
SampleTosspayConstant.CANCEL_REASON
|
||||||
@ -162,13 +160,13 @@ class TosspayClientTest(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun runConfirmTest() {
|
fun runConfirmTest() {
|
||||||
val paymentResponse: PaymentClientConfirmResponse = client.confirm(
|
val paymentGatewayResponse: PaymentGatewayResponse = client.confirm(
|
||||||
SampleTosspayConstant.PAYMENT_KEY,
|
SampleTosspayConstant.PAYMENT_KEY,
|
||||||
SampleTosspayConstant.ORDER_ID,
|
SampleTosspayConstant.ORDER_ID,
|
||||||
SampleTosspayConstant.AMOUNT
|
SampleTosspayConstant.AMOUNT
|
||||||
)
|
)
|
||||||
|
|
||||||
assertSoftly(paymentResponse) {
|
assertSoftly(paymentGatewayResponse) {
|
||||||
this.paymentKey shouldBe SampleTosspayConstant.PAYMENT_KEY
|
this.paymentKey shouldBe SampleTosspayConstant.PAYMENT_KEY
|
||||||
this.totalAmount shouldBe SampleTosspayConstant.AMOUNT
|
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.KoreaDate
|
||||||
import com.sangdol.common.utils.KoreaTime
|
import com.sangdol.common.utils.KoreaTime
|
||||||
import com.sangdol.roomescape.auth.exception.AuthErrorCode
|
import com.sangdol.roomescape.auth.exception.AuthErrorCode
|
||||||
import com.sangdol.roomescape.payment.infrastructure.common.BankCode
|
import com.sangdol.roomescape.payment.business.domain.BankCode
|
||||||
import com.sangdol.roomescape.payment.infrastructure.common.CardIssuerCode
|
import com.sangdol.roomescape.payment.business.domain.CardIssuerCode
|
||||||
import com.sangdol.roomescape.payment.infrastructure.common.EasyPayCompanyCode
|
import com.sangdol.roomescape.payment.business.domain.EasyPayCompanyCode
|
||||||
import com.sangdol.roomescape.payment.infrastructure.persistence.PaymentDetailRepository
|
import com.sangdol.roomescape.payment.infrastructure.persistence.PaymentDetailRepository
|
||||||
import com.sangdol.roomescape.reservation.exception.ReservationErrorCode
|
import com.sangdol.roomescape.reservation.exception.ReservationErrorCode
|
||||||
import com.sangdol.roomescape.reservation.infrastructure.persistence.CanceledReservationRepository
|
import com.sangdol.roomescape.reservation.infrastructure.persistence.CanceledReservationRepository
|
||||||
|
|||||||
@ -1,32 +1,27 @@
|
|||||||
package com.sangdol.roomescape.supports
|
package com.sangdol.roomescape.supports
|
||||||
|
|
||||||
import com.sangdol.roomescape.payment.business.PaymentWriter
|
import com.sangdol.roomescape.payment.business.PaymentWriter
|
||||||
import com.sangdol.roomescape.payment.infrastructure.client.CardDetail
|
import com.sangdol.roomescape.payment.business.domain.PaymentMethod
|
||||||
import com.sangdol.roomescape.payment.infrastructure.client.EasyPayDetail
|
import com.sangdol.roomescape.payment.dto.*
|
||||||
import com.sangdol.roomescape.payment.infrastructure.client.TransferDetail
|
|
||||||
import com.sangdol.roomescape.payment.infrastructure.common.PaymentMethod
|
|
||||||
import com.sangdol.roomescape.payment.infrastructure.persistence.CanceledPaymentEntity
|
import com.sangdol.roomescape.payment.infrastructure.persistence.CanceledPaymentEntity
|
||||||
import com.sangdol.roomescape.payment.infrastructure.persistence.PaymentEntity
|
import com.sangdol.roomescape.payment.infrastructure.persistence.PaymentEntity
|
||||||
import com.sangdol.roomescape.payment.infrastructure.persistence.PaymentRepository
|
import com.sangdol.roomescape.payment.infrastructure.persistence.PaymentRepository
|
||||||
import com.sangdol.roomescape.payment.web.PaymentConfirmRequest
|
import com.sangdol.roomescape.payment.mapper.toResponse
|
||||||
import com.sangdol.roomescape.payment.web.PaymentWithDetailResponse
|
import com.sangdol.roomescape.reservation.dto.PendingReservationCreateRequest
|
||||||
import com.sangdol.roomescape.payment.web.toDetailResponse
|
|
||||||
import com.sangdol.roomescape.payment.web.toPaymentDetailResponse
|
|
||||||
import com.sangdol.roomescape.reservation.infrastructure.persistence.ReservationEntity
|
import com.sangdol.roomescape.reservation.infrastructure.persistence.ReservationEntity
|
||||||
import com.sangdol.roomescape.reservation.infrastructure.persistence.ReservationRepository
|
import com.sangdol.roomescape.reservation.infrastructure.persistence.ReservationRepository
|
||||||
import com.sangdol.roomescape.reservation.infrastructure.persistence.ReservationStatus
|
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.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.ScheduleEntity
|
||||||
import com.sangdol.roomescape.schedule.infrastructure.persistence.ScheduleRepository
|
import com.sangdol.roomescape.schedule.infrastructure.persistence.ScheduleRepository
|
||||||
import com.sangdol.roomescape.schedule.infrastructure.persistence.ScheduleStatus
|
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.StoreEntity
|
||||||
import com.sangdol.roomescape.store.infrastructure.persistence.StoreRepository
|
import com.sangdol.roomescape.store.infrastructure.persistence.StoreRepository
|
||||||
import com.sangdol.roomescape.store.infrastructure.persistence.StoreStatus
|
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.ThemeEntity
|
||||||
import com.sangdol.roomescape.theme.infrastructure.persistence.ThemeRepository
|
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.theme.mapper.toEntity
|
||||||
import com.sangdol.roomescape.user.infrastructure.persistence.UserEntity
|
import com.sangdol.roomescape.user.infrastructure.persistence.UserEntity
|
||||||
import org.springframework.data.repository.findByIdOrNull
|
import org.springframework.data.repository.findByIdOrNull
|
||||||
@ -164,10 +159,10 @@ class DummyInitializer(
|
|||||||
fun createPayment(
|
fun createPayment(
|
||||||
reservationId: Long,
|
reservationId: Long,
|
||||||
request: PaymentConfirmRequest = PaymentFixture.confirmRequest,
|
request: PaymentConfirmRequest = PaymentFixture.confirmRequest,
|
||||||
cardDetail: CardDetail? = null,
|
cardDetail: CardDetailResponse? = null,
|
||||||
easyPayDetail: EasyPayDetail? = null,
|
easyPayDetail: EasyPayDetailResponse? = null,
|
||||||
transferDetail: TransferDetail? = null,
|
transferDetail: TransferDetailResponse? = null,
|
||||||
): PaymentWithDetailResponse {
|
): PaymentResponse {
|
||||||
val method = if (easyPayDetail != null) {
|
val method = if (easyPayDetail != null) {
|
||||||
PaymentMethod.EASY_PAY
|
PaymentMethod.EASY_PAY
|
||||||
} else if (cardDetail != null) {
|
} else if (cardDetail != null) {
|
||||||
@ -190,12 +185,12 @@ class DummyInitializer(
|
|||||||
|
|
||||||
val payment = paymentWriter.createPayment(
|
val payment = paymentWriter.createPayment(
|
||||||
reservationId = reservationId,
|
reservationId = reservationId,
|
||||||
paymentClientConfirmResponse = clientConfirmResponse
|
paymentGatewayResponse = clientConfirmResponse
|
||||||
)
|
)
|
||||||
|
|
||||||
val detail = paymentWriter.createDetail(clientConfirmResponse, payment.id)
|
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(
|
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.AdminEntity
|
||||||
import com.sangdol.roomescape.admin.infrastructure.persistence.AdminPermissionLevel
|
import com.sangdol.roomescape.admin.infrastructure.persistence.AdminPermissionLevel
|
||||||
import com.sangdol.roomescape.admin.infrastructure.persistence.AdminType
|
import com.sangdol.roomescape.admin.infrastructure.persistence.AdminType
|
||||||
import com.sangdol.roomescape.payment.infrastructure.client.*
|
import com.sangdol.roomescape.payment.business.domain.BankCode
|
||||||
import com.sangdol.roomescape.payment.infrastructure.common.*
|
import com.sangdol.roomescape.payment.business.domain.CardIssuerCode
|
||||||
import com.sangdol.roomescape.payment.web.PaymentCancelRequest
|
import com.sangdol.roomescape.payment.business.domain.CardOwnerType
|
||||||
import com.sangdol.roomescape.payment.web.PaymentConfirmRequest
|
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.reservation.dto.PendingReservationCreateRequest
|
||||||
import com.sangdol.roomescape.schedule.infrastructure.persistence.ScheduleEntity
|
import com.sangdol.roomescape.schedule.infrastructure.persistence.ScheduleEntity
|
||||||
import com.sangdol.roomescape.schedule.infrastructure.persistence.ScheduleEntityFactory
|
import com.sangdol.roomescape.schedule.infrastructure.persistence.ScheduleEntityFactory
|
||||||
@ -254,7 +266,7 @@ object PaymentFixture {
|
|||||||
cardType: CardType = CardType.entries.random(),
|
cardType: CardType = CardType.entries.random(),
|
||||||
ownerType: CardOwnerType = CardOwnerType.entries.random(),
|
ownerType: CardOwnerType = CardOwnerType.entries.random(),
|
||||||
installmentPlanMonths: Int = 0,
|
installmentPlanMonths: Int = 0,
|
||||||
): CardDetail = CardDetail(
|
): CardDetailResponse = CardDetailResponse(
|
||||||
issuerCode = issuerCode,
|
issuerCode = issuerCode,
|
||||||
number = "${(400000..500000).random()}*********",
|
number = "${(400000..500000).random()}*********",
|
||||||
amount = amount,
|
amount = amount,
|
||||||
@ -269,12 +281,12 @@ object PaymentFixture {
|
|||||||
amount: Int,
|
amount: Int,
|
||||||
provider: EasyPayCompanyCode = EasyPayCompanyCode.entries.random(),
|
provider: EasyPayCompanyCode = EasyPayCompanyCode.entries.random(),
|
||||||
discountAmount: Int = 0
|
discountAmount: Int = 0
|
||||||
): EasyPayDetail = EasyPayDetail(provider, amount, discountAmount)
|
): EasyPayDetailResponse = EasyPayDetailResponse(provider, amount, discountAmount)
|
||||||
|
|
||||||
fun transferDetail(
|
fun transferDetail(
|
||||||
bankCode: BankCode = BankCode.entries.random(),
|
bankCode: BankCode = BankCode.entries.random(),
|
||||||
settlementStatus: String = "COMPLETED"
|
settlementStatus: String = "COMPLETED"
|
||||||
): TransferDetail = TransferDetail(
|
): TransferDetailResponse = TransferDetailResponse(
|
||||||
bankCode = bankCode,
|
bankCode = bankCode,
|
||||||
settlementStatus = settlementStatus
|
settlementStatus = settlementStatus
|
||||||
)
|
)
|
||||||
@ -283,11 +295,11 @@ object PaymentFixture {
|
|||||||
paymentKey: String,
|
paymentKey: String,
|
||||||
amount: Int,
|
amount: Int,
|
||||||
method: PaymentMethod,
|
method: PaymentMethod,
|
||||||
cardDetail: CardDetail?,
|
cardDetail: CardDetailResponse?,
|
||||||
easyPayDetail: EasyPayDetail?,
|
easyPayDetail: EasyPayDetailResponse?,
|
||||||
transferDetail: TransferDetail?,
|
transferDetail: TransferDetailResponse?,
|
||||||
orderId: String = randomString(25),
|
orderId: String = randomString(25),
|
||||||
) = PaymentClientConfirmResponse(
|
) = PaymentGatewayResponse(
|
||||||
paymentKey = paymentKey,
|
paymentKey = paymentKey,
|
||||||
status = PaymentStatus.DONE,
|
status = PaymentStatus.DONE,
|
||||||
orderId = orderId,
|
orderId = orderId,
|
||||||
@ -309,7 +321,7 @@ object PaymentFixture {
|
|||||||
transferDiscountAmount: Int = 0,
|
transferDiscountAmount: Int = 0,
|
||||||
easypayDiscountAmount: Int = 0,
|
easypayDiscountAmount: Int = 0,
|
||||||
cancelReason: String = "cancelReason"
|
cancelReason: String = "cancelReason"
|
||||||
) = PaymentClientCancelResponse(
|
) = PaymentGatewayCancelResponse(
|
||||||
status = PaymentStatus.CANCELED,
|
status = PaymentStatus.CANCELED,
|
||||||
cancels = CancelDetail(
|
cancels = CancelDetail(
|
||||||
cancelAmount = amount,
|
cancelAmount = amount,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user