completed transaction workflow

This commit is contained in:
2025-10-21 23:47:15 +02:00
parent 2b6ef3ab14
commit 77a6dd69a6
12 changed files with 384 additions and 430 deletions

View File

@@ -40,230 +40,8 @@ public class TransactionService {
@Getter
private final TransactionRepository transactionRepository;
private final PaymentProcessorFactory paymentProcessorFactory;
private final ProviderService providerService;
private final ChargeService chargeService;
private final AdditionalDataService additionalDataService;
private final RecipientService recipientService;
private final TransactionEventService transactionEventService;
private final SalesInvoiceHandler salesInvoiceHandler;
private final JournalEntryHandler journalEntryHandler;
private final PaymentEntryHandler paymentEntryHandler;
private final PurchaseInvoiceHandler purchaseInvoiceHandler;
private final PurchasePaymentEntryHandler purchasePaymentEntryHandler;
public Transaction integration(Transaction transaction) {
transaction.setType(RequestType.INTEGRATION);
TransactionEvent transactionEvent = TransactionEvent.builder()
.transactionId(transaction.getId().toString())
.event(transaction.getType().name())
.status(Status.PROCESSING)
.build();
transactionEventService.save(transactionEvent);
LogicPipeline<Transaction, Transaction> transactionLogic =
new LogicPipeline<>(new ValidationHandler())
.addHandler(journalEntryHandler) // todo: do this in a separate thread
.addHandler(paymentEntryHandler); // todo: do this in a separate thread
transaction = transactionLogic.execute(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);
transaction.setIntegrationProcessorLabel(provider.getIntegrationProcessorLabel()); // for reference purposes
TransactionProcessorInterface transactionProcessorInterface =
(TransactionProcessorInterface) paymentProcessorFactory.getPaymentProcessor(label);
try {
transactionProcessorInterface.process(transaction);
transaction.setIntegrationStatus(transaction.getStatus());
transactionRepository.save(transaction);
}catch (Exception e){
e.getCause().printStackTrace();
transaction.setStatus(Status.FAILED);
transaction.setResponseCode("01");
transaction.setErrorMessage(e.getMessage());
transactionRepository.save(transaction);
return transaction;
}
// run post integration logic
LogicPipeline<Transaction, Transaction> postTransactionLogic =
new LogicPipeline<>(purchaseInvoiceHandler) // todo: do this in a separate thread
.addHandler(purchasePaymentEntryHandler); // todo: do this in a separate thread
transaction = postTransactionLogic.execute(transaction);
transactionEvent.setStatus(transaction.getStatus());
transactionEvent.setMessage(transaction.getErrorMessage());
transactionEventService.save(transactionEvent);
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();
// if the transaction is already successful, return it
if(transaction.getIntegrationStatus() == Status.SUCCESS){
return transaction;
}
TransactionEvent transactionEvent = TransactionEvent.builder()
.transactionId(transaction.getId().toString())
.event(RequestType.POLL.name())
.status(Status.PROCESSING)
.build();
transactionEventService.save(transactionEvent);
// no persistence happens during polling unless the transaction status changes
String label = "REQUEST_" + transaction.getPaymentProcessorLabel() + "_" + transaction.getAuthType();
logger.info("label: {}", label);
TransactionProcessorInterface transactionProcessorInterface =
(TransactionProcessorInterface) paymentProcessorFactory.getPaymentProcessor(label);
try {
// find out if the gateway tran was successful
transactionProcessorInterface.poll(transaction);
transactionEvent.setStatus(transaction.getStatus());
transactionEvent.setMessage(transaction.getErrorMessage());
transactionEventService.save(transactionEvent);
transaction.setPollingStatus(transaction.getStatus());
transactionRepository.save(transaction);
// if tran was successful push integration to the aggregator
if(transaction.getStatus() == Status.SUCCESS){
transaction.setType(RequestType.INTEGRATION);
integration(transaction);
}
} catch (Exception e) {
e.printStackTrace();
transaction.setStatus(Status.FAILED);
transaction.setResponseCode("01");
transaction.setErrorMessage(e.getMessage());
}
return transaction;
}
public Transaction request(Transaction incomingTransaction) {
// if payment request (not confirm), then fetch already existing transaction record
Transaction transaction = incomingTransaction;
if(incomingTransaction.getId() != null){
transaction = getTransactionRepository().findById(incomingTransaction.getId()).orElseThrow(() ->
new ApiException("Transaction not found for ID: " + incomingTransaction.getId()));
transaction.setType(incomingTransaction.getType()); // type should be REQUEST here
transaction.setAuthType(incomingTransaction.getAuthType());
}
// run pre transaction logic
LogicPipeline<Transaction, Transaction> preTransactionLogic =
new LogicPipeline<>(new CalculateChargesHandler(chargeService))
.addHandler(new FormattingHandler())
.addHandler(new ValidationHandler());
transaction = preTransactionLogic.execute(transaction);
transactionRepository.save(transaction);
TransactionEvent transactionEvent = TransactionEvent.builder()
.transactionId(transaction.getId().toString())
.event(transaction.getType().name())
.status(Status.PROCESSING)
.build();
transactionEventService.save(transactionEvent);
String label = transaction.getType() + "_" + transaction.getPaymentProcessorLabel() + "_" + transaction.getAuthType();
logger.info("label: {}", label);
TransactionProcessorInterface transactionProcessorInterface =
(TransactionProcessorInterface) paymentProcessorFactory.getPaymentProcessor(label);
try {
// MAIN TRANSACTION LOGIC!
transactionProcessorInterface.process(transaction);
transaction.setPaymentStatus(transaction.getStatus());
}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))
.addHandler(salesInvoiceHandler);// todo: do this in a separate thread
transaction = postTransactionLogic.execute(transaction);
transactionEvent.setStatus(transaction.getStatus());
transactionEvent.setMessage(transaction.getErrorMessage());
transactionEventService.save(transactionEvent);
return transaction;
}
public Transaction confirm(Transaction transaction) {
// run pre transaction logic
LogicPipeline<Transaction, Transaction> preTransactionLogic =
new LogicPipeline<>(new CalculateChargesHandler(chargeService))
.addHandler(new ConfirmationLabelHandler(providerService))
.addHandler(new ConfirmationLogicHandler())
.addHandler(new FormattingHandler())
.addHandler(new ValidationHandler());
transaction = preTransactionLogic.execute(transaction);
transactionRepository.save(transaction);
TransactionEvent transactionEvent = TransactionEvent.builder()
.transactionId(transaction.getId().toString())
.event(transaction.getType().name())
.status(Status.PROCESSING)
.build();
transactionEventService.save(transactionEvent);
TransactionProcessorInterface transactionProcessorInterface =
(TransactionProcessorInterface) paymentProcessorFactory.getPaymentProcessor(
transaction.getConfirmationProcessorLabel());
try {
// MAIN TRANSACTION LOGIC!
transactionProcessorInterface.process(transaction);
transaction.setConfirmationStatus(transaction.getStatus());
}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);
transactionEvent.setStatus(transaction.getStatus());
transactionEvent.setMessage(transaction.getErrorMessage());
transactionEventService.save(transactionEvent);
return transaction;
}
public Transaction findById(UUID id) {
Transaction transaction = transactionRepository.findById(id).orElseThrow(() -> new ApiException("Transaction not found for ID: " + id));