mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-11-02 04:04:43 +08:00
feat(core): customer_details storage in payment_intent (#5007)
Co-authored-by: Narayan Bhat <narayan.bhat@juspay.in> Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
This commit is contained in:
@ -22,6 +22,7 @@ use api_models::{
|
||||
use common_enums::enums::MerchantStorageScheme;
|
||||
use common_utils::{
|
||||
consts,
|
||||
crypto::Encryptable,
|
||||
ext_traits::{AsyncExt, Encode, StringExt, ValueExt},
|
||||
generate_id, id_type,
|
||||
types::MinorUnit,
|
||||
@ -66,7 +67,7 @@ use crate::{
|
||||
types::{decrypt, encrypt_optional, AsyncLift},
|
||||
},
|
||||
storage::{self, enums, PaymentMethodListContext, PaymentTokenData},
|
||||
transformers::ForeignFrom,
|
||||
transformers::{ForeignFrom, ForeignTryFrom},
|
||||
},
|
||||
utils::{self, ConnectorResponseExt, OptionExt},
|
||||
};
|
||||
@ -467,8 +468,9 @@ pub async fn add_payment_method_data(
|
||||
};
|
||||
|
||||
let updated_pmd = Some(PaymentMethodsData::Card(updated_card));
|
||||
let pm_data_encrypted =
|
||||
create_encrypted_data(&key_store, updated_pmd).await;
|
||||
let pm_data_encrypted = create_encrypted_data(&key_store, updated_pmd)
|
||||
.await
|
||||
.map(|details| details.into());
|
||||
|
||||
let pm_update = storage::PaymentMethodUpdate::AdditionalDataUpdate {
|
||||
payment_method_data: pm_data_encrypted,
|
||||
@ -689,7 +691,9 @@ pub async fn add_payment_method(
|
||||
let updated_pmd = updated_card.as_ref().map(|card| {
|
||||
PaymentMethodsData::Card(CardDetailsPaymentMethod::from(card.clone()))
|
||||
});
|
||||
let pm_data_encrypted = create_encrypted_data(key_store, updated_pmd).await;
|
||||
let pm_data_encrypted = create_encrypted_data(key_store, updated_pmd)
|
||||
.await
|
||||
.map(|details| details.into());
|
||||
|
||||
let pm_update = storage::PaymentMethodUpdate::PaymentMethodDataUpdate {
|
||||
payment_method_data: pm_data_encrypted,
|
||||
@ -763,7 +767,10 @@ pub async fn insert_payment_method(
|
||||
.card
|
||||
.as_ref()
|
||||
.map(|card| PaymentMethodsData::Card(CardDetailsPaymentMethod::from(card.clone())));
|
||||
let pm_data_encrypted = create_encrypted_data(key_store, pm_card_details).await;
|
||||
let pm_data_encrypted = create_encrypted_data(key_store, pm_card_details)
|
||||
.await
|
||||
.map(|details| details.into());
|
||||
|
||||
create_payment_method(
|
||||
db,
|
||||
&req,
|
||||
@ -943,7 +950,9 @@ pub async fn update_customer_payment_method(
|
||||
let updated_pmd = updated_card
|
||||
.as_ref()
|
||||
.map(|card| PaymentMethodsData::Card(CardDetailsPaymentMethod::from(card.clone())));
|
||||
let pm_data_encrypted = create_encrypted_data(&key_store, updated_pmd).await;
|
||||
let pm_data_encrypted = create_encrypted_data(&key_store, updated_pmd)
|
||||
.await
|
||||
.map(|details| details.into());
|
||||
|
||||
let pm_update = storage::PaymentMethodUpdate::PaymentMethodDataUpdate {
|
||||
payment_method_data: pm_data_encrypted,
|
||||
@ -2227,12 +2236,13 @@ pub async fn list_payment_methods(
|
||||
.then_some(billing_address.as_ref())
|
||||
.flatten();
|
||||
|
||||
let req = api_models::payments::PaymentsRequest::foreign_from((
|
||||
let req = api_models::payments::PaymentsRequest::foreign_try_from((
|
||||
payment_attempt.as_ref(),
|
||||
payment_intent.as_ref(),
|
||||
shipping_address.as_ref(),
|
||||
billing_address_for_calculating_required_fields,
|
||||
customer.as_ref(),
|
||||
));
|
||||
))?;
|
||||
let req_val = serde_json::to_value(req).ok();
|
||||
logger::debug!(filtered_payment_methods=?response);
|
||||
|
||||
@ -4358,14 +4368,13 @@ pub async fn delete_payment_method(
|
||||
pub async fn create_encrypted_data<T>(
|
||||
key_store: &domain::MerchantKeyStore,
|
||||
data: Option<T>,
|
||||
) -> Option<Encryption>
|
||||
) -> Option<Encryptable<Secret<serde_json::Value>>>
|
||||
where
|
||||
T: Debug + serde::Serialize,
|
||||
{
|
||||
let key = key_store.key.get_inner().peek();
|
||||
|
||||
let encrypted_data: Option<Encryption> = data
|
||||
.as_ref()
|
||||
data.as_ref()
|
||||
.map(Encode::encode_to_value)
|
||||
.transpose()
|
||||
.change_context(errors::StorageError::SerializationFailed)
|
||||
@ -4383,9 +4392,6 @@ where
|
||||
logger::error!(err=?err);
|
||||
None
|
||||
})
|
||||
.map(|details| details.into());
|
||||
|
||||
encrypted_data
|
||||
}
|
||||
|
||||
pub async fn list_countries_currencies_for_connector_payment_method(
|
||||
|
||||
@ -18,7 +18,7 @@ use error_stack::{report, ResultExt};
|
||||
use futures::future::Either;
|
||||
use hyperswitch_domain_models::{
|
||||
mandates::MandateData,
|
||||
payments::{payment_attempt::PaymentAttempt, PaymentIntent},
|
||||
payments::{payment_attempt::PaymentAttempt, payment_intent::CustomerData, PaymentIntent},
|
||||
router_data::KlarnaSdkResponse,
|
||||
};
|
||||
use josekit::jwe;
|
||||
@ -44,7 +44,11 @@ use crate::{
|
||||
authentication,
|
||||
errors::{self, CustomResult, RouterResult, StorageErrorExt},
|
||||
mandate::helpers::MandateGenericData,
|
||||
payment_methods::{self, cards, vault},
|
||||
payment_methods::{
|
||||
self,
|
||||
cards::{self, create_encrypted_data},
|
||||
vault,
|
||||
},
|
||||
payments,
|
||||
pm_auth::retrieve_payment_method_from_auth_service,
|
||||
},
|
||||
@ -1580,6 +1584,61 @@ pub async fn create_customer_if_not_exist<'a, F: Clone, R>(
|
||||
.get_required_value("customer")
|
||||
.change_context(errors::StorageError::ValueNotFound("customer".to_owned()))?;
|
||||
|
||||
let temp_customer_data = if request_customer_details.name.is_some()
|
||||
|| request_customer_details.email.is_some()
|
||||
|| request_customer_details.phone.is_some()
|
||||
|| request_customer_details.phone_country_code.is_some()
|
||||
{
|
||||
Some(CustomerData {
|
||||
name: request_customer_details.name.clone(),
|
||||
email: request_customer_details.email.clone(),
|
||||
phone: request_customer_details.phone.clone(),
|
||||
phone_country_code: request_customer_details.phone_country_code.clone(),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// Updation of Customer Details for the cases where both customer_id and specific customer
|
||||
// details are provided in Payment Update Request
|
||||
let raw_customer_details = payment_data
|
||||
.payment_intent
|
||||
.customer_details
|
||||
.clone()
|
||||
.map(|customer_details_encrypted| {
|
||||
customer_details_encrypted
|
||||
.into_inner()
|
||||
.expose()
|
||||
.parse_value::<CustomerData>("CustomerData")
|
||||
})
|
||||
.transpose()
|
||||
.change_context(errors::StorageError::DeserializationFailed)
|
||||
.attach_printable("Failed to parse customer data from payment intent")?
|
||||
.map(|parsed_customer_data| CustomerData {
|
||||
name: request_customer_details
|
||||
.name
|
||||
.clone()
|
||||
.or(parsed_customer_data.name.clone()),
|
||||
email: request_customer_details
|
||||
.email
|
||||
.clone()
|
||||
.or(parsed_customer_data.email.clone()),
|
||||
phone: request_customer_details
|
||||
.phone
|
||||
.clone()
|
||||
.or(parsed_customer_data.phone.clone()),
|
||||
phone_country_code: request_customer_details
|
||||
.phone_country_code
|
||||
.clone()
|
||||
.or(parsed_customer_data.phone_country_code.clone()),
|
||||
})
|
||||
.or(temp_customer_data);
|
||||
|
||||
payment_data.payment_intent.customer_details = raw_customer_details
|
||||
.clone()
|
||||
.async_and_then(|_| async { create_encrypted_data(key_store, raw_customer_details).await })
|
||||
.await;
|
||||
|
||||
let customer_id = request_customer_details
|
||||
.customer_id
|
||||
.or(payment_data.payment_intent.customer_id.clone());
|
||||
@ -3062,6 +3121,7 @@ mod tests {
|
||||
request_external_three_ds_authentication: None,
|
||||
charges: None,
|
||||
frm_metadata: None,
|
||||
customer_details: None,
|
||||
};
|
||||
let req_cs = Some("1".to_string());
|
||||
assert!(authenticate_client_secret(req_cs.as_ref(), &payment_intent).is_ok());
|
||||
@ -3121,6 +3181,7 @@ mod tests {
|
||||
request_external_three_ds_authentication: None,
|
||||
charges: None,
|
||||
frm_metadata: None,
|
||||
customer_details: None,
|
||||
};
|
||||
let req_cs = Some("1".to_string());
|
||||
assert!(authenticate_client_secret(req_cs.as_ref(), &payment_intent,).is_err())
|
||||
@ -3179,6 +3240,7 @@ mod tests {
|
||||
request_external_three_ds_authentication: None,
|
||||
charges: None,
|
||||
frm_metadata: None,
|
||||
customer_details: None,
|
||||
};
|
||||
let req_cs = Some("1".to_string());
|
||||
assert!(authenticate_client_secret(req_cs.as_ref(), &payment_intent).is_err())
|
||||
|
||||
@ -1084,6 +1084,7 @@ impl<F: Clone> UpdateTracker<F, PaymentData<F>, api::PaymentsRequest> for Paymen
|
||||
None
|
||||
};
|
||||
|
||||
let customer_details = payment_data.payment_intent.customer_details.clone();
|
||||
let business_sub_label = payment_data.payment_attempt.business_sub_label.clone();
|
||||
let authentication_type = payment_data.payment_attempt.authentication_type;
|
||||
|
||||
@ -1255,6 +1256,7 @@ impl<F: Clone> UpdateTracker<F, PaymentData<F>, api::PaymentsRequest> for Paymen
|
||||
session_expiry,
|
||||
request_external_three_ds_authentication: None,
|
||||
frm_metadata: m_frm_metadata,
|
||||
customer_details,
|
||||
},
|
||||
&m_key_store,
|
||||
storage_scheme,
|
||||
|
||||
@ -12,7 +12,8 @@ use diesel_models::{ephemeral_key, PaymentMethod};
|
||||
use error_stack::{self, ResultExt};
|
||||
use hyperswitch_domain_models::{
|
||||
mandates::{MandateData, MandateDetails},
|
||||
payments::payment_attempt::PaymentAttempt,
|
||||
payments::{payment_attempt::PaymentAttempt, payment_intent::CustomerData},
|
||||
type_encryption::decrypt,
|
||||
};
|
||||
use masking::{ExposeInterface, PeekInterface, Secret};
|
||||
use router_derive::PaymentOperation;
|
||||
@ -26,6 +27,7 @@ use crate::{
|
||||
errors::{self, CustomResult, RouterResult, StorageErrorExt},
|
||||
mandate::helpers as m_helpers,
|
||||
payment_link,
|
||||
payment_methods::cards::create_encrypted_data,
|
||||
payments::{self, helpers, operations, CustomerDetails, PaymentAddress, PaymentData},
|
||||
utils as core_utils,
|
||||
},
|
||||
@ -245,8 +247,10 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for Pa
|
||||
};
|
||||
|
||||
let payment_intent_new = Self::make_payment_intent(
|
||||
state,
|
||||
&payment_id,
|
||||
merchant_account,
|
||||
merchant_key_store,
|
||||
money,
|
||||
request,
|
||||
shipping_address
|
||||
@ -560,7 +564,7 @@ impl<F: Clone> UpdateTracker<F, PaymentData<F>, api::PaymentsRequest> for Paymen
|
||||
state: &'b SessionState,
|
||||
_req_state: ReqState,
|
||||
mut payment_data: PaymentData<F>,
|
||||
_customer: Option<domain::Customer>,
|
||||
customer: Option<domain::Customer>,
|
||||
storage_scheme: enums::MerchantStorageScheme,
|
||||
_updated_customer: Option<storage::CustomerUpdate>,
|
||||
key_store: &domain::MerchantKeyStore,
|
||||
@ -628,16 +632,30 @@ impl<F: Clone> UpdateTracker<F, PaymentData<F>, api::PaymentsRequest> for Paymen
|
||||
|
||||
let customer_id = payment_data.payment_intent.customer_id.clone();
|
||||
|
||||
let raw_customer_details = customer
|
||||
.map(|customer| CustomerData::try_from(customer.clone()))
|
||||
.transpose()?;
|
||||
|
||||
// Updation of Customer Details for the cases where both customer_id and specific customer
|
||||
// details are provided in Payment Create Request
|
||||
let customer_details = raw_customer_details
|
||||
.clone()
|
||||
.async_and_then(|_| async {
|
||||
create_encrypted_data(key_store, raw_customer_details).await
|
||||
})
|
||||
.await;
|
||||
|
||||
payment_data.payment_intent = state
|
||||
.store
|
||||
.update_payment_intent(
|
||||
payment_data.payment_intent,
|
||||
storage::PaymentIntentUpdate::ReturnUrlUpdate {
|
||||
storage::PaymentIntentUpdate::PaymentCreateUpdate {
|
||||
return_url: None,
|
||||
status,
|
||||
customer_id,
|
||||
shipping_address_id: None,
|
||||
billing_address_id: None,
|
||||
customer_details,
|
||||
updated_by: storage_scheme.to_string(),
|
||||
},
|
||||
key_store,
|
||||
@ -815,7 +833,7 @@ impl PaymentCreate {
|
||||
additional_pm_data = payment_method_info
|
||||
.as_ref()
|
||||
.async_map(|pm_info| async {
|
||||
domain::types::decrypt::<serde_json::Value, masking::WithType>(
|
||||
decrypt::<serde_json::Value, masking::WithType>(
|
||||
pm_info.payment_method_data.clone(),
|
||||
key_store.key.get_inner().peek(),
|
||||
)
|
||||
@ -956,8 +974,10 @@ impl PaymentCreate {
|
||||
#[instrument(skip_all)]
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
async fn make_payment_intent(
|
||||
_state: &SessionState,
|
||||
payment_id: &str,
|
||||
merchant_account: &domain::MerchantAccount,
|
||||
key_store: &domain::MerchantKeyStore,
|
||||
money: (api::Amount, enums::Currency),
|
||||
request: &api::PaymentsRequest,
|
||||
shipping_address_id: Option<String>,
|
||||
@ -1023,6 +1043,30 @@ impl PaymentCreate {
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)?
|
||||
.map(Secret::new);
|
||||
|
||||
// Derivation of directly supplied Customer data in our Payment Create Request
|
||||
let raw_customer_details = if request.customer_id.is_none()
|
||||
&& (request.name.is_some()
|
||||
|| request.email.is_some()
|
||||
|| request.phone.is_some()
|
||||
|| request.phone_country_code.is_some())
|
||||
{
|
||||
Some(CustomerData {
|
||||
name: request.name.clone(),
|
||||
phone: request.phone.clone(),
|
||||
email: request.email.clone(),
|
||||
phone_country_code: request.phone_country_code.clone(),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// Encrypting our Customer Details to be stored in Payment Intent
|
||||
let customer_details = if raw_customer_details.is_some() {
|
||||
create_encrypted_data(key_store, raw_customer_details).await
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Ok(storage::PaymentIntent {
|
||||
payment_id: payment_id.to_string(),
|
||||
merchant_id: merchant_account.merchant_id.to_string(),
|
||||
@ -1070,6 +1114,7 @@ impl PaymentCreate {
|
||||
.request_external_three_ds_authentication,
|
||||
charges,
|
||||
frm_metadata: request.frm_metadata.clone(),
|
||||
customer_details,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -4,8 +4,12 @@ use api_models::{
|
||||
enums::FrmSuggestion, mandates::RecurringDetails, payments::RequestSurchargeDetails,
|
||||
};
|
||||
use async_trait::async_trait;
|
||||
use common_utils::ext_traits::{AsyncExt, Encode, ValueExt};
|
||||
use common_utils::{
|
||||
ext_traits::{AsyncExt, Encode, ValueExt},
|
||||
pii::Email,
|
||||
};
|
||||
use error_stack::{report, ResultExt};
|
||||
use hyperswitch_domain_models::payments::payment_intent::CustomerData;
|
||||
use router_derive::PaymentOperation;
|
||||
use router_env::{instrument, tracing};
|
||||
|
||||
@ -661,7 +665,7 @@ impl<F: Clone> UpdateTracker<F, PaymentData<F>, api::PaymentsRequest> for Paymen
|
||||
.await
|
||||
.to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?;
|
||||
|
||||
let customer_id = customer.map(|c| c.customer_id);
|
||||
let customer_id = customer.clone().map(|c| c.customer_id);
|
||||
|
||||
let intent_status = {
|
||||
let current_intent_status = payment_data.payment_intent.status;
|
||||
@ -681,6 +685,8 @@ impl<F: Clone> UpdateTracker<F, PaymentData<F>, api::PaymentsRequest> for Paymen
|
||||
payment_data.payment_intent.billing_address_id.clone(),
|
||||
);
|
||||
|
||||
let customer_details = payment_data.payment_intent.customer_details.clone();
|
||||
|
||||
let return_url = payment_data.payment_intent.return_url.clone();
|
||||
let setup_future_usage = payment_data.payment_intent.setup_future_usage;
|
||||
let business_label = payment_data.payment_intent.business_label.clone();
|
||||
@ -726,6 +732,7 @@ impl<F: Clone> UpdateTracker<F, PaymentData<F>, api::PaymentsRequest> for Paymen
|
||||
.payment_intent
|
||||
.request_external_three_ds_authentication,
|
||||
frm_metadata,
|
||||
customer_details,
|
||||
},
|
||||
key_store,
|
||||
storage_scheme,
|
||||
@ -740,6 +747,18 @@ impl<F: Clone> UpdateTracker<F, PaymentData<F>, api::PaymentsRequest> for Paymen
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<domain::Customer> for CustomerData {
|
||||
type Error = errors::ApiErrorResponse;
|
||||
fn try_from(value: domain::Customer) -> Result<Self, Self::Error> {
|
||||
Ok(Self {
|
||||
name: value.name.map(|name| name.into_inner()),
|
||||
email: value.email.map(Email::from),
|
||||
phone: value.phone.map(|ph| ph.into_inner()),
|
||||
phone_country_code: value.phone_country_code,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: Send + Clone> ValidateRequest<F, api::PaymentsRequest> for PaymentUpdate {
|
||||
#[instrument(skip_all)]
|
||||
fn validate_request<'a, 'b>(
|
||||
|
||||
@ -210,14 +210,17 @@ where
|
||||
});
|
||||
|
||||
let pm_data_encrypted =
|
||||
payment_methods::cards::create_encrypted_data(key_store, pm_card_details).await;
|
||||
payment_methods::cards::create_encrypted_data(key_store, pm_card_details)
|
||||
.await
|
||||
.map(|details| details.into());
|
||||
|
||||
let encrypted_payment_method_billing_address =
|
||||
payment_methods::cards::create_encrypted_data(
|
||||
key_store,
|
||||
payment_method_billing_address,
|
||||
)
|
||||
.await;
|
||||
.await
|
||||
.map(|details| details.into());
|
||||
|
||||
let mut payment_method_id = resp.payment_method_id.clone();
|
||||
let mut locker_id = None;
|
||||
@ -509,7 +512,8 @@ where
|
||||
key_store,
|
||||
updated_pmd,
|
||||
)
|
||||
.await;
|
||||
.await
|
||||
.map(|details| details.into());
|
||||
|
||||
let pm_update =
|
||||
storage::PaymentMethodUpdate::PaymentMethodDataUpdate {
|
||||
|
||||
@ -1,16 +1,17 @@
|
||||
use std::{fmt::Debug, marker::PhantomData, str::FromStr};
|
||||
|
||||
use api_models::payments::{
|
||||
FrmMessage, GetAddressFromPaymentMethodData, PaymentChargeRequest, PaymentChargeResponse,
|
||||
RequestSurchargeDetails,
|
||||
CustomerDetailsResponse, FrmMessage, GetAddressFromPaymentMethodData, PaymentChargeRequest,
|
||||
PaymentChargeResponse, RequestSurchargeDetails,
|
||||
};
|
||||
#[cfg(feature = "payouts")]
|
||||
use api_models::payouts::PayoutAttemptResponse;
|
||||
use common_enums::RequestIncrementalAuthorization;
|
||||
use common_utils::{consts::X_HS_LATENCY, fp_utils, types::MinorUnit};
|
||||
use common_utils::{consts::X_HS_LATENCY, fp_utils, pii::Email, types::MinorUnit};
|
||||
use diesel_models::ephemeral_key;
|
||||
use error_stack::{report, ResultExt};
|
||||
use masking::{Maskable, PeekInterface, Secret};
|
||||
use hyperswitch_domain_models::payments::payment_intent::CustomerData;
|
||||
use masking::{ExposeInterface, Maskable, PeekInterface, Secret};
|
||||
use router_env::{instrument, metrics::add_attributes, tracing};
|
||||
|
||||
use super::{flows::Feature, types::AuthenticationData, PaymentData};
|
||||
@ -506,7 +507,47 @@ where
|
||||
))
|
||||
}
|
||||
|
||||
let customer_details_response = customer.as_ref().map(ForeignInto::foreign_into);
|
||||
// For the case when we don't have Customer data directly stored in Payment intent
|
||||
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
|
||||
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
|
||||
.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
|
||||
.as_ref()
|
||||
.and_then(|customer| customer.phone_country_code.clone()),
|
||||
),
|
||||
})
|
||||
} else {
|
||||
customer_table_response
|
||||
}
|
||||
} else {
|
||||
customer_table_response
|
||||
};
|
||||
|
||||
headers.extend(
|
||||
external_latency
|
||||
|
||||
@ -449,7 +449,9 @@ pub async fn save_payout_data_to_locker(
|
||||
)
|
||||
});
|
||||
(
|
||||
cards::create_encrypted_data(key_store, Some(pm_data)).await,
|
||||
cards::create_encrypted_data(key_store, Some(pm_data))
|
||||
.await
|
||||
.map(|details| details.into()),
|
||||
payment_method,
|
||||
)
|
||||
} else {
|
||||
|
||||
@ -421,6 +421,7 @@ async fn store_bank_details_in_payment_methods(
|
||||
let encrypted_data =
|
||||
cards::create_encrypted_data(&key_store, Some(payment_method_data))
|
||||
.await
|
||||
.map(|details| details.into())
|
||||
.ok_or(ApiErrorResponse::InternalServerError)?;
|
||||
let pm_update = storage::PaymentMethodUpdate::PaymentMethodDataUpdate {
|
||||
payment_method_data: Some(encrypted_data),
|
||||
@ -432,6 +433,7 @@ async fn store_bank_details_in_payment_methods(
|
||||
let encrypted_data =
|
||||
cards::create_encrypted_data(&key_store, Some(payment_method_data))
|
||||
.await
|
||||
.map(|details| details.into())
|
||||
.ok_or(ApiErrorResponse::InternalServerError)?;
|
||||
let pm_id = generate_id(consts::ID_LENGTH, "pm");
|
||||
let now = common_utils::date_time::now();
|
||||
|
||||
Reference in New Issue
Block a user