fix(router): make customer details None in the Psync flow if the customer is deleted (#5732)

Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
This commit is contained in:
Shankar Singh C
2024-09-03 15:52:35 +05:30
committed by GitHub
parent 42f945fd5e
commit 98cfc13f53
5 changed files with 244 additions and 23 deletions

View File

@ -1372,6 +1372,18 @@ pub async fn get_customer_from_details<F: Clone>(
todo!()
}
#[cfg(all(feature = "v2", feature = "customer_v2"))]
pub async fn get_customer_details_even_for_redacted_customer<F: Clone>(
_state: &SessionState,
_customer_id: Option<id_type::CustomerId>,
_merchant_id: &id_type::MerchantId,
_payment_data: &mut PaymentData<F>,
_merchant_key_store: &domain::MerchantKeyStore,
_storage_scheme: enums::MerchantStorageScheme,
) -> CustomResult<Option<domain::Customer>, errors::StorageError> {
todo!()
}
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "customer_v2")))]
pub async fn get_customer_from_details<F: Clone>(
state: &SessionState,
@ -1712,6 +1724,44 @@ pub async fn create_customer_if_not_exist<'a, F: Clone, R>(
))
}
// This function is to retrieve customer details. If the customer is deleted, it returns
// customer details that contains the fields as Redacted
#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "customer_v2")))]
pub async fn get_customer_details_even_for_redacted_customer<F: Clone>(
state: &SessionState,
customer_id: Option<id_type::CustomerId>,
merchant_id: &id_type::MerchantId,
payment_data: &mut PaymentData<F>,
merchant_key_store: &domain::MerchantKeyStore,
storage_scheme: enums::MerchantStorageScheme,
) -> CustomResult<Option<domain::Customer>, errors::StorageError> {
match customer_id {
None => Ok(None),
Some(customer_id) => {
let db = &*state.store;
let customer_details = db
.find_customer_optional_with_redacted_customer_details_by_customer_id_merchant_id(
&state.into(),
&customer_id,
merchant_id,
merchant_key_store,
storage_scheme,
)
.await?;
payment_data.email = payment_data.email.clone().or_else(|| {
customer_details.as_ref().and_then(|inner| {
inner
.email
.clone()
.map(|encrypted_value| encrypted_value.into())
})
});
Ok(customer_details)
}
}
}
pub async fn retrieve_payment_method_with_temporary_token(
state: &SessionState,
token: &str,

View File

@ -276,7 +276,7 @@ where
> {
Ok((
Box::new(self),
helpers::get_customer_from_details(
helpers::get_customer_details_even_for_redacted_customer(
state,
payment_data.payment_intent.customer_id.clone(),
&merchant_key_store.merchant_id,

View File

@ -601,36 +601,50 @@ where
let customer_table_response: Option<CustomerDetailsResponse> =
customer.as_ref().map(ForeignInto::foreign_into);
// If we have customer data in Payment Intent, We are populating the Retrieve response from the
// same
// If we have customer data in Payment Intent and if the customer is not deleted, We are populating the Retrieve response from the
// same. If the customer is deleted then we use the customer table to populate customer details
let customer_details_response =
if let Some(customer_details_raw) = payment_intent.customer_details.clone() {
let customer_details_encrypted =
serde_json::from_value::<CustomerData>(customer_details_raw.into_inner().expose());
if let Ok(customer_details_encrypted_data) = customer_details_encrypted {
Some(CustomerDetailsResponse {
id: customer_table_response.and_then(|customer_data| customer_data.id),
name: customer_details_encrypted_data
.name
.or(customer.as_ref().and_then(|customer| {
customer.name.as_ref().map(|name| name.clone().into_inner())
})),
email: customer_details_encrypted_data.email.or(customer
id: customer_table_response
.as_ref()
.and_then(|customer| customer.email.clone().map(Email::from))),
phone: customer_details_encrypted_data
.phone
.or(customer.as_ref().and_then(|customer| {
customer
.phone
.as_ref()
.map(|phone| phone.clone().into_inner())
})),
phone_country_code: customer_details_encrypted_data.phone_country_code.or(
customer
.and_then(|customer_data| customer_data.id.clone()),
name: customer_table_response
.as_ref()
.and_then(|customer_data| customer_data.name.clone())
.or(customer_details_encrypted_data
.name
.or(customer.as_ref().and_then(|customer| {
customer.name.as_ref().map(|name| name.clone().into_inner())
}))),
email: customer_table_response
.as_ref()
.and_then(|customer_data| customer_data.email.clone())
.or(customer_details_encrypted_data.email.or(customer
.as_ref()
.and_then(|customer| customer.phone_country_code.clone()),
),
.and_then(|customer| customer.email.clone().map(Email::from)))),
phone: customer_table_response
.as_ref()
.and_then(|customer_data| customer_data.phone.clone())
.or(customer_details_encrypted_data
.phone
.or(customer.as_ref().and_then(|customer| {
customer
.phone
.as_ref()
.map(|phone| phone.clone().into_inner())
}))),
phone_country_code: customer_table_response
.as_ref()
.and_then(|customer_data| customer_data.phone_country_code.clone())
.or(customer_details_encrypted_data
.phone_country_code
.or(customer
.as_ref()
.and_then(|customer| customer.phone_country_code.clone()))),
})
} else {
customer_table_response