            NovalnetAPIStatus::Success => {
                let transaction_id = item
                    .response
                    .transaction
                    .clone()
                    .and_then(|data| data.tid)
                    .map(|tid| tid.expose().to_string());
                let transaction_status = item
                    .response
                    .transaction
                    .clone()
                    .map(|transaction_data| transaction_data.status)
                    .unwrap_or(NovalnetTransactionStatus::Pending);
                let mandate_reference_id = NovalnetSyncResponseTransactionData::get_token(
                    item.response.transaction.as_ref(),
                );

                Ok(Self {
                    status: common_enums::AttemptStatus::from(transaction_status),
                    response: Ok(PaymentsResponseData::TransactionResponse {
                        resource_id: transaction_id
                            .clone()
                            .map(ResponseId::ConnectorTransactionId)
                            .unwrap_or(ResponseId::NoResponseId),
                        redirection_data: Box::new(None),
                        mandate_reference: Box::new(mandate_reference_id.as_ref().map(|id| {
                            MandateReference {
                                connector_mandate_id: Some(id.clone()),
                                payment_method_id: None,
                                mandate_metadata: None,
                                connector_mandate_request_reference_id: None,
                            }
                        })),
                        connector_metadata: None,
                        network_txn_id: item.response.transaction.and_then(|data| {
                            data.payment_data
                                .and_then(|payment_data| match payment_data {
                                    NovalnetResponsePaymentData::Card(card) => {
                                        card.scheme_tid.map(|tid| tid.expose())
                                    }
                                    NovalnetResponsePaymentData::Paypal(_) => None,
                                })
                        }),
                        connector_response_reference_id: transaction_id.clone(),
                        incremental_authorization_allowed: None,
                        charges: None,
                    }),
                    ..item.data
                })
            }
            NovalnetAPIStatus::Failure => {
                let response = Err(get_error_response(item.response.result, item.http_code));
                Ok(Self {
                    response,
                    ..item.data
                })
            }
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NovalnetCaptureTransactionData {
    pub amount: Option<MinorUnit>,
    pub capture: CaptureData,
    pub currency: Option<common_enums::Currency>,
    pub order_no: Option<String>,
    pub payment_type: String,
    pub status: NovalnetTransactionStatus,
    pub status_code: Option<u64>,
    pub test_mode: Option<u8>,
    pub tid: Secret<i64>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CaptureData {
    amount: Option<u64>,
    payment_type: Option<String>,
    status: Option<String>,
    status_code: u64,
    tid: Option<Secret<i64>>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NovalnetCaptureResponse {
    pub result: ResultData,
    pub transaction: Option<NovalnetCaptureTransactionData>,
}

impl<F>
    TryFrom<
        ResponseRouterData<F, NovalnetCaptureResponse, PaymentsCaptureData, PaymentsResponseData>,
    > for RouterData<F, PaymentsCaptureData, PaymentsResponseData>
{
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        item: ResponseRouterData<
            F,
            NovalnetCaptureResponse,
            PaymentsCaptureData,
            PaymentsResponseData,
        >,
    ) -> Result<Self, Self::Error> {
        match item.response.result.status {
            NovalnetAPIStatus::Success => {
                let transaction_id = item
                    .response
                    .transaction
                    .clone()
                    .map(|data| data.tid.expose().to_string());
                let transaction_status = item
                    .response
                    .transaction
                    .map(|transaction_data| transaction_data.status)
                    .unwrap_or(NovalnetTransactionStatus::Pending);

                Ok(Self {
                    status: common_enums::AttemptStatus::from(transaction_status),
                    response: Ok(PaymentsResponseData::TransactionResponse {
                        resource_id: transaction_id
                            .clone()
                            .map(ResponseId::ConnectorTransactionId)
                            .unwrap_or(ResponseId::NoResponseId),
                        redirection_data: Box::new(None),
                        mandate_reference: Box::new(None),
                        connector_metadata: None,
                        network_txn_id: None,
                        connector_response_reference_id: transaction_id.clone(),
                        incremental_authorization_allowed: None,
                        charges: None,
                    }),
                    ..item.data
                })
            }
            NovalnetAPIStatus::Failure => {
                let response = Err(get_error_response(item.response.result, item.http_code));
                Ok(Self {
                    response,
                    ..item.data
                })
            }
        }
    }
}

#[derive(Default, Debug, Serialize)]
pub struct NovalnetSyncTransaction {
    tid: String,
}

#[derive(Default, Debug, Serialize)]
pub struct NovalnetSyncRequest {
    pub transaction: NovalnetSyncTransaction,
    pub custom: NovalnetCustom,
}

impl TryFrom<&RefundSyncRouterData> for NovalnetSyncRequest {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(item: &RefundSyncRouterData) -> Result<Self, Self::Error> {
        let transaction = NovalnetSyncTransaction {
            tid: item.request.connector_transaction_id.clone(),
        };

        let custom = NovalnetCustom {
            lang: item
                .request
                .get_optional_language_from_browser_info()
                .unwrap_or(consts::DEFAULT_LOCALE.to_string().to_string()),
        };
        Ok(Self {
            transaction,
            custom,
        })
    }
}

impl TryFrom<RefundsResponseRouterData<RSync, NovalnetRefundSyncResponse>>
    for RefundsRouterData<RSync>
{
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        item: RefundsResponseRouterData<RSync, NovalnetRefundSyncResponse>,
    ) -> Result<Self, Self::Error> {
        match item.response.result.status {
            NovalnetAPIStatus::Success => {
                let refund_id = item
                    .response
                    .transaction
                    .clone()
                    .and_then(|data| data.tid)
                    .map(|tid| tid.expose().to_string())
                    .unwrap_or("".to_string());
                //NOTE: Mapping refund_id with "" incase we dont get any tid

                let transaction_status = item
                    .response
                    .transaction
                    .map(|transaction_data| transaction_data.status)
                    .unwrap_or(NovalnetTransactionStatus::Pending);

                Ok(Self {
                    response: Ok(RefundsResponseData {
                        connector_refund_id: refund_id,
                        refund_status: enums::RefundStatus::from(transaction_status),
                    }),
                    ..item.data
                })
            }
            NovalnetAPIStatus::Failure => {
                let response = Err(get_error_response(item.response.result, item.http_code));
                Ok(Self {
                    response,
                    ..item.data
                })
            }
        }
    }
}

#[derive(Default, Debug, Serialize)]
pub struct NovalnetCancelTransaction {
    tid: String,
}

#[derive(Default, Debug, Serialize)]
pub struct NovalnetCancelRequest {
    pub transaction: NovalnetCancelTransaction,
    pub custom: NovalnetCustom,
}

impl TryFrom<&PaymentsCancelRouterData> for NovalnetCancelRequest {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(item: &PaymentsCancelRouterData) -> Result<Self, Self::Error> {
        let transaction = NovalnetCancelTransaction {
            tid: item.request.connector_transaction_id.clone(),
        };

