refactor: separate DB queries and HTML creation for payout links (#4967)

Signed-off-by: Chikke Srujan <chikke.srujan@Chikke-Srujan-C02FC60MMD6M.local>
Signed-off-by: chikke srujan <121822803+srujanchikke@users.noreply.github.com>
Signed-off-by: Chikke Srujan <chikke.srujan@Chikke-Srujan-G961M60MK7.local>
Co-authored-by: chikke srujan <121822803+srujanchikke@users.noreply.github.com>
Co-authored-by: Chikke Srujan <chikke.srujan@Chikke-Srujan-C02FC60MMD6M.local>
Co-authored-by: Srujan chikke <chikke.srujan@juspay.in>
Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
Co-authored-by: Chikke Srujan <chikke.srujan@Chikke-Srujan-G961M60MK7.local>
This commit is contained in:
Kashif
2024-06-25 19:37:10 +05:30
committed by GitHub
parent 7c639bf878
commit 9e4b2d1c11
92 changed files with 4442 additions and 199 deletions

View File

@ -3,7 +3,7 @@ use std::collections::HashMap;
use common_utils::{
consts,
crypto::{Encryptable, OptionalEncryptableName},
pii,
link_utils, pii,
};
use masking::Secret;
use serde::{Deserialize, Serialize};
@ -95,6 +95,10 @@ pub struct MerchantAccountCreate {
/// The id of the organization to which the merchant belongs to
pub organization_id: Option<String>,
/// Default payment method collect link config
#[schema(value_type = Option<BusinessCollectLinkConfig>)]
pub pm_collect_link_config: Option<BusinessCollectLinkConfig>,
}
#[derive(Clone, Debug, Deserialize, Serialize, ToSchema)]
@ -186,6 +190,10 @@ pub struct MerchantAccountUpdate {
/// To unset this field, pass an empty string
#[schema(max_length = 64)]
pub default_profile: Option<String>,
/// Default payment method collect link config
#[schema(value_type = Option<BusinessCollectLinkConfig>)]
pub pm_collect_link_config: Option<BusinessCollectLinkConfig>,
}
#[derive(Clone, Debug, ToSchema, Serialize)]
@ -277,6 +285,10 @@ pub struct MerchantAccountResponse {
/// Used to indicate the status of the recon module for a merchant account
#[schema(value_type = ReconStatus, example = "not_requested")]
pub recon_status: enums::ReconStatus,
/// Default payment method collect link config
#[schema(value_type = Option<BusinessCollectLinkConfig>)]
pub pm_collect_link_config: Option<BusinessCollectLinkConfig>,
}
#[derive(Clone, Debug, Deserialize, ToSchema, Serialize)]
@ -944,6 +956,10 @@ pub struct BusinessProfileCreate {
/// initiated transaction) based on the routing rules.
/// If set to `false`, MIT will go through the same connector as the CIT.
pub is_connector_agnostic_mit_enabled: Option<bool>,
/// Default payout link config
#[schema(value_type = Option<BusinessPayoutLinkConfig>)]
pub payout_link_config: Option<BusinessPayoutLinkConfig>,
}
#[derive(Clone, Debug, ToSchema, Serialize)]
@ -1028,6 +1044,10 @@ pub struct BusinessProfileResponse {
/// initiated transaction) based on the routing rules.
/// If set to `false`, MIT will go through the same connector as the CIT.
pub is_connector_agnostic_mit_enabled: Option<bool>,
/// Default payout link config
#[schema(value_type = Option<BusinessPayoutLinkConfig>)]
pub payout_link_config: Option<BusinessPayoutLinkConfig>,
}
#[derive(Clone, Debug, Deserialize, ToSchema, Serialize)]
@ -1104,6 +1124,35 @@ pub struct BusinessProfileUpdate {
/// initiated transaction) based on the routing rules.
/// If set to `false`, MIT will go through the same connector as the CIT.
pub is_connector_agnostic_mit_enabled: Option<bool>,
/// Default payout link config
#[schema(value_type = Option<BusinessPayoutLinkConfig>)]
pub payout_link_config: Option<BusinessPayoutLinkConfig>,
}
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, ToSchema)]
pub struct BusinessCollectLinkConfig {
#[serde(flatten)]
pub config: BusinessGenericLinkConfig,
/// List of payment methods shown on collect UI
#[schema(value_type = Vec<EnabledPaymentMethod>, example = r#"[{"payment_method": "bank_transfer", "payment_method_types": ["ach", "bacs", "sepa"]}]"#)]
pub enabled_payment_methods: Vec<link_utils::EnabledPaymentMethod>,
}
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, ToSchema)]
pub struct BusinessPayoutLinkConfig {
#[serde(flatten)]
pub config: BusinessGenericLinkConfig,
}
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, ToSchema)]
pub struct BusinessGenericLinkConfig {
/// Custom domain name to be used for hosting the link
pub domain_name: Option<String>,
#[serde(flatten)]
#[schema(value_type = GenericLinkUiConfig)]
pub ui_config: link_utils::GenericLinkUiConfig,
}
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, PartialEq, ToSchema)]

