    connectors::Bankofamerica,
    connectors::Barclaycard,
    connectors::Billwerk,
    connectors::Bitpay,
    connectors::Blackhawknetwork,
    connectors::Bluecode,
    connectors::Bluesnap,
    connectors::Braintree,
    connectors::Boku,
    connectors::Breadpay,
    connectors::Cashtocode,
    connectors::Celero,
    connectors::Chargebee,
    connectors::Checkbook,
    connectors::Checkout,
    connectors::Coinbase,
    connectors::Coingate,
    connectors::Cryptopay,
    connectors::Custombilling,
    connectors::Cybersource,
    connectors::Datatrans,
    connectors::Deutschebank,
    connectors::Digitalvirgo,
    connectors::Dlocal,
    connectors::Dwolla,
    connectors::Elavon,
    connectors::Facilitapay,
    connectors::Fiserv,
    connectors::Fiservemea,
    connectors::Fiuu,
    connectors::Flexiti,
    connectors::Forte,
    connectors::Getnet,
    connectors::Globalpay,
    connectors::Globepay,
    connectors::Gocardless,
    connectors::Gpayments,
    connectors::Hipay,
    connectors::Helcim,
    connectors::HyperswitchVault,
    connectors::Hyperwallet,
    connectors::Iatapay,
    connectors::Inespay,
    connectors::Itaubank,
    connectors::Jpmorgan,
    connectors::Juspaythreedsserver,
    connectors::Katapult,
    connectors::Klarna,
    connectors::Netcetera,
    connectors::Nmi,
    connectors::Noon,
    connectors::Nordea,
    connectors::Novalnet,
    connectors::Nexinets,
    connectors::Nexixpay,
    connectors::Opayo,
    connectors::Opennode,
    connectors::Nuvei,
    connectors::Paybox,
    connectors::Payeezy,
    connectors::Payload,
    connectors::Payme,
    connectors::Paypal,
    connectors::Paysafe,
    connectors::Paystack,
    connectors::Paytm,
    connectors::Payone,
    connectors::Payu,
    connectors::Phonepe,
    connectors::Placetopay,
    connectors::Plaid,
    connectors::Powertranz,
    connectors::Prophetpay,
    connectors::Mifinity,
    connectors::Mollie,
    connectors::Moneris,
    connectors::Mpgs,
    connectors::Multisafepay,
    connectors::Rapyd,
    connectors::Razorpay,
    connectors::Recurly,
    connectors::Redsys,
    connectors::Riskified,
    connectors::Santander,
    connectors::Shift4,
    connectors::Sift,
    connectors::Silverflow,
    connectors::Signifyd,
    connectors::Stax,
    connectors::Square,
    connectors::Stripe,
    connectors::Stripebilling,
    connectors::Taxjar,
    connectors::Threedsecureio,
    connectors::Thunes,
    connectors::Tokenio,
    connectors::Trustpay,
    connectors::Trustpayments,
    connectors::Tsys,
    connectors::UnifiedAuthenticationService,
    connectors::Worldline,
    connectors::Worldpay,
    connectors::Worldpayvantiv,
    connectors::Worldpayxml,
    connectors::Wellsfargo,
    connectors::Wellsfargopayout,
    connectors::Volt,
    connectors::Xendit,
    connectors::Zen,
    connectors::Zsl,
    connectors::CtpMastercard
);

#[cfg(feature = "payouts")]
macro_rules! default_imp_for_payouts_fulfill {
    ($($path:ident::$connector:ident),*) => {
        $(
            impl PayoutFulfill for $path::$connector {}
            impl
            ConnectorIntegration<
            PoFulfill,
            PayoutsData,
            PayoutsResponseData,
        > for $path::$connector
        {}
    )*
    };
}

#[cfg(feature = "payouts")]
default_imp_for_payouts_fulfill!(
    connectors::Paysafe,
    connectors::Affirm,
    connectors::Vgs,
    connectors::Aci,
    connectors::Airwallex,
    connectors::Amazonpay,
    connectors::Archipel,
    connectors::Authipay,
    connectors::Authorizedotnet,
    connectors::Bambora,
    connectors::Bamboraapac,
    connectors::Bankofamerica,
    connectors::Barclaycard,
    connectors::Billwerk,
    connectors::Bitpay,
    connectors::Blackhawknetwork,
    connectors::Bluecode,
    connectors::Bluesnap,
    connectors::Braintree,
    connectors::Boku,
    connectors::Breadpay,
    connectors::Cashtocode,
    connectors::Celero,
    connectors::Chargebee,
    connectors::Checkbook,
    connectors::Checkout,
    connectors::Coinbase,
    connectors::Coingate,
    connectors::Cryptopay,
    connectors::Custombilling,
    connectors::Datatrans,
    connectors::Deutschebank,
    connectors::Digitalvirgo,
    connectors::Dlocal,
    connectors::Dwolla,
    connectors::Elavon,
    connectors::Facilitapay,
    connectors::Fiserv,
    connectors::Fiservemea,
    connectors::Fiuu,
    connectors::Flexiti,
    connectors::Forte,
    connectors::Getnet,
    connectors::Globalpay,
    connectors::Globepay,
    connectors::Gocardless,
    connectors::Gpayments,
    connectors::Hipay,
    connectors::Helcim,
    connectors::HyperswitchVault,
    connectors::Hyperwallet,
    connectors::Iatapay,
    connectors::Inespay,
    connectors::Itaubank,
    connectors::Jpmorgan,
    connectors::Juspaythreedsserver,
    connectors::Katapult,
    connectors::Klarna,
    connectors::Netcetera,
    connectors::Noon,
    connectors::Nordea,
    connectors::Novalnet,
    connectors::Nexinets,
    connectors::Nexixpay,
    connectors::Opayo,
    connectors::Opennode,
    connectors::Nmi,
    connectors::Nuvei,
    connectors::Paybox,
    connectors::Payeezy,
    connectors::Payload,
    connectors::Payme,
    connectors::Paystack,
    connectors::Paytm,
    connectors::Payu,
    connectors::Phonepe,
    connectors::Placetopay,
    connectors::Plaid,
    connectors::Powertranz,
    connectors::Prophetpay,
    connectors::Mifinity,
    connectors::Mollie,
    connectors::Moneris,
    connectors::Mpgs,
    connectors::Multisafepay,
    connectors::Rapyd,
    connectors::Razorpay,
    connectors::Recurly,
    connectors::Redsys,
    connectors::Riskified,
    connectors::Santander,
    connectors::Shift4,
    connectors::Sift,
    connectors::Silverflow,
    connectors::Signifyd,
    connectors::Stax,
    connectors::Square,
    connectors::Stripebilling,
    connectors::Taxjar,
    connectors::Threedsecureio,
    connectors::Thunes,
    connectors::Tokenio,
    connectors::Trustpay,
    connectors::Trustpayments,
    connectors::Tsys,
    connectors::UnifiedAuthenticationService,
    connectors::Worldline,
    connectors::Worldpay,
    connectors::Worldpayvantiv,
    connectors::Worldpayxml,
    connectors::Wellsfargo,
    connectors::Wellsfargopayout,
    connectors::Volt,
    connectors::Xendit,
    connectors::Zen,
    connectors::Zsl,
    connectors::CtpMastercard
);

#[cfg(feature = "payouts")]
macro_rules! default_imp_for_payouts_cancel {
    ($($path:ident::$connector:ident),*) => {
        $(
            impl PayoutCancel for $path::$connector {}
            impl
            ConnectorIntegration<
            PoCancel,
            PayoutsData,
            PayoutsResponseData,
        > for $path::$connector
        {}
    )*
    };
}

#[cfg(feature = "payouts")]
default_imp_for_payouts_cancel!(
    connectors::Vgs,
    connectors::Aci,
    connectors::Adyenplatform,
    connectors::Affirm,
    connectors::Airwallex,
    connectors::Amazonpay,
    connectors::Archipel,
    connectors::Authipay,
    connectors::Authorizedotnet,
    connectors::Bambora,
    connectors::Bamboraapac,
    connectors::Bankofamerica,
    connectors::Barclaycard,
    connectors::Billwerk,
    connectors::Bitpay,
    connectors::Blackhawknetwork,
    connectors::Bluecode,
    connectors::Bluesnap,
    connectors::Braintree,
    connectors::Boku,
    connectors::Breadpay,
    connectors::Cashtocode,
    connectors::Celero,
    connectors::Chargebee,
    connectors::Checkbook,
    connectors::Checkout,
    connectors::Coinbase,
    connectors::Coingate,
    connectors::Cryptopay,
    connectors::Custombilling,
    connectors::Cybersource,
    connectors::Datatrans,
    connectors::Deutschebank,
    connectors::Digitalvirgo,
    connectors::Dlocal,
    connectors::Dwolla,
    connectors::Elavon,
    connectors::Facilitapay,
    connectors::Fiserv,
    connectors::Fiservemea,
    connectors::Fiuu,
    connectors::Flexiti,
    connectors::Forte,
    connectors::Getnet,
    connectors::Globalpay,
    connectors::Globepay,
    connectors::Gocardless,
    connectors::Gpayments,
    connectors::Hipay,
    connectors::Helcim,
    connectors::HyperswitchVault,
    connectors::Hyperwallet,
    connectors::Iatapay,
    connectors::Inespay,
    connectors::Itaubank,
    connectors::Jpmorgan,
    connectors::Juspaythreedsserver,
    connectors::Katapult,
    connectors::Klarna,
    connectors::Netcetera,
    connectors::Nmi,
    connectors::Noon,
    connectors::Nordea,
    connectors::Novalnet,
    connectors::Nexinets,
    connectors::Nexixpay,
    connectors::Opayo,
    connectors::Opennode,
    connectors::Nuvei,
    connectors::Paybox,
    connectors::Payeezy,
    connectors::Payload,
    connectors::Payme,
    connectors::Paypal,
    connectors::Paysafe,
    connectors::Paystack,
    connectors::Paytm,
    connectors::Payone,
    connectors::Payu,
    connectors::Phonepe,
    connectors::Placetopay,
    connectors::Plaid,
    connectors::Powertranz,
    connectors::Prophetpay,
    connectors::Mifinity,
    connectors::Mollie,
    connectors::Moneris,
    connectors::Mpgs,
    connectors::Multisafepay,
    connectors::Rapyd,
    connectors::Razorpay,
    connectors::Recurly,
    connectors::Redsys,
    connectors::Riskified,
    connectors::Santander,
    connectors::Shift4,
    connectors::Sift,
    connectors::Silverflow,
    connectors::Signifyd,
    connectors::Stax,
    connectors::Square,
    connectors::Stripebilling,
    connectors::Taxjar,
    connectors::Threedsecureio,
    connectors::Thunes,
    connectors::Tokenio,
    connectors::Trustpay,
    connectors::Trustpayments,
    connectors::Tsys,
    connectors::UnifiedAuthenticationService,
    connectors::Worldline,
    connectors::Worldpay,
    connectors::Worldpayvantiv,
    connectors::Worldpayxml,
    connectors::Wellsfargo,
    connectors::Wellsfargopayout,
    connectors::Volt,
    connectors::Xendit,
    connectors::Zen,
    connectors::Zsl,
    connectors::CtpMastercard
);

#[cfg(feature = "payouts")]
macro_rules! default_imp_for_payouts_quote {
    ($($path:ident::$connector:ident),*) => {
        $(
            impl PayoutQuote for $path::$connector {}
            impl
            ConnectorIntegration<
            PoQuote,
            PayoutsData,
            PayoutsResponseData,
        > for $path::$connector
        {}
    )*
    };
}