        let custom = NovalnetCustom {
            lang: item
                .request
                .get_optional_language_from_browser_info()
                .unwrap_or(consts::DEFAULT_LOCALE.to_string().to_string()),
        };
        Ok(Self {
            transaction,
            custom,
        })
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NovalnetCancelResponse {
    result: ResultData,
    transaction: Option<NovalnetPaymentsResponseTransactionData>,
}

impl<F>
    TryFrom<ResponseRouterData<F, NovalnetCancelResponse, PaymentsCancelData, PaymentsResponseData>>
    for RouterData<F, PaymentsCancelData, PaymentsResponseData>
{
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        item: ResponseRouterData<
            F,
            NovalnetCancelResponse,
            PaymentsCancelData,
            PaymentsResponseData,
        >,
    ) -> Result<Self, Self::Error> {
        match item.response.result.status {
            NovalnetAPIStatus::Success => {
                let transaction_id = item
                    .response
                    .transaction
                    .clone()
                    .and_then(|data| data.tid.map(|tid| tid.expose().to_string()));
                let transaction_status = item
                    .response
                    .transaction
                    .and_then(|transaction_data| transaction_data.status)
                    .unwrap_or(NovalnetTransactionStatus::Pending);
                Ok(Self {
                    status: if transaction_status == NovalnetTransactionStatus::Deactivated {
                        enums::AttemptStatus::Voided
                    } else {
                        enums::AttemptStatus::VoidFailed
                    },
                    response: Ok(PaymentsResponseData::TransactionResponse {
                        resource_id: transaction_id
                            .clone()
                            .map(ResponseId::ConnectorTransactionId)
                            .unwrap_or(ResponseId::NoResponseId),
                        redirection_data: Box::new(None),
                        mandate_reference: Box::new(None),
                        connector_metadata: None,
                        network_txn_id: None,
                        connector_response_reference_id: transaction_id.clone(),
                        incremental_authorization_allowed: None,
                        charges: None,
                    }),
                    ..item.data
                })
            }
            NovalnetAPIStatus::Failure => {
                let response = Err(get_error_response(item.response.result, item.http_code));
                Ok(Self {
                    response,
                    ..item.data
                })
            }
        }
    }
}

//TODO: Fill the struct with respective fields
#[derive(Default, Debug, Serialize, Deserialize)]
pub struct NovalnetErrorResponse {
    pub status_code: u64,
    pub code: String,
    pub message: String,
    pub reason: Option<String>,
}

#[derive(Display, Debug, Serialize, Deserialize)]
#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum WebhookEventType {
    Payment,
    TransactionCapture,
    TransactionCancel,
    TransactionRefund,
    Chargeback,
    Credit,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct NovalnetWebhookEvent {
    pub checksum: String,
    pub tid: i64,
    pub parent_tid: Option<i64>,
    #[serde(rename = "type")]
    pub event_type: WebhookEventType,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(untagged)]
pub enum NovalnetWebhookTransactionData {
    SyncTransactionData(NovalnetSyncResponseTransactionData),
    CaptureTransactionData(NovalnetCaptureTransactionData),
    CancelTransactionData(NovalnetPaymentsResponseTransactionData),
    RefundsTransactionData(NovalnetRefundsTransactionData),
}
#[derive(Serialize, Deserialize, Debug)]
pub struct NovalnetWebhookNotificationResponse {
    pub event: NovalnetWebhookEvent,
    pub result: ResultData,
    pub transaction: NovalnetWebhookTransactionData,
}

pub fn is_refund_event(event_code: &WebhookEventType) -> bool {
    matches!(event_code, WebhookEventType::TransactionRefund)
}

pub fn get_incoming_webhook_event(
    status: WebhookEventType,
    transaction_status: NovalnetTransactionStatus,
) -> IncomingWebhookEvent {
    match status {
        WebhookEventType::Payment => match transaction_status {
            NovalnetTransactionStatus::Confirmed | NovalnetTransactionStatus::Success => {
                IncomingWebhookEvent::PaymentIntentSuccess
            }
            NovalnetTransactionStatus::OnHold => {
                IncomingWebhookEvent::PaymentIntentAuthorizationSuccess
            }
            NovalnetTransactionStatus::Pending => IncomingWebhookEvent::PaymentIntentProcessing,
            NovalnetTransactionStatus::Progress => IncomingWebhookEvent::EventNotSupported,
            _ => IncomingWebhookEvent::PaymentIntentFailure,
        },
        WebhookEventType::TransactionCapture => match transaction_status {
            NovalnetTransactionStatus::Confirmed | NovalnetTransactionStatus::Success => {
                IncomingWebhookEvent::PaymentIntentCaptureSuccess
            }
            _ => IncomingWebhookEvent::PaymentIntentCaptureFailure,
        },
        WebhookEventType::TransactionCancel => match transaction_status {
            NovalnetTransactionStatus::Deactivated => IncomingWebhookEvent::PaymentIntentCancelled,
            _ => IncomingWebhookEvent::PaymentIntentCancelFailure,
        },
        WebhookEventType::TransactionRefund => match transaction_status {
            NovalnetTransactionStatus::Confirmed | NovalnetTransactionStatus::Success => {
                IncomingWebhookEvent::RefundSuccess
            }
            _ => IncomingWebhookEvent::RefundFailure,
        },
        WebhookEventType::Chargeback => IncomingWebhookEvent::DisputeOpened,
        WebhookEventType::Credit => IncomingWebhookEvent::DisputeWon,
    }
}

pub fn reverse_string(s: &str) -> String {
    s.chars().rev().collect()
}

#[derive(Display, Debug, Serialize, Deserialize)]
pub enum WebhookDisputeStatus {
    DisputeOpened,
    DisputeWon,
    Unknown,
}

pub fn get_novalnet_dispute_status(status: WebhookEventType) -> WebhookDisputeStatus {
    match status {
        WebhookEventType::Chargeback => WebhookDisputeStatus::DisputeOpened,
        WebhookEventType::Credit => WebhookDisputeStatus::DisputeWon,
        _ => WebhookDisputeStatus::Unknown,
    }
}

pub fn option_to_result<T>(opt: Option<T>) -> Result<T, errors::ConnectorError> {
    opt.ok_or(errors::ConnectorError::WebhookBodyDecodingFailed)
}

impl TryFrom<&SetupMandateRouterData> for NovalnetPaymentsRequest {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(item: &SetupMandateRouterData) -> Result<Self, Self::Error> {
        let auth = NovalnetAuthType::try_from(&item.connector_auth_type)?;

        let merchant = NovalnetPaymentsRequestMerchant {
            signature: auth.product_activation_key,
            tariff: auth.tariff_id,
        };

        let enforce_3d = match item.auth_type {
            enums::AuthenticationType::ThreeDs => Some(1),
            enums::AuthenticationType::NoThreeDs => None,
        };
        let test_mode = get_test_mode(item.test_mode);
        let req_address = item.get_optional_billing();

        let billing = NovalnetPaymentsRequestBilling {
            house_no: item.get_optional_billing_line1(),
            street: item.get_optional_billing_line2(),
            city: item.get_optional_billing_city().map(Secret::new),
            zip: item.get_optional_billing_zip(),
            country_code: item.get_optional_billing_country(),
        };

        let email = item.get_billing_email().or(item.request.get_email())?;

        let customer = NovalnetPaymentsRequestCustomer {
            first_name: req_address.and_then(|addr| addr.get_optional_first_name()),
            last_name: req_address.and_then(|addr| addr.get_optional_last_name()),
            email,
            mobile: item.get_optional_billing_phone_number(),
            billing: Some(billing),
            // no_nc is used to indicate if minimal customer data is passed or not
            no_nc: MINIMAL_CUSTOMER_DATA_PASSED,
        };

        let lang = item
            .request
            .get_optional_language_from_browser_info()
            .unwrap_or(consts::DEFAULT_LOCALE.to_string().to_string());

        let custom = NovalnetCustom { lang };
        let hook_url = item.request.get_webhook_url()?;
        let return_url = item.request.get_return_url()?;
        let create_token = Some(CREATE_TOKEN_REQUIRED);

