File: crates/analytics/src/api_event/types.rs

use api_models::analytics::api_event::{ApiEventDimensions, ApiEventFilters};
use error_stack::ResultExt;

use crate::{
    query::{QueryBuilder, QueryFilter, QueryResult, ToSql},
    types::{AnalyticsCollection, AnalyticsDataSource},
};

impl<T> QueryFilter<T> for ApiEventFilters
where
    T: AnalyticsDataSource,
    AnalyticsCollection: ToSql<T>,
{
    fn set_filter_clause(&self, builder: &mut QueryBuilder<T>) -> QueryResult<()> {
        if !self.status_code.is_empty() {
            builder
                .add_filter_in_range_clause(ApiEventDimensions::StatusCode, &self.status_code)
                .attach_printable("Error adding status_code filter")?;
        }
        if !self.flow_type.is_empty() {
            builder
                .add_filter_in_range_clause(ApiEventDimensions::FlowType, &self.flow_type)
                .attach_printable("Error adding flow_type filter")?;
        }
        if !self.api_flow.is_empty() {
            builder
                .add_filter_in_range_clause(ApiEventDimensions::ApiFlow, &self.api_flow)
                .attach_printable("Error adding api_name filter")?;
        }

        Ok(())
    }
}


File: crates/router/src/db/customers.rs

pub use hyperswitch_domain_models::customer::{CustomerInterface, CustomerListConstraints};


OpenAPI Block Path: components.schemas.PazeWalletData
{
  "type": "object",
  "required": [
    "complete_response"
  ],
  "properties": {
    "complete_response": {
      "type": "string"
    }
  }
}


impl Capturable for PaymentsRejectData {}

impl Capturable for for PaymentsRejectData


File: crates/openapi/src/routes/merchant_account.rs
 Public functions: 10

#[cfg(feature = "v1")]
/// Merchant Account - Create
///
/// Create a new account for a *merchant* and the *merchant* could be a seller or retailer or client who likes to receive and send payments.
#[utoipa::path(
    post,
    path = "/accounts",
    request_body(
        content = MerchantAccountCreate,
        examples(
            (
                "Create a merchant account with minimal fields" = (
                    value = json!({"merchant_id": "merchant_abc"})
                )
            ),
            (
                "Create a merchant account with webhook url" = (
                    value = json!({
                        "merchant_id": "merchant_abc",
                        "webhook_details" : {
                            "webhook_url": "https://webhook.site/a5c54f75-1f7e-4545-b781-af525b7e37a0"
                        }
                    })
                )
            ),
            (
                "Create a merchant account with return url" = (
                    value = json!({"merchant_id": "merchant_abc",
                "return_url": "https://example.com"})
                )
            )
        )

    ),
    responses(
        (status = 200, description = "Merchant Account Created", body = MerchantAccountResponse),
        (status = 400, description = "Invalid data")
    ),
    tag = "Merchant Account",
    operation_id = "Create a Merchant Account",
    security(("admin_api_key" = []))
)]
pub async fn merchant_account_create() {}

#[cfg(feature = "v2")]
/// Merchant Account - Create
///
/// Create a new account for a *merchant* and the *merchant* could be a seller or retailer or client who likes to receive and send payments.
///
/// Before creating the merchant account, it is mandatory to create an organization.
#[utoipa::path(
    post,
    path = "/v2/merchant-accounts",
    params(
      (
        "X-Organization-Id" = String, Header,
        description = "Organization ID for which the merchant account has to be created.",
        example = json!({"X-Organization-Id": "org_abcdefghijklmnop"})
      ),
    ),
    request_body(
        content = MerchantAccountCreate,
        examples(
            (
                "Create a merchant account with minimal fields" = (
                    value = json!({
                        "merchant_name": "Cloth Store",
                    })
                )
            ),
            (
                "Create a merchant account with merchant details" = (
                    value = json!({
                        "merchant_name": "Cloth Store",
                        "merchant_details": {
                                "primary_contact_person": "John Doe",
                                "primary_email": "example@company.com"
                        }
                    })
                )
            ),
            (
                "Create a merchant account with metadata" = (
                    value = json!({
                        "merchant_name": "Cloth Store",
                        "metadata": {
                                "key_1": "John Doe",
                                "key_2": "Trends"
                        }
                    })
                )
            ),

        )

    ),
    responses(
        (status = 200, description = "Merchant Account Created", body = MerchantAccountResponse),
        (status = 400, description = "Invalid data")
    ),
    tag = "Merchant Account",
    operation_id = "Create a Merchant Account",
    security(("admin_api_key" = []))
)]
pub async fn merchant_account_create() {}

#[cfg(feature = "v1")]
/// Merchant Account - Retrieve
///
/// Retrieve a *merchant* account details.
#[utoipa::path(
    get,
    path = "/accounts/{account_id}",
    params (("account_id" = String, Path, description = "The unique identifier for the merchant account")),
    responses(
        (status = 200, description = "Merchant Account Retrieved", body = MerchantAccountResponse),
        (status = 404, description = "Merchant account not found")
    ),
    tag = "Merchant Account",
    operation_id = "Retrieve a Merchant Account",
    security(("admin_api_key" = []))
)]
pub async fn retrieve_merchant_account() {}

#[cfg(feature = "v2")]
/// Merchant Account - Retrieve
///
/// Retrieve a *merchant* account details.
#[utoipa::path(
    get,
    path = "/v2/merchant-accounts/{id}",
    params (("id" = String, Path, description = "The unique identifier for the merchant account")),
    responses(
        (status = 200, description = "Merchant Account Retrieved", body = MerchantAccountResponse),
        (status = 404, description = "Merchant account not found")
    ),
    tag = "Merchant Account",
    operation_id = "Retrieve a Merchant Account",
    security(("admin_api_key" = []))
)]
pub async fn merchant_account_retrieve() {}

#[cfg(feature = "v1")]
/// Merchant Account - Update
///
/// Updates details of an existing merchant account. Helpful in updating merchant details such as email, contact details, or other configuration details like webhook, routing algorithm etc
#[utoipa::path(
    post,
    path = "/accounts/{account_id}",
    request_body (
        content = MerchantAccountUpdate,
        examples(
            (
            "Update merchant name" = (
                value = json!({
                    "merchant_id": "merchant_abc",
                    "merchant_name": "merchant_name"
                })
            )
            ),
            ("Update webhook url" = (
                    value = json!({
                        "merchant_id": "merchant_abc",
                        "webhook_details": {
                            "webhook_url": "https://webhook.site/a5c54f75-1f7e-4545-b781-af525b7e37a0"
                        }
                    })
                )
            ),
            ("Update return url" = (
                value = json!({
                    "merchant_id": "merchant_abc",
                    "return_url": "https://example.com"
                })
            )))),
    params (("account_id" = String, Path, description = "The unique identifier for the merchant account")),
    responses(
        (status = 200, description = "Merchant Account Updated", body = MerchantAccountResponse),
        (status = 404, description = "Merchant account not found")
    ),
    tag = "Merchant Account",
    operation_id = "Update a Merchant Account",
    security(("admin_api_key" = []))
)]
pub async fn update_merchant_account() {}

#[cfg(feature = "v2")]
/// Merchant Account - Update
///
/// Updates details of an existing merchant account. Helpful in updating merchant details such as email, contact details, or other configuration details like webhook, routing algorithm etc
#[utoipa::path(
    put,
    path = "/v2/merchant-accounts/{id}",
    request_body (
        content = MerchantAccountUpdate,
        examples(
            (
            "Update merchant name" = (
                value = json!({
                    "merchant_id": "merchant_abc",
                    "merchant_name": "merchant_name"
                })
            )
            ),
            ("Update Merchant Details" = (
                    value = json!({
                        "merchant_details": {
                                "primary_contact_person": "John Doe",
                                "primary_email": "example@company.com"
                        }
                    })
                )
            ),
            )),
    params (("id" = String, Path, description = "The unique identifier for the merchant account")),
    responses(
        (status = 200, description = "Merchant Account Updated", body = MerchantAccountResponse),
        (status = 404, description = "Merchant account not found")
    ),
    tag = "Merchant Account",
    operation_id = "Update a Merchant Account",
    security(("admin_api_key" = []))
)]
pub async fn merchant_account_update() {}

#[cfg(feature = "v1")]
/// Merchant Account - Delete
///
/// Delete a *merchant* account
#[utoipa::path(
    delete,
    path = "/accounts/{account_id}",
    params (("account_id" = String, Path, description = "The unique identifier for the merchant account")),
    responses(
        (status = 200, description = "Merchant Account Deleted", body = MerchantAccountDeleteResponse),
        (status = 404, description = "Merchant account not found")
    ),
    tag = "Merchant Account",
    operation_id = "Delete a Merchant Account",
    security(("admin_api_key" = []))
)]
pub async fn delete_merchant_account() {}

#[cfg(feature = "v1")]
/// Merchant Account - KV Status
///
/// Toggle KV mode for the Merchant Account
#[utoipa::path(
    post,
    path = "/accounts/{account_id}/kv",
    request_body (
        content = ToggleKVRequest,
        examples (
            ("Enable KV for Merchant" = (
                value = json!({
                "kv_enabled": "true"
                })
        )),
        ("Disable KV for Merchant" = (
                value = json!({
                "kv_enabled": "false"
                })
        )))
    ),
    params (("account_id" = String, Path, description = "The unique identifier for the merchant account")),
    responses(
        (status = 200, description = "KV mode is enabled/disabled for Merchant Account", body = ToggleKVResponse),
        (status = 400, description = "Invalid data"),
        (status = 404, description = "Merchant account not found")
    ),
    tag = "Merchant Account",
    operation_id = "Enable/Disable KV for a Merchant Account",
    security(("admin_api_key" = []))
)]
pub async fn merchant_account_kv_status() {}

/// Merchant Connector - List
///
/// List Merchant Connector Details for the merchant
#[utoipa::path(
    get,
    path = "/accounts/{account_id}/profile/connectors",
    params(
        ("account_id" = String, Path, description = "The unique identifier for the merchant account"),
    ),
    responses(
        (status = 200, description = "Merchant Connector list retrieved successfully", body = Vec<MerchantConnectorResponse>),
        (status = 404, description = "Merchant Connector does not exist in records"),
        (status = 401, description = "Unauthorized request")
    ),
    tag = "Merchant Connector Account",
    operation_id = "List all Merchant Connectors for The given Profile",
    security(("admin_api_key" = []))
)]
pub async fn payment_connector_list_profile() {}

