            None,
            HeaderPayload::with_source(common_enums::PaymentSource::Webhook),
        ))
        .await
    } else {
        Err(report!(
            errors::ApiErrorResponse::WebhookAuthenticationFailed
        ))
    };

    match response? {
        services::ApplicationResponse::JsonWithHeaders((payments_response, _)) => {
            let payment_id = payments_response.payment_id.clone();

            let event_type: Option<enums::EventType> = payments_response.status.into();
            let status = payments_response.status;

            // If event is NOT an UnsupportedEvent, trigger Outgoing Webhook
            if let Some(outgoing_event_type) = event_type {
                let primary_object_created_at = payments_response.created;
                Box::pin(super::create_event_and_trigger_outgoing_webhook(
                    state,
                    merchant_context,
                    business_profile,
                    outgoing_event_type,
                    enums::EventClass::Payments,
                    payment_id.get_string_repr().to_owned(),
                    enums::EventObjectType::PaymentDetails,
                    api::OutgoingWebhookContent::PaymentDetails(Box::new(payments_response)),
                    primary_object_created_at,
                ))
                .await?;
            }

            Ok(WebhookResponseTracker::Payment { payment_id, status })
        }

        _ => Err(errors::ApiErrorResponse::WebhookProcessingFailure)
            .attach_printable("received non-json response from payments core")?,
    }
}

async fn get_payment_id(
    db: &dyn StorageInterface,
    payment_id: &api::PaymentIdType,
    merchant_id: &common_utils::id_type::MerchantId,
    storage_scheme: enums::MerchantStorageScheme,
) -> errors::RouterResult<common_utils::id_type::PaymentId> {
    let pay_id = || async {
        match payment_id {
            api_models::payments::PaymentIdType::PaymentIntentId(ref id) => Ok(id.to_owned()),
            api_models::payments::PaymentIdType::ConnectorTransactionId(ref id) => db
                .find_payment_attempt_by_merchant_id_connector_txn_id(
                    merchant_id,
                    id,
                    storage_scheme,
                )
                .await
                .map(|p| p.payment_id),
            api_models::payments::PaymentIdType::PaymentAttemptId(ref id) => db
                .find_payment_attempt_by_attempt_id_merchant_id(id, merchant_id, storage_scheme)
                .await
                .map(|p| p.payment_id),
            api_models::payments::PaymentIdType::PreprocessingId(ref id) => db
                .find_payment_attempt_by_preprocessing_id_merchant_id(
                    id,
                    merchant_id,
                    storage_scheme,
                )
                .await
                .map(|p| p.payment_id),
        }
    };

    pay_id()
        .await
        .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)
}

#[inline]
async fn verify_webhook_source_verification_call(
    connector: ConnectorEnum,
    state: &SessionState,
    merchant_context: &domain::MerchantContext,
    merchant_connector_account: domain::MerchantConnectorAccount,
    connector_name: &str,
    request_details: &IncomingWebhookRequestDetails<'_>,
) -> CustomResult<bool, errors::ConnectorError> {
    let connector_data = ConnectorData::get_connector_by_name(
        &state.conf.connectors,
        connector_name,
        GetToken::Connector,
        None,
    )
    .change_context(errors::ConnectorError::WebhookSourceVerificationFailed)
    .attach_printable("invalid connector name received in payment attempt")?;
    let connector_integration: services::BoxedWebhookSourceVerificationConnectorIntegrationInterface<
        hyperswitch_domain_models::router_flow_types::VerifyWebhookSource,
        VerifyWebhookSourceRequestData,
        VerifyWebhookSourceResponseData,
    > = connector_data.connector.get_connector_integration();
    let connector_webhook_secrets = connector
        .get_webhook_source_verification_merchant_secret(
            merchant_context.get_merchant_account().get_id(),
            connector_name,
            merchant_connector_account.connector_webhook_details.clone(),
        )
        .await
        .change_context(errors::ConnectorError::WebhookSourceVerificationFailed)?;

    let router_data = construct_webhook_router_data(
        state,
        connector_name,
        merchant_connector_account,
        merchant_context,
        &connector_webhook_secrets,
        request_details,
    )
    .await
    .change_context(errors::ConnectorError::WebhookSourceVerificationFailed)
    .attach_printable("Failed while constructing webhook router data")?;

    let response = services::execute_connector_processing_step(
        state,
        connector_integration,
        &router_data,
        payments::CallConnectorAction::Trigger,
        None,
        None,
    )
    .await?;

    let verification_result = response
        .response
        .map(|response| response.verify_webhook_status);
    match verification_result {
        Ok(VerifyWebhookStatus::SourceVerified) => Ok(true),
        _ => Ok(false),
    }
}

pub fn get_connector_by_connector_name(
    state: &SessionState,
    connector_name: &str,
    merchant_connector_id: Option<common_utils::id_type::MerchantConnectorAccountId>,
) -> CustomResult<(ConnectorEnum, String), errors::ApiErrorResponse> {
    let authentication_connector =
        api_models::enums::convert_authentication_connector(connector_name);
    #[cfg(feature = "frm")]
    {
        let frm_connector = api_models::enums::convert_frm_connector(connector_name);
        if frm_connector.is_some() {
            let frm_connector_data =
                api::FraudCheckConnectorData::get_connector_by_name(connector_name)?;
            return Ok((
                frm_connector_data.connector,
                frm_connector_data.connector_name.to_string(),
            ));
        }
    }

    let (connector, connector_name) = if authentication_connector.is_some() {
        let authentication_connector_data =
            api::AuthenticationConnectorData::get_connector_by_name(connector_name)?;
        (
            authentication_connector_data.connector,
            authentication_connector_data.connector_name.to_string(),
        )
    } else {
        let connector_data = ConnectorData::get_connector_by_name(
            &state.conf.connectors,
            connector_name,
            GetToken::Connector,
            merchant_connector_id,
        )
        .change_context(errors::ApiErrorResponse::InvalidRequestData {
            message: "invalid connector name received".to_string(),
        })
        .attach_printable("Failed construction of ConnectorData")?;
        (
            connector_data.connector,
            connector_data.connector_name.to_string(),
        )
    };
    Ok((connector, connector_name))
}

/// This function fetches the merchant connector account ( if the url used is /{merchant_connector_id})
/// if merchant connector id is not passed in the request, then this will return None for mca
async fn fetch_optional_mca_and_connector(
    state: &SessionState,
    merchant_context: &domain::MerchantContext,
    connector_name_or_mca_id: &str,
) -> CustomResult<
    (
        Option<domain::MerchantConnectorAccount>,
        ConnectorEnum,
        String,
    ),
    errors::ApiErrorResponse,
> {
    let db = &state.store;
    if connector_name_or_mca_id.starts_with("mca_") {
        #[cfg(feature = "v1")]
        let mca = db
            .find_by_merchant_connector_account_merchant_id_merchant_connector_id(
                &state.into(),
                merchant_context.get_merchant_account().get_id(),
                &common_utils::id_type::MerchantConnectorAccountId::wrap(
                    connector_name_or_mca_id.to_owned(),
                )
                .change_context(errors::ApiErrorResponse::InternalServerError)
                .attach_printable(
                    "Error while converting MerchanConnectorAccountId from string
                    ",
                )?,
                merchant_context.get_merchant_key_store(),
            )
            .await
            .to_not_found_response(errors::ApiErrorResponse::MerchantConnectorAccountNotFound {
                id: connector_name_or_mca_id.to_string(),
            })
            .attach_printable(
                "error while fetching merchant_connector_account from connector_id",
            )?;

        #[cfg(feature = "v2")]
        let mca: domain::MerchantConnectorAccount = {
            let _ = merchant_account;
            let _ = key_store;
            let _ = db;
            todo!()
        };

        let (connector, connector_name) =
            get_connector_by_connector_name(state, &mca.connector_name, Some(mca.get_id()))?;

        Ok((Some(mca), connector, connector_name))
    } else {
        // Merchant connector account is already being queried, it is safe to set connector id as None
        let (connector, connector_name) =
            get_connector_by_connector_name(state, connector_name_or_mca_id, None)?;
        Ok((None, connector, connector_name))
    }
}

fn should_update_connector_mandate_details(
    source_verified: bool,
    event_type: webhooks::IncomingWebhookEvent,
) -> bool {
    source_verified && event_type == webhooks::IncomingWebhookEvent::PaymentIntentSuccess
}

