                    message: error_code.clone(),
                    reason: Some(error_code),
                    status_code: item.http_code,
                    attempt_status: None,
                    connector_transaction_id: None,
                    network_advice_code: None,
                    network_decline_code: None,
                    network_error_message: None,
                    connector_metadata: None,
                });
                (item.data.status, response)
            }
            (Some(_), Some(_)) | (None, None) => {
                Err(errors::ConnectorError::ResponseHandlingFailed)?
            }
        };

        Ok(Self {
            status,
            response,
            ..item.data
        })
    }
}

pub fn build_refund_sync_request(item: &RefundSyncRouterData) -> Result<Vec<u8>, Error> {
    let transaction_type = transaction_type::REFUND.to_owned();
    let auth = RedsysAuthType::try_from(&item.connector_auth_type)?;
    let connector_transaction_id = item.request.connector_transaction_id.clone();
    construct_sync_request(connector_transaction_id, transaction_type, auth)
}

impl TryFrom<RefundsResponseRouterData<RSync, RedsysSyncResponse>> for RefundsRouterData<RSync> {
    type Error = Error;
    fn try_from(
        item: RefundsResponseRouterData<RSync, RedsysSyncResponse>,
    ) -> Result<Self, Self::Error> {
        let message_data = item
            .response
            .body
            .consultaoperacionesresponse
            .consultaoperacionesreturn
            .messages
            .version
            .message;
        let response = match (message_data.response, message_data.errormsg) {
            (None, Some(errormsg)) => {
                let error_code = errormsg.ds_errorcode.clone();
                Err(ErrorResponse {
                    code: error_code.clone(),
                    message: error_code.clone(),
                    reason: Some(error_code),
                    status_code: item.http_code,
                    attempt_status: None,
                    connector_transaction_id: None,
                    network_advice_code: None,
                    network_decline_code: None,
                    network_error_message: None,
                    connector_metadata: None,
                })
            }
            (Some(response), None) => {
                if let Some(ds_response) = response.ds_response {
                    let refund_status = enums::RefundStatus::try_from(ds_response.clone())?;

                    if connector_utils::is_refund_failure(refund_status) {
                        Err(ErrorResponse {
                            status_code: item.http_code,
                            code: ds_response.0.clone(),
                            message: ds_response.0.clone(),
                            reason: Some(ds_response.0.clone()),
                            attempt_status: None,
                            connector_transaction_id: None,
                            network_advice_code: None,
                            network_decline_code: None,
                            network_error_message: None,
                            connector_metadata: None,
                        })
                    } else {
                        Ok(RefundsResponseData {
                            connector_refund_id: response.ds_order,
                            refund_status,
                        })
                    }
                } else {
                    // When the refund is pending
                    Ok(RefundsResponseData {
                        connector_refund_id: response.ds_order,
                        refund_status: enums::RefundStatus::Pending,
                    })
                }
            }
            (Some(_), Some(_)) | (None, None) => {
                Err(errors::ConnectorError::ResponseHandlingFailed)?
            }
        };

        Ok(Self {
            response,
            ..item.data
        })
    }
}


// Struct: PaymentMethodsSessionUpdateInternal
// File: crates/diesel_models/src/payment_methods_session.rs
// Module: diesel_models
// Implementations: 0

pub struct PaymentMethodsSessionUpdateInternal


// Struct: ChargebackData
// File: crates/hyperswitch_connectors/src/connectors/nuvei/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct ChargebackData


// Struct: ThreeDSData
// File: crates/hyperswitch_connectors/src/connectors/unified_authentication_service/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct ThreeDSData


// Struct: MerchantConnectorAccountFeatureMetadata
// File: crates/hyperswitch_domain_models/src/merchant_connector_account.rs
// Module: hyperswitch_domain_models
// Implementations: 0

pub struct MerchantConnectorAccountFeatureMetadata


// Struct: DecisionManagerRequest
// File: crates/api_models/src/conditional_configs.rs
// Module: api_models
// Implementations: 1
// Traits: events::ApiEventMetric

pub struct DecisionManagerRequest


        Ok(Self::Wallet(StripeWallet::GooglepayToken(GooglePayToken {
            token: Secret::new(
                gpay_data
                    .tokenization_data
                    .get_encrypted_google_pay_token()
                    .change_context(ConnectorError::MissingRequiredField {
                        field_name: "gpay wallet_token",
                    })?
                    .as_bytes()
                    .parse_struct::<StripeGpayToken>("StripeGpayToken")
                    .change_context(ConnectorError::InvalidWalletToken {
                        wallet_name: "Google Pay".to_string(),
                    })?
                    .id,
            ),
            payment_type: StripePaymentMethodType::Card,
        })))
    }
}