#[cfg(feature = "payouts")]
default_imp_for_payouts_quote!(
    connectors::Vgs,
    connectors::Aci,
    connectors::Adyen,
    connectors::Adyenplatform,
    connectors::Affirm,
    connectors::Airwallex,
    connectors::Amazonpay,
    connectors::Archipel,
    connectors::Authipay,
    connectors::Authorizedotnet,
    connectors::Bambora,
    connectors::Bamboraapac,
    connectors::Bankofamerica,
    connectors::Barclaycard,
    connectors::Billwerk,
    connectors::Bitpay,
    connectors::Blackhawknetwork,
    connectors::Bluecode,
    connectors::Bluesnap,
    connectors::Braintree,
    connectors::Boku,
    connectors::Breadpay,
    connectors::Cashtocode,
    connectors::Celero,
    connectors::Chargebee,
    connectors::Checkbook,
    connectors::Checkout,
    connectors::Coinbase,
    connectors::Coingate,
    connectors::Cryptopay,
    connectors::Custombilling,
    connectors::Cybersource,
    connectors::Datatrans,
    connectors::Deutschebank,
    connectors::Digitalvirgo,
    connectors::Dlocal,
    connectors::Dwolla,
    connectors::Elavon,
    connectors::Facilitapay,
    connectors::Fiserv,
    connectors::Fiservemea,
    connectors::Fiuu,
    connectors::Flexiti,
    connectors::Forte,
    connectors::Getnet,
    connectors::Globalpay,
    connectors::Globepay,
    connectors::Gocardless,
    connectors::Gpayments,
    connectors::Hipay,
    connectors::Helcim,
    connectors::HyperswitchVault,
    connectors::Hyperwallet,
    connectors::Iatapay,
    connectors::Inespay,
    connectors::Itaubank,
    connectors::Jpmorgan,
    connectors::Juspaythreedsserver,
    connectors::Katapult,
    connectors::Klarna,
    connectors::Netcetera,
    connectors::Nmi,
    connectors::Noon,
    connectors::Nordea,
    connectors::Novalnet,
    connectors::Nexinets,
    connectors::Nexixpay,
    connectors::Opayo,
    connectors::Opennode,
    connectors::Nuvei,
    connectors::Paybox,
    connectors::Payeezy,
    connectors::Payload,
    connectors::Payone,
    connectors::Payme,
    connectors::Paypal,
    connectors::Paysafe,
    connectors::Paystack,
    connectors::Paytm,
    connectors::Payu,
    connectors::Phonepe,
    connectors::Placetopay,
    connectors::Plaid,
    connectors::Powertranz,
    connectors::Prophetpay,
    connectors::Mifinity,
    connectors::Mollie,
    connectors::Moneris,
    connectors::Mpgs,
    connectors::Multisafepay,
    connectors::Rapyd,
    connectors::Razorpay,
    connectors::Recurly,
    connectors::Redsys,
    connectors::Riskified,
    connectors::Santander,
    connectors::Shift4,
    connectors::Sift,
    connectors::Silverflow,
    connectors::Signifyd,
    connectors::Stax,
    connectors::Square,
    connectors::Stripe,
    connectors::Stripebilling,
    connectors::Taxjar,
    connectors::Threedsecureio,
    connectors::Thunes,
    connectors::Tokenio,
    connectors::Trustpay,
    connectors::Trustpayments,
    connectors::Tsys,
    connectors::UnifiedAuthenticationService,
    connectors::Worldline,
    connectors::Worldpay,
    connectors::Worldpayvantiv,
    connectors::Worldpayxml,
    connectors::Wellsfargo,
    connectors::Wellsfargopayout,
    connectors::Volt,
    connectors::Xendit,
    connectors::Zen,
    connectors::Zsl,
    connectors::CtpMastercard
);

#[cfg(feature = "payouts")]
macro_rules! default_imp_for_payouts_recipient {
    ($($path:ident::$connector:ident),*) => {
        $(
            impl PayoutRecipient for $path::$connector {}
            impl
            ConnectorIntegration<
            PoRecipient,
            PayoutsData,
            PayoutsResponseData,
        > for $path::$connector
        {}
    )*
    };
}

#[cfg(feature = "payouts")]
default_imp_for_payouts_recipient!(
    connectors::Vgs,
    connectors::Aci,
    connectors::Adyen,
    connectors::Adyenplatform,
    connectors::Affirm,
    connectors::Airwallex,
    connectors::Amazonpay,
    connectors::Archipel,
    connectors::Authipay,
    connectors::Authorizedotnet,
    connectors::Bambora,
    connectors::Bamboraapac,
    connectors::Bankofamerica,
    connectors::Barclaycard,
    connectors::Billwerk,
    connectors::Bitpay,
    connectors::Blackhawknetwork,
    connectors::Bluecode,
    connectors::Bluesnap,
    connectors::Braintree,
    connectors::Boku,
    connectors::Breadpay,
    connectors::Cashtocode,
    connectors::Celero,
    connectors::Chargebee,
    connectors::Checkbook,
    connectors::Checkout,
    connectors::Coinbase,
    connectors::Coingate,
    connectors::Cryptopay,
    connectors::Custombilling,
    connectors::Cybersource,
    connectors::Datatrans,
    connectors::Deutschebank,
    connectors::Digitalvirgo,
    connectors::Dlocal,
    connectors::Dwolla,
    connectors::Elavon,
    connectors::Facilitapay,
    connectors::Fiserv,
    connectors::Fiservemea,
    connectors::Fiuu,
    connectors::Flexiti,
    connectors::Forte,
    connectors::Getnet,
    connectors::Globalpay,
    connectors::Globepay,
    connectors::Gocardless,
    connectors::Gpayments,
    connectors::Hipay,
    connectors::Helcim,
    connectors::HyperswitchVault,
    connectors::Hyperwallet,
    connectors::Iatapay,
    connectors::Inespay,
    connectors::Itaubank,
    connectors::Jpmorgan,
    connectors::Juspaythreedsserver,
    connectors::Katapult,
    connectors::Klarna,
    connectors::Netcetera,
    connectors::Nmi,
    connectors::Noon,
    connectors::Nordea,
    connectors::Novalnet,
    connectors::Nexinets,
    connectors::Nexixpay,
    connectors::Opayo,
    connectors::Opennode,
    connectors::Nuvei,
    connectors::Paybox,
    connectors::Payeezy,
    connectors::Payload,
    connectors::Payme,
    connectors::Payone,
    connectors::Paypal,
    connectors::Paysafe,
    connectors::Paystack,
    connectors::Paytm,
    connectors::Payu,
    connectors::Phonepe,
    connectors::Placetopay,
    connectors::Plaid,
    connectors::Powertranz,
    connectors::Prophetpay,
    connectors::Mifinity,
    connectors::Mollie,
    connectors::Moneris,
    connectors::Mpgs,
    connectors::Multisafepay,
    connectors::Rapyd,
    connectors::Razorpay,
    connectors::Recurly,
    connectors::Redsys,
    connectors::Riskified,
    connectors::Santander,
    connectors::Shift4,
    connectors::Sift,
    connectors::Silverflow,
    connectors::Signifyd,
    connectors::Stax,
    connectors::Square,
    connectors::Stripebilling,
    connectors::Taxjar,
    connectors::Threedsecureio,
    connectors::Thunes,
    connectors::Tokenio,
    connectors::Trustpay,
    connectors::Trustpayments,
    connectors::Tsys,
    connectors::UnifiedAuthenticationService,
    connectors::Worldline,
    connectors::Worldpay,
    connectors::Worldpayvantiv,
    connectors::Worldpayxml,
    connectors::Wellsfargo,
    connectors::Wellsfargopayout,
    connectors::Volt,
    connectors::Xendit,
    connectors::Zen,
    connectors::Zsl,
    connectors::CtpMastercard
);

#[cfg(feature = "payouts")]
macro_rules! default_imp_for_payouts_recipient_account {
    ($($path:ident::$connector:ident),*) => {
        $(
            impl PayoutRecipientAccount for $path::$connector {}
            impl
            ConnectorIntegration<
            PoRecipientAccount,
            PayoutsData,
            PayoutsResponseData,
        > for $path::$connector
        {}
    )*
    };
}

#[cfg(feature = "payouts")]
default_imp_for_payouts_recipient_account!(
    connectors::Vgs,
    connectors::Aci,
    connectors::Adyen,
    connectors::Adyenplatform,
    connectors::Affirm,
    connectors::Airwallex,
    connectors::Amazonpay,
    connectors::Archipel,
    connectors::Authipay,
    connectors::Authorizedotnet,
    connectors::Bambora,
    connectors::Bamboraapac,
    connectors::Bankofamerica,
    connectors::Barclaycard,
    connectors::Billwerk,
    connectors::Bitpay,
    connectors::Blackhawknetwork,
    connectors::Bluecode,
    connectors::Bluesnap,
    connectors::Braintree,
    connectors::Boku,
    connectors::Breadpay,
    connectors::Cashtocode,
    connectors::Celero,
    connectors::Chargebee,
    connectors::Checkbook,
    connectors::Checkout,
    connectors::Coinbase,
    connectors::Coingate,
    connectors::Cryptopay,
    connectors::Custombilling,
    connectors::Cybersource,
    connectors::Datatrans,
    connectors::Deutschebank,
    connectors::Digitalvirgo,
    connectors::Dlocal,
    connectors::Dwolla,
    connectors::Ebanx,
    connectors::Elavon,
    connectors::Facilitapay,
    connectors::Fiserv,
    connectors::Fiservemea,
    connectors::Fiuu,
    connectors::Flexiti,
    connectors::Forte,
    connectors::Getnet,
    connectors::Globalpay,
    connectors::Globepay,
    connectors::Gocardless,
    connectors::Gpayments,
    connectors::Hipay,
    connectors::Helcim,
    connectors::HyperswitchVault,
    connectors::Hyperwallet,
    connectors::Iatapay,
    connectors::Inespay,
    connectors::Itaubank,
    connectors::Jpmorgan,
    connectors::Juspaythreedsserver,
    connectors::Katapult,
    connectors::Klarna,
    connectors::Netcetera,
    connectors::Nmi,
    connectors::Noon,
    connectors::Nordea,
    connectors::Novalnet,
    connectors::Nexinets,
    connectors::Nexixpay,
    connectors::Opayo,
    connectors::Opennode,
    connectors::Nuvei,
    connectors::Paybox,
    connectors::Payeezy,
    connectors::Payload,
    connectors::Payme,
    connectors::Payone,
    connectors::Paypal,
    connectors::Paysafe,
    connectors::Paystack,
    connectors::Paytm,
    connectors::Payu,
    connectors::Phonepe,
    connectors::Placetopay,
    connectors::Plaid,
    connectors::Powertranz,
    connectors::Prophetpay,
    connectors::Mifinity,
    connectors::Mollie,
    connectors::Moneris,
    connectors::Mpgs,
    connectors::Multisafepay,
    connectors::Rapyd,
    connectors::Razorpay,
    connectors::Recurly,
    connectors::Redsys,
    connectors::Riskified,
    connectors::Santander,
    connectors::Shift4,
    connectors::Sift,
    connectors::Silverflow,
    connectors::Signifyd,
    connectors::Stax,
    connectors::Square,
    connectors::Stripebilling,
    connectors::Taxjar,
    connectors::Threedsecureio,
    connectors::Thunes,
    connectors::Tokenio,
    connectors::Trustpay,
    connectors::Trustpayments,
    connectors::Tsys,
    connectors::UnifiedAuthenticationService,
    connectors::Wise,
    connectors::Worldline,
    connectors::Worldpay,
    connectors::Worldpayvantiv,
    connectors::Worldpayxml,
    connectors::Wellsfargo,
    connectors::Wellsfargopayout,
    connectors::Volt,
    connectors::Xendit,
    connectors::Zen,
    connectors::Zsl,
    connectors::CtpMastercard
);

#[cfg(feature = "frm")]
macro_rules! default_imp_for_frm_sale {
    ($($path:ident::$connector:ident),*) => {
        $(
            impl FraudCheckSale for $path::$connector {}
            impl
            ConnectorIntegration<
            Sale,
            FraudCheckSaleData,
            FraudCheckResponseData,
        > for $path::$connector
        {}
    )*
    };
}

