        }
        api_enums::Country::BonaireSintEustatiusAndSaba => {
            dir::enums::Country::BonaireSintEustatiusAndSaba
        }
        api_enums::Country::BosniaAndHerzegovina => dir::enums::Country::BosniaAndHerzegovina,
        api_enums::Country::Botswana => dir::enums::Country::Botswana,
        api_enums::Country::BouvetIsland => dir::enums::Country::BouvetIsland,
        api_enums::Country::Brazil => dir::enums::Country::Brazil,
        api_enums::Country::BritishIndianOceanTerritory => {
            dir::enums::Country::BritishIndianOceanTerritory
        }
        api_enums::Country::BruneiDarussalam => dir::enums::Country::BruneiDarussalam,
        api_enums::Country::Bulgaria => dir::enums::Country::Bulgaria,
        api_enums::Country::BurkinaFaso => dir::enums::Country::BurkinaFaso,
        api_enums::Country::Burundi => dir::enums::Country::Burundi,
        api_enums::Country::CaboVerde => dir::enums::Country::CaboVerde,
        api_enums::Country::Cambodia => dir::enums::Country::Cambodia,
        api_enums::Country::Cameroon => dir::enums::Country::Cameroon,
        api_enums::Country::Canada => dir::enums::Country::Canada,
        api_enums::Country::CaymanIslands => dir::enums::Country::CaymanIslands,
        api_enums::Country::CentralAfricanRepublic => dir::enums::Country::CentralAfricanRepublic,
        api_enums::Country::Chad => dir::enums::Country::Chad,
        api_enums::Country::Chile => dir::enums::Country::Chile,
        api_enums::Country::China => dir::enums::Country::China,
        api_enums::Country::ChristmasIsland => dir::enums::Country::ChristmasIsland,
        api_enums::Country::CocosKeelingIslands => dir::enums::Country::CocosKeelingIslands,
        api_enums::Country::Colombia => dir::enums::Country::Colombia,
        api_enums::Country::Comoros => dir::enums::Country::Comoros,
        api_enums::Country::Congo => dir::enums::Country::Congo,
        api_enums::Country::CongoDemocraticRepublic => dir::enums::Country::CongoDemocraticRepublic,
        api_enums::Country::CookIslands => dir::enums::Country::CookIslands,
        api_enums::Country::CostaRica => dir::enums::Country::CostaRica,
        api_enums::Country::CotedIvoire => dir::enums::Country::CotedIvoire,
        api_enums::Country::Croatia => dir::enums::Country::Croatia,
        api_enums::Country::Cuba => dir::enums::Country::Cuba,
        api_enums::Country::Curacao => dir::enums::Country::Curacao,
        api_enums::Country::Cyprus => dir::enums::Country::Cyprus,
        api_enums::Country::Czechia => dir::enums::Country::Czechia,
        api_enums::Country::Denmark => dir::enums::Country::Denmark,
        api_enums::Country::Djibouti => dir::enums::Country::Djibouti,
        api_enums::Country::Dominica => dir::enums::Country::Dominica,
        api_enums::Country::DominicanRepublic => dir::enums::Country::DominicanRepublic,
        api_enums::Country::Ecuador => dir::enums::Country::Ecuador,
        api_enums::Country::Egypt => dir::enums::Country::Egypt,
        api_enums::Country::ElSalvador => dir::enums::Country::ElSalvador,
        api_enums::Country::EquatorialGuinea => dir::enums::Country::EquatorialGuinea,
        api_enums::Country::Eritrea => dir::enums::Country::Eritrea,
        api_enums::Country::Estonia => dir::enums::Country::Estonia,
        api_enums::Country::Ethiopia => dir::enums::Country::Ethiopia,
        api_enums::Country::FalklandIslandsMalvinas => dir::enums::Country::FalklandIslandsMalvinas,
        api_enums::Country::FaroeIslands => dir::enums::Country::FaroeIslands,
        api_enums::Country::Fiji => dir::enums::Country::Fiji,
        api_enums::Country::Finland => dir::enums::Country::Finland,
        api_enums::Country::France => dir::enums::Country::France,
        api_enums::Country::FrenchGuiana => dir::enums::Country::FrenchGuiana,
        api_enums::Country::FrenchPolynesia => dir::enums::Country::FrenchPolynesia,
        api_enums::Country::FrenchSouthernTerritories => {
            dir::enums::Country::FrenchSouthernTerritories
        }
        api_enums::Country::Gabon => dir::enums::Country::Gabon,
        api_enums::Country::Gambia => dir::enums::Country::Gambia,
        api_enums::Country::Georgia => dir::enums::Country::Georgia,
        api_enums::Country::Germany => dir::enums::Country::Germany,
        api_enums::Country::Ghana => dir::enums::Country::Ghana,
        api_enums::Country::Gibraltar => dir::enums::Country::Gibraltar,
        api_enums::Country::Greece => dir::enums::Country::Greece,
        api_enums::Country::Greenland => dir::enums::Country::Greenland,
        api_enums::Country::Grenada => dir::enums::Country::Grenada,
        api_enums::Country::Guadeloupe => dir::enums::Country::Guadeloupe,
        api_enums::Country::Guam => dir::enums::Country::Guam,
        api_enums::Country::Guatemala => dir::enums::Country::Guatemala,
        api_enums::Country::Guernsey => dir::enums::Country::Guernsey,
        api_enums::Country::Guinea => dir::enums::Country::Guinea,
        api_enums::Country::GuineaBissau => dir::enums::Country::GuineaBissau,
        api_enums::Country::Guyana => dir::enums::Country::Guyana,
        api_enums::Country::Haiti => dir::enums::Country::Haiti,
        api_enums::Country::HeardIslandAndMcDonaldIslands => {
            dir::enums::Country::HeardIslandAndMcDonaldIslands
        }
        api_enums::Country::HolySee => dir::enums::Country::HolySee,
        api_enums::Country::Honduras => dir::enums::Country::Honduras,
        api_enums::Country::HongKong => dir::enums::Country::HongKong,
        api_enums::Country::Hungary => dir::enums::Country::Hungary,
        api_enums::Country::Iceland => dir::enums::Country::Iceland,
        api_enums::Country::India => dir::enums::Country::India,
        api_enums::Country::Indonesia => dir::enums::Country::Indonesia,
        api_enums::Country::IranIslamicRepublic => dir::enums::Country::IranIslamicRepublic,
        api_enums::Country::Iraq => dir::enums::Country::Iraq,
        api_enums::Country::Ireland => dir::enums::Country::Ireland,
        api_enums::Country::IsleOfMan => dir::enums::Country::IsleOfMan,
        api_enums::Country::Israel => dir::enums::Country::Israel,
        api_enums::Country::Italy => dir::enums::Country::Italy,
        api_enums::Country::Jamaica => dir::enums::Country::Jamaica,
        api_enums::Country::Japan => dir::enums::Country::Japan,
        api_enums::Country::Jersey => dir::enums::Country::Jersey,
        api_enums::Country::Jordan => dir::enums::Country::Jordan,
        api_enums::Country::Kazakhstan => dir::enums::Country::Kazakhstan,
        api_enums::Country::Kenya => dir::enums::Country::Kenya,
        api_enums::Country::Kiribati => dir::enums::Country::Kiribati,
        api_enums::Country::KoreaDemocraticPeoplesRepublic => {
            dir::enums::Country::KoreaDemocraticPeoplesRepublic
        }
        api_enums::Country::KoreaRepublic => dir::enums::Country::KoreaRepublic,
        api_enums::Country::Kuwait => dir::enums::Country::Kuwait,
        api_enums::Country::Kyrgyzstan => dir::enums::Country::Kyrgyzstan,
        api_enums::Country::LaoPeoplesDemocraticRepublic => {
            dir::enums::Country::LaoPeoplesDemocraticRepublic
        }
        api_enums::Country::Latvia => dir::enums::Country::Latvia,
        api_enums::Country::Lebanon => dir::enums::Country::Lebanon,
        api_enums::Country::Lesotho => dir::enums::Country::Lesotho,
        api_enums::Country::Liberia => dir::enums::Country::Liberia,
        api_enums::Country::Libya => dir::enums::Country::Libya,
        api_enums::Country::Liechtenstein => dir::enums::Country::Liechtenstein,
        api_enums::Country::Lithuania => dir::enums::Country::Lithuania,
        api_enums::Country::Luxembourg => dir::enums::Country::Luxembourg,
        api_enums::Country::Macao => dir::enums::Country::Macao,
        api_enums::Country::MacedoniaTheFormerYugoslavRepublic => {
            dir::enums::Country::MacedoniaTheFormerYugoslavRepublic
        }
        api_enums::Country::Madagascar => dir::enums::Country::Madagascar,
        api_enums::Country::Malawi => dir::enums::Country::Malawi,
        api_enums::Country::Malaysia => dir::enums::Country::Malaysia,
        api_enums::Country::Maldives => dir::enums::Country::Maldives,
        api_enums::Country::Mali => dir::enums::Country::Mali,
        api_enums::Country::Malta => dir::enums::Country::Malta,
        api_enums::Country::MarshallIslands => dir::enums::Country::MarshallIslands,
        api_enums::Country::Martinique => dir::enums::Country::Martinique,
        api_enums::Country::Mauritania => dir::enums::Country::Mauritania,
        api_enums::Country::Mauritius => dir::enums::Country::Mauritius,
        api_enums::Country::Mayotte => dir::enums::Country::Mayotte,
        api_enums::Country::Mexico => dir::enums::Country::Mexico,
        api_enums::Country::MicronesiaFederatedStates => {
            dir::enums::Country::MicronesiaFederatedStates
        }
        api_enums::Country::MoldovaRepublic => dir::enums::Country::MoldovaRepublic,
        api_enums::Country::Monaco => dir::enums::Country::Monaco,
        api_enums::Country::Mongolia => dir::enums::Country::Mongolia,
        api_enums::Country::Montenegro => dir::enums::Country::Montenegro,
        api_enums::Country::Montserrat => dir::enums::Country::Montserrat,
        api_enums::Country::Morocco => dir::enums::Country::Morocco,
        api_enums::Country::Mozambique => dir::enums::Country::Mozambique,
        api_enums::Country::Myanmar => dir::enums::Country::Myanmar,
        api_enums::Country::Namibia => dir::enums::Country::Namibia,
        api_enums::Country::Nauru => dir::enums::Country::Nauru,
        api_enums::Country::Nepal => dir::enums::Country::Nepal,
        api_enums::Country::Netherlands => dir::enums::Country::Netherlands,
        api_enums::Country::NewCaledonia => dir::enums::Country::NewCaledonia,
        api_enums::Country::NewZealand => dir::enums::Country::NewZealand,
        api_enums::Country::Nicaragua => dir::enums::Country::Nicaragua,
        api_enums::Country::Niger => dir::enums::Country::Niger,
        api_enums::Country::Nigeria => dir::enums::Country::Nigeria,
        api_enums::Country::Niue => dir::enums::Country::Niue,
        api_enums::Country::NorfolkIsland => dir::enums::Country::NorfolkIsland,
        api_enums::Country::NorthernMarianaIslands => dir::enums::Country::NorthernMarianaIslands,
        api_enums::Country::Norway => dir::enums::Country::Norway,
        api_enums::Country::Oman => dir::enums::Country::Oman,
        api_enums::Country::Pakistan => dir::enums::Country::Pakistan,
        api_enums::Country::Palau => dir::enums::Country::Palau,
        api_enums::Country::PalestineState => dir::enums::Country::PalestineState,
        api_enums::Country::Panama => dir::enums::Country::Panama,
        api_enums::Country::PapuaNewGuinea => dir::enums::Country::PapuaNewGuinea,
        api_enums::Country::Paraguay => dir::enums::Country::Paraguay,
        api_enums::Country::Peru => dir::enums::Country::Peru,
        api_enums::Country::Philippines => dir::enums::Country::Philippines,
        api_enums::Country::Pitcairn => dir::enums::Country::Pitcairn,

        api_enums::Country::Poland => dir::enums::Country::Poland,
        api_enums::Country::Portugal => dir::enums::Country::Portugal,
        api_enums::Country::PuertoRico => dir::enums::Country::PuertoRico,

        api_enums::Country::Qatar => dir::enums::Country::Qatar,
        api_enums::Country::Reunion => dir::enums::Country::Reunion,
        api_enums::Country::Romania => dir::enums::Country::Romania,
        api_enums::Country::RussianFederation => dir::enums::Country::RussianFederation,
        api_enums::Country::Rwanda => dir::enums::Country::Rwanda,
        api_enums::Country::SaintBarthelemy => dir::enums::Country::SaintBarthelemy,
        api_enums::Country::SaintHelenaAscensionAndTristandaCunha => {
            dir::enums::Country::SaintHelenaAscensionAndTristandaCunha
        }
        api_enums::Country::SaintKittsAndNevis => dir::enums::Country::SaintKittsAndNevis,
        api_enums::Country::SaintLucia => dir::enums::Country::SaintLucia,
        api_enums::Country::SaintMartinFrenchpart => dir::enums::Country::SaintMartinFrenchpart,
        api_enums::Country::SaintPierreAndMiquelon => dir::enums::Country::SaintPierreAndMiquelon,
        api_enums::Country::SaintVincentAndTheGrenadines => {
            dir::enums::Country::SaintVincentAndTheGrenadines
        }
        api_enums::Country::Samoa => dir::enums::Country::Samoa,
        api_enums::Country::SanMarino => dir::enums::Country::SanMarino,
        api_enums::Country::SaoTomeAndPrincipe => dir::enums::Country::SaoTomeAndPrincipe,
        api_enums::Country::SaudiArabia => dir::enums::Country::SaudiArabia,
        api_enums::Country::Senegal => dir::enums::Country::Senegal,
        api_enums::Country::Serbia => dir::enums::Country::Serbia,
        api_enums::Country::Seychelles => dir::enums::Country::Seychelles,
        api_enums::Country::SierraLeone => dir::enums::Country::SierraLeone,
        api_enums::Country::Singapore => dir::enums::Country::Singapore,
        api_enums::Country::SintMaartenDutchpart => dir::enums::Country::SintMaartenDutchpart,
        api_enums::Country::Slovakia => dir::enums::Country::Slovakia,
        api_enums::Country::Slovenia => dir::enums::Country::Slovenia,
        api_enums::Country::SolomonIslands => dir::enums::Country::SolomonIslands,
        api_enums::Country::Somalia => dir::enums::Country::Somalia,
        api_enums::Country::SouthAfrica => dir::enums::Country::SouthAfrica,
        api_enums::Country::SouthGeorgiaAndTheSouthSandwichIslands => {
            dir::enums::Country::SouthGeorgiaAndTheSouthSandwichIslands
        }
        api_enums::Country::SouthSudan => dir::enums::Country::SouthSudan,
        api_enums::Country::Spain => dir::enums::Country::Spain,
        api_enums::Country::SriLanka => dir::enums::Country::SriLanka,
        api_enums::Country::Sudan => dir::enums::Country::Sudan,
        api_enums::Country::Suriname => dir::enums::Country::Suriname,
        api_enums::Country::SvalbardAndJanMayen => dir::enums::Country::SvalbardAndJanMayen,
        api_enums::Country::Swaziland => dir::enums::Country::Swaziland,
        api_enums::Country::Sweden => dir::enums::Country::Sweden,
        api_enums::Country::Switzerland => dir::enums::Country::Switzerland,
        api_enums::Country::SyrianArabRepublic => dir::enums::Country::SyrianArabRepublic,
        api_enums::Country::TaiwanProvinceOfChina => dir::enums::Country::TaiwanProvinceOfChina,
        api_enums::Country::Tajikistan => dir::enums::Country::Tajikistan,
        api_enums::Country::TanzaniaUnitedRepublic => dir::enums::Country::TanzaniaUnitedRepublic,
        api_enums::Country::Thailand => dir::enums::Country::Thailand,
        api_enums::Country::TimorLeste => dir::enums::Country::TimorLeste,
        api_enums::Country::Togo => dir::enums::Country::Togo,
        api_enums::Country::Tokelau => dir::enums::Country::Tokelau,
        api_enums::Country::Tonga => dir::enums::Country::Tonga,
        api_enums::Country::TrinidadAndTobago => dir::enums::Country::TrinidadAndTobago,
        api_enums::Country::Tunisia => dir::enums::Country::Tunisia,
        api_enums::Country::Turkey => dir::enums::Country::Turkey,
        api_enums::Country::Turkmenistan => dir::enums::Country::Turkmenistan,
        api_enums::Country::TurksAndCaicosIslands => dir::enums::Country::TurksAndCaicosIslands,
        api_enums::Country::Tuvalu => dir::enums::Country::Tuvalu,
        api_enums::Country::Uganda => dir::enums::Country::Uganda,
        api_enums::Country::Ukraine => dir::enums::Country::Ukraine,
        api_enums::Country::UnitedArabEmirates => dir::enums::Country::UnitedArabEmirates,
        api_enums::Country::UnitedKingdomOfGreatBritainAndNorthernIreland => {
            dir::enums::Country::UnitedKingdomOfGreatBritainAndNorthernIreland
        }
        api_enums::Country::UnitedStatesOfAmerica => dir::enums::Country::UnitedStatesOfAmerica,
        api_enums::Country::UnitedStatesMinorOutlyingIslands => {
            dir::enums::Country::UnitedStatesMinorOutlyingIslands
        }
        api_enums::Country::Uruguay => dir::enums::Country::Uruguay,
        api_enums::Country::Uzbekistan => dir::enums::Country::Uzbekistan,
        api_enums::Country::Vanuatu => dir::enums::Country::Vanuatu,
        api_enums::Country::VenezuelaBolivarianRepublic => {
            dir::enums::Country::VenezuelaBolivarianRepublic
        }
        api_enums::Country::Vietnam => dir::enums::Country::Vietnam,
        api_enums::Country::VirginIslandsBritish => dir::enums::Country::VirginIslandsBritish,
        api_enums::Country::VirginIslandsUS => dir::enums::Country::VirginIslandsUS,
        api_enums::Country::WallisAndFutuna => dir::enums::Country::WallisAndFutuna,
        api_enums::Country::WesternSahara => dir::enums::Country::WesternSahara,
        api_enums::Country::Yemen => dir::enums::Country::Yemen,
        api_enums::Country::Zambia => dir::enums::Country::Zambia,
        api_enums::Country::Zimbabwe => dir::enums::Country::Zimbabwe,
    }
}

