OpenAPI Block Path: components.schemas.ResponsePaymentMethodTypes
{
  "type": "object",
  "required": [
    "payment_method_type"
  ],
  "properties": {
    "payment_method_type": {
      "$ref": "#/components/schemas/PaymentMethodType"
    },
    "payment_experience": {
      "type": "array",
      "items": {
        "$ref": "#/components/schemas/PaymentExperienceTypes"
      },
      "description": "The list of payment experiences enabled, if applicable for a payment method type",
      "nullable": true
    },
    "card_networks": {
      "type": "array",
      "items": {
        "$ref": "#/components/schemas/CardNetworkTypes"
      },
      "description": "The list of card networks enabled, if applicable for a payment method type",
      "nullable": true
    },
    "bank_names": {
      "type": "array",
      "items": {
        "$ref": "#/components/schemas/BankCodeResponse"
      },
      "description": "The list of banks enabled, if applicable for a payment method type . To be deprecated soon.",
      "deprecated": true,
      "nullable": true
    },
    "bank_debits": {
      "allOf": [
        {
          "$ref": "#/components/schemas/BankDebitTypes"
        }
      ],
      "nullable": true
    },
    "bank_transfers": {
      "allOf": [
        {
          "$ref": "#/components/schemas/BankTransferTypes"
        }
      ],
      "nullable": true
    },
    "required_fields": {
      "type": "object",
      "description": "Required fields for the payment_method_type.",
      "additionalProperties": {
        "$ref": "#/components/schemas/RequiredFieldInfo"
      },
      "nullable": true
    },
    "surcharge_details": {
      "allOf": [
        {
          "$ref": "#/components/schemas/SurchargeDetailsResponse"
        }
      ],
      "nullable": true
    },
    "pm_auth_connector": {
      "type": "string",
      "description": "auth service connector label for this payment method type, if exists",
      "nullable": true
    }
  }
}


pub struct PaymentConfirm;


pub struct RefundResponse {
    id: String,
    status: RefundStatus,
}


pub async fn modify_trackers<F, FData, D>(
    state: &routes::SessionState,
    connector: String,
    payment_data: &mut D,
    key_store: &domain::MerchantKeyStore,
    storage_scheme: storage_enums::MerchantStorageScheme,
    router_data: types::RouterData<F, FData, types::PaymentsResponseData>,
    is_step_up: bool,
) -> RouterResult<()>
where
    F: Clone + Send,
    FData: Send,
    D: payments::OperationSessionGetters<F> + payments::OperationSessionSetters<F> + Send + Sync,
{
    todo!()
}


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


pub async fn mock_get_card<'a>(
    db: &dyn db::StorageInterface,
    card_id: &'a str,
) -> errors::CustomResult<(payment_methods::GetCardResponse, Option<String>), errors::VaultError> {
    let locker_mock_up = db
        .find_locker_by_card_id(card_id)
        .await
        .change_context(errors::VaultError::FetchCardFailed)?;
    let add_card_response = payment_methods::AddCardResponse {
        card_id: locker_mock_up
            .payment_method_id
            .unwrap_or(locker_mock_up.card_id),
        external_id: locker_mock_up.external_id,
        card_fingerprint: locker_mock_up.card_fingerprint.into(),
        card_global_fingerprint: locker_mock_up.card_global_fingerprint.into(),
        merchant_id: Some(locker_mock_up.merchant_id),
        card_number: cards::CardNumber::try_from(locker_mock_up.card_number)
            .change_context(errors::VaultError::ResponseDeserializationFailed)
            .attach_printable("Invalid card number format from the mock locker")
            .map(Some)?,
        card_exp_year: Some(locker_mock_up.card_exp_year.into()),
        card_exp_month: Some(locker_mock_up.card_exp_month.into()),
        name_on_card: locker_mock_up.name_on_card.map(|card| card.into()),
        nickname: locker_mock_up.nickname,
        customer_id: locker_mock_up.customer_id,
        duplicate: locker_mock_up.duplicate,
    };
    Ok((
        payment_methods::GetCardResponse {
            card: add_card_response,
        },
        locker_mock_up.card_cvc,
    ))
}


pub struct DisputeMetricsBucketValue {
    pub disputes_challenged: Option<u64>,
    pub disputes_won: Option<u64>,
    pub disputes_lost: Option<u64>,
    pub disputed_amount: Option<u64>,
    pub dispute_lost_amount: Option<u64>,
    pub total_dispute: Option<u64>,
}


impl fred::types::FromRedis for DelReply {
    fn from_value(value: fred::types::RedisValue) -> Result<Self, fred::error::RedisError> {
        match value {
            fred::types::RedisValue::Integer(1) => Ok(Self::KeyDeleted),
            fred::types::RedisValue::Integer(0) => Ok(Self::KeyNotDeleted),
            _ => Err(fred::error::RedisError::new(
                fred::error::RedisErrorKind::Unknown,
                "Unexpected del command reply",
            )),
        }
    }
}

impl fred::types::FromRedis for for DelReply


impl PaymentIntentFetchConstraints {
    pub fn get_profile_id_list(&self) -> Option<Vec<id_type::ProfileId>> {
        if let Self::List(pi_list_params) = self {
            pi_list_params.profile_id.clone()
        } else {
            None
        }
    }
}


pub struct RapydIncomingWebhook {
    pub id: String,
    #[serde(rename = "type")]
    pub webhook_type: RapydWebhookObjectEventType,
    pub data: WebhookData,
    pub trigger_operation_id: Option<String>,
    pub status: String,
    pub created_at: i64,
}


impl CardInfoBuilder<CardInfoFetch> {
    fn new() -> Self {
        Self {
            state: std::marker::PhantomData,
            card_info: None,
        }
    }
}


impl OrganizationBridge for OrganizationNew {
    fn get_organization_id(&self) -> id_type::OrganizationId {
        self.org_id.clone()
    }
    fn get_organization_name(&self) -> Option<String> {
        self.org_name.clone()
    }
    fn set_organization_name(&mut self, organization_name: String) {
        self.org_name = Some(organization_name);
    }
}

impl OrganizationBridge for for OrganizationNew


impl PaymentCapture for Signifyd {}


impl ApiEventMetric for CurrencyConversionParams {}

impl ApiEventMetric for for CurrencyConversionParams


impl api::Payment for Paypal {}


impl ApplePayPredecryptData {
    /// Get the four-digit expiration year from the Apple Pay pre-decrypt data
    pub fn get_two_digit_expiry_year(&self) -> Result<Secret<String>, errors::ValidationError> {
        let binding = self.application_expiration_year.clone();
        let year = binding.peek();
        Ok(Secret::new(
            year.get(year.len() - 2..)
                .ok_or(errors::ValidationError::InvalidValue {
                    message: "Invalid two-digit year".to_string(),
                })?
                .to_string(),
        ))
    }

    /// Get the four-digit expiration year from the Apple Pay pre-decrypt data
    pub fn get_four_digit_expiry_year(&self) -> Secret<String> {
        let mut year = self.application_expiration_year.peek().clone();
        if year.len() == 2 {
            year = format!("20{year}");
        }
        Secret::new(year)
    }

    /// Get the expiration month from the Apple Pay pre-decrypt data
    pub fn get_expiry_month(&self) -> Result<Secret<String>, errors::ValidationError> {
        let month_str = self.application_expiration_month.peek();
        let month = month_str
            .parse::<u8>()
            .map_err(|_| errors::ValidationError::InvalidValue {
                message: format!("Failed to parse expiry month: {month_str}"),
            })?;

        if !(1..=12).contains(&month) {
            return Err(errors::ValidationError::InvalidValue {
                message: format!("Invalid expiry month: {month}. Must be between 1 and 12"),
            }
            .into());
        }
        Ok(self.application_expiration_month.clone())
    }

    /// Get the expiry date in MMYY format from the Apple Pay pre-decrypt data
    pub fn get_expiry_date_as_mmyy(&self) -> Result<Secret<String>, errors::ValidationError> {
        let year = self.get_two_digit_expiry_year()?.expose();
        let month = self.get_expiry_month()?.expose();
        Ok(Secret::new(format!("{month}{year}")))
    }
}


/// Get the encrypted Apple Pay payment data if it exists
    pub fn get_encrypted_apple_pay_payment_data_optional(&self) -> Option<&String> {
        match self {
            Self::Encrypted(encrypted_data) => Some(encrypted_data),
            Self::Decrypted(_) => None,
        }
    }


pub struct MollieCardTokenRequest {
    card_holder: Secret<String>,
    card_number: CardNumber,
    card_cvv: Secret<String>,
    card_expiry_date: Secret<String>,
    locale: String,
    testmode: bool,
    profile_token: Secret<String>,
}


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


