Bug: [FEATURE] Card Testing Guard



### Feature Description

We have implemented three rules for detecting and preventing this card testing attacks:

I) Card <> IP Blocking for Merchant : If there are X number of unsuccessful payment attempts from a single IP Address for a specific merchant, then that combination of Card <> IP will be blocked for that merchant for a particular duration.

II) Card Blocking for Guest Users for Merchant: If there are X number of unsuccessful payment attempts for a single card, then guest user payments will be blocked for that card and that merchant for a particular duration. Logged in customers will still be able to use that card for payment.

III) Customer ID Blocking for Merchant: If there are X number of unsuccessful payment attempts from a single Customer ID, then that customer ID will be blocked from making any payments for a particular duration.

These unsuccessful payment thresholds and duration for blocking is configurable and stored in database.
Whether the merchants want these rules to be enabled/disabled, that is also configurable.

### Possible Implementation

The attacker gets the `client_secret` from the payment intent create call which happens through our SDK, and uses the `client_secret` to hit the /confirm API repeatedly with different sets of card numbers and CVC.

A method validate_request_with_state has been created in the `GetTracker` trait which enforces the three above mentioned rules depending on the `business_profile` config. The `validate_request_with_state` method internally calls `validate_card_ip_blocking_for_business_profile` method, `validate_guest_user_card_blocking_for_business_profile` method and `validate_customer_id_blocking_for_business_profile` method for performing the below validations:

I) Card<>IP Blocking: A fingerprint is generated for the card which is unique to the `business_profile` (by using a hash key which is unique to the profile and stored as `card_testing_secret_key` in `business_profile`). This is done so that the cards are blocked at a profile level. The IP Address is fetched from the payment intent create request, and then for each unsuccessful payment attempt, the value of the redis key CardFingerprint<>IP is increased by 1, and after it reaches a certain threshold, it is blocked.

II) Guest User Card Blocking: A fingerprint is generated for the card which is unique to the `business_profile` (by using a hash key which is unique to the profile and stored as `card_testing_secret_key` in `business_profile`). This is done so that the cards are not blocked at a profile level. For each unsuccessful payment attempt, the value of the redis key CardFingerprint is increased by 1, and after it reaches a certain threshold, it is blocked, but only for guest users. Logged in customers can still make payments with that card.

III) Customer ID Blocking: The `customer_id` is fetched from the payment intent create call request, and then for each unsuccessful payment attempt, the value of redis key CardFingerprint<>Profile is increased by 1, and after it reaches a certain threshold, it is blocked.

### Have you spent some time checking if this feature request has been raised before?

- [x] I checked and didn't find a similar issue

### Have you read the Contributing Guidelines?

- [x] I have read the [Contributing Guidelines](https://github.com/juspay/hyperswitch/blob/main/docs/CONTRIBUTING.md)

### Are you willing to submit a PR?

Yes, I am willing to submit a PR!
diff --git a/api-reference-v2/openapi_spec.json b/api-reference-v2/openapi_spec.json
index aebc0b38c27..f81eca420a0 100644
--- a/api-reference-v2/openapi_spec.json
+++ b/api-reference-v2/openapi_spec.json
@@ -7096,6 +7096,56 @@
           }
         }
       },
+      "CardTestingGuardConfig": {
+        "type": "object",
+        "required": [
+          "card_ip_blocking_status",
+          "card_ip_blocking_threshold",
+          "guest_user_card_blocking_status",
+          "guest_user_card_blocking_threshold",
+          "customer_id_blocking_status",
+          "customer_id_blocking_threshold",
+          "card_testing_guard_expiry"
+        ],
+        "properties": {
+          "card_ip_blocking_status": {
+            "$ref": "#/components/schemas/CardTestingGuardStatus"
+          },
+          "card_ip_blocking_threshold": {
+            "type": "integer",
+            "format": "int32",
+            "description": "Determines the unsuccessful payment threshold for Card IP Blocking for profile"
+          },
+          "guest_user_card_blocking_status": {
+            "$ref": "#/components/schemas/CardTestingGuardStatus"
+          },
+          "guest_user_card_blocking_threshold": {
+            "type": "integer",
+            "format": "int32",
+            "description": "Determines the unsuccessful payment threshold for Guest User Card Blocking for profile"
+          },
+          "customer_id_blocking_status": {
+            "$ref": "#/components/schemas/CardTestingGuardStatus"
+          },
+          "customer_id_blocking_threshold": {
+            "type": "integer",
+            "format": "int32",
+            "description": "Determines the unsuccessful payment threshold for Customer Id Blocking for profile"
+          },
+          "card_testing_guard_expiry": {
+            "type": "integer",
+            "format": "int32",
+            "description": "Determines Redis Expiry for Card Testing Guard for profile"
+          }
+        }
+      },
+      "CardTestingGuardStatus": {
+        "type": "string",
+        "enum": [
+          "enabled",
+          "disabled"
+        ]
+      },
       "CardToken": {
         "type": "object",
         "required": [
@@ -18592,6 +18642,14 @@
             "type": "object",
             "description": "Product authentication ids",
             "nullable": true
+          },
+          "card_testing_guard_config": {
+            "allOf": [
+              {
+                "$ref": "#/components/schemas/CardTestingGuardConfig"
+              }
+            ],
+            "nullable": true
           }
         },
         "additionalProperties": false
@@ -18816,6 +18874,14 @@
             "type": "object",
             "description": "Product authentication ids",
             "nullable": true
+          },
+          "card_testing_guard_config": {
+            "allOf": [
+              {
+                "$ref": "#/components/schemas/CardTestingGuardConfig"
+              }
+            ],
+            "nullable": true
           }
         }
       },
diff --git a/crates/api_models/src/admin.rs b/crates/api_models/src/admin.rs
index 77488262c75..be7841fe5e1 100644
--- a/crates/api_models/src/admin.rs
+++ b/crates/api_models/src/admin.rs
@@ -238,6 +238,31 @@ impl MerchantAccountCreate {
     }
 }
 
+#[derive(Clone, Debug, Deserialize, Serialize, ToSchema)]
+pub struct CardTestingGuardConfig {
+    /// Determines if Card IP Blocking is enabled for profile
+    pub card_ip_blocking_status: CardTestingGuardStatus,
+    /// Determines the unsuccessful payment threshold for Card IP Blocking for profile
+    pub card_ip_blocking_threshold: i32,
+    /// Determines if Guest User Card Blocking is enabled for profile
+    pub guest_user_card_blocking_status: CardTestingGuardStatus,
+    /// Determines the unsuccessful payment threshold for Guest User Card Blocking for profile
+    pub guest_user_card_blocking_threshold: i32,
+    /// Determines if Customer Id Blocking is enabled for profile
+    pub customer_id_blocking_status: CardTestingGuardStatus,
+    /// Determines the unsuccessful payment threshold for Customer Id Blocking for profile
+    pub customer_id_blocking_threshold: i32,
+    /// Determines Redis Expiry for Card Testing Guard for profile
+    pub card_testing_guard_expiry: i32,
+}
+
+#[derive(Debug, Clone, serde::Deserialize, serde::Serialize, ToSchema)]
+#[serde(rename_all = "snake_case")]
+pub enum CardTestingGuardStatus {
+    Enabled,
+    Disabled,
+}
+
 #[derive(Clone, Debug, Deserialize, Serialize, ToSchema)]
 pub struct AuthenticationConnectorDetails {
     /// List of authentication connectors
@@ -1912,6 +1937,9 @@ pub struct ProfileCreate {
     #[schema(value_type = Option<Object>, example = r#"{ "click_to_pay": "mca_ushduqwhdohwd", "netcetera": "mca_kwqhudqwd" }"#)]
     pub authentication_product_ids:
         Option<common_types::payments::AuthenticationConnectorAccountMap>,
+
+    /// Card Testing Guard Configs
+    pub card_testing_guard_config: Option<CardTestingGuardConfig>,
 }
 
 #[nutype::nutype(
@@ -2030,6 +2058,9 @@ pub struct ProfileCreate {
     #[schema(value_type = Option<Object>, example = r#"{ "click_to_pay": "mca_ushduqwhdohwd", "netcetera": "mca_kwqhudqwd" }"#)]
     pub authentication_product_ids:
         Option<common_types::payments::AuthenticationConnectorAccountMap>,
+
+    /// Card Testing Guard Configs
+    pub card_testing_guard_config: Option<CardTestingGuardConfig>,
 }
 
 #[cfg(feature = "v1")]
@@ -2171,6 +2202,9 @@ pub struct ProfileResponse {
     #[schema(value_type = Option<Object>, example = r#"{ "click_to_pay": "mca_ushduqwhdohwd", "netcetera": "mca_kwqhudqwd" }"#)]
     pub authentication_product_ids:
         Option<common_types::payments::AuthenticationConnectorAccountMap>,
+
+    /// Card Testing Guard Configs
+    pub card_testing_guard_config: Option<CardTestingGuardConfig>,
 }
 
 #[cfg(feature = "v2")]
@@ -2295,6 +2329,9 @@ pub struct ProfileResponse {
     #[schema(value_type = Option<Object>, example = r#"{ "click_to_pay": "mca_ushduqwhdohwd", "netcetera": "mca_kwqhudqwd" }"#)]
     pub authentication_product_ids:
         Option<common_types::payments::AuthenticationConnectorAccountMap>,
+
+    /// Card Testing Guard Configs
+    pub card_testing_guard_config: Option<CardTestingGuardConfig>,
 }
 
 #[cfg(feature = "v1")]
@@ -2426,6 +2463,9 @@ pub struct ProfileUpdate {
     #[schema(value_type = Option<Object>, example = r#"{ "click_to_pay": "mca_ushduqwhdohwd", "netcetera": "mca_kwqhudqwd" }"#)]
     pub authentication_product_ids:
         Option<common_types::payments::AuthenticationConnectorAccountMap>,
+
+    /// Card Testing Guard Configs
+    pub card_testing_guard_config: Option<CardTestingGuardConfig>,
 }
 
 #[cfg(feature = "v2")]
@@ -2538,6 +2578,9 @@ pub struct ProfileUpdate {
     #[schema(value_type = Option<Object>, example = r#"{ "click_to_pay": "mca_ushduqwhdohwd", "netcetera": "mca_kwqhudqwd" }"#)]
     pub authentication_product_ids:
         Option<common_types::payments::AuthenticationConnectorAccountMap>,
+
+    /// Card Testing Guard Configs
+    pub card_testing_guard_config: Option<CardTestingGuardConfig>,
 }
 
 #[derive(Clone, Debug, serde::Deserialize, serde::Serialize, ToSchema)]
diff --git a/crates/common_utils/src/consts.rs b/crates/common_utils/src/consts.rs
index fdda26cc77c..3ccf39a6068 100644
--- a/crates/common_utils/src/consts.rs
+++ b/crates/common_utils/src/consts.rs
@@ -152,3 +152,24 @@ pub const X_REQUEST_ID: &str = "x-request-id";
 
 /// Default Tenant ID for the `Global` tenant
 pub const DEFAULT_GLOBAL_TENANT_ID: &str = "global";
+
+/// Default status of Card IP Blocking
+pub const DEFAULT_CARD_IP_BLOCKING_STATUS: bool = false;
+
+/// Default Threshold for Card IP Blocking
+pub const DEFAULT_CARD_IP_BLOCKING_THRESHOLD: i32 = 3;
+
+/// Default status of Guest User Card Blocking
+pub const DEFAULT_GUEST_USER_CARD_BLOCKING_STATUS: bool = false;
+
+/// Default Threshold for Card Blocking for Guest Users
+pub const DEFAULT_GUEST_USER_CARD_BLOCKING_THRESHOLD: i32 = 10;
+
+/// Default status of Customer ID Blocking
+pub const DEFAULT_CUSTOMER_ID_BLOCKING_STATUS: bool = false;
+
+/// Default Threshold for Customer ID Blocking
+pub const DEFAULT_CUSTOMER_ID_BLOCKING_THRESHOLD: i32 = 5;
+
+/// Default Card Testing Guard Redis Expiry in seconds
+pub const DEFAULT_CARD_TESTING_GUARD_EXPIRY_IN_SECS: i32 = 3600;
diff --git a/crates/diesel_models/src/business_profile.rs b/crates/diesel_models/src/business_profile.rs
index 92da1978458..fdded6a3a34 100644
--- a/crates/diesel_models/src/business_profile.rs
+++ b/crates/diesel_models/src/business_profile.rs
@@ -61,6 +61,8 @@ pub struct Profile {
     pub is_click_to_pay_enabled: bool,
     pub authentication_product_ids:
         Option<common_types::payments::AuthenticationConnectorAccountMap>,
+    pub card_testing_guard_config: Option<CardTestingGuardConfig>,
+    pub card_testing_secret_key: Option<Encryption>,
 }
 
 #[cfg(feature = "v1")]
@@ -107,6 +109,8 @@ pub struct ProfileNew {
     pub is_click_to_pay_enabled: bool,
     pub authentication_product_ids:
         Option<common_types::payments::AuthenticationConnectorAccountMap>,
+    pub card_testing_guard_config: Option<CardTestingGuardConfig>,
+    pub card_testing_secret_key: Option<Encryption>,
 }
 
 #[cfg(feature = "v1")]
@@ -151,6 +155,8 @@ pub struct ProfileUpdateInternal {
     pub is_click_to_pay_enabled: Option<bool>,
     pub authentication_product_ids:
         Option<common_types::payments::AuthenticationConnectorAccountMap>,
+    pub card_testing_guard_config: Option<CardTestingGuardConfig>,
+    pub card_testing_secret_key: Option<Encryption>,
 }
 
 #[cfg(feature = "v1")]
@@ -193,6 +199,8 @@ impl ProfileUpdateInternal {
             always_request_extended_authorization,
             is_click_to_pay_enabled,
             authentication_product_ids,
+            card_testing_guard_config,
+            card_testing_secret_key,
         } = self;
         Profile {
             profile_id: source.profile_id,
@@ -258,6 +266,9 @@ impl ProfileUpdateInternal {
                 .unwrap_or(source.is_click_to_pay_enabled),
             authentication_product_ids: authentication_product_ids
                 .or(source.authentication_product_ids),
+            card_testing_guard_config: card_testing_guard_config
+                .or(source.card_testing_guard_config),
+            card_testing_secret_key,
         }
     }
 }
@@ -317,6 +328,8 @@ pub struct Profile {
     pub authentication_product_ids:
         Option<common_types::payments::AuthenticationConnectorAccountMap>,
     pub three_ds_decision_manager_config: Option<common_types::payments::DecisionManagerRecord>,
+    pub card_testing_guard_config: Option<CardTestingGuardConfig>,
+    pub card_testing_secret_key: Option<Encryption>,
 }
 
 impl Profile {
@@ -379,6 +392,8 @@ pub struct ProfileNew {
     pub authentication_product_ids:
         Option<common_types::payments::AuthenticationConnectorAccountMap>,
     pub three_ds_decision_manager_config: Option<common_types::payments::DecisionManagerRecord>,
+    pub card_testing_guard_config: Option<CardTestingGuardConfig>,
+    pub card_testing_secret_key: Option<Encryption>,
 }
 
 #[cfg(feature = "v2")]
@@ -425,6 +440,8 @@ pub struct ProfileUpdateInternal {
     pub authentication_product_ids:
         Option<common_types::payments::AuthenticationConnectorAccountMap>,
     pub three_ds_decision_manager_config: Option<common_types::payments::DecisionManagerRecord>,
+    pub card_testing_guard_config: Option<CardTestingGuardConfig>,
+    pub card_testing_secret_key: Option<Encryption>,
 }
 
 #[cfg(feature = "v2")]
@@ -469,6 +486,8 @@ impl ProfileUpdateInternal {
             is_click_to_pay_enabled,
             authentication_product_ids,
             three_ds_decision_manager_config,
+            card_testing_guard_config,
+            card_testing_secret_key,
         } = self;
         Profile {
             id: source.id,
@@ -540,6 +559,9 @@ impl ProfileUpdateInternal {
                 .or(source.authentication_product_ids),
             three_ds_decision_manager_config: three_ds_decision_manager_config
                 .or(source.three_ds_decision_manager_config),
+            card_testing_guard_config: card_testing_guard_config
+                .or(source.card_testing_guard_config),
+            card_testing_secret_key: card_testing_secret_key.or(source.card_testing_secret_key),
         }
     }
 }
