From b49814b6c84bdf9d3d1c6e5d9b89c5a467363d27 Mon Sep 17 00:00:00 2001 From: Subham Pramanik Date: Fri, 3 Apr 2020 00:37:59 +0530 Subject: [PATCH 1/8] FIX: Updated central-repo links in readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 293b402..564854f 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ Put a settings.xml into your ~/.m2 directory with the following content: central Central Repository - http://repo.maven.apache.org/maven2 + https://repo.maven.apache.org/maven2 default false @@ -39,7 +39,7 @@ Put a settings.xml into your ~/.m2 directory with the following content: central Central Repository - http://repo.maven.apache.org/maven2 + https://repo.maven.apache.org/maven2 default false never From 7378b102e39f15010f8d92b0b676881331fe2e09 Mon Sep 17 00:00:00 2001 From: Subham Pramanik Date: Sat, 4 Apr 2020 04:40:49 +0530 Subject: [PATCH 2/8] Created config and application.yml --- .../psp/mpesa/config/MPesaSettings.java | 98 ++++++++++++++++ work/mpesa/application.yml | 106 ++++++++++++++++++ 2 files changed, 204 insertions(+) create mode 100644 sources/payment-hub/src/main/java/org/openmf/psp/mpesa/config/MPesaSettings.java create mode 100644 work/mpesa/application.yml diff --git a/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/config/MPesaSettings.java b/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/config/MPesaSettings.java new file mode 100644 index 0000000..5d57bc6 --- /dev/null +++ b/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/config/MPesaSettings.java @@ -0,0 +1,98 @@ +package org.openmf.psp.mpesa.config; + +import javax.annotation.PostConstruct; +import org.openmf.psp.config.ApplicationSettings; +import org.openmf.psp.config.Binding; +import org.openmf.psp.config.Header; +import org.openmf.psp.config.HubSettings; +import org.openmf.psp.config.Operation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ConfigurationProperties("mpesa-settings") +public class MPesaSettings extends ApplicationSettings { + + private String consumerKey; + private String consumerSecret; + + HubSettings hubSettings; + + MPesaSettings() { + + } + + @Autowired + public MPesaSettings(HubSettings hubSettings) { + this.hubSettings = hubSettings; + } + + @PostConstruct + public void postConstruct() { + postConstruct(hubSettings); + } + + public String getConsumerKey() { + return consumerKey; + } + + public void setConsumerKey(String consumerKey) { + this.consumerKey = consumerKey; + } + + public String getConsumerSecret() { + return consumerSecret; + } + + public void setConsumerSecret(String consumerSecret) { + this.consumerSecret = consumerSecret; + } + + public enum MPesaHeader implements Header { + TENANT("tenant"); // Arbitrary variable, need to confirm + + private final String configName; + + MPesaHeader(String configName) { + this.configName = configName; + } + + @Override + public String getConfigName() { + return configName; + } + } + + public enum MPesaOperation implements Operation { + OAUTH("oauth-token"), + BALANCE("account-balance"); + + private final String configName; + + MPesaOperation(String configName) { + this.configName = configName; + } + + @Override + public String getConfigName() { + return configName; + } + } + + public enum MPesaBinding implements Binding { + BALANCE("balance"); // Arbitrary variable, need to confirm + + private final String configName; + + MPesaBinding(String configName) { + this.configName = configName; + } + + @Override + public String getConfigName() { + return configName; + } + } + +} diff --git a/work/mpesa/application.yml b/work/mpesa/application.yml new file mode 100644 index 0000000..886e146 --- /dev/null +++ b/work/mpesa/application.yml @@ -0,0 +1,106 @@ +debug: true + +spring: + main: + web-application-type: none + +# the name of Camel +camel: + springboot: + name: RestCamel + +iban-settings: + fsp-instance-id-first-index: 4 + fsp-instance-id-length: 4 + fsp-tenant-id-first-index: 8 + fsp-tenant-id-length: 4 + +hub-settings: + instance: in02 + expiration: 30000 + tenants: tn03, tn04 + +channel-settings: + cors-enabled: true + headers: + - name: tenant + key: X-Tenant-Identifier + operations: #hub -> channel + - name: operation-basic-settings + host: https://fineract.mifos.io + tenants: + - name: tn03 + port: 48888 + - name: tn04 + port: 48889 + - name: quotes #post notification + base: interoperation/quotes + - name: transfers #post notification + base: interoperation/transfers + - name: response #put async response + base: interoperation/transactions + bindings: #channel -> hub + - name: binding-basic-settings + host: http://0.0.0.0 + port: 80 + - name: parties + base: channel/parties + - name: payment #post payment request + base: channel/transactions #/in01/channel/transactions + - name: status #get status by hub id + base: channel/transactions + - name: client-status #get status by client id + base: channel/transactions/client + +fsp-settings: + ilp-secret: h4on38bsDjKiat2783gnklgafikmeuu5123kpobb7jm99 + auth: + profile: BASIC + encode: NONE + login-class: org.openmf.psp.dto.fsp.LoginFineractXResponseDTO + headers: + - name: user + key: User + - name: tenant + key: Fineract-Platform-TenantId + operations: #hub -> fsp + - name: operation-basic-settings + user: mifos + password: password + host: https://fineract.mifos.io + port: 8443 + - name: auth #login + base: fineract-provider/api/v1/authentication + - name: requests + base: fineract-provider/api/v1/interoperation/requests + - name: parties + base: fineract-provider/api/v1/interoperation/parties + - name: quotes + base: fineract-provider/api/v1/interoperation/quotes + - name: transfers + base: fineract-provider/api/v1/interoperation/transfers + + +mpesa-settings: + consumer-key: LOyKl0JIxeqwpv7qEUiU4QnKDuuiUPGO + consumer-secret: UirFo80R4UOACqvi + headers: + # TODO: Complete it + operations: #hub -> ott + - name: operation-basic-settings + host: https://sandbox.safaricom.co.ke + - name: oauth-token + base: oauth/v1/generate?grant_type=client_credentials + - name: account-balance + base: mpesa/accountbalance/v1/query + bindings: #ott -> hub + - name: binding-basic-settings + host: http://0.0.0.0 + #TODO: Complete it + + + +mock-settings: + start-channel-consumers: false + start-switch-consumers: false + start-fsp-consumers: false From 4488c0a381926a27abef1a7c3f4a5b78b0be46ea Mon Sep 17 00:00:00 2001 From: Subham Pramanik Date: Sat, 4 Apr 2020 21:39:25 +0530 Subject: [PATCH 3/8] [DEV] Fetch Access token implemented --- .../psp/mpesa/dto/AccessTokenResponse.java | 23 ++++++ .../openmf/psp/mpesa/dto/BalanceRequest.java | 80 +++++++++++++++++++ .../routebuilder/channel/AccountBalance.java | 57 +++++++++++++ .../routebuilder/channel/BaseTransaction.java | 39 +++++++++ .../processor/FetchAccessTokenProcessor.java | 56 +++++++++++++ 5 files changed, 255 insertions(+) create mode 100644 sources/payment-hub/src/main/java/org/openmf/psp/mpesa/dto/AccessTokenResponse.java create mode 100644 sources/payment-hub/src/main/java/org/openmf/psp/mpesa/dto/BalanceRequest.java create mode 100644 sources/payment-hub/src/main/java/org/openmf/psp/mpesa/routebuilder/channel/AccountBalance.java create mode 100644 sources/payment-hub/src/main/java/org/openmf/psp/mpesa/routebuilder/channel/BaseTransaction.java create mode 100644 sources/payment-hub/src/main/java/org/openmf/psp/mpesa/routebuilder/processor/FetchAccessTokenProcessor.java diff --git a/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/dto/AccessTokenResponse.java b/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/dto/AccessTokenResponse.java new file mode 100644 index 0000000..a3f8155 --- /dev/null +++ b/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/dto/AccessTokenResponse.java @@ -0,0 +1,23 @@ +package org.openmf.psp.mpesa.dto; + +public class AccessTokenResponse { + + String access_token; + String expires_in; + + public String getAccess_token() { + return access_token; + } + + public void setAccess_token(String access_token) { + this.access_token = access_token; + } + + public String getExpires_in() { + return expires_in; + } + + public void setExpires_in(String expires_in) { + this.expires_in = expires_in; + } +} diff --git a/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/dto/BalanceRequest.java b/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/dto/BalanceRequest.java new file mode 100644 index 0000000..96895ab --- /dev/null +++ b/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/dto/BalanceRequest.java @@ -0,0 +1,80 @@ +package org.openmf.psp.mpesa.dto; + +import java.util.Arrays; + +public class BalanceRequest { + + String CommandID; + String PartyA; + String IdentifierType; + String Remarks; + String Initiator; + String SecurityCredential; + String QueueTimeOutURL; + String ResultURL; + + public String getCommandID() { + return CommandID; + } + + public void setCommandID(String commandID) { + CommandID = commandID; + } + + public String getPartyA() { + return PartyA; + } + + public void setPartyA(String partyA) { + PartyA = partyA; + } + + public String getIdentifierType() { + return IdentifierType; + } + + public void setIdentifierType(String identifierType) { + IdentifierType = identifierType; + } + + public String getRemarks() { + return Remarks; + } + + public void setRemarks(String remarks) { + Remarks = remarks; + } + + public String getInitiator() { + return Initiator; + } + + public void setInitiator(String initiator) { + Initiator = initiator; + } + + public String getSecurityCredential() { + return SecurityCredential; + } + + public void setSecurityCredentials(String securityCredential) { + SecurityCredential = securityCredential; + } + + public String getQueueTimeOutURL() { + return QueueTimeOutURL; + } + + public void setQueueTimeOutURL(String queueTimeOutURL) { + QueueTimeOutURL = queueTimeOutURL; + } + + public String getResultURL() { + return ResultURL; + } + + public void setResultURL(String resultURL) { + ResultURL = resultURL; + } + +} diff --git a/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/routebuilder/channel/AccountBalance.java b/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/routebuilder/channel/AccountBalance.java new file mode 100644 index 0000000..119451e --- /dev/null +++ b/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/routebuilder/channel/AccountBalance.java @@ -0,0 +1,57 @@ +package org.openmf.psp.mpesa.routebuilder.channel; + +import org.apache.camel.CamelContext; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.model.dataformat.JsonLibrary; +import org.openmf.psp.config.BindingProperties; +import org.openmf.psp.config.HubSettings; +import org.openmf.psp.config.OperationProperties; +import org.openmf.psp.mpesa.config.MPesaSettings; +import org.openmf.psp.mpesa.dto.BalanceRequest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class AccountBalance extends RouteBuilder { + + private HubSettings hubSettings; + private MPesaSettings mPesaSettings; + + @Autowired + public AccountBalance(CamelContext camelContext, HubSettings hubSettings, MPesaSettings mPesaSetting) { + super(camelContext); + this.hubSettings = hubSettings; + this.mPesaSettings = mPesaSetting; + } + + @Override + public void configure() throws Exception { + + OperationProperties transactionOperation = mPesaSettings.getOperation(MPesaSettings.MPesaOperation.BALANCE); + OperationProperties oauthOperation = mPesaSettings.getOperation(MPesaSettings.MPesaOperation.OAUTH); + String apiTransactionEndpoint = transactionOperation.getUrl(); + String apiOAuthEndpoint = oauthOperation.getUrl(); + + BindingProperties binding = mPesaSettings.getBinding(MPesaSettings.MPesaBinding.BALANCE); + String url = binding.getUrl(); + + String consumerEndpoint = ""; //Confirm with Avik + + from(consumerEndpoint) + .id("receive-account-balance-check-request") + .log("Account balance check request received") + .streamCaching() + .process(exchange -> { + exchange.setProperty("consumerKey", mPesaSettings.getConsumerKey()); + exchange.setProperty("consumerSecret", mPesaSettings.getConsumerSecret()); + exchange.setProperty("apiOAuthEndpoint", apiOAuthEndpoint); + exchange.setProperty("apiTransactionEndpoint", apiTransactionEndpoint); + exchange.setProperty("transactionType", binding.getName()); + exchange.setProperty("mainBody", exchange.getIn().getBody(String.class)); + }) + .unmarshal().json(JsonLibrary.Jackson, BalanceRequest.class) + .to("direct:conductTransaction") + ; + + } +} diff --git a/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/routebuilder/channel/BaseTransaction.java b/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/routebuilder/channel/BaseTransaction.java new file mode 100644 index 0000000..1b9ea6b --- /dev/null +++ b/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/routebuilder/channel/BaseTransaction.java @@ -0,0 +1,39 @@ +package org.openmf.psp.mpesa.routebuilder.channel; + +import org.apache.camel.builder.RouteBuilder; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class BaseTransaction extends RouteBuilder { + + @Override + public void configure() throws Exception { + + from("direct:conductTransaction") + .id("conductTransaction") + .log("Starting transaction") + .to("direct:getAccessToken") + ; + + from("direct:getAccessToken") + .id("getAccessToken") + .log("Initiated Process to get Access Token") + .process("fetchAccessTokenProcessor") + .choice() + .when(exchange -> exchange.getProperty("tokenResponseCode", String.class).equals("200")) + .log("Access Token fetch successful, moving to transaction.") + .to("direct:commitTransaction") + .otherwise() + .log("Access token fetch unsuccessful.") + .to("direct:transactionFailure") + ; + + from("direct:commitTransaction") + .id("commitTransaction") + .log("Committing Transaction") + .process("postTransactionProcess") + ; + + } + +} diff --git a/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/routebuilder/processor/FetchAccessTokenProcessor.java b/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/routebuilder/processor/FetchAccessTokenProcessor.java new file mode 100644 index 0000000..88e251d --- /dev/null +++ b/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/routebuilder/processor/FetchAccessTokenProcessor.java @@ -0,0 +1,56 @@ +package org.openmf.psp.mpesa.routebuilder.processor; + +import com.sun.org.apache.xerces.internal.impl.dv.util.Base64; +import org.apache.camel.Exchange; +import org.apache.camel.Processor; +import org.openmf.psp.mpesa.dto.AccessTokenResponse; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; + +@Component("fetchAccessTokenProcessor") +public class FetchAccessTokenProcessor implements Processor { + + RestTemplate restTemplate; + + public FetchAccessTokenProcessor(RestTemplate restTemplate) { + this.restTemplate = restTemplate; + } + + @Override + public void process (Exchange exchange) throws Exception { + + String app_key = exchange.getProperty("consumerKey", String.class); + String app_secret = exchange.getProperty("consumerSecret", String.class); + String appKeySecret = app_key + ":" + app_secret; + byte[] bytes = appKeySecret.getBytes("ISO-8859-1"); + String auth = Base64.encode(bytes); + + String url = exchange.getProperty("apiOAuthEndpoint", String.class); + + HttpHeaders headers = new HttpHeaders(); + headers.set("authorization", "Basic " + auth); + headers.set("cache-control", "no-cache"); + + HttpEntity entity = new HttpEntity<>(headers); + + HttpMethod method = HttpMethod.GET; + + HttpStatus responseCode = restTemplate.exchange(url, method, entity, AccessTokenResponse.class).getStatusCode(); + + AccessTokenResponse response = null; + + if (responseCode == HttpStatus.OK) { + response = restTemplate.exchange(url, method, entity, AccessTokenResponse.class).getBody(); + exchange.setProperty("tokenResponseCose", "200"); + exchange.setProperty("access_token", response.getAccess_token()); + } else { + exchange.setProperty("tokenResponseCode", String.valueOf(responseCode.value())); + } + + } + +} From 4a916374f1ac5cf1d4a8c7a6c8566016fb0fab15 Mon Sep 17 00:00:00 2001 From: Subham Pramanik Date: Sun, 5 Apr 2020 01:19:24 +0530 Subject: [PATCH 4/8] [DEV] Added Post transaction for balance query --- .../openmf/psp/mpesa/dto/ReferenceData.java | 14 ++++ .../openmf/psp/mpesa/dto/ReferenceItem.java | 23 ++++++ .../java/org/openmf/psp/mpesa/dto/Result.java | 77 +++++++++++++++++++ .../openmf/psp/mpesa/dto/ResultParameter.java | 23 ++++++ .../psp/mpesa/dto/ResultParameters.java | 16 ++++ .../psp/mpesa/dto/TransactionResponse.java | 14 ++++ .../routebuilder/channel/AccountBalance.java | 2 +- .../routebuilder/channel/BaseTransaction.java | 5 ++ .../processor/FetchAccessTokenProcessor.java | 16 ++-- .../processor/PostTransactionProcessor.java | 50 ++++++++++++ 10 files changed, 231 insertions(+), 9 deletions(-) create mode 100644 sources/payment-hub/src/main/java/org/openmf/psp/mpesa/dto/ReferenceData.java create mode 100644 sources/payment-hub/src/main/java/org/openmf/psp/mpesa/dto/ReferenceItem.java create mode 100644 sources/payment-hub/src/main/java/org/openmf/psp/mpesa/dto/Result.java create mode 100644 sources/payment-hub/src/main/java/org/openmf/psp/mpesa/dto/ResultParameter.java create mode 100644 sources/payment-hub/src/main/java/org/openmf/psp/mpesa/dto/ResultParameters.java create mode 100644 sources/payment-hub/src/main/java/org/openmf/psp/mpesa/dto/TransactionResponse.java create mode 100644 sources/payment-hub/src/main/java/org/openmf/psp/mpesa/routebuilder/processor/PostTransactionProcessor.java diff --git a/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/dto/ReferenceData.java b/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/dto/ReferenceData.java new file mode 100644 index 0000000..9e6570c --- /dev/null +++ b/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/dto/ReferenceData.java @@ -0,0 +1,14 @@ +package org.openmf.psp.mpesa.dto; + +public class ReferenceData { + + public ReferenceItem referenceItem; + + public ReferenceItem getReferenceItem() { + return referenceItem; + } + + public void setReferenceItem(ReferenceItem referenceItem) { + this.referenceItem = referenceItem; + } +} diff --git a/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/dto/ReferenceItem.java b/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/dto/ReferenceItem.java new file mode 100644 index 0000000..6e98ca5 --- /dev/null +++ b/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/dto/ReferenceItem.java @@ -0,0 +1,23 @@ +package org.openmf.psp.mpesa.dto; + +public class ReferenceItem { + + public String key; + public String value; + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } +} diff --git a/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/dto/Result.java b/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/dto/Result.java new file mode 100644 index 0000000..a021c25 --- /dev/null +++ b/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/dto/Result.java @@ -0,0 +1,77 @@ +package org.openmf.psp.mpesa.dto; + +public class Result { + + public String conversationID; + public String originatorConversationID; + public ReferenceData referenceData; + public Integer resultCode; + public String resultDesc; + public ResultParameters resultParameters; + public Integer resultType; + public String transactionID; + + public String getConversationID() { + return conversationID; + } + + public void setConversationID(String conversationID) { + this.conversationID = conversationID; + } + + public String getOriginatorConversationID() { + return originatorConversationID; + } + + public void setOriginatorConversationID(String originatorConversationID) { + this.originatorConversationID = originatorConversationID; + } + + public ReferenceData getReferenceData() { + return referenceData; + } + + public void setReferenceData(ReferenceData referenceData) { + this.referenceData = referenceData; + } + + public Integer getResultCode() { + return resultCode; + } + + public void setResultCode(Integer resultCode) { + this.resultCode = resultCode; + } + + public String getResultDesc() { + return resultDesc; + } + + public void setResultDesc(String resultDesc) { + this.resultDesc = resultDesc; + } + + public ResultParameters getResultParameters() { + return resultParameters; + } + + public void setResultParameters(ResultParameters resultParameters) { + this.resultParameters = resultParameters; + } + + public Integer getResultType() { + return resultType; + } + + public void setResultType(Integer resultType) { + this.resultType = resultType; + } + + public String getTransactionID() { + return transactionID; + } + + public void setTransactionID(String transactionID) { + this.transactionID = transactionID; + } +} diff --git a/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/dto/ResultParameter.java b/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/dto/ResultParameter.java new file mode 100644 index 0000000..a6294c8 --- /dev/null +++ b/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/dto/ResultParameter.java @@ -0,0 +1,23 @@ +package org.openmf.psp.mpesa.dto; + +public class ResultParameter { + + public String key; + public Integer value; + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public Integer getValue() { + return value; + } + + public void setValue(Integer value) { + this.value = value; + } +} diff --git a/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/dto/ResultParameters.java b/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/dto/ResultParameters.java new file mode 100644 index 0000000..2cc1f7b --- /dev/null +++ b/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/dto/ResultParameters.java @@ -0,0 +1,16 @@ +package org.openmf.psp.mpesa.dto; + +import java.util.List; + +public class ResultParameters { + + List resultParameter = null; + + public List getResultParameter() { + return resultParameter; + } + + public void setResultParameter(List resultParameter) { + this.resultParameter = resultParameter; + } +} diff --git a/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/dto/TransactionResponse.java b/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/dto/TransactionResponse.java new file mode 100644 index 0000000..0cadd36 --- /dev/null +++ b/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/dto/TransactionResponse.java @@ -0,0 +1,14 @@ +package org.openmf.psp.mpesa.dto; + +public class TransactionResponse { + + public Result result; + + public Result getResult() { + return result; + } + + public void setResult(Result result) { + this.result = result; + } +} diff --git a/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/routebuilder/channel/AccountBalance.java b/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/routebuilder/channel/AccountBalance.java index 119451e..fbcdef5 100644 --- a/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/routebuilder/channel/AccountBalance.java +++ b/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/routebuilder/channel/AccountBalance.java @@ -35,7 +35,7 @@ public void configure() throws Exception { BindingProperties binding = mPesaSettings.getBinding(MPesaSettings.MPesaBinding.BALANCE); String url = binding.getUrl(); - String consumerEndpoint = ""; //Confirm with Avik + String consumerEndpoint = ""; //TODO: Add consumerEndpoint after discussion from(consumerEndpoint) .id("receive-account-balance-check-request") diff --git a/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/routebuilder/channel/BaseTransaction.java b/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/routebuilder/channel/BaseTransaction.java index 1b9ea6b..c328b83 100644 --- a/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/routebuilder/channel/BaseTransaction.java +++ b/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/routebuilder/channel/BaseTransaction.java @@ -32,6 +32,11 @@ public void configure() throws Exception { .id("commitTransaction") .log("Committing Transaction") .process("postTransactionProcess") + .choice() + .when(exchange -> exchange.getProperty("transactionResponseCode", String.class).equals("200")) + .log("Transaction was successful") + .otherwise() + .log("Transaction failed!") ; } diff --git a/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/routebuilder/processor/FetchAccessTokenProcessor.java b/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/routebuilder/processor/FetchAccessTokenProcessor.java index 88e251d..56968da 100644 --- a/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/routebuilder/processor/FetchAccessTokenProcessor.java +++ b/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/routebuilder/processor/FetchAccessTokenProcessor.java @@ -1,6 +1,7 @@ package org.openmf.psp.mpesa.routebuilder.processor; import com.sun.org.apache.xerces.internal.impl.dv.util.Base64; +import java.nio.charset.StandardCharsets; import org.apache.camel.Exchange; import org.apache.camel.Processor; import org.openmf.psp.mpesa.dto.AccessTokenResponse; @@ -8,6 +9,7 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; import org.springframework.web.client.RestTemplate; @@ -26,7 +28,7 @@ public void process (Exchange exchange) throws Exception { String app_key = exchange.getProperty("consumerKey", String.class); String app_secret = exchange.getProperty("consumerSecret", String.class); String appKeySecret = app_key + ":" + app_secret; - byte[] bytes = appKeySecret.getBytes("ISO-8859-1"); + byte[] bytes = appKeySecret.getBytes(StandardCharsets.ISO_8859_1); String auth = Base64.encode(bytes); String url = exchange.getProperty("apiOAuthEndpoint", String.class); @@ -39,16 +41,14 @@ public void process (Exchange exchange) throws Exception { HttpMethod method = HttpMethod.GET; - HttpStatus responseCode = restTemplate.exchange(url, method, entity, AccessTokenResponse.class).getStatusCode(); + ResponseEntity responseEntity = restTemplate.exchange(url, method, entity, AccessTokenResponse.class); + AccessTokenResponse response = responseEntity.getBody(); - AccessTokenResponse response = null; - - if (responseCode == HttpStatus.OK) { - response = restTemplate.exchange(url, method, entity, AccessTokenResponse.class).getBody(); - exchange.setProperty("tokenResponseCose", "200"); + if (responseEntity.getStatusCode() == HttpStatus.OK && response != null) { + exchange.setProperty("tokenResponseCode", "200"); exchange.setProperty("access_token", response.getAccess_token()); } else { - exchange.setProperty("tokenResponseCode", String.valueOf(responseCode.value())); + exchange.setProperty("tokenResponseCode", String.valueOf(responseEntity.getStatusCode().value())); } } diff --git a/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/routebuilder/processor/PostTransactionProcessor.java b/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/routebuilder/processor/PostTransactionProcessor.java new file mode 100644 index 0000000..817d910 --- /dev/null +++ b/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/routebuilder/processor/PostTransactionProcessor.java @@ -0,0 +1,50 @@ +package org.openmf.psp.mpesa.routebuilder.processor; + +import org.apache.camel.Exchange; +import org.apache.camel.Processor; +import org.openmf.psp.mpesa.dto.TransactionResponse; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; + +@Component("postTransactionProcessor") +public class PostTransactionProcessor implements Processor { + + RestTemplate restTemplate; + + public PostTransactionProcessor(RestTemplate restTemplate) { + this.restTemplate = restTemplate; + } + + @Override + public void process (Exchange exchange) throws Exception { + + String body = exchange.getProperty("mainBody", String.class); + + String url = exchange.getProperty("apiTransactionEndpoint", String.class); + String access_token = exchange.getProperty("access_token", String.class); + + HttpHeaders headers = new HttpHeaders(); + headers.set("authorization", "Bearer " + access_token); + headers.set("content-type", "application/json"); + + HttpEntity entity = new HttpEntity<>(body, headers); + + HttpMethod method = HttpMethod.POST; + + ResponseEntity responseEntity = restTemplate.exchange(url, method, entity, TransactionResponse.class); + TransactionResponse response = responseEntity.getBody(); + + if (responseEntity.getStatusCode() == HttpStatus.OK && response != null) { + exchange.setProperty("transactionResponseCode", "200"); + exchange.getIn().setBody(response); + } else { + exchange.setProperty("transactionResponseCode", String.valueOf(responseEntity.getStatusCode().value())); + } + } + +} From 985f841a265ab50d09324cac26a3a8a95e88e0bb Mon Sep 17 00:00:00 2001 From: Subham Pramanik Date: Sun, 5 Apr 2020 01:30:51 +0530 Subject: [PATCH 5/8] Refac: updated application.yml file --- work/mpesa/application.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/work/mpesa/application.yml b/work/mpesa/application.yml index 886e146..39b6f97 100644 --- a/work/mpesa/application.yml +++ b/work/mpesa/application.yml @@ -96,7 +96,10 @@ mpesa-settings: bindings: #ott -> hub - name: binding-basic-settings host: http://0.0.0.0 - #TODO: Complete it + port: #TODO: Discuss for the port number + - name: balance + host: balance + #TODO: Complete the bindings From 851061be3ebf231434b083050e8198b7565150f8 Mon Sep 17 00:00:00 2001 From: Subham Pramanik Date: Sun, 5 Apr 2020 03:36:56 +0530 Subject: [PATCH 6/8] [FIX] Marshal response --- .../psp/mpesa/routebuilder/channel/AccountBalance.java | 1 + .../mpesa/routebuilder/channel/BaseTransaction.java | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/routebuilder/channel/AccountBalance.java b/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/routebuilder/channel/AccountBalance.java index fbcdef5..a100801 100644 --- a/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/routebuilder/channel/AccountBalance.java +++ b/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/routebuilder/channel/AccountBalance.java @@ -49,6 +49,7 @@ public void configure() throws Exception { exchange.setProperty("transactionType", binding.getName()); exchange.setProperty("mainBody", exchange.getIn().getBody(String.class)); }) + .unmarshal().json(JsonLibrary.Jackson, BalanceRequest.class) .to("direct:conductTransaction") ; diff --git a/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/routebuilder/channel/BaseTransaction.java b/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/routebuilder/channel/BaseTransaction.java index c328b83..d8315fd 100644 --- a/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/routebuilder/channel/BaseTransaction.java +++ b/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/routebuilder/channel/BaseTransaction.java @@ -1,6 +1,8 @@ package org.openmf.psp.mpesa.routebuilder.channel; import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.model.dataformat.JsonLibrary; +import org.openmf.psp.mpesa.config.MPesaSettings; import org.springframework.context.annotation.Configuration; @Configuration @@ -35,10 +37,18 @@ public void configure() throws Exception { .choice() .when(exchange -> exchange.getProperty("transactionResponseCode", String.class).equals("200")) .log("Transaction was successful") + .to("direct:endTransaction") .otherwise() .log("Transaction failed!") ; + from("direct:endTransaction") + .id("endTransaction") + .choice() + .when(exchange -> exchange.getProperty("transactionType", String.class).equals(MPesaSettings.MPesaBinding.BALANCE)) + .marshal().json(JsonLibrary.Jackson) + ; + } } From 1c9c3ca61c16753a6df21348fef0db3d6de7a425 Mon Sep 17 00:00:00 2001 From: Subham Pramanik Date: Tue, 21 Apr 2020 22:09:34 +0530 Subject: [PATCH 7/8] refac: changed naming convention --- .../mpesa/routebuilder/channel/BaseTransaction.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/routebuilder/channel/BaseTransaction.java b/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/routebuilder/channel/BaseTransaction.java index d8315fd..4932521 100644 --- a/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/routebuilder/channel/BaseTransaction.java +++ b/sources/payment-hub/src/main/java/org/openmf/psp/mpesa/routebuilder/channel/BaseTransaction.java @@ -24,22 +24,22 @@ public void configure() throws Exception { .choice() .when(exchange -> exchange.getProperty("tokenResponseCode", String.class).equals("200")) .log("Access Token fetch successful, moving to transaction.") - .to("direct:commitTransaction") + .to("direct:commitBalanceCheck") .otherwise() .log("Access token fetch unsuccessful.") .to("direct:transactionFailure") ; - from("direct:commitTransaction") - .id("commitTransaction") - .log("Committing Transaction") + from("direct:commitBalanceCheck") + .id("commitBalanceCheck") + .log("Committing Balance Check") .process("postTransactionProcess") .choice() .when(exchange -> exchange.getProperty("transactionResponseCode", String.class).equals("200")) - .log("Transaction was successful") + .log("Balance Check was successful") .to("direct:endTransaction") .otherwise() - .log("Transaction failed!") + .log("Balance Check failed!") ; from("direct:endTransaction") From 4344db356ba36e159bde691d308a7fad29097512 Mon Sep 17 00:00:00 2001 From: Subham Pramanik Date: Tue, 21 Apr 2020 23:11:15 +0530 Subject: [PATCH 8/8] refac: removed dead code --- work/mpesa/application.yml | 111 +++++++++++++++++-------------------- 1 file changed, 51 insertions(+), 60 deletions(-) diff --git a/work/mpesa/application.yml b/work/mpesa/application.yml index 39b6f97..b0eb173 100644 --- a/work/mpesa/application.yml +++ b/work/mpesa/application.yml @@ -23,34 +23,32 @@ hub-settings: channel-settings: cors-enabled: true headers: - - name: tenant - key: X-Tenant-Identifier + - name: tenant + key: X-Tenant-Identifier operations: #hub -> channel - - name: operation-basic-settings - host: https://fineract.mifos.io - tenants: - - name: tn03 - port: 48888 - - name: tn04 - port: 48889 - - name: quotes #post notification - base: interoperation/quotes - - name: transfers #post notification - base: interoperation/transfers - - name: response #put async response - base: interoperation/transactions + - name: operation-basic-settings + host: https://fineract.mifos.io + tenants: + - name: tn03 + port: 48888 + - name: tn04 + port: 48889 + - name: transfers #post notification + base: interoperation/transfers + - name: response #put async response + base: interoperation/transactions bindings: #channel -> hub - - name: binding-basic-settings - host: http://0.0.0.0 - port: 80 - - name: parties - base: channel/parties - - name: payment #post payment request - base: channel/transactions #/in01/channel/transactions - - name: status #get status by hub id - base: channel/transactions - - name: client-status #get status by client id - base: channel/transactions/client + - name: binding-basic-settings + host: http://0.0.0.0 + port: 80 + - name: parties + base: channel/parties + - name: payment #post payment request + base: channel/transactions #/in01/channel/transactions + - name: status #get status by hub id + base: channel/transactions + - name: client-status #get status by client id + base: channel/transactions/client fsp-settings: ilp-secret: h4on38bsDjKiat2783gnklgafikmeuu5123kpobb7jm99 @@ -59,27 +57,22 @@ fsp-settings: encode: NONE login-class: org.openmf.psp.dto.fsp.LoginFineractXResponseDTO headers: - - name: user - key: User - - name: tenant - key: Fineract-Platform-TenantId + - name: user + key: User + - name: tenant + key: Fineract-Platform-TenantId operations: #hub -> fsp - - name: operation-basic-settings - user: mifos - password: password - host: https://fineract.mifos.io - port: 8443 - - name: auth #login - base: fineract-provider/api/v1/authentication - - name: requests - base: fineract-provider/api/v1/interoperation/requests - - name: parties - base: fineract-provider/api/v1/interoperation/parties - - name: quotes - base: fineract-provider/api/v1/interoperation/quotes - - name: transfers - base: fineract-provider/api/v1/interoperation/transfers - + - name: operation-basic-settings + user: mifos + password: password + host: https://fineract.mifos.io + port: 8443 + - name: auth #login + base: fineract-provider/api/v1/authentication + - name: requests + base: fineract-provider/api/v1/interoperation/requests + - name: transfers + base: fineract-provider/api/v1/interoperation/transfers mpesa-settings: consumer-key: LOyKl0JIxeqwpv7qEUiU4QnKDuuiUPGO @@ -87,21 +80,19 @@ mpesa-settings: headers: # TODO: Complete it operations: #hub -> ott - - name: operation-basic-settings - host: https://sandbox.safaricom.co.ke - - name: oauth-token - base: oauth/v1/generate?grant_type=client_credentials - - name: account-balance - base: mpesa/accountbalance/v1/query + - name: operation-basic-settings + host: https://sandbox.safaricom.co.ke + - name: oauth-token + base: oauth/v1/generate?grant_type=client_credentials + - name: account-balance + base: mpesa/accountbalance/v1/query bindings: #ott -> hub - - name: binding-basic-settings - host: http://0.0.0.0 - port: #TODO: Discuss for the port number - - name: balance - host: balance - #TODO: Complete the bindings - - + - name: binding-basic-settings + host: http://0.0.0.0 + port: #TODO: Discuss for the port number + - name: balance + host: balance + #TODO: Complete the bindings mock-settings: start-channel-consumers: false