Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: add states in PayoutStatus #2059

Closed
wants to merge 18 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
1ee078c
feat(payouts): integrate stripe connect
kashif-m Aug 23, 2023
bd2c91e
feat(payouts): enable PayoutRecipientAccountCreation
kashif-m Aug 24, 2023
7484a79
feat: move stripe connect business details in payout's metadata
kashif-m Aug 28, 2023
63e83d2
refactor: make StripeConnect onboarding fields optional
kashif-m Aug 31, 2023
b1286ed
Merge remote-tracking branch 'origin/main' into payout_stripe_connect
Sep 20, 2023
db5c940
Merge remote-tracking branch 'origin/main' into payout_stripe_connect
Sep 21, 2023
7f0b01d
refactor: update stripe connector integration for payout APIs
Sep 22, 2023
a735e6c
Merge remote-tracking branch 'origin/main' into payout_stripe_connect
kashif-m Oct 4, 2023
0d30886
fix: consume profile_id throughout payouts flow
kashif-m Oct 9, 2023
251cdd4
feat: add recipient's external account creation as a ProcessTracker task
kashif-m Oct 9, 2023
8e1a661
Merge remote-tracking branch 'origin/profile_id_payouts' into payout_…
kashif-m Oct 9, 2023
58c5cb7
feat: add subsequent payout steps after recipient onboarding in PT flow
kashif-m Oct 11, 2023
63aaab0
Merge remote-tracking branch 'origin/main' into payout_stripe_connect
Oct 12, 2023
9e1e230
fix: add default implementation for Volt for PayoutRecipientAccount flow
Oct 12, 2023
c993af4
Merge remote-tracking branch 'origin/main' into payout_stripe_connect
Oct 12, 2023
fd5f482
refactor: optimize payouts connector integration for Stripe
Oct 13, 2023
eda581b
refactor: update PayoutStatus to represent multiple states
kashif-m Aug 31, 2023
fba6690
chore: update Cargo.lock
github-actions[bot] Oct 16, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion config/config.example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,7 @@ cashapp = {country = "US", currency = "USD"}

[connector_customer]
connector_list = "gocardless,stax,stripe"
payout_connector_list = "wise"
payout_connector_list = "stripe,wise"

[bank_config.online_banking_fpx]
adyen.banks = "affin_bank,agro_bank,alliance_bank,am_bank,bank_islam,bank_muamalat,bank_rakyat,bank_simpanan_nasional,cimb_bank,hong_leong_bank,hsbc_bank,kuwait_finance_house,may_bank,ocbc_bank,public_bank,rhb_bank,standard_chartered_bank,uob_bank"
Expand Down
2 changes: 1 addition & 1 deletion config/development.toml
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,7 @@ bluesnap = {payment_method = "card"}

[connector_customer]
connector_list = "gocardless,stax,stripe"
payout_connector_list = "wise"
payout_connector_list = "stripe,wise"

[dummy_connector]
enabled = true
Expand Down
2 changes: 1 addition & 1 deletion config/docker_compose.toml
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ bank_debit.sepa = { connector_list = "gocardless"}

[connector_customer]
connector_list = "gocardless,stax,stripe"
payout_connector_list = "wise"
payout_connector_list = "stripe,wise"

