Issue:
Bug: [FEATURE]: Add partner flow for PayPal



### Feature Description

PayPal offers an onboarding flow, where merchants can be onboarded directly from a partner account. But for that, we need to change the authentication logic for PayPal request.

We should be able to take a 3rd field in the connector_account_details. So we need to support SignatureKey as well.

### Possible Implementation

Add support for SignatureKey

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

Pull request description:
## 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 -->
- Make PayPal support `SignatureKey` `auth_type`.
- Add extra fields in `orders` request.

### 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).
-->
To support PayPal onboarding flow.

## 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)?
-->
Postman.
### Payment Connector - Create
Paypal now supports `TemporaryAuth` in the `auth_type`. You can find more details about this in this PR #2833.
Paypal also support `SignatureKey` in the `auth_type`.
```
curl --location 'http://localhost:8080/account/merchant_1700133263/connectors' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: test_admin' \
--data '{
  "connector_type": "fiz_operations",
  "connector_name": "paypal",
  "connector_account_details": {
    "auth_type": "SignatureKey",
    "api_key": "client_secret",
    "key1": "client_id",
    "api_secret": "partner_id"
  },
  "status": "active",
  "disabled": false
}'

```

If all the fields are passed correctly you will a normal mca response.



## 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
- [ ] I added a [CHANGELOG](/CHANGELOG.md) entry if applicable


Testing:

Postman.
### Payment Connector - Create
Paypal now supports `TemporaryAuth` in the `auth_type`. You can find more details about this in this PR #2833.
Paypal also support `SignatureKey` in the `auth_type`.
```
curl --location 'http://localhost:8080/account/merchant_1700133263/connectors' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: test_admin' \
--data '{
  "connector_type": "fiz_operations",
  "connector_name": "paypal",
  "connector_account_details": {
    "auth_type": "SignatureKey",
    "api_key": "client_secret",
    "key1": "client_id",
    "api_secret": "partner_id"
  },
  "status": "active",
  "disabled": false
}'

```

If all the fields are passed correctly you will a normal mca response.

Patch:
diff --git a/crates/router/src/connector/paypal.rs b/crates/router/src/connector/paypal.rs
index e514ebbed2f..0e8cff8c056 100644
--- a/crates/router/src/connector/paypal.rs
+++ b/crates/router/src/connector/paypal.rs
@@ -5,10 +5,10 @@ use base64::Engine;
 use common_utils::ext_traits::ByteSliceExt;
 use diesel_models::enums;
 use error_stack::{IntoReport, ResultExt};
-use masking::PeekInterface;
+use masking::{ExposeInterface, PeekInterface, Secret};
 use transformers as paypal;
 
-use self::transformers::{PaypalAuthResponse, PaypalMeta, PaypalWebhookEventType};
+use self::transformers::{auth_headers, PaypalAuthResponse, PaypalMeta, PaypalWebhookEventType};
 use super::utils::PaymentsCompleteAuthorizeRequestData;
 use crate::{
     configs::settings,
@@ -31,7 +31,7 @@ use crate::{
         self,
         api::{self, CompleteAuthorize, ConnectorCommon, ConnectorCommonExt, VerifyWebhookSource},
         transformers::ForeignFrom,
-        ErrorResponse, Response,
+        ConnectorAuthType, ErrorResponse, Response,
     },
     utils::{self, BytesExt},
 };
@@ -110,8 +110,8 @@ where
             .clone()
             .ok_or(errors::ConnectorError::FailedToObtainAuthType)?;
         let key = &req.attempt_id;
