From fad712cedbe1b63fdc46d58eef0fd358e5cab926 Mon Sep 17 00:00:00 2001 From: Mrudul Vajpayee Date: Fri, 10 Jan 2025 13:46:56 +0530 Subject: [PATCH] check allowed payment method types in enabled options --- crates/router/src/core/metrics.rs | 1 + crates/router/src/core/payments/operations.rs | 2 + .../payments/operations/payment_create.rs | 99 ++++++++++++++++++- 3 files changed, 97 insertions(+), 5 deletions(-) diff --git a/crates/router/src/core/metrics.rs b/crates/router/src/core/metrics.rs index a98a4ffb259f..1a77cbbc72c2 100644 --- a/crates/router/src/core/metrics.rs +++ b/crates/router/src/core/metrics.rs @@ -88,3 +88,4 @@ counter_metric!(PARTIAL_AUTH_FAILURE, GLOBAL_METER); counter_metric!(API_KEY_REQUEST_INITIATED, GLOBAL_METER); counter_metric!(API_KEY_REQUEST_COMPLETED, GLOBAL_METER); +counter_metric!(PAYMENT_METHOD_TYPES_MISCONFIGATION_METRIC, GLOBAL_METER); diff --git a/crates/router/src/core/payments/operations.rs b/crates/router/src/core/payments/operations.rs index 4adb94034181..977fdbea1b73 100644 --- a/crates/router/src/core/payments/operations.rs +++ b/crates/router/src/core/payments/operations.rs @@ -863,3 +863,5 @@ pub trait ShouldCallConnector { force_sync: Option, ) -> bool; } + +pub const MERCHANT_ID: &str = "merchant_id"; diff --git a/crates/router/src/core/payments/operations/payment_create.rs b/crates/router/src/core/payments/operations/payment_create.rs index b7b3420987d1..fe60ef0a114e 100644 --- a/crates/router/src/core/payments/operations/payment_create.rs +++ b/crates/router/src/core/payments/operations/payment_create.rs @@ -1,8 +1,8 @@ -use std::marker::PhantomData; +use std::{collections::HashSet, marker::PhantomData}; use api_models::{ - enums::FrmSuggestion, mandates::RecurringDetails, payment_methods::PaymentMethodsData, - payments::GetAddressFromPaymentMethodData, + admin::PaymentMethodsEnabled, enums::FrmSuggestion, mandates::RecurringDetails, + payment_methods::PaymentMethodsData, payments::GetAddressFromPaymentMethodData, }; use async_trait::async_trait; use common_utils::{ @@ -30,13 +30,15 @@ use router_derive::PaymentOperation; use router_env::{instrument, logger, tracing}; use time::PrimitiveDateTime; -use super::{BoxedOperation, Domain, GetTracker, Operation, UpdateTracker, ValidateRequest}; +use super::{ + BoxedOperation, Domain, GetTracker, Operation, UpdateTracker, ValidateRequest, MERCHANT_ID, +}; use crate::{ consts, core::{ errors::{self, CustomResult, RouterResult, StorageErrorExt}, mandate::helpers as m_helpers, - payment_link, + metrics, payment_link, payment_methods::cards::create_encrypted_data, payments::{self, helpers, operations, CustomerDetails, PaymentAddress, PaymentData}, utils as core_utils, @@ -309,6 +311,93 @@ impl GetTracker, api::PaymentsRequest> ) .await?; + let allowed_payment_method_types = payment_intent_new + .allowed_payment_method_types + .clone() + .map(|val| { + val.parse_value::>("allowed_payment_method_types") + }) + .transpose() + .unwrap_or_else(|error| { + logger::error!( + ?error, + "Failed to deserialize PaymentIntent allowed_payment_method_types" + ); + None + }); + + if let Some(allowed_payment_method_types) = allowed_payment_method_types { + let all_connector_accounts = db + .find_merchant_connector_account_by_merchant_id_and_disabled_list( + &state.into(), + merchant_account.get_id(), + false, + merchant_key_store, + ) + .await + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Database error when querying for merchant connector accounts")?; + + let filtered_connector_accounts = + helpers::filter_mca_based_on_profile_and_connector_type( + all_connector_accounts, + &profile_id, + common_enums::ConnectorType::PaymentProcessor, + ); + + let supporting_payment_method_types: HashSet<_> = filtered_connector_accounts + .iter() + .flat_map(|connector_account| { + connector_account + .payment_methods_enabled + .clone() + .unwrap_or_default() + .into_iter() + .map(|payment_methods_enabled| { + payment_methods_enabled + .parse_value::("payment_methods_enabled") + }) + .filter_map(|parsed_payment_method_result| { + parsed_payment_method_result + .inspect_err(|err| { + logger::error!(session_token_parsing_error = ?err); + }) + .ok() + }) + .flat_map(|parsed_payment_methods_enabled| { + parsed_payment_methods_enabled + .payment_method_types + .unwrap_or_default() + .into_iter() + .map(|payment_method_type| payment_method_type.payment_method_type) + }) + }) + .collect(); + + let unsupported_payment_methods: Vec<_> = allowed_payment_method_types + .iter() + .filter(|allowed_pmt| !supporting_payment_method_types.contains(allowed_pmt)) + .collect(); + + if !unsupported_payment_methods.is_empty() { + metrics::PAYMENT_METHOD_TYPES_MISCONFIGATION_METRIC.add( + 1, + router_env::metric_attributes!(( + MERCHANT_ID, + merchant_account.get_id().clone() + )), + ); + } + + if unsupported_payment_methods.len() == allowed_payment_method_types.len() { + return Err(errors::ApiErrorResponse::IncorrectPaymentMethodConfiguration) + .attach_printable(format!( + "None of the allowed payment method types {:?} are configured for this merchant connector account.", + allowed_payment_method_types + )); + } + } + let (payment_attempt_new, additional_payment_data) = Self::make_payment_attempt( &payment_id, merchant_id,