File: crates/router/src/types.rs
 Public functions: 1
 Public structs: 11

// FIXME: Why were these data types grouped this way?
//
// Folder `types` is strange for Rust ecosystem, nevertheless it might be okay.
// But folder `enum` is even more strange I unlikely okay. Why should not we introduce folders `type`, `structs` and `traits`? :)
// Is it better to split data types according to business logic instead.
// For example, customers/address/dispute/mandate is "models".
// Separation of concerns instead of separation of forms.

pub mod api;
pub mod authentication;
pub mod connector_transformers;
pub mod domain;
#[cfg(feature = "frm")]
pub mod fraud_check;
pub mod payment_methods;
pub mod pm_auth;
use masking::Secret;
pub mod storage;
pub mod transformers;
use std::marker::PhantomData;

pub use api_models::{enums::Connector, mandates};
#[cfg(feature = "payouts")]
pub use api_models::{enums::PayoutConnectors, payouts as payout_types};
#[cfg(feature = "v2")]
use common_utils::errors::CustomResult;
pub use common_utils::{pii, pii::Email, request::RequestContent, types::MinorUnit};
#[cfg(feature = "v2")]
use error_stack::ResultExt;
#[cfg(feature = "frm")]
pub use hyperswitch_domain_models::router_data_v2::FrmFlowData;
use hyperswitch_domain_models::router_flow_types::{
    self,
    access_token_auth::AccessTokenAuth,
    dispute::{Accept, Defend, Dsync, Evidence, Fetch},
    files::{Retrieve, Upload},
    mandate_revoke::MandateRevoke,
    payments::{
        Approve, Authorize, AuthorizeSessionToken, Balance, CalculateTax, Capture,
        CompleteAuthorize, CreateConnectorCustomer, CreateOrder, ExternalVaultProxy,
        IncrementalAuthorization, InitPayment, PSync, PostCaptureVoid, PostProcessing,
        PostSessionTokens, PreProcessing, Reject, SdkSessionUpdate, Session, SetupMandate,
        UpdateMetadata, Void,
    },
    refunds::{Execute, RSync},
    webhooks::VerifyWebhookSource,
};
pub use hyperswitch_domain_models::{
    payment_address::PaymentAddress,
    router_data::{
        AccessToken, AccessTokenAuthenticationResponse, AdditionalPaymentMethodConnectorResponse,
        ConnectorAuthType, ConnectorResponseData, ErrorResponse, GooglePayPaymentMethodDetails,
        GooglePayPredecryptDataInternal, L2L3Data, PaymentMethodBalance, PaymentMethodToken,
        RecurringMandatePaymentData, RouterData,
    },
    router_data_v2::{
        AccessTokenFlowData, AuthenticationTokenFlowData, DisputesFlowData,
        ExternalAuthenticationFlowData, FilesFlowData, MandateRevokeFlowData, PaymentFlowData,
        RefundFlowData, RouterDataV2, UasFlowData, WebhookSourceVerifyData,
    },
    router_request_types::{
        revenue_recovery::{
            BillingConnectorInvoiceSyncRequest, BillingConnectorPaymentsSyncRequest,
            RevenueRecoveryRecordBackRequest,
        },
        unified_authentication_service::{
            UasAuthenticationRequestData, UasAuthenticationResponseData,
            UasConfirmationRequestData, UasPostAuthenticationRequestData,
            UasPreAuthenticationRequestData,
        },
        AcceptDisputeRequestData, AccessTokenAuthenticationRequestData, AccessTokenRequestData,
        AuthorizeSessionTokenData, BrowserInformation, ChargeRefunds, ChargeRefundsOptions,
        CompleteAuthorizeData, CompleteAuthorizeRedirectResponse, ConnectorCustomerData,
        CreateOrderRequestData, DefendDisputeRequestData, DestinationChargeRefund,
        DirectChargeRefund, DisputeSyncData, ExternalVaultProxyPaymentsData,
        FetchDisputesRequestData, MandateRevokeRequestData, MultipleCaptureRequestData,
        PaymentMethodTokenizationData, PaymentsApproveData, PaymentsAuthorizeData,
        PaymentsCancelData, PaymentsCancelPostCaptureData, PaymentsCaptureData,
        PaymentsIncrementalAuthorizationData, PaymentsPostProcessingData,
        PaymentsPostSessionTokensData, PaymentsPreProcessingData, PaymentsRejectData,
        PaymentsSessionData, PaymentsSyncData, PaymentsTaxCalculationData,
        PaymentsUpdateMetadataData, RefundsData, ResponseId, RetrieveFileRequestData,
        SdkPaymentsSessionUpdateData, SetupMandateRequestData, SplitRefundsRequest,
        SubmitEvidenceRequestData, SyncRequestType, UploadFileRequestData, VaultRequestData,
        VerifyWebhookSourceRequestData,
    },
    router_response_types::{
        revenue_recovery::{
            BillingConnectorInvoiceSyncResponse, BillingConnectorPaymentsSyncResponse,
            RevenueRecoveryRecordBackResponse,
        },
        AcceptDisputeResponse, CaptureSyncResponse, DefendDisputeResponse, DisputeSyncResponse,
        FetchDisputesResponse, MandateReference, MandateRevokeResponseData, PaymentsResponseData,
        PreprocessingResponseId, RefundsResponseData, RetrieveFileResponse, SubmitEvidenceResponse,
        TaxCalculationResponseData, UploadFileResponse, VaultResponseData,
        VerifyWebhookSourceResponseData, VerifyWebhookStatus,
    },
};
#[cfg(feature = "payouts")]
pub use hyperswitch_domain_models::{
    router_data_v2::PayoutFlowData, router_request_types::PayoutsData,
    router_response_types::PayoutsResponseData,
};
#[cfg(feature = "payouts")]
pub use hyperswitch_interfaces::types::{
    PayoutCancelType, PayoutCreateType, PayoutEligibilityType, PayoutFulfillType, PayoutQuoteType,
    PayoutRecipientAccountType, PayoutRecipientType, PayoutSyncType,
};
pub use hyperswitch_interfaces::{
    disputes::DisputePayload,
    types::{
        AcceptDisputeType, ConnectorCustomerType, DefendDisputeType, FetchDisputesType,
        IncrementalAuthorizationType, MandateRevokeType, PaymentsAuthorizeType,
        PaymentsBalanceType, PaymentsCaptureType, PaymentsCompleteAuthorizeType, PaymentsInitType,
        PaymentsPostCaptureVoidType, PaymentsPostProcessingType, PaymentsPostSessionTokensType,
        PaymentsPreAuthorizeType, PaymentsPreProcessingType, PaymentsSessionType, PaymentsSyncType,
        PaymentsUpdateMetadataType, PaymentsVoidType, RefreshTokenType, RefundExecuteType,
        RefundSyncType, Response, RetrieveFileType, SdkSessionUpdateType, SetupMandateType,
        SubmitEvidenceType, TokenizationType, UploadFileType, VerifyWebhookSourceType,
    },
};

#[cfg(feature = "v2")]
use crate::core::errors;
pub use crate::core::payments::CustomerDetails;
#[cfg(feature = "payouts")]
use crate::core::utils::IRRELEVANT_CONNECTOR_REQUEST_REFERENCE_ID_IN_PAYOUTS_FLOW;
use crate::{
    consts,
    core::payments::{OperationSessionGetters, PaymentData},
    services,
    types::transformers::{ForeignFrom, ForeignTryFrom},
};

pub type PaymentsAuthorizeRouterData =
    RouterData<Authorize, PaymentsAuthorizeData, PaymentsResponseData>;
pub type ExternalVaultProxyPaymentsRouterData =
    RouterData<ExternalVaultProxy, ExternalVaultProxyPaymentsData, PaymentsResponseData>;
pub type PaymentsPreProcessingRouterData =
    RouterData<PreProcessing, PaymentsPreProcessingData, PaymentsResponseData>;
pub type PaymentsPostProcessingRouterData =
    RouterData<PostProcessing, PaymentsPostProcessingData, PaymentsResponseData>;
pub type PaymentsAuthorizeSessionTokenRouterData =
    RouterData<AuthorizeSessionToken, AuthorizeSessionTokenData, PaymentsResponseData>;
pub type PaymentsCompleteAuthorizeRouterData =
    RouterData<CompleteAuthorize, CompleteAuthorizeData, PaymentsResponseData>;
pub type PaymentsInitRouterData =
    RouterData<InitPayment, PaymentsAuthorizeData, PaymentsResponseData>;
pub type PaymentsBalanceRouterData =
    RouterData<Balance, PaymentsAuthorizeData, PaymentsResponseData>;
