pub async fn push_metrics_with_update_window_for_contract_based_routing(
    state: &SessionState,
    payment_attempt: &storage::PaymentAttempt,
    routable_connectors: Vec<routing_types::RoutableConnectorChoice>,
    profile_id: &id_type::ProfileId,
    dynamic_routing_algo_ref: routing_types::DynamicRoutingAlgorithmRef,
    _dynamic_routing_config_params_interpolator: DynamicRoutingConfigParamsInterpolator,
) -> RouterResult<()> {
    if let Some(contract_routing_algo_ref) = dynamic_routing_algo_ref.contract_based_routing {
        if contract_routing_algo_ref.enabled_feature != routing_types::DynamicRoutingFeatures::None
        {
            let client = &state
                .grpc_client
                .dynamic_routing
                .as_ref()
                .ok_or(errors::ApiErrorResponse::GenericNotFoundError {
                    message: "dynamic routing gRPC client not found".to_string(),
                })?
                .contract_based_client;

            let payment_connector = &payment_attempt.connector.clone().ok_or(
                errors::ApiErrorResponse::GenericNotFoundError {
                    message: "unable to derive payment connector from payment attempt".to_string(),
                },
            )?;

            let contract_based_routing_config =
                fetch_dynamic_routing_configs::<routing_types::ContractBasedRoutingConfig>(
                    state,
                    profile_id,
                    contract_routing_algo_ref
                        .algorithm_id_with_timestamp
                        .algorithm_id
                        .ok_or(errors::ApiErrorResponse::GenericNotFoundError {
                            message: "contract_routing algorithm_id not found".to_string(),
                        })
                        .attach_printable(
                            "contract_based_routing_algorithm_id not found in business_profile",
                        )?,
                )
                .await
                .change_context(errors::ApiErrorResponse::GenericNotFoundError {
                    message: "contract based dynamic routing configs not found".to_string(),
                })
                .attach_printable("unable to retrieve contract based dynamic routing configs")?;

            let mut existing_label_info = None;

            contract_based_routing_config
                .label_info
                .as_ref()
                .map(|label_info_vec| {
                    for label_info in label_info_vec {
                        if Some(&label_info.mca_id)
                            == payment_attempt.merchant_connector_id.as_ref()
                        {
                            existing_label_info = Some(label_info.clone());
                        }
                    }
                });

            let final_label_info = existing_label_info
                .ok_or(errors::ApiErrorResponse::GenericNotFoundError {
                    message: "LabelInformation from ContractBasedRoutingConfig not found"
                        .to_string(),
                })
                .attach_printable(
                    "unable to get LabelInformation from ContractBasedRoutingConfig",
                )?;

            logger::debug!(
                "contract based routing: matched LabelInformation - {:?}",
                final_label_info
            );

            let request_label_info = routing_types::LabelInformation {
                label: final_label_info.label.clone(),
                target_count: final_label_info.target_count,
                target_time: final_label_info.target_time,
                mca_id: final_label_info.mca_id.to_owned(),
            };

            let payment_status_attribute =
                get_desired_payment_status_for_dynamic_routing_metrics(payment_attempt.status);

            if payment_status_attribute == common_enums::AttemptStatus::Charged {
                let event_request = routing_utils::UpdateContractRequestEventRequest {
                    id: profile_id.get_string_repr().to_string(),
                    params: "".to_string(),
                    labels_information: vec![
                        routing_utils::ContractLabelInformationEventRequest::from(
                            &request_label_info,
                        ),
                    ],
                };

                let routing_events_wrapper = routing_utils::RoutingEventsWrapper::new(
                    state.tenant.tenant_id.clone(),
                    state.request_id,
                    payment_attempt.payment_id.get_string_repr().to_string(),
                    profile_id.to_owned(),
                    payment_attempt.merchant_id.to_owned(),
                    "IntelligentRouter: UpdateContractScore".to_string(),
                    Some(event_request.clone()),
                    true,
                    false,
                );

                let closure = || async {
                    let update_response_result = client
                    .update_contracts(
                        profile_id.get_string_repr().into(),
                        vec![request_label_info],
                        "".to_string(),
                        vec![],
                        1,
                        state.get_grpc_headers(),
                    )
                    .await
                    .change_context(errors::ApiErrorResponse::InternalServerError)
                    .attach_printable(
                        "unable to update contract based routing window in dynamic routing service",
                    );

                    match update_response_result {
                        Ok(resp) => {
                            let updated_resp =
                                routing_utils::UpdateContractEventResponse::try_from(&resp)
                                .change_context(errors::RoutingError::RoutingEventsError { message: "Unable to convert to UpdateContractEventResponse from UpdateContractResponse".to_string(), status_code: 500 })?;
                            Ok(Some(updated_resp))
                        }
                        Err(err) => {
                            logger::error!(
                                "unable to update elimination  score in dynamic routing service: {:?}",
                                err.current_context()
                            );

                            // have to refactor errors
                            Err(error_stack::report!(
                                errors::RoutingError::ContractScoreUpdationError
                            ))
                        }
                    }
                };

                let events_response = routing_events_wrapper.construct_event_builder( "ContractScoreCalculator.UpdateContract".to_string(),
                routing_events::RoutingEngine::IntelligentRouter,
                routing_events::ApiMethod::Grpc)
                .change_context(errors::ApiErrorResponse::InternalServerError)
                .attach_printable("ContractRouting-Intelligent-Router: Failed to construct RoutingEventsBuilder")?
                .trigger_event(state, closure)
                .await
                .change_context(errors::ApiErrorResponse::InternalServerError)
                .attach_printable("ContractRouting-Intelligent-Router: Failed to update contract scores in Intelligent-Router")?;

                let _response: routing_utils::UpdateContractEventResponse = events_response
                    .response
                    .ok_or(errors::ApiErrorResponse::InternalServerError)
                    .attach_printable(
                        "UpdateContractEventResponse not found in RoutingEventResponse",
                    )?;

                let mut routing_event = events_response
                    .event
                    .ok_or(errors::RoutingError::RoutingEventsError {
                        message:
                            "ContractRouting-Intelligent-Router: RoutingEvent not found in RoutingEventsResponse"
                                .to_string(),
                        status_code: 500,
                    })
                    .change_context(errors::ApiErrorResponse::InternalServerError)
                    .attach_printable("ContractRouting-Intelligent-Router: RoutingEvent not found in RoutingEventsResponse")?;

                routing_event.set_payment_connector(routing_types::RoutableConnectorChoice {
                    choice_kind: api_models::routing::RoutableChoiceKind::FullStruct,
                    connector: common_enums::RoutableConnectors::from_str(
                        final_label_info.label.as_str(),
                    )
                    .change_context(errors::ApiErrorResponse::InternalServerError)
                    .attach_printable("unable to infer routable_connector from connector")?,
                    merchant_connector_id: Some(final_label_info.mca_id.clone()),
                });
                routing_event.set_status_code(200);
                state.event_handler().log_event(&routing_event);
            }

            let contract_based_connectors = routable_connectors
                .into_iter()
                .filter(|conn| {
                    conn.merchant_connector_id.clone() == Some(final_label_info.mca_id.clone())
                })
                .collect::<Vec<_>>();

            let contract_scores = client
                .calculate_contract_score(
                    profile_id.get_string_repr().into(),
                    contract_based_routing_config.clone(),
                    "".to_string(),
                    contract_based_connectors,
                    state.get_grpc_headers(),
                )
                .await
                .change_context(errors::ApiErrorResponse::InternalServerError)
                .attach_printable(
                    "unable to calculate/fetch contract scores from dynamic routing service",
                )?;

            let first_contract_based_connector = &contract_scores
                .labels_with_score
                .first()
                .ok_or(errors::ApiErrorResponse::InternalServerError)
                .attach_printable(
                    "unable to fetch the first connector from list of connectors obtained from dynamic routing service",
                )?;

            let (first_contract_based_connector, connector_score, current_payment_cnt) = (first_contract_based_connector.label
                .split_once(':')
                .ok_or(errors::ApiErrorResponse::InternalServerError)
                .attach_printable(format!(
                    "unable to split connector_name and mca_id from the first connector {first_contract_based_connector:?} obtained from dynamic routing service",

                ))?
                .0, first_contract_based_connector.score, first_contract_based_connector.current_count );

            core_metrics::DYNAMIC_CONTRACT_BASED_ROUTING.add(
                1,
                router_env::metric_attributes!(
                    (
                        "tenant",
                        state.tenant.tenant_id.get_string_repr().to_owned(),
                    ),
                    (
                        "merchant_profile_id",
                        format!(
                            "{}:{}",
                            payment_attempt.merchant_id.get_string_repr(),
                            payment_attempt.profile_id.get_string_repr()
                        ),
                    ),
                    (
                        "contract_based_routing_connector",
                        first_contract_based_connector.to_string(),
                    ),
                    (
                        "contract_based_routing_connector_score",
                        connector_score.to_string(),
                    ),
                    (
                        "current_payment_count_contract_based_routing_connector",
                        current_payment_cnt.to_string(),
                    ),
                    ("payment_connector", payment_connector.to_string()),
                    (
                        "currency",
                        payment_attempt
                            .currency
                            .map_or_else(|| "None".to_string(), |currency| currency.to_string()),
                    ),
                    (
                        "payment_method",
                        payment_attempt.payment_method.map_or_else(
                            || "None".to_string(),
                            |payment_method| payment_method.to_string(),
                        ),
                    ),
                    (
                        "payment_method_type",
                        payment_attempt.payment_method_type.map_or_else(
                            || "None".to_string(),
                            |payment_method_type| payment_method_type.to_string(),
                        ),
                    ),
                    (
                        "capture_method",
                        payment_attempt.capture_method.map_or_else(
                            || "None".to_string(),
                            |capture_method| capture_method.to_string(),
                        ),
                    ),
                    (
                        "authentication_type",
                        payment_attempt.authentication_type.map_or_else(
                            || "None".to_string(),
                            |authentication_type| authentication_type.to_string(),
                        ),
                    ),
                    ("payment_status", payment_attempt.status.to_string()),
                ),
            );
            logger::debug!("successfully pushed contract_based_routing metrics");

            Ok(())
        } else {
            Ok(())
        }
    } else {
        Ok(())
    }
}


