pub fn apply_changeset(self, source: Profile) -> Profile {
        let Self {
            profile_name,
            modified_at,
            return_url,
            enable_payment_response_hash,
            payment_response_hash_key,
            redirect_to_merchant_with_http_post,
            webhook_details,
            metadata,
            routing_algorithm,
            intent_fulfillment_time,
            frm_routing_algorithm,
            payout_routing_algorithm,
            is_recon_enabled,
            applepay_verified_domains,
            payment_link_config,
            session_expiry,
            authentication_connector_details,
            payout_link_config,
            is_extended_card_info_enabled,
            extended_card_info_config,
            is_connector_agnostic_mit_enabled,
            use_billing_as_payment_method_billing,
            collect_shipping_details_from_wallet_connector,
            collect_billing_details_from_wallet_connector,
            outgoing_webhook_custom_http_headers,
            always_collect_billing_details_from_wallet_connector,
            always_collect_shipping_details_from_wallet_connector,
            tax_connector_id,
            is_tax_connector_enabled,
            dynamic_routing_algorithm,
            is_network_tokenization_enabled,
            is_auto_retries_enabled,
            max_auto_retries_enabled,
            always_request_extended_authorization,
            is_click_to_pay_enabled,
            authentication_product_ids,
            card_testing_guard_config,
            card_testing_secret_key,
            is_clear_pan_retries_enabled,
            force_3ds_challenge,
            is_debit_routing_enabled,
            merchant_business_country,
            is_iframe_redirection_enabled,
            is_pre_network_tokenization_enabled,
            three_ds_decision_rule_algorithm,
            acquirer_config_map,
            merchant_category_code,
            merchant_country_code,
            dispute_polling_interval,
            is_manual_retry_enabled,
        } = self;
        Profile {
            profile_id: source.profile_id,
            merchant_id: source.merchant_id,
            profile_name: profile_name.unwrap_or(source.profile_name),
            created_at: source.created_at,
            modified_at,
            return_url: return_url.or(source.return_url),
            enable_payment_response_hash: enable_payment_response_hash
                .unwrap_or(source.enable_payment_response_hash),
            payment_response_hash_key: payment_response_hash_key
                .or(source.payment_response_hash_key),
            redirect_to_merchant_with_http_post: redirect_to_merchant_with_http_post
                .unwrap_or(source.redirect_to_merchant_with_http_post),
            webhook_details: webhook_details.or(source.webhook_details),
            metadata: metadata.or(source.metadata),
            routing_algorithm: routing_algorithm.or(source.routing_algorithm),
            intent_fulfillment_time: intent_fulfillment_time.or(source.intent_fulfillment_time),
            frm_routing_algorithm: frm_routing_algorithm.or(source.frm_routing_algorithm),
            payout_routing_algorithm: payout_routing_algorithm.or(source.payout_routing_algorithm),
            is_recon_enabled: is_recon_enabled.unwrap_or(source.is_recon_enabled),
            applepay_verified_domains: applepay_verified_domains
                .or(source.applepay_verified_domains),
            payment_link_config: payment_link_config.or(source.payment_link_config),
            session_expiry: session_expiry.or(source.session_expiry),
            authentication_connector_details: authentication_connector_details
                .or(source.authentication_connector_details),
            payout_link_config: payout_link_config.or(source.payout_link_config),
            is_extended_card_info_enabled: is_extended_card_info_enabled
                .or(source.is_extended_card_info_enabled),
            is_connector_agnostic_mit_enabled: is_connector_agnostic_mit_enabled
                .or(source.is_connector_agnostic_mit_enabled),
            extended_card_info_config: extended_card_info_config
                .or(source.extended_card_info_config),
            use_billing_as_payment_method_billing: use_billing_as_payment_method_billing
                .or(source.use_billing_as_payment_method_billing),
            collect_shipping_details_from_wallet_connector:
                collect_shipping_details_from_wallet_connector
                    .or(source.collect_shipping_details_from_wallet_connector),
            collect_billing_details_from_wallet_connector:
                collect_billing_details_from_wallet_connector
                    .or(source.collect_billing_details_from_wallet_connector),
            outgoing_webhook_custom_http_headers: outgoing_webhook_custom_http_headers
                .or(source.outgoing_webhook_custom_http_headers),
            always_collect_billing_details_from_wallet_connector:
                always_collect_billing_details_from_wallet_connector
                    .or(source.always_collect_billing_details_from_wallet_connector),
            always_collect_shipping_details_from_wallet_connector:
                always_collect_shipping_details_from_wallet_connector
                    .or(source.always_collect_shipping_details_from_wallet_connector),
            tax_connector_id: tax_connector_id.or(source.tax_connector_id),
            is_tax_connector_enabled: is_tax_connector_enabled.or(source.is_tax_connector_enabled),
            version: source.version,
            dynamic_routing_algorithm: dynamic_routing_algorithm
                .or(source.dynamic_routing_algorithm),
            is_network_tokenization_enabled: is_network_tokenization_enabled
                .unwrap_or(source.is_network_tokenization_enabled),
            is_auto_retries_enabled: is_auto_retries_enabled.or(source.is_auto_retries_enabled),
            max_auto_retries_enabled: max_auto_retries_enabled.or(source.max_auto_retries_enabled),
            always_request_extended_authorization: always_request_extended_authorization
                .or(source.always_request_extended_authorization),
            is_click_to_pay_enabled: is_click_to_pay_enabled
                .unwrap_or(source.is_click_to_pay_enabled),
            authentication_product_ids: authentication_product_ids
                .or(source.authentication_product_ids),
            card_testing_guard_config: card_testing_guard_config
                .or(source.card_testing_guard_config),
            card_testing_secret_key,
            is_clear_pan_retries_enabled: is_clear_pan_retries_enabled
                .unwrap_or(source.is_clear_pan_retries_enabled),
            force_3ds_challenge,
            id: source.id,
            is_debit_routing_enabled: is_debit_routing_enabled
                .unwrap_or(source.is_debit_routing_enabled),
            merchant_business_country: merchant_business_country
                .or(source.merchant_business_country),
            is_iframe_redirection_enabled: is_iframe_redirection_enabled
                .or(source.is_iframe_redirection_enabled),
            is_pre_network_tokenization_enabled: is_pre_network_tokenization_enabled
                .or(source.is_pre_network_tokenization_enabled),
            three_ds_decision_rule_algorithm: three_ds_decision_rule_algorithm
                .or(source.three_ds_decision_rule_algorithm),
            acquirer_config_map: acquirer_config_map.or(source.acquirer_config_map),
            merchant_category_code: merchant_category_code.or(source.merchant_category_code),
            merchant_country_code: merchant_country_code.or(source.merchant_country_code),
            dispute_polling_interval: dispute_polling_interval.or(source.dispute_polling_interval),
            is_manual_retry_enabled: is_manual_retry_enabled.or(source.is_manual_retry_enabled),
        }
    }


impl super::behaviour::Conversion for UserKeyStore {
    type DstType = diesel_models::user_key_store::UserKeyStore;
    type NewDstType = diesel_models::user_key_store::UserKeyStoreNew;

    async fn convert(self) -> CustomResult<Self::DstType, ValidationError> {
        Ok(diesel_models::user_key_store::UserKeyStore {
            key: self.key.into(),
            user_id: self.user_id,
            created_at: self.created_at,
        })
    }

    async fn convert_back(
        state: &KeyManagerState,
        item: Self::DstType,
        key: &Secret<Vec<u8>>,
        _key_manager_identifier: Identifier,
    ) -> CustomResult<Self, ValidationError>
    where
        Self: Sized,
    {
        let identifier = Identifier::User(item.user_id.clone());
        Ok(Self {
            key: crypto_operation(
                state,
                type_name!(Self::DstType),
                CryptoOperation::Decrypt(item.key),
                identifier,
                key.peek(),
            )
            .await
            .and_then(|val| val.try_into_operation())
            .change_context(ValidationError::InvalidValue {
                message: "Failed while decrypting customer data".to_string(),
            })?,
            user_id: item.user_id,
            created_at: item.created_at,
        })
    }

    async fn construct_new(self) -> CustomResult<Self::NewDstType, ValidationError> {
        Ok(diesel_models::user_key_store::UserKeyStoreNew {
            user_id: self.user_id,
            key: self.key.into(),
            created_at: date_time::now(),
        })
    }
}

impl super::behaviour::Conversion for for UserKeyStore


File: crates/hyperswitch_connectors/src/connectors/nmi/transformers.rs
 Public functions: 2
 Public structs: 31

use api_models::webhooks::IncomingWebhookEvent;
use cards::CardNumber;
use common_enums::{AttemptStatus, AuthenticationType, CountryAlpha2, Currency, RefundStatus};
use common_utils::{errors::CustomResult, ext_traits::XmlExt, pii::Email, types::FloatMajorUnit};
use error_stack::{report, Report, ResultExt};
use hyperswitch_domain_models::{
    payment_method_data::{
        ApplePayWalletData, Card, GooglePayWalletData, PaymentMethodData, WalletData,
    },
    router_data::{ConnectorAuthType, ErrorResponse, RouterData},
    router_flow_types::{
        Authorize, Capture, CompleteAuthorize, Execute, PreProcessing, RSync, SetupMandate, Void,
    },
    router_request_types::{
        CompleteAuthorizeData, PaymentsAuthorizeData, PaymentsCaptureData,
        PaymentsPreProcessingData, ResponseId,
    },
    router_response_types::{PaymentsResponseData, RedirectForm, RefundsResponseData},
    types::{
        PaymentsAuthorizeRouterData, PaymentsCancelRouterData, PaymentsCaptureRouterData,
        PaymentsCompleteAuthorizeRouterData, PaymentsPreProcessingRouterData,
        PaymentsSyncRouterData, RefundSyncRouterData, RefundsRouterData, SetupMandateRouterData,
    },
};
use hyperswitch_interfaces::errors::ConnectorError;
use masking::{ExposeInterface, PeekInterface, Secret};
use serde::{Deserialize, Serialize};

use crate::{
    types::{PaymentsResponseRouterData, RefundsResponseRouterData, ResponseRouterData},
    utils::{
        get_unimplemented_payment_method_error_message, to_currency_base_unit_asf64,
        AddressDetailsData as _, CardData as _, PaymentsAuthorizeRequestData,
        PaymentsCompleteAuthorizeRequestData as _, RouterData as _,
    },
};

type Error = Report<ConnectorError>;

#[derive(Debug, Serialize)]
#[serde(rename_all = "lowercase")]
pub enum TransactionType {
    Auth,
    Capture,
    Refund,
    Sale,
    Validate,
    Void,
}

pub struct NmiAuthType {
    pub(super) api_key: Secret<String>,
    pub(super) public_key: Option<Secret<String>>,
}

impl TryFrom<&ConnectorAuthType> for NmiAuthType {
    type Error = Error;
    fn try_from(auth_type: &ConnectorAuthType) -> Result<Self, Self::Error> {
        match auth_type {
            ConnectorAuthType::HeaderKey { api_key } => Ok(Self {
                api_key: api_key.to_owned(),
                public_key: None,
            }),
            ConnectorAuthType::BodyKey { api_key, key1 } => Ok(Self {
                api_key: api_key.to_owned(),
                public_key: Some(key1.to_owned()),
            }),
            _ => Err(ConnectorError::FailedToObtainAuthType.into()),
        }
    }
}