pub fn business_country_to_dir_value(c: api_enums::Country) -> dir::DirValue {
    dir::DirValue::BusinessCountry(get_dir_country_dir_value(c))
}

pub fn billing_country_to_dir_value(c: api_enums::Country) -> dir::DirValue {
    dir::DirValue::BillingCountry(get_dir_country_dir_value(c))
}


// Struct: MetricsBucketResponse
// File: crates/api_models/src/analytics/sdk_events.rs
// Module: api_models
// Implementations: 0

pub struct MetricsBucketResponse


// Function: add_access_token
// File: crates/router/src/core/payments/access_token.rs
// Module: router

pub fn add_access_token<
    F: Clone + 'static,
    Req: Debug + Clone + 'static,
    Res: Debug + Clone + 'static,
>(
    state: &SessionState,
    connector: &api_types::ConnectorData,
    merchant_context: &domain::MerchantContext,
    router_data: &types::RouterData<F, Req, Res>,
    creds_identifier: Option<&str>,
) -> RouterResult<types::AddAccessTokenResult>


// Struct: PaymentMethodStatusUpdateWorkflow
// File: crates/router/src/workflows/payment_method_status_update.rs
// Module: router
// Implementations: 0

pub struct PaymentMethodStatusUpdateWorkflow


// Struct: ZenMerchantActionData
// File: crates/hyperswitch_connectors/src/connectors/zen/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct ZenMerchantActionData