        match item.request.payment_method_data {
            PaymentMethodData::Card(ref req_card) => {
                let novalnet_card = NovalNetPaymentData::Card(NovalnetCard {
                    card_number: req_card.card_number.clone(),
                    card_expiry_month: req_card.card_exp_month.clone(),
                    card_expiry_year: req_card.card_exp_year.clone(),
                    card_cvc: req_card.card_cvc.clone(),
                    card_holder: item.get_billing_address()?.get_full_name()?,
                });

                let transaction = NovalnetPaymentsRequestTransaction {
                    test_mode,
                    payment_type: NovalNetPaymentTypes::CREDITCARD,
                    amount: NovalNetAmount::Int(0),
                    currency: item.request.currency,
                    order_no: item.connector_request_reference_id.clone(),
                    hook_url: Some(hook_url),
                    return_url: Some(return_url.clone()),
                    error_return_url: Some(return_url.clone()),
                    payment_data: Some(novalnet_card),
                    enforce_3d,
                    create_token,
                };

                Ok(Self {
                    merchant,
                    transaction,
                    customer,
                    custom,
                })
            }

            PaymentMethodData::Wallet(ref wallet_data) => match wallet_data {
                WalletDataPaymentMethod::GooglePay(ref req_wallet) => {
                    let novalnet_google_pay: NovalNetPaymentData =
                        NovalNetPaymentData::GooglePay(NovalnetGooglePay {
                            wallet_data: Secret::new(
                                req_wallet
                                    .tokenization_data
                                    .get_encrypted_google_pay_token()
                                    .change_context(errors::ConnectorError::MissingRequiredField {
                                        field_name: "gpay wallet_token",
                                    })?
                                    .clone(),
                            ),
                        });

                    let transaction = NovalnetPaymentsRequestTransaction {
                        test_mode,
                        payment_type: NovalNetPaymentTypes::GOOGLEPAY,
                        amount: NovalNetAmount::Int(0),
                        currency: item.request.currency,
                        order_no: item.connector_request_reference_id.clone(),
                        hook_url: Some(hook_url),
                        return_url: None,
                        error_return_url: None,
                        payment_data: Some(novalnet_google_pay),
                        enforce_3d,
                        create_token,
                    };

                    Ok(Self {
                        merchant,
                        transaction,
                        customer,
                        custom,
                    })
                }
                WalletDataPaymentMethod::ApplePay(payment_method_data) => {
                    let transaction = NovalnetPaymentsRequestTransaction {
                        test_mode,
                        payment_type: NovalNetPaymentTypes::APPLEPAY,
                        amount: NovalNetAmount::Int(0),
                        currency: item.request.currency,
                        order_no: item.connector_request_reference_id.clone(),
                        hook_url: Some(hook_url),
                        return_url: None,
                        error_return_url: None,
                        payment_data: Some(NovalNetPaymentData::ApplePay(NovalnetApplePay {
                            wallet_data: payment_method_data.get_applepay_decoded_payment_data()?,
                        })),
                        enforce_3d: None,
                        create_token,
                    };

                    Ok(Self {
                        merchant,
                        transaction,
                        customer,
                        custom,
                    })
                }
                WalletDataPaymentMethod::AliPayQr(_)
                | WalletDataPaymentMethod::AliPayRedirect(_)
                | WalletDataPaymentMethod::AliPayHkRedirect(_)
                | WalletDataPaymentMethod::AmazonPay(_)
                | WalletDataPaymentMethod::AmazonPayRedirect(_)
                | WalletDataPaymentMethod::Paysera(_)
                | WalletDataPaymentMethod::Skrill(_)
                | WalletDataPaymentMethod::BluecodeRedirect {}
                | WalletDataPaymentMethod::MomoRedirect(_)
                | WalletDataPaymentMethod::KakaoPayRedirect(_)
                | WalletDataPaymentMethod::GoPayRedirect(_)
                | WalletDataPaymentMethod::GcashRedirect(_)
                | WalletDataPaymentMethod::ApplePayRedirect(_)
                | WalletDataPaymentMethod::ApplePayThirdPartySdk(_)
                | WalletDataPaymentMethod::DanaRedirect {}
                | WalletDataPaymentMethod::GooglePayRedirect(_)
                | WalletDataPaymentMethod::GooglePayThirdPartySdk(_)
                | WalletDataPaymentMethod::MbWayRedirect(_)
                | WalletDataPaymentMethod::MobilePayRedirect(_)
                | WalletDataPaymentMethod::RevolutPay(_) => {
                    Err(errors::ConnectorError::NotImplemented(
                        utils::get_unimplemented_payment_method_error_message("novalnet"),
                    ))?
                }
                WalletDataPaymentMethod::PaypalRedirect(_) => {
                    let transaction = NovalnetPaymentsRequestTransaction {
                        test_mode,
                        payment_type: NovalNetPaymentTypes::PAYPAL,
                        amount: NovalNetAmount::Int(0),
                        currency: item.request.currency,
                        order_no: item.connector_request_reference_id.clone(),
                        hook_url: Some(hook_url),
                        return_url: Some(return_url.clone()),
                        error_return_url: Some(return_url.clone()),
                        payment_data: None,
                        enforce_3d: None,
                        create_token,
                    };

                    Ok(Self {
                        merchant,
                        transaction,
                        customer,
                        custom,
                    })
                }
                WalletDataPaymentMethod::PaypalSdk(_)
                | WalletDataPaymentMethod::Paze(_)
                | WalletDataPaymentMethod::SamsungPay(_)
                | WalletDataPaymentMethod::TwintRedirect {}
                | WalletDataPaymentMethod::VippsRedirect {}
                | WalletDataPaymentMethod::TouchNGoRedirect(_)
                | WalletDataPaymentMethod::WeChatPayRedirect(_)
                | WalletDataPaymentMethod::CashappQr(_)
                | WalletDataPaymentMethod::SwishQr(_)
                | WalletDataPaymentMethod::WeChatPayQr(_)
                | WalletDataPaymentMethod::Mifinity(_) => {
                    Err(errors::ConnectorError::NotImplemented(
                        utils::get_unimplemented_payment_method_error_message("novalnet"),
                    ))?
                }
            },
            _ => Err(errors::ConnectorError::NotImplemented(
                utils::get_unimplemented_payment_method_error_message("novalnet"),
            ))?,
        }
    }
}


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

impl ConnectorSpecifications for for Boku


// Struct: CeleroRefundRequest
// File: crates/hyperswitch_connectors/src/connectors/celero/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct CeleroRefundRequest


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

// Public submodules:
pub mod transformers;


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

pub struct CybersourcePaymentsCaptureRequest


// Function: deep_health_check
// File: crates/router/src/bin/scheduler.rs
// Module: router

pub fn deep_health_check(
    state: web::Data<routes::AppState>,
    service: web::Data<String>,
) -> impl actix_web::Responder


// File: crates/router/src/services/kafka/revenue_recovery.rs
// Module: router
// Public structs: 1

use common_utils::{id_type, types::MinorUnit};
use masking::Secret;
use time::OffsetDateTime;
#[derive(serde::Serialize, Debug)]
pub struct RevenueRecovery<'a> {
    pub merchant_id: &'a id_type::MerchantId,
    pub invoice_amount: MinorUnit,
    pub invoice_currency: &'a common_enums::Currency,
    #[serde(default, with = "time::serde::timestamp::nanoseconds::option")]
    pub invoice_due_date: Option<OffsetDateTime>,
    #[serde(with = "time::serde::timestamp::nanoseconds::option")]
    pub invoice_date: Option<OffsetDateTime>,
    pub billing_country: Option<&'a common_enums::CountryAlpha2>,
    pub billing_state: Option<Secret<String>>,
    pub billing_city: Option<Secret<String>>,
    pub attempt_amount: MinorUnit,
    pub attempt_currency: &'a common_enums::Currency,
    pub attempt_status: &'a common_enums::AttemptStatus,
    pub pg_error_code: Option<String>,
    pub network_advice_code: Option<String>,
    pub network_error_code: Option<String>,
    pub first_pg_error_code: Option<String>,
    pub first_network_advice_code: Option<String>,
    pub first_network_error_code: Option<String>,
    #[serde(default, with = "time::serde::timestamp::nanoseconds")]
    pub attempt_created_at: OffsetDateTime,
    pub payment_method_type: Option<&'a common_enums::PaymentMethod>,
    pub payment_method_subtype: Option<&'a common_enums::PaymentMethodType>,
    pub card_network: Option<&'a common_enums::CardNetwork>,
    pub card_issuer: Option<String>,
    pub retry_count: Option<i32>,
    pub payment_gateway: Option<common_enums::connector_enums::Connector>,
}

impl super::KafkaMessage for RevenueRecovery<'_> {
    fn key(&self) -> String {
        self.merchant_id.get_string_repr().to_string()
    }

    fn event_type(&self) -> crate::events::EventType {
        crate::events::EventType::RevenueRecovery
    }
}


// Implementation: impl ConnectorValidation for for Paybox
// File: crates/hyperswitch_connectors/src/connectors/paybox.rs
// Module: hyperswitch_connectors
// Methods: 1 total (0 public)

impl ConnectorValidation for for Paybox


// Struct: QueryTransactionResponse
// File: crates/hyperswitch_connectors/src/connectors/bamboraapac/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct QueryTransactionResponse


// File: crates/api_models/src/events/locker_migration.rs
// Module: api_models

use common_utils::events::ApiEventMetric;

use crate::locker_migration::MigrateCardResponse;

impl ApiEventMetric for MigrateCardResponse {
    fn get_api_event_type(&self) -> Option<common_utils::events::ApiEventsType> {
        Some(common_utils::events::ApiEventsType::RustLocker)
    }
}


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

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


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

pub struct FluidData


// File: crates/router/src/core/payment_link/validator.rs
// Module: router
// Public functions: 1

use actix_http::header;
use api_models::admin::PaymentLinkConfig;
use common_utils::validation::validate_domain_against_allowed_domains;
use error_stack::{report, ResultExt};
use url::Url;

use crate::{
    core::errors::{self, RouterResult},
    types::storage::PaymentLink,
};

