mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-29 00:49:42 +08:00
fix(list): adding configuation changes for filtering pm based on countries & currencies (#669)
This commit is contained in:
@ -1,10 +1,14 @@
|
||||
use std::path::PathBuf;
|
||||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
path::PathBuf,
|
||||
str::FromStr,
|
||||
};
|
||||
|
||||
use common_utils::ext_traits::ConfigExt;
|
||||
use config::{Environment, File};
|
||||
use redis_interface::RedisSettings;
|
||||
pub use router_env::config::{Log, LogConsole, LogFile, LogTelemetry};
|
||||
use serde::Deserialize;
|
||||
use serde::{Deserialize, Deserializer};
|
||||
|
||||
use crate::{
|
||||
core::errors::{ApplicationError, ApplicationResult},
|
||||
@ -51,6 +55,64 @@ pub struct Settings {
|
||||
pub drainer: DrainerSettings,
|
||||
pub jwekey: Jwekey,
|
||||
pub webhooks: WebhooksSettings,
|
||||
pub pm_filters: ConnectorFilters,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Clone, Default)]
|
||||
#[serde(transparent)]
|
||||
pub struct ConnectorFilters(pub HashMap<String, PaymentMethodFilters>);
|
||||
|
||||
#[derive(Debug, Deserialize, Clone, Default)]
|
||||
#[serde(transparent)]
|
||||
pub struct PaymentMethodFilters(
|
||||
pub HashMap<api_models::enums::PaymentMethodType, CurrencyCountryFilter>,
|
||||
);
|
||||
|
||||
#[derive(Debug, Deserialize, Clone, Default)]
|
||||
#[serde(default)]
|
||||
pub struct CurrencyCountryFilter {
|
||||
#[serde(deserialize_with = "currency_set_deser")]
|
||||
pub currency: Option<HashSet<api_models::enums::Currency>>,
|
||||
#[serde(deserialize_with = "string_set_deser")]
|
||||
pub country: Option<HashSet<String>>,
|
||||
}
|
||||
|
||||
fn string_set_deser<'a, D>(deserializer: D) -> Result<Option<HashSet<String>>, D::Error>
|
||||
where
|
||||
D: Deserializer<'a>,
|
||||
{
|
||||
let value = <Option<String>>::deserialize(deserializer)?;
|
||||
Ok(value.and_then(|inner| {
|
||||
let list = inner
|
||||
.trim()
|
||||
.split(',')
|
||||
.map(|value| value.to_string())
|
||||
.collect::<HashSet<_>>();
|
||||
match list.len() {
|
||||
0 => None,
|
||||
_ => Some(list),
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
fn currency_set_deser<'a, D>(
|
||||
deserializer: D,
|
||||
) -> Result<Option<HashSet<api_models::enums::Currency>>, D::Error>
|
||||
where
|
||||
D: Deserializer<'a>,
|
||||
{
|
||||
let value = <Option<String>>::deserialize(deserializer)?;
|
||||
Ok(value.and_then(|inner| {
|
||||
let list = inner
|
||||
.trim()
|
||||
.split(',')
|
||||
.flat_map(api_models::enums::Currency::from_str)
|
||||
.collect::<HashSet<_>>();
|
||||
match list.len() {
|
||||
0 => None,
|
||||
_ => Some(list),
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Clone)]
|
||||
|
||||
@ -14,6 +14,7 @@ use error_stack::{report, ResultExt};
|
||||
use router_env::{instrument, tracing};
|
||||
|
||||
use crate::{
|
||||
configs::settings,
|
||||
core::{
|
||||
errors::{self, StorageErrorExt},
|
||||
payment_methods::{transformers as payment_methods, vault},
|
||||
@ -348,10 +349,13 @@ pub async fn delete_card<'a>(
|
||||
}
|
||||
|
||||
pub async fn list_payment_methods(
|
||||
db: &dyn db::StorageInterface,
|
||||
state: &routes::AppState,
|
||||
merchant_account: storage::MerchantAccount,
|
||||
mut req: api::ListPaymentMethodRequest,
|
||||
) -> errors::RouterResponse<api::ListPaymentMethodResponse> {
|
||||
let db = &*state.store;
|
||||
let pm_config_mapping = &state.conf.pm_filters;
|
||||
|
||||
let payment_intent = helpers::verify_client_secret(
|
||||
db,
|
||||
merchant_account.storage_scheme,
|
||||
@ -410,6 +414,7 @@ pub async fn list_payment_methods(
|
||||
payment_attempt.as_ref(),
|
||||
address.as_ref(),
|
||||
mca.connector_name,
|
||||
pm_config_mapping,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
@ -567,6 +572,7 @@ pub async fn list_payment_methods(
|
||||
)))
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
async fn filter_payment_methods(
|
||||
payment_methods: Vec<serde_json::Value>,
|
||||
req: &mut api::ListPaymentMethodRequest,
|
||||
@ -575,6 +581,7 @@ async fn filter_payment_methods(
|
||||
payment_attempt: Option<&storage::PaymentAttempt>,
|
||||
address: Option<&storage::Address>,
|
||||
connector: String,
|
||||
config: &settings::ConnectorFilters,
|
||||
) -> errors::CustomResult<(), errors::ApiErrorResponse> {
|
||||
for payment_method in payment_methods.into_iter() {
|
||||
let parse_result = serde_json::from_value::<PaymentMethodsEnabled>(payment_method);
|
||||
@ -627,6 +634,16 @@ async fn filter_payment_methods(
|
||||
true
|
||||
};
|
||||
|
||||
let filter5 = filter_pm_based_on_config(
|
||||
config,
|
||||
&connector,
|
||||
&payment_method_object.payment_method_type,
|
||||
address.and_then(|inner| inner.country.clone()),
|
||||
payment_attempt
|
||||
.and_then(|value| value.currency)
|
||||
.map(|value| value.foreign_into()),
|
||||
);
|
||||
|
||||
let connector = connector.clone();
|
||||
|
||||
let response_pm_type = ResponsePaymentMethodIntermediate::new(
|
||||
@ -635,7 +652,7 @@ async fn filter_payment_methods(
|
||||
payment_method,
|
||||
);
|
||||
|
||||
if filter && filter2 && filter3 && filter4 {
|
||||
if filter && filter2 && filter3 && filter4 && filter5 {
|
||||
resp.push(response_pm_type);
|
||||
}
|
||||
}
|
||||
@ -645,6 +662,33 @@ async fn filter_payment_methods(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn filter_pm_based_on_config<'a>(
|
||||
config: &'a crate::configs::settings::ConnectorFilters,
|
||||
connector: &'a str,
|
||||
payment_method_type: &'a api_enums::PaymentMethodType,
|
||||
country: Option<String>,
|
||||
currency: Option<api_enums::Currency>,
|
||||
) -> bool {
|
||||
config
|
||||
.0
|
||||
.get(connector)
|
||||
.and_then(|inner| inner.0.get(payment_method_type))
|
||||
.map(|value| {
|
||||
let condition1 = value
|
||||
.country
|
||||
.as_ref()
|
||||
.zip(country)
|
||||
.map(|(lhs, rhs)| lhs.contains(&rhs));
|
||||
let condition2 = value
|
||||
.currency
|
||||
.as_ref()
|
||||
.zip(currency)
|
||||
.map(|(lhs, rhs)| lhs.contains(&rhs));
|
||||
condition1.unwrap_or(true) && condition2.unwrap_or(true)
|
||||
})
|
||||
.unwrap_or(true)
|
||||
}
|
||||
|
||||
fn filter_pm_card_network_based(
|
||||
pm_card_networks: Option<&Vec<api_enums::CardNetwork>>,
|
||||
request_card_networks: Option<&Vec<api_enums::CardNetwork>>,
|
||||
|
||||
@ -82,9 +82,7 @@ pub async fn list_payment_method_api(
|
||||
state.get_ref(),
|
||||
&req,
|
||||
payload,
|
||||
|state, merchant_account, req| {
|
||||
cards::list_payment_methods(&*state.store, merchant_account, req)
|
||||
},
|
||||
cards::list_payment_methods,
|
||||
&*auth,
|
||||
)
|
||||
.await
|
||||
|
||||
Reference in New Issue
Block a user