Bug: Pass `required_billing_contact_fields` field in apple pay session call based on dynamic fields



This change is required as part of the one click checkout where in which we expect apple pay to collect the billing details from the customer and pass it in the confirm call with the `payment_data`. 
In order for apple pay to collect the billing details from customer we need to pass``"requiredBillingContactFields": ["postalAddress"]`` in the `/session` call. Hence we need to have a validation in the backend that checks for the dynamic fields for a specific connector and pass the `required_billing_contact_fields` to sdk.
diff --git a/crates/api_models/src/enums.rs b/crates/api_models/src/enums.rs
index 884e0fd82f8..37d17dcff17 100644
--- a/crates/api_models/src/enums.rs
+++ b/crates/api_models/src/enums.rs
@@ -396,13 +396,11 @@ pub struct UnresolvedResponseReason {
     Clone,
     Debug,
     Eq,
-    PartialEq,
     serde::Deserialize,
     serde::Serialize,
     strum::Display,
     strum::EnumString,
     ToSchema,
-    Hash,
 )]
 #[serde(rename_all = "snake_case")]
 #[strum(serialize_all = "snake_case")]
@@ -430,6 +428,89 @@ pub enum FieldType {
     DropDown { options: Vec<String> },
 }
 
+impl FieldType {
+    pub fn get_billing_variants() -> Vec<Self> {
+        vec![
+            Self::UserBillingName,
+            Self::UserAddressLine1,
+            Self::UserAddressLine2,
+            Self::UserAddressCity,
+            Self::UserAddressPincode,
+            Self::UserAddressState,
+            Self::UserAddressCountry { options: vec![] },
+        ]
+    }
+}
+
+/// This implementatiobn is to ignore the inner value of UserAddressCountry enum while comparing
+impl PartialEq for FieldType {
+    fn eq(&self, other: &Self) -> bool {
+        match (self, other) {
+            (Self::UserCardNumber, Self::UserCardNumber) => true,
+            (Self::UserCardExpiryMonth, Self::UserCardExpiryMonth) => true,
+            (Self::UserCardExpiryYear, Self::UserCardExpiryYear) => true,
+            (Self::UserCardCvc, Self::UserCardCvc) => true,
+            (Self::UserFullName, Self::UserFullName) => true,
+            (Self::UserEmailAddress, Self::UserEmailAddress) => true,
+            (Self::UserPhoneNumber, Self::UserPhoneNumber) => true,
+            (Self::UserCountryCode, Self::UserCountryCode) => true,
+            (
+                Self::UserCountry {
+                    options: options_self,
+                },
+                Self::UserCountry {
+                    options: options_other,
+                },
+            ) => options_self.eq(options_other),
+            (
+                Self::UserCurrency {
+                    options: options_self,
+                },
+                Self::UserCurrency {
+                    options: options_other,
+                },
+            ) => options_self.eq(options_other),
+            (Self::UserBillingName, Self::UserBillingName) => true,
+            (Self::UserAddressLine1, Self::UserAddressLine1) => true,
+            (Self::UserAddressLine2, Self::UserAddressLine2) => true,
+            (Self::UserAddressCity, Self::UserAddressCity) => true,
+            (Self::UserAddressPincode, Self::UserAddressPincode) => true,
+            (Self::UserAddressState, Self::UserAddressState) => true,
+            (Self::UserAddressCountry { .. }, Self::UserAddressCountry { .. }) => true,
+            (Self::UserBlikCode, Self::UserBlikCode) => true,
+            (Self::UserBank, Self::UserBank) => true,
+            (Self::Text, Self::Text) => true,
+            (
+                Self::DropDown {
+                    options: options_self,
+                },
+                Self::DropDown {
+                    options: options_other,
+                },
+            ) => options_self.eq(options_other),
+            _unused => false,
+        }
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use super::*;
+
+    #[test]
+    fn test_partialeq_for_field_type() {
+        let user_address_country_is_us = FieldType::UserAddressCountry {
+            options: vec!["US".to_string()],
+        };
+
+        let user_address_country_is_all = FieldType::UserAddressCountry {
+            options: vec!["ALL".to_string()],
+        };
+
+        assert!(user_address_country_is_us.eq(&user_address_country_is_all))
+    }
+}
+
 #[derive(
     Debug,
     serde::Deserialize,
diff --git a/crates/api_models/src/payment_methods.rs b/crates/api_models/src/payment_methods.rs
index 96136d69370..b7a58b3b5b6 100644
--- a/crates/api_models/src/payment_methods.rs
+++ b/crates/api_models/src/payment_methods.rs
@@ -537,7 +537,7 @@ impl From<Percentage<SURCHARGE_PERCENTAGE_PRECISION_LENGTH>> for SurchargePercen
     }
 }
 /// Required fields info used while listing the payment_method_data