-
-        Ok(vec![
+        let auth = paypal::PaypalAuthType::try_from(&req.connector_auth_type)?;
+        let mut headers = vec![
             (
                 headers::CONTENT_TYPE.to_string(),
                 self.get_content_type().to_string().into(),
@@ -121,17 +121,57 @@ where
                 format!("Bearer {}", access_token.token.peek()).into_masked(),
             ),
             (
-                "Prefer".to_string(),
+                auth_headers::PREFER.to_string(),
                 "return=representation".to_string().into(),
             ),
             (
-                "PayPal-Request-Id".to_string(),
+                auth_headers::PAYPAL_REQUEST_ID.to_string(),
                 key.to_string().into_masked(),
             ),
-        ])
+        ];
+        if let Ok(paypal::PaypalConnectorCredentials::PartnerIntegration(credentials)) =
+            auth.get_credentials()
+        {
+            let auth_assertion_header =
+                construct_auth_assertion_header(&credentials.payer_id, &credentials.client_id);
+            headers.extend(vec![
+                (
+                    auth_headers::PAYPAL_AUTH_ASSERTION.to_string(),
+                    auth_assertion_header.to_string().into_masked(),
+                ),
+                (
+                    auth_headers::PAYPAL_PARTNER_ATTRIBUTION_ID.to_string(),
+                    "HyperSwitchPPCP_SP".to_string().into(),
+                ),
+            ])
+        } else {
+            headers.extend(vec![(
+                auth_headers::PAYPAL_PARTNER_ATTRIBUTION_ID.to_string(),
+                "HyperSwitchlegacy_Ecom".to_string().into(),
+            )])
+        }
+        Ok(headers)
     }
 }
 
