mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-27 11:24:45 +08:00
feat: list for dynamic routing (#8111)
Co-authored-by: Sarthak Soni <sarthakasoni@gmail.com> Co-authored-by: Gaurav Rawat <104276743+GauravRawat369@users.noreply.github.com> Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Co-authored-by: Chethan Rao <70657455+Chethan-rao@users.noreply.github.com>
This commit is contained in:
@ -58,7 +58,7 @@ pub struct MerchantAccountCreate {
|
||||
|
||||
/// The routing algorithm to be used for routing payouts to desired connectors
|
||||
#[cfg(feature = "payouts")]
|
||||
#[schema(value_type = Option<RoutingAlgorithm>,example = json!({"type": "single", "data": "wise"}))]
|
||||
#[schema(value_type = Option<StaticRoutingAlgorithm>,example = json!({"type": "single", "data": "wise"}))]
|
||||
pub payout_routing_algorithm: Option<serde_json::Value>,
|
||||
|
||||
/// A boolean value to indicate if the merchant is a sub-merchant under a master or a parent merchant. By default, its value is false.
|
||||
@ -165,8 +165,9 @@ impl MerchantAccountCreate {
|
||||
pub fn parse_routing_algorithm(&self) -> CustomResult<(), errors::ParsingError> {
|
||||
match self.routing_algorithm {
|
||||
Some(ref routing_algorithm) => {
|
||||
let _: routing::RoutingAlgorithm =
|
||||
routing_algorithm.clone().parse_value("RoutingAlgorithm")?;
|
||||
let _: routing::StaticRoutingAlgorithm = routing_algorithm
|
||||
.clone()
|
||||
.parse_value("StaticRoutingAlgorithm")?;
|
||||
Ok(())
|
||||
}
|
||||
None => Ok(()),
|
||||
@ -325,7 +326,7 @@ pub struct MerchantAccountUpdate {
|
||||
|
||||
/// The routing algorithm to be used to process the incoming request from merchant to outgoing payment processor or payment method. The default is 'Custom'
|
||||
#[cfg(feature = "payouts")]
|
||||
#[schema(value_type = Option<RoutingAlgorithm>,example = json!({"type": "single", "data": "wise"}))]
|
||||
#[schema(value_type = Option<StaticRoutingAlgorithm>,example = json!({"type": "single", "data": "wise"}))]
|
||||
pub payout_routing_algorithm: Option<serde_json::Value>,
|
||||
|
||||
/// A boolean value to indicate if the merchant is a sub-merchant under a master or a parent merchant. By default, its value is false.
|
||||
@ -425,8 +426,9 @@ impl MerchantAccountUpdate {
|
||||
pub fn parse_routing_algorithm(&self) -> CustomResult<(), errors::ParsingError> {
|
||||
match self.routing_algorithm {
|
||||
Some(ref routing_algorithm) => {
|
||||
let _: routing::RoutingAlgorithm =
|
||||
routing_algorithm.clone().parse_value("RoutingAlgorithm")?;
|
||||
let _: routing::StaticRoutingAlgorithm = routing_algorithm
|
||||
.clone()
|
||||
.parse_value("StaticRoutingAlgorithm")?;
|
||||
Ok(())
|
||||
}
|
||||
None => Ok(()),
|
||||
@ -517,7 +519,7 @@ pub struct MerchantAccountResponse {
|
||||
|
||||
/// The routing algorithm to be used to process the incoming request from merchant to outgoing payment processor or payment method. The default is 'Custom'
|
||||
#[cfg(feature = "payouts")]
|
||||
#[schema(value_type = Option<RoutingAlgorithm>,example = json!({"type": "single", "data": "wise"}))]
|
||||
#[schema(value_type = Option<StaticRoutingAlgorithm>,example = json!({"type": "single", "data": "wise"}))]
|
||||
pub payout_routing_algorithm: Option<serde_json::Value>,
|
||||
|
||||
/// A boolean value to indicate if the merchant is a sub-merchant under a master or a parent merchant. By default, its value is false.
|
||||
@ -545,7 +547,7 @@ pub struct MerchantAccountResponse {
|
||||
pub primary_business_details: Vec<PrimaryBusinessDetails>,
|
||||
|
||||
/// The frm routing algorithm to be used to process the incoming request from merchant to outgoing payment FRM.
|
||||
#[schema(value_type = Option<RoutingAlgorithm>, max_length = 255, example = r#"{"type": "single", "data": "stripe" }"#)]
|
||||
#[schema(value_type = Option<StaticRoutingAlgorithm>, max_length = 255, example = r#"{"type": "single", "data": "stripe" }"#)]
|
||||
pub frm_routing_algorithm: Option<serde_json::Value>,
|
||||
|
||||
/// The organization id merchant is associated with
|
||||
@ -1897,7 +1899,7 @@ pub struct ProfileCreate {
|
||||
|
||||
/// The routing algorithm to be used to process the incoming request from merchant to outgoing payment processor or payment method. The default is 'Custom'
|
||||
#[cfg(feature = "payouts")]
|
||||
#[schema(value_type = Option<RoutingAlgorithm>,example = json!({"type": "single", "data": "wise"}))]
|
||||
#[schema(value_type = Option<StaticRoutingAlgorithm>,example = json!({"type": "single", "data": "wise"}))]
|
||||
pub payout_routing_algorithm: Option<serde_json::Value>,
|
||||
|
||||
/// Verified Apple Pay domains for a particular profile
|
||||
@ -2199,7 +2201,7 @@ pub struct ProfileResponse {
|
||||
|
||||
/// The routing algorithm to be used to process the incoming request from merchant to outgoing payment processor or payment method. The default is 'Custom'
|
||||
#[cfg(feature = "payouts")]
|
||||
#[schema(value_type = Option<RoutingAlgorithm>,example = json!({"type": "single", "data": "wise"}))]
|
||||
#[schema(value_type = Option<StaticRoutingAlgorithm>,example = json!({"type": "single", "data": "wise"}))]
|
||||
pub payout_routing_algorithm: Option<serde_json::Value>,
|
||||
|
||||
/// Verified Apple Pay domains for a particular profile
|
||||
@ -2504,7 +2506,7 @@ pub struct ProfileUpdate {
|
||||
|
||||
/// The routing algorithm to be used to process the incoming request from merchant to outgoing payment processor or payment method. The default is 'Custom'
|
||||
#[cfg(feature = "payouts")]
|
||||
#[schema(value_type = Option<RoutingAlgorithm>,example = json!({"type": "single", "data": "wise"}))]
|
||||
#[schema(value_type = Option<StaticRoutingAlgorithm>,example = json!({"type": "single", "data": "wise"}))]
|
||||
pub payout_routing_algorithm: Option<serde_json::Value>,
|
||||
|
||||
/// Verified Apple Pay domains for a particular profile
|
||||
|
||||
@ -6,9 +6,9 @@ use crate::routing::{
|
||||
LinkedRoutingConfigRetrieveResponse, MerchantRoutingAlgorithm, ProfileDefaultRoutingConfig,
|
||||
RoutingAlgorithmId, RoutingConfigRequest, RoutingDictionaryRecord, RoutingKind,
|
||||
RoutingLinkWrapper, RoutingPayloadWrapper, RoutingRetrieveLinkQuery,
|
||||
RoutingRetrieveLinkQueryWrapper, RoutingRetrieveQuery, RoutingVolumeSplitWrapper,
|
||||
SuccessBasedRoutingConfig, SuccessBasedRoutingPayloadWrapper, ToggleDynamicRoutingQuery,
|
||||
ToggleDynamicRoutingWrapper,
|
||||
RoutingRetrieveLinkQueryWrapper, RoutingRetrieveQuery, RoutingVolumeSplit,
|
||||
RoutingVolumeSplitWrapper, SuccessBasedRoutingConfig, SuccessBasedRoutingPayloadWrapper,
|
||||
ToggleDynamicRoutingQuery, ToggleDynamicRoutingWrapper,
|
||||
};
|
||||
|
||||
impl ApiEventMetric for RoutingKind {
|
||||
@ -134,3 +134,9 @@ impl ApiEventMetric for RoutingVolumeSplitWrapper {
|
||||
Some(ApiEventsType::Routing)
|
||||
}
|
||||
}
|
||||
|
||||
impl ApiEventMetric for RoutingVolumeSplit {
|
||||
fn get_api_event_type(&self) -> Option<ApiEventsType> {
|
||||
Some(ApiEventsType::Routing)
|
||||
}
|
||||
}
|
||||
|
||||
@ -58,7 +58,7 @@ pub struct PayoutCreateRequest {
|
||||
pub currency: Option<api_enums::Currency>,
|
||||
|
||||
/// Specifies routing algorithm for selecting a connector
|
||||
#[schema(value_type = Option<RoutingAlgorithm>, example = json!({
|
||||
#[schema(value_type = Option<StaticRoutingAlgorithm>, example = json!({
|
||||
"type": "single",
|
||||
"data": "adyen"
|
||||
}))]
|
||||
|
||||
@ -49,7 +49,7 @@ impl ConnectorSelection {
|
||||
pub struct RoutingConfigRequest {
|
||||
pub name: String,
|
||||
pub description: String,
|
||||
pub algorithm: RoutingAlgorithm,
|
||||
pub algorithm: StaticRoutingAlgorithm,
|
||||
#[schema(value_type = String)]
|
||||
pub profile_id: common_utils::id_type::ProfileId,
|
||||
}
|
||||
@ -59,7 +59,7 @@ pub struct RoutingConfigRequest {
|
||||
pub struct RoutingConfigRequest {
|
||||
pub name: Option<String>,
|
||||
pub description: Option<String>,
|
||||
pub algorithm: Option<RoutingAlgorithm>,
|
||||
pub algorithm: Option<StaticRoutingAlgorithm>,
|
||||
#[schema(value_type = Option<String>)]
|
||||
pub profile_id: Option<common_utils::id_type::ProfileId>,
|
||||
}
|
||||
@ -96,7 +96,7 @@ pub struct RoutingRetrieveResponse {
|
||||
#[derive(Debug, serde::Serialize, ToSchema)]
|
||||
#[serde(untagged)]
|
||||
pub enum LinkedRoutingConfigRetrieveResponse {
|
||||
MerchantAccountBased(RoutingRetrieveResponse),
|
||||
MerchantAccountBased(Box<RoutingRetrieveResponse>),
|
||||
ProfileBased(Vec<RoutingDictionaryRecord>),
|
||||
}
|
||||
|
||||
@ -109,7 +109,7 @@ pub struct MerchantRoutingAlgorithm {
|
||||
pub profile_id: common_utils::id_type::ProfileId,
|
||||
pub name: String,
|
||||
pub description: String,
|
||||
pub algorithm: RoutingAlgorithm,
|
||||
pub algorithm: RoutingAlgorithmWrapper,
|
||||
pub created_at: i64,
|
||||
pub modified_at: i64,
|
||||
pub algorithm_for: TransactionType,
|
||||
@ -301,6 +301,20 @@ pub struct RoutingPayloadWrapper {
|
||||
pub updated_config: Vec<RoutableConnectorChoice>,
|
||||
pub profile_id: common_utils::id_type::ProfileId,
|
||||
}
|
||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
|
||||
#[serde(untagged)]
|
||||
pub enum RoutingAlgorithmWrapper {
|
||||
Static(StaticRoutingAlgorithm),
|
||||
Dynamic(DynamicRoutingAlgorithm),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
|
||||
#[serde(untagged)]
|
||||
pub enum DynamicRoutingAlgorithm {
|
||||
EliminationBasedAlgorithm(EliminationRoutingConfig),
|
||||
SuccessBasedAlgorithm(SuccessBasedRoutingConfig),
|
||||
ContractBasedAlgorithm(ContractBasedRoutingConfig),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
|
||||
#[serde(
|
||||
@ -309,8 +323,7 @@ pub struct RoutingPayloadWrapper {
|
||||
rename_all = "snake_case",
|
||||
try_from = "RoutingAlgorithmSerde"
|
||||
)]
|
||||
/// Routing Algorithm kind
|
||||
pub enum RoutingAlgorithm {
|
||||
pub enum StaticRoutingAlgorithm {
|
||||
Single(Box<RoutableConnectorChoice>),
|
||||
Priority(Vec<RoutableConnectorChoice>),
|
||||
VolumeSplit(Vec<ConnectorVolumeSplit>),
|
||||
@ -318,7 +331,7 @@ pub enum RoutingAlgorithm {
|
||||
Advanced(ast::Program<ConnectorSelection>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
|
||||
#[serde(tag = "type", content = "data", rename_all = "snake_case")]
|
||||
pub enum RoutingAlgorithmSerde {
|
||||
Single(Box<RoutableConnectorChoice>),
|
||||
@ -327,7 +340,7 @@ pub enum RoutingAlgorithmSerde {
|
||||
Advanced(ast::Program<ConnectorSelection>),
|
||||
}
|
||||
|
||||
impl TryFrom<RoutingAlgorithmSerde> for RoutingAlgorithm {
|
||||
impl TryFrom<RoutingAlgorithmSerde> for StaticRoutingAlgorithm {
|
||||
type Error = error_stack::Report<ParsingError>;
|
||||
|
||||
fn try_from(value: RoutingAlgorithmSerde) -> Result<Self, Self::Error> {
|
||||
@ -434,7 +447,7 @@ impl From<StraightThroughAlgorithm> for StraightThroughAlgorithmSerde {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<StraightThroughAlgorithm> for RoutingAlgorithm {
|
||||
impl From<StraightThroughAlgorithm> for StaticRoutingAlgorithm {
|
||||
fn from(value: StraightThroughAlgorithm) -> Self {
|
||||
match value {
|
||||
StraightThroughAlgorithm::Single(conn) => Self::Single(conn),
|
||||
@ -444,7 +457,7 @@ impl From<StraightThroughAlgorithm> for RoutingAlgorithm {
|
||||
}
|
||||
}
|
||||
|
||||
impl RoutingAlgorithm {
|
||||
impl StaticRoutingAlgorithm {
|
||||
pub fn get_kind(&self) -> RoutingAlgorithmKind {
|
||||
match self {
|
||||
Self::Single(_) => RoutingAlgorithmKind::Single,
|
||||
@ -845,6 +858,7 @@ pub struct ToggleDynamicRoutingPath {
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, ToSchema)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct EliminationRoutingConfig {
|
||||
pub params: Option<Vec<DynamicRoutingConfigParams>>,
|
||||
pub elimination_analyser_config: Option<EliminationAnalyserConfig>,
|
||||
@ -853,6 +867,7 @@ pub struct EliminationRoutingConfig {
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, Copy, ToSchema)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct EliminationAnalyserConfig {
|
||||
pub bucket_size: Option<u64>,
|
||||
pub bucket_leak_interval_in_secs: Option<u64>,
|
||||
@ -924,6 +939,7 @@ impl EliminationRoutingConfig {
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, ToSchema)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct SuccessBasedRoutingConfig {
|
||||
pub params: Option<Vec<DynamicRoutingConfigParams>>,
|
||||
pub config: Option<SuccessBasedRoutingConfigBody>,
|
||||
@ -950,7 +966,9 @@ impl Default for SuccessBasedRoutingConfig {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, ToSchema, strum::Display)]
|
||||
#[derive(
|
||||
serde::Serialize, serde::Deserialize, Debug, Clone, ToSchema, PartialEq, strum::Display,
|
||||
)]
|
||||
pub enum DynamicRoutingConfigParams {
|
||||
PaymentMethod,
|
||||
PaymentMethodType,
|
||||
@ -962,6 +980,7 @@ pub enum DynamicRoutingConfigParams {
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, ToSchema)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct SuccessBasedRoutingConfigBody {
|
||||
pub min_aggregates_size: Option<u32>,
|
||||
pub default_success_rate: Option<f64>,
|
||||
|
||||
Reference in New Issue
Block a user