impl TryFrom<(&PaymentsAuthorizeRouterData, MinorUnit)> for PaymentIntentRequest {
    type Error = error_stack::Report<ConnectorError>;
    fn try_from(data: (&PaymentsAuthorizeRouterData, MinorUnit)) -> Result<Self, Self::Error> {
        let item = data.0;

        let mandate_metadata = item
            .request
            .mandate_id
            .as_ref()
            .and_then(|mandate_id| mandate_id.mandate_reference_id.as_ref())
            .and_then(|reference_id| match reference_id {
                payments::MandateReferenceId::ConnectorMandateId(mandate_data) => {
                    Some(mandate_data.get_mandate_metadata())
                }
                _ => None,
            });

        let (transfer_account_id, charge_type, application_fees) = if let Some(secret_value) =
            mandate_metadata.as_ref().and_then(|s| s.as_ref())
        {
            let json_value = secret_value.clone().expose();

            let parsed: Result<StripeSplitPaymentRequest, _> = serde_json::from_value(json_value);

            match parsed {
                Ok(data) => (
                    data.transfer_account_id,
                    data.charge_type,
                    data.application_fees,
                ),
                Err(_) => (None, None, None),
            }
        } else {
            (None, None, None)
        };

        let payment_method_token = match &item.request.split_payments {
            Some(SplitPaymentsRequest::StripeSplitPayment(_)) => {
                match item.payment_method_token.clone() {
                    Some(PaymentMethodToken::Token(secret)) => Some(secret),
                    _ => None,
                }
            }
            _ => None,
        };

        let amount = data.1;
        let order_id = item.connector_request_reference_id.clone();

        let shipping_address = if payment_method_token.is_some() {
            None
        } else {
            Some(StripeShippingAddress {
                city: item.get_optional_shipping_city(),
                country: item.get_optional_shipping_country(),
                line1: item.get_optional_shipping_line1(),
                line2: item.get_optional_shipping_line2(),
                zip: item.get_optional_shipping_zip(),
                state: item.get_optional_shipping_state(),
                name: item.get_optional_shipping_full_name(),
                phone: item.get_optional_shipping_phone_number(),
            })
        };

        let billing_address = if payment_method_token.is_some() {
            None
        } else {
            Some(StripeBillingAddress {
                city: item.get_optional_billing_city(),
                country: item.get_optional_billing_country(),
                address_line1: item.get_optional_billing_line1(),
                address_line2: item.get_optional_billing_line2(),
                zip_code: item.get_optional_billing_zip(),
                state: item.get_optional_billing_state(),
                name: item.get_optional_billing_full_name(),
                email: item.get_optional_billing_email(),
                phone: item.get_optional_billing_phone_number(),
            })
        };

        let mut payment_method_options = None;

        let (
            mut payment_data,
            payment_method,
            billing_address,
            payment_method_types,
            setup_future_usage,
        ) = if payment_method_token.is_some() {
            (None, None, StripeBillingAddress::default(), None, None)
        } else {
            match item
                .request
                .mandate_id
                .clone()
                .and_then(|mandate_ids| mandate_ids.mandate_reference_id)
            {
                Some(payments::MandateReferenceId::ConnectorMandateId(connector_mandate_ids)) => (
                    None,
                    connector_mandate_ids.get_connector_mandate_id(),
                    StripeBillingAddress::default(),
                    get_payment_method_type_for_saved_payment_method_payment(item)?,
                    None,
                ),
                Some(payments::MandateReferenceId::NetworkMandateId(network_transaction_id)) => {
                    payment_method_options = Some(StripePaymentMethodOptions::Card {
                        mandate_options: None,
                        network_transaction_id: None,
                        mit_exemption: Some(MitExemption {
                            network_transaction_id: Secret::new(network_transaction_id),
                        }),
                    });

                    let payment_data = match item.request.payment_method_data {
                        PaymentMethodData::CardDetailsForNetworkTransactionId(
                            ref card_details_for_network_transaction_id,
                        ) => StripePaymentMethodData::Card(StripeCardData {
                            payment_method_data_type: StripePaymentMethodType::Card,
                            payment_method_data_card_number:
                                card_details_for_network_transaction_id.card_number.clone(),
                            payment_method_data_card_exp_month:
                                card_details_for_network_transaction_id
                                    .card_exp_month
                                    .clone(),
                            payment_method_data_card_exp_year:
                                card_details_for_network_transaction_id
                                    .card_exp_year
                                    .clone(),
                            payment_method_data_card_cvc: None,
                            payment_method_auth_type: None,
                            payment_method_data_card_preferred_network:
                                card_details_for_network_transaction_id
                                    .card_network
                                    .clone()
                                    .and_then(get_stripe_card_network),
                            request_incremental_authorization: None,
                            request_extended_authorization: None,
                            request_overcapture: None,
                        }),
                        PaymentMethodData::CardRedirect(_)
                        | PaymentMethodData::Wallet(_)
                        | PaymentMethodData::PayLater(_)
                        | PaymentMethodData::BankRedirect(_)
                        | PaymentMethodData::BankDebit(_)
                        | PaymentMethodData::BankTransfer(_)
                        | PaymentMethodData::Crypto(_)
                        | PaymentMethodData::MandatePayment
                        | PaymentMethodData::Reward
                        | PaymentMethodData::RealTimePayment(_)
                        | PaymentMethodData::MobilePayment(_)
                        | PaymentMethodData::Upi(_)
                        | PaymentMethodData::Voucher(_)
                        | PaymentMethodData::GiftCard(_)
                        | PaymentMethodData::OpenBanking(_)
                        | PaymentMethodData::CardToken(_)
                        | PaymentMethodData::NetworkToken(_)
                        | PaymentMethodData::Card(_) => Err(ConnectorError::NotSupported {
                            message: "Network tokenization for payment method".to_string(),
                            connector: "Stripe",
                        })?,
                    };

                    (
                        Some(payment_data),
                        None,
                        StripeBillingAddress::default(),
                        None,
                        None,
                    )
                }
                Some(payments::MandateReferenceId::NetworkTokenWithNTI(_)) | None => {
                    let (payment_method_data, payment_method_type, billing_address) =
                        create_stripe_payment_method(
                            &item.request.payment_method_data,
                            PaymentRequestDetails {
                                auth_type : item.auth_type,
                                payment_method_token: item.payment_method_token.clone(),
                                is_customer_initiated_mandate_payment: Some(
                                PaymentsAuthorizeRequestData::is_customer_initiated_mandate_payment(
                                    &item.request,
                                ),
                            ),
                            billing_address: billing_address.ok_or_else(|| {
                                ConnectorError::MissingRequiredField {
                                    field_name: "billing_address",
                                }
                            })?,
                            request_incremental_authorization: item.request.request_incremental_authorization,
                            request_extended_authorization: item.request.request_extended_authorization,
                            request_overcapture: item.request
                                .enable_overcapture
                                .and_then(get_stripe_overcapture_request),
                })?;

                    validate_shipping_address_against_payment_method(
                        &shipping_address,
                        payment_method_type.as_ref(),
                    )?;

                    (
                        Some(payment_method_data),
                        None,
                        billing_address,
                        payment_method_type,
                        item.request.setup_future_usage,
                    )
                }
            }
        };

        if payment_method_token.is_none() {
            payment_data = match item.request.payment_method_data {
                PaymentMethodData::Wallet(WalletData::ApplePay(_)) => {
                    let payment_method_token = item
                        .payment_method_token
                        .to_owned()
                        .get_required_value("payment_token")
                        .change_context(ConnectorError::InvalidWalletToken {
                            wallet_name: "Apple Pay".to_string(),
                        })?;

                    let payment_method_token = match payment_method_token {
                        PaymentMethodToken::Token(payment_method_token) => payment_method_token,
                        PaymentMethodToken::ApplePayDecrypt(_) => {
                            Err(ConnectorError::InvalidWalletToken {
                                wallet_name: "Apple Pay".to_string(),
                            })?
                        }
                        PaymentMethodToken::PazeDecrypt(_) => {
                            Err(crate::unimplemented_payment_method!("Paze", "Stripe"))?
                        }
                        PaymentMethodToken::GooglePayDecrypt(_) => {
                            Err(crate::unimplemented_payment_method!("Google Pay", "Stripe"))?
                        }
                    };
                    Some(StripePaymentMethodData::Wallet(
                        StripeWallet::ApplepayPayment(ApplepayPayment {
                            token: payment_method_token,
                            payment_method_types: StripePaymentMethodType::Card,
                        }),
                    ))
                }
                _ => payment_data,
            }
        } else {
            payment_data = None
        };

        let setup_mandate_details = item
            .request
            .setup_mandate_details
            .as_ref()
            .and_then(|mandate_details| {
                mandate_details
                    .customer_acceptance
                    .as_ref()
                    .map(|customer_acceptance| {
                        Ok::<_, error_stack::Report<ConnectorError>>(
                            match customer_acceptance.acceptance_type {
                                AcceptanceType::Online => {
                                    let online_mandate = customer_acceptance
                                        .online
                                        .clone()
                                        .get_required_value("online")
                                        .change_context(ConnectorError::MissingRequiredField {
                                            field_name: "online",
                                        })?;
                                    StripeMandateRequest {
                                        mandate_type: StripeMandateType::Online {
                                            ip_address: online_mandate
                                                .ip_address
                                                .get_required_value("ip_address")
                                                .change_context(
                                                    ConnectorError::MissingRequiredField {
                                                        field_name: "ip_address",
                                                    },
                                                )?,
                                            user_agent: online_mandate.user_agent,
                                        },
                                    }
                                }
                                AcceptanceType::Offline => StripeMandateRequest {
                                    mandate_type: StripeMandateType::Offline,
                                },
                            },
                        )
                    })
            })
            .transpose()?
            .or_else(|| {
                //stripe requires us to send mandate_data while making recurring payment through saved bank debit
                if payment_method.is_some() {
                    //check if payment is done through saved payment method
                    match &payment_method_types {
                        //check if payment method is bank debit
                        Some(
                            StripePaymentMethodType::Ach
                            | StripePaymentMethodType::Sepa
                            | StripePaymentMethodType::Becs
                            | StripePaymentMethodType::Bacs,
                        ) => Some(StripeMandateRequest {
                            mandate_type: StripeMandateType::Offline,
                        }),
                        _ => None,
                    }
                } else {
                    None
                }
            });

        let meta_data =
            get_transaction_metadata(item.request.metadata.clone().map(Into::into), order_id);

        // We pass browser_info only when payment_data exists.
        // Hence, we're pass Null during recurring payments as payment_method_data[type] is not passed
        let browser_info = if payment_data.is_some() && payment_method_token.is_none() {
            item.request
                .browser_info
                .clone()
                .map(StripeBrowserInformation::from)
        } else {
            None
        };

        let charges = match &item.request.split_payments {
            Some(SplitPaymentsRequest::StripeSplitPayment(stripe_split_payment)) => {
                match &stripe_split_payment.charge_type {
                    PaymentChargeType::Stripe(charge_type) => match charge_type {
                        StripeChargeType::Direct => Some(IntentCharges {
                            application_fee_amount: stripe_split_payment.application_fees,
                            destination_account_id: None,
                        }),
                        StripeChargeType::Destination => Some(IntentCharges {
                            application_fee_amount: stripe_split_payment.application_fees,
                            destination_account_id: Some(
                                stripe_split_payment.transfer_account_id.clone(),
                            ),
                        }),
                    },
                }
            }
            Some(SplitPaymentsRequest::AdyenSplitPayment(_))
            | Some(SplitPaymentsRequest::XenditSplitPayment(_))
            | None => None,
        };

        let charges_in = if charges.is_none() {
            match charge_type {
                Some(PaymentChargeType::Stripe(StripeChargeType::Direct)) => Some(IntentCharges {
                    application_fee_amount: application_fees, // default to 0 if None
                    destination_account_id: None,
                }),
                Some(PaymentChargeType::Stripe(StripeChargeType::Destination)) => {
                    Some(IntentCharges {
                        application_fee_amount: application_fees,
                        destination_account_id: transfer_account_id,
                    })
                }
                _ => None,
            }
        } else {
            charges
        };

        let pm = match (payment_method, payment_method_token.clone()) {
            (Some(method), _) => Some(Secret::new(method)),
            (None, Some(token)) => Some(token),
            (None, None) => None,
        };

        Ok(Self {
            amount,                                      //hopefully we don't loose some cents here
            currency: item.request.currency.to_string(), //we need to copy the value and not transfer ownership
            statement_descriptor_suffix: item.request.statement_descriptor_suffix.clone(),
            statement_descriptor: item.request.statement_descriptor.clone(),
            meta_data,
            return_url: item
                .request
                .router_return_url
                .clone()
                .unwrap_or_else(|| "https://juspay.in/".to_string()),
            confirm: true, // Stripe requires confirm to be true if return URL is present
            description: item.description.clone(),
            shipping: shipping_address,
            billing: billing_address,
            capture_method: StripeCaptureMethod::from(item.request.capture_method),
            payment_data,
            payment_method_options,
            payment_method: pm,
            customer: item.connector_customer.clone().map(Secret::new),
            setup_mandate_details,
            off_session: item.request.off_session,
            setup_future_usage: match (
                item.request.split_payments.as_ref(),
                item.request.setup_future_usage,
                item.request.customer_acceptance.as_ref(),
            ) {
                (Some(_), Some(usage), Some(_)) => Some(usage),
                _ => setup_future_usage,
            },

            payment_method_types,
            expand: Some(ExpandableObjects::LatestCharge),
            browser_info,
            charges: charges_in,
        })
    }
}