async fn update_connector_mandate_details(
    state: &SessionState,
    merchant_context: &domain::MerchantContext,
    object_ref_id: api::ObjectReferenceId,
    connector: &ConnectorEnum,
    request_details: &IncomingWebhookRequestDetails<'_>,
) -> CustomResult<(), errors::ApiErrorResponse> {
    let webhook_connector_mandate_details = connector
        .get_mandate_details(request_details)
        .switch()
        .attach_printable("Could not find connector mandate details in incoming webhook body")?;

    let webhook_connector_network_transaction_id = connector
        .get_network_txn_id(request_details)
        .switch()
        .attach_printable(
            "Could not find connector network transaction id in incoming webhook body",
        )?;

    // Either one OR both of the fields are present
    if webhook_connector_mandate_details.is_some()
        || webhook_connector_network_transaction_id.is_some()
    {
        let payment_attempt =
            get_payment_attempt_from_object_reference_id(state, object_ref_id, merchant_context)
                .await?;
        if let Some(ref payment_method_id) = payment_attempt.payment_method_id {
            let key_manager_state = &state.into();
            let payment_method_info = state
                .store
                .find_payment_method(
                    key_manager_state,
                    merchant_context.get_merchant_key_store(),
                    payment_method_id,
                    merchant_context.get_merchant_account().storage_scheme,
                )
                .await
                .to_not_found_response(errors::ApiErrorResponse::PaymentMethodNotFound)?;

            // Update connector's mandate details
            let updated_connector_mandate_details =
                if let Some(webhook_mandate_details) = webhook_connector_mandate_details {
                    let mandate_details = payment_method_info
                        .get_common_mandate_reference()
                        .change_context(errors::ApiErrorResponse::InternalServerError)
                        .attach_printable("Failed to deserialize to Payment Mandate Reference")?;

                    let merchant_connector_account_id = payment_attempt
                        .merchant_connector_id
                        .clone()
                        .get_required_value("merchant_connector_id")?;

                    if mandate_details.payments.as_ref().map_or(true, |payments| {
                        !payments.0.contains_key(&merchant_connector_account_id)
                    }) {
                        // Update the payment attempt to maintain consistency across tables.
                        let (mandate_metadata, connector_mandate_request_reference_id) =
                            payment_attempt
                                .connector_mandate_detail
                                .as_ref()
                                .map(|details| {
                                    (
                                        details.mandate_metadata.clone(),
                                        details.connector_mandate_request_reference_id.clone(),
                                    )
                                })
                                .unwrap_or((None, None));

                        let connector_mandate_reference_id = ConnectorMandateReferenceId {
                            connector_mandate_id: Some(
                                webhook_mandate_details
                                    .connector_mandate_id
                                    .peek()
                                    .to_string(),
                            ),
                            payment_method_id: Some(payment_method_id.to_string()),
                            mandate_metadata,
                            connector_mandate_request_reference_id,
                        };

                        let attempt_update =
                            storage::PaymentAttemptUpdate::ConnectorMandateDetailUpdate {
                                connector_mandate_detail: Some(connector_mandate_reference_id),
                                updated_by: merchant_context
                                    .get_merchant_account()
                                    .storage_scheme
                                    .to_string(),
                            };

                        state
                            .store
                            .update_payment_attempt_with_attempt_id(
                                payment_attempt.clone(),
                                attempt_update,
                                merchant_context.get_merchant_account().storage_scheme,
                            )
                            .await
                            .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?;

                        insert_mandate_details(
                            &payment_attempt,
                            &webhook_mandate_details,
                            Some(mandate_details),
                        )?
                    } else {
                        logger::info!(
                        "Skipping connector mandate details update since they are already present."
                    );
                        None
                    }
                } else {
                    None
                };

            let connector_mandate_details_value = updated_connector_mandate_details
                .map(|common_mandate| {
                    common_mandate.get_mandate_details_value().map_err(|err| {
                        router_env::logger::error!(
                            "Failed to get get_mandate_details_value : {:?}",
                            err
                        );
                        errors::ApiErrorResponse::MandateUpdateFailed
                    })
                })
                .transpose()?;

            let pm_update = diesel_models::PaymentMethodUpdate::ConnectorNetworkTransactionIdAndMandateDetailsUpdate {
                connector_mandate_details: connector_mandate_details_value.map(masking::Secret::new),
                network_transaction_id: webhook_connector_network_transaction_id
                    .map(|webhook_network_transaction_id| webhook_network_transaction_id.get_id().clone()),
            };

            state
                .store
                .update_payment_method(
                    key_manager_state,
                    merchant_context.get_merchant_key_store(),
                    payment_method_info,
                    pm_update,
                    merchant_context.get_merchant_account().storage_scheme,
                )
                .await
                .change_context(errors::ApiErrorResponse::InternalServerError)
                .attach_printable("Failed to update payment method in db")?;
        }
    }
    Ok(())
}

fn insert_mandate_details(
    payment_attempt: &PaymentAttempt,
    webhook_mandate_details: &hyperswitch_domain_models::router_flow_types::ConnectorMandateDetails,
    payment_method_mandate_details: Option<CommonMandateReference>,
) -> CustomResult<Option<CommonMandateReference>, errors::ApiErrorResponse> {
    let (mandate_metadata, connector_mandate_request_reference_id) = payment_attempt
        .connector_mandate_detail
        .clone()
        .map(|mandate_reference| {
            (
                mandate_reference.mandate_metadata,
                mandate_reference.connector_mandate_request_reference_id,
            )
        })
        .unwrap_or((None, None));
    let connector_mandate_details = tokenization::update_connector_mandate_details(
        payment_method_mandate_details,
        payment_attempt.payment_method_type,
        Some(
            payment_attempt
                .net_amount
                .get_total_amount()
                .get_amount_as_i64(),
        ),
        payment_attempt.currency,
        payment_attempt.merchant_connector_id.clone(),
        Some(
            webhook_mandate_details
                .connector_mandate_id
                .peek()
                .to_string(),
        ),
        mandate_metadata,
        connector_mandate_request_reference_id,
    )?;
    Ok(connector_mandate_details)
}


File: crates/router/src/routes/hypersense.rs
 Public functions: 3

use actix_web::{web, HttpRequest, HttpResponse};
use api_models::external_service_auth as external_service_auth_api;
use router_env::Flow;

use super::AppState;
use crate::{
    core::{api_locking, external_service_auth},
    services::{
        api,
        authentication::{self, ExternalServiceType},
    },
};

