Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions api-reference-v2/openapi_spec.json
Original file line number Diff line number Diff line change
Expand Up @@ -7646,8 +7646,9 @@
"card_brands": {
"type": "array",
"items": {
"type": "string"
}
"$ref": "#/components/schemas/CardNetwork"
},
"example": "[Visa, Mastercard]"
},
"acquirer_bin": {
"type": "string"
Expand Down
5 changes: 3 additions & 2 deletions api-reference/openapi_spec.json
Original file line number Diff line number Diff line change
Expand Up @@ -9732,8 +9732,9 @@
"card_brands": {
"type": "array",
"items": {
"type": "string"
}
"$ref": "#/components/schemas/CardNetwork"
},
"example": "[Visa, Mastercard]"
},
"acquirer_bin": {
"type": "string"
Expand Down
5 changes: 4 additions & 1 deletion config/deployments/production.toml
Original file line number Diff line number Diff line change
Expand Up @@ -616,4 +616,7 @@ connector_list = "cybersource"
enabled = false

[billing_connectors_payment_sync]
billing_connectors_which_require_payment_sync = "stripebilling, recurly"
billing_connectors_which_require_payment_sync = "stripebilling, recurly"

[authentication_providers]
click_to_pay = {connector_list = "adyen, cybersource"}
5 changes: 4 additions & 1 deletion config/deployments/sandbox.toml
Original file line number Diff line number Diff line change
Expand Up @@ -617,4 +617,7 @@ connector_list = "cybersource"
enabled = false

[billing_connectors_payment_sync]
billing_connectors_which_require_payment_sync = "stripebilling, recurly"
billing_connectors_which_require_payment_sync = "stripebilling, recurly"

[authentication_providers]
click_to_pay = {connector_list = "adyen, cybersource"}
3 changes: 3 additions & 0 deletions config/development.toml
Original file line number Diff line number Diff line change
Expand Up @@ -1032,6 +1032,9 @@ background_color = "#FFFFFF"
[platform]
enabled = true

[authentication_providers]
click_to_pay = {connector_list = "adyen, cybersource"}

[open_router]
enabled = false
url = "http://localhost:8080"
3 changes: 3 additions & 0 deletions config/docker_compose.toml
Original file line number Diff line number Diff line change
Expand Up @@ -899,3 +899,6 @@ background_color = "#FFFFFF"

[platform]
enabled = true

[authentication_providers]
click_to_pay = {connector_list = "adyen, cybersource"}
3 changes: 2 additions & 1 deletion crates/api_models/src/payments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8228,7 +8228,8 @@ pub struct ClickToPaySessionResponse {
pub dpa_id: String,
pub dpa_name: String,
pub locale: String,
pub card_brands: Vec<String>,
#[schema(value_type = Vec<CardNetwork>, example = "[Visa, Mastercard]")]
pub card_brands: HashSet<api_enums::CardNetwork>,
pub acquirer_bin: String,
pub acquirer_merchant_id: String,
pub merchant_category_code: String,
Expand Down
16 changes: 0 additions & 16 deletions crates/connector_configs/toml/development.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5552,14 +5552,6 @@ placeholder="Enter locale"
required=true
type="Text"

[ctp_mastercard.metadata.card_brands]
name="card_brands"
label="Card Brands"
placeholder="Enter Card Brands"
required=true
type="MultiSelect"
options=["visa","mastercard"]

[ctp_mastercard.metadata.acquirer_bin]
name="acquirer_bin"
label="Acquire Bin"
Expand Down Expand Up @@ -5757,14 +5749,6 @@ placeholder="Enter locale"
required=true
type="Text"

[ctp_visa.metadata.card_brands]
name="card_brands"
label="Card Brands"
placeholder="Enter Card Brands"
required=true
type="MultiSelect"
options=["visa","mastercard"]

[ctp_visa.metadata.acquirer_bin]
name="acquirer_bin"
label="Acquire Bin"
Expand Down
62 changes: 54 additions & 8 deletions crates/connector_configs/toml/production.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4281,14 +4281,6 @@ placeholder="Enter locale"
required=true
type="Text"

[ctp_visa.metadata.card_brands]
name="card_brands"
label="Card Brands"
placeholder="Enter Card Brands"
required=true
type="MultiSelect"
options=["visa","mastercard"]

[ctp_visa.metadata.acquirer_bin]
name="acquirer_bin"
label="Acquire Bin"
Expand Down Expand Up @@ -4354,6 +4346,60 @@ api_key = "Merchant ID"
key1 = "Terminal ID"
api_secret = "Secret Key"


[ctp_mastercard]
[ctp_mastercard.connector_auth.HeaderKey]
api_key="API Key"

[ctp_mastercard.metadata.dpa_id]
name="dpa_id"
label="DPA Id"
placeholder="Enter DPA Id"
required=true
type="Text"

[ctp_mastercard.metadata.dpa_name]
name="dpa_name"
label="DPA Name"
placeholder="Enter DPA Name"
required=true
type="Text"

[ctp_mastercard.metadata.locale]
name="locale"
label="Locale"
placeholder="Enter locale"
required=true
type="Text"

[ctp_mastercard.metadata.acquirer_bin]
name="acquirer_bin"
label="Acquire Bin"
placeholder="Enter Acquirer Bin"
required=true
type="Text"

[ctp_mastercard.metadata.acquirer_merchant_id]
name="acquirer_merchant_id"
label="Acquire Merchant Id"
placeholder="Enter Acquirer Merchant Id"
required=true
type="Text"

[ctp_mastercard.metadata.merchant_category_code]
name="merchant_category_code"
label="Merchant Category Code"
placeholder="Enter Merchant Category Code"
required=true
type="Text"

[ctp_mastercard.metadata.merchant_country_code]
name="merchant_country_code"
label="Merchant Country Code"
placeholder="Enter Merchant Country Code"
required=true
type="Text"

[facilitapay]
[[facilitapay.bank_transfer]]
payment_method_type = "pix"
Expand Down
15 changes: 1 addition & 14 deletions crates/connector_configs/toml/sandbox.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5521,13 +5521,7 @@ placeholder="Enter locale"
required=true
type="Text"

[ctp_mastercard.metadata.card_brands]
name="card_brands"
label="Card Brands"
placeholder="Enter Card Brands"
required=true
type="MultiSelect"
options=["visa","mastercard"]


[ctp_mastercard.metadata.acquirer_bin]
name="acquirer_bin"
Expand Down Expand Up @@ -5728,13 +5722,6 @@ placeholder="Enter locale"
required=true
type="Text"

[ctp_visa.metadata.card_brands]
name="card_brands"
label="Card Brands"
placeholder="Enter Card Brands"
required=true
type="MultiSelect"
options=["visa","mastercard"]

[ctp_visa.metadata.acquirer_bin]
name="acquirer_bin"
Expand Down
18 changes: 18 additions & 0 deletions crates/diesel_models/src/query/merchant_connector_account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,24 @@ impl MerchantConnectorAccount {
.await
}
}

pub async fn list_enabled_by_profile_id(
conn: &PgPooledConn,
profile_id: &common_utils::id_type::ProfileId,
connector_type: common_enums::ConnectorType,
) -> StorageResult<Vec<Self>> {
generics::generic_filter::<<Self as HasTable>::Table, _, _, _>(
conn,
dsl::profile_id
.eq(profile_id.to_owned())
.and(dsl::disabled.eq(false))
.and(dsl::connector_type.eq(connector_type)),
None,
None,
Some(dsl::created_at.asc()),
)
.await
}
}