#[cfg(feature = "v2")]
/// Merchant Account - Profile List
///
/// List profiles for an Merchant
#[utoipa::path(
    get,
    path = "/v2/merchant-accounts/{id}/profiles",
    params (("id" = String, Path, description = "The unique identifier for the Merchant")),
    responses(
        (status = 200, description = "profile list retrieved successfully", body = Vec<ProfileResponse>),
        (status = 400, description = "Invalid data")
    ),
    tag = "Merchant Account",
    operation_id = "List Profiles",
    security(("admin_api_key" = []))
)]
pub async fn profiles_list() {}


impl api::RefundSync for Prophetpay {}


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

---
openapi: post /accounts/{account_id}
---


impl EmailClient for AwsSes {
    type RichText = Body;

    fn convert_to_rich_text(
        &self,
        intermediate_string: IntermediateString,
    ) -> CustomResult<Self::RichText, EmailError> {
        let email_body = Body::builder()
            .html(
                Content::builder()
                    .data(intermediate_string.into_inner())
                    .charset("UTF-8")
                    .build()
                    .change_context(EmailError::ContentBuildFailure)?,
            )
            .build();

        Ok(email_body)
    }

    async fn send_email(
        &self,
        recipient: pii::Email,
        subject: String,
        body: Self::RichText,
        proxy_url: Option<&String>,
    ) -> EmailResult<()> {
        // Not using the same email client which was created at startup as the role session would expire
        // Create a client every time when the email is being sent
        let email_client = Self::create_client(&self.settings, &self.ses_config, proxy_url)
            .await
            .change_context(EmailError::ClientBuildingFailure)?;

        email_client
            .send_email()
            .from_email_address(self.sender.to_owned())
            .destination(
                Destination::builder()
                    .to_addresses(recipient.peek())
                    .build(),
            )
            .content(
                EmailContent::builder()
                    .simple(
                        Message::builder()
                            .subject(
                                Content::builder()
                                    .data(subject)
                                    .build()
                                    .change_context(EmailError::ContentBuildFailure)?,
                            )
                            .body(body)
                            .build(),
                    )
                    .build(),
            )
            .send()
            .await
            .map_err(|e| AwsSesError::SendingFailure(Box::new(e)))
            .change_context(EmailError::EmailSendingFailure)?;

        Ok(())
    }
}


/// Maps from proto WebhookEventType enum values to IncomingWebhookEvent variants
    pub fn from_ucs_event_type(event_type: i32) -> Self {
        match event_type {
            0 => Self::EventNotSupported,
            // Payment intent events
            1 => Self::PaymentIntentFailure,
            2 => Self::PaymentIntentSuccess,
            3 => Self::PaymentIntentProcessing,
            4 => Self::PaymentIntentPartiallyFunded,
            5 => Self::PaymentIntentCancelled,
            6 => Self::PaymentIntentCancelFailure,
            7 => Self::PaymentIntentAuthorizationSuccess,
            8 => Self::PaymentIntentAuthorizationFailure,
            9 => Self::PaymentIntentCaptureSuccess,
            10 => Self::PaymentIntentCaptureFailure,
            11 => Self::PaymentIntentExpired,
            12 => Self::PaymentActionRequired,
            // Source events
            13 => Self::SourceChargeable,
            14 => Self::SourceTransactionCreated,
            // Refund events
            15 => Self::RefundFailure,
            16 => Self::RefundSuccess,
            // Dispute events
            17 => Self::DisputeOpened,
            18 => Self::DisputeExpired,
            19 => Self::DisputeAccepted,
            20 => Self::DisputeCancelled,
            21 => Self::DisputeChallenged,
            22 => Self::DisputeWon,
            23 => Self::DisputeLost,
            // Mandate events
            24 => Self::MandateActive,
            25 => Self::MandateRevoked,
            // Miscellaneous events
            26 => Self::EndpointVerification,
            27 => Self::ExternalAuthenticationARes,
            28 => Self::FrmApproved,
            29 => Self::FrmRejected,
            // Payout events
            #[cfg(feature = "payouts")]
            30 => Self::PayoutSuccess,
            #[cfg(feature = "payouts")]
            31 => Self::PayoutFailure,
            #[cfg(feature = "payouts")]
            32 => Self::PayoutProcessing,
            #[cfg(feature = "payouts")]
            33 => Self::PayoutCancelled,
            #[cfg(feature = "payouts")]
            34 => Self::PayoutCreated,
            #[cfg(feature = "payouts")]
            35 => Self::PayoutExpired,
            #[cfg(feature = "payouts")]
            36 => Self::PayoutReversed,
            _ => Self::EventNotSupported,
        }
    }


pub struct CurrencyFactors {
    /// The factor that will be multiplied to provide Currency output
    pub to_factor: Decimal,
    /// The factor that will be multiplied to provide for the base output
    pub from_factor: Decimal,
}


OpenAPI Block Path: components.schemas.CreateApiKeyRequest
{
  "type": "object",
  "description": "The request body for creating an API Key.",
  "required": [
    "name",
    "expiration"
  ],
  "properties": {
    "name": {
      "type": "string",
      "description": "A unique name for the API Key to help you identify it.",
      "example": "Sandbox integration key",
      "maxLength": 64
    },
    "description": {
      "type": "string",
      "description": "A description to provide more context about the API Key.",
      "example": "Key used by our developers to integrate with the sandbox environment",
      "nullable": true,
      "maxLength": 256
    },
    "expiration": {
      "$ref": "#/components/schemas/ApiKeyExpiration"
    }
  },
  "additionalProperties": false
}


pub fn get_connector_test_mode(&self) -> Option<bool> {
        todo!()
    }


OpenAPI Block Path: paths."/routing/rule/evaluate"
{
  "post": {
    "tags": [
      "Routing"
    ],
    "summary": "Routing - Rule Evaluate",
    "description": "Evaluate routing rules",
    "operationId": "Evaluate routing rules (alternative)",
    "requestBody": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/RoutingEvaluateRequest"
          }
        }
      },
      "required": true
    },
    "responses": {
      "200": {
        "description": "Routing rules evaluated successfully",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/RoutingEvaluateResponse"
            }
          }
        }
      },
      "400": {
        "description": "Request body is malformed"
      },
      "403": {
        "description": "Forbidden"
      },
      "404": {
        "description": "Resource missing"
      },
      "422": {
        "description": "Unprocessable request"
      },
      "500": {
        "description": "Internal server error"
      }
    },
    "security": [
      {
        "api_key": []
      }
    ]
  }
}


pub async fn save_card_and_network_token_in_locker(
    state: &SessionState,
    customer_id: id_type::CustomerId,
    payment_method_status: common_enums::PaymentMethodStatus,
    payment_method_data: domain::PaymentMethodData,
    vault_operation: Option<hyperswitch_domain_models::payments::VaultOperation>,
    payment_method_info: Option<domain::PaymentMethod>,
    merchant_context: &domain::MerchantContext,
    payment_method_create_request: api::PaymentMethodCreate,
    is_network_tokenization_enabled: bool,
) -> RouterResult<(
    (
        api_models::payment_methods::PaymentMethodResponse,
        Option<payment_methods::transformers::DataDuplicationCheck>,
        Option<String>,
    ),
    Option<api_models::payment_methods::PaymentMethodResponse>,
)> {
    let network_token_requestor_reference_id = payment_method_info
        .and_then(|pm_info| pm_info.network_token_requestor_reference_id.clone());

    match vault_operation {
        Some(hyperswitch_domain_models::payments::VaultOperation::SaveCardData(card)) => {
            let card_data = api::CardDetail::from(card.card_data.clone());
            if let (Some(nt_ref_id), Some(tokenization_service)) = (
                card.network_token_req_ref_id.clone(),
                &state.conf.network_tokenization_service,
            ) {
                let _ = record_operation_time(
                    async {
                        network_tokenization::delete_network_token_from_tokenization_service(
                            state,
                            nt_ref_id.clone(),
                            &customer_id,
                            tokenization_service.get_inner(),
                        )
                        .await
                    },
                    &metrics::DELETE_NETWORK_TOKEN_TIME,
                    &[],
                )
                .await;
            }
            let (res, dc) = Box::pin(save_in_locker(
                state,
                merchant_context,
                payment_method_create_request.to_owned(),
                Some(card_data),
            ))
            .await
            .change_context(errors::ApiErrorResponse::InternalServerError)
            .attach_printable("Add Card In Locker Failed")?;

            Ok(((res, dc, None), None))
        }
        Some(hyperswitch_domain_models::payments::VaultOperation::SaveCardAndNetworkTokenData(
            save_card_and_network_token_data,
        )) => {
            let card_data =
                api::CardDetail::from(save_card_and_network_token_data.card_data.clone());

            let network_token_data = api::CardDetail::from(
                save_card_and_network_token_data
                    .network_token
                    .network_token_data
                    .clone(),
            );

            if payment_method_status == common_enums::PaymentMethodStatus::Active {
                let (res, dc) = Box::pin(save_in_locker(
                    state,
                    merchant_context,
                    payment_method_create_request.to_owned(),
                    Some(card_data),
                ))
                .await
                .change_context(errors::ApiErrorResponse::InternalServerError)
                .attach_printable("Add Card In Locker Failed")?;

                let (network_token_resp, _dc, _) = Box::pin(save_network_token_in_locker(
                    state,
                    merchant_context,
                    &save_card_and_network_token_data.card_data,
                    Some(network_token_data),
                    payment_method_create_request.clone(),
                ))
                .await
                .change_context(errors::ApiErrorResponse::InternalServerError)
                .attach_printable("Add Network Token In Locker Failed")?;

                Ok((
                    (res, dc, network_token_requestor_reference_id),
                    network_token_resp,
                ))
            } else {
                if let (Some(nt_ref_id), Some(tokenization_service)) = (
                    network_token_requestor_reference_id.clone(),
                    &state.conf.network_tokenization_service,
                ) {
                    let _ = record_operation_time(
                        async {
                            network_tokenization::delete_network_token_from_tokenization_service(
                                state,
                                nt_ref_id.clone(),
                                &customer_id,
                                tokenization_service.get_inner(),
                            )
                            .await
                        },
                        &metrics::DELETE_NETWORK_TOKEN_TIME,
                        &[],
                    )
                    .await;
                }
                let (res, dc) = Box::pin(save_in_locker(
                    state,
                    merchant_context,
                    payment_method_create_request.to_owned(),
                    Some(card_data),
                ))
                .await
                .change_context(errors::ApiErrorResponse::InternalServerError)
                .attach_printable("Add Card In Locker Failed")?;

                Ok(((res, dc, None), None))
            }
        }
        _ => {
            let (res, dc) = Box::pin(save_in_locker(
                state,
                merchant_context,
                payment_method_create_request.to_owned(),
                None,
            ))
            .await?;

            if is_network_tokenization_enabled {
                match &payment_method_data {
                    domain::PaymentMethodData::Card(card) => {
                        let (
                            network_token_resp,
                            _network_token_duplication_check, //the duplication check is discarded, since each card has only one token, handling card duplication check will be suffice
                            network_token_requestor_ref_id,
                        ) = Box::pin(save_network_token_in_locker(
                            state,
                            merchant_context,
                            card,
                            None,
                            payment_method_create_request.clone(),
                        ))
                        .await?;

                        Ok((
                            (res, dc, network_token_requestor_ref_id),
                            network_token_resp,
                        ))
                    }
                    _ => Ok(((res, dc, None), None)), //network_token_resp is None in case of other payment methods
                }
            } else {
                Ok(((res, dc, None), None))
            }
        }
    }
}