fn get_stripe_overcapture_request(
    enable_overcapture: primitive_wrappers::EnableOvercaptureBool,
) -> Option<StripeRequestOvercaptureBool> {
    match enable_overcapture.deref() {
        true => Some(StripeRequestOvercaptureBool::IfAvailable),
        false => None,
    }
}

fn get_payment_method_type_for_saved_payment_method_payment(
    item: &PaymentsAuthorizeRouterData,
) -> Result<Option<StripePaymentMethodType>, error_stack::Report<ConnectorError>> {
    if item.payment_method == api_enums::PaymentMethod::Card {
        Ok(Some(StripePaymentMethodType::Card)) //stripe takes ["Card"] as default
    } else {
        let stripe_payment_method_type = match item.recurring_mandate_payment_data.clone() {
            Some(recurring_payment_method_data) => {
                match recurring_payment_method_data.payment_method_type {
                    Some(payment_method_type) => {
                        StripePaymentMethodType::try_from(payment_method_type)
                    }
                    None => Err(ConnectorError::MissingRequiredField {
                        field_name: "payment_method_type",
                    }
                    .into()),
                }
            }
            None => Err(ConnectorError::MissingRequiredField {
                field_name: "recurring_mandate_payment_data",
            }
            .into()),
        }?;
        match stripe_payment_method_type {
            //Stripe converts Ideal, Bancontact & Sofort Bank redirect methods to Sepa direct debit and attaches to the customer for future usage
            StripePaymentMethodType::Ideal
            | StripePaymentMethodType::Bancontact
            | StripePaymentMethodType::Sofort => Ok(Some(StripePaymentMethodType::Sepa)),
            _ => Ok(Some(stripe_payment_method_type)),
        }
    }
}

impl From<BrowserInformation> for StripeBrowserInformation {
    fn from(item: BrowserInformation) -> Self {
        Self {
            ip_address: item.ip_address.map(|ip| Secret::new(ip.to_string())),
            user_agent: item.user_agent,
        }
    }
}

impl TryFrom<&SetupMandateRouterData> for SetupIntentRequest {
    type Error = error_stack::Report<ConnectorError>;
    fn try_from(item: &SetupMandateRouterData) -> Result<Self, Self::Error> {
        //Only cards supported for mandates
        let pm_type = StripePaymentMethodType::Card;
        let payment_data = StripePaymentMethodData::try_from((item, item.auth_type, pm_type))?;

        let meta_data = Some(get_transaction_metadata(
            item.request.metadata.clone(),
            item.connector_request_reference_id.clone(),
        ));

        let browser_info = item
            .request
            .browser_info
            .clone()
            .map(StripeBrowserInformation::from);

        Ok(Self {
            confirm: true,
            payment_data,
            return_url: item.request.router_return_url.clone(),
            off_session: item.request.off_session,
            usage: item.request.setup_future_usage,
            payment_method_options: None,
            customer: item.connector_customer.to_owned().map(Secret::new),
            meta_data,
            payment_method_types: Some(pm_type),
            expand: Some(ExpandableObjects::LatestAttempt),
            browser_info,
        })
    }
}

impl TryFrom<&TokenizationRouterData> for TokenRequest {
    type Error = error_stack::Report<ConnectorError>;
    fn try_from(item: &TokenizationRouterData) -> Result<Self, Self::Error> {
        let billing_address = StripeBillingAddressCardToken {
            name: item.get_optional_billing_full_name(),
            email: item.get_optional_billing_email(),
            phone: item.get_optional_billing_phone_number(),
            address_line1: item.get_optional_billing_line1(),
            address_line2: item.get_optional_billing_line2(),
            city: item.get_optional_billing_city(),
            state: item.get_optional_billing_state(),
        };

        // Card flow for tokenization is handled separately because of API contact difference
        let request_payment_data = match &item.request.payment_method_data {
            PaymentMethodData::Card(card_details) => {
                StripePaymentMethodData::CardToken(StripeCardToken {
                    payment_method_type: Some(StripePaymentMethodType::Card),
                    token_card_number: card_details.card_number.clone(),
                    token_card_exp_month: card_details.card_exp_month.clone(),
                    token_card_exp_year: card_details.card_exp_year.clone(),
                    token_card_cvc: card_details.card_cvc.clone(),
                    billing: billing_address,
                })
            }
            _ => {
                create_stripe_payment_method(
                    &item.request.payment_method_data,
                    PaymentRequestDetails {
                        auth_type: item.auth_type,
                        payment_method_token: item.payment_method_token.clone(),
                        is_customer_initiated_mandate_payment: None,
                        billing_address: StripeBillingAddress::default(),
                        request_incremental_authorization: false,
                        request_extended_authorization: None,
                        request_overcapture: None,
                    },
                )?
                .0
            }
        };

        Ok(Self {
            token_data: request_payment_data,
        })
    }
}

impl TryFrom<&ConnectorCustomerRouterData> for CustomerRequest {
    type Error = error_stack::Report<ConnectorError>;
    fn try_from(item: &ConnectorCustomerRouterData) -> Result<Self, Self::Error> {
        Ok(Self {
            description: item.request.description.to_owned(),
            email: item.request.email.to_owned(),
            phone: item.request.phone.to_owned(),
            name: item.request.name.to_owned(),
            source: item.request.preprocessing_id.to_owned().map(Secret::new),
        })
    }
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct StripeSplitPaymentRequest {
    pub charge_type: Option<PaymentChargeType>,
    pub application_fees: Option<MinorUnit>,
    pub transfer_account_id: Option<String>,
}

impl TryFrom<&PaymentsAuthorizeRouterData> for StripeSplitPaymentRequest {
    type Error = error_stack::Report<ConnectorError>;

