diff --git a/crates/router/src/core/payments.rs b/crates/router/src/core/payments.rs index e9b19be78b..26ba2e1065 100644 --- a/crates/router/src/core/payments.rs +++ b/crates/router/src/core/payments.rs @@ -120,16 +120,9 @@ where get_connector_tokenization_action(state, &operation, payment_data, &validate_result) .await?; - let connector_string = connector - .as_ref() - .and_then(|connector_type| match connector_type { - api::ConnectorCallType::Single(connector) => Some(connector.connector_name.to_string()), - _ => None, - }); - - let updated_customer = call_create_connector_customer( + let updated_customer = call_create_connector_customer_if_required( state, - &connector_string, + &payment_data.payment_attempt.connector.clone(), &customer, &merchant_account, &mut payment_data, @@ -612,7 +605,7 @@ where Ok(payment_data) } -pub async fn call_create_connector_customer( +pub async fn call_create_connector_customer_if_required( state: &AppState, connector_name: &Option, customer: &Option, @@ -640,14 +633,31 @@ where connector_name, api::GetToken::Connector, )?; - let router_data = payment_data - .construct_router_data(state, connector.connector.id(), merchant_account, customer) - .await?; - let (connector_customer, customer_update) = router_data - .create_connector_customer(state, &connector, customer) - .await?; - payment_data.connector_customer_id = connector_customer; - Ok(customer_update) + let (is_eligible, connector_customer_id, connector_customer_map) = + customers::should_call_connector_create_customer(state, &connector, customer)?; + + if is_eligible { + // Create customer at connector and update the customer table to store this data + let router_data = payment_data + .construct_router_data( + state, + connector.connector.id(), + merchant_account, + customer, + ) + .await?; + + let (connector_customer, customer_update) = router_data + .create_connector_customer(state, &connector, connector_customer_map) + .await?; + + payment_data.connector_customer_id = connector_customer; + Ok(customer_update) + } else { + // Customer already created in previous calls use the same value, no need to update + payment_data.connector_customer_id = connector_customer_id; + Ok(None) + } } None => Ok(None), } diff --git a/crates/router/src/core/payments/customers.rs b/crates/router/src/core/payments/customers.rs index 890e7bfa4d..910fb5f985 100644 --- a/crates/router/src/core/payments/customers.rs +++ b/crates/router/src/core/payments/customers.rs @@ -15,68 +15,62 @@ use crate::{ pub async fn create_connector_customer( state: &AppState, connector: &api::ConnectorData, - customer: &Option, router_data: &types::RouterData, customer_request_data: types::ConnectorCustomerData, + connector_customer_map: Option>, ) -> RouterResult<(Option, Option)> { - let (is_eligible, connector_customer_id, connector_customer_map) = - should_call_connector_create_customer(state, connector, customer)?; + let connector_integration: services::BoxedConnectorIntegration< + '_, + api::CreateConnectorCustomer, + types::ConnectorCustomerData, + types::PaymentsResponseData, + > = connector.connector.get_connector_integration(); - if is_eligible { - let connector_integration: services::BoxedConnectorIntegration< - '_, - api::CreateConnectorCustomer, - types::ConnectorCustomerData, - types::PaymentsResponseData, - > = connector.connector.get_connector_integration(); + let customer_response_data: Result = + Err(types::ErrorResponse::default()); - let customer_response_data: Result = - Err(types::ErrorResponse::default()); + let customer_router_data = payments::helpers::router_data_type_conversion::< + _, + api::CreateConnectorCustomer, + _, + _, + _, + _, + >( + router_data.clone(), + customer_request_data, + customer_response_data, + ); - let customer_router_data = payments::helpers::router_data_type_conversion::< - _, - api::CreateConnectorCustomer, - _, - _, - _, - _, - >( - router_data.clone(), - customer_request_data, - customer_response_data, - ); + let resp = services::execute_connector_processing_step( + state, + connector_integration, + &customer_router_data, + payments::CallConnectorAction::Trigger, + ) + .await + .map_err(|error| error.to_payment_failed_response())?; - let resp = services::execute_connector_processing_step( - state, - connector_integration, - &customer_router_data, - payments::CallConnectorAction::Trigger, - ) - .await - .map_err(|error| error.to_payment_failed_response())?; + let connector_customer_id = match resp.response { + Ok(response) => match response { + types::PaymentsResponseData::ConnectorCustomerResponse { + connector_customer_id, + } => Some(connector_customer_id), + _ => None, + }, + Err(err) => { + logger::debug!(payment_method_tokenization_error=?err); + None + } + }; - let connector_customer_id = match resp.response { - Ok(response) => match response { - types::PaymentsResponseData::ConnectorCustomerResponse { - connector_customer_id, - } => Some(connector_customer_id), - _ => None, - }, - Err(err) => { - logger::debug!(payment_method_tokenization_error=?err); - None - } - }; - let update_customer = update_connector_customer_in_customers( - connector, - connector_customer_map, - &connector_customer_id, - ) - .await?; - Ok((connector_customer_id, update_customer)) - } else { - Ok((connector_customer_id, None)) - } + let update_customer = update_connector_customer_in_customers( + connector, + connector_customer_map, + &connector_customer_id, + ) + .await?; + Ok((connector_customer_id, update_customer)) } type CreateCustomerCheck = ( @@ -96,6 +90,7 @@ pub fn should_call_connector_create_customer( .connector_customer .connector_list .contains(&connector.connector_name); + if connector_customer_filter { match customer { Some(customer) => match &customer.connector_customer { diff --git a/crates/router/src/core/payments/flows.rs b/crates/router/src/core/payments/flows.rs index 0ec52df1f3..a03a5372de 100644 --- a/crates/router/src/core/payments/flows.rs +++ b/crates/router/src/core/payments/flows.rs @@ -74,7 +74,7 @@ pub trait Feature { &self, _state: &AppState, _connector: &api::ConnectorData, - _customer: &Option, + _connector_customer_map: Option>, ) -> RouterResult<(Option, Option)> where F: Clone, diff --git a/crates/router/src/core/payments/flows/authorize_flow.rs b/crates/router/src/core/payments/flows/authorize_flow.rs index 5ff299761f..b95fe32078 100644 --- a/crates/router/src/core/payments/flows/authorize_flow.rs +++ b/crates/router/src/core/payments/flows/authorize_flow.rs @@ -100,14 +100,14 @@ impl Feature for types::PaymentsAu &self, state: &AppState, connector: &api::ConnectorData, - customer: &Option, + connector_customer_map: Option>, ) -> RouterResult<(Option, Option)> { customers::create_connector_customer( state, connector, - customer, self, types::ConnectorCustomerData::try_from(self.request.to_owned())?, + connector_customer_map, ) .await } diff --git a/crates/router/src/core/payments/flows/verfiy_flow.rs b/crates/router/src/core/payments/flows/verfiy_flow.rs index 51745cbde1..235a43b568 100644 --- a/crates/router/src/core/payments/flows/verfiy_flow.rs +++ b/crates/router/src/core/payments/flows/verfiy_flow.rs @@ -84,14 +84,14 @@ impl Feature for types::VerifyRouterData &self, state: &AppState, connector: &api::ConnectorData, - customer: &Option, + connector_customer_map: Option>, ) -> RouterResult<(Option, Option)> { customers::create_connector_customer( state, connector, - customer, self, types::ConnectorCustomerData::try_from(self.request.to_owned())?, + connector_customer_map, ) .await }