            Some("Any Aggregator For Payment Method Types"),
            None::<()>,
            None,
        )
        .map_err(KgraphError::GraphConstructionError)?;

    agg_node_id.push((
        any_agg_node,
        cgraph::Relation::Positive,
        cgraph::Strength::Normal,
    ));

    builder
        .make_any_aggregator(&agg_node_id, Some("Configs"), None::<()>, None)
        .map_err(KgraphError::GraphConstructionError)
}

#[cfg(feature = "v2")]
fn compile_merchant_connector_graph(
    builder: &mut cgraph::ConstraintGraphBuilder<dir::DirValue>,
    mca: admin_api::MerchantConnectorResponse,
    config: &kgraph_types::CountryCurrencyFilter,
) -> Result<(), KgraphError> {
    let connector = common_enums::RoutableConnectors::try_from(mca.connector_name)
        .map_err(|_| KgraphError::InvalidConnectorName(mca.connector_name))?;

    let mut agg_nodes: Vec<(cgraph::NodeId, cgraph::Relation, cgraph::Strength)> = Vec::new();

    if let Some(pms_enabled) = mca.payment_methods_enabled.clone() {
        for pm_enabled in pms_enabled {
            let maybe_pm_enabled_id = compile_payment_method_enabled(builder, pm_enabled)?;
            if let Some(pm_enabled_id) = maybe_pm_enabled_id {
                agg_nodes.push((
                    pm_enabled_id,
                    cgraph::Relation::Positive,
                    cgraph::Strength::Strong,
                ));
            }
        }
    }

    let aggregator_info = "Available Payment methods for connector";
    let pms_enabled_agg_id = builder
        .make_any_aggregator(&agg_nodes, Some(aggregator_info), None::<()>, None)
        .map_err(KgraphError::GraphConstructionError)?;

    let config_info = "Config for respective PaymentMethodType for the connector";

    let config_enabled_agg_id = compile_config_graph(builder, config, connector)?;

    let domain_level_node_id = builder
        .make_all_aggregator(
            &[
                (
                    config_enabled_agg_id,
                    cgraph::Relation::Positive,
                    cgraph::Strength::Normal,
                ),
                (
                    pms_enabled_agg_id,
                    cgraph::Relation::Positive,
                    cgraph::Strength::Normal,
                ),
            ],
            Some(config_info),
            None::<()>,
            None,
        )
        .map_err(KgraphError::GraphConstructionError)?;
    let connector_dir_val = dir::DirValue::Connector(Box::new(ast::ConnectorChoice { connector }));

    let connector_info = "Connector";
    let connector_node_id =
        builder.make_value_node(connector_dir_val.into(), Some(connector_info), None::<()>);

    builder
        .make_edge(
            domain_level_node_id,
            connector_node_id,
            cgraph::Strength::Normal,
            cgraph::Relation::Positive,
            None::<cgraph::DomainId>,
        )
        .map_err(KgraphError::GraphConstructionError)?;

    Ok(())
}

#[cfg(feature = "v1")]
fn compile_merchant_connector_graph(
    builder: &mut cgraph::ConstraintGraphBuilder<dir::DirValue>,
    mca: admin_api::MerchantConnectorResponse,
    config: &kgraph_types::CountryCurrencyFilter,
) -> Result<(), KgraphError> {
    let connector = common_enums::RoutableConnectors::from_str(&mca.connector_name)
        .map_err(|_| KgraphError::InvalidConnectorName(mca.connector_name.clone()))?;

    let mut agg_nodes: Vec<(cgraph::NodeId, cgraph::Relation, cgraph::Strength)> = Vec::new();

    if let Some(pms_enabled) = mca.payment_methods_enabled.clone() {
        for pm_enabled in pms_enabled {
            let maybe_pm_enabled_id = compile_payment_method_enabled(builder, pm_enabled)?;
            if let Some(pm_enabled_id) = maybe_pm_enabled_id {
                agg_nodes.push((
                    pm_enabled_id,
                    cgraph::Relation::Positive,
                    cgraph::Strength::Strong,
                ));
            }
        }
    }

    let aggregator_info = "Available Payment methods for connector";
    let pms_enabled_agg_id = builder
        .make_any_aggregator(&agg_nodes, Some(aggregator_info), None::<()>, None)
        .map_err(KgraphError::GraphConstructionError)?;

    let config_info = "Config for respective PaymentMethodType for the connector";

    let config_enabled_agg_id = compile_config_graph(builder, config, connector)?;

    let domain_level_node_id = builder
        .make_all_aggregator(
            &[
                (
                    config_enabled_agg_id,
                    cgraph::Relation::Positive,
                    cgraph::Strength::Normal,
                ),
                (
                    pms_enabled_agg_id,
                    cgraph::Relation::Positive,
                    cgraph::Strength::Normal,
                ),
            ],
            Some(config_info),
            None::<()>,
            None,
        )
        .map_err(KgraphError::GraphConstructionError)?;
    let connector_dir_val = dir::DirValue::Connector(Box::new(ast::ConnectorChoice { connector }));

    let connector_info = "Connector";
    let connector_node_id =
        builder.make_value_node(connector_dir_val.into(), Some(connector_info), None::<()>);

    builder
        .make_edge(
            domain_level_node_id,
            connector_node_id,
            cgraph::Strength::Normal,
            cgraph::Relation::Positive,
            None::<cgraph::DomainId>,
        )
        .map_err(KgraphError::GraphConstructionError)?;

    Ok(())
}

// #[cfg(feature = "v1")]
pub fn make_mca_graph(
    accts: Vec<admin_api::MerchantConnectorResponse>,
    config: &kgraph_types::CountryCurrencyFilter,
) -> Result<cgraph::ConstraintGraph<dir::DirValue>, KgraphError> {
    let mut builder = cgraph::ConstraintGraphBuilder::new();
    let _domain = builder.make_domain(
        DOMAIN_IDENTIFIER.to_string(),
        "Payment methods enabled for MerchantConnectorAccount",
    );
    for acct in accts {
        compile_merchant_connector_graph(&mut builder, acct, config)?;
    }

    Ok(builder.build())
}

#[cfg(feature = "v1")]
#[cfg(test)]
mod tests {
    #![allow(clippy::expect_used)]

    use std::collections::{HashMap, HashSet};

    use api_models::enums as api_enums;
    use euclid::{
        dirval,
        dssa::graph::{AnalysisContext, CgraphExt},
    };
    use hyperswitch_constraint_graph::{ConstraintGraph, CycleCheck, Memoization};

    use super::*;
    use crate::types as kgraph_types;