// Function: get_token_data
// File: crates/router/src/types/storage/payment_method.rs
// Module: router

pub fn get_token_data(&self) -> Option<PaymentTokenData>


// Function: get_individual_surcharge_key_value_pairs
// File: crates/router/src/core/payments/types.rs
// Module: router

pub fn get_individual_surcharge_key_value_pairs(&self) -> Vec<(String, SurchargeDetails)>


// Struct: XenditAuthType
// File: crates/hyperswitch_connectors/src/connectors/xendit/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct XenditAuthType


// File: crates/analytics/src/payments/metrics/avg_ticket_size.rs
// Module: analytics

use std::collections::HashSet;

use api_models::analytics::{
    payments::{PaymentDimensions, PaymentFilters, PaymentMetricsBucketIdentifier},
    Granularity, TimeRange,
};
use common_utils::errors::ReportSwitchExt;
use diesel_models::enums as storage_enums;
use error_stack::ResultExt;
use time::PrimitiveDateTime;

use super::{PaymentMetric, PaymentMetricRow};
use crate::{
    enums::AuthInfo,
    query::{Aggregate, GroupByClause, QueryBuilder, QueryFilter, SeriesBucket, ToSql, Window},
    types::{AnalyticsCollection, AnalyticsDataSource, MetricsError, MetricsResult},
};

#[derive(Default)]
pub(super) struct AvgTicketSize;

#[async_trait::async_trait]
impl<T> PaymentMetric<T> for AvgTicketSize
where
    T: AnalyticsDataSource + super::PaymentMetricAnalytics,
    PrimitiveDateTime: ToSql<T>,
    AnalyticsCollection: ToSql<T>,
    Granularity: GroupByClause<T>,
    Aggregate<&'static str>: ToSql<T>,
    Window<&'static str>: ToSql<T>,
{
    async fn load_metrics(
        &self,
        dimensions: &[PaymentDimensions],
        auth: &AuthInfo,
        filters: &PaymentFilters,
        granularity: Option<Granularity>,
        time_range: &TimeRange,
        pool: &T,
    ) -> MetricsResult<HashSet<(PaymentMetricsBucketIdentifier, PaymentMetricRow)>> {
        let mut query_builder: QueryBuilder<T> = QueryBuilder::new(AnalyticsCollection::Payment);

        for dim in dimensions.iter() {
            query_builder.add_select_column(dim).switch()?;
        }

        query_builder
            .add_select_column(Aggregate::Sum {
                field: "amount",
                alias: Some("total"),
            })
            .switch()?;
        query_builder
            .add_select_column(Aggregate::Count {
                field: None,
                alias: Some("count"),
            })
            .switch()?;
        query_builder
            .add_select_column(Aggregate::Min {
                field: "created_at",
                alias: Some("start_bucket"),
            })
            .switch()?;
        query_builder
            .add_select_column(Aggregate::Max {
                field: "created_at",
                alias: Some("end_bucket"),
            })
            .switch()?;

        filters.set_filter_clause(&mut query_builder).switch()?;

        auth.set_filter_clause(&mut query_builder).switch()?;

        time_range
            .set_filter_clause(&mut query_builder)
            .attach_printable("Error filtering time range")
            .switch()?;

        for dim in dimensions.iter() {
            query_builder
                .add_group_by_clause(dim)
                .attach_printable("Error grouping by dimensions")
                .switch()?;
        }

        if let Some(granularity) = granularity {
            granularity
                .set_group_by_clause(&mut query_builder)
                .attach_printable("Error adding granularity")
                .switch()?;
        }

        query_builder
            .add_filter_clause(
                PaymentDimensions::PaymentStatus,
                storage_enums::AttemptStatus::Charged,
            )
            .switch()?;

        query_builder
            .execute_query::<PaymentMetricRow, _>(pool)
            .await
            .change_context(MetricsError::QueryBuildingError)?
            .change_context(MetricsError::QueryExecutionFailure)?
            .into_iter()
            .map(|i| {
                Ok((
                    PaymentMetricsBucketIdentifier::new(
                        i.currency.as_ref().map(|i| i.0),
                        i.status.as_ref().map(|i| i.0),
                        i.connector.clone(),
                        i.authentication_type.as_ref().map(|i| i.0),
                        i.payment_method.clone(),
                        i.payment_method_type.clone(),
                        i.client_source.clone(),
                        i.client_version.clone(),
                        i.profile_id.clone(),
                        i.card_network.clone(),
                        i.merchant_id.clone(),
                        i.card_last_4.clone(),
                        i.card_issuer.clone(),
                        i.error_reason.clone(),
                        i.routing_approach.as_ref().map(|i| i.0.clone()),
                        i.signature_network.clone(),
                        i.is_issuer_regulated,
                        i.is_debit_routed,
                        TimeRange {
                            start_time: match (granularity, i.start_bucket) {
                                (Some(g), Some(st)) => g.clip_to_start(st)?,
                                _ => time_range.start_time,
                            },
                            end_time: granularity.as_ref().map_or_else(
                                || Ok(time_range.end_time),
                                |g| i.end_bucket.map(|et| g.clip_to_end(et)).transpose(),
                            )?,
                        },
                    ),
                    i,
                ))
            })
            .collect::<error_stack::Result<
                HashSet<(PaymentMetricsBucketIdentifier, PaymentMetricRow)>,
                crate::query::PostProcessingError,
            >>()
            .change_context(MetricsError::PostProcessingFailure)
    }
}


// Implementation: impl ConnectorValidation for for Paytm
// File: crates/hyperswitch_connectors/src/connectors/paytm.rs
// Module: hyperswitch_connectors
// Methods: 2 total (0 public)

