pub async fn add_payment_method_data(
    state: routes::SessionState,
    req: api::PaymentMethodCreate,
    merchant_context: domain::MerchantContext,
    pm_id: String,
) -> errors::RouterResponse<api::PaymentMethodResponse> {
    let db = &*state.store;
    let cards = PmCards {
        state: &state,
        merchant_context: &merchant_context,
    };

    let pmd = req
        .payment_method_data
        .clone()
        .get_required_value("payment_method_data")?;
    req.payment_method.get_required_value("payment_method")?;
    let client_secret = req
        .client_secret
        .clone()
        .get_required_value("client_secret")?;
    let payment_method = db
        .find_payment_method(
            &((&state).into()),
            merchant_context.get_merchant_key_store(),
            pm_id.as_str(),
            merchant_context.get_merchant_account().storage_scheme,
        )
        .await
        .change_context(errors::ApiErrorResponse::PaymentMethodNotFound)
        .attach_printable("Unable to find payment method")?;

    if payment_method.status != enums::PaymentMethodStatus::AwaitingData {
        return Err((errors::ApiErrorResponse::ClientSecretExpired).into());
    }

    let customer_id = payment_method.customer_id.clone();

    let customer = db
        .find_customer_by_customer_id_merchant_id(
            &(&state).into(),
            &customer_id,
            merchant_context.get_merchant_account().get_id(),
            merchant_context.get_merchant_key_store(),
            merchant_context.get_merchant_account().storage_scheme,
        )
        .await
        .to_not_found_response(errors::ApiErrorResponse::CustomerNotFound)?;

    let client_secret_expired =
        authenticate_pm_client_secret_and_check_expiry(&client_secret, &payment_method)?;

    if client_secret_expired {
        return Err((errors::ApiErrorResponse::ClientSecretExpired).into());
    };
    let key_manager_state = (&state).into();
    match pmd {
        api_models::payment_methods::PaymentMethodCreateData::Card(card) => {
            helpers::validate_card_expiry(&card.card_exp_month, &card.card_exp_year)?;
            let resp = Box::pin(cards.add_card_to_locker(req.clone(), &card, &customer_id, None))
                .await
                .change_context(errors::ApiErrorResponse::InternalServerError);

            match resp {
                Ok((mut pm_resp, duplication_check)) => {
                    if duplication_check.is_some() {
                        let pm_update = storage::PaymentMethodUpdate::StatusUpdate {
                            status: Some(enums::PaymentMethodStatus::Inactive),
                        };

                        db.update_payment_method(
                            &((&state).into()),
                            merchant_context.get_merchant_key_store(),
                            payment_method,
                            pm_update,
                            merchant_context.get_merchant_account().storage_scheme,
                        )
                        .await
                        .change_context(errors::ApiErrorResponse::InternalServerError)
                        .attach_printable("Failed to add payment method in db")?;

                        cards
                            .get_or_insert_payment_method(
                                req.clone(),
                                &mut pm_resp,
                                &customer_id,
                                merchant_context.get_merchant_key_store(),
                            )
                            .await?;

                        return Ok(services::ApplicationResponse::Json(pm_resp));
                    } else {
                        let locker_id = pm_resp.payment_method_id.clone();
                        pm_resp.payment_method_id.clone_from(&pm_id);
                        pm_resp.client_secret = Some(client_secret.clone());

                        let card_isin = card.card_number.get_card_isin();

                        let card_info = db
                            .get_card_info(card_isin.as_str())
                            .await
                            .change_context(errors::ApiErrorResponse::InternalServerError)
                            .attach_printable("Failed to get card info")?;

                        let updated_card = CardDetailsPaymentMethod {
                            issuer_country: card_info
                                .as_ref()
                                .and_then(|ci| ci.card_issuing_country.clone()),
                            last4_digits: Some(card.card_number.get_last4()),
                            expiry_month: Some(card.card_exp_month),
                            expiry_year: Some(card.card_exp_year),
                            nick_name: card.nick_name,
                            card_holder_name: card.card_holder_name,
                            card_network: card_info.as_ref().and_then(|ci| ci.card_network.clone()),
                            card_isin: Some(card_isin),
                            card_issuer: card_info.as_ref().and_then(|ci| ci.card_issuer.clone()),
                            card_type: card_info.as_ref().and_then(|ci| ci.card_type.clone()),
                            saved_to_locker: true,
                            co_badged_card_data: None,
                        };
                        let pm_data_encrypted: Encryptable<Secret<serde_json::Value>> =
                            create_encrypted_data(
                                &key_manager_state,
                                merchant_context.get_merchant_key_store(),
                                PaymentMethodsData::Card(updated_card),
                            )
                            .await
                            .change_context(errors::ApiErrorResponse::InternalServerError)
                            .attach_printable("Unable to encrypt payment method data")?;

                        let pm_update = storage::PaymentMethodUpdate::AdditionalDataUpdate {
                            payment_method_data: Some(pm_data_encrypted.into()),
                            status: Some(enums::PaymentMethodStatus::Active),
                            locker_id: Some(locker_id),
                            network_token_requestor_reference_id: None,
                            payment_method: req.payment_method,
                            payment_method_issuer: req.payment_method_issuer,
                            payment_method_type: req.payment_method_type,
                            network_token_locker_id: None,
                            network_token_payment_method_data: None,
                        };

                        db.update_payment_method(
                            &((&state).into()),
                            merchant_context.get_merchant_key_store(),
                            payment_method,
                            pm_update,
                            merchant_context.get_merchant_account().storage_scheme,
                        )
                        .await
                        .change_context(errors::ApiErrorResponse::InternalServerError)
                        .attach_printable("Failed to add payment method in db")?;

                        if customer.default_payment_method_id.is_none() {
                            let _ = cards
                                .set_default_payment_method(
                                    merchant_context.get_merchant_account().get_id(),
                                    &customer_id,
                                    pm_id,
                                )
                                .await
                                .map_err(|error| {
                                    logger::error!(
                                        ?error,
                                        "Failed to set the payment method as default"
                                    )
                                });
                        }

                        return Ok(services::ApplicationResponse::Json(pm_resp));
                    }
                }
                Err(e) => {
                    let pm_update = storage::PaymentMethodUpdate::StatusUpdate {
                        status: Some(enums::PaymentMethodStatus::Inactive),
                    };

                    db.update_payment_method(
                        &((&state).into()),
                        merchant_context.get_merchant_key_store(),
                        payment_method,
                        pm_update,
                        merchant_context.get_merchant_account().storage_scheme,
                    )
                    .await
                    .change_context(errors::ApiErrorResponse::InternalServerError)
                    .attach_printable("Failed to update payment method in db")?;

                    return Err(e.attach_printable("Failed to add card to locker"));
                }
            }
        }
    }
}


impl std::ops::Deref for PaymentsTokenReference {
    type Target =
        HashMap<common_utils::id_type::MerchantConnectorAccountId, ConnectorTokenReferenceRecord>;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl std::ops::Deref for for PaymentsTokenReference


pub struct OpenMsearchOutput {
    #[serde(default)]
    pub responses: Vec<OpensearchOutput>,
    pub error: Option<OpensearchErrorDetails>,
}


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


File: crates/router/tests/connectors/unified_authentication_service.rs

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 UnifiedAuthenticationServiceTest;
impl ConnectorActions for UnifiedAuthenticationServiceTest {}
impl utils::Connector for UnifiedAuthenticationServiceTest {
    fn get_data(&self) -> api::ConnectorData {
        use router::connector::UnifiedAuthenticationService;
        utils::construct_connector_data_old(
            Box::new(UnifiedAuthenticationService::new()),
            types::Connector::Plaid,
            api::GetToken::Connector,
            None,
        )
    }

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

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

static CONNECTOR: UnifiedAuthenticationServiceTest = UnifiedAuthenticationServiceTest {};

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


impl api::PaymentToken for Razorpay {}


pub struct BarclaycardAuthenticationErrorResponse {
    pub response: AuthenticationErrorInformation,
}


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

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

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

    fn get_auth_header(
        &self,
        auth_type: &ConnectorAuthType,
    ) -> CustomResult<Vec<(String, Maskable<String>)>, errors::ConnectorError> {
        let auth = SquareAuthType::try_from(auth_type)
            .change_context(errors::ConnectorError::FailedToObtainAuthType)?;
        Ok(vec![(
            headers::AUTHORIZATION.to_string(),
            format!("Bearer {}", auth.api_key.peek()).into_masked(),
        )])
    }

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

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

        let mut reason_list = Vec::new();
        for error_iter in response.errors.iter() {
            if let Some(error) = error_iter.detail.clone() {
                reason_list.push(error)
            }
        }
        let reason = reason_list.join(" ");

        Ok(ErrorResponse {
            status_code: res.status_code,
            code: response
                .errors
                .first()
                .and_then(|error| error.code.clone())
                .unwrap_or(consts::NO_ERROR_CODE.to_string()),
            message: response
                .errors
                .first()
                .and_then(|error| error.category.clone())
                .unwrap_or(consts::NO_ERROR_MESSAGE.to_string()),
            reason: Some(reason),
            attempt_status: None,
            connector_transaction_id: None,
            network_advice_code: None,
            network_decline_code: None,
            network_error_message: None,
            connector_metadata: None,
        })
    }
}