[multiple_api_version_supported_connectors]
supported_connectors = "braintree"
Expand Down
2 changes: 2 additions & 0 deletions crates/api_models/src/enums.rs
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ pub enum RoutableConnectors {
#[strum(serialize_all = "snake_case")]
pub enum PayoutConnectors {
Adyen,
Stripe,
Wise,
}

Expand All @@ -266,6 +267,7 @@ impl From<PayoutConnectors> for RoutableConnectors {
fn from(value: PayoutConnectors) -> Self {
match value {
PayoutConnectors::Adyen => Self::Adyen,
PayoutConnectors::Stripe => Self::Stripe,
PayoutConnectors::Wise => Self::Wise,
}
}
Expand Down
42 changes: 42 additions & 0 deletions crates/api_models/src/payouts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use common_utils::{
pii::{self, Email},
};
use masking::Secret;
use router_derive::DebugAsDisplay;
use serde::{Deserialize, Serialize};
use utoipa::ToSchema;

Expand Down Expand Up @@ -388,6 +389,7 @@ pub struct PayoutCreateResponse {
#[derive(Default, Debug, Clone, Deserialize, ToSchema)]
pub struct PayoutRetrieveBody {
pub force_sync: Option<bool>,
pub merchant_id: Option<String>,
}

#[derive(Default, Debug, Serialize, ToSchema, Clone, Deserialize)]
Expand All @@ -406,6 +408,9 @@ pub struct PayoutRetrieveRequest {
/// (defaults to false)
#[schema(value_type = Option<bool>, default = false, example = true)]
pub force_sync: Option<bool>,

/// The identifier for the Merchant Account.
pub merchant_id: Option<String>,
}

#[derive(Default, Debug, Serialize, ToSchema, Clone, Deserialize)]
Expand All @@ -420,3 +425,40 @@ pub struct PayoutActionRequest {
)]
pub payout_id: String,
}

#[derive(Default, DebugAsDisplay, Debug, ToSchema, Clone, Deserialize)]
pub struct PayoutVendorAccountDetails {
pub vendor_details: PayoutVendorDetails,
pub individual_details: PayoutIndividualDetails,
}

#[derive(Default, DebugAsDisplay, Debug, Serialize, ToSchema, Clone, Deserialize)]
pub struct PayoutVendorDetails {
pub account_type: String,
pub business_type: String,
pub business_profile_mcc: Option<i32>,
pub business_profile_url: Option<String>,
pub business_profile_name: Option<Secret<String>>,
pub company_address_line1: Option<Secret<String>>,
pub company_address_line2: Option<Secret<String>>,
pub company_address_postal_code: Option<Secret<String>>,
pub company_address_city: Option<Secret<String>>,
pub company_address_state: Option<Secret<String>>,
pub company_phone: Option<Secret<String>>,
pub company_tax_id: Option<Secret<String>>,
pub company_owners_provided: Option<bool>,
pub capabilities_card_payments: Option<bool>,
pub capabilities_transfers: Option<bool>,
}

#[derive(Default, DebugAsDisplay, Debug, Serialize, ToSchema, Clone, Deserialize)]
pub struct PayoutIndividualDetails {
pub tos_acceptance_date: Option<i64>,
pub tos_acceptance_ip: Option<Secret<String>>,
pub individual_dob_day: Option<Secret<String>>,
pub individual_dob_month: Option<Secret<String>>,
pub individual_dob_year: Option<Secret<String>>,
pub individual_id_number: Option<Secret<String>>,
pub individual_ssn_last_4: Option<Secret<String>>,
pub external_account_account_holder_type: Option<String>,
}
14 changes: 9 additions & 5 deletions crates/common_enums/src/enums.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1668,15 +1668,19 @@ pub enum CanadaStatesAbbreviation {
#[serde(rename_all = "snake_case")]
#[strum(serialize_all = "snake_case")]
pub enum PayoutStatus {
RequiresCustomerAction,
RequiresPayoutMethodData,
#[default]
RequiresCreation,
RequiresFulfillment,
Processing,
OutgoingPaymentSent,
Success,
Failed,
Cancelled,
Pending,
Ineligible,
#[default]
RequiresCreation,
RequiresPayoutMethodData,
RequiresFulfillment,
Expired,
FundsRefunded,
}

#[derive(
Expand Down
2 changes: 2 additions & 0 deletions crates/common_utils/src/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ pub const PAYMENTS_LIST_MAX_LIMIT_V1: u32 = 100;
/// Maximum limit for payments list post api with filters
pub const PAYMENTS_LIST_MAX_LIMIT_V2: u32 = 20;

/// Average delay (in ms) between account onboarding's API response and the changes to actually reflect at Stripe's end
pub const STRIPE_ACCOUNT_ONBOARDING_DELAY_IN_SECONDS: i64 = 15;
/// surcharge percentage maximum precision length
pub const SURCHARGE_PERCENTAGE_PRECISION_LENGTH: u8 = 2;

Expand Down
3 changes: 3 additions & 0 deletions crates/diesel_models/src/payout_attempt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ pub struct PayoutAttempt {
#[serde(with = "common_utils::custom_serde::iso8601")]
pub last_modified_at: PrimitiveDateTime,
pub profile_id: Option<String>,
pub confirm: bool,
}

impl Default for PayoutAttempt {
Expand All @@ -51,6 +52,7 @@ impl Default for PayoutAttempt {
created_at: now,
last_modified_at: now,
profile_id: None,
confirm: false,
}
}
}
Expand Down Expand Up @@ -88,6 +90,7 @@ pub struct PayoutAttemptNew {
#[serde(default, with = "common_utils::custom_serde::iso8601::option")]
pub last_modified_at: Option<PrimitiveDateTime>,
pub profile_id: Option<String>,
pub confirm: bool,
}

#[derive(Debug)]
Expand Down
1 change: 1 addition & 0 deletions crates/diesel_models/src/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -689,6 +689,7 @@ diesel::table! {
last_modified_at -> Timestamp,
#[max_length = 64]
profile_id -> Nullable<Varchar>,
confirm -> Bool,
}
}

