pub async fn filter_payout_methods(
    state: &SessionState,
    merchant_context: &domain::MerchantContext,
    payout: &hyperswitch_domain_models::payouts::payouts::Payouts,
    address: Option<&domain::Address>,
) -> errors::RouterResult<Vec<link_utils::EnabledPaymentMethod>> {
    use masking::ExposeInterface;

    let db = &*state.store;
    let key_manager_state = &state.into();
    //Fetch all merchant connector accounts
    let all_mcas = db
        .find_merchant_connector_account_by_merchant_id_and_disabled_list(
            key_manager_state,
            merchant_context.get_merchant_account().get_id(),
            false,
            merchant_context.get_merchant_key_store(),
        )
        .await
        .to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound)?;
    // Filter MCAs based on profile_id and connector_type
    let filtered_mcas = all_mcas.filter_based_on_profile_and_connector_type(
        &payout.profile_id,
        common_enums::ConnectorType::PayoutProcessor,
    );

    let mut response: Vec<link_utils::EnabledPaymentMethod> = vec![];
    let mut payment_method_list_hm: HashMap<
        common_enums::PaymentMethod,
        HashSet<common_enums::PaymentMethodType>,
    > = HashMap::new();
    let mut bank_transfer_hash_set: HashSet<common_enums::PaymentMethodType> = HashSet::new();
    let mut card_hash_set: HashSet<common_enums::PaymentMethodType> = HashSet::new();
    let mut wallet_hash_set: HashSet<common_enums::PaymentMethodType> = HashSet::new();
    let payout_filter_config = &state.conf.payout_method_filters.clone();
    for mca in &filtered_mcas {
        let payout_methods = match &mca.payment_methods_enabled {
            Some(pm) => pm,
            None => continue,
        };
        for payout_method in payout_methods.iter() {
            let parse_result = serde_json::from_value::<api_models::admin::PaymentMethodsEnabled>(
                payout_method.clone().expose(),
            );
            if let Ok(payment_methods_enabled) = parse_result {
                let payment_method = payment_methods_enabled.payment_method;
                let payment_method_types = match payment_methods_enabled.payment_method_types {
                    Some(payment_method_types) => payment_method_types,
                    None => continue,
                };
                let connector = mca.connector_name.clone();
                let payout_filter = payout_filter_config.0.get(&connector);
                for request_payout_method_type in &payment_method_types {
                    let currency_country_filter = check_currency_country_filters(
                        payout_filter,
                        request_payout_method_type,
                        payout.destination_currency,
                        address
                            .as_ref()
                            .and_then(|address| address.country)
                            .as_ref(),
                    )?;
                    if currency_country_filter.unwrap_or(true) {
                        match payment_method {
                            common_enums::PaymentMethod::Card => {
                                card_hash_set
                                    .insert(request_payout_method_type.payment_method_type);
                                payment_method_list_hm
                                    .insert(payment_method, card_hash_set.clone());
                            }
                            common_enums::PaymentMethod::Wallet => {
                                wallet_hash_set
                                    .insert(request_payout_method_type.payment_method_type);
                                payment_method_list_hm
                                    .insert(payment_method, wallet_hash_set.clone());
                            }
                            common_enums::PaymentMethod::BankTransfer => {
                                bank_transfer_hash_set
                                    .insert(request_payout_method_type.payment_method_type);
                                payment_method_list_hm
                                    .insert(payment_method, bank_transfer_hash_set.clone());
                            }
                            common_enums::PaymentMethod::CardRedirect
                            | common_enums::PaymentMethod::PayLater
                            | common_enums::PaymentMethod::BankRedirect
                            | common_enums::PaymentMethod::Crypto
                            | common_enums::PaymentMethod::BankDebit
                            | common_enums::PaymentMethod::Reward
                            | common_enums::PaymentMethod::RealTimePayment
                            | common_enums::PaymentMethod::MobilePayment
                            | common_enums::PaymentMethod::Upi
                            | common_enums::PaymentMethod::Voucher
                            | common_enums::PaymentMethod::OpenBanking
                            | common_enums::PaymentMethod::GiftCard => continue,
                        }
                    }
                }
            }
        }
    }
    for (payment_method, payment_method_types) in payment_method_list_hm {
        if !payment_method_types.is_empty() {
            let enabled_payment_method = link_utils::EnabledPaymentMethod {
                payment_method,
                payment_method_types,
            };
            response.push(enabled_payment_method);
        }
    }
    Ok(response)
}


impl api::PaymentAuthorize for Globalpay {}

impl api::PaymentAuthorize for for Globalpay


pub struct ApiKeyExpiryWorkflow;


pub struct OutgoingWebhookLogsRequest {
    pub payment_id: common_utils::id_type::PaymentId,
    pub event_id: Option<String>,
    pub refund_id: Option<String>,
    pub dispute_id: Option<String>,
    pub mandate_id: Option<String>,
    pub payment_method_id: Option<String>,
    pub attempt_id: Option<String>,
}


pub trait DomainType: Debug + Sync + Conversion {}


File: crates/hyperswitch_connectors/src/connectors/stax.rs
 Public structs: 1

pub mod transformers;

use std::{fmt::Debug, sync::LazyLock};

use api_models::webhooks::IncomingWebhookEvent;
use common_enums::enums;
use common_utils::{
    errors::CustomResult,
    ext_traits::ByteSliceExt,
    request::{Method, Request, RequestBuilder, RequestContent},
};
use error_stack::ResultExt;
use hyperswitch_domain_models::{
    router_data::{AccessToken, ConnectorAuthType, ErrorResponse, RouterData},
    router_flow_types::{
        access_token_auth::AccessTokenAuth,
        payments::{
            Authorize, Capture, CreateConnectorCustomer, PSync, PaymentMethodToken, Session,
            SetupMandate, Void,
        },
        refunds::{Execute, RSync},
    },
    router_request_types::{
        AccessTokenRequestData, ConnectorCustomerData, PaymentMethodTokenizationData,
        PaymentsAuthorizeData, PaymentsCancelData, PaymentsCaptureData, PaymentsSessionData,
        PaymentsSyncData, RefundsData, SetupMandateRequestData,
    },
    router_response_types::{
        ConnectorInfo, PaymentMethodDetails, PaymentsResponseData, RefundsResponseData,
        SupportedPaymentMethods, SupportedPaymentMethodsExt,
    },
    types::{
        ConnectorCustomerRouterData, PaymentsAuthorizeRouterData, PaymentsCancelRouterData,
        PaymentsCaptureRouterData, PaymentsSyncRouterData, RefundSyncRouterData, RefundsRouterData,
        TokenizationRouterData,
    },
};
use hyperswitch_interfaces::{
    api::{
        self, ConnectorCommon, ConnectorCommonExt, ConnectorIntegration, ConnectorSpecifications,
        ConnectorValidation,
    },
    configs::Connectors,
    consts, errors,
    events::connector_api_logs::ConnectorEvent,
    types::{self, Response},
    webhooks,
};
use masking::{Mask, PeekInterface, Secret};
use transformers as stax;

use self::stax::StaxWebhookEventType;
use crate::{
    constants::headers,
    types::ResponseRouterData,
    utils::{self, RefundsRequestData},
};
#[derive(Debug, Clone)]
pub struct Stax;

impl api::Payment for Stax {}
impl api::PaymentSession for Stax {}
impl api::ConnectorAccessToken for Stax {}
impl api::MandateSetup for Stax {}
impl api::PaymentAuthorize for Stax {}
impl api::PaymentSync for Stax {}
impl api::PaymentCapture for Stax {}
impl api::PaymentVoid for Stax {}
impl api::Refund for Stax {}
impl api::RefundExecute for Stax {}
impl api::RefundSync for Stax {}
impl api::PaymentToken for Stax {}

impl<Flow, Request, Response> ConnectorCommonExt<Flow, Request, Response> for Stax
where
    Self: ConnectorIntegration<Flow, Request, Response>,
{
    fn build_headers(
        &self,
        req: &RouterData<Flow, Request, Response>,
        _connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        let mut header = vec![(
            headers::CONTENT_TYPE.to_string(),
            types::PaymentsAuthorizeType::get_content_type(self)
                .to_string()
                .into(),
        )];
        let mut api_key = self.get_auth_header(&req.connector_auth_type)?;
        header.append(&mut api_key);
        Ok(header)
    }
}

impl ConnectorCommon for Stax {
    fn id(&self) -> &'static str {
        "stax"
    }

    fn get_currency_unit(&self) -> api::CurrencyUnit {
        api::CurrencyUnit::Base
    }

    fn common_get_content_type(&self) -> &'static str {
        "application/json"
    }

    fn base_url<'a>(&self, connectors: &'a Connectors) -> &'a str {
        connectors.stax.base_url.as_ref()
    }

    fn get_auth_header(
        &self,
        auth_type: &ConnectorAuthType,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        let auth = stax::StaxAuthType::try_from(auth_type)
            .change_context(errors::ConnectorError::FailedToObtainAuthType)?;

        Ok(vec![(
            headers::AUTHORIZATION.to_string(),
            format!("Bearer {}", auth.api_key.peek()).into_masked(),
        )])
    }

    fn build_error_response(
        &self,
        res: Response,
        _event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        Ok(ErrorResponse {
            status_code: res.status_code,
            code: consts::NO_ERROR_CODE.to_string(),
            message: consts::NO_ERROR_MESSAGE.to_string(),
            reason: Some(
                std::str::from_utf8(&res.response)
                    .change_context(errors::ConnectorError::ResponseDeserializationFailed)?
                    .to_owned(),
            ),
            attempt_status: None,
            connector_transaction_id: None,
            network_advice_code: None,
            network_decline_code: None,
            network_error_message: None,
            connector_metadata: None,
        })
    }
}