impl api::Refund for Archipel {}


pub struct ApplePayPaymentInformation {
    tokenized_card: TokenizedCard,
}


Documentation: api-reference/intelligent-router-api-reference/success-rate/update-success-rate-window.mdx
# Type: Doc File

---
openapi: post /success_rate.SuccessRateCalculator/UpdateSuccessRateWindow
---


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


pub async fn perform_success_based_routing<F, D>(
    state: &SessionState,
    routable_connectors: Vec<api_routing::RoutableConnectorChoice>,
    profile_id: &common_utils::id_type::ProfileId,
    merchant_id: &common_utils::id_type::MerchantId,
    payment_id: &common_utils::id_type::PaymentId,
    success_based_routing_config_params_interpolator: routing::helpers::DynamicRoutingConfigParamsInterpolator,
    success_based_algo_ref: api_routing::SuccessBasedAlgorithm,
    payment_data: &mut D,
) -> RoutingResult<Vec<api_routing::RoutableConnectorChoice>>
where
    F: Send + Clone,
    D: OperationSessionGetters<F> + OperationSessionSetters<F> + Send + Sync + Clone,
{
    if success_based_algo_ref.enabled_feature
        == api_routing::DynamicRoutingFeatures::DynamicConnectorSelection
    {
        logger::debug!(
            "performing success_based_routing for profile {}",
            profile_id.get_string_repr()
        );
        let client = &state
            .grpc_client
            .dynamic_routing
            .as_ref()
            .ok_or(errors::RoutingError::SuccessRateClientInitializationError)
            .attach_printable("dynamic routing gRPC client not found")?
            .success_rate_client;

        let success_based_routing_configs = routing::helpers::fetch_dynamic_routing_configs::<
            api_routing::SuccessBasedRoutingConfig,
        >(
            state,
            profile_id,
            success_based_algo_ref
                .algorithm_id_with_timestamp
                .algorithm_id
                .ok_or(errors::RoutingError::GenericNotFoundError {
                    field: "success_based_routing_algorithm_id".to_string(),
                })
                .attach_printable("success_based_routing_algorithm_id not found in profile_id")?,
        )
        .await
        .change_context(errors::RoutingError::SuccessBasedRoutingConfigError)
        .attach_printable("unable to fetch success_rate based dynamic routing configs")?;

        let success_based_routing_config_params = success_based_routing_config_params_interpolator
            .get_string_val(
                success_based_routing_configs
                    .params
                    .as_ref()
                    .ok_or(errors::RoutingError::SuccessBasedRoutingParamsNotFoundError)?,
            );

        let event_request = utils::CalSuccessRateEventRequest {
            id: profile_id.get_string_repr().to_string(),
            params: success_based_routing_config_params.clone(),
            labels: routable_connectors
                .iter()
                .map(|conn_choice| conn_choice.to_string())
                .collect::<Vec<_>>(),
            config: success_based_routing_configs
                .config
                .as_ref()
                .map(utils::CalSuccessRateConfigEventRequest::from),
        };

        let routing_events_wrapper = utils::RoutingEventsWrapper::new(
            state.tenant.tenant_id.clone(),
            state.request_id,
            payment_id.get_string_repr().to_string(),
            profile_id.to_owned(),
            merchant_id.to_owned(),
            "IntelligentRouter: CalculateSuccessRate".to_string(),
            Some(event_request.clone()),
            true,
            false,
        );

        let closure = || async {
            let success_based_connectors_result = client
                .calculate_success_rate(
                    profile_id.get_string_repr().into(),
                    success_based_routing_configs,
                    success_based_routing_config_params,
                    routable_connectors,
                    state.get_grpc_headers(),
                )
                .await
                .change_context(errors::RoutingError::SuccessRateCalculationError)
                .attach_printable(
                    "unable to calculate/fetch success rate from dynamic routing service",
                );

            match success_based_connectors_result {
                Ok(success_response) => {
                    let updated_resp = utils::CalSuccessRateEventResponse::try_from(
                        &success_response,
                    )
                    .change_context(errors::RoutingError::RoutingEventsError { message: "unable to convert SuccessBasedConnectors to CalSuccessRateEventResponse".to_string(), status_code: 500 })
                    .attach_printable(
                        "unable to convert SuccessBasedConnectors to CalSuccessRateEventResponse",
                    )?;

                    Ok(Some(updated_resp))
                }
                Err(e) => {
                    logger::error!(
                        "unable to calculate/fetch success rate from dynamic routing service: {:?}",
                        e.current_context()
                    );

                    Err(error_stack::report!(
                        errors::RoutingError::SuccessRateCalculationError
                    ))
                }
            }
        };

        let events_response = routing_events_wrapper
            .construct_event_builder(
                "SuccessRateCalculator.FetchSuccessRate".to_string(),
                RoutingEngine::IntelligentRouter,
                ApiMethod::Grpc,
            )?
            .trigger_event(state, closure)
            .await?;

        let success_based_connectors: utils::CalSuccessRateEventResponse = events_response
            .response
            .ok_or(errors::RoutingError::SuccessRateCalculationError)?;

        // Need to log error case
        let mut routing_event =
            events_response
                .event
                .ok_or(errors::RoutingError::RoutingEventsError {
                    message:
                        "SR-Intelligent-Router: RoutingEvent not found in RoutingEventsResponse"
                            .to_string(),
                    status_code: 500,
                })?;

        routing_event.set_routing_approach(success_based_connectors.routing_approach.to_string());
        payment_data.set_routing_approach_in_attempt(Some(common_enums::RoutingApproach::from(
            success_based_connectors.routing_approach,
        )));

        let mut connectors = Vec::with_capacity(success_based_connectors.labels_with_score.len());
        for label_with_score in success_based_connectors.labels_with_score {
            let (connector, merchant_connector_id) = label_with_score.label
                .split_once(':')
                .ok_or(errors::RoutingError::InvalidSuccessBasedConnectorLabel(label_with_score.label.to_string()))
                .attach_printable(
                    "unable to split connector_name and mca_id from the label obtained by the dynamic routing service",
                )?;
            connectors.push(api_routing::RoutableConnectorChoice {
                choice_kind: api_routing::RoutableChoiceKind::FullStruct,
                connector: common_enums::RoutableConnectors::from_str(connector)
                    .change_context(errors::RoutingError::GenericConversionError {
                        from: "String".to_string(),
                        to: "RoutableConnectors".to_string(),
                    })
                    .attach_printable("unable to convert String to RoutableConnectors")?,
                merchant_connector_id: Some(
                    common_utils::id_type::MerchantConnectorAccountId::wrap(
                        merchant_connector_id.to_string(),
                    )
                    .change_context(errors::RoutingError::GenericConversionError {
                        from: "String".to_string(),
                        to: "MerchantConnectorAccountId".to_string(),
                    })
                    .attach_printable("unable to convert MerchantConnectorAccountId from string")?,
                ),
            });
        }
        logger::debug!(success_based_routing_connectors=?connectors);

        routing_event.set_status_code(200);
        routing_event.set_routable_connectors(connectors.clone());
        state.event_handler().log_event(&routing_event);
        Ok(connectors)
    } else {
        Ok(routable_connectors)
    }
}


pub struct SessionRoutingChoice {
    pub connector: api_oss::ConnectorData,
    pub payment_method_type: api_enums::PaymentMethodType,
}


impl Cybersource {
    pub fn generate_digest(&self, payload: &[u8]) -> String {
        let payload_digest = digest::digest(&digest::SHA256, payload);
        consts::BASE64_ENGINE.encode(payload_digest)
    }