OpenAPI Block Path: components.schemas.ProfileAcquirerUpdate
{
  "type": "object",
  "properties": {
    "acquirer_assigned_merchant_id": {
      "type": "string",
      "example": "M987654321",
      "nullable": true
    },
    "merchant_name": {
      "type": "string",
      "example": "Updated Retailer Name",
      "nullable": true
    },
    "network": {
      "type": "string",
      "example": "MASTERCARD",
      "nullable": true
    },
    "acquirer_bin": {
      "type": "string",
      "example": "987654",
      "nullable": true
    },
    "acquirer_ica": {
      "type": "string",
      "example": "501299",
      "nullable": true
    },
    "acquirer_fraud_rate": {
      "type": "number",
      "format": "double",
      "example": "0.02",
      "nullable": true
    }
  },
  "additionalProperties": false
}


pub(crate) async fn decide_retry_failure_action(
        state: &SessionState,
        merchant_id: &id_type::MerchantId,
        pt: storage::ProcessTracker,
        revenue_recovery_payment_data: &storage::revenue_recovery::RevenueRecoveryPaymentData,
        payment_attempt: &PaymentAttempt,
        payment_intent: &PaymentIntent,
    ) -> RecoveryResult<Self> {
        let db = &*state.store;
        let next_retry_count = pt.retry_count + 1;
        let error_message = payment_attempt
            .error
            .as_ref()
            .map(|details| details.message.clone());
        let error_code = payment_attempt
            .error
            .as_ref()
            .map(|details| details.code.clone());
        let connector_name = payment_attempt
            .connector
            .clone()
            .ok_or(errors::RecoveryError::ValueNotFound)
            .attach_printable("unable to derive payment connector from payment attempt")?;
        let gsm_record = helpers::get_gsm_record(
            state,
            error_code,
            error_message,
            connector_name,
            REVENUE_RECOVERY.to_string(),
        )
        .await;
        let is_hard_decline = gsm_record
            .and_then(|gsm_record| gsm_record.error_category)
            .map(|gsm_error_category| {
                gsm_error_category == common_enums::ErrorCategory::HardDecline
            })
            .unwrap_or(false);
        let schedule_time = revenue_recovery_payment_data
            .get_schedule_time_based_on_retry_type(
                state,
                merchant_id,
                next_retry_count,
                payment_attempt,
                payment_intent,
                is_hard_decline,
            )
            .await;

        match schedule_time {
            Some(schedule_time) => Ok(Self::RetryPayment(schedule_time)),

            None => Ok(Self::TerminalFailure(payment_attempt.clone())),
        }
    }


/// Calculate the net amount for the order
    pub fn calculate_net_amount(&self) -> MinorUnit {
        self.order_amount
            + self.shipping_cost.unwrap_or(MinorUnit::zero())
            + self.surcharge_amount.unwrap_or(MinorUnit::zero())
            + self.tax_on_surcharge.unwrap_or(MinorUnit::zero())
    }


pub struct VaultFingerprintResponse {
    pub fingerprint_id: String,
}


pub struct DefendDisputeRequestData {
    pub dispute_id: String,
    pub connector_dispute_id: String,
}


impl ResponseError for CustomJsonError {
        fn status_code(&self) -> StatusCode {
            StatusCode::BAD_REQUEST
        }

        fn error_response(&self) -> actix_web::HttpResponse<actix_web::body::BoxBody> {
            use actix_web::http::header;

            actix_web::HttpResponseBuilder::new(self.status_code())
                .insert_header((header::CONTENT_TYPE, mime::APPLICATION_JSON))
                .body(self.to_string())
        }
    }

impl ResponseError for for CustomJsonError


pub struct PayuRefundResponseData {
    refund_id: String,
    ext_refund_id: String,
    amount: String,
    currency_code: enums::Currency,
    description: String,
    creation_date_time: String,
    status: RefundStatus,
    status_date_time: Option<String>,
}


impl ConnectorRedirectResponse for Trustpay {
    fn get_flow_type(
        &self,
        _query_params: &str,
        _json_payload: Option<serde_json::Value>,
        action: PaymentAction,
    ) -> CustomResult<enums::CallConnectorAction, errors::ConnectorError> {
        match action {
            PaymentAction::PSync
            | PaymentAction::CompleteAuthorize
            | PaymentAction::PaymentAuthenticateCompleteAuthorize => {
                Ok(enums::CallConnectorAction::Trigger)
            }
        }
    }
}

impl ConnectorRedirectResponse for for Trustpay


pub async fn deep_health_check(
    state: web::Data<routes::AppState>,
    service: web::Data<String>,
) -> impl actix_web::Responder {
    let mut checks = HashMap::new();
    let stores = state.stores.clone();
    let app_state = Arc::clone(&state.into_inner());
    let service_name = service.into_inner();
    for (tenant, _) in stores {
        let session_state_res = app_state.clone().get_session_state(&tenant, None, || {
            errors::ApiErrorResponse::MissingRequiredField {
                field_name: "tenant_id",
            }
            .into()
        });
        let session_state = match session_state_res {
            Ok(state) => state,
            Err(err) => {
                return api::log_and_return_error_response(err);
            }
        };
        let report = deep_health_check_func(session_state, &service_name).await;
        match report {
            Ok(response) => {
                checks.insert(
                    tenant,
                    serde_json::to_string(&response)
                        .map_err(|err| {
                            logger::error!(serialization_error=?err);
                        })
                        .unwrap_or_default(),
                );
            }
            Err(err) => {
                return api::log_and_return_error_response(err);
            }
        }
    }
    services::http_response_json(
        serde_json::to_string(&checks)
            .map_err(|err| {
                logger::error!(serialization_error=?err);
            })
            .unwrap_or_default(),
    )
}


impl Responder {
    let flow = Flow::ApiKeyCreate;
    let payload = json_payload.into_inner();

    Box::pin(api::server_wrap(
        flow,
        state,
        &req,
        payload,
        |state, auth::AuthenticationDataWithoutProfile { key_store, .. }, payload, _| async {
            api_keys::create_api_key(state, payload, key_store).await
        },
        auth::auth_type(
            &auth::AdminApiAuthWithMerchantIdFromHeader,
            &auth::JWTAuthMerchantFromHeader {
                required_permission: Permission::MerchantApiKeyWrite,
            },
            req.headers(),
        ),
        api_locking::LockAction::NotApplicable,
    ))
    .await
}


pub async fn routing_link_config() {}


pub struct PayoneRouterData<T> {
    pub amount: MinorUnit,
    pub router_data: T,
}


pub async fn retrieve_poll_status(
    state: web::Data<AppState>,
    req: HttpRequest,
    path: web::Path<String>,
) -> HttpResponse {
    let flow = Flow::RetrievePollStatus;
    let poll_id = PollId {
        poll_id: path.into_inner(),
    };
    Box::pin(api::server_wrap(
        flow,
        state,
        &req,
        poll_id,
        |state, auth, req, _| {
            let merchant_context = domain::MerchantContext::NormalMerchant(Box::new(
                domain::Context(auth.merchant_account, auth.key_store),
            ));
            poll::retrieve_poll_status(state, req, merchant_context)
        },
        &auth::HeaderAuth(auth::PublishableKeyAuth),
        api_locking::LockAction::NotApplicable,
    ))
    .await
}


pub struct Pay3dsRequest {
    buyer_name: Secret<String>,
    buyer_email: pii::Email,
    buyer_key: Secret<String>,
    payme_sale_id: String,
    meta_data_jwt: Secret<String>,
}


