    #[schema(value_type = Option<Bank>)]
    #[serde(skip_serializing_if = "Option::is_none")]
    pub bank_transfer: Option<payouts::Bank>,

    #[schema(value_type = Option<PrimitiveDateTime>, example = "2024-02-24T11:04:09.922Z")]
    #[serde(default, with = "common_utils::custom_serde::iso8601::option")]
    pub last_used_at: Option<time::PrimitiveDateTime>,

    /// For Client based calls
    pub client_secret: Option<String>,
}

#[cfg(feature = "v2")]
#[derive(Debug, serde::Deserialize, serde::Serialize, ToSchema, Clone)]
pub struct ConnectorTokenDetails {
    /// The unique identifier of the connector account through which the token was generated
    #[schema(value_type = String, example = "mca_")]
    pub connector_id: id_type::MerchantConnectorAccountId,

    #[schema(value_type = TokenizationType)]
    pub token_type: common_enums::TokenizationType,

    /// The status of connector token if it is active or inactive
    #[schema(value_type = ConnectorTokenStatus)]
    pub status: common_enums::ConnectorTokenStatus,

    /// The reference id of the connector token
    /// This is the reference that was passed to connector when creating the token
    pub connector_token_request_reference_id: Option<String>,

    pub original_payment_authorized_amount: Option<MinorUnit>,

    /// The currency of the original payment authorized amount
    #[schema(value_type = Currency)]
    pub original_payment_authorized_currency: Option<common_enums::Currency>,

    /// Metadata associated with the connector token
    pub metadata: Option<pii::SecretSerdeValue>,

    /// The value of the connector token. This token can be used to make merchant initiated payments ( MIT ), directly with the connector.
    pub token: masking::Secret<String>,
}

#[cfg(feature = "v2")]
#[derive(Debug, serde::Serialize, serde::Deserialize, ToSchema, Clone)]
pub struct PaymentMethodResponse {
    /// The unique identifier of the Payment method
    #[schema(value_type = String, example = "12345_pm_01926c58bc6e77c09e809964e72af8c8")]
    pub id: id_type::GlobalPaymentMethodId,

    /// Unique identifier for a merchant
    #[schema(value_type = String, example = "merchant_1671528864")]
    pub merchant_id: id_type::MerchantId,

    /// The unique identifier of the customer.
    #[schema(
        min_length = 32,
        max_length = 64,
        example = "12345_cus_01926c58bc6e77c09e809964e72af8c8",
        value_type = String
    )]
    pub customer_id: id_type::GlobalCustomerId,

    /// The type of payment method use for the payment.
    #[schema(value_type = PaymentMethod, example = "card")]
    pub payment_method_type: Option<api_enums::PaymentMethod>,

    /// This is a sub-category of payment method.
    #[schema(value_type = Option<PaymentMethodType>, example = "credit")]
    pub payment_method_subtype: Option<api_enums::PaymentMethodType>,

    /// Indicates whether the payment method supports recurring payments. Optional.
    #[schema(example = true)]
    pub recurring_enabled: Option<bool>,

    /// A timestamp (ISO 8601 code) that determines when the payment method was created
    #[schema(value_type = Option<PrimitiveDateTime>, example = "2023-01-18T11:04:09.922Z")]
    #[serde(default, with = "common_utils::custom_serde::iso8601::option")]
    pub created: Option<time::PrimitiveDateTime>,

    /// A timestamp (ISO 8601 code) that determines when the payment method was last used
    #[schema(value_type = Option<PrimitiveDateTime>, example = "2024-02-24T11:04:09.922Z")]
    #[serde(default, with = "common_utils::custom_serde::iso8601::option")]
    pub last_used_at: Option<time::PrimitiveDateTime>,

    /// The payment method details related to the payment method
    pub payment_method_data: Option<PaymentMethodResponseData>,

    /// The connector token details if available
    pub connector_tokens: Option<Vec<ConnectorTokenDetails>>,

    pub network_token: Option<NetworkTokenResponse>,
}

#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize)]
pub enum PaymentMethodsData {
    Card(CardDetailsPaymentMethod),
    BankDetails(PaymentMethodDataBankCreds),
    WalletDetails(PaymentMethodDataWalletInfo),
}

#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize)]
pub struct ExternalVaultTokenData {
    /// Tokenized reference for Card Number
    pub tokenized_card_number: masking::Secret<String>,
}

#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize)]
pub struct CardDetailsPaymentMethod {
    pub last4_digits: Option<String>,
    pub issuer_country: Option<String>,
    pub expiry_month: Option<masking::Secret<String>>,
    pub expiry_year: Option<masking::Secret<String>>,
    pub nick_name: Option<masking::Secret<String>>,
    pub card_holder_name: Option<masking::Secret<String>>,
    pub card_isin: Option<String>,
    pub card_issuer: Option<String>,
    pub card_network: Option<api_enums::CardNetwork>,
    pub card_type: Option<String>,
    #[serde(default = "saved_in_locker_default")]
    pub saved_to_locker: bool,
    pub co_badged_card_data: Option<CoBadgedCardDataToBeSaved>,
}

impl From<&CoBadgedCardData> for CoBadgedCardDataToBeSaved {
    fn from(co_badged_card_data: &CoBadgedCardData) -> Self {
        Self {
            co_badged_card_networks: co_badged_card_data
                .co_badged_card_networks_info
                .get_card_networks(),
            issuer_country_code: co_badged_card_data.issuer_country_code,
            is_regulated: co_badged_card_data.is_regulated,
            regulated_name: co_badged_card_data.regulated_name.clone(),
        }
    }
}

#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize)]
pub struct CoBadgedCardData {
    pub co_badged_card_networks_info: open_router::CoBadgedCardNetworks,
    pub issuer_country_code: common_enums::CountryAlpha2,
    pub is_regulated: bool,
    pub regulated_name: Option<common_enums::RegulatedName>,
}

#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize)]
pub struct CoBadgedCardDataToBeSaved {
    pub co_badged_card_networks: Vec<common_enums::CardNetwork>,
    pub issuer_country_code: common_enums::CountryAlpha2,
    pub is_regulated: bool,
    pub regulated_name: Option<common_enums::RegulatedName>,
}

#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, ToSchema)]
pub struct NetworkTokenDetailsPaymentMethod {
    pub last4_digits: Option<String>,
    #[schema(value_type = Option<CountryAlpha2>)]
    pub issuer_country: Option<common_enums::CountryAlpha2>,
    #[schema(value_type = Option<String>)]
    pub network_token_expiry_month: Option<masking::Secret<String>>,
    #[schema(value_type = Option<String>)]
    pub network_token_expiry_year: Option<masking::Secret<String>>,
    #[schema(value_type = Option<String>)]
    pub nick_name: Option<masking::Secret<String>>,
    #[schema(value_type = Option<String>)]
    pub card_holder_name: Option<masking::Secret<String>>,
    pub card_isin: Option<String>,
    pub card_issuer: Option<String>,
    #[schema(value_type = Option<CardNetwork>)]
    pub card_network: Option<api_enums::CardNetwork>,
    pub card_type: Option<String>,
    #[serde(default = "saved_in_locker_default")]
    pub saved_to_locker: bool,
}

#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct PaymentMethodDataBankCreds {
    pub mask: String,
    pub hash: String,
    pub account_type: Option<String>,
    pub account_name: Option<String>,
    pub payment_method_type: api_enums::PaymentMethodType,
    pub connector_details: Vec<BankAccountConnectorDetails>,
}

#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
pub struct PaymentMethodDataWalletInfo {
    /// Last 4 digits of the card number
    pub last4: String,
    /// The information of the payment method
    pub card_network: String,
    /// The type of payment method
    #[serde(rename = "type")]
    pub card_type: Option<String>,
}

impl From<payments::additional_info::WalletAdditionalDataForCard> for PaymentMethodDataWalletInfo {
    fn from(item: payments::additional_info::WalletAdditionalDataForCard) -> Self {
        Self {
            last4: item.last4,
            card_network: item.card_network,
            card_type: item.card_type,
        }
    }
}

impl From<PaymentMethodDataWalletInfo> for payments::additional_info::WalletAdditionalDataForCard {
    fn from(item: PaymentMethodDataWalletInfo) -> Self {
        Self {
            last4: item.last4,
            card_network: item.card_network,
            card_type: item.card_type,
        }
    }
}

impl From<payments::ApplepayPaymentMethod> for PaymentMethodDataWalletInfo {
    fn from(item: payments::ApplepayPaymentMethod) -> Self {
        Self {
            last4: item
                .display_name
                .chars()
                .rev()
                .take(4)
                .collect::<Vec<_>>()
                .into_iter()
                .rev()
                .collect(),
            card_network: item.network,
            card_type: Some(item.pm_type),
        }
    }
}

impl TryFrom<PaymentMethodDataWalletInfo> for payments::ApplepayPaymentMethod {
    type Error = error_stack::Report<errors::ValidationError>;
    fn try_from(item: PaymentMethodDataWalletInfo) -> Result<Self, Self::Error> {
        Ok(Self {
            display_name: item.last4,
            network: item.card_network,
            pm_type: item.card_type.get_required_value("card_type")?,
        })
    }
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct BankAccountTokenData {
    pub payment_method_type: api_enums::PaymentMethodType,
    pub payment_method: api_enums::PaymentMethod,
    pub connector_details: BankAccountConnectorDetails,
}

#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct BankAccountConnectorDetails {
    pub connector: String,
    pub account_id: masking::Secret<String>,
    pub mca_id: id_type::MerchantConnectorAccountId,
    pub access_token: BankAccountAccessCreds,
}

#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
pub enum BankAccountAccessCreds {
    AccessToken(masking::Secret<String>),
}

#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
pub struct Card {
    pub card_number: CardNumber,
    pub name_on_card: Option<masking::Secret<String>>,
    pub card_exp_month: masking::Secret<String>,
    pub card_exp_year: masking::Secret<String>,
    pub card_brand: Option<String>,
    pub card_isin: Option<String>,
    pub nick_name: Option<String>,
}

#[cfg(feature = "v1")]
impl From<(Card, Option<common_enums::CardNetwork>)> for CardDetail {
    fn from((card, card_network): (Card, Option<common_enums::CardNetwork>)) -> Self {
        Self {
            card_number: card.card_number.clone(),
            card_exp_month: card.card_exp_month.clone(),
            card_exp_year: card.card_exp_year.clone(),
            card_holder_name: card.name_on_card.clone(),
            nick_name: card.nick_name.map(masking::Secret::new),
            card_issuing_country: None,
            card_network,
            card_issuer: None,
            card_type: None,
        }
    }
}

#[cfg(feature = "v1")]
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone, ToSchema)]
pub struct CardDetailFromLocker {
    pub scheme: Option<String>,
    pub issuer_country: Option<String>,
    pub last4_digits: Option<String>,
    #[serde(skip)]
    #[schema(value_type=Option<String>)]
    pub card_number: Option<CardNumber>,