    fn build_test_data() -> ConstraintGraph<dir::DirValue> {
        use api_models::{admin::*, payment_methods::*};
        let profile_id = common_utils::generate_profile_id_of_default_length();

        // #[cfg(feature = "v2")]
        // let stripe_account = MerchantConnectorResponse {
        //     connector_type: api_enums::ConnectorType::FizOperations,
        //     connector_name: "stripe".to_string(),
        //     id: common_utils::generate_merchant_connector_account_id_of_default_length(),
        //     connector_label: Some("something".to_string()),
        //     connector_account_details: masking::Secret::new(serde_json::json!({})),
        //     disabled: None,
        //     metadata: None,
        //     payment_methods_enabled: Some(vec![PaymentMethodsEnabled {
        //         payment_method: api_enums::PaymentMethod::Card,
        //         payment_method_types: Some(vec![
        //             RequestPaymentMethodTypes {
        //                 payment_method_type: api_enums::PaymentMethodType::Credit,
        //                 payment_experience: None,
        //                 card_networks: Some(vec![
        //                     api_enums::CardNetwork::Visa,
        //                     api_enums::CardNetwork::Mastercard,
        //                 ]),
        //                 accepted_currencies: Some(AcceptedCurrencies::EnableOnly(vec![
        //                     api_enums::Currency::INR,
        //                 ])),
        //                 accepted_countries: None,
        //                 minimum_amount: Some(MinorUnit::new(10)),
        //                 maximum_amount: Some(MinorUnit::new(1000)),
        //                 recurring_enabled: true,
        //                 installment_payment_enabled: true,
        //             },
        //             RequestPaymentMethodTypes {
        //                 payment_method_type: api_enums::PaymentMethodType::Debit,
        //                 payment_experience: None,
        //                 card_networks: Some(vec![
        //                     api_enums::CardNetwork::Maestro,
        //                     api_enums::CardNetwork::JCB,
        //                 ]),
        //                 accepted_currencies: Some(AcceptedCurrencies::EnableOnly(vec![
        //                     api_enums::Currency::GBP,
        //                 ])),
        //                 accepted_countries: None,
        //                 minimum_amount: Some(MinorUnit::new(10)),
        //                 maximum_amount: Some(MinorUnit::new(1000)),
        //                 recurring_enabled: true,
        //                 installment_payment_enabled: true,
        //             },
        //         ]),
        //     }]),
        //     frm_configs: None,
        //     connector_webhook_details: None,
        //     profile_id,
        //     applepay_verified_domains: None,
        //     pm_auth_config: None,
        //     status: api_enums::ConnectorStatus::Inactive,
        //     additional_merchant_data: None,
        //     connector_wallets_details: None,
        // };
        #[cfg(feature = "v1")]
        let stripe_account = MerchantConnectorResponse {
            connector_type: api_enums::ConnectorType::FizOperations,
            connector_name: "stripe".to_string(),
            merchant_connector_id:
                common_utils::generate_merchant_connector_account_id_of_default_length(),
            business_country: Some(api_enums::CountryAlpha2::US),
            connector_label: Some("something".to_string()),
            business_label: Some("food".to_string()),
            business_sub_label: None,
            connector_account_details: masking::Secret::new(serde_json::json!({})),
            test_mode: None,
            disabled: None,
            metadata: None,
            payment_methods_enabled: Some(vec![PaymentMethodsEnabled {
                payment_method: api_enums::PaymentMethod::Card,
                payment_method_types: Some(vec![
                    RequestPaymentMethodTypes {
                        payment_method_type: api_enums::PaymentMethodType::Credit,
                        payment_experience: None,
                        card_networks: Some(vec![
                            api_enums::CardNetwork::Visa,
                            api_enums::CardNetwork::Mastercard,
                        ]),
                        accepted_currencies: Some(AcceptedCurrencies::EnableOnly(vec![
                            api_enums::Currency::INR,
                        ])),
                        accepted_countries: None,
                        minimum_amount: Some(MinorUnit::new(10)),
                        maximum_amount: Some(MinorUnit::new(1000)),
                        recurring_enabled: Some(true),
                        installment_payment_enabled: Some(true),
                    },
                    RequestPaymentMethodTypes {
                        payment_method_type: api_enums::PaymentMethodType::Debit,
                        payment_experience: None,
                        card_networks: Some(vec![
                            api_enums::CardNetwork::Maestro,
                            api_enums::CardNetwork::JCB,
                        ]),
                        accepted_currencies: Some(AcceptedCurrencies::EnableOnly(vec![
                            api_enums::Currency::GBP,
                        ])),
                        accepted_countries: None,
                        minimum_amount: Some(MinorUnit::new(10)),
                        maximum_amount: Some(MinorUnit::new(1000)),
                        recurring_enabled: Some(true),
                        installment_payment_enabled: Some(true),
                    },
                ]),
            }]),
            frm_configs: None,
            connector_webhook_details: None,
            profile_id,
            applepay_verified_domains: None,
            pm_auth_config: None,
            status: api_enums::ConnectorStatus::Inactive,
            additional_merchant_data: None,
            connector_wallets_details: None,
        };

        let config_map = kgraph_types::CountryCurrencyFilter {
            connector_configs: HashMap::from([(
                api_enums::RoutableConnectors::Stripe,
                kgraph_types::PaymentMethodFilters(HashMap::from([
                    (
                        kgraph_types::PaymentMethodFilterKey::PaymentMethodType(
                            api_enums::PaymentMethodType::Credit,
                        ),
                        kgraph_types::CurrencyCountryFlowFilter {
                            currency: Some(HashSet::from([
                                api_enums::Currency::INR,
                                api_enums::Currency::USD,
                            ])),
                            country: Some(HashSet::from([api_enums::CountryAlpha2::IN])),
                            not_available_flows: Some(kgraph_types::NotAvailableFlows {
                                capture_method: Some(api_enums::CaptureMethod::Manual),
                            }),
                        },
                    ),
                    (
                        kgraph_types::PaymentMethodFilterKey::PaymentMethodType(
                            api_enums::PaymentMethodType::Debit,
                        ),
                        kgraph_types::CurrencyCountryFlowFilter {
                            currency: Some(HashSet::from([
                                api_enums::Currency::GBP,
                                api_enums::Currency::PHP,
                            ])),
                            country: Some(HashSet::from([api_enums::CountryAlpha2::IN])),
                            not_available_flows: Some(kgraph_types::NotAvailableFlows {
                                capture_method: Some(api_enums::CaptureMethod::Manual),
                            }),
                        },
                    ),
                ])),
            )]),
            default_configs: None,
        };

        make_mca_graph(vec![stripe_account], &config_map).expect("Failed graph construction")
    }

    #[test]
    fn test_credit_card_success_case() {
        let graph = build_test_data();

        let result = graph.key_value_analysis(
            dirval!(Connector = Stripe),
            &AnalysisContext::from_dir_values([
                dirval!(Connector = Stripe),
                dirval!(PaymentMethod = Card),
                dirval!(CardType = Credit),
                dirval!(CardNetwork = Visa),
                dirval!(PaymentCurrency = INR),
                dirval!(PaymentAmount = 101),
            ]),
            &mut Memoization::new(),
            &mut CycleCheck::new(),
            None,
        );

        assert!(result.is_ok());
    }

    #[test]
    fn test_debit_card_success_case() {
        let graph = build_test_data();

        let result = graph.key_value_analysis(
            dirval!(Connector = Stripe),
            &AnalysisContext::from_dir_values([
                dirval!(Connector = Stripe),
                dirval!(PaymentMethod = Card),
                dirval!(CardType = Debit),
                dirval!(CardNetwork = Maestro),
                dirval!(PaymentCurrency = GBP),
                dirval!(PaymentAmount = 100),
            ]),
            &mut Memoization::new(),
            &mut CycleCheck::new(),
            None,
        );

        assert!(result.is_ok());
    }

    #[test]
    fn test_single_mismatch_failure_case() {
        let graph = build_test_data();

        let result = graph.key_value_analysis(
            dirval!(Connector = Stripe),
            &AnalysisContext::from_dir_values([
                dirval!(Connector = Stripe),
                dirval!(PaymentMethod = Card),
                dirval!(CardType = Debit),
                dirval!(CardNetwork = Maestro),
                dirval!(PaymentCurrency = PHP),
                dirval!(PaymentAmount = 100),
            ]),
            &mut Memoization::new(),
            &mut CycleCheck::new(),
            None,
        );

        assert!(result.is_err());
    }

    #[test]
    fn test_amount_mismatch_failure_case() {
        let graph = build_test_data();

        let result = graph.key_value_analysis(
            dirval!(Connector = Stripe),
            &AnalysisContext::from_dir_values([
                dirval!(Connector = Stripe),
                dirval!(PaymentMethod = Card),
                dirval!(CardType = Debit),
                dirval!(CardNetwork = Visa),
                dirval!(PaymentCurrency = GBP),
                dirval!(PaymentAmount = 7),
            ]),
            &mut Memoization::new(),
            &mut CycleCheck::new(),
            None,
        );

        assert!(result.is_err());
    }

    #[test]
    fn test_incomplete_data_failure_case() {
        let graph = build_test_data();

        let result = graph.key_value_analysis(
            dirval!(Connector = Stripe),
            &AnalysisContext::from_dir_values([
                dirval!(Connector = Stripe),
                dirval!(PaymentMethod = Card),
                dirval!(CardType = Debit),
                dirval!(PaymentCurrency = GBP),
                dirval!(PaymentAmount = 7),
            ]),
            &mut Memoization::new(),
            &mut CycleCheck::new(),
            None,
        );

        //println!("{:#?}", result);
        //println!("{}", serde_json::to_string_pretty(&result).expect("Hello"));

        assert!(result.is_err());
    }

    #[test]
    fn test_incomplete_data_failure_case2() {
        let graph = build_test_data();

        let result = graph.key_value_analysis(
            dirval!(Connector = Stripe),
            &AnalysisContext::from_dir_values([
                dirval!(Connector = Stripe),
                dirval!(CardType = Debit),
                dirval!(CardNetwork = Visa),
                dirval!(PaymentCurrency = GBP),
                dirval!(PaymentAmount = 100),
            ]),
            &mut Memoization::new(),
            &mut CycleCheck::new(),
            None,
        );

        //println!("{:#?}", result);
        //println!("{}", serde_json::to_string_pretty(&result).expect("Hello"));

        assert!(result.is_err());
    }