pub struct CoingateConnectorMetadataObject {
    pub currency_id: i32,
    pub platform_id: i32,
    pub ledger_account_id: Secret<String>,
}


pub struct BamboraAuthType {
    pub(super) api_key: Secret<String>,
}


pub struct PazeConsumer {
    // This is consumer data not customer data.
    pub first_name: Option<Secret<String>>,
    pub last_name: Option<Secret<String>>,
    pub full_name: Secret<String>,
    pub email_address: common_utils::pii::Email,
    pub mobile_number: Option<PazePhoneNumber>,
    pub country_code: Option<common_enums::enums::CountryAlpha2>,
    pub language_code: Option<String>,
}


impl MandateUpdate {
    pub fn convert_to_mandate_update(
        self,
        storage_scheme: MerchantStorageScheme,
    ) -> MandateUpdateInternal {
        let mut updated_object = MandateUpdateInternal::from(self);
        updated_object.updated_by = Some(storage_scheme.to_string());
        updated_object
    }
}


File: crates/hyperswitch_connectors/src/connectors/elavon.rs
 Public functions: 2
 Public structs: 1

pub mod transformers;
use std::{collections::HashMap, str, sync::LazyLock};

use common_enums::{enums, CaptureMethod, PaymentMethod, PaymentMethodType};
use common_utils::{
    errors::CustomResult,
    request::{Method, Request, RequestBuilder, RequestContent},
    types::{AmountConvertor, StringMajorUnit, StringMajorUnitForConnector},
};
use error_stack::report;
use hyperswitch_domain_models::{
    payment_method_data::PaymentMethodData,
    router_data::{AccessToken, ErrorResponse, RouterData},
    router_flow_types::{
        access_token_auth::AccessTokenAuth,
        payments::{Authorize, Capture, PSync, PaymentMethodToken, Session, SetupMandate, Void},
        refunds::{Execute, RSync},
    },
    router_request_types::{
        AccessTokenRequestData, PaymentMethodTokenizationData, PaymentsAuthorizeData,
        PaymentsCancelData, PaymentsCaptureData, PaymentsSessionData, PaymentsSyncData,
        RefundsData, SetupMandateRequestData,
    },
    router_response_types::{
        ConnectorInfo, PaymentMethodDetails, PaymentsResponseData, RefundsResponseData,
        SupportedPaymentMethods, SupportedPaymentMethodsExt,
    },
    types::{
        PaymentsAuthorizeRouterData, PaymentsCancelRouterData, PaymentsCaptureRouterData,
        PaymentsSyncRouterData, RefundSyncRouterData, RefundsRouterData,
    },
};
use hyperswitch_interfaces::{
    api::{
        self, ConnectorCommon, ConnectorCommonExt, ConnectorIntegration, ConnectorSpecifications,
        ConnectorValidation,
    },
    configs::Connectors,
    errors,
    events::connector_api_logs::ConnectorEvent,
    types::{self, Response},
    webhooks,
};
use masking::{Secret, WithoutType};
use serde::Serialize;
use transformers as elavon;

use crate::{
    constants::headers,
    types::ResponseRouterData,
    utils,
    utils::{is_mandate_supported, PaymentMethodDataType},
};

pub fn struct_to_xml<T: Serialize>(
    item: &T,
) -> Result<HashMap<String, Secret<String, WithoutType>>, errors::ConnectorError> {
    let xml_content = quick_xml::se::to_string_with_root("txn", &item).map_err(|e| {
        router_env::logger::error!("Error serializing Struct: {:?}", e);
        errors::ConnectorError::ResponseDeserializationFailed
    })?;

    let mut result = HashMap::new();
    result.insert(
        "xmldata".to_string(),
        Secret::<_, WithoutType>::new(xml_content),
    );
    Ok(result)
}
#[derive(Clone)]
pub struct Elavon {
    amount_converter: &'static (dyn AmountConvertor<Output = StringMajorUnit> + Sync),
}

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

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

impl ConnectorIntegration<PaymentMethodToken, PaymentMethodTokenizationData, PaymentsResponseData>
    for Elavon
{
    // Not Implemented (R)
}

impl<Flow, Request, Response> ConnectorCommonExt<Flow, Request, Response> for Elavon
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(),
            self.get_content_type().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 Elavon {
    fn id(&self) -> &'static str {
        "elavon"
    }

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

    fn common_get_content_type(&self) -> &'static str {
        "application/x-www-form-urlencoded"
    }

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

impl ConnectorIntegration<Session, PaymentsSessionData, PaymentsResponseData> for Elavon {}

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

impl ConnectorIntegration<SetupMandate, SetupMandateRequestData, PaymentsResponseData> for Elavon {}