pub async fn handle_action(
        &self,
        state: &SessionState,
        business_profile: &domain::Profile,
        merchant_context: &domain::MerchantContext,
        billing_connector_account: &hyperswitch_domain_models::merchant_connector_account::MerchantConnectorAccount,
        mca_retry_threshold: u16,
        intent_retry_count: u16,
        recovery_tuple: &(
            Option<revenue_recovery::RecoveryPaymentAttempt>,
            revenue_recovery::RecoveryPaymentIntent,
        )


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


impl Responder {
        let flow = AnalyticsFlow::GetPaymentFilters;
        Box::pin(api::server_wrap(
            flow,
            state,
            &req,
            json_payload.into_inner(),
            |state, auth: AuthenticationData, req, _| async move {
                let org_id = auth.merchant_account.get_org_id();
                let merchant_id = auth.merchant_account.get_id();
                let profile_id = auth
                    .profile_id
                    .ok_or(report!(UserErrors::JwtProfileIdMissing))
                    .change_context(AnalyticsError::AccessForbiddenError)?;
                let auth: AuthInfo = AuthInfo::ProfileLevel {
                    org_id: org_id.clone(),
                    merchant_id: merchant_id.clone(),
                    profile_ids: vec![profile_id.clone()],
                };
                analytics::payments::get_filters(&state.pool, req, &auth)
                    .await
                    .map(ApplicationResponse::Json)
            },
            &auth::JWTAuth {
                permission: Permission::ProfileAnalyticsRead,
            },
            api_locking::LockAction::NotApplicable,
        ))
        .await
    }


pub fn get_connector_config(
        connector: Connector,
    ) -> Result<Option<ConnectorTomlConfig>, String> {
        let connector_data = Self::new()?;
        match connector {
            Connector::Aci => Ok(connector_data.aci),
            Connector::Authipay => Ok(connector_data.authipay),
            Connector::Adyen => Ok(connector_data.adyen),
            Connector::Affirm => Ok(connector_data.affirm),
            Connector::Adyenplatform => Err("Use get_payout_connector_config".to_string()),
            Connector::Airwallex => Ok(connector_data.airwallex),
            Connector::Amazonpay => Ok(connector_data.amazonpay),
            Connector::Archipel => Ok(connector_data.archipel),
            Connector::Authorizedotnet => Ok(connector_data.authorizedotnet),
            Connector::Bamboraapac => Ok(connector_data.bamboraapac),
            Connector::Bankofamerica => Ok(connector_data.bankofamerica),
            Connector::Barclaycard => Ok(connector_data.barclaycard),
            Connector::Billwerk => Ok(connector_data.billwerk),
            Connector::Bitpay => Ok(connector_data.bitpay),
            Connector::Bluesnap => Ok(connector_data.bluesnap),
            Connector::Bluecode => Ok(connector_data.bluecode),
            Connector::Blackhawknetwork => Ok(connector_data.blackhawknetwork),
            Connector::Boku => Ok(connector_data.boku),
            Connector::Braintree => Ok(connector_data.braintree),
            Connector::Breadpay => Ok(connector_data.breadpay),
            Connector::Cashtocode => Ok(connector_data.cashtocode),
            Connector::Celero => Ok(connector_data.celero),
            Connector::Chargebee => Ok(connector_data.chargebee),
            Connector::Checkbook => Ok(connector_data.checkbook),
            Connector::Checkout => Ok(connector_data.checkout),
            Connector::Coinbase => Ok(connector_data.coinbase),
            Connector::Coingate => Ok(connector_data.coingate),
            Connector::Cryptopay => Ok(connector_data.cryptopay),
            Connector::CtpVisa => Ok(connector_data.ctp_visa),
            Connector::Custombilling => Ok(connector_data.custombilling),
            Connector::Cybersource => Ok(connector_data.cybersource),
            #[cfg(feature = "dummy_connector")]
            Connector::DummyBillingConnector => Ok(connector_data.dummy_connector),
            Connector::Iatapay => Ok(connector_data.iatapay),
            Connector::Itaubank => Ok(connector_data.itaubank),
            Connector::Opennode => Ok(connector_data.opennode),
            Connector::Bambora => Ok(connector_data.bambora),
            Connector::Datatrans => Ok(connector_data.datatrans),
            Connector::Deutschebank => Ok(connector_data.deutschebank),
            Connector::Digitalvirgo => Ok(connector_data.digitalvirgo),
            Connector::Dlocal => Ok(connector_data.dlocal),
            Connector::Dwolla => Ok(connector_data.dwolla),
            Connector::Ebanx => Ok(connector_data.ebanx_payout),
            Connector::Elavon => Ok(connector_data.elavon),
            Connector::Facilitapay => Ok(connector_data.facilitapay),
            Connector::Fiserv => Ok(connector_data.fiserv),
            Connector::Fiservemea => Ok(connector_data.fiservemea),
            Connector::Fiuu => Ok(connector_data.fiuu),
            Connector::Flexiti => Ok(connector_data.flexiti),
            Connector::Forte => Ok(connector_data.forte),
            Connector::Getnet => Ok(connector_data.getnet),
            Connector::Globalpay => Ok(connector_data.globalpay),
            Connector::Globepay => Ok(connector_data.globepay),
            Connector::Gocardless => Ok(connector_data.gocardless),
            Connector::Gpayments => Ok(connector_data.gpayments),
            Connector::Hipay => Ok(connector_data.hipay),
            Connector::HyperswitchVault => Ok(connector_data.hyperswitch_vault),
            Connector::Helcim => Ok(connector_data.helcim),
            Connector::Inespay => Ok(connector_data.inespay),
            Connector::Jpmorgan => Ok(connector_data.jpmorgan),
            Connector::Juspaythreedsserver => Ok(connector_data.juspaythreedsserver),
            Connector::Klarna => Ok(connector_data.klarna),
            Connector::Mifinity => Ok(connector_data.mifinity),
            Connector::Mollie => Ok(connector_data.mollie),
            Connector::Moneris => Ok(connector_data.moneris),
            Connector::Multisafepay => Ok(connector_data.multisafepay),
            Connector::Nexinets => Ok(connector_data.nexinets),
            Connector::Nexixpay => Ok(connector_data.nexixpay),
            Connector::Prophetpay => Ok(connector_data.prophetpay),
            Connector::Nmi => Ok(connector_data.nmi),
            Connector::Nordea => Ok(connector_data.nordea),
            Connector::Nomupay => Err("Use get_payout_connector_config".to_string()),
            Connector::Novalnet => Ok(connector_data.novalnet),
            Connector::Noon => Ok(connector_data.noon),
            Connector::Nuvei => Ok(connector_data.nuvei),
            Connector::Paybox => Ok(connector_data.paybox),
            Connector::Payload => Ok(connector_data.payload),
            Connector::Payme => Ok(connector_data.payme),
            Connector::Payone => Err("Use get_payout_connector_config".to_string()),
            Connector::Paypal => Ok(connector_data.paypal),
            Connector::Paysafe => Ok(connector_data.paysafe),
            Connector::Paystack => Ok(connector_data.paystack),
            Connector::Payu => Ok(connector_data.payu),
            Connector::Placetopay => Ok(connector_data.placetopay),
            Connector::Plaid => Ok(connector_data.plaid),
            Connector::Powertranz => Ok(connector_data.powertranz),
            Connector::Razorpay => Ok(connector_data.razorpay),
            Connector::Rapyd => Ok(connector_data.rapyd),
            Connector::Recurly => Ok(connector_data.recurly),
            Connector::Redsys => Ok(connector_data.redsys),
            Connector::Riskified => Ok(connector_data.riskified),
            Connector::Santander => Ok(connector_data.santander),
            Connector::Shift4 => Ok(connector_data.shift4),
            Connector::Signifyd => Ok(connector_data.signifyd),
            Connector::Silverflow => Ok(connector_data.silverflow),
            Connector::Square => Ok(connector_data.square),
            Connector::Stax => Ok(connector_data.stax),
            Connector::Stripe => Ok(connector_data.stripe),
            Connector::Stripebilling => Ok(connector_data.stripebilling),
            Connector::Tokenio => Ok(connector_data.tokenio),
            Connector::Trustpay => Ok(connector_data.trustpay),
            Connector::Threedsecureio => Ok(connector_data.threedsecureio),
            Connector::Taxjar => Ok(connector_data.taxjar),
            Connector::Tsys => Ok(connector_data.tsys),
            Connector::Vgs => Ok(connector_data.vgs),
            Connector::Volt => Ok(connector_data.volt),
            Connector::Wellsfargo => Ok(connector_data.wellsfargo),
            Connector::Wise => Err("Use get_payout_connector_config".to_string()),
            Connector::Worldline => Ok(connector_data.worldline),
            Connector::Worldpay => Ok(connector_data.worldpay),
            Connector::Worldpayvantiv => Ok(connector_data.worldpayvantiv),
            Connector::Worldpayxml => Ok(connector_data.worldpayxml),
            Connector::Zen => Ok(connector_data.zen),
            Connector::Zsl => Ok(connector_data.zsl),
            #[cfg(feature = "dummy_connector")]
            Connector::DummyConnector1 => Ok(connector_data.dummy_connector),
            #[cfg(feature = "dummy_connector")]
            Connector::DummyConnector2 => Ok(connector_data.dummy_connector),
            #[cfg(feature = "dummy_connector")]
            Connector::DummyConnector3 => Ok(connector_data.dummy_connector),
            #[cfg(feature = "dummy_connector")]
            Connector::DummyConnector4 => Ok(connector_data.stripe_test),
            #[cfg(feature = "dummy_connector")]
            Connector::DummyConnector5 => Ok(connector_data.dummy_connector),
            #[cfg(feature = "dummy_connector")]
            Connector::DummyConnector6 => Ok(connector_data.dummy_connector),
            #[cfg(feature = "dummy_connector")]
            Connector::DummyConnector7 => Ok(connector_data.paypal_test),
            Connector::Netcetera => Ok(connector_data.netcetera),
            Connector::CtpMastercard => Ok(connector_data.ctp_mastercard),
            Connector::Xendit => Ok(connector_data.xendit),
            Connector::Paytm => Ok(connector_data.paytm),
            Connector::Phonepe => Ok(connector_data.phonepe),
        }
    }


impl CustomerResponse {
    pub fn get_merchant_reference_id(&self) -> Option<id_type::CustomerId> {
        Some(self.customer_id.clone())
    }
}


pub async fn list_initial_delivery_attempts(
    state: SessionState,
    merchant_id: common_utils::id_type::MerchantId,
    api_constraints: api::webhook_events::EventListConstraints,
) -> RouterResponse<api::webhook_events::TotalEventsResponse> {
    let profile_id = api_constraints.profile_id.clone();
    let constraints = api::webhook_events::EventListConstraintsInternal::foreign_try_from(
        api_constraints.clone(),
    )?;

    let store = state.store.as_ref();
    let key_manager_state = &(&state).into();
    let (account, key_store) =
        get_account_and_key_store(state.clone(), merchant_id.clone(), profile_id.clone()).await?;

    let now = common_utils::date_time::now();
    let events_list_begin_time =
        (now.date() - time::Duration::days(INITIAL_DELIVERY_ATTEMPTS_LIST_MAX_DAYS)).midnight();

    let (events, total_count) = match constraints {
        api_models::webhook_events::EventListConstraintsInternal::ObjectIdFilter { object_id } => {
            let events = match account {
                MerchantAccountOrProfile::MerchantAccount(merchant_account) => {
                    store
                        .list_initial_events_by_merchant_id_primary_object_id(
                            key_manager_state,
                            merchant_account.get_id(),
                            &object_id,
                            &key_store,
                        )
                        .await
                }
                MerchantAccountOrProfile::Profile(business_profile) => {
                    store
                        .list_initial_events_by_profile_id_primary_object_id(
                            key_manager_state,
                            business_profile.get_id(),
                            &object_id,
                            &key_store,
                        )
                        .await
                }
            }
            .change_context(errors::ApiErrorResponse::InternalServerError)
            .attach_printable("Failed to list events with specified constraints")?;

            let total_count = i64::try_from(events.len())
                .change_context(errors::ApiErrorResponse::InternalServerError)
                .attach_printable("Error while converting from usize to i64")?;
            (events, total_count)
        }
        api_models::webhook_events::EventListConstraintsInternal::GenericFilter {
            created_after,
            created_before,
            limit,
            offset,
            event_classes,
            event_types,
            is_delivered,
        } => {
            let limit = match limit {
                Some(limit) if  limit <= INITIAL_DELIVERY_ATTEMPTS_LIST_MAX_LIMIT => Ok(Some(limit)),
                Some(limit) if limit > INITIAL_DELIVERY_ATTEMPTS_LIST_MAX_LIMIT => Err(
                    errors::ApiErrorResponse::InvalidRequestData{
                        message: format!("`limit` must be a number less than {INITIAL_DELIVERY_ATTEMPTS_LIST_MAX_LIMIT}")
                    }
                ),
                _  => Ok(Some(INITIAL_DELIVERY_ATTEMPTS_LIST_MAX_LIMIT)),
            }?;
            let offset = match offset {
                Some(offset) if offset > 0 => Some(offset),
                _ => None,
            };

            let event_classes = event_classes.unwrap_or(HashSet::new());
            let mut event_types = event_types.unwrap_or(HashSet::new());
            if !event_classes.is_empty() {
                event_types = finalize_event_types(event_classes, event_types).await?;
            }

            fp_utils::when(
                !created_after
                    .zip(created_before)
                    .map(|(created_after, created_before)| created_after <= created_before)
                    .unwrap_or(true),
                || {
                    Err(errors::ApiErrorResponse::InvalidRequestData { message: "The `created_after` timestamp must be an earlier timestamp compared to the `created_before` timestamp".to_string() })
                },
            )?;

            let created_after = match created_after {
                Some(created_after) => {
                    if created_after < events_list_begin_time {
                        Err(errors::ApiErrorResponse::InvalidRequestData { message: format!("`created_after` must be a timestamp within the past {INITIAL_DELIVERY_ATTEMPTS_LIST_MAX_DAYS} days.") })
                    } else {
                        Ok(created_after)
                    }
                }
                None => Ok(events_list_begin_time),
            }?;

            let created_before = match created_before {
                Some(created_before) => {
                    if created_before < events_list_begin_time {
                        Err(errors::ApiErrorResponse::InvalidRequestData { message: format!("`created_before` must be a timestamp within the past {INITIAL_DELIVERY_ATTEMPTS_LIST_MAX_DAYS} days.") })
                    } else {
                        Ok(created_before)
                    }
                }
                None => Ok(now),
            }?;

            let events = match account {
                MerchantAccountOrProfile::MerchantAccount(merchant_account) => {
                    store
                        .list_initial_events_by_merchant_id_constraints(
                            key_manager_state,
                            merchant_account.get_id(),
                            created_after,
                            created_before,
                            limit,
                            offset,
                            event_types.clone(),
                            is_delivered,
                            &key_store,
                        )
                        .await
                }
                MerchantAccountOrProfile::Profile(business_profile) => {
                    store
                        .list_initial_events_by_profile_id_constraints(
                            key_manager_state,
                            business_profile.get_id(),
                            created_after,
                            created_before,
                            limit,
                            offset,
                            event_types.clone(),
                            is_delivered,
                            &key_store,
                        )
                        .await
                }
            }
            .change_context(errors::ApiErrorResponse::InternalServerError)
            .attach_printable("Failed to list events with specified constraints")?;

            let total_count = store
                .count_initial_events_by_constraints(
                    &merchant_id,
                    profile_id,
                    created_after,
                    created_before,
                    event_types,
                    is_delivered,
                )
                .await
                .change_context(errors::ApiErrorResponse::InternalServerError)
                .attach_printable("Failed to get total events count")?;

            (events, total_count)
        }
    };

    let events = events
        .into_iter()
        .map(api::webhook_events::EventListItemResponse::try_from)
        .collect::<Result<Vec<_>, _>>()?;

    Ok(ApplicationResponse::Json(
        api::webhook_events::TotalEventsResponse::new(total_count, events),
    ))
}


impl api::PaymentToken for Barclaycard {}

impl api::PaymentToken for for Barclaycard


pub struct AccessTokenAuth;


impl api::PaymentCapture for Hyperwallet {}

impl api::PaymentCapture for for Hyperwallet


pub fn apply_changeset(self, source: Payouts) -> Payouts {
        let PayoutsUpdateInternal {
            amount,
            destination_currency,
            source_currency,
            description,
            recurring,
            auto_fulfill,
            return_url,
            entity_type,
            metadata,
            payout_method_id,
            profile_id,
            status,
            last_modified_at,
            attempt_count,
            confirm,
            payout_type,
            address_id,
            customer_id,
        } = self.into();
        Payouts {
            amount: amount.unwrap_or(source.amount),
            destination_currency: destination_currency.unwrap_or(source.destination_currency),
            source_currency: source_currency.unwrap_or(source.source_currency),
            description: description.or(source.description),
            recurring: recurring.unwrap_or(source.recurring),
            auto_fulfill: auto_fulfill.unwrap_or(source.auto_fulfill),
            return_url: return_url.or(source.return_url),
            entity_type: entity_type.unwrap_or(source.entity_type),
            metadata: metadata.or(source.metadata),
            payout_method_id: payout_method_id.or(source.payout_method_id),
            profile_id: profile_id.unwrap_or(source.profile_id),
            status: status.unwrap_or(source.status),
            last_modified_at,
            attempt_count: attempt_count.unwrap_or(source.attempt_count),
            confirm: confirm.or(source.confirm),
            payout_type: payout_type.or(source.payout_type),
            address_id: address_id.or(source.address_id),
            customer_id: customer_id.or(source.customer_id),
            ..source
        }
    }


pub struct ProcessedAmountAccumulator {
    pub count_with_retries: Option<i64>,
    pub total_with_retries: Option<i64>,
    pub count_without_retries: Option<i64>,
    pub total_without_retries: Option<i64>,
}


pub async fn default_specific_dynamic_routing_setup(
    state: &SessionState,
    key_store: domain::MerchantKeyStore,
    business_profile: domain::Profile,
    feature_to_enable: routing_types::DynamicRoutingFeatures,
    mut dynamic_routing_algo_ref: routing_types::DynamicRoutingAlgorithmRef,
    dynamic_routing_type: routing_types::DynamicRoutingType,
) -> RouterResult<ApplicationResponse<routing_types::RoutingDictionaryRecord>> {
    let db = state.store.as_ref();
    let key_manager_state = &state.into();
    let profile_id = business_profile.get_id().clone();
    let merchant_id = business_profile.merchant_id.clone();
    let algorithm_id = common_utils::generate_routing_id_of_default_length();
    let timestamp = common_utils::date_time::now();

    let algo = match dynamic_routing_type {
        routing_types::DynamicRoutingType::SuccessRateBasedRouting => {
            let default_success_based_routing_config =
                if state.conf.open_router.dynamic_routing_enabled {
                    routing_types::SuccessBasedRoutingConfig::open_router_config_default()
                } else {
                    routing_types::SuccessBasedRoutingConfig::default()
                };

            routing_algorithm::RoutingAlgorithm {
                algorithm_id: algorithm_id.clone(),
                profile_id: profile_id.clone(),
                merchant_id,
                name: SUCCESS_BASED_DYNAMIC_ROUTING_ALGORITHM.to_string(),
                description: None,
                kind: diesel_models::enums::RoutingAlgorithmKind::Dynamic,
                algorithm_data: serde_json::json!(default_success_based_routing_config),
                created_at: timestamp,
                modified_at: timestamp,
                algorithm_for: common_enums::TransactionType::Payment,
                decision_engine_routing_id: None,
            }
        }
        routing_types::DynamicRoutingType::EliminationRouting => {
            let default_elimination_routing_config =
                if state.conf.open_router.dynamic_routing_enabled {
                    routing_types::EliminationRoutingConfig::open_router_config_default()
                } else {
                    routing_types::EliminationRoutingConfig::default()
                };

            routing_algorithm::RoutingAlgorithm {
                algorithm_id: algorithm_id.clone(),
                profile_id: profile_id.clone(),
                merchant_id,
                name: ELIMINATION_BASED_DYNAMIC_ROUTING_ALGORITHM.to_string(),
                description: None,
                kind: diesel_models::enums::RoutingAlgorithmKind::Dynamic,
                algorithm_data: serde_json::json!(default_elimination_routing_config),
                created_at: timestamp,
                modified_at: timestamp,
                algorithm_for: common_enums::TransactionType::Payment,
                decision_engine_routing_id: None,
            }
        }

        routing_types::DynamicRoutingType::ContractBasedRouting => {
            return Err((errors::ApiErrorResponse::InvalidRequestData {
                message: "Contract routing cannot be set as default".to_string(),
            })
            .into())
        }
    };

    // Call to DE here
    // Need to map out the cases if this call should always be made or not
    if state.conf.open_router.dynamic_routing_enabled {
        enable_decision_engine_dynamic_routing_setup(
            state,
            business_profile.get_id(),
            dynamic_routing_type,
            &mut dynamic_routing_algo_ref,
            None,
        )
        .await
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("Unable to setup decision engine dynamic routing")?;
    }

    let record = db
        .insert_routing_algorithm(algo)
        .await
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("Unable to insert record in routing algorithm table")?;

    dynamic_routing_algo_ref.update_algorithm_id(
        algorithm_id,
        feature_to_enable,
        dynamic_routing_type,
    );
    update_business_profile_active_dynamic_algorithm_ref(
        db,
        key_manager_state,
        &key_store,
        business_profile,
        dynamic_routing_algo_ref,
    )
    .await?;

    let new_record = record.foreign_into();

    core_metrics::ROUTING_CREATE_SUCCESS_RESPONSE.add(
        1,
        router_env::metric_attributes!(("profile_id", profile_id.clone())),
    );
    Ok(ApplicationResponse::Json(new_record))
}


pub struct TxnData {
    #[serde(rename = "RequestURL")]
    pub request_url: String,
    pub request_type: RequestType,
    pub request_data: RequestData,
    pub request_method: String,
}


pub struct VecLinearErrorStack<'a>(Vec<LinearErrorStack<'a>>);


