From 3edd1f58ae8e36505370a9a6f2d9ce88e0e995d9 Mon Sep 17 00:00:00 2001 From: Apurb Rajdhan <103931815+apurbraj@users.noreply.github.com> Date: Wed, 14 Aug 2024 12:20:04 +0530 Subject: [PATCH 01/17] [setup]Delete config file of service (#5) * Delete config file of service Fix config file path address build issue * Fix * remove ci chart --- .circleci/config.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 15e00903..b04c4c3d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -2250,8 +2250,8 @@ jobs: echo "Deploying to environment..." # Add your deployment scripts/commands here echo "Deployment completed." - - + + workflows: version: 2 @@ -2462,4 +2462,3 @@ workflows: - Ngrok requires: - build-g2p-sandbox-ci-chart - From 05ed6194a39be2cfc7d9abcf6455e4ca57dad5c8 Mon Sep 17 00:00:00 2001 From: sourabh Date: Thu, 29 Aug 2024 10:40:27 +0530 Subject: [PATCH 02/17] [phee-718] Add MTN connector changes --- .../api/definition/TransactionApi.java | 6 +- .../TransactionApiController.java | 20 +++++- .../channel/camel/config/CamelProperties.java | 1 + .../camel/routes/ChannelRouteBuilder.java | 49 +++++++++---- .../channel/gsma_api/GsmaP2PResponseDto.java | 5 ++ .../channel/validator/HeaderValidator.java | 17 +++++ .../src/main/resources/application.yml | 4 ++ .../api/MtnCollectionApi.java | 58 ++++++++++++++++ .../mockpaymentschema/schema/MtnRtpDTO.java | 15 ++++ .../mockpaymentschema/schema/Payer.java | 13 ++++ .../schema/RequestToPayFailureResponse.java | 17 +++++ .../schema/RequestToPaySuccessResponse.java | 17 +++++ .../service/MtnCollectionService.java | 69 +++++++++++++++++++ .../src/main/resources/application.yml | 10 +++ .../cucumber/stepdef/MtnStepDef.java | 4 ++ .../src/test/java/resources/mtn.feature | 0 16 files changed, 287 insertions(+), 18 deletions(-) create mode 100644 ph-ee-connector-mock-payment-schema/src/main/java/org/mifos/connector/mockpaymentschema/api/MtnCollectionApi.java create mode 100644 ph-ee-connector-mock-payment-schema/src/main/java/org/mifos/connector/mockpaymentschema/schema/MtnRtpDTO.java create mode 100644 ph-ee-connector-mock-payment-schema/src/main/java/org/mifos/connector/mockpaymentschema/schema/Payer.java create mode 100644 ph-ee-connector-mock-payment-schema/src/main/java/org/mifos/connector/mockpaymentschema/schema/RequestToPayFailureResponse.java create mode 100644 ph-ee-connector-mock-payment-schema/src/main/java/org/mifos/connector/mockpaymentschema/schema/RequestToPaySuccessResponse.java create mode 100644 ph-ee-connector-mock-payment-schema/src/main/java/org/mifos/connector/mockpaymentschema/service/MtnCollectionService.java create mode 100644 ph-ee-integration-test/src/test/java/org/mifos/integrationtest/cucumber/stepdef/MtnStepDef.java create mode 100644 ph-ee-integration-test/src/test/java/resources/mtn.feature diff --git a/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/api/definition/TransactionApi.java b/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/api/definition/TransactionApi.java index cf151b52..31df059c 100644 --- a/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/api/definition/TransactionApi.java +++ b/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/api/definition/TransactionApi.java @@ -1,5 +1,6 @@ package org.mifos.connector.channel.api.definition; +import static org.mifos.connector.channel.camel.config.CamelProperties.CALLBACK_URL; import static org.mifos.connector.channel.camel.config.CamelProperties.CLIENTCORRELATIONID; import static org.mifos.connector.channel.zeebe.ZeebeVariables.TRANSACTION_ID; @@ -24,8 +25,9 @@ public interface TransactionApi { @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = "application/json", schema = @Schema(implementation = InvalidRequestBodyResponseDto.class))) }) @PostMapping("/channel/transactionRequest") ResponseEntity transaction(@RequestHeader(value = "Platform-TenantId") String tenant, - @RequestHeader(value = CLIENTCORRELATIONID, required = false) String correlationId, - @RequestBody TransactionChannelRequestDTO requestBody) throws JsonProcessingException; + @RequestHeader(value = CLIENTCORRELATIONID, required = false) String correlationId, + @RequestHeader(value = CALLBACK_URL, required = false) String callbackURL, + @RequestBody TransactionChannelRequestDTO requestBody) throws JsonProcessingException; @PostMapping("/channel/transaction/{" + TRANSACTION_ID + "}/resolve") void transactionResolve(@RequestBody String requestBody) throws JsonProcessingException; diff --git a/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/api/implementation/TransactionApiController.java b/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/api/implementation/TransactionApiController.java index 7f9bf005..dd15acac 100644 --- a/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/api/implementation/TransactionApiController.java +++ b/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/api/implementation/TransactionApiController.java @@ -9,6 +9,7 @@ import org.apache.camel.Exchange; import org.apache.camel.ProducerTemplate; import org.mifos.connector.channel.api.definition.TransactionApi; +import org.mifos.connector.channel.camel.routes.ChannelRouteBuilder; import org.mifos.connector.channel.gsma_api.GsmaP2PResponseDto; import org.mifos.connector.channel.service.ValidateHeaders; import org.mifos.connector.channel.utils.HeaderConstants; @@ -19,10 +20,13 @@ import org.mifos.connector.common.channel.dto.TransactionChannelRequestDTO; import org.mifos.connector.common.exception.ValidationException; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RestController; +import java.util.Objects; + @RestController public class TransactionApiController implements TransactionApi { @@ -30,11 +34,15 @@ public class TransactionApiController implements TransactionApi { ObjectMapper objectMapper; @Autowired private ProducerTemplate producerTemplate; + @Autowired + ChannelRouteBuilder routeBuilder; + @Value("${mtn-transaction-request.tenant}") + private String mtnTenant; @Override @ValidateHeaders(requiredHeaders = { HeaderConstants.PLATFORM_TENANT_ID, - HeaderConstants.CLIENT_CORRELATION_ID }, validatorClass = HeaderValidator.class, validationFunction = "validateTransactionRequest") - public ResponseEntity transaction(String tenant, String correlationId, TransactionChannelRequestDTO requestBody) + HeaderConstants.CLIENT_CORRELATION_ID , HeaderConstants.X_Callback_URL}, validatorClass = HeaderValidator.class, validationFunction = "validateTransactionRequest") + public ResponseEntity transaction(String tenant, String correlationId, String callbackURL, TransactionChannelRequestDTO requestBody) throws JsonProcessingException { try { @@ -45,6 +53,13 @@ public ResponseEntity transaction(String tenant, String corr Headers headers = new Headers.HeaderBuilder().addHeader("Platform-TenantId", tenant).addHeader(CLIENTCORRELATIONID, correlationId) .build(); + + if(Objects.equals(tenant, mtnTenant)) { + String transactionId = routeBuilder.mtnTxn(requestBody, mtnTenant, callbackURL); + GsmaP2PResponseDto responseDto = new GsmaP2PResponseDto(transactionId); + return ResponseEntity.status(HttpStatus.ACCEPTED).body(responseDto); + } + Exchange exchange = SpringWrapperUtil.getDefaultWrappedExchange(producerTemplate.getCamelContext(), headers, objectMapper.writeValueAsString(requestBody)); producerTemplate.send("direct:post-transaction-request", exchange); @@ -64,6 +79,5 @@ public void transactionResolve(String requestBody) throws JsonProcessingExceptio Headers headers = new Headers.HeaderBuilder().build(); Exchange exchange = SpringWrapperUtil.getDefaultWrappedExchange(producerTemplate.getCamelContext(), null, requestBody); producerTemplate.send("direct:post-transaction-resolve", exchange); - } } diff --git a/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/camel/config/CamelProperties.java b/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/camel/config/CamelProperties.java index cb00c7c2..77daaa25 100644 --- a/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/camel/config/CamelProperties.java +++ b/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/camel/config/CamelProperties.java @@ -16,5 +16,6 @@ private CamelProperties() {} public static final String PAYEE_DFSP_ID = "X-PayeeDFSP-ID"; public static final String X_CALLBACKURL = "X-CallbackURL"; public static final String COUNTRY = "X-Country"; + public static final String CALLBACK_URL = "X-CallbackURL"; } diff --git a/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/camel/routes/ChannelRouteBuilder.java b/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/camel/routes/ChannelRouteBuilder.java index c1b340e4..50c710cd 100644 --- a/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/camel/routes/ChannelRouteBuilder.java +++ b/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/camel/routes/ChannelRouteBuilder.java @@ -32,19 +32,6 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.exc.InvalidFormatException; import io.camunda.zeebe.client.ZeebeClient; -import java.nio.charset.StandardCharsets; -import java.time.Duration; -import java.time.Instant; -import java.time.LocalDateTime; -import java.time.ZoneId; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Spliterator; -import javax.net.ssl.HttpsURLConnection; import org.apache.camel.Exchange; import org.apache.camel.LoggingLevel; import org.apache.camel.component.bean.validator.BeanValidationException; @@ -62,6 +49,7 @@ import org.mifos.connector.channel.utils.AMSProps; import org.mifos.connector.channel.utils.AMSUtils; import org.mifos.connector.channel.utils.Constants; +import org.mifos.connector.channel.utils.HeaderConstants; import org.mifos.connector.channel.zeebe.ZeebeProcessStarter; import org.mifos.connector.common.camel.AuthProcessor; import org.mifos.connector.common.camel.AuthProperties; @@ -86,6 +74,25 @@ import org.springframework.web.reactive.function.client.WebClient; import org.springframework.web.util.UriComponentsBuilder; +import javax.net.ssl.HttpsURLConnection; +import java.nio.charset.StandardCharsets; +import java.time.Duration; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.util.*; + +import static java.util.Base64.getEncoder; +import static java.util.Spliterators.spliteratorUnknownSize; +import static java.util.stream.StreamSupport.stream; +import static org.mifos.connector.channel.camel.config.CamelProperties.*; +import static org.mifos.connector.channel.zeebe.ZeebeMessages.OPERATOR_MANUAL_RECOVERY; +import static org.mifos.connector.channel.zeebe.ZeebeVariables.*; +import static org.mifos.connector.common.mojaloop.type.InitiatorType.CONSUMER; +import static org.mifos.connector.common.mojaloop.type.Scenario.TRANSFER; +import static org.mifos.connector.common.mojaloop.type.TransactionRole.PAYEE; +import static org.mifos.connector.common.mojaloop.type.TransactionRole.PAYER; + @Component public class ChannelRouteBuilder extends ErrorHandlerRouteBuilder { @@ -103,6 +110,7 @@ public class ChannelRouteBuilder extends ErrorHandlerRouteBuilder { private String paymentTransferFlow; private String specialPaymentTransferFlow; private String transactionRequestFlow; + private String mtnTransactionRequestFlow; private String partyRegistration; private String inboundTransactionReqFlow; private String restAuthHost; @@ -127,6 +135,7 @@ public ChannelRouteBuilder(@Value("#{'${dfspids}'.split(',')}") List dfs @Value("${bpmn.flows.payment-transfer}") String paymentTransferFlow, @Value("${bpmn.flows.special-payment-transfer}") String specialPaymentTransferFlow, @Value("${bpmn.flows.transaction-request}") String transactionRequestFlow, + @Value("${bpmn.flows.mtn-transaction-request}") String mtnTransactionRequestFlow, @Value("${bpmn.flows.party-registration}") String partyRegistration, @Value("${bpmn.flows.inboundTransactionReq-flow}") String inboundTransactionReqFlow, @Value("${rest.authorization.host}") String restAuthHost, @Value("${operations.url}") String operationsUrl, @@ -163,6 +172,7 @@ public ChannelRouteBuilder(@Value("#{'${dfspids}'.split(',')}") List dfs this.restAuthHeader = restAuthHeader; this.operationsAuthEnabled = operationsAuthEnabled; this.destinationDfspId = destinationDfspId; + this.mtnTransactionRequestFlow = mtnTransactionRequestFlow; } @Override @@ -374,6 +384,19 @@ private void transferRoutes() { }); } + public String mtnTxn(TransactionChannelRequestDTO requestBody, String tenantId, String callbackURL) throws JsonProcessingException { + Map extraVariables = new HashMap<>(); + String body = objectMapper.writeValueAsString(requestBody); + extraVariables.put(HeaderConstants.X_Callback_URL, callbackURL); + + String tenantSpecificBpmn = mtnTransactionRequestFlow.replace("{dfspid}", tenantId); + + String transactionId = zeebeProcessStarter.startZeebeWorkflow(tenantSpecificBpmn, body, extraVariables); + + logger.debug("transactionId is : {}", transactionId); + return transactionId; + } + public ResponseEntity fetchApibyWorkflowKey(HttpEntity entity, long workflowInstanceKey) { return restTemplate.exchange(operationsUrl + "/transfer/" + workflowInstanceKey, HttpMethod.GET, entity, String.class); } diff --git a/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/gsma_api/GsmaP2PResponseDto.java b/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/gsma_api/GsmaP2PResponseDto.java index fc5415a2..a1574293 100644 --- a/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/gsma_api/GsmaP2PResponseDto.java +++ b/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/gsma_api/GsmaP2PResponseDto.java @@ -1,5 +1,10 @@ package org.mifos.connector.channel.gsma_api; +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@AllArgsConstructor public class GsmaP2PResponseDto { public String transactionId; diff --git a/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/validator/HeaderValidator.java b/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/validator/HeaderValidator.java index 00a98445..4ac2cd39 100644 --- a/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/validator/HeaderValidator.java +++ b/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/validator/HeaderValidator.java @@ -7,6 +7,8 @@ import java.util.List; import java.util.Set; import javax.servlet.http.HttpServletRequest; + +import lombok.extern.slf4j.Slf4j; import org.mifos.connector.channel.utils.ChannelValidatorsEnum; import org.mifos.connector.channel.utils.HeaderConstants; import org.mifos.connector.common.channel.dto.PhErrorDTO; @@ -16,6 +18,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; +@Slf4j @Component public class HeaderValidator { @@ -25,6 +28,9 @@ public class HeaderValidator { @Value("#{'${default_headers}'.split(',')}") private List defaultHeader; + @Value("${mtn-transaction-request.tenant}") + private String mtnTenant; + private static final String resource = "channelValidator"; public PhErrorDTO validateTransfer(Set requiredHeaders, HttpServletRequest request) { @@ -54,6 +60,17 @@ public PhErrorDTO validateTransactionRequest(Set requiredHeaders, HttpSe request.getHeader(HeaderConstants.PLATFORM_TENANT_ID), ChannelValidatorsEnum.INVALID_PLATFORM_TENANT_ID, 20, ChannelValidatorsEnum.INVALID_PLATFORM_TENANT_ID_LENGTH); + // Checks for X-CallbackURL + if (request.getHeader(HeaderConstants.PLATFORM_TENANT_ID).equals(mtnTenant)) { + validatorBuilder.validateFieldIsNullAndMaxLengthWithFailureCode(resource, HeaderConstants.X_Callback_URL, + request.getHeader(HeaderConstants.X_Callback_URL), ChannelValidatorsEnum.INVALID_X_CALLBACK_URL, 100, + ChannelValidatorsEnum.INVALID_X_CALLBACK_URL_LENGTH); + } else { + validatorBuilder.validateFieldIgnoreNullAndMaxLengthWithFailureCode(resource, HeaderConstants.X_Callback_URL, + request.getHeader(HeaderConstants.X_Callback_URL), 100, + ChannelValidatorsEnum.INVALID_X_CALLBACK_URL_LENGTH); + } + return handleValidationErrors(validatorBuilder); } diff --git a/ph-ee-connector-channel/src/main/resources/application.yml b/ph-ee-connector-channel/src/main/resources/application.yml index 86c543f8..6dbe72aa 100644 --- a/ph-ee-connector-channel/src/main/resources/application.yml +++ b/ph-ee-connector-channel/src/main/resources/application.yml @@ -56,6 +56,10 @@ bpmn: international-remittance-payee: "international_remittance_payee_process-{dfspid}" international-remittance-payer: "international_remittance_payer_process-{dfspid}" inboundTransactionReq-flow: "{ps}_flow_{ams}-{dfspid}" + mtn-transaction-request: "mtn_payee_transaction_request-{dfspid}" + +mtn-transaction-request: + tenant: "rhino" ams: groups: diff --git a/ph-ee-connector-mock-payment-schema/src/main/java/org/mifos/connector/mockpaymentschema/api/MtnCollectionApi.java b/ph-ee-connector-mock-payment-schema/src/main/java/org/mifos/connector/mockpaymentschema/api/MtnCollectionApi.java new file mode 100644 index 00000000..7de3d512 --- /dev/null +++ b/ph-ee-connector-mock-payment-schema/src/main/java/org/mifos/connector/mockpaymentschema/api/MtnCollectionApi.java @@ -0,0 +1,58 @@ +package org.mifos.connector.mockpaymentschema.api; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.extern.slf4j.Slf4j; +import org.mifos.connector.mockpaymentschema.schema.MtnRtpDTO; +import org.mifos.connector.mockpaymentschema.service.MtnCollectionService; +import org.mifos.connector.mockpaymentschema.service.SendCallbackService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.Objects; + +@Slf4j +@RestController +@RequestMapping("/mtn/collection") +public class MtnCollectionApi { + + @Autowired + private MtnCollectionService mtnService; + + @Autowired + private SendCallbackService callbackService; + + @Value("${mtn.contactpoint}") + private String mtnContactpoint; + + @Value("${mtn.endpoints.callback}") + private String callbackEndpoint; + + @Autowired + private ObjectMapper objectMapper; + + + @PostMapping("/v1_0/requesttopay") + public ResponseEntity requestToPay(@RequestBody MtnRtpDTO request) throws JsonProcessingException { + ResponseEntity response = mtnService.requestToPay(request); + + String callbackUrl = mtnContactpoint + callbackEndpoint; + callbackService.sendCallback(objectMapper.writeValueAsString(response.getBody()), callbackUrl); + + + return response; + } + + @GetMapping("/v1_0/requesttopay/{referenceId}") + public ResponseEntity getRequestToPayStatus(@PathVariable(name = "referenceId") String referenceId) throws + JsonProcessingException { + ResponseEntity response = mtnService.getRequestToPayStatus(referenceId); + + String callbackUrl = mtnContactpoint + callbackEndpoint; + callbackService.sendCallback(objectMapper.writeValueAsString(response.getBody()), callbackUrl); + + return response; + } +} diff --git a/ph-ee-connector-mock-payment-schema/src/main/java/org/mifos/connector/mockpaymentschema/schema/MtnRtpDTO.java b/ph-ee-connector-mock-payment-schema/src/main/java/org/mifos/connector/mockpaymentschema/schema/MtnRtpDTO.java new file mode 100644 index 00000000..a58e3767 --- /dev/null +++ b/ph-ee-connector-mock-payment-schema/src/main/java/org/mifos/connector/mockpaymentschema/schema/MtnRtpDTO.java @@ -0,0 +1,15 @@ +package org.mifos.connector.mockpaymentschema.schema; + +import lombok.*; + +@Setter +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class MtnRtpDTO { + private String amount; + private String currency; + private String externalId; + private Payer payer; +} diff --git a/ph-ee-connector-mock-payment-schema/src/main/java/org/mifos/connector/mockpaymentschema/schema/Payer.java b/ph-ee-connector-mock-payment-schema/src/main/java/org/mifos/connector/mockpaymentschema/schema/Payer.java new file mode 100644 index 00000000..172db5af --- /dev/null +++ b/ph-ee-connector-mock-payment-schema/src/main/java/org/mifos/connector/mockpaymentschema/schema/Payer.java @@ -0,0 +1,13 @@ +package org.mifos.connector.mockpaymentschema.schema; + +import lombok.*; + +@Getter +@Setter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class Payer { + private String partyIdType; + private String partyId; +} \ No newline at end of file diff --git a/ph-ee-connector-mock-payment-schema/src/main/java/org/mifos/connector/mockpaymentschema/schema/RequestToPayFailureResponse.java b/ph-ee-connector-mock-payment-schema/src/main/java/org/mifos/connector/mockpaymentschema/schema/RequestToPayFailureResponse.java new file mode 100644 index 00000000..657f1357 --- /dev/null +++ b/ph-ee-connector-mock-payment-schema/src/main/java/org/mifos/connector/mockpaymentschema/schema/RequestToPayFailureResponse.java @@ -0,0 +1,17 @@ +package org.mifos.connector.mockpaymentschema.schema; + +import lombok.*; + +@Getter +@Setter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class RequestToPayFailureResponse { + private String externalId; + private String amount; + private String currency; + private Payer payer; + private String status; + private String reason; +} diff --git a/ph-ee-connector-mock-payment-schema/src/main/java/org/mifos/connector/mockpaymentschema/schema/RequestToPaySuccessResponse.java b/ph-ee-connector-mock-payment-schema/src/main/java/org/mifos/connector/mockpaymentschema/schema/RequestToPaySuccessResponse.java new file mode 100644 index 00000000..ee2c4442 --- /dev/null +++ b/ph-ee-connector-mock-payment-schema/src/main/java/org/mifos/connector/mockpaymentschema/schema/RequestToPaySuccessResponse.java @@ -0,0 +1,17 @@ +package org.mifos.connector.mockpaymentschema.schema; + +import lombok.*; + +@Getter +@Setter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class RequestToPaySuccessResponse { + private String financialTransactionId; + private String externalId; + private String amount; + private String currency; + private Payer payer; + private String status; +} \ No newline at end of file diff --git a/ph-ee-connector-mock-payment-schema/src/main/java/org/mifos/connector/mockpaymentschema/service/MtnCollectionService.java b/ph-ee-connector-mock-payment-schema/src/main/java/org/mifos/connector/mockpaymentschema/service/MtnCollectionService.java new file mode 100644 index 00000000..d917e211 --- /dev/null +++ b/ph-ee-connector-mock-payment-schema/src/main/java/org/mifos/connector/mockpaymentschema/service/MtnCollectionService.java @@ -0,0 +1,69 @@ +package org.mifos.connector.mockpaymentschema.service; + + +import org.mifos.connector.mockpaymentschema.schema.MtnRtpDTO; +import org.mifos.connector.mockpaymentschema.schema.Payer; +import org.mifos.connector.mockpaymentschema.schema.RequestToPayFailureResponse; +import org.mifos.connector.mockpaymentschema.schema.RequestToPaySuccessResponse; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; + +import java.util.UUID; + +@Service +public class MtnCollectionService { + + @Value("${mtn.payerIdentifier.reject}") + private String rejectPayerId; + + @Value("${mtn.payerIdentifier.delay}") + private String callbackDelayPayerId; + + public ResponseEntity requestToPay(MtnRtpDTO requestBody) { + String partyId = requestBody.getPayer().getPartyIdType(); + if (partyId.equals(rejectPayerId)) { + RequestToPayFailureResponse failureResponse = converterForFailureResponse(requestBody); + return ResponseEntity.status(HttpStatus.ACCEPTED).body((T) failureResponse); + } + RequestToPaySuccessResponse successResponse = converterForSuccessfulResponse(requestBody); + return ResponseEntity.status(HttpStatus.ACCEPTED).body((T) successResponse); + } + + public ResponseEntity getRequestToPayStatus(String referenceId) { + Payer payer = Payer.builder() + .partyIdType("MSISDN") + .partyId(callbackDelayPayerId) + .build(); + + RequestToPaySuccessResponse response = RequestToPaySuccessResponse.builder().payer(payer).build(); + return ResponseEntity.status(HttpStatus.ACCEPTED).body((T) response); + } + + + private RequestToPayFailureResponse converterForFailureResponse(MtnRtpDTO requestToPayDTO) { + + return RequestToPayFailureResponse.builder() + .externalId(requestToPayDTO.getExternalId()) + .amount(requestToPayDTO.getAmount()) + .currency(requestToPayDTO.getCurrency()) + .payer(requestToPayDTO.getPayer()) + .status("FAILED") + .reason("APPROVAL_REJECTED") + .build(); + } + + private RequestToPaySuccessResponse converterForSuccessfulResponse(MtnRtpDTO requestToPayDTO) { + + String financialTransactionId = UUID.randomUUID().toString().replace("-", ""); + return RequestToPaySuccessResponse.builder() + .financialTransactionId(financialTransactionId) + .externalId(requestToPayDTO.getExternalId()) + .amount(requestToPayDTO.getAmount()) + .currency(requestToPayDTO.getCurrency()) + .payer(requestToPayDTO.getPayer()) + .status("SUCCESSFUL") + .build(); + } +} \ No newline at end of file diff --git a/ph-ee-connector-mock-payment-schema/src/main/resources/application.yml b/ph-ee-connector-mock-payment-schema/src/main/resources/application.yml index 3e85667b..19900b4b 100644 --- a/ph-ee-connector-mock-payment-schema/src/main/resources/application.yml +++ b/ph-ee-connector-mock-payment-schema/src/main/resources/application.yml @@ -42,6 +42,16 @@ async: threshold: amount: 20000 +mtn: + contactpoint: "http://localhost:8080" + endpoints: + callback: "/callback" + payerIdentifier: + reject: 46733123451 + delay: 46733123454 + failure: 46733123450 + + management: endpoint: health: diff --git a/ph-ee-integration-test/src/test/java/org/mifos/integrationtest/cucumber/stepdef/MtnStepDef.java b/ph-ee-integration-test/src/test/java/org/mifos/integrationtest/cucumber/stepdef/MtnStepDef.java new file mode 100644 index 00000000..f964d9d2 --- /dev/null +++ b/ph-ee-integration-test/src/test/java/org/mifos/integrationtest/cucumber/stepdef/MtnStepDef.java @@ -0,0 +1,4 @@ +package org.mifos.integrationtest.cucumber.stepdef; + +public class MtnStepDef { +} diff --git a/ph-ee-integration-test/src/test/java/resources/mtn.feature b/ph-ee-integration-test/src/test/java/resources/mtn.feature new file mode 100644 index 00000000..e69de29b From ab61f7aa65841eadec9616b7e0bcd89cf5f1f9c5 Mon Sep 17 00:00:00 2001 From: sourabh Date: Thu, 29 Aug 2024 10:57:03 +0530 Subject: [PATCH 03/17] Added spotless changes --- .../api/definition/TransactionApi.java | 6 ++-- .../TransactionApiController.java | 13 ++++----- .../camel/routes/ChannelRouteBuilder.java | 29 +++++++------------ .../channel/validator/HeaderValidator.java | 4 +-- 4 files changed, 20 insertions(+), 32 deletions(-) diff --git a/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/api/definition/TransactionApi.java b/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/api/definition/TransactionApi.java index 31df059c..f70987fa 100644 --- a/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/api/definition/TransactionApi.java +++ b/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/api/definition/TransactionApi.java @@ -25,9 +25,9 @@ public interface TransactionApi { @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = "application/json", schema = @Schema(implementation = InvalidRequestBodyResponseDto.class))) }) @PostMapping("/channel/transactionRequest") ResponseEntity transaction(@RequestHeader(value = "Platform-TenantId") String tenant, - @RequestHeader(value = CLIENTCORRELATIONID, required = false) String correlationId, - @RequestHeader(value = CALLBACK_URL, required = false) String callbackURL, - @RequestBody TransactionChannelRequestDTO requestBody) throws JsonProcessingException; + @RequestHeader(value = CLIENTCORRELATIONID, required = false) String correlationId, + @RequestHeader(value = CALLBACK_URL, required = false) String callbackURL, + @RequestBody TransactionChannelRequestDTO requestBody) throws JsonProcessingException; @PostMapping("/channel/transaction/{" + TRANSACTION_ID + "}/resolve") void transactionResolve(@RequestBody String requestBody) throws JsonProcessingException; diff --git a/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/api/implementation/TransactionApiController.java b/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/api/implementation/TransactionApiController.java index dd15acac..d6179527 100644 --- a/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/api/implementation/TransactionApiController.java +++ b/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/api/implementation/TransactionApiController.java @@ -6,6 +6,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import io.camunda.zeebe.client.api.command.ClientStatusException; import io.grpc.Status; +import java.util.Objects; import org.apache.camel.Exchange; import org.apache.camel.ProducerTemplate; import org.mifos.connector.channel.api.definition.TransactionApi; @@ -25,8 +26,6 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RestController; -import java.util.Objects; - @RestController public class TransactionApiController implements TransactionApi { @@ -40,10 +39,10 @@ public class TransactionApiController implements TransactionApi { private String mtnTenant; @Override - @ValidateHeaders(requiredHeaders = { HeaderConstants.PLATFORM_TENANT_ID, - HeaderConstants.CLIENT_CORRELATION_ID , HeaderConstants.X_Callback_URL}, validatorClass = HeaderValidator.class, validationFunction = "validateTransactionRequest") - public ResponseEntity transaction(String tenant, String correlationId, String callbackURL, TransactionChannelRequestDTO requestBody) - throws JsonProcessingException { + @ValidateHeaders(requiredHeaders = { HeaderConstants.PLATFORM_TENANT_ID, HeaderConstants.CLIENT_CORRELATION_ID, + HeaderConstants.X_Callback_URL }, validatorClass = HeaderValidator.class, validationFunction = "validateTransactionRequest") + public ResponseEntity transaction(String tenant, String correlationId, String callbackURL, + TransactionChannelRequestDTO requestBody) throws JsonProcessingException { try { ChannelValidator.validateTransfer(requestBody); @@ -54,7 +53,7 @@ public ResponseEntity transaction(String tenant, String corr Headers headers = new Headers.HeaderBuilder().addHeader("Platform-TenantId", tenant).addHeader(CLIENTCORRELATIONID, correlationId) .build(); - if(Objects.equals(tenant, mtnTenant)) { + if (Objects.equals(tenant, mtnTenant)) { String transactionId = routeBuilder.mtnTxn(requestBody, mtnTenant, callbackURL); GsmaP2PResponseDto responseDto = new GsmaP2PResponseDto(transactionId); return ResponseEntity.status(HttpStatus.ACCEPTED).body(responseDto); diff --git a/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/camel/routes/ChannelRouteBuilder.java b/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/camel/routes/ChannelRouteBuilder.java index 50c710cd..7b14d779 100644 --- a/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/camel/routes/ChannelRouteBuilder.java +++ b/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/camel/routes/ChannelRouteBuilder.java @@ -23,6 +23,9 @@ import static org.mifos.connector.channel.zeebe.ZeebeVariables.PAYMENT_SCHEME; import static org.mifos.connector.channel.zeebe.ZeebeVariables.TENANT_ID; import static org.mifos.connector.channel.zeebe.ZeebeVariables.TRANSACTION_ID; +import static org.mifos.connector.channel.camel.config.CamelProperties.*; +import static org.mifos.connector.channel.zeebe.ZeebeMessages.OPERATOR_MANUAL_RECOVERY; +import static org.mifos.connector.channel.zeebe.ZeebeVariables.*; import static org.mifos.connector.common.mojaloop.type.InitiatorType.CONSUMER; import static org.mifos.connector.common.mojaloop.type.Scenario.TRANSFER; import static org.mifos.connector.common.mojaloop.type.TransactionRole.PAYEE; @@ -32,6 +35,13 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.exc.InvalidFormatException; import io.camunda.zeebe.client.ZeebeClient; +import java.nio.charset.StandardCharsets; +import java.time.Duration; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.util.*; +import javax.net.ssl.HttpsURLConnection; import org.apache.camel.Exchange; import org.apache.camel.LoggingLevel; import org.apache.camel.component.bean.validator.BeanValidationException; @@ -74,25 +84,6 @@ import org.springframework.web.reactive.function.client.WebClient; import org.springframework.web.util.UriComponentsBuilder; -import javax.net.ssl.HttpsURLConnection; -import java.nio.charset.StandardCharsets; -import java.time.Duration; -import java.time.Instant; -import java.time.LocalDateTime; -import java.time.ZoneId; -import java.util.*; - -import static java.util.Base64.getEncoder; -import static java.util.Spliterators.spliteratorUnknownSize; -import static java.util.stream.StreamSupport.stream; -import static org.mifos.connector.channel.camel.config.CamelProperties.*; -import static org.mifos.connector.channel.zeebe.ZeebeMessages.OPERATOR_MANUAL_RECOVERY; -import static org.mifos.connector.channel.zeebe.ZeebeVariables.*; -import static org.mifos.connector.common.mojaloop.type.InitiatorType.CONSUMER; -import static org.mifos.connector.common.mojaloop.type.Scenario.TRANSFER; -import static org.mifos.connector.common.mojaloop.type.TransactionRole.PAYEE; -import static org.mifos.connector.common.mojaloop.type.TransactionRole.PAYER; - @Component public class ChannelRouteBuilder extends ErrorHandlerRouteBuilder { diff --git a/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/validator/HeaderValidator.java b/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/validator/HeaderValidator.java index 4ac2cd39..9906c0bb 100644 --- a/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/validator/HeaderValidator.java +++ b/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/validator/HeaderValidator.java @@ -7,7 +7,6 @@ import java.util.List; import java.util.Set; import javax.servlet.http.HttpServletRequest; - import lombok.extern.slf4j.Slf4j; import org.mifos.connector.channel.utils.ChannelValidatorsEnum; import org.mifos.connector.channel.utils.HeaderConstants; @@ -67,8 +66,7 @@ public PhErrorDTO validateTransactionRequest(Set requiredHeaders, HttpSe ChannelValidatorsEnum.INVALID_X_CALLBACK_URL_LENGTH); } else { validatorBuilder.validateFieldIgnoreNullAndMaxLengthWithFailureCode(resource, HeaderConstants.X_Callback_URL, - request.getHeader(HeaderConstants.X_Callback_URL), 100, - ChannelValidatorsEnum.INVALID_X_CALLBACK_URL_LENGTH); + request.getHeader(HeaderConstants.X_Callback_URL), 100, ChannelValidatorsEnum.INVALID_X_CALLBACK_URL_LENGTH); } return handleValidationErrors(validatorBuilder); From b1d90ae7b24d9968a3325d6d48ebf1617f07ae9a Mon Sep 17 00:00:00 2001 From: sourabh Date: Fri, 30 Aug 2024 10:57:50 +0530 Subject: [PATCH 04/17] Add helm config and integration test for mtn connector --- .../src/main/resources/application.yml | 2 +- .../ph-ee-engine/connector-mtn/Chart.yaml | 5 + .../connector-mtn/templates/clusterrole.yaml | 11 ++ .../templates/clusterrolebinding.yaml | 15 ++ .../connector-mtn/templates/deployment.yaml | 62 ++++++++ .../connector-mtn/templates/ingress.yaml | 49 ++++++ .../connector-mtn/templates/role.yaml | 14 ++ .../connector-mtn/templates/rolebinding.yaml | 15 ++ .../connector-mtn/templates/service.yaml | 18 +++ .../templates/serviceaccount.yaml | 12 ++ .../ph-ee-engine/connector-mtn/values.yaml | 41 +++++ .../src/main/resources/application-local.yml | 36 ++++- .../cucumber/stepdef/MtnStepDef.java | 143 +++++++++++++++++- .../src/test/java/resources/mtn.feature | 25 +++ 14 files changed, 444 insertions(+), 4 deletions(-) create mode 100644 ph-ee-env-template/helm/ph-ee-engine/connector-mtn/Chart.yaml create mode 100644 ph-ee-env-template/helm/ph-ee-engine/connector-mtn/templates/clusterrole.yaml create mode 100644 ph-ee-env-template/helm/ph-ee-engine/connector-mtn/templates/clusterrolebinding.yaml create mode 100644 ph-ee-env-template/helm/ph-ee-engine/connector-mtn/templates/deployment.yaml create mode 100644 ph-ee-env-template/helm/ph-ee-engine/connector-mtn/templates/ingress.yaml create mode 100644 ph-ee-env-template/helm/ph-ee-engine/connector-mtn/templates/role.yaml create mode 100644 ph-ee-env-template/helm/ph-ee-engine/connector-mtn/templates/rolebinding.yaml create mode 100644 ph-ee-env-template/helm/ph-ee-engine/connector-mtn/templates/service.yaml create mode 100644 ph-ee-env-template/helm/ph-ee-engine/connector-mtn/templates/serviceaccount.yaml create mode 100644 ph-ee-env-template/helm/ph-ee-engine/connector-mtn/values.yaml diff --git a/ph-ee-connector-mock-payment-schema/src/main/resources/application.yml b/ph-ee-connector-mock-payment-schema/src/main/resources/application.yml index 19900b4b..66bc0099 100644 --- a/ph-ee-connector-mock-payment-schema/src/main/resources/application.yml +++ b/ph-ee-connector-mock-payment-schema/src/main/resources/application.yml @@ -43,7 +43,7 @@ threshold: amount: 20000 mtn: - contactpoint: "http://localhost:8080" + contactpoint: "http://ph-ee-connector-mtn:80" endpoints: callback: "/callback" payerIdentifier: diff --git a/ph-ee-env-template/helm/ph-ee-engine/connector-mtn/Chart.yaml b/ph-ee-env-template/helm/ph-ee-engine/connector-mtn/Chart.yaml new file mode 100644 index 00000000..61276536 --- /dev/null +++ b/ph-ee-env-template/helm/ph-ee-engine/connector-mtn/Chart.yaml @@ -0,0 +1,5 @@ +apiVersion: v1 +description: ph_ee_connector_mtn +name: connector_mtn +version: 1.0.0 +appVersion: "1.0.0" \ No newline at end of file diff --git a/ph-ee-env-template/helm/ph-ee-engine/connector-mtn/templates/clusterrole.yaml b/ph-ee-env-template/helm/ph-ee-engine/connector-mtn/templates/clusterrole.yaml new file mode 100644 index 00000000..fe1a82b3 --- /dev/null +++ b/ph-ee-env-template/helm/ph-ee-engine/connector-mtn/templates/clusterrole.yaml @@ -0,0 +1,11 @@ +{{- if .Values.managedServiceAccount }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + # "namespace" omitted since ClusterRoles are not namespaced + name: ph-ee-connector-mtn-c-role +rules: + - apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "watch", "list"] + {{- end -}} diff --git a/ph-ee-env-template/helm/ph-ee-engine/connector-mtn/templates/clusterrolebinding.yaml b/ph-ee-env-template/helm/ph-ee-engine/connector-mtn/templates/clusterrolebinding.yaml new file mode 100644 index 00000000..0817592b --- /dev/null +++ b/ph-ee-env-template/helm/ph-ee-engine/connector-mtn/templates/clusterrolebinding.yaml @@ -0,0 +1,15 @@ +{{- if .Values.managedServiceAccount }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: ph-ee-connector-mtn-c-role-binding +subjects: + - kind: ServiceAccount + name: ph-ee-connector-mtn # name of your service account + namespace: {{ .Release.Namespace }} # this is the namespace your service account is in +roleRef: # referring to your ClusterRole + kind: ClusterRole + name: ph-ee-connector-mtn-c-role + apiGroup: rbac.authorization.k8s.io + + {{- end -}} diff --git a/ph-ee-env-template/helm/ph-ee-engine/connector-mtn/templates/deployment.yaml b/ph-ee-env-template/helm/ph-ee-engine/connector-mtn/templates/deployment.yaml new file mode 100644 index 00000000..5b7a81df --- /dev/null +++ b/ph-ee-env-template/helm/ph-ee-engine/connector-mtn/templates/deployment.yaml @@ -0,0 +1,62 @@ +{{- if .Values.enabled -}} + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: ph-ee-connector-mtn + labels: + app: ph-ee-connector-mtn +spec: + replicas: {{ .Values.replicas }} + selector: + matchLabels: + app: ph-ee-connector-mtn + template: + metadata: + labels: + app: ph-ee-connector-mtn + annotations: + {{- if .Values.deployment.annotations }} + {{ toYaml .Values.deployment.annotations | indent 8 }} + {{- end }} +spec: + initContainers: + #During this Pod's initialization, check that zeebe-gateway service is up and running before starting this pod + - name: check-zeebe-gateway-ready + image: busybox:latest + command: [ 'sh', '-c','until nc -vz {{ .Release.Name }}-zeebe-gateway 26500; do echo "Waiting for zeebe-gateway service"; sleep 2; done;' ] + containers: + - name: ph-ee-connector-mtn + image: "{{ .Values.image }}" + ports: + - containerPort: 5000 + imagePullPolicy: "{{ .Values.imagePullPolicy }}" + livenessProbe: + httpGet: + path: /actuator/health/liveness + port: 8080 + initialDelaySeconds: {{.Values.livenessProbe.initialDelaySeconds}} + periodSeconds: {{.Values.livenessProbe.periodSeconds}} + readinessProbe: + httpGet: + path: /actuator/health/readiness + port: 8080 + initialDelaySeconds: {{.Values.readinessProbe.initialDelaySeconds}} + periodSeconds: {{.Values.readinessProbe.periodSeconds}} + resources: + limits: + memory: "{{ .Values.limits.memory }}" + cpu: "{{ .Values.limits.cpu }}" + requests: + memory: "{{ .Values.requests.memory }}" + cpu: "{{ .Values.requests.cpu }}" + env: + - name: "loggingLevelRoot" + value: "{{ .Values.global.loggingLevelRoot }}" + {{- if .Values.extraEnvs | default .Values.deployment.extraEnvs }} + {{ toYaml ( .Values.extraEnvs | default .Values.deployment.extraEnvs ) | indent 10 }} + {{- end }} +envFrom: {{ toYaml ( .Values.envFrom | default .Values.deployment.envFrom ) | nindent 12 }} +securityContext: {{ toYaml ( .Values.podSecurityContext | default .Values.deployment.securityContext ) | nindent 12 }} + + {{- end }} diff --git a/ph-ee-env-template/helm/ph-ee-engine/connector-mtn/templates/ingress.yaml b/ph-ee-env-template/helm/ph-ee-engine/connector-mtn/templates/ingress.yaml new file mode 100644 index 00000000..054d387c --- /dev/null +++ b/ph-ee-env-template/helm/ph-ee-engine/connector-mtn/templates/ingress.yaml @@ -0,0 +1,49 @@ +{{- if .Values.ingress.enabled -}} + {{- $pathtype := .Values.ingress.pathtype -}} + {{- $ingressPath := .Values.ingress.path -}} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: ph-ee-connector-mtn + labels: + app: {{ .Chart.Name }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} + {{- with .Values.ingress.annotations }} +annotations: + {{ toYaml . | indent 4 }} + {{- end }} +spec: + {{- if .Values.ingress.className }} + ingressClassName: {{ .Values.ingress.className | quote }} + {{- end }} + {{- if .Values.ingress.tls }} +tls: + {{- if .ingressPath }} + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- else }} + {{ toYaml .Values.ingress.tls | indent 4 }} + {{- end }} + {{- end}} +rules: + {{- range .Values.ingress.hosts }} +- host: {{ .host }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + pathType: {{ $pathtype }} + backend: + service: + name: {{ .backend.service.name}} + port: + number: {{ .backend.service.port.number}} + {{- end }} + {{- end }} + {{- end }} diff --git a/ph-ee-env-template/helm/ph-ee-engine/connector-mtn/templates/role.yaml b/ph-ee-env-template/helm/ph-ee-engine/connector-mtn/templates/role.yaml new file mode 100644 index 00000000..f1234f20 --- /dev/null +++ b/ph-ee-env-template/helm/ph-ee-engine/connector-mtn/templates/role.yaml @@ -0,0 +1,14 @@ +{{- if .Values.managedServiceAccount }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: ph-ee-connector-mtn-role + namespace: {{ .Release.Namespace }} +rules: + - apiGroups: + - "" + resources: + - pods + - configmaps + verbs: ["get", "create", "update"] + {{- end -}} diff --git a/ph-ee-env-template/helm/ph-ee-engine/connector-mtn/templates/rolebinding.yaml b/ph-ee-env-template/helm/ph-ee-engine/connector-mtn/templates/rolebinding.yaml new file mode 100644 index 00000000..4c4bba5b --- /dev/null +++ b/ph-ee-env-template/helm/ph-ee-engine/connector-mtn/templates/rolebinding.yaml @@ -0,0 +1,15 @@ +{{- if .Values.managedServiceAccount }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: ph-ee-connector-mtn-role-binding + namespace: {{ .Release.Namespace }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: ph-ee-connector-mtn-role +subjects: + - kind: ServiceAccount + name: ph-ee-connector-mtn + namespace: {{ .Release.Namespace }} + {{- end -}} diff --git a/ph-ee-env-template/helm/ph-ee-engine/connector-mtn/templates/service.yaml b/ph-ee-env-template/helm/ph-ee-engine/connector-mtn/templates/service.yaml new file mode 100644 index 00000000..9a1043e4 --- /dev/null +++ b/ph-ee-env-template/helm/ph-ee-engine/connector-mtn/templates/service.yaml @@ -0,0 +1,18 @@ +{{- if .Values.enabled -}} +apiVersion: {{ .Values.service.apiversion }} +kind: Service +metadata: + labels: + app: ph-ee-connector-mtn + name: ph-ee-connector-mtn +spec: + ports: + - name: port + port: 80 + protocol: TCP + targetPort: 5000 + selector: + app: ph-ee-connector-mtn + sessionAffinity: None + type: ClusterIP + {{- end }} diff --git a/ph-ee-env-template/helm/ph-ee-engine/connector-mtn/templates/serviceaccount.yaml b/ph-ee-env-template/helm/ph-ee-engine/connector-mtn/templates/serviceaccount.yaml new file mode 100644 index 00000000..a814a4af --- /dev/null +++ b/ph-ee-env-template/helm/ph-ee-engine/connector-mtn/templates/serviceaccount.yaml @@ -0,0 +1,12 @@ +{{- if .Values.managedServiceAccount }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: ph-ee-connector-mtn + annotations: + {{- with .Values.serviceAccountAnnotations }} + {{- toYaml . | nindent 4 }} + {{- end }} + labels: + app: ph-ee-connector-mtn + {{- end -}} diff --git a/ph-ee-env-template/helm/ph-ee-engine/connector-mtn/values.yaml b/ph-ee-env-template/helm/ph-ee-engine/connector-mtn/values.yaml new file mode 100644 index 00000000..45522382 --- /dev/null +++ b/ph-ee-env-template/helm/ph-ee-engine/connector-mtn/values.yaml @@ -0,0 +1,41 @@ +service: + apiversion: "v1" + +secret: + apiversion: "v1" + +configmap: + apiversion: "v1" + +enabled: false +image: "" +loggingLevelRoot: "INFO" +limits: + cpu: "500m" + memory: "512M" +requests: + cpu: "100m" + memory: "256M" + +ingress: + enabled: false + annotations: {} + pathtype: ImplementationSpecific + hosts: + - host: "" + paths: + - path: / + tls: [] + +deployment: + apiVersion: "apps/v1" + annotations: + deployTime: "{{ .Values.deployTime }}" + +livenessProbe: + initialDelaySeconds: 20 + periodSeconds: 30 + +readinessProbe: + initialDelaySeconds: 20 + periodSeconds: 30 diff --git a/ph-ee-importer-rdbms/src/main/resources/application-local.yml b/ph-ee-importer-rdbms/src/main/resources/application-local.yml index e008e74a..a8362112 100644 --- a/ph-ee-importer-rdbms/src/main/resources/application-local.yml +++ b/ph-ee-importer-rdbms/src/main/resources/application-local.yml @@ -1331,5 +1331,37 @@ transfer: variableName: payerPartyId - field: errorInformation variableName: errorInformation - - + - name: mtn_payee_transaction_request + direction: INCOMING + type: TRANSACTION-REQUEST + transformers: + - field: amount + variableName: channelRequest + jsonPath: $.amount.amount + - field: currency + variableName: channelRequest + jsonPath: $.amount.currency + - field: payeePartyIdType + variableName: channelRequest + jsonPath: $.payee.partyIdInfo.partyIdType + - field: payeePartyId + variableName: channelRequest + jsonPath: $.payee.partyIdInfo.partyIdentifier + - field: payerPartyIdType + variableName: channelRequest + jsonPath: $.payer.partyIdInfo.partyIdType + - field: payerPartyId + variableName: channelRequest + jsonPath: $.payer.partyIdInfo.partyIdentifier + - field: transactionId + variableName: transactionId + - field: currency + variableName: currency + - field: batchId + variableName: batchId + - field: tenantId + variableName: tenantId + - field: errorInformation + variableName: errorInformation + - field: clientCorrelationId + variableName: clientCorrelationId diff --git a/ph-ee-integration-test/src/test/java/org/mifos/integrationtest/cucumber/stepdef/MtnStepDef.java b/ph-ee-integration-test/src/test/java/org/mifos/integrationtest/cucumber/stepdef/MtnStepDef.java index f964d9d2..c7f67c8a 100644 --- a/ph-ee-integration-test/src/test/java/org/mifos/integrationtest/cucumber/stepdef/MtnStepDef.java +++ b/ph-ee-integration-test/src/test/java/org/mifos/integrationtest/cucumber/stepdef/MtnStepDef.java @@ -1,4 +1,145 @@ package org.mifos.integrationtest.cucumber.stepdef; -public class MtnStepDef { +import com.github.tomakehurst.wiremock.stubbing.ServeEvent; +import io.cucumber.core.internal.com.fasterxml.jackson.core.JsonProcessingException; +import io.cucumber.core.internal.com.fasterxml.jackson.databind.JsonNode; +import io.cucumber.core.internal.com.fasterxml.jackson.databind.ObjectMapper; +import io.cucumber.java.en.And; +import io.cucumber.java.en.Given; +import io.cucumber.java.en.Then; +import io.cucumber.java.en.When; +import io.restassured.RestAssured; +import io.restassured.builder.ResponseSpecBuilder; +import io.restassured.specification.RequestSpecification; +import org.mifos.connector.common.channel.dto.TransactionChannelRequestDTO; +import org.mifos.connector.common.mojaloop.dto.MoneyData; +import org.mifos.connector.common.mojaloop.dto.Party; +import org.mifos.connector.common.mojaloop.type.IdentifierType; +import org.mifos.integrationtest.common.TransactionHelper; +import org.mifos.integrationtest.common.Utils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; + +import java.io.IOException; +import java.util.List; + +import static com.github.tomakehurst.wiremock.client.WireMock.getAllServeEvents; +import static com.google.common.truth.Truth.assertThat; +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.awaitility.Awaitility.await; + +public class MtnStepDef extends BaseStepDef{ + @Autowired + MockServerStepDef mockServerStepDef; + + @Autowired + ScenarioScopeState scenarioScopeState; + + Logger logger = LoggerFactory.getLogger(MtnStepDef.class); + + @Value("${tenantconfig.tenants.paymentbb1}") + private String tenant; + + private String tenantHeader = "Platform-TenantId"; + + @Given("I can create a TransactionChannelRequestDTO for MTN Transaction Request with PayerId {string}") + public void iCreateATransactionChannelRequestDTOForMtn(String payerId) { + TransactionHelper transactionHelper = new TransactionHelper(); + Party payer = transactionHelper.partyHelper(IdentifierType.MSISDN, payerId); + Party payee = transactionHelper.partyHelper(IdentifierType.MSISDN, "27710101999"); + MoneyData amount = transactionHelper.amountHelper("100", "SNR"); + TransactionChannelRequestDTO requestDTO = transactionHelper.transactionChannelRequestHelper(payer, payee, amount); + requestDTO.setClientRefId("123"); + ObjectMapper objectMapper = new ObjectMapper(); + + scenarioScopeState.payerIdentifier = payerId; + try { + scenarioScopeState.createTransactionChannelRequestBody = objectMapper.writeValueAsString(requestDTO); + } catch (Exception e) { + logger.error("An Exception occurred", e); + } + } + + @When("I call the transaction request API for MTN with expected status of {int}") + public void iCallTheTransactionRequestAPIForMtnWithExpectedStatusOf(int expectedStatus) { + RequestSpecification requestSpec = Utils.getDefaultSpec(); + + scenarioScopeState.tenant = tenant; + scenarioScopeState.response = RestAssured.given(requestSpec).header("Content-Type", "application/json") + .header(tenantHeader, scenarioScopeState.tenant) + .header("X-CallbackURL", identityMapperConfig.callbackURL) + .baseUri(channelConnectorConfig.channelConnectorContactPoint) + .body(scenarioScopeState.createTransactionChannelRequestBody).expect() + .spec(new ResponseSpecBuilder().expectStatusCode(expectedStatus).build()).when() + .post(channelConnectorConfig.transferReqEndpoint).andReturn().asString(); + + logger.info("Transaction Request Response: {}", scenarioScopeState.response); + } + + @When("I call the transaction request API for MTN with expected status of {int} and {string}") + public void iCallTheTransactionRequestAPIForMtnWithExpectedStatusOf(int expectedStatus, String stub) { + RequestSpecification requestSpec = Utils.getDefaultSpec(); + + scenarioScopeState.tenant = tenant; + scenarioScopeState.response = RestAssured.given(requestSpec).header("Content-Type", "application/json") + .header(tenantHeader, scenarioScopeState.tenant) + .header("X-CallbackURL", identityMapperConfig.callbackURL + stub) + .baseUri(channelConnectorConfig.channelConnectorContactPoint) + .body(scenarioScopeState.createTransactionChannelRequestBody).expect() + .spec(new ResponseSpecBuilder().expectStatusCode(expectedStatus).build()).when() + .post(channelConnectorConfig.transferReqEndpoint).andReturn().asString(); + + logger.info("Transaction Request Response: {}", scenarioScopeState.response); + } + + @Then("I should be able to extract response body from callback for mtn") + public void iShouldBeAbleToExtractResponseBodyFromCallbackForMtn() { + await().atMost(awaitMost, SECONDS).pollDelay(pollDelay, SECONDS).pollInterval(pollInterval, SECONDS).untilAsserted(() -> { + boolean flag = false; + JsonNode rootNode = null; + + List allServeEvents = getAllServeEvents(); + for (int i = allServeEvents.size() - 1; i >= 0; i--) { + ServeEvent request = allServeEvents.get(i); + if (!(request.getRequest().getBodyAsString()).isEmpty()) { + flag = true; + try { + rootNode = objectMapper.readTree(request.getRequest().getBody()); + logger.info("Rootnode value:" + rootNode); + assertThat(rootNode).isNotNull(); + } catch (IOException e) { + throw new RuntimeException(e); + } + + } + assertThat(flag).isTrue(); + + if (rootNode.has("financialTransactionId")) { + scenarioScopeState.callbackBody = request.getRequest().getBodyAsString(); + assertThat(scenarioScopeState.callbackBody.contains(scenarioScopeState.payerIdentifier)); + } + } + }); + } + + + + @And("I should have {string} and {string} in mtn callback response") + public void iShouldHaveAndInResponse(String status, String statusValue) { + assertThat(scenarioScopeState.callbackBody).contains(status); + assertThat(scenarioScopeState.callbackBody).contains(statusValue); + + } + + @Then("I set the header as invalid for mtn") + public void setTenantAsNull() { + scenarioScopeState.tenant = null; + } + + + + + } diff --git a/ph-ee-integration-test/src/test/java/resources/mtn.feature b/ph-ee-integration-test/src/test/java/resources/mtn.feature index e69de29b..f95300da 100644 --- a/ph-ee-integration-test/src/test/java/resources/mtn.feature +++ b/ph-ee-integration-test/src/test/java/resources/mtn.feature @@ -0,0 +1,25 @@ + +Feature: Mtn Flow Test + + Scenario: MTN Flow validation test + Given I can create a TransactionChannelRequestDTO for MTN Transaction Request with PayerId "" + Then I set the header as invalid for mtn + When I call the transaction request API for MTN with expected status of 400 + + Scenario: Mtn Flow Test for Successful Payment Response + When I can inject MockServer + Then I can start mock server + And I can register the stub with "/transactionRequest" endpoint for "PUT" request with status of 200 + Given I can create a TransactionChannelRequestDTO for MTN Transaction Request with PayerId "875621381" + When I call the transaction request API for MTN with expected status of 202 and "/transactionRequest" + Then I should be able to extract response body from callback for mtn + And I should have "status" and "SUCCESSFUL" in mtn callback response + + Scenario: Mtn Flow Test for Failed Payment Response + When I can inject MockServer + Then I can start mock server + And I can register the stub with "/transactionRequest" endpoint for "PUT" request with status of 200 + Given I can create a TransactionChannelRequestDTO for MTN Transaction Request with PayerId "46733123451" + When I call the transaction request API for MTN with expected status of 202 and "/transactionRequest" + Then I should be able to extract response body from callback for mtn + And I should have "status" and "FAILED" in mtn callback response \ No newline at end of file From c7e6c008cb1204680e2a4d69d4ca45f0425e1ecd Mon Sep 17 00:00:00 2001 From: sourabh Date: Mon, 2 Sep 2024 09:25:20 +0530 Subject: [PATCH 05/17] Fix checkstyle issue --- .../camel/routes/ChannelRouteBuilder.java | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/camel/routes/ChannelRouteBuilder.java b/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/camel/routes/ChannelRouteBuilder.java index 7b14d779..e25f22b1 100644 --- a/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/camel/routes/ChannelRouteBuilder.java +++ b/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/camel/routes/ChannelRouteBuilder.java @@ -24,8 +24,20 @@ import static org.mifos.connector.channel.zeebe.ZeebeVariables.TENANT_ID; import static org.mifos.connector.channel.zeebe.ZeebeVariables.TRANSACTION_ID; import static org.mifos.connector.channel.camel.config.CamelProperties.*; +import static org.mifos.connector.channel.camel.config.CamelProperties.PAYEE_DFSP_ID; +import static org.mifos.connector.channel.camel.config.CamelProperties.PAYMENT_SCHEME_HEADER; +import static org.mifos.connector.channel.camel.config.CamelProperties.REGISTERING_INSTITUTION_ID; import static org.mifos.connector.channel.zeebe.ZeebeMessages.OPERATOR_MANUAL_RECOVERY; -import static org.mifos.connector.channel.zeebe.ZeebeVariables.*; +import static org.mifos.connector.channel.zeebe.ZeebeVariables.ACCOUNT; +import static org.mifos.connector.channel.zeebe.ZeebeVariables.AMS; +import static org.mifos.connector.channel.zeebe.ZeebeVariables.CHANNEL_REQUEST; +import static org.mifos.connector.channel.zeebe.ZeebeVariables.IS_AUTHORISATION_REQUIRED; +import static org.mifos.connector.channel.zeebe.ZeebeVariables.IS_RTP_REQUEST; +import static org.mifos.connector.channel.zeebe.ZeebeVariables.PARTY_ID; +import static org.mifos.connector.channel.zeebe.ZeebeVariables.PARTY_ID_TYPE; +import static org.mifos.connector.channel.zeebe.ZeebeVariables.PAYMENT_SCHEME; +import static org.mifos.connector.channel.zeebe.ZeebeVariables.TENANT_ID; +import static org.mifos.connector.channel.zeebe.ZeebeVariables.TRANSACTION_ID; import static org.mifos.connector.common.mojaloop.type.InitiatorType.CONSUMER; import static org.mifos.connector.common.mojaloop.type.Scenario.TRANSFER; import static org.mifos.connector.common.mojaloop.type.TransactionRole.PAYEE; @@ -40,7 +52,13 @@ import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneId; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Spliterator; import javax.net.ssl.HttpsURLConnection; import org.apache.camel.Exchange; import org.apache.camel.LoggingLevel; From 0355670b20cbaa8e30e743688f3b286719a7bbc9 Mon Sep 17 00:00:00 2001 From: sourabh Date: Mon, 2 Sep 2024 10:17:02 +0530 Subject: [PATCH 06/17] Add Tc tags --- .../src/test/java/resources/mtn.feature | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/ph-ee-integration-test/src/test/java/resources/mtn.feature b/ph-ee-integration-test/src/test/java/resources/mtn.feature index f95300da..e11dbfed 100644 --- a/ph-ee-integration-test/src/test/java/resources/mtn.feature +++ b/ph-ee-integration-test/src/test/java/resources/mtn.feature @@ -1,12 +1,14 @@ Feature: Mtn Flow Test - Scenario: MTN Flow validation test + @gov + Scenario: MTN-001 MTN Flow validation test Given I can create a TransactionChannelRequestDTO for MTN Transaction Request with PayerId "" Then I set the header as invalid for mtn When I call the transaction request API for MTN with expected status of 400 - Scenario: Mtn Flow Test for Successful Payment Response + @gov + Scenario: MTN-002 Mtn Flow Test for Successful Payment Response When I can inject MockServer Then I can start mock server And I can register the stub with "/transactionRequest" endpoint for "PUT" request with status of 200 @@ -15,7 +17,8 @@ Feature: Mtn Flow Test Then I should be able to extract response body from callback for mtn And I should have "status" and "SUCCESSFUL" in mtn callback response - Scenario: Mtn Flow Test for Failed Payment Response + @gov + Scenario: MTN-003 Mtn Flow Test for Failed Payment Response When I can inject MockServer Then I can start mock server And I can register the stub with "/transactionRequest" endpoint for "PUT" request with status of 200 From 115f11800b75c735f45980c648983fe457ba8eab Mon Sep 17 00:00:00 2001 From: sourabh Date: Mon, 2 Sep 2024 19:20:42 +0530 Subject: [PATCH 07/17] Fix checkstyle issues --- .../cucumber/stepdef/MtnStepDef.java | 39 +++++++------------ 1 file changed, 14 insertions(+), 25 deletions(-) diff --git a/ph-ee-integration-test/src/test/java/org/mifos/integrationtest/cucumber/stepdef/MtnStepDef.java b/ph-ee-integration-test/src/test/java/org/mifos/integrationtest/cucumber/stepdef/MtnStepDef.java index c7f67c8a..d60f3427 100644 --- a/ph-ee-integration-test/src/test/java/org/mifos/integrationtest/cucumber/stepdef/MtnStepDef.java +++ b/ph-ee-integration-test/src/test/java/org/mifos/integrationtest/cucumber/stepdef/MtnStepDef.java @@ -1,7 +1,11 @@ package org.mifos.integrationtest.cucumber.stepdef; +import static com.github.tomakehurst.wiremock.client.WireMock.getAllServeEvents; +import static com.google.common.truth.Truth.assertThat; +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.awaitility.Awaitility.await; + import com.github.tomakehurst.wiremock.stubbing.ServeEvent; -import io.cucumber.core.internal.com.fasterxml.jackson.core.JsonProcessingException; import io.cucumber.core.internal.com.fasterxml.jackson.databind.JsonNode; import io.cucumber.core.internal.com.fasterxml.jackson.databind.ObjectMapper; import io.cucumber.java.en.And; @@ -11,6 +15,8 @@ import io.restassured.RestAssured; import io.restassured.builder.ResponseSpecBuilder; import io.restassured.specification.RequestSpecification; +import java.io.IOException; +import java.util.List; import org.mifos.connector.common.channel.dto.TransactionChannelRequestDTO; import org.mifos.connector.common.mojaloop.dto.MoneyData; import org.mifos.connector.common.mojaloop.dto.Party; @@ -22,15 +28,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import java.io.IOException; -import java.util.List; - -import static com.github.tomakehurst.wiremock.client.WireMock.getAllServeEvents; -import static com.google.common.truth.Truth.assertThat; -import static java.util.concurrent.TimeUnit.SECONDS; -import static org.awaitility.Awaitility.await; +public class MtnStepDef extends BaseStepDef { -public class MtnStepDef extends BaseStepDef{ @Autowired MockServerStepDef mockServerStepDef; @@ -68,11 +67,9 @@ public void iCallTheTransactionRequestAPIForMtnWithExpectedStatusOf(int expected scenarioScopeState.tenant = tenant; scenarioScopeState.response = RestAssured.given(requestSpec).header("Content-Type", "application/json") - .header(tenantHeader, scenarioScopeState.tenant) - .header("X-CallbackURL", identityMapperConfig.callbackURL) - .baseUri(channelConnectorConfig.channelConnectorContactPoint) - .body(scenarioScopeState.createTransactionChannelRequestBody).expect() - .spec(new ResponseSpecBuilder().expectStatusCode(expectedStatus).build()).when() + .header(tenantHeader, scenarioScopeState.tenant).header("X-CallbackURL", identityMapperConfig.callbackURL) + .baseUri(channelConnectorConfig.channelConnectorContactPoint).body(scenarioScopeState.createTransactionChannelRequestBody) + .expect().spec(new ResponseSpecBuilder().expectStatusCode(expectedStatus).build()).when() .post(channelConnectorConfig.transferReqEndpoint).andReturn().asString(); logger.info("Transaction Request Response: {}", scenarioScopeState.response); @@ -84,11 +81,9 @@ public void iCallTheTransactionRequestAPIForMtnWithExpectedStatusOf(int expected scenarioScopeState.tenant = tenant; scenarioScopeState.response = RestAssured.given(requestSpec).header("Content-Type", "application/json") - .header(tenantHeader, scenarioScopeState.tenant) - .header("X-CallbackURL", identityMapperConfig.callbackURL + stub) - .baseUri(channelConnectorConfig.channelConnectorContactPoint) - .body(scenarioScopeState.createTransactionChannelRequestBody).expect() - .spec(new ResponseSpecBuilder().expectStatusCode(expectedStatus).build()).when() + .header(tenantHeader, scenarioScopeState.tenant).header("X-CallbackURL", identityMapperConfig.callbackURL + stub) + .baseUri(channelConnectorConfig.channelConnectorContactPoint).body(scenarioScopeState.createTransactionChannelRequestBody) + .expect().spec(new ResponseSpecBuilder().expectStatusCode(expectedStatus).build()).when() .post(channelConnectorConfig.transferReqEndpoint).andReturn().asString(); logger.info("Transaction Request Response: {}", scenarioScopeState.response); @@ -124,8 +119,6 @@ public void iShouldBeAbleToExtractResponseBodyFromCallbackForMtn() { }); } - - @And("I should have {string} and {string} in mtn callback response") public void iShouldHaveAndInResponse(String status, String statusValue) { assertThat(scenarioScopeState.callbackBody).contains(status); @@ -138,8 +131,4 @@ public void setTenantAsNull() { scenarioScopeState.tenant = null; } - - - - } From ef8870be7a84fc7139c168cc621801ddb51e73fa Mon Sep 17 00:00:00 2001 From: sourabh Date: Tue, 3 Sep 2024 13:16:56 +0530 Subject: [PATCH 08/17] Update helm config --- ph-ee-env-template/helm/g2p-sandbox/values.yaml | 2 ++ .../helm/ph-ee-engine/connector-mtn/Chart.yaml | 4 ++-- ph-ee-env-template/helm/ph-ee-engine/requirements.yaml | 7 ++++++- ph-ee-env-template/helm/ph-ee-engine/values.yaml | 3 +++ 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/ph-ee-env-template/helm/g2p-sandbox/values.yaml b/ph-ee-env-template/helm/g2p-sandbox/values.yaml index f5cb072a..db3cc3bd 100644 --- a/ph-ee-env-template/helm/g2p-sandbox/values.yaml +++ b/ph-ee-env-template/helm/g2p-sandbox/values.yaml @@ -595,6 +595,8 @@ ph-ee-engine: enabled: true minio: enabled: true + connector-mtn: + enabled: true connector_airtel: enabled: true diff --git a/ph-ee-env-template/helm/ph-ee-engine/connector-mtn/Chart.yaml b/ph-ee-env-template/helm/ph-ee-engine/connector-mtn/Chart.yaml index 61276536..0071f735 100644 --- a/ph-ee-env-template/helm/ph-ee-engine/connector-mtn/Chart.yaml +++ b/ph-ee-env-template/helm/ph-ee-engine/connector-mtn/Chart.yaml @@ -1,5 +1,5 @@ apiVersion: v1 -description: ph_ee_connector_mtn -name: connector_mtn +description: ph-ee-connector-mtn +name: connector-mtn version: 1.0.0 appVersion: "1.0.0" \ No newline at end of file diff --git a/ph-ee-env-template/helm/ph-ee-engine/requirements.yaml b/ph-ee-env-template/helm/ph-ee-engine/requirements.yaml index e5857cb8..b376f7b3 100644 --- a/ph-ee-env-template/helm/ph-ee-engine/requirements.yaml +++ b/ph-ee-env-template/helm/ph-ee-engine/requirements.yaml @@ -128,4 +128,9 @@ dependencies: - name: ph-ee-connector version: 1.0.0 repository: "file://./connector-ph-ee-bulk" - condition: "ph-ee-connector.enabled" \ No newline at end of file + condition: "ph-ee-connector.enabled" + + - name: connector-mtn + version: 1.0.0 + repository: "file://./connector-mtn" + condition: "connector-mtn.enabled" \ No newline at end of file diff --git a/ph-ee-env-template/helm/ph-ee-engine/values.yaml b/ph-ee-env-template/helm/ph-ee-engine/values.yaml index 2c009331..40addd9f 100644 --- a/ph-ee-env-template/helm/ph-ee-engine/values.yaml +++ b/ph-ee-env-template/helm/ph-ee-engine/values.yaml @@ -2361,3 +2361,6 @@ minio: post_installation_job: enabled: false + +connector-mtn: + enabled: false From 93d3445e9652cfa0686a75ca88eb0307ffb7c7a0 Mon Sep 17 00:00:00 2001 From: sourabh Date: Tue, 3 Sep 2024 14:31:24 +0530 Subject: [PATCH 09/17] Update helm config --- ph-ee-env-template/helm/g2p-sandbox/values.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/ph-ee-env-template/helm/g2p-sandbox/values.yaml b/ph-ee-env-template/helm/g2p-sandbox/values.yaml index db3cc3bd..2295a922 100644 --- a/ph-ee-env-template/helm/g2p-sandbox/values.yaml +++ b/ph-ee-env-template/helm/g2p-sandbox/values.yaml @@ -597,6 +597,7 @@ ph-ee-engine: enabled: true connector-mtn: enabled: true + image: docker.io/fynarfin/ph-ee-connector-mtn:latest connector_airtel: enabled: true From b1a9f6c22e5b0d2227ee3278503c33aab0e8e22f Mon Sep 17 00:00:00 2001 From: sourabh Date: Tue, 3 Sep 2024 18:43:12 +0530 Subject: [PATCH 10/17] Enable remote access --- .circleci/config.yml | 116 +++++++++++++++++++++---------------------- 1 file changed, 58 insertions(+), 58 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index b04c4c3d..0ee48d02 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -294,64 +294,64 @@ jobs: kubectl create namespace paymenthub kubectl get -A namespace - # # For remote access to minikube uncomment the following lines. - # #---------------------minikube remote aceess start--------------------- - # sudo apt install nginx - # sudo touch /etc/nginx/conf.d/minikube.conf - # echo "create nginx conf" - # sudo chmod 777 -R /etc/nginx/conf.d/ - # echo "changed access" - - # sudo apt-get install apache2-utils -y - # echo "apache2-utils installed" - # htpasswd -bc /home/circleci/project/.htpasswd minikube minikube - - # sudo cat \< /etc/nginx/conf.d/minikube.conf - # server { - # listen 8080; - # listen [::]:8080; - # server_name localhost; - # access_log /home/circleci/project/nginx_access.log; - # auth_basic "Administrators Area"; - # auth_basic_user_file /home/circleci/project/.htpasswd; - - # location / { - # proxy_pass https://$MINIKUBE_IP:8443; - # proxy_ssl_certificate /home/circleci/.minikube/profiles/minikube/client.crt; - # proxy_ssl_certificate_key /home/circleci/.minikube/profiles/minikube/client.key; - # } - # } - # EOF - # sudo service nginx restart || echo 'start nginx' - # SYSTEMD_LESS=FRXMK systemctl status nginx.service - - # sleep 10 - - # echo "test-nginx-proxy" - # curl -u minikube:minikube http://localhost:8080 - - # curl -s https://ngrok-agent.s3.amazonaws.com/ngrok.asc | sudo tee /etc/apt/trusted.gpg.d/ngrok.asc >/dev/null && echo "deb https://ngrok-agent.s3.amazonaws.com buster main" | sudo tee /etc/apt/sources.list.d/ngrok.list && sudo apt update && sudo apt install ngrok - # ngrok config add-authtoken $AUTH_TOKEN - # echo "web_addr: $LOCAL_PORT" >> /home/circleci/.config/ngrok/ngrok.yml - # ngrok http 8080 > /dev/null & - - # echo -n "Extracting ngrok public url ." - # NGROK_PUBLIC_URL="" - # while [ -z "$NGROK_PUBLIC_URL" ]; do - # # Run 'curl' against ngrok API and extract public (using 'sed' command) - # export NGROK_PUBLIC_URL=$(curl --silent --max-time 10 --connect-timeout 5 \ - # --show-error http://127.0.0.1:$LOCAL_PORT/api/tunnels | \ - # sed -nE 's/.*public_url":"https:..([^"]*).*/\1/p') - # sleep 1 - # echo -n "." - # done - # echo ---------copy the below public_URL for NGrok---------- - # echo "https://$NGROK_PUBLIC_URL" - # echo "https://$NGROK_PUBLIC_URL" - - # echo "test ngrok " - # curl -u minikube:minikube https://$NGROK_PUBLIC_URL - # echo "https://$NGROK_PUBLIC_URL" + # For remote access to minikube uncomment the following lines. + #---------------------minikube remote aceess start--------------------- + sudo apt install nginx + sudo touch /etc/nginx/conf.d/minikube.conf + echo "create nginx conf" + sudo chmod 777 -R /etc/nginx/conf.d/ + echo "changed access" + + sudo apt-get install apache2-utils -y + echo "apache2-utils installed" + htpasswd -bc /home/circleci/project/.htpasswd minikube minikube + + sudo cat \< /etc/nginx/conf.d/minikube.conf + server { + listen 8080; + listen [::]:8080; + server_name localhost; + access_log /home/circleci/project/nginx_access.log; + auth_basic "Administrators Area"; + auth_basic_user_file /home/circleci/project/.htpasswd; + + location / { + proxy_pass https://$MINIKUBE_IP:8443; + proxy_ssl_certificate /home/circleci/.minikube/profiles/minikube/client.crt; + proxy_ssl_certificate_key /home/circleci/.minikube/profiles/minikube/client.key; + } + } + EOF + sudo service nginx restart || echo 'start nginx' + SYSTEMD_LESS=FRXMK systemctl status nginx.service + + sleep 10 + + echo "test-nginx-proxy" + curl -u minikube:minikube http://localhost:8080 + + curl -s https://ngrok-agent.s3.amazonaws.com/ngrok.asc | sudo tee /etc/apt/trusted.gpg.d/ngrok.asc >/dev/null && echo "deb https://ngrok-agent.s3.amazonaws.com buster main" | sudo tee /etc/apt/sources.list.d/ngrok.list && sudo apt update && sudo apt install ngrok + ngrok config add-authtoken $AUTH_TOKEN + echo "web_addr: $LOCAL_PORT" >> /home/circleci/.config/ngrok/ngrok.yml + ngrok http 8080 > /dev/null & + + echo -n "Extracting ngrok public url ." + NGROK_PUBLIC_URL="" + while [ -z "$NGROK_PUBLIC_URL" ]; do + # Run 'curl' against ngrok API and extract public (using 'sed' command) + export NGROK_PUBLIC_URL=$(curl --silent --max-time 10 --connect-timeout 5 \ + --show-error http://127.0.0.1:$LOCAL_PORT/api/tunnels | \ + sed -nE 's/.*public_url":"https:..([^"]*).*/\1/p') + sleep 1 + echo -n "." + done + echo ---------copy the below public_URL for NGrok---------- + echo "https://$NGROK_PUBLIC_URL" + echo "https://$NGROK_PUBLIC_URL" + + echo "test ngrok " + curl -u minikube:minikube https://$NGROK_PUBLIC_URL + echo "https://$NGROK_PUBLIC_URL" # # ---------------------minikube remote access end--------------------- curl https://baltocdn.com/helm/signing.asc | gpg --dearmor | sudo tee /usr/share/keyrings/helm.gpg > /dev/null From e9e24510c5180f1bd9557c2d5ab786746a808708 Mon Sep 17 00:00:00 2001 From: sourabh Date: Thu, 5 Sep 2024 18:25:01 +0530 Subject: [PATCH 11/17] Update CI token --- ph-ee-env-template/.circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ph-ee-env-template/.circleci/config.yml b/ph-ee-env-template/.circleci/config.yml index b320e600..611d4124 100644 --- a/ph-ee-env-template/.circleci/config.yml +++ b/ph-ee-env-template/.circleci/config.yml @@ -327,7 +327,7 @@ jobs: # curl -u minikube:minikube http://localhost:8080 # curl -s https://ngrok-agent.s3.amazonaws.com/ngrok.asc | sudo tee /etc/apt/trusted.gpg.d/ngrok.asc >/dev/null && echo "deb https://ngrok-agent.s3.amazonaws.com buster main" | sudo tee /etc/apt/sources.list.d/ngrok.list && sudo apt update && sudo apt install ngrok - # ngrok config add-authtoken $AUTH_TOKEN + # ngrok config add-authtoken 2ZnrKw4YOaVLAUMniCIIIhNQuol_7D3RTeSgeJNSikR4sVtWc # echo "web_addr: $LOCAL_PORT" >> /home/circleci/.config/ngrok/ngrok.yml # ngrok http 8080 > /dev/null & From c242387649f291433df3f8882b19d6507ee7ff5d Mon Sep 17 00:00:00 2001 From: sourabh Date: Thu, 5 Sep 2024 19:17:31 +0530 Subject: [PATCH 12/17] Reset config --- ph-ee-env-template/.circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ph-ee-env-template/.circleci/config.yml b/ph-ee-env-template/.circleci/config.yml index 611d4124..b320e600 100644 --- a/ph-ee-env-template/.circleci/config.yml +++ b/ph-ee-env-template/.circleci/config.yml @@ -327,7 +327,7 @@ jobs: # curl -u minikube:minikube http://localhost:8080 # curl -s https://ngrok-agent.s3.amazonaws.com/ngrok.asc | sudo tee /etc/apt/trusted.gpg.d/ngrok.asc >/dev/null && echo "deb https://ngrok-agent.s3.amazonaws.com buster main" | sudo tee /etc/apt/sources.list.d/ngrok.list && sudo apt update && sudo apt install ngrok - # ngrok config add-authtoken 2ZnrKw4YOaVLAUMniCIIIhNQuol_7D3RTeSgeJNSikR4sVtWc + # ngrok config add-authtoken $AUTH_TOKEN # echo "web_addr: $LOCAL_PORT" >> /home/circleci/.config/ngrok/ngrok.yml # ngrok http 8080 > /dev/null & From 5d1eaf103aeca06d4c8a739cdc1589edac2806ef Mon Sep 17 00:00:00 2001 From: sourabh Date: Wed, 11 Sep 2024 12:03:36 +0530 Subject: [PATCH 13/17] Fix checkstyle issue --- .../camel/routes/ChannelRouteBuilder.java | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/camel/routes/ChannelRouteBuilder.java b/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/camel/routes/ChannelRouteBuilder.java index e25f22b1..1ef2d06c 100644 --- a/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/camel/routes/ChannelRouteBuilder.java +++ b/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/camel/routes/ChannelRouteBuilder.java @@ -3,6 +3,7 @@ import static java.util.Base64.getEncoder; import static java.util.Spliterators.spliteratorUnknownSize; import static java.util.stream.StreamSupport.stream; +import static org.mifos.connector.channel.camel.config.CamelProperties.*; import static org.mifos.connector.channel.camel.config.CamelProperties.AUTH_TYPE; import static org.mifos.connector.channel.camel.config.CamelProperties.BATCH_ID; import static org.mifos.connector.channel.camel.config.CamelProperties.CLIENTCORRELATIONID; @@ -23,21 +24,6 @@ import static org.mifos.connector.channel.zeebe.ZeebeVariables.PAYMENT_SCHEME; import static org.mifos.connector.channel.zeebe.ZeebeVariables.TENANT_ID; import static org.mifos.connector.channel.zeebe.ZeebeVariables.TRANSACTION_ID; -import static org.mifos.connector.channel.camel.config.CamelProperties.*; -import static org.mifos.connector.channel.camel.config.CamelProperties.PAYEE_DFSP_ID; -import static org.mifos.connector.channel.camel.config.CamelProperties.PAYMENT_SCHEME_HEADER; -import static org.mifos.connector.channel.camel.config.CamelProperties.REGISTERING_INSTITUTION_ID; -import static org.mifos.connector.channel.zeebe.ZeebeMessages.OPERATOR_MANUAL_RECOVERY; -import static org.mifos.connector.channel.zeebe.ZeebeVariables.ACCOUNT; -import static org.mifos.connector.channel.zeebe.ZeebeVariables.AMS; -import static org.mifos.connector.channel.zeebe.ZeebeVariables.CHANNEL_REQUEST; -import static org.mifos.connector.channel.zeebe.ZeebeVariables.IS_AUTHORISATION_REQUIRED; -import static org.mifos.connector.channel.zeebe.ZeebeVariables.IS_RTP_REQUEST; -import static org.mifos.connector.channel.zeebe.ZeebeVariables.PARTY_ID; -import static org.mifos.connector.channel.zeebe.ZeebeVariables.PARTY_ID_TYPE; -import static org.mifos.connector.channel.zeebe.ZeebeVariables.PAYMENT_SCHEME; -import static org.mifos.connector.channel.zeebe.ZeebeVariables.TENANT_ID; -import static org.mifos.connector.channel.zeebe.ZeebeVariables.TRANSACTION_ID; import static org.mifos.connector.common.mojaloop.type.InitiatorType.CONSUMER; import static org.mifos.connector.common.mojaloop.type.Scenario.TRANSFER; import static org.mifos.connector.common.mojaloop.type.TransactionRole.PAYEE; From a275343e678b4c4d8785f7e45f93d0721f5da34a Mon Sep 17 00:00:00 2001 From: sourabh Date: Wed, 11 Sep 2024 12:06:36 +0530 Subject: [PATCH 14/17] Fix checkstyle issue --- .../connector/channel/camel/routes/ChannelRouteBuilder.java | 1 - 1 file changed, 1 deletion(-) diff --git a/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/camel/routes/ChannelRouteBuilder.java b/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/camel/routes/ChannelRouteBuilder.java index 1ef2d06c..45f8c617 100644 --- a/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/camel/routes/ChannelRouteBuilder.java +++ b/ph-ee-connector-channel/src/main/java/org/mifos/connector/channel/camel/routes/ChannelRouteBuilder.java @@ -3,7 +3,6 @@ import static java.util.Base64.getEncoder; import static java.util.Spliterators.spliteratorUnknownSize; import static java.util.stream.StreamSupport.stream; -import static org.mifos.connector.channel.camel.config.CamelProperties.*; import static org.mifos.connector.channel.camel.config.CamelProperties.AUTH_TYPE; import static org.mifos.connector.channel.camel.config.CamelProperties.BATCH_ID; import static org.mifos.connector.channel.camel.config.CamelProperties.CLIENTCORRELATIONID; From ff01de818737309b45b6facc2302522c23f467fd Mon Sep 17 00:00:00 2001 From: sourabh Date: Wed, 11 Sep 2024 12:57:49 +0530 Subject: [PATCH 15/17] Restore config --- .circleci/config.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 0ee48d02..0ef543ba 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -2462,3 +2462,4 @@ workflows: - Ngrok requires: - build-g2p-sandbox-ci-chart + - From 3836f648e00e76ae5096de0f854a399c1c4c2093 Mon Sep 17 00:00:00 2001 From: sourabh Date: Wed, 11 Sep 2024 13:00:28 +0530 Subject: [PATCH 16/17] Restore config --- .circleci/config.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 0ef543ba..0ee48d02 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -2462,4 +2462,3 @@ workflows: - Ngrok requires: - build-g2p-sandbox-ci-chart - - From fbba332eab7f26c32c28ace6795c3b24b1799a48 Mon Sep 17 00:00:00 2001 From: sourabh Date: Wed, 11 Sep 2024 14:14:20 +0530 Subject: [PATCH 17/17] Restore config --- .circleci/config.yml | 121 ++++++++++++++++++++++--------------------- 1 file changed, 61 insertions(+), 60 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 0ee48d02..15e00903 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -294,64 +294,64 @@ jobs: kubectl create namespace paymenthub kubectl get -A namespace - # For remote access to minikube uncomment the following lines. - #---------------------minikube remote aceess start--------------------- - sudo apt install nginx - sudo touch /etc/nginx/conf.d/minikube.conf - echo "create nginx conf" - sudo chmod 777 -R /etc/nginx/conf.d/ - echo "changed access" - - sudo apt-get install apache2-utils -y - echo "apache2-utils installed" - htpasswd -bc /home/circleci/project/.htpasswd minikube minikube - - sudo cat \< /etc/nginx/conf.d/minikube.conf - server { - listen 8080; - listen [::]:8080; - server_name localhost; - access_log /home/circleci/project/nginx_access.log; - auth_basic "Administrators Area"; - auth_basic_user_file /home/circleci/project/.htpasswd; - - location / { - proxy_pass https://$MINIKUBE_IP:8443; - proxy_ssl_certificate /home/circleci/.minikube/profiles/minikube/client.crt; - proxy_ssl_certificate_key /home/circleci/.minikube/profiles/minikube/client.key; - } - } - EOF - sudo service nginx restart || echo 'start nginx' - SYSTEMD_LESS=FRXMK systemctl status nginx.service - - sleep 10 - - echo "test-nginx-proxy" - curl -u minikube:minikube http://localhost:8080 - - curl -s https://ngrok-agent.s3.amazonaws.com/ngrok.asc | sudo tee /etc/apt/trusted.gpg.d/ngrok.asc >/dev/null && echo "deb https://ngrok-agent.s3.amazonaws.com buster main" | sudo tee /etc/apt/sources.list.d/ngrok.list && sudo apt update && sudo apt install ngrok - ngrok config add-authtoken $AUTH_TOKEN - echo "web_addr: $LOCAL_PORT" >> /home/circleci/.config/ngrok/ngrok.yml - ngrok http 8080 > /dev/null & - - echo -n "Extracting ngrok public url ." - NGROK_PUBLIC_URL="" - while [ -z "$NGROK_PUBLIC_URL" ]; do - # Run 'curl' against ngrok API and extract public (using 'sed' command) - export NGROK_PUBLIC_URL=$(curl --silent --max-time 10 --connect-timeout 5 \ - --show-error http://127.0.0.1:$LOCAL_PORT/api/tunnels | \ - sed -nE 's/.*public_url":"https:..([^"]*).*/\1/p') - sleep 1 - echo -n "." - done - echo ---------copy the below public_URL for NGrok---------- - echo "https://$NGROK_PUBLIC_URL" - echo "https://$NGROK_PUBLIC_URL" - - echo "test ngrok " - curl -u minikube:minikube https://$NGROK_PUBLIC_URL - echo "https://$NGROK_PUBLIC_URL" + # # For remote access to minikube uncomment the following lines. + # #---------------------minikube remote aceess start--------------------- + # sudo apt install nginx + # sudo touch /etc/nginx/conf.d/minikube.conf + # echo "create nginx conf" + # sudo chmod 777 -R /etc/nginx/conf.d/ + # echo "changed access" + + # sudo apt-get install apache2-utils -y + # echo "apache2-utils installed" + # htpasswd -bc /home/circleci/project/.htpasswd minikube minikube + + # sudo cat \< /etc/nginx/conf.d/minikube.conf + # server { + # listen 8080; + # listen [::]:8080; + # server_name localhost; + # access_log /home/circleci/project/nginx_access.log; + # auth_basic "Administrators Area"; + # auth_basic_user_file /home/circleci/project/.htpasswd; + + # location / { + # proxy_pass https://$MINIKUBE_IP:8443; + # proxy_ssl_certificate /home/circleci/.minikube/profiles/minikube/client.crt; + # proxy_ssl_certificate_key /home/circleci/.minikube/profiles/minikube/client.key; + # } + # } + # EOF + # sudo service nginx restart || echo 'start nginx' + # SYSTEMD_LESS=FRXMK systemctl status nginx.service + + # sleep 10 + + # echo "test-nginx-proxy" + # curl -u minikube:minikube http://localhost:8080 + + # curl -s https://ngrok-agent.s3.amazonaws.com/ngrok.asc | sudo tee /etc/apt/trusted.gpg.d/ngrok.asc >/dev/null && echo "deb https://ngrok-agent.s3.amazonaws.com buster main" | sudo tee /etc/apt/sources.list.d/ngrok.list && sudo apt update && sudo apt install ngrok + # ngrok config add-authtoken $AUTH_TOKEN + # echo "web_addr: $LOCAL_PORT" >> /home/circleci/.config/ngrok/ngrok.yml + # ngrok http 8080 > /dev/null & + + # echo -n "Extracting ngrok public url ." + # NGROK_PUBLIC_URL="" + # while [ -z "$NGROK_PUBLIC_URL" ]; do + # # Run 'curl' against ngrok API and extract public (using 'sed' command) + # export NGROK_PUBLIC_URL=$(curl --silent --max-time 10 --connect-timeout 5 \ + # --show-error http://127.0.0.1:$LOCAL_PORT/api/tunnels | \ + # sed -nE 's/.*public_url":"https:..([^"]*).*/\1/p') + # sleep 1 + # echo -n "." + # done + # echo ---------copy the below public_URL for NGrok---------- + # echo "https://$NGROK_PUBLIC_URL" + # echo "https://$NGROK_PUBLIC_URL" + + # echo "test ngrok " + # curl -u minikube:minikube https://$NGROK_PUBLIC_URL + # echo "https://$NGROK_PUBLIC_URL" # # ---------------------minikube remote access end--------------------- curl https://baltocdn.com/helm/signing.asc | gpg --dearmor | sudo tee /usr/share/keyrings/helm.gpg > /dev/null @@ -2250,8 +2250,8 @@ jobs: echo "Deploying to environment..." # Add your deployment scripts/commands here echo "Deployment completed." - - + + workflows: version: 2 @@ -2462,3 +2462,4 @@ workflows: - Ngrok requires: - build-g2p-sandbox-ci-chart +