Bug: [BUG] Certificate decode failed when creating the session token for `applepay`



### Bug Description

It bugs out when creating session token for `applepay` if the certificate provided is in the wrong format.

### Expected Behavior

If the certificate provided is in the wrong format, then it should error out during creation of the `merchant_connector_account` where the certificate is provided.

### Actual Behavior

It fails when creating the session token for applepay.

### Steps To Reproduce

Provide an unambiguous set of steps to reproduce this bug. Include code or configuration to reproduce, if relevant.
1. Create a mca with wrong applepay certificate ( delete few characters, or do not base64 encode ).
2. Create a payment with confirm = false
3. Create session token
Result -> Applepay session token will not be generated

The log will be 
![Screenshot 2023-06-07 at 11 30 24 AM](https://github.com/juspay/hyperswitch/assets/48803246/5644cc0b-1fbe-49f6-b33f-6e1a09a0dcce)



### Context For The Bug

_No response_

### Environment

Are you using hyperswitch hosted version? Yes/No No
If yes, please provide the value of the `x-request-id` response header for helping us debug your issue.


### Have you spent some time to check if this bug has been raised before?

- [X] I checked and didn't find 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/crates/api_models/src/payments.rs b/crates/api_models/src/payments.rs
index 83be6c85c3f..96b5e3f29b4 100644
--- a/crates/api_models/src/payments.rs
+++ b/crates/api_models/src/payments.rs
@@ -1713,6 +1713,12 @@ pub struct ApplepaySessionRequest {
     pub initiative_context: String,
 }
 
+#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
+pub struct ConnectorMetadata {
+    pub apple_pay: Option<ApplePayMetadata>,
+    pub google_pay: Option<GpayMetaData>,
+}
+
 #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
 pub struct ApplepaySessionTokenData {
     #[serde(rename = "apple_pay")]
diff --git a/crates/router/src/core/admin.rs b/crates/router/src/core/admin.rs
index 72f2e9eaa92..c36ba7c734d 100644
--- a/crates/router/src/core/admin.rs
+++ b/crates/router/src/core/admin.rs
@@ -380,6 +380,36 @@ fn get_business_details_wrapper(
     }
 }
 
+fn validate_certificate_in_mca_metadata(
+    connector_metadata: Secret<serde_json::Value>,
+) -> RouterResult<()> {
+    let parsed_connector_metadata = connector_metadata
+        .parse_value::<api_models::payments::ConnectorMetadata>("ApplepaySessionTokenData")
+        .change_context(errors::ParsingError::StructParseFailure("Metadata"))
+        .change_context(errors::ApiErrorResponse::InvalidDataFormat {
+            field_name: "metadata".to_string(),
+            expected_format: "connector metadata".to_string(),
+        })?;
+
+    parsed_connector_metadata
+        .apple_pay
+        .map(|applepay_metadata| {
+            let api_models::payments::SessionTokenInfo {
+                certificate,
+                certificate_keys,
+                ..
+            } = applepay_metadata.session_token_data;
+            helpers::create_identity_from_certificate_and_key(certificate, certificate_keys)
+                .change_context(errors::ApiErrorResponse::InvalidDataValue {
+                    field_name: "certificate/certificate key",
+                })
+                .map(|_identity_result| ())
+        })
+        .transpose()?;
+
+    Ok(())
+}
+
 pub async fn create_payment_connector(
     store: &dyn StorageInterface,
     req: api::MerchantConnectorCreate,
@@ -390,6 +420,11 @@ pub async fn create_payment_connector(
         .change_context(errors::ApiErrorResponse::InternalServerError)
         .attach_printable("Unable to get key from merchant key store")?;
 
+    req.metadata
+        .clone()
+        .map(validate_certificate_in_mca_metadata)
+        .transpose()?;
+
     let merchant_account = store
         .find_merchant_account_by_merchant_id(merchant_id)
         .await
diff --git a/crates/router/src/core/payments/helpers.rs b/crates/router/src/core/payments/helpers.rs
index 88c71df4814..9dfdbef9f62 100644
--- a/crates/router/src/core/payments/helpers.rs
+++ b/crates/router/src/core/payments/helpers.rs
@@ -1,5 +1,6 @@
 use std::borrow::Cow;
 
+use base64::Engine;
 use common_utils::{
     ext_traits::{AsyncExt, ByteSliceExt, ValueExt},
     fp_utils, generate_id, pii,
@@ -46,6 +47,33 @@ use crate::{
     },
 };
 
+pub fn create_identity_from_certificate_and_key(
+    encoded_certificate: String,
+    encoded_certificate_key: String,
+) -> Result<reqwest::Identity, error_stack::Report<errors::ApiClientError>> {
+    let decoded_certificate = consts::BASE64_ENGINE
+        .decode(encoded_certificate)
+        .into_report()
+        .change_context(errors::ApiClientError::CertificateDecodeFailed)?;
+
+    let decoded_certificate_key = consts::BASE64_ENGINE
+        .decode(encoded_certificate_key)
+        .into_report()
+        .change_context(errors::ApiClientError::CertificateDecodeFailed)?;
+
+    let certificate = String::from_utf8(decoded_certificate)
+        .into_report()
+        .change_context(errors::ApiClientError::CertificateDecodeFailed)?;
+
+    let certificate_key = String::from_utf8(decoded_certificate_key)
+        .into_report()
+        .change_context(errors::ApiClientError::CertificateDecodeFailed)?;
+
+    reqwest::Identity::from_pkcs8_pem(certificate.as_bytes(), certificate_key.as_bytes())
+        .into_report()
+        .change_context(errors::ApiClientError::CertificateDecodeFailed)
+}
+
 pub fn filter_mca_based_on_business_details(
     merchant_connector_accounts: Vec<domain::MerchantConnectorAccount>,
     payment_intent: Option<&storage_models::payment_intent::PaymentIntent>,
diff --git a/crates/router/src/services/api/client.rs b/crates/router/src/services/api/client.rs
index 3d6ba2afcb3..d37f22f750a 100644
--- a/crates/router/src/services/api/client.rs
+++ b/crates/router/src/services/api/client.rs
@@ -1,11 +1,12 @@
-use base64::Engine;
 use error_stack::{IntoReport, ResultExt};
 use once_cell::sync::OnceCell;
 
 use crate::{
     configs::settings::{Locker, Proxy},
-    consts,
-    core::errors::{self, CustomResult},
+    core::{
+        errors::{self, CustomResult},
+        payments,
+    },
 };
 
 static NON_PROXIED_CLIENT: OnceCell<reqwest::Client> = OnceCell::new();
@@ -74,30 +75,13 @@ pub(super) fn create_client(
     client_certificate_key: Option<String>,
 ) -> CustomResult<reqwest::Client, errors::ApiClientError> {
     match (client_certificate, client_certificate_key) {
-        (Some(encoded_cert), Some(encoded_cert_key)) => {
+        (Some(encoded_certificate), Some(encoded_certificate_key)) => {
             let client_builder = get_client_builder(proxy_config, should_bypass_proxy)?;
 
-            let decoded_cert = consts::BASE64_ENGINE
-                .decode(encoded_cert)
-                .into_report()
-                .change_context(errors::ApiClientError::CertificateDecodeFailed)?;
-            let decoded_cert_key = consts::BASE64_ENGINE
-                .decode(encoded_cert_key)
-                .into_report()
-                .change_context(errors::ApiClientError::CertificateDecodeFailed)?;
-
-            let certificate = String::from_utf8(decoded_cert)
-                .into_report()
-                .change_context(errors::ApiClientError::CertificateDecodeFailed)?;
-            let certificate_key = String::from_utf8(decoded_cert_key)
-                .into_report()
-                .change_context(errors::ApiClientError::CertificateDecodeFailed)?;
-            let identity = reqwest::Identity::from_pkcs8_pem(
-                certificate.as_bytes(),
-                certificate_key.as_bytes(),
-            )
-            .into_report()
-            .change_context(errors::ApiClientError::CertificateDecodeFailed)?;
+            let identity = payments::helpers::create_identity_from_certificate_and_key(
+                encoded_certificate,
+                encoded_certificate_key,
+            )?;
 
             client_builder
                 .identity(identity)

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

- [x] Bugfix

## Description
<!-- Describe your changes in detail -->
We used to have a lot of errors when creating applepay session tokens because of invalid certificates being sent when creating the merchant connector account. 

This PR will not allow the merchant connector account to be created if the format of certificates are invalid. To do this, it will decode the certificates and then create the identity ( the same process is followed when we will be sending the request to applepay, so if this succeeds then we can be sure that the session token will not have any certificate decode errors ).

This will remove unnecessary 5xx being sent, such errors are bad request errors.


## 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 its an obvious bug or documentation fix
that will have little conversation).
-->
Fixes #1373 

## 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)?
-->
- Create mca with valid certificates -> session tokens are generated correctly
<img width="839" alt="Screenshot 2023-06-08 at 12 26 57 PM" src="https://github.com/juspay/hyperswitch/assets/48803246/4eab7519-4501-45fd-8475-7906216804aa">


- Create mca with invalid applepay certificates.
<img width="1257" alt="Screenshot 2023-06-08 at 12 28 48 PM" src="https://github.com/juspay/hyperswitch/assets/48803246/acfa1553-bb49-4387-be49-796b902773e1">

- Create mca with invalid format for metadata, will fail
<img width="1274" alt="Screenshot 2023-06-08 at 12 32 01 PM" src="https://github.com/juspay/hyperswitch/assets/48803246/a361d4c7-3085-44bf-96c1-d81e0a1d7f94">

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