                expiry_date,
            } => Self::Pix(Box::new(
                api_models::payments::additional_info::PixBankTransferAdditionalData {
                    pix_key: pix_key.map(MaskedBankAccount::from),
                    cpf: cpf.map(MaskedBankAccount::from),
                    cnpj: cnpj.map(MaskedBankAccount::from),
                    source_bank_account_id,
                    destination_bank_account_id,
                    expiry_date,
                },
            )),
            BankTransferData::Pse {} => Self::Pse {},
            BankTransferData::LocalBankTransfer { bank_code } => Self::LocalBankTransfer(Box::new(
                api_models::payments::additional_info::LocalBankTransferAdditionalData {
                    bank_code: bank_code.map(MaskedBankAccount::from),
                },
            )),
            BankTransferData::InstantBankTransfer {} => Self::InstantBankTransfer {},
            BankTransferData::InstantBankTransferFinland {} => Self::InstantBankTransferFinland {},
            BankTransferData::InstantBankTransferPoland {} => Self::InstantBankTransferPoland {},
            BankTransferData::IndonesianBankTransfer { bank_name } => {
                Self::IndonesianBankTransfer { bank_name }
            }
        }
    }
}

impl From<api_models::payments::RealTimePaymentData> for RealTimePaymentData {
    fn from(value: api_models::payments::RealTimePaymentData) -> Self {
        match value {
            api_models::payments::RealTimePaymentData::Fps {} => Self::Fps {},
            api_models::payments::RealTimePaymentData::DuitNow {} => Self::DuitNow {},
            api_models::payments::RealTimePaymentData::PromptPay {} => Self::PromptPay {},
            api_models::payments::RealTimePaymentData::VietQr {} => Self::VietQr {},
        }
    }
}

impl From<RealTimePaymentData> for api_models::payments::RealTimePaymentData {
    fn from(value: RealTimePaymentData) -> Self {
        match value {
            RealTimePaymentData::Fps {} => Self::Fps {},
            RealTimePaymentData::DuitNow {} => Self::DuitNow {},
            RealTimePaymentData::PromptPay {} => Self::PromptPay {},
            RealTimePaymentData::VietQr {} => Self::VietQr {},
        }
    }
}

impl From<api_models::payments::OpenBankingData> for OpenBankingData {
    fn from(value: api_models::payments::OpenBankingData) -> Self {
        match value {
            api_models::payments::OpenBankingData::OpenBankingPIS {} => Self::OpenBankingPIS {},
        }
    }
}

impl From<OpenBankingData> for api_models::payments::OpenBankingData {
    fn from(value: OpenBankingData) -> Self {
        match value {
            OpenBankingData::OpenBankingPIS {} => Self::OpenBankingPIS {},
        }
    }
}

impl From<api_models::payments::MobilePaymentData> for MobilePaymentData {
    fn from(value: api_models::payments::MobilePaymentData) -> Self {
        match value {
            api_models::payments::MobilePaymentData::DirectCarrierBilling {
                msisdn,
                client_uid,
            } => Self::DirectCarrierBilling { msisdn, client_uid },
        }
    }
}

impl From<MobilePaymentData> for api_models::payments::MobilePaymentData {
    fn from(value: MobilePaymentData) -> Self {
        match value {
            MobilePaymentData::DirectCarrierBilling { msisdn, client_uid } => {
                Self::DirectCarrierBilling { msisdn, client_uid }
            }
        }
    }
}

#[derive(Debug, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TokenizedCardValue1 {
    pub card_number: String,
    pub exp_year: String,
    pub exp_month: String,
    pub nickname: Option<String>,
    pub card_last_four: Option<String>,
    pub card_token: Option<String>,
    pub card_holder_name: Option<Secret<String>>,
}

#[derive(Debug, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TokenizedCardValue2 {
    pub card_security_code: Option<String>,
    pub card_fingerprint: Option<String>,
    pub external_id: Option<String>,
    pub customer_id: Option<id_type::CustomerId>,
    pub payment_method_id: Option<String>,
}

#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct TokenizedWalletValue1 {
    pub data: WalletData,
}

#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct TokenizedWalletValue2 {
    pub customer_id: Option<id_type::CustomerId>,
}

#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct TokenizedBankTransferValue1 {
    pub data: BankTransferData,
}

#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct TokenizedBankTransferValue2 {
    pub customer_id: Option<id_type::CustomerId>,
}

#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct TokenizedBankRedirectValue1 {
    pub data: BankRedirectData,
}

#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct TokenizedBankRedirectValue2 {
    pub customer_id: Option<id_type::CustomerId>,
}

#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct TokenizedBankDebitValue2 {
    pub customer_id: Option<id_type::CustomerId>,
}

#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct TokenizedBankDebitValue1 {
    pub data: BankDebitData,
}

pub trait GetPaymentMethodType {
    fn get_payment_method_type(&self) -> api_enums::PaymentMethodType;
}

impl GetPaymentMethodType for CardRedirectData {
    fn get_payment_method_type(&self) -> api_enums::PaymentMethodType {
        match self {
            Self::Knet {} => api_enums::PaymentMethodType::Knet,
            Self::Benefit {} => api_enums::PaymentMethodType::Benefit,
            Self::MomoAtm {} => api_enums::PaymentMethodType::MomoAtm,
            Self::CardRedirect {} => api_enums::PaymentMethodType::CardRedirect,
        }
    }
}

impl GetPaymentMethodType for WalletData {
    fn get_payment_method_type(&self) -> api_enums::PaymentMethodType {
        match self {
            Self::AliPayQr(_) | Self::AliPayRedirect(_) => api_enums::PaymentMethodType::AliPay,
            Self::AliPayHkRedirect(_) => api_enums::PaymentMethodType::AliPayHk,
            Self::AmazonPayRedirect(_) => api_enums::PaymentMethodType::AmazonPay,
            Self::Skrill(_) => api_enums::PaymentMethodType::Skrill,
            Self::Paysera(_) => api_enums::PaymentMethodType::Paysera,
            Self::MomoRedirect(_) => api_enums::PaymentMethodType::Momo,
            Self::KakaoPayRedirect(_) => api_enums::PaymentMethodType::KakaoPay,
            Self::GoPayRedirect(_) => api_enums::PaymentMethodType::GoPay,
            Self::GcashRedirect(_) => api_enums::PaymentMethodType::Gcash,
            Self::AmazonPay(_) => api_enums::PaymentMethodType::AmazonPay,
            Self::ApplePay(_) | Self::ApplePayRedirect(_) | Self::ApplePayThirdPartySdk(_) => {
                api_enums::PaymentMethodType::ApplePay
            }
            Self::DanaRedirect {} => api_enums::PaymentMethodType::Dana,
            Self::GooglePay(_) | Self::GooglePayRedirect(_) | Self::GooglePayThirdPartySdk(_) => {
                api_enums::PaymentMethodType::GooglePay
            }
            Self::BluecodeRedirect {} => api_enums::PaymentMethodType::Bluecode,
            Self::MbWayRedirect(_) => api_enums::PaymentMethodType::MbWay,
            Self::MobilePayRedirect(_) => api_enums::PaymentMethodType::MobilePay,
            Self::PaypalRedirect(_) | Self::PaypalSdk(_) => api_enums::PaymentMethodType::Paypal,
            Self::Paze(_) => api_enums::PaymentMethodType::Paze,
            Self::SamsungPay(_) => api_enums::PaymentMethodType::SamsungPay,
            Self::TwintRedirect {} => api_enums::PaymentMethodType::Twint,
            Self::VippsRedirect {} => api_enums::PaymentMethodType::Vipps,
            Self::TouchNGoRedirect(_) => api_enums::PaymentMethodType::TouchNGo,
            Self::WeChatPayRedirect(_) | Self::WeChatPayQr(_) => {
                api_enums::PaymentMethodType::WeChatPay
            }
            Self::CashappQr(_) => api_enums::PaymentMethodType::Cashapp,
            Self::SwishQr(_) => api_enums::PaymentMethodType::Swish,
            Self::Mifinity(_) => api_enums::PaymentMethodType::Mifinity,
            Self::RevolutPay(_) => api_enums::PaymentMethodType::RevolutPay,
        }
    }
}

impl GetPaymentMethodType for PayLaterData {
    fn get_payment_method_type(&self) -> api_enums::PaymentMethodType {
        match self {
            Self::KlarnaRedirect { .. } => api_enums::PaymentMethodType::Klarna,
            Self::KlarnaSdk { .. } => api_enums::PaymentMethodType::Klarna,
            Self::FlexitiRedirect { .. } => api_enums::PaymentMethodType::Flexiti,
            Self::AffirmRedirect {} => api_enums::PaymentMethodType::Affirm,
            Self::AfterpayClearpayRedirect { .. } => api_enums::PaymentMethodType::AfterpayClearpay,
            Self::PayBrightRedirect {} => api_enums::PaymentMethodType::PayBright,
            Self::WalleyRedirect {} => api_enums::PaymentMethodType::Walley,
            Self::AlmaRedirect {} => api_enums::PaymentMethodType::Alma,
            Self::AtomeRedirect {} => api_enums::PaymentMethodType::Atome,
            Self::BreadpayRedirect {} => api_enums::PaymentMethodType::Breadpay,
        }
    }
}