@@ -553,6 +575,20 @@ pub struct AuthenticationConnectorDetails {
 
 common_utils::impl_to_sql_from_sql_json!(AuthenticationConnectorDetails);
 
+#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, diesel::AsExpression)]
+#[diesel(sql_type = diesel::sql_types::Jsonb)]
+pub struct CardTestingGuardConfig {
+    pub is_card_ip_blocking_enabled: bool,
+    pub card_ip_blocking_threshold: i32,
+    pub is_guest_user_card_blocking_enabled: bool,
+    pub guest_user_card_blocking_threshold: i32,
+    pub is_customer_id_blocking_enabled: bool,
+    pub customer_id_blocking_threshold: i32,
+    pub card_testing_guard_expiry: i32,
+}
+
+common_utils::impl_to_sql_from_sql_json!(CardTestingGuardConfig);
+
 #[derive(Clone, Debug, serde::Deserialize, serde::Serialize, diesel::AsExpression)]
 #[diesel(sql_type = diesel::sql_types::Json)]
 pub struct WebhookDetails {
diff --git a/crates/diesel_models/src/schema.rs b/crates/diesel_models/src/schema.rs
index cfc0f28e4d0..57c43a1955b 100644
--- a/crates/diesel_models/src/schema.rs
+++ b/crates/diesel_models/src/schema.rs
@@ -219,6 +219,8 @@ diesel::table! {
         always_request_extended_authorization -> Nullable<Bool>,
         is_click_to_pay_enabled -> Bool,
         authentication_product_ids -> Nullable<Jsonb>,
+        card_testing_guard_config -> Nullable<Jsonb>,
+        card_testing_secret_key -> Nullable<Bytea>,
     }
 }
 
diff --git a/crates/diesel_models/src/schema_v2.rs b/crates/diesel_models/src/schema_v2.rs
index 69ba37e8df6..2351bdb83c9 100644
--- a/crates/diesel_models/src/schema_v2.rs
+++ b/crates/diesel_models/src/schema_v2.rs
@@ -228,6 +228,8 @@ diesel::table! {
         is_click_to_pay_enabled -> Bool,
         authentication_product_ids -> Nullable<Jsonb>,
         three_ds_decision_manager_config -> Nullable<Jsonb>,
+        card_testing_guard_config -> Nullable<Jsonb>,
+        card_testing_secret_key -> Nullable<Bytea>,
     }
 }
 
diff --git a/crates/hyperswitch_domain_models/src/business_profile.rs b/crates/hyperswitch_domain_models/src/business_profile.rs
index 4a6a84124a7..07fd0a9fd90 100644
--- a/crates/hyperswitch_domain_models/src/business_profile.rs
+++ b/crates/hyperswitch_domain_models/src/business_profile.rs
@@ -1,5 +1,5 @@
 use common_utils::{
-    crypto::OptionalEncryptableValue,
+    crypto::{OptionalEncryptableName, OptionalEncryptableValue},
     date_time,
     encryption::Encryption,
     errors::{CustomResult, ValidationError},
@@ -8,7 +8,7 @@ use common_utils::{
 };
 use diesel_models::business_profile::{
     AuthenticationConnectorDetails, BusinessPaymentLinkConfig, BusinessPayoutLinkConfig,
-    ProfileUpdateInternal, WebhookDetails,
+    CardTestingGuardConfig, ProfileUpdateInternal, WebhookDetails,
 };
 use error_stack::ResultExt;
 use masking::{PeekInterface, Secret};
@@ -62,6 +62,8 @@ pub struct Profile {
     pub is_click_to_pay_enabled: bool,
     pub authentication_product_ids:
         Option<common_types::payments::AuthenticationConnectorAccountMap>,
+    pub card_testing_guard_config: Option<CardTestingGuardConfig>,
+    pub card_testing_secret_key: OptionalEncryptableName,
 }
 
 #[cfg(feature = "v1")]
@@ -106,6 +108,8 @@ pub struct ProfileSetter {
     pub is_click_to_pay_enabled: bool,
     pub authentication_product_ids:
         Option<common_types::payments::AuthenticationConnectorAccountMap>,
+    pub card_testing_guard_config: Option<CardTestingGuardConfig>,
+    pub card_testing_secret_key: OptionalEncryptableName,
 }
 
 #[cfg(feature = "v1")]
@@ -156,6 +160,8 @@ impl From<ProfileSetter> for Profile {
             always_request_extended_authorization: value.always_request_extended_authorization,
             is_click_to_pay_enabled: value.is_click_to_pay_enabled,
             authentication_product_ids: value.authentication_product_ids,
+            card_testing_guard_config: value.card_testing_guard_config,
+            card_testing_secret_key: value.card_testing_secret_key,
         }
     }
 }
@@ -208,6 +214,8 @@ pub struct ProfileGeneralUpdate {
     pub is_click_to_pay_enabled: Option<bool>,
     pub authentication_product_ids:
         Option<common_types::payments::AuthenticationConnectorAccountMap>,
+    pub card_testing_guard_config: Option<CardTestingGuardConfig>,
+    pub card_testing_secret_key: OptionalEncryptableName,
 }
 
 #[cfg(feature = "v1")]
@@ -230,6 +238,9 @@ pub enum ProfileUpdate {
     NetworkTokenizationUpdate {
         is_network_tokenization_enabled: bool,
     },
+    CardTestingSecretKeyUpdate {
+        card_testing_secret_key: OptionalEncryptableName,
+    },
 }
 
 #[cfg(feature = "v1")]
@@ -272,6 +283,8 @@ impl From<ProfileUpdate> for ProfileUpdateInternal {
                     max_auto_retries_enabled,
                     is_click_to_pay_enabled,
                     authentication_product_ids,
+                    card_testing_guard_config,
+                    card_testing_secret_key,
                 } = *update;
 
                 Self {
@@ -312,6 +325,8 @@ impl From<ProfileUpdate> for ProfileUpdateInternal {
                     always_request_extended_authorization: None,
                     is_click_to_pay_enabled,
                     authentication_product_ids,
+                    card_testing_guard_config,
+                    card_testing_secret_key: card_testing_secret_key.map(Encryption::from),
                 }
             }
             ProfileUpdate::RoutingAlgorithmUpdate {
@@ -354,6 +369,8 @@ impl From<ProfileUpdate> for ProfileUpdateInternal {
                 always_request_extended_authorization: None,
                 is_click_to_pay_enabled: None,
                 authentication_product_ids: None,
+                card_testing_guard_config: None,
+                card_testing_secret_key: None,
             },
             ProfileUpdate::DynamicRoutingAlgorithmUpdate {
                 dynamic_routing_algorithm,
@@ -394,6 +411,8 @@ impl From<ProfileUpdate> for ProfileUpdateInternal {
                 always_request_extended_authorization: None,
                 is_click_to_pay_enabled: None,
                 authentication_product_ids: None,
+                card_testing_guard_config: None,
+                card_testing_secret_key: None,
             },
             ProfileUpdate::ExtendedCardInfoUpdate {
                 is_extended_card_info_enabled,
@@ -434,6 +453,8 @@ impl From<ProfileUpdate> for ProfileUpdateInternal {
                 always_request_extended_authorization: None,
                 is_click_to_pay_enabled: None,
                 authentication_product_ids: None,
+                card_testing_guard_config: None,
+                card_testing_secret_key: None,
             },
             ProfileUpdate::ConnectorAgnosticMitUpdate {
                 is_connector_agnostic_mit_enabled,
@@ -474,6 +495,8 @@ impl From<ProfileUpdate> for ProfileUpdateInternal {
                 always_request_extended_authorization: None,
                 is_click_to_pay_enabled: None,
                 authentication_product_ids: None,
+                card_testing_guard_config: None,
+                card_testing_secret_key: None,
             },
             ProfileUpdate::NetworkTokenizationUpdate {
                 is_network_tokenization_enabled,
@@ -514,6 +537,50 @@ impl From<ProfileUpdate> for ProfileUpdateInternal {
                 always_request_extended_authorization: None,
                 is_click_to_pay_enabled: None,
                 authentication_product_ids: None,
+                card_testing_guard_config: None,
+                card_testing_secret_key: None,
+            },
+            ProfileUpdate::CardTestingSecretKeyUpdate {
+                card_testing_secret_key,
+            } => Self {
+                profile_name: None,
+                modified_at: now,
+                return_url: None,
+                enable_payment_response_hash: None,
+                payment_response_hash_key: None,
+                redirect_to_merchant_with_http_post: None,
+                webhook_details: None,
+                metadata: None,
+                routing_algorithm: None,
+                intent_fulfillment_time: None,
+                frm_routing_algorithm: None,
+                payout_routing_algorithm: None,
+                is_recon_enabled: None,
+                applepay_verified_domains: None,
+                payment_link_config: None,
+                session_expiry: None,
+                authentication_connector_details: None,
+                payout_link_config: None,
+                is_extended_card_info_enabled: None,
+                extended_card_info_config: None,
+                is_connector_agnostic_mit_enabled: None,
+                use_billing_as_payment_method_billing: None,
+                collect_shipping_details_from_wallet_connector: None,
+                collect_billing_details_from_wallet_connector: None,
+                outgoing_webhook_custom_http_headers: None,
+                always_collect_billing_details_from_wallet_connector: None,
+                always_collect_shipping_details_from_wallet_connector: None,
+                tax_connector_id: None,
+                is_tax_connector_enabled: None,
+                dynamic_routing_algorithm: None,
+                is_network_tokenization_enabled: None,
+                is_auto_retries_enabled: None,
+                max_auto_retries_enabled: None,
+                always_request_extended_authorization: None,
+                is_click_to_pay_enabled: None,
+                authentication_product_ids: None,
+                card_testing_guard_config: None,
+                card_testing_secret_key: card_testing_secret_key.map(Encryption::from),
             },
         }
     }
@@ -573,6 +640,8 @@ impl super::behaviour::Conversion for Profile {
             always_request_extended_authorization: self.always_request_extended_authorization,
             is_click_to_pay_enabled: self.is_click_to_pay_enabled,
             authentication_product_ids: self.authentication_product_ids,
+            card_testing_guard_config: self.card_testing_guard_config,
+            card_testing_secret_key: self.card_testing_secret_key.map(|name| name.into()),
         })
     }
 
@@ -644,6 +713,21 @@ impl super::behaviour::Conversion for Profile {
                 always_request_extended_authorization: item.always_request_extended_authorization,
                 is_click_to_pay_enabled: item.is_click_to_pay_enabled,
                 authentication_product_ids: item.authentication_product_ids,
+                card_testing_guard_config: item.card_testing_guard_config,
+                card_testing_secret_key: item
+                    .card_testing_secret_key
+                    .async_lift(|inner| async {
+                        crypto_operation(
+                            state,
+                            type_name!(Self::DstType),
+                            CryptoOperation::DecryptOptional(inner),
+                            key_manager_identifier.clone(),
+                            key.peek(),
+                        )
+                        .await
+                        .and_then(|val| val.try_into_optionaloperation())
+                    })
+                    .await?,
             })
         }
         .await
@@ -698,6 +782,8 @@ impl super::behaviour::Conversion for Profile {
             max_auto_retries_enabled: self.max_auto_retries_enabled,
             is_click_to_pay_enabled: self.is_click_to_pay_enabled,
             authentication_product_ids: self.authentication_product_ids,
+            card_testing_guard_config: self.card_testing_guard_config,
+            card_testing_secret_key: self.card_testing_secret_key.map(Encryption::from),
         })
     }
 }
@@ -746,6 +832,8 @@ pub struct Profile {
     pub authentication_product_ids:
         Option<common_types::payments::AuthenticationConnectorAccountMap>,
     pub three_ds_decision_manager_config: Option<common_types::payments::DecisionManagerRecord>,
+    pub card_testing_guard_config: Option<CardTestingGuardConfig>,
+    pub card_testing_secret_key: OptionalEncryptableName,
 }
 
 #[cfg(feature = "v2")]
@@ -790,6 +878,8 @@ pub struct ProfileSetter {
     pub authentication_product_ids:
         Option<common_types::payments::AuthenticationConnectorAccountMap>,
     pub three_ds_decision_manager_config: Option<common_types::payments::DecisionManagerRecord>,
+    pub card_testing_guard_config: Option<CardTestingGuardConfig>,
+    pub card_testing_secret_key: OptionalEncryptableName,
 }
 
 #[cfg(feature = "v2")]
@@ -840,6 +930,8 @@ impl From<ProfileSetter> for Profile {
             is_click_to_pay_enabled: value.is_click_to_pay_enabled,
             authentication_product_ids: value.authentication_product_ids,
             three_ds_decision_manager_config: value.three_ds_decision_manager_config,
+            card_testing_guard_config: value.card_testing_guard_config,
+            card_testing_secret_key: value.card_testing_secret_key,
         }
     }
 }
@@ -894,6 +986,8 @@ pub struct ProfileGeneralUpdate {
     pub authentication_product_ids:
         Option<common_types::payments::AuthenticationConnectorAccountMap>,
     pub three_ds_decision_manager_config: Option<common_types::payments::DecisionManagerRecord>,
+    pub card_testing_guard_config: Option<CardTestingGuardConfig>,
+    pub card_testing_secret_key: OptionalEncryptableName,
 }
 
 #[cfg(feature = "v2")]
@@ -922,6 +1016,9 @@ pub enum ProfileUpdate {
     DecisionManagerRecordUpdate {
         three_ds_decision_manager_config: common_types::payments::DecisionManagerRecord,
     },
+    CardTestingSecretKeyUpdate {
+        card_testing_secret_key: OptionalEncryptableName,
+    },
 }
 
 #[cfg(feature = "v2")]
