From 0d2fca32b65c89325b70b53418359e5577564c5b Mon Sep 17 00:00:00 2001 From: kalpana Date: Fri, 24 Nov 2023 13:44:43 +0530 Subject: [PATCH] VRP consent initiation flow implementation --- .../repository/conf/open-banking.xml.j2 | 5 + .../common/util/ErrorConstants.java | 14 +- .../common/ConsentExtensionConstants.java | 34 +- .../AcceleratorConsentExtensionFactory.java | 5 + .../manage/impl/VRPConsentRequestHandler.java | 192 +++++++++ .../validator/VRPConsentRequestValidator.java | 288 +++++++++++++ .../extensions/util/ConsentManageUtil.java | 395 +++++++++++++++++- 7 files changed, 918 insertions(+), 15 deletions(-) create mode 100644 open-banking-accelerator/components/consent-management/com.wso2.openbanking.accelerator.consent.extensions/src/main/java/com/wso2/openbanking/accelerator/consent/extensions/manage/impl/VRPConsentRequestHandler.java create mode 100644 open-banking-accelerator/components/consent-management/com.wso2.openbanking.accelerator.consent.extensions/src/main/java/com/wso2/openbanking/accelerator/consent/extensions/manage/validator/VRPConsentRequestValidator.java diff --git a/open-banking-accelerator/accelerators/ob-is/carbon-home/repository/resources/conf/templates/repository/conf/open-banking.xml.j2 b/open-banking-accelerator/accelerators/ob-is/carbon-home/repository/resources/conf/templates/repository/conf/open-banking.xml.j2 index 9b0a5cfa..e06fa574 100644 --- a/open-banking-accelerator/accelerators/ob-is/carbon-home/repository/resources/conf/templates/repository/conf/open-banking.xml.j2 +++ b/open-banking-accelerator/accelerators/ob-is/carbon-home/repository/resources/conf/templates/repository/conf/open-banking.xml.j2 @@ -206,6 +206,11 @@ {% else %} https://localhost:8243/open-banking/{version}/cbpii/ {% endif %} + {% if open_banking.consent.vrp_consent_self_link is defined %} + {{open_banking.consent.vrp_consent_self_link}} + {% else %} + https://localhost:8243/open-banking/{version}/vrp/ + {% endif %} {% if open_banking.consent.data_retention.enabled is defined %} {{open_banking.consent.data_retention.enabled}} diff --git a/open-banking-accelerator/components/com.wso2.openbanking.accelerator.common/src/main/java/com/wso2/openbanking/accelerator/common/util/ErrorConstants.java b/open-banking-accelerator/components/com.wso2.openbanking.accelerator.common/src/main/java/com/wso2/openbanking/accelerator/common/util/ErrorConstants.java index 7f3ce859..182b4c35 100644 --- a/open-banking-accelerator/components/com.wso2.openbanking.accelerator.common/src/main/java/com/wso2/openbanking/accelerator/common/util/ErrorConstants.java +++ b/open-banking-accelerator/components/com.wso2.openbanking.accelerator.common/src/main/java/com/wso2/openbanking/accelerator/common/util/ErrorConstants.java @@ -108,7 +108,6 @@ public class ErrorConstants { public static final String PATH_CONSENT_ID = "Data.Initiation.Consent-id"; public static final String PATH_DATA = "Data"; public static final String PATH_INITIATION = "Data.Initiation"; - public static final String PATH_RISK = "Data.Risk"; public static final String PATH_URL = "Data.Url"; public static final String PATH_EXPIRATION_DATE = "Data.Expiration-Date"; public static final String MSG_MISSING_DEBTOR_ACC = "Mandatory parameter DebtorAccount is missing in the payload."; @@ -207,9 +206,6 @@ public class ErrorConstants { ErrorConstants.PATH_DATA; public static final String INITIATION_NOT_FOUND = "Initiation is not found or empty in the request.:" + ErrorConstants.PATH_INITIATION; - public static final String RISK_MISMATCH = "RISK Does Not Match.:" + ErrorConstants.PATH_RISK; - public static final String RISK_NOT_FOUND = "RISK is not found or empty in the request.:" + - ErrorConstants.PATH_RISK; public static final String INVALID_URI_ERROR = "Path requested is invalid. :" + ErrorConstants.PATH_URL; public static final String COF_CONSENT_STATE_INVALID = "Confirmation of Funds validation failed due to invalid" + " consent state.:" + ErrorConstants.PATH_STATUS; @@ -221,9 +217,15 @@ public class ErrorConstants { " retrieval request"; public static final String INVALID_CONSENT_ID = "Invalid Consent Id found in the request"; public static final String CONSENT_ID_NOT_FOUND = "Consent ID not available in consent data"; - public static final String FIELD_INVALID_DATE = "OB.Field.InvalidDate"; public static final String EXPIRED_DATE_ERROR = "The ExpirationDateTime value has to be a future date."; - + public static final String PATH_MAXIMUM_INDIVIDUAL_AMOUNT = "Data.ControlParameters.MaximumIndividualAmount.Amount"; + public static final String INVALID_MAXIMUM_INDIVIDUAL_AMOUNT = "Invalid value for Amount in MaximumIndividualAmount"; + public static final String INVALID_CURRENCY = "Invalid value for currency in MaximumIndividualAmount" ; + public static final String INVALID_PERIOD_ALIGNMENT = "Invalid value for period alignment in PeriodicLimits"; + public static final String INVALID_PERIOD_TYPE = "Invalid value for period type in PeriodicLimits"; + public static final String PATH_PERIOD_TYPE = "Data.ControlParameters.PeriodicLimits.PeriodType"; + public static final String INVALID_VALID_TO_DATE = "Valid to Date specified in the request is invalid"; + public static final String PATH_VALID_TO_DATE = "Data.ControlParameters.ValidToDateTime"; } diff --git a/open-banking-accelerator/components/consent-management/com.wso2.openbanking.accelerator.consent.extensions/src/main/java/com/wso2/openbanking/accelerator/consent/extensions/common/ConsentExtensionConstants.java b/open-banking-accelerator/components/consent-management/com.wso2.openbanking.accelerator.consent.extensions/src/main/java/com/wso2/openbanking/accelerator/consent/extensions/common/ConsentExtensionConstants.java index 6d02d829..f18db57b 100644 --- a/open-banking-accelerator/components/consent-management/com.wso2.openbanking.accelerator.consent.extensions/src/main/java/com/wso2/openbanking/accelerator/consent/extensions/common/ConsentExtensionConstants.java +++ b/open-banking-accelerator/components/consent-management/com.wso2.openbanking.accelerator.consent.extensions/src/main/java/com/wso2/openbanking/accelerator/consent/extensions/common/ConsentExtensionConstants.java @@ -48,6 +48,8 @@ public class ConsentExtensionConstants { public static final String HTTP_CODE = "httpCode"; public static final String ERRORS = "errors"; public static final String PAYMENTS = "payments"; + public static final String VRP = "vrp"; + public static final String DATA = "Data"; public static final String INITIATION = "Initiation"; public static final String STATUS = "Status"; @@ -108,7 +110,6 @@ public class ConsentExtensionConstants { public static final String OPENBANKING_INTENT_ID = "openbanking_intent_id"; public static final String VALUE = "value"; public static final String AUTHORIZED_STATUS = "authorised"; - public static final String EXPIRATION_DATE = "ExpirationDateTime"; public static final String EXPIRATION_DATE_TITLE = "Expiration Date Time"; public static final String INSTRUCTED_AMOUNT_TITLE = "Instructed Amount"; @@ -121,8 +122,8 @@ public class ConsentExtensionConstants { public static final String INSTRUCTION_IDENTIFICATION = "InstructionIdentification"; public static final String REJECTED_STATUS = "rejected"; public static final String OPEN_ENDED_AUTHORIZATION = "Open Ended Authorization Requested"; - public static final String DEBTOR_ACC_TITLE = "Debtor Account"; - public static final String SCHEME_NAME_TITLE = "Scheme Name"; + public static final String DEBTOR_ACC_TITLE = "DebtorAccount"; + public static final String SCHEME_NAME_TITLE = "SchemeName"; public static final String IDENTIFICATION_TITLE = "Identification"; public static final String NAME_TITLE = "Name"; public static final String SECONDARY_IDENTIFICATION_TITLE = "Secondary Identification"; @@ -153,19 +154,38 @@ public class ConsentExtensionConstants { public static final String ACCOUNTS_SELF_LINK = "Consent.AccountAPIURL"; public static final String PAYMENT_SELF_LINK = "Consent.PaymentAPIURL"; public static final String COF_SELF_LINK = "Consent.FundsConfirmationAPIURL"; + public static final String VRP_SELF_LINK = "Consent.VRPAPIURL"; public static final String REVOKED_STATUS = "revoked"; - public static final String DISPLAY_NAME = "display_name"; public static final String ACCOUNT_DATA = "account_data"; public static final String SELECTED_ACCOUNT = "selectedAccount"; public static final String PAYMENT_COF_PATH = "funds-confirmation"; - public static final String AWAITING_UPLOAD_STATUS = "awaitingUpload"; - public static final String OB_REVOKED_STATUS = "Revoked"; public static final String OB_REJECTED_STATUS = "Rejected"; public static final String OB_AUTHORIZED_STATUS = "Authorised"; public static final String OB_AWAITING_AUTH_STATUS = "AwaitingAuthorisation"; public static final String OB_AWAITING_UPLOAD_STATUS = "AwaitingUpload"; - + public static final String VRP_CONSENT_PATH = "domestic-vrp-consents"; + public static final String VRP_PAYMENT = "vrp-payment"; + public static final String PAID_AMOUNT = "paid-amount"; + public static final String LAST_PAYMENT_DATE = "last-payment-date"; + public static final String AUTH_TYPE_AUTHORIZATION = "authorization"; + public static final String CONTROL_PARAMETERS = "ControlParameters"; + public static final String MAXIMUM_INDIVIDUAL_AMOUNT = "MaximumIndividualAmount"; + public static final String PERIOD_ALIGNMENT = "PeriodicAlignment"; + public static final String PERIODIC_LIMITS = "PeriodicLimits"; + public static final String PERIOD_TYPE = "PeriodType"; + public static final String PERIOD_AMOUNT_LIMIT = "Amount"; + public static final String CONSENT = "consent-periodicAlignment"; + public static final String CALENDER = "calender-periodicAlignment"; + public static final String DAY = "Day"; + public static final String WEEK = "Week"; + public static final String FORTNIGHT = "Fortnight"; + public static final String MONTH = "Month"; + public static final String HALF_YEAR = "Half-year"; + public static final String YEAR = "Year"; + public static final String VALID_TO_DATE_TIME = "ValidToDateTime"; + public static final String VALID_FROM_DATE_TIME = "ValidFromDateTime"; + public static final String VRP_RESPONSE_PROCESS_PATH = "vrp-response-process"; } diff --git a/open-banking-accelerator/components/consent-management/com.wso2.openbanking.accelerator.consent.extensions/src/main/java/com/wso2/openbanking/accelerator/consent/extensions/common/factory/AcceleratorConsentExtensionFactory.java b/open-banking-accelerator/components/consent-management/com.wso2.openbanking.accelerator.consent.extensions/src/main/java/com/wso2/openbanking/accelerator/consent/extensions/common/factory/AcceleratorConsentExtensionFactory.java index ef849604..0c2197bd 100644 --- a/open-banking-accelerator/components/consent-management/com.wso2.openbanking.accelerator.consent.extensions/src/main/java/com/wso2/openbanking/accelerator/consent/extensions/common/factory/AcceleratorConsentExtensionFactory.java +++ b/open-banking-accelerator/components/consent-management/com.wso2.openbanking.accelerator.consent.extensions/src/main/java/com/wso2/openbanking/accelerator/consent/extensions/common/factory/AcceleratorConsentExtensionFactory.java @@ -30,6 +30,7 @@ import com.wso2.openbanking.accelerator.consent.extensions.manage.impl.CofConsentRequestHandler; import com.wso2.openbanking.accelerator.consent.extensions.manage.impl.ConsentManageRequestHandler; import com.wso2.openbanking.accelerator.consent.extensions.manage.impl.PaymentConsentRequestHandler; +import com.wso2.openbanking.accelerator.consent.extensions.manage.impl.VRPConsentRequestHandler; /** * Factory class to get the class based in request type. @@ -55,6 +56,10 @@ public static ConsentManageRequestHandler getConsentManageRequestValidator(Strin case ConsentExtensionConstants.PAYMENT_CONSENT_PATH: consentManageRequestHandler = new PaymentConsentRequestHandler(); break; + case ConsentExtensionConstants.VRP_CONSENT_PATH: + case ConsentExtensionConstants.VRP_RESPONSE_PROCESS_PATH: + consentManageRequestHandler = new VRPConsentRequestHandler(); + break; default: return null; } diff --git a/open-banking-accelerator/components/consent-management/com.wso2.openbanking.accelerator.consent.extensions/src/main/java/com/wso2/openbanking/accelerator/consent/extensions/manage/impl/VRPConsentRequestHandler.java b/open-banking-accelerator/components/consent-management/com.wso2.openbanking.accelerator.consent.extensions/src/main/java/com/wso2/openbanking/accelerator/consent/extensions/manage/impl/VRPConsentRequestHandler.java new file mode 100644 index 00000000..45ac82aa --- /dev/null +++ b/open-banking-accelerator/components/consent-management/com.wso2.openbanking.accelerator.consent.extensions/src/main/java/com/wso2/openbanking/accelerator/consent/extensions/manage/impl/VRPConsentRequestHandler.java @@ -0,0 +1,192 @@ +/** + * Copyright (c) 2021-2022, WSO2 LLC. (https://www.wso2.com). All Rights Reserved. + * This software is the property of WSO2 LLC. and its suppliers, if any. + * Dissemination of any information or reproduction of any material contained + * herein in any form is strictly forbidden, unless permitted by WSO2 expressly. + * You may not alter or remove any copyright or other notice from copies of this content. + */ + +package com.wso2.openbanking.accelerator.consent.extensions.manage.impl; + +import com.wso2.openbanking.accelerator.common.exception.ConsentManagementException; +import com.wso2.openbanking.accelerator.common.util.ErrorConstants; +import com.wso2.openbanking.accelerator.consent.extensions.common.ConsentException; +import com.wso2.openbanking.accelerator.consent.extensions.common.ConsentExtensionConstants; +import com.wso2.openbanking.accelerator.consent.extensions.common.ConsentExtensionUtils; +import com.wso2.openbanking.accelerator.consent.extensions.common.ConsentServiceUtil; +import com.wso2.openbanking.accelerator.consent.extensions.common.ResponseStatus; +import com.wso2.openbanking.accelerator.consent.extensions.internal.ConsentExtensionsDataHolder; +import com.wso2.openbanking.accelerator.consent.extensions.manage.model.ConsentManageData; +import com.wso2.openbanking.accelerator.consent.extensions.manage.validator.VRPConsentRequestValidator; +import com.wso2.openbanking.accelerator.consent.extensions.util.ConsentManageUtil; +import com.wso2.openbanking.accelerator.consent.mgt.dao.models.ConsentResource; +import com.wso2.openbanking.accelerator.consent.mgt.dao.models.DetailedConsentResource; +import net.minidev.json.JSONArray; +import net.minidev.json.JSONObject; +import net.minidev.json.parser.JSONParser; +import net.minidev.json.parser.ParseException; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.util.HashMap; +import java.util.Map; + +import static com.wso2.openbanking.accelerator.consent.extensions.common.ConsentExtensionConstants.AUTH_TYPE_AUTHORIZATION; +import static com.wso2.openbanking.accelerator.consent.extensions.common.ConsentExtensionConstants.CREATED_STATUS; + +/** + * Consent Manage request handler class for VRP Payment Request Validation. + */ +public class VRPConsentRequestHandler implements ConsentManageRequestHandler { + + private static final Log log = LogFactory.getLog(VRPConsentRequestHandler.class); + + /** + * Method to handle Variable Recurring Payment Consent Manage Post Request. + * + * @param consentManageData Object containing request details + */ + @Override + public void handleConsentManagePost(ConsentManageData consentManageData) { + + try { + //Validate cutoff datetime + if (ConsentExtensionUtils.shouldInitiationRequestBeRejected()) { + log.error(ErrorConstants.MSG_ELAPSED_CUT_OFF_DATE_TIME); + throw new ConsentException(ResponseStatus.BAD_REQUEST, ErrorConstants.PAYMENT_INITIATION_HANDLE_ERROR); + } + + //Get the request payload from the ConsentManageData + Object request = consentManageData.getPayload(); + if (!(request instanceof JSONObject)) { + log.error(ErrorConstants.PAYLOAD_FORMAT_ERROR); + throw new ConsentException(ResponseStatus.BAD_REQUEST, ErrorConstants.INVALID_REQ_PAYLOAD); + } + + JSONObject requestObject = (JSONObject) request; + + //Set request object to the response + JSONObject response = requestObject; + + //Check Idempotency key exists + if (StringUtils.isEmpty(consentManageData.getHeaders() + .get(ConsentExtensionConstants.X_IDEMPOTENCY_KEY))) { + throw new ConsentException(ResponseStatus.BAD_REQUEST, ErrorConstants.IDEMPOTENCY_KEY_NOT_FOUND); + } + + //Handle payment initiation flows + handlePaymentPost(consentManageData, requestObject, response); + + } catch (ConsentManagementException e) { + log.error(e.getMessage()); + throw new ConsentException(ResponseStatus.INTERNAL_SERVER_ERROR, + ErrorConstants.PAYMENT_INITIATION_HANDLE_ERROR); + } + } + + + @Override + public void handleConsentManageGet(ConsentManageData consentManageData) { + + String consentId = consentManageData.getRequestPath().split("/")[1]; + if (ConsentManageUtil.isConsentIdValid(consentId)) { + try { + ConsentResource consent = ConsentServiceUtil.getConsentService().getConsent(consentId, + false); + if (consent == null) { + throw new ConsentException(ResponseStatus.BAD_REQUEST, ErrorConstants.RESOURCE_CONSENT_MISMATCH); + } + // Check whether the client id is matching + if (!consent.getClientID().equals(consentManageData.getClientId())) { + //Throwing same error as null scenario since client will not be able to identify if consent + // exists if consent does not belong to them + throw new ConsentException(ResponseStatus.BAD_REQUEST, + ErrorConstants.NO_CONSENT_FOR_CLIENT_ERROR); + } + JSONObject receiptJSON = (JSONObject) new JSONParser(JSONParser.MODE_PERMISSIVE). + parse(consent.getReceipt()); + consentManageData.setResponsePayload(ConsentManageUtil + .getInitiationRetrievalResponse(receiptJSON, consent, consentManageData, + ConsentExtensionConstants.VRP)); + consentManageData.setResponseStatus(ResponseStatus.OK); + } catch (ConsentManagementException | ParseException e) { + throw new ConsentException(ResponseStatus.INTERNAL_SERVER_ERROR, + ErrorConstants.ACC_INITIATION_RETRIEVAL_ERROR); + } + } else { + throw new ConsentException(ResponseStatus.BAD_REQUEST, ErrorConstants.INVALID_CONSENT_ID); + } + } + + @Override + public void handleConsentManageDelete(ConsentManageData consentManageData) { + + ConsentManageUtil.handleConsentManageDelete(consentManageData); + } + + /** + * Method to handle the Variable Recurring Payment POST requests. + * + * @param consentManageData Object containing request details + * @param requestObject Request payload + * @param response Response + */ + private void handlePaymentPost(ConsentManageData consentManageData, JSONObject requestObject, JSONObject response) + throws ConsentManagementException { + + DetailedConsentResource createdConsent; + + //Validate Payment Initiation request + JSONObject validationResponse = VRPConsentRequestValidator.validatePaymentInitiation(requestObject); + + //Throw an error if the initiation payload is not valid + if (!((boolean) validationResponse.get(ConsentExtensionConstants.IS_VALID))) { + + log.error(ErrorConstants.PAYLOAD_INVALID); + throw new ConsentException((ResponseStatus) validationResponse + .get(ConsentExtensionConstants.HTTP_CODE), + String.valueOf(validationResponse.get(ConsentExtensionConstants.ERRORS))); + } + + ConsentResource requestedConsent = new ConsentResource(consentManageData.getClientId(), + requestObject.toJSONString(), ConsentExtensionConstants.VRP, + ConsentExtensionConstants.AWAITING_AUTH_STATUS); + + createdConsent = ConsentExtensionsDataHolder.getInstance().getConsentCoreService() + .createAuthorizableConsent(requestedConsent, null, + CREATED_STATUS, AUTH_TYPE_AUTHORIZATION, true); + + //Set consent attributes for storing + Map consentAttributes = new HashMap(); + consentAttributes.put(ConsentExtensionConstants.IDEMPOTENCY_KEY, consentManageData.getHeaders() + .get(ConsentExtensionConstants.X_IDEMPOTENCY_KEY)); + //Store consent attributes + ConsentServiceUtil.getConsentService().storeConsentAttributes(createdConsent.getConsentID(), + consentAttributes); + consentManageData.setResponsePayload(ConsentManageUtil.getInitiationResponse(response, createdConsent, + consentManageData, ConsentExtensionConstants.VRP_PAYMENT)); + + //Set Control Parameters as consent attributes to store + JSONObject controlParameters = (JSONObject) ((JSONObject) ((JSONObject) consentManageData.getPayload()) + .get(ConsentExtensionConstants.DATA)).get(ConsentExtensionConstants.CONTROL_PARAMETERS); + consentAttributes.put(ConsentExtensionConstants.MAXIMUM_INDIVIDUAL_AMOUNT, ((JSONObject) (controlParameters) + .get(ConsentExtensionConstants.MAXIMUM_INDIVIDUAL_AMOUNT)).get(ConsentExtensionConstants.AMOUNT) + .toString()); + consentAttributes.put(ConsentExtensionConstants.PERIOD_TYPE, ((JSONObject) ((JSONArray) (controlParameters) + .get(ConsentExtensionConstants.PERIODIC_LIMITS)).get(0)).get(ConsentExtensionConstants.PERIOD_TYPE) + .toString()); + consentAttributes.put(ConsentExtensionConstants.PERIOD_AMOUNT_LIMIT, ((JSONObject) + ((JSONArray) (controlParameters).get(ConsentExtensionConstants.PERIODIC_LIMITS)).get(0)) + .get(ConsentExtensionConstants.PERIOD_AMOUNT_LIMIT).toString()); + consentAttributes.put(ConsentExtensionConstants.PAID_AMOUNT, "0"); + consentAttributes.put(ConsentExtensionConstants.LAST_PAYMENT_DATE, "0"); + + Map headers = consentManageData.getHeaders(); + //Setting response headers + //Setting created time and idempotency to headers to handle idempotency in Gateway + consentManageData.setResponseHeader(ConsentExtensionConstants.X_IDEMPOTENCY_KEY, + headers.get(ConsentExtensionConstants.X_IDEMPOTENCY_KEY)); + consentManageData.setResponseStatus(ResponseStatus.CREATED); + } +} diff --git a/open-banking-accelerator/components/consent-management/com.wso2.openbanking.accelerator.consent.extensions/src/main/java/com/wso2/openbanking/accelerator/consent/extensions/manage/validator/VRPConsentRequestValidator.java b/open-banking-accelerator/components/consent-management/com.wso2.openbanking.accelerator.consent.extensions/src/main/java/com/wso2/openbanking/accelerator/consent/extensions/manage/validator/VRPConsentRequestValidator.java new file mode 100644 index 00000000..0bb6bae1 --- /dev/null +++ b/open-banking-accelerator/components/consent-management/com.wso2.openbanking.accelerator.consent.extensions/src/main/java/com/wso2/openbanking/accelerator/consent/extensions/manage/validator/VRPConsentRequestValidator.java @@ -0,0 +1,288 @@ +/** + * Copyright (c) 2022, WSO2 Inc. (http://www.wso2.com). All Rights Reserved. + * + * This software is the property of WSO2 Inc. and its suppliers, if any. + * Dissemination of any information or reproduction of any material contained + * herein is strictly forbidden, unless permitted by WSO2 in accordance with + * the WSO2 Software License available at https://wso2.com/licenses/eula/3.1. + * For specific language governing the permissions and limitations under this + * license, please see the license as well as any agreement you’ve entered into + * with WSO2 governing the purchase of this software and any associated services. + */ + +package com.wso2.openbanking.accelerator.consent.extensions.manage.validator; +import com.wso2.openbanking.accelerator.common.util.ErrorConstants; +import com.wso2.openbanking.accelerator.consent.extensions.common.ConsentExtensionConstants; +import com.wso2.openbanking.accelerator.consent.extensions.common.ResponseStatus; +import com.wso2.openbanking.accelerator.consent.extensions.util.ConsentManageUtil; +import net.minidev.json.JSONArray; +import net.minidev.json.JSONObject; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.time.OffsetDateTime; +import java.util.Iterator; + + +/** + * Consent Manage validator class for Variable Recurring Payment Request Validation. + */ +public class VRPConsentRequestValidator { + + private static final Log log = LogFactory.getLog(VRPConsentRequestValidator.class); + + public static final String MAXIMUM_INDIVIDUAL_AMOUNT_NOT_FOUND = "Instructed Amount isn't present in the payload"; + + public static final String PATH_MAXIMUM_INDIVIDUAL_CURRENCY = "Data.ControlParameters." + + "MaximumIndividualAmount.Currency"; + + public static final String MAXIMUM_INDIVIDUAL_AMOUNT_CURRENCY_NOT_FOUND = "Instructed currency isn't " + + "present in the payload"; + + public static final String INVALID_PERIOD_ALIGNMENT = "Invalid value for period alignment in PeriodicLimits"; + + public static final String PATH_PERIOD_ALIGNMENT = "Data.ControlParameters.PeriodLimits.PeriodAlignment"; + + /** + * Method to validate variable recurring payment control parameters. + * + * @param controlParameters Initiation Object + * @return validation response object + */ + public static JSONObject validatecontrolParameters(JSONObject controlParameters) { + JSONObject validationResponse = new JSONObject(); + + //Validate Maximum individual amount in control parameters + if (controlParameters.containsKey(ConsentExtensionConstants.MAXIMUM_INDIVIDUAL_AMOUNT)) { + JSONObject maximumIndividualAmount = (JSONObject) controlParameters + .get(ConsentExtensionConstants.MAXIMUM_INDIVIDUAL_AMOUNT); + Object amount = maximumIndividualAmount.get(ConsentExtensionConstants.AMOUNT); + Object currency = maximumIndividualAmount.get(ConsentExtensionConstants.CURRENCY); + + // validate amount + if (!ConsentManageUtil.validateAmount(maximumIndividualAmount)) { + log.error(ErrorConstants.INVALID_MAXIMUM_INDIVIDUAL_AMOUNT); + return ConsentManageUtil.getValidationResponse(ErrorConstants.FIELD_INVALID, + ErrorConstants.INVALID_MAXIMUM_INDIVIDUAL_AMOUNT, + ErrorConstants.PATH_MAXIMUM_INDIVIDUAL_AMOUNT); + } + + if (amount == null || StringUtils.isEmpty(amount.toString())) { + log.error(MAXIMUM_INDIVIDUAL_AMOUNT_NOT_FOUND); + validationResponse.put(ConsentExtensionConstants.IS_VALID, false); + validationResponse.put(ConsentExtensionConstants.HTTP_CODE, ResponseStatus.BAD_REQUEST); + validationResponse.put(ConsentExtensionConstants.ERRORS, MAXIMUM_INDIVIDUAL_AMOUNT_NOT_FOUND); + return validationResponse; + } + + //validate currency + if (!ConsentManageUtil.validateCurrency(maximumIndividualAmount)) { + log.error(ErrorConstants.INVALID_CURRENCY); + validationResponse.put(ConsentExtensionConstants.IS_VALID, false); + validationResponse.put(ConsentExtensionConstants.HTTP_CODE, ResponseStatus.BAD_REQUEST); + validationResponse.put(ConsentExtensionConstants.ERRORS, + ErrorConstants.PATH_MAXIMUM_INDIVIDUAL_AMOUNT); + return ConsentManageUtil.getValidationResponse(ErrorConstants.FIELD_INVALID, + ErrorConstants.INVALID_CURRENCY, ErrorConstants.PATH_MAXIMUM_INDIVIDUAL_AMOUNT); + } + + if (currency == null || StringUtils.isEmpty(currency.toString())) { + log.error(MAXIMUM_INDIVIDUAL_AMOUNT_CURRENCY_NOT_FOUND); + validationResponse.put(ConsentExtensionConstants.IS_VALID, false); + validationResponse.put(ConsentExtensionConstants.HTTP_CODE, ResponseStatus.BAD_REQUEST); + validationResponse.put(ConsentExtensionConstants.ERRORS, + MAXIMUM_INDIVIDUAL_AMOUNT_CURRENCY_NOT_FOUND); + return validationResponse; + } + } + + //Validate RequestedExecutionDateTime in controlParameters + if (controlParameters.containsKey(ConsentExtensionConstants.VALID_TO_DATE_TIME)) { + + String validTo = controlParameters.getAsString(ConsentExtensionConstants.VALID_TO_DATE_TIME); + String validFrom = controlParameters.getAsString(ConsentExtensionConstants.VALID_FROM_DATE_TIME); + + OffsetDateTime validToDateTime = OffsetDateTime.parse(validTo); + OffsetDateTime validFromDateTime = OffsetDateTime.parse(validFrom); + OffsetDateTime currentDateTime = OffsetDateTime.now(validToDateTime.getOffset()); + + //If the ValidToDAte is older than current date OR ValidToDAte is older than ValidFromDAte, return error + if (currentDateTime.isAfter(validToDateTime) || validFromDateTime.isAfter(validToDateTime)) { + log.error(ErrorConstants.INVALID_VALID_TO_DATE); + return ConsentManageUtil.getValidationResponse(ErrorConstants.FIELD_INVALID, + ErrorConstants.INVALID_VALID_TO_DATE, ErrorConstants.PATH_VALID_TO_DATE); + } + } + + //Validate periodic limits in control parameters + if (controlParameters.containsKey(ConsentExtensionConstants.PERIODIC_LIMITS)) { + JSONArray periodicLimits = (JSONArray) controlParameters.get(ConsentExtensionConstants.PERIODIC_LIMITS); + Iterator it = periodicLimits.iterator(); + + while (it.hasNext()) { + JSONObject limit = (JSONObject) it.next(); + + Object amount = limit.get(ConsentExtensionConstants.AMOUNT); + Object currency = limit.get(ConsentExtensionConstants.CURRENCY); + Object periodType = limit.get(ConsentExtensionConstants.PERIOD_TYPE); + + // validate amount + if (!ConsentManageUtil.validateAmount(limit)) { + log.error(ErrorConstants.INVALID_MAXIMUM_INDIVIDUAL_AMOUNT); + return ConsentManageUtil.getValidationResponse(ErrorConstants.FIELD_INVALID, + ErrorConstants.INVALID_MAXIMUM_INDIVIDUAL_AMOUNT, + ErrorConstants.PATH_MAXIMUM_INDIVIDUAL_AMOUNT); + } + + if (amount == null || StringUtils.isEmpty(amount.toString())) { + log.error(MAXIMUM_INDIVIDUAL_AMOUNT_NOT_FOUND); + validationResponse.put(ConsentExtensionConstants.IS_VALID, false); + validationResponse.put(ConsentExtensionConstants.HTTP_CODE, ResponseStatus.BAD_REQUEST); + validationResponse.put(ConsentExtensionConstants.ERRORS, + MAXIMUM_INDIVIDUAL_AMOUNT_NOT_FOUND); + return validationResponse; + } + + //validate currency + if (!ConsentManageUtil.validateCurrency(limit)) { + log.error(ErrorConstants.INVALID_CURRENCY); + return ConsentManageUtil.getValidationResponse(ErrorConstants.FIELD_INVALID, + ErrorConstants.INVALID_CURRENCY, ErrorConstants.PATH_MAXIMUM_INDIVIDUAL_AMOUNT); + } + + if (currency == null || StringUtils.isEmpty(currency.toString())) { + log.error(MAXIMUM_INDIVIDUAL_AMOUNT_CURRENCY_NOT_FOUND); + validationResponse.put(ConsentExtensionConstants.IS_VALID, false); + validationResponse.put(ConsentExtensionConstants.HTTP_CODE, ResponseStatus.BAD_REQUEST); + validationResponse.put(ConsentExtensionConstants.ERRORS, + MAXIMUM_INDIVIDUAL_AMOUNT_CURRENCY_NOT_FOUND); + return validationResponse; + } + + //validate period alignment + if (ConsentManageUtil.validatePeriodicAlignment(limit)) { + log.error(ErrorConstants.INVALID_PERIOD_ALIGNMENT); + return ConsentManageUtil.getValidationResponse(ErrorConstants.FIELD_INVALID, + INVALID_PERIOD_ALIGNMENT, PATH_PERIOD_ALIGNMENT); + } + + //validate period type + if (!ConsentManageUtil.validatePeriodicType(limit)) { + log.error(ErrorConstants.INVALID_PERIOD_TYPE); + return ConsentManageUtil.getValidationResponse(ErrorConstants.FIELD_INVALID, + ErrorConstants.INVALID_PERIOD_TYPE, ErrorConstants.PATH_PERIOD_TYPE); + } + + if (periodType == null || StringUtils.isEmpty(periodType.toString())) { + log.error(ErrorConstants.INVALID_PERIOD_TYPE); + validationResponse.put(ConsentExtensionConstants.IS_VALID, false); + validationResponse.put(ConsentExtensionConstants.HTTP_CODE, ResponseStatus.BAD_REQUEST); + validationResponse.put(ConsentExtensionConstants.ERRORS, ErrorConstants.INVALID_PERIOD_TYPE); + return validationResponse; + } + } + + validationResponse.put(ConsentExtensionConstants.IS_VALID, true); + return validationResponse; + } + return validationResponse; + } + + /** + * Method to validate variable recurring payment initiation request. + * + * @param initiation Initiation Object + * @return validation response object + */ + public static JSONObject validatePaymentInitiation(JSONObject initiation) { + + JSONObject validationResponse = new JSONObject(); + validationResponse.put(ConsentExtensionConstants.IS_VALID, false); + + //Check request body is valid and not empty + JSONObject dataValidationResult = ConsentManageUtil.validateInitiationDataBody(initiation); + if (!(boolean) dataValidationResult.get(ConsentExtensionConstants.IS_VALID)) { + return dataValidationResult; + } + + JSONObject data = (JSONObject) initiation.get(ConsentExtensionConstants.DATA); + + //Validate initiation in the VRP payload + if (data.containsKey(ConsentExtensionConstants.INITIATION)) { + JSONObject initiationValidationResult = VRPConsentRequestValidator + .validateVRPInitiationPayload((JSONObject) data.get(ConsentExtensionConstants.INITIATION)); + + if (!(boolean) initiationValidationResult.get(ConsentExtensionConstants.IS_VALID)) { + return initiationValidationResult; + } + } else { + log.error(ErrorConstants.PAYLOAD_FORMAT_ERROR); + return ConsentManageUtil.getValidationResponse(ErrorConstants.RESOURCE_INVALID_FORMAT, + ErrorConstants.PAYLOAD_FORMAT_ERROR, ErrorConstants.PATH_REQUEST_BODY); + } + + //Validate the ControlParameter in the payload + if (data.containsKey(ConsentExtensionConstants.CONTROL_PARAMETERS)) { + JSONObject controlParameterValidationResult = + VRPConsentRequestValidator.validatecontrolParameters((JSONObject) + data.get(ConsentExtensionConstants.CONTROL_PARAMETERS)); + + if (!(boolean) controlParameterValidationResult.get(ConsentExtensionConstants.IS_VALID)) { + return controlParameterValidationResult; + } + } else { + log.error(ErrorConstants.PAYLOAD_FORMAT_ERROR); + return ConsentManageUtil.getValidationResponse(ErrorConstants.RESOURCE_INVALID_FORMAT, + ErrorConstants.PAYLOAD_FORMAT_ERROR, ErrorConstants.PATH_REQUEST_BODY); + } + + validationResponse.put(ConsentExtensionConstants.IS_VALID, true); + return validationResponse; + } + + + /** + * Validator class to validate variable recurring payment initiation payload. + * @param initiation + * @return validationResponse + */ + public static JSONObject validateVRPInitiationPayload(JSONObject initiation) { + + JSONObject validationResponse = new JSONObject(); + + //Validate DebtorAccount + if (initiation.containsKey(ConsentExtensionConstants.DEBTOR_ACC)) { + + JSONObject debtorAccount = (JSONObject) initiation.get(ConsentExtensionConstants.DEBTOR_ACC); + JSONObject validationResult = ConsentManageUtil.validateVRPDebtorAccount(debtorAccount); + + if (!(boolean) validationResult.get(ConsentExtensionConstants.IS_VALID)) { + return validationResult; + } + } + + //Validate CreditorAccount + if (initiation.containsKey(ConsentExtensionConstants.CREDITOR_ACC)) { + JSONObject creditorAccount = (JSONObject) initiation.get(ConsentExtensionConstants.CREDITOR_ACC); + + JSONObject validationResult = ConsentManageUtil.validateVRPCreditorAccount(creditorAccount); + + if (!(boolean) validationResult.get(ConsentExtensionConstants.IS_VALID)) { + return validationResult; + } + } + + validationResponse.put(ConsentExtensionConstants.IS_VALID, true); + return validationResponse; + } + +} + + + + + + + + diff --git a/open-banking-accelerator/components/consent-management/com.wso2.openbanking.accelerator.consent.extensions/src/main/java/com/wso2/openbanking/accelerator/consent/extensions/util/ConsentManageUtil.java b/open-banking-accelerator/components/consent-management/com.wso2.openbanking.accelerator.consent.extensions/src/main/java/com/wso2/openbanking/accelerator/consent/extensions/util/ConsentManageUtil.java index 5506c011..717e0af9 100644 --- a/open-banking-accelerator/components/consent-management/com.wso2.openbanking.accelerator.consent.extensions/src/main/java/com/wso2/openbanking/accelerator/consent/extensions/util/ConsentManageUtil.java +++ b/open-banking-accelerator/components/consent-management/com.wso2.openbanking.accelerator.consent.extensions/src/main/java/com/wso2/openbanking/accelerator/consent/extensions/util/ConsentManageUtil.java @@ -30,6 +30,8 @@ import com.wso2.openbanking.accelerator.consent.mgt.dao.models.ConsentResource; import com.wso2.openbanking.accelerator.consent.mgt.dao.models.DetailedConsentResource; import net.minidev.json.JSONObject; +import net.minidev.json.parser.JSONParser; +import net.minidev.json.parser.ParseException; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -42,6 +44,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.EnumSet; +import java.util.List; import java.util.regex.Pattern; /** @@ -153,7 +156,7 @@ public static JSONObject validateDebtorAccount(JSONObject debtorAccount) { log.error(ErrorConstants.INVALID_DEBTOR_ACC_IDENTIFICATION); validationResponse.put(ConsentExtensionConstants.IS_VALID, false); validationResponse.put(ConsentExtensionConstants.HTTP_CODE, ResponseStatus.BAD_REQUEST); - validationResponse.put(ConsentExtensionConstants.ERRORS, ErrorConstants.INVALID_DEBTOR_ACC_IDENTIFICATION); + validationResponse.put(ConsentExtensionConstants.ERRORS, ErrorConstants.MISSING_DEBTOR_ACC_IDENTIFICATION); return validationResponse; } @@ -320,7 +323,6 @@ public static void handleConsentManageDelete(ConsentManageData consentManageData Boolean shouldRevokeTokens; if (ConsentManageUtil.isConsentIdValid(consentId)) { try { - ConsentResource consentResource = ConsentExtensionsDataHolder.getInstance().getConsentCoreService() .getConsent(consentId, false); @@ -585,6 +587,9 @@ public static String constructSelfLink(String consentId, ConsentManageData conse } else if (ConsentExtensionConstants.FUNDSCONFIRMATIONS.equals(type)) { baseUrl = (String) parser.getConfiguration().get( ConsentExtensionConstants.COF_SELF_LINK); + } else if (ConsentExtensionConstants.VRP.equals(type)) { + baseUrl = (String) parser.getConfiguration().get( + ConsentExtensionConstants.VRP_SELF_LINK); } String requestPath = consentManageData.getRequestPath(); @@ -621,4 +626,390 @@ public static boolean isConsentExpirationTimeValid(String expDateVal) { } } + /** + * validate the maximum amount in the payload in VRP. + */ + public static boolean validateAmount(JSONObject maximumIndividualAmount) { + return (maximumIndividualAmount != null && maximumIndividualAmount + .containsKey(ConsentExtensionConstants.AMOUNT)); + } + + /** + * validate the currency in the payload in VRP. + */ + public static boolean validateCurrency(JSONObject maximumIndividualAmount) { + return (maximumIndividualAmount != null && maximumIndividualAmount + .containsKey(ConsentExtensionConstants.CURRENCY)); + } + + /** + * validate the periodiclimits in the payload in VRP. + */ + public static boolean validatePeriodicAlignment(JSONObject periodiclimit) { + String periodAlignment = (String) periodiclimit.get(ConsentExtensionConstants.PERIOD_ALIGNMENT); + + return (ConsentExtensionConstants.CONSENT.equals(periodAlignment) || + ConsentExtensionConstants.CALENDER.equals(periodAlignment)); + } + + /** + * method to validate periodic type in VRP. + */ + public static boolean validatePeriodicType(JSONObject periodiclimit) { + String periodType = (String) periodiclimit.get(ConsentExtensionConstants.PERIOD_TYPE); + + List periodTypes = Arrays.asList(ConsentExtensionConstants.DAY, + ConsentExtensionConstants.WEEK, ConsentExtensionConstants.FORTNIGHT, + ConsentExtensionConstants.MONTH, ConsentExtensionConstants.HALF_YEAR, + ConsentExtensionConstants.YEAR); + + return (periodTypes.contains(periodType)); + } + + public static boolean validateRevokeStatus(JSONObject revokedNotification) { + + String revokedStatus = (String) revokedNotification.get(ConsentExtensionConstants.REVOKED_STATUS); + + return (ConsentExtensionConstants.REVOKED_STATUS.equals(revokedStatus)); + + } + /** + * Method to handle the Payment GET requests. + * + * @param consentManageData Object containing request details + * @param consent Consent stored at initiation post + * @throws ConsentManagementException + */ + private static void handlePaymentInitiationGet(ConsentManageData consentManageData, ConsentResource consent, + String paymentType) throws ParseException { + + String type = ConsentExtensionConstants.VRP.equals(paymentType) ? ConsentExtensionConstants.VRP : + ConsentExtensionConstants.PAYMENTS; + JSONObject receiptJSON = (JSONObject) new JSONParser(JSONParser.MODE_PERMISSIVE). + parse(consent.getReceipt()); + consentManageData.setResponsePayload(ConsentManageUtil + .getInitiationRetrievalResponse(receiptJSON, consent, consentManageData, type)); + consentManageData.setResponseStatus(ResponseStatus.OK); + } + + + /** + * Utility class to check whether the Debtor/Creditor AccountSecondary Identification is valid. + * + * @param accSecondaryIdentification Debtor/Creditor Account Secondary Identification + * @return + */ + public static boolean isSecondaryIdentificationValid(String accSecondaryIdentification) { + return (accSecondaryIdentification.length() <= 34); + } + + /** + * Utility class to check whether the Debtor/Creditor Account Name is valid. + * + * @param accName Debtor/Creditor Account Name + * @return + */ + public static boolean isAccNameValid(String accName) { + return (accName.length() <= 350); + } + + + /** + * Utility class to check whether the Debtor/Creditor Account Identification is valid. + * + * @param identification Debtor/Creditor Account Identification + * @return + */ + public static boolean isIdentificationValid(String identification) { + return (identification.length() <= 256); + } + + + /** + * Utility class to check whether the Debtor/Creditor Account Scheme name matches with Enum values. + * + * @param schemeName Debtor/Creditor Account Scheme Name + * @return + */ + public static boolean isSchemeNameValid(String schemeName) { + EnumSet set = EnumSet.allOf(DebtorAccountSchemeNameEnum.class); + return set.contains(DebtorAccountSchemeNameEnum.fromValue(schemeName)); + } + + /** + * Utility class to check whether the Debtor/Creditor Account Scheme name length. + * + * @param schemeName Debtor/Creditor Account Scheme Name + * @return + */ + public static boolean validateSchemeNameLength(String schemeName) { + return (schemeName.length() <= 256); + } + + /** + * Method to validate debtor account in vrp. + * + * @param debtorAccount Debtor Account object + * @return validationResponse + */ + public static JSONObject validateVRPDebtorAccount(JSONObject debtorAccount) { + + JSONObject validationResponse = new JSONObject(); + + //Check Debtor Account exists + if (debtorAccount.containsKey(ConsentExtensionConstants.SCHEME_NAME)) { + //Check Debtor Account Scheme name exists + if (StringUtils.isEmpty(debtorAccount.getAsString(ConsentExtensionConstants.SCHEME_NAME))) { + log.error(ErrorConstants.MISSING_DEBTOR_ACC_SCHEME_NAME); + validationResponse.put(ConsentExtensionConstants.IS_VALID, false); + validationResponse.put(ConsentExtensionConstants.HTTP_CODE, ResponseStatus.BAD_REQUEST); + validationResponse.put(ConsentExtensionConstants.ERRORS, ErrorConstants.MISSING_DEBTOR_ACC_SCHEME_NAME); + return validationResponse; + } + + Object schemeName = debtorAccount.get(ConsentExtensionConstants.SCHEME_NAME); + + if (schemeName == null || StringUtils.isEmpty(schemeName.toString())) { + log.error(ErrorConstants.MISSING_DEBTOR_ACC_SCHEME_NAME); + validationResponse.put(ConsentExtensionConstants.IS_VALID, false); + validationResponse.put(ConsentExtensionConstants.HTTP_CODE, ResponseStatus.BAD_REQUEST); + validationResponse.put(ConsentExtensionConstants.ERRORS, ErrorConstants.MISSING_DEBTOR_ACC_SCHEME_NAME); + return validationResponse; + } + //Validate Debtor Account Scheme name + if (!(schemeName instanceof String) || + ConsentManageUtil.isSchemeNameValid((String) schemeName) || + !ConsentManageUtil.validateSchemeNameLength((String) schemeName)) { + log.error(ErrorConstants.INVALID_DEBTOR_ACC_SCHEME_NAME); + validationResponse.put(ConsentExtensionConstants.IS_VALID, false); + validationResponse.put(ConsentExtensionConstants.HTTP_CODE, ResponseStatus.BAD_REQUEST); + validationResponse.put(ConsentExtensionConstants.ERRORS, ErrorConstants.INVALID_DEBTOR_ACC_SCHEME_NAME); + return validationResponse; + } + } else { + log.error(ErrorConstants.MISSING_DEBTOR_ACC_SCHEME_NAME); + validationResponse.put(ConsentExtensionConstants.IS_VALID, false); + validationResponse.put(ConsentExtensionConstants.HTTP_CODE, ResponseStatus.BAD_REQUEST); + validationResponse.put(ConsentExtensionConstants.ERRORS, ErrorConstants.INVALID_DEBTOR_ACC_SCHEME_NAME); + return validationResponse; + } + + //Check Debtor Account Identification existing + if (debtorAccount.containsKey(ConsentExtensionConstants.IDENTIFICATION)) { + //Check Debtor Account Identification is empty + if (StringUtils.isEmpty(debtorAccount.getAsString(ConsentExtensionConstants.IDENTIFICATION))) { + log.error(ErrorConstants.MISSING_DEBTOR_ACC_SCHEME_NAME); + validationResponse.put(ConsentExtensionConstants.IS_VALID, false); + validationResponse.put(ConsentExtensionConstants.HTTP_CODE, ResponseStatus.BAD_REQUEST); + validationResponse.put(ConsentExtensionConstants.ERRORS, + ErrorConstants.MISSING_DEBTOR_ACC_IDENTIFICATION); + return validationResponse; + } + + Object identification = debtorAccount.get(ConsentExtensionConstants.IDENTIFICATION); + //Validate Debtor Account Identification + if (!(identification instanceof String) || + !ConsentManageUtil.isIdentificationValid((String) identification)) { + log.error(ErrorConstants.INVALID_DEBTOR_ACC_IDENTIFICATION); + validationResponse.put(ConsentExtensionConstants.IS_VALID, false); + validationResponse.put(ConsentExtensionConstants.HTTP_CODE, ResponseStatus.BAD_REQUEST); + validationResponse.put(ConsentExtensionConstants.ERRORS, + ErrorConstants.MISSING_DEBTOR_ACC_IDENTIFICATION); + return validationResponse; + } + } else { + log.error(ErrorConstants.MISSING_DEBTOR_ACC_IDENTIFICATION); + validationResponse.put(ConsentExtensionConstants.IS_VALID, false); + validationResponse.put(ConsentExtensionConstants.HTTP_CODE, ResponseStatus.BAD_REQUEST); + validationResponse.put(ConsentExtensionConstants.ERRORS, ErrorConstants.MISSING_DEBTOR_ACC_IDENTIFICATION); + return validationResponse; + } + + //Validate Debtor Account Name + + Object debtorAcc = debtorAccount.get(ConsentExtensionConstants.NAME); + + if (debtorAcc == null || StringUtils.isEmpty(debtorAcc.toString())) { + log.error(ErrorConstants.FIELD_MISSING); + validationResponse.put(ConsentExtensionConstants.IS_VALID, false); + validationResponse.put(ConsentExtensionConstants.HTTP_CODE, ResponseStatus.BAD_REQUEST); + validationResponse.put(ConsentExtensionConstants.ERRORS, ErrorConstants.FIELD_MISSING); + return validationResponse; + } + + if (debtorAccount.containsKey(ConsentExtensionConstants.NAME) && + (!(debtorAccount.get(ConsentExtensionConstants.NAME) instanceof String) || + !ConsentManageUtil.isAccNameValid(debtorAccount + .getAsString(ConsentExtensionConstants.NAME)))) { + log.error(ErrorConstants.INVALID_DEBTOR_ACC_NAME); + validationResponse.put(ConsentExtensionConstants.IS_VALID, false); + validationResponse.put(ConsentExtensionConstants.HTTP_CODE, ResponseStatus.BAD_REQUEST); + validationResponse.put(ConsentExtensionConstants.ERRORS, ErrorConstants.INVALID_DEBTOR_ACC_NAME); + return validationResponse; + } + + //Validate Debtor Account Secondary Identification + if (debtorAccount.containsKey(ConsentExtensionConstants.SECONDARY_IDENTIFICATION) && + (!(debtorAccount.get(ConsentExtensionConstants.SECONDARY_IDENTIFICATION) instanceof String) || + !ConsentManageUtil.isSecondaryIdentificationValid(debtorAccount + .getAsString(ConsentExtensionConstants.SECONDARY_IDENTIFICATION)))) { + log.error(ErrorConstants.INVALID_DEBTOR_ACC_SEC_IDENTIFICATION); + validationResponse.put(ConsentExtensionConstants.IS_VALID, false); + validationResponse.put(ConsentExtensionConstants.HTTP_CODE, ResponseStatus.BAD_REQUEST); + validationResponse.put(ConsentExtensionConstants.ERRORS, + ErrorConstants.INVALID_DEBTOR_ACC_SEC_IDENTIFICATION); + return validationResponse; + } + + //Validate Sort Code number scheme + String schemeName = debtorAccount.getAsString(ConsentExtensionConstants.SCHEME_NAME); + String identification = debtorAccount.getAsString(ConsentExtensionConstants.IDENTIFICATION); + if (!checkSortCodeSchemeNameAndIdentificationValidity(schemeName, identification)) { + log.error(ErrorConstants.INVALID_IDENTIFICATION); + validationResponse.put(ConsentExtensionConstants.IS_VALID, false); + validationResponse.put(ConsentExtensionConstants.HTTP_CODE, ResponseStatus.BAD_REQUEST); + validationResponse.put(ConsentExtensionConstants.ERRORS, ErrorConstants.INVALID_IDENTIFICATION); + return validationResponse; + } + validationResponse.put(ConsentExtensionConstants.IS_VALID, true); + return validationResponse; + } + + + /** + * Validate creditor account in vrp initiation payload. + * + * @param creditorAccount Creditor Account object + * + * @return validationResponse + */ + public static JSONObject validateVRPCreditorAccount(JSONObject creditorAccount) { + + JSONObject validationResponse = new JSONObject(); + + //Check Creditor Account exists + if (creditorAccount.containsKey(ConsentExtensionConstants.SCHEME_NAME)) { + //Check Creditor Account Scheme name exists + if (StringUtils.isEmpty(creditorAccount.getAsString(ConsentExtensionConstants.SCHEME_NAME))) { + log.error(ErrorConstants.MISSING_DEBTOR_ACC_SCHEME_NAME); + validationResponse.put(ConsentExtensionConstants.IS_VALID, false); + validationResponse.put(ConsentExtensionConstants.HTTP_CODE, ResponseStatus.BAD_REQUEST); + validationResponse.put(ConsentExtensionConstants.ERRORS, + ErrorConstants.MISSING_CREDITOR_ACC_SCHEME_NAME); + return validationResponse; + } + + Object schemeName = creditorAccount.get(ConsentExtensionConstants.SCHEME_NAME); + //Validate Creditor Account Scheme name + if (!(schemeName instanceof String) || + ConsentManageUtil.isSchemeNameValid((String) schemeName) || + !ConsentManageUtil.validateSchemeNameLength((String) schemeName)) { + log.error(ErrorConstants.INVALID_CREDITOR_ACC_SCHEME_NAME); + validationResponse.put(ConsentExtensionConstants.IS_VALID, false); + validationResponse.put(ConsentExtensionConstants.HTTP_CODE, ResponseStatus.BAD_REQUEST); + validationResponse.put(ConsentExtensionConstants.ERRORS, + ErrorConstants.INVALID_CREDITOR_ACC_SCHEME_NAME); + return validationResponse; + } + } else { + log.error(ErrorConstants.MISSING_CREDITOR_ACC_SCHEME_NAME); + validationResponse.put(ConsentExtensionConstants.IS_VALID, false); + validationResponse.put(ConsentExtensionConstants.HTTP_CODE, ResponseStatus.BAD_REQUEST); + validationResponse.put(ConsentExtensionConstants.ERRORS, + ErrorConstants.INVALID_CREDITOR_ACC_SCHEME_NAME); + return validationResponse; + } + + //Check Creditor Account Identification existing + if (creditorAccount.containsKey(ConsentExtensionConstants.IDENTIFICATION)) { + //Check Creditor Account Identification is empty + if (StringUtils.isEmpty(creditorAccount.getAsString(ConsentExtensionConstants.IDENTIFICATION))) { + log.error(ErrorConstants.MISSING_CREDITOR_ACC_IDENTIFICATION); + validationResponse.put(ConsentExtensionConstants.IS_VALID, false); + validationResponse.put(ConsentExtensionConstants.HTTP_CODE, ResponseStatus.BAD_REQUEST); + validationResponse.put(ConsentExtensionConstants.ERRORS, + ErrorConstants.MISSING_CREDITOR_ACC_IDENTIFICATION); + return validationResponse; + } + + Object identification = creditorAccount.get(ConsentExtensionConstants.IDENTIFICATION); + //Validate Creditor Account Identification + if (!(identification instanceof String) || + !ConsentManageUtil.isIdentificationValid((String) identification)) { + log.error(ErrorConstants.INVALID_CREDITOR_ACC_IDENTIFICATION); + validationResponse.put(ConsentExtensionConstants.IS_VALID, false); + validationResponse.put(ConsentExtensionConstants.HTTP_CODE, ResponseStatus.BAD_REQUEST); + validationResponse.put(ConsentExtensionConstants.ERRORS, + ErrorConstants.MISSING_CREDITOR_ACC_IDENTIFICATION); + return validationResponse; + } + } else { + log.error(ErrorConstants.MISSING_CREDITOR_ACC_IDENTIFICATION); + validationResponse.put(ConsentExtensionConstants.IS_VALID, false); + validationResponse.put(ConsentExtensionConstants.HTTP_CODE, ResponseStatus.BAD_REQUEST); + validationResponse.put(ConsentExtensionConstants.ERRORS, + ErrorConstants.MISSING_CREDITOR_ACC_IDENTIFICATION); + return validationResponse; + } + + //Validate Creditor Account Name + Object creditorAcc = creditorAccount.get(ConsentExtensionConstants.NAME); + + if (creditorAcc == null || StringUtils.isEmpty(creditorAcc.toString())) { + log.error(ErrorConstants.FIELD_MISSING); + validationResponse.put(ConsentExtensionConstants.IS_VALID, false); + validationResponse.put(ConsentExtensionConstants.HTTP_CODE, ResponseStatus.BAD_REQUEST); + validationResponse.put(ConsentExtensionConstants.ERRORS, ErrorConstants.FIELD_MISSING); + return validationResponse; + } + if (creditorAccount.containsKey(ConsentExtensionConstants.NAME) && + (!(creditorAccount.get(ConsentExtensionConstants.NAME) instanceof String) || + !ConsentManageUtil.isAccNameValid(creditorAccount + .getAsString(ConsentExtensionConstants.NAME)))) { + log.error(ErrorConstants.INVALID_CREDITOR_ACC_NAME); + validationResponse.put(ConsentExtensionConstants.IS_VALID, false); + validationResponse.put(ConsentExtensionConstants.HTTP_CODE, ResponseStatus.BAD_REQUEST); + validationResponse.put(ConsentExtensionConstants.ERRORS, ErrorConstants.INVALID_CREDITOR_ACC_NAME); + return validationResponse; + } + + //Validate Creditor Account Secondary Identification + Object creditorAccSecondaryIdentification = creditorAccount.get(ConsentExtensionConstants + .SECONDARY_IDENTIFICATION); + + if (creditorAccSecondaryIdentification == null || StringUtils.isEmpty + (creditorAccSecondaryIdentification.toString())) { + log.error(ErrorConstants.FIELD_MISSING); + validationResponse.put(ConsentExtensionConstants.IS_VALID, false); + validationResponse.put(ConsentExtensionConstants.HTTP_CODE, ResponseStatus.BAD_REQUEST); + validationResponse.put(ConsentExtensionConstants.ERRORS, ErrorConstants.FIELD_MISSING); + return validationResponse; + } + if (creditorAccount.containsKey(ConsentExtensionConstants.SECONDARY_IDENTIFICATION) && + (!(creditorAccount.get(ConsentExtensionConstants.SECONDARY_IDENTIFICATION) instanceof String) || + !ConsentManageUtil.isSecondaryIdentificationValid(creditorAccount + .getAsString(ConsentExtensionConstants.SECONDARY_IDENTIFICATION)))) { + log.error(ErrorConstants.INVALID_CREDITOR_ACC_IDENTIFICATION); + validationResponse.put(ConsentExtensionConstants.IS_VALID, false); + validationResponse.put(ConsentExtensionConstants.HTTP_CODE, ResponseStatus.BAD_REQUEST); + validationResponse.put(ConsentExtensionConstants.ERRORS, + ErrorConstants.INVALID_CREDITOR_ACC_SEC_IDENTIFICATION); + return validationResponse; + } + + //Validate Sort Code number scheme + String schemeName = creditorAccount.getAsString(ConsentExtensionConstants.SCHEME_NAME); + String identification = creditorAccount.getAsString(ConsentExtensionConstants.IDENTIFICATION); + if (!checkSortCodeSchemeNameAndIdentificationValidity(schemeName, identification)) { + log.error(ErrorConstants.INVALID_IDENTIFICATION); + validationResponse.put(ConsentExtensionConstants.IS_VALID, false); + validationResponse.put(ConsentExtensionConstants.HTTP_CODE, ResponseStatus.BAD_REQUEST); + validationResponse.put(ConsentExtensionConstants.ERRORS, ErrorConstants.INVALID_IDENTIFICATION); + return validationResponse; + } + validationResponse.put(ConsentExtensionConstants.IS_VALID, true); + return validationResponse; + } } + +