pub async fn trigger_refund_to_gateway(
    state: &SessionState,
    refund: &diesel_refund::Refund,
    merchant_context: &domain::MerchantContext,
    payment_attempt: &storage::PaymentAttempt,
    payment_intent: &storage::PaymentIntent,
) -> errors::RouterResult<diesel_refund::Refund> {
    let db = &*state.store;

    let mca_id = payment_attempt.get_attempt_merchant_connector_account_id()?;

    let storage_scheme = merchant_context.get_merchant_account().storage_scheme;

    let mca = db
        .find_merchant_connector_account_by_id(
            &state.into(),
            &mca_id,
            merchant_context.get_merchant_key_store(),
        )
        .await
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("Failed to fetch merchant connector account")?;

    metrics::REFUND_COUNT.add(
        1,
        router_env::metric_attributes!(("connector", mca_id.get_string_repr().to_string())),
    );

    let connector_enum = mca.connector_name;

    let connector: api::ConnectorData = api::ConnectorData::get_connector_by_name(
        &state.conf.connectors,
        &connector_enum.to_string(),
        api::GetToken::Connector,
        Some(mca_id.clone()),
    )?;

    refunds_validator::validate_for_valid_refunds(payment_attempt, connector.connector_name)?;

    let merchant_connector_account =
        domain::MerchantConnectorAccountTypeDetails::MerchantConnectorAccount(Box::new(mca));

    let mut router_data = core_utils::construct_refund_router_data(
        state,
        connector_enum,
        merchant_context,
        payment_intent,
        payment_attempt,
        refund,
        &merchant_connector_account,
    )
    .await?;

    let add_access_token_result = Box::pin(access_token::add_access_token(
        state,
        &connector,
        merchant_context,
        &router_data,
        None,
    ))
    .await?;

    logger::debug!(refund_router_data=?router_data);

    access_token::update_router_data_with_access_token_result(
        &add_access_token_result,
        &mut router_data,
        &payments::CallConnectorAction::Trigger,
    );

    let connector_response = Box::pin(call_connector_service(
        state,
        &connector,
        add_access_token_result,
        router_data,
    ))
    .await;

    let refund_update = get_refund_update_object(
        state,
        &connector,
        &storage_scheme,
        merchant_context,
        &connector_response,
    )
    .await;

    let response = match refund_update {
        Some(refund_update) => state
            .store
            .update_refund(
                refund.to_owned(),
                refund_update,
                merchant_context.get_merchant_account().storage_scheme,
            )
            .await
            .to_not_found_response(errors::ApiErrorResponse::InternalServerError)
            .attach_printable_lazy(|| {
                format!(
                    "Failed while updating refund: refund_id: {}",
                    refund.id.get_string_repr()
                )
            })?,
        None => refund.to_owned(),
    };
    // Implement outgoing webhooks here
    connector_response.to_refund_failed_response()?;
    Ok(response)
}


impl api::RefundExecute for Deutschebank {}

impl api::RefundExecute for for Deutschebank


pub struct MerchantAccountUpdateInternal {
    pub merchant_name: Option<Encryption>,
    pub merchant_details: Option<Encryption>,
    pub return_url: Option<String>,
    pub webhook_details: Option<crate::business_profile::WebhookDetails>,
    pub sub_merchants_enabled: Option<bool>,
    pub parent_merchant_id: Option<common_utils::id_type::MerchantId>,
    pub enable_payment_response_hash: Option<bool>,
    pub payment_response_hash_key: Option<String>,
    pub redirect_to_merchant_with_http_post: Option<bool>,
    pub publishable_key: Option<String>,
    pub storage_scheme: Option<storage_enums::MerchantStorageScheme>,
    pub locker_id: Option<String>,
    pub metadata: Option<pii::SecretSerdeValue>,
    pub routing_algorithm: Option<serde_json::Value>,
    pub primary_business_details: Option<serde_json::Value>,
    pub modified_at: time::PrimitiveDateTime,
    pub intent_fulfillment_time: Option<i64>,
    pub frm_routing_algorithm: Option<serde_json::Value>,
    pub payout_routing_algorithm: Option<serde_json::Value>,
    pub organization_id: Option<common_utils::id_type::OrganizationId>,
    pub is_recon_enabled: Option<bool>,
    pub default_profile: Option<Option<common_utils::id_type::ProfileId>>,
    pub recon_status: Option<storage_enums::ReconStatus>,
    pub payment_link_config: Option<serde_json::Value>,
    pub pm_collect_link_config: Option<serde_json::Value>,
    pub is_platform_account: Option<bool>,
    pub product_type: Option<common_enums::MerchantProductType>,
}


pub async fn dummy_connector_payment(
    state: web::Data<app::AppState>,
    req: actix_web::HttpRequest,
    json_payload: web::Json<types::DummyConnectorPaymentRequest>,
) -> impl actix_web::Responder {
    let payload = json_payload.into_inner();
    let flow = types::Flow::DummyPaymentCreate;
    Box::pin(api::server_wrap(
        flow,
        state,
        &req,
        payload,
        |state, _: (), req, _| core::payment(state, req),
        &auth::NoAuth,
        api_locking::LockAction::NotApplicable,
    ))
    .await
}


Documentation: api-reference/v1/refunds/refunds--update.mdx
# Type: Doc File

---
openapi: post /refunds/{refund_id}
---


pub struct MandateUpdateMems {
    pub orig: Mandate,
    pub update_data: MandateUpdateInternal,
}


pub struct ToggleDynamicRoutingQuery {
    pub enable: DynamicRoutingFeatures,
}


pub fn generate_new() -> Self {
        let mut rand = rand::thread_rng();
        let recovery_codes = (0..consts::user::RECOVERY_CODES_COUNT)
            .map(|_| {
                let code_part_1 =
                    Alphanumeric.sample_string(&mut rand, consts::user::RECOVERY_CODE_LENGTH / 2);
                let code_part_2 =
                    Alphanumeric.sample_string(&mut rand, consts::user::RECOVERY_CODE_LENGTH / 2);

                Secret::new(format!("{code_part_1}-{code_part_2}"))
            })
            .collect::<Vec<_>>();

        Self(recovery_codes)
    }


File: connector-template/transformers.rs
 Public structs: 1

use common_enums::enums;
use serde::{Deserialize, Serialize};
use masking::Secret;
use common_utils::types::{StringMinorUnit};
use hyperswitch_domain_models::{
    payment_method_data::PaymentMethodData,
    router_data::{ConnectorAuthType, RouterData},
    router_flow_types::refunds::{Execute, RSync},
    router_request_types::ResponseId,
    router_response_types::{PaymentsResponseData, RefundsResponseData},
    types::{PaymentsAuthorizeRouterData, RefundsRouterData},
};
use hyperswitch_interfaces::errors;
use crate::types::{RefundsResponseRouterData, ResponseRouterData};

//TODO: Fill the struct with respective fields
pub struct {{project-name | downcase | pascal_case}}RouterData<T> {
    pub amount: StringMinorUnit, // The type of amount that a connector accepts, for example, String, i64, f64, etc.
    pub router_data: T,
}

impl<T>
    From<(
        StringMinorUnit,
        T,
    )> for {{project-name | downcase | pascal_case}}RouterData<T>
{
    fn from(
        (amount, item): (
            StringMinorUnit,
            T,
        ),
    ) -> Self {
         //Todo :  use utils to convert the amount to the type of amount that a connector accepts
        Self {
            amount,
            router_data: item,
        }
    }
}

//TODO: Fill the struct with respective fields
#[derive(Default, Debug, Serialize, PartialEq)]
pub struct {{project-name | downcase | pascal_case}}PaymentsRequest {
    amount: StringMinorUnit,
    card: {{project-name | downcase | pascal_case}}Card
}

#[derive(Default, Debug, Serialize, Eq, PartialEq)]
pub struct {{project-name | downcase | pascal_case}}Card {
    number: cards::CardNumber,
    expiry_month: Secret<String>,
    expiry_year: Secret<String>,
    cvc: Secret<String>,
    complete: bool,
}

impl TryFrom<&{{project-name | downcase | pascal_case}}RouterData<&PaymentsAuthorizeRouterData>> for {{project-name | downcase | pascal_case}}PaymentsRequest  {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(item: &{{project-name | downcase | pascal_case}}RouterData<&PaymentsAuthorizeRouterData>) -> Result<Self,Self::Error> {
        match item.router_data.request.payment_method_data.clone() {
            PaymentMethodData::Card(_) => {
                Err(errors::ConnectorError::NotImplemented("Card payment method not implemented".to_string()).into())
            },
            _ => Err(errors::ConnectorError::NotImplemented("Payment method".to_string()).into()),
        }

    }
}

//TODO: Fill the struct with respective fields
// Auth Struct
pub struct {{project-name | downcase | pascal_case}}AuthType {
    pub(super) api_key: Secret<String>
}

impl TryFrom<&ConnectorAuthType> for {{project-name | downcase | pascal_case}}AuthType  {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(auth_type: &ConnectorAuthType) -> Result<Self, Self::Error> {
        match auth_type {
            ConnectorAuthType::HeaderKey { api_key } => Ok(Self {
                api_key: api_key.to_owned(),
            }),
            _ => Err(errors::ConnectorError::FailedToObtainAuthType.into()),
        }
    }
}
// PaymentsResponse
//TODO: Append the remaining status flags
#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "lowercase")]
pub enum {{project-name | downcase | pascal_case}}PaymentStatus {
    Succeeded,
    Failed,
    #[default]
    Processing,
}

impl From<{{project-name | downcase | pascal_case}}PaymentStatus> for common_enums::AttemptStatus {
    fn from(item: {{project-name | downcase | pascal_case}}PaymentStatus) -> Self {
        match item {
            {{project-name | downcase | pascal_case}}PaymentStatus::Succeeded => Self::Charged,
            {{project-name | downcase | pascal_case}}PaymentStatus::Failed => Self::Failure,
            {{project-name | downcase | pascal_case}}PaymentStatus::Processing => Self::Authorizing,
        }
    }
}

//TODO: Fill the struct with respective fields
#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct {{project-name | downcase | pascal_case}}PaymentsResponse {
    status: {{project-name | downcase | pascal_case}}PaymentStatus,
    id: String,
}

