            RequestBuilder::new()
                .method(Method::Get)
                .url(&types::RefundSyncType::get_url(self, req, connectors)?)
                .attach_default_headers()
                .headers(types::RefundSyncType::get_headers(self, req, connectors)?)
                .set_body(types::RefundSyncType::get_request_body(
                    self, req, connectors,
                )?)
                .build(),
        ))
    }

    fn handle_response(
        &self,
        data: &RefundSyncRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<RefundSyncRouterData, errors::ConnectorError> {
        let response: barclaycard::BarclaycardRsyncResponse = res
            .response
            .parse_struct("barclaycard 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)
    }
}

impl ConnectorIntegration<CompleteAuthorize, CompleteAuthorizeData, PaymentsResponseData>
    for Barclaycard
{
    fn get_headers(
        &self,
        req: &PaymentsCompleteAuthorizeRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, 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: &PaymentsCompleteAuthorizeRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        Ok(format!(
            "{}pts/v2/payments/",
            ConnectorCommon::base_url(self, connectors)
        ))
    }
    fn get_request_body(
        &self,
        req: &PaymentsCompleteAuthorizeRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let amount_in_minor_unit = MinorUnit::new(req.request.amount);
        let amount = convert_amount(
            self.amount_converter,
            amount_in_minor_unit,
            req.request.currency,
        )?;
        let connector_router_data = barclaycard::BarclaycardRouterData::try_from((amount, req))?;

        let connector_req =
            barclaycard::BarclaycardPaymentsRequest::try_from(&connector_router_data)?;
        Ok(RequestContent::Json(Box::new(connector_req)))
    }
    fn build_request(
        &self,
        req: &PaymentsCompleteAuthorizeRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        Ok(Some(
            RequestBuilder::new()
                .method(Method::Post)
                .url(&types::PaymentsCompleteAuthorizeType::get_url(
                    self, req, connectors,
                )?)
                .attach_default_headers()
                .headers(types::PaymentsCompleteAuthorizeType::get_headers(
                    self, req, connectors,
                )?)
                .set_body(types::PaymentsCompleteAuthorizeType::get_request_body(
                    self, req, connectors,
                )?)
                .build(),
        ))
    }

    fn handle_response(
        &self,
        data: &PaymentsCompleteAuthorizeRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<PaymentsCompleteAuthorizeRouterData, errors::ConnectorError> {
        let response: barclaycard::BarclaycardPaymentsResponse = res
            .response
            .parse_struct("Barclaycard PaymentResponse")
            .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)
    }

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

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

        let attempt_status = match response.reason {
            Some(reason) => match reason {
                transformers::Reason::SystemError => Some(enums::AttemptStatus::Failure),
                transformers::Reason::ServerTimeout | transformers::Reason::ServiceTimeout => None,
            },
            None => None,
        };
        Ok(ErrorResponse {
            status_code: res.status_code,
            reason: response.status.clone(),
            code: response
                .status
                .unwrap_or(hyperswitch_interfaces::consts::NO_ERROR_CODE.to_string()),
            message: response
                .message
                .unwrap_or(hyperswitch_interfaces::consts::NO_ERROR_MESSAGE.to_string()),
            attempt_status,
            connector_transaction_id: None,
            network_advice_code: None,
            network_decline_code: None,
            network_error_message: None,
            connector_metadata: None,
        })
    }
}

#[async_trait::async_trait]
impl webhooks::IncomingWebhook for Barclaycard {
    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 BARCLAYCARD_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::JCB,
            common_enums::CardNetwork::Discover,
            common_enums::CardNetwork::Maestro,
            common_enums::CardNetwork::Interac,
            common_enums::CardNetwork::DinersClub,
            common_enums::CardNetwork::CartesBancaires,
            common_enums::CardNetwork::UnionPay,
        ];

        let mut barclaycard_supported_payment_methods = SupportedPaymentMethods::new();

        barclaycard_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::Supported,
                            no_three_ds: common_enums::FeatureStatus::Supported,
                            supported_card_networks: supported_card_network.clone(),
                        }
                    }),
                ),
            },
        );

        barclaycard_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::Supported,
                            no_three_ds: common_enums::FeatureStatus::Supported,
                            supported_card_networks: supported_card_network.clone(),
                        }
                    }),
                ),
            },
        );

        barclaycard_supported_payment_methods.add(
            enums::PaymentMethod::Wallet,
            enums::PaymentMethodType::GooglePay,
            PaymentMethodDetails {
                mandates: enums::FeatureStatus::NotSupported,
                refunds: enums::FeatureStatus::Supported,
                supported_capture_methods,
                specific_features: None,
            },
        );

        barclaycard_supported_payment_methods
    });

static BARCLAYCARD_CONNECTOR_INFO: ConnectorInfo = ConnectorInfo {
    display_name: "BarclayCard SmartPay Fuse",
    description: "Barclaycard, part of Barclays Bank UK PLC, is a leading global payment business that helps consumers, retailers and businesses to make and take payments flexibly, and to access short-term credit and point of sale finance.",
    connector_type: enums::HyperswitchConnectorCategory::BankAcquirer,
    integration_status: enums::ConnectorIntegrationStatus::Sandbox,
};

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

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

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

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


pub fn server(state: AppState) -> Scope {
        let mut route = web::scope("/customers").app_data(web::Data::new(state));

        #[cfg(feature = "olap")]
        {
            route = route
                .service(
                    web::resource("/{customer_id}/mandates")
                        .route(web::get().to(customers::get_customer_mandates)),
                )
                .service(web::resource("/list").route(web::get().to(customers::customers_list)))
        }

        #[cfg(feature = "oltp")]
        {
            route = route
                .service(web::resource("").route(web::post().to(customers::customers_create)))
                .service(
                    web::resource("/payment_methods").route(
                        web::get().to(payment_methods::list_customer_payment_method_api_client),
                    ),
                )
                .service(
                    web::resource("/{customer_id}/payment_methods")
                        .route(web::get().to(payment_methods::list_customer_payment_method_api)),
                )
                .service(
                    web::resource("/{customer_id}/payment_methods/{payment_method_id}/default")
                        .route(web::post().to(payment_methods::default_payment_method_set_api)),
                )
                .service(
                    web::resource("/{customer_id}")
                        .route(web::get().to(customers::customers_retrieve))
                        .route(web::post().to(customers::customers_update))
                        .route(web::delete().to(customers::customers_delete)),
                )
        }

        route
    }


pub async fn perform_surcharge_decision_management_for_session_flow(
    state: &SessionState,
    algorithm_ref: routing::RoutingAlgorithmRef,
    payment_attempt: &storage::PaymentAttempt,
    payment_intent: &storage::PaymentIntent,
    billing_address: Option<hyperswitch_domain_models::address::Address>,
    payment_method_type_list: &Vec<common_enums::PaymentMethodType>,
) -> ConditionalConfigResult<types::SurchargeMetadata> {
    let mut surcharge_metadata = types::SurchargeMetadata::new(payment_attempt.attempt_id.clone());
    let surcharge_source = match (
        payment_attempt.get_surcharge_details(),
        algorithm_ref.surcharge_config_algo_id,
    ) {
        (Some(request_surcharge_details), _) => {
            SurchargeSource::Predetermined(request_surcharge_details)
        }
        (None, Some(algorithm_id)) => {
            let cached_algo = ensure_algorithm_cached(
                &*state.store,
                &payment_attempt.merchant_id,
                algorithm_id.as_str(),
            )
            .await?;

            SurchargeSource::Generate(cached_algo)
        }
        (None, None) => return Ok(surcharge_metadata),
    };
    let mut backend_input =
        make_dsl_input_for_surcharge(payment_attempt, payment_intent, billing_address)
            .change_context(ConfigError::InputConstructionError)?;
    for payment_method_type in payment_method_type_list {
        backend_input.payment_method.payment_method_type = Some(*payment_method_type);
        // in case of session flow, payment_method will always be wallet
        backend_input.payment_method.payment_method = Some(payment_method_type.to_owned().into());
        surcharge_source.generate_surcharge_details_and_populate_surcharge_metadata(
            &backend_input,
            payment_attempt,
            (
                &mut surcharge_metadata,
                types::SurchargeKey::PaymentMethodData(
                    payment_method_type.to_owned().into(),
                    *payment_method_type,
                    None,
                ),
            ),
        )?;
    }
    Ok(surcharge_metadata)
}


