pub struct NetceteraAuthenticationRequest {
    /// Specifies the preferred version of 3D Secure protocol to be utilized while executing 3D Secure authentication.
    /// 3DS Server initiates an authentication request with the preferred version and if this version is not supported by
    /// other 3D Secure components, it falls back to the next supported version(s) and continues authentication.
    ///
    /// If the preferred version is enforced by setting  #enforcePreferredProtocolVersion flag, but this version
    /// is not supported by one of the 3D Secure components, 3DS Server does not initiate an authentication and provides
    /// corresponding error message to the customer.
    ///
    /// The accepted values are:
    /// - 2.1.0 -> prefer authentication with 2.1.0 version,
    /// - 2.2.0 -> prefer authentication with 2.2.0 version,
    /// - 2.3.1 -> prefer authentication with 2.3.1 version,
    /// - latest -> prefer authentication with the latest version, the 3DS Server is certified for. 2.3.1 at this moment.
    pub preferred_protocol_version: Option<SemanticVersion>,
    /// Boolean flag that enforces preferred 3D Secure protocol version to be used in 3D Secure authentication.
    /// The value should be set true to enforce preferred version. If value is false or not provided,
    /// 3DS Server can fall back to next supported 3DS protocol version while initiating 3D Secure authentication.
    ///
    /// For application initiated transactions (deviceChannel = '01'), the preferred protocol version must be enforced.
    pub enforce_preferred_protocol_version: Option<bool>,
    pub device_channel: netcetera_types::NetceteraDeviceChannel,
    /// Identifies the category of the message for a specific use case. The accepted values are:
    ///
    /// - 01 -> PA
    /// - 02 -> NPA
    /// - 80 - 99 -> PS Specific Values (80 -> MasterCard Identity Check Insights;
    ///                                85 -> MasterCard Identity Check, Production Validation PA;
    ///                                86 -> MasterCard Identity Check, Production Validation NPA)
    pub message_category: netcetera_types::NetceteraMessageCategory,
    #[serde(rename = "threeDSCompInd")]
    pub three_ds_comp_ind: Option<netcetera_types::ThreeDSMethodCompletionIndicator>,
    /**
     * Contains the 3DS Server Transaction ID used during the previous execution of the 3DS method. Accepted value
     * length is 36 characters. Accepted value is a Canonical format as defined in IETF RFC 4122. May utilise any of the
     * specified versions if the output meets specified requirements.
     *
     * This field is required if the 3DS Requestor reuses previous 3DS Method execution with deviceChannel = 02 (BRW).
     * Available for supporting EMV 3DS 2.3.1 and later versions.
     */
    #[serde(rename = "threeDSMethodId")]
    pub three_ds_method_id: Option<String>,
    #[serde(rename = "threeDSRequestor")]
    pub three_ds_requestor: Option<netcetera_types::ThreeDSRequestor>,
    #[serde(rename = "threeDSServerTransID")]
    pub three_ds_server_trans_id: String,
    #[serde(rename = "threeDSRequestorURL")]
    pub three_ds_requestor_url: Option<String>,
    pub cardholder_account: netcetera_types::CardholderAccount,
    pub cardholder: Option<netcetera_types::Cardholder>,
    pub purchase: Option<netcetera_types::Purchase>,
    pub acquirer: Option<netcetera_types::AcquirerData>,
    pub merchant: Option<netcetera_types::MerchantData>,
    pub broad_info: Option<String>,
    pub device_render_options: Option<netcetera_types::DeviceRenderingOptionsSupported>,
    pub message_extension: Option<Vec<MessageExtensionAttribute>>,
    pub challenge_message_extension: Option<Vec<MessageExtensionAttribute>>,
    pub browser_information: Option<netcetera_types::Browser>,
    #[serde(rename = "threeRIInd")]
    pub three_ri_ind: Option<String>,
    pub sdk_information: Option<netcetera_types::Sdk>,
    pub device: Option<String>,
    pub multi_transaction: Option<String>,
    pub device_id: Option<String>,
    pub user_id: Option<String>,
    pub payee_origin: Option<url::Url>,
}


pub struct NovolnetRedirectionResponse {
    status: NovalnetTransactionStatus,
    tid: Secret<String>,
}


pub struct Xendit {
    amount_converter: &'static (dyn AmountConvertor<Output = FloatMajorUnit> + Sync),
}


pub fn payments_confirm_intent() {}


impl std::error::Error for ApiErrorResponse {}

impl std::error::Error for for ApiErrorResponse


pub fn generate_runner() -> Result<ReturnArgs> {
    let args = Args::parse();

    match args.get_module_name() {
        Some(Module::Users) => generate_newman_command_for_users(),
        Some(Module::Connector) => generate_newman_command_for_connector(),
        // Running connector tests when no module is passed to keep the previous test behavior same
        None => generate_newman_command_for_connector(),
    }
}


File: crates/router/src/events/event_logger.rs
 Public structs: 1

use std::collections::HashMap;

use events::{EventsError, Message, MessagingInterface};
use masking::ErasedMaskSerialize;
use time::PrimitiveDateTime;

use super::EventType;
use crate::services::{kafka::KafkaMessage, logger};

#[derive(Clone, Debug, Default)]
pub struct EventLogger {}

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

impl MessagingInterface for EventLogger {
    type MessageClass = EventType;

    fn send_message<T>(
        &self,
        data: T,
        metadata: HashMap<String, String>,
        _timestamp: PrimitiveDateTime,
    ) -> error_stack::Result<(), EventsError>
    where
        T: Message<Class = Self::MessageClass> + ErasedMaskSerialize,
    {
        logger::info!(event =? data.masked_serialize().unwrap_or_else(|e| serde_json::json!({"error": e.to_string()})), event_type =? data.get_message_class(), event_id =? data.identifier(), log_type =? "event", metadata = ?metadata);
        Ok(())
    }
}


impl api::RefundSync for Braintree {}


pub struct BitpayErrorResponse {
    pub error: String,
    pub code: Option<String>,
    pub message: Option<String>,
}


pub struct AnalysisError {
    #[serde(flatten)]
    pub error_type: AnalysisErrorType,
    pub metadata: Metadata,
}


impl MasterKeyInterface for Store {
    fn get_master_key(&self) -> &[u8] {
        self.master_key().peek()
    }
}


pub async fn perform_calculate_workflow(
    state: &SessionState,
    process: &storage::ProcessTracker,
    profile: &domain::Profile,
    merchant_context: domain::MerchantContext,
    tracking_data: &pcr::RevenueRecoveryWorkflowTrackingData,
    revenue_recovery_payment_data: &pcr::RevenueRecoveryPaymentData,
    payment_intent: &PaymentIntent,
) -> Result<(), sch_errors::ProcessTrackerError> {
    let db = &*state.store;
    let merchant_id = revenue_recovery_payment_data.merchant_account.get_id();
    let profile_id = revenue_recovery_payment_data.profile.get_id();
    let billing_mca_id = revenue_recovery_payment_data.billing_mca.get_id();

    logger::info!(
        process_id = %process.id,
        payment_id = %tracking_data.global_payment_id.get_string_repr(),
        "Starting CALCULATE_WORKFLOW..."
    );

    // 1. Extract connector_customer_id and token_list from tracking_data
    let connector_customer_id = payment_intent
        .extract_connector_customer_id_from_payment_intent()
        .change_context(errors::RecoveryError::ValueNotFound)
        .attach_printable("Failed to extract customer ID from payment intent")?;

    let merchant_context_from_revenue_recovery_payment_data =
        domain::MerchantContext::NormalMerchant(Box::new(domain::Context(
            revenue_recovery_payment_data.merchant_account.clone(),
            revenue_recovery_payment_data.key_store.clone(),
        )));

    let retry_algorithm_type = match profile
        .revenue_recovery_retry_algorithm_type
        .filter(|retry_type|
             *retry_type != common_enums::RevenueRecoveryAlgorithmType::Monitoring) // ignore Monitoring in profile
        .unwrap_or(tracking_data.revenue_recovery_retry)                                                                  // fallback to tracking_data
    {
        common_enums::RevenueRecoveryAlgorithmType::Smart => common_enums::RevenueRecoveryAlgorithmType::Smart,
        common_enums::RevenueRecoveryAlgorithmType::Cascading => common_enums::RevenueRecoveryAlgorithmType::Cascading,
        common_enums::RevenueRecoveryAlgorithmType::Monitoring => {
            return Err(sch_errors::ProcessTrackerError::ProcessUpdateFailed);
        }
    };

    // 2. Get best available token
    let best_time_to_schedule = match workflows::revenue_recovery::get_token_with_schedule_time_based_on_retry_algorithm_type(
        state,
        &connector_customer_id,
        payment_intent,
        retry_algorithm_type,
        process.retry_count,
    )
    .await
    {
        Ok(token_opt) => token_opt,
        Err(e) => {
            logger::error!(
                error = ?e,
                connector_customer_id = %connector_customer_id,
                "Failed to get best PSP token"
            );
            None
        }
    };

    match best_time_to_schedule {
        Some(scheduled_time) => {
            logger::info!(
                process_id = %process.id,
                connector_customer_id = %connector_customer_id,
                "Found best available token, creating EXECUTE_WORKFLOW task"
            );

            // 3. If token found: create EXECUTE_WORKFLOW task and finish CALCULATE_WORKFLOW
            insert_execute_pcr_task_to_pt(
                &tracking_data.billing_mca_id,
                state,
                &tracking_data.merchant_id,
                payment_intent,
                &tracking_data.profile_id,
                &tracking_data.payment_attempt_id,
                storage::ProcessTrackerRunner::PassiveRecoveryWorkflow,
                retry_algorithm_type,
                scheduled_time,
            )
            .await?;

            db.as_scheduler()
                .finish_process_with_business_status(
                    process.clone(),
                    business_status::CALCULATE_WORKFLOW_SCHEDULED,
                )
                .await
                .map_err(|e| {
                    logger::error!(
                        process_id = %process.id,
                        error = ?e,
                        "Failed to update CALCULATE_WORKFLOW status to complete"
                    );
                    sch_errors::ProcessTrackerError::ProcessUpdateFailed
                })?;

            logger::info!(
                process_id = %process.id,
                connector_customer_id = %connector_customer_id,
                "CALCULATE_WORKFLOW completed successfully"
            );
        }

        None => {
            let scheduled_token = match storage::revenue_recovery_redis_operation::
                RedisTokenManager::get_payment_processor_token_with_schedule_time(state, &connector_customer_id)
                .await {
                    Ok(scheduled_token_opt) => scheduled_token_opt,
                    Err(e) => {
                        logger::error!(
                            error = ?e,
                            connector_customer_id = %connector_customer_id,
                            "Failed to get PSP token status"
                        );
                        None
                    }
                };

            match scheduled_token {
                Some(scheduled_token) => {
                    // Update scheduled time to scheduled time + 15 minutes
                    // here scheduled_time is the wait time 15 minutes is a buffer time that we are adding
                    logger::info!(
                        process_id = %process.id,
                        connector_customer_id = %connector_customer_id,
                        "No token but time available, rescheduling for scheduled time + 15 mins"
                    );

                    update_calculate_job_schedule_time(
                        db,
                        process,
                        time::Duration::seconds(
                            state
                                .conf
                                .revenue_recovery
                                .recovery_timestamp
                                .job_schedule_buffer_time_in_seconds,
                        ),
                        scheduled_token.scheduled_at,
                        &connector_customer_id,
                    )
                    .await?;
                }
                None => {
                    let hard_decline_flag = storage::revenue_recovery_redis_operation::
                        RedisTokenManager::are_all_tokens_hard_declined(
                            state,
                            &connector_customer_id
                        )
                        .await
                        .ok()
                        .unwrap_or(false);

                    match hard_decline_flag {
                        false => {
                            logger::info!(
                                process_id = %process.id,
                                connector_customer_id = %connector_customer_id,
                                "Hard decline flag is false, rescheduling for scheduled time + 15 mins"
                            );

                            update_calculate_job_schedule_time(
                                db,
                                process,
                                time::Duration::seconds(
                                    state
                                        .conf
                                        .revenue_recovery
                                        .recovery_timestamp
                                        .job_schedule_buffer_time_in_seconds,
                                ),
                                Some(common_utils::date_time::now()),
                                &connector_customer_id,
                            )
                            .await?;
                        }
                        true => {
                            // Finish calculate workflow with CALCULATE_WORKFLOW_FINISH
                            logger::info!(
                                process_id = %process.id,
                                connector_customer_id = %connector_customer_id,
                                "No token available, finishing CALCULATE_WORKFLOW"
                            );

                            db.as_scheduler()
                                .finish_process_with_business_status(
                                    process.clone(),
                                    business_status::CALCULATE_WORKFLOW_FINISH,
                                )
                                .await
                                .map_err(|e| {
                                    logger::error!(
                                        process_id = %process.id,
                                        error = ?e,
                                        "Failed to finish CALCULATE_WORKFLOW"
                                    );
                                    sch_errors::ProcessTrackerError::ProcessUpdateFailed
                                })?;

                            logger::info!(
                                process_id = %process.id,
                                connector_customer_id = %connector_customer_id,
                                "CALCULATE_WORKFLOW finished successfully"
                            );
                        }
                    }
                }
            }
        }
    }
    Ok(())
}