View File

@ -4,8 +4,9 @@ use crate::{
payment_methods::{
CustomerDefaultPaymentMethodResponse, CustomerPaymentMethodsListResponse,
DefaultPaymentMethod, ListCountriesCurrenciesRequest, ListCountriesCurrenciesResponse,
PaymentMethodDeleteResponse, PaymentMethodListRequest, PaymentMethodListResponse,
PaymentMethodResponse, PaymentMethodUpdate,
PaymentMethodCollectLinkRenderRequest, PaymentMethodCollectLinkRequest,
PaymentMethodCollectLinkResponse, PaymentMethodDeleteResponse, PaymentMethodListRequest,
PaymentMethodListResponse, PaymentMethodResponse, PaymentMethodUpdate,
},
payments::{
ExtendedCardInfoResponse, PaymentIdType, PaymentListConstraints,
@ -156,6 +157,32 @@ impl ApiEventMetric for CustomerDefaultPaymentMethodResponse {
}
}
impl ApiEventMetric for PaymentMethodCollectLinkRequest {
fn get_api_event_type(&self) -> Option<ApiEventsType> {
self.pm_collect_link_id
.as_ref()
.map(|id| ApiEventsType::PaymentMethodCollectLink {
link_id: id.clone(),
})
}
}
impl ApiEventMetric for PaymentMethodCollectLinkRenderRequest {
fn get_api_event_type(&self) -> Option<ApiEventsType> {
Some(ApiEventsType::PaymentMethodCollectLink {
link_id: self.pm_collect_link_id.clone(),
})
}
}
impl ApiEventMetric for PaymentMethodCollectLinkResponse {
fn get_api_event_type(&self) -> Option<ApiEventsType> {
Some(ApiEventsType::PaymentMethodCollectLink {
link_id: self.pm_collect_link_id.clone(),
})
}
}
impl ApiEventMetric for PaymentListFilterConstraints {
fn get_api_event_type(&self) -> Option<ApiEventsType> {
Some(ApiEventsType::ResourceListAPI)

View File

@ -1,54 +1,71 @@
use common_utils::events::{ApiEventMetric, ApiEventsType};
use crate::payouts::{
PayoutActionRequest, PayoutCreateRequest, PayoutCreateResponse, PayoutListConstraints,
PayoutListFilterConstraints, PayoutListFilters, PayoutListResponse, PayoutRetrieveRequest,
PayoutActionRequest, PayoutCreateRequest, PayoutCreateResponse, PayoutLinkInitiateRequest,
PayoutListConstraints, PayoutListFilterConstraints, PayoutListFilters, PayoutListResponse,
PayoutRetrieveRequest,
};
impl ApiEventMetric for PayoutRetrieveRequest {
fn get_api_event_type(&self) -> Option<ApiEventsType> {
Some(ApiEventsType::Payout)
Some(ApiEventsType::Payout {
payout_id: self.payout_id.clone(),
})
}
}
impl ApiEventMetric for PayoutCreateRequest {
fn get_api_event_type(&self) -> Option<ApiEventsType> {
Some(ApiEventsType::Payout)
self.payout_id.as_ref().map(|id| ApiEventsType::Payout {
payout_id: id.clone(),
})
}
}
impl ApiEventMetric for PayoutCreateResponse {
fn get_api_event_type(&self) -> Option<ApiEventsType> {
Some(ApiEventsType::Payout)
Some(ApiEventsType::Payout {
payout_id: self.payout_id.clone(),
})
}
}
impl ApiEventMetric for PayoutActionRequest {
fn get_api_event_type(&self) -> Option<ApiEventsType> {
Some(ApiEventsType::Payout)
Some(ApiEventsType::Payout {
payout_id: self.payout_id.clone(),
})
}
}
impl ApiEventMetric for PayoutListConstraints {
fn get_api_event_type(&self) -> Option<ApiEventsType> {
Some(ApiEventsType::Payout)
Some(ApiEventsType::ResourceListAPI)
}
}
impl ApiEventMetric for PayoutListFilterConstraints {
fn get_api_event_type(&self) -> Option<ApiEventsType> {
Some(ApiEventsType::Payout)
Some(ApiEventsType::ResourceListAPI)
}
}
impl ApiEventMetric for PayoutListResponse {
fn get_api_event_type(&self) -> Option<ApiEventsType> {
Some(ApiEventsType::Payout)
Some(ApiEventsType::ResourceListAPI)
}
}
impl ApiEventMetric for PayoutListFilters {
fn get_api_event_type(&self) -> Option<ApiEventsType> {
Some(ApiEventsType::Payout)
Some(ApiEventsType::ResourceListAPI)
}
}
impl ApiEventMetric for PayoutLinkInitiateRequest {
fn get_api_event_type(&self) -> Option<ApiEventsType> {
Some(ApiEventsType::Payout {
payout_id: self.payout_id.clone(),
})
}
}

View File

@ -4,7 +4,7 @@ use cards::CardNumber;
use common_utils::{
consts::SURCHARGE_PERCENTAGE_PRECISION_LENGTH,
crypto::OptionalEncryptableName,
id_type, pii,
id_type, link_utils, pii,
types::{MinorUnit, Percentage, Surcharge},
};
use serde::de;
@ -944,6 +944,104 @@ pub struct CustomerPaymentMethod {
pub billing: Option<payments::Address>,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct PaymentMethodCollectLinkRequest {
/// The unique identifier for the collect link.
#[schema(value_type = Option<String>, example = "pm_collect_link_2bdacf398vwzq5n422S1")]
pub pm_collect_link_id: Option<String>,
/// The unique identifier of the customer.
#[schema(value_type = String, example = "cus_92dnwed8s32bV9D8Snbiasd8v")]
pub customer_id: id_type::CustomerId,
#[serde(flatten)]
#[schema(value_type = Option<GenericLinkUiConfig>)]
pub ui_config: Option<link_utils::GenericLinkUiConfig>,
/// Will be used to expire client secret after certain amount of time to be supplied in seconds
/// (900) for 15 mins
#[schema(value_type = Option<u32>, example = 900)]
pub session_expiry: Option<u32>,
/// Redirect to this URL post completion
#[schema(value_type = Option<String>, example = "https://sandbox.hyperswitch.io/payment_method/collect/pm_collect_link_2bdacf398vwzq5n422S1/status")]
pub return_url: Option<String>,
/// List of payment methods shown on collect UI
#[schema(value_type = Option<Vec<EnabledPaymentMethod>>, example = r#"[{"payment_method": "bank_transfer", "payment_method_types": ["ach", "bacs"]}]"#)]
pub enabled_payment_methods: Option<Vec<link_utils::EnabledPaymentMethod>>,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct PaymentMethodCollectLinkResponse {
/// The unique identifier for the collect link.
#[schema(value_type = String, example = "pm_collect_link_2bdacf398vwzq5n422S1")]
pub pm_collect_link_id: String,
/// The unique identifier of the customer.
#[schema(value_type = String, example = "cus_92dnwed8s32bV9D8Snbiasd8v")]
pub customer_id: id_type::CustomerId,
/// Time when this link will be expired in ISO8601 format
#[schema(value_type = PrimitiveDateTime, example = "2025-01-18T11:04:09.922Z")]
#[serde(with = "common_utils::custom_serde::iso8601")]
pub expiry: time::PrimitiveDateTime,
/// 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")]
pub link: masking::Secret<String>,
/// Redirect to this URL post completion
#[schema(value_type = Option<String>, example = "https://sandbox.hyperswitch.io/payment_method/collect/pm_collect_link_2bdacf398vwzq5n422S1/status")]
pub return_url: Option<String>,
/// Collect link config used
#[serde(flatten)]
#[schema(value_type = GenericLinkUiConfig)]
pub ui_config: link_utils::GenericLinkUiConfig,
/// List of payment methods shown on collect UI
#[schema(value_type = Option<Vec<EnabledPaymentMethod>>, example = r#"[{"payment_method": "bank_transfer", "payment_method_types": ["ach", "bacs"]}]"#)]
pub enabled_payment_methods: Option<Vec<link_utils::EnabledPaymentMethod>>,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct PaymentMethodCollectLinkRenderRequest {
/// Unique identifier for a merchant.
#[schema(example = "merchant_1671528864")]
pub merchant_id: String,
/// The unique identifier for the collect link.
#[schema(value_type = String, example = "pm_collect_link_2bdacf398vwzq5n422S1")]
pub pm_collect_link_id: String,
}
#[derive(Clone, Debug, serde::Serialize)]
pub struct PaymentMethodCollectLinkDetails {
pub publishable_key: masking::Secret<String>,
pub client_secret: masking::Secret<String>,
pub pm_collect_link_id: String,
pub customer_id: id_type::CustomerId,
#[serde(with = "common_utils::custom_serde::iso8601")]
pub session_expiry: time::PrimitiveDateTime,
pub return_url: Option<String>,
#[serde(flatten)]
pub ui_config: link_utils::GenericLinkUIConfigFormData,
pub enabled_payment_methods: Option<Vec<link_utils::EnabledPaymentMethod>>,
}
#[derive(Clone, Debug, serde::Serialize)]
pub struct PaymentMethodCollectLinkStatusDetails {
pub pm_collect_link_id: String,
pub customer_id: id_type::CustomerId,
#[serde(with = "common_utils::custom_serde::iso8601")]
pub session_expiry: time::PrimitiveDateTime,
pub return_url: Option<String>,
pub status: link_utils::PaymentMethodCollectStatus,
#[serde(flatten)]
pub ui_config: link_utils::GenericLinkUIConfigFormData,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
pub struct MaskedBankDetails {
pub mask: String,

View File

@ -1,7 +1,7 @@
use cards::CardNumber;
use common_utils::{
consts::default_payouts_list_limit,
crypto, id_type,
crypto, id_type, link_utils,
pii::{self, Email},
};
use masking::Secret;
@ -141,17 +141,45 @@ pub struct PayoutCreateRequest {
#[schema(value_type = Option<Object>, example = r#"{ "udf1": "some-value", "udf2": "some-value" }"#)]
pub metadata: Option<pii::SecretSerdeValue>,
/// Provide a reference to a stored payment method
/// Provide a reference to a stored payout method
#[schema(example = "187282ab-40ef-47a9-9206-5099ba31e432")]
pub payout_token: Option<String>,
/// The business profile to use for this payment, if not passed the default business profile
/// The business profile to use for this payout, if not passed the default business profile
/// associated with the merchant account will be used.
pub profile_id: Option<String>,
/// The send method for processing payouts
#[schema(value_type = PayoutSendPriority, example = "instant")]
pub priority: Option<api_enums::PayoutSendPriority>,
/// Whether to get the payout link (if applicable)
#[schema(default = false, example = true)]
pub payout_link: Option<bool>,
/// custom payout link config for the particular payout
#[schema(value_type = Option<PayoutCreatePayoutLinkConfig>)]
pub payout_link_config: Option<PayoutCreatePayoutLinkConfig>,
/// Will be used to expire client secret after certain amount of time to be supplied in seconds
/// (900) for 15 mins
#[schema(value_type = Option<u32>, example = 900)]
pub session_expiry: Option<u32>,
}
#[derive(Default, Debug, Deserialize, Serialize, Clone, ToSchema)]
pub struct PayoutCreatePayoutLinkConfig {
/// The unique identifier for the collect link.
#[schema(value_type = Option<String>, example = "pm_collect_link_2bdacf398vwzq5n422S1")]
pub payout_link_id: Option<String>,
#[serde(flatten)]
#[schema(value_type = Option<GenericLinkUiConfig>)]
pub ui_config: Option<link_utils::GenericLinkUiConfig>,
/// List of payout methods shown on collect UI
#[schema(value_type = Option<Vec<EnabledPaymentMethod>>, example = r#"[{"payment_method": "bank_transfer", "payment_method_types": ["ach", "bacs"]}]"#)]
pub enabled_payment_methods: Option<Vec<link_utils::EnabledPaymentMethod>>,
}
#[derive(Debug, Clone, Deserialize, Serialize, ToSchema)]
@ -437,7 +465,7 @@ pub struct PayoutCreateResponse {
#[schema(value_type = String, example = "E0001")]
pub error_code: Option<String>,
/// The business profile that is associated with this payment
/// The business profile that is associated with this payout
pub profile_id: String,
/// Time when the payout was created
@ -457,6 +485,10 @@ pub struct PayoutCreateResponse {
#[schema(value_type = Option<Vec<PayoutAttemptResponse>>)]
#[serde(skip_serializing_if = "Option::is_none")]
pub attempts: Option<Vec<PayoutAttemptResponse>>,
// If payout link is request, this represents response on
#[schema(value_type = Option<PayoutLinkResponse>)]
pub payout_link: Option<PayoutLinkResponse>,
}
#[derive(
@ -659,8 +691,53 @@ pub struct PayoutListFilters {
pub connector: Vec<api_enums::PayoutConnectors>,
/// The list of available currency filters
pub currency: Vec<common_enums::Currency>,
/// The list of available payment status filters
/// The list of available payout status filters
pub status: Vec<common_enums::PayoutStatus>,
/// The list of available payment method filters
/// The list of available payout method filters
pub payout_method: Vec<common_enums::PayoutType>,
}
#[derive(Clone, Debug, serde::Serialize, ToSchema)]
pub struct PayoutLinkResponse {
pub payout_link_id: String,
#[schema(value_type = String)]
pub link: Secret<String>,
}
#[derive(Clone, Debug, serde::Deserialize, ToSchema, serde::Serialize)]
pub struct PayoutLinkInitiateRequest {
pub merchant_id: String,
pub payout_id: String,
}
#[derive(Clone, Debug, serde::Serialize)]
pub struct PayoutLinkDetails {
pub publishable_key: Secret<String>,
pub client_secret: Secret<String>,
pub payout_link_id: String,
pub payout_id: String,
pub customer_id: id_type::CustomerId,
#[serde(with = "common_utils::custom_serde::iso8601")]
pub session_expiry: PrimitiveDateTime,
pub return_url: Option<String>,
#[serde(flatten)]
pub ui_config: link_utils::GenericLinkUIConfigFormData,
pub enabled_payment_methods: Vec<link_utils::EnabledPaymentMethod>,
pub amount: String,
pub currency: common_enums::Currency,
}
#[derive(Clone, Debug, serde::Serialize)]
pub struct PayoutLinkStatusDetails {
pub payout_link_id: String,
pub payout_id: String,
pub customer_id: id_type::CustomerId,
#[serde(with = "common_utils::custom_serde::iso8601")]
pub session_expiry: PrimitiveDateTime,
pub return_url: Option<String>,
pub status: api_enums::PayoutStatus,
pub error_code: Option<String>,
pub error_message: Option<String>,
#[serde(flatten)]
pub ui_config: link_utils::GenericLinkUIConfigFormData,
}