    pub fn generate_signature(
        &self,
        auth: cybersource::CybersourceAuthType,
        host: String,
        resource: &str,
        payload: &String,
        date: OffsetDateTime,
        http_method: Method,
    ) -> CustomResult<String, errors::ConnectorError> {
        let cybersource::CybersourceAuthType {
            api_key,
            merchant_account,
            api_secret,
        } = auth;
        let is_post_method = matches!(http_method, Method::Post);
        let is_patch_method = matches!(http_method, Method::Patch);
        let is_delete_method = matches!(http_method, Method::Delete);
        let digest_str = if is_post_method || is_patch_method {
            "digest "
        } else {
            ""
        };
        let headers = format!("host date (request-target) {digest_str}v-c-merchant-id");
        let request_target = if is_post_method {
            format!("(request-target): post {resource}\ndigest: SHA-256={payload}\n")
        } else if is_patch_method {
            format!("(request-target): patch {resource}\ndigest: SHA-256={payload}\n")
        } else if is_delete_method {
            format!("(request-target): delete {resource}\n")
        } else {
            format!("(request-target): get {resource}\n")
        };
        let signature_string = format!(
            "host: {host}\ndate: {date}\n{request_target}v-c-merchant-id: {}",
            merchant_account.peek()
        );
        let key_value = consts::BASE64_ENGINE
            .decode(api_secret.expose())
            .change_context(errors::ConnectorError::InvalidConnectorConfig {
                config: "connector_account_details.api_secret",
            })?;
        let key = hmac::Key::new(hmac::HMAC_SHA256, &key_value);
        let signature_value =
            consts::BASE64_ENGINE.encode(hmac::sign(&key, signature_string.as_bytes()).as_ref());
        let signature_header = format!(
            r#"keyid="{}", algorithm="HmacSHA256", headers="{headers}", signature="{signature_value}""#,
            api_key.peek()
        );

        Ok(signature_header)
    }
}


pub struct Verify;


pub struct AciCaptureRequest {
    #[serde(flatten)]
    pub txn_details: TransactionDetails,
}


pub async fn fetch_disputes_from_connector(
    state: SessionState,
    merchant_context: domain::MerchantContext,
    merchant_connector_id: common_utils::id_type::MerchantConnectorAccountId,
    req: FetchDisputesRequestData,
) -> RouterResponse<FetchDisputesResponse> {
    let db = &*state.store;
    let key_manager_state = &(&state).into();
    let merchant_id = merchant_context.get_merchant_account().get_id();
    let merchant_connector_account = db
        .find_by_merchant_connector_account_merchant_id_merchant_connector_id(
            key_manager_state,
            merchant_id,
            &merchant_connector_id,
            merchant_context.get_merchant_key_store(),
        )
        .await
        .to_not_found_response(errors::ApiErrorResponse::MerchantConnectorAccountNotFound {
            id: merchant_connector_id.get_string_repr().to_string(),
        })?;
    let connector_name = merchant_connector_account.connector_name.clone();
    let connector_data = api::ConnectorData::get_connector_by_name(
        &state.conf.connectors,
        &connector_name,
        api::GetToken::Connector,
        Some(merchant_connector_id.clone()),
    )?;
    let connector_integration: services::BoxedDisputeConnectorIntegrationInterface<
        api::Fetch,
        FetchDisputesRequestData,
        FetchDisputesResponse,
    > = connector_data.connector.get_connector_integration();

    let router_data =
        core_utils::construct_dispute_list_router_data(&state, merchant_connector_account, req)
            .await?;

    let response = services::execute_connector_processing_step(
        &state,
        connector_integration,
        &router_data,
        payments::CallConnectorAction::Trigger,
        None,
        None,
    )
    .await
    .to_dispute_failed_response()
    .attach_printable("Failed while calling accept dispute connector api")?;
    let fetch_dispute_response =
        response
            .response
            .map_err(|err| errors::ApiErrorResponse::ExternalConnectorError {
                code: err.code,
                message: err.message,
                connector: connector_name.clone(),
                status_code: err.status_code,
                reason: err.reason,
            })?;

    for dispute in &fetch_dispute_response {
        // check if payment already exist
        let payment_attempt = webhooks::incoming::get_payment_attempt_from_object_reference_id(
            &state,
            dispute.object_reference_id.clone(),
            &merchant_context,
        )
        .await;

        if payment_attempt.is_ok() {
            let schedule_time = process_dispute::get_sync_process_schedule_time(
                &*state.store,
                &connector_name,
                merchant_id,
                0,
            )
            .await
            .change_context(errors::ApiErrorResponse::InternalServerError)
            .attach_printable("Failed while getting process schedule time")?;

            let response = add_process_dispute_task_to_pt(
                db,
                &connector_name,
                dispute,
                merchant_id.clone(),
                schedule_time,
            )
            .await;

            match response {
                Err(report)
                    if report
                        .downcast_ref::<errors::StorageError>()
                        .is_some_and(|error| {
                            matches!(error, errors::StorageError::DuplicateValue { .. })
                        }) =>
                {
                    Ok(())
                }
                Ok(_) => Ok(()),
                Err(_) => Err(errors::ApiErrorResponse::InternalServerError)
                    .attach_printable("Failed while adding task to process tracker"),
            }?;
        } else {
            router_env::logger::info!("Disputed payment does not exist in our records");
        }
    }

    Ok(services::ApplicationResponse::Json(fetch_dispute_response))
}


pub fn update_enabled_features(
        &mut self,
        algo_type: DynamicRoutingType,
        feature_to_enable: DynamicRoutingFeatures,
    ) {
        match algo_type {
            DynamicRoutingType::SuccessRateBasedRouting => {
                self.success_based_algorithm
                    .as_mut()
                    .map(|algo| algo.enabled_feature = feature_to_enable);
            }
            DynamicRoutingType::EliminationRouting => {
                self.elimination_routing_algorithm
                    .as_mut()
                    .map(|algo| algo.enabled_feature = feature_to_enable);
            }
            DynamicRoutingType::ContractBasedRouting => {
                self.contract_based_routing
                    .as_mut()
                    .map(|algo| algo.enabled_feature = feature_to_enable);
            }
        }
    }


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


pub struct GocardlessMandateRequest {
    mandates: Mandate,
}


pub struct DigitalvirgoPaymentsRequest {
    amount: FloatMajorUnit,
    amount_surcharge: Option<FloatMajorUnit>,
    client_uid: Option<String>,
    msisdn: String,
    product_name: String,
    description: Option<String>,
    partner_transaction_id: String,
}


impl super::payments::metrics::PaymentMetricAnalytics for SqlxClient {}

impl super::payments::metrics::PaymentMetricAnalytics for for SqlxClient


Documentation: api-reference/v2/payment-method-session/payment-method-session--retrieve.mdx
# Type: Doc File

---
openapi: get /v2/payment-method-sessions/{id}
---


impl PartialEq for RoutableConnectorChoice {
    fn eq(&self, other: &Self) -> bool {
        self.connector.eq(&other.connector)
            && self.merchant_connector_id.eq(&other.merchant_connector_id)
    }
}

impl PartialEq for for RoutableConnectorChoice


pub async fn get_role_info<A>(state: &A, token: &AuthToken) -> RouterResult<roles::RoleInfo>
where
    A: SessionStateInfo + Sync,
{
    if let Some(role_info) = roles::predefined_roles::PREDEFINED_ROLES.get(token.role_id.as_str()) {
        return Ok(role_info.clone());
    }

    if let Ok(role_info) = get_role_info_from_cache(state, &token.role_id)
        .await
        .map_err(|e| logger::error!("Failed to get permissions from cache {e:?}"))
    {
        return Ok(role_info.clone());
    }

    let role_info = get_role_info_from_db(
        state,
        &token.role_id,
        &token.org_id,
        token
            .tenant_id
            .as_ref()
            .unwrap_or(&state.session_state().tenant.tenant_id),
    )
    .await?;

    let token_expiry =
        i64::try_from(token.exp).change_context(ApiErrorResponse::InternalServerError)?;
    let cache_ttl = token_expiry - common_utils::date_time::now_unix_timestamp();

    if cache_ttl > 0 {
        set_role_info_in_cache(state, &token.role_id, &role_info, cache_ttl)
            .await
            .map_err(|e| logger::error!("Failed to set role info in cache {e:?}"))
            .ok();
    }
    Ok(role_info)
}


impl ConnectorValidation for Affirm {
    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(())
    }
}


pub fn get_payment_routing_algorithm(
        &self,
    ) -> CustomResult<
        Option<api_models::routing::RoutingAlgorithmRef>,
        api_error_response::ApiErrorResponse,
    > {
        self.routing_algorithm
            .clone()
            .map(|val| {
                val.parse_value::<api_models::routing::RoutingAlgorithmRef>("RoutingAlgorithmRef")
            })
            .transpose()
            .change_context(api_error_response::ApiErrorResponse::InternalServerError)
            .attach_printable("unable to deserialize routing algorithm ref from merchant account")
    }


impl api::Refund for Elavon {}


pub struct PaymentIntentCreate;


pub struct GetActivePaymentsMetricRequest {
    #[serde(default)]
    pub metrics: HashSet<ActivePaymentsMetrics>,
    pub time_range: TimeRange,
}


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

impl ToTokens for for OperationsEnumMeta


pub struct StripeConnectRecipientAccountCreateResponse {
    id: String,
}


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


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


