From ae0071e2082906b4609e002717512af38a5f4919 Mon Sep 17 00:00:00 2001 From: Shankar Singh C Date: Tue, 29 Apr 2025 12:43:08 +0530 Subject: [PATCH 1/2] feat(router): add debit routing support for saved card flow --- crates/api_models/src/open_router.rs | 29 ++- crates/api_models/src/payment_methods.rs | 17 +- .../src/payment_method_data.rs | 45 +++- .../src/payment_methods.rs | 30 ++- crates/router/src/core/debit_routing.rs | 229 +++++++++++++++--- .../router/src/core/payment_methods/cards.rs | 13 +- .../src/core/payment_methods/tokenize.rs | 2 + .../payment_methods/tokenize/card_executor.rs | 1 + .../tokenize/payment_method_executor.rs | 1 + .../router/src/core/payment_methods/vault.rs | 1 + crates/router/src/core/payments.rs | 73 +++++- crates/router/src/core/payments/helpers.rs | 12 +- .../router/src/core/payments/tokenization.rs | 17 +- crates/router/src/core/payouts/helpers.rs | 2 + crates/router/src/utils/verify_connector.rs | 1 + crates/router/tests/connectors/aci.rs | 2 + crates/router/tests/connectors/adyen.rs | 1 + crates/router/tests/connectors/airwallex.rs | 1 + crates/router/tests/connectors/fiserv.rs | 1 + crates/router/tests/connectors/rapyd.rs | 2 + crates/router/tests/connectors/utils.rs | 1 + crates/router/tests/connectors/worldline.rs | 1 + 22 files changed, 413 insertions(+), 69 deletions(-) diff --git a/crates/api_models/src/open_router.rs b/crates/api_models/src/open_router.rs index a3dd0b00f2b..3ff8ef06da3 100644 --- a/crates/api_models/src/open_router.rs +++ b/crates/api_models/src/open_router.rs @@ -1,5 +1,7 @@ use std::{collections::HashMap, fmt::Debug}; +use crate::enums::{Currency, PaymentMethod, RoutableConnectors}; +use crate::payment_methods; use common_utils::{id_type, types::MinorUnit}; pub use euclid::{ dssa::types::EuclidAnalysable, @@ -10,8 +12,6 @@ pub use euclid::{ }; use serde::{Deserialize, Serialize}; -use crate::enums::{Currency, PaymentMethod, RoutableConnectors}; - #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct OpenRouterDecideGatewayRequest { @@ -49,7 +49,6 @@ pub struct PaymentInfo { // paymentSource: Option, // authType: Option, // cardIssuerBankName: Option, - pub card_isin: Option, // cardType: Option, // cardSwitchProvider: Option>, @@ -70,6 +69,30 @@ pub struct DebitRoutingOutput { pub card_type: common_enums::CardType, } +impl From<&DebitRoutingOutput> for payment_methods::CoBadgedCardData { + fn from(output: &DebitRoutingOutput) -> Self { + payment_methods::CoBadgedCardData { + co_badged_card_networks: output.co_badged_card_networks.clone(), + issuer_country: output.issuer_country.clone(), + is_regulated: output.is_regulated.clone(), + regulated_name: output.regulated_name.clone(), + card_type: output.card_type.clone(), + } + } +} + +impl From for DebitRoutingRequestData { + fn from(output: payment_methods::CoBadgedCardData) -> Self { + DebitRoutingRequestData { + co_badged_card_networks: output.co_badged_card_networks.clone(), + issuer_country: output.issuer_country.clone(), + is_regulated: output.is_regulated.clone(), + regulated_name: output.regulated_name.clone(), + card_type: output.card_type.clone(), + } + } +} + #[derive(Debug, Clone, Serialize, Deserialize)] pub struct CoBadgedCardRequest { pub merchant_category_code: common_enums::MerchantCategoryCode, diff --git a/crates/api_models/src/payment_methods.rs b/crates/api_models/src/payment_methods.rs index 4313d224019..dbc2ac600be 100644 --- a/crates/api_models/src/payment_methods.rs +++ b/crates/api_models/src/payment_methods.rs @@ -987,6 +987,16 @@ pub struct CardDetailsPaymentMethod { pub card_type: Option, #[serde(default = "saved_in_locker_default")] pub saved_to_locker: bool, + pub co_badged_card_data: Option, +} + +#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] +pub struct CoBadgedCardData { + pub co_badged_card_networks: Vec, + pub issuer_country: common_enums::CountryAlpha2, + pub is_regulated: bool, + pub regulated_name: Option, + pub card_type: common_enums::CardType, } #[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, ToSchema)] @@ -1322,8 +1332,10 @@ impl From for CardDetailsPaymentMethod { any(feature = "v1", feature = "v2"), not(feature = "payment_methods_v2") ))] -impl From for CardDetailsPaymentMethod { - fn from(item: CardDetailFromLocker) -> Self { +impl From<(CardDetailFromLocker, Option<&CoBadgedCardData>)> for CardDetailsPaymentMethod { + fn from( + (item, co_badged_card_data): (CardDetailFromLocker, Option<&CoBadgedCardData>), + ) -> Self { Self { issuer_country: item.issuer_country, last4_digits: item.last4_digits, @@ -1336,6 +1348,7 @@ impl From for CardDetailsPaymentMethod { card_network: item.card_network, card_type: item.card_type, saved_to_locker: item.saved_to_locker, + co_badged_card_data: co_badged_card_data.cloned(), } } } diff --git a/crates/hyperswitch_domain_models/src/payment_method_data.rs b/crates/hyperswitch_domain_models/src/payment_method_data.rs index 2d386d0f002..6e4d102bb1b 100644 --- a/crates/hyperswitch_domain_models/src/payment_method_data.rs +++ b/crates/hyperswitch_domain_models/src/payment_method_data.rs @@ -77,6 +77,14 @@ impl PaymentMethodData { pub fn is_network_token_payment_method_data(&self) -> bool { matches!(self, Self::NetworkToken(_)) } + + pub fn get_co_badged_card_data(&self) -> Option<&payment_methods::CoBadgedCardData> { + if let PaymentMethodData::Card(card) = self { + card.co_badged_card_data.as_ref() + } else { + None + } + } } #[derive(Eq, PartialEq, Clone, Debug, Serialize, Deserialize, Default)] @@ -87,11 +95,13 @@ pub struct Card { pub card_cvc: Secret, pub card_issuer: Option, pub card_network: Option, + // we use this as the card type for co-badged cards as well pub card_type: Option, pub card_issuing_country: Option, pub bank_code: Option, pub nick_name: Option>, pub card_holder_name: Option>, + pub co_badged_card_data: Option, } #[derive(Eq, PartialEq, Clone, Debug, Serialize, Deserialize, Default)] @@ -120,6 +130,7 @@ pub struct CardDetail { pub bank_code: Option, pub nick_name: Option>, pub card_holder_name: Option>, + pub co_badged_card_data: Option, } impl CardDetailsForNetworkTransactionId { @@ -162,6 +173,7 @@ impl From<&Card> for CardDetail { bank_code: item.bank_code.to_owned(), nick_name: item.nick_name.to_owned(), card_holder_name: item.card_holder_name.to_owned(), + co_badged_card_data: item.co_badged_card_data.to_owned(), } } } @@ -732,7 +744,7 @@ impl From for PaymentMethodData { fn from(api_model_payment_method_data: api_models::payments::PaymentMethodData) -> Self { match api_model_payment_method_data { api_models::payments::PaymentMethodData::Card(card_data) => { - Self::Card(Card::from(card_data)) + Self::Card(Card::from((card_data, None))) } api_models::payments::PaymentMethodData::CardRedirect(card_redirect) => { Self::CardRedirect(From::from(card_redirect)) @@ -782,8 +794,21 @@ impl From for PaymentMethodData { } } -impl From for Card { - fn from(value: api_models::payments::Card) -> Self { +impl + From<( + api_models::payments::Card, + Option, + )> for Card +{ + fn from( + (value, co_badged_card_data): ( + api_models::payments::Card, + Option, + ), + ) -> Self { + let a = co_badged_card_data + .clone() + .map(|x| x.co_badged_card_networks[0].clone()); let api_models::payments::Card { card_number, card_exp_month, @@ -804,12 +829,13 @@ impl From for Card { card_exp_year, card_cvc, card_issuer, - card_network, + card_network: a.or(card_network), card_type, card_issuing_country, bank_code, nick_name, card_holder_name, + co_badged_card_data, } } } @@ -1875,6 +1901,16 @@ pub enum PaymentMethodsData { NetworkToken(NetworkTokenDetailsPaymentMethod), } +impl PaymentMethodsData { + pub fn get_co_badged_card_data(&self) -> Option { + if let PaymentMethodsData::Card(card) = self { + card.co_badged_card_data.clone() + } else { + None + } + } +} + #[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] pub struct NetworkTokenDetailsPaymentMethod { pub last4_digits: Option, @@ -1909,6 +1945,7 @@ pub struct CardDetailsPaymentMethod { pub card_type: Option, #[serde(default = "saved_in_locker_default")] pub saved_to_locker: bool, + pub co_badged_card_data: Option, } #[cfg(all(feature = "v2", feature = "payment_methods_v2"))] diff --git a/crates/hyperswitch_domain_models/src/payment_methods.rs b/crates/hyperswitch_domain_models/src/payment_methods.rs index 955d01c94df..aa2f6223bdc 100644 --- a/crates/hyperswitch_domain_models/src/payment_methods.rs +++ b/crates/hyperswitch_domain_models/src/payment_methods.rs @@ -1,5 +1,11 @@ #[cfg(feature = "v2")] use api_models::payment_methods::PaymentMethodsData; + +use crate::payment_method_data as domain_payment_method_data; +#[cfg(feature = "v1")] +use masking::ExposeInterface; +#[cfg(feature = "v1")] +use router_env::logger; // specific imports because of using the macro use common_enums::enums::MerchantStorageScheme; #[cfg(all(feature = "v2", feature = "payment_methods_v2"))] @@ -20,10 +26,7 @@ use serde_json::Value; use time::PrimitiveDateTime; #[cfg(all(feature = "v2", feature = "payment_methods_v2"))] -use crate::{ - address::Address, payment_method_data as domain_payment_method_data, - type_encryption::OptionalEncryptableJsonType, -}; +use crate::{address::Address, type_encryption::OptionalEncryptableJsonType}; use crate::{ mandates::{self, CommonMandateReference}, merchant_key_store::MerchantKeyStore, @@ -131,6 +134,25 @@ impl PaymentMethod { &self.payment_method_id } + #[cfg(feature = "v1")] + pub fn get_payment_methods_data( + &self, + ) -> Option { + self.payment_method_data + .clone() + .map(|value| value.into_inner().expose()) + .and_then(|value| { + serde_json::from_value::(value) + .map_err(|error| { + logger::warn!( + ?error, + "Failed to parse payment method data in payment method info" + ); + }) + .ok() + }) + } + #[cfg(all(feature = "v2", feature = "payment_methods_v2"))] pub fn get_id(&self) -> &id_type::GlobalPaymentMethodId { &self.id diff --git a/crates/router/src/core/debit_routing.rs b/crates/router/src/core/debit_routing.rs index 55dae362e06..a8d2945a08a 100644 --- a/crates/router/src/core/debit_routing.rs +++ b/crates/router/src/core/debit_routing.rs @@ -1,4 +1,4 @@ -use api_models::enums as api_enums; +use api_models::{enums as api_enums, payment_methods}; use common_enums::enums; use masking::Secret; @@ -26,7 +26,7 @@ pub async fn perform_debit_routing( operation: &BoxedOperation<'_, F, Req, D>, state: &SessionState, business_profile: &domain::Profile, - payment_data: &D, + payment_data: &mut D, connector: Option, ) -> (Option, bool) where @@ -208,7 +208,7 @@ async fn handle_pre_determined_connector( debit_routing_config: &settings::DebitRoutingConfig, debit_routing_supported_connectors: HashSet, connector_data: &api::ConnectorRoutingData, - payment_data: &D, + payment_data: &mut D, acquirer_country: enums::CountryAlpha2, ) -> Option where @@ -243,9 +243,120 @@ where None } -pub async fn get_sorted_co_badged_networks_by_fee>( +// pub async fn get_sorted_co_badged_networks_by_fee< +// F: Clone, +// D: OperationSessionGetters + OperationSessionSetters, +// >( +// state: &SessionState, +// payment_data: &mut D, +// acquirer_country: enums::CountryAlpha2, +// ) -> Option> { +// logger::debug!("Fetching sorted card networks based on their respective network fees"); + +// let payment_method_data_optional = payment_data.get_payment_method_data(); +// let payment_attempt = payment_data.get_payment_attempt(); + +// let debit_routing_output_optional = if let Some( +// hyperswitch_domain_models::payment_method_data::PaymentMethodsData::Card(card), +// ) = payment_data +// .get_payment_method_info() +// .and_then(|payment_method_info| payment_method_info.get_payment_methods_data()) +// { +// if let Some(saved_co_badged_card_data) = &card.co_badged_card_data { +// logger::debug!("Co-badged card data is present in the saved payment method"); +// let co_badged_card_request = api_models::open_router::CoBadgedCardRequest { +// merchant_category_code: enums::MerchantCategoryCode::Mcc0001, +// acquirer_country, +// co_badged_card_data: Some(api_models::open_router::DebitRoutingRequestData::from( +// saved_co_badged_card_data, +// )), +// }; + +// let debit_routing_output_optional = routing::perform_open_routing_for_debit_routing( +// state, +// payment_attempt, +// co_badged_card_request, +// None, +// ) +// .await +// .map_err(|error| { +// logger::warn!(?error, "Failed to calculate total fees per network"); +// }) +// .ok(); +// debit_routing_output_optional +// } else if let Some(saved_card_isin) = &card.card_isin { +// logger::debug!("Co-badged card data is not present; proceeding with the flow using the saved card BIN."); +// let co_badged_card_request = api_models::open_router::CoBadgedCardRequest { +// merchant_category_code: enums::MerchantCategoryCode::Mcc0001, +// acquirer_country, +// co_badged_card_data: None, +// }; + +// let debit_routing_output_optional = routing::perform_open_routing_for_debit_routing( +// state, +// payment_attempt, +// co_badged_card_request, +// Some(Secret::new(saved_card_isin.clone())), +// ) +// .await +// .map_err(|error| { +// logger::warn!(?error, "Failed to calculate total fees per network"); +// }) +// .ok(); +// debit_routing_output_optional +// } else { +// None +// } +// } else if let Some(hyperswitch_domain_models::payment_method_data::PaymentMethodData::Card( +// card, +// )) = payment_method_data_optional +// { +// logger::debug!( +// "Co-badged card data is not present; proceeding with card data form the request." +// ); +// let co_badged_card_request = api_models::open_router::CoBadgedCardRequest { +// merchant_category_code: enums::MerchantCategoryCode::Mcc0001, +// acquirer_country, +// co_badged_card_data: None, +// }; + +// // perform_open_routing_for_debit_routing +// let debit_routing_output_optional = routing::perform_open_routing_for_debit_routing( +// state, +// payment_attempt, +// co_badged_card_request, +// Some(Secret::new(card.card_number.get_card_isin())), +// ) +// .await +// .map_err(|error| { +// logger::warn!(?error, "Failed to calculate total fees per network"); +// }) +// .ok(); +// debit_routing_output_optional +// } else { +// None +// }; + +// debit_routing_output_optional +// .as_ref() +// .map(|debit_routing_output| { +// payment_data.set_co_badged_card_data(payment_methods::CoBadgedCardData::from( +// debit_routing_output, +// )) +// }); + +// let co_badged_card_networks = +// debit_routing_output_optional.map(|data| data.co_badged_card_networks); + +// co_badged_card_networks +// } + +pub async fn get_sorted_co_badged_networks_by_fee< + F: Clone, + D: OperationSessionGetters + OperationSessionSetters, +>( state: &SessionState, - payment_data: &D, + payment_data: &mut D, acquirer_country: enums::CountryAlpha2, ) -> Option> { logger::debug!("Fetching sorted card networks based on their respective network fees"); @@ -253,35 +364,89 @@ pub async fn get_sorted_co_badged_networks_by_fee None, + _ => { + let co_badged_card_request = api_models::open_router::CoBadgedCardRequest { + merchant_category_code: enums::MerchantCategoryCode::Mcc0001, + acquirer_country, + co_badged_card_data: saved_co_badged_card_data + .map(api_models::open_router::DebitRoutingRequestData::from), + }; + + routing::perform_open_routing_for_debit_routing( + state, + payment_attempt, + co_badged_card_request, + card_isin, + ) + .await + .map_err(|error| { + logger::warn!(?error, "Failed to calculate total fees per network"); + }) + .ok() + } + }; - return debit_routing_output_optional; - } - None + // let co_badged_card_request = api_models::open_router::CoBadgedCardRequest { + // merchant_category_code: enums::MerchantCategoryCode::Mcc0001, + // acquirer_country, + // co_badged_card_data: saved_co_badged_card_data + // .map(api_models::open_router::DebitRoutingRequestData::from), + // }; + + // let debit_routing_output_optional = routing::perform_open_routing_for_debit_routing( + // state, + // payment_attempt, + // co_badged_card_request, + // card_isin, + // ) + // .await + // .map_err(|error| { + // logger::warn!(?error, "Failed to calculate total fees per network"); + // }) + // .ok(); + + debit_routing_output_optional + .as_ref() + .map(|debit_routing_output| { + payment_data.set_co_badged_card_data(payment_methods::CoBadgedCardData::from( + debit_routing_output, + )) + }); + + let co_badged_card_networks = + debit_routing_output_optional.map(|data| data.co_badged_card_networks); + + co_badged_card_networks } async fn handle_retryable_connector( @@ -289,7 +454,7 @@ async fn handle_retryable_connector( debit_routing_config: &settings::DebitRoutingConfig, debit_routing_supported_connectors: HashSet, connector_data_list: Vec, - payment_data: &D, + payment_data: &mut D, acquirer_country: enums::CountryAlpha2, ) -> Option where diff --git a/crates/router/src/core/payment_methods/cards.rs b/crates/router/src/core/payment_methods/cards.rs index e9fefffbb07..e340e4b815d 100644 --- a/crates/router/src/core/payment_methods/cards.rs +++ b/crates/router/src/core/payment_methods/cards.rs @@ -776,7 +776,7 @@ pub async fn skip_locker_call_and_migrate_payment_method( .to_not_found_response(errors::ApiErrorResponse::CustomerNotFound)?; let payment_method_card_details = - PaymentMethodsData::Card(CardDetailsPaymentMethod::from(card.clone())); + PaymentMethodsData::Card(CardDetailsPaymentMethod::from((card.clone(), None))); let payment_method_data_encrypted: Option>> = Some( create_encrypted_data(key_manager_state, key_store, payment_method_card_details) @@ -934,7 +934,7 @@ pub async fn save_network_token_and_update_payment_method( let pm_token_details = token_pm_resp .card .as_ref() - .map(|card| PaymentMethodsData::Card(CardDetailsPaymentMethod::from(card.clone()))); + .map(|card| PaymentMethodsData::Card(CardDetailsPaymentMethod::from((card.clone(), None)))); let pm_network_token_data_encrypted = pm_token_details .async_map(|pm_card| create_encrypted_data(key_manager_state, key_store, pm_card)) .await @@ -1369,6 +1369,7 @@ pub async fn add_payment_method_data( card_issuer: card_info.as_ref().and_then(|ci| ci.card_issuer.clone()), card_type: card_info.as_ref().and_then(|ci| ci.card_type.clone()), saved_to_locker: true, + co_badged_card_data: None, }; let pm_data_encrypted: Encryptable> = create_encrypted_data( @@ -1636,7 +1637,7 @@ pub async fn add_payment_method( }); let updated_pmd = updated_card.as_ref().map(|card| { - PaymentMethodsData::Card(CardDetailsPaymentMethod::from(card.clone())) + PaymentMethodsData::Card(CardDetailsPaymentMethod::from((card.clone(), None))) }); let pm_data_encrypted: Option>> = updated_pmd @@ -1898,7 +1899,7 @@ pub async fn save_migration_payment_method( }); let updated_pmd = updated_card.as_ref().map(|card| { - PaymentMethodsData::Card(CardDetailsPaymentMethod::from(card.clone())) + PaymentMethodsData::Card(CardDetailsPaymentMethod::from((card.clone(), None))) }); let pm_data_encrypted: Option>> = updated_pmd @@ -2007,7 +2008,7 @@ pub async fn insert_payment_method( let pm_card_details = resp .card .clone() - .map(|card| PaymentMethodsData::Card(CardDetailsPaymentMethod::from(card.clone()))); + .map(|card| PaymentMethodsData::Card(CardDetailsPaymentMethod::from((card.clone(), None)))); let key_manager_state = state.into(); let pm_data_encrypted: crypto::OptionalEncryptableValue = pm_card_details .clone() @@ -2233,7 +2234,7 @@ pub async fn update_customer_payment_method( let updated_pmd = updated_card .as_ref() - .map(|card| PaymentMethodsData::Card(CardDetailsPaymentMethod::from(card.clone()))); + .map(|card| PaymentMethodsData::Card(CardDetailsPaymentMethod::from((card.clone(), None)))); let key_manager_state = (&state).into(); let pm_data_encrypted: Option>> = updated_pmd .async_map(|updated_pmd| { diff --git a/crates/router/src/core/payment_methods/tokenize.rs b/crates/router/src/core/payment_methods/tokenize.rs index bd0a5a2192b..c2dec2cebe2 100644 --- a/crates/router/src/core/payment_methods/tokenize.rs +++ b/crates/router/src/core/payment_methods/tokenize.rs @@ -277,6 +277,7 @@ where card_network: card_details.card_network.clone(), card_type: card_details.card_type.clone(), saved_to_locker, + co_badged_card_data: card_details.co_badged_card_data.clone(), }); create_encrypted_data(&self.state.into(), self.key_store, pm_data) .await @@ -302,6 +303,7 @@ where card_network: card_details.card_network.clone(), card_type: card_details.card_type.clone(), saved_to_locker, + co_badged_card_data: None, }); create_encrypted_data(&self.state.into(), self.key_store, token_data) .await diff --git a/crates/router/src/core/payment_methods/tokenize/card_executor.rs b/crates/router/src/core/payment_methods/tokenize/card_executor.rs index eb9d3d6b6c6..e04e688933d 100644 --- a/crates/router/src/core/payment_methods/tokenize/card_executor.rs +++ b/crates/router/src/core/payment_methods/tokenize/card_executor.rs @@ -131,6 +131,7 @@ impl<'a> NetworkTokenizationBuilder<'a, CardRequestValidated> { .map_or(card_req.card_issuing_country.clone(), |card_info| { card_info.card_issuing_country.clone() }), + co_badged_card_data: None, }; NetworkTokenizationBuilder { state: std::marker::PhantomData, diff --git a/crates/router/src/core/payment_methods/tokenize/payment_method_executor.rs b/crates/router/src/core/payment_methods/tokenize/payment_method_executor.rs index 2249434b107..a55896b36c5 100644 --- a/crates/router/src/core/payment_methods/tokenize/payment_method_executor.rs +++ b/crates/router/src/core/payment_methods/tokenize/payment_method_executor.rs @@ -151,6 +151,7 @@ impl<'a> NetworkTokenizationBuilder<'a, PmValidated> { card_issuing_country: optional_card_info .as_ref() .and_then(|card_info| card_info.card_issuing_country.clone()), + co_badged_card_data: None, }; NetworkTokenizationBuilder { state: std::marker::PhantomData, diff --git a/crates/router/src/core/payment_methods/vault.rs b/crates/router/src/core/payment_methods/vault.rs index 71d57ef7964..2e34c2ac0aa 100644 --- a/crates/router/src/core/payment_methods/vault.rs +++ b/crates/router/src/core/payment_methods/vault.rs @@ -121,6 +121,7 @@ impl Vaultable for domain::Card { card_type: None, nick_name: value1.nickname.map(masking::Secret::new), card_holder_name: value1.card_holder_name, + co_badged_card_data: None, }; let supp_data = SupplementaryVaultData { diff --git a/crates/router/src/core/payments.rs b/crates/router/src/core/payments.rs index 1e51c7df6e7..be6b8bab631 100644 --- a/crates/router/src/core/payments.rs +++ b/crates/router/src/core/payments.rs @@ -25,9 +25,7 @@ pub mod payment_methods; #[cfg(feature = "olap")] use api_models::admin::MerchantConnectorInfo; use api_models::{ - self, enums, - mandates::RecurringDetails, - payments::{self as payments_api}, + self, enums, mandates::RecurringDetails, payments::{self as payments_api}, }; pub use common_enums::enums::CallConnectorAction; use common_utils::{ @@ -368,7 +366,7 @@ where &operation, state, &business_profile, - &payment_data, + &mut payment_data, connector, ).await; @@ -622,8 +620,8 @@ where let mut connectors = connectors.clone().into_iter(); let connector_data = if business_profile.is_debit_routing_enabled && is_debit_routing_performed { - if let Some((connector_data, local_network)) = find_connector_with_networks(&mut connectors) { - payment_data.set_local_network(local_network); + if let Some((connector_data, network)) = find_connector_with_networks(&mut connectors) { + payment_data.set_card_network(network); connector_data } else { get_connector_data(&mut connectors)?.connector_data @@ -8148,7 +8146,11 @@ pub trait OperationSessionSetters { &mut self, merchant_connector_id: Option, ); - fn set_local_network(&mut self, local_network: enums::CardNetwork); + fn set_card_network(&mut self, card_network: enums::CardNetwork); + fn set_co_badged_card_data( + &mut self, + co_badged_card_data: api_models::payment_methods::CoBadgedCardData, + ); #[cfg(feature = "v1")] fn set_capture_method_in_attempt(&mut self, capture_method: enums::CaptureMethod); fn set_frm_message(&mut self, frm_message: FraudCheck); @@ -8378,11 +8380,28 @@ impl OperationSessionSetters for PaymentData { self.payment_attempt.merchant_connector_id = merchant_connector_id; } - fn set_local_network(&mut self, local_network: enums::CardNetwork) { + fn set_card_network(&mut self, card_network: enums::CardNetwork) { + if let Some(domain::PaymentMethodData::Card(card)) = &mut self.payment_method_data { + card.card_network = Some(card_network); + }; + } + + fn set_co_badged_card_data(&mut self, co_badged_card_data: api_models::payment_methods::CoBadgedCardData) { + logger::debug!("set co-badged card data"); if let Some(domain::PaymentMethodData::Card(card)) = &mut self.payment_method_data { - card.card_network = Some(local_network); + card.co_badged_card_data = Some(co_badged_card_data); + logger::debug!("set co-badged card data in payment method data"); + } else { + if let Some(hyperswitch_domain_models::payment_method_data::PaymentMethodsData::Card(card)) = &mut self + .get_payment_method_info() + .and_then(|payment_method_info| payment_method_info.get_payment_methods_data()) + { + card.co_badged_card_data = Some(co_badged_card_data); + logger::debug!("set co-badged card data in payment method info"); + }; }; } + #[cfg(feature = "v1")] fn set_capture_method_in_attempt(&mut self, capture_method: enums::CaptureMethod) { @@ -8606,7 +8625,14 @@ impl OperationSessionSetters for PaymentIntentData { todo!() } - fn set_local_network(&mut self, local_network: enums::CardNetwork) { + fn set_card_network(&mut self, card_network: enums::CardNetwork) { + todo!() + } + + fn set_co_badged_card_data( + &mut self, + co_badged_card_data: api_models::payment_methods::CoBadgedCardData, + ) { todo!() } @@ -8847,7 +8873,14 @@ impl OperationSessionSetters for PaymentConfirmData { todo!() } - fn set_local_network(&mut self, local_network: enums::CardNetwork) { + fn set_card_network(&mut self, card_network: enums::CardNetwork) { + todo!() + } + + fn set_co_badged_card_data( + &mut self, + co_badged_card_data: api_models::payment_methods::CoBadgedCardData, + ) { todo!() } @@ -9060,7 +9093,14 @@ impl OperationSessionSetters for PaymentStatusData { todo!() } - fn set_local_network(&mut self, local_network: enums::CardNetwork) { + fn set_card_network(&mut self, card_network: enums::CardNetwork) { + todo!() + } + + fn set_co_badged_card_data( + &mut self, + co_badged_card_data: api_models::payment_methods::CoBadgedCardData, + ) { todo!() } @@ -9283,7 +9323,14 @@ impl OperationSessionSetters for PaymentCaptureData { todo!() } - fn set_local_network(&mut self, local_network: enums::CardNetwork) { + fn set_card_network(&mut self, card_network: enums::CardNetwork) { + todo!() + } + + fn set_co_badged_card_data( + &mut self, + co_badged_card_data: api_models::payment_methods::CoBadgedCardData, + ) { todo!() } diff --git a/crates/router/src/core/payments/helpers.rs b/crates/router/src/core/payments/helpers.rs index db3d106ee94..9866405253f 100644 --- a/crates/router/src/core/payments/helpers.rs +++ b/crates/router/src/core/payments/helpers.rs @@ -2120,6 +2120,11 @@ pub async fn retrieve_payment_method_data_with_permanent_token( .network_token_requestor_reference_id .clone(), ); + + let co_badged_card_data = payment_method_info + .get_payment_methods_data() + .and_then(|payment_methods_data| payment_methods_data.get_co_badged_card_data()); + match vault_fetch_action { VaultFetchAction::FetchCardDetailsFromLocker => { let card = vault_data @@ -2132,6 +2137,7 @@ pub async fn retrieve_payment_method_data_with_permanent_token( &payment_intent.merchant_id, locker_id, card_token_data, + co_badged_card_data, ) .await }) @@ -2182,6 +2188,7 @@ pub async fn retrieve_payment_method_data_with_permanent_token( &payment_intent.merchant_id, locker_id, card_token_data, + co_badged_card_data, ) .await }) @@ -2246,6 +2253,7 @@ pub async fn retrieve_card_with_permanent_token_for_external_authentication( &payment_intent.merchant_id, locker_id, card_token_data, + None, ) .await .change_context(errors::ApiErrorResponse::InternalServerError) @@ -2263,7 +2271,9 @@ pub async fn fetch_card_details_from_locker( merchant_id: &id_type::MerchantId, locker_id: &str, card_token_data: Option<&domain::CardToken>, + co_badged_card_data: Option, ) -> RouterResult { + logger::debug!("Fetching card details from locker"); let card = cards::get_card_from_locker(state, customer_id, merchant_id, locker_id) .await .change_context(errors::ApiErrorResponse::InternalServerError) @@ -2308,7 +2318,7 @@ pub async fn fetch_card_details_from_locker( card_issuing_country: None, bank_code: None, }; - Ok(api_card.into()) + Ok(domain::Card::from((api_card, co_badged_card_data))) } #[cfg(all( diff --git a/crates/router/src/core/payments/tokenization.rs b/crates/router/src/core/payments/tokenization.rs index 49f8d7b8eb7..f50a28abbb0 100644 --- a/crates/router/src/core/payments/tokenization.rs +++ b/crates/router/src/core/payments/tokenization.rs @@ -196,6 +196,11 @@ where payment_method_billing_address, ) .await?; + let payment_methods_data = + &save_payment_method_data.request.get_payment_method_data(); + + let co_badged_card_data = payment_methods_data.get_co_badged_card_data(); + let customer_id = customer_id.to_owned().get_required_value("customer_id")?; let merchant_id = merchant_account.get_id(); let is_network_tokenization_enabled = @@ -264,7 +269,7 @@ where save_payment_method_data.request.get_payment_method_data(), ) { (Some(card), _) => Some(PaymentMethodsData::Card( - CardDetailsPaymentMethod::from(card.clone()), + CardDetailsPaymentMethod::from((card.clone(), co_badged_card_data.clone())), )), ( _, @@ -289,7 +294,10 @@ where > = match network_token_resp { Some(token_resp) => { let pm_token_details = token_resp.card.as_ref().map(|card| { - PaymentMethodsData::Card(CardDetailsPaymentMethod::from(card.clone())) + PaymentMethodsData::Card(CardDetailsPaymentMethod::from(( + card.clone(), + None, + ))) }); pm_token_details @@ -622,9 +630,10 @@ where }); let updated_pmd = updated_card.as_ref().map(|card| { - PaymentMethodsData::Card(CardDetailsPaymentMethod::from( + PaymentMethodsData::Card(CardDetailsPaymentMethod::from(( card.clone(), - )) + None, + ))) }); let pm_data_encrypted: Option< Encryptable>, diff --git a/crates/router/src/core/payouts/helpers.rs b/crates/router/src/core/payouts/helpers.rs index 5427e6f15ad..bd71643f6c7 100644 --- a/crates/router/src/core/payouts/helpers.rs +++ b/crates/router/src/core/payouts/helpers.rs @@ -486,6 +486,7 @@ pub async fn save_payout_data_to_locker( card_network: card_info.card_network, card_type: card_info.card_type, saved_to_locker: true, + co_badged_card_data: None, }, ) }) @@ -506,6 +507,7 @@ pub async fn save_payout_data_to_locker( card_network: None, card_type: None, saved_to_locker: true, + co_badged_card_data: None, }, ) }); diff --git a/crates/router/src/utils/verify_connector.rs b/crates/router/src/utils/verify_connector.rs index b13ba70e6fb..0f5d9e6b318 100644 --- a/crates/router/src/utils/verify_connector.rs +++ b/crates/router/src/utils/verify_connector.rs @@ -24,6 +24,7 @@ pub fn generate_card_from_details( card_issuing_country: None, bank_code: None, card_holder_name: None, + co_badged_card_data: None, }) } diff --git a/crates/router/tests/connectors/aci.rs b/crates/router/tests/connectors/aci.rs index 8b3372d7dec..3497a048a8a 100644 --- a/crates/router/tests/connectors/aci.rs +++ b/crates/router/tests/connectors/aci.rs @@ -52,6 +52,7 @@ fn construct_payment_router_data() -> types::PaymentsAuthorizeRouterData { bank_code: None, nick_name: Some(Secret::new("nick_name".into())), card_holder_name: Some(Secret::new("card holder name".into())), + co_badged_card_data: None, }), confirm: true, statement_descriptor_suffix: None, @@ -302,6 +303,7 @@ async fn payments_create_failure() { bank_code: None, nick_name: Some(Secret::new("nick_name".into())), card_holder_name: Some(Secret::new("card holder name".into())), + co_badged_card_data: None, }); 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 c7ad3b69a32..d7017d3d44e 100644 --- a/crates/router/tests/connectors/adyen.rs +++ b/crates/router/tests/connectors/adyen.rs @@ -154,6 +154,7 @@ impl AdyenTest { bank_code: None, nick_name: Some(Secret::new("nick_name".into())), card_holder_name: Some(Secret::new("card holder name".into())), + co_badged_card_data: None, }), confirm: true, statement_descriptor_suffix: None, diff --git a/crates/router/tests/connectors/airwallex.rs b/crates/router/tests/connectors/airwallex.rs index 0e538818d50..bf5a06f157a 100644 --- a/crates/router/tests/connectors/airwallex.rs +++ b/crates/router/tests/connectors/airwallex.rs @@ -83,6 +83,7 @@ fn payment_method_details() -> Option { bank_code: None, nick_name: Some(Secret::new("nick_name".into())), card_holder_name: Some(Secret::new("card holder name".into())), + co_badged_card_data: None, }), capture_method: Some(diesel_models::enums::CaptureMethod::Manual), router_return_url: Some("https://google.com".to_string()), diff --git a/crates/router/tests/connectors/fiserv.rs b/crates/router/tests/connectors/fiserv.rs index 78235278ed9..77ab8223145 100644 --- a/crates/router/tests/connectors/fiserv.rs +++ b/crates/router/tests/connectors/fiserv.rs @@ -54,6 +54,7 @@ fn payment_method_details() -> Option { bank_code: None, nick_name: Some(Secret::new("nick_name".into())), card_holder_name: Some(Secret::new("card holder name".into())), + co_badged_card_data: None, }), capture_method: Some(diesel_models::enums::CaptureMethod::Manual), ..utils::PaymentAuthorizeType::default().0 diff --git a/crates/router/tests/connectors/rapyd.rs b/crates/router/tests/connectors/rapyd.rs index ee6ac303e88..e173f4753d6 100644 --- a/crates/router/tests/connectors/rapyd.rs +++ b/crates/router/tests/connectors/rapyd.rs @@ -54,6 +54,7 @@ async fn should_only_authorize_payment() { bank_code: None, nick_name: Some(Secret::new("nick_name".into())), card_holder_name: Some(Secret::new("card holder name".into())), + co_badged_card_data: None, }), capture_method: Some(diesel_models::enums::CaptureMethod::Manual), ..utils::PaymentAuthorizeType::default().0 @@ -82,6 +83,7 @@ async fn should_authorize_and_capture_payment() { bank_code: None, nick_name: Some(Secret::new("nick_name".into())), card_holder_name: Some(Secret::new("card holder name".into())), + co_badged_card_data: None, }), ..utils::PaymentAuthorizeType::default().0 }), diff --git a/crates/router/tests/connectors/utils.rs b/crates/router/tests/connectors/utils.rs index 6a7239b5b46..f590128e2f9 100644 --- a/crates/router/tests/connectors/utils.rs +++ b/crates/router/tests/connectors/utils.rs @@ -940,6 +940,7 @@ impl Default for CCardType { bank_code: None, nick_name: Some(Secret::new("nick_name".into())), card_holder_name: Some(Secret::new("card holder name".into())), + co_badged_card_data: None, }) } } diff --git a/crates/router/tests/connectors/worldline.rs b/crates/router/tests/connectors/worldline.rs index 793a1cc15f4..22fd198bd0a 100644 --- a/crates/router/tests/connectors/worldline.rs +++ b/crates/router/tests/connectors/worldline.rs @@ -84,6 +84,7 @@ impl WorldlineTest { bank_code: None, nick_name: Some(Secret::new("nick_name".into())), card_holder_name: Some(Secret::new("card holder name".into())), + co_badged_card_data: None, }), confirm: true, statement_descriptor_suffix: None, From 368b20fff6e2953e4876c4435d81c8bc09ee1b93 Mon Sep 17 00:00:00 2001 From: Shankar Singh C Date: Tue, 29 Apr 2025 13:41:31 +0530 Subject: [PATCH 2/2] fix clippy errors --- crates/api_models/src/open_router.rs | 22 +-- crates/api_models/src/payment_methods.rs | 2 + crates/common_enums/src/enums.rs | 1 + .../src/payment_method_data.rs | 22 +-- crates/router/src/core/debit_routing.rs | 132 +----------------- crates/router/src/core/payments.rs | 16 +-- .../router/src/core/payments/tokenization.rs | 2 +- 7 files changed, 37 insertions(+), 160 deletions(-) diff --git a/crates/api_models/src/open_router.rs b/crates/api_models/src/open_router.rs index 3ff8ef06da3..dac85b60635 100644 --- a/crates/api_models/src/open_router.rs +++ b/crates/api_models/src/open_router.rs @@ -71,24 +71,24 @@ pub struct DebitRoutingOutput { impl From<&DebitRoutingOutput> for payment_methods::CoBadgedCardData { fn from(output: &DebitRoutingOutput) -> Self { - payment_methods::CoBadgedCardData { + Self { co_badged_card_networks: output.co_badged_card_networks.clone(), - issuer_country: output.issuer_country.clone(), - is_regulated: output.is_regulated.clone(), - regulated_name: output.regulated_name.clone(), - card_type: output.card_type.clone(), + issuer_country: output.issuer_country, + is_regulated: output.is_regulated, + regulated_name: output.regulated_name, + card_type: output.card_type, } } } impl From for DebitRoutingRequestData { fn from(output: payment_methods::CoBadgedCardData) -> Self { - DebitRoutingRequestData { - co_badged_card_networks: output.co_badged_card_networks.clone(), - issuer_country: output.issuer_country.clone(), - is_regulated: output.is_regulated.clone(), - regulated_name: output.regulated_name.clone(), - card_type: output.card_type.clone(), + Self { + co_badged_card_networks: output.co_badged_card_networks, + issuer_country: output.issuer_country, + is_regulated: output.is_regulated, + regulated_name: output.regulated_name, + card_type: output.card_type, } } } diff --git a/crates/api_models/src/payment_methods.rs b/crates/api_models/src/payment_methods.rs index dbc2ac600be..16bf6f760fe 100644 --- a/crates/api_models/src/payment_methods.rs +++ b/crates/api_models/src/payment_methods.rs @@ -1324,6 +1324,7 @@ impl From for CardDetailsPaymentMethod { card_network: item.card_network, card_type: item.card_type.map(|card| card.to_string()), saved_to_locker: true, + co_badged_card_data: None, } } } @@ -1368,6 +1369,7 @@ impl From for CardDetailsPaymentMethod { card_network: item.card_network, card_type: item.card_type, saved_to_locker: item.saved_to_locker, + co_badged_card_data: None, } } } diff --git a/crates/common_enums/src/enums.rs b/crates/common_enums/src/enums.rs index a163c240dca..eabe6a2f553 100644 --- a/crates/common_enums/src/enums.rs +++ b/crates/common_enums/src/enums.rs @@ -2269,6 +2269,7 @@ pub enum MandateStatus { /// Indicates the card network. #[derive( Clone, + Copy, Debug, Eq, Hash, diff --git a/crates/hyperswitch_domain_models/src/payment_method_data.rs b/crates/hyperswitch_domain_models/src/payment_method_data.rs index 6e4d102bb1b..b3c4cb9e7a8 100644 --- a/crates/hyperswitch_domain_models/src/payment_method_data.rs +++ b/crates/hyperswitch_domain_models/src/payment_method_data.rs @@ -79,7 +79,7 @@ impl PaymentMethodData { } pub fn get_co_badged_card_data(&self) -> Option<&payment_methods::CoBadgedCardData> { - if let PaymentMethodData::Card(card) = self { + if let Self::Card(card) = self { card.co_badged_card_data.as_ref() } else { None @@ -735,6 +735,7 @@ impl TryFrom for PaymentMethodData { bank_code: None, nick_name, card_holder_name, + co_badged_card_data: None, })), } } @@ -801,14 +802,18 @@ impl )> for Card { fn from( - (value, co_badged_card_data): ( + (value, co_badged_card_data_optional): ( api_models::payments::Card, Option, ), ) -> Self { - let a = co_badged_card_data - .clone() - .map(|x| x.co_badged_card_networks[0].clone()); + let first_co_badged_card_network = + co_badged_card_data_optional + .as_ref() + .and_then(|co_badged_card_data| { + co_badged_card_data.co_badged_card_networks.first().cloned() + }); + let api_models::payments::Card { card_number, card_exp_month, @@ -829,13 +834,13 @@ impl card_exp_year, card_cvc, card_issuer, - card_network: a.or(card_network), + card_network: first_co_badged_card_network.or(card_network), card_type, card_issuing_country, bank_code, nick_name, card_holder_name, - co_badged_card_data, + co_badged_card_data: co_badged_card_data_optional, } } } @@ -1903,7 +1908,7 @@ pub enum PaymentMethodsData { impl PaymentMethodsData { pub fn get_co_badged_card_data(&self) -> Option { - if let PaymentMethodsData::Card(card) = self { + if let Self::Card(card) = self { card.co_badged_card_data.clone() } else { None @@ -1963,6 +1968,7 @@ impl From for CardDetailsPaymentMethod { card_network: item.card_network, card_type: item.card_type.map(|card| card.to_string()), saved_to_locker: true, + co_badged_card_data: None, } } } diff --git a/crates/router/src/core/debit_routing.rs b/crates/router/src/core/debit_routing.rs index 0043afc7858..58f6029eb67 100644 --- a/crates/router/src/core/debit_routing.rs +++ b/crates/router/src/core/debit_routing.rs @@ -243,114 +243,6 @@ where None } -// pub async fn get_sorted_co_badged_networks_by_fee< -// F: Clone, -// D: OperationSessionGetters + OperationSessionSetters, -// >( -// state: &SessionState, -// payment_data: &mut D, -// acquirer_country: enums::CountryAlpha2, -// ) -> Option> { -// logger::debug!("Fetching sorted card networks based on their respective network fees"); - -// let payment_method_data_optional = payment_data.get_payment_method_data(); -// let payment_attempt = payment_data.get_payment_attempt(); - -// let debit_routing_output_optional = if let Some( -// hyperswitch_domain_models::payment_method_data::PaymentMethodsData::Card(card), -// ) = payment_data -// .get_payment_method_info() -// .and_then(|payment_method_info| payment_method_info.get_payment_methods_data()) -// { -// if let Some(saved_co_badged_card_data) = &card.co_badged_card_data { -// logger::debug!("Co-badged card data is present in the saved payment method"); -// let co_badged_card_request = api_models::open_router::CoBadgedCardRequest { -// merchant_category_code: enums::MerchantCategoryCode::Mcc0001, -// acquirer_country, -// co_badged_card_data: Some(api_models::open_router::DebitRoutingRequestData::from( -// saved_co_badged_card_data, -// )), -// }; - -// let debit_routing_output_optional = routing::perform_open_routing_for_debit_routing( -// state, -// payment_attempt, -// co_badged_card_request, -// None, -// ) -// .await -// .map_err(|error| { -// logger::warn!(?error, "Failed to calculate total fees per network"); -// }) -// .ok(); -// debit_routing_output_optional -// } else if let Some(saved_card_isin) = &card.card_isin { -// logger::debug!("Co-badged card data is not present; proceeding with the flow using the saved card BIN."); -// let co_badged_card_request = api_models::open_router::CoBadgedCardRequest { -// merchant_category_code: enums::MerchantCategoryCode::Mcc0001, -// acquirer_country, -// co_badged_card_data: None, -// }; - -// let debit_routing_output_optional = routing::perform_open_routing_for_debit_routing( -// state, -// payment_attempt, -// co_badged_card_request, -// Some(Secret::new(saved_card_isin.clone())), -// ) -// .await -// .map_err(|error| { -// logger::warn!(?error, "Failed to calculate total fees per network"); -// }) -// .ok(); -// debit_routing_output_optional -// } else { -// None -// } -// } else if let Some(hyperswitch_domain_models::payment_method_data::PaymentMethodData::Card( -// card, -// )) = payment_method_data_optional -// { -// logger::debug!( -// "Co-badged card data is not present; proceeding with card data form the request." -// ); -// let co_badged_card_request = api_models::open_router::CoBadgedCardRequest { -// merchant_category_code: enums::MerchantCategoryCode::Mcc0001, -// acquirer_country, -// co_badged_card_data: None, -// }; - -// // perform_open_routing_for_debit_routing -// let debit_routing_output_optional = routing::perform_open_routing_for_debit_routing( -// state, -// payment_attempt, -// co_badged_card_request, -// Some(Secret::new(card.card_number.get_card_isin())), -// ) -// .await -// .map_err(|error| { -// logger::warn!(?error, "Failed to calculate total fees per network"); -// }) -// .ok(); -// debit_routing_output_optional -// } else { -// None -// }; - -// debit_routing_output_optional -// .as_ref() -// .map(|debit_routing_output| { -// payment_data.set_co_badged_card_data(payment_methods::CoBadgedCardData::from( -// debit_routing_output, -// )) -// }); - -// let co_badged_card_networks = -// debit_routing_output_optional.map(|data| data.co_badged_card_networks); - -// co_badged_card_networks -// } - pub async fn get_sorted_co_badged_networks_by_fee< F: Clone, D: OperationSessionGetters + OperationSessionSetters, @@ -416,25 +308,6 @@ pub async fn get_sorted_co_badged_networks_by_fee< } }; - // let co_badged_card_request = api_models::open_router::CoBadgedCardRequest { - // merchant_category_code: enums::MerchantCategoryCode::Mcc0001, - // acquirer_country, - // co_badged_card_data: saved_co_badged_card_data - // .map(api_models::open_router::DebitRoutingRequestData::from), - // }; - - // let debit_routing_output_optional = routing::perform_open_routing_for_debit_routing( - // state, - // payment_attempt, - // co_badged_card_request, - // card_isin, - // ) - // .await - // .map_err(|error| { - // logger::warn!(?error, "Failed to calculate total fees per network"); - // }) - // .ok(); - debit_routing_output_optional .as_ref() .map(|debit_routing_output| { @@ -443,10 +316,7 @@ pub async fn get_sorted_co_badged_networks_by_fee< )) }); - let co_badged_card_networks = - debit_routing_output_optional.map(|data| data.co_badged_card_networks); - - co_badged_card_networks + debit_routing_output_optional.map(|data| data.co_badged_card_networks) } async fn handle_retryable_connector( diff --git a/crates/router/src/core/payments.rs b/crates/router/src/core/payments.rs index be6b8bab631..0a6653a5b64 100644 --- a/crates/router/src/core/payments.rs +++ b/crates/router/src/core/payments.rs @@ -8391,15 +8391,13 @@ impl OperationSessionSetters for PaymentData { if let Some(domain::PaymentMethodData::Card(card)) = &mut self.payment_method_data { card.co_badged_card_data = Some(co_badged_card_data); logger::debug!("set co-badged card data in payment method data"); - } else { - if let Some(hyperswitch_domain_models::payment_method_data::PaymentMethodsData::Card(card)) = &mut self - .get_payment_method_info() - .and_then(|payment_method_info| payment_method_info.get_payment_methods_data()) - { - card.co_badged_card_data = Some(co_badged_card_data); - logger::debug!("set co-badged card data in payment method info"); - }; - }; + } else if let Some(hyperswitch_domain_models::payment_method_data::PaymentMethodsData::Card(card)) = &mut self + .get_payment_method_info() + .and_then(|payment_method_info| payment_method_info.get_payment_methods_data()) + { + card.co_badged_card_data = Some(co_badged_card_data); + logger::debug!("set co-badged card data in payment method info"); + }; } diff --git a/crates/router/src/core/payments/tokenization.rs b/crates/router/src/core/payments/tokenization.rs index f50a28abbb0..54def25b9f7 100644 --- a/crates/router/src/core/payments/tokenization.rs +++ b/crates/router/src/core/payments/tokenization.rs @@ -269,7 +269,7 @@ where save_payment_method_data.request.get_payment_method_data(), ) { (Some(card), _) => Some(PaymentMethodsData::Card( - CardDetailsPaymentMethod::from((card.clone(), co_badged_card_data.clone())), + CardDetailsPaymentMethod::from((card.clone(), co_badged_card_data)), )), ( _,