impl ConnectorIntegration<Authorize, PaymentsAuthorizeData, PaymentsResponseData> for Elavon {
    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!("{}processxml.do", self.base_url(connectors)))
    }

    fn get_request_body(
        &self,
        req: &PaymentsAuthorizeRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let amount = utils::convert_amount(
            self.amount_converter,
            req.request.minor_amount,
            req.request.currency,
        )?;

        let connector_router_data = elavon::ElavonRouterData::from((amount, req));
        let connector_req = elavon::ElavonPaymentsRequest::try_from(&connector_router_data)?;
        router_env::logger::info!(raw_connector_request=?connector_req);
        Ok(RequestContent::FormUrlEncoded(Box::new(struct_to_xml(
            &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: elavon::ElavonPaymentsResponse =
            utils::deserialize_xml_to_struct(&res.response)?;
        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 Elavon {
    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> {
        Ok(format!("{}processxml.do", self.base_url(connectors)))
    }

    fn get_request_body(
        &self,
        req: &PaymentsSyncRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let connector_req = elavon::SyncRequest::try_from(req)?;
        router_env::logger::info!(raw_connector_request=?connector_req);
        Ok(RequestContent::FormUrlEncoded(Box::new(struct_to_xml(
            &connector_req,
        )?)))
    }

    fn build_request(
        &self,
        req: &PaymentsSyncRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        Ok(Some(
            RequestBuilder::new()
                .method(Method::Post)
                .url(&types::PaymentsSyncType::get_url(self, req, connectors)?)
                .attach_default_headers()
                .set_body(types::PaymentsSyncType::get_request_body(
                    self, req, connectors,
                )?)
                .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: elavon::ElavonSyncResponse = utils::deserialize_xml_to_struct(&res.response)?;
        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 Elavon {
    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!("{}processxml.do", self.base_url(connectors)))
    }

    fn get_request_body(
        &self,
        req: &PaymentsCaptureRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let amount = utils::convert_amount(
            self.amount_converter,
            req.request.minor_amount_to_capture,
            req.request.currency,
        )?;
        let connector_router_data = elavon::ElavonRouterData::from((amount, req));
        let connector_req = elavon::PaymentsCaptureRequest::try_from(&connector_router_data)?;
        router_env::logger::info!(raw_connector_request=?connector_req);
        Ok(RequestContent::FormUrlEncoded(Box::new(struct_to_xml(
            &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: elavon::ElavonPaymentsResponse =
            utils::deserialize_xml_to_struct(&res.response)?;
        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 Elavon {
    fn build_request(
        &self,
        _req: &PaymentsCancelRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        Err(errors::ConnectorError::NotImplemented("Cancel/Void flow".to_string()).into())
    }
}

impl ConnectorIntegration<Execute, RefundsData, RefundsResponseData> for Elavon {
    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> {
        Ok(format!("{}processxml.do", self.base_url(connectors)))
    }

    fn get_request_body(
        &self,
        req: &RefundsRouterData<Execute>,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let refund_amount = utils::convert_amount(
            self.amount_converter,
            req.request.minor_refund_amount,
            req.request.currency,
        )?;

        let connector_router_data = elavon::ElavonRouterData::from((refund_amount, req));
        let connector_req = elavon::ElavonRefundRequest::try_from(&connector_router_data)?;
        router_env::logger::info!(raw_connector_request=?connector_req);
        Ok(RequestContent::FormUrlEncoded(Box::new(struct_to_xml(
            &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: elavon::ElavonPaymentsResponse =
            utils::deserialize_xml_to_struct(&res.response)?;
        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 Elavon {
    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!("{}processxml.do", self.base_url(connectors)))
    }
    fn get_request_body(
        &self,
        req: &RefundSyncRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let connector_req = elavon::SyncRequest::try_from(req)?;
        router_env::logger::info!(raw_connector_request=?connector_req);
        Ok(RequestContent::FormUrlEncoded(Box::new(struct_to_xml(
            &connector_req,
        )?)))
    }

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

    fn handle_response(
        &self,
        data: &RefundSyncRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<RefundSyncRouterData, errors::ConnectorError> {
        let response: elavon::ElavonSyncResponse = utils::deserialize_xml_to_struct(&res.response)?;
        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 Elavon {
    fn get_webhook_object_reference_id(
        &self,
        _request: &webhooks::IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<api_models::webhooks::ObjectReferenceId, errors::ConnectorError> {
        Err(report!(errors::ConnectorError::WebhooksNotImplemented))
    }

    fn get_webhook_event_type(
        &self,
        _request: &webhooks::IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<api_models::webhooks::IncomingWebhookEvent, errors::ConnectorError> {
        Err(report!(errors::ConnectorError::WebhooksNotImplemented))
    }

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

impl ConnectorValidation for Elavon {
    fn validate_mandate_payment(
        &self,
        pm_type: Option<PaymentMethodType>,
        pm_data: PaymentMethodData,
    ) -> CustomResult<(), errors::ConnectorError> {
        let mandate_supported_pmd = std::collections::HashSet::from([PaymentMethodDataType::Card]);
        is_mandate_supported(pm_data, pm_type, mandate_supported_pmd, self.id())
    }
}

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

    let supported_card_network = vec![
        common_enums::CardNetwork::Visa,
        common_enums::CardNetwork::Mastercard,
        common_enums::CardNetwork::AmericanExpress,
        common_enums::CardNetwork::JCB,
        common_enums::CardNetwork::DinersClub,
        common_enums::CardNetwork::UnionPay,
        common_enums::CardNetwork::Discover,
        common_enums::CardNetwork::CartesBancaires,
        common_enums::CardNetwork::Interac,
    ];

    let mut elavon_supported_payment_methods = SupportedPaymentMethods::new();

    elavon_supported_payment_methods.add(
        PaymentMethod::Card,
        PaymentMethodType::Credit,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::Supported,
            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(),
                    }
                }),
            ),
        },
    );

    elavon_supported_payment_methods.add(
        PaymentMethod::Card,
        PaymentMethodType::Debit,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::Supported,
            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(),
                    }
                }),
            ),
        },
    );

    elavon_supported_payment_methods
});

static ELAVON_CONNECTOR_INFO: ConnectorInfo = ConnectorInfo {
    display_name: "Elavon",
    description: "Elavon, a wholly owned subsidiary of U.S. Bank, has been a global leader in payment processing for more than 30 years.",
    connector_type: enums::HyperswitchConnectorCategory::PaymentGateway,
    integration_status: enums::ConnectorIntegrationStatus::Sandbox,
};

static ELAVON_SUPPORTED_WEBHOOK_FLOWS: [enums::EventClass; 0] = [];

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

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

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


impl api::ConnectorAccessToken for Fiservemea {}

impl api::ConnectorAccessToken for for Fiservemea


    RiebiņiMunicipality,
    #[strum(serialize = "RIX")]
    Riga,
    #[strum(serialize = "079")]
    RojaMunicipality,
    #[strum(serialize = "080")]
    RopažiMunicipality,
    #[strum(serialize = "081")]
    RucavaMunicipality,
    #[strum(serialize = "082")]
    RugājiMunicipality,
    #[strum(serialize = "083")]
    RundāleMunicipality,
    #[strum(serialize = "REZ")]
    Rēzekne,
    #[strum(serialize = "077")]
    RēzekneMunicipality,
    #[strum(serialize = "084")]
    RūjienaMunicipality,
    #[strum(serialize = "085")]
    SalaMunicipality,
    #[strum(serialize = "086")]
    SalacgrīvaMunicipality,
    #[strum(serialize = "087")]
    SalaspilsMunicipality,
    #[strum(serialize = "088")]
    SaldusMunicipality,
    #[strum(serialize = "089")]
    SaulkrastiMunicipality,
    #[strum(serialize = "091")]
    SiguldaMunicipality,
    #[strum(serialize = "093")]
    SkrundaMunicipality,
    #[strum(serialize = "092")]
    SkrīveriMunicipality,
    #[strum(serialize = "094")]
    SmilteneMunicipality,
    #[strum(serialize = "095")]
    StopiņiMunicipality,
    #[strum(serialize = "096")]
    StrenčiMunicipality,
    #[strum(serialize = "090")]
    SējaMunicipality,
}

#[derive(
    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, strum::Display, strum::EnumString,
)]
pub enum ItalyStatesAbbreviation {
    #[strum(serialize = "65")]
    Abruzzo,
    #[strum(serialize = "23")]
    AostaValley,
    #[strum(serialize = "75")]
    Apulia,
    #[strum(serialize = "77")]
    Basilicata,
    #[strum(serialize = "BN")]
    BeneventoProvince,
    #[strum(serialize = "78")]
    Calabria,
    #[strum(serialize = "72")]
    Campania,
    #[strum(serialize = "45")]
    EmiliaRomagna,
    #[strum(serialize = "36")]
    FriuliVeneziaGiulia,
    #[strum(serialize = "62")]
    Lazio,
    #[strum(serialize = "42")]
    Liguria,
    #[strum(serialize = "25")]
    Lombardy,
    #[strum(serialize = "57")]
    Marche,
    #[strum(serialize = "67")]
    Molise,
    #[strum(serialize = "21")]
    Piedmont,
    #[strum(serialize = "88")]
    Sardinia,
    #[strum(serialize = "82")]
    Sicily,
    #[strum(serialize = "32")]
    TrentinoSouthTyrol,
    #[strum(serialize = "52")]
    Tuscany,
    #[strum(serialize = "55")]
    Umbria,
    #[strum(serialize = "34")]
    Veneto,
    #[strum(serialize = "AG")]
    Agrigento,
    #[strum(serialize = "CL")]
    Caltanissetta,
    #[strum(serialize = "EN")]
    Enna,
    #[strum(serialize = "RG")]
    Ragusa,
    #[strum(serialize = "SR")]
    Siracusa,
    #[strum(serialize = "TP")]
    Trapani,
    #[strum(serialize = "BA")]
    Bari,
    #[strum(serialize = "BO")]
    Bologna,
    #[strum(serialize = "CA")]
    Cagliari,
    #[strum(serialize = "CT")]
    Catania,
    #[strum(serialize = "FI")]
    Florence,
    #[strum(serialize = "GE")]
    Genoa,
    #[strum(serialize = "ME")]
    Messina,
    #[strum(serialize = "MI")]
    Milan,
    #[strum(serialize = "NA")]
    Naples,
    #[strum(serialize = "PA")]
    Palermo,
    #[strum(serialize = "RC")]
    ReggioCalabria,
    #[strum(serialize = "RM")]
    Rome,
    #[strum(serialize = "TO")]
    Turin,
    #[strum(serialize = "VE")]
    Venice,
}

#[derive(
    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, strum::Display, strum::EnumString,
)]
pub enum LiechtensteinStatesAbbreviation {
    #[strum(serialize = "01")]
    Balzers,
    #[strum(serialize = "02")]
    Eschen,
    #[strum(serialize = "03")]
    Gamprin,
    #[strum(serialize = "04")]
    Mauren,
    #[strum(serialize = "05")]
    Planken,
    #[strum(serialize = "06")]
    Ruggell,
    #[strum(serialize = "07")]
    Schaan,
    #[strum(serialize = "08")]
    Schellenberg,
    #[strum(serialize = "09")]
    Triesen,
    #[strum(serialize = "10")]
    Triesenberg,
    #[strum(serialize = "11")]
    Vaduz,
}

#[derive(
    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, strum::Display, strum::EnumString,
)]
pub enum LithuaniaStatesAbbreviation {
    #[strum(serialize = "01")]
    AkmeneDistrictMunicipality,
    #[strum(serialize = "02")]
    AlytusCityMunicipality,
    #[strum(serialize = "AL")]
    AlytusCounty,
    #[strum(serialize = "03")]
    AlytusDistrictMunicipality,
    #[strum(serialize = "05")]
    BirstonasMunicipality,
    #[strum(serialize = "06")]
    BirzaiDistrictMunicipality,
    #[strum(serialize = "07")]
    DruskininkaiMunicipality,
    #[strum(serialize = "08")]
    ElektrenaiMunicipality,
    #[strum(serialize = "09")]
    IgnalinaDistrictMunicipality,
    #[strum(serialize = "10")]
    JonavaDistrictMunicipality,
    #[strum(serialize = "11")]
    JoniskisDistrictMunicipality,
    #[strum(serialize = "12")]
    JurbarkasDistrictMunicipality,
    #[strum(serialize = "13")]
    KaisiadorysDistrictMunicipality,
    #[strum(serialize = "14")]
    KalvarijaMunicipality,
    #[strum(serialize = "15")]
    KaunasCityMunicipality,
    #[strum(serialize = "KU")]
    KaunasCounty,
    #[strum(serialize = "16")]
    KaunasDistrictMunicipality,
    #[strum(serialize = "17")]
    KazluRudaMunicipality,
    #[strum(serialize = "19")]
    KelmeDistrictMunicipality,
    #[strum(serialize = "20")]
    KlaipedaCityMunicipality,
    #[strum(serialize = "KL")]
    KlaipedaCounty,
    #[strum(serialize = "21")]
    KlaipedaDistrictMunicipality,
    #[strum(serialize = "22")]
    KretingaDistrictMunicipality,
    #[strum(serialize = "23")]
    KupiskisDistrictMunicipality,
    #[strum(serialize = "18")]
    KedainiaiDistrictMunicipality,
    #[strum(serialize = "24")]
    LazdijaiDistrictMunicipality,
    #[strum(serialize = "MR")]
    MarijampoleCounty,
    #[strum(serialize = "25")]
    MarijampoleMunicipality,
    #[strum(serialize = "26")]
    MazeikiaiDistrictMunicipality,
    #[strum(serialize = "27")]
    MoletaiDistrictMunicipality,
    #[strum(serialize = "28")]
    NeringaMunicipality,
    #[strum(serialize = "29")]
    PagegiaiMunicipality,
    #[strum(serialize = "30")]
    PakruojisDistrictMunicipality,
    #[strum(serialize = "31")]
    PalangaCityMunicipality,
    #[strum(serialize = "32")]
    PanevezysCityMunicipality,
    #[strum(serialize = "PN")]
    PanevezysCounty,
    #[strum(serialize = "33")]
    PanevezysDistrictMunicipality,
    #[strum(serialize = "34")]
    PasvalysDistrictMunicipality,
    #[strum(serialize = "35")]
    PlungeDistrictMunicipality,
    #[strum(serialize = "36")]
    PrienaiDistrictMunicipality,
    #[strum(serialize = "37")]
    RadviliskisDistrictMunicipality,
    #[strum(serialize = "38")]
    RaseiniaiDistrictMunicipality,
    #[strum(serialize = "39")]
    RietavasMunicipality,
    #[strum(serialize = "40")]
    RokiskisDistrictMunicipality,
    #[strum(serialize = "48")]
    SkuodasDistrictMunicipality,
    #[strum(serialize = "TA")]
    TaurageCounty,
    #[strum(serialize = "50")]
    TaurageDistrictMunicipality,
    #[strum(serialize = "TE")]
    TelsiaiCounty,
    #[strum(serialize = "51")]
    TelsiaiDistrictMunicipality,
    #[strum(serialize = "52")]
    TrakaiDistrictMunicipality,
    #[strum(serialize = "53")]
    UkmergeDistrictMunicipality,
    #[strum(serialize = "UT")]
    UtenaCounty,
    #[strum(serialize = "54")]
    UtenaDistrictMunicipality,
    #[strum(serialize = "55")]
    VarenaDistrictMunicipality,
    #[strum(serialize = "56")]
    VilkaviskisDistrictMunicipality,
    #[strum(serialize = "57")]
    VilniusCityMunicipality,
    #[strum(serialize = "VL")]
    VilniusCounty,
    #[strum(serialize = "58")]
    VilniusDistrictMunicipality,
    #[strum(serialize = "59")]
    VisaginasMunicipality,
    #[strum(serialize = "60")]
    ZarasaiDistrictMunicipality,
    #[strum(serialize = "41")]
    SakiaiDistrictMunicipality,
    #[strum(serialize = "42")]
    SalcininkaiDistrictMunicipality,
    #[strum(serialize = "43")]
    SiauliaiCityMunicipality,
    #[strum(serialize = "SA")]
    SiauliaiCounty,
    #[strum(serialize = "44")]
    SiauliaiDistrictMunicipality,
    #[strum(serialize = "45")]
    SilaleDistrictMunicipality,
    #[strum(serialize = "46")]
    SiluteDistrictMunicipality,
    #[strum(serialize = "47")]
    SirvintosDistrictMunicipality,
    #[strum(serialize = "49")]
    SvencionysDistrictMunicipality,
}

#[derive(
    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, strum::Display, strum::EnumString,
)]
pub enum MaltaStatesAbbreviation {
    #[strum(serialize = "01")]
    Attard,
    #[strum(serialize = "02")]
    Balzan,
    #[strum(serialize = "03")]
    Birgu,
    #[strum(serialize = "04")]
    Birkirkara,
    #[strum(serialize = "05")]
    Birżebbuġa,
    #[strum(serialize = "06")]
    Cospicua,
    #[strum(serialize = "07")]
    Dingli,
    #[strum(serialize = "08")]
    Fgura,
    #[strum(serialize = "09")]
    Floriana,
    #[strum(serialize = "10")]
    Fontana,
    #[strum(serialize = "11")]
    Gudja,
    #[strum(serialize = "12")]
    Gżira,
    #[strum(serialize = "13")]
    Għajnsielem,
    #[strum(serialize = "14")]
    Għarb,
    #[strum(serialize = "15")]
    Għargħur,
    #[strum(serialize = "16")]
    Għasri,
    #[strum(serialize = "17")]
    Għaxaq,
    #[strum(serialize = "18")]
    Ħamrun,
    #[strum(serialize = "19")]
    Iklin,
    #[strum(serialize = "20")]
    Senglea,
    #[strum(serialize = "21")]
    Kalkara,
    #[strum(serialize = "22")]
    Kerċem,
    #[strum(serialize = "23")]
    Kirkop,
    #[strum(serialize = "24")]
    Lija,
    #[strum(serialize = "25")]
    Luqa,
    #[strum(serialize = "26")]
    Marsa,
    #[strum(serialize = "27")]
    Marsaskala,
    #[strum(serialize = "28")]
    Marsaxlokk,
    #[strum(serialize = "29")]
    Mdina,
    #[strum(serialize = "30")]
    Mellieħa,
    #[strum(serialize = "31")]
    Mġarr,
    #[strum(serialize = "32")]
    Mosta,
    #[strum(serialize = "33")]
    Mqabba,
    #[strum(serialize = "34")]
    Msida,
    #[strum(serialize = "35")]
    Mtarfa,
    #[strum(serialize = "36")]
    Munxar,
    #[strum(serialize = "37")]
    Nadur,
    #[strum(serialize = "38")]
    Naxxar,
    #[strum(serialize = "39")]
    Paola,
    #[strum(serialize = "40")]
    Pembroke,
    #[strum(serialize = "41")]
    Pietà,
    #[strum(serialize = "42")]
    Qala,
    #[strum(serialize = "43")]
    Qormi,
    #[strum(serialize = "44")]
    Qrendi,
    #[strum(serialize = "45")]
    Victoria,
    #[strum(serialize = "46")]
    Rabat,
    #[strum(serialize = "48")]
    StJulians,
    #[strum(serialize = "49")]
    SanĠwann,
    #[strum(serialize = "50")]
    SaintLawrence,
    #[strum(serialize = "51")]
    StPaulsBay,
    #[strum(serialize = "52")]
    Sannat,
    #[strum(serialize = "53")]
    SantaLuċija,
    #[strum(serialize = "54")]
    SantaVenera,
    #[strum(serialize = "55")]
    Siġġiewi,
    #[strum(serialize = "56")]
    Sliema,
    #[strum(serialize = "57")]
    Swieqi,
    #[strum(serialize = "58")]
    TaXbiex,
    #[strum(serialize = "59")]
    Tarxien,
    #[strum(serialize = "60")]
    Valletta,
    #[strum(serialize = "61")]
    Xagħra,
    #[strum(serialize = "62")]
    Xewkija,
    #[strum(serialize = "63")]
    Xgħajra,
    #[strum(serialize = "64")]
    Żabbar,
    #[strum(serialize = "65")]
    ŻebbuġGozo,
    #[strum(serialize = "66")]
    ŻebbuġMalta,
    #[strum(serialize = "67")]
    Żejtun,
    #[strum(serialize = "68")]
    Żurrieq,
}

#[derive(
    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, strum::Display, strum::EnumString,
)]
pub enum MoldovaStatesAbbreviation {
    #[strum(serialize = "AN")]
    AneniiNoiDistrict,
    #[strum(serialize = "BS")]
    BasarabeascaDistrict,
    #[strum(serialize = "BD")]
    BenderMunicipality,
    #[strum(serialize = "BR")]
    BriceniDistrict,
    #[strum(serialize = "BA")]
    BălțiMunicipality,
    #[strum(serialize = "CA")]
    CahulDistrict,
    #[strum(serialize = "CT")]
    CantemirDistrict,
    #[strum(serialize = "CU")]
    ChișinăuMunicipality,
    #[strum(serialize = "CM")]
    CimișliaDistrict,
    #[strum(serialize = "CR")]
    CriuleniDistrict,
    #[strum(serialize = "CL")]
    CălărașiDistrict,
    #[strum(serialize = "CS")]
    CăușeniDistrict,
    #[strum(serialize = "DO")]
    DondușeniDistrict,
    #[strum(serialize = "DR")]
    DrochiaDistrict,
    #[strum(serialize = "DU")]
    DubăsariDistrict,
    #[strum(serialize = "ED")]
    EdinețDistrict,
    #[strum(serialize = "FL")]
    FloreștiDistrict,
    #[strum(serialize = "FA")]
    FăleștiDistrict,
    #[strum(serialize = "GA")]
    Găgăuzia,
    #[strum(serialize = "GL")]
    GlodeniDistrict,
    #[strum(serialize = "HI")]
    HînceștiDistrict,
    #[strum(serialize = "IA")]
    IaloveniDistrict,
    #[strum(serialize = "NI")]
    NisporeniDistrict,
    #[strum(serialize = "OC")]
    OcnițaDistrict,
    #[strum(serialize = "OR")]
    OrheiDistrict,
    #[strum(serialize = "RE")]
    RezinaDistrict,
    #[strum(serialize = "RI")]
    RîșcaniDistrict,
    #[strum(serialize = "SO")]
    SorocaDistrict,
    #[strum(serialize = "ST")]
    StrășeniDistrict,
    #[strum(serialize = "SI")]
    SîngereiDistrict,
    #[strum(serialize = "TA")]
    TaracliaDistrict,
    #[strum(serialize = "TE")]
    TeleneștiDistrict,
    #[strum(serialize = "SN")]
    TransnistriaAutonomousTerritorialUnit,
    #[strum(serialize = "UN")]
    UngheniDistrict,
    #[strum(serialize = "SD")]
    ȘoldăneștiDistrict,
    #[strum(serialize = "SV")]
    ȘtefanVodăDistrict,
}