@@ -958,6 +1055,8 @@ impl From<ProfileUpdate> for ProfileUpdateInternal {
                     is_click_to_pay_enabled,
                     authentication_product_ids,
                     three_ds_decision_manager_config,
+                    card_testing_guard_config,
+                    card_testing_secret_key,
                 } = *update;
                 Self {
                     profile_name,
@@ -999,6 +1098,8 @@ impl From<ProfileUpdate> for ProfileUpdateInternal {
                     is_click_to_pay_enabled,
                     authentication_product_ids,
                     three_ds_decision_manager_config,
+                    card_testing_guard_config,
+                    card_testing_secret_key: card_testing_secret_key.map(Encryption::from),
                 }
             }
             ProfileUpdate::RoutingAlgorithmUpdate {
@@ -1043,6 +1144,8 @@ impl From<ProfileUpdate> for ProfileUpdateInternal {
                 is_click_to_pay_enabled: None,
                 authentication_product_ids: None,
                 three_ds_decision_manager_config: None,
+                card_testing_guard_config: None,
+                card_testing_secret_key: None,
             },
             ProfileUpdate::ExtendedCardInfoUpdate {
                 is_extended_card_info_enabled,
@@ -1085,6 +1188,8 @@ impl From<ProfileUpdate> for ProfileUpdateInternal {
                 is_click_to_pay_enabled: None,
                 authentication_product_ids: None,
                 three_ds_decision_manager_config: None,
+                card_testing_guard_config: None,
+                card_testing_secret_key: None,
             },
             ProfileUpdate::ConnectorAgnosticMitUpdate {
                 is_connector_agnostic_mit_enabled,
@@ -1127,6 +1232,8 @@ impl From<ProfileUpdate> for ProfileUpdateInternal {
                 is_click_to_pay_enabled: None,
                 authentication_product_ids: None,
                 three_ds_decision_manager_config: None,
+                card_testing_guard_config: None,
+                card_testing_secret_key: None,
             },
             ProfileUpdate::DefaultRoutingFallbackUpdate {
                 default_fallback_routing,
@@ -1169,6 +1276,8 @@ impl From<ProfileUpdate> for ProfileUpdateInternal {
                 is_click_to_pay_enabled: None,
                 authentication_product_ids: None,
                 three_ds_decision_manager_config: None,
+                card_testing_guard_config: None,
+                card_testing_secret_key: None,
             },
             ProfileUpdate::NetworkTokenizationUpdate {
                 is_network_tokenization_enabled,
@@ -1211,6 +1320,8 @@ impl From<ProfileUpdate> for ProfileUpdateInternal {
                 is_click_to_pay_enabled: None,
                 authentication_product_ids: None,
                 three_ds_decision_manager_config: None,
+                card_testing_guard_config: None,
+                card_testing_secret_key: None,
             },
             ProfileUpdate::CollectCvvDuringPaymentUpdate {
                 should_collect_cvv_during_payment,
@@ -1253,6 +1364,8 @@ impl From<ProfileUpdate> for ProfileUpdateInternal {
                 is_click_to_pay_enabled: None,
                 authentication_product_ids: None,
                 three_ds_decision_manager_config: None,
+                card_testing_guard_config: None,
+                card_testing_secret_key: None,
             },
             ProfileUpdate::DecisionManagerRecordUpdate {
                 three_ds_decision_manager_config,
@@ -1295,6 +1408,52 @@ impl From<ProfileUpdate> for ProfileUpdateInternal {
                 is_click_to_pay_enabled: None,
                 authentication_product_ids: None,
                 three_ds_decision_manager_config: Some(three_ds_decision_manager_config),
+                card_testing_guard_config: None,
+                card_testing_secret_key: None,
+            },
+            ProfileUpdate::CardTestingSecretKeyUpdate {
+                card_testing_secret_key,
+            } => Self {
+                profile_name: None,
+                modified_at: now,
+                return_url: None,
+                enable_payment_response_hash: None,
+                payment_response_hash_key: None,
+                redirect_to_merchant_with_http_post: None,
+                webhook_details: None,
+                metadata: None,
+                is_recon_enabled: None,
+                applepay_verified_domains: None,
+                payment_link_config: None,
+                session_expiry: None,
+                authentication_connector_details: None,
+                payout_link_config: None,
+                is_extended_card_info_enabled: None,
+                extended_card_info_config: None,
+                is_connector_agnostic_mit_enabled: None,
+                use_billing_as_payment_method_billing: None,
+                collect_shipping_details_from_wallet_connector: None,
+                collect_billing_details_from_wallet_connector: None,
+                outgoing_webhook_custom_http_headers: None,
+                always_collect_billing_details_from_wallet_connector: None,
+                always_collect_shipping_details_from_wallet_connector: None,
+                routing_algorithm_id: None,
+                payout_routing_algorithm_id: None,
+                order_fulfillment_time: None,
+                order_fulfillment_time_origin: None,
+                frm_routing_algorithm_id: None,
+                default_fallback_routing: None,
+                should_collect_cvv_during_payment: None,
+                tax_connector_id: None,
+                is_tax_connector_enabled: None,
+                is_network_tokenization_enabled: None,
+                is_auto_retries_enabled: None,
+                max_auto_retries_enabled: None,
+                is_click_to_pay_enabled: None,
+                authentication_product_ids: None,
+                three_ds_decision_manager_config: None,
+                card_testing_guard_config: None,
+                card_testing_secret_key: card_testing_secret_key.map(Encryption::from),
             },
         }
     }
@@ -1358,6 +1517,8 @@ impl super::behaviour::Conversion for Profile {
             is_click_to_pay_enabled: self.is_click_to_pay_enabled,
             authentication_product_ids: self.authentication_product_ids,
             three_ds_decision_manager_config: self.three_ds_decision_manager_config,
+            card_testing_guard_config: self.card_testing_guard_config,
+            card_testing_secret_key: self.card_testing_secret_key.map(|name| name.into()),
         })
     }
 
@@ -1429,6 +1590,21 @@ impl super::behaviour::Conversion for Profile {
                 is_click_to_pay_enabled: item.is_click_to_pay_enabled,
                 authentication_product_ids: item.authentication_product_ids,
                 three_ds_decision_manager_config: item.three_ds_decision_manager_config,
+                card_testing_guard_config: item.card_testing_guard_config,
+                card_testing_secret_key: item
+                    .card_testing_secret_key
+                    .async_lift(|inner| async {
+                        crypto_operation(
+                            state,
+                            type_name!(Self::DstType),
+                            CryptoOperation::DecryptOptional(inner),
+                            key_manager_identifier.clone(),
+                            key.peek(),
+                        )
+                        .await
+                        .and_then(|val| val.try_into_optionaloperation())
+                    })
+                    .await?,
             })
         }
         .await
@@ -1487,6 +1663,8 @@ impl super::behaviour::Conversion for Profile {
             is_click_to_pay_enabled: self.is_click_to_pay_enabled,
             authentication_product_ids: self.authentication_product_ids,
             three_ds_decision_manager_config: self.three_ds_decision_manager_config,
+            card_testing_guard_config: self.card_testing_guard_config,
+            card_testing_secret_key: self.card_testing_secret_key.map(Encryption::from),
         })
     }
 }
diff --git a/crates/hyperswitch_domain_models/src/card_testing_guard_data.rs b/crates/hyperswitch_domain_models/src/card_testing_guard_data.rs
new file mode 100644
index 00000000000..329f89b946b
--- /dev/null
+++ b/crates/hyperswitch_domain_models/src/card_testing_guard_data.rs
@@ -0,0 +1,12 @@
+use serde::{self, Deserialize, Serialize};
+
+#[derive(Clone, Serialize, Deserialize, Debug)]
+pub struct CardTestingGuardData {
+    pub is_card_ip_blocking_enabled: bool,
+    pub card_ip_blocking_cache_key: String,
+    pub is_guest_user_card_blocking_enabled: bool,
+    pub guest_user_card_blocking_cache_key: String,
+    pub is_customer_id_blocking_enabled: bool,
+    pub customer_id_blocking_cache_key: String,
+    pub card_testing_guard_expiry: i32,
+}
diff --git a/crates/hyperswitch_domain_models/src/lib.rs b/crates/hyperswitch_domain_models/src/lib.rs
index ef2cbe064d6..011f9619cdd 100644
--- a/crates/hyperswitch_domain_models/src/lib.rs
+++ b/crates/hyperswitch_domain_models/src/lib.rs
@@ -3,6 +3,7 @@ pub mod api;
 pub mod behaviour;
 pub mod business_profile;
 pub mod callback_mapper;
+pub mod card_testing_guard_data;
 pub mod consts;
 pub mod customer;
 pub mod disputes;
diff --git a/crates/openapi/src/openapi.rs b/crates/openapi/src/openapi.rs
index 1b6f73fb1cd..8d18d1fe59f 100644
--- a/crates/openapi/src/openapi.rs
+++ b/crates/openapi/src/openapi.rs
@@ -250,6 +250,8 @@ Never share your secret api keys. Keep them guarded and secure.
         api_models::admin::BusinessGenericLinkConfig,
         api_models::admin::BusinessCollectLinkConfig,
         api_models::admin::BusinessPayoutLinkConfig,
+        api_models::admin::CardTestingGuardConfig,
+        api_models::admin::CardTestingGuardStatus,
         api_models::customers::CustomerRequest,
         api_models::customers::CustomerUpdateRequest,
         api_models::customers::CustomerDeleteResponse,
diff --git a/crates/openapi/src/openapi_v2.rs b/crates/openapi/src/openapi_v2.rs
index eeb732f81de..ac432fab965 100644
--- a/crates/openapi/src/openapi_v2.rs
+++ b/crates/openapi/src/openapi_v2.rs
@@ -286,6 +286,8 @@ Never share your secret api keys. Keep them guarded and secure.
         api_models::enums::UIWidgetFormLayout,
         api_models::admin::MerchantConnectorCreate,
         api_models::admin::AdditionalMerchantData,
+        api_models::admin::CardTestingGuardConfig,
+        api_models::admin::CardTestingGuardStatus,
         api_models::admin::ConnectorWalletDetails,
         api_models::admin::MerchantRecipientData,
         api_models::admin::MerchantAccountData,
diff --git a/crates/router/src/consts.rs b/crates/router/src/consts.rs
index dc3c2d532e8..57ec34227b0 100644
--- a/crates/router/src/consts.rs
+++ b/crates/router/src/consts.rs
@@ -89,6 +89,12 @@ pub const EMAIL_SUBJECT_APPROVAL_RECON_REQUEST: &str =
 
 pub const ROLE_INFO_CACHE_PREFIX: &str = "CR_INFO_";
 
+pub const CARD_IP_BLOCKING_CACHE_KEY_PREFIX: &str = "CARD_IP_BLOCKING";
+
+pub const GUEST_USER_CARD_BLOCKING_CACHE_KEY_PREFIX: &str = "GUEST_USER_CARD_BLOCKING";
+
+pub const CUSTOMER_ID_BLOCKING_PREFIX: &str = "CUSTOMER_ID_BLOCKING";
+
 #[cfg(feature = "olap")]
 pub const VERIFY_CONNECTOR_ID_PREFIX: &str = "conn_verify";
 #[cfg(feature = "olap")]
diff --git a/crates/router/src/core.rs b/crates/router/src/core.rs
index 18b3ad14358..365cdaf3a12 100644
--- a/crates/router/src/core.rs
+++ b/crates/router/src/core.rs
@@ -7,6 +7,7 @@ pub mod authentication;
 #[cfg(feature = "v1")]
 pub mod blocklist;
 pub mod cache;
+pub mod card_testing_guard;
 pub mod cards_info;
 pub mod conditional_config;
 pub mod configs;
diff --git a/crates/router/src/core/admin.rs b/crates/router/src/core/admin.rs
index 98b55cd9823..bc93b9c53eb 100644
--- a/crates/router/src/core/admin.rs
+++ b/crates/router/src/core/admin.rs
@@ -12,7 +12,7 @@ use common_utils::{
 };
 use diesel_models::configs;
 #[cfg(all(any(feature = "v1", feature = "v2"), feature = "olap"))]
-use diesel_models::organization::OrganizationBridge;
+use diesel_models::{business_profile::CardTestingGuardConfig, organization::OrganizationBridge};
 use error_stack::{report, FutureExt, ResultExt};
 use hyperswitch_domain_models::merchant_connector_account::{
     FromRequestEncryptableMerchantConnectorAccount, UpdateEncryptableMerchantConnectorAccount,
@@ -3645,6 +3645,35 @@ impl ProfileCreateBridge for api::ProfileCreate {
             })
             .transpose()?;
 
+        let key = key_store.key.clone().into_inner();
+        let key_manager_state = state.into();
+
+        let card_testing_secret_key = Some(Secret::new(utils::generate_id(
+            consts::FINGERPRINT_SECRET_LENGTH,
+            "fs",
+        )));
+
+        let card_testing_guard_config = match self.card_testing_guard_config {
+            Some(card_testing_guard_config) => Some(CardTestingGuardConfig::foreign_from(
+                card_testing_guard_config,
+            )),
+            None => Some(CardTestingGuardConfig {
+                is_card_ip_blocking_enabled: common_utils::consts::DEFAULT_CARD_IP_BLOCKING_STATUS,
+                card_ip_blocking_threshold:
+                    common_utils::consts::DEFAULT_CARD_IP_BLOCKING_THRESHOLD,
+                is_guest_user_card_blocking_enabled:
+                    common_utils::consts::DEFAULT_GUEST_USER_CARD_BLOCKING_STATUS,
+                guest_user_card_blocking_threshold:
+                    common_utils::consts::DEFAULT_GUEST_USER_CARD_BLOCKING_THRESHOLD,
+                is_customer_id_blocking_enabled:
+                    common_utils::consts::DEFAULT_CUSTOMER_ID_BLOCKING_STATUS,
+                customer_id_blocking_threshold:
+                    common_utils::consts::DEFAULT_CUSTOMER_ID_BLOCKING_THRESHOLD,
+                card_testing_guard_expiry:
+                    common_utils::consts::DEFAULT_CARD_TESTING_GUARD_EXPIRY_IN_SECS,
+            }),
+        };
+
         Ok(domain::Profile::from(domain::ProfileSetter {
             profile_id,
             merchant_id: merchant_account.get_id().clone(),
@@ -3717,6 +3746,22 @@ impl ProfileCreateBridge for api::ProfileCreate {
             always_request_extended_authorization: self.always_request_extended_authorization,
             is_click_to_pay_enabled: self.is_click_to_pay_enabled,
             authentication_product_ids: self.authentication_product_ids,
+            card_testing_guard_config,
+            card_testing_secret_key: card_testing_secret_key
+                .async_lift(|inner| async {
+                    domain_types::crypto_operation(
+                        &key_manager_state,
+                        common_utils::type_name!(domain::Profile),
+                        domain_types::CryptoOperation::EncryptOptional(inner),
+                        km_types::Identifier::Merchant(key_store.merchant_id.clone()),
+                        key.peek(),
+                    )
+                    .await
+                    .and_then(|val| val.try_into_optionaloperation())
+                })
+                .await
+                .change_context(errors::ApiErrorResponse::InternalServerError)
+                .attach_printable("error while generating card testing secret key")?,
         }))
     }
 
@@ -3768,6 +3813,35 @@ impl ProfileCreateBridge for api::ProfileCreate {
             })
             .transpose()?;
 
+        let key = key_store.key.clone().into_inner();
+        let key_manager_state = state.into();
+
+        let card_testing_secret_key = Some(Secret::new(utils::generate_id(
+            consts::FINGERPRINT_SECRET_LENGTH,
+            "fs",
+        )));
+
+        let card_testing_guard_config = match self.card_testing_guard_config {
+            Some(card_testing_guard_config) => Some(CardTestingGuardConfig::foreign_from(
+                card_testing_guard_config,
+            )),
+            None => Some(CardTestingGuardConfig {
+                is_card_ip_blocking_enabled: common_utils::consts::DEFAULT_CARD_IP_BLOCKING_STATUS,
+                card_ip_blocking_threshold:
+                    common_utils::consts::DEFAULT_CARD_IP_BLOCKING_THRESHOLD,
+                is_guest_user_card_blocking_enabled:
+                    common_utils::consts::DEFAULT_GUEST_USER_CARD_BLOCKING_STATUS,
+                guest_user_card_blocking_threshold:
+                    common_utils::consts::DEFAULT_GUEST_USER_CARD_BLOCKING_THRESHOLD,
+                is_customer_id_blocking_enabled:
+                    common_utils::consts::DEFAULT_CUSTOMER_ID_BLOCKING_STATUS,
+                customer_id_blocking_threshold:
+                    common_utils::consts::DEFAULT_CUSTOMER_ID_BLOCKING_THRESHOLD,
+                card_testing_guard_expiry:
+                    common_utils::consts::DEFAULT_CARD_TESTING_GUARD_EXPIRY_IN_SECS,
+            }),
+        };
+
         Ok(domain::Profile::from(domain::ProfileSetter {
             id: profile_id,
             merchant_id: merchant_id.clone(),
@@ -3827,6 +3901,22 @@ impl ProfileCreateBridge for api::ProfileCreate {
             is_click_to_pay_enabled: self.is_click_to_pay_enabled,
             authentication_product_ids: self.authentication_product_ids,
             three_ds_decision_manager_config: None,
+            card_testing_guard_config,
+            card_testing_secret_key: card_testing_secret_key
+                .async_lift(|inner| async {
+                    domain_types::crypto_operation(
+                        &key_manager_state,
+                        common_utils::type_name!(domain::Profile),
+                        domain_types::CryptoOperation::EncryptOptional(inner),
+                        km_types::Identifier::Merchant(key_store.merchant_id.clone()),
+                        key.peek(),
+                    )
+                    .await
+                    .and_then(|val| val.try_into_optionaloperation())
+                })
+                .await
+                .change_context(errors::ApiErrorResponse::InternalServerError)
+                .attach_printable("error while generating card testing secret key")?,
         }))
     }
 }