#[derive(Debug, Serialize)]
pub struct NmiRouterData<T> {
    pub amount: FloatMajorUnit,
    pub router_data: T,
}

impl<T> From<(FloatMajorUnit, T)> for NmiRouterData<T> {
    fn from((amount, router_data): (FloatMajorUnit, T)) -> Self {
        Self {
            amount,
            router_data,
        }
    }
}

#[derive(Debug, Serialize)]
pub struct NmiVaultRequest {
    security_key: Secret<String>,
    ccnumber: CardNumber,
    ccexp: Secret<String>,
    cvv: Secret<String>,
    first_name: Secret<String>,
    last_name: Secret<String>,
    address1: Option<Secret<String>>,
    address2: Option<Secret<String>>,
    city: Option<String>,
    state: Option<Secret<String>>,
    zip: Option<Secret<String>>,
    country: Option<CountryAlpha2>,
    customer_vault: CustomerAction,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum CustomerAction {
    AddCustomer,
    UpdateCustomer,
}

impl TryFrom<&PaymentsPreProcessingRouterData> for NmiVaultRequest {
    type Error = Error;
    fn try_from(item: &PaymentsPreProcessingRouterData) -> Result<Self, Self::Error> {
        let auth_type: NmiAuthType = (&item.connector_auth_type).try_into()?;
        let (ccnumber, ccexp, cvv) = get_card_details(item.request.payment_method_data.clone())?;
        let billing_details = item.get_billing_address()?;
        let first_name = billing_details.get_first_name()?;

        Ok(Self {
            security_key: auth_type.api_key,
            ccnumber,
            ccexp,
            cvv,
            first_name: first_name.clone(),
            last_name: billing_details
                .get_last_name()
                .unwrap_or(first_name)
                .clone(),
            address1: billing_details.line1.clone(),
            address2: billing_details.line2.clone(),
            city: billing_details.city.clone(),
            state: billing_details.state.clone(),
            country: billing_details.country,
            zip: billing_details.zip.clone(),
            customer_vault: CustomerAction::AddCustomer,
        })
    }
}

fn get_card_details(
    payment_method_data: Option<PaymentMethodData>,
) -> CustomResult<(CardNumber, Secret<String>, Secret<String>), ConnectorError> {
    match payment_method_data {
        Some(PaymentMethodData::Card(ref card_details)) => Ok((
            card_details.card_number.clone(),
            card_details.get_card_expiry_month_year_2_digit_with_delimiter("".to_string())?,
            card_details.card_cvc.clone(),
        )),
        _ => Err(
            ConnectorError::NotImplemented(get_unimplemented_payment_method_error_message("Nmi"))
                .into(),
        ),
    }
}

#[derive(Debug, Deserialize, Serialize)]
pub struct NmiVaultResponse {
    pub response: Response,
    pub responsetext: String,
    pub customer_vault_id: Option<Secret<String>>,
    pub response_code: String,
    pub transactionid: String,
}

impl
    TryFrom<
        ResponseRouterData<
            PreProcessing,
            NmiVaultResponse,
            PaymentsPreProcessingData,
            PaymentsResponseData,
        >,
    > for PaymentsPreProcessingRouterData
{
    type Error = Error;
    fn try_from(
        item: ResponseRouterData<
            PreProcessing,
            NmiVaultResponse,
            PaymentsPreProcessingData,
            PaymentsResponseData,
        >,
    ) -> Result<Self, Self::Error> {
        let auth_type: NmiAuthType = (&item.data.connector_auth_type).try_into()?;
        let amount_data = item
            .data
            .request
            .amount
            .ok_or(ConnectorError::MissingRequiredField {
                field_name: "amount",
            })?;
        let currency_data =
            item.data
                .request
                .currency
                .ok_or(ConnectorError::MissingRequiredField {
                    field_name: "currency",
                })?;
        let (response, status) = match item.response.response {
            Response::Approved => (
                Ok(PaymentsResponseData::TransactionResponse {
                    resource_id: ResponseId::NoResponseId,
                    redirection_data: Box::new(Some(RedirectForm::Nmi {
                        amount: to_currency_base_unit_asf64(amount_data, currency_data.to_owned())?
                            .to_string(),
                        currency: currency_data,
                        customer_vault_id: item
                            .response
                            .customer_vault_id
                            .ok_or(ConnectorError::MissingRequiredField {
                                field_name: "customer_vault_id",
                            })?
                            .peek()
                            .to_string(),
                        public_key: auth_type.public_key.ok_or(
                            ConnectorError::InvalidConnectorConfig {
                                config: "public_key",
                            },
                        )?,
                        order_id: item.data.connector_request_reference_id.clone(),
                    })),
                    mandate_reference: Box::new(None),
                    connector_metadata: None,
                    network_txn_id: None,
                    connector_response_reference_id: Some(item.response.transactionid),
                    incremental_authorization_allowed: None,
                    charges: None,
                }),
                AttemptStatus::AuthenticationPending,
            ),
            Response::Declined | Response::Error => (
                Err(ErrorResponse {
                    code: item.response.response_code,
                    message: item.response.responsetext.to_owned(),
                    reason: Some(item.response.responsetext),
                    status_code: item.http_code,
                    attempt_status: None,
                    connector_transaction_id: Some(item.response.transactionid),
                    network_advice_code: None,
                    network_decline_code: None,
                    network_error_message: None,
                    connector_metadata: None,
                }),
                AttemptStatus::Failure,
            ),
        };
        Ok(Self {
            status,
            response,
            ..item.data
        })
    }
}

#[derive(Debug, Serialize)]
pub struct NmiCompleteRequest {
    amount: FloatMajorUnit,
    #[serde(rename = "type")]
    transaction_type: TransactionType,
    security_key: Secret<String>,
    orderid: Option<String>,
    customer_vault_id: Secret<String>,
    email: Option<Email>,
    cardholder_auth: Option<String>,
    cavv: Option<String>,
    xid: Option<String>,
    eci: Option<String>,
    cvv: Secret<String>,
    three_ds_version: Option<String>,
    directory_server_id: Option<Secret<String>>,
}

#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
#[serde(untagged)]
pub enum NmiRedirectResponse {
    NmiRedirectResponseData(NmiRedirectResponseData),
    NmiErrorResponseData(NmiErrorResponseData),
}

#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct NmiErrorResponseData {
    pub code: String,
    pub message: String,
}

#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct NmiRedirectResponseData {
    cavv: Option<String>,
    xid: Option<String>,
    eci: Option<String>,
    card_holder_auth: Option<String>,
    three_ds_version: Option<String>,
    order_id: Option<String>,
    directory_server_id: Option<Secret<String>>,
    customer_vault_id: Secret<String>,
}

impl TryFrom<&NmiRouterData<&PaymentsCompleteAuthorizeRouterData>> for NmiCompleteRequest {
    type Error = Error;
    fn try_from(
        item: &NmiRouterData<&PaymentsCompleteAuthorizeRouterData>,
    ) -> Result<Self, Self::Error> {
        let transaction_type = match item.router_data.request.is_auto_capture()? {
            true => TransactionType::Sale,
            false => TransactionType::Auth,
        };
        let auth_type: NmiAuthType = (&item.router_data.connector_auth_type).try_into()?;
        let payload_data = item
            .router_data
            .request
            .get_redirect_response_payload()?
            .expose();

        let three_ds_data: NmiRedirectResponseData = serde_json::from_value(payload_data)
            .change_context(ConnectorError::MissingConnectorRedirectionPayload {
                field_name: "three_ds_data",
            })?;

        let (_, _, cvv) = get_card_details(item.router_data.request.payment_method_data.clone())?;

        Ok(Self {
            amount: item.amount,
            transaction_type,
            security_key: auth_type.api_key,
            orderid: three_ds_data.order_id,
            customer_vault_id: three_ds_data.customer_vault_id,
            email: item.router_data.request.email.clone(),
            cvv,
            cardholder_auth: three_ds_data.card_holder_auth,
            cavv: three_ds_data.cavv,
            xid: three_ds_data.xid,
            eci: three_ds_data.eci,
            three_ds_version: three_ds_data.three_ds_version,
            directory_server_id: three_ds_data.directory_server_id,
        })
    }
}

#[derive(Debug, Deserialize, Serialize)]
pub struct NmiCompleteResponse {
    pub response: Response,
    pub responsetext: String,
    pub authcode: Option<String>,
    pub transactionid: String,
    pub avsresponse: Option<String>,
    pub cvvresponse: Option<String>,
    pub orderid: String,
    pub response_code: String,
    customer_vault_id: Option<Secret<String>>,
}

impl
    TryFrom<
        ResponseRouterData<
            CompleteAuthorize,
            NmiCompleteResponse,
            CompleteAuthorizeData,
            PaymentsResponseData,
        >,
    > for PaymentsCompleteAuthorizeRouterData
{
    type Error = Error;
    fn try_from(
        item: ResponseRouterData<
            CompleteAuthorize,
            NmiCompleteResponse,
            CompleteAuthorizeData,
            PaymentsResponseData,
        >,
    ) -> Result<Self, Self::Error> {
        let (response, status) = match item.response.response {
            Response::Approved => (
                Ok(PaymentsResponseData::TransactionResponse {
                    resource_id: ResponseId::ConnectorTransactionId(item.response.transactionid),
                    redirection_data: Box::new(None),
                    mandate_reference: match item.response.customer_vault_id {
                        Some(vault_id) => Box::new(Some(
                            hyperswitch_domain_models::router_response_types::MandateReference {
                                connector_mandate_id: Some(vault_id.expose()),
                                payment_method_id: None,
                                mandate_metadata: None,
                                connector_mandate_request_reference_id: None,
                            },
                        )),
                        None => Box::new(None),
                    },
                    connector_metadata: None,
                    network_txn_id: None,
                    connector_response_reference_id: Some(item.response.orderid),
                    incremental_authorization_allowed: None,
                    charges: None,
                }),
                if item.data.request.is_auto_capture()? {
                    AttemptStatus::Charged
                } else {
                    AttemptStatus::Authorized
                },
            ),
            Response::Declined | Response::Error => (
                Err(get_nmi_error_response(item.response, item.http_code)),
                AttemptStatus::Failure,
            ),
        };
        Ok(Self {
            status,
            response,
            ..item.data
        })
    }
}

fn get_nmi_error_response(response: NmiCompleteResponse, http_code: u16) -> ErrorResponse {
    ErrorResponse {
        code: response.response_code,
        message: response.responsetext.to_owned(),
        reason: Some(response.responsetext),
        status_code: http_code,
        attempt_status: None,
        connector_transaction_id: Some(response.transactionid),
        network_advice_code: None,
        network_decline_code: None,
        network_error_message: None,
        connector_metadata: None,
    }
}

