Bug: [FEATURE] [Iatapay] add upi qr support 



### Feature Description

Add support for Upi QR code through Iatapay

### Possible Implementation

1. Add a upi intent payment id
2. Add a upi_qr payment data type
3. Do necessary contract changes


### 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 5f9618738b2..cd405e3ca98 100644
--- a/crates/api_models/src/payments.rs
+++ b/crates/api_models/src/payments.rs
@@ -1664,7 +1664,10 @@ impl GetPaymentMethodType for CryptoData {
 
 impl GetPaymentMethodType for UpiData {
     fn get_payment_method_type(&self) -> api_enums::PaymentMethodType {
-        api_enums::PaymentMethodType::UpiCollect
+        match self {
+            Self::UpiCollect(_) => api_enums::PaymentMethodType::UpiCollect,
+            Self::UpiIntent(_) => api_enums::PaymentMethodType::UpiIntent,
+        }
     }
 }
 impl GetPaymentMethodType for VoucherData {
@@ -2119,11 +2122,21 @@ pub struct CryptoData {
 
 #[derive(Debug, Clone, Eq, PartialEq, serde::Deserialize, serde::Serialize, ToSchema)]
 #[serde(rename_all = "snake_case")]
-pub struct UpiData {
+pub enum UpiData {
+    UpiCollect(UpiCollectData),
+    UpiIntent(UpiIntentData),
+}
+
+#[derive(Debug, Clone, Eq, PartialEq, serde::Deserialize, serde::Serialize, ToSchema)]
+#[serde(rename_all = "snake_case")]
+pub struct UpiCollectData {
     #[schema(value_type = Option<String>, example = "successtest@iata")]
     pub vpa_id: Option<Secret<String, pii::UpiVpaMaskingStrategy>>,
 }
 
+#[derive(Debug, Clone, Eq, PartialEq, serde::Deserialize, serde::Serialize, ToSchema)]
+pub struct UpiIntentData {}
+
 #[derive(Debug, Clone, Eq, PartialEq, serde::Deserialize, serde::Serialize, ToSchema)]
 pub struct SofortBilling {
     /// The country associated with the billing
@@ -2960,6 +2973,11 @@ pub enum NextActionData {
         /// The url for Qr code given by the connector
         qr_code_url: Option<Url>,
     },
+    /// Contains url to fetch Qr code data
+    FetchQrCodeInformation {
+        #[schema(value_type = String)]
+        qr_code_fetch_url: Url,
+    },
     /// Contains the download url and the reference number for transaction
     DisplayVoucherInformation {
         #[schema(value_type = String)]
@@ -3045,6 +3063,11 @@ pub struct SdkNextActionData {
     pub next_action: NextActionCall,
 }
 
+#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, ToSchema)]
+pub struct FetchQrCodeInformation {
+    pub qr_code_fetch_url: Url,
+}
+
 #[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize, ToSchema)]
 pub struct BankTransferNextStepsData {
     /// The instructions for performing a bank transfer
diff --git a/crates/common_enums/src/enums.rs b/crates/common_enums/src/enums.rs
index dc4ca6b2cb3..3df291d5681 100644
--- a/crates/common_enums/src/enums.rs
+++ b/crates/common_enums/src/enums.rs
@@ -1430,6 +1430,7 @@ pub enum PaymentMethodType {
     Trustly,
     Twint,
     UpiCollect,
+    UpiIntent,
     Vipps,
     Venmo,
     Walley,
diff --git a/crates/common_enums/src/transformers.rs b/crates/common_enums/src/transformers.rs
index faca2579c0a..cb37180c987 100644
--- a/crates/common_enums/src/transformers.rs
+++ b/crates/common_enums/src/transformers.rs
@@ -1854,6 +1854,7 @@ impl From<PaymentMethodType> for PaymentMethod {
             PaymentMethodType::Trustly => Self::BankRedirect,
             PaymentMethodType::Twint => Self::Wallet,
             PaymentMethodType::UpiCollect => Self::Upi,
+            PaymentMethodType::UpiIntent => Self::Upi,
             PaymentMethodType::Vipps => Self::Wallet,
             PaymentMethodType::Venmo => Self::Wallet,
             PaymentMethodType::Walley => Self::PayLater,
diff --git a/crates/euclid/src/frontend/dir/enums.rs b/crates/euclid/src/frontend/dir/enums.rs
index c5f864bf770..133fee18c0d 100644
--- a/crates/euclid/src/frontend/dir/enums.rs
+++ b/crates/euclid/src/frontend/dir/enums.rs
@@ -268,6 +268,7 @@ pub enum CryptoType {
 #[strum(serialize_all = "snake_case")]
 pub enum UpiType {
     UpiCollect,
+    UpiIntent,
 }
 
 #[derive(
diff --git a/crates/euclid/src/frontend/dir/lowering.rs b/crates/euclid/src/frontend/dir/lowering.rs
index f6b156bf909..cc4c9be2a2d 100644
--- a/crates/euclid/src/frontend/dir/lowering.rs
+++ b/crates/euclid/src/frontend/dir/lowering.rs
@@ -75,6 +75,7 @@ impl From<enums::UpiType> for global_enums::PaymentMethodType {
     fn from(value: enums::UpiType) -> Self {
         match value {
             enums::UpiType::UpiCollect => Self::UpiCollect,
+            enums::UpiType::UpiIntent => Self::UpiIntent,
         }
     }
 }
diff --git a/crates/euclid/src/frontend/dir/transformers.rs b/crates/euclid/src/frontend/dir/transformers.rs
index bcc951b0057..052561b5aab 100644
--- a/crates/euclid/src/frontend/dir/transformers.rs
+++ b/crates/euclid/src/frontend/dir/transformers.rs
@@ -109,6 +109,7 @@ impl IntoDirValue for (global_enums::PaymentMethodType, global_enums::PaymentMet
             }
             global_enums::PaymentMethodType::Evoucher => Ok(dirval!(RewardType = Evoucher)),
             global_enums::PaymentMethodType::UpiCollect => Ok(dirval!(UpiType = UpiCollect)),
+            global_enums::PaymentMethodType::UpiIntent => Ok(dirval!(UpiType = UpiIntent)),
             global_enums::PaymentMethodType::SamsungPay => Ok(dirval!(WalletType = SamsungPay)),
             global_enums::PaymentMethodType::GoPay => Ok(dirval!(WalletType = GoPay)),
             global_enums::PaymentMethodType::KakaoPay => Ok(dirval!(WalletType = KakaoPay)),
diff --git a/crates/hyperswitch_domain_models/src/payment_method_data.rs b/crates/hyperswitch_domain_models/src/payment_method_data.rs
index 9dc85c103e9..7517918ed95 100644
--- a/crates/hyperswitch_domain_models/src/payment_method_data.rs
+++ b/crates/hyperswitch_domain_models/src/payment_method_data.rs
@@ -289,10 +289,20 @@ pub struct CryptoData {
 
 #[derive(Debug, Clone, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
 #[serde(rename_all = "snake_case")]
-pub struct UpiData {
+pub enum UpiData {
+    UpiCollect(UpiCollectData),
+    UpiIntent(UpiIntentData),
+}
+
+#[derive(Debug, Clone, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
+#[serde(rename_all = "snake_case")]
+pub struct UpiCollectData {
     pub vpa_id: Option<Secret<String, pii::UpiVpaMaskingStrategy>>,
 }
 
+#[derive(Debug, Clone, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
+pub struct UpiIntentData {}
+
 #[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
 #[serde(rename_all = "snake_case")]
 pub enum VoucherData {
@@ -690,8 +700,12 @@ impl From<api_models::payments::CryptoData> for CryptoData {
 
 impl From<api_models::payments::UpiData> for UpiData {
     fn from(value: api_models::payments::UpiData) -> Self {
-        let api_models::payments::UpiData { vpa_id } = value;
-        Self { vpa_id }
+        match value {
+            api_models::payments::UpiData::UpiCollect(upi) => {
+                Self::UpiCollect(UpiCollectData { vpa_id: upi.vpa_id })
+            }
+            api_models::payments::UpiData::UpiIntent(_) => Self::UpiIntent(UpiIntentData {}),
+        }
     }
 }
 
diff --git a/crates/kgraph_utils/src/mca.rs b/crates/kgraph_utils/src/mca.rs
index b32c8c23bd9..76c7381bf22 100644
--- a/crates/kgraph_utils/src/mca.rs
+++ b/crates/kgraph_utils/src/mca.rs
@@ -77,7 +77,6 @@ fn get_dir_value_payment_method(
 
         api_enums::PaymentMethodType::ClassicReward => Ok(dirval!(RewardType = ClassicReward)),
         api_enums::PaymentMethodType::Evoucher => Ok(dirval!(RewardType = Evoucher)),
-        api_enums::PaymentMethodType::UpiCollect => Ok(dirval!(UpiType = UpiCollect)),
         api_enums::PaymentMethodType::SamsungPay => Ok(dirval!(WalletType = SamsungPay)),
         api_enums::PaymentMethodType::GoPay => Ok(dirval!(WalletType = GoPay)),
         api_enums::PaymentMethodType::KakaoPay => Ok(dirval!(WalletType = KakaoPay)),
@@ -133,6 +132,8 @@ fn get_dir_value_payment_method(
         api_enums::PaymentMethodType::Oxxo => Ok(dirval!(VoucherType = Oxxo)),
         api_enums::PaymentMethodType::CardRedirect => Ok(dirval!(CardRedirectType = CardRedirect)),
         api_enums::PaymentMethodType::Venmo => Ok(dirval!(WalletType = Venmo)),
+        api_enums::PaymentMethodType::UpiIntent => Ok(dirval!(UpiType = UpiIntent)),
+        api_enums::PaymentMethodType::UpiCollect => Ok(dirval!(UpiType = UpiCollect)),
     }
 }
 
diff --git a/crates/kgraph_utils/src/transformers.rs b/crates/kgraph_utils/src/transformers.rs
index 3e43a4324f9..1bff0eac0d7 100644
--- a/crates/kgraph_utils/src/transformers.rs
+++ b/crates/kgraph_utils/src/transformers.rs
@@ -230,6 +230,7 @@ impl IntoDirValue for (api_enums::PaymentMethodType, api_enums::PaymentMethod) {
             api_enums::PaymentMethodType::ClassicReward => Ok(dirval!(RewardType = ClassicReward)),
             api_enums::PaymentMethodType::Evoucher => Ok(dirval!(RewardType = Evoucher)),
             api_enums::PaymentMethodType::UpiCollect => Ok(dirval!(UpiType = UpiCollect)),
+            api_enums::PaymentMethodType::UpiIntent => Ok(dirval!(UpiType = UpiIntent)),
             api_enums::PaymentMethodType::SamsungPay => Ok(dirval!(WalletType = SamsungPay)),
             api_enums::PaymentMethodType::GoPay => Ok(dirval!(WalletType = GoPay)),
             api_enums::PaymentMethodType::KakaoPay => Ok(dirval!(WalletType = KakaoPay)),
diff --git a/crates/openapi/src/openapi.rs b/crates/openapi/src/openapi.rs
index c67ea2d2746..fd0688ed293 100644
--- a/crates/openapi/src/openapi.rs
+++ b/crates/openapi/src/openapi.rs
@@ -291,6 +291,8 @@ Never share your secret api keys. Keep them guarded and secure.
         api_models::payments::CryptoData,
         api_models::payments::RewardData,
         api_models::payments::UpiData,
+        api_models::payments::UpiCollectData,
+        api_models::payments::UpiIntentData,
         api_models::payments::VoucherData,
         api_models::payments::BoletoVoucherData,
         api_models::payments::AlfamartVoucherData,
diff --git a/crates/router/src/compatibility/stripe/payment_intents/types.rs b/crates/router/src/compatibility/stripe/payment_intents/types.rs
index 5e8c9ea08c0..0526eacb2e8 100644
--- a/crates/router/src/compatibility/stripe/payment_intents/types.rs
+++ b/crates/router/src/compatibility/stripe/payment_intents/types.rs
@@ -141,10 +141,10 @@ impl From<StripeWallet> for payments::WalletData {
 }
 
 impl From<StripeUpi> for payments::UpiData {
-    fn from(upi: StripeUpi) -> Self {
-        Self {
-            vpa_id: Some(upi.vpa_id),
-        }
+    fn from(upi_data: StripeUpi) -> Self {
+        Self::UpiCollect(payments::UpiCollectData {
+            vpa_id: Some(upi_data.vpa_id),
+        })
     }
 }
 
@@ -315,6 +315,18 @@ impl TryFrom<StripePaymentIntentRequest> for payments::PaymentsRequest {
 
         let amount = item.amount.map(|amount| MinorUnit::new(amount).into());
 
+        let payment_method_data = item.payment_method_data.as_ref().map(|pmd| {
+            let payment_method_data = match pmd.payment_method_details.as_ref() {
+                Some(spmd) => Some(payments::PaymentMethodData::from(spmd.to_owned())),
+                None => get_pmd_based_on_payment_method_type(item.payment_method_types),
+            };
+
+            payments::PaymentMethodDataRequest {
+                payment_method_data,
+                billing: pmd.billing_details.clone().map(payments::Address::from),
+            }
+        });
+
         let request = Ok(Self {
             payment_id: item.id.map(payments::PaymentIdType::PaymentIntentId),
             amount,
@@ -334,16 +346,7 @@ impl TryFrom<StripePaymentIntentRequest> for payments::PaymentsRequest {
             phone: item.shipping.as_ref().and_then(|s| s.phone.clone()),
             description: item.description,
             return_url: item.return_url,
-            payment_method_data: item.payment_method_data.as_ref().and_then(|pmd| {
-                pmd.payment_method_details
-                    .as_ref()
-                    .map(|spmd| payments::PaymentMethodDataRequest {
-                        payment_method_data: Some(payments::PaymentMethodData::from(
-                            spmd.to_owned(),
-                        )),
-                        billing: pmd.billing_details.clone().map(payments::Address::from),
-                    })
-            }),
+            payment_method_data,
             payment_method: item
                 .payment_method_data
                 .as_ref()
@@ -816,6 +819,9 @@ pub enum StripeNextAction {
         display_to_timestamp: Option<i64>,
         qr_code_url: Option<url::Url>,
     },
+    FetchQrCodeInformation {
+        qr_code_fetch_url: url::Url,
+    },
     DisplayVoucherInformation {
         voucher_details: payments::VoucherNextStepData,
     },
@@ -858,6 +864,9 @@ pub(crate) fn into_stripe_next_action(
             display_to_timestamp,
             qr_code_url,
         },
+        payments::NextActionData::FetchQrCodeInformation { qr_code_fetch_url } => {
+            StripeNextAction::FetchQrCodeInformation { qr_code_fetch_url }
+        }
         payments::NextActionData::DisplayVoucherInformation { voucher_details } => {
             StripeNextAction::DisplayVoucherInformation { voucher_details }
         }
@@ -884,3 +893,15 @@ pub(crate) fn into_stripe_next_action(
 pub struct StripePaymentRetrieveBody {
     pub client_secret: Option<String>,
 }
+
+//To handle payment types that have empty payment method data
+fn get_pmd_based_on_payment_method_type(
+    payment_method_type: Option<api_enums::PaymentMethodType>,
+) -> Option<payments::PaymentMethodData> {
+    match payment_method_type {
+        Some(api_enums::PaymentMethodType::UpiIntent) => Some(payments::PaymentMethodData::Upi(
+            payments::UpiData::UpiIntent(payments::UpiIntentData {}),
+        )),
+        _ => None,
+    }
+}
diff --git a/crates/router/src/compatibility/stripe/setup_intents/types.rs b/crates/router/src/compatibility/stripe/setup_intents/types.rs
index bbcafb65e9f..9a1cf58f11b 100644
--- a/crates/router/src/compatibility/stripe/setup_intents/types.rs
+++ b/crates/router/src/compatibility/stripe/setup_intents/types.rs
@@ -382,6 +382,9 @@ pub enum StripeNextAction {
         display_to_timestamp: Option<i64>,
         qr_code_url: Option<url::Url>,
     },
+    FetchQrCodeInformation {
+        qr_code_fetch_url: url::Url,
+    },
     DisplayVoucherInformation {
         voucher_details: payments::VoucherNextStepData,
     },
@@ -424,6 +427,9 @@ pub(crate) fn into_stripe_next_action(
             display_to_timestamp,
             qr_code_url,
         },
+        payments::NextActionData::FetchQrCodeInformation { qr_code_fetch_url } => {
+            StripeNextAction::FetchQrCodeInformation { qr_code_fetch_url }
+        }
         payments::NextActionData::DisplayVoucherInformation { voucher_details } => {
             StripeNextAction::DisplayVoucherInformation { voucher_details }
         }
diff --git a/crates/router/src/connector/adyen.rs b/crates/router/src/connector/adyen.rs
index e2effb2e325..1a63dc50c9e 100644
--- a/crates/router/src/connector/adyen.rs
+++ b/crates/router/src/connector/adyen.rs
@@ -214,7 +214,8 @@ impl ConnectorValidation for Adyen {
                 | PaymentMethodType::SamsungPay
                 | PaymentMethodType::Evoucher
                 | PaymentMethodType::Cashapp
-                | PaymentMethodType::UpiCollect => {
+                | PaymentMethodType::UpiCollect
+                | PaymentMethodType::UpiIntent => {
                     capture_method_not_supported!(connector, capture_method, payment_method_type)
                 }
             },
diff --git a/crates/router/src/connector/iatapay/transformers.rs b/crates/router/src/connector/iatapay/transformers.rs
index 5daa33ab944..b36792e90ca 100644
--- a/crates/router/src/connector/iatapay/transformers.rs
+++ b/crates/router/src/connector/iatapay/transformers.rs
@@ -1,7 +1,8 @@
 use std::collections::HashMap;
 
 use api_models::enums::PaymentMethod;
-use common_utils::errors::CustomResult;
+use common_utils::{errors::CustomResult, ext_traits::Encode};
+use error_stack::ResultExt;
 use masking::{Secret, SwitchStrategy};
 use serde::{Deserialize, Serialize};
 
@@ -84,6 +85,13 @@ pub struct PayerInfo {
     token_id: Secret<String>,
 }
 
+#[derive(Debug, Serialize)]
+#[serde(rename_all = "UPPERCASE")]
+pub enum PreferredCheckoutMethod {
+    Vpa,
+    Qr,
+}
+
 #[derive(Debug, Serialize)]
 #[serde(rename_all = "camelCase")]
 pub struct IatapayPaymentsRequest {
@@ -95,7 +103,9 @@ pub struct IatapayPaymentsRequest {
     locale: String,
     redirect_urls: RedirectUrls,
     notification_url: String,
+    #[serde(skip_serializing_if = "Option::is_none")]
     payer_info: Option<PayerInfo>,
+    preferred_checkout_method: Option<PreferredCheckoutMethod>,
 }
 
 impl
@@ -136,24 +146,31 @@ impl
             | PaymentMethod::GiftCard => item.router_data.get_billing_country()?.to_string(),
         };
         let return_url = item.router_data.get_return_url()?;
-        let payer_info = match item.router_data.request.payment_method_data.clone() {
-            domain::PaymentMethodData::Upi(upi_data) => upi_data.vpa_id.map(|id| PayerInfo {
-                token_id: id.switch_strategy(),
-            }),
-            domain::PaymentMethodData::Card(_)
-            | domain::PaymentMethodData::CardRedirect(_)
-            | domain::PaymentMethodData::Wallet(_)
-            | domain::PaymentMethodData::PayLater(_)
-            | domain::PaymentMethodData::BankRedirect(_)
-            | domain::PaymentMethodData::BankDebit(_)
-            | domain::PaymentMethodData::BankTransfer(_)
-            | domain::PaymentMethodData::Crypto(_)
-            | domain::PaymentMethodData::MandatePayment
-            | domain::PaymentMethodData::Reward
-            | domain::PaymentMethodData::Voucher(_)
-            | domain::PaymentMethodData::GiftCard(_)
-            | domain::PaymentMethodData::CardToken(_) => None,
-        };
+        let (payer_info, preferred_checkout_method) =
+            match item.router_data.request.payment_method_data.clone() {
+                domain::PaymentMethodData::Upi(upi_type) => match upi_type {
+                    domain::UpiData::UpiCollect(upi_data) => (
+                        upi_data.vpa_id.map(|id| PayerInfo {
+                            token_id: id.switch_strategy(),
+                        }),
+                        Some(PreferredCheckoutMethod::Vpa),
+                    ),
+                    domain::UpiData::UpiIntent(_) => (None, Some(PreferredCheckoutMethod::Qr)),
+                },
+                domain::PaymentMethodData::Card(_)
+                | domain::PaymentMethodData::CardRedirect(_)
+                | domain::PaymentMethodData::Wallet(_)
+                | domain::PaymentMethodData::PayLater(_)
+                | domain::PaymentMethodData::BankRedirect(_)
+                | domain::PaymentMethodData::BankDebit(_)
+                | domain::PaymentMethodData::BankTransfer(_)
+                | domain::PaymentMethodData::Crypto(_)
+                | domain::PaymentMethodData::MandatePayment
+                | domain::PaymentMethodData::Reward
+                | domain::PaymentMethodData::Voucher(_)
+                | domain::PaymentMethodData::GiftCard(_)
+                | domain::PaymentMethodData::CardToken(_) => (None, None),
+            };
         let payload = Self {
             merchant_id: IatapayAuthType::try_from(&item.router_data.connector_auth_type)?
                 .merchant_id,
@@ -165,6 +182,7 @@ impl
             redirect_urls: get_redirect_url(return_url),
             payer_info,
             notification_url: item.router_data.request.get_webhook_url()?,
+            preferred_checkout_method,
         };
         Ok(payload)
     }
@@ -291,8 +309,46 @@ fn get_iatpay_response(
     };
     let connector_response_reference_id = response.merchant_payment_id.or(response.iata_payment_id);
 
-    let payment_response_data = response.checkout_methods.map_or(
-        types::PaymentsResponseData::TransactionResponse {
+    let payment_response_data = match response.checkout_methods {
+        Some(checkout_methods) => {
+            let (connector_metadata, redirection_data) =
+                match checkout_methods.redirect.redirect_url.ends_with("qr") {
+                    true => {
+                        let qr_code_info = api_models::payments::FetchQrCodeInformation {
+                            qr_code_fetch_url: url::Url::parse(
+                                &checkout_methods.redirect.redirect_url,
+                            )
+                            .change_context(errors::ConnectorError::ResponseHandlingFailed)?,
+                        };
+                        (
+                            Some(qr_code_info.encode_to_value())
+                                .transpose()
+                                .change_context(errors::ConnectorError::ResponseHandlingFailed)?,
+                            None,
+                        )
+                    }
+                    false => (
+                        None,
+                        Some(services::RedirectForm::Form {
+                            endpoint: checkout_methods.redirect.redirect_url,
+                            method: services::Method::Get,
+                            form_fields,
+                        }),
+                    ),
+                };
+
+            types::PaymentsResponseData::TransactionResponse {
+                resource_id: id,
+                redirection_data,
+                mandate_reference: None,
+                connector_metadata,
+                network_txn_id: None,
+                connector_response_reference_id: connector_response_reference_id.clone(),
+                incremental_authorization_allowed: None,
+                charge_id: None,
+            }
+        }
+        None => types::PaymentsResponseData::TransactionResponse {
             resource_id: id.clone(),
             redirection_data: None,
             mandate_reference: None,
@@ -302,21 +358,8 @@ fn get_iatpay_response(
             incremental_authorization_allowed: None,
             charge_id: None,
         },
-        |checkout_methods| types::PaymentsResponseData::TransactionResponse {
-            resource_id: id,
-            redirection_data: Some(services::RedirectForm::Form {
-                endpoint: checkout_methods.redirect.redirect_url,
-                method: services::Method::Get,
-                form_fields,
-            }),
-            mandate_reference: None,
-            connector_metadata: None,
-            network_txn_id: None,
-            connector_response_reference_id: connector_response_reference_id.clone(),
-            incremental_authorization_allowed: None,
-            charge_id: None,
-        },
-    );
+    };
+
     Ok((status, error, payment_response_data))
 }
 
diff --git a/crates/router/src/connector/klarna.rs b/crates/router/src/connector/klarna.rs
index 5c174c69e3b..48b6616a64e 100644
--- a/crates/router/src/connector/klarna.rs
+++ b/crates/router/src/connector/klarna.rs
@@ -398,6 +398,7 @@ impl
                         | common_enums::PaymentMethodType::Trustly
                         | common_enums::PaymentMethodType::Twint
                         | common_enums::PaymentMethodType::UpiCollect
+                        | common_enums::PaymentMethodType::UpiIntent
                         | common_enums::PaymentMethodType::Venmo
                         | common_enums::PaymentMethodType::Vipps
                         | common_enums::PaymentMethodType::Walley
diff --git a/crates/router/src/connector/stripe/transformers.rs b/crates/router/src/connector/stripe/transformers.rs
index 55b0d7f4675..83bca39626f 100644
--- a/crates/router/src/connector/stripe/transformers.rs
+++ b/crates/router/src/connector/stripe/transformers.rs
@@ -675,6 +675,7 @@ impl TryFrom<enums::PaymentMethodType> for StripePaymentMethodType {
             | enums::PaymentMethodType::Paypal
             | enums::PaymentMethodType::Pix
             | enums::PaymentMethodType::UpiCollect
+            | enums::PaymentMethodType::UpiIntent
             | enums::PaymentMethodType::Cashapp
             | enums::PaymentMethodType::Oxxo => Err(errors::ConnectorError::NotImplemented(
                 connector_util::get_unimplemented_payment_method_error_message("stripe"),
diff --git a/crates/router/src/core/payments.rs b/crates/router/src/core/payments.rs
index a39f0deb3ca..db99ff590cd 100644
--- a/crates/router/src/core/payments.rs
+++ b/crates/router/src/core/payments.rs
@@ -1009,6 +1009,7 @@ impl PaymentRedirectFlow for PaymentRedirectCompleteAuthorize {
                         api_models::payments::NextActionData::DisplayBankTransferInformation { .. } => None,
                         api_models::payments::NextActionData::ThirdPartySdkSessionToken { .. } => None,
                         api_models::payments::NextActionData::QrCodeInformation{..} => None,
+                        api_models::payments::NextActionData::FetchQrCodeInformation{..} => None,
                         api_models::payments::NextActionData::DisplayVoucherInformation{ .. } => None,
                         api_models::payments::NextActionData::WaitScreenInformation{..} => None,
                         api_models::payments::NextActionData::ThreeDsInvoke{..} => None,
diff --git a/crates/router/src/core/payments/helpers.rs b/crates/router/src/core/payments/helpers.rs
index 973ca4b2266..6e3f6a9bf6e 100644
--- a/crates/router/src/core/payments/helpers.rs
+++ b/crates/router/src/core/payments/helpers.rs
@@ -2338,7 +2338,7 @@ pub fn validate_payment_method_type_against_payment_method(
         ),
         api_enums::PaymentMethod::Upi => matches!(
             payment_method_type,
-            api_enums::PaymentMethodType::UpiCollect
+            api_enums::PaymentMethodType::UpiCollect | api_enums::PaymentMethodType::UpiIntent
         ),
         api_enums::PaymentMethod::Voucher => matches!(
             payment_method_type,
@@ -4252,9 +4252,9 @@ pub fn get_key_params_for_surcharge_details(
         )),
         api_models::payments::PaymentMethodData::MandatePayment => None,
         api_models::payments::PaymentMethodData::Reward => None,
-        api_models::payments::PaymentMethodData::Upi(_) => Some((
+        api_models::payments::PaymentMethodData::Upi(upi_data) => Some((
             common_enums::PaymentMethod::Upi,
-            common_enums::PaymentMethodType::UpiCollect,
+            upi_data.get_payment_method_type(),
             None,
         )),
         api_models::payments::PaymentMethodData::Voucher(voucher) => Some((
diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs
index 7f6b0cc1f61..8f6af2f89bc 100644
--- a/crates/router/src/core/payments/transformers.rs
+++ b/crates/router/src/core/payments/transformers.rs
@@ -541,6 +541,9 @@ where
 
         let papal_sdk_next_action = paypal_sdk_next_steps_check(payment_attempt.clone())?;
 
+        let next_action_containing_fetch_qr_code_url =
+            fetch_qr_code_url_next_steps_check(payment_attempt.clone())?;
+
         let next_action_containing_wait_screen =
             wait_screen_next_steps_check(payment_attempt.clone())?;
 
@@ -550,6 +553,7 @@ where
             || next_action_containing_qr_code_url.is_some()
             || next_action_containing_wait_screen.is_some()
             || papal_sdk_next_action.is_some()
+            || next_action_containing_fetch_qr_code_url.is_some()
             || payment_data.authentication.is_some()
         {
             next_action_response = bank_transfer_next_steps
@@ -566,6 +570,11 @@ where
                         .or(next_action_containing_qr_code_url.map(|qr_code_data| {
                             api_models::payments::NextActionData::foreign_from(qr_code_data)
                         }))
+                        .or(next_action_containing_fetch_qr_code_url.map(|fetch_qr_code_data| {
+                            api_models::payments::NextActionData::FetchQrCodeInformation {
+                                qr_code_fetch_url: fetch_qr_code_data.qr_code_fetch_url
+                            }
+                        }))
                         .or(papal_sdk_next_action.map(|paypal_next_action_data| {
                             api_models::payments::NextActionData::InvokeSdkClient{
                                 next_action_data: paypal_next_action_data
@@ -899,6 +908,18 @@ pub fn paypal_sdk_next_steps_check(
     Ok(paypal_next_steps)
 }
 
+pub fn fetch_qr_code_url_next_steps_check(
+    payment_attempt: storage::PaymentAttempt,
+) -> RouterResult<Option<api_models::payments::FetchQrCodeInformation>> {
+    let qr_code_steps: Option<Result<api_models::payments::FetchQrCodeInformation, _>> =
+        payment_attempt
+            .connector_metadata
+            .map(|metadata| metadata.parse_value("FetchQrCodeInformation"));
+
+    let qr_code_fetch_url = qr_code_steps.transpose().ok().flatten();
+    Ok(qr_code_fetch_url)
+}
+
 pub fn wait_screen_next_steps_check(
     payment_attempt: storage::PaymentAttempt,
 ) -> RouterResult<Option<api_models::payments::WaitScreenInstructions>> {
@@ -1108,8 +1129,8 @@ impl ForeignFrom<api_models::payments::QrCodeInformation> for api_models::paymen
                 display_to_timestamp,
             } => Self::QrCodeInformation {
                 qr_code_url: Some(qr_code_url),
-                display_to_timestamp,
                 image_data_url: None,
+                display_to_timestamp,
             },
         }
     }
diff --git a/crates/router/src/types/domain/payments.rs b/crates/router/src/types/domain/payments.rs
index 7b1f3365490..51d3210a70f 100644
--- a/crates/router/src/types/domain/payments.rs
+++ b/crates/router/src/types/domain/payments.rs
@@ -5,6 +5,6 @@ pub use hyperswitch_domain_models::payment_method_data::{
     GooglePayPaymentMethodInfo, GooglePayRedirectData, GooglePayThirdPartySdkData,
     GooglePayWalletData, GpayTokenizationData, IndomaretVoucherData, KakaoPayRedirection,
     MbWayRedirection, PayLaterData, PaymentMethodData, SamsungPayWalletData,
-    SepaAndBacsBillingDetails, SwishQrData, TouchNGoRedirection, VoucherData, WalletData,
-    WeChatPayQr,
+    SepaAndBacsBillingDetails, SwishQrData, TouchNGoRedirection, UpiCollectData, UpiData,
+    UpiIntentData, VoucherData, WalletData, WeChatPayQr,
 };
diff --git a/crates/router/src/types/transformers.rs b/crates/router/src/types/transformers.rs
index da8e8c621b7..59ec42abfd2 100644
--- a/crates/router/src/types/transformers.rs
+++ b/crates/router/src/types/transformers.rs
@@ -461,7 +461,9 @@ impl ForeignFrom<api_enums::PaymentMethodType> for api_enums::PaymentMethod {
             | api_enums::PaymentMethodType::Trustly
             | api_enums::PaymentMethodType::Bizum
             | api_enums::PaymentMethodType::Interac => Self::BankRedirect,
-            api_enums::PaymentMethodType::UpiCollect => Self::Upi,
+            api_enums::PaymentMethodType::UpiCollect | api_enums::PaymentMethodType::UpiIntent => {
+                Self::Upi
+            }
             api_enums::PaymentMethodType::CryptoCurrency => Self::Crypto,
             api_enums::PaymentMethodType::Ach
             | api_enums::PaymentMethodType::Sepa
diff --git a/openapi/openapi_spec.json b/openapi/openapi_spec.json
index b87b516de28..30bd356cd45 100644
--- a/openapi/openapi_spec.json
+++ b/openapi/openapi_spec.json
@@ -11757,6 +11757,25 @@
               }
             }
           },
+          {
+            "type": "object",
+            "description": "Contains url to fetch Qr code data",
+            "required": [
+              "qr_code_fetch_url",
+              "type"
+            ],
+            "properties": {
+              "qr_code_fetch_url": {
+                "type": "string"
+              },
+              "type": {
+                "type": "string",
+                "enum": [
+                  "fetch_qr_code_information"
+                ]
+              }
+            }
+          },
           {
             "type": "object",
             "description": "Contains the download url and the reference number for transaction",
@@ -13529,6 +13548,7 @@
           "trustly",
           "twint",
           "upi_collect",
+          "upi_intent",
           "vipps",
           "venmo",
           "walley",
@@ -18692,7 +18712,7 @@
         },
         "additionalProperties": false
       },
-      "UpiData": {
+      "UpiCollectData": {
         "type": "object",
         "properties": {
           "vpa_id": {
@@ -18702,6 +18722,35 @@
           }
         }
       },
+      "UpiData": {
+        "oneOf": [
+          {
+            "type": "object",
+            "required": [
+              "upi_collect"
+            ],
+            "properties": {
+              "upi_collect": {
+                "$ref": "#/components/schemas/UpiCollectData"
+              }
+            }
+          },
+          {
+            "type": "object",
+            "required": [
+              "upi_intent"
+            ],
+            "properties": {
+              "upi_intent": {
+                "$ref": "#/components/schemas/UpiIntentData"
+              }
+            }
+          }
+        ]
+      },
+      "UpiIntentData": {
+        "type": "object"
+      },
       "ValueType": {
         "oneOf": [
           {

## 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 PR introduces a new payment_method_type: `upi_intent` and a new  payment_method_data:  `upi_qr: {}`  along with iatapay qr code implementation.



### Additional Changes

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



## 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)?
-->
_Note:Test through stripe compatibility layer_
1. Create a upi qr payment 
```
curl --location 'http://localhost:8080/payments' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: dev_ZLiIlOCsh5GUTiRJCCSc6lOIXpo0tTGuROyxvZokpKSIl5Lh5mCYwBB9IZV3Jno2' \
--data-raw '{
    "amount": 5000,
    "currency": "INR",
    "confirm": true,
    "capture_method": "automatic",
    "capture_on": "2022-09-10T10:11:12Z",
    "amount_to_capture": 5000,
    "customer_id": "IatapayCustomer",
    "email": "guest@example.com",
    "name": "John Doe",
    "phone": "999999999",
    "phone_country_code": "+1",
    "description": "Its my first payment request",
    "authentication_type": "no_three_ds",
    "return_url": "https://google.com",
    "payment_method": "upi",
    "payment_method_type": "upi_intent",
    "payment_method_data": {
        "upi": {
            "upi_intent": {
                
            }
        }
    },
    "billing": {
        "address": {
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "city": "San Fransico",
            "state": "California",
            "zip": "94122",
            "country": "IN",
            "first_name": "joseph",
            "last_name": "Doe"
        },
        "phone": {
            "number": "8056594427",
            "country_code": "+91"
        }
    },
    "shipping": {
        "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"
        }
    },
    "statement_descriptor_name": "joseph",
    "statement_descriptor_suffix": "JS",
    "metadata": {
        "udf1": "value1",
        "new_customer": "true",
        "login_date": "2019-09-10T10:11:12Z"
    }
}'
```
Response

```
{
    "payment_id": "pay_ZBLXkfFi0wcdBPrQkKPL",
    "merchant_id": "merchant_1716310637",
    "status": "requires_customer_action",
    "amount": 5000,
    "net_amount": 5000,
    "amount_capturable": 5000,
    "amount_received": null,
    "connector": "iatapay",
    "client_secret": "pay_ZBLXkfFi0wcdBPrQkKPL_secret_YYAnlcRyF7ZX3r82WtjL",
    "created": "2024-05-22T10:04:05.468Z",
    "currency": "INR",
    "customer_id": "IatapayCustomer",
    "customer": {
        "id": "IatapayCustomer",
        "name": "John Doe",
        "email": "guest@example.com",
        "phone": "999999999",
        "phone_country_code": "+1"
    },
    "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": "upi",
    "payment_method_data": {
        "upi": {},
        "billing": null
    },
    "payment_token": null,
    "shipping": {
        "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
    },
    "billing": {
        "address": {
            "city": "San Fransico",
            "country": "IN",
            "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": "guest@example.com",
    "name": "John Doe",
    "phone": "999999999",
    "return_url": "https://google.com/",
    "authentication_type": "no_three_ds",
    "statement_descriptor_name": "joseph",
    "statement_descriptor_suffix": "JS",
      "next_action": {
        "type": "fetch_qr_code_information",
        "qr_code_fetch_url": "https://sandbox.iata-pay.iata.org/api/v1/payments/PJHE6F45O1D7M/checkout/api/qr"
    },
    "cancellation_reason": null,
    "error_code": null,
    "error_message": null,
    "unified_code": null,
    "unified_message": null,
    "payment_experience": null,
    "payment_method_type": "upi_intent",
    "connector_label": null,
    "business_country": null,
    "business_label": "default",
    "business_sub_label": null,
    "allowed_payment_method_types": null,
    "ephemeral_key": {
        "customer_id": "IatapayCustomer",
        "created_at": 1716372245,
        "expires": 1716375845,
        "secret": "epk_41f95816c9844c2e9c8672ec5bc91d65"
    },
    "manual_retry_allowed": null,
    "connector_transaction_id": "P1D74RYCPET6J",
    "frm_message": null,
    "metadata": {
        "udf1": "value1",
        "login_date": "2019-09-10T10:11:12Z",
        "new_customer": "true"
    },
    "connector_metadata": null,
    "feature_metadata": null,
    "reference_id": "pay_ZBLXkfFi0wcdBPrQkKPL_1",
    "payment_link": null,
    "profile_id": "pro_aqLkyMdeFcYrp3v3yPd8",
    "surcharge_details": null,
    "attempt_count": 1,
    "merchant_decision": null,
    "merchant_connector_id": "mca_nLDpyk2OF9mrlivQTJnS",
    "incremental_authorization_allowed": null,
    "authorization_count": null,
    "incremental_authorizations": null,
    "external_authentication_details": null,
    "external_3ds_authentication_attempted": false,
    "expires_on": "2024-05-22T10:19:05.468Z",
    "fingerprint": null,
    "browser_info": null,
    "payment_method_id": null,
    "payment_method_status": null,
    "updated": "2024-05-22T10:04:08.642Z",
    "frm_metadata": null
}
```

2. Create a upi payment
```
curl --location 'http://localhost:8080/payments' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key:""' \
--data-raw '{
    "amount": 5000,
    "currency": "INR",
    "confirm": true,
    "capture_method": "automatic",
    "capture_on": "2022-09-10T10:11:12Z",
    "amount_to_capture": 5000,
    "customer_id": "IatapayCustomer",
    "email": "guest@example.com",
    "name": "John Doe",
    "phone": "999999999",
    "phone_country_code": "+1",
    "description": "Its my first payment request",
    "authentication_type": "no_three_ds",
    "return_url": "https://google.com",
    "payment_method": "upi",
    "payment_method_type": "upi_collect",
    "payment_method_data": {
        "upi": {
            "upi_collect": {
                  "vpa_id": "successtest@ita"
            }
        }
    },
    "billing": {
        "address": {
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "city": "San Fransico",
            "state": "California",
            "zip": "94122",
            "country": "IN",
            "first_name": "joseph",
            "last_name": "Doe"
        },
        "phone": {
            "number": "8056594427",
            "country_code": "+91"
        }
    },
    "shipping": {
        "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"
        }
    },
    "statement_descriptor_name": "joseph",
    "statement_descriptor_suffix": "JS",
    "metadata": {
        "udf1": "value1",
        "new_customer": "true",
        "login_date": "2019-09-10T10:11:12Z"
    }
}'
```
Response
```
{
    "payment_id": "pay_VfMfCw7jxtbHNc5xvF4Z",
    "merchant_id": "merchant_1716310637",
    "status": "requires_customer_action",
    "amount": 5000,
    "net_amount": 5000,
    "amount_capturable": 5000,
    "amount_received": null,
    "connector": "iatapay",
    "client_secret": "pay_VfMfCw7jxtbHNc5xvF4Z_secret_lMsdWF0m50OBBvxe1fl7",
    "created": "2024-05-22T09:54:19.813Z",
    "currency": "INR",
    "customer_id": "IatapayCustomer",
    "customer": {
        "id": "IatapayCustomer",
        "name": "John Doe",
        "email": "guest@example.com",
        "phone": "999999999",
        "phone_country_code": "+1"
    },
    "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": "upi",
    "payment_method_data": {
        "upi": {},
        "billing": null
    },
    "payment_token": null,
    "shipping": {
        "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
    },
    "billing": {
        "address": {
            "city": "San Fransico",
            "country": "IN",
            "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": "guest@example.com",
    "name": "John Doe",
    "phone": "999999999",
    "return_url": "https://google.com/",
    "authentication_type": "no_three_ds",
    "statement_descriptor_name": "joseph",
    "statement_descriptor_suffix": "JS",
    "next_action": {
        "type": "redirect_to_url",
        "redirect_to_url": "http://localhost:8080/payments/redirect/pay_VfMfCw7jxtbHNc5xvF4Z/merchant_1716310637/pay_VfMfCw7jxtbHNc5xvF4Z_1"
    },
    "cancellation_reason": null,
    "error_code": null,
    "error_message": null,
    "unified_code": null,
    "unified_message": null,
    "payment_experience": null,
    "payment_method_type": "upi_collect",
    "connector_label": null,
    "business_country": null,
    "business_label": "default",
    "business_sub_label": null,
    "allowed_payment_method_types": null,
    "ephemeral_key": {
        "customer_id": "IatapayCustomer",
        "created_at": 1716371659,
        "expires": 1716375259,
        "secret": "epk_7bb67ee9c3304c8a9458ba6ef2488225"
    },
    "manual_retry_allowed": null,
    "connector_transaction_id": "P46Y265SXCTXZ",
    "frm_message": null,
    "metadata": {
        "udf1": "value1",
        "login_date": "2019-09-10T10:11:12Z",
        "new_customer": "true"
    },
    "connector_metadata": null,
    "feature_metadata": null,
    "reference_id": "pay_VfMfCw7jxtbHNc5xvF4Z_1",
    "payment_link": null,
    "profile_id": "pro_aqLkyMdeFcYrp3v3yPd8",
    "surcharge_details": null,
    "attempt_count": 1,
    "merchant_decision": null,
    "merchant_connector_id": "mca_nLDpyk2OF9mrlivQTJnS",
    "incremental_authorization_allowed": null,
    "authorization_count": null,
    "incremental_authorizations": null,
    "external_authentication_details": null,
    "external_3ds_authentication_attempted": false,
    "expires_on": "2024-05-22T10:09:19.813Z",
    "fingerprint": null,
    "browser_info": null,
    "payment_method_id": null,
    "payment_method_status": null,
    "updated": "2024-05-22T09:54:21.635Z",
    "frm_metadata": null
}
```

Stimulate Terminal status (for Failed - `FAILED`)
```
curl --location --request PUT 'https://sandbox.iata-pay.iata.org/api/v2/payments/P50G9SL4HD0A7/simulate' \
--header 'Content-Type: application/json' \
--header 'Authorization:  access_token' \
--data '{
    "status": "SETTLED"
}'
```


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