    #[schema(value_type=Option<String>)]
    pub expiry_month: Option<masking::Secret<String>>,

    #[schema(value_type=Option<String>)]
    pub expiry_year: Option<masking::Secret<String>>,

    #[schema(value_type=Option<String>)]
    pub card_token: Option<masking::Secret<String>>,

    #[schema(value_type=Option<String>)]
    pub card_holder_name: Option<masking::Secret<String>>,

    #[schema(value_type=Option<String>)]
    pub card_fingerprint: Option<masking::Secret<String>>,

    #[schema(value_type=Option<String>)]
    pub nick_name: Option<masking::Secret<String>>,

    #[schema(value_type = Option<CardNetwork>)]
    pub card_network: Option<api_enums::CardNetwork>,

    pub card_isin: Option<String>,
    pub card_issuer: Option<String>,
    pub card_type: Option<String>,
    pub saved_to_locker: bool,
}

#[cfg(feature = "v2")]
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone, ToSchema)]
pub struct CardDetailFromLocker {
    #[schema(value_type = Option<CountryAlpha2>)]
    pub issuer_country: Option<api_enums::CountryAlpha2>,
    pub last4_digits: Option<String>,
    #[serde(skip)]
    #[schema(value_type=Option<String>)]
    pub card_number: Option<CardNumber>,

    #[schema(value_type=Option<String>)]
    pub expiry_month: Option<masking::Secret<String>>,

    #[schema(value_type=Option<String>)]
    pub expiry_year: Option<masking::Secret<String>>,

    #[schema(value_type=Option<String>)]
    pub card_holder_name: Option<masking::Secret<String>>,

    #[schema(value_type=Option<String>)]
    pub card_fingerprint: Option<masking::Secret<String>>,

    #[schema(value_type=Option<String>)]
    pub nick_name: Option<masking::Secret<String>>,

    #[schema(value_type = Option<CardNetwork>)]
    pub card_network: Option<api_enums::CardNetwork>,

    pub card_isin: Option<String>,
    pub card_issuer: Option<String>,
    pub card_type: Option<String>,
    pub saved_to_locker: bool,
}

#[cfg(feature = "v2")]
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone, ToSchema)]
pub struct NetworkTokenResponse {
    pub payment_method_data: NetworkTokenDetailsPaymentMethod,
}

fn saved_in_locker_default() -> bool {
    true
}

#[cfg(feature = "v1")]
impl From<CardDetailFromLocker> for payments::AdditionalCardInfo {
    fn from(item: CardDetailFromLocker) -> Self {
        Self {
            card_issuer: item.card_issuer,
            card_network: item.card_network,
            card_type: item.card_type,
            card_issuing_country: item.issuer_country,
            bank_code: None,
            last4: item.last4_digits,
            card_isin: item.card_isin,
            card_extended_bin: item
                .card_number
                .map(|card_number| card_number.get_extended_card_bin()),
            card_exp_month: item.expiry_month,
            card_exp_year: item.expiry_year,
            card_holder_name: item.card_holder_name,
            payment_checks: None,
            authentication_data: None,
            is_regulated: None,
            signature_network: None,
        }
    }
}

#[cfg(feature = "v2")]
impl From<CardDetailFromLocker> for payments::AdditionalCardInfo {
    fn from(item: CardDetailFromLocker) -> Self {
        Self {
            card_issuer: item.card_issuer,
            card_network: item.card_network,
            card_type: item.card_type,
            card_issuing_country: item.issuer_country.map(|country| country.to_string()),
            bank_code: None,
            last4: item.last4_digits,
            card_isin: item.card_isin,
            card_extended_bin: item
                .card_number
                .map(|card_number| card_number.get_extended_card_bin()),
            card_exp_month: item.expiry_month,
            card_exp_year: item.expiry_year,
            card_holder_name: item.card_holder_name,
            payment_checks: None,
            authentication_data: None,
            is_regulated: None,
            signature_network: None,
        }
    }
}

#[cfg(feature = "v2")]
#[derive(Debug, serde::Serialize, ToSchema)]
pub struct PaymentMethodListResponseForSession {
    /// The list of payment methods that are enabled for the business profile
    pub payment_methods_enabled: Vec<ResponsePaymentMethodTypes>,

    /// The list of saved payment methods of the customer
    pub customer_payment_methods: Vec<CustomerPaymentMethodResponseItem>,
}

#[cfg(feature = "v1")]
impl From<CardDetailsPaymentMethod> for CardDetailFromLocker {
    fn from(item: CardDetailsPaymentMethod) -> Self {
        Self {
            scheme: None,
            issuer_country: item.issuer_country,
            last4_digits: item.last4_digits,
            card_number: None,
            expiry_month: item.expiry_month,
            expiry_year: item.expiry_year,
            card_token: None,
            card_holder_name: item.card_holder_name,
            card_fingerprint: None,
            nick_name: item.nick_name,
            card_isin: item.card_isin,
            card_issuer: item.card_issuer,
            card_network: item.card_network,
            card_type: item.card_type,
            saved_to_locker: item.saved_to_locker,
        }
    }
}

#[cfg(feature = "v2")]
impl From<CardDetailsPaymentMethod> for CardDetailFromLocker {
    fn from(item: CardDetailsPaymentMethod) -> Self {
        Self {
            issuer_country: item
                .issuer_country
                .as_ref()
                .map(|c| api_enums::CountryAlpha2::from_str(c))
                .transpose()
                .ok()
                .flatten(),
            last4_digits: item.last4_digits,
            card_number: None,
            expiry_month: item.expiry_month,
            expiry_year: item.expiry_year,
            card_holder_name: item.card_holder_name,
            card_fingerprint: None,
            nick_name: item.nick_name,
            card_isin: item.card_isin,
            card_issuer: item.card_issuer,
            card_network: item.card_network,
            card_type: item.card_type,
            saved_to_locker: item.saved_to_locker,
        }
    }
}

#[cfg(feature = "v2")]
impl From<CardDetail> for CardDetailFromLocker {
    fn from(item: CardDetail) -> Self {
        Self {
            issuer_country: item.card_issuing_country,
            last4_digits: Some(item.card_number.get_last4()),
            card_number: Some(item.card_number),
            expiry_month: Some(item.card_exp_month),
            expiry_year: Some(item.card_exp_year),
            card_holder_name: item.card_holder_name,
            nick_name: item.nick_name,
            card_isin: None,
            card_issuer: item.card_issuer,
            card_network: item.card_network,
            card_type: item.card_type.map(|card| card.to_string()),
            saved_to_locker: true,
            card_fingerprint: None,
        }
    }
}

#[cfg(feature = "v1")]
impl From<CardDetail> for CardDetailFromLocker {
    fn from(item: CardDetail) -> Self {
        // scheme should be updated in case of co-badged cards
        let card_scheme = item
            .card_network
            .clone()
            .map(|card_network| card_network.to_string());
        Self {
            issuer_country: item.card_issuing_country,
            last4_digits: Some(item.card_number.get_last4()),
            card_number: Some(item.card_number),
            expiry_month: Some(item.card_exp_month),
            expiry_year: Some(item.card_exp_year),
            card_holder_name: item.card_holder_name,
            nick_name: item.nick_name,
            card_isin: None,
            card_issuer: item.card_issuer,
            card_network: item.card_network,
            card_type: item.card_type.map(|card| card.to_string()),
            saved_to_locker: true,
            card_fingerprint: None,
            scheme: card_scheme,
            card_token: None,
        }
    }
}

#[cfg(feature = "v2")]
impl From<CardDetail> for CardDetailsPaymentMethod {
    fn from(item: CardDetail) -> Self {
        Self {
            issuer_country: item.card_issuing_country.map(|c| c.to_string()),
            last4_digits: Some(item.card_number.get_last4()),
            expiry_month: Some(item.card_exp_month),
            expiry_year: Some(item.card_exp_year),
            card_holder_name: item.card_holder_name,
            nick_name: item.nick_name,
            card_isin: None,
            card_issuer: item.card_issuer,
            card_network: item.card_network,
            card_type: item.card_type.map(|card| card.to_string()),
            saved_to_locker: true,
            co_badged_card_data: None,
        }
    }
}

#[cfg(feature = "v1")]
impl From<(CardDetailFromLocker, Option<&CoBadgedCardData>)> for CardDetailsPaymentMethod {
    fn from(
        (item, co_badged_card_data): (CardDetailFromLocker, Option<&CoBadgedCardData>),
    ) -> Self {
        Self {
            issuer_country: item.issuer_country,
            last4_digits: item.last4_digits,
            expiry_month: item.expiry_month,
            expiry_year: item.expiry_year,
            nick_name: item.nick_name,
            card_holder_name: item.card_holder_name,
            card_isin: item.card_isin,
            card_issuer: item.card_issuer,
            card_network: item.card_network,
            card_type: item.card_type,
            saved_to_locker: item.saved_to_locker,
            co_badged_card_data: co_badged_card_data.map(CoBadgedCardDataToBeSaved::from),
        }
    }
}

#[cfg(feature = "v2")]
impl From<CardDetailFromLocker> for CardDetailsPaymentMethod {
    fn from(item: CardDetailFromLocker) -> Self {
        Self {
            issuer_country: item.issuer_country.map(|country| country.to_string()),
            last4_digits: item.last4_digits,
            expiry_month: item.expiry_month,
            expiry_year: item.expiry_year,
            nick_name: item.nick_name,
            card_holder_name: item.card_holder_name,
            card_isin: item.card_isin,
            card_issuer: item.card_issuer,
            card_network: item.card_network,
            card_type: item.card_type,
            saved_to_locker: item.saved_to_locker,
            co_badged_card_data: None,
        }
    }
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema, PartialEq, Eq)]
pub struct PaymentExperienceTypes {
    /// The payment experience enabled
    #[schema(value_type = Option<PaymentExperience>, example = "redirect_to_url")]
    pub payment_experience_type: api_enums::PaymentExperience,

    /// The list of eligible connectors for a given payment experience
    #[schema(example = json!(["stripe", "adyen"]))]
    pub eligible_connectors: Vec<String>,
}

#[derive(Debug, Clone, serde::Serialize, ToSchema, PartialEq)]
pub struct CardNetworkTypes {
    /// The card network enabled
    #[schema(value_type = Option<CardNetwork>, example = "Visa")]
    pub card_network: api_enums::CardNetwork,

    /// surcharge details for this card network
    pub surcharge_details: Option<SurchargeDetailsResponse>,

    /// The list of eligible connectors for a given card network
    #[schema(example = json!(["stripe", "adyen"]))]
    pub eligible_connectors: Vec<String>,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema, PartialEq, Eq)]
