Bug: [FEATURE] Set header consumption as optional in Open banking flows



### Feature Description

Set header consumption as optional in Open banking flows

### Possible Implementation

Set header consumption as optional in Open banking flows

### 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/crates/api_models/src/pm_auth.rs b/crates/api_models/src/pm_auth.rs
index 443a4c30394..8ed52907da8 100644
--- a/crates/api_models/src/pm_auth.rs
+++ b/crates/api_models/src/pm_auth.rs
@@ -4,8 +4,6 @@ use common_utils::{
     id_type, impl_api_event_type,
 };
 
-use crate::enums as api_enums;
-
 #[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
 #[serde(rename_all = "snake_case")]
 pub struct LinkTokenCreateRequest {
@@ -14,9 +12,6 @@ pub struct LinkTokenCreateRequest {
     pub payment_id: id_type::PaymentId, // payment_id to be passed in req body for redis pm_auth connector name fetch
     pub payment_method: PaymentMethod,  // payment_method to be used for filtering pm_auth connector
     pub payment_method_type: PaymentMethodType, // payment_method_type to be used for filtering pm_auth connector
-    pub client_platform: api_enums::ClientPlatform, // Client Platform to perform platform based processing
-    pub android_package_name: Option<String>, // Android Package name to be sent for Android platform
-    pub redirect_uri: Option<String>, // Merchant redirect_uri to be sent in case of IOS platform
 }
 
 #[derive(Debug, Clone, serde::Serialize)]
diff --git a/crates/pm_auth/src/connector/plaid/transformers.rs b/crates/pm_auth/src/connector/plaid/transformers.rs
index af0c26a5b85..a91aa57a1e4 100644
--- a/crates/pm_auth/src/connector/plaid/transformers.rs
+++ b/crates/pm_auth/src/connector/plaid/transformers.rs
@@ -45,28 +45,20 @@ impl TryFrom<&types::LinkTokenRouterData> for PlaidLinkTokenRequest {
                 )?,
             },
             android_package_name: match item.request.client_platform {
-                api_models::enums::ClientPlatform::Android => {
-                    Some(item.request.android_package_name.clone().ok_or(
-                        errors::ConnectorError::MissingRequiredField {
-                            field_name: "android_package_name",
-                        },
-                    )?)
+                Some(api_models::enums::ClientPlatform::Android) => {
+                    item.request.android_package_name.clone()
                 }
-                api_models::enums::ClientPlatform::Ios
-                | api_models::enums::ClientPlatform::Web
-                | api_models::enums::ClientPlatform::Unknown => None,
+                Some(api_models::enums::ClientPlatform::Ios)
+                | Some(api_models::enums::ClientPlatform::Web)
+                | Some(api_models::enums::ClientPlatform::Unknown)
+                | None => None,
             },
             redirect_uri: match item.request.client_platform {
-                api_models::enums::ClientPlatform::Ios => {
-                    Some(item.request.redirect_uri.clone().ok_or(
-                        errors::ConnectorError::MissingRequiredField {
-                            field_name: "redirect_uri",
-                        },
-                    )?)
-                }
-                api_models::enums::ClientPlatform::Android
-                | api_models::enums::ClientPlatform::Web
-                | api_models::enums::ClientPlatform::Unknown => None,
+                Some(api_models::enums::ClientPlatform::Ios) => item.request.redirect_uri.clone(),
+                Some(api_models::enums::ClientPlatform::Android)
+                | Some(api_models::enums::ClientPlatform::Web)
+                | Some(api_models::enums::ClientPlatform::Unknown)
+                | None => None,
             },
         })
     }
diff --git a/crates/pm_auth/src/types.rs b/crates/pm_auth/src/types.rs
index 878043afe50..bae9ee59848 100644
--- a/crates/pm_auth/src/types.rs
+++ b/crates/pm_auth/src/types.rs
@@ -25,7 +25,7 @@ pub struct LinkTokenRequest {
     pub country_codes: Option<Vec<String>>,
     pub language: Option<String>,
     pub user_info: Option<id_type::CustomerId>,
-    pub client_platform: api_enums::ClientPlatform,
+    pub client_platform: Option<api_enums::ClientPlatform>,
     pub android_package_name: Option<String>,
     pub redirect_uri: Option<String>,
 }