#[derive(
    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, strum::Display, strum::EnumString,
)]
pub enum MonacoStatesAbbreviation {
    Monaco,
}

#[derive(
    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, strum::Display, strum::EnumString,
)]
pub enum MontenegroStatesAbbreviation {
    #[strum(serialize = "01")]
    AndrijevicaMunicipality,
    #[strum(serialize = "02")]
    BarMunicipality,
    #[strum(serialize = "03")]
    BeraneMunicipality,
    #[strum(serialize = "04")]
    BijeloPoljeMunicipality,
    #[strum(serialize = "05")]
    BudvaMunicipality,
    #[strum(serialize = "07")]
    DanilovgradMunicipality,
    #[strum(serialize = "22")]
    GusinjeMunicipality,
    #[strum(serialize = "09")]
    KolasinMunicipality,
    #[strum(serialize = "10")]
    KotorMunicipality,
    #[strum(serialize = "11")]
    MojkovacMunicipality,
    #[strum(serialize = "12")]
    NiksicMunicipality,
    #[strum(serialize = "06")]
    OldRoyalCapitalCetinje,
    #[strum(serialize = "23")]
    PetnjicaMunicipality,
    #[strum(serialize = "13")]
    PlavMunicipality,
    #[strum(serialize = "14")]
    PljevljaMunicipality,
    #[strum(serialize = "15")]
    PlužineMunicipality,
    #[strum(serialize = "16")]
    PodgoricaMunicipality,
    #[strum(serialize = "17")]
    RožajeMunicipality,
    #[strum(serialize = "19")]
    TivatMunicipality,
    #[strum(serialize = "20")]
    UlcinjMunicipality,
    #[strum(serialize = "18")]
    SavnikMunicipality,
    #[strum(serialize = "21")]
    ŽabljakMunicipality,
}