impl ConnectorValidation for Stax {
    fn validate_connector_against_payment_request(
        &self,
        capture_method: Option<enums::CaptureMethod>,
        _payment_method: enums::PaymentMethod,
        _pmt: Option<enums::PaymentMethodType>,
    ) -> CustomResult<(), errors::ConnectorError> {
        let capture_method = capture_method.unwrap_or_default();
        match capture_method {
            enums::CaptureMethod::Automatic
            | enums::CaptureMethod::Manual
            | enums::CaptureMethod::SequentialAutomatic => Ok(()),
            enums::CaptureMethod::ManualMultiple | enums::CaptureMethod::Scheduled => Err(
                utils::construct_not_supported_error_report(capture_method, self.id()),
            ),
        }
    }
}

impl api::ConnectorCustomer for Stax {}

impl ConnectorIntegration<CreateConnectorCustomer, ConnectorCustomerData, PaymentsResponseData>
    for Stax
{
    fn get_headers(
        &self,
        req: &ConnectorCustomerRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        self.build_headers(req, connectors)
    }

    fn get_content_type(&self) -> &'static str {
        self.common_get_content_type()
    }

    fn get_url(
        &self,
        _req: &ConnectorCustomerRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        Ok(format!("{}customer", self.base_url(connectors),))
    }

    fn get_request_body(
        &self,
        req: &ConnectorCustomerRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let connector_req = stax::StaxCustomerRequest::try_from(req)?;

        Ok(RequestContent::Json(Box::new(connector_req)))
    }

    fn build_request(
        &self,
        req: &ConnectorCustomerRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        Ok(Some(
            RequestBuilder::new()
                .method(Method::Post)
                .url(&types::ConnectorCustomerType::get_url(
                    self, req, connectors,
                )?)
                .attach_default_headers()
                .headers(types::ConnectorCustomerType::get_headers(
                    self, req, connectors,
                )?)
                .set_body(types::ConnectorCustomerType::get_request_body(
                    self, req, connectors,
                )?)
                .build(),
        ))
    }

    fn handle_response(
        &self,
        data: &ConnectorCustomerRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<ConnectorCustomerRouterData, errors::ConnectorError>
    where
        PaymentsResponseData: Clone,
    {
        let response: stax::StaxCustomerResponse = res
            .response
            .parse_struct("StaxCustomerResponse")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;

        event_builder.map(|i| i.set_response_body(&response));
        router_env::logger::info!(connector_response=?response);

        RouterData::try_from(ResponseRouterData {
            response,
            data: data.clone(),
            http_code: res.status_code,
        })
    }

    fn get_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        self.build_error_response(res, event_builder)
    }
}

impl ConnectorIntegration<PaymentMethodToken, PaymentMethodTokenizationData, PaymentsResponseData>
    for Stax
{
    fn get_headers(
        &self,
        req: &TokenizationRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        self.build_headers(req, connectors)
    }

    fn get_content_type(&self) -> &'static str {
        self.common_get_content_type()
    }

    fn get_url(
        &self,
        _req: &TokenizationRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        Ok(format!("{}payment-method/", self.base_url(connectors)))
    }

    fn get_request_body(
        &self,
        req: &TokenizationRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let connector_req = stax::StaxTokenRequest::try_from(req)?;

        Ok(RequestContent::Json(Box::new(connector_req)))
    }

    fn build_request(
        &self,
        req: &TokenizationRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        Ok(Some(
            RequestBuilder::new()
                .method(Method::Post)
                .url(&types::TokenizationType::get_url(self, req, connectors)?)
                .attach_default_headers()
                .headers(types::TokenizationType::get_headers(self, req, connectors)?)
                .set_body(types::TokenizationType::get_request_body(
                    self, req, connectors,
                )?)
                .build(),
        ))
    }

    fn handle_response(
        &self,
        data: &TokenizationRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<TokenizationRouterData, errors::ConnectorError>
    where
        PaymentsResponseData: Clone,
    {
        let response: stax::StaxTokenResponse = res
            .response
            .parse_struct("StaxTokenResponse")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;

        event_builder.map(|i| i.set_response_body(&response));
        router_env::logger::info!(connector_response=?response);

        RouterData::try_from(ResponseRouterData {
            response,
            data: data.clone(),
            http_code: res.status_code,
        })
        .change_context(errors::ConnectorError::ResponseHandlingFailed)
    }
    fn get_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        self.build_error_response(res, event_builder)
    }
}

impl ConnectorIntegration<Session, PaymentsSessionData, PaymentsResponseData> for Stax {
    //TODO: implement sessions flow
}

impl ConnectorIntegration<AccessTokenAuth, AccessTokenRequestData, AccessToken> for Stax {}

impl ConnectorIntegration<SetupMandate, SetupMandateRequestData, PaymentsResponseData> for Stax {
    fn build_request(
        &self,
        _req: &RouterData<SetupMandate, SetupMandateRequestData, PaymentsResponseData>,
        _connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        Err(
            errors::ConnectorError::NotImplemented("Setup Mandate flow for Stax".to_string())
                .into(),
        )
    }
}

impl ConnectorIntegration<Authorize, PaymentsAuthorizeData, PaymentsResponseData> for Stax {
    fn get_headers(
        &self,
        req: &PaymentsAuthorizeRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        self.build_headers(req, connectors)
    }

    fn get_content_type(&self) -> &'static str {
        self.common_get_content_type()
    }

    fn get_url(
        &self,
        _req: &PaymentsAuthorizeRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        Ok(format!("{}charge", self.base_url(connectors),))
    }

    fn get_request_body(
        &self,
        req: &PaymentsAuthorizeRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let connector_router_data = stax::StaxRouterData::try_from((
            &self.get_currency_unit(),
            req.request.currency,
            req.request.amount,
            req,
        ))?;
        let connector_req = stax::StaxPaymentsRequest::try_from(&connector_router_data)?;

        Ok(RequestContent::Json(Box::new(connector_req)))
    }

    fn build_request(
        &self,
        req: &PaymentsAuthorizeRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        Ok(Some(
            RequestBuilder::new()
                .method(Method::Post)
                .url(&types::PaymentsAuthorizeType::get_url(
                    self, req, connectors,
                )?)
                .attach_default_headers()
                .headers(types::PaymentsAuthorizeType::get_headers(
                    self, req, connectors,
                )?)
                .set_body(types::PaymentsAuthorizeType::get_request_body(
                    self, req, connectors,
                )?)
                .build(),
        ))
    }

    fn handle_response(
        &self,
        data: &PaymentsAuthorizeRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<PaymentsAuthorizeRouterData, errors::ConnectorError> {
        let response: stax::StaxPaymentsResponse = res
            .response
            .parse_struct("StaxPaymentsAuthorizeResponse")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;

        event_builder.map(|i| i.set_response_body(&response));
        router_env::logger::info!(connector_response=?response);

        RouterData::try_from(ResponseRouterData {
            response,
            data: data.clone(),
            http_code: res.status_code,
        })
    }

    fn get_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        self.build_error_response(res, event_builder)
    }
}

impl ConnectorIntegration<PSync, PaymentsSyncData, PaymentsResponseData> for Stax {
    fn get_headers(
        &self,
        req: &PaymentsSyncRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        self.build_headers(req, connectors)
    }

    fn get_content_type(&self) -> &'static str {
        self.common_get_content_type()
    }

    fn get_url(
        &self,
        req: &PaymentsSyncRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        let connector_payment_id = req
            .request
            .connector_transaction_id
            .get_connector_transaction_id()
            .change_context(errors::ConnectorError::MissingConnectorTransactionID)?;

        Ok(format!(
            "{}/transaction/{connector_payment_id}",
            self.base_url(connectors),
        ))
    }

    fn build_request(
        &self,
        req: &PaymentsSyncRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        Ok(Some(
            RequestBuilder::new()
                .method(Method::Get)
                .url(&types::PaymentsSyncType::get_url(self, req, connectors)?)
                .attach_default_headers()
                .headers(types::PaymentsSyncType::get_headers(self, req, connectors)?)
                .build(),
        ))
    }

    fn handle_response(
        &self,
        data: &PaymentsSyncRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<PaymentsSyncRouterData, errors::ConnectorError> {
        let response: stax::StaxPaymentsResponse = res
            .response
            .parse_struct("StaxPaymentsSyncResponse")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;

        event_builder.map(|i| i.set_response_body(&response));
        router_env::logger::info!(connector_response=?response);

        RouterData::try_from(ResponseRouterData {
            response,
            data: data.clone(),
            http_code: res.status_code,
        })
    }

    fn get_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        self.build_error_response(res, event_builder)
    }
}

impl ConnectorIntegration<Capture, PaymentsCaptureData, PaymentsResponseData> for Stax {
    fn get_headers(
        &self,
        req: &PaymentsCaptureRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        self.build_headers(req, connectors)
    }

    fn get_content_type(&self) -> &'static str {
        self.common_get_content_type()
    }

    fn get_url(
        &self,
        req: &PaymentsCaptureRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        Ok(format!(
            "{}/transaction/{}/capture",
            self.base_url(connectors),
            req.request.connector_transaction_id,
        ))
    }

    fn get_request_body(
        &self,
        req: &PaymentsCaptureRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let connector_router_data = stax::StaxRouterData::try_from((
            &self.get_currency_unit(),
            req.request.currency,
            req.request.amount_to_capture,
            req,
        ))?;
        let connector_req = stax::StaxCaptureRequest::try_from(&connector_router_data)?;
        Ok(RequestContent::Json(Box::new(connector_req)))
    }

    fn build_request(
        &self,
        req: &PaymentsCaptureRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        Ok(Some(
            RequestBuilder::new()
                .method(Method::Post)
                .url(&types::PaymentsCaptureType::get_url(self, req, connectors)?)
                .attach_default_headers()
                .headers(types::PaymentsCaptureType::get_headers(
                    self, req, connectors,
                )?)
                .set_body(types::PaymentsCaptureType::get_request_body(
                    self, req, connectors,
                )?)
                .build(),
        ))
    }

    fn handle_response(
        &self,
        data: &PaymentsCaptureRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<PaymentsCaptureRouterData, errors::ConnectorError> {
        let response: stax::StaxPaymentsResponse = res
            .response
            .parse_struct("StaxPaymentsCaptureResponse")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;

        event_builder.map(|i| i.set_response_body(&response));
        router_env::logger::info!(connector_response=?response);

        RouterData::try_from(ResponseRouterData {
            response,
            data: data.clone(),
            http_code: res.status_code,
        })
    }

    fn get_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        self.build_error_response(res, event_builder)
    }
}

