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:
Kashif
2023-11-21 13:04:22 +05:30
committed by GitHub
parent cfabfa60db
commit 5c4e7c9031
96 changed files with 2310 additions and 62 deletions

View File

@ -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",
})?,
};

View File

@ -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)

View File

@ -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,
})
}

View File

@ -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))
}

View File

@ -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())