impl<'a> KafkaPaymentAttempt<'a> {
    pub fn from_storage(attempt: &'a PaymentAttempt) -> Self {
        use masking::PeekInterface;
        let PaymentAttempt {
            payment_id,
            merchant_id,
            amount_details,
            status,
            connector,
            error,
            authentication_type,
            created_at,
            modified_at,
            last_synced,
            cancellation_reason,
            browser_info,
            payment_token,
            connector_metadata,
            payment_experience,
            payment_method_data,
            routing_result,
            preprocessing_step_id,
            multiple_capture_count,
            connector_response_reference_id,
            updated_by,
            redirection_data,
            encoded_data,
            merchant_connector_id,
            external_three_ds_authentication_attempted,
            authentication_connector,
            authentication_id,
            fingerprint_id,
            client_source,
            client_version,
            customer_acceptance,
            profile_id,
            organization_id,
            payment_method_type,
            payment_method_id,
            connector_payment_id,
            payment_method_subtype,
            authentication_applied,
            external_reference_id,
            payment_method_billing_address,
            id,
            connector_token_details,
            card_discovery,
            charges,
            feature_metadata,
            processor_merchant_id,
            created_by,
            connector_request_reference_id,
            network_transaction_id: _,
        } = attempt;

        let (connector_payment_id, connector_payment_data) = connector_payment_id
            .clone()
            .map(types::ConnectorTransactionId::form_id_and_data)
            .map(|(txn_id, txn_data)| (Some(txn_id), txn_data))
            .unwrap_or((None, None));

        Self {
            payment_id,
            merchant_id,
            attempt_id: id,
            status: *status,
            amount: amount_details.get_net_amount(),
            connector: connector.as_ref(),
            error_message: error.as_ref().map(|error_details| &error_details.message),
            surcharge_amount: amount_details.get_surcharge_amount(),
            tax_amount: amount_details.get_tax_on_surcharge(),
            payment_method_id: payment_method_id.as_ref(),
            payment_method: *payment_method_type,
            connector_transaction_id: connector_response_reference_id.as_ref(),
            authentication_type: *authentication_type,
            created_at: created_at.assume_utc(),
            modified_at: modified_at.assume_utc(),
            last_synced: last_synced.map(|i| i.assume_utc()),
            cancellation_reason: cancellation_reason.as_ref(),
            amount_to_capture: amount_details.get_amount_to_capture(),
            browser_info: browser_info.as_ref(),
            error_code: error.as_ref().map(|error_details| &error_details.code),
            connector_metadata: connector_metadata.as_ref().map(|v| v.peek().to_string()),
            payment_experience: payment_experience.as_ref(),
            payment_method_type: payment_method_subtype,
            payment_method_data: payment_method_data.as_ref().map(|v| v.peek().to_string()),
            error_reason: error
                .as_ref()
                .and_then(|error_details| error_details.reason.as_ref()),
            multiple_capture_count: *multiple_capture_count,
            amount_capturable: amount_details.get_amount_capturable(),
            merchant_connector_id: merchant_connector_id.as_ref(),
            net_amount: amount_details.get_net_amount(),
            unified_code: error
                .as_ref()
                .and_then(|error_details| error_details.unified_code.as_ref()),
            unified_message: error
                .as_ref()
                .and_then(|error_details| error_details.unified_message.as_ref()),
            client_source: client_source.as_ref(),
            client_version: client_version.as_ref(),
            profile_id,
            organization_id,
            card_network: payment_method_data
                .as_ref()
                .map(|data| data.peek())
                .and_then(|data| data.as_object())
                .and_then(|pm| pm.get("card"))
                .and_then(|data| data.as_object())
                .and_then(|card| card.get("card_network"))
                .and_then(|network| network.as_str())
                .map(|network| network.to_string()),
            card_discovery: card_discovery.map(|discovery| discovery.to_string()),
            payment_token: payment_token.clone(),
            preprocessing_step_id: preprocessing_step_id.clone(),
            connector_response_reference_id: connector_response_reference_id.clone(),
            updated_by,
            encoded_data: encoded_data.as_ref(),
            external_three_ds_authentication_attempted: *external_three_ds_authentication_attempted,
            authentication_connector: authentication_connector.clone(),
            authentication_id: authentication_id
                .as_ref()
                .map(|id| id.get_string_repr().to_string().clone()),
            fingerprint_id: fingerprint_id.clone(),
            customer_acceptance: customer_acceptance.as_ref(),
            shipping_cost: amount_details.get_shipping_cost(),
            order_tax_amount: amount_details.get_order_tax_amount(),
            charges: charges.clone(),
            processor_merchant_id,
            created_by: created_by.as_ref(),
            payment_method_type_v2: *payment_method_type,
            connector_payment_id: connector_payment_id.as_ref().cloned(),
            payment_method_subtype: *payment_method_subtype,
            routing_result: routing_result.clone(),
            authentication_applied: *authentication_applied,
            external_reference_id: external_reference_id.clone(),
            tax_on_surcharge: amount_details.get_tax_on_surcharge(),
            payment_method_billing_address: payment_method_billing_address
                .as_ref()
                .map(|v| masking::Secret::new(v.get_inner())),
            redirection_data: redirection_data.as_ref(),
            connector_payment_data,
            connector_token_details: connector_token_details.as_ref(),
            feature_metadata: feature_metadata.as_ref(),
            network_advice_code: error
                .as_ref()
                .and_then(|details| details.network_advice_code.clone()),
            network_decline_code: error
                .as_ref()
                .and_then(|details| details.network_decline_code.clone()),
            network_error_message: error
                .as_ref()
                .and_then(|details| details.network_error_message.clone()),
            connector_request_reference_id: connector_request_reference_id.clone(),
        }
    }
}


File: crates/test_utils/tests/connectors/mollie_ui.rs

use serial_test::serial;
use thirtyfour::{prelude::*, WebDriver};

use crate::{selenium::*, tester};

struct MollieSeleniumTest;

impl SeleniumTest for MollieSeleniumTest {
    fn get_connector_name(&self) -> String {
        "mollie".to_string()
    }
}

async fn should_make_mollie_paypal_payment(web_driver: WebDriver) -> Result<(), WebDriverError> {
    let conn = MollieSeleniumTest {};
    conn.make_redirection_payment(
        web_driver,
        vec![
            Event::Trigger(Trigger::Goto(&format!("{CHECKOUT_BASE_URL}/saved/32"))),
            Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))),
            Event::Assert(Assert::IsPresent("Test profile")),
            Event::Trigger(Trigger::Click(By::Css("input[value='paid']"))),
            Event::Trigger(Trigger::Click(By::Css(
                "button[class='button form__button']",
            ))),
            Event::Assert(Assert::IsPresent("Google")),
            Event::Assert(Assert::Contains(
                Selector::QueryParamStr,
                "status=succeeded",
            )),
        ],
    )
    .await?;
    Ok(())
}

async fn should_make_mollie_sofort_payment(web_driver: WebDriver) -> Result<(), WebDriverError> {
    let conn = MollieSeleniumTest {};
    conn.make_redirection_payment(
        web_driver,
        vec![
            Event::Trigger(Trigger::Goto(&format!("{CHECKOUT_BASE_URL}/saved/29"))),
            Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))),
            Event::Assert(Assert::IsPresent("Test profile")),
            Event::Trigger(Trigger::Click(By::Css("input[value='paid']"))),
            Event::Trigger(Trigger::Click(By::Css(
                "button[class='button form__button']",
            ))),
            Event::Assert(Assert::IsPresent("Google")),
            Event::Assert(Assert::Contains(
                Selector::QueryParamStr,
                "status=succeeded",
            )),
        ],
    )
    .await?;
    Ok(())
}

async fn should_make_mollie_ideal_payment(web_driver: WebDriver) -> Result<(), WebDriverError> {
    let conn: MollieSeleniumTest = MollieSeleniumTest {};
    conn.make_redirection_payment(
        web_driver,
        vec![
            Event::Trigger(Trigger::Goto(&format!("{CHECKOUT_BASE_URL}/saved/36"))),
            Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))),
            Event::Assert(Assert::IsPresent("Test profile")),
            Event::Trigger(Trigger::Click(By::ClassName(
                "payment-method-list--bordered",
            ))),
            Event::Assert(Assert::IsPresent("Test profile")),
            Event::Trigger(Trigger::Click(By::Css("input[value='paid']"))),
            Event::Trigger(Trigger::Click(By::Css(
                "button[class='button form__button']",
            ))),
            Event::Assert(Assert::IsPresent("succeeded")),
        ],
    )
    .await?;
    Ok(())
}

async fn should_make_mollie_eps_payment(web_driver: WebDriver) -> Result<(), WebDriverError> {
    let conn = MollieSeleniumTest {};
    conn.make_redirection_payment(
        web_driver,
        vec![
            Event::Trigger(Trigger::Goto(&format!("{CHECKOUT_BASE_URL}/saved/38"))),
            Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))),
            Event::Assert(Assert::IsPresent("Test profile")),
            Event::Trigger(Trigger::Click(By::Css("input[value='paid']"))),
            Event::Trigger(Trigger::Click(By::Css(
                "button[class='button form__button']",
            ))),
            Event::Assert(Assert::IsPresent("Google")),
            Event::Assert(Assert::Contains(
                Selector::QueryParamStr,
                "status=succeeded",
            )),
        ],
    )
    .await?;
    Ok(())
}

async fn should_make_mollie_giropay_payment(web_driver: WebDriver) -> Result<(), WebDriverError> {
    let conn = MollieSeleniumTest {};
    conn.make_redirection_payment(
        web_driver,
        vec![
            Event::Trigger(Trigger::Goto(&format!("{CHECKOUT_BASE_URL}/saved/41"))),
            Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))),
            Event::Assert(Assert::IsPresent("Test profile")),
            Event::Trigger(Trigger::Click(By::Css("input[value='paid']"))),
            Event::Trigger(Trigger::Click(By::Css(
                "button[class='button form__button']",
            ))),
            Event::Assert(Assert::IsPresent("Google")),
            Event::Assert(Assert::Contains(
                Selector::QueryParamStr,
                "status=succeeded",
            )),
        ],
    )
    .await?;
    Ok(())
}

async fn should_make_mollie_bancontact_card_payment(c: WebDriver) -> Result<(), WebDriverError> {
    let conn = MollieSeleniumTest {};
    conn.make_redirection_payment(
        c,
        vec![
            Event::Trigger(Trigger::Goto(&format!("{CHECKOUT_BASE_URL}/saved/86"))),
            Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))),
            Event::Assert(Assert::IsPresent("Test profile")),
            Event::Trigger(Trigger::Click(By::Css("input[value='paid']"))),
            Event::Trigger(Trigger::Click(By::Css(
                "button[class='button form__button']",
            ))),
            Event::Assert(Assert::IsPresent("Google")),
            Event::Assert(Assert::Contains(
                Selector::QueryParamStr,
                "status=succeeded",
            )),
        ],
    )
    .await?;
    Ok(())
}

async fn should_make_mollie_przelewy24_payment(c: WebDriver) -> Result<(), WebDriverError> {
    let conn = MollieSeleniumTest {};
    conn.make_redirection_payment(
        c,
        vec![
            Event::Trigger(Trigger::Goto(&format!("{CHECKOUT_BASE_URL}/saved/87"))),
            Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))),
            Event::Assert(Assert::IsPresent("Test profile")),
            Event::Trigger(Trigger::Click(By::Css("input[value='paid']"))),
            Event::Trigger(Trigger::Click(By::Css(
                "button[class='button form__button']",
            ))),
            Event::Assert(Assert::IsPresent("Google")),
            Event::Assert(Assert::Contains(
                Selector::QueryParamStr,
                "status=succeeded",
            )),
        ],
    )
    .await?;
    Ok(())
}