impl ConnectorIntegration<Void, PaymentsCancelData, PaymentsResponseData> for Stax {
    fn get_headers(
        &self,
        req: &PaymentsCancelRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        self.build_headers(req, connectors)
    }

    fn get_content_type(&self) -> &'static str {
        self.common_get_content_type()
    }

    fn get_url(
        &self,
        req: &PaymentsCancelRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        Ok(format!(
            "{}/transaction/{}/void-or-refund",
            self.base_url(connectors),
            req.request.connector_transaction_id,
        ))
    }

    fn build_request(
        &self,
        req: &PaymentsCancelRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        Ok(Some(
            RequestBuilder::new()
                .method(Method::Post)
                .url(&types::PaymentsVoidType::get_url(self, req, connectors)?)
                .attach_default_headers()
                .headers(types::PaymentsVoidType::get_headers(self, req, connectors)?)
                .build(),
        ))
    }

    fn handle_response(
        &self,
        data: &PaymentsCancelRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<PaymentsCancelRouterData, errors::ConnectorError> {
        let response: stax::StaxPaymentsResponse = res
            .response
            .parse_struct("StaxPaymentsVoidResponse")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;

        event_builder.map(|i| i.set_response_body(&response));
        router_env::logger::info!(connector_response=?response);

        RouterData::try_from(ResponseRouterData {
            response,
            data: data.clone(),
            http_code: res.status_code,
        })
    }

    fn get_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        self.build_error_response(res, event_builder)
    }
}

impl ConnectorIntegration<Execute, RefundsData, RefundsResponseData> for Stax {
    fn get_headers(
        &self,
        req: &RefundsRouterData<Execute>,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        self.build_headers(req, connectors)
    }

    fn get_content_type(&self) -> &'static str {
        self.common_get_content_type()
    }

    fn get_url(
        &self,
        req: &RefundsRouterData<Execute>,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        let connector_transaction_id = if req.request.connector_metadata.is_some() {
            let stax_capture: stax::StaxMetaData =
                utils::to_connector_meta(req.request.connector_metadata.clone())?;
            stax_capture.capture_id
        } else {
            req.request.connector_transaction_id.clone()
        };

        Ok(format!(
            "{}/transaction/{}/refund",
            self.base_url(connectors),
            connector_transaction_id,
        ))
    }

    fn get_request_body(
        &self,
        req: &RefundsRouterData<Execute>,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let connector_router_data = stax::StaxRouterData::try_from((
            &self.get_currency_unit(),
            req.request.currency,
            req.request.refund_amount,
            req,
        ))?;
        let connector_req = stax::StaxRefundRequest::try_from(&connector_router_data)?;
        Ok(RequestContent::Json(Box::new(connector_req)))
    }

    fn build_request(
        &self,
        req: &RefundsRouterData<Execute>,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        let request = RequestBuilder::new()
            .method(Method::Post)
            .url(&types::RefundExecuteType::get_url(self, req, connectors)?)
            .attach_default_headers()
            .headers(types::RefundExecuteType::get_headers(
                self, req, connectors,
            )?)
            .set_body(types::RefundExecuteType::get_request_body(
                self, req, connectors,
            )?)
            .build();
        Ok(Some(request))
    }

    fn handle_response(
        &self,
        data: &RefundsRouterData<Execute>,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<RefundsRouterData<Execute>, errors::ConnectorError> {
        let response: stax::RefundResponse = res
            .response
            .parse_struct("StaxRefundResponse")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;

        event_builder.map(|i| i.set_response_body(&response));
        router_env::logger::info!(connector_response=?response);

        RouterData::try_from(ResponseRouterData {
            response,
            data: data.clone(),
            http_code: res.status_code,
        })
    }

    fn get_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        self.build_error_response(res, event_builder)
    }
}

impl ConnectorIntegration<RSync, RefundsData, RefundsResponseData> for Stax {
    fn get_headers(
        &self,
        req: &RefundSyncRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        self.build_headers(req, connectors)
    }

    fn get_content_type(&self) -> &'static str {
        self.common_get_content_type()
    }

    fn get_url(
        &self,
        req: &RefundSyncRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        Ok(format!(
            "{}/transaction/{}",
            self.base_url(connectors),
            req.request.get_connector_refund_id()?,
        ))
    }

    fn build_request(
        &self,
        req: &RefundSyncRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        Ok(Some(
            RequestBuilder::new()
                .method(Method::Get)
                .url(&types::RefundSyncType::get_url(self, req, connectors)?)
                .attach_default_headers()
                .headers(types::RefundSyncType::get_headers(self, req, connectors)?)
                .build(),
        ))
    }

    fn handle_response(
        &self,
        data: &RefundSyncRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<RefundSyncRouterData, errors::ConnectorError> {
        let response: stax::RefundResponse = res
            .response
            .parse_struct("StaxRefundSyncResponse")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;

        event_builder.map(|i| i.set_response_body(&response));
        router_env::logger::info!(connector_response=?response);

        RouterData::try_from(ResponseRouterData {
            response,
            data: data.clone(),
            http_code: res.status_code,
        })
    }

    fn get_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        self.build_error_response(res, event_builder)
    }
}

#[async_trait::async_trait]
impl webhooks::IncomingWebhook for Stax {
    async fn verify_webhook_source(
        &self,
        _request: &webhooks::IncomingWebhookRequestDetails<'_>,
        _merchant_id: &common_utils::id_type::MerchantId,
        _connector_webhook_details: Option<common_utils::pii::SecretSerdeValue>,
        _connector_account_details: common_utils::crypto::Encryptable<Secret<serde_json::Value>>,
        _connector_label: &str,
    ) -> CustomResult<bool, errors::ConnectorError> {
        Ok(false)
    }

    fn get_webhook_object_reference_id(
        &self,
        request: &webhooks::IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<api_models::webhooks::ObjectReferenceId, errors::ConnectorError> {
        let webhook_body: stax::StaxWebhookBody = request
            .body
            .parse_struct("StaxWebhookBody")
            .change_context(errors::ConnectorError::WebhookReferenceIdNotFound)?;

        match webhook_body.transaction_type {
            StaxWebhookEventType::Refund => Ok(api_models::webhooks::ObjectReferenceId::RefundId(
                api_models::webhooks::RefundIdType::ConnectorRefundId(webhook_body.id),
            )),
            StaxWebhookEventType::Unknown => {
                Err(errors::ConnectorError::WebhookEventTypeNotFound.into())
            }
            StaxWebhookEventType::PreAuth
            | StaxWebhookEventType::Capture
            | StaxWebhookEventType::Charge
            | StaxWebhookEventType::Void => Ok(api_models::webhooks::ObjectReferenceId::PaymentId(
                api_models::payments::PaymentIdType::ConnectorTransactionId(
                    match webhook_body.transaction_type {
                        StaxWebhookEventType::Capture => webhook_body
                            .auth_id
                            .ok_or(errors::ConnectorError::WebhookReferenceIdNotFound)?,
                        _ => webhook_body.id,
                    },
                ),
            )),
        }
    }

    fn get_webhook_event_type(
        &self,
        request: &webhooks::IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<IncomingWebhookEvent, errors::ConnectorError> {
        let details: stax::StaxWebhookBody = request
            .body
            .parse_struct("StaxWebhookEventType")
            .change_context(errors::ConnectorError::WebhookEventTypeNotFound)?;

        Ok(match &details.transaction_type {
            StaxWebhookEventType::Refund => match &details.success {
                true => IncomingWebhookEvent::RefundSuccess,
                false => IncomingWebhookEvent::RefundFailure,
            },
            StaxWebhookEventType::Capture | StaxWebhookEventType::Charge => {
                match &details.success {
                    true => IncomingWebhookEvent::PaymentIntentSuccess,
                    false => IncomingWebhookEvent::PaymentIntentFailure,
                }
            }
            StaxWebhookEventType::PreAuth
            | StaxWebhookEventType::Void
            | StaxWebhookEventType::Unknown => IncomingWebhookEvent::EventNotSupported,
        })
    }

    fn get_webhook_resource_object(
        &self,
        request: &webhooks::IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<Box<dyn masking::ErasedMaskSerialize>, errors::ConnectorError> {
        let reference_object: serde_json::Value = serde_json::from_slice(request.body)
            .change_context(errors::ConnectorError::WebhookResourceObjectNotFound)?;
        Ok(Box::new(reference_object))
    }
}

static STAX_SUPPORTED_PAYMENT_METHODS: LazyLock<SupportedPaymentMethods> = LazyLock::new(|| {
    let supported_capture_methods = vec![
        enums::CaptureMethod::Automatic,
        enums::CaptureMethod::Manual,
        enums::CaptureMethod::SequentialAutomatic,
    ];

    let supported_card_network = vec![
        common_enums::CardNetwork::Visa,
        common_enums::CardNetwork::Mastercard,
        common_enums::CardNetwork::AmericanExpress,
        common_enums::CardNetwork::Discover,
    ];

    let mut stax_supported_payment_methods = SupportedPaymentMethods::new();

    stax_supported_payment_methods.add(
        enums::PaymentMethod::BankDebit,
        enums::PaymentMethodType::Ach,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods.clone(),
            specific_features: None,
        },
    );

    stax_supported_payment_methods.add(
        enums::PaymentMethod::Card,
        enums::PaymentMethodType::Credit,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods.clone(),
            specific_features: Some(
                api_models::feature_matrix::PaymentMethodSpecificFeatures::Card({
                    api_models::feature_matrix::CardSpecificFeatures {
                        three_ds: common_enums::FeatureStatus::NotSupported,
                        no_three_ds: common_enums::FeatureStatus::Supported,
                        supported_card_networks: supported_card_network.clone(),
                    }
                }),
            ),
        },
    );

    stax_supported_payment_methods.add(
        enums::PaymentMethod::Card,
        enums::PaymentMethodType::Debit,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods.clone(),
            specific_features: Some(
                api_models::feature_matrix::PaymentMethodSpecificFeatures::Card({
                    api_models::feature_matrix::CardSpecificFeatures {
                        three_ds: common_enums::FeatureStatus::NotSupported,
                        no_three_ds: common_enums::FeatureStatus::Supported,
                        supported_card_networks: supported_card_network.clone(),
                    }
                }),
            ),
        },
    );

    stax_supported_payment_methods
});