    fn try_from(item: &PaymentsAuthorizeRouterData) -> Result<Self, Self::Error> {
        //extracting mandate metadata from CIT call if CIT call was a Split Payment
        let from_metadata = item
            .request
            .mandate_id
            .as_ref()
            .and_then(|mandate_id| mandate_id.mandate_reference_id.as_ref())
            .and_then(|reference_id| match reference_id {
                payments::MandateReferenceId::ConnectorMandateId(mandate_data) => {
                    mandate_data.get_mandate_metadata()
                }
                _ => None,
            })
            .and_then(|secret_value| {
                let json_value = secret_value.clone().expose();
                match serde_json::from_value::<Self>(json_value.clone()) {
                    Ok(val) => Some(val),
                    Err(err) => {
                        router_env::logger::info!(
                            "STRIPE: Picking merchant_account_id and merchant_config_currency from payments request: {:?}", err
                        );
                        None
                    }
                }
            });

        // If the Split Payment Request in MIT mismatches with the metadata from CIT, throw an error
        if from_metadata.is_some() && item.request.split_payments.is_some() {
            let mut mit_charge_type = None;
            let mut mit_application_fees = None;
            let mut mit_transfer_account_id = None;
            if let Some(SplitPaymentsRequest::StripeSplitPayment(stripe_split_payment)) =
                item.request.split_payments.as_ref()
            {
                mit_charge_type = Some(stripe_split_payment.charge_type.clone());
                mit_application_fees = stripe_split_payment.application_fees;
                mit_transfer_account_id = Some(stripe_split_payment.transfer_account_id.clone());
            }

            if mit_charge_type != from_metadata.as_ref().and_then(|m| m.charge_type.clone())
                || mit_application_fees != from_metadata.as_ref().and_then(|m| m.application_fees)
                || mit_transfer_account_id
                    != from_metadata
                        .as_ref()
                        .and_then(|m| m.transfer_account_id.clone())
            {
                let mismatched_fields = ["transfer_account_id", "application_fees", "charge_type"];

                let field_str = mismatched_fields.join(", ");
                return Err(error_stack::Report::from(
                    ConnectorError::MandatePaymentDataMismatch { fields: field_str },
                ));
            }
        }

        // If Mandate Metadata from CIT call has something, populate it
        let (charge_type, mut transfer_account_id, application_fees) =
            if let Some(ref metadata) = from_metadata {
                (
                    metadata.charge_type.clone(),
                    metadata.transfer_account_id.clone(),
                    metadata.application_fees,
                )
            } else {
                (None, None, None)
            };

        // If Charge Type is Destination, transfer_account_id need not be appended in headers
        if charge_type == Some(PaymentChargeType::Stripe(StripeChargeType::Destination)) {
            transfer_account_id = None;
        }
        Ok(Self {
            charge_type,
            transfer_account_id,
            application_fees,
        })
    }
}

#[derive(Debug, Serialize)]
pub struct StripeIncrementalAuthRequest {
    pub amount: MinorUnit,
}

#[derive(Clone, Default, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum StripePaymentStatus {
    Succeeded,
    Failed,
    #[default]
    Processing,
    #[serde(rename = "requires_action")]
    RequiresCustomerAction,
    #[serde(rename = "requires_payment_method")]
    RequiresPaymentMethod,
    RequiresConfirmation,
    Canceled,
    RequiresCapture,
    Chargeable,
    Consumed,
    Pending,
}

impl From<StripePaymentStatus> for AttemptStatus {
    fn from(item: StripePaymentStatus) -> Self {
        match item {
            StripePaymentStatus::Succeeded => Self::Charged,
            StripePaymentStatus::Failed => Self::Failure,
            StripePaymentStatus::Processing => Self::Authorizing,
            StripePaymentStatus::RequiresCustomerAction => Self::AuthenticationPending,
            // Make the payment attempt status as failed
            StripePaymentStatus::RequiresPaymentMethod => Self::Failure,
            StripePaymentStatus::RequiresConfirmation => Self::ConfirmationAwaited,
            StripePaymentStatus::Canceled => Self::Voided,
            StripePaymentStatus::RequiresCapture => Self::Authorized,
            StripePaymentStatus::Chargeable => Self::Authorizing,
            StripePaymentStatus::Consumed => Self::Authorizing,
            StripePaymentStatus::Pending => Self::Pending,
        }
    }
}

#[derive(Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
pub struct PaymentIntentResponse {
    pub id: String,
    pub object: String,
    pub amount: MinorUnit,
    #[serde(default, deserialize_with = "deserialize_zero_minor_amount_as_none")]
    // stripe gives amount_captured as 0 for payment intents instead of null
    pub amount_received: Option<MinorUnit>,
    pub amount_capturable: Option<MinorUnit>,
    pub currency: String,
    pub status: StripePaymentStatus,
    pub client_secret: Option<Secret<String>>,
    pub created: i32,
    pub customer: Option<Secret<String>>,
    pub payment_method: Option<Secret<String>>,
    pub description: Option<String>,
    pub statement_descriptor: Option<String>,
    pub statement_descriptor_suffix: Option<String>,
    pub metadata: StripeMetadata,
    pub next_action: Option<StripeNextActionResponse>,
    pub payment_method_options: Option<StripePaymentMethodOptions>,
    pub last_payment_error: Option<ErrorDetails>,
    pub latest_attempt: Option<LatestAttempt>, //need a merchant to test this
    pub latest_charge: Option<StripeChargeEnum>,
}

#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
pub struct StripeSourceResponse {
    pub id: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub ach_credit_transfer: Option<AchCreditTransferResponse>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub multibanco: Option<MultibancoCreditTansferResponse>,
    pub receiver: AchReceiverDetails,
    pub status: StripePaymentStatus,
}

#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
pub struct AchCreditTransferResponse {
    pub account_number: Secret<String>,
    pub bank_name: Secret<String>,
    pub routing_number: Secret<String>,
    pub swift_code: Secret<String>,
}

#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
pub struct MultibancoCreditTansferResponse {
    pub reference: Secret<String>,
    pub entity: Secret<String>,
}

#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
pub struct AchReceiverDetails {
    pub amount_received: MinorUnit,
    pub amount_charged: MinorUnit,
}

#[serde_with::skip_serializing_none]
#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
pub struct SepaAndBacsBankTransferInstructions {
    pub bacs_bank_instructions: Option<BacsFinancialDetails>,
    pub sepa_bank_instructions: Option<SepaFinancialDetails>,
    pub receiver: SepaAndBacsReceiver,
}

#[serde_with::skip_serializing_none]
#[derive(Clone, Debug, Serialize)]
pub struct QrCodeNextInstructions {
    pub image_data_url: Url,
    pub display_to_timestamp: Option<i64>,
}

#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
pub struct SepaAndBacsReceiver {
    pub amount_received: MinorUnit,
    pub amount_remaining: MinorUnit,
}

#[derive(Debug, Default, Eq, PartialEq, Deserialize)]
pub struct PaymentSyncResponse {
    #[serde(flatten)]
    pub intent_fields: PaymentIntentResponse,
    pub last_payment_error: Option<ErrorDetails>,
}

impl Deref for PaymentSyncResponse {
    type Target = PaymentIntentResponse;

    fn deref(&self) -> &Self::Target {
        &self.intent_fields
    }
}

#[derive(Deserialize, Debug, Serialize)]
pub struct PaymentIntentSyncResponse {
    #[serde(flatten)]
    payment_intent_fields: PaymentIntentResponse,
    pub latest_charge: Option<StripeChargeEnum>,
}

#[derive(Debug, Eq, PartialEq, Deserialize, Clone, Serialize)]
#[serde(untagged)]
pub enum StripeChargeEnum {
    ChargeId(String),
    ChargeObject(Box<StripeCharge>),
}

impl StripeChargeEnum {
    pub fn get_overcapture_status(&self) -> Option<primitive_wrappers::OvercaptureEnabledBool> {
        match self {
            Self::ChargeObject(charge_object) => charge_object
                .payment_method_details
                .as_ref()
                .and_then(|payment_method_details| match payment_method_details {
                    StripePaymentMethodDetailsResponse::Card { card } => card
                        .overcapture
                        .as_ref()
                        .and_then(|overcapture| match overcapture.status {
                            Some(StripeOvercaptureStatus::Available) => {
                                Some(primitive_wrappers::OvercaptureEnabledBool::new(true))
                            }
                            Some(StripeOvercaptureStatus::Unavailable) => {
                                Some(primitive_wrappers::OvercaptureEnabledBool::new(false))
                            }
                            None => None,
                        }),
                    _ => None,
                }),
            _ => None,
        }
    }

    pub fn get_maximum_capturable_amount(&self) -> Option<MinorUnit> {
        match self {
            Self::ChargeObject(charge_object) => {
                if let Some(payment_method_details) = charge_object.payment_method_details.as_ref()
                {
                    match payment_method_details {
                        StripePaymentMethodDetailsResponse::Card { card } => card
                            .overcapture
                            .as_ref()
                            .and_then(|overcapture| overcapture.maximum_amount_capturable),
                        _ => None,
                    }
                } else {
                    None
                }
            }
            _ => None,
        }
    }
}

#[derive(Deserialize, Clone, Debug, PartialEq, Eq, Serialize)]
pub struct StripeCharge {
    pub id: String,
    pub payment_method_details: Option<StripePaymentMethodDetailsResponse>,
}

#[derive(Deserialize, Clone, Debug, PartialEq, Eq, Serialize)]
pub struct StripeBankRedirectDetails {
    #[serde(rename = "generated_sepa_debit")]
    attached_payment_method: Option<Secret<String>>,
}