impl GetPaymentMethodType for BankRedirectData {
    fn get_payment_method_type(&self) -> api_enums::PaymentMethodType {
        match self {
            Self::BancontactCard { .. } => api_enums::PaymentMethodType::BancontactCard,
            Self::Bizum {} => api_enums::PaymentMethodType::Bizum,
            Self::Blik { .. } => api_enums::PaymentMethodType::Blik,
            Self::Eft { .. } => api_enums::PaymentMethodType::Eft,
            Self::Eps { .. } => api_enums::PaymentMethodType::Eps,
            Self::Giropay { .. } => api_enums::PaymentMethodType::Giropay,
            Self::Ideal { .. } => api_enums::PaymentMethodType::Ideal,
            Self::Interac { .. } => api_enums::PaymentMethodType::Interac,
            Self::OnlineBankingCzechRepublic { .. } => {
                api_enums::PaymentMethodType::OnlineBankingCzechRepublic
            }
            Self::OnlineBankingFinland { .. } => api_enums::PaymentMethodType::OnlineBankingFinland,
            Self::OnlineBankingPoland { .. } => api_enums::PaymentMethodType::OnlineBankingPoland,
            Self::OnlineBankingSlovakia { .. } => {
                api_enums::PaymentMethodType::OnlineBankingSlovakia
            }
            Self::OpenBankingUk { .. } => api_enums::PaymentMethodType::OpenBankingUk,
            Self::Przelewy24 { .. } => api_enums::PaymentMethodType::Przelewy24,
            Self::Sofort { .. } => api_enums::PaymentMethodType::Sofort,
            Self::Trustly { .. } => api_enums::PaymentMethodType::Trustly,
            Self::OnlineBankingFpx { .. } => api_enums::PaymentMethodType::OnlineBankingFpx,
            Self::OnlineBankingThailand { .. } => {
                api_enums::PaymentMethodType::OnlineBankingThailand
            }
            Self::LocalBankRedirect { .. } => api_enums::PaymentMethodType::LocalBankRedirect,
        }
    }
}

impl GetPaymentMethodType for BankDebitData {
    fn get_payment_method_type(&self) -> api_enums::PaymentMethodType {
        match self {
            Self::AchBankDebit { .. } => api_enums::PaymentMethodType::Ach,
            Self::SepaBankDebit { .. } => api_enums::PaymentMethodType::Sepa,
            Self::BecsBankDebit { .. } => api_enums::PaymentMethodType::Becs,
            Self::BacsBankDebit { .. } => api_enums::PaymentMethodType::Bacs,
        }
    }
}

impl GetPaymentMethodType for BankTransferData {
    fn get_payment_method_type(&self) -> api_enums::PaymentMethodType {
        match self {
            Self::AchBankTransfer { .. } => api_enums::PaymentMethodType::Ach,
            Self::SepaBankTransfer { .. } => api_enums::PaymentMethodType::Sepa,
            Self::BacsBankTransfer { .. } => api_enums::PaymentMethodType::Bacs,
            Self::MultibancoBankTransfer { .. } => api_enums::PaymentMethodType::Multibanco,
            Self::PermataBankTransfer { .. } => api_enums::PaymentMethodType::PermataBankTransfer,
            Self::BcaBankTransfer { .. } => api_enums::PaymentMethodType::BcaBankTransfer,
            Self::BniVaBankTransfer { .. } => api_enums::PaymentMethodType::BniVa,
            Self::BriVaBankTransfer { .. } => api_enums::PaymentMethodType::BriVa,
            Self::CimbVaBankTransfer { .. } => api_enums::PaymentMethodType::CimbVa,
            Self::DanamonVaBankTransfer { .. } => api_enums::PaymentMethodType::DanamonVa,
            Self::MandiriVaBankTransfer { .. } => api_enums::PaymentMethodType::MandiriVa,
            Self::Pix { .. } => api_enums::PaymentMethodType::Pix,
            Self::Pse {} => api_enums::PaymentMethodType::Pse,
            Self::LocalBankTransfer { .. } => api_enums::PaymentMethodType::LocalBankTransfer,
            Self::InstantBankTransfer {} => api_enums::PaymentMethodType::InstantBankTransfer,
            Self::InstantBankTransferFinland {} => {
                api_enums::PaymentMethodType::InstantBankTransferFinland
            }
            Self::InstantBankTransferPoland {} => {
                api_enums::PaymentMethodType::InstantBankTransferPoland
            }
            Self::IndonesianBankTransfer { .. } => {
                api_enums::PaymentMethodType::IndonesianBankTransfer
            }
        }
    }
}

impl GetPaymentMethodType for CryptoData {
    fn get_payment_method_type(&self) -> api_enums::PaymentMethodType {
        api_enums::PaymentMethodType::CryptoCurrency
    }
}

impl GetPaymentMethodType for RealTimePaymentData {
    fn get_payment_method_type(&self) -> api_enums::PaymentMethodType {
        match self {
            Self::Fps {} => api_enums::PaymentMethodType::Fps,
            Self::DuitNow {} => api_enums::PaymentMethodType::DuitNow,
            Self::PromptPay {} => api_enums::PaymentMethodType::PromptPay,
            Self::VietQr {} => api_enums::PaymentMethodType::VietQr,
        }
    }
}

impl GetPaymentMethodType for UpiData {
    fn get_payment_method_type(&self) -> api_enums::PaymentMethodType {
        match self {
            Self::UpiCollect(_) => api_enums::PaymentMethodType::UpiCollect,
            Self::UpiIntent(_) => api_enums::PaymentMethodType::UpiIntent,
        }
    }
}
impl GetPaymentMethodType for VoucherData {
    fn get_payment_method_type(&self) -> api_enums::PaymentMethodType {
        match self {
            Self::Boleto(_) => api_enums::PaymentMethodType::Boleto,
            Self::Efecty => api_enums::PaymentMethodType::Efecty,
            Self::PagoEfectivo => api_enums::PaymentMethodType::PagoEfectivo,
            Self::RedCompra => api_enums::PaymentMethodType::RedCompra,
            Self::RedPagos => api_enums::PaymentMethodType::RedPagos,
            Self::Alfamart(_) => api_enums::PaymentMethodType::Alfamart,
            Self::Indomaret(_) => api_enums::PaymentMethodType::Indomaret,
            Self::Oxxo => api_enums::PaymentMethodType::Oxxo,
            Self::SevenEleven(_) => api_enums::PaymentMethodType::SevenEleven,
            Self::Lawson(_) => api_enums::PaymentMethodType::Lawson,
            Self::MiniStop(_) => api_enums::PaymentMethodType::MiniStop,
            Self::FamilyMart(_) => api_enums::PaymentMethodType::FamilyMart,
            Self::Seicomart(_) => api_enums::PaymentMethodType::Seicomart,
            Self::PayEasy(_) => api_enums::PaymentMethodType::PayEasy,
        }
    }
}
impl GetPaymentMethodType for GiftCardData {
    fn get_payment_method_type(&self) -> api_enums::PaymentMethodType {
        match self {
            Self::Givex(_) => api_enums::PaymentMethodType::Givex,
            Self::PaySafeCard {} => api_enums::PaymentMethodType::PaySafeCard,
            Self::BhnCardNetwork(_) => api_enums::PaymentMethodType::BhnCardNetwork,
        }
    }
}

impl GetPaymentMethodType for OpenBankingData {
    fn get_payment_method_type(&self) -> api_enums::PaymentMethodType {
        match self {
            Self::OpenBankingPIS {} => api_enums::PaymentMethodType::OpenBankingPIS,
        }
    }
}

impl GetPaymentMethodType for MobilePaymentData {
    fn get_payment_method_type(&self) -> api_enums::PaymentMethodType {
        match self {
            Self::DirectCarrierBilling { .. } => api_enums::PaymentMethodType::DirectCarrierBilling,
        }
    }
}

impl From<Card> for ExtendedCardInfo {
    fn from(value: Card) -> Self {
        Self {
            card_number: value.card_number,
            card_exp_month: value.card_exp_month,
            card_exp_year: value.card_exp_year,
            card_holder_name: None,
            card_cvc: value.card_cvc,
            card_issuer: value.card_issuer,
            card_network: value.card_network,
            card_type: value.card_type,
            card_issuing_country: value.card_issuing_country,
            bank_code: value.bank_code,
        }
    }
}

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

impl From<GooglePayWalletData> for payment_methods::PaymentMethodDataWalletInfo {
    fn from(item: GooglePayWalletData) -> Self {
        Self {
            last4: item.info.card_details,
            card_network: item.info.card_network,
            card_type: Some(item.pm_type),
        }
    }
}