OpenAPI Block Path: components.schemas.WalletAdditionalData
{
  "oneOf": [
    {
      "$ref": "#/components/schemas/PaypalAdditionalData"
    },
    {
      "$ref": "#/components/schemas/VenmoAdditionalData"
    }
  ],
  "description": "Masked payout method details for wallet payout method"
}


pub struct SdkInitiatedCount;


impl ConnectorCommon for Dlocal {
    fn id(&self) -> &'static str {
        "dlocal"
    }

    fn get_currency_unit(&self) -> api::CurrencyUnit {
        api::CurrencyUnit::Minor
    }

    fn common_get_content_type(&self) -> &'static str {
        "application/json"
    }

    fn base_url<'a>(&self, connectors: &'a Connectors) -> &'a str {
        connectors.dlocal.base_url.as_ref()
    }

    fn build_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        let response: dlocal::DlocalErrorResponse = res
            .response
            .parse_struct("Dlocal ErrorResponse")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;

        event_builder.map(|i: &mut ConnectorEvent| i.set_error_response_body(&response));
        router_env::logger::info!(connector_response=?response);

        Ok(ErrorResponse {
            status_code: res.status_code,
            code: response.code.to_string(),
            message: response.message,
            reason: response.param,
            attempt_status: None,
            connector_transaction_id: None,
            network_advice_code: None,
            network_decline_code: None,
            network_error_message: None,
            connector_metadata: None,
        })
    }
}


pub struct NotAvailableFlows {
    pub capture_method: Option<api_enums::CaptureMethod>,
}


impl<T> RequiredFromNullable<T> {
        /// Extracts the inner value from the wrapper
        pub fn into_inner(self) -> T {
            self.0
        }
    }


pub struct BarclaycardRsyncResponse {
    id: String,
    application_information: Option<RsyncApplicationInformation>,
    error_information: Option<BarclaycardErrorInformation>,
}


pub struct ResponseStatus {
    pub environment: String,
    pub response_type: String,
    pub response_code: ForteResponseCode,
    pub response_desc: String,
    pub authorization_code: String,
    pub avs_result: Option<String>,
    pub cvv_result: Option<String>,
}


pub async fn update_by_unified_code_unified_message_locale(
        conn: &PgPooledConn,
        unified_code: String,
        unified_message: String,
        locale: String,
        data: UnifiedTranslationsUpdate,
    ) -> StorageResult<Self> {
        generics::generic_update_with_results::<
            <Self as HasTable>::Table,
            UnifiedTranslationsUpdateInternal,
            _,
            _,
        >(
            conn,
            dsl::unified_code
                .eq(unified_code)
                .and(dsl::unified_message.eq(unified_message))
                .and(dsl::locale.eq(locale)),
            data.into(),
        )
        .await?
        .first()
        .cloned()
        .ok_or_else(|| {
            report!(errors::DatabaseError::NotFound)
                .attach_printable("Error while updating unified_translations entry")
        })
    }


pub async fn routing_retrieve_default_config(
    state: web::Data<AppState>,
    req: HttpRequest,
    path: web::Path<common_utils::id_type::ProfileId>,
) -> impl Responder {
    let path = path.into_inner();
    Box::pin(oss_api::server_wrap(
        Flow::RoutingRetrieveDefaultConfig,
        state,
        &req,
        path.clone(),
        |state, auth: auth::AuthenticationData, profile_id, _| {
            let merchant_context = domain::MerchantContext::NormalMerchant(Box::new(
                domain::Context(auth.merchant_account, auth.key_store),
            ));
            routing::retrieve_default_fallback_algorithm_for_profile(
                state,
                merchant_context,
                profile_id,
            )
        },
        #[cfg(not(feature = "release"))]
        auth::auth_type(
            &auth::V2ApiKeyAuth {
                is_connected_allowed: false,
                is_platform_allowed: false,
            },
            &auth::JWTAuthProfileFromRoute {
                profile_id: path,
                required_permission: Permission::MerchantRoutingRead,
            },
            req.headers(),
        ),
        #[cfg(feature = "release")]
        &auth::JWTAuthProfileFromRoute {
            profile_id: path,
            required_permission: Permission::MerchantRoutingRead,
        },
        api_locking::LockAction::NotApplicable,
    ))
    .await
}


pub struct GooglePayPaymentInformation {
    fluid_data: FluidData,
}