-#[derive(Debug, serde::Deserialize, serde::Serialize, Clone, PartialEq, Eq, ToSchema, Hash)]
+#[derive(Debug, serde::Deserialize, serde::Serialize, Clone, PartialEq, Eq, ToSchema)]
 pub struct RequiredFieldInfo {
     /// Required field for a payment_method through a payment_method_type
     pub required_field: String,
diff --git a/crates/api_models/src/payments.rs b/crates/api_models/src/payments.rs
index f1ce53580aa..ad5c02f6baa 100644
--- a/crates/api_models/src/payments.rs
+++ b/crates/api_models/src/payments.rs
@@ -3867,6 +3867,24 @@ pub struct GpayAllowedMethodsParameters {
     pub allowed_auth_methods: Vec<String>,
     /// The list of allowed card networks (ex: AMEX,JCB etc)
     pub allowed_card_networks: Vec<String>,
+    /// Is billing address required
+    pub billing_address_required: Option<bool>,
+    /// Billing address parameters
+    pub billing_address_parameters: Option<GpayBillingAddressParameters>,
+}
+
+#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, serde::Deserialize, ToSchema)]
+pub struct GpayBillingAddressParameters {
+    /// Is billing phone number required
+    pub phone_number_required: bool,
+    /// Billing address format
+    pub format: GpayBillingAddressFormat,
+}
+
+#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, serde::Deserialize, ToSchema)]
+pub enum GpayBillingAddressFormat {
+    FULL,
+    MIN,
 }
 
 #[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, serde::Deserialize, ToSchema)]
@@ -4213,6 +4231,8 @@ pub struct ApplePayPaymentRequest {
     /// The list of supported networks
     pub supported_networks: Option<Vec<String>>,
     pub merchant_identifier: Option<String>,
+    /// The required billing contact fields for connector
+    pub required_billing_contact_fields: Option<Vec<String>>,
 }
 
 #[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, ToSchema, serde::Deserialize)]
diff --git a/crates/connector_configs/src/transformer.rs b/crates/connector_configs/src/transformer.rs
index f89c2e5921b..01332c9d29e 100644
--- a/crates/connector_configs/src/transformer.rs
+++ b/crates/connector_configs/src/transformer.rs
@@ -291,6 +291,8 @@ impl DashboardRequestPayload {
                                     "MASTERCARD".to_string(),
                                     "VISA".to_string(),
                                 ],
+                                billing_address_required: None,
+                                billing_address_parameters: None,
                             };
                         let allowed_payment_methods = payments::GpayAllowedPaymentMethods {
                             payment_method_type: String::from("CARD"),
diff --git a/crates/openapi/src/openapi.rs b/crates/openapi/src/openapi.rs
index 7abbc3b77e4..66e951af7b2 100644
--- a/crates/openapi/src/openapi.rs
+++ b/crates/openapi/src/openapi.rs
@@ -388,6 +388,8 @@ Never share your secret api keys. Keep them guarded and secure.
         api_models::payments::GooglePayRedirectData,
         api_models::payments::GooglePayThirdPartySdk,
         api_models::payments::GooglePaySessionResponse,
+        api_models::payments::GpayBillingAddressParameters,
+        api_models::payments::GpayBillingAddressFormat,
         api_models::payments::SepaBankTransferInstructions,
         api_models::payments::BacsBankTransferInstructions,
         api_models::payments::RedirectResponse,
diff --git a/crates/router/src/connector/bluesnap/transformers.rs b/crates/router/src/connector/bluesnap/transformers.rs
index 0630fef2748..251a928c09e 100644
--- a/crates/router/src/connector/bluesnap/transformers.rs
+++ b/crates/router/src/connector/bluesnap/transformers.rs
@@ -538,6 +538,7 @@ impl TryFrom<types::PaymentsSessionResponseRouterData<BluesnapWalletTokenRespons
                             merchant_capabilities: Some(payment_request_data.merchant_capabilities),
                             supported_networks: Some(payment_request_data.supported_networks),
                             merchant_identifier: Some(session_token_data.merchant_identifier),
+                            required_billing_contact_fields: None,
                         }),
                         connector: "bluesnap".to_string(),
                         delayed_session_token: false,
diff --git a/crates/router/src/connector/payme/transformers.rs b/crates/router/src/connector/payme/transformers.rs
index 0b3f4fb48ce..686858008b6 100644
--- a/crates/router/src/connector/payme/transformers.rs
+++ b/crates/router/src/connector/payme/transformers.rs
@@ -550,6 +550,7 @@ impl<F>
                                     merchant_capabilities: None,
                                     supported_networks: None,
                                     merchant_identifier: None,
+                                    required_billing_contact_fields: None,
                                 },
                             ),
                             connector: "payme".to_string(),
diff --git a/crates/router/src/connector/trustpay/transformers.rs b/crates/router/src/connector/trustpay/transformers.rs
index 5a318e5e440..7f84e301916 100644
--- a/crates/router/src/connector/trustpay/transformers.rs
+++ b/crates/router/src/connector/trustpay/transformers.rs
@@ -1223,6 +1223,7 @@ pub fn get_apple_pay_session<F, T>(
                         ),
                         total: apple_pay_init_result.total.into(),
                         merchant_identifier: None,
+                        required_billing_contact_fields: None,
                     }),
                     connector: "trustpay".to_string(),
                     delayed_session_token: true,
