pub trait ConnectorIntegration<T, Req, Resp>: ConnectorIntegrationAny<T, Req, Resp> + Sync {
    fn get_headers(
        &self,
        _req: &super::PaymentAuthRouterData<T, Req, Resp>,
        _connectors: &auth_types::PaymentMethodAuthConnectors,
    ) -> CustomResult<Vec<(String, Maskable<String>)>, ConnectorError> {
        Ok(vec![])
    }

    fn get_content_type(&self) -> &'static str {
        mime::APPLICATION_JSON.essence_str()
    }

    fn get_url(
        &self,
        _req: &super::PaymentAuthRouterData<T, Req, Resp>,
        _connectors: &auth_types::PaymentMethodAuthConnectors,
    ) -> CustomResult<String, ConnectorError> {
        Ok(String::new())
    }

    fn get_request_body(
        &self,
        _req: &super::PaymentAuthRouterData<T, Req, Resp>,
    ) -> CustomResult<RequestContent, ConnectorError> {
        Ok(RequestContent::Json(Box::new(serde_json::json!(r#"{}"#))))
    }

    fn build_request(
        &self,
        _req: &super::PaymentAuthRouterData<T, Req, Resp>,
        _connectors: &auth_types::PaymentMethodAuthConnectors,
    ) -> CustomResult<Option<Request>, ConnectorError> {
        Ok(None)
    }

    fn handle_response(
        &self,
        data: &super::PaymentAuthRouterData<T, Req, Resp>,
        _res: auth_types::Response,
    ) -> CustomResult<super::PaymentAuthRouterData<T, Req, Resp>, ConnectorError>
    where
        T: Clone,
        Req: Clone,
        Resp: Clone,
    {
        Ok(data.clone())
    }

    fn get_error_response(
        &self,
        _res: auth_types::Response,
    ) -> CustomResult<auth_types::ErrorResponse, ConnectorError> {
        Ok(auth_types::ErrorResponse::get_not_implemented())
    }

    fn get_5xx_error_response(
        &self,
        res: auth_types::Response,
    ) -> CustomResult<auth_types::ErrorResponse, ConnectorError> {
        let error_message = match res.status_code {
            500 => "internal_server_error",
            501 => "not_implemented",
            502 => "bad_gateway",
            503 => "service_unavailable",
            504 => "gateway_timeout",
            505 => "http_version_not_supported",
            506 => "variant_also_negotiates",
            507 => "insufficient_storage",
            508 => "loop_detected",
            510 => "not_extended",
            511 => "network_authentication_required",
            _ => "unknown_error",
        };
        Ok(auth_types::ErrorResponse {
            code: res.status_code.to_string(),
            message: error_message.to_string(),
            reason: String::from_utf8(res.response.to_vec()).ok(),
            status_code: res.status_code,
        })
    }
}


impl api::RefundExecute for Paystack {}

impl api::RefundExecute for for Paystack


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

pub mod transformers;

use std::sync::LazyLock;

use common_enums::enums;
use common_utils::{
    errors::CustomResult,
    ext_traits::BytesExt,
    request::{Method, Request, RequestBuilder, RequestContent},
    types::{AmountConvertor, StringMinorUnit, StringMinorUnitForConnector},
};
use error_stack::{report, ResultExt};
use hyperswitch_domain_models::{
    payment_method_data::PaymentMethodData,
    router_data::{AccessToken, ConnectorAuthType, 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, PaymentsResponseData, RefundsResponseData, SupportedPaymentMethods,
    },
    types::{
        PaymentsAuthorizeRouterData, 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::{ExposeInterface, Mask};
use transformers as hyperwallet;

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

#[derive(Clone)]
pub struct Hyperwallet {
    amount_converter: &'static (dyn AmountConvertor<Output = StringMinorUnit> + Sync),
}

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

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

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

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

    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.hyperwallet.base_url.as_ref()
    }

    fn get_auth_header(
        &self,
        auth_type: &ConnectorAuthType,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        let auth = hyperwallet::HyperwalletAuthType::try_from(auth_type)
            .change_context(errors::ConnectorError::FailedToObtainAuthType)?;
        Ok(vec![(
            headers::AUTHORIZATION.to_string(),
            auth.api_key.expose().into_masked(),
        )])
    }

    fn build_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        let response: hyperwallet::HyperwalletErrorResponse = res
            .response
            .parse_struct("HyperwalletErrorResponse")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;

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

        Ok(ErrorResponse {
            status_code: res.status_code,
            code: response.code,
            message: response.message,
            reason: response.reason,
            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 Hyperwallet {
    fn validate_mandate_payment(
        &self,
        _pm_type: Option<enums::PaymentMethodType>,
        pm_data: PaymentMethodData,
    ) -> CustomResult<(), errors::ConnectorError> {
        match pm_data {
            PaymentMethodData::Card(_) => Err(errors::ConnectorError::NotImplemented(
                "validate_mandate_payment does not support cards".to_string(),
            )
            .into()),
            _ => Ok(()),
        }
    }

    fn validate_psync_reference_id(
        &self,
        _data: &PaymentsSyncData,
        _is_three_ds: bool,
        _status: enums::AttemptStatus,
        _connector_meta_data: Option<common_utils::pii::SecretSerdeValue>,
    ) -> CustomResult<(), errors::ConnectorError> {
        Ok(())
    }
}

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

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

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

impl ConnectorIntegration<Authorize, PaymentsAuthorizeData, PaymentsResponseData> for Hyperwallet {
    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> {
        Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into())
    }

    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 = hyperwallet::HyperwalletRouterData::from((amount, req));
        let connector_req =
            hyperwallet::HyperwalletPaymentsRequest::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: hyperwallet::HyperwalletPaymentsResponse = res
            .response
            .parse_struct("Hyperwallet PaymentsAuthorizeResponse")
            .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 Hyperwallet {
    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> {
        Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into())
    }

    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: hyperwallet::HyperwalletPaymentsResponse = res
            .response
            .parse_struct("hyperwallet PaymentsSyncResponse")
            .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 Hyperwallet {
    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> {
        Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into())
    }

    fn get_request_body(
        &self,
        _req: &PaymentsCaptureRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        Err(errors::ConnectorError::NotImplemented("get_request_body method".to_string()).into())
    }

    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: hyperwallet::HyperwalletPaymentsResponse = res
            .response
            .parse_struct("Hyperwallet PaymentsCaptureResponse")
            .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 Hyperwallet {}

impl ConnectorIntegration<Execute, RefundsData, RefundsResponseData> for Hyperwallet {
    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> {
        Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into())
    }

    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 = hyperwallet::HyperwalletRouterData::from((refund_amount, req));
        let connector_req =
            hyperwallet::HyperwalletRefundRequest::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: hyperwallet::RefundResponse = res
            .response
            .parse_struct("hyperwallet RefundResponse")
            .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 Hyperwallet {
    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> {
        Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into())
    }

    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)?)
                .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: hyperwallet::RefundResponse = res
            .response
            .parse_struct("hyperwallet RefundSyncResponse")
            .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 Hyperwallet {
    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))
    }
}

static HYPERWALLET_SUPPORTED_PAYMENT_METHODS: LazyLock<SupportedPaymentMethods> =
    LazyLock::new(SupportedPaymentMethods::new);

static HYPERWALLET_CONNECTOR_INFO: ConnectorInfo = ConnectorInfo {
    display_name: "Hyperwallet",
    description: "Hyperwallet connector",
    connector_type: enums::HyperswitchConnectorCategory::PayoutProcessor,
    integration_status: enums::ConnectorIntegrationStatus::Alpha,
};

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

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

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

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


pub struct RevenueRecoveryResponse {
    pub id: String,
    pub name: Option<String>,
    pub schedule_time_for_payment: Option<PrimitiveDateTime>,
    pub schedule_time_for_psync: Option<PrimitiveDateTime>,
    #[schema(value_type = ProcessTrackerStatus, example = "finish")]
    pub status: enums::ProcessTrackerStatus,
    pub business_status: String,
}


pub fn generate_permissions_inner(input: TokenStream) -> TokenStream {
    let input = parse_macro_input!(input as Input);

    let res = input.permissions.iter();

    let mut enum_keys = Vec::new();
    let mut scope_impl_per = Vec::new();
    let mut entity_impl_per = Vec::new();
    let mut resource_impl_per = Vec::new();

    let mut entity_impl_res = Vec::new();

    for per in res {
        let resource_name = &per.resource_name;
        let mut permissions = Vec::new();

        for scope in per.scopes.iter() {
            for entity in per.entities.iter() {
                let key = format_ident!("{}{}{}", entity, per.resource_name, scope);

                enum_keys.push(quote! { #key });
                scope_impl_per.push(quote! { Permission::#key => PermissionScope::#scope });
                entity_impl_per.push(quote! { Permission::#key => EntityType::#entity });
                resource_impl_per.push(quote! { Permission::#key => Resource::#resource_name });
                permissions.push(quote! { Permission::#key });
            }
            let entities_iter = per.entities.iter();
            entity_impl_res
                .push(quote! { Resource::#resource_name => vec![#(EntityType::#entities_iter),*] });
        }
    }

    let expanded = quote! {
        #[derive(
            Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, serde::Serialize, serde::Deserialize, strum::Display
        )]
        pub enum Permission {
            #(#enum_keys),*
        }

        impl Permission {
            pub fn scope(&self) -> PermissionScope {
                match self {
                    #(#scope_impl_per),*
                }
            }
            pub fn entity_type(&self) -> EntityType {
                match self {
                    #(#entity_impl_per),*
                }
            }
            pub fn resource(&self) -> Resource {
                match self {
                    #(#resource_impl_per),*
                }
            }
        }

        pub trait ResourceExt {
            fn entities(&self) -> Vec<EntityType>;
        }

        impl ResourceExt for Resource {
            fn entities(&self) -> Vec<EntityType> {
                match self {
                    #(#entity_impl_res),*
                }
            }
        }
    };
    expanded.into()
}


pub struct SquareWebhookData {
    pub id: String,
    pub object: SquareWebhookObject,
}


pub fn get_negation(&self) -> Option<&[dir::DirValue]> {
        if let Self::Negation(vals) = self {
            Some(vals)
        } else {
            None
        }
    }


impl RoutingAlgorithmInterface for KafkaStore {
    async fn insert_routing_algorithm(
        &self,
        routing_algorithm: storage::RoutingAlgorithm,
    ) -> CustomResult<storage::RoutingAlgorithm, errors::StorageError> {
        self.diesel_store
            .insert_routing_algorithm(routing_algorithm)
            .await
    }

    async fn find_routing_algorithm_by_profile_id_algorithm_id(
        &self,
        profile_id: &id_type::ProfileId,
        algorithm_id: &id_type::RoutingId,
    ) -> CustomResult<storage::RoutingAlgorithm, errors::StorageError> {
        self.diesel_store
            .find_routing_algorithm_by_profile_id_algorithm_id(profile_id, algorithm_id)
            .await
    }

    async fn find_routing_algorithm_by_algorithm_id_merchant_id(
        &self,
        algorithm_id: &id_type::RoutingId,
        merchant_id: &id_type::MerchantId,
    ) -> CustomResult<storage::RoutingAlgorithm, errors::StorageError> {
        self.diesel_store
            .find_routing_algorithm_by_algorithm_id_merchant_id(algorithm_id, merchant_id)
            .await
    }

    async fn find_routing_algorithm_metadata_by_algorithm_id_profile_id(
        &self,
        algorithm_id: &id_type::RoutingId,
        profile_id: &id_type::ProfileId,
    ) -> CustomResult<storage::RoutingProfileMetadata, errors::StorageError> {
        self.diesel_store
            .find_routing_algorithm_metadata_by_algorithm_id_profile_id(algorithm_id, profile_id)
            .await
    }

    async fn list_routing_algorithm_metadata_by_profile_id(
        &self,
        profile_id: &id_type::ProfileId,
        limit: i64,
        offset: i64,
    ) -> CustomResult<Vec<storage::RoutingProfileMetadata>, errors::StorageError> {
        self.diesel_store
            .list_routing_algorithm_metadata_by_profile_id(profile_id, limit, offset)
            .await
    }

    async fn list_routing_algorithm_metadata_by_merchant_id(
        &self,
        merchant_id: &id_type::MerchantId,
        limit: i64,
        offset: i64,
    ) -> CustomResult<Vec<storage::RoutingProfileMetadata>, errors::StorageError> {
        self.diesel_store
            .list_routing_algorithm_metadata_by_merchant_id(merchant_id, limit, offset)
            .await
    }

    async fn list_routing_algorithm_metadata_by_merchant_id_transaction_type(
        &self,
        merchant_id: &id_type::MerchantId,
        transaction_type: &enums::TransactionType,
        limit: i64,
        offset: i64,
    ) -> CustomResult<Vec<storage::RoutingProfileMetadata>, errors::StorageError> {
        self.diesel_store
            .list_routing_algorithm_metadata_by_merchant_id_transaction_type(
                merchant_id,
                transaction_type,
                limit,
                offset,
            )
            .await
    }
}

impl RoutingAlgorithmInterface for for KafkaStore


impl api::MandateSetup for Globepay {}


/// Default constructor.
    pub fn new() -> Self {
        Self::default()
    }


pub struct ProfileUpdateInternal {
    pub profile_name: Option<String>,
    pub modified_at: time::PrimitiveDateTime,
    pub return_url: Option<String>,
    pub enable_payment_response_hash: Option<bool>,
    pub payment_response_hash_key: Option<String>,
    pub redirect_to_merchant_with_http_post: Option<bool>,
    pub webhook_details: Option<WebhookDetails>,
    pub metadata: Option<pii::SecretSerdeValue>,
    pub routing_algorithm: Option<serde_json::Value>,
    pub intent_fulfillment_time: Option<i64>,
    pub frm_routing_algorithm: Option<serde_json::Value>,
    pub payout_routing_algorithm: Option<serde_json::Value>,
    pub is_recon_enabled: Option<bool>,
    #[diesel(deserialize_as = super::OptionalDieselArray<String>)]
    pub applepay_verified_domains: Option<Vec<String>>,
    pub payment_link_config: Option<BusinessPaymentLinkConfig>,
    pub session_expiry: Option<i64>,
    pub authentication_connector_details: Option<AuthenticationConnectorDetails>,
    pub payout_link_config: Option<BusinessPayoutLinkConfig>,
    pub is_extended_card_info_enabled: Option<bool>,
    pub extended_card_info_config: Option<pii::SecretSerdeValue>,
    pub is_connector_agnostic_mit_enabled: Option<bool>,
    pub use_billing_as_payment_method_billing: Option<bool>,
    pub collect_shipping_details_from_wallet_connector: Option<bool>,
    pub collect_billing_details_from_wallet_connector: Option<bool>,
    pub outgoing_webhook_custom_http_headers: Option<Encryption>,
    pub always_collect_billing_details_from_wallet_connector: Option<bool>,
    pub always_collect_shipping_details_from_wallet_connector: Option<bool>,
    pub tax_connector_id: Option<common_utils::id_type::MerchantConnectorAccountId>,
    pub is_tax_connector_enabled: Option<bool>,
    pub dynamic_routing_algorithm: Option<serde_json::Value>,
    pub is_network_tokenization_enabled: Option<bool>,
    pub is_auto_retries_enabled: Option<bool>,
    pub max_auto_retries_enabled: Option<i16>,
    pub always_request_extended_authorization:
        Option<primitive_wrappers::AlwaysRequestExtendedAuthorization>,
    pub is_click_to_pay_enabled: Option<bool>,
    pub authentication_product_ids:
        Option<common_types::payments::AuthenticationConnectorAccountMap>,
    pub card_testing_guard_config: Option<CardTestingGuardConfig>,
    pub card_testing_secret_key: Option<Encryption>,
    pub is_clear_pan_retries_enabled: Option<bool>,
    pub force_3ds_challenge: Option<bool>,
    pub is_debit_routing_enabled: Option<bool>,
    pub merchant_business_country: Option<common_enums::CountryAlpha2>,
    pub is_iframe_redirection_enabled: Option<bool>,
    pub is_pre_network_tokenization_enabled: Option<bool>,
    pub three_ds_decision_rule_algorithm: Option<serde_json::Value>,
    pub acquirer_config_map: Option<common_types::domain::AcquirerConfigMap>,
    pub merchant_category_code: Option<common_enums::MerchantCategoryCode>,
    pub merchant_country_code: Option<common_types::payments::MerchantCountryCode>,
    pub dispute_polling_interval: Option<primitive_wrappers::DisputePollingIntervalInHours>,
    pub is_manual_retry_enabled: Option<bool>,
}


File: crates/router/src/db/payment_link.rs

use error_stack::report;
use router_env::{instrument, tracing};

use crate::{
    connection,
    core::errors::{self, CustomResult},
    db::MockDb,
    services::Store,
    types::storage::{self, PaymentLinkDbExt},
};

#[async_trait::async_trait]
pub trait PaymentLinkInterface {
    async fn find_payment_link_by_payment_link_id(
        &self,
        payment_link_id: &str,
    ) -> CustomResult<storage::PaymentLink, errors::StorageError>;

    async fn insert_payment_link(
        &self,
        _payment_link: storage::PaymentLinkNew,
    ) -> CustomResult<storage::PaymentLink, errors::StorageError>;

    async fn list_payment_link_by_merchant_id(
        &self,
        merchant_id: &common_utils::id_type::MerchantId,
        payment_link_constraints: api_models::payments::PaymentLinkListConstraints,
    ) -> CustomResult<Vec<storage::PaymentLink>, errors::StorageError>;
}

#[async_trait::async_trait]
impl PaymentLinkInterface for Store {
    #[instrument(skip_all)]
    async fn find_payment_link_by_payment_link_id(
        &self,
        payment_link_id: &str,
    ) -> CustomResult<storage::PaymentLink, errors::StorageError> {
        let conn = connection::pg_connection_read(self).await?;
        storage::PaymentLink::find_link_by_payment_link_id(&conn, payment_link_id)
            .await
            .map_err(|error| report!(errors::StorageError::from(error)))
    }

    #[instrument(skip_all)]
    async fn insert_payment_link(
        &self,
        payment_link_config: storage::PaymentLinkNew,
    ) -> CustomResult<storage::PaymentLink, errors::StorageError> {
        let conn = connection::pg_connection_write(self).await?;
        payment_link_config
            .insert(&conn)
            .await
            .map_err(|error| report!(errors::StorageError::from(error)))
    }

    #[instrument(skip_all)]
    async fn list_payment_link_by_merchant_id(
        &self,
        merchant_id: &common_utils::id_type::MerchantId,
        payment_link_constraints: api_models::payments::PaymentLinkListConstraints,
    ) -> CustomResult<Vec<storage::PaymentLink>, errors::StorageError> {
        let conn = connection::pg_connection_read(self).await?;
        storage::PaymentLink::filter_by_constraints(&conn, merchant_id, payment_link_constraints)
            .await
            .map_err(|error| report!(errors::StorageError::from(error)))
    }
}

#[async_trait::async_trait]
impl PaymentLinkInterface for MockDb {
    async fn insert_payment_link(
        &self,
        _payment_link: storage::PaymentLinkNew,
    ) -> CustomResult<storage::PaymentLink, errors::StorageError> {
        // TODO: Implement function for `MockDb`
        Err(errors::StorageError::MockDbError)?
    }

    async fn find_payment_link_by_payment_link_id(
        &self,
        _payment_link_id: &str,
    ) -> CustomResult<storage::PaymentLink, errors::StorageError> {
        // TODO: Implement function for `MockDb`x
        Err(errors::StorageError::MockDbError)?
    }

    async fn list_payment_link_by_merchant_id(
        &self,
        _merchant_id: &common_utils::id_type::MerchantId,
        _payment_link_constraints: api_models::payments::PaymentLinkListConstraints,
    ) -> CustomResult<Vec<storage::PaymentLink>, errors::StorageError> {
        // TODO: Implement function for `MockDb`x
        Err(errors::StorageError::MockDbError)?
    }
}


pub struct BarclaycardAuthSetupRequest {
    payment_information: PaymentInformation,
    client_reference_information: ClientReferenceInformation,
}


#[proc_macro_derive(Setter, attributes(auth_based))]
pub fn setter(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
    let input = syn::parse_macro_input!(input as syn::DeriveInput);
    let ident = &input.ident;
    // All the fields in the parent struct
    let fields = if let syn::Data::Struct(syn::DataStruct {
        fields: syn::Fields::Named(syn::FieldsNamed { ref named, .. }),
        ..
    }) = input.data
    {
        named
    } else {
        // FIXME: Use `compile_error!()` instead
        panic!("You can't use this proc-macro on structs without fields");
    };

    // Methods in the build struct like if the struct is
    // Struct i {n: u32}
    // this will be
    // pub fn set_n(&mut self,n: u32)
    let build_methods = fields.iter().map(|f| {
        let name = f.ident.as_ref().unwrap();
        let method_name = format!("set_{name}");
        let method_ident = syn::Ident::new(&method_name, name.span());
        let ty = &f.ty;
        if check_if_auth_based_attr_is_present(f, "auth_based") {
            quote::quote! {
                pub fn #method_ident(&mut self, val:#ty, is_merchant_flow: bool)->&mut Self{
                    if is_merchant_flow {
                        self.#name = val;
                    }
                    self
                }
            }
        } else {
            quote::quote! {
                pub fn #method_ident(&mut self, val:#ty)->&mut Self{
                    self.#name = val;
                    self
                }
            }
        }
    });
    let output = quote::quote! {
    #[automatically_derived]
    impl #ident {
            #(#build_methods)*
        }

    };
    output.into()
}


pub struct PayuRefundRequest {
    refund: PayuRefundRequestData,
}


pub struct PayPalDetails {
    pub success_url: Option<String>,
    pub cancel_url: Option<String>,
}


impl api::ConnectorAccessToken for Adyen {}

impl api::ConnectorAccessToken for for Adyen


pub struct VerifyWebhookSource;


pub struct FrmPaymentMethod {
    ///payment methods(card, wallet, etc) that can be used in the payment
    #[schema(value_type = PaymentMethod,example = "card")]
    pub payment_method: Option<common_enums::PaymentMethod>,
    ///payment method types(credit, debit) that can be used in the payment. This field is deprecated. It has not been removed to provide backward compatibility.
    pub payment_method_types: Option<Vec<FrmPaymentMethodType>>,
    ///frm flow type to be used, can be pre/post
    #[schema(value_type = Option<FrmPreferredFlowTypes>)]
    pub flow: Option<api_enums::FrmPreferredFlowTypes>,
}


impl api::ConnectorAccessToken for Klarna {}

impl api::ConnectorAccessToken for for Klarna


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


OpenAPI Block Path: components.schemas.CustomerDetails
{
  "type": "object",
  "description": "Passing this object creates a new customer or attaches an existing customer to the payment",
  "required": [
    "id"
  ],
  "properties": {
    "id": {
      "type": "string",
      "description": "The identifier for the customer.",
      "example": "cus_y3oqhf46pyzuxjbcn2giaqnb44",
      "maxLength": 64,
      "minLength": 1
    },
    "name": {
      "type": "string",
      "description": "The customer's name",
      "example": "John Doe",
      "nullable": true,
      "maxLength": 255
    },
    "email": {
      "type": "string",
      "description": "The customer's email address",
      "example": "johntest@test.com",
      "nullable": true,
      "maxLength": 255
    },
    "phone": {
      "type": "string",
      "description": "The customer's phone number",
      "example": "9123456789",
      "nullable": true,
      "maxLength": 10
    },
    "phone_country_code": {
      "type": "string",
      "description": "The country code for the customer's phone number",
      "example": "+1",
      "nullable": true,
      "maxLength": 2
    },
    "tax_registration_id": {
      "type": "string",
      "description": "The tax registration identifier of the customer.",
      "nullable": true,
      "maxLength": 255
    }
  }
}


impl super::KafkaMessage for KafkaPayout<'_> {
    fn key(&self) -> String {
        format!(
            "{}_{}",
            self.merchant_id.get_string_repr(),
            self.payout_attempt_id
        )
    }

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

impl super::KafkaMessage for for KafkaPayout


pub async fn perform_cgraph_filtering(
    state: &SessionState,
    key_store: &domain::MerchantKeyStore,
    chosen: Vec<routing_types::RoutableConnectorChoice>,
    backend_input: dsl_inputs::BackendInput,
    eligible_connectors: Option<&Vec<api_enums::RoutableConnectors>>,
    profile_id: &common_utils::id_type::ProfileId,
    transaction_type: &api_enums::TransactionType,
) -> RoutingResult<Vec<routing_types::RoutableConnectorChoice>> {
    let context = euclid_graph::AnalysisContext::from_dir_values(
        backend_input
            .into_context()
            .change_context(errors::RoutingError::KgraphAnalysisError)?,
    );
    let cached_cgraph = get_merchant_cgraph(state, key_store, profile_id, transaction_type).await?;

    let mut final_selection = Vec::<routing_types::RoutableConnectorChoice>::new();
    for choice in chosen {
        let routable_connector = choice.connector;
        let euclid_choice: ast::ConnectorChoice = choice.clone().foreign_into();
        let dir_val = euclid_choice
            .into_dir_value()
            .change_context(errors::RoutingError::KgraphAnalysisError)?;
        let cgraph_eligible = cached_cgraph
            .check_value_validity(
                dir_val,
                &context,
                &mut hyperswitch_constraint_graph::Memoization::new(),
                &mut hyperswitch_constraint_graph::CycleCheck::new(),
                None,
            )
            .change_context(errors::RoutingError::KgraphAnalysisError)?;

        let filter_eligible =
            eligible_connectors.map_or(true, |list| list.contains(&routable_connector));

        if cgraph_eligible && filter_eligible {
            final_selection.push(choice);
        }
    }

    Ok(final_selection)
}


File: crates/common_utils/src/hashing.rs
 Public structs: 1

use masking::{PeekInterface, Secret, Strategy};
use serde::{Deserialize, Serialize, Serializer};

#[derive(Clone, PartialEq, Debug, Deserialize)]
/// Represents a hashed string using blake3's hashing strategy.
pub struct HashedString<T: Strategy<String>>(Secret<String, T>);

impl<T: Strategy<String>> Serialize for HashedString<T> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let hashed_value = blake3::hash(self.0.peek().as_bytes()).to_hex();
        hashed_value.serialize(serializer)
    }
}

impl<T: Strategy<String>> From<Secret<String, T>> for HashedString<T> {
    fn from(value: Secret<String, T>) -> Self {
        Self(value)
    }
}


pub struct DeutschebankMandatePostRequest {
    approval_by: DeutschebankSEPAApproval,
    email_address: Email,
    iban: Secret<String>,
    first_name: Secret<String>,
    last_name: Secret<String>,
}


pub struct BankFee {
    /// Example 'domestic_transaction' only for DK domestic payments
    #[serde(rename = "_type")]
    pub bank_fee_type: Option<String>,
    /// Country code according to ISO Alpha-2
    pub country_code: Option<CountryAlpha2>,
    /// Currency code according to ISO 4217
    pub currency_code: Option<api_models::enums::Currency>,
    /// Value of the fee.
    pub value: Option<StringMajorUnit>,
    pub fees: Option<Vec<TransactionFee>>,
    /// Monetary amount
    pub total_fee_amount: InstructedAmount,
}


pub fn get_new_merchant(&self) -> NewUserMerchant {
        self.new_merchant.clone()
    }


pub struct FraudCheckTransactionData {
    pub amount: i64,
    pub order_details: Option<Vec<OrderDetailsWithAmount>>,
    pub currency: Option<common_enums::Currency>,
    pub payment_method: Option<common_enums::PaymentMethod>,
    pub error_code: Option<String>,
    pub error_message: Option<String>,
    pub connector_transaction_id: Option<String>,
    //The name of the payment gateway or financial institution that processed the transaction.
    pub connector: Option<String>,
}


File: crates/analytics/src/payment_intents/metrics/sessionized_metrics/payments_success_rate.rs

use std::collections::HashSet;

use api_models::analytics::{
    payment_intents::{
        PaymentIntentDimensions, PaymentIntentFilters, PaymentIntentMetricsBucketIdentifier,
    },
    Granularity, TimeRange,
};
use common_utils::errors::ReportSwitchExt;
use error_stack::ResultExt;
use time::PrimitiveDateTime;

use super::PaymentIntentMetricRow;
use crate::{
    enums::AuthInfo,
    query::{Aggregate, GroupByClause, QueryBuilder, QueryFilter, SeriesBucket, ToSql, Window},
    types::{AnalyticsCollection, AnalyticsDataSource, MetricsError, MetricsResult},
};

#[derive(Default)]
pub(crate) struct PaymentsSuccessRate;

#[async_trait::async_trait]
impl<T> super::PaymentIntentMetric<T> for PaymentsSuccessRate
where
    T: AnalyticsDataSource + super::PaymentIntentMetricAnalytics,
    PrimitiveDateTime: ToSql<T>,
    AnalyticsCollection: ToSql<T>,
    Granularity: GroupByClause<T>,
    Aggregate<&'static str>: ToSql<T>,
    Window<&'static str>: ToSql<T>,
{
    async fn load_metrics(
        &self,
        dimensions: &[PaymentIntentDimensions],
        auth: &AuthInfo,
        filters: &PaymentIntentFilters,
        granularity: Option<Granularity>,
        time_range: &TimeRange,
        pool: &T,
    ) -> MetricsResult<HashSet<(PaymentIntentMetricsBucketIdentifier, PaymentIntentMetricRow)>>
    {
        let mut query_builder: QueryBuilder<T> =
            QueryBuilder::new(AnalyticsCollection::PaymentIntentSessionized);

        let mut dimensions = dimensions.to_vec();

        dimensions.push(PaymentIntentDimensions::PaymentIntentStatus);

        for dim in dimensions.iter() {
            query_builder.add_select_column(dim).switch()?;
        }
        query_builder
            .add_select_column(Aggregate::Count {
                field: None,
                alias: Some("count"),
            })
            .switch()?;

        query_builder
            .add_select_column("(attempt_count = 1) as first_attempt".to_string())
            .switch()?;

        query_builder
            .add_select_column(Aggregate::Min {
                field: "created_at",
                alias: Some("start_bucket"),
            })
            .switch()?;
        query_builder
            .add_select_column(Aggregate::Max {
                field: "created_at",
                alias: Some("end_bucket"),
            })
            .switch()?;

        filters.set_filter_clause(&mut query_builder).switch()?;

        auth.set_filter_clause(&mut query_builder).switch()?;

        time_range
            .set_filter_clause(&mut query_builder)
            .attach_printable("Error filtering time range")
            .switch()?;

        for dim in dimensions.iter() {
            query_builder
                .add_group_by_clause(dim)
                .attach_printable("Error grouping by dimensions")
                .switch()?;
        }

        query_builder
            .add_group_by_clause("first_attempt")
            .attach_printable("Error grouping by first_attempt")
            .switch()?;

        if let Some(granularity) = granularity {
            granularity
                .set_group_by_clause(&mut query_builder)
                .attach_printable("Error adding granularity")
                .switch()?;
        }

        query_builder
            .execute_query::<PaymentIntentMetricRow, _>(pool)
            .await
            .change_context(MetricsError::QueryBuildingError)?
            .change_context(MetricsError::QueryExecutionFailure)?
            .into_iter()
            .map(|i| {
                Ok((
                    PaymentIntentMetricsBucketIdentifier::new(
                        None,
                        i.currency.as_ref().map(|i| i.0),
                        i.profile_id.clone(),
                        i.connector.clone(),
                        i.authentication_type.as_ref().map(|i| i.0),
                        i.payment_method.clone(),
                        i.payment_method_type.clone(),
                        i.card_network.clone(),
                        i.merchant_id.clone(),
                        i.card_last_4.clone(),
                        i.card_issuer.clone(),
                        i.error_reason.clone(),
                        TimeRange {
                            start_time: match (granularity, i.start_bucket) {
                                (Some(g), Some(st)) => g.clip_to_start(st)?,
                                _ => time_range.start_time,
                            },
                            end_time: granularity.as_ref().map_or_else(
                                || Ok(time_range.end_time),
                                |g| i.end_bucket.map(|et| g.clip_to_end(et)).transpose(),
                            )?,
                        },
                    ),
                    i,
                ))
            })
            .collect::<error_stack::Result<
                HashSet<(PaymentIntentMetricsBucketIdentifier, PaymentIntentMetricRow)>,
                crate::query::PostProcessingError,
            >>()
            .change_context(MetricsError::PostProcessingFailure)
    }
}


pub fn generate_signature(
        &self,
        auth: barclaycard::BarclaycardAuthType,
        host: String,
        resource: &str,
        payload: &String,
        date: OffsetDateTime,
        http_method: Method,
    ) -> CustomResult<String, errors::ConnectorError> {
        let barclaycard::BarclaycardAuthType {
            api_key,
            merchant_account,
            api_secret,
        } = auth;
        let is_post_method = matches!(http_method, Method::Post);
        let digest_str = if is_post_method { "digest " } else { "" };
        let headers = format!("host date (request-target) {digest_str}{V_C_MERCHANT_ID}");
        let request_target = if is_post_method {
            format!("(request-target): post {resource}\ndigest: SHA-256={payload}\n")
        } else {
            format!("(request-target): get {resource}\n")
        };
        let signature_string = format!(
            "host: {host}\ndate: {date}\n{request_target}{V_C_MERCHANT_ID}: {}",
            merchant_account.peek()
        );
        let key_value = consts::BASE64_ENGINE
            .decode(api_secret.expose())
            .change_context(errors::ConnectorError::InvalidConnectorConfig {
                config: "connector_account_details.api_secret",
            })?;
        let key = hmac::Key::new(hmac::HMAC_SHA256, &key_value);
        let signature_value =
            consts::BASE64_ENGINE.encode(hmac::sign(&key, signature_string.as_bytes()).as_ref());
        let signature_header = format!(
            r#"keyid="{}", algorithm="HmacSHA256", headers="{headers}", signature="{signature_value}""#,
            api_key.peek()
        );

        Ok(signature_header)
    }


pub fn get_entity_type(&self) -> EntityType {
        self.entity_type
    }


pub struct PspTokenization {
    /// The tokenization type to be applied for the payment method
    #[schema(value_type = TokenizationType)]
    pub tokenization_type: common_enums::TokenizationType,

    /// The merchant connector id to be used for tokenization
    #[schema(value_type = String)]
    pub connector_id: common_utils::id_type::MerchantConnectorAccountId,
}


pub struct Card {
    #[serde(rename = "account-number")]
    pub account_number: CardNumber,
    #[serde(rename = "expiration-month")]
    pub expiration_month: Secret<String>,
    #[serde(rename = "expiration-year")]
    pub expiration_year: Secret<String>,
    #[serde(rename = "card-security-code")]
    pub card_security_code: Secret<String>,
    #[serde(rename = "card-type")]
    pub card_type: String,
}


OpenAPI Block Path: components.schemas.BacsBankDebitAdditionalData
{
  "type": "object",
  "required": [
    "account_number",
    "sort_code"
  ],
  "properties": {
    "account_number": {
      "type": "string",
      "description": "Partially masked account number for Bacs payment method",
      "example": "0001****3456"
    },
    "sort_code": {
      "type": "string",
      "description": "Partially masked sort code for Bacs payment method",
      "example": "108800"
    },
    "bank_account_holder_name": {
      "type": "string",
      "description": "Bank account's owner name",
      "example": "John Doe",
      "nullable": true
    }
  }
}


impl api::PaymentAuthorize for Coinbase {}

impl api::PaymentAuthorize for for Coinbase


pub trait SchedulerSessionState: Send + Sync + Clone {
    fn get_db(&self) -> Box<dyn SchedulerInterface>;
}


File: crates/router_env/src/logger/config.rs
 Public functions: 6
 Public structs: 6

//! Logger-specific config.

use std::path::PathBuf;

use serde::Deserialize;

/// Config settings.
#[derive(Debug, Deserialize, Clone)]
pub struct Config {
    /// Logging to a file.
    pub log: Log,
}

/// Log config settings.
#[derive(Debug, Deserialize, Clone, Default)]
#[serde(default)]
pub struct Log {
    /// Logging to a file.
    pub file: LogFile,
    /// Logging to a console.
    pub console: LogConsole,
    /// Telemetry / tracing.
    pub telemetry: LogTelemetry,
}

/// Logging to a file.
#[derive(Debug, Deserialize, Clone)]
#[serde(default)]
pub struct LogFile {
    /// Whether you want to store log in log files.
    pub enabled: bool,
    /// Where to store log files.
    pub path: String,
    /// Name of log file without suffix.
    pub file_name: String,
    /// What gets into log files.
    pub level: Level,
    /// Directive which sets the log level for one or more crates/modules.
    pub filtering_directive: Option<String>,
    // pub do_async: bool, // is not used
    // pub rotation: u16,
}

/// Describes the level of verbosity of a span or event.
#[derive(Debug, Clone, Copy)]
pub struct Level(pub(super) tracing::Level);

impl Level {
    /// Returns the most verbose [`tracing::Level`]
    pub fn into_level(self) -> tracing::Level {
        self.0
    }
}

impl<'de> Deserialize<'de> for Level {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        use std::str::FromStr as _;

        let s = String::deserialize(deserializer)?;
        tracing::Level::from_str(&s)
            .map(Level)
            .map_err(serde::de::Error::custom)
    }
}

/// Logging to a console.
#[derive(Debug, Deserialize, Clone)]
#[serde(default)]
pub struct LogConsole {
    /// Whether you want to see log in your terminal.
    pub enabled: bool,
    /// What you see in your terminal.
    pub level: Level,
    /// Log format
    #[serde(default)]
    pub log_format: LogFormat,
    /// Directive which sets the log level for one or more crates/modules.
    pub filtering_directive: Option<String>,
}

/// Telemetry / tracing.
#[derive(Debug, Deserialize, Clone, Default)]
#[serde(default)]
pub struct LogTelemetry {
    /// Whether the traces pipeline is enabled.
    pub traces_enabled: bool,
    /// Whether the metrics pipeline is enabled.
    pub metrics_enabled: bool,
    /// Whether errors in setting up traces or metrics pipelines must be ignored.
    pub ignore_errors: bool,
    /// Sampling rate for traces
    pub sampling_rate: Option<f64>,
    /// Base endpoint URL to send metrics and traces to. Can optionally include the port number.
    pub otel_exporter_otlp_endpoint: Option<String>,
    /// Timeout (in milliseconds) for sending metrics and traces.
    pub otel_exporter_otlp_timeout: Option<u64>,
    /// Whether to use xray ID generator, (enable this if you plan to use AWS-XRAY)
    pub use_xray_generator: bool,
    /// Route Based Tracing
    pub route_to_trace: Option<Vec<String>>,
    /// Interval for collecting the metrics (such as gauge) in background thread
    pub bg_metrics_collection_interval_in_secs: Option<u16>,
}

/// Telemetry / tracing.
#[derive(Default, Debug, Deserialize, Clone, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum LogFormat {
    /// Default pretty log format
    Default,
    /// JSON based structured logging
    #[default]
    Json,
    /// JSON based structured logging with pretty print
    PrettyJson,
}

impl Config {
    /// Default constructor.
    pub fn new() -> Result<Self, config::ConfigError> {
        Self::new_with_config_path(None)
    }

    /// Constructor expecting config path set explicitly.
    pub fn new_with_config_path(
        explicit_config_path: Option<PathBuf>,
    ) -> Result<Self, config::ConfigError> {
        // Configuration values are picked up in the following priority order (1 being least
        // priority):
        // 1. Defaults from the implementation of the `Default` trait.
        // 2. Values from config file. The config file accessed depends on the environment
        //    specified by the `RUN_ENV` environment variable. `RUN_ENV` can be one of
        //    `development`, `sandbox` or `production`. If nothing is specified for `RUN_ENV`,
        //    `/config/development.toml` file is read.
        // 3. Environment variables prefixed with `ROUTER` and each level separated by double
        //    underscores.
        //
        // Values in config file override the defaults in `Default` trait, and the values set using
        // environment variables override both the defaults and the config file values.

        let environment = crate::env::which();
        let config_path = Self::config_path(&environment.to_string(), explicit_config_path);

        let config = Self::builder(&environment.to_string())?
            .add_source(config::File::from(config_path).required(false))
            .add_source(config::Environment::with_prefix("ROUTER").separator("__"))
            .build()?;

        // The logger may not yet be initialized when constructing the application configuration
        #[allow(clippy::print_stderr)]
        serde_path_to_error::deserialize(config).map_err(|error| {
            crate::error!(%error, "Unable to deserialize configuration");
            eprintln!("Unable to deserialize application configuration: {error}");
            error.into_inner()
        })
    }

    /// Construct config builder extending it by fall-back defaults and setting config file to load.
    pub fn builder(
        environment: &str,
    ) -> Result<config::ConfigBuilder<config::builder::DefaultState>, config::ConfigError> {
        config::Config::builder()
            // Here, it should be `set_override()` not `set_default()`.
            // "env" can't be altered by config field.
            // Should be single source of truth.
            .set_override("env", environment)
    }

    /// Config path.
    pub fn config_path(environment: &str, explicit_config_path: Option<PathBuf>) -> PathBuf {
        let mut config_path = PathBuf::new();
        if let Some(explicit_config_path_val) = explicit_config_path {
            config_path.push(explicit_config_path_val);
        } else {
            let config_file_name = match environment {
                "production" => "production.toml",
                "sandbox" => "sandbox.toml",
                _ => "development.toml",
            };

            let config_directory = Self::get_config_directory();
            config_path.push(config_directory);
            config_path.push(config_file_name);
        }
        config_path
    }

    /// Get the Directory for the config file
    /// Read the env variable `CONFIG_DIR` or fallback to `config`
    pub fn get_config_directory() -> PathBuf {
        let mut config_path = PathBuf::new();

        let config_directory =
            std::env::var(crate::env::vars::CONFIG_DIR).unwrap_or_else(|_| "config".into());

        config_path.push(crate::env::workspace_path());
        config_path.push(config_directory);
        config_path
    }
}


impl Payone {
    pub fn new() -> &'static Self {
        &Self {
            #[cfg(feature = "payouts")]
            amount_converter: &MinorUnitForConnector,
        }
    }
    pub fn generate_signature(
        &self,
        auth: payone::PayoneAuthType,
        http_method: String,
        canonicalized_path: String,
        content_type: String,
        date_header: String,
    ) -> CustomResult<String, ConnectorError> {
        let payone::PayoneAuthType {
            api_key,
            api_secret,
            ..
        } = auth;
        let string_to_hash: String = format!(
            "{}\n{}\n{}\n{}\n",
            http_method,
            content_type.trim(),
            date_header.trim(),
            canonicalized_path.trim()
        );
        let key = hmac::Key::new(hmac::HMAC_SHA256, api_secret.expose().as_bytes());
        let hash_hmac = BASE64_ENGINE.encode(hmac::sign(&key, string_to_hash.as_bytes()));
        let signature_header = format!("GCS v1HMAC:{}:{}", api_key.peek(), hash_hmac);

        Ok(signature_header)
    }
}


pub struct CompleteAuthorizeData {
    pub payment_method_data: Option<PaymentMethodData>,
    pub amount: i64,
    pub email: Option<pii::Email>,
    pub currency: storage_enums::Currency,
    pub confirm: bool,
    pub statement_descriptor_suffix: Option<String>,
    pub capture_method: Option<storage_enums::CaptureMethod>,
    // Mandates
    pub setup_future_usage: Option<storage_enums::FutureUsage>,
    pub mandate_id: Option<api_models::payments::MandateIds>,
    pub off_session: Option<bool>,
    pub setup_mandate_details: Option<mandates::MandateData>,
    pub redirect_response: Option<CompleteAuthorizeRedirectResponse>,
    pub browser_info: Option<BrowserInformation>,
    pub connector_transaction_id: Option<String>,
    pub connector_meta: Option<serde_json::Value>,
    pub complete_authorize_url: Option<String>,
    pub metadata: Option<serde_json::Value>,
    pub customer_acceptance: Option<common_payments_types::CustomerAcceptance>,
    // New amount for amount frame work
    pub minor_amount: MinorUnit,
    pub merchant_account_id: Option<Secret<String>>,
    pub merchant_config_currency: Option<storage_enums::Currency>,
    pub threeds_method_comp_ind: Option<api_models::payments::ThreeDsCompletionIndicator>,
}


impl CrmInterface for NoCrm {
    async fn make_body(&self, _details: CrmPayload) -> RequestContent {
        RequestContent::Json(Box::new(()))
    }

    async fn make_request(&self, _body: RequestContent, _origin_base_url: String) -> Request {
        RequestBuilder::default().build()
    }

    async fn send_request(
        &self,
        _proxy: &Proxy,
        _request: Request,
    ) -> CustomResult<reqwest::Response, HttpClientError> {
        logger::info!("No CRM configured!");
        Err(HttpClientError::UnexpectedState).attach_printable("No CRM configured!")
    }
}


pub struct Mandate {
    pub mandate_id: String,
    pub customer_id: common_utils::id_type::CustomerId,
    pub merchant_id: common_utils::id_type::MerchantId,
    pub payment_method_id: String,
    pub mandate_status: storage_enums::MandateStatus,
    pub mandate_type: storage_enums::MandateType,
    pub customer_accepted_at: Option<PrimitiveDateTime>,
    pub customer_ip_address: Option<Secret<String, pii::IpAddress>>,
    pub customer_user_agent: Option<String>,
    pub network_transaction_id: Option<String>,
    pub previous_attempt_id: Option<String>,
    pub created_at: PrimitiveDateTime,
    pub mandate_amount: Option<i64>,
    pub mandate_currency: Option<storage_enums::Currency>,
    pub amount_captured: Option<i64>,
    pub connector: String,
    pub connector_mandate_id: Option<String>,
    pub start_date: Option<PrimitiveDateTime>,
    pub end_date: Option<PrimitiveDateTime>,
    pub metadata: Option<pii::SecretSerdeValue>,
    pub connector_mandate_ids: Option<pii::SecretSerdeValue>,
    pub original_payment_id: Option<common_utils::id_type::PaymentId>,
    pub merchant_connector_id: Option<common_utils::id_type::MerchantConnectorAccountId>,
    pub updated_by: Option<String>,
    // This is the extended version of customer user agent that can store string upto 2048 characters unlike customer user agent that can store 255 characters at max
    pub customer_user_agent_extended: Option<String>,
}


pub struct DynamicRoutingConfigParamsInterpolator {
    pub payment_method: Option<common_enums::PaymentMethod>,
    pub payment_method_type: Option<common_enums::PaymentMethodType>,
    pub authentication_type: Option<common_enums::AuthenticationType>,
    pub currency: Option<common_enums::Currency>,
    pub country: Option<common_enums::CountryAlpha2>,
    pub card_network: Option<String>,
    pub card_bin: Option<String>,
}


impl RefundInterface for KafkaStore {
    #[cfg(feature = "v1")]
    async fn find_refund_by_internal_reference_id_merchant_id(
        &self,
        internal_reference_id: &str,
        merchant_id: &id_type::MerchantId,
        storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<diesel_refund::Refund, errors::StorageError> {
        self.diesel_store
            .find_refund_by_internal_reference_id_merchant_id(
                internal_reference_id,
                merchant_id,
                storage_scheme,
            )
            .await
    }

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

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

    #[cfg(feature = "v1")]
    async fn find_refund_by_merchant_id_connector_refund_id_connector(
        &self,
        merchant_id: &id_type::MerchantId,
        connector_refund_id: &str,
        connector: &str,
        storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<diesel_refund::Refund, errors::StorageError> {
        self.diesel_store
            .find_refund_by_merchant_id_connector_refund_id_connector(
                merchant_id,
                connector_refund_id,
                connector,
                storage_scheme,
            )
            .await
    }

    async fn update_refund(
        &self,
        this: diesel_refund::Refund,
        refund: diesel_refund::RefundUpdate,
        storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<diesel_refund::Refund, errors::StorageError> {
        let refund = self
            .diesel_store
            .update_refund(this.clone(), refund, storage_scheme)
            .await?;

        if let Err(er) = self
            .kafka_producer
            .log_refund(&refund, Some(this), self.tenant_id.clone())
            .await
        {
            logger::error!(message="Failed to insert analytics event for Refund Update {refund?}", error_message=?er);
        }
        Ok(refund)
    }

    async fn find_refund_by_merchant_id_connector_transaction_id(
        &self,
        merchant_id: &id_type::MerchantId,
        connector_transaction_id: &str,
        storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<Vec<diesel_refund::Refund>, errors::StorageError> {
        self.diesel_store
            .find_refund_by_merchant_id_connector_transaction_id(
                merchant_id,
                connector_transaction_id,
                storage_scheme,
            )
            .await
    }

    #[cfg(feature = "v2")]
    async fn find_refund_by_id(
        &self,
        id: &id_type::GlobalRefundId,
        storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<diesel_refund::Refund, errors::StorageError> {
        self.diesel_store
            .find_refund_by_id(id, storage_scheme)
            .await
    }

    async fn insert_refund(
        &self,
        new: diesel_refund::RefundNew,
        storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<diesel_refund::Refund, errors::StorageError> {
        let refund = self.diesel_store.insert_refund(new, storage_scheme).await?;

        if let Err(er) = self
            .kafka_producer
            .log_refund(&refund, None, self.tenant_id.clone())
            .await
        {
            logger::error!(message="Failed to insert analytics event for Refund Create {refund?}", error_message=?er);
        }
        Ok(refund)
    }

    #[cfg(all(feature = "v1", feature = "olap"))]
    async fn filter_refund_by_constraints(
        &self,
        merchant_id: &id_type::MerchantId,
        refund_details: &refunds::RefundListConstraints,
        storage_scheme: MerchantStorageScheme,
        limit: i64,
        offset: i64,
    ) -> CustomResult<Vec<diesel_refund::Refund>, errors::StorageError> {
        self.diesel_store
            .filter_refund_by_constraints(
                merchant_id,
                refund_details,
                storage_scheme,
                limit,
                offset,
            )
            .await
    }

    #[cfg(feature = "v2")]
    async fn filter_refund_by_constraints(
        &self,
        merchant_id: &id_type::MerchantId,
        refund_details: refunds::RefundListConstraints,
        storage_scheme: MerchantStorageScheme,
        limit: i64,
        offset: i64,
    ) -> CustomResult<Vec<diesel_refund::Refund>, errors::StorageError> {
        self.diesel_store
            .filter_refund_by_constraints(
                merchant_id,
                refund_details,
                storage_scheme,
                limit,
                offset,
            )
            .await
    }

    #[cfg(all(feature = "v1", feature = "olap"))]
    async fn filter_refund_by_meta_constraints(
        &self,
        merchant_id: &id_type::MerchantId,
        refund_details: &common_utils::types::TimeRange,
        storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<api_models::refunds::RefundListMetaData, errors::StorageError> {
        self.diesel_store
            .filter_refund_by_meta_constraints(merchant_id, refund_details, storage_scheme)
            .await
    }

    #[cfg(all(feature = "v1", feature = "olap"))]
    async fn get_refund_status_with_count(
        &self,
        merchant_id: &id_type::MerchantId,
        profile_id_list: Option<Vec<id_type::ProfileId>>,
        constraints: &common_utils::types::TimeRange,
        storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<Vec<(common_enums::RefundStatus, i64)>, errors::StorageError> {
        self.diesel_store
            .get_refund_status_with_count(merchant_id, profile_id_list, constraints, storage_scheme)
            .await
    }

    #[cfg(all(feature = "v1", feature = "olap"))]
    async fn get_total_count_of_refunds(
        &self,
        merchant_id: &id_type::MerchantId,
        refund_details: &refunds::RefundListConstraints,
        storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<i64, errors::StorageError> {
        self.diesel_store
            .get_total_count_of_refunds(merchant_id, refund_details, storage_scheme)
            .await
    }

    #[cfg(feature = "v2")]
    async fn get_total_count_of_refunds(
        &self,
        merchant_id: &id_type::MerchantId,
        refund_details: refunds::RefundListConstraints,
        storage_scheme: MerchantStorageScheme,
    ) -> CustomResult<i64, errors::StorageError> {
        self.diesel_store
            .get_total_count_of_refunds(merchant_id, refund_details, storage_scheme)
            .await
    }
}


OpenAPI Block Path: components.schemas.TriggeredBy
{
  "type": "string",
  "enum": [
    "internal",
    "external"
  ]
}


pub struct ArchipelCard {
    number: cards::CardNumber,
    expiry: CardExpiryDate,
    security_code: Option<Secret<String>>,
    card_holder_name: Option<Secret<String>>,
    application_selection_indicator: ApplicationSelectionIndicator,
    scheme: ArchipelCardScheme,
}


pub async fn connector_retrieve() {}


pub fn inner(self) -> StrongSecret<Vec<u8>> {
        self.0
    }


pub struct ProductionAgreementRequest {
    pub version: String,
    #[serde(skip_deserializing)]
    pub ip_address: Option<Secret<String, pii::IpAddress>>,
}


File: crates/api_models/src/analytics/payments.rs
 Public functions: 1
 Public structs: 10

use std::{
    collections::hash_map::DefaultHasher,
    hash::{Hash, Hasher},
};

use common_utils::id_type;

use super::{ForexMetric, NameDescription, TimeRange};
use crate::enums::{
    AttemptStatus, AuthenticationType, CardNetwork, Connector, Currency, PaymentMethod,
    PaymentMethodType, RoutingApproach,
};

#[derive(Clone, Debug, Default, serde::Deserialize, serde::Serialize)]
pub struct PaymentFilters {
    #[serde(default)]
    pub currency: Vec<Currency>,
    #[serde(default)]
    pub status: Vec<AttemptStatus>,
    #[serde(default)]
    pub connector: Vec<Connector>,
    #[serde(default)]
    pub auth_type: Vec<AuthenticationType>,
    #[serde(default)]
    pub payment_method: Vec<PaymentMethod>,
    #[serde(default)]
    pub payment_method_type: Vec<PaymentMethodType>,
    #[serde(default)]
    pub client_source: Vec<String>,
    #[serde(default)]
    pub client_version: Vec<String>,
    #[serde(default)]
    pub card_network: Vec<CardNetwork>,
    #[serde(default)]
    pub profile_id: Vec<id_type::ProfileId>,
    #[serde(default)]
    pub merchant_id: Vec<id_type::MerchantId>,
    #[serde(default)]
    pub card_last_4: Vec<String>,
    #[serde(default)]
    pub card_issuer: Vec<String>,
    #[serde(default)]
    pub error_reason: Vec<String>,
    #[serde(default)]
    pub first_attempt: Vec<bool>,
    #[serde(default)]
    pub routing_approach: Vec<RoutingApproach>,
    #[serde(default)]
    pub signature_network: Vec<String>,
    #[serde(default)]
    pub is_issuer_regulated: Vec<bool>,
    #[serde(default)]
    pub is_debit_routed: Vec<bool>,
}

#[derive(
    Debug,
    serde::Serialize,
    serde::Deserialize,
    strum::AsRefStr,
    PartialEq,
    PartialOrd,
    Eq,
    Ord,
    strum::Display,
    strum::EnumIter,
    Clone,
    Copy,
)]
#[serde(rename_all = "snake_case")]
#[strum(serialize_all = "snake_case")]
pub enum PaymentDimensions {
    // Do not change the order of these enums
    // Consult the Dashboard FE folks since these also affects the order of metrics on FE
    Connector,
    PaymentMethod,
    PaymentMethodType,
    Currency,
    #[strum(serialize = "authentication_type")]
    #[serde(rename = "authentication_type")]
    AuthType,
    #[strum(serialize = "status")]
    #[serde(rename = "status")]
    PaymentStatus,
    ClientSource,
    ClientVersion,
    ProfileId,
    CardNetwork,
    MerchantId,
    #[strum(serialize = "card_last_4")]
    #[serde(rename = "card_last_4")]
    CardLast4,
    CardIssuer,
    ErrorReason,
    RoutingApproach,
    SignatureNetwork,
    IsIssuerRegulated,
    IsDebitRouted,
}

#[derive(
    Clone,
    Debug,
    Hash,
    PartialEq,
    Eq,
    serde::Serialize,
    serde::Deserialize,
    strum::Display,
    strum::EnumIter,
    strum::AsRefStr,
)]
#[strum(serialize_all = "snake_case")]
#[serde(rename_all = "snake_case")]
pub enum PaymentMetrics {
    PaymentSuccessRate,
    PaymentCount,
    PaymentSuccessCount,
    PaymentProcessedAmount,
    AvgTicketSize,
    RetriesCount,
    ConnectorSuccessRate,
    DebitRouting,
    SessionizedPaymentSuccessRate,
    SessionizedPaymentCount,
    SessionizedPaymentSuccessCount,
    SessionizedPaymentProcessedAmount,
    SessionizedAvgTicketSize,
    SessionizedRetriesCount,
    SessionizedConnectorSuccessRate,
    SessionizedDebitRouting,
    PaymentsDistribution,
    FailureReasons,
}

impl ForexMetric for PaymentMetrics {
    fn is_forex_metric(&self) -> bool {
        matches!(
            self,
            Self::PaymentProcessedAmount
                | Self::AvgTicketSize
                | Self::DebitRouting
                | Self::SessionizedPaymentProcessedAmount
                | Self::SessionizedAvgTicketSize
                | Self::SessionizedDebitRouting,
        )
    }
}
#[derive(Debug, Default, serde::Serialize)]
pub struct ErrorResult {
    pub reason: String,
    pub count: i64,
    pub percentage: f64,
}

#[derive(
    Clone,
    Copy,
    Debug,
    Hash,
    PartialEq,
    Eq,
    serde::Serialize,
    serde::Deserialize,
    strum::Display,
    strum::EnumIter,
    strum::AsRefStr,
)]
#[strum(serialize_all = "snake_case")]
#[serde(rename_all = "snake_case")]
pub enum PaymentDistributions {
    #[strum(serialize = "error_message")]
    PaymentErrorMessage,
}

pub mod metric_behaviour {
    pub struct PaymentSuccessRate;
    pub struct PaymentCount;
    pub struct PaymentSuccessCount;
    pub struct PaymentProcessedAmount;
    pub struct AvgTicketSize;
}

impl From<PaymentMetrics> for NameDescription {
    fn from(value: PaymentMetrics) -> Self {
        Self {
            name: value.to_string(),
            desc: String::new(),
        }
    }
}

impl From<PaymentDimensions> for NameDescription {
    fn from(value: PaymentDimensions) -> Self {
        Self {
            name: value.to_string(),
            desc: String::new(),
        }
    }
}

#[derive(Debug, serde::Serialize, Eq)]
pub struct PaymentMetricsBucketIdentifier {
    pub currency: Option<Currency>,
    pub status: Option<AttemptStatus>,
    pub connector: Option<String>,
    #[serde(rename = "authentication_type")]
    pub auth_type: Option<AuthenticationType>,
    pub payment_method: Option<String>,
    pub payment_method_type: Option<String>,
    pub client_source: Option<String>,
    pub client_version: Option<String>,
    pub profile_id: Option<String>,
    pub card_network: Option<String>,
    pub merchant_id: Option<String>,
    pub card_last_4: Option<String>,
    pub card_issuer: Option<String>,
    pub error_reason: Option<String>,
    pub routing_approach: Option<RoutingApproach>,
    pub signature_network: Option<String>,
    pub is_issuer_regulated: Option<bool>,
    pub is_debit_routed: Option<bool>,
    #[serde(rename = "time_range")]
    pub time_bucket: TimeRange,
    // Coz FE sucks
    #[serde(rename = "time_bucket")]
    #[serde(with = "common_utils::custom_serde::iso8601custom")]
    pub start_time: time::PrimitiveDateTime,
}

impl PaymentMetricsBucketIdentifier {
    #[allow(clippy::too_many_arguments)]
    pub fn new(
        currency: Option<Currency>,
        status: Option<AttemptStatus>,
        connector: Option<String>,
        auth_type: Option<AuthenticationType>,
        payment_method: Option<String>,
        payment_method_type: Option<String>,
        client_source: Option<String>,
        client_version: Option<String>,
        profile_id: Option<String>,
        card_network: Option<String>,
        merchant_id: Option<String>,
        card_last_4: Option<String>,
        card_issuer: Option<String>,
        error_reason: Option<String>,
        routing_approach: Option<RoutingApproach>,
        signature_network: Option<String>,
        is_issuer_regulated: Option<bool>,
        is_debit_routed: Option<bool>,
        normalized_time_range: TimeRange,
    ) -> Self {
        Self {
            currency,
            status,
            connector,
            auth_type,
            payment_method,
            payment_method_type,
            client_source,
            client_version,
            profile_id,
            card_network,
            merchant_id,
            card_last_4,
            card_issuer,
            error_reason,
            routing_approach,
            signature_network,
            is_issuer_regulated,
            is_debit_routed,
            time_bucket: normalized_time_range,
            start_time: normalized_time_range.start_time,
        }
    }
}

impl Hash for PaymentMetricsBucketIdentifier {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.currency.hash(state);
        self.status.map(|i| i.to_string()).hash(state);
        self.connector.hash(state);
        self.auth_type.map(|i| i.to_string()).hash(state);
        self.payment_method.hash(state);
        self.payment_method_type.hash(state);
        self.client_source.hash(state);
        self.client_version.hash(state);
        self.profile_id.hash(state);
        self.card_network.hash(state);
        self.merchant_id.hash(state);
        self.card_last_4.hash(state);
        self.card_issuer.hash(state);
        self.error_reason.hash(state);
        self.routing_approach
            .clone()
            .map(|i| i.to_string())
            .hash(state);
        self.signature_network.hash(state);
        self.is_issuer_regulated.hash(state);
        self.is_debit_routed.hash(state);
        self.time_bucket.hash(state);
    }
}

impl PartialEq for PaymentMetricsBucketIdentifier {
    fn eq(&self, other: &Self) -> bool {
        let mut left = DefaultHasher::new();
        self.hash(&mut left);
        let mut right = DefaultHasher::new();
        other.hash(&mut right);
        left.finish() == right.finish()
    }
}

#[derive(Debug, serde::Serialize)]
pub struct PaymentMetricsBucketValue {
    pub payment_success_rate: Option<f64>,
    pub payment_count: Option<u64>,
    pub payment_success_count: Option<u64>,
    pub payment_processed_amount: Option<u64>,
    pub payment_processed_amount_in_usd: Option<u64>,
    pub payment_processed_count: Option<u64>,
    pub payment_processed_amount_without_smart_retries: Option<u64>,
    pub payment_processed_amount_without_smart_retries_usd: Option<u64>,
    pub payment_processed_count_without_smart_retries: Option<u64>,
    pub avg_ticket_size: Option<f64>,
    pub payment_error_message: Option<Vec<ErrorResult>>,
    pub retries_count: Option<u64>,
    pub retries_amount_processed: Option<u64>,
    pub connector_success_rate: Option<f64>,
    pub payments_success_rate_distribution: Option<f64>,
    pub payments_success_rate_distribution_without_smart_retries: Option<f64>,
    pub payments_success_rate_distribution_with_only_retries: Option<f64>,
    pub payments_failure_rate_distribution: Option<f64>,
    pub payments_failure_rate_distribution_without_smart_retries: Option<f64>,
    pub payments_failure_rate_distribution_with_only_retries: Option<f64>,
    pub failure_reason_count: Option<u64>,
    pub failure_reason_count_without_smart_retries: Option<u64>,
    pub debit_routed_transaction_count: Option<u64>,
    pub debit_routing_savings: Option<u64>,
    pub debit_routing_savings_in_usd: Option<u64>,
}

#[derive(Debug, serde::Serialize)]
pub struct MetricsBucketResponse {
    #[serde(flatten)]
    pub values: PaymentMetricsBucketValue,
    #[serde(flatten)]
    pub dimensions: PaymentMetricsBucketIdentifier,
}


pub struct DummyConnectorPaymentsRequest<const T: u8> {
    amount: MinorUnit,
    currency: Currency,
    payment_method_data: DummyPaymentMethodData,
    return_url: Option<String>,
    connector: DummyConnectors,
}


impl api::RefundSync for Payload {}


pub async fn resolve_lineage_from_user_role(
        state: &SessionState,
        user_role: &UserRole,
        user_id: &str,
    ) -> UserResult<LineageContext> {
        let org_id = utils::user_role::get_single_org_id(state, user_role).await?;
        let merchant_id =
            utils::user_role::get_single_merchant_id(state, user_role, &org_id).await?;
        let profile_id =
            utils::user_role::get_single_profile_id(state, user_role, &merchant_id).await?;

        Ok(LineageContext {
            user_id: user_id.to_string(),
            org_id,
            merchant_id,
            profile_id,
            role_id: user_role.role_id.clone(),
            tenant_id: user_role.tenant_id.clone(),
        })
    }


/// Get the expiration month from the Google Pay pre-decrypt data
    pub fn get_expiry_month(&self) -> Result<Secret<String>, errors::ValidationError> {
        let month_str = self.card_exp_month.peek();
        let month = month_str
            .parse::<u8>()
            .map_err(|_| errors::ValidationError::InvalidValue {
                message: format!("Failed to parse expiry month: {month_str}"),
            })?;

        if !(1..=12).contains(&month) {
            return Err(errors::ValidationError::InvalidValue {
                message: format!("Invalid expiry month: {month}. Must be between 1 and 12"),
            }
            .into());
        }
        Ok(self.card_exp_month.clone())
    }


impl api::PayoutCreate for Paypal {}


File: crates/router/src/core/errors/user/sample_data.rs

use api_models::errors::types::{ApiError, ApiErrorResponse};
use common_utils::errors::{CustomResult, ErrorSwitch, ErrorSwitchFrom};
use storage_impl::errors::StorageError;

pub type SampleDataResult<T> = CustomResult<T, SampleDataError>;

#[derive(Debug, Clone, serde::Serialize, thiserror::Error)]
pub enum SampleDataError {
    #[error["Internal Server Error"]]
    InternalServerError,
    #[error("Data Does Not Exist")]
    DataDoesNotExist,
    #[error("Invalid Parameters")]
    InvalidParameters,
    #[error["Invalid Records"]]
    InvalidRange,
}

impl ErrorSwitch<ApiErrorResponse> for SampleDataError {
    fn switch(&self) -> ApiErrorResponse {
        match self {
            Self::InternalServerError => ApiErrorResponse::InternalServerError(ApiError::new(
                "SD",
                0,
                "Something went wrong",
                None,
            )),
            Self::DataDoesNotExist => ApiErrorResponse::NotFound(ApiError::new(
                "SD",
                1,
                "Sample Data not present for given request",
                None,
            )),
            Self::InvalidParameters => ApiErrorResponse::BadRequest(ApiError::new(
                "SD",
                2,
                "Invalid parameters to generate Sample Data",
                None,
            )),
            Self::InvalidRange => ApiErrorResponse::BadRequest(ApiError::new(
                "SD",
                3,
                "Records to be generated should be between range 10 and 100",
                None,
            )),
        }
    }
}

impl ErrorSwitchFrom<StorageError> for SampleDataError {
    fn switch_from(error: &StorageError) -> Self {
        match matches!(error, StorageError::ValueNotFound(_)) {
            true => Self::DataDoesNotExist,
            false => Self::InternalServerError,
        }
    }
}


pub async fn set_dashboard_metadata(
    state: web::Data<AppState>,
    req: HttpRequest,
    json_payload: web::Json<user_api::dashboard_metadata::SetMetaDataRequest>,
) -> HttpResponse {
    let flow = Flow::SetDashboardMetadata;
    let mut payload = json_payload.into_inner();

    if let Err(e) = ReportSwitchExt::<(), ApiErrorResponse>::switch(set_ip_address_if_required(
        &mut payload,
        req.headers(),
    )) {
        return api::log_and_return_error_response(e);
    }

    Box::pin(api::server_wrap(
        flow,
        state,
        &req,
        payload,
        user_core::dashboard_metadata::set_metadata,
        &auth::JWTAuth {
            permission: Permission::ProfileAccountWrite,
        },
        api_locking::LockAction::NotApplicable,
    ))
    .await
}


File: crates/router/src/compatibility.rs

pub mod stripe;
pub mod wrap;


impl api::PaymentSync for Gpayments {}


pub struct DwollaAmount {
    pub currency: common_enums::Currency,
    pub value: StringMajorUnit,
}


impl api::PaymentSync for Adyen {}


pub trait PayoutsInterface {}


pub struct Storage<'a> {
    /// Hash map to store values.
    pub values: HashMap<&'a str, serde_json::Value>,
}


pub struct NmiRefundSyncResponse {
    transaction: RefundSyncBody,
}


pub async fn refresh_routing_cache_v1(
    state: &SessionState,
    key: String,
    algorithm_id: &common_utils::id_type::RoutingId,
    profile_id: &common_utils::id_type::ProfileId,
) -> RoutingResult<Arc<CachedAlgorithm>> {
    let algorithm = {
        let algorithm = state
            .store
            .find_routing_algorithm_by_profile_id_algorithm_id(profile_id, algorithm_id)
            .await
            .change_context(errors::RoutingError::DslMissingInDb)?;
        let algorithm: routing_types::StaticRoutingAlgorithm = algorithm
            .algorithm_data
            .parse_value("RoutingAlgorithm")
            .change_context(errors::RoutingError::DslParsingError)?;
        algorithm
    };

    let cached_algorithm = match algorithm {
        routing_types::StaticRoutingAlgorithm::Single(conn) => CachedAlgorithm::Single(conn),
        routing_types::StaticRoutingAlgorithm::Priority(plist) => CachedAlgorithm::Priority(plist),
        routing_types::StaticRoutingAlgorithm::VolumeSplit(splits) => {
            CachedAlgorithm::VolumeSplit(splits)
        }
        routing_types::StaticRoutingAlgorithm::Advanced(program) => {
            let interpreter = backend::VirInterpreterBackend::with_program(program)
                .change_context(errors::RoutingError::DslBackendInitError)
                .attach_printable("Error initializing DSL interpreter backend")?;

            CachedAlgorithm::Advanced(interpreter)
        }
        api_models::routing::StaticRoutingAlgorithm::ThreeDsDecisionRule(_program) => {
            Err(errors::RoutingError::InvalidRoutingAlgorithmStructure)
                .attach_printable("Unsupported algorithm received")?
        }
    };

    let arc_cached_algorithm = Arc::new(cached_algorithm);

    ROUTING_CACHE
        .push(
            CacheKey {
                key,
                prefix: state.tenant.redis_key_prefix.clone(),
            },
            arc_cached_algorithm.clone(),
        )
        .await;

    Ok(arc_cached_algorithm)
}


pub async fn routing_create_config() {}


pub struct ProcessingInformation {
    commerce_indicator: String,
    capture: Option<bool>,
    payment_solution: Option<String>,
    cavv_algorithm: Option<String>,
}


pub struct ProxyRequestWrapper(pub proxy_api_models::ProxyRequest);


File: crates/external_services/src/file_storage/file_system.rs

//! Module for local file system storage operations

use std::{
    fs::{remove_file, File},
    io::{Read, Write},
    path::PathBuf,
};

use common_utils::errors::CustomResult;
use error_stack::ResultExt;

use crate::file_storage::{FileStorageError, FileStorageInterface};

/// Constructs the file path for a given file key within the file system.
/// The file path is generated based on the workspace path and the provided file key.
fn get_file_path(file_key: impl AsRef<str>) -> PathBuf {
    let mut file_path = PathBuf::new();
    file_path.push(std::env::current_dir().unwrap_or(".".into()));

    file_path.push("files");
    file_path.push(file_key.as_ref());
    file_path
}

/// Represents a file system for storing and managing files locally.
#[derive(Debug, Clone)]
pub(super) struct FileSystem;

impl FileSystem {
    /// Saves the provided file data to the file system under the specified file key.
    async fn upload_file(
        &self,
        file_key: &str,
        file: Vec<u8>,
    ) -> CustomResult<(), FileSystemStorageError> {
        let file_path = get_file_path(file_key);

        // Ignore the file name and create directories in the `file_path` if not exists
        std::fs::create_dir_all(
            file_path
                .parent()
                .ok_or(FileSystemStorageError::CreateDirFailed)
                .attach_printable("Failed to obtain parent directory")?,
        )
        .change_context(FileSystemStorageError::CreateDirFailed)?;

        let mut file_handler =
            File::create(file_path).change_context(FileSystemStorageError::CreateFailure)?;
        file_handler
            .write_all(&file)
            .change_context(FileSystemStorageError::WriteFailure)?;
        Ok(())
    }

    /// Deletes the file associated with the specified file key from the file system.
    async fn delete_file(&self, file_key: &str) -> CustomResult<(), FileSystemStorageError> {
        let file_path = get_file_path(file_key);
        remove_file(file_path).change_context(FileSystemStorageError::DeleteFailure)?;
        Ok(())
    }

    /// Retrieves the file content associated with the specified file key from the file system.
    async fn retrieve_file(&self, file_key: &str) -> CustomResult<Vec<u8>, FileSystemStorageError> {
        let mut received_data: Vec<u8> = Vec::new();
        let file_path = get_file_path(file_key);
        let mut file =
            File::open(file_path).change_context(FileSystemStorageError::FileOpenFailure)?;
        file.read_to_end(&mut received_data)
            .change_context(FileSystemStorageError::ReadFailure)?;
        Ok(received_data)
    }
}

#[async_trait::async_trait]
impl FileStorageInterface for FileSystem {
    /// Saves the provided file data to the file system under the specified file key.
    async fn upload_file(
        &self,
        file_key: &str,
        file: Vec<u8>,
    ) -> CustomResult<(), FileStorageError> {
        self.upload_file(file_key, file)
            .await
            .change_context(FileStorageError::UploadFailed)?;
        Ok(())
    }

    /// Deletes the file associated with the specified file key from the file system.
    async fn delete_file(&self, file_key: &str) -> CustomResult<(), FileStorageError> {
        self.delete_file(file_key)
            .await
            .change_context(FileStorageError::DeleteFailed)?;
        Ok(())
    }

    /// Retrieves the file content associated with the specified file key from the file system.
    async fn retrieve_file(&self, file_key: &str) -> CustomResult<Vec<u8>, FileStorageError> {
        Ok(self
            .retrieve_file(file_key)
            .await
            .change_context(FileStorageError::RetrieveFailed)?)
    }
}

/// Represents an error that can occur during local file system storage operations.
#[derive(Debug, thiserror::Error)]
enum FileSystemStorageError {
    /// Error indicating opening a file failed
    #[error("Failed while opening the file")]
    FileOpenFailure,

    /// Error indicating file creation failed.
    #[error("Failed to create file")]
    CreateFailure,

    /// Error indicating reading a file failed.
    #[error("Failed while reading the file")]
    ReadFailure,

    /// Error indicating writing to a file failed.
    #[error("Failed while writing into file")]
    WriteFailure,

    /// Error indicating file deletion failed.
    #[error("Failed while deleting the file")]
    DeleteFailure,

    /// Error indicating directory creation failed
    #[error("Failed while creating a directory")]
    CreateDirFailed,
}


impl super::KafkaMessage for KafkaAuthenticationEvent<'_> {
    fn key(&self) -> String {
        format!(
            "{}_{}",
            self.merchant_id.get_string_repr(),
            self.authentication_id.get_string_repr()
        )
    }

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

impl super::KafkaMessage for for KafkaAuthenticationEvent