    sale_status: SaleStatus,
    payme_transaction_id: Option<String>,
    status_error_code: Option<u32>,
}

impl TryFrom<RefundsResponseRouterData<Execute, PaymeRefundResponse>>
    for RefundsRouterData<Execute>
{
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        item: RefundsResponseRouterData<Execute, PaymeRefundResponse>,
    ) -> Result<Self, Self::Error> {
        let refund_status = enums::RefundStatus::try_from(item.response.sale_status.clone())?;
        let response = if utils::is_refund_failure(refund_status) {
            let payme_response = &item.response;
            let status_error_code = payme_response
                .status_error_code
                .map(|error_code| error_code.to_string());
            Err(ErrorResponse {
                code: status_error_code
                    .clone()
                    .unwrap_or_else(|| consts::NO_ERROR_CODE.to_string()),
                message: status_error_code
                    .clone()
                    .unwrap_or_else(|| consts::NO_ERROR_MESSAGE.to_string()),
                reason: status_error_code,
                status_code: item.http_code,
                attempt_status: None,
                connector_transaction_id: payme_response.payme_transaction_id.clone(),
                network_advice_code: None,
                network_decline_code: None,
                network_error_message: None,
                connector_metadata: None,
            })
        } else {
            Ok(RefundsResponseData {
                connector_refund_id: item
                    .response
                    .payme_transaction_id
                    .ok_or(errors::ConnectorError::MissingConnectorRefundID)?,
                refund_status,
            })
        };
        Ok(Self {
            response,
            ..item.data
        })
    }
}

#[derive(Debug, Serialize)]
pub struct PaymeVoidRequest {
    sale_currency: enums::Currency,
    payme_sale_id: String,
    seller_payme_id: Secret<String>,
    language: String,
}

impl TryFrom<&PaymeRouterData<&RouterData<Void, PaymentsCancelData, PaymentsResponseData>>>
    for PaymeVoidRequest
{
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        item: &PaymeRouterData<&RouterData<Void, PaymentsCancelData, PaymentsResponseData>>,
    ) -> Result<Self, Self::Error> {
        let auth_type = PaymeAuthType::try_from(&item.router_data.connector_auth_type)?;
        Ok(Self {
            payme_sale_id: item.router_data.request.connector_transaction_id.clone(),
            seller_payme_id: auth_type.seller_payme_id,
            sale_currency: item.router_data.request.get_currency()?,
            language: LANGUAGE.to_string(),
        })
    }
}

#[derive(Debug, Deserialize, Serialize)]
pub struct PaymeVoidResponse {
    sale_status: SaleStatus,
    payme_transaction_id: Option<String>,
    status_error_code: Option<u32>,
}

impl TryFrom<PaymentsCancelResponseRouterData<PaymeVoidResponse>> for PaymentsCancelRouterData {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        item: PaymentsCancelResponseRouterData<PaymeVoidResponse>,
    ) -> Result<Self, Self::Error> {
        let status = enums::AttemptStatus::from(item.response.sale_status.clone());
        let response = if utils::is_payment_failure(status) {
            let payme_response = &item.response;
            let status_error_code = payme_response
                .status_error_code
                .map(|error_code| error_code.to_string());
            Err(ErrorResponse {
                code: status_error_code
                    .clone()
                    .unwrap_or_else(|| consts::NO_ERROR_CODE.to_string()),
                message: status_error_code
                    .clone()
                    .unwrap_or_else(|| consts::NO_ERROR_MESSAGE.to_string()),
                reason: status_error_code,
                status_code: item.http_code,
                attempt_status: None,
                connector_transaction_id: payme_response.payme_transaction_id.clone(),
                network_advice_code: None,
                network_decline_code: None,
                network_error_message: None,
                connector_metadata: None,
            })
        } else {
            // Since we are not receiving payme_sale_id, we are not populating the transaction response
            Ok(PaymentsResponseData::TransactionResponse {
                resource_id: ResponseId::NoResponseId,
                redirection_data: Box::new(None),
                mandate_reference: Box::new(None),
                connector_metadata: None,
                network_txn_id: None,
                connector_response_reference_id: None,
                incremental_authorization_allowed: None,
                charges: None,
            })
        };
        Ok(Self {
            status,
            response,
            ..item.data
        })
    }
}

#[derive(Debug, Serialize, Deserialize)]
pub struct PaymeQueryTransactionResponse {
    items: Vec<TransactionQuery>,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct TransactionQuery {
    sale_status: SaleStatus,
    payme_transaction_id: String,
}

impl<F, T> TryFrom<ResponseRouterData<F, PaymeQueryTransactionResponse, T, RefundsResponseData>>
    for RouterData<F, T, RefundsResponseData>
{
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        item: ResponseRouterData<F, PaymeQueryTransactionResponse, T, RefundsResponseData>,
    ) -> Result<Self, Self::Error> {
        let pay_sale_response = item
            .response
            .items
            .first()
            .ok_or(errors::ConnectorError::ResponseHandlingFailed)?;
        let refund_status = enums::RefundStatus::try_from(pay_sale_response.sale_status.clone())?;
        let response = if utils::is_refund_failure(refund_status) {
            Err(ErrorResponse {
                code: consts::NO_ERROR_CODE.to_string(),
                message: consts::NO_ERROR_CODE.to_string(),
                reason: None,
                status_code: item.http_code,
                attempt_status: None,
                connector_transaction_id: Some(pay_sale_response.payme_transaction_id.clone()),
                network_advice_code: None,
                network_decline_code: None,
                network_error_message: None,
                connector_metadata: None,
            })
        } else {
            Ok(RefundsResponseData {
                refund_status,
                connector_refund_id: pay_sale_response.payme_transaction_id.clone(),
            })
        };
        Ok(Self {
            response,
            ..item.data
        })
    }
}

fn get_services(item: &PaymentsPreProcessingRouterData) -> Option<ThreeDs> {
    match item.auth_type {
        AuthenticationType::ThreeDs => {
            let settings = ThreeDsSettings { active: true };
            Some(ThreeDs {
                name: ThreeDsType::ThreeDs,
                settings,
            })
        }
        AuthenticationType::NoThreeDs => None,
    }
}

