// Struct: WellsfargoVoidRequest
// File: crates/hyperswitch_connectors/src/connectors/wellsfargo/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct WellsfargoVoidRequest


// Function: insert
// File: crates/diesel_models/src/query/tokenization.rs
// Module: diesel_models

pub fn insert(self, conn: &PgPooledConn) -> StorageResult<Self>


// Implementation: impl fmt::Display for for RecordType
// File: crates/router_env/src/logger/formatter.rs
// Module: router_env
// Methods: 1 total (0 public)

impl fmt::Display for for RecordType


// Implementation: impl ConnectorSpecifications for for Threedsecureio
// File: crates/hyperswitch_connectors/src/connectors/threedsecureio.rs
// Module: hyperswitch_connectors
// Methods: 3 total (0 public)

impl ConnectorSpecifications for for Threedsecureio


// Trait: PaymentMetric
// File: crates/analytics/src/payments/metrics.rs
// Module: analytics

pub trait PaymentMetric<T>


// Function: find_by_locker_id
// File: crates/diesel_models/src/query/payment_method.rs
// Module: diesel_models

pub fn find_by_locker_id(conn: &PgPooledConn, locker_id: &str) -> StorageResult<Self>


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

impl api::PaymentToken for for Amazonpay


// Struct: HeaderPayload
// File: crates/hyperswitch_domain_models/src/payments.rs
// Module: hyperswitch_domain_models
// Implementations: 1

pub struct HeaderPayload


// Implementation: impl ConnectorSpecifications for for Payone
// File: crates/hyperswitch_connectors/src/connectors/payone.rs
// Module: hyperswitch_connectors
// Methods: 3 total (0 public)

impl ConnectorSpecifications for for Payone


// Struct: PaymentAttemptUpdateMems
// File: crates/diesel_models/src/kv.rs
// Module: diesel_models
// Implementations: 0

pub struct PaymentAttemptUpdateMems


// Function: retrieve_default_routing_config_for_profiles
// File: crates/router/src/core/routing.rs
// Module: router

pub fn retrieve_default_routing_config_for_profiles(
    state: SessionState,
    merchant_context: domain::MerchantContext,
    transaction_type: &enums::TransactionType,
) -> RouterResponse<Vec<routing_types::ProfileDefaultRoutingConfig>>


// Struct: AuthipayPaymentsRequest
// File: crates/hyperswitch_connectors/src/connectors/authipay/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct AuthipayPaymentsRequest


// Function: find_by_merchant_id_event_id
// File: crates/diesel_models/src/query/events.rs
// Module: diesel_models

pub fn find_by_merchant_id_event_id(
        conn: &PgPooledConn,
        merchant_id: &common_utils::id_type::MerchantId,
        event_id: &str,
    ) -> StorageResult<Self>


// Struct: BluecodeCard
// File: crates/hyperswitch_connectors/src/connectors/bluecode/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct BluecodeCard


// Function: get_test_card_details
// File: crates/router/src/utils/verify_connector.rs
// Module: router

pub fn get_test_card_details(
    connector_name: Connector,
) -> errors::RouterResult<Option<domain::Card>>


// Struct: MetadataValue
// File: crates/api_models/src/routing.rs
// Module: api_models
// Implementations: 0

pub struct MetadataValue


// Struct: SingleRefundResponseData
// File: crates/hyperswitch_connectors/src/connectors/boku/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct SingleRefundResponseData


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

pub fn set_order_amount(&mut self, order_amount: MinorUnit)


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

impl Authorizedotnet


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

impl api::ConnectorAccessToken for for Klarna


// File: crates/router/src/core/utils.rs
// Module: router
// Public functions: 40

pub mod refunds_transformers;
pub mod refunds_validator;

use std::{collections::HashSet, marker::PhantomData, str::FromStr};

use api_models::enums::{Connector, DisputeStage, DisputeStatus};
#[cfg(feature = "payouts")]
use api_models::payouts::PayoutVendorAccountDetails;
use common_enums::{IntentStatus, RequestIncrementalAuthorization};
#[cfg(feature = "payouts")]
use common_utils::{crypto::Encryptable, pii::Email};
use common_utils::{
    errors::CustomResult,
    ext_traits::AsyncExt,
    types::{keymanager::KeyManagerState, ConnectorTransactionIdTrait, MinorUnit},
};
use diesel_models::refund as diesel_refund;
use error_stack::{report, ResultExt};
#[cfg(feature = "v2")]
use hyperswitch_domain_models::types::VaultRouterData;
use hyperswitch_domain_models::{
    merchant_connector_account::MerchantConnectorAccount,
    payment_address::PaymentAddress,
    router_data::ErrorResponse,
    router_data_v2::flow_common_types::VaultConnectorFlowData,
    router_request_types,
    types::{OrderDetailsWithAmount, VaultRouterDataV2},
};
use hyperswitch_interfaces::api::ConnectorSpecifications;
#[cfg(feature = "v2")]
use masking::ExposeOptionInterface;
use masking::Secret;
#[cfg(feature = "payouts")]
use masking::{ExposeInterface, PeekInterface};
use maud::{html, PreEscaped};
use regex::Regex;
use router_env::{instrument, tracing};

use super::payments::helpers;
#[cfg(feature = "payouts")]
use super::payouts::{helpers as payout_helpers, PayoutData};
#[cfg(feature = "payouts")]
use crate::core::payments;
#[cfg(feature = "v2")]
use crate::core::payments::helpers as payment_helpers;
use crate::{
    configs::Settings,
    consts,
    core::{
        errors::{self, RouterResult, StorageErrorExt},
        payments::PaymentData,
    },
    db::StorageInterface,
    routes::SessionState,
    types::{
        self, api, domain,
        storage::{self, enums},
        PollConfig,
    },
    utils::{generate_id, OptionExt, ValueExt},
};

pub const IRRELEVANT_CONNECTOR_REQUEST_REFERENCE_ID_IN_DISPUTE_FLOW: &str =
    "irrelevant_connector_request_reference_id_in_dispute_flow";
#[cfg(feature = "payouts")]
pub const IRRELEVANT_CONNECTOR_REQUEST_REFERENCE_ID_IN_PAYOUTS_FLOW: &str =
    "irrelevant_connector_request_reference_id_in_payouts_flow";
const IRRELEVANT_ATTEMPT_ID_IN_DISPUTE_FLOW: &str = "irrelevant_attempt_id_in_dispute_flow";

#[cfg(all(feature = "payouts", feature = "v2"))]
#[instrument(skip_all)]
pub async fn construct_payout_router_data<'a, F>(
    _state: &SessionState,
    _connector_data: &api::ConnectorData,
    _merchant_context: &domain::MerchantContext,
    _payout_data: &mut PayoutData,
) -> RouterResult<types::PayoutsRouterData<F>> {
    todo!()
}

#[cfg(all(feature = "payouts", feature = "v1"))]
#[instrument(skip_all)]
pub async fn construct_payout_router_data<'a, F>(
    state: &SessionState,
    connector_data: &api::ConnectorData,
    merchant_context: &domain::MerchantContext,
    payout_data: &mut PayoutData,
) -> RouterResult<types::PayoutsRouterData<F>> {
    let merchant_connector_account = payout_data
        .merchant_connector_account
        .clone()
        .get_required_value("merchant_connector_account")?;
    let connector_name = connector_data.connector_name;
    let connector_auth_type: types::ConnectorAuthType = merchant_connector_account
        .get_connector_account_details()
        .parse_value("ConnectorAuthType")
        .change_context(errors::ApiErrorResponse::InternalServerError)?;

    let billing = payout_data.billing_address.to_owned();

    let billing_address = billing.map(api_models::payments::Address::from);

    let address = PaymentAddress::new(None, billing_address.map(From::from), None, None);

    let test_mode: Option<bool> = merchant_connector_account.is_test_mode_on();
    let payouts = &payout_data.payouts;
    let payout_attempt = &payout_data.payout_attempt;
    let customer_details = &payout_data.customer_details;
    let connector_label = format!(
        "{}_{}",
        payout_data.profile_id.get_string_repr(),
        connector_name
    );
    let connector_customer_id = customer_details
        .as_ref()
        .and_then(|c| c.connector_customer.as_ref())
        .and_then(|connector_customer_value| {
            connector_customer_value
                .clone()
                .expose()
                .get(connector_label)
                .cloned()
        })
        .and_then(|id| serde_json::from_value::<String>(id).ok());

    let vendor_details: Option<PayoutVendorAccountDetails> =
        match api_models::enums::PayoutConnectors::try_from(connector_name.to_owned()).map_err(
            |err| report!(errors::ApiErrorResponse::InternalServerError).attach_printable(err),
        )? {
            api_models::enums::PayoutConnectors::Stripe => {
                payout_data.payouts.metadata.to_owned().and_then(|meta| {
                    let val = meta
                        .peek()
                        .to_owned()
                        .parse_value("PayoutVendorAccountDetails")
                        .ok();
                    val
                })
            }
            _ => None,
        };

    let webhook_url = helpers::create_webhook_url(
        &state.base_url,
        &merchant_context.get_merchant_account().get_id().to_owned(),
        merchant_connector_account
            .get_mca_id()
            .get_required_value("merchant_connector_id")?
            .get_string_repr(),
    );

    let connector_transfer_method_id =
        payout_helpers::should_create_connector_transfer_method(&*payout_data, connector_data)?;

    let router_data = types::RouterData {
        flow: PhantomData,
        merchant_id: merchant_context.get_merchant_account().get_id().to_owned(),
        customer_id: customer_details.to_owned().map(|c| c.customer_id),
        tenant_id: state.tenant.tenant_id.clone(),
        connector_customer: connector_customer_id,
        connector: connector_name.to_string(),
        payment_id: common_utils::id_type::PaymentId::get_irrelevant_id("payout")
            .get_string_repr()
            .to_owned(),
        attempt_id: "".to_string(),
        status: enums::AttemptStatus::Failure,
        payment_method: enums::PaymentMethod::default(),
        connector_auth_type,
        description: None,
        address,
        auth_type: enums::AuthenticationType::default(),
        connector_meta_data: merchant_connector_account.get_metadata(),
        connector_wallets_details: merchant_connector_account.get_connector_wallets_details(),
        amount_captured: None,
        minor_amount_captured: None,
        payment_method_status: None,
        request: types::PayoutsData {
            payout_id: payouts.payout_id.clone(),
            amount: payouts.amount.get_amount_as_i64(),
            minor_amount: payouts.amount,
            connector_payout_id: payout_attempt.connector_payout_id.clone(),
            destination_currency: payouts.destination_currency,
            source_currency: payouts.source_currency,
            entity_type: payouts.entity_type.to_owned(),
            payout_type: payouts.payout_type,
            vendor_details,
            priority: payouts.priority,
            customer_details: customer_details
                .to_owned()
                .map(|c| payments::CustomerDetails {
                    customer_id: Some(c.customer_id),
                    name: c.name.map(Encryptable::into_inner),
                    email: c.email.map(Email::from),
                    phone: c.phone.map(Encryptable::into_inner),
                    phone_country_code: c.phone_country_code,
                    tax_registration_id: c.tax_registration_id.map(Encryptable::into_inner),
                }),
            connector_transfer_method_id,
            webhook_url: Some(webhook_url),
        },
        response: Ok(types::PayoutsResponseData::default()),
        access_token: None,
        session_token: None,
        reference_id: None,
        payment_method_token: None,
        recurring_mandate_payment_data: None,
        preprocessing_id: None,
        connector_request_reference_id: payout_attempt.payout_attempt_id.clone(),
        payout_method_data: payout_data.payout_method_data.to_owned(),
        quote_id: None,
        test_mode,
        payment_method_balance: None,
        connector_api_version: None,
        connector_http_status_code: None,
        external_latency: None,
        apple_pay_flow: None,
        frm_metadata: None,
        refund_id: None,
        dispute_id: None,
        connector_response: None,
        integrity_check: Ok(()),
        additional_merchant_data: None,
        header_payload: None,
        connector_mandate_request_reference_id: None,
        authentication_id: None,
        psd2_sca_exemption_type: None,
        raw_connector_response: None,
        is_payment_id_from_merchant: None,
        l2_l3_data: None,
        minor_amount_capturable: None,
    };

    Ok(router_data)
}