    #[test]
    fn test_sandbox_applepay_bug_usecase() {
        let value = serde_json::json!([
            {
                "connector_type": "payment_processor",
                "connector_name": "bluesnap",
                "merchant_connector_id": "REDACTED",
                "status": "inactive",
                "connector_account_details": {
                    "auth_type": "BodyKey",
                    "api_key": "REDACTED",
                    "key1": "REDACTED"
                },
                "test_mode": true,
                "disabled": false,
                "payment_methods_enabled": [
                    {
                        "payment_method": "card",
                        "payment_method_types": [
                            {
                                "payment_method_type": "credit",
                                "payment_experience": null,
                                "card_networks": [
                                    "Mastercard",
                                    "Visa",
                                    "AmericanExpress",
                                    "JCB",
                                    "DinersClub",
                                    "Discover",
                                    "CartesBancaires",
                                    "UnionPay"
                                ],
                                "accepted_currencies": null,
                                "accepted_countries": null,
                                "minimum_amount": 1,
                                "maximum_amount": 68607706,
                                "recurring_enabled": true,
                                "installment_payment_enabled": true
                            },
                            {
                                "payment_method_type": "debit",
                                "payment_experience": null,
                                "card_networks": [
                                    "Mastercard",
                                    "Visa",
                                    "Interac",
                                    "AmericanExpress",
                                    "JCB",
                                    "DinersClub",
                                    "Discover",
                                    "CartesBancaires",
                                    "UnionPay"
                                ],
                                "accepted_currencies": null,
                                "accepted_countries": null,
                                "minimum_amount": 1,
                                "maximum_amount": 68607706,
                                "recurring_enabled": true,
                                "installment_payment_enabled": true
                            }
                        ]
                    },
                    {
                        "payment_method": "wallet",
                        "payment_method_types": [
                            {
                                "payment_method_type": "google_pay",
                                "payment_experience": "invoke_sdk_client",
                                "card_networks": null,
                                "accepted_currencies": null,
                                "accepted_countries": null,
                                "minimum_amount": 1,
                                "maximum_amount": 68607706,
                                "recurring_enabled": true,
                                "installment_payment_enabled": true
                            }
                        ]
                    }
                ],
                "metadata": {},
                "business_country": "US",
                "business_label": "default",
                "business_sub_label": null,
                "frm_configs": null
            },
            {
                "connector_type": "payment_processor",
                "connector_name": "stripe",
                "merchant_connector_id": "REDACTED",
                "status": "inactive",
                "connector_account_details": {
                    "auth_type": "HeaderKey",
                    "api_key": "REDACTED"
                },
                "test_mode": true,
                "disabled": false,
                "payment_methods_enabled": [
                    {
                        "payment_method": "card",
                        "payment_method_types": [
                            {
                                "payment_method_type": "credit",
                                "payment_experience": null,
                                "card_networks": [
                                    "Mastercard",
                                    "Visa",
                                    "AmericanExpress",
                                    "JCB",
                                    "DinersClub",
                                    "Discover",
                                    "CartesBancaires",
                                    "UnionPay"
                                ],
                                "accepted_currencies": null,
                                "accepted_countries": null,
                                "minimum_amount": 1,
                                "maximum_amount": 68607706,
                                "recurring_enabled": true,
                                "installment_payment_enabled": true
                            },
                            {
                                "payment_method_type": "debit",
                                "payment_experience": null,
                                "card_networks": [
                                    "Mastercard",
                                    "Visa",
                                    "Interac",
                                    "AmericanExpress",
                                    "JCB",
                                    "DinersClub",
                                    "Discover",
                                    "CartesBancaires",
                                    "UnionPay"
                                ],
                                "accepted_currencies": null,
                                "accepted_countries": null,
                                "minimum_amount": 1,
                                "maximum_amount": 68607706,
                                "recurring_enabled": true,
                                "installment_payment_enabled": true
                            }
                        ]
                    },
                    {
                        "payment_method": "wallet",
                        "payment_method_types": [
                            {
                                "payment_method_type": "apple_pay",
                                "payment_experience": "invoke_sdk_client",
                                "card_networks": null,
                                "accepted_currencies": null,
                                "accepted_countries": null,
                                "minimum_amount": 1,
                                "maximum_amount": 68607706,
                                "recurring_enabled": true,
                                "installment_payment_enabled": true
                            }
                        ]
                    },
                    {
                        "payment_method": "pay_later",
                        "payment_method_types": []
                    }
                ],
                "metadata": {},
                "business_country": "US",
                "business_label": "default",
                "business_sub_label": null,
                "frm_configs": null
            }
        ]);

        let data: Vec<admin_api::MerchantConnectorResponse> =
            serde_json::from_value(value).expect("data");
        let config = kgraph_types::CountryCurrencyFilter {
            connector_configs: HashMap::new(),
            default_configs: None,
        };
        let graph = make_mca_graph(data, &config).expect("graph");
        let context = AnalysisContext::from_dir_values([
            dirval!(Connector = Stripe),
            dirval!(PaymentAmount = 212),
            dirval!(PaymentCurrency = ILS),
            dirval!(PaymentMethod = Wallet),
            dirval!(WalletType = ApplePay),
        ]);

        let result = graph.key_value_analysis(
            dirval!(Connector = Stripe),
            &context,
            &mut Memoization::new(),
            &mut CycleCheck::new(),
            None,
        );

        assert!(result.is_ok(), "stripe validation failed");

        let result = graph.key_value_analysis(
            dirval!(Connector = Bluesnap),
            &context,
            &mut Memoization::new(),
            &mut CycleCheck::new(),
            None,
        );
        assert!(result.is_err(), "bluesnap validation failed");
    }
}


// Struct: PayoutLink
// File: crates/diesel_models/src/generic_link.rs
// Module: diesel_models
// Implementations: 0

pub struct PayoutLink


// Function: get_connector_test_mode
// File: crates/hyperswitch_domain_models/src/merchant_connector_account.rs
// Module: hyperswitch_domain_models

pub fn get_connector_test_mode(&self) -> Option<bool>


// Struct: StripeConnectErrorResponse
// File: crates/hyperswitch_connectors/src/connectors/stripe/transformers/connect.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct StripeConnectErrorResponse


// Module Structure
// File: crates/hyperswitch_connectors/src/connectors/tokenex.rs
// Module: hyperswitch_connectors

// Public submodules:
pub mod transformers;


// Function: insert
// File: crates/diesel_models/src/query/routing_algorithm.rs
// Module: diesel_models

pub fn insert(self, conn: &PgPooledConn) -> StorageResult<Self>


// Struct: CustomerUpdateInternal
// File: crates/diesel_models/src/customers.rs
// Module: diesel_models
// Implementations: 2

pub struct CustomerUpdateInternal


// Struct: SetupProcessor
// File: crates/api_models/src/user/dashboard_metadata.rs
// Module: api_models
// Implementations: 0

pub struct SetupProcessor


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

impl Responder


// Struct: BatchEncryptDataRequest
// File: crates/common_utils/src/types/keymanager.rs
// Module: common_utils
// Implementations: 0

pub struct BatchEncryptDataRequest


// Implementation: impl IncomingWebhook for for Shift4
// File: crates/hyperswitch_connectors/src/connectors/shift4.rs
// Module: hyperswitch_connectors
// Methods: 3 total (0 public)

impl IncomingWebhook for for Shift4


// Struct: NexixpayRSyncResponse
// File: crates/hyperswitch_connectors/src/connectors/nexixpay/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct NexixpayRSyncResponse


// Struct: EliminationRoutingEventRequest
// File: crates/api_models/src/routing.rs
// Module: api_models
// Implementations: 0

pub struct EliminationRoutingEventRequest


// Struct: CmdLineConf
// File: crates/drainer/src/settings.rs
// Module: drainer
// Implementations: 0

pub struct CmdLineConf


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

pub struct PayoutBatchHeader


// Trait: SignatureCalculationData
// File: crates/hyperswitch_connectors/src/connectors/redsys/transformers.rs
// Module: hyperswitch_connectors

pub trait SignatureCalculationData


// Function: delete_payment_method_data_from_vault_internal
// File: crates/router/src/core/payment_methods/vault.rs
// Module: router

pub fn delete_payment_method_data_from_vault_internal(
    state: &routes::SessionState,
    merchant_context: &domain::MerchantContext,
    vault_id: domain::VaultId,
    customer_id: &id_type::GlobalCustomerId,
) -> CustomResult<pm_types::VaultDeleteResponse, errors::VaultError>


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

impl Responder


// Function: new
// File: crates/hyperswitch_connectors/src/connectors/getnet.rs
// Module: hyperswitch_connectors

pub fn new() -> &'static Self


// Implementation: impl EventContext
// File: crates/events/src/lib.rs
// Module: events
// Methods: 5 total (5 public)

impl EventContext


// File: crates/scheduler/src/db/process_tracker.rs
// Module: scheduler

use common_utils::errors::CustomResult;
pub use diesel_models as storage;
use diesel_models::enums as storage_enums;
use error_stack::{report, ResultExt};
use storage_impl::{connection, errors, mock_db::MockDb};
use time::PrimitiveDateTime;

use crate::{metrics, scheduler::Store};

#[async_trait::async_trait]
pub trait ProcessTrackerInterface: Send + Sync + 'static {
    async fn reinitialize_limbo_processes(
        &self,
        ids: Vec<String>,
        schedule_time: PrimitiveDateTime,
    ) -> CustomResult<usize, errors::StorageError>;

    async fn find_process_by_id(
        &self,
        id: &str,
    ) -> CustomResult<Option<storage::ProcessTracker>, errors::StorageError>;

    async fn update_process(
        &self,
        this: storage::ProcessTracker,
        process: storage::ProcessTrackerUpdate,
    ) -> CustomResult<storage::ProcessTracker, errors::StorageError>;

    async fn process_tracker_update_process_status_by_ids(
        &self,
        task_ids: Vec<String>,
        task_update: storage::ProcessTrackerUpdate,
    ) -> CustomResult<usize, errors::StorageError>;

    async fn insert_process(
        &self,
        new: storage::ProcessTrackerNew,
    ) -> CustomResult<storage::ProcessTracker, errors::StorageError>;

    async fn reset_process(
        &self,
        this: storage::ProcessTracker,
        schedule_time: PrimitiveDateTime,
    ) -> CustomResult<(), errors::StorageError>;

    async fn retry_process(
        &self,
        this: storage::ProcessTracker,
        schedule_time: PrimitiveDateTime,
    ) -> CustomResult<(), errors::StorageError>;

    async fn finish_process_with_business_status(
        &self,
        this: storage::ProcessTracker,
        business_status: &'static str,
    ) -> CustomResult<(), errors::StorageError>;

    async fn find_processes_by_time_status(
        &self,
        time_lower_limit: PrimitiveDateTime,
        time_upper_limit: PrimitiveDateTime,
        status: storage_enums::ProcessTrackerStatus,
        limit: Option<i64>,
    ) -> CustomResult<Vec<storage::ProcessTracker>, errors::StorageError>;
}