pub async fn payouts_create() {}


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

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

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

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

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

        match response {
            Ok(response_data) => {
                event_builder.map(|i| i.set_error_response_body(&response_data));
                router_env::logger::info!(connector_response=?response_data);
                let status_code = match res.status_code {
                    500..=511 => 200,
                    _ => res.status_code,
                };
                Ok(ErrorResponse {
                    status_code,
                    code: response_data.status_error_code.to_string(),
                    message: response_data.status_error_details.clone(),
                    reason: Some(format!(
                        "{}, additional info: {}",
                        response_data.status_error_details, response_data.status_additional_info
                    )),
                    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})));
                router_env::logger::error!(deserialization_error =? error_msg);
                utils::handle_json_response_deserialization_failure(res, "payme")
            }
        }
    }
}


impl UploadFile for Stripe {}


impl SurchargeCalculationOverride {
    pub fn as_bool(self) -> bool {
        match self {
            Self::Skip => false,
            Self::Calculate => true,
        }
    }
}


impl api::MandateSetup for Noon {}


pub struct PlaidLinkTokenResponse {
    link_token: String,
}


pub struct TokenReference {
    pub field: String,
}


pub struct SurchargePercentage {
    percentage: f32,
}


impl<'a> KafkaPaymentAttempt<'a> {
    pub fn from_storage(attempt: &'a PaymentAttempt) -> Self {
        let card_payment_method_data = attempt
            .get_payment_method_data()
            .and_then(|data| data.get_additional_card_info());
        Self {
            payment_id: &attempt.payment_id,
            merchant_id: &attempt.merchant_id,
            attempt_id: &attempt.attempt_id,
            status: attempt.status,
            amount: attempt.net_amount.get_order_amount(),
            currency: attempt.currency,
            save_to_locker: attempt.save_to_locker,
            connector: attempt.connector.as_ref(),
            error_message: attempt.error_message.as_ref(),
            offer_amount: attempt.offer_amount,
            surcharge_amount: attempt.net_amount.get_surcharge_amount(),
            tax_amount: attempt.net_amount.get_tax_on_surcharge(),
            payment_method_id: attempt.payment_method_id.as_ref(),
            payment_method: attempt.payment_method,
            connector_transaction_id: attempt.connector_transaction_id.as_ref(),
            capture_method: attempt.capture_method,
            capture_on: attempt.capture_on.map(|i| i.assume_utc()),
            confirm: attempt.confirm,
            authentication_type: attempt.authentication_type,
            created_at: attempt.created_at.assume_utc(),
            modified_at: attempt.modified_at.assume_utc(),
            last_synced: attempt.last_synced.map(|i| i.assume_utc()),
            cancellation_reason: attempt.cancellation_reason.as_ref(),
            amount_to_capture: attempt.amount_to_capture,
            mandate_id: attempt.mandate_id.as_ref(),
            browser_info: attempt.browser_info.as_ref().map(|v| v.to_string()),
            error_code: attempt.error_code.as_ref(),
            connector_metadata: attempt.connector_metadata.as_ref().map(|v| v.to_string()),
            payment_experience: attempt.payment_experience.as_ref(),
            payment_method_type: attempt.payment_method_type.as_ref(),
            payment_method_data: attempt.payment_method_data.as_ref().map(|v| v.to_string()),
            error_reason: attempt.error_reason.as_ref(),
            multiple_capture_count: attempt.multiple_capture_count,
            amount_capturable: attempt.amount_capturable,
            merchant_connector_id: attempt.merchant_connector_id.as_ref(),
            net_amount: attempt.net_amount.get_total_amount(),
            unified_code: attempt.unified_code.as_ref(),
            unified_message: attempt.unified_message.as_ref(),
            mandate_data: attempt.mandate_data.as_ref(),
            client_source: attempt.client_source.as_ref(),
            client_version: attempt.client_version.as_ref(),
            profile_id: &attempt.profile_id,
            organization_id: &attempt.organization_id,
            card_network: attempt
                .payment_method_data
                .as_ref()
                .and_then(|data| data.as_object())
                .and_then(|pm| pm.get("card"))
                .and_then(|data| data.as_object())
                .and_then(|card| card.get("card_network"))
                .and_then(|network| network.as_str())
                .map(|network| network.to_string()),
            card_discovery: attempt
                .card_discovery
                .map(|discovery| discovery.to_string()),
            routing_approach: attempt.routing_approach.clone(),
            debit_routing_savings: attempt.debit_routing_savings,
            signature_network: card_payment_method_data
                .as_ref()
                .and_then(|data| data.signature_network.clone()),
            is_issuer_regulated: card_payment_method_data.and_then(|data| data.is_regulated),
        }
    }
}


pub struct Payer {
    pub name: Secret<String>,
    pub document_type: enums::DocumentKind,
    pub document_number: Option<Secret<String>>,
    pub address: Secret<String>,
    pub neighborhood: Secret<String>,
    pub city: String,
    pub state: Secret<String>,
    pub zipcode: Secret<String>,
}


pub struct PaysafeMeta {
    pub payment_handle_token: Secret<String>,
}


pub async fn get_aggregates_for_payments(
    state: SessionState,
    merchant_context: domain::MerchantContext,
    profile_id_list: Option<Vec<id_type::ProfileId>>,
    time_range: common_utils::types::TimeRange,
) -> RouterResponse<api::PaymentsAggregateResponse> {
    let db = state.store.as_ref();
    let intent_status_with_count = db
        .get_intent_status_with_count(
            merchant_context.get_merchant_account().get_id(),
            profile_id_list,
            &time_range,
        )
        .await
        .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?;

    let mut status_map: HashMap<enums::IntentStatus, i64> =
        intent_status_with_count.into_iter().collect();
    for status in enums::IntentStatus::iter() {
        status_map.entry(status).or_default();
    }

    Ok(services::ApplicationResponse::Json(
        api::PaymentsAggregateResponse {
            status_with_count: status_map,
        },
    ))
}


pub struct ProfileCreate {
    /// The name of profile
    #[schema(max_length = 64)]
    pub profile_name: Option<String>,

    /// The URL to redirect after the completion of the operation
    #[schema(value_type = Option<String>, max_length = 255, example = "https://www.example.com/success")]
    pub return_url: Option<url::Url>,

    /// A boolean value to indicate if payment response hash needs to be enabled
    #[schema(default = true, example = true)]
    pub enable_payment_response_hash: Option<bool>,

    /// Refers to the hash key used for calculating the signature for webhooks and redirect response. If the value is not provided, a value is automatically generated.
    pub payment_response_hash_key: Option<String>,

    /// A boolean value to indicate if redirect to merchant with http post needs to be enabled
    #[schema(default = false, example = true)]
    pub redirect_to_merchant_with_http_post: Option<bool>,

    /// Webhook related details
    pub webhook_details: Option<WebhookDetails>,

    /// Metadata is useful for storing additional, unstructured information on an object.
    #[schema(value_type = Option<Object>, example = r#"{ "city": "NY", "unit": "245" }"#)]
    pub metadata: Option<pii::SecretSerdeValue>,

    /// The routing algorithm to be used for routing payments to desired connectors
    #[schema(value_type = Option<Object>,example = json!({"type": "single", "data": "stripe"}))]
    pub routing_algorithm: Option<serde_json::Value>,

    /// Will be used to determine the time till which your payment will be active once the payment session starts
    #[schema(example = 900)]
    pub intent_fulfillment_time: Option<u32>,

    /// The frm routing algorithm to be used for routing payments to desired FRM's
    #[schema(value_type = Option<Object>,example = json!({"type": "single", "data": "signifyd"}))]
    pub frm_routing_algorithm: Option<serde_json::Value>,