@@ -3960,6 +4050,7 @@ trait ProfileUpdateBridge {
         self,
         state: &SessionState,
         key_store: &domain::MerchantKeyStore,
+        business_profile: &domain::Profile,
     ) -> RouterResult<domain::ProfileUpdate>;
 }
 
@@ -3970,6 +4061,7 @@ impl ProfileUpdateBridge for api::ProfileUpdate {
         self,
         state: &SessionState,
         key_store: &domain::MerchantKeyStore,
+        business_profile: &domain::Profile,
     ) -> RouterResult<domain::ProfileUpdate> {
         if let Some(session_expiry) = &self.session_expiry {
             helpers::validate_session_expiry(session_expiry.to_owned())?;
@@ -4034,6 +4126,35 @@ impl ProfileUpdateBridge for api::ProfileUpdate {
             })
             .transpose()?;
 
+        let key = key_store.key.clone().into_inner();
+        let key_manager_state = state.into();
+
+        let card_testing_secret_key = match business_profile.card_testing_secret_key {
+            Some(_) => None,
+            None => {
+                let card_testing_secret_key = Some(Secret::new(utils::generate_id(
+                    consts::FINGERPRINT_SECRET_LENGTH,
+                    "fs",
+                )));
+
+                card_testing_secret_key
+                    .async_lift(|inner| async {
+                        domain_types::crypto_operation(
+                            &key_manager_state,
+                            common_utils::type_name!(domain::Profile),
+                            domain_types::CryptoOperation::EncryptOptional(inner),
+                            km_types::Identifier::Merchant(key_store.merchant_id.clone()),
+                            key.peek(),
+                        )
+                        .await
+                        .and_then(|val| val.try_into_optionaloperation())
+                    })
+                    .await
+                    .change_context(errors::ApiErrorResponse::InternalServerError)
+                    .attach_printable("error while generating card testing secret key")?
+            }
+        };
+
         Ok(domain::ProfileUpdate::Update(Box::new(
             domain::ProfileGeneralUpdate {
                 profile_name: self.profile_name,
@@ -4078,6 +4199,10 @@ impl ProfileUpdateBridge for api::ProfileUpdate {
                 max_auto_retries_enabled: self.max_auto_retries_enabled.map(i16::from),
                 is_click_to_pay_enabled: self.is_click_to_pay_enabled,
                 authentication_product_ids: self.authentication_product_ids,
+                card_testing_guard_config: self
+                    .card_testing_guard_config
+                    .map(ForeignInto::foreign_into),
+                card_testing_secret_key,
             },
         )))
     }
@@ -4090,6 +4215,7 @@ impl ProfileUpdateBridge for api::ProfileUpdate {
         self,
         state: &SessionState,
         key_store: &domain::MerchantKeyStore,
+        business_profile: &domain::Profile,
     ) -> RouterResult<domain::ProfileUpdate> {
         if let Some(session_expiry) = &self.session_expiry {
             helpers::validate_session_expiry(session_expiry.to_owned())?;
@@ -4140,6 +4266,35 @@ impl ProfileUpdateBridge for api::ProfileUpdate {
             })
             .transpose()?;
 
+        let key = key_store.key.clone().into_inner();
+        let key_manager_state = state.into();
+
+        let card_testing_secret_key = match business_profile.card_testing_secret_key {
+            Some(_) => None,
+            None => {
+                let card_testing_secret_key = Some(Secret::new(utils::generate_id(
+                    consts::FINGERPRINT_SECRET_LENGTH,
+                    "fs",
+                )));
+
+                card_testing_secret_key
+                    .async_lift(|inner| async {
+                        domain_types::crypto_operation(
+                            &key_manager_state,
+                            common_utils::type_name!(domain::Profile),
+                            domain_types::CryptoOperation::EncryptOptional(inner),
+                            km_types::Identifier::Merchant(key_store.merchant_id.clone()),
+                            key.peek(),
+                        )
+                        .await
+                        .and_then(|val| val.try_into_optionaloperation())
+                    })
+                    .await
+                    .change_context(errors::ApiErrorResponse::InternalServerError)
+                    .attach_printable("error while generating card testing secret key")?
+            }
+        };
+
         Ok(domain::ProfileUpdate::Update(Box::new(
             domain::ProfileGeneralUpdate {
                 profile_name: self.profile_name,
@@ -4177,6 +4332,10 @@ impl ProfileUpdateBridge for api::ProfileUpdate {
                 is_click_to_pay_enabled: self.is_click_to_pay_enabled,
                 authentication_product_ids: self.authentication_product_ids,
                 three_ds_decision_manager_config: None,
+                card_testing_guard_config: self
+                    .card_testing_guard_config
+                    .map(ForeignInto::foreign_into),
+                card_testing_secret_key,
             },
         )))
     }
@@ -4200,7 +4359,7 @@ pub async fn update_profile(
         })?;
 
     let profile_update = request
-        .get_update_profile_object(&state, &key_store)
+        .get_update_profile_object(&state, &key_store, &business_profile)
         .await?;
 
     let updated_business_profile = db
diff --git a/crates/router/src/core/card_testing_guard.rs b/crates/router/src/core/card_testing_guard.rs
new file mode 100644
index 00000000000..1b480a9e2ab
--- /dev/null
+++ b/crates/router/src/core/card_testing_guard.rs
@@ -0,0 +1,3 @@
+pub mod utils;
+
+use crate::core::errors;
diff --git a/crates/router/src/core/card_testing_guard/utils.rs b/crates/router/src/core/card_testing_guard/utils.rs
new file mode 100644
index 00000000000..85f949b3b87
--- /dev/null
+++ b/crates/router/src/core/card_testing_guard/utils.rs
@@ -0,0 +1,196 @@
+use error_stack::ResultExt;
+use hyperswitch_domain_models::{
+    card_testing_guard_data::CardTestingGuardData, router_request_types::BrowserInformation,
+};
+use masking::{PeekInterface, Secret};
+use router_env::logger;
+
+use super::errors;
+use crate::{
+    core::{errors::RouterResult, payments::helpers},
+    routes::SessionState,
+    services,
+    types::{api, domain},
+    utils::crypto::{self, SignMessage},
+};
+
+pub async fn validate_card_testing_guard_checks(
+    state: &SessionState,
+    request: &api::PaymentsRequest,
+    payment_method_data: Option<&api_models::payments::PaymentMethodData>,
+    customer_id: &Option<common_utils::id_type::CustomerId>,
+    business_profile: &domain::Profile,
+) -> RouterResult<Option<CardTestingGuardData>> {
+    match &business_profile.card_testing_guard_config {
+        Some(card_testing_guard_config) => {
+            let fingerprint = generate_fingerprint(payment_method_data, business_profile).await?;
+
+            let card_testing_guard_expiry = card_testing_guard_config.card_testing_guard_expiry;
+
+            let mut card_ip_blocking_cache_key = String::new();
+            let mut guest_user_card_blocking_cache_key = String::new();
+            let mut customer_id_blocking_cache_key = String::new();
+
+            if card_testing_guard_config.is_card_ip_blocking_enabled {
+                if let Some(browser_info) = &request.browser_info {
+                    #[cfg(feature = "v1")]
+                    {
+                        let browser_info =
+                            serde_json::from_value::<BrowserInformation>(browser_info.clone())
+                                .change_context(errors::ApiErrorResponse::InternalServerError)
+                                .attach_printable("could not parse browser_info")?;
+
+                        if let Some(browser_info_ip) = browser_info.ip_address {
+                            card_ip_blocking_cache_key =
+                                helpers::validate_card_ip_blocking_for_business_profile(
+                                    state,
+                                    browser_info_ip,
+                                    fingerprint.clone(),
+                                    card_testing_guard_config,
+                                )
+                                .await?;
+                        }
+                    }
+
+                    #[cfg(feature = "v2")]
+                    {
+                        if let Some(browser_info_ip) = browser_info.ip_address {
+                            card_ip_blocking_cache_key =
+                                helpers::validate_card_ip_blocking_for_business_profile(
+                                    state,
+                                    browser_info_ip,
+                                    fingerprint.clone(),
+                                    card_testing_guard_config,
+                                )
+                                .await?;
+                        }
+                    }
+                }
+            }
+
+            if card_testing_guard_config.is_guest_user_card_blocking_enabled {
+                guest_user_card_blocking_cache_key =
+                    helpers::validate_guest_user_card_blocking_for_business_profile(
+                        state,
+                        fingerprint.clone(),
+                        customer_id.clone(),
+                        card_testing_guard_config,
+                    )
+                    .await?;
+            }
+
+            if card_testing_guard_config.is_customer_id_blocking_enabled {
+                if let Some(customer_id) = customer_id.clone() {
+                    customer_id_blocking_cache_key =
+                        helpers::validate_customer_id_blocking_for_business_profile(
+                            state,
+                            customer_id.clone(),
+                            business_profile.get_id(),
+                            card_testing_guard_config,
+                        )
+                        .await?;
+                }
+            }
+
+            Ok(Some(CardTestingGuardData {
+                is_card_ip_blocking_enabled: card_testing_guard_config.is_card_ip_blocking_enabled,
+                card_ip_blocking_cache_key,
+                is_guest_user_card_blocking_enabled: card_testing_guard_config
+                    .is_guest_user_card_blocking_enabled,
+                guest_user_card_blocking_cache_key,
+                is_customer_id_blocking_enabled: card_testing_guard_config
+                    .is_customer_id_blocking_enabled,
+                customer_id_blocking_cache_key,
+                card_testing_guard_expiry,
+            }))
+        }
+        None => Ok(None),
+    }
+}
+
+pub async fn generate_fingerprint(
+    payment_method_data: Option<&api_models::payments::PaymentMethodData>,
+    business_profile: &domain::Profile,
+) -> RouterResult<Secret<String>> {
+    let card_testing_secret_key = &business_profile.card_testing_secret_key;
+
+    match card_testing_secret_key {
+        Some(card_testing_secret_key) => {
+            let card_number_fingerprint = payment_method_data
+                .as_ref()
+                .and_then(|pm_data| match pm_data {
+                    api_models::payments::PaymentMethodData::Card(card) => {
+                        crypto::HmacSha512::sign_message(
+                            &crypto::HmacSha512,
+                            card_testing_secret_key.get_inner().peek().as_bytes(),
+                            card.card_number.clone().get_card_no().as_bytes(),
+                        )
+                        .attach_printable("error in pm fingerprint creation")
+                        .map_or_else(
+                            |err| {
+                                logger::error!(error=?err);
+                                None
+                            },
+                            Some,
+                        )
+                    }
+                    _ => None,
+                })
+                .map(hex::encode);
+
+            card_number_fingerprint.map(Secret::new).ok_or_else(|| {
+                error_stack::report!(errors::ApiErrorResponse::InternalServerError)
+                    .attach_printable("Error while masking fingerprint")
+            })
+        }
+        None => Err(errors::ApiErrorResponse::InternalServerError)
+            .attach_printable("card testing secret key not configured")?,
+    }
+}
+
+pub async fn increment_blocked_count_in_cache(
+    state: &SessionState,
+    card_testing_guard_data: Option<CardTestingGuardData>,
+) -> RouterResult<()> {
+    if let Some(card_testing_guard_data) = card_testing_guard_data.clone() {
+        if card_testing_guard_data.is_card_ip_blocking_enabled
+            && !card_testing_guard_data
+                .card_ip_blocking_cache_key
+                .is_empty()
+        {
+            let _ = services::card_testing_guard::increment_blocked_count_in_cache(
+                state,
+                &card_testing_guard_data.card_ip_blocking_cache_key,
+                card_testing_guard_data.card_testing_guard_expiry.into(),
+            )
+            .await;
+        }
+
+        if card_testing_guard_data.is_guest_user_card_blocking_enabled
+            && !card_testing_guard_data
+                .guest_user_card_blocking_cache_key
+                .is_empty()
+        {
+            let _ = services::card_testing_guard::increment_blocked_count_in_cache(
+                state,
+                &card_testing_guard_data.guest_user_card_blocking_cache_key,
+                card_testing_guard_data.card_testing_guard_expiry.into(),
+            )
+            .await;
+        }
+
+        if card_testing_guard_data.is_customer_id_blocking_enabled
+            && !card_testing_guard_data
+                .customer_id_blocking_cache_key
+                .is_empty()
+        {
+            let _ = services::card_testing_guard::increment_blocked_count_in_cache(
+                state,
+                &card_testing_guard_data.customer_id_blocking_cache_key,
+                card_testing_guard_data.card_testing_guard_expiry.into(),
+            )
+            .await;
+        }
+    }
+    Ok(())
+}
diff --git a/crates/router/src/core/payments.rs b/crates/router/src/core/payments.rs
index 1898dd40666..17775b83aab 100644
--- a/crates/router/src/core/payments.rs
+++ b/crates/router/src/core/payments.rs
@@ -301,6 +301,12 @@ where
             platform_merchant_account.as_ref(),
         )
         .await?;
+
+    operation
+        .to_get_tracker()?
+        .validate_request_with_state(state, &req, &mut payment_data, &business_profile)
+        .await?;
+
     core_utils::validate_profile_id_from_auth_layer(
         profile_id_from_auth_layer,
         &payment_data.get_payment_intent().clone(),
@@ -4982,6 +4988,8 @@ where
     pub tax_data: Option<TaxData>,
     pub session_id: Option<String>,
     pub service_details: Option<api_models::payments::CtpServiceDetails>,
+    pub card_testing_guard_data:
+        Option<hyperswitch_domain_models::card_testing_guard_data::CardTestingGuardData>,
 }
 
 #[derive(Clone, serde::Serialize, Debug)]
diff --git a/crates/router/src/core/payments/helpers.rs b/crates/router/src/core/payments/helpers.rs
index 032262b30aa..ba509221956 100644
--- a/crates/router/src/core/payments/helpers.rs
+++ b/crates/router/src/core/payments/helpers.rs
@@ -1,4 +1,4 @@
-use std::{borrow::Cow, collections::HashSet, str::FromStr};
+use std::{borrow::Cow, collections::HashSet, net::IpAddr, str::FromStr};
 
 #[cfg(feature = "v2")]
 use api_models::ephemeral_key::ClientSecretResponse;
@@ -1478,6 +1478,84 @@ pub fn validate_customer_information(
     }
 }
 