#[async_trait::async_trait]
impl ProcessTrackerInterface for Store {
    async fn find_process_by_id(
        &self,
        id: &str,
    ) -> CustomResult<Option<storage::ProcessTracker>, errors::StorageError> {
        let conn = connection::pg_connection_read(self).await?;
        storage::ProcessTracker::find_process_by_id(&conn, id)
            .await
            .map_err(|error| report!(errors::StorageError::from(error)))
    }

    async fn reinitialize_limbo_processes(
        &self,
        ids: Vec<String>,
        schedule_time: PrimitiveDateTime,
    ) -> CustomResult<usize, errors::StorageError> {
        let conn = connection::pg_connection_write(self).await?;
        storage::ProcessTracker::reinitialize_limbo_processes(&conn, ids, schedule_time)
            .await
            .map_err(|error| report!(errors::StorageError::from(error)))
    }

    async fn find_processes_by_time_status(
        &self,
        time_lower_limit: PrimitiveDateTime,
        time_upper_limit: PrimitiveDateTime,
        status: storage_enums::ProcessTrackerStatus,
        limit: Option<i64>,
    ) -> CustomResult<Vec<storage::ProcessTracker>, errors::StorageError> {
        let conn = connection::pg_connection_read(self).await?;
        storage::ProcessTracker::find_processes_by_time_status(
            &conn,
            time_lower_limit,
            time_upper_limit,
            status,
            limit,
            common_types::consts::API_VERSION,
        )
        .await
        .map_err(|error| report!(errors::StorageError::from(error)))
    }

    async fn insert_process(
        &self,
        new: storage::ProcessTrackerNew,
    ) -> CustomResult<storage::ProcessTracker, errors::StorageError> {
        let conn = connection::pg_connection_write(self).await?;
        new.insert_process(&conn)
            .await
            .map_err(|error| report!(errors::StorageError::from(error)))
    }

    async fn update_process(
        &self,
        this: storage::ProcessTracker,
        process: storage::ProcessTrackerUpdate,
    ) -> CustomResult<storage::ProcessTracker, errors::StorageError> {
        let conn = connection::pg_connection_write(self).await?;
        this.update(&conn, process)
            .await
            .map_err(|error| report!(errors::StorageError::from(error)))
    }

    async fn reset_process(
        &self,
        this: storage::ProcessTracker,
        schedule_time: PrimitiveDateTime,
    ) -> CustomResult<(), errors::StorageError> {
        self.update_process(
            this,
            storage::ProcessTrackerUpdate::StatusRetryUpdate {
                status: storage_enums::ProcessTrackerStatus::New,
                retry_count: 0,
                schedule_time,
            },
        )
        .await?;
        Ok(())
    }

    async fn retry_process(
        &self,
        this: storage::ProcessTracker,
        schedule_time: PrimitiveDateTime,
    ) -> CustomResult<(), errors::StorageError> {
        metrics::TASK_RETRIED.add(1, &[]);
        let retry_count = this.retry_count + 1;
        self.update_process(
            this,
            storage::ProcessTrackerUpdate::StatusRetryUpdate {
                status: storage_enums::ProcessTrackerStatus::Pending,
                retry_count,
                schedule_time,
            },
        )
        .await?;
        Ok(())
    }

    async fn finish_process_with_business_status(
        &self,
        this: storage::ProcessTracker,
        business_status: &'static str,
    ) -> CustomResult<(), errors::StorageError> {
        self.update_process(
            this,
            storage::ProcessTrackerUpdate::StatusUpdate {
                status: storage_enums::ProcessTrackerStatus::Finish,
                business_status: Some(String::from(business_status)),
            },
        )
        .await
        .attach_printable("Failed to update business status of process")?;
        metrics::TASK_FINISHED.add(1, &[]);
        Ok(())
    }

    async fn process_tracker_update_process_status_by_ids(
        &self,
        task_ids: Vec<String>,
        task_update: storage::ProcessTrackerUpdate,
    ) -> CustomResult<usize, errors::StorageError> {
        let conn = connection::pg_connection_write(self).await?;
        storage::ProcessTracker::update_process_status_by_ids(&conn, task_ids, task_update)
            .await
            .map_err(|error| report!(errors::StorageError::from(error)))
    }
}

#[async_trait::async_trait]
impl ProcessTrackerInterface for MockDb {
    async fn find_process_by_id(
        &self,
        id: &str,
    ) -> CustomResult<Option<storage::ProcessTracker>, errors::StorageError> {
        let optional = self
            .processes
            .lock()
            .await
            .iter()
            .find(|process| process.id == id)
            .cloned();

        Ok(optional)
    }

    async fn reinitialize_limbo_processes(
        &self,
        _ids: Vec<String>,
        _schedule_time: PrimitiveDateTime,
    ) -> CustomResult<usize, errors::StorageError> {
        // [#172]: Implement function for `MockDb`
        Err(errors::StorageError::MockDbError)?
    }

    async fn find_processes_by_time_status(
        &self,
        _time_lower_limit: PrimitiveDateTime,
        _time_upper_limit: PrimitiveDateTime,
        _status: storage_enums::ProcessTrackerStatus,
        _limit: Option<i64>,
    ) -> CustomResult<Vec<storage::ProcessTracker>, errors::StorageError> {
        // [#172]: Implement function for `MockDb`
        Err(errors::StorageError::MockDbError)?
    }
    async fn insert_process(
        &self,
        new: storage::ProcessTrackerNew,
    ) -> CustomResult<storage::ProcessTracker, errors::StorageError> {
        let mut processes = self.processes.lock().await;
        let process = storage::ProcessTracker {
            id: new.id,
            name: new.name,
            tag: new.tag,
            runner: new.runner,
            retry_count: new.retry_count,
            schedule_time: new.schedule_time,
            rule: new.rule,
            tracking_data: new.tracking_data,
            business_status: new.business_status,
            status: new.status,
            event: new.event,
            created_at: new.created_at,
            updated_at: new.updated_at,
            version: new.version,
        };
        processes.push(process.clone());
        Ok(process)
    }

    async fn update_process(
        &self,
        _this: storage::ProcessTracker,
        _process: storage::ProcessTrackerUpdate,
    ) -> CustomResult<storage::ProcessTracker, errors::StorageError> {
        // [#172]: Implement function for `MockDb`
        Err(errors::StorageError::MockDbError)?
    }

    async fn reset_process(
        &self,
        _this: storage::ProcessTracker,
        _schedule_time: PrimitiveDateTime,
    ) -> CustomResult<(), errors::StorageError> {
        // [#172]: Implement function for `MockDb`
        Err(errors::StorageError::MockDbError)?
    }

    async fn retry_process(
        &self,
        _this: storage::ProcessTracker,
        _schedule_time: PrimitiveDateTime,
    ) -> CustomResult<(), errors::StorageError> {
        // [#172]: Implement function for `MockDb`
        Err(errors::StorageError::MockDbError)?
    }

    async fn finish_process_with_business_status(
        &self,
        _this: storage::ProcessTracker,
        _business_status: &'static str,
    ) -> CustomResult<(), errors::StorageError> {
        // [#172]: Implement function for `MockDb`
        Err(errors::StorageError::MockDbError)?
    }

    async fn process_tracker_update_process_status_by_ids(
        &self,
        _task_ids: Vec<String>,
        _task_update: storage::ProcessTrackerUpdate,
    ) -> CustomResult<usize, errors::StorageError> {
        // [#172]: Implement function for `MockDb`
        Err(errors::StorageError::MockDbError)?
    }
}


// Struct: ArchipelCaptureRequest
// File: crates/hyperswitch_connectors/src/connectors/archipel/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct ArchipelCaptureRequest


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

impl api::PaymentsPreProcessing for for Gocardless


// Function: get_merchant_pm_filter_graph
// File: crates/router/src/core/payment_methods/utils.rs
// Module: router

pub fn get_merchant_pm_filter_graph(
    state: &SessionState,
    key: &str,
) -> Option<Arc<hyperswitch_constraint_graph::ConstraintGraph<dir::DirValue>>>


// Struct: PostAuthenticationResponse
// File: crates/router/src/types/api/authentication.rs
// Module: router
// Implementations: 0

pub struct PostAuthenticationResponse


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

impl Responder


// File: crates/analytics/src/sdk_events/filters.rs
// Module: analytics
// Public functions: 1
// Public structs: 1

use api_models::analytics::{sdk_events::SdkEventDimensions, Granularity, TimeRange};
use common_utils::errors::ReportSwitchExt;
use error_stack::ResultExt;
use time::PrimitiveDateTime;

use crate::{
    query::{Aggregate, GroupByClause, QueryBuilder, QueryFilter, ToSql, Window},
    types::{AnalyticsCollection, AnalyticsDataSource, FiltersError, FiltersResult, LoadRow},
};