impl<F,T> TryFrom<ResponseRouterData<F, {{project-name | downcase | pascal_case}}PaymentsResponse, T, PaymentsResponseData>> for RouterData<F, T, PaymentsResponseData> {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(item: ResponseRouterData<F, {{project-name | downcase | pascal_case}}PaymentsResponse, T, PaymentsResponseData>) -> Result<Self,Self::Error> {
        Ok(Self {
            status: common_enums::AttemptStatus::from(item.response.status),
            response: Ok(PaymentsResponseData::TransactionResponse {
                resource_id: ResponseId::ConnectorTransactionId(item.response.id),
                redirection_data: Box::new(None),
                mandate_reference: Box::new(None),
                connector_metadata: None,
                network_txn_id: None,
                connector_response_reference_id: None,
                incremental_authorization_allowed: None,
                charges: None,
            }),
            ..item.data
        })
    }
}

//TODO: Fill the struct with respective fields
// REFUND :
// Type definition for RefundRequest
#[derive(Default, Debug, Serialize)]
pub struct {{project-name | downcase | pascal_case}}RefundRequest {
    pub amount: StringMinorUnit
}

impl<F> TryFrom<&{{project-name | downcase | pascal_case}}RouterData<&RefundsRouterData<F>>> for {{project-name | downcase | pascal_case}}RefundRequest {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(item: &{{project-name | downcase | pascal_case}}RouterData<&RefundsRouterData<F>>) -> Result<Self,Self::Error> {
        Ok(Self {
            amount: item.amount.to_owned(),
        })
    }
}

// Type definition for Refund Response

#[allow(dead_code)]
#[derive(Debug, Copy, Serialize, Default, Deserialize, Clone)]
pub enum RefundStatus {
    Succeeded,
    Failed,
    #[default]
    Processing,
}

impl From<RefundStatus> for enums::RefundStatus {
    fn from(item: RefundStatus) -> Self {
        match item {
            RefundStatus::Succeeded => Self::Success,
            RefundStatus::Failed => Self::Failure,
            RefundStatus::Processing => Self::Pending,
            //TODO: Review mapping
        }
    }
}

//TODO: Fill the struct with respective fields
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct RefundResponse {
    id: String,
    status: RefundStatus
}

impl TryFrom<RefundsResponseRouterData<Execute, RefundResponse>>
    for RefundsRouterData<Execute>
{
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        item: RefundsResponseRouterData<Execute, RefundResponse>,
    ) -> Result<Self, Self::Error> {
        Ok(Self {
            response: Ok(RefundsResponseData {
                connector_refund_id: item.response.id.to_string(),
                refund_status: enums::RefundStatus::from(item.response.status),
            }),
            ..item.data
        })
    }
}

impl TryFrom<RefundsResponseRouterData<RSync, RefundResponse>> for RefundsRouterData<RSync>
{
     type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(item: RefundsResponseRouterData<RSync, RefundResponse>) -> Result<Self,Self::Error> {
        Ok(Self {
            response: Ok(RefundsResponseData {
                connector_refund_id: item.response.id.to_string(),
                refund_status: enums::RefundStatus::from(item.response.status),
            }),
            ..item.data
        })
     }
 }

//TODO: Fill the struct with respective fields
#[derive(Default, Debug, Serialize, Deserialize, PartialEq)]
pub struct {{project-name | downcase | pascal_case}}ErrorResponse {
    pub status_code: u16,
    pub code: String,
    pub message: String,
    pub reason: Option<String>,
    pub network_advice_code: Option<String>,
    pub network_decline_code: Option<String>,
    pub network_error_message: Option<String>,
}


impl api::PaymentAuthorize for Authipay {}

impl api::PaymentAuthorize for for Authipay


pub async fn update_by_merchant_id_payout_attempt_id(
        conn: &PgPooledConn,
        merchant_id: &common_utils::id_type::MerchantId,
        payout_attempt_id: &str,
        payout: PayoutAttemptUpdate,
    ) -> StorageResult<Self> {
        generics::generic_update_with_results::<<Self as HasTable>::Table, _, _, _>(
            conn,
            dsl::merchant_id
                .eq(merchant_id.to_owned())
                .and(dsl::payout_attempt_id.eq(payout_attempt_id.to_owned())),
            PayoutAttemptUpdateInternal::from(payout),
        )
        .await?
        .first()
        .cloned()
        .ok_or_else(|| {
            report!(DatabaseError::NotFound).attach_printable("Error while updating payout")
        })
    }


/// Get the org_id from the lineage
    pub fn org_id(&self) -> Option<&id_type::OrganizationId> {
        match self {
            Self::Tenant { .. } => None,
            Self::Organization { org_id, .. }
            | Self::Merchant { org_id, .. }
            | Self::Profile { org_id, .. } => Some(org_id),
        }
    }


impl api::RefundExecute for Razorpay {}

impl api::RefundExecute for for Razorpay


impl GetLockingInput for FPaymentsApproveRequest<'_> {
    fn get_locking_input<F>(&self, flow: F) -> api_locking::LockAction
    where
        F: types::FlowMetric,
        lock_utils::ApiIdentifier: From<F>,
    {
        api_locking::LockAction::Hold {
            input: api_locking::LockingInput {
                unique_locking_key: self.0.payment_id.get_string_repr().to_owned(),
                api_identifier: lock_utils::ApiIdentifier::from(flow),
                override_lock_retries: None,
            },
        }
    }
}

impl GetLockingInput for for FPaymentsApproveRequest


pub struct HyperwalletRefundRequest {
    pub amount: StringMinorUnit,
}


File: crates/hyperswitch_connectors/src/connectors/sift.rs
 Public functions: 1
 Public structs: 1

pub mod transformers;

use std::sync::LazyLock;

use common_enums::enums;
use common_utils::{
    errors::CustomResult,
    ext_traits::BytesExt,
    request::{Method, Request, RequestBuilder, RequestContent},
    types::{AmountConvertor, StringMinorUnit, StringMinorUnitForConnector},
};
use error_stack::{report, ResultExt};
use hyperswitch_domain_models::{
    payment_method_data::PaymentMethodData,
    router_data::{AccessToken, ConnectorAuthType, ErrorResponse, RouterData},
    router_flow_types::{
        access_token_auth::AccessTokenAuth,
        payments::{Authorize, Capture, PSync, PaymentMethodToken, Session, SetupMandate, Void},
        refunds::{Execute, RSync},
    },
    router_request_types::{
        AccessTokenRequestData, PaymentMethodTokenizationData, PaymentsAuthorizeData,
        PaymentsCancelData, PaymentsCaptureData, PaymentsSessionData, PaymentsSyncData,
        RefundsData, SetupMandateRequestData,
    },
    router_response_types::{
        ConnectorInfo, PaymentsResponseData, RefundsResponseData, SupportedPaymentMethods,
    },
    types::{
        PaymentsAuthorizeRouterData, PaymentsCaptureRouterData, PaymentsSyncRouterData,
        RefundSyncRouterData, RefundsRouterData,
    },
};
use hyperswitch_interfaces::{
    api::{
        self, ConnectorCommon, ConnectorCommonExt, ConnectorIntegration, ConnectorSpecifications,
        ConnectorValidation,
    },
    configs::Connectors,
    errors,
    events::connector_api_logs::ConnectorEvent,
    types::{self, Response},
    webhooks,
};
use masking::{ExposeInterface, Mask};
use transformers as sift;

use crate::{constants::headers, types::ResponseRouterData, utils};

#[derive(Clone)]
pub struct Sift {
    amount_converter: &'static (dyn AmountConvertor<Output = StringMinorUnit> + Sync),
}

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

impl api::Payment for Sift {}
impl api::PaymentSession for Sift {}
impl api::ConnectorAccessToken for Sift {}
impl api::MandateSetup for Sift {}
impl api::PaymentAuthorize for Sift {}
impl api::PaymentSync for Sift {}
impl api::PaymentCapture for Sift {}
impl api::PaymentVoid for Sift {}
impl api::Refund for Sift {}
impl api::RefundExecute for Sift {}
impl api::RefundSync for Sift {}
impl api::PaymentToken for Sift {}

impl ConnectorIntegration<PaymentMethodToken, PaymentMethodTokenizationData, PaymentsResponseData>
    for Sift
{
    // Not Implemented (R)
}

impl<Flow, Request, Response> ConnectorCommonExt<Flow, Request, Response> for Sift
where
    Self: ConnectorIntegration<Flow, Request, Response>,
{
    fn build_headers(
        &self,
        req: &RouterData<Flow, Request, Response>,
        _connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        let mut header = vec![(
            headers::CONTENT_TYPE.to_string(),
            self.get_content_type().to_string().into(),
        )];
        let mut api_key = self.get_auth_header(&req.connector_auth_type)?;
        header.append(&mut api_key);
        Ok(header)
    }
}

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

    fn get_currency_unit(&self) -> api::CurrencyUnit {
        api::CurrencyUnit::Minor
        //    TODO! Check connector documentation, on which unit they are processing the currency.
        //    If the connector accepts amount in lower unit ( i.e cents for USD) then return api::CurrencyUnit::Minor,
        //    if connector accepts amount in base unit (i.e dollars for USD) then return api::CurrencyUnit::Base
    }

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

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

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

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

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

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

impl ConnectorValidation for Sift {
    fn validate_mandate_payment(
        &self,
        _pm_type: Option<enums::PaymentMethodType>,
        pm_data: PaymentMethodData,
    ) -> CustomResult<(), errors::ConnectorError> {
        match pm_data {
            PaymentMethodData::Card(_) => Err(errors::ConnectorError::NotImplemented(
                "validate_mandate_payment does not support cards".to_string(),
            )
            .into()),
            _ => Ok(()),
        }
    }

    fn validate_psync_reference_id(
        &self,
        _data: &PaymentsSyncData,
        _is_three_ds: bool,
        _status: enums::AttemptStatus,
        _connector_meta_data: Option<common_utils::pii::SecretSerdeValue>,
    ) -> CustomResult<(), errors::ConnectorError> {
        Ok(())
    }
}

impl ConnectorIntegration<Session, PaymentsSessionData, PaymentsResponseData> for Sift {
    //TODO: implement sessions flow
}

impl ConnectorIntegration<AccessTokenAuth, AccessTokenRequestData, AccessToken> for Sift {}

impl ConnectorIntegration<SetupMandate, SetupMandateRequestData, PaymentsResponseData> for Sift {}

impl ConnectorIntegration<Authorize, PaymentsAuthorizeData, PaymentsResponseData> for Sift {
    fn get_headers(
        &self,
        req: &PaymentsAuthorizeRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        self.build_headers(req, connectors)
    }

