// Struct: Digitalvirgo
// File: crates/hyperswitch_connectors/src/connectors/digitalvirgo.rs
// Module: hyperswitch_connectors
// Implementations: 19
// Traits: api::Payment, api::PaymentSession, api::ConnectorAccessToken, api::MandateSetup, api::PaymentAuthorize, api::PaymentSync, api::PaymentCapture, api::PaymentVoid, api::Refund, api::RefundExecute, api::RefundSync, api::PaymentToken, api::PaymentsCompleteAuthorize, ConnectorCommon, ConnectorValidation, ConnectorRedirectResponse, webhooks::IncomingWebhook, ConnectorSpecifications

pub struct Digitalvirgo

api::Payment api::PaymentSession api::ConnectorAccessToken api::MandateSetup api::PaymentAuthorize api::PaymentSync api::PaymentCapture api::PaymentVoid api::Refund api::RefundExecute api::RefundSync api::PaymentToken api::PaymentsCompleteAuthorize ConnectorCommon ConnectorValidation ConnectorRedirectResponse webhooks::IncomingWebhook ConnectorSpecifications


// Implementation: impl api::PaymentSession for for Placetopay
// File: crates/hyperswitch_connectors/src/connectors/placetopay.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::PaymentSession for for Placetopay


// Function: collect
// File: crates/analytics/src/sdk_events/accumulator.rs
// Module: analytics

pub fn collect(self) -> SdkEventMetricsBucketValue


// Struct: ValueData
// File: crates/euclid/src/dssa/types.rs
// Module: euclid
// Implementations: 0

pub struct ValueData


// Struct: DisputeEvidenceBlock
// File: crates/api_models/src/disputes.rs
// Module: api_models
// Implementations: 0

pub struct DisputeEvidenceBlock


// Implementation: impl ValidateStatusForOperation for for PaymentUpdateIntent
// File: crates/router/src/core/payments/operations/payment_update_intent.rs
// Module: router
// Methods: 1 total (0 public)

impl ValidateStatusForOperation for for PaymentUpdateIntent


// Trait: NuveiPaymentsGenericResponse
// File: crates/hyperswitch_connectors/src/connectors/nuvei/transformers.rs
// Module: hyperswitch_connectors

pub trait NuveiPaymentsGenericResponse


// Implementation: impl RequiredFieldsInput
// File: crates/router/src/core/payments/payment_methods.rs
// Module: router
// Methods: 1 total (0 public)

impl RequiredFieldsInput


// Struct: PayloadRefundRequest
// File: crates/hyperswitch_connectors/src/connectors/payload/requests.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct PayloadRefundRequest


// Implementation: impl ConnectorValidation for for Checkbook
// File: crates/hyperswitch_connectors/src/connectors/checkbook.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl ConnectorValidation for for Checkbook


// Struct: AttachPayoutAccountWorkflow
// File: crates/router/src/workflows/attach_payout_account_workflow.rs
// Module: router
// Implementations: 0

pub struct AttachPayoutAccountWorkflow


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

// Public submodules:
pub mod transformers;


// Struct: FiservemeaRouterData
// File: crates/hyperswitch_connectors/src/connectors/fiservemea/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct FiservemeaRouterData<T>


// Implementation: impl Health
// File: crates/router/src/routes/app.rs
// Module: router
// Methods: 1 total (1 public)

impl Health


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

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


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

impl ConnectorSpecifications for for Adyen


// Function: find_by_role_id_in_lineage
// File: crates/diesel_models/src/query/role.rs
// Module: diesel_models

pub fn find_by_role_id_in_lineage(
        conn: &PgPooledConn,
        role_id: &str,
        merchant_id: &id_type::MerchantId,
        org_id: &id_type::OrganizationId,
        profile_id: &id_type::ProfileId,
        tenant_id: &id_type::TenantId,
    ) -> StorageResult<Self>


// Struct: NetworkTokenization
// File: crates/common_types/src/payment_methods.rs
// Module: common_types
// Implementations: 0

pub struct NetworkTokenization


// Implementation: impl common_utils::events::ApiEventMetric for for EventRetrieveResponse
// File: crates/api_models/src/webhook_events.rs
// Module: api_models
// Methods: 1 total (0 public)

impl common_utils::events::ApiEventMetric for for EventRetrieveResponse


// Struct: CybersourceNotAvailableErrorObject
// File: crates/hyperswitch_connectors/src/connectors/cybersource/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct CybersourceNotAvailableErrorObject


// Implementation: impl api::ConnectorAccessToken for for Phonepe
// File: crates/hyperswitch_connectors/src/connectors/phonepe.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::ConnectorAccessToken for for Phonepe


// Function: generate_signature
// File: crates/hyperswitch_connectors/src/connectors/rapyd.rs
// Module: hyperswitch_connectors

pub fn generate_signature(
        &self,
        auth: &rapyd::RapydAuthType,
        http_method: &str,
        url_path: &str,
        body: &str,
        timestamp: i64,
        salt: &str,
    ) -> CustomResult<String, errors::ConnectorError>


// Implementation: impl FrmMetricAccumulator for for BlockedRateAccumulator
// File: crates/analytics/src/frm/accumulator.rs
// Module: analytics
// Methods: 2 total (0 public)

impl FrmMetricAccumulator for for BlockedRateAccumulator


// Implementation: impl PaymentIncrementalAuthorization for for Paypal
// File: crates/hyperswitch_connectors/src/connectors/paypal.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl PaymentIncrementalAuthorization for for Paypal


// Struct: RefundResponse
// File: crates/hyperswitch_connectors/src/connectors/thunes/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct RefundResponse


// Implementation: impl Default for for MerchantAccountRoutingAlgorithm
// File: crates/router/src/core/payments/routing.rs
// Module: router
// Methods: 1 total (0 public)

impl Default for for MerchantAccountRoutingAlgorithm


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

pub fn get_capture_by_capture_id(&self, capture_id: String) -> Option<&storage::Capture>


// Struct: ExtraParameters
// File: crates/hyperswitch_connectors/src/connectors/fiuu/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct ExtraParameters


// Implementation: impl api::Refund for for Adyenplatform
// File: crates/hyperswitch_connectors/src/connectors/adyenplatform.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::Refund for for Adyenplatform


// Struct: CardNetworkTokenizeRecord
// File: crates/hyperswitch_domain_models/src/bulk_tokenization.rs
// Module: hyperswitch_domain_models
// Implementations: 0

pub struct CardNetworkTokenizeRecord


// Struct: PlaidSyncRequest
// File: crates/hyperswitch_connectors/src/connectors/plaid/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct PlaidSyncRequest


// Struct: Braintree
// File: crates/hyperswitch_connectors/src/connectors/braintree.rs
// Module: hyperswitch_connectors
// Implementations: 20
// Traits: ConnectorCommon, ConnectorValidation, api::Payment, api::PaymentAuthorize, api::PaymentSync, api::PaymentVoid, api::PaymentCapture, api::PaymentsCompleteAuthorize, api::PaymentSession, api::ConnectorAccessToken, api::ConnectorMandateRevoke, api::PaymentToken, api::MandateSetup, api::Refund, api::RefundExecute, api::RefundSync, IncomingWebhook, ConnectorRedirectResponse, ConnectorSpecifications

pub struct Braintree

ConnectorCommon ConnectorValidation api::Payment api::PaymentAuthorize api::PaymentSync api::PaymentVoid api::PaymentCapture api::PaymentsCompleteAuthorize api::PaymentSession api::ConnectorAccessToken api::ConnectorMandateRevoke api::PaymentToken api::MandateSetup api::Refund api::RefundExecute api::RefundSync IncomingWebhook ConnectorRedirectResponse ConnectorSpecifications


// File: crates/analytics/src/errors.rs
// Module: analytics

use api_models::errors::types::{ApiError, ApiErrorResponse};
use common_utils::errors::{CustomResult, ErrorSwitch};

pub type AnalyticsResult<T> = CustomResult<T, AnalyticsError>;