#[cfg(feature = "frm")]
default_imp_for_frm_sale!(
    connectors::Vgs,
    connectors::Aci,
    connectors::Adyen,
    connectors::Adyenplatform,
    connectors::Affirm,
    connectors::Airwallex,
    connectors::Amazonpay,
    connectors::Archipel,
    connectors::Authipay,
    connectors::Authorizedotnet,
    connectors::Bambora,
    connectors::Bamboraapac,
    connectors::Bankofamerica,
    connectors::Barclaycard,
    connectors::Billwerk,
    connectors::Bitpay,
    connectors::Blackhawknetwork,
    connectors::Bluecode,
    connectors::Bluesnap,
    connectors::Braintree,
    connectors::Boku,
    connectors::Breadpay,
    connectors::Cashtocode,
    connectors::Celero,
    connectors::Chargebee,
    connectors::Checkbook,
    connectors::Checkout,
    connectors::Coinbase,
    connectors::Coingate,
    connectors::Cryptopay,
    connectors::Custombilling,
    connectors::Cybersource,
    connectors::Datatrans,
    connectors::Deutschebank,
    connectors::Digitalvirgo,
    connectors::Dlocal,
    connectors::Dwolla,
    connectors::Ebanx,
    connectors::Elavon,
    connectors::Facilitapay,
    connectors::Fiserv,
    connectors::Fiservemea,
    connectors::Fiuu,
    connectors::Flexiti,
    connectors::Forte,
    connectors::Getnet,
    connectors::Globalpay,
    connectors::Globepay,
    connectors::Gocardless,
    connectors::Gpayments,
    connectors::Hipay,
    connectors::Helcim,
    connectors::HyperswitchVault,
    connectors::Hyperwallet,
    connectors::Iatapay,
    connectors::Inespay,
    connectors::Itaubank,
    connectors::Jpmorgan,
    connectors::Juspaythreedsserver,
    connectors::Katapult,
    connectors::Klarna,
    connectors::Netcetera,
    connectors::Nomupay,
    connectors::Nmi,
    connectors::Noon,
    connectors::Nordea,
    connectors::Novalnet,
    connectors::Nexinets,
    connectors::Nexixpay,
    connectors::Opayo,
    connectors::Opennode,
    connectors::Nuvei,
    connectors::Paybox,
    connectors::Payeezy,
    connectors::Payload,
    connectors::Payme,
    connectors::Payone,
    connectors::Paypal,
    connectors::Paysafe,
    connectors::Paystack,
    connectors::Paytm,
    connectors::Payu,
    connectors::Phonepe,
    connectors::Placetopay,
    connectors::Plaid,
    connectors::Powertranz,
    connectors::Prophetpay,
    connectors::Mifinity,
    connectors::Mollie,
    connectors::Moneris,
    connectors::Mpgs,
    connectors::Multisafepay,
    connectors::Rapyd,
    connectors::Razorpay,
    connectors::Recurly,
    connectors::Redsys,
    connectors::Santander,
    connectors::Shift4,
    connectors::Sift,
    connectors::Silverflow,
    connectors::Stax,
    connectors::Square,
    connectors::Stripe,
    connectors::Stripebilling,
    connectors::Taxjar,
    connectors::Threedsecureio,
    connectors::Thunes,
    connectors::Tokenio,
    connectors::Trustpay,
    connectors::Trustpayments,
    connectors::Tsys,
    connectors::UnifiedAuthenticationService,
    connectors::Wise,
    connectors::Worldline,
    connectors::Worldpay,
    connectors::Worldpayvantiv,
    connectors::Worldpayxml,
    connectors::Wellsfargo,
    connectors::Wellsfargopayout,
    connectors::Volt,
    connectors::Xendit,
    connectors::Zen,
    connectors::Zsl,
    connectors::CtpMastercard
);

#[cfg(feature = "frm")]
macro_rules! default_imp_for_frm_checkout {
    ($($path:ident::$connector:ident),*) => {
        $(
            impl FraudCheckCheckout for $path::$connector {}
            impl
            ConnectorIntegration<
            Checkout,
            FraudCheckCheckoutData,
            FraudCheckResponseData,
        > for $path::$connector
        {}
    )*
    };
}

#[cfg(feature = "frm")]
default_imp_for_frm_checkout!(
    connectors::Vgs,
    connectors::Aci,
    connectors::Adyen,
    connectors::Adyenplatform,
    connectors::Affirm,
    connectors::Airwallex,
    connectors::Amazonpay,
    connectors::Archipel,
    connectors::Authipay,
    connectors::Authorizedotnet,
    connectors::Bambora,
    connectors::Bamboraapac,
    connectors::Bankofamerica,
    connectors::Barclaycard,
    connectors::Billwerk,
    connectors::Bitpay,
    connectors::Blackhawknetwork,
    connectors::Bluecode,
    connectors::Bluesnap,
    connectors::Braintree,
    connectors::Boku,
    connectors::Breadpay,
    connectors::Cashtocode,
    connectors::Celero,
    connectors::Chargebee,
    connectors::Checkbook,
    connectors::Checkout,
    connectors::Coinbase,
    connectors::Coingate,
    connectors::Cryptopay,
    connectors::Custombilling,
    connectors::Cybersource,
    connectors::Datatrans,
    connectors::Deutschebank,
    connectors::Digitalvirgo,
    connectors::Dlocal,
    connectors::Dwolla,
    connectors::Ebanx,
    connectors::Elavon,
    connectors::Facilitapay,
    connectors::Fiserv,
    connectors::Fiservemea,
    connectors::Fiuu,
    connectors::Flexiti,
    connectors::Forte,
    connectors::Getnet,
    connectors::Globalpay,
    connectors::Globepay,
    connectors::Gocardless,
    connectors::Gpayments,
    connectors::Hipay,
    connectors::Helcim,
    connectors::HyperswitchVault,
    connectors::Hyperwallet,
    connectors::Iatapay,
    connectors::Inespay,
    connectors::Itaubank,
    connectors::Jpmorgan,
    connectors::Juspaythreedsserver,
    connectors::Katapult,
    connectors::Klarna,
    connectors::Netcetera,
    connectors::Nmi,
    connectors::Nomupay,
    connectors::Noon,
    connectors::Nordea,
    connectors::Novalnet,
    connectors::Nexinets,
    connectors::Nexixpay,
    connectors::Opayo,
    connectors::Opennode,
    connectors::Nuvei,
    connectors::Paybox,
    connectors::Payeezy,
    connectors::Payload,
    connectors::Payme,
    connectors::Payone,
    connectors::Paypal,
    connectors::Paysafe,
    connectors::Paystack,
    connectors::Paytm,
    connectors::Payu,
    connectors::Phonepe,
    connectors::Placetopay,
    connectors::Plaid,
    connectors::Powertranz,
    connectors::Prophetpay,
    connectors::Mifinity,
    connectors::Mollie,
    connectors::Moneris,
    connectors::Mpgs,
    connectors::Multisafepay,
    connectors::Rapyd,
    connectors::Razorpay,
    connectors::Recurly,
    connectors::Redsys,
    connectors::Santander,
    connectors::Shift4,
    connectors::Sift,
    connectors::Silverflow,
    connectors::Stax,
    connectors::Square,
    connectors::Stripe,
    connectors::Stripebilling,
    connectors::Taxjar,
    connectors::Threedsecureio,
    connectors::Thunes,
    connectors::Tokenio,
    connectors::Trustpay,
    connectors::Trustpayments,
    connectors::Tsys,
    connectors::UnifiedAuthenticationService,
    connectors::Wise,
    connectors::Worldline,
    connectors::Worldpay,
    connectors::Worldpayvantiv,
    connectors::Worldpayxml,
    connectors::Wellsfargo,
    connectors::Wellsfargopayout,
    connectors::Volt,
    connectors::Xendit,
    connectors::Zen,
    connectors::Zsl,
    connectors::CtpMastercard
);

#[cfg(feature = "frm")]
macro_rules! default_imp_for_frm_transaction {
    ($($path:ident::$connector:ident),*) => {
        $(
            impl FraudCheckTransaction for $path::$connector {}
            impl
            ConnectorIntegration<
            Transaction,
            FraudCheckTransactionData,
            FraudCheckResponseData,
        > for $path::$connector
        {}
    )*
    };
}

#[cfg(feature = "frm")]
default_imp_for_frm_transaction!(
    connectors::Vgs,
    connectors::Aci,
    connectors::Adyen,
    connectors::Adyenplatform,
    connectors::Affirm,
    connectors::Airwallex,
    connectors::Amazonpay,
    connectors::Archipel,
    connectors::Authipay,
    connectors::Authorizedotnet,
    connectors::Bambora,
    connectors::Bamboraapac,
    connectors::Bankofamerica,
    connectors::Barclaycard,
    connectors::Billwerk,
    connectors::Bitpay,
    connectors::Blackhawknetwork,
    connectors::Bluecode,
    connectors::Bluesnap,
    connectors::Braintree,
    connectors::Boku,
    connectors::Breadpay,
    connectors::Cashtocode,
    connectors::Celero,
    connectors::Chargebee,
    connectors::Checkbook,
    connectors::Checkout,
    connectors::Coinbase,
    connectors::Coingate,
    connectors::Cryptopay,
    connectors::Custombilling,
    connectors::Cybersource,
    connectors::Datatrans,
    connectors::Deutschebank,
    connectors::Digitalvirgo,
    connectors::Dlocal,
    connectors::Dwolla,
    connectors::Ebanx,
    connectors::Elavon,
    connectors::Facilitapay,
    connectors::Fiserv,
    connectors::Fiservemea,
    connectors::Fiuu,
    connectors::Flexiti,
    connectors::Forte,
    connectors::Getnet,
    connectors::Globalpay,
    connectors::Globepay,
    connectors::Gocardless,
    connectors::Gpayments,
    connectors::Hipay,
    connectors::Helcim,
    connectors::HyperswitchVault,
    connectors::Hyperwallet,
    connectors::Iatapay,
    connectors::Inespay,
    connectors::Itaubank,
    connectors::Jpmorgan,
    connectors::Juspaythreedsserver,
    connectors::Katapult,
    connectors::Klarna,
    connectors::Netcetera,
    connectors::Nmi,
    connectors::Nomupay,
    connectors::Noon,
    connectors::Nordea,
    connectors::Novalnet,
    connectors::Nexinets,
    connectors::Nexixpay,
    connectors::Opayo,
    connectors::Opennode,
    connectors::Nuvei,
    connectors::Paybox,
    connectors::Payeezy,
    connectors::Payload,
    connectors::Payme,
    connectors::Payone,
    connectors::Paypal,
    connectors::Paysafe,
    connectors::Paystack,
    connectors::Paytm,
    connectors::Payu,
    connectors::Phonepe,
    connectors::Placetopay,
    connectors::Plaid,
    connectors::Powertranz,
    connectors::Prophetpay,
    connectors::Mifinity,
    connectors::Mollie,
    connectors::Moneris,
    connectors::Mpgs,
    connectors::Multisafepay,
    connectors::Rapyd,
    connectors::Razorpay,
    connectors::Recurly,
    connectors::Redsys,
    connectors::Santander,
    connectors::Shift4,
    connectors::Sift,
    connectors::Silverflow,
    connectors::Stax,
    connectors::Square,
    connectors::Stripe,
    connectors::Stripebilling,
    connectors::Taxjar,
    connectors::Threedsecureio,
    connectors::Thunes,
    connectors::Tokenio,
    connectors::Trustpay,
    connectors::Trustpayments,
    connectors::Tsys,
    connectors::UnifiedAuthenticationService,
    connectors::Wise,
    connectors::Worldline,
    connectors::Worldpay,
    connectors::Worldpayvantiv,
    connectors::Worldpayxml,
    connectors::Wellsfargo,
    connectors::Wellsfargopayout,
    connectors::Volt,
    connectors::Xendit,
    connectors::Zen,
    connectors::Zsl,
    connectors::CtpMastercard
);