    /// The routing algorithm to be used to process the incoming request from merchant to outgoing payment processor or payment method. The default is 'Custom'
    #[cfg(feature = "payouts")]
    #[schema(value_type = Option<StaticRoutingAlgorithm>,example = json!({"type": "single", "data": "wise"}))]
    pub payout_routing_algorithm: Option<serde_json::Value>,

    /// Verified Apple Pay domains for a particular profile
    pub applepay_verified_domains: Option<Vec<String>>,

    /// Client Secret Default expiry for all payments created under this profile
    #[schema(example = 900)]
    pub session_expiry: Option<u32>,

    /// Default Payment Link config for all payment links created under this profile
    pub payment_link_config: Option<BusinessPaymentLinkConfig>,

    /// External 3DS authentication details
    pub authentication_connector_details: Option<AuthenticationConnectorDetails>,

    /// Whether to use the billing details passed when creating the intent as payment method billing
    pub use_billing_as_payment_method_billing: Option<bool>,

    /// A boolean value to indicate if customer shipping details needs to be collected from wallet
    /// connector only if it is required field for connector (Eg. Apple Pay, Google Pay etc)
    #[schema(default = false, example = false)]
    pub collect_shipping_details_from_wallet_connector: Option<bool>,

    /// A boolean value to indicate if customer billing details needs to be collected from wallet
    /// connector only if it is required field for connector (Eg. Apple Pay, Google Pay etc)
    #[schema(default = false, example = false)]
    pub collect_billing_details_from_wallet_connector: Option<bool>,

    /// A boolean value to indicate if customer shipping details needs to be collected from wallet
    /// connector irrespective of connector required fields (Eg. Apple pay, Google pay etc)
    #[schema(default = false, example = false)]
    pub always_collect_shipping_details_from_wallet_connector: Option<bool>,

    /// A boolean value to indicate if customer billing details needs to be collected from wallet
    /// connector irrespective of connector required fields (Eg. Apple pay, Google pay etc)
    #[schema(default = false, example = false)]
    pub always_collect_billing_details_from_wallet_connector: Option<bool>,

    /// Indicates if the MIT (merchant initiated transaction) payments can be made connector
    /// agnostic, i.e., MITs may be processed through different connector than CIT (customer
    /// initiated transaction) based on the routing rules.
    /// If set to `false`, MIT will go through the same connector as the CIT.
    pub is_connector_agnostic_mit_enabled: Option<bool>,

    /// Default payout link config
    #[schema(value_type = Option<BusinessPayoutLinkConfig>)]
    pub payout_link_config: Option<BusinessPayoutLinkConfig>,

    /// These key-value pairs are sent as additional custom headers in the outgoing webhook request. It is recommended not to use more than four key-value pairs.
    #[schema(value_type = Option<Object>, example = r#"{ "key1": "value-1", "key2": "value-2" }"#)]
    pub outgoing_webhook_custom_http_headers: Option<HashMap<String, String>>,

    /// Merchant Connector id to be stored for tax_calculator connector
    #[schema(value_type = Option<String>)]
    pub tax_connector_id: Option<id_type::MerchantConnectorAccountId>,

    /// Indicates if tax_calculator connector is enabled or not.
    /// If set to `true` tax_connector_id will be checked.
    #[serde(default)]
    pub is_tax_connector_enabled: bool,

    /// Indicates if network tokenization is enabled or not.
    #[serde(default)]
    pub is_network_tokenization_enabled: bool,

    /// Indicates if is_auto_retries_enabled is enabled or not.
    pub is_auto_retries_enabled: Option<bool>,

    /// Maximum number of auto retries allowed for a payment
    pub max_auto_retries_enabled: Option<u8>,

    /// Bool indicating if extended authentication must be requested for all payments
    #[schema(value_type = Option<bool>)]
    pub always_request_extended_authorization:
        Option<primitive_wrappers::AlwaysRequestExtendedAuthorization>,

    /// Indicates if click to pay is enabled or not.
    #[serde(default)]
    pub is_click_to_pay_enabled: bool,

    /// Product authentication ids
    #[schema(value_type = Option<Object>, example = r#"{ "click_to_pay": "mca_ushduqwhdohwd", "netcetera": "mca_kwqhudqwd" }"#)]
    pub authentication_product_ids:
        Option<common_types::payments::AuthenticationConnectorAccountMap>,

    /// Card Testing Guard Configs
    pub card_testing_guard_config: Option<CardTestingGuardConfig>,

    ///Indicates if clear pan retries is enabled or not.
    pub is_clear_pan_retries_enabled: Option<bool>,

    /// Indicates if 3ds challenge is forced
    pub force_3ds_challenge: Option<bool>,

    /// Indicates if debit routing is enabled or not
    #[schema(value_type = Option<bool>)]
    pub is_debit_routing_enabled: Option<bool>,

    //Merchant country for the profile
    #[schema(value_type = Option<CountryAlpha2>, example = "US")]
    pub merchant_business_country: Option<api_enums::CountryAlpha2>,

    /// Indicates if the redirection has to open in the iframe
    #[schema(example = false)]
    pub is_iframe_redirection_enabled: Option<bool>,

    /// Indicates if pre network tokenization is enabled or not
    pub is_pre_network_tokenization_enabled: Option<bool>,

    /// Four-digit code assigned based on business type to determine processing fees and risk level
    #[schema(value_type = Option<MerchantCategoryCode>, example = "5411")]
    pub merchant_category_code: Option<api_enums::MerchantCategoryCode>,

    /// Merchant country code.
    /// This is a 3-digit ISO 3166-1 numeric country code that represents the country in which the merchant is registered or operates.
    /// Merchants typically receive this value based on their business registration information or during onboarding via payment processors or acquiring banks.
    /// It is used in payment processing, fraud detection, and regulatory compliance to determine regional rules and routing behavior.
    #[schema(value_type = Option<MerchantCountryCode>, example = "840")]
    pub merchant_country_code: Option<common_types::payments::MerchantCountryCode>,

    /// Time interval (in hours) for polling the connector to check dispute statuses
    #[schema(value_type = Option<i32>, example = 2)]
    pub dispute_polling_interval: Option<primitive_wrappers::DisputePollingIntervalInHours>,

    /// Indicates if manual retry for payment is enabled or not
    pub is_manual_retry_enabled: Option<bool>,
}


pub fn make_domain(
        &mut self,
        domain_identifier: String,
        domain_description: &str,
    ) -> Result<DomainId, GraphError<V>> {
        let domain_identifier = DomainIdentifier::new(domain_identifier);
        Ok(self
            .domain_identifier_map
            .clone()
            .get(&domain_identifier)
            .map_or_else(
                || {
                    let domain_id = self.domain.push(DomainInfo {
                        domain_identifier: domain_identifier.clone(),
                        domain_description: domain_description.to_string(),
                    });
                    self.domain_identifier_map
                        .insert(domain_identifier, domain_id);
                    domain_id
                },
                |domain_id| *domain_id,
            ))
    }


/// Get the tenant_id from the lineage
    pub fn tenant_id(&self) -> &id_type::TenantId {
        match self {
            Self::Tenant { tenant_id }
            | Self::Organization { tenant_id, .. }
            | Self::Merchant { tenant_id, .. }
            | Self::Profile { tenant_id, .. } => tenant_id,
        }
    }


pub struct FlexitiSyncResponse {
    transaction_id: String,
    purchase: FlexitiPurchase,
}


OpenAPI Block Path: components.schemas.GpayBillingAddressParameters
{
  "type": "object",
  "required": [
    "phone_number_required",
    "format"
  ],
  "properties": {
    "phone_number_required": {
      "type": "boolean",
      "description": "Is billing phone number required"
    },
    "format": {
      "$ref": "#/components/schemas/GpayBillingAddressFormat"
    }
  }
}