#[derive(Default, Debug, Serialize, Deserialize, PartialEq)]
pub struct PaymeErrorResponse {
    pub status_code: u16,
    pub status_error_details: String,
    pub status_additional_info: serde_json::Value,
    pub status_error_code: u32,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")]
pub enum NotifyType {
    SaleComplete,
    SaleAuthorized,
    Refund,
    SaleFailure,
    SaleChargeback,
    SaleChargebackRefund,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct WebhookEventDataResource {
    pub sale_status: SaleStatus,
    pub payme_signature: Secret<String>,
    pub buyer_key: Option<Secret<String>>,
    pub notify_type: NotifyType,
    pub payme_sale_id: String,
    pub payme_transaction_id: String,
    pub status_error_details: Option<String>,
    pub status_error_code: Option<u32>,
    pub price: MinorUnit,
    pub currency: enums::Currency,
}

#[derive(Debug, Deserialize)]
pub struct WebhookEventDataResourceEvent {
    pub notify_type: NotifyType,
}

#[derive(Debug, Deserialize)]
pub struct WebhookEventDataResourceSignature {
    pub payme_signature: Secret<String>,
}

/// This try_from will ensure that webhook body would be properly parsed into PSync response
impl From<WebhookEventDataResource> for PaymePaySaleResponse {
    fn from(value: WebhookEventDataResource) -> Self {
        Self {
            sale_status: value.sale_status,
            payme_sale_id: value.payme_sale_id,
            payme_transaction_id: Some(value.payme_transaction_id),
            buyer_key: value.buyer_key,
            sale_3ds: None,
            redirect_url: None,
            status_error_code: value.status_error_code,
            status_error_details: value.status_error_details,
        }
    }
}

/// This try_from will ensure that webhook body would be properly parsed into RSync response
impl From<WebhookEventDataResource> for PaymeQueryTransactionResponse {
    fn from(value: WebhookEventDataResource) -> Self {
        let item = TransactionQuery {
            sale_status: value.sale_status,
            payme_transaction_id: value.payme_transaction_id,
        };
        Self { items: vec![item] }
    }
}

impl From<NotifyType> for api_models::webhooks::IncomingWebhookEvent {
    fn from(value: NotifyType) -> Self {
        match value {
            NotifyType::SaleComplete => Self::PaymentIntentSuccess,
            NotifyType::Refund => Self::RefundSuccess,
            NotifyType::SaleFailure => Self::PaymentIntentFailure,
            NotifyType::SaleChargeback => Self::DisputeOpened,
            NotifyType::SaleChargebackRefund => Self::DisputeWon,
            NotifyType::SaleAuthorized => Self::EventNotSupported,
        }
    }
}


// Struct: AffirmPSyncResponse
// File: crates/hyperswitch_connectors/src/connectors/affirm/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct AffirmPSyncResponse


// Struct: TransactionDetailsUiConfiguration
// File: crates/api_models/src/admin.rs
// Module: api_models
// Implementations: 0

pub struct TransactionDetailsUiConfiguration


// Module Structure
// File: crates/router/src/core/payments/types.rs
// Module: router

// Public exports:
pub use hyperswitch_domain_models::router_request_types::{
    AuthenticationData, SplitRefundsRequest, StripeSplitRefund, SurchargeDetails,
};


// File: crates/diesel_models/src/hyperswitch_ai_interaction.rs
// Module: diesel_models
// Public structs: 2

use common_utils::encryption::Encryption;
use diesel::{self, Identifiable, Insertable, Queryable, Selectable};
use serde::{Deserialize, Serialize};
use time::PrimitiveDateTime;

use crate::schema::hyperswitch_ai_interaction;

#[derive(
    Clone,
    Debug,
    Deserialize,
    Identifiable,
    Queryable,
    Selectable,
    Serialize,
    router_derive::DebugAsDisplay,
)]
#[diesel(table_name = hyperswitch_ai_interaction, primary_key(id, created_at), check_for_backend(diesel::pg::Pg))]
pub struct HyperswitchAiInteraction {
    pub id: String,
    pub session_id: Option<String>,
    pub user_id: Option<String>,
    pub merchant_id: Option<String>,
    pub profile_id: Option<String>,
    pub org_id: Option<String>,
    pub role_id: Option<String>,
    pub user_query: Option<Encryption>,
    pub response: Option<Encryption>,
    pub database_query: Option<String>,
    pub interaction_status: Option<String>,
    pub created_at: PrimitiveDateTime,
}

#[derive(router_derive::Setter, Clone, Debug, Insertable, router_derive::DebugAsDisplay)]
#[diesel(table_name = hyperswitch_ai_interaction)]
pub struct HyperswitchAiInteractionNew {
    pub id: String,
    pub session_id: Option<String>,
    pub user_id: Option<String>,
    pub merchant_id: Option<String>,
    pub profile_id: Option<String>,
    pub org_id: Option<String>,
    pub role_id: Option<String>,
    pub user_query: Option<Encryption>,
    pub response: Option<Encryption>,
    pub database_query: Option<String>,
    pub interaction_status: Option<String>,
    pub created_at: PrimitiveDateTime,
}


// Implementation: impl api::RefundSync for for Nexixpay
// File: crates/hyperswitch_connectors/src/connectors/nexixpay.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::RefundSync for for Nexixpay


// File: crates/diesel_models/src/query/api_keys.rs
// Module: diesel_models
// Public functions: 6

use diesel::{associations::HasTable, BoolExpressionMethods, ExpressionMethods};

use super::generics;
use crate::{
    api_keys::{ApiKey, ApiKeyNew, ApiKeyUpdate, ApiKeyUpdateInternal, HashedApiKey},
    errors,
    schema::api_keys::dsl,
    PgPooledConn, StorageResult,
};

impl ApiKeyNew {
    pub async fn insert(self, conn: &PgPooledConn) -> StorageResult<ApiKey> {
        generics::generic_insert(conn, self).await
    }
}

impl ApiKey {
    pub async fn update_by_merchant_id_key_id(
        conn: &PgPooledConn,
        merchant_id: common_utils::id_type::MerchantId,
        key_id: common_utils::id_type::ApiKeyId,
        api_key_update: ApiKeyUpdate,
    ) -> StorageResult<Self> {
        match generics::generic_update_with_unique_predicate_get_result::<
            <Self as HasTable>::Table,
            _,
            _,
            _,
        >(
            conn,
            dsl::merchant_id
                .eq(merchant_id.to_owned())
                .and(dsl::key_id.eq(key_id.to_owned())),
            ApiKeyUpdateInternal::from(api_key_update),
        )
        .await
        {
            Err(error) => match error.current_context() {
                errors::DatabaseError::NotFound => {
                    Err(error.attach_printable("API key with the given key ID does not exist"))
                }
                errors::DatabaseError::NoFieldsToUpdate => {
                    generics::generic_find_one::<<Self as HasTable>::Table, _, _>(
                        conn,
                        dsl::merchant_id
                            .eq(merchant_id.to_owned())
                            .and(dsl::key_id.eq(key_id.to_owned())),
                    )
                    .await
                }
                _ => Err(error),
            },
            result => result,
        }
    }

    pub async fn revoke_by_merchant_id_key_id(
        conn: &PgPooledConn,
        merchant_id: &common_utils::id_type::MerchantId,
        key_id: &common_utils::id_type::ApiKeyId,
    ) -> StorageResult<bool> {
        generics::generic_delete::<<Self as HasTable>::Table, _>(
            conn,
            dsl::merchant_id
                .eq(merchant_id.to_owned())
                .and(dsl::key_id.eq(key_id.to_owned())),
        )
        .await
    }

    pub async fn find_optional_by_merchant_id_key_id(
        conn: &PgPooledConn,
        merchant_id: &common_utils::id_type::MerchantId,
        key_id: &common_utils::id_type::ApiKeyId,
    ) -> StorageResult<Option<Self>> {
        generics::generic_find_one_optional::<<Self as HasTable>::Table, _, _>(
            conn,
            dsl::merchant_id
                .eq(merchant_id.to_owned())
                .and(dsl::key_id.eq(key_id.to_owned())),
        )
        .await
    }

    pub async fn find_optional_by_hashed_api_key(
        conn: &PgPooledConn,
        hashed_api_key: HashedApiKey,
    ) -> StorageResult<Option<Self>> {
        generics::generic_find_one_optional::<<Self as HasTable>::Table, _, _>(
            conn,
            dsl::hashed_api_key.eq(hashed_api_key),
        )
        .await
    }

    pub async fn find_by_merchant_id(
        conn: &PgPooledConn,
        merchant_id: &common_utils::id_type::MerchantId,
        limit: Option<i64>,
        offset: Option<i64>,
    ) -> StorageResult<Vec<Self>> {
        generics::generic_filter::<<Self as HasTable>::Table, _, _, _>(
            conn,
            dsl::merchant_id.eq(merchant_id.to_owned()),
            limit,
            offset,
            Some(dsl::created_at.asc()),
        )
        .await
    }
}


// Function: new
// File: crates/hyperswitch_domain_models/src/router_response_types.rs
// Module: hyperswitch_domain_models

pub fn new(
        connector_customer_id: String,
        name: Option<String>,
        email: Option<String>,
        billing_address: Option<AddressDetails>,
    ) -> Self


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

impl api::Payment for for Tsys