#[cfg(feature = "frm")]
macro_rules! default_imp_for_frm_fulfillment {
    ($($path:ident::$connector:ident),*) => {
        $(


Documentation: api-reference/v1/customers/customers--update.mdx
# Type: Doc File

---
openapi: post /customers/{customer_id}
---


impl api::RefundExecute for Payme {}


pub async fn update_user_role(
    state: web::Data<AppState>,
    req: HttpRequest,
    json_payload: web::Json<user_role_api::UpdateUserRoleRequest>,
) -> HttpResponse {
    let flow = Flow::UpdateUserRole;
    let payload = json_payload.into_inner();
    Box::pin(api::server_wrap(
        flow,
        state.clone(),
        &req,
        payload,
        user_role_core::update_user_role,
        &auth::JWTAuth {
            permission: Permission::ProfileUserWrite,
        },
        api_locking::LockAction::NotApplicable,
    ))
    .await
}


OpenAPI Block Path: components.schemas.GiftCardResponse
{
  "allOf": [
    {
      "allOf": [
        {
          "$ref": "#/components/schemas/GiftCardAdditionalData"
        }
      ],
      "nullable": true
    },
    {
      "type": "object"
    }
  ]
}


pub struct CustomerDeleteResponse {
    pub id: id_type::CustomerId,
    pub deleted: bool,
}


pub async fn get_grpc_client_interface(&self) -> Arc<GrpcClients> {
        #[cfg(any(feature = "dynamic_routing", feature = "revenue_recovery"))]
        let client =
            hyper_util::client::legacy::Client::builder(hyper_util::rt::TokioExecutor::new())
                .http2_only(true)
                .build_http();

        #[cfg(feature = "dynamic_routing")]
        let dynamic_routing_connection = self
            .dynamic_routing_client
            .clone()
            .map(|config| config.get_dynamic_routing_connection(client.clone()))
            .transpose()
            .expect("Failed to establish a connection with the Dynamic Routing Server")
            .flatten();

        #[cfg(feature = "dynamic_routing")]
        let health_client = HealthCheckClient::build_connections(self, client.clone())
            .await
            .expect("Failed to build gRPC connections");

        let unified_connector_service_client =
            UnifiedConnectorServiceClient::build_connections(self).await;

        #[cfg(feature = "revenue_recovery")]
        let recovery_decider_client = {
            match &self.recovery_decider_client {
                Some(config) => {
                    // Validate the config first
                    config
                        .validate()
                        .expect("Recovery Decider configuration validation failed");

                    // Create the client
                    let client = config
                        .get_recovery_decider_connection(client.clone())
                        .expect(
                            "Failed to establish a connection with the Recovery Decider Server",
                        );

                    logger::info!("Recovery Decider gRPC client successfully initialized");
                    let boxed_client: Box<dyn RecoveryDeciderClientInterface> = Box::new(client);
                    Some(boxed_client)
                }
                None => {
                    logger::debug!("Recovery Decider client configuration not provided, client will be disabled");
                    None
                }
            }
        };

        Arc::new(GrpcClients {
            #[cfg(feature = "dynamic_routing")]
            dynamic_routing: dynamic_routing_connection,
            #[cfg(feature = "dynamic_routing")]
            health_client,
            #[cfg(feature = "revenue_recovery")]
            recovery_decider_client,
            unified_connector_service_client,
        })
    }


pub struct BusinessCollectLinkConfig {
    #[serde(flatten)]
    pub config: BusinessGenericLinkConfig,

    /// List of payment methods shown on collect UI
    #[schema(value_type = Vec<EnabledPaymentMethod>, example = r#"[{"payment_method": "bank_transfer", "payment_method_types": ["ach", "bacs", "sepa"]}]"#)]
    pub enabled_payment_methods: Vec<link_utils::EnabledPaymentMethod>,
}


pub async fn persist_individual_surcharge_details_in_redis(
        &self,
        state: &SessionState,
        business_profile: &Profile,
    ) -> RouterResult<()> {
        if !self.is_empty_result() {
            let redis_conn = state
                .store
                .get_redis_conn()
                .change_context(errors::ApiErrorResponse::InternalServerError)
                .attach_printable("Failed to get redis connection")?;
            let redis_key = Self::get_surcharge_metadata_redis_key(&self.payment_attempt_id);

            let mut value_list = Vec::with_capacity(self.get_surcharge_results_size());
            for (key, value) in self.get_individual_surcharge_key_value_pairs().into_iter() {
                value_list.push((
                    key,
                    value
                        .encode_to_string_of_json()
                        .change_context(errors::ApiErrorResponse::InternalServerError)
                        .attach_printable("Failed to encode to string of json")?,
                ));
            }
            let intent_fulfillment_time = business_profile
                .get_order_fulfillment_time()
                .unwrap_or(router_consts::DEFAULT_FULFILLMENT_TIME);
            redis_conn
                .set_hash_fields(
                    &redis_key.as_str().into(),
                    value_list,
                    Some(intent_fulfillment_time),
                )
                .await
                .change_context(errors::ApiErrorResponse::InternalServerError)
                .attach_printable("Failed to write to redis")?;
            logger::debug!("Surcharge results stored in redis with key = {}", redis_key);
        }
        Ok(())
    }


impl EventLogger {
    #[track_caller]
    pub(super) fn log_event<T: KafkaMessage>(&self, event: &T) {
        logger::info!(event = ?event.masked_serialize().unwrap_or_else(|e| serde_json::json!({"error": e.to_string()})), event_type =? event.event_type(), event_id =? event.key(), log_type =? "event");
    }
}


pub struct GocardlessError {
    pub message: String,
    pub code: u16,
    pub errors: Vec<Error>,
    #[serde(rename = "type")]
    pub error_type: String,
}


File: crates/router/tests/connectors/dlocal.rs
 Public functions: 1

#![allow(clippy::print_stdout)]

use std::str::FromStr;

use hyperswitch_domain_models::address::{Address, AddressDetails};
use masking::Secret;
use router::types::{self, api, domain, storage::enums, PaymentAddress};

use crate::{
    connector_auth,
    utils::{self, ConnectorActions, PaymentInfo},
};

#[derive(Clone, Copy)]
struct DlocalTest;
impl ConnectorActions for DlocalTest {}
impl utils::Connector for DlocalTest {
    fn get_data(&self) -> api::ConnectorData {
        use router::connector::Dlocal;
        utils::construct_connector_data_old(
            Box::new(Dlocal::new()),
            types::Connector::Dlocal,
            api::GetToken::Connector,
            None,
        )
    }

    fn get_auth_token(&self) -> types::ConnectorAuthType {
        utils::to_connector_auth_type(
            connector_auth::ConnectorAuthentication::new()
                .dlocal
                .expect("Missing connector authentication configuration")
                .into(),
        )
    }

    fn get_name(&self) -> String {
        "dlocal".to_string()
    }
}

static CONNECTOR: DlocalTest = DlocalTest {};

// Cards Positive Tests
// Creates a payment using the manual capture flow (Non 3DS).
#[actix_web::test]
async fn should_only_authorize_payment() {
    let response = CONNECTOR
        .authorize_payment(None, Some(get_payment_info()))
        .await
        .expect("Authorize payment response");
    assert_eq!(response.status, enums::AttemptStatus::Authorized);
}

// Captures a payment using the manual capture flow (Non 3DS).
#[actix_web::test]
async fn should_capture_authorized_payment() {
    let response = CONNECTOR
        .authorize_and_capture_payment(None, None, Some(get_payment_info()))
        .await
        .expect("Capture payment response");
    assert_eq!(response.status, enums::AttemptStatus::Charged);
}

// Partially captures a payment using the manual capture flow (Non 3DS).
#[actix_web::test]
async fn should_partially_capture_authorized_payment() {
    let response = CONNECTOR
        .authorize_and_capture_payment(
            None,
            Some(types::PaymentsCaptureData {
                amount_to_capture: 50,
                ..utils::PaymentCaptureType::default().0
            }),
            Some(get_payment_info()),
        )
        .await
        .expect("Capture payment response");
    assert_eq!(response.status, enums::AttemptStatus::Charged);
}

// Synchronizes a payment using the manual capture flow (Non 3DS).
#[actix_web::test]
async fn should_sync_authorized_payment() {
    let authorize_response = CONNECTOR
        .authorize_payment(None, Some(get_payment_info()))
        .await
        .expect("Authorize payment response");
    let txn_id = utils::get_connector_transaction_id(authorize_response.response);
    let response = CONNECTOR
        .psync_retry_till_status_matches(
            enums::AttemptStatus::Authorized,
            Some(types::PaymentsSyncData {
                connector_transaction_id: types::ResponseId::ConnectorTransactionId(
                    txn_id.unwrap(),
                ),
                ..Default::default()
            }),
            Some(get_payment_info()),
        )
        .await
        .expect("PSync response");
    println!("{}", response.status);
    assert_eq!(response.status, enums::AttemptStatus::Authorized,);
}

// Voids a payment using the manual capture flow (Non 3DS).
#[actix_web::test]
async fn should_void_authorized_payment() {
    let response = CONNECTOR
        .authorize_and_void_payment(
            None,
            Some(types::PaymentsCancelData {
                connector_transaction_id: String::from(""),
                cancellation_reason: Some("requested_by_customer".to_string()),
                ..Default::default()
            }),
            Some(get_payment_info()),
        )
        .await
        .expect("Void payment response");
    assert_eq!(response.status, enums::AttemptStatus::Voided);
}

// Refunds a payment using the manual capture flow (Non 3DS).
#[actix_web::test]
async fn should_refund_manually_captured_payment() {
    let response = CONNECTOR
        .capture_payment_and_refund(None, None, None, Some(get_payment_info()))
        .await
        .unwrap();
    assert_eq!(
        response.response.unwrap().refund_status,
        enums::RefundStatus::Success,
    );
}

// Partially refunds a payment using the manual capture flow (Non 3DS).
#[actix_web::test]
async fn should_partially_refund_manually_captured_payment() {
    let response = CONNECTOR
        .capture_payment_and_refund(
            None,
            None,
            Some(types::RefundsData {
                refund_amount: 50,
                ..utils::PaymentRefundType::default().0
            }),
            Some(get_payment_info()),
        )
        .await
        .unwrap();
    assert_eq!(
        response.response.unwrap().refund_status,
        enums::RefundStatus::Success,
    );
}

// Synchronizes a refund using the manual capture flow (Non 3DS).
#[actix_web::test]
async fn should_sync_manually_captured_refund() {
    let refund_response = CONNECTOR
        .capture_payment_and_refund(None, None, None, Some(get_payment_info()))
        .await
        .unwrap();
    let response = CONNECTOR
        .rsync_retry_till_status_matches(
            enums::RefundStatus::Success,
            refund_response.response.unwrap().connector_refund_id,
            None,
            Some(get_payment_info()),
        )
        .await
        .unwrap();
    assert_eq!(
        response.response.unwrap().refund_status,
        enums::RefundStatus::Success,
    );
}

// Creates a payment using the automatic capture flow (Non 3DS).
#[actix_web::test]
async fn should_make_payment() {
    let authorize_response = CONNECTOR
        .make_payment(None, Some(get_payment_info()))
        .await
        .unwrap();
    assert_eq!(authorize_response.status, enums::AttemptStatus::Charged);
}

// Synchronizes a payment using the automatic capture flow (Non 3DS).
#[actix_web::test]
async fn should_sync_auto_captured_payment() {
    let authorize_response = CONNECTOR
        .make_payment(None, Some(get_payment_info()))
        .await
        .unwrap();
    assert_eq!(authorize_response.status, enums::AttemptStatus::Charged);
    let txn_id = utils::get_connector_transaction_id(authorize_response.response);
    assert_ne!(txn_id, None, "Empty connector transaction id");
    let response = CONNECTOR
        .psync_retry_till_status_matches(
            enums::AttemptStatus::Charged,
            Some(types::PaymentsSyncData {
                connector_transaction_id: types::ResponseId::ConnectorTransactionId(
                    txn_id.unwrap(),
                ),
                ..Default::default()
            }),
            Some(get_payment_info()),
        )
        .await
        .unwrap();
    assert_eq!(response.status, enums::AttemptStatus::Charged,);
}

// Refunds a payment using the automatic capture flow (Non 3DS).
#[actix_web::test]
async fn should_refund_auto_captured_payment() {
    let response = CONNECTOR
        .make_payment_and_refund(None, None, Some(get_payment_info()))
        .await
        .unwrap();
    assert_eq!(
        response.response.unwrap().refund_status,
        enums::RefundStatus::Success,
    );
}

// Partially refunds a payment using the automatic capture flow (Non 3DS).
#[actix_web::test]
async fn should_partially_refund_succeeded_payment() {
    let refund_response = CONNECTOR
        .make_payment_and_refund(
            None,
            Some(types::RefundsData {
                refund_amount: 50,
                ..utils::PaymentRefundType::default().0
            }),
            Some(get_payment_info()),
        )
        .await
        .unwrap();
    assert_eq!(
        refund_response.response.unwrap().refund_status,
        enums::RefundStatus::Success,
    );
}

// Creates multiple refunds against a payment using the automatic capture flow (Non 3DS).
#[actix_web::test]
async fn should_refund_succeeded_payment_multiple_times() {
    CONNECTOR
        .make_payment_and_multiple_refund(
            None,
            Some(types::RefundsData {
                refund_amount: 50,
                ..utils::PaymentRefundType::default().0
            }),
            Some(get_payment_info()),
        )
        .await;
}

// Synchronizes a refund using the automatic capture flow (Non 3DS).
#[actix_web::test]
async fn should_sync_refund() {
    let refund_response = CONNECTOR
        .make_payment_and_refund(None, None, Some(get_payment_info()))
        .await
        .unwrap();
    let response = CONNECTOR
        .rsync_retry_till_status_matches(
            enums::RefundStatus::Success,
            refund_response.response.unwrap().connector_refund_id,
            None,
            Some(get_payment_info()),
        )
        .await
        .unwrap();
    assert_eq!(
        response.response.unwrap().refund_status,
        enums::RefundStatus::Success,
    );
}

// Cards Negative scenarios
// Creates a payment with incorrect card number.
#[actix_web::test]
async fn should_fail_payment_for_incorrect_card_number() {
    let response = CONNECTOR
        .make_payment(
            Some(types::PaymentsAuthorizeData {
                payment_method_data: domain::PaymentMethodData::Card(domain::Card {
                    card_number: cards::CardNumber::from_str("1891011").unwrap(),
                    ..utils::CCardType::default().0
                }),
                ..utils::PaymentAuthorizeType::default().0
            }),
            Some(get_payment_info()),
        )
        .await
        .unwrap();
    let x = response.response.unwrap_err();
    assert_eq!(x.message, "Invalid parameter");
    assert_eq!(x.reason, Some("card.number".to_string()));
}

// Creates a payment with incorrect CVC.
#[actix_web::test]
async fn should_fail_payment_for_incorrect_cvc() {
    let response = CONNECTOR
        .make_payment(
            Some(types::PaymentsAuthorizeData {
                payment_method_data: domain::PaymentMethodData::Card(domain::Card {
                    card_cvc: Secret::new("1ad2345".to_string()),
                    ..utils::CCardType::default().0
                }),
                ..utils::PaymentAuthorizeType::default().0
            }),
            Some(get_payment_info()),
        )
        .await
        .unwrap();
    let x = response.response.unwrap_err();
    assert_eq!(x.message, "Invalid parameter");
    assert_eq!(x.reason, Some("card.cvv".to_string()));
}

// Creates a payment with incorrect expiry month.
#[actix_web::test]
async fn should_fail_payment_for_invalid_exp_month() {
    let response = CONNECTOR
        .make_payment(
            Some(types::PaymentsAuthorizeData {
                payment_method_data: domain::PaymentMethodData::Card(domain::Card {
                    card_exp_month: Secret::new("201".to_string()),
                    ..utils::CCardType::default().0
                }),
                ..utils::PaymentAuthorizeType::default().0
            }),
            Some(get_payment_info()),
        )
        .await
        .unwrap();
    let x = response.response.unwrap_err();
    assert_eq!(x.message, "Invalid parameter");
    assert_eq!(x.reason, Some("card.expiration_month".to_string()));
}

// Creates a payment with incorrect expiry year.
#[actix_web::test]
async fn should_fail_payment_for_incorrect_expiry_year() {
    let response = CONNECTOR
        .make_payment(
            Some(types::PaymentsAuthorizeData {
                payment_method_data: domain::PaymentMethodData::Card(domain::Card {
                    card_exp_year: Secret::new("20001".to_string()),
                    ..utils::CCardType::default().0
                }),
                ..utils::PaymentAuthorizeType::default().0
            }),
            Some(get_payment_info()),
        )
        .await
        .unwrap();
    let x = response.response.unwrap_err();
    assert_eq!(x.message, "Invalid parameter");
    assert_eq!(x.reason, Some("card.expiration_year".to_string()));
}

// Voids a payment using automatic capture flow (Non 3DS).
#[actix_web::test]
async fn should_fail_void_payment_for_auto_capture() {
    let authorize_response = CONNECTOR
        .make_payment(None, Some(get_payment_info()))
        .await
        .unwrap();
    assert_eq!(authorize_response.status, enums::AttemptStatus::Charged);
    let txn_id = utils::get_connector_transaction_id(authorize_response.response);
    assert_ne!(txn_id, None, "Empty connector transaction id");
    let void_response = CONNECTOR
        .void_payment(txn_id.unwrap(), None, None)
        .await
        .unwrap();
    let x = void_response.response.unwrap_err();
    assert_eq!(x.code, "5021");
    assert_eq!(x.message, "Acquirer could not process the request");
}

// Captures a payment using invalid connector payment id.
#[actix_web::test]
async fn should_fail_capture_for_invalid_payment() {
    let capture_response = CONNECTOR
        .capture_payment("123456sdf789".to_string(), None, Some(get_payment_info()))
        .await
        .unwrap();
    let x = capture_response.response.unwrap_err();
    assert_eq!(x.code, "3003");
}

// Refunds a payment with refund amount higher than payment amount.
#[actix_web::test]
async fn should_fail_for_refund_amount_higher_than_payment_amount() {
    let response = CONNECTOR
        .make_payment_and_refund(
            None,
            Some(types::RefundsData {
                refund_amount: 150,
                ..utils::PaymentRefundType::default().0
            }),
            Some(get_payment_info()),
        )
        .await
        .unwrap();
    let x = response.response.unwrap_err();
    println!("response from refund amount higher payment");
    println!("{}", x.code);
    assert_eq!(x.code, "5007");
    assert_eq!(x.message, "Amount exceeded");
}

pub fn get_payment_info() -> PaymentInfo {
    PaymentInfo {
        address: Some(PaymentAddress::new(
            None,
            Some(Address {
                phone: None,
                address: Some(AddressDetails {
                    city: None,
                    country: Some(api_models::enums::CountryAlpha2::PA),
                    line1: None,
                    line2: None,
                    line3: None,
                    zip: None,
                    state: None,
                    first_name: None,
                    last_name: None,
                    origin_zip: None,
                }),
                email: None,
            }),
            None,
            None,
        )),
        auth_type: None,
        access_token: None,
        connector_meta_data: None,
        ..Default::default()
    }
}
// Connector dependent test cases goes here

// [#478]: add unit tests for non 3DS, wallets & webhooks in connector tests


pub struct RefundUpdateMems {
    pub orig: Refund,
    pub update_data: RefundUpdate,
}


pub struct GroupsAndResources {
    pub groups: Vec<PermissionGroup>,
    pub resources: Vec<Resource>,
}


pub struct RedirectPayload {
    #[serde(rename = "PaRes")]
    pa_res: Option<Secret<String>>,

    #[serde(rename = "paymentId")]
    payment_id: Option<String>,
}


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


pub struct PayoutLinkInitiateRequest {
    #[schema(value_type = String)]
    pub merchant_id: id_type::MerchantId,
    #[schema(value_type = String)]
    pub payout_id: id_type::PayoutId,
}


pub fn four_digits(&self) -> String {
        self.peek().to_string()
    }


pub async fn routing_update_default_config_for_profile(
    state: web::Data<AppState>,
    req: HttpRequest,
    path: web::Path<common_utils::id_type::ProfileId>,
    json_payload: web::Json<Vec<routing_types::RoutableConnectorChoice>>,
    transaction_type: &enums::TransactionType,
) -> impl Responder {
    let routing_payload_wrapper = routing_types::RoutingPayloadWrapper {
        updated_config: json_payload.into_inner(),
        profile_id: path.into_inner(),
    };
    Box::pin(oss_api::server_wrap(
        Flow::RoutingUpdateDefaultConfig,
        state,
        &req,
        routing_payload_wrapper.clone(),
        |state, auth: auth::AuthenticationData, wrapper, _| {
            let merchant_context = domain::MerchantContext::NormalMerchant(Box::new(
                domain::Context(auth.merchant_account, auth.key_store),
            ));
            routing::update_default_routing_config_for_profile(
                state,
                merchant_context,
                wrapper.updated_config,
                wrapper.profile_id,
                transaction_type,
            )
        },
        auth::auth_type(
            &auth::HeaderAuth(auth::ApiKeyAuth {
                is_connected_allowed: false,
                is_platform_allowed: false,
            }),
            &auth::JWTAuthProfileFromRoute {
                profile_id: routing_payload_wrapper.profile_id,
                required_permission: Permission::ProfileRoutingWrite,
            },
            req.headers(),
        ),
        api_locking::LockAction::NotApplicable,
    ))
    .await
}


pub struct LoanInformation {
    pub fees: Option<LoanFees>,
}


/// Convert the amount to its base denomination based on Currency and return f64
    pub fn to_currency_base_unit_asf64(self, amount: i64) -> Result<f64, TryFromIntError> {
        let amount_f64: f64 = u32::try_from(amount)?.into();
        let amount = if self.is_zero_decimal_currency() {
            amount_f64
        } else if self.is_three_decimal_currency() {
            amount_f64 / 1000.00
        } else {
            amount_f64 / 100.00
        };
        Ok(amount)
    }


pub fn validate(&self) -> Result<(), ApplicationError> {
        use common_utils::{ext_traits::ConfigExt, fp_utils::when};

        match self {
            Self::Basic { username, password } => {
                when(username.is_default_or_empty(), || {
                    Err(ApplicationError::InvalidConfigurationValueError(
                        "Opensearch Basic auth username must not be empty".into(),
                    ))
                })?;

                when(password.is_default_or_empty(), || {
                    Err(ApplicationError::InvalidConfigurationValueError(
                        "Opensearch Basic auth password must not be empty".into(),
                    ))
                })?;
            }

            Self::Aws { region } => {
                when(region.is_default_or_empty(), || {
                    Err(ApplicationError::InvalidConfigurationValueError(
                        "Opensearch Aws auth region must not be empty".into(),
                    ))
                })?;
            }
        };

        Ok(())
    }


pub struct ErrorInformation {
    pub message: String,
    pub reason: String,
    pub details: Option<Vec<Details>>,
}


File: crates/router_derive/src/macros/generate_schema.rs
 Public functions: 1
 Public structs: 1

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

use indexmap::IndexMap;
use syn::{self, parse::Parse, parse_quote, punctuated::Punctuated, Token};

use crate::macros::helpers;

/// Parse schemas from attribute
/// Example
///
/// #[mandatory_in(PaymentsCreateRequest, PaymentsUpdateRequest)]
/// would return
///
/// [PaymentsCreateRequest, PaymentsUpdateRequest]
fn get_inner_path_ident(attribute: &syn::Attribute) -> syn::Result<Vec<syn::Ident>> {
    Ok(attribute
        .parse_args_with(Punctuated::<syn::Ident, Token![,]>::parse_terminated)?
        .into_iter()
        .collect::<Vec<_>>())
}

#[allow(dead_code)]
/// Get the type of field
fn get_field_type(field_type: syn::Type) -> syn::Result<syn::Ident> {
    if let syn::Type::Path(path) = field_type {
        path.path
            .segments
            .last()
            .map(|last_path_segment| last_path_segment.ident.to_owned())
            .ok_or(syn::Error::new(
                proc_macro2::Span::call_site(),
                "Atleast one ident must be specified",
            ))
    } else {
        Err(syn::Error::new(
            proc_macro2::Span::call_site(),
            "Only path fields are supported",
        ))
    }
}

#[allow(dead_code)]
/// Get the inner type of option
fn get_inner_option_type(field: &syn::Type) -> syn::Result<syn::Ident> {
    if let syn::Type::Path(ref path) = &field {
        if let Some(segment) = path.path.segments.last() {
            if let syn::PathArguments::AngleBracketed(ref args) = &segment.arguments {
                if let Some(syn::GenericArgument::Type(ty)) = args.args.first() {
                    return get_field_type(ty.clone());
                }
            }
        }
    }

    Err(syn::Error::new(
        proc_macro2::Span::call_site(),
        "Only path fields are supported",
    ))
}

mod schema_keyword {
    use syn::custom_keyword;

    custom_keyword!(schema);
}

#[derive(Debug, Clone)]
pub struct SchemaMeta {
    struct_name: syn::Ident,
    type_ident: syn::Ident,
}

/// parse #[mandatory_in(PaymentsCreateRequest = u64)]
impl Parse for SchemaMeta {
    fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
        let struct_name = input.parse::<syn::Ident>()?;
        input.parse::<syn::Token![=]>()?;
        let type_ident = input.parse::<syn::Ident>()?;
        Ok(Self {
            struct_name,
            type_ident,
        })
    }
}

impl quote::ToTokens for SchemaMeta {
    fn to_tokens(&self, _: &mut proc_macro2::TokenStream) {}
}

pub fn polymorphic_macro_derive_inner(
    input: syn::DeriveInput,
) -> syn::Result<proc_macro2::TokenStream> {
    let schemas_to_create =
        helpers::get_metadata_inner::<syn::Ident>("generate_schemas", &input.attrs)?;

    let fields = helpers::get_struct_fields(input.data)
        .map_err(|error| syn::Error::new(proc_macro2::Span::call_site(), error))?;

    // Go through all the fields and create a mapping of required fields for a schema
    // PaymentsCreate -> ["amount","currency"]
    // This will be stored in the hashmap with key as
    // required_fields -> ((amount, PaymentsCreate), (currency, PaymentsCreate))
    // and values as the type
    //
    // (amount, PaymentsCreate) -> Amount
    let mut required_fields = HashMap::<(syn::Ident, syn::Ident), syn::Ident>::new();

    // These fields will be removed in the schema
    // PaymentsUpdate -> ["client_secret"]
    // This will be stored in a hashset
    // hide_fields -> ((client_secret, PaymentsUpdate))
    let mut hide_fields = HashSet::<(syn::Ident, syn::Ident)>::new();
    let mut all_fields = IndexMap::<syn::Field, Vec<syn::Attribute>>::new();

    for field in fields {
        // Partition the attributes of a field into two vectors
        // One with #[mandatory_in] attributes present
        // Rest of the attributes ( include only the schema attribute, serde is not required)
        let (mandatory_attribute, other_attributes) = field
            .attrs
            .iter()
            .partition::<Vec<_>, _>(|attribute| attribute.path().is_ident("mandatory_in"));

        let hidden_fields = field
            .attrs
            .iter()
            .filter(|attribute| attribute.path().is_ident("remove_in"))
            .collect::<Vec<_>>();

        // Other attributes ( schema ) are to be printed as is
        other_attributes
            .iter()
            .filter(|attribute| {
                attribute.path().is_ident("schema") || attribute.path().is_ident("doc")
            })
            .for_each(|attribute| {
                // Since attributes will be modified, the field should not contain any attributes
                // So create a field, with previous attributes removed
                let mut field_without_attributes = field.clone();
                field_without_attributes.attrs.clear();

                all_fields
                    .entry(field_without_attributes.to_owned())
                    .or_default()
                    .push(attribute.to_owned().to_owned());
            });

        // Mandatory attributes are to be inserted into hashset
        // The hashset will store it in this format
        // ("amount", PaymentsCreateRequest)
        // ("currency", PaymentsConfirmRequest)
        //
        // For these attributes, we need to later add #[schema(required = true)] attribute
        let field_ident = field.ident.ok_or(syn::Error::new(
            proc_macro2::Span::call_site(),
            "Cannot use `mandatory_in` on unnamed fields",
        ))?;

        // Parse the  #[mandatory_in(PaymentsCreateRequest = u64)] and insert into hashmap
        // key -> ("amount", PaymentsCreateRequest)
        // value -> u64
        if let Some(mandatory_in_attribute) =
            helpers::get_metadata_inner::<SchemaMeta>("mandatory_in", mandatory_attribute)?.first()
        {
            let key = (
                field_ident.clone(),
                mandatory_in_attribute.struct_name.clone(),
            );
            let value = mandatory_in_attribute.type_ident.clone();
            required_fields.insert(key, value);
        }

        // Hidden fields are to be inserted in the Hashset
        // The hashset will store it in this format
        // ("client_secret", PaymentsUpdate)
        //
        // These fields will not be added to the struct
        _ = hidden_fields
            .iter()
            // Filter only #[mandatory_in] attributes
            .map(|&attribute| get_inner_path_ident(attribute))
            .try_for_each(|schemas| {
                let res = schemas
                    .map_err(|error| syn::Error::new(proc_macro2::Span::call_site(), error))?
                    .iter()
                    .map(|schema| (field_ident.clone(), schema.to_owned()))
                    .collect::<HashSet<_>>();

                hide_fields.extend(res);
                Ok::<_, syn::Error>(())
            });
    }

    // iterate over the schemas and build them with their fields
    let schemas = schemas_to_create
        .iter()
        .map(|schema| {
            let fields = all_fields
                .iter()
                .filter_map(|(field, attributes)| {
                    let mut final_attributes = attributes.clone();

                    if let Some(field_ident) = field.ident.to_owned() {
                        // If the field is required for this schema, then add
                        // #[schema(value_type = type)] for this field
                        if let Some(required_field_type) =
                            required_fields.get(&(field_ident.clone(), schema.to_owned()))
                        {
                            // This is a required field in the Schema
                            // Add the value type and remove original value type ( if present )
                            let attribute_without_schema_type = attributes
                                .iter()
                                .filter(|attribute| !attribute.path().is_ident("schema"))
                                .map(Clone::clone)
                                .collect::<Vec<_>>();

                            final_attributes = attribute_without_schema_type;

                            let value_type_attribute: syn::Attribute =
                                parse_quote!(#[schema(value_type = #required_field_type)]);
                            final_attributes.push(value_type_attribute);
                        }
                    }

                    // If the field is to be not shown then
                    let is_hidden_field = field
                        .ident
                        .clone()
                        .map(|field_ident| hide_fields.contains(&(field_ident, schema.to_owned())))
                        .unwrap_or(false);

                    if is_hidden_field {
                        None
                    } else {
                        Some(quote::quote! {
                            #(#final_attributes)*
                            #field,
                        })
                    }
                })
                .collect::<Vec<_>>();
            quote::quote! {
                #[derive(utoipa::ToSchema)]
                pub struct #schema {
                    #(#fields)*
                }
            }
        })
        .collect::<Vec<_>>();

    Ok(quote::quote! {
        #(#schemas)*
    })
}


pub fn debug_as_display_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
    let ast = syn::parse_macro_input!(input as syn::DeriveInput);

    let tokens =
        macros::debug_as_display_inner(&ast).unwrap_or_else(|error| error.to_compile_error());
    tokens.into()
}


pub struct BraintreeRefundResponseData {
    pub refund_transaction: BraintreeRefundTransaction,
}


pub struct EventDetails {
    pub id: String,
    pub payment_request_id: Option<String>,
    pub amount: FloatMajorUnit,
    pub currency: String,
}


pub struct ProfileWrapper {
    pub profile: domain::Profile,
}


/// A trait for types that can be constructed from encoded data in the form of a String.
pub trait FromEncoded: Sized {
    /// Constructs an instance of the type from the provided encoded input.
    ///
    /// # Parameters
    ///
    /// - `input`: A String containing the encoded data.
    ///
    /// # Returns
    ///
    /// An `Option<Self>` representing the constructed instance if successful, or `None` otherwise.
    ///
    /// # Example
    ///
    /// ```rust
    /// use external_services::hashicorp_vault::core::FromEncoded;
    /// use masking::Secret;
    /// let secret_instance = Secret::<String>::from_encoded("encoded_secret_string".to_string());
    /// let vec_instance = Vec::<u8>::from_encoded("68656c6c6f".to_string());
    /// ```
    fn from_encoded(input: String) -> Option<Self>;
}


pub struct UserMerchantCreate {
    pub company_name: String,
    pub product_type: Option<common_enums::MerchantProductType>,
    pub merchant_account_type: Option<common_enums::MerchantAccountRequestType>,
}


pub fn get_refund_body(
    req: &BamboraapacRouterData<&types::RefundExecuteRouterData>,
) -> Result<Vec<u8>, Error> {
    let receipt = req.router_data.request.connector_transaction_id.to_owned();
    let auth_details = BamboraapacAuthType::try_from(&req.router_data.connector_auth_type)?;
    let body = format!(
        r#"
            <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
            xmlns:dts="http://www.ippayments.com.au/interface/api/dts">
                <soapenv:Header/>
                <soapenv:Body>
                    <dts:SubmitSingleRefund>
                        <dts:trnXML>
                            <![CDATA[
                            <Refund>
                                <CustRef>{}</CustRef>
                                <Receipt>{}</Receipt>
                                <Amount>{}</Amount>
                                <Security>
                                    <UserName>{}</UserName>
                                    <Password>{}</Password>
                                </Security>
                            </Refund>
                            ]]>
                        </dts:trnXML>
                    </dts:SubmitSingleRefund>
                </soapenv:Body>
            </soapenv:Envelope>
        "#,
        req.router_data.request.refund_id.to_owned(),
        receipt,
        req.amount,
        auth_details.username.peek(),
        auth_details.password.peek(),
    );

    Ok(body.as_bytes().to_vec())
}


pub struct RedirectResponse {
    pub param: Option<Secret<String>>,
    pub json_payload: Option<pii::SecretSerdeValue>,
}


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

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

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

impl ConnectorSpecifications for for Payme


File: crates/hyperswitch_connectors/src/connectors/razorpay/transformers.rs
 Public functions: 1
 Public structs: 24

use std::collections::HashMap;

use api_models::payments::PollConfig;
use common_enums::enums;
use common_utils::{
    errors::CustomResult,
    pii::{self, Email, IpAddress},
    types::MinorUnit,
};
use hyperswitch_domain_models::{
    payment_method_data::{PaymentMethodData, UpiData},
    router_data::{ConnectorAuthType, RouterData},
    router_flow_types::refunds::{Execute, RSync},
    router_request_types::{PaymentsAuthorizeData, ResponseId},
    router_response_types::{PaymentsResponseData, RefundsResponseData},
    types,
};
use hyperswitch_interfaces::errors;
use masking::Secret;
use serde::{Deserialize, Serialize};
use time::{Duration, OffsetDateTime};

use crate::{
    types::{CreateOrderResponseRouterData, RefundsResponseRouterData, ResponseRouterData},
    utils::{
        get_unimplemented_payment_method_error_message, missing_field_err,
        PaymentsAuthorizeRequestData, RouterData as OtherRouterData,
    },
};

pub struct RazorpayRouterData<T> {
    pub amount: MinorUnit,
    pub router_data: T,
}

impl<T> TryFrom<(MinorUnit, T)> for RazorpayRouterData<T> {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from((amount, item): (MinorUnit, T)) -> Result<Self, Self::Error> {
        Ok(Self {
            amount,
            router_data: item,
        })
    }
}

pub const VERSION: i32 = 1;

#[derive(Debug, Serialize)]
#[serde(rename_all = "snake_case")]
pub struct RazorpayOrderRequest {
    pub amount: MinorUnit,
    pub currency: enums::Currency,
    pub receipt: String,
    pub partial_payment: Option<bool>,
    pub first_payment_min_amount: Option<MinorUnit>,
    pub notes: Option<RazorpayNotes>,
}

#[derive(Debug, Deserialize, Serialize)]
#[serde(untagged)]
pub enum RazorpayNotes {
    Map(HashMap<String, String>),
    EmptyMap(HashMap<String, String>),
}

impl TryFrom<&RazorpayRouterData<&types::CreateOrderRouterData>> for RazorpayOrderRequest {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        item: &RazorpayRouterData<&types::CreateOrderRouterData>,
    ) -> Result<Self, Self::Error> {
        let currency = item.router_data.request.currency;
        let receipt = item.router_data.connector_request_reference_id.clone();

        Ok(Self {
            amount: item.amount,
            currency,
            receipt,
            partial_payment: None,
            first_payment_min_amount: None,
            notes: None,
        })
    }
}