#[derive(
    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, strum::Display, strum::EnumString,
)]
pub enum NetherlandsStatesAbbreviation {
    #[strum(serialize = "BQ1")]
    Bonaire,
    #[strum(serialize = "DR")]
    Drenthe,
    #[strum(serialize = "FL")]
    Flevoland,
    #[strum(serialize = "FR")]
    Friesland,
    #[strum(serialize = "GE")]
    Gelderland,
    #[strum(serialize = "GR")]
    Groningen,
    #[strum(serialize = "LI")]
    Limburg,
    #[strum(serialize = "NB")]
    NorthBrabant,
    #[strum(serialize = "NH")]
    NorthHolland,
    #[strum(serialize = "OV")]
    Overijssel,
    #[strum(serialize = "BQ2")]
    Saba,
    #[strum(serialize = "BQ3")]
    SintEustatius,
    #[strum(serialize = "ZH")]
    SouthHolland,
    #[strum(serialize = "UT")]
    Utrecht,
    #[strum(serialize = "ZE")]
    Zeeland,
}

#[derive(
    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, strum::Display, strum::EnumString,
)]
pub enum NorthMacedoniaStatesAbbreviation {
    #[strum(serialize = "01")]
    AerodromMunicipality,
    #[strum(serialize = "02")]
    AracinovoMunicipality,
    #[strum(serialize = "03")]
    BerovoMunicipality,
    #[strum(serialize = "04")]
    BitolaMunicipality,
    #[strum(serialize = "05")]
    BogdanciMunicipality,
    #[strum(serialize = "06")]
    BogovinjeMunicipality,
    #[strum(serialize = "07")]
    BosilovoMunicipality,
    #[strum(serialize = "08")]
    BrvenicaMunicipality,
    #[strum(serialize = "09")]
    ButelMunicipality,
    #[strum(serialize = "77")]
    CentarMunicipality,
    #[strum(serialize = "78")]
    CentarZupaMunicipality,
    #[strum(serialize = "22")]
    DebarcaMunicipality,
    #[strum(serialize = "23")]
    DelcevoMunicipality,
    #[strum(serialize = "25")]
    DemirHisarMunicipality,
    #[strum(serialize = "24")]
    DemirKapijaMunicipality,
    #[strum(serialize = "26")]
    DojranMunicipality,
    #[strum(serialize = "27")]
    DolneniMunicipality,
    #[strum(serialize = "28")]
    DrugovoMunicipality,
    #[strum(serialize = "17")]
    GaziBabaMunicipality,
    #[strum(serialize = "18")]
    GevgelijaMunicipality,
    #[strum(serialize = "29")]
    GjorcePetrovMunicipality,
    #[strum(serialize = "19")]
    GostivarMunicipality,
    #[strum(serialize = "20")]
    GradskoMunicipality,
    #[strum(serialize = "85")]
    GreaterSkopje,
    #[strum(serialize = "34")]
    IlindenMunicipality,
    #[strum(serialize = "35")]
    JegunovceMunicipality,
    #[strum(serialize = "37")]
    Karbinci,
    #[strum(serialize = "38")]
    KarposMunicipality,
    #[strum(serialize = "36")]
    KavadarciMunicipality,
    #[strum(serialize = "39")]
    KiselaVodaMunicipality,
    #[strum(serialize = "40")]
    KicevoMunicipality,
    #[strum(serialize = "41")]
    KonceMunicipality,
    #[strum(serialize = "42")]
    KocaniMunicipality,
    #[strum(serialize = "43")]
    KratovoMunicipality,
    #[strum(serialize = "44")]
    KrivaPalankaMunicipality,
    #[strum(serialize = "45")]
    KrivogastaniMunicipality,
    #[strum(serialize = "46")]
    KrusevoMunicipality,
    #[strum(serialize = "47")]
    KumanovoMunicipality,
    #[strum(serialize = "48")]
    LipkovoMunicipality,
    #[strum(serialize = "49")]
    LozovoMunicipality,
    #[strum(serialize = "51")]
    MakedonskaKamenicaMunicipality,
    #[strum(serialize = "52")]
    MakedonskiBrodMunicipality,
    #[strum(serialize = "50")]
    MavrovoAndRostusaMunicipality,
    #[strum(serialize = "53")]
    MogilaMunicipality,
    #[strum(serialize = "54")]
    NegotinoMunicipality,
    #[strum(serialize = "55")]
    NovaciMunicipality,
    #[strum(serialize = "56")]
    NovoSeloMunicipality,
    #[strum(serialize = "58")]
    OhridMunicipality,
    #[strum(serialize = "57")]
    OslomejMunicipality,
    #[strum(serialize = "60")]
    PehcevoMunicipality,
    #[strum(serialize = "59")]
    PetrovecMunicipality,
    #[strum(serialize = "61")]
    PlasnicaMunicipality,
    #[strum(serialize = "62")]
    PrilepMunicipality,
    #[strum(serialize = "63")]
    ProbishtipMunicipality,
    #[strum(serialize = "64")]
    RadovisMunicipality,
    #[strum(serialize = "65")]
    RankovceMunicipality,
    #[strum(serialize = "66")]
    ResenMunicipality,
    #[strum(serialize = "67")]
    RosomanMunicipality,
    #[strum(serialize = "68")]
    SarajMunicipality,
    #[strum(serialize = "70")]
    SopisteMunicipality,
    #[strum(serialize = "71")]
    StaroNagoricaneMunicipality,
    #[strum(serialize = "72")]
    StrugaMunicipality,
    #[strum(serialize = "73")]
    StrumicaMunicipality,
    #[strum(serialize = "74")]
    StudenicaniMunicipality,
    #[strum(serialize = "69")]
    SvetiNikoleMunicipality,
    #[strum(serialize = "75")]
    TearceMunicipality,
    #[strum(serialize = "76")]
    TetovoMunicipality,
    #[strum(serialize = "10")]
    ValandovoMunicipality,
    #[strum(serialize = "11")]
    VasilevoMunicipality,
    #[strum(serialize = "13")]
    VelesMunicipality,
    #[strum(serialize = "12")]
    VevcaniMunicipality,
    #[strum(serialize = "14")]
    VinicaMunicipality,
    #[strum(serialize = "15")]
    VranesticaMunicipality,
    #[strum(serialize = "16")]
    VrapcisteMunicipality,
    #[strum(serialize = "31")]
    ZajasMunicipality,
    #[strum(serialize = "32")]
    ZelenikovoMunicipality,
    #[strum(serialize = "33")]
    ZrnovciMunicipality,
    #[strum(serialize = "79")]
    CairMunicipality,
    #[strum(serialize = "80")]
    CaskaMunicipality,
    #[strum(serialize = "81")]
    CesinovoOblesevoMunicipality,
    #[strum(serialize = "82")]
    CucerSandevoMunicipality,
    #[strum(serialize = "83")]
    StipMunicipality,
    #[strum(serialize = "84")]
    ShutoOrizariMunicipality,
    #[strum(serialize = "30")]
    ZelinoMunicipality,
}

