Bug: [FEATURE] Update MCA Update to process additional merchant data for open banking connectors



### Feature Description

Currently, we only accept `additional_merchant_data` in the MCA create req, we need to accept it in update req as well and and add the logic for processing the data in the MCA update core.

### Possible Implementation

Need to update the relevant api_models and core logic

### 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/api-reference-v2/openapi_spec.json b/api-reference-v2/openapi_spec.json
index 458e1ae9ff0..b68a5c91c8b 100644
--- a/api-reference-v2/openapi_spec.json
+++ b/api-reference-v2/openapi_spec.json
@@ -7766,6 +7766,14 @@
             "example": "y3oqhf46pyzuxjbcn2giaqnb44",
             "maxLength": 64,
             "minLength": 1
+          },
+          "additional_merchant_data": {
+            "allOf": [
+              {
+                "$ref": "#/components/schemas/AdditionalMerchantData"
+              }
+            ],
+            "nullable": true
           }
         },
         "additionalProperties": false
diff --git a/crates/api_models/src/admin.rs b/crates/api_models/src/admin.rs
index b073c219517..e4f61fc2e41 100644
--- a/crates/api_models/src/admin.rs
+++ b/crates/api_models/src/admin.rs
@@ -1555,6 +1555,10 @@ pub struct MerchantConnectorUpdate {
 
     #[schema(value_type = ConnectorStatus, example = "inactive")]
     pub status: Option<api_enums::ConnectorStatus>,
+
+    /// In case the merchant needs to store any additional sensitive data
+    #[schema(value_type = Option<AdditionalMerchantData>)]
+    pub additional_merchant_data: Option<AdditionalMerchantData>,
 }
 
 /// Create a new Merchant Connector for the merchant account. The connector could be a payment processor / facilitator / acquirer or specialized services like Fraud / Accounting etc."
@@ -1636,6 +1640,10 @@ pub struct MerchantConnectorUpdate {
     /// The identifier for the Merchant Account
     #[schema(value_type = String, max_length = 64, min_length = 1, example = "y3oqhf46pyzuxjbcn2giaqnb44")]
     pub merchant_id: id_type::MerchantId,
+
+    /// In case the merchant needs to store any additional sensitive data
+    #[schema(value_type = Option<AdditionalMerchantData>)]
+    pub additional_merchant_data: Option<AdditionalMerchantData>,
 }
 
 #[cfg(all(feature = "v2", feature = "merchant_connector_account_v2"))]
diff --git a/crates/diesel_models/src/merchant_connector_account.rs b/crates/diesel_models/src/merchant_connector_account.rs
index 876240f44a3..19fe880f3aa 100644
--- a/crates/diesel_models/src/merchant_connector_account.rs
+++ b/crates/diesel_models/src/merchant_connector_account.rs
@@ -203,6 +203,7 @@ pub struct MerchantConnectorAccountUpdateInternal {
     pub pm_auth_config: Option<pii::SecretSerdeValue>,
     pub status: Option<storage_enums::ConnectorStatus>,
     pub connector_wallets_details: Option<Encryption>,
+    pub additional_merchant_data: Option<Encryption>,
 }
 
 #[cfg(all(feature = "v2", feature = "merchant_connector_account_v2"))]
@@ -224,6 +225,7 @@ pub struct MerchantConnectorAccountUpdateInternal {
     pub pm_auth_config: Option<pii::SecretSerdeValue>,
     pub status: Option<storage_enums::ConnectorStatus>,
     pub connector_wallets_details: Option<Encryption>,
+    pub additional_merchant_data: Option<Encryption>,
 }
 
 #[cfg(all(