#[derive(Debug, Serialize, Deserialize)]
pub struct RazorpayMetaData {
    pub order_id: String,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct RazorpayOrderResponse {
    pub id: String,
}

impl TryFrom<CreateOrderResponseRouterData<RazorpayOrderResponse>>
    for types::CreateOrderRouterData
{
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        item: CreateOrderResponseRouterData<RazorpayOrderResponse>,
    ) -> Result<Self, Self::Error> {
        Ok(Self {
            response: Ok(PaymentsResponseData::PaymentsCreateOrderResponse {
                order_id: item.response.id.clone(),
            }),
            ..item.data
        })
    }
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "snake_case")]
pub struct UpiDetails {
    flow: UpiFlow,
    vpa: Secret<String, pii::UpiVpaMaskingStrategy>,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum UpiFlow {
    Collect,
    Intent,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "snake_case")]
pub struct RazorpayPaymentsRequest {
    amount: MinorUnit,
    currency: enums::Currency,
    order_id: String,
    email: Email,
    contact: Secret<String>,
    method: RazorpayPaymentMethod,
    upi: UpiDetails,
    #[serde(skip_serializing_if = "Option::is_none")]
    ip: Option<Secret<String, IpAddress>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    user_agent: Option<String>,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum RazorpayPaymentMethod {
    Upi,
}

impl TryFrom<&RazorpayRouterData<&types::PaymentsAuthorizeRouterData>> for RazorpayPaymentsRequest {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        item: &RazorpayRouterData<&types::PaymentsAuthorizeRouterData>,
    ) -> Result<Self, Self::Error> {
        let payment_router_data = item.router_data;
        let router_request = &payment_router_data.request;
        let payment_method_data = &router_request.payment_method_data;

        let (razorpay_payment_method, upi_details) = match payment_method_data {
            PaymentMethodData::Upi(upi_type_data) => match upi_type_data {
                UpiData::UpiCollect(upi_collect_data) => {
                    let vpa_secret = upi_collect_data
                        .vpa_id
                        .clone()
                        .ok_or_else(missing_field_err("payment_method_data.upi.collect.vpa_id"))?;
                    (
                        RazorpayPaymentMethod::Upi,
                        UpiDetails {
                            flow: UpiFlow::Collect,
                            vpa: vpa_secret,
                        },
                    )
                }
                UpiData::UpiIntent(_upi_intent_data) => {
                    Err(errors::ConnectorError::NotImplemented(
                        get_unimplemented_payment_method_error_message("razorpay"),
                    ))?
                }
            },
            _ => Err(errors::ConnectorError::NotImplemented(
                get_unimplemented_payment_method_error_message("razorpay"),
            ))?,
        };

        let contact_number = item.router_data.get_billing_phone_number()?;
        let order_id = router_request.get_order_id()?;
        let email = item.router_data.get_billing_email()?;
        let ip = router_request.get_ip_address_as_optional();
        let user_agent = router_request.get_optional_user_agent();

        Ok(Self {
            amount: item.amount,
            currency: router_request.currency,
            order_id,
            email,
            contact: contact_number,
            method: razorpay_payment_method,
            upi: upi_details,
            ip,
            user_agent,
        })
    }
}