+fn construct_auth_assertion_header(
+    payer_id: &Secret<String>,
+    client_id: &Secret<String>,
+) -> String {
+    let algorithm = consts::BASE64_ENGINE
+        .encode("{\"alg\":\"none\"}")
+        .to_string();
+    let merchant_credentials = format!(
+        "{{\"iss\":\"{}\",\"payer_id\":\"{}\"}}",
+        client_id.clone().expose(),
+        payer_id.clone().expose()
+    );
+    let encoded_credentials = consts::BASE64_ENGINE
+        .encode(merchant_credentials)
+        .to_string();
+    format!("{algorithm}.{encoded_credentials}.")
+}
+
 impl ConnectorCommon for Paypal {
     fn id(&self) -> &'static str {
         "paypal"
@@ -151,14 +191,14 @@ impl ConnectorCommon for Paypal {
 
     fn get_auth_header(
         &self,
-        auth_type: &types::ConnectorAuthType,
+        auth_type: &ConnectorAuthType,
     ) -> CustomResult<Vec<(String, request::Maskable<String>)>, errors::ConnectorError> {
-        let auth: paypal::PaypalAuthType = auth_type
-            .try_into()
-            .change_context(errors::ConnectorError::FailedToObtainAuthType)?;
+        let auth = paypal::PaypalAuthType::try_from(auth_type)?;
+        let credentials = auth.get_credentials()?;
+
         Ok(vec![(
             headers::AUTHORIZATION.to_string(),
-            auth.api_key.into_masked(),
+            credentials.get_client_secret().into_masked(),
         )])
     }
 
@@ -260,15 +300,9 @@ impl ConnectorIntegration<api::AccessTokenAuth, types::AccessTokenRequestData, t
         req: &types::RefreshTokenRouterData,
         _connectors: &settings::Connectors,
     ) -> CustomResult<Vec<(String, request::Maskable<String>)>, errors::ConnectorError> {
-        let auth: paypal::PaypalAuthType = (&req.connector_auth_type)
-            .try_into()
-            .change_context(errors::ConnectorError::FailedToObtainAuthType)?;
-
-        let auth_id = auth
-            .key1
-            .zip(auth.api_key)
-            .map(|(key1, api_key)| format!("{}:{}", key1, api_key));
-        let auth_val = format!("Basic {}", consts::BASE64_ENGINE.encode(auth_id.peek()));
+        let auth = paypal::PaypalAuthType::try_from(&req.connector_auth_type)?;
+        let credentials = auth.get_credentials()?;
+        let auth_val = credentials.generate_authorization_value();
 
         Ok(vec![
             (
@@ -998,15 +1032,9 @@ impl
         >,
         _connectors: &settings::Connectors,
     ) -> CustomResult<Vec<(String, request::Maskable<String>)>, errors::ConnectorError> {
-        let auth: paypal::PaypalAuthType = (&req.connector_auth_type)
-            .try_into()
-            .change_context(errors::ConnectorError::FailedToObtainAuthType)?;
-
-        let auth_id = auth
-            .key1
-            .zip(auth.api_key)
-            .map(|(key1, api_key)| format!("{}:{}", key1, api_key));
-        let auth_val = format!("Basic {}", consts::BASE64_ENGINE.encode(auth_id.peek()));
+        let auth = paypal::PaypalAuthType::try_from(&req.connector_auth_type)?;
+        let credentials = auth.get_credentials()?;
+        let auth_val = credentials.generate_authorization_value();
 
         Ok(vec![
             (
diff --git a/crates/router/src/connector/paypal/transformers.rs b/crates/router/src/connector/paypal/transformers.rs
index 5468c6bb806..d023077ff00 100644
--- a/crates/router/src/connector/paypal/transformers.rs
+++ b/crates/router/src/connector/paypal/transformers.rs
@@ -1,7 +1,8 @@
 use api_models::{enums, payments::BankRedirectData};
+use base64::Engine;
 use common_utils::errors::CustomResult;
 use error_stack::{IntoReport, ResultExt};
-use masking::Secret;
+use masking::{ExposeInterface, Secret};
 use serde::{Deserialize, Serialize};
 use time::PrimitiveDateTime;
 use url::Url;
@@ -11,10 +12,11 @@ use crate::{
         self, to_connector_meta, AccessTokenRequestInfo, AddressDetailsData,
         BankRedirectBillingData, CardData, PaymentsAuthorizeRequestData,
     },
+    consts,
     core::errors,
     services,
     types::{
-        self, api, storage::enums as storage_enums, transformers::ForeignFrom,
+        self, api, storage::enums as storage_enums, transformers::ForeignFrom, ConnectorAuthType,
         VerifyWebhookSourceResponseData,
     },
 };
@@ -57,6 +59,12 @@ mod webhook_headers {
     pub const PAYPAL_CERT_URL: &str = "paypal-cert-url";
     pub const PAYPAL_AUTH_ALGO: &str = "paypal-auth-algo";
 }
+pub mod auth_headers {
+    pub const PAYPAL_PARTNER_ATTRIBUTION_ID: &str = "PayPal-Partner-Attribution-Id";
+    pub const PREFER: &str = "Prefer";
+    pub const PAYPAL_REQUEST_ID: &str = "PayPal-Request-Id";
+    pub const PAYPAL_AUTH_ASSERTION: &str = "PayPal-Auth-Assertion";
+}
 
 #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
 #[serde(rename_all = "UPPERCASE")]
@@ -72,19 +80,111 @@ pub struct OrderAmount {
     pub value: String,
 }
 
+#[derive(Default, Debug, Serialize, Deserialize, Eq, PartialEq)]
+pub struct OrderRequestAmount {
+    pub currency_code: storage_enums::Currency,
+    pub value: String,
+    pub breakdown: AmountBreakdown,
+}
+
+impl From<&PaypalRouterData<&types::PaymentsAuthorizeRouterData>> for OrderRequestAmount {
+    fn from(item: &PaypalRouterData<&types::PaymentsAuthorizeRouterData>) -> Self {
+        Self {
+            currency_code: item.router_data.request.currency,
+            value: item.amount.to_owned(),
+            breakdown: AmountBreakdown {
+                item_total: OrderAmount {
+                    currency_code: item.router_data.request.currency,
+                    value: item.amount.to_owned(),
+                },
+            },
+        }
+    }
+}
+
+#[derive(Default, Debug, Serialize, Deserialize, Eq, PartialEq)]
+pub struct AmountBreakdown {
+    item_total: OrderAmount,
+}
+
 #[derive(Default, Debug, Serialize, Eq, PartialEq)]
 pub struct PurchaseUnitRequest {
     reference_id: Option<String>, //reference for an item in purchase_units
     invoice_id: Option<String>, //The API caller-provided external invoice number for this order. Appears in both the payer's transaction history and the emails that the payer receives.
     custom_id: Option<String>,  //Used to reconcile client transactions with PayPal transactions.
-    amount: OrderAmount,
+    amount: OrderRequestAmount,
+    #[serde(skip_serializing_if = "Option::is_none")]
+    payee: Option<Payee>,
+    shipping: Option<ShippingAddress>,
+    items: Vec<ItemDetails>,
 }
 
-#[derive(Debug, Serialize)]
+#[derive(Default, Debug, Serialize, Eq, PartialEq)]
+pub struct Payee {
+    merchant_id: Secret<String>,
+}
+
+#[derive(Default, Debug, Serialize, Eq, PartialEq)]
+pub struct ItemDetails {
+    name: String,
+    quantity: u16,
+    unit_amount: OrderAmount,
+}
+
+impl From<&PaypalRouterData<&types::PaymentsAuthorizeRouterData>> for ItemDetails {
+    fn from(item: &PaypalRouterData<&types::PaymentsAuthorizeRouterData>) -> Self {
+        Self {
+            name: format!(
+                "Payment for invoice {}",
+                item.router_data.connector_request_reference_id
+            ),
+            quantity: 1,
+            unit_amount: OrderAmount {
+                currency_code: item.router_data.request.currency,
+                value: item.amount.to_string(),
+            },
+        }
+    }
+}
+
+#[derive(Default, Debug, Serialize, Eq, PartialEq)]
 pub struct Address {
     address_line_1: Option<Secret<String>>,
     postal_code: Option<Secret<String>>,
     country_code: api_models::enums::CountryAlpha2,
+    admin_area_2: Option<String>,
+}
+
+#[derive(Default, Debug, Serialize, Eq, PartialEq)]
+pub struct ShippingAddress {
+    address: Option<Address>,
+    name: Option<ShippingName>,
+}
+
+impl TryFrom<&PaypalRouterData<&types::PaymentsAuthorizeRouterData>> for ShippingAddress {
+    type Error = error_stack::Report<errors::ConnectorError>;
+
+    fn try_from(
+        item: &PaypalRouterData<&types::PaymentsAuthorizeRouterData>,
+    ) -> Result<Self, Self::Error> {
+        Ok(Self {
+            address: get_address_info(item.router_data.address.shipping.as_ref())?,
+            name: Some(ShippingName {
+                full_name: item
+                    .router_data
+                    .address
+                    .shipping
+                    .as_ref()
+                    .and_then(|inner_data| inner_data.address.as_ref())
+                    .and_then(|inner_data| inner_data.first_name.clone()),
+            }),
+        })
+    }
+}
+
+#[derive(Default, Debug, Serialize, Eq, PartialEq)]
+pub struct ShippingName {
+    full_name: Option<Secret<String>>,
 }
 
 #[derive(Debug, Serialize)]
@@ -124,6 +224,22 @@ pub struct RedirectRequest {
 pub struct ContextStruct {
     return_url: Option<String>,
     cancel_url: Option<String>,
+    user_action: Option<UserAction>,
+    shipping_preference: ShippingPreference,
+}
+
+#[derive(Debug, Serialize)]
+pub enum UserAction {
+    #[serde(rename = "PAY_NOW")]
+    PayNow,
+}
+
+#[derive(Debug, Serialize)]
+pub enum ShippingPreference {
+    #[serde(rename = "SET_PROVIDED_ADDRESS")]
+    SetProvidedAddress,
+    #[serde(rename = "GET_FROM_FILE")]
+    GetFromFile,
 }
 
 #[derive(Debug, Serialize)]
@@ -158,6 +274,7 @@ fn get_address_info(
             country_code: address.get_country()?.to_owned(),
             address_line_1: address.line1.clone(),
             postal_code: address.zip.clone(),
+            admin_area_2: address.city.clone(),
         }),
         None => None,
     };
@@ -180,6 +297,12 @@ fn get_payment_source(
             experience_context: ContextStruct {
                 return_url: item.request.complete_authorize_url.clone(),
                 cancel_url: item.request.complete_authorize_url.clone(),
+                shipping_preference: if item.address.shipping.is_some() {
+                    ShippingPreference::SetProvidedAddress
+                } else {
+                    ShippingPreference::GetFromFile
+                },
+                user_action: Some(UserAction::PayNow),
             },
         })),
         BankRedirectData::Giropay {
@@ -194,6 +317,12 @@ fn get_payment_source(
             experience_context: ContextStruct {
                 return_url: item.request.complete_authorize_url.clone(),
                 cancel_url: item.request.complete_authorize_url.clone(),
+                shipping_preference: if item.address.shipping.is_some() {
+                    ShippingPreference::SetProvidedAddress
+                } else {
+                    ShippingPreference::GetFromFile
+                },
+                user_action: Some(UserAction::PayNow),
             },
         })),
         BankRedirectData::Ideal {
@@ -208,6 +337,12 @@ fn get_payment_source(
             experience_context: ContextStruct {
                 return_url: item.request.complete_authorize_url.clone(),
                 cancel_url: item.request.complete_authorize_url.clone(),
+                shipping_preference: if item.address.shipping.is_some() {
+                    ShippingPreference::SetProvidedAddress
+                } else {
+                    ShippingPreference::GetFromFile
+                },
+                user_action: Some(UserAction::PayNow),
             },
         })),
         BankRedirectData::Sofort {
@@ -220,6 +355,12 @@ fn get_payment_source(
             experience_context: ContextStruct {
                 return_url: item.request.complete_authorize_url.clone(),
                 cancel_url: item.request.complete_authorize_url.clone(),
+                shipping_preference: if item.address.shipping.is_some() {
+                    ShippingPreference::SetProvidedAddress
+                } else {
+                    ShippingPreference::GetFromFile
+                },
+                user_action: Some(UserAction::PayNow),
             },
         })),
         BankRedirectData::BancontactCard { .. }
@@ -247,11 +388,24 @@ fn get_payment_source(
     }
 }
 
