From d6e71b959ddbdc99411fc7d669df61f373de4e32 Mon Sep 17 00:00:00 2001 From: phillyphil91 <57916112+phillyphil91@users.noreply.github.com> Date: Tue, 9 May 2023 16:30:50 +0200 Subject: [PATCH] feat(cards): add credit card number validation (#889) Co-authored-by: Sanchith Hegde --- Cargo.lock | 23 ++- connector-template/test.rs | 23 --- connector-template/transformers.rs | 2 +- crates/api_models/Cargo.toml | 1 + crates/api_models/src/payment_methods.rs | 5 +- crates/api_models/src/payments.rs | 5 +- crates/cards/Cargo.toml | 4 +- crates/cards/src/lib.rs | 3 + crates/cards/src/validate.rs | 143 ++++++++++++++++++ crates/common_utils/src/pii.rs | 33 +--- crates/router/Cargo.toml | 1 + .../stripe/payment_intents/types.rs | 2 +- .../stripe/setup_intents/types.rs | 2 +- .../router/src/connector/aci/transformers.rs | 2 +- .../src/connector/adyen/transformers.rs | 7 +- .../src/connector/airwallex/transformers.rs | 8 +- .../connector/authorizedotnet/transformers.rs | 6 +- .../src/connector/bambora/transformers.rs | 2 +- .../src/connector/bluesnap/transformers.rs | 4 +- .../src/connector/braintree/transformers.rs | 2 +- .../src/connector/checkout/transformers.rs | 2 +- .../src/connector/cybersource/transformers.rs | 2 +- .../src/connector/dlocal/transformers.rs | 4 +- .../connector/dummyconnector/transformers.rs | 2 +- .../src/connector/fiserv/transformers.rs | 9 +- .../src/connector/forte/transformers.rs | 4 +- .../src/connector/globalpay/requests.rs | 3 +- .../connector/multisafepay/transformers.rs | 4 +- .../src/connector/nexinets/transformers.rs | 3 +- .../src/connector/nuvei/transformers.rs | 2 +- .../src/connector/payeezy/transformers.rs | 4 +- .../src/connector/paypal/transformers.rs | 4 +- .../router/src/connector/payu/transformers.rs | 4 +- .../src/connector/rapyd/transformers.rs | 4 +- .../src/connector/shift4/transformers.rs | 5 +- .../src/connector/stripe/transformers.rs | 2 +- .../src/connector/trustpay/transformers.rs | 3 +- crates/router/src/connector/utils.rs | 6 +- .../src/connector/worldline/transformers.rs | 9 +- .../router/src/connector/worldpay/requests.rs | 3 +- .../router/src/connector/zen/transformers.rs | 4 +- .../router/src/core/payment_methods/cards.rs | 28 ++-- .../src/core/payment_methods/transformers.rs | 12 +- .../router/src/core/payment_methods/vault.rs | 7 +- crates/router/src/lib.rs | 2 +- .../src/routes/dummy_connector/types.rs | 2 +- .../src/routes/dummy_connector/utils.rs | 4 +- crates/router/src/services/api.rs | 12 +- crates/router/src/types/api/payments.rs | 2 +- crates/router/tests/connectors/aci.rs | 6 +- crates/router/tests/connectors/adyen.rs | 27 +--- crates/router/tests/connectors/airwallex.rs | 27 +--- .../tests/connectors/authorizedotnet.rs | 6 +- crates/router/tests/connectors/bambora.rs | 33 +--- crates/router/tests/connectors/bluesnap.rs | 29 +--- crates/router/tests/connectors/checkout.rs | 26 +--- crates/router/tests/connectors/coinbase.rs | 27 +--- crates/router/tests/connectors/cybersource.rs | 20 +-- crates/router/tests/connectors/dlocal.rs | 25 +-- .../router/tests/connectors/dummyconnector.rs | 28 +--- crates/router/tests/connectors/fiserv.rs | 27 +--- crates/router/tests/connectors/forte.rs | 30 +--- crates/router/tests/connectors/globalpay.rs | 5 +- crates/router/tests/connectors/main.rs | 7 +- .../router/tests/connectors/multisafepay.rs | 24 +-- crates/router/tests/connectors/nexinets.rs | 30 +--- crates/router/tests/connectors/nuvei.rs | 31 +--- crates/router/tests/connectors/opennode.rs | 27 +--- crates/router/tests/connectors/payeezy.rs | 28 +--- crates/router/tests/connectors/paypal.rs | 29 +--- crates/router/tests/connectors/rapyd.rs | 8 +- crates/router/tests/connectors/shift4.rs | 27 +--- crates/router/tests/connectors/stripe.rs | 28 +--- crates/router/tests/connectors/trustpay.rs | 32 +--- crates/router/tests/connectors/utils.rs | 4 +- crates/router/tests/connectors/worldline.rs | 4 +- crates/router/tests/connectors/zen.rs | 32 +--- crates/router/tests/payments.rs | 4 +- crates/router/tests/payments2.rs | 4 +- 79 files changed, 381 insertions(+), 684 deletions(-) create mode 100644 crates/cards/src/validate.rs diff --git a/Cargo.lock b/Cargo.lock index 82cc4015a5..3ef85ac8f6 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 ce75612143..9885ccf67c 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 7e3caf100e..3a4f5c5e3a 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, - number: Secret, + number: cards::CardNumber, expiry_month: Secret, expiry_year: Secret, cvc: Secret, diff --git a/crates/api_models/Cargo.toml b/crates/api_models/Cargo.toml index f1824e41be..c11e9cebde 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 91b1affb1d..a171b08d6e 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, + pub card_number: CardNumber, /// Card Expiry Month #[schema(value_type = String,example = "10")] @@ -142,7 +143,7 @@ pub struct CardDetailFromLocker { pub last4_digits: Option, #[serde(skip)] #[schema(value_type=Option)] - pub card_number: Option>, + pub card_number: Option, #[schema(value_type=Option)] pub expiry_month: Option>, diff --git a/crates/api_models/src/payments.rs b/crates/api_models/src/payments.rs index b2834c078e..57dd2b0076 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, + 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, + card_number: CardNumber, /// The card's expiry month #[schema(value_type = String, example = "24")] card_exp_month: Secret, diff --git a/crates/cards/Cargo.toml b/crates/cards/Cargo.toml index 7971726c9a..4b05bc4948 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 00bd0578c3..d8aedc36e1 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); diff --git a/crates/cards/src/validate.rs b/crates/cards/src/validate.rs new file mode 100644 index 0000000000..6fcb5e1180 --- /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 for CCValError { + fn from(_: core::convert::Infallible) -> Self { + Self + } +} + +/// Card number +#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize)] +pub struct CardNumber(StrongSecret); + +impl FromStr for CardNumber { + type Err = CCValError; + + fn from_str(s: &str) -> Result { + 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 for CardNumber { + type Error = CCValError; + + fn try_from(value: String) -> Result { + Self::from_str(&value) + } +} + +impl Deref for CardNumber { + type Target = StrongSecret; + + fn deref(&self) -> &StrongSecret { + &self.0 + } +} + +impl<'de> Deserialize<'de> for CardNumber { + fn deserialize>(d: D) -> Result { + let s = String::deserialize(d)?; + Self::from_str(&s).map_err(serde::de::Error::custom) + } +} + +pub struct CardNumberStrategy; + +impl Strategy for CardNumberStrategy +where + T: AsRef, +{ + 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 = + Secret::new("1234567890987654".to_string()); + assert_eq!("123456**********", format!("{secret:?}")); + } + + #[test] + fn test_invalid_card_number_masking() { + let secret: Secret = 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::(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::(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 d4c4571659..24d72f2b37 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; -/// Card number -#[derive(Debug)] -pub struct CardNumber; - -impl Strategy for CardNumber -where - T: AsRef, -{ - 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 = Secret::new("1234567890987654".to_string()); - assert_eq!("123456**********", format!("{secret:?}")); - } - - #[test] - fn test_invalid_card_number_masking() { - let secret: Secret = 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 e4a9a25efc..88fcf92d38 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 eaaf82b1f0..8c2796b434 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 for payments::Address { #[derive(Default, Serialize, PartialEq, Eq, Deserialize, Clone)] pub struct StripeCard { - pub number: pii::Secret, + pub number: cards::CardNumber, pub exp_month: pii::Secret, pub exp_year: pii::Secret, pub cvc: pii::Secret, diff --git a/crates/router/src/compatibility/stripe/setup_intents/types.rs b/crates/router/src/compatibility/stripe/setup_intents/types.rs index 645729d083..1bc7f3fb85 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 for payments::Address { #[derive(Default, Serialize, PartialEq, Eq, Deserialize, Clone)] pub struct StripeCard { - pub number: pii::Secret, + pub number: cards::CardNumber, pub exp_month: pii::Secret, pub exp_year: pii::Secret, pub cvc: pii::Secret, diff --git a/crates/router/src/connector/aci/transformers.rs b/crates/router/src/connector/aci/transformers.rs index acb1784929..fad1ffed0d 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, + pub card_number: cards::CardNumber, #[serde(rename = "card.holder")] pub card_holder: Secret, #[serde(rename = "card.expiryMonth")] diff --git a/crates/router/src/connector/adyen/transformers.rs b/crates/router/src/connector/adyen/transformers.rs index 199ab239a3..5dc6f7d5ba 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, @@ -301,7 +302,7 @@ pub struct BancontactCardData { #[serde(rename = "type")] payment_type: PaymentType, brand: String, - number: Secret, + number: CardNumber, expiry_month: Secret, expiry_year: Secret, holder_name: Secret, @@ -521,7 +522,7 @@ pub struct AdyenMandate { pub struct AdyenCard { #[serde(rename = "type")] payment_type: PaymentType, - number: Secret, + number: CardNumber, expiry_month: Secret, expiry_year: Secret, cvc: Option>, diff --git a/crates/router/src/connector/airwallex/transformers.rs b/crates/router/src/connector/airwallex/transformers.rs index 86831e592c..ca3df4aff9 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, expiry_year: Secret, - number: Secret, + number: cards::CardNumber, cvc: Secret, } @@ -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 0c93ba198f..1c3ec89156 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, + card_number: masking::StrongSecret, expiration_date: masking::Secret, #[serde(skip_serializing_if = "Option::is_none")] card_code: Option>, @@ -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 443e703e66..14ce731627 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, - number: Secret, + number: cards::CardNumber, expiry_month: Secret, expiry_year: Secret, cvd: Secret, diff --git a/crates/router/src/connector/bluesnap/transformers.rs b/crates/router/src/connector/bluesnap/transformers.rs index aef423be6e..dd538e929a 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, + card_number: cards::CardNumber, expiration_month: Secret, expiration_year: Secret, security_code: Secret, diff --git a/crates/router/src/connector/braintree/transformers.rs b/crates/router/src/connector/braintree/transformers.rs index dd9c03dafe..b5e81097ca 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, + number: cards::CardNumber, expiration_month: Secret, expiration_year: Secret, cvv: Secret, diff --git a/crates/router/src/connector/checkout/transformers.rs b/crates/router/src/connector/checkout/transformers.rs index 2e9a8f2b82..98c24dcc3c 100644 --- a/crates/router/src/connector/checkout/transformers.rs +++ b/crates/router/src/connector/checkout/transformers.rs @@ -97,7 +97,7 @@ impl pub struct CardSource { #[serde(rename = "type")] pub source_type: CheckoutSourceTypes, - pub number: pii::Secret, + pub number: cards::CardNumber, pub expiry_month: pii::Secret, pub expiry_year: pii::Secret, pub cvv: pii::Secret, diff --git a/crates/router/src/connector/cybersource/transformers.rs b/crates/router/src/connector/cybersource/transformers.rs index a72d00ab41..3ca45f84c2 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, + number: cards::CardNumber, expiration_month: Secret, expiration_year: Secret, security_code: Secret, diff --git a/crates/router/src/connector/dlocal/transformers.rs b/crates/router/src/connector/dlocal/transformers.rs index f33b0b43c2..8e084635f0 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, - pub number: Secret, + pub number: cards::CardNumber, pub cvv: Secret, pub expiration_month: Secret, pub expiration_year: Secret, diff --git a/crates/router/src/connector/dummyconnector/transformers.rs b/crates/router/src/connector/dummyconnector/transformers.rs index e55664a6aa..8840429020 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, - number: Secret, + number: cards::CardNumber, expiry_month: Secret, expiry_year: Secret, cvc: Secret, diff --git a/crates/router/src/connector/fiserv/transformers.rs b/crates/router/src/connector/fiserv/transformers.rs index b52f5d259b..a02bf4cc4e 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, + card_data: cards::CardNumber, expiration_month: Secret, expiration_year: Secret, security_code: Secret, @@ -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 a806d2af94..415aae14df 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, - account_number: Secret, + account_number: CardNumber, expire_month: Secret, expire_year: Secret, card_verification_value: Secret, diff --git a/crates/router/src/connector/globalpay/requests.rs b/crates/router/src/connector/globalpay/requests.rs index 46ca9c7255..2f06c12137 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, /// The the card account number used to authorize the transaction. Also known as PAN. - pub number: Secret, + pub number: cards::CardNumber, /// Contains the pin block info, relating to the pin code the Payer entered. pub pin_block: Option, /// 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 7f60c70c2f..0b060a5c46 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>, + pub card_number: Option, pub card_holder_name: Option>, pub card_expiry_date: Option, pub card_cvc: Option>, diff --git a/crates/router/src/connector/nexinets/transformers.rs b/crates/router/src/connector/nexinets/transformers.rs index 05655430a6..13a2060355 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, + card_number: CardNumber, expiry_month: Secret, expiry_year: Secret, verification: Secret, diff --git a/crates/router/src/connector/nuvei/transformers.rs b/crates/router/src/connector/nuvei/transformers.rs index 4fc70bba81..fdf79c5da4 100644 --- a/crates/router/src/connector/nuvei/transformers.rs +++ b/crates/router/src/connector/nuvei/transformers.rs @@ -197,7 +197,7 @@ pub struct BillingAddress { #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Card { - pub card_number: Option>, + pub card_number: Option, pub card_holder_name: Option>, pub expiration_month: Option>, pub expiration_year: Option>, diff --git a/crates/router/src/connector/payeezy/transformers.rs b/crates/router/src/connector/payeezy/transformers.rs index 29c15b5672..5c01be19ae 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, - pub card_number: Secret, + pub card_number: CardNumber, pub exp_date: Secret, pub cvv: Secret, } diff --git a/crates/router/src/connector/paypal/transformers.rs b/crates/router/src/connector/paypal/transformers.rs index c1115a5243..75ae059855 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
, expiry: Option>, name: Secret, - number: Option>, + number: Option, security_code: Option>, } diff --git a/crates/router/src/connector/payu/transformers.rs b/crates/router/src/connector/payu/transformers.rs index 7e7cc8abf4..d141a01843 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, + number: cards::CardNumber, expiration_month: Secret, expiration_year: Secret, cvv: Secret, diff --git a/crates/router/src/connector/rapyd/transformers.rs b/crates/router/src/connector/rapyd/transformers.rs index 63a0075515..f112456ae5 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, + pub number: cards::CardNumber, pub expiration_month: Secret, pub expiration_year: Secret, pub name: Secret, diff --git a/crates/router/src/connector/shift4/transformers.rs b/crates/router/src/connector/shift4/transformers.rs index 6931a91d1e..75c3ca7887 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, + pub card_number: CardNumber, #[serde(rename = "card[expMonth]")] pub card_exp_month: Secret, #[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, + pub number: CardNumber, pub exp_month: Secret, pub exp_year: Secret, pub cardholder_name: Secret, diff --git a/crates/router/src/connector/stripe/transformers.rs b/crates/router/src/connector/stripe/transformers.rs index 62e88e918e..f50337403e 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, + pub payment_method_data_card_number: cards::CardNumber, #[serde(rename = "payment_method_data[card][exp_month]")] pub payment_method_data_card_exp_month: Secret, #[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 1a11e39d79..3b437771b0 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, + pub pan: cards::CardNumber, pub cvv: Secret, #[serde(rename = "exp")] pub expiry_date: Secret, diff --git a/crates/router/src/connector/utils.rs b/crates/router/src/connector/utils.rs index e11ecbc467..63776c39bb 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 { - let card: Secret = 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 f6aab824a7..74f678b287 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, + pub card_number: cards::CardNumber, pub cardholder_name: Secret, pub cvv: Secret, pub expiry_date: Secret, @@ -152,10 +152,7 @@ fn make_card_request( ); let expiry_date: Secret = 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 d4d2f6121d..5d6fdeb510 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>, #[serde(rename = "type")] pub payment_type: PaymentType, - pub card_number: Secret, + 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 c8de11c556..7cfdac52a0 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, + number: CardNumber, expiry_date: Secret, cvv: Secret, } diff --git a/crates/router/src/core/payment_methods/cards.rs b/crates/router/src/core/payment_methods/cards.rs index a662145b47..ff99a5c4d5 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 { - 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 { - 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 a12070f7fa..d4751a7d08 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, + pub card_number: cards::CardNumber, pub name_on_card: Option>, pub card_exp_month: Secret, pub card_exp_year: Secret, @@ -80,7 +80,7 @@ pub struct DeleteCardResp { #[derive(Debug, Deserialize, Serialize)] #[serde(rename_all = "camelCase")] pub struct AddCardRequest<'a> { - pub card_number: Secret, + pub card_number: cards::CardNumber, pub customer_id: &'a str, pub card_exp_month: Secret, pub card_exp_year: Secret, @@ -99,7 +99,7 @@ pub struct AddCardResponse { pub card_global_fingerprint: Secret, #[serde(rename = "merchant_id")] pub merchant_id: Option, - pub card_number: Option>, + pub card_number: Option, pub card_exp_year: Option>, pub card_exp_month: Option>, pub name_on_card: Option>, @@ -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, @@ -639,7 +639,7 @@ pub fn mk_card_value1( card_token: Option, ) -> CustomResult { 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 02fe7359e6..10cca24d18 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 bf20ef67e4..fb2ea5b073 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 5685c6eb99..c66fa13d1a 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, - pub number: Secret, + pub number: cards::CardNumber, pub expiry_month: Secret, pub expiry_year: Secret, pub cvc: Secret, diff --git a/crates/router/src/routes/dummy_connector/utils.rs b/crates/router/src/routes/dummy_connector/utils.rs index a510a14685..f218833192 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 ff2d10ddd4..fb61feeedf 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!("