diff --git a/crates/hyperswitch_domain_models/src/merchant_connector_account.rs b/crates/hyperswitch_domain_models/src/merchant_connector_account.rs
index 9e2f6918b43..d763531f3bd 100644
--- a/crates/hyperswitch_domain_models/src/merchant_connector_account.rs
+++ b/crates/hyperswitch_domain_models/src/merchant_connector_account.rs
@@ -109,6 +109,7 @@ pub enum MerchantConnectorAccountUpdate {
         connector_label: Option<String>,
         status: Option<enums::ConnectorStatus>,
         connector_wallets_details: Option<Encryptable<pii::SecretSerdeValue>>,
+        additional_merchant_data: Option<Encryptable<pii::SecretSerdeValue>>,
     },
     ConnectorWalletDetailsUpdate {
         connector_wallets_details: Encryptable<pii::SecretSerdeValue>,
@@ -131,6 +132,7 @@ pub enum MerchantConnectorAccountUpdate {
         connector_label: Option<String>,
         status: Option<enums::ConnectorStatus>,
         connector_wallets_details: Option<Encryptable<pii::SecretSerdeValue>>,
+        additional_merchant_data: Option<Encryptable<pii::SecretSerdeValue>>,
     },
     ConnectorWalletDetailsUpdate {
         connector_wallets_details: Encryptable<pii::SecretSerdeValue>,
@@ -453,6 +455,7 @@ impl From<MerchantConnectorAccountUpdate> for MerchantConnectorAccountUpdateInte
                 connector_label,
                 status,
                 connector_wallets_details,
+                additional_merchant_data,
             } => Self {
                 connector_type,
                 connector_name,
@@ -471,6 +474,7 @@ impl From<MerchantConnectorAccountUpdate> for MerchantConnectorAccountUpdateInte
                 connector_label,
                 status,
                 connector_wallets_details: connector_wallets_details.map(Encryption::from),
+                additional_merchant_data: additional_merchant_data.map(Encryption::from),
             },
             MerchantConnectorAccountUpdate::ConnectorWalletDetailsUpdate {
                 connector_wallets_details,
@@ -492,6 +496,7 @@ impl From<MerchantConnectorAccountUpdate> for MerchantConnectorAccountUpdateInte
                 applepay_verified_domains: None,
                 pm_auth_config: None,
                 status: None,
+                additional_merchant_data: None,
             },
         }
     }
@@ -514,6 +519,7 @@ impl From<MerchantConnectorAccountUpdate> for MerchantConnectorAccountUpdateInte
                 connector_label,
                 status,
                 connector_wallets_details,
+                additional_merchant_data,
             } => Self {
                 connector_type,
                 connector_account_details: connector_account_details.map(Encryption::from),
@@ -528,6 +534,7 @@ impl From<MerchantConnectorAccountUpdate> for MerchantConnectorAccountUpdateInte
                 connector_label,
                 status,
                 connector_wallets_details: connector_wallets_details.map(Encryption::from),
+                additional_merchant_data: additional_merchant_data.map(Encryption::from),
             },
             MerchantConnectorAccountUpdate::ConnectorWalletDetailsUpdate {
                 connector_wallets_details,
@@ -545,6 +552,7 @@ impl From<MerchantConnectorAccountUpdate> for MerchantConnectorAccountUpdateInte
                 applepay_verified_domains: None,
                 pm_auth_config: None,
                 status: None,
+                additional_merchant_data: None,
             },
         }
     }
diff --git a/crates/router/src/core/admin.rs b/crates/router/src/core/admin.rs
index 1f5fb068408..da497c77f16 100644
--- a/crates/router/src/core/admin.rs
+++ b/crates/router/src/core/admin.rs
@@ -2027,6 +2027,30 @@ impl MerchantConnectorAccountUpdateBridge for api_models::admin::MerchantConnect
 
         pm_auth_config_validation.validate_pm_auth_config().await?;
 
+        let merchant_recipient_data = if let Some(data) = &self.additional_merchant_data {
+            Some(
+                process_open_banking_connectors(
+                    state,
+                    merchant_account.get_id(),
+                    &auth,
+                    &self.connector_type,
+                    &connector_enum,
+                    types::AdditionalMerchantData::foreign_from(data.clone()),
+                )
+                .await?,
+            )
+        } else {
+            None
+        }
+        .map(|data| {
+            serde_json::to_value(types::AdditionalMerchantData::OpenBankingRecipientData(
+                data,
+            ))
+        })
+        .transpose()
+        .change_context(errors::ApiErrorResponse::InternalServerError)
+        .attach_printable("Failed to serialize MerchantRecipientData")?;
+
         Ok(storage::MerchantConnectorAccountUpdate::Update {
             connector_type: Some(self.connector_type),
             connector_label: self.connector_label.clone(),
@@ -2061,6 +2085,23 @@ impl MerchantConnectorAccountUpdateBridge for api_models::admin::MerchantConnect
             applepay_verified_domains: None,
             pm_auth_config: self.pm_auth_config,
             status: Some(connector_status),
+            additional_merchant_data: if let Some(mcd) = merchant_recipient_data {
+                Some(
+                    domain_types::crypto_operation(
+                        key_manager_state,
+                        type_name!(domain::MerchantConnectorAccount),
+                        domain_types::CryptoOperation::Encrypt(Secret::new(mcd)),
+                        km_types::Identifier::Merchant(key_store.merchant_id.clone()),
+                        key_store.key.peek(),
+                    )
+                    .await
+                    .and_then(|val| val.try_into_operation())
+                    .change_context(errors::ApiErrorResponse::InternalServerError)
+                    .attach_printable("Unable to encrypt additional_merchant_data")?,
+                )
+            } else {
+                None
+            },
             connector_wallets_details: helpers::get_encrypted_apple_pay_connector_wallets_details(
                 state, &key_store, &metadata,
             )
@@ -2163,6 +2204,30 @@ impl MerchantConnectorAccountUpdateBridge for api_models::admin::MerchantConnect
             }
         }
 