+pub async fn validate_card_ip_blocking_for_business_profile(
+    state: &SessionState,
+    ip: IpAddr,
+    fingerprnt: masking::Secret<String>,
+    card_testing_guard_config: &diesel_models::business_profile::CardTestingGuardConfig,
+) -> RouterResult<String> {
+    let cache_key = format!(
+        "{}_{}_{}",
+        consts::CARD_IP_BLOCKING_CACHE_KEY_PREFIX,
+        fingerprnt.peek(),
+        ip
+    );
+
+    let unsuccessful_payment_threshold = card_testing_guard_config.card_ip_blocking_threshold;
+
+    validate_blocking_threshold(state, unsuccessful_payment_threshold, cache_key).await
+}
+
+pub async fn validate_guest_user_card_blocking_for_business_profile(
+    state: &SessionState,
+    fingerprnt: masking::Secret<String>,
+    customer_id: Option<id_type::CustomerId>,
+    card_testing_guard_config: &diesel_models::business_profile::CardTestingGuardConfig,
+) -> RouterResult<String> {
+    let cache_key = format!(
+        "{}_{}",
+        consts::GUEST_USER_CARD_BLOCKING_CACHE_KEY_PREFIX,
+        fingerprnt.peek()
+    );
+
+    let unsuccessful_payment_threshold =
+        card_testing_guard_config.guest_user_card_blocking_threshold;
+
+    if customer_id.is_none() {
+        Ok(validate_blocking_threshold(state, unsuccessful_payment_threshold, cache_key).await?)
+    } else {
+        Ok(cache_key)
+    }
+}
+
+pub async fn validate_customer_id_blocking_for_business_profile(
+    state: &SessionState,
+    customer_id: id_type::CustomerId,
+    profile_id: &id_type::ProfileId,
+    card_testing_guard_config: &diesel_models::business_profile::CardTestingGuardConfig,
+) -> RouterResult<String> {
+    let cache_key = format!(
+        "{}_{}_{}",
+        consts::CUSTOMER_ID_BLOCKING_PREFIX,
+        profile_id.get_string_repr(),
+        customer_id.get_string_repr(),
+    );
+
+    let unsuccessful_payment_threshold = card_testing_guard_config.customer_id_blocking_threshold;
+
+    validate_blocking_threshold(state, unsuccessful_payment_threshold, cache_key).await
+}
+
+pub async fn validate_blocking_threshold(
+    state: &SessionState,
+    unsuccessful_payment_threshold: i32,
+    cache_key: String,
+) -> RouterResult<String> {
+    match services::card_testing_guard::get_blocked_count_from_cache(state, &cache_key).await {
+        Ok(Some(unsuccessful_payment_count)) => {
+            if unsuccessful_payment_count >= unsuccessful_payment_threshold {
+                Err(errors::ApiErrorResponse::PreconditionFailed {
+                    message: "Blocked due to suspicious activity".to_string(),
+                })?
+            } else {
+                Ok(cache_key)
+            }
+        }
+        Ok(None) => Ok(cache_key),
+        Err(error) => Err(errors::ApiErrorResponse::InternalServerError).attach_printable(error)?,
+    }
+}
+
 #[cfg(feature = "v1")]
 /// Get the customer details from customer field if present
 /// or from the individual fields in `PaymentsRequest`
diff --git a/crates/router/src/core/payments/operations.rs b/crates/router/src/core/payments/operations.rs
index b305370f6c1..a1ebaa04152 100644
--- a/crates/router/src/core/payments/operations.rs
+++ b/crates/router/src/core/payments/operations.rs
@@ -206,6 +206,16 @@ pub trait GetTracker<F: Clone, D, R>: Send {
         header_payload: &hyperswitch_domain_models::payments::HeaderPayload,
         platform_merchant_account: Option<&domain::MerchantAccount>,
     ) -> RouterResult<GetTrackerResponse<D>>;
+
+    async fn validate_request_with_state(
+        &self,
+        _state: &SessionState,
+        _request: &R,
+        _payment_data: &mut D,
+        _business_profile: &domain::Profile,
+    ) -> RouterResult<()> {
+        Ok(())
+    }
 }
 
 #[async_trait]
diff --git a/crates/router/src/core/payments/operations/payment_approve.rs b/crates/router/src/core/payments/operations/payment_approve.rs
index bdb0548d6a4..393d08a68d4 100644
--- a/crates/router/src/core/payments/operations/payment_approve.rs
+++ b/crates/router/src/core/payments/operations/payment_approve.rs
@@ -200,6 +200,7 @@ impl<F: Send + Clone + Sync> GetTracker<F, PaymentData<F>, api::PaymentsCaptureR
             tax_data: None,
             session_id: None,
             service_details: None,
+            card_testing_guard_data: None,
         };
 
         let get_trackers_response = operations::GetTrackerResponse {
diff --git a/crates/router/src/core/payments/operations/payment_cancel.rs b/crates/router/src/core/payments/operations/payment_cancel.rs
index b41247003bd..d713e7aa567 100644
--- a/crates/router/src/core/payments/operations/payment_cancel.rs
+++ b/crates/router/src/core/payments/operations/payment_cancel.rs
@@ -211,6 +211,7 @@ impl<F: Send + Clone + Sync> GetTracker<F, PaymentData<F>, api::PaymentsCancelRe
             tax_data: None,
             session_id: None,
             service_details: None,
+            card_testing_guard_data: None,
         };
 
         let get_trackers_response = operations::GetTrackerResponse {
diff --git a/crates/router/src/core/payments/operations/payment_capture.rs b/crates/router/src/core/payments/operations/payment_capture.rs
index 2bb8dd279e5..2a58adb822c 100644
--- a/crates/router/src/core/payments/operations/payment_capture.rs
+++ b/crates/router/src/core/payments/operations/payment_capture.rs
@@ -260,6 +260,7 @@ impl<F: Send + Clone + Sync> GetTracker<F, payments::PaymentData<F>, api::Paymen
             tax_data: None,
             session_id: None,
             service_details: None,
+            card_testing_guard_data: None,
         };
 
         let get_trackers_response = operations::GetTrackerResponse {
diff --git a/crates/router/src/core/payments/operations/payment_complete_authorize.rs b/crates/router/src/core/payments/operations/payment_complete_authorize.rs
index f1279f394b2..fab2a9144c7 100644
--- a/crates/router/src/core/payments/operations/payment_complete_authorize.rs
+++ b/crates/router/src/core/payments/operations/payment_complete_authorize.rs
@@ -354,6 +354,7 @@ impl<F: Send + Clone + Sync> GetTracker<F, PaymentData<F>, api::PaymentsRequest>
             tax_data: None,
             session_id: None,
             service_details: None,
+            card_testing_guard_data: None,
         };
 
         let customer_details = Some(CustomerDetails {
diff --git a/crates/router/src/core/payments/operations/payment_confirm.rs b/crates/router/src/core/payments/operations/payment_confirm.rs
index 43057855467..62f60d938a2 100644
--- a/crates/router/src/core/payments/operations/payment_confirm.rs
+++ b/crates/router/src/core/payments/operations/payment_confirm.rs
@@ -33,6 +33,7 @@ use crate::{
     core::{
         authentication,
         blocklist::utils as blocklist_utils,
+        card_testing_guard::utils as card_testing_guard_utils,
         errors::{self, CustomResult, RouterResult, StorageErrorExt},
         mandate::helpers as m_helpers,
         payments::{
@@ -825,6 +826,7 @@ impl<F: Send + Clone + Sync> GetTracker<F, PaymentData<F>, api::PaymentsRequest>
             tax_data: None,
             session_id: None,
             service_details: request.ctp_service_details.clone(),
+            card_testing_guard_data: None,
         };
 
         let get_trackers_response = operations::GetTrackerResponse {
@@ -837,6 +839,39 @@ impl<F: Send + Clone + Sync> GetTracker<F, PaymentData<F>, api::PaymentsRequest>
 
         Ok(get_trackers_response)
     }
+
+    async fn validate_request_with_state(
+        &self,
+        state: &SessionState,
+        request: &api::PaymentsRequest,
+        payment_data: &mut PaymentData<F>,
+        business_profile: &domain::Profile,
+    ) -> RouterResult<()> {
+        let payment_method_data: Option<&api_models::payments::PaymentMethodData> = request
+            .payment_method_data
+            .as_ref()
+            .and_then(|request_payment_method_data| {
+                request_payment_method_data.payment_method_data.as_ref()
+            });
+
+        let customer_id = &payment_data.payment_intent.customer_id;
+
+        match payment_method_data {
+            Some(api_models::payments::PaymentMethodData::Card(_card)) => {
+                payment_data.card_testing_guard_data =
+                    card_testing_guard_utils::validate_card_testing_guard_checks(
+                        state,
+                        request,
+                        payment_method_data,
+                        customer_id,
+                        business_profile,
+                    )
+                    .await?;
+                Ok(())
+            }
+            _ => Ok(()),
+        }
+    }
 }
 
 #[async_trait]
@@ -1870,6 +1905,7 @@ impl<F: Clone + Sync> UpdateTracker<F, PaymentData<F>, api::PaymentsRequest> for
     }
 }
 
+#[async_trait]
 impl<F: Send + Clone + Sync> ValidateRequest<F, api::PaymentsRequest, PaymentData<F>>
     for PaymentConfirm
 {
diff --git a/crates/router/src/core/payments/operations/payment_create.rs b/crates/router/src/core/payments/operations/payment_create.rs
index 1d3a56162e9..06036c4bc59 100644
--- a/crates/router/src/core/payments/operations/payment_create.rs
+++ b/crates/router/src/core/payments/operations/payment_create.rs
@@ -625,6 +625,7 @@ impl<F: Send + Clone + Sync> GetTracker<F, PaymentData<F>, api::PaymentsRequest>
             tax_data: None,
             session_id: None,
             service_details: None,
+            card_testing_guard_data: None,
         };
 
         let get_trackers_response = operations::GetTrackerResponse {
diff --git a/crates/router/src/core/payments/operations/payment_post_session_tokens.rs b/crates/router/src/core/payments/operations/payment_post_session_tokens.rs
index 9f21dbc9981..0a3efc92ccd 100644
--- a/crates/router/src/core/payments/operations/payment_post_session_tokens.rs
+++ b/crates/router/src/core/payments/operations/payment_post_session_tokens.rs
@@ -169,6 +169,7 @@ impl<F: Send + Clone + Sync> GetTracker<F, PaymentData<F>, api::PaymentsPostSess
             tax_data: None,
             session_id: None,
             service_details: None,
+            card_testing_guard_data: None,
         };
         let get_trackers_response = operations::GetTrackerResponse {
             operation: Box::new(self),
diff --git a/crates/router/src/core/payments/operations/payment_reject.rs b/crates/router/src/core/payments/operations/payment_reject.rs
index 1591b1d6a47..91317dbde68 100644
--- a/crates/router/src/core/payments/operations/payment_reject.rs
+++ b/crates/router/src/core/payments/operations/payment_reject.rs
@@ -198,6 +198,7 @@ impl<F: Send + Clone + Sync> GetTracker<F, PaymentData<F>, PaymentsCancelRequest
             tax_data: None,
             session_id: None,
             service_details: None,
+            card_testing_guard_data: None,
         };
 
         let get_trackers_response = operations::GetTrackerResponse {
diff --git a/crates/router/src/core/payments/operations/payment_response.rs b/crates/router/src/core/payments/operations/payment_response.rs
index 25ae8c84c39..f543c9aa1a0 100644
--- a/crates/router/src/core/payments/operations/payment_response.rs
+++ b/crates/router/src/core/payments/operations/payment_response.rs
@@ -30,6 +30,7 @@ use crate::{
     connector::utils::PaymentResponseRouterData,
     consts,
     core::{
+        card_testing_guard::utils as card_testing_guard_utils,
         errors::{self, CustomResult, RouterResult, StorageErrorExt},
         mandate,
         payment_methods::{self, cards::create_encrypted_data},
@@ -2047,6 +2048,14 @@ async fn payment_response_update_tracker<F: Clone, T: types::Capturable>(
             .map(|info| info.status = status)
     });
 
+    if payment_data.payment_attempt.status == enums::AttemptStatus::Failure {
+        let _ = card_testing_guard_utils::increment_blocked_count_in_cache(
+            state,
+            payment_data.card_testing_guard_data.clone(),
+        )
+        .await;
+    }
+
     match router_data.integrity_check {
         Ok(()) => Ok(payment_data),
         Err(err) => {
diff --git a/crates/router/src/core/payments/operations/payment_session.rs b/crates/router/src/core/payments/operations/payment_session.rs
index be4f804a8a7..a86ca0be4ef 100644
--- a/crates/router/src/core/payments/operations/payment_session.rs
+++ b/crates/router/src/core/payments/operations/payment_session.rs
@@ -216,6 +216,7 @@ impl<F: Send + Clone + Sync> GetTracker<F, PaymentData<F>, api::PaymentsSessionR
             tax_data: None,
             session_id: None,
             service_details: None,
+            card_testing_guard_data: None,
         };
 
         let get_trackers_response = operations::GetTrackerResponse {
diff --git a/crates/router/src/core/payments/operations/payment_start.rs b/crates/router/src/core/payments/operations/payment_start.rs
index 299d7237807..ebae54e1220 100644
--- a/crates/router/src/core/payments/operations/payment_start.rs
+++ b/crates/router/src/core/payments/operations/payment_start.rs
@@ -203,6 +203,7 @@ impl<F: Send + Clone + Sync> GetTracker<F, PaymentData<F>, api::PaymentsStartReq
             tax_data: None,
             session_id: None,
             service_details: None,
+            card_testing_guard_data: None,
         };
 
         let get_trackers_response = operations::GetTrackerResponse {
diff --git a/crates/router/src/core/payments/operations/payment_status.rs b/crates/router/src/core/payments/operations/payment_status.rs
index c458f95ad97..e05eed41419 100644
--- a/crates/router/src/core/payments/operations/payment_status.rs
+++ b/crates/router/src/core/payments/operations/payment_status.rs
@@ -534,6 +534,7 @@ async fn get_tracker_for_sync<
         tax_data: None,
         session_id: None,
         service_details: None,
+        card_testing_guard_data: None,
     };
 
     let get_trackers_response = operations::GetTrackerResponse {
diff --git a/crates/router/src/core/payments/operations/payment_update.rs b/crates/router/src/core/payments/operations/payment_update.rs
index ac37513f2b9..89a94552bc2 100644
--- a/crates/router/src/core/payments/operations/payment_update.rs
+++ b/crates/router/src/core/payments/operations/payment_update.rs
@@ -495,6 +495,7 @@ impl<F: Send + Clone + Sync> GetTracker<F, PaymentData<F>, api::PaymentsRequest>
             tax_data: None,
             session_id: None,
             service_details: None,
+            card_testing_guard_data: None,
         };
 
         let get_trackers_response = operations::GetTrackerResponse {
diff --git a/crates/router/src/core/payments/operations/payments_incremental_authorization.rs b/crates/router/src/core/payments/operations/payments_incremental_authorization.rs
index 95c50f2f17e..8ef656599a7 100644
--- a/crates/router/src/core/payments/operations/payments_incremental_authorization.rs
+++ b/crates/router/src/core/payments/operations/payments_incremental_authorization.rs
@@ -177,6 +177,7 @@ impl<F: Send + Clone + Sync>
             tax_data: None,
             session_id: None,
             service_details: None,
+            card_testing_guard_data: None,
         };
 
         let get_trackers_response = operations::GetTrackerResponse {
diff --git a/crates/router/src/core/payments/operations/tax_calculation.rs b/crates/router/src/core/payments/operations/tax_calculation.rs
index bcda2af8768..0d31c4d5de1 100644
--- a/crates/router/src/core/payments/operations/tax_calculation.rs
+++ b/crates/router/src/core/payments/operations/tax_calculation.rs
@@ -183,6 +183,7 @@ impl<F: Send + Clone + Sync>
             tax_data: Some(tax_data),
             session_id: request.session_id.clone(),
             service_details: None,
+            card_testing_guard_data: None,
         };
         let get_trackers_response = operations::GetTrackerResponse {
             operation: Box::new(self),
diff --git a/crates/router/src/services.rs b/crates/router/src/services.rs
index 18bc1eb41c4..57f9fadcbcd 100644
--- a/crates/router/src/services.rs
+++ b/crates/router/src/services.rs
@@ -12,6 +12,7 @@ pub mod kafka;
 pub mod logger;
 pub mod pm_auth;
 
+pub mod card_testing_guard;
 #[cfg(feature = "olap")]
 pub mod openidconnect;
 
diff --git a/crates/router/src/services/card_testing_guard.rs b/crates/router/src/services/card_testing_guard.rs
new file mode 100644
index 00000000000..09c5dbd9504
--- /dev/null
+++ b/crates/router/src/services/card_testing_guard.rs
@@ -0,0 +1,78 @@
+use std::sync::Arc;
+
+use error_stack::ResultExt;
+use redis_interface::RedisConnectionPool;
+
+use crate::{
+    core::errors::{ApiErrorResponse, RouterResult},
+    routes::app::SessionStateInfo,
+};
+
+fn get_redis_connection<A: SessionStateInfo>(state: &A) -> RouterResult<Arc<RedisConnectionPool>> {
+    state
+        .store()
+        .get_redis_conn()
+        .change_context(ApiErrorResponse::InternalServerError)
+        .attach_printable("Failed to get redis connection")
+}
+
+pub async fn set_blocked_count_in_cache<A>(
+    state: &A,
+    cache_key: &str,
+    value: i32,
+    expiry: i64,
+) -> RouterResult<()>
+where
+    A: SessionStateInfo + Sync,
+{
+    let redis_conn = get_redis_connection(state)?;
+
+    redis_conn
+        .set_key_with_expiry(&cache_key.into(), value, expiry)
+        .await
+        .change_context(ApiErrorResponse::InternalServerError)
+}
+
+pub async fn get_blocked_count_from_cache<A>(
+    state: &A,
+    cache_key: &str,
+) -> RouterResult<Option<i32>>
+where
+    A: SessionStateInfo + Sync,
+{
+    let redis_conn = get_redis_connection(state)?;
+
+    let value: Option<i32> = redis_conn
+        .get_key(&cache_key.into())
+        .await
+        .change_context(ApiErrorResponse::InternalServerError)?;
+
+    Ok(value)
+}
+
+pub async fn increment_blocked_count_in_cache<A>(
+    state: &A,
+    cache_key: &str,
+    expiry: i64,
+) -> RouterResult<()>
+where
+    A: SessionStateInfo + Sync,
+{
+    let redis_conn = get_redis_connection(state)?;
+
+    let value: Option<i32> = redis_conn
+        .get_key(&cache_key.into())
+        .await
+        .change_context(ApiErrorResponse::InternalServerError)?;
+
+    let mut incremented_blocked_count: i32 = 1;
+
+    if let Some(actual_value) = value {
+        incremented_blocked_count = actual_value + 1;
+    }
+
+    redis_conn
+        .set_key_with_expiry(&cache_key.into(), incremented_blocked_count, expiry)
+        .await
+        .change_context(ApiErrorResponse::InternalServerError)
+}
diff --git a/crates/router/src/types/api/admin.rs b/crates/router/src/types/api/admin.rs
index 289b56a7800..2852766cdd3 100644
--- a/crates/router/src/types/api/admin.rs
+++ b/crates/router/src/types/api/admin.rs
@@ -15,20 +15,25 @@ pub use api_models::{
         OrganizationCreateRequest, OrganizationId, OrganizationResponse, OrganizationUpdateRequest,
     },
 };
-use common_utils::ext_traits::ValueExt;
+use common_utils::{ext_traits::ValueExt, types::keymanager as km_types};
 use diesel_models::organization::OrganizationBridge;
 use error_stack::ResultExt;
 use hyperswitch_domain_models::merchant_key_store::MerchantKeyStore;
-use masking::{ExposeInterface, Secret};
+use masking::{ExposeInterface, PeekInterface, Secret};
 
 use crate::{
+    consts,
     core::errors,
     routes::SessionState,
     types::{
-        domain,
+        domain::{
+            self,
+            types::{self as domain_types, AsyncLift},
+        },
         transformers::{ForeignInto, ForeignTryFrom},
         ForeignFrom,
     },
+    utils,
 };
 
 impl ForeignFrom<diesel_models::organization::Organization> for OrganizationResponse {
@@ -179,6 +184,9 @@ impl ForeignTryFrom<domain::Profile> for ProfileResponse {
             always_request_extended_authorization: item.always_request_extended_authorization,
             is_click_to_pay_enabled: item.is_click_to_pay_enabled,
             authentication_product_ids: item.authentication_product_ids,
+            card_testing_guard_config: item
+                .card_testing_guard_config
+                .map(ForeignInto::foreign_into),
         })
     }
 }
@@ -250,6 +258,9 @@ impl ForeignTryFrom<domain::Profile> for ProfileResponse {
             is_network_tokenization_enabled: item.is_network_tokenization_enabled,
             is_click_to_pay_enabled: item.is_click_to_pay_enabled,
             authentication_product_ids: item.authentication_product_ids,
+            card_testing_guard_config: item
+                .card_testing_guard_config
+                .map(ForeignInto::foreign_into),
         })
     }
 }