async fn should_make_mollie_3ds_payment(web_driver: WebDriver) -> Result<(), WebDriverError> {
    let conn = MollieSeleniumTest {};
    conn.make_redirection_payment(
        web_driver,
        vec![
            Event::Trigger(Trigger::Goto(&format!("{CHECKOUT_BASE_URL}/saved/148"))),
            Event::Trigger(Trigger::Click(By::Id("card-submit-btn"))),
            Event::Assert(Assert::IsPresent("Test profile")),
            Event::Trigger(Trigger::Click(By::Css("input[value='paid']"))),
            Event::Trigger(Trigger::Click(By::Css(
                "button[class='button form__button']",
            ))),
            Event::Assert(Assert::IsPresent("succeeded")),
        ],
    )
    .await?;
    Ok(())
}

#[test]
#[serial]
fn should_make_mollie_paypal_payment_test() {
    tester!(should_make_mollie_paypal_payment);
}

#[test]
#[serial]
fn should_make_mollie_sofort_payment_test() {
    tester!(should_make_mollie_sofort_payment);
}

#[test]
#[serial]
fn should_make_mollie_ideal_payment_test() {
    tester!(should_make_mollie_ideal_payment);
}

#[test]
#[serial]
fn should_make_mollie_eps_payment_test() {
    tester!(should_make_mollie_eps_payment);
}

#[test]
#[serial]
fn should_make_mollie_giropay_payment_test() {
    tester!(should_make_mollie_giropay_payment);
}

#[test]
#[serial]
fn should_make_mollie_bancontact_card_payment_test() {
    tester!(should_make_mollie_bancontact_card_payment);
}

#[test]
#[serial]
fn should_make_mollie_przelewy24_payment_test() {
    tester!(should_make_mollie_przelewy24_payment);
}

#[test]
#[serial]
fn should_make_mollie_3ds_payment_test() {
    tester!(should_make_mollie_3ds_payment);
}


pub struct UasFlowData {
    pub authenticate_by: String,
    pub source_authentication_id: common_utils::id_type::AuthenticationId,
}


pub async fn find_by_merchant_reference_id_merchant_id(
        conn: &PgPooledConn,
        merchant_reference_id: &id_type::CustomerId,
        merchant_id: &id_type::MerchantId,
    ) -> StorageResult<Self> {
        generics::generic_find_one::<<Self as HasTable>::Table, _, _>(
            conn,
            dsl::merchant_id
                .eq(merchant_id.to_owned())
                .and(dsl::merchant_reference_id.eq(merchant_reference_id.to_owned())),
        )
        .await
    }


pub struct PaymentsVoidRequest {
    pub ssl_transaction_type: TransactionType,
    pub ssl_account_id: Secret<String>,
    pub ssl_user_id: Secret<String>,
    pub ssl_pin: Secret<String>,
    pub ssl_txn_id: String,
}


pub struct MerchantConnectorAccount {
    pub merchant_id: id_type::MerchantId,
    pub connector_name: common_enums::connector_enums::Connector,
    pub connector_account_details: Encryption,
    pub disabled: Option<bool>,
    #[diesel(deserialize_as = super::OptionalDieselArray<common_types::payment_methods::PaymentMethodsEnabled>)]
    pub payment_methods_enabled: Option<Vec<common_types::payment_methods::PaymentMethodsEnabled>>,
    pub connector_type: storage_enums::ConnectorType,
    pub metadata: Option<pii::SecretSerdeValue>,
    pub connector_label: Option<String>,
    pub created_at: time::PrimitiveDateTime,
    pub modified_at: time::PrimitiveDateTime,
    pub connector_webhook_details: Option<pii::SecretSerdeValue>,
    #[diesel(deserialize_as = super::OptionalDieselArray<pii::SecretSerdeValue>)]
    pub frm_config: Option<Vec<pii::SecretSerdeValue>>,
    #[diesel(deserialize_as = RequiredFromNullable<id_type::ProfileId>)]
    pub profile_id: id_type::ProfileId,
    #[diesel(deserialize_as = super::OptionalDieselArray<String>)]
    pub applepay_verified_domains: Option<Vec<String>>,
    pub pm_auth_config: Option<pii::SecretSerdeValue>,
    pub status: storage_enums::ConnectorStatus,
    pub additional_merchant_data: Option<Encryption>,
    pub connector_wallets_details: Option<Encryption>,
    pub version: common_enums::ApiVersion,
    pub id: id_type::MerchantConnectorAccountId,
    pub feature_metadata: Option<MerchantConnectorAccountFeatureMetadata>,
}


/// Unify the address details, giving priority to `self` when details are present in both
    pub fn unify_address_details(&self, other: Option<&Self>) -> Self {
        if let Some(other) = other {
            let (first_name, last_name) = if self
                .first_name
                .as_ref()
                .is_some_and(|first_name| !first_name.peek().trim().is_empty())
            {
                (self.first_name.clone(), self.last_name.clone())
            } else {
                (other.first_name.clone(), other.last_name.clone())
            };

            Self {
                first_name,
                last_name,
                city: self.city.clone().or(other.city.clone()),
                country: self.country.or(other.country),
                line1: self.line1.clone().or(other.line1.clone()),
                line2: self.line2.clone().or(other.line2.clone()),
                line3: self.line3.clone().or(other.line3.clone()),
                zip: self.zip.clone().or(other.zip.clone()),
                state: self.state.clone().or(other.state.clone()),
                origin_zip: self.origin_zip.clone().or(other.origin_zip.clone()),
            }
        } else {
            self.clone()
        }
    }


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

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

use super::generics;
use crate::{
    errors,
    relay::{Relay, RelayNew, RelayUpdateInternal},
    schema::relay::dsl,
    PgPooledConn, StorageResult,
};

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

impl Relay {
    pub async fn update(
        self,
        conn: &PgPooledConn,
        relay: RelayUpdateInternal,
    ) -> StorageResult<Self> {
        match generics::generic_update_with_unique_predicate_get_result::<
            <Self as HasTable>::Table,
            _,
            _,
            _,
        >(conn, dsl::id.eq(self.id.to_owned()), relay)
        .await
        {
            Err(error) => match error.current_context() {
                errors::DatabaseError::NoFieldsToUpdate => Ok(self),
                _ => Err(error),
            },
            result => result,
        }
    }

    pub async fn find_by_id(
        conn: &PgPooledConn,
        id: &common_utils::id_type::RelayId,
    ) -> StorageResult<Self> {
        generics::generic_find_one::<<Self as HasTable>::Table, _, _>(
            conn,
            dsl::id.eq(id.to_owned()),
        )
        .await
    }

    pub async fn find_by_profile_id_connector_reference_id(
        conn: &PgPooledConn,
        profile_id: &common_utils::id_type::ProfileId,
        connector_reference_id: &str,
    ) -> StorageResult<Self> {
        generics::generic_find_one::<<Self as HasTable>::Table, _, _>(
            conn,
            dsl::profile_id
                .eq(profile_id.to_owned())
                .and(dsl::connector_reference_id.eq(connector_reference_id.to_owned())),
        )
        .await
    }
}


pub struct ForteCancelResponse {
    pub transaction_id: String,
    pub location_id: Secret<String>,
    pub action: String,
    pub authorization_code: String,
    pub entered_by: String,
    pub response: CancelResponseStatus,
}


impl api::PaymentAuthorize for Coingate {}

impl api::PaymentAuthorize for for Coingate


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


pub async fn list_user_authentication_methods_for_auth_id(
        conn: &PgPooledConn,
        auth_id: &str,
    ) -> StorageResult<Vec<Self>> {
        generics::generic_filter::<<Self as HasTable>::Table, _, _, _>(
            conn,
            dsl::auth_id.eq(auth_id.to_owned()),
            None,
            None,
            Some(dsl::last_modified_at.asc()),
        )
        .await
    }


impl api::PaymentSession for Inespay {}

impl api::PaymentSession for for Inespay


impl KafkaStore {
    pub async fn new(
        store: Store,
        mut kafka_producer: KafkaProducer,
        tenant_id: TenantID,
        tenant_config: &dyn TenantConfig,
    ) -> Self {
        kafka_producer.set_tenancy(tenant_config);
        Self {
            kafka_producer,
            diesel_store: store,
            tenant_id,
        }
    }
}


pub struct ActivePaymentsMetricRow {
    pub count: Option<i64>,
}


pub struct OrderInformationWithBill {
    amount_details: Amount,
    bill_to: Option<BillTo>,
}


impl Deref for CardExpirationMonth {
    type Target = StrongSecret<u8>;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}


pub fn into_inner(self) -> String {
        self.0
    }


pub struct MandateData {
    pub mandate_acceptance_type: Option<enums::MandateAcceptanceType>,
    pub mandate_type: Option<enums::MandateType>,
    pub payment_type: Option<enums::PaymentType>,
}


pub struct BankPaymentInformationResponse {
    pub status: TrustpayBankRedirectPaymentStatus,
    pub status_reason_information: Option<StatusReasonInformation>,
    pub references: ReferencesResponse,
    pub amount: WebhookAmount,
}


pub async fn check_if_already_exists_in_db(&self, state: SessionState) -> UserResult<()> {
        if state
            .global_store
            .find_user_by_email(&self.get_email())
            .await
            .is_ok()
        {
            return Err(report!(UserErrors::UserExists));
        }
        Ok(())
    }


Documentation: crates/router_env/README.md
# Type: Doc File

# router_env

Environment of payment router: logger, basic config, its environment awareness.

## Example

```rust
use router_env::logger;
use tracing::{self, instrument};

#[instrument]
pub fn sample() -> () {
    logger::log!(
        logger::Level::INFO,
        payment_id = 8565654,
        payment_attempt_id = 596456465,
        merchant_id = 954865,
        tag = ?logger::Tag::ApiIncomingRequest,
        category = ?logger::Category::Api,
        flow = "some_flow",
        session_id = "some_session",
    );
}
```