impl webhooks::IncomingWebhook for Silverflow {
    fn get_webhook_object_reference_id(
        &self,
        request: &webhooks::IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<api_models::webhooks::ObjectReferenceId, errors::ConnectorError> {
        let webhook_body = String::from_utf8(request.body.to_vec())
            .change_context(errors::ConnectorError::WebhookReferenceIdNotFound)?;

        let webhook_event: silverflow::SilverflowWebhookEvent = webhook_body
            .parse_struct("SilverflowWebhookEvent")
            .change_context(errors::ConnectorError::WebhookReferenceIdNotFound)?;

        // For payments, use charge_key; for refunds, use refund_key
        if let Some(charge_key) = webhook_event.event_data.charge_key {
            Ok(api_models::webhooks::ObjectReferenceId::PaymentId(
                api_models::payments::PaymentIdType::ConnectorTransactionId(charge_key),
            ))
        } else if let Some(refund_key) = webhook_event.event_data.refund_key {
            Ok(api_models::webhooks::ObjectReferenceId::RefundId(
                api_models::webhooks::RefundIdType::ConnectorRefundId(refund_key),
            ))
        } else {
            Err(errors::ConnectorError::WebhookReferenceIdNotFound.into())
        }
    }

    fn get_webhook_event_type(
        &self,
        request: &webhooks::IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<api_models::webhooks::IncomingWebhookEvent, errors::ConnectorError> {
        let webhook_body = String::from_utf8(request.body.to_vec())
            .change_context(errors::ConnectorError::WebhookEventTypeNotFound)?;

        let webhook_event: silverflow::SilverflowWebhookEvent = webhook_body
            .parse_struct("SilverflowWebhookEvent")
            .change_context(errors::ConnectorError::WebhookEventTypeNotFound)?;

        match webhook_event.event_type.as_str() {
            "charge.authorization.succeeded" => {
                // Handle manual capture flow: check if clearing is still pending
                if let Some(status) = webhook_event.event_data.status {
                    match (&status.authorization, &status.clearing) {
                        (
                            silverflow::SilverflowAuthorizationStatus::Approved,
                            silverflow::SilverflowClearingStatus::Pending,
                        ) => {
                            // Manual capture: authorization succeeded, but clearing is pending
                            Ok(api_models::webhooks::IncomingWebhookEvent::PaymentIntentAuthorizationSuccess)
                        }
                        (
                            silverflow::SilverflowAuthorizationStatus::Approved,
                            silverflow::SilverflowClearingStatus::Cleared,
                        ) => {
                            // Automatic capture: authorization and clearing both completed
                            Ok(api_models::webhooks::IncomingWebhookEvent::PaymentIntentSuccess)
                        }
                        _ => {
                            // Fallback for other authorization states
                            Ok(api_models::webhooks::IncomingWebhookEvent::PaymentIntentAuthorizationSuccess)
                        }
                    }
                } else {
                    // Fallback when status is not available
                    Ok(api_models::webhooks::IncomingWebhookEvent::PaymentIntentAuthorizationSuccess)
                }
            }
            "charge.authorization.failed" => {
                Ok(api_models::webhooks::IncomingWebhookEvent::PaymentIntentFailure)
            }
            "charge.clearing.succeeded" => {
                Ok(api_models::webhooks::IncomingWebhookEvent::PaymentIntentSuccess)
            }
            "charge.clearing.failed" => {
                Ok(api_models::webhooks::IncomingWebhookEvent::PaymentIntentFailure)
            }
            "refund.succeeded" => Ok(api_models::webhooks::IncomingWebhookEvent::RefundSuccess),
            "refund.failed" => Ok(api_models::webhooks::IncomingWebhookEvent::RefundFailure),
            _ => Ok(api_models::webhooks::IncomingWebhookEvent::EventNotSupported),
        }
    }

    fn get_webhook_resource_object(
        &self,
        request: &webhooks::IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<Box<dyn masking::ErasedMaskSerialize>, errors::ConnectorError> {
        let webhook_body = String::from_utf8(request.body.to_vec())
            .change_context(errors::ConnectorError::WebhookResourceObjectNotFound)?;

        let webhook_event: silverflow::SilverflowWebhookEvent = webhook_body
            .parse_struct("SilverflowWebhookEvent")
            .change_context(errors::ConnectorError::WebhookResourceObjectNotFound)?;

        Ok(Box::new(webhook_event))
    }

    fn get_webhook_source_verification_algorithm(
        &self,
        _request: &webhooks::IncomingWebhookRequestDetails<'_>,
    ) -> CustomResult<Box<dyn crypto::VerifySignature + Send>, errors::ConnectorError> {
        Ok(Box::new(crypto::HmacSha256))
    }

    fn get_webhook_source_verification_signature(
        &self,
        request: &webhooks::IncomingWebhookRequestDetails<'_>,
        _connector_webhook_secrets: &api_models::webhooks::ConnectorWebhookSecrets,
    ) -> CustomResult<Vec<u8>, errors::ConnectorError> {
        let signature = request
            .headers
            .get("X-Silverflow-Signature")
            .ok_or(errors::ConnectorError::WebhookSignatureNotFound)?
            .to_str()
            .change_context(errors::ConnectorError::WebhookSignatureNotFound)?;

        hex::decode(signature).change_context(errors::ConnectorError::WebhookSignatureNotFound)
    }

    fn get_webhook_source_verification_message(
        &self,
        request: &webhooks::IncomingWebhookRequestDetails<'_>,
        _merchant_id: &common_utils::id_type::MerchantId,
        _connector_webhook_secrets: &api_models::webhooks::ConnectorWebhookSecrets,
    ) -> CustomResult<Vec<u8>, errors::ConnectorError> {
        Ok(request.body.to_vec())
    }
}

impl webhooks::IncomingWebhook for for Silverflow


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

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

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

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

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

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

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

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

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

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

    #[serde(rename = "NUMTRANS")]
    pub transaction_number: String,

    #[serde(rename = "NUMAPPEL")]
    pub paybox_order_id: String,
}


pub struct HyperwalletPaymentsRequest {
    amount: StringMinorUnit,
    card: HyperwalletCard,
}


pub async fn merchant_account_list() {}


pub struct ExpiryResponse {
    month: Option<Secret<i32>>,
    year: Option<Secret<i32>>,
}


pub struct GpaymentsPreAuthenticationRequest {
    pub acct_number: CardNumber,
    pub card_scheme: Option<CardScheme>,
    pub challenge_window_size: Option<ChallengeWindowSize>,

    /// URL where the 3DS requestor receives events during authentication.
    /// ActiveServer calls this URL through the iframe to notify events occurring during authentication.
    ///
    /// Example: "https://example.requestor.com/3ds-notify"
    /// Length: Maximum 2000 characters
    pub event_callback_url: String,

    /// Merchant identifier assigned by the acquirer.
    /// This may be the same value used in authorization requests sent on behalf of the 3DS Requestor.
    ///
    /// Example: "1234567890123456789012345678901234"
    /// Length: Maximum 35 characters
    pub merchant_id: common_utils::id_type::MerchantId,

    /// Optional boolean. If set to true, ActiveServer will not collect the browser information automatically.
    /// The requestor must have a backend implementation to collect browser information.
    pub skip_auto_browser_info_collect: Option<bool>,

    /// Universal unique transaction identifier assigned by the 3DS Requestor to identify a single transaction.
    ///
    /// Example: "6afa6072-9412-446b-9673-2f98b3ee98a2"
    /// Length: 36 characters
    #[serde(rename = "threeDSRequestorTransID")]
    pub three_ds_requestor_trans_id: String,
}


impl api::Refund for Helcim {}


pub async fn create_payment_method_for_confirm(
    state: &SessionState,
    customer_id: &id_type::GlobalCustomerId,
    payment_method_id: id_type::GlobalPaymentMethodId,
    external_vault_source: Option<id_type::MerchantConnectorAccountId>,
    merchant_id: &id_type::MerchantId,
    key_store: &domain::MerchantKeyStore,
    storage_scheme: enums::MerchantStorageScheme,
    payment_method_type: storage_enums::PaymentMethod,
    payment_method_subtype: storage_enums::PaymentMethodType,
    encrypted_payment_method_billing_address: Option<
        Encryptable<hyperswitch_domain_models::address::Address>,
    >,
    encrypted_payment_method_data: Option<Encryptable<payment_methods::PaymentMethodsData>>,
    encrypted_external_vault_token_data: Option<
        Encryptable<payment_methods::ExternalVaultTokenData>,
    >,
) -> CustomResult<domain::PaymentMethod, errors::ApiErrorResponse> {
    let db = &*state.store;
    let key_manager_state = &state.into();
    let current_time = common_utils::date_time::now();

    let response = db
        .insert_payment_method(
            key_manager_state,
            key_store,
            domain::PaymentMethod {
                customer_id: customer_id.to_owned(),
                merchant_id: merchant_id.to_owned(),
                id: payment_method_id,
                locker_id: None,
                payment_method_type: Some(payment_method_type),
                payment_method_subtype: Some(payment_method_subtype),
                payment_method_data: encrypted_payment_method_data,
                connector_mandate_details: None,
                customer_acceptance: None,
                client_secret: None,
                status: enums::PaymentMethodStatus::Inactive,
                network_transaction_id: None,
                created_at: current_time,
                last_modified: current_time,
                last_used_at: current_time,
                payment_method_billing_address: encrypted_payment_method_billing_address,
                updated_by: None,
                version: common_types::consts::API_VERSION,
                locker_fingerprint_id: None,
                network_token_locker_id: None,
                network_token_payment_method_data: None,
                network_token_requestor_reference_id: None,
                external_vault_source,
                external_vault_token_data: encrypted_external_vault_token_data,
            },
            storage_scheme,
        )
        .await
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("Failed to add payment method in db")?;

    Ok(response)
}


impl PartialEq for FrmMetricsBucketIdentifier {
    fn eq(&self, other: &Self) -> bool {
        let mut left = DefaultHasher::new();
        self.hash(&mut left);
        let mut right = DefaultHasher::new();
        other.hash(&mut right);
        left.finish() == right.finish()
    }
}

impl PartialEq for for FrmMetricsBucketIdentifier


pub struct Custombilling {
    amount_converter: &'static (dyn AmountConvertor<Output = StringMinorUnit> + Sync),
}


pub struct ApiErrorResponse {
    pub code: Option<String>,
    pub message: String,
}


pub fn get_customer_id(&self) -> Option<&id_type::CustomerId> {
        self.customer_id
            .as_ref()
            .or(self.customer.as_ref().map(|customer| &customer.id))
    }


impl LockingInput {
    fn get_redis_locking_key(&self, merchant_id: &common_utils::id_type::MerchantId) -> String {
        format!(
            "{}_{}_{}_{}",
            API_LOCK_PREFIX,
            merchant_id.get_string_repr(),
            self.api_identifier,
            self.unique_locking_key
        )
    }
}


impl api::PaymentVoid for Razorpay {}


Documentation: api-reference/v2/profile/profile--activate-routing-algorithm.mdx
# Type: Doc File

---
openapi: patch /v2/profiles/{id}/activate-routing-algorithm
---


impl MerchantId {
    pub fn new(merchant_id: String) -> UserResult<Self> {
        let merchant_id = merchant_id.trim().to_lowercase().replace(' ', "_");
        let is_empty_or_whitespace = merchant_id.is_empty();

        let is_all_valid_characters = merchant_id.chars().all(|x| x.is_alphanumeric() || x == '_');
        if is_empty_or_whitespace || !is_all_valid_characters {
            Err(UserErrors::MerchantIdParsingError.into())
        } else {
            Ok(Self(merchant_id.to_string()))
        }
    }

    pub fn get_secret(&self) -> String {
        self.0.clone()
    }
}


pub struct PaymentMethodDetails {
    payment_card: Option<PaymentCardDetails>,
    payment_method_type: Option<String>,
    payment_method_brand: Option<String>,
}


pub struct AmazonpayPaymentsResponse {
    charge_id: String,
    charge_amount: ChargeAmount,
    charge_permission_id: String,
    capture_amount: Option<ChargeAmount>,
    refunded_amount: Option<ChargeAmount>,
    soft_descriptor: Option<String>,
    provider_metadata: Option<ProviderMetadata>,
    converted_amount: Option<ChargeAmount>,
    conversion_rate: Option<f64>,
    channel: Option<String>,
    charge_initiator: Option<String>,
    status_details: PaymentsStatusDetails,
    creation_timestamp: String,
    expiration_timestamp: String,
    release_environment: Option<ReleaseEnvironment>,
    merchant_metadata: Option<MerchantMetadata>,
    platform_id: Option<String>,
    web_checkout_details: Option<WebCheckoutDetails>,
    disbursement_details: Option<String>,
    payment_method: Option<String>,
}


pub struct ApplePayWalletData {
    /// The payment data of Apple pay
    pub payment_data: common_types::payments::ApplePayPaymentData,
    /// The payment method of Apple pay
    pub payment_method: ApplepayPaymentMethod,
    /// The unique identifier for the transaction
    pub transaction_identifier: String,
}


/// get_should_call_gsm_payout_key
    pub fn get_should_call_gsm_payout_key(
        &self,
        payout_retry_type: common_enums::PayoutRetryType,
    ) -> String {
        match payout_retry_type {
            common_enums::PayoutRetryType::SingleConnector => format!(
                "should_call_gsm_single_connector_payout_{}",
                self.get_string_repr()
            ),
            common_enums::PayoutRetryType::MultiConnector => format!(
                "should_call_gsm_multiple_connector_payout_{}",
                self.get_string_repr()
            ),
        }
    }


pub fn new(tracking_id: String, return_url: String) -> Self {
        Self {
            tracking_id,
            operations: vec![PartnerReferralOperations {
                operation: PayPalReferralOperationType::ApiIntegration,
                api_integration_preference: PartnerReferralIntegrationPreference {
                    rest_api_integration: PartnerReferralRestApiIntegration {
                        integration_method: IntegrationMethod::Paypal,
                        integration_type: PayPalIntegrationType::ThirdParty,
                        third_party_details: PartnerReferralThirdPartyDetails {
                            features: vec![
                                PayPalFeatures::Payment,
                                PayPalFeatures::Refund,
                                PayPalFeatures::Vault,
                                PayPalFeatures::AccessMerchantInformation,
                                PayPalFeatures::BillingAgreement,
                                PayPalFeatures::ReadSellerDispute,
                            ],
                        },
                    },
                },
            }],
            products: vec![PayPalProducts::Ppcp, PayPalProducts::AdvancedVaulting],
            capabilities: vec![PayPalCapabilities::PaypalWalletVaultingAdvanced],
            partner_config_override: PartnerConfigOverride {
                partner_logo_url: "https://hyperswitch.io/img/websiteIcon.svg".to_string(),
                return_url,
            },
            legal_consents: vec![LegalConsent {
                consent_type: LegalConsentType::ShareDataConsent,
                granted: true,
            }],
        }
    }


impl api::PaymentSync for Archipel {}


pub struct GetTrackerResponse<'a, F: Clone, R, D> {
    pub operation: BoxedOperation<'a, F, R, D>,
    pub customer_details: Option<CustomerDetails>,
    pub payment_data: D,
    pub business_profile: domain::Profile,
    pub mandate_type: Option<api::MandateTransactionType>,
}


File: crates/storage_impl/src/payments/payment_intent.rs

#[cfg(feature = "olap")]
use api_models::payments::{AmountFilter, Order, SortBy, SortOn};
#[cfg(feature = "olap")]
use async_bb8_diesel::{AsyncConnection, AsyncRunQueryDsl};
#[cfg(feature = "v2")]
use common_utils::fallback_reverse_lookup_not_found;
use common_utils::{
    ext_traits::{AsyncExt, Encode},
    types::keymanager::KeyManagerState,
};
#[cfg(feature = "olap")]
use diesel::{associations::HasTable, ExpressionMethods, JoinOnDsl, QueryDsl};
#[cfg(feature = "v1")]
use diesel_models::payment_intent::PaymentIntentUpdate as DieselPaymentIntentUpdate;
#[cfg(feature = "v2")]
use diesel_models::payment_intent::PaymentIntentUpdateInternal;
#[cfg(feature = "olap")]
use diesel_models::query::generics::db_metrics;
#[cfg(feature = "v2")]
use diesel_models::reverse_lookup::ReverseLookupNew;
#[cfg(all(feature = "v1", feature = "olap"))]
use diesel_models::schema::{
    payment_attempt::{self as payment_attempt_schema, dsl as pa_dsl},
    payment_intent::dsl as pi_dsl,
};
#[cfg(all(feature = "v2", feature = "olap"))]
use diesel_models::schema_v2::{
    payment_attempt::{self as payment_attempt_schema, dsl as pa_dsl},
    payment_intent::dsl as pi_dsl,
};
use diesel_models::{
    enums::MerchantStorageScheme, kv, payment_intent::PaymentIntent as DieselPaymentIntent,
};
use error_stack::ResultExt;
#[cfg(feature = "olap")]
use hyperswitch_domain_models::payments::{
    payment_attempt::PaymentAttempt, payment_intent::PaymentIntentFetchConstraints,
};
use hyperswitch_domain_models::{
    behaviour::Conversion,
    merchant_key_store::MerchantKeyStore,
    payments::{
        payment_intent::{PaymentIntentInterface, PaymentIntentUpdate},
        PaymentIntent,
    },
};
use redis_interface::HsetnxReply;
#[cfg(feature = "olap")]
use router_env::logger;
use router_env::{instrument, tracing};

#[cfg(feature = "olap")]
use crate::connection;
use crate::{
    diesel_error_to_data_error,
    errors::{RedisErrorExt, StorageError},
    kv_router_store::KVRouterStore,
    redis::kv_store::{decide_storage_scheme, kv_wrapper, KvOperation, Op, PartitionKey},
    utils::{self, pg_connection_read, pg_connection_write},
    DatabaseStore,
};
#[cfg(feature = "v2")]
use crate::{errors, lookup::ReverseLookupInterface};

#[async_trait::async_trait]
impl<T: DatabaseStore> PaymentIntentInterface for KVRouterStore<T> {
    type Error = StorageError;
    #[cfg(feature = "v1")]
    async fn insert_payment_intent(
        &self,
        state: &KeyManagerState,
        payment_intent: PaymentIntent,
        merchant_key_store: &MerchantKeyStore,
        storage_scheme: MerchantStorageScheme,
    ) -> error_stack::Result<PaymentIntent, StorageError> {
        let merchant_id = payment_intent.merchant_id.clone();
        let payment_id = payment_intent.get_id().to_owned();
        let field = payment_intent.get_id().get_hash_key_for_kv_store();
        let key = PartitionKey::MerchantIdPaymentId {
            merchant_id: &merchant_id,
            payment_id: &payment_id,
        };
        let storage_scheme = Box::pin(decide_storage_scheme::<_, DieselPaymentIntent>(
            self,
            storage_scheme,
            Op::Insert,
        ))
        .await;
        match storage_scheme {
            MerchantStorageScheme::PostgresOnly => {
                self.router_store
                    .insert_payment_intent(
                        state,
                        payment_intent,
                        merchant_key_store,
                        storage_scheme,
                    )
                    .await
            }

            MerchantStorageScheme::RedisKv => {
                let key_str = key.to_string();
                let new_payment_intent = payment_intent
                    .clone()
                    .construct_new()
                    .await
                    .change_context(StorageError::EncryptionError)?;

                let redis_entry = kv::TypedSql {
                    op: kv::DBOperation::Insert {
                        insertable: Box::new(kv::Insertable::PaymentIntent(Box::new(
                            new_payment_intent,
                        ))),
                    },
                };

                let diesel_payment_intent = payment_intent
                    .clone()
                    .convert()
                    .await
                    .change_context(StorageError::EncryptionError)?;

                match Box::pin(kv_wrapper::<DieselPaymentIntent, _, _>(
                    self,
                    KvOperation::<DieselPaymentIntent>::HSetNx(
                        &field,
                        &diesel_payment_intent,
                        redis_entry,
                    ),
                    key,
                ))
                .await
                .map_err(|err| err.to_redis_failed_response(&key_str))?
                .try_into_hsetnx()
                {
                    Ok(HsetnxReply::KeyNotSet) => Err(StorageError::DuplicateValue {
                        entity: "payment_intent",
                        key: Some(key_str),
                    }
                    .into()),
                    Ok(HsetnxReply::KeySet) => Ok(payment_intent),
                    Err(error) => Err(error.change_context(StorageError::KVError)),
                }
            }
        }
    }