pub struct PaypalLinks {
    href: Option<Url>,
    rel: String,
}


pub struct BillingAddress {
    pub email: Email,
    pub first_name: Option<Secret<String>>,
    pub last_name: Option<Secret<String>>,
    pub country: api_models::enums::CountryAlpha2,
    pub phone: Option<Secret<String>>,
    pub city: Option<Secret<String>>,
    pub address: Option<Secret<String>>,
    pub street_number: Option<Secret<String>>,
    pub zip: Option<Secret<String>>,
    pub state: Option<Secret<String>>,
    pub cell: Option<Secret<String>>,
    pub address_match: Option<Secret<String>>,
    pub address_line2: Option<Secret<String>>,
    pub address_line3: Option<Secret<String>>,
    pub home_phone: Option<Secret<String>>,
    pub work_phone: Option<Secret<String>>,
}


pub struct GsmUpdateRequest {
    /// The connector through which payment has gone through
    pub connector: String,
    /// The flow in which the code and message occurred for a connector
    pub flow: String,
    /// The sub_flow in which the code and message occurred  for a connector
    pub sub_flow: String,
    /// code received from the connector
    pub code: String,
    /// message received from the connector
    pub message: String,
    /// status provided by the router
    pub status: Option<String>,
    /// optional error provided by the router
    pub router_error: Option<String>,
    /// decision to be taken for auto retries flow
    /// **Deprecated**: This field is now included as part of `feature_data` under the `Retry` variant.
    #[schema(deprecated)]
    #[schema(value_type = Option<GsmDecision>)]
    pub decision: Option<api_enums::GsmDecision>,
    /// indicates if step_up retry is possible
    /// **Deprecated**: This field is now included as part of `feature_data` under the `Retry` variant.
    #[schema(deprecated)]
    pub step_up_possible: Option<bool>,
    /// error code unified across the connectors
    pub unified_code: Option<String>,
    /// error message unified across the connectors
    pub unified_message: Option<String>,
    /// category in which error belongs to
    #[schema(value_type = Option<ErrorCategory>)]
    pub error_category: Option<api_enums::ErrorCategory>,
    /// indicates if retry with pan is possible
    /// **Deprecated**: This field is now included as part of `feature_data` under the `Retry` variant.
    #[schema(deprecated)]
    pub clear_pan_possible: Option<bool>,
    /// Indicates the GSM feature associated with the request,
    /// such as retry mechanisms or other specific functionalities provided by the system.
    #[schema(value_type = Option<GsmFeature>)]
    pub feature: Option<api_enums::GsmFeature>,
    /// Contains the data relevant to the specified GSM feature, if applicable.
    /// For example, if the `feature` is `Retry`, this will include configuration
    /// details specific to the retry behavior.
    #[schema(value_type = Option<GsmFeatureData>)]
    pub feature_data: Option<common_types::domain::GsmFeatureData>,
}


