mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-11-01 11:06:50 +08:00
feat(core): use redis as temp locker instead of basilisk (#2789)
This commit is contained in:
committed by
GitHub
parent
9cc8b93070
commit
6678689265
@ -49,3 +49,6 @@ pub(crate) const MERCHANT_ID_FIELD_EXTENSION_ID: &str = "1.2.840.113635.100.6.32
|
||||
pub(crate) const METRICS_HOST_TAG_NAME: &str = "host";
|
||||
pub const MAX_ROUTING_CONFIGS_PER_MERCHANT: usize = 100;
|
||||
pub const ROUTING_CONFIG_ID_LENGTH: usize = 10;
|
||||
|
||||
pub const LOCKER_REDIS_PREFIX: &str = "LOCKER_PM_TOKEN";
|
||||
pub const LOCKER_REDIS_EXPIRY_SECONDS: u32 = 60 * 15; // 15 minutes
|
||||
|
||||
@ -13,7 +13,10 @@ use diesel_models::enums;
|
||||
use crate::{
|
||||
core::{errors::RouterResult, payments::helpers},
|
||||
routes::AppState,
|
||||
types::api::{self, payments},
|
||||
types::{
|
||||
api::{self, payments},
|
||||
domain,
|
||||
},
|
||||
};
|
||||
|
||||
pub struct Oss;
|
||||
@ -25,6 +28,7 @@ pub trait PaymentMethodRetrieve {
|
||||
state: &AppState,
|
||||
payment_intent: &PaymentIntent,
|
||||
payment_attempt: &PaymentAttempt,
|
||||
merchant_key_store: &domain::MerchantKeyStore,
|
||||
) -> RouterResult<(Option<payments::PaymentMethodData>, Option<String>)>;
|
||||
}
|
||||
|
||||
@ -35,6 +39,7 @@ impl PaymentMethodRetrieve for Oss {
|
||||
state: &AppState,
|
||||
payment_intent: &PaymentIntent,
|
||||
payment_attempt: &PaymentAttempt,
|
||||
merchant_key_store: &domain::MerchantKeyStore,
|
||||
) -> RouterResult<(Option<payments::PaymentMethodData>, Option<String>)> {
|
||||
match pm_data {
|
||||
pm_opt @ Some(pm @ api::PaymentMethodData::Card(_)) => {
|
||||
@ -44,6 +49,7 @@ impl PaymentMethodRetrieve for Oss {
|
||||
payment_intent,
|
||||
enums::PaymentMethod::Card,
|
||||
pm,
|
||||
merchant_key_store,
|
||||
)
|
||||
.await?;
|
||||
|
||||
@ -64,6 +70,7 @@ impl PaymentMethodRetrieve for Oss {
|
||||
payment_intent,
|
||||
enums::PaymentMethod::BankTransfer,
|
||||
pm,
|
||||
merchant_key_store,
|
||||
)
|
||||
.await?;
|
||||
|
||||
@ -76,6 +83,7 @@ impl PaymentMethodRetrieve for Oss {
|
||||
payment_intent,
|
||||
enums::PaymentMethod::Wallet,
|
||||
pm,
|
||||
merchant_key_store,
|
||||
)
|
||||
.await?;
|
||||
|
||||
@ -88,6 +96,7 @@ impl PaymentMethodRetrieve for Oss {
|
||||
payment_intent,
|
||||
enums::PaymentMethod::BankRedirect,
|
||||
pm,
|
||||
merchant_key_store,
|
||||
)
|
||||
.await?;
|
||||
|
||||
|
||||
@ -2009,7 +2009,7 @@ pub async fn list_customer_payment_method(
|
||||
let hyperswitch_token = generate_id(consts::ID_LENGTH, "token");
|
||||
|
||||
let card = if pm.payment_method == enums::PaymentMethod::Card {
|
||||
get_card_details(&pm, key, state, &hyperswitch_token).await?
|
||||
get_card_details(&pm, key, state, &hyperswitch_token, &key_store).await?
|
||||
} else {
|
||||
None
|
||||
};
|
||||
@ -2104,6 +2104,7 @@ async fn get_card_details(
|
||||
key: &[u8],
|
||||
state: &routes::AppState,
|
||||
hyperswitch_token: &str,
|
||||
key_store: &domain::MerchantKeyStore,
|
||||
) -> errors::RouterResult<Option<api::CardDetailFromLocker>> {
|
||||
let mut _card_decrypted =
|
||||
decrypt::<serde_json::Value, masking::WithType>(pm.payment_method_data.clone(), key)
|
||||
@ -2120,7 +2121,7 @@ async fn get_card_details(
|
||||
});
|
||||
|
||||
Ok(Some(
|
||||
get_lookup_key_from_locker(state, hyperswitch_token, pm).await?,
|
||||
get_lookup_key_from_locker(state, hyperswitch_token, pm, key_store).await?,
|
||||
))
|
||||
}
|
||||
|
||||
@ -2128,6 +2129,7 @@ pub async fn get_lookup_key_from_locker(
|
||||
state: &routes::AppState,
|
||||
payment_token: &str,
|
||||
pm: &storage::PaymentMethod,
|
||||
merchant_key_store: &domain::MerchantKeyStore,
|
||||
) -> errors::RouterResult<api::CardDetailFromLocker> {
|
||||
let card = get_card_from_locker(
|
||||
state,
|
||||
@ -2142,8 +2144,14 @@ pub async fn get_lookup_key_from_locker(
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Get Card Details Failed")?;
|
||||
let card = card_detail.clone();
|
||||
let resp =
|
||||
BasiliskCardSupport::create_payment_method_data_in_locker(state, payment_token, card, pm)
|
||||
|
||||
let resp = TempLockerCardSupport::create_payment_method_data_in_temp_locker(
|
||||
state,
|
||||
payment_token,
|
||||
card,
|
||||
pm,
|
||||
merchant_key_store,
|
||||
)
|
||||
.await?;
|
||||
Ok(resp)
|
||||
}
|
||||
@ -2177,6 +2185,7 @@ pub async fn get_lookup_key_for_payout_method(
|
||||
Some(payout_token.to_string()),
|
||||
&pm_parsed,
|
||||
Some(pm.customer_id.to_owned()),
|
||||
key_store,
|
||||
)
|
||||
.await
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
@ -2190,110 +2199,16 @@ pub async fn get_lookup_key_for_payout_method(
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BasiliskCardSupport;
|
||||
pub struct TempLockerCardSupport;
|
||||
|
||||
#[cfg(not(feature = "basilisk"))]
|
||||
impl BasiliskCardSupport {
|
||||
async fn create_payment_method_data_in_locker(
|
||||
state: &routes::AppState,
|
||||
payment_token: &str,
|
||||
card: api::CardDetailFromLocker,
|
||||
pm: &storage::PaymentMethod,
|
||||
) -> errors::RouterResult<api::CardDetailFromLocker> {
|
||||
let card_number = card.card_number.clone().get_required_value("card_number")?;
|
||||
let card_exp_month = card
|
||||
.expiry_month
|
||||
.clone()
|
||||
.expose_option()
|
||||
.get_required_value("expiry_month")?;
|
||||
let card_exp_year = card
|
||||
.expiry_year
|
||||
.clone()
|
||||
.expose_option()
|
||||
.get_required_value("expiry_year")?;
|
||||
let card_holder_name = card
|
||||
.card_holder_name
|
||||
.clone()
|
||||
.expose_option()
|
||||
.unwrap_or_default();
|
||||
let value1 = payment_methods::mk_card_value1(
|
||||
card_number,
|
||||
card_exp_year,
|
||||
card_exp_month,
|
||||
Some(card_holder_name),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
)
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Error getting Value1 for locker")?;
|
||||
let value2 = payment_methods::mk_card_value2(
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
Some(pm.customer_id.to_string()),
|
||||
Some(pm.payment_method_id.to_string()),
|
||||
)
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Error getting Value2 for locker")?;
|
||||
|
||||
let value1 = vault::VaultPaymentMethod::Card(value1);
|
||||
let value2 = vault::VaultPaymentMethod::Card(value2);
|
||||
|
||||
let value1 = utils::Encode::<vault::VaultPaymentMethod>::encode_to_string_of_json(&value1)
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Wrapped value1 construction failed when saving card to locker")?;
|
||||
|
||||
let value2 = utils::Encode::<vault::VaultPaymentMethod>::encode_to_string_of_json(&value2)
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Wrapped value2 construction failed when saving card to locker")?;
|
||||
|
||||
let db_value = vault::MockTokenizeDBValue { value1, value2 };
|
||||
|
||||
let value_string =
|
||||
utils::Encode::<vault::MockTokenizeDBValue>::encode_to_string_of_json(&db_value)
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable(
|
||||
"Mock tokenize value construction failed when saving card to locker",
|
||||
)?;
|
||||
|
||||
let db = &*state.store;
|
||||
|
||||
let already_present = db.find_config_by_key(payment_token).await;
|
||||
|
||||
if already_present.is_err() {
|
||||
let config = storage::ConfigNew {
|
||||
key: payment_token.to_string(),
|
||||
config: value_string,
|
||||
};
|
||||
|
||||
db.insert_config(config)
|
||||
.await
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Mock tokenization save to db failed")?;
|
||||
} else {
|
||||
let config_update = storage::ConfigUpdate::Update {
|
||||
config: Some(value_string),
|
||||
};
|
||||
|
||||
db.update_config_by_key(payment_token, config_update)
|
||||
.await
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Mock tokenization db update failed")?;
|
||||
}
|
||||
|
||||
Ok(card)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "basilisk")]
|
||||
impl BasiliskCardSupport {
|
||||
impl TempLockerCardSupport {
|
||||
#[instrument(skip_all)]
|
||||
async fn create_payment_method_data_in_locker(
|
||||
async fn create_payment_method_data_in_temp_locker(
|
||||
state: &routes::AppState,
|
||||
payment_token: &str,
|
||||
card: api::CardDetailFromLocker,
|
||||
pm: &storage::PaymentMethod,
|
||||
merchant_key_store: &domain::MerchantKeyStore,
|
||||
) -> errors::RouterResult<api::CardDetailFromLocker> {
|
||||
let card_number = card.card_number.clone().get_required_value("card_number")?;
|
||||
let card_exp_month = card
|
||||
@ -2343,8 +2258,14 @@ impl BasiliskCardSupport {
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Wrapped value2 construction failed when saving card to locker")?;
|
||||
|
||||
let lookup_key =
|
||||
vault::create_tokenize(state, value1, Some(value2), payment_token.to_string()).await?;
|
||||
let lookup_key = vault::create_tokenize(
|
||||
state,
|
||||
value1,
|
||||
Some(value2),
|
||||
payment_token.to_string(),
|
||||
merchant_key_store.key.get_inner(),
|
||||
)
|
||||
.await?;
|
||||
vault::add_delete_tokenized_data_task(
|
||||
&*state.store,
|
||||
&lookup_key,
|
||||
|
||||
@ -1,34 +1,30 @@
|
||||
use common_utils::generate_id_with_default_len;
|
||||
#[cfg(feature = "basilisk")]
|
||||
use error_stack::report;
|
||||
use error_stack::{IntoReport, ResultExt};
|
||||
use common_utils::{
|
||||
crypto::{DecodeMessage, EncodeMessage, GcmAes256},
|
||||
ext_traits::BytesExt,
|
||||
generate_id_with_default_len,
|
||||
};
|
||||
use error_stack::{report, IntoReport, ResultExt};
|
||||
#[cfg(feature = "basilisk")]
|
||||
use josekit::jwe;
|
||||
use masking::PeekInterface;
|
||||
use router_env::{instrument, tracing};
|
||||
#[cfg(feature = "basilisk")]
|
||||
use scheduler::{types::process_data, utils as process_tracker_utils};
|
||||
|
||||
#[cfg(feature = "basilisk")]
|
||||
use crate::routes::metrics;
|
||||
#[cfg(feature = "payouts")]
|
||||
use crate::types::api::payouts;
|
||||
use crate::{
|
||||
configs::settings,
|
||||
consts,
|
||||
core::errors::{self, CustomResult, RouterResult},
|
||||
logger, routes,
|
||||
db, logger, routes,
|
||||
routes::metrics,
|
||||
types::{
|
||||
api,
|
||||
storage::{self, enums},
|
||||
api, domain,
|
||||
storage::{self, enums, ProcessTrackerExt},
|
||||
},
|
||||
utils::{self, StringExt},
|
||||
};
|
||||
#[cfg(feature = "basilisk")]
|
||||
use crate::{core::payment_methods::transformers as payment_methods, services, utils::BytesExt};
|
||||
#[cfg(feature = "basilisk")]
|
||||
use crate::{db, types::storage::ProcessTrackerExt};
|
||||
|
||||
#[cfg(feature = "basilisk")]
|
||||
use crate::{core::payment_methods::transformers as payment_methods, services, settings};
|
||||
const VAULT_SERVICE_NAME: &str = "CARD";
|
||||
#[cfg(feature = "basilisk")]
|
||||
const VAULT_VERSION: &str = "0";
|
||||
@ -622,196 +618,15 @@ pub struct MockTokenizeDBValue {
|
||||
|
||||
pub struct Vault;
|
||||
|
||||
#[cfg(not(feature = "basilisk"))]
|
||||
impl Vault {
|
||||
#[instrument(skip_all)]
|
||||
pub async fn get_payment_method_data_from_locker(
|
||||
state: &routes::AppState,
|
||||
lookup_key: &str,
|
||||
merchant_key_store: &domain::MerchantKeyStore,
|
||||
) -> RouterResult<(Option<api::PaymentMethodData>, SupplementaryVaultData)> {
|
||||
let config = state
|
||||
.store
|
||||
.find_config_by_key(lookup_key)
|
||||
.await
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Could not find payment method in vault")?;
|
||||
|
||||
let tokenize_value: MockTokenizeDBValue = config
|
||||
.config
|
||||
.parse_struct("MockTokenizeDBValue")
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Unable to deserialize Mock tokenize db value")?;
|
||||
|
||||
let (payment_method, supp_data) =
|
||||
api::PaymentMethodData::from_values(tokenize_value.value1, tokenize_value.value2)
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Error parsing Payment Method from Values")?;
|
||||
|
||||
Ok((Some(payment_method), supp_data))
|
||||
}
|
||||
|
||||
#[cfg(feature = "payouts")]
|
||||
#[instrument(skip_all)]
|
||||
pub async fn get_payout_method_data_from_temporary_locker(
|
||||
state: &routes::AppState,
|
||||
lookup_key: &str,
|
||||
) -> RouterResult<(Option<api::PayoutMethodData>, SupplementaryVaultData)> {
|
||||
let config = state
|
||||
.store
|
||||
.find_config_by_key(lookup_key)
|
||||
.await
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Could not find payment method in vault")?;
|
||||
|
||||
let tokenize_value: MockTokenizeDBValue = config
|
||||
.config
|
||||
.parse_struct("MockTokenizeDBValue")
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Unable to deserialize Mock tokenize db value")?;
|
||||
|
||||
let (payout_method, supp_data) =
|
||||
api::PayoutMethodData::from_values(tokenize_value.value1, tokenize_value.value2)
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Error parsing Payout Method from Values")?;
|
||||
|
||||
Ok((Some(payout_method), supp_data))
|
||||
}
|
||||
|
||||
#[cfg(feature = "payouts")]
|
||||
#[instrument(skip_all)]
|
||||
pub async fn store_payout_method_data_in_locker(
|
||||
state: &routes::AppState,
|
||||
token_id: Option<String>,
|
||||
payout_method: &api::PayoutMethodData,
|
||||
customer_id: Option<String>,
|
||||
) -> RouterResult<String> {
|
||||
let value1 = payout_method
|
||||
.get_value1(customer_id.clone())
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Error getting Value1 for locker")?;
|
||||
|
||||
let value2 = payout_method
|
||||
.get_value2(customer_id)
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Error getting Value2 for locker")?;
|
||||
|
||||
let lookup_key = token_id.unwrap_or_else(|| generate_id_with_default_len("token"));
|
||||
|
||||
let db_value = MockTokenizeDBValue { value1, value2 };
|
||||
|
||||
let value_string =
|
||||
utils::Encode::<MockTokenizeDBValue>::encode_to_string_of_json(&db_value)
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Failed to encode payout method as mock tokenize db value")?;
|
||||
|
||||
let already_present = state.store.find_config_by_key(&lookup_key).await;
|
||||
|
||||
if already_present.is_err() {
|
||||
let config = storage::ConfigNew {
|
||||
key: lookup_key.clone(),
|
||||
config: value_string,
|
||||
};
|
||||
|
||||
state
|
||||
.store
|
||||
.insert_config(config)
|
||||
.await
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Mock tokenization save to db failed insert")?;
|
||||
} else {
|
||||
let config_update = storage::ConfigUpdate::Update {
|
||||
config: Some(value_string),
|
||||
};
|
||||
state
|
||||
.store
|
||||
.update_config_by_key(&lookup_key, config_update)
|
||||
.await
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Mock tokenization save to db failed update")?;
|
||||
}
|
||||
|
||||
Ok(lookup_key)
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
pub async fn store_payment_method_data_in_locker(
|
||||
state: &routes::AppState,
|
||||
token_id: Option<String>,
|
||||
payment_method: &api::PaymentMethodData,
|
||||
customer_id: Option<String>,
|
||||
_pm: enums::PaymentMethod,
|
||||
) -> RouterResult<String> {
|
||||
let value1 = payment_method
|
||||
.get_value1(customer_id.clone())
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Error getting Value1 for locker")?;
|
||||
|
||||
let value2 = payment_method
|
||||
.get_value2(customer_id)
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Error getting Value12 for locker")?;
|
||||
|
||||
let lookup_key = token_id.unwrap_or_else(|| generate_id_with_default_len("token"));
|
||||
|
||||
let db_value = MockTokenizeDBValue { value1, value2 };
|
||||
|
||||
let value_string =
|
||||
utils::Encode::<MockTokenizeDBValue>::encode_to_string_of_json(&db_value)
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Failed to encode payment method as mock tokenize db value")?;
|
||||
|
||||
let already_present = state.store.find_config_by_key(&lookup_key).await;
|
||||
|
||||
if already_present.is_err() {
|
||||
let config = storage::ConfigNew {
|
||||
key: lookup_key.clone(),
|
||||
config: value_string,
|
||||
};
|
||||
|
||||
state
|
||||
.store
|
||||
.insert_config(config)
|
||||
.await
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Mock tokenization save to db failed insert")?;
|
||||
} else {
|
||||
let config_update = storage::ConfigUpdate::Update {
|
||||
config: Some(value_string),
|
||||
};
|
||||
state
|
||||
.store
|
||||
.update_config_by_key(&lookup_key, config_update)
|
||||
.await
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Mock tokenization save to db failed update")?;
|
||||
}
|
||||
|
||||
Ok(lookup_key)
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
pub async fn delete_locker_payment_method_by_lookup_key(
|
||||
state: &routes::AppState,
|
||||
lookup_key: &Option<String>,
|
||||
) {
|
||||
let db = &*state.store;
|
||||
if let Some(id) = lookup_key {
|
||||
match db.delete_config_by_key(id).await {
|
||||
Ok(_) => logger::info!("Card Deleted from locker mock up"),
|
||||
Err(err) => logger::error!("Err: Card Delete from locker Failed : {}", err),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "basilisk")]
|
||||
impl Vault {
|
||||
#[instrument(skip_all)]
|
||||
pub async fn get_payment_method_data_from_locker(
|
||||
state: &routes::AppState,
|
||||
lookup_key: &str,
|
||||
) -> RouterResult<(Option<api::PaymentMethodData>, SupplementaryVaultData)> {
|
||||
let de_tokenize = get_tokenized_data(state, lookup_key, true).await?;
|
||||
let de_tokenize =
|
||||
get_tokenized_data(state, lookup_key, true, merchant_key_store.key.get_inner()).await?;
|
||||
let (payment_method, customer_id) =
|
||||
api::PaymentMethodData::from_values(de_tokenize.value1, de_tokenize.value2)
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
@ -827,6 +642,7 @@ impl Vault {
|
||||
payment_method: &api::PaymentMethodData,
|
||||
customer_id: Option<String>,
|
||||
pm: enums::PaymentMethod,
|
||||
merchant_key_store: &domain::MerchantKeyStore,
|
||||
) -> RouterResult<String> {
|
||||
let value1 = payment_method
|
||||
.get_value1(customer_id.clone())
|
||||
@ -840,7 +656,14 @@ impl Vault {
|
||||
|
||||
let lookup_key = token_id.unwrap_or_else(|| generate_id_with_default_len("token"));
|
||||
|
||||
let lookup_key = create_tokenize(state, value1, Some(value2), lookup_key).await?;
|
||||
let lookup_key = create_tokenize(
|
||||
state,
|
||||
value1,
|
||||
Some(value2),
|
||||
lookup_key,
|
||||
merchant_key_store.key.get_inner(),
|
||||
)
|
||||
.await?;
|
||||
add_delete_tokenized_data_task(&*state.store, &lookup_key, pm).await?;
|
||||
metrics::TOKENIZED_DATA_COUNT.add(&metrics::CONTEXT, 1, &[]);
|
||||
Ok(lookup_key)
|
||||
@ -851,8 +674,10 @@ impl Vault {
|
||||
pub async fn get_payout_method_data_from_temporary_locker(
|
||||
state: &routes::AppState,
|
||||
lookup_key: &str,
|
||||
merchant_key_store: &domain::MerchantKeyStore,
|
||||
) -> RouterResult<(Option<api::PayoutMethodData>, SupplementaryVaultData)> {
|
||||
let de_tokenize = get_tokenized_data(state, lookup_key, true).await?;
|
||||
let de_tokenize =
|
||||
get_tokenized_data(state, lookup_key, true, merchant_key_store.key.get_inner()).await?;
|
||||
let (payout_method, supp_data) =
|
||||
api::PayoutMethodData::from_values(de_tokenize.value1, de_tokenize.value2)
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
@ -868,6 +693,7 @@ impl Vault {
|
||||
token_id: Option<String>,
|
||||
payout_method: &api::PayoutMethodData,
|
||||
customer_id: Option<String>,
|
||||
merchant_key_store: &domain::MerchantKeyStore,
|
||||
) -> RouterResult<String> {
|
||||
let value1 = payout_method
|
||||
.get_value1(customer_id.clone())
|
||||
@ -881,7 +707,14 @@ impl Vault {
|
||||
|
||||
let lookup_key = token_id.unwrap_or_else(|| generate_id_with_default_len("token"));
|
||||
|
||||
let lookup_key = create_tokenize(state, value1, Some(value2), lookup_key).await?;
|
||||
let lookup_key = create_tokenize(
|
||||
state,
|
||||
value1,
|
||||
Some(value2),
|
||||
lookup_key,
|
||||
merchant_key_store.key.get_inner(),
|
||||
)
|
||||
.await?;
|
||||
// add_delete_tokenized_data_task(&*state.store, &lookup_key, pm).await?;
|
||||
// scheduler_metrics::TOKENIZED_DATA_COUNT.add(&metrics::CONTEXT, 1, &[]);
|
||||
Ok(lookup_key)
|
||||
@ -893,31 +726,334 @@ impl Vault {
|
||||
lookup_key: &Option<String>,
|
||||
) {
|
||||
if let Some(lookup_key) = lookup_key {
|
||||
let delete_resp = delete_tokenized_data(state, lookup_key).await;
|
||||
match delete_resp {
|
||||
Ok(resp) => {
|
||||
if resp == "Ok" {
|
||||
logger::info!("Card From locker deleted Successfully")
|
||||
} else {
|
||||
logger::error!("Error: Deleting Card From Locker : {:?}", resp)
|
||||
}
|
||||
}
|
||||
Err(err) => logger::error!("Err: Deleting Card From Locker : {:?}", err),
|
||||
}
|
||||
delete_tokenized_data(state, lookup_key)
|
||||
.await
|
||||
.map(|_| logger::info!("Card From locker deleted Successfully"))
|
||||
.map_err(|err| logger::error!("Error: Deleting Card From Redis Locker : {:?}", err))
|
||||
.ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------TokenizeService------------------------------------------------
|
||||
pub fn get_key_id(keys: &settings::Jwekey) -> &str {
|
||||
let key_identifier = "1"; // [#46]: Fetch this value from redis or external sources
|
||||
if key_identifier == "1" {
|
||||
&keys.locker_key_identifier1
|
||||
} else {
|
||||
&keys.locker_key_identifier2
|
||||
|
||||
#[inline(always)]
|
||||
fn get_redis_locker_key(lookup_key: &str) -> String {
|
||||
format!("{}_{}", consts::LOCKER_REDIS_PREFIX, lookup_key)
|
||||
}
|
||||
|
||||
#[instrument(skip(state, value1, value2))]
|
||||
pub async fn create_tokenize(
|
||||
state: &routes::AppState,
|
||||
value1: String,
|
||||
value2: Option<String>,
|
||||
lookup_key: String,
|
||||
encryption_key: &masking::Secret<Vec<u8>>,
|
||||
) -> RouterResult<String> {
|
||||
let redis_key = get_redis_locker_key(lookup_key.as_str());
|
||||
let func = || async {
|
||||
metrics::CREATED_TOKENIZED_CARD.add(&metrics::CONTEXT, 1, &[]);
|
||||
|
||||
let payload_to_be_encrypted = api::TokenizePayloadRequest {
|
||||
value1: value1.clone(),
|
||||
value2: value2.clone().unwrap_or_default(),
|
||||
lookup_key: lookup_key.clone(),
|
||||
service_name: VAULT_SERVICE_NAME.to_string(),
|
||||
};
|
||||
|
||||
let payload = utils::Encode::<api::TokenizePayloadRequest>::encode_to_string_of_json(
|
||||
&payload_to_be_encrypted,
|
||||
)
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)?;
|
||||
|
||||
let encrypted_payload = GcmAes256
|
||||
.encode_message(encryption_key.peek().as_ref(), payload.as_bytes())
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Failed to encode redis temp locker data")?;
|
||||
|
||||
let redis_conn = state
|
||||
.store
|
||||
.get_redis_conn()
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Failed to get redis connection")?;
|
||||
|
||||
redis_conn
|
||||
.set_key_if_not_exists_with_expiry(
|
||||
redis_key.as_str(),
|
||||
bytes::Bytes::from(encrypted_payload),
|
||||
Some(i64::from(consts::LOCKER_REDIS_EXPIRY_SECONDS)),
|
||||
)
|
||||
.await
|
||||
.map(|_| lookup_key.clone())
|
||||
.map_err(|err| {
|
||||
metrics::TEMP_LOCKER_FAILURES.add(&metrics::CONTEXT, 1, &[]);
|
||||
err
|
||||
})
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Error from redis locker")
|
||||
};
|
||||
|
||||
match func().await {
|
||||
Ok(s) => {
|
||||
logger::info!(
|
||||
"Insert payload in redis locker successful with lookup key: {:?}",
|
||||
redis_key
|
||||
);
|
||||
Ok(s)
|
||||
}
|
||||
Err(err) => {
|
||||
logger::error!("Redis Temp locker Failed: {:?}", err);
|
||||
|
||||
#[cfg(feature = "basilisk")]
|
||||
return old_create_tokenize(state, value1, value2, lookup_key).await;
|
||||
|
||||
#[cfg(not(feature = "basilisk"))]
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(skip(state))]
|
||||
pub async fn get_tokenized_data(
|
||||
state: &routes::AppState,
|
||||
lookup_key: &str,
|
||||
_should_get_value2: bool,
|
||||
encryption_key: &masking::Secret<Vec<u8>>,
|
||||
) -> RouterResult<api::TokenizePayloadRequest> {
|
||||
let redis_key = get_redis_locker_key(lookup_key);
|
||||
let func = || async {
|
||||
metrics::GET_TOKENIZED_CARD.add(&metrics::CONTEXT, 1, &[]);
|
||||
|
||||
let redis_conn = state
|
||||
.store
|
||||
.get_redis_conn()
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Failed to get redis connection")?;
|
||||
|
||||
let response = redis_conn.get_key::<bytes::Bytes>(redis_key.as_str()).await;
|
||||
|
||||
match response {
|
||||
Ok(resp) => {
|
||||
let decrypted_payload = GcmAes256
|
||||
.decode_message(
|
||||
encryption_key.peek().as_ref(),
|
||||
masking::Secret::new(resp.into()),
|
||||
)
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Failed to decode redis temp locker data")?;
|
||||
|
||||
let get_response: api::TokenizePayloadRequest =
|
||||
bytes::Bytes::from(decrypted_payload)
|
||||
.parse_struct("TokenizePayloadRequest")
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable(
|
||||
"Error getting TokenizePayloadRequest from tokenize response",
|
||||
)?;
|
||||
|
||||
Ok(get_response)
|
||||
}
|
||||
Err(err) => {
|
||||
metrics::TEMP_LOCKER_FAILURES.add(&metrics::CONTEXT, 1, &[]);
|
||||
Err(err).change_context(errors::ApiErrorResponse::UnprocessableEntity {
|
||||
message: "Token is invalid or expired".into(),
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
match func().await {
|
||||
Ok(s) => {
|
||||
logger::info!(
|
||||
"Fetch payload in redis locker successful with lookup key: {:?}",
|
||||
redis_key
|
||||
);
|
||||
Ok(s)
|
||||
}
|
||||
Err(err) => {
|
||||
logger::error!("Redis Temp locker Failed: {:?}", err);
|
||||
|
||||
#[cfg(feature = "basilisk")]
|
||||
return old_get_tokenized_data(state, lookup_key, _should_get_value2).await;
|
||||
|
||||
#[cfg(not(feature = "basilisk"))]
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(skip(state))]
|
||||
pub async fn delete_tokenized_data(state: &routes::AppState, lookup_key: &str) -> RouterResult<()> {
|
||||
let redis_key = get_redis_locker_key(lookup_key);
|
||||
let func = || async {
|
||||
metrics::DELETED_TOKENIZED_CARD.add(&metrics::CONTEXT, 1, &[]);
|
||||
|
||||
let redis_conn = state
|
||||
.store
|
||||
.get_redis_conn()
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Failed to get redis connection")?;
|
||||
|
||||
let response = redis_conn.delete_key(redis_key.as_str()).await;
|
||||
|
||||
match response {
|
||||
Ok(redis_interface::DelReply::KeyDeleted) => Ok(()),
|
||||
Ok(redis_interface::DelReply::KeyNotDeleted) => {
|
||||
Err(errors::ApiErrorResponse::InternalServerError)
|
||||
.into_report()
|
||||
.attach_printable("Token invalid or expired")
|
||||
}
|
||||
Err(err) => {
|
||||
metrics::TEMP_LOCKER_FAILURES.add(&metrics::CONTEXT, 1, &[]);
|
||||
Err(errors::ApiErrorResponse::InternalServerError)
|
||||
.into_report()
|
||||
.attach_printable_lazy(|| {
|
||||
format!("Failed to delete from redis locker: {err:?}")
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
match func().await {
|
||||
Ok(s) => {
|
||||
logger::info!(
|
||||
"Delete payload in redis locker successful with lookup key: {:?}",
|
||||
redis_key
|
||||
);
|
||||
Ok(s)
|
||||
}
|
||||
Err(err) => {
|
||||
logger::error!("Redis Temp locker Failed: {:?}", err);
|
||||
|
||||
#[cfg(feature = "basilisk")]
|
||||
return old_delete_tokenized_data(state, lookup_key).await;
|
||||
|
||||
#[cfg(not(feature = "basilisk"))]
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ********************************************** PROCESS TRACKER **********************************************
|
||||
|
||||
pub async fn add_delete_tokenized_data_task(
|
||||
db: &dyn db::StorageInterface,
|
||||
lookup_key: &str,
|
||||
pm: enums::PaymentMethod,
|
||||
) -> RouterResult<()> {
|
||||
let runner = "DELETE_TOKENIZE_DATA_WORKFLOW";
|
||||
let current_time = common_utils::date_time::now();
|
||||
let tracking_data = serde_json::to_value(storage::TokenizeCoreWorkflow {
|
||||
lookup_key: lookup_key.to_owned(),
|
||||
pm,
|
||||
})
|
||||
.into_report()
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable_lazy(|| format!("unable to convert into value {lookup_key:?}"))?;
|
||||
|
||||
let schedule_time = get_delete_tokenize_schedule_time(db, &pm, 0).await;
|
||||
|
||||
let process_tracker_entry = storage::ProcessTrackerNew {
|
||||
id: format!("{runner}_{lookup_key}"),
|
||||
name: Some(String::from(runner)),
|
||||
tag: vec![String::from("BASILISK-V3")],
|
||||
runner: Some(String::from(runner)),
|
||||
retry_count: 0,
|
||||
schedule_time,
|
||||
rule: String::new(),
|
||||
tracking_data,
|
||||
business_status: String::from("Pending"),
|
||||
status: enums::ProcessTrackerStatus::New,
|
||||
event: vec![],
|
||||
created_at: current_time,
|
||||
updated_at: current_time,
|
||||
};
|
||||
let response = db.insert_process(process_tracker_entry).await;
|
||||
response.map(|_| ()).or_else(|err| {
|
||||
if err.current_context().is_db_unique_violation() {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(report!(errors::ApiErrorResponse::InternalServerError))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn start_tokenize_data_workflow(
|
||||
state: &routes::AppState,
|
||||
tokenize_tracker: &storage::ProcessTracker,
|
||||
) -> Result<(), errors::ProcessTrackerError> {
|
||||
let db = &*state.store;
|
||||
let delete_tokenize_data = serde_json::from_value::<storage::TokenizeCoreWorkflow>(
|
||||
tokenize_tracker.tracking_data.clone(),
|
||||
)
|
||||
.into_report()
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable_lazy(|| {
|
||||
format!(
|
||||
"unable to convert into DeleteTokenizeByTokenRequest {:?}",
|
||||
tokenize_tracker.tracking_data
|
||||
)
|
||||
})?;
|
||||
|
||||
match delete_tokenized_data(state, &delete_tokenize_data.lookup_key).await {
|
||||
Ok(()) => {
|
||||
logger::info!("Card From locker deleted Successfully");
|
||||
//mark task as finished
|
||||
let id = tokenize_tracker.id.clone();
|
||||
tokenize_tracker
|
||||
.clone()
|
||||
.finish_with_status(db.as_scheduler(), format!("COMPLETED_BY_PT_{id}"))
|
||||
.await?;
|
||||
}
|
||||
Err(err) => {
|
||||
logger::error!("Err: Deleting Card From Locker : {:?}", err);
|
||||
retry_delete_tokenize(db, &delete_tokenize_data.pm, tokenize_tracker.to_owned())
|
||||
.await?;
|
||||
metrics::RETRIED_DELETE_DATA_COUNT.add(&metrics::CONTEXT, 1, &[]);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn get_delete_tokenize_schedule_time(
|
||||
db: &dyn db::StorageInterface,
|
||||
pm: &enums::PaymentMethod,
|
||||
retry_count: i32,
|
||||
) -> Option<time::PrimitiveDateTime> {
|
||||
let redis_mapping = db::get_and_deserialize_key(
|
||||
db,
|
||||
&format!("pt_mapping_delete_{pm}_tokenize_data"),
|
||||
"PaymentMethodsPTMapping",
|
||||
)
|
||||
.await;
|
||||
let mapping = match redis_mapping {
|
||||
Ok(x) => x,
|
||||
Err(err) => {
|
||||
logger::info!("Redis Mapping Error: {}", err);
|
||||
process_data::PaymentMethodsPTMapping::default()
|
||||
}
|
||||
};
|
||||
let time_delta = process_tracker_utils::get_pm_schedule_time(mapping, pm, retry_count + 1);
|
||||
|
||||
process_tracker_utils::get_time_from_delta(time_delta)
|
||||
}
|
||||
|
||||
pub async fn retry_delete_tokenize(
|
||||
db: &dyn db::StorageInterface,
|
||||
pm: &enums::PaymentMethod,
|
||||
pt: storage::ProcessTracker,
|
||||
) -> Result<(), errors::ProcessTrackerError> {
|
||||
let schedule_time = get_delete_tokenize_schedule_time(db, pm, pt.retry_count).await;
|
||||
|
||||
match schedule_time {
|
||||
Some(s_time) => pt.retry(db.as_scheduler(), s_time).await,
|
||||
None => {
|
||||
pt.finish_with_status(db.as_scheduler(), "RETRIES_EXCEEDED".to_string())
|
||||
.await
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback logic of old temp locker needs to be removed later
|
||||
|
||||
#[cfg(feature = "basilisk")]
|
||||
async fn get_locker_jwe_keys(
|
||||
keys: &settings::ActiveKmsSecrets,
|
||||
@ -936,13 +1072,13 @@ async fn get_locker_jwe_keys(
|
||||
}
|
||||
|
||||
#[cfg(feature = "basilisk")]
|
||||
pub async fn create_tokenize(
|
||||
#[instrument(skip(state, value1, value2))]
|
||||
pub async fn old_create_tokenize(
|
||||
state: &routes::AppState,
|
||||
value1: String,
|
||||
value2: Option<String>,
|
||||
lookup_key: String,
|
||||
) -> RouterResult<String> {
|
||||
metrics::CREATED_TOKENIZED_CARD.add(&metrics::CONTEXT, 1, &[]);
|
||||
let payload_to_be_encrypted = api::TokenizePayloadRequest {
|
||||
value1,
|
||||
value2: value2.unwrap_or_default(),
|
||||
@ -1017,7 +1153,7 @@ pub async fn create_tokenize(
|
||||
}
|
||||
|
||||
#[cfg(feature = "basilisk")]
|
||||
pub async fn get_tokenized_data(
|
||||
pub async fn old_get_tokenized_data(
|
||||
state: &routes::AppState,
|
||||
lookup_key: &str,
|
||||
should_get_value2: bool,
|
||||
@ -1096,10 +1232,10 @@ pub async fn get_tokenized_data(
|
||||
}
|
||||
|
||||
#[cfg(feature = "basilisk")]
|
||||
pub async fn delete_tokenized_data(
|
||||
pub async fn old_delete_tokenized_data(
|
||||
state: &routes::AppState,
|
||||
lookup_key: &str,
|
||||
) -> RouterResult<String> {
|
||||
) -> RouterResult<()> {
|
||||
metrics::DELETED_TOKENIZED_CARD.add(&metrics::CONTEXT, 1, &[]);
|
||||
let payload_to_be_encrypted = api::DeleteTokenizeByTokenRequest {
|
||||
lookup_key: lookup_key.to_string(),
|
||||
@ -1136,11 +1272,11 @@ pub async fn delete_tokenized_data(
|
||||
.attach_printable("Error while making /tokenize/delete/token call to the locker")?;
|
||||
match response {
|
||||
Ok(r) => {
|
||||
let delete_response = std::str::from_utf8(&r.response)
|
||||
let _delete_response = std::str::from_utf8(&r.response)
|
||||
.into_report()
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Decoding Failed for basilisk delete response")?;
|
||||
Ok(delete_response.to_string())
|
||||
Ok(())
|
||||
}
|
||||
Err(err) => {
|
||||
metrics::TEMP_LOCKER_FAILURES.add(&metrics::CONTEXT, 1, &[]);
|
||||
@ -1151,133 +1287,12 @@ pub async fn delete_tokenized_data(
|
||||
}
|
||||
}
|
||||
|
||||
// ********************************************** PROCESS TRACKER **********************************************
|
||||
#[cfg(feature = "basilisk")]
|
||||
pub async fn add_delete_tokenized_data_task(
|
||||
db: &dyn db::StorageInterface,
|
||||
lookup_key: &str,
|
||||
pm: enums::PaymentMethod,
|
||||
) -> RouterResult<()> {
|
||||
let runner = "DELETE_TOKENIZE_DATA_WORKFLOW";
|
||||
let current_time = common_utils::date_time::now();
|
||||
let tracking_data = serde_json::to_value(storage::TokenizeCoreWorkflow {
|
||||
lookup_key: lookup_key.to_owned(),
|
||||
pm,
|
||||
})
|
||||
.into_report()
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable_lazy(|| format!("unable to convert into value {lookup_key:?}"))?;
|
||||
|
||||
let schedule_time = get_delete_tokenize_schedule_time(db, &pm, 0).await;
|
||||
|
||||
let process_tracker_entry = storage::ProcessTrackerNew {
|
||||
id: format!("{runner}_{lookup_key}"),
|
||||
name: Some(String::from(runner)),
|
||||
tag: vec![String::from("BASILISK-V3")],
|
||||
runner: Some(String::from(runner)),
|
||||
retry_count: 0,
|
||||
schedule_time,
|
||||
rule: String::new(),
|
||||
tracking_data,
|
||||
business_status: String::from("Pending"),
|
||||
status: enums::ProcessTrackerStatus::New,
|
||||
event: vec![],
|
||||
created_at: current_time,
|
||||
updated_at: current_time,
|
||||
};
|
||||
let response = db.insert_process(process_tracker_entry).await;
|
||||
response.map(|_| ()).or_else(|err| {
|
||||
if err.current_context().is_db_unique_violation() {
|
||||
Ok(())
|
||||
pub fn get_key_id(keys: &settings::Jwekey) -> &str {
|
||||
let key_identifier = "1"; // [#46]: Fetch this value from redis or external sources
|
||||
if key_identifier == "1" {
|
||||
&keys.locker_key_identifier1
|
||||
} else {
|
||||
Err(report!(errors::ApiErrorResponse::InternalServerError))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(feature = "basilisk")]
|
||||
pub async fn start_tokenize_data_workflow(
|
||||
state: &routes::AppState,
|
||||
tokenize_tracker: &storage::ProcessTracker,
|
||||
) -> Result<(), errors::ProcessTrackerError> {
|
||||
let db = &*state.store;
|
||||
let delete_tokenize_data = serde_json::from_value::<storage::TokenizeCoreWorkflow>(
|
||||
tokenize_tracker.tracking_data.clone(),
|
||||
)
|
||||
.into_report()
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable_lazy(|| {
|
||||
format!(
|
||||
"unable to convert into DeleteTokenizeByTokenRequest {:?}",
|
||||
tokenize_tracker.tracking_data
|
||||
)
|
||||
})?;
|
||||
|
||||
let delete_resp = delete_tokenized_data(state, &delete_tokenize_data.lookup_key).await;
|
||||
match delete_resp {
|
||||
Ok(resp) => {
|
||||
if resp == "Ok" {
|
||||
logger::info!("Card From locker deleted Successfully");
|
||||
//mark task as finished
|
||||
let id = tokenize_tracker.id.clone();
|
||||
tokenize_tracker
|
||||
.clone()
|
||||
.finish_with_status(db.as_scheduler(), format!("COMPLETED_BY_PT_{id}"))
|
||||
.await?;
|
||||
} else {
|
||||
logger::error!("Error: Deleting Card From Locker : {:?}", resp);
|
||||
retry_delete_tokenize(db, &delete_tokenize_data.pm, tokenize_tracker.to_owned())
|
||||
.await?;
|
||||
metrics::RETRIED_DELETE_DATA_COUNT.add(&metrics::CONTEXT, 1, &[]);
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
logger::error!("Err: Deleting Card From Locker : {:?}", err);
|
||||
retry_delete_tokenize(db, &delete_tokenize_data.pm, tokenize_tracker.to_owned())
|
||||
.await?;
|
||||
metrics::RETRIED_DELETE_DATA_COUNT.add(&metrics::CONTEXT, 1, &[]);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(feature = "basilisk")]
|
||||
pub async fn get_delete_tokenize_schedule_time(
|
||||
db: &dyn db::StorageInterface,
|
||||
pm: &enums::PaymentMethod,
|
||||
retry_count: i32,
|
||||
) -> Option<time::PrimitiveDateTime> {
|
||||
let redis_mapping = db::get_and_deserialize_key(
|
||||
db,
|
||||
&format!("pt_mapping_delete_{pm}_tokenize_data"),
|
||||
"PaymentMethodsPTMapping",
|
||||
)
|
||||
.await;
|
||||
let mapping = match redis_mapping {
|
||||
Ok(x) => x,
|
||||
Err(err) => {
|
||||
logger::info!("Redis Mapping Error: {}", err);
|
||||
process_data::PaymentMethodsPTMapping::default()
|
||||
}
|
||||
};
|
||||
let time_delta = process_tracker_utils::get_pm_schedule_time(mapping, pm, retry_count + 1);
|
||||
|
||||
process_tracker_utils::get_time_from_delta(time_delta)
|
||||
}
|
||||
|
||||
#[cfg(feature = "basilisk")]
|
||||
pub async fn retry_delete_tokenize(
|
||||
db: &dyn db::StorageInterface,
|
||||
pm: &enums::PaymentMethod,
|
||||
pt: storage::ProcessTracker,
|
||||
) -> Result<(), errors::ProcessTrackerError> {
|
||||
let schedule_time = get_delete_tokenize_schedule_time(db, pm, pt.retry_count).await;
|
||||
|
||||
match schedule_time {
|
||||
Some(s_time) => pt.retry(db.as_scheduler(), s_time).await,
|
||||
None => {
|
||||
pt.finish_with_status(db.as_scheduler(), "RETRIES_EXCEEDED".to_string())
|
||||
.await
|
||||
}
|
||||
&keys.locker_key_identifier2
|
||||
}
|
||||
}
|
||||
|
||||
@ -153,6 +153,7 @@ where
|
||||
&operation,
|
||||
&mut payment_data,
|
||||
&validate_result,
|
||||
&key_store,
|
||||
)
|
||||
.await?;
|
||||
|
||||
@ -717,6 +718,7 @@ where
|
||||
payment_data,
|
||||
validate_result,
|
||||
&merchant_connector_account,
|
||||
key_store,
|
||||
)
|
||||
.await?;
|
||||
|
||||
@ -1399,6 +1401,7 @@ pub async fn get_connector_tokenization_action_when_confirm_true<F, Req, Ctx>(
|
||||
payment_data: &mut PaymentData<F>,
|
||||
validate_result: &operations::ValidateResult<'_>,
|
||||
merchant_connector_account: &helpers::MerchantConnectorAccountType,
|
||||
merchant_key_store: &domain::MerchantKeyStore,
|
||||
) -> RouterResult<(PaymentData<F>, TokenizationAction)>
|
||||
where
|
||||
F: Send + Clone,
|
||||
@ -1461,7 +1464,12 @@ where
|
||||
TokenizationAction::TokenizeInRouter => {
|
||||
let (_operation, payment_method_data) = operation
|
||||
.to_domain()?
|
||||
.make_pm_data(state, payment_data, validate_result.storage_scheme)
|
||||
.make_pm_data(
|
||||
state,
|
||||
payment_data,
|
||||
validate_result.storage_scheme,
|
||||
merchant_key_store,
|
||||
)
|
||||
.await?;
|
||||
payment_data.payment_method_data = payment_method_data;
|
||||
TokenizationAction::SkipConnectorTokenization
|
||||
@ -1471,7 +1479,12 @@ where
|
||||
TokenizationAction::TokenizeInConnectorAndRouter => {
|
||||
let (_operation, payment_method_data) = operation
|
||||
.to_domain()?
|
||||
.make_pm_data(state, payment_data, validate_result.storage_scheme)
|
||||
.make_pm_data(
|
||||
state,
|
||||
payment_data,
|
||||
validate_result.storage_scheme,
|
||||
merchant_key_store,
|
||||
)
|
||||
.await?;
|
||||
|
||||
payment_data.payment_method_data = payment_method_data;
|
||||
@ -1507,6 +1520,7 @@ pub async fn tokenize_in_router_when_confirm_false<F, Req, Ctx>(
|
||||
operation: &BoxedOperation<'_, F, Req, Ctx>,
|
||||
payment_data: &mut PaymentData<F>,
|
||||
validate_result: &operations::ValidateResult<'_>,
|
||||
merchant_key_store: &domain::MerchantKeyStore,
|
||||
) -> RouterResult<PaymentData<F>>
|
||||
where
|
||||
F: Send + Clone,
|
||||
@ -1516,7 +1530,12 @@ where
|
||||
let payment_data = if !is_operation_confirm(operation) {
|
||||
let (_operation, payment_method_data) = operation
|
||||
.to_domain()?
|
||||
.make_pm_data(state, payment_data, validate_result.storage_scheme)
|
||||
.make_pm_data(
|
||||
state,
|
||||
payment_data,
|
||||
validate_result.storage_scheme,
|
||||
merchant_key_store,
|
||||
)
|
||||
.await?;
|
||||
payment_data.payment_method_data = payment_method_data;
|
||||
payment_data
|
||||
|
||||
@ -95,7 +95,8 @@ impl Feature<api::Authorize, types::PaymentsAuthorizeData> for types::PaymentsAu
|
||||
|
||||
metrics::PAYMENT_COUNT.add(&metrics::CONTEXT, 1, &[]); // Metrics
|
||||
|
||||
let save_payment_result = tokenization::save_payment_method(
|
||||
if resp.request.setup_mandate_details.clone().is_some() {
|
||||
let payment_method_id = tokenization::save_payment_method(
|
||||
state,
|
||||
connector,
|
||||
resp.to_owned(),
|
||||
@ -104,28 +105,46 @@ impl Feature<api::Authorize, types::PaymentsAuthorizeData> for types::PaymentsAu
|
||||
self.request.payment_method_type,
|
||||
key_store,
|
||||
)
|
||||
.await;
|
||||
|
||||
let pm_id = match save_payment_result {
|
||||
Ok(payment_method_id) => Ok(payment_method_id),
|
||||
Err(error) => {
|
||||
if resp.request.setup_mandate_details.clone().is_some() {
|
||||
Err(error)
|
||||
} else {
|
||||
logger::error!(save_payment_method_error=?error);
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
}?;
|
||||
|
||||
.await?;
|
||||
Ok(mandate::mandate_procedure(
|
||||
state,
|
||||
resp,
|
||||
maybe_customer,
|
||||
pm_id,
|
||||
payment_method_id,
|
||||
connector.merchant_connector_id.clone(),
|
||||
)
|
||||
.await?)
|
||||
} else {
|
||||
let connector = connector.clone();
|
||||
let response = resp.clone();
|
||||
let maybe_customer = maybe_customer.clone();
|
||||
let merchant_account = merchant_account.clone();
|
||||
let key_store = key_store.clone();
|
||||
let state = state.clone();
|
||||
|
||||
logger::info!("Initiating async call to save_payment_method in locker");
|
||||
|
||||
tokio::spawn(async move {
|
||||
logger::info!("Starting async call to save_payment_method in locker");
|
||||
|
||||
let result = tokenization::save_payment_method(
|
||||
&state,
|
||||
&connector,
|
||||
response,
|
||||
&maybe_customer,
|
||||
&merchant_account,
|
||||
self.request.payment_method_type,
|
||||
&key_store,
|
||||
)
|
||||
.await;
|
||||
|
||||
if let Err(err) = result {
|
||||
logger::error!("Asynchronously saving card in locker failed : {:?}", err);
|
||||
}
|
||||
});
|
||||
|
||||
Ok(resp)
|
||||
}
|
||||
} else {
|
||||
Ok(self.clone())
|
||||
}
|
||||
|
||||
@ -399,6 +399,7 @@ pub async fn get_token_pm_type_mandate_details(
|
||||
request: &api::PaymentsRequest,
|
||||
mandate_type: Option<api::MandateTransactionType>,
|
||||
merchant_account: &domain::MerchantAccount,
|
||||
merchant_key_store: &domain::MerchantKeyStore,
|
||||
) -> RouterResult<(
|
||||
Option<String>,
|
||||
Option<storage_enums::PaymentMethod>,
|
||||
@ -427,7 +428,13 @@ pub async fn get_token_pm_type_mandate_details(
|
||||
recurring_mandate_payment_data,
|
||||
payment_method_type_,
|
||||
mandate_connector,
|
||||
) = get_token_for_recurring_mandate(state, request, merchant_account).await?;
|
||||
) = get_token_for_recurring_mandate(
|
||||
state,
|
||||
request,
|
||||
merchant_account,
|
||||
merchant_key_store,
|
||||
)
|
||||
.await?;
|
||||
Ok((
|
||||
token_,
|
||||
payment_method_,
|
||||
@ -452,6 +459,7 @@ pub async fn get_token_for_recurring_mandate(
|
||||
state: &AppState,
|
||||
req: &api::PaymentsRequest,
|
||||
merchant_account: &domain::MerchantAccount,
|
||||
merchant_key_store: &domain::MerchantKeyStore,
|
||||
) -> RouterResult<(
|
||||
Option<String>,
|
||||
Option<storage_enums::PaymentMethod>,
|
||||
@ -501,7 +509,9 @@ pub async fn get_token_for_recurring_mandate(
|
||||
};
|
||||
|
||||
if let diesel_models::enums::PaymentMethod::Card = payment_method.payment_method {
|
||||
let _ = cards::get_lookup_key_from_locker(state, &token, &payment_method).await?;
|
||||
let _ =
|
||||
cards::get_lookup_key_from_locker(state, &token, &payment_method, merchant_key_store)
|
||||
.await?;
|
||||
if let Some(payment_method_from_request) = req.payment_method {
|
||||
let pm: storage_enums::PaymentMethod = payment_method_from_request;
|
||||
if pm != payment_method.payment_method {
|
||||
@ -1320,6 +1330,7 @@ pub async fn make_pm_data<'a, F: Clone, R, Ctx: PaymentMethodRetrieve>(
|
||||
operation: BoxedOperation<'a, F, R, Ctx>,
|
||||
state: &'a AppState,
|
||||
payment_data: &mut PaymentData<F>,
|
||||
merchant_key_store: &domain::MerchantKeyStore,
|
||||
) -> RouterResult<(
|
||||
BoxedOperation<'a, F, R, Ctx>,
|
||||
Option<api::PaymentMethodData>,
|
||||
@ -1373,6 +1384,7 @@ pub async fn make_pm_data<'a, F: Clone, R, Ctx: PaymentMethodRetrieve>(
|
||||
let (pm, supplementary_data) = vault::Vault::get_payment_method_data_from_locker(
|
||||
state,
|
||||
&hyperswitch_token,
|
||||
merchant_key_store,
|
||||
)
|
||||
.await
|
||||
.attach_printable(
|
||||
@ -1402,6 +1414,7 @@ pub async fn make_pm_data<'a, F: Clone, R, Ctx: PaymentMethodRetrieve>(
|
||||
&updated_pm,
|
||||
payment_data.payment_intent.customer_id.to_owned(),
|
||||
enums::PaymentMethod::Card,
|
||||
merchant_key_store,
|
||||
)
|
||||
.await?;
|
||||
Some(updated_pm)
|
||||
@ -1442,6 +1455,7 @@ pub async fn make_pm_data<'a, F: Clone, R, Ctx: PaymentMethodRetrieve>(
|
||||
state,
|
||||
&payment_data.payment_intent,
|
||||
&payment_data.payment_attempt,
|
||||
merchant_key_store,
|
||||
)
|
||||
.await?;
|
||||
|
||||
@ -1461,6 +1475,7 @@ pub async fn store_in_vault_and_generate_ppmt(
|
||||
payment_intent: &PaymentIntent,
|
||||
payment_attempt: &PaymentAttempt,
|
||||
payment_method: enums::PaymentMethod,
|
||||
merchant_key_store: &domain::MerchantKeyStore,
|
||||
) -> RouterResult<String> {
|
||||
let router_token = vault::Vault::store_payment_method_data_in_locker(
|
||||
state,
|
||||
@ -1468,6 +1483,7 @@ pub async fn store_in_vault_and_generate_ppmt(
|
||||
payment_method_data,
|
||||
payment_intent.customer_id.to_owned(),
|
||||
payment_method,
|
||||
merchant_key_store,
|
||||
)
|
||||
.await?;
|
||||
let parent_payment_method_token = generate_id(consts::ID_LENGTH, "token");
|
||||
@ -1491,6 +1507,7 @@ pub async fn store_payment_method_data_in_vault(
|
||||
payment_intent: &PaymentIntent,
|
||||
payment_method: enums::PaymentMethod,
|
||||
payment_method_data: &api::PaymentMethodData,
|
||||
merchant_key_store: &domain::MerchantKeyStore,
|
||||
) -> RouterResult<Option<String>> {
|
||||
if should_store_payment_method_data_in_vault(
|
||||
&state.conf.temp_locker_enable_config,
|
||||
@ -1503,6 +1520,7 @@ pub async fn store_payment_method_data_in_vault(
|
||||
payment_intent,
|
||||
payment_attempt,
|
||||
payment_method,
|
||||
merchant_key_store,
|
||||
)
|
||||
.await?;
|
||||
|
||||
|
||||
@ -123,6 +123,7 @@ pub trait Domain<F: Clone, R, Ctx: PaymentMethodRetrieve>: Send + Sync {
|
||||
state: &'a AppState,
|
||||
payment_data: &mut PaymentData<F>,
|
||||
storage_scheme: enums::MerchantStorageScheme,
|
||||
merchant_key_store: &domain::MerchantKeyStore,
|
||||
) -> RouterResult<(
|
||||
BoxedOperation<'a, F, R, Ctx>,
|
||||
Option<api::PaymentMethodData>,
|
||||
@ -233,11 +234,12 @@ where
|
||||
state: &'a AppState,
|
||||
payment_data: &mut PaymentData<F>,
|
||||
_storage_scheme: enums::MerchantStorageScheme,
|
||||
merchant_key_store: &domain::MerchantKeyStore,
|
||||
) -> RouterResult<(
|
||||
BoxedOperation<'a, F, api::PaymentsRetrieveRequest, Ctx>,
|
||||
Option<api::PaymentMethodData>,
|
||||
)> {
|
||||
helpers::make_pm_data(Box::new(self), state, payment_data).await
|
||||
helpers::make_pm_data(Box::new(self), state, payment_data, merchant_key_store).await
|
||||
}
|
||||
}
|
||||
|
||||
@ -282,6 +284,7 @@ where
|
||||
_state: &'a AppState,
|
||||
_payment_data: &mut PaymentData<F>,
|
||||
_storage_scheme: enums::MerchantStorageScheme,
|
||||
_merchant_key_store: &domain::MerchantKeyStore,
|
||||
) -> RouterResult<(
|
||||
BoxedOperation<'a, F, api::PaymentsCaptureRequest, Ctx>,
|
||||
Option<api::PaymentMethodData>,
|
||||
@ -343,6 +346,7 @@ where
|
||||
_state: &'a AppState,
|
||||
_payment_data: &mut PaymentData<F>,
|
||||
_storage_scheme: enums::MerchantStorageScheme,
|
||||
_merchant_key_store: &domain::MerchantKeyStore,
|
||||
) -> RouterResult<(
|
||||
BoxedOperation<'a, F, api::PaymentsCancelRequest, Ctx>,
|
||||
Option<api::PaymentMethodData>,
|
||||
@ -394,6 +398,7 @@ where
|
||||
_state: &'a AppState,
|
||||
_payment_data: &mut PaymentData<F>,
|
||||
_storage_scheme: enums::MerchantStorageScheme,
|
||||
_merchant_key_store: &domain::MerchantKeyStore,
|
||||
) -> RouterResult<(
|
||||
BoxedOperation<'a, F, api::PaymentsRejectRequest, Ctx>,
|
||||
Option<api::PaymentMethodData>,
|
||||
|
||||
@ -88,6 +88,7 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve>
|
||||
request,
|
||||
mandate_type.clone(),
|
||||
merchant_account,
|
||||
key_store,
|
||||
)
|
||||
.await?;
|
||||
|
||||
@ -299,12 +300,13 @@ impl<F: Clone + Send, Ctx: PaymentMethodRetrieve> Domain<F, api::PaymentsRequest
|
||||
state: &'a AppState,
|
||||
payment_data: &mut PaymentData<F>,
|
||||
_storage_scheme: storage_enums::MerchantStorageScheme,
|
||||
merchant_key_store: &domain::MerchantKeyStore,
|
||||
) -> RouterResult<(
|
||||
BoxedOperation<'a, F, api::PaymentsRequest, Ctx>,
|
||||
Option<api::PaymentMethodData>,
|
||||
)> {
|
||||
let (op, payment_method_data) =
|
||||
helpers::make_pm_data(Box::new(self), state, payment_data).await?;
|
||||
helpers::make_pm_data(Box::new(self), state, payment_data, merchant_key_store).await?;
|
||||
|
||||
utils::when(payment_method_data.is_none(), || {
|
||||
Err(errors::ApiErrorResponse::PaymentMethodNotFound)
|
||||
|
||||
@ -87,6 +87,7 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve>
|
||||
request,
|
||||
mandate_type.clone(),
|
||||
merchant_account,
|
||||
key_store,
|
||||
)
|
||||
.await?;
|
||||
|
||||
@ -294,12 +295,13 @@ impl<F: Clone + Send, Ctx: PaymentMethodRetrieve> Domain<F, api::PaymentsRequest
|
||||
state: &'a AppState,
|
||||
payment_data: &mut PaymentData<F>,
|
||||
_storage_scheme: storage_enums::MerchantStorageScheme,
|
||||
merchant_key_store: &domain::MerchantKeyStore,
|
||||
) -> RouterResult<(
|
||||
BoxedOperation<'a, F, api::PaymentsRequest, Ctx>,
|
||||
Option<api::PaymentMethodData>,
|
||||
)> {
|
||||
let (op, payment_method_data) =
|
||||
helpers::make_pm_data(Box::new(self), state, payment_data).await?;
|
||||
helpers::make_pm_data(Box::new(self), state, payment_data, merchant_key_store).await?;
|
||||
Ok((op, payment_method_data))
|
||||
}
|
||||
|
||||
|
||||
@ -69,6 +69,7 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve>
|
||||
request,
|
||||
mandate_type.clone(),
|
||||
merchant_account,
|
||||
key_store,
|
||||
);
|
||||
|
||||
let (mut payment_intent, mandate_details) =
|
||||
@ -423,12 +424,13 @@ impl<F: Clone + Send, Ctx: PaymentMethodRetrieve> Domain<F, api::PaymentsRequest
|
||||
state: &'a AppState,
|
||||
payment_data: &mut PaymentData<F>,
|
||||
_storage_scheme: storage_enums::MerchantStorageScheme,
|
||||
key_store: &domain::MerchantKeyStore,
|
||||
) -> RouterResult<(
|
||||
BoxedOperation<'a, F, api::PaymentsRequest, Ctx>,
|
||||
Option<api::PaymentMethodData>,
|
||||
)> {
|
||||
let (op, payment_method_data) =
|
||||
helpers::make_pm_data(Box::new(self), state, payment_data).await?;
|
||||
helpers::make_pm_data(Box::new(self), state, payment_data, key_store).await?;
|
||||
|
||||
utils::when(payment_method_data.is_none(), || {
|
||||
Err(errors::ApiErrorResponse::PaymentMethodNotFound)
|
||||
|
||||
@ -107,6 +107,7 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve>
|
||||
request,
|
||||
mandate_type,
|
||||
merchant_account,
|
||||
merchant_key_store,
|
||||
)
|
||||
.await?;
|
||||
|
||||
@ -353,11 +354,12 @@ impl<F: Clone + Send, Ctx: PaymentMethodRetrieve> Domain<F, api::PaymentsRequest
|
||||
state: &'a AppState,
|
||||
payment_data: &mut PaymentData<F>,
|
||||
_storage_scheme: enums::MerchantStorageScheme,
|
||||
merchant_key_store: &domain::MerchantKeyStore,
|
||||
) -> RouterResult<(
|
||||
BoxedOperation<'a, F, api::PaymentsRequest, Ctx>,
|
||||
Option<api::PaymentMethodData>,
|
||||
)> {
|
||||
helpers::make_pm_data(Box::new(self), state, payment_data).await
|
||||
helpers::make_pm_data(Box::new(self), state, payment_data, merchant_key_store).await
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
|
||||
@ -297,11 +297,12 @@ where
|
||||
state: &'a AppState,
|
||||
payment_data: &mut PaymentData<F>,
|
||||
_storage_scheme: storage_enums::MerchantStorageScheme,
|
||||
merchant_key_store: &domain::MerchantKeyStore,
|
||||
) -> RouterResult<(
|
||||
BoxedOperation<'a, F, api::VerifyRequest, Ctx>,
|
||||
Option<api::PaymentMethodData>,
|
||||
)> {
|
||||
helpers::make_pm_data(Box::new(self), state, payment_data).await
|
||||
helpers::make_pm_data(Box::new(self), state, payment_data, merchant_key_store).await
|
||||
}
|
||||
|
||||
async fn get_connector<'a>(
|
||||
|
||||
@ -318,6 +318,7 @@ where
|
||||
_state: &'b AppState,
|
||||
_payment_data: &mut PaymentData<F>,
|
||||
_storage_scheme: storage_enums::MerchantStorageScheme,
|
||||
_merchant_key_store: &domain::MerchantKeyStore,
|
||||
) -> RouterResult<(
|
||||
BoxedOperation<'b, F, api::PaymentsSessionRequest, Ctx>,
|
||||
Option<api::PaymentMethodData>,
|
||||
|
||||
@ -282,6 +282,7 @@ where
|
||||
state: &'a AppState,
|
||||
payment_data: &mut PaymentData<F>,
|
||||
_storage_scheme: storage_enums::MerchantStorageScheme,
|
||||
merchant_key_store: &domain::MerchantKeyStore,
|
||||
) -> RouterResult<(
|
||||
BoxedOperation<'a, F, api::PaymentsStartRequest, Ctx>,
|
||||
Option<api::PaymentMethodData>,
|
||||
@ -293,7 +294,7 @@ where
|
||||
.map(|connector_name| connector_name == *"bluesnap".to_string())
|
||||
.unwrap_or(false)
|
||||
{
|
||||
helpers::make_pm_data(Box::new(self), state, payment_data).await
|
||||
helpers::make_pm_data(Box::new(self), state, payment_data, merchant_key_store).await
|
||||
} else {
|
||||
Ok((Box::new(self), None))
|
||||
}
|
||||
|
||||
@ -95,11 +95,12 @@ impl<F: Clone + Send, Ctx: PaymentMethodRetrieve> Domain<F, api::PaymentsRequest
|
||||
state: &'a AppState,
|
||||
payment_data: &mut PaymentData<F>,
|
||||
_storage_scheme: enums::MerchantStorageScheme,
|
||||
merchant_key_store: &domain::MerchantKeyStore,
|
||||
) -> RouterResult<(
|
||||
BoxedOperation<'a, F, api::PaymentsRequest, Ctx>,
|
||||
Option<api::PaymentMethodData>,
|
||||
)> {
|
||||
helpers::make_pm_data(Box::new(self), state, payment_data).await
|
||||
helpers::make_pm_data(Box::new(self), state, payment_data, merchant_key_store).await
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
|
||||
@ -106,6 +106,7 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve>
|
||||
request,
|
||||
mandate_type.clone(),
|
||||
merchant_account,
|
||||
key_store,
|
||||
)
|
||||
.await?;
|
||||
|
||||
@ -394,11 +395,12 @@ impl<F: Clone + Send, Ctx: PaymentMethodRetrieve> Domain<F, api::PaymentsRequest
|
||||
state: &'a AppState,
|
||||
payment_data: &mut PaymentData<F>,
|
||||
_storage_scheme: storage_enums::MerchantStorageScheme,
|
||||
merchant_key_store: &domain::MerchantKeyStore,
|
||||
) -> RouterResult<(
|
||||
BoxedOperation<'a, F, api::PaymentsRequest, Ctx>,
|
||||
Option<api::PaymentMethodData>,
|
||||
)> {
|
||||
helpers::make_pm_data(Box::new(self), state, payment_data).await
|
||||
helpers::make_pm_data(Box::new(self), state, payment_data, merchant_key_store).await
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
use common_utils::{ext_traits::ValueExt, pii};
|
||||
use error_stack::{report, ResultExt};
|
||||
use masking::ExposeInterface;
|
||||
use router_env::{instrument, tracing};
|
||||
|
||||
use super::helpers;
|
||||
use crate::{
|
||||
@ -20,6 +21,7 @@ use crate::{
|
||||
utils::OptionExt,
|
||||
};
|
||||
|
||||
#[instrument(skip_all)]
|
||||
pub async fn save_payment_method<F: Clone, FData>(
|
||||
state: &AppState,
|
||||
connector: &api::ConnectorData,
|
||||
|
||||
@ -112,7 +112,7 @@ where
|
||||
|
||||
// Validate create request
|
||||
let (payout_id, payout_method_data) =
|
||||
validator::validate_create_request(&state, &merchant_account, &req).await?;
|
||||
validator::validate_create_request(&state, &merchant_account, &req, &key_store).await?;
|
||||
|
||||
// Create DB entries
|
||||
let mut payout_data = payout_create_db_entries(
|
||||
@ -403,6 +403,7 @@ pub async fn payouts_fulfill_core(
|
||||
&payout_attempt.merchant_id,
|
||||
&payout_attempt.payout_id,
|
||||
Some(&payout_data.payouts.payout_type),
|
||||
&key_store,
|
||||
)
|
||||
.await?
|
||||
.get_required_value("payout_method_data")?,
|
||||
@ -458,6 +459,7 @@ pub async fn call_connector_payout(
|
||||
&payout_attempt.merchant_id,
|
||||
&payout_attempt.payout_id,
|
||||
Some(&payouts.payout_type),
|
||||
key_store,
|
||||
)
|
||||
.await?
|
||||
.get_required_value("payout_method_data")?,
|
||||
|
||||
@ -28,6 +28,7 @@ use crate::{
|
||||
utils::{self, OptionExt},
|
||||
};
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub async fn make_payout_method_data<'a>(
|
||||
state: &'a AppState,
|
||||
payout_method_data: Option<&api::PayoutMethodData>,
|
||||
@ -36,6 +37,7 @@ pub async fn make_payout_method_data<'a>(
|
||||
merchant_id: &str,
|
||||
payout_id: &str,
|
||||
payout_type: Option<&api_enums::PayoutType>,
|
||||
merchant_key_store: &domain::MerchantKeyStore,
|
||||
) -> RouterResult<Option<api::PayoutMethodData>> {
|
||||
let db = &*state.store;
|
||||
let hyperswitch_token = if let Some(payout_token) = payout_token {
|
||||
@ -67,9 +69,11 @@ pub async fn make_payout_method_data<'a>(
|
||||
match (payout_method_data.to_owned(), hyperswitch_token) {
|
||||
// Get operation
|
||||
(None, Some(payout_token)) => {
|
||||
let (pm, supplementary_data) = vault::Vault::get_payout_method_data_from_temporary_locker(
|
||||
let (pm, supplementary_data) =
|
||||
vault::Vault::get_payout_method_data_from_temporary_locker(
|
||||
state,
|
||||
&payout_token,
|
||||
merchant_key_store,
|
||||
)
|
||||
.await
|
||||
.attach_printable(
|
||||
@ -93,6 +97,7 @@ pub async fn make_payout_method_data<'a>(
|
||||
payout_token.to_owned(),
|
||||
payout_method,
|
||||
Some(customer_id.to_owned()),
|
||||
merchant_key_store,
|
||||
)
|
||||
.await?;
|
||||
|
||||
|
||||
@ -57,6 +57,7 @@ pub async fn validate_create_request(
|
||||
state: &AppState,
|
||||
merchant_account: &domain::MerchantAccount,
|
||||
req: &payouts::PayoutCreateRequest,
|
||||
merchant_key_store: &domain::MerchantKeyStore,
|
||||
) -> RouterResult<(String, Option<payouts::PayoutMethodData>)> {
|
||||
let merchant_id = &merchant_account.merchant_id;
|
||||
|
||||
@ -103,6 +104,7 @@ pub async fn validate_create_request(
|
||||
&merchant_account.merchant_id,
|
||||
payout_id.as_ref(),
|
||||
req.payout_type.as_ref(),
|
||||
merchant_key_store,
|
||||
)
|
||||
.await?
|
||||
}
|
||||
|
||||
@ -1,12 +1,11 @@
|
||||
use api_models::enums as api_enums;
|
||||
pub use api_models::payment_methods::{
|
||||
CardDetail, CardDetailFromLocker, CardDetailsPaymentMethod, CustomerPaymentMethod,
|
||||
CustomerPaymentMethodsListResponse, DeleteTokenizeByDateRequest, DeleteTokenizeByTokenRequest,
|
||||
GetTokenizePayloadRequest, GetTokenizePayloadResponse, PaymentMethodCreate,
|
||||
PaymentMethodDeleteResponse, PaymentMethodId, PaymentMethodList, PaymentMethodListRequest,
|
||||
PaymentMethodListResponse, PaymentMethodResponse, PaymentMethodUpdate, PaymentMethodsData,
|
||||
TokenizePayloadEncrypted, TokenizePayloadRequest, TokenizedCardValue1, TokenizedCardValue2,
|
||||
TokenizedWalletValue1, TokenizedWalletValue2,
|
||||
CustomerPaymentMethodsListResponse, DeleteTokenizeByTokenRequest, GetTokenizePayloadRequest,
|
||||
GetTokenizePayloadResponse, PaymentMethodCreate, PaymentMethodDeleteResponse, PaymentMethodId,
|
||||
PaymentMethodList, PaymentMethodListRequest, PaymentMethodListResponse, PaymentMethodResponse,
|
||||
PaymentMethodUpdate, PaymentMethodsData, TokenizePayloadEncrypted, TokenizePayloadRequest,
|
||||
TokenizedCardValue1, TokenizedCardValue2, TokenizedWalletValue1, TokenizedWalletValue2,
|
||||
};
|
||||
use error_stack::report;
|
||||
|
||||
|
||||
@ -1,14 +1,13 @@
|
||||
use scheduler::consumer::workflows::ProcessTrackerWorkflow;
|
||||
|
||||
#[cfg(feature = "basilisk")]
|
||||
use crate::core::payment_methods::vault;
|
||||
use crate::{errors, logger::error, routes::AppState, types::storage};
|
||||
use crate::{
|
||||
core::payment_methods::vault, errors, logger::error, routes::AppState, types::storage,
|
||||
};
|
||||
|
||||
pub struct DeleteTokenizeDataWorkflow;
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl ProcessTrackerWorkflow<AppState> for DeleteTokenizeDataWorkflow {
|
||||
#[cfg(feature = "basilisk")]
|
||||
async fn execute_workflow<'a>(
|
||||
&'a self,
|
||||
state: &'a AppState,
|
||||
@ -17,15 +16,6 @@ impl ProcessTrackerWorkflow<AppState> for DeleteTokenizeDataWorkflow {
|
||||
Ok(vault::start_tokenize_data_workflow(state, &process).await?)
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "basilisk"))]
|
||||
async fn execute_workflow<'a>(
|
||||
&'a self,
|
||||
_state: &'a AppState,
|
||||
_process: storage::ProcessTracker,
|
||||
) -> Result<(), errors::ProcessTrackerError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn error_handler<'a>(
|
||||
&'a self,
|
||||
_state: &'a AppState,
|
||||
|
||||
Reference in New Issue
Block a user