pub type PaymentsSyncRouterData = RouterData<PSync, PaymentsSyncData, PaymentsResponseData>;
pub type PaymentsCaptureRouterData = RouterData<Capture, PaymentsCaptureData, PaymentsResponseData>;
pub type PaymentsIncrementalAuthorizationRouterData = RouterData<
    IncrementalAuthorization,
    PaymentsIncrementalAuthorizationData,
    PaymentsResponseData,
>;
pub type PaymentsTaxCalculationRouterData =
    RouterData<CalculateTax, PaymentsTaxCalculationData, TaxCalculationResponseData>;

pub type CreateOrderRouterData =
    RouterData<CreateOrder, CreateOrderRequestData, PaymentsResponseData>;

pub type SdkSessionUpdateRouterData =
    RouterData<SdkSessionUpdate, SdkPaymentsSessionUpdateData, PaymentsResponseData>;

pub type PaymentsPostSessionTokensRouterData =
    RouterData<PostSessionTokens, PaymentsPostSessionTokensData, PaymentsResponseData>;

pub type PaymentsUpdateMetadataRouterData =
    RouterData<UpdateMetadata, PaymentsUpdateMetadataData, PaymentsResponseData>;

pub type PaymentsCancelRouterData = RouterData<Void, PaymentsCancelData, PaymentsResponseData>;
pub type PaymentsCancelPostCaptureRouterData =
    RouterData<PostCaptureVoid, PaymentsCancelPostCaptureData, PaymentsResponseData>;
pub type PaymentsRejectRouterData = RouterData<Reject, PaymentsRejectData, PaymentsResponseData>;
pub type PaymentsApproveRouterData = RouterData<Approve, PaymentsApproveData, PaymentsResponseData>;
pub type PaymentsSessionRouterData = RouterData<Session, PaymentsSessionData, PaymentsResponseData>;
pub type RefundsRouterData<F> = RouterData<F, RefundsData, RefundsResponseData>;
pub type RefundExecuteRouterData = RouterData<Execute, RefundsData, RefundsResponseData>;
pub type RefundSyncRouterData = RouterData<RSync, RefundsData, RefundsResponseData>;
pub type TokenizationRouterData = RouterData<
    router_flow_types::PaymentMethodToken,
    PaymentMethodTokenizationData,
    PaymentsResponseData,
>;
pub type ConnectorCustomerRouterData =
    RouterData<CreateConnectorCustomer, ConnectorCustomerData, PaymentsResponseData>;

pub type RefreshTokenRouterData = RouterData<AccessTokenAuth, AccessTokenRequestData, AccessToken>;

pub type PaymentsResponseRouterData<R> =
    ResponseRouterData<Authorize, R, PaymentsAuthorizeData, PaymentsResponseData>;
pub type PaymentsCancelResponseRouterData<R> =
    ResponseRouterData<Void, R, PaymentsCancelData, PaymentsResponseData>;
pub type PaymentsCancelPostCaptureResponseRouterData<R> =
    ResponseRouterData<PostCaptureVoid, R, PaymentsCancelPostCaptureData, PaymentsResponseData>;
pub type PaymentsBalanceResponseRouterData<R> =
    ResponseRouterData<Balance, R, PaymentsAuthorizeData, PaymentsResponseData>;
pub type PaymentsSyncResponseRouterData<R> =
    ResponseRouterData<PSync, R, PaymentsSyncData, PaymentsResponseData>;
pub type PaymentsSessionResponseRouterData<R> =
    ResponseRouterData<Session, R, PaymentsSessionData, PaymentsResponseData>;
pub type PaymentsInitResponseRouterData<R> =
    ResponseRouterData<InitPayment, R, PaymentsAuthorizeData, PaymentsResponseData>;
pub type SdkSessionUpdateResponseRouterData<R> =
    ResponseRouterData<SdkSessionUpdate, R, SdkPaymentsSessionUpdateData, PaymentsResponseData>;
pub type PaymentsCaptureResponseRouterData<R> =
    ResponseRouterData<Capture, R, PaymentsCaptureData, PaymentsResponseData>;
pub type PaymentsPreprocessingResponseRouterData<R> =
    ResponseRouterData<PreProcessing, R, PaymentsPreProcessingData, PaymentsResponseData>;
pub type TokenizationResponseRouterData<R> =
    ResponseRouterData<PaymentMethodToken, R, PaymentMethodTokenizationData, PaymentsResponseData>;
pub type ConnectorCustomerResponseRouterData<R> =
    ResponseRouterData<CreateConnectorCustomer, R, ConnectorCustomerData, PaymentsResponseData>;

pub type RefundsResponseRouterData<F, R> =
    ResponseRouterData<F, R, RefundsData, RefundsResponseData>;

pub type SetupMandateRouterData =
    RouterData<SetupMandate, SetupMandateRequestData, PaymentsResponseData>;

pub type AcceptDisputeRouterData =
    RouterData<Accept, AcceptDisputeRequestData, AcceptDisputeResponse>;

pub type VerifyWebhookSourceRouterData = RouterData<
    VerifyWebhookSource,
    VerifyWebhookSourceRequestData,
    VerifyWebhookSourceResponseData,
>;

pub type SubmitEvidenceRouterData =
    RouterData<Evidence, SubmitEvidenceRequestData, SubmitEvidenceResponse>;

pub type UploadFileRouterData = RouterData<Upload, UploadFileRequestData, UploadFileResponse>;

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

pub type DefendDisputeRouterData =
    RouterData<Defend, DefendDisputeRequestData, DefendDisputeResponse>;

pub type FetchDisputesRouterData =
    RouterData<Fetch, FetchDisputesRequestData, FetchDisputesResponse>;

pub type DisputeSyncRouterData = RouterData<Dsync, DisputeSyncData, DisputeSyncResponse>;

pub type MandateRevokeRouterData =
    RouterData<MandateRevoke, MandateRevokeRequestData, MandateRevokeResponseData>;

#[cfg(feature = "payouts")]
pub type PayoutsRouterData<F> = RouterData<F, PayoutsData, PayoutsResponseData>;

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

#[cfg(feature = "payouts")]
pub type PayoutActionData = Vec<(
    storage::Payouts,
    storage::PayoutAttempt,
    Option<domain::Customer>,
    Option<api_models::payments::Address>,
)>;

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

pub trait Capturable {
    fn get_captured_amount<F>(
        &self,
        _amount_captured: Option<i64>,
        _payment_data: &PaymentData<F>,
    ) -> Option<i64>
    where
        F: Clone,
    {
        None
    }
    fn get_amount_capturable<F>(
        &self,
        _payment_data: &PaymentData<F>,
        _get_amount_capturable: Option<i64>,
        _attempt_status: common_enums::AttemptStatus,
    ) -> Option<i64>
    where
        F: Clone,
    {
        None
    }
}

#[cfg(feature = "v1")]
impl Capturable for PaymentsAuthorizeData {
    fn get_captured_amount<F>(
        &self,
        amount_captured: Option<i64>,
        payment_data: &PaymentData<F>,
    ) -> Option<i64>
    where
        F: Clone,
    {
        amount_captured.or(Some(
            payment_data
                .payment_attempt
                .get_total_amount()
                .get_amount_as_i64(),
        ))
    }

    fn get_amount_capturable<F>(
        &self,
        payment_data: &PaymentData<F>,
        amount_capturable: Option<i64>,
        attempt_status: common_enums::AttemptStatus,
    ) -> Option<i64>
    where
        F: Clone,
    {
        let amount_capturable_from_intent_status = match payment_data.get_capture_method().unwrap_or_default()
        {
            common_enums::CaptureMethod::Automatic
            | common_enums::CaptureMethod::SequentialAutomatic => {
                let intent_status = common_enums::IntentStatus::foreign_from(attempt_status);
                match intent_status {
                    common_enums::IntentStatus::Succeeded
                    | common_enums::IntentStatus::Failed
                    | common_enums::IntentStatus::Conflicted
                    | common_enums::IntentStatus::Expired => Some(0),
                    common_enums::IntentStatus::Cancelled
                    | common_enums::IntentStatus::CancelledPostCapture
                    | common_enums::IntentStatus::PartiallyCaptured
                    | common_enums::IntentStatus::RequiresCustomerAction
                    | common_enums::IntentStatus::RequiresMerchantAction
                    | common_enums::IntentStatus::RequiresPaymentMethod
                    | common_enums::IntentStatus::RequiresConfirmation
                    | common_enums::IntentStatus::RequiresCapture
                    | common_enums::IntentStatus::PartiallyCapturedAndCapturable
                    | common_enums::IntentStatus::PartiallyAuthorizedAndRequiresCapture
                    | common_enums::IntentStatus::Processing => None,
                }
            },
            common_enums::CaptureMethod::Manual => Some(payment_data.payment_attempt.get_total_amount().get_amount_as_i64()),
            // In case of manual multiple, amount capturable must be inferred from all captures.
            common_enums::CaptureMethod::ManualMultiple |
            // Scheduled capture is not supported as of now
            common_enums::CaptureMethod::Scheduled => None,
        };
        amount_capturable
            .or(amount_capturable_from_intent_status)
            .or(Some(
                payment_data
                    .payment_attempt
                    .get_total_amount()
                    .get_amount_as_i64(),
            ))
    }
}