#[derive(Deserialize, Clone, Debug, PartialEq, Eq, Serialize)]
pub struct StripeCashappDetails {
    buyer_id: Option<String>,
    cashtag: Option<String>,
}

impl Deref for PaymentIntentSyncResponse {
    type Target = PaymentIntentResponse;

    fn deref(&self) -> &Self::Target {
        &self.payment_intent_fields
    }
}

#[derive(Deserialize, Clone, Debug, PartialEq, Eq, Serialize)]
pub struct StripeAdditionalCardDetails {
    checks: Option<Value>,
    three_d_secure: Option<Value>,
    network_transaction_id: Option<String>,
    extended_authorization: Option<StripeExtendedAuthorizationResponse>,
    #[serde(default, with = "common_utils::custom_serde::timestamp::option")]
    capture_before: Option<PrimitiveDateTime>,
    overcapture: Option<StripeOvercaptureResponse>,
}

#[derive(Deserialize, Clone, Debug, PartialEq, Eq, Serialize)]
pub struct StripeExtendedAuthorizationResponse {
    status: Option<StripeExtendedAuthorizationStatus>,
}

#[derive(Deserialize, Clone, Debug, PartialEq, Eq, Serialize)]
#[serde(rename_all = "lowercase")]
pub enum StripeExtendedAuthorizationStatus {
    Disabled,
    Enabled,
}

#[derive(Deserialize, Clone, Debug, PartialEq, Eq, Serialize)]
pub struct StripeOvercaptureResponse {
    status: Option<StripeOvercaptureStatus>,
    #[serde(default, deserialize_with = "deserialize_zero_minor_amount_as_none")]
    // stripe gives amount_captured as 0 for payment intents instead of null
    maximum_amount_capturable: Option<MinorUnit>,
}

#[derive(Deserialize, Clone, Debug, PartialEq, Eq, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum StripeOvercaptureStatus {
    Available,
    Unavailable,
}

#[derive(Deserialize, Clone, Debug, PartialEq, Eq, Serialize)]
#[serde(rename_all = "snake_case", tag = "type")]
pub enum StripePaymentMethodDetailsResponse {
    //only ideal and bancontact is supported by stripe for recurring payment in bank redirect
    Ideal {
        ideal: StripeBankRedirectDetails,
    },
    Bancontact {
        bancontact: StripeBankRedirectDetails,
    },

    //other payment method types supported by stripe. To avoid deserialization error.
    Blik,
    Eps,
    Fpx,
    Giropay,
    #[serde(rename = "p24")]
    Przelewy24,
    Card {
        card: StripeAdditionalCardDetails,
    },
    Cashapp {
        cashapp: StripeCashappDetails,
    },
    Klarna,
    Affirm,
    AfterpayClearpay,
    AmazonPay,
    ApplePay,
    #[serde(rename = "us_bank_account")]
    Ach,
    #[serde(rename = "sepa_debit")]
    Sepa,
    #[serde(rename = "au_becs_debit")]
    Becs,
    #[serde(rename = "bacs_debit")]
    Bacs,
    #[serde(rename = "wechat_pay")]
    Wechatpay,
    Alipay,
    CustomerBalance,
    RevolutPay,
}

pub struct AdditionalPaymentMethodDetails {
    pub payment_checks: Option<Value>,
    pub authentication_details: Option<Value>,
    pub extended_authorization: Option<StripeExtendedAuthorizationResponse>,
    pub capture_before: Option<PrimitiveDateTime>,
}

impl From<&AdditionalPaymentMethodDetails> for AdditionalPaymentMethodConnectorResponse {
    fn from(item: &AdditionalPaymentMethodDetails) -> Self {
        Self::Card {
            authentication_data: item.authentication_details.clone(),
            payment_checks: item.payment_checks.clone(),
            card_network: None,
            domestic_network: None,
        }
    }
}

impl From<&AdditionalPaymentMethodDetails> for ExtendedAuthorizationResponseData {
    fn from(item: &AdditionalPaymentMethodDetails) -> Self {
        Self {
            extended_authentication_applied: item.extended_authorization.as_ref().map(
                |extended_authorization| {
                    primitive_wrappers::ExtendedAuthorizationAppliedBool::from(matches!(
                        extended_authorization.status,
                        Some(StripeExtendedAuthorizationStatus::Enabled)
                    ))
                },
            ),
            capture_before: item.capture_before,
        }
    }
}

impl StripePaymentMethodDetailsResponse {
    pub fn get_additional_payment_method_data(&self) -> Option<AdditionalPaymentMethodDetails> {
        match self {
            Self::Card { card } => Some(AdditionalPaymentMethodDetails {
                payment_checks: card.checks.clone(),
                authentication_details: card.three_d_secure.clone(),
                extended_authorization: card.extended_authorization.clone(),
                capture_before: card.capture_before,
            }),
            Self::Ideal { .. }
            | Self::Bancontact { .. }
            | Self::Blik
            | Self::Eps
            | Self::Fpx
            | Self::Giropay
            | Self::Przelewy24
            | Self::Klarna
            | Self::Affirm
            | Self::AfterpayClearpay
            | Self::AmazonPay
            | Self::ApplePay
            | Self::Ach
            | Self::Sepa
            | Self::Becs
            | Self::Bacs
            | Self::Wechatpay
            | Self::Alipay
            | Self::CustomerBalance
            | Self::RevolutPay
            | Self::Cashapp { .. } => None,
        }
    }
}

#[derive(Deserialize)]
pub struct SetupIntentSyncResponse {
    #[serde(flatten)]
    setup_intent_fields: SetupIntentResponse,
}

impl Deref for SetupIntentSyncResponse {
    type Target = SetupIntentResponse;

    fn deref(&self) -> &Self::Target {
        &self.setup_intent_fields
    }
}

impl From<SetupIntentSyncResponse> for PaymentIntentSyncResponse {
    fn from(value: SetupIntentSyncResponse) -> Self {
        Self {
            payment_intent_fields: value.setup_intent_fields.into(),
            latest_charge: None,
        }
    }
}

impl From<SetupIntentResponse> for PaymentIntentResponse {
    fn from(value: SetupIntentResponse) -> Self {
        Self {
            id: value.id,
            object: value.object,
            status: value.status,
            client_secret: Some(value.client_secret),
            customer: value.customer,
            description: None,
            statement_descriptor: value.statement_descriptor,
            statement_descriptor_suffix: value.statement_descriptor_suffix,
            metadata: value.metadata,
            next_action: value.next_action,
            payment_method_options: value.payment_method_options,
            last_payment_error: value.last_setup_error,
            ..Default::default()
        }
    }
}

#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
pub struct SetupIntentResponse {
    pub id: String,
    pub object: String,
    pub status: StripePaymentStatus, // Change to SetupStatus
    pub client_secret: Secret<String>,
    pub customer: Option<Secret<String>>,
    pub payment_method: Option<String>,
    pub statement_descriptor: Option<String>,
    pub statement_descriptor_suffix: Option<String>,
    pub metadata: StripeMetadata,
    pub next_action: Option<StripeNextActionResponse>,
    pub payment_method_options: Option<StripePaymentMethodOptions>,
    pub latest_attempt: Option<LatestAttempt>,
    pub last_setup_error: Option<ErrorDetails>,
}

