Skip to content

Commit

Permalink
Merge pull request #21 from FIAP-3SOAT-G15/feature/saga
Browse files Browse the repository at this point in the history
initial saga
  • Loading branch information
wellyfrs authored Aug 7, 2024
2 parents d19a3f5 + 8c8e42a commit d85d059
Show file tree
Hide file tree
Showing 36 changed files with 367 additions and 244 deletions.
16 changes: 14 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -41,13 +41,25 @@ 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"]
interval: 10s
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:
16 changes: 16 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<name>payments</name>
<description>Payments API</description>
<properties>
<awsspring.version>3.0.4</awsspring.version>
<java.version>17</java.version>
<kotlin.version>1.8.22</kotlin.version>
<kotlin.compiler.jvmTarget>17</kotlin.compiler.jvmTarget>
Expand Down Expand Up @@ -110,6 +111,14 @@
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-sts</artifactId>
</dependency>
<dependency>
<groupId>io.awspring.cloud</groupId>
<artifactId>spring-cloud-aws-starter-sns</artifactId>
</dependency>
<dependency>
<groupId>io.awspring.cloud</groupId>
<artifactId>spring-cloud-aws-starter-sqs</artifactId>
</dependency>
<dependency>
<groupId>io.github.boostchicken</groupId>
<artifactId>spring-data-dynamodb</artifactId>
Expand Down Expand Up @@ -149,6 +158,13 @@
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>io.awspring.cloud</groupId>
<artifactId>spring-cloud-aws-dependencies</artifactId>
<version>${awsspring.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand All @@ -28,9 +25,6 @@ class PaymentController(
return ResponseEntity.ok(loadPaymentUseCase.getByPaymentId(paymentId))
}

override fun create(paymentHTTPRequest: PaymentHTTPRequest): ResponseEntity<Payment> {
return ResponseEntity.ok(providePaymentRequestUseCase.providePaymentRequest(paymentHTTPRequest))
}

override fun fail(paymentId: String): ResponseEntity<Payment> {
return ResponseEntity.ok(changePaymentStatusUseCase.failPayment(paymentId))
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -21,13 +18,11 @@ class ServiceConfig {
@Bean
fun createPaymentService(
paymentRepository: PaymentGateway,
paymentProvider: PaymentProviderGateway,
confirmOrderUseCase: ConfirmOrderUseCase
paymentProvider: PaymentProviderGateway
): PaymentService {
return PaymentService(
paymentRepository,
paymentProvider,
confirmOrderUseCase
)
}

Expand All @@ -46,10 +41,4 @@ class ServiceConfig {
)
}

@Bean
fun paymentOrderService(orderGateway: OrderGateway): OrderService {
return OrderService(
orderGateway
)
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,6 @@ interface PaymentGateway {
fun findAll(): List<Payment>

fun upsert(payment: Payment): Payment

fun publishPayment(payment: Payment): Payment
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
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
import org.mapstruct.factory.Mappers

class PaymentGatewayImpl(
private val paymentRepository: PaymentDynamoRepository,
private val paymentSender: PaymentSender
) : PaymentGateway {
private val mapper = Mappers.getMapper(PaymentMapper::class.java)

Expand Down Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.fiap.payments.adapter.messaging

import com.fiap.payments.domain.entities.Payment

interface PaymentSender {
fun sendPayment(payment: Payment)
}
Original file line number Diff line number Diff line change
@@ -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)
}
}
Original file line number Diff line number Diff line change
@@ -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))
)
}
}
20 changes: 0 additions & 20 deletions src/main/kotlin/com/fiap/payments/client/OrderApiClient.kt

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -14,17 +14,13 @@ 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")
fun createTransactionalGateway(): TransactionalGateway {
return TransactionalGatewayImpl()
}

@Bean("OrderGateway")
fun createOrderGateway(orderApiClient: OrderApiClient): OrderGateway {
return OrderGatewayImpl(orderApiClient)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
Original file line number Diff line number Diff line change
@@ -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)
}
}


Loading

0 comments on commit d85d059

Please sign in to comment.