// File: crates/router_env/src/vergen.rs
// Module: router_env
// Public functions: 2

/// Configures the [`vergen`][::vergen] crate to generate the `cargo` build instructions.
///
/// This function should be typically called within build scripts to generate `cargo` build
/// instructions for the corresponding crate.
///
/// # Panics
///
/// Panics if `vergen` fails to generate `cargo` build instructions.
#[cfg(feature = "vergen")]
#[allow(clippy::expect_used)]
pub fn generate_cargo_instructions() {
    use std::io::Write;

    use vergen::EmitBuilder;

    EmitBuilder::builder()
        .cargo_debug()
        .cargo_opt_level()
        .cargo_target_triple()
        .git_commit_timestamp()
        .git_describe(true, true, None)
        .git_sha(true)
        .rustc_semver()
        .rustc_commit_hash()
        .emit()
        .expect("Failed to generate `cargo` build instructions");

    writeln!(
        &mut std::io::stdout(),
        "cargo:rustc-env=CARGO_PROFILE={}",
        std::env::var("PROFILE").expect("Failed to obtain `cargo` profile")
    )
    .expect("Failed to set `CARGO_PROFILE` environment variable");
}

#[cfg(not(feature = "vergen"))]
pub fn generate_cargo_instructions() {}


// Implementation: impl ThemeNew
// File: crates/diesel_models/src/query/user/theme.rs
// Module: diesel_models
// Methods: 1 total (0 public)

impl ThemeNew


// Implementation: impl Cybersource
// File: crates/hyperswitch_connectors/src/connectors/cybersource.rs
// Module: hyperswitch_connectors
// Methods: 2 total (2 public)

impl Cybersource


// Implementation: impl api::PaymentSync for for Vgs
// File: crates/hyperswitch_connectors/src/connectors/vgs.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::PaymentSync for for Vgs


// Implementation: impl Webhooks
// File: crates/router/src/compatibility/stripe/app.rs
// Module: router
// Methods: 1 total (1 public)

impl Webhooks


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

pub mod transformers;

use std::sync::LazyLock;

use api_models::webhooks::IncomingWebhookEvent;
use base64::Engine;
use common_enums::{enums, CallConnectorAction, PaymentAction};
use common_utils::{
    consts::BASE64_ENGINE,
    crypto,
    errors::{CustomResult, ParsingError},
    ext_traits::{BytesExt, XmlExt},
    request::{Method, Request, RequestBuilder, RequestContent},
    types::{
        AmountConvertor, StringMajorUnit, StringMajorUnitForConnector, StringMinorUnit,
        StringMinorUnitForConnector,
    },
};
use error_stack::{report, Report, ResultExt};
use hyperswitch_domain_models::{
    api::ApplicationResponse,
    router_data::{AccessToken, ConnectorAuthType, ErrorResponse, RouterData},
    router_flow_types::{
        access_token_auth::AccessTokenAuth,
        mandate_revoke::MandateRevoke,
        payments::{Authorize, Capture, PSync, PaymentMethodToken, Session, SetupMandate, Void},
        refunds::{Execute, RSync},
        CompleteAuthorize,
    },
    router_request_types::{
        AccessTokenRequestData, CompleteAuthorizeData, MandateRevokeRequestData,
        PaymentMethodTokenizationData, PaymentsAuthorizeData, PaymentsCancelData,
        PaymentsCaptureData, PaymentsSessionData, PaymentsSyncData, RefundsData,
        SetupMandateRequestData,
    },
    router_response_types::{
        ConnectorInfo, MandateRevokeResponseData, PaymentMethodDetails, PaymentsResponseData,
        RefundsResponseData, SupportedPaymentMethods, SupportedPaymentMethodsExt,
    },
    types::{
        MandateRevokeRouterData, PaymentsAuthorizeRouterData, PaymentsCancelRouterData,
        PaymentsCaptureRouterData, PaymentsCompleteAuthorizeRouterData, PaymentsSyncRouterData,
        RefundSyncRouterData, RefundsRouterData, TokenizationRouterData,
    },
};
use hyperswitch_interfaces::{
    api::{
        self, ConnectorCommon, ConnectorCommonExt, ConnectorIntegration, ConnectorRedirectResponse,
        ConnectorSpecifications, ConnectorValidation,
    },
    configs::Connectors,
    consts::{NO_ERROR_CODE, NO_ERROR_MESSAGE},
    disputes::DisputePayload,
    errors,
    events::connector_api_logs::ConnectorEvent,
    types::{
        MandateRevokeType, PaymentsAuthorizeType, PaymentsCaptureType,
        PaymentsCompleteAuthorizeType, PaymentsSyncType, PaymentsVoidType, RefundExecuteType,
        RefundSyncType, Response, TokenizationType,
    },
    webhooks::{IncomingWebhook, IncomingWebhookFlowError, IncomingWebhookRequestDetails},
};
use masking::{ExposeInterface, Mask, PeekInterface, Secret};
use ring::hmac;
use router_env::logger;
use sha1::{Digest, Sha1};
use transformers::{self as braintree, get_status};

use crate::{
    constants::headers,
    types::ResponseRouterData,
    utils::{
        self, convert_amount, is_mandate_supported, PaymentMethodDataType,
        PaymentsAuthorizeRequestData, PaymentsCompleteAuthorizeRequestData,
    },
};

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

impl Braintree {
    pub const fn new() -> &'static Self {
        &Self {
            amount_converter: &StringMajorUnitForConnector,
            amount_converter_webhooks: &StringMinorUnitForConnector,
        }
    }
}

pub const BRAINTREE_VERSION: &str = "Braintree-Version";
pub const BRAINTREE_VERSION_VALUE: &str = "2019-01-01";

impl<Flow, Request, Response> ConnectorCommonExt<Flow, Request, Response> for Braintree
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(),
            ),
            (
                BRAINTREE_VERSION.to_string(),
                BRAINTREE_VERSION_VALUE.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 Braintree {
    fn id(&self) -> &'static str {
        "braintree"
    }

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

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

    fn get_auth_header(
        &self,
        auth_type: &ConnectorAuthType,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        let auth = braintree::BraintreeAuthType::try_from(auth_type)
            .change_context(errors::ConnectorError::FailedToObtainAuthType)?;
        let auth_key = format!("{}:{}", auth.public_key.peek(), auth.private_key.peek());
        let auth_header = format!("Basic {}", BASE64_ENGINE.encode(auth_key));
        Ok(vec![(
            headers::AUTHORIZATION.to_string(),
            auth_header.into_masked(),
        )])
    }

    fn build_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        let response: Result<braintree::ErrorResponses, Report<ParsingError>> =
            res.response.parse_struct("Braintree Error Response");

        match response {
            Ok(braintree::ErrorResponses::BraintreeApiErrorResponse(response)) => {
                event_builder.map(|i| i.set_error_response_body(&response));
                router_env::logger::info!(connector_response=?response);

                let error_object = response.api_error_response.errors;
                let error = error_object.errors.first().or(error_object
                    .transaction
                    .as_ref()
                    .and_then(|transaction_error| {
                        transaction_error.errors.first().or(transaction_error
                            .credit_card
                            .as_ref()
                            .and_then(|credit_card_error| credit_card_error.errors.first()))
                    }));
                let (code, message) = error.map_or(
                    (NO_ERROR_CODE.to_string(), NO_ERROR_MESSAGE.to_string()),
                    |error| (error.code.clone(), error.message.clone()),
                );
                Ok(ErrorResponse {
                    status_code: res.status_code,
                    code,
                    message,
                    reason: Some(response.api_error_response.message),
                    attempt_status: None,
                    connector_transaction_id: None,
                    network_advice_code: None,
                    network_decline_code: None,
                    network_error_message: None,
                    connector_metadata: None,
                })
            }
            Ok(braintree::ErrorResponses::BraintreeErrorResponse(response)) => {
                event_builder.map(|i| i.set_error_response_body(&response));
                router_env::logger::info!(connector_response=?response);

                Ok(ErrorResponse {
                    status_code: res.status_code,
                    code: NO_ERROR_CODE.to_string(),
                    message: NO_ERROR_MESSAGE.to_string(),
                    reason: Some(response.errors),
                    attempt_status: None,
                    connector_transaction_id: None,
                    network_advice_code: None,
                    network_decline_code: None,
                    network_error_message: None,
                    connector_metadata: None,
                })
            }
            Err(error_msg) => {
                event_builder.map(|event| event.set_error(serde_json::json!({"error": res.response.escape_ascii().to_string(), "status_code": res.status_code})));
                logger::error!(deserialization_error =? error_msg);
                utils::handle_json_response_deserialization_failure(res, "braintree")
            }
        }
    }
}

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