pub struct BankDebitTypes {
    pub eligible_connectors: Vec<String>,
}

#[cfg(feature = "v1")]
#[derive(Debug, Clone, serde::Serialize, ToSchema, PartialEq)]
pub struct ResponsePaymentMethodTypes {
    /// The payment method type enabled
    #[schema(example = "klarna", value_type = PaymentMethodType)]
    pub payment_method_type: api_enums::PaymentMethodType,

    /// The list of payment experiences enabled, if applicable for a payment method type
    pub payment_experience: Option<Vec<PaymentExperienceTypes>>,

    /// The list of card networks enabled, if applicable for a payment method type
    pub card_networks: Option<Vec<CardNetworkTypes>>,

    #[schema(deprecated)]
    /// The list of banks enabled, if applicable for a payment method type . To be deprecated soon.
    pub bank_names: Option<Vec<BankCodeResponse>>,

    /// The Bank debit payment method information, if applicable for a payment method type.
    pub bank_debits: Option<BankDebitTypes>,

    /// The Bank transfer payment method information, if applicable for a payment method type.
    pub bank_transfers: Option<BankTransferTypes>,

    /// Required fields for the payment_method_type.
    pub required_fields: Option<HashMap<String, RequiredFieldInfo>>,

    /// surcharge details for this payment method type if exists
    pub surcharge_details: Option<SurchargeDetailsResponse>,

    /// auth service connector label for this payment method type, if exists
    pub pm_auth_connector: Option<String>,
}

#[cfg(feature = "v2")]
#[derive(Debug, Clone, serde::Serialize, ToSchema, PartialEq)]
#[serde(untagged)] // Untagged used for serialization only
pub enum PaymentMethodSubtypeSpecificData {
    #[schema(title = "card")]
    Card {
        card_networks: Vec<CardNetworkTypes>,
    },
    #[schema(title = "bank")]
    Bank {
        #[schema(value_type = BankNames)]
        bank_names: Vec<common_enums::BankNames>,
    },
}

#[cfg(feature = "v2")]
#[derive(Debug, Clone, serde::Serialize, ToSchema, PartialEq)]
pub struct ResponsePaymentMethodTypes {
    /// The payment method type enabled
    #[schema(example = "pay_later", value_type = PaymentMethod)]
    pub payment_method_type: common_enums::PaymentMethod,

    /// The payment method subtype enabled
    #[schema(example = "klarna", value_type = PaymentMethodType)]
    pub payment_method_subtype: common_enums::PaymentMethodType,

    /// payment method subtype specific information
    #[serde(flatten)]
    pub extra_information: Option<PaymentMethodSubtypeSpecificData>,

    /// Required fields for the payment_method_type.
    /// This is the union of all the required fields for the payment method type enabled in all the connectors.
    pub required_fields: Vec<RequiredFieldInfo>,
}

#[derive(Clone, Debug, PartialEq, serde::Serialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub struct SurchargeDetailsResponse {
    /// surcharge value
    pub surcharge: SurchargeResponse,
    /// tax on surcharge value
    pub tax_on_surcharge: Option<SurchargePercentage>,
    /// surcharge amount for this payment
    pub display_surcharge_amount: f64,
    /// tax on surcharge amount for this payment
    pub display_tax_on_surcharge_amount: f64,
    /// sum of display_surcharge_amount and display_tax_on_surcharge_amount
    pub display_total_surcharge_amount: f64,
}

#[derive(Clone, Debug, PartialEq, serde::Serialize, ToSchema)]
#[serde(rename_all = "snake_case", tag = "type", content = "value")]
pub enum SurchargeResponse {
    /// Fixed Surcharge value
    Fixed(MinorUnit),
    /// Surcharge percentage
    Rate(SurchargePercentage),
}

impl From<Surcharge> for SurchargeResponse {
    fn from(value: Surcharge) -> Self {
        match value {
            Surcharge::Fixed(amount) => Self::Fixed(amount),
            Surcharge::Rate(percentage) => Self::Rate(percentage.into()),
        }
    }
}

#[derive(Clone, Default, Debug, PartialEq, serde::Serialize, ToSchema)]
pub struct SurchargePercentage {
    percentage: f32,
}

impl From<Percentage<SURCHARGE_PERCENTAGE_PRECISION_LENGTH>> for SurchargePercentage {
    fn from(value: Percentage<SURCHARGE_PERCENTAGE_PRECISION_LENGTH>) -> Self {
        Self {
            percentage: value.get_percentage(),
        }
    }
}
/// Required fields info used while listing the payment_method_data
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone, PartialEq, Eq, ToSchema)]
pub struct RequiredFieldInfo {
    /// Required field for a payment_method through a payment_method_type
    pub required_field: String,

    /// Display name of the required field in the front-end
    pub display_name: String,

    /// Possible field type of required field
    #[schema(value_type = FieldType)]
    pub field_type: api_enums::FieldType,

    #[schema(value_type = Option<String>)]
    pub value: Option<masking::Secret<String>>,
}

#[derive(Debug, Clone, serde::Serialize, ToSchema)]
pub struct ResponsePaymentMethodsEnabled {
    /// The payment method enabled
    #[schema(value_type = PaymentMethod)]
    pub payment_method: api_enums::PaymentMethod,

    /// The list of payment method types enabled for a connector account
    pub payment_method_types: Vec<ResponsePaymentMethodTypes>,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema, PartialEq, Eq)]
pub struct BankTransferTypes {
    /// The list of eligible connectors for a given payment experience
    #[schema(example = json!(["stripe", "adyen"]))]
    pub eligible_connectors: Vec<String>,
}

#[derive(Clone, Debug)]
pub struct ResponsePaymentMethodIntermediate {
    pub payment_method_type: api_enums::PaymentMethodType,
    pub payment_experience: Option<api_enums::PaymentExperience>,
    pub card_networks: Option<Vec<api_enums::CardNetwork>>,
    pub payment_method: api_enums::PaymentMethod,
    pub connector: String,
    pub merchant_connector_id: String,
}

impl ResponsePaymentMethodIntermediate {
    pub fn new(
        pm_type: RequestPaymentMethodTypes,
        connector: String,
        merchant_connector_id: String,
        pm: api_enums::PaymentMethod,
    ) -> Self {
        Self {
            payment_method_type: pm_type.payment_method_type,
            payment_experience: pm_type.payment_experience,
            card_networks: pm_type.card_networks,
            payment_method: pm,
            connector,
            merchant_connector_id,
        }
    }
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema, PartialEq, Eq, Hash)]
pub struct RequestPaymentMethodTypes {
    #[schema(value_type = PaymentMethodType)]
    pub payment_method_type: api_enums::PaymentMethodType,
    #[schema(value_type = Option<PaymentExperience>)]
    pub payment_experience: Option<api_enums::PaymentExperience>,
    #[schema(value_type = Option<Vec<CardNetwork>>)]
    pub card_networks: Option<Vec<api_enums::CardNetwork>>,
    /// List of currencies accepted or has the processing capabilities of the processor
    #[schema(example = json!(
        {
            "type": "specific_accepted",
            "list": ["USD", "INR"]
        }
    ), value_type = Option<AcceptedCurrencies>)]
    pub accepted_currencies: Option<admin::AcceptedCurrencies>,

    ///  List of Countries accepted or has the processing capabilities of the processor
    #[schema(example = json!(
        {
            "type": "specific_accepted",
            "list": ["UK", "AU"]
        }
    ), value_type = Option<AcceptedCountries>)]
    pub accepted_countries: Option<admin::AcceptedCountries>,

    /// Minimum amount supported by the processor. To be represented in the lowest denomination of the target currency (For example, for USD it should be in cents)
    #[schema(example = 1)]
    pub minimum_amount: Option<MinorUnit>,

    /// Maximum amount supported by the processor. To be represented in the lowest denomination of
    /// the target currency (For example, for USD it should be in cents)
    #[schema(example = 1313)]
    pub maximum_amount: Option<MinorUnit>,

    /// Indicates whether the payment method supports recurring payments. Optional.
    #[schema(example = false)]
    pub recurring_enabled: Option<bool>,

    /// Indicates whether the payment method is eligible for installment payments (e.g., EMI, BNPL). Optional.
    #[schema(example = true)]
    pub installment_payment_enabled: Option<bool>,
}
impl RequestPaymentMethodTypes {
    /// Get payment_method_type
    #[cfg(feature = "v1")]
    pub fn get_payment_method_type(&self) -> Option<api_enums::PaymentMethodType> {
        Some(self.payment_method_type)
    }
}

#[cfg(feature = "v1")]
//List Payment Method
#[derive(Debug, Clone, serde::Serialize, Default, ToSchema)]
#[serde(deny_unknown_fields)]
pub struct PaymentMethodListRequest {
    /// This is a 15 minute expiry token which shall be used from the client to authenticate and perform sessions from the SDK
    #[schema(max_length = 30, min_length = 30, example = "secret_k2uj3he2893eiu2d")]
    pub client_secret: Option<String>,

    /// The two-letter ISO currency code
    #[schema(value_type = Option<Vec<CountryAlpha2>>, example = json!(["US", "UK", "IN"]))]
    pub accepted_countries: Option<Vec<api_enums::CountryAlpha2>>,

    /// The three-letter ISO currency code
    #[schema(value_type = Option<Vec<Currency>>,example = json!(["USD", "EUR"]))]
    pub accepted_currencies: Option<Vec<api_enums::Currency>>,

    /// Filter by amount
    #[schema(example = 60)]
    pub amount: Option<MinorUnit>,

    /// Indicates whether the payment method supports recurring payments. Optional.
    #[schema(example = true)]
    pub recurring_enabled: Option<bool>,

    /// Indicates whether the payment method is eligible for installment payments (e.g., EMI, BNPL). Optional.
    #[schema(example = true)]
    pub installment_payment_enabled: Option<bool>,

    /// Indicates whether the payment method is eligible for card netwotks
    #[schema(value_type = Option<Vec<CardNetwork>>, example = json!(["visa", "mastercard"]))]
    pub card_networks: Option<Vec<api_enums::CardNetwork>>,

    /// Indicates the limit of last used payment methods
    #[schema(example = 1)]
    pub limit: Option<i64>,
}

#[cfg(feature = "v1")]
impl<'de> serde::Deserialize<'de> for PaymentMethodListRequest {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        struct FieldVisitor;

        impl<'de> de::Visitor<'de> for FieldVisitor {
            type Value = PaymentMethodListRequest;

            fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
                formatter.write_str("Failed while deserializing as map")
            }

            fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
            where
                A: de::MapAccess<'de>,
            {
                let mut output = PaymentMethodListRequest::default();

                while let Some(key) = map.next_key()? {
                    match key {
                        "client_secret" => {
                            set_or_reject_duplicate(
                                &mut output.client_secret,
                                "client_secret",
                                map.next_value()?,
                            )?;
                        }
                        "accepted_countries" => match output.accepted_countries.as_mut() {
                            Some(inner) => inner.push(map.next_value()?),
                            None => {
                                output.accepted_countries = Some(vec![map.next_value()?]);
                            }
                        },
                        "accepted_currencies" => match output.accepted_currencies.as_mut() {
                            Some(inner) => inner.push(map.next_value()?),
                            None => {
                                output.accepted_currencies = Some(vec![map.next_value()?]);
                            }
                        },
                        "amount" => {
                            set_or_reject_duplicate(
                                &mut output.amount,
                                "amount",
                                map.next_value()?,
                            )?;
                        }
                        "recurring_enabled" => {
                            set_or_reject_duplicate(
                                &mut output.recurring_enabled,
                                "recurring_enabled",
                                map.next_value()?,
                            )?;
                        }
                        "installment_payment_enabled" => {
                            set_or_reject_duplicate(
                                &mut output.installment_payment_enabled,
                                "installment_payment_enabled",
                                map.next_value()?,
                            )?;
                        }
                        "card_network" => match output.card_networks.as_mut() {
                            Some(inner) => inner.push(map.next_value()?),
                            None => output.card_networks = Some(vec![map.next_value()?]),
                        },
                        "limit" => {
                            set_or_reject_duplicate(&mut output.limit, "limit", map.next_value()?)?;
                        }
                        _ => {}
                    }
                }

                Ok(output)


// Implementation: impl EmailSettings
// File: crates/external_services/src/email.rs
// Module: external_services
// Methods: 1 total (1 public)

impl EmailSettings


// Implementation: impl api::PaymentToken for for Prophetpay
// File: crates/hyperswitch_connectors/src/connectors/prophetpay.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::PaymentToken for for Prophetpay


// Function: connector_create
// File: crates/openapi/src/routes/merchant_connector_account.rs
// Module: openapi

pub fn connector_create()


// Function: apply_changeset
// File: crates/diesel_models/src/merchant_account.rs
// Module: diesel_models

pub fn apply_changeset(self, source: MerchantAccount) -> MerchantAccount


// Function: update_payouts_and_payout_attempt
// File: crates/router/src/core/payouts/helpers.rs
// Module: router

pub fn update_payouts_and_payout_attempt(
    _payout_data: &mut PayoutData,
    _merchant_context: &domain::MerchantContext,
    _req: &payouts::PayoutCreateRequest,
    _state: &SessionState,
) -> CustomResult<(), errors::ApiErrorResponse>


// Function: three_ds_decision_rule_execute
// File: crates/openapi/src/routes/three_ds_decision_rule.rs
// Module: openapi

pub fn three_ds_decision_rule_execute()


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

// Public submodules:
pub mod transformers;


// Function: validate_card_expiry
// File: crates/payment_methods/src/core/migration.rs
// Module: payment_methods

pub fn validate_card_expiry(
    card_exp_month: &masking::Secret<String>,
    card_exp_year: &masking::Secret<String>,
) -> errors::CustomResult<(), errors::ApiErrorResponse>


// Implementation: impl PaymentCapture for for Plaid
// File: crates/hyperswitch_connectors/src/connectors/plaid.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl PaymentCapture for for Plaid


// Function: fetch_user_roles_by_payload
// File: crates/router/src/utils/user_role.rs
// Module: router

pub fn fetch_user_roles_by_payload(
    state: &SessionState,
    payload: ListUserRolesByOrgIdPayload<'_>,
    request_entity_type: Option<EntityType>,
) -> UserResult<HashSet<UserRole>>


// Module Structure
// File: crates/router/src/routes/payments.rs
// Module: router

// Public submodules:
pub mod helpers;


// Function: list_all_themes_in_lineage
// File: crates/router/src/routes/user/theme.rs
// Module: router

pub fn list_all_themes_in_lineage(
    state: web::Data<AppState>,
    req: HttpRequest,
    query: web::Query<theme_api::EntityTypeQueryParam>,
) -> HttpResponse


// File: crates/payment_methods/src/configs/settings.rs
// Module: payment_methods
// Public structs: 15

use std::collections::{HashMap, HashSet};

use api_models::{enums, payment_methods::RequiredFieldInfo};
use common_utils::errors::CustomResult;
use hyperswitch_interfaces::secrets_interface::{
    secret_handler::SecretsHandler,
    secret_state::{RawSecret, SecretStateContainer, SecuredSecret},
    SecretManagementInterface, SecretsManagementError,
};
use masking::Secret;
use serde::{self, Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize, Clone)]
#[cfg_attr(feature = "v2", derive(Default))] // Configs are read from the config file in config/payment_required_fields.toml
pub struct RequiredFields(pub HashMap<enums::PaymentMethod, PaymentMethodType>);

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct PaymentMethodType(pub HashMap<enums::PaymentMethodType, ConnectorFields>);

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct ConnectorFields {
    pub fields: HashMap<enums::Connector, RequiredFieldFinal>,
}

#[derive(Debug, Deserialize, Clone, Default)]
pub struct BankRedirectConfig(pub HashMap<enums::PaymentMethodType, ConnectorBankNames>);
#[derive(Debug, Deserialize, Clone)]
pub struct ConnectorBankNames(pub HashMap<String, BanksVector>);

#[derive(Debug, Deserialize, Clone)]
pub struct BanksVector {
    #[serde(deserialize_with = "deserialize_hashset")]
    pub banks: HashSet<common_enums::enums::BankNames>,
}

#[cfg(feature = "v1")]
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct RequiredFieldFinal {
    pub mandate: HashMap<String, RequiredFieldInfo>,
    pub non_mandate: HashMap<String, RequiredFieldInfo>,
    pub common: HashMap<String, RequiredFieldInfo>,
}
#[cfg(feature = "v2")]
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct RequiredFieldFinal {
    pub mandate: Option<Vec<RequiredFieldInfo>>,
    pub non_mandate: Option<Vec<RequiredFieldInfo>>,
    pub common: Option<Vec<RequiredFieldInfo>>,
}

#[derive(Debug, Deserialize, Clone, Default)]
pub struct PaymentMethodAuth {
    pub redis_expiry: i64,
    pub pm_auth_key: Secret<String>,
}

#[async_trait::async_trait]
impl SecretsHandler for PaymentMethodAuth {
    async fn convert_to_raw_secret(
        value: SecretStateContainer<Self, SecuredSecret>,
        secret_management_client: &dyn SecretManagementInterface,
    ) -> CustomResult<SecretStateContainer<Self, RawSecret>, SecretsManagementError> {
        let payment_method_auth = value.get_inner();

        let pm_auth_key = secret_management_client
            .get_secret(payment_method_auth.pm_auth_key.clone())
            .await?;

        Ok(value.transition_state(|payment_method_auth| Self {
            pm_auth_key,
            ..payment_method_auth
        }))
    }
}

#[derive(Debug, Deserialize, Clone, Default)]
#[serde(default)]
pub struct EligiblePaymentMethods {
    #[serde(deserialize_with = "deserialize_hashset")]
    pub sdk_eligible_payment_methods: HashSet<String>,
}
#[derive(Debug, Deserialize, Clone)]
pub struct SupportedPaymentMethodsForMandate(
    pub HashMap<enums::PaymentMethod, SupportedPaymentMethodTypesForMandate>,
);

#[derive(Debug, Deserialize, Clone)]
pub struct SupportedPaymentMethodTypesForMandate(
    pub HashMap<enums::PaymentMethodType, SupportedConnectorsForMandate>,
);

#[derive(Debug, Deserialize, Clone)]
pub struct SupportedConnectorsForMandate {
    #[serde(deserialize_with = "deserialize_hashset")]
    pub connector_list: HashSet<enums::Connector>,
}
#[derive(Debug, Deserialize, Clone)]
pub struct Mandates {
    pub supported_payment_methods: SupportedPaymentMethodsForMandate,
    pub update_mandate_supported: SupportedPaymentMethodsForMandate,
}

#[derive(Debug, Deserialize, Clone)]
pub struct ZeroMandates {
    pub supported_payment_methods: SupportedPaymentMethodsForMandate,
}

fn deserialize_hashset_inner<T>(value: impl AsRef<str>) -> Result<HashSet<T>, String>
where
    T: Eq + std::str::FromStr + std::hash::Hash,
    <T as std::str::FromStr>::Err: std::fmt::Display,
{
    let (values, errors) = value
        .as_ref()
        .trim()
        .split(',')
        .map(|s| {
            T::from_str(s.trim()).map_err(|error| {
                format!(
                    "Unable to deserialize `{}` as `{}`: {error}",
                    s.trim(),
                    std::any::type_name::<T>()
                )
            })
        })
        .fold(
            (HashSet::new(), Vec::new()),
            |(mut values, mut errors), result| match result {
                Ok(t) => {
                    values.insert(t);
                    (values, errors)
                }
                Err(error) => {
                    errors.push(error);
                    (values, errors)
                }
            },
        );
    if !errors.is_empty() {
        Err(format!("Some errors occurred:\n{}", errors.join("\n")))
    } else {
        Ok(values)
    }
}

fn deserialize_hashset<'a, D, T>(deserializer: D) -> Result<HashSet<T>, D::Error>
where
    D: serde::Deserializer<'a>,
    T: Eq + std::str::FromStr + std::hash::Hash,
    <T as std::str::FromStr>::Err: std::fmt::Display,
{
    use serde::de::Error;

    deserialize_hashset_inner(<String>::deserialize(deserializer)?).map_err(D::Error::custom)
}


// File: crates/router/src/core/errors/user.rs
// Module: router
// Public functions: 1

use common_utils::errors::CustomResult;

use crate::services::ApplicationResponse;

pub type UserResult<T> = CustomResult<T, UserErrors>;
pub type UserResponse<T> = CustomResult<ApplicationResponse<T>, UserErrors>;
pub mod sample_data;

#[derive(Debug, thiserror::Error)]
pub enum UserErrors {
    #[error("User InternalServerError")]
    InternalServerError,
    #[error("InvalidCredentials")]
    InvalidCredentials,
    #[error("UserNotFound")]
    UserNotFound,
    #[error("UserExists")]
    UserExists,
    #[error("LinkInvalid")]
    LinkInvalid,
    #[error("UnverifiedUser")]
    UnverifiedUser,
    #[error("InvalidOldPassword")]
    InvalidOldPassword,
    #[error("EmailParsingError")]
    EmailParsingError,
    #[error("NameParsingError")]
    NameParsingError,
    #[error("PasswordParsingError")]
    PasswordParsingError,
    #[error("UserAlreadyVerified")]
    UserAlreadyVerified,
    #[error("CompanyNameParsingError")]
    CompanyNameParsingError,
    #[error("MerchantAccountCreationError: {0}")]
    MerchantAccountCreationError(String),
    #[error("InvalidEmailError")]
    InvalidEmailError,
    #[error("DuplicateOrganizationId")]
    DuplicateOrganizationId,
    #[error("MerchantIdNotFound")]
    MerchantIdNotFound,
    #[error("MetadataAlreadySet")]
    MetadataAlreadySet,
    #[error("InvalidRoleId")]
    InvalidRoleId,
    #[error("InvalidRoleOperation")]
    InvalidRoleOperation,
    #[error("IpAddressParsingFailed")]
    IpAddressParsingFailed,
    #[error("InvalidMetadataRequest")]
    InvalidMetadataRequest,
    #[error("MerchantIdParsingError")]
    MerchantIdParsingError,
    #[error("ChangePasswordError")]
    ChangePasswordError,
    #[error("InvalidDeleteOperation")]
    InvalidDeleteOperation,
    #[error("MaxInvitationsError")]
    MaxInvitationsError,
    #[error("RoleNotFound")]
    RoleNotFound,
    #[error("InvalidRoleOperationWithMessage")]
    InvalidRoleOperationWithMessage(String),
    #[error("RoleNameParsingError")]
    RoleNameParsingError,
    #[error("RoleNameAlreadyExists")]
    RoleNameAlreadyExists,
    #[error("TotpNotSetup")]
    TotpNotSetup,
    #[error("InvalidTotp")]
    InvalidTotp,
    #[error("TotpRequired")]
    TotpRequired,
    #[error("InvalidRecoveryCode")]
    InvalidRecoveryCode,
    #[error("TwoFactorAuthRequired")]
    TwoFactorAuthRequired,
    #[error("TwoFactorAuthNotSetup")]
    TwoFactorAuthNotSetup,
    #[error("TOTP secret not found")]
    TotpSecretNotFound,
    #[error("User auth method already exists")]
    UserAuthMethodAlreadyExists,
    #[error("Invalid user auth method operation")]
    InvalidUserAuthMethodOperation,
    #[error("Auth config parsing error")]
    AuthConfigParsingError,
    #[error("Invalid SSO request")]
    SSOFailed,
    #[error("profile_id missing in JWT")]
    JwtProfileIdMissing,
    #[error("Maximum attempts reached for TOTP")]
    MaxTotpAttemptsReached,
    #[error("Maximum attempts reached for Recovery Code")]
    MaxRecoveryCodeAttemptsReached,
    #[error("Forbidden tenant id")]
    ForbiddenTenantId,
    #[error("Error Uploading file to Theme Storage")]
    ErrorUploadingFile,
    #[error("Error Retrieving file from Theme Storage")]
    ErrorRetrievingFile,
    #[error("Theme not found")]
    ThemeNotFound,
    #[error("Theme with lineage already exists")]
    ThemeAlreadyExists,
    #[error("Invalid field: {0} in lineage")]
    InvalidThemeLineage(String),
    #[error("Missing required field: email_config")]
    MissingEmailConfig,
    #[error("Invalid Auth Method Operation: {0}")]
    InvalidAuthMethodOperationWithMessage(String),
    #[error("Invalid Clone Connector Operation: {0}")]
    InvalidCloneConnectorOperation(String),
    #[error("Error cloning connector: {0}")]
    ErrorCloningConnector(String),
}

impl common_utils::errors::ErrorSwitch<api_models::errors::types::ApiErrorResponse> for UserErrors {
    fn switch(&self) -> api_models::errors::types::ApiErrorResponse {
        use api_models::errors::types::{ApiError, ApiErrorResponse as AER};
        let sub_code = "UR";
        match self {
            Self::InternalServerError => {
                AER::InternalServerError(ApiError::new("HE", 0, self.get_error_message(), None))
            }
            Self::InvalidCredentials => {
                AER::Unauthorized(ApiError::new(sub_code, 1, self.get_error_message(), None))
            }
            Self::UserNotFound => {
                AER::Unauthorized(ApiError::new(sub_code, 2, self.get_error_message(), None))
            }
            Self::UserExists => {
                AER::BadRequest(ApiError::new(sub_code, 3, self.get_error_message(), None))
            }
            Self::LinkInvalid => {
                AER::Unauthorized(ApiError::new(sub_code, 4, self.get_error_message(), None))
            }
            Self::UnverifiedUser => {
                AER::Unauthorized(ApiError::new(sub_code, 5, self.get_error_message(), None))
            }
            Self::InvalidOldPassword => {
                AER::BadRequest(ApiError::new(sub_code, 6, self.get_error_message(), None))
            }
            Self::EmailParsingError => {
                AER::BadRequest(ApiError::new(sub_code, 7, self.get_error_message(), None))
            }
            Self::NameParsingError => {
                AER::BadRequest(ApiError::new(sub_code, 8, self.get_error_message(), None))
            }
            Self::PasswordParsingError => {
                AER::BadRequest(ApiError::new(sub_code, 9, self.get_error_message(), None))
            }
            Self::UserAlreadyVerified => {
                AER::Unauthorized(ApiError::new(sub_code, 11, self.get_error_message(), None))
            }
            Self::CompanyNameParsingError => {
                AER::BadRequest(ApiError::new(sub_code, 14, self.get_error_message(), None))
            }
            Self::MerchantAccountCreationError(_) => AER::InternalServerError(ApiError::new(
                sub_code,
                15,
                self.get_error_message(),
                None,
            )),
            Self::InvalidEmailError => {
                AER::BadRequest(ApiError::new(sub_code, 16, self.get_error_message(), None))
            }
            Self::MerchantIdNotFound => {
                AER::BadRequest(ApiError::new(sub_code, 18, self.get_error_message(), None))
            }
            Self::MetadataAlreadySet => {
                AER::BadRequest(ApiError::new(sub_code, 19, self.get_error_message(), None))
            }
            Self::DuplicateOrganizationId => AER::InternalServerError(ApiError::new(
                sub_code,
                21,
                self.get_error_message(),
                None,
            )),
            Self::InvalidRoleId => {
                AER::BadRequest(ApiError::new(sub_code, 22, self.get_error_message(), None))
            }
            Self::InvalidRoleOperation => {
                AER::BadRequest(ApiError::new(sub_code, 23, self.get_error_message(), None))
            }
            Self::IpAddressParsingFailed => AER::InternalServerError(ApiError::new(
                sub_code,
                24,
                self.get_error_message(),
                None,
            )),
            Self::InvalidMetadataRequest => {
                AER::BadRequest(ApiError::new(sub_code, 26, self.get_error_message(), None))
            }
            Self::MerchantIdParsingError => {
                AER::BadRequest(ApiError::new(sub_code, 28, self.get_error_message(), None))
            }
            Self::ChangePasswordError => {
                AER::BadRequest(ApiError::new(sub_code, 29, self.get_error_message(), None))
            }
            Self::InvalidDeleteOperation => {
                AER::BadRequest(ApiError::new(sub_code, 30, self.get_error_message(), None))
            }
            Self::MaxInvitationsError => {
                AER::BadRequest(ApiError::new(sub_code, 31, self.get_error_message(), None))
            }
            Self::RoleNotFound => {
                AER::BadRequest(ApiError::new(sub_code, 32, self.get_error_message(), None))
            }
            Self::InvalidRoleOperationWithMessage(_) => {
                AER::BadRequest(ApiError::new(sub_code, 33, self.get_error_message(), None))
            }
            Self::RoleNameParsingError => {
                AER::BadRequest(ApiError::new(sub_code, 34, self.get_error_message(), None))
            }
            Self::RoleNameAlreadyExists => {
                AER::BadRequest(ApiError::new(sub_code, 35, self.get_error_message(), None))
            }
            Self::TotpNotSetup => {
                AER::BadRequest(ApiError::new(sub_code, 36, self.get_error_message(), None))
            }
            Self::InvalidTotp => {
                AER::BadRequest(ApiError::new(sub_code, 37, self.get_error_message(), None))
            }
            Self::TotpRequired => {
                AER::BadRequest(ApiError::new(sub_code, 38, self.get_error_message(), None))
            }
            Self::InvalidRecoveryCode => {
                AER::BadRequest(ApiError::new(sub_code, 39, self.get_error_message(), None))
            }
            Self::TwoFactorAuthRequired => {
                AER::BadRequest(ApiError::new(sub_code, 40, self.get_error_message(), None))
            }
            Self::TwoFactorAuthNotSetup => {
                AER::BadRequest(ApiError::new(sub_code, 41, self.get_error_message(), None))
            }
            Self::TotpSecretNotFound => {
                AER::BadRequest(ApiError::new(sub_code, 42, self.get_error_message(), None))
            }
            Self::UserAuthMethodAlreadyExists => {
                AER::BadRequest(ApiError::new(sub_code, 43, self.get_error_message(), None))
            }
            Self::InvalidUserAuthMethodOperation => {
                AER::BadRequest(ApiError::new(sub_code, 44, self.get_error_message(), None))
            }
            Self::AuthConfigParsingError => {
                AER::BadRequest(ApiError::new(sub_code, 45, self.get_error_message(), None))
            }
            Self::SSOFailed => {
                AER::BadRequest(ApiError::new(sub_code, 46, self.get_error_message(), None))
            }
            Self::JwtProfileIdMissing => {
                AER::Unauthorized(ApiError::new(sub_code, 47, self.get_error_message(), None))
            }
            Self::MaxTotpAttemptsReached => {
                AER::BadRequest(ApiError::new(sub_code, 48, self.get_error_message(), None))
            }
            Self::MaxRecoveryCodeAttemptsReached => {
                AER::BadRequest(ApiError::new(sub_code, 49, self.get_error_message(), None))
            }
            Self::ForbiddenTenantId => {
                AER::BadRequest(ApiError::new(sub_code, 50, self.get_error_message(), None))
            }
            Self::ErrorUploadingFile => AER::InternalServerError(ApiError::new(
                sub_code,
                51,
                self.get_error_message(),
                None,
            )),
            Self::ErrorRetrievingFile => AER::InternalServerError(ApiError::new(
                sub_code,
                52,
                self.get_error_message(),
                None,
            )),
            Self::ThemeNotFound => {
                AER::NotFound(ApiError::new(sub_code, 53, self.get_error_message(), None))
            }
            Self::ThemeAlreadyExists => {
                AER::BadRequest(ApiError::new(sub_code, 54, self.get_error_message(), None))
            }
            Self::InvalidThemeLineage(_) => {
                AER::BadRequest(ApiError::new(sub_code, 55, self.get_error_message(), None))
            }
            Self::MissingEmailConfig => {
                AER::BadRequest(ApiError::new(sub_code, 56, self.get_error_message(), None))
            }
            Self::InvalidAuthMethodOperationWithMessage(_) => {
                AER::BadRequest(ApiError::new(sub_code, 57, self.get_error_message(), None))
            }
            Self::InvalidCloneConnectorOperation(_) => {
                AER::BadRequest(ApiError::new(sub_code, 58, self.get_error_message(), None))
            }
            Self::ErrorCloningConnector(_) => AER::InternalServerError(ApiError::new(
                sub_code,
                59,
                self.get_error_message(),
                None,
            )),
        }
    }
}

impl UserErrors {
    pub fn get_error_message(&self) -> String {
        match self {
            Self::InternalServerError => "Something went wrong".to_string(),
            Self::InvalidCredentials => "Incorrect email or password".to_string(),
            Self::UserNotFound => "Email doesn’t exist. Register".to_string(),
            Self::UserExists => "An account already exists with this email".to_string(),
            Self::LinkInvalid => "Invalid or expired link".to_string(),
            Self::UnverifiedUser => "Kindly verify your account".to_string(),
            Self::InvalidOldPassword => {
                "Old password incorrect. Please enter the correct password".to_string()
            }
            Self::EmailParsingError => "Invalid Email".to_string(),
            Self::NameParsingError => "Invalid Name".to_string(),
            Self::PasswordParsingError => "Invalid Password".to_string(),
            Self::UserAlreadyVerified => "User already verified".to_string(),
            Self::CompanyNameParsingError => "Invalid Company Name".to_string(),
            Self::MerchantAccountCreationError(error_message) => error_message.to_string(),
            Self::InvalidEmailError => "Invalid Email".to_string(),
            Self::MerchantIdNotFound => "Invalid Merchant ID".to_string(),
            Self::MetadataAlreadySet => "Metadata already set".to_string(),
            Self::DuplicateOrganizationId => {
                "An Organization with the id already exists".to_string()
            }
            Self::InvalidRoleId => "Invalid Role ID".to_string(),
            Self::InvalidRoleOperation => "User Role Operation Not Supported".to_string(),
            Self::IpAddressParsingFailed => "Something went wrong".to_string(),
            Self::InvalidMetadataRequest => "Invalid Metadata Request".to_string(),
            Self::MerchantIdParsingError => "Invalid Merchant Id".to_string(),
            Self::ChangePasswordError => "Old and new password cannot be same".to_string(),
            Self::InvalidDeleteOperation => "Delete Operation Not Supported".to_string(),
            Self::MaxInvitationsError => "Maximum invite count per request exceeded".to_string(),
            Self::RoleNotFound => "Role Not Found".to_string(),
            Self::InvalidRoleOperationWithMessage(error_message) => error_message.to_string(),
            Self::RoleNameParsingError => "Invalid Role Name".to_string(),
            Self::RoleNameAlreadyExists => "Role name already exists".to_string(),
            Self::TotpNotSetup => "TOTP not setup".to_string(),
            Self::InvalidTotp => "Invalid TOTP".to_string(),
            Self::TotpRequired => "TOTP required".to_string(),
            Self::InvalidRecoveryCode => "Invalid Recovery Code".to_string(),
            Self::MaxTotpAttemptsReached => "Maximum attempts reached for TOTP".to_string(),
            Self::MaxRecoveryCodeAttemptsReached => {
                "Maximum attempts reached for Recovery Code".to_string()
            }
            Self::TwoFactorAuthRequired => "Two factor auth required".to_string(),
            Self::TwoFactorAuthNotSetup => "Two factor auth not setup".to_string(),
            Self::TotpSecretNotFound => "TOTP secret not found".to_string(),
            Self::UserAuthMethodAlreadyExists => "User auth method already exists".to_string(),
            Self::InvalidUserAuthMethodOperation => {
                "Invalid user auth method operation".to_string()
            }
            Self::AuthConfigParsingError => "Auth config parsing error".to_string(),
            Self::SSOFailed => "Invalid SSO request".to_string(),
            Self::JwtProfileIdMissing => "profile_id missing in JWT".to_string(),
            Self::ForbiddenTenantId => "Forbidden tenant id".to_string(),
            Self::ErrorUploadingFile => "Error Uploading file to Theme Storage".to_string(),
            Self::ErrorRetrievingFile => "Error Retrieving file from Theme Storage".to_string(),
            Self::ThemeNotFound => "Theme not found".to_string(),
            Self::ThemeAlreadyExists => "Theme with lineage already exists".to_string(),
            Self::InvalidThemeLineage(field_name) => {
                format!("Invalid field: {field_name} in lineage")
            }
            Self::MissingEmailConfig => "Missing required field: email_config".to_string(),
            Self::InvalidAuthMethodOperationWithMessage(operation) => {
                format!("Invalid Auth Method Operation: {operation}")
            }
            Self::InvalidCloneConnectorOperation(operation) => {
                format!("Invalid Clone Connector Operation: {operation}")
            }
            Self::ErrorCloningConnector(error_message) => {
                format!("Error cloning connector: {error_message}")
            }
        }
    }
}


// Struct: CustomerDeleteResponse
// File: crates/api_models/src/customers.rs
// Module: api_models
// Implementations: 0

pub struct CustomerDeleteResponse


// Implementation: impl api::Refund for for Trustpay
// File: crates/hyperswitch_connectors/src/connectors/trustpay.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::Refund for for Trustpay


// Struct: MandateDetails
// File: crates/hyperswitch_connectors/src/connectors/datatrans/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct MandateDetails


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

impl api::PaymentAuthorize for for Santander


// Struct: NordeaResponseLinks
// File: crates/hyperswitch_connectors/src/connectors/nordea/responses.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct NordeaResponseLinks


// Struct: AccessTokenAuthenticationResponse
// File: crates/hyperswitch_domain_models/src/router_data.rs
// Module: hyperswitch_domain_models
// Implementations: 0

pub struct AccessTokenAuthenticationResponse


// Implementation: impl api::MandateSetup for for Paystack
// File: crates/hyperswitch_connectors/src/connectors/paystack.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::MandateSetup for for Paystack


// Function: get_total_surcharge_amount
// File: crates/hyperswitch_domain_models/src/payments/payment_attempt.rs
// Module: hyperswitch_domain_models

pub fn get_total_surcharge_amount(&self) -> Option<MinorUnit>


// Function: terminate_two_factor_auth
// File: crates/router/src/routes/user.rs
// Module: router

pub fn terminate_two_factor_auth(
    state: web::Data<AppState>,
    req: HttpRequest,
    query: web::Query<user_api::SkipTwoFactorAuthQueryParam>,
) -> HttpResponse


// Function: log_payment_intent_delete
// File: crates/router/src/services/kafka.rs
// Module: router

pub fn log_payment_intent_delete(
        &self,
        delete_old_intent: &PaymentIntent,
        tenant_id: TenantID,
        infra_values: Option<Value>,
    ) -> MQResult<()>


// Implementation: impl std::str::FromStr for for PaymentReferenceId
// File: crates/common_utils/src/id_type/payment.rs
// Module: common_utils
// Methods: 1 total (0 public)

impl std::str::FromStr for for PaymentReferenceId


// File: crates/hyperswitch_domain_models/src/router_response_types.rs
// Module: hyperswitch_domain_models
// Public functions: 9
// Public structs: 13

pub mod disputes;
pub mod fraud_check;
pub mod revenue_recovery;
pub mod subscriptions;
use std::collections::HashMap;

use api_models::payments::AddressDetails;
use common_utils::{pii, request::Method, types::MinorUnit};
pub use disputes::{
    AcceptDisputeResponse, DefendDisputeResponse, DisputeSyncResponse, FetchDisputesResponse,
    SubmitEvidenceResponse,
};

use crate::{
    errors::api_error_response::ApiErrorResponse,
    router_request_types::{authentication::AuthNFlowType, ResponseId},
    vault::PaymentMethodVaultingData,
};

#[derive(Debug, Clone)]
pub struct RefundsResponseData {
    pub connector_refund_id: String,
    pub refund_status: common_enums::RefundStatus,
    // pub amount_received: Option<i32>, // Calculation for amount received not in place yet
}

#[derive(Debug, Clone)]
pub struct ConnectorCustomerResponseData {
    pub connector_customer_id: String,
    pub name: Option<String>,
    pub email: Option<String>,
    pub billing_address: Option<AddressDetails>,
}

impl ConnectorCustomerResponseData {
    pub fn new_with_customer_id(connector_customer_id: String) -> Self {
        Self::new(connector_customer_id, None, None, None)
    }
    pub fn new(
        connector_customer_id: String,
        name: Option<String>,
        email: Option<String>,
        billing_address: Option<AddressDetails>,
    ) -> Self {
        Self {
            connector_customer_id,
            name,
            email,
            billing_address,
        }
    }
}

#[derive(Debug, Clone)]
pub enum PaymentsResponseData {
    TransactionResponse {
        resource_id: ResponseId,
        redirection_data: Box<Option<RedirectForm>>,
        mandate_reference: Box<Option<MandateReference>>,
        connector_metadata: Option<serde_json::Value>,
        network_txn_id: Option<String>,
        connector_response_reference_id: Option<String>,
        incremental_authorization_allowed: Option<bool>,
        charges: Option<common_types::payments::ConnectorChargeResponseData>,
    },
    MultipleCaptureResponse {
        // pending_capture_id_list: Vec<String>,
        capture_sync_response_list: HashMap<String, CaptureSyncResponse>,
    },
    SessionResponse {
        session_token: api_models::payments::SessionToken,
    },
    SessionTokenResponse {
        session_token: String,
    },
    TransactionUnresolvedResponse {
        resource_id: ResponseId,
        //to add more info on cypto response, like `unresolved` reason(overpaid, underpaid, delayed)
        reason: Option<api_models::enums::UnresolvedResponseReason>,
        connector_response_reference_id: Option<String>,
    },
    TokenizationResponse {
        token: String,
    },