#[cfg(feature = "v2")]
Expand Down
1 change: 1 addition & 0 deletions crates/router/src/configs/secrets_transformers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,7 @@ pub(crate) async fn fetch_raw_secrets(
network_tokenization_supported_connectors: conf.network_tokenization_supported_connectors,
theme: conf.theme,
platform: conf.platform,
authentication_providers: conf.authentication_providers,
open_router: conf.open_router,
}
}
26 changes: 26 additions & 0 deletions crates/router/src/configs/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ pub struct Settings<S: SecretState> {
pub network_tokenization_supported_connectors: NetworkTokenizationSupportedConnectors,
pub theme: ThemeSettings,
pub platform: Platform,
pub authentication_providers: AuthenticationProviders,
pub open_router: OpenRouter,
}

Expand Down Expand Up @@ -508,6 +509,31 @@ pub struct CorsSettings {
pub allowed_methods: HashSet<String>,
}

#[derive(Debug, Deserialize, Clone, Default)]
pub struct AuthenticationProviders {
#[serde(deserialize_with = "deserialize_connector_list")]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there's already a deserializer for this type, deserialize_hashset, is it possible to use that?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the requirement is little different here, the one you mentioning goes something like bank_debit.ach = { connector_list = "gocardless,adyen" } where as mine is click_to_pay = {connector_list = "adyen, cybersource"}

pub click_to_pay: HashSet<enums::Connector>,
}

fn deserialize_connector_list<'a, D>(deserializer: D) -> Result<HashSet<enums::Connector>, D::Error>
where
D: serde::Deserializer<'a>,
{
use serde::de::Error;

#[derive(Deserialize)]
struct Wrapper {
connector_list: String,
}

let wrapper = Wrapper::deserialize(deserializer)?;
wrapper
.connector_list
.split(',')
.map(|s| s.trim().parse().map_err(D::Error::custom))
.collect()
}

