Issue:
Bug: [BUG] mandate_data is being passed in Response but not in Request while creating/updating/confirming payment intents



### Bug Description

The field `mandate_data` is being populated while processing the request but it's not a request body parameter itself. Add it as a request body parameter in `StripePaymentIntentRequest` struct.

### Have you spent some time to check if this bug has been raised before?

- [X] I checked and didn't find similar issue

### Have you read the Contributing Guidelines?

- [X] I have read the [Contributing Guidelines](https://github.com/juspay/hyperswitch/blob/main/docs/CONTRIBUTING.md)

### Are you willing to submit a PR?

Yes I am willing to submit a PR!

Pull request description:
## Type of Change
<!-- Put an `x` in the boxes that apply -->

- [x] Bugfix
- [x] New feature

## Description
<!-- Describe your changes in detail -->
This PR adds new fields, enums and structs and does the corresponding mappings wherever required.

## Motivation and Context
<!--
Why is this change required? What problem does it solve?
If it fixes an open issue, please link to the issue here.

If you don't have an issue, we'd recommend starting with one first so the PR
can focus on the implementation (unless its an obvious bug or documentation fix
that will have little conversation).
-->
This PR solves these issues :

https://github.com/juspay/hyperswitch/issues/1615
https://github.com/juspay/hyperswitch/issues/1616
https://github.com/juspay/hyperswitch/issues/1618
https://github.com/juspay/hyperswitch/issues/1632

## 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)?
-->
Manually

## Checklist
<!-- Put an `x` in the boxes that apply -->

- [x] I formatted the code `cargo +nightly fmt --all`
- [x] I addressed lints thrown by `cargo clippy`
- [x] I reviewed submitted code

Testing:

Manually

Patch:
diff --git a/crates/router/src/compatibility/stripe/payment_intents/types.rs b/crates/router/src/compatibility/stripe/payment_intents/types.rs
index de8af66214d..e06b264cef2 100644
--- a/crates/router/src/compatibility/stripe/payment_intents/types.rs
+++ b/crates/router/src/compatibility/stripe/payment_intents/types.rs
@@ -1,15 +1,21 @@
 use std::str::FromStr;
 
 use api_models::payments;
-use common_utils::{crypto::Encryptable, date_time, ext_traits::StringExt, pii as secret};
+use common_utils::{
+    crypto::Encryptable,
+    date_time,
+    ext_traits::StringExt,
+    pii::{IpAddress, SecretSerdeValue},
+};
 use error_stack::{IntoReport, ResultExt};
 use serde::{Deserialize, Serialize};
+use time::PrimitiveDateTime;
 
 use crate::{
     compatibility::stripe::refunds::types as stripe_refunds,
     consts,
     core::errors,
-    pii::{self, Email, PeekInterface},
+    pii::{Email, PeekInterface},
     types::{
         api::{admin, enums as api_enums},
         transformers::{ForeignFrom, ForeignTryFrom},
@@ -21,7 +27,7 @@ pub struct StripeBillingDetails {
     pub address: Option<payments::AddressDetails>,
     pub email: Option<Email>,
     pub name: Option<String>,
-    pub phone: Option<pii::Secret<String>>,
+    pub phone: Option<masking::Secret<String>>,
 }
 
 impl From<StripeBillingDetails> for payments::Address {
@@ -42,10 +48,10 @@ impl From<StripeBillingDetails> for payments::Address {
 #[derive(Default, Serialize, PartialEq, Eq, Deserialize, Clone, Debug)]
 pub struct StripeCard {
     pub number: cards::CardNumber,
-    pub exp_month: pii::Secret<String>,
-    pub exp_year: pii::Secret<String>,
-    pub cvc: pii::Secret<String>,
-    pub holder_name: Option<pii::Secret<String>>,
+    pub exp_month: masking::Secret<String>,
+    pub exp_year: masking::Secret<String>,
+    pub cvc: masking::Secret<String>,
+    pub holder_name: Option<masking::Secret<String>>,
 }
 
 #[derive(Serialize, PartialEq, Eq, Deserialize, Clone)]
@@ -78,7 +84,7 @@ pub struct StripePaymentMethodData {
     pub billing_details: Option<StripeBillingDetails>,
     #[serde(flatten)]
     pub payment_method_details: Option<StripePaymentMethodDetails>, // enum
-    pub metadata: Option<secret::SecretSerdeValue>,
+    pub metadata: Option<SecretSerdeValue>,
 }
 
 #[derive(PartialEq, Eq, Deserialize, Clone)]
@@ -127,11 +133,21 @@ impl From<StripePaymentMethodDetails> for payments::PaymentMethodData {
 
 #[derive(Default, Serialize, PartialEq, Eq, Deserialize, Clone)]
 pub struct Shipping {
-    pub address: Option<payments::AddressDetails>,
-    pub name: Option<String>,
+    pub address: AddressDetails,
+    pub name: Option<masking::Secret<String>>,
     pub carrier: Option<String>,
-    pub phone: Option<pii::Secret<String>>,
-    pub tracking_number: Option<pii::Secret<String>>,
+    pub phone: Option<masking::Secret<String>>,
+    pub tracking_number: Option<masking::Secret<String>>,
+}
+
+#[derive(Default, Serialize, PartialEq, Eq, Deserialize, Clone)]
+pub struct AddressDetails {
+    pub city: Option<String>,
+    pub country: Option<api_enums::CountryAlpha2>,
+    pub line1: Option<masking::Secret<String>>,
+    pub line2: Option<masking::Secret<String>>,
+    pub postal_code: Option<masking::Secret<String>>,
+    pub state: Option<masking::Secret<String>>,
 }
 
 impl From<Shipping> for payments::Address {
@@ -139,19 +155,61 @@ impl From<Shipping> for payments::Address {
         Self {
             phone: Some(payments::PhoneDetails {
                 number: details.phone,
-                country_code: details.address.as_ref().and_then(|address| {
-                    address.country.as_ref().map(|country| country.to_string())
-                }),
+                country_code: details.address.country.map(|country| country.to_string()),
+            }),
+            address: Some(payments::AddressDetails {
+                city: details.address.city,
+                country: details.address.country,
+                line1: details.address.line1,
+                line2: details.address.line2,
+                zip: details.address.postal_code,
+                state: details.address.state,
+                first_name: details.name,
+                line3: None,
+                last_name: None,
             }),
-            address: details.address,
         }
     }
 }
 
+#[derive(Default, Serialize, PartialEq, Eq, Deserialize, Clone)]
+pub struct MandateData {
+    pub customer_acceptance: CustomerAcceptance,
+    pub mandate_type: Option<StripeMandateType>,
+    pub amount: Option<i64>,
+    #[serde(default, with = "common_utils::custom_serde::timestamp::option")]
+    pub start_date: Option<PrimitiveDateTime>,
+    #[serde(default, with = "common_utils::custom_serde::timestamp::option")]
+    pub end_date: Option<PrimitiveDateTime>,
+}
+
+#[derive(Default, Serialize, PartialEq, Eq, Deserialize, Clone)]
+pub struct CustomerAcceptance {
+    #[serde(rename = "type")]
+    pub acceptance_type: Option<AcceptanceType>,
+    pub accepted_at: Option<PrimitiveDateTime>,
+    pub online: Option<OnlineMandate>,
+}
+
+#[derive(Default, Debug, serde::Deserialize, serde::Serialize, PartialEq, Eq, Clone)]
+#[serde(rename_all = "lowercase")]
+pub enum AcceptanceType {
+    Online,
+    #[default]
+    Offline,
+}
+
+#[derive(Default, Eq, PartialEq, Debug, serde::Deserialize, serde::Serialize, Clone)]
+#[serde(deny_unknown_fields)]
+pub struct OnlineMandate {
+    pub ip_address: masking::Secret<String, IpAddress>,
+    pub user_agent: String,
+}
+
 #[derive(Deserialize, Clone)]
 pub struct StripePaymentIntentRequest {
     pub id: Option<String>,
-    pub amount: Option<i64>, //amount in cents, hence passed as integer
+    pub amount: Option<i64>, // amount in cents, hence passed as integer
     pub connector: Option<Vec<api_enums::RoutableConnectors>>,
     pub currency: Option<String>,
     #[serde(rename = "amount_to_capture")]
@@ -167,39 +225,26 @@ pub struct StripePaymentIntentRequest {
     pub shipping: Option<Shipping>,
     pub statement_descriptor: Option<String>,
     pub statement_descriptor_suffix: Option<String>,
-    pub metadata: Option<secret::SecretSerdeValue>,
-    pub client_secret: Option<pii::Secret<String>>,
+    pub metadata: Option<SecretSerdeValue>,
+    pub client_secret: Option<masking::Secret<String>>,
     pub payment_method_options: Option<StripePaymentMethodOptions>,
     pub merchant_connector_details: Option<admin::MerchantConnectorDetailsWrap>,
-    pub mandate_id: Option<String>,
+    pub mandate: Option<String>,
     pub off_session: Option<bool>,
-    pub payment_method_type: Option<api_enums::PaymentMethodType>,
+    pub payment_method_types: Option<api_enums::PaymentMethodType>,
     pub receipt_ipaddress: Option<String>,
     pub user_agent: Option<String>,
+    pub mandate_data: Option<MandateData>,
+    pub automatic_payment_methods: Option<SecretSerdeValue>, // not used
+    pub payment_method: Option<String>,                      // not used
+    pub confirmation_method: Option<String>,                 // not used
+    pub error_on_requires_action: Option<String>,            // not used
+    pub radar_options: Option<SecretSerdeValue>,             // not used
 }
 
 impl TryFrom<StripePaymentIntentRequest> for payments::PaymentsRequest {
     type Error = error_stack::Report<errors::ApiErrorResponse>;
     fn try_from(item: StripePaymentIntentRequest) -> errors::RouterResult<Self> {
-        let (mandate_options, authentication_type) = match item.payment_method_options {
-            Some(pmo) => {
-                let StripePaymentMethodOptions::Card {
-                    request_three_d_secure,
-                    mandate_options,
-                }: StripePaymentMethodOptions = pmo;
-                (
-                    Option::<payments::MandateData>::foreign_try_from((
-                        mandate_options,
-                        item.currency.to_owned(),
-                    ))?,
-                    Some(api_enums::AuthenticationType::foreign_from(
-                        request_three_d_secure,
-                    )),
-                )
-            }
-            None => (None, None),
-        };
-
         let routable_connector: Option<api_enums::RoutableConnectors> =
             item.connector.and_then(|v| v.into_iter().next());
 
@@ -262,13 +307,26 @@ impl TryFrom<StripePaymentIntentRequest> for payments::PaymentsRequest {
             statement_descriptor_suffix: item.statement_descriptor_suffix,
             metadata: item.metadata,
             client_secret: item.client_secret.map(|s| s.peek().clone()),
-            authentication_type,
-            mandate_data: mandate_options,
+            authentication_type: match item.payment_method_options {
+                Some(pmo) => {
+                    let StripePaymentMethodOptions::Card {
+                        request_three_d_secure,
+                    }: StripePaymentMethodOptions = pmo;
+                    Some(api_enums::AuthenticationType::foreign_from(
+                        request_three_d_secure,
+                    ))
+                }
+                None => None,
+            },
+            mandate_data: ForeignTryFrom::foreign_try_from((
+                item.mandate_data,
+                item.currency.to_owned(),
+            ))?,
             merchant_connector_details: item.merchant_connector_details,
             setup_future_usage: item.setup_future_usage,
-            mandate_id: item.mandate_id,
+            mandate_id: item.mandate,
             off_session: item.off_session,
-            payment_method_type: item.payment_method_type,
+            payment_method_type: item.payment_method_types,
             routing,
             browser_info: Some(
                 serde_json::to_value(crate::types::BrowserInformation {
@@ -280,6 +338,7 @@ impl TryFrom<StripePaymentIntentRequest> for payments::PaymentsRequest {
                 .change_context(errors::ApiErrorResponse::InternalServerError)
                 .attach_printable("convert to browser info failed")?,
             ),
+
             ..Self::default()
         });
         request
@@ -334,6 +393,7 @@ impl ToString for CancellationReason {
         })
     }
 }
+
 #[derive(Debug, Deserialize, Serialize, Copy, Clone)]
 pub struct StripePaymentCancelRequest {
     cancellation_reason: Option<CancellationReason>,
@@ -348,11 +408,6 @@ impl From<StripePaymentCancelRequest> for payments::PaymentsCancelRequest {
     }
 }
 
-#[derive(Default, PartialEq, Eq, Deserialize, Clone)]
-pub struct StripeCaptureRequest {
-    pub amount_to_capture: Option<i64>,
-}
-
 #[derive(Default, Eq, PartialEq, Serialize, Debug)]
 pub struct StripePaymentIntentResponse {
     pub id: Option<String>,
@@ -366,8 +421,8 @@ pub struct StripePaymentIntentResponse {
     pub created: Option<i64>,
     pub customer: Option<String>,
     pub refunds: Option<Vec<stripe_refunds::StripeRefundResponse>>,
-    pub mandate_id: Option<String>,
-    pub metadata: Option<secret::SecretSerdeValue>,
+    pub mandate: Option<String>,
+    pub metadata: Option<SecretSerdeValue>,
     pub charges: Charges,
     pub connector: Option<String>,
     pub description: Option<String>,
@@ -382,7 +437,7 @@ pub struct StripePaymentIntentResponse {
     pub shipping: Option<payments::Address>,
     pub billing: Option<payments::Address>,
     #[serde(with = "common_utils::custom_serde::iso8601::option")]
-    pub capture_on: Option<time::PrimitiveDateTime>,
+    pub capture_on: Option<PrimitiveDateTime>,
     pub payment_token: Option<String>,
     pub email: Option<Email>,
     pub phone: Option<masking::Secret<String>>,
@@ -423,7 +478,7 @@ impl From<payments::PaymentsResponse> for StripePaymentIntentResponse {
             refunds: resp
                 .refunds
                 .map(|a| a.into_iter().map(Into::into).collect()),
-            mandate_id: resp.mandate_id,
+            mandate: resp.mandate_id,
             mandate_data: resp.mandate_data,
             setup_future_usage: resp.setup_future_usage,
             off_session: resp.off_session,
@@ -543,7 +598,7 @@ impl TryFrom<StripePaymentListConstraints> for payments::PaymentListConstraints
 #[inline]
 fn from_timestamp_to_datetime(
     time: Option<i64>,
-) -> Result<Option<time::PrimitiveDateTime>, errors::ApiErrorResponse> {
+) -> Result<Option<PrimitiveDateTime>, errors::ApiErrorResponse> {
     if let Some(time) = time {
         let time = time::OffsetDateTime::from_unix_timestamp(time).map_err(|_| {
             errors::ApiErrorResponse::InvalidRequestData {
@@ -581,7 +636,6 @@ impl From<payments::PaymentListResponse> for StripePaymentIntentListResponse {
 pub enum StripePaymentMethodOptions {
     Card {
         request_three_d_secure: Option<Request3DS>,
-        mandate_options: Option<MandateOption>,
     },
 }
 
@@ -595,21 +649,21 @@ pub enum StripeMandateType {
 #[derive(PartialEq, Eq, Clone, Default, Deserialize, Serialize, Debug)]
 pub struct MandateOption {
     #[serde(default, with = "common_utils::custom_serde::timestamp::option")]
-    pub accepted_at: Option<time::PrimitiveDateTime>,
+    pub accepted_at: Option<PrimitiveDateTime>,
     pub user_agent: Option<String>,
-    pub ip_address: Option<pii::Secret<String, common_utils::pii::IpAddress>>,
+    pub ip_address: Option<masking::Secret<String, IpAddress>>,
     pub mandate_type: Option<StripeMandateType>,
     pub amount: Option<i64>,
     #[serde(default, with = "common_utils::custom_serde::timestamp::option")]
-    pub start_date: Option<time::PrimitiveDateTime>,
+    pub start_date: Option<PrimitiveDateTime>,
     #[serde(default, with = "common_utils::custom_serde::timestamp::option")]
-    pub end_date: Option<time::PrimitiveDateTime>,
+    pub end_date: Option<PrimitiveDateTime>,
 }
 
-impl ForeignTryFrom<(Option<MandateOption>, Option<String>)> for Option<payments::MandateData> {
+impl ForeignTryFrom<(Option<MandateData>, Option<String>)> for Option<payments::MandateData> {
     type Error = error_stack::Report<errors::ApiErrorResponse>;
     fn foreign_try_from(
-        (mandate_options, currency): (Option<MandateOption>, Option<String>),
+        (mandate_data, currency): (Option<MandateData>, Option<String>),
     ) -> errors::RouterResult<Self> {
         let currency = currency
             .ok_or(errors::ApiErrorResponse::MissingRequiredField {
@@ -623,7 +677,7 @@ impl ForeignTryFrom<(Option<MandateOption>, Option<String>)> for Option<payments
                     },
                 )
             })?;
-        let mandate_data = mandate_options.map(|mandate| payments::MandateData {
+        let mandate_data = mandate_data.map(|mandate| payments::MandateData {
             mandate_type: match mandate.mandate_type {
                 Some(item) => match item {
                     StripeMandateType::SingleUse => Some(payments::MandateType::SingleUse(
@@ -641,11 +695,14 @@ impl ForeignTryFrom<(Option<MandateOption>, Option<String>)> for Option<payments
             },
             customer_acceptance: Some(payments::CustomerAcceptance {
                 acceptance_type: payments::AcceptanceType::Online,
-                accepted_at: mandate.accepted_at,
-                online: Some(payments::OnlineMandate {
-                    ip_address: mandate.ip_address,
-                    user_agent: mandate.user_agent.unwrap_or_default(),
-                }),
+                accepted_at: mandate.customer_acceptance.accepted_at,
+                online: mandate
+                    .customer_acceptance
+                    .online
+                    .map(|online| payments::OnlineMandate {
+                        ip_address: Some(online.ip_address),
+                        user_agent: online.user_agent,
+                    }),
             }),
         });
         Ok(mandate_data)
diff --git a/crates/router/src/compatibility/stripe/setup_intents/types.rs b/crates/router/src/compatibility/stripe/setup_intents/types.rs
index d4b6aac306b..5224228a968 100644
--- a/crates/router/src/compatibility/stripe/setup_intents/types.rs
+++ b/crates/router/src/compatibility/stripe/setup_intents/types.rs
@@ -147,29 +147,12 @@ pub struct StripeSetupIntentRequest {
     pub merchant_connector_details: Option<admin::MerchantConnectorDetailsWrap>,
     pub receipt_ipaddress: Option<String>,
     pub user_agent: Option<String>,
+    pub mandate_data: Option<payment_intent::MandateData>,
 }
 
 impl TryFrom<StripeSetupIntentRequest> for payments::PaymentsRequest {
     type Error = error_stack::Report<errors::ApiErrorResponse>;
     fn try_from(item: StripeSetupIntentRequest) -> errors::RouterResult<Self> {
-        let (mandate_options, authentication_type) = match item.payment_method_options {
-            Some(pmo) => {
-                let payment_intent::StripePaymentMethodOptions::Card {
-                    request_three_d_secure,
-                    mandate_options,
-                }: payment_intent::StripePaymentMethodOptions = pmo;
-                (
-                    Option::<payments::MandateData>::foreign_try_from((
-                        mandate_options,
-                        item.currency.to_owned(),
-                    ))?,
-                    Some(api_enums::AuthenticationType::foreign_from(
-                        request_three_d_secure,
-                    )),
-                )
-            }
-            None => (None, None),
-        };
         let routable_connector: Option<api_enums::RoutableConnectors> =
             item.connector.and_then(|v| v.into_iter().next());
 
@@ -243,9 +226,22 @@ impl TryFrom<StripeSetupIntentRequest> for payments::PaymentsRequest {
             client_secret: item.client_secret.map(|s| s.peek().clone()),
             setup_future_usage: item.setup_future_usage,
             merchant_connector_details: item.merchant_connector_details,
-            authentication_type,
             routing,
-            mandate_data: mandate_options,
+            authentication_type: match item.payment_method_options {
+                Some(pmo) => {
+                    let payment_intent::StripePaymentMethodOptions::Card {
+                        request_three_d_secure,
+                    }: payment_intent::StripePaymentMethodOptions = pmo;
+                    Some(api_enums::AuthenticationType::foreign_from(
+                        request_three_d_secure,
+                    ))
+                }
+                None => None,
+            },
+            mandate_data: ForeignTryFrom::foreign_try_from((
+                item.mandate_data,
+                item.currency.to_owned(),
+            ))?,
             browser_info: Some(
                 serde_json::to_value(crate::types::BrowserInformation {
                     ip_address,