progress on aligning transaction payloads
This commit is contained in:
@@ -9,7 +9,7 @@ import zw.qantra.tm.domain.services.CategoryService;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/categories")
|
@RequestMapping("/public/categories")
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class CategoryController {
|
public class CategoryController {
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import zw.qantra.tm.domain.models.Transaction;
|
|||||||
import zw.qantra.tm.domain.services.TransactionService;
|
import zw.qantra.tm.domain.services.TransactionService;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/confirm/transaction")
|
@RequestMapping("/public/confirm/transaction")
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class ConfirmationController {
|
public class ConfirmationController {
|
||||||
private final TransactionService transactionService;
|
private final TransactionService transactionService;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
|||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/integration/transaction")
|
@RequestMapping("/public/integration/transaction")
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class IntegrationController {
|
public class IntegrationController {
|
||||||
@PostMapping()
|
@PostMapping()
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import java.util.Optional;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/payment-processors")
|
@RequestMapping("/public/payment-processors")
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class PaymentProcessorController {
|
public class PaymentProcessorController {
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import zw.qantra.tm.domain.services.ProviderService;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/providers")
|
@RequestMapping("/public/providers")
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class ProviderController {
|
public class ProviderController {
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import java.util.List;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/recipients")
|
@RequestMapping("/public/recipients")
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class RecipientController {
|
public class RecipientController {
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package zw.qantra.tm.domain.controllers;
|
|||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import net.kaczmarzyk.spring.data.jpa.domain.Equal;
|
import net.kaczmarzyk.spring.data.jpa.domain.Equal;
|
||||||
import net.kaczmarzyk.spring.data.jpa.web.annotation.And;
|
|
||||||
import net.kaczmarzyk.spring.data.jpa.web.annotation.Or;
|
import net.kaczmarzyk.spring.data.jpa.web.annotation.Or;
|
||||||
import net.kaczmarzyk.spring.data.jpa.web.annotation.Spec;
|
import net.kaczmarzyk.spring.data.jpa.web.annotation.Spec;
|
||||||
import net.kaczmarzyk.spring.data.jpa.web.annotation.Conjunction;
|
import net.kaczmarzyk.spring.data.jpa.web.annotation.Conjunction;
|
||||||
@@ -21,7 +20,7 @@ import zw.qantra.tm.utils.LogUtils;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/transaction")
|
@RequestMapping("/public/transaction")
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class TransactonController {
|
public class TransactonController {
|
||||||
Logger logger = LoggerFactory.getLogger(TransactonController.class);
|
Logger logger = LoggerFactory.getLogger(TransactonController.class);
|
||||||
|
|||||||
@@ -3,5 +3,6 @@ package zw.qantra.tm.domain.enums;
|
|||||||
public enum RequestType {
|
public enum RequestType {
|
||||||
CONFIRM,
|
CONFIRM,
|
||||||
REQUEST,
|
REQUEST,
|
||||||
|
POLL,
|
||||||
INTEGRATION
|
INTEGRATION
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,5 +5,8 @@ public enum Status {
|
|||||||
PENDING,
|
PENDING,
|
||||||
FAILED,
|
FAILED,
|
||||||
CANCELLED,
|
CANCELLED,
|
||||||
REVERSED
|
REVERSED,
|
||||||
|
AUTHORIZED,
|
||||||
|
REJECTED,
|
||||||
|
PROCESSING
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,6 +59,19 @@ public class Transaction extends BaseEntity {
|
|||||||
private String providerImage;
|
private String providerImage;
|
||||||
private String paymentProcessorImage;
|
private String paymentProcessorImage;
|
||||||
|
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
private Status authorizationStatus;
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
private Status confirmationStatus;
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
private Status paymentStatus;
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
private Status integrationStatus;
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
private Status reversalStatus;
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
private Status pollingStatus;
|
||||||
|
|
||||||
private String erpSalesRef;
|
private String erpSalesRef;
|
||||||
private String erpJournalRef;
|
private String erpJournalRef;
|
||||||
private String erpSalesPaymentRef;
|
private String erpSalesPaymentRef;
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package zw.qantra.tm.domain.models;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.Enumerated;
|
||||||
|
import jakarta.persistence.EnumType;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
import zw.qantra.tm.domain.enums.Status;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||||
|
public class TransactionEvent extends BaseEntity {
|
||||||
|
private String transactionId;
|
||||||
|
private String event;
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
private Status status;
|
||||||
|
private String message;
|
||||||
|
private String data;
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package zw.qantra.tm.domain.repositories;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import zw.qantra.tm.domain.models.TransactionEvent;
|
||||||
|
|
||||||
|
public interface TransactionEventRepository extends JpaRepository<TransactionEvent, UUID> {
|
||||||
|
List<TransactionEvent> findByTransactionId(UUID transactionId);
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@ import org.springframework.stereotype.Repository;
|
|||||||
import zw.qantra.tm.domain.enums.RequestType;
|
import zw.qantra.tm.domain.enums.RequestType;
|
||||||
import zw.qantra.tm.domain.models.Transaction;
|
import zw.qantra.tm.domain.models.Transaction;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package zw.qantra.tm.domain.services;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import zw.qantra.tm.domain.models.TransactionEvent;
|
||||||
|
import zw.qantra.tm.domain.repositories.TransactionEventRepository;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class TransactionEventService {
|
||||||
|
private final TransactionEventRepository transactionEventRepository;
|
||||||
|
|
||||||
|
public void save(TransactionEvent transactionEvent) {
|
||||||
|
transactionEventRepository.save(transactionEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -30,6 +30,8 @@ import zw.qantra.tm.domain.services.processors.handlers.RecipientsUpdateHandler;
|
|||||||
import zw.qantra.tm.domain.services.processors.handlers.ValidationHandler;
|
import zw.qantra.tm.domain.services.processors.handlers.ValidationHandler;
|
||||||
import zw.qantra.tm.domain.services.processors.handlers.erp.PurchaseInvoiceHandler;
|
import zw.qantra.tm.domain.services.processors.handlers.erp.PurchaseInvoiceHandler;
|
||||||
import zw.qantra.tm.domain.services.processors.handlers.erp.SalesInvoiceHandler;
|
import zw.qantra.tm.domain.services.processors.handlers.erp.SalesInvoiceHandler;
|
||||||
|
import zw.qantra.tm.domain.models.TransactionEvent;
|
||||||
|
import zw.qantra.tm.domain.services.TransactionEventService;
|
||||||
import zw.qantra.tm.exceptions.ApiException;
|
import zw.qantra.tm.exceptions.ApiException;
|
||||||
import zw.qantra.tm.utils.Utils;
|
import zw.qantra.tm.utils.Utils;
|
||||||
|
|
||||||
@@ -45,10 +47,18 @@ public class TransactionService {
|
|||||||
private final ChargeService chargeService;
|
private final ChargeService chargeService;
|
||||||
private final AdditionalDataService additionalDataService;
|
private final AdditionalDataService additionalDataService;
|
||||||
private final RecipientService recipientService;
|
private final RecipientService recipientService;
|
||||||
|
private final TransactionEventService transactionEventService;
|
||||||
|
|
||||||
public Transaction integration(Transaction transaction) {
|
public Transaction integration(Transaction transaction) {
|
||||||
transaction.setType(RequestType.INTEGRATION);
|
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 =
|
LogicPipeline<Transaction, Transaction> transactionLogic =
|
||||||
new LogicPipeline<>(new ValidationHandler());
|
new LogicPipeline<>(new ValidationHandler());
|
||||||
transaction = transactionLogic.execute(transaction);
|
transaction = transactionLogic.execute(transaction);
|
||||||
@@ -82,6 +92,10 @@ public class TransactionService {
|
|||||||
new LogicPipeline<>(new PurchaseInvoiceHandler());
|
new LogicPipeline<>(new PurchaseInvoiceHandler());
|
||||||
transaction = postTransactionLogic.execute(transaction);
|
transaction = postTransactionLogic.execute(transaction);
|
||||||
|
|
||||||
|
transactionEvent.setStatus(transaction.getStatus());
|
||||||
|
transactionEvent.setMessage(transaction.getErrorMessage());
|
||||||
|
transactionEventService.save(transactionEvent);
|
||||||
|
|
||||||
return transaction;
|
return transaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,6 +110,13 @@ public class TransactionService {
|
|||||||
return transaction;
|
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
|
// no persistence happens during polling unless the transaction status changes
|
||||||
String label = getLabel(transaction);
|
String label = getLabel(transaction);
|
||||||
logger.info("label: {}", label);
|
logger.info("label: {}", label);
|
||||||
@@ -106,12 +127,14 @@ public class TransactionService {
|
|||||||
// find out if the gateway tran was successful
|
// find out if the gateway tran was successful
|
||||||
transactionProcessorInterface.poll(transaction);
|
transactionProcessorInterface.poll(transaction);
|
||||||
|
|
||||||
// if tran was successful deep copy transaction & push integration to the aggregator
|
transactionEvent.setStatus(transaction.getStatus());
|
||||||
|
transactionEvent.setMessage(transaction.getErrorMessage());
|
||||||
|
transactionEventService.save(transactionEvent);
|
||||||
|
|
||||||
|
// if tran was successful push integration to the aggregator
|
||||||
if(transaction.getStatus() == Status.SUCCESS){
|
if(transaction.getStatus() == Status.SUCCESS){
|
||||||
Transaction transactionCopy = Utils.deepCopy(transaction, Transaction.class);
|
transaction.setType(RequestType.INTEGRATION);
|
||||||
transactionCopy.setType(RequestType.INTEGRATION);
|
integration(transaction);
|
||||||
transactionCopy.setId(null);
|
|
||||||
integration(transactionCopy);
|
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
@@ -119,11 +142,25 @@ public class TransactionService {
|
|||||||
transaction.setResponseCode("01");
|
transaction.setResponseCode("01");
|
||||||
transaction.setErrorMessage(e.getMessage());
|
transaction.setErrorMessage(e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
return transaction;
|
return transaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Transaction execute(Transaction transaction) {
|
public Transaction execute(Transaction incomingTransaction) {
|
||||||
transaction.setReference(UUID.randomUUID().toString());
|
// 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
|
||||||
|
}
|
||||||
|
|
||||||
|
TransactionEvent transactionEvent = TransactionEvent.builder()
|
||||||
|
.transactionId(transaction.getId().toString())
|
||||||
|
.event(transaction.getType().name())
|
||||||
|
.status(Status.PROCESSING)
|
||||||
|
.build();
|
||||||
|
transactionEventService.save(transactionEvent);
|
||||||
|
|
||||||
// run pre transaction logic
|
// run pre transaction logic
|
||||||
LogicPipeline<Transaction, Transaction> preTransactionLogic =
|
LogicPipeline<Transaction, Transaction> preTransactionLogic =
|
||||||
@@ -143,6 +180,12 @@ public class TransactionService {
|
|||||||
// MAIN TRANSACTION LOGIC!
|
// MAIN TRANSACTION LOGIC!
|
||||||
transactionProcessorInterface.process(transaction);
|
transactionProcessorInterface.process(transaction);
|
||||||
|
|
||||||
|
if(transaction.getType() == RequestType.CONFIRM){
|
||||||
|
transaction.setConfirmationStatus(transaction.getStatus());
|
||||||
|
}else{
|
||||||
|
transaction.setPaymentStatus(transaction.getStatus());
|
||||||
|
}
|
||||||
|
|
||||||
}catch (Exception e){
|
}catch (Exception e){
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
transaction.setStatus(Status.FAILED);
|
transaction.setStatus(Status.FAILED);
|
||||||
@@ -158,13 +201,16 @@ public class TransactionService {
|
|||||||
.addHandler(new SalesInvoiceHandler());
|
.addHandler(new SalesInvoiceHandler());
|
||||||
transaction = postTransactionLogic.execute(transaction);
|
transaction = postTransactionLogic.execute(transaction);
|
||||||
|
|
||||||
|
transactionEvent.setStatus(transaction.getStatus());
|
||||||
|
transactionEvent.setMessage(transaction.getErrorMessage());
|
||||||
|
transactionEventService.save(transactionEvent);
|
||||||
|
|
||||||
return transaction;
|
return transaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getLabel(Transaction transaction){
|
private String getLabel(Transaction transaction){
|
||||||
String label = "";
|
String label = "";
|
||||||
List<RequestType> list = Arrays.asList(RequestType.CONFIRM);
|
if(transaction.getType() == RequestType.CONFIRM){
|
||||||
if(list.contains(transaction.getType())){
|
|
||||||
// get processor label from billClientId
|
// get processor label from billClientId
|
||||||
Provider provider = providerService.getProviderRepository()
|
Provider provider = providerService.getProviderRepository()
|
||||||
.findByClientId(transaction.getBillClientId());
|
.findByClientId(transaction.getBillClientId());
|
||||||
@@ -173,6 +219,8 @@ public class TransactionService {
|
|||||||
}
|
}
|
||||||
label = transaction.getType() + "_" +
|
label = transaction.getType() + "_" +
|
||||||
provider.getLabel();
|
provider.getLabel();
|
||||||
|
|
||||||
|
transaction.setIntegrationProcessorLabel(provider.getIntegrationProcessorLabel());
|
||||||
}else{
|
}else{
|
||||||
label = transaction.getType() + "_" +
|
label = transaction.getType() + "_" +
|
||||||
transaction.getPaymentProcessorLabel() + "_" +
|
transaction.getPaymentProcessorLabel() + "_" +
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package zw.qantra.tm.domain.services.processors.handlers;
|
package zw.qantra.tm.domain.services.processors.handlers;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
import zw.qantra.tm.domain.enums.RequestType;
|
import zw.qantra.tm.domain.enums.RequestType;
|
||||||
import zw.qantra.tm.domain.models.Transaction;
|
import zw.qantra.tm.domain.models.Transaction;
|
||||||
import zw.qantra.tm.utils.Utils;
|
import zw.qantra.tm.utils.Utils;
|
||||||
@@ -9,6 +11,7 @@ public class ConfirmationLogicHandler implements LogicHandler<Transaction, Trans
|
|||||||
public Transaction process(Transaction transaction) {
|
public Transaction process(Transaction transaction) {
|
||||||
if(transaction.getType().equals(RequestType.CONFIRM)) {
|
if(transaction.getType().equals(RequestType.CONFIRM)) {
|
||||||
transaction.setTrace(Utils.getUid());
|
transaction.setTrace(Utils.getUid());
|
||||||
|
transaction.setReference(UUID.randomUUID().toString());
|
||||||
}
|
}
|
||||||
return transaction;
|
return transaction;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user