Bug: [FEATURE] Add the configs for revoking as well as updating the mandates 



### Feature Description

Add envs of the connectors that support the revokinga s well as updation of mandates

### Possible Implementation

Make an env that has the list of all the connectors that support revoke as well as mandate flow , and if we try to update or revoke the mandate for a connector that is not there in the list we throw a suitable error

### Have you spent some time checking if this feature request has been raised before?

- [X] I checked and didn't find a similar issue

### Have you read the Contributing Guidelines?

- [X] I have read the [Contributing Guidelines](https://github.com/juspay/hyperswitch/blob/main/docs/CONTRIBUTING.md)

### Are you willing to submit a PR?

Yes, I am willing to submit a PR!
diff --git a/config/config.example.toml b/config/config.example.toml
index dd1206b20dc..dda768bec3c 100644
--- a/config/config.example.toml
+++ b/config/config.example.toml
@@ -391,6 +391,9 @@ bank_redirect.ideal = {connector_list = "stripe,adyen,globalpay"} # Mandate supp
 bank_redirect.sofort = {connector_list = "stripe,adyen,globalpay"}
 wallet.apple_pay = { connector_list = "stripe,adyen,cybersource,noon" }
 
+[mandates.update_mandate_supported]
+card.credit ={connector_list ="cybersource"}  # Update Mandate supported payment method type and connector for card 
+card.debit = {connector_list ="cybersource"}  # Update Mandate supported payment method type and connector for card 
 
 # Required fields info used while listing the payment_method_data
 [required_fields.pay_later] # payment_method = "pay_later"
diff --git a/config/deployments/integration_test.toml b/config/deployments/integration_test.toml
index dfb1fc9ee28..1ba455ee134 100644
--- a/config/deployments/integration_test.toml
+++ b/config/deployments/integration_test.toml
@@ -120,6 +120,10 @@ wallet.paypal.connector_list = "adyen"
 bank_redirect.ideal = {connector_list = "stripe,adyen,globalpay"}
 bank_redirect.sofort = {connector_list = "stripe,adyen,globalpay"}
 
+[mandates.update_mandate_supported]
+card.credit ={connector_list ="cybersource"}
+card.debit = {connector_list ="cybersource"}
+
 [multiple_api_version_supported_connectors]
 supported_connectors = "braintree"
 
diff --git a/config/deployments/production.toml b/config/deployments/production.toml
index 82d5c00c806..ae764682321 100644
--- a/config/deployments/production.toml
+++ b/config/deployments/production.toml
@@ -120,6 +120,10 @@ wallet.paypal.connector_list = "adyen"
 bank_redirect.ideal = {connector_list = "stripe,adyen,globalpay"}
 bank_redirect.sofort = {connector_list = "stripe,adyen,globalpay"}
 
+[mandates.update_mandate_supported]
+card.credit ={connector_list ="cybersource"}
+card.debit = {connector_list ="cybersource"}
+
 [multiple_api_version_supported_connectors]
 supported_connectors = "braintree"
 
diff --git a/config/deployments/sandbox.toml b/config/deployments/sandbox.toml
index dfc3033ea20..1cac50298ff 100644
--- a/config/deployments/sandbox.toml
+++ b/config/deployments/sandbox.toml
@@ -120,6 +120,10 @@ wallet.paypal.connector_list = "adyen"
 bank_redirect.ideal = {connector_list = "stripe,adyen,globalpay"}
 bank_redirect.sofort = {connector_list = "stripe,adyen,globalpay"}
 
+[mandates.update_mandate_supported]
+card.credit ={connector_list ="cybersource"}
+card.debit = {connector_list ="cybersource"}
+
 [multiple_api_version_supported_connectors]
 supported_connectors = "braintree"
 
diff --git a/config/development.toml b/config/development.toml
index 1fd76d04ff5..1075452fbd6 100644
--- a/config/development.toml
+++ b/config/development.toml
@@ -487,6 +487,10 @@ bank_debit.sepa = { connector_list = "gocardless"}
 bank_redirect.ideal = {connector_list = "stripe,adyen,globalpay"}
 bank_redirect.sofort = {connector_list = "stripe,adyen,globalpay"}
 
+[mandates.update_mandate_supported]
+card.credit ={connector_list ="cybersource"}
+card.debit = {connector_list ="cybersource"}
+
 [connector_request_reference_id_config]
 merchant_ids_send_payment_id_as_connector_request_id = []
 
diff --git a/crates/api_models/src/payments.rs b/crates/api_models/src/payments.rs
index 07a891efd34..a9d415230e9 100644
--- a/crates/api_models/src/payments.rs
+++ b/crates/api_models/src/payments.rs
@@ -1011,6 +1011,23 @@ impl PaymentMethodData {
             self.to_owned()
         }
     }
