chore: making of function create_encrypted_data (#5251)

Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
This commit is contained in:
Prajjwal Kumar
2024-07-12 18:34:57 +05:30
committed by GitHub
parent bf4ec90d45
commit 6ee1cad469
8 changed files with 181 additions and 126 deletions

View File

@ -46,6 +46,8 @@ use super::surcharge_decision_configs::{
};
#[cfg(not(feature = "connector_choice_mca_id"))]
use crate::core::utils::get_connector_label;
#[cfg(feature = "payouts")]
use crate::types::domain::types::AsyncLift;
use crate::{
configs::settings,
core::{
@ -67,10 +69,7 @@ use crate::{
services,
types::{
api::{self, routing as routing_types, PaymentMethodCreateExt},
domain::{
self,
types::{decrypt, encrypt_optional, AsyncLift},
},
domain::{self, types::decrypt},
storage::{self, enums, PaymentMethodListContext, PaymentTokenData},
transformers::{ForeignFrom, ForeignTryFrom},
},
@ -351,9 +350,14 @@ pub async fn skip_locker_call_and_migrate_payment_method(
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Failed to parse connector mandate details")?;
let payment_method_billing_address = create_encrypted_data(key_store, req.billing.clone())
let payment_method_billing_address: Option<Encryptable<Secret<serde_json::Value>>> = req
.billing
.clone()
.async_map(|billing| create_encrypted_data(key_store, billing))
.await
.map(|details| details.into());
.transpose()
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Unable to encrypt Payment method billing address")?;
let customer = db
.find_customer_by_customer_id_merchant_id(
@ -484,10 +488,13 @@ pub async fn skip_locker_call_and_migrate_payment_method(
.as_ref()
.map(|card| PaymentMethodsData::Card(CardDetailsPaymentMethod::from(card.clone())));
let payment_method_data_encrypted =
create_encrypted_data(key_store, payment_method_card_details)
let payment_method_data_encrypted: Option<Encryptable<Secret<serde_json::Value>>> =
payment_method_card_details
.async_map(|card_details| create_encrypted_data(key_store, card_details))
.await
.map(|details| details.into());
.transpose()
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Unable to encrypt Payment method card details")?;
let payment_method_metadata: Option<serde_json::Value> =
req.metadata.as_ref().map(|data| data.peek()).cloned();
@ -508,7 +515,7 @@ pub async fn skip_locker_call_and_migrate_payment_method(
payment_method_issuer: req.payment_method_issuer.clone(),
scheme: req.card_network.clone(),
metadata: payment_method_metadata.map(Secret::new),
payment_method_data: payment_method_data_encrypted,
payment_method_data: payment_method_data_encrypted.map(Into::into),
connector_mandate_details: Some(connector_mandate_details),
customer_acceptance: None,
client_secret: None,
@ -527,7 +534,7 @@ pub async fn skip_locker_call_and_migrate_payment_method(
created_at: current_time,
last_modified: current_time,
last_used_at: current_time,
payment_method_billing_address,
payment_method_billing_address: payment_method_billing_address.map(Into::into),
updated_by: None,
},
merchant_account.storage_scheme,
@ -591,9 +598,14 @@ pub async fn get_client_secret_or_add_payment_method(
#[cfg(feature = "payouts")]
let condition = req.card.is_some() || req.bank_transfer.is_some() || req.wallet.is_some();
let payment_method_billing_address = create_encrypted_data(key_store, req.billing.clone())
let payment_method_billing_address: Option<Encryptable<Secret<serde_json::Value>>> = req
.billing
.clone()
.async_map(|billing| create_encrypted_data(key_store, billing))
.await
.map(|details| details.into());
.transpose()
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Unable to encrypt Payment method billing address")?;
let connector_mandate_details = req
.connector_mandate_details
@ -622,7 +634,7 @@ pub async fn get_client_secret_or_add_payment_method(
Some(enums::PaymentMethodStatus::AwaitingData),
None,
merchant_account.storage_scheme,
payment_method_billing_address,
payment_method_billing_address.map(Into::into),
None,
)
.await?;
@ -793,13 +805,17 @@ pub async fn add_payment_method_data(
saved_to_locker: true,
};
let updated_pmd = Some(PaymentMethodsData::Card(updated_card));
let pm_data_encrypted = create_encrypted_data(&key_store, updated_pmd)
let pm_data_encrypted: Encryptable<Secret<serde_json::Value>> =
create_encrypted_data(
&key_store,
PaymentMethodsData::Card(updated_card),
)
.await
.map(|details| details.into());
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Unable to encrypt payment method data")?;
let pm_update = storage::PaymentMethodUpdate::AdditionalDataUpdate {
payment_method_data: pm_data_encrypted,
payment_method_data: Some(pm_data_encrypted.into()),
status: Some(enums::PaymentMethodStatus::Active),
locker_id: Some(locker_id),
payment_method: req.payment_method,
@ -870,9 +886,14 @@ pub async fn add_payment_method(
let merchant_id = &merchant_account.merchant_id;
let customer_id = req.customer_id.clone().get_required_value("customer_id")?;
let payment_method = req.payment_method.get_required_value("payment_method")?;
let payment_method_billing_address = create_encrypted_data(key_store, req.billing.clone())
let payment_method_billing_address: Option<Encryptable<Secret<serde_json::Value>>> = req
.billing
.clone()
.async_map(|billing| create_encrypted_data(key_store, billing))
.await
.map(|details| details.into());
.transpose()
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Unable to encrypt Payment method billing address")?;
let connector_mandate_details = req
.connector_mandate_details
@ -1041,12 +1062,16 @@ 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)
let pm_data_encrypted: Option<Encryptable<Secret<serde_json::Value>>> =
updated_pmd
.async_map(|updated_pmd| create_encrypted_data(key_store, updated_pmd))
.await
.map(|details| details.into());
.transpose()
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Unable to encrypt payment method data")?;
let pm_update = storage::PaymentMethodUpdate::PaymentMethodDataUpdate {
payment_method_data: pm_data_encrypted,
payment_method_data: pm_data_encrypted.map(Into::into),
};
db.update_payment_method(
@ -1086,7 +1111,7 @@ pub async fn add_payment_method(
connector_mandate_details,
req.network_transaction_id.clone(),
merchant_account.storage_scheme,
payment_method_billing_address,
payment_method_billing_address.map(Into::into),
)
.await?;
@ -1117,9 +1142,14 @@ pub async fn insert_payment_method(
.card
.clone()
.map(|card| PaymentMethodsData::Card(CardDetailsPaymentMethod::from(card.clone())));
let pm_data_encrypted = create_encrypted_data(key_store, pm_card_details)
let pm_data_encrypted: Option<Encryptable<Secret<serde_json::Value>>> = pm_card_details
.clone()
.async_map(|pm_card| create_encrypted_data(key_store, pm_card))
.await
.map(|details| details.into());
.transpose()
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Unable to encrypt payment method data")?;
create_payment_method(
db,
@ -1130,7 +1160,7 @@ pub async fn insert_payment_method(
merchant_id,
pm_metadata,
customer_acceptance,
pm_data_encrypted,
pm_data_encrypted.map(Into::into),
key_store,
connector_mandate_details,
None,
@ -1307,12 +1337,16 @@ 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)
let pm_data_encrypted: Option<Encryptable<Secret<serde_json::Value>>> = updated_pmd
.async_map(|updated_pmd| create_encrypted_data(&key_store, updated_pmd))
.await
.map(|details| details.into());
.transpose()
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Unable to encrypt payment method data")?;
let pm_update = storage::PaymentMethodUpdate::PaymentMethodDataUpdate {
payment_method_data: pm_data_encrypted,
payment_method_data: pm_data_encrypted.map(Into::into),
};
add_card_resp
@ -1436,7 +1470,7 @@ pub async fn add_bank_to_locker(
let secret: Secret<String> = Secret::new(v.to_string());
secret
})
.async_lift(|inner| encrypt_optional(inner, key))
.async_lift(|inner| domain::types::encrypt_optional(inner, key))
.await
}
.await
@ -4563,31 +4597,25 @@ pub async fn delete_payment_method(
pub async fn create_encrypted_data<T>(
key_store: &domain::MerchantKeyStore,
data: Option<T>,
) -> Option<Encryptable<Secret<serde_json::Value>>>
data: T,
) -> Result<Encryptable<Secret<serde_json::Value>>, error_stack::Report<errors::StorageError>>
where
T: Debug + serde::Serialize,
{
let key = key_store.key.get_inner().peek();
data.as_ref()
.map(Encode::encode_to_value)
.transpose()
let encoded_data = Encode::encode_to_value(&data)
.change_context(errors::StorageError::SerializationFailed)
.attach_printable("Unable to convert data to a value")
.unwrap_or_else(|error| {
logger::error!(?error);
None
})
.map(Secret::<_, masking::WithType>::new)
.async_lift(|inner| encrypt_optional(inner, key))
.attach_printable("Unable to encode data")?;
let secret_data = Secret::<_, masking::WithType>::new(encoded_data);
let encrypted_data = domain::types::encrypt(secret_data, key)
.await
.change_context(errors::StorageError::EncryptionError)
.attach_printable("Unable to encrypt data")
.unwrap_or_else(|error| {
logger::error!(?error);
None
})
.attach_printable("Unable to encrypt data")?;
Ok(encrypted_data)
}
pub async fn list_countries_currencies_for_connector_payment_method(

View File

@ -1612,8 +1612,11 @@ pub async fn create_customer_if_not_exist<'a, F: Clone, R>(
payment_data.payment_intent.customer_details = raw_customer_details
.clone()
.async_and_then(|_| async { create_encrypted_data(key_store, raw_customer_details).await })
.await;
.async_map(|customer_details| create_encrypted_data(key_store, customer_details))
.await
.transpose()
.change_context(errors::StorageError::EncryptionError)
.attach_printable("Unable to encrypt customer details")?;
let customer_id = request_customer_details
.customer_id

View File

@ -1222,12 +1222,20 @@ impl<F: Clone> UpdateTracker<F, PaymentData<F>, api::PaymentsRequest> for Paymen
let billing_address = payment_data.address.get_payment_billing();
let billing_details = billing_address
.async_and_then(|_| async { create_encrypted_data(key_store, billing_address).await })
.await;
.async_map(|billing_details| create_encrypted_data(key_store, billing_details))
.await
.transpose()
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Unable to encrypt billing details")?;
let shipping_address = payment_data.address.get_shipping();
let shipping_details = shipping_address
.async_and_then(|_| async { create_encrypted_data(key_store, shipping_address).await })
.await;
.async_map(|shipping_details| create_encrypted_data(key_store, shipping_details))
.await
.transpose()
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Unable to encrypt shipping details")?;
let m_payment_data_payment_intent = payment_data.payment_intent.clone();
let m_customer_id = customer_id.clone();
let m_shipping_address_id = shipping_address_id.clone();

View File

@ -642,10 +642,11 @@ impl<F: Clone> UpdateTracker<F, PaymentData<F>, api::PaymentsRequest> for Paymen
// 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;
.async_map(|customer_details| create_encrypted_data(key_store, customer_details))
.await
.transpose()
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Unable to encrypt customer details")?;
payment_data.payment_intent = state
.store
@ -1047,20 +1048,22 @@ impl PaymentCreate {
let billing_details = request
.billing
.clone()
.async_and_then(|_| async {
create_encrypted_data(key_store, request.billing.clone()).await
})
.await;
.async_map(|billing_details| create_encrypted_data(key_store, billing_details))
.await
.transpose()
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Unable to encrypt billing details")?;
// Derivation of directly supplied Shipping Address data in our Payment Create Request
// Encrypting our Shipping Address Details to be stored in Payment Intent
let shipping_details = request
.shipping
.clone()
.async_and_then(|_| async {
create_encrypted_data(key_store, request.shipping.clone()).await
})
.await;
.async_map(|shipping_details| create_encrypted_data(key_store, shipping_details))
.await
.transpose()
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Unable to encrypt shipping details")?;
// Derivation of directly supplied Customer data in our Payment Create Request
let raw_customer_details = if request.get_customer_id().is_none()
@ -1080,11 +1083,12 @@ impl PaymentCreate {
};
// 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
};
let customer_details = raw_customer_details
.async_map(|customer_details| create_encrypted_data(key_store, customer_details))
.await
.transpose()
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Unable to encrypt customer details")?;
Ok(storage::PaymentIntent {
payment_id: payment_id.to_string(),

View File

@ -715,22 +715,21 @@ impl<F: Clone> UpdateTracker<F, PaymentData<F>, api::PaymentsRequest> for Paymen
let billing_details = payment_data
.address
.get_payment_billing()
.async_and_then(|_| async {
create_encrypted_data(
key_store,
payment_data.address.get_payment_billing().cloned(),
)
.async_map(|billing_details| create_encrypted_data(key_store, billing_details))
.await
})
.await;
.transpose()
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Unable to encrypt billing details")?;
let shipping_details = payment_data
.address
.get_shipping()
.async_and_then(|_| async {
create_encrypted_data(key_store, payment_data.address.get_shipping().cloned()).await
})
.await;
.async_map(|shipping_details| create_encrypted_data(key_store, shipping_details))
.await
.transpose()
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Unable to encrypt shipping details")?;
let order_details = payment_data.payment_intent.order_details.clone();
let metadata = payment_data.payment_intent.metadata.clone();
let frm_metadata = payment_data.payment_intent.frm_metadata.clone();

View File

@ -3,11 +3,12 @@ use std::collections::HashMap;
use api_models::payment_methods::PaymentMethodsData;
use common_enums::PaymentMethod;
use common_utils::{
ext_traits::{Encode, ValueExt},
crypto::Encryptable,
ext_traits::{AsyncExt, Encode, ValueExt},
id_type, pii,
};
use error_stack::{report, ResultExt};
use masking::{ExposeInterface, PeekInterface};
use masking::{ExposeInterface, PeekInterface, Secret};
use router_env::{instrument, metrics::add_attributes, tracing};
use super::helpers;
@ -15,7 +16,9 @@ use crate::{
consts,
core::{
errors::{self, ConnectorErrorExt, RouterResult, StorageErrorExt},
mandate, payment_methods, payments,
mandate,
payment_methods::{self, cards::create_encrypted_data},
payments,
},
logger,
routes::{metrics, SessionState},
@ -64,7 +67,7 @@ pub async fn save_payment_method<FData>(
key_store: &domain::MerchantKeyStore,
amount: Option<i64>,
currency: Option<storage_enums::Currency>,
billing_name: Option<masking::Secret<String>>,
billing_name: Option<Secret<String>>,
payment_method_billing_address: Option<&api::Address>,
business_profile: &storage::business_profile::BusinessProfile,
) -> RouterResult<(Option<String>, Option<common_enums::PaymentMethodStatus>)>
@ -209,18 +212,22 @@ where
PaymentMethodsData::Card(CardDetailsPaymentMethod::from(card.clone()))
});
let pm_data_encrypted =
payment_methods::cards::create_encrypted_data(key_store, pm_card_details)
let pm_data_encrypted: Option<Encryptable<Secret<serde_json::Value>>> =
pm_card_details
.async_map(|pm_card| create_encrypted_data(key_store, pm_card))
.await
.map(|details| details.into());
.transpose()
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Unable to encrypt payment method data")?;
let encrypted_payment_method_billing_address =
payment_methods::cards::create_encrypted_data(
key_store,
payment_method_billing_address,
)
let encrypted_payment_method_billing_address: Option<
Encryptable<Secret<serde_json::Value>>,
> = payment_method_billing_address
.async_map(|address| create_encrypted_data(key_store, address.clone()))
.await
.map(|details| details.into());
.transpose()
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Unable to encrypt payment method billing address")?;
let mut payment_method_id = resp.payment_method_id.clone();
let mut locker_id = None;
@ -311,13 +318,14 @@ where
merchant_id,
pm_metadata,
customer_acceptance,
pm_data_encrypted,
pm_data_encrypted.map(Into::into),
key_store,
connector_mandate_details,
None,
network_transaction_id,
merchant_account.storage_scheme,
encrypted_payment_method_billing_address,
encrypted_payment_method_billing_address
.map(Into::into),
resp.card.and_then(|card| {
card.card_network
.map(|card_network| card_network.to_string())
@ -411,7 +419,8 @@ where
connector_mandate_details,
network_transaction_id,
merchant_account.storage_scheme,
encrypted_payment_method_billing_address,
encrypted_payment_method_billing_address
.map(Into::into),
)
.await
} else {
@ -506,18 +515,19 @@ where
card.clone(),
))
});
let pm_data_encrypted =
payment_methods::cards::create_encrypted_data(
key_store,
updated_pmd,
)
let pm_data_encrypted: Option<
Encryptable<Secret<serde_json::Value>>,
> = updated_pmd
.async_map(|pmd| create_encrypted_data(key_store, pmd))
.await
.map(|details| details.into());
.transpose()
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Unable to encrypt payment method data")?;
payment_methods::cards::update_payment_method_and_last_used(
db,
existing_pm,
pm_data_encrypted,
pm_data_encrypted.map(Into::into),
merchant_account.storage_scheme,
)
.await
@ -599,13 +609,13 @@ where
merchant_id,
pm_metadata,
customer_acceptance,
pm_data_encrypted,
pm_data_encrypted.map(Into::into),
key_store,
connector_mandate_details,
None,
network_transaction_id,
merchant_account.storage_scheme,
encrypted_payment_method_billing_address,
encrypted_payment_method_billing_address.map(Into::into),
resp.card.and_then(|card| {
card.card_network
.map(|card_network| card_network.to_string())
@ -877,9 +887,9 @@ pub fn update_router_data_with_payment_method_token_result<F: Clone, T>(
match payment_method_token_result.payment_method_token_result {
Ok(pm_token_result) => {
router_data.payment_method_token = pm_token_result.map(|pm_token| {
hyperswitch_domain_models::router_data::PaymentMethodToken::Token(
masking::Secret::new(pm_token),
)
hyperswitch_domain_models::router_data::PaymentMethodToken::Token(Secret::new(
pm_token,
))
});
true

View File

@ -452,9 +452,12 @@ pub async fn save_payout_data_to_locker(
)
});
(
cards::create_encrypted_data(key_store, Some(pm_data))
Some(
cards::create_encrypted_data(key_store, pm_data)
.await
.map(|details| details.into()),
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Unable to encrypt customer details")?,
),
payment_method,
)
} else {
@ -494,7 +497,7 @@ pub async fn save_payout_data_to_locker(
&merchant_account.merchant_id,
None,
None,
card_details_encrypted.clone(),
card_details_encrypted.clone().map(Into::into),
key_store,
None,
None,
@ -557,7 +560,7 @@ pub async fn save_payout_data_to_locker(
// Update card's metadata in payment_methods table
let pm_update = storage::PaymentMethodUpdate::PaymentMethodDataUpdate {
payment_method_data: card_details_encrypted,
payment_method_data: card_details_encrypted.map(Into::into),
};
db.update_payment_method(existing_pm, pm_update, merchant_account.storage_scheme)
.await

View File

@ -432,13 +432,13 @@ async fn store_bank_details_in_payment_methods(
);
let payment_method_data = payment_methods::PaymentMethodsData::BankDetails(pmd);
let encrypted_data =
cards::create_encrypted_data(&key_store, Some(payment_method_data))
let encrypted_data = cards::create_encrypted_data(&key_store, payment_method_data)
.await
.map(|details| details.into())
.ok_or(ApiErrorResponse::InternalServerError)?;
.change_context(ApiErrorResponse::InternalServerError)
.attach_printable("Unable to encrypt customer details")?;
let pm_update = storage::PaymentMethodUpdate::PaymentMethodDataUpdate {
payment_method_data: Some(encrypted_data),
payment_method_data: Some(encrypted_data.into()),
};
update_entries.push((pm.clone(), pm_update));
@ -447,8 +447,8 @@ 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)?;
.change_context(ApiErrorResponse::InternalServerError)
.attach_printable("Unable to encrypt customer details")?;
let pm_id = generate_id(consts::ID_LENGTH, "pm");
let now = common_utils::date_time::now();
let pm_new = storage::PaymentMethodNew {
@ -461,7 +461,7 @@ async fn store_bank_details_in_payment_methods(
payment_method_issuer: None,
scheme: None,
metadata: None,
payment_method_data: Some(encrypted_data),
payment_method_data: Some(encrypted_data.into()),
payment_method_issuer_code: None,
accepted_currency: None,
token: None,