Bug: [FEATURE]: Add Session token flow for Paypal Sdk



### Feature Description

 Add Session token flow for Paypal Sdk

### Possible Implementation

- Accept data in `metadata` field of the MCA - create call
- Return that data in the sessions call
- Change payment_experience for paypal via paypal to sdk 

### 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/payments.rs b/crates/api_models/src/payments.rs
index f0ce3839fce..5f9618738b2 100644
--- a/crates/api_models/src/payments.rs
+++ b/crates/api_models/src/payments.rs
@@ -2939,13 +2939,17 @@ pub enum NextActionType {
 #[serde(tag = "type", rename_all = "snake_case")]
 pub enum NextActionData {
     /// Contains the url for redirection flow
-    RedirectToUrl { redirect_to_url: String },
+    RedirectToUrl {
+        redirect_to_url: String,
+    },
     /// Informs the next steps for bank transfer and also contains the charges details (ex: amount received, amount charged etc)
     DisplayBankTransferInformation {
         bank_transfer_steps_and_charges_details: BankTransferNextStepsData,
     },
     /// Contains third party sdk session token response
-    ThirdPartySdkSessionToken { session_token: Option<SessionToken> },
+    ThirdPartySdkSessionToken {
+        session_token: Option<SessionToken>,
+    },
     /// Contains url for Qr code image, this qr code has to be shown in sdk
     QrCodeInformation {
         #[schema(value_type = String)]
@@ -2967,7 +2971,12 @@ pub enum NextActionData {
         display_to_timestamp: Option<i128>,
     },
     /// Contains the information regarding three_ds_method_data submission, three_ds authentication, and authorization flows
-    ThreeDsInvoke { three_ds_data: ThreeDsData },
+    ThreeDsInvoke {
+        three_ds_data: ThreeDsData,
+    },
+    InvokeSdkClient {
+        next_action_data: SdkNextActionData,
+    },
 }
 
 #[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, ToSchema)]
@@ -3030,6 +3039,12 @@ pub enum QrCodeInformation {
     },
 }
 
+#[derive(Clone, Debug, serde::Serialize, serde::Deserialize, Eq, PartialEq, ToSchema)]
+#[serde(rename_all = "snake_case")]
+pub struct SdkNextActionData {
+    pub next_action: NextActionCall,
+}
+
 #[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, ToSchema)]
 pub struct BankTransferNextStepsData {
     /// The instructions for performing a bank transfer
@@ -4030,6 +4045,17 @@ pub struct GpaySessionTokenData {
     pub data: GpayMetaData,
 }
 
+#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
+pub struct PaypalSdkMetaData {
+    pub client_id: String,
+}
+
+#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
+pub struct PaypalSdkSessionTokenData {
+    #[serde(rename = "paypal_sdk")]
+    pub data: PaypalSdkMetaData,
+}
+
 #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
 #[serde(rename_all = "camelCase")]
 pub struct ApplepaySessionRequest {
@@ -4207,8 +4233,12 @@ pub struct KlarnaSessionTokenResponse {
 #[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, ToSchema)]
 #[serde(rename_all = "lowercase")]
 pub struct PaypalSessionTokenResponse {
+    /// Name of the connector
+    pub connector: String,
     /// The session token for PayPal
     pub session_token: String,
+    /// The next action for the sdk (ex: calling confirm or sync call)
+    pub sdk_next_action: SdkNextAction,
 }
 
 #[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, ToSchema)]
@@ -4238,13 +4268,15 @@ pub struct SdkNextAction {
     pub next_action: NextActionCall,
 }
 
-#[derive(Debug, Eq, PartialEq, serde::Serialize, Clone, ToSchema)]
+#[derive(Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, Clone, ToSchema)]
 #[serde(rename_all = "snake_case")]
 pub enum NextActionCall {
     /// The next action call is confirm
     Confirm,
     /// The next action call is sync
     Sync,
+    /// The next action call is Complete Authorize
+    CompleteAuthorize,
 }
 
 #[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, ToSchema)]
diff --git a/crates/connector_configs/src/common_config.rs b/crates/connector_configs/src/common_config.rs
index b11a74a3ca6..fff210b6e4d 100644
--- a/crates/connector_configs/src/common_config.rs
+++ b/crates/connector_configs/src/common_config.rs
@@ -54,6 +54,12 @@ pub enum GooglePayData {
     Zen(ZenGooglePay),
 }
 
+#[serde_with::skip_serializing_none]
+#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
+pub struct PaypalSdkData {
+    pub client_id: Option<String>,
+}
+
 #[serde_with::skip_serializing_none]
 #[derive(Debug, Deserialize, serde::Serialize, Clone)]
 #[serde(untagged)]
@@ -79,6 +85,7 @@ pub struct ApiModelMetaData {
     pub terminal_id: Option<String>,
     pub merchant_id: Option<String>,
     pub google_pay: Option<GoogleApiModelData>,
+    pub paypal_sdk: Option<PaypalSdkData>,
     pub apple_pay: Option<ApplePayData>,
     pub apple_pay_combined: Option<ApplePayData>,
     pub endpoint_prefix: Option<String>,
@@ -180,6 +187,7 @@ pub struct DashboardMetaData {
     pub terminal_id: Option<String>,
     pub merchant_id: Option<String>,
     pub google_pay: Option<GooglePayData>,
+    pub paypal_sdk: Option<PaypalSdkData>,
     pub apple_pay: Option<ApplePayData>,
     pub apple_pay_combined: Option<ApplePayData>,
     pub endpoint_prefix: Option<String>,
diff --git a/crates/connector_configs/src/connector.rs b/crates/connector_configs/src/connector.rs
index e1d55e39385..7118c87b092 100644
--- a/crates/connector_configs/src/connector.rs
+++ b/crates/connector_configs/src/connector.rs
@@ -10,7 +10,7 @@ use serde::Deserialize;
 #[cfg(any(feature = "sandbox", feature = "development", feature = "production"))]
 use toml;
 
-use crate::common_config::{CardProvider, GooglePayData, Provider, ZenApplePay};
+use crate::common_config::{CardProvider, GooglePayData, PaypalSdkData, Provider, ZenApplePay};
 
 #[derive(Default, Debug, Clone, serde::Serialize, serde::Deserialize)]
 pub struct Classic {
@@ -79,6 +79,7 @@ pub struct ConfigMetadata {
     pub account_name: Option<String>,
     pub terminal_id: Option<String>,
     pub google_pay: Option<GooglePayData>,
+    pub paypal_sdk: Option<PaypalSdkData>,
     pub apple_pay: Option<ApplePayTomlConfig>,
     pub merchant_id: Option<String>,
     pub endpoint_prefix: Option<String>,
diff --git a/crates/connector_configs/src/response_modifier.rs b/crates/connector_configs/src/response_modifier.rs
index 8f7da58c4dc..ebf97d83162 100644
--- a/crates/connector_configs/src/response_modifier.rs
+++ b/crates/connector_configs/src/response_modifier.rs
@@ -309,6 +309,7 @@ impl From<ApiModelMetaData> for DashboardMetaData {
             terminal_id: api_model.terminal_id,
             merchant_id: api_model.merchant_id,
             google_pay: get_google_pay_metadata_response(api_model.google_pay),
+            paypal_sdk: api_model.paypal_sdk,
             apple_pay: api_model.apple_pay,
             apple_pay_combined: api_model.apple_pay_combined,
             endpoint_prefix: api_model.endpoint_prefix,
diff --git a/crates/connector_configs/src/transformer.rs b/crates/connector_configs/src/transformer.rs
index 01332c9d29e..ae4b0206767 100644
--- a/crates/connector_configs/src/transformer.rs
+++ b/crates/connector_configs/src/transformer.rs
@@ -46,7 +46,9 @@ impl DashboardRequestPayload {
                 (Connector::Zen, GooglePay) | (Connector::Zen, ApplePay) => {
                     Some(api_models::enums::PaymentExperience::RedirectToUrl)
                 }
-                (Connector::Braintree, Paypal) | (Connector::Klarna, Klarna) => {
+                (Connector::Paypal, Paypal)
+                | (Connector::Braintree, Paypal)
+                | (Connector::Klarna, Klarna) => {
                     Some(api_models::enums::PaymentExperience::InvokeSdkClient)
                 }
                 (Connector::Globepay, AliPay)
@@ -194,6 +196,7 @@ impl DashboardRequestPayload {
             three_ds_requestor_name: None,
             three_ds_requestor_id: None,
             pull_mechanism_for_external_3ds_enabled: None,
+            paypal_sdk: None,
         };
         let meta_data = match request.metadata {
             Some(data) => data,
@@ -205,6 +208,7 @@ impl DashboardRequestPayload {
         let merchant_id = meta_data.merchant_id.clone();
         let terminal_id = meta_data.terminal_id.clone();
         let endpoint_prefix = meta_data.endpoint_prefix.clone();
+        let paypal_sdk = meta_data.paypal_sdk;
         let apple_pay = meta_data.apple_pay;
         let apple_pay_combined = meta_data.apple_pay_combined;
         let merchant_config_currency = meta_data.merchant_config_currency;
@@ -228,6 +232,7 @@ impl DashboardRequestPayload {
             merchant_config_currency,
             apple_pay_combined,
             endpoint_prefix,
+            paypal_sdk,
             mcc,
             merchant_country_code,
             merchant_name,
diff --git a/crates/connector_configs/toml/development.toml b/crates/connector_configs/toml/development.toml
index d9e7ec58f75..fcccf9c7e28 100644
--- a/crates/connector_configs/toml/development.toml
+++ b/crates/connector_configs/toml/development.toml
@@ -1645,6 +1645,8 @@ api_key="Client Secret"
 key1="Client ID"
 [paypal.connector_webhook_details]
 merchant_secret="Source verification key"
+[paypal.metadata.paypal_sdk]
+client_id="Client ID"
 
 [paypal_payout]
 [[paypal.wallet]]
diff --git a/crates/connector_configs/toml/production.toml b/crates/connector_configs/toml/production.toml
index 202bce64c1f..96fba850e7e 100644
--- a/crates/connector_configs/toml/production.toml
+++ b/crates/connector_configs/toml/production.toml
@@ -1265,6 +1265,8 @@ api_key="Client Secret"
 key1="Client ID"
 [paypal.connector_webhook_details]
 merchant_secret="Source verification key"
+[paypal.metadata.paypal_sdk]
+client_id="Client ID"
 
 [payu]
 [[payu.credit]]
diff --git a/crates/connector_configs/toml/sandbox.toml b/crates/connector_configs/toml/sandbox.toml
index 450e14d1080..932352f20e4 100644
--- a/crates/connector_configs/toml/sandbox.toml
+++ b/crates/connector_configs/toml/sandbox.toml
@@ -1645,6 +1645,8 @@ api_key="Client Secret"
 key1="Client ID"
 [paypal.connector_webhook_details]
 merchant_secret="Source verification key"
+[paypal.metadata.paypal_sdk]
+client_id="Client ID"
 
 [paypal_payout]
 [[paypal.wallet]]
diff --git a/crates/openapi/src/openapi.rs b/crates/openapi/src/openapi.rs
index 8830c689937..c67ea2d2746 100644
--- a/crates/openapi/src/openapi.rs
+++ b/crates/openapi/src/openapi.rs
@@ -367,6 +367,7 @@ Never share your secret api keys. Keep them guarded and secure.
         api_models::payments::ApplepaySessionTokenResponse,
         api_models::payments::SdkNextAction,
         api_models::payments::NextActionCall,
+        api_models::payments::SdkNextActionData,
         api_models::payments::SamsungPayWalletData,
         api_models::payments::WeChatPay,
         api_models::payments::GpayTokenizationData,
diff --git a/crates/router/src/compatibility/stripe/payment_intents/types.rs b/crates/router/src/compatibility/stripe/payment_intents/types.rs
index d615acff1ca..5e8c9ea08c0 100644
--- a/crates/router/src/compatibility/stripe/payment_intents/types.rs
+++ b/crates/router/src/compatibility/stripe/payment_intents/types.rs
@@ -823,6 +823,9 @@ pub enum StripeNextAction {
         display_from_timestamp: i128,
         display_to_timestamp: Option<i128>,
     },
+    InvokeSdkClient {
+        next_action_data: payments::SdkNextActionData,
+    },
 }
 
 pub(crate) fn into_stripe_next_action(
@@ -871,6 +874,9 @@ pub(crate) fn into_stripe_next_action(
                 url: None,
             },
         },
+        payments::NextActionData::InvokeSdkClient { next_action_data } => {
+            StripeNextAction::InvokeSdkClient { next_action_data }
+        }
     })
 }
 
diff --git a/crates/router/src/compatibility/stripe/setup_intents/types.rs b/crates/router/src/compatibility/stripe/setup_intents/types.rs
index 03335d42722..bbcafb65e9f 100644
--- a/crates/router/src/compatibility/stripe/setup_intents/types.rs
+++ b/crates/router/src/compatibility/stripe/setup_intents/types.rs
@@ -389,6 +389,9 @@ pub enum StripeNextAction {
         display_from_timestamp: i128,
         display_to_timestamp: Option<i128>,
     },
+    InvokeSdkClient {
+        next_action_data: payments::SdkNextActionData,
+    },
 }
 
 pub(crate) fn into_stripe_next_action(
@@ -437,6 +440,9 @@ pub(crate) fn into_stripe_next_action(
                 url: None,
             },
         },
+        payments::NextActionData::InvokeSdkClient { next_action_data } => {
+            StripeNextAction::InvokeSdkClient { next_action_data }
+        }
     })
 }
 
diff --git a/crates/router/src/configs/defaults.rs b/crates/router/src/configs/defaults.rs
index 1fe86a209e3..0405f318071 100644
--- a/crates/router/src/configs/defaults.rs
+++ b/crates/router/src/configs/defaults.rs
@@ -7914,6 +7914,170 @@ impl Default for super::settings::RequiredFields {
                             ]),
                         },
                     ),
+                    (
+                        // Added shipping fields for the SDK flow to accept it from wallet directly,
+                        // this won't show up in SDK in payment's sheet but will be used in the background
+                        enums::PaymentMethodType::Paypal,
+                        ConnectorFields {
+                            fields: HashMap::from([
+                                (
+                                    enums::Connector::Braintree,
+                                    RequiredFieldFinal {
+                                        mandate: HashMap::new(),
+                                        non_mandate: HashMap::new(),
+                                        common: HashMap::from([
+                                            (
+                                                "shipping.address.first_name".to_string(),
+                                                RequiredFieldInfo {
+                                                    required_field: "shipping.address.first_name".to_string(),
+                                                    display_name: "shipping_first_name".to_string(),
+                                                    field_type: enums::FieldType::UserShippingName,
+                                                    value: None,
+                                                }
+                                            ),
+                                            (
+                                                "shipping.address.last_name".to_string(),
+                                                RequiredFieldInfo {
+                                                    required_field: "shipping.address.last_name".to_string(),
+                                                    display_name: "shipping_last_name".to_string(),
+                                                    field_type: enums::FieldType::UserShippingName,
+                                                    value: None,
+                                                }
+                                            ),
+                                            (
+                                                "shipping.address.city".to_string(),
+                                                RequiredFieldInfo {
+                                                    required_field: "shipping.address.city".to_string(),
+                                                    display_name: "city".to_string(),
+                                                    field_type: enums::FieldType::UserShippingAddressCity,
+                                                    value: None,
+                                                }
+                                            ),
+                                            (
+                                                "shipping.address.state".to_string(),
+                                                RequiredFieldInfo {
+                                                    required_field: "shipping.address.state".to_string(),
+                                                    display_name: "state".to_string(),
+                                                    field_type: enums::FieldType::UserShippingAddressState,
+                                                    value: None,
+                                                }
+                                            ),
+                                            (
+                                                "shipping.address.zip".to_string(),
+                                                RequiredFieldInfo {
+                                                    required_field: "shipping.address.zip".to_string(),
+                                                    display_name: "zip".to_string(),
+                                                    field_type: enums::FieldType::UserShippingAddressPincode,
+                                                    value: None,
+                                                }
+                                            ),
+                                            (
+                                                "shipping.address.country".to_string(),
+                                                RequiredFieldInfo {
+                                                    required_field: "shipping.address.country".to_string(),
+                                                    display_name: "country".to_string(),
+                                                    field_type: enums::FieldType::UserShippingAddressCountry{
+                                                        options: vec![
+                                                            "ALL".to_string(),
+                                                        ]
+                                                    },
+                                                    value: None,
+                                                }
+                                            ),
+                                            (
+                                                "shipping.address.line1".to_string(),
+                                                RequiredFieldInfo {
+                                                    required_field: "shipping.address.line1".to_string(),
+                                                    display_name: "line1".to_string(),
+                                                    field_type: enums::FieldType::UserShippingAddressLine1,
+                                                    value: None,
+                                                }
+                                            ),
+                                        ]),
+                                    }
+                                ),
+                                (
+                                    enums::Connector::Paypal,
+                                    RequiredFieldFinal {
+                                        mandate: HashMap::new(),
+                                        non_mandate: HashMap::new(
+                                        ),
+                                        common: HashMap::from(
+                                            [
+                                                (
+                                                    "shipping.address.first_name".to_string(),
+                                                    RequiredFieldInfo {
+                                                        required_field: "shipping.address.first_name".to_string(),
+                                                        display_name: "shipping_first_name".to_string(),
+                                                        field_type: enums::FieldType::UserShippingName,
+                                                        value: None,
+                                                    }
+                                                ),
+                                                (
+                                                    "shipping.address.last_name".to_string(),
+                                                    RequiredFieldInfo {
+                                                        required_field: "shipping.address.last_name".to_string(),
+                                                        display_name: "shipping_last_name".to_string(),
+                                                        field_type: enums::FieldType::UserShippingName,
+                                                        value: None,
+                                                    }
+                                                ),
+                                                (
+                                                    "shipping.address.city".to_string(),
+                                                    RequiredFieldInfo {
+                                                        required_field: "shipping.address.city".to_string(),
+                                                        display_name: "city".to_string(),
+                                                        field_type: enums::FieldType::UserShippingAddressCity,
+                                                        value: None,
+                                                    }
+                                                ),
+                                                (
+                                                    "shipping.address.state".to_string(),
+                                                    RequiredFieldInfo {
+                                                        required_field: "shipping.address.state".to_string(),
+                                                        display_name: "state".to_string(),
+                                                        field_type: enums::FieldType::UserShippingAddressState,
+                                                        value: None,
+                                                    }
+                                                ),
+                                                (
+                                                    "shipping.address.zip".to_string(),
+                                                    RequiredFieldInfo {
+                                                        required_field: "shipping.address.zip".to_string(),
+                                                        display_name: "zip".to_string(),
+                                                        field_type: enums::FieldType::UserShippingAddressPincode,
+                                                        value: None,
+                                                    }
+                                                ),
+                                                (
+                                                    "shipping.address.country".to_string(),
+                                                    RequiredFieldInfo {
+                                                        required_field: "shipping.address.country".to_string(),
+                                                        display_name: "country".to_string(),
+                                                        field_type: enums::FieldType::UserShippingAddressCountry{
+                                                            options: vec![
+                                                                "ALL".to_string(),
+                                                            ]
+                                                        },
+                                                        value: None,
+                                                    }
+                                                ),
+                                                (
+                                                    "shipping.address.line1".to_string(),
+                                                    RequiredFieldInfo {
+                                                        required_field: "shipping.address.line1".to_string(),
+                                                        display_name: "line1".to_string(),
+                                                        field_type: enums::FieldType::UserShippingAddressLine1,
+                                                        value: None,
+                                                    }
+                                                ),
+                                            ]
+                                        ),
+                                    }
+                                ),
+                               ]),
+                        },
+                    ),
                 ])),
             ),
             (
diff --git a/crates/router/src/connector/braintree/transformers.rs b/crates/router/src/connector/braintree/transformers.rs
index a939f0a83f7..136782cab6e 100644
--- a/crates/router/src/connector/braintree/transformers.rs
+++ b/crates/router/src/connector/braintree/transformers.rs
@@ -308,6 +308,10 @@ impl<F, T>
                 session_token: api::SessionToken::Paypal(Box::new(
                     payments::PaypalSessionTokenResponse {
                         session_token: item.response.client_token.value.expose(),
+                        connector: "braintree".to_string(),
+                        sdk_next_action: payments::SdkNextAction {
+                            next_action: payments::NextActionCall::Confirm,
+                        },
                     },
                 )),
             }),