pub fn validate_payment_method_type_against_payment_method(
    payment_method: api_enums::PaymentMethod,
    payment_method_type: api_enums::PaymentMethodType,
) -> bool {
    match payment_method {
        #[cfg(feature = "v1")]
        api_enums::PaymentMethod::Card => matches!(
            payment_method_type,
            api_enums::PaymentMethodType::Credit | api_enums::PaymentMethodType::Debit
        ),
        #[cfg(feature = "v2")]
        api_enums::PaymentMethod::Card => matches!(
            payment_method_type,
            api_enums::PaymentMethodType::Credit
                | api_enums::PaymentMethodType::Debit
                | api_enums::PaymentMethodType::Card
        ),
        api_enums::PaymentMethod::PayLater => matches!(
            payment_method_type,
            api_enums::PaymentMethodType::Affirm
                | api_enums::PaymentMethodType::Alma
                | api_enums::PaymentMethodType::AfterpayClearpay
                | api_enums::PaymentMethodType::Klarna
                | api_enums::PaymentMethodType::PayBright
                | api_enums::PaymentMethodType::Atome
                | api_enums::PaymentMethodType::Walley
                | api_enums::PaymentMethodType::Breadpay
                | api_enums::PaymentMethodType::Flexiti
        ),
        api_enums::PaymentMethod::Wallet => matches!(
            payment_method_type,
            api_enums::PaymentMethodType::AmazonPay
                | api_enums::PaymentMethodType::Bluecode
                | api_enums::PaymentMethodType::Paysera
                | api_enums::PaymentMethodType::Skrill
                | api_enums::PaymentMethodType::ApplePay
                | api_enums::PaymentMethodType::GooglePay
                | api_enums::PaymentMethodType::Paypal
                | api_enums::PaymentMethodType::AliPay
                | api_enums::PaymentMethodType::AliPayHk
                | api_enums::PaymentMethodType::Dana
                | api_enums::PaymentMethodType::MbWay
                | api_enums::PaymentMethodType::MobilePay
                | api_enums::PaymentMethodType::SamsungPay
                | api_enums::PaymentMethodType::Twint
                | api_enums::PaymentMethodType::Vipps
                | api_enums::PaymentMethodType::TouchNGo
                | api_enums::PaymentMethodType::Swish
                | api_enums::PaymentMethodType::WeChatPay
                | api_enums::PaymentMethodType::GoPay
                | api_enums::PaymentMethodType::Gcash
                | api_enums::PaymentMethodType::Momo
                | api_enums::PaymentMethodType::KakaoPay
                | api_enums::PaymentMethodType::Cashapp
                | api_enums::PaymentMethodType::Mifinity
                | api_enums::PaymentMethodType::Paze
                | api_enums::PaymentMethodType::RevolutPay
        ),
        api_enums::PaymentMethod::BankRedirect => matches!(
            payment_method_type,
            api_enums::PaymentMethodType::Giropay
                | api_enums::PaymentMethodType::Ideal
                | api_enums::PaymentMethodType::Sofort
                | api_enums::PaymentMethodType::Eft
                | api_enums::PaymentMethodType::Eps
                | api_enums::PaymentMethodType::BancontactCard
                | api_enums::PaymentMethodType::Blik
                | api_enums::PaymentMethodType::LocalBankRedirect
                | api_enums::PaymentMethodType::OnlineBankingThailand
                | api_enums::PaymentMethodType::OnlineBankingCzechRepublic
                | api_enums::PaymentMethodType::OnlineBankingFinland
                | api_enums::PaymentMethodType::OnlineBankingFpx
                | api_enums::PaymentMethodType::OnlineBankingPoland
                | api_enums::PaymentMethodType::OnlineBankingSlovakia
                | api_enums::PaymentMethodType::Przelewy24
                | api_enums::PaymentMethodType::Trustly
                | api_enums::PaymentMethodType::Bizum
                | api_enums::PaymentMethodType::Interac
                | api_enums::PaymentMethodType::OpenBankingUk
                | api_enums::PaymentMethodType::OpenBankingPIS
        ),
        api_enums::PaymentMethod::BankTransfer => matches!(
            payment_method_type,
            api_enums::PaymentMethodType::Ach
                | api_enums::PaymentMethodType::SepaBankTransfer
                | api_enums::PaymentMethodType::Bacs
                | api_enums::PaymentMethodType::Multibanco
                | api_enums::PaymentMethodType::Pix
                | api_enums::PaymentMethodType::Pse
                | api_enums::PaymentMethodType::PermataBankTransfer
                | api_enums::PaymentMethodType::BcaBankTransfer
                | api_enums::PaymentMethodType::BniVa
                | api_enums::PaymentMethodType::BriVa
                | api_enums::PaymentMethodType::CimbVa
                | api_enums::PaymentMethodType::DanamonVa
                | api_enums::PaymentMethodType::MandiriVa
                | api_enums::PaymentMethodType::LocalBankTransfer
                | api_enums::PaymentMethodType::InstantBankTransfer
                | api_enums::PaymentMethodType::InstantBankTransferFinland
                | api_enums::PaymentMethodType::InstantBankTransferPoland
                | api_enums::PaymentMethodType::IndonesianBankTransfer
        ),
        api_enums::PaymentMethod::BankDebit => matches!(
            payment_method_type,
            api_enums::PaymentMethodType::Ach
                | api_enums::PaymentMethodType::Sepa
                | api_enums::PaymentMethodType::Bacs
                | api_enums::PaymentMethodType::Becs
        ),
        api_enums::PaymentMethod::Crypto => matches!(
            payment_method_type,
            api_enums::PaymentMethodType::CryptoCurrency
        ),
        api_enums::PaymentMethod::Reward => matches!(
            payment_method_type,
            api_enums::PaymentMethodType::Evoucher | api_enums::PaymentMethodType::ClassicReward
        ),
        api_enums::PaymentMethod::RealTimePayment => matches!(
            payment_method_type,
            api_enums::PaymentMethodType::Fps
                | api_enums::PaymentMethodType::DuitNow
                | api_enums::PaymentMethodType::PromptPay
                | api_enums::PaymentMethodType::VietQr
        ),
        api_enums::PaymentMethod::Upi => matches!(
            payment_method_type,
            api_enums::PaymentMethodType::UpiCollect | api_enums::PaymentMethodType::UpiIntent
        ),
        api_enums::PaymentMethod::Voucher => matches!(
            payment_method_type,
            api_enums::PaymentMethodType::Boleto
                | api_enums::PaymentMethodType::Efecty
                | api_enums::PaymentMethodType::PagoEfectivo
                | api_enums::PaymentMethodType::RedCompra
                | api_enums::PaymentMethodType::RedPagos
                | api_enums::PaymentMethodType::Indomaret
                | api_enums::PaymentMethodType::Alfamart
                | api_enums::PaymentMethodType::Oxxo
                | api_enums::PaymentMethodType::SevenEleven
                | api_enums::PaymentMethodType::Lawson
                | api_enums::PaymentMethodType::MiniStop
                | api_enums::PaymentMethodType::FamilyMart
                | api_enums::PaymentMethodType::Seicomart
                | api_enums::PaymentMethodType::PayEasy
        ),
        api_enums::PaymentMethod::GiftCard => {
            matches!(
                payment_method_type,
                api_enums::PaymentMethodType::Givex | api_enums::PaymentMethodType::PaySafeCard
            )
        }
        api_enums::PaymentMethod::CardRedirect => matches!(
            payment_method_type,
            api_enums::PaymentMethodType::Knet
                | api_enums::PaymentMethodType::Benefit
                | api_enums::PaymentMethodType::MomoAtm
                | api_enums::PaymentMethodType::CardRedirect
        ),
        api_enums::PaymentMethod::OpenBanking => matches!(
            payment_method_type,
            api_enums::PaymentMethodType::OpenBankingPIS
        ),
        api_enums::PaymentMethod::MobilePayment => matches!(
            payment_method_type,
            api_enums::PaymentMethodType::DirectCarrierBilling
        ),
    }
}


pub struct AirwallexAuthUpdateResponse {
    #[serde(with = "common_utils::custom_serde::iso8601")]
    expires_at: PrimitiveDateTime,
    token: Secret<String>,
}


pub struct Threedsecureio;


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

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

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

impl ConnectorSpecifications for for Globalpay


File: crates/router/src/types/storage/capture.rs