    fn get_content_type(&self) -> &'static str {
        self.common_get_content_type()
    }

    fn get_url(
        &self,
        _req: &PaymentsAuthorizeRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into())
    }

    fn get_request_body(
        &self,
        req: &PaymentsAuthorizeRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let amount = utils::convert_amount(
            self.amount_converter,
            req.request.minor_amount,
            req.request.currency,
        )?;

        let connector_router_data = sift::SiftRouterData::from((amount, req));
        let connector_req = sift::SiftPaymentsRequest::try_from(&connector_router_data)?;
        Ok(RequestContent::Json(Box::new(connector_req)))
    }

    fn build_request(
        &self,
        req: &PaymentsAuthorizeRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        Ok(Some(
            RequestBuilder::new()
                .method(Method::Post)
                .url(&types::PaymentsAuthorizeType::get_url(
                    self, req, connectors,
                )?)
                .attach_default_headers()
                .headers(types::PaymentsAuthorizeType::get_headers(
                    self, req, connectors,
                )?)
                .set_body(types::PaymentsAuthorizeType::get_request_body(
                    self, req, connectors,
                )?)
                .build(),
        ))
    }

    fn handle_response(
        &self,
        data: &PaymentsAuthorizeRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<PaymentsAuthorizeRouterData, errors::ConnectorError> {
        let response: sift::SiftPaymentsResponse = res
            .response
            .parse_struct("Sift PaymentsAuthorizeResponse")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
        event_builder.map(|i| i.set_response_body(&response));
        router_env::logger::info!(connector_response=?response);
        RouterData::try_from(ResponseRouterData {
            response,
            data: data.clone(),
            http_code: res.status_code,
        })
    }

    fn get_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        self.build_error_response(res, event_builder)
    }
}

impl ConnectorIntegration<PSync, PaymentsSyncData, PaymentsResponseData> for Sift {
    fn get_headers(
        &self,
        req: &PaymentsSyncRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        self.build_headers(req, connectors)
    }

    fn get_content_type(&self) -> &'static str {
        self.common_get_content_type()
    }

    fn get_url(
        &self,
        _req: &PaymentsSyncRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into())
    }

    fn build_request(
        &self,
        req: &PaymentsSyncRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        Ok(Some(
            RequestBuilder::new()
                .method(Method::Get)
                .url(&types::PaymentsSyncType::get_url(self, req, connectors)?)
                .attach_default_headers()
                .headers(types::PaymentsSyncType::get_headers(self, req, connectors)?)
                .build(),
        ))
    }

    fn handle_response(
        &self,
        data: &PaymentsSyncRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<PaymentsSyncRouterData, errors::ConnectorError> {
        let response: sift::SiftPaymentsResponse = res
            .response
            .parse_struct("sift PaymentsSyncResponse")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
        event_builder.map(|i| i.set_response_body(&response));
        router_env::logger::info!(connector_response=?response);
        RouterData::try_from(ResponseRouterData {
            response,
            data: data.clone(),
            http_code: res.status_code,
        })
    }

    fn get_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        self.build_error_response(res, event_builder)
    }
}

impl ConnectorIntegration<Capture, PaymentsCaptureData, PaymentsResponseData> for Sift {
    fn get_headers(
        &self,
        req: &PaymentsCaptureRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        self.build_headers(req, connectors)
    }

    fn get_content_type(&self) -> &'static str {
        self.common_get_content_type()
    }

    fn get_url(
        &self,
        _req: &PaymentsCaptureRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into())
    }

    fn get_request_body(
        &self,
        _req: &PaymentsCaptureRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        Err(errors::ConnectorError::NotImplemented("get_request_body method".to_string()).into())
    }

    fn build_request(
        &self,
        req: &PaymentsCaptureRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        Ok(Some(
            RequestBuilder::new()
                .method(Method::Post)
                .url(&types::PaymentsCaptureType::get_url(self, req, connectors)?)
                .attach_default_headers()
                .headers(types::PaymentsCaptureType::get_headers(
                    self, req, connectors,
                )?)
                .set_body(types::PaymentsCaptureType::get_request_body(
                    self, req, connectors,
                )?)
                .build(),
        ))
    }

    fn handle_response(
        &self,
        data: &PaymentsCaptureRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<PaymentsCaptureRouterData, errors::ConnectorError> {
        let response: sift::SiftPaymentsResponse = res
            .response
            .parse_struct("Sift PaymentsCaptureResponse")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
        event_builder.map(|i| i.set_response_body(&response));
        router_env::logger::info!(connector_response=?response);
        RouterData::try_from(ResponseRouterData {
            response,
            data: data.clone(),
            http_code: res.status_code,
        })
    }

    fn get_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        self.build_error_response(res, event_builder)
    }
}

impl ConnectorIntegration<Void, PaymentsCancelData, PaymentsResponseData> for Sift {}

impl ConnectorIntegration<Execute, RefundsData, RefundsResponseData> for Sift {
    fn get_headers(
        &self,
        req: &RefundsRouterData<Execute>,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        self.build_headers(req, connectors)
    }

    fn get_content_type(&self) -> &'static str {
        self.common_get_content_type()
    }

    fn get_url(
        &self,
        _req: &RefundsRouterData<Execute>,
        _connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into())
    }

    fn get_request_body(
        &self,
        req: &RefundsRouterData<Execute>,
        _connectors: &Connectors,
    ) -> CustomResult<RequestContent, errors::ConnectorError> {
        let refund_amount = utils::convert_amount(
            self.amount_converter,
            req.request.minor_refund_amount,
            req.request.currency,
        )?;

        let connector_router_data = sift::SiftRouterData::from((refund_amount, req));
        let connector_req = sift::SiftRefundRequest::try_from(&connector_router_data)?;
        Ok(RequestContent::Json(Box::new(connector_req)))
    }

    fn build_request(
        &self,
        req: &RefundsRouterData<Execute>,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        let request = RequestBuilder::new()
            .method(Method::Post)
            .url(&types::RefundExecuteType::get_url(self, req, connectors)?)
            .attach_default_headers()
            .headers(types::RefundExecuteType::get_headers(
                self, req, connectors,
            )?)
            .set_body(types::RefundExecuteType::get_request_body(
                self, req, connectors,
            )?)
            .build();
        Ok(Some(request))
    }

    fn handle_response(
        &self,
        data: &RefundsRouterData<Execute>,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<RefundsRouterData<Execute>, errors::ConnectorError> {
        let response: sift::RefundResponse = res
            .response
            .parse_struct("sift RefundResponse")
            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
        event_builder.map(|i| i.set_response_body(&response));
        router_env::logger::info!(connector_response=?response);
        RouterData::try_from(ResponseRouterData {
            response,
            data: data.clone(),
            http_code: res.status_code,
        })
    }

    fn get_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        self.build_error_response(res, event_builder)
    }
}

impl ConnectorIntegration<RSync, RefundsData, RefundsResponseData> for Sift {
    fn get_headers(
        &self,
        req: &RefundSyncRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
        self.build_headers(req, connectors)
    }