#[cfg(feature = "v1")]
impl Capturable for PaymentsCaptureData {
    fn get_captured_amount<F>(
        &self,
        _amount_captured: Option<i64>,
        _payment_data: &PaymentData<F>,
    ) -> Option<i64>
    where
        F: Clone,
    {
        Some(self.amount_to_capture)
    }
    fn get_amount_capturable<F>(
        &self,
        _payment_data: &PaymentData<F>,
        _amount_capturable: Option<i64>,
        attempt_status: common_enums::AttemptStatus,
    ) -> Option<i64>
    where
        F: Clone,
    {
        let intent_status = common_enums::IntentStatus::foreign_from(attempt_status);
        match intent_status {
            common_enums::IntentStatus::Succeeded
            | common_enums::IntentStatus::PartiallyCaptured
            | common_enums::IntentStatus::Conflicted
            | common_enums::IntentStatus::Expired => Some(0),
            common_enums::IntentStatus::Processing
            | common_enums::IntentStatus::Cancelled
            | common_enums::IntentStatus::CancelledPostCapture
            | common_enums::IntentStatus::Failed
            | common_enums::IntentStatus::RequiresCustomerAction
            | common_enums::IntentStatus::RequiresMerchantAction
            | common_enums::IntentStatus::RequiresPaymentMethod
            | common_enums::IntentStatus::RequiresConfirmation
            | common_enums::IntentStatus::RequiresCapture
            | common_enums::IntentStatus::PartiallyCapturedAndCapturable
            | common_enums::IntentStatus::PartiallyAuthorizedAndRequiresCapture => None,
        }
    }
}

#[cfg(feature = "v1")]
impl Capturable for CompleteAuthorizeData {
    fn get_captured_amount<F>(
        &self,
        amount_captured: Option<i64>,
        payment_data: &PaymentData<F>,
    ) -> Option<i64>
    where
        F: Clone,
    {
        amount_captured.or(Some(
            payment_data
                .payment_attempt
                .get_total_amount()
                .get_amount_as_i64(),
        ))
    }
    fn get_amount_capturable<F>(
        &self,
        payment_data: &PaymentData<F>,
        amount_capturable: Option<i64>,
        attempt_status: common_enums::AttemptStatus,
    ) -> Option<i64>
    where
        F: Clone,
    {
        let amount_capturable_from_intent_status = match payment_data
            .get_capture_method()
            .unwrap_or_default()
        {
            common_enums::CaptureMethod::Automatic | common_enums::CaptureMethod::SequentialAutomatic => {
                let intent_status = common_enums::IntentStatus::foreign_from(attempt_status);
                match intent_status {
                    common_enums::IntentStatus::Succeeded
                    | common_enums::IntentStatus::Failed
                    | common_enums::IntentStatus::Conflicted
                    | common_enums::IntentStatus::Expired => Some(0),
                    common_enums::IntentStatus::Cancelled | common_enums::IntentStatus::PartiallyCaptured
                    | common_enums::IntentStatus::CancelledPostCapture
                    | common_enums::IntentStatus::RequiresCustomerAction
                    | common_enums::IntentStatus::RequiresMerchantAction
                    | common_enums::IntentStatus::RequiresPaymentMethod
                    | common_enums::IntentStatus::RequiresConfirmation
                    | common_enums::IntentStatus::RequiresCapture
                    | common_enums::IntentStatus::PartiallyCapturedAndCapturable
                    | common_enums::IntentStatus::PartiallyAuthorizedAndRequiresCapture
                    | common_enums::IntentStatus::Processing => None,
                }
            },
            common_enums::CaptureMethod::Manual => Some(payment_data.payment_attempt.get_total_amount().get_amount_as_i64()),
            // In case of manual multiple, amount capturable must be inferred from all captures.
            common_enums::CaptureMethod::ManualMultiple |
            // Scheduled capture is not supported as of now
            common_enums::CaptureMethod::Scheduled => None,
        };
        amount_capturable
            .or(amount_capturable_from_intent_status)
            .or(Some(
                payment_data
                    .payment_attempt
                    .get_total_amount()
                    .get_amount_as_i64(),
            ))
    }
}

impl Capturable for SetupMandateRequestData {}
impl Capturable for PaymentsTaxCalculationData {}
impl Capturable for SdkPaymentsSessionUpdateData {}
impl Capturable for PaymentsPostSessionTokensData {}
impl Capturable for PaymentsUpdateMetadataData {}
impl Capturable for PaymentsCancelData {
    fn get_captured_amount<F>(
        &self,
        _amount_captured: Option<i64>,
        payment_data: &PaymentData<F>,
    ) -> Option<i64>
    where
        F: Clone,
    {
        // return previously captured amount
        payment_data
            .payment_intent
            .amount_captured
            .map(|amt| amt.get_amount_as_i64())
    }
    fn get_amount_capturable<F>(
        &self,
        _payment_data: &PaymentData<F>,
        _amount_capturable: Option<i64>,
        attempt_status: common_enums::AttemptStatus,
    ) -> Option<i64>
    where
        F: Clone,
    {
        let intent_status = common_enums::IntentStatus::foreign_from(attempt_status);
        match intent_status {
            common_enums::IntentStatus::Cancelled
            | common_enums::IntentStatus::CancelledPostCapture
            | common_enums::IntentStatus::Processing
            | common_enums::IntentStatus::PartiallyCaptured
            | common_enums::IntentStatus::Conflicted
            | common_enums::IntentStatus::Expired => Some(0),
            common_enums::IntentStatus::Succeeded
            | common_enums::IntentStatus::Failed
            | common_enums::IntentStatus::RequiresCustomerAction
            | common_enums::IntentStatus::RequiresMerchantAction
            | common_enums::IntentStatus::RequiresPaymentMethod
            | common_enums::IntentStatus::RequiresConfirmation
            | common_enums::IntentStatus::RequiresCapture
            | common_enums::IntentStatus::PartiallyAuthorizedAndRequiresCapture
            | common_enums::IntentStatus::PartiallyCapturedAndCapturable => None,
        }
    }
}
impl Capturable for PaymentsCancelPostCaptureData {
    fn get_captured_amount<F>(
        &self,
        _amount_captured: Option<i64>,
        payment_data: &PaymentData<F>,
    ) -> Option<i64>
    where
        F: Clone,
    {
        // return previously captured amount
        payment_data
            .payment_intent
            .amount_captured
            .map(|amt| amt.get_amount_as_i64())
    }
    fn get_amount_capturable<F>(
        &self,
        _payment_data: &PaymentData<F>,
        _amount_capturable: Option<i64>,
        attempt_status: common_enums::AttemptStatus,
    ) -> Option<i64>
    where
        F: Clone,
    {
        let intent_status = common_enums::IntentStatus::foreign_from(attempt_status);
        match intent_status {
            common_enums::IntentStatus::Cancelled
            | common_enums::IntentStatus::CancelledPostCapture
            | common_enums::IntentStatus::PartiallyCaptured
            | common_enums::IntentStatus::Conflicted
            | common_enums::IntentStatus::Expired => Some(0),
            common_enums::IntentStatus::Succeeded
            | common_enums::IntentStatus::Failed
            | common_enums::IntentStatus::RequiresCustomerAction
            | common_enums::IntentStatus::RequiresMerchantAction
            | common_enums::IntentStatus::RequiresPaymentMethod
            | common_enums::IntentStatus::RequiresConfirmation
            | common_enums::IntentStatus::RequiresCapture
            | common_enums::IntentStatus::PartiallyCapturedAndCapturable
            | common_enums::IntentStatus::Processing
            | common_enums::IntentStatus::PartiallyAuthorizedAndRequiresCapture => None,
        }
    }
}
impl Capturable for PaymentsApproveData {}
impl Capturable for PaymentsRejectData {}
impl Capturable for PaymentsSessionData {}
impl Capturable for PaymentsIncrementalAuthorizationData {
    fn get_amount_capturable<F>(
        &self,
        _payment_data: &PaymentData<F>,
        amount_capturable: Option<i64>,
        _attempt_status: common_enums::AttemptStatus,
    ) -> Option<i64>
    where
        F: Clone,
    {
        amount_capturable.or(Some(self.total_amount))
    }
}
impl Capturable for PaymentsSyncData {
    #[cfg(feature = "v1")]
    fn get_captured_amount<F>(
        &self,
        _amount_captured: Option<i64>,
        payment_data: &PaymentData<F>,
    ) -> Option<i64>
    where
        F: Clone,
    {
        payment_data
            .payment_attempt
            .amount_to_capture
            .or(payment_data.payment_intent.amount_captured)
            .or_else(|| Some(payment_data.payment_attempt.get_total_amount()))
            .map(|amt| amt.get_amount_as_i64())
    }