pub async fn get_action_url_from_paypal(
    state: SessionState,
    tracking_id: String,
    return_url: String,
) -> RouterResult<String> {
    let referral_request = Box::pin(build_referral_request(
        state.clone(),
        tracking_id,
        return_url,
    ))
    .await?;
    let referral_response = http_client::send_request(&state.conf.proxy, referral_request, None)
        .await
        .change_context(ApiErrorResponse::InternalServerError)
        .attach_printable("Failed to send request to paypal referrals")?;

    let parsed_response: types::paypal::PartnerReferralResponse = referral_response
        .json()
        .await
        .change_context(ApiErrorResponse::InternalServerError)
        .attach_printable("Failed to parse paypal response")?;

    parsed_response.extract_action_url()
}


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

pub mod helpers;

use api_models::files;
use error_stack::ResultExt;

use super::errors::{self, RouterResponse};
use crate::{
    consts,
    routes::SessionState,
    services::ApplicationResponse,
    types::{api, domain},
};

pub async fn files_create_core(
    state: SessionState,
    merchant_context: domain::MerchantContext,
    create_file_request: api::CreateFileRequest,
) -> RouterResponse<files::CreateFileResponse> {
    helpers::validate_file_upload(
        &state,
        merchant_context.clone(),
        create_file_request.clone(),
    )
    .await?;
    let file_id = common_utils::generate_id(consts::ID_LENGTH, "file");
    let file_key = format!(
        "{}/{}",
        merchant_context
            .get_merchant_account()
            .get_id()
            .get_string_repr(),
        file_id
    );
    let file_new: diesel_models::FileMetadataNew = diesel_models::file::FileMetadataNew {
        file_id: file_id.clone(),
        merchant_id: merchant_context.get_merchant_account().get_id().clone(),
        file_name: create_file_request.file_name.clone(),
        file_size: create_file_request.file_size,
        file_type: create_file_request.file_type.to_string(),
        provider_file_id: None,
        file_upload_provider: None,
        available: false,
        connector_label: None,
        profile_id: None,
        merchant_connector_id: None,
    };

    let file_metadata_object = state
        .store
        .insert_file_metadata(file_new)
        .await
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("Unable to insert file_metadata")?;
    let (provider_file_id, file_upload_provider, profile_id, merchant_connector_id) = Box::pin(
        helpers::upload_and_get_provider_provider_file_id_profile_id(
            &state,
            &merchant_context,
            &create_file_request,
            file_key.clone(),
        ),
    )
    .await?;

    // Update file metadata
    let update_file_metadata = diesel_models::file::FileMetadataUpdate::Update {
        provider_file_id: Some(provider_file_id),
        file_upload_provider: Some(file_upload_provider),
        available: true,
        profile_id,
        merchant_connector_id,
    };
    state
        .store
        .as_ref()
        .update_file_metadata(file_metadata_object, update_file_metadata)
        .await
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable_lazy(|| {
            format!("Unable to update file_metadata with file_id: {file_id}")
        })?;
    Ok(ApplicationResponse::Json(files::CreateFileResponse {
        file_id,
    }))
}

pub async fn files_delete_core(
    state: SessionState,
    merchant_context: domain::MerchantContext,
    req: api::FileId,
) -> RouterResponse<serde_json::Value> {
    helpers::delete_file_using_file_id(&state, req.file_id.clone(), &merchant_context).await?;
    state
        .store
        .as_ref()
        .delete_file_metadata_by_merchant_id_file_id(
            merchant_context.get_merchant_account().get_id(),
            &req.file_id,
        )
        .await
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("Unable to delete file_metadata")?;
    Ok(ApplicationResponse::StatusOk)
}

pub async fn files_retrieve_core(
    state: SessionState,
    merchant_context: domain::MerchantContext,
    req: api::FileRetrieveRequest,
) -> RouterResponse<serde_json::Value> {
    let file_metadata_object = state
        .store
        .as_ref()
        .find_file_metadata_by_merchant_id_file_id(
            merchant_context.get_merchant_account().get_id(),
            &req.file_id,
        )
        .await
        .change_context(errors::ApiErrorResponse::FileNotFound)
        .attach_printable("Unable to retrieve file_metadata")?;
    let file_info = helpers::retrieve_file_and_provider_file_id_from_file_id(
        &state,
        Some(req.file_id),
        req.dispute_id,
        &merchant_context,
        api::FileDataRequired::Required,
    )
    .await?;
    let content_type = file_metadata_object
        .file_type
        .parse::<mime::Mime>()
        .change_context(errors::ApiErrorResponse::InternalServerError)
        .attach_printable("Failed to parse file content type")?;
    Ok(ApplicationResponse::FileData((
        file_info
            .file_data
            .ok_or(errors::ApiErrorResponse::FileNotAvailable)
            .attach_printable("File data not found")?,
        content_type,
    )))
}


pub struct Server {
    pub port: u16,
    pub workers: usize,
    pub host: String,
}


pub fn new() -> &'static Self {
        &Self {
            #[cfg(feature = "payouts")]
            amount_converter: &FloatMajorUnitForConnector,
        }
    }


pub struct BraintreeCancelRequest {
    query: String,
    variables: VariableCancelInput,
}


File: crates/api_models/src/analytics/frm.rs
 Public functions: 1
 Public structs: 6

use std::{
    collections::hash_map::DefaultHasher,
    hash::{Hash, Hasher},
};

use common_enums::enums::FraudCheckStatus;

#[derive(
    Clone,
    Copy,
    Debug,
    Default,
    Eq,
    PartialEq,
    serde::Serialize,
    serde::Deserialize,
    strum::Display,
    strum::EnumString,
)]
#[serde(rename_all = "snake_case")]
#[strum(serialize_all = "snake_case")]
pub enum FrmTransactionType {
    #[default]
    PreFrm,
    PostFrm,
}

use super::{NameDescription, TimeRange};
#[derive(Clone, Debug, Default, serde::Deserialize, serde::Serialize)]
pub struct FrmFilters {
    #[serde(default)]
    pub frm_status: Vec<FraudCheckStatus>,
    #[serde(default)]
    pub frm_name: Vec<String>,
    #[serde(default)]
    pub frm_transaction_type: Vec<FrmTransactionType>,
}

#[derive(
    Debug,
    serde::Serialize,
    serde::Deserialize,
    strum::AsRefStr,
    PartialEq,
    PartialOrd,
    Eq,
    Ord,
    strum::Display,
    strum::EnumIter,
    Clone,
    Copy,
)]
#[serde(rename_all = "snake_case")]
#[strum(serialize_all = "snake_case")]
pub enum FrmDimensions {
    FrmStatus,
    FrmName,
    FrmTransactionType,
}

#[derive(
    Clone,
    Debug,
    Hash,
    PartialEq,
    Eq,
    serde::Serialize,
    serde::Deserialize,
    strum::Display,
    strum::EnumIter,
    strum::AsRefStr,
)]
#[strum(serialize_all = "snake_case")]
#[serde(rename_all = "snake_case")]
pub enum FrmMetrics {
    FrmTriggeredAttempts,
    FrmBlockedRate,
}