#[derive(
    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, strum::Display, strum::EnumString,
)]
pub enum NorwayStatesAbbreviation {
    #[strum(serialize = "02")]
    Akershus,
    #[strum(serialize = "06")]
    Buskerud,
    #[strum(serialize = "20")]
    Finnmark,
    #[strum(serialize = "04")]
    Hedmark,
    #[strum(serialize = "12")]
    Hordaland,
    #[strum(serialize = "22")]
    JanMayen,
    #[strum(serialize = "15")]
    MoreOgRomsdal,
    #[strum(serialize = "17")]
    NordTrondelag,
    #[strum(serialize = "18")]
    Nordland,
    #[strum(serialize = "05")]
    Oppland,
    #[strum(serialize = "03")]
    Oslo,
    #[strum(serialize = "11")]
    Rogaland,
    #[strum(serialize = "14")]
    SognOgFjordane,
    #[strum(serialize = "21")]
    Svalbard,
    #[strum(serialize = "16")]
    SorTrondelag,
    #[strum(serialize = "08")]
    Telemark,
    #[strum(serialize = "19")]
    Troms,
    #[strum(serialize = "50")]
    Trondelag,
    #[strum(serialize = "10")]
    VestAgder,
    #[strum(serialize = "07")]
    Vestfold,
    #[strum(serialize = "01")]
    Ostfold,
}

#[derive(
    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, strum::Display, strum::EnumString,
)]
pub enum PolandStatesAbbreviation {
    #[strum(serialize = "30")]
    GreaterPoland,
    #[strum(serialize = "26")]
    HolyCross,
    #[strum(serialize = "04")]
    KuyaviaPomerania,
    #[strum(serialize = "12")]
    LesserPoland,
    #[strum(serialize = "02")]
    LowerSilesia,
    #[strum(serialize = "06")]
    Lublin,
    #[strum(serialize = "08")]
    Lubusz,
    #[strum(serialize = "10")]
    Łódź,
    #[strum(serialize = "14")]
    Mazovia,
    #[strum(serialize = "20")]
    Podlaskie,
    #[strum(serialize = "22")]
    Pomerania,
    #[strum(serialize = "24")]
    Silesia,
    #[strum(serialize = "18")]
    Subcarpathia,
    #[strum(serialize = "16")]
    UpperSilesia,
    #[strum(serialize = "28")]
    WarmiaMasuria,
    #[strum(serialize = "32")]
    WestPomerania,
}

#[derive(
    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, strum::Display, strum::EnumString,
)]
pub enum PortugalStatesAbbreviation {
    #[strum(serialize = "01")]
    AveiroDistrict,
    #[strum(serialize = "20")]
    Azores,
    #[strum(serialize = "02")]
    BejaDistrict,
    #[strum(serialize = "03")]
    BragaDistrict,
    #[strum(serialize = "04")]
    BragancaDistrict,
    #[strum(serialize = "05")]
    CasteloBrancoDistrict,
    #[strum(serialize = "06")]
    CoimbraDistrict,
    #[strum(serialize = "08")]
    FaroDistrict,
    #[strum(serialize = "09")]
    GuardaDistrict,
    #[strum(serialize = "10")]
    LeiriaDistrict,
    #[strum(serialize = "11")]
    LisbonDistrict,
    #[strum(serialize = "30")]
    Madeira,
    #[strum(serialize = "12")]
    PortalegreDistrict,
    #[strum(serialize = "13")]
    PortoDistrict,
    #[strum(serialize = "14")]
    SantaremDistrict,
    #[strum(serialize = "15")]
    SetubalDistrict,
    #[strum(serialize = "16")]
    VianaDoCasteloDistrict,
    #[strum(serialize = "17")]
    VilaRealDistrict,
    #[strum(serialize = "18")]
    ViseuDistrict,
    #[strum(serialize = "07")]
    EvoraDistrict,
}