static STAX_CONNECTOR_INFO: ConnectorInfo = ConnectorInfo {
    display_name: "Stax",
    description:
        "Stax is a payment processing platform that helps businesses accept payments and manage their payment ecosystem ",
    connector_type: enums::HyperswitchConnectorCategory::PaymentGateway,
    integration_status: enums::ConnectorIntegrationStatus::Sandbox,
};

static STAX_SUPPORTED_WEBHOOK_FLOWS: [enums::EventClass; 2] =
    [enums::EventClass::Payments, enums::EventClass::Refunds];

impl ConnectorSpecifications for Stax {
    fn get_connector_about(&self) -> Option<&'static ConnectorInfo> {
        Some(&STAX_CONNECTOR_INFO)
    }

    fn get_supported_payment_methods(&self) -> Option<&'static SupportedPaymentMethods> {
        Some(&*STAX_SUPPORTED_PAYMENT_METHODS)
    }

    fn get_supported_webhook_flows(&self) -> Option<&'static [enums::EventClass]> {
        Some(&STAX_SUPPORTED_WEBHOOK_FLOWS)
    }
}


impl api::RefundSync for Noon {}


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


OpenAPI Block Path: components.schemas.PaymentsExternalAuthenticationRequest
{
  "type": "object",
  "required": [
    "client_secret",
    "device_channel",
    "threeds_method_comp_ind"
  ],
  "properties": {
    "client_secret": {
      "type": "string",
      "description": "Client Secret"
    },
    "sdk_information": {
      "allOf": [
        {
          "$ref": "#/components/schemas/SdkInformation"
        }
      ],
      "nullable": true
    },
    "device_channel": {
      "$ref": "#/components/schemas/DeviceChannel"
    },
    "threeds_method_comp_ind": {
      "$ref": "#/components/schemas/ThreeDsCompletionIndicator"
    }
  }
}


pub struct PaymentsRedirectResponseData {
    pub payment_id: id_type::GlobalPaymentId,
    pub query_params: String,
    pub json_payload: Option<serde_json::Value>,
}


pub async fn update_user_authentication_method(
    state: SessionState,
    req: user_api::UpdateUserAuthenticationMethodRequest,
) -> UserResponse<()> {
    let user_auth_encryption_key = hex::decode(
        state
            .conf
            .user_auth_methods
            .get_inner()
            .encryption_key
            .clone()
            .expose(),
    )
    .change_context(UserErrors::InternalServerError)
    .attach_printable("Failed to decode DEK")?;

    match req {
        user_api::UpdateUserAuthenticationMethodRequest::AuthMethod {
            id,
            auth_config: auth_method,
        } => {
            let (private_config, public_config) =
                utils::user::construct_public_and_private_db_configs(
                    &state,
                    &auth_method,
                    &user_auth_encryption_key,
                    id.clone(),
                )
                .await?;

            state
                .store
                .update_user_authentication_method(
                    &id,
                    UserAuthenticationMethodUpdate::UpdateConfig {
                        private_config,
                        public_config,
                    },
                )
                .await
                .map_err(|error| {
                    let user_error = match error.current_context() {
                        StorageError::ValueNotFound(_) => {
                            UserErrors::InvalidAuthMethodOperationWithMessage(
                                "Auth method not found".to_string(),
                            )
                        }
                        StorageError::DuplicateValue { .. } => {
                            UserErrors::UserAuthMethodAlreadyExists
                        }
                        _ => UserErrors::InternalServerError,
                    };
                    error.change_context(user_error)
                })?;
        }
        user_api::UpdateUserAuthenticationMethodRequest::EmailDomain {
            owner_id,
            email_domain,
        } => {
            let auth_methods = state
                .store
                .list_user_authentication_methods_for_owner_id(&owner_id)
                .await
                .change_context(UserErrors::InternalServerError)?;

            futures::future::try_join_all(auth_methods.iter().map(|auth_method| async {
                state
                    .store
                    .update_user_authentication_method(
                        &auth_method.id,
                        UserAuthenticationMethodUpdate::EmailDomain {
                            email_domain: email_domain.clone(),
                        },
                    )
                    .await
                    .to_duplicate_response(UserErrors::UserAuthMethodAlreadyExists)
            }))
            .await?;
        }
    }

    Ok(ApplicationResponse::StatusOk)
}


pub struct AirwallexWebhookDataResource {
    // Should this be a secret by default since it represents webhook payload
    pub object: Secret<serde_json::Value>,
}


pub fn get_metadata(&self) -> Option<pii::SecretSerdeValue> {
        self.metadata.clone()
    }


impl api::PaymentVoid for Fiservemea {}

impl api::PaymentVoid for for Fiservemea


pub fn validate(&self) -> Result<(), ApplicationError> {
        common_utils::fp_utils::when(self.wallets.is_empty(), || {
            Err(ApplicationError::InvalidConfigurationValueError(
                "list of connectors supporting wallets must not be empty".into(),
            ))
        })
    }


/// Here the fields passed in payment_method_data_billing takes precedence
    pub fn unify_with_payment_method_data_billing(
        self,
        payment_method_data_billing: Option<Address>,
    ) -> Self {
        // Unify the billing details with `payment_method_data.billing_details`
        let unified_payment_method_billing = payment_method_data_billing
            .map(|payment_method_data_billing| {
                payment_method_data_billing.unify_address(self.get_payment_method_billing())
            })
            .or(self.get_payment_method_billing().cloned());

        Self {
            shipping: self.shipping,
            billing: self.billing,
            unified_payment_method_billing,
            payment_method_billing: self.payment_method_billing,
        }
    }


/// Checks if step-up retry is possible.
    pub fn is_step_up_possible(&self) -> bool {
        self.step_up_possible
    }


pub fn convert_expiry(expiry: time::PrimitiveDateTime) -> u64 {
    let now = common_utils::date_time::now();
    let duration = expiry - now;
    let output = duration.whole_seconds();

    match output {
        i64::MIN..=0 => 0,
        _ => output as u64,
    }
}


macro_rules! db_type {
    ($a: ident, $str: tt) => {
        impl DbType for $a {
            fn name() -> &'static str {
                stringify!($str)
            }
        }
    };
    ($a:ident) => {
        impl DbType for $a {
            fn name() -> &'static str {
                stringify!($a)
            }
        }
    };
}


impl State for PmTokenized {}