diff --git a/crates/router/src/connector/plaid/transformers.rs b/crates/router/src/connector/plaid/transformers.rs
index c4eb5a7a035..f0cf91b9cf6 100644
--- a/crates/router/src/connector/plaid/transformers.rs
+++ b/crates/router/src/connector/plaid/transformers.rs
@@ -163,21 +163,15 @@ impl TryFrom<&types::PaymentsPostProcessingRouterData> for PlaidLinkTokenRequest
         match item.request.payment_method_data {
             domain::PaymentMethodData::OpenBanking(ref data) => match data {
                 domain::OpenBankingData::OpenBankingPIS { .. } => {
-                    let headers = item.header_payload.clone().ok_or(
-                        errors::ConnectorError::MissingRequiredField {
-                            field_name: "header_payload",
-                        },
-                    )?;
+                    let headers = item.header_payload.clone();
 
-                    let platform = headers.x_client_platform.ok_or(
-                        errors::ConnectorError::MissingRequiredField {
-                            field_name: "x_client_platform",
-                        },
-                    )?;
+                    let platform = headers
+                        .as_ref()
+                        .and_then(|headers| headers.x_client_platform.clone());
 
                     let (is_android, is_ios) = match platform {
-                        common_enums::ClientPlatform::Android => (true, false),
-                        common_enums::ClientPlatform::Ios => (false, true),
+                        Some(common_enums::ClientPlatform::Android) => (true, false),
+                        Some(common_enums::ClientPlatform::Ios) => (false, true),
                         _ => (false, false),
                     };
 
@@ -208,20 +202,16 @@ impl TryFrom<&types::PaymentsPostProcessingRouterData> for PlaidLinkTokenRequest
                                 .ok_or(errors::ConnectorError::MissingConnectorTransactionID)?,
                         },
                         android_package_name: if is_android {
-                            Some(headers.x_app_id.ok_or(
-                                errors::ConnectorError::MissingRequiredField {
-                                    field_name: "x-app-id",
-                                },
-                            )?)
+                            headers
+                                .as_ref()
+                                .and_then(|headers| headers.x_app_id.clone())
                         } else {
                             None
                         },
                         redirect_uri: if is_ios {
-                            Some(headers.x_redirect_uri.ok_or(
-                                errors::ConnectorError::MissingRequiredField {
-                                    field_name: "x_redirect_uri",
-                                },
-                            )?)
+                            headers
+                                .as_ref()
+                                .and_then(|headers| headers.x_redirect_uri.clone())
                         } else {
                             None
                         },
diff --git a/crates/router/src/core/pm_auth.rs b/crates/router/src/core/pm_auth.rs
index a09ca4fc6e6..a37a91a55f1 100644
--- a/crates/router/src/core/pm_auth.rs
+++ b/crates/router/src/core/pm_auth.rs
@@ -51,6 +51,7 @@ pub async fn create_link_token(
     merchant_account: domain::MerchantAccount,
     key_store: domain::MerchantKeyStore,
     payload: api_models::pm_auth::LinkTokenCreateRequest,
+    headers: Option<api_models::payments::HeaderPayload>,
 ) -> RouterResponse<api_models::pm_auth::LinkTokenCreateResponse> {
     let db = &*state.store;
 
@@ -165,9 +166,13 @@ pub async fn create_link_token(
             )?]),
             language: payload.language,
             user_info: payment_intent.and_then(|pi| pi.customer_id),
-            client_platform: payload.client_platform,
-            android_package_name: payload.android_package_name,
-            redirect_uri: payload.redirect_uri,
+            client_platform: headers
+                .as_ref()
+                .and_then(|header| header.x_client_platform.clone()),
+            android_package_name: headers.as_ref().and_then(|header| header.x_app_id.clone()),
+            redirect_uri: headers
+                .as_ref()
+                .and_then(|header| header.x_redirect_uri.clone()),
         },
         response: Ok(pm_auth_types::LinkTokenResponse {
             link_token: "".to_string(),
@@ -211,6 +216,7 @@ pub async fn create_link_token(
     _merchant_account: domain::MerchantAccount,
     _key_store: domain::MerchantKeyStore,
     _payload: api_models::pm_auth::LinkTokenCreateRequest,
+    _headers: Option<api_models::payments::HeaderPayload>,
 ) -> RouterResponse<api_models::pm_auth::LinkTokenCreateResponse> {
     todo!()
 }
diff --git a/crates/router/src/routes/pm_auth.rs b/crates/router/src/routes/pm_auth.rs
index e0cce9c515c..cc0ab02b556 100644
--- a/crates/router/src/routes/pm_auth.rs
+++ b/crates/router/src/routes/pm_auth.rs
@@ -2,7 +2,9 @@ use actix_web::{web, HttpRequest, Responder};
 use api_models as api_types;
 use router_env::{instrument, tracing, types::Flow};
 
-use crate::{core::api_locking, routes::AppState, services::api as oss_api};
+use crate::{
+    core::api_locking, routes::AppState, services::api, types::transformers::ForeignTryFrom,
+};
 
 #[instrument(skip_all, fields(flow = ?Flow::PmAuthLinkTokenCreate))]
 pub async fn link_token_create(
@@ -17,9 +19,17 @@ pub async fn link_token_create(
         &payload,
     ) {
         Ok((auth, _auth_flow)) => (auth, _auth_flow),
-        Err(e) => return oss_api::log_and_return_error_response(e),
+        Err(e) => return api::log_and_return_error_response(e),
     };
-    Box::pin(oss_api::server_wrap(
+
+    let header_payload = match api_types::payments::HeaderPayload::foreign_try_from(req.headers()) {
+        Ok(headers) => headers,
+        Err(err) => {
+            return api::log_and_return_error_response(err);
+        }
+    };
+
+    Box::pin(api::server_wrap(
         flow,
         state,
         &req,
@@ -30,6 +40,7 @@ pub async fn link_token_create(
                 auth.merchant_account,
                 auth.key_store,
                 payload,
+                Some(header_payload.clone()),
             )
         },
         &*auth,
@@ -51,9 +62,9 @@ pub async fn exchange_token(
         &payload,
     ) {
         Ok((auth, _auth_flow)) => (auth, _auth_flow),
-        Err(e) => return oss_api::log_and_return_error_response(e),
+        Err(e) => return api::log_and_return_error_response(e),
     };
-    Box::pin(oss_api::server_wrap(
+    Box::pin(api::server_wrap(
         flow,
         state,
         &req,

## 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 -->
Make header data to consume in open banking flows as optional.


### 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)?
-->
Test all open banking flows (PM auth and Payment initiation)
Refer to this PR - https://github.com/juspay/hyperswitch/pull/3952

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