pub struct RazorpayAuthType {
    pub(super) razorpay_id: Secret<String>,
    pub(super) razorpay_secret: Secret<String>,
}

impl TryFrom<&ConnectorAuthType> for RazorpayAuthType {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(auth_type: &ConnectorAuthType) -> Result<Self, Self::Error> {
        match auth_type {
            ConnectorAuthType::BodyKey { api_key, key1 } => Ok(Self {
                razorpay_id: api_key.to_owned(),
                razorpay_secret: key1.to_owned(),
            }),
            _ => Err(errors::ConnectorError::FailedToObtainAuthType.into()),
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NextAction {
    pub action: String,
    pub url: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RazorpayPaymentsResponse {
    pub razorpay_payment_id: String,
}

impl<F>
    TryFrom<
        ResponseRouterData<
            F,
            RazorpayPaymentsResponse,
            PaymentsAuthorizeData,
            PaymentsResponseData,
        >,
    > for RouterData<F, PaymentsAuthorizeData, PaymentsResponseData>
{
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        item: ResponseRouterData<
            F,
            RazorpayPaymentsResponse,
            PaymentsAuthorizeData,
            PaymentsResponseData,
        >,
    ) -> Result<Self, Self::Error> {
        let connector_metadata = get_wait_screen_metadata()?;
        let order_id = item.data.request.get_order_id()?;
        Ok(Self {
            status: enums::AttemptStatus::AuthenticationPending,
            response: Ok(PaymentsResponseData::TransactionResponse {
                resource_id: ResponseId::ConnectorTransactionId(
                    item.response.razorpay_payment_id.clone(),
                ),
                redirection_data: Box::new(None),
                mandate_reference: Box::new(None),
                connector_metadata,
                network_txn_id: None,
                connector_response_reference_id: Some(order_id),
                incremental_authorization_allowed: None,
                charges: None,
            }),
            ..item.data
        })
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WaitScreenData {
    display_from_timestamp: i128,
    display_to_timestamp: Option<i128>,
    poll_config: Option<PollConfig>,
}

pub fn get_wait_screen_metadata() -> CustomResult<Option<serde_json::Value>, errors::ConnectorError>
{
    let current_time = OffsetDateTime::now_utc().unix_timestamp_nanos();
    Ok(Some(serde_json::json!(WaitScreenData {
        display_from_timestamp: current_time,
        display_to_timestamp: Some(current_time + Duration::minutes(5).whole_nanoseconds()),
        poll_config: Some(PollConfig {
            delay_in_secs: 5,
            frequency: 5,
        }),
    })))
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RazorpaySyncResponse {
    items: Vec<RazorpaySyncItem>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RazorpaySyncItem {
    id: String,
    status: RazorpayStatus,
}

#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum RazorpayStatus {
    Created,
    Authorized,
    Captured,
    Refunded,
    Failed,
}

fn get_psync_razorpay_payment_status(razorpay_status: RazorpayStatus) -> enums::AttemptStatus {
    match razorpay_status {
        RazorpayStatus::Created => enums::AttemptStatus::Pending,
        RazorpayStatus::Authorized => enums::AttemptStatus::Authorized,
        RazorpayStatus::Captured | RazorpayStatus::Refunded => enums::AttemptStatus::Charged,
        RazorpayStatus::Failed => enums::AttemptStatus::Failure,
    }
}

impl<F, T> TryFrom<ResponseRouterData<F, RazorpaySyncResponse, T, PaymentsResponseData>>
    for RouterData<F, T, PaymentsResponseData>
{
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        item: ResponseRouterData<F, RazorpaySyncResponse, T, PaymentsResponseData>,
    ) -> Result<Self, Self::Error> {
        let status = match item.response.items.last() {
            Some(last_item) => {
                let razorpay_status = last_item.status;
                get_psync_razorpay_payment_status(razorpay_status)
            }
            None => item.data.status,
        };
        Ok(Self {
            status,
            response: Ok(PaymentsResponseData::TransactionResponse {
                resource_id: ResponseId::NoResponseId,
                redirection_data: Box::new(None),
                mandate_reference: Box::new(None),
                connector_metadata: None,
                network_txn_id: None,
                connector_response_reference_id: None,
                incremental_authorization_allowed: None,
                charges: None,
            }),
            ..item.data
        })
    }
}

#[derive(Default, Debug, Serialize)]
#[serde(rename_all = "snake_case")]
pub struct RazorpayRefundRequest {
    pub amount: MinorUnit,
}

impl<F> TryFrom<&RazorpayRouterData<&types::RefundsRouterData<F>>> for RazorpayRefundRequest {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        item: &RazorpayRouterData<&types::RefundsRouterData<F>>,
    ) -> Result<Self, Self::Error> {
        Ok(Self {
            amount: item.amount,
        })
    }
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct RazorpayRefundResponse {
    pub id: String,
    pub status: RazorpayRefundStatus,
}

#[derive(Debug, Serialize, Eq, PartialEq, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum RazorpayRefundStatus {
    Created,
    Processed,
    Failed,
    Pending,
}

impl From<RazorpayRefundStatus> for enums::RefundStatus {
    fn from(item: RazorpayRefundStatus) -> Self {
        match item {
            RazorpayRefundStatus::Processed => Self::Success,
            RazorpayRefundStatus::Pending | RazorpayRefundStatus::Created => Self::Pending,
            RazorpayRefundStatus::Failed => Self::Failure,
        }
    }
}

impl TryFrom<RefundsResponseRouterData<Execute, RazorpayRefundResponse>>
    for types::RefundsRouterData<Execute>
{
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        item: RefundsResponseRouterData<Execute, RazorpayRefundResponse>,
    ) -> Result<Self, Self::Error> {
        Ok(Self {
            response: Ok(RefundsResponseData {
                connector_refund_id: item.response.id.to_string(),
                refund_status: enums::RefundStatus::from(item.response.status),
            }),
            ..item.data
        })
    }
}

// This code can be used later when Razorpay webhooks are implemented

// #[derive(Debug, Deserialize, Serialize)]
// #[serde(untagged)]
// pub enum RazorpayPaymentsResponseData {
//     PsyncResponse(RazorpaySyncResponse),
//     WebhookResponse(WebhookPaymentEntity),
// }

// impl From<RazorpayWebhookPaymentStatus> for enums::AttemptStatus {
//     fn from(status: RazorpayWebhookPaymentStatus) -> Self {
//         match status {
//             RazorpayWebhookPaymentStatus::Authorized => Self::Authorized,
//             RazorpayWebhookPaymentStatus::Captured => Self::Charged,
//             RazorpayWebhookPaymentStatus::Failed => Self::Failure,
//         }
//     }
// }

// impl<F, T> TryFrom<ResponseRouterData<F, RazorpayPaymentsResponseData, T, PaymentsResponseData>>
//     for RouterData<F, T, PaymentsResponseData>
// {
//     type Error = error_stack::Report<errors::ConnectorError>;
//     fn try_from(
//         item: ResponseRouterData<F, RazorpayPaymentsResponseData, T, PaymentsResponseData>,
//     ) -> Result<Self, Self::Error> {
//         match item.response {
//             RazorpayPaymentsResponseData::PsyncResponse(sync_response) => {
//                 let status = get_psync_razorpay_payment_status(sync_response.status.clone());
//                 Ok(Self {
//                     status,
//                     response: if is_payment_failure(status) {
//                         Err(RouterErrorResponse {
//                             code: sync_response.status.clone().to_string(),
//                             message: sync_response.status.clone().to_string(),
//                             reason: Some(sync_response.status.to_string()),
//                             status_code: item.http_code,
//                             attempt_status: Some(status),
//                             connector_transaction_id: None,
//                             network_advice_code: None,
//                             network_decline_code: None,
//                             network_error_message: None,
//                         })
//                     } else {
//                         Ok(PaymentsResponseData::TransactionResponse {
//                             resource_id: ResponseId::NoResponseId,
//                             redirection_data: Box::new(None),
//                             mandate_reference: Box::new(None),
//                             connector_metadata: None,
//                             network_txn_id: None,
//                             connector_response_reference_id: None,
//                             incremental_authorization_allowed: None,
//                             charges: None,
//                         })
//                     },
//                     ..item.data
//                 })
//             }
//             RazorpayPaymentsResponseData::WebhookResponse(webhook_payment_entity) => {
//                 let razorpay_status = webhook_payment_entity.status;
//                 let status = enums::AttemptStatus::from(razorpay_status.clone());

//                 Ok(Self {
//                     status,
//                     response: if is_payment_failure(status) {
//                         Err(RouterErrorResponse {
//                             code: razorpay_status.clone().to_string(),
//                             message: razorpay_status.clone().to_string(),
//                             reason: Some(razorpay_status.to_string()),
//                             status_code: item.http_code,
//                             attempt_status: Some(status),
//                             connector_transaction_id: Some(webhook_payment_entity.id.clone()),
//                             network_advice_code: None,
//                             network_decline_code: None,
//                             network_error_message: None,
//                         })
//                     } else {
//                         Ok(PaymentsResponseData::TransactionResponse {
//                             resource_id: ResponseId::ConnectorTransactionId(
//                                 webhook_payment_entity.id.clone(),
//                             ),
//                             redirection_data: Box::new(None),
//                             mandate_reference: Box::new(None),
//                             connector_metadata: None,
//                             network_txn_id: None,
//                             connector_response_reference_id: Some(webhook_payment_entity.id),
//                             incremental_authorization_allowed: None,
//                             charges: None,
//                         })
//                     },
//                     ..item.data
//                 })
//             }
//         }
//     }
// }

impl TryFrom<RefundsResponseRouterData<RSync, RazorpayRefundResponse>>
    for types::RefundsRouterData<RSync>
{
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        item: RefundsResponseRouterData<RSync, RazorpayRefundResponse>,
    ) -> Result<Self, Self::Error> {
        Ok(Self {
            response: Ok(RefundsResponseData {
                connector_refund_id: item.response.id.to_string(),
                refund_status: enums::RefundStatus::from(item.response.status),
            }),
            ..item.data
        })
    }
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(untagged)]
pub enum ErrorResponse {
    RazorpayErrorResponse(RazorpayErrorResponse),
    RazorpayStringError(String),
    RazorpayError(RazorpayErrorMessage),
}

#[derive(Debug, Default, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct RazorpayErrorMessage {
    pub message: String,
}

#[derive(Debug, Default, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct RazorpayErrorResponse {
    pub error: RazorpayError,
}