impl<const T: u8> IncomingWebhook for DummyConnector<T> {
    fn get_webhook_object_reference_id(
        &self,
        _request: &IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<ObjectReferenceId, ConnectorError> {
        Err(report!(ConnectorError::WebhooksNotImplemented))
    }

    fn get_webhook_event_type(
        &self,
        _request: &IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<IncomingWebhookEvent, ConnectorError> {
        Ok(IncomingWebhookEvent::EventNotSupported)
    }

    fn get_webhook_resource_object(
        &self,
        _request: &IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<Box<dyn masking::ErasedMaskSerialize>, ConnectorError> {
        Err(report!(ConnectorError::WebhooksNotImplemented))
    }
}

impl IncomingWebhook for for DummyConnector


OpenAPI Block Path: components.schemas.BankNames
{
  "type": "string",
  "description": "Name of banks supported by Hyperswitch",
  "enum": [
    "american_express",
    "affin_bank",
    "agro_bank",
    "alliance_bank",
    "am_bank",
    "bank_of_america",
    "bank_of_china",
    "bank_islam",
    "bank_muamalat",
    "bank_rakyat",
    "bank_simpanan_nasional",
    "barclays",
    "blik_p_s_p",
    "capital_one",
    "chase",
    "citi",
    "cimb_bank",
    "discover",
    "navy_federal_credit_union",
    "pentagon_federal_credit_union",
    "synchrony_bank",
    "wells_fargo",
    "abn_amro",
    "asn_bank",
    "bunq",
    "handelsbanken",
    "hong_leong_bank",
    "hsbc_bank",
    "ing",
    "knab",
    "kuwait_finance_house",
    "moneyou",
    "rabobank",
    "regiobank",
    "revolut",
    "sns_bank",
    "triodos_bank",
    "van_lanschot",
    "arzte_und_apotheker_bank",
    "austrian_anadi_bank_ag",
    "bank_austria",
    "bank99_ag",
    "bankhaus_carl_spangler",
    "bankhaus_schelhammer_und_schattera_ag",
    "bank_millennium",
    "bank_p_e_k_a_o_s_a",
    "bawag_psk_ag",
    "bks_bank_ag",
    "brull_kallmus_bank_ag",
    "btv_vier_lander_bank",
    "capital_bank_grawe_gruppe_ag",
    "ceska_sporitelna",
    "dolomitenbank",
    "easybank_ag",
    "e_platby_v_u_b",
    "erste_bank_und_sparkassen",
    "friesland_bank",
    "hypo_alpeadriabank_international_ag",
    "hypo_noe_lb_fur_niederosterreich_u_wien",
    "hypo_oberosterreich_salzburg_steiermark",
    "hypo_tirol_bank_ag",
    "hypo_vorarlberg_bank_ag",
    "hypo_bank_burgenland_aktiengesellschaft",
    "komercni_banka",
    "m_bank",
    "marchfelder_bank",
    "maybank",
    "oberbank_ag",
    "osterreichische_arzte_und_apothekerbank",
    "ocbc_bank",
    "pay_with_i_n_g",
    "place_z_i_p_k_o",
    "platnosc_online_karta_platnicza",
    "posojilnica_bank_e_gen",
    "postova_banka",
    "public_bank",
    "raiffeisen_bankengruppe_osterreich",
    "rhb_bank",
    "schelhammer_capital_bank_ag",
    "standard_chartered_bank",
    "schoellerbank_ag",
    "sparda_bank_wien",
    "sporo_pay",
    "santander_przelew24",
    "tatra_pay",
    "viamo",
    "volksbank_gruppe",
    "volkskreditbank_ag",
    "vr_bank_braunau",
    "uob_bank",
    "pay_with_alior_bank",
    "banki_spoldzielcze",
    "pay_with_inteligo",
    "b_n_p_paribas_poland",
    "bank_nowy_s_a",
    "credit_agricole",
    "pay_with_b_o_s",
    "pay_with_citi_handlowy",
    "pay_with_plus_bank",
    "toyota_bank",
    "velo_bank",
    "e_transfer_pocztowy24",
    "plus_bank",
    "etransfer_pocztowy24",
    "banki_spbdzielcze",
    "bank_nowy_bfg_sa",
    "getin_bank",
    "blik",
    "noble_pay",
    "idea_bank",
    "envelo_bank",
    "nest_przelew",
    "mbank_mtransfer",
    "inteligo",
    "pbac_z_ipko",
    "bnp_paribas",
    "bank_pekao_sa",
    "volkswagen_bank",
    "alior_bank",
    "boz",
    "bangkok_bank",
    "krungsri_bank",
    "krung_thai_bank",
    "the_siam_commercial_bank",
    "kasikorn_bank",
    "open_bank_success",
    "open_bank_failure",
    "open_bank_cancelled",
    "aib",
    "bank_of_scotland",
    "danske_bank",
    "first_direct",
    "first_trust",
    "halifax",
    "lloyds",
    "monzo",
    "nat_west",
    "nationwide_bank",
    "royal_bank_of_scotland",
    "starling",
    "tsb_bank",
    "tesco_bank",
    "ulster_bank",
    "yoursafe",
    "n26",
    "nationale_nederlanden"
  ]
}


pub struct JWTAuthProfileFromRoute {
    pub profile_id: id_type::ProfileId,
    pub required_permission: Permission,
}


pub struct EventListItemResponse {
    /// The identifier for the Event.
    #[schema(max_length = 64, example = "evt_018e31720d1b7a2b82677d3032cab959")]
    pub event_id: String,

    /// The identifier for the Merchant Account.
    #[schema(max_length = 64, example = "y3oqhf46pyzuxjbcn2giaqnb44", value_type = String)]
    pub merchant_id: common_utils::id_type::MerchantId,

    /// The identifier for the Business Profile.
    #[schema(max_length = 64, value_type = String, example = "SqB0zwDGR5wHppWf0bx7GKr1f2")]
    pub profile_id: common_utils::id_type::ProfileId,

    /// The identifier for the object (Payment Intent ID, Refund ID, etc.)
    #[schema(max_length = 64, example = "QHrfd5LUDdZaKtAjdJmMu0dMa1")]
    pub object_id: String,

    /// Specifies the type of event, which includes the object and its status.
    pub event_type: EventType,

    /// Specifies the class of event (the type of object: Payment, Refund, etc.)
    pub event_class: EventClass,

    /// Indicates whether the webhook was ultimately delivered or not.
    pub is_delivery_successful: Option<bool>,

    /// The identifier for the initial delivery attempt. This will be the same as `event_id` for
    /// the initial delivery attempt.
    #[schema(max_length = 64, example = "evt_018e31720d1b7a2b82677d3032cab959")]
    pub initial_attempt_id: String,

    /// Time at which the event was created.
    #[schema(example = "2022-09-10T10:11:12Z")]
    #[serde(with = "common_utils::custom_serde::iso8601")]
    pub created: PrimitiveDateTime,
}


pub async fn routing_retrieve_default_config_for_profiles(
    state: web::Data<AppState>,
    req: HttpRequest,
    transaction_type: &enums::TransactionType,
) -> impl Responder {
    Box::pin(oss_api::server_wrap(
        Flow::RoutingRetrieveDefaultConfig,
        state,
        &req,
        (),
        |state, auth: auth::AuthenticationData, _, _| {
            let merchant_context = domain::MerchantContext::NormalMerchant(Box::new(
                domain::Context(auth.merchant_account, auth.key_store),
            ));
            routing::retrieve_default_routing_config_for_profiles(
                state,
                merchant_context,
                transaction_type,
            )
        },
        #[cfg(not(feature = "release"))]
        auth::auth_type(
            &auth::HeaderAuth(auth::ApiKeyAuth {
                is_connected_allowed: false,
                is_platform_allowed: false,
            }),
            &auth::JWTAuth {
                permission: Permission::MerchantRoutingRead,
            },
            req.headers(),
        ),
        #[cfg(feature = "release")]
        auth::auth_type(
            &auth::HeaderAuth(auth::ApiKeyAuth {
                is_connected_allowed: false,
                is_platform_allowed: false,
            }),
            &auth::JWTAuth {
                permission: Permission::MerchantRoutingRead,
            },
            req.headers(),
        ),
        api_locking::LockAction::NotApplicable,
    ))
    .await
}


impl PaymentAttempt {
    #[cfg(feature = "v1")]
    pub fn get_payment_method(&self) -> Option<storage_enums::PaymentMethod> {
        self.payment_method
    }

    #[cfg(feature = "v2")]
    pub fn get_payment_method(&self) -> Option<storage_enums::PaymentMethod> {
        // TODO: check if we can fix this
        Some(self.payment_method_type)
    }

    #[cfg(feature = "v1")]
    pub fn get_payment_method_type(&self) -> Option<storage_enums::PaymentMethodType> {
        self.payment_method_type
    }

    #[cfg(feature = "v2")]
    pub fn get_payment_method_type(&self) -> Option<storage_enums::PaymentMethodType> {
        // TODO: check if we can fix this
        Some(self.payment_method_subtype)
    }

    #[cfg(feature = "v1")]
    pub fn get_id(&self) -> &str {
        &self.attempt_id
    }

    #[cfg(feature = "v2")]
    pub fn get_id(&self) -> &id_type::GlobalAttemptId {
        &self.id
    }

    #[cfg(feature = "v1")]
    pub fn get_connector_payment_id(&self) -> Option<&str> {
        self.connector_transaction_id.as_deref()
    }

    #[cfg(feature = "v2")]
    pub fn get_connector_payment_id(&self) -> Option<&str> {
        self.connector_payment_id.as_deref()
    }

    /// Construct the domain model from the ConfirmIntentRequest and PaymentIntent
    #[cfg(feature = "v2")]
    pub async fn create_domain_model(
        payment_intent: &super::PaymentIntent,
        cell_id: id_type::CellId,
        storage_scheme: storage_enums::MerchantStorageScheme,
        request: &api_models::payments::PaymentsConfirmIntentRequest,
        encrypted_data: DecryptedPaymentAttempt,
    ) -> CustomResult<Self, errors::api_error_response::ApiErrorResponse> {
        let id = id_type::GlobalAttemptId::generate(&cell_id);
        let intent_amount_details = payment_intent.amount_details.clone();

        let attempt_amount_details = intent_amount_details.create_attempt_amount_details(request);

        let now = common_utils::date_time::now();

        let payment_method_billing_address = encrypted_data
            .payment_method_billing_address
            .as_ref()
            .map(|data| {
                data.clone()
                    .deserialize_inner_value(|value| value.parse_value("Address"))
            })
            .transpose()
            .change_context(errors::api_error_response::ApiErrorResponse::InternalServerError)
            .attach_printable("Unable to decode billing address")?;

        let connector_token = Some(diesel_models::ConnectorTokenDetails {
            connector_mandate_id: None,
            connector_token_request_reference_id: Some(common_utils::generate_id_with_len(
                consts::CONNECTOR_MANDATE_REQUEST_REFERENCE_ID_LENGTH,
            )),
        });

        let authentication_type = payment_intent.authentication_type.unwrap_or_default();

        Ok(Self {
            payment_id: payment_intent.id.clone(),
            merchant_id: payment_intent.merchant_id.clone(),
            amount_details: attempt_amount_details,
            status: common_enums::AttemptStatus::Started,
            // This will be decided by the routing algorithm and updated in update trackers
            // right before calling the connector
            connector: None,
            authentication_type,
            created_at: now,
            modified_at: now,
            last_synced: None,
            cancellation_reason: None,
            browser_info: request.browser_info.clone(),
            payment_token: request.payment_token.clone(),
            connector_metadata: None,
            payment_experience: None,
            payment_method_data: None,
            routing_result: None,
            preprocessing_step_id: None,
            multiple_capture_count: None,
            connector_response_reference_id: None,
            updated_by: storage_scheme.to_string(),
            redirection_data: None,
            encoded_data: None,
            merchant_connector_id: None,
            external_three_ds_authentication_attempted: None,
            authentication_connector: None,
            authentication_id: None,
            fingerprint_id: None,
            charges: None,
            client_source: None,
            client_version: None,
            customer_acceptance: request.customer_acceptance.clone().map(Secret::new),
            profile_id: payment_intent.profile_id.clone(),
            organization_id: payment_intent.organization_id.clone(),
            payment_method_type: request.payment_method_type,
            payment_method_id: request.payment_method_id.clone(),
            connector_payment_id: None,
            payment_method_subtype: request.payment_method_subtype,
            authentication_applied: None,
            external_reference_id: None,
            payment_method_billing_address,
            error: None,
            connector_token_details: connector_token,
            id,
            card_discovery: None,
            feature_metadata: None,
            processor_merchant_id: payment_intent.merchant_id.clone(),
            created_by: None,
            connector_request_reference_id: None,
            network_transaction_id: None,
        })
    }

    #[cfg(feature = "v2")]
    pub async fn proxy_create_domain_model(
        payment_intent: &super::PaymentIntent,
        cell_id: id_type::CellId,
        storage_scheme: storage_enums::MerchantStorageScheme,
        request: &api_models::payments::ProxyPaymentsRequest,
        encrypted_data: DecryptedPaymentAttempt,
    ) -> CustomResult<Self, errors::api_error_response::ApiErrorResponse> {
        let id = id_type::GlobalAttemptId::generate(&cell_id);
        let intent_amount_details = payment_intent.amount_details.clone();

        let attempt_amount_details =
            intent_amount_details.proxy_create_attempt_amount_details(request);

        let now = common_utils::date_time::now();
        let payment_method_billing_address = encrypted_data
            .payment_method_billing_address
            .as_ref()
            .map(|data| {
                data.clone()
                    .deserialize_inner_value(|value| value.parse_value("Address"))
            })
            .transpose()
            .change_context(errors::api_error_response::ApiErrorResponse::InternalServerError)
            .attach_printable("Unable to decode billing address")?;
        let connector_token = Some(diesel_models::ConnectorTokenDetails {
            connector_mandate_id: None,
            connector_token_request_reference_id: Some(common_utils::generate_id_with_len(
                consts::CONNECTOR_MANDATE_REQUEST_REFERENCE_ID_LENGTH,
            )),
        });
        let payment_method_type_data = payment_intent.get_payment_method_type();

        let payment_method_subtype_data = payment_intent.get_payment_method_sub_type();
        let authentication_type = payment_intent.authentication_type.unwrap_or_default();
        Ok(Self {
            payment_id: payment_intent.id.clone(),
            merchant_id: payment_intent.merchant_id.clone(),
            amount_details: attempt_amount_details,
            status: common_enums::AttemptStatus::Started,
            connector: Some(request.connector.clone()),
            authentication_type,
            created_at: now,
            modified_at: now,
            last_synced: None,
            cancellation_reason: None,
            browser_info: request.browser_info.clone(),
            payment_token: None,
            connector_metadata: None,
            payment_experience: None,
            payment_method_data: None,
            routing_result: None,
            preprocessing_step_id: None,
            multiple_capture_count: None,
            connector_response_reference_id: None,
            updated_by: storage_scheme.to_string(),
            redirection_data: None,
            encoded_data: None,
            merchant_connector_id: Some(request.merchant_connector_id.clone()),
            external_three_ds_authentication_attempted: None,
            authentication_connector: None,
            authentication_id: None,
            fingerprint_id: None,
            charges: None,
            client_source: None,
            client_version: None,
            customer_acceptance: None,
            profile_id: payment_intent.profile_id.clone(),
            organization_id: payment_intent.organization_id.clone(),
            payment_method_type: payment_method_type_data
                .unwrap_or(common_enums::PaymentMethod::Card),
            payment_method_id: None,
            connector_payment_id: None,
            payment_method_subtype: payment_method_subtype_data
                .unwrap_or(common_enums::PaymentMethodType::Credit),
            authentication_applied: None,
            external_reference_id: None,
            payment_method_billing_address,
            error: None,
            connector_token_details: connector_token,
            feature_metadata: None,
            id,
            card_discovery: None,
            processor_merchant_id: payment_intent.merchant_id.clone(),
            created_by: None,
            connector_request_reference_id: None,
            network_transaction_id: None,
        })
    }

    #[cfg(feature = "v2")]
    pub async fn external_vault_proxy_create_domain_model(
        payment_intent: &super::PaymentIntent,
        cell_id: id_type::CellId,
        storage_scheme: storage_enums::MerchantStorageScheme,
        request: &api_models::payments::ExternalVaultProxyPaymentsRequest,
        encrypted_data: DecryptedPaymentAttempt,
    ) -> CustomResult<Self, errors::api_error_response::ApiErrorResponse> {
        let id = id_type::GlobalAttemptId::generate(&cell_id);
        let intent_amount_details = payment_intent.amount_details.clone();
        let attempt_amount_details = AttemptAmountDetails {
            net_amount: intent_amount_details.order_amount,
            amount_to_capture: None,
            surcharge_amount: None,
            tax_on_surcharge: None,
            amount_capturable: intent_amount_details.order_amount,
            shipping_cost: None,
            order_tax_amount: None,
        };

        let now = common_utils::date_time::now();
        let payment_method_billing_address = encrypted_data
            .payment_method_billing_address
            .as_ref()
            .map(|data| {
                data.clone()
                    .deserialize_inner_value(|value| value.parse_value("Address"))
            })
            .transpose()
            .change_context(errors::api_error_response::ApiErrorResponse::InternalServerError)
            .attach_printable("Unable to decode billing address")?;
        let connector_token = Some(diesel_models::ConnectorTokenDetails {
            connector_mandate_id: None,
            connector_token_request_reference_id: Some(common_utils::generate_id_with_len(
                consts::CONNECTOR_MANDATE_REQUEST_REFERENCE_ID_LENGTH,
            )),
        });
        let payment_method_type_data = payment_intent.get_payment_method_type();

        let payment_method_subtype_data = payment_intent.get_payment_method_sub_type();
        let authentication_type = payment_intent.authentication_type.unwrap_or_default();
        Ok(Self {
            payment_id: payment_intent.id.clone(),
            merchant_id: payment_intent.merchant_id.clone(),
            amount_details: attempt_amount_details,
            status: common_enums::AttemptStatus::Started,
            connector: None,
            authentication_type,
            created_at: now,
            modified_at: now,
            last_synced: None,
            cancellation_reason: None,
            browser_info: request.browser_info.clone(),
            payment_token: request.payment_token.clone(),
            connector_metadata: None,
            payment_experience: None,
            payment_method_data: None,
            routing_result: None,
            preprocessing_step_id: None,
            multiple_capture_count: None,
            connector_response_reference_id: None,
            updated_by: storage_scheme.to_string(),
            redirection_data: None,
            encoded_data: None,
            merchant_connector_id: None,
            external_three_ds_authentication_attempted: None,
            authentication_connector: None,
            authentication_id: None,
            fingerprint_id: None,
            charges: None,
            client_source: None,
            client_version: None,
            customer_acceptance: request.customer_acceptance.clone().map(Secret::new),
            profile_id: payment_intent.profile_id.clone(),
            organization_id: payment_intent.organization_id.clone(),
            payment_method_type: payment_method_type_data
                .unwrap_or(common_enums::PaymentMethod::Card),
            payment_method_id: request.payment_method_id.clone(),
            connector_payment_id: None,
            payment_method_subtype: payment_method_subtype_data
                .unwrap_or(common_enums::PaymentMethodType::Credit),
            authentication_applied: None,
            external_reference_id: None,
            payment_method_billing_address,
            error: None,
            connector_token_details: connector_token,
            feature_metadata: None,
            id,
            card_discovery: None,
            processor_merchant_id: payment_intent.merchant_id.clone(),
            created_by: None,
            connector_request_reference_id: None,
            network_transaction_id: None,
        })
    }

    /// Construct the domain model from the ConfirmIntentRequest and PaymentIntent
    #[cfg(feature = "v2")]
    pub async fn create_domain_model_using_record_request(
        payment_intent: &super::PaymentIntent,
        cell_id: id_type::CellId,
        storage_scheme: storage_enums::MerchantStorageScheme,
        request: &api_models::payments::PaymentsAttemptRecordRequest,
        encrypted_data: DecryptedPaymentAttempt,
    ) -> CustomResult<Self, errors::api_error_response::ApiErrorResponse> {
        let id = id_type::GlobalAttemptId::generate(&cell_id);

        let amount_details = AttemptAmountDetailsSetter::from(&request.amount_details);

        let now = common_utils::date_time::now();
        // we consume transaction_created_at from webhook request, if it is not present we take store current time as transaction_created_at.
        let transaction_created_at = request
            .transaction_created_at
            .unwrap_or(common_utils::date_time::now());

        // This function is called in the record attempt flow, which tells us that this is a payment attempt created by an external system.
        let feature_metadata = PaymentAttemptFeatureMetadata {
            revenue_recovery: Some({
                PaymentAttemptRevenueRecoveryData {
                    attempt_triggered_by: request.triggered_by,
                    charge_id: request.feature_metadata.as_ref().and_then(|metadata| {
                        metadata
                            .revenue_recovery
                            .as_ref()
                            .and_then(|data| data.charge_id.clone())
                    }),
                }
            }),
        };

        let payment_method_data = request
            .payment_method_data
            .as_ref()
            .map(|data| data.payment_method_data.clone().encode_to_value())
            .transpose()
            .change_context(errors::api_error_response::ApiErrorResponse::InternalServerError)
            .attach_printable("Unable to decode additional payment method data")?
            .map(pii::SecretSerdeValue::new);

        let payment_method_billing_address = encrypted_data
            .payment_method_billing_address
            .as_ref()
            .map(|data| {
                data.clone()
                    .deserialize_inner_value(|value| value.parse_value("Address"))
            })
            .transpose()
            .change_context(errors::api_error_response::ApiErrorResponse::InternalServerError)
            .attach_printable("Unable to decode billing address")?;
        let error = request.error.as_ref().map(ErrorDetails::from);
        let connector_payment_id = request
            .connector_transaction_id
            .as_ref()
            .map(|txn_id| txn_id.get_id().clone());
        let connector = request.connector.map(|connector| connector.to_string());
        let connector_request_reference_id = payment_intent
            .merchant_reference_id
            .as_ref()
            .map(|id| id.get_string_repr().to_owned());
        Ok(Self {
            payment_id: payment_intent.id.clone(),
            merchant_id: payment_intent.merchant_id.clone(),
            amount_details: AttemptAmountDetails::from(amount_details),
            status: request.status,
            connector,
            authentication_type: storage_enums::AuthenticationType::NoThreeDs,
            created_at: transaction_created_at,
            modified_at: now,
            last_synced: None,
            cancellation_reason: None,
            browser_info: None,
            payment_token: None,
            connector_metadata: None,
            payment_experience: None,
            payment_method_data,
            routing_result: None,
            preprocessing_step_id: None,
            multiple_capture_count: None,
            connector_response_reference_id: None,
            updated_by: storage_scheme.to_string(),
            redirection_data: None,
            encoded_data: None,
            merchant_connector_id: request.payment_merchant_connector_id.clone(),
            external_three_ds_authentication_attempted: None,
            authentication_connector: None,
            authentication_id: None,
            fingerprint_id: None,
            client_source: None,
            client_version: None,
            customer_acceptance: None,
            profile_id: payment_intent.profile_id.clone(),
            organization_id: payment_intent.organization_id.clone(),
            payment_method_type: request.payment_method_type,
            payment_method_id: None,
            connector_payment_id,
            payment_method_subtype: request.payment_method_subtype,
            authentication_applied: None,
            external_reference_id: None,
            payment_method_billing_address,
            error,
            feature_metadata: Some(feature_metadata),
            id,
            connector_token_details: Some(diesel_models::ConnectorTokenDetails {
                connector_mandate_id: Some(request.processor_payment_method_token.clone()),
                connector_token_request_reference_id: None,
            }),
            card_discovery: None,
            charges: None,
            processor_merchant_id: payment_intent.merchant_id.clone(),
            created_by: None,
            connector_request_reference_id,
            network_transaction_id: None,
        })
    }

    pub fn get_attempt_merchant_connector_account_id(
        &self,
    ) -> CustomResult<
        id_type::MerchantConnectorAccountId,
        errors::api_error_response::ApiErrorResponse,
    > {
        let merchant_connector_id = self
            .merchant_connector_id
            .clone()
            .get_required_value("merchant_connector_id")
            .change_context(errors::api_error_response::ApiErrorResponse::InternalServerError)
            .attach_printable("Merchant connector id is None")?;
        Ok(merchant_connector_id)
    }
}


pub struct CalSuccessRateEventResponse {
    pub labels_with_score: Vec<LabelWithScoreEventResponse>,
    pub routing_approach: RoutingApproach,
}


impl api::Refund for Digitalvirgo {}


pub fn get_card(&self) -> Option<&payment_methods::CardDetail> {
        match self {
            Self::Card(card) => Some(card),
            #[cfg(feature = "v2")]
            Self::NetworkToken(_) => None,
        }
    }


pub struct DrainerSettings {
    pub stream_name: String,
    pub num_partitions: u8,
    pub max_read_count: u64,
    pub shutdown_interval: u32, // in milliseconds
    pub loop_interval: u32,     // in milliseconds
}


File: crates/router_env/src/logger/formatter.rs
 Public functions: 3
 Public structs: 1

//! Formatting [layer](https://docs.rs/tracing-subscriber/0.3.15/tracing_subscriber/layer/trait.Layer.html) for Router.

use std::{
    collections::{HashMap, HashSet},
    fmt,
    io::Write,
    sync::LazyLock,
};

use config::ConfigError;
use serde::ser::{SerializeMap, Serializer};
use serde_json::{ser::Formatter, Value};
// use time::format_description::well_known::Rfc3339;
use time::format_description::well_known::Iso8601;
use tracing::{Event, Metadata, Subscriber};
use tracing_subscriber::{
    fmt::MakeWriter,
    layer::Context,
    registry::{LookupSpan, SpanRef},
    Layer,
};

use crate::Storage;
// TODO: Documentation coverage for this crate

// Implicit keys

const MESSAGE: &str = "message";
const HOSTNAME: &str = "hostname";
const PID: &str = "pid";
const ENV: &str = "env";
const VERSION: &str = "version";
const BUILD: &str = "build";
const LEVEL: &str = "level";
const TARGET: &str = "target";
const SERVICE: &str = "service";
const LINE: &str = "line";
const FILE: &str = "file";
const FN: &str = "fn";
const FULL_NAME: &str = "full_name";
const TIME: &str = "time";

// Extra implicit keys. Keys that are provided during runtime but should be treated as
// implicit in the logs

const FLOW: &str = "flow";
const MERCHANT_AUTH: &str = "merchant_authentication";
const MERCHANT_ID: &str = "merchant_id";
const REQUEST_METHOD: &str = "request_method";
const REQUEST_URL_PATH: &str = "request_url_path";
const REQUEST_ID: &str = "request_id";
const WORKFLOW_ID: &str = "workflow_id";
const GLOBAL_ID: &str = "global_id";
const SESSION_ID: &str = "session_id";

/// Set of predefined implicit keys.
pub static IMPLICIT_KEYS: LazyLock<rustc_hash::FxHashSet<&str>> = LazyLock::new(|| {
    let mut set = rustc_hash::FxHashSet::default();

    set.insert(HOSTNAME);
    set.insert(PID);
    set.insert(ENV);
    set.insert(VERSION);
    set.insert(BUILD);
    set.insert(LEVEL);
    set.insert(TARGET);
    set.insert(SERVICE);
    set.insert(LINE);
    set.insert(FILE);
    set.insert(FN);
    set.insert(FULL_NAME);
    set.insert(TIME);

    set
});

/// Extra implicit keys. Keys that are not purely implicit but need to be logged alongside
/// other implicit keys in the log json.
pub static EXTRA_IMPLICIT_KEYS: LazyLock<rustc_hash::FxHashSet<&str>> = LazyLock::new(|| {
    let mut set = rustc_hash::FxHashSet::default();

    set.insert(MESSAGE);
    set.insert(FLOW);
    set.insert(MERCHANT_AUTH);
    set.insert(MERCHANT_ID);
    set.insert(REQUEST_METHOD);
    set.insert(REQUEST_URL_PATH);
    set.insert(REQUEST_ID);
    set.insert(GLOBAL_ID);
    set.insert(SESSION_ID);
    set.insert(WORKFLOW_ID);

    set
});

/// Describe type of record: entering a span, exiting a span, an event.
#[derive(Clone, Debug)]
pub enum RecordType {
    /// Entering a span.
    EnterSpan,
    /// Exiting a span.
    ExitSpan,
    /// Event.
    Event,
}

impl fmt::Display for RecordType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let repr = match self {
            Self::EnterSpan => "START",
            Self::ExitSpan => "END",
            Self::Event => "EVENT",
        };
        write!(f, "{repr}")
    }
}

/// Format log records.
/// `FormattingLayer` relies on the `tracing_bunyan_formatter::JsonStorageLayer` which is storage of entries.
#[derive(Debug)]
pub struct FormattingLayer<W, F>
where
    W: for<'a> MakeWriter<'a> + 'static,
    F: Formatter + Clone,
{
    dst_writer: W,
    pid: u32,
    hostname: String,
    env: String,
    service: String,
    #[cfg(feature = "vergen")]
    version: String,
    #[cfg(feature = "vergen")]
    build: String,
    default_fields: HashMap<String, Value>,
    formatter: F,
}

impl<W, F> FormattingLayer<W, F>
where
    W: for<'a> MakeWriter<'a> + 'static,
    F: Formatter + Clone,
{
    /// Constructor of `FormattingLayer`.
    ///
    /// A `name` will be attached to all records during formatting.
    /// A `dst_writer` to forward all records.
    ///
    /// ## Example
    /// ```rust
    /// let formatting_layer = router_env::FormattingLayer::new("my_service", std::io::stdout, serde_json::ser::CompactFormatter);
    /// ```
    pub fn new(
        service: &str,
        dst_writer: W,
        formatter: F,
    ) -> error_stack::Result<Self, ConfigError> {
        Self::new_with_implicit_entries(service, dst_writer, HashMap::new(), formatter)
    }

    /// Construct of `FormattingLayer with implicit default entries.
    pub fn new_with_implicit_entries(
        service: &str,
        dst_writer: W,
        default_fields: HashMap<String, Value>,
        formatter: F,
    ) -> error_stack::Result<Self, ConfigError> {
        let pid = std::process::id();
        let hostname = gethostname::gethostname().to_string_lossy().into_owned();
        let service = service.to_string();
        #[cfg(feature = "vergen")]
        let version = crate::version!().to_string();
        #[cfg(feature = "vergen")]
        let build = crate::build!().to_string();
        let env = crate::env::which().to_string();
        for key in default_fields.keys() {
            if IMPLICIT_KEYS.contains(key.as_str()) {
                return Err(ConfigError::Message(format!(
                    "A reserved key `{key}` was included in `default_fields` in the log formatting layer"
                ))
                .into());
            }
        }

        Ok(Self {
            dst_writer,
            pid,
            hostname,
            env,
            service,
            #[cfg(feature = "vergen")]
            version,
            #[cfg(feature = "vergen")]
            build,
            default_fields,
            formatter,
        })
    }

    /// Serialize common for both span and event entries.
    fn common_serialize<S>(
        &self,
        map_serializer: &mut impl SerializeMap<Error = serde_json::Error>,
        metadata: &Metadata<'_>,
        span: Option<&SpanRef<'_, S>>,
        storage: &Storage<'_>,
        name: &str,
    ) -> Result<(), std::io::Error>
    where
        S: Subscriber + for<'a> LookupSpan<'a>,
    {
        let is_extra = |s: &str| !IMPLICIT_KEYS.contains(s);
        let is_extra_implicit = |s: &str| is_extra(s) && EXTRA_IMPLICIT_KEYS.contains(s);

        map_serializer.serialize_entry(HOSTNAME, &self.hostname)?;
        map_serializer.serialize_entry(PID, &self.pid)?;
        map_serializer.serialize_entry(ENV, &self.env)?;
        #[cfg(feature = "vergen")]
        map_serializer.serialize_entry(VERSION, &self.version)?;
        #[cfg(feature = "vergen")]
        map_serializer.serialize_entry(BUILD, &self.build)?;
        map_serializer.serialize_entry(LEVEL, &format_args!("{}", metadata.level()))?;
        map_serializer.serialize_entry(TARGET, metadata.target())?;
        map_serializer.serialize_entry(SERVICE, &self.service)?;
        map_serializer.serialize_entry(LINE, &metadata.line())?;
        map_serializer.serialize_entry(FILE, &metadata.file())?;
        map_serializer.serialize_entry(FN, name)?;
        map_serializer
            .serialize_entry(FULL_NAME, &format_args!("{}::{}", metadata.target(), name))?;
        if let Ok(time) = &time::OffsetDateTime::now_utc().format(&Iso8601::DEFAULT) {
            map_serializer.serialize_entry(TIME, time)?;
        }

        // Write down implicit default entries.
        for (key, value) in self.default_fields.iter() {
            map_serializer.serialize_entry(key, value)?;
        }

        #[cfg(feature = "log_custom_entries_to_extra")]
        let mut extra = serde_json::Map::default();
        let mut explicit_entries_set: HashSet<&str> = HashSet::default();
        // Write down explicit event's entries.
        for (key, value) in storage.values.iter() {
            if is_extra_implicit(key) {
                #[cfg(feature = "log_extra_implicit_fields")]
                map_serializer.serialize_entry(key, value)?;
                explicit_entries_set.insert(key);
            } else if is_extra(key) {
                #[cfg(feature = "log_custom_entries_to_extra")]
                extra.insert(key.to_string(), value.clone());
                #[cfg(not(feature = "log_custom_entries_to_extra"))]
                map_serializer.serialize_entry(key, value)?;
                explicit_entries_set.insert(key);
            } else {
                tracing::warn!(
                    ?key,
                    ?value,
                    "Attempting to log a reserved entry. It won't be added to the logs"
                );
            }
        }

        // Write down entries from the span, if it exists.
        if let Some(span) = &span {
            let extensions = span.extensions();
            if let Some(visitor) = extensions.get::<Storage<'_>>() {
                for (key, value) in &visitor.values {
                    if is_extra_implicit(key) && !explicit_entries_set.contains(key) {
                        #[cfg(feature = "log_extra_implicit_fields")]
                        map_serializer.serialize_entry(key, value)?;
                    } else if is_extra(key) && !explicit_entries_set.contains(key) {
                        #[cfg(feature = "log_custom_entries_to_extra")]
                        extra.insert(key.to_string(), value.clone());
                        #[cfg(not(feature = "log_custom_entries_to_extra"))]
                        map_serializer.serialize_entry(key, value)?;
                    } else {
                        tracing::warn!(
                            ?key,
                            ?value,
                            "Attempting to log a reserved entry. It won't be added to the logs"
                        );
                    }
                }
            }
        }

        #[cfg(feature = "log_custom_entries_to_extra")]
        map_serializer.serialize_entry("extra", &extra)?;

        Ok(())
    }