OpenAPI Block Path: components.schemas.SurchargeResponse
{
  "oneOf": [
    {
      "type": "object",
      "required": [
        "type",
        "value"
      ],
      "properties": {
        "type": {
          "type": "string",
          "enum": [
            "fixed"
          ]
        },
        "value": {
          "$ref": "#/components/schemas/MinorUnit"
        }
      }
    },
    {
      "type": "object",
      "required": [
        "type",
        "value"
      ],
      "properties": {
        "type": {
          "type": "string",
          "enum": [
            "rate"
          ]
        },
        "value": {
          "$ref": "#/components/schemas/SurchargePercentage"
        }
      }
    }
  ],
  "discriminator": {
    "propertyName": "type"
  }
}


    fn to_old_router_data(
        new_router_data: RouterDataV2<T, Self, Req, Resp>,
    ) -> CustomResult<RouterData<T, Req, Resp>, ConnectorError>
    where
        Self: Sized,
    {
        let Self {
            merchant_id,
            customer_id,
            connector_customer,
            payment_id,
            attempt_id,
            status,
            payment_method,
            description,
            address,
            auth_type,
            connector_meta_data,
            amount_captured,
            minor_amount_captured,
            access_token,
            session_token,
            reference_id,
            payment_method_token,
            recurring_mandate_payment_data,
            preprocessing_id,
            payment_method_balance,
            connector_api_version,
            connector_request_reference_id,
            test_mode,
            connector_http_status_code,
            external_latency,
            apple_pay_flow,
            connector_response,
            payment_method_status,
        } = new_router_data.resource_common_data;
        let mut router_data = get_default_router_data(
            new_router_data.tenant_id.clone(),
            "external vault proxy",
            new_router_data.request,
            new_router_data.response,
        );
        router_data.merchant_id = merchant_id;
        router_data.customer_id = customer_id;
        router_data.connector_customer = connector_customer;
        router_data.payment_id = payment_id;
        router_data.attempt_id = attempt_id;
        router_data.status = status;
        router_data.payment_method = payment_method;
        router_data.description = description;
        router_data.address = address;
        router_data.auth_type = auth_type;
        router_data.connector_meta_data = connector_meta_data;
        router_data.amount_captured = amount_captured;
        router_data.minor_amount_captured = minor_amount_captured;
        router_data.access_token = access_token;
        router_data.session_token = session_token;
        router_data.reference_id = reference_id;
        router_data.payment_method_token = payment_method_token;
        router_data.recurring_mandate_payment_data = recurring_mandate_payment_data;
        router_data.preprocessing_id = preprocessing_id;
        router_data.payment_method_balance = payment_method_balance;
        router_data.connector_api_version = connector_api_version;
        router_data.connector_request_reference_id = connector_request_reference_id;
        router_data.test_mode = test_mode;
        router_data.connector_http_status_code = connector_http_status_code;
        router_data.external_latency = external_latency;
        router_data.apple_pay_flow = apple_pay_flow;
        router_data.connector_response = connector_response;
        router_data.payment_method_status = payment_method_status;
        Ok(router_data)
    }
}


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


pub fn get_connector_auth(
    connector: enums::Connector,
    connector_data: &settings::ConnectorOnboarding,
) -> RouterResult<types::ConnectorAuthType> {
    match connector {
        enums::Connector::Paypal => Ok(types::ConnectorAuthType::BodyKey {
            api_key: connector_data.paypal.client_secret.clone(),
            key1: connector_data.paypal.client_id.clone(),
        }),
        _ => Err(ApiErrorResponse::NotImplemented {
            message: NotImplementedMessage::Reason(format!(
                "Onboarding is not implemented for {connector}",
            )),
        }
        .into()),
    }
}


pub async fn find_by_payment_id_merchant_id(
        conn: &PgPooledConn,
        payment_id: &common_utils::id_type::PaymentId,
        merchant_id: &common_utils::id_type::MerchantId,
    ) -> StorageResult<Vec<Self>> {
        generics::generic_filter::<
            <Self as HasTable>::Table,
            _,
            <<Self as HasTable>::Table as Table>::PrimaryKey,
            _,
        >(
            conn,
            dsl::merchant_id
                .eq(merchant_id.to_owned())
                .and(dsl::payment_id.eq(payment_id.to_owned())),
            None,
            None,
            None,
        )
        .await
    }


pub struct AuthorizeResponse {
    pub is_email_sent: bool,
    //this field is added for audit/debug reasons
    #[serde(skip_serializing)]
    pub user_id: String,
}


impl Responder {
    let flow = Flow::PaymentsCreateAndConfirmIntent;
    let header_payload = match HeaderPayload::foreign_try_from(req.headers()) {
        Ok(headers) => headers,
        Err(err) => {
            return api::log_and_return_error_response(err);
        }
    };

    let auth_type = if state.conf.merchant_id_auth.merchant_id_auth_enabled {
        &auth::MerchantIdAuth
    } else {
        match env::which() {
            env::Env::Production => &auth::V2ApiKeyAuth {
                is_connected_allowed: false,
                is_platform_allowed: false,
            },
            _ => auth::auth_type(
                &auth::V2ApiKeyAuth {
                    is_connected_allowed: false,
                    is_platform_allowed: false,
                },
                &auth::JWTAuth {
                    permission: Permission::ProfilePaymentWrite,
                },
                req.headers(),
            ),
        }
    };

    Box::pin(api::server_wrap(
        flow,
        state,
        &req,
        json_payload.into_inner(),
        |state, auth: auth::AuthenticationData, request, req_state| {
            let merchant_context = domain::MerchantContext::NormalMerchant(Box::new(
                domain::Context(auth.merchant_account, auth.key_store),
            ));
            payments::payments_create_and_confirm_intent(
                state,
                req_state,
                merchant_context,
                auth.profile,
                request,
                header_payload.clone(),
            )
        },
        auth_type,
        api_locking::LockAction::NotApplicable,
    ))
    .await
}


pub fn new_for_create(
        mut previous_captures: Vec<storage::Capture>,
        new_capture: storage::Capture,
    ) -> Self {
        previous_captures.push(new_capture.clone());
        Self {
            all_captures: previous_captures
                .into_iter()
                .map(|capture| (capture.capture_id.clone(), capture))
                .collect(),
            latest_capture: new_capture,
            _private: Private {},
            expand_captures: None,
        }
    }


/// Performs Payment Sync/Get
    pub async fn payment_get(
        &self,
        payment_get_request: payments_grpc::PaymentServiceGetRequest,
        connector_auth_metadata: ConnectorAuthMetadata,
        grpc_headers: GrpcHeaders,
    ) -> UnifiedConnectorServiceResult<tonic::Response<payments_grpc::PaymentServiceGetResponse>>
    {
        let mut request = tonic::Request::new(payment_get_request);

        let connector_name = connector_auth_metadata.connector_name.clone();
        let metadata = build_unified_connector_service_grpc_headers(
            connector_auth_metadata,
            None,
            grpc_headers,
        )?;
        *request.metadata_mut() = metadata;

        self.client
            .clone()
            .get(request)
            .await
            .change_context(UnifiedConnectorServiceError::PaymentGetFailure)
            .inspect_err(|error| {
                logger::error!(
                    grpc_error=?error,
                    method="payment_get",
                    connector_name=?connector_name,
                    "UCS payment get/sync gRPC call failed"
                )
            })
    }


pub struct DigitalvirgoRouterData<T> {
    pub amount: FloatMajorUnit,
    pub surcharge_amount: Option<FloatMajorUnit>,
    pub router_data: T,
}


File: crates/router/src/core/card_testing_guard/utils.rs
 Public functions: 3

use error_stack::ResultExt;
use hyperswitch_domain_models::{
    card_testing_guard_data::CardTestingGuardData, router_request_types::BrowserInformation,
};
use masking::{PeekInterface, Secret};
use router_env::logger;

use super::errors;
use crate::{
    core::{errors::RouterResult, payments::helpers},
    routes::SessionState,
    services,
    types::{api, domain},
    utils::crypto::{self, SignMessage},
};

pub async fn validate_card_testing_guard_checks(
    state: &SessionState,
    request: &api::PaymentsRequest,
    payment_method_data: Option<&api_models::payments::PaymentMethodData>,
    customer_id: &Option<common_utils::id_type::CustomerId>,
    business_profile: &domain::Profile,
) -> RouterResult<Option<CardTestingGuardData>> {
    match &business_profile.card_testing_guard_config {
        Some(card_testing_guard_config) => {
            let fingerprint = generate_fingerprint(payment_method_data, business_profile).await?;

            let card_testing_guard_expiry = card_testing_guard_config.card_testing_guard_expiry;

            let mut card_ip_blocking_cache_key = String::new();
            let mut guest_user_card_blocking_cache_key = String::new();
            let mut customer_id_blocking_cache_key = String::new();

            if card_testing_guard_config.is_card_ip_blocking_enabled {
                if let Some(browser_info) = &request.browser_info {
                    #[cfg(feature = "v1")]
                    {
                        let browser_info =
                            serde_json::from_value::<BrowserInformation>(browser_info.clone())
                                .change_context(errors::ApiErrorResponse::InternalServerError)
                                .attach_printable("could not parse browser_info")?;

                        if let Some(browser_info_ip) = browser_info.ip_address {
                            card_ip_blocking_cache_key =
                                helpers::validate_card_ip_blocking_for_business_profile(
                                    state,
                                    browser_info_ip,
                                    fingerprint.clone(),
                                    card_testing_guard_config,
                                )
                                .await?;
                        }
                    }

                    #[cfg(feature = "v2")]
                    {
                        if let Some(browser_info_ip) = browser_info.ip_address {
                            card_ip_blocking_cache_key =
                                helpers::validate_card_ip_blocking_for_business_profile(
                                    state,
                                    browser_info_ip,
                                    fingerprint.clone(),
                                    card_testing_guard_config,
                                )
                                .await?;
                        }
                    }
                }
            }

            if card_testing_guard_config.is_guest_user_card_blocking_enabled {
                guest_user_card_blocking_cache_key =
                    helpers::validate_guest_user_card_blocking_for_business_profile(
                        state,
                        fingerprint.clone(),
                        customer_id.clone(),
                        card_testing_guard_config,
                    )
                    .await?;
            }

            if card_testing_guard_config.is_customer_id_blocking_enabled {
                if let Some(customer_id) = customer_id.clone() {
                    customer_id_blocking_cache_key =
                        helpers::validate_customer_id_blocking_for_business_profile(
                            state,
                            customer_id.clone(),
                            business_profile.get_id(),
                            card_testing_guard_config,
                        )
                        .await?;
                }
            }

            Ok(Some(CardTestingGuardData {
                is_card_ip_blocking_enabled: card_testing_guard_config.is_card_ip_blocking_enabled,
                card_ip_blocking_cache_key,
                is_guest_user_card_blocking_enabled: card_testing_guard_config
                    .is_guest_user_card_blocking_enabled,
                guest_user_card_blocking_cache_key,
                is_customer_id_blocking_enabled: card_testing_guard_config
                    .is_customer_id_blocking_enabled,
                customer_id_blocking_cache_key,
                card_testing_guard_expiry,
            }))
        }
        None => Ok(None),
    }
}

