mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-28 12:15:40 +08:00
refactor: use hashmap deserializer for generic_link options (#5157)
Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
This commit is contained in:
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -1990,6 +1990,7 @@ dependencies = [
|
|||||||
"thiserror",
|
"thiserror",
|
||||||
"time",
|
"time",
|
||||||
"tokio 1.37.0",
|
"tokio 1.37.0",
|
||||||
|
"url",
|
||||||
"utoipa",
|
"utoipa",
|
||||||
"uuid",
|
"uuid",
|
||||||
]
|
]
|
||||||
@ -4311,6 +4312,7 @@ dependencies = [
|
|||||||
"serde_json",
|
"serde_json",
|
||||||
"subtle",
|
"subtle",
|
||||||
"time",
|
"time",
|
||||||
|
"url",
|
||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@ -9154,7 +9154,8 @@
|
|||||||
"items": {
|
"items": {
|
||||||
"$ref": "#/components/schemas/PaymentMethodType"
|
"$ref": "#/components/schemas/PaymentMethodType"
|
||||||
},
|
},
|
||||||
"description": "An array of associated payment method types"
|
"description": "An array of associated payment method types",
|
||||||
|
"uniqueItems": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -561,9 +561,9 @@ theme = "#1A1A1A"
|
|||||||
logo = "https://app.hyperswitch.io/HyperswitchFavicon.png"
|
logo = "https://app.hyperswitch.io/HyperswitchFavicon.png"
|
||||||
merchant_name = "HyperSwitch"
|
merchant_name = "HyperSwitch"
|
||||||
[generic_link.payment_method_collect.enabled_payment_methods]
|
[generic_link.payment_method_collect.enabled_payment_methods]
|
||||||
card = ["credit", "debit"]
|
card = "credit,debit"
|
||||||
bank_transfer = ["ach", "bacs", "sepa"]
|
bank_transfer = "ach,bacs,sepa"
|
||||||
wallet = ["paypal", "pix", "venmo"]
|
wallet = "paypal,pix,venmo"
|
||||||
|
|
||||||
[generic_link.payout_link]
|
[generic_link.payout_link]
|
||||||
sdk_url = "http://localhost:9090/0.16.7/v0/HyperLoader.js"
|
sdk_url = "http://localhost:9090/0.16.7/v0/HyperLoader.js"
|
||||||
@ -573,9 +573,9 @@ theme = "#1A1A1A"
|
|||||||
logo = "https://app.hyperswitch.io/HyperswitchFavicon.png"
|
logo = "https://app.hyperswitch.io/HyperswitchFavicon.png"
|
||||||
merchant_name = "HyperSwitch"
|
merchant_name = "HyperSwitch"
|
||||||
[generic_link.payout_link.enabled_payment_methods]
|
[generic_link.payout_link.enabled_payment_methods]
|
||||||
card = ["credit", "debit"]
|
card = "credit,debit"
|
||||||
bank_transfer = ["ach", "bacs", "sepa"]
|
bank_transfer = "ach,bacs,sepa"
|
||||||
wallet = ["paypal", "pix", "venmo"]
|
wallet = "paypal,pix,venmo"
|
||||||
|
|
||||||
[payment_link]
|
[payment_link]
|
||||||
sdk_url = "http://localhost:9090/0.16.7/v0/HyperLoader.js"
|
sdk_url = "http://localhost:9090/0.16.7/v0/HyperLoader.js"
|
||||||
|
|||||||
@ -165,9 +165,9 @@ theme = "#4285F4"
|
|||||||
logo = "https://app.hyperswitch.io/HyperswitchFavicon.png"
|
logo = "https://app.hyperswitch.io/HyperswitchFavicon.png"
|
||||||
merchant_name = "HyperSwitch"
|
merchant_name = "HyperSwitch"
|
||||||
[generic_link.payment_method_collect.enabled_payment_methods]
|
[generic_link.payment_method_collect.enabled_payment_methods]
|
||||||
card = ["credit", "debit"]
|
card = "credit,debit"
|
||||||
bank_transfer = ["ach", "bacs", "sepa"]
|
bank_transfer = "ach,bacs,sepa"
|
||||||
wallet = ["paypal", "pix", "venmo"]
|
wallet = "paypal,pix,venmo"
|
||||||
|
|
||||||
[generic_link.payout_link]
|
[generic_link.payout_link]
|
||||||
sdk_url = "http://localhost:9090/0.16.7/v0/HyperLoader.js"
|
sdk_url = "http://localhost:9090/0.16.7/v0/HyperLoader.js"
|
||||||
@ -177,9 +177,9 @@ theme = "#4285F4"
|
|||||||
logo = "https://app.hyperswitch.io/HyperswitchFavicon.png"
|
logo = "https://app.hyperswitch.io/HyperswitchFavicon.png"
|
||||||
merchant_name = "HyperSwitch"
|
merchant_name = "HyperSwitch"
|
||||||
[generic_link.payout_link.enabled_payment_methods]
|
[generic_link.payout_link.enabled_payment_methods]
|
||||||
card = ["credit", "debit"]
|
card = "credit,debit"
|
||||||
bank_transfer = ["ach", "bacs", "sepa"]
|
bank_transfer = "ach,bacs,sepa"
|
||||||
wallet = ["paypal", "pix", "venmo"]
|
wallet = "paypal,pix,venmo"
|
||||||
|
|
||||||
[payment_link]
|
[payment_link]
|
||||||
sdk_url = "http://localhost:9090/0.16.7/v0/HyperLoader.js"
|
sdk_url = "http://localhost:9090/0.16.7/v0/HyperLoader.js"
|
||||||
|
|||||||
@ -576,9 +576,9 @@ theme = "#4285F4"
|
|||||||
logo = "https://app.hyperswitch.io/HyperswitchFavicon.png"
|
logo = "https://app.hyperswitch.io/HyperswitchFavicon.png"
|
||||||
merchant_name = "HyperSwitch"
|
merchant_name = "HyperSwitch"
|
||||||
[generic_link.payment_method_collect.enabled_payment_methods]
|
[generic_link.payment_method_collect.enabled_payment_methods]
|
||||||
card = ["credit", "debit"]
|
card = "credit,debit"
|
||||||
bank_transfer = ["ach", "bacs", "sepa"]
|
bank_transfer = "ach,bacs,sepa"
|
||||||
wallet = ["paypal", "pix", "venmo"]
|
wallet = "paypal,pix,venmo"
|
||||||
|
|
||||||
[generic_link.payout_link]
|
[generic_link.payout_link]
|
||||||
sdk_url = "http://localhost:9050/HyperLoader.js"
|
sdk_url = "http://localhost:9050/HyperLoader.js"
|
||||||
@ -588,9 +588,9 @@ theme = "#4285F4"
|
|||||||
logo = "https://app.hyperswitch.io/HyperswitchFavicon.png"
|
logo = "https://app.hyperswitch.io/HyperswitchFavicon.png"
|
||||||
merchant_name = "HyperSwitch"
|
merchant_name = "HyperSwitch"
|
||||||
[generic_link.payout_link.enabled_payment_methods]
|
[generic_link.payout_link.enabled_payment_methods]
|
||||||
card = ["credit", "debit"]
|
card = "credit,debit"
|
||||||
bank_transfer = ["ach", "bacs", "sepa"]
|
bank_transfer = "ach,bacs,sepa"
|
||||||
wallet = ["paypal", "pix", "venmo"]
|
wallet = "paypal,pix,venmo"
|
||||||
|
|
||||||
[payment_link]
|
[payment_link]
|
||||||
sdk_url = "http://localhost:9050/HyperLoader.js"
|
sdk_url = "http://localhost:9050/HyperLoader.js"
|
||||||
|
|||||||
@ -525,9 +525,9 @@ theme = "#4285F4"
|
|||||||
logo = "https://app.hyperswitch.io/HyperswitchFavicon.png"
|
logo = "https://app.hyperswitch.io/HyperswitchFavicon.png"
|
||||||
merchant_name = "HyperSwitch"
|
merchant_name = "HyperSwitch"
|
||||||
[generic_link.payment_method_collect.enabled_payment_methods]
|
[generic_link.payment_method_collect.enabled_payment_methods]
|
||||||
card = ["credit", "debit"]
|
card = "credit,debit"
|
||||||
bank_transfer = ["ach", "bacs", "sepa"]
|
bank_transfer = "ach,bacs,sepa"
|
||||||
wallet = ["paypal", "pix", "venmo"]
|
wallet = "paypal,pix,venmo"
|
||||||
|
|
||||||
[generic_link.payout_link]
|
[generic_link.payout_link]
|
||||||
sdk_url = "http://localhost:9090/0.16.7/v0/HyperLoader.js"
|
sdk_url = "http://localhost:9090/0.16.7/v0/HyperLoader.js"
|
||||||
@ -537,6 +537,6 @@ theme = "#4285F4"
|
|||||||
logo = "https://app.hyperswitch.io/HyperswitchFavicon.png"
|
logo = "https://app.hyperswitch.io/HyperswitchFavicon.png"
|
||||||
merchant_name = "HyperSwitch"
|
merchant_name = "HyperSwitch"
|
||||||
[generic_link.payout_link.enabled_payment_methods]
|
[generic_link.payout_link.enabled_payment_methods]
|
||||||
card = ["credit", "debit"]
|
card = "credit,debit"
|
||||||
bank_transfer = ["ach", "bacs", "sepa"]
|
bank_transfer = "ach,bacs,sepa"
|
||||||
wallet = ["paypal", "pix", "venmo"]
|
wallet = "paypal,pix,venmo"
|
||||||
|
|||||||
@ -989,7 +989,7 @@ pub struct PaymentMethodCollectLinkResponse {
|
|||||||
|
|
||||||
/// URL to the form's link generated for collecting payment method details.
|
/// URL to the form's link generated for collecting payment method details.
|
||||||
#[schema(value_type = String, example = "https://sandbox.hyperswitch.io/payment_method/collect/pm_collect_link_2bdacf398vwzq5n422S1")]
|
#[schema(value_type = String, example = "https://sandbox.hyperswitch.io/payment_method/collect/pm_collect_link_2bdacf398vwzq5n422S1")]
|
||||||
pub link: masking::Secret<String>,
|
pub link: masking::Secret<url::Url>,
|
||||||
|
|
||||||
/// Redirect to this URL post completion
|
/// Redirect to this URL post completion
|
||||||
#[schema(value_type = Option<String>, example = "https://sandbox.hyperswitch.io/payment_method/collect/pm_collect_link_2bdacf398vwzq5n422S1/status")]
|
#[schema(value_type = Option<String>, example = "https://sandbox.hyperswitch.io/payment_method/collect/pm_collect_link_2bdacf398vwzq5n422S1/status")]
|
||||||
@ -1026,7 +1026,7 @@ pub struct PaymentMethodCollectLinkDetails {
|
|||||||
pub session_expiry: time::PrimitiveDateTime,
|
pub session_expiry: time::PrimitiveDateTime,
|
||||||
pub return_url: Option<String>,
|
pub return_url: Option<String>,
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub ui_config: link_utils::GenericLinkUIConfigFormData,
|
pub ui_config: link_utils::GenericLinkUiConfigFormData,
|
||||||
pub enabled_payment_methods: Option<Vec<link_utils::EnabledPaymentMethod>>,
|
pub enabled_payment_methods: Option<Vec<link_utils::EnabledPaymentMethod>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1036,10 +1036,10 @@ pub struct PaymentMethodCollectLinkStatusDetails {
|
|||||||
pub customer_id: id_type::CustomerId,
|
pub customer_id: id_type::CustomerId,
|
||||||
#[serde(with = "common_utils::custom_serde::iso8601")]
|
#[serde(with = "common_utils::custom_serde::iso8601")]
|
||||||
pub session_expiry: time::PrimitiveDateTime,
|
pub session_expiry: time::PrimitiveDateTime,
|
||||||
pub return_url: Option<String>,
|
pub return_url: Option<url::Url>,
|
||||||
pub status: link_utils::PaymentMethodCollectStatus,
|
pub status: link_utils::PaymentMethodCollectStatus,
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub ui_config: link_utils::GenericLinkUIConfigFormData,
|
pub ui_config: link_utils::GenericLinkUiConfigFormData,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
|
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
|
||||||
|
|||||||
@ -702,7 +702,7 @@ pub struct PayoutListFilters {
|
|||||||
pub struct PayoutLinkResponse {
|
pub struct PayoutLinkResponse {
|
||||||
pub payout_link_id: String,
|
pub payout_link_id: String,
|
||||||
#[schema(value_type = String)]
|
#[schema(value_type = String)]
|
||||||
pub link: Secret<String>,
|
pub link: Secret<url::Url>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, serde::Deserialize, ToSchema, serde::Serialize)]
|
#[derive(Clone, Debug, serde::Deserialize, ToSchema, serde::Serialize)]
|
||||||
@ -720,9 +720,9 @@ pub struct PayoutLinkDetails {
|
|||||||
pub customer_id: id_type::CustomerId,
|
pub customer_id: id_type::CustomerId,
|
||||||
#[serde(with = "common_utils::custom_serde::iso8601")]
|
#[serde(with = "common_utils::custom_serde::iso8601")]
|
||||||
pub session_expiry: PrimitiveDateTime,
|
pub session_expiry: PrimitiveDateTime,
|
||||||
pub return_url: Option<String>,
|
pub return_url: Option<url::Url>,
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub ui_config: link_utils::GenericLinkUIConfigFormData,
|
pub ui_config: link_utils::GenericLinkUiConfigFormData,
|
||||||
pub enabled_payment_methods: Vec<link_utils::EnabledPaymentMethod>,
|
pub enabled_payment_methods: Vec<link_utils::EnabledPaymentMethod>,
|
||||||
pub amount: common_utils::types::StringMajorUnit,
|
pub amount: common_utils::types::StringMajorUnit,
|
||||||
pub currency: common_enums::Currency,
|
pub currency: common_enums::Currency,
|
||||||
@ -735,10 +735,10 @@ pub struct PayoutLinkStatusDetails {
|
|||||||
pub customer_id: id_type::CustomerId,
|
pub customer_id: id_type::CustomerId,
|
||||||
#[serde(with = "common_utils::custom_serde::iso8601")]
|
#[serde(with = "common_utils::custom_serde::iso8601")]
|
||||||
pub session_expiry: PrimitiveDateTime,
|
pub session_expiry: PrimitiveDateTime,
|
||||||
pub return_url: Option<String>,
|
pub return_url: Option<url::Url>,
|
||||||
pub status: api_enums::PayoutStatus,
|
pub status: api_enums::PayoutStatus,
|
||||||
pub error_code: Option<String>,
|
pub error_code: Option<String>,
|
||||||
pub error_message: Option<String>,
|
pub error_message: Option<String>,
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub ui_config: link_utils::GenericLinkUIConfigFormData,
|
pub ui_config: link_utils::GenericLinkUiConfigFormData,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -41,6 +41,7 @@ strum = { version = "0.26.2", features = ["derive"] }
|
|||||||
thiserror = "1.0.58"
|
thiserror = "1.0.58"
|
||||||
time = { version = "0.3.35", features = ["serde", "serde-well-known", "std"] }
|
time = { version = "0.3.35", features = ["serde", "serde-well-known", "std"] }
|
||||||
tokio = { version = "1.37.0", features = ["macros", "rt-multi-thread"], optional = true }
|
tokio = { version = "1.37.0", features = ["macros", "rt-multi-thread"], optional = true }
|
||||||
|
url = { version = "2.5.0", features = ["serde"] }
|
||||||
utoipa = { version = "4.2.0", features = ["preserve_order", "preserve_path_order"] }
|
utoipa = { version = "4.2.0", features = ["preserve_order", "preserve_path_order"] }
|
||||||
uuid = { version = "1.8.0", features = ["v7"] }
|
uuid = { version = "1.8.0", features = ["v7"] }
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
//! Common
|
//! Common
|
||||||
|
|
||||||
use std::primitive::i64;
|
use std::{collections::HashSet, primitive::i64};
|
||||||
|
|
||||||
use common_enums::enums;
|
use common_enums::enums;
|
||||||
use diesel::{
|
use diesel::{
|
||||||
@ -148,7 +148,7 @@ pub struct PayoutLinkData {
|
|||||||
/// Identifier for the payouts resource
|
/// Identifier for the payouts resource
|
||||||
pub payout_id: String,
|
pub payout_id: String,
|
||||||
/// Link to render the payout link
|
/// Link to render the payout link
|
||||||
pub link: Secret<String>,
|
pub link: url::Url,
|
||||||
/// Client secret generated for authenticating frontend APIs
|
/// Client secret generated for authenticating frontend APIs
|
||||||
pub client_secret: Secret<String>,
|
pub client_secret: Secret<String>,
|
||||||
/// Expiry in seconds from the time it was created
|
/// Expiry in seconds from the time it was created
|
||||||
@ -167,11 +167,11 @@ pub struct PayoutLinkData {
|
|||||||
crate::impl_to_sql_from_sql_json!(PayoutLinkData);
|
crate::impl_to_sql_from_sql_json!(PayoutLinkData);
|
||||||
|
|
||||||
/// Object for GenericLinkUiConfig
|
/// Object for GenericLinkUiConfig
|
||||||
#[derive(Clone, Debug, Default, serde::Deserialize, Serialize, ToSchema)]
|
#[derive(Clone, Debug, serde::Deserialize, Serialize, ToSchema)]
|
||||||
pub struct GenericLinkUiConfig {
|
pub struct GenericLinkUiConfig {
|
||||||
/// Merchant's display logo
|
/// Merchant's display logo
|
||||||
#[schema(value_type = Option<String>, max_length = 255, example = "https://hyperswitch.io/favicon.ico")]
|
#[schema(value_type = Option<String>, max_length = 255, example = "https://hyperswitch.io/favicon.ico")]
|
||||||
pub logo: Option<String>,
|
pub logo: Option<url::Url>,
|
||||||
|
|
||||||
/// Custom merchant name for the link
|
/// Custom merchant name for the link
|
||||||
#[schema(value_type = Option<String>, max_length = 255, example = "Hyperswitch")]
|
#[schema(value_type = Option<String>, max_length = 255, example = "Hyperswitch")]
|
||||||
@ -182,12 +182,12 @@ pub struct GenericLinkUiConfig {
|
|||||||
pub theme: Option<String>,
|
pub theme: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Object for GenericLinkUIConfigFormData
|
/// Object for GenericLinkUiConfigFormData
|
||||||
#[derive(Clone, Debug, Default, serde::Deserialize, Serialize, ToSchema)]
|
#[derive(Clone, Debug, serde::Deserialize, Serialize, ToSchema)]
|
||||||
pub struct GenericLinkUIConfigFormData {
|
pub struct GenericLinkUiConfigFormData {
|
||||||
/// Merchant's display logo
|
/// Merchant's display logo
|
||||||
#[schema(value_type = String, max_length = 255, example = "https://hyperswitch.io/favicon.ico")]
|
#[schema(value_type = String, max_length = 255, example = "https://hyperswitch.io/favicon.ico")]
|
||||||
pub logo: String,
|
pub logo: url::Url,
|
||||||
|
|
||||||
/// Custom merchant name for the link
|
/// Custom merchant name for the link
|
||||||
#[schema(value_type = String, max_length = 255, example = "Hyperswitch")]
|
#[schema(value_type = String, max_length = 255, example = "Hyperswitch")]
|
||||||
@ -206,6 +206,6 @@ pub struct EnabledPaymentMethod {
|
|||||||
pub payment_method: enums::PaymentMethod,
|
pub payment_method: enums::PaymentMethod,
|
||||||
|
|
||||||
/// An array of associated payment method types
|
/// An array of associated payment method types
|
||||||
#[schema(value_type = Vec<PaymentMethodType>)]
|
#[schema(value_type = HashSet<PaymentMethodType>)]
|
||||||
pub payment_method_types: Vec<enums::PaymentMethodType>,
|
pub payment_method_types: HashSet<enums::PaymentMethodType>,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,6 +25,7 @@ serde = { version = "1", features = ["derive"], optional = true }
|
|||||||
serde_json = { version = "1.0.115", optional = true }
|
serde_json = { version = "1.0.115", optional = true }
|
||||||
subtle = "2.5.0"
|
subtle = "2.5.0"
|
||||||
time = {version = "0.3.35", optional = true, features = ["serde-human-readable"] }
|
time = {version = "0.3.35", optional = true, features = ["serde-human-readable"] }
|
||||||
|
url = { version = "2.5.0", features = ["serde"] }
|
||||||
zeroize = { version = "1.7", default-features = false }
|
zeroize = { version = "1.7", default-features = false }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
|||||||
@ -29,6 +29,7 @@ impl SerializableSecret for u8 {}
|
|||||||
impl SerializableSecret for u16 {}
|
impl SerializableSecret for u16 {}
|
||||||
impl SerializableSecret for i8 {}
|
impl SerializableSecret for i8 {}
|
||||||
impl SerializableSecret for i32 {}
|
impl SerializableSecret for i32 {}
|
||||||
|
impl SerializableSecret for url::Url {}
|
||||||
|
|
||||||
#[cfg(feature = "time")]
|
#[cfg(feature = "time")]
|
||||||
impl SerializableSecret for time::Date {}
|
impl SerializableSecret for time::Date {}
|
||||||
|
|||||||
@ -213,21 +213,48 @@ pub struct GenericLink {
|
|||||||
pub payout_link: GenericLinkEnvConfig,
|
pub payout_link: GenericLinkEnvConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Clone, Default)]
|
#[derive(Debug, Deserialize, Clone)]
|
||||||
pub struct GenericLinkEnvConfig {
|
pub struct GenericLinkEnvConfig {
|
||||||
pub sdk_url: String,
|
pub sdk_url: url::Url,
|
||||||
pub expiry: u32,
|
pub expiry: u32,
|
||||||
pub ui_config: GenericLinkEnvUiConfig,
|
pub ui_config: GenericLinkEnvUiConfig,
|
||||||
pub enabled_payment_methods: HashMap<enums::PaymentMethod, Vec<enums::PaymentMethodType>>,
|
#[serde(deserialize_with = "deserialize_hashmap")]
|
||||||
|
pub enabled_payment_methods: HashMap<enums::PaymentMethod, HashSet<enums::PaymentMethodType>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Clone, Default)]
|
impl Default for GenericLinkEnvConfig {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
#[allow(clippy::expect_used)]
|
||||||
|
sdk_url: url::Url::parse("http://localhost:9050/HyperLoader.js")
|
||||||
|
.expect("Failed to parse default SDK URL"),
|
||||||
|
expiry: 900,
|
||||||
|
ui_config: GenericLinkEnvUiConfig::default(),
|
||||||
|
enabled_payment_methods: HashMap::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Clone)]
|
||||||
pub struct GenericLinkEnvUiConfig {
|
pub struct GenericLinkEnvUiConfig {
|
||||||
pub logo: String,
|
pub logo: url::Url,
|
||||||
pub merchant_name: Secret<String>,
|
pub merchant_name: Secret<String>,
|
||||||
pub theme: String,
|
pub theme: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::panic)]
|
||||||
|
impl Default for GenericLinkEnvUiConfig {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
#[allow(clippy::expect_used)]
|
||||||
|
logo: url::Url::parse("https://hyperswitch.io/favicon.ico")
|
||||||
|
.expect("Failed to parse default logo URL"),
|
||||||
|
merchant_name: Secret::new("HyperSwitch".to_string()),
|
||||||
|
theme: "#4285F4".to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Clone, Default)]
|
#[derive(Debug, Deserialize, Clone, Default)]
|
||||||
pub struct PaymentLink {
|
pub struct PaymentLink {
|
||||||
pub sdk_url: String,
|
pub sdk_url: String,
|
||||||
@ -689,13 +716,7 @@ impl Settings<SecuredSecret> {
|
|||||||
.with_list_parse_key("redis.cluster_urls")
|
.with_list_parse_key("redis.cluster_urls")
|
||||||
.with_list_parse_key("events.kafka.brokers")
|
.with_list_parse_key("events.kafka.brokers")
|
||||||
.with_list_parse_key("connectors.supported.wallets")
|
.with_list_parse_key("connectors.supported.wallets")
|
||||||
.with_list_parse_key("connector_request_reference_id_config.merchant_ids_send_payment_id_as_connector_request_id")
|
.with_list_parse_key("connector_request_reference_id_config.merchant_ids_send_payment_id_as_connector_request_id"),
|
||||||
.with_list_parse_key("generic_link.payment_method_collect.enabled_payment_methods.card")
|
|
||||||
.with_list_parse_key("generic_link.payment_method_collect.enabled_payment_methods.bank_transfer")
|
|
||||||
.with_list_parse_key("generic_link.payment_method_collect.enabled_payment_methods.wallet")
|
|
||||||
.with_list_parse_key("generic_link.payout_link.enabled_payment_methods.card")
|
|
||||||
.with_list_parse_key("generic_link.payout_link.enabled_payment_methods.bank_transfer")
|
|
||||||
.with_list_parse_key("generic_link.payout_link.enabled_payment_methods.wallet"),
|
|
||||||
|
|
||||||
)
|
)
|
||||||
.build()?;
|
.build()?;
|
||||||
@ -841,6 +862,61 @@ pub struct ServerTls {
|
|||||||
pub certificate: PathBuf,
|
pub certificate: PathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn deserialize_hashmap_inner<K, V>(
|
||||||
|
value: HashMap<String, String>,
|
||||||
|
) -> Result<HashMap<K, HashSet<V>>, String>
|
||||||
|
where
|
||||||
|
K: Eq + std::str::FromStr + std::hash::Hash,
|
||||||
|
V: Eq + std::str::FromStr + std::hash::Hash,
|
||||||
|
<K as std::str::FromStr>::Err: std::fmt::Display,
|
||||||
|
<V as std::str::FromStr>::Err: std::fmt::Display,
|
||||||
|
{
|
||||||
|
let (values, errors) = value
|
||||||
|
.into_iter()
|
||||||
|
.map(
|
||||||
|
|(k, v)| match (K::from_str(k.trim()), deserialize_hashset_inner(v)) {
|
||||||
|
(Err(error), _) => Err(format!(
|
||||||
|
"Unable to deserialize `{}` as `{}`: {error}",
|
||||||
|
k,
|
||||||
|
std::any::type_name::<K>()
|
||||||
|
)),
|
||||||
|
(_, Err(error)) => Err(error),
|
||||||
|
(Ok(key), Ok(value)) => Ok((key, value)),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.fold(
|
||||||
|
(HashMap::new(), Vec::new()),
|
||||||
|
|(mut values, mut errors), result| match result {
|
||||||
|
Ok((key, value)) => {
|
||||||
|
values.insert(key, value);
|
||||||
|
(values, errors)
|
||||||
|
}
|
||||||
|
Err(error) => {
|
||||||
|
errors.push(error);
|
||||||
|
(values, errors)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if !errors.is_empty() {
|
||||||
|
Err(format!("Some errors occurred:\n{}", errors.join("\n")))
|
||||||
|
} else {
|
||||||
|
Ok(values)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_hashmap<'a, D, K, V>(deserializer: D) -> Result<HashMap<K, HashSet<V>>, D::Error>
|
||||||
|
where
|
||||||
|
D: serde::Deserializer<'a>,
|
||||||
|
K: Eq + std::str::FromStr + std::hash::Hash,
|
||||||
|
V: Eq + std::str::FromStr + std::hash::Hash,
|
||||||
|
<K as std::str::FromStr>::Err: std::fmt::Display,
|
||||||
|
<V as std::str::FromStr>::Err: std::fmt::Display,
|
||||||
|
{
|
||||||
|
use serde::de::Error;
|
||||||
|
deserialize_hashmap_inner(<HashMap<String, String>>::deserialize(deserializer)?)
|
||||||
|
.map_err(D::Error::custom)
|
||||||
|
}
|
||||||
|
|
||||||
fn deserialize_hashset_inner<T>(value: impl AsRef<str>) -> Result<HashSet<T>, String>
|
fn deserialize_hashset_inner<T>(value: impl AsRef<str>) -> Result<HashSet<T>, String>
|
||||||
where
|
where
|
||||||
T: Eq + std::str::FromStr + std::hash::Hash,
|
T: Eq + std::str::FromStr + std::hash::Hash,
|
||||||
@ -909,6 +985,114 @@ where
|
|||||||
})?
|
})?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod hashmap_deserialization_test {
|
||||||
|
#![allow(clippy::unwrap_used)]
|
||||||
|
use std::collections::{HashMap, HashSet};
|
||||||
|
|
||||||
|
use serde::de::{
|
||||||
|
value::{Error as ValueError, MapDeserializer},
|
||||||
|
IntoDeserializer,
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::deserialize_hashmap;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_payment_method_and_payment_method_types() {
|
||||||
|
use diesel_models::enums::{PaymentMethod, PaymentMethodType};
|
||||||
|
|
||||||
|
let input_map: HashMap<String, String> = serde_json::json!({
|
||||||
|
"bank_transfer": "ach,bacs",
|
||||||
|
"wallet": "paypal,venmo",
|
||||||
|
})
|
||||||
|
.as_object()
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.map(|(k, v)| (k.to_string(), v.to_string()))
|
||||||
|
.collect();
|
||||||
|
let deserializer: MapDeserializer<
|
||||||
|
'_,
|
||||||
|
std::collections::hash_map::IntoIter<String, String>,
|
||||||
|
ValueError,
|
||||||
|
> = input_map.into_deserializer();
|
||||||
|
let result = deserialize_hashmap::<'_, _, PaymentMethod, PaymentMethodType>(deserializer);
|
||||||
|
let expected_result = HashMap::from([
|
||||||
|
(
|
||||||
|
PaymentMethod::BankTransfer,
|
||||||
|
HashSet::from([PaymentMethodType::Ach, PaymentMethodType::Bacs]),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
PaymentMethod::Wallet,
|
||||||
|
HashSet::from([PaymentMethodType::Paypal, PaymentMethodType::Venmo]),
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
|
||||||
|
assert!(result.is_ok());
|
||||||
|
assert_eq!(result.unwrap(), expected_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_payment_method_and_payment_method_types_with_spaces() {
|
||||||
|
use diesel_models::enums::{PaymentMethod, PaymentMethodType};
|
||||||
|
|
||||||
|
let input_map: HashMap<String, String> = serde_json::json!({
|
||||||
|
" bank_transfer ": " ach , bacs ",
|
||||||
|
"wallet ": " paypal , pix , venmo ",
|
||||||
|
})
|
||||||
|
.as_object()
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.map(|(k, v)| (k.to_string(), v.to_string()))
|
||||||
|
.collect();
|
||||||
|
let deserializer: MapDeserializer<
|
||||||
|
'_,
|
||||||
|
std::collections::hash_map::IntoIter<String, String>,
|
||||||
|
ValueError,
|
||||||
|
> = input_map.into_deserializer();
|
||||||
|
let result = deserialize_hashmap::<'_, _, PaymentMethod, PaymentMethodType>(deserializer);
|
||||||
|
let expected_result = HashMap::from([
|
||||||
|
(
|
||||||
|
PaymentMethod::BankTransfer,
|
||||||
|
HashSet::from([PaymentMethodType::Ach, PaymentMethodType::Bacs]),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
PaymentMethod::Wallet,
|
||||||
|
HashSet::from([
|
||||||
|
PaymentMethodType::Paypal,
|
||||||
|
PaymentMethodType::Pix,
|
||||||
|
PaymentMethodType::Venmo,
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
|
||||||
|
assert!(result.is_ok());
|
||||||
|
assert_eq!(result.unwrap(), expected_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_payment_method_deserializer_error() {
|
||||||
|
use diesel_models::enums::{PaymentMethod, PaymentMethodType};
|
||||||
|
|
||||||
|
let input_map: HashMap<String, String> = serde_json::json!({
|
||||||
|
"unknown": "ach,bacs",
|
||||||
|
"wallet": "paypal,unknown",
|
||||||
|
})
|
||||||
|
.as_object()
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.map(|(k, v)| (k.to_string(), v.to_string()))
|
||||||
|
.collect();
|
||||||
|
let deserializer: MapDeserializer<
|
||||||
|
'_,
|
||||||
|
std::collections::hash_map::IntoIter<String, String>,
|
||||||
|
ValueError,
|
||||||
|
> = input_map.into_deserializer();
|
||||||
|
let result = deserialize_hashmap::<'_, _, PaymentMethod, PaymentMethodType>(deserializer);
|
||||||
|
|
||||||
|
assert!(result.is_err());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod hashset_deserialization_test {
|
mod hashset_deserialization_test {
|
||||||
#![allow(clippy::unwrap_used)]
|
#![allow(clippy::unwrap_used)]
|
||||||
|
|||||||
@ -189,12 +189,6 @@ impl super::settings::GenericLinkEnvConfig {
|
|||||||
Err(ApplicationError::InvalidConfigurationValueError(
|
Err(ApplicationError::InvalidConfigurationValueError(
|
||||||
"link's expiry should not be 0".into(),
|
"link's expiry should not be 0".into(),
|
||||||
))
|
))
|
||||||
})?;
|
|
||||||
|
|
||||||
when(self.sdk_url.is_empty(), || {
|
|
||||||
Err(ApplicationError::InvalidConfigurationValueError(
|
|
||||||
"sdk_url to be integrated in the link cannot be empty".into(),
|
|
||||||
))
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,7 +28,7 @@ body {
|
|||||||
|
|
||||||
.main, #payment-method-collect {
|
.main, #payment-method-collect {
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
width: 100vw;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.main {
|
.main {
|
||||||
@ -45,7 +45,6 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.main {
|
.main {
|
||||||
width: auto;
|
|
||||||
min-width: 300px;
|
min-width: 300px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,7 +28,7 @@ body {
|
|||||||
|
|
||||||
.main, #payout-link {
|
.main, #payout-link {
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
width: 100vw;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.main {
|
.main {
|
||||||
@ -45,7 +45,6 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.main {
|
.main {
|
||||||
width: auto;
|
|
||||||
min-width: 300px;
|
min-width: 300px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -76,6 +76,7 @@ function renderStatusDetails(payoutDetails) {
|
|||||||
case "success":
|
case "success":
|
||||||
break;
|
break;
|
||||||
case "initiated":
|
case "initiated":
|
||||||
|
case "requires_fulfillment":
|
||||||
case "pending":
|
case "pending":
|
||||||
statusInfo.statusImageSrc =
|
statusInfo.statusImageSrc =
|
||||||
"https://live.hyperswitch.io/payment-link-assets/pending.png";
|
"https://live.hyperswitch.io/payment-link-assets/pending.png";
|
||||||
@ -91,7 +92,6 @@ function renderStatusDetails(payoutDetails) {
|
|||||||
case "requires_creation":
|
case "requires_creation":
|
||||||
case "requires_confirmation":
|
case "requires_confirmation":
|
||||||
case "requires_payout_method_data":
|
case "requires_payout_method_data":
|
||||||
case "requires_fulfillment":
|
|
||||||
case "requires_vendor_account_creation":
|
case "requires_vendor_account_creation":
|
||||||
default:
|
default:
|
||||||
statusInfo.statusImageSrc =
|
statusInfo.statusImageSrc =
|
||||||
|
|||||||
@ -12,6 +12,7 @@ use diesel_models::{
|
|||||||
};
|
};
|
||||||
use error_stack::{report, ResultExt};
|
use error_stack::{report, ResultExt};
|
||||||
use hyperswitch_domain_models::payments::{payment_attempt::PaymentAttempt, PaymentIntent};
|
use hyperswitch_domain_models::payments::{payment_attempt::PaymentAttempt, PaymentIntent};
|
||||||
|
use masking::PeekInterface;
|
||||||
use router_env::{instrument, tracing};
|
use router_env::{instrument, tracing};
|
||||||
use time::Duration;
|
use time::Duration;
|
||||||
|
|
||||||
@ -145,11 +146,17 @@ pub async fn initiate_pm_collect_link(
|
|||||||
)?;
|
)?;
|
||||||
|
|
||||||
// Return response
|
// Return response
|
||||||
|
let url = pm_collect_link.url.peek();
|
||||||
let response = payment_methods::PaymentMethodCollectLinkResponse {
|
let response = payment_methods::PaymentMethodCollectLinkResponse {
|
||||||
pm_collect_link_id: pm_collect_link.link_id,
|
pm_collect_link_id: pm_collect_link.link_id,
|
||||||
customer_id,
|
customer_id,
|
||||||
expiry: pm_collect_link.expiry,
|
expiry: pm_collect_link.expiry,
|
||||||
link: pm_collect_link.url,
|
link: url::Url::parse(url)
|
||||||
|
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||||
|
.attach_printable_lazy(|| {
|
||||||
|
format!("Failed to parse the payment method collect link - {}", url)
|
||||||
|
})?
|
||||||
|
.into(),
|
||||||
return_url: pm_collect_link.return_url,
|
return_url: pm_collect_link.return_url,
|
||||||
ui_config: pm_collect_link.link_data.ui_config,
|
ui_config: pm_collect_link.link_data.ui_config,
|
||||||
enabled_payment_methods: pm_collect_link.link_data.enabled_payment_methods,
|
enabled_payment_methods: pm_collect_link.link_data.enabled_payment_methods,
|
||||||
@ -214,7 +221,7 @@ pub async fn render_pm_collect_link(
|
|||||||
let link_data = pm_collect_link.link_data;
|
let link_data = pm_collect_link.link_data;
|
||||||
let default_config = &state.conf.generic_link.payment_method_collect;
|
let default_config = &state.conf.generic_link.payment_method_collect;
|
||||||
let default_ui_config = default_config.ui_config.clone();
|
let default_ui_config = default_config.ui_config.clone();
|
||||||
let ui_config_data = common_utils::link_utils::GenericLinkUIConfigFormData {
|
let ui_config_data = common_utils::link_utils::GenericLinkUiConfigFormData {
|
||||||
merchant_name: link_data
|
merchant_name: link_data
|
||||||
.ui_config
|
.ui_config
|
||||||
.merchant_name
|
.merchant_name
|
||||||
@ -295,7 +302,7 @@ pub async fn render_pm_collect_link(
|
|||||||
let generic_form_data = services::GenericLinkFormData {
|
let generic_form_data = services::GenericLinkFormData {
|
||||||
js_data: serialized_js_content,
|
js_data: serialized_js_content,
|
||||||
css_data: serialized_css_content,
|
css_data: serialized_css_content,
|
||||||
sdk_url: default_config.sdk_url.clone(),
|
sdk_url: default_config.sdk_url.to_string(),
|
||||||
html_meta_tags: String::new(),
|
html_meta_tags: String::new(),
|
||||||
};
|
};
|
||||||
Ok(services::ApplicationResponse::GenericLinkForm(Box::new(
|
Ok(services::ApplicationResponse::GenericLinkForm(Box::new(
|
||||||
@ -310,7 +317,15 @@ pub async fn render_pm_collect_link(
|
|||||||
pm_collect_link_id: pm_collect_link.link_id,
|
pm_collect_link_id: pm_collect_link.link_id,
|
||||||
customer_id: link_data.customer_id,
|
customer_id: link_data.customer_id,
|
||||||
session_expiry: pm_collect_link.expiry,
|
session_expiry: pm_collect_link.expiry,
|
||||||
return_url: pm_collect_link.return_url,
|
return_url: pm_collect_link
|
||||||
|
.return_url
|
||||||
|
.as_ref()
|
||||||
|
.map(|url| url::Url::parse(url))
|
||||||
|
.transpose()
|
||||||
|
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||||
|
.attach_printable(
|
||||||
|
"Failed to parse return URL for payment method collect's status link",
|
||||||
|
)?,
|
||||||
ui_config: ui_config_data,
|
ui_config: ui_config_data,
|
||||||
status,
|
status,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -113,7 +113,7 @@ pub async fn validate_request_and_initiate_payment_method_collect_link(
|
|||||||
{
|
{
|
||||||
let enabled_payment_method = link_utils::EnabledPaymentMethod {
|
let enabled_payment_method = link_utils::EnabledPaymentMethod {
|
||||||
payment_method,
|
payment_method,
|
||||||
payment_method_types,
|
payment_method_types: payment_method_types.into_iter().collect(),
|
||||||
};
|
};
|
||||||
default_enabled_payout_methods.push(enabled_payment_method);
|
default_enabled_payout_methods.push(enabled_payment_method);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,7 +15,7 @@ use crate::{
|
|||||||
errors,
|
errors,
|
||||||
routes::{app::StorageInterface, SessionState},
|
routes::{app::StorageInterface, SessionState},
|
||||||
services::{self, GenericLinks},
|
services::{self, GenericLinks},
|
||||||
types::{api::enums, domain},
|
types::domain,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub async fn initiate_payout_link(
|
pub async fn initiate_payout_link(
|
||||||
@ -64,7 +64,7 @@ pub async fn initiate_payout_link(
|
|||||||
let link_data = payout_link.link_data.clone();
|
let link_data = payout_link.link_data.clone();
|
||||||
let default_config = &state.conf.generic_link.payout_link;
|
let default_config = &state.conf.generic_link.payout_link;
|
||||||
let default_ui_config = default_config.ui_config.clone();
|
let default_ui_config = default_config.ui_config.clone();
|
||||||
let ui_config_data = link_utils::GenericLinkUIConfigFormData {
|
let ui_config_data = link_utils::GenericLinkUiConfigFormData {
|
||||||
merchant_name: link_data
|
merchant_name: link_data
|
||||||
.ui_config
|
.ui_config
|
||||||
.merchant_name
|
.merchant_name
|
||||||
@ -161,7 +161,13 @@ pub async fn initiate_payout_link(
|
|||||||
payout_id: payout_link.primary_reference,
|
payout_id: payout_link.primary_reference,
|
||||||
customer_id: customer.customer_id,
|
customer_id: customer.customer_id,
|
||||||
session_expiry: payout_link.expiry,
|
session_expiry: payout_link.expiry,
|
||||||
return_url: payout_link.return_url,
|
return_url: payout_link
|
||||||
|
.return_url
|
||||||
|
.as_ref()
|
||||||
|
.map(|url| url::Url::parse(url))
|
||||||
|
.transpose()
|
||||||
|
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||||
|
.attach_printable("Failed to parse payout status link's return URL")?,
|
||||||
ui_config: ui_config_data,
|
ui_config: ui_config_data,
|
||||||
enabled_payment_methods,
|
enabled_payment_methods,
|
||||||
amount,
|
amount,
|
||||||
@ -181,7 +187,7 @@ pub async fn initiate_payout_link(
|
|||||||
let generic_form_data = services::GenericLinkFormData {
|
let generic_form_data = services::GenericLinkFormData {
|
||||||
js_data: serialized_js_content,
|
js_data: serialized_js_content,
|
||||||
css_data: serialized_css_content,
|
css_data: serialized_css_content,
|
||||||
sdk_url: default_config.sdk_url.clone(),
|
sdk_url: default_config.sdk_url.to_string(),
|
||||||
html_meta_tags: String::new(),
|
html_meta_tags: String::new(),
|
||||||
};
|
};
|
||||||
Ok(services::ApplicationResponse::GenericLinkForm(Box::new(
|
Ok(services::ApplicationResponse::GenericLinkForm(Box::new(
|
||||||
@ -196,7 +202,13 @@ pub async fn initiate_payout_link(
|
|||||||
payout_id: payout_link.primary_reference,
|
payout_id: payout_link.primary_reference,
|
||||||
customer_id: link_data.customer_id,
|
customer_id: link_data.customer_id,
|
||||||
session_expiry: payout_link.expiry,
|
session_expiry: payout_link.expiry,
|
||||||
return_url: payout_link.return_url,
|
return_url: payout_link
|
||||||
|
.return_url
|
||||||
|
.as_ref()
|
||||||
|
.map(|url| url::Url::parse(url))
|
||||||
|
.transpose()
|
||||||
|
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||||
|
.attach_printable("Failed to parse payout status link's return URL")?,
|
||||||
status: payout.status,
|
status: payout.status,
|
||||||
error_code: payout_attempt.error_code,
|
error_code: payout_attempt.error_code,
|
||||||
error_message: payout_attempt.error_message,
|
error_message: payout_attempt.error_message,
|
||||||
@ -287,12 +299,10 @@ pub async fn filter_payout_methods(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (pm, method_types) in payment_method_list_hm {
|
for (payment_method, payment_method_types) in payment_method_list_hm {
|
||||||
if !method_types.is_empty() {
|
if !payment_method_types.is_empty() {
|
||||||
let payment_method_types: Vec<enums::PaymentMethodType> =
|
|
||||||
method_types.into_iter().collect();
|
|
||||||
let enabled_payment_method = link_utils::EnabledPaymentMethod {
|
let enabled_payment_method = link_utils::EnabledPaymentMethod {
|
||||||
payment_method: pm,
|
payment_method,
|
||||||
payment_method_types,
|
payment_method_types,
|
||||||
};
|
};
|
||||||
response.push(enabled_payment_method);
|
response.push(enabled_payment_method);
|
||||||
|
|||||||
@ -20,6 +20,7 @@ use error_stack::{report, ResultExt};
|
|||||||
use futures::future::join_all;
|
use futures::future::join_all;
|
||||||
#[cfg(feature = "olap")]
|
#[cfg(feature = "olap")]
|
||||||
use hyperswitch_domain_models::errors::StorageError;
|
use hyperswitch_domain_models::errors::StorageError;
|
||||||
|
use masking::PeekInterface;
|
||||||
#[cfg(feature = "payout_retry")]
|
#[cfg(feature = "payout_retry")]
|
||||||
use retry::GsmValidation;
|
use retry::GsmValidation;
|
||||||
#[cfg(feature = "olap")]
|
#[cfg(feature = "olap")]
|
||||||
@ -379,7 +380,6 @@ pub async fn payouts_confirm_core(
|
|||||||
storage_enums::PayoutStatus::Ineligible,
|
storage_enums::PayoutStatus::Ineligible,
|
||||||
storage_enums::PayoutStatus::RequiresFulfillment,
|
storage_enums::PayoutStatus::RequiresFulfillment,
|
||||||
storage_enums::PayoutStatus::RequiresVendorAccountCreation,
|
storage_enums::PayoutStatus::RequiresVendorAccountCreation,
|
||||||
storage_enums::PayoutStatus::RequiresVendorAccountCreation,
|
|
||||||
],
|
],
|
||||||
"confirm",
|
"confirm",
|
||||||
)?;
|
)?;
|
||||||
@ -1946,10 +1946,16 @@ pub async fn response_handler(
|
|||||||
connector_transaction_id: payout_attempt.connector_payout_id,
|
connector_transaction_id: payout_attempt.connector_payout_id,
|
||||||
priority: payouts.priority,
|
priority: payouts.priority,
|
||||||
attempts: None,
|
attempts: None,
|
||||||
payout_link: payout_link.map(|payout_link| PayoutLinkResponse {
|
payout_link: payout_link
|
||||||
payout_link_id: payout_link.link_id.clone(),
|
.map(|payout_link| {
|
||||||
link: payout_link.url,
|
url::Url::parse(payout_link.url.peek()).map(|link| PayoutLinkResponse {
|
||||||
}),
|
payout_link_id: payout_link.link_id,
|
||||||
|
link: link.into(),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.transpose()
|
||||||
|
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||||
|
.attach_printable("Failed to parse payout link's URL")?,
|
||||||
};
|
};
|
||||||
Ok(services::ApplicationResponse::Json(response))
|
Ok(services::ApplicationResponse::Json(response))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -251,7 +251,10 @@ pub async fn create_payout_link(
|
|||||||
.session_expiry
|
.session_expiry
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map_or(default_config.expiry, |expiry| *expiry);
|
.map_or(default_config.expiry, |expiry| *expiry);
|
||||||
let link = Secret::new(format!("{base_url}/payout_link/{merchant_id}/{payout_id}"));
|
let url = format!("{base_url}/payout_link/{merchant_id}/{payout_id}");
|
||||||
|
let link = url::Url::parse(&url)
|
||||||
|
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||||
|
.attach_printable_lazy(|| format!("Failed to form payout link URL - {}", url))?;
|
||||||
let req_enabled_payment_methods = payout_link_config_req
|
let req_enabled_payment_methods = payout_link_config_req
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|req| req.enabled_payment_methods.to_owned());
|
.and_then(|req| req.enabled_payment_methods.to_owned());
|
||||||
@ -301,7 +304,7 @@ pub async fn create_payout_link_db_entry(
|
|||||||
link_type: common_enums::GenericLinkType::PayoutLink,
|
link_type: common_enums::GenericLinkType::PayoutLink,
|
||||||
link_status: GenericLinkStatus::PayoutLink(PayoutLinkStatus::Initiated),
|
link_status: GenericLinkStatus::PayoutLink(PayoutLinkStatus::Initiated),
|
||||||
link_data,
|
link_data,
|
||||||
url: payout_link_data.link.clone(),
|
url: payout_link_data.link.to_string().into(),
|
||||||
return_url,
|
return_url,
|
||||||
expiry: common_utils::date_time::now()
|
expiry: common_utils::date_time::now()
|
||||||
+ Duration::seconds(payout_link_data.session_expiry.into()),
|
+ Duration::seconds(payout_link_data.session_expiry.into()),
|
||||||
|
|||||||
@ -224,7 +224,11 @@ impl AppState {
|
|||||||
.await
|
.await
|
||||||
.expect("Failed to create secret management client");
|
.expect("Failed to create secret management client");
|
||||||
|
|
||||||
let conf = secrets_transformers::fetch_raw_secrets(conf, &*secret_management_client).await;
|
let conf = Box::pin(secrets_transformers::fetch_raw_secrets(
|
||||||
|
conf,
|
||||||
|
&*secret_management_client,
|
||||||
|
))
|
||||||
|
.await;
|
||||||
|
|
||||||
#[allow(clippy::expect_used)]
|
#[allow(clippy::expect_used)]
|
||||||
let encryption_client = conf
|
let encryption_client = conf
|
||||||
|
|||||||
Reference in New Issue
Block a user