pub fn validate_secure_payment_link_render_request(
    request_headers: &header::HeaderMap,
    payment_link: &PaymentLink,
    payment_link_config: &PaymentLinkConfig,
) -> RouterResult<()> {
    let link_id = payment_link.payment_link_id.clone();
    let allowed_domains = payment_link_config
        .allowed_domains
        .clone()
        .ok_or(report!(errors::ApiErrorResponse::InvalidRequestUrl))
        .attach_printable_lazy(|| {
            format!("Secure payment link was not generated for {link_id}\nmissing allowed_domains")
        })?;

    // Validate secure_link was generated
    if payment_link.secure_link.clone().is_none() {
        return Err(report!(errors::ApiErrorResponse::InvalidRequestUrl)).attach_printable_lazy(
            || format!("Secure payment link was not generated for {link_id}\nmissing secure_link"),
        );
    }

    // Fetch destination is "iframe"
    match request_headers.get("sec-fetch-dest").and_then(|v| v.to_str().ok()) {
        Some("iframe") => Ok(()),
        Some(requestor) => Err(report!(errors::ApiErrorResponse::AccessForbidden {
            resource: "payment_link".to_string(),
        }))
        .attach_printable_lazy(|| {
            format!(
                "Access to payment_link [{link_id}] is forbidden when requested through {requestor}",

            )
        }),
        None => Err(report!(errors::ApiErrorResponse::AccessForbidden {
            resource: "payment_link".to_string(),
        }))
        .attach_printable_lazy(|| {
            format!(
                "Access to payment_link [{link_id}] is forbidden when sec-fetch-dest is not present in request headers",

            )
        }),
    }?;

    // Validate origin / referer
    let domain_in_req = {
        let origin_or_referer = request_headers
            .get("origin")
            .or_else(|| request_headers.get("referer"))
            .and_then(|v| v.to_str().ok())
            .ok_or_else(|| {
                report!(errors::ApiErrorResponse::AccessForbidden {
                    resource: "payment_link".to_string(),
                })
            })
            .attach_printable_lazy(|| {
                format!(
                    "Access to payment_link [{link_id}] is forbidden when origin or referer is not present in request headers",

                )
            })?;

        let url = Url::parse(origin_or_referer)
            .map_err(|_| {
                report!(errors::ApiErrorResponse::AccessForbidden {
                    resource: "payment_link".to_string(),
                })
            })
            .attach_printable_lazy(|| {
                format!("Invalid URL found in request headers {origin_or_referer}")
            })?;

        url.host_str()
            .and_then(|host| url.port().map(|port| format!("{host}:{port}")))
            .or_else(|| url.host_str().map(String::from))
            .ok_or_else(|| {
                report!(errors::ApiErrorResponse::AccessForbidden {
                    resource: "payment_link".to_string(),
                })
            })
            .attach_printable_lazy(|| {
                format!("host or port not found in request headers {url:?}")
            })?
    };

    if validate_domain_against_allowed_domains(&domain_in_req, allowed_domains) {
        Ok(())
    } else {
        Err(report!(errors::ApiErrorResponse::AccessForbidden {
            resource: "payment_link".to_string(),
        }))
        .attach_printable_lazy(|| {
            format!(
                "Access to payment_link [{link_id}] is forbidden from requestor - {domain_in_req}",
            )
        })
    }
}


// Function: payment_intent_list
// File: crates/router/src/compatibility/stripe/payment_intents.rs
// Module: router

pub fn payment_intent_list(
    state: web::Data<routes::AppState>,
    req: HttpRequest,
    payload: web::Query<types::StripePaymentListConstraints>,
) -> HttpResponse


// Struct: DlocalPaymentsSyncResponse
// File: crates/hyperswitch_connectors/src/connectors/dlocal/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct DlocalPaymentsSyncResponse


// Function: do_retry
// File: crates/router/src/core/payouts/retry.rs
// Module: router

pub fn do_retry(
    state: &routes::SessionState,
    connector: api::ConnectorData,
    merchant_context: &domain::MerchantContext,
    payout_data: &mut PayoutData,
) -> RouterResult<()>


// Implementation: impl api::Payment for for Multisafepay
// File: crates/hyperswitch_connectors/src/connectors/multisafepay.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::Payment for for Multisafepay


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

use async_bb8_diesel::AsyncConnection;
use common_utils::{
    encryption::Encryption,
    ext_traits::{AsyncExt, ByteSliceExt, Encode},
    types::keymanager::KeyManagerState,
};
use error_stack::{report, ResultExt};
use router_env::{instrument, tracing};
#[cfg(feature = "accounts_cache")]
use storage_impl::redis::cache;
use storage_impl::redis::kv_store::RedisConnInterface;

use super::{MockDb, Store};
use crate::{
    connection,
    core::errors::{self, CustomResult},
    types::{
        self,
        domain::{
            self,
            behaviour::{Conversion, ReverseConversion},
        },
        storage,
    },
};

#[async_trait::async_trait]
pub trait ConnectorAccessToken {
    async fn get_access_token(
        &self,
        merchant_id: &common_utils::id_type::MerchantId,
        merchant_connector_id_or_connector_name: &str,
    ) -> CustomResult<Option<types::AccessToken>, errors::StorageError>;

    async fn set_access_token(
        &self,
        merchant_id: &common_utils::id_type::MerchantId,
        merchant_connector_id_or_connector_name: &str,
        access_token: types::AccessToken,
    ) -> CustomResult<(), errors::StorageError>;
}

#[async_trait::async_trait]
impl ConnectorAccessToken for Store {
    #[instrument(skip_all)]
    async fn get_access_token(
        &self,
        merchant_id: &common_utils::id_type::MerchantId,
        merchant_connector_id_or_connector_name: &str,
    ) -> CustomResult<Option<types::AccessToken>, errors::StorageError> {
        //TODO: Handle race condition
        // This function should acquire a global lock on some resource, if access token is already
        // being refreshed by other request then wait till it finishes and use the same access token
        let key = common_utils::access_token::create_access_token_key(
            merchant_id,
            merchant_connector_id_or_connector_name,
        );

        let maybe_token = self
            .get_redis_conn()
            .map_err(Into::<errors::StorageError>::into)?
            .get_key::<Option<Vec<u8>>>(&key.into())
            .await
            .change_context(errors::StorageError::KVError)
            .attach_printable("DB error when getting access token")?;

        let access_token = maybe_token
            .map(|token| token.parse_struct::<types::AccessToken>("AccessToken"))
            .transpose()
            .change_context(errors::StorageError::DeserializationFailed)?;

        Ok(access_token)
    }

    #[instrument(skip_all)]
    async fn set_access_token(
        &self,
        merchant_id: &common_utils::id_type::MerchantId,
        merchant_connector_id_or_connector_name: &str,
        access_token: types::AccessToken,
    ) -> CustomResult<(), errors::StorageError> {
        let key = common_utils::access_token::create_access_token_key(
            merchant_id,
            merchant_connector_id_or_connector_name,
        );
        let serialized_access_token = access_token
            .encode_to_string_of_json()
            .change_context(errors::StorageError::SerializationFailed)?;
        self.get_redis_conn()
            .map_err(Into::<errors::StorageError>::into)?
            .set_key_with_expiry(&key.into(), serialized_access_token, access_token.expires)
            .await
            .change_context(errors::StorageError::KVError)
    }
}

#[async_trait::async_trait]
impl ConnectorAccessToken for MockDb {
    async fn get_access_token(
        &self,
        _merchant_id: &common_utils::id_type::MerchantId,
        _merchant_connector_id_or_connector_name: &str,
    ) -> CustomResult<Option<types::AccessToken>, errors::StorageError> {
        Ok(None)
    }

    async fn set_access_token(
        &self,
        _merchant_id: &common_utils::id_type::MerchantId,
        _merchant_connector_id_or_connector_name: &str,
        _access_token: types::AccessToken,
    ) -> CustomResult<(), errors::StorageError> {
        Ok(())
    }
}