pub async fn generate_fingerprint(
    payment_method_data: Option<&api_models::payments::PaymentMethodData>,
    business_profile: &domain::Profile,
) -> RouterResult<Secret<String>> {
    let card_testing_secret_key = &business_profile.card_testing_secret_key;

    match card_testing_secret_key {
        Some(card_testing_secret_key) => {
            let card_number_fingerprint = payment_method_data
                .as_ref()
                .and_then(|pm_data| match pm_data {
                    api_models::payments::PaymentMethodData::Card(card) => {
                        crypto::HmacSha512::sign_message(
                            &crypto::HmacSha512,
                            card_testing_secret_key.get_inner().peek().as_bytes(),
                            card.card_number.clone().get_card_no().as_bytes(),
                        )
                        .attach_printable("error in pm fingerprint creation")
                        .map_or_else(
                            |err| {
                                logger::error!(error=?err);
                                None
                            },
                            Some,
                        )
                    }
                    _ => None,
                })
                .map(hex::encode);

            card_number_fingerprint.map(Secret::new).ok_or_else(|| {
                error_stack::report!(errors::ApiErrorResponse::InternalServerError)
                    .attach_printable("Error while masking fingerprint")
            })
        }
        None => Err(errors::ApiErrorResponse::InternalServerError)
            .attach_printable("card testing secret key not configured")?,
    }
}

pub async fn increment_blocked_count_in_cache(
    state: &SessionState,
    card_testing_guard_data: Option<CardTestingGuardData>,
) -> RouterResult<()> {
    if let Some(card_testing_guard_data) = card_testing_guard_data.clone() {
        if card_testing_guard_data.is_card_ip_blocking_enabled
            && !card_testing_guard_data
                .card_ip_blocking_cache_key
                .is_empty()
        {
            let _ = services::card_testing_guard::increment_blocked_count_in_cache(
                state,
                &card_testing_guard_data.card_ip_blocking_cache_key,
                card_testing_guard_data.card_testing_guard_expiry.into(),
            )
            .await;
        }

        if card_testing_guard_data.is_guest_user_card_blocking_enabled
            && !card_testing_guard_data
                .guest_user_card_blocking_cache_key
                .is_empty()
        {
            let _ = services::card_testing_guard::increment_blocked_count_in_cache(
                state,
                &card_testing_guard_data.guest_user_card_blocking_cache_key,
                card_testing_guard_data.card_testing_guard_expiry.into(),
            )
            .await;
        }

        if card_testing_guard_data.is_customer_id_blocking_enabled
            && !card_testing_guard_data
                .customer_id_blocking_cache_key
                .is_empty()
        {
            let _ = services::card_testing_guard::increment_blocked_count_in_cache(
                state,
                &card_testing_guard_data.customer_id_blocking_cache_key,
                card_testing_guard_data.card_testing_guard_expiry.into(),
            )
            .await;
        }
    }
    Ok(())
}


impl UserRole {
    fn check_user_in_lineage(
        tenant_id: id_type::TenantId,
        org_id: Option<id_type::OrganizationId>,
        merchant_id: Option<id_type::MerchantId>,
        profile_id: Option<id_type::ProfileId>,
    ) -> Box<
        dyn diesel::BoxableExpression<<Self as HasTable>::Table, Pg, SqlType = Nullable<Bool>>
            + 'static,
    > {
        // Checking in user roles, for a user in token hierarchy, only one of the relations will be true:
        // either tenant level, org level, merchant level, or profile level
        // Tenant-level: (tenant_id = ? && org_id = null && merchant_id = null && profile_id = null)
        // Org-level: (org_id = ? && merchant_id = null && profile_id = null)
        // Merchant-level: (org_id = ? && merchant_id = ? && profile_id = null)
        // Profile-level: (org_id = ? && merchant_id = ? && profile_id = ?)
        Box::new(
            // Tenant-level condition
            dsl::tenant_id
                .eq(tenant_id.clone())
                .and(dsl::org_id.is_null())
                .and(dsl::merchant_id.is_null())
                .and(dsl::profile_id.is_null())
                .or(
                    // Org-level condition
                    dsl::tenant_id
                        .eq(tenant_id.clone())
                        .and(dsl::org_id.eq(org_id.clone()))
                        .and(dsl::merchant_id.is_null())
                        .and(dsl::profile_id.is_null()),
                )
                .or(
                    // Merchant-level condition
                    dsl::tenant_id
                        .eq(tenant_id.clone())
                        .and(dsl::org_id.eq(org_id.clone()))
                        .and(dsl::merchant_id.eq(merchant_id.clone()))
                        .and(dsl::profile_id.is_null()),
                )
                .or(
                    // Profile-level condition
                    dsl::tenant_id
                        .eq(tenant_id)
                        .and(dsl::org_id.eq(org_id))
                        .and(dsl::merchant_id.eq(merchant_id))
                        .and(dsl::profile_id.eq(profile_id)),
                ),
        )
    }

    pub async fn find_by_user_id_tenant_id_org_id_merchant_id_profile_id(
        conn: &PgPooledConn,
        user_id: String,
        tenant_id: id_type::TenantId,
        org_id: id_type::OrganizationId,
        merchant_id: id_type::MerchantId,
        profile_id: id_type::ProfileId,
        version: UserRoleVersion,
    ) -> StorageResult<Self> {
        let check_lineage = Self::check_user_in_lineage(
            tenant_id,
            Some(org_id),
            Some(merchant_id),
            Some(profile_id),
        );

        let predicate = dsl::user_id
            .eq(user_id)
            .and(check_lineage)
            .and(dsl::version.eq(version));

        generics::generic_find_one::<<Self as HasTable>::Table, _, _>(conn, predicate).await
    }

    #[allow(clippy::too_many_arguments)]
    pub async fn update_by_user_id_tenant_id_org_id_merchant_id_profile_id(
        conn: &PgPooledConn,
        user_id: String,
        tenant_id: id_type::TenantId,
        org_id: id_type::OrganizationId,
        merchant_id: Option<id_type::MerchantId>,
        profile_id: Option<id_type::ProfileId>,
        update: UserRoleUpdate,
        version: UserRoleVersion,
    ) -> StorageResult<Self> {
        let check_lineage = dsl::tenant_id
            .eq(tenant_id.clone())
            .and(dsl::org_id.is_null())
            .and(dsl::merchant_id.is_null())
            .and(dsl::profile_id.is_null())
            .or(
                // Org-level condition
                dsl::tenant_id
                    .eq(tenant_id.clone())
                    .and(dsl::org_id.eq(org_id.clone()))
                    .and(dsl::merchant_id.is_null())
                    .and(dsl::profile_id.is_null()),
            )
            .or(
                // Merchant-level condition
                dsl::tenant_id
                    .eq(tenant_id.clone())
                    .and(dsl::org_id.eq(org_id.clone()))
                    .and(dsl::merchant_id.eq(merchant_id.clone()))
                    .and(dsl::profile_id.is_null()),
            )
            .or(
                // Profile-level condition
                dsl::tenant_id
                    .eq(tenant_id)
                    .and(dsl::org_id.eq(org_id))
                    .and(dsl::merchant_id.eq(merchant_id))
                    .and(dsl::profile_id.eq(profile_id)),
            );

        let predicate = dsl::user_id
            .eq(user_id)
            .and(check_lineage)
            .and(dsl::version.eq(version));

        generics::generic_update_with_unique_predicate_get_result::<
            <Self as HasTable>::Table,
            UserRoleUpdateInternal,
            _,
            _,
        >(conn, predicate, update.into())
        .await
    }

    pub async fn delete_by_user_id_tenant_id_org_id_merchant_id_profile_id(
        conn: &PgPooledConn,
        user_id: String,
        tenant_id: id_type::TenantId,
        org_id: id_type::OrganizationId,
        merchant_id: id_type::MerchantId,
        profile_id: id_type::ProfileId,
        version: UserRoleVersion,
    ) -> StorageResult<Self> {
        let check_lineage = Self::check_user_in_lineage(
            tenant_id,
            Some(org_id),
            Some(merchant_id),
            Some(profile_id),
        );

        let predicate = dsl::user_id
            .eq(user_id)
            .and(check_lineage)
            .and(dsl::version.eq(version));

        generics::generic_delete_one_with_result::<<Self as HasTable>::Table, _, _>(conn, predicate)
            .await
    }