#[derive(
    Debug, Clone, PartialEq, Eq, Serialize, Deserialize, strum::Display, strum::EnumString,
)]
pub enum SpainStatesAbbreviation {
    #[strum(serialize = "C")]
    ACorunaProvince,
    #[strum(serialize = "AB")]
    AlbaceteProvince,
    #[strum(serialize = "A")]
    AlicanteProvince,
    #[strum(serialize = "AL")]
    AlmeriaProvince,
    #[strum(serialize = "AN")]
    Andalusia,
    #[strum(serialize = "VI")]
    ArabaAlava,
    #[strum(serialize = "AR")]
    Aragon,
    #[strum(serialize = "BA")]
    BadajozProvince,
    #[strum(serialize = "PM")]
    BalearicIslands,
    #[strum(serialize = "B")]
    BarcelonaProvince,
    #[strum(serialize = "PV")]
    BasqueCountry,
    #[strum(serialize = "BI")]
    Biscay,
    #[strum(serialize = "BU")]
    BurgosProvince,
    #[strum(serialize = "CN")]
    CanaryIslands,


File: crates/diesel_models/src/errors.rs

#[derive(Copy, Clone, Debug, thiserror::Error)]
pub enum DatabaseError {
    #[error("An error occurred when obtaining database connection")]
    DatabaseConnectionError,
    #[error("The requested resource was not found in the database")]
    NotFound,
    #[error("A unique constraint violation occurred")]
    UniqueViolation,
    #[error("No fields were provided to be updated")]
    NoFieldsToUpdate,
    #[error("An error occurred when generating typed SQL query")]
    QueryGenerationFailed,
    // InsertFailed,
    #[error("An unknown error occurred")]
    Others,
}

impl From<diesel::result::Error> for DatabaseError {
    fn from(error: diesel::result::Error) -> Self {
        match error {
            diesel::result::Error::DatabaseError(
                diesel::result::DatabaseErrorKind::UniqueViolation,
                _,
            ) => Self::UniqueViolation,
            diesel::result::Error::NotFound => Self::NotFound,
            diesel::result::Error::QueryBuilderError(_) => Self::QueryGenerationFailed,
            _ => Self::Others,
        }
    }
}


File: crates/router/src/core/poll.rs
 Public functions: 1

use api_models::poll::PollResponse;
use common_utils::ext_traits::StringExt;
use error_stack::ResultExt;
use router_env::{instrument, tracing};

use super::errors;
use crate::{
    core::errors::RouterResponse, services::ApplicationResponse, types::domain, SessionState,
};

#[instrument(skip_all)]
pub async fn retrieve_poll_status(
    state: SessionState,
    req: crate::types::api::PollId,
    merchant_context: domain::MerchantContext,
) -> RouterResponse<PollResponse> {
    let redis_conn = state
        .store
        .get_redis_conn()
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("Failed to get redis connection")?;
    let request_poll_id = req.poll_id;
    // prepend 'poll_{merchant_id}_' to restrict access to only fetching Poll IDs, as this is a freely passed string in the request
    let poll_id = super::utils::get_poll_id(
        merchant_context.get_merchant_account().get_id(),
        request_poll_id.clone(),
    );
    let redis_value = redis_conn
        .get_key::<Option<String>>(&poll_id.as_str().into())
        .await
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable_lazy(|| {
            format!(
                "Error while fetching the value for {} from redis",
                poll_id.clone()
            )
        })?
        .ok_or(errors::ApiErrorResponse::PollNotFound {
            id: request_poll_id.clone(),
        })?;
    let status = redis_value
        .parse_enum("PollStatus")
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("Error while parsing PollStatus")?;
    let poll_response = PollResponse {
        poll_id: request_poll_id,
        status,
    };
    Ok(ApplicationResponse::Json(poll_response))
}


pub struct BillwerkErrorResponse {
    pub code: Option<i32>,
    pub error: String,
    pub message: Option<String>,
}


pub async fn create_role_v2(
    state: web::Data<AppState>,
    req: HttpRequest,
    json_payload: web::Json<role_api::CreateRoleV2Request>,
) -> HttpResponse {
    let flow = Flow::CreateRoleV2;
    Box::pin(api::server_wrap(
        flow,
        state.clone(),
        &req,
        json_payload.into_inner(),
        role_core::create_role_v2,
        &auth::JWTAuth {
            permission: Permission::MerchantUserWrite,
        },
        api_locking::LockAction::NotApplicable,
    ))
    .await
}


pub struct AdyenCardDetails {
    card_holder: AdyenAccountHolder,
    card_identification: AdyenCardIdentification,
}


pub struct BokuPsyncRequest {
    country: String,
    merchant_id: Secret<String>,
    merchant_transaction_id: Secret<String>,
}


impl api::PaymentAuthorize for Custombilling {}

impl api::PaymentAuthorize for for Custombilling


impl ValidateStatusForOperation for PaymentIntentConfirm {
    /// Validate if the current operation can be performed on the current status of the payment intent
    fn validate_status_for_operation(
        &self,
        intent_status: common_enums::IntentStatus,
    ) -> Result<(), errors::ApiErrorResponse> {
        match intent_status {
            common_enums::IntentStatus::RequiresPaymentMethod => Ok(()),
            common_enums::IntentStatus::Succeeded
            | common_enums::IntentStatus::Conflicted
            | common_enums::IntentStatus::Failed
            | common_enums::IntentStatus::Cancelled
            | common_enums::IntentStatus::CancelledPostCapture
            | common_enums::IntentStatus::Processing
            | common_enums::IntentStatus::RequiresCustomerAction
            | common_enums::IntentStatus::RequiresMerchantAction
            | common_enums::IntentStatus::RequiresCapture
            | common_enums::IntentStatus::PartiallyAuthorizedAndRequiresCapture
            | common_enums::IntentStatus::PartiallyCaptured
            | common_enums::IntentStatus::RequiresConfirmation
            | common_enums::IntentStatus::PartiallyCapturedAndCapturable
            | common_enums::IntentStatus::Expired => {
                Err(errors::ApiErrorResponse::PaymentUnexpectedState {
                    current_flow: format!("{self:?}"),
                    field_name: "status".to_string(),
                    current_value: intent_status.to_string(),
                    states: ["requires_payment_method".to_string()].join(", "),
                })
            }
        }
    }
}

impl ValidateStatusForOperation for for PaymentIntentConfirm


impl ConnectorValidation for Nomupay {}

impl ConnectorValidation for for Nomupay


impl HashiCorpVault {
    /// Creates a new instance of HashiCorpVault based on the provided configuration.
    ///
    /// # Parameters
    ///
    /// - `config`: A reference to a `HashiCorpVaultConfig` containing the configuration details.
    pub fn new(config: &HashiCorpVaultConfig) -> error_stack::Result<Self, HashiCorpError> {
        VaultClient::new(
            VaultClientSettingsBuilder::default()
                .address(&config.url)
                .token(config.token.peek())
                .build()
                .map_err(Into::<Report<_>>::into)
                .change_context(HashiCorpError::ClientCreationFailed)
                .attach_printable("Failed while building vault settings")?,
        )
        .map_err(Into::<Report<_>>::into)
        .change_context(HashiCorpError::ClientCreationFailed)
        .map(|client| Self { client })
    }

