mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-11-01 19:42:27 +08:00
refactor: add mapping for ConnectorError in payouts flow (#2608)
Co-authored-by: Kashif <kashif@protonmail.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Kashif <mohammed.kashif@juspay.in>
This commit is contained in:
@ -4010,8 +4010,12 @@ impl<F> TryFrom<&AdyenRouterData<&types::PayoutsRouterData<F>>> for AdyenPayoutC
|
||||
iban: Some(b.iban),
|
||||
tax_id: None,
|
||||
},
|
||||
_ => Err(errors::ConnectorError::NotSupported {
|
||||
message: "Bank transfers via ACH or Bacs are not supported".to_string(),
|
||||
payouts::BankPayout::Ach(..) => Err(errors::ConnectorError::NotSupported {
|
||||
message: "Bank transfer via ACH is not supported".to_string(),
|
||||
connector: "Adyen",
|
||||
})?,
|
||||
payouts::BankPayout::Bacs(..) => Err(errors::ConnectorError::NotSupported {
|
||||
message: "Bank transfer via Bacs is not supported".to_string(),
|
||||
connector: "Adyen",
|
||||
})?,
|
||||
};
|
||||
|
||||
@ -400,6 +400,11 @@ impl<T> ConnectorErrorExt<T> for error_stack::Result<T, errors::ConnectorError>
|
||||
field_names: field_names.to_vec(),
|
||||
}
|
||||
}
|
||||
errors::ConnectorError::NotSupported { message, connector } => {
|
||||
errors::ApiErrorResponse::NotSupported {
|
||||
message: format!("{} by {}", message, connector),
|
||||
}
|
||||
}
|
||||
_ => errors::ApiErrorResponse::InternalServerError,
|
||||
};
|
||||
err.change_context(error)
|
||||
|
||||
@ -35,6 +35,7 @@ pub struct PayoutData {
|
||||
pub payout_attempt: storage::PayoutAttempt,
|
||||
pub payout_method_data: Option<payouts::PayoutMethodData>,
|
||||
pub merchant_connector_account: Option<payment_helpers::MerchantConnectorAccountType>,
|
||||
pub profile_id: String,
|
||||
}
|
||||
|
||||
// ********************************************** CORE FLOWS **********************************************
|
||||
@ -96,9 +97,7 @@ pub async fn payouts_create_core(
|
||||
merchant_account: domain::MerchantAccount,
|
||||
key_store: domain::MerchantKeyStore,
|
||||
req: payouts::PayoutCreateRequest,
|
||||
) -> RouterResponse<payouts::PayoutCreateResponse>
|
||||
where
|
||||
{
|
||||
) -> RouterResponse<payouts::PayoutCreateResponse> {
|
||||
// Form connector data
|
||||
let connector_data = get_connector_data(
|
||||
&state,
|
||||
@ -111,7 +110,7 @@ where
|
||||
.await?;
|
||||
|
||||
// Validate create request
|
||||
let (payout_id, payout_method_data) =
|
||||
let (payout_id, payout_method_data, profile_id) =
|
||||
validator::validate_create_request(&state, &merchant_account, &req, &key_store).await?;
|
||||
|
||||
// Create DB entries
|
||||
@ -121,6 +120,7 @@ where
|
||||
&key_store,
|
||||
&req,
|
||||
&payout_id,
|
||||
&profile_id,
|
||||
&connector_data.connector_name,
|
||||
payout_method_data.as_ref(),
|
||||
)
|
||||
@ -561,18 +561,8 @@ pub async fn create_recipient(
|
||||
let customer_details = payout_data.customer_details.to_owned();
|
||||
let connector_name = connector_data.connector_name.to_string();
|
||||
|
||||
let profile_id = core_utils::get_profile_id_from_business_details(
|
||||
payout_data.payout_attempt.business_country,
|
||||
payout_data.payout_attempt.business_label.as_ref(),
|
||||
merchant_account,
|
||||
payout_data.payout_attempt.profile_id.as_ref(),
|
||||
&*state.store,
|
||||
false,
|
||||
)
|
||||
.await?;
|
||||
|
||||
// Create the connector label using {profile_id}_{connector_name}
|
||||
let connector_label = format!("{profile_id}_{}", connector_name);
|
||||
let connector_label = format!("{}_{}", payout_data.profile_id, connector_name);
|
||||
|
||||
let (should_call_connector, _connector_customer_id) =
|
||||
helpers::should_call_payout_connector_create_customer(
|
||||
@ -1124,6 +1114,7 @@ pub async fn response_handler(
|
||||
}
|
||||
|
||||
// DB entries
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
#[cfg(feature = "payouts")]
|
||||
pub async fn payout_create_db_entries(
|
||||
state: &AppState,
|
||||
@ -1131,6 +1122,7 @@ pub async fn payout_create_db_entries(
|
||||
key_store: &domain::MerchantKeyStore,
|
||||
req: &payouts::PayoutCreateRequest,
|
||||
payout_id: &String,
|
||||
profile_id: &String,
|
||||
connector_name: &api_enums::PayoutConnectors,
|
||||
stored_payout_method_data: Option<&payouts::PayoutMethodData>,
|
||||
) -> RouterResult<PayoutData> {
|
||||
@ -1231,8 +1223,7 @@ pub async fn payout_create_db_entries(
|
||||
} else {
|
||||
storage_enums::PayoutStatus::RequiresPayoutMethodData
|
||||
};
|
||||
let _id = core_utils::get_or_generate_uuid("payout_attempt_id", None)?;
|
||||
let payout_attempt_id = format!("{}_{}", merchant_id.to_owned(), payout_id.to_owned());
|
||||
let payout_attempt_id = utils::get_payment_attempt_id(payout_id, 1);
|
||||
|
||||
let payout_attempt_req = storage::PayoutAttemptNew::default()
|
||||
.set_payout_attempt_id(payout_attempt_id.to_string())
|
||||
@ -1247,7 +1238,7 @@ pub async fn payout_create_db_entries(
|
||||
.set_payout_token(req.payout_token.to_owned())
|
||||
.set_created_at(Some(common_utils::date_time::now()))
|
||||
.set_last_modified_at(Some(common_utils::date_time::now()))
|
||||
.set_profile_id(req.profile_id.to_owned())
|
||||
.set_profile_id(Some(profile_id.to_string()))
|
||||
.to_owned();
|
||||
let payout_attempt = db
|
||||
.insert_payout_attempt(payout_attempt_req)
|
||||
@ -1269,6 +1260,7 @@ pub async fn payout_create_db_entries(
|
||||
.cloned()
|
||||
.or(stored_payout_method_data.cloned()),
|
||||
merchant_connector_account: None,
|
||||
profile_id: profile_id.to_owned(),
|
||||
})
|
||||
}
|
||||
|
||||
@ -1318,6 +1310,8 @@ pub async fn make_payout_data(
|
||||
.await
|
||||
.map_or(None, |c| c);
|
||||
|
||||
let profile_id = payout_attempt.profile_id.clone();
|
||||
|
||||
Ok(PayoutData {
|
||||
billing_address,
|
||||
customer_details,
|
||||
@ -1325,5 +1319,6 @@ pub async fn make_payout_data(
|
||||
payout_attempt,
|
||||
payout_method_data: None,
|
||||
merchant_connector_account: None,
|
||||
profile_id,
|
||||
})
|
||||
}
|
||||
|
||||
@ -8,7 +8,6 @@ use crate::{
|
||||
utils as core_utils,
|
||||
},
|
||||
db::StorageInterface,
|
||||
logger,
|
||||
routes::AppState,
|
||||
types::{api::payouts, domain, storage},
|
||||
utils,
|
||||
@ -24,8 +23,6 @@ pub async fn validate_uniqueness_of_payout_id_against_merchant_id(
|
||||
let payout = db
|
||||
.find_payout_by_merchant_id_payout_id(merchant_id, payout_id)
|
||||
.await;
|
||||
|
||||
logger::debug!(?payout);
|
||||
match payout {
|
||||
Err(err) => {
|
||||
if err.current_context().is_db_not_found() {
|
||||
@ -58,7 +55,7 @@ pub async fn validate_create_request(
|
||||
merchant_account: &domain::MerchantAccount,
|
||||
req: &payouts::PayoutCreateRequest,
|
||||
merchant_key_store: &domain::MerchantKeyStore,
|
||||
) -> RouterResult<(String, Option<payouts::PayoutMethodData>)> {
|
||||
) -> RouterResult<(String, Option<payouts::PayoutMethodData>, String)> {
|
||||
let merchant_id = &merchant_account.merchant_id;
|
||||
|
||||
// Merchant ID
|
||||
@ -111,5 +108,16 @@ pub async fn validate_create_request(
|
||||
None => None,
|
||||
};
|
||||
|
||||
Ok((payout_id, payout_method_data))
|
||||
// Profile ID
|
||||
let profile_id = core_utils::get_profile_id_from_business_details(
|
||||
req.business_country,
|
||||
req.business_label.as_ref(),
|
||||
merchant_account,
|
||||
req.profile_id.as_ref(),
|
||||
&*state.store,
|
||||
false,
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok((payout_id, payout_method_data, profile_id))
|
||||
}
|
||||
|
||||
@ -48,33 +48,21 @@ pub async fn get_mca_for_payout<'a>(
|
||||
merchant_account: &domain::MerchantAccount,
|
||||
key_store: &domain::MerchantKeyStore,
|
||||
payout_data: &PayoutData,
|
||||
) -> RouterResult<(helpers::MerchantConnectorAccountType, String)> {
|
||||
let payout_attempt = &payout_data.payout_attempt;
|
||||
let profile_id = get_profile_id_from_business_details(
|
||||
payout_attempt.business_country,
|
||||
payout_attempt.business_label.as_ref(),
|
||||
merchant_account,
|
||||
payout_attempt.profile_id.as_ref(),
|
||||
&*state.store,
|
||||
false,
|
||||
)
|
||||
.await
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("profile_id is not set in payout_attempt")?;
|
||||
) -> RouterResult<helpers::MerchantConnectorAccountType> {
|
||||
match payout_data.merchant_connector_account.to_owned() {
|
||||
Some(mca) => Ok((mca, profile_id)),
|
||||
Some(mca) => Ok(mca),
|
||||
None => {
|
||||
let merchant_connector_account = helpers::get_merchant_connector_account(
|
||||
state,
|
||||
merchant_account.merchant_id.as_str(),
|
||||
None,
|
||||
key_store,
|
||||
&profile_id,
|
||||
&payout_data.profile_id,
|
||||
connector_id,
|
||||
payout_attempt.merchant_connector_id.as_ref(),
|
||||
payout_data.payout_attempt.merchant_connector_id.as_ref(),
|
||||
)
|
||||
.await?;
|
||||
Ok((merchant_connector_account, profile_id))
|
||||
Ok(merchant_connector_account)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -89,7 +77,7 @@ pub async fn construct_payout_router_data<'a, F>(
|
||||
_request: &api_models::payouts::PayoutRequest,
|
||||
payout_data: &mut PayoutData,
|
||||
) -> RouterResult<types::PayoutsRouterData<F>> {
|
||||
let (merchant_connector_account, profile_id) = get_mca_for_payout(
|
||||
let merchant_connector_account = get_mca_for_payout(
|
||||
state,
|
||||
connector_id,
|
||||
merchant_account,
|
||||
@ -135,7 +123,7 @@ pub async fn construct_payout_router_data<'a, F>(
|
||||
let payouts = &payout_data.payouts;
|
||||
let payout_attempt = &payout_data.payout_attempt;
|
||||
let customer_details = &payout_data.customer_details;
|
||||
let connector_label = format!("{profile_id}_{}", payout_attempt.connector);
|
||||
let connector_label = format!("{}_{}", payout_data.profile_id, payout_attempt.connector);
|
||||
let connector_customer_id = customer_details
|
||||
.as_ref()
|
||||
.and_then(|c| c.connector_customer.as_ref())
|
||||
|
||||
Reference in New Issue
Block a user