    #[allow(clippy::too_many_arguments)]
    pub async fn generic_user_roles_list_for_user(
        conn: &PgPooledConn,
        user_id: String,
        tenant_id: id_type::TenantId,
        org_id: Option<id_type::OrganizationId>,
        merchant_id: Option<id_type::MerchantId>,
        profile_id: Option<id_type::ProfileId>,
        entity_id: Option<String>,
        status: Option<UserStatus>,
        version: Option<UserRoleVersion>,
        limit: Option<u32>,
    ) -> StorageResult<Vec<Self>> {
        let mut query = <Self as HasTable>::table()
            .filter(dsl::user_id.eq(user_id).and(dsl::tenant_id.eq(tenant_id)))
            .into_boxed();

        if let Some(org_id) = org_id {
            query = query.filter(dsl::org_id.eq(org_id));
        }

        if let Some(merchant_id) = merchant_id {
            query = query.filter(dsl::merchant_id.eq(merchant_id));
        }

        if let Some(profile_id) = profile_id {
            query = query.filter(dsl::profile_id.eq(profile_id));
        }

        if let Some(entity_id) = entity_id {
            query = query.filter(dsl::entity_id.eq(entity_id));
        }

        if let Some(version) = version {
            query = query.filter(dsl::version.eq(version));
        }

        if let Some(status) = status {
            query = query.filter(dsl::status.eq(status));
        }

        if let Some(limit) = limit {
            query = query.limit(limit.into());
        }

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

        match generics::db_metrics::track_database_call::<Self, _, _>(
            query.get_results_async(conn),
            generics::db_metrics::DatabaseOperation::Filter,
        )
        .await
        {
            Ok(value) => Ok(value),
            Err(err) => match err {
                DieselError::NotFound => {
                    Err(report!(err)).change_context(errors::DatabaseError::NotFound)
                }
                _ => Err(report!(err)).change_context(errors::DatabaseError::Others),
            },
        }
    }

    #[allow(clippy::too_many_arguments)]
    pub async fn generic_user_roles_list_for_org_and_extra(
        conn: &PgPooledConn,
        user_id: Option<String>,
        tenant_id: id_type::TenantId,
        org_id: id_type::OrganizationId,
        merchant_id: Option<id_type::MerchantId>,
        profile_id: Option<id_type::ProfileId>,
        version: Option<UserRoleVersion>,
        limit: Option<u32>,
    ) -> StorageResult<Vec<Self>> {
        let mut query = <Self as HasTable>::table()
            .filter(dsl::org_id.eq(org_id).and(dsl::tenant_id.eq(tenant_id)))
            .into_boxed();

        if let Some(user_id) = user_id {
            query = query.filter(dsl::user_id.eq(user_id));
        }

        if let Some(merchant_id) = merchant_id {
            query = query.filter(dsl::merchant_id.eq(merchant_id));
        }

        if let Some(profile_id) = profile_id {
            query = query.filter(dsl::profile_id.eq(profile_id));
        }

        if let Some(version) = version {
            query = query.filter(dsl::version.eq(version));
        }

        if let Some(limit) = limit {
            query = query.limit(limit.into());
        }

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

        match generics::db_metrics::track_database_call::<Self, _, _>(
            query.get_results_async(conn),
            generics::db_metrics::DatabaseOperation::Filter,
        )
        .await
        {
            Ok(value) => Ok(value),
            Err(err) => match err {
                DieselError::NotFound => {
                    Err(report!(err)).change_context(errors::DatabaseError::NotFound)
                }
                _ => Err(report!(err)).change_context(errors::DatabaseError::Others),
            },
        }
    }

    pub async fn list_user_roles_by_user_id_across_tenants(
        conn: &PgPooledConn,
        user_id: String,
        limit: Option<u32>,
    ) -> StorageResult<Vec<Self>> {
        let mut query = <Self as HasTable>::table()
            .filter(dsl::user_id.eq(user_id))
            .into_boxed();
        if let Some(limit) = limit {
            query = query.limit(limit.into());
        }

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

        match generics::db_metrics::track_database_call::<Self, _, _>(
            query.get_results_async(conn),
            generics::db_metrics::DatabaseOperation::Filter,
        )
        .await
        {
            Ok(value) => Ok(value),
            Err(err) => match err {
                DieselError::NotFound => {
                    Err(report!(err)).change_context(errors::DatabaseError::NotFound)
                }
                _ => Err(report!(err)).change_context(errors::DatabaseError::Others),
            },
        }
    }
}


/// get_surcharge_dsk_key
    pub fn get_surcharge_dsk_key(&self) -> String {
        format!("surcharge_dsl_{}", self.get_string_repr())
    }


pub struct TokenizationNew {
    pub id: common_utils::id_type::GlobalTokenId,
    pub merchant_id: common_utils::id_type::MerchantId,
    pub customer_id: common_utils::id_type::GlobalCustomerId,
    pub locker_id: String,
    pub flag: common_enums::TokenizationFlag,
    pub version: common_enums::ApiVersion,
}


impl SerializableSecret for u8 {}


impl DefendDispute for Adyen {}


pub fn generate_authorization_signature(
        &self,
        auth: fiserv::FiservAuthType,
        request_id: &str,
        payload: &str,
        timestamp: i128,
    ) -> CustomResult<String, errors::ConnectorError> {
        let fiserv::FiservAuthType {
            api_key,
            api_secret,
            ..
        } = auth;
        let raw_signature = format!("{}{request_id}{timestamp}{payload}", api_key.peek());

        let key = hmac::Key::new(hmac::HMAC_SHA256, api_secret.expose().as_bytes());
        let signature_value = common_utils::consts::BASE64_ENGINE
            .encode(hmac::sign(&key, raw_signature.as_bytes()).as_ref());
        Ok(signature_value)
    }


pub fn get_payment_merchant_connector_account_id_using_account_reference_id(
        &self,
        account_reference_id: String,
    ) -> Option<id_type::MerchantConnectorAccountId> {
        self.feature_metadata.as_ref().and_then(|metadata| {
            metadata.revenue_recovery.as_ref().and_then(|recovery| {
                recovery
                    .mca_reference
                    .billing_to_recovery
                    .get(&account_reference_id)
                    .cloned()
            })
        })
    }


pub async fn list_initial_attempts_by_profile_id_primary_object_id(
        conn: &PgPooledConn,
        profile_id: &common_utils::id_type::ProfileId,
        primary_object_id: &str,
    ) -> StorageResult<Vec<Self>> {
        generics::generic_filter::<<Self as HasTable>::Table, _, _, _>(
            conn,
            dsl::event_id
                .nullable()
                .eq(dsl::initial_attempt_id) // Filter initial attempts only
                .and(dsl::business_profile_id.eq(profile_id.to_owned()))
                .and(dsl::primary_object_id.eq(primary_object_id.to_owned())),
            None,
            None,
            Some(dsl::created_at.desc()),
        )
        .await
    }


impl api::PaymentSession for Bamboraapac {}

impl api::PaymentSession for for Bamboraapac


impl api::PaymentVoid for Hyperwallet {}

impl api::PaymentVoid for for Hyperwallet


pub struct PaypalSetupMandatesResponse {
    id: String,
    customer: Customer,
    payment_source: ZeroMandateSourceItem,
    links: Vec<PaypalLinks>,
}