pub use diesel_models::capture::*;


pub async fn create_customer(
    state: SessionState,
    merchant_context: domain::MerchantContext,
    customer_data: customers::CustomerRequest,
    connector_customer_details: Option<Vec<payment_methods_domain::ConnectorCustomerDetails>>,
) -> errors::CustomerResponse<customers::CustomerResponse> {
    let db: &dyn StorageInterface = state.store.as_ref();
    let key_manager_state = &(&state).into();

    let merchant_reference_id = customer_data.get_merchant_reference_id();

    let merchant_id = merchant_context.get_merchant_account().get_id();

    let merchant_reference_id_customer = MerchantReferenceIdForCustomer {
        merchant_reference_id: merchant_reference_id.as_ref(),
        merchant_id,
        merchant_account: merchant_context.get_merchant_account(),
        key_store: merchant_context.get_merchant_key_store(),
        key_manager_state,
    };

    // We first need to validate whether the customer with the given customer id already exists
    // this may seem like a redundant db call, as the insert_customer will anyway return this error
    //
    // Consider a scenario where the address is inserted and then when inserting the customer,
    // it errors out, now the address that was inserted is not deleted

    merchant_reference_id_customer
        .verify_if_merchant_reference_not_present_by_optional_merchant_reference_id(db)
        .await?;

    let domain_customer = customer_data
        .create_domain_model_from_request(
            &connector_customer_details,
            db,
            &merchant_reference_id,
            &merchant_context,
            key_manager_state,
            &state,
        )
        .await?;

    let customer = db
        .insert_customer(
            domain_customer,
            key_manager_state,
            merchant_context.get_merchant_key_store(),
            merchant_context.get_merchant_account().storage_scheme,
        )
        .await
        .to_duplicate_response(errors::CustomersErrorResponse::CustomerAlreadyExists)?;

    customer_data.generate_response(&customer)
}


impl api::PaymentVoid for Bambora {}


pub async fn upsert_conditional_config(
    state: SessionState,
    key_store: domain::MerchantKeyStore,
    request: DecisionManagerRequest,
    profile: domain::Profile,
) -> RouterResponse<common_types::payments::DecisionManagerRecord> {
    use common_utils::ext_traits::OptionExt;

    let key_manager_state: &KeyManagerState = &(&state).into();
    let db = &*state.store;
    let name = request.name;
    let program = request.program;
    let timestamp = common_utils::date_time::now_unix_timestamp();

    euclid::frontend::ast::lowering::lower_program(program.clone())
        .change_context(errors::ApiErrorResponse::InvalidRequestData {
            message: "Invalid Request Data".to_string(),
        })
        .attach_printable("The Request has an Invalid Comparison")?;

    let decision_manager_record = common_types::payments::DecisionManagerRecord {
        name,
        program,
        created_at: timestamp,
    };

    let business_profile_update = domain::ProfileUpdate::DecisionManagerRecordUpdate {
        three_ds_decision_manager_config: decision_manager_record,
    };
    let updated_profile = db
        .update_profile_by_profile_id(
            key_manager_state,
            &key_store,
            profile,
            business_profile_update,
        )
        .await
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("Failed to update decision manager record in business profile")?;

    Ok(service_api::ApplicationResponse::Json(
        updated_profile
            .three_ds_decision_manager_config
            .clone()
            .get_required_value("three_ds_decision_manager_config")
            .change_context(errors::ApiErrorResponse::InternalServerError)
            .attach_printable(
                "Failed to get updated decision manager record in business profile",
            )?,
    ))
}


OpenAPI Block Path: components.schemas.RankingAlgorithm
{
  "type": "string",
  "enum": [
    "SR_BASED_ROUTING",
    "PL_BASED_ROUTING",
    "NTW_BASED_ROUTING"
  ]
}


pub struct RefundsData {
    status: String,
    status_desc: String,
    refund_id: String,
}


impl api::ConnectorAccessToken for Dwolla {}

impl api::ConnectorAccessToken for for Dwolla


impl api::UnifiedAuthenticationServiceV2 for Recurly {}

impl api::UnifiedAuthenticationServiceV2 for for Recurly


impl api::PaymentSession for Cryptopay {}

impl api::PaymentSession for for Cryptopay


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

pub mod transformers;

use std::sync::LazyLock;

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

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

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

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

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

impl ConnectorIntegration<PaymentMethodToken, PaymentMethodTokenizationData, PaymentsResponseData>
    for Forte
{
}
pub const AUTH_ORG_ID_HEADER: &str = "X-Forte-Auth-Organization-Id";

impl<Flow, Request, Response> ConnectorCommonExt<Flow, Request, Response> for Forte
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 content_type = ConnectorCommon::common_get_content_type(self);
        let mut common_headers = self.get_auth_header(&req.connector_auth_type)?;
        common_headers.push((
            headers::CONTENT_TYPE.to_string(),
            content_type.to_string().into(),
        ));
        Ok(common_headers)
    }
}

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

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

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

    fn get_auth_header(
        &self,
        auth_type: &ConnectorAuthType,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        let auth = forte::ForteAuthType::try_from(auth_type)
            .change_context(errors::ConnectorError::FailedToObtainAuthType)?;
        let raw_basic_token = format!(
            "{}:{}",
            auth.api_access_id.peek(),
            auth.api_secret_key.peek()
        );
        let basic_token = format!("Basic {}", BASE64_ENGINE.encode(raw_basic_token));
        Ok(vec![
            (
                headers::AUTHORIZATION.to_string(),
                basic_token.into_masked(),
            ),
            (
                AUTH_ORG_ID_HEADER.to_string(),
                auth.organization_id.into_masked(),
            ),
        ])
    }
    fn build_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        let response: forte::ForteErrorResponse = res
            .response
            .parse_struct("Forte ErrorResponse")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;

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

        let message = response.response.response_desc;
        let code = response
            .response
            .response_code
            .unwrap_or_else(|| NO_ERROR_CODE.to_string());
        Ok(ErrorResponse {
            status_code: res.status_code,
            code,
            message,
            reason: None,
            attempt_status: None,
            connector_transaction_id: None,
            network_advice_code: None,
            network_decline_code: None,
            network_error_message: None,
            connector_metadata: None,
        })
    }
}

impl ConnectorValidation for Forte {}

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

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

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