    fn get_content_type(&self) -> &'static str {
        self.common_get_content_type()
    }

    fn get_url(
        &self,
        _req: &RefundSyncRouterData,
        _connectors: &Connectors,
    ) -> CustomResult<String, errors::ConnectorError> {
        Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into())
    }

    fn build_request(
        &self,
        req: &RefundSyncRouterData,
        connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError> {
        Ok(Some(
            RequestBuilder::new()
                .method(Method::Get)
                .url(&types::RefundSyncType::get_url(self, req, connectors)?)
                .attach_default_headers()
                .headers(types::RefundSyncType::get_headers(self, req, connectors)?)
                .set_body(types::RefundSyncType::get_request_body(
                    self, req, connectors,
                )?)
                .build(),
        ))
    }

    fn handle_response(
        &self,
        data: &RefundSyncRouterData,
        event_builder: Option<&mut ConnectorEvent>,
        res: Response,
    ) -> CustomResult<RefundSyncRouterData, errors::ConnectorError> {
        let response: sift::RefundResponse =
            res.response
                .parse_struct("sift RefundSyncResponse")
                .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
        event_builder.map(|i| i.set_response_body(&response));
        router_env::logger::info!(connector_response=?response);
        RouterData::try_from(ResponseRouterData {
            response,
            data: data.clone(),
            http_code: res.status_code,
        })
    }

    fn get_error_response(
        &self,
        res: Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError> {
        self.build_error_response(res, event_builder)
    }
}

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

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

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

static SIFT_SUPPORTED_PAYMENT_METHODS: LazyLock<SupportedPaymentMethods> =
    LazyLock::new(SupportedPaymentMethods::new);

static SIFT_CONNECTOR_INFO: ConnectorInfo = ConnectorInfo {
    display_name: "Sift",
    description: "Sift connector",
    connector_type: enums::HyperswitchConnectorCategory::PaymentGateway,
    integration_status: common_enums::ConnectorIntegrationStatus::Alpha,
};

static SIFT_SUPPORTED_WEBHOOK_FLOWS: [enums::EventClass; 0] = [];

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

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

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


impl Deref for ShouldCollectCvvDuringPayment {
        type Target = bool;

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

impl Deref for for ShouldCollectCvvDuringPayment


pub struct BlocklistNew {
    pub merchant_id: common_utils::id_type::MerchantId,
    pub fingerprint_id: String,
    pub data_kind: common_enums::BlocklistDataKind,
    pub metadata: Option<serde_json::Value>,
    pub created_at: time::PrimitiveDateTime,
}


pub struct DeleteTokenDataRequest {
    /// Customer ID for which the tokenization is requested
    #[schema(value_type = String, example = "12345_cus_01926c58bc6e77c09e809964e72af8c8")]
    pub customer_id: id_type::GlobalCustomerId,
    /// Session ID associated with the tokenization request
    #[schema(value_type = String, example = "12345_pms_01926c58bc6e77c09e809964e72af8c8")]
    pub session_id: id_type::GlobalPaymentMethodSessionId,
}


/// Get string representation of the id
    pub fn get_string_repr(&self) -> &str {
        self.0.get_string_repr()
    }


OpenAPI Block Path: components.schemas.CardNetwork
{
  "type": "string",
  "description": "Indicates the card network.",
  "enum": [
    "Visa",
    "Mastercard",
    "AmericanExpress",
    "JCB",
    "DinersClub",
    "Discover",
    "CartesBancaires",
    "UnionPay",
    "Interac",
    "RuPay",
    "Maestro",
    "Star",
    "Pulse",
    "Accel",
    "Nyce"
  ]
}


File: crates/analytics/src/disputes/metrics/dispute_status_metric.rs

use std::collections::HashSet;

use api_models::analytics::{
    disputes::{DisputeDimensions, DisputeFilters, DisputeMetricsBucketIdentifier},
    Granularity, TimeRange,
};
use common_utils::errors::ReportSwitchExt;
use error_stack::ResultExt;
use time::PrimitiveDateTime;

use super::DisputeMetricRow;
use crate::{
    enums::AuthInfo,
    query::{Aggregate, GroupByClause, QueryBuilder, QueryFilter, SeriesBucket, ToSql, Window},
    types::{AnalyticsCollection, AnalyticsDataSource, MetricsError, MetricsResult},
};
#[derive(Default)]
pub(super) struct DisputeStatusMetric {}

#[async_trait::async_trait]
impl<T> super::DisputeMetric<T> for DisputeStatusMetric
where
    T: AnalyticsDataSource + super::DisputeMetricAnalytics,
    PrimitiveDateTime: ToSql<T>,
    AnalyticsCollection: ToSql<T>,
    Granularity: GroupByClause<T>,
    Aggregate<&'static str>: ToSql<T>,
    Window<&'static str>: ToSql<T>,
{
    async fn load_metrics(
        &self,
        dimensions: &[DisputeDimensions],
        auth: &AuthInfo,
        filters: &DisputeFilters,
        granularity: Option<Granularity>,
        time_range: &TimeRange,
        pool: &T,
    ) -> MetricsResult<HashSet<(DisputeMetricsBucketIdentifier, DisputeMetricRow)>>
    where
        T: AnalyticsDataSource + super::DisputeMetricAnalytics,
    {
        let mut query_builder = QueryBuilder::new(AnalyticsCollection::Dispute);

        for dim in dimensions {
            query_builder.add_select_column(dim).switch()?;
        }

        query_builder.add_select_column("dispute_status").switch()?;

        query_builder
            .add_select_column(Aggregate::Count {
                field: None,
                alias: Some("count"),
            })
            .switch()?;
        query_builder
            .add_select_column(Aggregate::Min {
                field: "created_at",
                alias: Some("start_bucket"),
            })
            .switch()?;
        query_builder
            .add_select_column(Aggregate::Max {
                field: "created_at",
                alias: Some("end_bucket"),
            })
            .switch()?;

        filters.set_filter_clause(&mut query_builder).switch()?;

        auth.set_filter_clause(&mut query_builder).switch()?;

        time_range.set_filter_clause(&mut query_builder).switch()?;

        for dim in dimensions {
            query_builder.add_group_by_clause(dim).switch()?;
        }

        query_builder
            .add_group_by_clause("dispute_status")
            .switch()?;

        if let Some(granularity) = granularity {
            granularity
                .set_group_by_clause(&mut query_builder)
                .switch()?;
        }

        query_builder
            .execute_query::<DisputeMetricRow, _>(pool)
            .await
            .change_context(MetricsError::QueryBuildingError)?
            .change_context(MetricsError::QueryExecutionFailure)?
            .into_iter()
            .map(|i| {
                Ok((
                    DisputeMetricsBucketIdentifier::new(
                        i.dispute_stage.as_ref().map(|i| i.0),
                        i.connector.clone(),
                        i.currency.as_ref().map(|i| i.0),
                        TimeRange {
                            start_time: match (granularity, i.start_bucket) {
                                (Some(g), Some(st)) => g.clip_to_start(st)?,
                                _ => time_range.start_time,
                            },
                            end_time: granularity.as_ref().map_or_else(
                                || Ok(time_range.end_time),
                                |g| i.end_bucket.map(|et| g.clip_to_end(et)).transpose(),
                            )?,
                        },
                    ),
                    i,
                ))
            })
            .collect::<error_stack::Result<
                HashSet<(DisputeMetricsBucketIdentifier, DisputeMetricRow)>,
                crate::query::PostProcessingError,
            >>()
            .change_context(MetricsError::PostProcessingFailure)
    }
}


pub struct VersionData {
    #[serde(rename = "@Ds_Version")]
    ds_version: String,
    #[serde(rename = "Message")]
    message: Message,
}


pub struct GooglePayTokenPaymentInformation {
    fluid_data: FluidData,
    tokenized_card: GooglePayTokenizedCard,
}


impl api::PaymentVoid for Airwallex {}


impl api::PaymentCapture for Xendit {}


File: crates/router/src/core/payments/flows/psync_flow.rs

use std::{collections::HashMap, str::FromStr};

use async_trait::async_trait;
use error_stack::ResultExt;
use masking::Secret;
use unified_connector_service_client::payments as payments_grpc;

use super::{ConstructFlowSpecificData, Feature};
use crate::{
    connector::utils::RouterData,
    core::{
        errors::{ApiErrorResponse, ConnectorErrorExt, RouterResult},
        payments::{self, access_token, helpers, transformers, PaymentData},
        unified_connector_service::{
            build_unified_connector_service_auth_metadata,
            handle_unified_connector_service_response_for_payment_get, ucs_logging_wrapper,
        },
    },
    routes::SessionState,
    services::{self, api::ConnectorValidation, logger},
    types::{self, api, domain, transformers::ForeignTryFrom},
};

#[cfg(feature = "v1")]
#[async_trait]
impl ConstructFlowSpecificData<api::PSync, types::PaymentsSyncData, types::PaymentsResponseData>
    for PaymentData<api::PSync>
{
    async fn construct_router_data<'a>(
        &self,
        state: &SessionState,
        connector_id: &str,
        merchant_context: &domain::MerchantContext,
        customer: &Option<domain::Customer>,
        merchant_connector_account: &helpers::MerchantConnectorAccountType,
        merchant_recipient_data: Option<types::MerchantRecipientData>,
        header_payload: Option<hyperswitch_domain_models::payments::HeaderPayload>,
    ) -> RouterResult<
        types::RouterData<api::PSync, types::PaymentsSyncData, types::PaymentsResponseData>,
    > {
        Box::pin(transformers::construct_payment_router_data::<
            api::PSync,
            types::PaymentsSyncData,
        >(
            state,
            self.clone(),
            connector_id,
            merchant_context,
            customer,
            merchant_connector_account,
            merchant_recipient_data,
            header_payload,
        ))
        .await
    }
}

#[cfg(feature = "v2")]
#[async_trait]
impl ConstructFlowSpecificData<api::PSync, types::PaymentsSyncData, types::PaymentsResponseData>
    for hyperswitch_domain_models::payments::PaymentStatusData<api::PSync>
{
    async fn construct_router_data<'a>(
        &self,
        state: &SessionState,
        connector_id: &str,
        merchant_context: &domain::MerchantContext,
        customer: &Option<domain::Customer>,
        merchant_connector_account: &domain::MerchantConnectorAccountTypeDetails,
        merchant_recipient_data: Option<types::MerchantRecipientData>,
        header_payload: Option<hyperswitch_domain_models::payments::HeaderPayload>,
    ) -> RouterResult<
        types::RouterData<api::PSync, types::PaymentsSyncData, types::PaymentsResponseData>,
    > {
        Box::pin(transformers::construct_router_data_for_psync(
            state,
            self.clone(),
            connector_id,
            merchant_context,
            customer,
            merchant_connector_account,
            merchant_recipient_data,
            header_payload,
        ))
        .await
    }
}

#[async_trait]
impl Feature<api::PSync, types::PaymentsSyncData>
    for types::RouterData<api::PSync, types::PaymentsSyncData, types::PaymentsResponseData>
{
    async fn decide_flows<'a>(
        mut self,
        state: &SessionState,
        connector: &api::ConnectorData,
        call_connector_action: payments::CallConnectorAction,
        connector_request: Option<services::Request>,
        _business_profile: &domain::Profile,
        _header_payload: hyperswitch_domain_models::payments::HeaderPayload,
        return_raw_connector_response: Option<bool>,
    ) -> RouterResult<Self> {
        let connector_integration: services::BoxedPaymentConnectorIntegrationInterface<
            api::PSync,
            types::PaymentsSyncData,
            types::PaymentsResponseData,
        > = connector.connector.get_connector_integration();

        let capture_sync_method_result = connector_integration
            .get_multiple_capture_sync_method()
            .to_payment_failed_response();

        match (self.request.sync_type.clone(), capture_sync_method_result) {
            (
                types::SyncRequestType::MultipleCaptureSync(pending_connector_capture_id_list),
                Ok(services::CaptureSyncMethod::Individual),
            ) => {
                let mut new_router_data = self
                    .execute_connector_processing_step_for_each_capture(
                        state,
                        pending_connector_capture_id_list,
                        call_connector_action,
                        connector_integration,
                        return_raw_connector_response,
                    )
                    .await?;
                // Initiating Integrity checks
                let integrity_result = helpers::check_integrity_based_on_flow(
                    &new_router_data.request,
                    &new_router_data.response,
                );

                new_router_data.integrity_check = integrity_result;

                Ok(new_router_data)
            }
            (types::SyncRequestType::MultipleCaptureSync(_), Err(err)) => Err(err),
            _ => {
                // for bulk sync of captures, above logic needs to be handled at connector end
                let mut new_router_data = services::execute_connector_processing_step(
                    state,
                    connector_integration,
                    &self,
                    call_connector_action,
                    connector_request,
                    return_raw_connector_response,
                )
                .await
                .to_payment_failed_response()?;

                // Initiating Integrity checks
                let integrity_result = helpers::check_integrity_based_on_flow(
                    &new_router_data.request,
                    &new_router_data.response,
                );

                new_router_data.integrity_check = integrity_result;

                Ok(new_router_data)
            }
        }
    }

    async fn add_access_token<'a>(
        &self,
        state: &SessionState,
        connector: &api::ConnectorData,
        merchant_context: &domain::MerchantContext,
        creds_identifier: Option<&str>,
    ) -> RouterResult<types::AddAccessTokenResult> {
        Box::pin(access_token::add_access_token(
            state,
            connector,
            merchant_context,
            self,
            creds_identifier,
        ))
        .await
    }

    async fn build_flow_specific_connector_request(
        &mut self,
        state: &SessionState,
        connector: &api::ConnectorData,
        call_connector_action: payments::CallConnectorAction,
    ) -> RouterResult<(Option<services::Request>, bool)> {
        let request = match call_connector_action {
            payments::CallConnectorAction::Trigger => {
                //validate_psync_reference_id if call_connector_action is trigger
                if connector
                    .connector
                    .validate_psync_reference_id(
                        &self.request,
                        self.is_three_ds(),
                        self.status,
                        self.connector_meta_data.clone(),
                    )
                    .is_err()
                {
                    logger::warn!(
                        "validate_psync_reference_id failed, hence skipping call to connector"
                    );
                    return Ok((None, false));
                }
                let connector_integration: services::BoxedPaymentConnectorIntegrationInterface<
                    api::PSync,
                    types::PaymentsSyncData,
                    types::PaymentsResponseData,
                > = connector.connector.get_connector_integration();

                connector_integration
                    .build_request(self, &state.conf.connectors)
                    .to_payment_failed_response()?
            }
            _ => None,
        };

        Ok((request, true))
    }

    async fn call_unified_connector_service<'a>(
        &mut self,
        state: &SessionState,
        #[cfg(feature = "v1")] merchant_connector_account: helpers::MerchantConnectorAccountType,
        #[cfg(feature = "v2")]
        merchant_connector_account: domain::MerchantConnectorAccountTypeDetails,
        merchant_context: &domain::MerchantContext,
    ) -> RouterResult<()> {
        let connector_name = self.connector.clone();
        let connector_enum = common_enums::connector_enums::Connector::from_str(&connector_name)
            .change_context(ApiErrorResponse::IncorrectConnectorNameGiven)?;

        let is_ucs_psync_disabled = state
            .conf
            .grpc_client
            .unified_connector_service
            .as_ref()
            .is_some_and(|config| {
                config
                    .ucs_psync_disabled_connectors
                    .contains(&connector_enum)
            });

        if is_ucs_psync_disabled {
            logger::info!(
                "UCS PSync call disabled for connector: {}, skipping UCS call",
                connector_name
            );
            return Ok(());
        }

        let client = state
            .grpc_client
            .unified_connector_service_client
            .clone()
            .ok_or(ApiErrorResponse::InternalServerError)
            .attach_printable("Failed to fetch Unified Connector Service client")?;

        let payment_get_request = payments_grpc::PaymentServiceGetRequest::foreign_try_from(&*self)
            .change_context(ApiErrorResponse::InternalServerError)
            .attach_printable("Failed to construct Payment Get Request")?;

        let connector_auth_metadata = build_unified_connector_service_auth_metadata(
            merchant_connector_account,
            merchant_context,
        )
        .change_context(ApiErrorResponse::InternalServerError)
        .attach_printable("Failed to construct request metadata")?;

        let updated_router_data = Box::pin(ucs_logging_wrapper(
            self.clone(),
            state,
            payment_get_request,
            |mut router_data, payment_get_request| async move {
                let response = client
                    .payment_get(
                        payment_get_request,
                        connector_auth_metadata,
                        state.get_grpc_headers(),
                    )
                    .await
                    .change_context(ApiErrorResponse::InternalServerError)
                    .attach_printable("Failed to get payment")?;

                let payment_get_response = response.into_inner();

                let (status, router_data_response, status_code) =
                    handle_unified_connector_service_response_for_payment_get(
                        payment_get_response.clone(),
                    )
                    .change_context(ApiErrorResponse::InternalServerError)
                    .attach_printable("Failed to deserialize UCS response")?;

                router_data.status = status;
                router_data.response = router_data_response;
                router_data.raw_connector_response = payment_get_response
                    .raw_connector_response
                    .clone()
                    .map(Secret::new);
                router_data.connector_http_status_code = Some(status_code);

                Ok((router_data, payment_get_response))
            },
        ))
        .await?;

        // Copy back the updated data
        *self = updated_router_data;
        Ok(())
    }
}