OpenAPI Block Path: components.schemas.AuthenticationSyncResponse
{
  "type": "object",
  "required": [
    "authentication_id",
    "merchant_id",
    "status",
    "amount",
    "currency",
    "created_at",
    "profile_id"
  ],
  "properties": {
    "authentication_id": {
      "type": "string",
      "description": "The unique identifier for this authentication.",
      "example": "auth_mbabizu24mvu3mela5njyhpit4"
    },
    "merchant_id": {
      "type": "string",
      "description": "This is an identifier for the merchant account.",
      "example": "merchant_abc"
    },
    "status": {
      "$ref": "#/components/schemas/AuthenticationStatus"
    },
    "client_secret": {
      "type": "string",
      "description": "The client secret for this authentication.",
      "nullable": true
    },
    "amount": {
      "$ref": "#/components/schemas/MinorUnit"
    },
    "currency": {
      "$ref": "#/components/schemas/Currency"
    },
    "authentication_connector": {
      "allOf": [
        {
          "$ref": "#/components/schemas/AuthenticationConnectors"
        }
      ],
      "nullable": true
    },
    "force_3ds_challenge": {
      "type": "boolean",
      "description": "Whether 3DS challenge was forced.",
      "nullable": true
    },
    "return_url": {
      "type": "string",
      "description": "The URL to which the user should be redirected after authentication.",
      "nullable": true
    },
    "created_at": {
      "type": "string",
      "format": "date-time",
      "example": "2022-09-10T10:11:12Z"
    },
    "profile_id": {
      "type": "string",
      "description": "The business profile that is associated with this authentication."
    },
    "psd2_sca_exemption_type": {
      "allOf": [
        {
          "$ref": "#/components/schemas/ScaExemptionType"
        }
      ],
      "nullable": true
    },
    "acquirer_details": {
      "allOf": [
        {
          "$ref": "#/components/schemas/AcquirerDetails"
        }
      ],
      "nullable": true
    },
    "threeds_server_transaction_id": {
      "type": "string",
      "description": "The unique identifier from the 3DS server.",
      "nullable": true
    },
    "maximum_supported_3ds_version": {
      "type": "string",
      "description": "The maximum supported 3DS version.",
      "nullable": true
    },
    "connector_authentication_id": {
      "type": "string",
      "description": "The unique identifier from the connector.",
      "nullable": true
    },
    "three_ds_method_data": {
      "type": "string",
      "description": "The data required to perform the 3DS method.",
      "nullable": true
    },
    "three_ds_method_url": {
      "type": "string",
      "description": "The URL for the 3DS method.",
      "nullable": true
    },
    "message_version": {
      "type": "string",
      "description": "The version of the message.",
      "nullable": true
    },
    "connector_metadata": {
      "description": "The metadata for this authentication.",
      "nullable": true
    },
    "directory_server_id": {
      "type": "string",
      "description": "The unique identifier for the directory server.",
      "nullable": true
    },
    "billing": {
      "allOf": [
        {
          "$ref": "#/components/schemas/Address"
        }
      ],
      "nullable": true
    },
    "shipping": {
      "allOf": [
        {
          "$ref": "#/components/schemas/Address"
        }
      ],
      "nullable": true
    },
    "browser_information": {
      "allOf": [
        {
          "$ref": "#/components/schemas/BrowserInformation"
        }
      ],
      "nullable": true
    },
    "email": {
      "type": "string",
      "description": "Email.",
      "nullable": true
    },
    "trans_status": {
      "allOf": [
        {
          "$ref": "#/components/schemas/TransactionStatus"
        }
      ],
      "nullable": true
    },
    "acs_url": {
      "type": "string",
      "description": "Access Server URL for challenge submission.",
      "nullable": true
    },
    "challenge_request": {
      "type": "string",
      "description": "Challenge request to be sent to acs_url.",
      "nullable": true
    },
    "acs_reference_number": {
      "type": "string",
      "description": "Unique identifier assigned by EMVCo.",
      "nullable": true
    },
    "acs_trans_id": {
      "type": "string",
      "description": "Unique identifier assigned by the ACS.",
      "nullable": true
    },
    "acs_signed_content": {
      "type": "string",
      "description": "JWS object created by the ACS for the ARes message.",
      "nullable": true
    },
    "three_ds_requestor_url": {
      "type": "string",
      "description": "Three DS Requestor URL.",
      "nullable": true
    },
    "three_ds_requestor_app_url": {
      "type": "string",
      "description": "Merchant app URL for OOB authentication.",
      "nullable": true
    },
    "authentication_value": {
      "type": "string",
      "description": "The authentication value for this authentication, only available in case of server to server request. Unavailable in case of client request due to security concern.",
      "nullable": true
    },
    "eci": {
      "type": "string",
      "description": "ECI value for this authentication, only available in case of server to server request. Unavailable in case of client request due to security concern.",
      "nullable": true
    },
    "error_message": {
      "type": "string",
      "description": "Error message if any.",
      "nullable": true
    },
    "error_code": {
      "type": "string",
      "description": "Error code if any.",
      "nullable": true
    },
    "profile_acquirer_id": {
      "type": "string",
      "description": "Profile Acquirer ID",
      "nullable": true
    }
  }
}


File: crates/router_derive/src/macros/api_error/helpers.rs

use proc_macro2::TokenStream;
use quote::ToTokens;
use syn::{
    parse::Parse, spanned::Spanned, DeriveInput, Field, Fields, LitStr, Token, TypePath, Variant,
};

use crate::macros::helpers::{get_metadata_inner, occurrence_error};

mod keyword {
    use syn::custom_keyword;

    // Enum metadata
    custom_keyword!(error_type_enum);

    // Variant metadata
    custom_keyword!(error_type);
    custom_keyword!(code);
    custom_keyword!(message);
    custom_keyword!(ignore);
}

enum EnumMeta {
    ErrorTypeEnum {
        keyword: keyword::error_type_enum,
        value: TypePath,
    },
}

impl Parse for EnumMeta {
    fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
        let lookahead = input.lookahead1();
        if lookahead.peek(keyword::error_type_enum) {
            let keyword = input.parse()?;
            input.parse::<Token![=]>()?;
            let value = input.parse()?;
            Ok(Self::ErrorTypeEnum { keyword, value })
        } else {
            Err(lookahead.error())
        }
    }
}

impl ToTokens for EnumMeta {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        match self {
            Self::ErrorTypeEnum { keyword, .. } => keyword.to_tokens(tokens),
        }
    }
}

trait DeriveInputExt {
    /// Get all the error metadata associated with an enum.
    fn get_metadata(&self) -> syn::Result<Vec<EnumMeta>>;
}

impl DeriveInputExt for DeriveInput {
    fn get_metadata(&self) -> syn::Result<Vec<EnumMeta>> {
        get_metadata_inner("error", &self.attrs)
    }
}

pub(super) trait HasErrorTypeProperties {
    fn get_type_properties(&self) -> syn::Result<ErrorTypeProperties>;
}

#[derive(Clone, Debug, Default)]
pub(super) struct ErrorTypeProperties {
    pub error_type_enum: Option<TypePath>,
}

impl HasErrorTypeProperties for DeriveInput {
    fn get_type_properties(&self) -> syn::Result<ErrorTypeProperties> {
        let mut output = ErrorTypeProperties::default();

        let mut error_type_enum_keyword = None;
        for meta in self.get_metadata()? {
            match meta {
                EnumMeta::ErrorTypeEnum { keyword, value } => {
                    if let Some(first_keyword) = error_type_enum_keyword {
                        return Err(occurrence_error(first_keyword, keyword, "error_type_enum"));
                    }

                    error_type_enum_keyword = Some(keyword);
                    output.error_type_enum = Some(value);
                }
            }
        }

        if output.error_type_enum.is_none() {
            return Err(syn::Error::new(
                self.span(),
                "error(error_type_enum) attribute not found",
            ));
        }

        Ok(output)
    }
}

enum VariantMeta {
    ErrorType {
        keyword: keyword::error_type,
        value: TypePath,
    },
    Code {
        keyword: keyword::code,
        value: LitStr,
    },
    Message {
        keyword: keyword::message,
        value: LitStr,
    },
    Ignore {
        keyword: keyword::ignore,
        value: LitStr,
    },
}

impl Parse for VariantMeta {
    fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
        let lookahead = input.lookahead1();
        if lookahead.peek(keyword::error_type) {
            let keyword = input.parse()?;
            let _: Token![=] = input.parse()?;
            let value = input.parse()?;
            Ok(Self::ErrorType { keyword, value })
        } else if lookahead.peek(keyword::code) {
            let keyword = input.parse()?;
            let _: Token![=] = input.parse()?;
            let value = input.parse()?;
            Ok(Self::Code { keyword, value })
        } else if lookahead.peek(keyword::message) {
            let keyword = input.parse()?;
            let _: Token![=] = input.parse()?;
            let value = input.parse()?;
            Ok(Self::Message { keyword, value })
        } else if lookahead.peek(keyword::ignore) {
            let keyword = input.parse()?;
            let _: Token![=] = input.parse()?;
            let value = input.parse()?;
            Ok(Self::Ignore { keyword, value })
        } else {
            Err(lookahead.error())
        }
    }
}

impl ToTokens for VariantMeta {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        match self {
            Self::ErrorType { keyword, .. } => keyword.to_tokens(tokens),
            Self::Code { keyword, .. } => keyword.to_tokens(tokens),
            Self::Message { keyword, .. } => keyword.to_tokens(tokens),
            Self::Ignore { keyword, .. } => keyword.to_tokens(tokens),
        }
    }
}

trait VariantExt {
    /// Get all the error metadata associated with an enum variant.
    fn get_metadata(&self) -> syn::Result<Vec<VariantMeta>>;
}

impl VariantExt for Variant {
    fn get_metadata(&self) -> syn::Result<Vec<VariantMeta>> {
        get_metadata_inner("error", &self.attrs)
    }
}

pub(super) trait HasErrorVariantProperties {
    fn get_variant_properties(&self) -> syn::Result<ErrorVariantProperties>;
}

#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub(super) struct ErrorVariantProperties {
    pub error_type: Option<TypePath>,
    pub code: Option<LitStr>,
    pub message: Option<LitStr>,
    pub ignore: std::collections::HashSet<String>,
}

impl HasErrorVariantProperties for Variant {
    fn get_variant_properties(&self) -> syn::Result<ErrorVariantProperties> {
        let mut output = ErrorVariantProperties::default();

        let mut error_type_keyword = None;
        let mut code_keyword = None;
        let mut message_keyword = None;
        let mut ignore_keyword = None;
        for meta in self.get_metadata()? {
            match meta {
                VariantMeta::ErrorType { keyword, value } => {
                    if let Some(first_keyword) = error_type_keyword {
                        return Err(occurrence_error(first_keyword, keyword, "error_type"));
                    }

                    error_type_keyword = Some(keyword);
                    output.error_type = Some(value);
                }
                VariantMeta::Code { keyword, value } => {
                    if let Some(first_keyword) = code_keyword {
                        return Err(occurrence_error(first_keyword, keyword, "code"));
                    }

                    code_keyword = Some(keyword);
                    output.code = Some(value);
                }
                VariantMeta::Message { keyword, value } => {
                    if let Some(first_keyword) = message_keyword {
                        return Err(occurrence_error(first_keyword, keyword, "message"));
                    }

                    message_keyword = Some(keyword);
                    output.message = Some(value);
                }
                VariantMeta::Ignore { keyword, value } => {
                    if let Some(first_keyword) = ignore_keyword {
                        return Err(occurrence_error(first_keyword, keyword, "ignore"));
                    }
                    ignore_keyword = Some(keyword);
                    output.ignore = value
                        .value()
                        .replace(' ', "")
                        .split(',')
                        .map(ToString::to_string)
                        .collect();
                }
            }
        }

        Ok(output)
    }
}