pub async fn form_payment_link_data(
    state: &SessionState,
    merchant_context: domain::MerchantContext,
    merchant_id: common_utils::id_type::MerchantId,
    payment_id: common_utils::id_type::PaymentId,
) -> RouterResult<(PaymentLink, PaymentLinkData, PaymentLinkConfig)> {
    let db = &*state.store;
    let key_manager_state = &state.into();

    let payment_intent = db
        .find_payment_intent_by_payment_id_merchant_id(
            &(state).into(),
            &payment_id,
            &merchant_id,
            merchant_context.get_merchant_key_store(),
            merchant_context.get_merchant_account().storage_scheme,
        )
        .await
        .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?;

    let payment_link_id = payment_intent
        .payment_link_id
        .get_required_value("payment_link_id")
        .change_context(errors::ApiErrorResponse::PaymentLinkNotFound)?;

    let merchant_name_from_merchant_account = merchant_context
        .get_merchant_account()
        .merchant_name
        .clone()
        .map(|merchant_name| merchant_name.into_inner().peek().to_owned())
        .unwrap_or_default();

    let payment_link = db
        .find_payment_link_by_payment_link_id(&payment_link_id)
        .await
        .to_not_found_response(errors::ApiErrorResponse::PaymentLinkNotFound)?;

    let payment_link_config =
        if let Some(pl_config_value) = payment_link.payment_link_config.clone() {
            extract_payment_link_config(pl_config_value)?
        } else {
            PaymentLinkConfig {
                theme: DEFAULT_BACKGROUND_COLOR.to_string(),
                logo: DEFAULT_MERCHANT_LOGO.to_string(),
                seller_name: merchant_name_from_merchant_account,
                sdk_layout: DEFAULT_SDK_LAYOUT.to_owned(),
                display_sdk_only: DEFAULT_DISPLAY_SDK_ONLY,
                enabled_saved_payment_method: DEFAULT_ENABLE_SAVED_PAYMENT_METHOD,
                hide_card_nickname_field: DEFAULT_HIDE_CARD_NICKNAME_FIELD,
                show_card_form_by_default: DEFAULT_SHOW_CARD_FORM,
                allowed_domains: DEFAULT_ALLOWED_DOMAINS,
                transaction_details: None,
                background_image: None,
                details_layout: None,
                branding_visibility: None,
                payment_button_text: None,
                custom_message_for_card_terms: None,
                payment_button_colour: None,
                skip_status_screen: None,
                background_colour: None,
                payment_button_text_colour: None,
                sdk_ui_rules: None,
                payment_link_ui_rules: None,
                enable_button_only_on_form_ready: DEFAULT_ENABLE_BUTTON_ONLY_ON_FORM_READY,
                payment_form_header_text: None,
                payment_form_label_type: None,
                show_card_terms: None,
                is_setup_mandate_flow: None,
                color_icon_card_cvc_error: None,
            }
        };

    let profile_id = payment_link
        .profile_id
        .clone()
        .or(payment_intent.profile_id)
        .ok_or(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("Profile id missing in payment link and payment intent")?;

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

    let return_url = if let Some(payment_create_return_url) = payment_intent.return_url.clone() {
        payment_create_return_url
    } else {
        business_profile
            .return_url
            .ok_or(errors::ApiErrorResponse::MissingRequiredField {
                field_name: "return_url",
            })?
    };

    let (currency, client_secret) = validate_sdk_requirements(
        payment_intent.currency,
        payment_intent.client_secret.clone(),
    )?;

    let required_conversion_type = StringMajorUnitForCore;

    let amount = required_conversion_type
        .convert(payment_intent.amount, currency)
        .change_context(errors::ApiErrorResponse::AmountConversionFailed {
            amount_type: "StringMajorUnit",
        })?;

    let order_details = validate_order_details(payment_intent.order_details.clone(), currency)?;

    let session_expiry = payment_link.fulfilment_time.unwrap_or_else(|| {
        payment_intent
            .created_at
            .saturating_add(time::Duration::seconds(DEFAULT_SESSION_EXPIRY))
    });

    // converting first letter of merchant name to upperCase
    let merchant_name = capitalize_first_char(&payment_link_config.seller_name);
    let payment_link_status = check_payment_link_status(session_expiry);

    let is_payment_link_terminal_state = check_payment_link_invalid_conditions(
        payment_intent.status,
        &[
            storage_enums::IntentStatus::Cancelled,
            storage_enums::IntentStatus::Failed,
            storage_enums::IntentStatus::Processing,
            storage_enums::IntentStatus::RequiresCapture,
            storage_enums::IntentStatus::RequiresMerchantAction,
            storage_enums::IntentStatus::Succeeded,
            storage_enums::IntentStatus::PartiallyCaptured,
            storage_enums::IntentStatus::RequiresCustomerAction,
        ],
    );

    let attempt_id = payment_intent.active_attempt.get_id().clone();
    let payment_attempt = db
        .find_payment_attempt_by_payment_id_merchant_id_attempt_id(
            &payment_intent.payment_id,
            &merchant_id,
            &attempt_id.clone(),
            merchant_context.get_merchant_account().storage_scheme,
        )
        .await
        .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?;
    if is_payment_link_terminal_state
        || payment_link_status == api_models::payments::PaymentLinkStatus::Expired
    {
        let status = match payment_link_status {
            api_models::payments::PaymentLinkStatus::Active => {
                logger::info!("displaying status page as the requested payment link has reached terminal state with payment status as {:?}", payment_intent.status);
                PaymentLinkStatusWrap::IntentStatus(payment_intent.status)
            }
            api_models::payments::PaymentLinkStatus::Expired => {
                if is_payment_link_terminal_state {
                    logger::info!("displaying status page as the requested payment link has reached terminal state with payment status as {:?}", payment_intent.status);
                    PaymentLinkStatusWrap::IntentStatus(payment_intent.status)
                } else {
                    logger::info!(
                        "displaying status page as the requested payment link has expired"
                    );
                    PaymentLinkStatusWrap::PaymentLinkStatus(
                        api_models::payments::PaymentLinkStatus::Expired,
                    )
                }
            }
        };

        let attempt_id = payment_intent.active_attempt.get_id().clone();
        let payment_attempt = db
            .find_payment_attempt_by_payment_id_merchant_id_attempt_id(
                &payment_intent.payment_id,
                &merchant_id,
                &attempt_id.clone(),
                merchant_context.get_merchant_account().storage_scheme,
            )
            .await
            .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?;
        let payment_details = api_models::payments::PaymentLinkStatusDetails {
            amount,
            currency,
            payment_id: payment_intent.payment_id,
            merchant_name,
            merchant_logo: payment_link_config.logo.clone(),
            created: payment_link.created_at,
            status,
            error_code: payment_attempt.error_code,
            error_message: payment_attempt.error_message,
            redirect: false,
            theme: payment_link_config.theme.clone(),
            return_url: return_url.clone(),
            locale: Some(state.clone().locale),
            transaction_details: payment_link_config.transaction_details.clone(),
            unified_code: payment_attempt.unified_code,
            unified_message: payment_attempt.unified_message,
            capture_method: payment_attempt.capture_method,
            setup_future_usage_applied: payment_attempt.setup_future_usage_applied,
        };

        return Ok((
            payment_link,
            PaymentLinkData::PaymentLinkStatusDetails(Box::new(payment_details)),
            payment_link_config,
        ));
    };

    let payment_link_details = api_models::payments::PaymentLinkDetails {
        amount,
        currency,
        payment_id: payment_intent.payment_id,
        merchant_name,
        order_details,
        return_url,
        session_expiry,
        pub_key: merchant_context
            .get_merchant_account()
            .publishable_key
            .to_owned(),
        client_secret,
        merchant_logo: payment_link_config.logo.clone(),
        max_items_visible_after_collapse: 3,
        theme: payment_link_config.theme.clone(),
        merchant_description: payment_intent.description,
        sdk_layout: payment_link_config.sdk_layout.clone(),
        display_sdk_only: payment_link_config.display_sdk_only,
        hide_card_nickname_field: payment_link_config.hide_card_nickname_field,
        show_card_form_by_default: payment_link_config.show_card_form_by_default,
        locale: Some(state.clone().locale),
        transaction_details: payment_link_config.transaction_details.clone(),
        background_image: payment_link_config.background_image.clone(),
        details_layout: payment_link_config.details_layout,
        branding_visibility: payment_link_config.branding_visibility,
        payment_button_text: payment_link_config.payment_button_text.clone(),
        custom_message_for_card_terms: payment_link_config.custom_message_for_card_terms.clone(),
        payment_button_colour: payment_link_config.payment_button_colour.clone(),
        skip_status_screen: payment_link_config.skip_status_screen,
        background_colour: payment_link_config.background_colour.clone(),
        payment_button_text_colour: payment_link_config.payment_button_text_colour.clone(),
        sdk_ui_rules: payment_link_config.sdk_ui_rules.clone(),
        status: payment_intent.status,
        enable_button_only_on_form_ready: payment_link_config.enable_button_only_on_form_ready,
        payment_form_header_text: payment_link_config.payment_form_header_text.clone(),
        payment_form_label_type: payment_link_config.payment_form_label_type,
        show_card_terms: payment_link_config.show_card_terms,
        is_setup_mandate_flow: payment_link_config.is_setup_mandate_flow,
        color_icon_card_cvc_error: payment_link_config.color_icon_card_cvc_error.clone(),
        capture_method: payment_attempt.capture_method,
        setup_future_usage_applied: payment_attempt.setup_future_usage_applied,
    };

    Ok((
        payment_link,
        PaymentLinkData::PaymentLinkDetails(Box::new(payment_link_details)),
        payment_link_config,
    ))
}


impl Mask for Secret<String> {
    type Output = String;
    fn into_masked(self) -> Maskable<Self::Output> {
        Maskable::new_masked(self)
    }
}


pub struct CardPaymentInformation {
    card: Card,
}


impl<'a, K, V> Iterator for Iter<'a, K, V>
where
    K: EntityId,
{
    type Item = (K, &'a V);

    fn next(&mut self) -> Option<Self::Item> {
        self.inner.next().map(|(id, val)| (K::with_id(id), val))
    }
}


impl api::ConnectorAccessToken for Breadpay {}

impl api::ConnectorAccessToken for for Breadpay


pub struct ItaubankPaymentsRequest {
    valor: PixPaymentValue,  // amount
    chave: Secret<String>,   // pix-key
    devedor: ItaubankDebtor, // debtor
}


impl api::RefundSync for Bamboraapac {}

impl api::RefundSync for for Bamboraapac


impl RoutableConnectorChoiceWithBucketName {
    pub fn new(routable_connector_choice: RoutableConnectorChoice, bucket_name: String) -> Self {
        Self {
            routable_connector_choice,
            bucket_name,
        }
    }
}


pub struct NuvieAmountDetails {
    total_tax: Option<StringMajorUnit>,
}


impl<K, V> fmt::Debug for DenseMap<K, V>
where
    K: EntityId + fmt::Debug,
    V: fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_map().entries(self.iter()).finish()
    }
}