#[serde_with::skip_serializing_none]
#[derive(Debug, Default, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct RazorpayError {
    pub code: String,
    pub description: String,
    pub source: Option<String>,
    pub step: Option<String>,
    pub reason: Option<String>,
    pub metadata: Option<Metadata>,
}

#[serde_with::skip_serializing_none]
#[derive(Debug, Default, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct Metadata {
    pub order_id: Option<String>,
}

// This code can be used later when Razorpay webhooks are implemented

// #[derive(Debug, Serialize, Deserialize)]

// pub struct RazorpayWebhookPayload {
//     pub event: RazorpayWebhookEventType,
//     pub payload: RazorpayWebhookPayloadBody,
// }

// #[derive(Debug, Serialize, Deserialize)]
// #[serde(untagged)]
// pub enum RazorpayWebhookEventType {
//     Payments(RazorpayWebhookPaymentEvent),
//     Refunds(RazorpayWebhookRefundEvent),
// }

// #[derive(Debug, Serialize, Deserialize)]
// pub struct RazorpayWebhookPayloadBody {
//     pub refund: Option<RazorpayRefundWebhookPayload>,
//     pub payment: RazorpayPaymentWebhookPayload,
// }

// #[derive(Debug, Serialize, Deserialize)]
// pub struct RazorpayPaymentWebhookPayload {
//     pub entity: WebhookPaymentEntity,
// }

