mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-30 01:27:31 +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)
|
get_connector_tokenization_action(state, &operation, payment_data, &validate_result)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let connector_string = connector
|
let updated_customer = call_create_connector_customer_if_required(
|
||||||
.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(
|
|
||||||
state,
|
state,
|
||||||
&connector_string,
|
&payment_data.payment_attempt.connector.clone(),
|
||||||
&customer,
|
&customer,
|
||||||
&merchant_account,
|
&merchant_account,
|
||||||
&mut payment_data,
|
&mut payment_data,
|
||||||
@ -612,7 +605,7 @@ where
|
|||||||
Ok(payment_data)
|
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,
|
state: &AppState,
|
||||||
connector_name: &Option<String>,
|
connector_name: &Option<String>,
|
||||||
customer: &Option<storage::Customer>,
|
customer: &Option<storage::Customer>,
|
||||||
@ -640,14 +633,31 @@ where
|
|||||||
connector_name,
|
connector_name,
|
||||||
api::GetToken::Connector,
|
api::GetToken::Connector,
|
||||||
)?;
|
)?;
|
||||||
let router_data = payment_data
|
let (is_eligible, connector_customer_id, connector_customer_map) =
|
||||||
.construct_router_data(state, connector.connector.id(), merchant_account, customer)
|
customers::should_call_connector_create_customer(state, &connector, customer)?;
|
||||||
.await?;
|
|
||||||
let (connector_customer, customer_update) = router_data
|
if is_eligible {
|
||||||
.create_connector_customer(state, &connector, customer)
|
// Create customer at connector and update the customer table to store this data
|
||||||
.await?;
|
let router_data = payment_data
|
||||||
payment_data.connector_customer_id = connector_customer;
|
.construct_router_data(
|
||||||
Ok(customer_update)
|
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),
|
None => Ok(None),
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,68 +15,62 @@ use crate::{
|
|||||||
pub async fn create_connector_customer<F: Clone, T: Clone>(
|
pub async fn create_connector_customer<F: Clone, T: Clone>(
|
||||||
state: &AppState,
|
state: &AppState,
|
||||||
connector: &api::ConnectorData,
|
connector: &api::ConnectorData,
|
||||||
customer: &Option<storage::Customer>,
|
|
||||||
router_data: &types::RouterData<F, T, types::PaymentsResponseData>,
|
router_data: &types::RouterData<F, T, types::PaymentsResponseData>,
|
||||||
customer_request_data: types::ConnectorCustomerData,
|
customer_request_data: types::ConnectorCustomerData,
|
||||||
|
connector_customer_map: Option<serde_json::Map<String, serde_json::Value>>,
|
||||||
) -> RouterResult<(Option<String>, Option<storage::CustomerUpdate>)> {
|
) -> RouterResult<(Option<String>, Option<storage::CustomerUpdate>)> {
|
||||||
let (is_eligible, connector_customer_id, connector_customer_map) =
|
let connector_integration: services::BoxedConnectorIntegration<
|
||||||
should_call_connector_create_customer(state, connector, customer)?;
|
'_,
|
||||||
|
api::CreateConnectorCustomer,
|
||||||
|
types::ConnectorCustomerData,
|
||||||
|
types::PaymentsResponseData,
|
||||||
|
> = connector.connector.get_connector_integration();
|
||||||
|
|
||||||
if is_eligible {
|
let customer_response_data: Result<types::PaymentsResponseData, types::ErrorResponse> =
|
||||||
let connector_integration: services::BoxedConnectorIntegration<
|
Err(types::ErrorResponse::default());
|
||||||
'_,
|
|
||||||
api::CreateConnectorCustomer,
|
|
||||||
types::ConnectorCustomerData,
|
|
||||||
types::PaymentsResponseData,
|
|
||||||
> = connector.connector.get_connector_integration();
|
|
||||||
|
|
||||||
let customer_response_data: Result<types::PaymentsResponseData, types::ErrorResponse> =
|
let customer_router_data = payments::helpers::router_data_type_conversion::<
|
||||||
Err(types::ErrorResponse::default());
|
_,
|
||||||
|
api::CreateConnectorCustomer,
|
||||||
|
_,
|
||||||
|
_,
|
||||||
|
_,
|
||||||
|
_,
|
||||||
|
>(
|
||||||
|
router_data.clone(),
|
||||||
|
customer_request_data,
|
||||||
|
customer_response_data,
|
||||||
|
);
|
||||||
|
|
||||||
let customer_router_data = payments::helpers::router_data_type_conversion::<
|
let resp = services::execute_connector_processing_step(
|
||||||
_,
|
state,
|
||||||
api::CreateConnectorCustomer,
|
connector_integration,
|
||||||
_,
|
&customer_router_data,
|
||||||
_,
|
payments::CallConnectorAction::Trigger,
|
||||||
_,
|
)
|
||||||
_,
|
.await
|
||||||
>(
|
.map_err(|error| error.to_payment_failed_response())?;
|
||||||
router_data.clone(),
|
|
||||||
customer_request_data,
|
|
||||||
customer_response_data,
|
|
||||||
);
|
|
||||||
|
|
||||||
let resp = services::execute_connector_processing_step(
|
let connector_customer_id = match resp.response {
|
||||||
state,
|
Ok(response) => match response {
|
||||||
connector_integration,
|
types::PaymentsResponseData::ConnectorCustomerResponse {
|
||||||
&customer_router_data,
|
connector_customer_id,
|
||||||
payments::CallConnectorAction::Trigger,
|
} => Some(connector_customer_id),
|
||||||
)
|
_ => None,
|
||||||
.await
|
},
|
||||||
.map_err(|error| error.to_payment_failed_response())?;
|
Err(err) => {
|
||||||
|
logger::debug!(payment_method_tokenization_error=?err);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let connector_customer_id = match resp.response {
|
let update_customer = update_connector_customer_in_customers(
|
||||||
Ok(response) => match response {
|
connector,
|
||||||
types::PaymentsResponseData::ConnectorCustomerResponse {
|
connector_customer_map,
|
||||||
connector_customer_id,
|
&connector_customer_id,
|
||||||
} => Some(connector_customer_id),
|
)
|
||||||
_ => None,
|
.await?;
|
||||||
},
|
Ok((connector_customer_id, update_customer))
|
||||||
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))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type CreateCustomerCheck = (
|
type CreateCustomerCheck = (
|
||||||
@ -96,6 +90,7 @@ pub fn should_call_connector_create_customer(
|
|||||||
.connector_customer
|
.connector_customer
|
||||||
.connector_list
|
.connector_list
|
||||||
.contains(&connector.connector_name);
|
.contains(&connector.connector_name);
|
||||||
|
|
||||||
if connector_customer_filter {
|
if connector_customer_filter {
|
||||||
match customer {
|
match customer {
|
||||||
Some(customer) => match &customer.connector_customer {
|
Some(customer) => match &customer.connector_customer {
|
||||||
|
|||||||
@ -74,7 +74,7 @@ pub trait Feature<F, T> {
|
|||||||
&self,
|
&self,
|
||||||
_state: &AppState,
|
_state: &AppState,
|
||||||
_connector: &api::ConnectorData,
|
_connector: &api::ConnectorData,
|
||||||
_customer: &Option<storage::Customer>,
|
_connector_customer_map: Option<serde_json::Map<String, serde_json::Value>>,
|
||||||
) -> RouterResult<(Option<String>, Option<storage::CustomerUpdate>)>
|
) -> RouterResult<(Option<String>, Option<storage::CustomerUpdate>)>
|
||||||
where
|
where
|
||||||
F: Clone,
|
F: Clone,
|
||||||
|
|||||||
@ -100,14 +100,14 @@ impl Feature<api::Authorize, types::PaymentsAuthorizeData> for types::PaymentsAu
|
|||||||
&self,
|
&self,
|
||||||
state: &AppState,
|
state: &AppState,
|
||||||
connector: &api::ConnectorData,
|
connector: &api::ConnectorData,
|
||||||
customer: &Option<storage::Customer>,
|
connector_customer_map: Option<serde_json::Map<String, serde_json::Value>>,
|
||||||
) -> RouterResult<(Option<String>, Option<storage::CustomerUpdate>)> {
|
) -> RouterResult<(Option<String>, Option<storage::CustomerUpdate>)> {
|
||||||
customers::create_connector_customer(
|
customers::create_connector_customer(
|
||||||
state,
|
state,
|
||||||
connector,
|
connector,
|
||||||
customer,
|
|
||||||
self,
|
self,
|
||||||
types::ConnectorCustomerData::try_from(self.request.to_owned())?,
|
types::ConnectorCustomerData::try_from(self.request.to_owned())?,
|
||||||
|
connector_customer_map,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|||||||
@ -84,14 +84,14 @@ impl Feature<api::Verify, types::VerifyRequestData> for types::VerifyRouterData
|
|||||||
&self,
|
&self,
|
||||||
state: &AppState,
|
state: &AppState,
|
||||||
connector: &api::ConnectorData,
|
connector: &api::ConnectorData,
|
||||||
customer: &Option<storage::Customer>,
|
connector_customer_map: Option<serde_json::Map<String, serde_json::Value>>,
|
||||||
) -> RouterResult<(Option<String>, Option<storage::CustomerUpdate>)> {
|
) -> RouterResult<(Option<String>, Option<storage::CustomerUpdate>)> {
|
||||||
customers::create_connector_customer(
|
customers::create_connector_customer(
|
||||||
state,
|
state,
|
||||||
connector,
|
connector,
|
||||||
customer,
|
|
||||||
self,
|
self,
|
||||||
types::ConnectorCustomerData::try_from(self.request.to_owned())?,
|
types::ConnectorCustomerData::try_from(self.request.to_owned())?,
|
||||||
|
connector_customer_map,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user