#[derive(Debug, Clone, serde::Serialize, thiserror::Error)]
pub enum AnalyticsError {
    #[allow(dead_code)]
    #[error("Not implemented: {0}")]
    NotImplemented(&'static str),
    #[error("Unknown Analytics Error")]
    UnknownError,
    #[error("Access Forbidden Analytics Error")]
    AccessForbiddenError,
    #[error("Failed to fetch currency exchange rate")]
    ForexFetchFailed,
}

impl ErrorSwitch<ApiErrorResponse> for AnalyticsError {
    fn switch(&self) -> ApiErrorResponse {
        match self {
            Self::NotImplemented(feature) => ApiErrorResponse::NotImplemented(ApiError::new(
                "IR",
                0,
                format!("{feature} is not implemented."),
                None,
            )),
            Self::UnknownError => ApiErrorResponse::InternalServerError(ApiError::new(
                "HE",
                0,
                "Something went wrong",
                None,
            )),
            Self::AccessForbiddenError => {
                ApiErrorResponse::Unauthorized(ApiError::new("IR", 0, "Access Forbidden", None))
            }
            Self::ForexFetchFailed => ApiErrorResponse::InternalServerError(ApiError::new(
                "HE",
                0,
                "Failed to fetch currency exchange rate",
                None,
            )),
        }
    }
}


// Implementation: impl api::ExternalVault for for Tokenex
// File: crates/hyperswitch_connectors/src/connectors/tokenex.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::ExternalVault for for Tokenex


// Struct: ExternalThreeDSConnectorMetadata
// File: crates/hyperswitch_domain_models/src/router_request_types/authentication.rs
// Module: hyperswitch_domain_models
// Implementations: 0

pub struct ExternalThreeDSConnectorMetadata


// Struct: RapydRouterData
// File: crates/hyperswitch_connectors/src/connectors/rapyd/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct RapydRouterData<T>


// Struct: CardResponseObject
// File: crates/hyperswitch_connectors/src/connectors/bankofamerica/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct CardResponseObject


// Struct: ExtendedAuthorizationAppliedBool
// File: crates/common_types/src/primitive_wrappers.rs
// Module: common_types
// Implementations: 1
// Traits: Deref

pub struct ExtendedAuthorizationAppliedBool


// Struct: ApiErrorResponse
// File: crates/hyperswitch_connectors/src/connectors/braintree/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct ApiErrorResponse


// Trait: PaymentDistribution
// File: crates/analytics/src/payments/distribution.rs
// Module: analytics

pub trait PaymentDistribution<T>


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

pub struct PaypalRedirection


// Implementation: impl RelayNew
// File: crates/diesel_models/src/query/relay.rs
// Module: diesel_models
// Methods: 1 total (0 public)

impl RelayNew


// Implementation: impl ProfileNew
// File: crates/router/src/routes/app.rs
// Module: router
// Methods: 2 total (2 public)

impl ProfileNew


// Implementation: impl Shift4AuthorizePreprocessingCommon for for PaymentsAuthorizeData
// File: crates/hyperswitch_connectors/src/connectors/shift4/transformers.rs
// Module: hyperswitch_connectors
// Methods: 7 total (0 public)

impl Shift4AuthorizePreprocessingCommon for for PaymentsAuthorizeData


// Struct: RefundListRequest
// File: crates/api_models/src/refunds.rs
// Module: api_models
// Implementations: 0

pub struct RefundListRequest


// Struct: ConnectorConfig
// File: crates/connector_configs/src/connector.rs
// Module: connector_configs
// Implementations: 1

pub struct ConnectorConfig


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

pub fn list_countries_currencies_for_connector_payment_method(
    state: routes::SessionState,
    req: ListCountriesCurrenciesRequest,
    _profile_id: Option<id_type::ProfileId>,
) -> errors::RouterResponse<ListCountriesCurrenciesResponse>


// Function: get_recovery_decider_connection
// File: crates/external_services/src/grpc_client/revenue_recovery/recovery_decider_client.rs
// Module: external_services

// Documentation: create a connection

pub fn get_recovery_decider_connection(
        &self,
        hyper_client: Client,
    ) -> Result<DeciderClient<Client>, Report<RecoveryDeciderError>>


// Function: update_payment_method_and_pm_id
// File: crates/hyperswitch_domain_models/src/payments.rs
// Module: hyperswitch_domain_models

pub fn update_payment_method_and_pm_id(
        &mut self,
        payment_method_id: id_type::GlobalPaymentMethodId,
        payment_method: payment_methods::PaymentMethod,
    )


// Function: workspace_path
// File: crates/router_env/src/env.rs
// Module: router_env

// Documentation: Path to the root directory of the cargo workspace. It is recommended that this be used by the application as the base path to build other paths such as configuration and logs directories.

pub fn workspace_path() -> PathBuf


// Module Structure
// File: crates/external_services/src/grpc_client/revenue_recovery.rs
// Module: external_services

// Public submodules:
pub mod recovery_decider_client;


// Function: migrate_payment_method
// File: crates/payment_methods/src/core/migration/payment_methods.rs
// Module: payment_methods

pub fn migrate_payment_method(
    _state: &state::PaymentMethodsState,
    _req: pm_api::PaymentMethodMigrate,
    _merchant_id: &id_type::MerchantId,
    _merchant_context: &merchant_context::MerchantContext,
    _controller: &dyn PaymentMethodsController,
) -> CustomResult<ApplicationResponse<pm_api::PaymentMethodMigrateResponse>, errors::ApiErrorResponse>


// File: crates/router/src/core/errors/transformers.rs
// Module: router

use common_utils::errors::ErrorSwitch;
use hyperswitch_domain_models::errors::api_error_response::ApiErrorResponse;

use super::{CustomersErrorResponse, StorageError};

impl ErrorSwitch<api_models::errors::types::ApiErrorResponse> for CustomersErrorResponse {
    fn switch(&self) -> api_models::errors::types::ApiErrorResponse {
        use api_models::errors::types::{ApiError, ApiErrorResponse as AER};
        match self {
            Self::CustomerRedacted => AER::BadRequest(ApiError::new(
                "IR",
                11,
                "Customer has already been redacted",
                None,
            )),
            Self::InternalServerError => {
                AER::InternalServerError(ApiError::new("HE", 0, "Something went wrong", None))
            }
            Self::MandateActive => AER::BadRequest(ApiError::new(
                "IR",
                10,
                "Customer has active mandate/subsciption",
                None,
            )),
            Self::CustomerNotFound => AER::NotFound(ApiError::new(
                "HE",
                2,
                "Customer does not exist in our records",
                None,
            )),
            Self::CustomerAlreadyExists => AER::BadRequest(ApiError::new(
                "IR",
                12,
                "Customer with the given `customer_id` already exists",
                None,
            )),
        }
    }
}

impl ErrorSwitch<CustomersErrorResponse> for StorageError {
    fn switch(&self) -> CustomersErrorResponse {
        use CustomersErrorResponse as CER;
        match self {
            err if err.is_db_not_found() => CER::CustomerNotFound,
            Self::CustomerRedacted => CER::CustomerRedacted,
            _ => CER::InternalServerError,
        }
    }
}

impl ErrorSwitch<CustomersErrorResponse> for common_utils::errors::CryptoError {
    fn switch(&self) -> CustomersErrorResponse {
        CustomersErrorResponse::InternalServerError
    }
}

impl ErrorSwitch<CustomersErrorResponse> for ApiErrorResponse {
    fn switch(&self) -> CustomersErrorResponse {
        use CustomersErrorResponse as CER;
        match self {
            Self::InternalServerError => CER::InternalServerError,
            Self::MandateActive => CER::MandateActive,
            Self::CustomerNotFound => CER::CustomerNotFound,
            _ => CER::InternalServerError,
        }
    }
}


// Implementation: impl UserName
// File: crates/router/src/types/domain/user.rs
// Module: router
// Methods: 2 total (2 public)

impl UserName


// Struct: BitpayRefundRequest
// File: crates/hyperswitch_connectors/src/connectors/bitpay/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct BitpayRefundRequest


// Implementation: impl super::KafkaMessage for for KafkaRefundEvent
// File: crates/router/src/services/kafka/refund_event.rs
// Module: router
// Methods: 2 total (0 public)

impl super::KafkaMessage for for KafkaRefundEvent


// File: crates/diesel_models/src/locker_mock_up.rs
// Module: diesel_models
// Public structs: 2

use diesel::{Identifiable, Insertable, Queryable, Selectable};

use crate::schema::locker_mock_up;

#[derive(Clone, Debug, Eq, Identifiable, Queryable, Selectable, PartialEq)]
#[diesel(table_name = locker_mock_up, primary_key(card_id), check_for_backend(diesel::pg::Pg))]
pub struct LockerMockUp {
    pub card_id: String,
    pub external_id: String,
    pub card_fingerprint: String,
    pub card_global_fingerprint: String,
    pub merchant_id: common_utils::id_type::MerchantId,
    pub card_number: String,
    pub card_exp_year: String,
    pub card_exp_month: String,
    pub name_on_card: Option<String>,
    pub nickname: Option<String>,
    pub customer_id: Option<common_utils::id_type::CustomerId>,
    pub duplicate: Option<bool>,
    pub card_cvc: Option<String>,
    pub payment_method_id: Option<String>,
    pub enc_card_data: Option<String>,
}

#[derive(Clone, Debug, Default, Insertable, router_derive::DebugAsDisplay)]
#[diesel(table_name = locker_mock_up)]
pub struct LockerMockUpNew {
    pub card_id: String,
    pub external_id: String,
    pub card_fingerprint: String,
    pub card_global_fingerprint: String,
    pub merchant_id: common_utils::id_type::MerchantId,
    pub card_number: String,
    pub card_exp_year: String,
    pub card_exp_month: String,
    pub name_on_card: Option<String>,
    pub card_cvc: Option<String>,
    pub payment_method_id: Option<String>,
    pub customer_id: Option<common_utils::id_type::CustomerId>,
    pub nickname: Option<String>,
    pub enc_card_data: Option<String>,
}


// Trait: ConnectorIntegrationAny
// File: crates/pm_auth/src/types/api.rs
// Module: pm_auth

pub trait ConnectorIntegrationAny<T, Req, Resp>: Send + Sync + 'static


// File: crates/router/tests/connectors/volt.rs
// Module: router

use masking::Secret;
use router::types::{self, domain, storage::enums};
use test_utils::connector_auth;

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

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

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

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

static CONNECTOR: VoltTest = VoltTest {};

fn get_default_payment_info() -> Option<utils::PaymentInfo> {
    None
}

fn payment_method_details() -> Option<types::PaymentsAuthorizeData> {
    None
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// Cards Negative scenarios
// Creates a payment with incorrect CVC.
#[actix_web::test]
async fn should_fail_payment_for_incorrect_cvc() {
    let response = CONNECTOR
        .make_payment(
            Some(types::PaymentsAuthorizeData {
                payment_method_data: domain::PaymentMethodData::Card(domain::Card {
                    card_cvc: Secret::new("12345".to_string()),
                    ..utils::CCardType::default().0
                }),
                ..utils::PaymentAuthorizeType::default().0
            }),
            get_default_payment_info(),
        )
        .await
        .unwrap();
    assert_eq!(
        response.response.unwrap_err().message,
        "Your card's security code is invalid.".to_string(),
    );
}

// Creates a payment with incorrect expiry month.
#[actix_web::test]
async fn should_fail_payment_for_invalid_exp_month() {
    let response = CONNECTOR
        .make_payment(
            Some(types::PaymentsAuthorizeData {
                payment_method_data: domain::PaymentMethodData::Card(domain::Card {
                    card_exp_month: Secret::new("20".to_string()),
                    ..utils::CCardType::default().0
                }),
                ..utils::PaymentAuthorizeType::default().0
            }),
            get_default_payment_info(),
        )
        .await
        .unwrap();
    assert_eq!(
        response.response.unwrap_err().message,
        "Your card's expiration month is invalid.".to_string(),
    );
}

// Creates a payment with incorrect expiry year.
#[actix_web::test]
async fn should_fail_payment_for_incorrect_expiry_year() {
    let response = CONNECTOR
        .make_payment(
            Some(types::PaymentsAuthorizeData {
                payment_method_data: domain::PaymentMethodData::Card(domain::Card {
                    card_exp_year: Secret::new("2000".to_string()),
                    ..utils::CCardType::default().0
                }),
                ..utils::PaymentAuthorizeType::default().0
            }),
            get_default_payment_info(),
        )
        .await
        .unwrap();
    assert_eq!(
        response.response.unwrap_err().message,
        "Your card's expiration year is invalid.".to_string(),
    );
}

// Voids a payment using automatic capture flow (Non 3DS).
#[actix_web::test]
async fn should_fail_void_payment_for_auto_capture() {
    let authorize_response = CONNECTOR
        .make_payment(payment_method_details(), get_default_payment_info())
        .await
        .unwrap();
    assert_eq!(authorize_response.status, enums::AttemptStatus::Charged);
    let txn_id = utils::get_connector_transaction_id(authorize_response.response);
    assert_ne!(txn_id, None, "Empty connector transaction id");
    let void_response = CONNECTOR
        .void_payment(txn_id.unwrap(), None, get_default_payment_info())
        .await
        .unwrap();
    assert_eq!(
        void_response.response.unwrap_err().message,
        "You cannot cancel this PaymentIntent because it has a status of succeeded."
    );
}

// Captures a payment using invalid connector payment id.
#[actix_web::test]
async fn should_fail_capture_for_invalid_payment() {
    let capture_response = CONNECTOR
        .capture_payment("123456789".to_string(), None, get_default_payment_info())
        .await
        .unwrap();
    assert_eq!(
        capture_response.response.unwrap_err().message,
        String::from("No such payment_intent: '123456789'")
    );
}

// Refunds a payment with refund amount higher than payment amount.
#[actix_web::test]
async fn should_fail_for_refund_amount_higher_than_payment_amount() {
    let response = CONNECTOR
        .make_payment_and_refund(
            payment_method_details(),
            Some(types::RefundsData {
                refund_amount: 150,
                ..utils::PaymentRefundType::default().0
            }),
            get_default_payment_info(),
        )
        .await
        .unwrap();
    assert_eq!(
        response.response.unwrap_err().message,
        "Refund amount (₹1.50) is greater than charge amount (₹1.00)",
    );
}

// Connector dependent test cases goes here

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


// Function: get_is_tax_connector_enabled
// File: crates/hyperswitch_domain_models/src/business_profile.rs
// Module: hyperswitch_domain_models

pub fn get_is_tax_connector_enabled(&self) -> bool


// Trait: PayoutAttemptInterface
// File: crates/hyperswitch_domain_models/src/payouts/payout_attempt.rs
// Module: hyperswitch_domain_models

pub trait PayoutAttemptInterface


// Struct: PaymentMethodBalance
// File: crates/hyperswitch_domain_models/src/router_data.rs
// Module: hyperswitch_domain_models
// Implementations: 0

pub struct PaymentMethodBalance


// File: crates/router/src/compatibility/stripe/payment_intents/types.rs
// Module: router
// Public functions: 1
// Public structs: 20

use std::str::FromStr;

use api_models::payments;
use common_types::payments as common_payments_types;
use common_utils::{
    crypto::Encryptable,
    date_time,
    ext_traits::StringExt,
    id_type,
    pii::{IpAddress, SecretSerdeValue, UpiVpaMaskingStrategy},
    types::MinorUnit,
};
use error_stack::ResultExt;
use serde::{Deserialize, Serialize};
use time::PrimitiveDateTime;

use crate::{
    compatibility::stripe::refunds::types as stripe_refunds,
    connector::utils::AddressData,
    consts,
    core::errors,
    pii::{Email, PeekInterface},
    types::{
        api::{admin, enums as api_enums},
        transformers::{ForeignFrom, ForeignTryFrom},
    },
};

#[derive(Default, Serialize, PartialEq, Eq, Deserialize, Clone, Debug)]
pub struct StripeBillingDetails {
    pub address: Option<AddressDetails>,
    pub email: Option<Email>,
    pub name: Option<String>,
    pub phone: Option<masking::Secret<String>>,
}

impl From<StripeBillingDetails> for payments::Address {
    fn from(details: StripeBillingDetails) -> Self {
        Self {
            phone: Some(payments::PhoneDetails {
                number: details.phone,
                country_code: details.address.as_ref().and_then(|address| {
                    address.country.as_ref().map(|country| country.to_string())
                }),
            }),
            email: details.email,
            address: details.address.map(|address| payments::AddressDetails {
                city: address.city,
                country: address.country,
                line1: address.line1,
                line2: address.line2,
                zip: address.postal_code,
                state: address.state,
                first_name: None,
                line3: None,
                last_name: None,
                origin_zip: None,
            }),
        }
    }
}

#[derive(Default, Serialize, PartialEq, Eq, Deserialize, Clone, Debug)]
pub struct StripeCard {
    pub number: cards::CardNumber,
    pub exp_month: masking::Secret<String>,
    pub exp_year: masking::Secret<String>,
    pub cvc: masking::Secret<String>,
    pub holder_name: Option<masking::Secret<String>>,
}

// ApplePay wallet param is not available in stripe Docs
#[derive(Serialize, PartialEq, Eq, Deserialize, Clone, Debug)]
#[serde(rename_all = "snake_case")]
pub enum StripeWallet {
    ApplePay(payments::ApplePayWalletData),
}

#[derive(Default, Serialize, PartialEq, Eq, Deserialize, Clone, Debug)]
pub struct StripeUpi {
    pub vpa_id: masking::Secret<String, UpiVpaMaskingStrategy>,
}

#[derive(Debug, Default, Serialize, PartialEq, Eq, Deserialize, Clone)]
#[serde(rename_all = "snake_case")]
pub enum StripePaymentMethodType {
    #[default]
    Card,
    Wallet,
    Upi,
    BankRedirect,
    RealTimePayment,
}

impl From<StripePaymentMethodType> for api_enums::PaymentMethod {
    fn from(item: StripePaymentMethodType) -> Self {
        match item {
            StripePaymentMethodType::Card => Self::Card,
            StripePaymentMethodType::Wallet => Self::Wallet,
            StripePaymentMethodType::Upi => Self::Upi,
            StripePaymentMethodType::BankRedirect => Self::BankRedirect,
            StripePaymentMethodType::RealTimePayment => Self::RealTimePayment,
        }
    }
}

#[derive(Default, PartialEq, Eq, Deserialize, Clone, Debug)]
pub struct StripePaymentMethodData {
    #[serde(rename = "type")]
    pub stype: StripePaymentMethodType,
    pub billing_details: Option<StripeBillingDetails>,
    #[serde(flatten)]
    pub payment_method_details: Option<StripePaymentMethodDetails>, // enum
    pub metadata: Option<SecretSerdeValue>,
}

#[derive(PartialEq, Eq, Deserialize, Clone, Debug)]
#[serde(rename_all = "snake_case")]
pub enum StripePaymentMethodDetails {
    Card(StripeCard),
    Wallet(StripeWallet),
    Upi(StripeUpi),
}

impl From<StripeCard> for payments::Card {
    fn from(card: StripeCard) -> Self {
        Self {
            card_number: card.number,
            card_exp_month: card.exp_month,
            card_exp_year: card.exp_year,
            card_holder_name: card.holder_name,
            card_cvc: card.cvc,
            card_issuer: None,
            card_network: None,
            bank_code: None,
            card_issuing_country: None,
            card_type: None,
            nick_name: None,
        }
    }
}

impl From<StripeWallet> for payments::WalletData {
    fn from(wallet: StripeWallet) -> Self {
        match wallet {
            StripeWallet::ApplePay(data) => Self::ApplePay(data),
        }
    }
}

impl From<StripeUpi> for payments::UpiData {
    fn from(upi_data: StripeUpi) -> Self {
        Self::UpiCollect(payments::UpiCollectData {
            vpa_id: Some(upi_data.vpa_id),
        })
    }
}

impl From<StripePaymentMethodDetails> for payments::PaymentMethodData {
    fn from(item: StripePaymentMethodDetails) -> Self {
        match item {
            StripePaymentMethodDetails::Card(card) => Self::Card(payments::Card::from(card)),
            StripePaymentMethodDetails::Wallet(wallet) => {
                Self::Wallet(payments::WalletData::from(wallet))
            }
            StripePaymentMethodDetails::Upi(upi) => Self::Upi(payments::UpiData::from(upi)),
        }
    }
}

#[derive(Default, Serialize, PartialEq, Eq, Deserialize, Clone, Debug)]
pub struct Shipping {
    pub address: AddressDetails,
    pub name: Option<masking::Secret<String>>,
    pub carrier: Option<String>,
    pub phone: Option<masking::Secret<String>>,
    pub tracking_number: Option<masking::Secret<String>>,
}

#[derive(Default, Serialize, PartialEq, Eq, Deserialize, Clone, Debug)]
pub struct AddressDetails {
    pub city: Option<String>,
    pub country: Option<api_enums::CountryAlpha2>,
    pub line1: Option<masking::Secret<String>>,
    pub line2: Option<masking::Secret<String>>,
    pub postal_code: Option<masking::Secret<String>>,
    pub state: Option<masking::Secret<String>>,
}

impl From<Shipping> for payments::Address {
    fn from(details: Shipping) -> Self {
        Self {
            phone: Some(payments::PhoneDetails {
                number: details.phone,
                country_code: details.address.country.map(|country| country.to_string()),
            }),
            email: None,
            address: Some(payments::AddressDetails {
                city: details.address.city,
                country: details.address.country,
                line1: details.address.line1,
                line2: details.address.line2,
                zip: details.address.postal_code,
                state: details.address.state,
                first_name: details.name,
                line3: None,
                last_name: None,
                origin_zip: None,
            }),
        }
    }
}

#[derive(Default, Serialize, PartialEq, Eq, Deserialize, Clone, Debug)]
pub struct MandateData {
    pub customer_acceptance: CustomerAcceptance,
    pub mandate_type: Option<StripeMandateType>,
    pub amount: Option<i64>,
    #[serde(default, with = "common_utils::custom_serde::timestamp::option")]
    pub start_date: Option<PrimitiveDateTime>,
    #[serde(default, with = "common_utils::custom_serde::timestamp::option")]
    pub end_date: Option<PrimitiveDateTime>,
}

#[derive(Default, Serialize, PartialEq, Eq, Deserialize, Clone, Debug)]
pub struct CustomerAcceptance {
    #[serde(rename = "type")]
    pub acceptance_type: Option<AcceptanceType>,
    pub accepted_at: Option<PrimitiveDateTime>,
    pub online: Option<OnlineMandate>,
}

#[derive(Default, Debug, serde::Deserialize, serde::Serialize, PartialEq, Eq, Clone)]
#[serde(rename_all = "lowercase")]
pub enum AcceptanceType {
    Online,
    #[default]
    Offline,
}

#[derive(Default, Eq, PartialEq, Debug, serde::Deserialize, serde::Serialize, Clone)]
#[serde(deny_unknown_fields)]
pub struct OnlineMandate {
    pub ip_address: masking::Secret<String, IpAddress>,
    pub user_agent: String,
}

#[derive(Deserialize, Clone, Debug)]
pub struct StripePaymentIntentRequest {
    pub id: Option<id_type::PaymentId>,
    pub amount: Option<i64>, // amount in cents, hence passed as integer
    pub connector: Option<Vec<api_enums::RoutableConnectors>>,
    pub currency: Option<String>,
    #[serde(rename = "amount_to_capture")]
    pub amount_capturable: Option<i64>,
    pub confirm: Option<bool>,
    pub capture_method: Option<api_enums::CaptureMethod>,
    pub customer: Option<id_type::CustomerId>,
    pub description: Option<String>,
    pub payment_method_data: Option<StripePaymentMethodData>,
    pub receipt_email: Option<Email>,
    pub return_url: Option<url::Url>,
    pub setup_future_usage: Option<api_enums::FutureUsage>,
    pub shipping: Option<Shipping>,
    pub statement_descriptor: Option<String>,
    pub statement_descriptor_suffix: Option<String>,
    pub metadata: Option<serde_json::Value>,
    pub client_secret: Option<masking::Secret<String>>,
    pub payment_method_options: Option<StripePaymentMethodOptions>,
    pub merchant_connector_details: Option<admin::MerchantConnectorDetailsWrap>,
    pub mandate: Option<String>,
    pub off_session: Option<bool>,
    pub payment_method_types: Option<api_enums::PaymentMethodType>,
    pub receipt_ipaddress: Option<String>,
    pub user_agent: Option<String>,
    pub mandate_data: Option<MandateData>,
    pub automatic_payment_methods: Option<SecretSerdeValue>, // not used
    pub payment_method: Option<String>,                      // not used
    pub confirmation_method: Option<String>,                 // not used
    pub error_on_requires_action: Option<String>,            // not used
    pub radar_options: Option<SecretSerdeValue>,             // not used
    pub connector_metadata: Option<payments::ConnectorMetadata>,
}

impl TryFrom<StripePaymentIntentRequest> for payments::PaymentsRequest {
    type Error = error_stack::Report<errors::ApiErrorResponse>;
    fn try_from(item: StripePaymentIntentRequest) -> errors::RouterResult<Self> {
        let routable_connector: Option<api_enums::RoutableConnectors> =
            item.connector.and_then(|v| v.into_iter().next());

        let routing = routable_connector
            .map(|connector| {
                api_models::routing::StaticRoutingAlgorithm::Single(Box::new(
                    api_models::routing::RoutableConnectorChoice {
                        choice_kind: api_models::routing::RoutableChoiceKind::FullStruct,
                        connector,
                        merchant_connector_id: None,
                    },
                ))
            })
            .map(|r| {
                serde_json::to_value(r)
                    .change_context(errors::ApiErrorResponse::InternalServerError)
                    .attach_printable("converting to routing failed")
            })
            .transpose()?;

        let ip_address = item
            .receipt_ipaddress
            .map(|ip| std::net::IpAddr::from_str(ip.as_str()))
            .transpose()
            .change_context(errors::ApiErrorResponse::InvalidDataFormat {
                field_name: "receipt_ipaddress".to_string(),
                expected_format: "127.0.0.1".to_string(),
            })?;

        let amount = item.amount.map(|amount| MinorUnit::new(amount).into());

        let payment_method_data = item.payment_method_data.as_ref().map(|pmd| {
            let billing = pmd.billing_details.clone().map(payments::Address::from);
            let payment_method_data = match pmd.payment_method_details.as_ref() {
                Some(spmd) => Some(payments::PaymentMethodData::from(spmd.to_owned())),
                None => get_pmd_based_on_payment_method_type(
                    item.payment_method_types,
                    billing.clone().map(From::from),
                ),
            };

            payments::PaymentMethodDataRequest {
                payment_method_data,
                billing,
            }
        });

        let request = Ok(Self {
            payment_id: item.id.map(payments::PaymentIdType::PaymentIntentId),
            amount,
            currency: item
                .currency
                .as_ref()
                .map(|c| c.to_uppercase().parse_enum("currency"))
                .transpose()
                .change_context(errors::ApiErrorResponse::InvalidDataValue {
                    field_name: "currency",
                })?,
            capture_method: item.capture_method,
            amount_to_capture: item.amount_capturable.map(MinorUnit::new),
            confirm: item.confirm,
            customer_id: item.customer,
            email: item.receipt_email,
            phone: item.shipping.as_ref().and_then(|s| s.phone.clone()),
            description: item.description,
            return_url: item.return_url,
            payment_method_data,
            payment_method: item
                .payment_method_data
                .as_ref()
                .map(|pmd| api_enums::PaymentMethod::from(pmd.stype.to_owned())),
            shipping: item
                .shipping
                .as_ref()
                .map(|s| payments::Address::from(s.to_owned())),
            billing: item
                .payment_method_data
                .and_then(|pmd| pmd.billing_details.map(payments::Address::from)),
            statement_descriptor_name: item.statement_descriptor,
            statement_descriptor_suffix: item.statement_descriptor_suffix,
            metadata: item.metadata,
            client_secret: item.client_secret.map(|s| s.peek().clone()),
            authentication_type: match item.payment_method_options {
                Some(pmo) => {
                    let StripePaymentMethodOptions::Card {
                        request_three_d_secure,
                    }: StripePaymentMethodOptions = pmo;
                    Some(api_enums::AuthenticationType::foreign_from(
                        request_three_d_secure,
                    ))
                }
                None => None,
            },
            mandate_data: ForeignTryFrom::foreign_try_from((
                item.mandate_data,
                item.currency.to_owned(),
            ))?,
            merchant_connector_details: item.merchant_connector_details,
            setup_future_usage: item.setup_future_usage,
            mandate_id: item.mandate,
            off_session: item.off_session,
            payment_method_type: item.payment_method_types,
            routing,
            browser_info: Some(
                serde_json::to_value(crate::types::BrowserInformation {
                    ip_address,
                    user_agent: item.user_agent,
                    ..Default::default()
                })
                .change_context(errors::ApiErrorResponse::InternalServerError)
                .attach_printable("convert to browser info failed")?,
            ),
            connector_metadata: item.connector_metadata,
            ..Self::default()
        });
        request
    }
}

#[derive(Clone, Default, Eq, PartialEq, Serialize, Deserialize, Debug)]
#[serde(rename_all = "snake_case")]
pub enum StripePaymentStatus {
    Succeeded,
    Canceled,
    #[default]
    Processing,
    RequiresAction,
    RequiresPaymentMethod,
    RequiresConfirmation,
    RequiresCapture,
}

impl From<api_enums::IntentStatus> for StripePaymentStatus {
    fn from(item: api_enums::IntentStatus) -> Self {
        match item {
            api_enums::IntentStatus::Succeeded | api_enums::IntentStatus::PartiallyCaptured => {
                Self::Succeeded
            }
            api_enums::IntentStatus::Failed | api_enums::IntentStatus::Expired => Self::Canceled,
            api_enums::IntentStatus::Processing => Self::Processing,
            api_enums::IntentStatus::RequiresCustomerAction
            | api_enums::IntentStatus::RequiresMerchantAction
            | api_enums::IntentStatus::Conflicted => Self::RequiresAction,
            api_enums::IntentStatus::RequiresPaymentMethod => Self::RequiresPaymentMethod,
            api_enums::IntentStatus::RequiresConfirmation => Self::RequiresConfirmation,
            api_enums::IntentStatus::RequiresCapture
            | api_enums::IntentStatus::PartiallyCapturedAndCapturable
            | api_enums::IntentStatus::PartiallyAuthorizedAndRequiresCapture => {
                Self::RequiresCapture
            }
            api_enums::IntentStatus::Cancelled | api_enums::IntentStatus::CancelledPostCapture => {
                Self::Canceled
            }
        }
    }
}

#[derive(Debug, Serialize, Deserialize, Copy, Clone, strum::Display)]
#[serde(rename_all = "snake_case")]
#[strum(serialize_all = "snake_case")]
pub enum CancellationReason {
    Duplicate,
    Fraudulent,
    RequestedByCustomer,
    Abandoned,
}

#[derive(Debug, Deserialize, Serialize, Copy, Clone)]
pub struct StripePaymentCancelRequest {
    cancellation_reason: Option<CancellationReason>,
}

impl From<StripePaymentCancelRequest> for payments::PaymentsCancelRequest {
    fn from(item: StripePaymentCancelRequest) -> Self {
        Self {
            cancellation_reason: item.cancellation_reason.map(|c| c.to_string()),
            ..Self::default()
        }
    }
}

#[derive(Default, Eq, PartialEq, Serialize, Debug)]
pub struct StripePaymentIntentResponse {
    pub id: id_type::PaymentId,
    pub object: &'static str,
    pub amount: i64,
    pub amount_received: Option<i64>,
    pub amount_capturable: i64,
    pub currency: String,
    pub status: StripePaymentStatus,
    pub client_secret: Option<masking::Secret<String>>,
    pub created: Option<i64>,
    pub customer: Option<id_type::CustomerId>,
    pub refunds: Option<Vec<stripe_refunds::StripeRefundResponse>>,
    pub mandate: Option<String>,
    pub metadata: Option<serde_json::Value>,
    pub charges: Charges,
    pub connector: Option<String>,
    pub description: Option<String>,
    pub mandate_data: Option<payments::MandateData>,
    pub setup_future_usage: Option<api_models::enums::FutureUsage>,
    pub off_session: Option<bool>,
    pub authentication_type: Option<api_models::enums::AuthenticationType>,
    pub next_action: Option<StripeNextAction>,
    pub cancellation_reason: Option<String>,
    pub payment_method: Option<api_models::enums::PaymentMethod>,
    pub payment_method_data: Option<payments::PaymentMethodDataResponse>,
    pub shipping: Option<payments::Address>,
    pub billing: Option<payments::Address>,
    #[serde(with = "common_utils::custom_serde::iso8601::option")]
    pub capture_on: Option<PrimitiveDateTime>,
    pub payment_token: Option<String>,
    pub email: Option<Email>,
    pub phone: Option<masking::Secret<String>>,
    pub statement_descriptor_suffix: Option<String>,
    pub statement_descriptor_name: Option<String>,
    pub capture_method: Option<api_models::enums::CaptureMethod>,
    pub name: Option<masking::Secret<String>>,
    pub last_payment_error: Option<LastPaymentError>,
    pub connector_transaction_id: Option<String>,
}

#[derive(Default, Eq, PartialEq, Serialize, Debug)]
pub struct LastPaymentError {
    charge: Option<String>,
    code: Option<String>,
    decline_code: Option<String>,
    message: String,
    param: Option<String>,
    payment_method: StripePaymentMethod,
    #[serde(rename = "type")]
    error_type: String,
}

impl From<payments::PaymentsResponse> for StripePaymentIntentResponse {
    fn from(resp: payments::PaymentsResponse) -> Self {
        Self {
            object: "payment_intent",
            id: resp.payment_id,
            status: StripePaymentStatus::from(resp.status),
            amount: resp.amount.get_amount_as_i64(),
            amount_capturable: resp.amount_capturable.get_amount_as_i64(),
            amount_received: resp.amount_received.map(|amt| amt.get_amount_as_i64()),
            connector: resp.connector,
            client_secret: resp.client_secret,
            created: resp.created.map(|t| t.assume_utc().unix_timestamp()),
            currency: resp.currency.to_lowercase(),
            customer: resp.customer_id,
            description: resp.description,
            refunds: resp
                .refunds
                .map(|a| a.into_iter().map(Into::into).collect()),
            mandate: resp.mandate_id,
            mandate_data: resp.mandate_data,
            setup_future_usage: resp.setup_future_usage,
            off_session: resp.off_session,
            capture_on: resp.capture_on,
            capture_method: resp.capture_method,
            payment_method: resp.payment_method,
            payment_method_data: resp
                .payment_method_data
                .and_then(|pmd| pmd.payment_method_data),
            payment_token: resp.payment_token,
            shipping: resp.shipping,
            billing: resp.billing,
            email: resp.email.map(|inner| inner.into()),
            name: resp.name.map(Encryptable::into_inner),
            phone: resp.phone.map(Encryptable::into_inner),
            authentication_type: resp.authentication_type,
            statement_descriptor_name: resp.statement_descriptor_name,
            statement_descriptor_suffix: resp.statement_descriptor_suffix,
            next_action: into_stripe_next_action(resp.next_action, resp.return_url),
            cancellation_reason: resp.cancellation_reason,
            metadata: resp.metadata,
            charges: Charges::new(),
            last_payment_error: resp.error_code.map(|code| LastPaymentError {
                charge: None,
                code: Some(code.to_owned()),
                decline_code: None,
                message: resp
                    .error_message
                    .unwrap_or_else(|| consts::NO_ERROR_MESSAGE.to_string()),
                param: None,
                payment_method: StripePaymentMethod {
                    payment_method_id: "place_holder_id".to_string(),
                    object: "payment_method",
                    card: None,
                    created: u64::try_from(date_time::now().assume_utc().unix_timestamp())
                        .unwrap_or_default(),
                    method_type: "card".to_string(),
                    livemode: false,
                },
                error_type: code,
            }),
            connector_transaction_id: resp.connector_transaction_id,
        }
    }
}

#[derive(Default, Eq, PartialEq, Serialize, Debug)]
pub struct StripePaymentMethod {
    #[serde(rename = "id")]
    payment_method_id: String,
    object: &'static str,
    card: Option<StripeCard>,
    created: u64,
    #[serde(rename = "type")]
    method_type: String,
    livemode: bool,
}

#[derive(Default, Eq, PartialEq, Serialize, Debug)]
pub struct Charges {
    object: &'static str,
    data: Vec<String>,
    has_more: bool,
    total_count: i32,
    url: String,
}

impl Charges {
    pub fn new() -> Self {
        Self {
            object: "list",
            data: vec![],
            has_more: false,
            total_count: 0,
            url: "http://placeholder".to_string(),
        }
    }
}

#[derive(Clone, Debug, serde::Deserialize)]
#[serde(deny_unknown_fields)]
pub struct StripePaymentListConstraints {
    pub customer: Option<id_type::CustomerId>,
    pub starting_after: Option<id_type::PaymentId>,
    pub ending_before: Option<id_type::PaymentId>,
    #[serde(default = "default_limit")]
    pub limit: u32,
    pub created: Option<i64>,
    #[serde(rename = "created[lt]")]
    pub created_lt: Option<i64>,
    #[serde(rename = "created[gt]")]
    pub created_gt: Option<i64>,
    #[serde(rename = "created[lte]")]
    pub created_lte: Option<i64>,
    #[serde(rename = "created[gte]")]
    pub created_gte: Option<i64>,
}

fn default_limit() -> u32 {
    10
}

impl TryFrom<StripePaymentListConstraints> for payments::PaymentListConstraints {
    type Error = error_stack::Report<errors::ApiErrorResponse>;
    fn try_from(item: StripePaymentListConstraints) -> Result<Self, Self::Error> {
        Ok(Self {
            customer_id: item.customer,
            starting_after: item.starting_after,
            ending_before: item.ending_before,
            limit: item.limit,
            created: from_timestamp_to_datetime(item.created)?,
            created_lt: from_timestamp_to_datetime(item.created_lt)?,
            created_gt: from_timestamp_to_datetime(item.created_gt)?,
            created_lte: from_timestamp_to_datetime(item.created_lte)?,
            created_gte: from_timestamp_to_datetime(item.created_gte)?,
        })
    }
}

#[inline]
fn from_timestamp_to_datetime(
    time: Option<i64>,
) -> Result<Option<PrimitiveDateTime>, errors::ApiErrorResponse> {
    if let Some(time) = time {
        let time = time::OffsetDateTime::from_unix_timestamp(time).map_err(|_| {
            errors::ApiErrorResponse::InvalidRequestData {
                message: "Error while converting timestamp".to_string(),
            }
        })?;

        Ok(Some(PrimitiveDateTime::new(time.date(), time.time())))
    } else {
        Ok(None)
    }
}

#[derive(Default, Eq, PartialEq, Serialize)]
pub struct StripePaymentIntentListResponse {
    pub object: String,
    pub url: String,
    pub has_more: bool,
    pub data: Vec<StripePaymentIntentResponse>,
}

impl From<payments::PaymentListResponse> for StripePaymentIntentListResponse {
    fn from(it: payments::PaymentListResponse) -> Self {
        Self {
            object: "list".to_string(),
            url: "/v1/payment_intents".to_string(),
            has_more: false,
            data: it.data.into_iter().map(Into::into).collect(),
        }
    }
}

#[derive(PartialEq, Eq, Deserialize, Clone, Debug)]
#[serde(rename_all = "snake_case")]
pub enum StripePaymentMethodOptions {
    Card {
        request_three_d_secure: Option<Request3DS>,
    },
}

#[derive(Eq, PartialEq, Debug, serde::Deserialize, serde::Serialize, Clone)]
#[serde(rename_all = "snake_case")]
pub enum StripeMandateType {
    SingleUse,
    MultiUse,
}

#[derive(PartialEq, Eq, Clone, Default, Deserialize, Serialize, Debug)]
pub struct MandateOption {
    #[serde(default, with = "common_utils::custom_serde::timestamp::option")]
    pub accepted_at: Option<PrimitiveDateTime>,
    pub user_agent: Option<String>,
    pub ip_address: Option<masking::Secret<String, IpAddress>>,
    pub mandate_type: Option<StripeMandateType>,
    pub amount: Option<i64>,
    #[serde(default, with = "common_utils::custom_serde::timestamp::option")]
    pub start_date: Option<PrimitiveDateTime>,
    #[serde(default, with = "common_utils::custom_serde::timestamp::option")]
    pub end_date: Option<PrimitiveDateTime>,
}

impl ForeignTryFrom<(Option<MandateData>, Option<String>)> for Option<payments::MandateData> {
    type Error = error_stack::Report<errors::ApiErrorResponse>;
    fn foreign_try_from(
        (mandate_data, currency): (Option<MandateData>, Option<String>),
    ) -> errors::RouterResult<Self> {
        let currency = currency
            .ok_or(
                errors::ApiErrorResponse::MissingRequiredField {
                    field_name: "currency",
                }
                .into(),
            )
            .and_then(|c| {
                c.to_uppercase().parse_enum("currency").change_context(
                    errors::ApiErrorResponse::InvalidDataValue {
                        field_name: "currency",
                    },
                )
            })?;
        let mandate_data = mandate_data.map(|mandate| payments::MandateData {
            mandate_type: match mandate.mandate_type {
                Some(item) => match item {
                    StripeMandateType::SingleUse => Some(payments::MandateType::SingleUse(
                        payments::MandateAmountData {
                            amount: MinorUnit::new(mandate.amount.unwrap_or_default()),
                            currency,
                            start_date: mandate.start_date,
                            end_date: mandate.end_date,
                            metadata: None,
                        },
                    )),
                    StripeMandateType::MultiUse => Some(payments::MandateType::MultiUse(Some(
                        payments::MandateAmountData {
                            amount: MinorUnit::new(mandate.amount.unwrap_or_default()),
                            currency,
                            start_date: mandate.start_date,
                            end_date: mandate.end_date,
                            metadata: None,
                        },
                    ))),
                },
                None => Some(payments::MandateType::MultiUse(Some(
                    payments::MandateAmountData {
                        amount: MinorUnit::new(mandate.amount.unwrap_or_default()),
                        currency,
                        start_date: mandate.start_date,
                        end_date: mandate.end_date,
                        metadata: None,
                    },
                ))),
            },
            customer_acceptance: Some(common_payments_types::CustomerAcceptance {
                acceptance_type: common_payments_types::AcceptanceType::Online,
                accepted_at: mandate.customer_acceptance.accepted_at,
                online: mandate.customer_acceptance.online.map(|online| {
                    common_payments_types::OnlineMandate {
                        ip_address: Some(online.ip_address),
                        user_agent: online.user_agent,
                    }
                }),
            }),
            update_mandate_id: None,
        });
        Ok(mandate_data)
    }
}

#[derive(Default, Eq, PartialEq, Serialize, Deserialize, Clone, Debug)]
#[serde(rename_all = "snake_case")]
pub enum Request3DS {
    #[default]
    Automatic,
    Any,
}

impl ForeignFrom<Option<Request3DS>> for api_models::enums::AuthenticationType {
    fn foreign_from(item: Option<Request3DS>) -> Self {
        match item.unwrap_or_default() {
            Request3DS::Automatic => Self::NoThreeDs,
            Request3DS::Any => Self::ThreeDs,
        }
    }
}

#[derive(Default, Eq, PartialEq, Serialize, Debug)]
pub struct RedirectUrl {
    pub return_url: Option<String>,
    pub url: Option<String>,
}

#[derive(Eq, PartialEq, serde::Serialize, Debug)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum StripeNextAction {
    RedirectToUrl {
        redirect_to_url: RedirectUrl,
    },
    DisplayBankTransferInformation {
        bank_transfer_steps_and_charges_details: payments::BankTransferNextStepsData,
    },
    ThirdPartySdkSessionToken {
        session_token: Option<payments::SessionToken>,
    },
    QrCodeInformation {
        image_data_url: Option<url::Url>,
        display_to_timestamp: Option<i64>,
        qr_code_url: Option<url::Url>,
        border_color: Option<String>,
        display_text: Option<String>,
    },
    FetchQrCodeInformation {
        qr_code_fetch_url: url::Url,
    },
    DisplayVoucherInformation {
        voucher_details: payments::VoucherNextStepData,
    },
    WaitScreenInformation {
        display_from_timestamp: i128,
        display_to_timestamp: Option<i128>,
        poll_config: Option<payments::PollConfig>,
    },
    InvokeSdkClient {
        next_action_data: payments::SdkNextActionData,
    },
    CollectOtp {
        consent_data_required: payments::MobilePaymentConsent,
    },
    InvokeHiddenIframe {
        iframe_data: payments::IframeData,
    },
}

pub(crate) fn into_stripe_next_action(
    next_action: Option<payments::NextActionData>,
    return_url: Option<String>,
) -> Option<StripeNextAction> {
    next_action.map(|next_action_data| match next_action_data {
        payments::NextActionData::RedirectToUrl { redirect_to_url } => {
            StripeNextAction::RedirectToUrl {
                redirect_to_url: RedirectUrl {
                    return_url,
                    url: Some(redirect_to_url),
                },
            }
        }
        payments::NextActionData::RedirectInsidePopup { popup_url, .. } => {
            StripeNextAction::RedirectToUrl {
                redirect_to_url: RedirectUrl {
                    return_url,
                    url: Some(popup_url),
                },
            }
        }
        payments::NextActionData::DisplayBankTransferInformation {
            bank_transfer_steps_and_charges_details,
        } => StripeNextAction::DisplayBankTransferInformation {
            bank_transfer_steps_and_charges_details,
        },
        payments::NextActionData::ThirdPartySdkSessionToken { session_token } => {
            StripeNextAction::ThirdPartySdkSessionToken { session_token }
        }

        payments::NextActionData::QrCodeInformation {
            image_data_url,
            display_to_timestamp,
            qr_code_url,
            border_color,
            display_text,
        } => StripeNextAction::QrCodeInformation {
            image_data_url,
            display_to_timestamp,
            qr_code_url,
            border_color,
            display_text,
        },
        payments::NextActionData::FetchQrCodeInformation { qr_code_fetch_url } => {
            StripeNextAction::FetchQrCodeInformation { qr_code_fetch_url }
        }
        payments::NextActionData::DisplayVoucherInformation { voucher_details } => {
            StripeNextAction::DisplayVoucherInformation { voucher_details }
        }
        payments::NextActionData::WaitScreenInformation {
            display_from_timestamp,
            display_to_timestamp,
            poll_config: _,
        } => StripeNextAction::WaitScreenInformation {
            display_from_timestamp,
            display_to_timestamp,
            poll_config: None,
        },
        payments::NextActionData::ThreeDsInvoke { .. } => StripeNextAction::RedirectToUrl {
            redirect_to_url: RedirectUrl {
                return_url: None,
                url: None,
            },
        },
        payments::NextActionData::InvokeSdkClient { next_action_data } => {
            StripeNextAction::InvokeSdkClient { next_action_data }
        }
        payments::NextActionData::CollectOtp {
            consent_data_required,
        } => StripeNextAction::CollectOtp {
            consent_data_required,
        },
        payments::NextActionData::InvokeHiddenIframe { iframe_data } => {
            StripeNextAction::InvokeHiddenIframe { iframe_data }
        }
    })
}

#[derive(Deserialize, Clone)]
pub struct StripePaymentRetrieveBody {
    pub client_secret: Option<String>,
}

//To handle payment types that have empty payment method data
fn get_pmd_based_on_payment_method_type(
    payment_method_type: Option<api_enums::PaymentMethodType>,
    billing_details: Option<hyperswitch_domain_models::address::Address>,
) -> Option<payments::PaymentMethodData> {
    match payment_method_type {
        Some(api_enums::PaymentMethodType::UpiIntent) => Some(payments::PaymentMethodData::Upi(
            payments::UpiData::UpiIntent(payments::UpiIntentData {}),
        )),
        Some(api_enums::PaymentMethodType::Fps) => {
            Some(payments::PaymentMethodData::RealTimePayment(Box::new(
                payments::RealTimePaymentData::Fps {},
            )))
        }
        Some(api_enums::PaymentMethodType::DuitNow) => {
            Some(payments::PaymentMethodData::RealTimePayment(Box::new(
                payments::RealTimePaymentData::DuitNow {},
            )))
        }
        Some(api_enums::PaymentMethodType::PromptPay) => {
            Some(payments::PaymentMethodData::RealTimePayment(Box::new(
                payments::RealTimePaymentData::PromptPay {},
            )))
        }
        Some(api_enums::PaymentMethodType::VietQr) => {
            Some(payments::PaymentMethodData::RealTimePayment(Box::new(
                payments::RealTimePaymentData::VietQr {},
            )))
        }
        Some(api_enums::PaymentMethodType::Ideal) => Some(
            payments::PaymentMethodData::BankRedirect(payments::BankRedirectData::Ideal {
                billing_details: billing_details.as_ref().map(|billing_data| {
                    payments::BankRedirectBilling {
                        billing_name: billing_data.get_optional_full_name(),
                        email: billing_data.email.clone(),
                    }
                }),
                bank_name: None,
                country: billing_details
                    .as_ref()
                    .and_then(|billing_data| billing_data.get_optional_country()),
            }),
        ),
        Some(api_enums::PaymentMethodType::LocalBankRedirect) => {
            Some(payments::PaymentMethodData::BankRedirect(
                payments::BankRedirectData::LocalBankRedirect {},
            ))
        }
        _ => None,
    }
}


// Function: new
// File: crates/api_models/src/payment_methods.rs
// Module: api_models

pub fn new(
        pm_type: RequestPaymentMethodTypes,
        connector: String,
        merchant_connector_id: String,
        pm: api_enums::PaymentMethod,
    ) -> Self


// Struct: CustomerListConstraints
// File: crates/diesel_models/src/query/customers.rs
// Module: diesel_models
// Implementations: 0

pub struct CustomerListConstraints


// Struct: NetworkField
// File: crates/hyperswitch_connectors/src/connectors/worldpayvantiv/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct NetworkField


// Implementation: impl api::MandateSetup for for Custombilling
// File: crates/hyperswitch_connectors/src/connectors/custombilling.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::MandateSetup for for Custombilling


// Struct: BluesnapPaymentsRequest
// File: crates/hyperswitch_connectors/src/connectors/bluesnap/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct BluesnapPaymentsRequest


// Function: polymorphic_macro_derive_inner
// File: crates/router_derive/src/macros/generate_schema.rs
// Module: router_derive

pub fn polymorphic_macro_derive_inner(
    input: syn::DeriveInput,
) -> syn::Result<proc_macro2::TokenStream>


// Struct: KlarnaAuthType
// File: crates/hyperswitch_connectors/src/connectors/klarna/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct KlarnaAuthType


// Function: get_temp_password
// File: crates/router/src/utils/user/password.rs
// Module: router

pub fn get_temp_password() -> Secret<String>


// Struct: LogConsole
// File: crates/router_env/src/logger/config.rs
// Module: router_env
// Implementations: 0

pub struct LogConsole


// Struct: ApplePayEncodedPaymentData
// File: crates/hyperswitch_connectors/src/connectors/bluesnap/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct ApplePayEncodedPaymentData


// Implementation: impl PaymentLinkNew
// File: crates/diesel_models/src/query/payment_link.rs
// Module: diesel_models
// Methods: 1 total (0 public)

impl PaymentLinkNew


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

pub struct CountryCodeWithName


// Implementation: impl PartialEq for for RefundMetricsBucketIdentifier
// File: crates/api_models/src/analytics/refunds.rs
// Module: api_models
// Methods: 1 total (0 public)

impl PartialEq for for RefundMetricsBucketIdentifier


// Function: set_validate_result
// File: crates/router/src/core/payment_methods/tokenize/card_executor.rs
// Module: router

pub fn set_validate_result(self) -> NetworkTokenizationBuilder<'a, CardRequestValidated>


// Implementation: impl api::RefundSync for for Payload
// File: crates/hyperswitch_connectors/src/connectors/payload.rs
// Module: hyperswitch_connectors
// Methods: 0 total (0 public)

impl api::RefundSync for for Payload


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

pub struct PaypalRefundRequest


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

impl api::PaymentSync for for Gocardless


// Function: get_pm_authentication_processor_config
// File: crates/connector_configs/src/connector.rs
// Module: connector_configs

pub fn get_pm_authentication_processor_config(
        connector: PmAuthConnectors,
    ) -> Result<Option<ConnectorTomlConfig>, String>


// Struct: LoonioRouterData
// File: crates/hyperswitch_connectors/src/connectors/loonio/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct LoonioRouterData<T>


// Struct: PhonepeRouterData
// File: crates/hyperswitch_connectors/src/connectors/phonepe/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 0

pub struct PhonepeRouterData<T>


// File: crates/diesel_models/src/query/configs.rs
// Module: diesel_models
// Public functions: 4

use diesel::{associations::HasTable, ExpressionMethods};

use super::generics;
use crate::{
    configs::{Config, ConfigNew, ConfigUpdate, ConfigUpdateInternal},
    errors,
    schema::configs::dsl,
    PgPooledConn, StorageResult,
};

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

impl Config {
    pub async fn find_by_key(conn: &PgPooledConn, key: &str) -> StorageResult<Self> {
        generics::generic_find_by_id::<<Self as HasTable>::Table, _, _>(conn, key.to_owned()).await
    }