#[async_trait]
pub trait RouterDataPSync
where
    Self: Sized,
{
    async fn execute_connector_processing_step_for_each_capture(
        &self,
        _state: &SessionState,
        _pending_connector_capture_id_list: Vec<String>,
        _call_connector_action: payments::CallConnectorAction,
        _connector_integration: services::BoxedPaymentConnectorIntegrationInterface<
            api::PSync,
            types::PaymentsSyncData,
            types::PaymentsResponseData,
        >,
        _return_raw_connector_response: Option<bool>,
    ) -> RouterResult<Self>;
}

#[async_trait]
impl RouterDataPSync
    for types::RouterData<api::PSync, types::PaymentsSyncData, types::PaymentsResponseData>
{
    async fn execute_connector_processing_step_for_each_capture(
        &self,
        state: &SessionState,
        pending_connector_capture_id_list: Vec<String>,
        call_connector_action: payments::CallConnectorAction,
        connector_integration: services::BoxedPaymentConnectorIntegrationInterface<
            api::PSync,
            types::PaymentsSyncData,
            types::PaymentsResponseData,
        >,
        return_raw_connector_response: Option<bool>,
    ) -> RouterResult<Self> {
        let mut capture_sync_response_map = HashMap::new();
        if let payments::CallConnectorAction::HandleResponse(_) = call_connector_action {
            // webhook consume flow, only call connector once. Since there will only be a single event in every webhook
            let resp = services::execute_connector_processing_step(
                state,
                connector_integration,
                self,
                call_connector_action.clone(),
                None,
                return_raw_connector_response,
            )
            .await
            .to_payment_failed_response()?;
            Ok(resp)
        } else {
            // in trigger, call connector for every capture_id
            for connector_capture_id in pending_connector_capture_id_list {
                // TEMPORARY FIX: remove the clone on router data after removing this function as an impl on trait RouterDataPSync
                // TRACKING ISSUE: https://github.com/juspay/hyperswitch/issues/4644
                let mut cloned_router_data = self.clone();
                cloned_router_data.request.connector_transaction_id =
                    types::ResponseId::ConnectorTransactionId(connector_capture_id.clone());
                let resp = services::execute_connector_processing_step(
                    state,
                    connector_integration.clone_box(),
                    &cloned_router_data,
                    call_connector_action.clone(),
                    None,
                    return_raw_connector_response,
                )
                .await
                .to_payment_failed_response()?;
                match resp.response {
                    Err(err) => {
                        capture_sync_response_map.insert(connector_capture_id, types::CaptureSyncResponse::Error {
                            code: err.code,
                            message: err.message,
                            reason: err.reason,
                            status_code: err.status_code,
                            amount: None,
                        });
                    },
                    Ok(types::PaymentsResponseData::MultipleCaptureResponse { capture_sync_response_list })=> {
                        capture_sync_response_map.extend(capture_sync_response_list.into_iter());
                    }
                    _ => Err(ApiErrorResponse::PreconditionFailed { message: "Response type must be PaymentsResponseData::MultipleCaptureResponse for payment sync".into() })?,
                };
            }
            let mut cloned_router_data = self.clone();
            cloned_router_data.response =
                Ok(types::PaymentsResponseData::MultipleCaptureResponse {
                    capture_sync_response_list: capture_sync_response_map,
                });
            Ok(cloned_router_data)
        }
    }
}


impl<'a> CardInfoMigrateExecutor<'a> {
    fn new(
        state: &'a routes::SessionState,
        record: &'a cards_info_api_types::CardInfoUpdateRequest,
    ) -> Self {
        Self { state, record }
    }

    async fn fetch_card_info(&self) -> RouterResult<Option<card_info_models::CardInfo>> {
        let db = self.state.store.as_ref();
        let maybe_card_info = db
            .get_card_info(&self.record.card_iin)
            .await
            .change_context(errors::ApiErrorResponse::InvalidCardIin)?;
        Ok(maybe_card_info)
    }

    async fn add_card_info(&self) -> RouterResult<card_info_models::CardInfo> {
        let db = self.state.store.as_ref();
        let card_info =
            cards_info::CardsInfoInterface::add_card_info(db, self.record.clone().foreign_into())
                .await
                .to_duplicate_response(errors::ApiErrorResponse::GenericDuplicateError {
                    message: "CardInfo with given key already exists in our records".to_string(),
                })?;
        Ok(card_info)
    }

    async fn update_card_info(&self) -> RouterResult<card_info_models::CardInfo> {
        let db = self.state.store.as_ref();
        let card_info = cards_info::CardsInfoInterface::update_card_info(
            db,
            self.record.card_iin.clone(),
            card_info_models::UpdateCardInfo {
                card_issuer: self.record.card_issuer.clone(),
                card_network: self.record.card_network.clone(),
                card_type: self.record.card_type.clone(),
                card_subtype: self.record.card_subtype.clone(),
                card_issuing_country: self.record.card_issuing_country.clone(),
                bank_code_id: self.record.bank_code_id.clone(),
                bank_code: self.record.bank_code.clone(),
                country_code: self.record.country_code.clone(),
                last_updated: Some(common_utils::date_time::now()),
                last_updated_provider: self.record.last_updated_provider.clone(),
            },
        )
        .await
        .to_not_found_response(errors::ApiErrorResponse::GenericNotFoundError {
            message: "Card info with given key does not exist in our records".to_string(),
        })
        .attach_printable("Failed while updating card info")?;
        Ok(card_info)
    }
}


pub struct ApplePayCertificatesMigrationRequest {
    pub merchant_ids: Vec<common_utils::id_type::MerchantId>,
}


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


impl api::RefundExecute for Worldline {}

impl api::RefundExecute for for Worldline


pub trait ActivePaymentsMetric<T>
where
    T: AnalyticsDataSource + ActivePaymentsMetricAnalytics,
{
    async fn load_metrics(
        &self,
        merchant_id: &common_utils::id_type::MerchantId,
        publishable_key: &str,
        time_range: &TimeRange,
        pool: &T,
    ) -> MetricsResult<
        HashSet<(
            ActivePaymentsMetricsBucketIdentifier,
            ActivePaymentsMetricRow,
        )>,
    >;
}