    /// Asynchronously fetches data from HashiCorp Vault using the specified engine.
    ///
    /// # Parameters
    ///
    /// - `data`: A String representing the location or identifier of the data in HashiCorp Vault.
    ///
    /// # Type Parameters
    ///
    /// - `En`: The engine type that implements the `Engine` trait.
    /// - `I`: The type that can be constructed from the retrieved encoded data.
    pub async fn fetch<En, I>(&self, data: String) -> error_stack::Result<I, HashiCorpError>
    where
        for<'a> En: Engine<
                ReturnType<'a, String> = Pin<
                    Box<
                        dyn Future<Output = error_stack::Result<String, HashiCorpError>>
                            + Send
                            + 'a,
                    >,
                >,
            > + 'a,
        I: FromEncoded,
    {
        let output = En::read(self, data).await?;
        I::from_encoded(output).ok_or(error_stack::report!(HashiCorpError::HexDecodingFailed))
    }
}


pub struct WisePayoutQuoteResponse {
    source_amount: f64,
    client_id: String,
    id: String,
    status: WiseStatus,
    profile: i64,
    rate: Option<i8>,
    source_currency: Option<String>,
    target_currency: Option<String>,
    user: Option<i64>,
    rate_type: Option<WiseRateType>,
    pay_out: Option<WisePayOutOption>,
}


pub async fn get_metrics(
    pool: &AnalyticsProvider,
    merchant_id: &common_utils::id_type::MerchantId,
    req: GetFrmMetricRequest,
) -> AnalyticsResult<MetricsResponse<FrmMetricsBucketResponse>> {
    let mut metrics_accumulator: HashMap<FrmMetricsBucketIdentifier, FrmMetricsAccumulator> =
        HashMap::new();
    let mut set = tokio::task::JoinSet::new();
    for metric_type in req.metrics.iter().cloned() {
        let req = req.clone();
        let pool = pool.clone();
        let task_span =
            tracing::debug_span!("analytics_frm_query", frm_metric = metric_type.as_ref());
        // Currently JoinSet works with only static lifetime references even if the task pool does not outlive the given reference
        // We can optimize away this clone once that is fixed
        let merchant_id_scoped = merchant_id.to_owned();
        set.spawn(
            async move {
                let data = pool
                    .get_frm_metrics(
                        &metric_type,
                        &req.group_by_names.clone(),
                        &merchant_id_scoped,
                        &req.filters,
                        req.time_series.map(|t| t.granularity),
                        &req.time_range,
                    )
                    .await
                    .change_context(AnalyticsError::UnknownError);
                (metric_type, data)
            }
            .instrument(task_span),
        );
    }

    while let Some((metric, data)) = set
        .join_next()
        .await
        .transpose()
        .change_context(AnalyticsError::UnknownError)?
    {
        let data = data?;

        let attributes = router_env::metric_attributes!(
            ("metric_type", metric.to_string()),
            ("source", pool.to_string()),
        );
        let value = u64::try_from(data.len());
        if let Ok(val) = value {
            metrics::BUCKETS_FETCHED.record(val, attributes);
            logger::debug!("Attributes: {:?}, Buckets fetched: {}", attributes, val);
        }

        for (id, value) in data {
            logger::debug!(bucket_id=?id, bucket_value=?value, "Bucket row for metric {metric}");
            let metrics_builder = metrics_accumulator.entry(id).or_default();
            match metric {
                FrmMetrics::FrmBlockedRate => {
                    metrics_builder.frm_blocked_rate.add_metrics_bucket(&value)
                }
                FrmMetrics::FrmTriggeredAttempts => metrics_builder
                    .frm_triggered_attempts
                    .add_metrics_bucket(&value),
            }
        }

        logger::debug!(
            "Analytics Accumulated Results: metric: {}, results: {:#?}",
            metric,
            metrics_accumulator
        );
    }
    let query_data: Vec<FrmMetricsBucketResponse> = metrics_accumulator
        .into_iter()
        .map(|(id, val)| FrmMetricsBucketResponse {
            values: val.collect(),
            dimensions: id,
        })
        .collect();

    Ok(MetricsResponse {
        query_data,
        meta_data: [AnalyticsMetadata {
            current_time_range: req.time_range,
        }],
    })
}


pub fn get_destination_url(&self) -> &str {
        self.0.destination_url.as_str()
    }


pub struct Shift4WebhookObjectEventType {
    #[serde(rename = "type")]
    pub event_type: Shift4WebhookEvent,
}


impl webhooks::IncomingWebhook for Paytm {
    fn get_webhook_object_reference_id(
        &self,
        _request: &webhooks::IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<api_models::webhooks::ObjectReferenceId, errors::ConnectorError> {
        Err(report!(errors::ConnectorError::WebhooksNotImplemented))
    }

    fn get_webhook_event_type(
        &self,
        _request: &webhooks::IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<api_models::webhooks::IncomingWebhookEvent, errors::ConnectorError> {
        Err(report!(errors::ConnectorError::WebhooksNotImplemented))
    }

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

impl webhooks::IncomingWebhook for for Paytm


pub struct NoonApplePayHeader {
    ephemeral_public_key: Secret<String>,
    public_key_hash: Secret<String>,
    transaction_id: Secret<String>,
}


pub fn new(profile: domain::Profile) -> Self {
        Self { profile }
    }


impl Responder {
    let flow = Flow::PaymentsList;
    let payload = payload.into_inner();
    Box::pin(api::server_wrap(
        flow,
        state,
        &req,
        payload,
        |state, auth: auth::AuthenticationData, req, _| {
            let merchant_context = domain::MerchantContext::NormalMerchant(Box::new(
                domain::Context(auth.merchant_account, auth.key_store),
            ));
            payments::list_payments(state, merchant_context, req)
        },
        auth::auth_type(
            &auth::V2ApiKeyAuth {
                is_connected_allowed: false,
                is_platform_allowed: false,
            },
            &auth::JWTAuth {
                permission: Permission::MerchantPaymentRead,
            },
            req.headers(),
        ),
        api_locking::LockAction::NotApplicable,
    ))
    .await
}


pub fn payments_create() {}


impl ConnectorValidation for Hipay {}


/// Returns the token_type string if encrypted data exists, otherwise returns an error
    pub fn get_encrypted_token_type(&self) -> Result<String, errors::ValidationError> {
        Ok(self
            .get_encrypted_google_pay_payment_data_mandatory()?
            .token_type
            .clone())
    }


OpenAPI Block Path: components.schemas.PaymentProcessingDetails
{
  "type": "object",
  "required": [
    "payment_processing_certificate",
    "payment_processing_certificate_key"
  ],
  "properties": {
    "payment_processing_certificate": {
      "type": "string"
    },
    "payment_processing_certificate_key": {
      "type": "string"
    }
  }
}


        )?;

        let payment_id = request
            .payment_id
            .clone()
            .ok_or(report!(errors::ApiErrorResponse::PaymentNotFound))?;

        let _request_straight_through: Option<api::routing::StraightThroughAlgorithm> = request
            .routing
            .clone()
            .map(|val| val.parse_value("RoutingAlgorithm"))
            .transpose()
            .change_context(errors::ApiErrorResponse::InvalidRequestData {
                message: "Invalid straight through routing rules format".to_string(),
            })
            .attach_printable("Invalid straight through routing rules format")?;

        Ok((
            Box::new(self),
            operations::ValidateResult {
                merchant_id: merchant_context.get_merchant_account().get_id().to_owned(),
                payment_id,
                storage_scheme: merchant_context.get_merchant_account().storage_scheme,
                requeue: matches!(
                    request.retry_action,
                    Some(api_models::enums::RetryAction::Requeue)
                ),
            },
        ))
    }
}


impl api::PaymentToken for Bitpay {}


impl ApiEventMetric for PollId {
    fn get_api_event_type(&self) -> Option<ApiEventsType> {
        Some(ApiEventsType::Poll {
            poll_id: self.poll_id.clone(),
        })
    }
}


pub fn new(payment_method_id: Option<String>, status: Option<String>) -> Self {
        Self {
            payment_method_id,
            status,
            modified_at: common_utils::date_time::now(),
        }
    }


File: crates/hyperswitch_connectors/src/connectors/hyperswitch_vault/transformers.rs
 Public structs: 7

use common_utils::pii::Email;
use hyperswitch_domain_models::{
    router_data::{ConnectorAuthType, RouterData},
    router_flow_types::vault::ExternalVaultCreateFlow,
    router_response_types::{PaymentsResponseData, VaultResponseData},
    types::{ConnectorCustomerRouterData, VaultRouterData},
};
use hyperswitch_interfaces::errors;
use masking::Secret;
use serde::{Deserialize, Serialize};

use crate::{types::ResponseRouterData, utils};

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

impl TryFrom<&VaultRouterData<ExternalVaultCreateFlow>> for HyperswitchVaultCreateRequest {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(item: &VaultRouterData<ExternalVaultCreateFlow>) -> Result<Self, Self::Error> {
        let customer_id = item
            .request
            .connector_customer_id
            .clone()
            .ok_or_else(utils::missing_field_err("connector_customer"))?;
        Ok(Self { customer_id })
    }
}

pub struct HyperswitchVaultAuthType {
    pub(super) api_key: Secret<String>,
    pub(super) profile_id: Secret<String>,
}

impl TryFrom<&ConnectorAuthType> for HyperswitchVaultAuthType {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(auth_type: &ConnectorAuthType) -> Result<Self, Self::Error> {
        match auth_type {
            ConnectorAuthType::SignatureKey {
                api_key,
                api_secret,
                ..
            } => Ok(Self {
                api_key: api_key.to_owned(),
                profile_id: api_secret.to_owned(),
            }),
            _ => Err(errors::ConnectorError::FailedToObtainAuthType.into()),
        }
    }
}

#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct HyperswitchVaultCreateResponse {
    id: Secret<String>,
    client_secret: Secret<String>,
}

impl<F, T> TryFrom<ResponseRouterData<F, HyperswitchVaultCreateResponse, T, VaultResponseData>>
    for RouterData<F, T, VaultResponseData>
{
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        item: ResponseRouterData<F, HyperswitchVaultCreateResponse, T, VaultResponseData>,
    ) -> Result<Self, Self::Error> {
        Ok(Self {
            response: Ok(VaultResponseData::ExternalVaultCreateResponse {
                session_id: item.response.id,
                client_secret: item.response.client_secret,
            }),
            ..item.data
        })
    }
}

#[derive(Default, Debug, Serialize)]
pub struct HyperswitchVaultCustomerCreateRequest {
    name: Option<Secret<String>>,
    email: Option<Email>,
}

impl TryFrom<&ConnectorCustomerRouterData> for HyperswitchVaultCustomerCreateRequest {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(item: &ConnectorCustomerRouterData) -> Result<Self, Self::Error> {
        Ok(Self {
            name: item.request.name.clone(),
            email: item.request.email.clone(),
        })
    }
}

#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct HyperswitchVaultCustomerCreateResponse {
    id: String,
}

impl<F, T>
    TryFrom<ResponseRouterData<F, HyperswitchVaultCustomerCreateResponse, T, PaymentsResponseData>>
    for RouterData<F, T, PaymentsResponseData>
{
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        item: ResponseRouterData<
            F,
            HyperswitchVaultCustomerCreateResponse,
            T,
            PaymentsResponseData,
        >,
    ) -> Result<Self, Self::Error> {
        Ok(Self {
            response: Ok(PaymentsResponseData::ConnectorCustomerResponse {
                connector_customer_id: item.response.id,
            }),
            ..item.data
        })
    }
}

#[derive(Default, Debug, Serialize, Deserialize)]
pub struct HyperswitchVaultErrorResponse {
    pub error: HyperswitchVaultErrorDetails,
}

#[derive(Default, Debug, Serialize, Deserialize)]
pub struct HyperswitchVaultErrorDetails {
    #[serde(alias = "type")]
    pub error_type: String,
    pub message: Option<String>,
    pub code: String,
}


pub struct SepaBankTransferAdditionalData {
    /// Partially masked international bank account number (iban) for SEPA
    #[schema(value_type = String, example = "DE8937******013000")]
    pub iban: MaskedIban,

    /// Bank name
    #[schema(value_type = Option<String>, example = "Deutsche Bank")]
    pub bank_name: Option<String>,

    /// Bank country code
    #[schema(value_type = Option<CountryAlpha2>, example = "US")]
    pub bank_country_code: Option<common_enums::CountryAlpha2>,

    /// Bank city
    #[schema(value_type = Option<String>, example = "California")]
    pub bank_city: Option<String>,

    /// [8 / 11 digits] Bank Identifier Code (bic) / Swift Code - used in many countries for identifying a bank and it's branches
    #[schema(value_type = Option<String>, example = "HSBCGB2LXXX")]
    pub bic: Option<MaskedBic>,
}