#[derive(Debug, Serialize)]
pub struct NmiValidateRequest {
    #[serde(rename = "type")]
    transaction_type: TransactionType,
    security_key: Secret<String>,
    ccnumber: CardNumber,
    ccexp: Secret<String>,
    cvv: Secret<String>,
    orderid: String,
    customer_vault: CustomerAction,
}

#[derive(Debug, Serialize)]
pub struct NmiPaymentsRequest {
    #[serde(rename = "type")]
    transaction_type: TransactionType,
    amount: FloatMajorUnit,
    security_key: Secret<String>,
    currency: Currency,
    #[serde(flatten)]
    payment_method: PaymentMethod,
    #[serde(flatten)]
    merchant_defined_field: Option<NmiMerchantDefinedField>,
    orderid: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    customer_vault: Option<CustomerAction>,
}

#[derive(Debug, Serialize)]
pub struct NmiMerchantDefinedField {
    #[serde(flatten)]
    inner: std::collections::BTreeMap<String, Secret<String>>,
}

impl NmiMerchantDefinedField {
    pub fn new(metadata: &serde_json::Value) -> Self {
        let metadata_as_string = metadata.to_string();
        let hash_map: std::collections::BTreeMap<String, serde_json::Value> =
            serde_json::from_str(&metadata_as_string).unwrap_or(std::collections::BTreeMap::new());
        let inner = hash_map
            .into_iter()
            .enumerate()
            .map(|(index, (hs_key, hs_value))| {
                let nmi_key = format!("merchant_defined_field_{}", index + 1);
                let nmi_value = format!("{hs_key}={hs_value}");
                (nmi_key, Secret::new(nmi_value))
            })
            .collect();
        Self { inner }
    }
}

#[derive(Debug, Serialize)]
#[serde(untagged)]
pub enum PaymentMethod {
    CardNonThreeDs(Box<CardData>),
    CardThreeDs(Box<CardThreeDsData>),
    GPay(Box<GooglePayData>),
    ApplePay(Box<ApplePayData>),
    MandatePayment(Box<MandatePayment>),
}

#[derive(Debug, Serialize)]
pub struct MandatePayment {
    customer_vault_id: Secret<String>,
}

#[derive(Debug, Serialize)]
pub struct CardData {
    ccnumber: CardNumber,
    ccexp: Secret<String>,
    cvv: Secret<String>,
}

#[derive(Debug, Serialize)]
pub struct CardThreeDsData {
    ccnumber: CardNumber,
    ccexp: Secret<String>,
    email: Option<Email>,
    cardholder_auth: Option<String>,
    cavv: Option<Secret<String>>,
    eci: Option<String>,
    cvv: Secret<String>,
    three_ds_version: Option<String>,
    directory_server_id: Option<Secret<String>>,
}

#[derive(Debug, Serialize)]
pub struct GooglePayData {
    googlepay_payment_data: Secret<String>,
}

#[derive(Debug, Serialize)]
pub struct ApplePayData {
    applepay_payment_data: Secret<String>,
}

impl TryFrom<&NmiRouterData<&PaymentsAuthorizeRouterData>> for NmiPaymentsRequest {
    type Error = Error;
    fn try_from(item: &NmiRouterData<&PaymentsAuthorizeRouterData>) -> Result<Self, Self::Error> {
        let transaction_type = match item.router_data.request.is_auto_capture()? {
            true => TransactionType::Sale,
            false => TransactionType::Auth,
        };
        let auth_type: NmiAuthType = (&item.router_data.connector_auth_type).try_into()?;
        let amount = item.amount;

        match item
            .router_data
            .request
            .mandate_id
            .clone()
            .and_then(|mandate_ids| mandate_ids.mandate_reference_id)
        {
            Some(api_models::payments::MandateReferenceId::ConnectorMandateId(
                connector_mandate_id,
            )) => Ok(Self {
                transaction_type,
                security_key: auth_type.api_key,
                amount,
                currency: item.router_data.request.currency,
                payment_method: PaymentMethod::MandatePayment(Box::new(MandatePayment {
                    customer_vault_id: Secret::new(
                        connector_mandate_id
                            .get_connector_mandate_id()
                            .ok_or(ConnectorError::MissingConnectorMandateID)?,
                    ),
                })),
                merchant_defined_field: item
                    .router_data
                    .request
                    .metadata
                    .as_ref()
                    .map(NmiMerchantDefinedField::new),
                orderid: item.router_data.connector_request_reference_id.clone(),
                customer_vault: None,
            }),
            Some(api_models::payments::MandateReferenceId::NetworkMandateId(_))
            | Some(api_models::payments::MandateReferenceId::NetworkTokenWithNTI(_)) => {
                Err(ConnectorError::NotImplemented(
                    get_unimplemented_payment_method_error_message("nmi"),
                ))?
            }
            None => {
                let payment_method = PaymentMethod::try_from((
                    &item.router_data.request.payment_method_data,
                    Some(item.router_data),
                ))?;

                Ok(Self {
                    transaction_type,
                    security_key: auth_type.api_key,
                    amount,
                    currency: item.router_data.request.currency,
                    payment_method,
                    merchant_defined_field: item
                        .router_data
                        .request
                        .metadata
                        .as_ref()
                        .map(NmiMerchantDefinedField::new),
                    orderid: item.router_data.connector_request_reference_id.clone(),
                    customer_vault: item
                        .router_data
                        .request
                        .is_mandate_payment()
                        .then_some(CustomerAction::AddCustomer),
                })
            }
        }
    }
}

impl TryFrom<(&PaymentMethodData, Option<&PaymentsAuthorizeRouterData>)> for PaymentMethod {
    type Error = Error;
    fn try_from(
        item: (&PaymentMethodData, Option<&PaymentsAuthorizeRouterData>),
    ) -> Result<Self, Self::Error> {
        let (payment_method_data, router_data) = item;
        match payment_method_data {
            PaymentMethodData::Card(ref card) => match router_data {
                Some(data) => match data.auth_type {
                    AuthenticationType::NoThreeDs => Ok(Self::try_from(card)?),
                    AuthenticationType::ThreeDs => Ok(Self::try_from((card, &data.request))?),
                },
                None => Ok(Self::try_from(card)?),
            },
            PaymentMethodData::Wallet(ref wallet_type) => match wallet_type {
                WalletData::GooglePay(ref googlepay_data) => Ok(Self::try_from(googlepay_data)?),
                WalletData::ApplePay(ref applepay_data) => Ok(Self::try_from(applepay_data)?),
                WalletData::AliPayQr(_)
                | WalletData::AliPayRedirect(_)
                | WalletData::AliPayHkRedirect(_)
                | WalletData::AmazonPayRedirect(_)
                | WalletData::Paysera(_)
                | WalletData::Skrill(_)
                | WalletData::BluecodeRedirect {}
                | WalletData::MomoRedirect(_)
                | WalletData::KakaoPayRedirect(_)
                | WalletData::GoPayRedirect(_)
                | WalletData::GcashRedirect(_)
                | WalletData::ApplePayRedirect(_)
                | WalletData::ApplePayThirdPartySdk(_)
                | WalletData::DanaRedirect {}
                | WalletData::GooglePayRedirect(_)
                | WalletData::GooglePayThirdPartySdk(_)
                | WalletData::MbWayRedirect(_)
                | WalletData::MobilePayRedirect(_)
                | WalletData::PaypalRedirect(_)
                | WalletData::PaypalSdk(_)
                | WalletData::Paze(_)
                | WalletData::SamsungPay(_)
                | WalletData::AmazonPay(_)
                | WalletData::TwintRedirect {}
                | WalletData::VippsRedirect {}
                | WalletData::TouchNGoRedirect(_)
                | WalletData::WeChatPayRedirect(_)
                | WalletData::WeChatPayQr(_)
                | WalletData::CashappQr(_)
                | WalletData::SwishQr(_)
                | WalletData::Mifinity(_)
                | WalletData::RevolutPay(_) => Err(report!(ConnectorError::NotImplemented(
                    get_unimplemented_payment_method_error_message("nmi"),
                ))),
            },
            PaymentMethodData::CardRedirect(_)
            | PaymentMethodData::PayLater(_)
            | PaymentMethodData::BankRedirect(_)
            | PaymentMethodData::BankDebit(_)
            | PaymentMethodData::BankTransfer(_)
            | PaymentMethodData::Crypto(_)
            | PaymentMethodData::MandatePayment
            | PaymentMethodData::Reward
            | PaymentMethodData::RealTimePayment(_)
            | PaymentMethodData::MobilePayment(_)
            | PaymentMethodData::Upi(_)
            | PaymentMethodData::Voucher(_)
            | PaymentMethodData::GiftCard(_)
            | PaymentMethodData::OpenBanking(_)
            | PaymentMethodData::CardToken(_)
            | PaymentMethodData::NetworkToken(_)
            | PaymentMethodData::CardDetailsForNetworkTransactionId(_) => Err(
                ConnectorError::NotImplemented(get_unimplemented_payment_method_error_message(
                    "nmi",
                ))
                .into(),
            ),
        }
    }
}

impl TryFrom<(&Card, &PaymentsAuthorizeData)> for PaymentMethod {
    type Error = Error;
    fn try_from(val: (&Card, &PaymentsAuthorizeData)) -> Result<Self, Self::Error> {
        let (card_data, item) = val;
        let auth_data = &item.get_authentication_data()?;
        let ccexp = card_data.get_card_expiry_month_year_2_digit_with_delimiter("".to_string())?;

        let card_3ds_details = CardThreeDsData {
            ccnumber: card_data.card_number.clone(),
            ccexp,
            cvv: card_data.card_cvc.clone(),
            email: item.email.clone(),
            cavv: Some(auth_data.cavv.clone()),
            eci: auth_data.eci.clone(),
            cardholder_auth: None,
            three_ds_version: auth_data
                .message_version
                .clone()
                .map(|version| version.to_string()),
            directory_server_id: auth_data
                .threeds_server_transaction_id
                .clone()
                .map(Secret::new),
        };

        Ok(Self::CardThreeDs(Box::new(card_3ds_details)))
    }
}

impl TryFrom<&Card> for PaymentMethod {
    type Error = Error;
    fn try_from(card: &Card) -> Result<Self, Self::Error> {
        let ccexp = card.get_card_expiry_month_year_2_digit_with_delimiter("".to_string())?;
        let card = CardData {
            ccnumber: card.card_number.clone(),
            ccexp,
            cvv: card.card_cvc.clone(),
        };
        Ok(Self::CardNonThreeDs(Box::new(card)))
    }
}

impl TryFrom<&GooglePayWalletData> for PaymentMethod {
    type Error = Report<ConnectorError>;
    fn try_from(wallet_data: &GooglePayWalletData) -> Result<Self, Self::Error> {
        let gpay_data = GooglePayData {
            googlepay_payment_data: Secret::new(
                wallet_data
                    .tokenization_data
                    .get_encrypted_google_pay_token()
                    .change_context(ConnectorError::MissingRequiredField {
                        field_name: "gpay wallet_token",
                    })?
                    .clone(),
            ),
        };
        Ok(Self::GPay(Box::new(gpay_data)))
    }
}