diff --git a/crates/router/src/connector/paypal.rs b/crates/router/src/connector/paypal.rs
index 9ff6b84a064..9e7b208ef70 100644
--- a/crates/router/src/connector/paypal.rs
+++ b/crates/router/src/connector/paypal.rs
@@ -34,7 +34,7 @@ use crate::{
         self,
         api::{self, CompleteAuthorize, ConnectorCommon, ConnectorCommonExt, VerifyWebhookSource},
         storage::enums as storage_enums,
-        transformers::ForeignFrom,
+        transformers::{ForeignFrom, ForeignTryFrom},
         ConnectorAuthType, ErrorResponse, Response,
     },
     utils::BytesExt,
@@ -629,7 +629,7 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
             res.response
                 .parse_struct("paypal PaypalAuthResponse")
                 .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
-
+        let payment_method_data = data.request.payment_method_data.clone();
         match response {
             PaypalAuthResponse::PaypalOrdersResponse(response) => {
                 event_builder.map(|i| i.set_response_body(&response));
@@ -644,11 +644,14 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
             PaypalAuthResponse::PaypalRedirectResponse(response) => {
                 event_builder.map(|i| i.set_response_body(&response));
                 router_env::logger::info!(connector_response=?response);
-                types::RouterData::try_from(types::ResponseRouterData {
-                    response,
-                    data: data.clone(),
-                    http_code: res.status_code,
-                })
+                types::RouterData::foreign_try_from((
+                    types::ResponseRouterData {
+                        response,
+                        data: data.clone(),
+                        http_code: res.status_code,
+                    },
+                    payment_method_data,
+                ))
             }
             PaypalAuthResponse::PaypalThreeDsResponse(response) => {
                 event_builder.map(|i| i.set_response_body(&response));
@@ -1033,11 +1036,14 @@ impl ConnectorIntegration<api::PSync, types::PaymentsSyncData, types::PaymentsRe
             .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
         event_builder.map(|i| i.set_response_body(&response));
         router_env::logger::info!(connector_response=?response);
-        types::RouterData::try_from(types::ResponseRouterData {
-            response,
-            data: data.clone(),
-            http_code: res.status_code,
-        })
+        types::RouterData::foreign_try_from((
+            types::ResponseRouterData {
+                response,
+                data: data.clone(),
+                http_code: res.status_code,
+            },
+            data.request.payment_experience,
+        ))
     }
 
     fn get_error_response(
diff --git a/crates/router/src/connector/paypal/transformers.rs b/crates/router/src/connector/paypal/transformers.rs
index 0ea1331c448..d240c1b05e0 100644
--- a/crates/router/src/connector/paypal/transformers.rs
+++ b/crates/router/src/connector/paypal/transformers.rs
@@ -18,7 +18,9 @@ use crate::{
     core::errors,
     services,
     types::{
-        self, api, domain, storage::enums as storage_enums, transformers::ForeignFrom,
+        self, api, domain,
+        storage::enums as storage_enums,
+        transformers::{ForeignFrom, ForeignTryFrom},
         ConnectorAuthType, VerifyWebhookSourceResponseData,
     },
 };
@@ -387,28 +389,33 @@ impl TryFrom<&PaypalRouterData<&types::PaymentsAuthorizeRouterData>> for PaypalP
         let paypal_auth: PaypalAuthType =
             PaypalAuthType::try_from(&item.router_data.connector_auth_type)?;
         let payee = get_payee(&paypal_auth);
+
+        let amount = OrderRequestAmount::from(item);
+
+        let intent = if item.router_data.request.is_auto_capture()? {
+            PaypalPaymentIntent::Capture
+        } else {
+            PaypalPaymentIntent::Authorize
+        };
+
+        let connector_request_reference_id =
+            item.router_data.connector_request_reference_id.clone();
+
+        let shipping_address = ShippingAddress::try_from(item)?;
+        let item_details = vec![ItemDetails::from(item)];
+
+        let purchase_units = vec![PurchaseUnitRequest {
+            reference_id: Some(connector_request_reference_id.clone()),
+            custom_id: Some(connector_request_reference_id.clone()),
+            invoice_id: Some(connector_request_reference_id),
+            amount,
+            payee,
+            shipping: Some(shipping_address),
+            items: item_details,
+        }];
+
         match item.router_data.request.payment_method_data {
             domain::PaymentMethodData::Card(ref ccard) => {
-                let intent = if item.router_data.request.is_auto_capture()? {
-                    PaypalPaymentIntent::Capture
-                } else {
-                    PaypalPaymentIntent::Authorize
-                };
-                let amount = OrderRequestAmount::from(item);
-                let connector_request_reference_id =
-                    item.router_data.connector_request_reference_id.clone();
-                let shipping_address = ShippingAddress::try_from(item)?;
-                let item_details = vec![ItemDetails::from(item)];
-
-                let purchase_units = vec![PurchaseUnitRequest {
-                    reference_id: Some(connector_request_reference_id.clone()),
-                    custom_id: Some(connector_request_reference_id.clone()),
-                    invoice_id: Some(connector_request_reference_id),
-                    amount,
-                    payee,
-                    shipping: Some(shipping_address),
-                    items: item_details,
-                }];
                 let card = item.router_data.request.get_card()?;
                 let expiry = Some(card.get_expiry_date_as_yyyymm("-"));
 
@@ -441,27 +448,6 @@ impl TryFrom<&PaypalRouterData<&types::PaymentsAuthorizeRouterData>> for PaypalP
             }
             domain::PaymentMethodData::Wallet(ref wallet_data) => match wallet_data {
                 domain::WalletData::PaypalRedirect(_) => {
-                    let intent = if item.router_data.request.is_auto_capture()? {
-                        PaypalPaymentIntent::Capture
-                    } else {
-                        PaypalPaymentIntent::Authorize
-                    };
-                    let amount = OrderRequestAmount::from(item);
-
-                    let connector_req_reference_id =
-                        item.router_data.connector_request_reference_id.clone();
-                    let shipping_address = ShippingAddress::try_from(item)?;
-                    let item_details = vec![ItemDetails::from(item)];
-
-                    let purchase_units = vec![PurchaseUnitRequest {
-                        reference_id: Some(connector_req_reference_id.clone()),
-                        custom_id: Some(connector_req_reference_id.clone()),
-                        invoice_id: Some(connector_req_reference_id),
-                        amount,
-                        payee,
-                        shipping: Some(shipping_address),
-                        items: item_details,
-                    }];
                     let payment_source =
                         Some(PaymentSourceItem::Paypal(PaypalRedirectionRequest {
                             experience_context: ContextStruct {
@@ -486,6 +472,23 @@ impl TryFrom<&PaypalRouterData<&types::PaymentsAuthorizeRouterData>> for PaypalP
                         payment_source,
                     })
                 }
+                domain::WalletData::PaypalSdk(_) => {
+                    let payment_source =
+                        Some(PaymentSourceItem::Paypal(PaypalRedirectionRequest {
+                            experience_context: ContextStruct {
+                                return_url: None,
+                                cancel_url: None,
+                                shipping_preference: ShippingPreference::GetFromFile,
+                                user_action: Some(UserAction::PayNow),
+                            },
+                        }));
+
+                    Ok(Self {
+                        intent,
+                        purchase_units,
+                        payment_source,
+                    })
+                }
                 domain::WalletData::AliPayQr(_)
                 | domain::WalletData::AliPayRedirect(_)
                 | domain::WalletData::AliPayHkRedirect(_)
@@ -502,7 +505,6 @@ impl TryFrom<&PaypalRouterData<&types::PaymentsAuthorizeRouterData>> for PaypalP
                 | domain::WalletData::GooglePayThirdPartySdk(_)
                 | domain::WalletData::MbWayRedirect(_)
                 | domain::WalletData::MobilePayRedirect(_)
-                | domain::WalletData::PaypalSdk(_)
                 | domain::WalletData::SamsungPay(_)
                 | domain::WalletData::TwintRedirect {}
                 | domain::WalletData::VippsRedirect {}
@@ -515,7 +517,7 @@ impl TryFrom<&PaypalRouterData<&types::PaymentsAuthorizeRouterData>> for PaypalP
                 ))?,
             },
             domain::PaymentMethodData::BankRedirect(ref bank_redirection_data) => {
-                let intent = if item.router_data.request.is_auto_capture()? {
+                let bank_redirect_intent = if item.router_data.request.is_auto_capture()? {
                     PaypalPaymentIntent::Capture
                 } else {
                     Err(errors::ConnectorError::FlowNotSupported {
@@ -523,26 +525,12 @@ impl TryFrom<&PaypalRouterData<&types::PaymentsAuthorizeRouterData>> for PaypalP
                         connector: "Paypal".to_string(),
                     })?
                 };
-                let amount = OrderRequestAmount::from(item);
-                let connector_req_reference_id =
-                    item.router_data.connector_request_reference_id.clone();
-                let shipping_address = ShippingAddress::try_from(item)?;
-                let item_details = vec![ItemDetails::from(item)];
-
-                let purchase_units = vec![PurchaseUnitRequest {
-                    reference_id: Some(connector_req_reference_id.clone()),
-                    custom_id: Some(connector_req_reference_id.clone()),
-                    invoice_id: Some(connector_req_reference_id),
-                    amount,
-                    payee,
-                    shipping: Some(shipping_address),
-                    items: item_details,
-                }];
+
                 let payment_source =
                     Some(get_payment_source(item.router_data, bank_redirection_data)?);
 
                 Ok(Self {
-                    intent,
+                    intent: bank_redirect_intent,
                     purchase_units,
                     payment_source,
                 })
@@ -1060,6 +1048,7 @@ pub struct PaypalMeta {
     pub authorize_id: Option<String>,
     pub capture_id: Option<String>,
     pub psync_flow: PaypalPaymentIntent,
+    pub next_action: Option<api_models::payments::NextActionCall>,
 }
 
 fn get_id_based_on_intent(
@@ -1112,7 +1101,8 @@ impl<F, T>
                 serde_json::json!(PaypalMeta {
                     authorize_id: None,
                     capture_id: Some(id),
-                    psync_flow: item.response.intent.clone()
+                    psync_flow: item.response.intent.clone(),
+                    next_action: None,
                 }),
                 types::ResponseId::ConnectorTransactionId(item.response.id.clone()),
             ),
@@ -1121,7 +1111,8 @@ impl<F, T>
                 serde_json::json!(PaypalMeta {
                     authorize_id: Some(id),
                     capture_id: None,
-                    psync_flow: item.response.intent.clone()
+                    psync_flow: item.response.intent.clone(),
+                    next_action: None,
                 }),
                 types::ResponseId::ConnectorTransactionId(item.response.id.clone()),
             ),
@@ -1183,23 +1174,27 @@ fn get_redirect_url(
 }
 
 impl<F>
-    TryFrom<
+    ForeignTryFrom<(
         types::ResponseRouterData<
             F,
             PaypalSyncResponse,
             types::PaymentsSyncData,
             types::PaymentsResponseData,
         >,
-    > for types::RouterData<F, types::PaymentsSyncData, types::PaymentsResponseData>
+        Option<common_enums::PaymentExperience>,
+    )> for types::RouterData<F, types::PaymentsSyncData, types::PaymentsResponseData>
 {
     type Error = error_stack::Report<errors::ConnectorError>;
-    fn try_from(
-        item: types::ResponseRouterData<
-            F,
-            PaypalSyncResponse,
-            types::PaymentsSyncData,
-            types::PaymentsResponseData,
-        >,
+    fn foreign_try_from(
+        (item, payment_experience): (
+            types::ResponseRouterData<
+                F,
+                PaypalSyncResponse,
+                types::PaymentsSyncData,
+                types::PaymentsResponseData,
+            >,
+            Option<common_enums::PaymentExperience>,
+        ),
     ) -> Result<Self, Self::Error> {
         match item.response {
             PaypalSyncResponse::PaypalOrdersSyncResponse(response) => {
@@ -1209,13 +1204,14 @@ impl<F>
                     http_code: item.http_code,
                 })
             }
-            PaypalSyncResponse::PaypalRedirectSyncResponse(response) => {
-                Self::try_from(types::ResponseRouterData {
+            PaypalSyncResponse::PaypalRedirectSyncResponse(response) => Self::foreign_try_from((
+                types::ResponseRouterData {
                     response,
                     data: item.data,
                     http_code: item.http_code,
-                })
-            }
+                },
+                payment_experience,
+            )),
             PaypalSyncResponse::PaypalPaymentsSyncResponse(response) => {
                 Self::try_from(types::ResponseRouterData {
                     response,
@@ -1235,25 +1231,96 @@ impl<F>
 }
 
 impl<F, T>
-    TryFrom<types::ResponseRouterData<F, PaypalRedirectResponse, T, types::PaymentsResponseData>>
-    for types::RouterData<F, T, types::PaymentsResponseData>
+    ForeignTryFrom<(
+        types::ResponseRouterData<F, PaypalRedirectResponse, T, types::PaymentsResponseData>,
+        Option<common_enums::PaymentExperience>,
+    )> for types::RouterData<F, T, types::PaymentsResponseData>
 {
     type Error = error_stack::Report<errors::ConnectorError>;
-    fn try_from(
-        item: types::ResponseRouterData<F, PaypalRedirectResponse, T, types::PaymentsResponseData>,
+    fn foreign_try_from(
+        (item, payment_experience): (
+            types::ResponseRouterData<F, PaypalRedirectResponse, T, types::PaymentsResponseData>,
+            Option<common_enums::PaymentExperience>,
+        ),
     ) -> Result<Self, Self::Error> {
         let status = storage_enums::AttemptStatus::foreign_from((
             item.response.clone().status,
             item.response.intent.clone(),
         ));
         let link = get_redirect_url(item.response.links.clone())?;
+
+        // For Paypal SDK flow, we need to trigger SDK client and then complete authorize
+        let next_action =
+            if let Some(common_enums::PaymentExperience::InvokeSdkClient) = payment_experience {
+                Some(api_models::payments::NextActionCall::CompleteAuthorize)
+            } else {
+                None
+            };
         let connector_meta = serde_json::json!(PaypalMeta {
             authorize_id: None,
             capture_id: None,
-            psync_flow: item.response.intent
+            psync_flow: item.response.intent,
+            next_action,
         });
         let purchase_units = item.response.purchase_units.first();
+        Ok(Self {
+            status,
+            response: Ok(types::PaymentsResponseData::TransactionResponse {
+                resource_id: types::ResponseId::ConnectorTransactionId(item.response.id.clone()),
+                redirection_data: Some(services::RedirectForm::from((
+                    link.ok_or(errors::ConnectorError::ResponseDeserializationFailed)?,
+                    services::Method::Get,
+                ))),
+                mandate_reference: None,
+                connector_metadata: Some(connector_meta),
+                network_txn_id: None,
+                connector_response_reference_id: Some(
+                    purchase_units.map_or(item.response.id, |item| item.invoice_id.clone()),
+                ),
+                incremental_authorization_allowed: None,
+                charge_id: None,
+            }),
+            ..item.data
+        })
+    }
+}
 
+impl<F, T>
+    ForeignTryFrom<(
+        types::ResponseRouterData<F, PaypalRedirectResponse, T, types::PaymentsResponseData>,
+        domain::PaymentMethodData,
+    )> for types::RouterData<F, T, types::PaymentsResponseData>
+{
+    type Error = error_stack::Report<errors::ConnectorError>;
+    fn foreign_try_from(
+        (item, payment_method_data): (
+            types::ResponseRouterData<F, PaypalRedirectResponse, T, types::PaymentsResponseData>,
+            domain::PaymentMethodData,
+        ),
+    ) -> Result<Self, Self::Error> {
+        let status = storage_enums::AttemptStatus::foreign_from((
+            item.response.clone().status,
+            item.response.intent.clone(),
+        ));
+        let link = get_redirect_url(item.response.links.clone())?;
+
+        // For Paypal SDK flow, we need to trigger SDK client and then complete authorize
+        let next_action =
+            if let domain::PaymentMethodData::Wallet(domain::WalletData::PaypalSdk(_)) =
+                payment_method_data
+            {
+                Some(api_models::payments::NextActionCall::CompleteAuthorize)
+            } else {
+                None
+            };
+
+        let connector_meta = serde_json::json!(PaypalMeta {
+            authorize_id: None,
+            capture_id: None,
+            psync_flow: item.response.intent,
+            next_action,
+        });
+        let purchase_units = item.response.purchase_units.first();
         Ok(Self {
             status,
             response: Ok(types::PaymentsResponseData::TransactionResponse {
@@ -1336,7 +1403,8 @@ impl<F>
         let connector_meta = serde_json::json!(PaypalMeta {
             authorize_id: None,
             capture_id: None,
-            psync_flow: PaypalPaymentIntent::Authenticate // when there is no capture or auth id present
+            psync_flow: PaypalPaymentIntent::Authenticate, // when there is no capture or auth id present
+            next_action: None,
         });
 
         let status = storage_enums::AttemptStatus::foreign_from((
@@ -1755,7 +1823,8 @@ impl TryFrom<types::PaymentsCaptureResponseRouterData<PaypalCaptureResponse>>
                 connector_metadata: Some(serde_json::json!(PaypalMeta {
                     authorize_id: connector_payment_id.authorize_id,
                     capture_id: Some(item.response.id.clone()),
-                    psync_flow: PaypalPaymentIntent::Capture
+                    psync_flow: PaypalPaymentIntent::Capture,
+                    next_action: None,
                 })),
                 network_txn_id: None,
                 connector_response_reference_id: item
diff --git a/crates/router/src/core/payments.rs b/crates/router/src/core/payments.rs
index f760e907288..a39f0deb3ca 100644
--- a/crates/router/src/core/payments.rs
+++ b/crates/router/src/core/payments.rs
@@ -1012,6 +1012,7 @@ impl PaymentRedirectFlow for PaymentRedirectCompleteAuthorize {
                         api_models::payments::NextActionData::DisplayVoucherInformation{ .. } => None,
                         api_models::payments::NextActionData::WaitScreenInformation{..} => None,
                         api_models::payments::NextActionData::ThreeDsInvoke{..} => None,
+                        api_models::payments::NextActionData::InvokeSdkClient{..} => None,
                     })
                     .ok_or(errors::ApiErrorResponse::InternalServerError)
 
diff --git a/crates/router/src/core/payments/flows/session_flow.rs b/crates/router/src/core/payments/flows/session_flow.rs
index 76ff96c7021..c74ed4bae15 100644
--- a/crates/router/src/core/payments/flows/session_flow.rs
+++ b/crates/router/src/core/payments/flows/session_flow.rs
@@ -634,6 +634,42 @@ where
     ) -> RouterResult<Self>;
 }
 
+fn create_paypal_sdk_session_token(
+    _state: &routes::AppState,
+    router_data: &types::PaymentsSessionRouterData,
+    connector: &api::ConnectorData,
+    _business_profile: &storage::business_profile::BusinessProfile,
+) -> RouterResult<types::PaymentsSessionRouterData> {
+    let connector_metadata = router_data.connector_meta_data.clone();
+
+    let paypal_sdk_data = connector_metadata
+        .clone()
+        .parse_value::<payment_types::PaypalSdkSessionTokenData>("PaypalSdkSessionTokenData")
+        .change_context(errors::ConnectorError::NoConnectorMetaData)
+        .attach_printable(format!(
+            "cannot parse paypal_sdk metadata from the given value {connector_metadata:?}"
+        ))
+        .change_context(errors::ApiErrorResponse::InvalidDataFormat {
+            field_name: "connector_metadata".to_string(),
+            expected_format: "paypal_sdk_metadata_format".to_string(),
+        })?;
+
+    Ok(types::PaymentsSessionRouterData {
+        response: Ok(types::PaymentsResponseData::SessionResponse {
+            session_token: payment_types::SessionToken::Paypal(Box::new(
+                payment_types::PaypalSessionTokenResponse {
+                    connector: connector.connector_name.to_string(),
+                    session_token: paypal_sdk_data.data.client_id,
+                    sdk_next_action: payment_types::SdkNextAction {
+                        next_action: payment_types::NextActionCall::Confirm,
+                    },
+                },
+            )),
+        }),
+        ..router_data.clone()
+    })
+}
+
 #[async_trait]
 impl RouterDataSession for types::PaymentsSessionRouterData {
     async fn decide_flow<'a, 'b>(
@@ -651,6 +687,9 @@ impl RouterDataSession for types::PaymentsSessionRouterData {
             api::GetToken::ApplePayMetadata => {
                 create_applepay_session_token(state, self, connector, business_profile).await
             }
+            api::GetToken::PaypalSdkMetadata => {
+                create_paypal_sdk_session_token(state, self, connector, business_profile)
+            }
             api::GetToken::Connector => {
                 let connector_integration: services::BoxedConnectorIntegration<
                     '_,
diff --git a/crates/router/src/core/payments/operations/payment_session.rs b/crates/router/src/core/payments/operations/payment_session.rs
index e4d91d4a068..2aa01cd587f 100644
--- a/crates/router/src/core/payments/operations/payment_session.rs
+++ b/crates/router/src/core/payments/operations/payment_session.rs
@@ -471,6 +471,7 @@ impl From<api_models::enums::PaymentMethodType> for api::GetToken {
         match value {
             api_models::enums::PaymentMethodType::GooglePay => Self::GpayMetadata,
             api_models::enums::PaymentMethodType::ApplePay => Self::ApplePayMetadata,
+            api_models::enums::PaymentMethodType::Paypal => Self::PaypalSdkMetadata,
             _ => Self::Connector,
         }
     }
diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs
index 11ce9cd7ede..7f6b0cc1f61 100644
--- a/crates/router/src/core/payments/transformers.rs
+++ b/crates/router/src/core/payments/transformers.rs
@@ -539,6 +539,8 @@ where
 
         let next_action_containing_qr_code_url = qr_code_next_steps_check(payment_attempt.clone())?;
 
+        let papal_sdk_next_action = paypal_sdk_next_steps_check(payment_attempt.clone())?;
+
         let next_action_containing_wait_screen =
             wait_screen_next_steps_check(payment_attempt.clone())?;
 
@@ -547,6 +549,7 @@ where
             || next_action_voucher.is_some()
             || next_action_containing_qr_code_url.is_some()
             || next_action_containing_wait_screen.is_some()
+            || papal_sdk_next_action.is_some()
             || payment_data.authentication.is_some()
         {
             next_action_response = bank_transfer_next_steps
@@ -563,6 +566,11 @@ where
                         .or(next_action_containing_qr_code_url.map(|qr_code_data| {
                             api_models::payments::NextActionData::foreign_from(qr_code_data)
                         }))
+                        .or(papal_sdk_next_action.map(|paypal_next_action_data| {
+                            api_models::payments::NextActionData::InvokeSdkClient{
+                                next_action_data: paypal_next_action_data
+                            }
+                        }))
                         .or(next_action_containing_wait_screen.map(|wait_screen_data| {
                             api_models::payments::NextActionData::WaitScreenInformation {
                                 display_from_timestamp: wait_screen_data.display_from_timestamp,
@@ -875,6 +883,21 @@ pub fn qr_code_next_steps_check(
     let qr_code_instructions = qr_code_steps.transpose().ok().flatten();
     Ok(qr_code_instructions)
 }
+pub fn paypal_sdk_next_steps_check(
+    payment_attempt: storage::PaymentAttempt,
+) -> RouterResult<Option<api_models::payments::SdkNextActionData>> {
+    let paypal_connector_metadata: Option<Result<api_models::payments::SdkNextActionData, _>> =
+        payment_attempt.connector_metadata.map(|metadata| {
+            metadata.parse_value("SdkNextActionData").map_err(|_| {
+                crate::logger::warn!(
+                    "SdkNextActionData parsing failed for paypal_connector_metadata"
+                )
+            })
+        });
+
+    let paypal_next_steps = paypal_connector_metadata.transpose().ok().flatten();
+    Ok(paypal_next_steps)
+}
 
 pub fn wait_screen_next_steps_check(
     payment_attempt: storage::PaymentAttempt,
@@ -1275,6 +1298,7 @@ impl<F: Clone> TryFrom<PaymentAdditionalData<'_, F>> for types::PaymentsSyncData
             },
             payment_method_type: payment_data.payment_attempt.payment_method_type,
             currency: payment_data.currency,
+            payment_experience: payment_data.payment_attempt.payment_experience,
         })
     }
 }
diff --git a/crates/router/src/types.rs b/crates/router/src/types.rs
index e2f2f6c0b70..89c2629c105 100644
--- a/crates/router/src/types.rs
+++ b/crates/router/src/types.rs
@@ -466,6 +466,7 @@ pub struct PaymentsSyncData {
     pub mandate_id: Option<api_models::payments::MandateIds>,
     pub payment_method_type: Option<storage_enums::PaymentMethodType>,
     pub currency: storage_enums::Currency,
+    pub payment_experience: Option<storage_enums::PaymentExperience>,
 }
 
 #[derive(Debug, Default, Clone)]
diff --git a/crates/router/src/types/api.rs b/crates/router/src/types/api.rs
index 2013f482750..aea5e326cf7 100644
--- a/crates/router/src/types/api.rs
+++ b/crates/router/src/types/api.rs
@@ -217,6 +217,7 @@ type BoxedConnector = Box<&'static (dyn Connector + Sync)>;
 pub enum GetToken {
     GpayMetadata,
     ApplePayMetadata,
+    PaypalSdkMetadata,
     Connector,
 }
 
diff --git a/crates/router/tests/connectors/bambora.rs b/crates/router/tests/connectors/bambora.rs
index 3115c1143d7..d0bc77e7500 100644
--- a/crates/router/tests/connectors/bambora.rs
+++ b/crates/router/tests/connectors/bambora.rs
@@ -110,6 +110,7 @@ async fn should_sync_authorized_payment() {
                 connector_meta: None,
                 payment_method_type: None,
                 currency: enums::Currency::USD,
+                payment_experience: None,
             }),
             None,
         )
@@ -226,6 +227,7 @@ async fn should_sync_auto_captured_payment() {
                 connector_meta: None,
                 payment_method_type: None,
                 currency: enums::Currency::USD,
+                payment_experience: None,
             }),
             None,
         )
diff --git a/crates/router/tests/connectors/forte.rs b/crates/router/tests/connectors/forte.rs
index d690524bd12..11153aa7088 100644
--- a/crates/router/tests/connectors/forte.rs
+++ b/crates/router/tests/connectors/forte.rs
@@ -159,6 +159,7 @@ async fn should_sync_authorized_payment() {
                 mandate_id: None,
                 payment_method_type: None,
                 currency: enums::Currency::USD,
+                payment_experience: None,
             }),
             get_default_payment_info(),
         )
diff --git a/crates/router/tests/connectors/nexinets.rs b/crates/router/tests/connectors/nexinets.rs
index cdf94113c5a..c6a14ac202f 100644
--- a/crates/router/tests/connectors/nexinets.rs
+++ b/crates/router/tests/connectors/nexinets.rs
@@ -126,6 +126,7 @@ async fn should_sync_authorized_payment() {
                 mandate_id: None,
                 payment_method_type: None,
                 currency: enums::Currency::EUR,
+                payment_experience: None,
             }),
             None,
         )
diff --git a/crates/router/tests/connectors/paypal.rs b/crates/router/tests/connectors/paypal.rs
index 704aeca5936..b53cf71acfd 100644
--- a/crates/router/tests/connectors/paypal.rs
+++ b/crates/router/tests/connectors/paypal.rs
@@ -143,6 +143,7 @@ async fn should_sync_authorized_payment() {
                 connector_meta,
                 payment_method_type: None,
                 currency: enums::Currency::USD,
+                payment_experience: None,
             }),
             get_default_payment_info(),
         )
@@ -341,6 +342,7 @@ async fn should_sync_auto_captured_payment() {
                 connector_meta,
                 payment_method_type: None,
                 currency: enums::Currency::USD,
+                payment_experience: None,
             }),
             get_default_payment_info(),
         )
diff --git a/crates/router/tests/connectors/utils.rs b/crates/router/tests/connectors/utils.rs
index 6718611b0c8..9955cb77df7 100644
--- a/crates/router/tests/connectors/utils.rs
+++ b/crates/router/tests/connectors/utils.rs
@@ -1002,6 +1002,7 @@ impl Default for PaymentSyncType {
             connector_meta: None,
             payment_method_type: None,
             currency: enums::Currency::USD,
+            payment_experience: None,
         };
         Self(data)
     }
diff --git a/crates/router/tests/connectors/zen.rs b/crates/router/tests/connectors/zen.rs
index b11b78025d0..552edcaaf6f 100644
--- a/crates/router/tests/connectors/zen.rs
+++ b/crates/router/tests/connectors/zen.rs
@@ -105,6 +105,7 @@ async fn should_sync_authorized_payment() {
                 mandate_id: None,
                 payment_method_type: None,
                 currency: enums::Currency::USD,
+                payment_experience: None,
             }),
             None,
         )
@@ -221,6 +222,7 @@ async fn should_sync_auto_captured_payment() {
                 mandate_id: None,
                 payment_method_type: None,
                 currency: enums::Currency::USD,
+                payment_experience: None,
             }),
             None,
         )
diff --git a/openapi/openapi_spec.json b/openapi/openapi_spec.json
index 47da1ae1074..b87b516de28 100644
--- a/openapi/openapi_spec.json
+++ b/openapi/openapi_spec.json
@@ -11660,7 +11660,8 @@
         "type": "string",
         "enum": [
           "confirm",
-          "sync"
+          "sync",
+          "complete_authorize"
         ]
       },
       "NextActionData": {
@@ -11816,6 +11817,24 @@
                 ]
               }
             }