#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize)]
pub enum PaymentMethodsData {
    Card(CardDetailsPaymentMethod),
    BankDetails(payment_methods::PaymentMethodDataBankCreds), //PaymentMethodDataBankCreds and its transformations should be moved to the domain models
    WalletDetails(payment_methods::PaymentMethodDataWalletInfo), //PaymentMethodDataWalletInfo and its transformations should be moved to the domain models
    NetworkToken(NetworkTokenDetailsPaymentMethod),
}

impl PaymentMethodsData {
    #[cfg(feature = "v1")]
    pub fn get_co_badged_card_data(&self) -> Option<payment_methods::CoBadgedCardData> {
        if let Self::Card(card) = self {
            card.co_badged_card_data.clone()
        } else {
            None
        }
    }
    #[cfg(feature = "v2")]
    pub fn get_co_badged_card_data(&self) -> Option<payment_methods::CoBadgedCardData> {
        todo!()
    }

    #[cfg(feature = "v1")]
    pub fn get_additional_payout_method_data(
        &self,
    ) -> Option<payout_method_utils::AdditionalPayoutMethodData> {
        match self {
            Self::Card(card_details) => {
                router_env::logger::info!("Populating AdditionalPayoutMethodData from Card payment method data for recurring payout");
                Some(payout_method_utils::AdditionalPayoutMethodData::Card(
                    Box::new(payout_method_utils::CardAdditionalData {
                        card_issuer: card_details.card_issuer.clone(),
                        card_network: card_details.card_network.clone(),
                        bank_code: None,
                        card_type: card_details.card_type.clone(),
                        card_issuing_country: card_details.issuer_country.clone(),
                        last4: card_details.last4_digits.clone(),
                        card_isin: card_details.card_isin.clone(),
                        card_extended_bin: None,
                        card_exp_month: card_details.expiry_month.clone(),
                        card_exp_year: card_details.expiry_year.clone(),
                        card_holder_name: card_details.card_holder_name.clone(),
                    }),
                ))
            }
            Self::BankDetails(_) | Self::WalletDetails(_) | Self::NetworkToken(_) => None,
        }
    }
    pub fn get_card_details(&self) -> Option<CardDetailsPaymentMethod> {
        if let Self::Card(card) = self {
            Some(card.clone())
        } else {
            None
        }
    }
}

#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
pub struct NetworkTokenDetailsPaymentMethod {
    pub last4_digits: Option<String>,
    pub issuer_country: Option<common_enums::CountryAlpha2>,
    pub network_token_expiry_month: Option<Secret<String>>,
    pub network_token_expiry_year: Option<Secret<String>>,
    pub nick_name: Option<Secret<String>>,
    pub card_holder_name: Option<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,
}

fn saved_in_locker_default() -> bool {
    true
}

#[cfg(feature = "v1")]
#[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<Secret<String>>,
    pub expiry_year: Option<Secret<String>>,
    pub nick_name: Option<Secret<String>>,
    pub card_holder_name: Option<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<payment_methods::CoBadgedCardData>,
}

#[cfg(feature = "v2")]
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
pub struct CardDetailsPaymentMethod {
    pub last4_digits: Option<String>,
    pub issuer_country: Option<String>,
    pub expiry_month: Option<Secret<String>>,
    pub expiry_year: Option<Secret<String>>,
    pub nick_name: Option<Secret<String>>,
    pub card_holder_name: Option<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,
}

#[cfg(feature = "v2")]
impl CardDetailsPaymentMethod {
    pub fn to_card_details_from_locker(self) -> payment_methods::CardDetailFromLocker {
        payment_methods::CardDetailFromLocker {
            card_number: None,
            card_holder_name: self.card_holder_name.clone(),
            card_issuer: self.card_issuer.clone(),
            card_network: self.card_network.clone(),
            card_type: self.card_type.clone(),
            issuer_country: self.clone().get_issuer_country_alpha2(),
            last4_digits: self.last4_digits,
            expiry_month: self.expiry_month,
            expiry_year: self.expiry_year,
            card_fingerprint: None,
            nick_name: self.nick_name,
            card_isin: self.card_isin,
            saved_to_locker: self.saved_to_locker,
        }
    }

    pub fn get_issuer_country_alpha2(self) -> Option<common_enums::CountryAlpha2> {
        self.issuer_country
            .as_ref()
            .map(|c| api_enums::CountryAlpha2::from_str(c))
            .transpose()
            .ok()
            .flatten()
    }
}

#[cfg(feature = "v1")]
impl From<payment_methods::CardDetail> for CardDetailsPaymentMethod {
    fn from(item: payment_methods::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 = "v2")]
impl From<payment_methods::CardDetail> for CardDetailsPaymentMethod {
    fn from(item: payment_methods::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,
        }
    }
}

#[cfg(feature = "v2")]
impl From<NetworkTokenDetails> for NetworkTokenDetailsPaymentMethod {
    fn from(item: NetworkTokenDetails) -> Self {
        Self {
            issuer_country: item.card_issuing_country,
            last4_digits: Some(item.network_token.get_last4()),
            network_token_expiry_month: Some(item.network_token_exp_month),
            network_token_expiry_year: Some(item.network_token_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,
        }
    }
}

#[cfg(feature = "v2")]
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
pub struct SingleUsePaymentMethodToken {
    pub token: Secret<String>,
    pub merchant_connector_id: id_type::MerchantConnectorAccountId,
}

#[cfg(feature = "v2")]
impl SingleUsePaymentMethodToken {
    pub fn get_single_use_token_from_payment_method_token(
        token: Secret<String>,
        mca_id: id_type::MerchantConnectorAccountId,
    ) -> Self {
        Self {
            token,
            merchant_connector_id: mca_id,
        }
    }
}

impl From<NetworkTokenDetailsPaymentMethod> for payment_methods::NetworkTokenDetailsPaymentMethod {
    fn from(item: NetworkTokenDetailsPaymentMethod) -> Self {
        Self {
            last4_digits: item.last4_digits,
            issuer_country: item.issuer_country,
            network_token_expiry_month: item.network_token_expiry_month,
            network_token_expiry_year: item.network_token_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,
        }
    }
}

#[cfg(feature = "v2")]
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
pub struct SingleUseTokenKey(String);

#[cfg(feature = "v2")]
impl SingleUseTokenKey {
    pub fn store_key(payment_method_id: &id_type::GlobalPaymentMethodId) -> Self {
        let new_token = format!("single_use_token_{}", payment_method_id.get_string_repr());
        Self(new_token)
    }