#[cfg(feature = "v2")]
#[instrument(skip_all)]
#[allow(clippy::too_many_arguments)]
pub async fn construct_refund_router_data<'a, F>(
    state: &'a SessionState,
    connector_enum: Connector,
    merchant_context: &domain::MerchantContext,
    payment_intent: &'a storage::PaymentIntent,
    payment_attempt: &storage::PaymentAttempt,
    refund: &'a diesel_refund::Refund,
    merchant_connector_account: &domain::MerchantConnectorAccountTypeDetails,
) -> RouterResult<types::RefundsRouterData<F>> {
    let auth_type = merchant_connector_account
        .get_connector_account_details()
        .change_context(errors::ApiErrorResponse::InternalServerError)?;

    let status = payment_attempt.status;

    let payment_amount = payment_attempt.get_total_amount();
    let currency = payment_intent.get_currency();

    let payment_method_type = payment_attempt.payment_method_type;

    let webhook_url = match merchant_connector_account {
        domain::MerchantConnectorAccountTypeDetails::MerchantConnectorAccount(
            merchant_connector_account,
        ) => Some(helpers::create_webhook_url(
            &state.base_url.clone(),
            merchant_context.get_merchant_account().get_id(),
            merchant_connector_account.get_id().get_string_repr(),
        )),
        // TODO: Implement for connectors that require a webhook URL to be included in the request payload.
        domain::MerchantConnectorAccountTypeDetails::MerchantConnectorDetails(_) => None,
    };

    let supported_connector = &state
        .conf
        .multiple_api_version_supported_connectors
        .supported_connectors;

    let connector_api_version = if supported_connector.contains(&connector_enum) {
        state
            .store
            .find_config_by_key(&format!("connector_api_version_{connector_enum}"))
            .await
            .map(|value| value.config)
            .ok()
    } else {
        None
    };

    let browser_info = payment_attempt
        .browser_info
        .clone()
        .map(types::BrowserInformation::from);

    let connector_refund_id = refund.get_optional_connector_refund_id().cloned();
    let capture_method = payment_intent.capture_method;

    let customer_id = payment_intent
        .get_optional_customer_id()
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("Failed to get optional customer id")?;

    let braintree_metadata = payment_intent
        .get_optional_connector_metadata()
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("Failed parsing ConnectorMetadata")?
        .and_then(|cm| cm.braintree);

    let merchant_account_id = braintree_metadata
        .as_ref()
        .and_then(|braintree| braintree.merchant_account_id.clone());

    let merchant_config_currency =
        braintree_metadata.and_then(|braintree| braintree.merchant_config_currency);

    let connector_wallets_details = match merchant_connector_account {
        domain::MerchantConnectorAccountTypeDetails::MerchantConnectorAccount(
            merchant_connector_account,
        ) => merchant_connector_account.get_connector_wallets_details(),
        domain::MerchantConnectorAccountTypeDetails::MerchantConnectorDetails(_) => None,
    };

    let router_data = types::RouterData {
        flow: PhantomData,
        merchant_id: merchant_context.get_merchant_account().get_id().clone(),
        customer_id,
        tenant_id: state.tenant.tenant_id.clone(),
        connector: connector_enum.to_string(),
        payment_id: payment_attempt.payment_id.get_string_repr().to_owned(),
        attempt_id: payment_attempt.id.get_string_repr().to_string().clone(),
        status,
        payment_method: payment_method_type,
        connector_auth_type: auth_type,
        description: None,
        // Does refund need shipping/billing address ?
        address: PaymentAddress::default(),
        auth_type: payment_attempt.authentication_type,
        connector_meta_data: merchant_connector_account.get_metadata(),
        connector_wallets_details,
        amount_captured: payment_intent
            .amount_captured
            .map(|amt| amt.get_amount_as_i64()),
        payment_method_status: None,
        minor_amount_captured: payment_intent.amount_captured,
        request: types::RefundsData {
            refund_id: refund.id.get_string_repr().to_string(),
            connector_transaction_id: refund.get_connector_transaction_id().clone(),
            refund_amount: refund.refund_amount.get_amount_as_i64(),
            minor_refund_amount: refund.refund_amount,
            currency,
            payment_amount: payment_amount.get_amount_as_i64(),
            minor_payment_amount: payment_amount,
            webhook_url,
            connector_metadata: payment_attempt.connector_metadata.clone().expose_option(),
            reason: refund.refund_reason.clone(),
            connector_refund_id: connector_refund_id.clone(),
            browser_info,
            split_refunds: None,
            integrity_object: None,
            refund_status: refund.refund_status,
            merchant_account_id,
            merchant_config_currency,
            refund_connector_metadata: refund.metadata.clone(),
            capture_method: Some(capture_method),
            additional_payment_method_data: None,
        },

        response: Ok(types::RefundsResponseData {
            connector_refund_id: connector_refund_id.unwrap_or_default(),
            refund_status: refund.refund_status,
        }),
        access_token: None,
        session_token: None,
        reference_id: None,
        payment_method_token: None,
        connector_customer: None,
        recurring_mandate_payment_data: None,
        preprocessing_id: None,
        connector_request_reference_id: refund
            .merchant_reference_id
            .get_string_repr()
            .to_string()
            .clone(),
        #[cfg(feature = "payouts")]
        payout_method_data: None,
        #[cfg(feature = "payouts")]
        quote_id: None,
        test_mode: None,
        payment_method_balance: None,
        connector_api_version,
        connector_http_status_code: None,
        external_latency: None,
        apple_pay_flow: None,
        frm_metadata: None,
        refund_id: Some(refund.id.get_string_repr().to_string().clone()),
        dispute_id: None,
        connector_response: None,
        integrity_check: Ok(()),
        additional_merchant_data: None,
        header_payload: None,
        connector_mandate_request_reference_id: None,
        authentication_id: None,
        psd2_sca_exemption_type: None,
        raw_connector_response: None,
        is_payment_id_from_merchant: None,
        l2_l3_data: None,
        minor_amount_capturable: None,
    };

    Ok(router_data)
}

