mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-28 12:15:40 +08:00
feat(payouts): add payout types in euclid crate (#3862)
Co-authored-by: Kashif <mohammed.kashif@juspay.in>
This commit is contained in:
@ -2057,12 +2057,15 @@ pub enum PayoutStatus {
|
||||
Debug,
|
||||
Default,
|
||||
Eq,
|
||||
Hash,
|
||||
PartialEq,
|
||||
ToSchema,
|
||||
serde::Deserialize,
|
||||
serde::Serialize,
|
||||
strum::Display,
|
||||
strum::EnumVariantNames,
|
||||
strum::EnumIter,
|
||||
strum::EnumString,
|
||||
ToSchema,
|
||||
)]
|
||||
#[router_derive::diesel_enum(storage_type = "db_enum")]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
|
||||
@ -23,10 +23,12 @@ common_enums = { version = "0.1.0", path = "../common_enums" }
|
||||
euclid_macros = { version = "0.1.0", path = "../euclid_macros" }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
ast_parser = ["dep:nom"]
|
||||
valued_jit = []
|
||||
connector_choice_mca_id = []
|
||||
dummy_connector = []
|
||||
payouts = []
|
||||
|
||||
[dev-dependencies]
|
||||
criterion = "0.5"
|
||||
|
||||
@ -34,6 +34,12 @@ collect_variants!(CaptureMethod);
|
||||
collect_variants!(Currency);
|
||||
collect_variants!(Country);
|
||||
collect_variants!(SetupFutureUsage);
|
||||
#[cfg(feature = "payouts")]
|
||||
collect_variants!(PayoutType);
|
||||
#[cfg(feature = "payouts")]
|
||||
collect_variants!(PayoutBankTransferType);
|
||||
#[cfg(feature = "payouts")]
|
||||
collect_variants!(PayoutWalletType);
|
||||
|
||||
#[derive(
|
||||
Clone,
|
||||
@ -94,3 +100,67 @@ pub enum MandateType {
|
||||
SingleUse,
|
||||
MultiUse,
|
||||
}
|
||||
|
||||
#[cfg(feature = "payouts")]
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
Hash,
|
||||
PartialEq,
|
||||
Eq,
|
||||
strum::Display,
|
||||
strum::EnumVariantNames,
|
||||
strum::EnumIter,
|
||||
strum::EnumString,
|
||||
serde::Serialize,
|
||||
serde::Deserialize,
|
||||
)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum PayoutBankTransferType {
|
||||
Ach,
|
||||
Bacs,
|
||||
Sepa,
|
||||
}
|
||||
|
||||
#[cfg(feature = "payouts")]
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
Hash,
|
||||
PartialEq,
|
||||
Eq,
|
||||
strum::Display,
|
||||
strum::EnumVariantNames,
|
||||
strum::EnumIter,
|
||||
strum::EnumString,
|
||||
serde::Serialize,
|
||||
serde::Deserialize,
|
||||
)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum PayoutWalletType {
|
||||
Paypal,
|
||||
}
|
||||
|
||||
#[cfg(feature = "payouts")]
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
Hash,
|
||||
PartialEq,
|
||||
Eq,
|
||||
strum::Display,
|
||||
strum::EnumVariantNames,
|
||||
strum::EnumIter,
|
||||
strum::EnumString,
|
||||
serde::Serialize,
|
||||
serde::Deserialize,
|
||||
)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum PayoutType {
|
||||
Card,
|
||||
BankTransfer,
|
||||
Wallet,
|
||||
}
|
||||
|
||||
@ -667,6 +667,101 @@ impl DirValue {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "payouts")]
|
||||
#[derive(
|
||||
Debug,
|
||||
Clone,
|
||||
Hash,
|
||||
PartialEq,
|
||||
Eq,
|
||||
serde::Serialize,
|
||||
strum::Display,
|
||||
strum::EnumIter,
|
||||
strum::EnumVariantNames,
|
||||
strum::EnumString,
|
||||
strum::EnumMessage,
|
||||
strum::EnumProperty,
|
||||
)]
|
||||
pub enum PayoutDirKeyKind {
|
||||
#[strum(
|
||||
serialize = "country",
|
||||
serialize = "business_country",
|
||||
detailed_message = "Country of the business unit",
|
||||
props(Category = "Merchant")
|
||||
)]
|
||||
#[serde(rename = "business_country", alias = "country")]
|
||||
BusinessCountry,
|
||||
|
||||
#[strum(
|
||||
serialize = "billing_country",
|
||||
detailed_message = "Country of the billing address of the customer",
|
||||
props(Category = "Customer")
|
||||
)]
|
||||
#[serde(rename = "billing_country")]
|
||||
BillingCountry,
|
||||
|
||||
#[strum(
|
||||
serialize = "business_label",
|
||||
detailed_message = "Identifier for business unit",
|
||||
props(Category = "Merchant")
|
||||
)]
|
||||
#[serde(rename = "business_label")]
|
||||
BusinessLabel,
|
||||
|
||||
#[strum(
|
||||
serialize = "amount",
|
||||
detailed_message = "Value of the transaction",
|
||||
props(Category = "Order details")
|
||||
)]
|
||||
#[serde(rename = "amount")]
|
||||
PayoutAmount,
|
||||
|
||||
#[strum(
|
||||
serialize = "payment_method",
|
||||
detailed_message = "Different modes of payout - eg. cards, wallets, banks",
|
||||
props(Category = "Payout Methods")
|
||||
)]
|
||||
#[serde(rename = "payment_method")]
|
||||
PayoutType,
|
||||
|
||||
#[strum(
|
||||
serialize = "wallet",
|
||||
detailed_message = "Supported types of Wallets for payouts",
|
||||
props(Category = "Payout Methods Type")
|
||||
)]
|
||||
#[serde(rename = "wallet")]
|
||||
WalletType,
|
||||
|
||||
#[strum(
|
||||
serialize = "bank_transfer",
|
||||
detailed_message = "Supported types of Bank transfer types for payouts",
|
||||
props(Category = "Payout Methods Type")
|
||||
)]
|
||||
#[serde(rename = "bank_transfer")]
|
||||
BankTransferType,
|
||||
}
|
||||
|
||||
#[cfg(feature = "payouts")]
|
||||
#[derive(
|
||||
Debug, Clone, Hash, PartialEq, Eq, serde::Serialize, strum::Display, strum::EnumVariantNames,
|
||||
)]
|
||||
pub enum PayoutDirValue {
|
||||
#[serde(rename = "business_country", alias = "country")]
|
||||
BusinessCountry(enums::Country),
|
||||
#[serde(rename = "billing_country")]
|
||||
BillingCountry(enums::Country),
|
||||
#[serde(rename = "business_label")]
|
||||
BusinessLabel(types::StrValue),
|
||||
#[serde(rename = "amount")]
|
||||
PayoutAmount(types::NumValue),
|
||||
#[serde(rename = "payment_method")]
|
||||
PayoutType(common_enums::PayoutType),
|
||||
#[serde(rename = "wallet")]
|
||||
WalletType(enums::PayoutWalletType),
|
||||
#[serde(rename = "bank_transfer")]
|
||||
BankTransferType(enums::PayoutBankTransferType),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum DirComparisonLogic {
|
||||
NegativeConjunction,
|
||||
|
||||
@ -6,6 +6,8 @@ pub use crate::enums::{
|
||||
Country as BillingCountry, Currency as PaymentCurrency, MandateAcceptanceType, MandateType,
|
||||
PaymentMethod, PaymentType, RoutableConnectors, SetupFutureUsage,
|
||||
};
|
||||
#[cfg(feature = "payouts")]
|
||||
pub use crate::enums::{PayoutBankTransferType, PayoutType, PayoutWalletType};
|
||||
|
||||
#[derive(
|
||||
Clone,
|
||||
|
||||
@ -11,14 +11,14 @@ crate-type = ["cdylib"]
|
||||
|
||||
[features]
|
||||
default = ["connector_choice_bcompat", "payouts", "connector_choice_mca_id"]
|
||||
release = ["connector_choice_bcompat", "connector_choice_mca_id"]
|
||||
release = ["connector_choice_bcompat", "connector_choice_mca_id", "payouts"]
|
||||
connector_choice_bcompat = ["api_models/connector_choice_bcompat"]
|
||||
connector_choice_mca_id = ["api_models/connector_choice_mca_id", "euclid/connector_choice_mca_id", "kgraph_utils/connector_choice_mca_id"]
|
||||
dummy_connector = ["kgraph_utils/dummy_connector", "connector_configs/dummy_connector"]
|
||||
production = ["connector_configs/production"]
|
||||
development = ["connector_configs/development"]
|
||||
sandbox = ["connector_configs/sandbox"]
|
||||
payouts = ["api_models/payouts"]
|
||||
payouts = ["api_models/payouts", "euclid/payouts"]
|
||||
|
||||
[dependencies]
|
||||
api_models = { version = "0.1.0", path = "../api_models", package = "api_models" }
|
||||
|
||||
@ -256,12 +256,13 @@ pub fn get_variant_values(key: &str) -> Result<JsValue, JsValue> {
|
||||
dir::DirKeyKind::CardRedirectType => dir_enums::CardRedirectType::VARIANTS,
|
||||
dir::DirKeyKind::GiftCardType => dir_enums::GiftCardType::VARIANTS,
|
||||
dir::DirKeyKind::VoucherType => dir_enums::VoucherType::VARIANTS,
|
||||
dir::DirKeyKind::BankDebitType => dir_enums::BankDebitType::VARIANTS,
|
||||
|
||||
dir::DirKeyKind::PaymentAmount
|
||||
| dir::DirKeyKind::Connector
|
||||
| dir::DirKeyKind::CardBin
|
||||
| dir::DirKeyKind::BusinessLabel
|
||||
| dir::DirKeyKind::MetaData => Err("Key does not have variants".to_string())?,
|
||||
dir::DirKeyKind::BankDebitType => dir_enums::BankDebitType::VARIANTS,
|
||||
};
|
||||
|
||||
Ok(serde_wasm_bindgen::to_value(variants)?)
|
||||
@ -335,3 +336,52 @@ pub fn get_response_payload(input: JsValue) -> JsResult {
|
||||
let result = ConnectorApiIntegrationPayload::get_transformed_response_payload(input);
|
||||
Ok(serde_wasm_bindgen::to_value(&result)?)
|
||||
}
|
||||
|
||||
#[cfg(feature = "payouts")]
|
||||
#[wasm_bindgen(js_name = getAllPayoutKeys)]
|
||||
pub fn get_all_payout_keys() -> JsResult {
|
||||
let keys: Vec<&'static str> = dir::PayoutDirKeyKind::VARIANTS.to_vec();
|
||||
Ok(serde_wasm_bindgen::to_value(&keys)?)
|
||||
}
|
||||
|
||||
#[cfg(feature = "payouts")]
|
||||
#[wasm_bindgen(js_name = getPayoutVariantValues)]
|
||||
pub fn get_payout_variant_values(key: &str) -> Result<JsValue, JsValue> {
|
||||
let key =
|
||||
dir::PayoutDirKeyKind::from_str(key).map_err(|_| "Invalid key received".to_string())?;
|
||||
|
||||
let variants: &[&str] = match key {
|
||||
dir::PayoutDirKeyKind::BusinessCountry => dir_enums::BusinessCountry::VARIANTS,
|
||||
dir::PayoutDirKeyKind::BillingCountry => dir_enums::BillingCountry::VARIANTS,
|
||||
dir::PayoutDirKeyKind::PayoutType => dir_enums::PayoutType::VARIANTS,
|
||||
dir::PayoutDirKeyKind::WalletType => dir_enums::PayoutWalletType::VARIANTS,
|
||||
dir::PayoutDirKeyKind::BankTransferType => dir_enums::PayoutBankTransferType::VARIANTS,
|
||||
|
||||
dir::PayoutDirKeyKind::PayoutAmount | dir::PayoutDirKeyKind::BusinessLabel => {
|
||||
Err("Key does not have variants".to_string())?
|
||||
}
|
||||
};
|
||||
|
||||
Ok(serde_wasm_bindgen::to_value(variants)?)
|
||||
}
|
||||
|
||||
#[cfg(feature = "payouts")]
|
||||
#[wasm_bindgen(js_name = getPayoutDescriptionCategory)]
|
||||
pub fn get_payout_description_category() -> JsResult {
|
||||
let keys = dir::PayoutDirKeyKind::VARIANTS.to_vec();
|
||||
let mut category: HashMap<Option<&str>, Vec<types::PayoutDetails<'_>>> = HashMap::new();
|
||||
for key in keys {
|
||||
let dir_key =
|
||||
dir::PayoutDirKeyKind::from_str(key).map_err(|_| "Invalid key received".to_string())?;
|
||||
let details = types::PayoutDetails {
|
||||
description: dir_key.get_detailed_message(),
|
||||
kind: dir_key.clone(),
|
||||
};
|
||||
category
|
||||
.entry(dir_key.get_str("Category"))
|
||||
.and_modify(|val| val.push(details.clone()))
|
||||
.or_insert(vec![details]);
|
||||
}
|
||||
|
||||
Ok(serde_wasm_bindgen::to_value(&category)?)
|
||||
}
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
use euclid::frontend::dir::DirKeyKind;
|
||||
#[cfg(feature = "payouts")]
|
||||
use euclid::frontend::dir::PayoutDirKeyKind;
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Serialize, Clone)]
|
||||
@ -6,3 +8,10 @@ pub struct Details<'a> {
|
||||
pub description: Option<&'a str>,
|
||||
pub kind: DirKeyKind,
|
||||
}
|
||||
|
||||
#[cfg(feature = "payouts")]
|
||||
#[derive(Serialize, Clone)]
|
||||
pub struct PayoutDetails<'a> {
|
||||
pub description: Option<&'a str>,
|
||||
pub kind: PayoutDirKeyKind,
|
||||
}
|
||||
|
||||
@ -714,6 +714,7 @@ pub async fn retrieve_linked_routing_config(
|
||||
state: AppState,
|
||||
merchant_account: domain::MerchantAccount,
|
||||
#[cfg(feature = "business_profile_routing")] query_params: RoutingRetrieveLinkQuery,
|
||||
#[cfg(feature = "business_profile_routing")] transaction_type: &enums::TransactionType,
|
||||
) -> RouterResponse<routing_types::LinkedRoutingConfigRetrieveResponse> {
|
||||
metrics::ROUTING_RETRIEVE_LINK_CONFIG.add(&metrics::CONTEXT, 1, &[]);
|
||||
let db = state.store.as_ref();
|
||||
@ -739,16 +740,17 @@ pub async fn retrieve_linked_routing_config(
|
||||
let mut active_algorithms = Vec::new();
|
||||
|
||||
for business_profile in business_profiles {
|
||||
let routing_ref: routing_types::RoutingAlgorithmRef = business_profile
|
||||
.routing_algorithm
|
||||
.clone()
|
||||
.map(|val| val.parse_value("RoutingAlgorithmRef"))
|
||||
.transpose()
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable(
|
||||
"unable to deserialize routing algorithm ref from merchant account",
|
||||
)?
|
||||
.unwrap_or_default();
|
||||
let routing_ref: routing_types::RoutingAlgorithmRef = match transaction_type {
|
||||
enums::TransactionType::Payment => business_profile.routing_algorithm,
|
||||
#[cfg(feature = "payouts")]
|
||||
enums::TransactionType::Payout => business_profile.payout_routing_algorithm,
|
||||
}
|
||||
.clone()
|
||||
.map(|val| val.parse_value("RoutingAlgorithmRef"))
|
||||
.transpose()
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("unable to deserialize routing algorithm ref from merchant account")?
|
||||
.unwrap_or_default();
|
||||
|
||||
if let Some(algorithm_id) = routing_ref.algorithm_id {
|
||||
let record = db
|
||||
|
||||
@ -401,10 +401,18 @@ impl Routing {
|
||||
#[allow(unused_mut)]
|
||||
let mut route = web::scope("/routing")
|
||||
.app_data(web::Data::new(state.clone()))
|
||||
.service(
|
||||
web::resource("/active")
|
||||
.route(web::get().to(cloud_routing::routing_retrieve_linked_config)),
|
||||
)
|
||||
.service(web::resource("/active").route(web::get().to(
|
||||
|state, req, #[cfg(feature = "business_profile_routing")] query_params| {
|
||||
cloud_routing::routing_retrieve_linked_config(
|
||||
state,
|
||||
req,
|
||||
#[cfg(feature = "business_profile_routing")]
|
||||
query_params,
|
||||
#[cfg(feature = "business_profile_routing")]
|
||||
&TransactionType::Payment,
|
||||
)
|
||||
},
|
||||
)))
|
||||
.service(
|
||||
web::resource("")
|
||||
.route(
|
||||
@ -524,6 +532,18 @@ impl Routing {
|
||||
)
|
||||
})),
|
||||
)
|
||||
.service(web::resource("/payouts/active").route(web::get().to(
|
||||
|state, req, #[cfg(feature = "business_profile_routing")] query_params| {
|
||||
cloud_routing::routing_retrieve_linked_config(
|
||||
state,
|
||||
req,
|
||||
#[cfg(feature = "business_profile_routing")]
|
||||
query_params,
|
||||
#[cfg(feature = "business_profile_routing")]
|
||||
&TransactionType::Payout,
|
||||
)
|
||||
},
|
||||
)))
|
||||
.service(
|
||||
web::resource("/payouts/default")
|
||||
.route(web::get().to(|state, req| {
|
||||
|
||||
@ -509,6 +509,7 @@ pub async fn routing_retrieve_linked_config(
|
||||
state: web::Data<AppState>,
|
||||
req: HttpRequest,
|
||||
#[cfg(feature = "business_profile_routing")] query: web::Query<RoutingRetrieveLinkQuery>,
|
||||
#[cfg(feature = "business_profile_routing")] transaction_type: &enums::TransactionType,
|
||||
) -> impl Responder {
|
||||
#[cfg(feature = "business_profile_routing")]
|
||||
{
|
||||
@ -520,7 +521,12 @@ pub async fn routing_retrieve_linked_config(
|
||||
&req,
|
||||
query.into_inner(),
|
||||
|state, auth: AuthenticationData, query_params| {
|
||||
routing::retrieve_linked_routing_config(state, auth.merchant_account, query_params)
|
||||
routing::retrieve_linked_routing_config(
|
||||
state,
|
||||
auth.merchant_account,
|
||||
query_params,
|
||||
transaction_type,
|
||||
)
|
||||
},
|
||||
#[cfg(not(feature = "release"))]
|
||||
auth::auth_type(
|
||||
|
||||
Reference in New Issue
Block a user