+          },
+          {
+            "type": "object",
+            "required": [
+              "next_action_data",
+              "type"
+            ],
+            "properties": {
+              "next_action_data": {
+                "$ref": "#/components/schemas/SdkNextActionData"
+              },
+              "type": {
+                "type": "string",
+                "enum": [
+                  "invoke_sdk_client"
+                ]
+              }
+            }
           }
         ],
         "discriminator": {
@@ -16780,12 +16799,21 @@
       "PaypalSessionTokenResponse": {
         "type": "object",
         "required": [
-          "session_token"
+          "connector",
+          "session_token",
+          "sdk_next_action"
         ],
         "properties": {
+          "connector": {
+            "type": "string",
+            "description": "Name of the connector"
+          },
           "session_token": {
             "type": "string",
             "description": "The session token for PayPal"
+          },
+          "sdk_next_action": {
+            "$ref": "#/components/schemas/SdkNextAction"
           }
         }
       },
@@ -18030,6 +18058,17 @@
           }
         }
       },
+      "SdkNextActionData": {
+        "type": "object",
+        "required": [
+          "next_action"
+        ],
+        "properties": {
+          "next_action": {
+            "$ref": "#/components/schemas/NextActionCall"
+          }
+        }
+      },
       "SecretInfoToInitiateSdk": {
         "type": "object",
         "required": [

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

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

## Description
<!-- Describe your changes in detail -->
Add session_token flow to enable Paypal via Paypal SDK

- Accept data in `metadata` field of the MCA - create call
- Return that data in the sessions call
- Change payment_experience for paypal via paypal to sdk 

### Additional Changes

- [x] 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).
-->
#4698 

## 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 Paypal MCA with payment_experience as `invoke_sdk_client` for Paypal Wallet
```
curl --location 'http://localhost:8080/account/merchant_1716757295/connectors' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: test_admin' \
--data '{
    "connector_type": "fiz_operations",
    "business_country": "US",
    
    "connector_name": "paypal",
    "connector_account_details": {
        "auth_type": "BodyKey",
        "api_key": "********************************",
        "key1": "ASK*****************************_2"
    },
    "test_mode": true,
    "disabled": false,
"payment_methods_enabled": [
        {
            "payment_method": "card",
            "payment_method_types": [
                {
                    "payment_method_type": "credit",
                    "payment_experience": null,
                    "card_networks": [
                        "Visa",
                        "Mastercard"
                    ],
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": 0,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                },
                {
                    "payment_method_type": "debit",
                    "payment_experience": null,
                    "card_networks": [
                        "Visa",
                        "Mastercard"
                    ],
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": 1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                }
            ]
        },
        {
            "payment_method": "wallet",
            "payment_method_types": [
                {
                    "payment_method_type": "paypal",
                    "payment_experience": "invoke_sdk_client",
                    "card_networks": null,
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": 1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                }
            ]
        }
    ],
    "metadata": {
        "paypal_sdk": {
            "client_id": "ASK****************************_2"
        }
    }
}'
```

### Payments Create
```
curl --location 'http://localhost:8080/payments' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--header 'api-key: dev_33Ad6faEcusLrqrqSeeFWyGRyTfOkKMoPMTSirAhCg0qqwkxQ25t7K1ucBEoq26M' \
--data-raw '{
    "amount": 6100,
    "currency": "USD",
    "confirm": false,
    "business_country": "US",
    "business_label": "default",
    "amount_to_capture": 6100,
    "capture_method": "automatic",
    "capture_on": "2022-09-10T10:11:12Z",
    "return_url": "https://google.com",
    "email": "something@gmail.com",
    "name": "Joseph Doe",
    "phone": "999999999",
    "phone_country_code": "+65",
    "description": "Its my first payment request",
    "statement_descriptor_name": "Juspay",
    "statement_descriptor_suffix": "Router",
    "billing": {
        "address": {
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "city": "San Fransico",
            "state": "California",
            "zip": "94122",
            "country": "US",
            "first_name": "joseph",
            "last_name": "Doe"
        },
        "phone": {
            "number": "8056594427",
            "country_code": "+91"
        }
    }
}'
```

### Session Token

```
curl --location 'http://localhost:8080/payments/session_tokens' \
--header 'Content-Type: application/json' \
--header 'api-key: pk_dev_77ee3a2eb65741a0a4a3f1f6f3f0aa94' \
--data '{
    "payment_id": "pay_msQQCSrBSCeNAZjBgwj9",
    "client_secret": "pay_msQQCSrBSCeNAZjBgwj9_secret_JdfpEbRZl5KTYwtNCURW",
    "wallets": []
}'
```

Response

```
{
    "payment_id": "pay_msQQCSrBSCeNAZjBgwj9",
    "client_secret": "pay_msQQCSrBSCeNAZjBgwj9_secret_JdfpEbRZl5KTYwtNCURW",
    "session_token": [
        {
            "wallet_name": "paypal",
            "connector": "paypal",
            "session_token": "ASK************************_2",
            "sdk_next_action": {
                "next_action": "confirm"
            }
        }
    ]
}
```

### Payments - Confirm

```
curl --location 'http://localhost:8080/payments/pay_msQQCSrBSCeNAZjBgwj9/confirm' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: dev_33Ad6faEcusLrqrqSeeFWyGRyTfOkKMoPMTSirAhCg0qqwkxQ25t7K1ucBEoq26M' \
--data '{
    "confirm": true,
    "payment_method": "wallet",
    "payment_method_type": "paypal",
    "payment_method_data": {
        "wallet": {
            "paypal_sdk": {
            "token":""
            }
        }
    }  
}'
```

Response:
```
{
    "payment_id": "pay_msQQCSrBSCeNAZjBgwj9",
    "merchant_id": "merchant_1716757295",
    "status": "requires_customer_action",
    "amount": 6100,
    "net_amount": 6100,
    "amount_capturable": 6100,
    "amount_received": null,
    "connector": "paypal",
    "client_secret": "pay_msQQCSrBSCeNAZjBgwj9_secret_JdfpEbRZl5KTYwtNCURW",
    "created": "2024-05-26T21:03:19.068Z",
    "currency": "USD",
    "customer_id": null,
    "customer": null,
    "description": "Its my first payment request",
    "refunds": null,
    "disputes": null,
    "mandate_id": null,
    "mandate_data": null,
    "setup_future_usage": null,
    "off_session": null,
    "capture_on": null,
    "capture_method": "automatic",
    "payment_method": "wallet",
    "payment_method_data": {
        "wallet": {},
        "billing": null
    },
    "payment_token": null,
    "shipping": null,
    "billing": {
        "address": {
            "city": "San Fransico",
            "country": "US",
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "zip": "94122",
            "state": "California",
            "first_name": "joseph",
            "last_name": "Doe"
        },
        "phone": {
            "number": "8056594427",
            "country_code": "+91"
        },
        "email": null
    },
    "order_details": null,
    "email": null,
    "name": null,
    "phone": null,
    "return_url": "https://google.com/",
    "authentication_type": "no_three_ds",
    "statement_descriptor_name": "Juspay",
    "statement_descriptor_suffix": "Router",
    "next_action": {
        "type": "invoke_sdk_client",
        "next_action_data": {
            "next_action": "complete_authorize"
        }
    },
    "cancellation_reason": null,
    "error_code": null,
    "error_message": null,
    "unified_code": null,
    "unified_message": null,
    "payment_experience": null,
    "payment_method_type": "paypal",
    "connector_label": "paypal_US_default",
    "business_country": "US",
    "business_label": "default",
    "business_sub_label": null,
    "allowed_payment_method_types": null,
    "ephemeral_key": null,
    "manual_retry_allowed": null,
    "connector_transaction_id": "39X68391D53803705",
    "frm_message": null,
    "metadata": null,
    "connector_metadata": {
        "apple_pay": null,
        "airwallex": null,
        "noon": {
            "order_category": "pay"
        }
    },
    "feature_metadata": null,
    "reference_id": "pay_msQQCSrBSCeNAZjBgwj9_1",
    "payment_link": null,
    "profile_id": "pro_L6gjuuDhzdKR9wlyV8yA",
    "surcharge_details": null,
    "attempt_count": 1,
    "merchant_decision": null,
    "merchant_connector_id": "mca_ziKihOYd8bxdqpoLhP3u",
    "incremental_authorization_allowed": null,
    "authorization_count": null,
    "incremental_authorizations": null,
    "external_authentication_details": null,
    "external_3ds_authentication_attempted": false,
    "expires_on": "2024-05-26T21:18:19.068Z",
    "fingerprint": null,
    "browser_info": {
        "language": null,
        "time_zone": null,
        "ip_address": "::1",
        "user_agent": null,
        "color_depth": null,
        "java_enabled": null,
        "screen_width": null,
        "accept_header": null,
        "screen_height": null,
        "java_script_enabled": null
    },
    "payment_method_id": null,
    "payment_method_status": null,
    "updated": "2024-05-26T21:06:09.286Z",
    "charges": null,
    "frm_metadata": null
}
```

### Authenticate Payment via SDK

### Payments - Complete Authorize
```
curl --location 'http://localhost:8080/payments/pay_msQQCSrBSCeNAZjBgwj9/complete_authorize' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: pk_dev_77ee3a2eb65741a0a4a3f1f6f3f0aa94' \
--data-raw '{
  "shipping": {
        "address": {
            "line1": "1467",
            "line2": "Kormangala",
            "line3": "Harrison Street",
            "city": "San Fransico",
            "state": "California",
            "zip": "94122",
            "country": "US",
            "first_name": "PiX"
        },
        "phone": {
            "number": "8056594427",
            "country_code": "+91"
        },
        "email": "guest@example.com"
    },
    "client_secret": "pay_msQQCSrBSCeNAZjBgwj9_secret_JdfpEbRZl5KTYwtNCURW"
}'
```

Test Scenarios

- Test all the payments flow: Authorize, Manual Capture, Auto Capture, Refunds and webhooks
- Test for backwards compatibility: i.e use an older account where `redirect_to_url` is configured as payment_experience none of the flow should get affected by new code
- Update the connector account to SDK experience and then sync older payments and try new payments as well

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