@@ -262,6 +273,7 @@ pub async fn create_profile_from_merchant_account(
     key_store: &MerchantKeyStore,
 ) -> Result<domain::Profile, error_stack::Report<errors::ApiErrorResponse>> {
     use common_utils::ext_traits::AsyncExt;
+    use diesel_models::business_profile::CardTestingGuardConfig;
 
     use crate::core;
 
@@ -306,6 +318,34 @@ pub async fn create_profile_from_merchant_account(
         })
         .transpose()?;
 
+    let key = key_store.key.clone().into_inner();
+    let key_manager_state = state.into();
+
+    let card_testing_secret_key = Some(Secret::new(utils::generate_id(
+        consts::FINGERPRINT_SECRET_LENGTH,
+        "fs",
+    )));
+
+    let card_testing_guard_config = match request.card_testing_guard_config {
+        Some(card_testing_guard_config) => Some(CardTestingGuardConfig::foreign_from(
+            card_testing_guard_config,
+        )),
+        None => Some(CardTestingGuardConfig {
+            is_card_ip_blocking_enabled: common_utils::consts::DEFAULT_CARD_IP_BLOCKING_STATUS,
+            card_ip_blocking_threshold: common_utils::consts::DEFAULT_CARD_IP_BLOCKING_THRESHOLD,
+            is_guest_user_card_blocking_enabled:
+                common_utils::consts::DEFAULT_GUEST_USER_CARD_BLOCKING_STATUS,
+            guest_user_card_blocking_threshold:
+                common_utils::consts::DEFAULT_GUEST_USER_CARD_BLOCKING_THRESHOLD,
+            is_customer_id_blocking_enabled:
+                common_utils::consts::DEFAULT_CUSTOMER_ID_BLOCKING_STATUS,
+            customer_id_blocking_threshold:
+                common_utils::consts::DEFAULT_CUSTOMER_ID_BLOCKING_THRESHOLD,
+            card_testing_guard_expiry:
+                common_utils::consts::DEFAULT_CARD_TESTING_GUARD_EXPIRY_IN_SECS,
+        }),
+    };
+
     Ok(domain::Profile::from(domain::ProfileSetter {
         profile_id,
         merchant_id,
@@ -379,5 +419,21 @@ pub async fn create_profile_from_merchant_account(
         always_request_extended_authorization: request.always_request_extended_authorization,
         is_click_to_pay_enabled: request.is_click_to_pay_enabled,
         authentication_product_ids: request.authentication_product_ids,
+        card_testing_guard_config,
+        card_testing_secret_key: card_testing_secret_key
+            .async_lift(|inner| async {
+                domain_types::crypto_operation(
+                    &key_manager_state,
+                    common_utils::type_name!(domain::Profile),
+                    domain_types::CryptoOperation::EncryptOptional(inner),
+                    km_types::Identifier::Merchant(key_store.merchant_id.clone()),
+                    key.peek(),
+                )
+                .await
+                .and_then(|val| val.try_into_optionaloperation())
+            })
+            .await
+            .change_context(errors::ApiErrorResponse::InternalServerError)
+            .attach_printable("error while generating card testing secret key")?,
     }))
 }
diff --git a/crates/router/src/types/transformers.rs b/crates/router/src/types/transformers.rs
index aa27e362df2..a05020856b9 100644
--- a/crates/router/src/types/transformers.rs
+++ b/crates/router/src/types/transformers.rs
@@ -2019,6 +2019,56 @@ impl ForeignFrom<diesel_models::business_profile::AuthenticationConnectorDetails
     }
 }
 
+impl ForeignFrom<api_models::admin::CardTestingGuardConfig>
+    for diesel_models::business_profile::CardTestingGuardConfig
+{
+    fn foreign_from(item: api_models::admin::CardTestingGuardConfig) -> Self {
+        Self {
+            is_card_ip_blocking_enabled: match item.card_ip_blocking_status {
+                api_models::admin::CardTestingGuardStatus::Enabled => true,
+                api_models::admin::CardTestingGuardStatus::Disabled => false,
+            },
+            card_ip_blocking_threshold: item.card_ip_blocking_threshold,
+            is_guest_user_card_blocking_enabled: match item.guest_user_card_blocking_status {
+                api_models::admin::CardTestingGuardStatus::Enabled => true,
+                api_models::admin::CardTestingGuardStatus::Disabled => false,
+            },
+            guest_user_card_blocking_threshold: item.guest_user_card_blocking_threshold,
+            is_customer_id_blocking_enabled: match item.customer_id_blocking_status {
+                api_models::admin::CardTestingGuardStatus::Enabled => true,
+                api_models::admin::CardTestingGuardStatus::Disabled => false,
+            },
+            customer_id_blocking_threshold: item.customer_id_blocking_threshold,
+            card_testing_guard_expiry: item.card_testing_guard_expiry,
+        }
+    }
+}
+
+impl ForeignFrom<diesel_models::business_profile::CardTestingGuardConfig>
+    for api_models::admin::CardTestingGuardConfig
+{
+    fn foreign_from(item: diesel_models::business_profile::CardTestingGuardConfig) -> Self {
+        Self {
+            card_ip_blocking_status: match item.is_card_ip_blocking_enabled {
+                true => api_models::admin::CardTestingGuardStatus::Enabled,
+                false => api_models::admin::CardTestingGuardStatus::Disabled,
+            },
+            card_ip_blocking_threshold: item.card_ip_blocking_threshold,
+            guest_user_card_blocking_status: match item.is_guest_user_card_blocking_enabled {
+                true => api_models::admin::CardTestingGuardStatus::Enabled,
+                false => api_models::admin::CardTestingGuardStatus::Disabled,
+            },
+            guest_user_card_blocking_threshold: item.guest_user_card_blocking_threshold,
+            customer_id_blocking_status: match item.is_customer_id_blocking_enabled {
+                true => api_models::admin::CardTestingGuardStatus::Enabled,
+                false => api_models::admin::CardTestingGuardStatus::Disabled,
+            },
+            customer_id_blocking_threshold: item.customer_id_blocking_threshold,
+            card_testing_guard_expiry: item.card_testing_guard_expiry,
+        }
+    }
+}
+
 impl ForeignFrom<api_models::admin::WebhookDetails>
     for diesel_models::business_profile::WebhookDetails
 {
diff --git a/migrations/2025-01-27-113914_add_card_testing_guard_config_column_to_business_profile/down.sql b/migrations/2025-01-27-113914_add_card_testing_guard_config_column_to_business_profile/down.sql
new file mode 100644
index 00000000000..bd9c5a00505
--- /dev/null
+++ b/migrations/2025-01-27-113914_add_card_testing_guard_config_column_to_business_profile/down.sql
@@ -0,0 +1,7 @@
+-- This file should undo anything in `up.sql`
+
+ALTER TABLE business_profile 
+DROP COLUMN IF EXISTS card_testing_guard_config;
+
+ALTER TABLE business_profile 
+DROP COLUMN IF EXISTS card_testing_secret_key;
diff --git a/migrations/2025-01-27-113914_add_card_testing_guard_config_column_to_business_profile/up.sql b/migrations/2025-01-27-113914_add_card_testing_guard_config_column_to_business_profile/up.sql
new file mode 100644
index 00000000000..e933074edff
--- /dev/null
+++ b/migrations/2025-01-27-113914_add_card_testing_guard_config_column_to_business_profile/up.sql
@@ -0,0 +1,9 @@
+-- Your SQL goes here
+
+ALTER TABLE business_profile
+ADD COLUMN card_testing_guard_config JSONB
+DEFAULT NULL;
+
+ALTER TABLE business_profile 
+ADD COLUMN card_testing_secret_key BYTEA
+DEFAULT NULL;
\ No newline at end of file

## Type of Change
<!-- Put an `x` in the boxes that apply -->

- [ ] Bugfix
- [x] New feature
- [ ] Enhancement
- [ ] Refactoring
- [ ] Dependency updates
- [ ] Documentation
- [ ] CI/CD

## Description
<!-- Describe your changes in detail -->

**Problem Statement:** 

Card testing attacks involve fraudsters using stolen credit card details to make small transactions on e-commerce sites using different combinations of CVC to verify if the CVC is valid. Successful transactions indicate the card is active and the CVC is valid, while failed ones are discarded. This is done to avoid detection before committing larger fraudulent purchases.

**Solution:**

We have implemented three rules for detecting and preventing this card testing attacks:

I) Card <> IP Blocking for Merchant : If there are X number of unsuccessful payment attempts from a single IP Address for a specific merchant, then that combination of Card <> IP will be blocked for that merchant for a particular duration.

II) Card Blocking for Guest Users for Merchant: If there are X number of unsuccessful payment attempts for a single card, then guest user payments will be blocked for that card and that merchant for a particular duration. Logged in customers will still be able to use that card for payment. 

III) Customer ID Blocking for Merchant: If there are X number of unsuccessful payment attempts from a single Customer ID, then that customer ID will be blocked from making any payments for a particular duration. 

These unsuccessful payment thresholds and duration for blocking is configurable and stored in database.
Whether the merchants want these rules to be enabled/disabled, that is also configurable.

**Implementation:**

The attacker gets the ```client_secret``` from the payment intent create call which happens through our SDK, and uses the ```client_secret``` to hit the /confirm API repeatedly with different sets of card numbers and CVC.

A method ```validate_request_with_state``` has been created in the ```GetTracker``` trait which enforces the three above mentioned rules depending on the business_profile config. The `validate_request_with_state method` internally calls `validate_card_ip_blocking_for_business_profile` method, `validate_guest_user_card_blocking_for_business_profile` method and `validate_customer_id_blocking_for_business_profile` method for performing the below validations:

I) Card<>IP Blocking: A fingerprint is generated for the card which is unique to the ```business_profile``` (by using a hash key which is unique to the profile and stored as ```card_testing_secret_key``` in ```business_profile```). This is done so that the cards are blocked at a profile level. The IP Address is fetched from the payment intent create request, and then for each unsuccessful payment attempt, the value of the redis key CardFingerprint<>IP is increased by 1, and after it reaches a certain threshold, it is blocked. 

II) Guest User Card Blocking: A fingerprint is generated for the card which is unique to the ```business_profile``` (by using a hash key which is unique to the profile and stored as ```card_testing_secret_key``` in ```business_profile```). This is done so that the cards are not blocked at a profile level. For each unsuccessful payment attempt, the value of the redis key CardFingerprint is increased by 1, and after it reaches a certain threshold, it is blocked, but only for guest users. Logged in customers can still make payments with that card.

III) Customer ID Blocking: The ```customer_id``` is fetched from the payment intent create call request, and then for each unsuccessful payment attempt, the value of redis key CardFingerprint<>Profile is increased by 1, and after it reaches a certain threshold, it is blocked. 


### Additional Changes

- [x] This PR modifies the API contract
- [x] This PR modifies the database schema
- [ ] This PR modifies application configuration/environment variables

<!--
Provide links to the files with corresponding changes.

Following are the paths where you can find config files:
1. `config`
2. `crates/router/src/configs`
3. `loadtest/config`
-->


## Motivation and Context
<!--
Why is this change required? What problem does it solve?
If it fixes an open issue, please link to the issue here.

If you don't have an issue, we'd recommend starting with one first so the PR
can focus on the implementation (unless it is an obvious bug or documentation fix
that will have little conversation).
-->