impl ConnectorValidation for for Paytm


// Implementation: impl api::PaymentAuthorize for for Vgs
// File: crates/hyperswitch_connectors/src/connectors/vgs.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::PaymentAuthorize for for Vgs


// Struct: PaymentAttemptCore
// File: crates/router/src/core/fraud_check/types.rs
// Module: router
// Implementations: 0

pub struct PaymentAttemptCore


// Implementation: impl api::revenue_recovery_v2::RevenueRecoveryRecordBackV2 for for Recurly
// File: crates/hyperswitch_connectors/src/connectors/recurly.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::revenue_recovery_v2::RevenueRecoveryRecordBackV2 for for Recurly


// Implementation: impl api::PaymentAuthorize for for Hyperwallet
// File: crates/hyperswitch_connectors/src/connectors/hyperwallet.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::PaymentAuthorize for for Hyperwallet


// Implementation: impl api::PaymentAuthorize for for Klarna
// File: crates/hyperswitch_connectors/src/connectors/klarna.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::PaymentAuthorize for for Klarna


// Struct: AuthorizedotnetSetupMandateResponse
// File: crates/hyperswitch_connectors/src/connectors/authorizedotnet/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct AuthorizedotnetSetupMandateResponse


// Struct: ZenCardDetails
// File: crates/hyperswitch_connectors/src/connectors/zen/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct ZenCardDetails


// Implementation: impl PaymentAttemptBatchNew
// File: crates/diesel_models/src/user/sample_data.rs
// Module: diesel_models
// Methods: 1 total (0 public)

impl PaymentAttemptBatchNew


// Struct: InstructionNarrative
// File: crates/hyperswitch_connectors/src/connectors/worldpay/requests.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct InstructionNarrative


// Implementation: impl Responder
// File: crates/router/src/routes/configs.rs
// Module: router
// Methods: 0 total (0 public)

impl Responder


// Implementation: impl DynamicRoutingClientConfig
// File: crates/external_services/src/grpc_client/dynamic_routing.rs
// Module: external_services
// Methods: 1 total (1 public)

impl DynamicRoutingClientConfig


// Implementation: impl PayoutsInterface for for RouterStore
// File: crates/storage_impl/src/lib.rs
// Module: storage_impl
// Methods: 0 total (0 public)

impl PayoutsInterface for for RouterStore


// Struct: PhonepeRefundRequest
// File: crates/hyperswitch_connectors/src/connectors/phonepe/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct PhonepeRefundRequest


// Module Structure
// File: crates/hyperswitch_connectors/src/connectors/razorpay.rs
// Module: hyperswitch_connectors

// Public submodules:
pub mod transformers;


// Struct: Rapyd
// File: crates/hyperswitch_connectors/src/connectors/rapyd.rs
// Module: hyperswitch_connectors
// Implementations: 18
// Traits: ConnectorCommon, ConnectorValidation, api::ConnectorAccessToken, api::PaymentToken, api::PaymentAuthorize, api::Payment, api::MandateSetup, api::PaymentVoid, api::PaymentSync, api::PaymentCapture, api::PaymentSession, api::Refund, api::RefundExecute, api::RefundSync, IncomingWebhook, ConnectorSpecifications

pub struct Rapyd

ConnectorCommon ConnectorValidation api::ConnectorAccessToken api::PaymentToken api::PaymentAuthorize api::Payment api::MandateSetup api::PaymentVoid api::PaymentSync api::PaymentCapture api::PaymentSession api::Refund api::RefundExecute api::RefundSync IncomingWebhook ConnectorSpecifications


// Struct: ArchipelWalletInformation
// File: crates/hyperswitch_connectors/src/connectors/archipel/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct ArchipelWalletInformation


// File: crates/router/src/core/payments/operations/payment_confirm.rs
// Module: router
// Public structs: 1

use std::marker::PhantomData;

#[cfg(feature = "v1")]
use api_models::payment_methods::PaymentMethodsData;
use api_models::{
    admin::ExtendedCardInfoConfig,
    enums::FrmSuggestion,
    payments::{ConnectorMandateReferenceId, ExtendedCardInfo, GetAddressFromPaymentMethodData},
};
use async_trait::async_trait;
use common_utils::ext_traits::{AsyncExt, Encode, StringExt, ValueExt};
use diesel_models::payment_attempt::ConnectorMandateReferenceId as DieselConnectorMandateReferenceId;
use error_stack::{report, ResultExt};
use futures::FutureExt;
#[cfg(feature = "v1")]
use hyperswitch_domain_models::payments::payment_intent::PaymentIntentUpdateFields;
use hyperswitch_domain_models::router_request_types::unified_authentication_service;
use masking::{ExposeInterface, PeekInterface};
use router_derive::PaymentOperation;
use router_env::{instrument, logger, tracing};
use tracing_futures::Instrument;

use super::{BoxedOperation, Domain, GetTracker, Operation, UpdateTracker, ValidateRequest};
#[cfg(feature = "v1")]
use crate::{
    consts,
    core::payment_methods::cards::create_encrypted_data,
    events::audit_events::{AuditEvent, AuditEventType},
};
use crate::{
    core::{
        authentication,
        blocklist::utils as blocklist_utils,
        card_testing_guard::utils as card_testing_guard_utils,
        errors::{self, CustomResult, RouterResult, StorageErrorExt},
        mandate::helpers as m_helpers,
        payments::{
            self, helpers, operations,
            operations::payment_confirm::unified_authentication_service::ThreeDsMetaData,
            populate_surcharge_details, CustomerDetails, PaymentAddress, PaymentData,
        },
        three_ds_decision_rule,
        unified_authentication_service::{
            self as uas_utils,
            types::{ClickToPay, UnifiedAuthenticationService},
        },
        utils as core_utils,
    },
    routes::{app::ReqState, SessionState},
    services,
    types::{
        self,
        api::{self, ConnectorCallType, PaymentIdTypeExt},
        domain::{self},
        storage::{self, enums as storage_enums},
        transformers::{ForeignFrom, ForeignInto},
    },
    utils::{self, OptionExt},
};

#[derive(Debug, Clone, Copy, PaymentOperation)]
#[operation(operations = "all", flow = "authorize")]
pub struct PaymentConfirm;

type PaymentConfirmOperation<'b, F> = BoxedOperation<'b, F, api::PaymentsRequest, PaymentData<F>>;

