mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-30 17:47:54 +08:00
feat: add payout service (#1665)
Co-authored-by: Kashif <mohammed.kashif@juspay.in> Co-authored-by: Manoj Ghorela <manoj.ghorela@juspay.in> Co-authored-by: Manoj Ghorela <118727120+manoj-juspay@users.noreply.github.com>
This commit is contained in:
@ -35,6 +35,15 @@ pub struct MerchantAccountCreate {
|
||||
#[schema(value_type = Option<Object>,example = json!({"type": "single", "data": "stripe"}))]
|
||||
pub routing_algorithm: Option<serde_json::Value>,
|
||||
|
||||
/// 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"}))]
|
||||
#[serde(
|
||||
default,
|
||||
deserialize_with = "payout_routing_algorithm::deserialize_option"
|
||||
)]
|
||||
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.
|
||||
#[schema(default = false, example = false)]
|
||||
pub sub_merchants_enabled: Option<bool>,
|
||||
@ -113,6 +122,15 @@ pub struct MerchantAccountUpdate {
|
||||
#[schema(value_type = Option<Object>,example = json!({"type": "single", "data": "stripe"}))]
|
||||
pub routing_algorithm: Option<serde_json::Value>,
|
||||
|
||||
/// 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"}))]
|
||||
#[serde(
|
||||
default,
|
||||
deserialize_with = "payout_routing_algorithm::deserialize_option"
|
||||
)]
|
||||
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.
|
||||
#[schema(default = false, example = false)]
|
||||
pub sub_merchants_enabled: Option<bool>,
|
||||
@ -194,6 +212,15 @@ pub struct MerchantAccountResponse {
|
||||
#[schema(value_type = Option<RoutingAlgorithm>, max_length = 255, example = "custom")]
|
||||
pub routing_algorithm: Option<serde_json::Value>,
|
||||
|
||||
/// 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"}))]
|
||||
#[serde(
|
||||
default,
|
||||
deserialize_with = "payout_routing_algorithm::deserialize_option"
|
||||
)]
|
||||
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.
|
||||
#[schema(default = false, example = false)]
|
||||
pub sub_merchants_enabled: Option<bool>,
|
||||
@ -273,6 +300,117 @@ pub struct MerchantDetails {
|
||||
/// The merchant's address details
|
||||
pub address: Option<AddressDetails>,
|
||||
}
|
||||
#[cfg(feature = "payouts")]
|
||||
pub mod payout_routing_algorithm {
|
||||
use std::{fmt, str::FromStr};
|
||||
|
||||
use serde::{
|
||||
de::{self, Visitor},
|
||||
Deserializer,
|
||||
};
|
||||
use serde_json::Map;
|
||||
|
||||
use super::PayoutRoutingAlgorithm;
|
||||
use crate::enums::PayoutConnectors;
|
||||
struct RoutingAlgorithmVisitor;
|
||||
struct OptionalRoutingAlgorithmVisitor;
|
||||
|
||||
impl<'de> Visitor<'de> for RoutingAlgorithmVisitor {
|
||||
type Value = serde_json::Value;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
formatter.write_str("routing algorithm")
|
||||
}
|
||||
|
||||
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
|
||||
where
|
||||
A: de::MapAccess<'de>,
|
||||
{
|
||||
let mut output = serde_json::Value::Object(Map::new());
|
||||
let mut routing_data: String = "".to_string();
|
||||
let mut routing_type: String = "".to_string();
|
||||
|
||||
while let Some(key) = map.next_key()? {
|
||||
match key {
|
||||
"type" => {
|
||||
routing_type = map.next_value()?;
|
||||
output["type"] = serde_json::Value::String(routing_type.to_owned());
|
||||
}
|
||||
"data" => {
|
||||
routing_data = map.next_value()?;
|
||||
output["data"] = serde_json::Value::String(routing_data.to_owned());
|
||||
}
|
||||
f => {
|
||||
output[f] = map.next_value()?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
match routing_type.as_ref() {
|
||||
"single" => {
|
||||
let routable_payout_connector = PayoutConnectors::from_str(&routing_data);
|
||||
let routable_conn = match routable_payout_connector {
|
||||
Ok(rpc) => Ok(rpc),
|
||||
Err(_) => Err(de::Error::custom(format!(
|
||||
"Unknown payout connector {routing_data}"
|
||||
))),
|
||||
}?;
|
||||
Ok(PayoutRoutingAlgorithm::Single(routable_conn))
|
||||
}
|
||||
u => Err(de::Error::custom(format!("Unknown routing algorithm {u}"))),
|
||||
}?;
|
||||
Ok(output)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Visitor<'de> for OptionalRoutingAlgorithmVisitor {
|
||||
type Value = Option<serde_json::Value>;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
formatter.write_str("routing algorithm")
|
||||
}
|
||||
|
||||
fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
deserializer
|
||||
.deserialize_any(RoutingAlgorithmVisitor)
|
||||
.map(Some)
|
||||
}
|
||||
|
||||
fn visit_none<E>(self) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn visit_unit<E>(self) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn deserialize<'a, D>(deserializer: D) -> Result<serde_json::Value, D::Error>
|
||||
where
|
||||
D: Deserializer<'a>,
|
||||
{
|
||||
deserializer.deserialize_any(RoutingAlgorithmVisitor)
|
||||
}
|
||||
|
||||
pub(crate) fn deserialize_option<'a, D>(
|
||||
deserializer: D,
|
||||
) -> Result<Option<serde_json::Value>, D::Error>
|
||||
where
|
||||
D: Deserializer<'a>,
|
||||
{
|
||||
deserializer.deserialize_option(OptionalRoutingAlgorithmVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[serde(tag = "type", content = "data", rename_all = "snake_case")]
|
||||
@ -787,3 +925,17 @@ pub struct MerchantConnectorDetails {
|
||||
#[schema(value_type = Option<Object>,max_length = 255,example = json!({ "city": "NY", "unit": "245" }))]
|
||||
pub metadata: Option<pii::SecretSerdeValue>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "payouts")]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[serde(tag = "type", content = "data", rename_all = "snake_case")]
|
||||
pub enum PayoutRoutingAlgorithm {
|
||||
Single(api_enums::PayoutConnectors),
|
||||
}
|
||||
|
||||
#[cfg(feature = "payouts")]
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[serde(tag = "type", content = "data", rename_all = "snake_case")]
|
||||
pub enum PayoutStraightThroughAlgorithm {
|
||||
Single(api_enums::PayoutConnectors),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user