impl ConnectorIntegration<Authorize, PaymentsAuthorizeData, PaymentsResponseData> for Forte {
    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> {
        let auth: forte::ForteAuthType = forte::ForteAuthType::try_from(&req.connector_auth_type)?;
        Ok(format!(
            "{}/organizations/{}/locations/{}/transactions",
            self.base_url(connectors),
            auth.organization_id.peek(),
            auth.location_id.peek()
        ))
    }

    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 = forte::ForteRouterData::from((amount, req));
        let connector_req = forte::FortePaymentsRequest::try_from(&connector_router_data)?;
        Ok(RequestContent::Json(Box::new(connector_req)))
    }

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

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

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

    fn get_url(
        &self,
        req: &PaymentsSyncRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        let auth: forte::ForteAuthType = forte::ForteAuthType::try_from(&req.connector_auth_type)?;
        let txn_id = PaymentsSyncRequestData::get_connector_transaction_id(&req.request)
            .change_context(errors::ConnectorError::MissingConnectorTransactionID)?;
        Ok(format!(
            "{}/organizations/{}/locations/{}/transactions/{}",
            self.base_url(connectors),
            auth.organization_id.peek(),
            auth.location_id.peek(),
            txn_id
        ))
    }

    fn build_request(
        &self,
        req: &PaymentsSyncRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        Ok(Some(
            RequestBuilder::new()
                .method(Method::Get)
                .url(&types::PaymentsSyncType::get_url(self, req, connectors)?)
                .attach_default_headers()
                .headers(types::PaymentsSyncType::get_headers(self, req, connectors)?)
                .build(),
        ))
    }
    fn handle_response(
        &self,
        data: &PaymentsSyncRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<PaymentsSyncRouterData, errors::ConnectorError> {
        let response: forte::FortePaymentsSyncResponse = res
            .response
            .parse_struct("forte 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 Forte {
    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> {
        let auth: forte::ForteAuthType = forte::ForteAuthType::try_from(&req.connector_auth_type)?;
        Ok(format!(
            "{}/organizations/{}/locations/{}/transactions",
            self.base_url(connectors),
            auth.organization_id.peek(),
            auth.location_id.peek()
        ))
    }

    fn get_request_body(
        &self,
        req: &PaymentsCaptureRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let connector_req = forte::ForteCaptureRequest::try_from(req)?;
        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::Put)
                .url(&types::PaymentsCaptureType::get_url(self, req, connectors)?)
                .attach_default_headers()
                .headers(types::PaymentsCaptureType::get_headers(
                    self, req, connectors,
                )?)
                .set_body(types::PaymentsCaptureType::get_request_body(
                    self, req, connectors,
                )?)
                .build(),
        ))
    }

    fn handle_response(
        &self,
        data: &PaymentsCaptureRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<PaymentsCaptureRouterData, errors::ConnectorError> {
        let response: forte::ForteCaptureResponse = res
            .response
            .parse_struct("Forte 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 Forte {
    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> {
        let auth: forte::ForteAuthType = forte::ForteAuthType::try_from(&req.connector_auth_type)?;
        Ok(format!(
            "{}/organizations/{}/locations/{}/transactions/{}",
            self.base_url(connectors),
            auth.organization_id.peek(),
            auth.location_id.peek(),
            req.request.connector_transaction_id
        ))
    }
    fn get_request_body(
        &self,
        req: &PaymentsCancelRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let connector_req = forte::ForteCancelRequest::try_from(req)?;
        Ok(RequestContent::Json(Box::new(connector_req)))
    }

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

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

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

    fn get_url(
        &self,
        req: &RefundsRouterData<Execute>,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        let auth: forte::ForteAuthType = forte::ForteAuthType::try_from(&req.connector_auth_type)?;
        Ok(format!(
            "{}/organizations/{}/locations/{}/transactions",
            self.base_url(connectors),
            auth.organization_id.peek(),
            auth.location_id.peek()
        ))
    }

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

        let connector_router_data = forte::ForteRouterData::from((refund_amount, req));
        let connector_req = forte::ForteRefundRequest::try_from(&connector_router_data)?;
        Ok(RequestContent::Json(Box::new(connector_req)))
    }

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

    fn handle_response(
        &self,
        data: &RefundsRouterData<Execute>,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<RefundsRouterData<Execute>, errors::ConnectorError> {
        let response: forte::RefundResponse = res
            .response
            .parse_struct("forte 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 Forte {
    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> {
        let auth: forte::ForteAuthType = forte::ForteAuthType::try_from(&req.connector_auth_type)?;
        Ok(format!(
            "{}/organizations/{}/locations/{}/transactions/{}",
            self.base_url(connectors),
            auth.organization_id.peek(),
            auth.location_id.peek(),
            req.request.get_connector_refund_id()?
        ))
    }

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

    fn handle_response(
        &self,
        data: &RefundSyncRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<RefundSyncRouterData, errors::ConnectorError> {
        let response: forte::RefundSyncResponse = res
            .response
            .parse_struct("forte 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 IncomingWebhook for Forte {
    fn get_webhook_object_reference_id(
        &self,
        _request: &IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<ObjectReferenceId, errors::ConnectorError> {
        Err(report!(errors::ConnectorError::WebhooksNotImplemented))
    }

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

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

static FORTE_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::AmericanExpress,
        common_enums::CardNetwork::Discover,
        common_enums::CardNetwork::DinersClub,
        common_enums::CardNetwork::JCB,
        common_enums::CardNetwork::Mastercard,
        common_enums::CardNetwork::Visa,
    ];

    let mut forte_supported_payment_methods = SupportedPaymentMethods::new();

    forte_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(),
                    }
                }),
            ),
        },
    );

    forte_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(),
                    }
                }),
            ),
        },
    );
    forte_supported_payment_methods
});

static FORTE_CONNECTOR_INFO: ConnectorInfo = ConnectorInfo {
    display_name: "Forte",
    description:
        "CSG Forte offers a unified payments platform, enabling businesses to securely process credit cards, debit cards, ACH/eCheck transactions, and more, with advanced fraud prevention and seamless integration.",
    connector_type: enums::HyperswitchConnectorCategory::PaymentGateway,
    integration_status: enums::ConnectorIntegrationStatus::Sandbox,
};

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

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

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

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


pub struct FilterValue {
    pub dimension: PaymentDimensions,
    pub values: Vec<String>,
}


pub struct OptionalDieselArray<T>(Option<Vec<Option<T>>>);


pub struct RedisSettings {
    pub host: String,
    pub port: u16,
    pub cluster_enabled: bool,
    pub cluster_urls: Vec<String>,
    pub use_legacy_version: bool,
    pub pool_size: usize,
    pub reconnect_max_attempts: u32,
    /// Reconnect delay in milliseconds
    pub reconnect_delay: u32,
    /// TTL in seconds
    pub default_ttl: u32,
    /// TTL for hash-tables in seconds
    pub default_hash_ttl: u32,
    pub stream_read_count: u64,
    pub auto_pipeline: bool,
    pub disable_auto_backpressure: bool,
    pub max_in_flight_commands: u64,
    pub default_command_timeout: u64,
    pub max_feed_count: u64,
    pub unresponsive_timeout: u64,
}


impl Responder {
        let flow = AnalyticsFlow::GetPaymentIntentFilters;
        Box::pin(api::server_wrap(
            flow,
            state,
            &req,
            json_payload.into_inner(),
            |state, auth: AuthenticationData, req, _| async move {
                analytics::payment_intents::get_filters(
                    &state.pool,
                    req,
                    auth.merchant_account.get_id(),
                )
                .await
                .map(ApplicationResponse::Json)
            },
            auth::auth_type(
                &auth::PlatformOrgAdminAuth {
                    is_admin_auth_allowed: false,
                    organization_id: None,
                },
                &auth::JWTAuth {
                    permission: Permission::MerchantAnalyticsRead,
                },
                req.headers(),
            ),
            api_locking::LockAction::NotApplicable,
        ))
        .await
    }


pub struct PaymentListFilters {
    pub connector: Vec<String>,
    pub currency: Vec<storage_enums::Currency>,
    pub status: Vec<storage_enums::IntentStatus>,
    pub payment_method: Vec<storage_enums::PaymentMethod>,
    pub payment_method_type: Vec<storage_enums::PaymentMethodType>,
    pub authentication_type: Vec<storage_enums::AuthenticationType>,
}


impl ConnectorValidation for Prophetpay {
    //TODO: implement functions when support enabled
}

