refactor(payout): move payout quote call to payout core from execute_pretasks (#4900)

This commit is contained in:
Hrithikesh
2024-06-07 16:14:05 +05:30
committed by GitHub
parent 39d46fd015
commit d0fd7095cd
10 changed files with 71 additions and 160 deletions

View File

@ -913,7 +913,6 @@ Utility functions for tests are also available at `tests/connector/utils`. These
Box::new(services::MockApiClient),
)
.await;
integration.execute_pretasks(&mut request, &state).await?;
Box::pin(call_connector(request, integration)).await
}
```

View File

@ -155,6 +155,10 @@ impl Connector {
matches!((self, payout_method), (_, PayoutType::Card))
}
#[cfg(feature = "payouts")]
pub fn is_payout_quote_call_required(&self) -> bool {
matches!(self, Self::Wise)
}
#[cfg(feature = "payouts")]
pub fn supports_access_token_for_payout(&self, payout_method: PayoutType) -> bool {
matches!((self, payout_method), (Self::Paypal, _))
}

View File

@ -26,8 +26,6 @@ use crate::{
},
utils::BytesExt,
};
#[cfg(feature = "payouts")]
use crate::{core::payments, routes, types::transformers::ForeignFrom};
#[derive(Debug, Clone)]
pub struct Wise;
@ -503,44 +501,6 @@ impl
impl services::ConnectorIntegration<api::PoCreate, types::PayoutsData, types::PayoutsResponseData>
for Wise
{
async fn execute_pretasks(
&self,
router_data: &mut types::PayoutsRouterData<api::PoCreate>,
app_state: &routes::SessionState,
) -> CustomResult<(), errors::ConnectorError> {
// Create a quote
let quote_router_data =
&types::PayoutsRouterData::foreign_from((&router_data, router_data.request.clone()));
let quote_connector_integration: Box<
&(dyn services::ConnectorIntegration<
api::PoQuote,
types::PayoutsData,
types::PayoutsResponseData,
> + Send
+ Sync
+ 'static),
> = Box::new(self);
let quote_router_resp = services::execute_connector_processing_step(
app_state,
quote_connector_integration,
quote_router_data,
payments::CallConnectorAction::Trigger,
None,
)
.await?;
match quote_router_resp.response.to_owned() {
Ok(resp) => {
router_data.quote_id = resp.connector_payout_id;
Ok(())
}
Err(_err) => {
router_data.response = quote_router_resp.response;
Ok(())
}
}
}
fn get_url(
&self,
_req: &types::PayoutsRouterData<api::PoCreate>,

View File

@ -205,10 +205,6 @@ impl Feature<api::Authorize, types::PaymentsAuthorizeData> for types::PaymentsAu
types::PaymentsAuthorizeData,
types::PaymentsResponseData,
> = connector.connector.get_connector_integration();
connector_integration
.execute_pretasks(self, state)
.await
.to_payment_failed_response()?;
metrics::EXECUTE_PRETASK_COUNT.add(
&metrics::CONTEXT,

View File

@ -738,18 +738,13 @@ pub async fn add_payment_method_token<F: Clone, T: types::Tokenizable + Clone>(
let pm_token_response_data: Result<types::PaymentsResponseData, types::ErrorResponse> =
Err(types::ErrorResponse::default());
let mut pm_token_router_data =
let pm_token_router_data =
helpers::router_data_type_conversion::<_, api::PaymentMethodToken, _, _, _, _>(
router_data.clone(),
pm_token_request_data,
pm_token_response_data,
);
connector_integration
.execute_pretasks(&mut pm_token_router_data, state)
.await
.to_payment_failed_response()?;
router_data
.request
.set_session_token(pm_token_router_data.session_token.clone());

View File

@ -26,7 +26,7 @@ use super::{
payments::customers,
};
#[cfg(feature = "olap")]
use crate::types::{domain::behaviour::Conversion, transformers::ForeignFrom};
use crate::types::domain::behaviour::Conversion;
use crate::{
core::{
errors::{self, CustomResult, RouterResponse, RouterResult},
@ -41,6 +41,7 @@ use crate::{
api::{self, payouts},
domain,
storage::{self, PaymentRoutingInfo},
transformers::ForeignFrom,
},
utils::{self, OptionExt},
};
@ -160,13 +161,13 @@ pub async fn make_connector_decision(
) -> RouterResult<()> {
match connector_call_type {
api::ConnectorCallType::PreDetermined(connector_data) => {
call_connector_payout(
Box::pin(call_connector_payout(
state,
merchant_account,
key_store,
&connector_data,
payout_data,
)
))
.await?;
#[cfg(feature = "payout_retry")]
@ -197,13 +198,13 @@ pub async fn make_connector_decision(
let connector_data = get_next_connector(&mut connectors)?;
call_connector_payout(
Box::pin(call_connector_payout(
state,
merchant_account,
key_store,
&connector_data,
payout_data,
)
))
.await?;
#[cfg(feature = "payout_retry")]
@ -933,13 +934,13 @@ pub async fn call_connector_payout(
.await?;
// Payout creation flow
complete_create_payout(
Box::pin(complete_create_payout(
state,
merchant_account,
key_store,
connector_data,
payout_data,
)
))
.await?;
};
@ -1380,10 +1381,7 @@ pub async fn create_payout(
> = connector_data.connector.get_connector_integration();
// 4. Execute pretasks
connector_integration
.execute_pretasks(&mut router_data, state)
.await
.to_payout_failed_response()?;
complete_payout_quote_steps_if_required(state, connector_data, &mut router_data).await?;
// 5. Call connector service
let router_data_resp = services::execute_connector_processing_step(
@ -1474,6 +1472,45 @@ pub async fn create_payout(
Ok(())
}
async fn complete_payout_quote_steps_if_required<F>(
state: &SessionState,
connector_data: &api::ConnectorData,
router_data: &mut types::RouterData<F, types::PayoutsData, types::PayoutsResponseData>,
) -> RouterResult<()> {
if connector_data
.connector_name
.is_payout_quote_call_required()
{
let quote_router_data =
types::PayoutsRouterData::foreign_from((router_data, router_data.request.clone()));
let connector_integration: services::BoxedConnectorIntegration<
'_,
api::PoQuote,
types::PayoutsData,
types::PayoutsResponseData,
> = connector_data.connector.get_connector_integration();
let router_data_resp = services::execute_connector_processing_step(
state,
connector_integration,
&quote_router_data,
payments::CallConnectorAction::Trigger,
None,
)
.await
.to_payout_failed_response()?;
match router_data_resp.response.to_owned() {
Ok(resp) => {
router_data.quote_id = resp.connector_payout_id;
}
Err(_err) => {
router_data.response = router_data_resp.response;
}
};
}
Ok(())
}
pub async fn complete_create_recipient_disburse_account(
state: &SessionState,
merchant_account: &domain::MerchantAccount,

View File

@ -246,7 +246,14 @@ pub async fn do_retry(
modify_trackers(state, &connector, merchant_account, payout_data).await?;
call_connector_payout(state, merchant_account, key_store, &connector, payout_data).await
Box::pin(call_connector_payout(
state,
merchant_account,
key_store,
&connector,
payout_data,
))
.await
}
#[instrument(skip_all)]

View File

@ -171,26 +171,6 @@ pub trait ConnectorIntegration<T, Req, Resp>: ConnectorIntegrationAny<T, Req, Re
Ok(None)
}
/// This module can be called before executing a payment flow where a pre-task is needed
/// Eg: Some connectors requires one-time session token before making a payment, we can add the session token creation logic in this block
async fn execute_pretasks(
&self,
_router_data: &mut types::RouterData<T, Req, Resp>,
_app_state: &SessionState,
) -> CustomResult<(), errors::ConnectorError> {
Ok(())
}
/// This module can be called after executing a payment flow where a post-task needed
/// Eg: Some connectors require payment sync to happen immediately after the authorize call to complete the transaction, we can add that logic in this block
async fn execute_posttasks(
&self,
_router_data: &mut types::RouterData<T, Req, Resp>,
_app_state: &SessionState,
) -> CustomResult<(), errors::ConnectorError> {
Ok(())
}
fn build_request(
&self,
req: &types::RouterData<T, Req, Resp>,

View File

@ -842,13 +842,13 @@ impl<F1, F2, T1, T2> ForeignFrom<(&RouterData<F1, T1, PaymentsResponseData>, T2)
#[cfg(feature = "payouts")]
impl<F1, F2>
ForeignFrom<(
&&mut RouterData<F1, PayoutsData, PayoutsResponseData>,
&RouterData<F1, PayoutsData, PayoutsResponseData>,
PayoutsData,
)> for RouterData<F2, PayoutsData, PayoutsResponseData>
{
fn foreign_from(
item: (
&&mut RouterData<F1, PayoutsData, PayoutsResponseData>,
&RouterData<F1, PayoutsData, PayoutsResponseData>,
PayoutsData,
),
) -> Self {

View File

@ -86,7 +86,7 @@ pub trait ConnectorActions: Connector {
payment_info: Option<PaymentInfo>,
) -> Result<types::PaymentsAuthorizeRouterData, Report<ConnectorError>> {
let integration = self.get_data().connector.get_connector_integration();
let mut request = self.generate_data(
let request = self.generate_data(
types::PaymentsAuthorizeData {
confirm: true,
capture_method: Some(diesel_models::enums::CaptureMethod::Manual),
@ -94,18 +94,6 @@ pub trait ConnectorActions: Connector {
},
payment_info,
);
let tx: oneshot::Sender<()> = oneshot::channel().0;
let app_state = Box::pin(routes::AppState::with_storage(
Settings::new().unwrap(),
StorageImpl::PostgresqlTest,
tx,
Box::new(services::MockApiClient),
))
.await;
let state = Arc::new(app_state)
.get_session_state("public", || {})
.unwrap();
integration.execute_pretasks(&mut request, &state).await?;
Box::pin(call_connector(request, integration)).await
}
@ -115,25 +103,12 @@ pub trait ConnectorActions: Connector {
payment_info: Option<PaymentInfo>,
) -> Result<types::ConnectorCustomerRouterData, Report<ConnectorError>> {
let integration = self.get_data().connector.get_connector_integration();
let mut request = self.generate_data(
let request = self.generate_data(
types::ConnectorCustomerData {
..(payment_data.unwrap_or(CustomerType::default().0))
},
payment_info,
);
let tx: oneshot::Sender<()> = oneshot::channel().0;
let app_state = Box::pin(routes::AppState::with_storage(
Settings::new().unwrap(),
StorageImpl::PostgresqlTest,
tx,
Box::new(services::MockApiClient),
))
.await;
let state = Arc::new(app_state)
.get_session_state("public", || {})
.unwrap();
integration.execute_pretasks(&mut request, &state).await?;
Box::pin(call_connector(request, integration)).await
}
@ -143,25 +118,12 @@ pub trait ConnectorActions: Connector {
payment_info: Option<PaymentInfo>,
) -> Result<types::TokenizationRouterData, Report<ConnectorError>> {
let integration = self.get_data().connector.get_connector_integration();
let mut request = self.generate_data(
let request = self.generate_data(
types::PaymentMethodTokenizationData {
..(payment_data.unwrap_or(TokenType::default().0))
},
payment_info,
);
let tx: oneshot::Sender<()> = oneshot::channel().0;
let app_state = Box::pin(routes::AppState::with_storage(
Settings::new().unwrap(),
StorageImpl::PostgresqlTest,
tx,
Box::new(services::MockApiClient),
))
.await;
let state = Arc::new(app_state)
.get_session_state("public", || {})
.unwrap();
integration.execute_pretasks(&mut request, &state).await?;
Box::pin(call_connector(request, integration)).await
}
@ -173,7 +135,7 @@ pub trait ConnectorActions: Connector {
payment_info: Option<PaymentInfo>,
) -> Result<types::PaymentsAuthorizeRouterData, Report<ConnectorError>> {
let integration = self.get_data().connector.get_connector_integration();
let mut request = self.generate_data(
let request = self.generate_data(
types::PaymentsAuthorizeData {
confirm: true,
capture_method: Some(diesel_models::enums::CaptureMethod::Automatic),
@ -181,19 +143,6 @@ pub trait ConnectorActions: Connector {
},
payment_info,
);
let tx: oneshot::Sender<()> = oneshot::channel().0;
let app_state = Box::pin(routes::AppState::with_storage(
Settings::new().unwrap(),
StorageImpl::PostgresqlTest,
tx,
Box::new(services::MockApiClient),
))
.await;
let state = Arc::new(app_state)
.get_session_state("public", || {})
.unwrap();
integration.execute_pretasks(&mut request, &state).await?;
Box::pin(call_connector(request, integration)).await
}
@ -609,7 +558,7 @@ pub trait ConnectorActions: Connector {
.ok_or(ConnectorError::FailedToObtainPreferredConnector)?
.connector
.get_connector_integration();
let mut request = self.get_payout_request(None, payout_type, payment_info);
let request = self.get_payout_request(None, payout_type, payment_info);
let tx: oneshot::Sender<()> = oneshot::channel().0;
let app_state = Box::pin(routes::AppState::with_storage(
@ -622,9 +571,6 @@ pub trait ConnectorActions: Connector {
let state = Arc::new(app_state)
.get_session_state("public", || {})
.unwrap();
connector_integration
.execute_pretasks(&mut request, &state)
.await?;
let res = services::api::execute_connector_processing_step(
&state,
connector_integration,
@ -653,7 +599,7 @@ pub trait ConnectorActions: Connector {
.ok_or(ConnectorError::FailedToObtainPreferredConnector)?
.connector
.get_connector_integration();
let mut request = self.get_payout_request(connector_payout_id, payout_type, payment_info);
let request = self.get_payout_request(connector_payout_id, payout_type, payment_info);
let tx: oneshot::Sender<()> = oneshot::channel().0;
let app_state = Box::pin(routes::AppState::with_storage(
@ -666,9 +612,6 @@ pub trait ConnectorActions: Connector {
let state = Arc::new(app_state)
.get_session_state("public", || {})
.unwrap();
connector_integration
.execute_pretasks(&mut request, &state)
.await?;
let res = services::api::execute_connector_processing_step(
&state,
connector_integration,
@ -711,9 +654,6 @@ pub trait ConnectorActions: Connector {
let state = Arc::new(app_state)
.get_session_state("public", || {})
.unwrap();
connector_integration
.execute_pretasks(&mut request, &state)
.await?;
let res = services::api::execute_connector_processing_step(
&state,
connector_integration,
@ -742,8 +682,7 @@ pub trait ConnectorActions: Connector {
.ok_or(ConnectorError::FailedToObtainPreferredConnector)?
.connector
.get_connector_integration();
let mut request =
self.get_payout_request(Some(connector_payout_id), payout_type, payment_info);
let request = self.get_payout_request(Some(connector_payout_id), payout_type, payment_info);
let tx: oneshot::Sender<()> = oneshot::channel().0;
let app_state = Box::pin(routes::AppState::with_storage(
@ -756,9 +695,6 @@ pub trait ConnectorActions: Connector {
let state = Arc::new(app_state)
.get_session_state("public", || {})
.unwrap();
connector_integration
.execute_pretasks(&mut request, &state)
.await?;
let res = services::api::execute_connector_processing_step(
&state,
connector_integration,
@ -838,7 +774,7 @@ pub trait ConnectorActions: Connector {
.ok_or(ConnectorError::FailedToObtainPreferredConnector)?
.connector
.get_connector_integration();
let mut request = self.get_payout_request(None, payout_type, payment_info);
let request = self.get_payout_request(None, payout_type, payment_info);
let tx = oneshot::channel().0;
let app_state = Box::pin(routes::AppState::with_storage(
@ -851,9 +787,6 @@ pub trait ConnectorActions: Connector {
let state = Arc::new(app_state)
.get_session_state("public", || {})
.unwrap();
connector_integration
.execute_pretasks(&mut request, &state)
.await?;
let res = services::api::execute_connector_processing_step(
&state,
connector_integration,