feat(routing): Add api-refs for new decision engine endpoints (#8709)

Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
This commit is contained in:
Gaurav Rawat
2025-07-29 16:18:51 +05:30
committed by GitHub
parent 3d085abf38
commit 4dea30ffa0
11 changed files with 755 additions and 121 deletions

View File

@ -220,7 +220,10 @@
"v1/routing/routing--retrieve-default-for-profile",
"v1/routing/routing--update-default-for-profile",
"v1/routing/routing--retrieve",
"v1/routing/routing--activate-config"
"v1/routing/routing--activate-config",
"v1/routing/routing--evaluate",
"v1/routing/routing--feedback",
"v1/routing/routing--rule-evaluate"
]
},
{

View File

@ -5174,6 +5174,162 @@
]
}
},
"/routing/evaluate": {
"post": {
"tags": [
"Routing"
],
"summary": "Routing - Evaluate",
"description": "Evaluate routing rules",
"operationId": "Evaluate routing rules",
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OpenRouterDecideGatewayRequest"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "Routing rules evaluated successfully",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/DecideGatewayResponse"
}
}
}
},
"400": {
"description": "Request body is malformed"
},
"403": {
"description": "Forbidden"
},
"404": {
"description": "Resource missing"
},
"422": {
"description": "Unprocessable request"
},
"500": {
"description": "Internal server error"
}
},
"security": [
{
"api_key": []
}
]
}
},
"/routing/feedback": {
"post": {
"tags": [
"Routing"
],
"summary": "Routing - Feedback",
"description": "Update gateway scores for dynamic routing",
"operationId": "Update gateway scores",
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UpdateScorePayload"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "Gateway score updated successfully",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UpdateScoreResponse"
}
}
}
},
"400": {
"description": "Request body is malformed"
},
"403": {
"description": "Forbidden"
},
"404": {
"description": "Resource missing"
},
"422": {
"description": "Unprocessable request"
},
"500": {
"description": "Internal server error"
}
},
"security": [
{
"api_key": []
}
]
}
},
"/routing/rule/evaluate": {
"post": {
"tags": [
"Routing"
],
"summary": "Routing - Rule Evaluate",
"description": "Evaluate routing rules",
"operationId": "Evaluate routing rules (alternative)",
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RoutingEvaluateRequest"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "Routing rules evaluated successfully",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RoutingEvaluateResponse"
}
}
}
},
"400": {
"description": "Request body is malformed"
},
"403": {
"description": "Forbidden"
},
"404": {
"description": "Resource missing"
},
"422": {
"description": "Unprocessable request"
},
"500": {
"description": "Internal server error"
}
},
"security": [
{
"api_key": []
}
]
}
},
"/blocklist": {
"delete": {
"tags": [
@ -13367,6 +13523,80 @@
}
}
},
"DeRoutableConnectorChoice": {
"type": "object",
"description": "Routable Connector chosen for a payment",
"required": [
"gateway_name",
"gateway_id"
],
"properties": {
"gateway_name": {
"$ref": "#/components/schemas/RoutableConnectors"
},
"gateway_id": {
"type": "string"
}
}
},
"DecideGatewayResponse": {
"type": "object",
"properties": {
"decided_gateway": {
"type": "string",
"nullable": true
},
"gateway_priority_map": {
"nullable": true
},
"filter_wise_gateways": {
"nullable": true
},
"priority_logic_tag": {
"type": "string",
"nullable": true
},
"routing_approach": {
"type": "string",
"nullable": true
},
"gateway_before_evaluation": {
"type": "string",
"nullable": true
},
"priority_logic_output": {
"allOf": [
{
"$ref": "#/components/schemas/PriorityLogicOutput"
}
],
"nullable": true
},
"reset_approach": {
"type": "string",
"nullable": true
},
"routing_dimension": {
"type": "string",
"nullable": true
},
"routing_dimension_level": {
"type": "string",
"nullable": true
},
"is_scheduled_outage": {
"type": "boolean",
"nullable": true
},
"is_dynamic_mga_enabled": {
"type": "boolean",
"nullable": true
},
"gateway_mga_id_map": {
"nullable": true
}
}
},
"DecisionEngineEliminationData": {
"type": "object",
"required": [
@ -18685,6 +18915,40 @@
}
}
},
"OpenRouterDecideGatewayRequest": {
"type": "object",
"required": [
"paymentInfo",
"merchantId"
],
"properties": {
"paymentInfo": {
"$ref": "#/components/schemas/PaymentInfo"
},
"merchantId": {
"type": "string"
},
"eligibleGatewayList": {
"type": "array",
"items": {
"type": "string"
},
"nullable": true
},
"rankingAlgorithm": {
"allOf": [
{
"$ref": "#/components/schemas/RankingAlgorithm"
}
],
"nullable": true
},
"eliminationEnabled": {
"type": "boolean",
"nullable": true
}
}
},
"OrderDetailsWithAmount": {
"type": "object",
"required": [
@ -19527,6 +19791,49 @@
}
}
},
"PaymentId": {
"type": "string",
"description": "A type for payment_id that can be used for payment ids"
},
"PaymentInfo": {
"type": "object",
"required": [
"paymentId",
"amount",
"currency",
"paymentType",
"paymentMethodType",
"paymentMethod"
],
"properties": {
"paymentId": {
"type": "string"
},
"amount": {
"$ref": "#/components/schemas/MinorUnit"
},
"currency": {
"$ref": "#/components/schemas/Currency"
},
"paymentType": {
"type": "string"
},
"metadata": {
"type": "string",
"nullable": true
},
"paymentMethodType": {
"type": "string"
},
"paymentMethod": {
"$ref": "#/components/schemas/PaymentMethod"
},
"cardIsin": {
"type": "string",
"nullable": true
}
}
},
"PaymentLinkBackgroundImageConfig": {
"type": "object",
"required": [
@ -26544,6 +26851,66 @@
},
"additionalProperties": false
},
"PriorityLogicData": {
"type": "object",
"properties": {
"name": {
"type": "string",
"nullable": true
},
"status": {
"type": "string",
"nullable": true
},
"failure_reason": {
"type": "string",
"nullable": true
}
}
},
"PriorityLogicOutput": {
"type": "object",
"properties": {
"isEnforcement": {
"type": "boolean",
"nullable": true
},
"gws": {
"type": "array",
"items": {
"type": "string"
},
"nullable": true
},
"priorityLogicTag": {
"type": "string",
"nullable": true
},
"gatewayReferenceIds": {
"type": "object",
"additionalProperties": {
"type": "string"
},
"nullable": true
},
"primaryLogic": {
"allOf": [
{
"$ref": "#/components/schemas/PriorityLogicData"
}
],
"nullable": true
},
"fallbackLogic": {
"allOf": [
{
"$ref": "#/components/schemas/PriorityLogicData"
}
],
"nullable": true
}
}
},
"ProcessorPaymentToken": {
"type": "object",
"description": "Processor payment token for MIT payments where payment_method_data is not available",
@ -26989,6 +27356,10 @@
}
}
},
"ProfileId": {
"type": "string",
"description": "A type for profile_id that can be used for business profile ids"
},
"ProfileResponse": {
"type": "object",
"required": [
@ -27325,6 +27696,14 @@
}
}
},
"RankingAlgorithm": {
"type": "string",
"enum": [
"SR_BASED_ROUTING",
"PL_BASED_ROUTING",
"NTW_BASED_ROUTING"
]
},
"RealTimePaymentData": {
"oneOf": [
{
@ -28666,6 +29045,56 @@
}
}
},
"RoutingEvaluateRequest": {
"type": "object",
"required": [
"created_by",
"parameters",
"fallback_output"
],
"properties": {
"created_by": {
"type": "string"
},
"parameters": {
"type": "object",
"description": "Parameters that can be used in the routing evaluate request.\neg: {\"parameters\": {\n\"payment_method\": {\"type\": \"enum_variant\", \"value\": \"card\"},\n\"payment_method_type\": {\"type\": \"enum_variant\", \"value\": \"credit\"},\n\"amount\": {\"type\": \"number\", \"value\": 10},\n\"currency\": {\"type\": \"str_value\", \"value\": \"INR\"},\n\"authentication_type\": {\"type\": \"enum_variant\", \"value\": \"three_ds\"},\n\"card_bin\": {\"type\": \"str_value\", \"value\": \"424242\"},\n\"capture_method\": {\"type\": \"enum_variant\", \"value\": \"scheduled\"},\n\"business_country\": {\"type\": \"str_value\", \"value\": \"IN\"},\n\"billing_country\": {\"type\": \"str_value\", \"value\": \"IN\"},\n\"business_label\": {\"type\": \"str_value\", \"value\": \"business_label\"},\n\"setup_future_usage\": {\"type\": \"enum_variant\", \"value\": \"off_session\"},\n\"card_network\": {\"type\": \"enum_variant\", \"value\": \"visa\"},\n\"payment_type\": {\"type\": \"enum_variant\", \"value\": \"recurring_mandate\"},\n\"mandate_type\": {\"type\": \"enum_variant\", \"value\": \"single_use\"},\n\"mandate_acceptance_type\": {\"type\": \"enum_variant\", \"value\": \"online\"},\n\"metadata\":{\"type\": \"metadata_variant\", \"value\": {\"key\": \"key1\", \"value\": \"value1\"}}\n}}"
},
"fallback_output": {
"type": "array",
"items": {
"$ref": "#/components/schemas/DeRoutableConnectorChoice"
}
}
}
},
"RoutingEvaluateResponse": {
"type": "object",
"required": [
"status",
"output",
"evaluated_output",
"eligible_connectors"
],
"properties": {
"status": {
"type": "string"
},
"output": {},
"evaluated_output": {
"type": "array",
"items": {
"$ref": "#/components/schemas/RoutableConnectorChoice"
}
},
"eligible_connectors": {
"type": "array",
"items": {
"$ref": "#/components/schemas/RoutableConnectorChoice"
}
}
}
},
"RoutingKind": {
"oneOf": [
{
@ -30529,6 +30958,33 @@
"external"
]
},
"TxnStatus": {
"type": "string",
"enum": [
"STARTED",
"AUTHENTICATION_FAILED",
"JUSPAY_DECLINED",
"PENDING_VBV",
"V_B_V_SUCCESSFUL",
"AUTHORIZED",
"AUTHORIZATION_FAILED",
"CHARGED",
"AUTHORIZING",
"C_O_D_INITIATED",
"VOIDED",
"VOID_INITIATED",
"NOP",
"CAPTURE_INITIATED",
"CAPTURE_FAILED",
"VOID_FAILED",
"AUTO_REFUNDED",
"PARTIAL_CHARGED",
"TO_BE_CHARGED",
"PENDING",
"FAILURE",
"DECLINED"
]
},
"UIWidgetFormLayout": {
"type": "string",
"enum": [
@ -30565,6 +31021,40 @@
},
"additionalProperties": false
},
"UpdateScorePayload": {
"type": "object",
"required": [
"merchantId",
"gateway",
"status",
"paymentId"
],
"properties": {
"merchantId": {
"type": "string"
},
"gateway": {
"type": "string"
},
"status": {
"$ref": "#/components/schemas/TxnStatus"
},
"paymentId": {
"type": "string"
}
}
},
"UpdateScoreResponse": {
"type": "object",
"required": [
"message"
],
"properties": {
"message": {
"type": "string"
}
}
},
"UpiAdditionalData": {
"oneOf": [
{
@ -30672,7 +31162,10 @@
]
},
"value": {
"$ref": "#/components/schemas/MinorUnit"
"type": "integer",
"format": "int64",
"description": "Represents a number literal",
"minimum": 0
}
}
},
@ -30732,6 +31225,25 @@
}
}
},
{
"type": "object",
"required": [
"type",
"value"
],
"properties": {
"type": {
"type": "string",
"enum": [
"global_ref"
]
},
"value": {
"type": "string",
"description": "Represents a global reference, which is a reference to a global variable"
}
}
},
{
"type": "object",
"required": [
@ -30748,7 +31260,9 @@
"value": {
"type": "array",
"items": {
"$ref": "#/components/schemas/MinorUnit"
"type": "integer",
"format": "int64",
"minimum": 0
},
"description": "Represents an array of numbers. This is basically used for\n\"one of the given numbers\" operations\neg: payment.method.amount = (1, 2, 3)"
}

View File

@ -0,0 +1,3 @@
---
openapi: post /routing/evaluate
---

View File

@ -0,0 +1,3 @@
---
openapi: post /routing/feedback
---

View File

@ -0,0 +1,3 @@
---
openapi: post /routing/rule/evaluate
---

View File

@ -16,17 +16,18 @@ use crate::{
payment_methods,
};
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct OpenRouterDecideGatewayRequest {
pub payment_info: PaymentInfo,
#[schema(value_type = String)]
pub merchant_id: id_type::ProfileId,
pub eligible_gateway_list: Option<Vec<String>>,
pub ranking_algorithm: Option<RankingAlgorithm>,
pub elimination_enabled: Option<bool>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct DecideGatewayResponse {
pub decided_gateway: Option<String>,
pub gateway_priority_map: Option<serde_json::Value>,
@ -43,7 +44,7 @@ pub struct DecideGatewayResponse {
pub gateway_mga_id_map: Option<serde_json::Value>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct PriorityLogicOutput {
pub is_enforcement: Option<bool>,
@ -54,14 +55,14 @@ pub struct PriorityLogicOutput {
pub fallback_logic: Option<PriorityLogicData>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct PriorityLogicData {
pub name: Option<String>,
pub status: Option<String>,
pub failure_reason: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, ToSchema)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum RankingAlgorithm {
SrBasedRouting,
@ -69,9 +70,10 @@ pub enum RankingAlgorithm {
NtwBasedRouting,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct PaymentInfo {
#[schema(value_type = String)]
pub payment_id: id_type::PaymentId,
pub amount: MinorUnit,
pub currency: Currency,
@ -189,21 +191,23 @@ pub struct UnifiedError {
pub developer_message: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct UpdateScorePayload {
#[schema(value_type = String)]
pub merchant_id: id_type::ProfileId,
pub gateway: String,
pub status: TxnStatus,
#[schema(value_type = String)]
pub payment_id: id_type::PaymentId,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
pub struct UpdateScoreResponse {
pub message: String,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum TxnStatus {
Started,

View File

@ -1444,3 +1444,122 @@ pub enum RoutingResultSource {
/// Inbuilt Hyperswitch Routing Engine
HyperswitchRouting,
}
//TODO: temporary change will be refactored afterwards
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize, PartialEq, ToSchema)]
pub struct RoutingEvaluateRequest {
pub created_by: String,
#[schema(value_type = Object)]
///Parameters that can be used in the routing evaluate request.
///eg: {"parameters": {
/// "payment_method": {"type": "enum_variant", "value": "card"},
/// "payment_method_type": {"type": "enum_variant", "value": "credit"},
/// "amount": {"type": "number", "value": 10},
/// "currency": {"type": "str_value", "value": "INR"},
/// "authentication_type": {"type": "enum_variant", "value": "three_ds"},
/// "card_bin": {"type": "str_value", "value": "424242"},
/// "capture_method": {"type": "enum_variant", "value": "scheduled"},
/// "business_country": {"type": "str_value", "value": "IN"},
/// "billing_country": {"type": "str_value", "value": "IN"},
/// "business_label": {"type": "str_value", "value": "business_label"},
/// "setup_future_usage": {"type": "enum_variant", "value": "off_session"},
/// "card_network": {"type": "enum_variant", "value": "visa"},
/// "payment_type": {"type": "enum_variant", "value": "recurring_mandate"},
/// "mandate_type": {"type": "enum_variant", "value": "single_use"},
/// "mandate_acceptance_type": {"type": "enum_variant", "value": "online"},
/// "metadata":{"type": "metadata_variant", "value": {"key": "key1", "value": "value1"}}
/// }}
pub parameters: std::collections::HashMap<String, Option<ValueType>>,
pub fallback_output: Vec<DeRoutableConnectorChoice>,
}
impl common_utils::events::ApiEventMetric for RoutingEvaluateRequest {}
#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, ToSchema)]
pub struct RoutingEvaluateResponse {
pub status: String,
pub output: serde_json::Value,
#[serde(deserialize_with = "deserialize_connector_choices")]
pub evaluated_output: Vec<RoutableConnectorChoice>,
#[serde(deserialize_with = "deserialize_connector_choices")]
pub eligible_connectors: Vec<RoutableConnectorChoice>,
}
impl common_utils::events::ApiEventMetric for RoutingEvaluateResponse {}
fn deserialize_connector_choices<'de, D>(
deserializer: D,
) -> Result<Vec<RoutableConnectorChoice>, D::Error>
where
D: serde::Deserializer<'de>,
{
let infos = Vec::<DeRoutableConnectorChoice>::deserialize(deserializer)?;
Ok(infos
.into_iter()
.map(RoutableConnectorChoice::from)
.collect())
}
impl From<DeRoutableConnectorChoice> for RoutableConnectorChoice {
fn from(choice: DeRoutableConnectorChoice) -> Self {
Self {
choice_kind: RoutableChoiceKind::FullStruct,
connector: choice.gateway_name,
merchant_connector_id: choice.gateway_id,
}
}
}
/// Routable Connector chosen for a payment
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct DeRoutableConnectorChoice {
pub gateway_name: RoutableConnectors,
#[schema(value_type = String)]
pub gateway_id: Option<common_utils::id_type::MerchantConnectorAccountId>,
}
/// Represents a value in the DSL
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, ToSchema)]
#[serde(tag = "type", content = "value", rename_all = "snake_case")]
pub enum ValueType {
/// Represents a number literal
Number(u64),
/// Represents an enum variant
EnumVariant(String),
/// Represents a Metadata variant
MetadataVariant(MetadataValue),
/// Represents a arbitrary String value
StrValue(String),
/// Represents a global reference, which is a reference to a global variable
GlobalRef(String),
/// Represents an array of numbers. This is basically used for
/// "one of the given numbers" operations
/// eg: payment.method.amount = (1, 2, 3)
NumberArray(Vec<u64>),
/// Similar to NumberArray but for enum variants
/// eg: payment.method.cardtype = (debit, credit)
EnumVariantArray(Vec<String>),
/// Like a number array but can include comparisons. Useful for
/// conditions like "500 < amount < 1000"
/// eg: payment.amount = (> 500, < 1000)
NumberComparisonArray(Vec<NumberComparison>),
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, ToSchema)]
pub struct MetadataValue {
pub key: String,
pub value: String,
}
/// Represents a number comparison for "NumberComparisonArrayValue"
#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub struct NumberComparison {
pub comparison_type: ComparisonType,
pub number: u64,
}
/// Conditional comparison type
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum ComparisonType {
Equal,
NotEqual,
LessThan,
LessThanEqual,
GreaterThan,
GreaterThanEqual,
}

View File

@ -170,6 +170,9 @@ Never share your secret api keys. Keep them guarded and secure.
routes::routing::toggle_elimination_routing,
routes::routing::contract_based_routing_setup_config,
routes::routing::contract_based_routing_update_configs,
routes::routing::call_decide_gateway_open_router,
routes::routing::call_update_gateway_score_open_router,
routes::routing::evaluate_routing_rule,
// Routes for blocklist
routes::blocklist::remove_entry_from_blocklist,
@ -809,6 +812,22 @@ Never share your secret api keys. Keep them guarded and secure.
api_models::authentication::ThreeDsData,
api_models::authentication::AuthenticationEligibilityRequest,
api_models::authentication::AuthenticationEligibilityResponse,
api_models::open_router::OpenRouterDecideGatewayRequest,
api_models::open_router::DecideGatewayResponse,
api_models::open_router::UpdateScorePayload,
api_models::open_router::UpdateScoreResponse,
api_models::routing::RoutingEvaluateRequest,
api_models::routing::RoutingEvaluateResponse,
api_models::routing::ValueType,
api_models::routing::DeRoutableConnectorChoice,
api_models::routing::RoutableConnectorChoice,
api_models::open_router::PaymentInfo,
common_utils::id_type::PaymentId,
common_utils::id_type::ProfileId,
api_models::open_router::RankingAlgorithm,
api_models::open_router::TxnStatus,
api_models::open_router::PriorityLogicOutput,
api_models::open_router::PriorityLogicData,
api_models::user::PlatformAccountCreateRequest,
api_models::user::PlatformAccountCreateResponse,
)),

View File

@ -386,3 +386,69 @@ pub async fn contract_based_routing_setup_config() {}
security(("api_key" = []), ("jwt_key" = []))
)]
pub async fn contract_based_routing_update_configs() {}
#[cfg(feature = "v1")]
/// Routing - Evaluate
///
/// Evaluate routing rules
#[utoipa::path(
post,
path = "/routing/evaluate",
request_body = OpenRouterDecideGatewayRequest,
responses(
(status = 200, description = "Routing rules evaluated successfully", body = DecideGatewayResponse),
(status = 400, description = "Request body is malformed"),
(status = 500, description = "Internal server error"),
(status = 404, description = "Resource missing"),
(status = 422, description = "Unprocessable request"),
(status = 403, description = "Forbidden"),
),
tag = "Routing",
operation_id = "Evaluate routing rules",
security(("api_key" = []))
)]
pub async fn call_decide_gateway_open_router() {}
#[cfg(feature = "v1")]
/// Routing - Feedback
///
/// Update gateway scores for dynamic routing
#[utoipa::path(
post,
path = "/routing/feedback",
request_body = UpdateScorePayload,
responses(
(status = 200, description = "Gateway score updated successfully", body = UpdateScoreResponse),
(status = 400, description = "Request body is malformed"),
(status = 500, description = "Internal server error"),
(status = 404, description = "Resource missing"),
(status = 422, description = "Unprocessable request"),
(status = 403, description = "Forbidden"),
),
tag = "Routing",
operation_id = "Update gateway scores",
security(("api_key" = []))
)]
pub async fn call_update_gateway_score_open_router() {}
#[cfg(feature = "v1")]
/// Routing - Rule Evaluate
///
/// Evaluate routing rules
#[utoipa::path(
post,
path = "/routing/rule/evaluate",
request_body = RoutingEvaluateRequest,
responses(
(status = 200, description = "Routing rules evaluated successfully", body = RoutingEvaluateResponse),
(status = 400, description = "Request body is malformed"),
(status = 500, description = "Internal server error"),
(status = 404, description = "Resource missing"),
(status = 422, description = "Unprocessable request"),
(status = 403, description = "Forbidden"),
),
tag = "Routing",
operation_id = "Evaluate routing rules (alternative)",
security(("api_key" = []))
)]
pub async fn evaluate_routing_rule() {}