pub mod metric_behaviour {
    pub struct FrmTriggeredAttempts;
    pub struct FrmBlockRate;
}

impl From<FrmMetrics> for NameDescription {
    fn from(value: FrmMetrics) -> Self {
        Self {
            name: value.to_string(),
            desc: String::new(),
        }
    }
}

impl From<FrmDimensions> for NameDescription {
    fn from(value: FrmDimensions) -> Self {
        Self {
            name: value.to_string(),
            desc: String::new(),
        }
    }
}

#[derive(Debug, serde::Serialize, Eq)]
pub struct FrmMetricsBucketIdentifier {
    pub frm_status: Option<String>,
    pub frm_name: Option<String>,
    pub frm_transaction_type: Option<String>,
    #[serde(rename = "time_range")]
    pub time_bucket: TimeRange,
    #[serde(rename = "time_bucket")]
    #[serde(with = "common_utils::custom_serde::iso8601custom")]
    pub start_time: time::PrimitiveDateTime,
}

impl Hash for FrmMetricsBucketIdentifier {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.frm_status.hash(state);
        self.frm_name.hash(state);
        self.frm_transaction_type.hash(state);
        self.time_bucket.hash(state);
    }
}

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

impl FrmMetricsBucketIdentifier {
    pub fn new(
        frm_status: Option<String>,
        frm_name: Option<String>,
        frm_transaction_type: Option<String>,
        normalized_time_range: TimeRange,
    ) -> Self {
        Self {
            frm_status,
            frm_name,
            frm_transaction_type,
            time_bucket: normalized_time_range,
            start_time: normalized_time_range.start_time,
        }
    }
}

#[derive(Debug, serde::Serialize)]
pub struct FrmMetricsBucketValue {
    pub frm_triggered_attempts: Option<u64>,
    pub frm_blocked_rate: Option<f64>,
}

#[derive(Debug, serde::Serialize)]
pub struct FrmMetricsBucketResponse {
    #[serde(flatten)]
    pub values: FrmMetricsBucketValue,
    #[serde(flatten)]
    pub dimensions: FrmMetricsBucketIdentifier,
}


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


pub fn create_merchant_connector_account(
        self,
        source: MerchantConnectorAccount,
    ) -> MerchantConnectorAccount {
        MerchantConnectorAccount {
            connector_type: self.connector_type.unwrap_or(source.connector_type),
            connector_account_details: self
                .connector_account_details
                .unwrap_or(source.connector_account_details),
            disabled: self.disabled,
            payment_methods_enabled: self.payment_methods_enabled,
            frm_config: self.frm_config,
            modified_at: self.modified_at.unwrap_or(source.modified_at),
            pm_auth_config: self.pm_auth_config,
            status: self.status.unwrap_or(source.status),
            feature_metadata: self.feature_metadata,

            ..source
        }
    }


impl api::PaymentSync for Stripe {}


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

impl std::error::Error for for InvalidCrmConfig


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


Documentation: api-reference/v1/gsm/gsm--get.mdx
# Type: Doc File

---
openapi: post /gsm/get
---


pub fn server(config: routes::AppState) -> Scope {
        web::scope("/customers")
            .app_data(web::Data::new(config))
            .service(web::resource("").route(web::post().to(customer_create)))
            .service(
                web::resource("/{customer_id}")
                    .route(web::get().to(customer_retrieve))
                    .route(web::post().to(customer_update))
                    .route(web::delete().to(customer_delete)),
            )
            .service(
                web::resource("/{customer_id}/payment_methods")
                    .route(web::get().to(list_customer_payment_method_api)),
            )
    }


pub fn polymorphic_schema(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
    let input = syn::parse_macro_input!(input as syn::DeriveInput);

    macros::polymorphic_macro_derive_inner(input)
        .unwrap_or_else(|error| error.into_compile_error())
        .into()
}


pub struct VoidBankTransaction {
    #[serde(rename = "id")]
    pub transaction_id: String,
    pub value: StringMajorUnit,
    pub currency: api_models::enums::Currency,
    pub iof_value: Option<StringMajorUnit>,
    pub fx_value: Option<StringMajorUnit>,
    pub exchange_rate: Option<StringMajorUnit>,
    pub exchange_currency: api_models::enums::Currency,
    pub exchanged_value: StringMajorUnit,
    pub exchange_approved: bool,
    pub wire_id: Option<String>,
    pub exchange_id: Option<String>,
    pub movement_date: String,
    pub source_name: Secret<String>,
    pub source_document_number: Secret<String>,
    pub source_document_type: String,
    pub source_id: String,
    pub source_type: String,
    pub source_description: String,
    pub source_bank: Option<String>,
    pub source_branch: Option<String>,
    pub source_account: Option<String>,
    pub source_bank_ispb: Option<String>,
    pub company_id: String,
    pub company_name: String,
}


OpenAPI Block Path: components.schemas.TimeRange
{
  "type": "object",
  "description": "A type representing a range of time for filtering, including a mandatory start time and an optional end time.",
  "required": [
    "start_time"
  ],
  "properties": {
    "start_time": {
      "type": "string",
      "format": "date-time",
      "description": "The start time to filter payments list or to get list of filters. To get list of filters start time is needed to be passed"
    },
    "end_time": {
      "type": "string",
      "format": "date-time",
      "description": "The end time to filter payments list or to get list of filters. If not passed the default time is now",
      "nullable": true
    }
  }
}


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

use error_stack::report;
use router_env::{instrument, tracing};
use storage_impl::MockDb;

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

#[async_trait::async_trait]
pub trait BlocklistLookupInterface {
    async fn insert_blocklist_lookup_entry(
        &self,
        blocklist_lookup_new: storage::BlocklistLookupNew,
    ) -> CustomResult<storage::BlocklistLookup, errors::StorageError>;

    async fn find_blocklist_lookup_entry_by_merchant_id_fingerprint(
        &self,
        merchant_id: &common_utils::id_type::MerchantId,
        fingerprint: &str,
    ) -> CustomResult<storage::BlocklistLookup, errors::StorageError>;

    async fn delete_blocklist_lookup_entry_by_merchant_id_fingerprint(
        &self,
        merchant_id: &common_utils::id_type::MerchantId,
        fingerprint: &str,
    ) -> CustomResult<storage::BlocklistLookup, errors::StorageError>;
}

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

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

    #[instrument(skip_all)]
    async fn delete_blocklist_lookup_entry_by_merchant_id_fingerprint(
        &self,
        merchant_id: &common_utils::id_type::MerchantId,
        fingerprint: &str,
    ) -> CustomResult<storage::BlocklistLookup, errors::StorageError> {
        let conn = connection::pg_connection_write(self).await?;
        storage::BlocklistLookup::delete_by_merchant_id_fingerprint(&conn, merchant_id, fingerprint)
            .await
            .map_err(|error| report!(errors::StorageError::from(error)))
    }
}

#[async_trait::async_trait]
impl BlocklistLookupInterface for MockDb {
    #[instrument(skip_all)]
    async fn insert_blocklist_lookup_entry(
        &self,
        _blocklist_lookup_entry: storage::BlocklistLookupNew,
    ) -> CustomResult<storage::BlocklistLookup, errors::StorageError> {
        Err(errors::StorageError::MockDbError)?
    }

    async fn find_blocklist_lookup_entry_by_merchant_id_fingerprint(
        &self,
        _merchant_id: &common_utils::id_type::MerchantId,
        _fingerprint: &str,
    ) -> CustomResult<storage::BlocklistLookup, errors::StorageError> {
        Err(errors::StorageError::MockDbError)?
    }

    async fn delete_blocklist_lookup_entry_by_merchant_id_fingerprint(
        &self,
        _merchant_id: &common_utils::id_type::MerchantId,
        _fingerprint: &str,
    ) -> CustomResult<storage::BlocklistLookup, errors::StorageError> {
        Err(errors::StorageError::MockDbError)?
    }
}

#[async_trait::async_trait]
impl BlocklistLookupInterface for KafkaStore {
    #[instrument(skip_all)]
    async fn insert_blocklist_lookup_entry(
        &self,
        blocklist_lookup_entry: storage::BlocklistLookupNew,
    ) -> CustomResult<storage::BlocklistLookup, errors::StorageError> {
        self.diesel_store
            .insert_blocklist_lookup_entry(blocklist_lookup_entry)
            .await
    }

    #[instrument(skip_all)]
    async fn find_blocklist_lookup_entry_by_merchant_id_fingerprint(
        &self,
        merchant_id: &common_utils::id_type::MerchantId,
        fingerprint: &str,
    ) -> CustomResult<storage::BlocklistLookup, errors::StorageError> {
        self.diesel_store
            .find_blocklist_lookup_entry_by_merchant_id_fingerprint(merchant_id, fingerprint)
            .await
    }

    #[instrument(skip_all)]
    async fn delete_blocklist_lookup_entry_by_merchant_id_fingerprint(
        &self,
        merchant_id: &common_utils::id_type::MerchantId,
        fingerprint: &str,
    ) -> CustomResult<storage::BlocklistLookup, errors::StorageError> {
        self.diesel_store
            .delete_blocklist_lookup_entry_by_merchant_id_fingerprint(merchant_id, fingerprint)
            .await
    }
}


impl<K, V> Default for DenseMap<K, V> {
    fn default() -> Self {
        Self::new()
    }
}


pub async fn list_invitations_for_user(
    state: web::Data<AppState>,
    req: HttpRequest,
) -> HttpResponse {
    let flow = Flow::ListInvitationsForUser;

    Box::pin(api::server_wrap(
        flow,
        state.clone(),
        &req,
        (),
        |state, user_id_from_token, _, _| {
            user_role_core::list_invitations_for_user(state, user_id_from_token)
        },
        &auth::SinglePurposeOrLoginTokenAuth(TokenPurpose::AcceptInvite),
        api_locking::LockAction::NotApplicable,
    ))
    .await
}


pub struct SquarePaymentsRequest {
    amount_money: SquarePaymentsAmountData,
    idempotency_key: Secret<String>,
    source_id: Secret<String>,
    autocomplete: bool,
    external_details: SquarePaymentsRequestExternalDetails,
}