pub trait SdkEventFilterAnalytics: LoadRow<SdkEventFilter> {}

pub async fn get_sdk_event_filter_for_dimension<T>(
    dimension: SdkEventDimensions,
    publishable_key: &String,
    time_range: &TimeRange,
    pool: &T,
) -> FiltersResult<Vec<SdkEventFilter>>
where
    T: AnalyticsDataSource + SdkEventFilterAnalytics,
    PrimitiveDateTime: ToSql<T>,
    AnalyticsCollection: ToSql<T>,
    Granularity: GroupByClause<T>,
    Aggregate<&'static str>: ToSql<T>,
    Window<&'static str>: ToSql<T>,
{
    let mut query_builder: QueryBuilder<T> =
        QueryBuilder::new(AnalyticsCollection::SdkEventsAnalytics);

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

    query_builder
        .add_filter_clause("merchant_id", publishable_key)
        .switch()?;

    query_builder.set_distinct();

    query_builder
        .execute_query::<SdkEventFilter, _>(pool)
        .await
        .change_context(FiltersError::QueryBuildingError)?
        .change_context(FiltersError::QueryExecutionFailure)
}

#[derive(Debug, serde::Serialize, Eq, PartialEq, serde::Deserialize)]
pub struct SdkEventFilter {
    pub payment_method: Option<String>,
    pub platform: Option<String>,
    pub browser_name: Option<String>,
    pub source: Option<String>,
    pub component: Option<String>,
    pub payment_experience: Option<String>,
}


// Struct: Mandates
// File: crates/payment_methods/src/configs/settings.rs
// Module: payment_methods
// Implementations: 0

pub struct Mandates


// Struct: SamsungPayWalletCredentials
// File: crates/hyperswitch_domain_models/src/payment_method_data.rs
// Module: hyperswitch_domain_models
// Implementations: 0

pub struct SamsungPayWalletCredentials


// Struct: PaymentMethodCollectLinkStatusDetails
// File: crates/api_models/src/payment_methods.rs
// Module: api_models
// Implementations: 0

pub struct PaymentMethodCollectLinkStatusDetails


// Struct: Paypal
// File: crates/api_models/src/payouts.rs
// Module: api_models
// Implementations: 0

pub struct Paypal


// Implementation: impl MerchantConnectorAccountUpdateInternal
// File: crates/diesel_models/src/merchant_connector_account.rs
// Module: diesel_models
// Methods: 1 total (1 public)

impl MerchantConnectorAccountUpdateInternal


// Function: get_expiry_month
// File: crates/common_types/src/payments.rs
// Module: common_types

// Documentation: Get the expiration month from the Apple Pay pre-decrypt data

pub fn get_expiry_month(&self) -> Result<Secret<String>, errors::ValidationError>


// Function: update_by_merchant_id_mandate_id
// File: crates/diesel_models/src/query/mandate.rs
// Module: diesel_models

pub fn update_by_merchant_id_mandate_id(
        conn: &PgPooledConn,
        merchant_id: &common_utils::id_type::MerchantId,
        mandate_id: &str,
        mandate: MandateUpdateInternal,
    ) -> StorageResult<Self>


// Struct: VirtualAccountsType
// File: crates/hyperswitch_connectors/src/connectors/nomupay/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct VirtualAccountsType


// Struct: CardNetworkTokenResponsePayload
// File: crates/router/src/types/payment_methods.rs
// Module: router
// Implementations: 0

pub struct CardNetworkTokenResponsePayload


// Struct: UserFromStorage
// File: crates/router/src/types/domain/user.rs
// Module: router
// Implementations: 1

pub struct UserFromStorage


// Implementation: impl ConnectorSpecifications for for Cybersource
// File: crates/hyperswitch_connectors/src/connectors/cybersource.rs
// Module: hyperswitch_connectors
// Methods: 3 total (0 public)

impl ConnectorSpecifications for for Cybersource


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

pub mod transformers;

use std::sync::LazyLock;

use api_models::webhooks::IncomingWebhookEvent;
use common_enums::{enums, CallConnectorAction, PaymentAction};
use common_utils::{
    crypto,
    errors::CustomResult,
    ext_traits::{ByteSliceExt, BytesExt, ValueExt},
    request::{Method, Request, RequestBuilder, RequestContent},
    types::{
        AmountConvertor, MinorUnit, StringMajorUnit, StringMajorUnitForConnector, StringMinorUnit,
        StringMinorUnitForConnector,
    },
};
use error_stack::{report, ResultExt};
use hyperswitch_domain_models::{
    router_data::{AccessToken, ErrorResponse, RouterData},
    router_flow_types::{
        access_token_auth::AccessTokenAuth,
        payments::{Authorize, Capture, PSync, PaymentMethodToken, Session, SetupMandate, Void},
        refunds::{Execute, RSync},
        CompleteAuthorize, PreProcessing,
    },
    router_request_types::{
        AccessTokenRequestData, CompleteAuthorizeData, PaymentMethodTokenizationData,
        PaymentsAuthorizeData, PaymentsCancelData, PaymentsCaptureData, PaymentsPreProcessingData,
        PaymentsSessionData, PaymentsSyncData, RefundsData, SetupMandateRequestData,
    },
    router_response_types::{
        ConnectorInfo, PaymentMethodDetails, PaymentsResponseData, RefundsResponseData,
        SupportedPaymentMethods, SupportedPaymentMethodsExt,
    },
    types::{
        PaymentsAuthorizeRouterData, PaymentsCancelRouterData, PaymentsCaptureRouterData,
        PaymentsCompleteAuthorizeRouterData, PaymentsPreProcessingRouterData,
        PaymentsSyncRouterData, RefundSyncRouterData, RefundsRouterData, SetupMandateRouterData,
    },
};
use hyperswitch_interfaces::{
    api::{
        self, ConnectorCommon, ConnectorCommonExt, ConnectorIntegration, ConnectorRedirectResponse,
        ConnectorSpecifications, ConnectorValidation,
    },
    configs::Connectors,
    disputes::DisputePayload,
    errors,
    events::connector_api_logs::ConnectorEvent,
    types::{self, Response},
    webhooks::{IncomingWebhook, IncomingWebhookRequestDetails},
};
use masking::{Mask, PeekInterface};
use router_env::logger;
use transformers as airwallex;

use crate::{
    connectors::airwallex::transformers::AirwallexAuthorizeResponse,
    constants::headers,
    types::{RefreshTokenRouterData, ResponseRouterData},
    utils::{convert_amount, AccessTokenRequestInfo, ForeignTryFrom, RefundsRequestData},
};

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

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