@@ -1326,6 +1327,8 @@ impl From<GpayAllowedMethodsParameters> for api_models::payments::GpayAllowedMet
         Self {
             allowed_auth_methods: value.allowed_auth_methods,
             allowed_card_networks: value.allowed_card_networks,
+            billing_address_required: None,
+            billing_address_parameters: None,
         }
     }
 }
diff --git a/crates/router/src/core/payments/flows/session_flow.rs b/crates/router/src/core/payments/flows/session_flow.rs
index 66e0f144807..c83c73f7624 100644
--- a/crates/router/src/core/payments/flows/session_flow.rs
+++ b/crates/router/src/core/payments/flows/session_flow.rs
@@ -11,9 +11,13 @@ use crate::{
         payments::{self, access_token, helpers, transformers, PaymentData},
     },
     headers, logger,
-    routes::{self, metrics},
+    routes::{self, app::settings, metrics},
     services,
-    types::{self, api, domain},
+    types::{
+        self,
+        api::{self, enums},
+        domain,
+    },
     utils::OptionExt,
 };
 
@@ -78,6 +82,39 @@ impl Feature<api::Session, types::PaymentsSessionData> for types::PaymentsSessio
     }
 }
 
+/// This function checks if for a given connector, payment_method and payment_method_type,
+/// the list of required_field_type is present in dynamic fields
+fn is_dynamic_fields_required(
+    required_fields: &settings::RequiredFields,
+    payment_method: enums::PaymentMethod,
+    payment_method_type: enums::PaymentMethodType,
+    connector: &types::Connector,
+    required_field_type: Vec<enums::FieldType>,
+) -> bool {
+    required_fields
+        .0
+        .get(&payment_method)
+        .and_then(|pm_type| pm_type.0.get(&payment_method_type))
+        .and_then(|required_fields_for_connector| {
+            required_fields_for_connector.fields.get(connector)
+        })
+        .map(|required_fields_final| {
+            required_fields_final
+                .non_mandate
+                .iter()
+                .any(|(_, val)| required_field_type.contains(&val.field_type))
+                || required_fields_final
+                    .mandate
+                    .iter()
+                    .any(|(_, val)| required_field_type.contains(&val.field_type))
+                || required_fields_final
+                    .common
+                    .iter()
+                    .any(|(_, val)| required_field_type.contains(&val.field_type))
+        })
+        .unwrap_or(false)
+}
+
 fn get_applepay_metadata(
     connector_metadata: Option<common_utils::pii::SecretSerdeValue>,
 ) -> RouterResult<payment_types::ApplepaySessionTokenMetadata> {
@@ -247,6 +284,20 @@ async fn create_applepay_session_token(
             router_data.request.to_owned(),
         )?;
 
+        let billing_variants = enums::FieldType::get_billing_variants();
+
+        let required_billing_contact_fields = if is_dynamic_fields_required(
+            &state.conf.required_fields,
+            enums::PaymentMethod::Wallet,
+            enums::PaymentMethodType::ApplePay,
+            &connector.connector_name,
+            billing_variants,
+        ) {
+            Some(vec!["postalAddress".to_string()])
+        } else {
+            None
+        };
+
         // Get apple pay payment request
         let applepay_payment_request = get_apple_pay_payment_request(
             amount_info,
@@ -254,6 +305,7 @@ async fn create_applepay_session_token(
             router_data.request.to_owned(),
             apple_pay_session_request.merchant_identifier.as_str(),
             merchant_business_country,
+            required_billing_contact_fields,
         )?;
 
         let applepay_session_request = build_apple_pay_session_request(
@@ -354,6 +406,7 @@ fn get_apple_pay_payment_request(
     session_data: types::PaymentsSessionData,
     merchant_identifier: &str,
     merchant_business_country: Option<api_models::enums::CountryAlpha2>,
+    required_billing_contact_fields: Option<Vec<String>>,
 ) -> RouterResult<payment_types::ApplePayPaymentRequest> {
     let applepay_payment_request = payment_types::ApplePayPaymentRequest {
         country_code: merchant_business_country.or(session_data.country).ok_or(
@@ -366,6 +419,7 @@ fn get_apple_pay_payment_request(
         merchant_capabilities: Some(payment_request_data.merchant_capabilities),
         supported_networks: Some(payment_request_data.supported_networks),
         merchant_identifier: Some(merchant_identifier.to_string()),
+        required_billing_contact_fields,
     };
     Ok(applepay_payment_request)
 }
@@ -443,6 +497,38 @@ fn create_gpay_session_token(
                 expected_format: "gpay_metadata_format".to_string(),
             })?;
 
+        let billing_variants = enums::FieldType::get_billing_variants();
+
+        let is_billing_details_required = is_dynamic_fields_required(
+            &state.conf.required_fields,
+            enums::PaymentMethod::Wallet,
+            enums::PaymentMethodType::GooglePay,
+            &connector.connector_name,
+            billing_variants,
+        );
+
+        let billing_address_parameters =
+            is_billing_details_required.then_some(payment_types::GpayBillingAddressParameters {
+                phone_number_required: is_billing_details_required,
+                format: payment_types::GpayBillingAddressFormat::FULL,
+            });
+
+        let gpay_allowed_payment_methods = gpay_data
+            .data
+            .allowed_payment_methods
+            .into_iter()
+            .map(
+                |allowed_payment_methods| payment_types::GpayAllowedPaymentMethods {
+                    parameters: payment_types::GpayAllowedMethodsParameters {
+                        billing_address_required: Some(is_billing_details_required),
+                        billing_address_parameters: billing_address_parameters.clone(),
+                        ..allowed_payment_methods.parameters
+                    },
+                    ..allowed_payment_methods
+                },
+            )
+            .collect();
+
         let session_data = router_data.request.clone();
         let transaction_info = payment_types::GpayTransactionInfo {
             country_code: session_data.country.unwrap_or_default(),
@@ -466,7 +552,7 @@ fn create_gpay_session_token(
                     payment_types::GpaySessionTokenResponse::GooglePaySession(
                         payment_types::GooglePaySessionResponse {
                             merchant_info: gpay_data.data.merchant_info,
-                            allowed_payment_methods: gpay_data.data.allowed_payment_methods,
+                            allowed_payment_methods: gpay_allowed_payment_methods,
                             transaction_info,
                             connector: connector.connector_name.to_string(),
                             sdk_next_action: payment_types::SdkNextAction {
diff --git a/openapi/openapi_spec.json b/openapi/openapi_spec.json
index 259d1669523..63f102268c1 100644
--- a/openapi/openapi_spec.json
+++ b/openapi/openapi_spec.json
@@ -4982,6 +4982,14 @@
           "merchant_identifier": {
             "type": "string",
             "nullable": true
+          },
+          "required_billing_contact_fields": {
+            "type": "array",
+            "items": {
+              "type": "string"
+            },
+            "description": "The required billing contact fields for connector",
+            "nullable": true
           }
         }
       },
@@ -9420,6 +9428,19 @@
               "type": "string"
             },
             "description": "The list of allowed card networks (ex: AMEX,JCB etc)"
+          },
+          "billing_address_required": {
+            "type": "boolean",
+            "description": "Is billing address required",
+            "nullable": true
+          },
+          "billing_address_parameters": {
+            "allOf": [
+              {
+                "$ref": "#/components/schemas/GpayBillingAddressParameters"
+              }
+            ],
+            "nullable": true
           }
         }
       },
@@ -9443,6 +9464,29 @@
           }
         }
       },
