From 1d18cce9c8b8ae465b70d9662cb6000de31f7385 Mon Sep 17 00:00:00 2001 From: Sk Sakil Mostak Date: Tue, 3 Dec 2024 19:53:55 +0530 Subject: [PATCH 01/19] feat: add card_holder_name validation --- crates/cards/src/lib.rs | 42 ++++++++++++++ crates/router/src/core/payments/helpers.rs | 58 +++++++++++++++++++ .../payments/operations/payment_confirm.rs | 8 +++ .../payments/operations/payment_create.rs | 7 +++ .../payments/operations/payment_update.rs | 7 +++ 5 files changed, 122 insertions(+) diff --git a/crates/cards/src/lib.rs b/crates/cards/src/lib.rs index 91cb93301a9..e65f03becfb 100644 --- a/crates/cards/src/lib.rs +++ b/crates/cards/src/lib.rs @@ -67,6 +67,48 @@ impl<'de> Deserialize<'de> for CardExpirationMonth { } } +#[derive(Serialize)] +pub struct CardHolderName(StrongSecret); + +impl TryFrom for CardHolderName { + type Error = error_stack::Report; + fn try_from(card_holder_name: String) -> Result { + for char in card_holder_name.chars() { + validate_character_in_card_holder_name(char)?; + } + Ok(Self(StrongSecret::new(card_holder_name))) + } +} + +fn validate_character_in_card_holder_name( + charcter: char, +) -> Result<(), error_stack::Report> { + if charcter.is_alphabetic() + || charcter == ' ' + || charcter == '.' + || charcter == '-' + || charcter == '\'' + || charcter == '~' + || charcter == '`' + { + Ok(()) + } else { + Err(report!(errors::ValidationError::InvalidValue { + message: "invalid charcter in card holder name".to_string() + })) + } +} + +impl<'de> Deserialize<'de> for CardHolderName { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let card_holder_name = String::deserialize(deserializer)?; + card_holder_name.try_into().map_err(de::Error::custom) + } +} + #[derive(Serialize)] pub struct CardExpirationYear(StrongSecret); diff --git a/crates/router/src/core/payments/helpers.rs b/crates/router/src/core/payments/helpers.rs index e7de03804d1..f15ba01c2ef 100644 --- a/crates/router/src/core/payments/helpers.rs +++ b/crates/router/src/core/payments/helpers.rs @@ -995,10 +995,48 @@ pub fn validate_card_data( )?; validate_card_expiry(&card.card_exp_month, &card.card_exp_year)?; + validate_card_holder_name(&card.card_holder_name)?; } Ok(()) } +pub fn validate_billing_name( + billing_address: Option<&api_models::payments::AddressDetails>, +) -> CustomResult<(), errors::ApiErrorResponse> { + let optional_first_name = billing_address.and_then(|address| address.first_name.clone()); + let optional_last_name = billing_address.and_then(|address| address.last_name.clone()); + + if let Some(first_name) = optional_first_name { + let first_name = first_name.peek().to_string(); + if first_name.len() > 256 { + Err(report!(errors::ApiErrorResponse::PreconditionFailed { + message: "Invalid First Name Length".to_string() + }))? + } + ::cards::CardHolderName::try_from(first_name).change_context( + errors::ApiErrorResponse::PreconditionFailed { + message: "Invalid First Name".to_string(), + }, + )?; + } + + if let Some(last_name) = optional_last_name { + let last_name = last_name.peek().to_string(); + if last_name.len() > 256 { + Err(report!(errors::ApiErrorResponse::PreconditionFailed { + message: "Invalid Last Name Length".to_string() + }))? + } + ::cards::CardHolderName::try_from(last_name).change_context( + errors::ApiErrorResponse::PreconditionFailed { + message: "Invalid Last Name".to_string(), + }, + )?; + } + + Ok(()) +} + #[instrument(skip_all)] pub fn validate_card_expiry( card_exp_month: &masking::Secret, @@ -1048,6 +1086,26 @@ pub fn validate_card_expiry( Ok(()) } +pub fn validate_card_holder_name( + optional_card_holder_name: &Option>, +) -> CustomResult<(), errors::ApiErrorResponse> { + if let Some(masked_card_holder_name) = optional_card_holder_name { + let card_holder_name = masked_card_holder_name.peek().to_string(); + if card_holder_name.len() > 256 { + Err(report!(errors::ApiErrorResponse::PreconditionFailed { + message: "Invalid Card Holder Name Length".to_string() + }))? + } + // validate card holder name + ::cards::CardHolderName::try_from(card_holder_name).change_context( + errors::ApiErrorResponse::PreconditionFailed { + message: "Invalid Card Holder Name".to_string(), + }, + )?; + } + Ok(()) +} + pub fn infer_payment_type( amount: &api::Amount, mandate_type: Option<&api::MandateTransactionType>, diff --git a/crates/router/src/core/payments/operations/payment_confirm.rs b/crates/router/src/core/payments/operations/payment_confirm.rs index b56260b407e..5ed69decc00 100644 --- a/crates/router/src/core/payments/operations/payment_confirm.rs +++ b/crates/router/src/core/payments/operations/payment_confirm.rs @@ -388,6 +388,14 @@ impl GetTracker, api::PaymentsRequest> for Pa .and_then(|pmd| pmd.payment_method_data.clone()), )?; + // validate billing name for card holder name + helpers::validate_billing_name( + request + .billing + .as_ref() + .and_then(|billing| billing.address.as_ref()), + )?; + payment_attempt.browser_info = browser_info; payment_attempt.payment_experience = request diff --git a/crates/router/src/core/payments/operations/payment_create.rs b/crates/router/src/core/payments/operations/payment_create.rs index 697c06603da..bcdd5fe17cc 100644 --- a/crates/router/src/core/payments/operations/payment_create.rs +++ b/crates/router/src/core/payments/operations/payment_create.rs @@ -985,6 +985,13 @@ impl ValidateRequest> f .as_ref() .and_then(|pmd| pmd.payment_method_data.clone()), )?; + // validate billing name for card holder name + helpers::validate_billing_name( + request + .billing + .as_ref() + .and_then(|billing| billing.address.as_ref()), + )?; helpers::validate_payment_method_fields_present(request)?; diff --git a/crates/router/src/core/payments/operations/payment_update.rs b/crates/router/src/core/payments/operations/payment_update.rs index 98491cab1db..0a9f5666dcb 100644 --- a/crates/router/src/core/payments/operations/payment_update.rs +++ b/crates/router/src/core/payments/operations/payment_update.rs @@ -100,6 +100,13 @@ impl GetTracker, api::PaymentsRequest> for Pa .as_ref() .and_then(|pmd| pmd.payment_method_data.clone()), )?; + // validate billing name for card holder name + helpers::validate_billing_name( + request + .billing + .as_ref() + .and_then(|billing| billing.address.as_ref()), + )?; helpers::validate_payment_status_against_allowed_statuses( &payment_intent.status, From 6bfa78e182265a7a5082edc65621939f4fc6ad46 Mon Sep 17 00:00:00 2001 From: Sk Sakil Mostak Date: Tue, 3 Dec 2024 20:08:24 +0530 Subject: [PATCH 02/19] refactor: spell check --- crates/cards/src/lib.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/crates/cards/src/lib.rs b/crates/cards/src/lib.rs index e65f03becfb..d156a8121c3 100644 --- a/crates/cards/src/lib.rs +++ b/crates/cards/src/lib.rs @@ -81,20 +81,20 @@ impl TryFrom for CardHolderName { } fn validate_character_in_card_holder_name( - charcter: char, + character: char, ) -> Result<(), error_stack::Report> { - if charcter.is_alphabetic() - || charcter == ' ' - || charcter == '.' - || charcter == '-' - || charcter == '\'' - || charcter == '~' - || charcter == '`' + if character.is_alphabetic() + || character == ' ' + || character == '.' + || character == '-' + || character == '\'' + || character == '~' + || character == '`' { Ok(()) } else { Err(report!(errors::ValidationError::InvalidValue { - message: "invalid charcter in card holder name".to_string() + message: "invalid character in card holder name".to_string() })) } } From 8d5c164b2021a63430941d5e8974ce1e43344d67 Mon Sep 17 00:00:00 2001 From: Sk Sakil Mostak Date: Wed, 4 Dec 2024 15:48:41 +0530 Subject: [PATCH 03/19] feat: add unit test cases --- crates/cards/src/lib.rs | 7 +++++++ crates/cards/tests/basic.rs | 29 ++++++++++++++++++++++++++--- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/crates/cards/src/lib.rs b/crates/cards/src/lib.rs index d156a8121c3..f231234f6ce 100644 --- a/crates/cards/src/lib.rs +++ b/crates/cards/src/lib.rs @@ -230,3 +230,10 @@ impl Deref for CardExpirationYear { &self.0 } } + +impl Deref for CardHolderName { + type Target = StrongSecret; + fn deref(&self) -> &Self::Target { + &self.0 + } +} diff --git a/crates/cards/tests/basic.rs b/crates/cards/tests/basic.rs index 0f27c9e0288..22239aaaacf 100644 --- a/crates/cards/tests/basic.rs +++ b/crates/cards/tests/basic.rs @@ -1,6 +1,8 @@ #![allow(clippy::unwrap_used, clippy::expect_used)] -use cards::{CardExpiration, CardExpirationMonth, CardExpirationYear, CardSecurityCode}; +use cards::{ + CardExpiration, CardExpirationMonth, CardExpirationYear, CardHolderName, CardSecurityCode, +}; use common_utils::date_time; use masking::PeekInterface; @@ -42,6 +44,27 @@ fn test_card_expiration_month() { assert!(invalid_deserialization.is_err()); } +#[test] +fn test_card_holder_name() { + // no panic + let card_holder_name = CardHolderName::try_from("Sakil O'Neil".to_string()).unwrap(); + + // will panic on unwrap + let invalid_card_holder_name = CardHolderName::try_from("$@k!l M*$t@k".to_string()); + + assert_eq!(*card_holder_name.peek(), "Sakil O'Neil"); + assert!(invalid_card_holder_name.is_err()); + + let serialized = serde_json::to_string(&card_holder_name).unwrap(); + assert_eq!(&serialized, "\"Sakil O'Neil\""); + + let derialized = serde_json::from_str::(&serialized).unwrap(); + assert_eq!(*derialized.peek(), "Sakil O'Neil".to_string()); + + let invalid_deserialization = serde_json::from_str::("$@k!l M*$t@k"); + assert!(invalid_deserialization.is_err()); +} + #[test] fn test_card_expiration_year() { let curr_date = date_time::now(); @@ -85,11 +108,11 @@ fn test_card_expiration() { assert!(invalid_card_exp.is_err()); let serialized = serde_json::to_string(&card_exp).unwrap(); - let expected_string = format!(r#"{{"month":{},"year":{}}}"#, 3, curr_year); + let expected_string = format!(r#"{{"month":{},"year":{}}}"#, curr_month, curr_year); assert_eq!(serialized, expected_string); let derialized = serde_json::from_str::(&serialized).unwrap(); - assert_eq!(*derialized.get_month().peek(), 3); + assert_eq!(*derialized.get_month().peek(), curr_month); assert_eq!(*derialized.get_year().peek(), curr_year); let invalid_serialized_string = r#"{"month":13,"year":123}"#; From 0793d2b0f131bb3cec43a7423b9ef630632e403f Mon Sep 17 00:00:00 2001 From: Sk Sakil Mostak Date: Wed, 4 Dec 2024 16:33:18 +0530 Subject: [PATCH 04/19] refactor: use unified billing address for payment confirm test --- .../payments/operations/payment_confirm.rs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/crates/router/src/core/payments/operations/payment_confirm.rs b/crates/router/src/core/payments/operations/payment_confirm.rs index 5ed69decc00..d84c041f744 100644 --- a/crates/router/src/core/payments/operations/payment_confirm.rs +++ b/crates/router/src/core/payments/operations/payment_confirm.rs @@ -388,14 +388,6 @@ impl GetTracker, api::PaymentsRequest> for Pa .and_then(|pmd| pmd.payment_method_data.clone()), )?; - // validate billing name for card holder name - helpers::validate_billing_name( - request - .billing - .as_ref() - .and_then(|billing| billing.address.as_ref()), - )?; - payment_attempt.browser_info = browser_info; payment_attempt.payment_experience = request @@ -718,6 +710,17 @@ impl GetTracker, api::PaymentsRequest> for Pa payment_method_data_billing.get_billing_address() }); + // validate billing name for card holder name + helpers::validate_billing_name( + payment_method_data_billing + .as_ref() + .and_then(|billing| billing.address.as_ref()) + .or(request + .billing + .as_ref() + .and_then(|billing| billing.address.as_ref())), + )?; + let unified_address = address.unify_with_payment_method_data_billing(payment_method_data_billing); From 8cadc2f1e6e25e150930fb7091c19da9a74b4621 Mon Sep 17 00:00:00 2001 From: Sk Sakil Mostak Date: Wed, 4 Dec 2024 17:58:43 +0530 Subject: [PATCH 05/19] refactor: resolve ci checks --- .../src/core/payments/operations/payment_confirm.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/crates/router/src/core/payments/operations/payment_confirm.rs b/crates/router/src/core/payments/operations/payment_confirm.rs index d84c041f744..dfc15bdc040 100644 --- a/crates/router/src/core/payments/operations/payment_confirm.rs +++ b/crates/router/src/core/payments/operations/payment_confirm.rs @@ -7,7 +7,9 @@ use api_models::{ admin::ExtendedCardInfoConfig, enums::FrmSuggestion, // payment_methods::PaymentMethodsData, - payments::{ConnectorMandateReferenceId, ExtendedCardInfo, GetAddressFromPaymentMethodData}, + payments::{ + Address, ConnectorMandateReferenceId, ExtendedCardInfo, GetAddressFromPaymentMethodData, + }, }; use async_trait::async_trait; use common_utils::ext_traits::{AsyncExt, Encode, StringExt, ValueExt}; @@ -714,11 +716,11 @@ impl GetTracker, api::PaymentsRequest> for Pa helpers::validate_billing_name( payment_method_data_billing .as_ref() - .and_then(|billing| billing.address.as_ref()) + .and_then(|billing: &Address| billing.address.as_ref()) .or(request .billing .as_ref() - .and_then(|billing| billing.address.as_ref())), + .and_then(|billing: &Address| billing.address.as_ref())), )?; let unified_address = From 62b63b6c3acd5325b7eb402f845486c687ba0a58 Mon Sep 17 00:00:00 2001 From: Sk Sakil Mostak Date: Sun, 15 Dec 2024 22:07:59 +0530 Subject: [PATCH 06/19] feat: add nametype and implement in domain crate --- crates/api_models/src/customers.rs | 3 +- crates/api_models/src/mandates.rs | 9 +- crates/api_models/src/payment_methods.rs | 47 ++++---- crates/api_models/src/payments.rs | 82 +++++++------ .../src/payments/additional_info.rs | 15 +-- crates/api_models/src/payouts.rs | 4 +- crates/cards/src/lib.rs | 51 +------- crates/cards/src/validate.rs | 114 +++++++++++++++++- crates/cards/tests/basic.rs | 25 +--- crates/common_utils/src/types.rs | 52 +++++++- .../src/connectors/worldline/transformers.rs | 10 +- crates/hyperswitch_connectors/src/utils.rs | 43 +++---- .../hyperswitch_domain_models/src/address.rs | 15 ++- .../src/payment_method_data.rs | 21 ++-- .../src/router_data.rs | 3 +- .../src/router_request_types/fraud_check.rs | 3 +- .../compatibility/stripe/customers/types.rs | 3 +- .../stripe/payment_intents/types.rs | 5 +- .../stripe/setup_intents/types.rs | 3 +- .../adyenplatform/transformers/payouts.rs | 3 +- .../src/connector/mifinity/transformers.rs | 5 +- .../connector/netcetera/netcetera_types.rs | 13 +- .../connector/riskified/transformers/api.rs | 9 +- .../connector/signifyd/transformers/api.rs | 3 +- .../connector/stripe/transformers/connect.rs | 5 +- crates/router/src/connector/utils.rs | 19 +-- crates/router/src/core/customers.rs | 5 +- crates/router/src/core/locker_migration.rs | 2 +- crates/router/src/core/payment_methods.rs | 3 +- .../router/src/core/payment_methods/cards.rs | 30 +++-- .../src/core/payment_methods/transformers.rs | 18 ++- .../router/src/core/payment_methods/vault.rs | 11 +- crates/router/src/core/payments/helpers.rs | 98 ++++----------- .../payments/operations/payment_confirm.rs | 15 +-- .../payments/operations/payment_create.rs | 7 -- .../payments/operations/payment_update.rs | 7 -- .../router/src/core/payments/tokenization.rs | 3 +- crates/router/src/core/payouts/helpers.rs | 10 +- crates/router/src/core/utils.rs | 28 ++++- crates/router/src/types/transformers.rs | 91 +++++++++++++- crates/router/src/utils.rs | 42 +++++-- 41 files changed, 557 insertions(+), 378 deletions(-) diff --git a/crates/api_models/src/customers.rs b/crates/api_models/src/customers.rs index 4f6411a42cd..0b2a8122ac5 100644 --- a/crates/api_models/src/customers.rs +++ b/crates/api_models/src/customers.rs @@ -1,3 +1,4 @@ +use cards::NameType; use common_utils::{crypto, custom_serde, id_type, pii, types::Description}; use masking::Secret; use serde::{Deserialize, Serialize}; @@ -18,7 +19,7 @@ pub struct CustomerRequest { pub merchant_id: id_type::MerchantId, /// The customer's name #[schema(max_length = 255, value_type = Option, example = "Jon Test")] - pub name: Option>, + pub name: Option, /// The customer's email address #[schema(value_type = Option, max_length = 255, example = "JonTest@test.com")] pub email: Option, diff --git a/crates/api_models/src/mandates.rs b/crates/api_models/src/mandates.rs index 2d61a630988..ea4a257f73f 100644 --- a/crates/api_models/src/mandates.rs +++ b/crates/api_models/src/mandates.rs @@ -1,3 +1,4 @@ +use cards::NameType; use masking::Secret; use serde::{Deserialize, Serialize}; use time::PrimitiveDateTime; @@ -57,7 +58,7 @@ pub struct MandateCardDetails { pub card_exp_year: Option>, /// The card holder name #[schema(value_type = Option)] - pub card_holder_name: Option>, + pub card_holder_name: Option, /// The token from card locker #[schema(value_type = Option)] pub card_token: Option>, @@ -79,7 +80,7 @@ pub struct MandateCardDetails { pub card_type: Option, /// The nick_name of the card holder #[schema(value_type = Option)] - pub nick_name: Option>, + pub nick_name: Option, } #[derive(Clone, Debug, Deserialize, ToSchema, Serialize)] @@ -151,7 +152,7 @@ pub struct NetworkTransactionIdAndCardDetails { /// The card holder's name #[schema(value_type = String, example = "John Test")] - pub card_holder_name: Option>, + pub card_holder_name: Option, /// The name of the issuer of card #[schema(example = "chase")] @@ -172,7 +173,7 @@ pub struct NetworkTransactionIdAndCardDetails { /// The card holder's nick name #[schema(value_type = Option, example = "John Test")] - pub nick_name: Option>, + pub nick_name: Option, /// The network transaction ID provided by the card network during a CIT (Customer Initiated Transaction), /// where `setup_future_usage` is set to `off_session`. diff --git a/crates/api_models/src/payment_methods.rs b/crates/api_models/src/payment_methods.rs index 283a0d662d7..57f18869ab9 100644 --- a/crates/api_models/src/payment_methods.rs +++ b/crates/api_models/src/payment_methods.rs @@ -2,7 +2,7 @@ use std::collections::{HashMap, HashSet}; #[cfg(all(feature = "v2", feature = "payment_methods_v2"))] use std::str::FromStr; -use cards::CardNumber; +use cards::{CardNumber, NameType}; use common_utils::{ consts::SURCHARGE_PERCENTAGE_PRECISION_LENGTH, crypto::OptionalEncryptableName, @@ -455,11 +455,11 @@ pub struct CardDetail { /// Card Holder Name #[schema(value_type = String,example = "John Doe")] - pub card_holder_name: Option>, + pub card_holder_name: Option, /// Card Holder's Nick Name #[schema(value_type = Option,example = "John Doe")] - pub nick_name: Option>, + pub nick_name: Option, /// Card Issuing Country pub card_issuing_country: Option, @@ -541,11 +541,11 @@ pub struct MigrateCardDetail { /// Card Holder Name #[schema(value_type = String,example = "John Doe")] - pub card_holder_name: Option>, + pub card_holder_name: Option, /// Card Holder's Nick Name #[schema(value_type = Option,example = "John Doe")] - pub nick_name: Option>, + pub nick_name: Option, /// Card Issuing Country pub card_issuing_country: Option, @@ -578,11 +578,11 @@ pub struct MigrateNetworkTokenData { /// Card Holder Name #[schema(value_type = String,example = "John Doe")] - pub card_holder_name: Option>, + pub card_holder_name: Option, /// Card Holder's Nick Name #[schema(value_type = Option,example = "John Doe")] - pub nick_name: Option>, + pub nick_name: Option, /// Card Issuing Country pub card_issuing_country: Option, @@ -625,11 +625,11 @@ pub struct CardDetailUpdate { /// Card Holder Name #[schema(value_type = String,example = "John Doe")] - pub card_holder_name: Option>, + pub card_holder_name: Option, /// Card Holder's Nick Name #[schema(value_type = Option,example = "John Doe")] - pub nick_name: Option>, + pub nick_name: Option, } #[cfg(all( @@ -652,10 +652,7 @@ impl CardDetailUpdate { .card_holder_name .clone() .or(card_data_from_locker.name_on_card), - nick_name: self - .nick_name - .clone() - .or(card_data_from_locker.nick_name.map(masking::Secret::new)), + nick_name: self.nick_name.clone().or(card_data_from_locker.nick_name), card_issuing_country: None, card_network: None, card_issuer: None, @@ -670,7 +667,7 @@ impl CardDetailUpdate { pub struct CardDetailUpdate { /// Card Holder Name #[schema(value_type = String,example = "John Doe")] - pub card_holder_name: Option>, + pub card_holder_name: Option, /// Card Holder's Nick Name #[schema(value_type = Option,example = "John Doe")] @@ -829,8 +826,8 @@ pub struct CardDetailsPaymentMethod { pub issuer_country: Option, pub expiry_month: Option>, pub expiry_year: Option>, - pub nick_name: Option>, - pub card_holder_name: Option>, + pub nick_name: Option, + pub card_holder_name: Option, pub card_isin: Option, pub card_issuer: Option, pub card_network: Option, @@ -903,12 +900,12 @@ pub enum BankAccountAccessCreds { #[derive(Debug, serde::Deserialize, serde::Serialize, Clone)] pub struct Card { pub card_number: CardNumber, - pub name_on_card: Option>, + pub name_on_card: Option, pub card_exp_month: masking::Secret, pub card_exp_year: masking::Secret, pub card_brand: Option, pub card_isin: Option, - pub nick_name: Option, + pub nick_name: Option, } #[cfg(all( @@ -934,13 +931,13 @@ pub struct CardDetailFromLocker { pub card_token: Option>, #[schema(value_type=Option)] - pub card_holder_name: Option>, + pub card_holder_name: Option, #[schema(value_type=Option)] pub card_fingerprint: Option>, #[schema(value_type=Option)] - pub nick_name: Option>, + pub nick_name: Option, #[schema(value_type = Option)] pub card_network: Option, @@ -968,7 +965,7 @@ pub struct CardDetailFromLocker { pub expiry_year: Option>, #[schema(value_type=Option)] - pub card_holder_name: Option>, + pub card_holder_name: Option, #[schema(value_type=Option)] pub card_fingerprint: Option>, @@ -2155,14 +2152,14 @@ pub struct TokenizedBankRedirectValue2 { #[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] pub struct PaymentMethodRecord { pub customer_id: id_type::CustomerId, - pub name: Option>, + pub name: Option, pub email: Option, pub phone: Option>, pub phone_country_code: Option, pub merchant_id: Option, pub payment_method: Option, pub payment_method_type: Option, - pub nick_name: masking::Secret, + pub nick_name: NameType, pub payment_instrument_id: Option>, pub card_number_masked: masking::Secret, pub card_expiry_month: masking::Secret, @@ -2171,8 +2168,8 @@ pub struct PaymentMethodRecord { pub original_transaction_id: Option, pub billing_address_zip: masking::Secret, pub billing_address_state: masking::Secret, - pub billing_address_first_name: masking::Secret, - pub billing_address_last_name: masking::Secret, + pub billing_address_first_name: NameType, + pub billing_address_last_name: NameType, pub billing_address_city: String, pub billing_address_country: Option, pub billing_address_line1: masking::Secret, diff --git a/crates/api_models/src/payments.rs b/crates/api_models/src/payments.rs index f46fd450bd4..a6a7079f33d 100644 --- a/crates/api_models/src/payments.rs +++ b/crates/api_models/src/payments.rs @@ -4,7 +4,7 @@ use std::{ num::NonZeroI64, }; pub mod additional_info; -use cards::CardNumber; +use cards::{CardNumber, NameType}; use common_enums::ProductType; #[cfg(feature = "v2")] use common_utils::id_type::GlobalPaymentId; @@ -1504,7 +1504,7 @@ pub struct Card { /// The card holder's name #[schema(value_type = String, example = "John Test")] - pub card_holder_name: Option>, + pub card_holder_name: Option, /// The CVC number for the card #[schema(value_type = String, example = "242")] @@ -1528,7 +1528,7 @@ pub struct Card { pub bank_code: Option, /// The card holder's nick name #[schema(value_type = Option, example = "John Test")] - pub nick_name: Option>, + pub nick_name: Option, } #[derive(Default, Eq, PartialEq, Clone, Debug, serde::Deserialize, serde::Serialize, ToSchema)] @@ -1547,7 +1547,7 @@ pub struct ExtendedCardInfo { /// The card holder's name #[schema(value_type = String, example = "John Test")] - pub card_holder_name: Option>, + pub card_holder_name: Option, /// The CVC number for the card #[schema(value_type = String, example = "242")] @@ -1606,13 +1606,15 @@ impl GetAddressFromPaymentMethodData for Card { let first_name = card_holder_name_iter .next() .map(ToOwned::to_owned) - .map(Secret::new); + .and_then(|name| { + NameType::try_from(name).ok() + }); let last_name = card_holder_name_iter.collect::>().join(" "); let last_name = if last_name.is_empty_after_trim() { None } else { - Some(Secret::new(last_name)) + NameType::try_from(last_name).ok() }; AddressDetails { @@ -1664,7 +1666,7 @@ impl Card { pub struct CardToken { /// The card holder's name #[schema(value_type = String, example = "John Test")] - pub card_holder_name: Option>, + pub card_holder_name: Option, /// The CVC number for the card #[schema(value_type = Option)] @@ -1706,7 +1708,7 @@ pub enum PayLaterData { billing_email: Option, /// The billing name #[schema(value_type = Option)] - billing_name: Option>, + billing_name: Option, }, /// For PayBright Redirect as PayLater Option PayBrightRedirect {}, @@ -1775,10 +1777,10 @@ pub enum BankDebitData { routing_number: Secret, #[schema(value_type = String, example = "John Test")] - card_holder_name: Option>, + card_holder_name: Option, #[schema(value_type = String, example = "John Doe")] - bank_account_holder_name: Option>, + bank_account_holder_name: Option, #[schema(value_type = String, example = "ACH")] bank_name: Option, @@ -1797,7 +1799,7 @@ pub enum BankDebitData { iban: Secret, /// Owner name for bank debit #[schema(value_type = String, example = "A. Schneider")] - bank_account_holder_name: Option>, + bank_account_holder_name: Option, }, BecsBankDebit { /// Billing details for bank debit @@ -1810,7 +1812,7 @@ pub enum BankDebitData { bsb_number: Secret, /// Owner name for bank debit #[schema(value_type = Option, example = "A. Schneider")] - bank_account_holder_name: Option>, + bank_account_holder_name: Option, }, BacsBankDebit { /// Billing details for bank debit @@ -1823,7 +1825,7 @@ pub enum BankDebitData { sort_code: Secret, /// holder name for bank debit #[schema(value_type = String, example = "A. Schneider")] - bank_account_holder_name: Option>, + bank_account_holder_name: Option, }, } @@ -1831,7 +1833,7 @@ impl GetAddressFromPaymentMethodData for BankDebitData { fn get_billing_address(&self) -> Option
{ fn get_billing_address_inner( bank_debit_billing: Option<&BankDebitBilling>, - bank_account_holder_name: Option<&Secret>, + bank_account_holder_name: Option<&NameType>, ) -> Option
{ // We will always have address here let mut address = bank_debit_billing @@ -2381,7 +2383,7 @@ pub struct AdditionalCardInfo { pub card_exp_year: Option>, - pub card_holder_name: Option>, + pub card_holder_name: Option, /// Additional payment checks done on the cvv and billing address by the processors. /// This is a free form field and the structure varies from processor to processor @@ -2478,7 +2480,7 @@ pub enum BankRedirectData { /// The card holder's name #[schema(value_type = String, example = "John Test")] - card_holder_name: Option>, + card_holder_name: Option, //Required by Stripes billing_details: Option, @@ -2723,10 +2725,10 @@ impl GetAddressFromPaymentMethodData for BankRedirectData { pub struct AlfamartVoucherData { /// The billing first name for Alfamart #[schema(value_type = Option, example = "Jane")] - pub first_name: Option>, + pub first_name: Option, /// The billing second name for Alfamart #[schema(value_type = Option, example = "Doe")] - pub last_name: Option>, + pub last_name: Option, /// The Email ID for Alfamart #[schema(value_type = Option, example = "example@me.com")] pub email: Option, @@ -2736,10 +2738,10 @@ pub struct AlfamartVoucherData { pub struct IndomaretVoucherData { /// The billing first name for Alfamart #[schema(value_type = Option, example = "Jane")] - pub first_name: Option>, + pub first_name: Option, /// The billing second name for Alfamart #[schema(value_type = Option, example = "Doe")] - pub last_name: Option>, + pub last_name: Option, /// The Email ID for Alfamart #[schema(value_type = Option, example = "example@me.com")] pub email: Option, @@ -2749,10 +2751,10 @@ pub struct IndomaretVoucherData { pub struct JCSVoucherData { /// The billing first name for Japanese convenience stores #[schema(value_type = Option, example = "Jane")] - pub first_name: Option>, + pub first_name: Option, /// The billing second name Japanese convenience stores #[schema(value_type = Option, example = "Doe")] - pub last_name: Option>, + pub last_name: Option, /// The Email ID for Japanese convenience stores #[schema(value_type = Option, example = "example@me.com")] pub email: Option, @@ -2772,10 +2774,10 @@ pub struct AchBillingDetails { pub struct DokuBillingDetails { /// The billing first name for Doku #[schema(value_type = Option, example = "Jane")] - pub first_name: Option>, + pub first_name: Option, /// The billing second name for Doku #[schema(value_type = Option, example = "Doe")] - pub last_name: Option>, + pub last_name: Option, /// The Email ID for Doku billing #[schema(value_type = Option, example = "example@me.com")] pub email: Option, @@ -2794,7 +2796,7 @@ pub struct SepaAndBacsBillingDetails { pub email: Option, /// The billing name for SEPA and BACS billing #[schema(value_type = Option, example = "Jane Doe")] - pub name: Option>, + pub name: Option, } #[derive(Debug, Clone, Eq, PartialEq, serde::Deserialize, serde::Serialize, ToSchema)] @@ -2832,7 +2834,7 @@ pub struct SofortBilling { pub struct BankRedirectBilling { /// The name for which billing is issued #[schema(value_type = String, example = "John Doe")] - pub billing_name: Option>, + pub billing_name: Option, /// The billing email for bank redirect #[schema(value_type = String, example = "example@example.com")] pub email: Option, @@ -3002,7 +3004,7 @@ impl GetAddressFromPaymentMethodData for BankTransferData { pub struct BankDebitBilling { /// The billing name for bank debits #[schema(value_type = Option, example = "John Doe")] - pub name: Option>, + pub name: Option, /// The billing email for bank debits #[schema(value_type = Option, example = "example@example.com")] pub email: Option, @@ -3426,7 +3428,7 @@ pub struct CardResponse { #[schema(value_type = Option)] pub card_exp_year: Option>, #[schema(value_type = Option)] - pub card_holder_name: Option>, + pub card_holder_name: Option, pub payment_checks: Option, pub authentication_data: Option, } @@ -3814,22 +3816,20 @@ pub struct AddressDetails { /// The first name for the address #[schema(value_type = Option, max_length = 255, example = "John")] - pub first_name: Option>, + pub first_name: Option, /// The last name for the address #[schema(value_type = Option, max_length = 255, example = "Doe")] - pub last_name: Option>, + pub last_name: Option, } impl AddressDetails { pub fn get_optional_full_name(&self) -> Option> { match (self.first_name.as_ref(), self.last_name.as_ref()) { - (Some(first_name), Some(last_name)) => Some(Secret::new(format!( - "{} {}", - first_name.peek(), - last_name.peek() - ))), - (Some(name), None) | (None, Some(name)) => Some(name.to_owned()), + (Some(first_name), Some(last_name)) => { + Some(Secret::new(format!("{} {}", first_name.peek(), last_name.peek()))) + } + (Some(name), None) | (None, Some(name)) => Some(Secret::from(name.to_owned())), _ => None, } } @@ -7055,7 +7055,7 @@ mod billing_from_payment_method_data { #[test] fn test_card_payment_method_data() { let card_payment_method_data = PaymentMethodData::Card(Card { - card_holder_name: Some(Secret::new(TEST_FIRST_NAME_SINGLE.into())), + card_holder_name: Some(NameType::try_from(TEST_FIRST_NAME_SINGLE.to_string()).unwrap()), ..Default::default() }); @@ -7081,7 +7081,7 @@ mod billing_from_payment_method_data { #[test] fn test_card_payment_method_data_full_name() { let card_payment_method_data = PaymentMethodData::Card(Card { - card_holder_name: Some(Secret::new(TEST_FULL_NAME.into())), + card_holder_name: Some(NameType::try_from(TEST_FULL_NAME.to_string()).unwrap()), ..Default::default() }); @@ -7094,7 +7094,9 @@ mod billing_from_payment_method_data { ); assert_eq!( - billing_address.last_name.expose_option(), + billing_address + .last_name + .map(|name| name.peek().to_string()), Some(TEST_LAST_NAME.into()) ); } @@ -7102,7 +7104,7 @@ mod billing_from_payment_method_data { #[test] fn test_card_payment_method_data_empty_string() { let card_payment_method_data = PaymentMethodData::Card(Card { - card_holder_name: Some(Secret::new("".to_string())), + card_holder_name: Some(NameType::try_from("".to_string()).unwrap()), ..Default::default() }); diff --git a/crates/api_models/src/payments/additional_info.rs b/crates/api_models/src/payments/additional_info.rs index 9e8c910cba7..647af25f684 100644 --- a/crates/api_models/src/payments/additional_info.rs +++ b/crates/api_models/src/payments/additional_info.rs @@ -1,3 +1,4 @@ +use cards::NameType; use common_utils::new_type::{ MaskedBankAccount, MaskedIban, MaskedRoutingNumber, MaskedSortCode, MaskedUpiVpaId, }; @@ -27,11 +28,11 @@ pub struct AchBankDebitAdditionalData { /// Card holder's name #[schema(value_type = Option, example = "John Doe")] - pub card_holder_name: Option>, + pub card_holder_name: Option, /// Bank account's owner name #[schema(value_type = Option, example = "John Doe")] - pub bank_account_holder_name: Option>, + pub bank_account_holder_name: Option, /// Name of the bank #[schema(value_type = Option, example = "ach")] @@ -58,7 +59,7 @@ pub struct BacsBankDebitAdditionalData { /// Bank account's owner name #[schema(value_type = Option, example = "John Doe")] - pub bank_account_holder_name: Option>, + pub bank_account_holder_name: Option, } #[derive(Eq, PartialEq, Clone, Debug, serde::Deserialize, serde::Serialize, ToSchema)] @@ -73,7 +74,7 @@ pub struct BecsBankDebitAdditionalData { /// Bank account's owner name #[schema(value_type = Option, example = "John Doe")] - pub bank_account_holder_name: Option>, + pub bank_account_holder_name: Option, } #[derive(Eq, PartialEq, Clone, Debug, serde::Deserialize, serde::Serialize, ToSchema)] @@ -84,7 +85,7 @@ pub struct SepaBankDebitAdditionalData { /// Bank account's owner name #[schema(value_type = Option, example = "John Doe")] - pub bank_account_holder_name: Option>, + pub bank_account_holder_name: Option, } #[derive(Eq, PartialEq, Clone, Debug, serde::Deserialize, serde::Serialize, ToSchema)] @@ -110,7 +111,7 @@ pub struct BancontactBankRedirectAdditionalData { /// The card holder's name #[schema(value_type = Option, example = "John Test")] - pub card_holder_name: Option>, + pub card_holder_name: Option, } #[derive(Eq, PartialEq, Clone, Debug, serde::Deserialize, serde::Serialize, ToSchema)] @@ -193,7 +194,7 @@ pub struct GivexGiftCardAdditionalData { pub struct CardTokenAdditionalData { /// The card holder's name #[schema(value_type = String, example = "John Test")] - pub card_holder_name: Option>, + pub card_holder_name: Option, } #[derive(Debug, Clone, Eq, PartialEq, serde::Deserialize, serde::Serialize, ToSchema)] diff --git a/crates/api_models/src/payouts.rs b/crates/api_models/src/payouts.rs index 237d165d572..8f97907d15b 100644 --- a/crates/api_models/src/payouts.rs +++ b/crates/api_models/src/payouts.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; -use cards::CardNumber; +use cards::{CardNumber, NameType}; use common_utils::{ consts::default_payouts_list_limit, crypto, id_type, link_utils, payout_method_utils, @@ -251,7 +251,7 @@ pub struct CardPayout { /// The card holder's name #[schema(value_type = String, example = "John Doe")] - pub card_holder_name: Option>, + pub card_holder_name: Option, } #[derive(Eq, PartialEq, Clone, Debug, Deserialize, Serialize, ToSchema)] diff --git a/crates/cards/src/lib.rs b/crates/cards/src/lib.rs index f231234f6ce..2f28917a6b3 100644 --- a/crates/cards/src/lib.rs +++ b/crates/cards/src/lib.rs @@ -7,7 +7,7 @@ use masking::{PeekInterface, StrongSecret}; use serde::{de, Deserialize, Serialize}; use time::{util::days_in_year_month, Date, Duration, PrimitiveDateTime, Time}; -pub use crate::validate::{CardNumber, CardNumberStrategy, CardNumberValidationErr}; +pub use crate::validate::{CardNumber, CardNumberStrategy, CardNumberValidationErr, NameType}; #[derive(Serialize)] pub struct CardSecurityCode(StrongSecret); @@ -67,48 +67,6 @@ impl<'de> Deserialize<'de> for CardExpirationMonth { } } -#[derive(Serialize)] -pub struct CardHolderName(StrongSecret); - -impl TryFrom for CardHolderName { - type Error = error_stack::Report; - fn try_from(card_holder_name: String) -> Result { - for char in card_holder_name.chars() { - validate_character_in_card_holder_name(char)?; - } - Ok(Self(StrongSecret::new(card_holder_name))) - } -} - -fn validate_character_in_card_holder_name( - character: char, -) -> Result<(), error_stack::Report> { - if character.is_alphabetic() - || character == ' ' - || character == '.' - || character == '-' - || character == '\'' - || character == '~' - || character == '`' - { - Ok(()) - } else { - Err(report!(errors::ValidationError::InvalidValue { - message: "invalid character in card holder name".to_string() - })) - } -} - -impl<'de> Deserialize<'de> for CardHolderName { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - let card_holder_name = String::deserialize(deserializer)?; - card_holder_name.try_into().map_err(de::Error::custom) - } -} - #[derive(Serialize)] pub struct CardExpirationYear(StrongSecret); @@ -230,10 +188,3 @@ impl Deref for CardExpirationYear { &self.0 } } - -impl Deref for CardHolderName { - type Target = StrongSecret; - fn deref(&self) -> &Self::Target { - &self.0 - } -} diff --git a/crates/cards/src/validate.rs b/crates/cards/src/validate.rs index d3a27da4823..1f599b119e7 100644 --- a/crates/cards/src/validate.rs +++ b/crates/cards/src/validate.rs @@ -1,8 +1,8 @@ use std::{collections::HashMap, fmt, ops::Deref, str::FromStr}; -use common_utils::errors::ValidationError; +use common_utils::{errors::ValidationError, ext_traits::ConfigExt, types::LengthString}; use error_stack::report; -use masking::{PeekInterface, Strategy, StrongSecret, WithType}; +use masking::{PeekInterface, Secret, Strategy, StrongSecret, WithType}; use once_cell::sync::Lazy; use regex::Regex; #[cfg(not(target_arch = "wasm32"))] @@ -227,6 +227,93 @@ where } } +// #[derive(Debug, Deserialize, Serialize, Error)] +// #[error("{0}")] +// pub struct NameTypeValidationErr(&'static str); + +#[derive(Clone, Default, Debug, Eq, PartialEq, Serialize)] +pub struct NameType(Secret>); + +impl TryFrom for NameType { + type Error = error_stack::Report; + fn try_from(card_holder_name: String) -> Result { + for char in card_holder_name.chars() { + validate_character_in_card_holder_name(char)?; + } + let valid_length_name = + LengthString::<256, 1>::from(card_holder_name.into()).map_err(|_| { + report!(ValidationError::InvalidValue { + message: "invalid length for name".to_string() + }) + })?; + Ok(Self(Secret::new(valid_length_name))) + } +} + +impl FromStr for NameType { + type Err = error_stack::Report; + + fn from_str(card_number: &str) -> Result { + Self::try_from(card_number.to_string()) + } +} + +impl From for Secret { + fn from(card_holder_name: NameType) -> Self { + Self::new(card_holder_name.peek().to_string()) + } +} + +impl From<&NameType> for Secret { + fn from(card_holder_name: &NameType) -> Self { + Self::new(card_holder_name.peek().to_string().to_owned()) + } +} + +fn validate_character_in_card_holder_name( + character: char, +) -> Result<(), error_stack::Report> { + if character.is_alphabetic() + || character == ' ' + || character == '.' + || character == '-' + || character == '\'' + || character == '~' + || character == '`' + { + Ok(()) + } else { + Err(report!(ValidationError::InvalidValue { + message: format!("invalid character found in card holder name: {}", character) + })) + } +} + +impl<'de> Deserialize<'de> for NameType { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let card_holder_name = String::deserialize(deserializer)?; + card_holder_name + .try_into() + .map_err(serde::de::Error::custom) + } +} + +impl Deref for NameType { + type Target = Secret>; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl ConfigExt for NameType { + fn is_empty_after_trim(&self) -> bool { + self.peek().trim().is_empty() + } +} + #[cfg(test)] mod tests { #![allow(clippy::unwrap_used)] @@ -313,4 +400,27 @@ mod tests { let error_msg = card_number.unwrap_err().to_string(); assert_eq!(error_msg, "card number invalid".to_string()); } + + // #[test] + // fn test_card_holder_name() { + + // let valid_name = LengthString::<256, 1>::try_from("Sakil O'Neil".to_string().into()).unwrap(); + // // no panic + // let card_holder_name = NameType::try_from("Sakil O'Neil".to_string()).unwrap(); + + // // will panic on unwrap + // let invalid_card_holder_name = NameType::try_from("$@k!l M*$t@k".to_string()); + + // assert_eq!(*card_holder_name.peek(), valid_name); + // assert!(invalid_card_holder_name.is_err()); + + // let serialized = serde_json::to_string(&card_holder_name).unwrap(); + // assert_eq!(&serialized, "\"Sakil O'Neil\""); + + // let derialized = serde_json::from_str::(&serialized).unwrap(); + // assert_eq!(*derialized.peek(), valid_name); + + // let invalid_deserialization = serde_json::from_str::("$@k!l M*$t@k"); + // assert!(invalid_deserialization.is_err()); + // } } diff --git a/crates/cards/tests/basic.rs b/crates/cards/tests/basic.rs index 22239aaaacf..971cbef32c5 100644 --- a/crates/cards/tests/basic.rs +++ b/crates/cards/tests/basic.rs @@ -1,8 +1,6 @@ #![allow(clippy::unwrap_used, clippy::expect_used)] -use cards::{ - CardExpiration, CardExpirationMonth, CardExpirationYear, CardHolderName, CardSecurityCode, -}; +use cards::{CardExpiration, CardExpirationMonth, CardExpirationYear, CardSecurityCode}; use common_utils::date_time; use masking::PeekInterface; @@ -44,27 +42,6 @@ fn test_card_expiration_month() { assert!(invalid_deserialization.is_err()); } -#[test] -fn test_card_holder_name() { - // no panic - let card_holder_name = CardHolderName::try_from("Sakil O'Neil".to_string()).unwrap(); - - // will panic on unwrap - let invalid_card_holder_name = CardHolderName::try_from("$@k!l M*$t@k".to_string()); - - assert_eq!(*card_holder_name.peek(), "Sakil O'Neil"); - assert!(invalid_card_holder_name.is_err()); - - let serialized = serde_json::to_string(&card_holder_name).unwrap(); - assert_eq!(&serialized, "\"Sakil O'Neil\""); - - let derialized = serde_json::from_str::(&serialized).unwrap(); - assert_eq!(*derialized.peek(), "Sakil O'Neil".to_string()); - - let invalid_deserialization = serde_json::from_str::("$@k!l M*$t@k"); - assert!(invalid_deserialization.is_err()); -} - #[test] fn test_card_expiration_year() { let curr_date = date_time::now(); diff --git a/crates/common_utils/src/types.rs b/crates/common_utils/src/types.rs index 1e547a49713..8a346a74989 100644 --- a/crates/common_utils/src/types.rs +++ b/crates/common_utils/src/types.rs @@ -12,7 +12,7 @@ use std::{ iter::Sum, ops::{Add, Mul, Sub}, primitive::i64, - str::FromStr, + str::{FromStr, SplitWhitespace}, }; use common_enums::enums; @@ -1075,11 +1075,11 @@ crate::impl_to_sql_from_sql_json!(ChargeRefunds); /// A common type of domain type that can be used for fields that contain a string with restriction of length #[derive(Debug, Clone, Serialize, Hash, PartialEq, Eq, AsExpression)] #[diesel(sql_type = sql_types::Text)] -pub(crate) struct LengthString(String); +pub struct LengthString(String); /// Error generated from violation of constraints for MerchantReferenceId #[derive(Debug, Error, PartialEq, Eq)] -pub(crate) enum LengthStringError { +pub enum LengthStringError { #[error("the maximum allowed length for this field is {0}")] /// Maximum length of string violated MaxLengthViolated(u16), @@ -1089,6 +1089,11 @@ pub(crate) enum LengthStringError { MinLengthViolated(u16), } +impl masking::SerializableSecret + for LengthString +{ +} + impl LengthString { /// Generates new [MerchantReferenceId] from the given input string pub fn from(input_string: Cow<'static, str>) -> Result { @@ -1110,6 +1115,47 @@ impl LengthString Self { Self(input_string) } + + /// Trim the name + pub fn trim(&self) -> Self { + Self(self.0.trim().to_string()) + } + + /// Check if the string is empty + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } + + /// Split the string by whitespace + pub fn split_whitespace(&self) -> SplitWhitespace<'_> { + self.0.split_whitespace() + } + + /// Split once at the first occurrence of the given character + pub fn split_once(&self, delimiter: char) -> Option<(&str, &str)> { + self.0.split_once(delimiter) + } + + /// Split once at the last occurrence of the given character + pub fn rsplit_once(&self, delimiter: char) -> Option<(&str, &str)> { + self.0.rsplit_once(delimiter) + } +} + +impl Display + for LengthString +{ + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) + } +} + +impl Default + for LengthString +{ + fn default() -> Self { + Self(String::default()) + } } impl<'de, const MAX_LENGTH: u16, const MIN_LENGTH: u16> Deserialize<'de> diff --git a/crates/hyperswitch_connectors/src/connectors/worldline/transformers.rs b/crates/hyperswitch_connectors/src/connectors/worldline/transformers.rs index 89ee8d1b29b..94fc9136160 100644 --- a/crates/hyperswitch_connectors/src/connectors/worldline/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/worldline/transformers.rs @@ -19,7 +19,7 @@ use url::Url; use crate::{ types::{RefundsResponseRouterData, ResponseRouterData}, - utils::{self, CardData, RouterData as RouterDataUtils}, + utils::{self, AddressDetailsData, CardData, RouterData as RouterDataUtils}, }; #[derive(Default, Debug, Serialize, Eq, PartialEq)] @@ -469,11 +469,11 @@ impl From for BillingAddress { impl From for Shipping { fn from(value: payments::AddressDetails) -> Self { Self { - city: value.city, - country_code: value.country, + city: value.city.clone(), + country_code: value.country.clone(), name: Some(Name { - first_name: value.first_name, - surname: value.last_name, + first_name: value.get_first_name().ok(), + surname: value.get_last_name().ok(), ..Default::default() }), state: value.state, diff --git a/crates/hyperswitch_connectors/src/utils.rs b/crates/hyperswitch_connectors/src/utils.rs index 181f46a2052..cfb71fc20f8 100644 --- a/crates/hyperswitch_connectors/src/utils.rs +++ b/crates/hyperswitch_connectors/src/utils.rs @@ -355,7 +355,7 @@ impl RouterData shipping_address .clone() .address - .and_then(|shipping_details| shipping_details.first_name) + .and_then(|shipping_details| shipping_details.first_name.map(From::from)) }) } @@ -364,7 +364,7 @@ impl RouterData shipping_address .clone() .address - .and_then(|shipping_details| shipping_details.last_name) + .and_then(|shipping_details| shipping_details.last_name.map(From::from)) }) } @@ -472,7 +472,7 @@ impl RouterData billing_address .clone() .address - .and_then(|billing_details| billing_details.first_name.clone()) + .and_then(|billing_details| billing_details.first_name.map(From::from)) }) .ok_or_else(missing_field_err( "payment_method_data.billing.address.first_name", @@ -495,7 +495,7 @@ impl RouterData billing_address .clone() .address - .and_then(|billing_details| billing_details.last_name.clone()) + .and_then(|billing_details| billing_details.last_name.map(From::from)) }) .ok_or_else(missing_field_err( "payment_method_data.billing.address.last_name", @@ -678,7 +678,7 @@ impl RouterData billing_address .clone() .address - .and_then(|billing_details| billing_details.first_name) + .and_then(|billing_details| billing_details.first_name.map(From::from)) }) } @@ -689,7 +689,7 @@ impl RouterData billing_address .clone() .address - .and_then(|billing_details| billing_details.last_name) + .and_then(|billing_details| billing_details.last_name.map(From::from)) }) } @@ -973,8 +973,8 @@ static CARD_REGEX: Lazy>> = Lazy }); pub trait AddressDetailsData { - fn get_first_name(&self) -> Result<&Secret, Error>; - fn get_last_name(&self) -> Result<&Secret, Error>; + fn get_first_name(&self) -> Result, Error>; + fn get_last_name(&self) -> Result, Error>; fn get_full_name(&self) -> Result, Error>; fn get_line1(&self) -> Result<&Secret, Error>; fn get_city(&self) -> Result<&String, Error>; @@ -991,26 +991,26 @@ pub trait AddressDetailsData { } impl AddressDetailsData for AddressDetails { - fn get_first_name(&self) -> Result<&Secret, Error> { + fn get_first_name(&self) -> Result, Error> { self.first_name - .as_ref() + .clone() + .map(From::from) .ok_or_else(missing_field_err("address.first_name")) } - fn get_last_name(&self) -> Result<&Secret, Error> { + fn get_last_name(&self) -> Result, Error> { self.last_name - .as_ref() + .clone() + .map(From::from) .ok_or_else(missing_field_err("address.last_name")) } fn get_full_name(&self) -> Result, Error> { - let first_name = self.get_first_name()?.peek().to_owned(); + let first_name = self.get_first_name()?.expose(); let last_name = self .get_last_name() - .ok() - .cloned() - .unwrap_or(Secret::new("".to_string())); - let last_name = last_name.peek(); + .unwrap_or(Secret::new("".to_string())) + .expose(); let full_name = format!("{} {}", first_name, last_name).trim().to_string(); Ok(Secret::new(full_name)) } @@ -1164,9 +1164,7 @@ pub trait PaymentsAuthorizeRequestData { fn get_metadata_as_object(&self) -> Option; fn get_authentication_data(&self) -> Result; fn get_customer_name(&self) -> Result, Error>; - fn get_card_holder_name_from_additional_payment_method_data( - &self, - ) -> Result, Error>; + fn get_card_holder_name_from_additional_payment_method_data(&self) -> Result, Error>; } impl PaymentsAuthorizeRequestData for PaymentsAuthorizeData { @@ -1329,13 +1327,12 @@ impl PaymentsAuthorizeRequestData for PaymentsAuthorizeData { .ok_or_else(missing_field_err("customer_name")) } - fn get_card_holder_name_from_additional_payment_method_data( - &self, - ) -> Result, Error> { + fn get_card_holder_name_from_additional_payment_method_data(&self) -> Result, Error> { match &self.additional_payment_method_data { Some(payments::AdditionalPaymentData::Card(card_data)) => Ok(card_data .card_holder_name .clone() + .map(From::from) .ok_or_else(|| errors::ConnectorError::MissingRequiredField { field_name: "card_holder_name", })?), diff --git a/crates/hyperswitch_domain_models/src/address.rs b/crates/hyperswitch_domain_models/src/address.rs index 85595c1ad9e..c61b5ade4b9 100644 --- a/crates/hyperswitch_domain_models/src/address.rs +++ b/crates/hyperswitch_domain_models/src/address.rs @@ -1,3 +1,4 @@ +use cards::NameType; use masking::{PeekInterface, Secret}; #[derive(Default, Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] @@ -33,18 +34,16 @@ pub struct AddressDetails { pub line3: Option>, pub zip: Option>, pub state: Option>, - pub first_name: Option>, - pub last_name: Option>, + pub first_name: Option, + pub last_name: Option, } impl AddressDetails { - pub fn get_optional_full_name(&self) -> Option> { + pub fn get_optional_full_name(&self) -> Option { match (self.first_name.as_ref(), self.last_name.as_ref()) { - (Some(first_name), Some(last_name)) => Some(Secret::new(format!( - "{} {}", - first_name.peek(), - last_name.peek() - ))), + (Some(first_name), Some(last_name)) => { + NameType::try_from(format!("{} {}", first_name.peek(), last_name.peek())).ok() + } (Some(name), None) | (None, Some(name)) => Some(name.to_owned()), _ => None, } diff --git a/crates/hyperswitch_domain_models/src/payment_method_data.rs b/crates/hyperswitch_domain_models/src/payment_method_data.rs index 820959a5963..581bcf294f9 100644 --- a/crates/hyperswitch_domain_models/src/payment_method_data.rs +++ b/crates/hyperswitch_domain_models/src/payment_method_data.rs @@ -2,6 +2,7 @@ use api_models::{ mandates, payment_methods, payments::{additional_info as payment_additional_types, ExtendedCardInfo}, }; +use cards::NameType; use common_enums::enums as api_enums; use common_utils::{ id_type, @@ -81,7 +82,7 @@ pub struct Card { pub card_type: Option, pub card_issuing_country: Option, pub bank_code: Option, - pub nick_name: Option>, + pub nick_name: Option, } #[derive(Eq, PartialEq, Clone, Debug, Serialize, Deserialize, Default)] @@ -94,7 +95,7 @@ pub struct CardDetailsForNetworkTransactionId { pub card_type: Option, pub card_issuing_country: Option, pub bank_code: Option, - pub nick_name: Option>, + pub nick_name: Option, } impl CardDetailsForNetworkTransactionId { @@ -371,7 +372,7 @@ pub enum BankRedirectData { card_number: Option, card_exp_month: Option>, card_exp_year: Option>, - card_holder_name: Option>, + card_holder_name: Option, }, Bizum {}, Blik { @@ -511,7 +512,7 @@ pub struct GiftCardDetails { #[serde(rename_all = "snake_case")] pub struct CardToken { /// The card holder's name - pub card_holder_name: Option>, + pub card_holder_name: Option, /// The CVC number for the card pub card_cvc: Option>, @@ -523,25 +524,25 @@ pub enum BankDebitData { AchBankDebit { account_number: Secret, routing_number: Secret, - card_holder_name: Option>, - bank_account_holder_name: Option>, + card_holder_name: Option, + bank_account_holder_name: Option, bank_name: Option, bank_type: Option, bank_holder_type: Option, }, SepaBankDebit { iban: Secret, - bank_account_holder_name: Option>, + bank_account_holder_name: Option, }, BecsBankDebit { account_number: Secret, bsb_number: Secret, - bank_account_holder_name: Option>, + bank_account_holder_name: Option, }, BacsBankDebit { account_number: Secret, sort_code: Secret, - bank_account_holder_name: Option>, + bank_account_holder_name: Option, }, } @@ -592,7 +593,7 @@ pub struct NetworkTokenData { pub card_type: Option, pub card_issuing_country: Option, pub bank_code: Option, - pub nick_name: Option>, + pub nick_name: Option, } #[derive(Eq, PartialEq, Clone, Debug, Serialize, Deserialize)] diff --git a/crates/hyperswitch_domain_models/src/router_data.rs b/crates/hyperswitch_domain_models/src/router_data.rs index a3867ce3e62..c64cdd254c1 100644 --- a/crates/hyperswitch_domain_models/src/router_data.rs +++ b/crates/hyperswitch_domain_models/src/router_data.rs @@ -1,5 +1,6 @@ use std::{collections::HashMap, marker::PhantomData}; +use cards::NameType; use common_utils::{ errors::IntegrityCheckError, ext_traits::{OptionExt, ValueExt}, @@ -280,7 +281,7 @@ pub struct PazeDynamicData { #[derive(Debug, Clone, serde::Deserialize)] #[serde(rename_all = "camelCase")] pub struct PazeAddress { - pub name: Option>, + pub name: Option, pub line1: Option>, pub line2: Option>, pub line3: Option>, diff --git a/crates/hyperswitch_domain_models/src/router_request_types/fraud_check.rs b/crates/hyperswitch_domain_models/src/router_request_types/fraud_check.rs index 4d7f4bfdf49..e92ca75f833 100644 --- a/crates/hyperswitch_domain_models/src/router_request_types/fraud_check.rs +++ b/crates/hyperswitch_domain_models/src/router_request_types/fraud_check.rs @@ -1,4 +1,5 @@ use api_models; +use cards::NameType; use common_enums; use common_utils::{ events::{ApiEventMetric, ApiEventsType}, @@ -140,7 +141,7 @@ pub struct Product { #[serde_with::skip_serializing_none] #[serde(rename_all = "snake_case")] pub struct Destination { - pub full_name: Secret, + pub full_name: NameType, pub organization: Option, pub email: Option, pub address: Address, diff --git a/crates/router/src/compatibility/stripe/customers/types.rs b/crates/router/src/compatibility/stripe/customers/types.rs index 83649f98232..dd67c91d7d0 100644 --- a/crates/router/src/compatibility/stripe/customers/types.rs +++ b/crates/router/src/compatibility/stripe/customers/types.rs @@ -6,6 +6,7 @@ use std::{convert::From, default::Default}; ))] use api_models::payment_methods as api_types; use api_models::payments; +use cards::NameType; #[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "customer_v2")))] use common_utils::{crypto::Encryptable, date_time}; use common_utils::{ @@ -42,7 +43,7 @@ pub struct StripeAddressDetails { pub struct CreateCustomerRequest { pub email: Option, pub invoice_prefix: Option, - pub name: Option>, + pub name: Option, pub phone: Option>, pub address: Option, pub metadata: Option, diff --git a/crates/router/src/compatibility/stripe/payment_intents/types.rs b/crates/router/src/compatibility/stripe/payment_intents/types.rs index 55516eeb3bc..1de5c5ae4f8 100644 --- a/crates/router/src/compatibility/stripe/payment_intents/types.rs +++ b/crates/router/src/compatibility/stripe/payment_intents/types.rs @@ -1,6 +1,7 @@ use std::str::FromStr; use api_models::payments; +use cards::NameType; use common_utils::{ crypto::Encryptable, date_time, @@ -64,7 +65,7 @@ pub struct StripeCard { pub exp_month: masking::Secret, pub exp_year: masking::Secret, pub cvc: masking::Secret, - pub holder_name: Option>, + pub holder_name: Option, } // ApplePay wallet param is not available in stripe Docs @@ -169,7 +170,7 @@ impl From for payments::PaymentMethodData { #[derive(Default, Serialize, PartialEq, Eq, Deserialize, Clone, Debug)] pub struct Shipping { pub address: AddressDetails, - pub name: Option>, + pub name: Option, pub carrier: Option, pub phone: Option>, pub tracking_number: Option>, diff --git a/crates/router/src/compatibility/stripe/setup_intents/types.rs b/crates/router/src/compatibility/stripe/setup_intents/types.rs index 03cf9742f70..6f84aa200b9 100644 --- a/crates/router/src/compatibility/stripe/setup_intents/types.rs +++ b/crates/router/src/compatibility/stripe/setup_intents/types.rs @@ -1,6 +1,7 @@ use std::str::FromStr; use api_models::payments; +use cards::NameType; use common_utils::{date_time, ext_traits::StringExt, id_type, pii as secret}; use error_stack::ResultExt; use router_env::logger; @@ -96,7 +97,7 @@ impl From for payments::Card { card_number: card.number, card_exp_month: card.exp_month, card_exp_year: card.exp_year, - card_holder_name: Some(masking::Secret::new("stripe_cust".to_owned())), + card_holder_name: NameType::try_from("Stripe_cust".to_string()).ok(), card_cvc: card.cvc, card_issuer: None, card_network: None, diff --git a/crates/router/src/connector/adyenplatform/transformers/payouts.rs b/crates/router/src/connector/adyenplatform/transformers/payouts.rs index f3f398760c4..62b597824e5 100644 --- a/crates/router/src/connector/adyenplatform/transformers/payouts.rs +++ b/crates/router/src/connector/adyenplatform/transformers/payouts.rs @@ -1,5 +1,6 @@ #[cfg(feature = "payouts")] use api_models::webhooks; +use cards::NameType; use common_utils::pii; use error_stack::{report, ResultExt}; use masking::Secret; @@ -68,7 +69,7 @@ pub struct AdyenBankAccountDetails { #[serde(rename_all = "camelCase")] pub struct AdyenBankAccountHolder { address: Option, - full_name: Secret, + full_name: NameType, #[serde(rename = "reference")] customer_id: Option, #[serde(rename = "type")] diff --git a/crates/router/src/connector/mifinity/transformers.rs b/crates/router/src/connector/mifinity/transformers.rs index 1e2c420c767..5d109a4f5af 100644 --- a/crates/router/src/connector/mifinity/transformers.rs +++ b/crates/router/src/connector/mifinity/transformers.rs @@ -1,3 +1,4 @@ +use cards::NameType; use common_utils::{ pii::{self, Email}, types::StringMajorUnit, @@ -74,8 +75,8 @@ pub struct Money { #[derive(Debug, Clone, Serialize, PartialEq)] #[serde(rename_all = "camelCase")] pub struct MifinityClient { - first_name: Secret, - last_name: Secret, + first_name: NameType, + last_name: NameType, phone: Secret, dialing_code: String, nationality: api_models::enums::CountryAlpha2, diff --git a/crates/router/src/connector/netcetera/netcetera_types.rs b/crates/router/src/connector/netcetera/netcetera_types.rs index 68a01b26fba..65817f29702 100644 --- a/crates/router/src/connector/netcetera/netcetera_types.rs +++ b/crates/router/src/connector/netcetera/netcetera_types.rs @@ -1,9 +1,8 @@ use std::collections::HashMap; +use cards::NameType; use common_utils::pii::Email; -use masking::ExposeInterface; use serde::{Deserialize, Serialize}; -use unidecode::unidecode; use crate::{ connector::utils::{AddressDetailsData, PhoneDetailsData}, @@ -615,7 +614,7 @@ pub struct Cardholder { /// /// Starting from EMV 3DS 2.3.1: /// This field is limited to 1-45 characters. - cardholder_name: Option>, + cardholder_name: Option, /// City portion of the shipping address requested by the Cardholder. /// @@ -747,11 +746,9 @@ impl .clone() .map(PhoneNumber::try_from) .transpose()?, - cardholder_name: billing_address.address.and_then(|address| { - address - .get_optional_full_name() - .map(|name| masking::Secret::new(unidecode(&name.expose()))) - }), + cardholder_name: billing_address + .address + .and_then(|address| address.get_optional_full_name()), ship_addr_city: shipping_address .as_ref() .and_then(|shipping_add| shipping_add.address.as_ref()) diff --git a/crates/router/src/connector/riskified/transformers/api.rs b/crates/router/src/connector/riskified/transformers/api.rs index 2d519b3caa8..0ab0e3da65c 100644 --- a/crates/router/src/connector/riskified/transformers/api.rs +++ b/crates/router/src/connector/riskified/transformers/api.rs @@ -1,4 +1,5 @@ use api_models::payments::AdditionalPaymentData; +use cards::NameType; use common_utils::{ ext_traits::ValueExt, id_type, @@ -104,8 +105,8 @@ pub struct ClientDetails { #[derive(Debug, Deserialize, Serialize, Eq, PartialEq, Clone)] pub struct RiskifiedCustomer { email: Option, - first_name: Option>, - last_name: Option>, + first_name: Option, + last_name: Option, #[serde(with = "common_utils::custom_serde::iso8601")] created_at: PrimitiveDateTime, verified_email: bool, @@ -123,8 +124,8 @@ pub enum CustomerAccountType { #[derive(Debug, Deserialize, Serialize, Eq, PartialEq, Clone)] pub struct OrderAddress { - first_name: Option>, - last_name: Option>, + first_name: Option, + last_name: Option, address1: Option>, country_code: Option, city: Option, diff --git a/crates/router/src/connector/signifyd/transformers/api.rs b/crates/router/src/connector/signifyd/transformers/api.rs index 028c0e82518..44c11ff8421 100644 --- a/crates/router/src/connector/signifyd/transformers/api.rs +++ b/crates/router/src/connector/signifyd/transformers/api.rs @@ -1,3 +1,4 @@ +use cards::NameType; use common_utils::{ext_traits::ValueExt, pii::Email}; use error_stack::{self, ResultExt}; pub use hyperswitch_domain_models::router_request_types::fraud_check::RefundMethod; @@ -91,7 +92,7 @@ pub struct Shipments { #[derive(Debug, Deserialize, Serialize, Eq, PartialEq, Clone)] #[serde(rename_all = "camelCase")] pub struct Destination { - full_name: Secret, + full_name: NameType, organization: Option, email: Option, address: Address, diff --git a/crates/router/src/connector/stripe/transformers/connect.rs b/crates/router/src/connector/stripe/transformers/connect.rs index 9852338038c..9a2046cd022 100644 --- a/crates/router/src/connector/stripe/transformers/connect.rs +++ b/crates/router/src/connector/stripe/transformers/connect.rs @@ -1,4 +1,5 @@ use api_models; +use cards::NameType; use common_utils::pii::Email; use error_stack::ResultExt; use masking::Secret; @@ -124,9 +125,9 @@ pub struct StripeConnectRecipientCreateRequest { #[serde(rename = "company[owners_provided]")] company_owners_provided: Option, #[serde(rename = "individual[first_name]")] - individual_first_name: Option>, + individual_first_name: Option, #[serde(rename = "individual[last_name]")] - individual_last_name: Option>, + individual_last_name: Option, #[serde(rename = "individual[dob][day]")] individual_dob_day: Option>, #[serde(rename = "individual[dob][month]")] diff --git a/crates/router/src/connector/utils.rs b/crates/router/src/connector/utils.rs index b5901f56d3b..425333ce1f0 100644 --- a/crates/router/src/connector/utils.rs +++ b/crates/router/src/connector/utils.rs @@ -10,6 +10,7 @@ use api_models::{ payments, }; use base64::Engine; +use cards::NameType; use common_utils::{ date_time, errors::{ParsingError, ReportSwitchExt}, @@ -227,7 +228,7 @@ impl RouterData for types::RouterData RouterData for types::RouterData RouterData for types::RouterData RouterData for types::RouterData RouterData for types::RouterData RouterData for types::RouterData Result<&Secret, Error>; - fn get_last_name(&self) -> Result<&Secret, Error>; - fn get_full_name(&self) -> Result, Error>; + fn get_first_name(&self) -> Result<&NameType, Error>; + fn get_last_name(&self) -> Result<&NameType, Error>; + fn get_full_name(&self) -> Result; fn get_line1(&self) -> Result<&Secret, Error>; fn get_city(&self) -> Result<&String, Error>; fn get_line2(&self) -> Result<&Secret, Error>; diff --git a/crates/router/src/core/customers.rs b/crates/router/src/core/customers.rs index 266873b1a11..122e0911797 100644 --- a/crates/router/src/core/customers.rs +++ b/crates/router/src/core/customers.rs @@ -147,7 +147,10 @@ impl CustomerCreateBridge for customers::CustomerRequest { types::CryptoOperation::BatchEncrypt( domain::FromRequestEncryptableCustomer::to_encryptable( domain::FromRequestEncryptableCustomer { - name: self.name.clone(), + name: self + .name + .clone() + .map(|name| Secret::new(name.peek().to_string())), email: self.email.clone().map(|a| a.expose().switch_strategy()), phone: self.phone.clone(), }, diff --git a/crates/router/src/core/locker_migration.rs b/crates/router/src/core/locker_migration.rs index dbadadb3a6f..fb7432f44a7 100644 --- a/crates/router/src/core/locker_migration.rs +++ b/crates/router/src/core/locker_migration.rs @@ -165,7 +165,7 @@ pub async fn call_to_locker( card_exp_month: card.card_exp_month, card_exp_year: card.card_exp_year, card_holder_name: card.name_on_card, - nick_name: card.nick_name.map(masking::Secret::new), + nick_name: card.nick_name, card_issuing_country: None, card_network: None, card_issuer: None, diff --git a/crates/router/src/core/payment_methods.rs b/crates/router/src/core/payment_methods.rs index 599d696ec06..750bc6dea98 100644 --- a/crates/router/src/core/payment_methods.rs +++ b/crates/router/src/core/payment_methods.rs @@ -13,6 +13,7 @@ use std::collections::HashSet; #[cfg(all(feature = "v2", feature = "payment_methods_v2"))] use std::str::FromStr; +use ::cards::NameType; #[cfg(all(feature = "v2", feature = "payment_methods_v2"))] pub use api_models::enums as api_enums; pub use api_models::enums::Connector; @@ -753,7 +754,7 @@ pub(crate) async fn get_payment_method_create_request( payment_method: Option, payment_method_type: Option, customer_id: &Option, - billing_name: Option>, + billing_name: Option, payment_method_billing_address: Option<&api_models::payments::Address>, ) -> RouterResult { match payment_method_data { diff --git a/crates/router/src/core/payment_methods/cards.rs b/crates/router/src/core/payment_methods/cards.rs index ad612ed6f3b..7c433fc5a1c 100644 --- a/crates/router/src/core/payment_methods/cards.rs +++ b/crates/router/src/core/payment_methods/cards.rs @@ -2303,22 +2303,22 @@ pub fn validate_payment_method_update( }) || card_updation_obj .card_holder_name - .map(|name| name.expose()) + .map(|name| name.peek().to_string()) .map_or(false, |new_card_holder_name| { existing_card_data .card_holder_name - .map(|name| name.expose()) + .map(|name| name.peek().to_string()) .map_or(true, |old_card_holder_name| { - new_card_holder_name != old_card_holder_name + new_card_holder_name != old_card_holder_name.to_string() }) }) || card_updation_obj .nick_name - .map(|nick_name| nick_name.expose()) + .map(|nick_name| nick_name.peek().to_string()) .map_or(false, |new_nick_name| { existing_card_data .nick_name - .map(|nick_name| nick_name.expose()) + .map(|nick_name| nick_name.peek().to_string()) .map_or(true, |old_nick_name| new_nick_name != old_nick_name) }) } @@ -2567,7 +2567,7 @@ pub async fn add_card_hs( card_exp_year: card.card_exp_year.to_owned(), card_brand: card.card_network.as_ref().map(ToString::to_string), card_isin: None, - nick_name: card.nick_name.as_ref().map(Secret::peek).cloned(), + nick_name: card.nick_name.to_owned(), }, ttl: state.conf.locker.ttl_for_storage_in_secs, }); @@ -2979,8 +2979,16 @@ pub async fn mock_call_to_locker_hs( card_number: store_card_req.card.card_number.peek().to_string(), card_exp_year: store_card_req.card.card_exp_year.peek().to_string(), card_exp_month: store_card_req.card.card_exp_month.peek().to_string(), - name_on_card: store_card_req.card.name_on_card.to_owned().expose_option(), - nickname: store_card_req.card.nick_name.to_owned(), + name_on_card: store_card_req + .card + .name_on_card + .to_owned() + .map(|name| name.peek().to_string()), + nickname: store_card_req + .card + .nick_name + .to_owned() + .map(|nick_name| nick_name.peek().to_string()), ..locker_mock_up }, payment_methods::StoreLockerReq::LockerGeneric(store_generic_req) => { @@ -3031,7 +3039,9 @@ pub async fn mock_get_card<'a>( .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()), + name_on_card: locker_mock_up + .name_on_card + .and_then(|card| card.try_into().ok()), nickname: locker_mock_up.nickname, customer_id: locker_mock_up.customer_id, duplicate: locker_mock_up.duplicate, @@ -5714,7 +5724,7 @@ impl TempLockerCardSupport { let card_holder_name = card .card_holder_name .clone() - .expose_option() + .map(|name| name.peek().to_string()) .unwrap_or_default(); let value1 = payment_methods::mk_card_value1( card_number, diff --git a/crates/router/src/core/payment_methods/transformers.rs b/crates/router/src/core/payment_methods/transformers.rs index c3fbfd8afbf..07313dd5a9d 100644 --- a/crates/router/src/core/payment_methods/transformers.rs +++ b/crates/router/src/core/payment_methods/transformers.rs @@ -2,6 +2,7 @@ use std::str::FromStr; use api_models::{enums as api_enums, payment_methods::Card}; +use cards::NameType; #[cfg(all(feature = "v2", feature = "payment_methods_v2"))] use common_utils::ext_traits::ValueExt; use common_utils::{ @@ -10,7 +11,7 @@ use common_utils::{ pii::Email, request::RequestContent, }; -use error_stack::ResultExt; +use error_stack::{report, ResultExt}; use josekit::jwe; use router_env::tracing_actix_web::RequestId; use serde::{Deserialize, Serialize}; @@ -144,7 +145,7 @@ pub struct AddCardResponse { pub card_number: Option, pub card_exp_year: Option>, pub card_exp_month: Option>, - pub name_on_card: Option>, + pub name_on_card: Option, pub nickname: Option, pub customer_id: Option, pub duplicate: Option, @@ -661,7 +662,16 @@ pub fn mk_get_card_response(card: GetCardResponse) -> errors::RouterResult .get_required_value("card_exp_year")?, card_brand: None, card_isin: None, - nick_name: card.card.nickname, + nick_name: card.card.nickname.and_then(|name| { + NameType::try_from(name) + .map_err(|_| { + report!(errors::ApiErrorResponse::InvalidDataFormat { + field_name: "nick_name".to_string(), + expected_format: "NameType".to_string() + }) + }) + .ok() + }), }) } @@ -793,7 +803,7 @@ pub fn get_card_detail( card_token: None, card_fingerprint: None, card_holder_name: response.name_on_card, - nick_name: response.nick_name.map(Secret::new), + nick_name: response.nick_name, card_isin: None, card_issuer: None, card_network: None, diff --git a/crates/router/src/core/payment_methods/vault.rs b/crates/router/src/core/payment_methods/vault.rs index 7a24f2a30a2..8ff79a8dbc1 100644 --- a/crates/router/src/core/payment_methods/vault.rs +++ b/crates/router/src/core/payment_methods/vault.rs @@ -1,3 +1,4 @@ +use cards::NameType; use common_enums::PaymentMethodType; #[cfg(all(feature = "v2", feature = "payment_methods_v2"))] use common_utils::request; @@ -63,7 +64,7 @@ impl Vaultable for domain::Card { card_number: self.card_number.peek().clone(), exp_year: self.card_exp_year.peek().clone(), exp_month: self.card_exp_month.peek().clone(), - nickname: self.nick_name.as_ref().map(|name| name.peek().clone()), + nickname: self.nick_name.as_ref().map(|name| name.peek().to_string()), card_last_four: None, card_token: None, }; @@ -118,7 +119,9 @@ impl Vaultable for domain::Card { bank_code: None, card_issuing_country: None, card_type: None, - nick_name: value1.nickname.map(masking::Secret::new), + nick_name: value1 + .nickname + .and_then(|name| NameType::try_from(name).ok()), }; let supp_data = SupplementaryVaultData { @@ -512,7 +515,9 @@ impl Vaultable for api::CardPayout { .map_err(|_| errors::VaultError::FetchCardFailed)?, expiry_month: value1.exp_month.into(), expiry_year: value1.exp_year.into(), - card_holder_name: value1.name_on_card.map(masking::Secret::new), + card_holder_name: value1 + .name_on_card + .and_then(|name| NameType::try_from(name).ok()), }; let supp_data = SupplementaryVaultData { diff --git a/crates/router/src/core/payments/helpers.rs b/crates/router/src/core/payments/helpers.rs index f15ba01c2ef..454a2f141d2 100644 --- a/crates/router/src/core/payments/helpers.rs +++ b/crates/router/src/core/payments/helpers.rs @@ -130,14 +130,16 @@ pub async fn create_or_update_address_for_payment_by_request( line2: address.address.as_ref().and_then(|a| a.line2.clone()), line3: address.address.as_ref().and_then(|a| a.line3.clone()), state: address.address.as_ref().and_then(|a| a.state.clone()), - first_name: address - .address - .as_ref() - .and_then(|a| a.first_name.clone()), - last_name: address - .address - .as_ref() - .and_then(|a| a.last_name.clone()), + first_name: address.address.as_ref().and_then(|a| { + a.first_name + .clone() + .map(|name| masking::Secret::new(name.peek().to_string())) + }), + last_name: address.address.as_ref().and_then(|a| { + a.last_name + .clone() + .map(|name| masking::Secret::new(name.peek().to_string())) + }), zip: address.address.as_ref().and_then(|a| a.zip.clone()), phone_number: address .phone @@ -346,8 +348,16 @@ pub async fn get_domain_address( line2: address.address.as_ref().and_then(|a| a.line2.clone()), line3: address.address.as_ref().and_then(|a| a.line3.clone()), state: address.address.as_ref().and_then(|a| a.state.clone()), - first_name: address.address.as_ref().and_then(|a| a.first_name.clone()), - last_name: address.address.as_ref().and_then(|a| a.last_name.clone()), + first_name: address.address.as_ref().and_then(|a| { + a.first_name + .clone() + .map(|name| masking::Secret::new(name.peek().to_string())) + }), + last_name: address.address.as_ref().and_then(|a| { + a.last_name + .clone() + .map(|name| masking::Secret::new(name.peek().to_string())) + }), zip: address.address.as_ref().and_then(|a| a.zip.clone()), phone_number: address .phone @@ -995,45 +1005,7 @@ pub fn validate_card_data( )?; validate_card_expiry(&card.card_exp_month, &card.card_exp_year)?; - validate_card_holder_name(&card.card_holder_name)?; - } - Ok(()) -} - -pub fn validate_billing_name( - billing_address: Option<&api_models::payments::AddressDetails>, -) -> CustomResult<(), errors::ApiErrorResponse> { - let optional_first_name = billing_address.and_then(|address| address.first_name.clone()); - let optional_last_name = billing_address.and_then(|address| address.last_name.clone()); - - if let Some(first_name) = optional_first_name { - let first_name = first_name.peek().to_string(); - if first_name.len() > 256 { - Err(report!(errors::ApiErrorResponse::PreconditionFailed { - message: "Invalid First Name Length".to_string() - }))? - } - ::cards::CardHolderName::try_from(first_name).change_context( - errors::ApiErrorResponse::PreconditionFailed { - message: "Invalid First Name".to_string(), - }, - )?; - } - - if let Some(last_name) = optional_last_name { - let last_name = last_name.peek().to_string(); - if last_name.len() > 256 { - Err(report!(errors::ApiErrorResponse::PreconditionFailed { - message: "Invalid Last Name Length".to_string() - }))? - } - ::cards::CardHolderName::try_from(last_name).change_context( - errors::ApiErrorResponse::PreconditionFailed { - message: "Invalid Last Name".to_string(), - }, - )?; } - Ok(()) } @@ -1086,26 +1058,6 @@ pub fn validate_card_expiry( Ok(()) } -pub fn validate_card_holder_name( - optional_card_holder_name: &Option>, -) -> CustomResult<(), errors::ApiErrorResponse> { - if let Some(masked_card_holder_name) = optional_card_holder_name { - let card_holder_name = masked_card_holder_name.peek().to_string(); - if card_holder_name.len() > 256 { - Err(report!(errors::ApiErrorResponse::PreconditionFailed { - message: "Invalid Card Holder Name Length".to_string() - }))? - } - // validate card holder name - ::cards::CardHolderName::try_from(card_holder_name).change_context( - errors::ApiErrorResponse::PreconditionFailed { - message: "Invalid Card Holder Name".to_string(), - }, - )?; - } - Ok(()) -} - pub fn infer_payment_type( amount: &api::Amount, mandate_type: Option<&api::MandateTransactionType>, @@ -2017,7 +1969,7 @@ pub async fn retrieve_card_with_permanent_token( card_type: None, card_issuing_country: None, bank_code: None, - nick_name: card_details_from_locker.nick_name.map(masking::Secret::new), + nick_name: card_details_from_locker.nick_name, }; Ok( @@ -2116,7 +2068,7 @@ pub async fn retrieve_card_with_permanent_token( token_cryptogram: None, token_exp_month: token_data.card_exp_month, token_exp_year: token_data.card_exp_year, - nick_name: token_data.nick_name.map(masking::Secret::new), + nick_name: token_data.nick_name, card_issuer: None, card_network: None, card_type: None, @@ -2162,7 +2114,7 @@ pub async fn retrieve_card_with_permanent_token( card_type: None, card_issuing_country: None, bank_code: None, - nick_name: card_details_from_locker.nick_name.map(masking::Secret::new), + nick_name: card_details_from_locker.nick_name, }; Ok( @@ -2196,7 +2148,7 @@ pub async fn fetch_card_details_from_locker( // The card_holder_name from locker retrieved card is considered if it is a non-empty string or else card_holder_name is picked // from payment_method_data.card_token object let name_on_card = if let Some(name) = card.name_on_card.clone() { - if name.clone().expose().is_empty() { + if name.peek().is_empty() { card_token_data .and_then(|token_data| token_data.card_holder_name.clone()) .or(Some(name)) @@ -2218,7 +2170,7 @@ pub async fn fetch_card_details_from_locker( .card_cvc .unwrap_or_default(), card_issuer: None, - nick_name: card.nick_name.map(masking::Secret::new), + nick_name: card.nick_name, card_network: card .card_brand .map(|card_brand| enums::CardNetwork::from_str(&card_brand)) diff --git a/crates/router/src/core/payments/operations/payment_confirm.rs b/crates/router/src/core/payments/operations/payment_confirm.rs index dfc15bdc040..b56260b407e 100644 --- a/crates/router/src/core/payments/operations/payment_confirm.rs +++ b/crates/router/src/core/payments/operations/payment_confirm.rs @@ -7,9 +7,7 @@ use api_models::{ admin::ExtendedCardInfoConfig, enums::FrmSuggestion, // payment_methods::PaymentMethodsData, - payments::{ - Address, ConnectorMandateReferenceId, ExtendedCardInfo, GetAddressFromPaymentMethodData, - }, + payments::{ConnectorMandateReferenceId, ExtendedCardInfo, GetAddressFromPaymentMethodData}, }; use async_trait::async_trait; use common_utils::ext_traits::{AsyncExt, Encode, StringExt, ValueExt}; @@ -712,17 +710,6 @@ impl GetTracker, api::PaymentsRequest> for Pa payment_method_data_billing.get_billing_address() }); - // validate billing name for card holder name - helpers::validate_billing_name( - payment_method_data_billing - .as_ref() - .and_then(|billing: &Address| billing.address.as_ref()) - .or(request - .billing - .as_ref() - .and_then(|billing: &Address| billing.address.as_ref())), - )?; - let unified_address = address.unify_with_payment_method_data_billing(payment_method_data_billing); diff --git a/crates/router/src/core/payments/operations/payment_create.rs b/crates/router/src/core/payments/operations/payment_create.rs index bcdd5fe17cc..697c06603da 100644 --- a/crates/router/src/core/payments/operations/payment_create.rs +++ b/crates/router/src/core/payments/operations/payment_create.rs @@ -985,13 +985,6 @@ impl ValidateRequest> f .as_ref() .and_then(|pmd| pmd.payment_method_data.clone()), )?; - // validate billing name for card holder name - helpers::validate_billing_name( - request - .billing - .as_ref() - .and_then(|billing| billing.address.as_ref()), - )?; helpers::validate_payment_method_fields_present(request)?; diff --git a/crates/router/src/core/payments/operations/payment_update.rs b/crates/router/src/core/payments/operations/payment_update.rs index 0a9f5666dcb..98491cab1db 100644 --- a/crates/router/src/core/payments/operations/payment_update.rs +++ b/crates/router/src/core/payments/operations/payment_update.rs @@ -100,13 +100,6 @@ impl GetTracker, api::PaymentsRequest> for Pa .as_ref() .and_then(|pmd| pmd.payment_method_data.clone()), )?; - // validate billing name for card holder name - helpers::validate_billing_name( - request - .billing - .as_ref() - .and_then(|billing| billing.address.as_ref()), - )?; helpers::validate_payment_status_against_allowed_statuses( &payment_intent.status, diff --git a/crates/router/src/core/payments/tokenization.rs b/crates/router/src/core/payments/tokenization.rs index 14f64cab153..2a157581bdb 100644 --- a/crates/router/src/core/payments/tokenization.rs +++ b/crates/router/src/core/payments/tokenization.rs @@ -8,6 +8,7 @@ use api_models::payment_methods::PaymentMethodsData; use api_models::{ payment_methods::PaymentMethodDataWalletInfo, payments::ConnectorMandateReferenceId, }; +use cards::NameType; use common_enums::{ConnectorMandateStatus, PaymentMethod}; use common_utils::{ crypto::Encryptable, @@ -79,7 +80,7 @@ pub async fn save_payment_method( merchant_account: &domain::MerchantAccount, payment_method_type: Option, key_store: &domain::MerchantKeyStore, - billing_name: Option>, + billing_name: Option, payment_method_billing_address: Option<&api::Address>, business_profile: &domain::Profile, mut original_connector_mandate_reference_id: Option, diff --git a/crates/router/src/core/payouts/helpers.rs b/crates/router/src/core/payouts/helpers.rs index 49b18e53a0c..5f438f4d8d3 100644 --- a/crates/router/src/core/payouts/helpers.rs +++ b/crates/router/src/core/payouts/helpers.rs @@ -1354,7 +1354,10 @@ pub async fn get_additional_payout_data( card_extended_bin: card_extended_bin.clone(), card_exp_month: Some(card_data.expiry_month.clone()), card_exp_year: Some(card_data.expiry_year.clone()), - card_holder_name: card_data.card_holder_name.clone(), + card_holder_name: card_data + .card_holder_name + .clone() + .map(|name| Secret::new(name.peek().to_string())), }, )) }); @@ -1371,7 +1374,10 @@ pub async fn get_additional_payout_data( card_extended_bin, card_exp_month: Some(card_data.expiry_month.clone()), card_exp_year: Some(card_data.expiry_year.clone()), - card_holder_name: card_data.card_holder_name.clone(), + card_holder_name: card_data + .card_holder_name + .clone() + .map(|name| Secret::new(name.peek().to_string())), }, )) })) diff --git a/crates/router/src/core/utils.rs b/crates/router/src/core/utils.rs index 776692d6bec..e6211bd295d 100644 --- a/crates/router/src/core/utils.rs +++ b/crates/router/src/core/utils.rs @@ -72,6 +72,8 @@ pub async fn construct_payout_router_data<'a, F>( merchant_account: &domain::MerchantAccount, payout_data: &mut PayoutData, ) -> RouterResult> { + use cards::NameType; + let merchant_connector_account = payout_data .merchant_connector_account .clone() @@ -89,6 +91,28 @@ pub async fn construct_payout_router_data<'a, F>( number: a.phone_number.clone().map(Encryptable::into_inner), country_code: a.country_code.to_owned(), }; + let first_name = a + .first_name + .clone() + .map(Encryptable::into_inner) + .and_then(|name| { + NameType::try_from(name.expose()) + .map_err(|err| { + report!(errors::ApiErrorResponse::InternalServerError).attach_printable(err) + }) + .ok() + }); + let last_name = a + .last_name + .clone() + .map(Encryptable::into_inner) + .and_then(|name| { + NameType::try_from(name.expose()) + .map_err(|err| { + report!(errors::ApiErrorResponse::InternalServerError).attach_printable(err) + }) + .ok() + }); let address_details = api_models::payments::AddressDetails { city: a.city.to_owned(), country: a.country.to_owned(), @@ -96,8 +120,8 @@ pub async fn construct_payout_router_data<'a, F>( line2: a.line2.clone().map(Encryptable::into_inner), line3: a.line3.clone().map(Encryptable::into_inner), zip: a.zip.clone().map(Encryptable::into_inner), - first_name: a.first_name.clone().map(Encryptable::into_inner), - last_name: a.last_name.clone().map(Encryptable::into_inner), + first_name, + last_name, state: a.state.map(Encryptable::into_inner), }; diff --git a/crates/router/src/types/transformers.rs b/crates/router/src/types/transformers.rs index 210ae715202..0b85e55f7d0 100644 --- a/crates/router/src/types/transformers.rs +++ b/crates/router/src/types/transformers.rs @@ -4,6 +4,7 @@ use api_models::{ enums as api_enums, gsm as gsm_api_types, payment_methods, payments, routing::ConnectorSelection, }; +use cards::NameType; use common_utils::{ consts::X_HS_LATENCY, crypto::Encryptable, @@ -724,6 +725,32 @@ impl From<&domain::Address> for api_types::Address { { None } else { + let first_name = address + .first_name + .clone() + .map(Encryptable::into_inner) + .and_then(|name| { + NameType::try_from(name.expose()) + .map_err(|_| { + report!(errors::ValidationError::InvalidValue { + message: "Invalid first name".to_string() + }) + }) + .ok() + }); + let last_name = address + .last_name + .clone() + .map(Encryptable::into_inner) + .and_then(|name| { + NameType::try_from(name.expose()) + .map_err(|_| { + report!(errors::ValidationError::InvalidValue { + message: "Invalid last name".to_string() + }) + }) + .ok() + }); Some(api_types::AddressDetails { city: address.city.clone(), country: address.country, @@ -732,8 +759,8 @@ impl From<&domain::Address> for api_types::Address { line3: address.line3.clone().map(Encryptable::into_inner), state: address.state.clone().map(Encryptable::into_inner), zip: address.zip.clone().map(Encryptable::into_inner), - first_name: address.first_name.clone().map(Encryptable::into_inner), - last_name: address.last_name.clone().map(Encryptable::into_inner), + first_name, + last_name, }) }; @@ -770,6 +797,32 @@ impl ForeignFrom for api_types::Address { { None } else { + let first_name = address + .first_name + .clone() + .map(Encryptable::into_inner) + .and_then(|name| { + NameType::try_from(name.expose()) + .map_err(|_| { + report!(errors::ValidationError::InvalidValue { + message: "Invalid first name".to_string() + }) + }) + .ok() + }); + let last_name = address + .last_name + .clone() + .map(Encryptable::into_inner) + .and_then(|name| { + NameType::try_from(name.expose()) + .map_err(|_| { + report!(errors::ValidationError::InvalidValue { + message: "Invalid last name".to_string() + }) + }) + .ok() + }); Some(api_types::AddressDetails { city: address.city.clone(), country: address.country, @@ -778,8 +831,8 @@ impl ForeignFrom for api_types::Address { line3: address.line3.clone().map(Encryptable::into_inner), state: address.state.clone().map(Encryptable::into_inner), zip: address.zip.clone().map(Encryptable::into_inner), - first_name: address.first_name.clone().map(Encryptable::into_inner), - last_name: address.last_name.clone().map(Encryptable::into_inner), + first_name, + last_name, }) }; @@ -1623,6 +1676,32 @@ impl ForeignFrom<(storage::PaymentLink, payments::PaymentLinkStatus)> impl From for payments::AddressDetails { fn from(addr: domain::Address) -> Self { + let first_name = addr + .first_name + .clone() + .map(Encryptable::into_inner) + .and_then(|name| { + NameType::try_from(name.expose()) + .map_err(|_| { + report!(errors::ValidationError::InvalidValue { + message: "Invalid first name".to_string() + }) + }) + .ok() + }); + let last_name = addr + .last_name + .clone() + .map(Encryptable::into_inner) + .and_then(|name| { + NameType::try_from(name.expose()) + .map_err(|_| { + report!(errors::ValidationError::InvalidValue { + message: "Invalid first name".to_string() + }) + }) + .ok() + }); Self { city: addr.city, country: addr.country, @@ -1631,8 +1710,8 @@ impl From for payments::AddressDetails { line3: addr.line3.map(Encryptable::into_inner), zip: addr.zip.map(Encryptable::into_inner), state: addr.state.map(Encryptable::into_inner), - first_name: addr.first_name.map(Encryptable::into_inner), - last_name: addr.last_name.map(Encryptable::into_inner), + first_name, + last_name, } } } diff --git a/crates/router/src/utils.rs b/crates/router/src/utils.rs index 9dca6cf3477..f0761709582 100644 --- a/crates/router/src/utils.rs +++ b/crates/router/src/utils.rs @@ -36,7 +36,7 @@ pub use hyperswitch_connectors::utils::QrImage; use hyperswitch_domain_models::payments::PaymentIntent; #[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "customer_v2")))] use hyperswitch_domain_models::type_encryption::{crypto_operation, CryptoOperation}; -use masking::{ExposeInterface, SwitchStrategy}; +use masking::{ExposeInterface, PeekInterface, SwitchStrategy}; use nanoid::nanoid; use router_env::metrics::add_attributes; use serde::de::DeserializeOwned; @@ -791,8 +791,14 @@ impl CustomerAddress for api_models::customers::CustomerRequest { line2: address_details.line2.clone(), line3: address_details.line3.clone(), state: address_details.state.clone(), - first_name: address_details.first_name.clone(), - last_name: address_details.last_name.clone(), + first_name: address_details + .first_name + .clone() + .map(|name| masking::Secret::new(name.peek().to_string())), + last_name: address_details + .last_name + .clone() + .map(|name| masking::Secret::new(name.peek().to_string())), zip: address_details.zip.clone(), phone_number: self.phone.clone(), email: self @@ -853,8 +859,14 @@ impl CustomerAddress for api_models::customers::CustomerRequest { line2: address_details.line2.clone(), line3: address_details.line3.clone(), state: address_details.state.clone(), - first_name: address_details.first_name.clone(), - last_name: address_details.last_name.clone(), + first_name: address_details + .first_name + .clone() + .map(|name| masking::Secret::new(name.peek().to_string())), + last_name: address_details + .last_name + .clone() + .map(|name| masking::Secret::new(name.peek().to_string())), zip: address_details.zip.clone(), phone_number: self.phone.clone(), email: self @@ -927,8 +939,14 @@ impl CustomerAddress for api_models::customers::CustomerUpdateRequest { line2: address_details.line2.clone(), line3: address_details.line3.clone(), state: address_details.state.clone(), - first_name: address_details.first_name.clone(), - last_name: address_details.last_name.clone(), + first_name: address_details + .first_name + .clone() + .map(|name| masking::Secret::new(name.peek().to_string())), + last_name: address_details + .last_name + .clone() + .map(|name| masking::Secret::new(name.peek().to_string())), zip: address_details.zip.clone(), phone_number: self.phone.clone(), email: self @@ -988,8 +1006,14 @@ impl CustomerAddress for api_models::customers::CustomerUpdateRequest { line2: address_details.line2.clone(), line3: address_details.line3.clone(), state: address_details.state.clone(), - first_name: address_details.first_name.clone(), - last_name: address_details.last_name.clone(), + first_name: address_details + .first_name + .clone() + .map(|name| masking::Secret::new(name.peek().to_string())), + last_name: address_details + .last_name + .clone() + .map(|name| masking::Secret::new(name.peek().to_string())), zip: address_details.zip.clone(), phone_number: self.phone.clone(), email: self From 4397e2736a42151e7f1aa095ace9ac00754919b2 Mon Sep 17 00:00:00 2001 From: Sk Sakil Mostak Date: Mon, 16 Dec 2024 12:27:34 +0530 Subject: [PATCH 07/19] feat: add nametype to router crate --- crates/api_models/src/payments.rs | 26 ++++++++++++------- .../src/connectors/worldline/transformers.rs | 2 +- crates/hyperswitch_connectors/src/utils.rs | 8 ++++-- .../stripe/payment_intents/types.rs | 13 +++++++++- .../src/connector/adyen/transformers.rs | 6 +++-- .../adyenplatform/transformers/payouts.rs | 3 +-- .../connector/authorizedotnet/transformers.rs | 12 ++++----- .../connector/bankofamerica/transformers.rs | 4 +-- .../src/connector/bluesnap/transformers.rs | 4 +-- .../src/connector/cybersource/transformers.rs | 4 +-- .../src/connector/mifinity/transformers.rs | 5 ++-- .../connector/netcetera/netcetera_types.rs | 3 +-- .../src/connector/nuvei/transformers.rs | 6 ++--- .../src/connector/payone/transformers.rs | 1 + .../src/connector/paypal/transformers.rs | 4 +-- .../connector/riskified/transformers/api.rs | 17 ++++++------ .../connector/signifyd/transformers/api.rs | 5 ++-- .../src/connector/stripe/transformers.rs | 11 +++++--- .../src/connector/trustpay/transformers.rs | 3 ++- crates/router/src/connector/utils.rs | 18 ++++++------- .../src/connector/wellsfargo/transformers.rs | 4 +-- crates/router/src/core/payment_methods.rs | 17 +++++++++--- .../router/src/core/payment_methods/cards.rs | 2 +- .../router/src/core/payments/tokenization.rs | 3 +-- crates/router/src/types/api/payments.rs | 4 +-- 25 files changed, 107 insertions(+), 78 deletions(-) diff --git a/crates/api_models/src/payments.rs b/crates/api_models/src/payments.rs index a6a7079f33d..6a8444bab62 100644 --- a/crates/api_models/src/payments.rs +++ b/crates/api_models/src/payments.rs @@ -1606,9 +1606,7 @@ impl GetAddressFromPaymentMethodData for Card { let first_name = card_holder_name_iter .next() .map(ToOwned::to_owned) - .and_then(|name| { - NameType::try_from(name).ok() - }); + .and_then(|name| NameType::try_from(name).ok()); let last_name = card_holder_name_iter.collect::>().join(" "); let last_name = if last_name.is_empty_after_trim() { @@ -3826,9 +3824,11 @@ pub struct AddressDetails { impl AddressDetails { pub fn get_optional_full_name(&self) -> Option> { match (self.first_name.as_ref(), self.last_name.as_ref()) { - (Some(first_name), Some(last_name)) => { - Some(Secret::new(format!("{} {}", first_name.peek(), last_name.peek()))) - } + (Some(first_name), Some(last_name)) => Some(Secret::new(format!( + "{} {}", + first_name.peek(), + last_name.peek() + ))), (Some(name), None) | (None, Some(name)) => Some(Secret::from(name.to_owned())), _ => None, } @@ -6970,7 +6970,7 @@ mod billing_from_payment_method_data { #[test] fn test_bank_redirect_payment_method_data_eps() { let test_email = Email::try_from("example@example.com".to_string()).unwrap(); - let test_first_name = Secret::new(String::from("Chaser")); + let test_first_name = NameType::try_from(String::from("Chaser")).unwrap(); let bank_redirect_billing = BankRedirectBilling { billing_name: Some(test_first_name.clone()), @@ -7021,7 +7021,7 @@ mod billing_from_payment_method_data { #[test] fn test_bank_debit_payment_method_data_ach() { let test_email = Email::try_from("example@example.com".to_string()).unwrap(); - let test_first_name = Secret::new(String::from("Chaser")); + let test_first_name = NameType::try_from(String::from("Chaser")).unwrap(); let bank_redirect_billing = BankDebitBilling { name: Some(test_first_name.clone()), @@ -7064,7 +7064,11 @@ mod billing_from_payment_method_data { let billing_address = billing_address.unwrap(); assert_eq!( - billing_address.address.unwrap().first_name.expose_option(), + billing_address + .address + .unwrap() + .first_name + .map(|name| name.peek().to_string()), Some(TEST_FIRST_NAME_SINGLE.into()) ); } @@ -7089,7 +7093,9 @@ mod billing_from_payment_method_data { let billing_address = billing_details.address.unwrap(); assert_eq!( - billing_address.first_name.expose_option(), + billing_address + .first_name + .map(|name| name.peek().to_string()), Some(TEST_FIRST_NAME.into()) ); diff --git a/crates/hyperswitch_connectors/src/connectors/worldline/transformers.rs b/crates/hyperswitch_connectors/src/connectors/worldline/transformers.rs index 94fc9136160..4b5fa0231fb 100644 --- a/crates/hyperswitch_connectors/src/connectors/worldline/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/worldline/transformers.rs @@ -470,7 +470,7 @@ impl From for Shipping { fn from(value: payments::AddressDetails) -> Self { Self { city: value.city.clone(), - country_code: value.country.clone(), + country_code: value.country, name: Some(Name { first_name: value.get_first_name().ok(), surname: value.get_last_name().ok(), diff --git a/crates/hyperswitch_connectors/src/utils.rs b/crates/hyperswitch_connectors/src/utils.rs index cfb71fc20f8..52e7e8f5657 100644 --- a/crates/hyperswitch_connectors/src/utils.rs +++ b/crates/hyperswitch_connectors/src/utils.rs @@ -1164,7 +1164,9 @@ pub trait PaymentsAuthorizeRequestData { fn get_metadata_as_object(&self) -> Option; fn get_authentication_data(&self) -> Result; fn get_customer_name(&self) -> Result, Error>; - fn get_card_holder_name_from_additional_payment_method_data(&self) -> Result, Error>; + fn get_card_holder_name_from_additional_payment_method_data( + &self, + ) -> Result, Error>; } impl PaymentsAuthorizeRequestData for PaymentsAuthorizeData { @@ -1327,7 +1329,9 @@ impl PaymentsAuthorizeRequestData for PaymentsAuthorizeData { .ok_or_else(missing_field_err("customer_name")) } - fn get_card_holder_name_from_additional_payment_method_data(&self) -> Result, Error> { + fn get_card_holder_name_from_additional_payment_method_data( + &self, + ) -> Result, Error> { match &self.additional_payment_method_data { Some(payments::AdditionalPaymentData::Card(card_data)) => Ok(card_data .card_holder_name diff --git a/crates/router/src/compatibility/stripe/payment_intents/types.rs b/crates/router/src/compatibility/stripe/payment_intents/types.rs index 1de5c5ae4f8..8c1e0143b00 100644 --- a/crates/router/src/compatibility/stripe/payment_intents/types.rs +++ b/crates/router/src/compatibility/stripe/payment_intents/types.rs @@ -11,6 +11,8 @@ use common_utils::{ types::MinorUnit, }; use error_stack::ResultExt; +use masking::ExposeInterface; +use router_env::logger; use serde::{Deserialize, Serialize}; use time::PrimitiveDateTime; @@ -942,7 +944,16 @@ fn get_pmd_based_on_payment_method_type( payments::PaymentMethodData::BankRedirect(payments::BankRedirectData::Ideal { billing_details: billing_details.as_ref().map(|billing_data| { payments::BankRedirectBilling { - billing_name: billing_data.get_optional_full_name(), + billing_name: billing_data.get_optional_full_name().and_then(|name| { + NameType::try_from(name.expose()) + .map_err(|err| { + logger::error!( + "Error while converting name to NameType: {}", + err + ); + }) + .ok() + }), email: billing_data.email.clone(), } }), diff --git a/crates/router/src/connector/adyen/transformers.rs b/crates/router/src/connector/adyen/transformers.rs index cae5f508a2e..31935546a68 100644 --- a/crates/router/src/connector/adyen/transformers.rs +++ b/crates/router/src/connector/adyen/transformers.rs @@ -1820,8 +1820,8 @@ fn get_telephone_number(item: &types::PaymentsAuthorizeRouterData) -> Option) -> Option { let billing = address.and_then(|billing| billing.address.as_ref()); Some(ShopperName { - first_name: billing.and_then(|a| a.first_name.clone()), - last_name: billing.and_then(|a| a.last_name.clone()), + first_name: billing.and_then(|a| a.first_name.clone().map(From::from)), + last_name: billing.and_then(|a| a.last_name.clone().map(From::from)), }) } @@ -2161,6 +2161,7 @@ impl TryFrom<(&domain::WalletData, &types::PaymentsAuthorizeRouterData)> holder_name: paze_decrypted_data .billing_address .name + .map(From::from) .or(item.get_optional_billing_full_name()), brand: Some(paze_decrypted_data.payment_card_network.clone()) .and_then(get_adyen_card_network), @@ -4760,6 +4761,7 @@ impl TryFrom<&PayoutMethodData> for PayoutCardDetails { holder_name: card .card_holder_name .clone() + .map(From::from) .get_required_value("card_holder_name") .change_context(errors::ConnectorError::MissingRequiredField { field_name: "payout_method_data.card.holder_name", diff --git a/crates/router/src/connector/adyenplatform/transformers/payouts.rs b/crates/router/src/connector/adyenplatform/transformers/payouts.rs index 62b597824e5..f3f398760c4 100644 --- a/crates/router/src/connector/adyenplatform/transformers/payouts.rs +++ b/crates/router/src/connector/adyenplatform/transformers/payouts.rs @@ -1,6 +1,5 @@ #[cfg(feature = "payouts")] use api_models::webhooks; -use cards::NameType; use common_utils::pii; use error_stack::{report, ResultExt}; use masking::Secret; @@ -69,7 +68,7 @@ pub struct AdyenBankAccountDetails { #[serde(rename_all = "camelCase")] pub struct AdyenBankAccountHolder { address: Option, - full_name: NameType, + full_name: Secret, #[serde(rename = "reference")] customer_id: Option, #[serde(rename = "type")] diff --git a/crates/router/src/connector/authorizedotnet/transformers.rs b/crates/router/src/connector/authorizedotnet/transformers.rs index 42effdb4b4a..b9d8f886f9c 100644 --- a/crates/router/src/connector/authorizedotnet/transformers.rs +++ b/crates/router/src/connector/authorizedotnet/transformers.rs @@ -612,8 +612,8 @@ impl .get_optional_billing() .and_then(|billing_address| billing_address.address.as_ref()) .map(|address| BillTo { - first_name: address.first_name.clone(), - last_name: address.last_name.clone(), + first_name: address.first_name.clone().map(From::from), + last_name: address.last_name.clone().map(From::from), address: address.line1.clone(), city: address.city.clone(), state: address.state.clone(), @@ -752,8 +752,8 @@ impl .get_optional_billing() .and_then(|billing_address| billing_address.address.as_ref()) .map(|address| BillTo { - first_name: address.first_name.clone(), - last_name: address.last_name.clone(), + first_name: address.first_name.clone().map(From::from), + last_name: address.last_name.clone().map(From::from), address: address.line1.clone(), city: address.city.clone(), state: address.state.clone(), @@ -803,8 +803,8 @@ impl .get_optional_billing() .and_then(|billing_address| billing_address.address.as_ref()) .map(|address| BillTo { - first_name: address.first_name.clone(), - last_name: address.last_name.clone(), + first_name: address.first_name.clone().map(From::from), + last_name: address.last_name.clone().map(From::from), address: address.line1.clone(), city: address.city.clone(), state: address.state.clone(), diff --git a/crates/router/src/connector/bankofamerica/transformers.rs b/crates/router/src/connector/bankofamerica/transformers.rs index 1530cbd82f8..5db5ea3d959 100644 --- a/crates/router/src/connector/bankofamerica/transformers.rs +++ b/crates/router/src/connector/bankofamerica/transformers.rs @@ -510,8 +510,8 @@ fn build_bill_to( Ok(address_details .and_then(|addr| { addr.address.as_ref().map(|addr| BillTo { - first_name: addr.first_name.clone(), - last_name: addr.last_name.clone(), + first_name: addr.first_name.clone().map(From::from), + last_name: addr.last_name.clone().map(From::from), address1: addr.line1.clone(), locality: addr.city.clone(), administrative_area: addr.to_state_code_as_optional().ok().flatten(), diff --git a/crates/router/src/connector/bluesnap/transformers.rs b/crates/router/src/connector/bluesnap/transformers.rs index 022512ea1c1..b90cfd2eef0 100644 --- a/crates/router/src/connector/bluesnap/transformers.rs +++ b/crates/router/src/connector/bluesnap/transformers.rs @@ -334,8 +334,8 @@ impl TryFrom<&BluesnapRouterData<&types::PaymentsAuthorizeRouterData>> for Blues billing_contact: BillingDetails { country_code: billing_address.country, address_lines: Some(address), - family_name: billing_address.last_name.to_owned(), - given_name: billing_address.first_name.to_owned(), + family_name: billing_address.last_name.to_owned().map(From::from), + given_name: billing_address.first_name.to_owned().map(From::from), postal_code: billing_address.zip, }, } diff --git a/crates/router/src/connector/cybersource/transformers.rs b/crates/router/src/connector/cybersource/transformers.rs index 2ea36e3e35e..8154abcbc16 100644 --- a/crates/router/src/connector/cybersource/transformers.rs +++ b/crates/router/src/connector/cybersource/transformers.rs @@ -1118,8 +1118,8 @@ fn build_bill_to( Ok(address_details .and_then(|addr| { addr.address.as_ref().map(|addr| BillTo { - first_name: addr.first_name.remove_new_line(), - last_name: addr.last_name.remove_new_line(), + first_name: addr.first_name.clone().map(From::from), + last_name: addr.last_name.clone().map(From::from), address1: addr.line1.remove_new_line(), locality: addr.city.remove_new_line(), administrative_area: addr diff --git a/crates/router/src/connector/mifinity/transformers.rs b/crates/router/src/connector/mifinity/transformers.rs index 5d109a4f5af..1e2c420c767 100644 --- a/crates/router/src/connector/mifinity/transformers.rs +++ b/crates/router/src/connector/mifinity/transformers.rs @@ -1,4 +1,3 @@ -use cards::NameType; use common_utils::{ pii::{self, Email}, types::StringMajorUnit, @@ -75,8 +74,8 @@ pub struct Money { #[derive(Debug, Clone, Serialize, PartialEq)] #[serde(rename_all = "camelCase")] pub struct MifinityClient { - first_name: NameType, - last_name: NameType, + first_name: Secret, + last_name: Secret, phone: Secret, dialing_code: String, nationality: api_models::enums::CountryAlpha2, diff --git a/crates/router/src/connector/netcetera/netcetera_types.rs b/crates/router/src/connector/netcetera/netcetera_types.rs index 65817f29702..d3074aee5c7 100644 --- a/crates/router/src/connector/netcetera/netcetera_types.rs +++ b/crates/router/src/connector/netcetera/netcetera_types.rs @@ -1,6 +1,5 @@ use std::collections::HashMap; -use cards::NameType; use common_utils::pii::Email; use serde::{Deserialize, Serialize}; @@ -614,7 +613,7 @@ pub struct Cardholder { /// /// Starting from EMV 3DS 2.3.1: /// This field is limited to 1-45 characters. - cardholder_name: Option, + cardholder_name: Option>, /// City portion of the shipping address requested by the Cardholder. /// diff --git a/crates/router/src/connector/nuvei/transformers.rs b/crates/router/src/connector/nuvei/transformers.rs index 121ec1d7b7c..8b89e1429bf 100644 --- a/crates/router/src/connector/nuvei/transformers.rs +++ b/crates/router/src/connector/nuvei/transformers.rs @@ -813,9 +813,7 @@ where ( Some(BillingAddress { first_name: Some(first_name.clone()), - last_name: Some( - address.get_last_name().ok().unwrap_or(&first_name).clone(), - ), + last_name: Some(address.get_last_name().ok().unwrap_or(first_name)), email: item.request.get_email_required()?, country: item.get_billing_country()?, }), @@ -1059,7 +1057,7 @@ where let first_name = address.get_first_name()?.clone(); Some(BillingAddress { first_name: Some(first_name.clone()), - last_name: Some(address.get_last_name().ok().unwrap_or(&first_name).clone()), + last_name: Some(address.get_last_name().ok().unwrap_or(first_name)), email: item.request.get_email_required()?, country: item.get_billing_country()?, }) diff --git a/crates/router/src/connector/payone/transformers.rs b/crates/router/src/connector/payone/transformers.rs index 2ac9c083018..0e4593baaf4 100644 --- a/crates/router/src/connector/payone/transformers.rs +++ b/crates/router/src/connector/payone/transformers.rs @@ -146,6 +146,7 @@ impl TryFrom>> card_holder_name: card_data .card_holder_name .clone() + .map(From::from) .get_required_value("card_holder_name") .change_context(errors::ConnectorError::MissingRequiredField { field_name: "payout_method_data.card.holder_name", diff --git a/crates/router/src/connector/paypal/transformers.rs b/crates/router/src/connector/paypal/transformers.rs index c350f151d72..ea787562a81 100644 --- a/crates/router/src/connector/paypal/transformers.rs +++ b/crates/router/src/connector/paypal/transformers.rs @@ -320,7 +320,7 @@ impl From<&PaypalRouterData<&types::PaymentsAuthorizeRouterData>> for ShippingAd .router_data .get_optional_shipping() .and_then(|inner_data| inner_data.address.as_ref()) - .and_then(|inner_data| inner_data.first_name.clone()), + .and_then(|inner_data| inner_data.first_name.clone().map(From::from)), }), } } @@ -335,7 +335,7 @@ impl From<&PaypalRouterData<&types::PaymentsPostSessionTokensRouterData>> for Sh .router_data .get_optional_shipping() .and_then(|inner_data| inner_data.address.as_ref()) - .and_then(|inner_data| inner_data.first_name.clone()), + .and_then(|inner_data| inner_data.first_name.clone().map(From::from)), }), } } diff --git a/crates/router/src/connector/riskified/transformers/api.rs b/crates/router/src/connector/riskified/transformers/api.rs index 0ab0e3da65c..00adb871ea0 100644 --- a/crates/router/src/connector/riskified/transformers/api.rs +++ b/crates/router/src/connector/riskified/transformers/api.rs @@ -1,5 +1,4 @@ use api_models::payments::AdditionalPaymentData; -use cards::NameType; use common_utils::{ ext_traits::ValueExt, id_type, @@ -105,8 +104,8 @@ pub struct ClientDetails { #[derive(Debug, Deserialize, Serialize, Eq, PartialEq, Clone)] pub struct RiskifiedCustomer { email: Option, - first_name: Option, - last_name: Option, + first_name: Option>, + last_name: Option>, #[serde(with = "common_utils::custom_serde::iso8601")] created_at: PrimitiveDateTime, verified_email: bool, @@ -124,8 +123,8 @@ pub enum CustomerAccountType { #[derive(Debug, Deserialize, Serialize, Eq, PartialEq, Clone)] pub struct OrderAddress { - first_name: Option, - last_name: Option, + first_name: Option>, + last_name: Option>, address1: Option>, country_code: Option, city: Option, @@ -228,8 +227,8 @@ impl TryFrom<&RiskifiedRouterData<&frm_types::FrmCheckoutRouterData>> customer: RiskifiedCustomer { email: payment_data.request.email.clone(), - first_name: address.get_first_name().ok().cloned(), - last_name: address.get_last_name().ok().cloned(), + first_name: address.get_first_name().ok(), + last_name: address.get_last_name().ok(), created_at: common_utils::date_time::now(), verified_email: false, id: payment_data.get_customer_id()?, @@ -632,8 +631,8 @@ impl TryFrom<&api_models::payments::Address> for OrderAddress { field_name: "address", })?; Ok(Self { - first_name: address.first_name.clone(), - last_name: address.last_name.clone(), + first_name: address.first_name.clone().map(From::from), + last_name: address.last_name.clone().map(From::from), address1: address.line1.clone(), country_code: address.country, city: address.city.clone(), diff --git a/crates/router/src/connector/signifyd/transformers/api.rs b/crates/router/src/connector/signifyd/transformers/api.rs index 44c11ff8421..45cc7e50613 100644 --- a/crates/router/src/connector/signifyd/transformers/api.rs +++ b/crates/router/src/connector/signifyd/transformers/api.rs @@ -1,4 +1,3 @@ -use cards::NameType; use common_utils::{ext_traits::ValueExt, pii::Email}; use error_stack::{self, ResultExt}; pub use hyperswitch_domain_models::router_request_types::fraud_check::RefundMethod; @@ -92,7 +91,7 @@ pub struct Shipments { #[derive(Debug, Deserialize, Serialize, Eq, PartialEq, Clone)] #[serde(rename_all = "camelCase")] pub struct Destination { - full_name: NameType, + full_name: Secret, organization: Option, email: Option, address: Address, @@ -563,7 +562,7 @@ impl From for Product { impl From for Destination { fn from(destination: core_types::Destination) -> Self { Self { - full_name: destination.full_name, + full_name: destination.full_name.into(), organization: destination.organization, email: destination.email, address: Address::from(destination.address), diff --git a/crates/router/src/connector/stripe/transformers.rs b/crates/router/src/connector/stripe/transformers.rs index 6d9a4f1c459..b963740fb0d 100644 --- a/crates/router/src/connector/stripe/transformers.rs +++ b/crates/router/src/connector/stripe/transformers.rs @@ -1643,11 +1643,11 @@ impl TryFrom<(&types::PaymentsAuthorizeRouterData, MinorUnit)> for PaymentIntent state: shipping_address.and_then(|a| a.state.clone()), name: format!( "{} {}", - first_name.clone().expose(), + first_name.clone().peek(), shipping_detail .last_name .clone() - .expose_option() + .map(|last_name| last_name.peek().to_string()) .unwrap_or_default() ) .into(), @@ -1679,8 +1679,11 @@ impl TryFrom<(&types::PaymentsAuthorizeRouterData, MinorUnit)> for PaymentIntent a.first_name.as_ref().map(|first_name| { format!( "{} {}", - first_name.clone().expose(), - a.last_name.clone().expose_option().unwrap_or_default() + first_name.clone().peek(), + a.last_name + .clone() + .map(|name| name.peek().to_string()) + .unwrap_or_default() ) .into() }) diff --git a/crates/router/src/connector/trustpay/transformers.rs b/crates/router/src/connector/trustpay/transformers.rs index dafca256529..d40655ae72d 100644 --- a/crates/router/src/connector/trustpay/transformers.rs +++ b/crates/router/src/connector/trustpay/transformers.rs @@ -1,5 +1,6 @@ use std::collections::HashMap; +use cards::NameType; use common_utils::{ errors::CustomResult, pii::{self, Email}, @@ -312,7 +313,7 @@ fn get_card_request_data( fn get_full_name( billing_first_name: Secret, - billing_last_name: Option>, + billing_last_name: Option, ) -> Secret { match billing_last_name { Some(last_name) => format!("{} {}", billing_first_name.peek(), last_name.peek()).into(), diff --git a/crates/router/src/connector/utils.rs b/crates/router/src/connector/utils.rs index 425333ce1f0..eba15508088 100644 --- a/crates/router/src/connector/utils.rs +++ b/crates/router/src/connector/utils.rs @@ -10,7 +10,6 @@ use api_models::{ payments, }; use base64::Engine; -use cards::NameType; use common_utils::{ date_time, errors::{ParsingError, ReportSwitchExt}, @@ -1796,9 +1795,9 @@ impl PhoneDetailsData for api::PhoneDetails { } pub trait AddressDetailsData { - fn get_first_name(&self) -> Result<&NameType, Error>; - fn get_last_name(&self) -> Result<&NameType, Error>; - fn get_full_name(&self) -> Result; + fn get_first_name(&self) -> Result, Error>; + fn get_last_name(&self) -> Result, Error>; + fn get_full_name(&self) -> Result, Error>; fn get_line1(&self) -> Result<&Secret, Error>; fn get_city(&self) -> Result<&String, Error>; fn get_line2(&self) -> Result<&Secret, Error>; @@ -1813,15 +1812,17 @@ pub trait AddressDetailsData { } impl AddressDetailsData for api::AddressDetails { - fn get_first_name(&self) -> Result<&Secret, Error> { + fn get_first_name(&self) -> Result, Error> { self.first_name - .as_ref() + .clone() + .map(From::from) .ok_or_else(missing_field_err("address.first_name")) } - fn get_last_name(&self) -> Result<&Secret, Error> { + fn get_last_name(&self) -> Result, Error> { self.last_name - .as_ref() + .clone() + .map(From::from) .ok_or_else(missing_field_err("address.last_name")) } @@ -1830,7 +1831,6 @@ impl AddressDetailsData for api::AddressDetails { let last_name = self .get_last_name() .ok() - .cloned() .unwrap_or(Secret::new("".to_string())); let last_name = last_name.peek(); let full_name = format!("{} {}", first_name, last_name).trim().to_string(); diff --git a/crates/router/src/connector/wellsfargo/transformers.rs b/crates/router/src/connector/wellsfargo/transformers.rs index 3a2e35190e6..a60bd95fb5d 100644 --- a/crates/router/src/connector/wellsfargo/transformers.rs +++ b/crates/router/src/connector/wellsfargo/transformers.rs @@ -834,8 +834,8 @@ fn build_bill_to( let ad = Ok(address_details .and_then(|addr| { addr.address.as_ref().map(|addr| BillTo { - first_name: addr.first_name.clone(), - last_name: addr.last_name.clone(), + first_name: addr.first_name.clone().map(From::from), + last_name: addr.last_name.clone().map(From::from), address1: addr.line1.clone(), locality: addr.city.clone(), administrative_area: addr.to_state_code_as_optional().ok().flatten(), diff --git a/crates/router/src/core/payment_methods.rs b/crates/router/src/core/payment_methods.rs index 750bc6dea98..fe682493de2 100644 --- a/crates/router/src/core/payment_methods.rs +++ b/crates/router/src/core/payment_methods.rs @@ -41,8 +41,8 @@ use hyperswitch_domain_models::api::{GenericLinks, GenericLinksData}; use hyperswitch_domain_models::payments::{payment_attempt::PaymentAttempt, PaymentIntent}; #[cfg(all(feature = "v2", feature = "payment_methods_v2"))] use masking::ExposeInterface; -use masking::{PeekInterface, Secret}; -use router_env::{instrument, tracing}; +use masking::{ExposeInterface, PeekInterface, Secret}; +use router_env::{instrument, logger, tracing}; use time::Duration; use super::{ @@ -754,7 +754,7 @@ pub(crate) async fn get_payment_method_create_request( payment_method: Option, payment_method_type: Option, customer_id: &Option, - billing_name: Option, + billing_name: Option>, payment_method_billing_address: Option<&api_models::payments::Address>, ) -> RouterResult { match payment_method_data { @@ -765,7 +765,16 @@ pub(crate) async fn get_payment_method_create_request( card_number: card.card_number.clone(), card_exp_month: card.card_exp_month.clone(), card_exp_year: card.card_exp_year.clone(), - card_holder_name: billing_name, + card_holder_name: billing_name.and_then(|name| { + NameType::try_from(name.expose()) + .map_err(|err| { + logger::error!( + "Failed to convert billing name to NameType: {}", + err + ); + }) + .ok() + }), nick_name: card.nick_name.clone(), card_issuing_country: card.card_issuing_country.clone(), card_network: card.card_network.clone(), diff --git a/crates/router/src/core/payment_methods/cards.rs b/crates/router/src/core/payment_methods/cards.rs index 7c433fc5a1c..972850c90d1 100644 --- a/crates/router/src/core/payment_methods/cards.rs +++ b/crates/router/src/core/payment_methods/cards.rs @@ -2309,7 +2309,7 @@ pub fn validate_payment_method_update( .card_holder_name .map(|name| name.peek().to_string()) .map_or(true, |old_card_holder_name| { - new_card_holder_name != old_card_holder_name.to_string() + new_card_holder_name != old_card_holder_name }) }) || card_updation_obj diff --git a/crates/router/src/core/payments/tokenization.rs b/crates/router/src/core/payments/tokenization.rs index 2a157581bdb..14f64cab153 100644 --- a/crates/router/src/core/payments/tokenization.rs +++ b/crates/router/src/core/payments/tokenization.rs @@ -8,7 +8,6 @@ use api_models::payment_methods::PaymentMethodsData; use api_models::{ payment_methods::PaymentMethodDataWalletInfo, payments::ConnectorMandateReferenceId, }; -use cards::NameType; use common_enums::{ConnectorMandateStatus, PaymentMethod}; use common_utils::{ crypto::Encryptable, @@ -80,7 +79,7 @@ pub async fn save_payment_method( merchant_account: &domain::MerchantAccount, payment_method_type: Option, key_store: &domain::MerchantKeyStore, - billing_name: Option, + billing_name: Option>, payment_method_billing_address: Option<&api::Address>, business_profile: &domain::Profile, mut original_connector_mandate_reference_id: Option, diff --git a/crates/router/src/types/api/payments.rs b/crates/router/src/types/api/payments.rs index 524712f1ca0..1ff03bf2436 100644 --- a/crates/router/src/types/api/payments.rs +++ b/crates/router/src/types/api/payments.rs @@ -124,14 +124,14 @@ mod payments_test { 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: Some(masking::Secret::new("JohnDoe".to_string())), + card_holder_name: cards::NameType::try_from("JohnDoe".to_string()).ok(), card_cvc: "123".to_string().into(), card_issuer: Some("HDFC".to_string()), card_network: Some(api_models::enums::CardNetwork::Visa), bank_code: None, card_issuing_country: None, card_type: None, - nick_name: Some(masking::Secret::new("nick_name".into())), + nick_name: cards::NameType::try_from("nick_name".into()).ok(), } } From f8980db27e5fd1dad49308c1bcf65e1652583b57 Mon Sep 17 00:00:00 2001 From: Sk Sakil Mostak Date: Fri, 20 Dec 2024 18:16:29 +0530 Subject: [PATCH 08/19] refactor: unit tests --- crates/api_models/src/payments.rs | 1 - crates/cards/src/validate.rs | 33 +++++++++---------- crates/router/src/types/api/payments.rs | 2 +- crates/router/tests/connectors/aci.rs | 8 ++--- crates/router/tests/connectors/adyen.rs | 8 ++--- crates/router/tests/connectors/airwallex.rs | 6 ++-- crates/router/tests/connectors/bitpay.rs | 4 +-- crates/router/tests/connectors/bluesnap.rs | 4 +-- crates/router/tests/connectors/coinbase.rs | 4 +-- crates/router/tests/connectors/cryptopay.rs | 4 +-- crates/router/tests/connectors/cybersource.rs | 4 +-- crates/router/tests/connectors/fiserv.rs | 2 +- crates/router/tests/connectors/forte.rs | 4 +-- crates/router/tests/connectors/iatapay.rs | 4 +-- .../router/tests/connectors/multisafepay.rs | 4 +-- crates/router/tests/connectors/opennode.rs | 4 +-- crates/router/tests/connectors/payme.rs | 4 +-- crates/router/tests/connectors/rapyd.rs | 4 +-- crates/router/tests/connectors/trustpay.rs | 4 +-- crates/router/tests/connectors/utils.rs | 6 ++-- crates/router/tests/connectors/worldline.rs | 6 ++-- crates/router/tests/payments.rs | 8 ++--- crates/router/tests/payments2.rs | 8 ++--- 23 files changed, 67 insertions(+), 69 deletions(-) diff --git a/crates/api_models/src/payments.rs b/crates/api_models/src/payments.rs index 6a8444bab62..3290e0ee7c2 100644 --- a/crates/api_models/src/payments.rs +++ b/crates/api_models/src/payments.rs @@ -6938,7 +6938,6 @@ mod payments_response_api_contract { mod billing_from_payment_method_data { #![allow(clippy::unwrap_used)] use common_enums::CountryAlpha2; - use masking::ExposeOptionInterface; use super::*; diff --git a/crates/cards/src/validate.rs b/crates/cards/src/validate.rs index 1f599b119e7..53492751a52 100644 --- a/crates/cards/src/validate.rs +++ b/crates/cards/src/validate.rs @@ -401,26 +401,25 @@ mod tests { assert_eq!(error_msg, "card number invalid".to_string()); } - // #[test] - // fn test_card_holder_name() { - - // let valid_name = LengthString::<256, 1>::try_from("Sakil O'Neil".to_string().into()).unwrap(); - // // no panic - // let card_holder_name = NameType::try_from("Sakil O'Neil".to_string()).unwrap(); + #[test] + fn test_card_holder_name() { + let valid_name = "Sakil Mostak".to_string(); + // no panic + let card_holder_name = NameType::try_from("Sakil Mostak".to_string()).unwrap(); - // // will panic on unwrap - // let invalid_card_holder_name = NameType::try_from("$@k!l M*$t@k".to_string()); + // will panic on unwrap + let invalid_card_holder_name = NameType::try_from("$@k!l M*$t@k".to_string()); - // assert_eq!(*card_holder_name.peek(), valid_name); - // assert!(invalid_card_holder_name.is_err()); + assert_eq!(*card_holder_name.peek().to_string(), valid_name); + assert!(invalid_card_holder_name.is_err()); - // let serialized = serde_json::to_string(&card_holder_name).unwrap(); - // assert_eq!(&serialized, "\"Sakil O'Neil\""); + let serialized = serde_json::to_string(&card_holder_name).unwrap(); + assert_eq!(&serialized, "\"Sakil Mostak\""); - // let derialized = serde_json::from_str::(&serialized).unwrap(); - // assert_eq!(*derialized.peek(), valid_name); + let derialized = serde_json::from_str::(&serialized).unwrap(); + assert_eq!(derialized.peek().to_string(), valid_name); - // let invalid_deserialization = serde_json::from_str::("$@k!l M*$t@k"); - // assert!(invalid_deserialization.is_err()); - // } + let invalid_deserialization = serde_json::from_str::("$@k!l M*$t@k"); + assert!(invalid_deserialization.is_err()); + } } diff --git a/crates/router/src/types/api/payments.rs b/crates/router/src/types/api/payments.rs index 1ff03bf2436..03d594e1608 100644 --- a/crates/router/src/types/api/payments.rs +++ b/crates/router/src/types/api/payments.rs @@ -131,7 +131,7 @@ mod payments_test { bank_code: None, card_issuing_country: None, card_type: None, - nick_name: cards::NameType::try_from("nick_name".into()).ok(), + nick_name: cards::NameType::try_from("nick_name".to_string()).ok(), } } diff --git a/crates/router/tests/connectors/aci.rs b/crates/router/tests/connectors/aci.rs index 751359c7763..6c0a88d6b55 100644 --- a/crates/router/tests/connectors/aci.rs +++ b/crates/router/tests/connectors/aci.rs @@ -50,7 +50,7 @@ fn construct_payment_router_data() -> types::PaymentsAuthorizeRouterData { card_type: None, card_issuing_country: None, bank_code: None, - nick_name: Some(Secret::new("nick_name".into())), + nick_name: cards::NameType::try_from("nick_name".to_string()).ok(), }), confirm: true, statement_descriptor_suffix: None, @@ -87,8 +87,8 @@ fn construct_payment_router_data() -> types::PaymentsAuthorizeRouterData { None, Some(Address { address: Some(AddressDetails { - first_name: Some(Secret::new("John".to_string())), - last_name: Some(Secret::new("Doe".to_string())), + first_name: cards::NameType::try_from("John".to_string()).ok(), + last_name: cards::NameType::try_from("Doe".to_string()).ok(), ..Default::default() }), phone: Some(PhoneDetails { @@ -295,7 +295,7 @@ async fn payments_create_failure() { card_type: None, card_issuing_country: None, bank_code: None, - nick_name: Some(Secret::new("nick_name".into())), + nick_name: cards::NameType::try_from("nick_name".to_string()).ok(), }); let response = services::api::execute_connector_processing_step( diff --git a/crates/router/tests/connectors/adyen.rs b/crates/router/tests/connectors/adyen.rs index 2e8d4ab6862..bb9ba2b1d59 100644 --- a/crates/router/tests/connectors/adyen.rs +++ b/crates/router/tests/connectors/adyen.rs @@ -62,8 +62,8 @@ impl AdyenTest { line1: Some(Secret::new("1467".to_string())), line2: Some(Secret::new("Harrison Street".to_string())), line3: None, - first_name: Some(Secret::new("John".to_string())), - last_name: Some(Secret::new("Dough".to_string())), + first_name: cards::NameType::try_from("John".to_string()).ok(), + last_name: cards::NameType::try_from("Dough".to_string()).ok(), }), phone: Some(PhoneDetails { number: Some(Secret::new("9123456789".to_string())), @@ -108,7 +108,7 @@ impl AdyenTest { card_number: cards::CardNumber::from_str("4111111111111111").unwrap(), expiry_month: Secret::new("3".to_string()), expiry_year: Secret::new("2030".to_string()), - card_holder_name: Some(Secret::new("John Doe".to_string())), + card_holder_name: cards::NameType::try_from("John Doe".to_string()).ok(), }, )), enums::PayoutType::Bank => Some(types::api::PayoutMethodData::Bank( @@ -152,7 +152,7 @@ impl AdyenTest { card_type: None, card_issuing_country: None, bank_code: None, - nick_name: Some(Secret::new("nick_name".into())), + nick_name: cards::NameType::try_from("nick_name".to_string()).ok(), }), confirm: true, statement_descriptor_suffix: None, diff --git a/crates/router/tests/connectors/airwallex.rs b/crates/router/tests/connectors/airwallex.rs index f46a0cf7597..e35bebfc1da 100644 --- a/crates/router/tests/connectors/airwallex.rs +++ b/crates/router/tests/connectors/airwallex.rs @@ -57,8 +57,8 @@ fn get_default_payment_info() -> Option { None, Some(Address { address: Some(AddressDetails { - first_name: Some(Secret::new("John".to_string())), - last_name: Some(Secret::new("Doe".to_string())), + first_name: cards::NameType::try_from("John".to_string()).ok(), + last_name: cards::NameType::try_from("Doe".to_string()).ok(), ..Default::default() }), phone: None, @@ -81,7 +81,7 @@ fn payment_method_details() -> Option { card_type: None, card_issuing_country: None, bank_code: None, - nick_name: Some(Secret::new("nick_name".into())), + nick_name: cards::NameType::try_from("nick_name".to_string()).ok(), }), capture_method: Some(diesel_models::enums::CaptureMethod::Manual), router_return_url: Some("https://google.com".to_string()), diff --git a/crates/router/tests/connectors/bitpay.rs b/crates/router/tests/connectors/bitpay.rs index 43959fa683c..2790340adec 100644 --- a/crates/router/tests/connectors/bitpay.rs +++ b/crates/router/tests/connectors/bitpay.rs @@ -42,8 +42,8 @@ fn get_default_payment_info() -> Option { None, Some(api::Address { address: Some(api::AddressDetails { - first_name: Some(Secret::new("first".to_string())), - last_name: Some(Secret::new("last".to_string())), + first_name: cards::NameType::try_from("first".to_string()).ok(), + last_name: cards::NameType::try_from("last".to_string()).ok(), line1: Some(Secret::new("line1".to_string())), line2: Some(Secret::new("line2".to_string())), city: Some("city".to_string()), diff --git a/crates/router/tests/connectors/bluesnap.rs b/crates/router/tests/connectors/bluesnap.rs index 73799693d74..a400bb3c937 100644 --- a/crates/router/tests/connectors/bluesnap.rs +++ b/crates/router/tests/connectors/bluesnap.rs @@ -50,8 +50,8 @@ fn get_payment_info() -> Option { None, Some(Address { address: Some(AddressDetails { - first_name: Some(Secret::new("joseph".to_string())), - last_name: Some(Secret::new("Doe".to_string())), + first_name: cards::NameType::try_from("joseph".to_string()).ok(), + last_name: cards::NameType::try_from("Doe".to_string()).ok(), ..Default::default() }), phone: None, diff --git a/crates/router/tests/connectors/coinbase.rs b/crates/router/tests/connectors/coinbase.rs index 20be2e502ba..88871515dcc 100644 --- a/crates/router/tests/connectors/coinbase.rs +++ b/crates/router/tests/connectors/coinbase.rs @@ -43,8 +43,8 @@ fn get_default_payment_info() -> Option { None, Some(api::Address { address: Some(api::AddressDetails { - first_name: Some(Secret::new("first".to_string())), - last_name: Some(Secret::new("last".to_string())), + first_name: cards::NameType::try_from("first".to_string()).ok(), + last_name: cards::NameType::try_from("last".to_string()).ok(), line1: Some(Secret::new("line1".to_string())), line2: Some(Secret::new("line2".to_string())), city: Some("city".to_string()), diff --git a/crates/router/tests/connectors/cryptopay.rs b/crates/router/tests/connectors/cryptopay.rs index b5f57f7d6f5..f65c1c74f3a 100644 --- a/crates/router/tests/connectors/cryptopay.rs +++ b/crates/router/tests/connectors/cryptopay.rs @@ -42,8 +42,8 @@ fn get_default_payment_info() -> Option { None, Some(api::Address { address: Some(api::AddressDetails { - first_name: Some(Secret::new("first".to_string())), - last_name: Some(Secret::new("last".to_string())), + first_name: cards::NameType::try_from("first".to_string()).ok(), + last_name: cards::NameType::try_from("last".to_string()).ok(), line1: Some(Secret::new("line1".to_string())), line2: Some(Secret::new("line2".to_string())), city: Some("city".to_string()), diff --git a/crates/router/tests/connectors/cybersource.rs b/crates/router/tests/connectors/cybersource.rs index 0116b52f4ed..bda7d1e443a 100644 --- a/crates/router/tests/connectors/cybersource.rs +++ b/crates/router/tests/connectors/cybersource.rs @@ -39,8 +39,8 @@ fn get_default_payment_info() -> Option { None, Some(api::Address { address: Some(api::AddressDetails { - first_name: Some(Secret::new("first".to_string())), - last_name: Some(Secret::new("last".to_string())), + first_name: cards::NameType::try_from("first".to_string()).ok(), + last_name: cards::NameType::try_from("last".to_string()).ok(), line1: Some(Secret::new("line1".to_string())), line2: Some(Secret::new("line2".to_string())), city: Some("city".to_string()), diff --git a/crates/router/tests/connectors/fiserv.rs b/crates/router/tests/connectors/fiserv.rs index bfa16d74f54..18632b55f70 100644 --- a/crates/router/tests/connectors/fiserv.rs +++ b/crates/router/tests/connectors/fiserv.rs @@ -52,7 +52,7 @@ fn payment_method_details() -> Option { card_type: None, card_issuing_country: None, bank_code: None, - nick_name: Some(Secret::new("nick_name".into())), + nick_name: cards::NameType::try_from("nick_name".to_string()).ok(), }), capture_method: Some(diesel_models::enums::CaptureMethod::Manual), ..utils::PaymentAuthorizeType::default().0 diff --git a/crates/router/tests/connectors/forte.rs b/crates/router/tests/connectors/forte.rs index fa084fc4b2c..2565a19ee5e 100644 --- a/crates/router/tests/connectors/forte.rs +++ b/crates/router/tests/connectors/forte.rs @@ -56,8 +56,8 @@ fn get_default_payment_info() -> Option { None, Some(api::Address { address: Some(api::AddressDetails { - first_name: Some(Secret::new("first".to_string())), - last_name: Some(Secret::new("last".to_string())), + first_name: cards::NameType::try_from("first".to_string()).ok(), + last_name: cards::NameType::try_from("last".to_string()).ok(), line1: Some(Secret::new("line1".to_string())), line2: Some(Secret::new("line2".to_string())), city: Some("city".to_string()), diff --git a/crates/router/tests/connectors/iatapay.rs b/crates/router/tests/connectors/iatapay.rs index 577da6ce685..ac1e23c05ba 100644 --- a/crates/router/tests/connectors/iatapay.rs +++ b/crates/router/tests/connectors/iatapay.rs @@ -59,8 +59,8 @@ fn get_default_payment_info() -> Option { None, Some(api::Address { address: Some(api::AddressDetails { - first_name: Some(Secret::new("first".to_string())), - last_name: Some(Secret::new("last".to_string())), + first_name: cards::NameType::try_from("first".to_string()).ok(), + last_name: cards::NameType::try_from("last".to_string()).ok(), line1: Some(Secret::new("line1".to_string())), line2: Some(Secret::new("line2".to_string())), city: Some("city".to_string()), diff --git a/crates/router/tests/connectors/multisafepay.rs b/crates/router/tests/connectors/multisafepay.rs index 0d5af818c35..70c2fcd2434 100644 --- a/crates/router/tests/connectors/multisafepay.rs +++ b/crates/router/tests/connectors/multisafepay.rs @@ -42,8 +42,8 @@ fn get_default_payment_info() -> Option { None, Some(Address { address: Some(AddressDetails { - first_name: Some(Secret::new("John".to_string())), - last_name: Some(Secret::new("Doe".to_string())), + first_name: cards::NameType::try_from("John".to_string()).ok(), + last_name: cards::NameType::try_from("Doe".to_string()).ok(), line1: Some(Secret::new("Kraanspoor".to_string())), line2: Some(Secret::new("line2".to_string())), line3: Some(Secret::new("line3".to_string())), diff --git a/crates/router/tests/connectors/opennode.rs b/crates/router/tests/connectors/opennode.rs index e8778f9f423..ac54a294ceb 100644 --- a/crates/router/tests/connectors/opennode.rs +++ b/crates/router/tests/connectors/opennode.rs @@ -42,8 +42,8 @@ fn get_default_payment_info() -> Option { None, Some(api::Address { address: Some(api::AddressDetails { - first_name: Some(Secret::new("first".to_string())), - last_name: Some(Secret::new("last".to_string())), + first_name: cards::NameType::try_from("first".to_string()).ok(), + last_name: cards::NameType::try_from("last".to_string()).ok(), line1: Some(Secret::new("line1".to_string())), line2: Some(Secret::new("line2".to_string())), city: Some("city".to_string()), diff --git a/crates/router/tests/connectors/payme.rs b/crates/router/tests/connectors/payme.rs index dbc3795e7f1..11c4d19618a 100644 --- a/crates/router/tests/connectors/payme.rs +++ b/crates/router/tests/connectors/payme.rs @@ -54,8 +54,8 @@ fn get_default_payment_info() -> Option { line3: None, zip: None, state: None, - first_name: Some(Secret::new("John".to_string())), - last_name: Some(Secret::new("Doe".to_string())), + first_name: cards::NameType::try_from("John".to_string()).ok(), + last_name: cards::NameType::try_from("Doe".to_string()).ok(), }), phone: None, email: None, diff --git a/crates/router/tests/connectors/rapyd.rs b/crates/router/tests/connectors/rapyd.rs index ff083a37e59..17ce6205079 100644 --- a/crates/router/tests/connectors/rapyd.rs +++ b/crates/router/tests/connectors/rapyd.rs @@ -52,7 +52,7 @@ async fn should_only_authorize_payment() { card_type: None, card_issuing_country: None, bank_code: None, - nick_name: Some(Secret::new("nick_name".into())), + nick_name: cards::NameType::try_from("nick_name".to_string()).ok(), }), capture_method: Some(diesel_models::enums::CaptureMethod::Manual), ..utils::PaymentAuthorizeType::default().0 @@ -79,7 +79,7 @@ async fn should_authorize_and_capture_payment() { card_type: None, card_issuing_country: None, bank_code: None, - nick_name: Some(Secret::new("nick_name".into())), + nick_name: cards::NameType::try_from("nick_name".to_string()).ok(), }), ..utils::PaymentAuthorizeType::default().0 }), diff --git a/crates/router/tests/connectors/trustpay.rs b/crates/router/tests/connectors/trustpay.rs index bae62913a9a..95d17967d54 100644 --- a/crates/router/tests/connectors/trustpay.rs +++ b/crates/router/tests/connectors/trustpay.rs @@ -71,8 +71,8 @@ fn get_default_payment_info() -> Option { None, Some(api::Address { address: Some(api::AddressDetails { - first_name: Some(Secret::new("first".to_string())), - last_name: Some(Secret::new("last".to_string())), + first_name: cards::NameType::try_from("first".to_string()).ok(), + last_name: cards::NameType::try_from("last".to_string()).ok(), line1: Some(Secret::new("line1".to_string())), line2: Some(Secret::new("line2".to_string())), city: Some("city".to_string()), diff --git a/crates/router/tests/connectors/utils.rs b/crates/router/tests/connectors/utils.rs index f8f71a98283..4ff9bff002c 100644 --- a/crates/router/tests/connectors/utils.rs +++ b/crates/router/tests/connectors/utils.rs @@ -80,8 +80,8 @@ impl PaymentInfo { None, Some(types::api::Address { address: Some(types::api::AddressDetails { - first_name: Some(Secret::new("John".to_string())), - last_name: Some(Secret::new("Doe".to_string())), + first_name: cards::NameType::try_from("John".to_string()).ok(), + last_name: cards::NameType::try_from("Doe".to_string()).ok(), ..Default::default() }), phone: None, @@ -926,7 +926,7 @@ impl Default for CCardType { card_type: None, card_issuing_country: None, bank_code: None, - nick_name: Some(Secret::new("nick_name".into())), + nick_name: cards::NameType::try_from("nick_name".to_string()).ok(), }) } } diff --git a/crates/router/tests/connectors/worldline.rs b/crates/router/tests/connectors/worldline.rs index 73e710eb2f1..3faae04d26e 100644 --- a/crates/router/tests/connectors/worldline.rs +++ b/crates/router/tests/connectors/worldline.rs @@ -48,8 +48,8 @@ impl WorldlineTest { Some(Address { address: Some(AddressDetails { country: Some(api_models::enums::CountryAlpha2::US), - first_name: Some(Secret::new(String::from("John"))), - last_name: Some(Secret::new(String::from("Dough"))), + first_name: cards::NameType::try_from(String::from("John")).ok(), + last_name: cards::NameType::try_from(String::from("Dough")).ok(), ..Default::default() }), phone: None, @@ -82,7 +82,7 @@ impl WorldlineTest { card_type: None, card_issuing_country: None, bank_code: None, - nick_name: Some(Secret::new("nick_name".into())), + nick_name: cards::NameType::try_from("nick_name".to_string()).ok(), }), confirm: true, statement_descriptor_suffix: None, diff --git a/crates/router/tests/payments.rs b/crates/router/tests/payments.rs index 68ca08c8bd3..b6931b65f32 100644 --- a/crates/router/tests/payments.rs +++ b/crates/router/tests/payments.rs @@ -341,14 +341,14 @@ async fn payments_create_core() { 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: Some(masking::Secret::new("Arun Raj".to_string())), + card_holder_name: cards::NameType::try_from("Arun Raj".to_string()).ok(), card_cvc: "123".to_string().into(), card_issuer: None, card_network: None, card_type: None, card_issuing_country: None, bank_code: None, - nick_name: Some(masking::Secret::new("nick_name".into())), + nick_name: cards::NameType::try_from("nick_name".to_string()).ok(), })), billing: None, }), @@ -602,14 +602,14 @@ async fn payments_create_core_adyen_no_redirect() { 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: Some(masking::Secret::new("JohnDoe".to_string())), + card_holder_name: cards::NameType::try_from("JohnDoe".to_string()).ok(), card_cvc: "737".to_string().into(), card_issuer: None, card_network: None, card_type: None, card_issuing_country: None, bank_code: None, - nick_name: Some(masking::Secret::new("nick_name".into())), + nick_name: cards::NameType::try_from("nick_name".to_string()).ok(), })), billing: None, }), diff --git a/crates/router/tests/payments2.rs b/crates/router/tests/payments2.rs index 90fe3a1f847..e641d3a6990 100644 --- a/crates/router/tests/payments2.rs +++ b/crates/router/tests/payments2.rs @@ -102,14 +102,14 @@ async fn payments_create_core() { 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: Some(masking::Secret::new("Arun Raj".to_string())), + card_holder_name: cards::NameType::try_from("Arun Raj".to_string()).ok(), card_cvc: "123".to_string().into(), card_issuer: None, card_network: None, card_type: None, card_issuing_country: None, bank_code: None, - nick_name: Some(masking::Secret::new("nick_name".into())), + nick_name: cards::NameType::try_from("nick_name".to_string()).ok(), })), billing: None, }), @@ -371,14 +371,14 @@ async fn payments_create_core_adyen_no_redirect() { 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: Some(masking::Secret::new("JohnDoe".to_string())), + card_holder_name: cards::NameType::try_from("JohnDoe".to_string()).ok(), card_cvc: "737".to_string().into(), bank_code: None, card_issuer: None, card_network: None, card_type: None, card_issuing_country: None, - nick_name: Some(masking::Secret::new("nick_name".into())), + nick_name: cards::NameType::try_from("nick_name".to_string()).ok(), })), billing: None, }), From 998f9900c6db0976ca0492b0569614fc4e1f3407 Mon Sep 17 00:00:00 2001 From: Sk Sakil Mostak Date: Fri, 20 Dec 2024 18:57:53 +0530 Subject: [PATCH 09/19] refactor: nametype implementation for v2 --- crates/api_models/src/payment_methods.rs | 13 +++++-------- crates/router/src/core/payment_methods.rs | 15 +++++++++++---- .../src/core/payment_methods/transformers.rs | 2 +- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/crates/api_models/src/payment_methods.rs b/crates/api_models/src/payment_methods.rs index 57f18869ab9..83f4072f601 100644 --- a/crates/api_models/src/payment_methods.rs +++ b/crates/api_models/src/payment_methods.rs @@ -503,11 +503,11 @@ pub struct CardDetail { /// Card Holder Name #[schema(value_type = String,example = "John Doe")] - pub card_holder_name: Option>, + pub card_holder_name: Option, /// Card Holder's Nick Name #[schema(value_type = Option,example = "John Doe")] - pub nick_name: Option>, + pub nick_name: Option, /// Card Issuing Country #[schema(value_type = CountryAlpha2)] @@ -671,7 +671,7 @@ pub struct CardDetailUpdate { /// Card Holder's Nick Name #[schema(value_type = Option,example = "John Doe")] - pub nick_name: Option>, + pub nick_name: Option, } #[cfg(all(feature = "v2", feature = "payment_methods_v2"))] @@ -685,10 +685,7 @@ impl CardDetailUpdate { .card_holder_name .clone() .or(card_data_from_locker.name_on_card), - nick_name: self - .nick_name - .clone() - .or(card_data_from_locker.nick_name.map(masking::Secret::new)), + nick_name: self.nick_name.clone().or(card_data_from_locker.nick_name), card_issuing_country: None, card_network: None, card_issuer: None, @@ -971,7 +968,7 @@ pub struct CardDetailFromLocker { pub card_fingerprint: Option>, #[schema(value_type=Option)] - pub nick_name: Option>, + pub nick_name: Option, #[schema(value_type = Option)] pub card_network: Option, diff --git a/crates/router/src/core/payment_methods.rs b/crates/router/src/core/payment_methods.rs index fe682493de2..e3670d3beb2 100644 --- a/crates/router/src/core/payment_methods.rs +++ b/crates/router/src/core/payment_methods.rs @@ -39,8 +39,6 @@ use error_stack::{report, ResultExt}; #[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "customer_v2")))] use hyperswitch_domain_models::api::{GenericLinks, GenericLinksData}; use hyperswitch_domain_models::payments::{payment_attempt::PaymentAttempt, PaymentIntent}; -#[cfg(all(feature = "v2", feature = "payment_methods_v2"))] -use masking::ExposeInterface; use masking::{ExposeInterface, PeekInterface, Secret}; use router_env::{instrument, logger, tracing}; use time::Duration; @@ -53,7 +51,7 @@ use super::{ use crate::{ configs::settings, core::{payment_methods::transformers as pm_transforms, utils as core_utils}, - headers, logger, + headers, routes::payment_methods as pm_routes, services::encryption, types::{ @@ -687,7 +685,16 @@ pub(crate) async fn get_payment_method_create_request( card_number: card.card_number.clone(), card_exp_month: card.card_exp_month.clone(), card_exp_year: card.card_exp_year.clone(), - card_holder_name: billing_name, + card_holder_name: billing_name.and_then(|name| { + NameType::try_from(name.expose()) + .map_err(|err| { + logger::error!( + "Failed to convert billing name to NameType: {}", + err + ); + }) + .ok() + }), nick_name: card.nick_name.clone(), card_issuing_country: card .card_issuing_country diff --git a/crates/router/src/core/payment_methods/transformers.rs b/crates/router/src/core/payment_methods/transformers.rs index 07313dd5a9d..a07a3bc7ac2 100644 --- a/crates/router/src/core/payment_methods/transformers.rs +++ b/crates/router/src/core/payment_methods/transformers.rs @@ -830,7 +830,7 @@ pub fn get_card_detail( expiry_year: Some(response.card_exp_year), card_fingerprint: None, card_holder_name: response.name_on_card, - nick_name: response.nick_name.map(Secret::new), + nick_name: response.nick_name, card_isin: None, card_issuer: None, card_network: None, From 5199422d15955460762666c932355536fe363e9e Mon Sep 17 00:00:00 2001 From: Sk Sakil Mostak Date: Mon, 30 Dec 2024 17:26:21 +0530 Subject: [PATCH 10/19] refactor: conversion --- crates/cards/src/validate.rs | 11 +++++- .../src/connectors/worldline/transformers.rs | 6 +-- .../hyperswitch_domain_models/src/address.rs | 2 +- .../stripe/payment_intents/types.rs | 3 +- crates/router/src/core/customers.rs | 5 +-- crates/router/src/core/payment_methods.rs | 8 ++-- crates/router/src/core/payments/helpers.rs | 36 ++++++++---------- crates/router/src/core/payouts/helpers.rs | 10 +---- crates/router/src/core/utils.rs | 6 +-- crates/router/src/types/transformers.rs | 37 +++++++------------ crates/router/src/utils.rs | 30 +++------------ 11 files changed, 60 insertions(+), 94 deletions(-) diff --git a/crates/cards/src/validate.rs b/crates/cards/src/validate.rs index 7d59e7a8ab5..e266cd98c58 100644 --- a/crates/cards/src/validate.rs +++ b/crates/cards/src/validate.rs @@ -2,7 +2,7 @@ use std::{collections::HashMap, fmt, ops::Deref, str::FromStr}; use common_utils::{errors::ValidationError, ext_traits::ConfigExt, types::LengthString}; use error_stack::report; -use masking::{PeekInterface, Secret, Strategy, StrongSecret, WithType}; +use masking::{ExposeInterface, PeekInterface, Secret, Strategy, StrongSecret, WithType}; use once_cell::sync::Lazy; use regex::Regex; #[cfg(not(target_arch = "wasm32"))] @@ -256,6 +256,13 @@ impl TryFrom for NameType { } } +impl TryFrom> for NameType { + type Error = error_stack::Report; + fn try_from(masked_card_holder_name: Secret) -> Result { + Self::try_from(masked_card_holder_name.expose()) + } +} + impl FromStr for NameType { type Err = error_stack::Report; @@ -272,7 +279,7 @@ impl From for Secret { impl From<&NameType> for Secret { fn from(card_holder_name: &NameType) -> Self { - Self::new(card_holder_name.peek().to_string().to_owned()) + Self::new(card_holder_name.peek().to_string()) } } diff --git a/crates/hyperswitch_connectors/src/connectors/worldline/transformers.rs b/crates/hyperswitch_connectors/src/connectors/worldline/transformers.rs index b8cfc5aa01b..c6eb795e51b 100644 --- a/crates/hyperswitch_connectors/src/connectors/worldline/transformers.rs +++ b/crates/hyperswitch_connectors/src/connectors/worldline/transformers.rs @@ -18,7 +18,7 @@ use url::Url; use crate::{ types::{RefundsResponseRouterData, ResponseRouterData}, - utils::{self, AddressDetailsData, CardData, RouterData as RouterDataUtils}, + utils::{self, CardData, RouterData as RouterDataUtils}, }; #[derive(Default, Debug, Serialize, Eq, PartialEq)] @@ -474,8 +474,8 @@ impl From for Shipping { city: value.city.clone(), country_code: value.country, name: Some(Name { - first_name: value.get_first_name().ok(), - surname: value.get_last_name().ok(), + first_name: value.first_name.map(From::from), + surname: value.last_name.map(From::from), ..Default::default() }), state: value.state, diff --git a/crates/hyperswitch_domain_models/src/address.rs b/crates/hyperswitch_domain_models/src/address.rs index 7b4bc70c6a2..684697947d6 100644 --- a/crates/hyperswitch_domain_models/src/address.rs +++ b/crates/hyperswitch_domain_models/src/address.rs @@ -53,7 +53,7 @@ impl AddressDetails { first_name.peek(), last_name.peek() ))), - (Some(name), None) | (None, Some(name)) => Some(Secret::from(name.to_owned())), + (Some(name), None) | (None, Some(name)) => Some(Secret::from(name)), _ => None, } } diff --git a/crates/router/src/compatibility/stripe/payment_intents/types.rs b/crates/router/src/compatibility/stripe/payment_intents/types.rs index 99262bf4f79..ce578519bb3 100644 --- a/crates/router/src/compatibility/stripe/payment_intents/types.rs +++ b/crates/router/src/compatibility/stripe/payment_intents/types.rs @@ -11,7 +11,6 @@ use common_utils::{ types::MinorUnit, }; use error_stack::ResultExt; -use masking::ExposeInterface; use router_env::logger; use serde::{Deserialize, Serialize}; use time::PrimitiveDateTime; @@ -946,7 +945,7 @@ fn get_pmd_based_on_payment_method_type( billing_details: billing_details.as_ref().map(|billing_data| { payments::BankRedirectBilling { billing_name: billing_data.get_optional_full_name().and_then(|name| { - NameType::try_from(name.expose()) + NameType::try_from(name) .map_err(|err| { logger::error!( "Error while converting name to NameType: {}", diff --git a/crates/router/src/core/customers.rs b/crates/router/src/core/customers.rs index 0c337791db4..9f2a5726f91 100644 --- a/crates/router/src/core/customers.rs +++ b/crates/router/src/core/customers.rs @@ -147,10 +147,7 @@ impl CustomerCreateBridge for customers::CustomerRequest { types::CryptoOperation::BatchEncrypt( domain::FromRequestEncryptableCustomer::to_encryptable( domain::FromRequestEncryptableCustomer { - name: self - .name - .clone() - .map(|name| Secret::new(name.peek().to_string())), + name: self.name.clone().map(From::from), email: self.email.clone().map(|a| a.expose().switch_strategy()), phone: self.phone.clone(), }, diff --git a/crates/router/src/core/payment_methods.rs b/crates/router/src/core/payment_methods.rs index c73f5597b86..5eb05f6ec77 100644 --- a/crates/router/src/core/payment_methods.rs +++ b/crates/router/src/core/payment_methods.rs @@ -43,7 +43,9 @@ use error_stack::{report, ResultExt}; #[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "customer_v2")))] use hyperswitch_domain_models::api::{GenericLinks, GenericLinksData}; use hyperswitch_domain_models::payments::{payment_attempt::PaymentAttempt, PaymentIntent}; -use masking::{ExposeInterface, PeekInterface, Secret}; +#[cfg(all(feature = "v2", feature = "payment_methods_v2"))] +use masking::ExposeInterface; +use masking::{PeekInterface, Secret}; use router_env::{instrument, logger, tracing}; use time::Duration; @@ -692,7 +694,7 @@ pub(crate) async fn get_payment_method_create_request( card_exp_month: card.card_exp_month.clone(), card_exp_year: card.card_exp_year.clone(), card_holder_name: billing_name.and_then(|name| { - NameType::try_from(name.expose()) + NameType::try_from(name) .map_err(|err| { logger::error!( "Failed to convert billing name to NameType: {}", @@ -779,7 +781,7 @@ pub(crate) async fn get_payment_method_create_request( card_exp_month: card.card_exp_month.clone(), card_exp_year: card.card_exp_year.clone(), card_holder_name: billing_name.and_then(|name| { - NameType::try_from(name.expose()) + NameType::try_from(name) .map_err(|err| { logger::error!( "Failed to convert billing name to NameType: {}", diff --git a/crates/router/src/core/payments/helpers.rs b/crates/router/src/core/payments/helpers.rs index 8a48021efc7..3cc03e53ce9 100644 --- a/crates/router/src/core/payments/helpers.rs +++ b/crates/router/src/core/payments/helpers.rs @@ -128,16 +128,14 @@ pub async fn create_or_update_address_for_payment_by_request( line2: address.address.as_ref().and_then(|a| a.line2.clone()), line3: address.address.as_ref().and_then(|a| a.line3.clone()), state: address.address.as_ref().and_then(|a| a.state.clone()), - first_name: address.address.as_ref().and_then(|a| { - a.first_name - .clone() - .map(|name| masking::Secret::new(name.peek().to_string())) - }), - last_name: address.address.as_ref().and_then(|a| { - a.last_name - .clone() - .map(|name| masking::Secret::new(name.peek().to_string())) - }), + first_name: address + .address + .as_ref() + .and_then(|a| a.first_name.clone().map(From::from)), + last_name: address + .address + .as_ref() + .and_then(|a| a.last_name.clone().map(From::from)), zip: address.address.as_ref().and_then(|a| a.zip.clone()), phone_number: address .phone @@ -346,16 +344,14 @@ pub async fn get_domain_address( line2: address.address.as_ref().and_then(|a| a.line2.clone()), line3: address.address.as_ref().and_then(|a| a.line3.clone()), state: address.address.as_ref().and_then(|a| a.state.clone()), - first_name: address.address.as_ref().and_then(|a| { - a.first_name - .clone() - .map(|name| masking::Secret::new(name.peek().to_string())) - }), - last_name: address.address.as_ref().and_then(|a| { - a.last_name - .clone() - .map(|name| masking::Secret::new(name.peek().to_string())) - }), + first_name: address + .address + .as_ref() + .and_then(|a| a.first_name.clone().map(From::from)), + last_name: address + .address + .as_ref() + .and_then(|a| a.last_name.clone().map(From::from)), zip: address.address.as_ref().and_then(|a| a.zip.clone()), phone_number: address .phone diff --git a/crates/router/src/core/payouts/helpers.rs b/crates/router/src/core/payouts/helpers.rs index 53e56ede37b..5667f8e4ed2 100644 --- a/crates/router/src/core/payouts/helpers.rs +++ b/crates/router/src/core/payouts/helpers.rs @@ -1354,10 +1354,7 @@ pub async fn get_additional_payout_data( card_extended_bin: card_extended_bin.clone(), card_exp_month: Some(card_data.expiry_month.clone()), card_exp_year: Some(card_data.expiry_year.clone()), - card_holder_name: card_data - .card_holder_name - .clone() - .map(|name| Secret::new(name.peek().to_string())), + card_holder_name: card_data.card_holder_name.clone().map(From::from), }, )) }); @@ -1374,10 +1371,7 @@ pub async fn get_additional_payout_data( card_extended_bin, card_exp_month: Some(card_data.expiry_month.clone()), card_exp_year: Some(card_data.expiry_year.clone()), - card_holder_name: card_data - .card_holder_name - .clone() - .map(|name| Secret::new(name.peek().to_string())), + card_holder_name: card_data.card_holder_name.clone().map(From::from), }, )) })) diff --git a/crates/router/src/core/utils.rs b/crates/router/src/core/utils.rs index 9d729625a5f..8f21fea0670 100644 --- a/crates/router/src/core/utils.rs +++ b/crates/router/src/core/utils.rs @@ -19,7 +19,7 @@ use hyperswitch_domain_models::{ #[cfg(feature = "payouts")] use masking::{ExposeInterface, PeekInterface}; use maud::{html, PreEscaped}; -use router_env::{instrument, tracing}; +use router_env::{instrument, logger, tracing}; use uuid::Uuid; use super::payments::helpers; @@ -98,7 +98,7 @@ pub async fn construct_payout_router_data<'a, F>( .and_then(|name| { NameType::try_from(name.expose()) .map_err(|err| { - report!(errors::ApiErrorResponse::InternalServerError).attach_printable(err) + logger::error!("Error in converting first name: {err}"); }) .ok() }); @@ -109,7 +109,7 @@ pub async fn construct_payout_router_data<'a, F>( .and_then(|name| { NameType::try_from(name.expose()) .map_err(|err| { - report!(errors::ApiErrorResponse::InternalServerError).attach_printable(err) + logger::error!("Error in converting last name: {err}"); }) .ok() }); diff --git a/crates/router/src/types/transformers.rs b/crates/router/src/types/transformers.rs index 19418fbd917..96478590802 100644 --- a/crates/router/src/types/transformers.rs +++ b/crates/router/src/types/transformers.rs @@ -17,6 +17,7 @@ use diesel_models::enums as storage_enums; use error_stack::{report, ResultExt}; use hyperswitch_domain_models::payments::payment_intent::CustomerData; use masking::{ExposeInterface, PeekInterface, Secret}; +use router_env::logger; use super::domain; use crate::{ @@ -739,10 +740,8 @@ impl From<&domain::Address> for hyperswitch_domain_models::address::Address { .map(Encryptable::into_inner) .and_then(|name| { NameType::try_from(name.expose()) - .map_err(|_| { - report!(errors::ValidationError::InvalidValue { - message: "Invalid first name".to_string() - }) + .map_err(|err| { + logger::error!("Invalid first name: {err}"); }) .ok() }); @@ -752,10 +751,8 @@ impl From<&domain::Address> for hyperswitch_domain_models::address::Address { .map(Encryptable::into_inner) .and_then(|name| { NameType::try_from(name.expose()) - .map_err(|_| { - report!(errors::ValidationError::InvalidValue { - message: "Invalid last name".to_string() - }) + .map_err(|err| { + logger::error!("Invalid last name {err}"); }) .ok() }); @@ -811,10 +808,8 @@ impl ForeignFrom for api_types::Address { .map(Encryptable::into_inner) .and_then(|name| { NameType::try_from(name.expose()) - .map_err(|_| { - report!(errors::ValidationError::InvalidValue { - message: "Invalid first name".to_string() - }) + .map_err(|err| { + logger::error!("Invalid first name: {err}"); }) .ok() }); @@ -824,10 +819,8 @@ impl ForeignFrom for api_types::Address { .map(Encryptable::into_inner) .and_then(|name| { NameType::try_from(name.expose()) - .map_err(|_| { - report!(errors::ValidationError::InvalidValue { - message: "Invalid last name".to_string() - }) + .map_err(|err| { + logger::error!("Invalid last name {err}"); }) .ok() }); @@ -1695,10 +1688,8 @@ impl From for payments::AddressDetails { .map(Encryptable::into_inner) .and_then(|name| { NameType::try_from(name.expose()) - .map_err(|_| { - report!(errors::ValidationError::InvalidValue { - message: "Invalid first name".to_string() - }) + .map_err(|err| { + logger::error!("Invalid first name: {err}"); }) .ok() }); @@ -1708,10 +1699,8 @@ impl From for payments::AddressDetails { .map(Encryptable::into_inner) .and_then(|name| { NameType::try_from(name.expose()) - .map_err(|_| { - report!(errors::ValidationError::InvalidValue { - message: "Invalid first name".to_string() - }) + .map_err(|err| { + logger::error!("Invalid last name {err}"); }) .ok() }); diff --git a/crates/router/src/utils.rs b/crates/router/src/utils.rs index aea3568f032..c135ce2b2e9 100644 --- a/crates/router/src/utils.rs +++ b/crates/router/src/utils.rs @@ -777,14 +777,8 @@ impl CustomerAddress for api_models::customers::CustomerRequest { line2: address_details.line2.clone(), line3: address_details.line3.clone(), state: address_details.state.clone(), - first_name: address_details - .first_name - .clone() - .map(|name| masking::Secret::new(name.peek().to_string())), - last_name: address_details - .last_name - .clone() - .map(|name| masking::Secret::new(name.peek().to_string())), + first_name: address_details.first_name.clone().map(From::from), + last_name: address_details.last_name.clone().map(From::from), zip: address_details.zip.clone(), phone_number: self.phone.clone(), email: self @@ -925,14 +919,8 @@ impl CustomerAddress for api_models::customers::CustomerUpdateRequest { line2: address_details.line2.clone(), line3: address_details.line3.clone(), state: address_details.state.clone(), - first_name: address_details - .first_name - .clone() - .map(|name| masking::Secret::new(name.peek().to_string())), - last_name: address_details - .last_name - .clone() - .map(|name| masking::Secret::new(name.peek().to_string())), + first_name: address_details.first_name.clone().map(From::from), + last_name: address_details.last_name.clone().map(From::from), zip: address_details.zip.clone(), phone_number: self.phone.clone(), email: self @@ -992,14 +980,8 @@ impl CustomerAddress for api_models::customers::CustomerUpdateRequest { line2: address_details.line2.clone(), line3: address_details.line3.clone(), state: address_details.state.clone(), - first_name: address_details - .first_name - .clone() - .map(|name| masking::Secret::new(name.peek().to_string())), - last_name: address_details - .last_name - .clone() - .map(|name| masking::Secret::new(name.peek().to_string())), + first_name: address_details.first_name.clone().map(From::from), + last_name: address_details.last_name.clone().map(From::from), zip: address_details.zip.clone(), phone_number: self.phone.clone(), email: self From 53e92b4b00035ab38349bc773b88dfd6646dbf39 Mon Sep 17 00:00:00 2001 From: Sk Sakil Mostak Date: Tue, 14 Jan 2025 20:29:15 +0530 Subject: [PATCH 11/19] refactor: resolve comment --- crates/api_models/src/customers.rs | 6 +- crates/api_models/src/mandates.rs | 2 +- crates/api_models/src/payment_methods.rs | 4 +- crates/api_models/src/payments.rs | 4 +- .../src/payments/additional_info.rs | 8 +- crates/api_models/src/payouts.rs | 4 +- crates/cards/src/lib.rs | 2 +- crates/cards/src/validate.rs | 120 +---------------- crates/common_utils/src/types.rs | 122 +++++++++++++++++- .../hyperswitch_domain_models/src/address.rs | 2 +- .../src/payment_method_data.rs | 2 +- .../src/router_data.rs | 3 +- .../src/router_request_types/fraud_check.rs | 2 +- .../compatibility/stripe/customers/types.rs | 3 +- .../stripe/payment_intents/types.rs | 3 +- .../stripe/setup_intents/types.rs | 3 +- .../connector/stripe/transformers/connect.rs | 3 +- .../src/connector/trustpay/transformers.rs | 3 +- crates/router/src/core/payment_methods.rs | 3 +- .../src/core/payment_methods/transformers.rs | 2 +- .../router/src/core/payment_methods/vault.rs | 2 +- crates/router/src/core/utils.rs | 2 +- crates/router/src/types/api/payments.rs | 4 +- crates/router/src/types/transformers.rs | 3 +- crates/router/tests/connectors/aci.rs | 18 ++- crates/router/tests/connectors/adyen.rs | 18 ++- crates/router/tests/connectors/airwallex.rs | 11 +- crates/router/tests/connectors/bitpay.rs | 4 +- crates/router/tests/connectors/bluesnap.rs | 4 +- crates/router/tests/connectors/coinbase.rs | 4 +- crates/router/tests/connectors/cryptopay.rs | 4 +- crates/router/tests/connectors/cybersource.rs | 4 +- crates/router/tests/connectors/fiserv.rs | 7 +- crates/router/tests/connectors/forte.rs | 4 +- crates/router/tests/connectors/iatapay.rs | 4 +- .../router/tests/connectors/multisafepay.rs | 4 +- crates/router/tests/connectors/opennode.rs | 4 +- crates/router/tests/connectors/payme.rs | 4 +- crates/router/tests/connectors/rapyd.rs | 14 +- crates/router/tests/connectors/trustpay.rs | 4 +- crates/router/tests/connectors/utils.rs | 12 +- crates/router/tests/connectors/worldline.rs | 13 +- crates/router/tests/payments.rs | 10 +- crates/router/tests/payments2.rs | 10 +- 44 files changed, 254 insertions(+), 215 deletions(-) diff --git a/crates/api_models/src/customers.rs b/crates/api_models/src/customers.rs index 12829b98f2f..8275b80fe8e 100644 --- a/crates/api_models/src/customers.rs +++ b/crates/api_models/src/customers.rs @@ -1,5 +1,7 @@ -use cards::NameType; -use common_utils::{crypto, custom_serde, id_type, pii, types::Description}; +use common_utils::{ + crypto, custom_serde, id_type, pii, + types::{Description, NameType}, +}; use masking::Secret; use serde::{Deserialize, Serialize}; use utoipa::ToSchema; diff --git a/crates/api_models/src/mandates.rs b/crates/api_models/src/mandates.rs index ea4a257f73f..cc98a3a7897 100644 --- a/crates/api_models/src/mandates.rs +++ b/crates/api_models/src/mandates.rs @@ -1,4 +1,4 @@ -use cards::NameType; +use common_utils::types::NameType; use masking::Secret; use serde::{Deserialize, Serialize}; use time::PrimitiveDateTime; diff --git a/crates/api_models/src/payment_methods.rs b/crates/api_models/src/payment_methods.rs index 53ac34ce1fd..311ea5b4741 100644 --- a/crates/api_models/src/payment_methods.rs +++ b/crates/api_models/src/payment_methods.rs @@ -2,14 +2,14 @@ use std::collections::{HashMap, HashSet}; #[cfg(all(feature = "v2", feature = "payment_methods_v2"))] use std::str::FromStr; -use cards::{CardNumber, NameType}; +use cards::CardNumber; use common_utils::{ consts::SURCHARGE_PERCENTAGE_PRECISION_LENGTH, crypto::OptionalEncryptableName, errors, ext_traits::OptionExt, id_type, link_utils, pii, - types::{MinorUnit, Percentage, Surcharge}, + types::{MinorUnit, NameType, Percentage, Surcharge}, }; use masking::PeekInterface; use serde::de; diff --git a/crates/api_models/src/payments.rs b/crates/api_models/src/payments.rs index 70597de1832..9dcdd9fad92 100644 --- a/crates/api_models/src/payments.rs +++ b/crates/api_models/src/payments.rs @@ -4,7 +4,7 @@ use std::{ num::NonZeroI64, }; pub mod additional_info; -use cards::{CardNumber, NameType}; +use cards::CardNumber; use common_enums::ProductType; #[cfg(feature = "v2")] use common_utils::id_type::GlobalPaymentId; @@ -16,7 +16,7 @@ use common_utils::{ hashing::HashedString, id_type, pii::{self, Email}, - types::{MinorUnit, StringMajorUnit}, + types::{MinorUnit, NameType, StringMajorUnit}, }; use error_stack::ResultExt; use masking::{ExposeInterface, PeekInterface, Secret, WithType}; diff --git a/crates/api_models/src/payments/additional_info.rs b/crates/api_models/src/payments/additional_info.rs index 647af25f684..7909e112447 100644 --- a/crates/api_models/src/payments/additional_info.rs +++ b/crates/api_models/src/payments/additional_info.rs @@ -1,6 +1,8 @@ -use cards::NameType; -use common_utils::new_type::{ - MaskedBankAccount, MaskedIban, MaskedRoutingNumber, MaskedSortCode, MaskedUpiVpaId, +use common_utils::{ + new_type::{ + MaskedBankAccount, MaskedIban, MaskedRoutingNumber, MaskedSortCode, MaskedUpiVpaId, + }, + types::NameType, }; use masking::Secret; use utoipa::ToSchema; diff --git a/crates/api_models/src/payouts.rs b/crates/api_models/src/payouts.rs index 8f97907d15b..faa4ebd7aa5 100644 --- a/crates/api_models/src/payouts.rs +++ b/crates/api_models/src/payouts.rs @@ -1,12 +1,12 @@ use std::collections::HashMap; -use cards::{CardNumber, NameType}; +use cards::CardNumber; use common_utils::{ consts::default_payouts_list_limit, crypto, id_type, link_utils, payout_method_utils, pii::{self, Email}, transformers::ForeignFrom, - types::{UnifiedCode, UnifiedMessage}, + types::{NameType, UnifiedCode, UnifiedMessage}, }; use masking::Secret; use router_derive::FlatStruct; diff --git a/crates/cards/src/lib.rs b/crates/cards/src/lib.rs index 2f28917a6b3..91cb93301a9 100644 --- a/crates/cards/src/lib.rs +++ b/crates/cards/src/lib.rs @@ -7,7 +7,7 @@ use masking::{PeekInterface, StrongSecret}; use serde::{de, Deserialize, Serialize}; use time::{util::days_in_year_month, Date, Duration, PrimitiveDateTime, Time}; -pub use crate::validate::{CardNumber, CardNumberStrategy, CardNumberValidationErr, NameType}; +pub use crate::validate::{CardNumber, CardNumberStrategy, CardNumberValidationErr}; #[derive(Serialize)] pub struct CardSecurityCode(StrongSecret); diff --git a/crates/cards/src/validate.rs b/crates/cards/src/validate.rs index e266cd98c58..725d05b4807 100644 --- a/crates/cards/src/validate.rs +++ b/crates/cards/src/validate.rs @@ -1,8 +1,8 @@ use std::{collections::HashMap, fmt, ops::Deref, str::FromStr}; -use common_utils::{errors::ValidationError, ext_traits::ConfigExt, types::LengthString}; +use common_utils::errors::ValidationError; use error_stack::report; -use masking::{ExposeInterface, PeekInterface, Secret, Strategy, StrongSecret, WithType}; +use masking::{PeekInterface, Strategy, StrongSecret, WithType}; use once_cell::sync::Lazy; use regex::Regex; #[cfg(not(target_arch = "wasm32"))] @@ -233,100 +233,6 @@ where } } -// #[derive(Debug, Deserialize, Serialize, Error)] -// #[error("{0}")] -// pub struct NameTypeValidationErr(&'static str); - -#[derive(Clone, Default, Debug, Eq, PartialEq, Serialize)] -pub struct NameType(Secret>); - -impl TryFrom for NameType { - type Error = error_stack::Report; - fn try_from(card_holder_name: String) -> Result { - for char in card_holder_name.chars() { - validate_character_in_card_holder_name(char)?; - } - let valid_length_name = - LengthString::<256, 1>::from(card_holder_name.into()).map_err(|_| { - report!(ValidationError::InvalidValue { - message: "invalid length for name".to_string() - }) - })?; - Ok(Self(Secret::new(valid_length_name))) - } -} - -impl TryFrom> for NameType { - type Error = error_stack::Report; - fn try_from(masked_card_holder_name: Secret) -> Result { - Self::try_from(masked_card_holder_name.expose()) - } -} - -impl FromStr for NameType { - type Err = error_stack::Report; - - fn from_str(card_number: &str) -> Result { - Self::try_from(card_number.to_string()) - } -} - -impl From for Secret { - fn from(card_holder_name: NameType) -> Self { - Self::new(card_holder_name.peek().to_string()) - } -} - -impl From<&NameType> for Secret { - fn from(card_holder_name: &NameType) -> Self { - Self::new(card_holder_name.peek().to_string()) - } -} - -fn validate_character_in_card_holder_name( - character: char, -) -> Result<(), error_stack::Report> { - if character.is_alphabetic() - || character == ' ' - || character == '.' - || character == '-' - || character == '\'' - || character == '~' - || character == '`' - { - Ok(()) - } else { - Err(report!(ValidationError::InvalidValue { - message: format!("invalid character found in card holder name: {}", character) - })) - } -} - -impl<'de> Deserialize<'de> for NameType { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - let card_holder_name = String::deserialize(deserializer)?; - card_holder_name - .try_into() - .map_err(serde::de::Error::custom) - } -} - -impl Deref for NameType { - type Target = Secret>; - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl ConfigExt for NameType { - fn is_empty_after_trim(&self) -> bool { - self.peek().trim().is_empty() - } -} - #[cfg(test)] mod tests { #![allow(clippy::unwrap_used)] @@ -413,26 +319,4 @@ mod tests { let error_msg = card_number.unwrap_err().to_string(); assert_eq!(error_msg, "card number invalid".to_string()); } - - #[test] - fn test_card_holder_name() { - let valid_name = "Sakil Mostak".to_string(); - // no panic - let card_holder_name = NameType::try_from("Sakil Mostak".to_string()).unwrap(); - - // will panic on unwrap - let invalid_card_holder_name = NameType::try_from("$@k!l M*$t@k".to_string()); - - assert_eq!(*card_holder_name.peek().to_string(), valid_name); - assert!(invalid_card_holder_name.is_err()); - - let serialized = serde_json::to_string(&card_holder_name).unwrap(); - assert_eq!(&serialized, "\"Sakil Mostak\""); - - let derialized = serde_json::from_str::(&serialized).unwrap(); - assert_eq!(derialized.peek().to_string(), valid_name); - - let invalid_deserialization = serde_json::from_str::("$@k!l M*$t@k"); - assert!(invalid_deserialization.is_err()); - } } diff --git a/crates/common_utils/src/types.rs b/crates/common_utils/src/types.rs index 9edee9b42b4..1a6533c2f26 100644 --- a/crates/common_utils/src/types.rs +++ b/crates/common_utils/src/types.rs @@ -10,7 +10,7 @@ use std::{ borrow::Cow, fmt::Display, iter::Sum, - ops::{Add, Mul, Sub}, + ops::{Add, Deref, Mul, Sub}, primitive::i64, str::{FromStr, SplitWhitespace}, }; @@ -26,6 +26,7 @@ use diesel::{ AsExpression, FromSqlRow, Queryable, }; use error_stack::{report, ResultExt}; +use masking::{ExposeInterface, PeekInterface, Secret}; use rust_decimal::{ prelude::{FromPrimitive, ToPrimitive}, Decimal, @@ -41,6 +42,7 @@ use crate::{ self, MAX_DESCRIPTION_LENGTH, MAX_STATEMENT_DESCRIPTOR_LENGTH, PUBLISHABLE_KEY_LENGTH, }, errors::{CustomResult, ParsingError, PercentageError, ValidationError}, + ext_traits::ConfigExt, fp_utils::when, }; @@ -1397,6 +1399,124 @@ where } } +#[derive(Clone, Default, Debug, Eq, PartialEq, Serialize)] +/// NewType for validating Names +pub struct NameType(Secret>); + +impl TryFrom for NameType { + type Error = error_stack::Report; + fn try_from(card_holder_name: String) -> Result { + for char in card_holder_name.chars() { + validate_character_in_card_holder_name(char)?; + } + let valid_length_name = + LengthString::<256, 1>::from(card_holder_name.into()).map_err(|_| { + report!(ValidationError::InvalidValue { + message: "invalid length for name".to_string() + }) + })?; + Ok(Self(Secret::new(valid_length_name))) + } +} + +impl TryFrom> for NameType { + type Error = error_stack::Report; + fn try_from(masked_card_holder_name: Secret) -> Result { + Self::try_from(masked_card_holder_name.expose()) + } +} + +impl FromStr for NameType { + type Err = error_stack::Report; + + fn from_str(card_number: &str) -> Result { + Self::try_from(card_number.to_string()) + } +} + +impl From for Secret { + fn from(card_holder_name: NameType) -> Self { + Self::new(card_holder_name.peek().to_string()) + } +} + +impl From<&NameType> for Secret { + fn from(card_holder_name: &NameType) -> Self { + Self::new(card_holder_name.peek().to_string()) + } +} + +fn validate_character_in_card_holder_name( + character: char, +) -> Result<(), error_stack::Report> { + if character.is_alphabetic() + || character == ' ' + || character == '.' + || character == '-' + || character == '\'' + || character == '~' + || character == '`' + { + Ok(()) + } else { + Err(report!(ValidationError::InvalidValue { + message: format!("invalid character found in card holder name: {}", character) + })) + } +} + +impl<'de> Deserialize<'de> for NameType { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let card_holder_name = String::deserialize(deserializer)?; + card_holder_name + .try_into() + .map_err(serde::de::Error::custom) + } +} + +impl Deref for NameType { + type Target = Secret>; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl ConfigExt for NameType { + fn is_empty_after_trim(&self) -> bool { + self.peek().trim().is_empty() + } +} + +#[cfg(test)] +mod name_type_test { + #![allow(clippy::unwrap_used)] + use super::*; + #[test] + fn test_card_holder_name() { + let valid_name = "Sakil Mostak".to_string(); + // no panic + let card_holder_name = NameType::try_from("Sakil Mostak".to_string()).unwrap(); + + // will panic on unwrap + let invalid_card_holder_name = NameType::try_from("$@k!l M*$t@k".to_string()); + + assert_eq!(*card_holder_name.peek().to_string(), valid_name); + assert!(invalid_card_holder_name.is_err()); + + let serialized = serde_json::to_string(&card_holder_name).unwrap(); + assert_eq!(&serialized, "\"Sakil Mostak\""); + + let derialized = serde_json::from_str::(&serialized).unwrap(); + assert_eq!(derialized.peek().to_string(), valid_name); + + let invalid_deserialization = serde_json::from_str::("$@k!l M*$t@k"); + assert!(invalid_deserialization.is_err()); + } +} + #[cfg(feature = "v2")] /// Browser information to be used for 3DS 2.0 // If any of the field is PII, then we can make them as secret diff --git a/crates/hyperswitch_domain_models/src/address.rs b/crates/hyperswitch_domain_models/src/address.rs index 684697947d6..fc0f1f2cf6c 100644 --- a/crates/hyperswitch_domain_models/src/address.rs +++ b/crates/hyperswitch_domain_models/src/address.rs @@ -1,4 +1,4 @@ -use cards::NameType; +use common_utils::types::NameType; use masking::{PeekInterface, Secret}; #[derive(Default, Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] diff --git a/crates/hyperswitch_domain_models/src/payment_method_data.rs b/crates/hyperswitch_domain_models/src/payment_method_data.rs index a1e743e1bee..74105e7f223 100644 --- a/crates/hyperswitch_domain_models/src/payment_method_data.rs +++ b/crates/hyperswitch_domain_models/src/payment_method_data.rs @@ -2,7 +2,6 @@ use api_models::{ mandates, payment_methods, payments::{additional_info as payment_additional_types, ExtendedCardInfo}, }; -use cards::NameType; use common_enums::enums as api_enums; use common_utils::{ id_type, @@ -10,6 +9,7 @@ use common_utils::{ MaskedBankAccount, MaskedIban, MaskedRoutingNumber, MaskedSortCode, MaskedUpiVpaId, }, pii::{self, Email}, + types::NameType, }; use masking::{PeekInterface, Secret}; use serde::{Deserialize, Serialize}; diff --git a/crates/hyperswitch_domain_models/src/router_data.rs b/crates/hyperswitch_domain_models/src/router_data.rs index a6b2e0d2380..fd55003f6fd 100644 --- a/crates/hyperswitch_domain_models/src/router_data.rs +++ b/crates/hyperswitch_domain_models/src/router_data.rs @@ -1,11 +1,10 @@ use std::{collections::HashMap, marker::PhantomData}; -use cards::NameType; use common_utils::{ errors::IntegrityCheckError, ext_traits::{OptionExt, ValueExt}, id_type, - types::MinorUnit, + types::{MinorUnit, NameType}, }; use error_stack::ResultExt; use masking::{ExposeInterface, Secret}; diff --git a/crates/hyperswitch_domain_models/src/router_request_types/fraud_check.rs b/crates/hyperswitch_domain_models/src/router_request_types/fraud_check.rs index e92ca75f833..44feac85e32 100644 --- a/crates/hyperswitch_domain_models/src/router_request_types/fraud_check.rs +++ b/crates/hyperswitch_domain_models/src/router_request_types/fraud_check.rs @@ -1,9 +1,9 @@ use api_models; -use cards::NameType; use common_enums; use common_utils::{ events::{ApiEventMetric, ApiEventsType}, pii::Email, + types::NameType, }; use diesel_models::types::OrderDetailsWithAmount; use masking::Secret; diff --git a/crates/router/src/compatibility/stripe/customers/types.rs b/crates/router/src/compatibility/stripe/customers/types.rs index dd67c91d7d0..080aabf895f 100644 --- a/crates/router/src/compatibility/stripe/customers/types.rs +++ b/crates/router/src/compatibility/stripe/customers/types.rs @@ -6,13 +6,12 @@ use std::{convert::From, default::Default}; ))] use api_models::payment_methods as api_types; use api_models::payments; -use cards::NameType; #[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "customer_v2")))] use common_utils::{crypto::Encryptable, date_time}; use common_utils::{ id_type, pii::{self, Email}, - types::Description, + types::{Description, NameType}, }; use serde::{Deserialize, Serialize}; diff --git a/crates/router/src/compatibility/stripe/payment_intents/types.rs b/crates/router/src/compatibility/stripe/payment_intents/types.rs index ce578519bb3..db602fb6208 100644 --- a/crates/router/src/compatibility/stripe/payment_intents/types.rs +++ b/crates/router/src/compatibility/stripe/payment_intents/types.rs @@ -1,14 +1,13 @@ use std::str::FromStr; use api_models::payments; -use cards::NameType; use common_utils::{ crypto::Encryptable, date_time, ext_traits::StringExt, id_type, pii::{IpAddress, SecretSerdeValue, UpiVpaMaskingStrategy}, - types::MinorUnit, + types::{MinorUnit, NameType}, }; use error_stack::ResultExt; use router_env::logger; diff --git a/crates/router/src/compatibility/stripe/setup_intents/types.rs b/crates/router/src/compatibility/stripe/setup_intents/types.rs index 6f84aa200b9..021ee3869d9 100644 --- a/crates/router/src/compatibility/stripe/setup_intents/types.rs +++ b/crates/router/src/compatibility/stripe/setup_intents/types.rs @@ -1,8 +1,7 @@ use std::str::FromStr; use api_models::payments; -use cards::NameType; -use common_utils::{date_time, ext_traits::StringExt, id_type, pii as secret}; +use common_utils::{date_time, ext_traits::StringExt, id_type, pii as secret, types::NameType}; use error_stack::ResultExt; use router_env::logger; use serde::{Deserialize, Serialize}; diff --git a/crates/router/src/connector/stripe/transformers/connect.rs b/crates/router/src/connector/stripe/transformers/connect.rs index 9a2046cd022..49640218445 100644 --- a/crates/router/src/connector/stripe/transformers/connect.rs +++ b/crates/router/src/connector/stripe/transformers/connect.rs @@ -1,6 +1,5 @@ use api_models; -use cards::NameType; -use common_utils::pii::Email; +use common_utils::{pii::Email, types::NameType}; use error_stack::ResultExt; use masking::Secret; use serde::{Deserialize, Serialize}; diff --git a/crates/router/src/connector/trustpay/transformers.rs b/crates/router/src/connector/trustpay/transformers.rs index 32799656903..66961e762cb 100644 --- a/crates/router/src/connector/trustpay/transformers.rs +++ b/crates/router/src/connector/trustpay/transformers.rs @@ -1,10 +1,9 @@ use std::collections::HashMap; -use cards::NameType; use common_utils::{ errors::CustomResult, pii::{self, Email}, - types::StringMajorUnit, + types::{NameType, StringMajorUnit}, }; use error_stack::{report, ResultExt}; use masking::{ExposeInterface, PeekInterface, Secret}; diff --git a/crates/router/src/core/payment_methods.rs b/crates/router/src/core/payment_methods.rs index 5eb05f6ec77..16af0141fa7 100644 --- a/crates/router/src/core/payment_methods.rs +++ b/crates/router/src/core/payment_methods.rs @@ -17,7 +17,6 @@ use std::collections::HashSet; #[cfg(all(feature = "v2", feature = "payment_methods_v2"))] use std::str::FromStr; -use ::cards::NameType; #[cfg(all(feature = "v2", feature = "payment_methods_v2"))] pub use api_models::enums as api_enums; pub use api_models::enums::Connector; @@ -26,7 +25,7 @@ use api_models::payment_methods; pub use api_models::{enums::PayoutConnectors, payouts as payout_types}; #[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "customer_v2")))] use common_utils::ext_traits::Encode; -use common_utils::{consts::DEFAULT_LOCALE, id_type}; +use common_utils::{consts::DEFAULT_LOCALE, id_type, types::NameType}; #[cfg(all(feature = "v2", feature = "payment_methods_v2"))] use common_utils::{ crypto::{self, Encryptable}, diff --git a/crates/router/src/core/payment_methods/transformers.rs b/crates/router/src/core/payment_methods/transformers.rs index a07a3bc7ac2..fcaa024b5c9 100644 --- a/crates/router/src/core/payment_methods/transformers.rs +++ b/crates/router/src/core/payment_methods/transformers.rs @@ -2,7 +2,6 @@ use std::str::FromStr; use api_models::{enums as api_enums, payment_methods::Card}; -use cards::NameType; #[cfg(all(feature = "v2", feature = "payment_methods_v2"))] use common_utils::ext_traits::ValueExt; use common_utils::{ @@ -10,6 +9,7 @@ use common_utils::{ id_type, pii::Email, request::RequestContent, + types::NameType, }; use error_stack::{report, ResultExt}; use josekit::jwe; diff --git a/crates/router/src/core/payment_methods/vault.rs b/crates/router/src/core/payment_methods/vault.rs index 2abc4b6c22d..9a0741b9b0f 100644 --- a/crates/router/src/core/payment_methods/vault.rs +++ b/crates/router/src/core/payment_methods/vault.rs @@ -1,4 +1,3 @@ -use cards::NameType; use common_enums::PaymentMethodType; #[cfg(all(feature = "v2", feature = "payment_methods_v2"))] use common_utils::request; @@ -7,6 +6,7 @@ use common_utils::{ ext_traits::{BytesExt, Encode}, generate_id_with_default_len, id_type, pii::Email, + types::NameType, }; use error_stack::{report, ResultExt}; use masking::PeekInterface; diff --git a/crates/router/src/core/utils.rs b/crates/router/src/core/utils.rs index 8f21fea0670..86b162b82a1 100644 --- a/crates/router/src/core/utils.rs +++ b/crates/router/src/core/utils.rs @@ -72,7 +72,7 @@ pub async fn construct_payout_router_data<'a, F>( merchant_account: &domain::MerchantAccount, payout_data: &mut PayoutData, ) -> RouterResult> { - use cards::NameType; + use common_utils::types::NameType; let merchant_connector_account = payout_data .merchant_connector_account diff --git a/crates/router/src/types/api/payments.rs b/crates/router/src/types/api/payments.rs index b5afc3b0f27..2c8ddafd331 100644 --- a/crates/router/src/types/api/payments.rs +++ b/crates/router/src/types/api/payments.rs @@ -126,14 +126,14 @@ mod payments_test { 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: cards::NameType::try_from("JohnDoe".to_string()).ok(), + card_holder_name: common_utils::types::NameType::try_from("JohnDoe".to_string()).ok(), card_cvc: "123".to_string().into(), card_issuer: Some("HDFC".to_string()), card_network: Some(api_models::enums::CardNetwork::Visa), bank_code: None, card_issuing_country: None, card_type: None, - nick_name: cards::NameType::try_from("nick_name".to_string()).ok(), + nick_name: common_utils::types::NameType::try_from("nick_name".to_string()).ok(), } } diff --git a/crates/router/src/types/transformers.rs b/crates/router/src/types/transformers.rs index 96478590802..ea5465a415c 100644 --- a/crates/router/src/types/transformers.rs +++ b/crates/router/src/types/transformers.rs @@ -4,14 +4,13 @@ use api_models::{ enums as api_enums, gsm as gsm_api_types, payment_methods, payments, routing::ConnectorSelection, }; -use cards::NameType; use common_utils::{ consts::X_HS_LATENCY, crypto::Encryptable, ext_traits::{Encode, StringExt, ValueExt}, fp_utils::when, pii, - types::ConnectorTransactionIdTrait, + types::{ConnectorTransactionIdTrait, NameType}, }; use diesel_models::enums as storage_enums; use error_stack::{report, ResultExt}; diff --git a/crates/router/tests/connectors/aci.rs b/crates/router/tests/connectors/aci.rs index 8062524bfc6..5974eb0ea9d 100644 --- a/crates/router/tests/connectors/aci.rs +++ b/crates/router/tests/connectors/aci.rs @@ -50,8 +50,11 @@ fn construct_payment_router_data() -> types::PaymentsAuthorizeRouterData { card_type: None, card_issuing_country: None, bank_code: None, - nick_name: cards::NameType::try_from("nick_name".to_string()).ok(), - card_holder_name: cards::NameType::try_from("card holder name".to_string()).ok(), + nick_name: common_utils::types::NameType::try_from("nick_name".to_string()).ok(), + card_holder_name: common_utils::types::NameType::try_from( + "card holder name".to_string(), + ) + .ok(), }), confirm: true, statement_descriptor_suffix: None, @@ -88,8 +91,8 @@ fn construct_payment_router_data() -> types::PaymentsAuthorizeRouterData { None, Some(Address { address: Some(AddressDetails { - first_name: cards::NameType::try_from("John".to_string()).ok(), - last_name: cards::NameType::try_from("Doe".to_string()).ok(), + first_name: common_utils::types::NameType::try_from("John".to_string()).ok(), + last_name: common_utils::types::NameType::try_from("Doe".to_string()).ok(), ..Default::default() }), phone: Some(PhoneDetails { @@ -298,8 +301,11 @@ async fn payments_create_failure() { card_type: None, card_issuing_country: None, bank_code: None, - nick_name: cards::NameType::try_from("nick_name".to_string()).ok(), - card_holder_name: cards::NameType::try_from("card holder name".to_string()).ok(), + nick_name: common_utils::types::NameType::try_from("nick_name".to_string()).ok(), + card_holder_name: common_utils::types::NameType::try_from( + "card holder name".to_string(), + ) + .ok(), }); let response = services::api::execute_connector_processing_step( diff --git a/crates/router/tests/connectors/adyen.rs b/crates/router/tests/connectors/adyen.rs index fe133a4216d..705a7a192c5 100644 --- a/crates/router/tests/connectors/adyen.rs +++ b/crates/router/tests/connectors/adyen.rs @@ -62,8 +62,10 @@ impl AdyenTest { line1: Some(Secret::new("1467".to_string())), line2: Some(Secret::new("Harrison Street".to_string())), line3: None, - first_name: cards::NameType::try_from("John".to_string()).ok(), - last_name: cards::NameType::try_from("Dough".to_string()).ok(), + first_name: common_utils::types::NameType::try_from("John".to_string()) + .ok(), + last_name: common_utils::types::NameType::try_from("Dough".to_string()) + .ok(), }), phone: Some(PhoneDetails { number: Some(Secret::new("9123456789".to_string())), @@ -108,7 +110,10 @@ impl AdyenTest { card_number: cards::CardNumber::from_str("4111111111111111").unwrap(), expiry_month: Secret::new("3".to_string()), expiry_year: Secret::new("2030".to_string()), - card_holder_name: cards::NameType::try_from("John Doe".to_string()).ok(), + card_holder_name: common_utils::types::NameType::try_from( + "John Doe".to_string(), + ) + .ok(), }, )), enums::PayoutType::Bank => Some(types::api::PayoutMethodData::Bank( @@ -152,8 +157,11 @@ impl AdyenTest { card_type: None, card_issuing_country: None, bank_code: None, - nick_name: cards::NameType::try_from("nick_name".to_string()).ok(), - card_holder_name: cards::NameType::try_from("card holder name".to_string()).ok(), + nick_name: common_utils::types::NameType::try_from("nick_name".to_string()).ok(), + card_holder_name: common_utils::types::NameType::try_from( + "card holder name".to_string(), + ) + .ok(), }), confirm: true, statement_descriptor_suffix: None, diff --git a/crates/router/tests/connectors/airwallex.rs b/crates/router/tests/connectors/airwallex.rs index e4376828b13..5d282c21a8c 100644 --- a/crates/router/tests/connectors/airwallex.rs +++ b/crates/router/tests/connectors/airwallex.rs @@ -57,8 +57,8 @@ fn get_default_payment_info() -> Option { None, Some(Address { address: Some(AddressDetails { - first_name: cards::NameType::try_from("John".to_string()).ok(), - last_name: cards::NameType::try_from("Doe".to_string()).ok(), + first_name: common_utils::types::NameType::try_from("John".to_string()).ok(), + last_name: common_utils::types::NameType::try_from("Doe".to_string()).ok(), ..Default::default() }), phone: None, @@ -81,8 +81,11 @@ fn payment_method_details() -> Option { card_type: None, card_issuing_country: None, bank_code: None, - nick_name: cards::NameType::try_from("nick_name".to_string()).ok(), - card_holder_name: cards::NameType::try_from("card holder name".to_string()).ok(), + nick_name: common_utils::types::NameType::try_from("nick_name".to_string()).ok(), + card_holder_name: common_utils::types::NameType::try_from( + "card holder name".to_string(), + ) + .ok(), }), capture_method: Some(diesel_models::enums::CaptureMethod::Manual), router_return_url: Some("https://google.com".to_string()), diff --git a/crates/router/tests/connectors/bitpay.rs b/crates/router/tests/connectors/bitpay.rs index 3476a629ff2..f4a106ab7d2 100644 --- a/crates/router/tests/connectors/bitpay.rs +++ b/crates/router/tests/connectors/bitpay.rs @@ -43,8 +43,8 @@ fn get_default_payment_info() -> Option { None, Some(Address { address: Some(AddressDetails { - first_name: cards::NameType::try_from("first".to_string()).ok(), - last_name: cards::NameType::try_from("last".to_string()).ok(), + first_name: common_utils::types::NameType::try_from("first".to_string()).ok(), + last_name: common_utils::types::NameType::try_from("last".to_string()).ok(), line1: Some(Secret::new("line1".to_string())), line2: Some(Secret::new("line2".to_string())), city: Some("city".to_string()), diff --git a/crates/router/tests/connectors/bluesnap.rs b/crates/router/tests/connectors/bluesnap.rs index dcafa2506f8..7c304be7bc9 100644 --- a/crates/router/tests/connectors/bluesnap.rs +++ b/crates/router/tests/connectors/bluesnap.rs @@ -50,8 +50,8 @@ fn get_payment_info() -> Option { None, Some(Address { address: Some(AddressDetails { - first_name: cards::NameType::try_from("joseph".to_string()).ok(), - last_name: cards::NameType::try_from("Doe".to_string()).ok(), + first_name: common_utils::types::NameType::try_from("joseph".to_string()).ok(), + last_name: common_utils::types::NameType::try_from("Doe".to_string()).ok(), ..Default::default() }), phone: None, diff --git a/crates/router/tests/connectors/coinbase.rs b/crates/router/tests/connectors/coinbase.rs index 8bc729a4946..a0873c14664 100644 --- a/crates/router/tests/connectors/coinbase.rs +++ b/crates/router/tests/connectors/coinbase.rs @@ -44,8 +44,8 @@ fn get_default_payment_info() -> Option { None, Some(Address { address: Some(AddressDetails { - first_name: cards::NameType::try_from("first".to_string()).ok(), - last_name: cards::NameType::try_from("last".to_string()).ok(), + first_name: common_utils::types::NameType::try_from("first".to_string()).ok(), + last_name: common_utils::types::NameType::try_from("last".to_string()).ok(), line1: Some(Secret::new("line1".to_string())), line2: Some(Secret::new("line2".to_string())), city: Some("city".to_string()), diff --git a/crates/router/tests/connectors/cryptopay.rs b/crates/router/tests/connectors/cryptopay.rs index 82ae921fecc..7c26299311e 100644 --- a/crates/router/tests/connectors/cryptopay.rs +++ b/crates/router/tests/connectors/cryptopay.rs @@ -43,8 +43,8 @@ fn get_default_payment_info() -> Option { None, Some(Address { address: Some(AddressDetails { - first_name: cards::NameType::try_from("first".to_string()).ok(), - last_name: cards::NameType::try_from("last".to_string()).ok(), + first_name: common_utils::types::NameType::try_from("first".to_string()).ok(), + last_name: common_utils::types::NameType::try_from("last".to_string()).ok(), line1: Some(Secret::new("line1".to_string())), line2: Some(Secret::new("line2".to_string())), city: Some("city".to_string()), diff --git a/crates/router/tests/connectors/cybersource.rs b/crates/router/tests/connectors/cybersource.rs index 6730183bc6f..889ea9a368a 100644 --- a/crates/router/tests/connectors/cybersource.rs +++ b/crates/router/tests/connectors/cybersource.rs @@ -40,8 +40,8 @@ fn get_default_payment_info() -> Option { None, Some(Address { address: Some(AddressDetails { - first_name: cards::NameType::try_from("first".to_string()).ok(), - last_name: cards::NameType::try_from("last".to_string()).ok(), + first_name: common_utils::types::NameType::try_from("first".to_string()).ok(), + last_name: common_utils::types::NameType::try_from("last".to_string()).ok(), line1: Some(Secret::new("line1".to_string())), line2: Some(Secret::new("line2".to_string())), city: Some("city".to_string()), diff --git a/crates/router/tests/connectors/fiserv.rs b/crates/router/tests/connectors/fiserv.rs index c7381bcfc4e..6b98b350629 100644 --- a/crates/router/tests/connectors/fiserv.rs +++ b/crates/router/tests/connectors/fiserv.rs @@ -52,8 +52,11 @@ fn payment_method_details() -> Option { card_type: None, card_issuing_country: None, bank_code: None, - nick_name: cards::NameType::try_from("nick_name".to_string()).ok(), - card_holder_name: cards::NameType::try_from("card holder name".to_string()).ok(), + nick_name: common_utils::types::NameType::try_from("nick_name".to_string()).ok(), + card_holder_name: common_utils::types::NameType::try_from( + "card holder name".to_string(), + ) + .ok(), }), capture_method: Some(diesel_models::enums::CaptureMethod::Manual), ..utils::PaymentAuthorizeType::default().0 diff --git a/crates/router/tests/connectors/forte.rs b/crates/router/tests/connectors/forte.rs index 28d8831ee71..c0e25e9a30c 100644 --- a/crates/router/tests/connectors/forte.rs +++ b/crates/router/tests/connectors/forte.rs @@ -57,8 +57,8 @@ fn get_default_payment_info() -> Option { None, Some(Address { address: Some(AddressDetails { - first_name: cards::NameType::try_from("first".to_string()).ok(), - last_name: cards::NameType::try_from("last".to_string()).ok(), + first_name: common_utils::types::NameType::try_from("first".to_string()).ok(), + last_name: common_utils::types::NameType::try_from("last".to_string()).ok(), line1: Some(Secret::new("line1".to_string())), line2: Some(Secret::new("line2".to_string())), city: Some("city".to_string()), diff --git a/crates/router/tests/connectors/iatapay.rs b/crates/router/tests/connectors/iatapay.rs index adb3f9bfd51..3524e6cd407 100644 --- a/crates/router/tests/connectors/iatapay.rs +++ b/crates/router/tests/connectors/iatapay.rs @@ -60,8 +60,8 @@ fn get_default_payment_info() -> Option { None, Some(Address { address: Some(AddressDetails { - first_name: cards::NameType::try_from("first".to_string()).ok(), - last_name: cards::NameType::try_from("last".to_string()).ok(), + first_name: common_utils::types::NameType::try_from("first".to_string()).ok(), + last_name: common_utils::types::NameType::try_from("last".to_string()).ok(), line1: Some(Secret::new("line1".to_string())), line2: Some(Secret::new("line2".to_string())), city: Some("city".to_string()), diff --git a/crates/router/tests/connectors/multisafepay.rs b/crates/router/tests/connectors/multisafepay.rs index 80a98013f65..0727b9712a6 100644 --- a/crates/router/tests/connectors/multisafepay.rs +++ b/crates/router/tests/connectors/multisafepay.rs @@ -42,8 +42,8 @@ fn get_default_payment_info() -> Option { None, Some(Address { address: Some(AddressDetails { - first_name: cards::NameType::try_from("John".to_string()).ok(), - last_name: cards::NameType::try_from("Doe".to_string()).ok(), + first_name: common_utils::types::NameType::try_from("John".to_string()).ok(), + last_name: common_utils::types::NameType::try_from("Doe".to_string()).ok(), line1: Some(Secret::new("Kraanspoor".to_string())), line2: Some(Secret::new("line2".to_string())), line3: Some(Secret::new("line3".to_string())), diff --git a/crates/router/tests/connectors/opennode.rs b/crates/router/tests/connectors/opennode.rs index 142eb99704c..f2aa5454f20 100644 --- a/crates/router/tests/connectors/opennode.rs +++ b/crates/router/tests/connectors/opennode.rs @@ -43,8 +43,8 @@ fn get_default_payment_info() -> Option { None, Some(Address { address: Some(AddressDetails { - first_name: cards::NameType::try_from("first".to_string()).ok(), - last_name: cards::NameType::try_from("last".to_string()).ok(), + first_name: common_utils::types::NameType::try_from("first".to_string()).ok(), + last_name: common_utils::types::NameType::try_from("last".to_string()).ok(), line1: Some(Secret::new("line1".to_string())), line2: Some(Secret::new("line2".to_string())), city: Some("city".to_string()), diff --git a/crates/router/tests/connectors/payme.rs b/crates/router/tests/connectors/payme.rs index 8c66f4e1f2c..f1de9251110 100644 --- a/crates/router/tests/connectors/payme.rs +++ b/crates/router/tests/connectors/payme.rs @@ -54,8 +54,8 @@ fn get_default_payment_info() -> Option { line3: None, zip: None, state: None, - first_name: cards::NameType::try_from("John".to_string()).ok(), - last_name: cards::NameType::try_from("Doe".to_string()).ok(), + first_name: common_utils::types::NameType::try_from("John".to_string()).ok(), + last_name: common_utils::types::NameType::try_from("Doe".to_string()).ok(), }), phone: None, email: None, diff --git a/crates/router/tests/connectors/rapyd.rs b/crates/router/tests/connectors/rapyd.rs index 2ef2a0b9c01..e654b8c1a87 100644 --- a/crates/router/tests/connectors/rapyd.rs +++ b/crates/router/tests/connectors/rapyd.rs @@ -52,9 +52,12 @@ async fn should_only_authorize_payment() { card_type: None, card_issuing_country: None, bank_code: None, - nick_name: cards::NameType::try_from("nick_name".to_string()).ok(), - card_holder_name: cards::NameType::try_from("card holder name".to_string()) + nick_name: common_utils::types::NameType::try_from("nick_name".to_string()) .ok(), + card_holder_name: common_utils::types::NameType::try_from( + "card holder name".to_string(), + ) + .ok(), }), capture_method: Some(diesel_models::enums::CaptureMethod::Manual), ..utils::PaymentAuthorizeType::default().0 @@ -81,9 +84,12 @@ async fn should_authorize_and_capture_payment() { card_type: None, card_issuing_country: None, bank_code: None, - nick_name: cards::NameType::try_from("nick_name".to_string()).ok(), - card_holder_name: cards::NameType::try_from("card holder name".to_string()) + nick_name: common_utils::types::NameType::try_from("nick_name".to_string()) .ok(), + card_holder_name: common_utils::types::NameType::try_from( + "card holder name".to_string(), + ) + .ok(), }), ..utils::PaymentAuthorizeType::default().0 }), diff --git a/crates/router/tests/connectors/trustpay.rs b/crates/router/tests/connectors/trustpay.rs index 42b2c831aeb..49f2c226692 100644 --- a/crates/router/tests/connectors/trustpay.rs +++ b/crates/router/tests/connectors/trustpay.rs @@ -72,8 +72,8 @@ fn get_default_payment_info() -> Option { None, Some(Address { address: Some(AddressDetails { - first_name: cards::NameType::try_from("first".to_string()).ok(), - last_name: cards::NameType::try_from("last".to_string()).ok(), + first_name: common_utils::types::NameType::try_from("first".to_string()).ok(), + last_name: common_utils::types::NameType::try_from("last".to_string()).ok(), line1: Some(Secret::new("line1".to_string())), line2: Some(Secret::new("line2".to_string())), city: Some("city".to_string()), diff --git a/crates/router/tests/connectors/utils.rs b/crates/router/tests/connectors/utils.rs index 3c859737973..92f7bbe985f 100644 --- a/crates/router/tests/connectors/utils.rs +++ b/crates/router/tests/connectors/utils.rs @@ -80,8 +80,9 @@ impl PaymentInfo { None, Some(hyperswitch_domain_models::address::Address { address: Some(hyperswitch_domain_models::address::AddressDetails { - first_name: cards::NameType::try_from("John".to_string()).ok(), - last_name: cards::NameType::try_from("Doe".to_string()).ok(), + first_name: common_utils::types::NameType::try_from("John".to_string()) + .ok(), + last_name: common_utils::types::NameType::try_from("Doe".to_string()).ok(), ..Default::default() }), phone: None, @@ -927,8 +928,11 @@ impl Default for CCardType { card_type: None, card_issuing_country: None, bank_code: None, - nick_name: cards::NameType::try_from("nick_name".to_string()).ok(), - card_holder_name: cards::NameType::try_from("card holder name".to_string()).ok(), + nick_name: common_utils::types::NameType::try_from("nick_name".to_string()).ok(), + card_holder_name: common_utils::types::NameType::try_from( + "card holder name".to_string(), + ) + .ok(), }) } } diff --git a/crates/router/tests/connectors/worldline.rs b/crates/router/tests/connectors/worldline.rs index 592edfb08c7..2fcd85efe89 100644 --- a/crates/router/tests/connectors/worldline.rs +++ b/crates/router/tests/connectors/worldline.rs @@ -48,8 +48,10 @@ impl WorldlineTest { Some(Address { address: Some(AddressDetails { country: Some(api_models::enums::CountryAlpha2::US), - first_name: cards::NameType::try_from(String::from("John")).ok(), - last_name: cards::NameType::try_from(String::from("Dough")).ok(), + first_name: common_utils::types::NameType::try_from(String::from("John")) + .ok(), + last_name: common_utils::types::NameType::try_from(String::from("Dough")) + .ok(), ..Default::default() }), phone: None, @@ -82,8 +84,11 @@ impl WorldlineTest { card_type: None, card_issuing_country: None, bank_code: None, - nick_name: cards::NameType::try_from("nick_name".to_string()).ok(), - card_holder_name: cards::NameType::try_from("card holder name".to_string()).ok(), + nick_name: common_utils::types::NameType::try_from("nick_name".to_string()).ok(), + card_holder_name: common_utils::types::NameType::try_from( + "card holder name".to_string(), + ) + .ok(), }), confirm: true, statement_descriptor_suffix: None, diff --git a/crates/router/tests/payments.rs b/crates/router/tests/payments.rs index 6e2ea1fcd40..12cceaca755 100644 --- a/crates/router/tests/payments.rs +++ b/crates/router/tests/payments.rs @@ -341,14 +341,15 @@ async fn payments_create_core() { 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: cards::NameType::try_from("Arun Raj".to_string()).ok(), + card_holder_name: common_utils::types::NameType::try_from("Arun Raj".to_string()) + .ok(), card_cvc: "123".to_string().into(), card_issuer: None, card_network: None, card_type: None, card_issuing_country: None, bank_code: None, - nick_name: cards::NameType::try_from("nick_name".to_string()).ok(), + nick_name: common_utils::types::NameType::try_from("nick_name".to_string()).ok(), })), billing: None, }), @@ -602,14 +603,15 @@ async fn payments_create_core_adyen_no_redirect() { 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: cards::NameType::try_from("JohnDoe".to_string()).ok(), + card_holder_name: common_utils::types::NameType::try_from("JohnDoe".to_string()) + .ok(), card_cvc: "737".to_string().into(), card_issuer: None, card_network: None, card_type: None, card_issuing_country: None, bank_code: None, - nick_name: cards::NameType::try_from("nick_name".to_string()).ok(), + nick_name: common_utils::types::NameType::try_from("nick_name".to_string()).ok(), })), billing: None, }), diff --git a/crates/router/tests/payments2.rs b/crates/router/tests/payments2.rs index 3e2abbf6c52..441733be2a2 100644 --- a/crates/router/tests/payments2.rs +++ b/crates/router/tests/payments2.rs @@ -102,14 +102,15 @@ async fn payments_create_core() { 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: cards::NameType::try_from("Arun Raj".to_string()).ok(), + card_holder_name: common_utils::types::NameType::try_from("Arun Raj".to_string()) + .ok(), card_cvc: "123".to_string().into(), card_issuer: None, card_network: None, card_type: None, card_issuing_country: None, bank_code: None, - nick_name: cards::NameType::try_from("nick_name".to_string()).ok(), + nick_name: common_utils::types::NameType::try_from("nick_name".to_string()).ok(), })), billing: None, }), @@ -371,14 +372,15 @@ async fn payments_create_core_adyen_no_redirect() { 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: cards::NameType::try_from("JohnDoe".to_string()).ok(), + card_holder_name: common_utils::types::NameType::try_from("JohnDoe".to_string()) + .ok(), card_cvc: "737".to_string().into(), bank_code: None, card_issuer: None, card_network: None, card_type: None, card_issuing_country: None, - nick_name: cards::NameType::try_from("nick_name".to_string()).ok(), + nick_name: common_utils::types::NameType::try_from("nick_name".to_string()).ok(), })), billing: None, }), From 7aef96ea7ee2604acf7c36a63d1a73d093c14b70 Mon Sep 17 00:00:00 2001 From: Sk Sakil Mostak Date: Tue, 14 Jan 2025 22:15:38 +0530 Subject: [PATCH 12/19] refactor: resolve comments --- crates/common_utils/src/types.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/crates/common_utils/src/types.rs b/crates/common_utils/src/types.rs index 1a6533c2f26..a0794193950 100644 --- a/crates/common_utils/src/types.rs +++ b/crates/common_utils/src/types.rs @@ -26,7 +26,7 @@ use diesel::{ AsExpression, FromSqlRow, Queryable, }; use error_stack::{report, ResultExt}; -use masking::{ExposeInterface, PeekInterface, Secret}; +use masking::{ExposeInterface, PeekInterface}; use rust_decimal::{ prelude::{FromPrimitive, ToPrimitive}, Decimal, @@ -1401,7 +1401,7 @@ where #[derive(Clone, Default, Debug, Eq, PartialEq, Serialize)] /// NewType for validating Names -pub struct NameType(Secret>); +pub struct NameType(masking::Secret>); impl TryFrom for NameType { type Error = error_stack::Report; @@ -1415,13 +1415,13 @@ impl TryFrom for NameType { message: "invalid length for name".to_string() }) })?; - Ok(Self(Secret::new(valid_length_name))) + Ok(Self(masking::Secret::new(valid_length_name))) } } -impl TryFrom> for NameType { +impl TryFrom> for NameType { type Error = error_stack::Report; - fn try_from(masked_card_holder_name: Secret) -> Result { + fn try_from(masked_card_holder_name: masking::Secret) -> Result { Self::try_from(masked_card_holder_name.expose()) } } @@ -1434,13 +1434,13 @@ impl FromStr for NameType { } } -impl From for Secret { +impl From for masking::Secret { fn from(card_holder_name: NameType) -> Self { Self::new(card_holder_name.peek().to_string()) } } -impl From<&NameType> for Secret { +impl From<&NameType> for masking::Secret { fn from(card_holder_name: &NameType) -> Self { Self::new(card_holder_name.peek().to_string()) } @@ -1478,7 +1478,7 @@ impl<'de> Deserialize<'de> for NameType { } impl Deref for NameType { - type Target = Secret>; + type Target = masking::Secret>; fn deref(&self) -> &Self::Target { &self.0 } From e377b2b073d60fd87d05593e730a00026adc65bd Mon Sep 17 00:00:00 2001 From: Sk Sakil Mostak Date: Wed, 15 Jan 2025 16:01:55 +0530 Subject: [PATCH 13/19] refactor: minimum allowed size is zero --- crates/common_utils/src/types.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/common_utils/src/types.rs b/crates/common_utils/src/types.rs index a0794193950..c2611edc26b 100644 --- a/crates/common_utils/src/types.rs +++ b/crates/common_utils/src/types.rs @@ -1401,7 +1401,7 @@ where #[derive(Clone, Default, Debug, Eq, PartialEq, Serialize)] /// NewType for validating Names -pub struct NameType(masking::Secret>); +pub struct NameType(masking::Secret>); impl TryFrom for NameType { type Error = error_stack::Report; @@ -1410,7 +1410,7 @@ impl TryFrom for NameType { validate_character_in_card_holder_name(char)?; } let valid_length_name = - LengthString::<256, 1>::from(card_holder_name.into()).map_err(|_| { + LengthString::<256, 0>::from(card_holder_name.into()).map_err(|_| { report!(ValidationError::InvalidValue { message: "invalid length for name".to_string() }) @@ -1478,7 +1478,7 @@ impl<'de> Deserialize<'de> for NameType { } impl Deref for NameType { - type Target = masking::Secret>; + type Target = masking::Secret>; fn deref(&self) -> &Self::Target { &self.0 } From 8ebd788e6035c9331c60b38418ec2b5058bb8860 Mon Sep 17 00:00:00 2001 From: Sk Sakil Mostak Date: Fri, 17 Jan 2025 14:23:18 +0530 Subject: [PATCH 14/19] refactor: resolve conflict with main --- crates/hyperswitch_connectors/src/utils.rs | 1 + crates/router/src/core/payment_methods/cards.rs | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/crates/hyperswitch_connectors/src/utils.rs b/crates/hyperswitch_connectors/src/utils.rs index 8a86252911d..14647a09519 100644 --- a/crates/hyperswitch_connectors/src/utils.rs +++ b/crates/hyperswitch_connectors/src/utils.rs @@ -1036,6 +1036,7 @@ impl CardData for Card { fn get_cardholder_name(&self) -> Result, Error> { self.card_holder_name .clone() + .map(From::from) .ok_or_else(missing_field_err("card.card_holder_name")) } } diff --git a/crates/router/src/core/payment_methods/cards.rs b/crates/router/src/core/payment_methods/cards.rs index ab1e0b8739c..fff7bad873b 100644 --- a/crates/router/src/core/payment_methods/cards.rs +++ b/crates/router/src/core/payment_methods/cards.rs @@ -2320,20 +2320,20 @@ pub fn validate_payment_method_update( }) || card_updation_obj .card_holder_name - .map(|name| name.expose()) + .map(|name| name.peek().to_string()) .is_some_and(|new_card_holder_name| { existing_card_data .card_holder_name - .map(|name| name.expose()) + .map(|name| name.peek().to_string()) != Some(new_card_holder_name) }) || card_updation_obj .nick_name - .map(|nick_name| nick_name.expose()) + .map(|nick_name| nick_name.peek().to_string()) .is_some_and(|new_nick_name| { existing_card_data .nick_name - .map(|nick_name| nick_name.expose()) + .map(|nick_name| nick_name.peek().to_string()) != Some(new_nick_name) }) } From 6ae7480bb3b4728e2ff3153665ed5b0ac0a8b973 Mon Sep 17 00:00:00 2001 From: Sk Sakil Mostak Date: Mon, 20 Jan 2025 23:15:53 +0530 Subject: [PATCH 15/19] refactor: resolve comments --- Cargo.lock | 1 + crates/api_models/Cargo.toml | 1 + crates/api_models/src/customers.rs | 7 +- crates/api_models/src/mandates.rs | 9 +- crates/api_models/src/payment_methods.rs | 50 ++++----- crates/api_models/src/payments.rs | 100 +++++++++++------- .../src/payments/additional_info.rs | 21 ++-- crates/api_models/src/payouts.rs | 4 +- .../hyperswitch_domain_models/src/address.rs | 5 +- .../src/payment_method_data.rs | 27 +++-- .../src/router_data.rs | 4 +- .../src/router_request_types/fraud_check.rs | 3 +- .../compatibility/stripe/customers/types.rs | 4 +- .../stripe/payment_intents/types.rs | 14 +-- .../stripe/setup_intents/types.rs | 5 +- .../connector/stripe/transformers/connect.rs | 6 +- .../src/connector/trustpay/transformers.rs | 8 +- crates/router/src/core/payment_methods.rs | 16 +-- .../router/src/core/payment_methods/cards.rs | 10 +- .../src/core/payment_methods/transformers.rs | 14 +-- .../router/src/core/payment_methods/vault.rs | 21 ++-- crates/router/src/core/utils.rs | 6 +- crates/router/src/types/transformers.rs | 27 +++-- crates/router/src/utils.rs | 12 +-- 24 files changed, 193 insertions(+), 182 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2007f4f88a0..4f42606b343 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -469,6 +469,7 @@ dependencies = [ "nutype", "reqwest 0.11.27", "router_derive", + "router_env", "rustc-hash", "serde", "serde_json", diff --git a/crates/api_models/Cargo.toml b/crates/api_models/Cargo.toml index c159af97249..f7083b173da 100644 --- a/crates/api_models/Cargo.toml +++ b/crates/api_models/Cargo.toml @@ -47,6 +47,7 @@ common_utils = { version = "0.1.0", path = "../common_utils" } euclid = { version = "0.1.0", path = "../euclid" } masking = { version = "0.1.0", path = "../masking", default-features = false, features = ["alloc", "serde"] } router_derive = { version = "0.1.0", path = "../router_derive" } +router_env = { version = "0.1.0", path = "../router_env", features = ["log_extra_implicit_fields", "log_custom_entries_to_extra"] } [lints] workspace = true diff --git a/crates/api_models/src/customers.rs b/crates/api_models/src/customers.rs index 8275b80fe8e..2b0603ca8a9 100644 --- a/crates/api_models/src/customers.rs +++ b/crates/api_models/src/customers.rs @@ -1,7 +1,4 @@ -use common_utils::{ - crypto, custom_serde, id_type, pii, - types::{Description, NameType}, -}; +use common_utils::{crypto, custom_serde, id_type, pii, types::Description}; use masking::Secret; use serde::{Deserialize, Serialize}; use utoipa::ToSchema; @@ -21,7 +18,7 @@ pub struct CustomerRequest { pub merchant_id: id_type::MerchantId, /// The customer's name #[schema(max_length = 255, value_type = Option, example = "Jon Test")] - pub name: Option, + pub name: Option, /// The customer's email address #[schema(value_type = Option, max_length = 255, example = "JonTest@test.com")] pub email: Option, diff --git a/crates/api_models/src/mandates.rs b/crates/api_models/src/mandates.rs index cc98a3a7897..4c0b8d4d18c 100644 --- a/crates/api_models/src/mandates.rs +++ b/crates/api_models/src/mandates.rs @@ -1,4 +1,3 @@ -use common_utils::types::NameType; use masking::Secret; use serde::{Deserialize, Serialize}; use time::PrimitiveDateTime; @@ -58,7 +57,7 @@ pub struct MandateCardDetails { pub card_exp_year: Option>, /// The card holder name #[schema(value_type = Option)] - pub card_holder_name: Option, + pub card_holder_name: Option, /// The token from card locker #[schema(value_type = Option)] pub card_token: Option>, @@ -80,7 +79,7 @@ pub struct MandateCardDetails { pub card_type: Option, /// The nick_name of the card holder #[schema(value_type = Option)] - pub nick_name: Option, + pub nick_name: Option, } #[derive(Clone, Debug, Deserialize, ToSchema, Serialize)] @@ -152,7 +151,7 @@ pub struct NetworkTransactionIdAndCardDetails { /// The card holder's name #[schema(value_type = String, example = "John Test")] - pub card_holder_name: Option, + pub card_holder_name: Option, /// The name of the issuer of card #[schema(example = "chase")] @@ -173,7 +172,7 @@ pub struct NetworkTransactionIdAndCardDetails { /// The card holder's nick name #[schema(value_type = Option, example = "John Test")] - pub nick_name: Option, + pub nick_name: Option, /// The network transaction ID provided by the card network during a CIT (Customer Initiated Transaction), /// where `setup_future_usage` is set to `off_session`. diff --git a/crates/api_models/src/payment_methods.rs b/crates/api_models/src/payment_methods.rs index d1490065998..af96b05cb4d 100644 --- a/crates/api_models/src/payment_methods.rs +++ b/crates/api_models/src/payment_methods.rs @@ -9,7 +9,7 @@ use common_utils::{ errors, ext_traits::OptionExt, id_type, link_utils, pii, - types::{MinorUnit, NameType, Percentage, Surcharge}, + types::{MinorUnit, Percentage, Surcharge}, }; use masking::PeekInterface; use serde::de; @@ -421,11 +421,11 @@ pub struct CardDetail { /// Card Holder Name #[schema(value_type = String,example = "John Doe")] - pub card_holder_name: Option, + pub card_holder_name: Option, /// Card Holder's Nick Name #[schema(value_type = Option,example = "John Doe")] - pub nick_name: Option, + pub nick_name: Option, /// Card Issuing Country pub card_issuing_country: Option, @@ -469,11 +469,11 @@ pub struct CardDetail { /// Card Holder Name #[schema(value_type = String,example = "John Doe")] - pub card_holder_name: Option, + pub card_holder_name: Option, /// Card Holder's Nick Name #[schema(value_type = Option,example = "John Doe")] - pub nick_name: Option, + pub nick_name: Option, /// Card Issuing Country #[schema(value_type = CountryAlpha2)] @@ -507,11 +507,11 @@ pub struct MigrateCardDetail { /// Card Holder Name #[schema(value_type = String,example = "John Doe")] - pub card_holder_name: Option, + pub card_holder_name: Option, /// Card Holder's Nick Name #[schema(value_type = Option,example = "John Doe")] - pub nick_name: Option, + pub nick_name: Option, /// Card Issuing Country pub card_issuing_country: Option, @@ -544,11 +544,11 @@ pub struct MigrateNetworkTokenData { /// Card Holder Name #[schema(value_type = String,example = "John Doe")] - pub card_holder_name: Option, + pub card_holder_name: Option, /// Card Holder's Nick Name #[schema(value_type = Option,example = "John Doe")] - pub nick_name: Option, + pub nick_name: Option, /// Card Issuing Country pub card_issuing_country: Option, @@ -591,11 +591,11 @@ pub struct CardDetailUpdate { /// Card Holder Name #[schema(value_type = String,example = "John Doe")] - pub card_holder_name: Option, + pub card_holder_name: Option, /// Card Holder's Nick Name #[schema(value_type = Option,example = "John Doe")] - pub nick_name: Option, + pub nick_name: Option, } #[cfg(all( @@ -633,11 +633,11 @@ impl CardDetailUpdate { pub struct CardDetailUpdate { /// Card Holder Name #[schema(value_type = String,example = "John Doe")] - pub card_holder_name: Option, + pub card_holder_name: Option, /// Card Holder's Nick Name #[schema(value_type = Option,example = "John Doe")] - pub nick_name: Option, + pub nick_name: Option, } #[cfg(all(feature = "v2", feature = "payment_methods_v2"))] @@ -795,8 +795,8 @@ pub struct CardDetailsPaymentMethod { pub issuer_country: Option, pub expiry_month: Option>, pub expiry_year: Option>, - pub nick_name: Option, - pub card_holder_name: Option, + pub nick_name: Option, + pub card_holder_name: Option, pub card_isin: Option, pub card_issuer: Option, pub card_network: Option, @@ -869,12 +869,12 @@ pub enum BankAccountAccessCreds { #[derive(Debug, serde::Deserialize, serde::Serialize, Clone)] pub struct Card { pub card_number: CardNumber, - pub name_on_card: Option, + pub name_on_card: Option, pub card_exp_month: masking::Secret, pub card_exp_year: masking::Secret, pub card_brand: Option, pub card_isin: Option, - pub nick_name: Option, + pub nick_name: Option, } #[cfg(all( @@ -900,13 +900,13 @@ pub struct CardDetailFromLocker { pub card_token: Option>, #[schema(value_type=Option)] - pub card_holder_name: Option, + pub card_holder_name: Option, #[schema(value_type=Option)] pub card_fingerprint: Option>, #[schema(value_type=Option)] - pub nick_name: Option, + pub nick_name: Option, #[schema(value_type = Option)] pub card_network: Option, @@ -934,13 +934,13 @@ pub struct CardDetailFromLocker { pub expiry_year: Option>, #[schema(value_type=Option)] - pub card_holder_name: Option, + pub card_holder_name: Option, #[schema(value_type=Option)] pub card_fingerprint: Option>, #[schema(value_type=Option)] - pub nick_name: Option, + pub nick_name: Option, #[schema(value_type = Option)] pub card_network: Option, @@ -2138,14 +2138,14 @@ pub struct TokenizedBankRedirectValue2 { #[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] pub struct PaymentMethodRecord { pub customer_id: id_type::CustomerId, - pub name: Option, + pub name: Option, pub email: Option, pub phone: Option>, pub phone_country_code: Option, pub merchant_id: Option, pub payment_method: Option, pub payment_method_type: Option, - pub nick_name: NameType, + pub nick_name: common_utils::types::NameType, pub payment_instrument_id: Option>, pub card_number_masked: masking::Secret, pub card_expiry_month: masking::Secret, @@ -2154,8 +2154,8 @@ pub struct PaymentMethodRecord { pub original_transaction_id: Option, pub billing_address_zip: masking::Secret, pub billing_address_state: masking::Secret, - pub billing_address_first_name: NameType, - pub billing_address_last_name: NameType, + pub billing_address_first_name: common_utils::types::NameType, + pub billing_address_last_name: common_utils::types::NameType, pub billing_address_city: String, pub billing_address_country: Option, pub billing_address_line1: masking::Secret, diff --git a/crates/api_models/src/payments.rs b/crates/api_models/src/payments.rs index 5d723023dae..930ed18e36d 100644 --- a/crates/api_models/src/payments.rs +++ b/crates/api_models/src/payments.rs @@ -16,7 +16,7 @@ use common_utils::{ hashing::HashedString, id_type, pii::{self, Email}, - types::{MinorUnit, NameType, StringMajorUnit}, + types::{MinorUnit, StringMajorUnit}, }; use error_stack::ResultExt; use masking::{ExposeInterface, PeekInterface, Secret, WithType}; @@ -1683,7 +1683,7 @@ pub struct Card { /// The card holder's name #[schema(value_type = String, example = "John Test")] - pub card_holder_name: Option, + pub card_holder_name: Option, /// The CVC number for the card #[schema(value_type = String, example = "242")] @@ -1707,7 +1707,7 @@ pub struct Card { pub bank_code: Option, /// The card holder's nick name #[schema(value_type = Option, example = "John Test")] - pub nick_name: Option, + pub nick_name: Option, } #[derive(Default, Eq, PartialEq, Clone, Debug, serde::Deserialize, serde::Serialize, ToSchema)] @@ -1726,7 +1726,7 @@ pub struct ExtendedCardInfo { /// The card holder's name #[schema(value_type = String, example = "John Test")] - pub card_holder_name: Option, + pub card_holder_name: Option, /// The CVC number for the card #[schema(value_type = String, example = "242")] @@ -1785,13 +1785,23 @@ impl GetAddressFromPaymentMethodData for Card { let first_name = card_holder_name_iter .next() .map(ToOwned::to_owned) - .and_then(|name| NameType::try_from(name).ok()); + .and_then(|name| { + common_utils::types::NameType::try_from(name) + .map_err(|err| { + router_env::logger::error!("Invalid First Name: {}", err); + }) + .ok() + }); let last_name = card_holder_name_iter.collect::>().join(" "); let last_name = if last_name.is_empty_after_trim() { None } else { - NameType::try_from(last_name).ok() + common_utils::types::NameType::try_from(last_name) + .map_err(|err| { + router_env::logger::error!("Invalid Last Name: {}", err); + }) + .ok() }; AddressDetails { @@ -1843,7 +1853,7 @@ impl Card { pub struct CardToken { /// The card holder's name #[schema(value_type = String, example = "John Test")] - pub card_holder_name: Option, + pub card_holder_name: Option, /// The CVC number for the card #[schema(value_type = Option)] @@ -1886,7 +1896,7 @@ pub enum PayLaterData { billing_email: Option, /// The billing name #[schema(value_type = Option)] - billing_name: Option, + billing_name: Option, }, /// For PayBright Redirect as PayLater Option PayBrightRedirect {}, @@ -1956,10 +1966,10 @@ pub enum BankDebitData { routing_number: Secret, #[schema(value_type = String, example = "John Test")] - card_holder_name: Option, + card_holder_name: Option, #[schema(value_type = String, example = "John Doe")] - bank_account_holder_name: Option, + bank_account_holder_name: Option, #[schema(value_type = String, example = "ACH")] bank_name: Option, @@ -1978,7 +1988,7 @@ pub enum BankDebitData { iban: Secret, /// Owner name for bank debit #[schema(value_type = String, example = "A. Schneider")] - bank_account_holder_name: Option, + bank_account_holder_name: Option, }, BecsBankDebit { /// Billing details for bank debit @@ -1991,7 +2001,7 @@ pub enum BankDebitData { bsb_number: Secret, /// Owner name for bank debit #[schema(value_type = Option, example = "A. Schneider")] - bank_account_holder_name: Option, + bank_account_holder_name: Option, }, BacsBankDebit { /// Billing details for bank debit @@ -2004,7 +2014,7 @@ pub enum BankDebitData { sort_code: Secret, /// holder name for bank debit #[schema(value_type = String, example = "A. Schneider")] - bank_account_holder_name: Option, + bank_account_holder_name: Option, }, } @@ -2012,7 +2022,7 @@ impl GetAddressFromPaymentMethodData for BankDebitData { fn get_billing_address(&self) -> Option
{ fn get_billing_address_inner( bank_debit_billing: Option<&BankDebitBilling>, - bank_account_holder_name: Option<&NameType>, + bank_account_holder_name: Option<&common_utils::types::NameType>, ) -> Option
{ // We will always have address here let mut address = bank_debit_billing @@ -2142,7 +2152,16 @@ mod payment_method_data_serde { card.card_holder_name = billing_address_details .get_optional_full_name() .and_then(|name| { - NameType::try_from(name.expose()).ok() + common_utils::types::NameType::try_from( + name.expose(), + ) + .map_err(|err| { + router_env::logger::error!( + "Invalid Card Holder Name: {}", + err + ); + }) + .ok() }); } Some(PaymentMethodData::Card(card.clone())) @@ -2581,7 +2600,7 @@ pub struct AdditionalCardInfo { pub card_exp_year: Option>, - pub card_holder_name: Option, + pub card_holder_name: Option, /// Additional payment checks done on the cvv and billing address by the processors. /// This is a free form field and the structure varies from processor to processor @@ -2678,7 +2697,7 @@ pub enum BankRedirectData { /// The card holder's name #[schema(value_type = String, example = "John Test")] - card_holder_name: Option, + card_holder_name: Option, //Required by Stripes billing_details: Option, @@ -2923,10 +2942,10 @@ impl GetAddressFromPaymentMethodData for BankRedirectData { pub struct AlfamartVoucherData { /// The billing first name for Alfamart #[schema(value_type = Option, example = "Jane")] - pub first_name: Option, + pub first_name: Option, /// The billing second name for Alfamart #[schema(value_type = Option, example = "Doe")] - pub last_name: Option, + pub last_name: Option, /// The Email ID for Alfamart #[schema(value_type = Option, example = "example@me.com")] pub email: Option, @@ -2936,10 +2955,10 @@ pub struct AlfamartVoucherData { pub struct IndomaretVoucherData { /// The billing first name for Alfamart #[schema(value_type = Option, example = "Jane")] - pub first_name: Option, + pub first_name: Option, /// The billing second name for Alfamart #[schema(value_type = Option, example = "Doe")] - pub last_name: Option, + pub last_name: Option, /// The Email ID for Alfamart #[schema(value_type = Option, example = "example@me.com")] pub email: Option, @@ -2949,10 +2968,10 @@ pub struct IndomaretVoucherData { pub struct JCSVoucherData { /// The billing first name for Japanese convenience stores #[schema(value_type = Option, example = "Jane")] - pub first_name: Option, + pub first_name: Option, /// The billing second name Japanese convenience stores #[schema(value_type = Option, example = "Doe")] - pub last_name: Option, + pub last_name: Option, /// The Email ID for Japanese convenience stores #[schema(value_type = Option, example = "example@me.com")] pub email: Option, @@ -2972,10 +2991,10 @@ pub struct AchBillingDetails { pub struct DokuBillingDetails { /// The billing first name for Doku #[schema(value_type = Option, example = "Jane")] - pub first_name: Option, + pub first_name: Option, /// The billing second name for Doku #[schema(value_type = Option, example = "Doe")] - pub last_name: Option, + pub last_name: Option, /// The Email ID for Doku billing #[schema(value_type = Option, example = "example@me.com")] pub email: Option, @@ -2994,7 +3013,7 @@ pub struct SepaAndBacsBillingDetails { pub email: Option, /// The billing name for SEPA and BACS billing #[schema(value_type = Option, example = "Jane Doe")] - pub name: Option, + pub name: Option, } #[derive(Debug, Clone, Eq, PartialEq, serde::Deserialize, serde::Serialize, ToSchema)] @@ -3032,7 +3051,7 @@ pub struct SofortBilling { pub struct BankRedirectBilling { /// The name for which billing is issued #[schema(value_type = String, example = "John Doe")] - pub billing_name: Option, + pub billing_name: Option, /// The billing email for bank redirect #[schema(value_type = String, example = "example@example.com")] pub email: Option, @@ -3202,7 +3221,7 @@ impl GetAddressFromPaymentMethodData for BankTransferData { pub struct BankDebitBilling { /// The billing name for bank debits #[schema(value_type = Option, example = "John Doe")] - pub name: Option, + pub name: Option, /// The billing email for bank debits #[schema(value_type = Option, example = "example@example.com")] pub email: Option, @@ -3626,7 +3645,7 @@ pub struct CardResponse { #[schema(value_type = Option)] pub card_exp_year: Option>, #[schema(value_type = Option)] - pub card_holder_name: Option, + pub card_holder_name: Option, pub payment_checks: Option, pub authentication_data: Option, } @@ -4014,11 +4033,11 @@ pub struct AddressDetails { /// The first name for the address #[schema(value_type = Option, max_length = 255, example = "John")] - pub first_name: Option, + pub first_name: Option, /// The last name for the address #[schema(value_type = Option, max_length = 255, example = "Doe")] - pub last_name: Option, + pub last_name: Option, } impl AddressDetails { @@ -7367,7 +7386,8 @@ mod billing_from_payment_method_data { #[test] fn test_bank_redirect_payment_method_data_eps() { let test_email = Email::try_from("example@example.com".to_string()).unwrap(); - let test_first_name = NameType::try_from(String::from("Chaser")).unwrap(); + let test_first_name = + common_utils::types::NameType::try_from(String::from("Chaser")).unwrap(); let bank_redirect_billing = BankRedirectBilling { billing_name: Some(test_first_name.clone()), @@ -7418,7 +7438,8 @@ mod billing_from_payment_method_data { #[test] fn test_bank_debit_payment_method_data_ach() { let test_email = Email::try_from("example@example.com".to_string()).unwrap(); - let test_first_name = NameType::try_from(String::from("Chaser")).unwrap(); + let test_first_name = + common_utils::types::NameType::try_from(String::from("Chaser")).unwrap(); let bank_redirect_billing = BankDebitBilling { name: Some(test_first_name.clone()), @@ -7452,7 +7473,10 @@ mod billing_from_payment_method_data { #[test] fn test_card_payment_method_data() { let card_payment_method_data = PaymentMethodData::Card(Card { - card_holder_name: Some(NameType::try_from(TEST_FIRST_NAME_SINGLE.to_string()).unwrap()), + card_holder_name: Some( + common_utils::types::NameType::try_from(TEST_FIRST_NAME_SINGLE.to_string()) + .unwrap(), + ), ..Default::default() }); @@ -7482,7 +7506,9 @@ mod billing_from_payment_method_data { #[test] fn test_card_payment_method_data_full_name() { let card_payment_method_data = PaymentMethodData::Card(Card { - card_holder_name: Some(NameType::try_from(TEST_FULL_NAME.to_string()).unwrap()), + card_holder_name: Some( + common_utils::types::NameType::try_from(TEST_FULL_NAME.to_string()).unwrap(), + ), ..Default::default() }); @@ -7507,7 +7533,9 @@ mod billing_from_payment_method_data { #[test] fn test_card_payment_method_data_empty_string() { let card_payment_method_data = PaymentMethodData::Card(Card { - card_holder_name: Some(NameType::try_from("".to_string()).unwrap()), + card_holder_name: Some( + common_utils::types::NameType::try_from("".to_string()).unwrap(), + ), ..Default::default() }); diff --git a/crates/api_models/src/payments/additional_info.rs b/crates/api_models/src/payments/additional_info.rs index 7909e112447..56bcae9c32d 100644 --- a/crates/api_models/src/payments/additional_info.rs +++ b/crates/api_models/src/payments/additional_info.rs @@ -1,8 +1,5 @@ -use common_utils::{ - new_type::{ - MaskedBankAccount, MaskedIban, MaskedRoutingNumber, MaskedSortCode, MaskedUpiVpaId, - }, - types::NameType, +use common_utils::new_type::{ + MaskedBankAccount, MaskedIban, MaskedRoutingNumber, MaskedSortCode, MaskedUpiVpaId, }; use masking::Secret; use utoipa::ToSchema; @@ -30,11 +27,11 @@ pub struct AchBankDebitAdditionalData { /// Card holder's name #[schema(value_type = Option, example = "John Doe")] - pub card_holder_name: Option, + pub card_holder_name: Option, /// Bank account's owner name #[schema(value_type = Option, example = "John Doe")] - pub bank_account_holder_name: Option, + pub bank_account_holder_name: Option, /// Name of the bank #[schema(value_type = Option, example = "ach")] @@ -61,7 +58,7 @@ pub struct BacsBankDebitAdditionalData { /// Bank account's owner name #[schema(value_type = Option, example = "John Doe")] - pub bank_account_holder_name: Option, + pub bank_account_holder_name: Option, } #[derive(Eq, PartialEq, Clone, Debug, serde::Deserialize, serde::Serialize, ToSchema)] @@ -76,7 +73,7 @@ pub struct BecsBankDebitAdditionalData { /// Bank account's owner name #[schema(value_type = Option, example = "John Doe")] - pub bank_account_holder_name: Option, + pub bank_account_holder_name: Option, } #[derive(Eq, PartialEq, Clone, Debug, serde::Deserialize, serde::Serialize, ToSchema)] @@ -87,7 +84,7 @@ pub struct SepaBankDebitAdditionalData { /// Bank account's owner name #[schema(value_type = Option, example = "John Doe")] - pub bank_account_holder_name: Option, + pub bank_account_holder_name: Option, } #[derive(Eq, PartialEq, Clone, Debug, serde::Deserialize, serde::Serialize, ToSchema)] @@ -113,7 +110,7 @@ pub struct BancontactBankRedirectAdditionalData { /// The card holder's name #[schema(value_type = Option, example = "John Test")] - pub card_holder_name: Option, + pub card_holder_name: Option, } #[derive(Eq, PartialEq, Clone, Debug, serde::Deserialize, serde::Serialize, ToSchema)] @@ -196,7 +193,7 @@ pub struct GivexGiftCardAdditionalData { pub struct CardTokenAdditionalData { /// The card holder's name #[schema(value_type = String, example = "John Test")] - pub card_holder_name: Option, + pub card_holder_name: Option, } #[derive(Debug, Clone, Eq, PartialEq, serde::Deserialize, serde::Serialize, ToSchema)] diff --git a/crates/api_models/src/payouts.rs b/crates/api_models/src/payouts.rs index faa4ebd7aa5..293ec8eb4de 100644 --- a/crates/api_models/src/payouts.rs +++ b/crates/api_models/src/payouts.rs @@ -6,7 +6,7 @@ use common_utils::{ crypto, id_type, link_utils, payout_method_utils, pii::{self, Email}, transformers::ForeignFrom, - types::{NameType, UnifiedCode, UnifiedMessage}, + types::{UnifiedCode, UnifiedMessage}, }; use masking::Secret; use router_derive::FlatStruct; @@ -251,7 +251,7 @@ pub struct CardPayout { /// The card holder's name #[schema(value_type = String, example = "John Doe")] - pub card_holder_name: Option, + pub card_holder_name: Option, } #[derive(Eq, PartialEq, Clone, Debug, Deserialize, Serialize, ToSchema)] diff --git a/crates/hyperswitch_domain_models/src/address.rs b/crates/hyperswitch_domain_models/src/address.rs index fc0f1f2cf6c..ae881e4571a 100644 --- a/crates/hyperswitch_domain_models/src/address.rs +++ b/crates/hyperswitch_domain_models/src/address.rs @@ -1,4 +1,3 @@ -use common_utils::types::NameType; use masking::{PeekInterface, Secret}; #[derive(Default, Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] @@ -41,8 +40,8 @@ pub struct AddressDetails { pub line3: Option>, pub zip: Option>, pub state: Option>, - pub first_name: Option, - pub last_name: Option, + pub first_name: Option, + pub last_name: Option, } impl AddressDetails { diff --git a/crates/hyperswitch_domain_models/src/payment_method_data.rs b/crates/hyperswitch_domain_models/src/payment_method_data.rs index 74105e7f223..6a11df4ecbd 100644 --- a/crates/hyperswitch_domain_models/src/payment_method_data.rs +++ b/crates/hyperswitch_domain_models/src/payment_method_data.rs @@ -9,7 +9,6 @@ use common_utils::{ MaskedBankAccount, MaskedIban, MaskedRoutingNumber, MaskedSortCode, MaskedUpiVpaId, }, pii::{self, Email}, - types::NameType, }; use masking::{PeekInterface, Secret}; use serde::{Deserialize, Serialize}; @@ -82,8 +81,8 @@ pub struct Card { pub card_type: Option, pub card_issuing_country: Option, pub bank_code: Option, - pub nick_name: Option, - pub card_holder_name: Option, + pub nick_name: Option, + pub card_holder_name: Option, } #[derive(Eq, PartialEq, Clone, Debug, Serialize, Deserialize, Default)] @@ -96,8 +95,8 @@ pub struct CardDetailsForNetworkTransactionId { pub card_type: Option, pub card_issuing_country: Option, pub bank_code: Option, - pub nick_name: Option, - pub card_holder_name: Option, + pub nick_name: Option, + pub card_holder_name: Option, } impl CardDetailsForNetworkTransactionId { @@ -376,7 +375,7 @@ pub enum BankRedirectData { card_number: Option, card_exp_month: Option>, card_exp_year: Option>, - card_holder_name: Option, + card_holder_name: Option, }, Bizum {}, Blik { @@ -516,7 +515,7 @@ pub struct GiftCardDetails { #[serde(rename_all = "snake_case")] pub struct CardToken { /// The card holder's name - pub card_holder_name: Option, + pub card_holder_name: Option, /// The CVC number for the card pub card_cvc: Option>, @@ -528,25 +527,25 @@ pub enum BankDebitData { AchBankDebit { account_number: Secret, routing_number: Secret, - card_holder_name: Option, - bank_account_holder_name: Option, + card_holder_name: Option, + bank_account_holder_name: Option, bank_name: Option, bank_type: Option, bank_holder_type: Option, }, SepaBankDebit { iban: Secret, - bank_account_holder_name: Option, + bank_account_holder_name: Option, }, BecsBankDebit { account_number: Secret, bsb_number: Secret, - bank_account_holder_name: Option, + bank_account_holder_name: Option, }, BacsBankDebit { account_number: Secret, sort_code: Secret, - bank_account_holder_name: Option, + bank_account_holder_name: Option, }, } @@ -597,7 +596,7 @@ pub struct NetworkTokenData { pub card_type: Option, pub card_issuing_country: Option, pub bank_code: Option, - pub nick_name: Option, + pub nick_name: Option, pub eci: Option, } @@ -1446,7 +1445,7 @@ pub struct TokenizedCardValue1 { pub nickname: Option, pub card_last_four: Option, pub card_token: Option, - pub card_holder_name: Option, + pub card_holder_name: Option, } #[derive(Debug, serde::Serialize, serde::Deserialize)] diff --git a/crates/hyperswitch_domain_models/src/router_data.rs b/crates/hyperswitch_domain_models/src/router_data.rs index 02c193626ac..560b171d5c7 100644 --- a/crates/hyperswitch_domain_models/src/router_data.rs +++ b/crates/hyperswitch_domain_models/src/router_data.rs @@ -4,7 +4,7 @@ use common_utils::{ errors::IntegrityCheckError, ext_traits::{OptionExt, ValueExt}, id_type, - types::{MinorUnit, NameType}, + types::MinorUnit, }; use error_stack::ResultExt; use masking::{ExposeInterface, Secret}; @@ -281,7 +281,7 @@ pub struct PazeDynamicData { #[derive(Debug, Clone, serde::Deserialize)] #[serde(rename_all = "camelCase")] pub struct PazeAddress { - pub name: Option, + pub name: Option, pub line1: Option>, pub line2: Option>, pub line3: Option>, diff --git a/crates/hyperswitch_domain_models/src/router_request_types/fraud_check.rs b/crates/hyperswitch_domain_models/src/router_request_types/fraud_check.rs index 44feac85e32..1e55a8e3222 100644 --- a/crates/hyperswitch_domain_models/src/router_request_types/fraud_check.rs +++ b/crates/hyperswitch_domain_models/src/router_request_types/fraud_check.rs @@ -3,7 +3,6 @@ use common_enums; use common_utils::{ events::{ApiEventMetric, ApiEventsType}, pii::Email, - types::NameType, }; use diesel_models::types::OrderDetailsWithAmount; use masking::Secret; @@ -141,7 +140,7 @@ pub struct Product { #[serde_with::skip_serializing_none] #[serde(rename_all = "snake_case")] pub struct Destination { - pub full_name: NameType, + pub full_name: common_utils::types::NameType, pub organization: Option, pub email: Option, pub address: Address, diff --git a/crates/router/src/compatibility/stripe/customers/types.rs b/crates/router/src/compatibility/stripe/customers/types.rs index 080aabf895f..8f523be7d7a 100644 --- a/crates/router/src/compatibility/stripe/customers/types.rs +++ b/crates/router/src/compatibility/stripe/customers/types.rs @@ -11,7 +11,7 @@ use common_utils::{crypto::Encryptable, date_time}; use common_utils::{ id_type, pii::{self, Email}, - types::{Description, NameType}, + types::Description, }; use serde::{Deserialize, Serialize}; @@ -42,7 +42,7 @@ pub struct StripeAddressDetails { pub struct CreateCustomerRequest { pub email: Option, pub invoice_prefix: Option, - pub name: Option, + pub name: Option, pub phone: Option>, pub address: Option, pub metadata: Option, diff --git a/crates/router/src/compatibility/stripe/payment_intents/types.rs b/crates/router/src/compatibility/stripe/payment_intents/types.rs index db602fb6208..058f8c0b46e 100644 --- a/crates/router/src/compatibility/stripe/payment_intents/types.rs +++ b/crates/router/src/compatibility/stripe/payment_intents/types.rs @@ -7,10 +7,9 @@ use common_utils::{ ext_traits::StringExt, id_type, pii::{IpAddress, SecretSerdeValue, UpiVpaMaskingStrategy}, - types::{MinorUnit, NameType}, + types::MinorUnit, }; use error_stack::ResultExt; -use router_env::logger; use serde::{Deserialize, Serialize}; use time::PrimitiveDateTime; @@ -65,7 +64,7 @@ pub struct StripeCard { pub exp_month: masking::Secret, pub exp_year: masking::Secret, pub cvc: masking::Secret, - pub holder_name: Option, + pub holder_name: Option, } // ApplePay wallet param is not available in stripe Docs @@ -170,7 +169,7 @@ impl From for payments::PaymentMethodData { #[derive(Default, Serialize, PartialEq, Eq, Deserialize, Clone, Debug)] pub struct Shipping { pub address: AddressDetails, - pub name: Option, + pub name: Option, pub carrier: Option, pub phone: Option>, pub tracking_number: Option>, @@ -944,12 +943,9 @@ fn get_pmd_based_on_payment_method_type( billing_details: billing_details.as_ref().map(|billing_data| { payments::BankRedirectBilling { billing_name: billing_data.get_optional_full_name().and_then(|name| { - NameType::try_from(name) + common_utils::types::NameType::try_from(name) .map_err(|err| { - logger::error!( - "Error while converting name to NameType: {}", - err - ); + router_env::logger::error!("Invalid Billing Name: {}", err); }) .ok() }), diff --git a/crates/router/src/compatibility/stripe/setup_intents/types.rs b/crates/router/src/compatibility/stripe/setup_intents/types.rs index 021ee3869d9..e423f62ecad 100644 --- a/crates/router/src/compatibility/stripe/setup_intents/types.rs +++ b/crates/router/src/compatibility/stripe/setup_intents/types.rs @@ -1,7 +1,7 @@ use std::str::FromStr; use api_models::payments; -use common_utils::{date_time, ext_traits::StringExt, id_type, pii as secret, types::NameType}; +use common_utils::{date_time, ext_traits::StringExt, id_type, pii as secret}; use error_stack::ResultExt; use router_env::logger; use serde::{Deserialize, Serialize}; @@ -96,7 +96,8 @@ impl From for payments::Card { card_number: card.number, card_exp_month: card.exp_month, card_exp_year: card.exp_year, - card_holder_name: NameType::try_from("Stripe_cust".to_string()).ok(), + card_holder_name: common_utils::types::NameType::try_from("Stripe_cust".to_string()) + .ok(), card_cvc: card.cvc, card_issuer: None, card_network: None, diff --git a/crates/router/src/connector/stripe/transformers/connect.rs b/crates/router/src/connector/stripe/transformers/connect.rs index 49640218445..c749209509a 100644 --- a/crates/router/src/connector/stripe/transformers/connect.rs +++ b/crates/router/src/connector/stripe/transformers/connect.rs @@ -1,5 +1,5 @@ use api_models; -use common_utils::{pii::Email, types::NameType}; +use common_utils::pii::Email; use error_stack::ResultExt; use masking::Secret; use serde::{Deserialize, Serialize}; @@ -124,9 +124,9 @@ pub struct StripeConnectRecipientCreateRequest { #[serde(rename = "company[owners_provided]")] company_owners_provided: Option, #[serde(rename = "individual[first_name]")] - individual_first_name: Option, + individual_first_name: Option, #[serde(rename = "individual[last_name]")] - individual_last_name: Option, + individual_last_name: Option, #[serde(rename = "individual[dob][day]")] individual_dob_day: Option>, #[serde(rename = "individual[dob][month]")] diff --git a/crates/router/src/connector/trustpay/transformers.rs b/crates/router/src/connector/trustpay/transformers.rs index 124a69c12bd..799a519e8c0 100644 --- a/crates/router/src/connector/trustpay/transformers.rs +++ b/crates/router/src/connector/trustpay/transformers.rs @@ -3,7 +3,7 @@ use std::collections::HashMap; use common_utils::{ errors::CustomResult, pii::{self, Email}, - types::{NameType, StringMajorUnit}, + types::StringMajorUnit, }; use error_stack::{report, ResultExt}; use masking::{ExposeInterface, PeekInterface, Secret}; @@ -276,7 +276,7 @@ fn get_card_request_data( .get_billing()? .address .as_ref() - .and_then(|address| address.last_name.clone()); + .and_then(|address| address.last_name.clone().map(From::from)); Ok(TrustpayPaymentsRequest::CardsPaymentRequest(Box::new( PaymentRequestCards { amount, @@ -312,7 +312,7 @@ fn get_card_request_data( fn get_full_name( billing_first_name: Secret, - billing_last_name: Option, + billing_last_name: Option>, ) -> Secret { match billing_last_name { Some(last_name) => format!("{} {}", billing_first_name.peek(), last_name.peek()).into(), @@ -329,7 +329,7 @@ fn get_debtor_info( .get_billing()? .address .as_ref() - .and_then(|address| address.last_name.clone()); + .and_then(|address| address.last_name.clone().map(From::from)); Ok(match pm { TrustpayPaymentMethod::Blik => Some(DebtorInformation { name: get_full_name(params.billing_first_name, billing_last_name), diff --git a/crates/router/src/core/payment_methods.rs b/crates/router/src/core/payment_methods.rs index 0d084f51452..415051c3373 100644 --- a/crates/router/src/core/payment_methods.rs +++ b/crates/router/src/core/payment_methods.rs @@ -25,7 +25,7 @@ use api_models::payment_methods; pub use api_models::{enums::PayoutConnectors, payouts as payout_types}; #[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "customer_v2")))] use common_utils::ext_traits::Encode; -use common_utils::{consts::DEFAULT_LOCALE, id_type, types::NameType}; +use common_utils::{consts::DEFAULT_LOCALE, id_type}; #[cfg(all(feature = "v2", feature = "payment_methods_v2"))] use common_utils::{ crypto::{self, Encryptable}, @@ -693,12 +693,9 @@ pub(crate) async fn get_payment_method_create_request( card_exp_month: card.card_exp_month.clone(), card_exp_year: card.card_exp_year.clone(), card_holder_name: billing_name.and_then(|name| { - NameType::try_from(name) + common_utils::types::NameType::try_from(name) .map_err(|err| { - logger::error!( - "Failed to convert billing name to NameType: {}", - err - ); + logger::error!("Invalid Card Holder Name: {}", err); }) .ok() }), @@ -780,12 +777,9 @@ pub(crate) async fn get_payment_method_create_request( card_exp_month: card.card_exp_month.clone(), card_exp_year: card.card_exp_year.clone(), card_holder_name: billing_name.and_then(|name| { - NameType::try_from(name) + common_utils::types::NameType::try_from(name) .map_err(|err| { - logger::error!( - "Failed to convert billing name to NameType: {}", - err - ); + logger::error!("Invalid Card Holder Name: {}", err); }) .ok() }), diff --git a/crates/router/src/core/payment_methods/cards.rs b/crates/router/src/core/payment_methods/cards.rs index fff7bad873b..bc2b788a3a6 100644 --- a/crates/router/src/core/payment_methods/cards.rs +++ b/crates/router/src/core/payment_methods/cards.rs @@ -3041,9 +3041,13 @@ pub async fn mock_get_card<'a>( .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 - .and_then(|card| card.try_into().ok()), + name_on_card: locker_mock_up.name_on_card.and_then(|card| { + card.try_into() + .map_err(|_| { + router_env::logger::error!("Failed to convert name to NameType"); + }) + .ok() + }), nickname: locker_mock_up.nickname, customer_id: locker_mock_up.customer_id, duplicate: locker_mock_up.duplicate, diff --git a/crates/router/src/core/payment_methods/transformers.rs b/crates/router/src/core/payment_methods/transformers.rs index 9d624ff4127..5b7298dc267 100644 --- a/crates/router/src/core/payment_methods/transformers.rs +++ b/crates/router/src/core/payment_methods/transformers.rs @@ -9,9 +9,8 @@ use common_utils::{ id_type, pii::Email, request::RequestContent, - types::NameType, }; -use error_stack::{report, ResultExt}; +use error_stack::ResultExt; use josekit::jwe; use router_env::tracing_actix_web::RequestId; use serde::{Deserialize, Serialize}; @@ -145,7 +144,7 @@ pub struct AddCardResponse { pub card_number: Option, pub card_exp_year: Option>, pub card_exp_month: Option>, - pub name_on_card: Option, + pub name_on_card: Option, pub nickname: Option, pub customer_id: Option, pub duplicate: Option, @@ -664,12 +663,9 @@ pub fn mk_get_card_response(card: GetCardResponse) -> errors::RouterResult card_brand: None, card_isin: None, nick_name: card.card.nickname.and_then(|name| { - NameType::try_from(name) - .map_err(|_| { - report!(errors::ApiErrorResponse::InvalidDataFormat { - field_name: "nick_name".to_string(), - expected_format: "NameType".to_string() - }) + common_utils::types::NameType::try_from(name) + .map_err(|err| { + router_env::logger::error!("Invalid Nick Name: {}", err); }) .ok() }), diff --git a/crates/router/src/core/payment_methods/vault.rs b/crates/router/src/core/payment_methods/vault.rs index 38720e6e83a..88db241c31e 100644 --- a/crates/router/src/core/payment_methods/vault.rs +++ b/crates/router/src/core/payment_methods/vault.rs @@ -6,7 +6,6 @@ use common_utils::{ ext_traits::{BytesExt, Encode}, generate_id_with_default_len, id_type, pii::Email, - types::NameType, }; use error_stack::{report, ResultExt}; use masking::PeekInterface; @@ -120,9 +119,13 @@ impl Vaultable for domain::Card { bank_code: None, card_issuing_country: None, card_type: None, - nick_name: value1 - .nickname - .and_then(|name| NameType::try_from(name).ok()), + nick_name: value1.nickname.and_then(|name| { + common_utils::types::NameType::try_from(name) + .map_err(|err| { + router_env::logger::error!("Invalid Nick Name: {}", err); + }) + .ok() + }), card_holder_name: value1.card_holder_name, }; @@ -517,9 +520,13 @@ impl Vaultable for api::CardPayout { .map_err(|_| errors::VaultError::FetchCardFailed)?, expiry_month: value1.exp_month.into(), expiry_year: value1.exp_year.into(), - card_holder_name: value1 - .name_on_card - .and_then(|name| NameType::try_from(name).ok()), + card_holder_name: value1.name_on_card.and_then(|name| { + common_utils::types::NameType::try_from(name) + .map_err(|err| { + router_env::logger::error!("Invalid Nick Name: {}", err); + }) + .ok() + }), }; let supp_data = SupplementaryVaultData { diff --git a/crates/router/src/core/utils.rs b/crates/router/src/core/utils.rs index 0617c6bc392..aaa9953824c 100644 --- a/crates/router/src/core/utils.rs +++ b/crates/router/src/core/utils.rs @@ -19,7 +19,7 @@ use hyperswitch_domain_models::{ #[cfg(feature = "payouts")] use masking::{ExposeInterface, PeekInterface}; use maud::{html, PreEscaped}; -use router_env::{instrument, logger, tracing}; +use router_env::{instrument, tracing}; use uuid::Uuid; use super::payments::helpers; @@ -100,7 +100,7 @@ pub async fn construct_payout_router_data<'a, F>( .and_then(|name| { NameType::try_from(name.expose()) .map_err(|err| { - logger::error!("Error in converting first name: {err}"); + router_env::logger::error!("Invalid First Name: {}", err); }) .ok() }); @@ -111,7 +111,7 @@ pub async fn construct_payout_router_data<'a, F>( .and_then(|name| { NameType::try_from(name.expose()) .map_err(|err| { - logger::error!("Error in converting last name: {err}"); + router_env::logger::error!("Invalid Last Name: {}", err); }) .ok() }); diff --git a/crates/router/src/types/transformers.rs b/crates/router/src/types/transformers.rs index c49ab05ee48..96fe91413eb 100644 --- a/crates/router/src/types/transformers.rs +++ b/crates/router/src/types/transformers.rs @@ -10,13 +10,12 @@ use common_utils::{ ext_traits::{Encode, StringExt, ValueExt}, fp_utils::when, pii, - types::{ConnectorTransactionIdTrait, NameType}, + types::ConnectorTransactionIdTrait, }; use diesel_models::enums as storage_enums; use error_stack::{report, ResultExt}; use hyperswitch_domain_models::payments::payment_intent::CustomerData; use masking::{ExposeInterface, PeekInterface, Secret}; -use router_env::logger; use super::domain; use crate::{ @@ -754,9 +753,9 @@ impl From<&domain::Address> for hyperswitch_domain_models::address::Address { .clone() .map(Encryptable::into_inner) .and_then(|name| { - NameType::try_from(name.expose()) + common_utils::types::NameType::try_from(name.expose()) .map_err(|err| { - logger::error!("Invalid first name: {err}"); + router_env::logger::error!("Invalid First Name: {}", err); }) .ok() }); @@ -765,9 +764,9 @@ impl From<&domain::Address> for hyperswitch_domain_models::address::Address { .clone() .map(Encryptable::into_inner) .and_then(|name| { - NameType::try_from(name.expose()) + common_utils::types::NameType::try_from(name.expose()) .map_err(|err| { - logger::error!("Invalid last name {err}"); + router_env::logger::error!("Invalid Last Name {}", err); }) .ok() }); @@ -822,9 +821,9 @@ impl ForeignFrom for api_types::Address { .clone() .map(Encryptable::into_inner) .and_then(|name| { - NameType::try_from(name.expose()) + common_utils::types::NameType::try_from(name.expose()) .map_err(|err| { - logger::error!("Invalid first name: {err}"); + router_env::logger::error!("Invalid First Name: {}", err); }) .ok() }); @@ -833,9 +832,9 @@ impl ForeignFrom for api_types::Address { .clone() .map(Encryptable::into_inner) .and_then(|name| { - NameType::try_from(name.expose()) + common_utils::types::NameType::try_from(name.expose()) .map_err(|err| { - logger::error!("Invalid last name {err}"); + router_env::logger::error!("Invalid Last Name {}", err); }) .ok() }); @@ -1802,9 +1801,9 @@ impl From for payments::AddressDetails { .clone() .map(Encryptable::into_inner) .and_then(|name| { - NameType::try_from(name.expose()) + common_utils::types::NameType::try_from(name.expose()) .map_err(|err| { - logger::error!("Invalid first name: {err}"); + router_env::logger::error!("Invalid First Name: {}", err); }) .ok() }); @@ -1813,9 +1812,9 @@ impl From for payments::AddressDetails { .clone() .map(Encryptable::into_inner) .and_then(|name| { - NameType::try_from(name.expose()) + common_utils::types::NameType::try_from(name.expose()) .map_err(|err| { - logger::error!("Invalid last name {err}"); + router_env::logger::error!("Invalid Last Name {}", err); }) .ok() }); diff --git a/crates/router/src/utils.rs b/crates/router/src/utils.rs index 657b0ba6bd0..f5696a28518 100644 --- a/crates/router/src/utils.rs +++ b/crates/router/src/utils.rs @@ -36,7 +36,7 @@ pub use hyperswitch_connectors::utils::QrImage; use hyperswitch_domain_models::payments::PaymentIntent; #[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "customer_v2")))] use hyperswitch_domain_models::type_encryption::{crypto_operation, CryptoOperation}; -use masking::{ExposeInterface, PeekInterface, SwitchStrategy}; +use masking::{ExposeInterface, SwitchStrategy}; use nanoid::nanoid; use serde::de::DeserializeOwned; use serde_json::Value; @@ -840,14 +840,8 @@ impl CustomerAddress for api_models::customers::CustomerRequest { line2: address_details.line2.clone(), line3: address_details.line3.clone(), state: address_details.state.clone(), - first_name: address_details - .first_name - .clone() - .map(|name| masking::Secret::new(name.peek().to_string())), - last_name: address_details - .last_name - .clone() - .map(|name| masking::Secret::new(name.peek().to_string())), + first_name: address_details.first_name.clone().map(From::from), + last_name: address_details.last_name.clone().map(From::from), zip: address_details.zip.clone(), phone_number: self.phone.clone(), email: self From 4ead56c152a3b2c6956e9e516374b066fea25885 Mon Sep 17 00:00:00 2001 From: Sk Sakil Mostak Date: Thu, 23 Jan 2025 17:30:23 +0530 Subject: [PATCH 16/19] refactor: resolve comments --- crates/api_models/src/payment_methods.rs | 4 +-- crates/api_models/src/payments.rs | 21 +++++------- .../src/payment_method_data.rs | 2 +- crates/router/src/core/payment_methods.rs | 32 +++++++++++-------- .../router/src/core/payment_methods/cards.rs | 32 +++++++++++-------- .../src/core/payment_methods/transformers.rs | 14 +++----- .../router/src/core/payment_methods/vault.rs | 20 +++--------- 7 files changed, 55 insertions(+), 70 deletions(-) diff --git a/crates/api_models/src/payment_methods.rs b/crates/api_models/src/payment_methods.rs index af96b05cb4d..997ea5a5396 100644 --- a/crates/api_models/src/payment_methods.rs +++ b/crates/api_models/src/payment_methods.rs @@ -2069,8 +2069,8 @@ pub struct TokenizedCardValue1 { pub card_number: String, pub exp_year: String, pub exp_month: String, - pub name_on_card: Option, - pub nickname: Option, + pub name_on_card: Option, + pub nickname: Option, pub card_last_four: Option, pub card_token: Option, } diff --git a/crates/api_models/src/payments.rs b/crates/api_models/src/payments.rs index 930ed18e36d..7471df2f825 100644 --- a/crates/api_models/src/payments.rs +++ b/crates/api_models/src/payments.rs @@ -19,7 +19,7 @@ use common_utils::{ types::{MinorUnit, StringMajorUnit}, }; use error_stack::ResultExt; -use masking::{ExposeInterface, PeekInterface, Secret, WithType}; +use masking::{PeekInterface, Secret, WithType}; use router_derive::Setter; use serde::{de, ser::Serializer, Deserialize, Deserializer, Serialize}; use strum::Display; @@ -2151,18 +2151,13 @@ mod payment_method_data_serde { if card.card_holder_name.is_none() { card.card_holder_name = billing_address_details .get_optional_full_name() - .and_then(|name| { - common_utils::types::NameType::try_from( - name.expose(), - ) - .map_err(|err| { - router_env::logger::error!( - "Invalid Card Holder Name: {}", - err - ); - }) - .ok() - }); + .map(|name| { + common_utils::types::NameType::try_from(name) + .map_err(|err| { + de::Error::custom(err.to_string()) + }) + }) + .transpose()?; } Some(PaymentMethodData::Card(card.clone())) } diff --git a/crates/hyperswitch_domain_models/src/payment_method_data.rs b/crates/hyperswitch_domain_models/src/payment_method_data.rs index 6a11df4ecbd..4604eda610f 100644 --- a/crates/hyperswitch_domain_models/src/payment_method_data.rs +++ b/crates/hyperswitch_domain_models/src/payment_method_data.rs @@ -1442,7 +1442,7 @@ pub struct TokenizedCardValue1 { pub card_number: String, pub exp_year: String, pub exp_month: String, - pub nickname: Option, + pub nickname: Option, pub card_last_four: Option, pub card_token: Option, pub card_holder_name: Option, diff --git a/crates/router/src/core/payment_methods.rs b/crates/router/src/core/payment_methods.rs index 415051c3373..e3f0975375d 100644 --- a/crates/router/src/core/payment_methods.rs +++ b/crates/router/src/core/payment_methods.rs @@ -45,7 +45,7 @@ use hyperswitch_domain_models::payments::{payment_attempt::PaymentAttempt, Payme #[cfg(all(feature = "v2", feature = "payment_methods_v2"))] use masking::ExposeInterface; use masking::{PeekInterface, Secret}; -use router_env::{instrument, logger, tracing}; +use router_env::{instrument, tracing}; use time::Duration; use super::{ @@ -56,7 +56,7 @@ use super::{ use crate::{ configs::settings, core::{payment_methods::transformers as pm_transforms, utils as core_utils}, - headers, + headers, logger, routes::payment_methods as pm_routes, services::encryption, types::{ @@ -692,13 +692,15 @@ pub(crate) async fn get_payment_method_create_request( card_number: card.card_number.clone(), card_exp_month: card.card_exp_month.clone(), card_exp_year: card.card_exp_year.clone(), - card_holder_name: billing_name.and_then(|name| { - common_utils::types::NameType::try_from(name) - .map_err(|err| { - logger::error!("Invalid Card Holder Name: {}", err); + card_holder_name: billing_name + .map(|name| { + common_utils::types::NameType::try_from(name).map_err(|_| { + errors::ApiErrorResponse::InvalidDataValue { + field_name: "card_holder_name", + } }) - .ok() - }), + }) + .transpose()?, nick_name: card.nick_name.clone(), card_issuing_country: card .card_issuing_country @@ -776,13 +778,15 @@ pub(crate) async fn get_payment_method_create_request( card_number: card.card_number.clone(), card_exp_month: card.card_exp_month.clone(), card_exp_year: card.card_exp_year.clone(), - card_holder_name: billing_name.and_then(|name| { - common_utils::types::NameType::try_from(name) - .map_err(|err| { - logger::error!("Invalid Card Holder Name: {}", err); + card_holder_name: billing_name + .map(|name| { + common_utils::types::NameType::try_from(name).map_err(|_| { + errors::ApiErrorResponse::InvalidDataValue { + field_name: "card_holder_name", + } }) - .ok() - }), + }) + .transpose()?, nick_name: card.nick_name.clone(), card_issuing_country: card.card_issuing_country.clone(), card_network: card.card_network.clone(), diff --git a/crates/router/src/core/payment_methods/cards.rs b/crates/router/src/core/payment_methods/cards.rs index bc2b788a3a6..e9b14ad7371 100644 --- a/crates/router/src/core/payment_methods/cards.rs +++ b/crates/router/src/core/payment_methods/cards.rs @@ -3041,14 +3041,22 @@ pub async fn mock_get_card<'a>( .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.and_then(|card| { - card.try_into() - .map_err(|_| { - router_env::logger::error!("Failed to convert name to NameType"); - }) - .ok() - }), - nickname: locker_mock_up.nickname, + name_on_card: locker_mock_up + .name_on_card + .map(|card| { + common_utils::types::NameType::try_from(card) + .change_context(errors::VaultError::ResponseDeserializationFailed) + .attach_printable("Invalid card holder name format from the mock locker") + }) + .transpose()?, + nickname: locker_mock_up + .nickname + .map(|card| { + common_utils::types::NameType::try_from(card) + .change_context(errors::VaultError::ResponseDeserializationFailed) + .attach_printable("Invalid nick name format from the mock locker") + }) + .transpose()?, customer_id: locker_mock_up.customer_id, duplicate: locker_mock_up.duplicate, }; @@ -5717,16 +5725,12 @@ impl TempLockerCardSupport { .clone() .expose_option() .get_required_value("expiry_year")?; - let card_holder_name = card - .card_holder_name - .clone() - .map(|name| name.peek().to_string()) - .unwrap_or_default(); + let card_holder_name = card.card_holder_name.clone(); let value1 = payment_methods::mk_card_value1( card_number, card_exp_year, card_exp_month, - Some(card_holder_name), + card_holder_name, None, None, None, diff --git a/crates/router/src/core/payment_methods/transformers.rs b/crates/router/src/core/payment_methods/transformers.rs index 5b7298dc267..863c0476a06 100644 --- a/crates/router/src/core/payment_methods/transformers.rs +++ b/crates/router/src/core/payment_methods/transformers.rs @@ -145,7 +145,7 @@ pub struct AddCardResponse { pub card_exp_year: Option>, pub card_exp_month: Option>, pub name_on_card: Option, - pub nickname: Option, + pub nickname: Option, pub customer_id: Option, pub duplicate: Option, } @@ -662,13 +662,7 @@ pub fn mk_get_card_response(card: GetCardResponse) -> errors::RouterResult .get_required_value("card_exp_year")?, card_brand: None, card_isin: None, - nick_name: card.card.nickname.and_then(|name| { - common_utils::types::NameType::try_from(name) - .map_err(|err| { - router_env::logger::error!("Invalid Nick Name: {}", err); - }) - .ok() - }), + nick_name: card.card.nickname, }) } @@ -878,8 +872,8 @@ pub fn mk_card_value1( card_number: cards::CardNumber, exp_year: String, exp_month: String, - name_on_card: Option, - nickname: Option, + name_on_card: Option, + nickname: Option, card_last_four: Option, card_token: Option, ) -> CustomResult { diff --git a/crates/router/src/core/payment_methods/vault.rs b/crates/router/src/core/payment_methods/vault.rs index 88db241c31e..16edfffb5d1 100644 --- a/crates/router/src/core/payment_methods/vault.rs +++ b/crates/router/src/core/payment_methods/vault.rs @@ -63,7 +63,7 @@ impl Vaultable for domain::Card { card_number: self.card_number.peek().clone(), exp_year: self.card_exp_year.peek().clone(), exp_month: self.card_exp_month.peek().clone(), - nickname: self.nick_name.as_ref().map(|name| name.peek().to_string()), + nickname: self.nick_name.clone(), card_last_four: None, card_token: None, card_holder_name: self.card_holder_name.clone(), @@ -119,13 +119,7 @@ impl Vaultable for domain::Card { bank_code: None, card_issuing_country: None, card_type: None, - nick_name: value1.nickname.and_then(|name| { - common_utils::types::NameType::try_from(name) - .map_err(|err| { - router_env::logger::error!("Invalid Nick Name: {}", err); - }) - .ok() - }), + nick_name: value1.nickname, card_holder_name: value1.card_holder_name, }; @@ -469,7 +463,7 @@ impl Vaultable for api::CardPayout { card_number: self.card_number.peek().clone(), exp_year: self.expiry_year.peek().clone(), exp_month: self.expiry_month.peek().clone(), - name_on_card: self.card_holder_name.clone().map(|n| n.peek().to_string()), + name_on_card: self.card_holder_name.clone(), nickname: None, card_last_four: None, card_token: None, @@ -520,13 +514,7 @@ impl Vaultable for api::CardPayout { .map_err(|_| errors::VaultError::FetchCardFailed)?, expiry_month: value1.exp_month.into(), expiry_year: value1.exp_year.into(), - card_holder_name: value1.name_on_card.and_then(|name| { - common_utils::types::NameType::try_from(name) - .map_err(|err| { - router_env::logger::error!("Invalid Nick Name: {}", err); - }) - .ok() - }), + card_holder_name: value1.name_on_card, }; let supp_data = SupplementaryVaultData { From dc70eca5f961ede39544fa10a001602ba35ef6de Mon Sep 17 00:00:00 2001 From: Sk Sakil Mostak Date: Wed, 5 Feb 2025 17:46:28 +0530 Subject: [PATCH 17/19] refactor: resolve comments --- crates/common_utils/src/types.rs | 9 ++++ crates/hyperswitch_connectors/src/utils.rs | 2 + crates/router/src/core/utils.rs | 16 +------- crates/router/src/types/transformers.rs | 48 +++------------------- 4 files changed, 19 insertions(+), 56 deletions(-) diff --git a/crates/common_utils/src/types.rs b/crates/common_utils/src/types.rs index ca2ae731f2c..ff6404ef632 100644 --- a/crates/common_utils/src/types.rs +++ b/crates/common_utils/src/types.rs @@ -1426,6 +1426,15 @@ impl TryFrom> for NameType { } } +impl NameType { + /// This function is used to create NameType from a string without any validation + pub fn get_unchecked(card_holder_name: String) -> Self { + Self(masking::Secret::new(LengthString::<256, 0>::new_unchecked( + card_holder_name, + ))) + } +} + impl FromStr for NameType { type Err = error_stack::Report; diff --git a/crates/hyperswitch_connectors/src/utils.rs b/crates/hyperswitch_connectors/src/utils.rs index 9c61e912666..00dfab6e127 100644 --- a/crates/hyperswitch_connectors/src/utils.rs +++ b/crates/hyperswitch_connectors/src/utils.rs @@ -1130,6 +1130,7 @@ impl CardData for CardDetailsForNetworkTransactionId { fn get_cardholder_name(&self) -> Result, Error> { self.card_holder_name .clone() + .map(From::from) .ok_or_else(missing_field_err("card.card_holder_name")) } } @@ -2791,6 +2792,7 @@ impl CardData for api_models::payouts::CardPayout { fn get_cardholder_name(&self) -> Result, Error> { self.card_holder_name .clone() + .map(From::from) .ok_or_else(missing_field_err("card.card_holder_name")) } } diff --git a/crates/router/src/core/utils.rs b/crates/router/src/core/utils.rs index aaa9953824c..8de7ce254c8 100644 --- a/crates/router/src/core/utils.rs +++ b/crates/router/src/core/utils.rs @@ -97,24 +97,12 @@ pub async fn construct_payout_router_data<'a, F>( .first_name .clone() .map(Encryptable::into_inner) - .and_then(|name| { - NameType::try_from(name.expose()) - .map_err(|err| { - router_env::logger::error!("Invalid First Name: {}", err); - }) - .ok() - }); + .map(|name| NameType::get_unchecked(name.expose())); let last_name = a .last_name .clone() .map(Encryptable::into_inner) - .and_then(|name| { - NameType::try_from(name.expose()) - .map_err(|err| { - router_env::logger::error!("Invalid Last Name: {}", err); - }) - .ok() - }); + .map(|name| NameType::get_unchecked(name.expose())); let address_details = api_models::payments::AddressDetails { city: a.city.to_owned(), country: a.country.to_owned(), diff --git a/crates/router/src/types/transformers.rs b/crates/router/src/types/transformers.rs index 96fe91413eb..c5fde73d7cd 100644 --- a/crates/router/src/types/transformers.rs +++ b/crates/router/src/types/transformers.rs @@ -752,24 +752,12 @@ impl From<&domain::Address> for hyperswitch_domain_models::address::Address { .first_name .clone() .map(Encryptable::into_inner) - .and_then(|name| { - common_utils::types::NameType::try_from(name.expose()) - .map_err(|err| { - router_env::logger::error!("Invalid First Name: {}", err); - }) - .ok() - }); + .map(|name| common_utils::types::NameType::get_unchecked(name.expose())); let last_name = address .last_name .clone() .map(Encryptable::into_inner) - .and_then(|name| { - common_utils::types::NameType::try_from(name.expose()) - .map_err(|err| { - router_env::logger::error!("Invalid Last Name {}", err); - }) - .ok() - }); + .map(|name| common_utils::types::NameType::get_unchecked(name.expose())); Some(hyperswitch_domain_models::address::AddressDetails { city: address.city.clone(), country: address.country, @@ -820,24 +808,12 @@ impl ForeignFrom for api_types::Address { .first_name .clone() .map(Encryptable::into_inner) - .and_then(|name| { - common_utils::types::NameType::try_from(name.expose()) - .map_err(|err| { - router_env::logger::error!("Invalid First Name: {}", err); - }) - .ok() - }); + .map(|name| common_utils::types::NameType::get_unchecked(name.expose())); let last_name = address .last_name .clone() .map(Encryptable::into_inner) - .and_then(|name| { - common_utils::types::NameType::try_from(name.expose()) - .map_err(|err| { - router_env::logger::error!("Invalid Last Name {}", err); - }) - .ok() - }); + .map(|name| common_utils::types::NameType::get_unchecked(name.expose())); Some(api_types::AddressDetails { city: address.city.clone(), country: address.country, @@ -1800,24 +1776,12 @@ impl From for payments::AddressDetails { .first_name .clone() .map(Encryptable::into_inner) - .and_then(|name| { - common_utils::types::NameType::try_from(name.expose()) - .map_err(|err| { - router_env::logger::error!("Invalid First Name: {}", err); - }) - .ok() - }); + .map(|name| common_utils::types::NameType::get_unchecked(name.expose())); let last_name = addr .last_name .clone() .map(Encryptable::into_inner) - .and_then(|name| { - common_utils::types::NameType::try_from(name.expose()) - .map_err(|err| { - router_env::logger::error!("Invalid Last Name {}", err); - }) - .ok() - }); + .map(|name| common_utils::types::NameType::get_unchecked(name.expose())); Self { city: addr.city, country: addr.country, From f04391ac2e720ff3d6ab0ac796fc820bb58960ef Mon Sep 17 00:00:00 2001 From: Sk Sakil Mostak Date: Fri, 7 Feb 2025 02:05:23 +0530 Subject: [PATCH 18/19] refactor: resolve conflict with main --- crates/hyperswitch_connectors/src/utils.rs | 4 ++-- crates/router/src/core/unified_authentication_service.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/hyperswitch_connectors/src/utils.rs b/crates/hyperswitch_connectors/src/utils.rs index cf852507490..799828dc130 100644 --- a/crates/hyperswitch_connectors/src/utils.rs +++ b/crates/hyperswitch_connectors/src/utils.rs @@ -1302,11 +1302,11 @@ impl AddressDetailsData for AddressDetails { } fn get_optional_first_name(&self) -> Option> { - self.first_name.clone() + self.first_name.clone().map(From::from) } fn get_optional_last_name(&self) -> Option> { - self.last_name.clone() + self.last_name.clone().map(From::from) } } diff --git a/crates/router/src/core/unified_authentication_service.rs b/crates/router/src/core/unified_authentication_service.rs index 28d32f627cb..151ba234885 100644 --- a/crates/router/src/core/unified_authentication_service.rs +++ b/crates/router/src/core/unified_authentication_service.rs @@ -181,7 +181,7 @@ impl UnifiedAuthenticationService for ExternalAuthentication payment_data_type: None, encrypted_src_card_details: None, card_expiry_date: card.card_exp_year.clone(), - cardholder_name: card.card_holder_name.clone(), + cardholder_name: card.card_holder_name.clone().map(From::from), card_token_number: card.card_cvc.clone(), account_type: card.card_network.clone(), }) From e5653114c2d7f02d62159bf5b7d3a38f9de93f51 Mon Sep 17 00:00:00 2001 From: Sk Sakil Mostak Date: Fri, 21 Feb 2025 14:50:34 +0530 Subject: [PATCH 19/19] refactor: resolve conflct with main --- crates/common_utils/src/types.rs | 2 +- crates/hyperswitch_domain_models/src/payment_method_data.rs | 4 ++-- crates/router/src/connector/netcetera/netcetera_types.rs | 1 - .../router/src/core/payment_methods/network_tokenization.rs | 4 ++-- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/crates/common_utils/src/types.rs b/crates/common_utils/src/types.rs index aeb8608a04a..4b83b7f96e9 100644 --- a/crates/common_utils/src/types.rs +++ b/crates/common_utils/src/types.rs @@ -29,11 +29,11 @@ use diesel::{ AsExpression, FromSqlRow, Queryable, }; use error_stack::{report, ResultExt}; +use masking::{ExposeInterface, PeekInterface}; pub use primitive_wrappers::bool_wrappers::{ AlwaysRequestExtendedAuthorization, ExtendedAuthorizationAppliedBool, RequestExtendedAuthorizationBool, }; -use masking::{ExposeInterface, PeekInterface}; use rust_decimal::{ prelude::{FromPrimitive, ToPrimitive}, Decimal, diff --git a/crates/hyperswitch_domain_models/src/payment_method_data.rs b/crates/hyperswitch_domain_models/src/payment_method_data.rs index 7592141b065..eb518c4e02f 100644 --- a/crates/hyperswitch_domain_models/src/payment_method_data.rs +++ b/crates/hyperswitch_domain_models/src/payment_method_data.rs @@ -1815,8 +1815,8 @@ impl From for CardDetailsPaymentMethod { last4_digits: Some(item.card_number.get_last4()), expiry_month: Some(item.card_exp_month), expiry_year: Some(item.card_exp_year), - card_holder_name: item.card_holder_name, - nick_name: item.nick_name, + card_holder_name: item.card_holder_name.map(From::from), + nick_name: item.nick_name.map(From::from), card_isin: None, card_issuer: item.card_issuer, card_network: item.card_network, diff --git a/crates/router/src/connector/netcetera/netcetera_types.rs b/crates/router/src/connector/netcetera/netcetera_types.rs index 62a5a1fdc13..663c72c8ac9 100644 --- a/crates/router/src/connector/netcetera/netcetera_types.rs +++ b/crates/router/src/connector/netcetera/netcetera_types.rs @@ -2,7 +2,6 @@ use std::collections::HashMap; use common_utils::pii::Email; use hyperswitch_connectors::utils::AddressDetailsData; -use masking::ExposeInterface; use serde::{Deserialize, Serialize}; use crate::{connector::utils::PhoneDetailsData, errors, types::api::MessageCategory}; diff --git a/crates/router/src/core/payment_methods/network_tokenization.rs b/crates/router/src/core/payment_methods/network_tokenization.rs index 6799a1cf5ba..85c46718a7d 100644 --- a/crates/router/src/core/payment_methods/network_tokenization.rs +++ b/crates/router/src/core/payment_methods/network_tokenization.rs @@ -363,8 +363,8 @@ pub async fn make_card_network_tokenization_request( card_network: Some(resp.card_brand), card_type: card.card_type.clone(), card_issuing_country: card.card_issuing_country, - card_holder_name: card.card_holder_name.clone(), - nick_name: card.nick_name.clone(), + card_holder_name: card.card_holder_name.clone().map(From::from), + nick_name: card.nick_name.clone().map(From::from), }; Ok((network_token_details, network_token_req_ref_id)) }