Skip to content

Commit f8618e0

Browse files
feat: add support for 3ds and surcharge decision through routing rules (#2869)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
1 parent 3f3b797 commit f8618e0

23 files changed

+1717
-58
lines changed
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
use common_utils::events;
2+
use euclid::{
3+
dssa::types::EuclidAnalysable,
4+
enums,
5+
frontend::{
6+
ast::Program,
7+
dir::{DirKeyKind, DirValue, EuclidDirFilter},
8+
},
9+
types::Metadata,
10+
};
11+
use serde::{Deserialize, Serialize};
12+
13+
#[derive(
14+
Clone,
15+
Debug,
16+
Hash,
17+
PartialEq,
18+
Eq,
19+
strum::Display,
20+
strum::EnumVariantNames,
21+
strum::EnumIter,
22+
strum::EnumString,
23+
Serialize,
24+
Deserialize,
25+
)]
26+
#[serde(rename_all = "snake_case")]
27+
#[strum(serialize_all = "snake_case")]
28+
pub enum AuthenticationType {
29+
ThreeDs,
30+
NoThreeDs,
31+
}
32+
impl AuthenticationType {
33+
pub fn to_dir_value(&self) -> DirValue {
34+
match self {
35+
Self::ThreeDs => DirValue::AuthenticationType(enums::AuthenticationType::ThreeDs),
36+
Self::NoThreeDs => DirValue::AuthenticationType(enums::AuthenticationType::NoThreeDs),
37+
}
38+
}
39+
}
40+
41+
impl EuclidAnalysable for AuthenticationType {
42+
fn get_dir_value_for_analysis(&self, rule_name: String) -> Vec<(DirValue, Metadata)> {
43+
let auth = self.to_string();
44+
45+
vec![(
46+
self.to_dir_value(),
47+
std::collections::HashMap::from_iter([(
48+
"AUTHENTICATION_TYPE".to_string(),
49+
serde_json::json!({
50+
"rule_name":rule_name,
51+
"Authentication_type": auth,
52+
}),
53+
)]),
54+
)]
55+
}
56+
}
57+
58+
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
59+
pub struct ConditionalConfigs {
60+
pub override_3ds: Option<AuthenticationType>,
61+
}
62+
impl EuclidDirFilter for ConditionalConfigs {
63+
const ALLOWED: &'static [DirKeyKind] = &[
64+
DirKeyKind::PaymentMethod,
65+
DirKeyKind::CardType,
66+
DirKeyKind::CardNetwork,
67+
DirKeyKind::MetaData,
68+
DirKeyKind::PaymentAmount,
69+
DirKeyKind::PaymentCurrency,
70+
DirKeyKind::CaptureMethod,
71+
DirKeyKind::BillingCountry,
72+
DirKeyKind::BusinessCountry,
73+
];
74+
}
75+
76+
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
77+
pub struct DecisionManagerRecord {
78+
pub name: String,
79+
pub program: Program<ConditionalConfigs>,
80+
pub created_at: i64,
81+
pub modified_at: i64,
82+
}
83+
impl events::ApiEventMetric for DecisionManagerRecord {
84+
fn get_api_event_type(&self) -> Option<events::ApiEventsType> {
85+
Some(events::ApiEventsType::Routing)
86+
}
87+
}
88+
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
89+
#[serde(deny_unknown_fields)]
90+
pub struct ConditionalConfigReq {
91+
pub name: Option<String>,
92+
pub algorithm: Option<Program<ConditionalConfigs>>,
93+
}
94+
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
95+
96+
pub struct DecisionManagerRequest {
97+
pub name: Option<String>,
98+
pub program: Option<Program<ConditionalConfigs>>,
99+
}
100+
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
101+
#[serde(untagged)]
102+
pub enum DecisionManager {
103+
DecisionManagerv0(ConditionalConfigReq),
104+
DecisionManagerv1(DecisionManagerRequest),
105+
}
106+
107+
impl events::ApiEventMetric for DecisionManager {
108+
fn get_api_event_type(&self) -> Option<events::ApiEventsType> {
109+
Some(events::ApiEventsType::Routing)
110+
}
111+
}
112+
113+
pub type DecisionManagerResponse = DecisionManagerRecord;