+        let merchant_recipient_data = if let Some(data) = &self.additional_merchant_data {
+            Some(
+                process_open_banking_connectors(
+                    state,
+                    merchant_account.get_id(),
+                    &auth,
+                    &self.connector_type,
+                    &connector_enum,
+                    types::AdditionalMerchantData::foreign_from(data.clone()),
+                )
+                .await?,
+            )
+        } else {
+            None
+        }
+        .map(|data| {
+            serde_json::to_value(types::AdditionalMerchantData::OpenBankingRecipientData(
+                data,
+            ))
+        })
+        .transpose()
+        .change_context(errors::ApiErrorResponse::InternalServerError)
+        .attach_printable("Failed to serialize MerchantRecipientData")?;
+
         Ok(storage::MerchantConnectorAccountUpdate::Update {
             connector_type: Some(self.connector_type),
             connector_name: None,
@@ -2200,6 +2265,23 @@ impl MerchantConnectorAccountUpdateBridge for api_models::admin::MerchantConnect
             applepay_verified_domains: None,
             pm_auth_config: self.pm_auth_config,
             status: Some(connector_status),
+            additional_merchant_data: if let Some(mcd) = merchant_recipient_data {
+                Some(
+                    domain_types::crypto_operation(
+                        key_manager_state,
+                        type_name!(domain::MerchantConnectorAccount),
+                        domain_types::CryptoOperation::Encrypt(Secret::new(mcd)),
+                        km_types::Identifier::Merchant(key_store.merchant_id.clone()),
+                        key_store.key.peek(),
+                    )
+                    .await
+                    .and_then(|val| val.try_into_operation())
+                    .change_context(errors::ApiErrorResponse::InternalServerError)
+                    .attach_printable("Unable to encrypt additional_merchant_data")?,
+                )
+            } else {
+                None
+            },
             connector_wallets_details: helpers::get_encrypted_apple_pay_connector_wallets_details(
                 state, &key_store, &metadata,
             )
@@ -2297,7 +2379,7 @@ impl MerchantConnectorAccountCreateBridge for api::MerchantConnectorCreate {
         })
         .transpose()
         .change_context(errors::ApiErrorResponse::InternalServerError)
-        .attach_printable("Failed to get MerchantRecipientData")?;
+        .attach_printable("Failed to serialize MerchantRecipientData")?;
         Ok(domain::MerchantConnectorAccount {
             merchant_id: business_profile.merchant_id.clone(),
             connector_type: self.connector_type,
@@ -2346,7 +2428,7 @@ impl MerchantConnectorAccountCreateBridge for api::MerchantConnectorCreate {
                     key_manager_state,
                     type_name!(domain::MerchantConnectorAccount),
                     domain_types::CryptoOperation::Encrypt(Secret::new(mcd)),
-                    identifier,
+                    km_types::Identifier::Merchant(key_store.merchant_id.clone()),
                     key_store.key.peek(),
                 )
                 .await
@@ -2463,7 +2545,7 @@ impl MerchantConnectorAccountCreateBridge for api::MerchantConnectorCreate {
         })
         .transpose()
         .change_context(errors::ApiErrorResponse::InternalServerError)
-        .attach_printable("Failed to get MerchantRecipientData")?;
+        .attach_printable("Failed to serialize MerchantRecipientData")?;
         Ok(domain::MerchantConnectorAccount {
             merchant_id: business_profile.merchant_id.clone(),
             connector_type: self.connector_type,
diff --git a/crates/router/src/core/connector_onboarding/paypal.rs b/crates/router/src/core/connector_onboarding/paypal.rs
index 13b2bf16cdb..f967f2aece3 100644
--- a/crates/router/src/core/connector_onboarding/paypal.rs
+++ b/crates/router/src/core/connector_onboarding/paypal.rs
@@ -164,6 +164,7 @@ pub async fn update_mca(
         connector_webhook_details: None,
         pm_auth_config: None,
         test_mode: None,
+        additional_merchant_data: None,
     };
     #[cfg(all(feature = "v2", feature = "merchant_connector_account_v2"))]
     let request = MerchantConnectorUpdate {
@@ -178,6 +179,7 @@ pub async fn update_mca(
         connector_webhook_details: None,
         pm_auth_config: None,
         merchant_id: merchant_id.clone(),
+        additional_merchant_data: None,
     };
     let mca_response =
         admin::update_connector(state.clone(), &merchant_id, None, &connector_id, request).await?;
diff --git a/crates/router/src/core/verification/utils.rs b/crates/router/src/core/verification/utils.rs
index dd0aa3edef4..012f04299da 100644
--- a/crates/router/src/core/verification/utils.rs
+++ b/crates/router/src/core/verification/utils.rs
@@ -87,6 +87,7 @@ pub async fn check_existence_and_add_domain_to_db(
         connector_label: None,
         status: None,
         connector_wallets_details: None,
+        additional_merchant_data: None,
     };
     #[cfg(all(feature = "v2", feature = "merchant_connector_account_v2"))]
     let updated_mca = storage::MerchantConnectorAccountUpdate::Update {
@@ -102,6 +103,7 @@ pub async fn check_existence_and_add_domain_to_db(
         connector_label: None,
         status: None,
         connector_wallets_details: None,
+        additional_merchant_data: None,
     };
     state
         .store

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

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

## Description
<!-- Describe your changes in detail -->
This PR does - 
- In the PIS flow,  in merchant connector update, we didn't collect `additional_merchant_data` in the update req, have fixed that. Have also added relevant logic in MCA update core to process the data collected.

### 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?
<!--
Did you write an integration/unit/API test to verify the code changes?
Or did you test this change manually (provide relevant screenshots)?
-->
1. MCA create for Plaid - 
```
curl --location --request POST 'http://localhost:8080/account/merchant_1724231900/connectors' \
--header 'api-key: test_admin' \
--header 'Content-Type: application/json' \
--data-raw '{
    "connector_type": "payment_processor",
    "connector_name": "plaid",
    "connector_account_details": {
        "auth_type": "BodyKey",
        "api_key": "something",
        "key1": "something"
    },
    "test_mode": false,
    "disabled": false,
    "payment_methods_enabled": [
        {
            "payment_method": "open_banking",
            "payment_method_types": [
                {
                    "payment_method_type": "open_banking_pis",
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true,
                    "payment_experience": "redirect_to_url",
                    "accepted_currencies": {
                        "type": "enable_only",
                        "list": [
                            "EUR",
                            "GBP"
                        ]
                    },
                    "minimum_amount": 0
                }
            ]
        }
    ],
    "metadata": {
        "city": "NY",
        "unit": "246"
    }
}'
```
2. Update MCA with `additional_merchant_data`
```
curl --location --request POST 'http://localhost:8080/account/merchant_1724231900/connectors/mca_HaQGes1t8LKrBYOF6OGj' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: dev_cZOhqwgSt6Dl6A95YW10eWHV6LI9h2mdQ9JtDB8kxMJ4YCjFEwf0g5O2WfDnrgrW' \
--data-raw '{
    "connector_type": "payment_processor",
    "additional_merchant_data": {
        "open_banking_recipient_data": {
            "account_data": {
                "iban": {
                    "iban": "IT38R7004962566080427G36725",
                    "name": "merchant_name"
                }
            }
        }
    }
}'
```
Resposne - 
```
{
    "connector_type": "payment_processor",
    "connector_name": "plaid",
    "connector_label": "plaid_GB_default",
    "merchant_connector_id": "mca_HaQGes1t8LKrBYOF6OGj",
    "profile_id": "pro_iWX6p7sOYZnOE10swzA2",
    "connector_account_details": {
        "auth_type": "BodyKey",
        "api_key": "something",
        "key1": "something"
    },
    "payment_methods_enabled": [
        {
            "payment_method": "open_banking",
            "payment_method_types": [
                {
                    "payment_method_type": "open_banking_pis",
                    "payment_experience": "redirect_to_url",
                    "card_networks": null,
                    "accepted_currencies": {
                        "type": "enable_only",
                        "list": [
                            "EUR",
                            "GBP"
                        ]
                    },
                    "accepted_countries": null,
                    "minimum_amount": 0,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                }
            ]
        }
    ],
    "connector_webhook_details": null,
    "metadata": {
        "city": "NY",
        "unit": "246"
    },
    "test_mode": false,
    "disabled": false,
    "frm_configs": null,
    "business_country": null,
    "business_label": null,
    "business_sub_label": null,
    "applepay_verified_domains": null,
    "pm_auth_config": null,
    "status": "active",
    "additional_merchant_data": {
        "open_banking_recipient_data": {
            "account_data": {
                "iban": {
                    "iban": "IT38R7004962566080427G36725",
                    "name": "merchant_name",
                    "connector_recipient_id": "recipient-id-sandbox-3fafd4a5-269e-4ebc-9f9b-6f18c8f91a73"
                }
            }
        }
    }
}
```


## 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`
- [ ] I reviewed the submitted code
- [ ] I added unit tests for my changes where possible
