mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-27 19:46:48 +08:00
feat(core): Implement 3ds decision manger for V2 (#7022)
This commit is contained in:
1
.github/CODEOWNERS
vendored
1
.github/CODEOWNERS
vendored
@ -18,6 +18,7 @@ crates/router/src/services/ @juspay/hyperswitch-framework
|
|||||||
crates/router/src/db/ @juspay/hyperswitch-framework
|
crates/router/src/db/ @juspay/hyperswitch-framework
|
||||||
crates/router/src/routes/ @juspay/hyperswitch-framework
|
crates/router/src/routes/ @juspay/hyperswitch-framework
|
||||||
migrations/ @juspay/hyperswitch-framework
|
migrations/ @juspay/hyperswitch-framework
|
||||||
|
v2_migrations/ @juspay/hyperswitch-framework
|
||||||
api-reference/ @juspay/hyperswitch-framework
|
api-reference/ @juspay/hyperswitch-framework
|
||||||
api-reference-v2/ @juspay/hyperswitch-framework
|
api-reference-v2/ @juspay/hyperswitch-framework
|
||||||
Cargo.toml @juspay/hyperswitch-framework
|
Cargo.toml @juspay/hyperswitch-framework
|
||||||
|
|||||||
3
Cargo.lock
generated
3
Cargo.lock
generated
@ -2039,8 +2039,10 @@ dependencies = [
|
|||||||
"common_enums",
|
"common_enums",
|
||||||
"common_utils",
|
"common_utils",
|
||||||
"diesel",
|
"diesel",
|
||||||
|
"euclid",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"strum 0.26.3",
|
||||||
"utoipa",
|
"utoipa",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -3067,6 +3069,7 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"api_models",
|
"api_models",
|
||||||
"common_enums",
|
"common_enums",
|
||||||
|
"common_types",
|
||||||
"connector_configs",
|
"connector_configs",
|
||||||
"currency_conversion",
|
"currency_conversion",
|
||||||
"euclid",
|
"euclid",
|
||||||
|
|||||||
@ -1,82 +1,10 @@
|
|||||||
use common_utils::events;
|
use common_utils::events;
|
||||||
use euclid::{
|
use euclid::frontend::ast::Program;
|
||||||
dssa::types::EuclidAnalysable,
|
|
||||||
enums,
|
|
||||||
frontend::{
|
|
||||||
ast::Program,
|
|
||||||
dir::{DirKeyKind, DirValue, EuclidDirFilter},
|
|
||||||
},
|
|
||||||
types::Metadata,
|
|
||||||
};
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
#[derive(
|
|
||||||
Clone,
|
|
||||||
Debug,
|
|
||||||
Hash,
|
|
||||||
PartialEq,
|
|
||||||
Eq,
|
|
||||||
strum::Display,
|
|
||||||
strum::VariantNames,
|
|
||||||
strum::EnumIter,
|
|
||||||
strum::EnumString,
|
|
||||||
Serialize,
|
|
||||||
Deserialize,
|
|
||||||
)]
|
|
||||||
#[serde(rename_all = "snake_case")]
|
|
||||||
#[strum(serialize_all = "snake_case")]
|
|
||||||
pub enum AuthenticationType {
|
|
||||||
ThreeDs,
|
|
||||||
NoThreeDs,
|
|
||||||
}
|
|
||||||
impl AuthenticationType {
|
|
||||||
pub fn to_dir_value(&self) -> DirValue {
|
|
||||||
match self {
|
|
||||||
Self::ThreeDs => DirValue::AuthenticationType(enums::AuthenticationType::ThreeDs),
|
|
||||||
Self::NoThreeDs => DirValue::AuthenticationType(enums::AuthenticationType::NoThreeDs),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl EuclidAnalysable for AuthenticationType {
|
|
||||||
fn get_dir_value_for_analysis(&self, rule_name: String) -> Vec<(DirValue, Metadata)> {
|
|
||||||
let auth = self.to_string();
|
|
||||||
|
|
||||||
vec![(
|
|
||||||
self.to_dir_value(),
|
|
||||||
std::collections::HashMap::from_iter([(
|
|
||||||
"AUTHENTICATION_TYPE".to_string(),
|
|
||||||
serde_json::json!({
|
|
||||||
"rule_name":rule_name,
|
|
||||||
"Authentication_type": auth,
|
|
||||||
}),
|
|
||||||
)]),
|
|
||||||
)]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
|
||||||
pub struct ConditionalConfigs {
|
|
||||||
pub override_3ds: Option<AuthenticationType>,
|
|
||||||
}
|
|
||||||
impl EuclidDirFilter for ConditionalConfigs {
|
|
||||||
const ALLOWED: &'static [DirKeyKind] = &[
|
|
||||||
DirKeyKind::PaymentMethod,
|
|
||||||
DirKeyKind::CardType,
|
|
||||||
DirKeyKind::CardNetwork,
|
|
||||||
DirKeyKind::MetaData,
|
|
||||||
DirKeyKind::PaymentAmount,
|
|
||||||
DirKeyKind::PaymentCurrency,
|
|
||||||
DirKeyKind::CaptureMethod,
|
|
||||||
DirKeyKind::BillingCountry,
|
|
||||||
DirKeyKind::BusinessCountry,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||||||
pub struct DecisionManagerRecord {
|
pub struct DecisionManagerRecord {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub program: Program<ConditionalConfigs>,
|
pub program: Program<common_types::payments::ConditionalConfigs>,
|
||||||
pub created_at: i64,
|
pub created_at: i64,
|
||||||
pub modified_at: i64,
|
pub modified_at: i64,
|
||||||
}
|
}
|
||||||
@ -89,12 +17,14 @@ impl events::ApiEventMetric for DecisionManagerRecord {
|
|||||||
#[serde(deny_unknown_fields)]
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct ConditionalConfigReq {
|
pub struct ConditionalConfigReq {
|
||||||
pub name: Option<String>,
|
pub name: Option<String>,
|
||||||
pub algorithm: Option<Program<ConditionalConfigs>>,
|
pub algorithm: Option<Program<common_types::payments::ConditionalConfigs>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "v1")]
|
||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||||||
pub struct DecisionManagerRequest {
|
pub struct DecisionManagerRequest {
|
||||||
pub name: Option<String>,
|
pub name: Option<String>,
|
||||||
pub program: Option<Program<ConditionalConfigs>>,
|
pub program: Option<Program<common_types::payments::ConditionalConfigs>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||||||
@ -111,3 +41,17 @@ impl events::ApiEventMetric for DecisionManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub type DecisionManagerResponse = DecisionManagerRecord;
|
pub type DecisionManagerResponse = DecisionManagerRecord;
|
||||||
|
|
||||||
|
#[cfg(feature = "v2")]
|
||||||
|
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||||||
|
pub struct DecisionManagerRequest {
|
||||||
|
pub name: String,
|
||||||
|
pub program: Program<common_types::payments::ConditionalConfigs>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "v2")]
|
||||||
|
impl events::ApiEventMetric for DecisionManagerRequest {
|
||||||
|
fn get_api_event_type(&self) -> Option<events::ApiEventsType> {
|
||||||
|
Some(events::ApiEventsType::Routing)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -15,10 +15,12 @@ v2 = ["common_utils/v2"]
|
|||||||
diesel = "2.2.3"
|
diesel = "2.2.3"
|
||||||
serde = { version = "1.0.197", features = ["derive"] }
|
serde = { version = "1.0.197", features = ["derive"] }
|
||||||
serde_json = "1.0.115"
|
serde_json = "1.0.115"
|
||||||
|
strum = { version = "0.26", features = ["derive"] }
|
||||||
utoipa = { version = "4.2.0", features = ["preserve_order", "preserve_path_order"] }
|
utoipa = { version = "4.2.0", features = ["preserve_order", "preserve_path_order"] }
|
||||||
|
|
||||||
common_enums = { version = "0.1.0", path = "../common_enums" }
|
common_enums = { version = "0.1.0", path = "../common_enums" }
|
||||||
common_utils = { version = "0.1.0", path = "../common_utils"}
|
common_utils = { version = "0.1.0", path = "../common_utils"}
|
||||||
|
euclid = { version = "0.1.0", path = "../euclid" }
|
||||||
|
|
||||||
[lints]
|
[lints]
|
||||||
workspace = true
|
workspace = true
|
||||||
|
|||||||
@ -3,8 +3,12 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use common_enums::enums;
|
use common_enums::enums;
|
||||||
use common_utils::{errors, impl_to_sql_from_sql_json, types::MinorUnit};
|
use common_utils::{errors, events, impl_to_sql_from_sql_json, types::MinorUnit};
|
||||||
use diesel::{sql_types::Jsonb, AsExpression, FromSqlRow};
|
use diesel::{sql_types::Jsonb, AsExpression, FromSqlRow};
|
||||||
|
use euclid::frontend::{
|
||||||
|
ast::Program,
|
||||||
|
dir::{DirKeyKind, EuclidDirFilter},
|
||||||
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use utoipa::ToSchema;
|
use utoipa::ToSchema;
|
||||||
|
|
||||||
@ -21,26 +25,6 @@ pub enum SplitPaymentsRequest {
|
|||||||
}
|
}
|
||||||
impl_to_sql_from_sql_json!(SplitPaymentsRequest);
|
impl_to_sql_from_sql_json!(SplitPaymentsRequest);
|
||||||
|
|
||||||
#[derive(
|
|
||||||
Serialize, Deserialize, Debug, Clone, PartialEq, Eq, FromSqlRow, AsExpression, ToSchema,
|
|
||||||
)]
|
|
||||||
#[diesel(sql_type = Jsonb)]
|
|
||||||
#[serde(deny_unknown_fields)]
|
|
||||||
/// Fee information for Split Payments to be charged on the payment being collected for Stripe
|
|
||||||
pub struct StripeSplitPaymentRequest {
|
|
||||||
/// Stripe's charge type
|
|
||||||
#[schema(value_type = PaymentChargeType, example = "direct")]
|
|
||||||
pub charge_type: enums::PaymentChargeType,
|
|
||||||
|
|
||||||
/// Platform fees to be collected on the payment
|
|
||||||
#[schema(value_type = i64, example = 6540)]
|
|
||||||
pub application_fees: MinorUnit,
|
|
||||||
|
|
||||||
/// Identifier for the reseller's account to send the funds to
|
|
||||||
pub transfer_account_id: String,
|
|
||||||
}
|
|
||||||
impl_to_sql_from_sql_json!(StripeSplitPaymentRequest);
|
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
Serialize, Deserialize, Debug, Clone, PartialEq, Eq, FromSqlRow, AsExpression, ToSchema,
|
Serialize, Deserialize, Debug, Clone, PartialEq, Eq, FromSqlRow, AsExpression, ToSchema,
|
||||||
)]
|
)]
|
||||||
@ -65,3 +49,70 @@ impl AuthenticationConnectorAccountMap {
|
|||||||
.cloned()
|
.cloned()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(
|
||||||
|
Serialize, Deserialize, Debug, Clone, PartialEq, Eq, FromSqlRow, AsExpression, ToSchema,
|
||||||
|
)]
|
||||||
|
#[diesel(sql_type = Jsonb)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
|
/// Fee information for Split Payments to be charged on the payment being collected for Stripe
|
||||||
|
pub struct StripeSplitPaymentRequest {
|
||||||
|
/// Stripe's charge type
|
||||||
|
#[schema(value_type = PaymentChargeType, example = "direct")]
|
||||||
|
pub charge_type: enums::PaymentChargeType,
|
||||||
|
|
||||||
|
/// Platform fees to be collected on the payment
|
||||||
|
#[schema(value_type = i64, example = 6540)]
|
||||||
|
pub application_fees: MinorUnit,
|
||||||
|
|
||||||
|
/// Identifier for the reseller's account to send the funds to
|
||||||
|
pub transfer_account_id: String,
|
||||||
|
}
|
||||||
|
impl_to_sql_from_sql_json!(StripeSplitPaymentRequest);
|
||||||
|
|
||||||
|
#[derive(
|
||||||
|
Serialize, Default, Deserialize, Debug, Clone, PartialEq, Eq, FromSqlRow, AsExpression, ToSchema,
|
||||||
|
)]
|
||||||
|
#[diesel(sql_type = Jsonb)]
|
||||||
|
/// ConditionalConfigs
|
||||||
|
pub struct ConditionalConfigs {
|
||||||
|
/// Override 3DS
|
||||||
|
pub override_3ds: Option<common_enums::AuthenticationType>,
|
||||||
|
}
|
||||||
|
impl EuclidDirFilter for ConditionalConfigs {
|
||||||
|
const ALLOWED: &'static [DirKeyKind] = &[
|
||||||
|
DirKeyKind::PaymentMethod,
|
||||||
|
DirKeyKind::CardType,
|
||||||
|
DirKeyKind::CardNetwork,
|
||||||
|
DirKeyKind::MetaData,
|
||||||
|
DirKeyKind::PaymentAmount,
|
||||||
|
DirKeyKind::PaymentCurrency,
|
||||||
|
DirKeyKind::CaptureMethod,
|
||||||
|
DirKeyKind::BillingCountry,
|
||||||
|
DirKeyKind::BusinessCountry,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_to_sql_from_sql_json!(ConditionalConfigs);
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone, FromSqlRow, AsExpression, ToSchema)]
|
||||||
|
#[diesel(sql_type = Jsonb)]
|
||||||
|
/// DecisionManagerRecord
|
||||||
|
pub struct DecisionManagerRecord {
|
||||||
|
/// Name of the Decision Manager
|
||||||
|
pub name: String,
|
||||||
|
/// Program to be executed
|
||||||
|
pub program: Program<ConditionalConfigs>,
|
||||||
|
/// Created at timestamp
|
||||||
|
pub created_at: i64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl events::ApiEventMetric for DecisionManagerRecord {
|
||||||
|
fn get_api_event_type(&self) -> Option<events::ApiEventsType> {
|
||||||
|
Some(events::ApiEventsType::Routing)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl_to_sql_from_sql_json!(DecisionManagerRecord);
|
||||||
|
|
||||||
|
/// DecisionManagerResponse
|
||||||
|
pub type DecisionManagerResponse = DecisionManagerRecord;
|
||||||
|
|||||||
@ -310,6 +310,7 @@ pub struct Profile {
|
|||||||
pub is_click_to_pay_enabled: bool,
|
pub is_click_to_pay_enabled: bool,
|
||||||
pub authentication_product_ids:
|
pub authentication_product_ids:
|
||||||
Option<common_types::payments::AuthenticationConnectorAccountMap>,
|
Option<common_types::payments::AuthenticationConnectorAccountMap>,
|
||||||
|
pub three_ds_decision_manager_config: Option<common_types::payments::DecisionManagerRecord>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Profile {
|
impl Profile {
|
||||||
@ -371,6 +372,7 @@ pub struct ProfileNew {
|
|||||||
pub is_click_to_pay_enabled: bool,
|
pub is_click_to_pay_enabled: bool,
|
||||||
pub authentication_product_ids:
|
pub authentication_product_ids:
|
||||||
Option<common_types::payments::AuthenticationConnectorAccountMap>,
|
Option<common_types::payments::AuthenticationConnectorAccountMap>,
|
||||||
|
pub three_ds_decision_manager_config: Option<common_types::payments::DecisionManagerRecord>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "v2")]
|
#[cfg(feature = "v2")]
|
||||||
@ -416,6 +418,7 @@ pub struct ProfileUpdateInternal {
|
|||||||
pub is_click_to_pay_enabled: Option<bool>,
|
pub is_click_to_pay_enabled: Option<bool>,
|
||||||
pub authentication_product_ids:
|
pub authentication_product_ids:
|
||||||
Option<common_types::payments::AuthenticationConnectorAccountMap>,
|
Option<common_types::payments::AuthenticationConnectorAccountMap>,
|
||||||
|
pub three_ds_decision_manager_config: Option<common_types::payments::DecisionManagerRecord>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "v2")]
|
#[cfg(feature = "v2")]
|
||||||
@ -459,6 +462,7 @@ impl ProfileUpdateInternal {
|
|||||||
max_auto_retries_enabled,
|
max_auto_retries_enabled,
|
||||||
is_click_to_pay_enabled,
|
is_click_to_pay_enabled,
|
||||||
authentication_product_ids,
|
authentication_product_ids,
|
||||||
|
three_ds_decision_manager_config,
|
||||||
} = self;
|
} = self;
|
||||||
Profile {
|
Profile {
|
||||||
id: source.id,
|
id: source.id,
|
||||||
@ -527,6 +531,8 @@ impl ProfileUpdateInternal {
|
|||||||
.unwrap_or(source.is_click_to_pay_enabled),
|
.unwrap_or(source.is_click_to_pay_enabled),
|
||||||
authentication_product_ids: authentication_product_ids
|
authentication_product_ids: authentication_product_ids
|
||||||
.or(source.authentication_product_ids),
|
.or(source.authentication_product_ids),
|
||||||
|
three_ds_decision_manager_config: three_ds_decision_manager_config
|
||||||
|
.or(source.three_ds_decision_manager_config),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -224,6 +224,7 @@ diesel::table! {
|
|||||||
max_auto_retries_enabled -> Nullable<Int2>,
|
max_auto_retries_enabled -> Nullable<Int2>,
|
||||||
is_click_to_pay_enabled -> Bool,
|
is_click_to_pay_enabled -> Bool,
|
||||||
authentication_product_ids -> Nullable<Jsonb>,
|
authentication_product_ids -> Nullable<Jsonb>,
|
||||||
|
three_ds_decision_manager_config -> Nullable<Jsonb>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
use std::fmt;
|
use std::{collections::HashMap, fmt};
|
||||||
|
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
@ -159,3 +159,25 @@ pub enum ValueType {
|
|||||||
EnumVariants(Vec<EuclidValue>),
|
EnumVariants(Vec<EuclidValue>),
|
||||||
Number,
|
Number,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl EuclidAnalysable for common_enums::AuthenticationType {
|
||||||
|
fn get_dir_value_for_analysis(&self, rule_name: String) -> Vec<(dir::DirValue, Metadata)> {
|
||||||
|
let auth = self.to_string();
|
||||||
|
|
||||||
|
let dir_value = match self {
|
||||||
|
Self::ThreeDs => dir::DirValue::AuthenticationType(Self::ThreeDs),
|
||||||
|
Self::NoThreeDs => dir::DirValue::AuthenticationType(Self::NoThreeDs),
|
||||||
|
};
|
||||||
|
|
||||||
|
vec![(
|
||||||
|
dir_value,
|
||||||
|
HashMap::from_iter([(
|
||||||
|
"AUTHENTICATION_TYPE".to_string(),
|
||||||
|
serde_json::json!({
|
||||||
|
"rule_name": rule_name,
|
||||||
|
"Authentication_type": auth,
|
||||||
|
}),
|
||||||
|
)]),
|
||||||
|
)]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -22,6 +22,7 @@ v2 = []
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
api_models = { version = "0.1.0", path = "../api_models", package = "api_models" }
|
api_models = { version = "0.1.0", path = "../api_models", package = "api_models" }
|
||||||
common_enums = { version = "0.1.0", path = "../common_enums" }
|
common_enums = { version = "0.1.0", path = "../common_enums" }
|
||||||
|
common_types = { version = "0.1.0", path = "../common_types" }
|
||||||
connector_configs = { version = "0.1.0", path = "../connector_configs" }
|
connector_configs = { version = "0.1.0", path = "../connector_configs" }
|
||||||
currency_conversion = { version = "0.1.0", path = "../currency_conversion" }
|
currency_conversion = { version = "0.1.0", path = "../currency_conversion" }
|
||||||
euclid = { version = "0.1.0", path = "../euclid", features = [] }
|
euclid = { version = "0.1.0", path = "../euclid", features = [] }
|
||||||
|
|||||||
@ -7,7 +7,7 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use api_models::{
|
use api_models::{
|
||||||
conditional_configs::ConditionalConfigs, enums as api_model_enums, routing::ConnectorSelection,
|
enums as api_model_enums, routing::ConnectorSelection,
|
||||||
surcharge_decision_configs::SurchargeDecisionConfigs,
|
surcharge_decision_configs::SurchargeDecisionConfigs,
|
||||||
};
|
};
|
||||||
use common_enums::RoutableConnectors;
|
use common_enums::RoutableConnectors;
|
||||||
@ -221,7 +221,7 @@ pub fn get_key_type(key: &str) -> Result<String, String> {
|
|||||||
|
|
||||||
#[wasm_bindgen(js_name = getThreeDsKeys)]
|
#[wasm_bindgen(js_name = getThreeDsKeys)]
|
||||||
pub fn get_three_ds_keys() -> JsResult {
|
pub fn get_three_ds_keys() -> JsResult {
|
||||||
let keys = <ConditionalConfigs as EuclidDirFilter>::ALLOWED;
|
let keys = <common_types::payments::ConditionalConfigs as EuclidDirFilter>::ALLOWED;
|
||||||
Ok(serde_wasm_bindgen::to_value(keys)?)
|
Ok(serde_wasm_bindgen::to_value(keys)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -734,6 +734,7 @@ pub struct Profile {
|
|||||||
pub is_click_to_pay_enabled: bool,
|
pub is_click_to_pay_enabled: bool,
|
||||||
pub authentication_product_ids:
|
pub authentication_product_ids:
|
||||||
Option<common_types::payments::AuthenticationConnectorAccountMap>,
|
Option<common_types::payments::AuthenticationConnectorAccountMap>,
|
||||||
|
pub three_ds_decision_manager_config: Option<common_types::payments::DecisionManagerRecord>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "v2")]
|
#[cfg(feature = "v2")]
|
||||||
@ -777,6 +778,7 @@ pub struct ProfileSetter {
|
|||||||
pub is_click_to_pay_enabled: bool,
|
pub is_click_to_pay_enabled: bool,
|
||||||
pub authentication_product_ids:
|
pub authentication_product_ids:
|
||||||
Option<common_types::payments::AuthenticationConnectorAccountMap>,
|
Option<common_types::payments::AuthenticationConnectorAccountMap>,
|
||||||
|
pub three_ds_decision_manager_config: Option<common_types::payments::DecisionManagerRecord>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "v2")]
|
#[cfg(feature = "v2")]
|
||||||
@ -826,6 +828,7 @@ impl From<ProfileSetter> for Profile {
|
|||||||
is_network_tokenization_enabled: value.is_network_tokenization_enabled,
|
is_network_tokenization_enabled: value.is_network_tokenization_enabled,
|
||||||
is_click_to_pay_enabled: value.is_click_to_pay_enabled,
|
is_click_to_pay_enabled: value.is_click_to_pay_enabled,
|
||||||
authentication_product_ids: value.authentication_product_ids,
|
authentication_product_ids: value.authentication_product_ids,
|
||||||
|
three_ds_decision_manager_config: value.three_ds_decision_manager_config,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -879,6 +882,7 @@ pub struct ProfileGeneralUpdate {
|
|||||||
pub is_click_to_pay_enabled: Option<bool>,
|
pub is_click_to_pay_enabled: Option<bool>,
|
||||||
pub authentication_product_ids:
|
pub authentication_product_ids:
|
||||||
Option<common_types::payments::AuthenticationConnectorAccountMap>,
|
Option<common_types::payments::AuthenticationConnectorAccountMap>,
|
||||||
|
pub three_ds_decision_manager_config: Option<common_types::payments::DecisionManagerRecord>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "v2")]
|
#[cfg(feature = "v2")]
|
||||||
@ -904,6 +908,9 @@ pub enum ProfileUpdate {
|
|||||||
CollectCvvDuringPaymentUpdate {
|
CollectCvvDuringPaymentUpdate {
|
||||||
should_collect_cvv_during_payment: bool,
|
should_collect_cvv_during_payment: bool,
|
||||||
},
|
},
|
||||||
|
DecisionManagerRecordUpdate {
|
||||||
|
three_ds_decision_manager_config: common_types::payments::DecisionManagerRecord,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "v2")]
|
#[cfg(feature = "v2")]
|
||||||
@ -939,6 +946,7 @@ impl From<ProfileUpdate> for ProfileUpdateInternal {
|
|||||||
is_network_tokenization_enabled,
|
is_network_tokenization_enabled,
|
||||||
is_click_to_pay_enabled,
|
is_click_to_pay_enabled,
|
||||||
authentication_product_ids,
|
authentication_product_ids,
|
||||||
|
three_ds_decision_manager_config,
|
||||||
} = *update;
|
} = *update;
|
||||||
Self {
|
Self {
|
||||||
profile_name,
|
profile_name,
|
||||||
@ -979,6 +987,7 @@ impl From<ProfileUpdate> for ProfileUpdateInternal {
|
|||||||
max_auto_retries_enabled: None,
|
max_auto_retries_enabled: None,
|
||||||
is_click_to_pay_enabled: None,
|
is_click_to_pay_enabled: None,
|
||||||
authentication_product_ids,
|
authentication_product_ids,
|
||||||
|
three_ds_decision_manager_config,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ProfileUpdate::RoutingAlgorithmUpdate {
|
ProfileUpdate::RoutingAlgorithmUpdate {
|
||||||
@ -1022,6 +1031,7 @@ impl From<ProfileUpdate> for ProfileUpdateInternal {
|
|||||||
max_auto_retries_enabled: None,
|
max_auto_retries_enabled: None,
|
||||||
is_click_to_pay_enabled: None,
|
is_click_to_pay_enabled: None,
|
||||||
authentication_product_ids: None,
|
authentication_product_ids: None,
|
||||||
|
three_ds_decision_manager_config: None,
|
||||||
},
|
},
|
||||||
ProfileUpdate::ExtendedCardInfoUpdate {
|
ProfileUpdate::ExtendedCardInfoUpdate {
|
||||||
is_extended_card_info_enabled,
|
is_extended_card_info_enabled,
|
||||||
@ -1063,6 +1073,7 @@ impl From<ProfileUpdate> for ProfileUpdateInternal {
|
|||||||
max_auto_retries_enabled: None,
|
max_auto_retries_enabled: None,
|
||||||
is_click_to_pay_enabled: None,
|
is_click_to_pay_enabled: None,
|
||||||
authentication_product_ids: None,
|
authentication_product_ids: None,
|
||||||
|
three_ds_decision_manager_config: None,
|
||||||
},
|
},
|
||||||
ProfileUpdate::ConnectorAgnosticMitUpdate {
|
ProfileUpdate::ConnectorAgnosticMitUpdate {
|
||||||
is_connector_agnostic_mit_enabled,
|
is_connector_agnostic_mit_enabled,
|
||||||
@ -1104,6 +1115,7 @@ impl From<ProfileUpdate> for ProfileUpdateInternal {
|
|||||||
max_auto_retries_enabled: None,
|
max_auto_retries_enabled: None,
|
||||||
is_click_to_pay_enabled: None,
|
is_click_to_pay_enabled: None,
|
||||||
authentication_product_ids: None,
|
authentication_product_ids: None,
|
||||||
|
three_ds_decision_manager_config: None,
|
||||||
},
|
},
|
||||||
ProfileUpdate::DefaultRoutingFallbackUpdate {
|
ProfileUpdate::DefaultRoutingFallbackUpdate {
|
||||||
default_fallback_routing,
|
default_fallback_routing,
|
||||||
@ -1145,6 +1157,7 @@ impl From<ProfileUpdate> for ProfileUpdateInternal {
|
|||||||
max_auto_retries_enabled: None,
|
max_auto_retries_enabled: None,
|
||||||
is_click_to_pay_enabled: None,
|
is_click_to_pay_enabled: None,
|
||||||
authentication_product_ids: None,
|
authentication_product_ids: None,
|
||||||
|
three_ds_decision_manager_config: None,
|
||||||
},
|
},
|
||||||
ProfileUpdate::NetworkTokenizationUpdate {
|
ProfileUpdate::NetworkTokenizationUpdate {
|
||||||
is_network_tokenization_enabled,
|
is_network_tokenization_enabled,
|
||||||
@ -1186,6 +1199,7 @@ impl From<ProfileUpdate> for ProfileUpdateInternal {
|
|||||||
max_auto_retries_enabled: None,
|
max_auto_retries_enabled: None,
|
||||||
is_click_to_pay_enabled: None,
|
is_click_to_pay_enabled: None,
|
||||||
authentication_product_ids: None,
|
authentication_product_ids: None,
|
||||||
|
three_ds_decision_manager_config: None,
|
||||||
},
|
},
|
||||||
ProfileUpdate::CollectCvvDuringPaymentUpdate {
|
ProfileUpdate::CollectCvvDuringPaymentUpdate {
|
||||||
should_collect_cvv_during_payment,
|
should_collect_cvv_during_payment,
|
||||||
@ -1227,6 +1241,49 @@ impl From<ProfileUpdate> for ProfileUpdateInternal {
|
|||||||
max_auto_retries_enabled: None,
|
max_auto_retries_enabled: None,
|
||||||
is_click_to_pay_enabled: None,
|
is_click_to_pay_enabled: None,
|
||||||
authentication_product_ids: None,
|
authentication_product_ids: None,
|
||||||
|
three_ds_decision_manager_config: None,
|
||||||
|
},
|
||||||
|
ProfileUpdate::DecisionManagerRecordUpdate {
|
||||||
|
three_ds_decision_manager_config,
|
||||||
|
} => Self {
|
||||||
|
profile_name: None,
|
||||||
|
modified_at: now,
|
||||||
|
return_url: None,
|
||||||
|
enable_payment_response_hash: None,
|
||||||
|
payment_response_hash_key: None,
|
||||||
|
redirect_to_merchant_with_http_post: None,
|
||||||
|
webhook_details: None,
|
||||||
|
metadata: None,
|
||||||
|
is_recon_enabled: None,
|
||||||
|
applepay_verified_domains: None,
|
||||||
|
payment_link_config: None,
|
||||||
|
session_expiry: None,
|
||||||
|
authentication_connector_details: None,
|
||||||
|
payout_link_config: None,
|
||||||
|
is_extended_card_info_enabled: None,
|
||||||
|
extended_card_info_config: None,
|
||||||
|
is_connector_agnostic_mit_enabled: None,
|
||||||
|
use_billing_as_payment_method_billing: None,
|
||||||
|
collect_shipping_details_from_wallet_connector: None,
|
||||||
|
collect_billing_details_from_wallet_connector: None,
|
||||||
|
outgoing_webhook_custom_http_headers: None,
|
||||||
|
always_collect_billing_details_from_wallet_connector: None,
|
||||||
|
always_collect_shipping_details_from_wallet_connector: None,
|
||||||
|
routing_algorithm_id: None,
|
||||||
|
payout_routing_algorithm_id: None,
|
||||||
|
order_fulfillment_time: None,
|
||||||
|
order_fulfillment_time_origin: None,
|
||||||
|
frm_routing_algorithm_id: None,
|
||||||
|
default_fallback_routing: None,
|
||||||
|
should_collect_cvv_during_payment: None,
|
||||||
|
tax_connector_id: None,
|
||||||
|
is_tax_connector_enabled: None,
|
||||||
|
is_network_tokenization_enabled: None,
|
||||||
|
is_auto_retries_enabled: None,
|
||||||
|
max_auto_retries_enabled: None,
|
||||||
|
is_click_to_pay_enabled: None,
|
||||||
|
authentication_product_ids: None,
|
||||||
|
three_ds_decision_manager_config: Some(three_ds_decision_manager_config),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1288,6 +1345,7 @@ impl super::behaviour::Conversion for Profile {
|
|||||||
max_auto_retries_enabled: None,
|
max_auto_retries_enabled: None,
|
||||||
is_click_to_pay_enabled: self.is_click_to_pay_enabled,
|
is_click_to_pay_enabled: self.is_click_to_pay_enabled,
|
||||||
authentication_product_ids: self.authentication_product_ids,
|
authentication_product_ids: self.authentication_product_ids,
|
||||||
|
three_ds_decision_manager_config: self.three_ds_decision_manager_config,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1358,6 +1416,7 @@ impl super::behaviour::Conversion for Profile {
|
|||||||
is_network_tokenization_enabled: item.is_network_tokenization_enabled,
|
is_network_tokenization_enabled: item.is_network_tokenization_enabled,
|
||||||
is_click_to_pay_enabled: item.is_click_to_pay_enabled,
|
is_click_to_pay_enabled: item.is_click_to_pay_enabled,
|
||||||
authentication_product_ids: item.authentication_product_ids,
|
authentication_product_ids: item.authentication_product_ids,
|
||||||
|
three_ds_decision_manager_config: item.three_ds_decision_manager_config,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
.await
|
.await
|
||||||
@ -1415,6 +1474,7 @@ impl super::behaviour::Conversion for Profile {
|
|||||||
max_auto_retries_enabled: None,
|
max_auto_retries_enabled: None,
|
||||||
is_click_to_pay_enabled: self.is_click_to_pay_enabled,
|
is_click_to_pay_enabled: self.is_click_to_pay_enabled,
|
||||||
authentication_product_ids: self.authentication_product_ids,
|
authentication_product_ids: self.authentication_product_ids,
|
||||||
|
three_ds_decision_manager_config: self.three_ds_decision_manager_config,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3798,6 +3798,7 @@ impl ProfileCreateBridge for api::ProfileCreate {
|
|||||||
is_network_tokenization_enabled: self.is_network_tokenization_enabled,
|
is_network_tokenization_enabled: self.is_network_tokenization_enabled,
|
||||||
is_click_to_pay_enabled: self.is_click_to_pay_enabled,
|
is_click_to_pay_enabled: self.is_click_to_pay_enabled,
|
||||||
authentication_product_ids: self.authentication_product_ids,
|
authentication_product_ids: self.authentication_product_ids,
|
||||||
|
three_ds_decision_manager_config: None,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4147,6 +4148,7 @@ impl ProfileUpdateBridge for api::ProfileUpdate {
|
|||||||
is_network_tokenization_enabled: self.is_network_tokenization_enabled,
|
is_network_tokenization_enabled: self.is_network_tokenization_enabled,
|
||||||
is_click_to_pay_enabled: self.is_click_to_pay_enabled,
|
is_click_to_pay_enabled: self.is_click_to_pay_enabled,
|
||||||
authentication_product_ids: self.authentication_product_ids,
|
authentication_product_ids: self.authentication_product_ids,
|
||||||
|
three_ds_decision_manager_config: None,
|
||||||
},
|
},
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,11 @@
|
|||||||
|
#[cfg(feature = "v2")]
|
||||||
|
use api_models::conditional_configs::DecisionManagerRequest;
|
||||||
use api_models::conditional_configs::{
|
use api_models::conditional_configs::{
|
||||||
DecisionManager, DecisionManagerRecord, DecisionManagerResponse,
|
DecisionManager, DecisionManagerRecord, DecisionManagerResponse,
|
||||||
};
|
};
|
||||||
use common_utils::ext_traits::StringExt;
|
use common_utils::ext_traits::StringExt;
|
||||||
|
#[cfg(feature = "v2")]
|
||||||
|
use common_utils::types::keymanager::KeyManagerState;
|
||||||
use error_stack::ResultExt;
|
use error_stack::ResultExt;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -10,15 +14,57 @@ use crate::{
|
|||||||
services::api as service_api,
|
services::api as service_api,
|
||||||
types::domain,
|
types::domain,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "v2")]
|
#[cfg(feature = "v2")]
|
||||||
pub async fn upsert_conditional_config(
|
pub async fn upsert_conditional_config(
|
||||||
_state: SessionState,
|
state: SessionState,
|
||||||
_key_store: domain::MerchantKeyStore,
|
key_store: domain::MerchantKeyStore,
|
||||||
_merchant_account: domain::MerchantAccount,
|
request: DecisionManagerRequest,
|
||||||
_request: DecisionManager,
|
profile: domain::Profile,
|
||||||
) -> RouterResponse<DecisionManagerRecord> {
|
) -> RouterResponse<common_types::payments::DecisionManagerRecord> {
|
||||||
todo!()
|
use common_utils::ext_traits::OptionExt;
|
||||||
|
|
||||||
|
let key_manager_state: &KeyManagerState = &(&state).into();
|
||||||
|
let db = &*state.store;
|
||||||
|
let name = request.name;
|
||||||
|
let program = request.program;
|
||||||
|
let timestamp = common_utils::date_time::now_unix_timestamp();
|
||||||
|
|
||||||
|
euclid::frontend::ast::lowering::lower_program(program.clone())
|
||||||
|
.change_context(errors::ApiErrorResponse::InvalidRequestData {
|
||||||
|
message: "Invalid Request Data".to_string(),
|
||||||
|
})
|
||||||
|
.attach_printable("The Request has an Invalid Comparison")?;
|
||||||
|
|
||||||
|
let decision_manager_record = common_types::payments::DecisionManagerRecord {
|
||||||
|
name,
|
||||||
|
program,
|
||||||
|
created_at: timestamp,
|
||||||
|
};
|
||||||
|
|
||||||
|
let business_profile_update = domain::ProfileUpdate::DecisionManagerRecordUpdate {
|
||||||
|
three_ds_decision_manager_config: decision_manager_record,
|
||||||
|
};
|
||||||
|
let updated_profile = db
|
||||||
|
.update_profile_by_profile_id(
|
||||||
|
key_manager_state,
|
||||||
|
&key_store,
|
||||||
|
profile,
|
||||||
|
business_profile_update,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||||
|
.attach_printable("Failed to update decision manager record in business profile")?;
|
||||||
|
|
||||||
|
Ok(service_api::ApplicationResponse::Json(
|
||||||
|
updated_profile
|
||||||
|
.three_ds_decision_manager_config
|
||||||
|
.clone()
|
||||||
|
.get_required_value("three_ds_decision_manager_config")
|
||||||
|
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||||
|
.attach_printable(
|
||||||
|
"Failed to get updated decision manager record in business profile",
|
||||||
|
)?,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "v1")]
|
#[cfg(feature = "v1")]
|
||||||
@ -204,6 +250,7 @@ pub async fn delete_conditional_config(
|
|||||||
Ok(service_api::ApplicationResponse::StatusOk)
|
Ok(service_api::ApplicationResponse::StatusOk)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "v1")]
|
||||||
pub async fn retrieve_conditional_config(
|
pub async fn retrieve_conditional_config(
|
||||||
state: SessionState,
|
state: SessionState,
|
||||||
merchant_account: domain::MerchantAccount,
|
merchant_account: domain::MerchantAccount,
|
||||||
@ -229,3 +276,27 @@ pub async fn retrieve_conditional_config(
|
|||||||
};
|
};
|
||||||
Ok(service_api::ApplicationResponse::Json(response))
|
Ok(service_api::ApplicationResponse::Json(response))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "v2")]
|
||||||
|
pub async fn retrieve_conditional_config(
|
||||||
|
state: SessionState,
|
||||||
|
key_store: domain::MerchantKeyStore,
|
||||||
|
profile: domain::Profile,
|
||||||
|
) -> RouterResponse<common_types::payments::DecisionManagerResponse> {
|
||||||
|
let db = state.store.as_ref();
|
||||||
|
let key_manager_state: &KeyManagerState = &(&state).into();
|
||||||
|
let profile_id = profile.get_id();
|
||||||
|
|
||||||
|
let record = profile
|
||||||
|
.three_ds_decision_manager_config
|
||||||
|
.clone()
|
||||||
|
.ok_or(errors::ApiErrorResponse::InternalServerError)
|
||||||
|
.attach_printable("The Conditional Config Record was not found")?;
|
||||||
|
|
||||||
|
let response = common_types::payments::DecisionManagerRecord {
|
||||||
|
name: record.name,
|
||||||
|
program: record.program,
|
||||||
|
created_at: record.created_at,
|
||||||
|
};
|
||||||
|
Ok(service_api::ApplicationResponse::Json(response))
|
||||||
|
}
|
||||||
|
|||||||
@ -109,7 +109,7 @@ use crate::{
|
|||||||
api::{self, ConnectorCallType, ConnectorCommon},
|
api::{self, ConnectorCallType, ConnectorCommon},
|
||||||
domain,
|
domain,
|
||||||
storage::{self, enums as storage_enums, payment_attempt::PaymentAttemptExt},
|
storage::{self, enums as storage_enums, payment_attempt::PaymentAttemptExt},
|
||||||
transformers::{ForeignInto, ForeignTryInto},
|
transformers::ForeignTryInto,
|
||||||
},
|
},
|
||||||
utils::{
|
utils::{
|
||||||
self, add_apple_pay_flow_metrics, add_connector_http_status_code_metrics, Encode,
|
self, add_apple_pay_flow_metrics, add_connector_http_status_code_metrics, Encode,
|
||||||
@ -1145,7 +1145,7 @@ where
|
|||||||
Ok(payment_dsl_data
|
Ok(payment_dsl_data
|
||||||
.payment_attempt
|
.payment_attempt
|
||||||
.authentication_type
|
.authentication_type
|
||||||
.or(output.override_3ds.map(ForeignInto::foreign_into))
|
.or(output.override_3ds)
|
||||||
.or(Some(storage_enums::AuthenticationType::NoThreeDs)))
|
.or(Some(storage_enums::AuthenticationType::NoThreeDs)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,4 @@
|
|||||||
mod transformers;
|
use api_models::{conditional_configs::DecisionManagerRecord, routing};
|
||||||
|
|
||||||
use api_models::{
|
|
||||||
conditional_configs::{ConditionalConfigs, DecisionManagerRecord},
|
|
||||||
routing,
|
|
||||||
};
|
|
||||||
use common_utils::ext_traits::StringExt;
|
use common_utils::ext_traits::StringExt;
|
||||||
use error_stack::ResultExt;
|
use error_stack::ResultExt;
|
||||||
use euclid::backend::{self, inputs as dsl_inputs, EuclidBackend};
|
use euclid::backend::{self, inputs as dsl_inputs, EuclidBackend};
|
||||||
@ -23,11 +18,11 @@ pub async fn perform_decision_management(
|
|||||||
algorithm_ref: routing::RoutingAlgorithmRef,
|
algorithm_ref: routing::RoutingAlgorithmRef,
|
||||||
merchant_id: &common_utils::id_type::MerchantId,
|
merchant_id: &common_utils::id_type::MerchantId,
|
||||||
payment_data: &core_routing::PaymentsDslInput<'_>,
|
payment_data: &core_routing::PaymentsDslInput<'_>,
|
||||||
) -> ConditionalConfigResult<ConditionalConfigs> {
|
) -> ConditionalConfigResult<common_types::payments::ConditionalConfigs> {
|
||||||
let algorithm_id = if let Some(id) = algorithm_ref.config_algo_id {
|
let algorithm_id = if let Some(id) = algorithm_ref.config_algo_id {
|
||||||
id
|
id
|
||||||
} else {
|
} else {
|
||||||
return Ok(ConditionalConfigs::default());
|
return Ok(common_types::payments::ConditionalConfigs::default());
|
||||||
};
|
};
|
||||||
let db = &*state.store;
|
let db = &*state.store;
|
||||||
|
|
||||||
@ -64,8 +59,8 @@ pub async fn perform_decision_management(
|
|||||||
|
|
||||||
pub fn execute_dsl_and_get_conditional_config(
|
pub fn execute_dsl_and_get_conditional_config(
|
||||||
backend_input: dsl_inputs::BackendInput,
|
backend_input: dsl_inputs::BackendInput,
|
||||||
interpreter: &backend::VirInterpreterBackend<ConditionalConfigs>,
|
interpreter: &backend::VirInterpreterBackend<common_types::payments::ConditionalConfigs>,
|
||||||
) -> ConditionalConfigResult<ConditionalConfigs> {
|
) -> ConditionalConfigResult<common_types::payments::ConditionalConfigs> {
|
||||||
let routing_output = interpreter
|
let routing_output = interpreter
|
||||||
.execute(backend_input)
|
.execute(backend_input)
|
||||||
.map(|out| out.connector_selection)
|
.map(|out| out.connector_selection)
|
||||||
|
|||||||
@ -1,22 +0,0 @@
|
|||||||
use api_models::{self, conditional_configs};
|
|
||||||
use diesel_models::enums as storage_enums;
|
|
||||||
use euclid::enums as dsl_enums;
|
|
||||||
|
|
||||||
use crate::types::transformers::ForeignFrom;
|
|
||||||
impl ForeignFrom<dsl_enums::AuthenticationType> for conditional_configs::AuthenticationType {
|
|
||||||
fn foreign_from(from: dsl_enums::AuthenticationType) -> Self {
|
|
||||||
match from {
|
|
||||||
dsl_enums::AuthenticationType::ThreeDs => Self::ThreeDs,
|
|
||||||
dsl_enums::AuthenticationType::NoThreeDs => Self::NoThreeDs,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ForeignFrom<conditional_configs::AuthenticationType> for storage_enums::AuthenticationType {
|
|
||||||
fn foreign_from(from: conditional_configs::AuthenticationType) -> Self {
|
|
||||||
match from {
|
|
||||||
conditional_configs::AuthenticationType::ThreeDs => Self::ThreeDs,
|
|
||||||
conditional_configs::AuthenticationType::NoThreeDs => Self::NoThreeDs,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -197,17 +197,6 @@ pub async fn update_merchant_active_algorithm_ref(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "v2")]
|
|
||||||
pub async fn update_merchant_active_algorithm_ref(
|
|
||||||
_state: &SessionState,
|
|
||||||
_key_store: &domain::MerchantKeyStore,
|
|
||||||
_config_key: cache::CacheKind<'_>,
|
|
||||||
_algorithm_id: routing_types::RoutingAlgorithmRef,
|
|
||||||
) -> RouterResult<()> {
|
|
||||||
// TODO: handle updating the active routing algorithm for v2 in merchant account
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "v1")]
|
#[cfg(feature = "v1")]
|
||||||
pub async fn update_profile_active_algorithm_ref(
|
pub async fn update_profile_active_algorithm_ref(
|
||||||
db: &dyn StorageInterface,
|
db: &dyn StorageInterface,
|
||||||
|
|||||||
@ -1832,7 +1832,12 @@ impl Profile {
|
|||||||
&TransactionType::Payment,
|
&TransactionType::Payment,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
))),
|
)))
|
||||||
|
.service(
|
||||||
|
web::resource("/decision")
|
||||||
|
.route(web::put().to(routing::upsert_decision_manager_config))
|
||||||
|
.route(web::get().to(routing::retrieve_decision_manager_config)),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -688,7 +688,7 @@ pub async fn retrieve_surcharge_decision_manager_config(
|
|||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "olap")]
|
#[cfg(all(feature = "olap", feature = "v1"))]
|
||||||
#[instrument(skip_all)]
|
#[instrument(skip_all)]
|
||||||
pub async fn upsert_decision_manager_config(
|
pub async fn upsert_decision_manager_config(
|
||||||
state: web::Data<AppState>,
|
state: web::Data<AppState>,
|
||||||
@ -726,6 +726,44 @@ pub async fn upsert_decision_manager_config(
|
|||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(all(feature = "olap", feature = "v2"))]
|
||||||
|
#[instrument(skip_all)]
|
||||||
|
pub async fn upsert_decision_manager_config(
|
||||||
|
state: web::Data<AppState>,
|
||||||
|
req: HttpRequest,
|
||||||
|
json_payload: web::Json<api_models::conditional_configs::DecisionManagerRequest>,
|
||||||
|
) -> impl Responder {
|
||||||
|
let flow = Flow::DecisionManagerUpsertConfig;
|
||||||
|
Box::pin(oss_api::server_wrap(
|
||||||
|
flow,
|
||||||
|
state,
|
||||||
|
&req,
|
||||||
|
json_payload.into_inner(),
|
||||||
|
|state, auth: auth::AuthenticationData, update_decision, _| {
|
||||||
|
conditional_config::upsert_conditional_config(
|
||||||
|
state,
|
||||||
|
auth.key_store,
|
||||||
|
update_decision,
|
||||||
|
auth.profile,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
#[cfg(not(feature = "release"))]
|
||||||
|
auth::auth_type(
|
||||||
|
&auth::HeaderAuth(auth::ApiKeyAuth),
|
||||||
|
&auth::JWTAuth {
|
||||||
|
permission: Permission::ProfileThreeDsDecisionManagerWrite,
|
||||||
|
},
|
||||||
|
req.headers(),
|
||||||
|
),
|
||||||
|
#[cfg(feature = "release")]
|
||||||
|
&auth::JWTAuth {
|
||||||
|
permission: Permission::ProfileThreeDsDecisionManagerWrite,
|
||||||
|
},
|
||||||
|
api_locking::LockAction::NotApplicable,
|
||||||
|
))
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "olap")]
|
#[cfg(feature = "olap")]
|
||||||
#[instrument(skip_all)]
|
#[instrument(skip_all)]
|
||||||
pub async fn delete_decision_manager_config(
|
pub async fn delete_decision_manager_config(
|
||||||
@ -762,6 +800,40 @@ pub async fn delete_decision_manager_config(
|
|||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(all(feature = "olap", feature = "v2"))]
|
||||||
|
#[cfg(feature = "olap")]
|
||||||
|
#[instrument(skip_all)]
|
||||||
|
pub async fn retrieve_decision_manager_config(
|
||||||
|
state: web::Data<AppState>,
|
||||||
|
req: HttpRequest,
|
||||||
|
) -> impl Responder {
|
||||||
|
let flow = Flow::DecisionManagerRetrieveConfig;
|
||||||
|
Box::pin(oss_api::server_wrap(
|
||||||
|
flow,
|
||||||
|
state,
|
||||||
|
&req,
|
||||||
|
(),
|
||||||
|
|state, auth: auth::AuthenticationData, _, _| {
|
||||||
|
conditional_config::retrieve_conditional_config(state, auth.key_store, auth.profile)
|
||||||
|
},
|
||||||
|
#[cfg(not(feature = "release"))]
|
||||||
|
auth::auth_type(
|
||||||
|
&auth::HeaderAuth(auth::ApiKeyAuth),
|
||||||
|
&auth::JWTAuth {
|
||||||
|
permission: Permission::ProfileThreeDsDecisionManagerWrite,
|
||||||
|
},
|
||||||
|
req.headers(),
|
||||||
|
),
|
||||||
|
#[cfg(feature = "release")]
|
||||||
|
&auth::JWTAuth {
|
||||||
|
permission: Permission::ProfileThreeDsDecisionManagerWrite,
|
||||||
|
},
|
||||||
|
api_locking::LockAction::NotApplicable,
|
||||||
|
))
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(feature = "olap", feature = "v1"))]
|
||||||
#[cfg(feature = "olap")]
|
#[cfg(feature = "olap")]
|
||||||
#[instrument(skip_all)]
|
#[instrument(skip_all)]
|
||||||
pub async fn retrieve_decision_manager_config(
|
pub async fn retrieve_decision_manager_config(
|
||||||
|
|||||||
@ -45,7 +45,7 @@ generate_permissions! {
|
|||||||
},
|
},
|
||||||
ThreeDsDecisionManager: {
|
ThreeDsDecisionManager: {
|
||||||
scopes: [Read, Write],
|
scopes: [Read, Write],
|
||||||
entities: [Merchant]
|
entities: [Merchant, Profile]
|
||||||
},
|
},
|
||||||
SurchargeDecisionManager: {
|
SurchargeDecisionManager: {
|
||||||
scopes: [Read, Write],
|
scopes: [Read, Write],
|
||||||
|
|||||||
@ -0,0 +1,3 @@
|
|||||||
|
-- This file should undo anything in `up.sql`
|
||||||
|
ALTER TABLE business_profile
|
||||||
|
DROP COLUMN IF EXISTS three_ds_decision_manager_config;
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
-- Your SQL goes here
|
||||||
|
ALTER TABLE business_profile
|
||||||
|
ADD COLUMN IF NOT EXISTS three_ds_decision_manager_config jsonb;
|
||||||
Reference in New Issue
Block a user