    pub fn get_store_key(&self) -> &str {
        &self.0
    }
}

#[cfg(feature = "v1")]
impl From<Card> for payment_methods::CardDetail {
    fn from(card_data: Card) -> Self {
        Self {
            card_number: card_data.card_number.clone(),
            card_exp_month: card_data.card_exp_month.clone(),
            card_exp_year: card_data.card_exp_year.clone(),
            card_holder_name: None,
            nick_name: None,
            card_issuing_country: None,
            card_network: card_data.card_network.clone(),
            card_issuer: None,
            card_type: None,
        }
    }
}

#[cfg(feature = "v1")]
impl From<NetworkTokenData> for payment_methods::CardDetail {
    fn from(network_token_data: NetworkTokenData) -> Self {
        Self {
            card_number: network_token_data.token_number.clone(),
            card_exp_month: network_token_data.token_exp_month.clone(),
            card_exp_year: network_token_data.token_exp_year.clone(),
            card_holder_name: None,
            nick_name: None,
            card_issuing_country: None,
            card_network: network_token_data.card_network.clone(),
            card_issuer: None,
            card_type: None,
        }
    }
}

#[cfg(feature = "v1")]
impl
    From<(
        payment_methods::CardDetail,
        Option<&CardToken>,
        Option<payment_methods::CoBadgedCardData>,
    )> for Card
{
    fn from(
        value: (
            payment_methods::CardDetail,
            Option<&CardToken>,
            Option<payment_methods::CoBadgedCardData>,
        ),
    ) -> Self {
        let (
            payment_methods::CardDetail {
                card_number,
                card_exp_month,
                card_exp_year,
                card_holder_name,
                nick_name,
                card_network,
                card_issuer,
                card_issuing_country,
                card_type,
            },
            card_token_data,
            co_badged_card_data,
        ) = value;

        // The card_holder_name from locker retrieved card is considered if it is a non-empty string or else card_holder_name is picked
        let name_on_card = if let Some(name) = card_holder_name.clone() {
            if name.clone().expose().is_empty() {
                card_token_data
                    .and_then(|token_data| token_data.card_holder_name.clone())
                    .or(Some(name))
            } else {
                card_holder_name
            }
        } else {
            card_token_data.and_then(|token_data| token_data.card_holder_name.clone())
        };

        Self {
            card_number,
            card_exp_month,
            card_exp_year,
            card_holder_name: name_on_card,
            card_cvc: card_token_data
                .cloned()
                .unwrap_or_default()
                .card_cvc
                .unwrap_or_default(),
            card_issuer,
            card_network,
            card_type,
            card_issuing_country,
            bank_code: None,
            nick_name,
            co_badged_card_data,
        }
    }
}

#[cfg(feature = "v1")]
impl
    TryFrom<(
        cards::CardNumber,
        Option<&CardToken>,
        Option<payment_methods::CoBadgedCardData>,
        CardDetailsPaymentMethod,
    )> for Card
{
    type Error = error_stack::Report<common_utils::errors::ValidationError>;
    fn try_from(
        value: (
            cards::CardNumber,
            Option<&CardToken>,
            Option<payment_methods::CoBadgedCardData>,
            CardDetailsPaymentMethod,
        ),
    ) -> Result<Self, Self::Error> {
        let (card_number, card_token_data, co_badged_card_data, card_details) = value;

        // The card_holder_name from locker retrieved card is considered if it is a non-empty string or else card_holder_name is picked
        let name_on_card = if let Some(name) = card_details.card_holder_name.clone() {
            if name.clone().expose().is_empty() {
                card_token_data
                    .and_then(|token_data| token_data.card_holder_name.clone())
                    .or(Some(name))
            } else {
                Some(name)
            }
        } else {
            card_token_data.and_then(|token_data| token_data.card_holder_name.clone())
        };

        Ok(Self {
            card_number,
            card_exp_month: card_details
                .expiry_month
                .get_required_value("expiry_month")?
                .clone(),
            card_exp_year: card_details
                .expiry_year
                .get_required_value("expiry_year")?
                .clone(),
            card_holder_name: name_on_card,
            card_cvc: card_token_data
                .cloned()
                .unwrap_or_default()
                .card_cvc
                .unwrap_or_default(),
            card_issuer: card_details.card_issuer,
            card_network: card_details.card_network,
            card_type: card_details.card_type,
            card_issuing_country: card_details.issuer_country,
            bank_code: None,
            nick_name: card_details.nick_name,
            co_badged_card_data,
        })
    }
}


// Struct: Customer
// File: crates/hyperswitch_connectors/src/connectors/paypal/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct Customer


// Function: payments_connector_session
// File: crates/router/src/routes/payments.rs
// Module: router

pub fn payments_connector_session(
    state: web::Data<app::AppState>,
    req: actix_web::HttpRequest,
    json_payload: web::Json<payment_types::PaymentsSessionRequest>,
) -> impl Responder


// Struct: PaypalMandateStruct
// File: crates/hyperswitch_connectors/src/connectors/paypal/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct PaypalMandateStruct


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

impl Responder


// Implementation: impl Profile
// File: crates/router/src/routes/app.rs
// Module: router
// Methods: 1 total (1 public)

impl Profile


// File: crates/router_derive/src/macros/to_encryptable.rs
// Module: router_derive
// Public functions: 1
// Public structs: 1

use std::iter::Iterator;

use quote::{format_ident, quote};
use syn::{parse::Parse, punctuated::Punctuated, token::Comma, Field, Ident, Type as SynType};

use crate::macros::{helpers::get_struct_fields, misc::get_field_type};

pub struct FieldMeta {
    _meta_type: Ident,
    pub value: Ident,
}

impl Parse for FieldMeta {
    fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
        let _meta_type: Ident = input.parse()?;
        input.parse::<syn::Token![=]>()?;
        let value: Ident = input.parse()?;
        Ok(Self { _meta_type, value })
    }
}

impl quote::ToTokens for FieldMeta {
    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
        self.value.to_tokens(tokens);
    }
}

fn get_encryption_ty_meta(field: &Field) -> Option<FieldMeta> {
    let attrs = &field.attrs;

    attrs
        .iter()
        .flat_map(|s| s.parse_args::<FieldMeta>())
        .find(|s| s._meta_type.eq("ty"))
}

fn get_inner_type(path: &syn::TypePath) -> syn::Result<syn::TypePath> {
    path.path
        .segments
        .last()
        .and_then(|segment| match &segment.arguments {
            syn::PathArguments::AngleBracketed(args) => args.args.first(),
            _ => None,
        })
        .and_then(|arg| match arg {
            syn::GenericArgument::Type(SynType::Path(path)) => Some(path.clone()),
            _ => None,
        })
        .ok_or_else(|| {
            syn::Error::new(
                proc_macro2::Span::call_site(),
                "Only path fields are supported",
            )
        })
}

/// This function returns the inner most type recursively
/// For example:
///
/// In the case of `Encryptable<Secret<String>>> this returns String
fn get_inner_most_type(ty: SynType) -> syn::Result<Ident> {
    fn get_inner_type_recursive(path: syn::TypePath) -> syn::Result<syn::TypePath> {
        match get_inner_type(&path) {
            Ok(inner_path) => get_inner_type_recursive(inner_path),
            Err(_) => Ok(path),
        }
    }

    match ty {
        SynType::Path(path) => {
            let inner_path = get_inner_type_recursive(path)?;
            inner_path
                .path
                .segments
                .last()
                .map(|last_segment| last_segment.ident.to_owned())
                .ok_or_else(|| {
                    syn::Error::new(
                        proc_macro2::Span::call_site(),
                        "At least one ident must be specified",
                    )
                })
        }
        _ => Err(syn::Error::new(
            proc_macro2::Span::call_site(),
            "Only path fields are supported",
        )),
    }
}

/// This returns the field which implement #[encrypt] attribute
fn get_encryptable_fields(fields: Punctuated<Field, Comma>) -> Vec<Field> {
    fields
        .into_iter()
        .filter(|field| {
            field
                .attrs
                .iter()
                .any(|attr| attr.path().is_ident("encrypt"))
        })
        .collect()
}

/// This function returns the inner most type of a field
fn get_field_and_inner_types(fields: &[Field]) -> Vec<(Field, Ident)> {
    fields
        .iter()
        .flat_map(|field| {
            get_inner_most_type(field.ty.clone()).map(|field_name| (field.to_owned(), field_name))
        })
        .collect()
}

/// The type of the struct for which the batch encryption/decryption needs to be implemented
#[derive(PartialEq, Copy, Clone)]
enum StructType {
    Encrypted,
    Decrypted,
    DecryptedUpdate,
    FromRequest,
    Updated,
}

