poc completed

This commit is contained in:
2025-07-11 12:25:46 +02:00
parent 6ad1f55d4b
commit 1ba7a8cda4
28 changed files with 807 additions and 88 deletions

View File

@@ -3,23 +3,34 @@ package zw.qantra.tm.domain.services;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import zw.qantra.tm.domain.enums.RequestType;
import zw.qantra.tm.domain.enums.Status;
import zw.qantra.tm.domain.models.AdditionalData;
import zw.qantra.tm.domain.models.Provider;
import zw.qantra.tm.domain.models.Recipient;
import zw.qantra.tm.domain.models.Transaction;
import zw.qantra.tm.domain.repositories.TransactionRepository;
import zw.qantra.tm.domain.services.factories.PaymentProcessorFactory;
import zw.qantra.tm.domain.services.processors.TransactionProcessorInterface;
import zw.qantra.tm.domain.services.processors.handlers.CalculateChargesHandler;
import zw.qantra.tm.domain.services.processors.handlers.ConfirmationLogicHandler;
import zw.qantra.tm.domain.services.processors.handlers.FormattingHandler;
import zw.qantra.tm.domain.services.processors.handlers.LogicPipeline;
import zw.qantra.tm.domain.services.processors.handlers.RecipientsUpdateHandler;
import zw.qantra.tm.domain.services.processors.handlers.ValidationHandler;
import zw.qantra.tm.exceptions.ApiException;
import zw.qantra.tm.utils.Utils;
@Service
@RequiredArgsConstructor
@@ -29,42 +40,25 @@ public class TransactionService {
@Getter
private final TransactionRepository transactionRepository;
private final PaymentProcessorFactory paymentProcessorFactory;
private final CalculateChargesHandler calculateChargesHandler;
private final ProviderService providerService;
private final ChargeService chargeService;
private final AdditionalDataService additionalDataService;
private final RecipientService recipientService;
public Transaction poll(UUID uuid){
if(!transactionRepository.existsById(uuid)){
throw new ApiException("Transaction not found for ID: " + uuid);
}
Transaction transaction = transactionRepository.findById(uuid).get();
// no persistence happens during polling unless the transaction status changes
String label = getLabel(transaction);
logger.info("label: {}", label);
TransactionProcessorInterface transactionProcessorInterface =
(TransactionProcessorInterface) paymentProcessorFactory.getPaymentProcessor(label);
try {
transactionProcessorInterface.poll(transaction);
} catch (Exception e) {
e.printStackTrace();
transaction.setStatus(Status.FAILED);
transaction.setResponseCode("01");
transaction.setErrorMessage(e.getMessage());
}
return transaction;
}
public Transaction execute(Transaction transaction) {
transaction.setReference(UUID.randomUUID().toString());
public Transaction integration(Transaction transaction) {
transaction.setType(RequestType.INTEGRATION);
LogicPipeline<Transaction, Transaction> transactionLogic =
new LogicPipeline<>(calculateChargesHandler)
.addHandler(new ValidationHandler());
new LogicPipeline<>(new ValidationHandler());
transaction = transactionLogic.execute(transaction);
String label = getLabel(transaction);
Provider provider = providerService.getProviderRepository()
.findByClientId(transaction.getBillClientId());
if(provider == null){
throw new ApiException("Provider not found for billClientId: " + transaction.getBillClientId());
}
String label = transaction.getType() + "_" +
provider.getIntegrationProcessorLabel();
logger.info("label: {}", label);
TransactionProcessorInterface transactionProcessorInterface =
@@ -83,9 +77,80 @@ public class TransactionService {
return transaction;
}
public Transaction poll(UUID uuid){
if(!transactionRepository.existsById(uuid)){
throw new ApiException("Transaction not found for ID: " + uuid);
}
Transaction transaction = transactionRepository.findById(uuid).get();
// no persistence happens during polling unless the transaction status changes
String label = getLabel(transaction);
logger.info("label: {}", label);
TransactionProcessorInterface transactionProcessorInterface =
(TransactionProcessorInterface) paymentProcessorFactory.getPaymentProcessor(label);
try {
// find out if the gateway tran was successful
transactionProcessorInterface.poll(transaction);
// if tran was successful deep copy transaction & push integration to the aggregator
Transaction transactionCopy = Utils.deepCopy(transaction, Transaction.class);
transactionCopy.setType(RequestType.INTEGRATION);
transactionCopy.setId(null);
integration(transactionCopy);
} catch (Exception e) {
e.printStackTrace();
transaction.setStatus(Status.FAILED);
transaction.setResponseCode("01");
transaction.setErrorMessage(e.getMessage());
}
return transaction;
}
public Transaction execute(Transaction transaction) {
transaction.setReference(UUID.randomUUID().toString());
// run pre transaction logic
LogicPipeline<Transaction, Transaction> preTransactionLogic =
new LogicPipeline<>(new CalculateChargesHandler(chargeService))
.addHandler(new ConfirmationLogicHandler())
.addHandler(new FormattingHandler())
.addHandler(new ValidationHandler());
transaction = preTransactionLogic.execute(transaction);
String label = getLabel(transaction);
logger.info("label: {}", label);
TransactionProcessorInterface transactionProcessorInterface =
(TransactionProcessorInterface) paymentProcessorFactory.getPaymentProcessor(label);
try {
// MAIN TRANSACTION LOGIC!
transactionProcessorInterface.process(transaction);
}catch (Exception e){
e.printStackTrace();
transaction.setStatus(Status.FAILED);
transaction.setResponseCode("01");
transaction.setErrorMessage(e.getMessage());
transactionRepository.save(transaction);
return transaction;
}
// run post transaction logic
LogicPipeline<Transaction, Transaction> postTransactionLogic =
new LogicPipeline<>(new RecipientsUpdateHandler(recipientService));
transaction = postTransactionLogic.execute(transaction);
return transaction;
}
private String getLabel(Transaction transaction){
String label = "";
if(transaction.getType() == RequestType.CONFIRM){
List<RequestType> list = Arrays.asList(RequestType.CONFIRM);
if(list.contains(transaction.getType())){
// get processor label from billClientId
Provider provider = providerService.getProviderRepository()
.findByClientId(transaction.getBillClientId());
@@ -102,6 +167,20 @@ public class TransactionService {
return label;
}
public Transaction findById(UUID id) {
Transaction transaction = transactionRepository.findById(id).orElseThrow(() -> new ApiException("Transaction not found for ID: " + id));
AdditionalData additionalData = additionalDataService.getAdditionalDataRepository()
.findByTransactionId(id).orElseThrow(() -> new ApiException("Additional data not found for transaction ID: " + id));
transaction.setAdditionalData(Utils.fromJson(additionalData.getJsonString(), List.class));
return transaction;
}
public List<Transaction> findAll(Specification<Transaction> spec) {
return transactionRepository.findAll(spec, Sort.by(Sort.Direction.ASC, "createdAt"));
}
public Transaction save(Transaction transaction){
return transactionRepository.save(transaction);
}