feat: 결제 정보를 저장하는 PaymentEventListener 및 테스트 추가

This commit is contained in:
이상진 2025-10-16 13:15:52 +09:00
parent d0ee55be95
commit e0e7902654
2 changed files with 101 additions and 0 deletions

View File

@ -0,0 +1,48 @@
package com.sangdol.roomescape.payment.business.event
import com.sangdol.common.persistence.IDGenerator
import com.sangdol.roomescape.payment.infrastructure.persistence.PaymentDetailEntity
import com.sangdol.roomescape.payment.infrastructure.persistence.PaymentDetailRepository
import com.sangdol.roomescape.payment.infrastructure.persistence.PaymentEntity
import com.sangdol.roomescape.payment.infrastructure.persistence.PaymentRepository
import com.sangdol.roomescape.payment.mapper.toDetailEntity
import com.sangdol.roomescape.payment.mapper.toEntity
import io.github.oshai.kotlinlogging.KLogger
import io.github.oshai.kotlinlogging.KotlinLogging
import org.springframework.context.event.EventListener
import org.springframework.scheduling.annotation.Async
import org.springframework.stereotype.Component
import org.springframework.transaction.annotation.Transactional
private val log: KLogger = KotlinLogging.logger {}
@Component
class PaymentEventListener(
private val idGenerator: IDGenerator,
private val paymentRepository: PaymentRepository,
private val paymentDetailRepository: PaymentDetailRepository
) {
@Async
@EventListener
@Transactional
fun handlePaymentEvent(event: PaymentEvent) {
val reservationId = event.reservationId
log.info { "[handlePaymentEvent] 결제 정보 저장 이벤트 수신: reservationId=${reservationId}, paymentKey=${event.paymentKey}" }
val paymentId = idGenerator.create()
val paymentEntity: PaymentEntity = event.toEntity(paymentId)
paymentRepository.save(paymentEntity).also {
log.info { "[handlePaymentEvent] 결제 정보 저장 완료: paymentId=${paymentId}" }
}
val paymentDetailId = idGenerator.create()
val paymentDetailEntity: PaymentDetailEntity = event.toDetailEntity(id = paymentDetailId, paymentId = paymentId)
paymentDetailRepository.save(paymentDetailEntity).also {
log.info { "[handlePaymentEvent] 결제 상세 저장 완료: paymentDetailId=${paymentDetailId}" }
}
log.info { "[handlePaymentEvent] 결제 정보 저장 이벤트 처리 완료" }
}
}

View File

@ -0,0 +1,53 @@
package com.sangdol.roomescape.payment.business.event
import com.sangdol.roomescape.payment.business.domain.PaymentMethod
import com.sangdol.roomescape.payment.infrastructure.persistence.PaymentCardDetailEntity
import com.sangdol.roomescape.payment.infrastructure.persistence.PaymentDetailRepository
import com.sangdol.roomescape.payment.infrastructure.persistence.PaymentRepository
import com.sangdol.roomescape.payment.mapper.toEvent
import com.sangdol.roomescape.supports.FunSpecSpringbootTest
import com.sangdol.roomescape.supports.PaymentFixture
import com.sangdol.roomescape.supports.initialize
import io.kotest.assertions.assertSoftly
import io.kotest.matchers.nulls.shouldNotBeNull
import io.kotest.matchers.shouldBe
class PaymentEventListenerTest(
private val paymentEventListener: PaymentEventListener,
private val paymentRepository: PaymentRepository,
private val paymentDetailRepository: PaymentDetailRepository,
) : FunSpecSpringbootTest() {
init {
test("결제 완료 이벤트를 처리한다.") {
val reservationId = initialize("FK 제약조건 해소를 위한 예약 생성") {
val user = testAuthUtil.defaultUser()
dummyInitializer.createPendingReservation(user)
}.id
val paymentExternalAPIResponse = PaymentFixture.confirmResponse(
paymentKey = "paymentKey",
amount = 100_000,
method = PaymentMethod.CARD
)
paymentEventListener.handlePaymentEvent(paymentExternalAPIResponse.toEvent(reservationId)).also {
Thread.sleep(100)
}
val payment = paymentRepository.findByReservationId(reservationId)
assertSoftly(payment!!) {
this.paymentKey shouldBe paymentExternalAPIResponse.paymentKey
this.totalAmount shouldBe paymentExternalAPIResponse.totalAmount
this.method shouldBe paymentExternalAPIResponse.method
}
val paymentDetail = paymentDetailRepository.findByPaymentId(payment.id)
assertSoftly(paymentDetail) {
this.shouldNotBeNull()
this::class shouldBe PaymentCardDetailEntity::class
(this as PaymentCardDetailEntity).amount shouldBe paymentExternalAPIResponse.totalAmount
}
}
}
}