    #[cfg(feature = "v2")]
    async fn insert_payment_intent(
        &self,
        state: &KeyManagerState,
        payment_intent: PaymentIntent,
        merchant_key_store: &MerchantKeyStore,
        storage_scheme: MerchantStorageScheme,
    ) -> error_stack::Result<PaymentIntent, StorageError> {
        match storage_scheme {
            MerchantStorageScheme::PostgresOnly => {
                self.router_store
                    .insert_payment_intent(
                        state,
                        payment_intent,
                        merchant_key_store,
                        storage_scheme,
                    )
                    .await
            }

            MerchantStorageScheme::RedisKv => {
                let id = payment_intent.id.clone();
                let key = PartitionKey::GlobalPaymentId { id: &id };
                let field = format!("pi_{}", id.get_string_repr());
                let key_str = key.to_string();

                let new_payment_intent = payment_intent
                    .clone()
                    .construct_new()
                    .await
                    .change_context(StorageError::EncryptionError)?;

                let redis_entry = kv::TypedSql {
                    op: kv::DBOperation::Insert {
                        insertable: Box::new(kv::Insertable::PaymentIntent(Box::new(
                            new_payment_intent,
                        ))),
                    },
                };

                let diesel_payment_intent = payment_intent
                    .clone()
                    .convert()
                    .await
                    .change_context(StorageError::EncryptionError)?;

                if let Some(merchant_reference_id) = &payment_intent.merchant_reference_id {
                    let reverse_lookup = ReverseLookupNew {
                        lookup_id: format!(
                            "pi_merchant_reference_{}_{}",
                            payment_intent.profile_id.get_string_repr(),
                            merchant_reference_id.get_string_repr()
                        ),
                        pk_id: key_str.clone(),
                        sk_id: field.clone(),
                        source: "payment_intent".to_string(),
                        updated_by: storage_scheme.to_string(),
                    };
                    self.insert_reverse_lookup(reverse_lookup, storage_scheme)
                        .await?;
                }

                match Box::pin(kv_wrapper::<DieselPaymentIntent, _, _>(
                    self,
                    KvOperation::<DieselPaymentIntent>::HSetNx(
                        &field,
                        &diesel_payment_intent,
                        redis_entry,
                    ),
                    key,
                ))
                .await
                .map_err(|err| err.to_redis_failed_response(&key_str))?
                .try_into_hsetnx()
                {
                    Ok(HsetnxReply::KeyNotSet) => Err(StorageError::DuplicateValue {
                        entity: "payment_intent",
                        key: Some(key_str),
                    }
                    .into()),
                    Ok(HsetnxReply::KeySet) => Ok(payment_intent),
                    Err(error) => Err(error.change_context(StorageError::KVError)),
                }
            }
        }
    }