#[async_trait]
impl<F: Send + Clone + Sync> GetTracker<F, PaymentData<F>, api::PaymentsRequest>
    for PaymentConfirm
{
    #[instrument(skip_all)]
    async fn get_trackers<'a>(
        &'a self,
        state: &'a SessionState,
        payment_id: &api::PaymentIdType,
        request: &api::PaymentsRequest,
        merchant_context: &domain::MerchantContext,
        auth_flow: services::AuthFlow,
        header_payload: &hyperswitch_domain_models::payments::HeaderPayload,
    ) -> RouterResult<operations::GetTrackerResponse<'a, F, api::PaymentsRequest, PaymentData<F>>>
    {
        let key_manager_state = &state.into();

        let merchant_id = merchant_context.get_merchant_account().get_id();
        let storage_scheme = merchant_context.get_merchant_account().storage_scheme;
        let (currency, amount);

        let payment_id = payment_id
            .get_payment_intent_id()
            .change_context(errors::ApiErrorResponse::PaymentNotFound)?;

        // Stage 1
        let store = &*state.store;
        let m_merchant_id = merchant_id.clone();

        // Parallel calls - level 0
        let mut payment_intent = store
            .find_payment_intent_by_payment_id_merchant_id(
                key_manager_state,
                &payment_id,
                &m_merchant_id,
                merchant_context.get_merchant_key_store(),
                storage_scheme,
            )
            .await
            .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?;

        // TODO (#7195): Add platform merchant account validation once client_secret auth is solved

        if let Some(order_details) = &request.order_details {
            helpers::validate_order_details_amount(
                order_details.to_owned(),
                payment_intent.amount,
                false,
            )?;
        }

        helpers::validate_customer_access(&payment_intent, auth_flow, request)?;

        if [
            Some(common_enums::PaymentSource::Webhook),
            Some(common_enums::PaymentSource::ExternalAuthenticator),
        ]
        .contains(&header_payload.payment_confirm_source)
        {
            helpers::validate_payment_status_against_not_allowed_statuses(
                payment_intent.status,
                &[
                    storage_enums::IntentStatus::Cancelled,
                    storage_enums::IntentStatus::Succeeded,
                    storage_enums::IntentStatus::Processing,
                    storage_enums::IntentStatus::RequiresCapture,
                    storage_enums::IntentStatus::RequiresMerchantAction,
                ],
                "confirm",
            )?;
        } else {
            helpers::validate_payment_status_against_not_allowed_statuses(
                payment_intent.status,
                &[
                    storage_enums::IntentStatus::Cancelled,
                    storage_enums::IntentStatus::Succeeded,
                    storage_enums::IntentStatus::Processing,
                    storage_enums::IntentStatus::RequiresCapture,
                    storage_enums::IntentStatus::RequiresMerchantAction,
                    storage_enums::IntentStatus::RequiresCustomerAction,
                ],
                "confirm",
            )?;
        }

        helpers::authenticate_client_secret(request.client_secret.as_ref(), &payment_intent)?;

        let customer_details = helpers::get_customer_details_from_request(request);

        // Stage 2
        let attempt_id = payment_intent.active_attempt.get_id();
        let profile_id = payment_intent
            .profile_id
            .clone()
            .get_required_value("profile_id")
            .change_context(errors::ApiErrorResponse::InternalServerError)
            .attach_printable("'profile_id' not set in payment intent")?;

        let store = state.store.clone();
        let key_manager_state_clone = key_manager_state.clone();
        let key_store_clone = merchant_context.get_merchant_key_store().clone();

        let business_profile_fut = tokio::spawn(
            async move {
                store
                    .find_business_profile_by_profile_id(
                        &key_manager_state_clone,
                        &key_store_clone,
                        &profile_id,
                    )
                    .map(|business_profile_result| {
                        business_profile_result.to_not_found_response(
                            errors::ApiErrorResponse::ProfileNotFound {
                                id: profile_id.get_string_repr().to_owned(),
                            },
                        )
                    })
                    .await
            }
            .in_current_span(),
        );

        let store = state.store.clone();

        let m_payment_id = payment_intent.payment_id.clone();
        let m_merchant_id = merchant_id.clone();

        let payment_attempt_fut = tokio::spawn(
            async move {
                store
                    .find_payment_attempt_by_payment_id_merchant_id_attempt_id(
                        &m_payment_id,
                        &m_merchant_id,
                        attempt_id.as_str(),
                        storage_scheme,
                    )
                    .map(|x| x.to_not_found_response(errors::ApiErrorResponse::PaymentNotFound))
                    .await
            }
            .in_current_span(),
        );

        let m_merchant_id = merchant_id.clone();
        let m_request_shipping = request.shipping.clone();
        let m_payment_intent_shipping_address_id = payment_intent.shipping_address_id.clone();
        let m_payment_intent_payment_id = payment_intent.payment_id.clone();
        let m_customer_details_customer_id = customer_details.customer_id.clone();
        let m_payment_intent_customer_id = payment_intent.customer_id.clone();
        let m_key_store = merchant_context.get_merchant_key_store().clone();
        let session_state = state.clone();

        let shipping_address_fut = tokio::spawn(
            async move {
                helpers::create_or_update_address_for_payment_by_request(
                    &session_state,
                    m_request_shipping.as_ref(),
                    m_payment_intent_shipping_address_id.as_deref(),
                    &m_merchant_id,
                    m_payment_intent_customer_id
                        .as_ref()
                        .or(m_customer_details_customer_id.as_ref()),
                    &m_key_store,
                    &m_payment_intent_payment_id,
                    storage_scheme,
                )
                .await
            }
            .in_current_span(),
        );

        let m_merchant_id = merchant_id.clone();
        let m_request_billing = request.billing.clone();
        let m_customer_details_customer_id = customer_details.customer_id.clone();
        let m_payment_intent_customer_id = payment_intent.customer_id.clone();
        let m_payment_intent_billing_address_id = payment_intent.billing_address_id.clone();
        let m_payment_intent_payment_id = payment_intent.payment_id.clone();
        let m_key_store = merchant_context.get_merchant_key_store().clone();
        let session_state = state.clone();

        let billing_address_fut = tokio::spawn(
            async move {
                helpers::create_or_update_address_for_payment_by_request(
                    &session_state,
                    m_request_billing.as_ref(),
                    m_payment_intent_billing_address_id.as_deref(),
                    &m_merchant_id,
                    m_payment_intent_customer_id
                        .as_ref()
                        .or(m_customer_details_customer_id.as_ref()),
                    &m_key_store,
                    &m_payment_intent_payment_id,
                    storage_scheme,
                )
                .await
            }
            .in_current_span(),
        );

        let m_merchant_id = merchant_id.clone();
        let store = state.clone().store;
        let m_request_merchant_connector_details = request.merchant_connector_details.clone();

        let config_update_fut = tokio::spawn(
            async move {
                m_request_merchant_connector_details
                    .async_map(|mcd| async {
                        helpers::insert_merchant_connector_creds_to_config(
                            store.as_ref(),
                            &m_merchant_id,
                            mcd,
                        )
                        .await
                    })
                    .map(|x| x.transpose())
                    .await
            }
            .in_current_span(),
        );

        // Based on whether a retry can be performed or not, fetch relevant entities
        let (mut payment_attempt, shipping_address, billing_address, business_profile) =
            match payment_intent.status {
                api_models::enums::IntentStatus::RequiresCustomerAction
                | api_models::enums::IntentStatus::RequiresMerchantAction
                | api_models::enums::IntentStatus::RequiresPaymentMethod
                | api_models::enums::IntentStatus::RequiresConfirmation => {
                    // Normal payment
                    // Parallel calls - level 1
                    let (payment_attempt, shipping_address, billing_address, business_profile, _) =
                        tokio::try_join!(
                            utils::flatten_join_error(payment_attempt_fut),
                            utils::flatten_join_error(shipping_address_fut),
                            utils::flatten_join_error(billing_address_fut),
                            utils::flatten_join_error(business_profile_fut),
                            utils::flatten_join_error(config_update_fut)
                        )?;

                    (
                        payment_attempt,
                        shipping_address,
                        billing_address,
                        business_profile,
                    )
                }
                _ => {
                    // Retry payment
                    let (
                        mut payment_attempt,
                        shipping_address,
                        billing_address,
                        business_profile,
                        _,
                    ) = tokio::try_join!(
                        utils::flatten_join_error(payment_attempt_fut),
                        utils::flatten_join_error(shipping_address_fut),
                        utils::flatten_join_error(billing_address_fut),
                        utils::flatten_join_error(business_profile_fut),
                        utils::flatten_join_error(config_update_fut)
                    )?;

                    let attempt_type = helpers::get_attempt_type(
                        &payment_intent,
                        &payment_attempt,
                        business_profile.is_manual_retry_enabled,
                        "confirm",
                    )?;

                    // 3
                    (payment_intent, payment_attempt) = attempt_type
                        .modify_payment_intent_and_payment_attempt(
                            request,
                            payment_intent,
                            payment_attempt,
                            state,
                            merchant_context.get_merchant_key_store(),
                            storage_scheme,
                        )
                        .await?;

                    (
                        payment_attempt,
                        shipping_address,
                        billing_address,
                        business_profile,
                    )
                }
            };

        payment_intent.order_details = request
            .get_order_details_as_value()
            .change_context(errors::ApiErrorResponse::InternalServerError)
            .attach_printable("Failed to convert order details to value")?
            .or(payment_intent.order_details);

        payment_intent.setup_future_usage = request
            .setup_future_usage
            .or(payment_intent.setup_future_usage);

        payment_intent.psd2_sca_exemption_type = request
            .psd2_sca_exemption_type
            .or(payment_intent.psd2_sca_exemption_type);

        let browser_info = request
            .browser_info
            .clone()
            .or(payment_attempt.browser_info)
            .as_ref()
            .map(Encode::encode_to_value)
            .transpose()
            .change_context(errors::ApiErrorResponse::InvalidDataValue {
                field_name: "browser_info",
            })?;
        let customer_acceptance = request.customer_acceptance.clone().or(payment_attempt
            .customer_acceptance
            .clone()
            .map(|customer_acceptance| {
                customer_acceptance
                    .expose()
                    .parse_value("CustomerAcceptance")
                    .change_context(errors::ApiErrorResponse::InternalServerError)
                    .attach_printable("Failed while deserializing customer_acceptance")
            })
            .transpose()?);

        let recurring_details = request.recurring_details.clone();

        helpers::validate_card_data(
            request
                .payment_method_data
                .as_ref()
                .and_then(|pmd| pmd.payment_method_data.clone()),
        )?;

        payment_attempt.browser_info = browser_info;

        payment_attempt.payment_experience = request
            .payment_experience
            .or(payment_attempt.payment_experience);

        payment_attempt.capture_method = request.capture_method.or(payment_attempt.capture_method);

        payment_attempt.customer_acceptance = request
            .customer_acceptance
            .clone()
            .map(|customer_acceptance| customer_acceptance.encode_to_value())
            .transpose()
            .change_context(errors::ApiErrorResponse::InternalServerError)
            .attach_printable("Failed while encoding customer_acceptance to value")?
            .map(masking::Secret::new)
            .or(payment_attempt.customer_acceptance);

        currency = payment_attempt.currency.get_required_value("currency")?;
        amount = payment_attempt.get_total_amount().into();

        helpers::validate_customer_id_mandatory_cases(
            request.setup_future_usage.is_some(),
            payment_intent
                .customer_id
                .as_ref()
                .or(customer_details.customer_id.as_ref()),
        )?;

        let creds_identifier = request
            .merchant_connector_details
            .as_ref()
            .map(|mcd| mcd.creds_identifier.to_owned());

        payment_intent.shipping_address_id =
            shipping_address.as_ref().map(|i| i.address_id.clone());
        payment_intent.billing_address_id = billing_address.as_ref().map(|i| i.address_id.clone());
        payment_intent.return_url = request
            .return_url
            .as_ref()
            .map(|a| a.to_string())
            .or(payment_intent.return_url);

        payment_intent.allowed_payment_method_types = request
            .get_allowed_payment_method_types_as_value()
            .change_context(errors::ApiErrorResponse::InternalServerError)
            .attach_printable("Error converting allowed_payment_types to Value")?
            .or(payment_intent.allowed_payment_method_types);

        payment_intent.connector_metadata = request
            .get_connector_metadata_as_value()
            .change_context(errors::ApiErrorResponse::InternalServerError)
            .attach_printable("Error converting connector_metadata to Value")?
            .or(payment_intent.connector_metadata);

        payment_intent.feature_metadata = request
            .get_feature_metadata_as_value()
            .change_context(errors::ApiErrorResponse::InternalServerError)
            .attach_printable("Error converting feature_metadata to Value")?
            .or(payment_intent.feature_metadata);
        payment_intent.metadata = request.metadata.clone().or(payment_intent.metadata);
        payment_intent.frm_metadata = request.frm_metadata.clone().or(payment_intent.frm_metadata);
        payment_intent.request_incremental_authorization = request
            .request_incremental_authorization
            .map(|request_incremental_authorization| {
                core_utils::get_request_incremental_authorization_value(
                    Some(request_incremental_authorization),
                    payment_attempt.capture_method,
                )
            })
            .unwrap_or(Ok(payment_intent.request_incremental_authorization))?;
        payment_intent.enable_partial_authorization = request
            .enable_partial_authorization
            .or(payment_intent.enable_partial_authorization);
        payment_attempt.business_sub_label = request
            .business_sub_label
            .clone()
            .or(payment_attempt.business_sub_label);

        let n_request_payment_method_data = request
            .payment_method_data
            .as_ref()
            .and_then(|pmd| pmd.payment_method_data.clone());

        let store = state.clone().store;
        let profile_id = payment_intent
            .profile_id
            .clone()
            .get_required_value("profile_id")
            .change_context(errors::ApiErrorResponse::InternalServerError)
            .attach_printable("'profile_id' not set in payment intent")?;

        let additional_pm_data_fut = tokio::spawn(
            async move {
                Ok(n_request_payment_method_data
                    .async_map(|payment_method_data| async move {
                        helpers::get_additional_payment_data(
                            &payment_method_data.into(),
                            store.as_ref(),
                            &profile_id,
                        )
                        .await
                    })
                    .await)
            }
            .in_current_span(),
        );

        let n_payment_method_billing_address_id =
            payment_attempt.payment_method_billing_address_id.clone();
        let n_request_payment_method_billing_address = request
            .payment_method_data
            .as_ref()
            .and_then(|pmd| pmd.billing.clone());
        let m_payment_intent_customer_id = payment_intent.customer_id.clone();
        let m_payment_intent_payment_id = payment_intent.payment_id.clone();
        let m_key_store = merchant_context.get_merchant_key_store().clone();
        let m_customer_details_customer_id = customer_details.customer_id.clone();
        let m_merchant_id = merchant_id.clone();
        let session_state = state.clone();

        let payment_method_billing_future = tokio::spawn(
            async move {
                helpers::create_or_update_address_for_payment_by_request(
                    &session_state,
                    n_request_payment_method_billing_address.as_ref(),
                    n_payment_method_billing_address_id.as_deref(),
                    &m_merchant_id,
                    m_payment_intent_customer_id
                        .as_ref()
                        .or(m_customer_details_customer_id.as_ref()),
                    &m_key_store,
                    &m_payment_intent_payment_id,
                    storage_scheme,
                )
                .await
            }
            .in_current_span(),
        );

        let mandate_type = m_helpers::get_mandate_type(
            request.mandate_data.clone(),
            request.off_session,
            payment_intent.setup_future_usage,
            request.customer_acceptance.clone(),
            request.payment_token.clone(),
            payment_attempt.payment_method.or(request.payment_method),
        )
        .change_context(errors::ApiErrorResponse::MandateValidationFailed {
            reason: "Expected one out of recurring_details and mandate_data but got both".into(),
        })?;

        let m_state = state.clone();
        let m_mandate_type = mandate_type;
        let m_merchant_context = merchant_context.clone();
        let m_request = request.clone();

        let payment_intent_customer_id = payment_intent.customer_id.clone();

        let mandate_details_fut = tokio::spawn(
            async move {
                Box::pin(helpers::get_token_pm_type_mandate_details(
                    &m_state,
                    &m_request,
                    m_mandate_type,
                    &m_merchant_context,
                    None,
                    payment_intent_customer_id.as_ref(),
                ))
                .await
            }
            .in_current_span(),
        );

        // Parallel calls - level 2
        let (mandate_details, additional_pm_info, payment_method_billing) = tokio::try_join!(
            utils::flatten_join_error(mandate_details_fut),
            utils::flatten_join_error(additional_pm_data_fut),
            utils::flatten_join_error(payment_method_billing_future),
        )?;

        let additional_pm_data = additional_pm_info.transpose()?.flatten();

        let m_helpers::MandateGenericData {
            token,
            payment_method,
            payment_method_type,
            mandate_data,
            recurring_mandate_payment_data,
            mandate_connector,
            payment_method_info,
        } = mandate_details;

        let token = token.or_else(|| payment_attempt.payment_token.clone());

        helpers::validate_pm_or_token_given(
            &request.payment_method,
            &request
                .payment_method_data
                .as_ref()
                .and_then(|pmd| pmd.payment_method_data.clone()),
            &request.payment_method_type,
            &mandate_type,
            &token,
            &request.ctp_service_details,
        )?;

        let (token_data, payment_method_info) = if let Some(token) = token.clone() {
            let token_data = helpers::retrieve_payment_token_data(
                state,
                token,
                payment_method.or(payment_attempt.payment_method),
            )
            .await?;

            let payment_method_info = helpers::retrieve_payment_method_from_db_with_token_data(
                state,
                merchant_context.get_merchant_key_store(),
                &token_data,
                storage_scheme,
            )
            .await?;
            (Some(token_data), payment_method_info)
        } else {
            (None, payment_method_info)
        };
        let additional_pm_data_from_locker = if let Some(ref pm) = payment_method_info {
            let card_detail_from_locker: Option<api::CardDetailFromLocker> = pm
                .payment_method_data
                .clone()
                .map(|x| x.into_inner().expose())
                .and_then(|v| {
                    v.parse_value("PaymentMethodsData")
                        .map_err(|err| {
                            router_env::logger::info!(
                                "PaymentMethodsData deserialization failed: {:?}",
                                err
                            )
                        })
                        .ok()
                })
                .and_then(|pmd| match pmd {
                    PaymentMethodsData::Card(crd) => Some(api::CardDetailFromLocker::from(crd)),
                    _ => None,
                });
            card_detail_from_locker.map(|card_details| {
                let additional_data = card_details.into();
                api_models::payments::AdditionalPaymentData::Card(Box::new(additional_data))
            })
        } else {
            None
        };
        // Only set `payment_attempt.payment_method_data` if `additional_pm_data_from_locker` is not None
        if let Some(additional_pm_data) = additional_pm_data_from_locker.as_ref() {
            payment_attempt.payment_method_data = Some(
                Encode::encode_to_value(additional_pm_data)
                    .change_context(errors::ApiErrorResponse::InternalServerError)
                    .attach_printable("Failed to encode additional pm data")?,
            );
        }

        payment_attempt.payment_method = payment_method.or(payment_attempt.payment_method);

        let payment_method_type = Option::<api_models::enums::PaymentMethodType>::foreign_from((
            payment_method_type,
            additional_pm_data.as_ref(),
            payment_method,
        ));

        payment_attempt.payment_method_type = payment_method_type
            .or(payment_attempt.payment_method_type)
            .or(payment_method_info
                .as_ref()
                .and_then(|pm_info| pm_info.get_payment_method_subtype()));

        // The operation merges mandate data from both request and payment_attempt
        let setup_mandate = mandate_data.map(|mut sm| {
            sm.mandate_type = payment_attempt.mandate_details.clone().or(sm.mandate_type);
            sm.update_mandate_id = payment_attempt
                .mandate_data
                .clone()
                .and_then(|mandate| mandate.update_mandate_id)
                .or(sm.update_mandate_id);
            sm
        });

        let mandate_details_present =
            payment_attempt.mandate_details.is_some() || request.mandate_data.is_some();
        helpers::validate_mandate_data_and_future_usage(
            payment_intent.setup_future_usage,
            mandate_details_present,
        )?;

        let payment_method_data_after_card_bin_call = request
            .payment_method_data
            .as_ref()
            .and_then(|request_payment_method_data| {
                request_payment_method_data.payment_method_data.as_ref()
            })
            .zip(additional_pm_data)
            .map(|(payment_method_data, additional_payment_data)| {
                payment_method_data.apply_additional_payment_data(additional_payment_data)
            })
            .transpose()
            .change_context(errors::ApiErrorResponse::InternalServerError)
            .attach_printable("Card cobadge check failed due to an invalid card network regex")?;

        payment_attempt.payment_method_billing_address_id = payment_method_billing
            .as_ref()
            .map(|payment_method_billing| payment_method_billing.address_id.clone());

        let address = PaymentAddress::new(
            shipping_address.as_ref().map(From::from),
            billing_address.as_ref().map(From::from),
            payment_method_billing.as_ref().map(From::from),
            business_profile.use_billing_as_payment_method_billing,
        );

        let payment_method_data_billing = request
            .payment_method_data
            .as_ref()
            .and_then(|pmd| pmd.payment_method_data.as_ref())
            .and_then(|payment_method_data_billing| {
                payment_method_data_billing.get_billing_address()
            })
            .map(From::from);

        let unified_address =
            address.unify_with_payment_method_data_billing(payment_method_data_billing);

        // If processor_payment_token is passed in request then populating the same in PaymentData
        let mandate_id = request
            .recurring_details
            .as_ref()
            .and_then(|recurring_details| match recurring_details {
                api_models::mandates::RecurringDetails::ProcessorPaymentToken(token) => {
                    payment_intent.is_payment_processor_token_flow = Some(true);
                    Some(api_models::payments::MandateIds {
                        mandate_id: None,
                        mandate_reference_id: Some(
                            api_models::payments::MandateReferenceId::ConnectorMandateId(
                                ConnectorMandateReferenceId::new(
                                    Some(token.processor_payment_token.clone()), // connector_mandate_id
                                    None, // payment_method_id
                                    None, // update_history
                                    None, // mandate_metadata
                                    None, // connector_mandate_request_reference_id
                                ),
                            ),
                        ),
                    })
                }
                _ => None,
            });

        let pmt_order_tax_amount = payment_intent.tax_details.clone().and_then(|tax| {
            if tax.payment_method_type.clone().map(|a| a.pmt) == payment_attempt.payment_method_type
            {
                tax.payment_method_type.map(|a| a.order_tax_amount)
            } else {
                None
            }
        });

        let order_tax_amount = pmt_order_tax_amount.or_else(|| {
            payment_intent
                .tax_details
                .clone()
                .and_then(|tax| tax.default.map(|a| a.order_tax_amount))
        });

        payment_attempt
            .net_amount
            .set_order_tax_amount(order_tax_amount);

        payment_attempt.connector_mandate_detail = Some(
            DieselConnectorMandateReferenceId::foreign_from(ConnectorMandateReferenceId::new(
                None,
                None,
                None, // update_history
                None, // mandate_metadata
                Some(common_utils::generate_id_with_len(
                    consts::CONNECTOR_MANDATE_REQUEST_REFERENCE_ID_LENGTH,
                )), // connector_mandate_request_reference_id
            )),
        );

        let payment_data = PaymentData {
            flow: PhantomData,
            payment_intent,
            payment_attempt,
            currency,
            amount,
            email: request.email.clone(),
            mandate_id: mandate_id.clone(),
            mandate_connector,
            setup_mandate,
            customer_acceptance,
            token,
            address: unified_address,
            token_data,
            confirm: request.confirm,
            payment_method_data: payment_method_data_after_card_bin_call.map(Into::into),
            payment_method_token: None,
            payment_method_info,
            force_sync: None,
            all_keys_required: None,
            refunds: vec![],
            disputes: vec![],
            attempts: None,
            sessions_token: vec![],
            card_cvc: request.card_cvc.clone(),
            creds_identifier,
            pm_token: None,
            connector_customer_id: None,
            recurring_mandate_payment_data,
            ephemeral_key: None,
            multiple_capture_data: None,
            redirect_response: None,
            surcharge_details: None,
            frm_message: None,
            payment_link_data: None,
            incremental_authorization_details: None,
            authorizations: vec![],
            authentication: None,
            recurring_details,
            poll_config: None,
            tax_data: None,
            session_id: None,
            service_details: request.ctp_service_details.clone(),
            card_testing_guard_data: None,
            vault_operation: None,
            threeds_method_comp_ind: None,
            whole_connector_response: None,
            is_manual_retry_enabled: business_profile.is_manual_retry_enabled,
        };

        let get_trackers_response = operations::GetTrackerResponse {
            operation: Box::new(self),
            customer_details: Some(customer_details),
            payment_data,
            business_profile,
            mandate_type,
        };

        Ok(get_trackers_response)
    }

    async fn validate_request_with_state(
        &self,
        state: &SessionState,
        request: &api::PaymentsRequest,
        payment_data: &mut PaymentData<F>,
        business_profile: &domain::Profile,
    ) -> RouterResult<()> {
        let payment_method_data: Option<&api_models::payments::PaymentMethodData> = request
            .payment_method_data
            .as_ref()
            .and_then(|request_payment_method_data| {
                request_payment_method_data.payment_method_data.as_ref()
            });

        let customer_id = &payment_data.payment_intent.customer_id;

        match payment_method_data {
            Some(api_models::payments::PaymentMethodData::Card(_card)) => {
                payment_data.card_testing_guard_data =
                    card_testing_guard_utils::validate_card_testing_guard_checks(
                        state,
                        request,
                        payment_method_data,
                        customer_id,
                        business_profile,
                    )
                    .await?;
                Ok(())
            }
            _ => Ok(()),
        }
    }
}