    pub async fn update_by_key(
        conn: &PgPooledConn,
        key: &str,
        config_update: ConfigUpdate,
    ) -> StorageResult<Self> {
        match generics::generic_update_by_id::<<Self as HasTable>::Table, _, _, _>(
            conn,
            key.to_owned(),
            ConfigUpdateInternal::from(config_update),
        )
        .await
        {
            Err(error) => match error.current_context() {
                errors::DatabaseError::NoFieldsToUpdate => {
                    generics::generic_find_by_id::<<Self as HasTable>::Table, _, _>(
                        conn,
                        key.to_owned(),
                    )
                    .await
                }
                _ => Err(error),
            },
            result => result,
        }
    }

    pub async fn delete_by_key(conn: &PgPooledConn, key: &str) -> StorageResult<Self> {
        generics::generic_delete_one_with_result::<<Self as HasTable>::Table, _, _>(
            conn,
            dsl::key.eq(key.to_owned()),
        )
        .await
    }
}


// Struct: HelcimPaymentsResponse
// File: crates/hyperswitch_connectors/src/connectors/helcim/transformers.rs
// Module: hyperswitch_connectors
// Implementations: 1
// Traits: utils::MultipleCaptureSyncResponse

pub struct HelcimPaymentsResponse


// Implementation: impl PartialEq for for UserRole
// File: crates/diesel_models/src/user_role.rs
// Module: diesel_models
// Methods: 1 total (0 public)

impl PartialEq for for UserRole


// Implementation: impl SubscriptionHandler
// File: crates/router/src/core/subscription.rs
// Module: router
// Methods: 2 total (1 public)

impl SubscriptionHandler