impl<Flow, Request, Response> ConnectorCommonExt<Flow, Request, Response> for Airwallex
where
    Self: ConnectorIntegration<Flow, Request, Response>,
{
    fn build_headers(
        &self,
        req: &RouterData<Flow, Request, Response>,
        _connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        let mut headers = vec![(
            headers::CONTENT_TYPE.to_string(),
            self.get_content_type().to_string().into(),
        )];
        let access_token = req
            .access_token
            .clone()
            .ok_or(errors::ConnectorError::FailedToObtainAuthType)?;

        let auth_header = (
            headers::AUTHORIZATION.to_string(),
            format!("Bearer {}", access_token.token.peek()).into_masked(),
        );

        headers.push(auth_header);
        Ok(headers)
    }
}

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

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

    fn build_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        logger::debug!(payu_error_response=?res);
        let response: airwallex::AirwallexErrorResponse = res
            .response
            .parse_struct("Airwallex ErrorResponse")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;

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

        Ok(ErrorResponse {
            status_code: res.status_code,
            code: response.code,
            message: response.message,
            reason: response.source,
            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 Airwallex {}

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

impl api::PaymentToken for Airwallex {}

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

impl api::ConnectorAccessToken for Airwallex {}

impl ConnectorIntegration<AccessTokenAuth, AccessTokenRequestData, AccessToken> for Airwallex {
    fn get_url(
        &self,
        _req: &RefreshTokenRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        Ok(format!(
            "{}{}",
            self.base_url(connectors),
            "api/v1/authentication/login"
        ))
    }

    fn get_headers(
        &self,
        req: &RefreshTokenRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        let headers = vec![
            (
                headers::X_API_KEY.to_string(),
                req.request.app_id.clone().into_masked(),
            ),
            ("Content-Length".to_string(), "0".to_string().into()),
            (
                "x-client-id".to_string(),
                req.get_request_id()?.into_masked(),
            ),
        ];
        Ok(headers)
    }

    fn build_request(
        &self,
        req: &RefreshTokenRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        let req = Some(
            RequestBuilder::new()
                .method(Method::Post)
                .attach_default_headers()
                .headers(types::RefreshTokenType::get_headers(self, req, connectors)?)
                .url(&types::RefreshTokenType::get_url(self, req, connectors)?)
                .build(),
        );
        logger::debug!(payu_access_token_request=?req);
        Ok(req)
    }
    fn handle_response(
        &self,
        data: &RefreshTokenRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<RefreshTokenRouterData, errors::ConnectorError> {
        logger::debug!(access_token_response=?res);
        let response: airwallex::AirwallexAuthUpdateResponse = res
            .response
            .parse_struct("airwallex AirwallexAuthUpdateResponse")
            .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,
        })
        .change_context(errors::ConnectorError::ResponseHandlingFailed)
    }

    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<PreProcessing, PaymentsPreProcessingData, PaymentsResponseData>
    for Airwallex
{
    fn get_headers(
        &self,
        req: &PaymentsPreProcessingRouterData,
        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: &PaymentsPreProcessingRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        Ok(format!(
            "{}{}",
            self.base_url(connectors),
            "api/v1/pa/payment_intents/create"
        ))
    }

    fn get_request_body(
        &self,
        req: &PaymentsPreProcessingRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let amount_in_minor_unit = MinorUnit::new(req.request.amount.ok_or(
            errors::ConnectorError::MissingRequiredField {
                field_name: "amount",
            },
        )?);
        let amount = convert_amount(
            self.amount_converter,
            amount_in_minor_unit,
            req.request
                .currency
                .ok_or(errors::ConnectorError::MissingRequiredField {
                    field_name: "currency",
                })?,
        )?;
        let connector_router_data = airwallex::AirwallexRouterData::try_from((amount, req))?;
        let connector_req = airwallex::AirwallexIntentRequest::try_from(&connector_router_data)?;
        Ok(RequestContent::Json(Box::new(connector_req)))
    }

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

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

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

impl api::PaymentAuthorize for Airwallex {}

#[async_trait::async_trait]
impl ConnectorIntegration<Authorize, PaymentsAuthorizeData, PaymentsResponseData> for Airwallex {
    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!(
            "{}{}{}{}",
            self.base_url(connectors),
            "api/v1/pa/payment_intents/",
            req.reference_id
                .clone()
                .ok_or(errors::ConnectorError::MissingConnectorTransactionID)?,
            "/confirm"
        ))
    }

    fn get_request_body(
        &self,
        req: &PaymentsAuthorizeRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let amount_in_minor_unit = MinorUnit::new(req.request.amount);
        let amount = convert_amount(
            self.amount_converter,
            amount_in_minor_unit,
            req.request.currency,
        )?;
        let connector_router_data = airwallex::AirwallexRouterData::try_from((amount, req))?;
        let connector_req = airwallex::AirwallexPaymentsRequest::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: AirwallexAuthorizeResponse = res
            .response
            .parse_struct("AirwallexAuthorizeResponse")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;

        event_builder.map(|i| i.set_response_body(&response));
        RouterData::foreign_try_from(ResponseRouterData {
            response,
            data: data.clone(),
            http_code: res.status_code,
        })
        .change_context(errors::ConnectorError::ResponseHandlingFailed)
    }

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

impl api::PaymentSync for Airwallex {}
impl ConnectorIntegration<PSync, PaymentsSyncData, PaymentsResponseData> for Airwallex {
    fn get_headers(
        &self,
        req: &PaymentsSyncRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        self.build_headers(req, connectors)
    }

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

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

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

    fn handle_response(
        &self,
        data: &PaymentsSyncRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<PaymentsSyncRouterData, errors::ConnectorError> {
        logger::debug!(payment_sync_response=?res);
        let response: airwallex::AirwallexPaymentsSyncResponse = res
            .response
            .parse_struct("airwallex AirwallexPaymentsSyncResponse")
            .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,
        })
        .change_context(errors::ConnectorError::ResponseHandlingFailed)
    }

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

impl ConnectorIntegration<CompleteAuthorize, CompleteAuthorizeData, PaymentsResponseData>
    for Airwallex
{
    fn get_headers(
        &self,
        req: &PaymentsCompleteAuthorizeRouterData,
        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: &PaymentsCompleteAuthorizeRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        let connector_payment_id = req
            .request
            .connector_transaction_id
            .clone()
            .ok_or(errors::ConnectorError::MissingConnectorTransactionID)?;
        Ok(format!(
            "{}api/v1/pa/payment_intents/{}/confirm_continue",
            self.base_url(connectors),
            connector_payment_id,
        ))
    }
    fn get_request_body(
        &self,
        req: &PaymentsCompleteAuthorizeRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let req_obj = airwallex::AirwallexCompleteRequest::try_from(req)?;

        Ok(RequestContent::Json(Box::new(req_obj)))
    }
    fn build_request(
        &self,
        req: &PaymentsCompleteAuthorizeRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        Ok(Some(
            RequestBuilder::new()
                .method(Method::Post)
                .url(&types::PaymentsCompleteAuthorizeType::get_url(
                    self, req, connectors,
                )?)
                .headers(types::PaymentsCompleteAuthorizeType::get_headers(
                    self, req, connectors,
                )?)
                .set_body(types::PaymentsCompleteAuthorizeType::get_request_body(
                    self, req, connectors,
                )?)
                .build(),
        ))
    }
    fn handle_response(
        &self,
        data: &PaymentsCompleteAuthorizeRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<PaymentsCompleteAuthorizeRouterData, errors::ConnectorError> {
        let response: airwallex::AirwallexPaymentsResponse = res
            .response
            .parse_struct("AirwallexPaymentsResponse")
            .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,
        })
        .change_context(errors::ConnectorError::ResponseHandlingFailed)
    }

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

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

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

    fn get_url(
        &self,
        req: &PaymentsCaptureRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        Ok(format!(
            "{}{}{}{}",
            self.base_url(connectors),
            "api/v1/pa/payment_intents/",
            req.request.connector_transaction_id,
            "/capture"
        ))
    }

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

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

    fn build_request(
        &self,
        req: &PaymentsCaptureRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        Ok(Some(
            RequestBuilder::new()
                .method(Method::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: airwallex::AirwallexPaymentsResponse = res
            .response
            .parse_struct("Airwallex PaymentsResponse")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
        event_builder.map(|i| i.set_response_body(&response));
        router_env::logger::info!(connector_response=?response);
        RouterData::try_from(ResponseRouterData {
            response,
            data: data.clone(),
            http_code: res.status_code,
        })
        .change_context(errors::ConnectorError::ResponseHandlingFailed)
    }

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

impl api::PaymentSession for Airwallex {}

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

impl api::PaymentVoid for Airwallex {}

impl ConnectorIntegration<Void, PaymentsCancelData, PaymentsResponseData> for Airwallex {
    fn get_headers(
        &self,
        req: &PaymentsCancelRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        self.build_headers(req, connectors)
    }

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

    fn get_url(
        &self,
        req: &PaymentsCancelRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        Ok(format!(
            "{}{}{}{}",
            self.base_url(connectors),
            "api/v1/pa/payment_intents/",
            req.request.connector_transaction_id,
            "/cancel"
        ))
    }
    fn get_request_body(
        &self,
        req: &PaymentsCancelRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let connector_req = airwallex::AirwallexPaymentsCancelRequest::try_from(req)?;

        Ok(RequestContent::Json(Box::new(connector_req)))
    }
    fn handle_response(
        &self,
        data: &PaymentsCancelRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<PaymentsCancelRouterData, errors::ConnectorError> {
        let response: airwallex::AirwallexPaymentsResponse = res
            .response
            .parse_struct("Airwallex PaymentsResponse")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
        event_builder.map(|i| i.set_response_body(&response));
        router_env::logger::info!(connector_response=?response);
        RouterData::try_from(ResponseRouterData {
            response,
            data: data.clone(),
            http_code: res.status_code,
        })
        .change_context(errors::ConnectorError::ResponseHandlingFailed)
    }

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

impl api::Refund for Airwallex {}
impl api::RefundExecute for Airwallex {}
impl api::RefundSync for Airwallex {}

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

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

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

    fn get_request_body(
        &self,
        req: &RefundsRouterData<Execute>,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let amount_in_minor_unit = MinorUnit::new(req.request.refund_amount);
        let amount = convert_amount(
            self.amount_converter,
            amount_in_minor_unit,
            req.request.currency,
        )?;
        let connector_router_data = airwallex::AirwallexRouterData::try_from((amount, req))?;
        let connector_req = airwallex::AirwallexRefundRequest::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> {
        logger::debug!(target: "router::connector::airwallex", response=?res);
        let response: airwallex::RefundResponse = res
            .response
            .parse_struct("airwallex RefundResponse")
            .change_context(errors::ConnectorError::RequestEncodingFailed)?;
        event_builder.map(|i| i.set_response_body(&response));
        router_env::logger::info!(connector_response=?response);
        RouterData::try_from(ResponseRouterData {
            response,
            data: data.clone(),
            http_code: res.status_code,
        })
        .change_context(errors::ConnectorError::ResponseHandlingFailed)
    }

    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 Airwallex {
    fn get_headers(
        &self,
        req: &RefundSyncRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        self.build_headers(req, connectors)
    }

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

    fn get_url(
        &self,
        req: &RefundSyncRouterData,
        connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        Ok(format!(
            "{}{}{}",
            self.base_url(connectors),
            "/api/v1/pa/refunds/",
            req.request.get_connector_refund_id()?
        ))
    }

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

    fn handle_response(
        &self,
        data: &RefundSyncRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<RefundSyncRouterData, errors::ConnectorError> {
        logger::debug!(target: "router::connector::airwallex", response=?res);
        let response: airwallex::RefundResponse = res
            .response
            .parse_struct("airwallex 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,
        })
        .change_context(errors::ConnectorError::ResponseHandlingFailed)
    }

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

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

    fn get_webhook_source_verification_signature(
        &self,
        request: &IncomingWebhookRequestDetails<'_>,
        _connector_webhook_secrets: &api_models::webhooks::ConnectorWebhookSecrets,
    ) -> CustomResult<Vec<u8>, errors::ConnectorError> {
        let security_header = request
            .headers
            .get("x-signature")
            .map(|header_value| {
                header_value
                    .to_str()
                    .map(String::from)
                    .map_err(|_| errors::ConnectorError::WebhookSignatureNotFound)
            })
            .ok_or(errors::ConnectorError::WebhookSignatureNotFound)??;

        hex::decode(security_header)
            .change_context(errors::ConnectorError::WebhookSignatureNotFound)
    }

    fn get_webhook_source_verification_message(
        &self,
        request: &IncomingWebhookRequestDetails<'_>,
        _merchant_id: &common_utils::id_type::MerchantId,
        _connector_webhook_secrets: &api_models::webhooks::ConnectorWebhookSecrets,
    ) -> CustomResult<Vec<u8>, errors::ConnectorError> {
        let timestamp = request
            .headers
            .get("x-timestamp")
            .map(|header_value| {
                header_value
                    .to_str()
                    .map(String::from)
                    .map_err(|_| errors::ConnectorError::WebhookSignatureNotFound)
            })
            .ok_or(errors::ConnectorError::WebhookSignatureNotFound)??;

        Ok(format!("{}{}", timestamp, String::from_utf8_lossy(request.body)).into_bytes())
    }

    fn get_webhook_object_reference_id(
        &self,
        request: &IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<api_models::webhooks::ObjectReferenceId, errors::ConnectorError> {
        let details: airwallex::AirwallexWebhookData = request
            .body
            .parse_struct("airwallexWebhookData")
            .change_context(errors::ConnectorError::WebhookReferenceIdNotFound)?;

        if airwallex::is_transaction_event(&details.name) {
            Ok(api_models::webhooks::ObjectReferenceId::PaymentId(
                api_models::payments::PaymentIdType::ConnectorTransactionId(
                    details
                        .source_id
                        .ok_or(errors::ConnectorError::WebhookReferenceIdNotFound)?,
                ),
            ))
        } else if airwallex::is_refund_event(&details.name) {
            Ok(api_models::webhooks::ObjectReferenceId::RefundId(
                api_models::webhooks::RefundIdType::ConnectorRefundId(
                    details
                        .source_id
                        .ok_or(errors::ConnectorError::WebhookReferenceIdNotFound)?,
                ),
            ))
        } else if airwallex::is_dispute_event(&details.name) {
            let dispute_details: airwallex::AirwallexDisputeObject = details
                .data
                .object
                .parse_value("AirwallexDisputeObject")
                .change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?;

            Ok(api_models::webhooks::ObjectReferenceId::PaymentId(
                api_models::payments::PaymentIdType::ConnectorTransactionId(
                    dispute_details.payment_intent_id,
                ),
            ))
        } else {
            Err(report!(errors::ConnectorError::WebhookEventTypeNotFound))
        }
    }

    fn get_webhook_event_type(
        &self,
        request: &IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<IncomingWebhookEvent, errors::ConnectorError> {
        let details: airwallex::AirwallexWebhookData = request
            .body
            .parse_struct("airwallexWebhookData")
            .change_context(errors::ConnectorError::WebhookReferenceIdNotFound)?;
        Ok(IncomingWebhookEvent::try_from(details.name)?)
    }

    fn get_webhook_resource_object(
        &self,
        request: &IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<Box<dyn masking::ErasedMaskSerialize>, errors::ConnectorError> {
        let details: airwallex::AirwallexWebhookObjectResource = request
            .body
            .parse_struct("AirwallexWebhookObjectResource")


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

impl api::Payment for for Coingate


// Function: create_encrypted_data
// File: crates/router/src/core/payment_methods/cards.rs
// Module: router

pub fn create_encrypted_data<T>(
    key_manager_state: &KeyManagerState,
    key_store: &domain::MerchantKeyStore,
    data: T,
) -> Result<Encryptable<Secret<serde_json::Value>>, error_stack::Report<errors::StorageError>>
where
    T: Debug + serde::Serialize,


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

pub fn get_individual_surcharge_detail_from_redis(
        state: &SessionState,
        surcharge_key: SurchargeKey,
        payment_attempt_id: &str,
    ) -> CustomResult<SurchargeDetails, RedisError>


// Function: payments_link_list
// File: crates/router/src/routes/payment_link.rs
// Module: router

pub fn payments_link_list(
    state: web::Data<AppState>,
    req: actix_web::HttpRequest,
    payload: web::Query<api_models::payments::PaymentLinkListConstraints>,
) -> impl Responder


// Module Structure
// File: crates/router/src/core/payment_methods/tokenize.rs
// Module: router

// Public submodules:
pub mod card_executor;
pub mod payment_method_executor;

// Public exports:
pub use card_executor::*;
pub use payment_method_executor::*;


// File: crates/hyperswitch_domain_models/src/router_data_v2/flow_common_types.rs
// Module: hyperswitch_domain_models
// Public structs: 23

use common_utils::{pii, types::MinorUnit};

use crate::{
    payment_address::PaymentAddress,
    payment_method_data::ApplePayFlow,
    router_data::{
        AccessToken, ConnectorResponseData, PaymentMethodBalance, PaymentMethodToken,
        RecurringMandatePaymentData,
    },
};

#[derive(Debug, Clone)]
pub struct PaymentFlowData {
    pub merchant_id: common_utils::id_type::MerchantId,
    pub customer_id: Option<common_utils::id_type::CustomerId>,
    pub connector_customer: Option<String>,
    pub payment_id: String,
    pub attempt_id: String,
    pub status: common_enums::AttemptStatus,
    pub payment_method: common_enums::PaymentMethod,
    pub description: Option<String>,
    pub address: PaymentAddress,
    pub auth_type: common_enums::AuthenticationType,
    pub connector_meta_data: Option<pii::SecretSerdeValue>,
    pub amount_captured: Option<i64>,
    // minor amount for amount framework
    pub minor_amount_captured: Option<MinorUnit>,
    pub access_token: Option<AccessToken>,
    pub session_token: Option<String>,
    pub reference_id: Option<String>,
    pub payment_method_token: Option<PaymentMethodToken>,
    pub recurring_mandate_payment_data: Option<RecurringMandatePaymentData>,
    pub preprocessing_id: Option<String>,
    /// This is the balance amount for gift cards or voucher
    pub payment_method_balance: Option<PaymentMethodBalance>,

    ///for switching between two different versions of the same connector
    pub connector_api_version: Option<String>,
    /// Contains a reference ID that should be sent in the connector request
    pub connector_request_reference_id: String,

    pub test_mode: Option<bool>,
    pub connector_http_status_code: Option<u16>,
    pub external_latency: Option<u128>,
    /// Contains apple pay flow type simplified or manual
    pub apple_pay_flow: Option<ApplePayFlow>,

    /// This field is used to store various data regarding the response from connector
    pub connector_response: Option<ConnectorResponseData>,
    pub payment_method_status: Option<common_enums::PaymentMethodStatus>,
}

#[derive(Debug, Clone)]
pub struct RefundFlowData {
    pub merchant_id: common_utils::id_type::MerchantId,
    pub customer_id: Option<common_utils::id_type::CustomerId>,
    pub payment_id: String,
    pub attempt_id: String,
    pub status: common_enums::AttemptStatus,
    pub payment_method: common_enums::PaymentMethod,
    pub connector_meta_data: Option<pii::SecretSerdeValue>,
    pub amount_captured: Option<i64>,
    // minor amount for amount framework
    pub minor_amount_captured: Option<MinorUnit>,
    /// Contains a reference ID that should be sent in the connector request
    pub connector_request_reference_id: String,
    pub refund_id: String,
}

#[cfg(feature = "payouts")]
#[derive(Debug, Clone)]
pub struct PayoutFlowData {
    pub merchant_id: common_utils::id_type::MerchantId,
    pub customer_id: Option<common_utils::id_type::CustomerId>,
    pub connector_customer: Option<String>,
    pub address: PaymentAddress,
    pub connector_meta_data: Option<pii::SecretSerdeValue>,
    pub connector_wallets_details: Option<pii::SecretSerdeValue>,
    /// Contains a reference ID that should be sent in the connector request
    pub connector_request_reference_id: String,
    pub payout_method_data: Option<api_models::payouts::PayoutMethodData>,
    pub quote_id: Option<String>,
}

#[cfg(feature = "frm")]
#[derive(Debug, Clone)]
pub struct FrmFlowData {
    pub merchant_id: common_utils::id_type::MerchantId,
    pub payment_id: String,
    pub attempt_id: String,
    pub payment_method: common_enums::enums::PaymentMethod,
    pub connector_request_reference_id: String,
    pub auth_type: common_enums::enums::AuthenticationType,
    pub connector_wallets_details: Option<pii::SecretSerdeValue>,
    pub connector_meta_data: Option<pii::SecretSerdeValue>,
    pub amount_captured: Option<i64>,
    // minor amount for amount framework
    pub minor_amount_captured: Option<MinorUnit>,
}

#[derive(Debug, Clone)]
pub struct ExternalAuthenticationFlowData {
    pub merchant_id: common_utils::id_type::MerchantId,
    pub connector_meta_data: Option<pii::SecretSerdeValue>,
    pub address: PaymentAddress,
}

#[derive(Debug, Clone)]
pub struct DisputesFlowData {
    pub merchant_id: common_utils::id_type::MerchantId,
    pub payment_id: String,
    pub attempt_id: String,
    pub payment_method: common_enums::enums::PaymentMethod,
    pub connector_meta_data: Option<pii::SecretSerdeValue>,
    pub amount_captured: Option<i64>,
    // minor amount for amount framework
    pub minor_amount_captured: Option<MinorUnit>,
    /// Contains a reference ID that should be sent in the connector request
    pub connector_request_reference_id: String,
    pub dispute_id: String,
}

#[derive(Debug, Clone)]
pub struct MandateRevokeFlowData {
    pub merchant_id: common_utils::id_type::MerchantId,
    pub customer_id: common_utils::id_type::CustomerId,
    pub payment_id: Option<String>,
}

#[derive(Debug, Clone)]
pub struct WebhookSourceVerifyData {
    pub merchant_id: common_utils::id_type::MerchantId,
}

#[derive(Debug, Clone)]
pub struct AuthenticationTokenFlowData {}

#[derive(Debug, Clone)]
pub struct AccessTokenFlowData {}

#[derive(Debug, Clone)]
pub struct FilesFlowData {
    pub merchant_id: common_utils::id_type::MerchantId,
    pub payment_id: String,
    pub attempt_id: String,
    pub connector_meta_data: Option<pii::SecretSerdeValue>,
    pub connector_request_reference_id: String,
}

#[derive(Debug, Clone)]
pub struct InvoiceRecordBackData;

#[derive(Debug, Clone)]
pub struct SubscriptionCustomerData {
    pub connector_meta_data: Option<pii::SecretSerdeValue>,
}

#[derive(Debug, Clone)]
pub struct SubscriptionCreateData {
    pub connector_meta_data: Option<pii::SecretSerdeValue>,
}

#[derive(Debug, Clone)]
pub struct GetSubscriptionPlansData {
    pub connector_meta_data: Option<pii::SecretSerdeValue>,
}

#[derive(Debug, Clone)]
pub struct GetSubscriptionPlanPricesData {
    pub connector_meta_data: Option<pii::SecretSerdeValue>,
}

#[derive(Debug, Clone)]
pub struct GetSubscriptionEstimateData;

#[derive(Debug, Clone)]
pub struct UasFlowData {
    pub authenticate_by: String,
    pub source_authentication_id: common_utils::id_type::AuthenticationId,
}

#[derive(Debug, Clone)]
pub struct BillingConnectorPaymentsSyncFlowData;

#[derive(Debug, Clone)]
pub struct BillingConnectorInvoiceSyncFlowData;

#[derive(Debug, Clone)]
pub struct VaultConnectorFlowData {
    pub merchant_id: common_utils::id_type::MerchantId,
}

#[derive(Debug, Clone)]
pub struct GiftCardBalanceCheckFlowData;

#[derive(Debug, Clone)]
pub struct ExternalVaultProxyFlowData {
    pub merchant_id: common_utils::id_type::MerchantId,
    pub customer_id: Option<common_utils::id_type::CustomerId>,
    pub connector_customer: Option<String>,
    pub payment_id: String,
    pub attempt_id: String,
    pub status: common_enums::AttemptStatus,
    pub payment_method: common_enums::PaymentMethod,
    pub description: Option<String>,
    pub address: PaymentAddress,
    pub auth_type: common_enums::AuthenticationType,
    pub connector_meta_data: Option<pii::SecretSerdeValue>,
    pub amount_captured: Option<i64>,
    // minor amount for amount framework
    pub minor_amount_captured: Option<MinorUnit>,
    pub access_token: Option<AccessToken>,
    pub session_token: Option<String>,
    pub reference_id: Option<String>,
    pub payment_method_token: Option<PaymentMethodToken>,
    pub recurring_mandate_payment_data: Option<RecurringMandatePaymentData>,
    pub preprocessing_id: Option<String>,
    /// This is the balance amount for gift cards or voucher
    pub payment_method_balance: Option<PaymentMethodBalance>,

    ///for switching between two different versions of the same connector
    pub connector_api_version: Option<String>,
    /// Contains a reference ID that should be sent in the connector request
    pub connector_request_reference_id: String,

    pub test_mode: Option<bool>,
    pub connector_http_status_code: Option<u16>,
    pub external_latency: Option<u128>,
    /// Contains apple pay flow type simplified or manual
    pub apple_pay_flow: Option<ApplePayFlow>,

    /// This field is used to store various data regarding the response from connector
    pub connector_response: Option<ConnectorResponseData>,
    pub payment_method_status: Option<common_enums::PaymentMethodStatus>,
}


// Struct: LabelInformation
// File: crates/api_models/src/routing.rs
// Module: api_models
// Implementations: 1

pub struct LabelInformation


// Struct: SubError
// File: crates/hyperswitch_connectors/src/connectors/payone/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct SubError


// Implementation: impl Mandate
// File: crates/diesel_models/src/query/mandate.rs
// Module: diesel_models
// Methods: 5 total (0 public)

impl Mandate


// Struct: VerifyConnectorRequest
// File: crates/api_models/src/verify_connector.rs
// Module: api_models
// Implementations: 0

pub struct VerifyConnectorRequest


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

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

use crate::{
    enums,
    query::generics,
    schema::dashboard_metadata::dsl,
    user::dashboard_metadata::{
        DashboardMetadata, DashboardMetadataNew, DashboardMetadataUpdate,
        DashboardMetadataUpdateInternal,
    },
    PgPooledConn, StorageResult,
};

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

impl DashboardMetadata {
    pub async fn update(
        conn: &PgPooledConn,
        user_id: Option<String>,
        merchant_id: id_type::MerchantId,
        org_id: id_type::OrganizationId,
        data_key: enums::DashboardMetadata,
        dashboard_metadata_update: DashboardMetadataUpdate,
    ) -> StorageResult<Self> {
        let predicate = dsl::merchant_id
            .eq(merchant_id.to_owned())
            .and(dsl::org_id.eq(org_id.to_owned()))
            .and(dsl::data_key.eq(data_key.to_owned()));

        if let Some(uid) = user_id {
            generics::generic_update_with_unique_predicate_get_result::<
                <Self as HasTable>::Table,
                _,
                _,
                _,
            >(
                conn,
                predicate.and(dsl::user_id.eq(uid)),
                DashboardMetadataUpdateInternal::from(dashboard_metadata_update),
            )
            .await
        } else {
            generics::generic_update_with_unique_predicate_get_result::<
                <Self as HasTable>::Table,
                _,
                _,
                _,
            >(
                conn,
                predicate.and(dsl::user_id.is_null()),
                DashboardMetadataUpdateInternal::from(dashboard_metadata_update),
            )
            .await
        }
    }

    pub async fn find_user_scoped_dashboard_metadata(
        conn: &PgPooledConn,
        user_id: String,
        merchant_id: id_type::MerchantId,
        org_id: id_type::OrganizationId,
        data_types: Vec<enums::DashboardMetadata>,
    ) -> StorageResult<Vec<Self>> {
        let predicate = dsl::user_id
            .eq(user_id)
            .and(dsl::merchant_id.eq(merchant_id))
            .and(dsl::org_id.eq(org_id))
            .and(dsl::data_key.eq_any(data_types));

        generics::generic_filter::<<Self as HasTable>::Table, _, _, _>(
            conn,
            predicate,
            None,
            None,
            Some(dsl::last_modified_at.asc()),
        )
        .await
    }

    pub async fn find_merchant_scoped_dashboard_metadata(
        conn: &PgPooledConn,
        merchant_id: id_type::MerchantId,
        org_id: id_type::OrganizationId,
        data_types: Vec<enums::DashboardMetadata>,
    ) -> StorageResult<Vec<Self>> {
        let predicate = dsl::merchant_id
            .eq(merchant_id)
            .and(dsl::org_id.eq(org_id))
            .and(dsl::data_key.eq_any(data_types));

        generics::generic_filter::<<Self as HasTable>::Table, _, _, _>(
            conn,
            predicate,
            None,
            None,
            Some(dsl::last_modified_at.asc()),
        )
        .await
    }

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

    pub async fn delete_user_scoped_dashboard_metadata_by_merchant_id_data_key(
        conn: &PgPooledConn,
        user_id: String,
        merchant_id: id_type::MerchantId,
        data_key: enums::DashboardMetadata,
    ) -> StorageResult<Self> {
        generics::generic_delete_one_with_result::<<Self as HasTable>::Table, _, _>(
            conn,
            dsl::user_id
                .eq(user_id)
                .and(dsl::merchant_id.eq(merchant_id))
                .and(dsl::data_key.eq(data_key)),
        )
        .await
    }
}