    ConnectorCustomerResponse(ConnectorCustomerResponseData),

    ThreeDSEnrollmentResponse {
        enrolled_v2: bool,
        related_transaction_id: Option<String>,
    },
    PreProcessingResponse {
        pre_processing_id: PreprocessingResponseId,
        connector_metadata: Option<serde_json::Value>,
        session_token: Option<api_models::payments::SessionToken>,
        connector_response_reference_id: Option<String>,
    },
    IncrementalAuthorizationResponse {
        status: common_enums::AuthorizationStatus,
        connector_authorization_id: Option<String>,
        error_code: Option<String>,
        error_message: Option<String>,
    },
    PostProcessingResponse {
        session_token: Option<api_models::payments::OpenBankingSessionToken>,
    },
    PaymentResourceUpdateResponse {
        status: common_enums::PaymentResourceUpdateStatus,
    },
    PaymentsCreateOrderResponse {
        order_id: String,
    },
}

#[derive(Debug, Clone)]
pub struct GiftCardBalanceCheckResponseData {
    pub balance: MinorUnit,
    pub currency: common_enums::Currency,
}

#[derive(Debug, Clone)]
pub struct TaxCalculationResponseData {
    pub order_tax_amount: MinorUnit,
}

#[derive(serde::Serialize, Debug, Clone)]
pub struct MandateReference {
    pub connector_mandate_id: Option<String>,
    pub payment_method_id: Option<String>,
    pub mandate_metadata: Option<pii::SecretSerdeValue>,
    pub connector_mandate_request_reference_id: Option<String>,
}

#[derive(Debug, Clone)]
pub enum CaptureSyncResponse {
    Success {
        resource_id: ResponseId,
        status: common_enums::AttemptStatus,
        connector_response_reference_id: Option<String>,
        amount: Option<MinorUnit>,
    },
    Error {
        code: String,
        message: String,
        reason: Option<String>,
        status_code: u16,
        amount: Option<MinorUnit>,
    },
}

impl CaptureSyncResponse {
    pub fn get_amount_captured(&self) -> Option<MinorUnit> {
        match self {
            Self::Success { amount, .. } | Self::Error { amount, .. } => *amount,
        }
    }
    pub fn get_connector_response_reference_id(&self) -> Option<String> {
        match self {
            Self::Success {
                connector_response_reference_id,
                ..
            } => connector_response_reference_id.clone(),
            Self::Error { .. } => None,
        }
    }
}
impl PaymentsResponseData {
    pub fn get_connector_metadata(&self) -> Option<masking::Secret<serde_json::Value>> {
        match self {
            Self::TransactionResponse {
                connector_metadata, ..
            }
            | Self::PreProcessingResponse {
                connector_metadata, ..
            } => connector_metadata.clone().map(masking::Secret::new),
            _ => None,
        }
    }
    pub fn get_network_transaction_id(&self) -> Option<String> {
        match self {
            Self::TransactionResponse { network_txn_id, .. } => network_txn_id.clone(),
            _ => None,
        }
    }