## How did you test it?
<!--
Did you write an integration/unit/API test to verify the code changes?
Or did you test this change manually (provide relevant screenshots)?
-->

**Postman Tests**

**Step By Step Guide to Test:**

1. Use Adyen Connector to test the curls (because for Adyen, only a specific CVC works for test cards)
2. Update Business Profile to set `card_ip_blocking_status` as `enabled`, `guest_user_card_blocking_status` as `disabled` and `customer_id_blocking_status` as `disabled`
3. Now that card_ip_blocking is enabled, start hitting the endpoints repeatedly with incorrect CVC to make the payments fail (Use curl provided below). After X attempts (determined by `card_ip_blocking_threshold`), the payment attempt will be blocked. 
4. Update Business Profile to set `card_ip_blocking_status` as `disabled`, `guest_user_card_blocking_status` as `enabled` and `customer_id_blocking_status` as `disabled`
5. Now that guest_user_card_blocking is enabled, start hitting the endpoints repeatedly with incorrect CVC to make the payments fail (Use curl provided below). After X attempts (determined by `guest_user_card_blocking_threshold`), the payment attempt will be blocked. 
6. Update Business Profile to set `card_ip_blocking_status` as `disabled`, `guest_user_card_blocking_status` as `disabled` and `customer_id_blocking_status` as `enabled`
7. Now that customer_id_blocking is enabled, start hitting the endpoints repeatedly with incorrect CVC to make the payments fail (Use curl provided below). After X attempts (determined by `customer_id_blocking_threshold`), the payment attempt will be blocked. 

**Update Business Profile (For enabling card_ip_blocking)**

-Request

```
curl --location 'http://localhost:8080/account/postman_merchant_GHAction_20cfc2e0-4fb3-4fde-a322-a5d4412b1596/business_profile/pro_VvEqQhEZBLj6WGrH4efC' \
--header 'Content-Type: application/json' \
--header 'api-key: test_admin' \
--data-raw '{
    "profile_name": "Update5",
    "return_url": "https://google.com/success",
    "enable_payment_response_hash": true,
    "redirect_to_merchant_with_http_post": false,
    "webhook_details": {
        "webhook_version": "1.0.1",
        "webhook_username": "ekart_retail",
        "webhook_password": "password_ekart@123",
        "webhook_url": "https://webhook.site",
        "payment_created_enabled": true,
        "payment_succeeded_enabled": true,
        "payment_failed_enabled": true
    },
    "metadata": null,
    
    
    
    
    "intent_fulfillment_time": 900,
    "frm_routing_algorithm": null,
    "payout_routing_algorithm": null,
    "applepay_verified_domains": null,
    "session_expiry": 900,
    "payment_link_config": {
        "display_billing_details": true,
        "hide_card_nickname_field": true
    },
    "authentication_connector_details": null,
    "use_billing_as_payment_method_billing": true,
    "collect_shipping_details_from_wallet_connector": false,
    "collect_billing_details_from_wallet_connector": false,
    "is_connector_agnostic_mit_enabled": false,
    "payout_link_config": null,
    "outgoing_webhook_custom_http_headers": null,
    "card_testing_guard_config": {
        "card_ip_blocking_status": "enabled",
        "card_ip_blocking_threshold": 3,
        "guest_user_card_blocking_status": "disabled",
        "guest_user_card_blocking_threshold": 10,
        "customer_id_blocking_status": "disabled",
        "customer_id_blocking_threshold": 5,
        "card_testing_guard_expiry": 3600
    }
}'
```

-Response 

```
{
    "merchant_id": "postman_merchant_GHAction_20cfc2e0-4fb3-4fde-a322-a5d4412b1596",
    "profile_id": "pro_VvEqQhEZBLj6WGrH4efC",
    "profile_name": "Update5",
    "return_url": "https://google.com/success",
    "enable_payment_response_hash": true,
    "payment_response_hash_key": "5C72AqxtJV2P2YfLQoIF7L72uuz9srr3H290cKiA8pEaR0H7kPWqmC8fB6Y8Xe4Y",
    "redirect_to_merchant_with_http_post": false,
    "webhook_details": {
        "webhook_version": "1.0.1",
        "webhook_username": "ekart_retail",
        "webhook_password": "password_ekart@123",
        "webhook_url": "https://webhook.site",
        "payment_created_enabled": true,
        "payment_succeeded_enabled": true,
        "payment_failed_enabled": true
    },
    "metadata": null,
    "routing_algorithm": null,
    "intent_fulfillment_time": 900,
    "frm_routing_algorithm": null,
    "payout_routing_algorithm": null,
    "applepay_verified_domains": null,
    "session_expiry": 900,
    "payment_link_config": {
        "domain_name": null,
        "theme": null,
        "logo": null,
        "seller_name": null,
        "sdk_layout": null,
        "display_sdk_only": null,
        "enabled_saved_payment_method": null,
        "hide_card_nickname_field": true,
        "show_card_form_by_default": null,
        "transaction_details": null,
        "background_image": null,
        "details_layout": null,
        "payment_button_text": null,
        "business_specific_configs": null,
        "allowed_domains": null,
        "branding_visibility": null
    },
    "authentication_connector_details": null,
    "use_billing_as_payment_method_billing": true,
    "extended_card_info_config": null,
    "collect_shipping_details_from_wallet_connector": false,
    "collect_billing_details_from_wallet_connector": false,
    "always_collect_shipping_details_from_wallet_connector": false,
    "always_collect_billing_details_from_wallet_connector": false,
    "is_connector_agnostic_mit_enabled": false,
    "payout_link_config": null,
    "outgoing_webhook_custom_http_headers": null,
    "tax_connector_id": null,
    "is_tax_connector_enabled": false,
    "is_network_tokenization_enabled": false,
    "is_auto_retries_enabled": false,
    "max_auto_retries_enabled": null,
    "is_click_to_pay_enabled": false,
    "authentication_product_ids": null,
    "card_testing_guard_config": {
        "card_ip_blocking_status": "enabled",
        "card_ip_blocking_threshold": 3,
        "guest_user_card_blocking_status": "disabled",
        "guest_user_card_blocking_threshold": 10,
        "customer_id_blocking_status": "disabled",
        "customer_id_blocking_threshold": 5,
        "card_testing_guard_expiry": 3600
    }
}
```

**1. Card <> IP Blocking (Below Threshold)**

-Request

```
curl --location 'http://localhost:8080/payments' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: dev_DXWmMAIEepKhfTAZd13oawyvbN7eNbPHY16nLqlZynQOAOcqdKRWBstt5cQSS7LO' \
--data-raw '{
    "amount": 12345,
    "currency": "USD",
    "confirm": true,
    "capture_method": "automatic",
    "capture_on": "2022-09-10T10:11:12Z",
    "amount_to_capture": 12345,
    "customer_id": "abcd",
    "email": "guest@example.com",
    "name": "John Doe",
    "phone": "999999999",
    "phone_country_code": "+1",
    "description": "Its my first payment request",
    "authentication_type": "no_three_ds",
    "return_url": "https://duck.com",
    "payment_method": "card",
    "payment_method_data": {
        "card": {
            "card_number": "4212345678901237",
            "card_exp_month": "03",
            "card_exp_year": "30",
            "card_holder_name": "John Smith",
            "card_cvc": "739"
        }
    },
    "billing": {
        "address": {
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "city": "San Fransico",
            "state": "California",
            "zip": "94122",
            "country": "US",
            "first_name": "joseph",
            "last_name": "Doe"
        },
        "phone": {
            "number": "9123456789",
            "country_code": "+91"
        }
    },
    "shipping": {
        "address": {
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "city": "San Fransico",
            "state": "California",
            "zip": "94122",
            "country": "US",
            "first_name": "joseph",
            "last_name": "Doe"
        },
        "phone": {
            "number": "9123456789",
            "country_code": "+91"
        }
    },
    "statement_descriptor_name": "joseph",
    "statement_descriptor_suffix": "JS",
    "browser_info": {
        "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36",
        "accept_header": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
        "language": "nl-NL",
        "color_depth": 24,
        "screen_height": 723,
        "screen_width": 1536,
        "time_zone": 0,
        "java_enabled": true,
        "java_script_enabled": true,
        "ip_address": "125.0.0.6"
    }
}'
```

-Response

```
{
    "payment_id": "pay_tVK43iCoFLj3giMpq1aR",
    "merchant_id": "postman_merchant_GHAction_7522c600-57f2-4a82-b4f4-9df401d240ab",
    "status": "failed",
    "amount": 12345,
    "net_amount": 12345,
    "shipping_cost": null,
    "amount_capturable": 0,
    "amount_received": null,
    "connector": "adyen",
    "client_secret": "pay_tVK43iCoFLj3giMpq1aR_secret_slmMPbx0VVLowhjqrwF9",
    "created": "2025-01-27T07:16:16.548Z",
    "currency": "USD",
    "customer_id": "abcd",
    "customer": {
        "id": "abcd",
        "name": "John Doe",
        "email": "guest@example.com",
        "phone": "999999999",
        "phone_country_code": "+1"
    },
    "description": "Its my first payment request",
    "refunds": null,
    "disputes": null,
    "mandate_id": null,
    "mandate_data": null,
    "setup_future_usage": null,
    "off_session": null,
    "capture_on": null,
    "capture_method": "automatic",
    "payment_method": "card",
    "payment_method_data": {
        "card": {
            "last4": "1237",
            "card_type": null,
            "card_network": null,
            "card_issuer": null,
            "card_issuing_country": null,
            "card_isin": "421234",
            "card_extended_bin": null,
            "card_exp_month": "03",
            "card_exp_year": "30",
            "card_holder_name": "John Smith",
            "payment_checks": null,
            "authentication_data": null
        },
        "billing": null
    },
    "payment_token": null,
    "shipping": {
        "address": {
            "city": "San Fransico",
            "country": "US",
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "zip": "94122",
            "state": "California",
            "first_name": "joseph",
            "last_name": "Doe"
        },
        "phone": {
            "number": "9123456789",
            "country_code": "+91"
        },
        "email": null
    },
    "billing": {
        "address": {
            "city": "San Fransico",
            "country": "US",
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "zip": "94122",
            "state": "California",
            "first_name": "joseph",
            "last_name": "Doe"
        },
        "phone": {
            "number": "9123456789",
            "country_code": "+91"
        },
        "email": null
    },
    "order_details": null,
    "email": "guest@example.com",
    "name": "John Doe",
    "phone": "999999999",
    "return_url": "https://duck.com/",
    "authentication_type": "no_three_ds",
    "statement_descriptor_name": "joseph",
    "statement_descriptor_suffix": "JS",
    "next_action": null,
    "cancellation_reason": null,
    "error_code": "24",
    "error_message": "CVC Declined",
    "unified_code": "UE_9000",
    "unified_message": "Something went wrong",
    "payment_experience": null,
    "payment_method_type": null,
    "connector_label": null,
    "business_country": null,
    "business_label": "default",
    "business_sub_label": null,
    "allowed_payment_method_types": null,
    "ephemeral_key": {
        "customer_id": "abcd",
        "created_at": 1737962176,
        "expires": 1737965776,
        "secret": "epk_76f0a10b19ad4a91bd597b75680b4afb"
    },
    "manual_retry_allowed": true,
    "connector_transaction_id": "D3W4SJB5J4P8CX65",
    "frm_message": null,
    "metadata": null,
    "connector_metadata": null,
    "feature_metadata": null,
    "reference_id": null,
    "payment_link": null,
    "profile_id": "pro_6nc1JRTymtljmHmhnTEt",
    "surcharge_details": null,
    "attempt_count": 1,
    "merchant_decision": null,
    "merchant_connector_id": "mca_wpJDRDrWhfV2oZR77bFX",
    "incremental_authorization_allowed": false,
    "authorization_count": null,
    "incremental_authorizations": null,
    "external_authentication_details": null,
    "external_3ds_authentication_attempted": false,
    "expires_on": "2025-01-27T07:31:16.548Z",
    "fingerprint": null,
    "browser_info": {
        "language": "nl-NL",
        "time_zone": 0,
        "ip_address": "125.0.0.6",
        "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36",
        "color_depth": 24,
        "java_enabled": true,
        "screen_width": 1536,
        "accept_header": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
        "screen_height": 723,
        "java_script_enabled": true
    },
    "payment_method_id": null,
    "payment_method_status": null,
    "updated": "2025-01-27T07:16:19.648Z",
    "split_payments": null,
    "frm_metadata": null,
    "merchant_order_reference_id": null,
    "order_tax_amount": null,
    "connector_mandate_id": null
}
```

**2. Card <> IP Blocking (After threshold)**

-Request

```
curl --location 'http://localhost:8080/payments' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: dev_DXWmMAIEepKhfTAZd13oawyvbN7eNbPHY16nLqlZynQOAOcqdKRWBstt5cQSS7LO' \
--data-raw '{
    "amount": 12345,
    "currency": "USD",
    "confirm": true,
    "capture_method": "automatic",
    "capture_on": "2022-09-10T10:11:12Z",
    "amount_to_capture": 12345,
    "customer_id": "abcd",
    "email": "guest@example.com",
    "name": "John Doe",
    "phone": "999999999",
    "phone_country_code": "+1",
    "description": "Its my first payment request",
    "authentication_type": "no_three_ds",
    "return_url": "https://duck.com",
    "payment_method": "card",
    "payment_method_data": {
        "card": {
            "card_number": "4212345678901237",
            "card_exp_month": "03",
            "card_exp_year": "30",
            "card_holder_name": "John Smith",
            "card_cvc": "739"
        }
    },
    "billing": {
        "address": {
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "city": "San Fransico",
            "state": "California",
            "zip": "94122",
            "country": "US",
            "first_name": "joseph",
            "last_name": "Doe"
        },
        "phone": {
            "number": "9123456789",
            "country_code": "+91"
        }
    },
    "shipping": {
        "address": {
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "city": "San Fransico",
            "state": "California",
            "zip": "94122",
            "country": "US",
            "first_name": "joseph",
            "last_name": "Doe"
        },
        "phone": {
            "number": "9123456789",
            "country_code": "+91"
        }
    },
    "statement_descriptor_name": "joseph",
    "statement_descriptor_suffix": "JS",
    "browser_info": {
        "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36",
        "accept_header": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
        "language": "nl-NL",
        "color_depth": 24,
        "screen_height": 723,
        "screen_width": 1536,
        "time_zone": 0,
        "java_enabled": true,
        "java_script_enabled": true,
        "ip_address": "125.0.0.6"
    }
}'
```

-Response

```
{
    "error": {
        "type": "invalid_request",
        "message": "Blocked due to suspicious activity",
        "code": "IR_16"
    }
}
```

**3. Guest User Card Blocking (Below Threshold)**

-Request

```
curl --location 'http://localhost:8080/payments' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: dev_DXWmMAIEepKhfTAZd13oawyvbN7eNbPHY16nLqlZynQOAOcqdKRWBstt5cQSS7LO' \
--data-raw '{
    "amount": 12345,
    "currency": "USD",
    "confirm": true,
    "capture_method": "automatic",
    "capture_on": "2022-09-10T10:11:12Z",
    "amount_to_capture": 12345,
    
    "email": "guest@example.com",
    "name": "John Doe",
    "phone": "999999999",
    "phone_country_code": "+1",
    "description": "Its my first payment request",
    "authentication_type": "no_three_ds",
    "return_url": "https://duck.com",
    "payment_method": "card",
    "payment_method_data": {
        "card": {
            "card_number": "4212345678901237",
            "card_exp_month": "03",
            "card_exp_year": "30",
            "card_holder_name": "John Smith",
            "card_cvc": "739"
        }
    },
    "billing": {
        "address": {
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "city": "San Fransico",
            "state": "California",
            "zip": "94122",
            "country": "US",
            "first_name": "joseph",
            "last_name": "Doe"
        },
        "phone": {
            "number": "9123456789",
            "country_code": "+91"
        }
    },
    "shipping": {
        "address": {
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "city": "San Fransico",
            "state": "California",
            "zip": "94122",
            "country": "US",
            "first_name": "joseph",
            "last_name": "Doe"
        },
        "phone": {
            "number": "9123456789",
            "country_code": "+91"
        }
    },
    "statement_descriptor_name": "joseph",
    "statement_descriptor_suffix": "JS",
    "browser_info": {
        "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36",
        "accept_header": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
        "language": "nl-NL",
        "color_depth": 24,
        "screen_height": 723,
        "screen_width": 1536,
        "time_zone": 0,
        "java_enabled": true,
        "java_script_enabled": true,
        "ip_address": "125.0.0.6"
    }
}'
```