#[cfg(feature = "v1")]
#[instrument(skip_all)]
#[allow(clippy::too_many_arguments)]
pub async fn construct_refund_router_data<'a, F>(
    state: &'a SessionState,
    connector_id: &str,
    merchant_context: &domain::MerchantContext,
    money: (MinorUnit, enums::Currency),
    payment_intent: &'a storage::PaymentIntent,
    payment_attempt: &storage::PaymentAttempt,
    refund: &'a diesel_refund::Refund,
    creds_identifier: Option<String>,
    split_refunds: Option<router_request_types::SplitRefundsRequest>,
) -> RouterResult<types::RefundsRouterData<F>> {
    let profile_id = payment_intent
        .profile_id
        .as_ref()
        .get_required_value("profile_id")
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("profile_id is not set in payment_intent")?;

    let merchant_connector_account = helpers::get_merchant_connector_account(
        state,
        merchant_context.get_merchant_account().get_id(),
        creds_identifier.as_deref(),
        merchant_context.get_merchant_key_store(),
        profile_id,
        connector_id,
        payment_attempt.merchant_connector_id.as_ref(),
    )
    .await?;

    let auth_type: types::ConnectorAuthType = merchant_connector_account
        .get_connector_account_details()
        .parse_value("ConnectorAuthType")
        .change_context(errors::ApiErrorResponse::InternalServerError)?;

    let status = payment_attempt.status;

    let (payment_amount, currency) = money;

    let payment_method_type = payment_attempt
        .payment_method
        .get_required_value("payment_method_type")
        .change_context(errors::ApiErrorResponse::InternalServerError)?;
    let merchant_connector_account_id_or_connector_name = payment_attempt
        .merchant_connector_id
        .as_ref()
        .map(|mca_id| mca_id.get_string_repr())
        .unwrap_or(connector_id);

    let webhook_url = Some(helpers::create_webhook_url(
        &state.base_url.clone(),
        merchant_context.get_merchant_account().get_id(),
        merchant_connector_account_id_or_connector_name,
    ));
    let test_mode: Option<bool> = merchant_connector_account.is_test_mode_on();

    let supported_connector = &state
        .conf
        .multiple_api_version_supported_connectors
        .supported_connectors;
    let connector_enum = Connector::from_str(connector_id)
        .change_context(errors::ConnectorError::InvalidConnectorName)
        .change_context(errors::ApiErrorResponse::InvalidDataValue {
            field_name: "connector",
        })
        .attach_printable_lazy(|| format!("unable to parse connector name {connector_id:?}"))?;

    let connector_api_version = if supported_connector.contains(&connector_enum) {
        state
            .store
            .find_config_by_key(&format!("connector_api_version_{connector_id}"))
            .await
            .map(|value| value.config)
            .ok()
    } else {
        None
    };

    let browser_info: Option<types::BrowserInformation> = payment_attempt
        .browser_info
        .clone()
        .map(|b| b.parse_value("BrowserInformation"))
        .transpose()
        .change_context(errors::ApiErrorResponse::InvalidDataValue {
            field_name: "browser_info",
        })?;

    let connector_refund_id = refund.get_optional_connector_refund_id().cloned();
    let capture_method = payment_attempt.capture_method;

    let braintree_metadata = payment_intent
        .connector_metadata
        .clone()
        .map(|cm| {
            cm.parse_value::<api_models::payments::ConnectorMetadata>("ConnectorMetadata")
                .change_context(errors::ApiErrorResponse::InternalServerError)
                .attach_printable("Failed parsing ConnectorMetadata")
        })
        .transpose()?
        .and_then(|cm| cm.braintree);

    let merchant_account_id = braintree_metadata
        .as_ref()
        .and_then(|braintree| braintree.merchant_account_id.clone());
    let merchant_config_currency =
        braintree_metadata.and_then(|braintree| braintree.merchant_config_currency);
    let additional_payment_method_data: Option<api_models::payments::AdditionalPaymentData> =
        payment_attempt
            .payment_method_data
            .clone()
            .and_then(|value| match serde_json::from_value(value) {
                Ok(data) => Some(data),
                Err(e) => {
                    router_env::logger::error!("Failed to deserialize payment_method_data: {}", e);
                    None
                }
            });

    let router_data = types::RouterData {
        flow: PhantomData,
        merchant_id: merchant_context.get_merchant_account().get_id().clone(),
        customer_id: payment_intent.customer_id.to_owned(),
        tenant_id: state.tenant.tenant_id.clone(),
        connector: connector_id.to_string(),
        payment_id: payment_attempt.payment_id.get_string_repr().to_owned(),
        attempt_id: payment_attempt.attempt_id.clone(),
        status,
        payment_method: payment_method_type,
        connector_auth_type: auth_type,
        description: None,
        // Does refund need shipping/billing address ?
        address: PaymentAddress::default(),
        auth_type: payment_attempt.authentication_type.unwrap_or_default(),
        connector_meta_data: merchant_connector_account.get_metadata(),
        connector_wallets_details: merchant_connector_account.get_connector_wallets_details(),
        amount_captured: payment_intent
            .amount_captured
            .map(|amt| amt.get_amount_as_i64()),
        payment_method_status: None,
        minor_amount_captured: payment_intent.amount_captured,
        request: types::RefundsData {
            refund_id: refund.refund_id.clone(),
            connector_transaction_id: refund.get_connector_transaction_id().clone(),
            refund_amount: refund.refund_amount.get_amount_as_i64(),
            minor_refund_amount: refund.refund_amount,
            currency,
            payment_amount: payment_amount.get_amount_as_i64(),
            minor_payment_amount: payment_amount,
            webhook_url,
            connector_metadata: payment_attempt.connector_metadata.clone(),
            refund_connector_metadata: refund.metadata.clone(),
            reason: refund.refund_reason.clone(),
            connector_refund_id: connector_refund_id.clone(),
            browser_info,
            split_refunds,
            integrity_object: None,
            refund_status: refund.refund_status,
            merchant_account_id,
            merchant_config_currency,
            capture_method,
            additional_payment_method_data,
        },

        response: Ok(types::RefundsResponseData {
            connector_refund_id: connector_refund_id.unwrap_or_default(),
            refund_status: refund.refund_status,
        }),
        access_token: None,
        session_token: None,
        reference_id: None,
        payment_method_token: None,
        connector_customer: None,
        recurring_mandate_payment_data: None,
        preprocessing_id: None,
        connector_request_reference_id: refund.refund_id.clone(),
        #[cfg(feature = "payouts")]
        payout_method_data: None,
        #[cfg(feature = "payouts")]
        quote_id: None,
        test_mode,
        payment_method_balance: None,
        connector_api_version,
        connector_http_status_code: None,
        external_latency: None,
        apple_pay_flow: None,
        frm_metadata: None,
        refund_id: Some(refund.refund_id.clone()),
        dispute_id: None,
        connector_response: None,
        integrity_check: Ok(()),
        additional_merchant_data: None,
        header_payload: None,
        connector_mandate_request_reference_id: None,
        authentication_id: None,
        psd2_sca_exemption_type: None,
        raw_connector_response: None,
        is_payment_id_from_merchant: None,
        l2_l3_data: None,
        minor_amount_capturable: None,
    };

    Ok(router_data)
}

pub fn get_or_generate_id(
    key: &str,
    provided_id: &Option<String>,
    prefix: &str,
) -> Result<String, errors::ApiErrorResponse> {
    let validate_id = |id| validate_id(id, key);
    provided_id
        .clone()
        .map_or(Ok(generate_id(consts::ID_LENGTH, prefix)), validate_id)
}

fn invalid_id_format_error(key: &str) -> errors::ApiErrorResponse {
    errors::ApiErrorResponse::InvalidDataFormat {
        field_name: key.to_string(),
        expected_format: format!(
            "length should be less than {} characters",
            consts::MAX_ID_LENGTH
        ),
    }
}

pub fn validate_id(id: String, key: &str) -> Result<String, errors::ApiErrorResponse> {
    if id.len() > consts::MAX_ID_LENGTH {
        Err(invalid_id_format_error(key))
    } else {
        Ok(id)
    }
}

#[cfg(feature = "v1")]
pub fn get_split_refunds(
    split_refund_input: refunds_transformers::SplitRefundInput,
) -> RouterResult<Option<router_request_types::SplitRefundsRequest>> {
    match split_refund_input.split_payment_request.as_ref() {
        Some(common_types::payments::SplitPaymentsRequest::StripeSplitPayment(stripe_payment)) => {
            let (charge_id_option, charge_type_option) = match (
                &split_refund_input.payment_charges,
                &split_refund_input.split_payment_request,
            ) {
                (
                    Some(common_types::payments::ConnectorChargeResponseData::StripeSplitPayment(
                        stripe_split_payment_response,
                    )),
                    _,
                ) => (
                    stripe_split_payment_response.charge_id.clone(),
                    Some(stripe_split_payment_response.charge_type.clone()),
                ),
                (
                    _,
                    Some(common_types::payments::SplitPaymentsRequest::StripeSplitPayment(
                        stripe_split_payment_request,
                    )),
                ) => (
                    split_refund_input.charge_id,
                    Some(stripe_split_payment_request.charge_type.clone()),
                ),
                (_, _) => (None, None),
            };

            if let Some(charge_id) = charge_id_option {
                let options = refunds_validator::validate_stripe_charge_refund(
                    charge_type_option,
                    &split_refund_input.refund_request,
                )?;

                Ok(Some(
                    router_request_types::SplitRefundsRequest::StripeSplitRefund(
                        router_request_types::StripeSplitRefund {
                            charge_id,
                            charge_type: stripe_payment.charge_type.clone(),
                            transfer_account_id: stripe_payment.transfer_account_id.clone(),
                            options,
                        },
                    ),
                ))
            } else {
                Ok(None)
            }
        }
        Some(common_types::payments::SplitPaymentsRequest::AdyenSplitPayment(_)) => {
            match &split_refund_input.payment_charges {
                Some(common_types::payments::ConnectorChargeResponseData::AdyenSplitPayment(
                    adyen_split_payment_response,
                )) => {
                    if let Some(common_types::refunds::SplitRefund::AdyenSplitRefund(
                        split_refund_request,
                    )) = split_refund_input.refund_request.clone()
                    {
                        refunds_validator::validate_adyen_charge_refund(
                            adyen_split_payment_response,
                            &split_refund_request,
                        )?;

                        Ok(Some(
                            router_request_types::SplitRefundsRequest::AdyenSplitRefund(
                                split_refund_request,
                            ),
                        ))
                    } else {
                        Ok(None)
                    }
                }
                _ => Ok(None),
            }
        }
        Some(common_types::payments::SplitPaymentsRequest::XenditSplitPayment(_)) => {
            match (
                &split_refund_input.payment_charges,
                &split_refund_input.refund_request,
            ) {
                (
                    Some(common_types::payments::ConnectorChargeResponseData::XenditSplitPayment(
                        xendit_split_payment_response,
                    )),
                    Some(common_types::refunds::SplitRefund::XenditSplitRefund(
                        split_refund_request,
                    )),
                ) => {
                    let user_id = refunds_validator::validate_xendit_charge_refund(
                        xendit_split_payment_response,
                        split_refund_request,
                    )?;

                    Ok(user_id.map(|for_user_id| {
                        router_request_types::SplitRefundsRequest::XenditSplitRefund(
                            common_types::domain::XenditSplitSubMerchantData { for_user_id },
                        )
                    }))
                }
                (
                    Some(common_types::payments::ConnectorChargeResponseData::XenditSplitPayment(
                        xendit_split_payment_response,
                    )),
                    None,
                ) => {
                    let option_for_user_id = match xendit_split_payment_response {
                        common_types::payments::XenditChargeResponseData::MultipleSplits(
                            common_types::payments::XenditMultipleSplitResponse {
                                for_user_id, ..
                            },
                        ) => for_user_id.clone(),
                        common_types::payments::XenditChargeResponseData::SingleSplit(
                            common_types::domain::XenditSplitSubMerchantData { for_user_id },
                        ) => Some(for_user_id.clone()),
                    };

                    if option_for_user_id.is_some() {
                        Err(errors::ApiErrorResponse::MissingRequiredField {
                            field_name: "split_refunds.xendit_split_refund.for_user_id",
                        })?
                    } else {
                        Ok(None)
                    }
                }
                _ => Ok(None),
            }
        }
        _ => Ok(None),
    }
}
#[cfg(test)]
mod tests {
    #![allow(clippy::expect_used)]
    use super::*;

    #[test]
    fn validate_id_length_constraint() {
        let payment_id =
            "abcdefghijlkmnopqrstuvwzyzabcdefghijknlmnopsjkdnfjsknfkjsdnfspoig".to_string(); //length = 65

        let result = validate_id(payment_id, "payment_id");
        assert!(result.is_err());
    }

    #[test]
    fn validate_id_proper_response() {
        let payment_id = "abcdefghijlkmnopqrstjhbjhjhkhbhgcxdfxvmhb".to_string();

        let result = validate_id(payment_id.clone(), "payment_id");
        assert!(result.is_ok());
        let result = result.unwrap_or_default();
        assert_eq!(result, payment_id);
    }

    #[test]
    fn test_generate_id() {
        let generated_id = generate_id(consts::ID_LENGTH, "ref");
        assert_eq!(generated_id.len(), consts::ID_LENGTH + 4)
    }