    #[cfg(all(feature = "v2", feature = "olap"))]
    #[instrument(skip_all)]
    async fn get_filtered_payment_intents_attempt(
        &self,
        state: &KeyManagerState,
        merchant_id: &common_utils::id_type::MerchantId,
        constraints: &PaymentIntentFetchConstraints,
        merchant_key_store: &MerchantKeyStore,
        storage_scheme: MerchantStorageScheme,
    ) -> error_stack::Result<Vec<(PaymentIntent, Option<PaymentAttempt>)>, StorageError> {
        self.router_store
            .get_filtered_payment_intents_attempt(
                state,
                merchant_id,
                constraints,
                merchant_key_store,
                storage_scheme,
            )
            .await
    }

    #[cfg(feature = "v1")]
    #[instrument(skip_all)]
    async fn update_payment_intent(
        &self,
        state: &KeyManagerState,
        this: PaymentIntent,
        payment_intent_update: PaymentIntentUpdate,
        merchant_key_store: &MerchantKeyStore,
        storage_scheme: MerchantStorageScheme,
    ) -> error_stack::Result<PaymentIntent, StorageError> {
        let merchant_id = this.merchant_id.clone();
        let payment_id = this.get_id().to_owned();
        let key = PartitionKey::MerchantIdPaymentId {
            merchant_id: &merchant_id,
            payment_id: &payment_id,
        };
        let field = format!("pi_{}", this.get_id().get_string_repr());
        let storage_scheme = Box::pin(decide_storage_scheme::<_, DieselPaymentIntent>(
            self,
            storage_scheme,
            Op::Update(key.clone(), &field, Some(&this.updated_by)),
        ))
        .await;
        match storage_scheme {
            MerchantStorageScheme::PostgresOnly => {
                self.router_store
                    .update_payment_intent(
                        state,
                        this,
                        payment_intent_update,
                        merchant_key_store,
                        storage_scheme,
                    )
                    .await
            }
            MerchantStorageScheme::RedisKv => {
                let key_str = key.to_string();

                let diesel_intent_update = DieselPaymentIntentUpdate::from(payment_intent_update);
                let origin_diesel_intent = this
                    .convert()
                    .await
                    .change_context(StorageError::EncryptionError)?;

                let diesel_intent = diesel_intent_update
                    .clone()
                    .apply_changeset(origin_diesel_intent.clone());
                // Check for database presence as well Maybe use a read replica here ?

                let redis_value = diesel_intent
                    .encode_to_string_of_json()
                    .change_context(StorageError::SerializationFailed)?;

                let redis_entry = kv::TypedSql {
                    op: kv::DBOperation::Update {
                        updatable: Box::new(kv::Updateable::PaymentIntentUpdate(Box::new(
                            kv::PaymentIntentUpdateMems {
                                orig: origin_diesel_intent,
                                update_data: diesel_intent_update,
                            },
                        ))),
                    },
                };

                Box::pin(kv_wrapper::<(), _, _>(
                    self,
                    KvOperation::<DieselPaymentIntent>::Hset((&field, redis_value), redis_entry),
                    key,
                ))
                .await
                .map_err(|err| err.to_redis_failed_response(&key_str))?
                .try_into_hset()
                .change_context(StorageError::KVError)?;

                let payment_intent = PaymentIntent::convert_back(
                    state,
                    diesel_intent,
                    merchant_key_store.key.get_inner(),
                    merchant_id.into(),
                )
                .await
                .change_context(StorageError::DecryptionError)?;

                Ok(payment_intent)
            }
        }
    }

    #[cfg(feature = "v2")]
    #[instrument(skip_all)]
    async fn update_payment_intent(
        &self,
        state: &KeyManagerState,
        this: PaymentIntent,
        payment_intent_update: PaymentIntentUpdate,
        merchant_key_store: &MerchantKeyStore,
        storage_scheme: MerchantStorageScheme,
    ) -> error_stack::Result<PaymentIntent, StorageError> {
        match storage_scheme {
            MerchantStorageScheme::PostgresOnly => {
                self.router_store
                    .update_payment_intent(
                        state,
                        this,
                        payment_intent_update,
                        merchant_key_store,
                        storage_scheme,
                    )
                    .await
            }
            MerchantStorageScheme::RedisKv => {
                let id = this.id.clone();
                let merchant_id = this.merchant_id.clone();
                let key = PartitionKey::GlobalPaymentId { id: &id };
                let field = format!("pi_{}", id.get_string_repr());
                let key_str = key.to_string();

                let diesel_intent_update =
                    PaymentIntentUpdateInternal::try_from(payment_intent_update)
                        .change_context(StorageError::DeserializationFailed)?;
                let origin_diesel_intent = this
                    .convert()
                    .await
                    .change_context(StorageError::EncryptionError)?;

                let diesel_intent = diesel_intent_update
                    .clone()
                    .apply_changeset(origin_diesel_intent.clone());

                let redis_value = diesel_intent
                    .encode_to_string_of_json()
                    .change_context(StorageError::SerializationFailed)?;

                let redis_entry = kv::TypedSql {
                    op: kv::DBOperation::Update {
                        updatable: Box::new(kv::Updateable::PaymentIntentUpdate(Box::new(
                            kv::PaymentIntentUpdateMems {
                                orig: origin_diesel_intent,
                                update_data: diesel_intent_update,
                            },
                        ))),
                    },
                };

                Box::pin(kv_wrapper::<(), _, _>(
                    self,
                    KvOperation::<DieselPaymentIntent>::Hset((&field, redis_value), redis_entry),
                    key,
                ))
                .await
                .map_err(|err| err.to_redis_failed_response(&key_str))?
                .try_into_hset()
                .change_context(StorageError::KVError)?;

                let payment_intent = PaymentIntent::convert_back(
                    state,
                    diesel_intent,
                    merchant_key_store.key.get_inner(),
                    merchant_id.into(),
                )
                .await
                .change_context(StorageError::DecryptionError)?;

                Ok(payment_intent)
            }
        }
    }

    #[cfg(feature = "v1")]
    #[instrument(skip_all)]
    async fn find_payment_intent_by_payment_id_merchant_id(
        &self,
        state: &KeyManagerState,
        payment_id: &common_utils::id_type::PaymentId,
        merchant_id: &common_utils::id_type::MerchantId,
        merchant_key_store: &MerchantKeyStore,
        storage_scheme: MerchantStorageScheme,
    ) -> error_stack::Result<PaymentIntent, StorageError> {
        let database_call = || async {
            let conn = pg_connection_read(self).await?;
            DieselPaymentIntent::find_by_payment_id_merchant_id(&conn, payment_id, merchant_id)
                .await
                .map_err(|er| {
                    let new_err = diesel_error_to_data_error(*er.current_context());
                    er.change_context(new_err)
                })
        };
        let storage_scheme = Box::pin(decide_storage_scheme::<_, DieselPaymentIntent>(
            self,
            storage_scheme,
            Op::Find,
        ))
        .await;
        let diesel_payment_intent = match storage_scheme {
            MerchantStorageScheme::PostgresOnly => database_call().await,

            MerchantStorageScheme::RedisKv => {
                let key = PartitionKey::MerchantIdPaymentId {
                    merchant_id,
                    payment_id,
                };
                let field = payment_id.get_hash_key_for_kv_store();
                Box::pin(utils::try_redis_get_else_try_database_get(
                    async {
                        Box::pin(kv_wrapper::<DieselPaymentIntent, _, _>(
                            self,
                            KvOperation::<DieselPaymentIntent>::HGet(&field),
                            key,
                        ))
                        .await?
                        .try_into_hget()
                    },
                    database_call,
                ))
                .await
            }
        }?;

        PaymentIntent::convert_back(
            state,
            diesel_payment_intent,
            merchant_key_store.key.get_inner(),
            merchant_id.to_owned().into(),
        )
        .await
        .change_context(StorageError::DecryptionError)
    }