#[async_trait]
impl<F: Clone + Send + Sync> Domain<F, api::PaymentsRequest, PaymentData<F>> for PaymentConfirm {
    #[instrument(skip_all)]
    async fn get_or_create_customer_details<'a>(
        &'a self,
        state: &SessionState,
        payment_data: &mut PaymentData<F>,
        request: Option<CustomerDetails>,
        key_store: &domain::MerchantKeyStore,
        storage_scheme: common_enums::enums::MerchantStorageScheme,
    ) -> CustomResult<
        (PaymentConfirmOperation<'a, F>, Option<domain::Customer>),
        errors::StorageError,
    > {
        helpers::create_customer_if_not_exist(
            state,
            Box::new(self),
            payment_data,
            request,
            &key_store.merchant_id,
            key_store,
            storage_scheme,
        )
        .await
    }

    #[instrument(skip_all)]
    async fn make_pm_data<'a>(
        &'a self,
        state: &'a SessionState,
        payment_data: &mut PaymentData<F>,
        storage_scheme: storage_enums::MerchantStorageScheme,
        key_store: &domain::MerchantKeyStore,
        customer: &Option<domain::Customer>,
        business_profile: &domain::Profile,
        should_retry_with_pan: bool,
    ) -> RouterResult<(
        PaymentConfirmOperation<'a, F>,
        Option<domain::PaymentMethodData>,
        Option<String>,
    )> {
        let (op, payment_method_data, pm_id) = Box::pin(helpers::make_pm_data(
            Box::new(self),
            state,
            payment_data,
            key_store,
            customer,
            storage_scheme,
            business_profile,
            should_retry_with_pan,
        ))
        .await?;
        utils::when(payment_method_data.is_none(), || {
            Err(errors::ApiErrorResponse::PaymentMethodNotFound)
        })?;

        Ok((op, payment_method_data, pm_id))
    }

    #[instrument(skip_all)]
    async fn add_task_to_process_tracker<'a>(
        &'a self,
        state: &'a SessionState,
        payment_attempt: &storage::PaymentAttempt,
        requeue: bool,
        schedule_time: Option<time::PrimitiveDateTime>,
    ) -> CustomResult<(), errors::ApiErrorResponse> {
        // This spawns this futures in a background thread, the exception inside this future won't affect
        // the current thread and the lifecycle of spawn thread is not handled by runtime.
        // So when server shutdown won't wait for this thread's completion.
        let m_payment_attempt = payment_attempt.clone();
        let m_state = state.clone();
        let m_self = *self;
        tokio::spawn(
            async move {
                helpers::add_domain_task_to_pt(
                    &m_self,
                    &m_state,
                    &m_payment_attempt,
                    requeue,
                    schedule_time,
                )
                .await
            }
            .in_current_span(),
        );

        Ok(())
    }

    async fn get_connector<'a>(
        &'a self,
        _merchant_context: &domain::MerchantContext,
        state: &SessionState,
        request: &api::PaymentsRequest,
        _payment_intent: &storage::PaymentIntent,
    ) -> CustomResult<api::ConnectorChoice, errors::ApiErrorResponse> {
        // Use a new connector in the confirm call or use the same one which was passed when
        // creating the payment or if none is passed then use the routing algorithm
        helpers::get_connector_default(state, request.routing.clone()).await
    }

    #[instrument(skip_all)]
    async fn populate_payment_data<'a>(
        &'a self,
        state: &SessionState,
        payment_data: &mut PaymentData<F>,
        _merchant_context: &domain::MerchantContext,
        business_profile: &domain::Profile,
        connector_data: &api::ConnectorData,
    ) -> CustomResult<(), errors::ApiErrorResponse> {
        populate_surcharge_details(state, payment_data).await?;
        payment_data.payment_attempt.request_extended_authorization = payment_data
            .payment_intent
            .get_request_extended_authorization_bool_if_connector_supports(
                connector_data.connector_name,
                business_profile.always_request_extended_authorization,
                payment_data.payment_attempt.payment_method,
                payment_data.payment_attempt.payment_method_type,
            );
        payment_data.payment_intent.enable_overcapture = payment_data
            .payment_intent
            .get_enable_overcapture_bool_if_connector_supports(
                connector_data.connector_name,
                business_profile.always_enable_overcapture,
                &payment_data.payment_attempt.capture_method,
            );
        Ok(())
    }

    #[allow(clippy::too_many_arguments)]
    async fn call_external_three_ds_authentication_if_eligible<'a>(
        &'a self,
        state: &SessionState,
        payment_data: &mut PaymentData<F>,
        should_continue_confirm_transaction: &mut bool,
        connector_call_type: &ConnectorCallType,
        business_profile: &domain::Profile,
        key_store: &domain::MerchantKeyStore,
        mandate_type: Option<api_models::payments::MandateTransactionType>,
    ) -> CustomResult<(), errors::ApiErrorResponse> {
        let external_authentication_flow =
            helpers::get_payment_external_authentication_flow_during_confirm(
                state,
                key_store,
                business_profile,
                payment_data,
                connector_call_type,
                mandate_type,
            )
            .await?;
        payment_data.authentication = match external_authentication_flow {
            Some(helpers::PaymentExternalAuthenticationFlow::PreAuthenticationFlow {
                acquirer_details,
                card,
                token,
            }) => {
                let authentication_store = Box::pin(authentication::perform_pre_authentication(
                    state,
                    key_store,
                    *card,
                    token,
                    business_profile,
                    acquirer_details,
                    payment_data.payment_attempt.payment_id.clone(),
                    payment_data.payment_attempt.organization_id.clone(),
                    payment_data.payment_intent.force_3ds_challenge,
                    payment_data.payment_intent.psd2_sca_exemption_type,
                ))
                .await?;
                if authentication_store
                    .authentication
                    .is_separate_authn_required()
                    || authentication_store
                        .authentication
                        .authentication_status
                        .is_failed()
                {
                    *should_continue_confirm_transaction = false;
                    let default_poll_config = types::PollConfig::default();
                    let default_config_str = default_poll_config
                        .encode_to_string_of_json()
                        .change_context(errors::ApiErrorResponse::InternalServerError)
                        .attach_printable("Error while stringifying default poll config")?;

                    // raise error if authentication_connector is not present since it should we be present in the current flow
                    let authentication_connector = authentication_store
                        .authentication
                        .authentication_connector
                        .clone()
                        .ok_or(errors::ApiErrorResponse::InternalServerError)
                        .attach_printable(
                            "authentication_connector not present in authentication record",
                        )?;

                    let poll_config = state
                        .store
                        .find_config_by_key_unwrap_or(
                            &types::PollConfig::get_poll_config_key(authentication_connector),
                            Some(default_config_str),
                        )
                        .await
                        .change_context(errors::ApiErrorResponse::InternalServerError)
                        .attach_printable("The poll config was not found in the DB")?;
                    let poll_config: types::PollConfig = poll_config
                        .config
                        .parse_struct("PollConfig")
                        .change_context(errors::ApiErrorResponse::InternalServerError)
                        .attach_printable("Error while parsing PollConfig")?;
                    payment_data.poll_config = Some(poll_config)
                }
                Some(authentication_store)
            }
            Some(helpers::PaymentExternalAuthenticationFlow::PostAuthenticationFlow {
                authentication_id,
            }) => {
                let authentication_store = Box::pin(authentication::perform_post_authentication(
                    state,
                    key_store,
                    business_profile.clone(),
                    authentication_id.clone(),
                    &payment_data.payment_intent.payment_id,
                ))
                .await?;
                //If authentication is not successful, skip the payment connector flows and mark the payment as failure
                if authentication_store.authentication.authentication_status
                    != api_models::enums::AuthenticationStatus::Success
                {
                    *should_continue_confirm_transaction = false;
                }
                Some(authentication_store)
            }
            None => None,
        };
        Ok(())
    }

    async fn apply_three_ds_authentication_strategy<'a>(
        &'a self,
        state: &SessionState,