fn extract_payment_method_connector_response_from_latest_charge(
    stripe_charge_enum: &StripeChargeEnum,
) -> Option<ConnectorResponseData> {
    let is_overcapture_enabled = stripe_charge_enum.get_overcapture_status();
    let additional_payment_method_details =
        if let StripeChargeEnum::ChargeObject(charge_object) = stripe_charge_enum {
            charge_object
                .payment_method_details
                .as_ref()


// Struct: SellerStatusDetailsResponse
// File: crates/router/src/types/api/connector_onboarding/paypal.rs
// Module: router
// Implementations: 1

pub struct SellerStatusDetailsResponse


// Struct: RefundFilterValue
// File: crates/api_models/src/analytics.rs
// Module: api_models
// Implementations: 0

pub struct RefundFilterValue


// Struct: BokuPsyncResponse
// File: crates/hyperswitch_connectors/src/connectors/boku/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct BokuPsyncResponse


// Function: invoke_lambda
// File: crates/analytics/src/lambda_utils.rs
// Module: analytics

pub fn invoke_lambda(
    function_name: &str,
    region: &str,
    json_bytes: &[u8],
) -> CustomResult<(), AnalyticsError>


// Function: customer_create
// File: crates/router/src/compatibility/stripe/customers.rs
// Module: router

pub fn customer_create(
    state: web::Data<routes::AppState>,
    qs_config: web::Data<serde_qs::Config>,
    req: HttpRequest,
    form_payload: web::Bytes,
) -> HttpResponse


// Function: get_profile_refund_filters
// File: crates/router/src/analytics.rs
// Module: router

pub fn get_profile_refund_filters(
        state: web::Data<AppState>,
        req: actix_web::HttpRequest,
        json_payload: web::Json<GetRefundFilterRequest>,
    ) -> impl Responder


// File: crates/router/src/core/payment_methods/tokenize/payment_method_executor.rs
// Module: router
// Public functions: 12
// Public structs: 7

use api_models::enums as api_enums;
use common_utils::{
    ext_traits::OptionExt, fp_utils::when, pii::Email, types::keymanager::KeyManagerState,
};
use error_stack::{report, ResultExt};
use masking::Secret;
use router_env::logger;

use super::{
    CardNetworkTokenizeExecutor, NetworkTokenizationBuilder, NetworkTokenizationProcess,
    NetworkTokenizationResponse, State, TransitionTo,
};
use crate::{
    core::payment_methods::transformers as pm_transformers,
    errors::{self, RouterResult},
    types::{api, domain},
};

// Available states for payment method tokenization
pub struct TokenizeWithPmId;
pub struct PmValidated;
pub struct PmFetched;
pub struct PmAssigned;
pub struct PmTokenized;
pub struct PmTokenStored;
pub struct PmTokenUpdated;

impl State for TokenizeWithPmId {}
impl State for PmValidated {}
impl State for PmFetched {}
impl State for PmAssigned {}
impl State for PmTokenized {}
impl State for PmTokenStored {}
impl State for PmTokenUpdated {}

// State transitions for payment method tokenization
impl TransitionTo<PmFetched> for TokenizeWithPmId {}
impl TransitionTo<PmValidated> for PmFetched {}
impl TransitionTo<PmAssigned> for PmValidated {}
impl TransitionTo<PmTokenized> for PmAssigned {}
impl TransitionTo<PmTokenStored> for PmTokenized {}
impl TransitionTo<PmTokenUpdated> for PmTokenStored {}

impl Default for NetworkTokenizationBuilder<'_, TokenizeWithPmId> {
    fn default() -> Self {
        Self::new()
    }
}

impl<'a> NetworkTokenizationBuilder<'a, TokenizeWithPmId> {
    pub fn new() -> Self {
        Self {
            state: std::marker::PhantomData,
            customer: None,
            card: None,
            card_cvc: None,
            network_token: None,
            stored_card: None,
            stored_token: None,
            payment_method_response: None,
            card_tokenized: false,
            error_code: None,
            error_message: None,
        }
    }
    pub fn set_payment_method(
        self,
        payment_method: &domain::PaymentMethod,
    ) -> NetworkTokenizationBuilder<'a, PmFetched> {
        let payment_method_response = api::PaymentMethodResponse {
            merchant_id: payment_method.merchant_id.clone(),
            customer_id: Some(payment_method.customer_id.clone()),
            payment_method_id: payment_method.payment_method_id.clone(),
            payment_method: payment_method.payment_method,
            payment_method_type: payment_method.payment_method_type,
            recurring_enabled: Some(true),
            installment_payment_enabled: Some(false),
            metadata: payment_method.metadata.clone(),
            created: Some(payment_method.created_at),
            last_used_at: Some(payment_method.last_used_at),
            client_secret: payment_method.client_secret.clone(),
            card: None,
            bank_transfer: None,
            payment_experience: None,
        };
        NetworkTokenizationBuilder {
            state: std::marker::PhantomData,
            payment_method_response: Some(payment_method_response),
            customer: self.customer,
            card: self.card,
            card_cvc: self.card_cvc,
            network_token: self.network_token,
            stored_card: self.stored_card,
            stored_token: self.stored_token,
            card_tokenized: self.card_tokenized,
            error_code: self.error_code,
            error_message: self.error_message,
        }
    }
}

impl<'a> NetworkTokenizationBuilder<'a, PmFetched> {
    pub fn set_validate_result(
        self,
        customer: &'a api::CustomerDetails,
    ) -> NetworkTokenizationBuilder<'a, PmValidated> {
        NetworkTokenizationBuilder {
            state: std::marker::PhantomData,
            customer: Some(customer),
            card: self.card,
            card_cvc: self.card_cvc,
            network_token: self.network_token,
            stored_card: self.stored_card,
            stored_token: self.stored_token,
            payment_method_response: self.payment_method_response,
            card_tokenized: self.card_tokenized,
            error_code: self.error_code,
            error_message: self.error_message,
        }
    }
}

impl<'a> NetworkTokenizationBuilder<'a, PmValidated> {
    pub fn set_card_details(
        self,
        card_from_locker: &'a api_models::payment_methods::Card,
        optional_card_info: Option<diesel_models::CardInfo>,
        card_cvc: Option<Secret<String>>,
    ) -> NetworkTokenizationBuilder<'a, PmAssigned> {
        let card = domain::CardDetail {
            card_number: card_from_locker.card_number.clone(),
            card_exp_month: card_from_locker.card_exp_month.clone(),
            card_exp_year: card_from_locker.card_exp_year.clone(),
            bank_code: optional_card_info
                .as_ref()
                .and_then(|card_info| card_info.bank_code.clone()),
            nick_name: card_from_locker
                .nick_name
                .as_ref()
                .map(|nick_name| Secret::new(nick_name.clone())),
            card_holder_name: card_from_locker.name_on_card.clone(),
            card_issuer: optional_card_info
                .as_ref()
                .and_then(|card_info| card_info.card_issuer.clone()),
            card_network: optional_card_info
                .as_ref()
                .and_then(|card_info| card_info.card_network.clone()),
            card_type: optional_card_info
                .as_ref()
                .and_then(|card_info| card_info.card_type.clone()),
            card_issuing_country: optional_card_info
                .as_ref()
                .and_then(|card_info| card_info.card_issuing_country.clone()),
            co_badged_card_data: None,
        };
        NetworkTokenizationBuilder {
            state: std::marker::PhantomData,
            card: Some(card),
            card_cvc,
            customer: self.customer,
            network_token: self.network_token,
            stored_card: self.stored_card,
            stored_token: self.stored_token,
            payment_method_response: self.payment_method_response,
            card_tokenized: self.card_tokenized,
            error_code: self.error_code,
            error_message: self.error_message,
        }
    }
}

impl<'a> NetworkTokenizationBuilder<'a, PmAssigned> {
    pub fn get_optional_card_and_cvc(
        &self,
    ) -> (Option<domain::CardDetail>, Option<Secret<String>>) {
        (self.card.clone(), self.card_cvc.clone())
    }
    pub fn set_token_details(
        self,
        network_token: &'a NetworkTokenizationResponse,
    ) -> NetworkTokenizationBuilder<'a, PmTokenized> {
        NetworkTokenizationBuilder {
            state: std::marker::PhantomData,
            network_token: Some(&network_token.0),
            card_tokenized: true,
            customer: self.customer,
            card: self.card,
            card_cvc: self.card_cvc,
            stored_card: self.stored_card,
            stored_token: self.stored_token,
            payment_method_response: self.payment_method_response,
            error_code: self.error_code,
            error_message: self.error_message,
        }
    }
}

impl<'a> NetworkTokenizationBuilder<'a, PmTokenized> {
    pub fn set_stored_token_response(
        self,
        store_token_response: &'a pm_transformers::StoreCardRespPayload,
    ) -> NetworkTokenizationBuilder<'a, PmTokenStored> {
        NetworkTokenizationBuilder {
            state: std::marker::PhantomData,
            stored_token: Some(store_token_response),
            customer: self.customer,
            card: self.card,
            card_cvc: self.card_cvc,
            network_token: self.network_token,
            stored_card: self.stored_card,
            payment_method_response: self.payment_method_response,
            card_tokenized: self.card_tokenized,
            error_code: self.error_code,
            error_message: self.error_message,
        }
    }
}