impl TryFrom<&ApplePayWalletData> for PaymentMethod {
    type Error = Error;
    fn try_from(apple_pay_wallet_data: &ApplePayWalletData) -> Result<Self, Self::Error> {
        let apple_pay_encrypted_data = apple_pay_wallet_data
            .payment_data
            .get_encrypted_apple_pay_payment_data_mandatory()
            .change_context(ConnectorError::MissingRequiredField {
                field_name: "Apple pay encrypted data",
            })?;

        let apple_pay_data = ApplePayData {
            applepay_payment_data: Secret::new(apple_pay_encrypted_data.clone()),
        };
        Ok(Self::ApplePay(Box::new(apple_pay_data)))
    }
}

impl TryFrom<&SetupMandateRouterData> for NmiValidateRequest {
    type Error = Error;
    fn try_from(item: &SetupMandateRouterData) -> Result<Self, Self::Error> {
        match item.request.amount {
            Some(amount) if amount > 0 => Err(ConnectorError::FlowNotSupported {
                flow: "Setup Mandate with non zero amount".to_string(),
                connector: "NMI".to_string(),
            }
            .into()),
            _ => {
                if let PaymentMethodData::Card(card_details) = &item.request.payment_method_data {
                    let auth_type: NmiAuthType = (&item.connector_auth_type).try_into()?;
                    Ok(Self {
                        transaction_type: TransactionType::Validate,
                        security_key: auth_type.api_key,
                        ccnumber: card_details.card_number.clone(),
                        ccexp: card_details
                            .get_card_expiry_month_year_2_digit_with_delimiter("".to_string())?,
                        cvv: card_details.card_cvc.clone(),
                        orderid: item.connector_request_reference_id.clone(),
                        customer_vault: CustomerAction::AddCustomer,
                    })
                } else {
                    Err(ConnectorError::NotImplemented(
                        get_unimplemented_payment_method_error_message("Nmi"),
                    )
                    .into())
                }
            }
        }
    }
}

#[derive(Debug, Serialize)]
pub struct NmiSyncRequest {
    pub order_id: String,
    pub security_key: Secret<String>,
}

impl TryFrom<&PaymentsSyncRouterData> for NmiSyncRequest {
    type Error = Error;
    fn try_from(item: &PaymentsSyncRouterData) -> Result<Self, Self::Error> {
        let auth = NmiAuthType::try_from(&item.connector_auth_type)?;
        Ok(Self {
            security_key: auth.api_key,
            order_id: item.attempt_id.clone(),
        })
    }
}

#[derive(Debug, Serialize)]
pub struct NmiCaptureRequest {
    #[serde(rename = "type")]
    pub transaction_type: TransactionType,
    pub security_key: Secret<String>,
    pub transactionid: String,
    pub amount: Option<FloatMajorUnit>,
}

impl TryFrom<&NmiRouterData<&PaymentsCaptureRouterData>> for NmiCaptureRequest {
    type Error = Error;
    fn try_from(item: &NmiRouterData<&PaymentsCaptureRouterData>) -> Result<Self, Self::Error> {
        let auth = NmiAuthType::try_from(&item.router_data.connector_auth_type)?;
        Ok(Self {
            transaction_type: TransactionType::Capture,
            security_key: auth.api_key,
            transactionid: item.router_data.request.connector_transaction_id.clone(),
            amount: Some(item.amount),
        })
    }
}

impl
    TryFrom<
        ResponseRouterData<Capture, StandardResponse, PaymentsCaptureData, PaymentsResponseData>,
    > for RouterData<Capture, PaymentsCaptureData, PaymentsResponseData>
{
    type Error = Error;
    fn try_from(
        item: ResponseRouterData<
            Capture,
            StandardResponse,
            PaymentsCaptureData,
            PaymentsResponseData,
        >,
    ) -> Result<Self, Self::Error> {
        let (response, status) = match item.response.response {
            Response::Approved => (
                Ok(PaymentsResponseData::TransactionResponse {
                    resource_id: ResponseId::ConnectorTransactionId(
                        item.response.transactionid.to_owned(),
                    ),
                    redirection_data: Box::new(None),
                    mandate_reference: Box::new(None),
                    connector_metadata: None,
                    network_txn_id: None,
                    connector_response_reference_id: Some(item.response.orderid),
                    incremental_authorization_allowed: None,
                    charges: None,
                }),
                AttemptStatus::Charged,
            ),
            Response::Declined | Response::Error => (
                Err(get_standard_error_response(item.response, item.http_code)),
                AttemptStatus::CaptureFailed,
            ),
        };
        Ok(Self {
            status,
            response,
            ..item.data
        })
    }
}

#[derive(Debug, Serialize)]
pub struct NmiCancelRequest {
    #[serde(rename = "type")]
    pub transaction_type: TransactionType,
    pub security_key: Secret<String>,
    pub transactionid: String,
    pub void_reason: NmiVoidReason,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "snake_case")]
pub enum NmiVoidReason {
    Fraud,
    UserCancel,
    IccRejected,
    IccCardRemoved,
    IccNoConfirmation,
    PosTimeout,
}

impl TryFrom<&PaymentsCancelRouterData> for NmiCancelRequest {
    type Error = Error;
    fn try_from(item: &PaymentsCancelRouterData) -> Result<Self, Self::Error> {
        let auth = NmiAuthType::try_from(&item.connector_auth_type)?;
        match &item.request.cancellation_reason {
            Some(cancellation_reason) => {
                let void_reason: NmiVoidReason = serde_json::from_str(&format!("\"{cancellation_reason}\"", ))
                    .map_err(|_| ConnectorError::NotSupported {
                        message: format!("Json deserialise error: unknown variant `{cancellation_reason}` expected to be one of `fraud`, `user_cancel`, `icc_rejected`,  `icc_card_removed`, `icc_no_confirmation`, `pos_timeout`. This cancellation_reason"),
                        connector: "nmi"
                    })?;
                Ok(Self {
                    transaction_type: TransactionType::Void,
                    security_key: auth.api_key,
                    transactionid: item.request.connector_transaction_id.clone(),
                    void_reason,
                })
            }
            None => Err(ConnectorError::MissingRequiredField {
                field_name: "cancellation_reason",
            }
            .into()),
        }
    }
}

#[derive(Debug, Deserialize, Serialize)]
pub enum Response {
    #[serde(alias = "1")]
    Approved,
    #[serde(alias = "2")]
    Declined,
    #[serde(alias = "3")]
    Error,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct StandardResponse {
    pub response: Response,
    pub responsetext: String,
    pub authcode: Option<String>,
    pub transactionid: String,
    pub avsresponse: Option<String>,
    pub cvvresponse: Option<String>,
    pub orderid: String,
    pub response_code: String,
    pub customer_vault_id: Option<Secret<String>>,
}

impl<T> TryFrom<ResponseRouterData<SetupMandate, StandardResponse, T, PaymentsResponseData>>
    for RouterData<SetupMandate, T, PaymentsResponseData>
{
    type Error = Error;
    fn try_from(
        item: ResponseRouterData<SetupMandate, StandardResponse, T, PaymentsResponseData>,
    ) -> Result<Self, Self::Error> {
        let (response, status) = match item.response.response {
            Response::Approved => (
                Ok(PaymentsResponseData::TransactionResponse {
                    resource_id: ResponseId::ConnectorTransactionId(
                        item.response.transactionid.clone(),
                    ),
                    redirection_data: Box::new(None),
                    mandate_reference: match item.response.customer_vault_id {
                        Some(vault_id) => Box::new(Some(
                            hyperswitch_domain_models::router_response_types::MandateReference {
                                connector_mandate_id: Some(vault_id.expose()),
                                payment_method_id: None,
                                mandate_metadata: None,
                                connector_mandate_request_reference_id: None,
                            },
                        )),
                        None => Box::new(None),
                    },
                    connector_metadata: None,
                    network_txn_id: None,
                    connector_response_reference_id: Some(item.response.orderid),
                    incremental_authorization_allowed: None,
                    charges: None,
                }),
                AttemptStatus::Charged,
            ),
            Response::Declined | Response::Error => (
                Err(get_standard_error_response(item.response, item.http_code)),
                AttemptStatus::Failure,
            ),
        };
        Ok(Self {
            status,
            response,
            ..item.data
        })
    }
}
fn get_standard_error_response(response: StandardResponse, http_code: u16) -> ErrorResponse {
    ErrorResponse {
        code: response.response_code,
        message: response.responsetext.to_owned(),
        reason: Some(response.responsetext),
        status_code: http_code,
        attempt_status: None,
        connector_transaction_id: Some(response.transactionid),
        network_advice_code: None,
        network_decline_code: None,
        network_error_message: None,
        connector_metadata: None,
    }
}

impl TryFrom<PaymentsResponseRouterData<StandardResponse>>
    for RouterData<Authorize, PaymentsAuthorizeData, PaymentsResponseData>
{
    type Error = Error;
    fn try_from(
        item: ResponseRouterData<
            Authorize,
            StandardResponse,
            PaymentsAuthorizeData,
            PaymentsResponseData,
        >,
    ) -> Result<Self, Self::Error> {
        let (response, status) = match item.response.response {
            Response::Approved => (
                Ok(PaymentsResponseData::TransactionResponse {
                    resource_id: ResponseId::ConnectorTransactionId(
                        item.response.transactionid.clone(),
                    ),
                    redirection_data: Box::new(None),
                    mandate_reference: match item.response.customer_vault_id {
                        Some(vault_id) => Box::new(Some(
                            hyperswitch_domain_models::router_response_types::MandateReference {
                                connector_mandate_id: Some(vault_id.expose()),
                                payment_method_id: None,
                                mandate_metadata: None,
                                connector_mandate_request_reference_id: None,
                            },
                        )),
                        None => Box::new(None),
                    },
                    connector_metadata: None,
                    network_txn_id: None,
                    connector_response_reference_id: Some(item.response.orderid),
                    incremental_authorization_allowed: None,
                    charges: None,
                }),
                if item.data.request.is_auto_capture()? {
                    AttemptStatus::Charged
                } else {
                    AttemptStatus::Authorized
                },
            ),
            Response::Declined | Response::Error => (
                Err(get_standard_error_response(item.response, item.http_code)),
                AttemptStatus::Failure,
            ),
        };
        Ok(Self {
            status,
            response,
            ..item.data
        })
    }
}

impl<T> TryFrom<ResponseRouterData<Void, StandardResponse, T, PaymentsResponseData>>
    for RouterData<Void, T, PaymentsResponseData>
{
    type Error = Error;
    fn try_from(
        item: ResponseRouterData<Void, StandardResponse, T, PaymentsResponseData>,
    ) -> Result<Self, Self::Error> {
        let (response, status) = match item.response.response {
            Response::Approved => (
                Ok(PaymentsResponseData::TransactionResponse {
                    resource_id: ResponseId::ConnectorTransactionId(
                        item.response.transactionid.clone(),
                    ),
                    redirection_data: Box::new(None),
                    mandate_reference: Box::new(None),
                    connector_metadata: None,
                    network_txn_id: None,
                    connector_response_reference_id: Some(item.response.orderid),
                    incremental_authorization_allowed: None,
                    charges: None,
                }),
                AttemptStatus::VoidInitiated,
            ),
            Response::Declined | Response::Error => (
                Err(get_standard_error_response(item.response, item.http_code)),
                AttemptStatus::VoidFailed,
            ),
        };
        Ok(Self {
            status,
            response,
            ..item.data
        })
    }
}

#[derive(Debug, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum NmiStatus {
    Abandoned,
    Cancelled,
    Pendingsettlement,
    Pending,
    Failed,
    Complete,
    InProgress,
    Unknown,
}