fn missing_attribute_error(variant: &Variant, attr: &str) -> syn::Error {
    syn::Error::new_spanned(variant, format!("{attr} must be specified"))
}

pub(super) fn check_missing_attributes(
    variant: &Variant,
    variant_properties: &ErrorVariantProperties,
) -> syn::Result<()> {
    if variant_properties.error_type.is_none() {
        return Err(missing_attribute_error(variant, "error_type"));
    }
    if variant_properties.code.is_none() {
        return Err(missing_attribute_error(variant, "code"));
    }
    if variant_properties.message.is_none() {
        return Err(missing_attribute_error(variant, "message"));
    }

    Ok(())
}

/// Get all the fields not used in the error message.
pub(super) fn get_unused_fields(
    fields: &Fields,
    message: &str,
    ignore: &std::collections::HashSet<String>,
) -> Vec<Field> {
    let fields = match fields {
        Fields::Unit => Vec::new(),
        Fields::Unnamed(_) => Vec::new(),
        Fields::Named(fields) => fields.named.iter().cloned().collect(),
    };
    fields
        .iter()
        .filter(|&field| {
            // Safety: Named fields are guaranteed to have an identifier.
            #[allow(clippy::unwrap_used)]
            let field_name = format!("{}", field.ident.as_ref().unwrap());
            !message.contains(&field_name) && !ignore.contains(&field_name)
        })
        .cloned()
        .collect()
}


File: crates/drainer/src/errors.rs

use redis_interface as redis;
use thiserror::Error;

#[derive(Debug, Error)]
pub enum DrainerError {
    #[error("Error in parsing config : {0}")]
    ConfigParsingError(String),
    #[error("Error during redis operation : {0:?}")]
    RedisError(error_stack::Report<redis::errors::RedisError>),
    #[error("Application configuration error: {0}")]
    ConfigurationError(config::ConfigError),
    #[error("Error while configuring signals: {0}")]
    SignalError(String),
    #[error("Error while parsing data from the stream: {0:?}")]
    ParsingError(error_stack::Report<common_utils::errors::ParsingError>),
    #[error("Unexpected error occurred: {0}")]
    UnexpectedError(String),
    #[error("I/O: {0}")]
    IoError(std::io::Error),
}

#[derive(Debug, Error, Clone, serde::Serialize)]
pub enum HealthCheckError {
    #[error("Database health check is failing with error: {message}")]
    DbError { message: String },
    #[error("Redis health check is failing with error: {message}")]
    RedisError { message: String },
}

impl From<std::io::Error> for DrainerError {
    fn from(err: std::io::Error) -> Self {
        Self::IoError(err)
    }
}

pub type DrainerResult<T> = error_stack::Result<T, DrainerError>;

impl From<config::ConfigError> for DrainerError {
    fn from(err: config::ConfigError) -> Self {
        Self::ConfigurationError(err)
    }
}

impl From<error_stack::Report<redis::errors::RedisError>> for DrainerError {
    fn from(err: error_stack::Report<redis::errors::RedisError>) -> Self {
        Self::RedisError(err)
    }
}

impl actix_web::ResponseError for HealthCheckError {
    fn status_code(&self) -> reqwest::StatusCode {
        use reqwest::StatusCode;

        match self {
            Self::DbError { .. } | Self::RedisError { .. } => StatusCode::INTERNAL_SERVER_ERROR,
        }
    }
}


impl api::PaymentSync for Stax {}


impl api::MandateSetup for UnifiedAuthenticationService {}

impl api::MandateSetup for for UnifiedAuthenticationService


File: crates/hyperswitch_domain_models/src/router_data_v2/flow_common_types.rs
 Public structs: 17

use common_utils::{pii, types::MinorUnit};

use crate::{
    payment_address::PaymentAddress,
    payment_method_data::ApplePayFlow,
    router_data::{
        AccessToken, ConnectorResponseData, PaymentMethodBalance, PaymentMethodToken,
        RecurringMandatePaymentData,
    },
};

#[derive(Debug, Clone)]
pub struct PaymentFlowData {
    pub merchant_id: common_utils::id_type::MerchantId,
    pub customer_id: Option<common_utils::id_type::CustomerId>,
    pub connector_customer: Option<String>,
    pub payment_id: String,
    pub attempt_id: String,
    pub status: common_enums::AttemptStatus,
    pub payment_method: common_enums::PaymentMethod,
    pub description: Option<String>,
    pub address: PaymentAddress,
    pub auth_type: common_enums::AuthenticationType,
    pub connector_meta_data: Option<pii::SecretSerdeValue>,
    pub amount_captured: Option<i64>,
    // minor amount for amount framework
    pub minor_amount_captured: Option<MinorUnit>,
    pub access_token: Option<AccessToken>,
    pub session_token: Option<String>,
    pub reference_id: Option<String>,
    pub payment_method_token: Option<PaymentMethodToken>,
    pub recurring_mandate_payment_data: Option<RecurringMandatePaymentData>,
    pub preprocessing_id: Option<String>,
    /// This is the balance amount for gift cards or voucher
    pub payment_method_balance: Option<PaymentMethodBalance>,

    ///for switching between two different versions of the same connector
    pub connector_api_version: Option<String>,
    /// Contains a reference ID that should be sent in the connector request
    pub connector_request_reference_id: String,

    pub test_mode: Option<bool>,
    pub connector_http_status_code: Option<u16>,
    pub external_latency: Option<u128>,
    /// Contains apple pay flow type simplified or manual
    pub apple_pay_flow: Option<ApplePayFlow>,

    /// This field is used to store various data regarding the response from connector
    pub connector_response: Option<ConnectorResponseData>,
    pub payment_method_status: Option<common_enums::PaymentMethodStatus>,
}

#[derive(Debug, Clone)]
pub struct RefundFlowData {
    pub merchant_id: common_utils::id_type::MerchantId,
    pub customer_id: Option<common_utils::id_type::CustomerId>,
    pub payment_id: String,
    pub attempt_id: String,
    pub status: common_enums::AttemptStatus,
    pub payment_method: common_enums::PaymentMethod,
    pub connector_meta_data: Option<pii::SecretSerdeValue>,
    pub amount_captured: Option<i64>,
    // minor amount for amount framework
    pub minor_amount_captured: Option<MinorUnit>,
    /// Contains a reference ID that should be sent in the connector request
    pub connector_request_reference_id: String,
    pub refund_id: String,
}

#[cfg(feature = "payouts")]
#[derive(Debug, Clone)]
pub struct PayoutFlowData {
    pub merchant_id: common_utils::id_type::MerchantId,
    pub customer_id: Option<common_utils::id_type::CustomerId>,
    pub connector_customer: Option<String>,
    pub address: PaymentAddress,
    pub connector_meta_data: Option<pii::SecretSerdeValue>,
    pub connector_wallets_details: Option<pii::SecretSerdeValue>,
    /// Contains a reference ID that should be sent in the connector request
    pub connector_request_reference_id: String,
    pub payout_method_data: Option<api_models::payouts::PayoutMethodData>,
    pub quote_id: Option<String>,
}

#[cfg(feature = "frm")]
#[derive(Debug, Clone)]
pub struct FrmFlowData {
    pub merchant_id: common_utils::id_type::MerchantId,
    pub payment_id: String,
    pub attempt_id: String,
    pub payment_method: common_enums::enums::PaymentMethod,
    pub connector_request_reference_id: String,
    pub auth_type: common_enums::enums::AuthenticationType,
    pub connector_wallets_details: Option<pii::SecretSerdeValue>,
    pub connector_meta_data: Option<pii::SecretSerdeValue>,
    pub amount_captured: Option<i64>,
    // minor amount for amount framework
    pub minor_amount_captured: Option<MinorUnit>,
}

#[derive(Debug, Clone)]
pub struct ExternalAuthenticationFlowData {
    pub merchant_id: common_utils::id_type::MerchantId,
    pub connector_meta_data: Option<pii::SecretSerdeValue>,
    pub address: PaymentAddress,
}

#[derive(Debug, Clone)]
pub struct DisputesFlowData {
    pub merchant_id: common_utils::id_type::MerchantId,
    pub payment_id: String,
    pub attempt_id: String,
    pub payment_method: common_enums::enums::PaymentMethod,
    pub connector_meta_data: Option<pii::SecretSerdeValue>,
    pub amount_captured: Option<i64>,
    // minor amount for amount framework
    pub minor_amount_captured: Option<MinorUnit>,
    /// Contains a reference ID that should be sent in the connector request
    pub connector_request_reference_id: String,
    pub dispute_id: String,
}

