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

use actix_web::{web, HttpRequest, Responder};
use router_env::{instrument, tracing, Flow};

use crate::{
    core::{api_locking, webhooks::webhook_events},
    routes::AppState,
    services::{
        api,
        authentication::{self as auth, UserFromToken},
        authorization::permissions::Permission,
    },
    types::api::webhook_events::{
        EventListConstraints, EventListRequestInternal, WebhookDeliveryAttemptListRequestInternal,
        WebhookDeliveryRetryRequestInternal,
    },
};

#[instrument(skip_all, fields(flow = ?Flow::WebhookEventInitialDeliveryAttemptList))]
pub async fn list_initial_webhook_delivery_attempts(
    state: web::Data<AppState>,
    req: HttpRequest,
    path: web::Path<common_utils::id_type::MerchantId>,
    json_payload: web::Json<EventListConstraints>,
) -> impl Responder {
    let flow = Flow::WebhookEventInitialDeliveryAttemptList;
    let merchant_id = path.into_inner();
    let constraints = json_payload.into_inner();

    let request_internal = EventListRequestInternal {
        merchant_id: merchant_id.clone(),
        constraints,
    };

    Box::pin(api::server_wrap(
        flow,
        state,
        &req,
        request_internal,
        |state, _, request_internal, _| {
            webhook_events::list_initial_delivery_attempts(
                state,
                request_internal.merchant_id,
                request_internal.constraints,
            )
        },
        auth::auth_type(
            &auth::AdminApiAuth,
            &auth::JWTAuthMerchantFromRoute {
                merchant_id,
                required_permission: Permission::MerchantWebhookEventRead,
            },
            req.headers(),
        ),
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

#[instrument(skip_all, fields(flow = ?Flow::WebhookEventInitialDeliveryAttemptList))]
pub async fn list_initial_webhook_delivery_attempts_with_jwtauth(
    state: web::Data<AppState>,
    req: HttpRequest,
    json_payload: web::Json<EventListConstraints>,
) -> impl Responder {
    let flow = Flow::WebhookEventInitialDeliveryAttemptList;
    let constraints = json_payload.into_inner();

    let request_internal = EventListRequestInternal {
        merchant_id: common_utils::id_type::MerchantId::default(),
        constraints,
    };

    Box::pin(api::server_wrap(
        flow,
        state,
        &req,
        request_internal,
        |state, auth: UserFromToken, mut request_internal, _| {
            let merchant_id = auth.merchant_id;
            let profile_id = auth.profile_id;

            request_internal.merchant_id = merchant_id;
            request_internal.constraints.profile_id = Some(profile_id);

            webhook_events::list_initial_delivery_attempts(
                state,
                request_internal.merchant_id,
                request_internal.constraints,
            )
        },
        &auth::JWTAuth {
            permission: Permission::ProfileWebhookEventRead,
        },
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

#[instrument(skip_all, fields(flow = ?Flow::WebhookEventDeliveryAttemptList))]
pub async fn list_webhook_delivery_attempts(
    state: web::Data<AppState>,
    req: HttpRequest,
    path: web::Path<(common_utils::id_type::MerchantId, String)>,
) -> impl Responder {
    let flow = Flow::WebhookEventDeliveryAttemptList;
    let (merchant_id, initial_attempt_id) = path.into_inner();

    let request_internal = WebhookDeliveryAttemptListRequestInternal {
        merchant_id: merchant_id.clone(),
        initial_attempt_id,
    };

    Box::pin(api::server_wrap(
        flow,
        state,
        &req,
        request_internal,
        |state, _, request_internal, _| {
            webhook_events::list_delivery_attempts(
                state,
                request_internal.merchant_id,
                request_internal.initial_attempt_id,
            )
        },
        auth::auth_type(
            &auth::AdminApiAuth,
            &auth::JWTAuthMerchantFromRoute {
                merchant_id,
                required_permission: Permission::MerchantWebhookEventRead,
            },
            req.headers(),
        ),
        api_locking::LockAction::NotApplicable,
    ))
    .await
}

#[instrument(skip_all, fields(flow = ?Flow::WebhookEventDeliveryRetry))]
#[cfg(feature = "v1")]
pub async fn retry_webhook_delivery_attempt(
    state: web::Data<AppState>,
    req: HttpRequest,
    path: web::Path<(common_utils::id_type::MerchantId, String)>,
) -> impl Responder {
    let flow = Flow::WebhookEventDeliveryRetry;
    let (merchant_id, event_id) = path.into_inner();

    let request_internal = WebhookDeliveryRetryRequestInternal {
        merchant_id: merchant_id.clone(),
        event_id,
    };

    Box::pin(api::server_wrap(
        flow,
        state,
        &req,
        request_internal,
        |state, _, request_internal, _| {
            webhook_events::retry_delivery_attempt(
                state,
                request_internal.merchant_id,
                request_internal.event_id,
            )
        },
        auth::auth_type(
            &auth::AdminApiAuth,
            &auth::JWTAuthMerchantFromRoute {
                merchant_id,
                required_permission: Permission::MerchantWebhookEventWrite,
            },
            req.headers(),
        ),
        api_locking::LockAction::NotApplicable,
    ))
    .await
}


pub struct PaypalData {
    paypal: PaypalDetails,
    #[serde(rename = "type")]
    payment_method_type: AirwallexPaymentType,
}


pub struct DecideGatewayResponse {
    pub decided_gateway: Option<String>,
    pub gateway_priority_map: Option<serde_json::Value>,
    pub filter_wise_gateways: Option<serde_json::Value>,
    pub priority_logic_tag: Option<String>,
    pub routing_approach: Option<String>,
    pub gateway_before_evaluation: Option<String>,
    pub priority_logic_output: Option<PriorityLogicOutput>,
    pub reset_approach: Option<String>,
    pub routing_dimension: Option<String>,
    pub routing_dimension_level: Option<String>,
    pub is_scheduled_outage: Option<bool>,
    pub is_dynamic_mga_enabled: Option<bool>,
    pub gateway_mga_id_map: Option<serde_json::Value>,
}


pub struct SantanderBoletoPaymentRequest {
    pub environment: Environment,
    pub nsu_code: String,
    pub nsu_date: String,
    pub covenant_code: String,
    pub bank_number: Secret<String>,
    pub client_number: Option<id_type::CustomerId>,
    pub due_date: String,
    pub issue_date: String,
    pub currency: Option<enums::Currency>,
    pub nominal_value: StringMajorUnit,
    pub participant_code: Option<String>,
    pub payer: Payer,
    pub beneficiary: Option<Beneficiary>,
    pub document_kind: BoletoDocumentKind,
    pub discount: Option<Discount>,
    pub fine_percentage: Option<String>,
    pub fine_quantity_days: Option<String>,
    pub interest_percentage: Option<String>,
    pub deduction_value: Option<FloatMajorUnit>,
    pub protest_type: Option<ProtestType>,
    pub protest_quantity_days: Option<i64>,
    pub write_off_quantity_days: Option<String>,
    pub payment_type: PaymentType,
    pub parcels_quantity: Option<i64>,
    pub value_type: Option<String>,
    pub min_value_or_percentage: Option<f64>,
    pub max_value_or_percentage: Option<f64>,
    pub iof_percentage: Option<f64>,
    pub sharing: Option<Sharing>,
    pub key: Option<Key>,
    pub tx_id: Option<String>,
    pub messages: Option<Vec<String>>,
}


pub struct AdyenBalanceAccount {
    description: String,
    id: String,
}


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


/// Insert a new payment token reference for the given connector_id
    pub fn insert_payment_token_reference_record(
        &mut self,
        connector_id: &common_utils::id_type::MerchantConnectorAccountId,
        record: ConnectorTokenReferenceRecord,
    ) {
        match self.payments {
            Some(ref mut payments_reference) => {
                payments_reference.insert(connector_id.clone(), record);
            }
            None => {
                let mut payments_reference = HashMap::new();
                payments_reference.insert(connector_id.clone(), record);
                self.payments = Some(PaymentsTokenReference(payments_reference));
            }
        }
    }


pub fn transform_payment_method(
        connector: Connector,
        provider: Vec<Provider>,
        payment_method: PaymentMethod,
    ) -> Vec<payment_methods::RequestPaymentMethodTypes> {
        let mut payment_method_types = Vec::new();
        for method_type in provider {
            let data = payment_methods::RequestPaymentMethodTypes {
                payment_method_type: method_type.payment_method_type,
                card_networks: None,
                minimum_amount: Some(MinorUnit::zero()),
                maximum_amount: Some(MinorUnit::new(68607706)),
                recurring_enabled: Some(true),
                installment_payment_enabled: Some(false),
                accepted_currencies: method_type.accepted_currencies,
                accepted_countries: method_type.accepted_countries,
                payment_experience: Self::get_payment_experience(
                    connector,
                    method_type.payment_method_type,
                    payment_method,
                    method_type.payment_experience,
                ),
            };
            payment_method_types.push(data)
        }
        payment_method_types
    }


pub async fn tokenize_cards(
    state: &SessionState,
    records: Vec<payment_methods_api::CardNetworkTokenizeRequest>,
    merchant_context: &domain::MerchantContext,
) -> errors::RouterResponse<Vec<payment_methods_api::CardNetworkTokenizeResponse>> {
    use futures::stream::StreamExt;

    // Process all records in parallel
    let responses = futures::stream::iter(records.into_iter())
        .map(|record| async move {
            let tokenize_request = record.data.clone();
            let customer = record.customer.clone();
            Box::pin(tokenize_card_flow(
                state,
                domain::CardNetworkTokenizeRequest::foreign_from(record),
                merchant_context,
            ))
            .await
            .unwrap_or_else(|e| {
                let err = e.current_context();
                payment_methods_api::CardNetworkTokenizeResponse {
                    tokenization_data: Some(tokenize_request),
                    error_code: Some(err.error_code()),
                    error_message: Some(err.error_message()),
                    card_tokenized: false,
                    payment_method_response: None,
                    customer: Some(customer),
                }
            })
        })
        .buffer_unordered(10)
        .collect()
        .await;

    // Return the final response
    Ok(services::ApplicationResponse::Json(responses))
}


impl api::RefundSync for Vgs {}


pub async fn verify_merchant_creds_for_applepay(
    state: SessionState,
    body: verifications::ApplepayMerchantVerificationRequest,
    merchant_id: common_utils::id_type::MerchantId,
    profile_id: Option<common_utils::id_type::ProfileId>,
) -> CustomResult<services::ApplicationResponse<ApplepayMerchantResponse>, errors::ApiErrorResponse>
{
    let applepay_merchant_configs = state.conf.applepay_merchant_configs.get_inner();

    let applepay_internal_merchant_identifier = applepay_merchant_configs
        .common_merchant_identifier
        .clone()
        .expose();
    let cert_data = applepay_merchant_configs.merchant_cert.clone();
    let key_data = applepay_merchant_configs.merchant_cert_key.clone();
    let applepay_endpoint = &applepay_merchant_configs.applepay_endpoint;

    let request_body = verifications::ApplepayMerchantVerificationConfigs {
        domain_names: body.domain_names.clone(),
        encrypt_to: applepay_internal_merchant_identifier.clone(),
        partner_internal_merchant_identifier: applepay_internal_merchant_identifier,
        partner_merchant_name: APPLEPAY_INTERNAL_MERCHANT_NAME.to_string(),
    };

    let apple_pay_merch_verification_req = services::RequestBuilder::new()
        .method(services::Method::Post)
        .url(applepay_endpoint)
        .attach_default_headers()
        .headers(vec![(
            headers::CONTENT_TYPE.to_string(),
            "application/json".to_string().into(),
        )])
        .set_body(RequestContent::Json(Box::new(request_body)))
        .add_certificate(Some(cert_data))
        .add_certificate_key(Some(key_data))
        .build();

    let response = services::call_connector_api(
        &state,
        apple_pay_merch_verification_req,
        "verify_merchant_creds_for_applepay",
    )
    .await;
    utils::log_applepay_verification_response_if_error(&response);

    let applepay_response =
        response.change_context(errors::ApiErrorResponse::InternalServerError)?;

    // Error is already logged
    match applepay_response {
        Ok(_) => {
            utils::check_existence_and_add_domain_to_db(
                &state,
                merchant_id,
                profile_id,
                body.merchant_connector_account_id.clone(),
                body.domain_names.clone(),
            )
            .await
            .change_context(errors::ApiErrorResponse::InternalServerError)?;
            Ok(services::api::ApplicationResponse::Json(
                ApplepayMerchantResponse {
                    status_message: "Applepay verification Completed".to_string(),
                },
            ))
        }
        Err(error) => {
            logger::error!(?error);
            Err(errors::ApiErrorResponse::InvalidRequestData {
                message: "Applepay verification Failed".to_string(),
            }
            .into())
        }
    }
}


pub(super) struct SerializeStructVariant<T: Serializer> {
        name: String,
        map: Map<String, Value>,
        ser: T,
    }


File: crates/hyperswitch_domain_models/src/router_flow_types/access_token_auth.rs
 Public structs: 2

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

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


impl api::PaymentSession for Checkbook {}

impl api::PaymentSession for for Checkbook


impl PaymentMethodVaultingData {
    pub fn get_card(&self) -> Option<&payment_methods::CardDetail> {
        match self {
            Self::Card(card) => Some(card),
            #[cfg(feature = "v2")]
            Self::NetworkToken(_) => None,
        }
    }
    pub fn get_payment_methods_data(&self) -> payment_method_data::PaymentMethodsData {
        match self {
            Self::Card(card) => payment_method_data::PaymentMethodsData::Card(
                payment_method_data::CardDetailsPaymentMethod::from(card.clone()),
            ),
            #[cfg(feature = "v2")]
            Self::NetworkToken(network_token) => {
                payment_method_data::PaymentMethodsData::NetworkToken(
                    payment_method_data::NetworkTokenDetailsPaymentMethod::from(
                        network_token.clone(),
                    ),
                )
            }
        }
    }
}


pub fn to_merchant_connector_info(&self, connector_label: &String) -> MerchantConnectorInfo {
        MerchantConnectorInfo {
            connector_label: connector_label.to_string(),
            merchant_connector_id: self.merchant_connector_id.clone(),
        }
    }


File: crates/router/src/services/authorization/roles/predefined_roles.rs

use std::{collections::HashMap, sync::LazyLock};

use common_enums::{EntityType, PermissionGroup, RoleScope};

use super::RoleInfo;
use crate::consts;

pub static PREDEFINED_ROLES: LazyLock<HashMap<&'static str, RoleInfo>> = LazyLock::new(|| {
    let mut roles = HashMap::new();

    // Internal Roles
    roles.insert(
        common_utils::consts::ROLE_ID_INTERNAL_ADMIN,
        RoleInfo {
            groups: vec![
                PermissionGroup::OperationsView,
                PermissionGroup::OperationsManage,
                PermissionGroup::ConnectorsView,
                PermissionGroup::ConnectorsManage,
                PermissionGroup::WorkflowsView,
                PermissionGroup::WorkflowsManage,
                PermissionGroup::AnalyticsView,
                PermissionGroup::UsersView,
                PermissionGroup::UsersManage,
                PermissionGroup::MerchantDetailsView,
                PermissionGroup::AccountView,
                PermissionGroup::MerchantDetailsManage,
                PermissionGroup::AccountManage,
                PermissionGroup::OrganizationManage,
                PermissionGroup::ReconOpsView,
                PermissionGroup::ReconOpsManage,
                PermissionGroup::ReconReportsView,
                PermissionGroup::ReconReportsManage,
            ],
            role_id: common_utils::consts::ROLE_ID_INTERNAL_ADMIN.to_string(),
            role_name: "internal_admin".to_string(),
            scope: RoleScope::Organization,
            entity_type: EntityType::Merchant,
            is_invitable: false,
            is_deletable: false,
            is_updatable: false,
            is_internal: true,
        },
    );
    roles.insert(
        common_utils::consts::ROLE_ID_INTERNAL_VIEW_ONLY_USER,
        RoleInfo {
            groups: vec![
                PermissionGroup::OperationsView,
                PermissionGroup::ConnectorsView,
                PermissionGroup::WorkflowsView,
                PermissionGroup::AnalyticsView,
                PermissionGroup::UsersView,
                PermissionGroup::MerchantDetailsView,
                PermissionGroup::AccountView,
                PermissionGroup::ReconOpsView,
                PermissionGroup::ReconReportsView,
            ],
            role_id: common_utils::consts::ROLE_ID_INTERNAL_VIEW_ONLY_USER.to_string(),
            role_name: "internal_view_only".to_string(),
            scope: RoleScope::Organization,
            entity_type: EntityType::Merchant,
            is_invitable: false,
            is_deletable: false,
            is_updatable: false,
            is_internal: true,
        },
    );
    roles.insert(
        common_utils::consts::ROLE_ID_INTERNAL_DEMO,
        RoleInfo {
            groups: vec![
                PermissionGroup::OperationsView,
                PermissionGroup::ConnectorsView,
                PermissionGroup::WorkflowsView,
                PermissionGroup::AnalyticsView,
                PermissionGroup::UsersView,
                PermissionGroup::MerchantDetailsView,
                PermissionGroup::AccountView,
                PermissionGroup::ReconOpsView,
                PermissionGroup::ReconReportsView,
                PermissionGroup::InternalManage,
            ],
            role_id: common_utils::consts::ROLE_ID_INTERNAL_DEMO.to_string(),
            role_name: "internal_demo".to_string(),
            scope: RoleScope::Organization,
            entity_type: EntityType::Merchant,
            is_invitable: false,
            is_deletable: false,
            is_updatable: false,
            is_internal: true,
        },
    );

    // Tenant Roles
    roles.insert(
        common_utils::consts::ROLE_ID_TENANT_ADMIN,
        RoleInfo {
            groups: vec![
                PermissionGroup::OperationsView,
                PermissionGroup::OperationsManage,
                PermissionGroup::ConnectorsView,
                PermissionGroup::ConnectorsManage,
                PermissionGroup::WorkflowsView,
                PermissionGroup::WorkflowsManage,
                PermissionGroup::AnalyticsView,
                PermissionGroup::UsersView,
                PermissionGroup::UsersManage,
                PermissionGroup::MerchantDetailsView,
                PermissionGroup::AccountView,
                PermissionGroup::MerchantDetailsManage,
                PermissionGroup::AccountManage,
                PermissionGroup::OrganizationManage,
                PermissionGroup::ReconOpsView,
                PermissionGroup::ReconOpsManage,
                PermissionGroup::ReconReportsView,
                PermissionGroup::ReconReportsManage,
            ],
            role_id: common_utils::consts::ROLE_ID_TENANT_ADMIN.to_string(),
            role_name: "tenant_admin".to_string(),
            scope: RoleScope::Organization,
            entity_type: EntityType::Tenant,
            is_invitable: false,
            is_deletable: false,
            is_updatable: false,
            is_internal: false,
        },
    );

    // Organization Roles
    roles.insert(
        common_utils::consts::ROLE_ID_ORGANIZATION_ADMIN,
        RoleInfo {
            groups: vec![
                PermissionGroup::OperationsView,
                PermissionGroup::OperationsManage,
                PermissionGroup::ConnectorsView,
                PermissionGroup::ConnectorsManage,
                PermissionGroup::WorkflowsView,
                PermissionGroup::WorkflowsManage,
                PermissionGroup::AnalyticsView,
                PermissionGroup::UsersView,
                PermissionGroup::UsersManage,
                PermissionGroup::MerchantDetailsView,
                PermissionGroup::AccountView,
                PermissionGroup::MerchantDetailsManage,
                PermissionGroup::AccountManage,
                PermissionGroup::OrganizationManage,
                PermissionGroup::ReconOpsView,
                PermissionGroup::ReconOpsManage,
                PermissionGroup::ReconReportsView,
                PermissionGroup::ReconReportsManage,
                PermissionGroup::ThemeView,
                PermissionGroup::ThemeManage,
            ],
            role_id: common_utils::consts::ROLE_ID_ORGANIZATION_ADMIN.to_string(),
            role_name: "organization_admin".to_string(),
            scope: RoleScope::Organization,
            entity_type: EntityType::Organization,
            is_invitable: true,
            is_deletable: true,
            is_updatable: true,
            is_internal: false,
        },
    );

    // MERCHANT ROLES
    roles.insert(
        consts::user_role::ROLE_ID_MERCHANT_ADMIN,
        RoleInfo {
            groups: vec![
                PermissionGroup::OperationsView,
                PermissionGroup::OperationsManage,
                PermissionGroup::ConnectorsView,
                PermissionGroup::ConnectorsManage,
                PermissionGroup::WorkflowsView,
                PermissionGroup::WorkflowsManage,
                PermissionGroup::AnalyticsView,
                PermissionGroup::UsersView,
                PermissionGroup::UsersManage,
                PermissionGroup::MerchantDetailsView,
                PermissionGroup::AccountView,
                PermissionGroup::MerchantDetailsManage,
                PermissionGroup::AccountManage,
                PermissionGroup::ReconOpsView,
                PermissionGroup::ReconOpsManage,
                PermissionGroup::ReconReportsView,
                PermissionGroup::ReconReportsManage,
            ],
            role_id: consts::user_role::ROLE_ID_MERCHANT_ADMIN.to_string(),
            role_name: "merchant_admin".to_string(),
            scope: RoleScope::Organization,
            entity_type: EntityType::Merchant,
            is_invitable: true,
            is_deletable: true,
            is_updatable: true,
            is_internal: false,
        },
    );
    roles.insert(
        consts::user_role::ROLE_ID_MERCHANT_VIEW_ONLY,
        RoleInfo {
            groups: vec![
                PermissionGroup::OperationsView,
                PermissionGroup::ConnectorsView,
                PermissionGroup::WorkflowsView,
                PermissionGroup::AnalyticsView,
                PermissionGroup::UsersView,
                PermissionGroup::MerchantDetailsView,
                PermissionGroup::AccountView,
                PermissionGroup::ReconOpsView,
                PermissionGroup::ReconReportsView,
            ],
            role_id: consts::user_role::ROLE_ID_MERCHANT_VIEW_ONLY.to_string(),
            role_name: "merchant_view_only".to_string(),
            scope: RoleScope::Organization,
            entity_type: EntityType::Merchant,
            is_invitable: true,
            is_deletable: true,
            is_updatable: true,
            is_internal: false,
        },
    );
    roles.insert(
        consts::user_role::ROLE_ID_MERCHANT_IAM_ADMIN,
        RoleInfo {
            groups: vec![
                PermissionGroup::OperationsView,
                PermissionGroup::AnalyticsView,
                PermissionGroup::UsersView,
                PermissionGroup::UsersManage,
                PermissionGroup::MerchantDetailsView,
                PermissionGroup::AccountView,
            ],
            role_id: consts::user_role::ROLE_ID_MERCHANT_IAM_ADMIN.to_string(),
            role_name: "merchant_iam".to_string(),
            scope: RoleScope::Organization,
            entity_type: EntityType::Merchant,
            is_invitable: true,
            is_deletable: true,
            is_updatable: true,
            is_internal: false,
        },
    );
    roles.insert(
        consts::user_role::ROLE_ID_MERCHANT_DEVELOPER,
        RoleInfo {
            groups: vec![
                PermissionGroup::OperationsView,
                PermissionGroup::ConnectorsView,
                PermissionGroup::AnalyticsView,
                PermissionGroup::UsersView,
                PermissionGroup::MerchantDetailsView,
                PermissionGroup::AccountView,
                PermissionGroup::MerchantDetailsManage,
                PermissionGroup::AccountManage,
                PermissionGroup::ReconOpsView,
                PermissionGroup::ReconReportsView,
            ],
            role_id: consts::user_role::ROLE_ID_MERCHANT_DEVELOPER.to_string(),
            role_name: "merchant_developer".to_string(),
            scope: RoleScope::Organization,
            entity_type: EntityType::Merchant,
            is_invitable: true,
            is_deletable: true,
            is_updatable: true,
            is_internal: false,
        },
    );
    roles.insert(
        consts::user_role::ROLE_ID_MERCHANT_OPERATOR,
        RoleInfo {
            groups: vec![
                PermissionGroup::OperationsView,
                PermissionGroup::OperationsManage,
                PermissionGroup::ConnectorsView,
                PermissionGroup::WorkflowsView,
                PermissionGroup::AnalyticsView,
                PermissionGroup::UsersView,
                PermissionGroup::MerchantDetailsView,
                PermissionGroup::AccountView,
                PermissionGroup::ReconOpsView,
                PermissionGroup::ReconOpsManage,
                PermissionGroup::ReconReportsView,
            ],
            role_id: consts::user_role::ROLE_ID_MERCHANT_OPERATOR.to_string(),
            role_name: "merchant_operator".to_string(),
            scope: RoleScope::Organization,
            entity_type: EntityType::Merchant,
            is_invitable: true,
            is_deletable: true,
            is_updatable: true,
            is_internal: false,
        },
    );
    roles.insert(
        consts::user_role::ROLE_ID_MERCHANT_CUSTOMER_SUPPORT,
        RoleInfo {
            groups: vec![
                PermissionGroup::OperationsView,
                PermissionGroup::AnalyticsView,
                PermissionGroup::UsersView,
                PermissionGroup::MerchantDetailsView,
                PermissionGroup::AccountView,
                PermissionGroup::ReconOpsView,
                PermissionGroup::ReconReportsView,
            ],
            role_id: consts::user_role::ROLE_ID_MERCHANT_CUSTOMER_SUPPORT.to_string(),
            role_name: "customer_support".to_string(),
            scope: RoleScope::Organization,
            entity_type: EntityType::Merchant,
            is_invitable: true,
            is_deletable: true,
            is_updatable: true,
            is_internal: false,
        },
    );

    // Profile Roles
    roles.insert(
        consts::user_role::ROLE_ID_PROFILE_ADMIN,
        RoleInfo {
            groups: vec![
                PermissionGroup::OperationsView,
                PermissionGroup::OperationsManage,
                PermissionGroup::ConnectorsView,
                PermissionGroup::ConnectorsManage,
                PermissionGroup::WorkflowsView,
                PermissionGroup::WorkflowsManage,
                PermissionGroup::AnalyticsView,
                PermissionGroup::UsersView,
                PermissionGroup::UsersManage,
                PermissionGroup::MerchantDetailsView,
                PermissionGroup::AccountView,
                PermissionGroup::MerchantDetailsManage,
                PermissionGroup::AccountManage,
            ],
            role_id: consts::user_role::ROLE_ID_PROFILE_ADMIN.to_string(),
            role_name: "profile_admin".to_string(),
            scope: RoleScope::Organization,
            entity_type: EntityType::Profile,
            is_invitable: true,
            is_deletable: true,
            is_updatable: true,
            is_internal: false,
        },
    );
    roles.insert(
        consts::user_role::ROLE_ID_PROFILE_VIEW_ONLY,
        RoleInfo {
            groups: vec![
                PermissionGroup::OperationsView,
                PermissionGroup::ConnectorsView,
                PermissionGroup::WorkflowsView,
                PermissionGroup::AnalyticsView,
                PermissionGroup::UsersView,
                PermissionGroup::MerchantDetailsView,
                PermissionGroup::AccountView,
            ],
            role_id: consts::user_role::ROLE_ID_PROFILE_VIEW_ONLY.to_string(),
            role_name: "profile_view_only".to_string(),
            scope: RoleScope::Organization,
            entity_type: EntityType::Profile,
            is_invitable: true,
            is_deletable: true,
            is_updatable: true,
            is_internal: false,
        },
    );
    roles.insert(
        consts::user_role::ROLE_ID_PROFILE_IAM_ADMIN,
        RoleInfo {
            groups: vec![
                PermissionGroup::OperationsView,
                PermissionGroup::AnalyticsView,
                PermissionGroup::UsersView,
                PermissionGroup::UsersManage,
                PermissionGroup::MerchantDetailsView,
                PermissionGroup::AccountView,
            ],
            role_id: consts::user_role::ROLE_ID_PROFILE_IAM_ADMIN.to_string(),
            role_name: "profile_iam".to_string(),
            scope: RoleScope::Organization,
            entity_type: EntityType::Profile,
            is_invitable: true,
            is_deletable: true,
            is_updatable: true,
            is_internal: false,
        },
    );
    roles.insert(
        consts::user_role::ROLE_ID_PROFILE_DEVELOPER,
        RoleInfo {
            groups: vec![
                PermissionGroup::OperationsView,
                PermissionGroup::ConnectorsView,
                PermissionGroup::AnalyticsView,
                PermissionGroup::UsersView,
                PermissionGroup::MerchantDetailsView,
                PermissionGroup::AccountView,
                PermissionGroup::MerchantDetailsManage,
                PermissionGroup::AccountManage,
            ],
            role_id: consts::user_role::ROLE_ID_PROFILE_DEVELOPER.to_string(),
            role_name: "profile_developer".to_string(),
            scope: RoleScope::Organization,
            entity_type: EntityType::Profile,
            is_invitable: true,
            is_deletable: true,
            is_updatable: true,
            is_internal: false,
        },
    );
    roles.insert(
        consts::user_role::ROLE_ID_PROFILE_OPERATOR,
        RoleInfo {
            groups: vec![
                PermissionGroup::OperationsView,
                PermissionGroup::OperationsManage,
                PermissionGroup::ConnectorsView,
                PermissionGroup::WorkflowsView,
                PermissionGroup::AnalyticsView,
                PermissionGroup::UsersView,
                PermissionGroup::MerchantDetailsView,
                PermissionGroup::AccountView,
            ],
            role_id: consts::user_role::ROLE_ID_PROFILE_OPERATOR.to_string(),
            role_name: "profile_operator".to_string(),
            scope: RoleScope::Organization,
            entity_type: EntityType::Profile,
            is_invitable: true,
            is_deletable: true,
            is_updatable: true,
            is_internal: false,
        },
    );
    roles.insert(
        consts::user_role::ROLE_ID_PROFILE_CUSTOMER_SUPPORT,
        RoleInfo {
            groups: vec![
                PermissionGroup::OperationsView,
                PermissionGroup::AnalyticsView,
                PermissionGroup::UsersView,
                PermissionGroup::MerchantDetailsView,
                PermissionGroup::AccountView,
            ],
            role_id: consts::user_role::ROLE_ID_PROFILE_CUSTOMER_SUPPORT.to_string(),
            role_name: "profile_customer_support".to_string(),
            scope: RoleScope::Organization,
            entity_type: EntityType::Profile,
            is_invitable: true,
            is_deletable: true,
            is_updatable: true,
            is_internal: false,
        },
    );
    roles
});


pub struct TokenizeCreditCardData {
    payment_method: TokenizePaymentMethodData,
}


OpenAPI Block Path: components.schemas.MandateAmountData
{
  "type": "object",
  "required": [
    "amount",
    "currency"
  ],
  "properties": {
    "amount": {
      "type": "integer",
      "format": "int64",
      "description": "The maximum amount to be debited for the mandate transaction",
      "example": 6540
    },
    "currency": {
      "$ref": "#/components/schemas/Currency"
    },
    "start_date": {
      "type": "string",
      "format": "date-time",
      "description": "Specifying start date of the mandate",
      "example": "2022-09-10T00:00:00Z",
      "nullable": true
    },
    "end_date": {
      "type": "string",
      "format": "date-time",
      "description": "Specifying end date of the mandate",
      "example": "2023-09-10T23:59:59Z",
      "nullable": true
    },
    "metadata": {
      "type": "object",
      "description": "Additional details required by mandate",
      "nullable": true
    }
  }
}


pub async fn link_routing_config_under_profile(
    state: SessionState,
    merchant_context: domain::MerchantContext,
    profile_id: common_utils::id_type::ProfileId,
    algorithm_id: common_utils::id_type::RoutingId,
    transaction_type: &enums::TransactionType,
) -> RouterResponse<routing_types::RoutingDictionaryRecord> {
    metrics::ROUTING_LINK_CONFIG.add(1, &[]);
    let db = state.store.as_ref();
    let key_manager_state = &(&state).into();

    let routing_algorithm = RoutingAlgorithmUpdate::fetch_routing_algo(
        merchant_context.get_merchant_account().get_id(),
        &algorithm_id,
        db,
    )
    .await?;

    utils::when(routing_algorithm.0.profile_id != profile_id, || {
        Err(errors::ApiErrorResponse::PreconditionFailed {
            message: "Profile Id is invalid for the routing config".to_string(),
        })
    })?;

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

    utils::when(
        routing_algorithm.0.algorithm_for != *transaction_type,
        || {
            Err(errors::ApiErrorResponse::PreconditionFailed {
                message: format!(
                    "Cannot use {}'s routing algorithm for {} operation",
                    routing_algorithm.0.algorithm_for, transaction_type
                ),
            })
        },
    )?;

    utils::when(
        business_profile.routing_algorithm_id == Some(algorithm_id.clone())
            || business_profile.payout_routing_algorithm_id == Some(algorithm_id.clone()),
        || {
            Err(errors::ApiErrorResponse::PreconditionFailed {
                message: "Algorithm is already active".to_string(),
            })
        },
    )?;
    admin::ProfileWrapper::new(business_profile)
        .update_profile_and_invalidate_routing_config_for_active_algorithm_id_update(
            db,
            key_manager_state,
            merchant_context.get_merchant_key_store(),
            algorithm_id,
            transaction_type,
        )
        .await?;

    metrics::ROUTING_LINK_CONFIG_SUCCESS_RESPONSE.add(1, &[]);
    Ok(service_api::ApplicationResponse::Json(
        routing_algorithm.0.foreign_into(),
    ))
}


pub struct OpennodePaymentsRequest {
    amount: MinorUnit,
    currency: String,
    description: String,
    auto_settle: bool,
    success_url: String,
    callback_url: String,
    order_id: String,
}


pub struct ForteCancelRequest {
    action: String,
    authorization_code: String,
}


pub struct NumberComparison {
    pub comparison_type: ComparisonType,
    pub number: u64,
}


OpenAPI Block Path: components.schemas.ApplePayRecurringPaymentRequest
{
  "type": "object",
  "required": [
    "payment_description",
    "regular_billing",
    "management_u_r_l"
  ],
  "properties": {
    "payment_description": {
      "type": "string",
      "description": "A description of the recurring payment that Apple Pay displays to the user in the payment sheet"
    },
    "regular_billing": {
      "$ref": "#/components/schemas/ApplePayRegularBillingRequest"
    },
    "billing_agreement": {
      "type": "string",
      "description": "A localized billing agreement that the payment sheet displays to the user before the user authorizes the payment",
      "nullable": true
    },
    "management_u_r_l": {
      "type": "string",
      "description": "A URL to a web page where the user can update or delete the payment method for the recurring payment",
      "example": "https://hyperswitch.io"
    }
  }
}


pub struct CheckoutTokenResponse {
    token: Secret<String>,
}


OpenAPI Block Path: components.schemas.GiftCardAdditionalData
{
  "oneOf": [
    {
      "type": "object",
      "required": [
        "givex"
      ],
      "properties": {
        "givex": {
          "$ref": "#/components/schemas/GivexGiftCardAdditionalData"
        }
      }
    },
    {
      "type": "object",
      "required": [
        "pay_safe_card"
      ],
      "properties": {
        "pay_safe_card": {
          "type": "object"
        }
      }
    },
    {
      "type": "object",
      "required": [
        "bhn_card_network"
      ],
      "properties": {
        "bhn_card_network": {
          "type": "object"
        }
      }
    }
  ]
}


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

use diesel_models::authentication::AuthenticationUpdateInternal;
use error_stack::report;
use router_env::{instrument, tracing};

use super::{MockDb, Store};
use crate::{
    connection,
    core::errors::{self, CustomResult},
    types::storage,
};

#[async_trait::async_trait]
pub trait AuthenticationInterface {
    async fn insert_authentication(
        &self,
        authentication: storage::AuthenticationNew,
    ) -> CustomResult<storage::Authentication, errors::StorageError>;

    async fn find_authentication_by_merchant_id_authentication_id(
        &self,
        merchant_id: &common_utils::id_type::MerchantId,
        authentication_id: &common_utils::id_type::AuthenticationId,
    ) -> CustomResult<storage::Authentication, errors::StorageError>;

    async fn find_authentication_by_merchant_id_connector_authentication_id(
        &self,
        merchant_id: common_utils::id_type::MerchantId,
        connector_authentication_id: String,
    ) -> CustomResult<storage::Authentication, errors::StorageError>;

    async fn update_authentication_by_merchant_id_authentication_id(
        &self,
        previous_state: storage::Authentication,
        authentication_update: storage::AuthenticationUpdate,
    ) -> CustomResult<storage::Authentication, errors::StorageError>;
}

#[async_trait::async_trait]
impl AuthenticationInterface for Store {
    #[instrument(skip_all)]
    async fn insert_authentication(
        &self,
        authentication: storage::AuthenticationNew,
    ) -> CustomResult<storage::Authentication, errors::StorageError> {
        let conn = connection::pg_connection_write(self).await?;
        authentication
            .insert(&conn)
            .await
            .map_err(|error| report!(errors::StorageError::from(error)))
    }

    #[instrument(skip_all)]
    async fn find_authentication_by_merchant_id_authentication_id(
        &self,
        merchant_id: &common_utils::id_type::MerchantId,
        authentication_id: &common_utils::id_type::AuthenticationId,
    ) -> CustomResult<storage::Authentication, errors::StorageError> {
        let conn = connection::pg_connection_read(self).await?;
        storage::Authentication::find_by_merchant_id_authentication_id(
            &conn,
            merchant_id,
            authentication_id,
        )
        .await
        .map_err(|error| report!(errors::StorageError::from(error)))
    }

    async fn find_authentication_by_merchant_id_connector_authentication_id(
        &self,
        merchant_id: common_utils::id_type::MerchantId,
        connector_authentication_id: String,
    ) -> CustomResult<storage::Authentication, errors::StorageError> {
        let conn = connection::pg_connection_read(self).await?;
        storage::Authentication::find_authentication_by_merchant_id_connector_authentication_id(
            &conn,
            &merchant_id,
            &connector_authentication_id,
        )
        .await
        .map_err(|error| report!(errors::StorageError::from(error)))
    }

    #[instrument(skip_all)]
    async fn update_authentication_by_merchant_id_authentication_id(
        &self,
        previous_state: storage::Authentication,
        authentication_update: storage::AuthenticationUpdate,
    ) -> CustomResult<storage::Authentication, errors::StorageError> {
        let conn = connection::pg_connection_write(self).await?;
        storage::Authentication::update_by_merchant_id_authentication_id(
            &conn,
            previous_state.merchant_id,
            previous_state.authentication_id,
            authentication_update,
        )
        .await
        .map_err(|error| report!(errors::StorageError::from(error)))
    }
}

#[async_trait::async_trait]
impl AuthenticationInterface for MockDb {
    async fn insert_authentication(
        &self,
        authentication: storage::AuthenticationNew,
    ) -> CustomResult<storage::Authentication, errors::StorageError> {
        let mut authentications = self.authentications.lock().await;
        if authentications.iter().any(|authentication_inner| {
            authentication_inner.authentication_id == authentication.authentication_id
        }) {
            Err(errors::StorageError::DuplicateValue {
                entity: "authentication_id",
                key: Some(
                    authentication
                        .authentication_id
                        .get_string_repr()
                        .to_string(),
                ),
            })?
        }
        let authentication = storage::Authentication {
            created_at: common_utils::date_time::now(),
            modified_at: common_utils::date_time::now(),
            authentication_id: authentication.authentication_id,
            merchant_id: authentication.merchant_id,
            authentication_status: authentication.authentication_status,
            authentication_connector: authentication.authentication_connector,
            connector_authentication_id: authentication.connector_authentication_id,
            authentication_data: None,
            payment_method_id: authentication.payment_method_id,
            authentication_type: authentication.authentication_type,
            authentication_lifecycle_status: authentication.authentication_lifecycle_status,
            error_code: authentication.error_code,
            error_message: authentication.error_message,
            connector_metadata: authentication.connector_metadata,
            maximum_supported_version: authentication.maximum_supported_version,
            threeds_server_transaction_id: authentication.threeds_server_transaction_id,
            cavv: authentication.cavv,
            authentication_flow_type: authentication.authentication_flow_type,
            message_version: authentication.message_version,
            eci: authentication.eci,
            trans_status: authentication.trans_status,
            acquirer_bin: authentication.acquirer_bin,
            acquirer_merchant_id: authentication.acquirer_merchant_id,
            three_ds_method_data: authentication.three_ds_method_data,
            three_ds_method_url: authentication.three_ds_method_url,
            acs_url: authentication.acs_url,
            challenge_request: authentication.challenge_request,
            acs_reference_number: authentication.acs_reference_number,
            acs_trans_id: authentication.acs_trans_id,
            acs_signed_content: authentication.acs_signed_content,
            profile_id: authentication.profile_id,
            payment_id: authentication.payment_id,
            merchant_connector_id: authentication.merchant_connector_id,
            ds_trans_id: authentication.ds_trans_id,
            directory_server_id: authentication.directory_server_id,
            acquirer_country_code: authentication.acquirer_country_code,
            service_details: authentication.service_details,
            organization_id: authentication.organization_id,
            authentication_client_secret: authentication.authentication_client_secret,
            force_3ds_challenge: authentication.force_3ds_challenge,
            psd2_sca_exemption_type: authentication.psd2_sca_exemption_type,
            return_url: authentication.return_url,
            amount: authentication.amount,
            currency: authentication.currency,
            billing_address: authentication.billing_address,
            shipping_address: authentication.shipping_address,
            browser_info: authentication.browser_info,
            email: authentication.email,
            profile_acquirer_id: authentication.profile_acquirer_id,
            challenge_code: authentication.challenge_code,
            challenge_cancel: authentication.challenge_cancel,
            challenge_code_reason: authentication.challenge_code_reason,
            message_extension: authentication.message_extension,
        };
        authentications.push(authentication.clone());
        Ok(authentication)
    }

    async fn find_authentication_by_merchant_id_authentication_id(
        &self,
        merchant_id: &common_utils::id_type::MerchantId,
        authentication_id: &common_utils::id_type::AuthenticationId,
    ) -> CustomResult<storage::Authentication, errors::StorageError> {
        let authentications = self.authentications.lock().await;
        authentications
            .iter()
            .find(|a| a.merchant_id == *merchant_id && a.authentication_id == *authentication_id)
            .ok_or(
                errors::StorageError::ValueNotFound(format!(
                    "cannot find authentication for authentication_id = {authentication_id:?} and merchant_id = {merchant_id:?}"
                )).into(),
            ).cloned()
    }

    async fn find_authentication_by_merchant_id_connector_authentication_id(
        &self,
        _merchant_id: common_utils::id_type::MerchantId,
        _connector_authentication_id: String,
    ) -> CustomResult<storage::Authentication, errors::StorageError> {
        Err(errors::StorageError::MockDbError)?
    }

    async fn update_authentication_by_merchant_id_authentication_id(
        &self,
        previous_state: storage::Authentication,
        authentication_update: storage::AuthenticationUpdate,
    ) -> CustomResult<storage::Authentication, errors::StorageError> {
        let mut authentications = self.authentications.lock().await;
        let authentication_id = previous_state.authentication_id.clone();
        let merchant_id = previous_state.merchant_id.clone();
        authentications
            .iter_mut()
            .find(|authentication| authentication.authentication_id == authentication_id && authentication.merchant_id == merchant_id)
            .map(|authentication| {
                let authentication_update_internal =
                    AuthenticationUpdateInternal::from(authentication_update);
                let updated_authentication = authentication_update_internal.apply_changeset(previous_state);
                *authentication = updated_authentication.clone();
                updated_authentication
            })
            .ok_or(
                errors::StorageError::ValueNotFound(format!(
                    "cannot find authentication for authentication_id = {authentication_id:?} and merchant_id = {merchant_id:?}"
                ))
                .into(),
            )
    }
}


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

    /// Name of the Connector
    #[schema(value_type = Connector, example = "stripe")]
    pub connector_name: api_enums::Connector,

    /// This is an unique label you can generate and pass in order to identify this connector account on your Hyperswitch dashboard and reports, If not passed then if will take `connector_name`_`profile_name`. Eg: if your profile label is `default`, connector label can be `stripe_default`
    #[schema(example = "stripe_US_travel")]
    pub connector_label: Option<String>,

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

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

    /// An object containing the details about the payment methods that need to be enabled under this merchant connector account
    #[schema(value_type = PaymentMethodsEnabled)]
    pub payment_methods_enabled: Option<Vec<common_types::payment_methods::PaymentMethodsEnabled>>,

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

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

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

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

    /// pm_auth_config will relate MCA records to their respective chosen auth services, based on payment_method and pmt
    #[schema(value_type = Option<Object>)]
    pub pm_auth_config: Option<pii::SecretSerdeValue>,

    #[schema(value_type = Option<ConnectorStatus>, example = "inactive")]
    // By default the ConnectorStatus is Active
    pub status: Option<api_enums::ConnectorStatus>,

    /// In case the merchant needs to store any additional sensitive data
    #[schema(value_type = Option<AdditionalMerchantData>)]
    pub additional_merchant_data: Option<AdditionalMerchantData>,

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

    /// Additional data that might be required by hyperswitch, to enable some specific features.
    #[schema(value_type = Option<MerchantConnectorAccountFeatureMetadata>)]
    pub feature_metadata: Option<MerchantConnectorAccountFeatureMetadata>,
}


pub struct DeliveryOptions {
    id: String,
    price: ChargeAmount,
    shipping_method: ShippingMethod,
    is_default: bool,
}


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

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

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

    #[cfg(feature = "v1")]
    fn generate_connector_request_reference_id(
        &self,
        payment_intent: &hyperswitch_domain_models::payments::PaymentIntent,
        payment_attempt: &hyperswitch_domain_models::payments::payment_attempt::PaymentAttempt,
        is_config_enabled_to_send_payment_id_as_connector_request_id: bool,
    ) -> String {
        if is_config_enabled_to_send_payment_id_as_connector_request_id
            && payment_intent.is_payment_id_from_merchant.unwrap_or(false)
        {
            payment_attempt.payment_id.get_string_repr().to_owned()
        } else {
            connector_utils::generate_12_digit_number().to_string()
        }
    }
}

impl ConnectorSpecifications for for Redsys


impl api::PaymentAuthorize for Nmi {}