-Response

```
{
    "payment_id": "pay_6FU271N4pLzdJAxJEr49",
    "merchant_id": "postman_merchant_GHAction_7522c600-57f2-4a82-b4f4-9df401d240ab",
    "status": "failed",
    "amount": 12345,
    "net_amount": 12345,
    "shipping_cost": null,
    "amount_capturable": 0,
    "amount_received": null,
    "connector": "adyen",
    "client_secret": "pay_6FU271N4pLzdJAxJEr49_secret_wvcjDfb9IucJ4G2m9P0O",
    "created": "2025-01-27T07:20:24.599Z",
    "currency": "USD",
    "customer_id": null,
    "customer": {
        "id": null,
        "name": "John Doe",
        "email": "guest@example.com",
        "phone": "999999999",
        "phone_country_code": "+1"
    },
    "description": "Its my first payment request",
    "refunds": null,
    "disputes": null,
    "mandate_id": null,
    "mandate_data": null,
    "setup_future_usage": null,
    "off_session": null,
    "capture_on": null,
    "capture_method": "automatic",
    "payment_method": "card",
    "payment_method_data": {
        "card": {
            "last4": "1237",
            "card_type": null,
            "card_network": null,
            "card_issuer": null,
            "card_issuing_country": null,
            "card_isin": "421234",
            "card_extended_bin": null,
            "card_exp_month": "03",
            "card_exp_year": "30",
            "card_holder_name": "John Smith",
            "payment_checks": null,
            "authentication_data": null
        },
        "billing": null
    },
    "payment_token": null,
    "shipping": {
        "address": {
            "city": "San Fransico",
            "country": "US",
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "zip": "94122",
            "state": "California",
            "first_name": "joseph",
            "last_name": "Doe"
        },
        "phone": {
            "number": "9123456789",
            "country_code": "+91"
        },
        "email": null
    },
    "billing": {
        "address": {
            "city": "San Fransico",
            "country": "US",
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "zip": "94122",
            "state": "California",
            "first_name": "joseph",
            "last_name": "Doe"
        },
        "phone": {
            "number": "9123456789",
            "country_code": "+91"
        },
        "email": null
    },
    "order_details": null,
    "email": null,
    "name": null,
    "phone": null,
    "return_url": "https://duck.com/",
    "authentication_type": "no_three_ds",
    "statement_descriptor_name": "joseph",
    "statement_descriptor_suffix": "JS",
    "next_action": null,
    "cancellation_reason": null,
    "error_code": "24",
    "error_message": "CVC Declined",
    "unified_code": "UE_9000",
    "unified_message": "Something went wrong",
    "payment_experience": null,
    "payment_method_type": null,
    "connector_label": null,
    "business_country": null,
    "business_label": "default",
    "business_sub_label": null,
    "allowed_payment_method_types": null,
    "ephemeral_key": null,
    "manual_retry_allowed": true,
    "connector_transaction_id": "NTQV5DFG3XPPT9V5",
    "frm_message": null,
    "metadata": null,
    "connector_metadata": null,
    "feature_metadata": null,
    "reference_id": null,
    "payment_link": null,
    "profile_id": "pro_6nc1JRTymtljmHmhnTEt",
    "surcharge_details": null,
    "attempt_count": 1,
    "merchant_decision": null,
    "merchant_connector_id": "mca_wpJDRDrWhfV2oZR77bFX",
    "incremental_authorization_allowed": false,
    "authorization_count": null,
    "incremental_authorizations": null,
    "external_authentication_details": null,
    "external_3ds_authentication_attempted": false,
    "expires_on": "2025-01-27T07:35:24.599Z",
    "fingerprint": null,
    "browser_info": {
        "language": "nl-NL",
        "time_zone": 0,
        "ip_address": "125.0.0.6",
        "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36",
        "color_depth": 24,
        "java_enabled": true,
        "screen_width": 1536,
        "accept_header": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
        "screen_height": 723,
        "java_script_enabled": true
    },
    "payment_method_id": null,
    "payment_method_status": null,
    "updated": "2025-01-27T07:20:26.282Z",
    "split_payments": null,
    "frm_metadata": null,
    "merchant_order_reference_id": null,
    "order_tax_amount": null,
    "connector_mandate_id": null
}
```

**4. Guest User Card Blocking (After Threshold & Guest User)**

-Request

```
curl --location 'http://localhost:8080/payments' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: dev_DXWmMAIEepKhfTAZd13oawyvbN7eNbPHY16nLqlZynQOAOcqdKRWBstt5cQSS7LO' \
--data-raw '{
    "amount": 12345,
    "currency": "USD",
    "confirm": true,
    "capture_method": "automatic",
    "capture_on": "2022-09-10T10:11:12Z",
    "amount_to_capture": 12345,
    
    "email": "guest@example.com",
    "name": "John Doe",
    "phone": "999999999",
    "phone_country_code": "+1",
    "description": "Its my first payment request",
    "authentication_type": "no_three_ds",
    "return_url": "https://duck.com",
    "payment_method": "card",
    "payment_method_data": {
        "card": {
            "card_number": "4212345678901237",
            "card_exp_month": "03",
            "card_exp_year": "30",
            "card_holder_name": "John Smith",
            "card_cvc": "739"
        }
    },
    "billing": {
        "address": {
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "city": "San Fransico",
            "state": "California",
            "zip": "94122",
            "country": "US",
            "first_name": "joseph",
            "last_name": "Doe"
        },
        "phone": {
            "number": "9123456789",
            "country_code": "+91"
        }
    },
    "shipping": {
        "address": {
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "city": "San Fransico",
            "state": "California",
            "zip": "94122",
            "country": "US",
            "first_name": "joseph",
            "last_name": "Doe"
        },
        "phone": {
            "number": "9123456789",
            "country_code": "+91"
        }
    },
    "statement_descriptor_name": "joseph",
    "statement_descriptor_suffix": "JS",
    "browser_info": {
        "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36",
        "accept_header": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
        "language": "nl-NL",
        "color_depth": 24,
        "screen_height": 723,
        "screen_width": 1536,
        "time_zone": 0,
        "java_enabled": true,
        "java_script_enabled": true,
        "ip_address": "125.0.0.6"
    }
}'
```

-Response

```
{
    "error": {
        "type": "invalid_request",
        "message": "Blocked due to suspicious activity",
        "code": "IR_16"
    }
}
```

**5. Customer ID Blocking (Below Threshold)**

-Request

```
curl --location 'http://localhost:8080/payments' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: dev_DXWmMAIEepKhfTAZd13oawyvbN7eNbPHY16nLqlZynQOAOcqdKRWBstt5cQSS7LO' \
--data-raw '{
    "amount": 12345,
    "currency": "USD",
    "confirm": true,
    "capture_method": "automatic",
    "capture_on": "2022-09-10T10:11:12Z",
    "amount_to_capture": 12345,
    "customer_id": "abcd",
    "email": "guest@example.com",
    "name": "John Doe",
    "phone": "999999999",
    "phone_country_code": "+1",
    "description": "Its my first payment request",
    "authentication_type": "no_three_ds",
    "return_url": "https://duck.com",
    "payment_method": "card",
    "payment_method_data": {
        "card": {
            "card_number": "4212345678901237",
            "card_exp_month": "03",
            "card_exp_year": "30",
            "card_holder_name": "John Smith",
            "card_cvc": "739"
        }
    },
    "billing": {
        "address": {
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "city": "San Fransico",
            "state": "California",
            "zip": "94122",
            "country": "US",
            "first_name": "joseph",
            "last_name": "Doe"
        },
        "phone": {
            "number": "9123456789",
            "country_code": "+91"
        }
    },
    "shipping": {
        "address": {
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "city": "San Fransico",
            "state": "California",
            "zip": "94122",
            "country": "US",
            "first_name": "joseph",
            "last_name": "Doe"
        },
        "phone": {
            "number": "9123456789",
            "country_code": "+91"
        }
    },
    "statement_descriptor_name": "joseph",
    "statement_descriptor_suffix": "JS",
    "browser_info": {
        "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36",
        "accept_header": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
        "language": "nl-NL",
        "color_depth": 24,
        "screen_height": 723,
        "screen_width": 1536,
        "time_zone": 0,
        "java_enabled": true,
        "java_script_enabled": true,
        "ip_address": "125.0.0.6"
    }
}'
```

-Response

```
{
    "payment_id": "pay_k631dMCrATBssb71COuI",
    "merchant_id": "postman_merchant_GHAction_7522c600-57f2-4a82-b4f4-9df401d240ab",
    "status": "failed",
    "amount": 12345,
    "net_amount": 12345,
    "shipping_cost": null,
    "amount_capturable": 0,
    "amount_received": null,
    "connector": "adyen",
    "client_secret": "pay_k631dMCrATBssb71COuI_secret_P5VvWWn8owaGR9cONsTA",
    "created": "2025-01-27T07:23:44.184Z",
    "currency": "USD",
    "customer_id": "abcd",
    "customer": {
        "id": "abcd",
        "name": "John Doe",
        "email": "guest@example.com",
        "phone": "999999999",
        "phone_country_code": "+1"
    },
    "description": "Its my first payment request",
    "refunds": null,
    "disputes": null,
    "mandate_id": null,
    "mandate_data": null,
    "setup_future_usage": null,
    "off_session": null,
    "capture_on": null,
    "capture_method": "automatic",
    "payment_method": "card",
    "payment_method_data": {
        "card": {
            "last4": "1237",
            "card_type": null,
            "card_network": null,
            "card_issuer": null,
            "card_issuing_country": null,
            "card_isin": "421234",
            "card_extended_bin": null,
            "card_exp_month": "03",
            "card_exp_year": "30",
            "card_holder_name": "John Smith",
            "payment_checks": null,
            "authentication_data": null
        },
        "billing": null
    },
    "payment_token": null,
    "shipping": {
        "address": {
            "city": "San Fransico",
            "country": "US",
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "zip": "94122",
            "state": "California",
            "first_name": "joseph",
            "last_name": "Doe"
        },
        "phone": {
            "number": "9123456789",
            "country_code": "+91"
        },
        "email": null
    },
    "billing": {
        "address": {
            "city": "San Fransico",
            "country": "US",
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "zip": "94122",
            "state": "California",
            "first_name": "joseph",
            "last_name": "Doe"
        },
        "phone": {
            "number": "9123456789",
            "country_code": "+91"
        },
        "email": null
    },
    "order_details": null,
    "email": "guest@example.com",
    "name": "John Doe",
    "phone": "999999999",
    "return_url": "https://duck.com/",
    "authentication_type": "no_three_ds",
    "statement_descriptor_name": "joseph",
    "statement_descriptor_suffix": "JS",
    "next_action": null,
    "cancellation_reason": null,
    "error_code": "24",
    "error_message": "CVC Declined",
    "unified_code": "UE_9000",
    "unified_message": "Something went wrong",
    "payment_experience": null,
    "payment_method_type": null,
    "connector_label": null,
    "business_country": null,
    "business_label": "default",
    "business_sub_label": null,
    "allowed_payment_method_types": null,
    "ephemeral_key": {
        "customer_id": "abcd",
        "created_at": 1737962624,
        "expires": 1737966224,
        "secret": "epk_365d150a51ac498a8be408a0e048fe9a"
    },
    "manual_retry_allowed": true,
    "connector_transaction_id": "BMF7X5SNLCWNM9V5",
    "frm_message": null,
    "metadata": null,
    "connector_metadata": null,
    "feature_metadata": null,
    "reference_id": null,
    "payment_link": null,
    "profile_id": "pro_6nc1JRTymtljmHmhnTEt",
    "surcharge_details": null,
    "attempt_count": 1,
    "merchant_decision": null,
    "merchant_connector_id": "mca_wpJDRDrWhfV2oZR77bFX",
    "incremental_authorization_allowed": false,
    "authorization_count": null,
    "incremental_authorizations": null,
    "external_authentication_details": null,
    "external_3ds_authentication_attempted": false,
    "expires_on": "2025-01-27T07:38:44.184Z",
    "fingerprint": null,
    "browser_info": {
        "language": "nl-NL",
        "time_zone": 0,
        "ip_address": "125.0.0.6",
        "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36",
        "color_depth": 24,
        "java_enabled": true,
        "screen_width": 1536,
        "accept_header": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
        "screen_height": 723,
        "java_script_enabled": true
    },
    "payment_method_id": null,
    "payment_method_status": null,
    "updated": "2025-01-27T07:23:45.746Z",
    "split_payments": null,
    "frm_metadata": null,
    "merchant_order_reference_id": null,
    "order_tax_amount": null,
    "connector_mandate_id": null
}
```

**6. Customer ID Blocking (After Threshold)**

-Request

```
curl --location 'http://localhost:8080/payments' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: dev_DXWmMAIEepKhfTAZd13oawyvbN7eNbPHY16nLqlZynQOAOcqdKRWBstt5cQSS7LO' \
--data-raw '{
    "amount": 12345,
    "currency": "USD",
    "confirm": true,
    "capture_method": "automatic",
    "capture_on": "2022-09-10T10:11:12Z",
    "amount_to_capture": 12345,
    "customer_id": "abcd",
    "email": "guest@example.com",
    "name": "John Doe",
    "phone": "999999999",
    "phone_country_code": "+1",
    "description": "Its my first payment request",
    "authentication_type": "no_three_ds",
    "return_url": "https://duck.com",
    "payment_method": "card",
    "payment_method_data": {
        "card": {
            "card_number": "4212345678901237",
            "card_exp_month": "03",
            "card_exp_year": "30",
            "card_holder_name": "John Smith",
            "card_cvc": "739"
        }
    },
    "billing": {
        "address": {
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "city": "San Fransico",
            "state": "California",
            "zip": "94122",
            "country": "US",
            "first_name": "joseph",
            "last_name": "Doe"
        },
        "phone": {
            "number": "9123456789",
            "country_code": "+91"
        }
    },
    "shipping": {
        "address": {
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "city": "San Fransico",
            "state": "California",
            "zip": "94122",
            "country": "US",
            "first_name": "joseph",
            "last_name": "Doe"
        },
        "phone": {
            "number": "9123456789",
            "country_code": "+91"
        }
    },
    "statement_descriptor_name": "joseph",
    "statement_descriptor_suffix": "JS",
    "browser_info": {
        "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36",
        "accept_header": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
        "language": "nl-NL",
        "color_depth": 24,
        "screen_height": 723,
        "screen_width": 1536,
        "time_zone": 0,
        "java_enabled": true,
        "java_script_enabled": true,
        "ip_address": "125.0.0.6"
    }
}'
```

-Response

```
{
    "error": {
        "type": "invalid_request",
        "message": "Blocked due to suspicious activity",
        "code": "IR_16"
    }
}
```

**Cypress Tests**

![image](https://github.com/user-attachments/assets/101ce207-06c0-4646-b612-6cdf9c3436c0)


## Checklist
<!-- Put an `x` in the boxes that apply -->

- [x] I formatted the code `cargo +nightly fmt --all`
- [x] I addressed lints thrown by `cargo clippy`
- [x] I reviewed the submitted code
- [ ] I added unit tests for my changes where possible