#[async_trait::async_trait]
pub trait MerchantConnectorAccountInterface
where
    domain::MerchantConnectorAccount: Conversion<
        DstType = storage::MerchantConnectorAccount,
        NewDstType = storage::MerchantConnectorAccountNew,
    >,
{
    #[cfg(feature = "v1")]
    async fn find_merchant_connector_account_by_merchant_id_connector_label(
        &self,
        state: &KeyManagerState,
        merchant_id: &common_utils::id_type::MerchantId,
        connector_label: &str,
        key_store: &domain::MerchantKeyStore,
    ) -> CustomResult<domain::MerchantConnectorAccount, errors::StorageError>;

    #[cfg(feature = "v1")]
    async fn find_merchant_connector_account_by_profile_id_connector_name(
        &self,
        state: &KeyManagerState,
        profile_id: &common_utils::id_type::ProfileId,
        connector_name: &str,
        key_store: &domain::MerchantKeyStore,
    ) -> CustomResult<domain::MerchantConnectorAccount, errors::StorageError>;

    #[cfg(feature = "v1")]
    async fn find_merchant_connector_account_by_merchant_id_connector_name(
        &self,
        state: &KeyManagerState,
        merchant_id: &common_utils::id_type::MerchantId,
        connector_name: &str,
        key_store: &domain::MerchantKeyStore,
    ) -> CustomResult<Vec<domain::MerchantConnectorAccount>, errors::StorageError>;

    async fn insert_merchant_connector_account(
        &self,
        state: &KeyManagerState,
        t: domain::MerchantConnectorAccount,
        key_store: &domain::MerchantKeyStore,
    ) -> CustomResult<domain::MerchantConnectorAccount, errors::StorageError>;

    #[cfg(feature = "v1")]
    async fn find_by_merchant_connector_account_merchant_id_merchant_connector_id(
        &self,
        state: &KeyManagerState,
        merchant_id: &common_utils::id_type::MerchantId,
        merchant_connector_id: &common_utils::id_type::MerchantConnectorAccountId,
        key_store: &domain::MerchantKeyStore,
    ) -> CustomResult<domain::MerchantConnectorAccount, errors::StorageError>;

    #[cfg(feature = "v2")]
    async fn find_merchant_connector_account_by_id(
        &self,
        state: &KeyManagerState,
        id: &common_utils::id_type::MerchantConnectorAccountId,
        key_store: &domain::MerchantKeyStore,
    ) -> CustomResult<domain::MerchantConnectorAccount, errors::StorageError>;

    async fn find_merchant_connector_account_by_merchant_id_and_disabled_list(
        &self,
        state: &KeyManagerState,
        merchant_id: &common_utils::id_type::MerchantId,
        get_disabled: bool,
        key_store: &domain::MerchantKeyStore,
    ) -> CustomResult<domain::MerchantConnectorAccounts, errors::StorageError>;

    #[cfg(all(feature = "olap", feature = "v2"))]
    async fn list_connector_account_by_profile_id(
        &self,
        state: &KeyManagerState,
        profile_id: &common_utils::id_type::ProfileId,
        key_store: &domain::MerchantKeyStore,
    ) -> CustomResult<Vec<domain::MerchantConnectorAccount>, errors::StorageError>;

    async fn list_enabled_connector_accounts_by_profile_id(
        &self,
        state: &KeyManagerState,
        profile_id: &common_utils::id_type::ProfileId,
        key_store: &domain::MerchantKeyStore,
        connector_type: common_enums::ConnectorType,
    ) -> CustomResult<Vec<domain::MerchantConnectorAccount>, errors::StorageError>;

    async fn update_merchant_connector_account(
        &self,
        state: &KeyManagerState,
        this: domain::MerchantConnectorAccount,
        merchant_connector_account: storage::MerchantConnectorAccountUpdateInternal,
        key_store: &domain::MerchantKeyStore,
    ) -> CustomResult<domain::MerchantConnectorAccount, errors::StorageError>;

    async fn update_multiple_merchant_connector_accounts(
        &self,
        this: Vec<(
            domain::MerchantConnectorAccount,
            storage::MerchantConnectorAccountUpdateInternal,
        )>,
    ) -> CustomResult<(), errors::StorageError>;

    #[cfg(feature = "v1")]
    async fn delete_merchant_connector_account_by_merchant_id_merchant_connector_id(
        &self,
        merchant_id: &common_utils::id_type::MerchantId,
        merchant_connector_id: &common_utils::id_type::MerchantConnectorAccountId,
    ) -> CustomResult<bool, errors::StorageError>;

    #[cfg(feature = "v2")]
    async fn delete_merchant_connector_account_by_id(
        &self,
        id: &common_utils::id_type::MerchantConnectorAccountId,
    ) -> CustomResult<bool, errors::StorageError>;
}

#[async_trait::async_trait]
impl MerchantConnectorAccountInterface for Store {
    #[cfg(feature = "v1")]
    #[instrument(skip_all)]
    async fn find_merchant_connector_account_by_merchant_id_connector_label(
        &self,
        state: &KeyManagerState,
        merchant_id: &common_utils::id_type::MerchantId,
        connector_label: &str,
        key_store: &domain::MerchantKeyStore,
    ) -> CustomResult<domain::MerchantConnectorAccount, errors::StorageError> {
        let find_call = || async {
            let conn = connection::pg_accounts_connection_read(self).await?;
            storage::MerchantConnectorAccount::find_by_merchant_id_connector(
                &conn,
                merchant_id,
                connector_label,
            )
            .await
            .map_err(|error| report!(errors::StorageError::from(error)))
        };

        #[cfg(not(feature = "accounts_cache"))]
        {
            find_call()
                .await?
                .convert(state, key_store.key.get_inner(), merchant_id.clone().into())
                .await
                .change_context(errors::StorageError::DeserializationFailed)
        }

        #[cfg(feature = "accounts_cache")]
        {
            cache::get_or_populate_in_memory(
                self,
                &format!("{}_{}", merchant_id.get_string_repr(), connector_label),
                find_call,
                &cache::ACCOUNTS_CACHE,
            )
            .await
            .async_and_then(|item| async {
                item.convert(
                    state,
                    key_store.key.get_inner(),
                    key_store.merchant_id.clone().into(),
                )
                .await
                .change_context(errors::StorageError::DecryptionError)
            })
            .await
        }
    }

    #[cfg(feature = "v1")]
    #[instrument(skip_all)]
    async fn find_merchant_connector_account_by_profile_id_connector_name(
        &self,
        state: &KeyManagerState,
        profile_id: &common_utils::id_type::ProfileId,
        connector_name: &str,
        key_store: &domain::MerchantKeyStore,
    ) -> CustomResult<domain::MerchantConnectorAccount, errors::StorageError> {
        let find_call = || async {
            let conn = connection::pg_accounts_connection_read(self).await?;
            storage::MerchantConnectorAccount::find_by_profile_id_connector_name(
                &conn,
                profile_id,
                connector_name,
            )
            .await
            .map_err(|error| report!(errors::StorageError::from(error)))
        };

        #[cfg(not(feature = "accounts_cache"))]
        {
            find_call()
                .await?
                .convert(
                    state,
                    key_store.key.get_inner(),
                    key_store.merchant_id.clone().into(),
                )
                .await
                .change_context(errors::StorageError::DeserializationFailed)
        }

        #[cfg(feature = "accounts_cache")]
        {
            cache::get_or_populate_in_memory(
                self,
                &format!("{}_{}", profile_id.get_string_repr(), connector_name),
                find_call,
                &cache::ACCOUNTS_CACHE,
            )
            .await
            .async_and_then(|item| async {
                item.convert(
                    state,
                    key_store.key.get_inner(),
                    key_store.merchant_id.clone().into(),
                )
                .await
                .change_context(errors::StorageError::DecryptionError)
            })
            .await
        }
    }

    #[cfg(feature = "v1")]
    #[instrument(skip_all)]
    async fn find_merchant_connector_account_by_merchant_id_connector_name(
        &self,
        state: &KeyManagerState,
        merchant_id: &common_utils::id_type::MerchantId,
        connector_name: &str,
        key_store: &domain::MerchantKeyStore,
    ) -> CustomResult<Vec<domain::MerchantConnectorAccount>, errors::StorageError> {
        let conn = connection::pg_accounts_connection_read(self).await?;
        storage::MerchantConnectorAccount::find_by_merchant_id_connector_name(
            &conn,
            merchant_id,
            connector_name,
        )
        .await
        .map_err(|error| report!(errors::StorageError::from(error)))
        .async_and_then(|items| async {
            let mut output = Vec::with_capacity(items.len());
            for item in items.into_iter() {
                output.push(
                    item.convert(
                        state,
                        key_store.key.get_inner(),
                        key_store.merchant_id.clone().into(),
                    )
                    .await
                    .change_context(errors::StorageError::DecryptionError)?,
                )
            }
            Ok(output)
        })
        .await
    }

