diff --git a/docker-compose.yml b/docker-compose.yml index d706a07..49b5850 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -15,7 +15,7 @@ services: AWS_ACCESS_KEY_ID: "fakekey" AWS_SECRET_ACCESS_KEY: "fakeaccesskey" AWS_DYNAMODB_ENDPOINT: http://paymentsdb:54000 - AWS_REGION: us-east-1 + AWS_REGION: us-east-2 ADMIN_ACCESS_TOKEN: token MOCK_PAYMENT_PROVIDER: true MP_TOKEN: token @@ -41,7 +41,7 @@ services: environment: AWS_ACCESS_KEY_ID: "fakekey" AWS_SECRET_ACCESS_KEY: "fakeaccesskey" - AWS_REGION: us-east-1 + AWS_REGION: us-east-2 command: ["-D\"java.library.path\"=./DynamoDBLocal_lib", "-jar", "DynamoDBLocal.jar", "-inMemory", "-sharedDb"] healthcheck: test: ["CMD-SHELL", "curl localhost:8000"] @@ -49,5 +49,17 @@ services: timeout: 5s retries: 5 + localstack: + image: localstack/localstack:latest + container_name: localstack-sqs-sns + ports: + - "4566:4566" + - "4510-4559:4510-4559" + environment: + - SERVICES=sqs,sns + - AWS_DEFAULT_REGION=us-east-2 + volumes: + - ./src/main/resources/localstack/localstack-init.sh:/etc/localstack/init/ready.d/init-aws.sh + volumes: payments_db: diff --git a/pom.xml b/pom.xml index 8948aa3..5f2ded1 100644 --- a/pom.xml +++ b/pom.xml @@ -14,6 +14,7 @@ payments Payments API + 3.0.4 17 1.8.22 17 @@ -110,6 +111,14 @@ com.amazonaws aws-java-sdk-sts + + io.awspring.cloud + spring-cloud-aws-starter-sns + + + io.awspring.cloud + spring-cloud-aws-starter-sqs + io.github.boostchicken spring-data-dynamodb @@ -149,6 +158,13 @@ pom import + + io.awspring.cloud + spring-cloud-aws-dependencies + ${awsspring.version} + pom + import + diff --git a/src/main/kotlin/com/fiap/payments/adapter/controller/PaymentController.kt b/src/main/kotlin/com/fiap/payments/adapter/controller/PaymentController.kt index 3f175b6..24b1501 100644 --- a/src/main/kotlin/com/fiap/payments/adapter/controller/PaymentController.kt +++ b/src/main/kotlin/com/fiap/payments/adapter/controller/PaymentController.kt @@ -2,10 +2,8 @@ package com.fiap.payments.adapter.controller import com.fiap.payments.domain.entities.Payment import com.fiap.payments.driver.web.PaymentAPI -import com.fiap.payments.driver.web.request.PaymentHTTPRequest import com.fiap.payments.usecases.ChangePaymentStatusUseCase import com.fiap.payments.usecases.LoadPaymentUseCase -import com.fiap.payments.usecases.ProvidePaymentRequestUseCase import com.fiap.payments.usecases.SyncPaymentUseCase import org.slf4j.LoggerFactory import org.springframework.http.ResponseEntity @@ -15,7 +13,6 @@ import org.springframework.web.bind.annotation.RestController class PaymentController( private val loadPaymentUseCase: LoadPaymentUseCase, private val syncPaymentUseCase: SyncPaymentUseCase, - private val providePaymentRequestUseCase: ProvidePaymentRequestUseCase, private val changePaymentStatusUseCase: ChangePaymentStatusUseCase, ) : PaymentAPI { private val log = LoggerFactory.getLogger(javaClass) @@ -28,9 +25,6 @@ class PaymentController( return ResponseEntity.ok(loadPaymentUseCase.getByPaymentId(paymentId)) } - override fun create(paymentHTTPRequest: PaymentHTTPRequest): ResponseEntity { - return ResponseEntity.ok(providePaymentRequestUseCase.providePaymentRequest(paymentHTTPRequest)) - } override fun fail(paymentId: String): ResponseEntity { return ResponseEntity.ok(changePaymentStatusUseCase.failPayment(paymentId)) diff --git a/src/main/kotlin/com/fiap/payments/adapter/controller/config/ServiceConfig.kt b/src/main/kotlin/com/fiap/payments/adapter/controller/config/ServiceConfig.kt index 56e0491..32763a5 100644 --- a/src/main/kotlin/com/fiap/payments/adapter/controller/config/ServiceConfig.kt +++ b/src/main/kotlin/com/fiap/payments/adapter/controller/config/ServiceConfig.kt @@ -1,13 +1,10 @@ package com.fiap.payments.adapter.controller.config import com.fiap.payments.PaymentsApiApp -import com.fiap.payments.adapter.gateway.OrderGateway import com.fiap.payments.adapter.gateway.PaymentGateway import com.fiap.payments.adapter.gateway.PaymentProviderGateway import com.fiap.payments.usecases.ChangePaymentStatusUseCase -import com.fiap.payments.usecases.ConfirmOrderUseCase import com.fiap.payments.usecases.LoadPaymentUseCase -import com.fiap.payments.usecases.services.OrderService import com.fiap.payments.usecases.services.PaymentService import com.fiap.payments.usecases.services.PaymentSyncService import org.springframework.context.annotation.Bean @@ -21,13 +18,11 @@ class ServiceConfig { @Bean fun createPaymentService( paymentRepository: PaymentGateway, - paymentProvider: PaymentProviderGateway, - confirmOrderUseCase: ConfirmOrderUseCase + paymentProvider: PaymentProviderGateway ): PaymentService { return PaymentService( paymentRepository, paymentProvider, - confirmOrderUseCase ) } @@ -46,10 +41,4 @@ class ServiceConfig { ) } - @Bean - fun paymentOrderService(orderGateway: OrderGateway): OrderService { - return OrderService( - orderGateway - ) - } } diff --git a/src/main/kotlin/com/fiap/payments/adapter/gateway/OrderGateway.kt b/src/main/kotlin/com/fiap/payments/adapter/gateway/OrderGateway.kt deleted file mode 100644 index 10907ad..0000000 --- a/src/main/kotlin/com/fiap/payments/adapter/gateway/OrderGateway.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.fiap.payments.adapter.gateway - -interface OrderGateway { - fun confirmOrder(orderNumber: Long) -} diff --git a/src/main/kotlin/com/fiap/payments/adapter/gateway/PaymentGateway.kt b/src/main/kotlin/com/fiap/payments/adapter/gateway/PaymentGateway.kt index e436c1b..8927932 100644 --- a/src/main/kotlin/com/fiap/payments/adapter/gateway/PaymentGateway.kt +++ b/src/main/kotlin/com/fiap/payments/adapter/gateway/PaymentGateway.kt @@ -8,4 +8,6 @@ interface PaymentGateway { fun findAll(): List fun upsert(payment: Payment): Payment + + fun publishPayment(payment: Payment): Payment } diff --git a/src/main/kotlin/com/fiap/payments/adapter/gateway/PaymentProviderGateway.kt b/src/main/kotlin/com/fiap/payments/adapter/gateway/PaymentProviderGateway.kt index 75595e2..5d18147 100644 --- a/src/main/kotlin/com/fiap/payments/adapter/gateway/PaymentProviderGateway.kt +++ b/src/main/kotlin/com/fiap/payments/adapter/gateway/PaymentProviderGateway.kt @@ -2,10 +2,10 @@ package com.fiap.payments.adapter.gateway import com.fiap.payments.domain.entities.PaymentRequest import com.fiap.payments.domain.valueobjects.PaymentStatus -import com.fiap.payments.driver.web.request.PaymentHTTPRequest +import com.fiap.payments.driver.messaging.event.PaymentRequestEvent interface PaymentProviderGateway { - fun createExternalOrder(paymentId: String, paymentHTTPRequest: PaymentHTTPRequest): PaymentRequest + fun createExternalOrder(paymentId: String, paymentHTTPRequest: PaymentRequestEvent): PaymentRequest fun checkExternalOrderStatus(externalOrderGlobalId: String): PaymentStatus } diff --git a/src/main/kotlin/com/fiap/payments/adapter/gateway/impl/OrderGatewayImpl.kt b/src/main/kotlin/com/fiap/payments/adapter/gateway/impl/OrderGatewayImpl.kt deleted file mode 100644 index bb1b8ef..0000000 --- a/src/main/kotlin/com/fiap/payments/adapter/gateway/impl/OrderGatewayImpl.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.fiap.payments.adapter.gateway.impl - -import com.fiap.payments.adapter.gateway.OrderGateway -import com.fiap.payments.client.OrderApiClient - -class OrderGatewayImpl( - private val orderApiClient: OrderApiClient -) : OrderGateway { - - override fun confirmOrder(orderNumber: Long) { - return orderApiClient.confirm(orderNumber) - } -} diff --git a/src/main/kotlin/com/fiap/payments/adapter/gateway/impl/PaymentGatewayImpl.kt b/src/main/kotlin/com/fiap/payments/adapter/gateway/impl/PaymentGatewayImpl.kt index 0c294fa..36bd8e0 100644 --- a/src/main/kotlin/com/fiap/payments/adapter/gateway/impl/PaymentGatewayImpl.kt +++ b/src/main/kotlin/com/fiap/payments/adapter/gateway/impl/PaymentGatewayImpl.kt @@ -1,6 +1,7 @@ package com.fiap.payments.adapter.gateway.impl import com.fiap.payments.adapter.gateway.PaymentGateway +import com.fiap.payments.adapter.messaging.PaymentSender import com.fiap.payments.domain.entities.Payment import com.fiap.payments.driver.database.persistence.mapper.PaymentMapper import com.fiap.payments.driver.database.persistence.repository.PaymentDynamoRepository @@ -8,6 +9,7 @@ import org.mapstruct.factory.Mappers class PaymentGatewayImpl( private val paymentRepository: PaymentDynamoRepository, + private val paymentSender: PaymentSender ) : PaymentGateway { private val mapper = Mappers.getMapper(PaymentMapper::class.java) @@ -37,6 +39,11 @@ class PaymentGatewayImpl( return persist(paymentUpdated) } + override fun publishPayment(payment: Payment): Payment { + paymentSender.sendPayment(payment) + return payment + } + private fun persist(payment: Payment): Payment = payment .let(mapper::toEntity) diff --git a/src/main/kotlin/com/fiap/payments/adapter/messaging/PaymentSender.kt b/src/main/kotlin/com/fiap/payments/adapter/messaging/PaymentSender.kt new file mode 100644 index 0000000..6bf64a6 --- /dev/null +++ b/src/main/kotlin/com/fiap/payments/adapter/messaging/PaymentSender.kt @@ -0,0 +1,7 @@ +package com.fiap.payments.adapter.messaging + +import com.fiap.payments.domain.entities.Payment + +interface PaymentSender { + fun sendPayment(payment: Payment) +} \ No newline at end of file diff --git a/src/main/kotlin/com/fiap/payments/adapter/messaging/config/MessagingConfig.kt b/src/main/kotlin/com/fiap/payments/adapter/messaging/config/MessagingConfig.kt new file mode 100644 index 0000000..1631848 --- /dev/null +++ b/src/main/kotlin/com/fiap/payments/adapter/messaging/config/MessagingConfig.kt @@ -0,0 +1,20 @@ +package com.fiap.payments.adapter.messaging.config + +import com.fasterxml.jackson.databind.ObjectMapper +import com.fiap.payments.adapter.messaging.PaymentSender +import com.fiap.payments.adapter.messaging.impl.PaymentSenderImpl +import io.awspring.cloud.sns.core.SnsTemplate +import org.springframework.beans.factory.annotation.Value +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration + +@Configuration +class MessagingConfig { + + @Bean + fun createPaymentSender(snsTemplate: SnsTemplate, + @Value("\${topic.response-payment}") topicName: String, + objectMapper: ObjectMapper): PaymentSender { + return PaymentSenderImpl(snsTemplate, topicName, objectMapper) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/fiap/payments/adapter/messaging/impl/PaymentSenderImpl.kt b/src/main/kotlin/com/fiap/payments/adapter/messaging/impl/PaymentSenderImpl.kt new file mode 100644 index 0000000..b9e8821 --- /dev/null +++ b/src/main/kotlin/com/fiap/payments/adapter/messaging/impl/PaymentSenderImpl.kt @@ -0,0 +1,20 @@ +package com.fiap.payments.adapter.messaging.impl + +import com.fasterxml.jackson.databind.ObjectMapper +import com.fiap.payments.adapter.messaging.PaymentSender +import com.fiap.payments.domain.entities.Payment +import io.awspring.cloud.sns.core.SnsTemplate +import org.springframework.messaging.support.GenericMessage + +class PaymentSenderImpl( + private val snsTemplate: SnsTemplate, + private val topicName: String, + private val mapper: ObjectMapper +) : PaymentSender { + + override fun sendPayment(payment: Payment) { + snsTemplate.send( + topicName, GenericMessage(mapper.writeValueAsString(payment)) + ) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/fiap/payments/client/OrderApiClient.kt b/src/main/kotlin/com/fiap/payments/client/OrderApiClient.kt deleted file mode 100644 index e740a9b..0000000 --- a/src/main/kotlin/com/fiap/payments/client/OrderApiClient.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.fiap.payments.client - -import org.springframework.cloud.openfeign.FeignClient -import org.springframework.web.bind.annotation.PathVariable -import org.springframework.web.bind.annotation.RequestMapping -import org.springframework.web.bind.annotation.RequestMethod - -@FeignClient( - name = "orders-client", - url = "\${clients.orders-api.url}" -) -interface OrderApiClient { - - @RequestMapping( - method = [RequestMethod.POST], - value = ["/orders/{orderNumber}/confirm"], - consumes = ["application/json"] - ) - fun confirm(@PathVariable orderNumber: Long) -} diff --git a/src/main/kotlin/com/fiap/payments/driver/database/config/GatewayConfig.kt b/src/main/kotlin/com/fiap/payments/driver/database/config/GatewayConfig.kt index 59cbfef..034a46a 100644 --- a/src/main/kotlin/com/fiap/payments/driver/database/config/GatewayConfig.kt +++ b/src/main/kotlin/com/fiap/payments/driver/database/config/GatewayConfig.kt @@ -3,7 +3,7 @@ package com.fiap.payments.driver.database.config import com.fiap.payments.PaymentsApiApp import com.fiap.payments.adapter.gateway.* import com.fiap.payments.adapter.gateway.impl.* -import com.fiap.payments.client.OrderApiClient +import com.fiap.payments.adapter.messaging.PaymentSender import com.fiap.payments.driver.database.persistence.repository.* import org.springframework.context.annotation.Bean import org.springframework.context.annotation.ComponentScan @@ -14,8 +14,8 @@ import org.springframework.context.annotation.Configuration class GatewayConfig { @Bean("PaymentGateway") - fun createPaymentGateway(paymentJpaRepository: PaymentDynamoRepository): PaymentGateway { - return PaymentGatewayImpl(paymentJpaRepository) + fun createPaymentGateway(paymentJpaRepository: PaymentDynamoRepository, paymentSender: PaymentSender): PaymentGateway { + return PaymentGatewayImpl(paymentJpaRepository, paymentSender) } @Bean("TransactionalGateway") @@ -23,8 +23,4 @@ class GatewayConfig { return TransactionalGatewayImpl() } - @Bean("OrderGateway") - fun createOrderGateway(orderApiClient: OrderApiClient): OrderGateway { - return OrderGatewayImpl(orderApiClient) - } } diff --git a/src/main/kotlin/com/fiap/payments/driver/database/provider/MercadoPagoPaymentProvider.kt b/src/main/kotlin/com/fiap/payments/driver/database/provider/MercadoPagoPaymentProvider.kt index 7282a4f..8411433 100644 --- a/src/main/kotlin/com/fiap/payments/driver/database/provider/MercadoPagoPaymentProvider.kt +++ b/src/main/kotlin/com/fiap/payments/driver/database/provider/MercadoPagoPaymentProvider.kt @@ -6,14 +6,14 @@ import com.fiap.payments.client.MercadoPagoQRCodeOrderRequest import com.fiap.payments.client.MercadoPagoQRCodeOrderRequestItem import com.fiap.payments.domain.entities.PaymentRequest import com.fiap.payments.domain.valueobjects.PaymentStatus -import com.fiap.payments.driver.web.request.PaymentHTTPRequest +import com.fiap.payments.driver.messaging.event.PaymentRequestEvent class MercadoPagoPaymentProvider( private val mercadoPagoClient: MercadoPagoClient, private val webhookBaseUrl: String, ) : PaymentProviderGateway { - override fun createExternalOrder(paymentId: String, paymentHTTPRequest: PaymentHTTPRequest): PaymentRequest { + override fun createExternalOrder(paymentId: String, paymentHTTPRequest: PaymentRequestEvent): PaymentRequest { // source_news=ipn indicates application will receive only Instant Payment Notifications (IPNs), not webhooks val notificationUrl = "${webhookBaseUrl}/payments/notifications/${paymentId}?source_news=ipn" diff --git a/src/main/kotlin/com/fiap/payments/driver/database/provider/PaymentProviderGatewayMock.kt b/src/main/kotlin/com/fiap/payments/driver/database/provider/PaymentProviderGatewayMock.kt index d365764..8d91c79 100644 --- a/src/main/kotlin/com/fiap/payments/driver/database/provider/PaymentProviderGatewayMock.kt +++ b/src/main/kotlin/com/fiap/payments/driver/database/provider/PaymentProviderGatewayMock.kt @@ -3,14 +3,14 @@ package com.fiap.payments.driver.database.provider import com.fiap.payments.adapter.gateway.PaymentProviderGateway import com.fiap.payments.domain.entities.PaymentRequest import com.fiap.payments.domain.valueobjects.PaymentStatus -import com.fiap.payments.driver.web.request.PaymentHTTPRequest +import com.fiap.payments.driver.messaging.event.PaymentRequestEvent import org.slf4j.LoggerFactory import java.util.* class PaymentProviderGatewayMock: PaymentProviderGateway { private val log = LoggerFactory.getLogger(javaClass) - override fun createExternalOrder(paymentId: String, paymentHTTPRequest: PaymentHTTPRequest): PaymentRequest { + override fun createExternalOrder(paymentId: String, paymentHTTPRequest: PaymentRequestEvent): PaymentRequest { log.info("Providing mocked payment request for order [${paymentHTTPRequest.orderInfo.number}]") return PaymentRequest( externalOrderId = UUID.randomUUID().toString(), diff --git a/src/main/kotlin/com/fiap/payments/driver/messaging/consumer/RequestPaymentConsumer.kt b/src/main/kotlin/com/fiap/payments/driver/messaging/consumer/RequestPaymentConsumer.kt new file mode 100644 index 0000000..cfaea70 --- /dev/null +++ b/src/main/kotlin/com/fiap/payments/driver/messaging/consumer/RequestPaymentConsumer.kt @@ -0,0 +1,28 @@ +package com.fiap.payments.driver.messaging.consumer + +import com.fiap.payments.driver.messaging.event.PaymentRequestEvent +import com.fiap.payments.usecases.ProvidePaymentRequestUseCase +import io.awspring.cloud.sqs.annotation.SqsListener +import org.slf4j.LoggerFactory +import org.springframework.context.event.EventListener +import org.springframework.messaging.MessageHeaders +import org.springframework.messaging.handler.annotation.Headers +import org.springframework.scheduling.annotation.EnableAsync +import org.springframework.stereotype.Component + +@Component +@EnableAsync +class RequestPaymentConsumer( + private val providePaymentRequestUseCase: ProvidePaymentRequestUseCase) { + + private val log = LoggerFactory.getLogger(javaClass) + + + @SqsListener("\${sqs.queues.request-payment}") + fun onMessage(message: PaymentRequestEvent, @Headers headers: MessageHeaders) { + log.info(message.toString()) + providePaymentRequestUseCase.providePaymentRequest(message) + } +} + + diff --git a/src/main/kotlin/com/fiap/payments/driver/web/request/PaymentHTTPRequest.kt b/src/main/kotlin/com/fiap/payments/driver/messaging/event/PaymentRequestEvent.kt similarity index 92% rename from src/main/kotlin/com/fiap/payments/driver/web/request/PaymentHTTPRequest.kt rename to src/main/kotlin/com/fiap/payments/driver/messaging/event/PaymentRequestEvent.kt index 2a4a669..003a5a1 100644 --- a/src/main/kotlin/com/fiap/payments/driver/web/request/PaymentHTTPRequest.kt +++ b/src/main/kotlin/com/fiap/payments/driver/messaging/event/PaymentRequestEvent.kt @@ -1,4 +1,4 @@ -package com.fiap.payments.driver.web.request +package com.fiap.payments.driver.messaging.event import com.fasterxml.jackson.annotation.JsonFormat import io.swagger.v3.oas.annotations.media.ArraySchema @@ -6,27 +6,27 @@ import io.swagger.v3.oas.annotations.media.Schema import java.math.BigDecimal import java.time.LocalDateTime -data class PaymentHTTPRequest( +class PaymentRequestEvent( val orderInfo: OrderInfo, ) data class OrderInfo( @Schema(title = "Número de pedido", example = "1", required = true) val number: Long, - + @JsonFormat(shape = JsonFormat.Shape.STRING) @Schema(title = "Valor total", example = "10.00", required = true) val total: BigDecimal, - + @ArraySchema( schema = Schema(implementation = OrderLine::class, required = true), minItems = 1 ) val lines: List, - + @Schema(title = "Data do pedido", example = "2024-05-19T11:00:00", required = true) val orderedAt: LocalDateTime, - + @Schema(title = "Solicitante", example = "John Doe", required = true) val orderedBy: String, ) @@ -34,14 +34,14 @@ data class OrderInfo( data class OrderLine( @Schema(title = "Nome do item de pedido", example = "Big Mac", required = true) val name: String, - + @JsonFormat(shape = JsonFormat.Shape.STRING) @Schema(title = "Valor unitário", example = "10.00", required = true) val unitPrice: BigDecimal, - + @Schema(title = "Quantidade", example = "1", required = true) val quantity: Long, - + @JsonFormat(shape = JsonFormat.Shape.STRING) @Schema(title = "Valor total", example = "10.00", required = true) val total: BigDecimal, diff --git a/src/main/kotlin/com/fiap/payments/driver/web/PaymentAPI.kt b/src/main/kotlin/com/fiap/payments/driver/web/PaymentAPI.kt index f72ab0d..79d92ab 100644 --- a/src/main/kotlin/com/fiap/payments/driver/web/PaymentAPI.kt +++ b/src/main/kotlin/com/fiap/payments/driver/web/PaymentAPI.kt @@ -1,7 +1,6 @@ package com.fiap.payments.driver.web import com.fiap.payments.domain.entities.Payment -import com.fiap.payments.driver.web.request.PaymentHTTPRequest import io.swagger.v3.oas.annotations.Operation import io.swagger.v3.oas.annotations.Parameter import io.swagger.v3.oas.annotations.enums.ParameterIn @@ -13,7 +12,6 @@ import org.springframework.http.ResponseEntity import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.PathVariable import org.springframework.web.bind.annotation.PostMapping -import org.springframework.web.bind.annotation.RequestBody import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RequestParam @@ -67,13 +65,6 @@ interface PaymentAPI { @RequestParam topic: String, ): ResponseEntity - @ApiResponses( - value = [ - ApiResponse(responseCode = "200", description = "Operação bem-sucedida"), - ], - ) - @PostMapping - fun create(@RequestBody paymentHTTPRequest: PaymentHTTPRequest): ResponseEntity @ApiResponses( value = [ diff --git a/src/main/kotlin/com/fiap/payments/usecases/ConfirmOrderUseCase.kt b/src/main/kotlin/com/fiap/payments/usecases/ConfirmOrderUseCase.kt deleted file mode 100644 index a09a88b..0000000 --- a/src/main/kotlin/com/fiap/payments/usecases/ConfirmOrderUseCase.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.fiap.payments.usecases - -interface ConfirmOrderUseCase { - fun confirmOrder(orderNumber: Long) -} diff --git a/src/main/kotlin/com/fiap/payments/usecases/ProvidePaymentRequestUseCase.kt b/src/main/kotlin/com/fiap/payments/usecases/ProvidePaymentRequestUseCase.kt index 00bc984..1577682 100644 --- a/src/main/kotlin/com/fiap/payments/usecases/ProvidePaymentRequestUseCase.kt +++ b/src/main/kotlin/com/fiap/payments/usecases/ProvidePaymentRequestUseCase.kt @@ -1,8 +1,8 @@ package com.fiap.payments.usecases import com.fiap.payments.domain.entities.Payment -import com.fiap.payments.driver.web.request.PaymentHTTPRequest +import com.fiap.payments.driver.messaging.event.PaymentRequestEvent interface ProvidePaymentRequestUseCase { - fun providePaymentRequest(paymentHTTPRequest: PaymentHTTPRequest): Payment + fun providePaymentRequest(paymentRequestEvent: PaymentRequestEvent): Payment } diff --git a/src/main/kotlin/com/fiap/payments/usecases/services/OrderService.kt b/src/main/kotlin/com/fiap/payments/usecases/services/OrderService.kt deleted file mode 100644 index e45e5cd..0000000 --- a/src/main/kotlin/com/fiap/payments/usecases/services/OrderService.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.fiap.payments.usecases.services - -import com.fiap.payments.adapter.gateway.OrderGateway -import com.fiap.payments.usecases.ConfirmOrderUseCase -import org.slf4j.LoggerFactory - -open class OrderService( - private val orderGateway: OrderGateway, -): ConfirmOrderUseCase { - private val log = LoggerFactory.getLogger(javaClass) - - override fun confirmOrder(orderNumber: Long) { - log.info("Requesting order [$orderNumber] to be confirmed") - return orderGateway.confirmOrder(orderNumber) - } -} diff --git a/src/main/kotlin/com/fiap/payments/usecases/services/PaymentService.kt b/src/main/kotlin/com/fiap/payments/usecases/services/PaymentService.kt index 4a52861..9e09605 100644 --- a/src/main/kotlin/com/fiap/payments/usecases/services/PaymentService.kt +++ b/src/main/kotlin/com/fiap/payments/usecases/services/PaymentService.kt @@ -2,13 +2,13 @@ package com.fiap.payments.usecases.services import com.fiap.payments.adapter.gateway.PaymentGateway import com.fiap.payments.adapter.gateway.PaymentProviderGateway +import com.fiap.payments.adapter.messaging.PaymentSender import com.fiap.payments.domain.entities.Payment import com.fiap.payments.domain.errors.ErrorType import com.fiap.payments.domain.errors.PaymentsException import com.fiap.payments.domain.valueobjects.PaymentStatus -import com.fiap.payments.driver.web.request.PaymentHTTPRequest +import com.fiap.payments.driver.messaging.event.PaymentRequestEvent import com.fiap.payments.usecases.ChangePaymentStatusUseCase -import com.fiap.payments.usecases.ConfirmOrderUseCase import com.fiap.payments.usecases.LoadPaymentUseCase import com.fiap.payments.usecases.ProvidePaymentRequestUseCase import org.slf4j.LoggerFactory @@ -17,7 +17,6 @@ import java.time.LocalDateTime class PaymentService( private val paymentGateway: PaymentGateway, private val paymentProvider: PaymentProviderGateway, - private val confirmOrderUseCase: ConfirmOrderUseCase, ) : LoadPaymentUseCase, ProvidePaymentRequestUseCase, ChangePaymentStatusUseCase @@ -37,9 +36,9 @@ class PaymentService( override fun findAll(): List = paymentGateway.findAll() - override fun providePaymentRequest(paymentHTTPRequest: PaymentHTTPRequest): Payment { + override fun providePaymentRequest(paymentRequestEvent: PaymentRequestEvent): Payment { var payment = Payment( - orderNumber = paymentHTTPRequest.orderInfo.number, + orderNumber = paymentRequestEvent.orderInfo.number, createdAt = LocalDateTime.now(), status = PaymentStatus.PENDING, statusChangedAt = LocalDateTime.now(), @@ -47,8 +46,8 @@ class PaymentService( payment = paymentGateway.upsert(payment) log.info("Payment $payment stored for order [${payment.orderNumber}]") - log.info("Requesting payment request for order [${paymentHTTPRequest.orderInfo.number}]") - val paymentRequest = paymentProvider.createExternalOrder(payment.id, paymentHTTPRequest) + log.info("Requesting payment request for order [${paymentRequestEvent.orderInfo.number}]") + val paymentRequest = paymentProvider.createExternalOrder(payment.id, paymentRequestEvent) payment = payment.copy( externalOrderId = paymentRequest.externalOrderId, @@ -57,20 +56,21 @@ class PaymentService( ) paymentGateway.upsert(payment) - return payment + return paymentGateway.publishPayment(payment) } override fun confirmPayment(paymentId: String): Payment { val confirmedPayment = changePaymentStatus(paymentId = paymentId, newStatus = PaymentStatus.CONFIRMED) - confirmOrderUseCase.confirmOrder(confirmedPayment.orderNumber) - return confirmedPayment + return paymentGateway.publishPayment(confirmedPayment) } override fun failPayment(paymentId: String): Payment = changePaymentStatus(paymentId = paymentId, newStatus = PaymentStatus.FAILED) + .let(paymentGateway::publishPayment) override fun expirePayment(paymentId: String): Payment = changePaymentStatus(paymentId = paymentId, newStatus = PaymentStatus.EXPIRED) + .let(paymentGateway::publishPayment) private fun changePaymentStatus(paymentId: String, newStatus: PaymentStatus): Payment = getByPaymentId(paymentId) diff --git a/src/main/resources/application-local.yml b/src/main/resources/application-local.yml index 8902513..009f37f 100644 --- a/src/main/resources/application-local.yml +++ b/src/main/resources/application-local.yml @@ -6,3 +6,24 @@ aws: payment-provider: mock: true + +spring: + cloud: + aws: + endpoint: http://localhost:4566 + credentials: + access-key: localstack + secret-key: localstack + region: + static: ${AWS_REGION} + +sqs: + queues: + request-payment: request-payment_queue + +topic: + response-payment: arn:aws:sns:us-east-2:000000000000:payment-response_topic + + +server: + port: 8081 diff --git a/src/main/resources/db/migration/localSchema/create_schema.sh b/src/main/resources/db/migration/localSchema/create_schema.sh index c73be25..7da9877 100755 --- a/src/main/resources/db/migration/localSchema/create_schema.sh +++ b/src/main/resources/db/migration/localSchema/create_schema.sh @@ -4,7 +4,7 @@ set -e export AWS_ACCESS_KEY_ID=fakekey export AWS_SECRET_ACCESS_KEY=fakeaccesskey -export AWS_REGION=us-east-1 +export AWS_REGION=us-east-2 aws dynamodb create-table \ --table-name payments \ diff --git a/src/main/resources/localstack/localstack-init.sh b/src/main/resources/localstack/localstack-init.sh new file mode 100755 index 0000000..e3c1e23 --- /dev/null +++ b/src/main/resources/localstack/localstack-init.sh @@ -0,0 +1,61 @@ +#!/bin/bash + +LOCALSTACK_HOST=localhost + +echo "Creating SQS queues..." + +SQS_QUEUES=("request-payment_queue" "payment-response_queue") + +for queue in "${SQS_QUEUES[@]}" +do + aws sqs create-queue \ + --endpoint-url=http://$LOCALSTACK_HOST:4566 \ + --queue-name="${queue}_dlq" + echo "DLQ queue [${queue}_dlq] created" + + aws sqs create-queue \ + --endpoint-url=http://$LOCALSTACK_HOST:4566 \ + --queue-name=$queue \ + --attributes DelaySeconds=5,RedrivePolicy="\"{\\\"deadLetterTargetArn\\\":\\\"arn:aws:sqs:us-west-2:000000000000:${queue}_dlq\\\",\\\"maxReceiveCount\\\":\\\"3\\\"}\"" + echo "Queue [$queue] created" +done + +echo "Creating SNS topics..." + +SNS_TOPICS=("request-payment_topic" "payment-response_topic") + +for topic in "${SNS_TOPICS[@]}" +do + aws sns create-topic \ + --endpoint-url=http://$LOCALSTACK_HOST:4566 \ + --name=$topic + echo "Topic [$topic] created" +done + + +aws sns subscribe \ + --endpoint-url=http://localhost:4566 \ + --topic-arn=arn:aws:sqs:us-east-2:000000000000:request-payment_topic \ + --protocol=sqs \ + --notification-endpoint=arn:aws:sns:us-east-2:000000000000:request-payment_queue + +echo "Topic request-payment_queue subscribe" + +aws sns subscribe \ + --endpoint-url=http://localhost:4566 \ + --topic-arn=arn:aws:sqs:us-east-2:000000000000:payment-response_topic \ + --protocol=sqs \ + --notification-endpoint=arn:aws:sns:us-east-2:000000000000:payment-response_queue + +echo "Topic payment-response_queue subscribe" + +echo "Configuration completed, ready to dev!" + + + +## It is necessary to configure --attribute-name=RawMessageDelivery +## for the message to be received in the correct format +## +## aws sns set-subscription-attributes --endpoint-url=http://localhost:4566 --subscription-arn=<> --attribute-name=RawMessageDelivery --attribute-value=true +## +## \ No newline at end of file diff --git a/src/test/kotlin/com/fiap/payments/TestFixtures.kt b/src/test/kotlin/com/fiap/payments/TestFixtures.kt index c931879..e81d26f 100644 --- a/src/test/kotlin/com/fiap/payments/TestFixtures.kt +++ b/src/test/kotlin/com/fiap/payments/TestFixtures.kt @@ -9,15 +9,14 @@ import com.fiap.payments.domain.entities.PaymentRequest import com.fiap.payments.domain.valueobjects.PaymentStatus import com.fiap.payments.driver.database.persistence.entities.PaymentDocument import com.fiap.payments.driver.database.provider.MercadoPagoPaymentProvider -import com.fiap.payments.driver.web.request.OrderInfo -import com.fiap.payments.driver.web.request.OrderLine -import com.fiap.payments.driver.web.request.PaymentHTTPRequest +import com.fiap.payments.driver.messaging.event.PaymentRequestEvent + import java.math.BigDecimal import java.time.LocalDateTime -fun createPaymentHTTPRequest( - orderInfo: OrderInfo = createOrderInfo() -) = PaymentHTTPRequest( +fun createPaymentEvent( + orderInfo: com.fiap.payments.driver.messaging.event.OrderInfo = createOrderInfo() +) = PaymentRequestEvent( orderInfo = orderInfo ) @@ -26,13 +25,13 @@ fun createOrderInfo( orderedAt: LocalDateTime = LocalDateTime.parse("2023-10-01T18:00:00"), orderedBy: String = "John Doe", totalAmount: BigDecimal = BigDecimal.valueOf(10) -) = OrderInfo( +) = com.fiap.payments.driver.messaging.event.OrderInfo( number = number, orderedAt = orderedAt, orderedBy = orderedBy, total = totalAmount, lines = listOf( - OrderLine( + com.fiap.payments.driver.messaging.event.OrderLine( name = "Item 1", quantity = 1, total = BigDecimal.valueOf(10), diff --git a/src/test/kotlin/com/fiap/payments/adapter/controller/PaymentControllerTest.kt b/src/test/kotlin/com/fiap/payments/adapter/controller/PaymentControllerTest.kt index 4ca9db2..43b9ccc 100644 --- a/src/test/kotlin/com/fiap/payments/adapter/controller/PaymentControllerTest.kt +++ b/src/test/kotlin/com/fiap/payments/adapter/controller/PaymentControllerTest.kt @@ -2,7 +2,7 @@ package com.fiap.payments.adapter.controller import com.fiap.payments.adapter.controller.PaymentController.IPNType import com.fiap.payments.createPayment -import com.fiap.payments.createPaymentHTTPRequest +import com.fiap.payments.createPaymentEvent import com.fiap.payments.domain.valueobjects.PaymentStatus import com.fiap.payments.usecases.ChangePaymentStatusUseCase import com.fiap.payments.usecases.LoadPaymentUseCase @@ -25,14 +25,12 @@ import java.util.* class PaymentControllerTest { private val loadPaymentUseCase = mockk() private val syncPaymentUseCase = mockk() - private val providePaymentRequestUseCase = mockk() private val changePaymentStatusUseCase = mockk() private val paymentController = PaymentController( loadPaymentUseCase, syncPaymentUseCase, - providePaymentRequestUseCase, changePaymentStatusUseCase ) @@ -64,17 +62,6 @@ class PaymentControllerTest { assertThat(result.body).isEqualTo(payment) } - @Test - fun `should create payment`() { - val paymentHTTPRequest = createPaymentHTTPRequest() - val payment = createPayment() - every { providePaymentRequestUseCase.providePaymentRequest(paymentHTTPRequest) } returns payment - - val result = paymentController.create(paymentHTTPRequest) - - assertThat(result.statusCode).isEqualTo(HttpStatus.OK) - assertThat(result.body).isEqualTo(payment) - } @Test fun `should fail payment`() { diff --git a/src/test/kotlin/com/fiap/payments/adapter/gateway/impl/OrderGatewayImplTest.kt b/src/test/kotlin/com/fiap/payments/adapter/gateway/impl/OrderGatewayImplTest.kt deleted file mode 100644 index d5c728e..0000000 --- a/src/test/kotlin/com/fiap/payments/adapter/gateway/impl/OrderGatewayImplTest.kt +++ /dev/null @@ -1,34 +0,0 @@ -package com.fiap.payments.adapter.gateway.impl - -import com.fiap.payments.client.OrderApiClient -import io.mockk.justRun -import io.mockk.mockk -import io.mockk.unmockkAll -import io.mockk.verify -import org.junit.jupiter.api.AfterEach -import org.junit.jupiter.api.Test - -class OrderGatewayImplTest { - private val orderApiClient = mockk() - - private val orderGatewayImpl = - OrderGatewayImpl( - orderApiClient - ) - - @AfterEach - fun tearDown() { - unmockkAll() - } - - @Test - fun `should confirm order`() { - val orderNumber = 1L - - justRun { orderApiClient.confirm(orderNumber) } - - orderGatewayImpl.confirmOrder(orderNumber) - - verify { orderApiClient.confirm(orderNumber) } - } -} diff --git a/src/test/kotlin/com/fiap/payments/adapter/gateway/impl/PaymentGatewayImplTest.kt b/src/test/kotlin/com/fiap/payments/adapter/gateway/impl/PaymentGatewayImplTest.kt index f133e6e..0e4530c 100644 --- a/src/test/kotlin/com/fiap/payments/adapter/gateway/impl/PaymentGatewayImplTest.kt +++ b/src/test/kotlin/com/fiap/payments/adapter/gateway/impl/PaymentGatewayImplTest.kt @@ -1,15 +1,13 @@ package com.fiap.payments.adapter.gateway.impl +import com.fiap.payments.adapter.messaging.PaymentSender import com.fiap.payments.createPayment import com.fiap.payments.createPaymentDocument import com.fiap.payments.domain.valueobjects.PaymentStatus import com.fiap.payments.driver.database.persistence.repository.PaymentDynamoRepository import com.fiap.payments.toDocument import com.fiap.payments.toPaymentEntity -import io.mockk.every -import io.mockk.mockk -import io.mockk.unmockkAll -import io.mockk.verify +import io.mockk.* import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.Nested @@ -18,10 +16,12 @@ import java.util.* class PaymentGatewayImplTest { private val paymentRepository = mockk() + private val paymentSender = mockk() + private val paymentGatewayImpl = PaymentGatewayImpl( - paymentRepository + paymentRepository, paymentSender ) @AfterEach @@ -99,4 +99,20 @@ class PaymentGatewayImplTest { verify(exactly = 1) { paymentRepository.save(any()) } } } + + @Nested + inner class PublishPayment { + + @Test + fun `should send payment`() { + val payment = createPayment() + + justRun { paymentSender.sendPayment(payment) } + + val paymentSent = paymentGatewayImpl.publishPayment(payment) + + assertThat(paymentSent.id).isEqualTo(payment.id) + } + + } } diff --git a/src/test/kotlin/com/fiap/payments/adapter/messaging/PaymentSenderImplTest.kt b/src/test/kotlin/com/fiap/payments/adapter/messaging/PaymentSenderImplTest.kt new file mode 100644 index 0000000..4dd38a5 --- /dev/null +++ b/src/test/kotlin/com/fiap/payments/adapter/messaging/PaymentSenderImplTest.kt @@ -0,0 +1,43 @@ +package com.fiap.payments.adapter.messaging + +import com.fasterxml.jackson.databind.ObjectMapper +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule +import com.fasterxml.jackson.module.kotlin.KotlinModule +import com.fiap.payments.adapter.messaging.impl.PaymentSenderImpl +import com.fiap.payments.createPayment +import io.awspring.cloud.sns.core.SnsTemplate +import io.mockk.justRun +import io.mockk.mockk +import org.junit.jupiter.api.Nested +import org.junit.jupiter.api.Test +import org.mockito.ArgumentMatchers.anyString +import org.springframework.messaging.support.GenericMessage + +class PaymentSenderImplTest { + + private val snsTemplate: SnsTemplate = mockk() + private val topicName: String = "topic" + private val mapper: ObjectMapper = ObjectMapper().registerModule(JavaTimeModule()) + + private val sender = PaymentSenderImpl( + snsTemplate = snsTemplate, + topicName = topicName, + mapper = mapper + ) + + @Nested + inner class SendPayment { + + @Test + fun `should send payment`() { + val payment = createPayment() + + justRun { snsTemplate.send(eq(topicName), any(GenericMessage::class)) } + + sender.sendPayment(payment) + } + + } + + +} \ No newline at end of file diff --git a/src/test/kotlin/com/fiap/payments/driver/database/provider/MercadoPagoPaymentProviderTest.kt b/src/test/kotlin/com/fiap/payments/driver/database/provider/MercadoPagoPaymentProviderTest.kt index d148e30..09fd762 100644 --- a/src/test/kotlin/com/fiap/payments/driver/database/provider/MercadoPagoPaymentProviderTest.kt +++ b/src/test/kotlin/com/fiap/payments/driver/database/provider/MercadoPagoPaymentProviderTest.kt @@ -3,7 +3,7 @@ package com.fiap.payments.driver.database.provider import com.fiap.payments.client.MercadoPagoClient import com.fiap.payments.createMercadoPagoMerchantOrderResponse import com.fiap.payments.createMercadoPagoQRCodeOrderResponse -import com.fiap.payments.createPaymentHTTPRequest +import com.fiap.payments.createPaymentEvent import com.fiap.payments.domain.valueobjects.PaymentStatus import com.fiap.payments.driver.database.provider.MercadoPagoPaymentProvider.MercadoPagoOrderStatus import io.mockk.every @@ -35,7 +35,7 @@ class MercadoPagoPaymentProviderTest { @Test fun `should create external order`() { val paymentId = UUID.randomUUID().toString() - val paymentHTTPRequest = createPaymentHTTPRequest() + val paymentHTTPRequest = createPaymentEvent() val mercadoPagoQRCodeOrderResponse = createMercadoPagoQRCodeOrderResponse() every { mercadoPagoClient.submitMerchantOrder(any()) } returns mercadoPagoQRCodeOrderResponse diff --git a/src/test/kotlin/com/fiap/payments/driver/database/provider/PaymentProviderGatewayMockTest.kt b/src/test/kotlin/com/fiap/payments/driver/database/provider/PaymentProviderGatewayMockTest.kt index 3d3029b..c53348b 100644 --- a/src/test/kotlin/com/fiap/payments/driver/database/provider/PaymentProviderGatewayMockTest.kt +++ b/src/test/kotlin/com/fiap/payments/driver/database/provider/PaymentProviderGatewayMockTest.kt @@ -1,6 +1,6 @@ package com.fiap.payments.driver.database.provider -import com.fiap.payments.createPaymentHTTPRequest +import com.fiap.payments.createPaymentEvent import com.fiap.payments.domain.valueobjects.PaymentStatus import io.mockk.unmockkAll import org.assertj.core.api.Assertions.assertThat @@ -19,7 +19,7 @@ class PaymentProviderGatewayMockTest { @Test fun `should create external order`() { val paymentId = UUID.randomUUID().toString() - val paymentHTTPRequest = createPaymentHTTPRequest() + val paymentHTTPRequest = createPaymentEvent() val result = paymentProviderGatewayMock.createExternalOrder(paymentId, paymentHTTPRequest) diff --git a/src/test/kotlin/com/fiap/payments/driver/messaging/consumer/RequestPaymentConsumerTest.kt b/src/test/kotlin/com/fiap/payments/driver/messaging/consumer/RequestPaymentConsumerTest.kt new file mode 100644 index 0000000..28a243d --- /dev/null +++ b/src/test/kotlin/com/fiap/payments/driver/messaging/consumer/RequestPaymentConsumerTest.kt @@ -0,0 +1,36 @@ +package com.fiap.payments.driver.messaging.consumer + +import com.fiap.payments.createPayment +import com.fiap.payments.createPaymentEvent +import com.fiap.payments.usecases.ProvidePaymentRequestUseCase +import io.mockk.every +import io.mockk.mockk +import org.junit.jupiter.api.Nested +import org.junit.jupiter.api.Test +import org.springframework.messaging.MessageHeaders + +class RequestPaymentConsumerTest { + + private val providePaymentRequestUseCase = mockk() + + private val consumer = RequestPaymentConsumer( + providePaymentRequestUseCase + ) + + @Nested + inner class ConsumeRequest { + + @Test + fun `should consume payment request`() { + val event = createPaymentEvent() + val payment = createPayment() + + every { providePaymentRequestUseCase.providePaymentRequest(event) } returns payment + + consumer.onMessage(event, MessageHeaders(emptyMap())) + } + + + } + +} \ No newline at end of file diff --git a/src/test/kotlin/com/fiap/payments/usecases/services/OrderServiceTest.kt b/src/test/kotlin/com/fiap/payments/usecases/services/OrderServiceTest.kt deleted file mode 100644 index 07e2112..0000000 --- a/src/test/kotlin/com/fiap/payments/usecases/services/OrderServiceTest.kt +++ /dev/null @@ -1,30 +0,0 @@ -package com.fiap.payments.usecases.services - -import com.fiap.payments.adapter.gateway.OrderGateway -import io.mockk.justRun -import io.mockk.mockk -import io.mockk.unmockkAll -import io.mockk.verify -import org.junit.jupiter.api.AfterEach -import org.junit.jupiter.api.Test - -class OrderServiceTest { - private val orderGateway = mockk() - - private val orderService = OrderService( - orderGateway, - ) - - @AfterEach - fun tearDown() { - unmockkAll() - } - - @Test - fun `should confirm order`() { - val orderNumber = 1L - justRun { orderGateway.confirmOrder(orderNumber) } - orderService.confirmOrder(orderNumber) - verify(exactly = 1) { orderGateway.confirmOrder(orderNumber) } - } -} diff --git a/src/test/kotlin/com/fiap/payments/usecases/services/PaymentServiceTest.kt b/src/test/kotlin/com/fiap/payments/usecases/services/PaymentServiceTest.kt index c2a9595..e016f93 100644 --- a/src/test/kotlin/com/fiap/payments/usecases/services/PaymentServiceTest.kt +++ b/src/test/kotlin/com/fiap/payments/usecases/services/PaymentServiceTest.kt @@ -3,12 +3,11 @@ package com.fiap.payments.usecases.services import com.fiap.payments.adapter.gateway.PaymentGateway import com.fiap.payments.adapter.gateway.PaymentProviderGateway import com.fiap.payments.createPayment -import com.fiap.payments.createPaymentHTTPRequest +import com.fiap.payments.createPaymentEvent import com.fiap.payments.createPaymentRequest import com.fiap.payments.domain.errors.ErrorType import com.fiap.payments.domain.errors.PaymentsException import com.fiap.payments.domain.valueobjects.PaymentStatus -import com.fiap.payments.usecases.ConfirmOrderUseCase import io.mockk.every import io.mockk.justRun import io.mockk.mockk @@ -25,15 +24,13 @@ import java.time.LocalDateTime import java.util.* class PaymentServiceTest { - private val paymentRepository = mockk() + private val paymentGateway = mockk() private val paymentProvider = mockk() - private val confirmOrderUseCase = mockk() private val paymentService = PaymentService( - paymentRepository, + paymentGateway, paymentProvider, - confirmOrderUseCase ) @AfterEach @@ -46,7 +43,7 @@ class PaymentServiceTest { @Test fun `should return existent payment`() { val payment = createPayment() - every { paymentRepository.findByPaymentId(payment.id) } returns payment + every { paymentGateway.findByPaymentId(payment.id) } returns payment val result = paymentService.getByPaymentId(payment.id) assertThat(result).isEqualTo(payment) } @@ -55,7 +52,7 @@ class PaymentServiceTest { fun `should throw an exception when payment is not found`() { val paymentId = "5019af79-11c8-4100-9d3c-e98563b1c52c" - every { paymentRepository.findByPaymentId(paymentId) } returns null + every { paymentGateway.findByPaymentId(paymentId) } returns null assertThatThrownBy { paymentService.getByPaymentId(paymentId) } .isInstanceOf(PaymentsException::class.java) @@ -70,12 +67,12 @@ class PaymentServiceTest { val paymentId = UUID.randomUUID().toString() val payment = createPayment(id = paymentId) - every { paymentRepository.findByPaymentId(paymentId) } returns payment + every { paymentGateway.findByPaymentId(paymentId) } returns payment val result = paymentService.findByPaymentId(paymentId) assertThat(result).isEqualTo(payment) - verify(exactly = 1) { paymentRepository.findByPaymentId(paymentId) } + verify(exactly = 1) { paymentGateway.findByPaymentId(paymentId) } } } @@ -85,12 +82,12 @@ class PaymentServiceTest { fun `should find all payments`() { val payments = listOf(createPayment()) - every { paymentRepository.findAll() } returns payments + every { paymentGateway.findAll() } returns payments val result = paymentService.findAll() assertThat(result).containsExactlyElementsOf(payments) - verify(exactly = 1) { paymentRepository.findAll() } + verify(exactly = 1) { paymentGateway.findAll() } } } @@ -99,17 +96,19 @@ class PaymentServiceTest { @Test fun `should create payment`() { - val paymentHTTPRequest = createPaymentHTTPRequest() + val paymentHTTPRequest = createPaymentEvent() val payment = createPayment() val paymentRequest = createPaymentRequest() - every { paymentRepository.upsert(any()) } returns payment + every { paymentGateway.upsert(any()) } returns payment every { paymentProvider.createExternalOrder(payment.id, paymentHTTPRequest) } returns paymentRequest + every { paymentGateway.publishPayment(payment) } returns payment + val result = paymentService.providePaymentRequest(paymentHTTPRequest) assertThat(result).isEqualTo(payment) - verify(exactly = 2) { paymentRepository.upsert(any()) } + verify(exactly = 2) { paymentGateway.upsert(any()) } } } @@ -124,14 +123,14 @@ class PaymentServiceTest { statusChangedAt = LocalDateTime.now() ) - every { paymentRepository.findByPaymentId(paymentId) } returns pendingPayment - every { paymentRepository.upsert(any()) } returns changedPayment - justRun { confirmOrderUseCase.confirmOrder(pendingPayment.orderNumber) } + every { paymentGateway.findByPaymentId(paymentId) } returns pendingPayment + every { paymentGateway.upsert(any()) } returns changedPayment + every { paymentGateway.publishPayment(changedPayment) } returns changedPayment val result = paymentService.confirmPayment(paymentId) assertThat(result).isEqualTo(changedPayment) - verify(exactly = 1) { confirmOrderUseCase.confirmOrder(pendingPayment.orderNumber) } + verify(exactly = 1) { paymentGateway.publishPayment(changedPayment) } } @ParameterizedTest @@ -140,7 +139,7 @@ class PaymentServiceTest { val paymentId = UUID.randomUUID().toString() val payment = createPayment(status = paymentStatus) - every { paymentRepository.findByPaymentId(paymentId) } returns payment + every { paymentGateway.findByPaymentId(paymentId) } returns payment assertThatThrownBy { paymentService.confirmPayment(paymentId) } .isInstanceOf(PaymentsException::class.java) @@ -159,8 +158,9 @@ class PaymentServiceTest { statusChangedAt = LocalDateTime.now() ) - every { paymentRepository.findByPaymentId(paymentId) } returns pendingPayment - every { paymentRepository.upsert(any()) } returns changedPayment + every { paymentGateway.findByPaymentId(paymentId) } returns pendingPayment + every { paymentGateway.upsert(any()) } returns changedPayment + every { paymentGateway.publishPayment(changedPayment) } returns changedPayment val result = paymentService.failPayment(paymentId) @@ -173,7 +173,7 @@ class PaymentServiceTest { val paymentId = UUID.randomUUID().toString() val payment = createPayment(status = paymentStatus) - every { paymentRepository.findByPaymentId(paymentId) } returns payment + every { paymentGateway.findByPaymentId(paymentId) } returns payment assertThatThrownBy { paymentService.failPayment(paymentId) } .isInstanceOf(PaymentsException::class.java) @@ -192,8 +192,9 @@ class PaymentServiceTest { statusChangedAt = LocalDateTime.now() ) - every { paymentRepository.findByPaymentId(paymentId) } returns pendingPayment - every { paymentRepository.upsert(any()) } returns changedPayment + every { paymentGateway.findByPaymentId(paymentId) } returns pendingPayment + every { paymentGateway.upsert(any()) } returns changedPayment + every { paymentGateway.publishPayment(changedPayment) } returns changedPayment val result = paymentService.expirePayment(paymentId) @@ -206,7 +207,7 @@ class PaymentServiceTest { val paymentId = UUID.randomUUID().toString() val payment = createPayment(status = paymentStatus) - every { paymentRepository.findByPaymentId(paymentId) } returns payment + every { paymentGateway.findByPaymentId(paymentId) } returns payment assertThatThrownBy { paymentService.expirePayment(paymentId) } .isInstanceOf(PaymentsException::class.java)