// Function: payouts_update
// File: crates/router/src/routes/payouts.rs
// Module: router

pub fn payouts_update(
    state: web::Data<AppState>,
    req: HttpRequest,
    path: web::Path<id_type::PayoutId>,
    json_payload: web::Json<payout_types::PayoutCreateRequest>,
) -> HttpResponse


// Implementation: impl FileStorageConfig
// File: crates/external_services/src/file_storage.rs
// Module: external_services
// Methods: 2 total (1 public)

impl FileStorageConfig


// Implementation: impl std::fmt::Display for for TrustpaymentsCredentialsOnFile
// File: crates/hyperswitch_connectors/src/connectors/trustpayments/transformers.rs
// Module: hyperswitch_connectors
// Methods: 1 total (0 public)

impl std::fmt::Display for for TrustpaymentsCredentialsOnFile


// Struct: StaxWebhookBody
// File: crates/hyperswitch_connectors/src/connectors/stax/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct StaxWebhookBody


// Function: new
// File: crates/hyperswitch_connectors/src/connectors/affirm.rs
// Module: hyperswitch_connectors

pub fn new() -> &'static Self


// Struct: NoonRevokeMandateResult
// File: crates/hyperswitch_connectors/src/connectors/noon/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct NoonRevokeMandateResult


// Implementation: impl GetRoutableConnectorsForChoice for for StraightThroughAlgorithmTypeSingle
// File: crates/router/src/core/routing.rs
// Module: router
// Methods: 1 total (0 public)

impl GetRoutableConnectorsForChoice for for StraightThroughAlgorithmTypeSingle


// Function: get_theme_using_lineage
// File: crates/router/src/core/user/theme.rs
// Module: router

pub fn get_theme_using_lineage(
    state: SessionState,
    lineage: ThemeLineage,
) -> UserResponse<theme_api::GetThemeResponse>


// Trait: CommonStorageInterface
// File: crates/router/src/db.rs
// Module: router

pub trait CommonStorageInterface: StorageInterface
    + GlobalStorageInterface
    + AccountsStorageInterface
    + PaymentMethodsStorageInterface


// Struct: ApplePayTokenPaymentInformation
// File: crates/hyperswitch_connectors/src/connectors/cybersource/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct ApplePayTokenPaymentInformation