    /// Flush memory buffer into an output stream trailing it with next line.
    ///
    /// Should be done by single `write_all` call to avoid fragmentation of log because of mutlithreading.
    fn flush(&self, mut buffer: Vec<u8>) -> Result<(), std::io::Error> {
        buffer.write_all(b"\n")?;
        self.dst_writer.make_writer().write_all(&buffer)
    }

    /// Serialize entries of span.
    fn span_serialize<S>(
        &self,
        span: &SpanRef<'_, S>,
        ty: RecordType,
    ) -> Result<Vec<u8>, std::io::Error>
    where
        S: Subscriber + for<'a> LookupSpan<'a>,
    {
        let mut buffer = Vec::new();
        let mut serializer =
            serde_json::Serializer::with_formatter(&mut buffer, self.formatter.clone());
        let mut map_serializer = serializer.serialize_map(None)?;
        let message = Self::span_message(span, ty);
        let mut storage = Storage::default();
        storage.record_value("message", message.into());

        self.common_serialize(
            &mut map_serializer,
            span.metadata(),
            Some(span),
            &storage,
            span.name(),
        )?;

        map_serializer.end()?;
        Ok(buffer)
    }

    /// Serialize event into a buffer of bytes using parent span.
    pub fn event_serialize<S>(
        &self,
        span: Option<&SpanRef<'_, S>>,
        event: &Event<'_>,
    ) -> std::io::Result<Vec<u8>>
    where
        S: Subscriber + for<'a> LookupSpan<'a>,
    {
        let mut buffer = Vec::new();
        let mut serializer =
            serde_json::Serializer::with_formatter(&mut buffer, self.formatter.clone());
        let mut map_serializer = serializer.serialize_map(None)?;

        let mut storage = Storage::default();
        event.record(&mut storage);

        let name = span.map_or("?", SpanRef::name);
        Self::event_message(span, event, &mut storage);

        self.common_serialize(&mut map_serializer, event.metadata(), span, &storage, name)?;

        map_serializer.end()?;
        Ok(buffer)
    }