pub async fn get_hypersense_token(state: web::Data<AppState>, req: HttpRequest) -> HttpResponse {
    let flow = Flow::HypersenseTokenRequest;
    Box::pin(api::server_wrap(
        flow,
        state,
        &req,
        (),
        |state, user, _, _| {
            external_service_auth::generate_external_token(
                state,
                user,
                ExternalServiceType::Hypersense,
            )
        },
        &authentication::DashboardNoPermissionAuth,
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

pub async fn signout_hypersense_token(
    state: web::Data<AppState>,
    http_req: HttpRequest,
    json_payload: web::Json<external_service_auth_api::ExternalSignoutTokenRequest>,
) -> HttpResponse {
    let flow = Flow::HypersenseSignoutToken;
    Box::pin(api::server_wrap(
        flow,
        state.clone(),
        &http_req,
        json_payload.into_inner(),
        |state, _: (), json_payload, _| {
            external_service_auth::signout_external_token(state, json_payload)
        },
        &authentication::NoAuth,
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

pub async fn verify_hypersense_token(
    state: web::Data<AppState>,
    http_req: HttpRequest,
    json_payload: web::Json<external_service_auth_api::ExternalVerifyTokenRequest>,
) -> HttpResponse {
    let flow = Flow::HypersenseVerifyToken;
    Box::pin(api::server_wrap(
        flow,
        state.clone(),
        &http_req,
        json_payload.into_inner(),
        |state, _: (), json_payload, _| {
            external_service_auth::verify_external_token(
                state,
                json_payload,
                ExternalServiceType::Hypersense,
            )
        },
        &authentication::NoAuth,
        api_locking::LockAction::NotApplicable,
    ))
    .await
}


pub struct ListUsersInEntityRequest {
    pub entity_type: Option<common_enums::EntityType>,
}


File: crates/hyperswitch_connectors/src/connectors/globepay/transformers.rs
 Public structs: 9

use common_enums::enums;
use common_utils::{ext_traits::Encode, types::MinorUnit};
use error_stack::ResultExt;
use hyperswitch_domain_models::{
    payment_method_data::{PaymentMethodData, WalletData},
    router_data::{ConnectorAuthType, ErrorResponse, RouterData},
    router_request_types::ResponseId,
    router_response_types::{PaymentsResponseData, RefundsResponseData},
    types::{self, RefundsRouterData},
};
use hyperswitch_interfaces::{consts, errors};
use masking::Secret;
use serde::{Deserialize, Serialize};

use crate::{
    types::{RefundsResponseRouterData, ResponseRouterData},
    utils::{get_unimplemented_payment_method_error_message, RouterData as _},
};
type Error = error_stack::Report<errors::ConnectorError>;

#[derive(Debug, Serialize)]
pub struct GlobepayRouterData<T> {
    pub amount: MinorUnit,
    pub router_data: T,
}

impl<T> From<(MinorUnit, T)> for GlobepayRouterData<T> {
    fn from((amount, router_data): (MinorUnit, T)) -> Self {
        Self {
            amount,
            router_data,
        }
    }
}

#[derive(Debug, Serialize)]
pub struct GlobepayPaymentsRequest {
    price: MinorUnit,
    description: String,
    currency: enums::Currency,
    channel: GlobepayChannel,
}

#[derive(Debug, Serialize)]
pub enum GlobepayChannel {
    Alipay,
    Wechat,
}

impl TryFrom<&GlobepayRouterData<&types::PaymentsAuthorizeRouterData>> for GlobepayPaymentsRequest {
    type Error = Error;
    fn try_from(
        item_data: &GlobepayRouterData<&types::PaymentsAuthorizeRouterData>,
    ) -> Result<Self, Self::Error> {
        let item = item_data.router_data.clone();
        let channel: GlobepayChannel = match &item.request.payment_method_data {
            PaymentMethodData::Wallet(ref wallet_data) => match wallet_data {
                WalletData::AliPayQr(_) => GlobepayChannel::Alipay,
                WalletData::WeChatPayQr(_) => GlobepayChannel::Wechat,
                WalletData::AliPayRedirect(_)
                | WalletData::AliPayHkRedirect(_)
                | WalletData::AmazonPay(_)
                | WalletData::AmazonPayRedirect(_)
                | WalletData::Paysera(_)
                | WalletData::Skrill(_)
                | WalletData::BluecodeRedirect {}
                | WalletData::MomoRedirect(_)
                | WalletData::KakaoPayRedirect(_)
                | WalletData::GoPayRedirect(_)
                | WalletData::GcashRedirect(_)
                | WalletData::ApplePay(_)
                | WalletData::ApplePayRedirect(_)
                | WalletData::ApplePayThirdPartySdk(_)
                | WalletData::DanaRedirect {}
                | WalletData::GooglePay(_)
                | WalletData::GooglePayRedirect(_)
                | WalletData::GooglePayThirdPartySdk(_)
                | WalletData::MbWayRedirect(_)
                | WalletData::MobilePayRedirect(_)
                | WalletData::PaypalRedirect(_)
                | WalletData::PaypalSdk(_)
                | WalletData::Paze(_)
                | WalletData::SamsungPay(_)
                | WalletData::TwintRedirect {}
                | WalletData::VippsRedirect {}
                | WalletData::TouchNGoRedirect(_)
                | WalletData::WeChatPayRedirect(_)
                | WalletData::CashappQr(_)
                | WalletData::SwishQr(_)
                | WalletData::Mifinity(_)
                | WalletData::RevolutPay(_) => Err(errors::ConnectorError::NotImplemented(
                    get_unimplemented_payment_method_error_message("globepay"),
                ))?,
            },
            PaymentMethodData::Card(_)
            | PaymentMethodData::CardRedirect(_)
            | PaymentMethodData::PayLater(_)
            | PaymentMethodData::BankRedirect(_)
            | PaymentMethodData::BankDebit(_)
            | PaymentMethodData::BankTransfer(_)
            | PaymentMethodData::Crypto(_)
            | PaymentMethodData::MandatePayment
            | PaymentMethodData::Reward
            | PaymentMethodData::RealTimePayment(_)
            | PaymentMethodData::MobilePayment(_)
            | PaymentMethodData::Upi(_)
            | PaymentMethodData::Voucher(_)
            | PaymentMethodData::GiftCard(_)
            | PaymentMethodData::OpenBanking(_)
            | PaymentMethodData::CardToken(_)
            | PaymentMethodData::NetworkToken(_)
            | PaymentMethodData::CardDetailsForNetworkTransactionId(_) => {
                Err(errors::ConnectorError::NotImplemented(
                    get_unimplemented_payment_method_error_message("globepay"),
                ))?
            }
        };
        let description = item.get_description()?;
        Ok(Self {
            price: item_data.amount,
            description,
            currency: item.request.currency,
            channel,
        })
    }
}

pub struct GlobepayAuthType {
    pub(super) partner_code: Secret<String>,
    pub(super) credential_code: Secret<String>,
}

impl TryFrom<&ConnectorAuthType> for GlobepayAuthType {
    type Error = Error;
    fn try_from(auth_type: &ConnectorAuthType) -> Result<Self, Self::Error> {
        match auth_type {
            ConnectorAuthType::BodyKey { api_key, key1 } => Ok(Self {
                partner_code: api_key.to_owned(),
                credential_code: key1.to_owned(),
            }),
            _ => Err(errors::ConnectorError::FailedToObtainAuthType.into()),
        }
    }
}

#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum GlobepayPaymentStatus {
    Success,
    Exists,
}

impl From<GlobepayPaymentStatus> for enums::AttemptStatus {
    fn from(item: GlobepayPaymentStatus) -> Self {
        match item {
            GlobepayPaymentStatus::Success => Self::AuthenticationPending, // this connector only have redirection flows so "Success" is mapped to authenticatoin pending ,ref = "https://pay.globepay.co/docs/en/#api-QRCode-NewQRCode"
            GlobepayPaymentStatus::Exists => Self::Failure,
        }
    }
}

#[derive(Debug, Deserialize, Serialize)]
pub struct GlobepayConnectorMetadata {
    image_data_url: url::Url,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct GlobepayPaymentsResponse {
    result_code: Option<GlobepayPaymentStatus>,
    order_id: Option<String>,
    qrcode_img: Option<url::Url>,
    return_code: GlobepayReturnCode, //Execution result
    return_msg: Option<String>,
}

#[derive(Debug, Deserialize, PartialEq, strum::Display, Serialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum GlobepayReturnCode {
    Success,
    OrderNotExist,
    OrderMismatch,
    Systemerror,
    InvalidShortId,
    SignTimeout,
    InvalidSign,
    ParamInvalid,
    NotPermitted,
    InvalidChannel,
    DuplicateOrderId,
    OrderNotPaid,
}

impl<F, T> TryFrom<ResponseRouterData<F, GlobepayPaymentsResponse, T, PaymentsResponseData>>
    for RouterData<F, T, PaymentsResponseData>
{
    type Error = Error;
    fn try_from(
        item: ResponseRouterData<F, GlobepayPaymentsResponse, T, PaymentsResponseData>,
    ) -> Result<Self, Self::Error> {
        if item.response.return_code == GlobepayReturnCode::Success {
            let globepay_metadata = GlobepayConnectorMetadata {
                image_data_url: item
                    .response
                    .qrcode_img
                    .ok_or(errors::ConnectorError::ResponseHandlingFailed)?,
            };
            let connector_metadata = Some(globepay_metadata.encode_to_value())
                .transpose()
                .change_context(errors::ConnectorError::ResponseHandlingFailed)?;
            let globepay_status = item
                .response
                .result_code
                .ok_or(errors::ConnectorError::ResponseHandlingFailed)?;

            Ok(Self {
                status: enums::AttemptStatus::from(globepay_status),
                response: Ok(PaymentsResponseData::TransactionResponse {
                    resource_id: ResponseId::ConnectorTransactionId(
                        item.response
                            .order_id
                            .ok_or(errors::ConnectorError::ResponseHandlingFailed)?,
                    ),
                    redirection_data: Box::new(None),
                    mandate_reference: Box::new(None),
                    connector_metadata,
                    network_txn_id: None,
                    connector_response_reference_id: None,
                    incremental_authorization_allowed: None,
                    charges: None,
                }),
                ..item.data
            })
        } else {
            Ok(Self {
                status: enums::AttemptStatus::Failure, //As this connector gives 200 in failed scenarios . if return_code is not success status is mapped to failure. ref = "https://pay.globepay.co/docs/en/#api-QRCode-NewQRCode"
                response: Err(get_error_response(
                    item.response.return_code,
                    item.response.return_msg,
                    item.http_code,
                )),
                ..item.data
            })
        }
    }
}

#[derive(Debug, Deserialize, Serialize)]
pub struct GlobepaySyncResponse {
    pub result_code: Option<GlobepayPaymentPsyncStatus>,
    pub order_id: Option<String>,
    pub return_code: GlobepayReturnCode,
    pub return_msg: Option<String>,
}

#[derive(Debug, Deserialize, Serialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum GlobepayPaymentPsyncStatus {
    Paying,
    CreateFail,
    Closed,
    PayFail,
    PaySuccess,
}

impl From<GlobepayPaymentPsyncStatus> for enums::AttemptStatus {
    fn from(item: GlobepayPaymentPsyncStatus) -> Self {
        match item {
            GlobepayPaymentPsyncStatus::PaySuccess => Self::Charged,
            GlobepayPaymentPsyncStatus::PayFail
            | GlobepayPaymentPsyncStatus::CreateFail
            | GlobepayPaymentPsyncStatus::Closed => Self::Failure,
            GlobepayPaymentPsyncStatus::Paying => Self::AuthenticationPending,
        }
    }
}

impl<F, T> TryFrom<ResponseRouterData<F, GlobepaySyncResponse, T, PaymentsResponseData>>
    for RouterData<F, T, PaymentsResponseData>
{
    type Error = Error;
    fn try_from(
        item: ResponseRouterData<F, GlobepaySyncResponse, T, PaymentsResponseData>,
    ) -> Result<Self, Self::Error> {
        if item.response.return_code == GlobepayReturnCode::Success {
            let globepay_status = item
                .response
                .result_code
                .ok_or(errors::ConnectorError::ResponseHandlingFailed)?;
            let globepay_id = item
                .response
                .order_id
                .ok_or(errors::ConnectorError::ResponseHandlingFailed)?;
            Ok(Self {
                status: enums::AttemptStatus::from(globepay_status),
                response: Ok(PaymentsResponseData::TransactionResponse {
                    resource_id: ResponseId::ConnectorTransactionId(globepay_id),
                    redirection_data: Box::new(None),
                    mandate_reference: Box::new(None),
                    connector_metadata: None,
                    network_txn_id: None,
                    connector_response_reference_id: None,
                    incremental_authorization_allowed: None,
                    charges: None,
                }),
                ..item.data
            })
        } else {
            Ok(Self {
                status: enums::AttemptStatus::Failure, //As this connector gives 200 in failed scenarios . if return_code is not success status is mapped to failure. ref = "https://pay.globepay.co/docs/en/#api-QRCode-NewQRCode"
                response: Err(get_error_response(
                    item.response.return_code,
                    item.response.return_msg,
                    item.http_code,
                )),
                ..item.data
            })
        }
    }
}

fn get_error_response(
    return_code: GlobepayReturnCode,
    return_msg: Option<String>,
    status_code: u16,
) -> ErrorResponse {
    ErrorResponse {
        code: return_code.to_string(),
        message: consts::NO_ERROR_MESSAGE.to_string(),
        reason: return_msg,
        status_code,
        attempt_status: None,
        connector_transaction_id: None,
        network_advice_code: None,
        network_decline_code: None,
        network_error_message: None,
        connector_metadata: None,
    }
}

#[derive(Debug, Serialize)]
pub struct GlobepayRefundRequest {
    pub fee: MinorUnit,
}

impl<F> TryFrom<&GlobepayRouterData<&RefundsRouterData<F>>> for GlobepayRefundRequest {
    type Error = Error;
    fn try_from(item: &GlobepayRouterData<&RefundsRouterData<F>>) -> Result<Self, Self::Error> {
        Ok(Self { fee: item.amount })
    }
}

#[derive(Debug, Deserialize, Serialize)]
pub enum GlobepayRefundStatus {
    Waiting,
    CreateFailed,
    Failed,
    Success,
    Finished,
    Change,
}

impl From<GlobepayRefundStatus> for enums::RefundStatus {
    fn from(item: GlobepayRefundStatus) -> Self {
        match item {
            GlobepayRefundStatus::Finished => Self::Success, //FINISHED: Refund success(funds has already been returned to user's account)
            GlobepayRefundStatus::Failed
            | GlobepayRefundStatus::CreateFailed
            | GlobepayRefundStatus::Change => Self::Failure, //CHANGE: Refund can not return to user's account. Manual operation is required
            GlobepayRefundStatus::Waiting | GlobepayRefundStatus::Success => Self::Pending, // SUCCESS: Submission succeeded, but refund is not yet complete. Waiting = Submission succeeded, but refund is not yet complete.
        }
    }
}

#[derive(Debug, Deserialize, Serialize)]
pub struct GlobepayRefundResponse {
    pub result_code: Option<GlobepayRefundStatus>,
    pub refund_id: Option<String>,
    pub return_code: GlobepayReturnCode,
    pub return_msg: Option<String>,
}

impl<T> TryFrom<RefundsResponseRouterData<T, GlobepayRefundResponse>> for RefundsRouterData<T> {
    type Error = Error;
    fn try_from(
        item: RefundsResponseRouterData<T, GlobepayRefundResponse>,
    ) -> Result<Self, Self::Error> {
        if item.response.return_code == GlobepayReturnCode::Success {
            let globepay_refund_id = item
                .response
                .refund_id
                .ok_or(errors::ConnectorError::ResponseHandlingFailed)?;
            let globepay_refund_status = item
                .response
                .result_code
                .ok_or(errors::ConnectorError::ResponseHandlingFailed)?;
            Ok(Self {
                response: Ok(RefundsResponseData {
                    connector_refund_id: globepay_refund_id,
                    refund_status: enums::RefundStatus::from(globepay_refund_status),
                }),
                ..item.data
            })
        } else {
            Ok(Self {
                response: Err(get_error_response(
                    item.response.return_code,
                    item.response.return_msg,
                    item.http_code,
                )),
                ..item.data
            })
        }
    }
}

#[derive(Debug, Deserialize, Serialize)]
pub struct GlobepayErrorResponse {
    pub return_msg: String,
    pub return_code: GlobepayReturnCode,
    pub message: String,
}


impl ApiEventMetric for AuthenticationCreateRequest {
    fn get_api_event_type(&self) -> Option<ApiEventsType> {
        self.authentication_id
            .as_ref()
            .map(|id| ApiEventsType::Authentication {
                authentication_id: id.clone(),
            })
    }
}

impl ApiEventMetric for for AuthenticationCreateRequest


pub struct GsmDeleteResponse {
    pub gsm_rule_delete: bool,
    /// The connector through which payment has gone through
    pub connector: String,
    /// The flow in which the code and message occurred for a connector
    pub flow: String,
    /// The sub_flow in which the code and message occurred  for a connector
    pub sub_flow: String,
    /// code received from the connector
    pub code: String,
}


pub async fn decision_engine_routing(
    state: &SessionState,
    backend_input: BackendInput,
    business_profile: &domain::Profile,
    payment_id: String,
    merchant_fallback_config: Vec<RoutableConnectorChoice>,
) -> RoutingResult<Vec<RoutableConnectorChoice>> {
    let routing_events_wrapper = RoutingEventsWrapper::new(
        state.tenant.tenant_id.clone(),
        state.request_id,
        payment_id,
        business_profile.get_id().to_owned(),
        business_profile.merchant_id.to_owned(),
        "DecisionEngine: Euclid Static Routing".to_string(),
        None,
        true,
        false,
    );

    let de_euclid_evaluate_response = perform_decision_euclid_routing(
        state,
        backend_input.clone(),
        business_profile.get_id().get_string_repr().to_string(),
        routing_events_wrapper,
        merchant_fallback_config,
    )
    .await;

    let Ok(de_euclid_response) = de_euclid_evaluate_response else {
        logger::error!("decision_engine_euclid_evaluation_error: error in evaluation of rule");
        return Ok(Vec::default());
    };

    let de_output_connector = extract_de_output_connectors(de_euclid_response.output)
            .map_err(|e| {
                logger::error!(error=?e, "decision_engine_euclid_evaluation_error: Failed to extract connector from Output");
                e
            })?;

    transform_de_output_for_router(
            de_output_connector.clone(),
            de_euclid_response.evaluated_output.clone(),
        )
        .map_err(|e| {
            logger::error!(error=?e, "decision_engine_euclid_evaluation_error: failed to transform connector from de-output");
            e
        })
}


pub struct AirwallexRedirectResponse {
    status: AirwallexPaymentStatus,
    id: String,
    amount: Option<f32>,
    payment_consent_id: Option<Secret<String>>,
    next_action: Option<AirwallexRedirectNextAction>,
}


pub struct UnifiedTranslationsUpdateInternal {
    pub translation: Option<String>,
    pub last_modified_at: PrimitiveDateTime,
}


impl api::PaymentSession for Adyenplatform {}

impl api::PaymentSession for for Adyenplatform


pub async fn delete_payment_intents(
    conn: &PgPooledConn,
    merchant_id: &common_utils::id_type::MerchantId,
) -> StorageResult<Vec<PaymentIntent>> {
    let query = diesel::delete(<PaymentIntent>::table())
        .filter(payment_intent_dsl::merchant_id.eq(merchant_id.to_owned()))
        .filter(payment_intent_dsl::merchant_reference_id.like("test_%"));

    logger::debug!(query = %debug_query::<diesel::pg::Pg,_>(&query).to_string());

    query
        .get_results_async(conn)
        .await
        .change_context(errors::DatabaseError::Others)
        .attach_printable("Error while deleting payment intents")
        .and_then(|result| match result.len() {
            n if n > 0 => {
                logger::debug!("{n} records deleted");
                Ok(result)
            }
            0 => Err(error_stack::report!(errors::DatabaseError::NotFound)
                .attach_printable("No records deleted")),
            _ => Ok(result),
        })
}


OpenAPI Block Path: components.schemas.MerchantConnectorResponse
{
  "type": "object",
  "description": "Response of creating a new Merchant Connector for the merchant account.\"",
  "required": [
    "connector_type",
    "connector_name",
    "merchant_connector_id",
    "profile_id",
    "status"
  ],
  "properties": {
    "connector_type": {
      "$ref": "#/components/schemas/ConnectorType"
    },
    "connector_name": {
      "$ref": "#/components/schemas/Connector"
    },
    "connector_label": {
      "type": "string",
      "description": "A unique label to identify the connector account created under a profile",
      "example": "stripe_US_travel",
      "nullable": true
    },
    "merchant_connector_id": {
      "type": "string",
      "description": "Unique ID of the merchant connector account",
      "example": "mca_5apGeP94tMts6rg3U3kR"
    },
    "profile_id": {
      "type": "string",
      "description": "Identifier for the profile, if not provided default will be chosen from merchant account",
      "maxLength": 64
    },
    "connector_account_details": {
      "allOf": [
        {
          "$ref": "#/components/schemas/MerchantConnectorDetails"
        }
      ],
      "nullable": true
    },
    "payment_methods_enabled": {
      "type": "array",
      "items": {
        "$ref": "#/components/schemas/PaymentMethodsEnabled"
      },
      "description": "An object containing the details about the payment methods that need to be enabled under this merchant connector account",
      "example": [
        {
          "accepted_countries": {
            "list": [
              "FR",
              "DE",
              "IN"
            ],
            "type": "disable_only"
          },
          "accepted_currencies": {
            "list": [
              "USD",
              "EUR"
            ],
            "type": "enable_only"
          },
          "installment_payment_enabled": true,
          "maximum_amount": 68607706,
          "minimum_amount": 1,
          "payment_method": "wallet",
          "payment_method_issuers": [
            "labore magna ipsum",
            "aute"
          ],
          "payment_method_types": [
            "upi_collect",
            "upi_intent"
          ],
          "payment_schemes": [
            "Discover",
            "Discover"
          ],
          "recurring_enabled": true
        }
      ],
      "nullable": true
    },
    "connector_webhook_details": {
      "allOf": [
        {
          "$ref": "#/components/schemas/MerchantConnectorWebhookDetails"
        }
      ],
      "nullable": true
    },
    "metadata": {
      "type": "object",
      "description": "Metadata is useful for storing additional, unstructured information on an object.",
      "nullable": true
    },
    "test_mode": {
      "type": "boolean",
      "description": "A boolean value to indicate if the connector is in Test mode. By default, its value is false.",
      "default": false,
      "example": false,
      "nullable": true
    },
    "disabled": {
      "type": "boolean",
      "description": "A boolean value to indicate if the connector is disabled. By default, its value is false.",
      "default": false,
      "example": false,
      "nullable": true
    },
    "frm_configs": {
      "type": "array",
      "items": {
        "$ref": "#/components/schemas/FrmConfigs"
      },
      "description": "Contains the frm configs for the merchant connector",
      "example": "\n[{\"gateway\":\"stripe\",\"payment_methods\":[{\"payment_method\":\"card\",\"payment_method_types\":[{\"payment_method_type\":\"credit\",\"card_networks\":[\"Visa\"],\"flow\":\"pre\",\"action\":\"cancel_txn\"},{\"payment_method_type\":\"debit\",\"card_networks\":[\"Visa\"],\"flow\":\"pre\"}]}]}]\n",
      "nullable": true
    },
    "business_country": {
      "allOf": [
        {
          "$ref": "#/components/schemas/CountryAlpha2"
        }
      ],
      "nullable": true
    },
    "business_label": {
      "type": "string",
      "description": "The business label to which the connector account is attached. To be deprecated soon. Use the 'profile_id' instead",
      "example": "travel",
      "nullable": true
    },
    "business_sub_label": {
      "type": "string",
      "description": "The business sublabel to which the connector account is attached. To be deprecated soon. Use the 'profile_id' instead",
      "example": "chase",
      "nullable": true
    },
    "applepay_verified_domains": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "identifier for the verified domains of a particular connector account",
      "nullable": true
    },
    "pm_auth_config": {
      "type": "object",
      "nullable": true
    },
    "status": {
      "$ref": "#/components/schemas/ConnectorStatus"
    },
    "additional_merchant_data": {
      "allOf": [
        {
          "$ref": "#/components/schemas/AdditionalMerchantData"
        }
      ],
      "nullable": true
    },
    "connector_wallets_details": {
      "allOf": [
        {
          "$ref": "#/components/schemas/ConnectorWalletDetails"
        }
      ],
      "nullable": true
    }
  },
  "additionalProperties": false
}


pub struct PaymentMethodCollectLinkRequest {
    /// The unique identifier for the collect link.
    #[schema(value_type = Option<String>, example = "pm_collect_link_2bdacf398vwzq5n422S1")]
    pub pm_collect_link_id: Option<String>,

    /// The unique identifier of the customer.
    #[schema(value_type = String, example = "cus_92dnwed8s32bV9D8Snbiasd8v")]
    pub customer_id: id_type::CustomerId,

    #[serde(flatten)]
    #[schema(value_type = Option<GenericLinkUiConfig>)]
    pub ui_config: Option<link_utils::GenericLinkUiConfig>,

    /// Will be used to expire client secret after certain amount of time to be supplied in seconds
    /// (900) for 15 mins
    #[schema(value_type = Option<u32>, example = 900)]
    pub session_expiry: Option<u32>,

    /// Redirect to this URL post completion
    #[schema(value_type = Option<String>, example = "https://sandbox.hyperswitch.io/payment_method/collect/pm_collect_link_2bdacf398vwzq5n422S1/status")]
    pub return_url: Option<String>,

    /// List of payment methods shown on collect UI
    #[schema(value_type = Option<Vec<EnabledPaymentMethod>>, example = r#"[{"payment_method": "bank_transfer", "payment_method_types": ["ach", "bacs"]}]"#)]
    pub enabled_payment_methods: Option<Vec<link_utils::EnabledPaymentMethod>>,
}


pub struct PaymentAccountFeatureInformation {
    health_card: Option<String>,
}


        merchant_account: storage::MerchantAccountUpdate,
        key_store: &domain::MerchantKeyStore,
    ) -> CustomResult<domain::MerchantAccount, errors::StorageError> {
        self.diesel_store
            .update_specific_fields_in_merchant(state, merchant_id, merchant_account, key_store)
            .await
    }

    async fn update_all_merchant_account(
        &self,
        merchant_account: storage::MerchantAccountUpdate,
    ) -> CustomResult<usize, errors::StorageError> {
        self.diesel_store
            .update_all_merchant_account(merchant_account)
            .await
    }

    async fn find_merchant_account_by_publishable_key(
        &self,
        state: &KeyManagerState,
        publishable_key: &str,
    ) -> CustomResult<(domain::MerchantAccount, domain::MerchantKeyStore), errors::StorageError>
    {
        self.diesel_store
            .find_merchant_account_by_publishable_key(state, publishable_key)
            .await
    }

    #[cfg(feature = "olap")]
    async fn list_merchant_accounts_by_organization_id(
        &self,
        state: &KeyManagerState,
        organization_id: &id_type::OrganizationId,
    ) -> CustomResult<Vec<domain::MerchantAccount>, errors::StorageError> {
        self.diesel_store
            .list_merchant_accounts_by_organization_id(state, organization_id)
            .await
    }

    async fn delete_merchant_account_by_merchant_id(
        &self,
        merchant_id: &id_type::MerchantId,
    ) -> CustomResult<bool, errors::StorageError> {
        self.diesel_store
            .delete_merchant_account_by_merchant_id(merchant_id)
            .await
    }

    #[cfg(feature = "olap")]
    async fn list_multiple_merchant_accounts(
        &self,
        state: &KeyManagerState,
        merchant_ids: Vec<id_type::MerchantId>,
    ) -> CustomResult<Vec<domain::MerchantAccount>, errors::StorageError> {
        self.diesel_store
            .list_multiple_merchant_accounts(state, merchant_ids)
            .await
    }

    #[cfg(feature = "olap")]
    async fn list_merchant_and_org_ids(
        &self,
        state: &KeyManagerState,
        limit: u32,
        offset: Option<u32>,
    ) -> CustomResult<Vec<(id_type::MerchantId, id_type::OrganizationId)>, errors::StorageError>
    {
        self.diesel_store
            .list_merchant_and_org_ids(state, limit, offset)
            .await
    }
}

#[async_trait::async_trait]
impl ConnectorAccessToken for KafkaStore {
    async fn get_access_token(
        &self,
        merchant_id: &id_type::MerchantId,
        merchant_connector_id: &str,
    ) -> CustomResult<Option<AccessToken>, errors::StorageError> {
        self.diesel_store
            .get_access_token(merchant_id, merchant_connector_id)
            .await
    }

    async fn set_access_token(
        &self,
        merchant_id: &id_type::MerchantId,
        merchant_connector_id: &str,
        access_token: AccessToken,
    ) -> CustomResult<(), errors::StorageError> {
        self.diesel_store
            .set_access_token(merchant_id, merchant_connector_id, access_token)
            .await
    }
}

#[async_trait::async_trait]
impl FileMetadataInterface for KafkaStore {
    async fn insert_file_metadata(
        &self,
        file: storage::FileMetadataNew,
    ) -> CustomResult<storage::FileMetadata, errors::StorageError> {
        self.diesel_store.insert_file_metadata(file).await
    }

    async fn find_file_metadata_by_merchant_id_file_id(
        &self,
        merchant_id: &id_type::MerchantId,
        file_id: &str,
    ) -> CustomResult<storage::FileMetadata, errors::StorageError> {
        self.diesel_store
            .find_file_metadata_by_merchant_id_file_id(merchant_id, file_id)
            .await
    }

    async fn delete_file_metadata_by_merchant_id_file_id(
        &self,
        merchant_id: &id_type::MerchantId,
        file_id: &str,
    ) -> CustomResult<bool, errors::StorageError> {
        self.diesel_store
            .delete_file_metadata_by_merchant_id_file_id(merchant_id, file_id)
            .await
    }

    async fn update_file_metadata(
        &self,
        this: storage::FileMetadata,
        file_metadata: storage::FileMetadataUpdate,
    ) -> CustomResult<storage::FileMetadata, errors::StorageError> {
        self.diesel_store
            .update_file_metadata(this, file_metadata)
            .await
    }
}

#[async_trait::async_trait]
impl MerchantConnectorAccountInterface for KafkaStore {
    async fn update_multiple_merchant_connector_accounts(
        &self,
        merchant_connector_accounts: Vec<(
            domain::MerchantConnectorAccount,
            storage::MerchantConnectorAccountUpdateInternal,
        )>,
    ) -> CustomResult<(), errors::StorageError> {
        self.diesel_store
            .update_multiple_merchant_connector_accounts(merchant_connector_accounts)
            .await
    }
    #[cfg(feature = "v1")]
    async fn find_merchant_connector_account_by_merchant_id_connector_label(
        &self,
        state: &KeyManagerState,
        merchant_id: &id_type::MerchantId,
        connector: &str,
        key_store: &domain::MerchantKeyStore,
    ) -> CustomResult<domain::MerchantConnectorAccount, errors::StorageError> {
        self.diesel_store
            .find_merchant_connector_account_by_merchant_id_connector_label(
                state,
                merchant_id,
                connector,
                key_store,
            )
            .await
    }

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

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

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

    async fn insert_merchant_connector_account(
        &self,
        state: &KeyManagerState,
        t: domain::MerchantConnectorAccount,
        key_store: &domain::MerchantKeyStore,
    ) -> CustomResult<domain::MerchantConnectorAccount, errors::StorageError> {
        self.diesel_store
            .insert_merchant_connector_account(state, t, key_store)
            .await
    }

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

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

    async fn find_merchant_connector_account_by_merchant_id_and_disabled_list(
        &self,
        state: &KeyManagerState,
        merchant_id: &id_type::MerchantId,
        get_disabled: bool,
        key_store: &domain::MerchantKeyStore,
    ) -> CustomResult<domain::MerchantConnectorAccounts, errors::StorageError> {
        self.diesel_store
            .find_merchant_connector_account_by_merchant_id_and_disabled_list(
                state,
                merchant_id,
                get_disabled,
                key_store,
            )
            .await
    }

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

    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> {
        self.diesel_store
            .update_merchant_connector_account(state, this, merchant_connector_account, key_store)
            .await
    }

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

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

#[async_trait::async_trait]
impl QueueInterface for KafkaStore {
    async fn fetch_consumer_tasks(
        &self,
        stream_name: &str,
        group_name: &str,
        consumer_name: &str,
    ) -> CustomResult<Vec<storage::ProcessTracker>, ProcessTrackerError> {
        self.diesel_store
            .fetch_consumer_tasks(stream_name, group_name, consumer_name)
            .await
    }

    async fn consumer_group_create(
        &self,
        stream: &str,
        group: &str,
        id: &RedisEntryId,
    ) -> CustomResult<(), RedisError> {
        self.diesel_store
            .consumer_group_create(stream, group, id)
            .await
    }

    async fn acquire_pt_lock(
        &self,
        tag: &str,
        lock_key: &str,
        lock_val: &str,
        ttl: i64,
    ) -> CustomResult<bool, RedisError> {
        self.diesel_store
            .acquire_pt_lock(tag, lock_key, lock_val, ttl)
            .await
    }

    async fn release_pt_lock(&self, tag: &str, lock_key: &str) -> CustomResult<bool, RedisError> {
        self.diesel_store.release_pt_lock(tag, lock_key).await
    }

    async fn stream_append_entry(
        &self,
        stream: &str,
        entry_id: &RedisEntryId,
        fields: Vec<(&str, String)>,
    ) -> CustomResult<(), RedisError> {
        self.diesel_store
            .stream_append_entry(stream, entry_id, fields)
            .await
    }

    async fn get_key(&self, key: &str) -> CustomResult<Vec<u8>, RedisError> {
        self.diesel_store.get_key(key).await
    }
}

#[async_trait::async_trait]
impl PaymentAttemptInterface for KafkaStore {
    type Error = errors::StorageError;
    #[cfg(feature = "v1")]
    async fn insert_payment_attempt(
        &self,
        payment_attempt: storage::PaymentAttemptNew,
        storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<storage::PaymentAttempt, errors::StorageError> {
        let attempt = self
            .diesel_store
            .insert_payment_attempt(payment_attempt, storage_scheme)
            .await?;

        if let Err(er) = self
            .kafka_producer
            .log_payment_attempt(&attempt, None, self.tenant_id.clone())
            .await
        {
            logger::error!(message="Failed to log analytics event for payment attempt {attempt:?}", error_message=?er)
        }

        Ok(attempt)
    }

    #[cfg(feature = "v2")]
    async fn insert_payment_attempt(
        &self,
        key_manager_state: &KeyManagerState,
        merchant_key_store: &domain::MerchantKeyStore,
        payment_attempt: storage::PaymentAttempt,
        storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<storage::PaymentAttempt, errors::StorageError> {
        let attempt = self
            .diesel_store
            .insert_payment_attempt(
                key_manager_state,
                merchant_key_store,
                payment_attempt,
                storage_scheme,
            )
            .await?;

        if let Err(er) = self
            .kafka_producer
            .log_payment_attempt(&attempt, None, self.tenant_id.clone())
            .await
        {
            logger::error!(message="Failed to log analytics event for payment attempt {attempt:?}", error_message=?er)
        }

        Ok(attempt)
    }

    #[cfg(feature = "v1")]
    async fn update_payment_attempt_with_attempt_id(
        &self,
        this: storage::PaymentAttempt,
        payment_attempt: storage::PaymentAttemptUpdate,
        storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<storage::PaymentAttempt, errors::StorageError> {
        let mut attempt = self
            .diesel_store
            .update_payment_attempt_with_attempt_id(
                this.clone(),
                payment_attempt.clone(),
                storage_scheme,
            )
            .await?;

        let debit_routing_savings = payment_attempt.get_debit_routing_savings();

        attempt.set_debit_routing_savings(debit_routing_savings);
        if let Err(er) = self
            .kafka_producer
            .log_payment_attempt(&attempt, Some(this), self.tenant_id.clone())
            .await
        {
            logger::error!(message="Failed to log analytics event for payment attempt {attempt:?}", error_message=?er)
        }

        Ok(attempt)
    }

    #[cfg(feature = "v2")]
    async fn update_payment_attempt(
        &self,
        key_manager_state: &KeyManagerState,
        merchant_key_store: &domain::MerchantKeyStore,
        this: storage::PaymentAttempt,
        payment_attempt: storage::PaymentAttemptUpdate,
        storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<storage::PaymentAttempt, errors::StorageError> {
        let attempt = self
            .diesel_store
            .update_payment_attempt(
                key_manager_state,
                merchant_key_store,
                this.clone(),
                payment_attempt,
                storage_scheme,
            )
            .await?;

        if let Err(er) = self
            .kafka_producer
            .log_payment_attempt(&attempt, Some(this), self.tenant_id.clone())
            .await
        {
            logger::error!(message="Failed to log analytics event for payment attempt {attempt:?}", error_message=?er)
        }

        Ok(attempt)
    }

    #[cfg(feature = "v1")]
    async fn find_payment_attempt_by_connector_transaction_id_payment_id_merchant_id(
        &self,
        connector_transaction_id: &common_utils::types::ConnectorTransactionId,
        payment_id: &id_type::PaymentId,
        merchant_id: &id_type::MerchantId,
        storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<storage::PaymentAttempt, errors::StorageError> {
        self.diesel_store
            .find_payment_attempt_by_connector_transaction_id_payment_id_merchant_id(
                connector_transaction_id,
                payment_id,
                merchant_id,
                storage_scheme,
            )
            .await
    }

    #[cfg(feature = "v1")]
    async fn find_payment_attempt_by_merchant_id_connector_txn_id(
        &self,
        merchant_id: &id_type::MerchantId,
        connector_txn_id: &str,
        storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<storage::PaymentAttempt, errors::StorageError> {
        self.diesel_store
            .find_payment_attempt_by_merchant_id_connector_txn_id(
                merchant_id,
                connector_txn_id,
                storage_scheme,
            )
            .await
    }

    #[cfg(feature = "v2")]
    async fn find_payment_attempt_by_profile_id_connector_transaction_id(
        &self,
        key_manager_state: &KeyManagerState,
        merchant_key_store: &domain::MerchantKeyStore,
        profile_id: &id_type::ProfileId,
        connector_transaction_id: &str,
        storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<storage::PaymentAttempt, errors::StorageError> {
        self.diesel_store
            .find_payment_attempt_by_profile_id_connector_transaction_id(
                key_manager_state,
                merchant_key_store,
                profile_id,
                connector_transaction_id,
                storage_scheme,
            )
            .await
    }

    #[cfg(feature = "v1")]
    async fn find_payment_attempt_by_payment_id_merchant_id_attempt_id(
        &self,
        payment_id: &id_type::PaymentId,
        merchant_id: &id_type::MerchantId,
        attempt_id: &str,
        storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<storage::PaymentAttempt, errors::StorageError> {
        self.diesel_store
            .find_payment_attempt_by_payment_id_merchant_id_attempt_id(
                payment_id,
                merchant_id,
                attempt_id,
                storage_scheme,
            )
            .await
    }

    #[cfg(feature = "v1")]
    async fn find_payment_attempt_by_attempt_id_merchant_id(
        &self,
        attempt_id: &str,
        merchant_id: &id_type::MerchantId,
        storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<storage::PaymentAttempt, errors::StorageError> {
        self.diesel_store
            .find_payment_attempt_by_attempt_id_merchant_id(attempt_id, merchant_id, storage_scheme)
            .await
    }

    #[cfg(feature = "v2")]
    async fn find_payment_attempt_by_id(
        &self,
        key_manager_state: &KeyManagerState,
        merchant_key_store: &domain::MerchantKeyStore,
        attempt_id: &id_type::GlobalAttemptId,
        storage_scheme: MerchantStorageScheme,
    ) -> error_stack::Result<storage::PaymentAttempt, errors::StorageError> {
        self.diesel_store
            .find_payment_attempt_by_id(
                key_manager_state,
                merchant_key_store,
                attempt_id,
                storage_scheme,
            )
            .await
    }

    #[cfg(feature = "v2")]
    async fn find_payment_attempts_by_payment_intent_id(
        &self,
        key_manager_state: &KeyManagerState,
        payment_id: &id_type::GlobalPaymentId,
        merchant_key_store: &domain::MerchantKeyStore,
        storage_scheme: MerchantStorageScheme,
    ) -> error_stack::Result<Vec<storage::PaymentAttempt>, errors::StorageError> {
        self.diesel_store
            .find_payment_attempts_by_payment_intent_id(
                key_manager_state,
                payment_id,
                merchant_key_store,
                storage_scheme,
            )
            .await
    }

    #[cfg(feature = "v1")]
    async fn find_payment_attempt_last_successful_attempt_by_payment_id_merchant_id(
        &self,
        payment_id: &id_type::PaymentId,
        merchant_id: &id_type::MerchantId,
        storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<storage::PaymentAttempt, errors::StorageError> {
        self.diesel_store
            .find_payment_attempt_last_successful_attempt_by_payment_id_merchant_id(
                payment_id,
                merchant_id,
                storage_scheme,
            )
            .await
    }

    #[cfg(feature = "v1")]
    async fn find_payment_attempt_last_successful_or_partially_captured_attempt_by_payment_id_merchant_id(
        &self,
        payment_id: &id_type::PaymentId,
        merchant_id: &id_type::MerchantId,
        storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<storage::PaymentAttempt, errors::StorageError> {
        self.diesel_store
            .find_payment_attempt_last_successful_or_partially_captured_attempt_by_payment_id_merchant_id(
                payment_id,
                merchant_id,
                storage_scheme,
            )
            .await
    }

    #[cfg(feature = "v2")]
    async fn find_payment_attempt_last_successful_or_partially_captured_attempt_by_payment_id(
        &self,
        key_manager_state: &KeyManagerState,
        merchant_key_store: &domain::MerchantKeyStore,
        payment_id: &id_type::GlobalPaymentId,
        storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<storage::PaymentAttempt, errors::StorageError> {
        self.diesel_store
            .find_payment_attempt_last_successful_or_partially_captured_attempt_by_payment_id(
                key_manager_state,
                merchant_key_store,
                payment_id,
                storage_scheme,
            )
            .await
    }

    #[cfg(feature = "v1")]
    async fn find_payment_attempt_by_preprocessing_id_merchant_id(
        &self,
        preprocessing_id: &str,
        merchant_id: &id_type::MerchantId,
        storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<storage::PaymentAttempt, errors::StorageError> {
        self.diesel_store
            .find_payment_attempt_by_preprocessing_id_merchant_id(
                preprocessing_id,
                merchant_id,
                storage_scheme,
            )
            .await
    }

    #[cfg(feature = "v1")]
    async fn get_filters_for_payments(
        &self,
        pi: &[hyperswitch_domain_models::payments::PaymentIntent],
        merchant_id: &id_type::MerchantId,
        storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<
        hyperswitch_domain_models::payments::payment_attempt::PaymentListFilters,
        errors::StorageError,
    > {
        self.diesel_store
            .get_filters_for_payments(pi, merchant_id, storage_scheme)
            .await
    }

    #[cfg(feature = "v1")]
    async fn get_total_count_of_filtered_payment_attempts(
        &self,
        merchant_id: &id_type::MerchantId,
        active_attempt_ids: &[String],
        connector: Option<Vec<api_models::enums::Connector>>,
        payment_method: Option<Vec<common_enums::PaymentMethod>>,
        payment_method_type: Option<Vec<common_enums::PaymentMethodType>>,
        authentication_type: Option<Vec<common_enums::AuthenticationType>>,
        merchant_connector_id: Option<Vec<id_type::MerchantConnectorAccountId>>,
        card_network: Option<Vec<common_enums::CardNetwork>>,
        card_discovery: Option<Vec<common_enums::CardDiscovery>>,
        storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<i64, errors::StorageError> {
        self.diesel_store
            .get_total_count_of_filtered_payment_attempts(
                merchant_id,
                active_attempt_ids,
                connector,
                payment_method,
                payment_method_type,
                authentication_type,
                merchant_connector_id,
                card_network,
                card_discovery,
                storage_scheme,
            )
            .await
    }

    #[cfg(feature = "v2")]
    async fn get_total_count_of_filtered_payment_attempts(
        &self,
        merchant_id: &id_type::MerchantId,
        active_attempt_ids: &[String],
        connector: Option<Vec<api_models::enums::Connector>>,
        payment_method_type: Option<Vec<common_enums::PaymentMethod>>,
        payment_method_subtype: Option<Vec<common_enums::PaymentMethodType>>,
        authentication_type: Option<Vec<common_enums::AuthenticationType>>,
        merchant_connector_id: Option<Vec<id_type::MerchantConnectorAccountId>>,
        card_network: Option<Vec<common_enums::CardNetwork>>,
        storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<i64, errors::StorageError> {
        self.diesel_store
            .get_total_count_of_filtered_payment_attempts(
                merchant_id,
                active_attempt_ids,
                connector,
                payment_method_type,
                payment_method_subtype,
                authentication_type,
                merchant_connector_id,
                card_network,
                storage_scheme,
            )
            .await
    }

    #[cfg(feature = "v1")]
    async fn find_attempts_by_merchant_id_payment_id(
        &self,
        merchant_id: &id_type::MerchantId,
        payment_id: &id_type::PaymentId,
        storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<Vec<storage::PaymentAttempt>, errors::StorageError> {
        self.diesel_store
            .find_attempts_by_merchant_id_payment_id(merchant_id, payment_id, storage_scheme)
            .await
    }
}

#[async_trait::async_trait]
impl PaymentIntentInterface for KafkaStore {
    type Error = errors::StorageError;
    async fn update_payment_intent(
        &self,
        state: &KeyManagerState,
        this: storage::PaymentIntent,
        payment_intent: storage::PaymentIntentUpdate,
        key_store: &domain::MerchantKeyStore,
        storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<storage::PaymentIntent, errors::StorageError> {
        let intent = self
            .diesel_store
            .update_payment_intent(
                state,
                this.clone(),
                payment_intent.clone(),
                key_store,
                storage_scheme,
            )
            .await?;

        if let Err(er) = self
            .kafka_producer
            .log_payment_intent(
                &intent,
                Some(this),
                self.tenant_id.clone(),
                state.add_confirm_value_in_infra_values(payment_intent.is_confirm_operation()),
            )
            .await
        {
            logger::error!(message="Failed to add analytics entry for Payment Intent {intent:?}", error_message=?er);
        };

        Ok(intent)
    }

    async fn insert_payment_intent(
        &self,
        state: &KeyManagerState,
        new: storage::PaymentIntent,
        key_store: &domain::MerchantKeyStore,
        storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<storage::PaymentIntent, errors::StorageError> {
        logger::debug!("Inserting PaymentIntent Via KafkaStore");
        let intent = self
            .diesel_store
            .insert_payment_intent(state, new, key_store, storage_scheme)
            .await?;

        if let Err(er) = self
            .kafka_producer
            .log_payment_intent(
                &intent,
                None,
                self.tenant_id.clone(),
                state.infra_values.clone(),
            )
            .await
        {
            logger::error!(message="Failed to add analytics entry for Payment Intent {intent:?}", error_message=?er);
        };

        Ok(intent)
    }

    #[cfg(feature = "v1")]
    async fn find_payment_intent_by_payment_id_merchant_id(
        &self,
        state: &KeyManagerState,
        payment_id: &id_type::PaymentId,
        merchant_id: &id_type::MerchantId,
        key_store: &domain::MerchantKeyStore,
        storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<storage::PaymentIntent, errors::StorageError> {
        self.diesel_store
            .find_payment_intent_by_payment_id_merchant_id(
                state,
                payment_id,
                merchant_id,
                key_store,
                storage_scheme,
            )
            .await
    }

    #[cfg(feature = "v2")]
    async fn find_payment_intent_by_id(
        &self,
        state: &KeyManagerState,
        payment_id: &id_type::GlobalPaymentId,
        key_store: &domain::MerchantKeyStore,
        storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<storage::PaymentIntent, errors::StorageError> {
        self.diesel_store
            .find_payment_intent_by_id(state, payment_id, key_store, storage_scheme)
            .await
    }

    #[cfg(all(feature = "olap", feature = "v1"))]
    async fn filter_payment_intent_by_constraints(
        &self,
        state: &KeyManagerState,
        merchant_id: &id_type::MerchantId,
        filters: &hyperswitch_domain_models::payments::payment_intent::PaymentIntentFetchConstraints,
        key_store: &domain::MerchantKeyStore,
        storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<Vec<storage::PaymentIntent>, errors::StorageError> {
        self.diesel_store
            .filter_payment_intent_by_constraints(
                state,
                merchant_id,
                filters,
                key_store,
                storage_scheme,
            )
            .await
    }

    #[cfg(all(feature = "olap", feature = "v1"))]
    async fn filter_payment_intents_by_time_range_constraints(
        &self,
        state: &KeyManagerState,
        merchant_id: &id_type::MerchantId,
        time_range: &common_utils::types::TimeRange,
        key_store: &domain::MerchantKeyStore,
        storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<Vec<storage::PaymentIntent>, errors::StorageError> {
        self.diesel_store
            .filter_payment_intents_by_time_range_constraints(
                state,
                merchant_id,
                time_range,
                key_store,
                storage_scheme,
            )
            .await
    }
    #[cfg(feature = "olap")]
    async fn get_intent_status_with_count(
        &self,
        merchant_id: &id_type::MerchantId,
        profile_id_list: Option<Vec<id_type::ProfileId>>,
        time_range: &common_utils::types::TimeRange,
    ) -> error_stack::Result<Vec<(common_enums::IntentStatus, i64)>, errors::StorageError> {
        self.diesel_store
            .get_intent_status_with_count(merchant_id, profile_id_list, time_range)
            .await
    }

    #[cfg(all(feature = "olap", feature = "v1"))]
    async fn get_filtered_payment_intents_attempt(
        &self,
        state: &KeyManagerState,
        merchant_id: &id_type::MerchantId,
        constraints: &hyperswitch_domain_models::payments::payment_intent::PaymentIntentFetchConstraints,
        key_store: &domain::MerchantKeyStore,
        storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<
        Vec<(
            hyperswitch_domain_models::payments::PaymentIntent,
            hyperswitch_domain_models::payments::payment_attempt::PaymentAttempt,
        )>,
        errors::StorageError,
    > {
        self.diesel_store
            .get_filtered_payment_intents_attempt(
                state,
                merchant_id,
                constraints,
                key_store,
                storage_scheme,
            )
            .await
    }

    #[cfg(all(feature = "olap", feature = "v2"))]
    async fn get_filtered_payment_intents_attempt(
        &self,
        state: &KeyManagerState,
        merchant_id: &id_type::MerchantId,
        constraints: &hyperswitch_domain_models::payments::payment_intent::PaymentIntentFetchConstraints,
        key_store: &domain::MerchantKeyStore,
        storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<
        Vec<(
            hyperswitch_domain_models::payments::PaymentIntent,
            Option<hyperswitch_domain_models::payments::payment_attempt::PaymentAttempt>,
        )>,
        errors::StorageError,
    > {
        self.diesel_store
            .get_filtered_payment_intents_attempt(
                state,
                merchant_id,
                constraints,
                key_store,
                storage_scheme,
            )
            .await
    }

    #[cfg(all(feature = "olap", feature = "v1"))]
    async fn get_filtered_active_attempt_ids_for_total_count(
        &self,
        merchant_id: &id_type::MerchantId,
        constraints: &hyperswitch_domain_models::payments::payment_intent::PaymentIntentFetchConstraints,
        storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<Vec<String>, errors::StorageError> {
        self.diesel_store
            .get_filtered_active_attempt_ids_for_total_count(
                merchant_id,
                constraints,
                storage_scheme,
            )
            .await
    }

    #[cfg(feature = "v2")]
    async fn find_payment_intent_by_merchant_reference_id_profile_id(
        &self,
        state: &KeyManagerState,
        merchant_reference_id: &id_type::PaymentReferenceId,
        profile_id: &id_type::ProfileId,
        merchant_key_store: &domain::MerchantKeyStore,
        storage_scheme: &MerchantStorageScheme,
    ) -> error_stack::Result<hyperswitch_domain_models::payments::PaymentIntent, errors::StorageError>
    {
        self.diesel_store
            .find_payment_intent_by_merchant_reference_id_profile_id(
                state,
                merchant_reference_id,
                profile_id,
                merchant_key_store,
                storage_scheme,
            )
            .await
    }
    #[cfg(all(feature = "olap", feature = "v2"))]
    async fn get_filtered_active_attempt_ids_for_total_count(
        &self,
        merchant_id: &id_type::MerchantId,
        constraints: &hyperswitch_domain_models::payments::payment_intent::PaymentIntentFetchConstraints,
        storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<Vec<Option<String>>, errors::StorageError> {
        self.diesel_store
            .get_filtered_active_attempt_ids_for_total_count(
                merchant_id,
                constraints,
                storage_scheme,
            )
            .await
    }
}

#[async_trait::async_trait]
impl PaymentMethodInterface for KafkaStore {
    type Error = errors::StorageError;
    #[cfg(feature = "v1")]
    async fn find_payment_method(
        &self,
        state: &KeyManagerState,
        key_store: &domain::MerchantKeyStore,
        payment_method_id: &str,
        storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<domain::PaymentMethod, errors::StorageError> {
        self.diesel_store
            .find_payment_method(state, key_store, payment_method_id, storage_scheme)
            .await
    }

    #[cfg(feature = "v2")]
    async fn find_payment_method(
        &self,
        state: &KeyManagerState,
        key_store: &domain::MerchantKeyStore,
        payment_method_id: &id_type::GlobalPaymentMethodId,
        storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<domain::PaymentMethod, errors::StorageError> {
        self.diesel_store
            .find_payment_method(state, key_store, payment_method_id, storage_scheme)
            .await
    }

    #[cfg(feature = "v1")]
    async fn find_payment_method_by_customer_id_merchant_id_list(
        &self,
        state: &KeyManagerState,
        key_store: &domain::MerchantKeyStore,
        customer_id: &id_type::CustomerId,
        merchant_id: &id_type::MerchantId,
        limit: Option<i64>,
    ) -> CustomResult<Vec<domain::PaymentMethod>, errors::StorageError> {
        self.diesel_store
            .find_payment_method_by_customer_id_merchant_id_list(
                state,
                key_store,
                customer_id,
                merchant_id,
                limit,
            )
            .await
    }

    #[cfg(feature = "v2")]
    async fn find_payment_method_list_by_global_customer_id(
        &self,
        state: &KeyManagerState,
        key_store: &domain::MerchantKeyStore,
        id: &id_type::GlobalCustomerId,
        limit: Option<i64>,
    ) -> CustomResult<Vec<domain::PaymentMethod>, errors::StorageError> {
        self.diesel_store
            .find_payment_method_list_by_global_customer_id(state, key_store, id, limit)
            .await
    }

    #[cfg(feature = "v1")]
    async fn find_payment_method_by_customer_id_merchant_id_status(
        &self,
        state: &KeyManagerState,
        key_store: &domain::MerchantKeyStore,
        customer_id: &id_type::CustomerId,
        merchant_id: &id_type::MerchantId,
        status: common_enums::PaymentMethodStatus,
        limit: Option<i64>,
        storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<Vec<domain::PaymentMethod>, errors::StorageError> {
        self.diesel_store
            .find_payment_method_by_customer_id_merchant_id_status(
                state,
                key_store,
                customer_id,
                merchant_id,
                status,
                limit,
                storage_scheme,
            )
            .await
    }

    #[cfg(feature = "v2")]
    async fn find_payment_method_by_global_customer_id_merchant_id_status(
        &self,


pub async fn verify_totp(
    state: SessionState,
    user_token: auth::UserIdFromAuth,
    req: user_api::VerifyTotpRequest,
) -> UserResponse<user_api::TokenResponse> {
    let user_from_db: domain::UserFromStorage = state
        .global_store
        .find_user_by_id(&user_token.user_id)
        .await
        .change_context(UserErrors::InternalServerError)?
        .into();

    if user_from_db.get_totp_status() != TotpStatus::Set {
        return Err(UserErrors::TotpNotSetup.into());
    }

    let user_totp_attempts =
        tfa_utils::get_totp_attempts_from_redis(&state, &user_token.user_id).await?;

    if user_totp_attempts >= consts::user::TOTP_MAX_ATTEMPTS {
        return Err(UserErrors::MaxTotpAttemptsReached.into());
    }

    let user_totp_secret = user_from_db
        .decrypt_and_get_totp_secret(&state)
        .await?
        .ok_or(UserErrors::InternalServerError)?;

    let totp = tfa_utils::generate_default_totp(
        user_from_db.get_email(),
        Some(user_totp_secret),
        state.conf.user.totp_issuer_name.clone(),
    )?;

    if totp
        .generate_current()
        .change_context(UserErrors::InternalServerError)?
        != req.totp.expose()
    {
        let _ = tfa_utils::insert_totp_attempts_in_redis(
            &state,
            &user_token.user_id,
            user_totp_attempts + 1,
        )
        .await
        .inspect_err(|error| logger::error!(?error));
        return Err(UserErrors::InvalidTotp.into());
    }

    tfa_utils::insert_totp_in_redis(&state, &user_token.user_id).await?;

    Ok(ApplicationResponse::StatusOk)
}


File: crates/router/src/core/fraud_check/flows/transaction_flow.rs
 Public functions: 1

use async_trait::async_trait;
use common_utils::ext_traits::ValueExt;
use error_stack::ResultExt;

use crate::{
    core::{
        errors::{ConnectorErrorExt, RouterResult},
        fraud_check::{FeatureFrm, FrmData},
        payments::{self, flows::ConstructFlowSpecificData, helpers},
    },
    errors, services,
    types::{
        api::fraud_check as frm_api,
        domain,
        fraud_check::{
            FraudCheckResponseData, FraudCheckTransactionData, FrmTransactionRouterData,
        },
        storage::enums as storage_enums,
        ConnectorAuthType, MerchantRecipientData, ResponseId, RouterData,
    },
    SessionState,
};

#[async_trait]
impl
    ConstructFlowSpecificData<
        frm_api::Transaction,
        FraudCheckTransactionData,
        FraudCheckResponseData,
    > for FrmData
{
    #[cfg(feature = "v2")]
    async fn construct_router_data<'a>(
        &self,
        _state: &SessionState,
        _connector_id: &str,
        _merchant_context: &domain::MerchantContext,
        _customer: &Option<domain::Customer>,
        _merchant_connector_account: &domain::MerchantConnectorAccountTypeDetails,
        _merchant_recipient_data: Option<MerchantRecipientData>,
        _header_payload: Option<hyperswitch_domain_models::payments::HeaderPayload>,
    ) -> RouterResult<
        RouterData<frm_api::Transaction, FraudCheckTransactionData, FraudCheckResponseData>,
    > {
        todo!()
    }

    #[cfg(feature = "v1")]
    async fn construct_router_data<'a>(
        &self,
        state: &SessionState,
        connector_id: &str,
        merchant_context: &domain::MerchantContext,
        customer: &Option<domain::Customer>,
        merchant_connector_account: &helpers::MerchantConnectorAccountType,
        _merchant_recipient_data: Option<MerchantRecipientData>,
        header_payload: Option<hyperswitch_domain_models::payments::HeaderPayload>,
    ) -> RouterResult<
        RouterData<frm_api::Transaction, FraudCheckTransactionData, FraudCheckResponseData>,
    > {
        let status = storage_enums::AttemptStatus::Pending;

        let auth_type: ConnectorAuthType = merchant_connector_account
            .get_connector_account_details()
            .parse_value("ConnectorAuthType")
            .change_context(errors::ApiErrorResponse::MerchantConnectorAccountNotFound {
                id: "ConnectorAuthType".to_string(),
            })?;

        let customer_id = customer.to_owned().map(|customer| customer.customer_id);

        let payment_method = self.payment_attempt.payment_method;
        let currency = self.payment_attempt.currency;

        let router_data = RouterData {
            flow: std::marker::PhantomData,
            merchant_id: merchant_context.get_merchant_account().get_id().clone(),
            tenant_id: state.tenant.tenant_id.clone(),
            customer_id,
            connector: connector_id.to_string(),
            payment_id: self.payment_intent.payment_id.get_string_repr().to_owned(),
            attempt_id: self.payment_attempt.attempt_id.clone(),
            status,
            payment_method: self
                .payment_attempt
                .payment_method
                .ok_or(errors::ApiErrorResponse::PaymentMethodNotFound)?,
            connector_auth_type: auth_type,
            description: None,
            address: self.address.clone(),
            auth_type: storage_enums::AuthenticationType::NoThreeDs,
            connector_meta_data: None,
            connector_wallets_details: None,
            amount_captured: None,
            minor_amount_captured: None,
            request: FraudCheckTransactionData {
                amount: self
                    .payment_attempt
                    .net_amount
                    .get_total_amount()
                    .get_amount_as_i64(),
                order_details: self.order_details.clone(),
                currency,
                payment_method,
                error_code: self.payment_attempt.error_code.clone(),
                error_message: self.payment_attempt.error_message.clone(),
                connector_transaction_id: self
                    .payment_attempt
                    .get_connector_payment_id()
                    .map(ToString::to_string),
                connector: self.payment_attempt.connector.clone(),
            }, // self.order_details
            response: Ok(FraudCheckResponseData::TransactionResponse {
                resource_id: ResponseId::ConnectorTransactionId("".to_string()),
                connector_metadata: None,
                status: storage_enums::FraudCheckStatus::Pending,
                score: None,
                reason: None,
            }),
            access_token: None,
            session_token: None,
            reference_id: None,
            payment_method_token: None,
            connector_customer: None,
            preprocessing_id: None,
            connector_request_reference_id: uuid::Uuid::new_v4().to_string(),
            test_mode: None,
            recurring_mandate_payment_data: None,
            #[cfg(feature = "payouts")]
            payout_method_data: None,
            #[cfg(feature = "payouts")]
            quote_id: None,
            payment_method_balance: None,
            connector_http_status_code: None,
            external_latency: None,
            connector_api_version: None,
            payment_method_status: None,
            apple_pay_flow: None,
            frm_metadata: self.frm_metadata.clone(),
            refund_id: None,
            dispute_id: None,
            connector_response: None,
            integrity_check: Ok(()),
            additional_merchant_data: None,
            header_payload,
            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)
    }
}

#[async_trait]
impl FeatureFrm<frm_api::Transaction, FraudCheckTransactionData> for FrmTransactionRouterData {
    async fn decide_frm_flows<'a>(
        mut self,
        state: &SessionState,
        connector: &frm_api::FraudCheckConnectorData,
        call_connector_action: payments::CallConnectorAction,
        merchant_context: &domain::MerchantContext,
    ) -> RouterResult<Self> {
        decide_frm_flow(
            &mut self,
            state,
            connector,
            call_connector_action,
            merchant_context,
        )
        .await
    }
}

pub async fn decide_frm_flow(
    router_data: &mut FrmTransactionRouterData,
    state: &SessionState,
    connector: &frm_api::FraudCheckConnectorData,
    call_connector_action: payments::CallConnectorAction,
    _merchant_context: &domain::MerchantContext,
) -> RouterResult<FrmTransactionRouterData> {
    let connector_integration: services::BoxedFrmConnectorIntegrationInterface<
        frm_api::Transaction,
        FraudCheckTransactionData,
        FraudCheckResponseData,
    > = connector.connector.get_connector_integration();
    let resp = services::execute_connector_processing_step(
        state,
        connector_integration,
        router_data,
        call_connector_action,
        None,
        None,
    )
    .await
    .to_payment_failed_response()?;

    Ok(resp)
}


pub struct FailedTransactionData {
    id: String,
    payment_details: Vec<DeclinedPaymentDetails>,
}


File: crates/diesel_models/src/cards_info.rs
 Public structs: 2

use diesel::{AsChangeset, Identifiable, Insertable, Queryable, Selectable};
use time::PrimitiveDateTime;

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

#[derive(
    Clone,
    Debug,
    Queryable,
    Identifiable,
    Selectable,
    serde::Deserialize,
    serde::Serialize,
    Insertable,
)]
#[diesel(table_name = cards_info, primary_key(card_iin), check_for_backend(diesel::pg::Pg))]
pub struct CardInfo {
    pub card_iin: String,
    pub card_issuer: Option<String>,
    pub card_network: Option<storage_enums::CardNetwork>,
    pub card_type: Option<String>,
    pub card_subtype: Option<String>,
    pub card_issuing_country: Option<String>,
    pub bank_code_id: Option<String>,
    pub bank_code: Option<String>,
    pub country_code: Option<String>,
    pub date_created: PrimitiveDateTime,
    pub last_updated: Option<PrimitiveDateTime>,
    pub last_updated_provider: Option<String>,
}

#[derive(
    Clone, Debug, PartialEq, Eq, AsChangeset, router_derive::DebugAsDisplay, serde::Deserialize,
)]
#[diesel(table_name = cards_info)]
pub struct UpdateCardInfo {
    pub card_issuer: Option<String>,
    pub card_network: Option<storage_enums::CardNetwork>,
    pub card_type: Option<String>,
    pub card_subtype: Option<String>,
    pub card_issuing_country: Option<String>,
    pub bank_code_id: Option<String>,
    pub bank_code: Option<String>,
    pub country_code: Option<String>,
    pub last_updated: Option<PrimitiveDateTime>,
    pub last_updated_provider: Option<String>,
}


pub async fn get_metrics(
    pool: &AnalyticsProvider,
    auth: &AuthInfo,
    req: GetAuthEventMetricRequest,
) -> AnalyticsResult<AuthEventMetricsResponse<MetricsBucketResponse>> {
    let mut metrics_accumulator: HashMap<
        AuthEventMetricsBucketIdentifier,
        AuthEventMetricsAccumulator,
    > = HashMap::new();

    let mut set = tokio::task::JoinSet::new();
    for metric_type in req.metrics.iter().cloned() {
        let req = req.clone();
        let auth_scoped = auth.to_owned();
        let pool = pool.clone();
        set.spawn(async move {
            let data = pool
                .get_auth_event_metrics(
                    &metric_type,
                    &req.group_by_names.clone(),
                    &auth_scoped,
                    &req.filters,
                    req.time_series.map(|t| t.granularity),
                    &req.time_range,
                )
                .await
                .change_context(AnalyticsError::UnknownError);
            (metric_type, data)
        });
    }

    while let Some((metric, data)) = set
        .join_next()
        .await
        .transpose()
        .change_context(AnalyticsError::UnknownError)?
    {
        for (id, value) in data? {
            let metrics_builder = metrics_accumulator.entry(id).or_default();
            match metric {
                AuthEventMetrics::AuthenticationCount => metrics_builder
                    .authentication_count
                    .add_metrics_bucket(&value),
                AuthEventMetrics::AuthenticationAttemptCount => metrics_builder
                    .authentication_attempt_count
                    .add_metrics_bucket(&value),
                AuthEventMetrics::AuthenticationSuccessCount => metrics_builder
                    .authentication_success_count
                    .add_metrics_bucket(&value),
                AuthEventMetrics::ChallengeFlowCount => metrics_builder
                    .challenge_flow_count
                    .add_metrics_bucket(&value),
                AuthEventMetrics::ChallengeAttemptCount => metrics_builder
                    .challenge_attempt_count
                    .add_metrics_bucket(&value),
                AuthEventMetrics::ChallengeSuccessCount => metrics_builder
                    .challenge_success_count
                    .add_metrics_bucket(&value),
                AuthEventMetrics::FrictionlessFlowCount => metrics_builder
                    .frictionless_flow_count
                    .add_metrics_bucket(&value),
                AuthEventMetrics::FrictionlessSuccessCount => metrics_builder
                    .frictionless_success_count
                    .add_metrics_bucket(&value),
                AuthEventMetrics::AuthenticationErrorMessage => metrics_builder
                    .authentication_error_message
                    .add_metrics_bucket(&value),
                AuthEventMetrics::AuthenticationFunnel => metrics_builder
                    .authentication_funnel
                    .add_metrics_bucket(&value),
                AuthEventMetrics::AuthenticationExemptionApprovedCount => metrics_builder
                    .authentication_exemption_approved_count
                    .add_metrics_bucket(&value),
                AuthEventMetrics::AuthenticationExemptionRequestedCount => metrics_builder
                    .authentication_exemption_requested_count
                    .add_metrics_bucket(&value),
            }
        }
    }

    let mut total_error_message_count = 0;
    let query_data: Vec<MetricsBucketResponse> = metrics_accumulator
        .into_iter()
        .map(|(id, val)| {
            let collected_values = val.collect();
            if let Some(count) = collected_values.error_message_count {
                total_error_message_count += count;
            }
            MetricsBucketResponse {
                values: collected_values,
                dimensions: id,
            }
        })
        .collect();
    Ok(AuthEventMetricsResponse {
        query_data,
        meta_data: [AuthEventsAnalyticsMetadata {
            total_error_message_count: Some(total_error_message_count),
        }],
    })
}