diff --git a/financial-services-accelerator/accelerators/fs-apim/pom.xml b/financial-services-accelerator/accelerators/fs-apim/pom.xml index 47dc76e1..3249ddba 100644 --- a/financial-services-accelerator/accelerators/fs-apim/pom.xml +++ b/financial-services-accelerator/accelerators/fs-apim/pom.xml @@ -95,6 +95,8 @@ regex="org.wso2.financial.services.accelerator.gateway-(\d.*?)\.jar$"/> + diff --git a/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.extensions/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/extensions/authorize/util/ConsentAuthorizeUtil.java b/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.extensions/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/extensions/authorize/util/ConsentAuthorizeUtil.java index 02c4b4bf..2e9b0af3 100644 --- a/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.extensions/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/extensions/authorize/util/ConsentAuthorizeUtil.java +++ b/financial-services-accelerator/components/org.wso2.financial.services.accelerator.consent.mgt.extensions/src/main/java/org/wso2/financial/services/accelerator/consent/mgt/extensions/authorize/util/ConsentAuthorizeUtil.java @@ -448,14 +448,13 @@ public static JSONArray appendDummyAccountID() { JSONArray accountsJSON = new JSONArray(); JSONObject accountOne = new JSONObject(); - accountOne.put("account_id", "12345"); + accountOne.put("account_id", "30080012343456"); accountOne.put("display_name", "Salary Saver Account"); accountsJSON.put(accountOne); JSONObject accountTwo = new JSONObject(); - accountTwo.put("account_id", "67890"); - accountTwo.put("account_id", "67890"); + accountTwo.put("account_id", "30080098763459"); accountTwo.put("display_name", "Max Bonus Account"); accountsJSON.put(accountTwo); diff --git a/financial-services-accelerator/internal-webapps/org.wso2.financial.services.accelerator.demo.backend/pom.xml b/financial-services-accelerator/internal-webapps/org.wso2.financial.services.accelerator.demo.backend/pom.xml new file mode 100644 index 00000000..8f39e356 --- /dev/null +++ b/financial-services-accelerator/internal-webapps/org.wso2.financial.services.accelerator.demo.backend/pom.xml @@ -0,0 +1,95 @@ + + + + + + financial-services-accelerator + org.wso2.financial.services.accelerator + 4.0.0-SNAPSHOT + ../../pom.xml + + 4.0.0 + + org.wso2.financial.services.accelerator.demo.backend + war + WSO2 Financial Services - Demo Backend + + + + javax.ws.rs + jsr311-api + + + com.github.spotbugs + spotbugs-annotations + + + net.minidev + json-smart + + + org.wso2.financial.services.accelerator + org.wso2.financial.services.accelerator.common + + + + + + + maven-war-plugin + + WEB-INF/lib/*.jar + api#fs#backend + + + + org.apache.maven.plugins + maven-compiler-plugin + + + com.github.spotbugs + spotbugs-maven-plugin + + Max + Low + true + true + ${project.build.directory}/spotbugs + ${project.basedir}/src/main/resources/findbugs-include.xml + + + com.h3xstream.findsecbugs + findsecbugs-plugin + ${com.h3xstream.findsecbugs.version} + + + + + + analyze-compile + compile + + check + + + + + + + diff --git a/financial-services-accelerator/internal-webapps/org.wso2.financial.services.accelerator.demo.backend/src/main/java/org/wso2/financial/services/accelerator/demo/backend/BankException.java b/financial-services-accelerator/internal-webapps/org.wso2.financial.services.accelerator.demo.backend/src/main/java/org/wso2/financial/services/accelerator/demo/backend/BankException.java new file mode 100644 index 00000000..6997d2d4 --- /dev/null +++ b/financial-services-accelerator/internal-webapps/org.wso2.financial.services.accelerator.demo.backend/src/main/java/org/wso2/financial/services/accelerator/demo/backend/BankException.java @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.financial.services.accelerator.demo.backend; + +/** + * BankException class. + */ +public class BankException extends Exception { + + public BankException(String msg) { + super(msg); + } + + public BankException(String msg, Throwable e) { + super(msg, e); + } + + public BankException(Throwable throwable) { + super(throwable); + } +} diff --git a/financial-services-accelerator/internal-webapps/org.wso2.financial.services.accelerator.demo.backend/src/main/java/org/wso2/financial/services/accelerator/demo/backend/BankExceptionHandler.java b/financial-services-accelerator/internal-webapps/org.wso2.financial.services.accelerator.demo.backend/src/main/java/org/wso2/financial/services/accelerator/demo/backend/BankExceptionHandler.java new file mode 100644 index 00000000..13aa38c1 --- /dev/null +++ b/financial-services-accelerator/internal-webapps/org.wso2.financial.services.accelerator.demo.backend/src/main/java/org/wso2/financial/services/accelerator/demo/backend/BankExceptionHandler.java @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.financial.services.accelerator.demo.backend; + +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.ext.ExceptionMapper; + +/** + * BankExceptionHandler class. + */ +public class BankExceptionHandler implements ExceptionMapper { + + public Response toResponse(BankException exception) { + return Response.status(Status.BAD_REQUEST).entity(exception.getMessage()) + .type(MediaType.APPLICATION_JSON).build(); + } +} diff --git a/financial-services-accelerator/internal-webapps/org.wso2.financial.services.accelerator.demo.backend/src/main/java/org/wso2/financial/services/accelerator/demo/backend/services/AccountService.java b/financial-services-accelerator/internal-webapps/org.wso2.financial.services.accelerator.demo.backend/src/main/java/org/wso2/financial/services/accelerator/demo/backend/services/AccountService.java new file mode 100644 index 00000000..6b208f72 --- /dev/null +++ b/financial-services-accelerator/internal-webapps/org.wso2.financial.services.accelerator.demo.backend/src/main/java/org/wso2/financial/services/accelerator/demo/backend/services/AccountService.java @@ -0,0 +1,261 @@ +/** + * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.financial.services.accelerator.demo.backend.services; + +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import org.wso2.financial.services.accelerator.demo.backend.BankException; + +import java.util.UUID; + +import javax.ws.rs.GET; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Response; + +/** + * AccountService class. + */ +@Path("/accountservice/") +public class AccountService { + + @SuppressFBWarnings("JAXRS_ENDPOINT") + // Suppressed content - Endpoint + // Suppression reason - False Positive : This endpoint is a demo endpoint that is not exposed in production + // Suppressed warning count - 1 + @GET + @Path("/accounts") + @Produces("application/json; charset=utf-8") + public Response getAccounts(@HeaderParam("x-fapi-interaction-id") String xFapiInteractionId, + @HeaderParam("Account-Request-Information") String accountRequestInfo) { + + String finalRespose = "{\n" + + " \"Data\": {\n" + + " \"Account\": [\n" + + " {\n" + + " \"AccountId\": \"30080012343456\",\n" + + " \"Status\": \"Enabled\",\n" + + " \"StatusUpdateDateTime\": \"2020-04-16T06:06:06+00:00\",\n" + + " \"Currency\": \"GBP\",\n" + + " \"AccountType\": \"Personal\",\n" + + " \"AccountSubType\": \"CurrentAccount\",\n" + + " \"Nickname\": \"Bills\",\n" + + " \"OpeningDate\": \"2020-01-16T06:06:06+00:00\",\n" + + " \"MaturityDate\": \"2025-04-16T06:06:06+00:00\",\n" + + " \"Account\": [{\n" + + " \"SchemeName\": \"SortCodeAccountNumber\",\n" + + " \"Identification\": \"30080012343456\",\n" + + " \"Name\": \"Mr Kevin\",\n" + + " \"SecondaryIdentification\": \"00021\"\n" + + " }]\n" + + " },\n" + + " {\n" + + " \"AccountId\": \"30080098763459\",\n" + + " \"Status\": \"Enabled\",\n" + + " \"StatusUpdateDateTime\": \"2020-04-16T06:06:06+00:00\",\n" + + " \"Currency\": \"GBP\",\n" + + " \"AccountType\": \"Personal\",\n" + + " \"AccountSubType\": \"CurrentAccount\",\n" + + " \"Nickname\": \"Bills\",\n" + + " \"OpeningDate\": \"2020-01-16T06:06:06+00:00\",\n" + + " \"MaturityDate\": \"2025-04-16T06:06:06+00:00\"\n" + + " }\n" + + " ]\n" + + " },\n" + + " \"Links\": {\n" + + " \"Self\": \"https://api.alphabank.com/open-banking/v4.0/accounts\"\n" + + " },\n" + + " \"Meta\": {\n" + + " \"TotalPages\": 1\n" + + " }\n" + + "}"; + + if (xFapiInteractionId == null) { + xFapiInteractionId = UUID.randomUUID().toString(); + } + return Response.status(200).entity(finalRespose) + .header("x-fapi-interaction-id", xFapiInteractionId).build(); + } + + @SuppressFBWarnings("JAXRS_ENDPOINT") + // Suppressed content - Endpoint + // Suppression reason - False Positive : This endpoint is a demo endpoint that is not exposed in production + // Suppressed warning count - 1 + @GET + @Path("/accounts/{AccountId}") + @Produces("application/json; charset=utf-8") + public Response getOneAccount(@PathParam("AccountId") String accountId, + @HeaderParam("x-fapi-interaction-id") String xFapiInteractionId, + @HeaderParam("Account-Request-Information") String accountRequestInfo) + throws BankException { + + String response = "{\n" + + " \"Data\": {\n" + + " \"Account\": [\n" + + " {\n" + + " \"AccountId\": \"" + accountId + "\",\n" + + " \"Status\": \"Enabled\",\n" + + " \"StatusUpdateDateTime\": \"2020-04-16T06:06:06+00:00\",\n" + + " \"Currency\": \"GBP\",\n" + + " \"AccountType\": \"Personal\",\n" + + " \"AccountSubType\": \"CurrentAccount\",\n" + + " \"Nickname\": \"Bills\",\n" + + " \"Account\": [{\n" + + " \"SchemeName\": \"SortCodeAccountNumber\",\n" + + " \"Identification\": \"" + accountId + "\",\n" + + " \"Name\": \"Mr Kevin\",\n" + + " \"SecondaryIdentification\": \"00021\"\n" + + " }]\n" + + " }\n" + + " ]\n" + + " },\n" + + " \"Links\": {\n" + + " \"Self\": \"https://api.alphabank.com/open-banking/v4.0/accounts/" + accountId + + "\"\n" + + " },\n" + + " \"Meta\": {\n" + + " \"TotalPages\": 1\n" + + " }\n" + + "}"; + + if (xFapiInteractionId == null) { + xFapiInteractionId = UUID.randomUUID().toString(); + } + return Response.status(200).entity(response) + .header("x-fapi-interaction-id", xFapiInteractionId).build(); + + } + + @SuppressFBWarnings("JAXRS_ENDPOINT") + // Suppressed content - Endpoint + // Suppression reason - False Positive : This endpoint is a demo endpoint that is not exposed in production + // Suppressed warning count - 1 + @GET + @Path("/accounts/{AccountId}/transactions") + @Produces("application/json; charset=utf-8") + public Response getAccountTransactions(@PathParam("AccountId") String accountId, + @HeaderParam("x-fapi-interaction-id") String xFapiInteractionId, + @HeaderParam("Account-Request-Information") String accountRequestInfo) + throws BankException { + + String response = "{\n" + + " \"Data\": {\n" + + " \"Transaction\": [\n" + + " {\n" + + " \"AccountId\": \"" + accountId + "\",\n" + + " \"TransactionId\": \"123\",\n" + + " \"TransactionReference\": \"Ref 1\",\n" + + " \"Amount\": {\n" + + " \"Amount\": \"10.00\",\n" + + " \"Currency\": \"GBP\"\n" + + " },\n" + + " \"CreditDebitIndicator\": \"" + "Credit" + "\",\n" + + " \"Status\": \"Booked\",\n" + + " \"BookingDateTime\": \"2017-04-05T10:43:07+00:00\",\n" + + " \"ValueDateTime\": \"2017-04-05T10:45:22+00:00\",\n" + + " \"TransactionInformation\": \"Cash from Aubrey\",\n" + + " \"BankTransactionCode\": {\n" + + " \"Code\": \"str\",\n" + + " \"SubCode\": \"str\"\n" + + " },\n" + + " \"ProprietaryBankTransactionCode\": {\n" + + " \"Code\": \"Transfer\",\n" + + " \"Issuer\": \"AlphaBank\"\n" + + " },\n" + + " \"Balance\": {\n" + + " \"Amount\": {\n" + + " \"Amount\": \"230.00\",\n" + + " \"Currency\": \"GBP\"\n" + + " },\n" + + " \"CreditDebitIndicator\": \"Credit\",\n" + + " \"Type\": \"InterimBooked\"\n" + + " }\n" + + " }\n" + + " ]\n" + + " },\n" + + " \"Links\": {\n" + + " \"Self\": \"https://api.alphabank.com/open-banking/v4.0/accounts/" + accountId + + "/transactions/\"\n" + + " },\n" + + " \"Meta\": {\n" + + " \"TotalPages\": 1,\n" + + " \"FirstAvailableDateTime\": \"2017-05-03T00:00:00+00:00\",\n" + + " \"LastAvailableDateTime\": \"2017-12-03T00:00:00+00:00\"\n" + + " }\n" + + "}"; + if (xFapiInteractionId == null) { + xFapiInteractionId = UUID.randomUUID().toString(); + } + return Response.status(200).entity(response) + .header("x-fapi-interaction-id", xFapiInteractionId).build(); + } + + @SuppressFBWarnings("JAXRS_ENDPOINT") + // Suppressed content - Endpoint + // Suppression reason - False Positive : This endpoint is a demo endpoint that is not exposed in production + // Suppressed warning count - 1 + @GET + @Path("/accounts/{AccountId}/balances") + @Produces("application/json; charset=utf-8") + public Response getAccountBalance(@PathParam("AccountId") String accountId, + @HeaderParam("x-fapi-interaction-id") String xFapiInteractionId, + @HeaderParam("Account-Request-Information") String accountRequestInfo) + throws BankException { + + String response = "{\n" + + " \"Data\": {\n" + + " \"Balance\": [\n" + + " {\n" + + " \"AccountId\": \"" + accountId + "\",\n" + + " \"Amount\": {\n" + + " \"Amount\": \"1230.00\",\n" + + " \"Currency\": \"GBP\"\n" + + " },\n" + + " \"CreditDebitIndicator\": \"Credit\",\n" + + " \"Type\": \"InterimAvailable\",\n" + + " \"DateTime\": \"2017-04-05T10:43:07+00:00\",\n" + + " \"CreditLine\": [\n" + + " {\n" + + " \"Included\": true,\n" + + " \"Amount\": {\n" + + " \"Amount\": \"1000.00\",\n" + + " \"Currency\": \"GBP\"\n" + + " },\n" + + " \"Type\": \"Pre-Agreed\"\n" + + " }\n" + + " ]\n" + + " }\n" + + " ]\n" + + " },\n" + + " \"Links\": {\n" + + " \"Self\": \"https://api.alphabank.com/open-banking/v4.0/accounts/" + accountId + + "/balances/\"\n" + + " },\n" + + " \"Meta\": {\n" + + " \"TotalPages\": 1\n" + + " }\n" + + "}"; + if (xFapiInteractionId == null) { + xFapiInteractionId = UUID.randomUUID().toString(); + } + return Response.status(200).entity(response) + .header("x-fapi-interaction-id", xFapiInteractionId).build(); + } +} diff --git a/financial-services-accelerator/internal-webapps/org.wso2.financial.services.accelerator.demo.backend/src/main/java/org/wso2/financial/services/accelerator/demo/backend/services/FundsConfirmationService.java b/financial-services-accelerator/internal-webapps/org.wso2.financial.services.accelerator.demo.backend/src/main/java/org/wso2/financial/services/accelerator/demo/backend/services/FundsConfirmationService.java new file mode 100644 index 00000000..f957ebd5 --- /dev/null +++ b/financial-services-accelerator/internal-webapps/org.wso2.financial.services.accelerator.demo.backend/src/main/java/org/wso2/financial/services/accelerator/demo/backend/services/FundsConfirmationService.java @@ -0,0 +1,82 @@ +/** + * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.financial.services.accelerator.demo.backend.services; + +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import net.minidev.json.JSONObject; +import net.minidev.json.parser.JSONParser; +import net.minidev.json.parser.ParseException; +import org.wso2.financial.services.accelerator.demo.backend.BankException; + +import javax.ws.rs.HeaderParam; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Response; + +/** + * FundsConfirmationService class. + */ +@Path("/fundsconfirmationservice/") +public class FundsConfirmationService { + + @SuppressFBWarnings("JAXRS_ENDPOINT") + // Suppressed content - JAXRS_ENDPOINT + // Suppression reason - False Positive : This endpoint is a demo endpoint that is not exposed in production + // Suppressed warning count - 1 + + @POST + @Path("/funds-confirmations") + @Produces("application/json; charset=utf-8") + public Response getAccountBalance(String requestString, + @HeaderParam("x-fapi-interaction-id") String xFapiInteractionId) + throws BankException { + + JSONObject request; + try { + JSONParser parser = new JSONParser(JSONParser.MODE_PERMISSIVE); + request = (JSONObject) parser.parse(requestString); + } catch (ParseException e) { + throw new BankException("Error in casting JSON body " + e); + } + + String consentId = ((JSONObject) request.get("Data")).getAsString("ConsentId"); + String response = "{\n" + + " \"Data\": {\n" + + " \"FundsConfirmationId\": \"836403\",\n" + + " \"ConsentId\": \"" + consentId + "\",\n" + + " \"CreationDateTime\": \"2017-06-02T00:00:00+00:00\",\n" + + " \"FundsAvailable\": true,\n" + + " \"Reference\": \"Purchase02\",\n" + + " \"InstructedAmount\": {\n" + + " \"Amount\": \"20.00\",\n" + + " \"Currency\": \"USD\"\n" + + " }\n" + + " },\n" + + " \"Links\": {\n" + + " \"Self\": \"https://api.alphabank.com/open-banking/v4.0/funds-confirmations/836403\"\n" + + " },\n" + + " \"Meta\": {\n" + + " }\n" + + "}"; + return Response.status(201).entity(response) + .header("x-fapi-interaction-id", xFapiInteractionId).build(); + } +} + diff --git a/financial-services-accelerator/internal-webapps/org.wso2.financial.services.accelerator.demo.backend/src/main/java/org/wso2/financial/services/accelerator/demo/backend/services/PaymentService.java b/financial-services-accelerator/internal-webapps/org.wso2.financial.services.accelerator.demo.backend/src/main/java/org/wso2/financial/services/accelerator/demo/backend/services/PaymentService.java new file mode 100644 index 00000000..0a967def --- /dev/null +++ b/financial-services-accelerator/internal-webapps/org.wso2.financial.services.accelerator.demo.backend/src/main/java/org/wso2/financial/services/accelerator/demo/backend/services/PaymentService.java @@ -0,0 +1,253 @@ +/** + * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.financial.services.accelerator.demo.backend.services; + +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import net.minidev.json.JSONObject; +import net.minidev.json.parser.JSONParser; +import net.minidev.json.parser.ParseException; +import org.apache.commons.lang3.StringUtils; +import org.wso2.financial.services.accelerator.demo.backend.BankException; + +import java.nio.charset.StandardCharsets; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.time.Instant; +import java.util.Base64; +import java.util.Date; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.Map; +import java.util.Queue; +import java.util.Random; +import java.util.UUID; + +import javax.ws.rs.GET; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Response; + +/** + * Payments Service class. + */ +@Path("/paymentservice/") +public class PaymentService { + + public static final String EXPECTED_EXECUTION_TIME = "ExpectedExecutionDateTime"; + public static final String EXPECTED_SETTLEMENT_TIME = "ExpectedSettlementDateTime"; + private static final Map domesticPayments = new HashMap<>(); + private static final int MAX_LIMIT = 500; + private static final Queue domesticPaymentsIdQueue = new LinkedList<>(); + + @SuppressFBWarnings("JAXRS_ENDPOINT") + // Suppressed content - Endpoint + // Suppression reason - False Positive : This endpoint is a demo endpoint that is not exposed in production + // Suppressed warning count - 1 + @GET + @Path("/payment-consents/{ConsentId}/funds-confirmation") + @Produces("application/json; charset=utf-8") + public Response getPaymentTypeFundsConfirmation(@PathParam("ConsentId") String paymentId) { + + Instant currentDate = Instant.now(); + + String response = "{\n" + + " \"Data\": {\n" + + " \"FundsAvailableResult\": {\n" + + " \"FundsAvailableDateTime\": \"" + currentDate.toString() + "\",\n" + + " \"FundsAvailable\": true\n" + + " }\n" + + " },\n" + + " \"Links\": {\n" + + " \"Self\": \"/pisp/payments/" + paymentId + "/funds-confirmation\"\n" + + " },\n" + + " \"Meta\": {}\n" + + "}"; + + return Response.status(200).entity(response) + .header("x-fapi-interaction-id", UUID.randomUUID().toString()) + .build(); + } + + @SuppressFBWarnings("JAXRS_ENDPOINT") + // Suppressed content - Endpoint + // Suppression reason - False Positive : This endpoint is a demo endpoint that is not exposed in production + // Suppressed warning count - 1 + + @POST + @Path("/payments") + @Produces("application/json; charset=utf-8") + public Response paymentSubmission(String requestString, @HeaderParam("x-fapi-interaction-id") String fid, + @HeaderParam("Account-Request-Information") String accountRequestInfo) + throws BankException { + + JSONObject jsonObject; + JSONObject accountRequestInformation; + + try { + accountRequestInformation = getRequest(accountRequestInfo); + JSONParser parser = new JSONParser(JSONParser.MODE_PERMISSIVE); + jsonObject = (JSONObject) parser.parse(requestString); + } catch (ParseException e) { + throw new BankException("Error in casting JSON body " + e); + } + + JSONObject additionalConsentInfo = (JSONObject) accountRequestInformation.get("additionalConsentInfo"); + + JSONObject response = cacheAndGetPaymentResponse(jsonObject, additionalConsentInfo); + return Response.status(201).entity(response.toString()) + .header("x-fapi-interaction-id", fid) + .build(); + + } + + @SuppressFBWarnings("JAXRS_ENDPOINT") + // Suppressed content - Endpoint + // Suppression reason - False Positive : This endpoint is a demo endpoint that is not exposed in production + // Suppressed warning count - 1 + + @GET + @Path("/payments/{paymentId}") + @Produces("application/json; charset=utf-8") + public Response getPaymentTypePayment(@PathParam("paymentId") String paymentId) { + + JSONObject responseObject = null; + if (StringUtils.isNotBlank(paymentId)) { + + responseObject = domesticPayments.get(paymentId); + + } + if (responseObject == null) { + responseObject = new JSONObject(); + } + + + return Response.status(200).entity(responseObject.toString()) + .header("x-fapi-interaction-id", "93bac548-d2de-4546-b106-880a5018460d") + .build(); + } + + private static JSONObject getRequest(String json) throws ParseException { + + String[] splitString = json.split("\\."); + String base64EncodedBody = splitString[1]; + String decodedString = null; + decodedString = new String(Base64.getUrlDecoder() + .decode(base64EncodedBody.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8); + + JSONParser parser = new JSONParser(JSONParser.MODE_PERMISSIVE); + JSONObject jsonObject = (JSONObject) parser.parse(decodedString); + return jsonObject; + } + + @SuppressFBWarnings("PREDICTABLE_RANDOM") + // Suppressed content - PREDICTABLE_RANDOM + // Suppression reason - False Positive : This endpoint is a demo endpoint that is not exposed in production + // Suppressed warning count - 1 + private JSONObject cacheAndGetPaymentResponse(JSONObject requestObject, + JSONObject additionalConsentInfo) + throws BankException { + + JSONObject responseObject; + + int randomPIN = new Random().nextInt(100); + + String status; + String paymentIdValue; + + paymentIdValue = ((JSONObject) requestObject.get("Data")).getAsString("ConsentId"); + paymentIdValue = paymentIdValue + "-" + randomPIN; + + status = "AcceptedSettlementCompleted"; + + + DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX"); + Date date = new Date(); + String currentDate = dateFormat.format(date); + + String readRefundAccount = additionalConsentInfo.getAsString("ReadRefundAccount"); + String cutOffTimeAcceptable = additionalConsentInfo.getAsString("CutOffTimeAcceptable"); + + try { + JSONParser parser = new JSONParser(JSONParser.MODE_PERMISSIVE); + responseObject = (JSONObject) parser.parse(requestObject.toString()); + + JSONObject dataObject = (JSONObject) responseObject.get("Data"); + + dataObject.put("PaymentId", paymentIdValue); + dataObject.put("Status", status); + dataObject.put("CreationDateTime", currentDate); + dataObject.put("StatusUpdateDateTime", currentDate); + + // Add refund account details if requested during consent initiation + if (Boolean.parseBoolean(readRefundAccount)) { + addRefundAccount(dataObject); + } + + JSONObject linksObject = new JSONObject(); + linksObject.put("Self", "/payments/" + paymentIdValue); + responseObject.put("Links", linksObject); + + JSONObject metaObject = new JSONObject(); + responseObject.put("Meta", metaObject); + + responseObject.remove("Risk"); + + } catch (ParseException e) { + throw new BankException(e); + } + addToCache(paymentIdValue, responseObject); + return responseObject; + } + + /** + * Add Refund account details to the response. + * + * @param dataObject + */ + private void addRefundAccount(JSONObject dataObject) { + + String schemeName = "OB.SortCodeAccountNumber"; + String identification = "Identification"; + String name = "NTPC Inc"; + + JSONObject accountData = new JSONObject(); + accountData.put("SchemeName", schemeName); + accountData.put("Identification", identification); + accountData.put("Name", name); + + JSONObject account = new JSONObject(); + account.put("Account", accountData); + + dataObject.put("Refund", account); + } + + private void addToCache(String paymentIdValue, JSONObject responseObject) { + + if (domesticPayments.size() > MAX_LIMIT) { + // Max limit reached + domesticPayments.remove(domesticPaymentsIdQueue.poll()); + } + domesticPayments.put(paymentIdValue, responseObject); + domesticPaymentsIdQueue.add(paymentIdValue); + + } +} diff --git a/financial-services-accelerator/internal-webapps/org.wso2.financial.services.accelerator.demo.backend/src/main/java/org/wso2/financial/services/accelerator/demo/backend/services/VrpService.java b/financial-services-accelerator/internal-webapps/org.wso2.financial.services.accelerator.demo.backend/src/main/java/org/wso2/financial/services/accelerator/demo/backend/services/VrpService.java new file mode 100644 index 00000000..dd8a2c6c --- /dev/null +++ b/financial-services-accelerator/internal-webapps/org.wso2.financial.services.accelerator.demo.backend/src/main/java/org/wso2/financial/services/accelerator/demo/backend/services/VrpService.java @@ -0,0 +1,265 @@ +/** + * Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com). + *

+ * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.wso2.financial.services.accelerator.demo.backend.services; + +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import net.minidev.json.JSONObject; +import net.minidev.json.parser.JSONParser; +import net.minidev.json.parser.ParseException; +import org.apache.commons.lang3.StringUtils; +import org.wso2.financial.services.accelerator.demo.backend.BankException; + +import java.nio.charset.StandardCharsets; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.time.Instant; +import java.util.Base64; +import java.util.Date; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.Map; +import java.util.Queue; +import java.util.Random; +import java.util.UUID; + +import javax.ws.rs.GET; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Response; + + +/** + * Vrp Service class. + */ +@Path("/vrpservice/") +public class VrpService { + + public static final String EXPECTED_EXECUTION_TIME = "ExpectedExecutionDateTime"; + public static final String EXPECTED_SETTLEMENT_TIME = "ExpectedSettlementDateTime"; + private static final int MAX_LIMIT = 500; + private static final Queue domesticVRPsIdQueue = new LinkedList<>(); + private static final Map domesticVRPs = new HashMap<>(); + + + @SuppressFBWarnings("JAXRS_ENDPOINT") + // Suppressed content - Endpoint + // Suppression reason - False Positive : This endpoint is a demo endpoint that is not exposed in production + // Suppressed warning count - 1 + @GET + @Path("/domestic-vrp-consents/{ConsentId}/funds-confirmation") + @Produces("application/json; charset=utf-8") + public Response getPaymentTypeFundsConfirmation(@PathParam("ConsentId") String domesticVRPId) { + + Instant currentDate = Instant.now(); + + String response = "{\n" + + " \"Data\": {\n" + + " \"FundsAvailableResult\": {\n" + + " \"FundsAvailableDateTime\": \"" + currentDate.toString() + "\",\n" + + " \"FundsAvailable\": true\n" + + " }\n" + + " },\n" + + " \"Links\": {\n" + + " \"Self\": \"/vrp/domestic-vrps/" + domesticVRPId + "/funds-confirmation\"\n" + + " },\n" + + " \"Meta\": {}\n" + + "}"; + + return Response.status(200).entity(response) + .header("x-fapi-interaction-id", UUID.randomUUID().toString()) + .build(); + } + + @SuppressFBWarnings("JAXRS_ENDPOINT") + // Suppressed content - Endpoint + // Suppression reason - False Positive : This endpoint is a demo endpoint that is not exposed in production + // Suppressed warning count - 1 + + @POST + @Path("/domestic-vrps") + @Produces("application/json; charset=utf-8") + public Response paymentSubmission(String requestString, @PathParam("paymentType") String paymentType, + @HeaderParam("x-fapi-interaction-id") String fid, + @HeaderParam("Account-Request-Information") String accountRequestInfo) + throws BankException { + + JSONObject jsonObject; + JSONObject accountRequestInformation; + + try { + accountRequestInformation = getRequest(paymentType, accountRequestInfo); + JSONParser parser = new JSONParser(JSONParser.MODE_PERMISSIVE); + jsonObject = (JSONObject) parser.parse(requestString); + } catch (ParseException e) { + throw new BankException("Error in casting JSON body " + e); + } + + JSONObject additionalConsentInfo = (JSONObject) accountRequestInformation.get("additionalConsentInfo"); + + JSONObject response = cacheAndGetPaymentResponse(paymentType, jsonObject, additionalConsentInfo); + return Response.status(201).entity(response.toString()) + .header("x-fapi-interaction-id", fid) + .build(); + + } + + @SuppressFBWarnings("JAXRS_ENDPOINT") + // Suppressed content - Endpoint + // Suppression reason - False Positive : This endpoint is a demo endpoint that is not exposed in production + // Suppressed warning count - 1 + + @GET + @Path("/domestic-vrps/{domesticVRPId}") + @Produces("application/json; charset=utf-8") + public Response getPaymentTypePayment(@PathParam("domesticVRPId") String domesticVRPId) { + + JSONObject responseObject = null; + if (StringUtils.isNotBlank(domesticVRPId)) { + + responseObject = domesticVRPs.get(domesticVRPId); + + } + if (responseObject == null) { + responseObject = new JSONObject(); + } + + + return Response.status(200).entity(responseObject.toString()) + .header("x-fapi-interaction-id", "93bac548-d2de-4546-b106-880a5018460d") + .build(); + } + + + private static JSONObject getRequest(String paymentType, String json) throws ParseException { + + String[] splitString = json.split("\\."); + String base64EncodedBody = splitString[1]; + String decodedString = null; + decodedString = new String(Base64.getUrlDecoder() + .decode(base64EncodedBody.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8); + + JSONParser parser = new JSONParser(JSONParser.MODE_PERMISSIVE); + JSONObject jsonObject = (JSONObject) parser.parse(decodedString); + return jsonObject; + } + + + @SuppressFBWarnings("PREDICTABLE_RANDOM") + // Suppressed content - PREDICTABLE_RANDOM + // Suppression reason - False Positive : This endpoint is a demo endpoint that is not exposed in production + // Suppressed warning count - 1 + private JSONObject cacheAndGetPaymentResponse(String paymentType, JSONObject requestObject, + JSONObject additionalConsentInfo) + throws BankException { + + JSONObject responseObject; + + int randomPIN = new Random().nextInt(100); + + String status; + String paymentIdValue; + + paymentIdValue = ((JSONObject) requestObject.get("Data")).getAsString("ConsentId"); + paymentIdValue = paymentIdValue + "-" + randomPIN; + + status = "AcceptedSettlementCompleted"; + + DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX"); + Date date = new Date(); + String currentDate = dateFormat.format(date); + + String readRefundAccount = additionalConsentInfo.getAsString("ReadRefundAccount"); + String cutOffTimeAcceptable = additionalConsentInfo.getAsString("CutOffTimeAcceptable"); + + try { + JSONParser parser = new JSONParser(JSONParser.MODE_PERMISSIVE); + responseObject = (JSONObject) parser.parse(requestObject.toString()); + + JSONObject dataObject = (JSONObject) responseObject.get("Data"); + + dataObject.put("DomesticVRPId", paymentIdValue); + dataObject.put("Status", status); + dataObject.put("CreationDateTime", currentDate); + dataObject.put("StatusUpdateDateTime", currentDate); + + if ("domestic-vrps".equals(paymentType)) { + JSONObject debtorAccount = new JSONObject(); + debtorAccount.put("SchemeName", "SortCodeAccountNumber"); + debtorAccount.put("SecondaryIdentification", "Roll 2901"); + debtorAccount.put("Name", "Deb Mal"); + debtorAccount.put("Identification", additionalConsentInfo.getAsString("AccountIds") + .split(":")[0].replace("[\"", "")); + + dataObject.put("DebtorAccount", debtorAccount); + + } + + // Add refund account details if requested during consent initiation + if (Boolean.parseBoolean(readRefundAccount)) { + addRefundAccount(dataObject); + } + + JSONObject linksObject = new JSONObject(); + linksObject.put("Self", "/domestic-vrps/" + paymentIdValue); + responseObject.put("Links", linksObject); + + JSONObject metaObject = new JSONObject(); + responseObject.put("Meta", metaObject); + + } catch (ParseException e) { + throw new BankException(e); + } + addToCache(paymentIdValue, responseObject); + return responseObject; + } + + /** + * Add Refund account details to the response. + * + * @param dataObject + */ + private void addRefundAccount(JSONObject dataObject) { + + String schemeName = "OB.SortCodeAccountNumber"; + String identification = "Identification"; + String name = "NTPC Inc"; + + JSONObject accountData = new JSONObject(); + accountData.put("SchemeName", schemeName); + accountData.put("Identification", identification); + accountData.put("Name", name); + + JSONObject account = new JSONObject(); + account.put("Account", accountData); + + dataObject.put("Refund", account); + } + + private void addToCache(String paymentIdValue, JSONObject responseObject) { + + if (domesticVRPs.size() > MAX_LIMIT) { + // Max limit reached + domesticVRPs.remove(domesticVRPsIdQueue.poll()); + } + domesticVRPs.put(paymentIdValue, responseObject); + domesticVRPsIdQueue.add(paymentIdValue); + } +} diff --git a/financial-services-accelerator/internal-webapps/org.wso2.financial.services.accelerator.demo.backend/src/main/resources/findbugs-include.xml b/financial-services-accelerator/internal-webapps/org.wso2.financial.services.accelerator.demo.backend/src/main/resources/findbugs-include.xml new file mode 100644 index 00000000..c6b932b1 --- /dev/null +++ b/financial-services-accelerator/internal-webapps/org.wso2.financial.services.accelerator.demo.backend/src/main/resources/findbugs-include.xml @@ -0,0 +1,22 @@ + + + + + + diff --git a/financial-services-accelerator/internal-webapps/org.wso2.financial.services.accelerator.demo.backend/src/main/webapp/META-INF/webapp-classloading.xml b/financial-services-accelerator/internal-webapps/org.wso2.financial.services.accelerator.demo.backend/src/main/webapp/META-INF/webapp-classloading.xml new file mode 100644 index 00000000..c1d9dfcc --- /dev/null +++ b/financial-services-accelerator/internal-webapps/org.wso2.financial.services.accelerator.demo.backend/src/main/webapp/META-INF/webapp-classloading.xml @@ -0,0 +1,34 @@ + + + + + + + + false + + + Carbon,CXF3 + diff --git a/financial-services-accelerator/internal-webapps/org.wso2.financial.services.accelerator.demo.backend/src/main/webapp/WEB-INF/cxf-servlet.xml b/financial-services-accelerator/internal-webapps/org.wso2.financial.services.accelerator.demo.backend/src/main/webapp/WEB-INF/cxf-servlet.xml new file mode 100644 index 00000000..65daf243 --- /dev/null +++ b/financial-services-accelerator/internal-webapps/org.wso2.financial.services.accelerator.demo.backend/src/main/webapp/WEB-INF/cxf-servlet.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/financial-services-accelerator/internal-webapps/org.wso2.financial.services.accelerator.demo.backend/src/main/webapp/WEB-INF/web.xml b/financial-services-accelerator/internal-webapps/org.wso2.financial.services.accelerator.demo.backend/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 00000000..442eec82 --- /dev/null +++ b/financial-services-accelerator/internal-webapps/org.wso2.financial.services.accelerator.demo.backend/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,152 @@ + + + + + + Financial-Services + + + AccountServiceJAXServlet + AccountService JAX-WS/JAX-RS Servlet + AccountService JAX-WS/JAX-RS Endpoint + + org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet + + + service-list-stylesheet + servicelist.css + + + jersey.config.server.provider.classnames + org.glassfish.jersey.media.multipart.MultiPartFeature + + + 1 + + + jaxrs.serviceClasses + + org.wso2.financial.services.accelerator.demo.backend.services.AccountService + + + + + + PaymentServiceJAXServlet + PaymentService JAX-WS/JAX-RS Servlet + PaymentService JAX-WS/JAX-RS Endpoint + + org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet + + + service-list-stylesheet + servicelist.css + + + jersey.config.server.provider.classnames + org.glassfish.jersey.media.multipart.MultiPartFeature + + + 1 + + + jaxrs.serviceClasses + + org.wso2.financial.services.accelerator.demo.backend.services.PaymentService + + + + + + VrpServiceJAXServlet + VrpService JAX-WS/JAX-RS Servlet + VrpService JAX-WS/JAX-RS Endpoint + + org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet + + + service-list-stylesheet + servicelist.css + + + jersey.config.server.provider.classnames + org.glassfish.jersey.media.multipart.MultiPartFeature + + + 1 + + + jaxrs.serviceClasses + + org.wso2.financial.services.accelerator.demo.backend.services.VrpService + + + + + + FundsConfirmationServiceJAXServlet + FundsConfirmationService JAX-WS/JAX-RS Servlet + FundsConfirmationService JAX-WS/JAX-RS Endpoint + + org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet + + + service-list-stylesheet + servicelist.css + + + jersey.config.server.provider.classnames + org.glassfish.jersey.media.multipart.MultiPartFeature + + + 1 + + + jaxrs.serviceClasses + + org.wso2.financial.services.accelerator.demo.backend.services.FundsConfirmationService + + + + + + AccountServiceJAXServlet + /services/accounts/* + + + PaymentServiceJAXServlet + /services/payments/* + + + VrpServiceJAXServlet + /services/domestic-vrps/* + + + FundsConfirmationServiceJAXServlet + /services/fundsConfirmation/* + + + + 60 + + + diff --git a/financial-services-accelerator/pom.xml b/financial-services-accelerator/pom.xml index c2b8ba0d..ba196537 100644 --- a/financial-services-accelerator/pom.xml +++ b/financial-services-accelerator/pom.xml @@ -30,7 +30,6 @@ WSO2 Financial Services Accelerator financial-services-accelerator pom - 4.0.0-SNAPSHOT components/org.wso2.financial.services.accelerator.common @@ -41,5 +40,6 @@ components/org.wso2.financial.services.accelerator.gateway internal-webapps/org.wso2.financial.services.accelerator.consent.mgt.endpoint internal-webapps/org.wso2.financial.services.accelerator.authentication.endpoint + internal-webapps/org.wso2.financial.services.accelerator.demo.backend diff --git a/pom.xml b/pom.xml index 879d236b..025a1d4e 100644 --- a/pom.xml +++ b/pom.xml @@ -373,6 +373,11 @@ javax.ws.rs-api ${javax.ws.rs-api.version} + + javax.ws.rs + jsr311-api + ${javax.ws.rs.version} + org.apache.cxf cxf-core @@ -580,6 +585,7 @@ 1.0.0.wso2v3 1.6.1 2.1.1 + 1.1.1 5.1.2.RELEASE 2.5 3.3.7