CreatePaymentUseCase.java
Bridget/payment-gateway-microservices/services/payment-service/src/main/java/com/checkout/paymentgw/payment/application/CreatePaymentUseCase.java
package com.checkout.paymentgw.payment.application;
import com.checkout.paymentgw.payment.api.dto.PostPaymentRequest;
import com.checkout.paymentgw.payment.api.dto.PostPaymentResponse;
import com.checkout.paymentgw.payment.client.BankAdapterClient;
import com.checkout.paymentgw.payment.client.BankAuthorisation;
import com.checkout.paymentgw.payment.client.FraudCheckClient;
import com.checkout.paymentgw.payment.client.FraudDecision;
import com.checkout.paymentgw.payment.domain.PaymentStatus;
import com.checkout.paymentgw.payment.idempotency.IdempotencyStore;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import java.util.Optional;
/**
* The orchestration saga for creating a payment.
*
* <p>Steps:
* <ol>
* <li>Idempotency check (Redis).</li>
* <li>Fraud check (sync REST, ≤ 250 ms; on failure → degrade to ALLOW or REVIEW).</li>
* <li>Bank authorisation (sync REST, ≤ 2 s, circuit-broken).</li>
* <li>Persist via {@link PaymentPersistenceService} — which owns the transaction
* so the {@code payments} row and the {@code payment_outbox} row are written
* atomically.</li>
* </ol>
*
* <p>The upstream calls (fraud, bank) intentionally happen <strong>outside</strong>
* the DB transaction so we don't hold a connection while waiting on network IO.
*/
@Service
public class CreatePaymentUseCase {
private static final Logger LOG = LoggerFactory.getLogger(CreatePaymentUseCase.class);
private final FraudCheckClient fraudCheck;
private final BankAdapterClient bank;
private final PaymentPersistenceService persistence;
private final IdempotencyStore idempotency;
public CreatePaymentUseCase(FraudCheckClient fraudCheck,
BankAdapterClient bank,
PaymentPersistenceService persistence,
IdempotencyStore idempotency) {
this.fraudCheck = fraudCheck;
this.bank = bank;
this.persistence = persistence;
this.idempotency = idempotency;
}
public PostPaymentResponse execute(String idempotencyKey, String merchantId, PostPaymentRequest request) {
Optional<PostPaymentResponse> cached = idempotency.lookup(merchantId, idempotencyKey);
if (cached.isPresent()) {
LOG.info("idempotency hit merchant={} key={}", merchantId, idempotencyKey);
return cached.get();
}
FraudDecision decision = fraudCheck.evaluate(merchantId, request);
if (decision.isBlocked()) {
PostPaymentResponse response = persistence.save(merchantId, request,
PaymentStatus.REJECTED, null, "FRAUD_BLOCKED");
idempotency.store(merchantId, idempotencyKey, response);
return response;
}
BankAuthorisation auth = bank.authorise(request);
PaymentStatus status = auth.authorised() ? PaymentStatus.AUTHORIZED : PaymentStatus.DECLINED;
PostPaymentResponse response = persistence.save(merchantId, request, status,
auth.authCode(), auth.declineReason());
idempotency.store(merchantId, idempotencyKey, response);
return response;
}
}
Artigos relacionados
PaymentGatewayApplication.java
PaymentGatewayApplication.java — java source code from the Bridget learning materials (Bridget/payment-gateway-challenge-java/src/main/java/com/checkout/payment/gateway/PaymentGatewayApplication.java).
Ler artigo →ApplicationConfiguration.java
ApplicationConfiguration.java — java source code from the Bridget learning materials (Bridget/payment-gateway-challenge-java/src/main/java/com/checkout/payment/gateway/configuration/ApplicationConfiguration.java).
Ler artigo →RequestResponseLogger.java
RequestResponseLogger.java — java source code from the Bridget learning materials (Bridget/payment-gateway-challenge-java/src/main/java/com/checkout/payment/gateway/configuration/RequestResponseLogger.java).
Ler artigo →PaymentGatewayController.java
PaymentGatewayController.java — java source code from the Bridget learning materials (Bridget/payment-gateway-challenge-java/src/main/java/com/checkout/payment/gateway/controller/PaymentGatewayController.java).
Ler artigo →PaymentStatus.java
PaymentStatus.java — java source code from the Bridget learning materials (Bridget/payment-gateway-challenge-java/src/main/java/com/checkout/payment/gateway/enums/PaymentStatus.java).
Ler artigo →BankErrorException.java
BankErrorException.java — java source code from the Bridget learning materials (Bridget/payment-gateway-challenge-java/src/main/java/com/checkout/payment/gateway/exception/BankErrorException.java).
Ler artigo →