+    pub fn get_payment_method(&self) -> Option<api_enums::PaymentMethod> {
+        match self {
+            Self::Card(_) => Some(api_enums::PaymentMethod::Card),
+            Self::CardRedirect(_) => Some(api_enums::PaymentMethod::CardRedirect),
+            Self::Wallet(_) => Some(api_enums::PaymentMethod::Wallet),
+            Self::PayLater(_) => Some(api_enums::PaymentMethod::PayLater),
+            Self::BankRedirect(_) => Some(api_enums::PaymentMethod::BankRedirect),
+            Self::BankDebit(_) => Some(api_enums::PaymentMethod::BankDebit),
+            Self::BankTransfer(_) => Some(api_enums::PaymentMethod::BankTransfer),
+            Self::Crypto(_) => Some(api_enums::PaymentMethod::Crypto),
+            Self::Reward => Some(api_enums::PaymentMethod::Reward),
+            Self::Upi(_) => Some(api_enums::PaymentMethod::Upi),
+            Self::Voucher(_) => Some(api_enums::PaymentMethod::Voucher),
+            Self::GiftCard(_) => Some(api_enums::PaymentMethod::GiftCard),
+            Self::CardToken(_) | Self::MandatePayment => None,
+        }
+    }
 }
 
 pub trait GetPaymentMethodType {
diff --git a/crates/router/src/configs/defaults.rs b/crates/router/src/configs/defaults.rs
index fc5ba0f55bc..71cd61ffa80 100644
--- a/crates/router/src/configs/defaults.rs
+++ b/crates/router/src/configs/defaults.rs
@@ -209,6 +209,7 @@ impl Default for Mandates {
                     ])),
                 ),
             ])),
+            update_mandate_supported: SupportedPaymentMethodsForMandate(HashMap::default()),
         }
     }
 }
