Bug: [FEATURE] Validate card numbers when accepting payment method information



### Feature Description

As of now, we just pass the card information to the payment processor without performing any form of validation on the provided card number. It'd be great if the card number could have been validated on our end whenever a payment is being created or payment method is being created, instead of invalid card numbers being caught by the payment processor.

It'd be preferable if the card number validation logic is included in a new crate called `cards` which would contain this validation of card numbers and card brand identification logic (taken up on #379). This must check that the card number provided is of correct length, and also handle whitespaces being included in the card number input. Please also include unit tests in your PR.

_For external contributors, clarify any questions you may have, and let us know that you're interested in picking this up. We'll assign this issue to you to reduce duplication of effort on the same task._

### Possible Implementation

For validating card numbers, you can use the [Luhn Algorithm](https://en.wikipedia.org/wiki/Luhn_algorithm). I'm thinking of an API like so (refer to [the newtype pattern](https://rust-unofficial.github.io/patterns/patterns/behavioural/newtype.html)):

```rust
use masking::StrongSecret;

struct CardNumber(StrongSecret<String>);

let card_number = CardNumber::from_str("..."); // You can use the `FromStr` trait for this purpose
```

This would ensure that a `CardNumber` once constructed is always valid and no further validation is necessary. You can also implement `Serialize` and `Deserialize` traits on `CardNumber`.

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

- [X] I checked and didn't find 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?

None
diff --git a/Cargo.lock b/Cargo.lock
index 82cc4015a53..3ef85ac8f6a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -364,6 +364,7 @@ name = "api_models"
 version = "0.1.0"
 dependencies = [
  "actix-web",
+ "cards",
  "common_enums",
  "common_utils",
  "error-stack",
@@ -1154,9 +1155,11 @@ version = "0.1.0"
 dependencies = [
  "common_utils",
  "error-stack",
+ "luhn",
  "masking",
  "serde",
  "serde_json",
+ "thiserror",
  "time 0.3.20",
 ]
 
@@ -1651,6 +1654,12 @@ dependencies = [
  "subtle",
 ]
 
+[[package]]
+name = "digits_iterator"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "af83450b771231745d43edf36dc9b7813ab83be5e8cbea344ccced1a09dfebcd"
+
 [[package]]
 name = "dirs"
 version = "4.0.0"
@@ -2641,6 +2650,15 @@ dependencies = [
  "cfg-if",
 ]
 
+[[package]]
+name = "luhn"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4d10b831402a3b10e018c8bc7f0ec3344a67d0725919cbaf393accb9baf8700b"
+dependencies = [
+ "digits_iterator",
+]
+
 [[package]]
 name = "mach2"
 version = "0.4.1"
@@ -3635,6 +3653,7 @@ dependencies = [
  "bb8",
  "blake3",
  "bytes",
+ "cards",
  "clap",
  "common_utils",
  "config",
@@ -5347,9 +5366,9 @@ checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
 
 [[package]]
 name = "winnow"
-version = "0.4.1"
+version = "0.4.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ae8970b36c66498d8ff1d66685dc86b91b29db0c7739899012f63a63814b4b28"
+checksum = "61de7bac303dc551fe038e2b3cef0f571087a47571ea6e79a87692ac99b99699"
 dependencies = [
  "memchr",
 ]
diff --git a/connector-template/test.rs b/connector-template/test.rs
index ce756121430..9885ccf67c7 100644
--- a/connector-template/test.rs
+++ b/connector-template/test.rs
@@ -302,29 +302,6 @@ async fn should_fail_payment_for_incorrect_card_number() {
     );
 }
 
-// Creates a payment with empty card number.
-#[actix_web::test]
-async fn should_fail_payment_for_empty_card_number() {
-    let response = CONNECTOR
-        .make_payment(
-            Some(types::PaymentsAuthorizeData {
-                payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-                    card_number: Secret::new(String::from("")),
-                    ..utils::CCardType::default().0
-                }),
-                ..utils::PaymentAuthorizeType::default().0
-            }),
-            get_default_payment_info(),
-        )
-        .await
-        .unwrap();
-    let x = response.response.unwrap_err();
-    assert_eq!(
-        x.message,
-        "You passed an empty string for 'payment_method_data[card][number]'.",
-    );
-}
-
 // Creates a payment with incorrect CVC.
 #[actix_web::test]
 async fn should_fail_payment_for_incorrect_cvc() {
diff --git a/connector-template/transformers.rs b/connector-template/transformers.rs
index 7e3caf100e1..3a4f5c5e3ac 100644
--- a/connector-template/transformers.rs
+++ b/connector-template/transformers.rs
@@ -12,7 +12,7 @@ pub struct {{project-name | downcase | pascal_case}}PaymentsRequest {
 #[derive(Default, Debug, Serialize, Eq, PartialEq)]
 pub struct {{project-name | downcase | pascal_case}}Card {
     name: Secret<String>,
-    number: Secret<String, common_utils::pii::CardNumber>,
+    number: cards::CardNumber,
     expiry_month: Secret<String>,
     expiry_year: Secret<String>,
     cvc: Secret<String>,
diff --git a/crates/api_models/Cargo.toml b/crates/api_models/Cargo.toml
index f1824e41be7..c11e9cebde6 100644
--- a/crates/api_models/Cargo.toml
+++ b/crates/api_models/Cargo.toml
@@ -33,3 +33,4 @@ common_utils = { version = "0.1.0", path = "../common_utils" }
 masking = { version = "0.1.0", path = "../masking" }
 router_derive = { version = "0.1.0", path = "../router_derive" }
 common_enums = {path = "../common_enums"}
+cards = { version = "0.1.0", path = "../cards" }
diff --git a/crates/api_models/src/payment_methods.rs b/crates/api_models/src/payment_methods.rs
index 91b1affb1dd..a171b08d6e7 100644
--- a/crates/api_models/src/payment_methods.rs
+++ b/crates/api_models/src/payment_methods.rs
@@ -1,3 +1,4 @@
+use cards::CardNumber;
 use common_utils::pii;
 use serde::de;
 use utoipa::ToSchema;
@@ -72,7 +73,7 @@ pub struct PaymentMethodUpdate {
 pub struct CardDetail {
     /// Card Number
     #[schema(value_type = String,example = "4111111145551142")]
-    pub card_number: masking::Secret<String, pii::CardNumber>,
+    pub card_number: CardNumber,
 
     /// Card Expiry Month
     #[schema(value_type = String,example = "10")]
@@ -142,7 +143,7 @@ pub struct CardDetailFromLocker {
     pub last4_digits: Option<String>,
     #[serde(skip)]
     #[schema(value_type=Option<String>)]
-    pub card_number: Option<masking::Secret<String, pii::CardNumber>>,
+    pub card_number: Option<CardNumber>,
 
     #[schema(value_type=Option<String>)]
     pub expiry_month: Option<masking::Secret<String>>,
diff --git a/crates/api_models/src/payments.rs b/crates/api_models/src/payments.rs
index b2834c078ea..57dd2b00763 100644
--- a/crates/api_models/src/payments.rs
+++ b/crates/api_models/src/payments.rs
@@ -1,5 +1,6 @@
 use std::num::NonZeroI64;
 
+use cards::CardNumber;
 use common_utils::{pii, pii::Email};
 use masking::{PeekInterface, Secret};
 use router_derive::Setter;
@@ -415,7 +416,7 @@ pub struct OnlineMandate {
 pub struct Card {
     /// The card number
     #[schema(value_type = String, example = "4242424242424242")]
-    pub card_number: Secret<String, pii::CardNumber>,
+    pub card_number: CardNumber,
 
     /// The card's expiry month
     #[schema(value_type = String, example = "24")]
@@ -580,7 +581,7 @@ pub enum BankRedirectData {
     BancontactCard {
         /// The card number
         #[schema(value_type = String, example = "4242424242424242")]
-        card_number: Secret<String, pii::CardNumber>,
+        card_number: CardNumber,
         /// The card's expiry month
         #[schema(value_type = String, example = "24")]
         card_exp_month: Secret<String>,
diff --git a/crates/cards/Cargo.toml b/crates/cards/Cargo.toml
index 7971726c9a6..4b05bc4948a 100644
--- a/crates/cards/Cargo.toml
+++ b/crates/cards/Cargo.toml
@@ -12,10 +12,12 @@ default = ["serde"]
 time = { version = "0.3.20" }
 error-stack = "0.3.1"
 serde = { version = "1", features = ["derive"], optional = true }
+thiserror = "1.0.40"
+luhn = "1.0.1"
 
 # First Party crates
 masking = { version = "0.1.0", path = "../masking" }
 common_utils = { version = "0.1.0", path = "../common_utils" }
 
 [dev-dependencies]
-serde_json = "1.0.94"
\ No newline at end of file
+serde_json = "1.0.94"
diff --git a/crates/cards/src/lib.rs b/crates/cards/src/lib.rs
index 00bd0578c3d..d8aedc36e1a 100644
--- a/crates/cards/src/lib.rs
+++ b/crates/cards/src/lib.rs
@@ -1,3 +1,4 @@
+pub mod validate;
 use std::ops::Deref;
 
 use common_utils::{date_time, errors};
@@ -9,6 +10,8 @@ use serde::{
 };
 use time::{util::days_in_year_month, Date, Duration, PrimitiveDateTime, Time};
 
+pub use crate::validate::{CCValError, CardNumber, CardNumberStrategy};
+
 #[derive(Serialize)]
 pub struct CardSecurityCode(StrongSecret<u16>);
 
diff --git a/crates/cards/src/validate.rs b/crates/cards/src/validate.rs
new file mode 100644
index 00000000000..6fcb5e11807
--- /dev/null
+++ b/crates/cards/src/validate.rs
@@ -0,0 +1,143 @@
+use std::{fmt, ops::Deref, str::FromStr};
+
+use masking::{Strategy, StrongSecret, WithType};
+use serde::{Deserialize, Deserializer, Serialize};
+use thiserror::Error;
+
+#[derive(Debug, Deserialize, Serialize, Error)]
+#[error("not a valid credit card number")]
+pub struct CCValError;
+
+impl From<core::convert::Infallible> for CCValError {
+    fn from(_: core::convert::Infallible) -> Self {
+        Self
+    }
+}
+
+/// Card number
+#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize)]
+pub struct CardNumber(StrongSecret<String, CardNumberStrategy>);
+
+impl FromStr for CardNumber {
+    type Err = CCValError;
+
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        match luhn::valid(s) {
+            true => {
+                let cc_no_whitespace: String = s.split_whitespace().collect();
+                Ok(Self(StrongSecret::from_str(&cc_no_whitespace)?))
+            }
+            false => Err(CCValError),
+        }
+    }
+}
+
+impl TryFrom<String> for CardNumber {
+    type Error = CCValError;
+
+    fn try_from(value: String) -> Result<Self, Self::Error> {
+        Self::from_str(&value)
+    }
+}
+
+impl Deref for CardNumber {
+    type Target = StrongSecret<String, CardNumberStrategy>;
+
+    fn deref(&self) -> &StrongSecret<String, CardNumberStrategy> {
+        &self.0
+    }
+}
+
+impl<'de> Deserialize<'de> for CardNumber {
+    fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
+        let s = String::deserialize(d)?;
+        Self::from_str(&s).map_err(serde::de::Error::custom)
+    }
+}
+
+pub struct CardNumberStrategy;
+
+impl<T> Strategy<T> for CardNumberStrategy
+where
+    T: AsRef<str>,
+{
+    fn fmt(val: &T, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let val_str: &str = val.as_ref();
+
+        if val_str.len() < 15 || val_str.len() > 19 {
+            return WithType::fmt(val, f);
+        }
+
+        write!(f, "{}{}", &val_str[..6], "*".repeat(val_str.len() - 6))
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    #![allow(clippy::unwrap_used)]
+
+    use masking::Secret;
+
+    use super::*;
+
+    #[test]
+    fn valid_card_number() {
+        let s = "371449635398431";
+        assert_eq!(
+            CardNumber::from_str(s).unwrap(),
+            CardNumber(StrongSecret::from_str(s).unwrap())
+        );
+    }
+
+    #[test]
+    fn invalid_card_number() {
+        let s = "371446431";
+        assert_eq!(
+            CardNumber::from_str(s).unwrap_err().to_string(),
+            "not a valid credit card number".to_string()
+        );
+    }
+
+    #[test]
+    fn card_number_no_whitespace() {
+        let s = "3714    4963  5398 431";
+        assert_eq!(
+            CardNumber::from_str(s).unwrap().to_string(),
+            "371449*********"
+        );
+    }
+
+    #[test]
+    fn test_valid_card_number_masking() {
+        let secret: Secret<String, CardNumberStrategy> =
+            Secret::new("1234567890987654".to_string());
+        assert_eq!("123456**********", format!("{secret:?}"));
+    }
+
+    #[test]
+    fn test_invalid_card_number_masking() {
+        let secret: Secret<String, CardNumberStrategy> = Secret::new("1234567890".to_string());
+        assert_eq!("*** alloc::string::String ***", format!("{secret:?}"));
+    }
+
+    #[test]
+    fn test_valid_card_number_strong_secret_masking() {
+        let card_number = CardNumber::from_str("3714 4963 5398 431").unwrap();
+        let secret = &(*card_number);
+        assert_eq!("371449*********", format!("{secret:?}"));
+    }
+
+    #[test]
+    fn test_valid_card_number_deserialization() {
+        let card_number = serde_json::from_str::<CardNumber>(r#""3714 4963 5398 431""#).unwrap();
+        let secret = card_number.to_string();
+        assert_eq!(r#""371449*********""#, format!("{secret:?}"));
+    }
+
+    #[test]
+    fn test_invalid_card_number_deserialization() {
+        let card_number = serde_json::from_str::<CardNumber>(r#""1234 5678""#);
+        let error_msg = card_number.unwrap_err().to_string();
+        assert_eq!(error_msg, "not a valid credit card number".to_string());
+    }
+}
diff --git a/crates/common_utils/src/pii.rs b/crates/common_utils/src/pii.rs
index d4c45716593..24d72f2b37f 100644
--- a/crates/common_utils/src/pii.rs
+++ b/crates/common_utils/src/pii.rs
@@ -21,25 +21,6 @@ pub const REDACTED: &str = "Redacted";
 /// Type alias for serde_json value which has Secret Information
 pub type SecretSerdeValue = Secret<serde_json::Value>;
 
-/// Card number
-#[derive(Debug)]
-pub struct CardNumber;
-
-impl<T> Strategy<T> for CardNumber
-where
-    T: AsRef<str>,
-{
-    fn fmt(val: &T, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let val_str: &str = val.as_ref();
-
-        if val_str.len() < 15 || val_str.len() > 19 {
-            return WithType::fmt(val, f);
-        }
-
-        write!(f, "{}{}", &val_str[..6], "*".repeat(val_str.len() - 6))
-    }
-}
-
 /*
 /// Phone number
 #[derive(Debug)]
@@ -226,21 +207,9 @@ mod pii_masking_strategy_tests {
 
     use masking::{ExposeInterface, Secret};
 
-    use super::{CardNumber, ClientSecret, Email, IpAddress};
+    use super::{ClientSecret, Email, IpAddress};
     use crate::pii::{EmailStrategy, REDACTED};
 
-    #[test]
-    fn test_valid_card_number_masking() {
-        let secret: Secret<String, CardNumber> = Secret::new("1234567890987654".to_string());
-        assert_eq!("123456**********", format!("{secret:?}"));
-    }
-
-    #[test]
-    fn test_invalid_card_number_masking() {
-        let secret: Secret<String, CardNumber> = Secret::new("1234567890".to_string());
-        assert_eq!("*** alloc::string::String ***", format!("{secret:?}"));
-    }
-
     /*
     #[test]
     fn test_valid_phone_number_masking() {
diff --git a/crates/router/Cargo.toml b/crates/router/Cargo.toml
index e4a9a25efcf..88fcf92d38b 100644
--- a/crates/router/Cargo.toml
+++ b/crates/router/Cargo.toml
@@ -84,6 +84,7 @@ uuid = { version = "1.3.1", features = ["serde", "v4"] }
 # First party crates
 api_models = { version = "0.1.0", path = "../api_models", features = ["errors"] }
 common_utils = { version = "0.1.0", path = "../common_utils", features = ["signals", "async_ext"] }
+cards = { version = "0.1.0", path = "../cards" }
 external_services = { version = "0.1.0", path = "../external_services" }
 masking = { version = "0.1.0", path = "../masking" }
 redis_interface = { version = "0.1.0", path = "../redis_interface" }
diff --git a/crates/router/src/compatibility/stripe/payment_intents/types.rs b/crates/router/src/compatibility/stripe/payment_intents/types.rs
index eaaf82b1f0f..8c2796b4345 100644
--- a/crates/router/src/compatibility/stripe/payment_intents/types.rs
+++ b/crates/router/src/compatibility/stripe/payment_intents/types.rs
@@ -39,7 +39,7 @@ impl From<StripeBillingDetails> for payments::Address {
 
 #[derive(Default, Serialize, PartialEq, Eq, Deserialize, Clone)]
 pub struct StripeCard {
-    pub number: pii::Secret<String, pii::CardNumber>,
+    pub number: cards::CardNumber,
     pub exp_month: pii::Secret<String>,
     pub exp_year: pii::Secret<String>,
     pub cvc: pii::Secret<String>,
diff --git a/crates/router/src/compatibility/stripe/setup_intents/types.rs b/crates/router/src/compatibility/stripe/setup_intents/types.rs
index 645729d083c..1bc7f3fb85f 100644
--- a/crates/router/src/compatibility/stripe/setup_intents/types.rs
+++ b/crates/router/src/compatibility/stripe/setup_intents/types.rs
@@ -40,7 +40,7 @@ impl From<StripeBillingDetails> for payments::Address {
 
 #[derive(Default, Serialize, PartialEq, Eq, Deserialize, Clone)]
 pub struct StripeCard {
-    pub number: pii::Secret<String, pii::CardNumber>,
+    pub number: cards::CardNumber,
     pub exp_month: pii::Secret<String>,
     pub exp_year: pii::Secret<String>,
     pub cvc: pii::Secret<String>,
diff --git a/crates/router/src/connector/aci/transformers.rs b/crates/router/src/connector/aci/transformers.rs
index acb17849299..fad1ffed0dc 100644
--- a/crates/router/src/connector/aci/transformers.rs
+++ b/crates/router/src/connector/aci/transformers.rs
@@ -88,7 +88,7 @@ pub enum PaymentBrand {
 #[derive(Debug, Clone, Eq, PartialEq, Serialize)]
 pub struct CardDetails {
     #[serde(rename = "card.number")]
-    pub card_number: Secret<String, common_utils::pii::CardNumber>,
+    pub card_number: cards::CardNumber,
     #[serde(rename = "card.holder")]
     pub card_holder: Secret<String>,
     #[serde(rename = "card.expiryMonth")]
diff --git a/crates/router/src/connector/adyen/transformers.rs b/crates/router/src/connector/adyen/transformers.rs
index 0d07eb72779..192d9c85d14 100644
--- a/crates/router/src/connector/adyen/transformers.rs
+++ b/crates/router/src/connector/adyen/transformers.rs
@@ -1,6 +1,7 @@
 use api_models::{
     enums::DisputeStage, payments::MandateReferenceId, webhooks::IncomingWebhookEvent,
 };
+use cards::CardNumber;
 use masking::PeekInterface;
 use reqwest::Url;
 use serde::{Deserialize, Serialize};
@@ -12,7 +13,7 @@ use crate::{
     },
     consts,
     core::errors,
-    pii::{self, Email, Secret},
+    pii::{Email, Secret},
     services,
     types::{
         self,
@@ -291,7 +292,7 @@ pub struct BancontactCardData {
     #[serde(rename = "type")]
     payment_type: PaymentType,
     brand: String,
-    number: Secret<String, pii::CardNumber>,
+    number: CardNumber,
     expiry_month: Secret<String>,
     expiry_year: Secret<String>,
     holder_name: Secret<String>,
@@ -511,7 +512,7 @@ pub struct AdyenMandate {
 pub struct AdyenCard {
     #[serde(rename = "type")]
     payment_type: PaymentType,
-    number: Secret<String, pii::CardNumber>,
+    number: CardNumber,
     expiry_month: Secret<String>,
     expiry_year: Secret<String>,
     cvc: Option<Secret<String>>,
diff --git a/crates/router/src/connector/airwallex/transformers.rs b/crates/router/src/connector/airwallex/transformers.rs
index 86831e592c7..ca3df4aff9a 100644
--- a/crates/router/src/connector/airwallex/transformers.rs
+++ b/crates/router/src/connector/airwallex/transformers.rs
@@ -6,7 +6,7 @@ use uuid::Uuid;
 use crate::{
     connector::utils,
     core::errors,
-    pii::{self, Secret},
+    pii::Secret,
     services,
     types::{self, api, storage::enums},
 };
@@ -57,7 +57,7 @@ pub struct AirwallexCard {
 pub struct AirwallexCardDetails {
     expiry_month: Secret<String>,
     expiry_year: Secret<String>,
-    number: Secret<String, pii::CardNumber>,
+    number: cards::CardNumber,
     cvc: Secret<String>,
 }
 
@@ -92,9 +92,7 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for AirwallexPaymentsRequest {
                     }));
                 Ok(AirwallexPaymentMethod::Card(AirwallexCard {
                     card: AirwallexCardDetails {
-                        number: ccard
-                            .card_number
-                            .map(|card| card.split_whitespace().collect()),
+                        number: ccard.card_number,
                         expiry_month: ccard.card_exp_month.clone(),
                         expiry_year: ccard.card_exp_year.clone(),
                         cvc: ccard.card_cvc,
diff --git a/crates/router/src/connector/authorizedotnet/transformers.rs b/crates/router/src/connector/authorizedotnet/transformers.rs
index 0c93ba198fe..1c3ec89156d 100644
--- a/crates/router/src/connector/authorizedotnet/transformers.rs
+++ b/crates/router/src/connector/authorizedotnet/transformers.rs
@@ -43,7 +43,7 @@ impl TryFrom<&types::ConnectorAuthType> for MerchantAuthentication {
 #[derive(Serialize, Deserialize, PartialEq, Debug)]
 #[serde(rename_all = "camelCase")]
 struct CreditCardDetails {
-    card_number: masking::Secret<String, common_utils::pii::CardNumber>,
+    card_number: masking::StrongSecret<String, cards::CardNumberStrategy>,
     expiration_date: masking::Secret<String>,
     #[serde(skip_serializing_if = "Option::is_none")]
     card_code: Option<masking::Secret<String>>,
@@ -97,7 +97,7 @@ fn get_pm_and_subsequent_auth_detail(
             match item.request.payment_method_data {
                 api::PaymentMethodData::Card(ref ccard) => {
                     let payment_details = PaymentDetails::CreditCard(CreditCardDetails {
-                        card_number: ccard.card_number.clone(),
+                        card_number: (*ccard.card_number).clone(),
                         expiration_date: ccard.get_expiry_date_as_yyyymm("-"),
                         card_code: None,
                     });
@@ -115,7 +115,7 @@ fn get_pm_and_subsequent_auth_detail(
             api::PaymentMethodData::Card(ref ccard) => {
                 Ok((
                     PaymentDetails::CreditCard(CreditCardDetails {
-                        card_number: ccard.card_number.clone(),
+                        card_number: (*ccard.card_number).clone(),
                         // expiration_date: format!("{expiry_year}-{expiry_month}").into(),
                         expiration_date: ccard.get_expiry_date_as_yyyymm("-"),
                         card_code: Some(ccard.card_cvc.clone()),
diff --git a/crates/router/src/connector/bambora/transformers.rs b/crates/router/src/connector/bambora/transformers.rs
index 443e703e662..14ce731627e 100644
--- a/crates/router/src/connector/bambora/transformers.rs
+++ b/crates/router/src/connector/bambora/transformers.rs
@@ -15,7 +15,7 @@ use crate::{
 #[derive(Default, Debug, Serialize, Eq, PartialEq)]
 pub struct BamboraCard {
     name: Secret<String>,
-    number: Secret<String, common_utils::pii::CardNumber>,
+    number: cards::CardNumber,
     expiry_month: Secret<String>,
     expiry_year: Secret<String>,
     cvd: Secret<String>,
diff --git a/crates/router/src/connector/bluesnap/transformers.rs b/crates/router/src/connector/bluesnap/transformers.rs
index aef423be6e2..dd538e929aa 100644
--- a/crates/router/src/connector/bluesnap/transformers.rs
+++ b/crates/router/src/connector/bluesnap/transformers.rs
@@ -10,7 +10,7 @@ use crate::{
     connector::utils,
     consts,
     core::errors,
-    pii::{self, Secret},
+    pii::Secret,
     types::{self, api, storage::enums, transformers::ForeignTryFrom},
     utils::Encode,
 };
@@ -42,7 +42,7 @@ pub enum PaymentMethodDetails {
 #[derive(Default, Debug, Serialize, Eq, PartialEq)]
 #[serde(rename_all = "camelCase")]
 pub struct Card {
-    card_number: Secret<String, pii::CardNumber>,
+    card_number: cards::CardNumber,
     expiration_month: Secret<String>,
     expiration_year: Secret<String>,
     security_code: Secret<String>,
diff --git a/crates/router/src/connector/braintree/transformers.rs b/crates/router/src/connector/braintree/transformers.rs
index dd9c03dafea..b5e81097ca1 100644
--- a/crates/router/src/connector/braintree/transformers.rs
+++ b/crates/router/src/connector/braintree/transformers.rs
@@ -78,7 +78,7 @@ pub struct Card {
 #[derive(Default, Debug, Serialize, Eq, PartialEq)]
 #[serde(rename_all = "camelCase")]
 pub struct CardDetails {
-    number: Secret<String, common_utils::pii::CardNumber>,
+    number: cards::CardNumber,
     expiration_month: Secret<String>,
     expiration_year: Secret<String>,
     cvv: Secret<String>,
diff --git a/crates/router/src/connector/checkout/transformers.rs b/crates/router/src/connector/checkout/transformers.rs
index 2e9a8f2b825..98c24dcc3c8 100644
--- a/crates/router/src/connector/checkout/transformers.rs
+++ b/crates/router/src/connector/checkout/transformers.rs
@@ -97,7 +97,7 @@ impl<F, T>
 pub struct CardSource {
     #[serde(rename = "type")]
     pub source_type: CheckoutSourceTypes,
-    pub number: pii::Secret<String, pii::CardNumber>,
+    pub number: cards::CardNumber,
     pub expiry_month: pii::Secret<String>,
     pub expiry_year: pii::Secret<String>,
     pub cvv: pii::Secret<String>,
diff --git a/crates/router/src/connector/cybersource/transformers.rs b/crates/router/src/connector/cybersource/transformers.rs
index a72d00ab41d..3ca45f84c27 100644
--- a/crates/router/src/connector/cybersource/transformers.rs
+++ b/crates/router/src/connector/cybersource/transformers.rs
@@ -45,7 +45,7 @@ pub struct PaymentInformation {
 #[derive(Default, Debug, Serialize, Eq, PartialEq)]
 #[serde(rename_all = "camelCase")]
 pub struct Card {
-    number: Secret<String, pii::CardNumber>,
+    number: cards::CardNumber,
     expiration_month: Secret<String>,
     expiration_year: Secret<String>,
     security_code: Secret<String>,
diff --git a/crates/router/src/connector/dlocal/transformers.rs b/crates/router/src/connector/dlocal/transformers.rs
index f33b0b43c29..8e084635f09 100644
--- a/crates/router/src/connector/dlocal/transformers.rs
+++ b/crates/router/src/connector/dlocal/transformers.rs
@@ -1,5 +1,5 @@
 use api_models::payments::AddressDetails;
-use common_utils::pii::{self, Email};
+use common_utils::pii::Email;
 use error_stack::ResultExt;
 use masking::{PeekInterface, Secret};
 use serde::{Deserialize, Serialize};
@@ -22,7 +22,7 @@ pub struct Payer {
 #[derive(Debug, Default, Eq, Clone, PartialEq, Serialize, Deserialize)]
 pub struct Card {
     pub holder_name: Secret<String>,
-    pub number: Secret<String, pii::CardNumber>,
+    pub number: cards::CardNumber,
     pub cvv: Secret<String>,
     pub expiration_month: Secret<String>,
     pub expiration_year: Secret<String>,
diff --git a/crates/router/src/connector/dummyconnector/transformers.rs b/crates/router/src/connector/dummyconnector/transformers.rs
index e55664a6aaa..88404290208 100644
--- a/crates/router/src/connector/dummyconnector/transformers.rs
+++ b/crates/router/src/connector/dummyconnector/transformers.rs
@@ -17,7 +17,7 @@ pub struct DummyConnectorPaymentsRequest {
 #[derive(Default, Debug, Serialize, Eq, PartialEq)]
 pub struct DummyConnectorCard {
     name: Secret<String>,
-    number: Secret<String, common_utils::pii::CardNumber>,
+    number: cards::CardNumber,
     expiry_month: Secret<String>,
     expiry_year: Secret<String>,
     cvc: Secret<String>,
diff --git a/crates/router/src/connector/fiserv/transformers.rs b/crates/router/src/connector/fiserv/transformers.rs
index b52f5d259b3..a02bf4cc4ee 100644
--- a/crates/router/src/connector/fiserv/transformers.rs
+++ b/crates/router/src/connector/fiserv/transformers.rs
@@ -5,7 +5,7 @@ use serde::{Deserialize, Serialize};
 use crate::{
     connector::utils::{self, PaymentsCancelRequestData, PaymentsSyncRequestData, RouterData},
     core::errors,
-    pii::{self, Secret},
+    pii::Secret,
     types::{self, api, storage::enums},
 };
 
@@ -36,7 +36,7 @@ pub enum Source {
 #[derive(Default, Debug, Serialize, Eq, PartialEq)]
 #[serde(rename_all = "camelCase")]
 pub struct CardData {
-    card_data: Secret<String, pii::CardNumber>,
+    card_data: cards::CardNumber,
     expiration_month: Secret<String>,
     expiration_year: Secret<String>,
     security_code: Secret<String>,
@@ -134,10 +134,7 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for FiservPaymentsRequest {
         let source = match item.request.payment_method_data.clone() {
             api::PaymentMethodData::Card(ref ccard) => {
                 let card = CardData {
-                    card_data: ccard
-                        .card_number
-                        .clone()
-                        .map(|card| card.split_whitespace().collect()),
+                    card_data: ccard.card_number.clone(),
                     expiration_month: ccard.card_exp_month.clone(),
                     expiration_year: ccard.card_exp_year.clone(),
                     security_code: ccard.card_cvc.clone(),
diff --git a/crates/router/src/connector/forte/transformers.rs b/crates/router/src/connector/forte/transformers.rs
index a806d2af94c..415aae14df5 100644
--- a/crates/router/src/connector/forte/transformers.rs
+++ b/crates/router/src/connector/forte/transformers.rs
@@ -1,3 +1,4 @@
+use cards::CardNumber;
 use masking::Secret;
 use serde::{Deserialize, Serialize};
 
@@ -6,7 +7,6 @@ use crate::{
         self, AddressDetailsData, CardData, PaymentsAuthorizeRequestData, RouterData,
     },
     core::errors,
-    pii::{self},
     types::{self, api, storage::enums, transformers::ForeignFrom},
 };
 
@@ -27,7 +27,7 @@ pub struct BillingAddress {
 pub struct Card {
     card_type: ForteCardType,
     name_on_card: Secret<String>,
-    account_number: Secret<String, pii::CardNumber>,
+    account_number: CardNumber,
     expire_month: Secret<String>,
     expire_year: Secret<String>,
     card_verification_value: Secret<String>,
diff --git a/crates/router/src/connector/globalpay/requests.rs b/crates/router/src/connector/globalpay/requests.rs
index 46ca9c72558..2f06c121378 100644
--- a/crates/router/src/connector/globalpay/requests.rs
+++ b/crates/router/src/connector/globalpay/requests.rs
@@ -1,4 +1,3 @@
-use common_utils::pii;
 use masking::Secret;
 use serde::{Deserialize, Serialize};
 
@@ -339,7 +338,7 @@ pub struct Card {
     /// Indicates whether the card is a debit or credit card.
     pub funding: Option<Funding>,
     /// The the card account number used to authorize the transaction. Also known as PAN.
-    pub number: Secret<String, pii::CardNumber>,
+    pub number: cards::CardNumber,
     /// Contains the pin block info, relating to the pin code the Payer entered.
     pub pin_block: Option<String>,
     /// The full card tag data for an EMV/chip card transaction.
diff --git a/crates/router/src/connector/multisafepay/transformers.rs b/crates/router/src/connector/multisafepay/transformers.rs
index 7f60c70c2f5..0b060a5c46f 100644
--- a/crates/router/src/connector/multisafepay/transformers.rs
+++ b/crates/router/src/connector/multisafepay/transformers.rs
@@ -6,7 +6,7 @@ use url::Url;
 use crate::{
     connector::utils::{self, AddressDetailsData, CardData, RouterData},
     core::errors,
-    pii::{self, Secret},
+    pii::Secret,
     services,
     types::{self, api, storage::enums},
 };
@@ -114,7 +114,7 @@ pub struct Customer {
 #[serde_with::skip_serializing_none]
 #[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
 pub struct GatewayInfo {
-    pub card_number: Option<Secret<String, pii::CardNumber>>,
+    pub card_number: Option<cards::CardNumber>,
     pub card_holder_name: Option<Secret<String>>,
     pub card_expiry_date: Option<i32>,
     pub card_cvc: Option<Secret<String>>,
diff --git a/crates/router/src/connector/nexinets/transformers.rs b/crates/router/src/connector/nexinets/transformers.rs
index 05655430a65..13a20603552 100644
--- a/crates/router/src/connector/nexinets/transformers.rs
+++ b/crates/router/src/connector/nexinets/transformers.rs
@@ -1,5 +1,6 @@
 use api_models::payments::PaymentMethodData;
 use base64::Engine;
+use cards::CardNumber;
 use common_utils::errors::CustomResult;
 use error_stack::{IntoReport, ResultExt};
 use masking::Secret;
@@ -75,7 +76,7 @@ pub enum CardDataDetails {
 #[derive(Debug, Serialize)]
 #[serde(rename_all = "camelCase")]
 pub struct CardDetails {
-    card_number: Secret<String, common_utils::pii::CardNumber>,
+    card_number: CardNumber,
     expiry_month: Secret<String>,
     expiry_year: Secret<String>,
     verification: Secret<String>,
diff --git a/crates/router/src/connector/nuvei/transformers.rs b/crates/router/src/connector/nuvei/transformers.rs
index 1653ecdc849..22541bbcbef 100644
--- a/crates/router/src/connector/nuvei/transformers.rs
+++ b/crates/router/src/connector/nuvei/transformers.rs
@@ -193,7 +193,7 @@ pub struct BillingAddress {
 #[derive(Debug, Clone, Default, Serialize, Deserialize)]
 #[serde(rename_all = "camelCase")]
 pub struct Card {
-    pub card_number: Option<Secret<String, common_utils::pii::CardNumber>>,
+    pub card_number: Option<cards::CardNumber>,
     pub card_holder_name: Option<Secret<String>>,
     pub expiration_month: Option<Secret<String>>,
     pub expiration_year: Option<Secret<String>>,
diff --git a/crates/router/src/connector/payeezy/transformers.rs b/crates/router/src/connector/payeezy/transformers.rs
index 29c15b56722..5c01be19ae5 100644
--- a/crates/router/src/connector/payeezy/transformers.rs
+++ b/crates/router/src/connector/payeezy/transformers.rs
@@ -1,3 +1,4 @@
+use cards::CardNumber;
 use common_utils::ext_traits::Encode;
 use error_stack::ResultExt;
 use masking::Secret;
@@ -6,7 +7,6 @@ use serde::{Deserialize, Serialize};
 use crate::{
     connector::utils::{self, CardData},
     core::errors,
-    pii::{self},
     types::{self, api, storage::enums, transformers::ForeignFrom},
 };
 
@@ -15,7 +15,7 @@ pub struct PayeezyCard {
     #[serde(rename = "type")]
     pub card_type: PayeezyCardType,
     pub cardholder_name: Secret<String>,
-    pub card_number: Secret<String, pii::CardNumber>,
+    pub card_number: CardNumber,
     pub exp_date: Secret<String>,
     pub cvv: Secret<String>,
 }
diff --git a/crates/router/src/connector/paypal/transformers.rs b/crates/router/src/connector/paypal/transformers.rs
index c1115a5243a..75ae0598552 100644
--- a/crates/router/src/connector/paypal/transformers.rs
+++ b/crates/router/src/connector/paypal/transformers.rs
@@ -9,7 +9,7 @@ use crate::{
         PaymentsAuthorizeRequestData,
     },
     core::errors,
-    pii, services,
+    services,
     types::{self, api, storage::enums as storage_enums, transformers::ForeignFrom},
 };
 
@@ -44,7 +44,7 @@ pub struct CardRequest {
     billing_address: Option<Address>,
     expiry: Option<Secret<String>>,
     name: Secret<String>,
-    number: Option<Secret<String, pii::CardNumber>>,
+    number: Option<cards::CardNumber>,
     security_code: Option<Secret<String>>,
 }
 
diff --git a/crates/router/src/connector/payu/transformers.rs b/crates/router/src/connector/payu/transformers.rs
index 7e7cc8abf40..d141a01843d 100644
--- a/crates/router/src/connector/payu/transformers.rs
+++ b/crates/router/src/connector/payu/transformers.rs
@@ -6,7 +6,7 @@ use crate::{
     connector::utils::AccessTokenRequestInfo,
     consts,
     core::errors,
-    pii::{self, Secret},
+    pii::Secret,
     types::{self, api, storage::enums},
 };
 
@@ -42,7 +42,7 @@ pub enum PayuPaymentMethodData {
 pub enum PayuCard {
     #[serde(rename_all = "camelCase")]
     Card {
-        number: Secret<String, pii::CardNumber>,
+        number: cards::CardNumber,
         expiration_month: Secret<String>,
         expiration_year: Secret<String>,
         cvv: Secret<String>,
diff --git a/crates/router/src/connector/rapyd/transformers.rs b/crates/router/src/connector/rapyd/transformers.rs
index 63a00755155..f112456ae59 100644
--- a/crates/router/src/connector/rapyd/transformers.rs
+++ b/crates/router/src/connector/rapyd/transformers.rs
@@ -5,7 +5,7 @@ use url::Url;
 use crate::{
     consts,
     core::errors,
-    pii::{self, Secret},
+    pii::Secret,
     services,
     types::{self, api, storage::enums, transformers::ForeignFrom},
     utils::OptionExt,
@@ -37,7 +37,7 @@ pub struct PaymentMethod {
 
 #[derive(Default, Debug, Serialize)]
 pub struct PaymentFields {
-    pub number: Secret<String, pii::CardNumber>,
+    pub number: cards::CardNumber,
     pub expiration_month: Secret<String>,
     pub expiration_year: Secret<String>,
     pub name: Secret<String>,
diff --git a/crates/router/src/connector/shift4/transformers.rs b/crates/router/src/connector/shift4/transformers.rs
index 6931a91d1ea..75c3ca78875 100644
--- a/crates/router/src/connector/shift4/transformers.rs
+++ b/crates/router/src/connector/shift4/transformers.rs
@@ -1,4 +1,5 @@
 use api_models::payments;
+use cards::CardNumber;
 use common_utils::pii::SecretSerdeValue;
 use error_stack::{IntoReport, ResultExt};
 use masking::Secret;
@@ -30,7 +31,7 @@ pub struct Shift43DSRequest {
     amount: String,
     currency: String,
     #[serde(rename = "card[number]")]
-    pub card_number: Secret<String, common_utils::pii::CardNumber>,
+    pub card_number: CardNumber,
     #[serde(rename = "card[expMonth]")]
     pub card_exp_month: Secret<String>,
     #[serde(rename = "card[expYear]")]
@@ -96,7 +97,7 @@ pub struct DeviceData;
 #[derive(Default, Debug, Serialize, Eq, PartialEq)]
 #[serde(rename_all = "camelCase")]
 pub struct Card {
-    pub number: Secret<String, common_utils::pii::CardNumber>,
+    pub number: CardNumber,
     pub exp_month: Secret<String>,
     pub exp_year: Secret<String>,
     pub cardholder_name: Secret<String>,
diff --git a/crates/router/src/connector/stripe/transformers.rs b/crates/router/src/connector/stripe/transformers.rs
index 62e88e918e6..f50337403e9 100644
--- a/crates/router/src/connector/stripe/transformers.rs
+++ b/crates/router/src/connector/stripe/transformers.rs
@@ -136,7 +136,7 @@ pub struct StripeCardData {
     #[serde(rename = "payment_method_data[type]")]
     pub payment_method_data_type: StripePaymentMethodType,
     #[serde(rename = "payment_method_data[card][number]")]
-    pub payment_method_data_card_number: Secret<String, pii::CardNumber>,
+    pub payment_method_data_card_number: cards::CardNumber,
     #[serde(rename = "payment_method_data[card][exp_month]")]
     pub payment_method_data_card_exp_month: Secret<String>,
     #[serde(rename = "payment_method_data[card][exp_year]")]
diff --git a/crates/router/src/connector/trustpay/transformers.rs b/crates/router/src/connector/trustpay/transformers.rs
index 1a11e39d79e..3b437771b0a 100644
--- a/crates/router/src/connector/trustpay/transformers.rs
+++ b/crates/router/src/connector/trustpay/transformers.rs
@@ -13,7 +13,6 @@ use crate::{
     },
     consts,
     core::errors,
-    pii::{self},
     services,
     types::{self, api, storage::enums, BrowserInformation},
 };
@@ -113,7 +112,7 @@ pub struct CallbackURLs {
 pub struct PaymentRequestCards {
     pub amount: String,
     pub currency: String,
-    pub pan: Secret<String, pii::CardNumber>,
+    pub pan: cards::CardNumber,
     pub cvv: Secret<String>,
     #[serde(rename = "exp")]
     pub expiry_date: Secret<String>,
diff --git a/crates/router/src/connector/utils.rs b/crates/router/src/connector/utils.rs
index e11ecbc467f..63776c39bb4 100644
--- a/crates/router/src/connector/utils.rs
+++ b/crates/router/src/connector/utils.rs
@@ -370,11 +370,7 @@ impl CardData for api::Card {
         Secret::new(year[year.len() - 2..].to_string())
     }
     fn get_card_issuer(&self) -> Result<CardIssuer, Error> {
-        let card: Secret<String, pii::CardNumber> = self
-            .card_number
-            .clone()
-            .map(|card| card.split_whitespace().collect());
-        get_card_issuer(card.peek().clone().as_str())
+        get_card_issuer(self.card_number.peek())
     }
     fn get_card_expiry_month_year_2_digit_with_delimiter(
         &self,
diff --git a/crates/router/src/connector/worldline/transformers.rs b/crates/router/src/connector/worldline/transformers.rs
index f6aab824a7e..74f678b2877 100644
--- a/crates/router/src/connector/worldline/transformers.rs
+++ b/crates/router/src/connector/worldline/transformers.rs
@@ -1,5 +1,5 @@
 use api_models::payments as api_models;
-use common_utils::pii::{self, Email};
+use common_utils::pii::Email;
 use masking::{PeekInterface, Secret};
 use serde::{Deserialize, Serialize};
 
@@ -17,7 +17,7 @@ use crate::{
 #[derive(Default, Debug, Serialize, Eq, PartialEq)]
 #[serde(rename_all = "camelCase")]
 pub struct Card {
-    pub card_number: Secret<String, pii::CardNumber>,
+    pub card_number: cards::CardNumber,
     pub cardholder_name: Secret<String>,
     pub cvv: Secret<String>,
     pub expiry_date: Secret<String>,
@@ -152,10 +152,7 @@ fn make_card_request(
     );
     let expiry_date: Secret<String> = Secret::new(secret_value);
     let card = Card {
-        card_number: ccard
-            .card_number
-            .clone()
-            .map(|card| card.split_whitespace().collect()),
+        card_number: ccard.card_number.clone(),
         cardholder_name: ccard.card_holder_name.clone(),
         cvv: ccard.card_cvc.clone(),
         expiry_date,
diff --git a/crates/router/src/connector/worldpay/requests.rs b/crates/router/src/connector/worldpay/requests.rs
index d4d2f6121dc..5d6fdeb5106 100644
--- a/crates/router/src/connector/worldpay/requests.rs
+++ b/crates/router/src/connector/worldpay/requests.rs
@@ -1,4 +1,3 @@
-use common_utils::pii;
 use masking::Secret;
 use serde::{Deserialize, Serialize};
 #[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)]
@@ -153,7 +152,7 @@ pub struct CardPayment {
     pub cvc: Option<Secret<String>>,
     #[serde(rename = "type")]
     pub payment_type: PaymentType,
-    pub card_number: Secret<String, pii::CardNumber>,
+    pub card_number: cards::CardNumber,
 }
 
 #[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)]
diff --git a/crates/router/src/connector/zen/transformers.rs b/crates/router/src/connector/zen/transformers.rs
index c8de11c556a..7cfdac52a0b 100644
--- a/crates/router/src/connector/zen/transformers.rs
+++ b/crates/router/src/connector/zen/transformers.rs
@@ -1,5 +1,6 @@
 use std::net::IpAddr;
 
+use cards::CardNumber;
 use common_utils::pii::Email;
 use masking::Secret;
 use serde::{Deserialize, Serialize};
@@ -9,7 +10,6 @@ use crate::{
         self, BrowserInformationData, CardData, PaymentsAuthorizeRequestData, RouterData,
     },
     core::errors,
-    pii,
     services::{self, Method},
     types::{self, api, storage::enums, transformers::ForeignTryFrom},
 };
@@ -99,7 +99,7 @@ pub enum ZenPaymentTypes {
 #[derive(Debug, Serialize)]
 #[serde(rename_all = "camelCase")]
 pub struct ZenCardDetails {
-    number: Secret<String, pii::CardNumber>,
+    number: CardNumber,
     expiry_date: Secret<String>,
     cvv: Secret<String>,
 }
diff --git a/crates/router/src/core/payment_methods/cards.rs b/crates/router/src/core/payment_methods/cards.rs
index a662145b47a..ff99a5c4d54 100644
--- a/crates/router/src/core/payment_methods/cards.rs
+++ b/crates/router/src/core/payment_methods/cards.rs
@@ -629,7 +629,13 @@ pub async fn mock_add_card(
         card_fingerprint: response.card_fingerprint.into(),
         card_global_fingerprint: response.card_global_fingerprint.into(),
         merchant_id: Some(response.merchant_id),
-        card_number: Some(response.card_number.into()),
+        card_number: response
+            .card_number
+            .try_into()
+            .into_report()
+            .change_context(errors::VaultError::ResponseDeserializationFailed)
+            .attach_printable("Invalid card number format from the mock locker")
+            .map(Some)?,
         card_exp_year: Some(response.card_exp_year.into()),
         card_exp_month: Some(response.card_exp_month.into()),
         name_on_card: response.name_on_card.map(|c| c.into()),
@@ -656,7 +662,13 @@ pub async fn mock_get_card<'a>(
         card_fingerprint: locker_mock_up.card_fingerprint.into(),
         card_global_fingerprint: locker_mock_up.card_global_fingerprint.into(),
         merchant_id: Some(locker_mock_up.merchant_id),
-        card_number: Some(locker_mock_up.card_number.into()),
+        card_number: locker_mock_up
+            .card_number
+            .try_into()
+            .into_report()
+            .change_context(errors::VaultError::ResponseDeserializationFailed)
+            .attach_printable("Invalid card number format from the mock locker")
+            .map(Some)?,
         card_exp_year: Some(locker_mock_up.card_exp_year.into()),
         card_exp_month: Some(locker_mock_up.card_exp_month.into()),
         name_on_card: locker_mock_up.name_on_card.map(|card| card.into()),
@@ -1620,11 +1632,7 @@ impl BasiliskCardSupport {
         card: api::CardDetailFromLocker,
         pm: &storage::PaymentMethod,
     ) -> errors::RouterResult<api::CardDetailFromLocker> {
-        let card_number = card
-            .card_number
-            .clone()
-            .expose_option()
-            .get_required_value("card_number")?;
+        let card_number = card.card_number.clone().get_required_value("card_number")?;
         let card_exp_month = card
             .expiry_month
             .clone()
@@ -1719,11 +1727,7 @@ impl BasiliskCardSupport {
         card: api::CardDetailFromLocker,
         pm: &storage::PaymentMethod,
     ) -> errors::RouterResult<api::CardDetailFromLocker> {
-        let card_number = card
-            .card_number
-            .clone()
-            .expose_option()
-            .get_required_value("card_number")?;
+        let card_number = card.card_number.clone().get_required_value("card_number")?;
         let card_exp_month = card
             .expiry_month
             .clone()
diff --git a/crates/router/src/core/payment_methods/transformers.rs b/crates/router/src/core/payment_methods/transformers.rs
index a12070f7fab..d4751a7d085 100644
--- a/crates/router/src/core/payment_methods/transformers.rs
+++ b/crates/router/src/core/payment_methods/transformers.rs
@@ -11,7 +11,7 @@ use crate::{
     configs::settings,
     core::errors::{self, CustomResult},
     headers,
-    pii::{self, prelude::*, Secret},
+    pii::{prelude::*, Secret},
     services::{api as services, encryption},
     types::{api, storage},
     utils::{self, OptionExt},
@@ -26,7 +26,7 @@ pub struct StoreCardReq<'a> {
 
 #[derive(Debug, Deserialize, Serialize)]
 pub struct Card {
-    pub card_number: Secret<String, pii::CardNumber>,
+    pub card_number: cards::CardNumber,
     pub name_on_card: Option<Secret<String>>,
     pub card_exp_month: Secret<String>,
     pub card_exp_year: Secret<String>,
@@ -80,7 +80,7 @@ pub struct DeleteCardResp {
 #[derive(Debug, Deserialize, Serialize)]
 #[serde(rename_all = "camelCase")]
 pub struct AddCardRequest<'a> {
-    pub card_number: Secret<String, pii::CardNumber>,
+    pub card_number: cards::CardNumber,
     pub customer_id: &'a str,
     pub card_exp_month: Secret<String>,
     pub card_exp_year: Secret<String>,
@@ -99,7 +99,7 @@ pub struct AddCardResponse {
     pub card_global_fingerprint: Secret<String>,
     #[serde(rename = "merchant_id")]
     pub merchant_id: Option<String>,
-    pub card_number: Option<Secret<String, pii::CardNumber>>,
+    pub card_number: Option<cards::CardNumber>,
     pub card_exp_year: Option<Secret<String>>,
     pub card_exp_month: Option<Secret<String>>,
     pub name_on_card: Option<Secret<String>>,
@@ -630,7 +630,7 @@ pub fn mk_crud_locker_request(
 }
 
 pub fn mk_card_value1(
-    card_number: String,
+    card_number: cards::CardNumber,
     exp_year: String,
     exp_month: String,
     name_on_card: Option<String>,
@@ -639,7 +639,7 @@ pub fn mk_card_value1(
     card_token: Option<String>,
 ) -> CustomResult<String, errors::VaultError> {
     let value1 = api::TokenizedCardValue1 {
-        card_number,
+        card_number: card_number.peek().clone(),
         exp_year,
         exp_month,
         name_on_card,
diff --git a/crates/router/src/core/payment_methods/vault.rs b/crates/router/src/core/payment_methods/vault.rs
index 02fe7359e6d..10cca24d183 100644
--- a/crates/router/src/core/payment_methods/vault.rs
+++ b/crates/router/src/core/payment_methods/vault.rs
@@ -94,7 +94,12 @@ impl Vaultable for api::Card {
             .attach_printable("Could not deserialize into card value2")?;
 
         let card = Self {
-            card_number: value1.card_number.into(),
+            card_number: value1
+                .card_number
+                .try_into()
+                .into_report()
+                .change_context(errors::VaultError::ResponseDeserializationFailed)
+                .attach_printable("Invalid card number format from the mock locker")?,
             card_exp_month: value1.exp_month.into(),
             card_exp_year: value1.exp_year.into(),
             card_holder_name: value1.name_on_card.unwrap_or_default().into(),
diff --git a/crates/router/src/lib.rs b/crates/router/src/lib.rs
index bf20ef67e4c..fb2ea5b073b 100644
--- a/crates/router/src/lib.rs
+++ b/crates/router/src/lib.rs
@@ -67,7 +67,7 @@ pub mod headers {
 pub mod pii {
     //! Personal Identifiable Information protection.
 
-    pub(crate) use common_utils::pii::{CardNumber, Email};
+    pub(crate) use common_utils::pii::Email;
     #[doc(inline)]
     pub use masking::*;
 }
diff --git a/crates/router/src/routes/dummy_connector/types.rs b/crates/router/src/routes/dummy_connector/types.rs
index 5685c6eb99c..c66fa13d1af 100644
--- a/crates/router/src/routes/dummy_connector/types.rs
+++ b/crates/router/src/routes/dummy_connector/types.rs
@@ -27,7 +27,7 @@ pub enum DummyConnectorPaymentMethodData {
 #[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
 pub struct DummyConnectorCard {
     pub name: Secret<String>,
-    pub number: Secret<String, common_utils::pii::CardNumber>,
+    pub number: cards::CardNumber,
     pub expiry_month: Secret<String>,
     pub expiry_year: Secret<String>,
     pub cvc: Secret<String>,
diff --git a/crates/router/src/routes/dummy_connector/utils.rs b/crates/router/src/routes/dummy_connector/utils.rs
index a510a14685e..f218833192b 100644
--- a/crates/router/src/routes/dummy_connector/utils.rs
+++ b/crates/router/src/routes/dummy_connector/utils.rs
@@ -1,6 +1,6 @@
 use app::AppState;
 use error_stack::{IntoReport, ResultExt};
-use masking::ExposeInterface;
+use masking::PeekInterface;
 use rand::Rng;
 use redis_interface::RedisConnectionPool;
 use tokio::time as tokio;
@@ -21,7 +21,7 @@ pub async fn payment(
     let payment_id = format!("dummy_{}", uuid::Uuid::new_v4());
     match req.payment_method_data {
         types::DummyConnectorPaymentMethodData::Card(card) => {
-            let card_number: String = card.number.expose();
+            let card_number = card.number.peek();
             tokio_mock_sleep(
                 state.conf.dummy_connector.payment_duration,
                 state.conf.dummy_connector.payment_tolerance,
diff --git a/crates/router/src/services/api.rs b/crates/router/src/services/api.rs
index ff2d10ddd49..fb61feeedfb 100644
--- a/crates/router/src/services/api.rs
+++ b/crates/router/src/services/api.rs
@@ -12,7 +12,7 @@ use std::{
 use actix_web::{body, HttpRequest, HttpResponse, Responder};
 use common_utils::errors::ReportSwitchExt;
 use error_stack::{report, IntoReport, Report, ResultExt};
-use masking::{ExposeInterface, ExposeOptionInterface, PeekInterface};
+use masking::{ExposeOptionInterface, PeekInterface};
 use router_env::{instrument, tracing, Tag};
 use serde::Serialize;
 use serde_json::json;
@@ -793,10 +793,10 @@ pub fn build_redirection_form(
             {
                 format!(
                     "var newCard={{ccNumber: \"{}\",cvv: \"{}\",expDate: \"{}/{}\",amount: {},currency: \"{}\"}};",
-                    ccard.card_number.expose(),
-                    ccard.card_cvc.expose(),
-                    ccard.card_exp_month.clone().expose(),
-                    ccard.card_exp_year.expose(),
+                    ccard.card_number.peek(),
+                    ccard.card_cvc.peek(),
+                    ccard.card_exp_month.peek(),
+                    ccard.card_exp_year.peek(),
                     amount,
                     currency
                 )
@@ -834,7 +834,7 @@ pub fn build_redirection_form(
                     }
 
                 (PreEscaped(format!("<script>
-                    bluesnap.threeDsPaymentsSetup(\"{payment_fields_token}\", 
+                    bluesnap.threeDsPaymentsSetup(\"{payment_fields_token}\",
                     function(sdkResponse) {{
                         console.log(sdkResponse);
                         var f = document.createElement('form');
diff --git a/crates/router/src/types/api/payments.rs b/crates/router/src/types/api/payments.rs
index 4c02ab9a758..5ac327ed436 100644
--- a/crates/router/src/types/api/payments.rs
+++ b/crates/router/src/types/api/payments.rs
@@ -204,7 +204,7 @@ mod payments_test {
     #[allow(dead_code)]
     fn card() -> Card {
         Card {
-            card_number: "1234432112344321".to_string().into(),
+            card_number: "1234432112344321".to_string().try_into().unwrap(),
             card_exp_month: "12".to_string().into(),
             card_exp_year: "99".to_string().into(),
             card_holder_name: "JohnDoe".to_string().into(),
diff --git a/crates/router/tests/connectors/aci.rs b/crates/router/tests/connectors/aci.rs
index 52169d90726..486ef680f32 100644
--- a/crates/router/tests/connectors/aci.rs
+++ b/crates/router/tests/connectors/aci.rs
@@ -1,4 +1,4 @@
-use std::marker::PhantomData;
+use std::{marker::PhantomData, str::FromStr};
 
 use masking::Secret;
 use router::{
@@ -35,7 +35,7 @@ fn construct_payment_router_data() -> types::PaymentsAuthorizeRouterData {
             amount: 1000,
             currency: enums::Currency::USD,
             payment_method_data: types::api::PaymentMethodData::Card(types::api::Card {
-                card_number: Secret::new("4200000000000000".to_string()),
+                card_number: cards::CardNumber::from_str("4200000000000000").unwrap(),
                 card_exp_month: Secret::new("10".to_string()),
                 card_exp_year: Secret::new("2025".to_string()),
                 card_holder_name: Secret::new("John Doe".to_string()),
@@ -174,7 +174,7 @@ async fn payments_create_failure() {
         let mut request = construct_payment_router_data();
         request.request.payment_method_data =
             types::api::PaymentMethodData::Card(types::api::Card {
-                card_number: Secret::new("420000000000000000".to_string()),
+                card_number: cards::CardNumber::from_str("4200000000000000").unwrap(),
                 card_exp_month: Secret::new("10".to_string()),
                 card_exp_year: Secret::new("2025".to_string()),
                 card_holder_name: Secret::new("John Doe".to_string()),
diff --git a/crates/router/tests/connectors/adyen.rs b/crates/router/tests/connectors/adyen.rs
index 19f1d79163b..720dd283874 100644
--- a/crates/router/tests/connectors/adyen.rs
+++ b/crates/router/tests/connectors/adyen.rs
@@ -1,3 +1,5 @@
+use std::str::FromStr;
+
 use api_models::payments::{Address, AddressDetails};
 use masking::Secret;
 use router::types::{self, api, storage::enums, PaymentAddress};
@@ -61,7 +63,7 @@ impl AdyenTest {
             amount: 3500,
             currency: enums::Currency::USD,
             payment_method_data: types::api::PaymentMethodData::Card(types::api::Card {
-                card_number: Secret::new(card_number.to_string()),
+                card_number: cards::CardNumber::from_str(card_number).unwrap(),
                 card_exp_month: Secret::new(card_exp_month.to_string()),
                 card_exp_year: Secret::new(card_exp_year.to_string()),
                 card_holder_name: Secret::new("John Doe".to_string()),
@@ -341,7 +343,7 @@ async fn should_fail_payment_for_incorrect_card_number() {
             Some(types::PaymentsAuthorizeData {
                 router_return_url: Some(String::from("http://localhost:8080")),
                 payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-                    card_number: Secret::new("1234567891011".to_string()),
+                    card_number: cards::CardNumber::from_str("1234567891011").unwrap(),
                     ..utils::CCardType::default().0
                 }),
                 ..utils::PaymentAuthorizeType::default().0
@@ -356,27 +358,6 @@ async fn should_fail_payment_for_incorrect_card_number() {
     );
 }
 
-// Creates a payment with empty card number.
-#[actix_web::test]
-async fn should_fail_payment_for_empty_card_number() {
-    let response = CONNECTOR
-        .make_payment(
-            Some(types::PaymentsAuthorizeData {
-                router_return_url: Some(String::from("http://localhost:8080")),
-                payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-                    card_number: Secret::new(String::from("")),
-                    ..utils::CCardType::default().0
-                }),
-                ..utils::PaymentAuthorizeType::default().0
-            }),
-            AdyenTest::get_payment_info(),
-        )
-        .await
-        .unwrap();
-    let x = response.response.unwrap_err();
-    assert_eq!(x.message, "Missing payment method details: number",);
-}
-
 // Creates a payment with incorrect CVC.
 #[actix_web::test]
 async fn should_fail_payment_for_incorrect_cvc() {
diff --git a/crates/router/tests/connectors/airwallex.rs b/crates/router/tests/connectors/airwallex.rs
index f2e026144cf..97a701636ed 100644
--- a/crates/router/tests/connectors/airwallex.rs
+++ b/crates/router/tests/connectors/airwallex.rs
@@ -1,3 +1,5 @@
+use std::str::FromStr;
+
 use masking::Secret;
 use router::types::{self, api, storage::enums, AccessToken};
 
@@ -53,7 +55,7 @@ fn get_default_payment_info() -> Option<utils::PaymentInfo> {
 fn payment_method_details() -> Option<types::PaymentsAuthorizeData> {
     Some(types::PaymentsAuthorizeData {
         payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-            card_number: Secret::new("4035501000000008".to_string()),
+            card_number: cards::CardNumber::from_str("4035501000000008").unwrap(),
             card_exp_month: Secret::new("02".to_string()),
             card_exp_year: Secret::new("2035".to_string()),
             card_holder_name: Secret::new("John Doe".to_string()),
@@ -350,7 +352,7 @@ async fn should_fail_payment_for_incorrect_card_number() {
         .make_payment(
             Some(types::PaymentsAuthorizeData {
                 payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-                    card_number: Secret::new("1234567891011".to_string()),
+                    card_number: cards::CardNumber::from_str("1234567891011").unwrap(),
                     ..utils::CCardType::default().0
                 }),
                 ..utils::PaymentAuthorizeType::default().0
@@ -365,27 +367,6 @@ async fn should_fail_payment_for_incorrect_card_number() {
     );
 }
 
-// Creates a payment with empty card number.
-#[serial_test::serial]
-#[actix_web::test]
-async fn should_fail_payment_for_empty_card_number() {
-    let response = CONNECTOR
-        .make_payment(
-            Some(types::PaymentsAuthorizeData {
-                payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-                    card_number: Secret::new(String::from("")),
-                    ..utils::CCardType::default().0
-                }),
-                ..utils::PaymentAuthorizeType::default().0
-            }),
-            get_default_payment_info(),
-        )
-        .await
-        .unwrap();
-    let x = response.response.unwrap_err();
-    assert_eq!(x.message, "Invalid card number",);
-}
-
 // Creates a payment with incorrect CVC.
 #[serial_test::serial]
 #[actix_web::test]
diff --git a/crates/router/tests/connectors/authorizedotnet.rs b/crates/router/tests/connectors/authorizedotnet.rs
index aa5c236db4c..cf3b16d02a5 100644
--- a/crates/router/tests/connectors/authorizedotnet.rs
+++ b/crates/router/tests/connectors/authorizedotnet.rs
@@ -1,4 +1,4 @@
-use std::marker::PhantomData;
+use std::{marker::PhantomData, str::FromStr};
 
 use masking::Secret;
 use router::{
@@ -35,7 +35,7 @@ fn construct_payment_router_data() -> types::PaymentsAuthorizeRouterData {
             amount: 100,
             currency: enums::Currency::USD,
             payment_method_data: types::api::PaymentMethodData::Card(types::api::Card {
-                card_number: Secret::new("5424000000000015".to_string()),
+                card_number: cards::CardNumber::from_str("5424000000000015").unwrap(),
                 card_exp_month: Secret::new("10".to_string()),
                 card_exp_year: Secret::new("2025".to_string()),
                 card_holder_name: Secret::new("John Doe".to_string()),
@@ -177,7 +177,7 @@ async fn payments_create_failure() {
 
         request.request.payment_method_data =
             types::api::PaymentMethodData::Card(types::api::Card {
-                card_number: Secret::new("542400000000001".to_string()),
+                card_number: cards::CardNumber::from_str("5424000000000015").unwrap(),
                 card_exp_month: Secret::new("10".to_string()),
                 card_exp_year: Secret::new("2025".to_string()),
                 card_holder_name: Secret::new("John Doe".to_string()),
diff --git a/crates/router/tests/connectors/bambora.rs b/crates/router/tests/connectors/bambora.rs
index 83a327aaf85..59020b8ea61 100644
--- a/crates/router/tests/connectors/bambora.rs
+++ b/crates/router/tests/connectors/bambora.rs
@@ -1,3 +1,5 @@
+use std::str::FromStr;
+
 use api_models::payments::PaymentMethodData;
 use masking::Secret;
 use router::types::{self, api, storage::enums};
@@ -38,7 +40,7 @@ static CONNECTOR: BamboraTest = BamboraTest {};
 fn get_default_payment_authorize_data() -> Option<types::PaymentsAuthorizeData> {
     Some(types::PaymentsAuthorizeData {
         payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-            card_number: Secret::new("4030000010001234".to_string()),
+            card_number: cards::CardNumber::from_str("4030000010001234").unwrap(),
             card_exp_year: Secret::new("25".to_string()),
             card_cvc: Secret::new("123".to_string()),
             ..utils::CCardType::default().0
@@ -286,7 +288,7 @@ async fn should_fail_payment_for_incorrect_card_number() {
         .make_payment(
             Some(types::PaymentsAuthorizeData {
                 payment_method_data: PaymentMethodData::Card(api::Card {
-                    card_number: Secret::new("1234567891011".to_string()),
+                    card_number: cards::CardNumber::from_str("1234567891011").unwrap(),
                     card_exp_year: Secret::new("25".to_string()),
                     ..utils::CCardType::default().0
                 }),
@@ -302,29 +304,6 @@ async fn should_fail_payment_for_incorrect_card_number() {
     );
 }
 
-// Creates a payment with empty card number.
-#[actix_web::test]
-async fn should_fail_payment_for_empty_card_number() {
-    let response = CONNECTOR
-        .make_payment(
-            Some(types::PaymentsAuthorizeData {
-                payment_method_data: PaymentMethodData::Card(api::Card {
-                    card_number: Secret::new(String::from("")),
-                    ..utils::CCardType::default().0
-                }),
-                ..utils::PaymentAuthorizeType::default().0
-            }),
-            None,
-        )
-        .await
-        .unwrap();
-    let x = response.response.unwrap_err();
-    assert_eq!(
-        x.reason,
-        Some(r#"[{"field":"card:number","message":"Invalid Card Number"},{"field":"card:expiry_year","message":"Invalid expiration year"}]"#.to_string()),
-    );
-}
-
 // Creates a payment with incorrect CVC.
 #[actix_web::test]
 async fn should_fail_payment_for_incorrect_cvc() {
@@ -356,7 +335,7 @@ async fn should_fail_payment_for_invalid_exp_month() {
             Some(types::PaymentsAuthorizeData {
                 payment_method_data: PaymentMethodData::Card(api::Card {
                     card_exp_month: Secret::new("20".to_string()),
-                    card_number: Secret::new("4030000010001234".to_string()),
+                    card_number: cards::CardNumber::from_str("4030000010001234").unwrap(),
                     card_exp_year: Secret::new("25".to_string()),
                     card_cvc: Secret::new("123".to_string()),
                     ..utils::CCardType::default().0
@@ -381,7 +360,7 @@ async fn should_fail_payment_for_incorrect_expiry_year() {
             Some(types::PaymentsAuthorizeData {
                 payment_method_data: PaymentMethodData::Card(api::Card {
                     card_exp_year: Secret::new("2000".to_string()),
-                    card_number: Secret::new("4030000010001234".to_string()),
+                    card_number: cards::CardNumber::from_str("4030000010001234").unwrap(),
                     card_cvc: Secret::new("123".to_string()),
                     ..utils::CCardType::default().0
                 }),
diff --git a/crates/router/tests/connectors/bluesnap.rs b/crates/router/tests/connectors/bluesnap.rs
index 4c3e4e848fe..c51b0d87dfb 100644
--- a/crates/router/tests/connectors/bluesnap.rs
+++ b/crates/router/tests/connectors/bluesnap.rs
@@ -1,3 +1,5 @@
+use std::str::FromStr;
+
 use masking::Secret;
 use router::types::{self, api, storage::enums, ConnectorAuthType};
 
@@ -363,7 +365,7 @@ async fn should_fail_payment_for_incorrect_card_number() {
         .make_payment(
             Some(types::PaymentsAuthorizeData {
                 payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-                    card_number: Secret::new("1234567891011".to_string()),
+                    card_number: cards::CardNumber::from_str("1234567891011").unwrap(),
                     ..utils::CCardType::default().0
                 }),
                 ..utils::PaymentAuthorizeType::default().0
@@ -378,31 +380,6 @@ async fn should_fail_payment_for_incorrect_card_number() {
     );
 }
 
-// Creates a payment with empty card number.
-
-#[serial_test::serial]
-#[actix_web::test]
-async fn should_fail_payment_for_empty_card_number() {
-    let response = CONNECTOR
-        .make_payment(
-            Some(types::PaymentsAuthorizeData {
-                payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-                    card_number: Secret::new(String::from("")),
-                    ..utils::CCardType::default().0
-                }),
-                ..utils::PaymentAuthorizeType::default().0
-            }),
-            None,
-        )
-        .await
-        .unwrap();
-    let x = response.response.unwrap_err();
-    assert_eq!(
-        x.message,
-        "Order creation failure due to problematic input.",
-    );
-}
-
 // Creates a payment with incorrect CVC.
 
 #[serial_test::serial]
diff --git a/crates/router/tests/connectors/checkout.rs b/crates/router/tests/connectors/checkout.rs
index 084295b8adf..56ef70ab9aa 100644
--- a/crates/router/tests/connectors/checkout.rs
+++ b/crates/router/tests/connectors/checkout.rs
@@ -1,3 +1,6 @@
+use std::str::FromStr;
+
+use cards::CardNumber;
 use masking::Secret;
 use router::types::{self, api, storage::enums};
 
@@ -318,7 +321,7 @@ async fn should_fail_payment_for_incorrect_card_number() {
         .make_payment(
             Some(types::PaymentsAuthorizeData {
                 payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-                    card_number: Secret::new("1234567891011".to_string()),
+                    card_number: CardNumber::from_str("1234567891011").unwrap(),
                     ..utils::CCardType::default().0
                 }),
                 ..utils::PaymentAuthorizeType::default().0
@@ -333,27 +336,6 @@ async fn should_fail_payment_for_incorrect_card_number() {
     );
 }
 
-// Creates a payment with empty card number.
-#[serial_test::serial]
-#[actix_web::test]
-async fn should_fail_payment_for_empty_card_number() {
-    let response = CONNECTOR
-        .make_payment(
-            Some(types::PaymentsAuthorizeData {
-                payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-                    card_number: Secret::new(String::from("")),
-                    ..utils::CCardType::default().0
-                }),
-                ..utils::PaymentAuthorizeType::default().0
-            }),
-            get_default_payment_info(),
-        )
-        .await
-        .unwrap();
-    let x = response.response.unwrap_err();
-    assert_eq!(x.code, "card_number_required",);
-}
-
 // Creates a payment with incorrect CVC.
 #[serial_test::serial]
 #[actix_web::test]
diff --git a/crates/router/tests/connectors/coinbase.rs b/crates/router/tests/connectors/coinbase.rs
index 2ce5efae67f..2a01ed7c621 100644
--- a/crates/router/tests/connectors/coinbase.rs
+++ b/crates/router/tests/connectors/coinbase.rs
@@ -1,3 +1,5 @@
+use std::str::FromStr;
+
 use masking::Secret;
 use router::types::{self, api, storage::enums};
 
@@ -303,7 +305,7 @@ async fn should_fail_payment_for_incorrect_card_number() {
         .make_payment(
             Some(types::PaymentsAuthorizeData {
                 payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-                    card_number: Secret::new("1234567891011".to_string()),
+                    card_number: cards::CardNumber::from_str("1234567891011").unwrap(),
                     ..utils::CCardType::default().0
                 }),
                 ..utils::PaymentAuthorizeType::default().0
@@ -318,29 +320,6 @@ async fn should_fail_payment_for_incorrect_card_number() {
     );
 }
 
-// Creates a payment with empty card number.
-#[actix_web::test]
-async fn should_fail_payment_for_empty_card_number() {
-    let response = CONNECTOR
-        .make_payment(
-            Some(types::PaymentsAuthorizeData {
-                payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-                    card_number: Secret::new(String::from("")),
-                    ..utils::CCardType::default().0
-                }),
-                ..utils::PaymentAuthorizeType::default().0
-            }),
-            get_default_payment_info(),
-        )
-        .await
-        .unwrap();
-    let x = response.response.unwrap_err();
-    assert_eq!(
-        x.message,
-        "You passed an empty string for 'payment_method_data[card][number]'.",
-    );
-}
-
 // Creates a payment with incorrect CVC.
 #[actix_web::test]
 async fn should_fail_payment_for_incorrect_cvc() {
diff --git a/crates/router/tests/connectors/cybersource.rs b/crates/router/tests/connectors/cybersource.rs
index 297a27ff662..d12e61ee4d1 100644
--- a/crates/router/tests/connectors/cybersource.rs
+++ b/crates/router/tests/connectors/cybersource.rs
@@ -155,7 +155,7 @@ async fn should_fail_payment_for_incorrect_card_number() {
         .make_payment(
             Some(types::PaymentsAuthorizeData {
                 payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-                    card_number: Secret::new("4024007134364111".to_string()),
+                    card_number: cards::CardNumber::from_str("4024007134364111").unwrap(),
                     ..utils::CCardType::default().0
                 }),
                 ..get_default_payment_authorize_data().unwrap()
@@ -168,24 +168,6 @@ async fn should_fail_payment_for_incorrect_card_number() {
     assert_eq!(x.message, "Decline - Invalid account number",);
 }
 #[actix_web::test]
-async fn should_fail_payment_for_no_card_number() {
-    let response = Cybersource {}
-        .make_payment(
-            Some(types::PaymentsAuthorizeData {
-                payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-                    card_number: Secret::new("".to_string()),
-                    ..utils::CCardType::default().0
-                }),
-                ..get_default_payment_authorize_data().unwrap()
-            }),
-            get_default_payment_info(),
-        )
-        .await
-        .unwrap();
-    let x = response.response.unwrap_err();
-    assert_eq!(x.message, "The order has been rejected by Decision Manager",);
-}
-#[actix_web::test]
 async fn should_fail_payment_for_invalid_exp_month() {
     let response = Cybersource {}
         .make_payment(
diff --git a/crates/router/tests/connectors/dlocal.rs b/crates/router/tests/connectors/dlocal.rs
index c0acd97596a..d323c72aa3e 100644
--- a/crates/router/tests/connectors/dlocal.rs
+++ b/crates/router/tests/connectors/dlocal.rs
@@ -1,3 +1,5 @@
+use std::str::FromStr;
+
 use api_models::payments::Address;
 use masking::Secret;
 use router::types::{self, api, storage::enums, PaymentAddress};
@@ -286,28 +288,7 @@ async fn should_fail_payment_for_incorrect_card_number() {
         .make_payment(
             Some(types::PaymentsAuthorizeData {
                 payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-                    card_number: Secret::new("1891011".to_string()),
-                    ..utils::CCardType::default().0
-                }),
-                ..utils::PaymentAuthorizeType::default().0
-            }),
-            Some(get_payment_info()),
-        )
-        .await
-        .unwrap();
-    let x = response.response.unwrap_err();
-    assert_eq!(x.message, "Invalid parameter",);
-    assert_eq!(x.reason, Some("card.number".to_string()));
-}
-
-// Creates a payment with empty card number.
-#[actix_web::test]
-async fn should_fail_payment_for_empty_card_number() {
-    let response = CONNECTOR
-        .make_payment(
-            Some(types::PaymentsAuthorizeData {
-                payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-                    card_number: Secret::new(String::from("")),
+                    card_number: cards::CardNumber::from_str("1891011").unwrap(),
                     ..utils::CCardType::default().0
                 }),
                 ..utils::PaymentAuthorizeType::default().0
diff --git a/crates/router/tests/connectors/dummyconnector.rs b/crates/router/tests/connectors/dummyconnector.rs
index ba422137a34..0449647c3c2 100644
--- a/crates/router/tests/connectors/dummyconnector.rs
+++ b/crates/router/tests/connectors/dummyconnector.rs
@@ -1,3 +1,6 @@
+use std::str::FromStr;
+
+use cards::CardNumber;
 use masking::Secret;
 use router::types::{self, api, storage::enums};
 
@@ -303,7 +306,7 @@ async fn should_fail_payment_for_incorrect_card_number() {
         .make_payment(
             Some(types::PaymentsAuthorizeData {
                 payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-                    card_number: Secret::new("1234567891011".to_string()),
+                    card_number: CardNumber::from_str("1234567891011").unwrap(),
                     ..utils::CCardType::default().0
                 }),
                 ..utils::PaymentAuthorizeType::default().0
@@ -318,29 +321,6 @@ async fn should_fail_payment_for_incorrect_card_number() {
     );
 }
 
-// Creates a payment with empty card number.
-#[actix_web::test]
-async fn should_fail_payment_for_empty_card_number() {
-    let response = CONNECTOR
-        .make_payment(
-            Some(types::PaymentsAuthorizeData {
-                payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-                    card_number: Secret::new(String::from("")),
-                    ..utils::CCardType::default().0
-                }),
-                ..utils::PaymentAuthorizeType::default().0
-            }),
-            get_default_payment_info(),
-        )
-        .await
-        .unwrap();
-    let x = response.response.unwrap_err();
-    assert_eq!(
-        x.message,
-        "You passed an empty string for 'payment_method_data[card][number]'.",
-    );
-}
-
 // Creates a payment with incorrect CVC.
 #[actix_web::test]
 async fn should_fail_payment_for_incorrect_cvc() {
diff --git a/crates/router/tests/connectors/fiserv.rs b/crates/router/tests/connectors/fiserv.rs
index 68a5fe191dc..61dcdf0de9d 100644
--- a/crates/router/tests/connectors/fiserv.rs
+++ b/crates/router/tests/connectors/fiserv.rs
@@ -1,3 +1,5 @@
+use std::str::FromStr;
+
 use masking::Secret;
 use router::types::{self, api, storage::enums};
 use serde_json::json;
@@ -39,7 +41,7 @@ impl utils::Connector for FiservTest {
 fn payment_method_details() -> Option<types::PaymentsAuthorizeData> {
     Some(types::PaymentsAuthorizeData {
         payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-            card_number: Secret::new("4005550000000019".to_string()),
+            card_number: cards::CardNumber::from_str("4005550000000019").unwrap(),
             card_exp_month: Secret::new("02".to_string()),
             card_exp_year: Secret::new("2035".to_string()),
             card_holder_name: Secret::new("John Doe".to_string()),
@@ -341,7 +343,7 @@ async fn should_fail_payment_for_incorrect_card_number() {
         .make_payment(
             Some(types::PaymentsAuthorizeData {
                 payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-                    card_number: Secret::new("1234567891011".to_string()),
+                    card_number: cards::CardNumber::from_str("1234567891011").unwrap(),
                     ..utils::CCardType::default().0
                 }),
                 ..utils::PaymentAuthorizeType::default().0
@@ -356,27 +358,6 @@ async fn should_fail_payment_for_incorrect_card_number() {
     );
 }
 
-// Creates a payment with empty card number.
-#[actix_web::test]
-#[serial_test::serial]
-async fn should_fail_payment_for_empty_card_number() {
-    let response = CONNECTOR
-        .make_payment(
-            Some(types::PaymentsAuthorizeData {
-                payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-                    card_number: Secret::new(String::from("")),
-                    ..utils::CCardType::default().0
-                }),
-                ..utils::PaymentAuthorizeType::default().0
-            }),
-            get_default_payment_info(),
-        )
-        .await
-        .unwrap();
-    let x = response.response.unwrap_err();
-    assert_eq!(x.message, "Invalid or Missing Field Data",);
-}
-
 // Creates a payment with incorrect CVC.
 #[actix_web::test]
 #[serial_test::serial]
diff --git a/crates/router/tests/connectors/forte.rs b/crates/router/tests/connectors/forte.rs
index 57fa0175000..aa2d09c94f1 100644
--- a/crates/router/tests/connectors/forte.rs
+++ b/crates/router/tests/connectors/forte.rs
@@ -1,5 +1,6 @@
-use std::time::Duration;
+use std::{str::FromStr, time::Duration};
 
+use cards::CardNumber;
 use masking::Secret;
 use router::types::{self, api, storage::enums};
 
@@ -39,7 +40,7 @@ static CONNECTOR: ForteTest = ForteTest {};
 fn get_payment_data() -> Option<types::PaymentsAuthorizeData> {
     Some(types::PaymentsAuthorizeData {
         payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-            card_number: Secret::new(String::from("4111111111111111")),
+            card_number: CardNumber::from_str("4111111111111111").unwrap(),
             ..utils::CCardType::default().0
         }),
         ..utils::PaymentAuthorizeType::default().0
@@ -459,7 +460,7 @@ async fn should_fail_payment_for_incorrect_card_number() {
         .make_payment(
             Some(types::PaymentsAuthorizeData {
                 payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-                    card_number: Secret::new("4111111111111100".to_string()),
+                    card_number: CardNumber::from_str("4111111111111100").unwrap(),
                     ..utils::CCardType::default().0
                 }),
                 ..utils::PaymentAuthorizeType::default().0
@@ -474,27 +475,6 @@ async fn should_fail_payment_for_incorrect_card_number() {
     );
 }
 
-// Creates a payment with empty card number.
-#[actix_web::test]
-async fn should_fail_payment_for_empty_card_number() {
-    let response = CONNECTOR
-        .make_payment(
-            Some(types::PaymentsAuthorizeData {
-                payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-                    card_number: Secret::new(String::from("")),
-                    ..utils::CCardType::default().0
-                }),
-                ..utils::PaymentAuthorizeType::default().0
-            }),
-            get_default_payment_info(),
-        )
-        .await;
-    assert_eq!(
-        *response.unwrap_err().current_context(),
-        router::core::errors::ConnectorError::NotImplemented("Card Type".into())
-    )
-}
-
 // Creates a payment with incorrect CVC.
 #[actix_web::test]
 async fn should_fail_payment_for_incorrect_cvc() {
@@ -665,7 +645,7 @@ async fn should_fail_for_refund_amount_higher_than_payment_amount() {
 async fn should_throw_not_implemented_for_unsupported_issuer() {
     let authorize_data = Some(types::PaymentsAuthorizeData {
         payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-            card_number: Secret::new(String::from("6759649826438453")),
+            card_number: CardNumber::from_str("6759649826438453").unwrap(),
             ..utils::CCardType::default().0
         }),
         capture_method: Some(enums::CaptureMethod::Automatic),
diff --git a/crates/router/tests/connectors/globalpay.rs b/crates/router/tests/connectors/globalpay.rs
index adbf67aaf1e..88df64e514e 100644
--- a/crates/router/tests/connectors/globalpay.rs
+++ b/crates/router/tests/connectors/globalpay.rs
@@ -1,4 +1,5 @@
-use masking::Secret;
+use std::str::FromStr;
+
 use router::types::{self, api, storage::enums};
 use serde_json::json;
 
@@ -120,7 +121,7 @@ async fn should_fail_payment_for_incorrect_cvc() {
         .make_payment(
             Some(types::PaymentsAuthorizeData {
                 payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-                    card_number: Secret::new("4024007134364842".to_string()),
+                    card_number: cards::CardNumber::from_str("4024007134364842").unwrap(),
                     ..utils::CCardType::default().0
                 }),
                 ..utils::PaymentAuthorizeType::default().0
diff --git a/crates/router/tests/connectors/main.rs b/crates/router/tests/connectors/main.rs
index 95b79c6166d..81d7ac8ea84 100644
--- a/crates/router/tests/connectors/main.rs
+++ b/crates/router/tests/connectors/main.rs
@@ -1,4 +1,9 @@
-#![allow(clippy::expect_used, clippy::panic, clippy::unwrap_used)]
+#![allow(
+    clippy::expect_used,
+    clippy::panic,
+    clippy::unwrap_in_result,
+    clippy::unwrap_used
+)]
 
 mod aci;
 mod adyen;
diff --git a/crates/router/tests/connectors/multisafepay.rs b/crates/router/tests/connectors/multisafepay.rs
index b884b6bb093..25a4ac198f7 100644
--- a/crates/router/tests/connectors/multisafepay.rs
+++ b/crates/router/tests/connectors/multisafepay.rs
@@ -1,3 +1,5 @@
+use std::str::FromStr;
+
 use masking::Secret;
 use router::types::{self, api, storage::enums};
 
@@ -278,7 +280,7 @@ async fn should_fail_payment_for_incorrect_card_number() {
         .make_payment(
             Some(types::PaymentsAuthorizeData {
                 payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-                    card_number: Secret::new("374500000000015".to_string()),
+                    card_number: cards::CardNumber::from_str("37450000000001").unwrap(),
                     ..utils::CCardType::default().0
                 }),
                 ..utils::PaymentAuthorizeType::default().0
@@ -290,26 +292,6 @@ async fn should_fail_payment_for_incorrect_card_number() {
     assert!(response.response.is_err());
 }
 
-// Creates a payment with empty card number.
-#[actix_web::test]
-async fn should_fail_payment_for_empty_card_number() {
-    let response = CONNECTOR
-        .make_payment(
-            Some(types::PaymentsAuthorizeData {
-                payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-                    card_number: Secret::new(String::from("")),
-                    ..utils::CCardType::default().0
-                }),
-                ..utils::PaymentAuthorizeType::default().0
-            }),
-            None,
-        )
-        .await
-        .unwrap();
-    let x = response.response.is_err();
-    assert!(x);
-}
-
 // Creates a payment with incorrect CVC.
 #[actix_web::test]
 async fn should_fail_payment_for_incorrect_cvc() {
diff --git a/crates/router/tests/connectors/nexinets.rs b/crates/router/tests/connectors/nexinets.rs
index 86817c2e588..760ad56fa15 100644
--- a/crates/router/tests/connectors/nexinets.rs
+++ b/crates/router/tests/connectors/nexinets.rs
@@ -1,3 +1,6 @@
+use std::str::FromStr;
+
+use cards::CardNumber;
 use masking::Secret;
 use router::types::{self, api, storage::enums, PaymentsAuthorizeData};
 
@@ -37,7 +40,7 @@ fn payment_method_details() -> Option<PaymentsAuthorizeData> {
     Some(PaymentsAuthorizeData {
         currency: storage_models::enums::Currency::EUR,
         payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-            card_number: Secret::new("4012001038443335".to_string()),
+            card_number: CardNumber::from_str("4012001038443336").unwrap(),
             ..utils::CCardType::default().0
         }),
         router_return_url: Some("https://google.com".to_string()),
@@ -499,7 +502,7 @@ async fn should_fail_payment_for_incorrect_card_number() {
         .make_payment(
             Some(PaymentsAuthorizeData {
                 payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-                    card_number: Secret::new("12345678910112331".to_string()),
+                    card_number: CardNumber::from_str("12345678910112331").unwrap(),
                     ..utils::CCardType::default().0
                 }),
                 currency: storage_models::enums::Currency::EUR,
@@ -515,29 +518,6 @@ async fn should_fail_payment_for_incorrect_card_number() {
     );
 }
 
-// Creates a payment with empty card number.
-#[actix_web::test]
-async fn should_fail_payment_for_empty_card_number() {
-    let response = CONNECTOR
-        .make_payment(
-            Some(PaymentsAuthorizeData {
-                payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-                    card_number: Secret::new(String::from("")),
-                    ..utils::CCardType::default().0
-                }),
-                ..utils::PaymentAuthorizeType::default().0
-            }),
-            None,
-        )
-        .await
-        .unwrap();
-    let x = response.response.unwrap_err();
-    assert_eq!(
-        x.message,
-        "payment.cardNumber : Bad value for 'payment.cardNumber'. Expected: string of length in range 12 <=> 19 representing a valid creditcard number.",
-    );
-}
-
 // Creates a payment with incorrect CVC.
 #[actix_web::test]
 async fn should_fail_payment_for_incorrect_cvc() {
diff --git a/crates/router/tests/connectors/nuvei.rs b/crates/router/tests/connectors/nuvei.rs
index e1d56f89e7a..564ca5c4ca6 100644
--- a/crates/router/tests/connectors/nuvei.rs
+++ b/crates/router/tests/connectors/nuvei.rs
@@ -1,3 +1,5 @@
+use std::str::FromStr;
+
 use masking::Secret;
 use router::types::{
     self, api,
@@ -41,7 +43,7 @@ static CONNECTOR: NuveiTest = NuveiTest {};
 fn get_payment_data() -> Option<types::PaymentsAuthorizeData> {
     Some(types::PaymentsAuthorizeData {
         payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-            card_number: Secret::new(String::from("4444 3333 2222 1111")),
+            card_number: cards::CardNumber::from_str("4444 3333 2222 1111").unwrap(),
             ..utils::CCardType::default().0
         }),
         ..utils::PaymentAuthorizeType::default().0
@@ -246,7 +248,7 @@ async fn should_fail_payment_for_incorrect_card_number() {
         .make_payment(
             Some(types::PaymentsAuthorizeData {
                 payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-                    card_number: Secret::new("1234567891011".to_string()),
+                    card_number: cards::CardNumber::from_str("1234567891011").unwrap(),
                     ..utils::CCardType::default().0
                 }),
                 ..utils::PaymentAuthorizeType::default().0
@@ -261,29 +263,6 @@ async fn should_fail_payment_for_incorrect_card_number() {
     );
 }
 
-// Creates a payment with empty card number.
-#[actix_web::test]
-async fn should_fail_payment_for_empty_card_number() {
-    let response = CONNECTOR
-        .make_payment(
-            Some(types::PaymentsAuthorizeData {
-                payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-                    card_number: Secret::new(String::from("")),
-                    ..utils::CCardType::default().0
-                }),
-                ..utils::PaymentAuthorizeType::default().0
-            }),
-            None,
-        )
-        .await
-        .unwrap();
-    let x = response.response.unwrap_err();
-    assert_eq!(
-        x.message,
-        "Missing or invalid CardData data. Missing card number.",
-    );
-}
-
 // Creates a payment with incorrect CVC.
 #[actix_web::test]
 async fn should_fail_payment_for_incorrect_cvc() {
@@ -335,7 +314,7 @@ async fn should_succeed_payment_for_incorrect_expiry_year() {
         .make_payment(
             Some(types::PaymentsAuthorizeData {
                 payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-                    card_number: Secret::new(String::from("4000027891380961")),
+                    card_number: cards::CardNumber::from_str("4000027891380961").unwrap(),
                     card_exp_year: Secret::new("2000".to_string()),
                     ..utils::CCardType::default().0
                 }),
diff --git a/crates/router/tests/connectors/opennode.rs b/crates/router/tests/connectors/opennode.rs
index 4ae979ce285..8d568789131 100644
--- a/crates/router/tests/connectors/opennode.rs
+++ b/crates/router/tests/connectors/opennode.rs
@@ -1,3 +1,5 @@
+use std::str::FromStr;
+
 use masking::Secret;
 use router::types::{self, api, storage::enums};
 
@@ -303,7 +305,7 @@ async fn should_fail_payment_for_incorrect_card_number() {
         .make_payment(
             Some(types::PaymentsAuthorizeData {
                 payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-                    card_number: Secret::new("1234567891011".to_string()),
+                    card_number: cards::CardNumber::from_str("1234567891011").unwrap(),
                     ..utils::CCardType::default().0
                 }),
                 ..utils::PaymentAuthorizeType::default().0
@@ -318,29 +320,6 @@ async fn should_fail_payment_for_incorrect_card_number() {
     );
 }
 
-// Creates a payment with empty card number.
-#[actix_web::test]
-async fn should_fail_payment_for_empty_card_number() {
-    let response = CONNECTOR
-        .make_payment(
-            Some(types::PaymentsAuthorizeData {
-                payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-                    card_number: Secret::new(String::from("")),
-                    ..utils::CCardType::default().0
-                }),
-                ..utils::PaymentAuthorizeType::default().0
-            }),
-            get_default_payment_info(),
-        )
-        .await
-        .unwrap();
-    let x = response.response.unwrap_err();
-    assert_eq!(
-        x.message,
-        "You passed an empty string for 'payment_method_data[card][number]'.",
-    );
-}
-
 // Creates a payment with incorrect CVC.
 #[actix_web::test]
 async fn should_fail_payment_for_incorrect_cvc() {
diff --git a/crates/router/tests/connectors/payeezy.rs b/crates/router/tests/connectors/payeezy.rs
index 166457fe3c3..ad7a6dad287 100644
--- a/crates/router/tests/connectors/payeezy.rs
+++ b/crates/router/tests/connectors/payeezy.rs
@@ -1,4 +1,7 @@
+use std::str::FromStr;
+
 use api_models::payments::{Address, AddressDetails};
+use cards::CardNumber;
 use masking::Secret;
 use router::{
     core::errors,
@@ -41,7 +44,7 @@ impl PayeezyTest {
     fn get_payment_data() -> Option<PaymentsAuthorizeData> {
         Some(PaymentsAuthorizeData {
             payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-                card_number: Secret::new(String::from("4012000033330026")),
+                card_number: CardNumber::from_str("4012000033330026").unwrap(),
                 ..utils::CCardType::default().0
             }),
             ..utils::PaymentAuthorizeType::default().0
@@ -364,7 +367,7 @@ async fn should_sync_refund() {}
 async fn should_throw_not_implemented_for_unsupported_issuer() {
     let authorize_data = Some(PaymentsAuthorizeData {
         payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-            card_number: Secret::new(String::from("630495060000000000")),
+            card_number: CardNumber::from_str("630495060000000000").unwrap(),
             ..utils::CCardType::default().0
         }),
         capture_method: Some(enums::CaptureMethod::Automatic),
@@ -383,27 +386,6 @@ async fn should_throw_not_implemented_for_unsupported_issuer() {
     )
 }
 
-// Creates a payment with empty card number.
-#[actix_web::test]
-async fn should_fail_payment_for_empty_card_number() {
-    let response = CONNECTOR
-        .make_payment(
-            Some(PaymentsAuthorizeData {
-                payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-                    card_number: Secret::new(String::from("")),
-                    ..utils::CCardType::default().0
-                }),
-                ..utils::PaymentAuthorizeType::default().0
-            }),
-            None,
-        )
-        .await;
-    assert_eq!(
-        *response.unwrap_err().current_context(),
-        errors::ConnectorError::NotImplemented("Card Type".to_string())
-    )
-}
-
 // Creates a payment with incorrect CVC.
 #[actix_web::test]
 async fn should_fail_payment_for_incorrect_cvc() {
diff --git a/crates/router/tests/connectors/paypal.rs b/crates/router/tests/connectors/paypal.rs
index 15b52c9d349..07626ce034d 100644
--- a/crates/router/tests/connectors/paypal.rs
+++ b/crates/router/tests/connectors/paypal.rs
@@ -1,3 +1,5 @@
+use std::str::FromStr;
+
 use masking::Secret;
 use router::types::{self, api, storage::enums, AccessToken, ConnectorAuthType};
 
@@ -53,7 +55,7 @@ fn get_default_payment_info() -> Option<utils::PaymentInfo> {
 fn get_payment_data() -> Option<types::PaymentsAuthorizeData> {
     Some(types::PaymentsAuthorizeData {
         payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-            card_number: Secret::new(String::from("4000020000000000")),
+            card_number: cards::CardNumber::from_str("4000020000000000").unwrap(),
             ..utils::CCardType::default().0
         }),
         ..utils::PaymentAuthorizeType::default().0
@@ -431,7 +433,7 @@ async fn should_fail_payment_for_incorrect_card_number() {
         .make_payment(
             Some(types::PaymentsAuthorizeData {
                 payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-                    card_number: Secret::new("1234567891011".to_string()),
+                    card_number: cards::CardNumber::from_str("1234567891011").unwrap(),
                     ..utils::CCardType::default().0
                 }),
                 ..utils::PaymentAuthorizeType::default().0
@@ -446,29 +448,6 @@ async fn should_fail_payment_for_incorrect_card_number() {
     );
 }
 
-// Creates a payment with empty card number.
-#[actix_web::test]
-async fn should_fail_payment_for_empty_card_number() {
-    let response = CONNECTOR
-        .make_payment(
-            Some(types::PaymentsAuthorizeData {
-                payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-                    card_number: Secret::new(String::from("")),
-                    ..utils::CCardType::default().0
-                }),
-                ..utils::PaymentAuthorizeType::default().0
-            }),
-            get_default_payment_info(),
-        )
-        .await
-        .unwrap();
-    let x = response.response.unwrap_err();
-    assert_eq!(
-        x.message,
-        "description - The card number is required when attempting to process payment with card., field - number;",
-    );
-}
-
 // Creates a payment with incorrect CVC.
 #[actix_web::test]
 async fn should_fail_payment_for_incorrect_cvc() {
diff --git a/crates/router/tests/connectors/rapyd.rs b/crates/router/tests/connectors/rapyd.rs
index 30c147581b8..29c6fa97ce8 100644
--- a/crates/router/tests/connectors/rapyd.rs
+++ b/crates/router/tests/connectors/rapyd.rs
@@ -1,3 +1,5 @@
+use std::str::FromStr;
+
 use futures::future::OptionFuture;
 use masking::Secret;
 use router::types::{self, api, storage::enums};
@@ -39,7 +41,7 @@ async fn should_only_authorize_payment() {
         .authorize_payment(
             Some(types::PaymentsAuthorizeData {
                 payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-                    card_number: Secret::new("4111111111111111".to_string()),
+                    card_number: cards::CardNumber::from_str("4111111111111111").unwrap(),
                     card_exp_month: Secret::new("02".to_string()),
                     card_exp_year: Secret::new("2024".to_string()),
                     card_holder_name: Secret::new("John Doe".to_string()),
@@ -63,7 +65,7 @@ async fn should_authorize_and_capture_payment() {
         .make_payment(
             Some(types::PaymentsAuthorizeData {
                 payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-                    card_number: Secret::new("4111111111111111".to_string()),
+                    card_number: cards::CardNumber::from_str("4111111111111111").unwrap(),
                     card_exp_month: Secret::new("02".to_string()),
                     card_exp_year: Secret::new("2024".to_string()),
                     card_holder_name: Secret::new("John Doe".to_string()),
@@ -142,7 +144,7 @@ async fn should_fail_payment_for_incorrect_card_number() {
         .make_payment(
             Some(types::PaymentsAuthorizeData {
                 payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-                    card_number: Secret::new("0000000000000000".to_string()),
+                    card_number: cards::CardNumber::from_str("0000000000000000").unwrap(),
                     ..utils::CCardType::default().0
                 }),
                 ..utils::PaymentAuthorizeType::default().0
diff --git a/crates/router/tests/connectors/shift4.rs b/crates/router/tests/connectors/shift4.rs
index a67fd0df8a3..0818e1e57ec 100644
--- a/crates/router/tests/connectors/shift4.rs
+++ b/crates/router/tests/connectors/shift4.rs
@@ -1,3 +1,5 @@
+use std::str::FromStr;
+
 use masking::Secret;
 use router::types::{self, api, storage::enums};
 
@@ -148,7 +150,7 @@ async fn should_fail_payment_for_incorrect_card_number() {
         .make_payment(
             Some(types::PaymentsAuthorizeData {
                 payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-                    card_number: Secret::new("1234567891011".to_string()),
+                    card_number: cards::CardNumber::from_str("1234567891011").unwrap(),
                     ..utils::CCardType::default().0
                 }),
                 ..utils::PaymentAuthorizeType::default().0
@@ -163,29 +165,6 @@ async fn should_fail_payment_for_incorrect_card_number() {
     );
 }
 
-// Creates a payment with empty card number.
-#[actix_web::test]
-async fn should_fail_payment_for_empty_card_number() {
-    let response = CONNECTOR
-        .make_payment(
-            Some(types::PaymentsAuthorizeData {
-                payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-                    card_number: Secret::new("".to_string()),
-                    ..utils::CCardType::default().0
-                }),
-                ..utils::PaymentAuthorizeType::default().0
-            }),
-            None,
-        )
-        .await
-        .unwrap();
-    let x = response.response.unwrap_err();
-    assert_eq!(
-        x.message,
-        "The card number is not a valid credit card number.",
-    );
-}
-
 // Creates a payment with incorrect CVC.
 #[actix_web::test]
 async fn should_succeed_payment_for_incorrect_cvc() {
diff --git a/crates/router/tests/connectors/stripe.rs b/crates/router/tests/connectors/stripe.rs
index 8d2cfc96a11..64f545d22cf 100644
--- a/crates/router/tests/connectors/stripe.rs
+++ b/crates/router/tests/connectors/stripe.rs
@@ -1,3 +1,5 @@
+use std::str::FromStr;
+
 use masking::Secret;
 use router::types::{self, api, storage::enums};
 
@@ -34,7 +36,7 @@ impl utils::Connector for Stripe {
 fn get_payment_authorize_data() -> Option<types::PaymentsAuthorizeData> {
     Some(types::PaymentsAuthorizeData {
         payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-            card_number: Secret::new("4242424242424242".to_string()),
+            card_number: cards::CardNumber::from_str("4242424242424242").unwrap(),
             ..utils::CCardType::default().0
         }),
         ..utils::PaymentAuthorizeType::default().0
@@ -155,7 +157,7 @@ async fn should_fail_payment_for_incorrect_card_number() {
         .make_payment(
             Some(types::PaymentsAuthorizeData {
                 payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-                    card_number: Secret::new("4024007134364842".to_string()),
+                    card_number: cards::CardNumber::from_str("4024007134364842").unwrap(),
                     ..utils::CCardType::default().0
                 }),
                 ..utils::PaymentAuthorizeType::default().0
@@ -171,28 +173,6 @@ async fn should_fail_payment_for_incorrect_card_number() {
     );
 }
 
-#[actix_web::test]
-async fn should_fail_payment_for_no_card_number() {
-    let response = Stripe {}
-        .make_payment(
-            Some(types::PaymentsAuthorizeData {
-                payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-                    card_number: Secret::new("".to_string()),
-                    ..utils::CCardType::default().0
-                }),
-                ..utils::PaymentAuthorizeType::default().0
-            }),
-            None,
-        )
-        .await
-        .unwrap();
-    let x = response.response.unwrap_err();
-    assert_eq!(
-        x.message,
-        "You passed an empty string for 'payment_method_data[card][number]'. We assume empty values are an attempt to unset a parameter; however 'payment_method_data[card][number]' cannot be unset. You should remove 'payment_method_data[card][number]' from your request or supply a non-empty value.",
-    );
-}
-
 #[actix_web::test]
 async fn should_fail_payment_for_invalid_exp_month() {
     let response = Stripe {}
diff --git a/crates/router/tests/connectors/trustpay.rs b/crates/router/tests/connectors/trustpay.rs
index d02bbdf4079..9d8355d17bc 100644
--- a/crates/router/tests/connectors/trustpay.rs
+++ b/crates/router/tests/connectors/trustpay.rs
@@ -1,3 +1,5 @@
+use std::str::FromStr;
+
 use masking::Secret;
 use router::types::{self, api, storage::enums, BrowserInformation};
 
@@ -50,7 +52,7 @@ fn get_default_browser_info() -> BrowserInformation {
 fn get_default_payment_authorize_data() -> Option<types::PaymentsAuthorizeData> {
     Some(types::PaymentsAuthorizeData {
         payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-            card_number: Secret::new("4200000000000000".to_string()),
+            card_number: cards::CardNumber::from_str("4200000000000000").unwrap(),
             card_exp_year: Secret::new("25".to_string()),
             card_cvc: Secret::new("123".to_string()),
             ..utils::CCardType::default().0
@@ -177,7 +179,7 @@ async fn should_sync_refund() {
 async fn should_fail_payment_for_incorrect_card_number() {
     let payment_authorize_data = types::PaymentsAuthorizeData {
         payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-            card_number: Secret::new("1234567891011".to_string()),
+            card_number: cards::CardNumber::from_str("1234567891011").unwrap(),
             card_exp_year: Secret::new("25".to_string()),
             card_cvc: Secret::new("123".to_string()),
             ..utils::CCardType::default().0
@@ -195,36 +197,12 @@ async fn should_fail_payment_for_incorrect_card_number() {
     );
 }
 
-// Creates a payment with empty card number.
-#[actix_web::test]
-async fn should_fail_payment_for_empty_card_number() {
-    let payment_authorize_data = types::PaymentsAuthorizeData {
-        payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-            card_number: Secret::new("".to_string()),
-            card_exp_year: Secret::new("25".to_string()),
-            card_cvc: Secret::new("123".to_string()),
-            ..utils::CCardType::default().0
-        }),
-        browser_info: Some(get_default_browser_info()),
-        ..utils::PaymentAuthorizeType::default().0
-    };
-    let response = CONNECTOR
-        .make_payment(Some(payment_authorize_data), get_default_payment_info())
-        .await
-        .unwrap();
-    let x = response.response.unwrap_err();
-    assert_eq!(
-        x.message,
-        "Errors { code: 61, description: \"invalid payment data (country or brand)\" }",
-    );
-}
-
 // Creates a payment with incorrect expiry year.
 #[actix_web::test]
 async fn should_fail_payment_for_incorrect_expiry_year() {
     let payment_authorize_data = Some(types::PaymentsAuthorizeData {
         payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-            card_number: Secret::new("4200000000000000".to_string()),
+            card_number: cards::CardNumber::from_str("4200000000000000").unwrap(),
             card_exp_year: Secret::new("22".to_string()),
             card_cvc: Secret::new("123".to_string()),
             ..utils::CCardType::default().0
diff --git a/crates/router/tests/connectors/utils.rs b/crates/router/tests/connectors/utils.rs
index c5815819e9f..71b7dd73f54 100644
--- a/crates/router/tests/connectors/utils.rs
+++ b/crates/router/tests/connectors/utils.rs
@@ -1,4 +1,4 @@
-use std::{fmt::Debug, marker::PhantomData, time::Duration};
+use std::{fmt::Debug, marker::PhantomData, str::FromStr, time::Duration};
 
 use async_trait::async_trait;
 use error_stack::Report;
@@ -473,7 +473,7 @@ pub struct BrowserInfoType(pub types::BrowserInformation);
 impl Default for CCardType {
     fn default() -> Self {
         Self(api::Card {
-            card_number: Secret::new("4200000000000000".to_string()),
+            card_number: cards::CardNumber::from_str("4200000000000000").unwrap(),
             card_exp_month: Secret::new("10".to_string()),
             card_exp_year: Secret::new("2025".to_string()),
             card_holder_name: Secret::new("John Doe".to_string()),
diff --git a/crates/router/tests/connectors/worldline.rs b/crates/router/tests/connectors/worldline.rs
index af88afb8907..296d8e5eba3 100644
--- a/crates/router/tests/connectors/worldline.rs
+++ b/crates/router/tests/connectors/worldline.rs
@@ -1,3 +1,5 @@
+use std::str::FromStr;
+
 use api_models::payments::{Address, AddressDetails};
 use masking::Secret;
 use router::{
@@ -64,7 +66,7 @@ impl WorldlineTest {
             amount: 3500,
             currency: enums::Currency::USD,
             payment_method_data: types::api::PaymentMethodData::Card(types::api::Card {
-                card_number: Secret::new(card_number.to_string()),
+                card_number: cards::CardNumber::from_str(card_number).unwrap(),
                 card_exp_month: Secret::new(card_exp_month.to_string()),
                 card_exp_year: Secret::new(card_exp_year.to_string()),
                 card_holder_name: Secret::new("John Doe".to_string()),
diff --git a/crates/router/tests/connectors/zen.rs b/crates/router/tests/connectors/zen.rs
index 4130a73990c..86dbc0c00c4 100644
--- a/crates/router/tests/connectors/zen.rs
+++ b/crates/router/tests/connectors/zen.rs
@@ -1,6 +1,7 @@
 use std::str::FromStr;
 
 use api_models::payments::OrderDetails;
+use cards::CardNumber;
 use common_utils::pii::Email;
 use masking::Secret;
 use router::types::{self, api, storage::enums};
@@ -300,7 +301,7 @@ async fn should_fail_payment_for_incorrect_card_number() {
         .make_payment(
             Some(types::PaymentsAuthorizeData {
                 payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-                    card_number: Secret::new("1234567891011".to_string()),
+                    card_number: CardNumber::from_str("1234567891011").unwrap(),
                     ..utils::CCardType::default().0
                 }),
                 order_details: Some(OrderDetails {
@@ -327,35 +328,6 @@ async fn should_fail_payment_for_incorrect_card_number() {
     );
 }
 
-// Creates a payment with empty card number.
-#[actix_web::test]
-async fn should_fail_payment_for_empty_card_number() {
-    let response = CONNECTOR
-        .make_payment(
-            Some(types::PaymentsAuthorizeData {
-                payment_method_data: types::api::PaymentMethodData::Card(api::Card {
-                    card_number: Secret::new(String::from("")),
-                    ..utils::CCardType::default().0
-                }),
-                order_details: Some(OrderDetails {
-                    product_name: "test".to_string(),
-                    quantity: 1,
-                }),
-                email: Some(Email::from_str("test@gmail.com").unwrap()),
-                webhook_url: Some("https://1635-116-74-253-164.ngrok-free.app".to_string()),
-                ..utils::PaymentAuthorizeType::default().0
-            }),
-            None,
-        )
-        .await
-        .unwrap();
-    let x = response.response.unwrap_err();
-    assert_eq!(
-        x.message.split_once(';').unwrap().0,
-        "Request data doesn't pass validation",
-    );
-}
-
 // Creates a payment with incorrect CVC.
 #[actix_web::test]
 async fn should_fail_payment_for_incorrect_cvc() {
diff --git a/crates/router/tests/payments.rs b/crates/router/tests/payments.rs
index 31d3712a6cc..6a9b7b0d941 100644
--- a/crates/router/tests/payments.rs
+++ b/crates/router/tests/payments.rs
@@ -302,7 +302,7 @@ async fn payments_create_core() {
         setup_future_usage: Some(api_enums::FutureUsage::OnSession),
         authentication_type: Some(api_enums::AuthenticationType::NoThreeDs),
         payment_method_data: Some(api::PaymentMethodData::Card(api::Card {
-            card_number: "4242424242424242".to_string().into(),
+            card_number: "4242424242424242".to_string().try_into().unwrap(),
             card_exp_month: "10".to_string().into(),
             card_exp_year: "35".to_string().into(),
             card_holder_name: "Arun Raj".to_string().into(),
@@ -449,7 +449,7 @@ async fn payments_create_core_adyen_no_redirect() {
         setup_future_usage: Some(api_enums::FutureUsage::OnSession),
         authentication_type: Some(api_enums::AuthenticationType::NoThreeDs),
         payment_method_data: Some(api::PaymentMethodData::Card(api::Card {
-            card_number: "5555 3412 4444 1115".to_string().into(),
+            card_number: "5555 3412 4444 1115".to_string().try_into().unwrap(),
             card_exp_month: "03".to_string().into(),
             card_exp_year: "2030".to_string().into(),
             card_holder_name: "JohnDoe".to_string().into(),
diff --git a/crates/router/tests/payments2.rs b/crates/router/tests/payments2.rs
index bb4119871df..1713e33c03f 100644
--- a/crates/router/tests/payments2.rs
+++ b/crates/router/tests/payments2.rs
@@ -62,7 +62,7 @@ async fn payments_create_core() {
         setup_future_usage: None,
         authentication_type: Some(api_enums::AuthenticationType::NoThreeDs),
         payment_method_data: Some(api::PaymentMethodData::Card(api::Card {
-            card_number: "4242424242424242".to_string().into(),
+            card_number: "4242424242424242".to_string().try_into().unwrap(),
             card_exp_month: "10".to_string().into(),
             card_exp_year: "35".to_string().into(),
             card_holder_name: "Arun Raj".to_string().into(),
@@ -215,7 +215,7 @@ async fn payments_create_core_adyen_no_redirect() {
         setup_future_usage: Some(api_enums::FutureUsage::OffSession),
         authentication_type: Some(api_enums::AuthenticationType::NoThreeDs),
         payment_method_data: Some(api::PaymentMethodData::Card(api::Card {
-            card_number: "5555 3412 4444 1115".to_string().into(),
+            card_number: "5555 3412 4444 1115".to_string().try_into().unwrap(),
             card_exp_month: "03".to_string().into(),
             card_exp_year: "2030".to_string().into(),
             card_holder_name: "JohnDoe".to_string().into(),

Fixes #606

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

- [ ] Bugfix
- [x] New feature
- [ ] Enhancement
- [ ] Refactoring
- [ ] Dependency updates

## Description
<!-- Describe your changes in detail -->
The PR adds a new crate called `cards`. Which currently just has a single module named validate which exposes the `CardNumber` struct as well as a `CCValError`.

The validation of a correct CC number is done via the Luhn Algorithm implemented in the `luhn` crate.

### Additional Changes

- [ ] 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 its an obvious bug or documentation fix
that will have little conversation).
-->
This PR address #606.

## 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)?
-->
Tests for successful and failing CC number validation have been added.


## 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 submitted code
- [x] I added unit tests for my changes where possible
- [ ] I added a [CHANGELOG](/CHANGELOG.md) entry if applicable