impl api::Refund for Mpgs {}


impl api::Refund for Paysafe {}


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


pub async fn routing_update_default_config() {}


pub struct DlocalPaymentsCancelRequest {
    pub cancel_id: String,
}


pub async fn new_token(
        user_id: String,
        purpose: TokenPurpose,
        origin: domain::Origin,
        settings: &Settings,
        path: Vec<TokenPurpose>,
        tenant_id: Option<id_type::TenantId>,
    ) -> UserResult<String> {
        let exp_duration =
            std::time::Duration::from_secs(consts::SINGLE_PURPOSE_TOKEN_TIME_IN_SECS);
        let exp = jwt::generate_exp(exp_duration)?.as_secs();
        let token_payload = Self {
            user_id,
            purpose,
            origin,
            exp,
            path,
            tenant_id,
        };
        jwt::generate_jwt(&token_payload, settings).await
    }


File: crates/hyperswitch_connectors/src/connectors/silverflow/transformers.rs
 Public structs: 35

use common_enums::enums;
use common_utils::types::MinorUnit;
use hyperswitch_domain_models::{
    payment_method_data::PaymentMethodData,
    router_data::{ConnectorAuthType, RouterData},
    router_flow_types::{
        payments::Void,
        refunds::{Execute, RSync},
    },
    router_request_types::{PaymentsCancelData, ResponseId},
    router_response_types::{PaymentsResponseData, RefundsResponseData},
    types::{PaymentsAuthorizeRouterData, PaymentsCaptureRouterData, RefundsRouterData},
};
use hyperswitch_interfaces::errors;
use masking::{ExposeInterface, PeekInterface, Secret};
use serde::{Deserialize, Serialize};

use crate::{
    types::{RefundsResponseRouterData, ResponseRouterData},
    utils::{self, CardData},
};

//TODO: Fill the struct with respective fields
pub struct SilverflowRouterData<T> {
    pub amount: MinorUnit, // The type of amount that a connector accepts, for example, String, i64, f64, etc.
    pub router_data: T,
}

impl<T> From<(MinorUnit, T)> for SilverflowRouterData<T> {
    fn from((amount, item): (MinorUnit, T)) -> Self {
        //Todo :  use utils to convert the amount to the type of amount that a connector accepts
        Self {
            amount,
            router_data: item,
        }
    }
}

// Basic structures for Silverflow API
#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Amount {
    value: MinorUnit,
    currency: String,
}

#[derive(Default, Debug, Serialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct Card {
    number: cards::CardNumber,
    expiry_month: Secret<String>,
    expiry_year: Secret<String>,
    cvc: Secret<String>,
    holder_name: Option<Secret<String>>,
}

#[derive(Default, Debug, Serialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct MerchantAcceptorResolver {
    merchant_acceptor_key: String,
}

#[derive(Default, Debug, Serialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct SilverflowPaymentsRequest {
    merchant_acceptor_resolver: MerchantAcceptorResolver,
    card: Card,
    amount: Amount,
    #[serde(rename = "type")]
    payment_type: PaymentType,
    clearing_mode: String,
}

#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct PaymentType {
    intent: String,
    card_entry: String,
    order: String,
}

impl TryFrom<&SilverflowRouterData<&PaymentsAuthorizeRouterData>> for SilverflowPaymentsRequest {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        item: &SilverflowRouterData<&PaymentsAuthorizeRouterData>,
    ) -> Result<Self, Self::Error> {
        // Check if 3DS is being requested - Silverflow doesn't support 3DS
        if matches!(
            item.router_data.auth_type,
            enums::AuthenticationType::ThreeDs
        ) {
            return Err(errors::ConnectorError::NotImplemented(
                utils::get_unimplemented_payment_method_error_message("silverflow"),
            )
            .into());
        }

        match item.router_data.request.payment_method_data.clone() {
            PaymentMethodData::Card(req_card) => {
                // Extract merchant acceptor key from connector auth
                let auth = SilverflowAuthType::try_from(&item.router_data.connector_auth_type)?;

                let card = Card {
                    number: req_card.card_number.clone(),
                    expiry_month: req_card.card_exp_month.clone(),
                    expiry_year: req_card.card_exp_year.clone(),
                    cvc: req_card.card_cvc.clone(),
                    holder_name: req_card.get_cardholder_name().ok(),
                };

                // Determine clearing mode based on capture method
                let clearing_mode = match item.router_data.request.capture_method {
                    Some(enums::CaptureMethod::Manual) => "manual".to_string(),
                    Some(enums::CaptureMethod::Automatic) | None => "auto".to_string(),
                    Some(enums::CaptureMethod::ManualMultiple)
                    | Some(enums::CaptureMethod::Scheduled)
                    | Some(enums::CaptureMethod::SequentialAutomatic) => {
                        return Err(errors::ConnectorError::NotSupported {
                            message: "Capture method not supported by Silverflow".to_string(),
                            connector: "Silverflow",
                        }
                        .into());
                    }
                };

                Ok(Self {
                    merchant_acceptor_resolver: MerchantAcceptorResolver {
                        merchant_acceptor_key: auth.merchant_acceptor_key.expose(),
                    },
                    card,
                    amount: Amount {
                        value: item.amount,
                        currency: item.router_data.request.currency.to_string(),
                    },
                    payment_type: PaymentType {
                        intent: "purchase".to_string(),
                        card_entry: "e-commerce".to_string(),
                        order: "checkout".to_string(),
                    },
                    clearing_mode,
                })
            }
            _ => Err(errors::ConnectorError::NotImplemented(
                utils::get_unimplemented_payment_method_error_message("silverflow"),
            )
            .into()),
        }
    }
}

// Auth Struct for HTTP Basic Authentication
pub struct SilverflowAuthType {
    pub(super) api_key: Secret<String>,
    pub(super) api_secret: Secret<String>,
    pub(super) merchant_acceptor_key: Secret<String>,
}

impl TryFrom<&ConnectorAuthType> for SilverflowAuthType {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(auth_type: &ConnectorAuthType) -> Result<Self, Self::Error> {
        match auth_type {
            ConnectorAuthType::SignatureKey {
                api_key,
                key1,
                api_secret,
            } => Ok(Self {
                api_key: api_key.clone(),
                api_secret: api_secret.clone(),
                merchant_acceptor_key: key1.clone(),
            }),
            _ => Err(errors::ConnectorError::FailedToObtainAuthType.into()),
        }
    }
}
// Enum for Silverflow payment authorization status
#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "lowercase")]
pub enum SilverflowAuthorizationStatus {
    Approved,
    Declined,
    Failed,
    #[default]
    Pending,
}

// Enum for Silverflow payment clearing status
#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "lowercase")]
pub enum SilverflowClearingStatus {
    Cleared,
    #[default]
    Pending,
    Failed,
}

// Payment Authorization Response Structures
#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct PaymentStatus {
    pub authentication: String,
    pub authorization: SilverflowAuthorizationStatus,
    pub clearing: SilverflowClearingStatus,
}

#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct MerchantAcceptorRef {
    pub key: String,
    pub version: i32,
}

#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct CardResponse {
    pub masked_number: String,
}

#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Authentication {
    pub sca: SCA,
    pub cvc: Secret<String>,
    pub avs: String,
}

#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct SCA {
    pub compliance: String,
    pub compliance_reason: String,
    pub method: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub result: Option<SCAResult>,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct SCAResult {
    pub version: String,
    pub directory_server_trans_id: String,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct AuthorizationIsoFields {
    pub response_code: String,
    pub response_code_description: String,
    pub authorization_code: String,
    pub network_code: String,
    pub system_trace_audit_number: Secret<String>,
    pub retrieval_reference_number: String,
    pub eci: String,
    pub network_specific_fields: NetworkSpecificFields,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct NetworkSpecificFields {
    pub transaction_identifier: String,
    pub cvv2_result_code: String,
}

#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct SilverflowPaymentsResponse {
    pub key: String,
    pub merchant_acceptor_ref: MerchantAcceptorRef,
    pub card: CardResponse,
    pub amount: Amount,
    #[serde(rename = "type")]
    pub payment_type: PaymentType,
    pub clearing_mode: String,
    pub status: PaymentStatus,
    pub authentication: Authentication,
    pub local_transaction_date_time: String,
    pub fraud_liability: String,
    pub authorization_iso_fields: Option<AuthorizationIsoFields>,
    pub created: String,
    pub version: i32,
}

impl From<&PaymentStatus> for common_enums::AttemptStatus {
    fn from(status: &PaymentStatus) -> Self {
        match (&status.authorization, &status.clearing) {
            (SilverflowAuthorizationStatus::Approved, SilverflowClearingStatus::Cleared) => {
                Self::Charged
            }
            (SilverflowAuthorizationStatus::Approved, SilverflowClearingStatus::Pending) => {
                Self::Authorized
            }
            (SilverflowAuthorizationStatus::Approved, SilverflowClearingStatus::Failed) => {
                Self::Failure
            }
            (SilverflowAuthorizationStatus::Declined, _) => Self::Failure,
            (SilverflowAuthorizationStatus::Failed, _) => Self::Failure,
            (SilverflowAuthorizationStatus::Pending, _) => Self::Pending,
        }
    }
}

impl<F, T> TryFrom<ResponseRouterData<F, SilverflowPaymentsResponse, T, PaymentsResponseData>>
    for RouterData<F, T, PaymentsResponseData>
{
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        item: ResponseRouterData<F, SilverflowPaymentsResponse, T, PaymentsResponseData>,
    ) -> Result<Self, Self::Error> {
        Ok(Self {
            status: common_enums::AttemptStatus::from(&item.response.status),
            response: Ok(PaymentsResponseData::TransactionResponse {
                resource_id: ResponseId::ConnectorTransactionId(item.response.key.clone()),
                redirection_data: Box::new(None),
                mandate_reference: Box::new(None),
                connector_metadata: None,
                network_txn_id: item
                    .response
                    .authorization_iso_fields
                    .as_ref()
                    .map(|fields| {
                        fields
                            .network_specific_fields
                            .transaction_identifier
                            .clone()
                    }),
                connector_response_reference_id: Some(item.response.key.clone()),
                incremental_authorization_allowed: Some(false),
                charges: None,
            }),
            ..item.data
        })
    }
}

