        let redis_conn = state
            .store
            .get_redis_conn()
            .change_context(errors::ApiErrorResponse::InternalServerError)
            .attach_printable("Failed to get redis connection")?;
        redis_conn
            .serialize_and_set_key_with_expiry(
                &self.key_for_token.as_str().into(),
                token,
                fulfillment_time,
            )
            .await
            .change_context(errors::StorageError::KVError)
            .change_context(errors::ApiErrorResponse::InternalServerError)
            .attach_printable("Failed to add token in redis")?;

        Ok(())
    }

    pub fn should_delete_payment_method_token(&self, status: IntentStatus) -> bool {
        // RequiresMerchantAction: When the payment goes for merchant review incase of potential fraud allow payment_method_token to be stored until resolved
        ![
            IntentStatus::RequiresCustomerAction,
            IntentStatus::RequiresMerchantAction,
        ]
        .contains(&status)
    }

    pub async fn delete(&self, state: &SessionState) -> CustomResult<(), errors::ApiErrorResponse> {
        let redis_conn = state
            .store
            .get_redis_conn()
            .change_context(errors::ApiErrorResponse::InternalServerError)
            .attach_printable("Failed to get redis connection")?;
        match redis_conn
            .delete_key(&self.key_for_token.as_str().into())
            .await
        {
            Ok(_) => Ok(()),
            Err(err) => {
                {
                    logger::info!("Error while deleting redis key: {:?}", err)
                };
                Ok(())
            }
        }
    }
}