// #[derive(Debug, Serialize, Deserialize)]
// pub struct RazorpayRefundWebhookPayload {
//     pub entity: WebhookRefundEntity,
// }

// #[derive(Debug, Serialize, Deserialize)]
// pub struct WebhookRefundEntity {
//     pub id: String,
//     pub status: RazorpayWebhookRefundEvent,
// }

// #[derive(Debug, Serialize, Eq, PartialEq, Deserialize)]
// pub enum RazorpayWebhookRefundEvent {
//     #[serde(rename = "refund.created")]
//     Created,
//     #[serde(rename = "refund.processed")]
//     Processed,
//     #[serde(rename = "refund.failed")]
//     Failed,
//     #[serde(rename = "refund.speed_change")]
//     SpeedChange,
// }

// #[derive(Debug, Serialize, Deserialize)]
// pub struct WebhookPaymentEntity {
//     pub id: String,
//     pub status: RazorpayWebhookPaymentStatus,
// }

// #[derive(Debug, Serialize, Eq, PartialEq, Clone, Deserialize)]
// #[serde(rename_all = "snake_case")]
// pub enum RazorpayWebhookPaymentStatus {
//     Authorized,
//     Captured,
//     Failed,
// }

// #[derive(Debug, Serialize, Eq, PartialEq, Deserialize)]
// pub enum RazorpayWebhookPaymentEvent {
//     #[serde(rename = "payment.authorized")]
//     Authorized,
//     #[serde(rename = "payment.captured")]
//     Captured,
//     #[serde(rename = "payment.failed")]
//     Failed,
// }

// impl TryFrom<RazorpayWebhookEventType> for api_models::webhooks::IncomingWebhookEvent {
//     type Error = errors::ConnectorError;

//     fn try_from(event_type: RazorpayWebhookEventType) -> Result<Self, Self::Error> {
//         match event_type {
//             RazorpayWebhookEventType::Payments(payment_event) => match payment_event {
//                 RazorpayWebhookPaymentEvent::Authorized => {
//                     Ok(Self::PaymentIntentAuthorizationSuccess)
//                 }
//                 RazorpayWebhookPaymentEvent::Captured => Ok(Self::PaymentIntentSuccess),
//                 RazorpayWebhookPaymentEvent::Failed => Ok(Self::PaymentIntentFailure),
//             },
//             RazorpayWebhookEventType::Refunds(refund_event) => match refund_event {
//                 RazorpayWebhookRefundEvent::Processed => Ok(Self::RefundSuccess),
//                 RazorpayWebhookRefundEvent::Created => Ok(Self::RefundSuccess),
//                 RazorpayWebhookRefundEvent::Failed => Ok(Self::RefundFailure),
//                 RazorpayWebhookRefundEvent::SpeedChange => Ok(Self::EventNotSupported),
//             },
//         }
//     }
// }


pub struct MandatePaymentRequest {
    #[serde(rename = "DATEQ")]
    pub date: String,

    #[serde(rename = "TYPE")]
    pub transaction_type: String,

    #[serde(rename = "NUMQUESTION")]
    pub paybox_request_number: String,

    #[serde(rename = "MONTANT")]
    pub amount: MinorUnit,

    #[serde(rename = "REFERENCE")]
    pub description_reference: String,

    #[serde(rename = "VERSION")]
    pub version: String,

    #[serde(rename = "DEVISE")]
    pub currency: String,

    #[serde(rename = "ACTIVITE")]
    pub activity: String,

    #[serde(rename = "SITE")]
    pub site: Secret<String>,

    #[serde(rename = "RANG")]
    pub rank: Secret<String>,

    #[serde(rename = "CLE")]
    pub key: Secret<String>,

    #[serde(rename = "DATEVAL")]
    pub cc_exp_date: Secret<String>,

    #[serde(rename = "REFABONNE")]
    pub customer_id: Secret<String>,

    #[serde(rename = "PORTEUR")]
    pub carrier_id: Secret<String>,
}


File: crates/openapi/src/routes/three_ds_decision_rule.rs
 Public functions: 1

/// 3DS Decision - Execute
#[utoipa::path(
    post,
    path = "/three_ds_decision/execute",
    request_body = ThreeDsDecisionRuleExecuteRequest,
    responses(
        (status = 200, description = "3DS Decision Rule Executed Successfully", body = ThreeDsDecisionRuleExecuteResponse),
        (status = 400, description = "Bad Request")
    ),
    tag = "3DS Decision Rule",
    operation_id = "Execute 3DS Decision Rule",
    security(("api_key" = []))
)]
pub fn three_ds_decision_rule_execute() {}


pub struct BitpayRefundRequest {
    pub amount: FloatMajorUnit,
}


pub async fn execute_authentication_token<
    F: Clone + 'static,
    Req: Debug + Clone + 'static,
    Res: Debug + Clone + 'static,
>(
    state: &SessionState,
    connector: &api_types::ConnectorData,
    router_data: &types::RouterData<F, Req, Res>,
) -> RouterResult<Option<types::AccessTokenAuthenticationResponse>> {
    let should_create_authentication_token = connector
        .connector
        .authentication_token_for_token_creation();

    if !should_create_authentication_token {
        return Ok(None);
    }

    let authentication_token_request_data = types::AccessTokenAuthenticationRequestData::try_from(
        router_data.connector_auth_type.clone(),
    )
    .attach_printable(
        "Could not create authentication token request, invalid connector account credentials",
    )?;

    let authentication_token_response_data: Result<
        types::AccessTokenAuthenticationResponse,
        types::ErrorResponse,
    > = Err(types::ErrorResponse::default());

    let auth_token_router_data = payments::helpers::router_data_type_conversion::<
        _,
        api_types::AccessTokenAuthentication,
        _,
        _,
        _,
        _,
    >(
        router_data.clone(),
        authentication_token_request_data,
        authentication_token_response_data,
    );

    let connector_integration: services::BoxedAuthenticationTokenConnectorIntegrationInterface<
        api_types::AccessTokenAuthentication,
        types::AccessTokenAuthenticationRequestData,
        types::AccessTokenAuthenticationResponse,
    > = connector.connector.get_connector_integration();

    let auth_token_router_data_result = services::execute_connector_processing_step(
        state,
        connector_integration,
        &auth_token_router_data,
        payments::CallConnectorAction::Trigger,
        None,
        None,
    )
    .await;

    let auth_token_result = match auth_token_router_data_result {
        Ok(router_data) => router_data.response,
        Err(connector_error) => {
            // Handle timeout errors
            if connector_error.current_context().is_connector_timeout() {
                let error_response = types::ErrorResponse {
                    code: consts::REQUEST_TIMEOUT_ERROR_CODE.to_string(),
                    message: consts::REQUEST_TIMEOUT_ERROR_MESSAGE.to_string(),
                    reason: Some(consts::REQUEST_TIMEOUT_ERROR_MESSAGE.to_string()),
                    status_code: 504,
                    attempt_status: None,
                    connector_transaction_id: None,
                    network_advice_code: None,
                    network_decline_code: None,
                    network_error_message: None,
                    connector_metadata: None,
                };
                Err(error_response)
            } else {
                return Err(connector_error
                    .change_context(errors::ApiErrorResponse::InternalServerError)
                    .attach_printable("Could not get authentication token"));
            }
        }
    };

    let authentication_token = auth_token_result
        .map_err(|_error| errors::ApiErrorResponse::InternalServerError)
        .attach_printable("Failed to get authentication token")?;

    Ok(Some(authentication_token))
}


pub fn get_payment_response_hash_key(&self) -> Option<String> {
        self.payment_response_hash_key.clone().or(Some(
            common_utils::crypto::generate_cryptographically_secure_random_string(64),
        ))
    }