// CAPTURE:
// Type definition for CaptureRequest based on Silverflow API documentation
#[derive(Default, Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct SilverflowCaptureRequest {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub amount: Option<i64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub close_charge: Option<bool>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub reference: Option<String>,
}

impl TryFrom<&PaymentsCaptureRouterData> for SilverflowCaptureRequest {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(item: &PaymentsCaptureRouterData) -> Result<Self, Self::Error> {
        // amount_to_capture is directly an i64, representing the amount in minor units
        let amount_to_capture = Some(item.request.amount_to_capture);

        Ok(Self {
            amount: amount_to_capture,
            close_charge: Some(true), // Default to closing charge after capture
            reference: Some(format!("capture-{}", item.payment_id)),
        })
    }
}

// Enum for Silverflow capture status
#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "lowercase")]
pub enum SilverflowCaptureStatus {
    Completed,
    #[default]
    Pending,
    Failed,
}

// Type definition for CaptureResponse based on Silverflow clearing action response
#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct SilverflowCaptureResponse {
    #[serde(rename = "type")]
    pub action_type: String,
    pub key: String,
    pub charge_key: String,
    pub status: SilverflowCaptureStatus,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub reference: Option<String>,
    pub amount: Amount,
    pub created: String,
    pub last_modified: String,
    pub version: i32,
}

impl From<&SilverflowCaptureResponse> for common_enums::AttemptStatus {
    fn from(response: &SilverflowCaptureResponse) -> Self {
        match response.status {
            SilverflowCaptureStatus::Completed => Self::Charged,
            SilverflowCaptureStatus::Pending => Self::Pending,
            SilverflowCaptureStatus::Failed => Self::Failure,
        }
    }
}

impl<F, T> TryFrom<ResponseRouterData<F, SilverflowCaptureResponse, T, PaymentsResponseData>>
    for RouterData<F, T, PaymentsResponseData>
{
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        item: ResponseRouterData<F, SilverflowCaptureResponse, T, PaymentsResponseData>,
    ) -> Result<Self, Self::Error> {
        Ok(Self {
            status: common_enums::AttemptStatus::from(&item.response),
            response: Ok(PaymentsResponseData::TransactionResponse {
                resource_id: ResponseId::ConnectorTransactionId(item.response.charge_key.clone()),
                redirection_data: Box::new(None),
                mandate_reference: Box::new(None),
                connector_metadata: None,
                network_txn_id: None,
                connector_response_reference_id: Some(item.response.key.clone()),
                incremental_authorization_allowed: Some(false),
                charges: None,
            }),
            ..item.data
        })
    }
}

// VOID/REVERSE:
// Type definition for Reverse Charge Request based on Silverflow API documentation
#[derive(Default, Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct SilverflowVoidRequest {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub replacement_amount: Option<i64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub reference: Option<String>,
}

impl TryFrom<&RouterData<Void, PaymentsCancelData, PaymentsResponseData>>
    for SilverflowVoidRequest
{
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        item: &RouterData<Void, PaymentsCancelData, PaymentsResponseData>,
    ) -> Result<Self, Self::Error> {
        Ok(Self {
            replacement_amount: Some(0), // Default to 0 for full reversal
            reference: Some(format!("void-{}", item.payment_id)),
        })
    }
}

// Enum for Silverflow void authorization status
#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "lowercase")]
pub enum SilverflowVoidAuthorizationStatus {
    Approved,
    Declined,
    Failed,
    #[default]
    Pending,
}

// Type definition for Void Status (only authorization, no clearing)
#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct VoidStatus {
    pub authorization: SilverflowVoidAuthorizationStatus,
}

// Type definition for Reverse Charge Response based on Silverflow API documentation
#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct SilverflowVoidResponse {
    #[serde(rename = "type")]
    pub action_type: String,
    pub key: String,
    pub charge_key: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub reference: Option<String>,
    pub replacement_amount: Amount,
    pub status: VoidStatus,
    pub authorization_response: Option<AuthorizationResponse>,
    pub created: String,
    pub last_modified: String,
    pub version: i32,
}

impl From<&SilverflowVoidResponse> for common_enums::AttemptStatus {
    fn from(response: &SilverflowVoidResponse) -> Self {
        match response.status.authorization {
            SilverflowVoidAuthorizationStatus::Approved => Self::Voided,
            SilverflowVoidAuthorizationStatus::Declined
            | SilverflowVoidAuthorizationStatus::Failed => Self::VoidFailed,
            SilverflowVoidAuthorizationStatus::Pending => Self::Pending,
        }
    }
}

impl<F, T> TryFrom<ResponseRouterData<F, SilverflowVoidResponse, T, PaymentsResponseData>>
    for RouterData<F, T, PaymentsResponseData>
{
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        item: ResponseRouterData<F, SilverflowVoidResponse, T, PaymentsResponseData>,
    ) -> Result<Self, Self::Error> {
        Ok(Self {
            status: common_enums::AttemptStatus::from(&item.response),
            response: Ok(PaymentsResponseData::TransactionResponse {
                resource_id: ResponseId::ConnectorTransactionId(item.response.charge_key.clone()),
                redirection_data: Box::new(None),
                mandate_reference: Box::new(None),
                connector_metadata: None,
                network_txn_id: None,
                connector_response_reference_id: Some(item.response.key.clone()),
                incremental_authorization_allowed: Some(false),
                charges: None,
            }),
            ..item.data
        })
    }
}

// REFUND :
// Type definition for DynamicDescriptor
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct DynamicDescriptor {
    pub merchant_name: String,
    pub merchant_city: String,
}

// Type definition for RefundRequest
#[derive(Default, Debug, Serialize)]
pub struct SilverflowRefundRequest {
    #[serde(rename = "refundAmount")]
    pub refund_amount: MinorUnit,
    pub reference: String,
}

impl<F> TryFrom<&SilverflowRouterData<&RefundsRouterData<F>>> for SilverflowRefundRequest {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(item: &SilverflowRouterData<&RefundsRouterData<F>>) -> Result<Self, Self::Error> {
        Ok(Self {
            refund_amount: item.amount,
            reference: format!("refund-{}", item.router_data.request.refund_id),
        })
    }
}

// Type definition for Authorization Response
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct AuthorizationResponse {
    pub network: String,

    pub response_code: String,

    pub response_code_description: String,
}

// Enum for Silverflow refund authorization status
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "lowercase")]
pub enum SilverflowRefundAuthorizationStatus {
    Approved,
    Declined,
    Failed,
    Pending,
}

// Enum for Silverflow refund status
#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "lowercase")]
pub enum SilverflowRefundStatus {
    Success,
    Failure,
    #[default]
    Pending,
}

impl From<&SilverflowRefundStatus> for enums::RefundStatus {
    fn from(item: &SilverflowRefundStatus) -> Self {
        match item {
            SilverflowRefundStatus::Success => Self::Success,
            SilverflowRefundStatus::Failure => Self::Failure,
            SilverflowRefundStatus::Pending => Self::Pending,
        }
    }
}

// Type definition for Refund Response
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct RefundResponse {
    #[serde(rename = "type")]
    pub action_type: String,
    pub key: String,
    pub charge_key: String,
    pub reference: String,
    pub amount: Amount,
    pub status: SilverflowRefundStatus,
    pub clear_after: Option<String>,
    pub authorization_response: Option<AuthorizationResponse>,
    pub created: String,
    pub last_modified: String,
    pub version: i32,
}

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

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

// TOKENIZATION:
// Type definition for TokenizationRequest
#[derive(Default, Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct SilverflowTokenizationRequest {
    pub reference: String,

    pub card_data: SilverflowCardData,
}

#[derive(Default, Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct SilverflowCardData {
    pub number: String,
    pub expiry_month: Secret<String>,
    pub expiry_year: Secret<String>,
    pub cvc: String,
    pub holder_name: String,
}

impl TryFrom<&PaymentsAuthorizeRouterData> for SilverflowTokenizationRequest {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(item: &PaymentsAuthorizeRouterData) -> Result<Self, Self::Error> {
        match item.request.payment_method_data.clone() {
            PaymentMethodData::Card(req_card) => {
                let card_data = SilverflowCardData {
                    number: req_card.card_number.peek().to_string(),
                    expiry_month: req_card.card_exp_month.clone(),
                    expiry_year: req_card.card_exp_year.clone(),
                    cvc: req_card.card_cvc.clone().expose(),
                    holder_name: req_card
                        .get_cardholder_name()
                        .unwrap_or(Secret::new("".to_string()))
                        .expose(),
                };

                Ok(Self {
                    reference: format!("CUSTOMER_ID_{}", item.payment_id),
                    card_data,
                })
            }
            _ => Err(errors::ConnectorError::NotImplemented(
                utils::get_unimplemented_payment_method_error_message("silverflow"),
            )
            .into()),
        }
    }
}

// Add TryFrom implementation for direct tokenization router data
impl
    TryFrom<
        &RouterData<
            hyperswitch_domain_models::router_flow_types::payments::PaymentMethodToken,
            hyperswitch_domain_models::router_request_types::PaymentMethodTokenizationData,
            PaymentsResponseData,
        >,
    > for SilverflowTokenizationRequest
{
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        item: &RouterData<
            hyperswitch_domain_models::router_flow_types::payments::PaymentMethodToken,
            hyperswitch_domain_models::router_request_types::PaymentMethodTokenizationData,
            PaymentsResponseData,
        >,
    ) -> Result<Self, Self::Error> {
        match item.request.payment_method_data.clone() {
            PaymentMethodData::Card(req_card) => {
                let card_data = SilverflowCardData {
                    number: req_card.card_number.peek().to_string(),
                    expiry_month: req_card.card_exp_month.clone(),
                    expiry_year: req_card.card_exp_year.clone(),
                    cvc: req_card.card_cvc.clone().expose(),
                    holder_name: req_card
                        .get_cardholder_name()
                        .unwrap_or(Secret::new("".to_string()))
                        .expose(),
                };

                Ok(Self {
                    reference: format!("CUSTOMER_ID_{}", item.payment_id),
                    card_data,
                })
            }
            _ => Err(errors::ConnectorError::NotImplemented(
                utils::get_unimplemented_payment_method_error_message("silverflow"),
            )
            .into()),
        }
    }
}