    #[test]
    fn test_filter_objects_based_on_profile_id_list() {
        #[derive(PartialEq, Debug, Clone)]
        struct Object {
            profile_id: Option<common_utils::id_type::ProfileId>,
        }

        impl Object {
            pub fn new(profile_id: &'static str) -> Self {
                Self {
                    profile_id: Some(
                        common_utils::id_type::ProfileId::try_from(std::borrow::Cow::from(
                            profile_id,
                        ))
                        .expect("invalid profile ID"),
                    ),
                }
            }
        }

        impl GetProfileId for Object {
            fn get_profile_id(&self) -> Option<&common_utils::id_type::ProfileId> {
                self.profile_id.as_ref()
            }
        }

        fn new_profile_id(profile_id: &'static str) -> common_utils::id_type::ProfileId {
            common_utils::id_type::ProfileId::try_from(std::borrow::Cow::from(profile_id))
                .expect("invalid profile ID")
        }

        // non empty object_list and profile_id_list
        let object_list = vec![
            Object::new("p1"),
            Object::new("p2"),
            Object::new("p2"),
            Object::new("p4"),
            Object::new("p5"),
        ];
        let profile_id_list = vec![
            new_profile_id("p1"),
            new_profile_id("p2"),
            new_profile_id("p3"),
        ];
        let filtered_list =
            filter_objects_based_on_profile_id_list(Some(profile_id_list), object_list.clone());
        let expected_result = vec![Object::new("p1"), Object::new("p2"), Object::new("p2")];
        assert_eq!(filtered_list, expected_result);

        // non empty object_list and empty profile_id_list
        let empty_profile_id_list = vec![];
        let filtered_list = filter_objects_based_on_profile_id_list(
            Some(empty_profile_id_list),
            object_list.clone(),
        );
        let expected_result = vec![];
        assert_eq!(filtered_list, expected_result);

        // non empty object_list and None profile_id_list
        let profile_id_list_as_none = None;
        let filtered_list =
            filter_objects_based_on_profile_id_list(profile_id_list_as_none, object_list);
        let expected_result = vec![
            Object::new("p1"),
            Object::new("p2"),
            Object::new("p2"),
            Object::new("p4"),
            Object::new("p5"),
        ];
        assert_eq!(filtered_list, expected_result);
    }
}

// Dispute Stage can move linearly from PreDispute -> Dispute -> PreArbitration -> Arbitration -> DisputeReversal
pub fn validate_dispute_stage(
    prev_dispute_stage: DisputeStage,
    dispute_stage: DisputeStage,
) -> bool {
    match prev_dispute_stage {
        DisputeStage::PreDispute => true,
        DisputeStage::Dispute => !matches!(dispute_stage, DisputeStage::PreDispute),
        DisputeStage::PreArbitration => matches!(
            dispute_stage,
            DisputeStage::PreArbitration
                | DisputeStage::Arbitration
                | DisputeStage::DisputeReversal
        ),
        DisputeStage::Arbitration => matches!(
            dispute_stage,
            DisputeStage::Arbitration | DisputeStage::DisputeReversal
        ),
        DisputeStage::DisputeReversal => matches!(dispute_stage, DisputeStage::DisputeReversal),
    }
}

//Dispute status can go from Opened -> (Expired | Accepted | Cancelled | Challenged -> (Won | Lost))
pub fn validate_dispute_status(
    prev_dispute_status: DisputeStatus,
    dispute_status: DisputeStatus,
) -> bool {
    match prev_dispute_status {
        DisputeStatus::DisputeOpened => true,
        DisputeStatus::DisputeExpired => {
            matches!(dispute_status, DisputeStatus::DisputeExpired)
        }
        DisputeStatus::DisputeAccepted => {
            matches!(dispute_status, DisputeStatus::DisputeAccepted)
        }
        DisputeStatus::DisputeCancelled => {
            matches!(dispute_status, DisputeStatus::DisputeCancelled)
        }
        DisputeStatus::DisputeChallenged => matches!(
            dispute_status,
            DisputeStatus::DisputeChallenged
                | DisputeStatus::DisputeWon
                | DisputeStatus::DisputeLost
                | DisputeStatus::DisputeAccepted
                | DisputeStatus::DisputeCancelled
                | DisputeStatus::DisputeExpired
        ),
        DisputeStatus::DisputeWon => matches!(dispute_status, DisputeStatus::DisputeWon),
        DisputeStatus::DisputeLost => matches!(dispute_status, DisputeStatus::DisputeLost),
    }
}

pub fn validate_dispute_stage_and_dispute_status(
    prev_dispute_stage: DisputeStage,
    prev_dispute_status: DisputeStatus,
    dispute_stage: DisputeStage,
    dispute_status: DisputeStatus,
) -> CustomResult<(), errors::WebhooksFlowError> {
    let dispute_stage_validation = validate_dispute_stage(prev_dispute_stage, dispute_stage);
    let dispute_status_validation = if dispute_stage == prev_dispute_stage {
        validate_dispute_status(prev_dispute_status, dispute_status)
    } else {
        true
    };
    common_utils::fp_utils::when(
        !(dispute_stage_validation && dispute_status_validation),
        || {
            super::metrics::INCOMING_DISPUTE_WEBHOOK_VALIDATION_FAILURE_METRIC.add(1, &[]);
            Err(errors::WebhooksFlowError::DisputeWebhookValidationFailed)?
        },
    )
}