    pub fn get_connector_transaction_id(
        &self,
    ) -> Result<String, error_stack::Report<ApiErrorResponse>> {
        match self {
            Self::TransactionResponse {
                resource_id: ResponseId::ConnectorTransactionId(txn_id),
                ..
            } => Ok(txn_id.to_string()),
            _ => Err(ApiErrorResponse::MissingRequiredField {
                field_name: "ConnectorTransactionId",
            }
            .into()),
        }
    }

    pub fn merge_transaction_responses(
        auth_response: &Self,
        capture_response: &Self,
    ) -> Result<Self, error_stack::Report<ApiErrorResponse>> {
        match (auth_response, capture_response) {
            (
                Self::TransactionResponse {
                    resource_id: _,
                    redirection_data: auth_redirection_data,
                    mandate_reference: auth_mandate_reference,
                    connector_metadata: auth_connector_metadata,
                    network_txn_id: auth_network_txn_id,
                    connector_response_reference_id: auth_connector_response_reference_id,
                    incremental_authorization_allowed: auth_incremental_auth_allowed,
                    charges: auth_charges,
                },
                Self::TransactionResponse {
                    resource_id: capture_resource_id,
                    redirection_data: capture_redirection_data,
                    mandate_reference: capture_mandate_reference,
                    connector_metadata: capture_connector_metadata,
                    network_txn_id: capture_network_txn_id,
                    connector_response_reference_id: capture_connector_response_reference_id,
                    incremental_authorization_allowed: capture_incremental_auth_allowed,
                    charges: capture_charges,
                },
            ) => Ok(Self::TransactionResponse {
                resource_id: capture_resource_id.clone(),
                redirection_data: Box::new(
                    capture_redirection_data
                        .clone()
                        .or_else(|| *auth_redirection_data.clone()),
                ),
                mandate_reference: Box::new(
                    auth_mandate_reference
                        .clone()
                        .or_else(|| *capture_mandate_reference.clone()),
                ),
                connector_metadata: capture_connector_metadata
                    .clone()
                    .or(auth_connector_metadata.clone()),
                network_txn_id: capture_network_txn_id
                    .clone()
                    .or(auth_network_txn_id.clone()),
                connector_response_reference_id: capture_connector_response_reference_id
                    .clone()
                    .or(auth_connector_response_reference_id.clone()),
                incremental_authorization_allowed: (*capture_incremental_auth_allowed)
                    .or(*auth_incremental_auth_allowed),
                charges: auth_charges.clone().or(capture_charges.clone()),
            }),
            _ => Err(ApiErrorResponse::NotSupported {
                message: "Invalid Flow ".to_owned(),
            }
            .into()),
        }
    }