/// Trait representing the connector integration interface
///
/// This trait defines the methods required for a connector integration interface.
pub trait ConnectorIntegrationInterface<F, ResourceCommonData, Req, Resp>: Send + Sync {
    /// Clone the connector integration interface
    ///
    /// # Returns
    ///
    /// A `Box` containing the cloned connector integration interface
    fn clone_box(
        &self,
    ) -> Box<dyn ConnectorIntegrationInterface<F, ResourceCommonData, Req, Resp> + Send + Sync>;
    /// Get the multiple capture sync method
    ///
    /// # Returns
    ///
    /// A `CustomResult` containing the `CaptureSyncMethod` or a `ConnectorError`
    fn get_multiple_capture_sync_method(
        &self,
    ) -> CustomResult<CaptureSyncMethod, errors::ConnectorError>;
    /// Build a request for the connector integration
    ///
    /// # Arguments
    ///
    /// * `req` - A reference to the RouterData
    /// # Returns
    ///
    /// A `CustomResult` containing an optional Request or a ConnectorError
    fn build_request(
        &self,
        req: &RouterData<F, Req, Resp>,
        _connectors: &Connectors,
    ) -> CustomResult<Option<Request>, errors::ConnectorError>;
    /// handles response from the connector
    fn handle_response(
        &self,
        data: &RouterData<F, Req, Resp>,
        event_builder: Option<&mut ConnectorEvent>,
        _res: types::Response,
    ) -> CustomResult<RouterData<F, Req, Resp>, errors::ConnectorError>
    where
        F: Clone,
        Req: Clone,
        Resp: Clone;
    /// Get the error response
    ///
    /// # Arguments
    ///
    /// * `res` - The response
    /// * `event_builder` - An optional event builder
    ///
    /// # Returns
    ///
    /// A `CustomResult` containing the `ErrorResponse` or a `ConnectorError`
    fn get_error_response(
        &self,
        res: types::Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError>;
    /// Get the 5xx error response
    ///
    /// # Arguments
    ///
    /// * `res` - The response
    /// * `event_builder` - An optional event builder
    ///
    /// # Returns
    ///
    /// A `CustomResult` containing the `ErrorResponse` or a `ConnectorError`
    fn get_5xx_error_response(
        &self,
        res: types::Response,
        event_builder: Option<&mut ConnectorEvent>,
    ) -> CustomResult<ErrorResponse, errors::ConnectorError>;
}


pub(crate) fn generate_event_id() -> String {
    common_utils::generate_time_ordered_id("evt")
}


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


pub struct ConnectorOnboarding;


pub struct DigitalvirgoConsentStatus {
    required: Option<bool>,
}


pub struct RefundDistributionRow {
    pub currency: Option<DBEnumWrapper<storage_enums::Currency>>,
    pub refund_status: Option<DBEnumWrapper<storage_enums::RefundStatus>>,
    pub connector: Option<String>,
    pub refund_type: Option<DBEnumWrapper<RefundType>>,
    pub profile_id: Option<String>,
    pub total: Option<bigdecimal::BigDecimal>,
    pub count: Option<i64>,
    pub refund_reason: Option<String>,
    pub refund_error_message: Option<String>,
    #[serde(with = "common_utils::custom_serde::iso8601::option")]
    pub start_bucket: Option<PrimitiveDateTime>,
    #[serde(with = "common_utils::custom_serde::iso8601::option")]
    pub end_bucket: Option<PrimitiveDateTime>,
}


pub async fn execute_card_tokenization(
    executor: tokenize::CardNetworkTokenizeExecutor<'_, domain::TokenizeCardRequest>,
    builder: tokenize::NetworkTokenizationBuilder<'_, tokenize::TokenizeWithCard>,
    req: &domain::TokenizeCardRequest,
) -> errors::RouterResult<api::CardNetworkTokenizeResponse> {
    // Validate request and get optional customer
    let optional_customer = executor
        .validate_request_and_fetch_optional_customer()
        .await?;
    let builder = builder.set_validate_result();

    // Perform BIN lookup and validate card network
    let optional_card_info = executor
        .fetch_bin_details_and_validate_card_network(
            req.raw_card_number.clone(),
            req.card_issuer.as_ref(),
            req.card_network.as_ref(),
            req.card_type.as_ref(),
            req.card_issuing_country.as_ref(),
        )
        .await?;
    let builder = builder.set_card_details(req, optional_card_info);

    // Create customer if not present
    let customer = match optional_customer {
        Some(customer) => customer,
        None => executor.create_customer().await?,
    };
    let builder = builder.set_customer(&customer);

    // Tokenize card
    let (optional_card, optional_cvc) = builder.get_optional_card_and_cvc();
    let domain_card = optional_card
        .get_required_value("card")
        .change_context(errors::ApiErrorResponse::InternalServerError)?;
    let network_token_details = executor
        .tokenize_card(&customer.id, &domain_card, optional_cvc)
        .await?;
    let builder = builder.set_token_details(&network_token_details);

    // Store card and token in locker
    let store_card_and_token_resp = executor
        .store_card_and_token_in_locker(&network_token_details, &domain_card, &customer.id)
        .await?;
    let builder = builder.set_stored_card_response(&store_card_and_token_resp);
    let builder = builder.set_stored_token_response(&store_card_and_token_resp);

    // Create payment method
    let payment_method = executor
        .create_payment_method(
            &store_card_and_token_resp,
            &network_token_details,
            &domain_card,
            &customer.id,
        )
        .await?;
    let builder = builder.set_payment_method_response(&payment_method);

    Ok(builder.build())
}


pub struct ArchipelRefundOrder {
    pub amount: MinorUnit,
    pub currency: Currency,
}


pub struct BreadpayPaymentsResponse {
    url: url::Url,
}


pub struct OrderDetailsWithAmount {
    /// Name of the product that is being purchased
    pub product_name: String,
    /// The quantity of the product to be purchased
    pub quantity: u16,
    /// the amount per quantity of product
    pub amount: MinorUnit,
    // Does the order includes shipping
    pub requires_shipping: Option<bool>,
    /// The image URL of the product
    pub product_img_link: Option<String>,
    /// ID of the product that is being purchased
    pub product_id: Option<String>,
    /// Category of the product that is being purchased
    pub category: Option<String>,
    /// Sub category of the product that is being purchased
    pub sub_category: Option<String>,
    /// Brand of the product that is being purchased
    pub brand: Option<String>,
    /// Type of the product that is being purchased
    pub product_type: Option<common_enums::ProductType>,
    /// The tax code for the product
    pub product_tax_code: Option<String>,
    /// tax rate applicable to the product
    pub tax_rate: Option<f64>,
    /// total tax amount applicable to the product
    pub total_tax_amount: Option<MinorUnit>,
    /// description of the product
    pub description: Option<String>,
    /// stock keeping unit of the product
    pub sku: Option<String>,
    /// universal product code of the product
    pub upc: Option<String>,
    /// commodity code of the product
    pub commodity_code: Option<String>,
    /// unit of measure of the product
    pub unit_of_measure: Option<String>,
    /// total amount of the product
    pub total_amount: Option<MinorUnit>,
    /// discount amount on the unit
    pub unit_discount_amount: Option<MinorUnit>,
}


pub struct NetceteraMetaData {
    pub mcc: Option<String>,
    pub merchant_country_code: Option<String>,
    pub merchant_name: Option<String>,
    pub endpoint_prefix: String,
    pub three_ds_requestor_name: Option<String>,
    pub three_ds_requestor_id: Option<String>,
    pub merchant_configuration_id: Option<String>,
}


pub fn get_error_data(error_response: Option<&NordeaErrorBody>) -> Option<&NordeaFailures> {
    error_response
        .and_then(|error| error.nordea_failures.as_ref())
        .and_then(|failures| failures.first())
}


impl SuccessBasedRoutingConfigBody {
    pub fn update(&mut self, new: Self) {
        if let Some(min_aggregates_size) = new.min_aggregates_size {
            self.min_aggregates_size = Some(min_aggregates_size)
        }
        if let Some(default_success_rate) = new.default_success_rate {
            self.default_success_rate = Some(default_success_rate)
        }
        if let Some(max_aggregates_size) = new.max_aggregates_size {
            self.max_aggregates_size = Some(max_aggregates_size)
        }
        if let Some(current_block_threshold) = new.current_block_threshold {
            self.current_block_threshold
                .as_mut()
                .map(|threshold| threshold.update(current_block_threshold));
        }
        self.specificity_level = new.specificity_level;
        if let Some(exploration_percent) = new.exploration_percent {
            self.exploration_percent = Some(exploration_percent);
        }
        if let Some(shuffle_on_tie_during_exploitation) = new.shuffle_on_tie_during_exploitation {
            self.shuffle_on_tie_during_exploitation = Some(shuffle_on_tie_during_exploitation);
        }
    }
}


pub struct PaymentIntentFilters {
    #[serde(default)]
    pub status: Vec<IntentStatus>,
    #[serde(default)]
    pub currency: Vec<Currency>,
    #[serde(default)]
    pub profile_id: Vec<id_type::ProfileId>,
    #[serde(default)]
    pub connector: Vec<Connector>,
    #[serde(default)]
    pub auth_type: Vec<AuthenticationType>,
    #[serde(default)]
    pub payment_method: Vec<PaymentMethod>,
    #[serde(default)]
    pub payment_method_type: Vec<PaymentMethodType>,
    #[serde(default)]
    pub card_network: Vec<String>,
    #[serde(default)]
    pub merchant_id: Vec<id_type::MerchantId>,
    #[serde(default)]
    pub card_last_4: Vec<String>,
    #[serde(default)]
    pub card_issuer: Vec<String>,
    #[serde(default)]
    pub error_reason: Vec<String>,
    #[serde(default)]
    pub customer_id: Vec<id_type::CustomerId>,
}


pub async fn update_with_id(
        self,
        conn: &PgPooledConn,
        refund: RefundUpdate,
    ) -> StorageResult<Self> {
        match generics::generic_update_by_id::<<Self as HasTable>::Table, _, _, _>(
            conn,
            self.id.to_owned(),
            RefundUpdateInternal::from(refund),
        )
        .await
        {
            Err(error) => match error.current_context() {
                errors::DatabaseError::NoFieldsToUpdate => Ok(self),
                _ => Err(error),
            },
            result => result,
        }
    }


pub fn from_headers(headers: &HeaderMap) -> RouterResult<Self> {
        let merchant_id = headers
            .get(HEADER_MERCHANT_ID)
            .and_then(|value| value.to_str().ok())
            .ok_or_else(|| ApiErrorResponse::InvalidRequestData {
                message: format!("`{HEADER_MERCHANT_ID}` header is invalid or not present"),
            })
            .map_err(error_stack::Report::from)
            .and_then(|merchant_id| {
                MerchantId::try_from(Cow::from(merchant_id.to_string())).change_context(
                    ApiErrorResponse::InvalidRequestData {
                        message: format!(
                            "`{HEADER_MERCHANT_ID}` header is invalid or not present",

                        ),
                    },
                )
            })?;

        let auth_type: PayloadType = headers
            .get(HEADER_AUTH_TYPE)
            .and_then(|inner| inner.to_str().ok())
            .ok_or_else(|| ApiErrorResponse::InvalidRequestData {
                message: format!("`{HEADER_AUTH_TYPE}` header not present"),
            })?
            .parse::<PayloadType>()
            .change_context(ApiErrorResponse::InvalidRequestData {
                message: format!("`{HEADER_AUTH_TYPE}` header not present"),
            })?;

        let key_id = headers
            .get(HEADER_KEY_ID)
            .and_then(|value| value.to_str().ok())
            .map(|key_id| ApiKeyId::try_from(Cow::from(key_id.to_string())))
            .transpose()
            .change_context(ApiErrorResponse::InvalidRequestData {
                message: format!("`{HEADER_KEY_ID}` header is invalid or not present"),
            })?;

        Ok(Self {
            payload_type: auth_type,
            merchant_id: Some(merchant_id),
            key_id,
        })
    }


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

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

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

impl webhooks::IncomingWebhook for for Moneris


pub struct GiftCardDetails {
    /// The gift card number
    pub number: Secret<String>,
    /// The card verification code.
    pub cvc: Secret<String>,
}


pub async fn get_refunds_filters_profile(
    state: web::Data<AppState>,
    req: HttpRequest,
) -> HttpResponse {
    let flow = Flow::RefundsFilters;
    Box::pin(api::server_wrap(
        flow,
        state,
        &req,
        (),
        |state, auth: auth::AuthenticationData, _, _| {
            let merchant_context = domain::MerchantContext::NormalMerchant(Box::new(
                domain::Context(auth.merchant_account, auth.key_store),
            ));
            get_filters_for_refunds(
                state,
                merchant_context,
                auth.profile_id.map(|profile_id| vec![profile_id]),
            )
        },
        auth::auth_type(
            &auth::HeaderAuth(auth::ApiKeyAuth {
                is_connected_allowed: false,
                is_platform_allowed: false,
            }),
            &auth::JWTAuth {
                permission: Permission::ProfileRefundRead,
            },
            req.headers(),
        ),
        api_locking::LockAction::NotApplicable,
    ))
    .await
}


pub async fn find_by_user_email(
        conn: &PgPooledConn,
        user_email: &pii::Email,
    ) -> StorageResult<Self> {
        generics::generic_find_one::<<Self as HasTable>::Table, _, _>(
            conn,
            users_dsl::email.eq(user_email.to_owned()),
        )
        .await
    }


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


pub struct Card {
    pub holder_name: Secret<String>,
    pub number: cards::CardNumber,
    pub cvv: Secret<String>,
    pub expiration_month: Secret<String>,
    pub expiration_year: Secret<String>,
    pub capture: String,
    pub installments_id: Option<String>,
    pub installments: Option<String>,
}


pub async fn retrieve_profile(
    state: SessionState,
    profile_id: id_type::ProfileId,
    key_store: domain::MerchantKeyStore,
) -> RouterResponse<api_models::admin::ProfileResponse> {
    let db = state.store.as_ref();

    let business_profile = db
        .find_business_profile_by_profile_id(&(&state).into(), &key_store, &profile_id)
        .await
        .to_not_found_response(errors::ApiErrorResponse::ProfileNotFound {
            id: profile_id.get_string_repr().to_owned(),
        })?;

    Ok(service_api::ApplicationResponse::Json(
        api_models::admin::ProfileResponse::foreign_try_from(business_profile)
            .change_context(errors::ApiErrorResponse::InternalServerError)
            .attach_printable("Failed to parse business profile details")?,
    ))
}


pub struct MerchantConnectorResponse {
    /// Type of the Connector for the financial use case. Could range from Payments to Accounting to Banking.
    #[schema(value_type = ConnectorType, example = "payment_processor")]
    pub connector_type: api_enums::ConnectorType,
    /// Name of the Connector
    #[schema(value_type = Connector, example = "stripe")]
    pub connector_name: String,