impl ConnectorValidation for for Prophetpay


        Ok(transformers::get_payapl_webhooks_event(
            payload.event_type,
            outcome,
        ))
    }

    fn get_webhook_resource_object(
        &self,
        request: &IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<Box<dyn masking::ErasedMaskSerialize>, errors::ConnectorError> {
        let details: paypal::PaypalWebhooksBody =
            request
                .body
                .parse_struct("PaypalWebhooksBody")
                .change_context(errors::ConnectorError::WebhookResourceObjectNotFound)?;
        Ok(match details.resource {
            paypal::PaypalResource::PaypalCardWebhooks(resource) => Box::new(
                paypal::PaypalPaymentsSyncResponse::try_from((*resource, details.event_type))?,
            ),
            paypal::PaypalResource::PaypalRedirectsWebhooks(resource) => Box::new(
                paypal::PaypalOrdersResponse::try_from((*resource, details.event_type))?,
            ),
            paypal::PaypalResource::PaypalRefundWebhooks(resource) => Box::new(
                paypal::RefundSyncResponse::try_from((*resource, details.event_type))?,
            ),
            paypal::PaypalResource::PaypalDisputeWebhooks(_) => Box::new(details),
            #[cfg(feature = "payouts")]
            paypal::PaypalResource::PaypalBatchPayoutWebhooks(resource) => {
                Box::new(paypal::PaypalPayoutSyncResponse::try_from(*resource)?)
            }
            #[cfg(feature = "payouts")]
            paypal::PaypalResource::PaypalItemPayoutWebhooks(resource) => Box::new(
                paypal::PaypalPayoutSyncResponse::try_from((*resource, details.event_type))?,
            ),
        })
    }

    fn get_dispute_details(
        &self,
        request: &IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<disputes::DisputePayload, errors::ConnectorError> {
        let webhook_payload: paypal::PaypalWebhooksBody = request
            .body
            .parse_struct("PaypalWebhooksBody")
            .change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?;
        match webhook_payload.resource {
            transformers::PaypalResource::PaypalCardWebhooks(_)
            | transformers::PaypalResource::PaypalRedirectsWebhooks(_)
            | transformers::PaypalResource::PaypalRefundWebhooks(_) => {
                Err(errors::ConnectorError::ResponseDeserializationFailed)
                    .attach_printable("Expected Dispute webhooks,but found other webhooks")?
            }
            #[cfg(feature = "payouts")]
            transformers::PaypalResource::PaypalBatchPayoutWebhooks(_)
            | transformers::PaypalResource::PaypalItemPayoutWebhooks(_) => {
                Err(errors::ConnectorError::ResponseDeserializationFailed)
                    .attach_printable("Expected Dispute webhooks,but found other webhooks")?
            }
            transformers::PaypalResource::PaypalDisputeWebhooks(payload) => {
                let amt = connector_utils::convert_back_amount_to_minor_units(
                    self.amount_converter,
                    payload.dispute_amount.value,
                    payload.dispute_amount.currency_code,
                )?;
                Ok(disputes::DisputePayload {
                    amount: connector_utils::convert_amount(
                        self.amount_converter_webhooks,
                        amt,
                        payload.dispute_amount.currency_code,
                    )?,
                    currency: payload.dispute_amount.currency_code,
                    dispute_stage: api_models::enums::DisputeStage::from(
                        payload.dispute_life_cycle_stage.clone(),
                    ),
                    connector_status: payload.status.to_string(),
                    connector_dispute_id: payload.dispute_id,
                    connector_reason: payload.reason.clone(),
                    connector_reason_code: payload.reason,
                    challenge_required_by: None,
                    created_at: payload.create_time,
                    updated_at: payload.update_time,
                })
            }
        }
    }
}

impl ConnectorRedirectResponse for Paypal {
    fn get_flow_type(
        &self,
        _query_params: &str,
        _json_payload: Option<serde_json::Value>,
        action: PaymentAction,
    ) -> CustomResult<CallConnectorAction, errors::ConnectorError> {
        match action {
            PaymentAction::PSync
            | PaymentAction::CompleteAuthorize
            | PaymentAction::PaymentAuthenticateCompleteAuthorize => {
                Ok(CallConnectorAction::Trigger)
            }
        }
    }
}

impl ConnectorErrorTypeMapping for Paypal {
    fn get_connector_error_type(
        &self,
        error_code: String,
        _error_message: String,
    ) -> ConnectorErrorType {
        match error_code.as_str() {
            "CANNOT_BE_NEGATIVE" => ConnectorErrorType::UserError,
            "CANNOT_BE_ZERO_OR_NEGATIVE" => ConnectorErrorType::UserError,
            "CARD_EXPIRED" => ConnectorErrorType::UserError,
            "DECIMAL_PRECISION" => ConnectorErrorType::UserError,
            "DUPLICATE_INVOICE_ID" => ConnectorErrorType::UserError,
            "INSTRUMENT_DECLINED" => ConnectorErrorType::BusinessError,
            "INTERNAL_SERVER_ERROR" => ConnectorErrorType::TechnicalError,
            "INVALID_ACCOUNT_STATUS" => ConnectorErrorType::BusinessError,
            "INVALID_CURRENCY_CODE" => ConnectorErrorType::UserError,
            "INVALID_PARAMETER_SYNTAX" => ConnectorErrorType::UserError,
            "INVALID_PARAMETER_VALUE" => ConnectorErrorType::UserError,
            "INVALID_RESOURCE_ID" => ConnectorErrorType::UserError,
            "INVALID_STRING_LENGTH" => ConnectorErrorType::UserError,
            "MISSING_REQUIRED_PARAMETER" => ConnectorErrorType::UserError,
            "PAYER_ACCOUNT_LOCKED_OR_CLOSED" => ConnectorErrorType::BusinessError,
            "PAYER_ACCOUNT_RESTRICTED" => ConnectorErrorType::BusinessError,
            "PAYER_CANNOT_PAY" => ConnectorErrorType::BusinessError,
            "PERMISSION_DENIED" => ConnectorErrorType::BusinessError,
            "INVALID_ARRAY_MAX_ITEMS" => ConnectorErrorType::UserError,
            "INVALID_ARRAY_MIN_ITEMS" => ConnectorErrorType::UserError,
            "INVALID_COUNTRY_CODE" => ConnectorErrorType::UserError,
            "NOT_SUPPORTED" => ConnectorErrorType::BusinessError,
            "PAYPAL_REQUEST_ID_REQUIRED" => ConnectorErrorType::UserError,
            "MALFORMED_REQUEST_JSON" => ConnectorErrorType::UserError,
            "PERMISSION_DENIED_FOR_DONATION_ITEMS" => ConnectorErrorType::BusinessError,
            "MALFORMED_REQUEST" => ConnectorErrorType::TechnicalError,
            "AMOUNT_MISMATCH" => ConnectorErrorType::UserError,
            "BILLING_ADDRESS_INVALID" => ConnectorErrorType::UserError,
            "CITY_REQUIRED" => ConnectorErrorType::UserError,
            "DONATION_ITEMS_NOT_SUPPORTED" => ConnectorErrorType::BusinessError,
            "DUPLICATE_REFERENCE_ID" => ConnectorErrorType::UserError,
            "INVALID_PAYER_ID" => ConnectorErrorType::UserError,
            "ITEM_TOTAL_REQUIRED" => ConnectorErrorType::UserError,
            "MAX_VALUE_EXCEEDED" => ConnectorErrorType::UserError,
            "MISSING_PICKUP_ADDRESS" => ConnectorErrorType::UserError,
            "MULTI_CURRENCY_ORDER" => ConnectorErrorType::BusinessError,
            "MULTIPLE_ITEM_CATEGORIES" => ConnectorErrorType::UserError,
            "MULTIPLE_SHIPPING_ADDRESS_NOT_SUPPORTED" => ConnectorErrorType::UserError,
            "MULTIPLE_SHIPPING_TYPE_NOT_SUPPORTED" => ConnectorErrorType::BusinessError,
            "PAYEE_ACCOUNT_INVALID" => ConnectorErrorType::UserError,
            "PAYEE_ACCOUNT_LOCKED_OR_CLOSED" => ConnectorErrorType::UserError,
            "REFERENCE_ID_REQUIRED" => ConnectorErrorType::UserError,
            "PAYMENT_SOURCE_CANNOT_BE_USED" => ConnectorErrorType::BusinessError,
            "PAYMENT_SOURCE_DECLINED_BY_PROCESSOR" => ConnectorErrorType::BusinessError,
            "PAYMENT_SOURCE_INFO_CANNOT_BE_VERIFIED" => ConnectorErrorType::BusinessError,
            "POSTAL_CODE_REQUIRED" => ConnectorErrorType::UserError,
            "SHIPPING_ADDRESS_INVALID" => ConnectorErrorType::UserError,
            "TAX_TOTAL_MISMATCH" => ConnectorErrorType::UserError,
            "TAX_TOTAL_REQUIRED" => ConnectorErrorType::UserError,
            "UNSUPPORTED_INTENT" => ConnectorErrorType::BusinessError,
            "UNSUPPORTED_PAYMENT_INSTRUCTION" => ConnectorErrorType::UserError,
            "SHIPPING_TYPE_NOT_SUPPORTED_FOR_CLIENT" => ConnectorErrorType::BusinessError,
            "UNSUPPORTED_SHIPPING_TYPE" => ConnectorErrorType::BusinessError,
            "PREFERRED_SHIPPING_OPTION_AMOUNT_MISMATCH" => ConnectorErrorType::UserError,
            "CARD_CLOSED" => ConnectorErrorType::BusinessError,
            "ORDER_CANNOT_BE_SAVED" => ConnectorErrorType::BusinessError,
            "SAVE_ORDER_NOT_SUPPORTED" => ConnectorErrorType::BusinessError,
            "FIELD_NOT_PATCHABLE" => ConnectorErrorType::UserError,
            "AMOUNT_NOT_PATCHABLE" => ConnectorErrorType::UserError,
            "INVALID_PATCH_OPERATION" => ConnectorErrorType::UserError,
            "PAYEE_ACCOUNT_NOT_SUPPORTED" => ConnectorErrorType::UserError,
            "PAYEE_ACCOUNT_NOT_VERIFIED" => ConnectorErrorType::UserError,
            "PAYEE_NOT_CONSENTED" => ConnectorErrorType::UserError,
            "INVALID_JSON_POINTER_FORMAT" => ConnectorErrorType::BusinessError,
            "INVALID_PARAMETER" => ConnectorErrorType::UserError,
            "NOT_PATCHABLE" => ConnectorErrorType::BusinessError,
            "PATCH_VALUE_REQUIRED" => ConnectorErrorType::UserError,
            "PATCH_PATH_REQUIRED" => ConnectorErrorType::UserError,
            "REFERENCE_ID_NOT_FOUND" => ConnectorErrorType::UserError,
            "SHIPPING_OPTION_NOT_SELECTED" => ConnectorErrorType::UserError,
            "SHIPPING_OPTIONS_NOT_SUPPORTED" => ConnectorErrorType::BusinessError,
            "MULTIPLE_SHIPPING_OPTION_SELECTED" => ConnectorErrorType::UserError,
            "ORDER_ALREADY_COMPLETED" => ConnectorErrorType::BusinessError,
            "ACTION_DOES_NOT_MATCH_INTENT" => ConnectorErrorType::BusinessError,
            "AGREEMENT_ALREADY_CANCELLED" => ConnectorErrorType::BusinessError,
            "BILLING_AGREEMENT_NOT_FOUND" => ConnectorErrorType::BusinessError,
            "DOMESTIC_TRANSACTION_REQUIRED" => ConnectorErrorType::BusinessError,
            "ORDER_NOT_APPROVED" => ConnectorErrorType::UserError,
            "MAX_NUMBER_OF_PAYMENT_ATTEMPTS_EXCEEDED" => ConnectorErrorType::TechnicalError,
            "PAYEE_BLOCKED_TRANSACTION" => ConnectorErrorType::BusinessError,
            "TRANSACTION_LIMIT_EXCEEDED" => ConnectorErrorType::UserError,
            "TRANSACTION_RECEIVING_LIMIT_EXCEEDED" => ConnectorErrorType::BusinessError,
            "TRANSACTION_REFUSED" => ConnectorErrorType::TechnicalError,
            "ORDER_ALREADY_AUTHORIZED" => ConnectorErrorType::BusinessError,
            "AUTH_CAPTURE_NOT_ENABLED" => ConnectorErrorType::BusinessError,
            "AMOUNT_CANNOT_BE_SPECIFIED" => ConnectorErrorType::BusinessError,
            "AUTHORIZATION_AMOUNT_EXCEEDED" => ConnectorErrorType::UserError,
            "AUTHORIZATION_CURRENCY_MISMATCH" => ConnectorErrorType::UserError,
            "MAX_AUTHORIZATION_COUNT_EXCEEDED" => ConnectorErrorType::BusinessError,
            "ORDER_COMPLETED_OR_VOIDED" => ConnectorErrorType::BusinessError,
            "ORDER_EXPIRED" => ConnectorErrorType::BusinessError,
            "INVALID_PICKUP_ADDRESS" => ConnectorErrorType::UserError,
            "CONSENT_NEEDED" => ConnectorErrorType::UserError,
            "COMPLIANCE_VIOLATION" => ConnectorErrorType::BusinessError,
            "REDIRECT_PAYER_FOR_ALTERNATE_FUNDING" => ConnectorErrorType::TechnicalError,
            "ORDER_ALREADY_CAPTURED" => ConnectorErrorType::UserError,
            "TRANSACTION_BLOCKED_BY_PAYEE" => ConnectorErrorType::BusinessError,
            "NOT_ENABLED_FOR_CARD_PROCESSING" => ConnectorErrorType::BusinessError,
            "PAYEE_NOT_ENABLED_FOR_CARD_PROCESSING" => ConnectorErrorType::BusinessError,
            _ => ConnectorErrorType::UnknownError,
        }
    }
}

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

    let supported_capture_methods_bank_redirect = vec![
        enums::CaptureMethod::Automatic,
        enums::CaptureMethod::SequentialAutomatic,
    ];

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

    let mut paypal_supported_payment_methods = SupportedPaymentMethods::new();

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

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

    paypal_supported_payment_methods.add(
        enums::PaymentMethod::Wallet,
        enums::PaymentMethodType::Paypal,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::Supported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods.clone(),
            specific_features: None,
        },
    );

    paypal_supported_payment_methods.add(
        enums::PaymentMethod::BankRedirect,
        enums::PaymentMethodType::Eps,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods_bank_redirect.clone(),
            specific_features: None,
        },
    );

    paypal_supported_payment_methods.add(
        enums::PaymentMethod::BankRedirect,
        enums::PaymentMethodType::Giropay,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods_bank_redirect.clone(),
            specific_features: None,
        },
    );

    paypal_supported_payment_methods.add(
        enums::PaymentMethod::BankRedirect,
        enums::PaymentMethodType::Ideal,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods_bank_redirect.clone(),
            specific_features: None,
        },
    );

    paypal_supported_payment_methods.add(
        enums::PaymentMethod::BankRedirect,
        enums::PaymentMethodType::Sofort,
        PaymentMethodDetails {
            mandates: enums::FeatureStatus::NotSupported,
            refunds: enums::FeatureStatus::Supported,
            supported_capture_methods: supported_capture_methods_bank_redirect.clone(),
            specific_features: None,
        },
    );

    paypal_supported_payment_methods
});