    #[cfg(feature = "v2")]
    pub fn get_updated_connector_token_details(
        &self,
        original_connector_mandate_request_reference_id: Option<String>,
    ) -> Option<diesel_models::ConnectorTokenDetails> {
        if let Self::TransactionResponse {
            mandate_reference, ..
        } = self
        {
            mandate_reference.clone().map(|mandate_ref| {
                let connector_mandate_id = mandate_ref.connector_mandate_id;
                let connector_mandate_request_reference_id = mandate_ref
                    .connector_mandate_request_reference_id
                    .or(original_connector_mandate_request_reference_id);

                diesel_models::ConnectorTokenDetails {
                    connector_mandate_id,
                    connector_token_request_reference_id: connector_mandate_request_reference_id,
                }
            })
        } else {
            None
        }
    }
}

#[derive(Debug, Clone)]
pub enum PreprocessingResponseId {
    PreProcessingId(String),
    ConnectorTransactionId(String),
}

#[derive(Debug, Eq, PartialEq, Clone, serde::Serialize, serde::Deserialize)]
pub enum RedirectForm {
    Form {
        endpoint: String,
        method: Method,
        form_fields: HashMap<String, String>,
    },
    Html {
        html_data: String,
    },
    BarclaycardAuthSetup {
        access_token: String,
        ddc_url: String,
        reference_id: String,
    },
    BarclaycardConsumerAuth {
        access_token: String,
        step_up_url: String,
    },
    BlueSnap {
        payment_fields_token: String, // payment-field-token
    },
    CybersourceAuthSetup {
        access_token: String,
        ddc_url: String,
        reference_id: String,
    },
    CybersourceConsumerAuth {
        access_token: String,
        step_up_url: String,
    },
    DeutschebankThreeDSChallengeFlow {
        acs_url: String,
        creq: String,
    },
    Payme,
    Braintree {
        client_token: String,
        card_token: String,
        bin: String,
        acs_url: String,
    },
    Nmi {
        amount: String,
        currency: common_enums::Currency,
        public_key: masking::Secret<String>,
        customer_vault_id: String,
        order_id: String,
    },
    Mifinity {
        initialization_token: String,
    },
    WorldpayDDCForm {
        endpoint: url::Url,
        method: Method,
        form_fields: HashMap<String, String>,
        collection_id: Option<String>,
    },
}

impl From<(url::Url, Method)> for RedirectForm {
    fn from((mut redirect_url, method): (url::Url, Method)) -> Self {
        let form_fields = HashMap::from_iter(
            redirect_url
                .query_pairs()
                .map(|(key, value)| (key.to_string(), value.to_string())),
        );

        // Do not include query params in the endpoint
        redirect_url.set_query(None);

        Self::Form {
            endpoint: redirect_url.to_string(),
            method,
            form_fields,
        }
    }
}

impl From<RedirectForm> for diesel_models::payment_attempt::RedirectForm {
    fn from(redirect_form: RedirectForm) -> Self {
        match redirect_form {
            RedirectForm::Form {
                endpoint,
                method,
                form_fields,
            } => Self::Form {
                endpoint,
                method,
                form_fields,
            },
            RedirectForm::Html { html_data } => Self::Html { html_data },
            RedirectForm::BarclaycardAuthSetup {
                access_token,
                ddc_url,
                reference_id,
            } => Self::BarclaycardAuthSetup {
                access_token,
                ddc_url,
                reference_id,
            },
            RedirectForm::BarclaycardConsumerAuth {
                access_token,
                step_up_url,
            } => Self::BarclaycardConsumerAuth {
                access_token,
                step_up_url,
            },
            RedirectForm::BlueSnap {
                payment_fields_token,
            } => Self::BlueSnap {
                payment_fields_token,
            },
            RedirectForm::CybersourceAuthSetup {
                access_token,
                ddc_url,
                reference_id,
            } => Self::CybersourceAuthSetup {
                access_token,
                ddc_url,
                reference_id,
            },
            RedirectForm::CybersourceConsumerAuth {
                access_token,
                step_up_url,
            } => Self::CybersourceConsumerAuth {
                access_token,
                step_up_url,
            },
            RedirectForm::DeutschebankThreeDSChallengeFlow { acs_url, creq } => {
                Self::DeutschebankThreeDSChallengeFlow { acs_url, creq }
            }
            RedirectForm::Payme => Self::Payme,
            RedirectForm::Braintree {
                client_token,
                card_token,
                bin,
                acs_url,
            } => Self::Braintree {
                client_token,
                card_token,
                bin,
                acs_url,
            },
            RedirectForm::Nmi {
                amount,
                currency,
                public_key,
                customer_vault_id,
                order_id,
            } => Self::Nmi {
                amount,
                currency,
                public_key,
                customer_vault_id,
                order_id,
            },
            RedirectForm::Mifinity {
                initialization_token,
            } => Self::Mifinity {
                initialization_token,
            },
            RedirectForm::WorldpayDDCForm {
                endpoint,
                method,
                form_fields,
                collection_id,
            } => Self::WorldpayDDCForm {
                endpoint: common_utils::types::Url::wrap(endpoint),
                method,
                form_fields,
                collection_id,
            },
        }
    }
}

impl From<diesel_models::payment_attempt::RedirectForm> for RedirectForm {
    fn from(redirect_form: diesel_models::payment_attempt::RedirectForm) -> Self {
        match redirect_form {
            diesel_models::payment_attempt::RedirectForm::Form {
                endpoint,
                method,
                form_fields,
            } => Self::Form {
                endpoint,
                method,
                form_fields,
            },
            diesel_models::payment_attempt::RedirectForm::Html { html_data } => {
                Self::Html { html_data }
            }
            diesel_models::payment_attempt::RedirectForm::BarclaycardAuthSetup {
                access_token,
                ddc_url,
                reference_id,
            } => Self::BarclaycardAuthSetup {
                access_token,
                ddc_url,
                reference_id,
            },
            diesel_models::payment_attempt::RedirectForm::BarclaycardConsumerAuth {
                access_token,
                step_up_url,
            } => Self::BarclaycardConsumerAuth {
                access_token,
                step_up_url,
            },
            diesel_models::payment_attempt::RedirectForm::BlueSnap {
                payment_fields_token,
            } => Self::BlueSnap {
                payment_fields_token,
            },
            diesel_models::payment_attempt::RedirectForm::CybersourceAuthSetup {
                access_token,
                ddc_url,
                reference_id,
            } => Self::CybersourceAuthSetup {
                access_token,
                ddc_url,
                reference_id,
            },
            diesel_models::payment_attempt::RedirectForm::CybersourceConsumerAuth {
                access_token,
                step_up_url,
            } => Self::CybersourceConsumerAuth {
                access_token,
                step_up_url,
            },
            diesel_models::RedirectForm::DeutschebankThreeDSChallengeFlow { acs_url, creq } => {
                Self::DeutschebankThreeDSChallengeFlow { acs_url, creq }
            }
            diesel_models::payment_attempt::RedirectForm::Payme => Self::Payme,
            diesel_models::payment_attempt::RedirectForm::Braintree {
                client_token,
                card_token,
                bin,
                acs_url,
            } => Self::Braintree {
                client_token,
                card_token,
                bin,
                acs_url,
            },
            diesel_models::payment_attempt::RedirectForm::Nmi {
                amount,
                currency,
                public_key,
                customer_vault_id,
                order_id,
            } => Self::Nmi {
                amount,
                currency,
                public_key,
                customer_vault_id,
                order_id,
            },
            diesel_models::payment_attempt::RedirectForm::Mifinity {
                initialization_token,
            } => Self::Mifinity {
                initialization_token,
            },
            diesel_models::payment_attempt::RedirectForm::WorldpayDDCForm {
                endpoint,
                method,
                form_fields,
                collection_id,
            } => Self::WorldpayDDCForm {
                endpoint: endpoint.into_inner(),
                method,
                form_fields,
                collection_id,
            },
        }
    }
}

#[derive(Default, Clone, Debug)]
pub struct UploadFileResponse {
    pub provider_file_id: String,
}
#[derive(Clone, Debug)]
pub struct RetrieveFileResponse {
    pub file_data: Vec<u8>,
}

#[cfg(feature = "payouts")]
#[derive(Clone, Debug, Default)]
pub struct PayoutsResponseData {
    pub status: Option<common_enums::PayoutStatus>,
    pub connector_payout_id: Option<String>,
    pub payout_eligible: Option<bool>,
    pub should_add_next_step_to_process_tracker: bool,
    pub error_code: Option<String>,
    pub error_message: Option<String>,
}

#[derive(Debug, Clone)]
pub struct VerifyWebhookSourceResponseData {
    pub verify_webhook_status: VerifyWebhookStatus,
}

#[derive(Debug, Clone)]
pub enum VerifyWebhookStatus {
    SourceVerified,
    SourceNotVerified,
}

#[derive(Debug, Clone)]
pub struct MandateRevokeResponseData {
    pub mandate_status: common_enums::MandateStatus,
}

#[derive(Debug, Clone)]
pub enum AuthenticationResponseData {
    PreAuthVersionCallResponse {
        maximum_supported_3ds_version: common_utils::types::SemanticVersion,
    },
    PreAuthThreeDsMethodCallResponse {
        threeds_server_transaction_id: String,
        three_ds_method_data: Option<String>,
        three_ds_method_url: Option<String>,
        connector_metadata: Option<serde_json::Value>,
    },
    PreAuthNResponse {
        threeds_server_transaction_id: String,
        maximum_supported_3ds_version: common_utils::types::SemanticVersion,
        connector_authentication_id: String,
        three_ds_method_data: Option<String>,
        three_ds_method_url: Option<String>,
        message_version: common_utils::types::SemanticVersion,
        connector_metadata: Option<serde_json::Value>,
        directory_server_id: Option<String>,
    },
    AuthNResponse {
        authn_flow_type: AuthNFlowType,
        authentication_value: Option<masking::Secret<String>>,
        trans_status: common_enums::TransactionStatus,
        connector_metadata: Option<serde_json::Value>,
        ds_trans_id: Option<String>,
        eci: Option<String>,
        challenge_code: Option<String>,
        challenge_cancel: Option<String>,
        challenge_code_reason: Option<String>,
        message_extension: Option<pii::SecretSerdeValue>,
    },
    PostAuthNResponse {
        trans_status: common_enums::TransactionStatus,
        authentication_value: Option<masking::Secret<String>>,
        eci: Option<String>,
        challenge_cancel: Option<String>,
        challenge_code_reason: Option<String>,
    },
}

#[derive(Debug, Clone)]
pub struct CompleteAuthorizeRedirectResponse {
    pub params: Option<masking::Secret<String>>,
    pub payload: Option<pii::SecretSerdeValue>,
}

/// Represents details of a payment method.
#[derive(Debug, Clone)]
pub struct PaymentMethodDetails {
    /// Indicates whether mandates are supported by this payment method.
    pub mandates: common_enums::FeatureStatus,
    /// Indicates whether refund is supported by this payment method.
    pub refunds: common_enums::FeatureStatus,
    /// List of supported capture methods
    pub supported_capture_methods: Vec<common_enums::CaptureMethod>,
    /// Payment method specific features
    pub specific_features: Option<api_models::feature_matrix::PaymentMethodSpecificFeatures>,
}

/// list of payment method types and metadata related to them
pub type PaymentMethodTypeMetadata = HashMap<common_enums::PaymentMethodType, PaymentMethodDetails>;

/// list of payment methods, payment method types and metadata related to them
pub type SupportedPaymentMethods = HashMap<common_enums::PaymentMethod, PaymentMethodTypeMetadata>;

#[derive(Debug, Clone)]
pub struct ConnectorInfo {
    /// Display name of the Connector
    pub display_name: &'static str,
    /// Description of the connector.
    pub description: &'static str,
    /// Connector Type
    pub connector_type: common_enums::HyperswitchConnectorCategory,
    /// Integration status of the connector
    pub integration_status: common_enums::ConnectorIntegrationStatus,
}

pub trait SupportedPaymentMethodsExt {
    fn add(
        &mut self,
        payment_method: common_enums::PaymentMethod,
        payment_method_type: common_enums::PaymentMethodType,
        payment_method_details: PaymentMethodDetails,
    );
}

impl SupportedPaymentMethodsExt for SupportedPaymentMethods {
    fn add(
        &mut self,
        payment_method: common_enums::PaymentMethod,
        payment_method_type: common_enums::PaymentMethodType,
        payment_method_details: PaymentMethodDetails,
    ) {
        if let Some(payment_method_data) = self.get_mut(&payment_method) {
            payment_method_data.insert(payment_method_type, payment_method_details);
        } else {
            let mut payment_method_type_metadata = PaymentMethodTypeMetadata::new();
            payment_method_type_metadata.insert(payment_method_type, payment_method_details);

            self.insert(payment_method, payment_method_type_metadata);
        }
    }
}

#[derive(Debug, Clone)]
pub enum VaultResponseData {
    ExternalVaultCreateResponse {
        session_id: masking::Secret<String>,
        client_secret: masking::Secret<String>,
    },
    ExternalVaultInsertResponse {
        connector_vault_id: String,
        fingerprint_id: String,
    },
    ExternalVaultRetrieveResponse {
        vault_data: PaymentMethodVaultingData,
    },
    ExternalVaultDeleteResponse {
        connector_vault_id: String,
    },
}

impl Default for VaultResponseData {
    fn default() -> Self {
        Self::ExternalVaultInsertResponse {
            connector_vault_id: String::new(),
            fingerprint_id: String::new(),
        }
    }
}


// Struct: FailureReasonsDistributionAccumulator
// File: crates/analytics/src/payments/accumulator.rs
// Module: analytics
// Implementations: 1
// Traits: PaymentMetricAccumulator

pub struct FailureReasonsDistributionAccumulator


// Struct: RefundData
// File: crates/hyperswitch_connectors/src/connectors/novalnet/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct RefundData


// Function: update_surcharge_config_id
// File: crates/api_models/src/routing.rs
// Module: api_models

pub fn update_surcharge_config_id(&mut self, ids: String)


// Struct: Tokenization
// File: crates/diesel_models/src/tokenization.rs
// Module: diesel_models
// Implementations: 0

pub struct Tokenization


// Struct: GetSubscriptionPlanPricesRequest
// File: crates/hyperswitch_domain_models/src/router_request_types/subscriptions.rs
// Module: hyperswitch_domain_models
// Implementations: 0

pub struct GetSubscriptionPlanPricesRequest


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

pub struct PaypalQueryParams