    .await?;

    let response = create_intent_response
        .get_json_body()
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("Unexpected response from payments core")?;

    match response.status {
        enums::IntentStatus::Failed => {
            let pt_update = storage::ProcessTrackerUpdate::Update {
                name: process_tracker.name.clone(),
                tracking_data: Some(process_tracker.tracking_data.clone()),
                business_status: Some(request_retrigger.business_status.clone()),
                status: Some(request_retrigger.status),
                updated_at: Some(common_utils::date_time::now()),
                retry_count: Some(process_tracker.retry_count + 1),
                schedule_time: Some(request_retrigger.schedule_time.unwrap_or(
                    common_utils::date_time::now().saturating_add(time::Duration::seconds(600)),
                )),
            };
            let updated_pt = db
                .update_process(process_tracker, pt_update)
                .await
                .change_context(errors::ApiErrorResponse::GenericNotFoundError {
                    message: "Failed to update the process tracker".to_owned(),
                })?;
            let response = revenue_recovery::RevenueRecoveryResponse {
                id: updated_pt.id,
                name: updated_pt.name,
                schedule_time_for_payment: updated_pt.schedule_time,
                schedule_time_for_psync: None,
                status: updated_pt.status,
                business_status: updated_pt.business_status,
            };
            Ok(ApplicationResponse::Json(response))
        }
        enums::IntentStatus::Succeeded
        | enums::IntentStatus::Cancelled
        | enums::IntentStatus::CancelledPostCapture
        | enums::IntentStatus::Processing
        | enums::IntentStatus::RequiresCustomerAction
        | enums::IntentStatus::RequiresMerchantAction
        | enums::IntentStatus::RequiresPaymentMethod
        | enums::IntentStatus::RequiresConfirmation
        | enums::IntentStatus::RequiresCapture
        | enums::IntentStatus::PartiallyCaptured
        | enums::IntentStatus::PartiallyCapturedAndCapturable
        | enums::IntentStatus::PartiallyAuthorizedAndRequiresCapture
        | enums::IntentStatus::Conflicted
        | enums::IntentStatus::Expired => Err(report!(errors::ApiErrorResponse::NotSupported {
            message: "Invalid Payment Status ".to_owned(),
        })),
    }
}
pub async fn get_payment_response_using_payment_get_operation(
    state: &SessionState,
    payment_intent_id: &id_type::GlobalPaymentId,
    revenue_recovery_payment_data: &pcr::RevenueRecoveryPaymentData,
    merchant_context: &domain::MerchantContext,
    active_payment_attempt_id: Option<&id_type::GlobalAttemptId>,
) -> Result<Option<ApplicationResponse<PaymentsResponse>>, sch_errors::ProcessTrackerError> {
    match active_payment_attempt_id {
        Some(_) => {
            let payment_response = api::call_psync_api(
                state,
                payment_intent_id,
                revenue_recovery_payment_data,
                false,
                false,
            )
            .await?;
            let payments_response = payment_response.generate_response(
                state,
                None,
                None,
                None,
                merchant_context,
                &revenue_recovery_payment_data.profile,
                None,
            )?;

            Ok(Some(payments_response))
        }
        None => Ok(None),
    }
}