#[cfg(feature = "v1")]
#[instrument(skip_all)]
pub async fn construct_accept_dispute_router_data<'a>(
    state: &'a SessionState,
    payment_intent: &'a storage::PaymentIntent,
    payment_attempt: &storage::PaymentAttempt,
    merchant_context: &domain::MerchantContext,
    dispute: &storage::Dispute,
) -> RouterResult<types::AcceptDisputeRouterData> {
    let profile_id = payment_intent
        .profile_id
        .as_ref()
        .get_required_value("profile_id")
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("profile_id is not set in payment_intent")?
        .clone();

    let merchant_connector_account = helpers::get_merchant_connector_account(
        state,
        merchant_context.get_merchant_account().get_id(),
        None,
        merchant_context.get_merchant_key_store(),
        &profile_id,
        &dispute.connector,
        payment_attempt.merchant_connector_id.as_ref(),
    )
    .await?;

    let test_mode: Option<bool> = merchant_connector_account.is_test_mode_on();
    let auth_type: types::ConnectorAuthType = merchant_connector_account
        .get_connector_account_details()
        .parse_value("ConnectorAuthType")
        .change_context(errors::ApiErrorResponse::InternalServerError)?;
    let payment_method = payment_attempt
        .payment_method
        .get_required_value("payment_method_type")?;
    let router_data = types::RouterData {
        flow: PhantomData,
        merchant_id: merchant_context.get_merchant_account().get_id().clone(),
        connector: dispute.connector.to_string(),
        tenant_id: state.tenant.tenant_id.clone(),
        payment_id: payment_attempt.payment_id.get_string_repr().to_owned(),
        attempt_id: payment_attempt.attempt_id.clone(),
        status: payment_attempt.status,
        payment_method,
        connector_auth_type: auth_type,
        description: None,
        address: PaymentAddress::default(),
        auth_type: payment_attempt.authentication_type.unwrap_or_default(),
        connector_meta_data: merchant_connector_account.get_metadata(),
        connector_wallets_details: merchant_connector_account.get_connector_wallets_details(),
        amount_captured: payment_intent
            .amount_captured
            .map(|amt| amt.get_amount_as_i64()),
        minor_amount_captured: payment_intent.amount_captured,
        payment_method_status: None,
        request: types::AcceptDisputeRequestData {
            dispute_id: dispute.dispute_id.clone(),
            connector_dispute_id: dispute.connector_dispute_id.clone(),
            dispute_status: dispute.dispute_status,
        },
        response: Err(ErrorResponse::default()),
        access_token: None,
        session_token: None,
        reference_id: None,
        payment_method_token: None,
        connector_customer: None,
        customer_id: None,
        recurring_mandate_payment_data: None,


// File: crates/euclid/src/dssa/utils.rs
// Module: euclid
// Public structs: 1

pub struct Unpacker;


// Function: extract_payment_link_config
// File: crates/router/src/core/payment_link.rs
// Module: router

pub fn extract_payment_link_config(
    pl_config: serde_json::Value,
) -> Result<PaymentLinkConfig, error_stack::Report<errors::ApiErrorResponse>>


// Struct: JpmorganCard
// File: crates/hyperswitch_connectors/src/connectors/jpmorgan/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct JpmorganCard


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

impl api::PaymentCapture for for Tsys


// Implementation: impl EncryptionManagementConfig
// File: crates/external_services/src/managers/encryption_management.rs
// Module: external_services
// Methods: 2 total (1 public)

impl EncryptionManagementConfig


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

pub struct AuthorizedotnetWebhookEventType


// File: crates/router/tests/connectors/noon.rs
// Module: router

use std::str::FromStr;

use masking::Secret;
use router::types::{self, storage::enums};

use crate::{
    connector_auth,
    utils::{self, ConnectorActions},
};

#[derive(Clone, Copy)]
struct NoonTest;
impl ConnectorActions for NoonTest {}
impl utils::Connector for NoonTest {
    fn get_data(&self) -> types::api::ConnectorData {
        use router::connector::Noon;
        utils::construct_connector_data_old(
            Box::new(Noon::new()),
            types::Connector::Noon,
            types::api::GetToken::Connector,
            None,
        )
    }

    fn get_auth_token(&self) -> types::ConnectorAuthType {
        utils::to_connector_auth_type(
            connector_auth::ConnectorAuthentication::new()
                .noon
                .expect("Missing connector authentication configuration")
                .into(),
        )
    }

    fn get_name(&self) -> String {
        "noon".to_string()
    }
}

static CONNECTOR: NoonTest = NoonTest {};

fn get_default_payment_info() -> Option<utils::PaymentInfo> {
    None
}

fn payment_method_details() -> Option<types::PaymentsAuthorizeData> {
    Some(types::PaymentsAuthorizeData {
        currency: enums::Currency::AED,
        ..utils::PaymentAuthorizeType::default().0
    })
}

// Cards Positive Tests
// Creates a payment using the manual capture flow (Non 3DS).
#[actix_web::test]
async fn should_only_authorize_payment() {
    let response = CONNECTOR
        .authorize_payment(payment_method_details(), get_default_payment_info())
        .await
        .expect("Authorize payment response");
    assert_eq!(response.status, enums::AttemptStatus::Authorized);
}

// Captures a payment using the manual capture flow (Non 3DS).
#[actix_web::test]
async fn should_capture_authorized_payment() {
    let response = CONNECTOR
        .authorize_and_capture_payment(payment_method_details(), None, get_default_payment_info())
        .await
        .expect("Capture payment response");
    assert_eq!(response.status, enums::AttemptStatus::Charged);
}

// Partially captures a payment using the manual capture flow (Non 3DS).
#[actix_web::test]
async fn should_partially_capture_authorized_payment() {
    let response = CONNECTOR
        .authorize_and_capture_payment(
            payment_method_details(),
            Some(types::PaymentsCaptureData {
                amount_to_capture: 50,
                ..utils::PaymentCaptureType::default().0
            }),
            get_default_payment_info(),
        )
        .await
        .expect("Capture payment response");
    assert_eq!(response.status, enums::AttemptStatus::Charged);
}

// Synchronizes a payment using the manual capture flow (Non 3DS).
#[actix_web::test]
async fn should_sync_authorized_payment() {
    let authorize_response = CONNECTOR
        .authorize_payment(payment_method_details(), get_default_payment_info())
        .await
        .expect("Authorize payment response");
    let txn_id = utils::get_connector_transaction_id(authorize_response.response);
    let response = CONNECTOR
        .psync_retry_till_status_matches(
            enums::AttemptStatus::Authorized,
            Some(types::PaymentsSyncData {
                connector_transaction_id: types::ResponseId::ConnectorTransactionId(
                    txn_id.unwrap(),
                ),
                ..Default::default()
            }),
            get_default_payment_info(),
        )
        .await
        .expect("PSync response");
    assert_eq!(response.status, enums::AttemptStatus::Authorized,);
}

// Voids a payment using the manual capture flow (Non 3DS).
#[actix_web::test]
async fn should_void_authorized_payment() {
    let response = CONNECTOR
        .authorize_and_void_payment(
            payment_method_details(),
            Some(types::PaymentsCancelData {
                connector_transaction_id: String::from(""),
                cancellation_reason: Some("requested_by_customer".to_string()),
                ..Default::default()
            }),
            get_default_payment_info(),
        )
        .await
        .expect("Void payment response");
    assert_eq!(response.status, enums::AttemptStatus::Voided);
}

// Refunds a payment using the manual capture flow (Non 3DS).
#[actix_web::test]
async fn should_refund_manually_captured_payment() {
    let response = CONNECTOR
        .capture_payment_and_refund(
            payment_method_details(),
            None,
            None,
            get_default_payment_info(),
        )
        .await
        .unwrap();
    assert_eq!(
        response.response.unwrap().refund_status,
        enums::RefundStatus::Success,
    );
}

// Partially refunds a payment using the manual capture flow (Non 3DS).
#[actix_web::test]
async fn should_partially_refund_manually_captured_payment() {
    let response = CONNECTOR
        .capture_payment_and_refund(
            payment_method_details(),
            None,
            Some(types::RefundsData {
                refund_amount: 50,
                ..utils::PaymentRefundType::default().0
            }),
            get_default_payment_info(),
        )
        .await
        .unwrap();
    assert_eq!(
        response.response.unwrap().refund_status,
        enums::RefundStatus::Success,
    );
}

// Synchronizes a refund using the manual capture flow (Non 3DS).
#[actix_web::test]
async fn should_sync_manually_captured_refund() {
    let refund_response = CONNECTOR
        .capture_payment_and_refund(
            payment_method_details(),
            None,
            None,
            get_default_payment_info(),
        )
        .await
        .unwrap();
    let response = CONNECTOR
        .rsync_retry_till_status_matches(
            enums::RefundStatus::Success,
            refund_response.response.unwrap().connector_refund_id,
            None,
            get_default_payment_info(),
        )
        .await
        .unwrap();
    assert_eq!(
        response.response.unwrap().refund_status,
        enums::RefundStatus::Success,
    );
}

// Creates a payment using the automatic capture flow (Non 3DS).
#[actix_web::test]
async fn should_make_payment() {
    let authorize_response = CONNECTOR
        .make_payment(payment_method_details(), get_default_payment_info())
        .await
        .unwrap();
    assert_eq!(authorize_response.status, enums::AttemptStatus::Charged);
}

// Synchronizes a payment using the automatic capture flow (Non 3DS).
#[actix_web::test]
async fn should_sync_auto_captured_payment() {
    let authorize_response = CONNECTOR
        .make_payment(payment_method_details(), get_default_payment_info())
        .await
        .unwrap();
    assert_eq!(authorize_response.status, enums::AttemptStatus::Charged);
    let txn_id = utils::get_connector_transaction_id(authorize_response.response);
    assert_ne!(txn_id, None, "Empty connector transaction id");
    let response = CONNECTOR
        .psync_retry_till_status_matches(
            enums::AttemptStatus::Charged,
            Some(types::PaymentsSyncData {
                connector_transaction_id: types::ResponseId::ConnectorTransactionId(
                    txn_id.unwrap(),
                ),
                capture_method: Some(enums::CaptureMethod::Automatic),
                ..Default::default()
            }),
            get_default_payment_info(),
        )
        .await
        .unwrap();
    assert_eq!(response.status, enums::AttemptStatus::Charged,);
}

// Refunds a payment using the automatic capture flow (Non 3DS).
#[actix_web::test]
async fn should_refund_auto_captured_payment() {
    let response = CONNECTOR
        .make_payment_and_refund(payment_method_details(), None, get_default_payment_info())
        .await
        .unwrap();
    assert_eq!(
        response.response.unwrap().refund_status,
        enums::RefundStatus::Success,
    );
}

// Partially refunds a payment using the automatic capture flow (Non 3DS).
#[actix_web::test]
async fn should_partially_refund_succeeded_payment() {
    let refund_response = CONNECTOR
        .make_payment_and_refund(
            payment_method_details(),
            Some(types::RefundsData {
                refund_amount: 50,
                ..utils::PaymentRefundType::default().0
            }),
            get_default_payment_info(),
        )
        .await
        .unwrap();
    assert_eq!(
        refund_response.response.unwrap().refund_status,
        enums::RefundStatus::Success,
    );
}

// Creates multiple refunds against a payment using the automatic capture flow (Non 3DS).
#[actix_web::test]
async fn should_refund_succeeded_payment_multiple_times() {
    CONNECTOR
        .make_payment_and_multiple_refund(
            payment_method_details(),
            Some(types::RefundsData {
                refund_amount: 50,
                ..utils::PaymentRefundType::default().0
            }),
            get_default_payment_info(),
        )
        .await;
}

// Synchronizes a refund using the automatic capture flow (Non 3DS).
#[actix_web::test]
async fn should_sync_refund() {
    let refund_response = CONNECTOR
        .make_payment_and_refund(payment_method_details(), None, get_default_payment_info())
        .await
        .unwrap();
    let response = CONNECTOR
        .rsync_retry_till_status_matches(
            enums::RefundStatus::Success,
            refund_response.response.unwrap().connector_refund_id,
            None,
            get_default_payment_info(),
        )
        .await
        .unwrap();
    assert_eq!(
        response.response.unwrap().refund_status,
        enums::RefundStatus::Success,
    );
}

// Cards Negative scenarios
// Creates a payment with incorrect card number.
#[actix_web::test]
async fn should_fail_payment_for_incorrect_card_number() {
    let response = CONNECTOR
        .make_payment(
            Some(types::PaymentsAuthorizeData {
                payment_method_data: types::domain::PaymentMethodData::Card(types::domain::Card {
                    card_number: cards::CardNumber::from_str("1234567891011").unwrap(),
                    ..utils::CCardType::default().0
                }),
                ..utils::PaymentAuthorizeType::default().0
            }),
            get_default_payment_info(),
        )
        .await
        .unwrap();
    assert_eq!(
        response.response.unwrap_err().message,
        "Your card number is incorrect.".to_string(),
    );
}

// Creates a payment with incorrect CVC.
#[actix_web::test]
async fn should_fail_payment_for_incorrect_cvc() {
    let response = CONNECTOR
        .make_payment(
            Some(types::PaymentsAuthorizeData {
                payment_method_data: types::domain::PaymentMethodData::Card(types::domain::Card {
                    card_cvc: Secret::new("12345".to_string()),
                    ..utils::CCardType::default().0
                }),
                ..utils::PaymentAuthorizeType::default().0
            }),
            get_default_payment_info(),
        )
        .await
        .unwrap();
    assert_eq!(
        response.response.unwrap_err().message,
        "Your card's security code is invalid.".to_string(),
    );
}

// Creates a payment with incorrect expiry month.
#[actix_web::test]
async fn should_fail_payment_for_invalid_exp_month() {
    let response = CONNECTOR
        .make_payment(
            Some(types::PaymentsAuthorizeData {
                payment_method_data: types::domain::PaymentMethodData::Card(types::domain::Card {
                    card_exp_month: Secret::new("20".to_string()),
                    ..utils::CCardType::default().0
                }),
                ..utils::PaymentAuthorizeType::default().0
            }),
            get_default_payment_info(),
        )
        .await
        .unwrap();
    assert_eq!(
        response.response.unwrap_err().message,
        "Your card's expiration month is invalid.".to_string(),
    );
}

// Creates a payment with incorrect expiry year.
#[actix_web::test]
async fn should_fail_payment_for_incorrect_expiry_year() {
    let response = CONNECTOR
        .make_payment(
            Some(types::PaymentsAuthorizeData {
                payment_method_data: types::domain::PaymentMethodData::Card(types::domain::Card {
                    card_exp_year: Secret::new("2000".to_string()),
                    ..utils::CCardType::default().0
                }),
                ..utils::PaymentAuthorizeType::default().0
            }),
            get_default_payment_info(),
        )
        .await
        .unwrap();
    assert_eq!(
        response.response.unwrap_err().message,
        "Your card's expiration year is invalid.".to_string(),
    );
}

// Voids a payment using automatic capture flow (Non 3DS).
#[actix_web::test]
async fn should_fail_void_payment_for_auto_capture() {
    let authorize_response = CONNECTOR
        .make_payment(payment_method_details(), get_default_payment_info())
        .await
        .unwrap();
    assert_eq!(authorize_response.status, enums::AttemptStatus::Charged);
    let txn_id = utils::get_connector_transaction_id(authorize_response.response);
    assert_ne!(txn_id, None, "Empty connector transaction id");
    let void_response = CONNECTOR
        .void_payment(txn_id.unwrap(), None, get_default_payment_info())
        .await
        .unwrap();
    assert_eq!(
        void_response.response.unwrap_err().message,
        "You cannot cancel this PaymentIntent because it has a status of succeeded."
    );
}

// Captures a payment using invalid connector payment id.
#[actix_web::test]
async fn should_fail_capture_for_invalid_payment() {
    let capture_response = CONNECTOR
        .capture_payment("123456789".to_string(), None, get_default_payment_info())
        .await
        .unwrap();
    assert_eq!(
        capture_response.response.unwrap_err().message,
        String::from("No such payment_intent: '123456789'")
    );
}

// Refunds a payment with refund amount higher than payment amount.
#[actix_web::test]
async fn should_fail_for_refund_amount_higher_than_payment_amount() {
    let response = CONNECTOR
        .make_payment_and_refund(
            payment_method_details(),
            Some(types::RefundsData {
                refund_amount: 150,
                ..utils::PaymentRefundType::default().0
            }),
            get_default_payment_info(),
        )
        .await
        .unwrap();
    assert_eq!(
        response.response.unwrap_err().message,
        "Refund amount (₹1.50) is greater than charge amount (₹1.00)",
    );
}

// Connector dependent test cases goes here

// [#478]: add unit tests for non 3DS, wallets & webhooks in connector tests


// Function: update_connector_mandate_details
// File: crates/router/src/core/payments/tokenization.rs
// Module: router

pub fn update_connector_mandate_details(
    mandate_details: Option<CommonMandateReference>,
    payment_method_type: Option<storage_enums::PaymentMethodType>,
    authorized_amount: Option<i64>,
    authorized_currency: Option<storage_enums::Currency>,
    merchant_connector_id: Option<id_type::MerchantConnectorAccountId>,
    connector_mandate_id: Option<String>,
    mandate_metadata: Option<Secret<serde_json::Value>>,
    connector_mandate_request_reference_id: Option<String>,
) -> RouterResult<Option<CommonMandateReference>>


// Implementation: impl AuthInfo for for AuthenticationDataWithMultipleProfiles
// File: crates/router/src/services/authentication.rs
// Module: router
// Methods: 1 total (0 public)

impl AuthInfo for for AuthenticationDataWithMultipleProfiles


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

impl api::PaymentToken for for Zen


// Function: retrieve_disputes_list_profile
// File: crates/openapi/src/routes/disputes.rs
// Module: openapi

pub fn retrieve_disputes_list_profile()


// File: crates/router/src/routes/revenue_recovery_data_backfill.rs
// Module: router
// Public functions: 2

use actix_multipart::form::MultipartForm;
use actix_web::{web, HttpRequest, HttpResponse};
use api_models::revenue_recovery_data_backfill::{BackfillQuery, RevenueRecoveryDataBackfillForm};
use router_env::{instrument, tracing, Flow};

use crate::{
    core::{api_locking, revenue_recovery_data_backfill},
    routes::AppState,
    services::{api, authentication as auth},
    types::{domain, storage},
};

#[instrument(skip_all, fields(flow = ?Flow::RecoveryDataBackfill))]
pub async fn revenue_recovery_data_backfill(
    state: web::Data<AppState>,
    req: HttpRequest,
    query: web::Query<BackfillQuery>,
    MultipartForm(form): MultipartForm<RevenueRecoveryDataBackfillForm>,
) -> HttpResponse {
    let flow = Flow::RecoveryDataBackfill;

    // Parse cutoff_time from query parameter
    let cutoff_datetime = match query
        .cutoff_time
        .as_ref()
        .map(|time_str| {
            time::PrimitiveDateTime::parse(
                time_str,
                &time::format_description::well_known::Iso8601::DEFAULT,
            )
        })
        .transpose()
    {
        Ok(datetime) => datetime,
        Err(err) => {
            return HttpResponse::BadRequest().json(serde_json::json!({
                "error": format!("Invalid datetime format: {}. Use ISO8601: 2024-01-15T10:30:00", err)
            }));
        }
    };

    let records = match form.validate_and_get_records_with_errors() {
        Ok(records) => records,
        Err(e) => {
            return HttpResponse::BadRequest().json(serde_json::json!({
                "error": e.to_string()
            }));
        }
    };

    Box::pin(api::server_wrap(
        flow,
        state,
        &req,
        records,
        |state, _, records, _req| {
            revenue_recovery_data_backfill::revenue_recovery_data_backfill(
                state,
                records.records,
                cutoff_datetime,
            )
        },
        &auth::V2AdminApiAuth,
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

#[instrument(skip_all, fields(flow = ?Flow::RecoveryDataBackfill))]
pub async fn revenue_recovery_data_backfill_status(
    state: web::Data<AppState>,
    req: HttpRequest,
    path: web::Path<String>,
) -> HttpResponse {
    let flow = Flow::RecoveryDataBackfill;
    let connector_customer_id = path.into_inner();

    Box::pin(api::server_wrap(
        flow,
        state,
        &req,
        connector_customer_id,
        |state, _: (), id, _| {
            revenue_recovery_data_backfill::unlock_connector_customer_status(state, id)
        },
        &auth::V2AdminApiAuth,
        api_locking::LockAction::NotApplicable,
    ))
    .await
}


// Struct: AccountIdConfigForRedirect
// File: crates/connector_configs/src/connector.rs
// Module: connector_configs
// Implementations: 0

pub struct AccountIdConfigForRedirect


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

impl api::PaymentVoid for for Klarna


// Struct: BankAccount
// File: crates/hyperswitch_connectors/src/connectors/nomupay/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct BankAccount


// Function: make_frm_data_and_fraud_check_operation
// File: crates/router/src/core/fraud_check.rs
// Module: router

pub fn make_frm_data_and_fraud_check_operation<F, D>(
    _db: &dyn StorageInterface,
    state: &SessionState,
    merchant_context: &domain::MerchantContext,
    payment_data: D,
    frm_routing_algorithm: FrmRoutingAlgorithm,
    profile_id: common_utils::id_type::ProfileId,
    frm_configs: FrmConfigsObject,
    _customer: &Option<domain::Customer>,
) -> RouterResult<FrmInfo<F, D>>
where
    F: Send + Clone,
    D: payments::OperationSessionGetters<F>
        + payments::OperationSessionSetters<F>
        + Send
        + Sync
        + Clone,


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

// Public submodules:
pub mod transformers;


// Function: form_payment_link_data
// File: crates/router/src/core/payment_link.rs
// Module: router

pub fn form_payment_link_data(
    state: &SessionState,
    merchant_context: domain::MerchantContext,
    merchant_id: common_utils::id_type::MerchantId,
    payment_id: common_utils::id_type::PaymentId,
) -> RouterResult<(PaymentLink, PaymentLinkData, PaymentLinkConfig)>


// Struct: BluesnapThreeDsReference
// File: crates/hyperswitch_connectors/src/connectors/bluesnap/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct BluesnapThreeDsReference


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

pub struct PaymentIntentCore


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

impl api::ConnectorAccessToken for for Novalnet


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

impl Blocklist


// Function: new
// File: crates/router/src/types/domain/user.rs
// Module: router

pub fn new(email: Secret<String, pii::EmailStrategy>) -> UserResult<Self>


// File: crates/router/src/types/api/poll.rs
// Module: router
// Public structs: 1

use serde;

#[derive(Default, Debug, serde::Deserialize, serde::Serialize)]
pub struct PollId {
    pub poll_id: String,
}


// File: crates/router/src/db/payment_method_session.rs
// Module: router

#[cfg(feature = "v2")]
use crate::core::errors::{self, CustomResult};
use crate::db::MockDb;

#[cfg(feature = "v2")]
#[async_trait::async_trait]
pub trait PaymentMethodsSessionInterface {
    async fn insert_payment_methods_session(
        &self,
        state: &common_utils::types::keymanager::KeyManagerState,
        key_store: &hyperswitch_domain_models::merchant_key_store::MerchantKeyStore,
        payment_methods_session: hyperswitch_domain_models::payment_methods::PaymentMethodSession,
        validity: i64,
    ) -> CustomResult<(), errors::StorageError>;

    async fn update_payment_method_session(
        &self,
        state: &common_utils::types::keymanager::KeyManagerState,
        key_store: &hyperswitch_domain_models::merchant_key_store::MerchantKeyStore,
        id: &common_utils::id_type::GlobalPaymentMethodSessionId,
        payment_methods_session: hyperswitch_domain_models::payment_methods::PaymentMethodsSessionUpdateEnum,
        current_session: hyperswitch_domain_models::payment_methods::PaymentMethodSession,
    ) -> CustomResult<
        hyperswitch_domain_models::payment_methods::PaymentMethodSession,
        errors::StorageError,
    >;

    async fn get_payment_methods_session(
        &self,
        state: &common_utils::types::keymanager::KeyManagerState,
        key_store: &hyperswitch_domain_models::merchant_key_store::MerchantKeyStore,
        id: &common_utils::id_type::GlobalPaymentMethodSessionId,
    ) -> CustomResult<
        hyperswitch_domain_models::payment_methods::PaymentMethodSession,
        errors::StorageError,
    >;
}

#[cfg(feature = "v1")]
pub trait PaymentMethodsSessionInterface {}

#[cfg(feature = "v1")]
impl PaymentMethodsSessionInterface for crate::services::Store {}

#[cfg(feature = "v2")]
mod storage {
    use error_stack::ResultExt;
    use hyperswitch_domain_models::behaviour::{Conversion, ReverseConversion};
    use router_env::{instrument, tracing};
    use storage_impl::redis::kv_store::RedisConnInterface;

    use super::PaymentMethodsSessionInterface;
    use crate::{
        core::errors::{self, CustomResult},
        services::Store,
    };

    #[async_trait::async_trait]
    impl PaymentMethodsSessionInterface for Store {
        #[instrument(skip_all)]
        async fn insert_payment_methods_session(
            &self,
            _state: &common_utils::types::keymanager::KeyManagerState,
            _key_store: &hyperswitch_domain_models::merchant_key_store::MerchantKeyStore,
            payment_methods_session: hyperswitch_domain_models::payment_methods::PaymentMethodSession,
            validity_in_seconds: i64,
        ) -> CustomResult<(), errors::StorageError> {
            let redis_key = payment_methods_session.id.get_redis_key();

            let db_model = payment_methods_session
                .construct_new()
                .await
                .change_context(errors::StorageError::EncryptionError)?;

            let redis_connection = self
                .get_redis_conn()
                .map_err(Into::<errors::StorageError>::into)?;

            redis_connection
                .serialize_and_set_key_with_expiry(&redis_key.into(), db_model, validity_in_seconds)
                .await
                .change_context(errors::StorageError::KVError)
                .attach_printable("Failed to insert payment methods session to redis")
        }

        #[instrument(skip_all)]
        async fn get_payment_methods_session(
            &self,
            state: &common_utils::types::keymanager::KeyManagerState,
            key_store: &hyperswitch_domain_models::merchant_key_store::MerchantKeyStore,
            id: &common_utils::id_type::GlobalPaymentMethodSessionId,
        ) -> CustomResult<
            hyperswitch_domain_models::payment_methods::PaymentMethodSession,
            errors::StorageError,
        > {
            let redis_key = id.get_redis_key();

            let redis_connection = self
                .get_redis_conn()
                .map_err(Into::<errors::StorageError>::into)?;

            let db_model = redis_connection
                .get_and_deserialize_key::<diesel_models::payment_methods_session::PaymentMethodSession>(&redis_key.into(), "PaymentMethodSession")
                .await
                .change_context(errors::StorageError::KVError)?;

            let key_manager_identifier = common_utils::types::keymanager::Identifier::Merchant(
                key_store.merchant_id.clone(),
            );

            db_model
                .convert(state, &key_store.key, key_manager_identifier)
                .await
                .change_context(errors::StorageError::DecryptionError)
                .attach_printable("Failed to decrypt payment methods session")
        }

        #[instrument(skip_all)]
        async fn update_payment_method_session(
            &self,
            state: &common_utils::types::keymanager::KeyManagerState,
            key_store: &hyperswitch_domain_models::merchant_key_store::MerchantKeyStore,
            session_id: &common_utils::id_type::GlobalPaymentMethodSessionId,
            update_request: hyperswitch_domain_models::payment_methods::PaymentMethodsSessionUpdateEnum,
            current_session: hyperswitch_domain_models::payment_methods::PaymentMethodSession,
        ) -> CustomResult<
            hyperswitch_domain_models::payment_methods::PaymentMethodSession,
            errors::StorageError,
        > {
            let redis_key = session_id.get_redis_key();

            let internal_obj = hyperswitch_domain_models::payment_methods::PaymentMethodsSessionUpdateInternal::from(update_request);

            let update_state = current_session.apply_changeset(internal_obj);

            let db_model = update_state
                .construct_new()
                .await
                .change_context(errors::StorageError::EncryptionError)?;

            let redis_connection = self
                .get_redis_conn()
                .map_err(Into::<errors::StorageError>::into)?;

            redis_connection
                .serialize_and_set_key_without_modifying_ttl(&redis_key.into(), db_model.clone())
                .await
                .change_context(errors::StorageError::KVError)
                .attach_printable("Failed to insert payment methods session to redis");

            let key_manager_identifier = common_utils::types::keymanager::Identifier::Merchant(
                key_store.merchant_id.clone(),
            );

            db_model
                .convert(state, &key_store.key, key_manager_identifier)
                .await
                .change_context(errors::StorageError::DecryptionError)
                .attach_printable("Failed to decrypt payment methods session")
        }
    }
}
#[cfg(feature = "v2")]
#[async_trait::async_trait]
impl PaymentMethodsSessionInterface for MockDb {
    async fn insert_payment_methods_session(
        &self,
        state: &common_utils::types::keymanager::KeyManagerState,
        key_store: &hyperswitch_domain_models::merchant_key_store::MerchantKeyStore,
        payment_methods_session: hyperswitch_domain_models::payment_methods::PaymentMethodSession,
        validity_in_seconds: i64,
    ) -> CustomResult<(), errors::StorageError> {
        Err(errors::StorageError::MockDbError)?
    }

    async fn update_payment_method_session(
        &self,
        state: &common_utils::types::keymanager::KeyManagerState,
        key_store: &hyperswitch_domain_models::merchant_key_store::MerchantKeyStore,
        id: &common_utils::id_type::GlobalPaymentMethodSessionId,
        payment_methods_session: hyperswitch_domain_models::payment_methods::PaymentMethodsSessionUpdateEnum,
        current_session: hyperswitch_domain_models::payment_methods::PaymentMethodSession,
    ) -> CustomResult<
        hyperswitch_domain_models::payment_methods::PaymentMethodSession,
        errors::StorageError,
    > {
        Err(errors::StorageError::MockDbError)?
    }

    #[cfg(feature = "v2")]
    async fn get_payment_methods_session(
        &self,
        state: &common_utils::types::keymanager::KeyManagerState,
        key_store: &hyperswitch_domain_models::merchant_key_store::MerchantKeyStore,
        id: &common_utils::id_type::GlobalPaymentMethodSessionId,
    ) -> CustomResult<
        hyperswitch_domain_models::payment_methods::PaymentMethodSession,
        errors::StorageError,
    > {
        Err(errors::StorageError::MockDbError)?
    }
}

#[cfg(feature = "v1")]
#[async_trait::async_trait]
impl PaymentMethodsSessionInterface for MockDb {}


// Struct: RefundMetricsBucketIdentifier
// File: crates/api_models/src/analytics/refunds.rs
// Module: api_models
// Implementations: 3
// Traits: Hash, PartialEq

pub struct RefundMetricsBucketIdentifier


// Struct: CheckTokenStatusResponse
// File: crates/router/src/types/payment_methods.rs
// Module: router
// Implementations: 0

pub struct CheckTokenStatusResponse


// Struct: Acquirer
// File: crates/hyperswitch_connectors/src/connectors/unified_authentication_service/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct Acquirer


// Struct: Redsys
// File: crates/hyperswitch_connectors/src/connectors/redsys.rs
// Module: hyperswitch_connectors
// Implementations: 19
// Traits: api::Payment, api::PaymentSession, api::ConnectorAccessToken, api::MandateSetup, api::PaymentAuthorize, api::PaymentSync, api::PaymentCapture, api::PaymentVoid, api::Refund, api::RefundExecute, api::RefundSync, api::PaymentToken, api::PaymentsPreProcessing, api::PaymentsCompleteAuthorize, ConnectorCommon, ConnectorValidation, webhooks::IncomingWebhook, ConnectorSpecifications

pub struct Redsys

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


// File: crates/hyperswitch_interfaces/src/api/vault.rs
// Module: hyperswitch_interfaces

//! Vault interface

use hyperswitch_domain_models::{
    router_flow_types::vault::{
        ExternalVaultCreateFlow, ExternalVaultDeleteFlow, ExternalVaultInsertFlow,
        ExternalVaultRetrieveFlow,
    },
    router_request_types::VaultRequestData,
    router_response_types::VaultResponseData,
};

use super::ConnectorCommon;
use crate::api::ConnectorIntegration;

/// trait ExternalVaultInsert
pub trait ExternalVaultInsert:
    ConnectorIntegration<ExternalVaultInsertFlow, VaultRequestData, VaultResponseData>
{
}

/// trait ExternalVaultRetrieve
pub trait ExternalVaultRetrieve:
    ConnectorIntegration<ExternalVaultRetrieveFlow, VaultRequestData, VaultResponseData>
{
}

/// trait ExternalVaultDelete
pub trait ExternalVaultDelete:
    ConnectorIntegration<ExternalVaultDeleteFlow, VaultRequestData, VaultResponseData>
{
}

/// trait ExternalVaultDelete
pub trait ExternalVaultCreate:
    ConnectorIntegration<ExternalVaultCreateFlow, VaultRequestData, VaultResponseData>
{
}

/// trait ExternalVault
pub trait ExternalVault:
    ConnectorCommon
    + ExternalVaultInsert
    + ExternalVaultRetrieve
    + ExternalVaultDelete
    + ExternalVaultCreate
{
}


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

pub fn update(&mut self, new: Self)


// Struct: PaystackWebhookData
// File: crates/hyperswitch_connectors/src/connectors/paystack/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct PaystackWebhookData


// Struct: WeChatPayQr
// File: crates/hyperswitch_domain_models/src/payment_method_data.rs
// Module: hyperswitch_domain_models
// Implementations: 0

pub struct WeChatPayQr


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

pub fn if_not_create_change_operation<'a, Op, F>(
    status: storage_enums::IntentStatus,
    confirm: Option<bool>,
    current: &'a Op,
) -> BoxedOperation<'a, F, api::PaymentsRequest, PaymentData<F>>
where
    F: Send + Clone + Sync,
    Op: Operation<F, api::PaymentsRequest, Data = PaymentData<F>> + Send + Sync,
    &'a Op: Operation<F, api::PaymentsRequest, Data = PaymentData<F>>,
    PaymentStatus: Operation<F, api::PaymentsRequest, Data = PaymentData<F>>,
    &'a PaymentStatus: Operation<F, api::PaymentsRequest, Data = PaymentData<F>>,


// Struct: PaymentMethodInput
// File: crates/euclid/src/backend/inputs.rs
// Module: euclid
// Implementations: 0

pub struct PaymentMethodInput


// Struct: ConnectorChoice
// File: crates/euclid/src/frontend/ast.rs
// Module: euclid
// Implementations: 0

pub struct ConnectorChoice


// Struct: PaymentsMandateReference
// File: crates/hyperswitch_domain_models/src/mandates.rs
// Module: hyperswitch_domain_models
// Implementations: 2
// Traits: std::ops::Deref, std::ops::DerefMut

pub struct PaymentsMandateReference


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

pub fn new() -> &'static Self


// Function: server
// File: crates/router/src/routes/app.rs
// Module: router

pub fn server(state: AppState) -> Scope


// Implementation: impl ConnectorSpecifications for for Novalnet
// File: crates/hyperswitch_connectors/src/connectors/novalnet.rs
// Module: hyperswitch_connectors
// Methods: 3 total (0 public)

impl ConnectorSpecifications for for Novalnet


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

pub struct Customer


// Struct: Cache
// File: crates/router/src/routes/app.rs
// Module: router
// Implementations: 1

pub struct Cache


// Function: generate_cargo_instructions
// File: crates/router_env/src/vergen.rs
// Module: router_env

pub fn generate_cargo_instructions()


// File: crates/api_models/src/health_check.rs
// Module: api_models
// Public structs: 2

use std::collections::hash_map::HashMap;
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct RouterHealthCheckResponse {
    pub database: bool,
    pub redis: bool,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub vault: Option<bool>,
    #[cfg(feature = "olap")]
    pub analytics: bool,
    #[cfg(feature = "olap")]
    pub opensearch: bool,
    pub outgoing_request: bool,
    #[cfg(feature = "dynamic_routing")]
    pub grpc_health_check: HealthCheckMap,
    #[cfg(feature = "dynamic_routing")]
    pub decision_engine: bool,
    pub unified_connector_service: Option<bool>,
}

impl common_utils::events::ApiEventMetric for RouterHealthCheckResponse {}

/// gRPC based services eligible for Health check
#[derive(Debug, Clone, Eq, PartialEq, Hash, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum HealthCheckServices {
    /// Dynamic routing service
    DynamicRoutingService,
}

pub type HealthCheckMap = HashMap<HealthCheckServices, bool>;

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct SchedulerHealthCheckResponse {
    pub database: bool,
    pub redis: bool,
    pub outgoing_request: bool,
}

pub enum HealthState {
    Running,
    Error,
    NotApplicable,
}

impl From<HealthState> for bool {
    fn from(value: HealthState) -> Self {
        match value {
            HealthState::Running => true,
            HealthState::Error | HealthState::NotApplicable => false,
        }
    }
}
impl From<HealthState> for Option<bool> {
    fn from(value: HealthState) -> Self {
        match value {
            HealthState::Running => Some(true),
            HealthState::Error => Some(false),
            HealthState::NotApplicable => None,
        }
    }
}

impl common_utils::events::ApiEventMetric for SchedulerHealthCheckResponse {}


// Struct: MerchantIdAuth
// File: crates/router/src/services/authentication.rs
// Module: router
// Implementations: 0

pub struct MerchantIdAuth


// File: crates/diesel_models/src/events.rs
// Module: diesel_models
// Public structs: 3

use common_utils::{custom_serde, encryption::Encryption};
use diesel::{
    expression::AsExpression, AsChangeset, Identifiable, Insertable, Queryable, Selectable,
};
use serde::{Deserialize, Serialize};
use time::PrimitiveDateTime;

use crate::{enums as storage_enums, schema::events};

#[derive(Clone, Debug, Insertable, router_derive::DebugAsDisplay)]
#[diesel(table_name = events)]
pub struct EventNew {
    pub event_id: String,
    pub event_type: storage_enums::EventType,
    pub event_class: storage_enums::EventClass,
    pub is_webhook_notified: bool,
    pub primary_object_id: String,
    pub primary_object_type: storage_enums::EventObjectType,
    pub created_at: PrimitiveDateTime,
    pub merchant_id: Option<common_utils::id_type::MerchantId>,
    pub business_profile_id: Option<common_utils::id_type::ProfileId>,
    pub primary_object_created_at: Option<PrimitiveDateTime>,
    pub idempotent_event_id: Option<String>,
    pub initial_attempt_id: Option<String>,
    pub request: Option<Encryption>,
    pub response: Option<Encryption>,
    pub delivery_attempt: Option<storage_enums::WebhookDeliveryAttempt>,
    pub metadata: Option<EventMetadata>,
    pub is_overall_delivery_successful: Option<bool>,
}

#[derive(Clone, Debug, Default, AsChangeset, router_derive::DebugAsDisplay)]
#[diesel(table_name = events)]
pub struct EventUpdateInternal {
    pub is_webhook_notified: Option<bool>,
    pub response: Option<Encryption>,
    pub is_overall_delivery_successful: Option<bool>,
}

#[derive(Clone, Debug, Deserialize, Serialize, Identifiable, Queryable, Selectable)]
#[diesel(table_name = events, primary_key(event_id), check_for_backend(diesel::pg::Pg))]
pub struct Event {
    pub event_id: String,
    pub event_type: storage_enums::EventType,
    pub event_class: storage_enums::EventClass,
    pub is_webhook_notified: bool,
    pub primary_object_id: String,
    pub primary_object_type: storage_enums::EventObjectType,
    #[serde(with = "custom_serde::iso8601")]
    pub created_at: PrimitiveDateTime,
    pub merchant_id: Option<common_utils::id_type::MerchantId>,
    pub business_profile_id: Option<common_utils::id_type::ProfileId>,
    // This column can be used to partition the database table, so that all events related to a
    // single object would reside in the same partition
    pub primary_object_created_at: Option<PrimitiveDateTime>,
    pub idempotent_event_id: Option<String>,
    pub initial_attempt_id: Option<String>,
    pub request: Option<Encryption>,
    pub response: Option<Encryption>,
    pub delivery_attempt: Option<storage_enums::WebhookDeliveryAttempt>,
    pub metadata: Option<EventMetadata>,
    pub is_overall_delivery_successful: Option<bool>,
}

#[derive(Clone, Debug, Deserialize, Serialize, AsExpression, diesel::FromSqlRow)]
#[diesel(sql_type = diesel::sql_types::Jsonb)]
pub enum EventMetadata {
    #[cfg(feature = "v1")]
    Payment {
        payment_id: common_utils::id_type::PaymentId,
    },
    #[cfg(feature = "v2")]
    Payment {
        payment_id: common_utils::id_type::GlobalPaymentId,
    },
    Payout {
        payout_id: common_utils::id_type::PayoutId,
    },
    #[cfg(feature = "v1")]
    Refund {
        payment_id: common_utils::id_type::PaymentId,
        refund_id: String,
    },
    #[cfg(feature = "v2")]
    Refund {
        payment_id: common_utils::id_type::GlobalPaymentId,
        refund_id: common_utils::id_type::GlobalRefundId,
    },
    #[cfg(feature = "v1")]
    Dispute {
        payment_id: common_utils::id_type::PaymentId,
        attempt_id: String,
        dispute_id: String,
    },
    #[cfg(feature = "v2")]
    Dispute {
        payment_id: common_utils::id_type::GlobalPaymentId,
        attempt_id: String,
        dispute_id: String,
    },
    Mandate {
        payment_method_id: String,
        mandate_id: String,
    },
}

common_utils::impl_to_sql_from_sql_json!(EventMetadata);


// Function: find_by_profile_id_connector_reference_id
// File: crates/diesel_models/src/query/relay.rs
// Module: diesel_models

pub fn find_by_profile_id_connector_reference_id(
        conn: &PgPooledConn,
        profile_id: &common_utils::id_type::ProfileId,
        connector_reference_id: &str,
    ) -> StorageResult<Self>


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

pub fn get_user_details(
    state: SessionState,
    user_from_token: auth::UserFromToken,
) -> UserResponse<user_api::GetUserDetailsResponse>


// Implementation: impl ConnectorCustomerResponseData
// File: crates/hyperswitch_domain_models/src/router_response_types.rs
// Module: hyperswitch_domain_models
// Methods: 2 total (2 public)

impl ConnectorCustomerResponseData


// Function: lower_program
// File: crates/euclid/src/frontend/ast/lowering.rs
// Module: euclid

// Documentation: uses the above rules and lowers the whole ast Program into DirProgram by specifying default_selection that is ast ConnectorSelection, a vector of DirRules and clones the metadata whatever comes in the ast_program

pub fn lower_program<O: EuclidDirFilter>(
    program: ast::Program<O>,
) -> Result<dir::DirProgram<O>, AnalysisError>


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

// Public submodules:
pub mod transformers;


// Implementation: impl api::PaymentSync for for Globepay
// File: crates/hyperswitch_connectors/src/connectors/globepay.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::PaymentSync for for Globepay


// Struct: MandateAmountData
// File: crates/diesel_models/src/enums.rs
// Module: diesel_models
// Implementations: 0

pub struct MandateAmountData


// Struct: GenerateNetworkTokenResponsePayload
// File: crates/router/src/types/payment_methods.rs
// Module: router
// Implementations: 0

pub struct GenerateNetworkTokenResponsePayload


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

impl IncomingWebhook for for Paypal


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

pub fn get_theme_using_theme_id(
    state: SessionState,
    theme_id: String,
) -> UserResponse<theme_api::GetThemeResponse>


// Struct: NewUserOrganization
// File: crates/router/src/types/domain/user.rs
// Module: router
// Implementations: 1

pub struct NewUserOrganization


// Struct: PaymeRouterData
// File: crates/hyperswitch_connectors/src/connectors/payme/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct PaymeRouterData<T>


// Implementation: impl PMAuthConfigValidation
// File: crates/router/src/core/admin.rs
// Module: router
// Methods: 2 total (0 public)

impl PMAuthConfigValidation


// Struct: DynamicRoutingConfigParamsInterpolator
// File: crates/router/src/core/routing/helpers.rs
// Module: router
// Implementations: 1

pub struct DynamicRoutingConfigParamsInterpolator


// Struct: DeutschebankThreeDSCompleteAuthorizeRequest
// File: crates/hyperswitch_connectors/src/connectors/deutschebank/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct DeutschebankThreeDSCompleteAuthorizeRequest


// Struct: ReturnLink
// File: crates/hyperswitch_connectors/src/connectors/paysafe/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct ReturnLink


// Function: update_gateway_score_open_router
// File: crates/router/src/core/routing.rs
// Module: router

pub fn update_gateway_score_open_router(
    state: SessionState,
    req_body: UpdateScorePayload,
) -> RouterResponse<UpdateScoreResponse>


// Function: authorization_attempt_status_from_transaction_state
// File: crates/hyperswitch_connectors/src/connectors/getnet/transformers.rs
// Module: hyperswitch_connectors

pub fn authorization_attempt_status_from_transaction_state(
    getnet_status: GetnetPaymentStatus,
    is_auto_capture: bool,
) -> AttemptStatus


// Implementation: impl ConnectorCommon for for Gocardless
// File: crates/hyperswitch_connectors/src/connectors/gocardless.rs
// Module: hyperswitch_connectors
// Methods: 6 total (0 public)

impl ConnectorCommon for for Gocardless


// Struct: GooglePayWalletData
// File: crates/hyperswitch_domain_models/src/payment_method_data.rs
// Module: hyperswitch_domain_models
// Implementations: 0

pub struct GooglePayWalletData


// Implementation: impl SuccessBasedAlgorithm
// File: crates/api_models/src/routing.rs
// Module: api_models
// Methods: 1 total (1 public)

impl SuccessBasedAlgorithm


// Struct: CryptopayErrorResponse
// File: crates/hyperswitch_connectors/src/connectors/cryptopay/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct CryptopayErrorResponse


// Implementation: impl ConnectorCommon for for Coinbase
// File: crates/hyperswitch_connectors/src/connectors/coinbase.rs
// Module: hyperswitch_connectors
// Methods: 5 total (0 public)

impl ConnectorCommon for for Coinbase


// Struct: SupportedPaymentMethodsForMandate
// File: crates/payment_methods/src/configs/settings.rs
// Module: payment_methods
// Implementations: 0

pub struct SupportedPaymentMethodsForMandate


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

pub struct AuthReversalResponse


// Implementation: impl RelayRequestInner
// File: crates/router/src/core/relay.rs
// Module: router
// Methods: 1 total (1 public)

impl RelayRequestInner


// Struct: AddressUpdateMems
// File: crates/diesel_models/src/kv.rs
// Module: diesel_models
// Implementations: 0

pub struct AddressUpdateMems


// Module Structure
// File: crates/router/src/services.rs
// Module: router

// Public submodules:
pub mod api;
pub mod authentication;
pub mod authorization;
pub mod connector_integration_interface;
pub mod email;
pub mod encryption;
pub mod jwt;
pub mod kafka;
pub mod logger;
pub mod pm_auth;
pub mod card_testing_guard;
pub mod openidconnect;

// Public exports:
pub use hyperswitch_interfaces::connector_integration_v2::{
    BoxedConnectorIntegrationV2, ConnectorIntegrationAnyV2, ConnectorIntegrationV2,
};
pub use self::{api::*, encryption::*};


// Struct: SurchargeDecisionManagerRecord
// File: crates/api_models/src/surcharge_decision_configs.rs
// Module: api_models
// Implementations: 1
// Traits: events::ApiEventMetric

pub struct SurchargeDecisionManagerRecord


// Struct: MbWayRedirection
// File: crates/hyperswitch_domain_models/src/payment_method_data.rs
// Module: hyperswitch_domain_models
// Implementations: 0

pub struct MbWayRedirection


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

impl api::ConnectorAccessToken for for Facilitapay