+fn get_payee(auth_type: &PaypalAuthType) -> Option<Payee> {
+    auth_type
+        .get_credentials()
+        .ok()
+        .and_then(|credentials| credentials.get_payer_id())
+        .map(|payer_id| Payee {
+            merchant_id: payer_id,
+        })
+}
+
 impl TryFrom<&PaypalRouterData<&types::PaymentsAuthorizeRouterData>> for PaypalPaymentsRequest {
     type Error = error_stack::Report<errors::ConnectorError>;
     fn try_from(
         item: &PaypalRouterData<&types::PaymentsAuthorizeRouterData>,
     ) -> Result<Self, Self::Error> {
+        let paypal_auth: PaypalAuthType =
+            PaypalAuthType::try_from(&item.router_data.connector_auth_type)?;
+        let payee = get_payee(&paypal_auth);
         match item.router_data.request.payment_method_data {
             api_models::payments::PaymentMethodData::Card(ref ccard) => {
                 let intent = if item.router_data.request.is_auto_capture()? {
@@ -259,18 +413,20 @@ impl TryFrom<&PaypalRouterData<&types::PaymentsAuthorizeRouterData>> for PaypalP
                 } else {
                     PaypalPaymentIntent::Authorize
                 };
-                let amount = OrderAmount {
-                    currency_code: item.router_data.request.currency,
-                    value: item.amount.to_owned(),
-                };
+                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("-"));
@@ -306,25 +462,29 @@ impl TryFrom<&PaypalRouterData<&types::PaymentsAuthorizeRouterData>> for PaypalP
                     } else {
                         PaypalPaymentIntent::Authorize
                     };
-                    let amount = OrderAmount {
-                        currency_code: item.router_data.request.currency,
-                        value: item.amount.to_owned(),
-                    };
+                    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 {
                                 return_url: item.router_data.request.complete_authorize_url.clone(),
                                 cancel_url: item.router_data.request.complete_authorize_url.clone(),
+                                shipping_preference: ShippingPreference::SetProvidedAddress,
+                                user_action: Some(UserAction::PayNow),
                             },
                         }));
 