// Type definition for TokenizationResponse
#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct SilverflowTokenizationResponse {
    pub key: String,
    #[serde(rename = "agentKey")]
    pub agent_key: String,
    pub last4: String,
    pub status: String,
    pub reference: String,
    #[serde(rename = "cardInfo")]
    pub card_info: Vec<CardInfo>,
    pub created: String,
    #[serde(rename = "cvcPresent")]
    pub cvc_present: bool,
    pub version: i32,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct CardInfo {
    #[serde(rename = "infoSource")]
    pub info_source: String,
    pub network: String,
    #[serde(rename = "primaryNetwork")]
    pub primary_network: bool,
}

impl<F, T> TryFrom<ResponseRouterData<F, SilverflowTokenizationResponse, T, PaymentsResponseData>>
    for RouterData<F, T, PaymentsResponseData>
{
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(
        item: ResponseRouterData<F, SilverflowTokenizationResponse, T, PaymentsResponseData>,
    ) -> Result<Self, Self::Error> {
        Ok(Self {
            response: Ok(PaymentsResponseData::TokenizationResponse {
                token: item.response.key,
            }),
            ..item.data
        })
    }
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct TokenizedCardDetails {
    pub masked_card_number: String,
    pub expiry_month: Secret<String>,
    pub expiry_year: Secret<String>,
    pub card_brand: String,
}

// WEBHOOKS:
// Type definition for Webhook Event structures
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct SilverflowWebhookEvent {
    pub event_type: String,
    pub event_data: SilverflowWebhookEventData,
    pub event_id: String,
    pub created: String,
    pub version: i32,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct SilverflowWebhookEventData {
    pub charge_key: Option<String>,
    pub refund_key: Option<String>,
    pub status: Option<PaymentStatus>,
    pub amount: Option<Amount>,
    pub transaction_reference: Option<String>,
}

// Error Response Structures based on Silverflow API format
#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct ErrorDetails {
    pub field: String,
    pub issue: String,
}

#[derive(Default, Debug, Serialize, Deserialize, PartialEq)]
pub struct SilverflowErrorResponse {
    pub error: SilverflowError,
}

#[derive(Default, Debug, Serialize, Deserialize, PartialEq)]
pub struct SilverflowError {
    pub code: String,
    pub message: String,
    pub details: Option<ErrorDetails>,
}


impl api::PaymentToken for Trustpayments {}

impl api::PaymentToken for for Trustpayments


pub async fn get_retries(
    state: &app::SessionState,
    retries: Option<i32>,
    merchant_id: &common_utils::id_type::MerchantId,
    retry_type: PayoutRetryType,
) -> Option<i32> {
    match retries {
        Some(retries) => Some(retries),
        None => {
            let key = merchant_id.get_max_auto_single_connector_payout_retries_enabled(retry_type);
            let db = &*state.store;
            db.find_config_by_key(key.as_str())
                .await
                .change_context(errors::ApiErrorResponse::InternalServerError)
                .and_then(|retries_config| {
                    retries_config
                        .config
                        .parse::<i32>()
                        .change_context(errors::ApiErrorResponse::InternalServerError)
                        .attach_printable("Retries config parsing failed")
                })
                .map_err(|err| {
                    logger::error!(retries_error=?err);
                    None::<i32>
                })
                .ok()
        }
    }
}


impl api::PaymentCapture for Juspaythreedsserver {}

impl api::PaymentCapture for for Juspaythreedsserver


pub fn set_three_d_s_comp_ind(mut self, three_d_s_comp_ind: ThreeDSCompInd) -> Self {
        self.three_d_s_comp_ind = Some(three_d_s_comp_ind);
        self
    }


pub struct PaymentMethod {
    pub customer_id: common_utils::id_type::CustomerId,
    pub merchant_id: common_utils::id_type::MerchantId,
    pub payment_method_id: String,
    #[diesel(deserialize_as = super::OptionalDieselArray<storage_enums::Currency>)]
    pub accepted_currency: Option<Vec<storage_enums::Currency>>,
    pub scheme: Option<String>,
    pub token: Option<String>,
    pub cardholder_name: Option<Secret<String>>,
    pub issuer_name: Option<String>,
    pub issuer_country: Option<String>,
    #[diesel(deserialize_as = super::OptionalDieselArray<String>)]
    pub payer_country: Option<Vec<String>>,
    pub is_stored: Option<bool>,
    pub swift_code: Option<String>,
    pub direct_debit_token: Option<String>,
    pub created_at: PrimitiveDateTime,
    pub last_modified: PrimitiveDateTime,
    pub payment_method: Option<storage_enums::PaymentMethod>,
    pub payment_method_type: Option<storage_enums::PaymentMethodType>,
    pub payment_method_issuer: Option<String>,
    pub payment_method_issuer_code: Option<storage_enums::PaymentMethodIssuerCode>,
    pub metadata: Option<pii::SecretSerdeValue>,
    pub payment_method_data: Option<Encryption>,
    pub locker_id: Option<String>,
    pub last_used_at: PrimitiveDateTime,
    pub connector_mandate_details: Option<serde_json::Value>,
    pub customer_acceptance: Option<pii::SecretSerdeValue>,
    pub status: storage_enums::PaymentMethodStatus,
    pub network_transaction_id: Option<String>,
    pub client_secret: Option<String>,
    pub payment_method_billing_address: Option<Encryption>,
    pub updated_by: Option<String>,
    pub version: common_enums::ApiVersion,
    pub network_token_requestor_reference_id: Option<String>,
    pub network_token_locker_id: Option<String>,
    pub network_token_payment_method_data: Option<Encryption>,
}


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


Web Documentation: Previous Roadmap - Q3 2025 | Hyperswitch
# Type: Web Doc

🗺 Our Roadmap typically pans out over a 3-month period and we establish topics we work on upfront.
👂And as always, we listen to your feedback and adapt our plans if needed.
Core Values
Our core values have pretty much remained the same since the early days and here they are:
Make payments more
accessible
and
affordable
to every digital business
Staying
simple
and
super-lightweight
, and at the same time
reliable
and
scalable
payment switch
Being
community-first
in ideation, planning and execution of features
Themes for Roadmap
Earlier this year, Hyperswitch was made more modular to provide businesses with focused solutions to specific payment-related problems. Hence, our roadmap, starting this quarter, will be published under each module. A summary of the 8 product modules is provided below :
Core Orchestration:
The core module supporting workflows unifying various connector
Vault:
Simplifying PCI compliance and data privacy regulations through a standalone Card Vault
Cost Observability:
Tracking and reducing payment processing costs via PSP reports.
Authentication:
Data driven 3DS routing decision system and unified authentication SDK to encompass the diversity of authentication products.
Intelligent Routing:
Routing service to dynamically select the most optimal PSP/ network in real time exploring/exploiting/managing multiple objectives simultaneously.

Alternate Payment Method Widgets:
Embracing the ever expanding diversity of payment methods and payment experiences through orchestration, and a simple add-on button to Checkout.
Revenue Recovery:
A payment recovery sub-system with a customizable retry engine that reduces passive churn to recover failed subscription payments.
Reconciliation:
Improving Finops efficiency in multi-acquirer settlement reconciliation.
Roadmap
Core Orchestration
Expand Hyperswitch with new payment connector integrations including Worldpay Vantiv, Payload, Dwolla, Bluecode, Checkbook.io, Trust Payments, Nordea, and Silverflow
Extend support for additional payment methods across existing integrations such as Multisafe, Airwallex, Braintree, and Fiserv
Introduce split payment support across - Gift cards, Long-term lending/leasing providers
File exchange based integration for payment method verification, payment processing and settlement instructions
Asynchronous chargeback handling for connectors without webhook support
L2 and L3 card data enablement across key acquirers
Vault
Standalone Network Tokenization service for SaaS merchants
Authentication
Improve authentication rates and user experience with EMVCo certified Juspay 3DS Server and Juspay 3DS SDK
Authentication Observability to provide analytics and insights to merchants with tightly coupled Acquirer 3DS for better authentication and authorization results.
Revenue Recovery
Open-source revenue recovery: Merchants will be able to self-deploy Hyperswitch's integrations and intelligence services onto their own stack
Multi-card retries: The system will intelligently utilize payment methods already present with the customer to perform retries on a given invoice
Intelligent invoice retrying: Automatically retries invoices declined due to hard decline error codes, within the retry budget specified by the merchant
Custom subscription support: Enables integration with the merchant’s in-house subscription management platform to recover failed payments
Intelligent Routing
Audit Trail and observability dashboard: Allows monitoring of performance across various routing modules
Extension of Least Cost Routing to wallet payments: Includes Apple Pay and Google Pay
Cost Observability
Smarter Fee Attribution Engine: Enhancing our system’s ability to accurately derive fee names from fragmented or ambiguous reports, fee rates and attribute costs across key dimensions such as card variants, acquirers, and funding sources
Conversational AI Interface: Introducing an intuitive, AI-powered chat experience that allows users to explore their payment processing fees through a rich, context-aware interface, making cost observability more interactive, insightful, and user-friendly
Expanded Acquirer Coverage: Adding support for five or more new acquirer report formats, enabling broader compatibility and faster onboarding for merchants working with a variety of providers
Reconciliation
N‑way ingestion & transformation: implement backend‑configured pipelines for any mix of OMS, PSP and bank asources to define normalization and transformation rules
Reconciliation summary views: display real‑time n‑way match rates, exception counts and trend charts in dashboard widgets, with click‑through to transaction‑ vs. entry‑level drill‑downs and one‑click resolution actions.
Transaction‑level audit logs: capture every transaction event in full detail with immutable records to ensure no information is lost
Custom export & reporting: enable merchants to generate and download tailored reconciliation reports
Adyen integration & auto‑fetch: provide a one‑click Adyen connector that securely pulls transactions on a schedule, auto‑maps fields and normalizes into your unified schema
Want to contribute to the roadmap?
Submit an idea or feature request here
with a simple explanation on
What?
and
Why?
included.
29 days ago
Was this helpful?