mirror of
				https://github.com/juspay/hyperswitch.git
				synced 2025-11-01 02:57:02 +08:00 
			
		
		
		
	fix(connector_customer): create connector_customer on requirement basis (#1097)
This commit is contained in:
		| @ -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<F, Req>( | ||||
| pub async fn call_create_connector_customer_if_required<F, Req>( | ||||
|     state: &AppState, | ||||
|     connector_name: &Option<String>, | ||||
|     customer: &Option<storage::Customer>, | ||||
| @ -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), | ||||
|     } | ||||
|  | ||||
| @ -15,68 +15,62 @@ use crate::{ | ||||
| pub async fn create_connector_customer<F: Clone, T: Clone>( | ||||
|     state: &AppState, | ||||
|     connector: &api::ConnectorData, | ||||
|     customer: &Option<storage::Customer>, | ||||
|     router_data: &types::RouterData<F, T, types::PaymentsResponseData>, | ||||
|     customer_request_data: types::ConnectorCustomerData, | ||||
|     connector_customer_map: Option<serde_json::Map<String, serde_json::Value>>, | ||||
| ) -> RouterResult<(Option<String>, Option<storage::CustomerUpdate>)> { | ||||
|     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<types::PaymentsResponseData, types::ErrorResponse> = | ||||
|         Err(types::ErrorResponse::default()); | ||||
|  | ||||
|         let customer_response_data: Result<types::PaymentsResponseData, types::ErrorResponse> = | ||||
|             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 { | ||||
|  | ||||
| @ -74,7 +74,7 @@ pub trait Feature<F, T> { | ||||
|         &self, | ||||
|         _state: &AppState, | ||||
|         _connector: &api::ConnectorData, | ||||
|         _customer: &Option<storage::Customer>, | ||||
|         _connector_customer_map: Option<serde_json::Map<String, serde_json::Value>>, | ||||
|     ) -> RouterResult<(Option<String>, Option<storage::CustomerUpdate>)> | ||||
|     where | ||||
|         F: Clone, | ||||
|  | ||||
| @ -100,14 +100,14 @@ impl Feature<api::Authorize, types::PaymentsAuthorizeData> for types::PaymentsAu | ||||
|         &self, | ||||
|         state: &AppState, | ||||
|         connector: &api::ConnectorData, | ||||
|         customer: &Option<storage::Customer>, | ||||
|         connector_customer_map: Option<serde_json::Map<String, serde_json::Value>>, | ||||
|     ) -> RouterResult<(Option<String>, Option<storage::CustomerUpdate>)> { | ||||
|         customers::create_connector_customer( | ||||
|             state, | ||||
|             connector, | ||||
|             customer, | ||||
|             self, | ||||
|             types::ConnectorCustomerData::try_from(self.request.to_owned())?, | ||||
|             connector_customer_map, | ||||
|         ) | ||||
|         .await | ||||
|     } | ||||
|  | ||||
| @ -84,14 +84,14 @@ impl Feature<api::Verify, types::VerifyRequestData> for types::VerifyRouterData | ||||
|         &self, | ||||
|         state: &AppState, | ||||
|         connector: &api::ConnectorData, | ||||
|         customer: &Option<storage::Customer>, | ||||
|         connector_customer_map: Option<serde_json::Map<String, serde_json::Value>>, | ||||
|     ) -> RouterResult<(Option<String>, Option<storage::CustomerUpdate>)> { | ||||
|         customers::create_connector_customer( | ||||
|             state, | ||||
|             connector, | ||||
|             customer, | ||||
|             self, | ||||
|             types::ConnectorCustomerData::try_from(self.request.to_owned())?, | ||||
|             connector_customer_map, | ||||
|         ) | ||||
|         .await | ||||
|     } | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 Narayan Bhat
					Narayan Bhat