impl<F, T> TryFrom<ResponseRouterData<F, SyncResponse, T, PaymentsResponseData>>
    for RouterData<F, T, PaymentsResponseData>
{
    type Error = Error;
    fn try_from(
        item: ResponseRouterData<F, SyncResponse, T, PaymentsResponseData>,
    ) -> Result<Self, Self::Error> {
        match item.response.transaction {
            Some(trn) => Ok(Self {


impl PaymentSession for Payone {}


impl CeleroTransactionResponseData {
    pub fn get_mandate_reference(&self) -> Box<Option<MandateReference>> {
        if self.payment_method_id.is_some() {
            Box::new(Some(MandateReference {
                connector_mandate_id: None,
                payment_method_id: self.payment_method_id.clone(),
                mandate_metadata: None,
                connector_mandate_request_reference_id: Some(self.id.clone()),
            }))
        } else {
            Box::new(None)
        }
    }
}


pub struct InternationalBankAccount {
    iban: Secret<String>,
    account_holder_name: Secret<String>,
}


impl api::PaymentAuthorize for Wellsfargopayout {}

impl api::PaymentAuthorize for for Wellsfargopayout


pub struct CardInfoBuilder<S: State> {
    state: std::marker::PhantomData<S>,
    pub card_info: Option<card_info_models::CardInfo>,
}


pub async fn payouts_core(
    state: &SessionState,
    merchant_context: &domain::MerchantContext,
    payout_data: &mut PayoutData,
    routing_algorithm: Option<serde_json::Value>,
    eligible_connectors: Option<Vec<api_enums::PayoutConnectors>>,
) -> RouterResult<()> {
    let payout_attempt = &payout_data.payout_attempt;

    // Form connector data
    let connector_call_type = get_connector_choice(
        state,
        merchant_context,
        payout_attempt.connector.clone(),
        routing_algorithm,
        payout_data,
        eligible_connectors,
    )
    .await?;

    // Call connector steps
    Box::pin(make_connector_decision(
        state,
        merchant_context,
        connector_call_type,
        payout_data,
    ))
    .await
}


OpenAPI Block Path: components.schemas.SuccessRateSpecificityLevel
{
  "type": "string",
  "enum": [
    "merchant",
    "global"
  ]
}


impl api::PaymentSession for Gocardless {}

impl api::PaymentSession for for Gocardless


OpenAPI Block Path: components.schemas.PaymentLinkDetailsLayout
{
  "type": "string",
  "enum": [
    "layout1",
    "layout2"
  ]
}


pub struct PaysafePaymentsSyncResponse {
    pub payments: Vec<PaysafePaymentsResponse>,
}


pub struct CybersourcePaymentsIncrementalAuthorizationResponse {
    status: CybersourceIncrementalAuthorizationStatus,
    error_information: Option<CybersourceErrorInformation>,
}


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


/// DecisionManagerRecord
pub struct DecisionManagerRecord {
    /// Name of the Decision Manager
    pub name: String,
    /// Program to be executed
    pub program: Program<ConditionalConfigs>,
    /// Created at timestamp
    pub created_at: i64,
}


pub struct ZenGooglePay {
    pub terminal_uuid: Option<String>,
    pub pay_wall_secret: Option<String>,
}


pub async fn files_create_core(
    state: SessionState,
    merchant_context: domain::MerchantContext,
    create_file_request: api::CreateFileRequest,
) -> RouterResponse<files::CreateFileResponse> {
    helpers::validate_file_upload(
        &state,
        merchant_context.clone(),
        create_file_request.clone(),
    )
    .await?;
    let file_id = common_utils::generate_id(consts::ID_LENGTH, "file");
    let file_key = format!(
        "{}/{}",
        merchant_context
            .get_merchant_account()
            .get_id()
            .get_string_repr(),
        file_id
    );
    let file_new: diesel_models::FileMetadataNew = diesel_models::file::FileMetadataNew {
        file_id: file_id.clone(),
        merchant_id: merchant_context.get_merchant_account().get_id().clone(),
        file_name: create_file_request.file_name.clone(),
        file_size: create_file_request.file_size,
        file_type: create_file_request.file_type.to_string(),
        provider_file_id: None,
        file_upload_provider: None,
        available: false,
        connector_label: None,
        profile_id: None,
        merchant_connector_id: None,
    };

    let file_metadata_object = state
        .store
        .insert_file_metadata(file_new)
        .await
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("Unable to insert file_metadata")?;
    let (provider_file_id, file_upload_provider, profile_id, merchant_connector_id) = Box::pin(
        helpers::upload_and_get_provider_provider_file_id_profile_id(
            &state,
            &merchant_context,
            &create_file_request,
            file_key.clone(),
        ),
    )
    .await?;

    // Update file metadata
    let update_file_metadata = diesel_models::file::FileMetadataUpdate::Update {
        provider_file_id: Some(provider_file_id),
        file_upload_provider: Some(file_upload_provider),
        available: true,
        profile_id,
        merchant_connector_id,
    };
    state
        .store
        .as_ref()
        .update_file_metadata(file_metadata_object, update_file_metadata)
        .await
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable_lazy(|| {
            format!("Unable to update file_metadata with file_id: {file_id}")
        })?;
    Ok(ApplicationResponse::Json(files::CreateFileResponse {
        file_id,
    }))
}


pub struct ReversalInformation {
    amount_details: Amount,
    reason: String,
}


pub async fn update_profile_active_algorithm_ref(
    db: &dyn StorageInterface,
    key_manager_state: &KeyManagerState,
    merchant_key_store: &domain::MerchantKeyStore,
    current_business_profile: domain::Profile,
    algorithm_id: routing_types::RoutingAlgorithmRef,
    transaction_type: &storage::enums::TransactionType,
) -> RouterResult<()> {
    let ref_val = algorithm_id
        .encode_to_value()
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("Failed to convert routing ref to value")?;

    let merchant_id = current_business_profile.merchant_id.clone();

    let profile_id = current_business_profile.get_id().to_owned();

    let (routing_algorithm, payout_routing_algorithm, three_ds_decision_rule_algorithm) =
        match transaction_type {
            storage::enums::TransactionType::Payment => (Some(ref_val), None, None),
            #[cfg(feature = "payouts")]
            storage::enums::TransactionType::Payout => (None, Some(ref_val), None),
            storage::enums::TransactionType::ThreeDsAuthentication => (None, None, Some(ref_val)),
        };

    let business_profile_update = domain::ProfileUpdate::RoutingAlgorithmUpdate {
        routing_algorithm,
        payout_routing_algorithm,
        three_ds_decision_rule_algorithm,
    };

    db.update_profile_by_profile_id(
        key_manager_state,
        merchant_key_store,
        current_business_profile,
        business_profile_update,
    )
    .await
    .change_context(errors::ApiErrorResponse::InternalServerError)
    .attach_printable("Failed to update routing algorithm ref in business profile")?;

    // Invalidate the routing cache for Payments and Payouts transaction types
    if !transaction_type.is_three_ds_authentication() {
        let routing_cache_key = cache::CacheKind::Routing(
            format!(
                "routing_config_{}_{}",
                merchant_id.get_string_repr(),
                profile_id.get_string_repr(),
            )
            .into(),
        );

        cache::redact_from_redis_and_publish(db.get_cache_store().as_ref(), [routing_cache_key])
            .await
            .change_context(errors::ApiErrorResponse::InternalServerError)
            .attach_printable("Failed to invalidate routing cache")?;
    }
    Ok(())
}


impl api::PaymentVoid for Bluecode {}


impl Responder {
    let flow = Flow::GetExtendedCardInfo;
    let payment_id = path.into_inner();

    Box::pin(api::server_wrap(
        flow,
        state,
        &req,
        payment_id,
        |state, auth: auth::AuthenticationData, payment_id, _| {
            let merchant_context = domain::MerchantContext::NormalMerchant(Box::new(
                domain::Context(auth.merchant_account, auth.key_store),
            ));
            payments::get_extended_card_info(
                state,
                merchant_context.get_merchant_account().get_id().to_owned(),
                payment_id,
            )
        },
        &auth::HeaderAuth(auth::ApiKeyAuth {
            is_connected_allowed: false,
            is_platform_allowed: true,
        }),
        api_locking::LockAction::NotApplicable,
    ))
    .await
}


pub struct BluesnapRouterData<T> {
    pub amount: StringMajorUnit,
    pub router_data: T,
}


pub struct RecoveryPaymentIntent {
    pub payment_id: id_type::GlobalPaymentId,
    pub status: common_enums::IntentStatus,
    pub feature_metadata: Option<api_payments::FeatureMetadata>,
    pub merchant_id: id_type::MerchantId,
    pub merchant_reference_id: Option<id_type::PaymentReferenceId>,
    pub invoice_amount: util_types::MinorUnit,
    pub invoice_currency: common_enums::Currency,
    pub created_at: Option<PrimitiveDateTime>,
    pub billing_address: Option<api_payments::Address>,
}


impl api::PaymentCapture for Stax {}


pub async fn insert_recovery_code_in_redis(state: &SessionState, user_id: &str) -> UserResult<()> {
    let redis_conn = super::get_redis_connection_for_global_tenant(state)?;
    let key = format!("{}{}", consts::user::REDIS_RECOVERY_CODE_PREFIX, user_id);
    redis_conn
        .set_key_with_expiry(
            &key.as_str().into(),
            common_utils::date_time::now_unix_timestamp(),
            state.conf.user.two_factor_auth_expiry_in_secs,
        )
        .await
        .change_context(UserErrors::InternalServerError)
}


pub fn validate(&self) -> Result<(), crate::core::errors::ApplicationError> {
        use common_utils::ext_traits::ConfigExt;

        use crate::core::errors::ApplicationError;

        common_utils::fp_utils::when(self.brokers.is_empty(), || {
            Err(ApplicationError::InvalidConfigurationValueError(
                "Kafka brokers must not be empty".into(),
            ))
        })?;

        common_utils::fp_utils::when(self.intent_analytics_topic.is_default_or_empty(), || {
            Err(ApplicationError::InvalidConfigurationValueError(
                "Kafka Intent Analytics topic must not be empty".into(),
            ))
        })?;

        common_utils::fp_utils::when(self.attempt_analytics_topic.is_default_or_empty(), || {
            Err(ApplicationError::InvalidConfigurationValueError(
                "Kafka Attempt Analytics topic must not be empty".into(),
            ))
        })?;

        common_utils::fp_utils::when(self.refund_analytics_topic.is_default_or_empty(), || {
            Err(ApplicationError::InvalidConfigurationValueError(
                "Kafka Refund Analytics topic must not be empty".into(),
            ))
        })?;

        common_utils::fp_utils::when(self.api_logs_topic.is_default_or_empty(), || {
            Err(ApplicationError::InvalidConfigurationValueError(
                "Kafka API event Analytics topic must not be empty".into(),
            ))
        })?;

        common_utils::fp_utils::when(self.connector_logs_topic.is_default_or_empty(), || {
            Err(ApplicationError::InvalidConfigurationValueError(
                "Kafka Connector Logs topic must not be empty".into(),
            ))
        })?;

        common_utils::fp_utils::when(
            self.outgoing_webhook_logs_topic.is_default_or_empty(),
            || {
                Err(ApplicationError::InvalidConfigurationValueError(
                    "Kafka Outgoing Webhook Logs topic must not be empty".into(),
                ))
            },
        )?;

        common_utils::fp_utils::when(self.dispute_analytics_topic.is_default_or_empty(), || {
            Err(ApplicationError::InvalidConfigurationValueError(
                "Kafka Dispute Logs topic must not be empty".into(),
            ))
        })?;

        common_utils::fp_utils::when(self.audit_events_topic.is_default_or_empty(), || {
            Err(ApplicationError::InvalidConfigurationValueError(
                "Kafka Audit Events topic must not be empty".into(),
            ))
        })?;

        #[cfg(feature = "payouts")]
        common_utils::fp_utils::when(self.payout_analytics_topic.is_default_or_empty(), || {
            Err(ApplicationError::InvalidConfigurationValueError(
                "Kafka Payout Analytics topic must not be empty".into(),
            ))
        })?;

        common_utils::fp_utils::when(self.consolidated_events_topic.is_default_or_empty(), || {
            Err(ApplicationError::InvalidConfigurationValueError(
                "Consolidated Events topic must not be empty".into(),
            ))
        })?;

        common_utils::fp_utils::when(
            self.authentication_analytics_topic.is_default_or_empty(),
            || {
                Err(ApplicationError::InvalidConfigurationValueError(
                    "Kafka Authentication Analytics topic must not be empty".into(),
                ))
            },
        )?;

        common_utils::fp_utils::when(self.routing_logs_topic.is_default_or_empty(), || {
            Err(ApplicationError::InvalidConfigurationValueError(
                "Kafka Routing Logs topic must not be empty".into(),
            ))
        })?;

        Ok(())
    }


/// Panics if `json_payload` array does not contain one `GetDisputeMetricRequest` element.
    pub async fn get_merchant_dispute_metrics(
        state: web::Data<AppState>,
        req: actix_web::HttpRequest,
        json_payload: web::Json<[GetDisputeMetricRequest; 1]>,
    ) -> impl Responder {
        // safety: This shouldn't panic owing to the data type
        #[allow(clippy::expect_used)]
        let payload = json_payload
            .into_inner()
            .to_vec()
            .pop()
            .expect("Couldn't get GetDisputeMetricRequest");
        let flow = AnalyticsFlow::GetDisputeMetrics;
        Box::pin(api::server_wrap(
            flow,
            state,
            &req,
            payload,
            |state, auth: AuthenticationData, req, _| async move {
                let org_id = auth.merchant_account.get_org_id();
                let merchant_id = auth.merchant_account.get_id();
                let auth: AuthInfo = AuthInfo::MerchantLevel {
                    org_id: org_id.clone(),
                    merchant_ids: vec![merchant_id.clone()],
                };
                analytics::disputes::get_metrics(&state.pool, &auth, req)
                    .await
                    .map(ApplicationResponse::Json)
            },
            &auth::JWTAuth {
                permission: Permission::MerchantAnalyticsRead,
            },
            api_locking::LockAction::NotApplicable,
        ))
        .await
    }


File: crates/router/src/routes/disputes/utils.rs
 Public functions: 2

use actix_multipart::{Field, Multipart};
use actix_web::web::Bytes;
use common_utils::{errors::CustomResult, ext_traits::StringExt, fp_utils};
use error_stack::ResultExt;
use futures::{StreamExt, TryStreamExt};

use crate::{
    core::{errors, files::helpers},
    types::api::{disputes, files},
    utils::OptionExt,
};

pub async fn parse_evidence_type(
    field: &mut Field,
) -> CustomResult<Option<disputes::EvidenceType>, errors::ApiErrorResponse> {
    let purpose = helpers::read_string(field).await;
    match purpose {
        Some(evidence_type) => Ok(Some(
            evidence_type
                .parse_enum("Evidence Type")
                .change_context(errors::ApiErrorResponse::InternalServerError)
                .attach_printable("Error parsing evidence type")?,
        )),
        _ => Ok(None),
    }
}

pub async fn get_attach_evidence_request(
    mut payload: Multipart,
) -> CustomResult<disputes::AttachEvidenceRequest, errors::ApiErrorResponse> {
    let mut option_evidence_type: Option<disputes::EvidenceType> = None;
    let mut dispute_id: Option<String> = None;

    let mut file_name: Option<String> = None;
    let mut file_content: Option<Vec<Bytes>> = None;

    while let Ok(Some(mut field)) = payload.try_next().await {
        let content_disposition = field.content_disposition();
        let field_name = content_disposition.get_name();
        // Parse the different parameters expected in the multipart request
        match field_name {
            Some("file") => {
                file_name = content_disposition.get_filename().map(String::from);
                //Collect the file content and throw error if something fails
                let mut file_data = Vec::new();
                let mut stream = field.into_stream();
                while let Some(chunk) = stream.next().await {
                    match chunk {
                        Ok(bytes) => file_data.push(bytes),
                        Err(err) => Err(errors::ApiErrorResponse::InternalServerError)
                            .attach_printable_lazy(|| format!("File parsing error: {err}"))?,
                    }
                }
                file_content = Some(file_data)
            }
            Some("dispute_id") => {
                dispute_id = helpers::read_string(&mut field).await;
            }
            Some("evidence_type") => {
                option_evidence_type = parse_evidence_type(&mut field).await?;
            }
            // Can ignore other params
            _ => (),
        }
    }
    let evidence_type = option_evidence_type.get_required_value("evidence_type")?;
    let file = file_content.get_required_value("file")?.concat().to_vec();
    //Get and validate file size
    let file_size = i32::try_from(file.len())
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("File size error")?;
    // Check if empty file and throw error
    fp_utils::when(file_size <= 0, || {
        Err(errors::ApiErrorResponse::MissingFile)
            .attach_printable("Missing / Invalid file in the request")
    })?;
    // Get file mime type using 'infer'
    let kind = infer::get(&file).ok_or(errors::ApiErrorResponse::MissingFileContentType)?;
    let file_type = kind
        .mime_type()
        .parse::<mime::Mime>()
        .change_context(errors::ApiErrorResponse::MissingFileContentType)
        .attach_printable("File content type error")?;
    let create_file_request = files::CreateFileRequest {
        file,
        file_name,
        file_size,
        file_type,
        purpose: files::FilePurpose::DisputeEvidence,
        dispute_id,
    };
    Ok(disputes::AttachEvidenceRequest {
        evidence_type,
        create_file_request,
    })
}


impl api::RefundSync for Forte {}


pub struct PaymentIntentListParams {
    pub offset: u32,
    pub starting_at: Option<PrimitiveDateTime>,
    pub ending_at: Option<PrimitiveDateTime>,
    pub amount_filter: Option<api_models::payments::AmountFilter>,
    pub connector: Option<Vec<api_models::enums::Connector>>,
    pub currency: Option<Vec<common_enums::Currency>>,
    pub status: Option<Vec<common_enums::IntentStatus>>,
    pub payment_method_type: Option<Vec<common_enums::PaymentMethod>>,
    pub payment_method_subtype: Option<Vec<common_enums::PaymentMethodType>>,
    pub authentication_type: Option<Vec<common_enums::AuthenticationType>>,
    pub merchant_connector_id: Option<Vec<id_type::MerchantConnectorAccountId>>,
    pub profile_id: Option<id_type::ProfileId>,
    pub customer_id: Option<id_type::GlobalCustomerId>,
    pub starting_after_id: Option<id_type::GlobalPaymentId>,
    pub ending_before_id: Option<id_type::GlobalPaymentId>,
    pub limit: Option<u32>,
    pub order: api_models::payments::Order,
    pub card_network: Option<Vec<common_enums::CardNetwork>>,
    pub merchant_order_reference_id: Option<String>,
    pub payment_id: Option<id_type::GlobalPaymentId>,
}


impl Responder {
    let flow = Flow::IncomingNetworkTokenWebhookReceive;

    Box::pin(api::server_wrap(
        flow.clone(),
        state,
        &req,
        (),
        |state, _: (), _, _| {
            webhooks::network_token_incoming_webhooks_wrapper::<W>(
                &flow,
                state.to_owned(),
                &req,
                body.clone(),
            )
        },
        &auth::NoAuth,
        api_locking::LockAction::NotApplicable,
    ))
    .await
}


impl api::RefundExecute for Boku {}


impl Organization {
    pub async fn find_by_org_id(
        conn: &PgPooledConn,
        org_id: id_type::OrganizationId,
    ) -> StorageResult<Self> {
        generics::generic_find_one::<<Self as HasTable>::Table, _, _>(
            conn,
            dsl_identifier.eq(org_id),
        )
        .await
    }

    pub async fn update_by_org_id(
        conn: &PgPooledConn,
        org_id: id_type::OrganizationId,
        update: OrganizationUpdate,
    ) -> StorageResult<Self> {
        generics::generic_update_with_unique_predicate_get_result::<
            <Self as HasTable>::Table,
            _,
            _,
            _,
        >(
            conn,
            dsl_identifier.eq(org_id),
            OrganizationUpdateInternal::from(update),
        )
        .await
    }
}


pub fn get_payout_connector_config(
        connector: PayoutConnectors,
    ) -> Result<Option<ConnectorTomlConfig>, String> {
        let connector_data = Self::new()?;
        match connector {
            PayoutConnectors::Adyen => Ok(connector_data.adyen_payout),
            PayoutConnectors::Adyenplatform => Ok(connector_data.adyenplatform_payout),
            PayoutConnectors::Cybersource => Ok(connector_data.cybersource_payout),
            PayoutConnectors::Ebanx => Ok(connector_data.ebanx_payout),
            PayoutConnectors::Nomupay => Ok(connector_data.nomupay_payout),
            PayoutConnectors::Payone => Ok(connector_data.payone_payout),
            PayoutConnectors::Paypal => Ok(connector_data.paypal_payout),
            PayoutConnectors::Stripe => Ok(connector_data.stripe_payout),
            PayoutConnectors::Wise => Ok(connector_data.wise_payout),
        }
    }


impl Hash for SdkEventMetricsBucketIdentifier {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.payment_method.hash(state);
        self.platform.hash(state);
        self.browser_name.hash(state);
        self.source.hash(state);
        self.component.hash(state);
        self.payment_experience.hash(state);
        self.time_bucket.hash(state);
    }
}

impl Hash for for SdkEventMetricsBucketIdentifier


pub struct BraintreeRedirectionResponse {
    pub authentication_response: String,
}


/// Paypal Ref - https://developer.paypal.com/docs/reports/reference/paypal-supported-currencies/
    pub fn to_currency_base_unit_with_zero_decimal_check(
        self,
        amount: i64,
    ) -> Result<String, TryFromIntError> {
        let amount_f64 = self.to_currency_base_unit_asf64(amount)?;
        if self.is_zero_decimal_currency() {
            Ok(amount_f64.to_string())
        } else {
            Ok(format!("{amount_f64:.2}"))
        }
    }


pub struct JpmorganCaptureRequest {
    capture_method: Option<CapMethod>,
    amount: MinorUnit,
    currency: Option<common_enums::Currency>,
}


pub async fn get_parent_info_for_role(
    state: SessionState,
    user_from_token: UserFromToken,
    role: role_api::GetRoleRequest,
) -> UserResponse<role_api::RoleInfoWithParents> {
    let role_info = roles::RoleInfo::from_role_id_org_id_tenant_id(
        &state,
        &role.role_id,
        &user_from_token.org_id,
        user_from_token
            .tenant_id
            .as_ref()
            .unwrap_or(&state.tenant.tenant_id),
    )
    .await
    .to_not_found_response(UserErrors::InvalidRoleId)?;

    if role_info.is_internal() {
        return Err(UserErrors::InvalidRoleId.into());
    }

    let parent_groups = ParentGroup::get_descriptions_for_groups(
        role_info.get_entity_type(),
        role_info.get_permission_groups().to_vec(),
    )
    .ok_or(UserErrors::InternalServerError)
    .attach_printable(format!(
        "No group descriptions found for role_id: {}",
        role.role_id
    ))?
    .into_iter()
    .map(|(parent_group, description)| role_api::ParentGroupInfo {
        name: parent_group.clone(),
        description,
        scopes: role_info
            .get_permission_groups()
            .iter()
            .filter_map(|group| (group.parent() == parent_group).then_some(group.scope()))
            // TODO: Remove this hashset conversion when merchant access
            // and organization access groups are removed
            .collect::<HashSet<_>>()
            .into_iter()
            .collect(),
    })
    .collect();

    Ok(ApplicationResponse::Json(role_api::RoleInfoWithParents {
        role_id: role.role_id,
        parent_groups,
        role_name: role_info.get_role_name().to_string(),
        role_scope: role_info.get_scope(),
    }))
}


pub struct StripeConnectPayoutCreateRequest {
    amount: i64,
    currency: Currency,
    destination: String,
    transfer_group: String,
}


pub async fn refunds_retrieve(
    state: web::Data<AppState>,
    req: HttpRequest,
    path: web::Path<String>,
    query_params: web::Query<api_models::refunds::RefundsRetrieveBody>,
) -> HttpResponse {
    let refund_request = refunds::RefundsRetrieveRequest {
        refund_id: path.into_inner(),
        force_sync: query_params.force_sync,
        merchant_connector_details: None,
    };
    let flow = match query_params.force_sync {
        Some(true) => Flow::RefundsRetrieveForceSync,
        _ => Flow::RefundsRetrieve,
    };

    tracing::Span::current().record("flow", flow.to_string());

    Box::pin(api::server_wrap(
        flow,
        state,
        &req,
        refund_request,
        |state, auth: auth::AuthenticationData, refund_request, _| {
            let merchant_context = domain::MerchantContext::NormalMerchant(Box::new(
                domain::Context(auth.merchant_account, auth.key_store),
            ));
            refund_response_wrapper(
                state,
                merchant_context,
                auth.profile_id,
                refund_request,
                refund_retrieve_core_with_refund_id,
            )
        },
        auth::auth_type(
            &auth::HeaderAuth(auth::ApiKeyAuth {
                is_connected_allowed: false,
                is_platform_allowed: false,
            }),
            &auth::JWTAuth {
                permission: Permission::ProfileRefundRead,
            },
            req.headers(),
        ),
        api_locking::LockAction::NotApplicable,
    ))
    .await
}


impl ProxyRecord {
    fn get_vault_id(&self) -> RouterResult<payment_methods::VaultId> {
        match self {
            Self::PaymentMethodRecord(payment_method) => payment_method
                .locker_id
                .clone()
                .get_required_value("vault_id")
                .change_context(errors::ApiErrorResponse::InternalServerError)
                .attach_printable("Locker id not present in Payment Method Entry"),
            Self::TokenizationRecord(tokenization_record) => Ok(
                payment_methods::VaultId::generate(tokenization_record.locker_id.clone()),
            ),
        }
    }

    fn get_customer_id(&self) -> id_type::GlobalCustomerId {
        match self {
            Self::PaymentMethodRecord(payment_method) => payment_method.customer_id.clone(),
            Self::TokenizationRecord(tokenization_record) => {
                tokenization_record.customer_id.clone()
            }
        }
    }

    pub async fn get_vault_data(
        &self,
        state: &SessionState,
        merchant_context: domain::MerchantContext,
    ) -> RouterResult<Value> {
        match self {
            Self::PaymentMethodRecord(_) => {
                let vault_resp = vault::retrieve_payment_method_from_vault_internal(
                    state,
                    &merchant_context,
                    &self.get_vault_id()?,
                    &self.get_customer_id(),
                )
                .await
                .change_context(errors::ApiErrorResponse::InternalServerError)
                .attach_printable("Error while fetching data from vault")?;

                Ok(vault_resp
                    .data
                    .encode_to_value()
                    .change_context(errors::ApiErrorResponse::InternalServerError)
                    .attach_printable("Failed to serialize vault data")?)
            }
            Self::TokenizationRecord(_) => {
                let vault_request = pm_types::VaultRetrieveRequest {
                    entity_id: self.get_customer_id(),
                    vault_id: self.get_vault_id()?,
                };

                let vault_data = vault::retrieve_value_from_vault(state, vault_request)
                    .await
                    .change_context(errors::ApiErrorResponse::InternalServerError)
                    .attach_printable("Failed to retrieve vault data")?;

                Ok(vault_data.get("data").cloned().unwrap_or(Value::Null))
            }
        }
    }
}


pub struct KlarnaRefundResponse {
    pub refund_id: String,
}


impl api::ExternalVault for Vgs {}


pub struct WalletDetails {
    pub data_descriptor: WalletMethod,
    pub data_value: Secret<String>,
}


pub struct KatapultPaymentsRequest {
    amount: StringMinorUnit,
    card: KatapultCard,
}


pub fn get_secret(self) -> Secret<String, pii::EmailStrategy> {
        (*self.0).clone()
    }


pub struct MerchantAccountCreateWithoutOrgId {
    /// Name of the Merchant Account, This will be used as a prefix to generate the id
    #[schema(value_type= String, max_length = 64, example = "NewAge Retailer")]
    pub merchant_name: Secret<common_utils::new_type::MerchantName>,

    /// Details about the merchant, contains phone and emails of primary and secondary contact person.
    pub merchant_details: Option<MerchantDetails>,

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

    #[schema(value_type = Option<MerchantProductType>)]
    pub product_type: Option<api_enums::MerchantProductType>,
}


OpenAPI Block Path: components.schemas.GiftCardData
{
  "oneOf": [
    {
      "type": "object",
      "required": [
        "givex"
      ],
      "properties": {
        "givex": {
          "$ref": "#/components/schemas/GiftCardDetails"
        }
      }
    },
    {
      "type": "object",
      "required": [
        "pay_safe_card"
      ],
      "properties": {
        "pay_safe_card": {
          "type": "object"
        }
      }
    },
    {
      "type": "object",
      "required": [
        "bhn_card_network"
      ],
      "properties": {
        "bhn_card_network": {
          "$ref": "#/components/schemas/BHNGiftCardDetails"
        }
      }
    }
  ]
}


impl api::PaymentSync for Wellsfargo {}

impl api::PaymentSync for for Wellsfargo


impl webhooks::IncomingWebhook for Opayo {
    fn get_webhook_object_reference_id(
        &self,
        _request: &webhooks::IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<api_models::webhooks::ObjectReferenceId, errors::ConnectorError> {
        Err(report!(errors::ConnectorError::WebhooksNotImplemented))
    }

    fn get_webhook_event_type(
        &self,
        _request: &webhooks::IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<api_models::webhooks::IncomingWebhookEvent, errors::ConnectorError> {
        Err(report!(errors::ConnectorError::WebhooksNotImplemented))
    }

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

impl webhooks::IncomingWebhook for for Opayo


pub struct FileUploadResponse {
    #[serde(rename = "id")]
    pub file_id: String,
}


File: crates/router/src/routes.rs

pub mod admin;
pub mod api_keys;
pub mod app;
#[cfg(feature = "v1")]
pub mod apple_pay_certificates_migration;
pub mod authentication;
#[cfg(all(feature = "olap", feature = "v1"))]
pub mod blocklist;
pub mod cache;
pub mod cards_info;
pub mod configs;
#[cfg(feature = "olap")]
pub mod connector_onboarding;
#[cfg(any(feature = "olap", feature = "oltp"))]
pub mod currency;
pub mod customers;
pub mod disputes;
#[cfg(feature = "dummy_connector")]
pub mod dummy_connector;
pub mod ephemeral_key;
pub mod feature_matrix;
pub mod files;
#[cfg(feature = "frm")]
pub mod fraud_check;
pub mod gsm;
pub mod health;
pub mod hypersense;
pub mod lock_utils;
#[cfg(feature = "v1")]
pub mod locker_migration;
pub mod mandates;
pub mod metrics;
#[cfg(feature = "v1")]
pub mod payment_link;
pub mod payment_methods;
pub mod payments;
#[cfg(feature = "payouts")]
pub mod payout_link;
#[cfg(feature = "payouts")]
pub mod payouts;
#[cfg(any(feature = "olap", feature = "oltp"))]
pub mod pm_auth;
pub mod poll;
#[cfg(feature = "olap")]
pub mod profile_acquirer;
#[cfg(feature = "olap")]
pub mod profiles;
#[cfg(feature = "recon")]
pub mod recon;
pub mod refunds;
#[cfg(feature = "olap")]
pub mod routing;
pub mod three_ds_decision_rule;
pub mod tokenization;
#[cfg(feature = "olap")]
pub mod user;
#[cfg(feature = "olap")]
pub mod user_role;
#[cfg(feature = "olap")]
pub mod verification;
#[cfg(feature = "olap")]
pub mod verify_connector;
#[cfg(all(feature = "olap", feature = "v1"))]
pub mod webhook_events;
pub mod webhooks;

#[cfg(all(feature = "v2", feature = "revenue_recovery"))]
pub mod recovery_webhooks;

pub mod relay;

#[cfg(feature = "olap")]
pub mod process_tracker;

#[cfg(feature = "v2")]
pub mod proxy;

pub mod chat;

#[cfg(feature = "dummy_connector")]
pub use self::app::DummyConnector;
#[cfg(feature = "v2")]
pub use self::app::PaymentMethodSession;
#[cfg(all(feature = "oltp", feature = "v2"))]
pub use self::app::Proxy;
#[cfg(all(feature = "olap", feature = "recon", feature = "v1"))]
pub use self::app::Recon;
#[cfg(feature = "v2")]
pub use self::app::Tokenization;
pub use self::app::{
    ApiKeys, AppState, ApplePayCertificatesMigration, Authentication, Cache, Cards, Chat, Configs,
    ConnectorOnboarding, Customers, Disputes, EphemeralKey, FeatureMatrix, Files, Forex, Gsm,
    Health, Hypersense, Mandates, MerchantAccount, MerchantConnectorAccount, PaymentLink,
    PaymentMethods, Payments, Poll, ProcessTracker, ProcessTrackerDeprecated, Profile,
    ProfileAcquirer, ProfileNew, Refunds, Relay, RelayWebhooks, SessionState, ThreeDsDecisionRule,
    User, UserDeprecated, Webhooks,
};
#[cfg(feature = "olap")]
pub use self::app::{Blocklist, Organization, Routing, Verify, WebhookEvents};
#[cfg(feature = "payouts")]
pub use self::app::{PayoutLink, Payouts};
#[cfg(all(feature = "stripe", feature = "v1"))]
pub use super::compatibility::stripe::StripeApis;
#[cfg(feature = "olap")]
pub use crate::analytics::routes::{self as analytics, Analytics};


OpenAPI Block Path: components.schemas.ProfileCreate
{
  "type": "object",
  "properties": {
    "profile_name": {
      "type": "string",
      "description": "The name of profile",
      "nullable": true,
      "maxLength": 64
    },
    "return_url": {
      "type": "string",
      "description": "The URL to redirect after the completion of the operation",
      "example": "https://www.example.com/success",
      "nullable": true,
      "maxLength": 255
    },
    "enable_payment_response_hash": {
      "type": "boolean",
      "description": "A boolean value to indicate if payment response hash needs to be enabled",
      "default": true,
      "example": true,
      "nullable": true
    },
    "payment_response_hash_key": {
      "type": "string",
      "description": "Refers to the hash key used for calculating the signature for webhooks and redirect response. If the value is not provided, a value is automatically generated.",
      "nullable": true
    },
    "redirect_to_merchant_with_http_post": {
      "type": "boolean",
      "description": "A boolean value to indicate if redirect to merchant with http post needs to be enabled",
      "default": false,
      "example": true,
      "nullable": true
    },
    "webhook_details": {
      "allOf": [
        {
          "$ref": "#/components/schemas/WebhookDetails"
        }
      ],
      "nullable": true
    },
    "metadata": {
      "type": "object",
      "description": "Metadata is useful for storing additional, unstructured information on an object.",
      "nullable": true
    },
    "routing_algorithm": {
      "type": "object",
      "description": "The routing algorithm to be used for routing payments to desired connectors",
      "nullable": true
    },
    "intent_fulfillment_time": {
      "type": "integer",
      "format": "int32",
      "description": "Will be used to determine the time till which your payment will be active once the payment session starts",
      "example": 900,
      "nullable": true,
      "minimum": 0
    },
    "frm_routing_algorithm": {
      "type": "object",
      "description": "The frm routing algorithm to be used for routing payments to desired FRM's",
      "nullable": true
    },
    "payout_routing_algorithm": {
      "allOf": [
        {
          "$ref": "#/components/schemas/StaticRoutingAlgorithm"
        }
      ],
      "nullable": true
    },
    "applepay_verified_domains": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Verified Apple Pay domains for a particular profile",
      "nullable": true
    },
    "session_expiry": {
      "type": "integer",
      "format": "int32",
      "description": "Client Secret Default expiry for all payments created under this profile",
      "example": 900,
      "nullable": true,
      "minimum": 0
    },
    "payment_link_config": {
      "allOf": [
        {
          "$ref": "#/components/schemas/BusinessPaymentLinkConfig"
        }
      ],
      "nullable": true
    },
    "authentication_connector_details": {
      "allOf": [
        {
          "$ref": "#/components/schemas/AuthenticationConnectorDetails"
        }
      ],
      "nullable": true
    },
    "use_billing_as_payment_method_billing": {
      "type": "boolean",
      "description": "Whether to use the billing details passed when creating the intent as payment method billing",
      "nullable": true
    },
    "collect_shipping_details_from_wallet_connector": {
      "type": "boolean",
      "description": "A boolean value to indicate if customer shipping details needs to be collected from wallet\nconnector only if it is required field for connector (Eg. Apple Pay, Google Pay etc)",
      "default": false,
      "example": false,
      "nullable": true
    },
    "collect_billing_details_from_wallet_connector": {
      "type": "boolean",
      "description": "A boolean value to indicate if customer billing details needs to be collected from wallet\nconnector only if it is required field for connector (Eg. Apple Pay, Google Pay etc)",
      "default": false,
      "example": false,
      "nullable": true
    },
    "always_collect_shipping_details_from_wallet_connector": {
      "type": "boolean",
      "description": "A boolean value to indicate if customer shipping details needs to be collected from wallet\nconnector irrespective of connector required fields (Eg. Apple pay, Google pay etc)",
      "default": false,
      "example": false,
      "nullable": true
    },
    "always_collect_billing_details_from_wallet_connector": {
      "type": "boolean",
      "description": "A boolean value to indicate if customer billing details needs to be collected from wallet\nconnector irrespective of connector required fields (Eg. Apple pay, Google pay etc)",
      "default": false,
      "example": false,
      "nullable": true
    },
    "is_connector_agnostic_mit_enabled": {
      "type": "boolean",
      "description": "Indicates if the MIT (merchant initiated transaction) payments can be made connector\nagnostic, i.e., MITs may be processed through different connector than CIT (customer\ninitiated transaction) based on the routing rules.\nIf set to `false`, MIT will go through the same connector as the CIT.",
      "nullable": true
    },
    "payout_link_config": {
      "allOf": [
        {
          "$ref": "#/components/schemas/BusinessPayoutLinkConfig"
        }
      ],
      "nullable": true
    },
    "outgoing_webhook_custom_http_headers": {
      "type": "object",
      "description": "These key-value pairs are sent as additional custom headers in the outgoing webhook request. It is recommended not to use more than four key-value pairs.",
      "nullable": true
    },
    "tax_connector_id": {
      "type": "string",
      "description": "Merchant Connector id to be stored for tax_calculator connector",
      "nullable": true
    },
    "is_tax_connector_enabled": {
      "type": "boolean",
      "description": "Indicates if tax_calculator connector is enabled or not.\nIf set to `true` tax_connector_id will be checked."
    },
    "is_network_tokenization_enabled": {
      "type": "boolean",
      "description": "Indicates if network tokenization is enabled or not."
    },
    "is_auto_retries_enabled": {
      "type": "boolean",
      "description": "Indicates if is_auto_retries_enabled is enabled or not.",
      "nullable": true
    },
    "max_auto_retries_enabled": {
      "type": "integer",
      "format": "int32",
      "description": "Maximum number of auto retries allowed for a payment",
      "nullable": true,
      "minimum": 0
    },
    "always_request_extended_authorization": {
      "type": "boolean",
      "description": "Bool indicating if extended authentication must be requested for all payments",
      "nullable": true
    },
    "is_click_to_pay_enabled": {
      "type": "boolean",
      "description": "Indicates if click to pay is enabled or not."
    },
    "authentication_product_ids": {
      "type": "object",
      "description": "Product authentication ids",
      "nullable": true
    },
    "card_testing_guard_config": {
      "allOf": [
        {
          "$ref": "#/components/schemas/CardTestingGuardConfig"
        }
      ],
      "nullable": true
    },
    "is_clear_pan_retries_enabled": {
      "type": "boolean",
      "description": "Indicates if clear pan retries is enabled or not.",
      "nullable": true
    },
    "force_3ds_challenge": {
      "type": "boolean",
      "description": "Indicates if 3ds challenge is forced",
      "nullable": true
    },
    "is_debit_routing_enabled": {
      "type": "boolean",
      "description": "Indicates if debit routing is enabled or not",
      "nullable": true
    },
    "merchant_business_country": {
      "allOf": [
        {
          "$ref": "#/components/schemas/CountryAlpha2"
        }
      ],
      "nullable": true
    },
    "is_iframe_redirection_enabled": {
      "type": "boolean",
      "description": "Indicates if the redirection has to open in the iframe",
      "example": false,
      "nullable": true
    },
    "is_pre_network_tokenization_enabled": {
      "type": "boolean",
      "description": "Indicates if pre network tokenization is enabled or not",
      "nullable": true
    },
    "merchant_category_code": {
      "allOf": [
        {
          "$ref": "#/components/schemas/MerchantCategoryCode"
        }
      ],
      "nullable": true
    },
    "merchant_country_code": {
      "allOf": [
        {
          "$ref": "#/components/schemas/MerchantCountryCode"
        }
      ],
      "nullable": true
    },
    "dispute_polling_interval": {
      "type": "integer",
      "format": "int32",
      "description": "Time interval (in hours) for polling the connector to check dispute statuses",
      "example": 2,
      "nullable": true
    },
    "is_manual_retry_enabled": {
      "type": "boolean",
      "description": "Indicates if manual retry for payment is enabled or not",
      "nullable": true
    }
  },
  "additionalProperties": false
}


pub struct MerchantConnectorAccountNew {
    pub merchant_id: Option<id_type::MerchantId>,
    pub connector_type: Option<storage_enums::ConnectorType>,
    pub connector_name: Option<common_enums::connector_enums::Connector>,
    pub connector_account_details: Option<Encryption>,
    pub disabled: Option<bool>,
    #[diesel(deserialize_as = super::OptionalDieselArray<common_types::payment_methods::PaymentMethodsEnabled>)]
    pub payment_methods_enabled: Option<Vec<common_types::payment_methods::PaymentMethodsEnabled>>,
    pub metadata: Option<pii::SecretSerdeValue>,
    pub connector_label: Option<String>,
    pub created_at: time::PrimitiveDateTime,
    pub modified_at: time::PrimitiveDateTime,
    pub connector_webhook_details: Option<pii::SecretSerdeValue>,
    #[diesel(deserialize_as = super::OptionalDieselArray<pii::SecretSerdeValue>)]
    pub frm_config: Option<Vec<pii::SecretSerdeValue>>,
    pub profile_id: id_type::ProfileId,
    #[diesel(deserialize_as = super::OptionalDieselArray<String>)]
    pub applepay_verified_domains: Option<Vec<String>>,
    pub pm_auth_config: Option<pii::SecretSerdeValue>,
    pub status: storage_enums::ConnectorStatus,
    pub additional_merchant_data: Option<Encryption>,
    pub connector_wallets_details: Option<Encryption>,
    pub version: common_enums::ApiVersion,
    pub id: id_type::MerchantConnectorAccountId,
    pub feature_metadata: Option<MerchantConnectorAccountFeatureMetadata>,
}


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

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

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

impl ConnectorSpecifications for for Nmi