    #[cfg(feature = "v2")]
    fn get_captured_amount<F>(
        &self,
        _amount_captured: Option<i64>,
        payment_data: &PaymentData<F>,
    ) -> Option<i64>
    where
        F: Clone,
    {
        // TODO: add a getter for this
        payment_data
            .payment_attempt
            .amount_details
            .get_amount_to_capture()
            .or_else(|| Some(payment_data.payment_attempt.get_total_amount()))
            .map(|amt| amt.get_amount_as_i64())
    }

    #[cfg(feature = "v1")]
    fn get_amount_capturable<F>(
        &self,
        payment_data: &PaymentData<F>,
        amount_capturable: Option<i64>,
        attempt_status: common_enums::AttemptStatus,
    ) -> Option<i64>
    where
        F: Clone,
    {
        if attempt_status.is_terminal_status() {
            Some(0)
        } else {
            amount_capturable.or(Some(MinorUnit::get_amount_as_i64(
                payment_data.payment_attempt.amount_capturable,
            )))
        }
    }

    #[cfg(feature = "v2")]
    fn get_amount_capturable<F>(
        &self,
        payment_data: &PaymentData<F>,
        amount_capturable: Option<i64>,
        attempt_status: common_enums::AttemptStatus,
    ) -> Option<i64>
    where
        F: Clone,
    {
        if attempt_status.is_terminal_status() {
            Some(0)
        } else {
            None
        }
    }
}

pub struct AddAccessTokenResult {
    pub access_token_result: Result<Option<AccessToken>, ErrorResponse>,
    pub connector_supports_access_token: bool,
}

pub struct PaymentMethodTokenResult {
    pub payment_method_token_result: Result<Option<String>, ErrorResponse>,
    pub is_payment_method_tokenization_performed: bool,
    pub connector_response: Option<ConnectorResponseData>,
}

#[derive(Clone)]
pub struct CreateOrderResult {
    pub create_order_result: Result<String, ErrorResponse>,
}

pub struct PspTokenResult {
    pub token: Result<String, ErrorResponse>,
}

#[derive(Debug, Clone, Copy)]
pub enum Redirection {
    Redirect,
    NoRedirect,
}

#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
pub struct PollConfig {
    pub delay_in_secs: i8,
    pub frequency: i8,
}

impl PollConfig {
    pub fn get_poll_config_key(connector: String) -> String {
        format!("poll_config_external_three_ds_{connector}")
    }
}

impl Default for PollConfig {
    fn default() -> Self {
        Self {
            delay_in_secs: consts::DEFAULT_POLL_DELAY_IN_SECS,
            frequency: consts::DEFAULT_POLL_FREQUENCY,
        }
    }
}

#[cfg(feature = "v1")]
#[derive(Clone, Debug)]
pub struct RedirectPaymentFlowResponse {
    pub payments_response: api_models::payments::PaymentsResponse,
    pub business_profile: domain::Profile,
}

#[cfg(feature = "v2")]
#[derive(Clone, Debug)]
pub struct RedirectPaymentFlowResponse<D> {
    pub payment_data: D,
    pub profile: domain::Profile,
}

#[cfg(feature = "v1")]
#[derive(Clone, Debug)]
pub struct AuthenticatePaymentFlowResponse {
    pub payments_response: api_models::payments::PaymentsResponse,
    pub poll_config: PollConfig,
    pub business_profile: domain::Profile,
}

#[derive(Debug, Clone, Default, serde::Deserialize, serde::Serialize)]
pub struct ConnectorResponse {
    pub merchant_id: common_utils::id_type::MerchantId,
    pub connector: String,
    pub payment_id: common_utils::id_type::PaymentId,
    pub amount: i64,
    pub connector_transaction_id: String,
    pub return_url: Option<String>,
    pub three_ds_form: Option<services::RedirectForm>,
}

pub struct ResponseRouterData<Flow, R, Request, Response> {
    pub response: R,
    pub data: RouterData<Flow, Request, Response>,
    pub http_code: u16,
}

#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
pub enum RecipientIdType {
    ConnectorId(Secret<String>),
    LockerId(Secret<String>),
}

#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "snake_case")]
pub enum MerchantAccountData {
    Iban {
        iban: Secret<String>,
        name: String,
        connector_recipient_id: Option<RecipientIdType>,
    },
    Bacs {
        account_number: Secret<String>,
        sort_code: Secret<String>,
        name: String,
        connector_recipient_id: Option<RecipientIdType>,
    },
    FasterPayments {
        account_number: Secret<String>,
        sort_code: Secret<String>,
        name: String,
        connector_recipient_id: Option<RecipientIdType>,
    },
    Sepa {
        iban: Secret<String>,
        name: String,
        connector_recipient_id: Option<RecipientIdType>,
    },
    SepaInstant {
        iban: Secret<String>,
        name: String,
        connector_recipient_id: Option<RecipientIdType>,
    },
    Elixir {
        account_number: Secret<String>,
        iban: Secret<String>,
        name: String,
        connector_recipient_id: Option<RecipientIdType>,
    },
    Bankgiro {
        number: Secret<String>,
        name: String,
        connector_recipient_id: Option<RecipientIdType>,
    },
    Plusgiro {
        number: Secret<String>,
        name: String,
        connector_recipient_id: Option<RecipientIdType>,
    },
}

impl ForeignFrom<MerchantAccountData> for api_models::admin::MerchantAccountData {
    fn foreign_from(from: MerchantAccountData) -> Self {
        match from {
            MerchantAccountData::Iban {
                iban,
                name,
                connector_recipient_id,
            } => Self::Iban {
                iban,
                name,
                connector_recipient_id: match connector_recipient_id {
                    Some(RecipientIdType::ConnectorId(id)) => Some(id.clone()),
                    _ => None,
                },
            },
            MerchantAccountData::Bacs {
                account_number,
                sort_code,
                name,
                connector_recipient_id,
            } => Self::Bacs {
                account_number,
                sort_code,
                name,
                connector_recipient_id: match connector_recipient_id {
                    Some(RecipientIdType::ConnectorId(id)) => Some(id.clone()),
                    _ => None,
                },
            },
            MerchantAccountData::FasterPayments {
                account_number,
                sort_code,
                name,
                connector_recipient_id,
            } => Self::FasterPayments {
                account_number,
                sort_code,
                name,
                connector_recipient_id: match connector_recipient_id {
                    Some(RecipientIdType::ConnectorId(id)) => Some(id.clone()),
                    _ => None,
                },
            },
            MerchantAccountData::Sepa {
                iban,
                name,
                connector_recipient_id,
            } => Self::Sepa {
                iban,
                name,
                connector_recipient_id: match connector_recipient_id {
                    Some(RecipientIdType::ConnectorId(id)) => Some(id.clone()),
                    _ => None,
                },
            },
            MerchantAccountData::SepaInstant {
                iban,
                name,
                connector_recipient_id,
            } => Self::SepaInstant {
                iban,
                name,
                connector_recipient_id: match connector_recipient_id {
                    Some(RecipientIdType::ConnectorId(id)) => Some(id.clone()),
                    _ => None,
                },
            },
            MerchantAccountData::Elixir {
                account_number,
                iban,
                name,
                connector_recipient_id,
            } => Self::Elixir {
                account_number,
                iban,
                name,
                connector_recipient_id: match connector_recipient_id {
                    Some(RecipientIdType::ConnectorId(id)) => Some(id.clone()),
                    _ => None,
                },
            },
            MerchantAccountData::Bankgiro {
                number,
                name,
                connector_recipient_id,
            } => Self::Bankgiro {
                number,
                name,
                connector_recipient_id: match connector_recipient_id {
                    Some(RecipientIdType::ConnectorId(id)) => Some(id.clone()),
                    _ => None,
                },
            },
            MerchantAccountData::Plusgiro {
                number,
                name,
                connector_recipient_id,
            } => Self::Plusgiro {
                number,
                name,
                connector_recipient_id: match connector_recipient_id {
                    Some(RecipientIdType::ConnectorId(id)) => Some(id.clone()),
                    _ => None,
                },
            },
        }
    }
}