pub struct PlaidBankAccountCredentialsNumbers {
    pub ach: Vec<PlaidBankAccountCredentialsACH>,
    pub eft: Vec<PlaidBankAccountCredentialsEFT>,
    pub international: Vec<PlaidBankAccountCredentialsInternational>,
    pub bacs: Vec<PlaidBankAccountCredentialsBacs>,
}


pub struct Shift4PaymentsRequest {
    amount: MinorUnit,
    currency: enums::Currency,
    captured: bool,
    metadata: Option<serde_json::Value>,
    #[serde(flatten)]
    payment_method: Shift4PaymentMethod,
}


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

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

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

impl ConnectorSpecifications for for Checkout


impl Capturable for PaymentsAuthorizeData {
    fn get_captured_amount<F>(
        &self,
        amount_captured: Option<i64>,
        payment_data: &PaymentData<F>,
    ) -> Option<i64>
    where
        F: Clone,
    {
        amount_captured.or(Some(
            payment_data
                .payment_attempt
                .get_total_amount()
                .get_amount_as_i64(),
        ))
    }

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

impl Capturable for for PaymentsAuthorizeData


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

impl events::ApiEventMetric for for SurchargeDecisionConfigReq


pub struct OpensearchTimeRange {
    #[serde(with = "common_utils::custom_serde::iso8601")]
    pub gte: PrimitiveDateTime,
    #[serde(default, with = "common_utils::custom_serde::iso8601::option")]
    pub lte: Option<PrimitiveDateTime>,
}


impl api::ConnectorAccessToken for Multisafepay {}

impl api::ConnectorAccessToken for for Multisafepay


pub async fn get_parent_info_for_role(
    state: web::Data<AppState>,
    req: HttpRequest,
    path: web::Path<String>,
) -> HttpResponse {
    let flow = Flow::GetRoleV2;
    let request_payload = user_role_api::role::GetRoleRequest {
        role_id: path.into_inner(),
    };
    Box::pin(api::server_wrap(
        flow,
        state.clone(),
        &req,
        request_payload,
        |state, user, payload, _| async move {
            role_core::get_parent_info_for_role(state, user, payload).await
        },
        &auth::JWTAuth {
            permission: Permission::ProfileUserRead,
        },
        api_locking::LockAction::NotApplicable,
    ))
    .await
}


pub async fn cache_store(
        cache_conf: &redis_interface::RedisSettings,
        cache_error_signal: tokio::sync::oneshot::Sender<()


pub struct LabelInformation {
    pub label: String,
    pub target_count: u64,
    pub target_time: u64,
    #[schema(value_type = String)]
    pub mca_id: common_utils::id_type::MerchantConnectorAccountId,
}


impl ConnectorValidation for Braintree {
    fn validate_mandate_payment(
        &self,
        pm_type: Option<enums::PaymentMethodType>,
        pm_data: hyperswitch_domain_models::payment_method_data::PaymentMethodData,
    ) -> CustomResult<(), errors::ConnectorError> {
        let mandate_supported_pmd = std::collections::HashSet::from([PaymentMethodDataType::Card]);
        is_mandate_supported(pm_data, pm_type, mandate_supported_pmd, self.id())
    }
}

impl ConnectorValidation for for Braintree


impl webhooks::IncomingWebhook for Breadpay {
    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 Breadpay


pub fn new(code: String) -> Self {
        Self {
            authorization_code: Secret::new(code),
        }
    }


File: crates/api_models/src/user/dashboard_metadata.rs
 Public structs: 12

use common_enums::{CountryAlpha2, MerchantProductType};
use common_utils::{id_type, pii};
use masking::Secret;
use strum::EnumString;

#[derive(Debug, serde::Deserialize, serde::Serialize)]
pub enum SetMetaDataRequest {
    ProductionAgreement(ProductionAgreementRequest),
    SetupProcessor(SetupProcessor),
    ConfigureEndpoint,
    SetupComplete,
    FirstProcessorConnected(ProcessorConnected),
    SecondProcessorConnected(ProcessorConnected),
    ConfiguredRouting(ConfiguredRouting),
    TestPayment(TestPayment),
    IntegrationMethod(IntegrationMethod),
    ConfigurationType(ConfigurationType),
    IntegrationCompleted,
    SPRoutingConfigured(ConfiguredRouting),
    Feedback(Feedback),
    ProdIntent(ProdIntent),
    SPTestPayment,
    DownloadWoocom,
    ConfigureWoocom,
    SetupWoocomWebhook,
    IsMultipleConfiguration,
    #[serde(skip)]
    IsChangePasswordRequired,
    OnboardingSurvey(OnboardingSurvey),
    ReconStatus(ReconStatus),
}

#[derive(Debug, serde::Deserialize, serde::Serialize)]
pub struct ProductionAgreementRequest {
    pub version: String,
    #[serde(skip_deserializing)]
    pub ip_address: Option<Secret<String, pii::IpAddress>>,
}

#[derive(Debug, serde::Deserialize, serde::Serialize)]
pub struct SetupProcessor {
    pub connector_id: String,
}

#[derive(Debug, serde::Deserialize, serde::Serialize)]
pub struct ProcessorConnected {
    pub processor_id: id_type::MerchantConnectorAccountId,
    pub processor_name: String,
}

#[derive(Debug, serde::Deserialize, serde::Serialize)]
pub struct OnboardingSurvey {
    pub designation: Option<String>,
    pub about_business: Option<String>,
    pub business_website: Option<String>,
    pub hyperswitch_req: Option<String>,
    pub major_markets: Option<Vec<String>>,
    pub business_size: Option<String>,
    pub required_features: Option<Vec<String>>,
    pub required_processors: Option<Vec<String>>,
    pub planned_live_date: Option<String>,
    pub miscellaneous: Option<String>,
}

#[derive(Debug, serde::Deserialize, serde::Serialize)]
pub struct ConfiguredRouting {
    pub routing_id: String,
}

#[derive(Debug, serde::Deserialize, serde::Serialize)]
pub struct TestPayment {
    pub payment_id: id_type::PaymentId,
}

#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
pub struct IntegrationMethod {
    pub integration_type: String,
}
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
pub enum ConfigurationType {
    Single,
    Multiple,
}

#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
pub struct Feedback {
    pub email: pii::Email,
    pub description: Option<String>,
    pub rating: Option<i32>,
    pub category: Option<String>,
}
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
pub struct ProdIntent {
    pub legal_business_name: Option<String>,
    pub business_label: Option<String>,
    pub business_location: Option<CountryAlpha2>,
    pub display_name: Option<String>,
    pub poc_email: Option<Secret<String>>,
    pub business_type: Option<String>,
    pub business_identifier: Option<String>,
    pub business_website: Option<String>,
    pub poc_name: Option<Secret<String>>,
    pub poc_contact: Option<Secret<String>>,
    pub comments: Option<String>,
    pub is_completed: bool,
    #[serde(default)]
    pub product_type: MerchantProductType,
    pub business_country_name: Option<String>,
}

#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
pub struct ReconStatus {
    pub is_order_data_set: bool,
    pub is_processor_data_set: bool,
}

#[derive(Debug, serde::Deserialize, EnumString, serde::Serialize)]
pub enum GetMetaDataRequest {
    ProductionAgreement,
    SetupProcessor,
    ConfigureEndpoint,
    SetupComplete,
    FirstProcessorConnected,
    SecondProcessorConnected,
    ConfiguredRouting,
    TestPayment,
    IntegrationMethod,
    ConfigurationType,
    IntegrationCompleted,
    StripeConnected,
    PaypalConnected,
    SPRoutingConfigured,
    Feedback,
    ProdIntent,
    SPTestPayment,
    DownloadWoocom,
    ConfigureWoocom,
    SetupWoocomWebhook,
    IsMultipleConfiguration,
    IsChangePasswordRequired,
    OnboardingSurvey,
    ReconStatus,
}

#[derive(Debug, serde::Deserialize, serde::Serialize)]
#[serde(transparent)]
pub struct GetMultipleMetaDataPayload {
    pub results: Vec<GetMetaDataRequest>,
}

#[derive(Debug, serde::Deserialize, serde::Serialize)]
pub struct GetMultipleMetaDataRequest {
    pub keys: String,
}

#[derive(Debug, serde::Serialize)]
pub enum GetMetaDataResponse {
    ProductionAgreement(bool),
    SetupProcessor(Option<SetupProcessor>),
    ConfigureEndpoint(bool),
    SetupComplete(bool),
    FirstProcessorConnected(Option<ProcessorConnected>),
    SecondProcessorConnected(Option<ProcessorConnected>),
    ConfiguredRouting(Option<ConfiguredRouting>),
    TestPayment(Option<TestPayment>),
    IntegrationMethod(Option<IntegrationMethod>),
    ConfigurationType(Option<ConfigurationType>),
    IntegrationCompleted(bool),
    StripeConnected(Option<ProcessorConnected>),
    PaypalConnected(Option<ProcessorConnected>),
    SPRoutingConfigured(Option<ConfiguredRouting>),
    Feedback(Option<Feedback>),
    ProdIntent(Option<ProdIntent>),
    SPTestPayment(bool),
    DownloadWoocom(bool),
    ConfigureWoocom(bool),
    SetupWoocomWebhook(bool),
    IsMultipleConfiguration(bool),
    IsChangePasswordRequired(bool),
    OnboardingSurvey(Option<OnboardingSurvey>),
    ReconStatus(Option<ReconStatus>),
}