impl api::Payment for Braintree {}

impl api::PaymentAuthorize for Braintree {}
impl api::PaymentSync for Braintree {}
impl api::PaymentVoid for Braintree {}
impl api::PaymentCapture for Braintree {}
impl api::PaymentsCompleteAuthorize for Braintree {}
impl api::PaymentSession for Braintree {}
impl api::ConnectorAccessToken for Braintree {}
impl api::ConnectorMandateRevoke for Braintree {}

impl ConnectorIntegration<AccessTokenAuth, AccessTokenRequestData, AccessToken> for Braintree {
    // Not Implemented (R)
}

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

impl api::PaymentToken for Braintree {}

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

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

    fn get_url(
        &self,
        _req: &TokenizationRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        Ok(self.base_url(connectors).to_string())
    }

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

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

    fn build_request(
        &self,
        req: &TokenizationRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        Ok(Some(
            RequestBuilder::new()
                .method(Method::Post)
                .url(&TokenizationType::get_url(self, req, connectors)?)
                .attach_default_headers()
                .headers(TokenizationType::get_headers(self, req, connectors)?)
                .set_body(TokenizationType::get_request_body(self, req, connectors)?)
                .build(),
        ))
    }
    fn handle_response(
        &self,
        data: &TokenizationRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<TokenizationRouterData, errors::ConnectorError>
    where
        PaymentsResponseData: Clone,
    {
        let response: transformers::BraintreeTokenResponse = res
            .response
            .parse_struct("BraintreeTokenResponse")
            .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 api::MandateSetup for Braintree {}

#[allow(dead_code)]
impl ConnectorIntegration<SetupMandate, SetupMandateRequestData, PaymentsResponseData>
    for Braintree
{
    // Not Implemented (R)
    fn build_request(
        &self,
        _req: &RouterData<SetupMandate, SetupMandateRequestData, PaymentsResponseData>,
        _connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        Err(
            errors::ConnectorError::NotImplemented("Setup Mandate flow for Braintree".to_string())
                .into(),
        )
    }
}

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

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

    fn get_url(
        &self,
        _req: &PaymentsCaptureRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        Ok(self.base_url(connectors).to_string())
    }

    fn get_request_body(
        &self,
        req: &PaymentsCaptureRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let amount = convert_amount(
            self.amount_converter,
            req.request.minor_amount_to_capture,
            req.request.currency,
        )?;
        let connector_router_data = braintree::BraintreeRouterData::try_from((amount, req))?;
        let connector_req =
            transformers::BraintreeCaptureRequest::try_from(&connector_router_data)?;

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

    fn build_request(
        &self,
        req: &PaymentsCaptureRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        Ok(Some(
            RequestBuilder::new()
                .method(Method::Post)
                .url(&PaymentsCaptureType::get_url(self, req, connectors)?)
                .attach_default_headers()
                .headers(PaymentsCaptureType::get_headers(self, req, connectors)?)
                .set_body(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: transformers::BraintreeCaptureResponse = res
            .response
            .parse_struct("Braintree 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<PSync, PaymentsSyncData, PaymentsResponseData> for Braintree {
    fn get_headers(
        &self,
        req: &PaymentsSyncRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        self.build_headers(req, connectors)
    }

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

    fn get_url(
        &self,
        _req: &PaymentsSyncRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        Ok(self.base_url(connectors).to_string())
    }

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

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

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

    fn handle_response(
        &self,
        data: &PaymentsSyncRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<PaymentsSyncRouterData, errors::ConnectorError> {
        let response: transformers::BraintreePSyncResponse = res
            .response
            .parse_struct("Braintree PaymentSyncResponse")
            .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<Authorize, PaymentsAuthorizeData, PaymentsResponseData> for Braintree {
    fn get_headers(
        &self,
        req: &PaymentsAuthorizeRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        self.build_headers(req, connectors)
    }

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

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

    fn get_request_body(
        &self,
        req: &PaymentsAuthorizeRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let amount = convert_amount(
            self.amount_converter,
            req.request.minor_amount,
            req.request.currency,
        )?;
        let connector_router_data = braintree::BraintreeRouterData::try_from((amount, req))?;
        let connector_req: transformers::BraintreePaymentsRequest =
            transformers::BraintreePaymentsRequest::try_from(&connector_router_data)?;
        Ok(RequestContent::Json(Box::new(connector_req)))
    }

    fn handle_response(
        &self,
        data: &PaymentsAuthorizeRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<PaymentsAuthorizeRouterData, errors::ConnectorError> {
        match data.request.is_auto_capture()? {
            true => {
                let response: transformers::BraintreePaymentsResponse = res
                    .response
                    .parse_struct("Braintree PaymentsResponse")
                    .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,
                })
            }
            false => {
                let response: transformers::BraintreeAuthResponse = res
                    .response
                    .parse_struct("Braintree AuthResponse")
                    .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<MandateRevoke, MandateRevokeRequestData, MandateRevokeResponseData>
    for Braintree
{
    fn get_headers(
        &self,
        req: &MandateRevokeRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        self.build_headers(req, connectors)
    }
    fn get_url(
        &self,
        _req: &MandateRevokeRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        Ok(self.base_url(connectors).to_string())
    }
    fn build_request(
        &self,
        req: &MandateRevokeRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        Ok(Some(
            RequestBuilder::new()
                .method(Method::Post)
                .url(&MandateRevokeType::get_url(self, req, connectors)?)
                .attach_default_headers()
                .headers(MandateRevokeType::get_headers(self, req, connectors)?)
                .set_body(MandateRevokeType::get_request_body(self, req, connectors)?)
                .build(),
        ))
    }
    fn get_request_body(
        &self,
        req: &MandateRevokeRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let connector_req = transformers::BraintreeRevokeMandateRequest::try_from(req)?;
        Ok(RequestContent::Json(Box::new(connector_req)))
    }

    fn handle_response(
        &self,
        data: &MandateRevokeRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<MandateRevokeRouterData, errors::ConnectorError> {
        let response: transformers::BraintreeRevokeMandateResponse = res
            .response
            .parse_struct("BraintreeRevokeMandateResponse")
            .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 Braintree {
    fn get_headers(
        &self,
        req: &PaymentsCancelRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        self.build_headers(req, connectors)
    }

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

    fn get_url(
        &self,
        _req: &PaymentsCancelRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        Ok(self.base_url(connectors).to_string())
    }

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

    fn get_request_body(
        &self,
        req: &PaymentsCancelRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let connector_req = transformers::BraintreeCancelRequest::try_from(req)?;
        Ok(RequestContent::Json(Box::new(connector_req)))
    }

    fn handle_response(
        &self,
        data: &PaymentsCancelRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<PaymentsCancelRouterData, errors::ConnectorError> {
        let response: transformers::BraintreeCancelResponse = res
            .response
            .parse_struct("Braintree VoidResponse")
            .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 api::Refund for Braintree {}
impl api::RefundExecute for Braintree {}
impl api::RefundSync for Braintree {}

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

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

    fn get_url(
        &self,
        _req: &RefundsRouterData<Execute>,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        Ok(self.base_url(connectors).to_string())
    }

    fn get_request_body(
        &self,
        req: &RefundsRouterData<Execute>,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let amount = convert_amount(
            self.amount_converter,
            req.request.minor_refund_amount,
            req.request.currency,
        )?;
        let connector_router_data = braintree::BraintreeRouterData::try_from((amount, req))?;
        let connector_req = transformers::BraintreeRefundRequest::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(&RefundExecuteType::get_url(self, req, connectors)?)
            .attach_default_headers()
            .headers(RefundExecuteType::get_headers(self, req, connectors)?)
            .set_body(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: transformers::BraintreeRefundResponse = res
            .response
            .parse_struct("Braintree RefundResponse")
            .change_context(errors::ConnectorError::RequestEncodingFailed)?;
        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 Braintree {
    fn get_headers(
        &self,
        req: &RefundSyncRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        self.build_headers(req, connectors)
    }

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

    fn get_url(
        &self,
        _req: &RefundSyncRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        Ok(self.base_url(connectors).to_string())
    }

    fn get_request_body(
        &self,
        req: &RefundSyncRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let connector_req = transformers::BraintreeRSyncRequest::try_from(req)?;
        Ok(RequestContent::Json(Box::new(connector_req)))
    }

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

    fn handle_response(
        &self,
        data: &RefundSyncRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<RouterData<RSync, RefundsData, RefundsResponseData>, errors::ConnectorError>
    {
        let response: transformers::BraintreeRSyncResponse = res
            .response
            .parse_struct("Braintree 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)
    }
}

#[async_trait::async_trait]
impl IncomingWebhook for Braintree {
    fn get_webhook_source_verification_algorithm(
        &self,
        _request: &IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<Box<dyn crypto::VerifySignature + Send>, errors::ConnectorError> {
        Ok(Box::new(crypto::HmacSha1))
    }

    fn get_webhook_source_verification_signature(
        &self,
        request: &IncomingWebhookRequestDetails<'_>,
        connector_webhook_secrets: &api_models::webhooks::ConnectorWebhookSecrets,
    ) -> CustomResult<Vec<u8>, errors::ConnectorError> {
        let notif_item = get_webhook_object_from_body(request.body)
            .change_context(errors::ConnectorError::WebhookSourceVerificationFailed)?;

        let signature_pairs: Vec<(&str, &str)> = notif_item
            .bt_signature
            .split('&')
            .collect::<Vec<&str>>()
            .into_iter()
            .map(|pair| pair.split_once('|').unwrap_or(("", "")))
            .collect::<Vec<(_, _)>>();

        let merchant_secret = connector_webhook_secrets
            .additional_secret //public key
            .clone()
            .ok_or(errors::ConnectorError::WebhookVerificationSecretNotFound)?;

        let signature = get_matching_webhook_signature(signature_pairs, merchant_secret.expose())
            .ok_or(errors::ConnectorError::WebhookSignatureNotFound)?;
        Ok(signature.as_bytes().to_vec())
    }

    fn get_webhook_source_verification_message(
        &self,
        request: &IncomingWebhookRequestDetails<'_>,
        _merchant_id: &common_utils::id_type::MerchantId,
        _connector_webhook_secrets: &api_models::webhooks::ConnectorWebhookSecrets,
    ) -> CustomResult<Vec<u8>, errors::ConnectorError> {
        let notify = get_webhook_object_from_body(request.body)
            .change_context(errors::ConnectorError::WebhookSourceVerificationFailed)?;

        let message = notify.bt_payload.to_string();

        Ok(message.into_bytes())
    }

    async fn verify_webhook_source(
        &self,
        request: &IncomingWebhookRequestDetails<'_>,
        merchant_id: &common_utils::id_type::MerchantId,
        connector_webhook_details: Option<common_utils::pii::SecretSerdeValue>,
        _connector_account_details: crypto::Encryptable<Secret<serde_json::Value>>,
        connector_label: &str,
    ) -> CustomResult<bool, errors::ConnectorError> {
        let connector_webhook_secrets = self
            .get_webhook_source_verification_merchant_secret(
                merchant_id,
                connector_label,
                connector_webhook_details,
            )
            .await
            .change_context(errors::ConnectorError::WebhookSourceVerificationFailed)?;

        let signature = self
            .get_webhook_source_verification_signature(request, &connector_webhook_secrets)
            .change_context(errors::ConnectorError::WebhookSignatureNotFound)?;

        let message = self
            .get_webhook_source_verification_message(
                request,
                merchant_id,
                &connector_webhook_secrets,
            )
            .change_context(errors::ConnectorError::WebhookSourceVerificationFailed)?;

        let sha1_hash_key = Sha1::digest(&connector_webhook_secrets.secret);

        let signing_key = hmac::Key::new(
            hmac::HMAC_SHA1_FOR_LEGACY_USE_ONLY,
            sha1_hash_key.as_slice(),
        );
        let signed_messaged = hmac::sign(&signing_key, &message);
        let payload_sign: String = hex::encode(signed_messaged);
        Ok(payload_sign.as_bytes().eq(&signature))
    }

    fn get_webhook_object_reference_id(
        &self,
        _request: &IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<api_models::webhooks::ObjectReferenceId, errors::ConnectorError> {
        let notif = get_webhook_object_from_body(_request.body)
            .change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?;

        let response = decode_webhook_payload(notif.bt_payload.replace('\n', "").as_bytes())?;

        match response.dispute {
            Some(dispute_data) => Ok(api_models::webhooks::ObjectReferenceId::PaymentId(
                api_models::payments::PaymentIdType::ConnectorTransactionId(
                    dispute_data.transaction.id,
                ),
            )),
            None => Err(report!(errors::ConnectorError::WebhookReferenceIdNotFound)),
        }
    }

    fn get_webhook_event_type(
        &self,
        request: &IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<IncomingWebhookEvent, errors::ConnectorError> {
        let notif = get_webhook_object_from_body(request.body)
            .change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?;

        let response = decode_webhook_payload(notif.bt_payload.replace('\n', "").as_bytes())?;

        Ok(get_status(response.kind.as_str()))
    }

    fn get_webhook_resource_object(
        &self,
        request: &IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<Box<dyn masking::ErasedMaskSerialize>, errors::ConnectorError> {
        let notif = get_webhook_object_from_body(request.body)
            .change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?;

        let response = decode_webhook_payload(notif.bt_payload.replace('\n', "").as_bytes())?;

        Ok(Box::new(response))
    }

    fn get_webhook_api_response(
        &self,
        _request: &IncomingWebhookRequestDetails<'_>,
        _error_kind: Option<IncomingWebhookFlowError>,


// Struct: CryptopayErrorData
// File: crates/hyperswitch_connectors/src/connectors/cryptopay/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct CryptopayErrorData


// Function: server
// File: crates/router/src/routes/app.rs
// Module: router

pub fn server(state: AppState) -> Scope


// Implementation: impl IncomingWebhook for for Nuvei
// File: crates/hyperswitch_connectors/src/connectors/nuvei.rs
// Module: hyperswitch_connectors
// Methods: 7 total (0 public)

impl IncomingWebhook for for Nuvei


// Struct: AvsResponse
// File: crates/hyperswitch_connectors/src/connectors/fiservemea/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct AvsResponse


// Struct: FeatureMatrixListResponse
// File: crates/api_models/src/feature_matrix.rs
// Module: api_models
// Implementations: 1
// Traits: common_utils::events::ApiEventMetric

pub struct FeatureMatrixListResponse


// Struct: MandateLink
// File: crates/hyperswitch_connectors/src/connectors/gocardless/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct MandateLink


// Struct: StripePaymentRetrieveBody
// File: crates/router/src/compatibility/stripe/payment_intents/types.rs
// Module: router
// Implementations: 0

pub struct StripePaymentRetrieveBody


// Struct: RoutingEvaluateRequest
// File: crates/api_models/src/routing.rs
// Module: api_models
// Implementations: 1
// Traits: common_utils::events::ApiEventMetric

pub struct RoutingEvaluateRequest


// Function: mk_add_card_response_hs
// File: crates/router/src/core/payment_methods/transformers.rs
// Module: router

pub fn mk_add_card_response_hs(
    card: api::CardDetail,
    card_reference: String,
    req: api::PaymentMethodCreate,
    merchant_id: &id_type::MerchantId,
) -> api::PaymentMethodResponse


// Function: get_optional_stored_credential
// File: crates/hyperswitch_connectors/src/connectors/nuvei/transformers.rs
// Module: hyperswitch_connectors

pub fn get_optional_stored_credential(is_stored_credential: Option<bool>) -> Option<Self>


// Function: update_capture
// File: crates/router/src/core/payments/types.rs
// Module: router

pub fn update_capture(&mut self, updated_capture: storage::Capture)


// Struct: HelcimLineItems
// File: crates/hyperswitch_connectors/src/connectors/helcim/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct HelcimLineItems


// File: crates/router/src/core/profile_acquirer.rs
// Module: router
// Public functions: 2

use api_models::profile_acquirer;
use common_utils::types::keymanager::KeyManagerState;
use error_stack::ResultExt;

use crate::{
    core::errors::{self, utils::StorageErrorExt, RouterResponse},
    services::api,
    types::domain,
    SessionState,
};

#[cfg(all(feature = "olap", feature = "v1"))]
pub async fn create_profile_acquirer(
    state: SessionState,
    request: profile_acquirer::ProfileAcquirerCreate,
    merchant_context: domain::MerchantContext,
) -> RouterResponse<profile_acquirer::ProfileAcquirerResponse> {
    let db = state.store.as_ref();
    let profile_acquirer_id = common_utils::generate_profile_acquirer_id_of_default_length();
    let key_manager_state: KeyManagerState = (&state).into();
    let merchant_key_store = merchant_context.get_merchant_key_store();

    let mut business_profile = db
        .find_business_profile_by_profile_id(
            &key_manager_state,
            merchant_key_store,
            &request.profile_id,
        )
        .await
        .to_not_found_response(errors::ApiErrorResponse::ProfileNotFound {
            id: request.profile_id.get_string_repr().to_owned(),
        })?;

    let incoming_acquirer_config = common_types::domain::AcquirerConfig {
        acquirer_assigned_merchant_id: request.acquirer_assigned_merchant_id.clone(),
        merchant_name: request.merchant_name.clone(),
        network: request.network.clone(),
        acquirer_bin: request.acquirer_bin.clone(),
        acquirer_ica: request.acquirer_ica.clone(),
        acquirer_fraud_rate: request.acquirer_fraud_rate,
    };

    // Check for duplicates before proceeding

    business_profile
        .acquirer_config_map
        .as_ref()
        .map_or(Ok(()), |configs_wrapper| {
            match configs_wrapper.0.values().any(|existing_config| existing_config == &incoming_acquirer_config) {
                true => Err(error_stack::report!(
                    errors::ApiErrorResponse::GenericDuplicateError {
                        message: format!(
                            "Duplicate acquirer configuration found for profile_id: {}. Conflicting configuration: {:?}",
                            request.profile_id.get_string_repr(),
                            incoming_acquirer_config
                        ),
                    }
                )),
                false => Ok(()),
            }
        })?;

    // Get a mutable reference to the HashMap inside AcquirerConfigMap,
    // initializing if it's None or the inner HashMap is not present.
    let configs_map = &mut business_profile
        .acquirer_config_map
        .get_or_insert_with(|| {
            common_types::domain::AcquirerConfigMap(std::collections::HashMap::new())
        })
        .0;

    configs_map.insert(
        profile_acquirer_id.clone(),
        incoming_acquirer_config.clone(),
    );

    let profile_update = domain::ProfileUpdate::AcquirerConfigMapUpdate {
        acquirer_config_map: business_profile.acquirer_config_map.clone(),
    };
    let updated_business_profile = db
        .update_profile_by_profile_id(
            &key_manager_state,
            merchant_key_store,
            business_profile,
            profile_update,
        )
        .await
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("Failed to update business profile with new acquirer config")?;

    let updated_acquire_details = updated_business_profile
        .acquirer_config_map
        .as_ref()
        .and_then(|acquirer_configs_wrapper| acquirer_configs_wrapper.0.get(&profile_acquirer_id))
        .ok_or(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("Failed to get updated acquirer config")?;

    let response = profile_acquirer::ProfileAcquirerResponse::from((
        profile_acquirer_id,
        &request.profile_id,
        updated_acquire_details,
    ));

    Ok(api::ApplicationResponse::Json(response))
}

#[cfg(all(feature = "olap", feature = "v1"))]
pub async fn update_profile_acquirer_config(
    state: SessionState,
    profile_id: common_utils::id_type::ProfileId,
    profile_acquirer_id: common_utils::id_type::ProfileAcquirerId,
    request: profile_acquirer::ProfileAcquirerUpdate,
    merchant_context: domain::MerchantContext,
) -> RouterResponse<profile_acquirer::ProfileAcquirerResponse> {
    let db = state.store.as_ref();
    let key_manager_state = (&state).into();
    let merchant_key_store = merchant_context.get_merchant_key_store();

    let mut business_profile = db
        .find_business_profile_by_profile_id(&key_manager_state, merchant_key_store, &profile_id)
        .await
        .to_not_found_response(errors::ApiErrorResponse::ProfileNotFound {
            id: profile_id.get_string_repr().to_owned(),
        })?;

    let acquirer_config_map = business_profile
        .acquirer_config_map
        .as_mut()
        .ok_or(errors::ApiErrorResponse::ProfileAcquirerNotFound {
            profile_id: profile_id.get_string_repr().to_owned(),
            profile_acquirer_id: profile_acquirer_id.get_string_repr().to_owned(),
        })
        .attach_printable("no acquirer config found in business profile")?;

    let mut potential_updated_config = acquirer_config_map
        .0
        .get(&profile_acquirer_id)
        .ok_or_else(|| errors::ApiErrorResponse::ProfileAcquirerNotFound {
            profile_id: profile_id.get_string_repr().to_owned(),
            profile_acquirer_id: profile_acquirer_id.get_string_repr().to_owned(),
        })?
        .clone();

    // updating value in existing acquirer config
    request
        .acquirer_assigned_merchant_id
        .map(|val| potential_updated_config.acquirer_assigned_merchant_id = val);
    request
        .merchant_name
        .map(|val| potential_updated_config.merchant_name = val);
    request
        .network
        .map(|val| potential_updated_config.network = val);
    request
        .acquirer_bin
        .map(|val| potential_updated_config.acquirer_bin = val);
    request
        .acquirer_ica
        .map(|val| potential_updated_config.acquirer_ica = Some(val.clone()));
    request
        .acquirer_fraud_rate
        .map(|val| potential_updated_config.acquirer_fraud_rate = val);

    // checking for duplicates in the acquirerConfigMap
    match acquirer_config_map
        .0
        .iter()
        .find(|(_existing_id, existing_config_val_ref)| {
        **existing_config_val_ref == potential_updated_config
        }) {
        Some((conflicting_id_of_found_item, _)) => {
            Err(error_stack::report!(errors::ApiErrorResponse::GenericDuplicateError {
            message: format!(
                "Duplicate acquirer configuration. This configuration already exists for profile_acquirer_id '{}' under profile_id '{}'.",
                conflicting_id_of_found_item.get_string_repr(),
                profile_id.get_string_repr()
            ),
        }))
    }
        None => Ok(()),
    }?;

    acquirer_config_map
        .0
        .insert(profile_acquirer_id.clone(), potential_updated_config);

    let updated_map_for_db_update = business_profile.acquirer_config_map.clone();

    let profile_update = domain::ProfileUpdate::AcquirerConfigMapUpdate {
        acquirer_config_map: updated_map_for_db_update,
    };

    let updated_business_profile = db
        .update_profile_by_profile_id(
            &key_manager_state,
            merchant_key_store,
            business_profile,
            profile_update,
        )
        .await
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("Failed to update business profile with updated acquirer config")?;

    let final_acquirer_details = updated_business_profile
        .acquirer_config_map
        .as_ref()
        .and_then(|configs_wrapper| configs_wrapper.0.get(&profile_acquirer_id))
        .ok_or(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("Failed to get updated acquirer config after DB update")?;

    let response = profile_acquirer::ProfileAcquirerResponse::from((
        profile_acquirer_id,
        &profile_id,
        final_acquirer_details,
    ));

    Ok(api::ApplicationResponse::Json(response))
}


// Struct: PlaidPaymentInitiation
// File: crates/hyperswitch_connectors/src/connectors/plaid/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct PlaidPaymentInitiation


// Trait: AuthenticateAndFetch
// File: crates/router/src/services/authentication.rs
// Module: router

pub trait AuthenticateAndFetch<T, A>


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

pub struct CeleroSearchRequest


// Function: contains_token
// File: crates/router/src/core/proxy/utils.rs
// Module: router

pub fn contains_token(s: &str) -> bool


// File: crates/analytics/src/auth_events/accumulator.rs
// Module: analytics
// Public functions: 1
// Public structs: 3

use api_models::analytics::auth_events::AuthEventMetricsBucketValue;

use super::metrics::AuthEventMetricRow;

#[derive(Debug, Default)]
pub struct AuthEventMetricsAccumulator {
    pub authentication_count: CountAccumulator,
    pub authentication_attempt_count: CountAccumulator,
    pub authentication_error_message: AuthenticationErrorMessageAccumulator,
    pub authentication_success_count: CountAccumulator,
    pub challenge_flow_count: CountAccumulator,
    pub challenge_attempt_count: CountAccumulator,
    pub challenge_success_count: CountAccumulator,
    pub frictionless_flow_count: CountAccumulator,
    pub frictionless_success_count: CountAccumulator,
    pub authentication_funnel: CountAccumulator,
    pub authentication_exemption_approved_count: CountAccumulator,
    pub authentication_exemption_requested_count: CountAccumulator,
}

#[derive(Debug, Default)]
#[repr(transparent)]
pub struct CountAccumulator {
    pub count: Option<i64>,
}

#[derive(Debug, Default)]
pub struct AuthenticationErrorMessageAccumulator {
    pub count: Option<i64>,
}

pub trait AuthEventMetricAccumulator {
    type MetricOutput;

    fn add_metrics_bucket(&mut self, metrics: &AuthEventMetricRow);

    fn collect(self) -> Self::MetricOutput;
}

impl AuthEventMetricAccumulator for CountAccumulator {
    type MetricOutput = Option<u64>;
    #[inline]
    fn add_metrics_bucket(&mut self, metrics: &AuthEventMetricRow) {
        self.count = match (self.count, metrics.count) {
            (None, None) => None,
            (None, i @ Some(_)) | (i @ Some(_), None) => i,
            (Some(a), Some(b)) => Some(a + b),
        }
    }
    #[inline]
    fn collect(self) -> Self::MetricOutput {
        self.count.and_then(|i| u64::try_from(i).ok())
    }
}

impl AuthEventMetricAccumulator for AuthenticationErrorMessageAccumulator {
    type MetricOutput = Option<u64>;
    #[inline]
    fn add_metrics_bucket(&mut self, metrics: &AuthEventMetricRow) {
        self.count = match (self.count, metrics.count) {
            (None, None) => None,
            (None, i @ Some(_)) | (i @ Some(_), None) => i,
            (Some(a), Some(b)) => Some(a + b),
        }
    }
    #[inline]
    fn collect(self) -> Self::MetricOutput {
        self.count.and_then(|i| u64::try_from(i).ok())
    }
}

impl AuthEventMetricsAccumulator {
    pub fn collect(self) -> AuthEventMetricsBucketValue {
        AuthEventMetricsBucketValue {
            authentication_count: self.authentication_count.collect(),
            authentication_attempt_count: self.authentication_attempt_count.collect(),
            authentication_success_count: self.authentication_success_count.collect(),
            challenge_flow_count: self.challenge_flow_count.collect(),
            challenge_attempt_count: self.challenge_attempt_count.collect(),
            challenge_success_count: self.challenge_success_count.collect(),
            frictionless_flow_count: self.frictionless_flow_count.collect(),
            frictionless_success_count: self.frictionless_success_count.collect(),
            error_message_count: self.authentication_error_message.collect(),
            authentication_funnel: self.authentication_funnel.collect(),
            authentication_exemption_approved_count: self
                .authentication_exemption_approved_count
                .collect(),
            authentication_exemption_requested_count: self
                .authentication_exemption_requested_count
                .collect(),
        }
    }
}


// File: crates/hyperswitch_connectors/src/connectors/tsys.rs
// Module: hyperswitch_connectors
// 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::{
    router_data::{AccessToken, ErrorResponse, RouterData},
    router_flow_types::{
        access_token_auth::AccessTokenAuth,
        payments::{Authorize, Capture, PSync, PaymentMethodToken, Session, SetupMandate, Void},
        refunds::{Execute, RSync},
    },
    router_request_types::{
        AccessTokenRequestData, PaymentMethodTokenizationData, PaymentsAuthorizeData,
        PaymentsCancelData, PaymentsCaptureData, PaymentsSessionData, PaymentsSyncData,
        RefundsData, SetupMandateRequestData,
    },
    router_response_types::{
        ConnectorInfo, PaymentMethodDetails, PaymentsResponseData, RefundsResponseData,
        SupportedPaymentMethods, SupportedPaymentMethodsExt,
    },
    types::{
        PaymentsAuthorizeRouterData, PaymentsCancelRouterData, PaymentsCaptureRouterData,
        PaymentsSyncRouterData, RefundSyncRouterData, RefundsRouterData,
    },
};
use hyperswitch_interfaces::{
    api::{
        self, ConnectorCommon, ConnectorCommonExt, ConnectorIntegration, ConnectorSpecifications,
        ConnectorValidation,
    },
    configs::Connectors,
    errors,
    events::connector_api_logs::ConnectorEvent,
    types::{
        PaymentsAuthorizeType, PaymentsCaptureType, PaymentsSyncType, PaymentsVoidType,
        RefundExecuteType, RefundSyncType, Response,
    },
    webhooks,
};
use transformers as tsys;

use crate::{constants::headers, types::ResponseRouterData, utils};
#[derive(Clone)]
pub struct Tsys {
    amount_converter: &'static (dyn AmountConvertor<Output = StringMinorUnit> + Sync),
}

impl Tsys {
    pub fn new() -> &'static Self {
        &Self {
            amount_converter: &StringMinorUnitForConnector,
        }
    }
}
impl api::Payment for Tsys {}
impl api::PaymentSession for Tsys {}
impl api::ConnectorAccessToken for Tsys {}
impl api::MandateSetup for Tsys {}
impl api::PaymentAuthorize for Tsys {}
impl api::PaymentSync for Tsys {}
impl api::PaymentCapture for Tsys {}
impl api::PaymentVoid for Tsys {}
impl api::Refund for Tsys {}
impl api::RefundExecute for Tsys {}
impl api::RefundSync for Tsys {}
impl api::PaymentToken for Tsys {}

impl ConnectorIntegration<PaymentMethodToken, PaymentMethodTokenizationData, PaymentsResponseData>
    for Tsys
{
}

impl<Flow, Request, Response> ConnectorCommonExt<Flow, Request, Response> for Tsys
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 header = vec![(
            headers::CONTENT_TYPE.to_string(),
            Self::get_content_type(self).to_string().into(),
        )];
        Ok(header)
    }
}

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

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

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

impl ConnectorValidation for Tsys {}

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

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

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

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

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

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

    fn get_request_body(
        &self,
        req: &PaymentsAuthorizeRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let amount = utils::convert_amount(
            self.amount_converter,
            req.request.minor_amount,
            req.request.currency,
        )?;
        let connector_router_data = tsys::TsysRouterData::from((amount, req));
        let connector_req: transformers::TsysPaymentsRequest =
            tsys::TsysPaymentsRequest::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(&PaymentsAuthorizeType::get_url(self, req, connectors)?)
                .attach_default_headers()
                .headers(PaymentsAuthorizeType::get_headers(self, req, connectors)?)
                .set_body(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: tsys::TsysPaymentsResponse = res
            .response
            .parse_struct("Tsys 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 Tsys {
    fn get_headers(
        &self,
        req: &PaymentsSyncRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        self.build_headers(req, connectors)
    }

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

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

    fn get_request_body(
        &self,
        req: &PaymentsSyncRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let connector_req = tsys::TsysSyncRequest::try_from(req)?;
        Ok(RequestContent::Json(Box::new(connector_req)))
    }

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

    fn handle_response(
        &self,
        data: &PaymentsSyncRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<PaymentsSyncRouterData, errors::ConnectorError> {
        let response: tsys::TsysSyncResponse = res
            .response
            .parse_struct("tsys 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 Tsys {
    fn get_headers(
        &self,
        req: &PaymentsCaptureRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        self.build_headers(req, connectors)
    }

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

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

    fn get_request_body(
        &self,
        req: &PaymentsCaptureRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let amount = utils::convert_amount(
            self.amount_converter,
            req.request.minor_amount_to_capture,
            req.request.currency,
        )?;
        let connector_router_data = tsys::TsysRouterData::from((amount, req));
        let connector_req = tsys::TsysPaymentsCaptureRequest::try_from(&connector_router_data)?;
        Ok(RequestContent::Json(Box::new(connector_req)))
    }

    fn build_request(
        &self,
        req: &PaymentsCaptureRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        Ok(Some(
            RequestBuilder::new()
                .method(Method::Post)
                .url(&PaymentsCaptureType::get_url(self, req, connectors)?)
                .attach_default_headers()
                .headers(PaymentsCaptureType::get_headers(self, req, connectors)?)
                .set_body(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: tsys::TsysPaymentsResponse = res
            .response
            .parse_struct("Tsys 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 Tsys {
    fn get_headers(
        &self,
        req: &PaymentsCancelRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        self.build_headers(req, connectors)
    }

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

    fn get_url(
        &self,
        _req: &PaymentsCancelRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        Ok(format!(
            "{}servlets/transnox_api_server",
            self.base_url(connectors),
        ))
    }
    fn get_request_body(
        &self,
        req: &PaymentsCancelRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let connector_req = tsys::TsysPaymentsCancelRequest::try_from(req)?;
        Ok(RequestContent::Json(Box::new(connector_req)))
    }

    fn build_request(
        &self,
        req: &PaymentsCancelRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        let request = RequestBuilder::new()
            .method(Method::Post)
            .url(&PaymentsVoidType::get_url(self, req, connectors)?)
            .headers(PaymentsVoidType::get_headers(self, req, connectors)?)
            .set_body(PaymentsVoidType::get_request_body(self, req, connectors)?)
            .build();

        Ok(Some(request))
    }

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

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

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

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

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

    fn get_url(
        &self,
        _req: &RefundsRouterData<Execute>,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        Ok(format!(
            "{}servlets/transnox_api_server",
            self.base_url(connectors)
        ))
    }

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

        let connector_req = tsys::TsysRefundRequest::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(&RefundExecuteType::get_url(self, req, connectors)?)
            .attach_default_headers()
            .headers(RefundExecuteType::get_headers(self, req, connectors)?)
            .set_body(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: tsys::RefundResponse = res
            .response
            .parse_struct("tsys 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 Tsys {
    fn get_headers(
        &self,
        req: &RefundSyncRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        self.build_headers(req, connectors)
    }

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

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

    fn get_request_body(
        &self,
        req: &RefundSyncRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let connector_req = tsys::TsysSyncRequest::try_from(req)?;
        Ok(RequestContent::Json(Box::new(connector_req)))
    }

    fn build_request(
        &self,
        req: &RefundSyncRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        Ok(Some(
            RequestBuilder::new()
                .method(Method::Post)
                .url(&RefundSyncType::get_url(self, req, connectors)?)
                .attach_default_headers()
                .headers(RefundSyncType::get_headers(self, req, connectors)?)
                .set_body(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: tsys::TsysSyncResponse = res
            .response
            .parse_struct("tsys 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 Tsys {
    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 TSYS_SUPPORTED_PAYMENT_METHODS: LazyLock<SupportedPaymentMethods> = LazyLock::new(|| {
    let supported_capture_methods = vec![
        enums::CaptureMethod::Automatic,
        enums::CaptureMethod::Manual,
        enums::CaptureMethod::SequentialAutomatic,
    ];

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

    let mut tsys_supported_payment_methods = SupportedPaymentMethods::new();

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

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

    tsys_supported_payment_methods
});

static TSYS_CONNECTOR_INFO: ConnectorInfo = ConnectorInfo {
    display_name: "Tsys",
    description: "TSYS, a Global Payments company, is the payment stack for the future, powered by unmatched expertise.",
    connector_type: enums::HyperswitchConnectorCategory::BankAcquirer,
    integration_status: enums::ConnectorIntegrationStatus::Beta,
};

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

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

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

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


// Struct: VaultStruct
// File: crates/hyperswitch_connectors/src/connectors/paypal/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct VaultStruct


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

impl Responder


// Implementation: impl api::RefundExecute for for Bankofamerica
// File: crates/hyperswitch_connectors/src/connectors/bankofamerica.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::RefundExecute for for Bankofamerica


// Struct: PayeezyCaptureOrVoidRequest
// File: crates/hyperswitch_connectors/src/connectors/payeezy/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct PayeezyCaptureOrVoidRequest


// Function: payments_cancel
// File: crates/router/src/routes/payments.rs
// Module: router

pub fn payments_cancel(
    state: web::Data<app::AppState>,
    req: actix_web::HttpRequest,
    json_payload: web::Json<payment_types::PaymentsCancelRequest>,
    path: web::Path<common_utils::id_type::PaymentId>,
) -> impl Responder


// Implementation: impl api::PaymentCapture for for Authipay
// File: crates/hyperswitch_connectors/src/connectors/authipay.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::PaymentCapture for for Authipay


// Struct: KlarnaRouterData
// File: crates/hyperswitch_connectors/src/connectors/klarna/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct KlarnaRouterData<T>


// Struct: FiuuCardData
// File: crates/hyperswitch_connectors/src/connectors/fiuu/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct FiuuCardData


// Struct: FiservPaymentsRequest
// File: crates/hyperswitch_connectors/src/connectors/fiserv/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct FiservPaymentsRequest