// This function can be implemented to reset the connector transmission and active attempt ID
// before pushing to the execute workflow.
pub async fn reset_connector_transmission_and_active_attempt_id_before_pushing_to_execute_workflow(
    state: &SessionState,
    payment_intent: &PaymentIntent,
    revenue_recovery_payment_data: &pcr::RevenueRecoveryPaymentData,
    active_payment_attempt_id: Option<&id_type::GlobalAttemptId>,
) -> Result<Option<()>, sch_errors::ProcessTrackerError> {
    let mut revenue_recovery_metadata = payment_intent
        .feature_metadata
        .as_ref()
        .and_then(|feature_metadata| feature_metadata.payment_revenue_recovery_metadata.clone())
        .get_required_value("Payment Revenue Recovery Metadata")?
        .convert_back();
    match active_payment_attempt_id {
        Some(_) => {
            // update the connector payment transmission field to Unsuccessful and unset active attempt id
            revenue_recovery_metadata.set_payment_transmission_field_for_api_request(
                enums::PaymentConnectorTransmission::ConnectorCallUnsuccessful,
            );

            let payment_update_req =
        api_payments::PaymentsUpdateIntentRequest::update_feature_metadata_and_active_attempt_with_api(
            payment_intent
                .feature_metadata
                .clone()
                .unwrap_or_default()
                .convert_back()
                .set_payment_revenue_recovery_metadata_using_api(
                    revenue_recovery_metadata.clone(),
                ),
            enums::UpdateActiveAttempt::Unset,
        );
            logger::info!(
                "Call made to payments update intent api , with the request body {:?}",
                payment_update_req
            );
            api::update_payment_intent_api(
                state,
                payment_intent.id.clone(),
                revenue_recovery_payment_data,
                payment_update_req,
            )
            .await
            .change_context(errors::RecoveryError::PaymentCallFailed)?;

            Ok(Some(()))
        }
        None => Ok(None),
    }
}


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