impl<'a> NetworkTokenizationBuilder<'a, PmTokenStored> {
    pub fn set_payment_method(
        self,
        payment_method: &'a domain::PaymentMethod,
    ) -> NetworkTokenizationBuilder<'a, PmTokenUpdated> {
        let payment_method_response = api::PaymentMethodResponse {
            merchant_id: payment_method.merchant_id.clone(),
            customer_id: Some(payment_method.customer_id.clone()),
            payment_method_id: payment_method.payment_method_id.clone(),
            payment_method: payment_method.payment_method,
            payment_method_type: payment_method.payment_method_type,
            recurring_enabled: Some(true),
            installment_payment_enabled: Some(false),
            metadata: payment_method.metadata.clone(),
            created: Some(payment_method.created_at),
            last_used_at: Some(payment_method.last_used_at),
            client_secret: payment_method.client_secret.clone(),
            card: None,
            bank_transfer: None,
            payment_experience: None,
        };
        NetworkTokenizationBuilder {
            state: std::marker::PhantomData,
            payment_method_response: Some(payment_method_response),
            customer: self.customer,
            card: self.card,
            card_cvc: self.card_cvc,
            stored_token: self.stored_token,
            network_token: self.network_token,
            stored_card: self.stored_card,
            card_tokenized: self.card_tokenized,
            error_code: self.error_code,
            error_message: self.error_message,
        }
    }
}

impl NetworkTokenizationBuilder<'_, PmTokenUpdated> {
    pub fn build(self) -> api::CardNetworkTokenizeResponse {
        api::CardNetworkTokenizeResponse {
            payment_method_response: self.payment_method_response,
            customer: self.customer.cloned(),
            card_tokenized: self.card_tokenized,
            error_code: self.error_code.cloned(),
            error_message: self.error_message.cloned(),
            // Below field is mutated by caller functions for batched API operations
            tokenization_data: None,
        }
    }
}

// Specific executor for payment method tokenization
impl CardNetworkTokenizeExecutor<'_, domain::TokenizePaymentMethodRequest> {
    pub async fn fetch_payment_method(
        &self,
        payment_method_id: &str,
    ) -> RouterResult<domain::PaymentMethod> {
        self.state
            .store
            .find_payment_method(
                &self.state.into(),
                self.key_store,
                payment_method_id,
                self.merchant_account.storage_scheme,
            )
            .await
            .map_err(|err| match err.current_context() {
                errors::StorageError::DatabaseError(err)
                    if matches!(
                        err.current_context(),
                        diesel_models::errors::DatabaseError::NotFound
                    ) =>
                {
                    report!(errors::ApiErrorResponse::InvalidRequestData {
                        message: "Invalid payment_method_id".into(),
                    })
                }
                errors::StorageError::ValueNotFound(_) => {
                    report!(errors::ApiErrorResponse::InvalidRequestData {
                        message: "Invalid payment_method_id".to_string(),
                    })
                }
                err => {
                    logger::info!("Error fetching payment_method: {:?}", err);
                    report!(errors::ApiErrorResponse::InternalServerError)
                }
            })
    }
    pub async fn validate_request_and_locker_reference_and_customer(
        &self,
        payment_method: &domain::PaymentMethod,
    ) -> RouterResult<(String, api::CustomerDetails)> {
        // Ensure customer ID matches
        let customer_id_in_req = self
            .customer
            .customer_id
            .clone()
            .get_required_value("customer_id")
            .change_context(errors::ApiErrorResponse::MissingRequiredField {
                field_name: "customer",
            })?;
        when(payment_method.customer_id != customer_id_in_req, || {
            Err(report!(errors::ApiErrorResponse::InvalidRequestData {
                message: "Payment method does not belong to the customer".to_string()
            }))
        })?;

        // Ensure payment method is card
        match payment_method.payment_method {
            Some(api_enums::PaymentMethod::Card) => Ok(()),
            Some(_) => Err(report!(errors::ApiErrorResponse::InvalidRequestData {
                message: "Payment method is not card".to_string()
            })),
            None => Err(report!(errors::ApiErrorResponse::InvalidRequestData {
                message: "Payment method is empty".to_string()
            })),
        }?;

        // Ensure card is not tokenized already
        when(
            payment_method
                .network_token_requestor_reference_id
                .is_some(),
            || {
                Err(report!(errors::ApiErrorResponse::InvalidRequestData {
                    message: "Card is already tokenized".to_string()
                }))
            },
        )?;

        // Ensure locker reference is present
        let locker_id = payment_method.locker_id.clone().ok_or(report!(
            errors::ApiErrorResponse::InvalidRequestData {
                message: "locker_id not found for given payment_method_id".to_string()
            }
        ))?;

        // Fetch customer
        let db = &*self.state.store;
        let key_manager_state: &KeyManagerState = &self.state.into();
        let customer = db
            .find_customer_by_customer_id_merchant_id(
                key_manager_state,
                &payment_method.customer_id,
                self.merchant_account.get_id(),
                self.key_store,
                self.merchant_account.storage_scheme,
            )
            .await
            .inspect_err(|err| logger::info!("Error fetching customer: {:?}", err))
            .change_context(errors::ApiErrorResponse::InternalServerError)?;

        let customer_details = api::CustomerDetails {
            id: customer.customer_id.clone(),
            name: customer.name.clone().map(|name| name.into_inner()),
            email: customer.email.clone().map(Email::from),
            phone: customer.phone.clone().map(|phone| phone.into_inner()),
            phone_country_code: customer.phone_country_code.clone(),
            tax_registration_id: customer
                .tax_registration_id
                .clone()
                .map(|tax_registration_id| tax_registration_id.into_inner()),
        };

        Ok((locker_id, customer_details))
    }
    pub async fn update_payment_method(
        &self,
        store_token_response: &pm_transformers::StoreCardRespPayload,
        payment_method: domain::PaymentMethod,
        network_token_details: &NetworkTokenizationResponse,
        card_details: &domain::CardDetail,
    ) -> RouterResult<domain::PaymentMethod> {
        // Form encrypted network token data
        let enc_token_data = self
            .encrypt_network_token(network_token_details, card_details, true)
            .await?;

        // Update payment method
        let payment_method_update = diesel_models::PaymentMethodUpdate::NetworkTokenDataUpdate {
            network_token_requestor_reference_id: network_token_details.1.clone(),
            network_token_locker_id: Some(store_token_response.card_reference.clone()),
            network_token_payment_method_data: Some(enc_token_data.into()),
        };
        self.state
            .store
            .update_payment_method(
                &self.state.into(),
                self.key_store,
                payment_method,
                payment_method_update,
                self.merchant_account.storage_scheme,
            )
            .await
            .inspect_err(|err| logger::info!("Error updating payment method: {:?}", err))
            .change_context(errors::ApiErrorResponse::InternalServerError)
    }
}


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

pub mod transformers;

use std::sync::LazyLock;

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

use crate::{
    constants::headers,
    types::ResponseRouterData,
    utils::{self, RefundsRequestData as _},
};

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

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

    pub fn generate_authorization_signature(
        &self,
        auth: fiservemea::FiservemeaAuthType,
        request_id: &str,
        payload: &str,
        timestamp: i128,
    ) -> CustomResult<String, errors::ConnectorError> {
        let fiservemea::FiservemeaAuthType {
            api_key,
            secret_key,
        } = auth;
        let raw_signature = format!("{}{request_id}{timestamp}{payload}", api_key.peek());

        let key = hmac::Key::new(hmac::HMAC_SHA256, secret_key.expose().as_bytes());
        let signature_value = common_utils::consts::BASE64_ENGINE
            .encode(hmac::sign(&key, raw_signature.as_bytes()).as_ref());
        Ok(signature_value)
    }
}

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

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

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

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

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