View File

@ -3,7 +3,9 @@ use std::collections::{HashMap, HashSet};
use api_models::{
open_router as or_types,
routing::{
self as api_routing, ConnectorSelection, ConnectorVolumeSplit, RoutableConnectorChoice,
self as api_routing, ComparisonType, ConnectorSelection, ConnectorVolumeSplit,
DeRoutableConnectorChoice, MetadataValue, NumberComparison, RoutableConnectorChoice,
RoutingEvaluateRequest, RoutingEvaluateResponse, ValueType,
},
};
use async_trait::async_trait;
@ -683,99 +685,6 @@ impl DecisionEngineErrorsInterface for or_types::ErrorResponse {
}
}
//TODO: temporary change will be refactored afterwards
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize, PartialEq)]
pub struct RoutingEvaluateRequest {
pub created_by: String,
pub parameters: HashMap<String, Option<ValueType>>,
pub fallback_output: Vec<DeRoutableConnectorChoice>,
}
impl common_utils::events::ApiEventMetric for RoutingEvaluateRequest {}
#[derive(Debug, serde::Serialize, serde::Deserialize, Clone)]
pub struct RoutingEvaluateResponse {
pub status: String,
pub output: serde_json::Value,
#[serde(deserialize_with = "deserialize_connector_choices")]
pub evaluated_output: Vec<RoutableConnectorChoice>,
#[serde(deserialize_with = "deserialize_connector_choices")]
pub eligible_connectors: Vec<RoutableConnectorChoice>,
}
impl common_utils::events::ApiEventMetric for RoutingEvaluateResponse {}
/// Routable Connector chosen for a payment
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct DeRoutableConnectorChoice {
pub gateway_name: common_enums::RoutableConnectors,
pub gateway_id: Option<id_type::MerchantConnectorAccountId>,
}
fn deserialize_connector_choices<'de, D>(
deserializer: D,
) -> Result<Vec<RoutableConnectorChoice>, D::Error>
where
D: serde::Deserializer<'de>,
{
let infos = Vec::<DeRoutableConnectorChoice>::deserialize(deserializer)?;
Ok(infos
.into_iter()
.map(RoutableConnectorChoice::from)
.collect())
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct MetadataValue {
pub key: String,
pub value: String,
}
/// Represents a value in the DSL
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(tag = "type", content = "value", rename_all = "snake_case")]
pub enum ValueType {
/// Represents a number literal
Number(u64),
/// Represents an enum variant
EnumVariant(String),
/// Represents a Metadata variant
MetadataVariant(MetadataValue),
/// Represents a arbitrary String value
StrValue(String),
/// Represents a global reference, which is a reference to a global variable
GlobalRef(String),
/// Represents an array of numbers. This is basically used for
/// "one of the given numbers" operations
/// eg: payment.method.amount = (1, 2, 3)
NumberArray(Vec<u64>),
/// Similar to NumberArray but for enum variants
/// eg: payment.method.cardtype = (debit, credit)
EnumVariantArray(Vec<String>),
/// Like a number array but can include comparisons. Useful for
/// conditions like "500 < amount < 1000"
/// eg: payment.amount = (> 500, < 1000)
NumberComparisonArray(Vec<NumberComparison>),
}
pub type Metadata = HashMap<String, serde_json::Value>;
/// Represents a number comparison for "NumberComparisonArrayValue"
#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub struct NumberComparison {
pub comparison_type: ComparisonType,
pub number: u64,
}
/// Conditional comparison type
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ComparisonType {
Equal,
NotEqual,
LessThan,
LessThanEqual,
GreaterThan,
GreaterThanEqual,
}
/// Represents a single comparison condition.
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
@ -875,16 +784,6 @@ impl ConnectorInfo {
}
}
impl From<DeRoutableConnectorChoice> for RoutableConnectorChoice {
fn from(choice: DeRoutableConnectorChoice) -> Self {
Self {
choice_kind: api_routing::RoutableChoiceKind::FullStruct,
connector: choice.gateway_name,
merchant_connector_id: choice.gateway_id,
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Output {
@ -896,6 +795,7 @@ pub enum Output {
pub type Globals = HashMap<String, HashSet<ValueType>>;
pub type Metadata = HashMap<String, serde_json::Value>;
/// The program, having a default connector selection and
/// a bunch of rules. Also can hold arbitrary metadata.
#[derive(Clone, Debug, Serialize, Deserialize)]

View File

@ -6,7 +6,10 @@
use actix_web::{web, HttpRequest, Responder};
use api_models::{
enums,
routing::{self as routing_types, RoutingRetrieveQuery},
routing::{
self as routing_types, RoutingEvaluateRequest, RoutingEvaluateResponse,
RoutingRetrieveQuery,
},
};
use error_stack::ResultExt;
use hyperswitch_domain_models::merchant_context::MerchantKeyStore;
@ -19,10 +22,7 @@ use router_env::{
use crate::{
core::{
api_locking, conditional_config,
payments::routing::utils::{
DecisionEngineApiHandler, EuclidApiClient, RoutingEvaluateRequest,
RoutingEvaluateResponse,
},
payments::routing::utils::{DecisionEngineApiHandler, EuclidApiClient},
routing, surcharge_decision_config,
},
db::errors::StorageErrorExt,