#[cfg(all(feature = "v1", any(feature = "olap", feature = "oltp")))]
#[instrument(skip_all, fields(flow = ?Flow::TokenizeCard))]
pub async fn tokenize_card_api(
    state: web::Data<AppState>,
    req: HttpRequest,
    json_payload: web::Json<payment_methods::CardNetworkTokenizeRequest>,
) -> HttpResponse {
    let flow = Flow::TokenizeCard;

    Box::pin(api::server_wrap(
        flow,
        state,
        &req,
        json_payload.into_inner(),
        |state, _, req, _| async move {
            let merchant_id = req.merchant_id.clone();
            let (key_store, merchant_account) = get_merchant_account(&state, &merchant_id).await?;
            let merchant_context = domain::MerchantContext::NormalMerchant(Box::new(
                domain::Context(merchant_account, key_store),
            ));
            let res = Box::pin(cards::tokenize_card_flow(
                &state,
                CardNetworkTokenizeRequest::foreign_from(req),
                &merchant_context,
            ))
            .await?;
            Ok(services::ApplicationResponse::Json(res))
        },
        &auth::AdminApiAuth,
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

#[cfg(all(feature = "v1", any(feature = "olap", feature = "oltp")))]
#[instrument(skip_all, fields(flow = ?Flow::TokenizeCardUsingPaymentMethodId))]
pub async fn tokenize_card_using_pm_api(
    state: web::Data<AppState>,
    req: HttpRequest,
    path: web::Path<String>,
    json_payload: web::Json<payment_methods::CardNetworkTokenizeRequest>,
) -> HttpResponse {
    let flow = Flow::TokenizeCardUsingPaymentMethodId;
    let pm_id = path.into_inner();
    let mut payload = json_payload.into_inner();
    if let payment_methods::TokenizeDataRequest::ExistingPaymentMethod(ref mut pm_data) =
        payload.data
    {
        pm_data.payment_method_id = pm_id;
    } else {
        return api::log_and_return_error_response(error_stack::report!(
            errors::ApiErrorResponse::InvalidDataValue { field_name: "card" }
        ));
    }

    Box::pin(api::server_wrap(
        flow,
        state,
        &req,
        payload,
        |state, _, req, _| async move {
            let merchant_id = req.merchant_id.clone();
            let (key_store, merchant_account) = get_merchant_account(&state, &merchant_id).await?;
            let merchant_context = domain::MerchantContext::NormalMerchant(Box::new(
                domain::Context(merchant_account, key_store),
            ));
            let res = Box::pin(cards::tokenize_card_flow(
                &state,
                CardNetworkTokenizeRequest::foreign_from(req),
                &merchant_context,
            ))
            .await?;
            Ok(services::ApplicationResponse::Json(res))
        },
        &auth::AdminApiAuth,
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

#[cfg(all(feature = "v1", any(feature = "olap", feature = "oltp")))]
#[instrument(skip_all, fields(flow = ?Flow::TokenizeCardBatch))]
pub async fn tokenize_card_batch_api(
    state: web::Data<AppState>,
    req: HttpRequest,
    MultipartForm(form): MultipartForm<tokenize::CardNetworkTokenizeForm>,
) -> HttpResponse {
    let flow = Flow::TokenizeCardBatch;
    let (merchant_id, records) = match tokenize::get_tokenize_card_form_records(form) {
        Ok(res) => res,
        Err(e) => return api::log_and_return_error_response(e.into()),
    };

    Box::pin(api::server_wrap(
        flow,
        state,
        &req,
        records,
        |state, _, req, _| {
            let merchant_id = merchant_id.clone();
            async move {
                let (key_store, merchant_account) =
                    get_merchant_account(&state, &merchant_id).await?;
                let merchant_context = domain::MerchantContext::NormalMerchant(Box::new(
                    domain::Context(merchant_account, key_store),
                ));
                Box::pin(tokenize::tokenize_cards(&state, req, &merchant_context)).await
            }
        },
        &auth::AdminApiAuth,
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

#[cfg(feature = "v2")]
#[instrument(skip_all, fields(flow = ?Flow::PaymentMethodSessionCreate))]
pub async fn payment_methods_session_create(
    state: web::Data<AppState>,
    req: HttpRequest,
    json_payload: web::Json<api_models::payment_methods::PaymentMethodSessionRequest>,
) -> HttpResponse {
    let flow = Flow::PaymentMethodSessionCreate;
    let payload = json_payload.into_inner();

    Box::pin(api::server_wrap(
        flow,
        state,
        &req,
        payload,
        |state, auth: auth::AuthenticationData, request, _| async move {
            let merchant_context = domain::MerchantContext::NormalMerchant(Box::new(
                domain::Context(auth.merchant_account, auth.key_store),
            ));
            payment_methods_routes::payment_methods_session_create(state, merchant_context, request)
                .await
        },
        &auth::V2ApiKeyAuth {
            is_connected_allowed: false,
            is_platform_allowed: false,
        },
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

#[cfg(feature = "v2")]
#[instrument(skip_all, fields(flow = ?Flow::PaymentMethodSessionUpdate))]
pub async fn payment_methods_session_update(
    state: web::Data<AppState>,
    req: HttpRequest,
    path: web::Path<id_type::GlobalPaymentMethodSessionId>,
    json_payload: web::Json<api_models::payment_methods::PaymentMethodsSessionUpdateRequest>,
) -> HttpResponse {
    let flow = Flow::PaymentMethodSessionUpdate;
    let payment_method_session_id = path.into_inner();
    let payload = json_payload.into_inner();
    Box::pin(api::server_wrap(
        flow,
        state,
        &req,
        payload,
        |state, auth: auth::AuthenticationData, req, _| {
            let value = payment_method_session_id.clone();
            async move {
                let merchant_context = domain::MerchantContext::NormalMerchant(Box::new(
                    domain::Context(auth.merchant_account, auth.key_store),
                ));
                payment_methods_routes::payment_methods_session_update(
                    state,
                    merchant_context,
                    value.clone(),
                    req,
                )
                .await
            }
        },
        &auth::V2ApiKeyAuth {
            is_connected_allowed: false,
            is_platform_allowed: false,
        },
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

#[cfg(feature = "v2")]
#[instrument(skip_all, fields(flow = ?Flow::PaymentMethodSessionRetrieve))]
pub async fn payment_methods_session_retrieve(
    state: web::Data<AppState>,
    req: HttpRequest,
    path: web::Path<id_type::GlobalPaymentMethodSessionId>,
) -> HttpResponse {
    let flow = Flow::PaymentMethodSessionRetrieve;
    let payment_method_session_id = path.into_inner();

    Box::pin(api::server_wrap(
        flow,
        state,
        &req,
        payment_method_session_id.clone(),
        |state, auth: auth::AuthenticationData, payment_method_session_id, _| async move {
            let merchant_context = domain::MerchantContext::NormalMerchant(Box::new(
                domain::Context(auth.merchant_account, auth.key_store),
            ));
            payment_methods_routes::payment_methods_session_retrieve(
                state,
                merchant_context,
                payment_method_session_id,
            )
            .await
        },
        auth::api_or_client_auth(
            &auth::V2ApiKeyAuth {
                is_connected_allowed: false,
                is_platform_allowed: false,
            },
            &auth::V2ClientAuth(
                common_utils::types::authentication::ResourceId::PaymentMethodSession(
                    payment_method_session_id,
                ),
            ),
            req.headers(),
        ),
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

#[cfg(feature = "v2")]
#[instrument(skip_all, fields(flow = ?Flow::PaymentMethodsList))]
pub async fn payment_method_session_list_payment_methods(
    state: web::Data<AppState>,
    req: HttpRequest,
    path: web::Path<id_type::GlobalPaymentMethodSessionId>,
) -> HttpResponse {
    let flow = Flow::PaymentMethodsList;
    let payment_method_session_id = path.into_inner();

    Box::pin(api::server_wrap(
        flow,
        state,
        &req,
        payment_method_session_id.clone(),
        |state, auth: auth::AuthenticationData, payment_method_session_id, _| {
            let merchant_context = domain::MerchantContext::NormalMerchant(Box::new(
                domain::Context(auth.merchant_account, auth.key_store),
            ));
            payment_methods_routes::list_payment_methods_for_session(
                state,
                merchant_context,
                auth.profile,
                payment_method_session_id,
            )
        },
        &auth::V2ClientAuth(
            common_utils::types::authentication::ResourceId::PaymentMethodSession(
                payment_method_session_id,
            ),
        ),
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

#[cfg(feature = "v2")]
#[derive(Clone, Debug, serde::Serialize)]
struct PaymentMethodsSessionGenericRequest<T: serde::Serialize> {
    payment_method_session_id: id_type::GlobalPaymentMethodSessionId,
    #[serde(flatten)]
    request: T,
}

#[cfg(feature = "v2")]
impl<T: serde::Serialize> common_utils::events::ApiEventMetric
    for PaymentMethodsSessionGenericRequest<T>
{
    fn get_api_event_type(&self) -> Option<common_utils::events::ApiEventsType> {
        Some(common_utils::events::ApiEventsType::PaymentMethodSession {
            payment_method_session_id: self.payment_method_session_id.clone(),
        })
    }
}

#[cfg(feature = "v2")]
#[instrument(skip_all, fields(flow = ?Flow::PaymentMethodSessionConfirm))]
pub async fn payment_method_session_confirm(
    state: web::Data<AppState>,
    req: HttpRequest,
    path: web::Path<id_type::GlobalPaymentMethodSessionId>,
    json_payload: web::Json<api_models::payment_methods::PaymentMethodSessionConfirmRequest>,
) -> HttpResponse {
    let flow = Flow::PaymentMethodSessionConfirm;
    let payload = json_payload.into_inner();
    let payment_method_session_id = path.into_inner();

    let request = PaymentMethodsSessionGenericRequest {
        payment_method_session_id: payment_method_session_id.clone(),
        request: payload,
    };

    Box::pin(api::server_wrap(
        flow,
        state,
        &req,
        request,
        |state, auth: auth::AuthenticationData, request, req_state| {
            let merchant_context = domain::MerchantContext::NormalMerchant(Box::new(
                domain::Context(auth.merchant_account, auth.key_store),
            ));
            payment_methods_routes::payment_methods_session_confirm(
                state,
                req_state,
                merchant_context,
                auth.profile,
                request.payment_method_session_id,
                request.request,
            )
        },
        &auth::V2ClientAuth(
            common_utils::types::authentication::ResourceId::PaymentMethodSession(
                payment_method_session_id,
            ),
        ),
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

#[cfg(feature = "v2")]
#[instrument(skip_all, fields(flow = ?Flow::PaymentMethodSessionUpdateSavedPaymentMethod))]
pub async fn payment_method_session_update_saved_payment_method(
    state: web::Data<AppState>,
    req: HttpRequest,
    path: web::Path<id_type::GlobalPaymentMethodSessionId>,
    json_payload: web::Json<
        api_models::payment_methods::PaymentMethodSessionUpdateSavedPaymentMethod,
    >,
) -> HttpResponse {
    let flow = Flow::PaymentMethodSessionUpdateSavedPaymentMethod;
    let payload = json_payload.into_inner();
    let payment_method_session_id = path.into_inner();

    let request = PaymentMethodsSessionGenericRequest {
        payment_method_session_id: payment_method_session_id.clone(),
        request: payload,
    };

    Box::pin(api::server_wrap(
        flow,
        state,
        &req,
        request,
        |state, auth: auth::AuthenticationData, request, _| {
            let merchant_context = domain::MerchantContext::NormalMerchant(Box::new(
                domain::Context(auth.merchant_account, auth.key_store),
            ));
            payment_methods_routes::payment_methods_session_update_payment_method(
                state,
                merchant_context,
                auth.profile,
                request.payment_method_session_id,
                request.request,
            )
        },
        &auth::V2ClientAuth(
            common_utils::types::authentication::ResourceId::PaymentMethodSession(
                payment_method_session_id,
            ),
        ),
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

#[cfg(feature = "v2")]
#[instrument(skip_all, fields(flow = ?Flow::PaymentMethodSessionUpdateSavedPaymentMethod))]
pub async fn payment_method_session_delete_saved_payment_method(
    state: web::Data<AppState>,
    req: HttpRequest,
    path: web::Path<id_type::GlobalPaymentMethodSessionId>,
    json_payload: web::Json<
        api_models::payment_methods::PaymentMethodSessionDeleteSavedPaymentMethod,
    >,
) -> HttpResponse {
    let flow = Flow::PaymentMethodSessionDeleteSavedPaymentMethod;
    let payload = json_payload.into_inner();
    let payment_method_session_id = path.into_inner();

    let request = PaymentMethodsSessionGenericRequest {
        payment_method_session_id: payment_method_session_id.clone(),
        request: payload,
    };

    Box::pin(api::server_wrap(
        flow,
        state,
        &req,
        request,
        |state, auth: auth::AuthenticationData, request, _| {
            let merchant_context = domain::MerchantContext::NormalMerchant(Box::new(
                domain::Context(auth.merchant_account, auth.key_store),
            ));
            payment_methods_routes::payment_methods_session_delete_payment_method(
                state,
                merchant_context,
                auth.profile,
                request.request.payment_method_id,
                request.payment_method_session_id,
            )
        },
        &auth::V2ClientAuth(
            common_utils::types::authentication::ResourceId::PaymentMethodSession(
                payment_method_session_id,
            ),
        ),
        api_locking::LockAction::NotApplicable,
    ))
    .await
}


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

---
openapi: post /gsm/update
---


pub struct CreateOrderRequestData {
    pub minor_amount: MinorUnit,
    pub currency: storage_enums::Currency,
}


    connectors::Coingate,
    connectors::Cryptopay,
    connectors::Custombilling,
    connectors::Datatrans,
    connectors::Dlocal,
    connectors::Dwolla,
    connectors::Ebanx,
    connectors::Elavon,
    connectors::Facilitapay,
    connectors::Fiserv,
    connectors::Fiservemea,
    connectors::Fiuu,
    connectors::Flexiti,
    connectors::Forte,
    connectors::Getnet,
    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::Mifinity,
    connectors::Moneris,
    connectors::Mpgs,
    connectors::Multisafepay,
    connectors::Netcetera,
    connectors::Nomupay,
    connectors::Noon,
    connectors::Nordea,
    connectors::Novalnet,
    connectors::Nexinets,
    connectors::Opayo,
    connectors::Opennode,
    connectors::Payeezy,
    connectors::Payload,
    connectors::Payone,
    connectors::Paystack,
    connectors::Paytm,
    connectors::Payu,
    connectors::Phonepe,
    connectors::Placetopay,
    connectors::Plaid,
    connectors::Rapyd,
    connectors::Razorpay,
    connectors::Recurly,
    connectors::Riskified,
    connectors::Santander,
    connectors::Sift,
    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::Wise,
    connectors::Wellsfargo,
    connectors::Wellsfargopayout,
    connectors::Worldline,
    connectors::Worldpayvantiv,
    connectors::Worldpayxml,
    connectors::Volt,
    connectors::Xendit,
    connectors::Zen,
    connectors::Zsl,
    connectors::CtpMastercard
);

macro_rules! default_imp_for_incremental_authorization {
    ($($path:ident::$connector:ident),*) => {
        $(
            impl PaymentIncrementalAuthorization for $path::$connector {}
            impl
            ConnectorIntegration<
            IncrementalAuthorization,
            PaymentsIncrementalAuthorizationData,
            PaymentsResponseData,
        > for $path::$connector
        {}
    )*
    };
}

default_imp_for_incremental_authorization!(
    connectors::Paysafe,
    connectors::Vgs,
    connectors::Aci,
    connectors::Adyen,
    connectors::Adyenplatform,
    connectors::Affirm,
    connectors::Airwallex,
    connectors::Amazonpay,
    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::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::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::Wellsfargopayout,
    connectors::Wise,
    connectors::Worldline,
    connectors::Worldpay,
    connectors::Worldpayvantiv,
    connectors::Worldpayxml,
    connectors::Volt,
    connectors::Xendit,
    connectors::Zen,
    connectors::Zsl,
    connectors::CtpMastercard
);

macro_rules! default_imp_for_create_customer {
    ($($path:ident::$connector:ident),*) => {
        $(
            impl ConnectorCustomer for $path::$connector {}
            impl
            ConnectorIntegration<
            CreateConnectorCustomer,
            ConnectorCustomerData,
            PaymentsResponseData,
        > for $path::$connector
        {}
    )*
    };
}

default_imp_for_create_customer!(
    connectors::Vgs,
    connectors::Aci,
    connectors::Adyen,
    connectors::Adyenplatform,
    connectors::Affirm,
    connectors::Airwallex,
    connectors::Amazonpay,
    connectors::Archipel,
    connectors::Authipay,
    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::Ebanx,
    connectors::Elavon,
    connectors::Fiserv,
    connectors::Fiservemea,
    connectors::Fiuu,
    connectors::Flexiti,
    connectors::Forte,
    connectors::Getnet,
    connectors::Globalpay,
    connectors::Globepay,
    connectors::Gpayments,
    connectors::Hipay,
    connectors::Helcim,
    connectors::Hyperwallet,
    connectors::Iatapay,
    connectors::Inespay,
    connectors::Itaubank,
    connectors::Jpmorgan,
    connectors::Juspaythreedsserver,
    connectors::Katapult,
    connectors::Klarna,
    connectors::Mifinity,
    connectors::Mollie,
    connectors::Moneris,
    connectors::Mpgs,
    connectors::Multisafepay,
    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::Payme,
    connectors::Payload,
    connectors::Payone,
    connectors::Paypal,
    connectors::Paysafe,
    connectors::Paystack,
    connectors::Paytm,
    connectors::Payu,
    connectors::Phonepe,
    connectors::Placetopay,
    connectors::Plaid,
    connectors::Powertranz,
    connectors::Prophetpay,
    connectors::Rapyd,
    connectors::Razorpay,
    connectors::Recurly,
    connectors::Redsys,
    connectors::Riskified,
    connectors::Santander,
    connectors::Shift4,
    connectors::Sift,
    connectors::Silverflow,
    connectors::Signifyd,
    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
);

macro_rules! default_imp_for_connector_redirect_response {
    ($($path:ident::$connector:ident),*) => {
        $(
            impl ConnectorRedirectResponse for $path::$connector {
                fn get_flow_type(
                    &self,
                    _query_params: &str,
                    _json_payload: Option<serde_json::Value>,
                    _action: common_enums::enums::PaymentAction
                ) -> CustomResult<common_enums::enums::CallConnectorAction, ConnectorError> {
                    Ok(common_enums::enums::CallConnectorAction::Trigger)
                }
            }
    )*
    };
}

default_imp_for_connector_redirect_response!(
    connectors::Paysafe,
    connectors::Trustpayments,
    connectors::Vgs,
    connectors::Aci,
    connectors::Adyen,
    connectors::Adyenplatform,
    connectors::Affirm,
    connectors::Amazonpay,
    connectors::Archipel,
    connectors::Authipay,
    connectors::Billwerk,
    connectors::Bitpay,
    connectors::Blackhawknetwork,
    connectors::Bluecode,
    connectors::Bamboraapac,
    connectors::Bankofamerica,
    connectors::Barclaycard,
    connectors::Boku,
    connectors::Cashtocode,
    connectors::Celero,
    connectors::Chargebee,
    connectors::Checkbook,
    connectors::Coinbase,
    connectors::Coingate,
    connectors::Cryptopay,
    connectors::Custombilling,
    connectors::Cybersource,
    connectors::Datatrans,
    connectors::Deutschebank,
    connectors::Dlocal,
    connectors::Dwolla,
    connectors::Ebanx,
    connectors::Elavon,
    connectors::Facilitapay,
    connectors::Fiserv,
    connectors::Fiservemea,
    connectors::Fiuu,
    connectors::Flexiti,
    connectors::Forte,
    connectors::Getnet,
    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::Mifinity,
    connectors::Moneris,
    connectors::Mpgs,
    connectors::Multisafepay,
    connectors::Netcetera,
    connectors::Nexinets,
    connectors::Nexixpay,
    connectors::Nordea,
    connectors::Opayo,
    connectors::Opennode,
    connectors::Payeezy,
    connectors::Payload,
    connectors::Paystack,
    connectors::Paytm,
    connectors::Payone,
    connectors::Payu,
    connectors::Phonepe,
    connectors::Placetopay,
    connectors::Plaid,
    connectors::Powertranz,
    connectors::Prophetpay,
    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::Tsys,
    connectors::UnifiedAuthenticationService,
    connectors::Wise,
    connectors::Wellsfargo,
    connectors::Wellsfargopayout,
    connectors::Worldline,
    connectors::Worldpayvantiv,
    connectors::Worldpayxml,
    connectors::Volt,
    connectors::Zsl,
    connectors::CtpMastercard
);

macro_rules! default_imp_for_pre_processing_steps{
    ($($path:ident::$connector:ident),*)=> {
        $(
            impl PaymentsPreProcessing for $path::$connector {}
            impl
            ConnectorIntegration<
            PreProcessing,
            PaymentsPreProcessingData,
            PaymentsResponseData,
        > for $path::$connector
        {}
    )*
    };
}

default_imp_for_pre_processing_steps!(
    connectors::Trustpayments,
    connectors::Silverflow,
    connectors::Vgs,
    connectors::Aci,
    connectors::Adyenplatform,
    connectors::Affirm,
    connectors::Amazonpay,
    connectors::Archipel,
    connectors::Authipay,
    connectors::Authorizedotnet,
    connectors::Bambora,
    connectors::Bamboraapac,
    connectors::Bankofamerica,
    connectors::Billwerk,
    connectors::Bitpay,
    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::Ebanx,
    connectors::Elavon,
    connectors::Facilitapay,
    connectors::Fiserv,
    connectors::Fiservemea,
    connectors::Fiuu,
    connectors::Flexiti,
    connectors::Forte,
    connectors::Getnet,
    connectors::Globalpay,
    connectors::Globepay,
    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::Noon,
    connectors::Novalnet,
    connectors::Nexinets,
    connectors::Opayo,
    connectors::Opennode,
    connectors::Paybox,
    connectors::Payeezy,
    connectors::Payload,
    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::Riskified,
    connectors::Santander,
    connectors::Sift,
    connectors::Signifyd,
    connectors::Stax,
    connectors::Square,
    connectors::Stripe,
    connectors::Stripebilling,
    connectors::Taxjar,
    connectors::Threedsecureio,
    connectors::Thunes,
    connectors::Tokenio,
    connectors::Tsys,
    connectors::UnifiedAuthenticationService,
    connectors::Wise,
    connectors::Worldline,
    connectors::Worldpay,
    connectors::Worldpayvantiv,
    connectors::Worldpayxml,
    connectors::Wellsfargo,
    connectors::Wellsfargopayout,
    connectors::Volt,
    connectors::Zen,
    connectors::Zsl,
    connectors::CtpMastercard
);

macro_rules! default_imp_for_post_processing_steps{
    ($($path:ident::$connector:ident),*)=> {
        $(
            impl PaymentsPostProcessing for $path::$connector {}
            impl
            ConnectorIntegration<
            PostProcessing,
            PaymentsPostProcessingData,
            PaymentsResponseData,
        > for $path::$connector
        {}
    )*
    };
}

default_imp_for_post_processing_steps!(
    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::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::Wise,
    connectors::Worldline,
    connectors::Worldpay,
    connectors::Worldpayvantiv,
    connectors::Worldpayxml,
    connectors::Wellsfargo,
    connectors::Wellsfargopayout,
    connectors::Volt,
    connectors::Xendit,
    connectors::Zen,
    connectors::Zsl,
    connectors::CtpMastercard
);

macro_rules! default_imp_for_approve {
    ($($path:ident::$connector:ident),*) => {
        $(
            impl PaymentApprove for $path::$connector {}
            impl
            ConnectorIntegration<
            Approve,
            PaymentsApproveData,
            PaymentsResponseData,
        > for $path::$connector
        {}
    )*
    };
}

default_imp_for_approve!(
    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::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::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::Wise,
    connectors::Worldline,
    connectors::Worldpay,
    connectors::Worldpayvantiv,
    connectors::Worldpayxml,
    connectors::Wellsfargo,
    connectors::Wellsfargopayout,
    connectors::Volt,
    connectors::Xendit,
    connectors::Zen,
    connectors::Zsl,
    connectors::CtpMastercard
);

macro_rules! default_imp_for_reject {
    ($($path:ident::$connector:ident),*) => {
        $(
            impl PaymentReject for $path::$connector {}
            impl
            ConnectorIntegration<
            Reject,
            PaymentsRejectData,
            PaymentsResponseData,
        > for $path::$connector
        {}
    )*
    };
}

default_imp_for_reject!(
    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::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::Wise,
    connectors::Worldline,
    connectors::Worldpay,
    connectors::Worldpayvantiv,
    connectors::Worldpayxml,
    connectors::Wellsfargo,
    connectors::Wellsfargopayout,
    connectors::Volt,
    connectors::Xendit,
    connectors::Zen,
    connectors::Zsl,
    connectors::CtpMastercard
);

macro_rules! default_imp_for_webhook_source_verification {
    ($($path:ident::$connector:ident),*) => {
        $(
            impl api::ConnectorVerifyWebhookSource for $path::$connector {}
            impl
            ConnectorIntegration<
            VerifyWebhookSource,
            VerifyWebhookSourceRequestData,
            VerifyWebhookSourceResponseData,
        > for $path::$connector
        {}
    )*
    };
}

default_imp_for_webhook_source_verification!(
    connectors::Paysafe,
    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::Ebanx,
    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::Payone,
    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::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
);

macro_rules! default_imp_for_accept_dispute {
    ($($path:ident::$connector:ident),*) => {
        $(
            impl Dispute for $path::$connector {}
            impl AcceptDispute for $path::$connector {}
            impl
                ConnectorIntegration<
                Accept,
                AcceptDisputeRequestData,
                AcceptDisputeResponse,
            > for $path::$connector
            {}
    )*
    };
}

default_imp_for_accept_dispute!(
    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::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,


pub struct LineageContext {
    /// user_id: String
    pub user_id: String,

    /// merchant_id: MerchantId
    pub merchant_id: id_type::MerchantId,

    /// role_id: String
    pub role_id: String,

    /// org_id: OrganizationId
    pub org_id: id_type::OrganizationId,

    /// profile_id: ProfileId
    pub profile_id: id_type::ProfileId,

    /// tenant_id: TenantId
    pub tenant_id: id_type::TenantId,
}


OpenAPI Block Path: components.schemas.MetadataValue
{
  "type": "object",
  "required": [
    "key",
    "value"
  ],
  "properties": {
    "key": {
      "type": "string"
    },
    "value": {
      "type": "string"
    }
  }
}


pub fn should_call_payout_connector_create_customer<'a>(
    state: &'a SessionState,
    connector: &'a api::ConnectorData,
    customer: &'a Option<domain::Customer>,
    connector_label: &'a str,
) -> (bool, Option<&'a str>) {
    // Check if create customer is required for the connector
    match enums::PayoutConnectors::try_from(connector.connector_name) {
        Ok(connector) => {
            let connector_needs_customer = state
                .conf
                .connector_customer
                .payout_connector_list
                .contains(&connector);

            if connector_needs_customer {
                let connector_customer_details = customer
                    .as_ref()
                    .and_then(|customer| customer.get_connector_customer_id(connector_label));
                let should_call_connector = connector_customer_details.is_none();
                (should_call_connector, connector_customer_details)
            } else {
                (false, None)
            }
        }
        _ => (false, None),
    }
}


File: crates/diesel_models/src/kv.rs
 Public functions: 4
 Public structs: 12

use error_stack::ResultExt;
use serde::{Deserialize, Serialize};

#[cfg(feature = "v2")]
use crate::payment_attempt::PaymentAttemptUpdateInternal;
#[cfg(feature = "v1")]
use crate::payment_intent::PaymentIntentUpdate;
#[cfg(feature = "v2")]
use crate::payment_intent::PaymentIntentUpdateInternal;
use crate::{
    address::{Address, AddressNew, AddressUpdateInternal},
    customers::{Customer, CustomerNew, CustomerUpdateInternal},
    errors,
    payment_attempt::{PaymentAttempt, PaymentAttemptNew, PaymentAttemptUpdate},
    payment_intent::PaymentIntentNew,
    payout_attempt::{PayoutAttempt, PayoutAttemptNew, PayoutAttemptUpdate},
    payouts::{Payouts, PayoutsNew, PayoutsUpdate},
    refund::{Refund, RefundNew, RefundUpdate},
    reverse_lookup::{ReverseLookup, ReverseLookupNew},
    Mandate, MandateNew, MandateUpdateInternal, PaymentIntent, PaymentMethod, PaymentMethodNew,
    PaymentMethodUpdateInternal, PgPooledConn,
};

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "snake_case", tag = "db_op", content = "data")]
pub enum DBOperation {
    Insert { insertable: Box<Insertable> },
    Update { updatable: Box<Updateable> },
}

impl DBOperation {
    pub fn operation<'a>(&self) -> &'a str {
        match self {
            Self::Insert { .. } => "insert",
            Self::Update { .. } => "update",
        }
    }
    pub fn table<'a>(&self) -> &'a str {
        match self {
            Self::Insert { insertable } => match **insertable {
                Insertable::PaymentIntent(_) => "payment_intent",
                Insertable::PaymentAttempt(_) => "payment_attempt",
                Insertable::Refund(_) => "refund",
                Insertable::Address(_) => "address",
                Insertable::Payouts(_) => "payouts",
                Insertable::PayoutAttempt(_) => "payout_attempt",
                Insertable::Customer(_) => "customer",
                Insertable::ReverseLookUp(_) => "reverse_lookup",
                Insertable::PaymentMethod(_) => "payment_method",
                Insertable::Mandate(_) => "mandate",
            },
            Self::Update { updatable } => match **updatable {
                Updateable::PaymentIntentUpdate(_) => "payment_intent",
                Updateable::PaymentAttemptUpdate(_) => "payment_attempt",
                Updateable::RefundUpdate(_) => "refund",
                Updateable::CustomerUpdate(_) => "customer",
                Updateable::AddressUpdate(_) => "address",
                Updateable::PayoutsUpdate(_) => "payouts",
                Updateable::PayoutAttemptUpdate(_) => "payout_attempt",
                Updateable::PaymentMethodUpdate(_) => "payment_method",
                Updateable::MandateUpdate(_) => " mandate",
            },
        }
    }
}

#[derive(Debug)]
pub enum DBResult {
    PaymentIntent(Box<PaymentIntent>),
    PaymentAttempt(Box<PaymentAttempt>),
    Refund(Box<Refund>),
    Address(Box<Address>),
    Customer(Box<Customer>),
    ReverseLookUp(Box<ReverseLookup>),
    Payouts(Box<Payouts>),
    PayoutAttempt(Box<PayoutAttempt>),
    PaymentMethod(Box<PaymentMethod>),
    Mandate(Box<Mandate>),
}

#[derive(Debug, Serialize, Deserialize)]
pub struct TypedSql {
    #[serde(flatten)]
    pub op: DBOperation,
}

impl DBOperation {
    pub async fn execute(self, conn: &PgPooledConn) -> crate::StorageResult<DBResult> {
        Ok(match self {
            Self::Insert { insertable } => match *insertable {
                Insertable::PaymentIntent(a) => {
                    DBResult::PaymentIntent(Box::new(a.insert(conn).await?))
                }
                Insertable::PaymentAttempt(a) => {
                    DBResult::PaymentAttempt(Box::new(a.insert(conn).await?))
                }
                Insertable::Refund(a) => DBResult::Refund(Box::new(a.insert(conn).await?)),
                Insertable::Address(addr) => DBResult::Address(Box::new(addr.insert(conn).await?)),
                Insertable::Customer(cust) => {
                    DBResult::Customer(Box::new(cust.insert(conn).await?))
                }
                Insertable::ReverseLookUp(rev) => {
                    DBResult::ReverseLookUp(Box::new(rev.insert(conn).await?))
                }
                Insertable::Payouts(rev) => DBResult::Payouts(Box::new(rev.insert(conn).await?)),
                Insertable::PayoutAttempt(rev) => {
                    DBResult::PayoutAttempt(Box::new(rev.insert(conn).await?))
                }
                Insertable::PaymentMethod(rev) => {
                    DBResult::PaymentMethod(Box::new(rev.insert(conn).await?))
                }
                Insertable::Mandate(m) => DBResult::Mandate(Box::new(m.insert(conn).await?)),
            },
            Self::Update { updatable } => match *updatable {
                #[cfg(feature = "v1")]
                Updateable::PaymentIntentUpdate(a) => {
                    DBResult::PaymentIntent(Box::new(a.orig.update(conn, a.update_data).await?))
                }
                #[cfg(feature = "v2")]
                Updateable::PaymentIntentUpdate(a) => {
                    DBResult::PaymentIntent(Box::new(a.orig.update(conn, a.update_data).await?))
                }
                #[cfg(feature = "v1")]
                Updateable::PaymentAttemptUpdate(a) => DBResult::PaymentAttempt(Box::new(
                    a.orig.update_with_attempt_id(conn, a.update_data).await?,
                )),
                #[cfg(feature = "v2")]
                Updateable::PaymentAttemptUpdate(a) => DBResult::PaymentAttempt(Box::new(
                    a.orig.update_with_attempt_id(conn, a.update_data).await?,
                )),
                #[cfg(feature = "v1")]
                Updateable::RefundUpdate(a) => {
                    DBResult::Refund(Box::new(a.orig.update(conn, a.update_data).await?))
                }
                #[cfg(feature = "v2")]
                Updateable::RefundUpdate(a) => {
                    DBResult::Refund(Box::new(a.orig.update_with_id(conn, a.update_data).await?))
                }
                Updateable::AddressUpdate(a) => {
                    DBResult::Address(Box::new(a.orig.update(conn, a.update_data).await?))
                }
                Updateable::PayoutsUpdate(a) => {
                    DBResult::Payouts(Box::new(a.orig.update(conn, a.update_data).await?))
                }
                Updateable::PayoutAttemptUpdate(a) => DBResult::PayoutAttempt(Box::new(
                    a.orig.update_with_attempt_id(conn, a.update_data).await?,
                )),
                #[cfg(feature = "v1")]
                Updateable::PaymentMethodUpdate(v) => DBResult::PaymentMethod(Box::new(
                    v.orig
                        .update_with_payment_method_id(conn, v.update_data)
                        .await?,
                )),
                #[cfg(feature = "v2")]
                Updateable::PaymentMethodUpdate(v) => DBResult::PaymentMethod(Box::new(
                    v.orig.update_with_id(conn, v.update_data).await?,
                )),
                Updateable::MandateUpdate(m) => DBResult::Mandate(Box::new(
                    Mandate::update_by_merchant_id_mandate_id(
                        conn,
                        &m.orig.merchant_id,
                        &m.orig.mandate_id,
                        m.update_data,
                    )
                    .await?,
                )),
                #[cfg(feature = "v1")]
                Updateable::CustomerUpdate(cust) => DBResult::Customer(Box::new(
                    Customer::update_by_customer_id_merchant_id(
                        conn,
                        cust.orig.customer_id.clone(),
                        cust.orig.merchant_id.clone(),
                        cust.update_data,
                    )
                    .await?,
                )),
                #[cfg(feature = "v2")]
                Updateable::CustomerUpdate(cust) => DBResult::Customer(Box::new(
                    Customer::update_by_id(conn, cust.orig.id, cust.update_data).await?,
                )),
            },
        })
    }
}

impl TypedSql {
    pub fn to_field_value_pairs(
        &self,
        request_id: String,
        global_id: String,
    ) -> crate::StorageResult<Vec<(&str, String)>> {
        let pushed_at = common_utils::date_time::now_unix_timestamp();

        Ok(vec![
            (
                "typed_sql",
                serde_json::to_string(self)
                    .change_context(errors::DatabaseError::QueryGenerationFailed)?,
            ),
            ("global_id", global_id),
            ("request_id", request_id),
            ("pushed_at", pushed_at.to_string()),
        ])
    }
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "snake_case", tag = "table", content = "data")]
pub enum Insertable {
    PaymentIntent(Box<PaymentIntentNew>),
    PaymentAttempt(Box<PaymentAttemptNew>),
    Refund(RefundNew),
    Address(Box<AddressNew>),
    Customer(CustomerNew),
    ReverseLookUp(ReverseLookupNew),
    Payouts(PayoutsNew),
    PayoutAttempt(PayoutAttemptNew),
    PaymentMethod(PaymentMethodNew),
    Mandate(MandateNew),
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "snake_case", tag = "table", content = "data")]
pub enum Updateable {
    PaymentIntentUpdate(Box<PaymentIntentUpdateMems>),
    PaymentAttemptUpdate(Box<PaymentAttemptUpdateMems>),
    RefundUpdate(Box<RefundUpdateMems>),
    CustomerUpdate(CustomerUpdateMems),
    AddressUpdate(Box<AddressUpdateMems>),
    PayoutsUpdate(PayoutsUpdateMems),
    PayoutAttemptUpdate(PayoutAttemptUpdateMems),
    PaymentMethodUpdate(Box<PaymentMethodUpdateMems>),
    MandateUpdate(MandateUpdateMems),
}

#[derive(Debug, Serialize, Deserialize)]
pub struct CustomerUpdateMems {
    pub orig: Customer,
    pub update_data: CustomerUpdateInternal,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct AddressUpdateMems {
    pub orig: Address,
    pub update_data: AddressUpdateInternal,
}
#[cfg(feature = "v1")]
#[derive(Debug, Serialize, Deserialize)]
pub struct PaymentIntentUpdateMems {
    pub orig: PaymentIntent,
    pub update_data: PaymentIntentUpdate,
}

#[cfg(feature = "v2")]
#[derive(Debug, Serialize, Deserialize)]
pub struct PaymentIntentUpdateMems {
    pub orig: PaymentIntent,
    pub update_data: PaymentIntentUpdateInternal,
}

#[cfg(feature = "v1")]
#[derive(Debug, Serialize, Deserialize)]
pub struct PaymentAttemptUpdateMems {
    pub orig: PaymentAttempt,
    pub update_data: PaymentAttemptUpdate,
}

#[cfg(feature = "v2")]
#[derive(Debug, Serialize, Deserialize)]
pub struct PaymentAttemptUpdateMems {
    pub orig: PaymentAttempt,
    pub update_data: PaymentAttemptUpdateInternal,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct RefundUpdateMems {
    pub orig: Refund,
    pub update_data: RefundUpdate,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct PayoutsUpdateMems {
    pub orig: Payouts,
    pub update_data: PayoutsUpdate,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct PayoutAttemptUpdateMems {
    pub orig: PayoutAttempt,
    pub update_data: PayoutAttemptUpdate,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct PaymentMethodUpdateMems {
    pub orig: PaymentMethod,
    pub update_data: PaymentMethodUpdateInternal,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct MandateUpdateMems {
    pub orig: Mandate,
    pub update_data: MandateUpdateInternal,
}


File: crates/hyperswitch_connectors/src/types.rs

#[cfg(feature = "v2")]
use hyperswitch_domain_models::router_data_v2::RouterDataV2;
#[cfg(feature = "payouts")]
use hyperswitch_domain_models::types::{PayoutsData, PayoutsResponseData};
use hyperswitch_domain_models::{
    router_data::{AccessToken, RouterData},
    router_flow_types::{
        authentication::{
            Authentication, PostAuthentication, PreAuthentication, PreAuthenticationVersionCall,
        },
        Accept, AccessTokenAuth, Authorize, Capture, CreateOrder, Defend, Dsync, Evidence, Fetch,
        PSync, PostProcessing, PreProcessing, Retrieve, Session, Upload, Void,
    },
    router_request_types::{
        authentication::{
            ConnectorAuthenticationRequestData, ConnectorPostAuthenticationRequestData,
            PreAuthNRequestData,
        },
        AcceptDisputeRequestData, AccessTokenRequestData, CreateOrderRequestData,
        DefendDisputeRequestData, DisputeSyncData, FetchDisputesRequestData, PaymentsAuthorizeData,
        PaymentsCancelData, PaymentsCaptureData, PaymentsPostProcessingData,
        PaymentsPreProcessingData, PaymentsSessionData, PaymentsSyncData, RefundsData,
        RetrieveFileRequestData, SubmitEvidenceRequestData, UploadFileRequestData,
    },
    router_response_types::{
        AcceptDisputeResponse, AuthenticationResponseData, DefendDisputeResponse,
        DisputeSyncResponse, FetchDisputesResponse, PaymentsResponseData, RefundsResponseData,
        RetrieveFileResponse, SubmitEvidenceResponse, UploadFileResponse,
    },
};
#[cfg(feature = "frm")]
use hyperswitch_domain_models::{
    router_flow_types::{Checkout, Fulfillment, RecordReturn, Sale, Transaction},
    router_request_types::fraud_check::{
        FraudCheckCheckoutData, FraudCheckFulfillmentData, FraudCheckRecordReturnData,
        FraudCheckSaleData, FraudCheckTransactionData,
    },
    router_response_types::fraud_check::FraudCheckResponseData,
};
use hyperswitch_interfaces::api::ConnectorIntegration;

pub(crate) type PaymentsSyncResponseRouterData<R> =
    ResponseRouterData<PSync, R, PaymentsSyncData, PaymentsResponseData>;
pub(crate) type PaymentsResponseRouterData<R> =
    ResponseRouterData<Authorize, R, PaymentsAuthorizeData, PaymentsResponseData>;
pub(crate) type PaymentsCaptureResponseRouterData<R> =
    ResponseRouterData<Capture, R, PaymentsCaptureData, PaymentsResponseData>;
pub(crate) type RefundsResponseRouterData<F, R> =
    ResponseRouterData<F, R, RefundsData, RefundsResponseData>;
pub(crate) type RefreshTokenRouterData =
    RouterData<AccessTokenAuth, AccessTokenRequestData, AccessToken>;

pub(crate) type PaymentsCancelResponseRouterData<R> =
    ResponseRouterData<Void, R, PaymentsCancelData, PaymentsResponseData>;
pub(crate) type PaymentsPreprocessingResponseRouterData<R> =
    ResponseRouterData<PreProcessing, R, PaymentsPreProcessingData, PaymentsResponseData>;
pub(crate) type PaymentsSessionResponseRouterData<R> =
    ResponseRouterData<Session, R, PaymentsSessionData, PaymentsResponseData>;
pub(crate) type CreateOrderResponseRouterData<R> =
    ResponseRouterData<CreateOrder, R, CreateOrderRequestData, PaymentsResponseData>;

pub(crate) type AcceptDisputeRouterData =
    RouterData<Accept, AcceptDisputeRequestData, AcceptDisputeResponse>;
pub(crate) type SubmitEvidenceRouterData =
    RouterData<Evidence, SubmitEvidenceRequestData, SubmitEvidenceResponse>;
pub(crate) type UploadFileRouterData =
    RouterData<Upload, UploadFileRequestData, UploadFileResponse>;
pub(crate) type DefendDisputeRouterData =
    RouterData<Defend, DefendDisputeRequestData, DefendDisputeResponse>;
pub(crate) type FetchDisputeRouterData =
    RouterData<Fetch, FetchDisputesRequestData, FetchDisputesResponse>;
pub(crate) type DisputeSyncRouterData = RouterData<Dsync, DisputeSyncData, DisputeSyncResponse>;

#[cfg(feature = "payouts")]
pub(crate) type PayoutsResponseRouterData<F, R> =
    ResponseRouterData<F, R, PayoutsData, PayoutsResponseData>;

// TODO: Remove `ResponseRouterData` from router crate after all the related type aliases are moved to this crate.
pub(crate) struct ResponseRouterData<Flow, R, Request, Response> {
    pub(crate) response: R,
    pub(crate) data: RouterData<Flow, Request, Response>,
    pub(crate) http_code: u16,
}
#[cfg(feature = "frm")]
pub(crate) type FrmFulfillmentRouterData =
    RouterData<Fulfillment, FraudCheckFulfillmentData, FraudCheckResponseData>;
#[cfg(feature = "frm")]
pub(crate) type FrmCheckoutType =
    dyn ConnectorIntegration<Checkout, FraudCheckCheckoutData, FraudCheckResponseData>;
#[cfg(feature = "frm")]
pub(crate) type FrmTransactionType =
    dyn ConnectorIntegration<Transaction, FraudCheckTransactionData, FraudCheckResponseData>;
#[cfg(feature = "frm")]
pub(crate) type FrmTransactionRouterData =
    RouterData<Transaction, FraudCheckTransactionData, FraudCheckResponseData>;
#[cfg(feature = "frm")]
pub(crate) type FrmFulfillmentType =
    dyn ConnectorIntegration<Fulfillment, FraudCheckFulfillmentData, FraudCheckResponseData>;
#[cfg(feature = "frm")]
pub(crate) type FrmCheckoutRouterData =
    RouterData<Checkout, FraudCheckCheckoutData, FraudCheckResponseData>;
#[cfg(feature = "v2")]
pub(crate) struct ResponseRouterDataV2<Flow, R, ResourceCommonData, Request, Response> {
    pub response: R,
    pub data: RouterDataV2<Flow, ResourceCommonData, Request, Response>,
    #[allow(dead_code)] // Used for metadata passing but this is not read
    pub http_code: u16,
}

pub(crate) type PreAuthNRouterData =
    RouterData<PreAuthentication, PreAuthNRequestData, AuthenticationResponseData>;
pub(crate) type PreAuthNVersionCallRouterData =
    RouterData<PreAuthenticationVersionCall, PreAuthNRequestData, AuthenticationResponseData>;
pub(crate) type ConnectorAuthenticationRouterData =
    RouterData<Authentication, ConnectorAuthenticationRequestData, AuthenticationResponseData>;
pub(crate) type ConnectorPostAuthenticationRouterData = RouterData<
    PostAuthentication,
    ConnectorPostAuthenticationRequestData,
    AuthenticationResponseData,
>;
pub(crate) type ConnectorAuthenticationType = dyn ConnectorIntegration<
    Authentication,
    ConnectorAuthenticationRequestData,
    AuthenticationResponseData,
>;
pub(crate) type ConnectorPostAuthenticationType = dyn ConnectorIntegration<
    PostAuthentication,
    ConnectorPostAuthenticationRequestData,
    AuthenticationResponseData,
>;
pub(crate) type ConnectorPreAuthenticationType =
    dyn ConnectorIntegration<PreAuthentication, PreAuthNRequestData, AuthenticationResponseData>;
pub(crate) type ConnectorPreAuthenticationVersionCallType = dyn ConnectorIntegration<
    PreAuthenticationVersionCall,
    PreAuthNRequestData,
    AuthenticationResponseData,
>;

pub(crate) type PaymentsPostProcessingRouterData =
    RouterData<PostProcessing, PaymentsPostProcessingData, PaymentsResponseData>;
#[cfg(feature = "frm")]
pub(crate) type FrmSaleRouterData = RouterData<Sale, FraudCheckSaleData, FraudCheckResponseData>;
#[cfg(feature = "frm")]
pub(crate) type FrmRecordReturnRouterData =
    RouterData<RecordReturn, FraudCheckRecordReturnData, FraudCheckResponseData>;
#[cfg(feature = "frm")]
pub(crate) type FrmRecordReturnType =
    dyn ConnectorIntegration<RecordReturn, FraudCheckRecordReturnData, FraudCheckResponseData>;
#[cfg(feature = "frm")]
pub(crate) type FrmSaleType =
    dyn ConnectorIntegration<Sale, FraudCheckSaleData, FraudCheckResponseData>;

pub(crate) type RetrieveFileRouterData =
    RouterData<Retrieve, RetrieveFileRequestData, RetrieveFileResponse>;

#[cfg(feature = "payouts")]
pub(crate) trait PayoutIndividualDetailsExt {
    type Error;
    fn get_external_account_account_holder_type(&self) -> Result<String, Self::Error>;
}

#[cfg(feature = "payouts")]
impl PayoutIndividualDetailsExt for api_models::payouts::PayoutIndividualDetails {
    type Error = error_stack::Report<hyperswitch_interfaces::errors::ConnectorError>;
    fn get_external_account_account_holder_type(&self) -> Result<String, Self::Error> {
        self.external_account_account_holder_type
            .clone()
            .ok_or_else(crate::utils::missing_field_err(
                "external_account_account_holder_type",
            ))
    }
}


pub struct NovalnetResponseCard {
    pub card_brand: Option<Secret<String>>,
    pub card_expiry_month: Secret<u8>,
    pub card_expiry_year: Secret<u16>,
    pub card_holder: Secret<String>,
    pub card_number: Secret<String>,
    pub cc_3d: Option<Secret<u8>>,
    pub last_four: Option<Secret<String>>,
    pub token: Option<Secret<String>>,
}


pub async fn list_payment_method_api() {}


pub struct RedisStore {
    // Maybe expose the redis_conn via traits instead of the making the field public
    pub(crate) redis_conn: Arc<redis_interface::RedisConnectionPool>,
}


pub struct AuthEventFilters {
    #[serde(default)]
    pub authentication_status: Vec<AuthenticationStatus>,
    #[serde(default)]
    pub trans_status: Vec<TransactionStatus>,
    #[serde(default)]
    pub authentication_type: Vec<DecoupledAuthenticationType>,
    #[serde(default)]
    pub error_message: Vec<String>,
    #[serde(default)]
    pub authentication_connector: Vec<AuthenticationConnectors>,
    #[serde(default)]
    pub message_version: Vec<String>,
    #[serde(default)]
    pub platform: Vec<String>,
    #[serde(default)]
    pub acs_reference_number: Vec<String>,
    #[serde(default)]
    pub mcc: Vec<String>,
    #[serde(default)]
    pub currency: Vec<Currency>,
    #[serde(default)]
    pub merchant_country: Vec<String>,
    #[serde(default)]
    pub billing_country: Vec<String>,
    #[serde(default)]
    pub shipping_country: Vec<String>,
    #[serde(default)]
    pub issuer_country: Vec<String>,
    #[serde(default)]
    pub earliest_supported_version: Vec<String>,
    #[serde(default)]
    pub latest_supported_version: Vec<String>,
    #[serde(default)]
    pub whitelist_decision: Vec<bool>,
    #[serde(default)]
    pub device_manufacturer: Vec<String>,
    #[serde(default)]
    pub device_type: Vec<String>,
    #[serde(default)]
    pub device_brand: Vec<String>,
    #[serde(default)]
    pub device_os: Vec<String>,
    #[serde(default)]
    pub device_display: Vec<String>,
    #[serde(default)]
    pub browser_name: Vec<String>,
    #[serde(default)]
    pub browser_version: Vec<String>,
    #[serde(default)]
    pub issuer_id: Vec<String>,
    #[serde(default)]
    pub scheme_name: Vec<String>,
    #[serde(default)]
    pub exemption_requested: Vec<bool>,
    #[serde(default)]
    pub exemption_accepted: Vec<bool>,
}


File: crates/api_models/src/three_ds_decision_rule.rs
 Public structs: 7

use euclid::frontend::dir::enums::{
    CustomerDeviceDisplaySize, CustomerDevicePlatform, CustomerDeviceType,
};
use utoipa::ToSchema;

/// Represents the payment data used in the 3DS decision rule.
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct PaymentData {
    /// The amount of the payment in minor units (e.g., cents for USD).
    #[schema(value_type = i64)]
    pub amount: common_utils::types::MinorUnit,
    /// The currency of the payment.
    #[schema(value_type = Currency)]
    pub currency: common_enums::Currency,
}

/// Represents metadata about the payment method used in the 3DS decision rule.
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct PaymentMethodMetaData {
    /// The card network (e.g., Visa, Mastercard) if the payment method is a card.
    #[schema(value_type = CardNetwork)]
    pub card_network: Option<common_enums::CardNetwork>,
}

/// Represents data about the customer's device used in the 3DS decision rule.
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct CustomerDeviceData {
    /// The platform of the customer's device (e.g., Web, Android, iOS).
    pub platform: Option<CustomerDevicePlatform>,
    /// The type of the customer's device (e.g., Mobile, Tablet, Desktop).
    pub device_type: Option<CustomerDeviceType>,
    /// The display size of the customer's device.
    pub display_size: Option<CustomerDeviceDisplaySize>,
}

/// Represents data about the issuer used in the 3DS decision rule.
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct IssuerData {
    /// The name of the issuer.
    pub name: Option<String>,
    /// The country of the issuer.
    #[schema(value_type = Country)]
    pub country: Option<common_enums::Country>,
}

/// Represents data about the acquirer used in the 3DS decision rule.
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct AcquirerData {
    /// The country of the acquirer.
    #[schema(value_type = Country)]
    pub country: Option<common_enums::Country>,
    /// The fraud rate associated with the acquirer.
    pub fraud_rate: Option<f64>,
}

/// Represents the request to execute a 3DS decision rule.
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
#[serde(deny_unknown_fields)]
pub struct ThreeDsDecisionRuleExecuteRequest {
    /// The ID of the routing algorithm to be executed.
    #[schema(value_type = String)]
    pub routing_id: common_utils::id_type::RoutingId,
    /// Data related to the payment.
    pub payment: PaymentData,
    /// Optional metadata about the payment method.
    pub payment_method: Option<PaymentMethodMetaData>,
    /// Optional data about the customer's device.
    pub customer_device: Option<CustomerDeviceData>,
    /// Optional data about the issuer.
    pub issuer: Option<IssuerData>,
    /// Optional data about the acquirer.
    pub acquirer: Option<AcquirerData>,
}

/// Represents the response from executing a 3DS decision rule.
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct ThreeDsDecisionRuleExecuteResponse {
    /// The decision made by the 3DS decision rule engine.
    #[schema(value_type = ThreeDSDecision)]
    pub decision: common_types::three_ds_decision_rule_engine::ThreeDSDecision,
}

impl common_utils::events::ApiEventMetric for ThreeDsDecisionRuleExecuteRequest {
    fn get_api_event_type(&self) -> Option<common_utils::events::ApiEventsType> {
        Some(common_utils::events::ApiEventsType::ThreeDsDecisionRule)
    }
}

impl common_utils::events::ApiEventMetric for ThreeDsDecisionRuleExecuteResponse {
    fn get_api_event_type(&self) -> Option<common_utils::events::ApiEventsType> {
        Some(common_utils::events::ApiEventsType::ThreeDsDecisionRule)
    }
}


pub struct PaymentMethodIntentConfirm {
    /// The unique identifier of the customer.
    #[schema(value_type = Option<String>, max_length = 64, min_length = 1, example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")]
    pub customer_id: Option<id_type::CustomerId>,

    /// Payment method data to be passed
    pub payment_method_data: PaymentMethodCreateData,

    /// The type of payment method use for the payment.
    #[schema(value_type = PaymentMethod,example = "card")]
    pub payment_method_type: api_enums::PaymentMethod,

    /// This is a sub-category of payment method.
    #[schema(value_type = PaymentMethodType,example = "credit")]
    pub payment_method_subtype: api_enums::PaymentMethodType,
}


/// Constructs a new SMTP client
    pub async fn create(conf: &EmailSettings, smtp_config: SmtpServerConfig) -> Self {
        Self {
            sender: conf.sender_email.clone(),
            smtp_config: smtp_config.clone(),
        }
    }


impl<T: DatabaseStore> RouterStore<T> {
    pub async fn from_config(
        db_conf: T::Config,
        tenant_config: &dyn config::TenantConfig,
        encryption_key: StrongSecret<Vec<u8>>,
        cache_store: Arc<RedisStore>,
        inmemory_cache_stream: &str,
    ) -> error_stack::Result<Self, StorageError> {
        let db_store = T::new(db_conf, tenant_config, false).await?;
        let redis_conn = cache_store.redis_conn.clone();
        let cache_store = Arc::new(RedisStore {
            redis_conn: Arc::new(RedisConnectionPool::clone(
                &redis_conn,
                tenant_config.get_redis_key_prefix(),
            )),
        });
        cache_store
            .redis_conn
            .subscribe(inmemory_cache_stream)
            .await
            .change_context(StorageError::InitializationError)
            .attach_printable("Failed to subscribe to inmemory cache stream")?;

        Ok(Self {
            db_store,
            cache_store,
            master_encryption_key: encryption_key,
            request_id: None,
        })
    }

    pub async fn cache_store(
        cache_conf: &redis_interface::RedisSettings,
        cache_error_signal: tokio::sync::oneshot::Sender<()>,
    ) -> error_stack::Result<Arc<RedisStore>, StorageError> {
        let cache_store = RedisStore::new(cache_conf)
            .await
            .change_context(StorageError::InitializationError)
            .attach_printable("Failed to create cache store")?;
        cache_store.set_error_callback(cache_error_signal);
        Ok(Arc::new(cache_store))
    }

    pub fn master_key(&self) -> &StrongSecret<Vec<u8>> {
        &self.master_encryption_key
    }

    pub async fn call_database<D, R, M>(
        &self,
        state: &KeyManagerState,
        key_store: &MerchantKeyStore,
        execute_query: R,
    ) -> error_stack::Result<D, StorageError>
    where
        D: Debug + Sync + Conversion,
        R: futures::Future<Output = error_stack::Result<M, diesel_models::errors::DatabaseError>>
            + Send,
        M: ReverseConversion<D>,
    {
        execute_query
            .await
            .map_err(|error| {
                let new_err = diesel_error_to_data_error(*error.current_context());
                error.change_context(new_err)
            })?
            .convert(
                state,
                key_store.key.get_inner(),
                key_store.merchant_id.clone().into(),
            )
            .await
            .change_context(StorageError::DecryptionError)
    }

    pub async fn find_optional_resource<D, R, M>(
        &self,
        state: &KeyManagerState,
        key_store: &MerchantKeyStore,
        execute_query_fut: R,
    ) -> error_stack::Result<Option<D>, StorageError>
    where
        D: Debug + Sync + Conversion,
        R: futures::Future<
                Output = error_stack::Result<Option<M>, diesel_models::errors::DatabaseError>,
            > + Send,
        M: ReverseConversion<D>,
    {
        match execute_query_fut.await.map_err(|error| {
            let new_err = diesel_error_to_data_error(*error.current_context());
            error.change_context(new_err)
        })? {
            Some(resource) => Ok(Some(
                resource
                    .convert(
                        state,
                        key_store.key.get_inner(),
                        key_store.merchant_id.clone().into(),
                    )
                    .await
                    .change_context(StorageError::DecryptionError)?,
            )),
            None => Ok(None),
        }
    }

    pub async fn find_resources<D, R, M>(
        &self,
        state: &KeyManagerState,
        key_store: &MerchantKeyStore,
        execute_query: R,
    ) -> error_stack::Result<Vec<D>, StorageError>
    where
        D: Debug + Sync + Conversion,
        R: futures::Future<
                Output = error_stack::Result<Vec<M>, diesel_models::errors::DatabaseError>,
            > + Send,
        M: ReverseConversion<D>,
    {
        let resource_futures = execute_query
            .await
            .map_err(|error| {
                let new_err = diesel_error_to_data_error(*error.current_context());
                error.change_context(new_err)
            })?
            .into_iter()
            .map(|resource| async {
                resource
                    .convert(
                        state,
                        key_store.key.get_inner(),
                        key_store.merchant_id.clone().into(),
                    )
                    .await
                    .change_context(StorageError::DecryptionError)
            })
            .collect::<Vec<_>>();

        let resources = futures::future::try_join_all(resource_futures).await?;

        Ok(resources)
    }

    /// # Panics
    ///
    /// Will panic if `CONNECTOR_AUTH_FILE_PATH` is not set
    pub async fn test_store(
        db_conf: T::Config,
        tenant_config: &dyn config::TenantConfig,
        cache_conf: &redis_interface::RedisSettings,
        encryption_key: StrongSecret<Vec<u8>>,
    ) -> error_stack::Result<Self, StorageError> {
        // TODO: create an error enum and return proper error here
        let db_store = T::new(db_conf, tenant_config, true).await?;
        let cache_store = RedisStore::new(cache_conf)
            .await
            .change_context(StorageError::InitializationError)
            .attach_printable("failed to create redis cache")?;
        Ok(Self {
            db_store,
            cache_store: Arc::new(cache_store),
            master_encryption_key: encryption_key,
            request_id: None,
        })
    }
}


pub fn mk_crud_locker_request(
    locker: &settings::Locker,
    path: &str,
    req: api::TokenizePayloadEncrypted,
    tenant_id: id_type::TenantId,
    request_id: Option<RequestId>,
) -> CustomResult<services::Request, errors::VaultError> {
    let mut url = locker.basilisk_host.to_owned();
    url.push_str(path);
    let mut request = services::Request::new(services::Method::Post, &url);
    request.add_default_headers();
    request.add_header(headers::CONTENT_TYPE, "application/json".into());
    request.add_header(
        headers::X_TENANT_ID,
        tenant_id.get_string_repr().to_owned().into(),
    );
    if let Some(req_id) = request_id {
        request.add_header(
            headers::X_REQUEST_ID,
            req_id.as_hyphenated().to_string().into(),
        );
    }

    request.set_body(RequestContent::Json(Box::new(req)));
    Ok(request)
}


pub struct CustomerId {
    id: String,
}


pub struct JpmorganPaymentMethodType {
    card: JpmorganCard,
}


pub fn get_flow(&self) -> UserFlow {
        self.next_flow
    }


pub async fn check_if_already_exists_in_db(&self, state: SessionState) -> UserResult<()> {
        if state
            .store
            .get_merchant_key_store_by_merchant_id(
                &(&state).into(),
                &self.get_merchant_id(),
                &state.store.get_master_key().to_vec().into(),
            )
            .await
            .is_ok()
        {
            return Err(UserErrors::MerchantAccountCreationError(format!(
                "Merchant with {:?} already exists",
                self.get_merchant_id()
            ))
            .into());
        }
        Ok(())
    }


pub struct PaymentLinkConfigRequest {
    /// custom theme for the payment link
    #[schema(value_type = Option<String>, max_length = 255, example = "#4E6ADD")]
    pub theme: Option<String>,
    /// merchant display logo
    #[schema(value_type = Option<String>, max_length = 255, example = "https://i.pinimg.com/736x/4d/83/5c/4d835ca8aafbbb15f84d07d926fda473.jpg")]
    pub logo: Option<String>,
    /// Custom merchant name for payment link
    #[schema(value_type = Option<String>, max_length = 255, example = "hyperswitch")]
    pub seller_name: Option<String>,
    /// Custom layout for sdk
    #[schema(value_type = Option<String>, max_length = 255, example = "accordion")]
    pub sdk_layout: Option<String>,
    /// Display only the sdk for payment link
    #[schema(default = false, example = true)]
    pub display_sdk_only: Option<bool>,
    /// Enable saved payment method option for payment link
    #[schema(default = false, example = true)]
    pub enabled_saved_payment_method: Option<bool>,
    /// Hide card nickname field option for payment link
    #[schema(default = false, example = true)]
    pub hide_card_nickname_field: Option<bool>,
    /// Show card form by default for payment link
    #[schema(default = true, example = true)]
    pub show_card_form_by_default: Option<bool>,
    /// Dynamic details related to merchant to be rendered in payment link
    pub transaction_details: Option<Vec<PaymentLinkTransactionDetails>>,
    /// Configurations for the background image for details section
    pub background_image: Option<PaymentLinkBackgroundImageConfig>,
    /// Custom layout for details section
    #[schema(value_type = Option<PaymentLinkDetailsLayout>, example = "layout1")]
    pub details_layout: Option<api_enums::PaymentLinkDetailsLayout>,
    /// Text for payment link's handle confirm button
    pub payment_button_text: Option<String>,
    /// Text for customizing message for card terms
    pub custom_message_for_card_terms: Option<String>,
    /// Custom background colour for payment link's handle confirm button
    pub payment_button_colour: Option<String>,
    /// Skip the status screen after payment completion
    pub skip_status_screen: Option<bool>,
    /// Custom text colour for payment link's handle confirm button
    pub payment_button_text_colour: Option<String>,
    /// Custom background colour for the payment link
    pub background_colour: Option<String>,
    /// SDK configuration rules
    pub sdk_ui_rules: Option<HashMap<String, HashMap<String, String>>>,
    /// Payment link configuration rules
    pub payment_link_ui_rules: Option<HashMap<String, HashMap<String, String>>>,
    /// Flag to enable the button only when the payment form is ready for submission
    pub enable_button_only_on_form_ready: Option<bool>,
    /// Optional header for the SDK's payment form
    pub payment_form_header_text: Option<String>,
    /// Label type in the SDK's payment form
    #[schema(value_type = Option<PaymentLinkSdkLabelType>, example = "floating")]
    pub payment_form_label_type: Option<api_enums::PaymentLinkSdkLabelType>,
    /// Boolean for controlling whether or not to show the explicit consent for storing cards
    #[schema(value_type = Option<PaymentLinkShowSdkTerms>, example = "always")]
    pub show_card_terms: Option<api_enums::PaymentLinkShowSdkTerms>,
    /// Boolean to control payment button text for setup mandate calls
    pub is_setup_mandate_flow: Option<bool>,
    /// Hex color for the CVC icon during error state
    pub color_icon_card_cvc_error: Option<String>,
}


impl MerchantConnectorValidator {
    fn parse_comma_separated_ids(
        ids_string: &str,
    ) -> Result<Vec<common_utils::id_type::MerchantConnectorAccountId>, errors::ApiErrorResponse>
    {
        // Estimate capacity based on comma count
        let capacity = ids_string.matches(',').count() + 1;
        let mut result = Vec::with_capacity(capacity);

        for id in ids_string.split(',') {
            let trimmed_id = id.trim();
            if !trimmed_id.is_empty() {
                let mca_id =
                    common_utils::id_type::MerchantConnectorAccountId::wrap(trimmed_id.to_string())
                        .map_err(|_| errors::ApiErrorResponse::InvalidRequestData {
                            message: format!("Invalid merchant_connector_account_id: {trimmed_id}"),
                        })?;
                result.push(mca_id);
            }
        }

        Ok(result)
    }

    fn validate_form_csv_conflicts(
        records: &[pm_api::PaymentMethodRecord],
        form_has_single_id: bool,
        form_has_multiple_ids: bool,
    ) -> Result<(), errors::ApiErrorResponse> {
        if form_has_single_id {
            // If form has merchant_connector_id, CSV records should not have merchant_connector_ids
            for (index, record) in records.iter().enumerate() {
                if record.merchant_connector_ids.is_some() {
                    return Err(errors::ApiErrorResponse::InvalidRequestData {
                        message: format!(
                            "Record at line {} has merchant_connector_ids but form has merchant_connector_id. Only one should be provided",
                            index + 1
                        ),
                    });
                }
            }
        }

        if form_has_multiple_ids {
            // If form has merchant_connector_ids, CSV records should not have merchant_connector_id
            for (index, record) in records.iter().enumerate() {
                if record.merchant_connector_id.is_some() {
                    return Err(errors::ApiErrorResponse::InvalidRequestData {
                        message: format!(
                            "Record at line {} has merchant_connector_id but form has merchant_connector_ids. Only one should be provided",
                            index + 1
                        ),
                    });
                }
            }
        }

        Ok(())
    }
}


impl Responder {
        let flow = AnalyticsFlow::GeneratePaymentReport;
        Box::pin(api::server_wrap(
            flow,
            state.clone(),
            &req,
            json_payload.into_inner(),
            |state, (auth, user_id): auth::AuthenticationDataWithUserId, payload, _| async move {
                let user = UserInterface::find_user_by_id(&*state.global_store, &user_id)
                    .await
                    .change_context(AnalyticsError::UnknownError)?;

                let user_email = UserEmail::from_pii_email(user.email)
                    .change_context(AnalyticsError::UnknownError)?
                    .get_secret();
                let org_id = auth.merchant_account.get_org_id();
                let merchant_id = auth.merchant_account.get_id();
                let profile_id = auth
                    .profile_id
                    .ok_or(report!(UserErrors::JwtProfileIdMissing))
                    .change_context(AnalyticsError::AccessForbiddenError)?;
                let lambda_req = GenerateReportRequest {
                    request: payload,
                    merchant_id: Some(merchant_id.clone()),
                    auth: AuthInfo::ProfileLevel {
                        org_id: org_id.clone(),
                        merchant_id: merchant_id.clone(),
                        profile_ids: vec![profile_id.clone()],
                    },
                    email: user_email,
                };

                let json_bytes =
                    serde_json::to_vec(&lambda_req).map_err(|_| AnalyticsError::UnknownError)?;
                invoke_lambda(
                    &state.conf.report_download_config.payment_function,
                    &state.conf.report_download_config.region,
                    &json_bytes,
                )
                .await
                .map(ApplicationResponse::Json)
            },
            &auth::JWTAuth {
                permission: Permission::ProfileReportRead,
            },
            api_locking::LockAction::NotApplicable,
        ))
        .await
    }


pub async fn check_payout_eligibility(
    state: &SessionState,
    merchant_context: &domain::MerchantContext,
    connector_data: &api::ConnectorData,
    payout_data: &mut PayoutData,
) -> RouterResult<()> {
    // 1. Form Router data
    let router_data = core_utils::construct_payout_router_data(
        state,
        connector_data,
        merchant_context,
        payout_data,
    )
    .await?;

    // 2. Fetch connector integration details
    let connector_integration: services::BoxedPayoutConnectorIntegrationInterface<
        api::PoEligibility,
        types::PayoutsData,
        types::PayoutsResponseData,
    > = connector_data.connector.get_connector_integration();

    // 3. Call connector service
    let router_data_resp = services::execute_connector_processing_step(
        state,
        connector_integration,
        &router_data,
        payments::CallConnectorAction::Trigger,
        None,
        None,
    )
    .await
    .to_payout_failed_response()?;

    // 4. Process data returned by the connector
    let db = &*state.store;
    match router_data_resp.response {
        Ok(payout_response_data) => {
            let payout_attempt = &payout_data.payout_attempt;
            let status = payout_response_data
                .status
                .unwrap_or(payout_attempt.status.to_owned());
            let updated_payout_attempt = storage::PayoutAttemptUpdate::StatusUpdate {
                connector_payout_id: payout_response_data.connector_payout_id,
                status,
                error_code: None,
                error_message: None,
                is_eligible: payout_response_data.payout_eligible,
                unified_code: None,
                unified_message: None,
            };
            payout_data.payout_attempt = db
                .update_payout_attempt(
                    payout_attempt,
                    updated_payout_attempt,
                    &payout_data.payouts,
                    merchant_context.get_merchant_account().storage_scheme,
                )
                .await
                .change_context(errors::ApiErrorResponse::InternalServerError)
                .attach_printable("Error updating payout_attempt in db")?;
            payout_data.payouts = db
                .update_payout(
                    &payout_data.payouts,
                    storage::PayoutsUpdate::StatusUpdate { status },
                    &payout_data.payout_attempt,
                    merchant_context.get_merchant_account().storage_scheme,
                )
                .await
                .change_context(errors::ApiErrorResponse::InternalServerError)
                .attach_printable("Error updating payouts in db")?;
            if helpers::is_payout_err_state(status) {
                return Err(report!(errors::ApiErrorResponse::PayoutFailed {
                    data: Some(
                        serde_json::json!({"payout_status": status.to_string(), "error_message": payout_data.payout_attempt.error_message.as_ref(), "error_code": payout_data.payout_attempt.error_code.as_ref()})
                    ),
                }));
            }
        }
        Err(err) => {
            let status = storage_enums::PayoutStatus::Failed;
            let (error_code, error_message) = (Some(err.code), Some(err.message));
            let (unified_code, unified_message) = helpers::get_gsm_record(
                state,
                error_code.clone(),
                error_message.clone(),
                payout_data.payout_attempt.connector.clone(),
                consts::PAYOUT_FLOW_STR,
            )
            .await
            .map_or(
                (
                    Some(crate::consts::DEFAULT_UNIFIED_ERROR_CODE.to_string()),
                    Some(crate::consts::DEFAULT_UNIFIED_ERROR_MESSAGE.to_string()),
                ),
                |gsm| (gsm.unified_code, gsm.unified_message),
            );
            let updated_payout_attempt = storage::PayoutAttemptUpdate::StatusUpdate {
                connector_payout_id: payout_data.payout_attempt.connector_payout_id.to_owned(),
                status,
                error_code,
                error_message,
                is_eligible: Some(false),
                unified_code: unified_code
                    .map(UnifiedCode::try_from)
                    .transpose()
                    .change_context(errors::ApiErrorResponse::InvalidDataValue {
                        field_name: "unified_code",
                    })?,
                unified_message: unified_message
                    .map(UnifiedMessage::try_from)
                    .transpose()
                    .change_context(errors::ApiErrorResponse::InvalidDataValue {
                        field_name: "unified_message",
                    })?,
            };
            payout_data.payout_attempt = db
                .update_payout_attempt(
                    &payout_data.payout_attempt,
                    updated_payout_attempt,
                    &payout_data.payouts,
                    merchant_context.get_merchant_account().storage_scheme,
                )
                .await
                .change_context(errors::ApiErrorResponse::InternalServerError)
                .attach_printable("Error updating payout_attempt in db")?;
            payout_data.payouts = db
                .update_payout(
                    &payout_data.payouts,
                    storage::PayoutsUpdate::StatusUpdate { status },
                    &payout_data.payout_attempt,
                    merchant_context.get_merchant_account().storage_scheme,
                )
                .await
                .change_context(errors::ApiErrorResponse::InternalServerError)
                .attach_printable("Error updating payouts in db")?;
        }
    };

    Ok(())
}


pub struct NovalnetErrorResponse {
    pub status_code: u64,
    pub code: String,
    pub message: String,
    pub reason: Option<String>,
}