impl StructType {
    /// Generates the fields for temporary structs which consists of the fields that should be
    /// encrypted/decrypted
    fn generate_struct_fields(self, fields: &[(Field, Ident)]) -> Vec<proc_macro2::TokenStream> {
        fields
            .iter()
            .map(|(field, inner_ty)| {
                let provided_ty = get_encryption_ty_meta(field);
                let is_option = get_field_type(field.ty.clone())
                    .map(|f| f.eq("Option"))
                    .unwrap_or_default();
                let ident = &field.ident;
                let inner_ty = if let Some(ref ty) = provided_ty {
                    &ty.value
                } else {
                    inner_ty
                };
                match (self, is_option) {
                    (Self::Encrypted, true) => quote! { pub #ident: Option<Encryption> },
                    (Self::Encrypted, false) => quote! { pub #ident: Encryption },
                    (Self::Decrypted, true) => {
                        quote! { pub #ident: Option<Encryptable<Secret<#inner_ty>>> }
                    }
                    (Self::Decrypted, false) => {
                        quote! { pub #ident: Encryptable<Secret<#inner_ty>> }
                    }
                    (Self::DecryptedUpdate, _) => {
                        quote! { pub #ident: Option<Encryptable<Secret<#inner_ty>>> }
                    }
                    (Self::FromRequest, true) => {
                        quote! { pub #ident: Option<Secret<#inner_ty>> }
                    }
                    (Self::FromRequest, false) => quote! { pub #ident: Secret<#inner_ty> },
                    (Self::Updated, _) => quote! { pub #ident: Option<Secret<#inner_ty>> },
                }
            })
            .collect()
    }

    /// Generates the ToEncryptable trait implementation
    fn generate_impls(
        self,
        gen1: proc_macro2::TokenStream,
        gen2: proc_macro2::TokenStream,
        gen3: proc_macro2::TokenStream,
        impl_st: proc_macro2::TokenStream,
        inner: &[Field],
    ) -> proc_macro2::TokenStream {
        let map_length = inner.len();

        let to_encryptable_impl = inner.iter().flat_map(|field| {
            get_field_type(field.ty.clone()).map(|field_ty| {
                let is_option = field_ty.eq("Option");
                let field_ident = &field.ident;
                let field_ident_string = field_ident.as_ref().map(|s| s.to_string());

                if is_option || self == Self::Updated {
                    quote! { self.#field_ident.map(|s| map.insert(#field_ident_string.to_string(), s)) }
                } else {
                    quote! { map.insert(#field_ident_string.to_string(), self.#field_ident) }
                }
            })
        });

        let from_encryptable_impl = inner.iter().flat_map(|field| {
            get_field_type(field.ty.clone()).map(|field_ty| {
                let is_option = field_ty.eq("Option");
                let field_ident = &field.ident;
                let field_ident_string = field_ident.as_ref().map(|s| s.to_string());

                if is_option || self == Self::Updated {
                    quote! { #field_ident: map.remove(#field_ident_string) }
                } else {
                    quote! {
                        #field_ident: map.remove(#field_ident_string).ok_or(
                            error_stack::report!(common_utils::errors::ParsingError::EncodeError(
                                "Unable to convert from HashMap",
                            ))
                        )?
                    }
                }
            })
        });

        quote! {
            impl ToEncryptable<#gen1, #gen2, #gen3> for #impl_st {
                fn to_encryptable(self) -> FxHashMap<String, #gen3> {
                    let mut map = FxHashMap::with_capacity_and_hasher(#map_length, Default::default());
                    #(#to_encryptable_impl;)*
                    map
                }

                fn from_encryptable(
                    mut map: FxHashMap<String, Encryptable<#gen2>>,
                ) -> CustomResult<#gen1, common_utils::errors::ParsingError> {
                    Ok(#gen1 {
                        #(#from_encryptable_impl,)*
                    })
                }
            }
        }
    }
}

/// This function generates the temporary struct and ToEncryptable impls for the temporary structs
fn generate_to_encryptable(
    struct_name: Ident,
    fields: Vec<Field>,
) -> syn::Result<proc_macro2::TokenStream> {
    let struct_types = [
        // The first two are to be used as return types we do not need to implement ToEncryptable
        // on it
        ("Decrypted", StructType::Decrypted),
        ("DecryptedUpdate", StructType::DecryptedUpdate),
        ("FromRequestEncryptable", StructType::FromRequest),
        ("Encrypted", StructType::Encrypted),
        ("UpdateEncryptable", StructType::Updated),
    ];

    let inner_types = get_field_and_inner_types(&fields);

    let inner_type = inner_types.first().ok_or_else(|| {
        syn::Error::new(
            proc_macro2::Span::call_site(),
            "Please use the macro with attribute #[encrypt] on the fields you want to encrypt",
        )
    })?;

    let provided_ty = get_encryption_ty_meta(&inner_type.0)
        .map(|ty| ty.value.clone())
        .unwrap_or(inner_type.1.clone());

    let structs = struct_types.iter().map(|(prefix, struct_type)| {
        let name = format_ident!("{}{}", prefix, struct_name);
        let temp_fields = struct_type.generate_struct_fields(&inner_types);
        quote! {
            pub struct #name {
                #(#temp_fields,)*
            }
        }
    });

    // These implementations shouldn't be implemented Decrypted and DecryptedUpdate temp structs
    // So skip the first two entries in the list
    let impls = struct_types
        .iter()
        .skip(2)
        .map(|(prefix, struct_type)| {
            let name = format_ident!("{}{}", prefix, struct_name);

            let impl_block = if *struct_type != StructType::DecryptedUpdate
                || *struct_type != StructType::Decrypted
            {
                let (gen1, gen2, gen3) = match struct_type {
                    StructType::FromRequest => {
                        let decrypted_name = format_ident!("Decrypted{}", struct_name);
                        (
                            quote! { #decrypted_name },
                            quote! { Secret<#provided_ty> },
                            quote! { Secret<#provided_ty> },
                        )
                    }
                    StructType::Encrypted => {
                        let decrypted_name = format_ident!("Decrypted{}", struct_name);
                        (
                            quote! { #decrypted_name },
                            quote! { Secret<#provided_ty> },
                            quote! { Encryption },
                        )
                    }
                    StructType::Updated => {
                        let decrypted_update_name = format_ident!("DecryptedUpdate{}", struct_name);
                        (
                            quote! { #decrypted_update_name },
                            quote! { Secret<#provided_ty> },
                            quote! { Secret<#provided_ty> },
                        )
                    }
                    //Unreachable statement
                    _ => (quote! {}, quote! {}, quote! {}),
                };

                struct_type.generate_impls(gen1, gen2, gen3, quote! { #name }, &fields)
            } else {
                quote! {}
            };

            Ok(quote! {
                #impl_block
            })
        })
        .collect::<syn::Result<Vec<_>>>()?;

    Ok(quote! {
        #(#structs)*
        #(#impls)*
    })
}

pub fn derive_to_encryption(
    input: syn::DeriveInput,
) -> Result<proc_macro2::TokenStream, syn::Error> {
    let struct_name = input.ident;
    let fields = get_encryptable_fields(get_struct_fields(input.data)?);

    generate_to_encryptable(struct_name, fields)
}


// Implementation: impl DummyConnectorRefundResponse
// File: crates/router/src/routes/dummy_connector/types.rs
// Module: router
// Methods: 1 total (1 public)

impl DummyConnectorRefundResponse


// Function: find_by_merchant_id_customer_id
// File: crates/diesel_models/src/query/mandate.rs
// Module: diesel_models

pub fn find_by_merchant_id_customer_id(
        conn: &PgPooledConn,
        merchant_id: &common_utils::id_type::MerchantId,
        customer_id: &common_utils::id_type::CustomerId,
    ) -> StorageResult<Vec<Self>>


// Function: receive_incoming_relay_webhook
// File: crates/router/src/routes/webhooks.rs
// Module: router

pub fn receive_incoming_relay_webhook<W: types::OutgoingWebhookType>(
    state: web::Data<AppState>,
    req: HttpRequest,
    body: web::Bytes,
    path: web::Path<(
        common_utils::id_type::MerchantId,
        common_utils::id_type::MerchantConnectorAccountId,
    )


// Function: refunds_retrieve
// File: crates/router/src/routes/refunds.rs
// Module: router

pub fn refunds_retrieve(
    state: web::Data<AppState>,
    req: HttpRequest,
    path: web::Path<String>,
    query_params: web::Query<api_models::refunds::RefundsRetrieveBody>,
) -> HttpResponse


// Implementation: impl api::ConnectorAccessToken for for Aci
// File: crates/hyperswitch_connectors/src/connectors/aci.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::ConnectorAccessToken for for Aci


// Implementation: impl api::ConnectorAccessToken for for Tokenio
// File: crates/hyperswitch_connectors/src/connectors/tokenio.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::ConnectorAccessToken for for Tokenio


// Struct: TestPayment
// File: crates/api_models/src/user/dashboard_metadata.rs
// Module: api_models
// Implementations: 0

pub struct TestPayment


// Function: validate
// File: crates/router/src/configs/validations.rs
// Module: router

pub fn validate(&self) -> Result<(), ApplicationError>


// Struct: GlobalpayCancelRouterData
// File: crates/hyperswitch_connectors/src/connectors/globalpay/requests.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct GlobalpayCancelRouterData<T>


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

impl Responder


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

use std::collections::HashSet;

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

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

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

#[async_trait::async_trait]
impl<T> super::PaymentMetric<T> for RetriesCount
where
    T: AnalyticsDataSource + super::PaymentMetricAnalytics,
    PrimitiveDateTime: ToSql<T>,
    AnalyticsCollection: ToSql<T>,
    Granularity: GroupByClause<T>,
    Aggregate<&'static str>: ToSql<T>,
    Window<&'static str>: ToSql<T>,
{
    async fn load_metrics(
        &self,
        _dimensions: &[PaymentDimensions],
        auth: &AuthInfo,
        _filters: &PaymentFilters,
        granularity: Option<Granularity>,
        time_range: &TimeRange,
        pool: &T,
    ) -> MetricsResult<HashSet<(PaymentMetricsBucketIdentifier, PaymentMetricRow)>> {
        let mut query_builder: QueryBuilder<T> =
            QueryBuilder::new(AnalyticsCollection::PaymentIntent);
        query_builder
            .add_select_column(Aggregate::Count {
                field: None,
                alias: Some("count"),
            })
            .switch()?;
        query_builder
            .add_select_column(Aggregate::Sum {
                field: "amount",
                alias: Some("total"),
            })
            .switch()?;
        query_builder
            .add_select_column(Aggregate::Min {
                field: "created_at",
                alias: Some("start_bucket"),
            })
            .switch()?;
        query_builder
            .add_select_column(Aggregate::Max {
                field: "created_at",
                alias: Some("end_bucket"),
            })
            .switch()?;
        auth.set_filter_clause(&mut query_builder).switch()?;

        query_builder
            .add_custom_filter_clause("attempt_count", "1", FilterTypes::Gt)
            .switch()?;
        query_builder
            .add_custom_filter_clause("status", IntentStatus::Succeeded, FilterTypes::Equal)
            .switch()?;
        time_range
            .set_filter_clause(&mut query_builder)
            .attach_printable("Error filtering time range")
            .switch()?;

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

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


// Function: flat_struct_derive
// File: crates/router_derive/src/lib.rs
// Module: router_derive

pub fn flat_struct_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream


// Function: accept_dispute
// File: crates/router/src/routes/disputes.rs
// Module: router

pub fn accept_dispute(
    state: web::Data<AppState>,
    req: HttpRequest,
    path: web::Path<String>,
) -> HttpResponse


// Struct: BankDebitTypes
// File: crates/api_models/src/payment_methods.rs
// Module: api_models
// Implementations: 0

pub struct BankDebitTypes


// Implementation: impl api::Payouts for for Paypal
// File: crates/hyperswitch_connectors/src/connectors/paypal.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::Payouts for for Paypal


// Implementation: impl PaymentConfirmData
// File: crates/hyperswitch_domain_models/src/payments.rs
// Module: hyperswitch_domain_models
// Methods: 3 total (3 public)

impl PaymentConfirmData


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

pub struct CustomerDetails


// Implementation: impl WebhookResponseTracker
// File: crates/api_models/src/webhooks.rs
// Module: api_models
// Methods: 3 total (3 public)

impl WebhookResponseTracker


// File: crates/hyperswitch_connectors/src/connectors/riskified/transformers/api.rs
// Module: hyperswitch_connectors
// Public structs: 30

use api_models::{payments::AdditionalPaymentData, webhooks::IncomingWebhookEvent};
use common_enums::{Currency, FraudCheckStatus};
use common_utils::{
    ext_traits::ValueExt,
    id_type,
    pii::Email,
    types::{AmountConvertor, StringMajorUnit, StringMajorUnitForConnector},
};
use error_stack::{self, ResultExt};
use hyperswitch_domain_models::{
    router_data::RouterData,
    router_flow_types::Fulfillment,
    router_request_types::{
        fraud_check::{FraudCheckFulfillmentData, FulfillmentStatus},
        BrowserInformation, ResponseId,
    },
    router_response_types::fraud_check::FraudCheckResponseData,
};
use hyperswitch_interfaces::errors::ConnectorError;
use masking::Secret;
use serde::{Deserialize, Serialize};
use time::PrimitiveDateTime;

use crate::{
    types::{
        FrmCheckoutRouterData, FrmFulfillmentRouterData, FrmTransactionRouterData,
        ResponseRouterData,
    },
    utils::{
        convert_amount, AddressDetailsData as _, FraudCheckCheckoutRequest,
        FraudCheckTransactionRequest, RouterData as _,
    },
};

type Error = error_stack::Report<ConnectorError>;

pub struct RiskifiedRouterData<T> {
    pub amount: StringMajorUnit,
    pub router_data: T,
    amount_converter: &'static (dyn AmountConvertor<Output = StringMajorUnit> + Sync),
}

impl<T> From<(StringMajorUnit, T)> for RiskifiedRouterData<T> {
    fn from((amount, router_data): (StringMajorUnit, T)) -> Self {
        Self {
            amount,
            router_data,
            amount_converter: &StringMajorUnitForConnector,
        }
    }
}

#[derive(Debug, Deserialize, Serialize, Eq, PartialEq, Clone)]
pub struct RiskifiedPaymentsCheckoutRequest {
    order: CheckoutRequest,
}

#[derive(Debug, Deserialize, Serialize, Eq, PartialEq, Clone)]
pub struct CheckoutRequest {
    id: String,
    note: Option<String>,
    email: Option<Email>,
    #[serde(with = "common_utils::custom_serde::iso8601")]
    created_at: PrimitiveDateTime,
    currency: Option<Currency>,
    #[serde(with = "common_utils::custom_serde::iso8601")]
    updated_at: PrimitiveDateTime,
    gateway: Option<String>,
    browser_ip: Option<std::net::IpAddr>,
    total_price: StringMajorUnit,
    total_discounts: i64,
    cart_token: String,
    referring_site: String,
    line_items: Vec<LineItem>,
    discount_codes: Vec<DiscountCodes>,
    shipping_lines: Vec<ShippingLines>,
    payment_details: Option<PaymentDetails>,
    customer: RiskifiedCustomer,
    billing_address: Option<OrderAddress>,
    shipping_address: Option<OrderAddress>,
    source: Source,
    client_details: ClientDetails,
    vendor_name: String,
}

#[derive(Debug, Deserialize, Serialize, Eq, PartialEq, Clone)]
pub struct PaymentDetails {
    credit_card_bin: Option<Secret<String>>,
    credit_card_number: Option<Secret<String>>,
    credit_card_company: Option<api_models::enums::CardNetwork>,
}

#[derive(Debug, Deserialize, Serialize, Eq, PartialEq, Clone)]
pub struct ShippingLines {
    price: StringMajorUnit,
    title: Option<String>,
}

#[derive(Debug, Deserialize, Serialize, Eq, PartialEq, Clone)]
pub struct DiscountCodes {
    amount: StringMajorUnit,
    code: Option<String>,
}

#[derive(Debug, Deserialize, Serialize, Eq, PartialEq, Clone)]
pub struct ClientDetails {
    user_agent: Option<String>,
    accept_language: Option<String>,
}

#[derive(Debug, Deserialize, Serialize, Eq, PartialEq, Clone)]
pub struct RiskifiedCustomer {
    email: Option<Email>,
    first_name: Option<Secret<String>>,
    last_name: Option<Secret<String>>,
    #[serde(with = "common_utils::custom_serde::iso8601")]
    created_at: PrimitiveDateTime,
    verified_email: bool,
    id: id_type::CustomerId,
    account_type: CustomerAccountType,
    orders_count: i32,
    phone: Option<Secret<String>>,
}

#[derive(Debug, Deserialize, Serialize, Eq, PartialEq, Clone)]
#[serde(rename_all = "lowercase")]
pub enum CustomerAccountType {
    Guest,
}

#[derive(Debug, Deserialize, Serialize, Eq, PartialEq, Clone)]
pub struct OrderAddress {
    first_name: Option<Secret<String>>,
    last_name: Option<Secret<String>>,
    address1: Option<Secret<String>>,
    country_code: Option<common_enums::CountryAlpha2>,
    city: Option<String>,
    province: Option<Secret<String>>,
    phone: Option<Secret<String>>,
    zip: Option<Secret<String>>,
}

#[derive(Debug, Deserialize, Serialize, Eq, PartialEq, Clone)]
pub struct LineItem {
    price: StringMajorUnit,
    quantity: i32,
    title: String,
    product_type: Option<common_enums::ProductType>,
    requires_shipping: Option<bool>,
    product_id: Option<String>,
    category: Option<String>,
    brand: Option<String>,
}

#[derive(Debug, Deserialize, Serialize, Eq, PartialEq, Clone)]
#[serde(rename_all = "snake_case")]
pub enum Source {
    DesktopWeb,
}

#[derive(Debug, Deserialize, Serialize, Eq, PartialEq, Clone)]
pub struct RiskifiedMetadata {
    vendor_name: String,
    shipping_lines: Vec<ShippingLines>,
}

impl TryFrom<&RiskifiedRouterData<&FrmCheckoutRouterData>> for RiskifiedPaymentsCheckoutRequest {
    type Error = Error;
    fn try_from(
        payment: &RiskifiedRouterData<&FrmCheckoutRouterData>,
    ) -> Result<Self, Self::Error> {
        let payment_data = payment.router_data.clone();
        let metadata: RiskifiedMetadata = payment_data
            .frm_metadata
            .clone()
            .ok_or(ConnectorError::MissingRequiredField {
                field_name: "frm_metadata",
            })?
            .parse_value("Riskified Metadata")
            .change_context(ConnectorError::InvalidDataFormat {
                field_name: "frm_metadata",
            })?;
        let billing_address = payment_data.get_billing()?;
        let shipping_address = payment_data.get_shipping_address_with_phone_number()?;
        let address = payment_data.get_billing_address()?;
        let line_items = payment_data
            .request
            .get_order_details()?
            .iter()
            .map(|order_detail| {
                let price = convert_amount(
                    payment.amount_converter,
                    order_detail.amount,
                    payment_data.request.currency.ok_or_else(|| {
                        ConnectorError::MissingRequiredField {
                            field_name: "currency",
                        }
                    })?,
                )?;

                Ok(LineItem {
                    price,
                    quantity: i32::from(order_detail.quantity),
                    title: order_detail.product_name.clone(),
                    product_type: order_detail.product_type.clone(),
                    requires_shipping: order_detail.requires_shipping,
                    product_id: order_detail.product_id.clone(),
                    category: order_detail.category.clone(),
                    brand: order_detail.brand.clone(),
                })
            })
            .collect::<Result<Vec<_>, Self::Error>>()?;

        Ok(Self {
            order: CheckoutRequest {
                id: payment_data.attempt_id.clone(),
                email: payment_data.request.email.clone(),
                created_at: common_utils::date_time::now(),
                updated_at: common_utils::date_time::now(),
                gateway: payment_data.request.gateway.clone(),
                total_price: payment.amount.clone(),
                cart_token: payment_data.attempt_id.clone(),
                line_items,
                source: Source::DesktopWeb,
                billing_address: OrderAddress::try_from(billing_address).ok(),
                shipping_address: OrderAddress::try_from(shipping_address).ok(),
                total_discounts: 0,
                currency: payment_data.request.currency,
                referring_site: "hyperswitch.io".to_owned(),
                discount_codes: Vec::new(),
                shipping_lines: metadata.shipping_lines,
                customer: RiskifiedCustomer {
                    email: payment_data.request.email.clone(),

                    first_name: address.get_first_name().ok().cloned(),
                    last_name: address.get_last_name().ok().cloned(),
                    created_at: common_utils::date_time::now(),
                    verified_email: false,
                    id: payment_data.get_customer_id()?,
                    account_type: CustomerAccountType::Guest,
                    orders_count: 0,
                    phone: billing_address
                        .clone()
                        .phone
                        .and_then(|phone_data| phone_data.number),
                },
                browser_ip: payment_data
                    .request
                    .browser_info
                    .as_ref()
                    .and_then(|browser_info| browser_info.ip_address),
                client_details: ClientDetails {
                    user_agent: payment_data
                        .request
                        .browser_info
                        .as_ref()
                        .and_then(|browser_info| browser_info.user_agent.clone()),
                    accept_language: payment_data.request.browser_info.as_ref().and_then(
                        |browser_info: &BrowserInformation| browser_info.language.clone(),
                    ),
                },
                note: payment_data.description.clone(),
                vendor_name: metadata.vendor_name,
                payment_details: match payment_data.request.payment_method_data.as_ref() {
                    Some(AdditionalPaymentData::Card(card_info)) => Some(PaymentDetails {
                        credit_card_bin: card_info.card_isin.clone().map(Secret::new),
                        credit_card_number: card_info
                            .last4
                            .clone()
                            .map(|last_four| format!("XXXX-XXXX-XXXX-{last_four}"))
                            .map(Secret::new),
                        credit_card_company: card_info.card_network.clone(),
                    }),
                    Some(_) | None => None,
                },
            },
        })
    }
}

#[derive(Debug, Deserialize, Serialize, Eq, PartialEq, Clone)]
pub struct RiskifiedPaymentsResponse {
    order: OrderResponse,
}

#[derive(Debug, Deserialize, Serialize, Eq, PartialEq, Clone)]
pub struct OrderResponse {
    id: String,
    status: PaymentStatus,
    description: Option<String>,
}

#[derive(Debug, Deserialize, Serialize, Eq, PartialEq, Clone)]
pub struct RiskifiedFulfilmentResponse {
    order: OrderFulfilmentResponse,
}

#[derive(Debug, Deserialize, Serialize, Eq, PartialEq, Clone)]
pub struct OrderFulfilmentResponse {
    id: String,
}

#[derive(Debug, Deserialize, Serialize, Eq, PartialEq, Clone)]
#[serde(rename_all = "lowercase")]
pub enum FulfilmentStatus {
    Fulfilled,
}

#[derive(Debug, Deserialize, Serialize, Eq, PartialEq, Clone)]
#[serde(rename_all = "lowercase")]
pub enum PaymentStatus {
    Captured,
    Created,
    Submitted,
    Approved,
    Declined,
    Processing,
}

impl<F, T> TryFrom<ResponseRouterData<F, RiskifiedPaymentsResponse, T, FraudCheckResponseData>>
    for RouterData<F, T, FraudCheckResponseData>
{
    type Error = Error;
    fn try_from(
        item: ResponseRouterData<F, RiskifiedPaymentsResponse, T, FraudCheckResponseData>,
    ) -> Result<Self, Self::Error> {
        Ok(Self {
            response: Ok(FraudCheckResponseData::TransactionResponse {
                resource_id: ResponseId::ConnectorTransactionId(item.response.order.id),
                status: FraudCheckStatus::from(item.response.order.status),
                connector_metadata: None,
                score: None,
                reason: item.response.order.description.map(serde_json::Value::from),
            }),
            ..item.data
        })
    }
}

impl From<PaymentStatus> for FraudCheckStatus {
    fn from(item: PaymentStatus) -> Self {
        match item {
            PaymentStatus::Approved => Self::Legit,
            PaymentStatus::Declined => Self::Fraud,
            _ => Self::Pending,
        }
    }
}

#[derive(Debug, Deserialize, Serialize, Eq, PartialEq, Clone)]
pub struct TransactionFailedRequest {
    checkout: FailedTransactionData,
}

#[derive(Debug, Deserialize, Serialize, Eq, PartialEq, Clone)]
pub struct FailedTransactionData {
    id: String,
    payment_details: Vec<DeclinedPaymentDetails>,
}

#[derive(Debug, Deserialize, Serialize, Eq, PartialEq, Clone)]
pub struct DeclinedPaymentDetails {
    authorization_error: AuthorizationError,
}

#[derive(Debug, Deserialize, Serialize, Eq, PartialEq, Clone)]
pub struct AuthorizationError {
    #[serde(with = "common_utils::custom_serde::iso8601")]
    created_at: PrimitiveDateTime,
    error_code: Option<String>,
    message: Option<String>,
}

impl TryFrom<&FrmTransactionRouterData> for TransactionFailedRequest {
    type Error = Error;
    fn try_from(item: &FrmTransactionRouterData) -> Result<Self, Self::Error> {
        Ok(Self {
            checkout: FailedTransactionData {
                id: item.attempt_id.clone(),
                payment_details: [DeclinedPaymentDetails {
                    authorization_error: AuthorizationError {
                        created_at: common_utils::date_time::now(),
                        error_code: item.request.error_code.clone(),
                        message: item.request.error_message.clone(),
                    },
                }]
                .to_vec(),
            },
        })
    }
}

#[derive(Debug, Deserialize, Serialize, Eq, PartialEq, Clone)]
pub struct RiskifiedFailedTransactionResponse {
    checkout: OrderResponse,
}

#[derive(Debug, Deserialize, Serialize, Eq, PartialEq, Clone)]
#[serde(untagged)]
pub enum RiskifiedTransactionResponse {
    FailedResponse(RiskifiedFailedTransactionResponse),
    SuccessResponse(RiskifiedPaymentsResponse),
}

impl<F, T>
    TryFrom<ResponseRouterData<F, RiskifiedFailedTransactionResponse, T, FraudCheckResponseData>>
    for RouterData<F, T, FraudCheckResponseData>
{
    type Error = Error;
    fn try_from(
        item: ResponseRouterData<F, RiskifiedFailedTransactionResponse, T, FraudCheckResponseData>,
    ) -> Result<Self, Self::Error> {
        Ok(Self {
            response: Ok(FraudCheckResponseData::TransactionResponse {
                resource_id: ResponseId::ConnectorTransactionId(item.response.checkout.id),
                status: FraudCheckStatus::from(item.response.checkout.status),
                connector_metadata: None,
                score: None,
                reason: item
                    .response
                    .checkout
                    .description
                    .map(serde_json::Value::from),
            }),
            ..item.data
        })
    }
}

#[derive(Debug, Deserialize, Serialize, Eq, PartialEq, Clone)]
pub struct TransactionSuccessRequest {
    order: SuccessfulTransactionData,
}

#[derive(Debug, Deserialize, Serialize, Eq, PartialEq, Clone)]
pub struct SuccessfulTransactionData {
    id: String,
    decision: TransactionDecisionData,
}

#[derive(Debug, Deserialize, Serialize, Eq, PartialEq, Clone)]
pub struct TransactionDecisionData {
    external_status: TransactionStatus,
    reason: Option<String>,
    amount: StringMajorUnit,
    currency: Currency,
    #[serde(with = "common_utils::custom_serde::iso8601")]
    decided_at: PrimitiveDateTime,
    payment_details: Vec<TransactionPaymentDetails>,
}

#[derive(Debug, Deserialize, Serialize, Eq, PartialEq, Clone)]
pub struct TransactionPaymentDetails {
    authorization_id: Option<String>,
}

#[derive(Debug, Deserialize, Serialize, Eq, PartialEq, Clone)]
#[serde(rename_all = "lowercase")]
pub enum TransactionStatus {
    Approved,
}

impl TryFrom<&RiskifiedRouterData<&FrmTransactionRouterData>> for TransactionSuccessRequest {
    type Error = Error;
    fn try_from(
        item_data: &RiskifiedRouterData<&FrmTransactionRouterData>,
    ) -> Result<Self, Self::Error> {
        let item = item_data.router_data.clone();
        Ok(Self {
            order: SuccessfulTransactionData {
                id: item.attempt_id.clone(),
                decision: TransactionDecisionData {
                    external_status: TransactionStatus::Approved,
                    reason: None,
                    amount: item_data.amount.clone(),
                    currency: item.request.get_currency()?,
                    decided_at: common_utils::date_time::now(),
                    payment_details: [TransactionPaymentDetails {
                        authorization_id: item.request.connector_transaction_id.clone(),
                    }]
                    .to_vec(),
                },
            },
        })
    }
}

#[derive(Debug, Deserialize, Serialize, Eq, PartialEq, Clone)]
pub struct RiskifiedFulfillmentRequest {
    order: OrderFulfillment,
}

#[derive(Debug, Deserialize, Serialize, Eq, PartialEq, Clone)]
#[serde(rename_all = "lowercase")]
pub enum FulfillmentRequestStatus {
    Success,
    Cancelled,
    Error,
    Failure,
}

#[derive(Debug, Deserialize, Serialize, Eq, PartialEq, Clone)]
pub struct OrderFulfillment {
    id: String,
    fulfillments: FulfilmentData,
}

#[derive(Debug, Deserialize, Serialize, Eq, PartialEq, Clone)]
pub struct FulfilmentData {
    fulfillment_id: String,
    #[serde(with = "common_utils::custom_serde::iso8601")]
    created_at: PrimitiveDateTime,
    status: Option<FulfillmentRequestStatus>,
    tracking_company: String,
    tracking_number: String,
    tracking_url: Option<String>,
}

impl TryFrom<&FrmFulfillmentRouterData> for RiskifiedFulfillmentRequest {
    type Error = Error;
    fn try_from(item: &FrmFulfillmentRouterData) -> Result<Self, Self::Error> {
        let tracking_number = item
            .request
            .fulfillment_req
            .tracking_numbers
            .as_ref()
            .and_then(|numbers| numbers.first().cloned())
            .ok_or(ConnectorError::MissingRequiredField {
                field_name: "tracking_number",
            })?;
        let tracking_url = item
            .request
            .fulfillment_req
            .tracking_urls
            .as_ref()
            .and_then(|urls| urls.first().cloned().map(|url| url.to_string()));
        Ok(Self {
            order: OrderFulfillment {
                id: item.attempt_id.clone(),
                fulfillments: FulfilmentData {
                    fulfillment_id: item.payment_id.clone(),
                    created_at: common_utils::date_time::now(),
                    status: item
                        .request
                        .fulfillment_req
                        .fulfillment_status
                        .clone()
                        .and_then(get_fulfillment_status),
                    tracking_company: item
                        .request
                        .fulfillment_req
                        .tracking_company
                        .clone()
                        .ok_or(ConnectorError::MissingRequiredField {
                            field_name: "tracking_company",
                        })?,
                    tracking_number,
                    tracking_url,
                },
            },
        })
    }
}

impl
    TryFrom<
        ResponseRouterData<
            Fulfillment,
            RiskifiedFulfilmentResponse,
            FraudCheckFulfillmentData,
            FraudCheckResponseData,
        >,
    > for RouterData<Fulfillment, FraudCheckFulfillmentData, FraudCheckResponseData>
{
    type Error = Error;
    fn try_from(
        item: ResponseRouterData<
            Fulfillment,
            RiskifiedFulfilmentResponse,
            FraudCheckFulfillmentData,
            FraudCheckResponseData,
        >,
    ) -> Result<Self, Self::Error> {
        Ok(Self {
            response: Ok(FraudCheckResponseData::FulfillmentResponse {
                order_id: item.response.order.id,
                shipment_ids: Vec::new(),
            }),
            ..item.data
        })
    }
}

#[derive(Debug, Deserialize, Serialize, Eq, PartialEq, Clone)]
pub struct ErrorResponse {
    pub error: ErrorData,
}

#[derive(Debug, Deserialize, Serialize, Eq, PartialEq, Clone)]
pub struct ErrorData {
    pub message: String,
}

impl TryFrom<&hyperswitch_domain_models::address::Address> for OrderAddress {
    type Error = Error;
    fn try_from(
        address_info: &hyperswitch_domain_models::address::Address,
    ) -> Result<Self, Self::Error> {
        let address = address_info
            .clone()
            .address
            .ok_or(ConnectorError::MissingRequiredField {
                field_name: "address",
            })?;
        Ok(Self {
            first_name: address.first_name.clone(),
            last_name: address.last_name.clone(),
            address1: address.line1.clone(),
            country_code: address.country,
            city: address.city.clone(),
            province: address.state.clone(),
            zip: address.zip.clone(),
            phone: address_info
                .phone
                .clone()
                .and_then(|phone_data| phone_data.number),
        })
    }
}

fn get_fulfillment_status(status: FulfillmentStatus) -> Option<FulfillmentRequestStatus> {
    match status {
        FulfillmentStatus::COMPLETE => Some(FulfillmentRequestStatus::Success),
        FulfillmentStatus::CANCELED => Some(FulfillmentRequestStatus::Cancelled),
        FulfillmentStatus::PARTIAL | FulfillmentStatus::REPLACEMENT => None,
    }
}

#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct RiskifiedWebhookBody {
    pub id: String,
    pub status: RiskifiedWebhookStatus,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
pub enum RiskifiedWebhookStatus {
    Approved,
    Declined,
}

impl From<RiskifiedWebhookStatus> for IncomingWebhookEvent {
    fn from(value: RiskifiedWebhookStatus) -> Self {
        match value {
            RiskifiedWebhookStatus::Declined => Self::FrmRejected,
            RiskifiedWebhookStatus::Approved => Self::FrmApproved,
        }
    }
}


// Implementation: impl api::RefundExecute for for Razorpay
// File: crates/hyperswitch_connectors/src/connectors/razorpay.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::RefundExecute for for Razorpay


// Struct: SavePaymentMethodDataResponse
// File: crates/router/src/core/payments/tokenization.rs
// Module: router
// Implementations: 0

pub struct SavePaymentMethodDataResponse


// Function: new
// File: crates/hyperswitch_domain_models/src/payment_address.rs
// Module: hyperswitch_domain_models

pub fn new(
        shipping: Option<Address>,
        billing: Option<Address>,
        payment_method_billing: Option<Address>,
        should_unify_address: Option<bool>,
    ) -> Self


// Struct: SchemaParameters
// File: crates/router_derive/src/macros/schema/helpers.rs
// Module: router_derive
// Implementations: 0

pub struct SchemaParameters


// Function: validate_auth_and_metadata_type
// File: crates/router/src/core/connector_validation.rs
// Module: router

pub fn validate_auth_and_metadata_type(
        &self,
    ) -> Result<(), error_stack::Report<errors::ApiErrorResponse>>


// Implementation: impl api::PaymentVoid for for Shift4
// File: crates/hyperswitch_connectors/src/connectors/shift4.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::PaymentVoid for for Shift4


// Struct: ChargebackRetrievalResponse
// File: crates/hyperswitch_connectors/src/connectors/worldpayvantiv/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct ChargebackRetrievalResponse


// Struct: SecretBytesMut
// File: crates/masking/src/bytes.rs
// Module: masking
// Implementations: 3
// Traits: fmt::Debug, Drop

pub struct SecretBytesMut


// Struct: BillingConnectorAdditionalCardInfo
// File: crates/diesel_models/src/types.rs
// Module: diesel_models
// Implementations: 0

pub struct BillingConnectorAdditionalCardInfo


// Struct: WorldlineRouterData
// File: crates/hyperswitch_connectors/src/connectors/worldline/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct WorldlineRouterData<T>


// Struct: Memoization
// File: crates/hyperswitch_constraint_graph/src/types.rs
// Module: hyperswitch_constraint_graph
// Implementations: 4
// Traits: Default, Deref, DerefMut

pub struct Memoization<V: ValueNode>


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

// Public submodules:
pub mod transformers;


// File: crates/router/src/types/api/verify_connector/stripe.rs
// Module: router

use error_stack::ResultExt;
use router_env::env;

use super::VerifyConnector;
use crate::{
    connector, core::errors, services, types,
    types::api::verify_connector::BoxedConnectorIntegrationInterface,
};

#[async_trait::async_trait]
impl VerifyConnector for connector::Stripe {
    async fn handle_payment_error_response<F, ResourceCommonData, Req, Resp>(
        connector: BoxedConnectorIntegrationInterface<F, ResourceCommonData, Req, Resp>,
        error_response: types::Response,
    ) -> errors::RouterResponse<()> {
        let error = connector
            .get_error_response(error_response, None)
            .change_context(errors::ApiErrorResponse::InternalServerError)?;
        match (env::which(), error.code.as_str()) {
            // In situations where an attempt is made to process a payment using a
            // Stripe production key along with a test card (which verify_connector is using),
            // Stripe will respond with a "card_declined" error. In production,
            // when this scenario occurs we will send back an "Ok" response.
            (env::Env::Production, "card_declined") => Ok(services::ApplicationResponse::StatusOk),
            _ => Err(errors::ApiErrorResponse::InvalidRequestData {
                message: error.reason.unwrap_or(error.message),
            }
            .into()),
        }
    }
}