impl<Flow, Request, Response> ConnectorCommonExt<Flow, Request, Response> for Fiservemea
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 timestamp = OffsetDateTime::now_utc().unix_timestamp_nanos() / 1_000_000;
        let auth: fiservemea::FiservemeaAuthType =
            fiservemea::FiservemeaAuthType::try_from(&req.connector_auth_type)?;

        let client_request_id = Uuid::new_v4().to_string();
        let http_method = self.get_http_method();
        let hmac = match http_method {
            Method::Get => self
                .generate_authorization_signature(auth.clone(), &client_request_id, "", timestamp)
                .change_context(errors::ConnectorError::RequestEncodingFailed)?,
            Method::Post | Method::Put | Method::Delete | Method::Patch => {
                let fiserv_req = self.get_request_body(req, connectors)?;
                self.generate_authorization_signature(
                    auth.clone(),
                    &client_request_id,
                    fiserv_req.get_inner_value().peek(),
                    timestamp,
                )
                .change_context(errors::ConnectorError::RequestEncodingFailed)?
            }
        };
        let headers = vec![
            (
                headers::CONTENT_TYPE.to_string(),
                types::PaymentsAuthorizeType::get_content_type(self)
                    .to_string()
                    .into(),
            ),
            ("Client-Request-Id".to_string(), client_request_id.into()),
            (headers::API_KEY.to_string(), auth.api_key.expose().into()),
            (headers::TIMESTAMP.to_string(), timestamp.to_string().into()),
            (headers::MESSAGE_SIGNATURE.to_string(), hmac.into_masked()),
        ];
        Ok(headers)
    }
}

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

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

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

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

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

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

        match response.error {
            Some(error) => {
                let details = error.details.map(|details| {
                    details
                        .iter()
                        .map(|detail| {
                            format!(
                                "{}: {}",
                                detail
                                    .field
                                    .clone()
                                    .unwrap_or("No Field Provided".to_string()),
                                detail
                                    .message
                                    .clone()
                                    .unwrap_or("No Message Provided".to_string())
                            )
                        })
                        .collect::<Vec<String>>()
                        .join(", ")
                });
                Ok(ErrorResponse {
                    status_code: res.status_code,
                    code: error.code.unwrap_or(consts::NO_ERROR_CODE.to_string()),
                    message: response
                        .response_type
                        .unwrap_or(consts::NO_ERROR_MESSAGE.to_string()),
                    reason: match details {
                        Some(details) => Some(format!(
                            "{} {}",
                            error.message.unwrap_or("".to_string()),
                            details
                        )),
                        None => error.message,
                    },
                    attempt_status: None,
                    connector_transaction_id: None,
                    network_advice_code: None,
                    network_decline_code: None,
                    network_error_message: None,
                    connector_metadata: None,
                })
            }
            None => Ok(ErrorResponse {
                status_code: res.status_code,
                code: consts::NO_ERROR_CODE.to_string(),
                message: response
                    .response_type
                    .clone()
                    .unwrap_or(consts::NO_ERROR_MESSAGE.to_string()),
                reason: response.response_type,
                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 Fiservemea {}

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

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

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

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

        let connector_router_data = fiservemea::FiservemeaRouterData::from((amount, req));
        let connector_req =
            fiservemea::FiservemeaPaymentsRequest::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: fiservemea::FiservemeaPaymentsResponse = res
            .response
            .parse_struct("Fiservemea PaymentsAuthorizeResponse")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
        event_builder.map(|i| i.set_response_body(&response));
        router_env::logger::info!(connector_response=?response);
        RouterData::try_from(ResponseRouterData {
            response,
            data: data.clone(),
            http_code: res.status_code,
        })
    }

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

impl ConnectorIntegration<PSync, PaymentsSyncData, PaymentsResponseData> for Fiservemea {
    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_http_method(&self) -> Method {
        Method::Get
    }

    fn get_url(
        &self,
        req: &PaymentsSyncRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        let connector_payment_id = req
            .request
            .connector_transaction_id
            .get_connector_transaction_id()
            .change_context(errors::ConnectorError::MissingConnectorTransactionID)?;
        Ok(format!(
            "{}/ipp/payments-gateway/v2/payments/{connector_payment_id}",
            self.base_url(connectors)
        ))
    }

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

    fn handle_response(
        &self,
        data: &PaymentsSyncRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<PaymentsSyncRouterData, errors::ConnectorError> {
        let response: fiservemea::FiservemeaPaymentsResponse = res
            .response
            .parse_struct("fiservemea 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 Fiservemea {
    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 connector_payment_id = req.request.connector_transaction_id.clone();
        Ok(format!(
            "{}/ipp/payments-gateway/v2/payments/{connector_payment_id}",
            self.base_url(connectors)
        ))
    }

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

        let connector_router_data = fiservemea::FiservemeaRouterData::from((amount, req));
        let connector_req = fiservemea::FiservemeaCaptureRequest::try_from(&connector_router_data)?;
        Ok(RequestContent::Json(Box::new(connector_req)))
    }

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

    fn handle_response(
        &self,
        data: &PaymentsCaptureRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<PaymentsCaptureRouterData, errors::ConnectorError> {
        let response: fiservemea::FiservemeaPaymentsResponse = res
            .response
            .parse_struct("Fiservemea 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 Fiservemea {
    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 connector_payment_id = req.request.connector_transaction_id.clone();
        Ok(format!(
            "{}/ipp/payments-gateway/v2/payments/{connector_payment_id}",
            self.base_url(connectors)
        ))
    }

    fn get_request_body(
        &self,
        req: &PaymentsCancelRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let connector_req = fiservemea::FiservemeaVoidRequest::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::Post)
                .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: fiservemea::FiservemeaPaymentsResponse = res
            .response
            .parse_struct("Fiservemea 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<Execute, RefundsData, RefundsResponseData> for Fiservemea {
    fn get_headers(
        &self,
        req: &RefundsRouterData<Execute>,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        self.build_headers(req, connectors)
    }

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

    fn get_url(
        &self,
        req: &RefundsRouterData<Execute>,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        let connector_payment_id = req.request.connector_transaction_id.clone();
        Ok(format!(
            "{}/ipp/payments-gateway/v2/payments/{connector_payment_id}",
            self.base_url(connectors)
        ))
    }

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

        let connector_router_data = fiservemea::FiservemeaRouterData::from((refund_amount, req));
        let connector_req = fiservemea::FiservemeaRefundRequest::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: fiservemea::FiservemeaPaymentsResponse = res
            .response
            .parse_struct("fiservemea 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 Fiservemea {
    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_http_method(&self) -> Method {
        Method::Get
    }

    fn get_url(
        &self,
        req: &RefundSyncRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        let connector_payment_id = req.request.get_connector_refund_id()?;
        Ok(format!(
            "{}/ipp/payments-gateway/v2/payments/{connector_payment_id}",
            self.base_url(connectors)
        ))
    }

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

    fn handle_response(
        &self,
        data: &RefundSyncRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<RefundSyncRouterData, errors::ConnectorError> {
        let response: fiservemea::FiservemeaPaymentsResponse = res
            .response
            .parse_struct("fiservemea RefundSyncResponse")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
        event_builder.map(|i| i.set_response_body(&response));
        router_env::logger::info!(connector_response=?response);
        RouterData::try_from(ResponseRouterData {
            response,
            data: data.clone(),
            http_code: res.status_code,
        })
    }

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

#[async_trait::async_trait]
impl webhooks::IncomingWebhook for Fiservemea {
    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 FISERVEMEA_SUPPORTED_PAYMENT_METHODS: LazyLock<SupportedPaymentMethods> =
    LazyLock::new(|| {
        let supported_capture_methods = vec![
            enums::CaptureMethod::Automatic,
            enums::CaptureMethod::Manual,
            enums::CaptureMethod::SequentialAutomatic,
        ];

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

        let mut fiservemea_supported_payment_methods = SupportedPaymentMethods::new();

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

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

        fiservemea_supported_payment_methods
    });

static FISERVEMEA_CONNECTOR_INFO: ConnectorInfo = ConnectorInfo {
    display_name: "Fiservemea",
    description: "Fiserv powers over 6+ million merchants and 10,000+ financial institutions enabling them to accept billions of payments a year.",
    connector_type: enums::HyperswitchConnectorCategory::BankAcquirer,
    integration_status: enums::ConnectorIntegrationStatus::Sandbox,
};

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

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

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

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


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

impl api::PaymentsPreProcessing for for Nexixpay


// Implementation: impl api::Refund for for Payeezy
// File: crates/hyperswitch_connectors/src/connectors/payeezy.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::Refund for for Payeezy


// Implementation: impl PayoutAttemptInterface for for KafkaStore
// File: crates/router/src/db/kafka_store.rs
// Module: router
// Methods: 0 total (0 public)

impl PayoutAttemptInterface for for KafkaStore


// Struct: BarclaycardVoidRequest
// File: crates/hyperswitch_connectors/src/connectors/barclaycard/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct BarclaycardVoidRequest


// Struct: GiftCardBalanceCheckResponseData
// File: crates/hyperswitch_domain_models/src/router_response_types.rs
// Module: hyperswitch_domain_models
// Implementations: 0

pub struct GiftCardBalanceCheckResponseData