diff --git a/src/main/java/zw/qantra/tm/domain/services/processors/integrations/StewardIntegrationProcessor.java b/src/main/java/zw/qantra/tm/domain/services/processors/integrations/StewardIntegrationProcessor.java index 41c41cf..b59cdf5 100644 --- a/src/main/java/zw/qantra/tm/domain/services/processors/integrations/StewardIntegrationProcessor.java +++ b/src/main/java/zw/qantra/tm/domain/services/processors/integrations/StewardIntegrationProcessor.java @@ -13,12 +13,14 @@ import zw.qantra.tm.domain.enums.Status; import zw.qantra.tm.domain.models.AdditionalData; import zw.qantra.tm.domain.models.Transaction; import zw.qantra.tm.domain.services.AdditionalDataService; +import zw.qantra.tm.domain.services.SettingService; import zw.qantra.tm.domain.services.TransactionService; import zw.qantra.tm.domain.services.processors.TransactionProcessorInterface; import zw.qantra.tm.rest.RestService; import zw.qantra.tm.utils.Utils; import java.util.LinkedHashMap; +import java.util.Objects; @Service("INTEGRATION_STEWARD") @RequiredArgsConstructor @@ -27,6 +29,7 @@ public class StewardIntegrationProcessor implements TransactionProcessorInterfac private final RestService restService; private final TransactionService transactionService; private final AdditionalDataService additionalDataService; + private final SettingService settingService; @Value("${sbz.aggregator.url}") private String aggregatorUrl; @@ -36,10 +39,20 @@ public class StewardIntegrationProcessor implements TransactionProcessorInterfac private String aggregatorPhone; @Value("${sbz.aggregator.account}") private String aggregatorAccount; + @Value("${powertel.clientid}") + private String powertelClientId; @Override @Transactional public Object process(Transaction transaction) throws Exception { + + if(settingService.getBooleanSetting("SIMULATE_INTEGRATION_FAILURE")){ + transaction.setStatus(Status.FAILED); + transaction.setResponseCode("92"); + transaction.setErrorMessage("Simulated failure"); + return transaction; + } + logger.info("processing integration"); String token = restService.getMerchantToken(); @@ -49,7 +62,7 @@ public class StewardIntegrationProcessor implements TransactionProcessorInterfac } BillPaymentDto request = BillPaymentDto.builder() - .type(RequestType.REQUEST) + .type(RequestType.CONFIRM) .billClientId(transaction.getBillClientId()) .debitRef(debitRef) .debitCurrency(transaction.getDebitCurrency()) @@ -60,14 +73,22 @@ public class StewardIntegrationProcessor implements TransactionProcessorInterfac .creditAccount(transaction.getCreditAccount()) // customer's zesa meter number .creditPhone(transaction.getCreditPhone()) // customer's contact phone number .billName(transaction.getBillName()) - .authType(transaction.getAuthType()) - .trace(transaction.getTrace()) .build(); + if(Objects.equals(powertelClientId, transaction.getBillClientId())) { + logger.info("send confirmation again"); + String url = aggregatorUrl + "/merchant/aggregation/transaction"; + LinkedHashMap response = restService.postWithToken(token, url, request, LinkedHashMap.class); + logger.info("response: {}", response.toString()); + } + + // once done, update and send request + request.setType(RequestType.REQUEST); + request.setAuthType(transaction.getAuthType()); + request.setTrace(transaction.getTrace()); + String url = aggregatorUrl + "/merchant/aggregation/transaction"; - LinkedHashMap response = restService.postWithToken(token, url, request, LinkedHashMap.class); - logger.info("response: {}", response.toString()); LinkedHashMap body = (LinkedHashMap) response.get("body"); diff --git a/src/main/java/zw/qantra/tm/domain/services/processors/payments/MPGSWebPaymentProcessor.java b/src/main/java/zw/qantra/tm/domain/services/processors/payments/MPGSWebPaymentProcessor.java index c6a5c39..71e30dd 100644 --- a/src/main/java/zw/qantra/tm/domain/services/processors/payments/MPGSWebPaymentProcessor.java +++ b/src/main/java/zw/qantra/tm/domain/services/processors/payments/MPGSWebPaymentProcessor.java @@ -148,6 +148,7 @@ public class MPGSWebPaymentProcessor implements TransactionProcessorInterface { } transaction.setStatus(Status.SUCCESS); + transaction.setPaymentStatus(Status.SUCCESS); transaction.setResponseCode("00"); transaction.setTargetUrl((String) body.get("targetUrl")); diff --git a/src/main/java/zw/qantra/tm/domain/workflows/TransactionWorkflow.java b/src/main/java/zw/qantra/tm/domain/workflows/TransactionWorkflow.java index 1d6abcd..0193713 100644 --- a/src/main/java/zw/qantra/tm/domain/workflows/TransactionWorkflow.java +++ b/src/main/java/zw/qantra/tm/domain/workflows/TransactionWorkflow.java @@ -46,29 +46,31 @@ public class TransactionWorkflow extends WorkflowDefinition { public static final State SALES_INVOICE = new State("salesInvoice"); public static final State JOURNAL_ENTRY = new State("journalEntry"); public static final State SALES_PAYMENT = new State("salesPayment"); - public static final State PURCHASE_INVOICE = new State("purchaseInvoice", WorkflowStateType.manual); + public static final State PURCHASE_INVOICE = new State("purchaseInvoice"); + public static final State PURCHASE_INVOICE_SUCCESS = new State("purchaseInvoiceSuccess", WorkflowStateType.manual); public static final State INTEGRATION = new State("integration"); public static final State PURCHASE_INVOICE_PAYMENT = new State("purchaseInvoicePayment"); - public static final State FAILED = new State("failed", WorkflowStateType.manual); + public static final State TRAN_FAILED = new State("failed", WorkflowStateType.manual); public static final State DONE = new State("done", WorkflowStateType.end); public TransactionWorkflow() { - super(TYPE, CALCULATE_CHARGES, FAILED); + super(TYPE, CALCULATE_CHARGES, TRAN_FAILED); permit(CALCULATE_CHARGES, CLEANUP); permit(CLEANUP, CONFIRM); - permit(CONFIRM, RECIPIENTS_UPDATE, FAILED); + permit(CONFIRM, RECIPIENTS_UPDATE, TRAN_FAILED); permit(RECIPIENTS_UPDATE, CONFIRM_SUCCESS); permit(CONFIRM_SUCCESS, GATEWAY_PAYMENT); - permit(GATEWAY_PAYMENT, GATEWAY_PAYMENT_SUCCESS, FAILED); + permit(GATEWAY_PAYMENT, GATEWAY_PAYMENT_SUCCESS, TRAN_FAILED); permit(GATEWAY_PAYMENT_SUCCESS, POLL_STATUS); - permit(POLL_STATUS, SALES_INVOICE, FAILED); + permit(POLL_STATUS, SALES_INVOICE, TRAN_FAILED); permit(SALES_INVOICE, JOURNAL_ENTRY); permit(JOURNAL_ENTRY, SALES_PAYMENT); permit(SALES_PAYMENT, PURCHASE_INVOICE); - permit(PURCHASE_INVOICE, INTEGRATION); - permit(INTEGRATION, PURCHASE_INVOICE_PAYMENT, FAILED); + permit(PURCHASE_INVOICE, PURCHASE_INVOICE_SUCCESS); + permit(PURCHASE_INVOICE_SUCCESS, INTEGRATION); + permit(INTEGRATION, PURCHASE_INVOICE_PAYMENT, TRAN_FAILED); permit(PURCHASE_INVOICE_PAYMENT, DONE); } @@ -78,13 +80,16 @@ public class TransactionWorkflow extends WorkflowDefinition { byte[] json = objectMapper.writeValueAsBytes(map); Transaction transaction = objectMapper.readValue(json, Transaction.class); - process(transaction, "calculateCharges"); + HandlerInterface handlerInterface = + (HandlerInterface) workflowHandlerFactory.getWorkflowHandler("calculateCharges"); + transaction = (Transaction) handlerInterface.process(transaction); + execution.setVariable("body", Utils.toJson(transaction)); return NextAction.moveToState(CLEANUP, "Charge calculation complete"); } catch (Exception e) { e.printStackTrace(); - return NextAction.moveToState(FAILED, e.getMessage()); + return NextAction.moveToState(TRAN_FAILED, e.getMessage()); } } @@ -94,13 +99,16 @@ public class TransactionWorkflow extends WorkflowDefinition { byte[] json = objectMapper.writeValueAsBytes(map); Transaction transaction = objectMapper.readValue(json, Transaction.class); - process(transaction, "cleanup"); + HandlerInterface handlerInterface = + (HandlerInterface) workflowHandlerFactory.getWorkflowHandler("cleanup"); + transaction = (Transaction) handlerInterface.process(transaction); + execution.setVariable("body", Utils.toJson(transaction)); return NextAction.moveToState(CONFIRM, "Cleanup complete"); } catch (Exception e) { e.printStackTrace(); - return NextAction.moveToState(FAILED, e.getMessage()); + return NextAction.moveToState(TRAN_FAILED, e.getMessage()); } } @@ -111,21 +119,26 @@ public class TransactionWorkflow extends WorkflowDefinition { Transaction transaction = objectMapper.readValue(json, Transaction.class); transaction.setWorkflowId(execution.getWorkflowInstanceId()); - transaction = process(transaction, "confirm"); + HandlerInterface handlerInterface = + (HandlerInterface) workflowHandlerFactory.getWorkflowHandler("confirm"); + transaction = (Transaction) handlerInterface.process(transaction); execution.setVariable("body", Utils.toJson(transaction)); return NextAction.moveToState(RECIPIENTS_UPDATE, "Recipients updated successfully"); } catch (Exception e) { e.printStackTrace(); - return NextAction.moveToState(FAILED, e.getMessage()); + return NextAction.moveToState(TRAN_FAILED, e.getMessage()); } } - public NextAction recipientsUpdate(StateExecution execution) throws IOException { + public NextAction recipientsUpdate(StateExecution execution) throws Exception { LinkedHashMap map = execution.getVariable("body", LinkedHashMap.class); byte[] json = objectMapper.writeValueAsBytes(map); Transaction transaction = objectMapper.readValue(json, Transaction.class); - process(transaction, "recipientsUpdate"); + HandlerInterface handlerInterface = + (HandlerInterface) workflowHandlerFactory.getWorkflowHandler("recipientsUpdate"); + handlerInterface.process(transaction); + return NextAction.moveToState(CONFIRM_SUCCESS, "Transaction confirmed successfully"); } @@ -140,12 +153,15 @@ public class TransactionWorkflow extends WorkflowDefinition { byte[] json = objectMapper.writeValueAsBytes(map); Transaction transaction = objectMapper.readValue(json, Transaction.class); - transaction = process(transaction, "gatewayPayment"); + HandlerInterface handlerInterface = + (HandlerInterface) workflowHandlerFactory.getWorkflowHandler("gatewayPayment"); + transaction = (Transaction) handlerInterface.process(transaction); + execution.setVariable("body", Utils.toJson(transaction)); return NextAction.moveToState(GATEWAY_PAYMENT_SUCCESS, "Gateway payment initiated"); } catch (Exception e) { e.printStackTrace(); - return NextAction.moveToState(FAILED, e.getMessage()); + return NextAction.moveToState(TRAN_FAILED, e.getMessage()); } } @@ -153,30 +169,37 @@ public class TransactionWorkflow extends WorkflowDefinition { log.info("Gateway payment initiation complete"); } - public NextAction pollStatus(StateExecution execution) { - try { - // cannot cast direct to Transaction object because of some jackson mapper hullabaloo :( - LinkedHashMap map = execution.getVariable("body", LinkedHashMap.class); - byte[] json = objectMapper.writeValueAsBytes(map); - Transaction transaction = objectMapper.readValue(json, Transaction.class); + public NextAction pollStatus(StateExecution execution) throws IOException { + // cannot cast direct to Transaction object because of some jackson mapper hullabaloo :( + LinkedHashMap map = execution.getVariable("body", LinkedHashMap.class); + byte[] json = objectMapper.writeValueAsBytes(map); + Transaction transaction = objectMapper.readValue(json, Transaction.class); + + try { + HandlerInterface handlerInterface = + (HandlerInterface) workflowHandlerFactory.getWorkflowHandler("pollStatus"); + transaction = (Transaction) handlerInterface.process(transaction); - transaction = process(transaction, "pollStatus"); execution.setVariable("body", Utils.toJson(transaction)); return NextAction.moveToState(SALES_INVOICE, "Polling complete"); } catch (Exception e) { - log.info(e.getCause().getMessage()); - return NextAction.moveToState(FAILED, e.getCause().getMessage()); + log.info(e.getMessage()); + execution.setVariable("body", Utils.toJson(transaction)); + return NextAction.moveToState(TRAN_FAILED, e.getMessage()); } } public NextAction salesInvoice(StateExecution execution) { try { // cannot cast direct to Transaction object because of some jackson mapper hullabaloo :( - LinkedHashMap map = execution.getVariable("request", LinkedHashMap.class); + LinkedHashMap map = execution.getVariable("body", LinkedHashMap.class); byte[] json = objectMapper.writeValueAsBytes(map); Transaction transaction = objectMapper.readValue(json, Transaction.class); - transaction = process(transaction, "salesInvoice"); + HandlerInterface handlerInterface = + (HandlerInterface) workflowHandlerFactory.getWorkflowHandler("salesInvoice"); + transaction = (Transaction) handlerInterface.process(transaction); + execution.setVariable("body", Utils.toJson(transaction)); return NextAction.moveToState(JOURNAL_ENTRY, "Sales invoice generated - id:" + transaction.getErpSalesRef()); @@ -192,7 +215,10 @@ public class TransactionWorkflow extends WorkflowDefinition { byte[] json = objectMapper.writeValueAsBytes(map); Transaction transaction = objectMapper.readValue(json, Transaction.class); - transaction = process(transaction, "journalEntry"); + HandlerInterface handlerInterface = + (HandlerInterface) workflowHandlerFactory.getWorkflowHandler("journalEntry"); + transaction = (Transaction) handlerInterface.process(transaction); + execution.setVariable("body", Utils.toJson(transaction)); return NextAction.moveToState(SALES_PAYMENT, "Journal Entry successful - id: " + transaction.getErpJournalRef()); @@ -208,7 +234,10 @@ public class TransactionWorkflow extends WorkflowDefinition { byte[] json = objectMapper.writeValueAsBytes(map); Transaction transaction = objectMapper.readValue(json, Transaction.class); - transaction = process(transaction, "salesPayment"); + HandlerInterface handlerInterface = + (HandlerInterface) workflowHandlerFactory.getWorkflowHandler("salesPayment"); + transaction = (Transaction) handlerInterface.process(transaction); + execution.setVariable("body", Utils.toJson(transaction)); return NextAction.moveToState(PURCHASE_INVOICE, "Sales payment successful - id: " + transaction.getErpSalesPaymentRef()); @@ -218,30 +247,46 @@ public class TransactionWorkflow extends WorkflowDefinition { } } - public void purchaseInvoice(StateExecution execution) throws IOException { - LinkedHashMap map = execution.getVariable("body", LinkedHashMap.class); - byte[] json = objectMapper.writeValueAsBytes(map); - Transaction transaction = objectMapper.readValue(json, Transaction.class); - - transaction = process(transaction, "purchaseInvoice"); - execution.setVariable("body", Utils.toJson(transaction)); - } - - public NextAction integration(StateExecution execution) { + public NextAction purchaseInvoice(StateExecution execution) throws Exception { try { LinkedHashMap map = execution.getVariable("body", LinkedHashMap.class); byte[] json = objectMapper.writeValueAsBytes(map); Transaction transaction = objectMapper.readValue(json, Transaction.class); - transaction = process(transaction, "integration"); + HandlerInterface handlerInterface = + (HandlerInterface) workflowHandlerFactory.getWorkflowHandler("purchaseInvoice"); + transaction = (Transaction) handlerInterface.process(transaction); + + execution.setVariable("body", Utils.toJson(transaction)); + return NextAction.moveToState(PURCHASE_INVOICE_SUCCESS, + "Purchase invoice successful - id: " + transaction.getErpPurchaseRef()); + + }catch (Exception e) { + e.printStackTrace(); + return NextAction.retryAfter(new DateTime().plusMinutes(1), e.getMessage()); + } + } + + public void purchaseInvoiceSuccess(StateExecution execution) { + log.info("Purchase invoice payment complete"); + } + + public NextAction integration(StateExecution execution) throws IOException { + LinkedHashMap map = execution.getVariable("body", LinkedHashMap.class); + byte[] json = objectMapper.writeValueAsBytes(map); + Transaction transaction = objectMapper.readValue(json, Transaction.class); + + try { + HandlerInterface handlerInterface = + (HandlerInterface) workflowHandlerFactory.getWorkflowHandler("integration"); + transaction = (Transaction) handlerInterface.process(transaction); + execution.setVariable("body", Utils.toJson(transaction)); return NextAction.moveToState(PURCHASE_INVOICE_PAYMENT, "Integration request successful"); - } catch (ApiException e) { - log.info(e.getMessage()); - return NextAction.moveToState(FAILED, e.getMessage()); } catch (Exception e) { log.info(e.getMessage()); - return NextAction.moveToState(FAILED, e.getMessage()); + execution.setVariable("body", Utils.toJson(transaction)); + return NextAction.moveToState(TRAN_FAILED, e.getMessage()); } } @@ -251,7 +296,10 @@ public class TransactionWorkflow extends WorkflowDefinition { byte[] json = objectMapper.writeValueAsBytes(map); Transaction transaction = objectMapper.readValue(json, Transaction.class); - transaction = process(transaction, "purchaseInvoicePayment"); + HandlerInterface handlerInterface = + (HandlerInterface) workflowHandlerFactory.getWorkflowHandler("purchaseInvoicePayment"); + transaction = (Transaction) handlerInterface.process(transaction); + execution.setVariable("body", Utils.toJson(transaction)); return NextAction.moveToState(DONE, "Purchase invoice payment generated - id: " + transaction.getErpPurchasePaymentRef()); @@ -260,21 +308,4 @@ public class TransactionWorkflow extends WorkflowDefinition { return NextAction.retryAfter(new DateTime().plusMinutes(1), e.getMessage()); } } - - public Transaction process(Transaction transaction, String beanName) { - HandlerInterface handlerInterface = - (HandlerInterface) workflowHandlerFactory.getWorkflowHandler(beanName); - try { - transaction = (Transaction) handlerInterface.process(transaction); - }catch (Exception e){ - e.printStackTrace(); - e.getCause().printStackTrace(); - transaction.setStatus(Status.FAILED); - transaction.setResponseCode("01"); - transaction.setErrorMessage(e.getMessage()); - transactionService.getTransactionRepository().save(transaction); - } - - return transaction; - } } diff --git a/src/main/java/zw/qantra/tm/domain/workflows/handlers/IntegrationHandler.java b/src/main/java/zw/qantra/tm/domain/workflows/handlers/IntegrationHandler.java index eac04a5..558f881 100644 --- a/src/main/java/zw/qantra/tm/domain/workflows/handlers/IntegrationHandler.java +++ b/src/main/java/zw/qantra/tm/domain/workflows/handlers/IntegrationHandler.java @@ -68,11 +68,13 @@ public class IntegrationHandler implements HandlerInterface { transactionEvent.setMessage(transaction.getErrorMessage()); transactionEventService.save(transactionEvent); + transaction.setIntegrationStatus(transaction.getStatus()); + if(transaction.getStatus() != Status.SUCCESS){ transactionService.save(transaction); throw new ApiException("Transaction failed: " + transaction.getErrorMessage() ); }else { - transaction.setIntegrationStatus(transaction.getStatus()); + transaction.setErrorMessage(null); } Transaction t1 = Utils.deepCopy(transaction, Transaction.class); diff --git a/src/main/java/zw/qantra/tm/domain/workflows/handlers/PollStatusHandler.java b/src/main/java/zw/qantra/tm/domain/workflows/handlers/PollStatusHandler.java index b453681..4b0884e 100644 --- a/src/main/java/zw/qantra/tm/domain/workflows/handlers/PollStatusHandler.java +++ b/src/main/java/zw/qantra/tm/domain/workflows/handlers/PollStatusHandler.java @@ -63,7 +63,6 @@ public class PollStatusHandler implements HandlerInterface { transaction.setErrorMessage(null); } - transactionService.save(transaction); - return transaction; + return transactionService.save(transaction); } } diff --git a/src/main/resources/application-lab.properties b/src/main/resources/application-lab.properties index 2e7e607..5839325 100644 --- a/src/main/resources/application-lab.properties +++ b/src/main/resources/application-lab.properties @@ -50,3 +50,5 @@ nflow.db.postgresql.driver=org.postgresql.Driver nflow.db.postgresql.url=jdbc:postgresql://173.212.247.232:5532/qpay nflow.db.postgresql.user=postgres nflow.db.postgresql.password=zdDZMzq6F4B4L1IUl + +powertel.clientid=powertel_zesa diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 93d5e33..eec13ee 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -65,3 +65,5 @@ spring.mail.username=notifications@qantra.co.zw spring.mail.password=QdZucpJMJIZ spring.mail.properties.mail.smtp.auth=true spring.mail.properties.mail.smtp.starttls.enable=true + +powertel.clientid=zesa_prepaid_usd \ No newline at end of file