        test_mode: test_mode_in_config,
    };

    create_payout_link_db_entry(state, merchant_id, &data, req.return_url.clone()).await
}

pub async fn create_payout_link_db_entry(
    state: &SessionState,
    merchant_id: &id_type::MerchantId,
    payout_link_data: &PayoutLinkData,
    return_url: Option<String>,
) -> RouterResult<PayoutLink> {
    let db: &dyn StorageInterface = &*state.store;

    let link_data = serde_json::to_value(payout_link_data)
        .map_err(|_| report!(errors::ApiErrorResponse::InternalServerError))
        .attach_printable("Failed to convert PayoutLinkData to Value")?;

    let payout_link = GenericLinkNew {
        link_id: payout_link_data.payout_link_id.to_string(),
        primary_reference: payout_link_data.payout_id.get_string_repr().to_string(),
        merchant_id: merchant_id.to_owned(),
        link_type: common_enums::GenericLinkType::PayoutLink,
        link_status: GenericLinkStatus::PayoutLink(PayoutLinkStatus::Initiated),
        link_data,
        url: payout_link_data.link.to_string().into(),
        return_url,
        expiry: common_utils::date_time::now()
            + Duration::seconds(payout_link_data.session_expiry.into()),
        ..Default::default()
    };

    db.insert_payout_link(payout_link)
        .await
        .to_duplicate_response(errors::ApiErrorResponse::GenericDuplicateError {
            message: "payout link already exists".to_string(),
        })
}

#[instrument(skip_all)]
pub async fn get_mca_from_profile_id(
    state: &SessionState,
    merchant_context: &domain::MerchantContext,
    profile_id: &id_type::ProfileId,
    connector_name: &str,
    merchant_connector_id: Option<&id_type::MerchantConnectorAccountId>,
) -> RouterResult<payment_helpers::MerchantConnectorAccountType> {
    let merchant_connector_account = payment_helpers::get_merchant_connector_account(
        state,
        merchant_context.get_merchant_account().get_id(),
        None,
        merchant_context.get_merchant_key_store(),
        profile_id,
        connector_name,
        merchant_connector_id,
    )
    .await?;

    Ok(merchant_connector_account)
}


// Implementation: impl Xendit
// File: crates/hyperswitch_connectors/src/connectors/xendit.rs
// Module: hyperswitch_connectors
// Methods: 1 total (1 public)

impl Xendit


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

pub struct CybersourceRecipientInfo


// Struct: ErrorResponse
// File: crates/api_models/src/errors/types.rs
// Module: api_models
// Implementations: 0

pub struct ErrorResponse