#[derive(Debug, Clone)]
pub struct MandateRevokeFlowData {
    pub merchant_id: common_utils::id_type::MerchantId,
    pub customer_id: common_utils::id_type::CustomerId,
    pub payment_id: Option<String>,
}

#[derive(Debug, Clone)]
pub struct WebhookSourceVerifyData {
    pub merchant_id: common_utils::id_type::MerchantId,
}

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

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

#[derive(Debug, Clone)]
pub struct FilesFlowData {
    pub merchant_id: common_utils::id_type::MerchantId,
    pub payment_id: String,
    pub attempt_id: String,
    pub connector_meta_data: Option<pii::SecretSerdeValue>,
    pub connector_request_reference_id: String,
}

#[derive(Debug, Clone)]
pub struct RevenueRecoveryRecordBackData;

#[derive(Debug, Clone)]
pub struct UasFlowData {
    pub authenticate_by: String,
    pub source_authentication_id: common_utils::id_type::AuthenticationId,
}

#[derive(Debug, Clone)]
pub struct BillingConnectorPaymentsSyncFlowData;

#[derive(Debug, Clone)]
pub struct BillingConnectorInvoiceSyncFlowData;

#[derive(Debug, Clone)]
pub struct VaultConnectorFlowData {
    pub merchant_id: common_utils::id_type::MerchantId,
}

#[derive(Debug, Clone)]
pub struct ExternalVaultProxyFlowData {
    pub merchant_id: common_utils::id_type::MerchantId,
    pub customer_id: Option<common_utils::id_type::CustomerId>,
    pub connector_customer: Option<String>,
    pub payment_id: String,
    pub attempt_id: String,
    pub status: common_enums::AttemptStatus,
    pub payment_method: common_enums::PaymentMethod,
    pub description: Option<String>,
    pub address: PaymentAddress,
    pub auth_type: common_enums::AuthenticationType,
    pub connector_meta_data: Option<pii::SecretSerdeValue>,
    pub amount_captured: Option<i64>,
    // minor amount for amount framework
    pub minor_amount_captured: Option<MinorUnit>,
    pub access_token: Option<AccessToken>,
    pub session_token: Option<String>,
    pub reference_id: Option<String>,
    pub payment_method_token: Option<PaymentMethodToken>,
    pub recurring_mandate_payment_data: Option<RecurringMandatePaymentData>,
    pub preprocessing_id: Option<String>,
    /// This is the balance amount for gift cards or voucher
    pub payment_method_balance: Option<PaymentMethodBalance>,

    ///for switching between two different versions of the same connector
    pub connector_api_version: Option<String>,
    /// Contains a reference ID that should be sent in the connector request
    pub connector_request_reference_id: String,

    pub test_mode: Option<bool>,
    pub connector_http_status_code: Option<u16>,
    pub external_latency: Option<u128>,
    /// Contains apple pay flow type simplified or manual
    pub apple_pay_flow: Option<ApplePayFlow>,

    /// This field is used to store various data regarding the response from connector
    pub connector_response: Option<ConnectorResponseData>,
    pub payment_method_status: Option<common_enums::PaymentMethodStatus>,
}


impl api::MandateSetup for Paytm {}


pub async fn unlink_routing_config(
    state: SessionState,
    merchant_context: domain::MerchantContext,
    request: routing_types::RoutingConfigRequest,
    authentication_profile_id: Option<common_utils::id_type::ProfileId>,
    transaction_type: enums::TransactionType,
) -> RouterResponse<routing_types::RoutingDictionaryRecord> {
    metrics::ROUTING_UNLINK_CONFIG.add(1, &[]);

    let db = state.store.as_ref();
    let key_manager_state = &(&state).into();

    let profile_id = request
        .profile_id
        .get_required_value("profile_id")
        .change_context(errors::ApiErrorResponse::MissingRequiredField {
            field_name: "profile_id",
        })
        .attach_printable("Profile_id not provided")?;

    let business_profile = core_utils::validate_and_get_business_profile(
        db,
        key_manager_state,
        merchant_context.get_merchant_key_store(),
        Some(&profile_id),
        merchant_context.get_merchant_account().get_id(),
    )
    .await?;

    match business_profile {
        Some(business_profile) => {
            core_utils::validate_profile_id_from_auth_layer(
                authentication_profile_id,
                &business_profile,
            )?;
            let routing_algo_ref: routing_types::RoutingAlgorithmRef = match transaction_type {
                enums::TransactionType::Payment => business_profile.routing_algorithm.clone(),
                #[cfg(feature = "payouts")]
                enums::TransactionType::Payout => business_profile.payout_routing_algorithm.clone(),
                enums::TransactionType::ThreeDsAuthentication => {
                    business_profile.three_ds_decision_rule_algorithm.clone()
                }
            }
            .map(|val| val.parse_value("RoutingAlgorithmRef"))
            .transpose()
            .change_context(errors::ApiErrorResponse::InternalServerError)
            .attach_printable("unable to deserialize routing algorithm ref from merchant account")?
            .unwrap_or_default();

            let timestamp = common_utils::date_time::now_unix_timestamp();

            match routing_algo_ref.algorithm_id {
                Some(algorithm_id) => {
                    let routing_algorithm: routing_types::RoutingAlgorithmRef =
                        routing_types::RoutingAlgorithmRef {
                            algorithm_id: None,
                            timestamp,
                            config_algo_id: routing_algo_ref.config_algo_id.clone(),
                            surcharge_config_algo_id: routing_algo_ref.surcharge_config_algo_id,
                        };

                    let record = db
                        .find_routing_algorithm_by_profile_id_algorithm_id(
                            &profile_id,
                            &algorithm_id,
                        )
                        .await
                        .to_not_found_response(errors::ApiErrorResponse::ResourceIdNotFound)?;
                    let response = record.foreign_into();
                    helpers::update_profile_active_algorithm_ref(
                        db,
                        key_manager_state,
                        merchant_context.get_merchant_key_store(),
                        business_profile,
                        routing_algorithm,
                        &transaction_type,
                    )
                    .await?;

                    metrics::ROUTING_UNLINK_CONFIG_SUCCESS_RESPONSE.add(1, &[]);
                    Ok(service_api::ApplicationResponse::Json(response))
                }
                None => Err(errors::ApiErrorResponse::PreconditionFailed {
                    message: "Algorithm is already inactive".to_string(),
                })?,
            }
        }
        None => Err(errors::ApiErrorResponse::InvalidRequestData {
            message: "The business_profile is not present".to_string(),
        }
        .into()),
    }
}


impl api::PaymentCapture for Nexixpay {}

impl api::PaymentCapture for for Nexixpay


pub async fn generic_user_roles_list_for_org_and_extra(
        conn: &PgPooledConn,
        user_id: Option<String>,
        tenant_id: id_type::TenantId,
        org_id: id_type::OrganizationId,
        merchant_id: Option<id_type::MerchantId>,
        profile_id: Option<id_type::ProfileId>,
        version: Option<UserRoleVersion>,
        limit: Option<u32>,
    ) -> StorageResult<Vec<Self>> {
        let mut query = <Self as HasTable>::table()
            .filter(dsl::org_id.eq(org_id).and(dsl::tenant_id.eq(tenant_id)))
            .into_boxed();

        if let Some(user_id) = user_id {
            query = query.filter(dsl::user_id.eq(user_id));
        }

        if let Some(merchant_id) = merchant_id {
            query = query.filter(dsl::merchant_id.eq(merchant_id));
        }

        if let Some(profile_id) = profile_id {
            query = query.filter(dsl::profile_id.eq(profile_id));
        }

        if let Some(version) = version {
            query = query.filter(dsl::version.eq(version));
        }

        if let Some(limit) = limit {
            query = query.limit(limit.into());
        }

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

        match generics::db_metrics::track_database_call::<Self, _, _>(
            query.get_results_async(conn),
            generics::db_metrics::DatabaseOperation::Filter,
        )
        .await
        {
            Ok(value) => Ok(value),
            Err(err) => match err {
                DieselError::NotFound => {
                    Err(report!(err)).change_context(errors::DatabaseError::NotFound)
                }
                _ => Err(report!(err)).change_context(errors::DatabaseError::Others),
            },
        }
    }


impl GetCaptureMethod for PaymentsSyncData {
    fn get_capture_method(&self) -> Option<enums::CaptureMethod> {
        self.capture_method
    }
}

impl GetCaptureMethod for for PaymentsSyncData


impl api::RefundExecute for Archipel {}

impl api::RefundExecute for for Archipel


/// Take ownership of a secret value
    pub fn new(secret: Secret) -> Self {
        Self {
            inner_secret: secret,
            masking_strategy: PhantomData,
        }
    }


pub struct PaymentVoidRequest {
    reference: String,
}


OpenAPI Block Path: components.schemas.BlikBankRedirectAdditionalData
{
  "type": "object",
  "properties": {
    "blik_code": {
      "type": "string",
      "example": "3GD9MO",
      "nullable": true
    }
  }
}