Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add routing support for v2 sdk session flow #6763

Open
wants to merge 29 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
0d7371f
feat: add session routing in sdk session token call in v2
hrithikesh026 Dec 5, 2024
0066206
Merge branch 'main' into add-routing-support-for-v2-sdk-session-flow
hrithikesh026 Dec 5, 2024
b80eb0a
chore: use MCA List wrapper across codebase
hrithikesh026 Dec 6, 2024
b700aa3
chore: address clippy warning for v2
hrithikesh026 Dec 6, 2024
76d11bc
chore: address cargo hack warnings
hrithikesh026 Dec 6, 2024
a8d48af
chore: add appropriate feature flags for imports
hrithikesh026 Dec 6, 2024
06129e0
chore: move routing enabled pmt set to consts
hrithikesh026 Dec 10, 2024
7b39303
feat: calculate and store pre_routing results in payment intent
hrithikesh026 Dec 11, 2024
91865ae
chore: update payment intent table with prerouting results in update …
hrithikesh026 Dec 11, 2024
e75bbca
chore: address cargo clippy warnings for v2 and v1
hrithikesh026 Dec 11, 2024
218229a
chore: add implmentation for to_update_tracker in Operation trait imp…
hrithikesh026 Dec 11, 2024
1d048ec
Merge remote-tracking branch 'origin/main' into add-routing-support-f…
hrithikesh026 Dec 11, 2024
cf729ca
Merge remote-tracking branch 'origin/main' into add-routing-support-f…
hrithikesh026 Dec 12, 2024
60d849f
chore: fix const imports
hrithikesh026 Dec 13, 2024
82171f4
chore: rename payment_method_type to payment_method_sub_type
hrithikesh026 Dec 13, 2024
d676e12
chore: rename payment_method to payment_method_type
hrithikesh026 Dec 13, 2024
a17b5ff
chore: rename payment_method to payment_method_type
hrithikesh026 Dec 13, 2024
6edf2ec
chore: use filter instead of for loop and mutable variable
hrithikesh026 Dec 13, 2024
f3429ce
fix: pass business profile from parent function instead of fetching f…
hrithikesh026 Dec 16, 2024
0eace21
chore: introduce SessionConnectorDatas
hrithikesh026 Dec 17, 2024
ddb44df
Merge remote-tracking branch 'origin/main' into add-routing-support-f…
hrithikesh026 Dec 17, 2024
f6251f4
fix: ignore spell check for SessionConnectorDatas
hrithikesh026 Dec 17, 2024
07cc398
refactor: refactor create_list_wrapper macro
hrithikesh026 Dec 19, 2024
d25eb76
Merge branch 'main' into add-routing-support-for-v2-sdk-session-flow
hrithikesh026 Dec 19, 2024
62ec72c
resolve merge conflicts
hrithikesh026 Dec 24, 2024
49eb7dc
Revert "resolve merge conflicts"
hrithikesh026 Dec 24, 2024
428b600
Merge remote-tracking branch 'origin/main' into add-routing-support-f…
hrithikesh026 Dec 24, 2024
890c452
chore: fix merge related errors
hrithikesh026 Dec 30, 2024
c00b149
Merge remote-tracking branch 'origin/main' into add-routing-support-f…
hrithikesh026 Dec 30, 2024
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
9 changes: 9 additions & 0 deletions crates/common_utils/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,7 @@ macro_rules! create_list_wrapper {
$($function_def: tt)*
}
) => {
#[derive(Clone, Debug)]
pub struct $wrapper_name(Vec<$type_name>);
impl $wrapper_name {
pub fn new(list: Vec<$type_name>) -> Self {
Expand All @@ -396,6 +397,14 @@ macro_rules! create_list_wrapper {
}
}

impl<'a> IntoIterator for &'a $wrapper_name {
type Item = &'a $type_name;
type IntoIter = std::slice::Iter<'a, $type_name>;
fn into_iter(self) -> Self::IntoIter {
self.0.iter()
}
}

impl FromIterator<$type_name> for $wrapper_name {
fn from_iter<T: IntoIterator<Item = $type_name>>(iter: T) -> Self {
Self(iter.into_iter().collect())
Expand Down
1 change: 1 addition & 0 deletions crates/diesel_models/src/payment_intent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,7 @@ pub struct PaymentIntentUpdateFields {
pub struct PaymentIntentUpdateInternal {
pub status: Option<storage_enums::IntentStatus>,
pub active_attempt_id: Option<common_utils::id_type::GlobalAttemptId>,
pub prerouting_algorithm: Option<serde_json::Value>,
pub modified_at: PrimitiveDateTime,
pub amount: Option<MinorUnit>,
pub currency: Option<storage_enums::Currency>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -563,10 +563,44 @@ common_utils::create_list_wrapper!(
MerchantConnectorAccounts,
MerchantConnectorAccount,
impl_functions: {
pub fn into_inner(self) -> Vec<MerchantConnectorAccount> {
self.0
}
pub fn retain<F>(&mut self, f: F)
where
F: FnMut(&MerchantConnectorAccount) -> bool
{
self.0.retain(f)
}
fn filter_and_map<'a, T>(
&'a self,
filter: impl Fn(&'a MerchantConnectorAccount) -> bool,
func: impl Fn(&'a MerchantConnectorAccount) -> T,
) -> rustc_hash::FxHashSet<T>
where
T: std::hash::Hash + Eq,
{
self.0
.iter()
.filter(|mca| filter(mca))
.map(func)
.collect::<rustc_hash::FxHashSet<_>>()
}

pub fn filter_by_profile<'a, T>(
&'a self,
profile_id: &'a id_type::ProfileId,
func: impl Fn(&'a MerchantConnectorAccount) -> T,
) -> rustc_hash::FxHashSet<T>
where
T: std::hash::Hash + Eq,
{
self.filter_and_map(|mca| mca.profile_id == *profile_id, func)
}
#[cfg(feature = "v2")]
pub fn get_connector_and_supporting_payment_method_type_for_session_call(
&self,
) -> Vec<(&MerchantConnectorAccount, common_enums::PaymentMethodType)> {
) -> Vec<(&MerchantConnectorAccount, common_enums::PaymentMethodType, common_enums::PaymentMethod)> {
let connector_and_supporting_payment_method_type = self.iter().flat_map(|connector_account| {
connector_account
.get_parsed_payment_methods_enabled()
Expand All @@ -592,7 +626,7 @@ common_utils::create_list_wrapper!(
is_invoke_sdk_client
})
.map(|payment_method_type| {
(connector_account, payment_method_type.payment_method_type)
(connector_account, payment_method_type.payment_method_type, parsed_payment_methods_enabled.payment_method)
})
.collect::<Vec<_>>()
})
Expand Down
48 changes: 48 additions & 0 deletions crates/hyperswitch_domain_models/src/payments/payment_intent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,11 @@ pub enum PaymentIntentUpdate {
status: common_enums::IntentStatus,
updated_by: String,
},
/// Update the payment intent details on payment sdk session call, before calling the connector.
SessionIntentUpdate {
prerouting_algorithm: serde_json::Value,
updated_by: String,
},
/// UpdateIntent
UpdateIntent(Box<PaymentIntentUpdateFields>),
}
Expand Down Expand Up @@ -359,6 +364,7 @@ impl From<PaymentIntentUpdate> for diesel_models::PaymentIntentUpdateInternal {
} => Self {
status: Some(status),
active_attempt_id: Some(active_attempt_id),
prerouting_algorithm: None,
modified_at: common_utils::date_time::now(),
amount: None,
currency: None,
Expand Down Expand Up @@ -395,6 +401,7 @@ impl From<PaymentIntentUpdate> for diesel_models::PaymentIntentUpdateInternal {
PaymentIntentUpdate::ConfirmIntentPostUpdate { status, updated_by } => Self {
status: Some(status),
active_attempt_id: None,
prerouting_algorithm: None,
modified_at: common_utils::date_time::now(),
amount: None,
currency: None,
Expand Down Expand Up @@ -430,7 +437,47 @@ impl From<PaymentIntentUpdate> for diesel_models::PaymentIntentUpdateInternal {
PaymentIntentUpdate::SyncUpdate { status, updated_by } => Self {
status: Some(status),
active_attempt_id: None,
prerouting_algorithm: None,
modified_at: common_utils::date_time::now(),
amount: None,
currency: None,
shipping_cost: None,
tax_details: None,
skip_external_tax_calculation: None,
surcharge_applicable: None,
surcharge_amount: None,
tax_on_surcharge: None,
routing_algorithm_id: None,
capture_method: None,
authentication_type: None,
billing_address: None,
shipping_address: None,
customer_present: None,
description: None,
return_url: None,
setup_future_usage: None,
apply_mit_exemption: None,
statement_descriptor: None,
order_details: None,
allowed_payment_method_types: None,
metadata: None,
connector_metadata: None,
feature_metadata: None,
payment_link_config: None,
request_incremental_authorization: None,
session_expiry: None,
frm_metadata: None,
request_external_three_ds_authentication: None,
updated_by,
},
PaymentIntentUpdate::SessionIntentUpdate {
prerouting_algorithm,
updated_by,
} => Self {
status: None,
active_attempt_id: None,
modified_at: common_utils::date_time::now(),
prerouting_algorithm: Some(prerouting_algorithm),
amount: None,
currency: None,
shipping_cost: None,
Expand Down Expand Up @@ -498,6 +545,7 @@ impl From<PaymentIntentUpdate> for diesel_models::PaymentIntentUpdateInternal {
Self {
status: None,
active_attempt_id: None,
prerouting_algorithm: None,
modified_at: common_utils::date_time::now(),

amount,
Expand Down
21 changes: 21 additions & 0 deletions crates/router/src/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use std::collections::HashSet;

use common_utils::consts;
pub use hyperswitch_interfaces::consts::{NO_ERROR_CODE, NO_ERROR_MESSAGE};
use once_cell::sync::Lazy;
// ID generation
pub(crate) const ID_LENGTH: usize = 20;
pub(crate) const MAX_ID_LENGTH: usize = 64;
Expand Down Expand Up @@ -173,6 +174,26 @@ pub const DEFAULT_PRODUCT_IMG: &str =
/// Default SDK Layout
pub const DEFAULT_SDK_LAYOUT: &str = "tabs";

pub static ROUTING_ENABLED_PAYMENT_METHODS: Lazy<HashSet<common_enums::PaymentMethod>> =
Lazy::new(|| {
let mut set = HashSet::new();
set.insert(common_enums::PaymentMethod::BankTransfer);
set.insert(common_enums::PaymentMethod::BankDebit);
set.insert(common_enums::PaymentMethod::BankRedirect);
set
});

pub static ROUTING_ENABLED_PAYMENT_METHOD_TYPES: Lazy<HashSet<common_enums::PaymentMethodType>> =
Lazy::new(|| {
let mut set = HashSet::new();
set.insert(common_enums::PaymentMethodType::GooglePay);
set.insert(common_enums::PaymentMethodType::ApplePay);
set.insert(common_enums::PaymentMethodType::Klarna);
set.insert(common_enums::PaymentMethodType::Paypal);
set.insert(common_enums::PaymentMethodType::SamsungPay);
set
});

/// Vault Add request url
#[cfg(all(feature = "v2", feature = "payment_methods_v2"))]
pub const ADD_VAULT_REQUEST_URL: &str = "/vault/add";
Expand Down
3 changes: 1 addition & 2 deletions crates/router/src/core/admin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1792,7 +1792,6 @@ impl<'a> PMAuthConfigValidation<'a> {
for conn_choice in config.enabled_payment_methods {
let pm_auth_mca = all_mcas
.clone()
.into_iter()
.find(|mca| mca.get_id() == conn_choice.mca_id)
.ok_or(errors::ApiErrorResponse::GenericNotFoundError {
message: "payment method auth connector account not found".to_string(),
Expand Down Expand Up @@ -2953,7 +2952,7 @@ async fn validate_pm_auth(
})
.attach_printable("Failed to deserialize Payment Method Auth config")?;

let all_mcas = &*state
let all_mcas = state
.store
.find_merchant_connector_account_by_merchant_id_and_disabled_list(
&state.into(),
Expand Down
4 changes: 1 addition & 3 deletions crates/router/src/core/payment_methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1561,10 +1561,8 @@ pub async fn list_customer_payment_method(
.await
.change_context(errors::ApiErrorResponse::MerchantAccountNotFound)?
} else {
Vec::new()
domain::MerchantConnectorAccounts::new(Vec::new())
};
let merchant_connector_accounts =
domain::MerchantConnectorAccounts::new(merchant_connector_accounts);

let pm_list_futures = filtered_saved_payment_methods_ctx
.into_iter()
Expand Down
40 changes: 15 additions & 25 deletions crates/router/src/core/payment_methods/cards.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ use crate::{
defaults::{get_billing_required_fields, get_shipping_required_fields},
settings,
},
consts as router_consts,
core::{
errors::{self, StorageErrorExt},
payment_methods::{
Expand All @@ -104,8 +105,8 @@ use crate::{
};
#[cfg(all(feature = "v2", feature = "payment_methods_v2"))]
use crate::{
consts as router_consts, core::payment_methods as pm_core, headers,
types::payment_methods as pm_types, utils::ConnectorResponseExt,
core::payment_methods as pm_core, headers, types::payment_methods as pm_types,
utils::ConnectorResponseExt,
};
#[cfg(all(
any(feature = "v1", feature = "v2"),
Expand Down Expand Up @@ -3368,11 +3369,9 @@ pub async fn list_payment_methods(
})?;

// filter out payment connectors based on profile_id
let filtered_mcas = helpers::filter_mca_based_on_profile_and_connector_type(
all_mcas.clone(),
&profile_id,
ConnectorType::PaymentProcessor,
);
let filtered_mcas = all_mcas
.clone()
.filter_based_on_profile_and_connector_type(&profile_id, ConnectorType::PaymentProcessor);

logger::debug!(mca_before_filtering=?filtered_mcas);

Expand Down Expand Up @@ -3529,19 +3528,9 @@ pub async fn list_payment_methods(
if let Some((payment_attempt, payment_intent)) =
payment_attempt.as_ref().zip(payment_intent.as_ref())
{
let routing_enabled_pms = HashSet::from([
api_enums::PaymentMethod::BankTransfer,
api_enums::PaymentMethod::BankDebit,
api_enums::PaymentMethod::BankRedirect,
]);

let routing_enabled_pm_types = HashSet::from([
api_enums::PaymentMethodType::GooglePay,
api_enums::PaymentMethodType::ApplePay,
api_enums::PaymentMethodType::Klarna,
api_enums::PaymentMethodType::Paypal,
api_enums::PaymentMethodType::SamsungPay,
]);
let routing_enabled_pms = &router_consts::ROUTING_ENABLED_PAYMENT_METHODS;

let routing_enabled_pm_types = &router_consts::ROUTING_ENABLED_PAYMENT_METHOD_TYPES;

let mut chosen = Vec::<api::SessionConnectorData>::new();
for intermediate in &response {
Expand All @@ -3558,7 +3547,8 @@ pub async fn list_payment_methods(
.attach_printable("invalid connector name received")?;

chosen.push(api::SessionConnectorData {
payment_method_type: intermediate.payment_method_type,
payment_method_sub_type: intermediate.payment_method_type,
payment_method_type: intermediate.payment_method,
connector: connector_data,
business_sub_label: None,
});
Expand Down Expand Up @@ -5244,13 +5234,13 @@ pub async fn get_mca_status(
.change_context(errors::ApiErrorResponse::MerchantConnectorAccountNotFound {
id: merchant_id.get_string_repr().to_owned(),
})?;
let merchant_connector_accounts = domain::MerchantConnectorAccounts::new(mcas);

return Ok(merchant_connector_accounts
.is_merchant_connector_account_id_in_connector_mandate_details(
return Ok(
mcas.is_merchant_connector_account_id_in_connector_mandate_details(
profile_id.as_ref(),
&connector_mandate_details,
));
),
);
}
Ok(false)
}
Expand Down
Loading
Loading