pub struct CardNetworkTypes


// File: crates/router/tests/connectors/blackhawknetwork.rs
// Module: router

use hyperswitch_domain_models::payment_method_data::{Card, PaymentMethodData};
use masking::Secret;
use router::types::{self, api, storage::enums};
use test_utils::connector_auth;

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

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

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

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

static CONNECTOR: BlackhawknetworkTest = BlackhawknetworkTest {};

fn get_default_payment_info() -> Option<utils::PaymentInfo> {
    None
}

fn payment_method_details() -> Option<types::PaymentsAuthorizeData> {
    None
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// Cards Negative scenarios
// Creates a payment with incorrect CVC.
#[actix_web::test]
async fn should_fail_payment_for_incorrect_cvc() {
    let response = CONNECTOR
        .make_payment(
            Some(types::PaymentsAuthorizeData {
                payment_method_data: PaymentMethodData::Card(Card {
                    card_cvc: Secret::new("12345".to_string()),
                    ..utils::CCardType::default().0
                }),
                ..utils::PaymentAuthorizeType::default().0
            }),
            get_default_payment_info(),
        )
        .await
        .unwrap();
    assert_eq!(
        response.response.unwrap_err().message,
        "Your card's security code is invalid.".to_string(),
    );
}

// Creates a payment with incorrect expiry month.
#[actix_web::test]
async fn should_fail_payment_for_invalid_exp_month() {
    let response = CONNECTOR
        .make_payment(
            Some(types::PaymentsAuthorizeData {
                payment_method_data: PaymentMethodData::Card(Card {
                    card_exp_month: Secret::new("20".to_string()),
                    ..utils::CCardType::default().0
                }),
                ..utils::PaymentAuthorizeType::default().0
            }),
            get_default_payment_info(),
        )
        .await
        .unwrap();
    assert_eq!(
        response.response.unwrap_err().message,
        "Your card's expiration month is invalid.".to_string(),
    );
}

// Creates a payment with incorrect expiry year.
#[actix_web::test]
async fn should_fail_payment_for_incorrect_expiry_year() {
    let response = CONNECTOR
        .make_payment(
            Some(types::PaymentsAuthorizeData {
                payment_method_data: PaymentMethodData::Card(Card {
                    card_exp_year: Secret::new("2000".to_string()),
                    ..utils::CCardType::default().0
                }),
                ..utils::PaymentAuthorizeType::default().0
            }),
            get_default_payment_info(),
        )
        .await
        .unwrap();
    assert_eq!(
        response.response.unwrap_err().message,
        "Your card's expiration year is invalid.".to_string(),
    );
}

// Voids a payment using automatic capture flow (Non 3DS).
#[actix_web::test]
async fn should_fail_void_payment_for_auto_capture() {
    let authorize_response = CONNECTOR
        .make_payment(payment_method_details(), get_default_payment_info())
        .await
        .unwrap();
    assert_eq!(authorize_response.status, enums::AttemptStatus::Charged);
    let txn_id = utils::get_connector_transaction_id(authorize_response.response);
    assert_ne!(txn_id, None, "Empty connector transaction id");
    let void_response = CONNECTOR
        .void_payment(txn_id.unwrap(), None, get_default_payment_info())
        .await
        .unwrap();
    assert_eq!(
        void_response.response.unwrap_err().message,
        "You cannot cancel this PaymentIntent because it has a status of succeeded."
    );
}

// Captures a payment using invalid connector payment id.
#[actix_web::test]
async fn should_fail_capture_for_invalid_payment() {
    let capture_response = CONNECTOR
        .capture_payment("123456789".to_string(), None, get_default_payment_info())
        .await
        .unwrap();
    assert_eq!(
        capture_response.response.unwrap_err().message,
        String::from("No such payment_intent: '123456789'")
    );
}

// Refunds a payment with refund amount higher than payment amount.
#[actix_web::test]
async fn should_fail_for_refund_amount_higher_than_payment_amount() {
    let response = CONNECTOR
        .make_payment_and_refund(
            payment_method_details(),
            Some(types::RefundsData {
                refund_amount: 150,
                ..utils::PaymentRefundType::default().0
            }),
            get_default_payment_info(),
        )
        .await
        .unwrap();
    assert_eq!(
        response.response.unwrap_err().message,
        "Refund amount (₹1.50) is greater than charge amount (₹1.00)",
    );
}

// Connector dependent test cases goes here

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


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

pub struct UserOrgMerchantCreateRequest