Skip to content

Commit

Permalink
chore: making of function create_encrypted_data (#5251)
Browse files Browse the repository at this point in the history
Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
  • Loading branch information
prajjwalkumar17 and hyperswitch-bot[bot] authored Jul 12, 2024
1 parent bf4ec90 commit 6ee1cad
Show file tree
Hide file tree
Showing 8 changed files with 182 additions and 127 deletions.
126 changes: 77 additions & 49 deletions crates/router/src/core/payment_methods/cards.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand All @@ -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},
},
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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();
Expand All @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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?;
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
.await
.map(|details| details.into());
let pm_data_encrypted: Option<Encryptable<Secret<serde_json::Value>>> =
updated_pmd
.async_map(|updated_pmd| create_encrypted_data(key_store, updated_pmd))
.await
.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(
Expand Down Expand Up @@ -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?;

Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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(
Expand Down
7 changes: 5 additions & 2 deletions crates/router/src/core/payments/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
16 changes: 12 additions & 4 deletions crates/router/src/core/payments/operations/payment_confirm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
38 changes: 21 additions & 17 deletions crates/router/src/core/payments/operations/payment_create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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()
Expand All @@ -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(),
Expand Down
Loading

0 comments on commit 6ee1cad

Please sign in to comment.