    /// Format message of a span.
    ///
    /// Example: "[FN_WITHOUT_COLON - START]"
    fn span_message<S>(span: &SpanRef<'_, S>, ty: RecordType) -> String
    where
        S: Subscriber + for<'a> LookupSpan<'a>,
    {
        format!("[{} - {}]", span.metadata().name().to_uppercase(), ty)
    }

    /// Format message of an event.
    ///
    /// Examples: "[FN_WITHOUT_COLON - EVENT] Message"
    fn event_message<S>(span: Option<&SpanRef<'_, S>>, event: &Event<'_>, storage: &mut Storage<'_>)
    where
        S: Subscriber + for<'a> LookupSpan<'a>,
    {
        // Get value of kept "message" or "target" if does not exist.
        let message = storage
            .values
            .entry("message")
            .or_insert_with(|| event.metadata().target().into());

        // Prepend the span name to the message if span exists.
        if let (Some(span), Value::String(a)) = (span, message) {
            *a = format!("{} {}", Self::span_message(span, RecordType::Event), a,);
        }
    }
}

#[allow(clippy::expect_used)]
impl<S, W, F> Layer<S> for FormattingLayer<W, F>
where
    S: Subscriber + for<'a> LookupSpan<'a>,
    W: for<'a> MakeWriter<'a> + 'static,
    F: Formatter + Clone + 'static,
{
    fn on_event(&self, event: &Event<'_>, ctx: Context<'_, S>) {
        // Event could have no span.
        let span = ctx.lookup_current();

        let result: std::io::Result<Vec<u8>> = self.event_serialize(span.as_ref(), event);
        if let Ok(formatted) = result {
            let _ = self.flush(formatted);
        }
    }

    #[cfg(feature = "log_active_span_json")]
    fn on_enter(&self, id: &tracing::Id, ctx: Context<'_, S>) {
        let span = ctx.span(id).expect("No span");
        if let Ok(serialized) = self.span_serialize(&span, RecordType::EnterSpan) {
            let _ = self.flush(serialized);
        }
    }

    #[cfg(not(feature = "log_active_span_json"))]
    fn on_close(&self, id: tracing::Id, ctx: Context<'_, S>) {
        let span = ctx.span(&id).expect("No span");
        if span.parent().is_none() {
            if let Ok(serialized) = self.span_serialize(&span, RecordType::ExitSpan) {
                let _ = self.flush(serialized);
            }
        }
    }

    #[cfg(feature = "log_active_span_json")]
    fn on_close(&self, id: tracing::Id, ctx: Context<'_, S>) {
        let span = ctx.span(&id).expect("No span");
        if let Ok(serialized) = self.span_serialize(&span, RecordType::ExitSpan) {
            let _ = self.flush(serialized);
        }
    }
}


impl api::Payment for Globepay {}


pub async fn get_organization(
    state: SessionState,
    org_id: api::OrganizationId,
) -> RouterResponse<api::OrganizationResponse> {
    #[cfg(all(feature = "v1", feature = "olap"))]
    {
        CreateOrValidateOrganization::new(Some(org_id.organization_id))
            .create_or_validate(state.accounts_store.as_ref())
            .await
            .map(ForeignFrom::foreign_from)
            .map(service_api::ApplicationResponse::Json)
    }
    #[cfg(all(feature = "v2", feature = "olap"))]
    {
        CreateOrValidateOrganization::new(org_id.organization_id)
            .create_or_validate(state.accounts_store.as_ref())
            .await
            .map(ForeignFrom::foreign_from)
            .map(service_api::ApplicationResponse::Json)
    }
}


impl DecisionEngineErrorsInterface for DeErrorResponse {
    fn get_error_message(&self) -> String {
        self.message.clone()
    }

    fn get_error_code(&self) -> String {
        self.code.clone()
    }

    fn get_error_data(&self) -> Option<String> {
        self.data.as_ref().map(|data| data.to_string())
    }
}

impl DecisionEngineErrorsInterface for for DeErrorResponse


impl Elavon {
    pub fn new() -> &'static Self {
        &Self {
            amount_converter: &StringMajorUnitForConnector,
        }
    }
}