    #[instrument(skip_all)]
    #[cfg(feature = "v1")]
    async fn find_by_merchant_connector_account_merchant_id_merchant_connector_id(
        &self,
        state: &KeyManagerState,
        merchant_id: &common_utils::id_type::MerchantId,
        merchant_connector_id: &common_utils::id_type::MerchantConnectorAccountId,
        key_store: &domain::MerchantKeyStore,
    ) -> CustomResult<domain::MerchantConnectorAccount, errors::StorageError> {
        let find_call = || async {
            let conn = connection::pg_accounts_connection_read(self).await?;
            storage::MerchantConnectorAccount::find_by_merchant_id_merchant_connector_id(
                &conn,
                merchant_id,
                merchant_connector_id,
            )
            .await
            .map_err(|error| report!(errors::StorageError::from(error)))
        };

        #[cfg(not(feature = "accounts_cache"))]
        {
            find_call()
                .await?
                .convert(
                    state,
                    key_store.key.get_inner(),
                    key_store.merchant_id.clone().into(),
                )
                .await
                .change_context(errors::StorageError::DecryptionError)
        }

        #[cfg(feature = "accounts_cache")]
        {
            cache::get_or_populate_in_memory(
                self,
                &format!(
                    "{}_{}",
                    merchant_id.get_string_repr(),
                    merchant_connector_id.get_string_repr()
                ),
                find_call,
                &cache::ACCOUNTS_CACHE,
            )
            .await?
            .convert(
                state,
                key_store.key.get_inner(),
                key_store.merchant_id.clone().into(),
            )
            .await
            .change_context(errors::StorageError::DecryptionError)
        }
    }

    #[instrument(skip_all)]
    #[cfg(feature = "v2")]
    async fn find_merchant_connector_account_by_id(
        &self,
        state: &KeyManagerState,
        id: &common_utils::id_type::MerchantConnectorAccountId,
        key_store: &domain::MerchantKeyStore,
    ) -> CustomResult<domain::MerchantConnectorAccount, errors::StorageError> {
        let find_call = || async {
            let conn = connection::pg_accounts_connection_read(self).await?;
            storage::MerchantConnectorAccount::find_by_id(&conn, id)
                .await
                .map_err(|error| report!(errors::StorageError::from(error)))
        };

        #[cfg(not(feature = "accounts_cache"))]
        {
            find_call()
                .await?
                .convert(
                    state,
                    key_store.key.get_inner(),
                    key_store.merchant_id.clone(),
                )
                .await
                .change_context(errors::StorageError::DecryptionError)
        }

        #[cfg(feature = "accounts_cache")]
        {
            cache::get_or_populate_in_memory(
                self,
                id.get_string_repr(),
                find_call,
                &cache::ACCOUNTS_CACHE,
            )
            .await?
            .convert(
                state,
                key_store.key.get_inner(),
                common_utils::types::keymanager::Identifier::Merchant(
                    key_store.merchant_id.clone(),
                ),
            )
            .await
            .change_context(errors::StorageError::DecryptionError)
        }
    }

    #[instrument(skip_all)]
    async fn insert_merchant_connector_account(
        &self,
        state: &KeyManagerState,
        t: domain::MerchantConnectorAccount,
        key_store: &domain::MerchantKeyStore,
    ) -> CustomResult<domain::MerchantConnectorAccount, errors::StorageError> {
        let conn = connection::pg_accounts_connection_write(self).await?;
        t.construct_new()
            .await
            .change_context(errors::StorageError::EncryptionError)?
            .insert(&conn)
            .await
            .map_err(|error| report!(errors::StorageError::from(error)))
            .async_and_then(|item| async {
                item.convert(
                    state,
                    key_store.key.get_inner(),
                    key_store.merchant_id.clone().into(),
                )
                .await
                .change_context(errors::StorageError::DecryptionError)
            })
            .await
    }

    async fn list_enabled_connector_accounts_by_profile_id(
        &self,
        state: &KeyManagerState,
        profile_id: &common_utils::id_type::ProfileId,
        key_store: &domain::MerchantKeyStore,
        connector_type: common_enums::ConnectorType,
    ) -> CustomResult<Vec<domain::MerchantConnectorAccount>, errors::StorageError> {
        let conn = connection::pg_accounts_connection_read(self).await?;

        storage::MerchantConnectorAccount::list_enabled_by_profile_id(
            &conn,
            profile_id,
            connector_type,
        )
        .await
        .map_err(|error| report!(errors::StorageError::from(error)))
        .async_and_then(|items| async {
            let mut output = Vec::with_capacity(items.len());
            for item in items.into_iter() {
                output.push(
                    item.convert(
                        state,
                        key_store.key.get_inner(),
                        key_store.merchant_id.clone().into(),
                    )
                    .await
                    .change_context(errors::StorageError::DecryptionError)?,
                )
            }
            Ok(output)
        })
        .await
    }

    #[instrument(skip_all)]
    async fn find_merchant_connector_account_by_merchant_id_and_disabled_list(
        &self,
        state: &KeyManagerState,
        merchant_id: &common_utils::id_type::MerchantId,
        get_disabled: bool,
        key_store: &domain::MerchantKeyStore,
    ) -> CustomResult<domain::MerchantConnectorAccounts, errors::StorageError> {
        let conn = connection::pg_accounts_connection_read(self).await?;
        let merchant_connector_account_vec =
            storage::MerchantConnectorAccount::find_by_merchant_id(
                &conn,
                merchant_id,
                get_disabled,
            )
            .await
            .map_err(|error| report!(errors::StorageError::from(error)))
            .async_and_then(|items| async {
                let mut output = Vec::with_capacity(items.len());
                for item in items.into_iter() {
                    output.push(
                        item.convert(
                            state,
                            key_store.key.get_inner(),
                            key_store.merchant_id.clone().into(),
                        )
                        .await
                        .change_context(errors::StorageError::DecryptionError)?,
                    )
                }
                Ok(output)
            })
            .await?;
        Ok(domain::MerchantConnectorAccounts::new(
            merchant_connector_account_vec,
        ))
    }

    #[instrument(skip_all)]
    #[cfg(all(feature = "olap", feature = "v2"))]
    async fn list_connector_account_by_profile_id(
        &self,
        state: &KeyManagerState,
        profile_id: &common_utils::id_type::ProfileId,
        key_store: &domain::MerchantKeyStore,
    ) -> CustomResult<Vec<domain::MerchantConnectorAccount>, errors::StorageError> {
        let conn = connection::pg_accounts_connection_read(self).await?;
        storage::MerchantConnectorAccount::list_by_profile_id(&conn, profile_id)
            .await
            .map_err(|error| report!(errors::StorageError::from(error)))
            .async_and_then(|items| async {
                let mut output = Vec::with_capacity(items.len());
                for item in items.into_iter() {
                    output.push(
                        item.convert(
                            state,
                            key_store.key.get_inner(),
                            key_store.merchant_id.clone().into(),
                        )
                        .await
                        .change_context(errors::StorageError::DecryptionError)?,
                    )
                }
                Ok(output)
            })
            .await
    }

    #[instrument(skip_all)]
    async fn update_multiple_merchant_connector_accounts(
        &self,
        merchant_connector_accounts: Vec<(
            domain::MerchantConnectorAccount,
            storage::MerchantConnectorAccountUpdateInternal,
        )>,
    ) -> CustomResult<(), errors::StorageError> {
        let conn = connection::pg_accounts_connection_write(self).await?;

        async fn update_call(
            connection: &diesel_models::PgPooledConn,
            (merchant_connector_account, mca_update): (
                domain::MerchantConnectorAccount,
                storage::MerchantConnectorAccountUpdateInternal,
            ),
        ) -> Result<(), error_stack::Report<storage_impl::errors::StorageError>> {
            Conversion::convert(merchant_connector_account)
                .await
                .change_context(errors::StorageError::EncryptionError)?
                .update(connection, mca_update)
                .await
                .map_err(|error| report!(errors::StorageError::from(error)))?;
            Ok(())
        }

        conn.transaction_async(|connection_pool| async move {
            for (merchant_connector_account, update_merchant_connector_account) in
                merchant_connector_accounts
            {
                #[cfg(feature = "v1")]
                let _connector_name = merchant_connector_account.connector_name.clone();

                #[cfg(feature = "v2")]
                let _connector_name = merchant_connector_account.connector_name.to_string();

                let _profile_id = merchant_connector_account.profile_id.clone();

                let _merchant_id = merchant_connector_account.merchant_id.clone();
                let _merchant_connector_id = merchant_connector_account.get_id().clone();

                let update = update_call(
                    &connection_pool,
                    (
                        merchant_connector_account,
                        update_merchant_connector_account,
                    ),
                );

                #[cfg(feature = "accounts_cache")]
                // Redact all caches as any of might be used because of backwards compatibility
                Box::pin(cache::publish_and_redact_multiple(
                    self,
                    [
                        cache::CacheKind::Accounts(
                            format!("{}_{}", _profile_id.get_string_repr(), _connector_name).into(),
                        ),
                        cache::CacheKind::Accounts(
                            format!(
                                "{}_{}",
                                _merchant_id.get_string_repr(),
                                _merchant_connector_id.get_string_repr()
                            )
                            .into(),
                        ),
                        cache::CacheKind::CGraph(
                            format!(
                                "cgraph_{}_{}",
                                _merchant_id.get_string_repr(),
                                _profile_id.get_string_repr()
                            )
                            .into(),
                        ),
                    ],
                    || update,
                ))
                .await
                .map_err(|error| {
                    // Returning `DatabaseConnectionError` after logging the actual error because
                    // -> it is not possible to get the underlying from `error_stack::Report<C>`
                    // -> it is not possible to write a `From` impl to convert the `diesel::result::Error` to `error_stack::Report<StorageError>`
                    //    because of Rust's orphan rules
                    router_env::logger::error!(
                        ?error,
                        "DB transaction for updating multiple merchant connector account failed"
                    );
                    errors::StorageError::DatabaseConnectionError
                })?;

                #[cfg(not(feature = "accounts_cache"))]
                {
                    update.await.map_err(|error| {
                        // Returning `DatabaseConnectionError` after logging the actual error because
                        // -> it is not possible to get the underlying from `error_stack::Report<C>`
                        // -> it is not possible to write a `From` impl to convert the `diesel::result::Error` to `error_stack::Report<StorageError>`
                        //    because of Rust's orphan rules
                        router_env::logger::error!(
                            ?error,
                            "DB transaction for updating multiple merchant connector account failed"
                        );
                        errors::StorageError::DatabaseConnectionError
                    })?;
                }
            }
            Ok::<_, errors::StorageError>(())
        })
        .await?;
        Ok(())
    }