+      "GpayBillingAddressFormat": {
+        "type": "string",
+        "enum": [
+          "FULL",
+          "MIN"
+        ]
+      },
+      "GpayBillingAddressParameters": {
+        "type": "object",
+        "required": [
+          "phone_number_required",
+          "format"
+        ],
+        "properties": {
+          "phone_number_required": {
+            "type": "boolean",
+            "description": "Is billing phone number required"
+          },
+          "format": {
+            "$ref": "#/components/schemas/GpayBillingAddressFormat"
+          }
+        }
+      },
       "GpayMerchantInfo": {
         "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 -->
This change is required as part of the one click checkout where in which we expect apple pay to collect the billing details from the customer and pass it in the confirm call with the `payment_data`. 
In order for apple pay to collect the billing details from customer we need to pass``"requiredBillingContactFields": ["postalAddress"]`` in the `/session` call. Hence we need to have a validation in the backend that checks for the dynamic fields for a specific connector and pass the `required_billing_contact_fields` to sdk.


### Additional Changes

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

<!--
Provide links to the files with corresponding changes.

Following are the paths where you can find config files:
1. `config`
2. `crates/router/src/configs`
3. `loadtest/config`
-->


## Motivation and Context
<!--
Why is this change required? What problem does it solve?
If it fixes an open issue, please link to the issue here.

If you don't have an issue, we'd recommend starting with one first so the PR
can focus on the implementation (unless it is an obvious bug or documentation fix
that will have little conversation).
-->


## How did you test it?
<!--
Did you write an integration/unit/API test to verify the code changes?
Or did you test this change manually (provide relevant screenshots)?
-->

-> Create a MCA for stripe
-> Apple pay payment create with confirm false
```
{
    "amount": 650,
    "currency": "USD",
    "confirm": false,
    "business_country": "US",
    "business_label": "default",
    "amount_to_capture": 650,
    "customer_id": "custhype1232",
    "capture_method": "automatic",
    "capture_on": "2022-09-10T10:11:12Z",
    "authentication_type": "three_ds",
    "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",
    "payment_method": "wallet",
    "payment_method_type": "apple_pay",
    "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"
        }
    },
    "payment_method_data": {
        "wallet": {
            "apple_pay": {
                "payment_data":"eyJkYXRhIjoiQ1ZoTGd5RGU3TzZjdFlhWHFiVWFONFZvRjBCQjhTbDZsenlXYUdCKzhKcXlic2hYVGxoNEFEcTZYb0t6ZWVSVGwvcUp6NDIvUFMwcmMxMCtqSyt5Z1F5NnlkT25EcnVDeVpkaVU4SWFGOEtOS2hJMFFKOU9JTk9aWFlYR0VzZEczNXlVNzcrQ0k1dk5lUjJiK1gyUXZTVTMzSjlOczJuTFRXZHpwb1VUSHJKU1RiSmFmTTlxYjlZOHZuZS9vZUdHQkV1ZU9DQWQxcFhjRE54SEl2dlc5Z0x3WXRPVldKZUEvUnh5MEdsb0VISng3VEhqUEVQUGJwMkVVZjRMQXZQOGlJSEpmUjM0THdEUVBIdmNSeW9nalRJSzJqOXZjUGRqS2xBSG1LUm5wZlhvWkY4VE16ZUJ6eWhGb0dKY3ZRa3JMc216OEcxTXowZGxlV2VmU2V0TkYxT1NMaldCdExrUXpvWG5xdU1ZeExMenU2SkxPZ1E5ejN1OStFNGQ2NHRZS1NYYlZBWGRKNXRMNTdvbSIsInNpZ25hdHVyZSI6Ik1JQUdDU3FHU0liM0RRRUhBcUNBTUlBQ0FRRXhEVEFMQmdsZ2hrZ0JaUU1FQWdFd2dBWUpLb1pJaHZjTkFRY0JBQUNnZ0RDQ0ErTXdnZ09Jb0FNQ0FRSUNDRXd3UVVsUm5WUTJNQW9HQ0NxR1NNNDlCQU1DTUhveExqQXNCZ05WQkFNTUpVRndjR3hsSUVGd2NHeHBZMkYwYVc5dUlFbHVkR1ZuY21GMGFXOXVJRU5CSUMwZ1J6TXhKakFrQmdOVkJBc01IVUZ3Y0d4bElFTmxjblJwWm1sallYUnBiMjRnUVhWMGFHOXlhWFI1TVJNd0VRWURWUVFLREFwQmNIQnNaU0JKYm1NdU1Rc3dDUVlEVlFRR0V3SlZVekFlRncweE9UQTFNVGd3TVRNeU5UZGFGdzB5TkRBMU1UWXdNVE15TlRkYU1GOHhKVEFqQmdOVkJBTU1IR1ZqWXkxemJYQXRZbkp2YTJWeUxYTnBaMjVmVlVNMExWQlNUMFF4RkRBU0JnTlZCQXNNQzJsUFV5QlRlWE4wWlcxek1STXdFUVlEVlFRS0RBcEJjSEJzWlNCSmJtTXVNUXN3Q1FZRFZRUUdFd0pWVXpCWk1CTUdCeXFHU000OUFnRUdDQ3FHU000OUF3RUhBMElBQk1JVmQrM3Ixc2V5SVk5bzNYQ1FvU0dOeDdDOWJ5d29QWVJnbGRsSzlLVkJHNE5DRHRnUjgwQitnek1mSEZURDkrc3lJTmE2MWRUdjlKS0ppVDU4RHhPamdnSVJNSUlDRFRBTUJnTlZIUk1CQWY4RUFqQUFNQjhHQTFVZEl3UVlNQmFBRkNQeVNjUlBrK1R2SitiRTlpaHNQNks3L1M1TE1FVUdDQ3NHQVFVRkJ3RUJCRGt3TnpBMUJnZ3JCZ0VGQlFjd0FZWXBhSFIwY0RvdkwyOWpjM0F1WVhCd2JHVXVZMjl0TDI5amMzQXdOQzFoY0hCc1pXRnBZMkV6TURJd2dnRWRCZ05WSFNBRWdnRVVNSUlCRURDQ0FRd0dDU3FHU0liM1kyUUZBVENCL2pDQnd3WUlLd1lCQlFVSEFnSXdnYllNZ2JOU1pXeHBZVzVqWlNCdmJpQjBhR2x6SUdObGNuUnBabWxqWVhSbElHSjVJR0Z1ZVNCd1lYSjBlU0JoYzNOMWJXVnpJR0ZqWTJWd2RHRnVZMlVnYjJZZ2RHaGxJSFJvWlc0Z1lYQndiR2xqWVdKc1pTQnpkR0Z1WkdGeVpDQjBaWEp0Y3lCaGJtUWdZMjl1WkdsMGFXOXVjeUJ2WmlCMWMyVXNJR05sY25ScFptbGpZWFJsSUhCdmJHbGplU0JoYm1RZ1kyVnlkR2xtYVdOaGRHbHZiaUJ3Y21GamRHbGpaU0J6ZEdGMFpXMWxiblJ6TGpBMkJnZ3JCZ0VGQlFjQ0FSWXFhSFIwY0RvdkwzZDNkeTVoY0hCc1pTNWpiMjB2WTJWeWRHbG1hV05oZEdWaGRYUm9iM0pwZEhrdk1EUUdBMVVkSHdRdE1Dc3dLYUFub0NXR0kyaDBkSEE2THk5amNtd3VZWEJ3YkdVdVkyOXRMMkZ3Y0d4bFlXbGpZVE11WTNKc01CMEdBMVVkRGdRV0JCU1VWOXR2MVhTQmhvbUpkaTkrVjRVSDU1dFlKREFPQmdOVkhROEJBZjhFQkFNQ0I0QXdEd1lKS29aSWh2ZGpaQVlkQkFJRkFEQUtCZ2dxaGtqT1BRUURBZ05KQURCR0FpRUF2Z2xYSCtjZUhuTmJWZVd2ckxUSEwrdEVYekFZVWlMSEpSQUN0aDY5YjFVQ0lRRFJpelVLWGRiZGJyRjBZRFd4SHJMT2g4K2o1cTlzdllPQWlRM0lMTjJxWXpDQ0F1NHdnZ0oxb0FNQ0FRSUNDRWx0TDc4Nm1OcVhNQW9HQ0NxR1NNNDlCQU1DTUdjeEd6QVpCZ05WQkFNTUVrRndjR3hsSUZKdmIzUWdRMEVnTFNCSE16RW1NQ1FHQTFVRUN3d2RRWEJ3YkdVZ1EyVnlkR2xtYVdOaGRHbHZiaUJCZFhSb2IzSnBkSGt4RXpBUkJnTlZCQW9NQ2tGd2NHeGxJRWx1WXk0eEN6QUpCZ05WQkFZVEFsVlRNQjRYRFRFME1EVXdOakl6TkRZek1Gb1hEVEk1TURVd05qSXpORFl6TUZvd2VqRXVNQ3dHQTFVRUF3d2xRWEJ3YkdVZ1FYQndiR2xqWVhScGIyNGdTVzUwWldkeVlYUnBiMjRnUTBFZ0xTQkhNekVtTUNRR0ExVUVDd3dkUVhCd2JHVWdRMlZ5ZEdsbWFXTmhkR2x2YmlCQmRYUm9iM0pwZEhreEV6QVJCZ05WQkFvTUNrRndjR3hsSUVsdVl5NHhDekFKQmdOVkJBWVRBbFZUTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFOEJjUmhCblhaSVhWR2w0bGdRZDI2SUNpNzk1N3JrM2dqZnhMaytFelZ0Vm1Xeld1SXRDWGRnMGlUbnU2Q1AxMkY4Nkl5M2E3Wm5DK3lPZ3BoUDlVUmFPQjl6Q0I5REJHQmdnckJnRUZCUWNCQVFRNk1EZ3dOZ1lJS3dZQkJRVUhNQUdHS21oMGRIQTZMeTl2WTNOd0xtRndjR3hsTG1OdmJTOXZZM053TURRdFlYQndiR1Z5YjI5MFkyRm5NekFkQmdOVkhRNEVGZ1FVSS9KSnhFK1Q1TzhuNXNUMktHdy9vcnY5TGtzd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZkJnTlZIU01FR0RBV2dCUzdzTjZoV0RPSW1xU0ttZDYrdmV1djJzc2txekEzQmdOVkhSOEVNREF1TUN5Z0txQW9oaVpvZEhSd09pOHZZM0pzTG1Gd2NHeGxMbU52YlM5aGNIQnNaWEp2YjNSallXY3pMbU55YkRBT0JnTlZIUThCQWY4RUJBTUNBUVl3RUFZS0tvWklodmRqWkFZQ0RnUUNCUUF3Q2dZSUtvWkl6ajBFQXdJRFp3QXdaQUl3T3M5eWcxRVdtYkdHK3pYRFZzcGl2L1FYN2RrUGRVMmlqcjd4bklGZVFyZUorSmozbTFtZm1OVkJEWStkNmNMK0FqQXlMZFZFSWJDakJYZHNYZk00TzVCbi9SZDhMQ0Z0bGsvR2NtbUNFbTlVK0hwOUc1bkxtd21KSVdFR21ROEpraDBBQURHQ0FZZ3dnZ0dFQWdFQk1JR0dNSG94TGpBc0JnTlZCQU1NSlVGd2NHeGxJRUZ3Y0d4cFkyRjBhVzl1SUVsdWRHVm5jbUYwYVc5dUlFTkJJQzBnUnpNeEpqQWtCZ05WQkFzTUhVRndjR3hsSUVObGNuUnBabWxqWVhScGIyNGdRWFYwYUc5eWFYUjVNUk13RVFZRFZRUUtEQXBCY0hCc1pTQkpibU11TVFzd0NRWURWUVFHRXdKVlV3SUlUREJCU1ZHZFZEWXdDd1lKWUlaSUFXVURCQUlCb0lHVE1CZ0dDU3FHU0liM0RRRUpBekVMQmdrcWhraUc5dzBCQndFd0hBWUpLb1pJaHZjTkFRa0ZNUThYRFRJME1ETXhOREE1TkRNeU0xb3dLQVlKS29aSWh2Y05BUWswTVJzdNTdMRElUVUQwcVI3RHd5SGx1VG0xMjJCejA5c2FzMkJVWitFRTlVPSIsImVwaGVtZXJhbFB1YmxpY0tleSI6Ik1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRXBoMkNUKytubXZpYjU3YWNJZmVKTjFCQmJyZUEveG84N2p1b0xETDFnS1IvYy9wRDZYK0xKSGRYUGJnMFBIT3pYYjJFYm5RR1ZWYmZIWHRkQzBYTTdBPT0iLCJ0cmFuc2FjdGlvbklkIjoiMjBlYzhlM2I2N2YyYmNmMDExMDVmODAwNmEwNWFmNTRiNjBkZDIwMzgyOTdlMmExMmI0Y2FlNDY0ODhjYjZhOSJ9LCJ2ZXJzaW9uIjoiRUNfdjEifQ==",
                "payment_method": {
                    "display_name": "Visa 0326",
                    "network": "Mastercard",
                    "type": "debit"
                },
                "transaction_identifier": "55CC32D7BF7890B9064433F15B9F23F849CF84AFD01E4E65DD8ADE306300E9D8"
            }
        }
    }
}
```
-> Since no dynamic fields was not added for stripe the `required_billing_contact_fields` is `null`
<img width="1133" alt="image" src="https://github.com/juspay/hyperswitch/assets/83439957/e4708058-ca0f-4d9c-8cc9-032097d9a5f1">

-> Create MCA create for cybersource
-> Apple pay payment create with confirm false
```
{
    "amount": 650,
    "currency": "USD",
    "confirm": false,
    "business_country": "US",
    "business_label": "default",
    "amount_to_capture": 650,
    "customer_id": "custhype1232",
    "capture_method": "automatic",
    "capture_on": "2022-09-10T10:11:12Z",
    "authentication_type": "three_ds",
    "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",
    "payment_method": "wallet",
    "payment_method_type": "apple_pay",
    "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"
        }
    },
    "payment_method_data": {
        "wallet": {
            "apple_pay": {
                "payment_data":"eyJkYXRhIjoiQ1ZoTGd5RGU3TzZjdFlhWHFiVWFONFZvRjBCQjhTbDZsenlXYUdCKzhKcXlic2hYVGxoNEFEcTZYb0t6ZWVSVGwvcUp6NDIvUFMwcmMxMCtqSyt5Z1F5NnlkT25EcnVDeVpkaVU4SWFGOEtOS2hJMFFKOU9JTk9aWFlYR0VzZEczNXlVNzcrQ0k1dk5lUjJiK1gyUXZTVTMzSjlOczJuTFRXZHpwb1VUSHJKU1RiSmFmTTlxYjlZOHZuZS9vZUdHQkV1ZU9DQWQxcFhjRE54SEl2dlc5Z0x3WXRPVldKZUEvUnh5MEdsb0VISng3VEhqUEVQUGJwMkVVZjRMQXZQOGlJSEpmUjM0THdEUVBIdmNSeW9nalRJSzJqOXZjUGRqS2xBSG1LUm5wZlhvWkY4VE16ZUJ6eWhGb0dKY3ZRa3JMc216OEcxTXowZGxlV2VmU2V0TkYxT1NMaldCdExrUXpvWG5xdU1ZeExMenU2SkxPZ1E5ejN1OStFNGQ2NHRZS1NYYlZBWGRKNXRMNTdvbSIsInNpZ25hdHVyZSI6Ik1JQUdDU3FHU0liM0RRRUhBcUNBTUlBQ0FRRXhEVEFMQmdsZ2hrZ0JaUU1FQWdFd2dBWUpLb1pJaHZjTkFRY0JBQUNnZ0RDQ0ErTXdnZ09Jb0FNQ0FRSUNDRXd3UVVsUm5WUTJNQW9HQ0NxR1NNNDlCQU1DTUhveExqQXNCZ05WQkFNTUpVRndjR3hsSUVGd2NHeHBZMkYwYVc5dUlFbHVkR1ZuY21GMGFXOXVJRU5CSUMwZ1J6TXhKakFrQmdOVkJBc01IVUZ3Y0d4bElFTmxjblJwWm1sallYUnBiMjRnUVhWMGFHOXlhWFI1TVJNd0VRWURWUVFLREFwQmNIQnNaU0JKYm1NdU1Rc3dDUVlEVlFRR0V3SlZVekFlRncweE9UQTFNVGd3TVRNeU5UZGFGdzB5TkRBMU1UWXdNVE15TlRkYU1GOHhKVEFqQmdOVkJBTU1IR1ZqWXkxemJYQXRZbkp2YTJWeUxYTnBaMjVmVlVNMExWQlNUMFF4RkRBU0JnTlZCQXNNQzJsUFV5QlRlWE4wWlcxek1STXdFUVlEVlFRS0RBcEJjSEJzWlNCSmJtTXVNUXN3Q1FZRFZRUUdFd0pWVXpCWk1CTUdCeXFHU000OUFnRUdDQ3FHU000OUF3RUhBMElBQk1JVmQrM3Ixc2V5SVk5bzNYQ1FvU0dOeDdDOWJ5d29QWVJnbGRsSzlLVkJHNE5DRHRnUjgwQitnek1mSEZURDkrc3lJTmE2MWRUdjlKS0ppVDU4RHhPamdnSVJNSUlDRFRBTUJnTlZIUk1CQWY4RUFqQUFNQjhHQTFVZEl3UVlNQmFBRkNQeVNjUlBrK1R2SitiRTlpaHNQNks3L1M1TE1FVUdDQ3NHQVFVRkJ3RUJCRGt3TnpBMUJnZ3JCZ0VGQlFjd0FZWXBhSFIwY0RvdkwyOWpjM0F1WVhCd2JHVXVZMjl0TDI5amMzQXdOQzFoY0hCc1pXRnBZMkV6TURJd2dnRWRCZ05WSFNBRWdnRVVNSUlCRURDQ0FRd0dDU3FHU0liM1kyUUZBVENCL2pDQnd3WUlLd1lCQlFVSEFnSXdnYllNZ2JOU1pXeHBZVzVqWlNCdmJpQjBhR2x6SUdObGNuUnBabWxqWVhSbElHSjVJR0Z1ZVNCd1lYSjBlU0JoYzNOMWJXVnpJR0ZqWTJWd2RHRnVZMlVnYjJZZ2RHaGxJSFJvWlc0Z1lYQndiR2xqWVdKc1pTQnpkR0Z1WkdGeVpDQjBaWEp0Y3lCaGJtUWdZMjl1WkdsMGFXOXVjeUJ2WmlCMWMyVXNJR05sY25ScFptbGpZWFJsSUhCdmJHbGplU0JoYm1RZ1kyVnlkR2xtYVdOaGRHbHZiaUJ3Y21GamRHbGpaU0J6ZEdGMFpXMWxiblJ6TGpBMkJnZ3JCZ0VGQlFjQ0FSWXFhSFIwY0RvdkwzZDNkeTVoY0hCc1pTNWpiMjB2WTJWeWRHbG1hV05oZEdWaGRYUm9iM0pwZEhrdk1EUUdBMVVkSHdRdE1Dc3dLYUFub0NXR0kyaDBkSEE2THk5amNtd3VZWEJ3YkdVdVkyOXRMMkZ3Y0d4bFlXbGpZVE11WTNKc01CMEdBMVVkRGdRV0JCU1VWOXR2MVhTQmhvbUpkaTkrVjRVSDU1dFlKREFPQmdOVkhROEJBZjhFQkFNQ0I0QXdEd1lKS29aSWh2ZGpaQVlkQkFJRkFEQUtCZ2dxaGtqT1BRUURBZ05KQURCR0FpRUF2Z2xYSCtjZUhuTmJWZVd2ckxUSEwrdEVYekFZVWlMSEpSQUN0aDY5YjFVQ0lRRFJpelVLWGRiZGJyRjBZRFd4SHJMT2g4K2o1cTlzdllPQWlRM0lMTjJxWXpDQ0F1NHdnZ0oxb0FNQ0FRSUNDRWx0TDc4Nm1OcVhNQW9HQ0NxR1NNNDlCQU1DTUdjeEd6QVpCZ05WQkFNTUVrRndjR3hsSUZKdmIzUWdRMEVnTFNCSE16RW1NQ1FHQTFVRUN3d2RRWEJ3YkdVZ1EyVnlkR2xtYVdOaGRHbHZiaUJCZFhSb2IzSnBkSGt4RXpBUkJnTlZCQW9NQ2tGd2NHeGxJRWx1WXk0eEN6QUpCZ05WQkFZVEFsVlRNQjRYRFRFME1EVXdOakl6TkRZek1Gb1hEVEk1TURVd05qSXpORFl6TUZvd2VqRXVNQ3dHQTFVRUF3d2xRWEJ3YkdVZ1FYQndiR2xqWVhScGIyNGdTVzUwWldkeVlYUnBiMjRnUTBFZ0xTQkhNekVtTUNRR0ExVUVDd3dkUVhCd2JHVWdRMlZ5ZEdsbWFXTmhkR2x2YmlCQmRYUm9iM0pwZEhreEV6QVJCZ05WQkFvTUNrRndjR3hsSUVsdVl5NHhDekFKQmdOVkJBWVRBbFZUTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFOEJjUmhCblhaSVhWR2w0bGdRZDI2SUNpNzk1N3JrM2dqZnhMaytFelZ0Vm1Xeld1SXRDWGRnMGlUbnU2Q1AxMkY4Nkl5M2E3Wm5DK3lPZ3BoUDlVUmFPQjl6Q0I5REJHQmdnckJnRUZCUWNCQVFRNk1EZ3dOZ1lJS3dZQkJRVUhNQUdHS21oMGRFCQmJyZUEveG84N2p1b0xETDFnS1IvYy9wRDZYK0xKSGRYUGJnMFBIT3pYYjJFYm5RR1ZWYmZIWHRkQzBYTTdBPT0iLCJ0cmFuc2FjdGlvbklkIjoiMjBlYzhlM2I2N2YyYmNmMDExMDVmODAwNmEwNWFmNTRiNjBkZDIwMzgyOTdlMmExMmI0Y2FlNDY0ODhjYjZhOSJ9LCJ2ZXJzaW9uIjoiRUNfdjEifQ==",
                "payment_method": {
                    "display_name": "Visa 0326",
                    "network": "Mastercard",
                    "type": "debit"
                },
                "transaction_identifier": "55CC32D7BF7890B9064433F15B9F23F849CF84AFD01E4E65DD8ADE306300E9D8"
            }
        }
    }
}
```

<img width="1109" alt="image" src="https://github.com/juspay/hyperswitch/assets/83439957/36aec432-6c2b-4bcf-a9ed-d5849fe96b19">

-> Session call having the `required_billing_contact_fields` being passed as the dynamic fields are present
<img width="1140" alt="image" src="https://github.com/juspay/hyperswitch/assets/83439957/e9d7a960-7d79-42a7-bbb6-4776cadc8fd5">


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