impl From<api_models::admin::MerchantAccountData> for MerchantAccountData {
    fn from(from: api_models::admin::MerchantAccountData) -> Self {
        match from {
            api_models::admin::MerchantAccountData::Iban {
                iban,
                name,
                connector_recipient_id,
            } => Self::Iban {
                iban,
                name,
                connector_recipient_id: connector_recipient_id.map(RecipientIdType::ConnectorId),
            },
            api_models::admin::MerchantAccountData::Bacs {
                account_number,
                sort_code,
                name,
                connector_recipient_id,
            } => Self::Bacs {
                account_number,
                sort_code,
                name,
                connector_recipient_id: connector_recipient_id.map(RecipientIdType::ConnectorId),
            },
            api_models::admin::MerchantAccountData::FasterPayments {
                account_number,
                sort_code,
                name,
                connector_recipient_id,
            } => Self::FasterPayments {
                account_number,
                sort_code,
                name,
                connector_recipient_id: connector_recipient_id.map(RecipientIdType::ConnectorId),
            },
            api_models::admin::MerchantAccountData::Sepa {
                iban,
                name,
                connector_recipient_id,
            } => Self::Sepa {
                iban,
                name,
                connector_recipient_id: connector_recipient_id.map(RecipientIdType::ConnectorId),
            },
            api_models::admin::MerchantAccountData::SepaInstant {
                iban,
                name,
                connector_recipient_id,
            } => Self::SepaInstant {
                iban,
                name,
                connector_recipient_id: connector_recipient_id.map(RecipientIdType::ConnectorId),
            },
            api_models::admin::MerchantAccountData::Elixir {
                account_number,
                iban,
                name,
                connector_recipient_id,
            } => Self::Elixir {
                account_number,
                iban,
                name,
                connector_recipient_id: connector_recipient_id.map(RecipientIdType::ConnectorId),
            },
            api_models::admin::MerchantAccountData::Bankgiro {
                number,
                name,
                connector_recipient_id,
            } => Self::Bankgiro {
                number,
                name,
                connector_recipient_id: connector_recipient_id.map(RecipientIdType::ConnectorId),
            },
            api_models::admin::MerchantAccountData::Plusgiro {
                number,
                name,
                connector_recipient_id,
            } => Self::Plusgiro {
                number,
                name,
                connector_recipient_id: connector_recipient_id.map(RecipientIdType::ConnectorId),
            },
        }
    }
}
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "snake_case")]
pub enum MerchantRecipientData {
    ConnectorRecipientId(Secret<String>),
    WalletId(Secret<String>),
    AccountData(MerchantAccountData),
}

impl ForeignFrom<MerchantRecipientData> for api_models::admin::MerchantRecipientData {
    fn foreign_from(value: MerchantRecipientData) -> Self {
        match value {
            MerchantRecipientData::ConnectorRecipientId(id) => Self::ConnectorRecipientId(id),
            MerchantRecipientData::WalletId(id) => Self::WalletId(id),
            MerchantRecipientData::AccountData(data) => {
                Self::AccountData(api_models::admin::MerchantAccountData::foreign_from(data))
            }
        }
    }
}

