diff --git a/crates/api_models/src/payment_methods.rs b/crates/api_models/src/payment_methods.rs index c3b8ed5f3b..a087d67368 100644 --- a/crates/api_models/src/payment_methods.rs +++ b/crates/api_models/src/payment_methods.rs @@ -6,7 +6,6 @@ use crate::enums as api_enums; #[derive(Debug, serde::Deserialize, serde::Serialize, Clone)] #[serde(deny_unknown_fields)] pub struct CreatePaymentMethod { - pub merchant_id: Option, pub payment_method: api_enums::PaymentMethodType, pub payment_method_type: Option, pub payment_method_issuer: Option, @@ -35,6 +34,8 @@ pub struct CardDetail { #[derive(Debug, serde::Deserialize, serde::Serialize)] pub struct PaymentMethodResponse { + pub merchant_id: String, + pub customer_id: Option, pub payment_method_id: String, pub payment_method: api_enums::PaymentMethodType, pub payment_method_type: Option, diff --git a/crates/router/src/core/payment_methods/cards.rs b/crates/router/src/core/payment_methods/cards.rs index e47cb85698..db4bfeeafb 100644 --- a/crates/router/src/core/payment_methods/cards.rs +++ b/crates/router/src/core/payment_methods/cards.rs @@ -26,13 +26,13 @@ use crate::{ pub async fn create_payment_method( db: &dyn db::StorageInterface, req: &api::CreatePaymentMethod, - customer_id: String, + customer_id: &str, payment_method_id: &str, merchant_id: &str, ) -> errors::CustomResult { let response = db .insert_payment_method(storage::PaymentMethodNew { - customer_id, + customer_id: customer_id.to_string(), merchant_id: merchant_id.to_string(), payment_method_id: payment_method_id.to_string(), payment_method: req.payment_method.foreign_into(), @@ -65,7 +65,7 @@ pub async fn add_payment_method( create_payment_method( &*state.store, &req, - customer_id, + &customer_id, &payment_method_id, &merchant_id, ) @@ -74,6 +74,8 @@ pub async fn add_payment_method( error.to_duplicate_response(errors::ApiErrorResponse::DuplicatePaymentMethod) })?; Ok(api::PaymentMethodResponse { + merchant_id, + customer_id: Some(customer_id), payment_method_id: payment_method_id.to_string(), payment_method: req.payment_method, payment_method_type: req.payment_method_type, @@ -114,7 +116,6 @@ pub async fn update_customer_payment_method( delete_card(state, &pm.merchant_id, &pm.payment_method_id).await?; }; let new_pm = api::CreatePaymentMethod { - merchant_id: Some(merchant_account.merchant_id.clone()), payment_method: pm.payment_method.foreign_into(), payment_method_type: pm.payment_method_type.map(|x| x.foreign_into()), payment_method_issuer: pm.payment_method_issuer, @@ -158,16 +159,26 @@ pub async fn add_card( mock_add_card(db, &card_id, &card, None).await? }; - create_payment_method( - db, - &req, - customer_id.to_string(), - &response.card_id, - merchant_id, - ) - .await - .change_context(errors::CardVaultError::PaymentMethodCreationFailed)?; - let payment_method_resp = payment_methods::mk_add_card_response(card, response, req); + if let Some(false) = response.duplicate { + create_payment_method(db, &req, &customer_id, &response.card_id, merchant_id) + .await + .change_context(errors::CardVaultError::PaymentMethodCreationFailed)?; + } else { + match db.find_payment_method(&response.card_id).await { + Ok(_) => (), + Err(err) => { + if err.current_context().is_db_not_found() { + create_payment_method(db, &req, &customer_id, &response.card_id, merchant_id) + .await + .change_context(errors::CardVaultError::PaymentMethodCreationFailed)?; + } else { + Err(errors::CardVaultError::PaymentMethodCreationFailed)?; + } + } + } + } + let payment_method_resp = + payment_methods::mk_add_card_response(card, response, req, merchant_id); Ok(payment_method_resp) } @@ -706,6 +717,8 @@ pub async fn retrieve_payment_method( None }; Ok(services::BachResponse::Json(api::PaymentMethodResponse { + merchant_id: pm.merchant_id, + customer_id: Some(pm.customer_id), payment_method_id: pm.payment_method_id, payment_method: pm.payment_method.foreign_into(), payment_method_type: pm.payment_method_type.map(ForeignInto::foreign_into), diff --git a/crates/router/src/core/payment_methods/transformers.rs b/crates/router/src/core/payment_methods/transformers.rs index 778ba1efb4..4edd4f1f16 100644 --- a/crates/router/src/core/payment_methods/transformers.rs +++ b/crates/router/src/core/payment_methods/transformers.rs @@ -93,12 +93,14 @@ pub fn mk_add_card_response( card: api::CardDetail, response: AddCardResponse, req: api::CreatePaymentMethod, + merchant_id: &str, ) -> api::PaymentMethodResponse { + let mut card_number = card.card_number.peek().to_owned(); let card = api::CardDetailFromLocker { scheme: None, - last4_digits: Some(card.card_number.peek().to_owned().split_off(12)), + last4_digits: Some(card_number.split_off(card_number.len() - 4)), issuer_country: None, // TODO bin mapping - card_number: None, + card_number: Some(card.card_number), expiry_month: Some(card.card_exp_month), expiry_year: Some(card.card_exp_year), card_token: Some(response.external_id.into()), // TODO ? @@ -106,6 +108,8 @@ pub fn mk_add_card_response( card_holder_name: None, }; api::PaymentMethodResponse { + merchant_id: merchant_id.to_owned(), + customer_id: req.customer_id, payment_method_id: response.card_id, payment_method: req.payment_method, payment_method_type: req.payment_method_type, @@ -171,10 +175,11 @@ pub fn get_card_detail( .card_number .get_required_value("card_number") .change_context(errors::CardVaultError::FetchCardFailed)?; + let mut last4_digits = card_number.peek().to_owned(); let card_detail = api::CardDetailFromLocker { scheme: pm.scheme.clone(), issuer_country: pm.issuer_country.clone(), - last4_digits: None, //.split_off(12)), //TODO: we need card number as well + last4_digits: Some(last4_digits.split_off(last4_digits.len() - 4)), card_number: Some(card_number), expiry_month: response.card_exp_month, expiry_year: response.card_exp_year, diff --git a/crates/router/src/core/payments/helpers.rs b/crates/router/src/core/payments/helpers.rs index cac54faa9b..c5c573bbff 100644 --- a/crates/router/src/core/payments/helpers.rs +++ b/crates/router/src/core/payments/helpers.rs @@ -498,7 +498,6 @@ pub(crate) async fn call_payment_method( Some(customer) => { let customer_id = customer.customer_id.clone(); let payment_method_request = api::CreatePaymentMethod { - merchant_id: Some(merchant_id.to_string()), payment_method: payment_method_type.foreign_into(), payment_method_type: None, payment_method_issuer: None, @@ -530,7 +529,6 @@ pub(crate) async fn call_payment_method( } _ => { let payment_method_request = api::CreatePaymentMethod { - merchant_id: Some(merchant_id.to_string()), payment_method: payment_method_type.foreign_into(), payment_method_type: None, payment_method_issuer: None,