mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-29 09:07:09 +08:00
fix: consume profile_id throughout payouts flow (#2501)
Co-authored-by: Kashif <mohammed.kashif@juspay.in>
This commit is contained in:
@ -146,6 +146,10 @@ pub struct PayoutCreateRequest {
|
||||
/// Provide a reference to a stored payment 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
|
||||
/// associated with the merchant account will be used.
|
||||
pub profile_id: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, ToSchema)]
|
||||
@ -376,6 +380,9 @@ pub struct PayoutCreateResponse {
|
||||
/// If there was an error while calling the connectors the code is received here
|
||||
#[schema(value_type = String, example = "E0001")]
|
||||
pub error_code: Option<String>,
|
||||
|
||||
/// The business profile that is associated with this payment
|
||||
pub profile_id: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, Deserialize, ToSchema)]
|
||||
|
||||
@ -618,7 +618,7 @@ pub async fn create_recipient(
|
||||
let merchant_id = merchant_account.merchant_id.to_owned();
|
||||
let updated_customer = storage::CustomerUpdate::ConnectorCustomer {
|
||||
connector_customer: Some(
|
||||
serde_json::json!({"id": recipient_create_data.connector_payout_id}),
|
||||
serde_json::json!({connector_label: recipient_create_data.connector_payout_id}),
|
||||
),
|
||||
};
|
||||
payout_data.customer_details = Some(
|
||||
@ -1116,6 +1116,7 @@ pub async fn response_handler(
|
||||
status: payout_attempt.status.to_owned(),
|
||||
error_message: payout_attempt.error_message.to_owned(),
|
||||
error_code: payout_attempt.error_code,
|
||||
profile_id: payout_attempt.profile_id,
|
||||
};
|
||||
Ok(services::ApplicationResponse::Json(response))
|
||||
}
|
||||
@ -1244,6 +1245,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())
|
||||
.to_owned();
|
||||
let payout_attempt = db
|
||||
.insert_payout_attempt(payout_attempt_req)
|
||||
|
||||
@ -40,31 +40,32 @@ pub async fn get_mca_for_payout<'a>(
|
||||
merchant_account: &domain::MerchantAccount,
|
||||
key_store: &domain::MerchantKeyStore,
|
||||
payout_data: &PayoutData,
|
||||
) -> RouterResult<helpers::MerchantConnectorAccountType> {
|
||||
) -> 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")?;
|
||||
match payout_data.merchant_connector_account.to_owned() {
|
||||
Some(mca) => Ok(mca),
|
||||
Some(mca) => Ok((mca, profile_id)),
|
||||
None => {
|
||||
let profile_id = payout_attempt
|
||||
.profile_id
|
||||
.as_ref()
|
||||
.ok_or(errors::ApiErrorResponse::MissingRequiredField {
|
||||
field_name: "business_profile",
|
||||
})
|
||||
.into_report()
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("profile_id is not set in payment_intent")?;
|
||||
|
||||
let merchant_connector_account = helpers::get_merchant_connector_account(
|
||||
state,
|
||||
merchant_account.merchant_id.as_str(),
|
||||
None,
|
||||
key_store,
|
||||
profile_id,
|
||||
&profile_id,
|
||||
connector_id,
|
||||
)
|
||||
.await?;
|
||||
Ok(merchant_connector_account)
|
||||
Ok((merchant_connector_account, profile_id))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -79,12 +80,7 @@ pub async fn construct_payout_router_data<'a, F>(
|
||||
_request: &api_models::payouts::PayoutRequest,
|
||||
payout_data: &mut PayoutData,
|
||||
) -> RouterResult<types::PayoutsRouterData<F>> {
|
||||
let (business_country, _) = helpers::get_business_details(
|
||||
payout_data.payout_attempt.business_country,
|
||||
payout_data.payout_attempt.business_label.as_ref(),
|
||||
merchant_account,
|
||||
)?;
|
||||
let merchant_connector_account = get_mca_for_payout(
|
||||
let (merchant_connector_account, profile_id) = get_mca_for_payout(
|
||||
state,
|
||||
connector_id,
|
||||
merchant_account,
|
||||
@ -130,10 +126,11 @@ 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_customer_id = customer_details
|
||||
.as_ref()
|
||||
.and_then(|c| c.connector_customer.as_ref())
|
||||
.and_then(|cc| cc.get("id"))
|
||||
.and_then(|cc| cc.get(connector_label))
|
||||
.and_then(|id| serde_json::from_value::<String>(id.to_owned()).ok());
|
||||
let router_data = types::RouterData {
|
||||
flow: PhantomData,
|
||||
@ -161,7 +158,6 @@ pub async fn construct_payout_router_data<'a, F>(
|
||||
source_currency: payouts.source_currency,
|
||||
entity_type: payouts.entity_type.to_owned(),
|
||||
payout_type: payouts.payout_type,
|
||||
country_code: business_country,
|
||||
customer_details: customer_details
|
||||
.to_owned()
|
||||
.map(|c| payments::CustomerDetails {
|
||||
|
||||
@ -335,7 +335,6 @@ pub struct PayoutsData {
|
||||
pub source_currency: storage_enums::Currency,
|
||||
pub payout_type: storage_enums::PayoutType,
|
||||
pub entity_type: storage_enums::PayoutEntityType,
|
||||
pub country_code: storage_enums::CountryAlpha2,
|
||||
pub customer_details: Option<CustomerDetails>,
|
||||
}
|
||||
|
||||
|
||||
@ -442,11 +442,6 @@ pub trait ConnectorActions: Connector {
|
||||
}),
|
||||
entity_type: enums::PayoutEntityType::Individual,
|
||||
payout_type,
|
||||
country_code: payment_info
|
||||
.to_owned()
|
||||
.map_or(enums::CountryAlpha2::NL, |pi| {
|
||||
pi.country.map_or(enums::CountryAlpha2::NL, |c| c)
|
||||
}),
|
||||
customer_details: Some(payments::CustomerDetails {
|
||||
customer_id: core_utils::get_or_generate_id("customer_id", &None, "cust_").ok(),
|
||||
name: Some(Secret::new("John Doe".to_string())),
|
||||
|
||||
@ -9847,6 +9847,11 @@
|
||||
"description": "Provide a reference to a stored payment method",
|
||||
"example": "187282ab-40ef-47a9-9206-5099ba31e432",
|
||||
"nullable": true
|
||||
},
|
||||
"profile_id": {
|
||||
"type": "string",
|
||||
"description": "The business profile to use for this payment, if not passed the default business profile\nassociated with the merchant account will be used.",
|
||||
"nullable": true
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -9996,6 +10001,11 @@
|
||||
"type": "string",
|
||||
"description": "If there was an error while calling the connectors the code is received here",
|
||||
"example": "E0001"
|
||||
},
|
||||
"profile_id": {
|
||||
"type": "string",
|
||||
"description": "The business profile that is associated with this payment",
|
||||
"nullable": true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user