impl From<api_models::admin::MerchantRecipientData> for MerchantRecipientData {


impl api::PaymentSync for Itaubank {}


File: crates/hyperswitch_connectors/src/connectors/nordea/responses.rs
 Public structs: 16

use common_enums::CountryAlpha2;
use common_utils::types::StringMajorUnit;
use masking::Secret;
use serde::{Deserialize, Serialize};

use super::requests::{
    CreditorAccount, DebitorAccount, InstructedAmount, PaymentsUrgency, RecurringInformation,
    ThirdPartyMessages,
};

// OAuth token response structure
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct NordeaOAuthExchangeResponse {
    pub access_token: Option<Secret<String>>,
    pub expires_in: Option<i64>,
    pub refresh_token: Option<Secret<String>>,
    pub token_type: Option<String>,
}

#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "PascalCase")]
pub enum NordeaPaymentStatus {
    #[default]
    PendingConfirmation,
    PendingSecondConfirmation,
    PendingUserApproval,
    OnHold,
    Confirmed,
    Rejected,
    Paid,
    InsufficientFunds,
    LimitExceeded,
    UserApprovalFailed,
    UserApprovalTimeout,
    UserApprovalCancelled,
    Unknown,
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct NordeaGroupHeader {
    /// Response creation time. Format: date-time.
    pub creation_date_time: Option<String>,
    /// HTTP code for response. Format: int32.
    pub http_code: Option<i32>,
    /// Original request id for correlation purposes
    pub message_identification: Option<String>,
    /// Details of paginated response
    pub message_pagination: Option<MessagePagination>,
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct NordeaResponseLinks {
    /// Describes the nature of the link, e.g. 'details' for a link to the detailed information of a listed resource.
    pub rel: Option<String>,
    /// Relative path to the linked resource
    pub href: Option<String>,
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum FeesType {
    Additional,
    Standard,
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct TransactionFee {
    /// Monetary amount
    pub amount: InstructedAmount,
    pub description: Option<String>,
    pub excluded_from_total_fee: Option<bool>,
    pub percentage: Option<bool>,
    #[serde(rename = "type")]
    pub fees_type: Option<FeesType>,
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct BankFee {
    /// Example 'domestic_transaction' only for DK domestic payments
    #[serde(rename = "_type")]
    pub bank_fee_type: Option<String>,
    /// Country code according to ISO Alpha-2
    pub country_code: Option<CountryAlpha2>,
    /// Currency code according to ISO 4217
    pub currency_code: Option<api_models::enums::Currency>,
    /// Value of the fee.
    pub value: Option<StringMajorUnit>,
    pub fees: Option<Vec<TransactionFee>>,
    /// Monetary amount
    pub total_fee_amount: InstructedAmount,
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "lowercase")]
pub enum ChargeBearer {
    Shar,
    Debt,
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct ExchangeRate {
    pub base_currency: Option<api_models::enums::Currency>,
    pub exchange_currency: Option<api_models::enums::Currency>,
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct MessagePagination {
    /// Resource listing may return a continuationKey if there's more results available.
    /// Request may be retried with the continuationKey, but otherwise same parameters, in order to get more results.
    pub continuation_key: Option<String>,
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct NordeaPaymentsInitiateResponseData {
    /// Unique payment identifier assigned for new payment
    #[serde(rename = "_id")]
    pub payment_id: String,
    /// HATEOAS inspired links: 'rel' and 'href'. Context specific link (only GET supported)
    #[serde(rename = "_links")]
    pub links: Option<Vec<NordeaResponseLinks>>,
    /// Marked as required field in the docs, but connector does not send amount in payment_response.amount
    pub amount: Option<StringMajorUnit>,
    /// Bearer of charges. shar = The Debtor (sender of the payment) will pay all fees charged by the sending bank.
    /// The Creditor (recipient of the payment) will pay all fees charged by the receiving bank.
    /// debt = The Debtor (sender of the payment) will bear all of the payment transaction fees.
    /// The creditor (beneficiary) will receive the full amount of the payment.
    pub charge_bearer: Option<ChargeBearer>,
    /// Creditor of the payment
    #[serde(rename = "creditor")]
    pub creditor_account: CreditorAccount,
    pub currency: Option<api_models::enums::Currency>,
    /// Debtor of the payment
    #[serde(rename = "debtor")]
    pub debitor_account: Option<DebitorAccount>,
    /// Timestamp of payment creation. ISO 8601 format yyyy-mm-ddThh:mm:ss.fffZ. Format:date-time.
    pub entry_date_time: Option<String>,
    /// Unique identification as assigned by a partner to identify the payment.
    pub external_id: Option<String>,
    /// An amount the bank will charge for executing the payment
    pub fee: Option<BankFee>,
    pub indicative_exchange_rate: Option<ExchangeRate>,
    /// It is mentioned as `number`. It can be an integer or a decimal number.
    pub rate: Option<f32>,
    /// Monetary amount
    pub instructed_amount: Option<InstructedAmount>,
    /// Indication of cross border payment to own account
    pub is_own_account_transfer: Option<bool>,
    /// OTP Challenge
    pub otp_challenge: Option<String>,
    /// Status of the payment
    pub payment_status: NordeaPaymentStatus,
    /// Planned execution date will indicate the day the payment will be finalized. If the payment has been pushed due to cut-off, it will be indicated in planned execution date. Format:date.
    pub planned_execution_date: Option<String>,
    /// Recurring information
    pub recurring: Option<RecurringInformation>,
    /// Choose a preferred execution date (or leave blank for today's date).
    /// This should be a valid bank day, and depending on the country the date will either be pushed to the next valid bank day,
    /// or return an error if a non-banking day date was supplied (all dates accepted in sandbox).
    /// SEPA: max +5 years from yesterday, Domestic: max. +1 year from yesterday. NB: Not supported for Own transfer Non-Recurring Norway.
    /// Format:date.
    pub requested_execution_date: Option<String>,
    /// Timestamp of payment creation. ISO 8601 format yyyy-mm-ddThh:mm:ss.fffZ Format:date-time.
    pub timestamp: Option<String>,
    /// Additional messages for third parties
    pub tpp_messages: Option<Vec<ThirdPartyMessages>>,
    pub transaction_fee: Option<Vec<BankFee>>,
    /// Currency that the cross border payment will be transferred in.
    /// This field is only supported for cross border payments for DK.
    /// If this field is not supplied then the payment will use the currency specified for the currency field of instructed_amount.
    pub transfer_currency: Option<api_models::enums::Currency>,
    /// Urgency of the payment. NB: This field is supported for DK Domestic ('standard' and 'express') and NO Domestic bank transfer payments ('standard' and 'express').
    /// Use 'express' for Straksbetaling (Instant payment).
    /// All other payment types ignore this input.
    /// For further details on urgencies and cut-offs, refer to the Nordea website.
    /// Value 'sameday' is marked as deprecated and will be removed in the future.
    pub urgency: Option<PaymentsUrgency>,
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct NordeaPaymentsInitiateResponse {
    /// Payment information
    #[serde(rename = "response")]
    pub payments_response: Option<NordeaPaymentsInitiateResponseData>,
    /// External response header
    pub group_header: Option<NordeaGroupHeader>,
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct NordeaPaymentsConfirmErrorObject {
    /// Error message
    pub error: Option<String>,
    /// Description of the error
    pub error_description: Option<String>,
    /// Payment id of the payment, the error is associated with
    pub payment_id: Option<String>,
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct NordeaPaymentsResponseWrapper {
    pub payments: Vec<NordeaPaymentsInitiateResponseData>,
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct NordeaPaymentsConfirmResponse {
    /// HATEOAS inspired links: 'rel' and 'href'
    #[serde(rename = "_links")]
    pub links: Option<Vec<NordeaResponseLinks>>,
    /// Error description
    pub errors: Option<Vec<NordeaPaymentsConfirmErrorObject>>,
    /// External response header
    pub group_header: Option<NordeaGroupHeader>,
    /// OTP Challenge
    pub otp_challenge: Option<String>,
    #[serde(rename = "response")]
    pub nordea_payments_response: Option<NordeaPaymentsResponseWrapper>,
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct NordeaOriginalRequest {
    /// Original request url
    #[serde(rename = "url")]
    pub nordea_url: Option<String>,
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct NordeaFailures {
    /// Failure code
    pub code: Option<String>,
    /// Failure description
    pub description: Option<String>,
    /// JSON path of the failing element if applicable
    pub path: Option<String>,
    /// Type of the validation error, e.g. NotNull
    #[serde(rename = "type")]
    pub failure_type: Option<String>,
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct NordeaErrorBody {
    // Serde JSON because connector returns an `(item)` object in failures array object
    /// More details on the occurred error: Validation error
    #[serde(rename = "failures")]
    pub nordea_failures: Option<Vec<NordeaFailures>>,
    /// Original request information
    #[serde(rename = "request")]
    pub nordea_request: Option<NordeaOriginalRequest>,
}

#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct NordeaErrorResponse {
    /// Error response body
    pub error: Option<NordeaErrorBody>,
    /// External response header
    pub group_header: Option<NordeaGroupHeader>,
    #[serde(rename = "httpCode")]
    pub http_code: Option<String>,
    #[serde(rename = "moreInformation")]
    pub more_information: Option<String>,
}

// Nordea does not support refunds in Private APIs. Only Corporate APIs support Refunds


pub struct GetRefundFilterRequest {
    pub time_range: TimeRange,
    #[serde(default)]
    pub group_by_names: Vec<RefundDimensions>,
}


pub struct RelayNew {
    pub id: common_utils::id_type::RelayId,
    pub connector_resource_id: String,
    pub connector_id: common_utils::id_type::MerchantConnectorAccountId,
    pub profile_id: common_utils::id_type::ProfileId,
    pub merchant_id: common_utils::id_type::MerchantId,
    pub relay_type: storage_enums::RelayType,
    pub request_data: Option<pii::SecretSerdeValue>,
    pub status: storage_enums::RelayStatus,
    pub connector_reference_id: Option<String>,
    pub error_code: Option<String>,
    pub error_message: Option<String>,
    #[serde(with = "common_utils::custom_serde::iso8601")]
    pub created_at: PrimitiveDateTime,
    #[serde(with = "common_utils::custom_serde::iso8601")]
    pub modified_at: PrimitiveDateTime,
    pub response_data: Option<pii::SecretSerdeValue>,
}


pub struct HyperswitchVault;


pub struct MonerisRefundRequest {
    pub refund_amount: Amount,
    pub idempotency_key: String,
    pub reason: Option<String>,
    pub payment_id: String,
}


impl CustomerAcceptance {
    /// Get the IP address
    pub fn get_ip_address(&self) -> Option<String> {
        self.online
            .as_ref()
            .and_then(|data| data.ip_address.as_ref().map(|ip| ip.peek().to_owned()))
    }

    /// Get the User Agent
    pub fn get_user_agent(&self) -> Option<String> {
        self.online.as_ref().map(|data| data.user_agent.clone())
    }

    /// Get when the customer acceptance was provided
    pub fn get_accepted_at(&self) -> PrimitiveDateTime {
        self.accepted_at.unwrap_or_else(date_time::now)
    }
}


impl Responder {
    let algorithm_id = path.into_inner();
    let flow = Flow::RoutingRetrieveConfig;
    Box::pin(oss_api::server_wrap(
        flow,
        state,
        &req,
        algorithm_id,
        |state, auth: auth::AuthenticationData, algorithm_id, _| {
            let merchant_context = domain::MerchantContext::NormalMerchant(Box::new(
                domain::Context(auth.merchant_account, auth.key_store),
            ));
            routing::retrieve_routing_algorithm_from_algorithm_id(
                state,
                merchant_context,
                auth.profile_id,
                algorithm_id,
            )
        },
        auth::auth_type(
            &auth::HeaderAuth(auth::ApiKeyAuth {
                is_connected_allowed: false,
                is_platform_allowed: false,
            }),
            &auth::JWTAuth {
                permission: Permission::ProfileRoutingRead,
            },
            req.headers(),
        ),
        api_locking::LockAction::NotApplicable,
    ))
    .await
}


impl api::PaymentsCreateOrder for Razorpay {}

impl api::PaymentsCreateOrder for for Razorpay


pub struct XenditPaymentsCaptureRequest {
    pub capture_amount: FloatMajorUnit,
}


impl Responder {
    use hyperswitch_domain_models::payments::PaymentIntentData;

    let flow = Flow::PaymentsCreateIntent;
    let header_payload = match HeaderPayload::foreign_try_from(req.headers()) {
        Ok(headers) => headers,
        Err(err) => {
            return api::log_and_return_error_response(err);
        }
    };
    let global_payment_id =
        common_utils::id_type::GlobalPaymentId::generate(&state.conf.cell_information.id);

    Box::pin(api::server_wrap(
        flow,
        state,
        &req,
        json_payload.into_inner(),
        |state, auth: auth::AuthenticationData, req, req_state| {
            let merchant_context = domain::MerchantContext::NormalMerchant(Box::new(
                domain::Context(auth.merchant_account, auth.key_store),
            ));

            payments::payments_intent_core::<
                api_types::PaymentCreateIntent,
                payment_types::PaymentsIntentResponse,
                _,
                _,
                PaymentIntentData<api_types::PaymentCreateIntent>,
            >(
                state,
                req_state,
                merchant_context,
                auth.profile,
                payments::operations::PaymentIntentCreate,
                req,
                global_payment_id.clone(),
                header_payload.clone(),
            )
        },
        match env::which() {
            env::Env::Production => &auth::V2ApiKeyAuth {
                is_connected_allowed: false,
                is_platform_allowed: false,
            },
            _ => auth::auth_type(
                &auth::V2ApiKeyAuth {
                    is_connected_allowed: false,
                    is_platform_allowed: false,
                },
                &auth::JWTAuth {
                    permission: Permission::ProfilePaymentWrite,
                },
                req.headers(),
            ),
        },
        api_locking::LockAction::NotApplicable,
    ))
    .await
}


impl RoutingEvent {
    /// fn new RoutingEvent
    #[allow(clippy::too_many_arguments)]
    pub fn new(
        tenant_id: common_utils::id_type::TenantId,
        routable_connectors: String,
        flow: &str,
        request: serde_json::Value,
        url: String,
        method: ApiMethod,
        payment_id: String,
        profile_id: common_utils::id_type::ProfileId,
        merchant_id: common_utils::id_type::MerchantId,
        request_id: Option<RequestId>,
        routing_engine: RoutingEngine,
    ) -> Self {
        Self {
            tenant_id,
            routable_connectors,
            flow: flow.to_string(),
            request: request.to_string(),
            response: None,
            error: None,
            url,
            method: method.to_string(),
            payment_id,
            profile_id,
            merchant_id,
            created_at: OffsetDateTime::now_utc().unix_timestamp_nanos(),
            status_code: None,
            request_id: request_id
                .map(|i| i.as_hyphenated().to_string())
                .unwrap_or("NO_REQUEST_ID".to_string()),
            routing_engine,
            payment_connector: None,
            routing_approach: None,
        }
    }

    /// fn set_response_body
    pub fn set_response_body<T: Serialize>(&mut self, response: &T) {
        match masking::masked_serialize(response) {
            Ok(masked) => {
                self.response = Some(masked.to_string());
            }
            Err(er) => self.set_error(json!({"error": er.to_string()})),
        }
    }

    /// fn set_error_response_body
    pub fn set_error_response_body<T: Serialize>(&mut self, response: &T) {
        match masking::masked_serialize(response) {
            Ok(masked) => {
                self.error = Some(masked.to_string());
            }
            Err(er) => self.set_error(json!({"error": er.to_string()})),
        }
    }

    /// fn set_error
    pub fn set_error(&mut self, error: serde_json::Value) {
        self.error = Some(error.to_string());
    }

    /// set response status code
    pub fn set_status_code(&mut self, code: u16) {
        self.status_code = Some(code);
    }

    /// set response status code
    pub fn set_routable_connectors(&mut self, connectors: Vec<RoutableConnectorChoice>) {
        let connectors = connectors
            .into_iter()
            .map(|c| {
                format!(
                    "{:?}:{:?}",
                    c.connector,
                    c.merchant_connector_id
                        .map(|id| id.get_string_repr().to_string())
                        .unwrap_or(String::from(""))
                )
            })
            .collect::<Vec<_>>()
            .join(",");
        self.routable_connectors = connectors;
    }

    /// set payment connector
    pub fn set_payment_connector(&mut self, connector: RoutableConnectorChoice) {
        self.payment_connector = Some(format!(
            "{:?}:{:?}",
            connector.connector,
            connector
                .merchant_connector_id
                .map(|id| id.get_string_repr().to_string())
                .unwrap_or(String::from(""))
        ));
    }

    /// set routing approach
    pub fn set_routing_approach(&mut self, approach: String) {
        self.routing_approach = Some(approach);
    }

    /// Returns the request ID of the event.
    pub fn get_request_id(&self) -> &str {
        &self.request_id
    }

    /// Returns the merchant ID of the event.
    pub fn get_merchant_id(&self) -> &str {
        self.merchant_id.get_string_repr()
    }

    /// Returns the payment ID of the event.
    pub fn get_payment_id(&self) -> &str {
        &self.payment_id
    }

    /// Returns the profile ID of the event.
    pub fn get_profile_id(&self) -> &str {
        self.profile_id.get_string_repr()
    }
}


impl api::MandateSetup for Vgs {}


impl Responder {
    let flow = Flow::ApiKeyList;
    let payload = query.into_inner();

    Box::pin(api::server_wrap(
        flow,
        state,
        &req,
        payload,
        |state,
         auth::AuthenticationDataWithoutProfile {
             merchant_account, ..
         },
         payload,
         _| async move {
            let merchant_id = merchant_account.get_id().to_owned();
            api_keys::list_api_keys(state, merchant_id, payload.limit, payload.skip).await
        },
        auth::auth_type(
            &auth::AdminApiAuthWithMerchantIdFromHeader,
            &auth::JWTAuthMerchantFromHeader {
                required_permission: Permission::MerchantApiKeyRead,
            },
            req.headers(),
        ),
        api_locking::LockAction::NotApplicable,
    ))
    .await
}


pub struct EliminationRoutingEventBucketConfig {
    pub bucket_size: Option<u64>,
    pub bucket_leak_interval_in_secs: Option<u64>,
}


pub struct PaypalConfirmTransactionRequest {
    merchant_authentication: AuthorizedotnetAuthType,
    transaction_request: TransactionConfirmRequest,
}


impl MerchantCategoryCode {
    pub fn to_merchant_category_name(&self) -> MerchantCategory {
        match self {
            Self::Mcc5411 => MerchantCategory::GroceryStoresSupermarkets,
            Self::Mcc7011 => MerchantCategory::LodgingHotelsMotelsResorts,
            Self::Mcc0763 => MerchantCategory::AgriculturalCooperatives,
            Self::Mcc8111 => MerchantCategory::AttorneysLegalServices,
            Self::Mcc5021 => MerchantCategory::OfficeAndCommercialFurniture,
            Self::Mcc4816 => MerchantCategory::ComputerNetworkInformationServices,
            Self::Mcc5661 => MerchantCategory::ShoeStores,
        }
    }
}


impl api::PaymentSession for Worldline {}

impl api::PaymentSession for for Worldline


impl api::PaymentToken for Amazonpay {}

impl api::PaymentToken for for Amazonpay


impl Profile {
    pub fn server(state: AppState) -> Scope {
        web::scope("/v2/profiles")
            .app_data(web::Data::new(state))
            .service(web::resource("").route(web::post().to(profiles::profile_create)))
            .service(
                web::scope("/{profile_id}")
                    .service(
                        web::resource("")
                            .route(web::get().to(profiles::profile_retrieve))
                            .route(web::put().to(profiles::profile_update)),
                    )
                    .service(
                        web::resource("/connector-accounts")
                            .route(web::get().to(admin::connector_list)),
                    )
                    .service(
                        web::resource("/fallback-routing")
                            .route(web::get().to(routing::routing_retrieve_default_config))
                            .route(web::patch().to(routing::routing_update_default_config)),
                    )
                    .service(
                        web::resource("/activate-routing-algorithm").route(web::patch().to(
                            |state, req, path, payload| {
                                routing::routing_link_config(
                                    state,
                                    req,
                                    path,
                                    payload,
                                    &TransactionType::Payment,
                                )
                            },
                        )),
                    )
                    .service(
                        web::resource("/deactivate-routing-algorithm").route(web::patch().to(
                            |state, req, path| {
                                routing::routing_unlink_config(
                                    state,
                                    req,
                                    path,
                                    &TransactionType::Payment,
                                )
                            },
                        )),
                    )
                    .service(web::resource("/routing-algorithm").route(web::get().to(
                        |state, req, query_params, path| {
                            routing::routing_retrieve_linked_config(
                                state,
                                req,
                                query_params,
                                path,
                                &TransactionType::Payment,
                            )
                        },
                    )))
                    .service(
                        web::resource("/decision")
                            .route(web::put().to(routing::upsert_decision_manager_config))
                            .route(web::get().to(routing::retrieve_decision_manager_config)),
                    ),
            )
    }
}


pub struct DummyConnectorPaymentResponse {
    pub status: DummyConnectorStatus,
    pub id: common_utils::id_type::PaymentId,
    pub amount: i64,
    pub currency: Currency,
    #[serde(with = "common_utils::custom_serde::iso8601")]
    pub created: PrimitiveDateTime,
    pub payment_method_type: DummyConnectorPaymentMethodType,
    pub next_action: Option<DummyConnectorNextAction>,
}


pub struct NexixpayCard {
    pan: CardNumber,
    expiry_date: Secret<String>,
}


pub fn server(state: AppState) -> Scope {
        web::scope("/v2/verify")
            .app_data(web::Data::new(state))
            .service(
                web::resource("/apple-pay/{merchant_id}")
                    .route(web::post().to(apple_pay_merchant_registration)),
            )
            .service(
                web::resource("/applepay-verified-domains")
                    .route(web::get().to(retrieve_apple_pay_verified_domains)),
            )
    }


pub fn perform_straight_through_routing(
    algorithm: &routing_types::StraightThroughAlgorithm,
    creds_identifier: Option<&str>,
) -> RoutingResult<(Vec<routing_types::RoutableConnectorChoice>, bool)> {
    Ok(match algorithm {
        routing_types::StraightThroughAlgorithm::Single(conn) => {
            (vec![(**conn).clone()], creds_identifier.is_none())
        }

        routing_types::StraightThroughAlgorithm::Priority(conns) => (conns.clone(), true),

        routing_types::StraightThroughAlgorithm::VolumeSplit(splits) => (
            perform_volume_split(splits.to_vec())
                .change_context(errors::RoutingError::ConnectorSelectionFailed)
                .attach_printable(
                    "Volume Split connector selection error in straight through routing",
                )?,
            true,
        ),
    })
}


impl FraudCheckCheckout for Riskified {}

impl FraudCheckCheckout for for Riskified


pub struct RoutingProfileMetadata {
    pub profile_id: id_type::ProfileId,
    pub algorithm_id: id_type::RoutingId,
    pub name: String,
    pub description: Option<String>,
    pub kind: enums::RoutingAlgorithmKind,
    pub created_at: time::PrimitiveDateTime,
    pub modified_at: time::PrimitiveDateTime,
    pub algorithm_for: enums::TransactionType,
}


pub struct ThreeDsCheck {
    pub enrollment_status: Option<EnrollmentStatus>,
    pub authentication_status: Option<AuthenticationStatus>,
}


pub struct StripeConnectPayoutFulfillResponse {
    id: String,
    currency: String,
    description: Option<String>,
    failure_balance_transaction: Option<String>,
    failure_code: Option<String>,
    failure_message: Option<String>,
    original_payout: Option<String>,
    reversed_by: Option<String>,
    statement_descriptor: Option<String>,
    status: StripeConnectPayoutStatus,
}


pub struct Organization {
    pub organization_details: Option<pii::SecretSerdeValue>,
    pub metadata: Option<pii::SecretSerdeValue>,
    pub created_at: time::PrimitiveDateTime,
    pub modified_at: time::PrimitiveDateTime,
    id: id_type::OrganizationId,
    organization_name: Option<String>,
    pub version: common_enums::ApiVersion,
    pub organization_type: Option<common_enums::OrganizationType>,
    pub platform_merchant_id: Option<id_type::MerchantId>,
}


impl api::PaymentSync for Iatapay {}


/// Fee information for Split Payments to be charged on the payment being collected for Stripe
pub struct StripeSplitPaymentRequest {
    /// Stripe's charge type
    #[schema(value_type = PaymentChargeType, example = "direct")]
    pub charge_type: enums::PaymentChargeType,

    /// Platform fees to be collected on the payment
    #[schema(value_type = i64, example = 6540)]
    pub application_fees: Option<MinorUnit>,

    /// Identifier for the reseller's account where the funds were transferred
    pub transfer_account_id: String,
}


pub struct MerchantURLs {
    terms: String,
    checkout: String,
    confirmation: String,
    push: String,
}


pub struct SuccessfulTransactionData {
    id: String,
    decision: TransactionDecisionData,
}


impl ConnectorValidation for Checkout {
    fn validate_connector_against_payment_request(
        &self,
        capture_method: Option<enums::CaptureMethod>,
        _payment_method: enums::PaymentMethod,
        _pmt: Option<enums::PaymentMethodType>,
    ) -> CustomResult<(), errors::ConnectorError> {
        let capture_method = capture_method.unwrap_or_default();
        match capture_method {
            enums::CaptureMethod::Automatic
            | enums::CaptureMethod::SequentialAutomatic
            | enums::CaptureMethod::Manual
            | enums::CaptureMethod::ManualMultiple => Ok(()),
            enums::CaptureMethod::Scheduled => Err(utils::construct_not_implemented_error_report(
                capture_method,
                self.id(),
            )),
        }
    }
}

impl ConnectorValidation for for Checkout


pub fn validate(&self) -> Result<(), errors::DrainerError> {
        self.server.validate()?;
        self.master_database.get_inner().validate()?;

        // The logger may not yet be initialized when validating the application configuration
        #[allow(clippy::print_stderr)]
        self.redis.validate().map_err(|error| {
            eprintln!("{error}");
            errors::DrainerError::ConfigParsingError("invalid Redis configuration".into())
        })?;
        self.drainer.validate()?;

        // The logger may not yet be initialized when validating the application configuration
        #[allow(clippy::print_stderr)]
        self.secrets_management.validate().map_err(|error| {
            eprintln!("{error}");
            errors::DrainerError::ConfigParsingError(
                "invalid secrets management configuration".into(),
            )
        })?;

        // The logger may not yet be initialized when validating the application configuration
        #[allow(clippy::print_stderr)]
        self.encryption_management.validate().map_err(|error| {
            eprintln!("{error}");
            errors::DrainerError::ConfigParsingError(
                "invalid encryption management configuration".into(),
            )
        })?;

        Ok(())
    }


File: crates/api_models/src/conditional_configs.rs
 Public structs: 4

use common_utils::events;
use euclid::frontend::ast::Program;

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct DecisionManagerRecord {
    pub name: String,
    pub program: Program<common_types::payments::ConditionalConfigs>,
    pub created_at: i64,
    pub modified_at: i64,
}
impl events::ApiEventMetric for DecisionManagerRecord {
    fn get_api_event_type(&self) -> Option<events::ApiEventsType> {
        Some(events::ApiEventsType::Routing)
    }
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
#[serde(deny_unknown_fields)]
pub struct ConditionalConfigReq {
    pub name: Option<String>,
    pub algorithm: Option<Program<common_types::payments::ConditionalConfigs>>,
}

#[cfg(feature = "v1")]
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct DecisionManagerRequest {
    pub name: Option<String>,
    pub program: Option<Program<common_types::payments::ConditionalConfigs>>,
}

#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
#[serde(untagged)]
pub enum DecisionManager {
    DecisionManagerv0(ConditionalConfigReq),
    DecisionManagerv1(DecisionManagerRequest),
}

impl events::ApiEventMetric for DecisionManager {
    fn get_api_event_type(&self) -> Option<events::ApiEventsType> {
        Some(events::ApiEventsType::Routing)
    }
}

pub type DecisionManagerResponse = DecisionManagerRecord;

#[cfg(feature = "v2")]
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct DecisionManagerRequest {
    pub name: String,
    pub program: Program<common_types::payments::ConditionalConfigs>,
}

#[cfg(feature = "v2")]
impl events::ApiEventMetric for DecisionManagerRequest {
    fn get_api_event_type(&self) -> Option<events::ApiEventsType> {
        Some(events::ApiEventsType::Routing)
    }
}


impl Hash for PaymentIntentMetricsBucketIdentifier {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.status.map(|i| i.to_string()).hash(state);
        self.currency.hash(state);
        self.profile_id.hash(state);
        self.connector.hash(state);
        self.auth_type.map(|i| i.to_string()).hash(state);
        self.payment_method.hash(state);
        self.payment_method_type.hash(state);
        self.card_network.hash(state);
        self.merchant_id.hash(state);
        self.card_last_4.hash(state);
        self.card_issuer.hash(state);
        self.error_reason.hash(state);
        self.time_bucket.hash(state);
    }
}

impl Hash for for PaymentIntentMetricsBucketIdentifier


pub struct SquarePaymentsResponseDetails {
    status: SquarePaymentStatus,
    id: String,
    amount_money: SquarePaymentsAmountData,
    reference_id: Option<String>,
}


pub async fn retry_webhook_delivery_attempt(
    state: web::Data<AppState>,
    req: HttpRequest,
    path: web::Path<(common_utils::id_type::MerchantId, String)


pub struct StripeConnectReversalRequest {
    amount: i64,
}


pub async fn list_user_authentication_methods(
    state: SessionState,
    req: user_api::GetUserAuthenticationMethodsRequest,
) -> UserResponse<Vec<user_api::UserAuthenticationMethodResponse>> {
    let user_authentication_methods = match (req.auth_id, req.email_domain) {
        (Some(auth_id), None) => state
            .store
            .list_user_authentication_methods_for_auth_id(&auth_id)
            .await
            .change_context(UserErrors::InternalServerError)?,
        (None, Some(email_domain)) => state
            .store
            .list_user_authentication_methods_for_email_domain(&email_domain)
            .await
            .change_context(UserErrors::InternalServerError)?,
        (Some(_), Some(_)) | (None, None) => {
            return Err(UserErrors::InvalidUserAuthMethodOperation.into());
        }
    };

    Ok(ApplicationResponse::Json(
        user_authentication_methods
            .into_iter()
            .map(|auth_method| {
                let auth_name = match (auth_method.auth_type, auth_method.public_config) {
                    (UserAuthType::OpenIdConnect, config) => {
                        let open_id_public_config: Option<user_api::OpenIdConnectPublicConfig> =
                            config
                                .map(|config| {
                                    utils::user::parse_value(config, "OpenIdConnectPublicConfig")
                                })
                                .transpose()?;
                        if let Some(public_config) = open_id_public_config {
                            Ok(Some(public_config.name))
                        } else {
                            Err(report!(UserErrors::InternalServerError))
                                .attach_printable("Public config not found for OIDC auth type")
                        }
                    }
                    _ => Ok(None),
                }?;

                Ok(user_api::UserAuthenticationMethodResponse {
                    id: auth_method.id,
                    auth_id: auth_method.auth_id,
                    auth_method: user_api::AuthMethodDetails {
                        name: auth_name,
                        auth_type: auth_method.auth_type,
                    },
                    allow_signup: auth_method.allow_signup,
                })
            })
            .collect::<UserResult<_>>()?,
    ))
}


pub fn get_end_date(
        &self,
        format: date_time::DateFormat,
    ) -> error_stack::Result<Option<String>, ParsingError> {
        self.end_date
            .map(|date| {
                date_time::format_date(date, format)
                    .change_context(ParsingError::DateTimeParsingError)
            })
            .transpose()
    }


impl<T: DatabaseStore> RedisConnInterface for KVRouterStore<T> {
    fn get_redis_conn(&self) -> error_stack::Result<Arc<RedisConnectionPool>, RedisError> {
        self.router_store.get_redis_conn()
    }
}

impl RedisConnInterface for for KVRouterStore