Expand Down
6 changes: 6 additions & 0 deletions crates/router/src/bin/scheduler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ pub enum PTRunner {
PaymentsSyncWorkflow,
RefundWorkflowRouter,
DeleteTokenizeDataWorkflow,
#[cfg(feature = "payouts")]
StripeAttachAccount,
}

#[derive(Debug, Copy, Clone)]
Expand All @@ -100,6 +102,10 @@ impl ProcessTrackerWorkflows<routes::AppState> for WorkflowRunner {
Some(PTRunner::DeleteTokenizeDataWorkflow) => {
Box::new(workflows::tokenized_data::DeleteTokenizeDataWorkflow)
}
#[cfg(feature = "payouts")]
Some(PTRunner::StripeAttachAccount) => Box::new(
workflows::stripe_attach_external_account::StripeAttachExternalAccountWorkflow,
),
_ => Err(ProcessTrackerError::UnexpectedFlow)?,
};
let app_state = &state.clone();
Expand Down
17 changes: 9 additions & 8 deletions crates/router/src/connector/adyen/transformers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4097,10 +4097,8 @@ impl<F> TryFrom<types::PayoutsResponseRouterData<F, AdyenPayoutResponse>>
let status = payout_eligible.map_or(
{
response.result_code.map_or(
response
.response
.map(storage_enums::PayoutStatus::foreign_from),
|rc| Some(storage_enums::PayoutStatus::foreign_from(rc)),
response.response.map(storage_enums::PayoutStatus::from),
|rc| Some(storage_enums::PayoutStatus::from(rc)),
)
},
|pe| {
Expand All @@ -4117,20 +4115,23 @@ impl<F> TryFrom<types::PayoutsResponseRouterData<F, AdyenPayoutResponse>>
status,
connector_payout_id: response.psp_reference,
payout_eligible,
should_add_next_step_to_process_tracker: false,
}),
..item.data
})
}
}

#[cfg(feature = "payouts")]
impl ForeignFrom<AdyenStatus> for storage_enums::PayoutStatus {
fn foreign_from(adyen_status: AdyenStatus) -> Self {
impl From<AdyenStatus> for storage_enums::PayoutStatus {
fn from(adyen_status: AdyenStatus) -> Self {
match adyen_status {
AdyenStatus::Authorised | AdyenStatus::PayoutConfirmReceived => Self::Success,
AdyenStatus::Authorised | AdyenStatus::PayoutConfirmReceived => {
Self::OutgoingPaymentSent
}
AdyenStatus::Cancelled | AdyenStatus::PayoutDeclineReceived => Self::Cancelled,
AdyenStatus::Error => Self::Failed,
AdyenStatus::Pending => Self::Pending,
AdyenStatus::Pending => Self::Processing,
AdyenStatus::PayoutSubmitReceived => Self::RequiresFulfillment,
_ => Self::Ineligible,
}
Expand Down
Loading
Loading