    /// A unique label to identify the connector account created under a profile
    #[schema(example = "stripe_US_travel")]
    pub connector_label: Option<String>,

    /// Unique ID of the merchant connector account
    #[schema(example = "mca_5apGeP94tMts6rg3U3kR", value_type = String)]
    pub merchant_connector_id: id_type::MerchantConnectorAccountId,

    /// Identifier for the profile, if not provided default will be chosen from merchant account
    #[schema(max_length = 64, value_type = String)]
    pub profile_id: id_type::ProfileId,

    /// An object containing the required details/credentials for a Connector account.
    #[schema(value_type = Option<MerchantConnectorDetails>,example = json!({ "auth_type": "HeaderKey","api_key": "Basic MyVerySecretApiKey" }))]
    pub connector_account_details: pii::SecretSerdeValue,

    /// An object containing the details about the payment methods that need to be enabled under this merchant connector account
    #[schema(example = json!([
        {
            "payment_method": "wallet",
            "payment_method_types": [
                "upi_collect",
                "upi_intent"
            ],
            "payment_method_issuers": [
                "labore magna ipsum",
                "aute"
            ],
            "payment_schemes": [
                "Discover",
                "Discover"
            ],
            "accepted_currencies": {
                "type": "enable_only",
                "list": ["USD", "EUR"]
            },
            "accepted_countries": {
                "type": "disable_only",
                "list": ["FR", "DE","IN"]
            },
            "minimum_amount": 1,
            "maximum_amount": 68607706,
            "recurring_enabled": true,
            "installment_payment_enabled": true
        }
    ]))]
    pub payment_methods_enabled: Option<Vec<PaymentMethodsEnabled>>,

    /// Webhook details of this merchant connector
    #[schema(example = json!({
        "connector_webhook_details": {
            "merchant_secret": "1234567890987654321"
        }
    }))]
    pub connector_webhook_details: Option<MerchantConnectorWebhookDetails>,

    /// Metadata is useful for storing additional, unstructured information on an object.
    #[schema(value_type = Option<Object>,max_length = 255,example = json!({ "city": "NY", "unit": "245" }))]
    pub metadata: Option<pii::SecretSerdeValue>,

    /// A boolean value to indicate if the connector is in Test mode. By default, its value is false.
    #[schema(default = false, example = false)]
    pub test_mode: Option<bool>,

    /// A boolean value to indicate if the connector is disabled. By default, its value is false.
    #[schema(default = false, example = false)]
    pub disabled: Option<bool>,

    /// Contains the frm configs for the merchant connector
    #[schema(example = json!(consts::FRM_CONFIGS_EG))]
    pub frm_configs: Option<Vec<FrmConfigs>>,

    /// The business country to which the connector account is attached. To be deprecated soon. Use the 'profile_id' instead
    #[schema(value_type = Option<CountryAlpha2>, example = "US")]
    pub business_country: Option<api_enums::CountryAlpha2>,

    ///The business label to which the connector account is attached. To be deprecated soon. Use the 'profile_id' instead
    #[schema(example = "travel")]
    pub business_label: Option<String>,

    /// The business sublabel to which the connector account is attached. To be deprecated soon. Use the 'profile_id' instead
    #[schema(example = "chase")]
    pub business_sub_label: Option<String>,

    /// identifier for the verified domains of a particular connector account
    pub applepay_verified_domains: Option<Vec<String>>,

    #[schema(value_type = Option<Object>)]
    pub pm_auth_config: Option<pii::SecretSerdeValue>,

    #[schema(value_type = ConnectorStatus, example = "inactive")]
    pub status: api_enums::ConnectorStatus,

    #[schema(value_type = Option<AdditionalMerchantData>)]
    pub additional_merchant_data: Option<AdditionalMerchantData>,

    /// The connector_wallets_details is used to store wallet details such as certificates and wallet credentials
    #[schema(value_type = Option<ConnectorWalletDetails>)]
    pub connector_wallets_details: Option<ConnectorWalletDetails>,
}


File: crates/diesel_models/src/query/user/sample_data.rs
 Public functions: 9

use async_bb8_diesel::AsyncRunQueryDsl;
use diesel::{associations::HasTable, debug_query, ExpressionMethods, TextExpressionMethods};
use error_stack::ResultExt;
use router_env::logger;

#[cfg(feature = "v1")]
use crate::schema::{
    payment_attempt::dsl as payment_attempt_dsl, payment_intent::dsl as payment_intent_dsl,
    refund::dsl as refund_dsl,
};
#[cfg(feature = "v2")]
use crate::schema_v2::{
    payment_attempt::dsl as payment_attempt_dsl, payment_intent::dsl as payment_intent_dsl,
    refund::dsl as refund_dsl,
};
use crate::{
    errors, schema::dispute::dsl as dispute_dsl, Dispute, DisputeNew, PaymentAttempt,
    PaymentIntent, PgPooledConn, Refund, RefundNew, StorageResult,
};
#[cfg(feature = "v1")]
use crate::{user, PaymentIntentNew};

#[cfg(feature = "v1")]
pub async fn insert_payment_intents(
    conn: &PgPooledConn,
    batch: Vec<PaymentIntentNew>,
) -> StorageResult<Vec<PaymentIntent>> {
    let query = diesel::insert_into(<PaymentIntent>::table()).values(batch);

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

    query
        .get_results_async(conn)
        .await
        .change_context(errors::DatabaseError::Others)
        .attach_printable("Error while inserting payment intents")
}

#[cfg(feature = "v1")]
pub async fn insert_payment_attempts(
    conn: &PgPooledConn,
    batch: Vec<user::sample_data::PaymentAttemptBatchNew>,
) -> StorageResult<Vec<PaymentAttempt>> {
    let query = diesel::insert_into(<PaymentAttempt>::table()).values(batch);

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

    query
        .get_results_async(conn)
        .await
        .change_context(errors::DatabaseError::Others)
        .attach_printable("Error while inserting payment attempts")
}

pub async fn insert_refunds(
    conn: &PgPooledConn,
    batch: Vec<RefundNew>,
) -> StorageResult<Vec<Refund>> {
    let query = diesel::insert_into(<Refund>::table()).values(batch);

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

    query
        .get_results_async(conn)
        .await
        .change_context(errors::DatabaseError::Others)
        .attach_printable("Error while inserting refunds")
}

pub async fn insert_disputes(
    conn: &PgPooledConn,
    batch: Vec<DisputeNew>,
) -> StorageResult<Vec<Dispute>> {
    let query = diesel::insert_into(<Dispute>::table()).values(batch);

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

    query
        .get_results_async(conn)
        .await
        .change_context(errors::DatabaseError::Others)
        .attach_printable("Error while inserting disputes")
}

#[cfg(feature = "v1")]
pub async fn delete_payment_intents(
    conn: &PgPooledConn,
    merchant_id: &common_utils::id_type::MerchantId,
) -> StorageResult<Vec<PaymentIntent>> {
    let query = diesel::delete(<PaymentIntent>::table())
        .filter(payment_intent_dsl::merchant_id.eq(merchant_id.to_owned()))
        .filter(payment_intent_dsl::payment_id.like("test_%"));

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

    query
        .get_results_async(conn)
        .await
        .change_context(errors::DatabaseError::Others)
        .attach_printable("Error while deleting payment intents")
        .and_then(|result| match result.len() {
            n if n > 0 => {
                logger::debug!("{n} records deleted");
                Ok(result)
            }
            0 => Err(error_stack::report!(errors::DatabaseError::NotFound)
                .attach_printable("No records deleted")),
            _ => Ok(result),
        })
}