    #[cfg(feature = "v2")]
    #[instrument(skip_all)]
    async fn find_payment_intent_by_id(
        &self,
        state: &KeyManagerState,
        id: &common_utils::id_type::GlobalPaymentId,
        merchant_key_store: &MerchantKeyStore,
        storage_scheme: MerchantStorageScheme,
    ) -> error_stack::Result<PaymentIntent, StorageError> {
        let storage_scheme = Box::pin(decide_storage_scheme::<_, DieselPaymentIntent>(
            self,
            storage_scheme,
            Op::Find,
        ))
        .await;

        let database_call = || async {
            let conn: bb8::PooledConnection<
                '_,
                async_bb8_diesel::ConnectionManager<diesel::PgConnection>,
            > = pg_connection_read(self).await?;

            DieselPaymentIntent::find_by_global_id(&conn, id)
                .await
                .map_err(|er| {
                    let new_err = diesel_error_to_data_error(*er.current_context());
                    er.change_context(new_err)
                })
        };

        let diesel_payment_intent = match storage_scheme {
            MerchantStorageScheme::PostgresOnly => database_call().await,
            MerchantStorageScheme::RedisKv => {
                let key = PartitionKey::GlobalPaymentId { id };
                let field = format!("pi_{}", id.get_string_repr());

                Box::pin(utils::try_redis_get_else_try_database_get(
                    async {
                        Box::pin(kv_wrapper::<DieselPaymentIntent, _, _>(
                            self,
                            KvOperation::<DieselPaymentIntent>::HGet(&field),
                            key,
                        ))
                        .await?
                        .try_into_hget()
                    },
                    database_call,
                ))
                .await
            }
        }?;

        let merchant_id = diesel_payment_intent.merchant_id.clone();

        PaymentIntent::convert_back(
            state,
            diesel_payment_intent,
            merchant_key_store.key.get_inner(),
            merchant_id.into(),
        )
        .await
        .change_context(StorageError::DecryptionError)
    }

    #[cfg(all(feature = "v1", feature = "olap"))]
    async fn filter_payment_intent_by_constraints(
        &self,
        state: &KeyManagerState,
        merchant_id: &common_utils::id_type::MerchantId,
        filters: &PaymentIntentFetchConstraints,
        merchant_key_store: &MerchantKeyStore,
        storage_scheme: MerchantStorageScheme,
    ) -> error_stack::Result<Vec<PaymentIntent>, StorageError> {
        self.router_store
            .filter_payment_intent_by_constraints(
                state,
                merchant_id,
                filters,
                merchant_key_store,
                storage_scheme,
            )
            .await
    }

    #[cfg(all(feature = "v1", feature = "olap"))]
    async fn filter_payment_intents_by_time_range_constraints(
        &self,
        state: &KeyManagerState,
        merchant_id: &common_utils::id_type::MerchantId,
        time_range: &common_utils::types::TimeRange,
        merchant_key_store: &MerchantKeyStore,
        storage_scheme: MerchantStorageScheme,
    ) -> error_stack::Result<Vec<PaymentIntent>, StorageError> {
        self.router_store
            .filter_payment_intents_by_time_range_constraints(
                state,
                merchant_id,
                time_range,
                merchant_key_store,
                storage_scheme,
            )
            .await
    }

    #[cfg(feature = "olap")]
    async fn get_intent_status_with_count(
        &self,
        merchant_id: &common_utils::id_type::MerchantId,
        profile_id_list: Option<Vec<common_utils::id_type::ProfileId>>,
        time_range: &common_utils::types::TimeRange,
    ) -> error_stack::Result<Vec<(common_enums::IntentStatus, i64)>, StorageError> {
        self.router_store
            .get_intent_status_with_count(merchant_id, profile_id_list, time_range)
            .await
    }

    #[cfg(all(feature = "v1", feature = "olap"))]
    async fn get_filtered_payment_intents_attempt(
        &self,
        state: &KeyManagerState,
        merchant_id: &common_utils::id_type::MerchantId,
        filters: &PaymentIntentFetchConstraints,
        merchant_key_store: &MerchantKeyStore,
        storage_scheme: MerchantStorageScheme,
    ) -> error_stack::Result<Vec<(PaymentIntent, PaymentAttempt)>, StorageError> {
        self.router_store
            .get_filtered_payment_intents_attempt(
                state,
                merchant_id,
                filters,
                merchant_key_store,
                storage_scheme,
            )
            .await
    }

    #[cfg(all(feature = "v1", feature = "olap"))]
    async fn get_filtered_active_attempt_ids_for_total_count(
        &self,
        merchant_id: &common_utils::id_type::MerchantId,
        constraints: &PaymentIntentFetchConstraints,
        storage_scheme: MerchantStorageScheme,
    ) -> error_stack::Result<Vec<String>, StorageError> {
        self.router_store
            .get_filtered_active_attempt_ids_for_total_count(
                merchant_id,
                constraints,
                storage_scheme,
            )
            .await
    }

    #[cfg(all(feature = "v2", feature = "olap"))]
    async fn get_filtered_active_attempt_ids_for_total_count(
        &self,
        merchant_id: &common_utils::id_type::MerchantId,
        constraints: &PaymentIntentFetchConstraints,
        storage_scheme: MerchantStorageScheme,
    ) -> error_stack::Result<Vec<Option<String>>, StorageError> {
        self.router_store
            .get_filtered_active_attempt_ids_for_total_count(
                merchant_id,
                constraints,
                storage_scheme,
            )
            .await
    }

    #[cfg(feature = "v2")]
    async fn find_payment_intent_by_merchant_reference_id_profile_id(
        &self,
        state: &KeyManagerState,
        merchant_reference_id: &common_utils::id_type::PaymentReferenceId,
        profile_id: &common_utils::id_type::ProfileId,
        merchant_key_store: &MerchantKeyStore,
        storage_scheme: &MerchantStorageScheme,
    ) -> error_stack::Result<PaymentIntent, StorageError> {
        match storage_scheme {
            MerchantStorageScheme::PostgresOnly => {
                self.router_store
                    .find_payment_intent_by_merchant_reference_id_profile_id(
                        state,
                        merchant_reference_id,
                        profile_id,
                        merchant_key_store,
                        storage_scheme,
                    )
                    .await
            }
            MerchantStorageScheme::RedisKv => {
                let lookup_id = format!(
                    "pi_merchant_reference_{}_{}",
                    profile_id.get_string_repr(),
                    merchant_reference_id.get_string_repr()
                );

                let lookup = fallback_reverse_lookup_not_found!(
                    self.get_lookup_by_lookup_id(&lookup_id, *storage_scheme)
                        .await,
                    self.router_store
                        .find_payment_intent_by_merchant_reference_id_profile_id(
                            state,
                            merchant_reference_id,
                            profile_id,
                            merchant_key_store,
                            storage_scheme,
                        )
                        .await
                );

                let key = PartitionKey::CombinationKey {
                    combination: &lookup.pk_id,
                };

                let database_call = || async {
                    let conn = pg_connection_read(self).await?;
                    DieselPaymentIntent::find_by_merchant_reference_id_profile_id(
                        &conn,
                        merchant_reference_id,
                        profile_id,
                    )
                    .await
                    .map_err(|er| {
                        let new_err = diesel_error_to_data_error(*er.current_context());
                        er.change_context(new_err)
                    })
                };

                let diesel_payment_intent = Box::pin(utils::try_redis_get_else_try_database_get(
                    async {
                        Box::pin(kv_wrapper::<DieselPaymentIntent, _, _>(
                            self,
                            KvOperation::<DieselPaymentIntent>::HGet(&lookup.sk_id),
                            key,
                        ))
                        .await?
                        .try_into_hget()
                    },
                    database_call,
                ))
                .await?;

                let merchant_id = diesel_payment_intent.merchant_id.clone();

                PaymentIntent::convert_back(
                    state,
                    diesel_payment_intent,
                    merchant_key_store.key.get_inner(),
                    merchant_id.into(),
                )
                .await
                .change_context(StorageError::DecryptionError)
            }
        }
    }
}

#[async_trait::async_trait]
impl<T: DatabaseStore> PaymentIntentInterface for crate::RouterStore<T> {
    type Error = StorageError;
    #[instrument(skip_all)]
    async fn insert_payment_intent(
        &self,
        state: &KeyManagerState,
        payment_intent: PaymentIntent,
        merchant_key_store: &MerchantKeyStore,
        _storage_scheme: MerchantStorageScheme,
    ) -> error_stack::Result<PaymentIntent, StorageError> {
        let conn = pg_connection_write(self).await?;
        let diesel_payment_intent = payment_intent
            .construct_new()
            .await
            .change_context(StorageError::EncryptionError)?
            .insert(&conn)
            .await
            .map_err(|er| {
                let new_err = diesel_error_to_data_error(*er.current_context());
                er.change_context(new_err)
            })?;

        PaymentIntent::convert_back(
            state,
            diesel_payment_intent,
            merchant_key_store.key.get_inner(),
            merchant_key_store.merchant_id.clone().into(),
        )
        .await
        .change_context(StorageError::DecryptionError)
    }

    #[cfg(feature = "v1")]
    #[instrument(skip_all)]
    async fn update_payment_intent(
        &self,
        state: &KeyManagerState,
        this: PaymentIntent,
        payment_intent: PaymentIntentUpdate,
        merchant_key_store: &MerchantKeyStore,
        _storage_scheme: MerchantStorageScheme,
    ) -> error_stack::Result<PaymentIntent, StorageError> {
        let conn = pg_connection_write(self).await?;
        let diesel_payment_intent_update = DieselPaymentIntentUpdate::from(payment_intent);

        let diesel_payment_intent = this
            .convert()
            .await
            .change_context(StorageError::EncryptionError)?
            .update(&conn, diesel_payment_intent_update)
            .await
            .map_err(|er| {
                let new_err = diesel_error_to_data_error(*er.current_context());
                er.change_context(new_err)
            })?;

        PaymentIntent::convert_back(
            state,
            diesel_payment_intent,
            merchant_key_store.key.get_inner(),
            merchant_key_store.merchant_id.clone().into(),
        )
        .await
        .change_context(StorageError::DecryptionError)
    }

    #[cfg(feature = "v2")]
    #[instrument(skip_all)]
    async fn update_payment_intent(
        &self,
        state: &KeyManagerState,
        this: PaymentIntent,
        payment_intent: PaymentIntentUpdate,
        merchant_key_store: &MerchantKeyStore,
        _storage_scheme: MerchantStorageScheme,
    ) -> error_stack::Result<PaymentIntent, StorageError> {
        let conn = pg_connection_write(self).await?;
        let diesel_payment_intent_update = PaymentIntentUpdateInternal::try_from(payment_intent)
            .change_context(StorageError::DeserializationFailed)?;
        let diesel_payment_intent = this
            .convert()
            .await
            .change_context(StorageError::EncryptionError)?
            .update(&conn, diesel_payment_intent_update)
            .await
            .map_err(|er| {
                let new_err = diesel_error_to_data_error(*er.current_context());
                er.change_context(new_err)
            })?;

        PaymentIntent::convert_back(
            state,
            diesel_payment_intent,
            merchant_key_store.key.get_inner(),
            merchant_key_store.merchant_id.clone().into(),
        )
        .await
        .change_context(StorageError::DecryptionError)
    }

