Bug: [BUG]:   MCA metadata deserialization failures should be 4xx



### :memo: Feature Description

- We don't have validation for Merchant Connector Account metadata, So while creating MCA we are allowing any json value. Because of which RequestEncodingFailure happening during payments for the MCA which doesn't have the expected fields. 
- Recreating scenario : Create a merchant connector account for coinbase with empty metadata .It doesn't throw error as we don't have metadata validation for coinbase . If you try to make payment now this will throw deserilization error for `CoinbaseConnectorMeta` which is merchant connector metadata for coinbase .



### :hammer: Possible Implementation

- In the event of a deserialization failure of MCA metadata during payments and refunds, convert the ParsingFailed error to ConnectorError::InvalidConnectorConfig. 
- We already have authType validation in core/admin.rs , we need similar validation for connector metadata for coinbase .
- Make sure that the config field in ConnectorError::InvalidConnectorConfig specifies the invalid configuration name. 
- Note that the ConnectorError::InvalidConnectorConfig error is already associated with [HTTP 400](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/400) in the core.
- You can check this PR for further reference https://github.com/juspay/hyperswitch/pull/2746

:bookmark: Note: All the changes needed should be contained within  `/hyperswitch_oss/crates/router/src/connector/utils.rs`


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

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

### :package: Have you read the Contributing Guidelines?

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

### :sparkles: Are you willing to submit a PR?
diff --git a/crates/router/src/connector/coinbase/transformers.rs b/crates/router/src/connector/coinbase/transformers.rs
index ce9bb3e871c..b1435e50df9 100644
--- a/crates/router/src/connector/coinbase/transformers.rs
+++ b/crates/router/src/connector/coinbase/transformers.rs
@@ -1,5 +1,7 @@
 use std::collections::HashMap;
 