@@ -374,18 +534,20 @@ impl TryFrom<&PaypalRouterData<&types::PaymentsAuthorizeRouterData>> for PaypalP
                         connector: "Paypal".to_string(),
                     })?
                 };
-                let amount = OrderAmount {
-                    currency_code: item.router_data.request.currency,
-                    value: item.amount.to_owned(),
-                };
+                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)?);
@@ -604,19 +766,98 @@ impl<F, T> TryFrom<types::ResponseRouterData<F, PaypalAuthUpdateResponse, T, typ
 }
 
 #[derive(Debug)]
-pub struct PaypalAuthType {
-    pub(super) api_key: Secret<String>,
-    pub(super) key1: Secret<String>,
+pub enum PaypalAuthType {
+    TemporaryAuth,
+    AuthWithDetails(PaypalConnectorCredentials),
+}
+
+#[derive(Debug)]
+pub enum PaypalConnectorCredentials {
+    StandardIntegration(StandardFlowCredentials),
+    PartnerIntegration(PartnerFlowCredentials),
 }
 
-impl TryFrom<&types::ConnectorAuthType> for PaypalAuthType {
+impl PaypalConnectorCredentials {
+    pub fn get_client_id(&self) -> Secret<String> {
+        match self {
+            Self::StandardIntegration(item) => item.client_id.clone(),
+            Self::PartnerIntegration(item) => item.client_id.clone(),
+        }
+    }
+
+    pub fn get_client_secret(&self) -> Secret<String> {
+        match self {
+            Self::StandardIntegration(item) => item.client_secret.clone(),
+            Self::PartnerIntegration(item) => item.client_secret.clone(),
+        }
+    }
+
+    pub fn get_payer_id(&self) -> Option<Secret<String>> {
+        match self {
+            Self::StandardIntegration(_) => None,
+            Self::PartnerIntegration(item) => Some(item.payer_id.clone()),
+        }
+    }
+
+    pub fn generate_authorization_value(&self) -> String {
+        let auth_id = format!(
+            "{}:{}",
+            self.get_client_id().expose(),
+            self.get_client_secret().expose(),
+        );
+        format!("Basic {}", consts::BASE64_ENGINE.encode(auth_id))
+    }
+}
+
+#[derive(Debug)]
+pub struct StandardFlowCredentials {
+    pub(super) client_id: Secret<String>,
+    pub(super) client_secret: Secret<String>,
+}
+
+#[derive(Debug)]
+pub struct PartnerFlowCredentials {
+    pub(super) client_id: Secret<String>,
+    pub(super) client_secret: Secret<String>,
+    pub(super) payer_id: Secret<String>,
+}
+
+impl PaypalAuthType {
+    pub fn get_credentials(
+        &self,
+    ) -> CustomResult<&PaypalConnectorCredentials, errors::ConnectorError> {
+        match self {
+            Self::TemporaryAuth => Err(errors::ConnectorError::InvalidConnectorConfig {
+                config: "TemporaryAuth found in connector_account_details",
+            }
+            .into()),
+            Self::AuthWithDetails(credentials) => Ok(credentials),
+        }
+    }
+}
+
+impl TryFrom<&ConnectorAuthType> for PaypalAuthType {
     type Error = error_stack::Report<errors::ConnectorError>;
-    fn try_from(auth_type: &types::ConnectorAuthType) -> Result<Self, Self::Error> {
+    fn try_from(auth_type: &ConnectorAuthType) -> Result<Self, Self::Error> {
         match auth_type {
-            types::ConnectorAuthType::BodyKey { api_key, key1 } => Ok(Self {
-                api_key: api_key.to_owned(),
-                key1: key1.to_owned(),
-            }),
+            types::ConnectorAuthType::BodyKey { api_key, key1 } => Ok(Self::AuthWithDetails(
+                PaypalConnectorCredentials::StandardIntegration(StandardFlowCredentials {
+                    client_id: key1.to_owned(),
+                    client_secret: api_key.to_owned(),
+                }),
+            )),
+            types::ConnectorAuthType::SignatureKey {
+                api_key,
+                key1,
+                api_secret,
+            } => Ok(Self::AuthWithDetails(
+                PaypalConnectorCredentials::PartnerIntegration(PartnerFlowCredentials {
+                    client_id: key1.to_owned(),
+                    client_secret: api_key.to_owned(),
+                    payer_id: api_secret.to_owned(),
+                }),
+            )),
+            types::ConnectorAuthType::TemporaryAuth => Ok(Self::TemporaryAuth),
             _ => Err(errors::ConnectorError::FailedToObtainAuthType)?,
         }
     }