    #[instrument(skip_all)]
    #[cfg(feature = "v1")]
    async fn update_merchant_connector_account(
        &self,
        state: &KeyManagerState,
        this: domain::MerchantConnectorAccount,
        merchant_connector_account: storage::MerchantConnectorAccountUpdateInternal,
        key_store: &domain::MerchantKeyStore,
    ) -> CustomResult<domain::MerchantConnectorAccount, errors::StorageError> {
        let _connector_name = this.connector_name.clone();
        let _profile_id = this.profile_id.clone();

        let _merchant_id = this.merchant_id.clone();
        let _merchant_connector_id = this.merchant_connector_id.clone();

        let update_call = || async {
            let conn = connection::pg_accounts_connection_write(self).await?;
            Conversion::convert(this)
                .await
                .change_context(errors::StorageError::EncryptionError)?
                .update(&conn, merchant_connector_account)
                .await
                .map_err(|error| report!(errors::StorageError::from(error)))
                .async_and_then(|item| async {
                    item.convert(
                        state,
                        key_store.key.get_inner(),
                        key_store.merchant_id.clone().into(),
                    )
                    .await
                    .change_context(errors::StorageError::DecryptionError)
                })
                .await
        };

        #[cfg(feature = "accounts_cache")]
        {
            // Redact all caches as any of might be used because of backwards compatibility
            cache::publish_and_redact_multiple(
                self,
                [
                    cache::CacheKind::Accounts(
                        format!("{}_{}", _profile_id.get_string_repr(), _connector_name).into(),
                    ),
                    cache::CacheKind::Accounts(
                        format!(
                            "{}_{}",
                            _merchant_id.get_string_repr(),
                            _merchant_connector_id.get_string_repr()
                        )
                        .into(),
                    ),
                    cache::CacheKind::CGraph(
                        format!(
                            "cgraph_{}_{}",
                            _merchant_id.get_string_repr(),
                            _profile_id.get_string_repr()
                        )
                        .into(),
                    ),
                    cache::CacheKind::PmFiltersCGraph(
                        format!(
                            "pm_filters_cgraph_{}_{}",
                            _merchant_id.get_string_repr(),
                            _profile_id.get_string_repr(),
                        )
                        .into(),
                    ),
                ],
                update_call,
            )
            .await
        }

        #[cfg(not(feature = "accounts_cache"))]
        {
            update_call().await
        }
    }

    #[instrument(skip_all)]
    #[cfg(feature = "v2")]
    async fn update_merchant_connector_account(
        &self,
        state: &KeyManagerState,
        this: domain::MerchantConnectorAccount,
        merchant_connector_account: storage::MerchantConnectorAccountUpdateInternal,
        key_store: &domain::MerchantKeyStore,
    ) -> CustomResult<domain::MerchantConnectorAccount, errors::StorageError> {
        let _connector_name = this.connector_name;
        let _profile_id = this.profile_id.clone();

        let _merchant_id = this.merchant_id.clone();
        let _merchant_connector_id = this.get_id().clone();

        let update_call = || async {
            let conn = connection::pg_accounts_connection_write(self).await?;
            Conversion::convert(this)
                .await
                .change_context(errors::StorageError::EncryptionError)?
                .update(&conn, merchant_connector_account)
                .await
                .map_err(|error| report!(errors::StorageError::from(error)))
                .async_and_then(|item| async {
                    item.convert(
                        state,
                        key_store.key.get_inner(),
                        common_utils::types::keymanager::Identifier::Merchant(
                            key_store.merchant_id.clone(),
                        ),
                    )
                    .await
                    .change_context(errors::StorageError::DecryptionError)
                })
                .await
        };

        #[cfg(feature = "accounts_cache")]
        {
            // Redact all caches as any of might be used because of backwards compatibility
            cache::publish_and_redact_multiple(
                self,
                [
                    cache::CacheKind::Accounts(
                        format!("{}_{}", _profile_id.get_string_repr(), _connector_name).into(),
                    ),
                    cache::CacheKind::Accounts(
                        _merchant_connector_id.get_string_repr().to_string().into(),
                    ),
                    cache::CacheKind::CGraph(
                        format!(
                            "cgraph_{}_{}",
                            _merchant_id.get_string_repr(),
                            _profile_id.get_string_repr()
                        )
                        .into(),
                    ),
                    cache::CacheKind::PmFiltersCGraph(
                        format!(
                            "pm_filters_cgraph_{}_{}",
                            _merchant_id.get_string_repr(),
                            _profile_id.get_string_repr()
                        )
                        .into(),
                    ),
                ],
                update_call,
            )
            .await
        }

        #[cfg(not(feature = "accounts_cache"))]
        {
            update_call().await
        }
    }

    #[instrument(skip_all)]
    #[cfg(feature = "v1")]
    async fn delete_merchant_connector_account_by_merchant_id_merchant_connector_id(
        &self,
        merchant_id: &common_utils::id_type::MerchantId,
        merchant_connector_id: &common_utils::id_type::MerchantConnectorAccountId,
    ) -> CustomResult<bool, errors::StorageError> {
        let conn = connection::pg_accounts_connection_write(self).await?;
        let delete_call = || async {
            storage::MerchantConnectorAccount::delete_by_merchant_id_merchant_connector_id(
                &conn,
                merchant_id,
                merchant_connector_id,
            )
            .await
            .map_err(|error| report!(errors::StorageError::from(error)))
        };

        #[cfg(feature = "accounts_cache")]
        {
            // We need to fetch mca here because the key that's saved in cache in
            // {merchant_id}_{connector_label}.
            // Used function from storage model to reuse the connection that made here instead of
            // creating new.

            let mca = storage::MerchantConnectorAccount::find_by_merchant_id_merchant_connector_id(
                &conn,
                merchant_id,
                merchant_connector_id,
            )
            .await
            .map_err(|error| report!(errors::StorageError::from(error)))?;

            let _profile_id = mca.profile_id.ok_or(errors::StorageError::ValueNotFound(
                "profile_id".to_string(),
            ))?;

            cache::publish_and_redact_multiple(
                self,
                [
                    cache::CacheKind::Accounts(
                        format!(
                            "{}_{}",
                            mca.merchant_id.get_string_repr(),
                            _profile_id.get_string_repr()
                        )
                        .into(),
                    ),
                    cache::CacheKind::CGraph(
                        format!(
                            "cgraph_{}_{}",
                            mca.merchant_id.get_string_repr(),
                            _profile_id.get_string_repr()
                        )
                        .into(),
                    ),
                    cache::CacheKind::PmFiltersCGraph(
                        format!(
                            "pm_filters_cgraph_{}_{}",
                            mca.merchant_id.get_string_repr(),
                            _profile_id.get_string_repr()
                        )
                        .into(),
                    ),
                ],
                delete_call,
            )
            .await
        }

        #[cfg(not(feature = "accounts_cache"))]
        {
            delete_call().await
        }
    }