+use common_utils::pii;
+use error_stack::ResultExt;
 use serde::{Deserialize, Serialize};
 
 use crate::{
@@ -250,6 +252,14 @@ pub struct CoinbaseConnectorMeta {
     pub pricing_type: String,
 }
 
+impl TryFrom<&Option<pii::SecretSerdeValue>> for CoinbaseConnectorMeta {
+    type Error = error_stack::Report<errors::ConnectorError>;
+    fn try_from(meta_data: &Option<pii::SecretSerdeValue>) -> Result<Self, Self::Error> {
+        utils::to_connector_meta_from_secret(meta_data.clone())
+            .change_context(errors::ConnectorError::InvalidConnectorConfig { config: "metadata" })
+    }
+}
+
 fn get_crypto_specific_payment_data(
     item: &types::PaymentsAuthorizeRouterData,
 ) -> Result<CoinbasePaymentsRequest, error_stack::Report<errors::ConnectorError>> {
@@ -260,11 +270,10 @@ fn get_crypto_specific_payment_data(
     let name =
         billing_address.and_then(|add| add.get_first_name().ok().map(|name| name.to_owned()));
     let description = item.get_description().ok();
-    let connector_meta: CoinbaseConnectorMeta =
-        utils::to_connector_meta_from_secret_with_required_field(
-            item.connector_meta_data.clone(),
-            "Pricing Type Not present in connector meta data",
-        )?;
+    let connector_meta = CoinbaseConnectorMeta::try_from(&item.connector_meta_data)
+        .change_context(errors::ConnectorError::InvalidConnectorConfig {
+            config: "Merchant connector account metadata",
+        })?;
     let pricing_type = connector_meta.pricing_type;
     let local_price = get_local_price(item);
     let redirect_url = item.request.get_return_url()?;
diff --git a/crates/router/src/connector/utils.rs b/crates/router/src/connector/utils.rs
index 8f028e37a9e..9df11a6dd14 100644
--- a/crates/router/src/connector/utils.rs
+++ b/crates/router/src/connector/utils.rs
@@ -1198,23 +1198,6 @@ where
     json.parse_value(std::any::type_name::<T>()).switch()
 }
 
-pub fn to_connector_meta_from_secret_with_required_field<T>(
-    connector_meta: Option<Secret<serde_json::Value>>,
-    error_message: &'static str,
-) -> Result<T, Error>
-where
-    T: serde::de::DeserializeOwned,
-{
-    let connector_error = errors::ConnectorError::MissingRequiredField {
-        field_name: error_message,
-    };
-    let parsed_meta = to_connector_meta_from_secret(connector_meta).ok();
-    match parsed_meta {
-        Some(meta) => Ok(meta),
-        _ => Err(connector_error.into()),
-    }
-}
-
 pub fn to_connector_meta_from_secret<T>(
     connector_meta: Option<Secret<serde_json::Value>>,
 ) -> Result<T, Error>
diff --git a/crates/router/src/core/admin.rs b/crates/router/src/core/admin.rs
index fd4cae3a2b9..364c5b9b212 100644
--- a/crates/router/src/core/admin.rs
+++ b/crates/router/src/core/admin.rs
@@ -1713,9 +1713,9 @@ pub(crate) fn validate_auth_and_metadata_type(
             checkout::transformers::CheckoutAuthType::try_from(val)?;
             Ok(())
         }
-
         api_enums::Connector::Coinbase => {
             coinbase::transformers::CoinbaseAuthType::try_from(val)?;
+            coinbase::transformers::CoinbaseConnectorMeta::try_from(connector_meta_data)?;
             Ok(())
         }
         api_enums::Connector::Cryptopay => {

## 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 -->

I've removed `to_connector_meta_from_secret_with_required_field`, which uses `MissingRequiredField` as an error (I also didn't like the unnecessary initialization of the `MissingRequiredField` before we knew if it would be needed). Instead, I added a `TryFrom` implementation for `CoinbaseConnectorMeta`, which uses the requested `ConnectorError::InvalidConnectorConfig`. Additionally, I included `CoinbaseConnectorMeta::try_from` in the `validate_auth_and_metadata_type` as suggested.

### Migration

```
-- The migration is for adding an empty `pricing_type` attribute for `CoinbaseConnectorMeta` where it is missing.
UPDATE merchant_connector_account
SET metadata = jsonb_insert(
    metadata,
    '{pricing_type}',
    '""',
    true
)
WHERE connector_name = 'coinbase'
    AND NOT metadata ? 'pricing_type';
```

### Additional Changes

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


## 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).
-->
This PR addresses the bug from the issue: https://github.com/juspay/hyperswitch/issues/2899.

## 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)?
-->

**Run unit test:**
```
cargo test --release  --package router --lib connector::coinbase::transformers::tests::coinbase_payments_request_try_from_works -- --exact
```
![image](https://github.com/juspay/hyperswitch/assets/8159517/a296af9b-a454-4d9b-a8ad-1939a837f04b)


### Migration script test

https://onecompiler.com/postgresql/3zz2tpkad

**Test script with test data and run migration:**
```label=dsa
CREATE TABLE merchant_connector_account (
    id SERIAL PRIMARY KEY,
    connector_name VARCHAR(255) NOT NULL
);
ALTER TABLE merchant_connector_account ADD COLUMN metadata JSONB DEFAULT NULL;

-- insert test data
INSERT INTO merchant_connector_account (
        id,
        connector_name,
        metadata
    )
VALUES
  (1, 'coinbase', '{ "pricing_type": "fixed-rate" }'),
  (2, 'coinbase', '{ "whatever_attribute": "abc" }'),
  (3, 'coinbase', '{}');

-- Before
select * from merchant_connector_account;

-- Run migration:
-- The migration is for adding an empty `pricing_type` attribute for `CoinbaseConnectorMeta` where it is missing.
UPDATE merchant_connector_account
SET metadata = jsonb_insert(
    metadata,
    '{pricing_type}',
    '""',
    true
)
WHERE connector_name = 'coinbase'
    AND NOT metadata ? 'pricing_type';
    
-- After
select * from merchant_connector_account;
```

**Output:**
```
Output:

CREATE TABLE
ALTER TABLE
INSERT 0 3
 id | connector_name |            metadata            
----+----------------+--------------------------------
  1 | coinbase       | {"pricing_type": "fixed-rate"}
  2 | coinbase       | {"whatever_attribute": "abc"}
  3 | coinbase       | {}
(3 rows)

UPDATE 2
 id | connector_name |                     metadata                      
----+----------------+---------------------------------------------------
  1 | coinbase       | {"pricing_type": "fixed-rate"}
  2 | coinbase       | {"pricing_type": "", "whatever_attribute": "abc"}
  3 | coinbase       | {"pricing_type": ""}
(3 rows)
```

**Run locally:**

**Invalid metadata:**
![image](https://github.com/juspay/hyperswitch/assets/8159517/5e087dad-9dab-4441-a444-787d8e720c1a)

**Empty metadata:**
![image](https://github.com/juspay/hyperswitch/assets/8159517/0f745195-0b0b-4276-aeba-c18ad11d3749)

**Correct metadata:**
![image](https://github.com/juspay/hyperswitch/assets/8159517/a5fe8ffa-12d2-449d-8363-a214aadca2fb)



## 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
- [x] I added unit tests for my changes where possible
- [ ] I added a [CHANGELOG](/CHANGELOG.md) entry if applicable