static PAYPAL_CONNECTOR_INFO: ConnectorInfo = ConnectorInfo {
    display_name: "Paypal",
    description: "PayPal is a global online payment system that enables individuals and businesses to send and receive money electronically.",
    connector_type: enums::HyperswitchConnectorCategory::PaymentGateway,
    integration_status: enums::ConnectorIntegrationStatus::Live,
};

static PAYPAL_SUPPORTED_WEBHOOK_FLOWS: [enums::EventClass; 3] = [
    enums::EventClass::Payments,
    enums::EventClass::Refunds,
    enums::EventClass::Disputes,
];

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

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

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


pub fn update_gateway_system_in_feature_metadata<F: Clone, D>(
    payment_data: &mut D,
    gateway_system: GatewaySystem,
) -> RouterResult<()>
where
    D: OperationSessionGetters<F> + OperationSessionSetters<F>,
{
    let mut payment_intent = payment_data.get_payment_intent().clone();

    let existing_metadata = payment_intent.feature_metadata.as_ref();

    let mut feature_metadata = existing_metadata
        .and_then(|metadata| serde_json::from_value::<FeatureMetadata>(metadata.clone()).ok())
        .unwrap_or_default();

    feature_metadata.gateway_system = Some(gateway_system);

    let updated_metadata = serde_json::to_value(feature_metadata)
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("Failed to serialize feature metadata")?;

    payment_intent.feature_metadata = Some(updated_metadata.clone());
    payment_data.set_payment_intent(payment_intent);

    Ok(())
}


impl ConnectorValidation for Dlocal {}


impl HeaderPayload {
    pub fn with_source(payment_confirm_source: common_enums::PaymentSource) -> Self {
        Self {
            payment_confirm_source: Some(payment_confirm_source),
            ..Default::default()
        }
    }
}


pub struct CaptureTransactionBody {
    amount: StringMajorUnit,
}