    #[cfg(feature = "v1")]
    #[instrument(skip_all)]
    async fn find_payment_intent_by_payment_id_merchant_id(
        &self,
        state: &KeyManagerState,
        payment_id: &common_utils::id_type::PaymentId,
        merchant_id: &common_utils::id_type::MerchantId,
        merchant_key_store: &MerchantKeyStore,
        _storage_scheme: MerchantStorageScheme,
    ) -> error_stack::Result<PaymentIntent, StorageError> {
        let conn = pg_connection_read(self).await?;

        DieselPaymentIntent::find_by_payment_id_merchant_id(&conn, payment_id, merchant_id)
            .await
            .map_err(|er| {
                let new_err = diesel_error_to_data_error(*er.current_context());
                er.change_context(new_err)
            })
            .async_and_then(|diesel_payment_intent| async {
                PaymentIntent::convert_back(
                    state,
                    diesel_payment_intent,
                    merchant_key_store.key.get_inner(),
                    merchant_key_store.merchant_id.clone().into(),
                )
                .await
                .change_context(StorageError::DecryptionError)
            })
            .await
    }

    #[cfg(feature = "v2")]
    #[instrument(skip_all)]
    async fn find_payment_intent_by_id(
        &self,
        state: &KeyManagerState,
        id: &common_utils::id_type::GlobalPaymentId,
        merchant_key_store: &MerchantKeyStore,
        _storage_scheme: MerchantStorageScheme,
    ) -> error_stack::Result<PaymentIntent, StorageError> {
        let conn = pg_connection_read(self).await?;
        let diesel_payment_intent = DieselPaymentIntent::find_by_global_id(&conn, id)
            .await
            .map_err(|er| {
                let new_err = diesel_error_to_data_error(*er.current_context());
                er.change_context(new_err)
            })?;

        let merchant_id = diesel_payment_intent.merchant_id.clone();

        PaymentIntent::convert_back(
            state,
            diesel_payment_intent,
            merchant_key_store.key.get_inner(),
            merchant_id.to_owned().into(),
        )
        .await
        .change_context(StorageError::DecryptionError)
    }

    #[cfg(feature = "v2")]
    #[instrument(skip_all)]
    async fn find_payment_intent_by_merchant_reference_id_profile_id(
        &self,
        state: &KeyManagerState,
        merchant_reference_id: &common_utils::id_type::PaymentReferenceId,
        profile_id: &common_utils::id_type::ProfileId,
        merchant_key_store: &MerchantKeyStore,
        _storage_scheme: &MerchantStorageScheme,
    ) -> error_stack::Result<PaymentIntent, StorageError> {
        let conn = pg_connection_read(self).await?;
        let diesel_payment_intent = DieselPaymentIntent::find_by_merchant_reference_id_profile_id(
            &conn,
            merchant_reference_id,
            profile_id,
        )
        .await
        .map_err(|er| {
            let new_err = diesel_error_to_data_error(*er.current_context());
            er.change_context(new_err)
        })?;
        let merchant_id = diesel_payment_intent.merchant_id.clone();

        PaymentIntent::convert_back(
            state,
            diesel_payment_intent,
            merchant_key_store.key.get_inner(),
            merchant_id.to_owned().into(),
        )
        .await
        .change_context(StorageError::DecryptionError)
    }

    #[cfg(all(feature = "v1", feature = "olap"))]
    #[instrument(skip_all)]
    async fn filter_payment_intent_by_constraints(
        &self,
        state: &KeyManagerState,
        merchant_id: &common_utils::id_type::MerchantId,
        filters: &PaymentIntentFetchConstraints,
        merchant_key_store: &MerchantKeyStore,
        storage_scheme: MerchantStorageScheme,
    ) -> error_stack::Result<Vec<PaymentIntent>, StorageError> {
        use futures::{future::try_join_all, FutureExt};

        let conn = connection::pg_connection_read(self).await?;
        let conn = async_bb8_diesel::Connection::as_async_conn(&conn);

        //[#350]: Replace this with Boxable Expression and pass it into generic filter
        // when https://github.com/rust-lang/rust/issues/52662 becomes stable
        let mut query = <DieselPaymentIntent as HasTable>::table()
            .filter(pi_dsl::merchant_id.eq(merchant_id.to_owned()))
            .order(pi_dsl::created_at.desc())
            .into_boxed();

        match filters {
            PaymentIntentFetchConstraints::Single { payment_intent_id } => {
                query = query.filter(pi_dsl::payment_id.eq(payment_intent_id.to_owned()));
            }
            PaymentIntentFetchConstraints::List(params) => {
                if let Some(limit) = params.limit {
                    query = query.limit(limit.into());
                }

                if let Some(customer_id) = &params.customer_id {
                    query = query.filter(pi_dsl::customer_id.eq(customer_id.clone()));
                }
                if let Some(profile_id) = &params.profile_id {
                    query = query.filter(pi_dsl::profile_id.eq_any(profile_id.clone()));
                }

                query = match (params.starting_at, &params.starting_after_id) {
                    (Some(starting_at), _) => query.filter(pi_dsl::created_at.ge(starting_at)),
                    (None, Some(starting_after_id)) => {
                        // TODO: Fetch partial columns for this query since we only need some columns
                        let starting_at = self
                            .find_payment_intent_by_payment_id_merchant_id(
                                state,
                                starting_after_id,
                                merchant_id,
                                merchant_key_store,
                                storage_scheme,
                            )
                            .await?
                            .created_at;
                        query.filter(pi_dsl::created_at.ge(starting_at))
                    }
                    (None, None) => query,
                };

                query = match (params.ending_at, &params.ending_before_id) {
                    (Some(ending_at), _) => query.filter(pi_dsl::created_at.le(ending_at)),
                    (None, Some(ending_before_id)) => {
                        // TODO: Fetch partial columns for this query since we only need some columns
                        let ending_at = self
                            .find_payment_intent_by_payment_id_merchant_id(
                                state,
                                ending_before_id,
                                merchant_id,
                                merchant_key_store,
                                storage_scheme,
                            )
                            .await?
                            .created_at;
                        query.filter(pi_dsl::created_at.le(ending_at))
                    }
                    (None, None) => query,
                };

                query = query.offset(params.offset.into());

                query = match &params.currency {
                    Some(currency) => query.filter(pi_dsl::currency.eq_any(currency.clone())),
                    None => query,
                };

                query = match &params.status {
                    Some(status) => query.filter(pi_dsl::status.eq_any(status.clone())),
                    None => query,
                };

                if let Some(currency) = &params.currency {
                    query = query.filter(pi_dsl::currency.eq_any(currency.clone()));
                }

                if let Some(status) = &params.status {
                    query = query.filter(pi_dsl::status.eq_any(status.clone()));
                }
            }
        }

        logger::debug!(query = %diesel::debug_query::<diesel::pg::Pg,_>(&query).to_string());

        db_metrics::track_database_call::<<DieselPaymentIntent as HasTable>::Table, _, _>(
            query.get_results_async::<DieselPaymentIntent>(conn),
            db_metrics::DatabaseOperation::Filter,
        )
        .await
        .map(|payment_intents| {
            try_join_all(payment_intents.into_iter().map(|diesel_payment_intent| {
                PaymentIntent::convert_back(
                    state,
                    diesel_payment_intent,
                    merchant_key_store.key.get_inner(),
                    merchant_key_store.merchant_id.clone().into(),
                )
            }))
            .map(|join_result| join_result.change_context(StorageError::DecryptionError))
        })
        .map_err(|er| {
            StorageError::DatabaseError(
                error_stack::report!(diesel_models::errors::DatabaseError::from(er))
                    .attach_printable("Error filtering payment records"),
            )
        })?
        .await
    }

    #[cfg(all(feature = "v1", feature = "olap"))]
    #[instrument(skip_all)]
    async fn filter_payment_intents_by_time_range_constraints(
        &self,
        state: &KeyManagerState,
        merchant_id: &common_utils::id_type::MerchantId,
        time_range: &common_utils::types::TimeRange,
        merchant_key_store: &MerchantKeyStore,
        storage_scheme: MerchantStorageScheme,
    ) -> error_stack::Result<Vec<PaymentIntent>, StorageError> {
        // TODO: Remove this redundant function
        let payment_filters = (*time_range).into();
        self.filter_payment_intent_by_constraints(
            state,
            merchant_id,
            &payment_filters,
            merchant_key_store,
            storage_scheme,
        )
        .await
    }