diff --git a/crates/router/src/configs/settings.rs b/crates/router/src/configs/settings.rs
index 2519455f95a..2572d764d06 100644
--- a/crates/router/src/configs/settings.rs
+++ b/crates/router/src/configs/settings.rs
@@ -237,6 +237,7 @@ pub struct DummyConnector {
 #[derive(Debug, Deserialize, Clone)]
 pub struct Mandates {
     pub supported_payment_methods: SupportedPaymentMethodsForMandate,
+    pub update_mandate_supported: SupportedPaymentMethodsForMandate,
 }
 
 #[derive(Debug, Deserialize, Clone)]
diff --git a/crates/router/src/core/mandate.rs b/crates/router/src/core/mandate.rs
index 7299ef624d8..e564e4a733e 100644
--- a/crates/router/src/core/mandate.rs
+++ b/crates/router/src/core/mandate.rs
@@ -59,7 +59,6 @@ pub async fn revoke_mandate(
         .find_mandate_by_merchant_id_mandate_id(&merchant_account.merchant_id, &req.mandate_id)
         .await
         .to_not_found_response(errors::ApiErrorResponse::MandateNotFound)?;
-
     let mandate_revoke_status = match mandate.mandate_status {
         common_enums::MandateStatus::Active
         | common_enums::MandateStatus::Inactive
diff --git a/crates/router/src/core/payment_methods/cards.rs b/crates/router/src/core/payment_methods/cards.rs
index e9beb84c7bb..7b505e7c01c 100644
--- a/crates/router/src/core/payment_methods/cards.rs
+++ b/crates/router/src/core/payment_methods/cards.rs
@@ -1219,6 +1219,7 @@ pub async fn list_payment_methods(
             mca.connector_name.clone(),
             pm_config_mapping,
             &state.conf.mandates.supported_payment_methods,
+            &state.conf.mandates.update_mandate_supported,
         )
         .await?;
     }
@@ -1985,6 +1986,7 @@ pub async fn filter_payment_methods(
     connector: String,
     config: &settings::ConnectorFilters,
     supported_payment_methods_for_mandate: &settings::SupportedPaymentMethodsForMandate,
+    supported_payment_methods_for_update_mandate: &settings::SupportedPaymentMethodsForMandate,
 ) -> errors::CustomResult<(), errors::ApiErrorResponse> {
     for payment_method in payment_methods.into_iter() {
         let parse_result = serde_json::from_value::<PaymentMethodsEnabled>(payment_method);
@@ -2091,13 +2093,20 @@ pub async fn filter_payment_methods(
                                     ),
                                 };
 
-                            if mandate_type_present || update_mandate_id_present {
+                            if mandate_type_present {
                                 filter_pm_based_on_supported_payments_for_mandate(
                                     supported_payment_methods_for_mandate,
                                     &payment_method,
                                     &payment_method_object.payment_method_type,
                                     connector_variant,
                                 )
+                            } else if update_mandate_id_present {
+                                filter_pm_based_on_update_mandate_support_for_connector(
+                                    supported_payment_methods_for_update_mandate,
+                                    &payment_method,
+                                    &payment_method_object.payment_method_type,
+                                    connector_variant,
+                                )
                             } else {
                                 true
                             }
@@ -2121,6 +2130,19 @@ pub async fn filter_payment_methods(
     }
     Ok(())
 }
+pub fn filter_pm_based_on_update_mandate_support_for_connector(
+    supported_payment_methods_for_mandate: &settings::SupportedPaymentMethodsForMandate,
+    payment_method: &api_enums::PaymentMethod,
+    payment_method_type: &api_enums::PaymentMethodType,
+    connector: api_enums::Connector,
+) -> bool {
+    supported_payment_methods_for_mandate
+        .0
+        .get(payment_method)
+        .and_then(|payment_method_type_hm| payment_method_type_hm.0.get(payment_method_type))
+        .map(|supported_connectors| supported_connectors.connector_list.contains(&connector))
+        .unwrap_or(false)
+}
 
 fn filter_pm_based_on_supported_payments_for_mandate(
     supported_payment_methods_for_mandate: &settings::SupportedPaymentMethodsForMandate,
diff --git a/crates/router/src/core/payments/flows/setup_mandate_flow.rs b/crates/router/src/core/payments/flows/setup_mandate_flow.rs
index 712184308dd..a81f97851d9 100644
--- a/crates/router/src/core/payments/flows/setup_mandate_flow.rs
+++ b/crates/router/src/core/payments/flows/setup_mandate_flow.rs
@@ -3,9 +3,11 @@ use error_stack::{IntoReport, ResultExt};
 
 use super::{ConstructFlowSpecificData, Feature};
 use crate::{
+    configs::settings,
     core::{
         errors::{self, ConnectorErrorExt, RouterResult, StorageErrorExt},
         mandate,
+        payment_methods::cards,
         payments::{
             self, access_token, customers, helpers, tokenization, transformers, PaymentData,
         },
@@ -60,106 +62,53 @@ impl Feature<api::SetupMandate, types::SetupMandateRequestData> for types::Setup
         connector_request: Option<services::Request>,
         key_store: &domain::MerchantKeyStore,
     ) -> RouterResult<Self> {
-        let connector_integration: services::BoxedConnectorIntegration<
-            '_,
-            api::SetupMandate,
-            types::SetupMandateRequestData,
-            types::PaymentsResponseData,
-        > = connector.connector.get_connector_integration();
-
-        let resp = services::execute_connector_processing_step(
-            state,
-            connector_integration,
-            &self,
-            call_connector_action.clone(),
-            connector_request,
-        )
-        .await
-        .to_setup_mandate_failed_response()?;
-
-        let is_mandate = resp.request.setup_mandate_details.is_some();
-
-        let pm_id = Box::pin(tokenization::save_payment_method(
-            state,
-            connector,
-            resp.to_owned(),
-            maybe_customer,
-            merchant_account,
-            self.request.payment_method_type,
-            key_store,
-            is_mandate,
-        ))
-        .await?;
-
         if let Some(mandate_id) = self
             .request
             .setup_mandate_details
             .as_ref()
             .and_then(|mandate_data| mandate_data.update_mandate_id.clone())
         {
-            let mandate = state
-                .store
-                .find_mandate_by_merchant_id_mandate_id(&merchant_account.merchant_id, &mandate_id)
-                .await
-                .to_not_found_response(errors::ApiErrorResponse::MandateNotFound)?;
-
-            let profile_id = mandate::helpers::get_profile_id_for_mandate(
+            self.update_mandate_flow(
                 state,
                 merchant_account,
-                mandate.clone(),
+                mandate_id,
+                connector,
+                key_store,
+                call_connector_action,
+                &state.conf.mandates.update_mandate_supported,
+                connector_request,
+                maybe_customer,
             )
-            .await?;
-            match resp.response {
-                Ok(types::PaymentsResponseData::TransactionResponse { .. }) => {
-                    let connector_integration: services::BoxedConnectorIntegration<
-                        '_,
-                        types::api::MandateRevoke,
-                        types::MandateRevokeRequestData,
-                        types::MandateRevokeResponseData,
-                    > = connector.connector.get_connector_integration();
-                    let merchant_connector_account = helpers::get_merchant_connector_account(
-                        state,
-                        &merchant_account.merchant_id,
-                        None,
-                        key_store,
-                        &profile_id,
-                        &mandate.connector,
-                        mandate.merchant_connector_id.as_ref(),
-                    )
-                    .await?;
-
-                    let router_data = mandate::utils::construct_mandate_revoke_router_data(
-                        merchant_connector_account,
-                        merchant_account,
-                        mandate.clone(),
-                    )
-                    .await?;
-
-                    let _response = services::execute_connector_processing_step(
-                        state,
-                        connector_integration,
-                        &router_data,
-                        call_connector_action,
-                        None,
-                    )
-                    .await
-                    .change_context(errors::ApiErrorResponse::InternalServerError)?;
-                    // TODO:Add the revoke mandate task to process tracker
-                    mandate::update_mandate_procedure(
-                        state,
-                        resp,
-                        mandate,
-                        &merchant_account.merchant_id,
-                        pm_id,
-                    )
-                    .await
-                }
-                Ok(_) => Err(errors::ApiErrorResponse::InternalServerError)
-                    .into_report()
-                    .attach_printable("Unexpected response received")?,
-                Err(_) => Ok(resp),
-            }
+            .await
         } else {
+            let connector_integration: services::BoxedConnectorIntegration<
+                '_,
+                api::SetupMandate,
+                types::SetupMandateRequestData,
+                types::PaymentsResponseData,
+            > = connector.connector.get_connector_integration();
+
+            let resp = services::execute_connector_processing_step(
+                state,
+                connector_integration,
+                &self,
+                call_connector_action.clone(),
+                connector_request,
+            )
+            .await
+            .to_setup_mandate_failed_response()?;
+            let is_mandate = resp.request.setup_mandate_details.is_some();
+            let pm_id = Box::pin(tokenization::save_payment_method(
+                state,
+                connector,
+                resp.to_owned(),
+                maybe_customer,
+                merchant_account,
+                self.request.payment_method_type,
+                key_store,
+                is_mandate,
+            ))
+            .await?;
             mandate::mandate_procedure(
                 state,
                 resp,
@@ -310,6 +259,130 @@ impl types::SetupMandateRouterData {
             _ => Ok(self.clone()),
         }
     }
+
+    async fn update_mandate_flow(
+        self,
+        state: &AppState,
+        merchant_account: &domain::MerchantAccount,
+        mandate_id: String,
+        connector: &api::ConnectorData,
+        key_store: &domain::MerchantKeyStore,
+        call_connector_action: payments::CallConnectorAction,
+        supported_connectors_for_update_mandate: &settings::SupportedPaymentMethodsForMandate,
+        connector_request: Option<services::Request>,
+        maybe_customer: &Option<domain::Customer>,
+    ) -> RouterResult<Self> {
+        let payment_method_type = self.request.payment_method_type;
+
+        let payment_method = self.request.payment_method_data.get_payment_method();
+        let supported_connectors_config =
+            payment_method
+                .zip(payment_method_type)
+                .map_or(false, |(pm, pmt)| {
+                    cards::filter_pm_based_on_update_mandate_support_for_connector(
+                        supported_connectors_for_update_mandate,
+                        &pm,
+                        &pmt,
+                        connector.connector_name,
+                    )
+                });
+        if supported_connectors_config {
+            let connector_integration: services::BoxedConnectorIntegration<
+                '_,
+                api::SetupMandate,
+                types::SetupMandateRequestData,
+                types::PaymentsResponseData,
+            > = connector.connector.get_connector_integration();
+
+            let resp = services::execute_connector_processing_step(
+                state,
+                connector_integration,
+                &self,
+                call_connector_action.clone(),
+                connector_request,
+            )
+            .await
+            .to_setup_mandate_failed_response()?;
+            let is_mandate = resp.request.setup_mandate_details.is_some();
+            let pm_id = Box::pin(tokenization::save_payment_method(
+                state,
+                connector,
+                resp.to_owned(),
+                maybe_customer,
+                merchant_account,
+                self.request.payment_method_type,
+                key_store,
+                is_mandate,
+            ))
+            .await?;
+            let mandate = state
+                .store
+                .find_mandate_by_merchant_id_mandate_id(&merchant_account.merchant_id, &mandate_id)
+                .await
+                .to_not_found_response(errors::ApiErrorResponse::MandateNotFound)?;
+
+            let profile_id = mandate::helpers::get_profile_id_for_mandate(
+                state,
+                merchant_account,
+                mandate.clone(),
+            )
+            .await?;
+            match resp.response {
+                Ok(types::PaymentsResponseData::TransactionResponse { .. }) => {
+                    let connector_integration: services::BoxedConnectorIntegration<
+                        '_,
+                        types::api::MandateRevoke,
+                        types::MandateRevokeRequestData,
+                        types::MandateRevokeResponseData,
+                    > = connector.connector.get_connector_integration();
+                    let merchant_connector_account = helpers::get_merchant_connector_account(
+                        state,
+                        &merchant_account.merchant_id,
+                        None,
+                        key_store,
+                        &profile_id,
+                        &mandate.connector,
+                        mandate.merchant_connector_id.as_ref(),
+                    )
+                    .await?;
+
+                    let router_data = mandate::utils::construct_mandate_revoke_router_data(
+                        merchant_connector_account,
+                        merchant_account,
+                        mandate.clone(),
+                    )
+                    .await?;
+
+                    let _response = services::execute_connector_processing_step(
+                        state,
+                        connector_integration,
+                        &router_data,
+                        call_connector_action,
+                        None,
+                    )
+                    .await
+                    .change_context(errors::ApiErrorResponse::InternalServerError)?;
+                    // TODO:Add the revoke mandate task to process tracker
+                    mandate::update_mandate_procedure(
+                        state,
+                        resp,
+                        mandate,
+                        &merchant_account.merchant_id,
+                        pm_id,
+                    )
+                    .await
+                }
+                Ok(_) => Err(errors::ApiErrorResponse::InternalServerError)
+                    .into_report()
+                    .attach_printable("Unexpected response received")?,
+                Err(_) => Ok(resp),
+            }
+        } else {
+            Err(errors::ApiErrorResponse::InternalServerError)
+                .into_report()
+                .attach_printable("Update Mandate Flow not implemented for the connector ")?
+        }
+    }
 }
 
 impl mandate::MandateBehaviour for types::SetupMandateRequestData {
diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs
index e92a924bf12..6cf547f668f 100644
--- a/crates/router/src/core/payments/transformers.rs
+++ b/crates/router/src/core/payments/transformers.rs
@@ -1342,7 +1342,6 @@ impl<F: Clone> TryFrom<PaymentAdditionalData<'_, F>> for types::PaymentsRejectDa
         })
     }
 }
-
 impl<F: Clone> TryFrom<PaymentAdditionalData<'_, F>> for types::PaymentsSessionData {
     type Error = error_stack::Report<errors::ApiErrorResponse>;
 
diff --git a/loadtest/config/development.toml b/loadtest/config/development.toml
index b9119b0dbb8..14d119768d0 100644
--- a/loadtest/config/development.toml
+++ b/loadtest/config/development.toml
@@ -252,6 +252,13 @@ bank_debit.sepa = { connector_list = "gocardless"}
 bank_redirect.ideal = {connector_list = "stripe,adyen,globalpay"}
 bank_redirect.sofort = {connector_list = "stripe,adyen,globalpay"}
 
+[mandates.update_mandate_supported]
+card.credit ={connector_list ="cybersource"}
+card.debit = {connector_list ="cybersource"}
+
+[mandates.update_mandate_supported]
+connector_list = "cybersource"
+
 [analytics]
 source = "sqlx"
 

## Type of Change
<!-- Put an `x` in the boxes that apply -->

- [ ] Bugfix
- [x] New feature
- [ ] Enhancement
- [ ] Refactoring
- [ ] Dependency updates
- [ ] Documentation
- [ ] CI/CD

## Description
 add config for update_mandate_flow and allow only those payment_methods that support update while Listing PaymentMethods For Merchants


### Additional Changes

- [ ] This PR modifies the API contract
- [ ] This PR modifies the database schema
- [ ] This PR modifies application configuration/environment variables

<!--
Provide links to the files with corresponding changes.

Following are the paths where you can find config files:
1. `config`
2. `crates/router/src/configs`
3. `loadtest/config`
-->


## Motivation and Context
<!--
Why is this change required? What problem does it solve?
If it fixes an open issue, please link to the issue here.

If you don't have an issue, we'd recommend starting with one first so the PR
can focus on the implementation (unless it is an obvious bug or documentation fix
that will have little conversation).
-->


## How did you test it?
- Create an MA and a MCA for Cybersource 
> Create an update_,mandate payment using cyber source it'll be successful
- Create  an MA and a MCA forStripe 
>  Create an update_,mandate payment using cyber source it should throw a 5xx

- Now ListPaymentMethodsForMerchnat in an Update Flow, we only list cards


## Checklist
<!-- Put an `x` in the boxes that apply -->

- [x] I formatted the code `cargo +nightly fmt --all`
- [x] I addressed lints thrown by `cargo clippy`
- [x] I reviewed the submitted code
- [ ] I added unit tests for my changes where possible
- [ ] I added a [CHANGELOG](/CHANGELOG.md) entry if applicable