crates/api_models/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ pub mod analytics;
44
pub mod api_keys;
55
pub mod bank_accounts;
66
pub mod cards_info;
7+
pub mod conditional_configs;
78
pub mod customers;
89
pub mod disputes;
910
pub mod enums;
@@ -22,6 +23,7 @@ pub mod payments;
2223
pub mod payouts;
2324
pub mod refunds;
2425
pub mod routing;
26+
pub mod surcharge_decision_configs;
2527
pub mod user;
2628
pub mod verifications;
2729
pub mod webhooks;
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
use common_utils::{consts::SURCHARGE_PERCENTAGE_PRECISION_LENGTH, events, types::Percentage};
2+
use euclid::frontend::{
3+
ast::Program,
4+
dir::{DirKeyKind, EuclidDirFilter},
5+
};
6+
use serde::{Deserialize, Serialize};
7+
8+
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
9+
#[serde(rename_all = "snake_case")]
10+
pub struct SurchargeDetails {
11+
pub surcharge: Surcharge,
12+
pub tax_on_surcharge: Option<Percentage<SURCHARGE_PERCENTAGE_PRECISION_LENGTH>>,
13+
}
14+
15+
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
16+
#[serde(rename_all = "snake_case", tag = "type", content = "value")]
17+
pub enum Surcharge {
18+
Fixed(i64),
19+
Rate(Percentage<SURCHARGE_PERCENTAGE_PRECISION_LENGTH>),
20+
}
21+
22+
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
23+
pub struct SurchargeDecisionConfigs {
24+
pub surcharge_details: Option<SurchargeDetails>,
25+
}
26+
impl EuclidDirFilter for SurchargeDecisionConfigs {
27+
const ALLOWED: &'static [DirKeyKind] = &[
28+
DirKeyKind::PaymentMethod,
29+
DirKeyKind::MetaData,
30+
DirKeyKind::PaymentAmount,
31+
DirKeyKind::PaymentCurrency,
32+
DirKeyKind::BillingCountry,
33+
DirKeyKind::CardType,
34+
DirKeyKind::CardNetwork,
35+
DirKeyKind::PayLaterType,
36+
DirKeyKind::WalletType,
37+
DirKeyKind::BankTransferType,
38+
DirKeyKind::BankRedirectType,
39+
DirKeyKind::BankDebitType,
40+
DirKeyKind::CryptoType,
41+
];
42+
}
43+
44+
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
45+
pub struct SurchargeDecisionManagerRecord {
46+
pub name: String,
47+
pub merchant_surcharge_configs: MerchantSurchargeConfigs,
48+
pub algorithm: Program<SurchargeDecisionConfigs>,
49+
pub created_at: i64,
50+
pub modified_at: i64,
51+
}
52+
53+
impl events::ApiEventMetric for SurchargeDecisionManagerRecord {
54+
fn get_api_event_type(&self) -> Option<events::ApiEventsType> {
55+
Some(events::ApiEventsType::Routing)
56+
}
57+
}
58+
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
59+
#[serde(deny_unknown_fields)]
60+
pub struct SurchargeDecisionConfigReq {
61+
pub name: Option<String>,
62+
pub merchant_surcharge_configs: MerchantSurchargeConfigs,
63+
pub algorithm: Option<Program<SurchargeDecisionConfigs>>,
64+
}
65+
66+
impl events::ApiEventMetric for SurchargeDecisionConfigReq {
67+
fn get_api_event_type(&self) -> Option<events::ApiEventsType> {
68+
Some(events::ApiEventsType::Routing)
69+
}
70+
}
71+
72+
#[derive(Debug, Default, Clone, serde::Serialize, serde::Deserialize)]
73+
pub struct MerchantSurchargeConfigs {
74+
pub show_surcharge_breakup_screen: Option<bool>,
75+
}
76+
77+
pub type SurchargeDecisionManagerResponse = SurchargeDecisionManagerRecord;

crates/router/src/core.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ pub mod api_keys;
33
pub mod api_locking;
44
pub mod cache;
55
pub mod cards_info;
6+
pub mod conditional_config;
67
pub mod configs;
78
pub mod customers;
89
pub mod disputes;
@@ -19,6 +20,7 @@ pub mod payments;
1920
pub mod payouts;
2021
pub mod refunds;
2122
pub mod routing;
23+
pub mod surcharge_decision_config;
2224
#[cfg(feature = "olap")]
2325
pub mod user;
2426
pub mod utils;

0 commit comments

Comments
 (0)