#[cfg(feature = "v2")]
pub async fn delete_payment_intents(
    conn: &PgPooledConn,
    merchant_id: &common_utils::id_type::MerchantId,
) -> StorageResult<Vec<PaymentIntent>> {
    let query = diesel::delete(<PaymentIntent>::table())
        .filter(payment_intent_dsl::merchant_id.eq(merchant_id.to_owned()))
        .filter(payment_intent_dsl::merchant_reference_id.like("test_%"));

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

    query
        .get_results_async(conn)
        .await
        .change_context(errors::DatabaseError::Others)
        .attach_printable("Error while deleting payment intents")
        .and_then(|result| match result.len() {
            n if n > 0 => {
                logger::debug!("{n} records deleted");
                Ok(result)
            }
            0 => Err(error_stack::report!(errors::DatabaseError::NotFound)
                .attach_printable("No records deleted")),
            _ => Ok(result),
        })
}
pub async fn delete_payment_attempts(
    conn: &PgPooledConn,
    merchant_id: &common_utils::id_type::MerchantId,
) -> StorageResult<Vec<PaymentAttempt>> {
    let query = diesel::delete(<PaymentAttempt>::table())
        .filter(payment_attempt_dsl::merchant_id.eq(merchant_id.to_owned()))
        .filter(payment_attempt_dsl::payment_id.like("test_%"));

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

    query
        .get_results_async(conn)
        .await
        .change_context(errors::DatabaseError::Others)
        .attach_printable("Error while deleting payment attempts")
        .and_then(|result| match result.len() {
            n if n > 0 => {
                logger::debug!("{n} records deleted");
                Ok(result)
            }
            0 => Err(error_stack::report!(errors::DatabaseError::NotFound)
                .attach_printable("No records deleted")),
            _ => Ok(result),
        })
}

pub async fn delete_refunds(
    conn: &PgPooledConn,
    merchant_id: &common_utils::id_type::MerchantId,
) -> StorageResult<Vec<Refund>> {
    let query = diesel::delete(<Refund>::table())
        .filter(refund_dsl::merchant_id.eq(merchant_id.to_owned()))
        .filter(refund_dsl::payment_id.like("test_%"));

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

    query
        .get_results_async(conn)
        .await
        .change_context(errors::DatabaseError::Others)
        .attach_printable("Error while deleting refunds")
        .and_then(|result| match result.len() {
            n if n > 0 => {
                logger::debug!("{n} records deleted");
                Ok(result)
            }
            0 => Err(error_stack::report!(errors::DatabaseError::NotFound)
                .attach_printable("No records deleted")),
            _ => Ok(result),
        })
}

pub async fn delete_disputes(
    conn: &PgPooledConn,
    merchant_id: &common_utils::id_type::MerchantId,
) -> StorageResult<Vec<Dispute>> {
    let query = diesel::delete(<Dispute>::table())
        .filter(dispute_dsl::merchant_id.eq(merchant_id.to_owned()))
        .filter(dispute_dsl::dispute_id.like("test_%"));

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

    query
        .get_results_async(conn)
        .await
        .change_context(errors::DatabaseError::Others)
        .attach_printable("Error while deleting disputes")
        .and_then(|result| match result.len() {
            n if n > 0 => {
                logger::debug!("{n} records deleted");
                Ok(result)
            }
            0 => Err(error_stack::report!(errors::DatabaseError::NotFound)
                .attach_printable("No records deleted")),
            _ => Ok(result),
        })
}


impl api::ConnectorAccessToken for Authipay {}

impl api::ConnectorAccessToken for for Authipay


File: crates/router/src/routes/recon.rs
 Public functions: 4

use actix_web::{web, HttpRequest, HttpResponse};
use api_models::recon as recon_api;
use router_env::Flow;

use super::AppState;
use crate::{
    core::{api_locking, recon},
    services::{api, authentication, authorization::permissions::Permission},
};

pub async fn update_merchant(
    state: web::Data<AppState>,
    req: HttpRequest,
    path: web::Path<common_utils::id_type::MerchantId>,
    json_payload: web::Json<recon_api::ReconUpdateMerchantRequest>,
) -> HttpResponse {
    let flow = Flow::ReconMerchantUpdate;
    let merchant_id = path.into_inner();

    Box::pin(api::server_wrap(
        flow,
        state,
        &req,
        json_payload.into_inner(),
        |state, auth, req, _| recon::recon_merchant_account_update(state, auth, req),
        &authentication::AdminApiAuthWithMerchantIdFromRoute(merchant_id),
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

pub async fn request_for_recon(state: web::Data<AppState>, http_req: HttpRequest) -> HttpResponse {
    let flow = Flow::ReconServiceRequest;
    Box::pin(api::server_wrap(
        flow,
        state,
        &http_req,
        (),
        |state, user, _, _| recon::send_recon_request(state, user),
        &authentication::JWTAuth {
            permission: Permission::MerchantAccountWrite,
        },
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

pub async fn get_recon_token(state: web::Data<AppState>, req: HttpRequest) -> HttpResponse {
    let flow = Flow::ReconTokenRequest;
    Box::pin(api::server_wrap(
        flow,
        state,
        &req,
        (),
        |state, user, _, _| recon::generate_recon_token(state, user),
        &authentication::JWTAuth {
            permission: Permission::MerchantReconTokenRead,
        },
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

#[cfg(feature = "recon")]
pub async fn verify_recon_token(state: web::Data<AppState>, http_req: HttpRequest) -> HttpResponse {
    let flow = Flow::ReconVerifyToken;
    Box::pin(api::server_wrap(
        flow,
        state.clone(),
        &http_req,
        (),
        |state, user, _req, _| recon::verify_recon_token(state, user),
        &authentication::JWTAuth {
            permission: Permission::MerchantReconTokenRead,
        },
        api_locking::LockAction::NotApplicable,
    ))
    .await
}


pub trait PaymentRedirectFlow: Sync {
    // Associated type for call_payment_flow response
    type PaymentFlowResponse;

    #[cfg(feature = "v1")]
    #[allow(clippy::too_many_arguments)]
    async fn call_payment_flow(
        &self,
        state: &SessionState,
        req_state: ReqState,
        merchant_context: domain::MerchantContext,
        req: PaymentsRedirectResponseData,
        connector_action: CallConnectorAction,
        connector: String,
        payment_id: id_type::PaymentId,
    ) -> RouterResult<Self::PaymentFlowResponse>;

    #[cfg(feature = "v2")]
    #[allow(clippy::too_many_arguments)]
    async fn call_payment_flow(
        &self,
        state: &SessionState,
        req_state: ReqState,
        merchant_context: domain::MerchantContext,
        profile: domain::Profile,
        req: PaymentsRedirectResponseData,
    ) -> RouterResult<Self::PaymentFlowResponse>;

    fn get_payment_action(&self) -> services::PaymentAction;

    #[cfg(feature = "v1")]
    fn generate_response(
        &self,
        payment_flow_response: &Self::PaymentFlowResponse,
        payment_id: id_type::PaymentId,
        connector: String,
    ) -> RouterResult<services::ApplicationResponse<api::RedirectionResponse>>;

    #[cfg(feature = "v2")]
    fn generate_response(
        &self,
        payment_flow_response: &Self::PaymentFlowResponse,
    ) -> RouterResult<services::ApplicationResponse<api::RedirectionResponse>>;

    #[cfg(feature = "v1")]
    async fn handle_payments_redirect_response(
        &self,
        state: SessionState,
        req_state: ReqState,
        merchant_context: domain::MerchantContext,
        req: PaymentsRedirectResponseData,
    ) -> RouterResponse<api::RedirectionResponse> {
        metrics::REDIRECTION_TRIGGERED.add(
            1,
            router_env::metric_attributes!(
                (
                    "connector",
                    req.connector.to_owned().unwrap_or("null".to_string()),
                ),
                (
                    "merchant_id",
                    merchant_context.get_merchant_account().get_id().clone()
                ),
            ),
        );
        let connector = req.connector.clone().get_required_value("connector")?;

        let query_params = req.param.clone().get_required_value("param")?;

        #[cfg(feature = "v1")]
        let resource_id = api::PaymentIdTypeExt::get_payment_intent_id(&req.resource_id)
            .change_context(errors::ApiErrorResponse::MissingRequiredField {
                field_name: "payment_id",
            })?;

        #[cfg(feature = "v2")]
        //TODO: Will get the global payment id from the resource id, we need to handle this in the further flow
        let resource_id: id_type::PaymentId = todo!();

        // This connector data is ephemeral, the call payment flow will get new connector data
        // with merchant account details, so the connector_id can be safely set to None here
        let connector_data = api::ConnectorData::get_connector_by_name(
            &state.conf.connectors,
            &connector,
            api::GetToken::Connector,
            None,
        )?;

        let flow_type = connector_data
            .connector
            .get_flow_type(
                &query_params,
                req.json_payload.clone(),
                self.get_payment_action(),
            )
            .change_context(errors::ApiErrorResponse::InternalServerError)
            .attach_printable("Failed to decide the response flow")?;

        let payment_flow_response = self
            .call_payment_flow(
                &state,
                req_state,
                merchant_context,
                req.clone(),
                flow_type,
                connector.clone(),
                resource_id.clone(),
            )
            .await?;

        self.generate_response(&payment_flow_response, resource_id, connector)
    }

    #[cfg(feature = "v2")]
    #[allow(clippy::too_many_arguments)]
    async fn handle_payments_redirect_response(
        &self,
        state: SessionState,
        req_state: ReqState,
        merchant_context: domain::MerchantContext,
        profile: domain::Profile,
        request: PaymentsRedirectResponseData,
    ) -> RouterResponse<api::RedirectionResponse> {
        metrics::REDIRECTION_TRIGGERED.add(
            1,
            router_env::metric_attributes!((
                "merchant_id",
                merchant_context.get_merchant_account().get_id().clone()
            )),
        );

        let payment_flow_response = self
            .call_payment_flow(&state, req_state, merchant_context, profile, request)
            .await?;

        self.generate_response(&payment_flow_response)
    }
}


impl CardDetailsForNetworkTransactionId {
    pub fn get_nti_and_card_details_for_mit_flow(
        recurring_details: mandates::RecurringDetails,
    ) -> Option<(api_models::payments::MandateReferenceId, Self)> {
        let network_transaction_id_and_card_details = match recurring_details {
            mandates::RecurringDetails::NetworkTransactionIdAndCardDetails(
                network_transaction_id_and_card_details,
            ) => Some(network_transaction_id_and_card_details),
            mandates::RecurringDetails::MandateId(_)
            | mandates::RecurringDetails::PaymentMethodId(_)
            | mandates::RecurringDetails::ProcessorPaymentToken(_) => None,
        }?;

        let mandate_reference_id = api_models::payments::MandateReferenceId::NetworkMandateId(
            network_transaction_id_and_card_details
                .network_transaction_id
                .peek()
                .to_string(),
        );

        Some((
            mandate_reference_id,
            network_transaction_id_and_card_details.clone().into(),
        ))
    }
}


pub struct AuthenticationTokenFlowData {}