#[derive(Debug, Deserialize, Clone, Default)]
pub struct NetworkTransactionIdSupportedConnectors {
#[serde(deserialize_with = "deserialize_hashset")]
Expand Down
68 changes: 66 additions & 2 deletions crates/router/src/core/payments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ pub mod types;
#[cfg(feature = "olap")]
use std::collections::HashMap;
use std::{
collections::HashSet, fmt::Debug, marker::PhantomData, ops::Deref, time::Instant, vec::IntoIter,
collections::HashSet, fmt::Debug, marker::PhantomData, ops::Deref, str::FromStr, time::Instant,
vec::IntoIter,
};

#[cfg(feature = "v2")]
Expand Down Expand Up @@ -4156,6 +4157,7 @@ where
key_store,
value,
payment_data.get_payment_intent(),
business_profile.get_id(),
)
.await?;
payment_data.push_sessions_token(session_token);
Expand All @@ -4177,6 +4179,7 @@ pub async fn get_session_token_for_click_to_pay(
key_store: &domain::MerchantKeyStore,
authentication_product_ids: common_types::payments::AuthenticationConnectorAccountMap,
payment_intent: &hyperswitch_domain_models::payments::PaymentIntent,
profile_id: &id_type::ProfileId,
) -> RouterResult<api_models::payments::SessionToken> {
let click_to_pay_mca_id = authentication_product_ids
.get_click_to_pay_connector_account_id()
Expand Down Expand Up @@ -4230,12 +4233,16 @@ pub async fn get_session_token_for_click_to_pay(
_ => None,
};

let card_brands =
get_card_brands_based_on_active_merchant_connector_account(state, profile_id, key_store)
.await?;

Ok(api_models::payments::SessionToken::ClickToPay(Box::new(
api_models::payments::ClickToPaySessionResponse {
dpa_id: click_to_pay_metadata.dpa_id,
dpa_name: click_to_pay_metadata.dpa_name,
locale: click_to_pay_metadata.locale,
card_brands: click_to_pay_metadata.card_brands,
card_brands,
acquirer_bin: click_to_pay_metadata.acquirer_bin,
acquirer_merchant_id: click_to_pay_metadata.acquirer_merchant_id,
merchant_category_code: click_to_pay_metadata.merchant_category_code,
Expand All @@ -4251,6 +4258,63 @@ pub async fn get_session_token_for_click_to_pay(
)))
}

#[cfg(feature = "v1")]
async fn get_card_brands_based_on_active_merchant_connector_account(
state: &SessionState,
profile_id: &id_type::ProfileId,
key_store: &domain::MerchantKeyStore,
) -> RouterResult<HashSet<enums::CardNetwork>> {
let key_manager_state = &(state).into();
let merchant_configured_payment_connectors = state
.store
.list_enabled_connector_accounts_by_profile_id(
key_manager_state,
profile_id,
key_store,
common_enums::ConnectorType::PaymentProcessor,
)
.await
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("error when fetching merchant connector accounts")?;

let payment_connectors_eligible_for_click_to_pay =
state.conf.authentication_providers.click_to_pay.clone();

let filtered_payment_connector_accounts: Vec<
hyperswitch_domain_models::merchant_connector_account::MerchantConnectorAccount,
> = merchant_configured_payment_connectors
.into_iter()
.filter(|account| {
enums::Connector::from_str(&account.connector_name)
.ok()
.map(|connector| payment_connectors_eligible_for_click_to_pay.contains(&connector))
.unwrap_or(false)
})
.collect();

let mut card_brands = HashSet::new();

for account in filtered_payment_connector_accounts {
if let Some(values) = &account.payment_methods_enabled {
for val in values {
let payment_methods_enabled: api_models::admin::PaymentMethodsEnabled =
serde_json::from_value(val.peek().to_owned()).inspect_err(|err| {
logger::error!("Failed to parse Payment methods enabled data set from dashboard because {}", err)
})
.change_context(errors::ApiErrorResponse::InternalServerError)?;
if let Some(payment_method_types) = payment_methods_enabled.payment_method_types {
for payment_method_type in payment_method_types {
if let Some(networks) = payment_method_type.card_networks {
card_brands.extend(networks);
}
}
}
}
}
}
Ok(card_brands)
}

fn validate_customer_details_for_click_to_pay(customer_details: &CustomerData) -> RouterResult<()> {
match (
customer_details.phone.as_ref(),
Expand Down
1 change: 0 additions & 1 deletion crates/router/src/db/kafka_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1281,7 +1281,6 @@ impl MerchantConnectorAccountInterface for KafkaStore {
.await
}

#[cfg(all(feature = "oltp", feature = "v2"))]
async fn list_enabled_connector_accounts_by_profile_id(
&self,
state: &KeyManagerState,
Expand Down
Loading
Loading