    #[instrument(skip_all)]
    #[cfg(feature = "v2")]
    async fn delete_merchant_connector_account_by_id(
        &self,
        id: &common_utils::id_type::MerchantConnectorAccountId,
    ) -> CustomResult<bool, errors::StorageError> {
        let conn = connection::pg_accounts_connection_write(self).await?;
        let delete_call = || async {
            storage::MerchantConnectorAccount::delete_by_id(&conn, id)
                .await
                .map_err(|error| report!(errors::StorageError::from(error)))
        };

        #[cfg(feature = "accounts_cache")]
        {
            // We need to fetch mca here because the key that's saved in cache in
            // {merchant_id}_{connector_label}.
            // Used function from storage model to reuse the connection that made here instead of
            // creating new.

            let mca = storage::MerchantConnectorAccount::find_by_id(&conn, id)
                .await
                .map_err(|error| report!(errors::StorageError::from(error)))?;

            let _profile_id = mca.profile_id;

            cache::publish_and_redact_multiple(
                self,
                [
                    cache::CacheKind::Accounts(
                        format!(
                            "{}_{}",
                            mca.merchant_id.get_string_repr(),
                            _profile_id.get_string_repr()
                        )
                        .into(),
                    ),
                    cache::CacheKind::CGraph(
                        format!(
                            "cgraph_{}_{}",
                            mca.merchant_id.get_string_repr(),
                            _profile_id.get_string_repr()
                        )
                        .into(),
                    ),
                    cache::CacheKind::PmFiltersCGraph(
                        format!(
                            "pm_filters_cgraph_{}_{}",
                            mca.merchant_id.get_string_repr(),
                            _profile_id.get_string_repr()
                        )
                        .into(),
                    ),
                ],
                delete_call,
            )
            .await
        }

        #[cfg(not(feature = "accounts_cache"))]
        {
            delete_call().await
        }
    }
}

#[async_trait::async_trait]
impl MerchantConnectorAccountInterface for MockDb {
    async fn update_multiple_merchant_connector_accounts(
        &self,
        _merchant_connector_accounts: Vec<(
            domain::MerchantConnectorAccount,
            storage::MerchantConnectorAccountUpdateInternal,
        )>,
    ) -> CustomResult<(), errors::StorageError> {
        // No need to implement this function for `MockDb` as this function will be removed after the
        // apple pay certificate migration
        Err(errors::StorageError::MockDbError)?
    }
    #[cfg(feature = "v1")]
    async fn find_merchant_connector_account_by_merchant_id_connector_label(
        &self,
        state: &KeyManagerState,
        merchant_id: &common_utils::id_type::MerchantId,
        connector: &str,
        key_store: &domain::MerchantKeyStore,
    ) -> CustomResult<domain::MerchantConnectorAccount, errors::StorageError> {
        match self
            .merchant_connector_accounts
            .lock()
            .await
            .iter()
            .find(|account| {
                account.merchant_id == *merchant_id
                    && account.connector_label == Some(connector.to_string())
            })
            .cloned()
            .async_map(|account| async {
                account
                    .convert(
                        state,
                        key_store.key.get_inner(),
                        key_store.merchant_id.clone().into(),
                    )
                    .await
                    .change_context(errors::StorageError::DecryptionError)
            })
            .await
        {
            Some(result) => result,
            None => {
                return Err(errors::StorageError::ValueNotFound(
                    "cannot find merchant connector account".to_string(),
                )
                .into())
            }
        }
    }

    async fn list_enabled_connector_accounts_by_profile_id(
        &self,
        _state: &KeyManagerState,
        _profile_id: &common_utils::id_type::ProfileId,
        _key_store: &domain::MerchantKeyStore,
        _connector_type: common_enums::ConnectorType,
    ) -> CustomResult<Vec<domain::MerchantConnectorAccount>, errors::StorageError> {
        Err(errors::StorageError::MockDbError)?
    }

    #[cfg(feature = "v1")]
    async fn find_merchant_connector_account_by_merchant_id_connector_name(
        &self,
        state: &KeyManagerState,
        merchant_id: &common_utils::id_type::MerchantId,
        connector_name: &str,
        key_store: &domain::MerchantKeyStore,
    ) -> CustomResult<Vec<domain::MerchantConnectorAccount>, errors::StorageError> {
        let accounts = self
            .merchant_connector_accounts
            .lock()
            .await
            .iter()
            .filter(|account| {
                account.merchant_id == *merchant_id && account.connector_name == connector_name
            })
            .cloned()
            .collect::<Vec<_>>();
        let mut output = Vec::with_capacity(accounts.len());
        for account in accounts.into_iter() {
            output.push(
                account
                    .convert(
                        state,
                        key_store.key.get_inner(),
                        key_store.merchant_id.clone().into(),
                    )
                    .await
                    .change_context(errors::StorageError::DecryptionError)?,
            )
        }
        Ok(output)
    }

    #[cfg(feature = "v1")]
    async fn find_merchant_connector_account_by_profile_id_connector_name(
        &self,
        state: &KeyManagerState,
        profile_id: &common_utils::id_type::ProfileId,
        connector_name: &str,
        key_store: &domain::MerchantKeyStore,
    ) -> CustomResult<domain::MerchantConnectorAccount, errors::StorageError> {
        let maybe_mca = self
            .merchant_connector_accounts
            .lock()
            .await
            .iter()
            .find(|account| {
                account.profile_id.eq(&Some(profile_id.to_owned()))
                    && account.connector_name == connector_name
            })
            .cloned();

        match maybe_mca {
            Some(mca) => mca
                .to_owned()
                .convert(
                    state,
                    key_store.key.get_inner(),
                    key_store.merchant_id.clone().into(),
                )
                .await
                .change_context(errors::StorageError::DecryptionError),
            None => Err(errors::StorageError::ValueNotFound(
                "cannot find merchant connector account".to_string(),
            )
            .into()),
        }
    }


// Struct: ThreedsecureioAuthenticationRequest
// File: crates/hyperswitch_connectors/src/connectors/threedsecureio/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct ThreedsecureioAuthenticationRequest


// Struct: PlatformOrgAdminAuthWithMerchantIdFromRoute
// File: crates/router/src/services/authentication.rs
// Module: router
// Implementations: 1

pub struct PlatformOrgAdminAuthWithMerchantIdFromRoute


// Struct: CeleroAddress
// File: crates/hyperswitch_connectors/src/connectors/celero/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct CeleroAddress


// Struct: ApplePayTotalInfo
// File: crates/hyperswitch_connectors/src/connectors/trustpay/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct ApplePayTotalInfo


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

// Public submodules:
pub mod compatibility;
pub mod configs;
pub mod connection;
pub mod connector;
pub mod consts;
pub mod core;
pub mod cors;
pub mod db;
pub mod env;
pub mod locale;
pub mod routes;
pub mod workflows;
pub mod analytics;
pub mod analytics_validator;
pub mod events;
// ... and 4 more

// Public exports:
pub use self::env::logger;
pub use masking::*;


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

impl Responder


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

pub struct ZenGeneralPaymentData


// Function: get_payment_method
// File: crates/api_models/src/admin.rs
// Module: api_models

pub fn get_payment_method(&self) -> Option<common_enums::PaymentMethod>


// Struct: ApplepayMerchantVerificationRequest
// File: crates/api_models/src/verifications.rs
// Module: api_models
// Implementations: 0

pub struct ApplepayMerchantVerificationRequest


// Implementation: impl api::PayoutQuote for for Nomupay
// File: crates/hyperswitch_connectors/src/connectors/nomupay.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::PayoutQuote for for Nomupay


// Struct: DwollaErrorDetail
// File: crates/hyperswitch_connectors/src/connectors/dwolla/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct DwollaErrorDetail


// Trait: AuthService
// File: crates/pm_auth/src/types/api/auth_service.rs
// Module: pm_auth

pub trait AuthService: super::ConnectorCommon
    + AuthServiceLinkToken
    + AuthServiceExchangeToken
    + AuthServiceBankAccountCredentials


// Struct: MandatePaymentRequest
// File: crates/hyperswitch_connectors/src/connectors/paybox/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct MandatePaymentRequest


// Implementation: impl ApiEventMetric for for CreateSubscriptionRequest
// File: crates/api_models/src/subscription.rs
// Module: api_models
// Methods: 0 total (0 public)

impl ApiEventMetric for for CreateSubscriptionRequest