    #[cfg(feature = "olap")]
    #[instrument(skip_all)]
    async fn get_intent_status_with_count(
        &self,
        merchant_id: &common_utils::id_type::MerchantId,
        profile_id_list: Option<Vec<common_utils::id_type::ProfileId>>,
        time_range: &common_utils::types::TimeRange,
    ) -> error_stack::Result<Vec<(common_enums::IntentStatus, i64)>, StorageError> {
        let conn = connection::pg_connection_read(self).await?;
        let conn = async_bb8_diesel::Connection::as_async_conn(&conn);

        let mut query = <DieselPaymentIntent as HasTable>::table()
            .group_by(pi_dsl::status)
            .select((pi_dsl::status, diesel::dsl::count_star()))
            .filter(pi_dsl::merchant_id.eq(merchant_id.to_owned()))
            .into_boxed();

        if let Some(profile_id) = profile_id_list {
            query = query.filter(pi_dsl::profile_id.eq_any(profile_id));
        }

        query = query.filter(pi_dsl::created_at.ge(time_range.start_time));

        query = match time_range.end_time {
            Some(ending_at) => query.filter(pi_dsl::created_at.le(ending_at)),
            None => query,
        };

        logger::debug!(filter = %diesel::debug_query::<diesel::pg::Pg,_>(&query).to_string());

        db_metrics::track_database_call::<<DieselPaymentIntent as HasTable>::Table, _, _>(
            query.get_results_async::<(common_enums::IntentStatus, i64)>(conn),
            db_metrics::DatabaseOperation::Filter,
        )
        .await
        .map_err(|er| {
            StorageError::DatabaseError(
                error_stack::report!(diesel_models::errors::DatabaseError::from(er))


pub struct ToggleBlocklistResponse {
    pub blocklist_guard_status: String,
}


pub struct RouterDataV2<Flow, ResourceCommonData, FlowSpecificRequest, FlowSpecificResponse> {
    pub flow: PhantomData<Flow>,
    pub tenant_id: id_type::TenantId,
    pub resource_common_data: ResourceCommonData,
    pub connector_auth_type: ConnectorAuthType,
    /// Contains flow-specific data required to construct a request and send it to the connector.
    pub request: FlowSpecificRequest,
    /// Contains flow-specific data that the connector responds with.
    pub response: Result<FlowSpecificResponse, ErrorResponse>,
}


pub struct BacsBankTransfer {
    /// Bank name
    #[schema(value_type = Option<String>, example = "Deutsche Bank")]
    pub bank_name: Option<String>,

    /// Bank country code
    #[schema(value_type = Option<CountryAlpha2>, example = "US")]
    pub bank_country_code: Option<api_enums::CountryAlpha2>,

    /// Bank city
    #[schema(value_type = Option<String>, example = "California")]
    pub bank_city: Option<String>,

    /// Bank account number is an unique identifier assigned by a bank to a customer.
    #[schema(value_type = String, example = "000123456")]
    pub bank_account_number: Secret<String>,

    /// [6 digits] Sort Code - used in UK and Ireland for identifying a bank and it's branches.
    #[schema(value_type = String, example = "98-76-54")]
    pub bank_sort_code: Secret<String>,
}


impl ConnectorCommon for Worldline {
    fn id(&self) -> &'static str {
        "worldline"
    }

    fn get_currency_unit(&self) -> api::CurrencyUnit {
        api::CurrencyUnit::Minor
    }

    fn base_url<'a>(&self, connectors: &'a Connectors) -> &'a str {
        connectors.worldline.base_url.as_ref()
    }

    fn build_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        let response: worldline::ErrorResponse = res
            .response
            .parse_struct("Worldline ErrorResponse")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;

        event_builder.map(|i| i.set_error_response_body(&response));
        logger::info!(connector_response=?response);

        let error = response.errors.into_iter().next().unwrap_or_default();
        Ok(ErrorResponse {
            status_code: res.status_code,
            code: error
                .code
                .unwrap_or_else(|| hyperswitch_interfaces::consts::NO_ERROR_CODE.to_string()),
            message: error
                .message
                .unwrap_or_else(|| hyperswitch_interfaces::consts::NO_ERROR_MESSAGE.to_string()),
            ..Default::default()
        })
    }
}


pub fn merge_metadata(
        &self,
        request_metadata: Value,
    ) -> Result<Value, common_utils::errors::ParsingError> {
        if !request_metadata.is_null() {
            match (&self.metadata, &request_metadata) {
                (Some(Value::Object(existing_map)), Value::Object(req_map)) => {
                    let mut merged = existing_map.clone();
                    merged.extend(req_map.clone());
                    Ok(Value::Object(merged))
                }
                (None, Value::Object(_)) => Ok(request_metadata),
                _ => {
                    router_env::logger::error!(
                        "Expected metadata to be an object, got: {:?}",
                        request_metadata
                    );
                    Err(common_utils::errors::ParsingError::UnknownError)
                }
            }
        } else {
            router_env::logger::error!("Metadata does not contain any key");
            Err(common_utils::errors::ParsingError::UnknownError)
        }
    }


pub(crate) fn get_payout_status(status: PaypalFulfillStatus) -> storage_enums::PayoutStatus {
    match status {
        PaypalFulfillStatus::Success => storage_enums::PayoutStatus::Success,
        PaypalFulfillStatus::Denied | PaypalFulfillStatus::Failed => {
            storage_enums::PayoutStatus::Failed
        }
        PaypalFulfillStatus::Cancelled => storage_enums::PayoutStatus::Cancelled,
        PaypalFulfillStatus::Pending | PaypalFulfillStatus::Processing => {
            storage_enums::PayoutStatus::Pending
        }
        PaypalFulfillStatus::Refunded | PaypalFulfillStatus::Returned => {
            storage_enums::PayoutStatus::Reversed
        }
    }
}


pub fn server(state: AppState) -> Scope {
        let mut route = web::scope("/v2/connector-accounts").app_data(web::Data::new(state));

        #[cfg(feature = "olap")]
        {
            use super::admin::*;

            route = route
                .service(web::resource("").route(web::post().to(connector_create)))
                .service(
                    web::resource("/{id}")
                        .route(web::put().to(connector_update))
                        .route(web::get().to(connector_retrieve))
                        .route(web::delete().to(connector_delete)),
                );
        }
        route
    }


impl api::PaymentSync for UnifiedAuthenticationService {}

impl api::PaymentSync for for UnifiedAuthenticationService


pub struct KatapultAuthType {
    pub(super) api_key: Secret<String>,
}


pub struct Profile {
    pub profile_id: common_utils::id_type::ProfileId,
    pub merchant_id: common_utils::id_type::MerchantId,
    pub profile_name: String,
    pub created_at: time::PrimitiveDateTime,
    pub modified_at: time::PrimitiveDateTime,
    pub return_url: Option<String>,
    pub enable_payment_response_hash: bool,
    pub payment_response_hash_key: Option<String>,
    pub redirect_to_merchant_with_http_post: bool,
    pub webhook_details: Option<WebhookDetails>,
    pub metadata: Option<pii::SecretSerdeValue>,
    pub routing_algorithm: Option<serde_json::Value>,
    pub intent_fulfillment_time: Option<i64>,
    pub frm_routing_algorithm: Option<serde_json::Value>,
    pub payout_routing_algorithm: Option<serde_json::Value>,
    pub is_recon_enabled: bool,
    #[diesel(deserialize_as = super::OptionalDieselArray<String>)]
    pub applepay_verified_domains: Option<Vec<String>>,
    pub payment_link_config: Option<BusinessPaymentLinkConfig>,
    pub session_expiry: Option<i64>,
    pub authentication_connector_details: Option<AuthenticationConnectorDetails>,
    pub payout_link_config: Option<BusinessPayoutLinkConfig>,
    pub is_extended_card_info_enabled: Option<bool>,
    pub extended_card_info_config: Option<pii::SecretSerdeValue>,
    pub is_connector_agnostic_mit_enabled: Option<bool>,
    pub use_billing_as_payment_method_billing: Option<bool>,
    pub collect_shipping_details_from_wallet_connector: Option<bool>,
    pub collect_billing_details_from_wallet_connector: Option<bool>,
    pub outgoing_webhook_custom_http_headers: Option<Encryption>,
    pub always_collect_billing_details_from_wallet_connector: Option<bool>,
    pub always_collect_shipping_details_from_wallet_connector: Option<bool>,
    pub tax_connector_id: Option<common_utils::id_type::MerchantConnectorAccountId>,
    pub is_tax_connector_enabled: Option<bool>,
    pub version: common_enums::ApiVersion,
    pub dynamic_routing_algorithm: Option<serde_json::Value>,
    pub is_network_tokenization_enabled: bool,
    pub is_auto_retries_enabled: Option<bool>,
    pub max_auto_retries_enabled: Option<i16>,
    pub always_request_extended_authorization:
        Option<primitive_wrappers::AlwaysRequestExtendedAuthorization>,
    pub is_click_to_pay_enabled: bool,
    pub authentication_product_ids:
        Option<common_types::payments::AuthenticationConnectorAccountMap>,
    pub card_testing_guard_config: Option<CardTestingGuardConfig>,
    pub card_testing_secret_key: Option<Encryption>,
    pub is_clear_pan_retries_enabled: bool,
    pub force_3ds_challenge: Option<bool>,
    pub is_debit_routing_enabled: bool,
    pub merchant_business_country: Option<common_enums::CountryAlpha2>,
    pub id: Option<common_utils::id_type::ProfileId>,
    pub is_iframe_redirection_enabled: Option<bool>,
    pub is_pre_network_tokenization_enabled: Option<bool>,
    pub three_ds_decision_rule_algorithm: Option<serde_json::Value>,
    pub acquirer_config_map: Option<common_types::domain::AcquirerConfigMap>,
    pub merchant_category_code: Option<common_enums::MerchantCategoryCode>,
    pub merchant_country_code: Option<common_types::payments::MerchantCountryCode>,
    pub dispute_polling_interval: Option<primitive_wrappers::DisputePollingIntervalInHours>,
    pub is_manual_retry_enabled: Option<bool>,
}


pub struct BarclaycardPaymentsRequest {
    processing_information: ProcessingInformation,
    payment_information: PaymentInformation,
    order_information: OrderInformationWithBill,
    client_reference_information: ClientReferenceInformation,
    #[serde(skip_serializing_if = "Option::is_none")]
    consumer_authentication_information: Option<BarclaycardConsumerAuthInformation>,
    #[serde(skip_serializing_if = "Option::is_none")]
    merchant_defined_information: Option<Vec<MerchantDefinedInformation>>,
}


pub struct PowertranzCard {
    cardholder_name: Secret<String>,
    card_pan: cards::CardNumber,
    card_expiration: Secret<String>,
    card_cvv: Secret<String>,
}


impl api::PaymentSync for Forte {}


pub struct KlarnaSdkResponse {
    pub payment_type: Option<String>,
}