Skip to content

Commit

Permalink
refactor(router): changed payment method token TTL to api contract ba…
Browse files Browse the repository at this point in the history
…sed config from const value (#5209)

Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
  • Loading branch information
sahkal and hyperswitch-bot[bot] authored Jul 4, 2024
1 parent 69b45ee commit 9417bc3
Show file tree
Hide file tree
Showing 20 changed files with 121 additions and 68 deletions.
10 changes: 2 additions & 8 deletions api-reference/openapi_spec.json
Original file line number Diff line number Diff line change
Expand Up @@ -6891,7 +6891,7 @@
"intent_fulfillment_time": {
"type": "integer",
"format": "int32",
"description": "Will be used to expire client secret after certain amount of time to be supplied in seconds\n(900) for 15 mins",
"description": "Will be used to determine the time till which your payment will be active once the payment session starts",
"example": 900,
"nullable": true,
"minimum": 0
Expand Down Expand Up @@ -7039,7 +7039,7 @@
"intent_fulfillment_time": {
"type": "integer",
"format": "int64",
"description": "Will be used to expire client secret after certain amount of time to be supplied in seconds\n(900) for 15 mins",
"description": "Will be used to determine the time till which your payment will be active once the payment session starts",
"example": 900,
"nullable": true
},
Expand Down Expand Up @@ -11298,12 +11298,6 @@
],
"nullable": true
},
"intent_fulfillment_time": {
"type": "integer",
"format": "int64",
"description": "Will be used to expire client secret after certain amount of time to be supplied in seconds\n(900) for 15 mins",
"nullable": true
},
"organization_id": {
"type": "string",
"description": "The organization id merchant is associated with"
Expand Down
13 changes: 3 additions & 10 deletions crates/api_models/src/admin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,10 +268,6 @@ pub struct MerchantAccountResponse {
#[schema(value_type = Option<RoutingAlgorithm>, max_length = 255, example = r#"{"type": "single", "data": "stripe" }"#)]
pub frm_routing_algorithm: Option<serde_json::Value>,

///Will be used to expire client secret after certain amount of time to be supplied in seconds
///(900) for 15 mins
pub intent_fulfillment_time: Option<i64>,

/// The organization id merchant is associated with
pub organization_id: String,

Expand Down Expand Up @@ -918,8 +914,7 @@ pub struct BusinessProfileCreate {
#[schema(value_type = Option<Object>,example = json!({"type": "single", "data": "stripe"}))]
pub routing_algorithm: Option<serde_json::Value>,

///Will be used to expire client secret after certain amount of time to be supplied in seconds
///(900) for 15 mins
/// Will be used to determine the time till which your payment will be active once the payment session starts
#[schema(example = 900)]
pub intent_fulfillment_time: Option<u32>,

Expand Down Expand Up @@ -1003,8 +998,7 @@ pub struct BusinessProfileResponse {
#[schema(value_type = Option<Object>,example = json!({"type": "single", "data": "stripe"}))]
pub routing_algorithm: Option<serde_json::Value>,

///Will be used to expire client secret after certain amount of time to be supplied in seconds
///(900) for 15 mins
/// Will be used to determine the time till which your payment will be active once the payment session starts
#[schema(example = 900)]
pub intent_fulfillment_time: Option<i64>,

Expand Down Expand Up @@ -1083,8 +1077,7 @@ pub struct BusinessProfileUpdate {
#[schema(value_type = Option<Object>,example = json!({"type": "single", "data": "stripe"}))]
pub routing_algorithm: Option<serde_json::Value>,

///Will be used to expire client secret after certain amount of time to be supplied in seconds
///(900) for 15 mins
/// Will be used to determine the time till which your payment will be active once the payment session starts
#[schema(example = 900)]
pub intent_fulfillment_time: Option<u32>,

Expand Down
3 changes: 3 additions & 0 deletions crates/common_utils/src/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ pub const DEFAULT_SDK_LAYOUT: &str = "tabs";
/// Payment intent default client secret expiry (in seconds)
pub const DEFAULT_SESSION_EXPIRY: i64 = 15 * 60;

/// Payment intent fulfillment time (in seconds)
pub const DEFAULT_INTENT_FULFILLMENT_TIME: i64 = 15 * 60;

/// Default bool for Display sdk only
pub const DEFAULT_DISPLAY_SDK_ONLY: bool = false;

Expand Down
6 changes: 6 additions & 0 deletions crates/router/src/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,12 @@ pub const MAX_SESSION_EXPIRY: u32 = 7890000;
/// Min payment session expiry
pub const MIN_SESSION_EXPIRY: u32 = 60;

/// Max payment intent fulfillment expiry
pub const MAX_INTENT_FULFILLMENT_EXPIRY: u32 = 1800;

/// Min payment intent fulfillment expiry
pub const MIN_INTENT_FULFILLMENT_EXPIRY: u32 = 60;

pub const LOCKER_HEALTH_CALL_PATH: &str = "/health";

pub const AUTHENTICATION_ID_PREFIX: &str = "authn";
Expand Down
9 changes: 9 additions & 0 deletions crates/router/src/core/admin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1519,6 +1519,11 @@ pub async fn create_business_profile(
if let Some(session_expiry) = &request.session_expiry {
helpers::validate_session_expiry(session_expiry.to_owned())?;
}

if let Some(intent_fulfillment_expiry) = &request.intent_fulfillment_time {
helpers::validate_intent_fulfillment_expiry(intent_fulfillment_expiry.to_owned())?;
}

let db = state.store.as_ref();
let key_store = db
.get_merchant_key_store_by_merchant_id(merchant_id, &db.get_master_key().to_vec().into())
Expand Down Expand Up @@ -1636,6 +1641,10 @@ pub async fn update_business_profile(
helpers::validate_session_expiry(session_expiry.to_owned())?;
}

if let Some(intent_fulfillment_expiry) = &request.intent_fulfillment_time {
helpers::validate_intent_fulfillment_expiry(intent_fulfillment_expiry.to_owned())?;
}

let webhook_details = request
.webhook_details
.as_ref()
Expand Down
5 changes: 5 additions & 0 deletions crates/router/src/core/payment_methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ pub async fn retrieve_payment_method(
payment_intent: &PaymentIntent,
payment_attempt: &PaymentAttempt,
merchant_key_store: &domain::MerchantKeyStore,
business_profile: Option<&diesel_models::business_profile::BusinessProfile>,
) -> RouterResult<(Option<payments::PaymentMethodData>, Option<String>)> {
match pm_data {
pm_opt @ Some(pm @ api::PaymentMethodData::Card(_)) => {
Expand All @@ -52,6 +53,7 @@ pub async fn retrieve_payment_method(
enums::PaymentMethod::Card,
pm,
merchant_key_store,
business_profile,
)
.await?;

Expand All @@ -74,6 +76,7 @@ pub async fn retrieve_payment_method(
enums::PaymentMethod::BankTransfer,
pm,
merchant_key_store,
business_profile,
)
.await?;

Expand All @@ -87,6 +90,7 @@ pub async fn retrieve_payment_method(
enums::PaymentMethod::Wallet,
pm,
merchant_key_store,
business_profile,
)
.await?;

Expand All @@ -100,6 +104,7 @@ pub async fn retrieve_payment_method(
enums::PaymentMethod::BankRedirect,
pm,
merchant_key_store,
business_profile,
)
.await?;

Expand Down
71 changes: 34 additions & 37 deletions crates/router/src/core/payment_methods/cards.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3504,6 +3504,31 @@ pub async fn list_customer_payment_method(
.to_not_found_response(errors::ApiErrorResponse::PaymentMethodNotFound)?;
//let mca = query::find_mca_by_merchant_id(conn, &merchant_account.merchant_id)?;
let mut customer_pms = Vec::new();

let profile_id = payment_intent
.as_ref()
.async_map(|payment_intent| async {
core_utils::get_profile_id_from_business_details(
payment_intent.business_country,
payment_intent.business_label.as_ref(),
&merchant_account,
payment_intent.profile_id.as_ref(),
db,
false,
)
.await
.attach_printable("Could not find profile id from business details")
})
.await
.transpose()?;

let business_profile = core_utils::validate_and_get_business_profile(
db,
profile_id.as_ref(),
&merchant_account.merchant_id,
)
.await?;

for pm in resp.into_iter() {
let parent_payment_method_token = generate_id(consts::ID_LENGTH, "token");

Expand Down Expand Up @@ -3652,19 +3677,23 @@ pub async fn list_customer_payment_method(
};
customer_pms.push(pma.to_owned());

let intent_created = payment_intent.as_ref().map(|intent| intent.created_at);

let redis_conn = state
.store
.get_redis_conn()
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Failed to get redis connection")?;

let intent_fulfillment_time = business_profile
.as_ref()
.and_then(|b_profile| b_profile.intent_fulfillment_time)
.unwrap_or(consts::DEFAULT_INTENT_FULFILLMENT_TIME);

ParentPaymentMethodToken::create_key_for_token((
&parent_payment_method_token,
pma.payment_method,
))
.insert(
intent_created,
intent_fulfillment_time,
payment_method_retrieval_context.hyperswitch_token_data,
state,
)
Expand All @@ -3683,18 +3712,9 @@ pub async fn list_customer_payment_method(
"pm_token_{}_{}_{}",
parent_payment_method_token, pma.payment_method, pm_metadata.0
);
let current_datetime_utc = common_utils::date_time::now();
let time_elapsed = current_datetime_utc
- payment_intent
.as_ref()
.map(|intent| intent.created_at)
.unwrap_or_else(|| current_datetime_utc);

redis_conn
.set_key_with_expiry(
&key,
pm_metadata.1,
consts::TOKEN_TTL - time_elapsed.whole_seconds(),
)
.set_key_with_expiry(&key, pm_metadata.1, intent_fulfillment_time)
.await
.change_context(errors::StorageError::KVError)
.change_context(errors::ApiErrorResponse::InternalServerError)
Expand Down Expand Up @@ -3724,29 +3744,6 @@ pub async fn list_customer_payment_method(
.await
.transpose()?;

let profile_id = payment_intent
.as_ref()
.async_map(|payment_intent| async {
crate::core::utils::get_profile_id_from_business_details(
payment_intent.business_country,
payment_intent.business_label.as_ref(),
&merchant_account,
payment_intent.profile_id.as_ref(),
db,
false,
)
.await
.attach_printable("Could not find profile id from business details")
})
.await
.transpose()?;
let business_profile = core_utils::validate_and_get_business_profile(
db,
profile_id.as_ref(),
&merchant_account.merchant_id,
)
.await?;

if let Some((payment_attempt, payment_intent, business_profile)) = payment_attempt
.zip(payment_intent)
.zip(business_profile)
Expand Down
7 changes: 7 additions & 0 deletions crates/router/src/core/payments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ where
&validate_result,
&key_store,
&customer,
Some(&business_profile),
)
.await?;

Expand Down Expand Up @@ -1437,6 +1438,7 @@ where
&merchant_connector_account,
key_store,
customer,
Some(business_profile),
)
.await?;
*payment_data = pd;
Expand Down Expand Up @@ -2297,6 +2299,7 @@ pub async fn get_connector_tokenization_action_when_confirm_true<F, Req>(
merchant_connector_account: &helpers::MerchantConnectorAccountType,
merchant_key_store: &domain::MerchantKeyStore,
customer: &Option<domain::Customer>,
business_profile: Option<&diesel_models::business_profile::BusinessProfile>,
) -> RouterResult<(PaymentData<F>, TokenizationAction)>
where
F: Send + Clone,
Expand Down Expand Up @@ -2363,6 +2366,7 @@ where
validate_result.storage_scheme,
merchant_key_store,
customer,
business_profile,
)
.await?;
payment_data.payment_method_data = payment_method_data;
Expand All @@ -2381,6 +2385,7 @@ where
validate_result.storage_scheme,
merchant_key_store,
customer,
business_profile,
)
.await?;

Expand Down Expand Up @@ -2422,6 +2427,7 @@ pub async fn tokenize_in_router_when_confirm_false_or_external_authentication<F,
validate_result: &operations::ValidateResult<'_>,
merchant_key_store: &domain::MerchantKeyStore,
customer: &Option<domain::Customer>,
business_profile: Option<&diesel_models::business_profile::BusinessProfile>,
) -> RouterResult<PaymentData<F>>
where
F: Send + Clone,
Expand All @@ -2440,6 +2446,7 @@ where
validate_result.storage_scheme,
merchant_key_store,
customer,
business_profile,
)
.await?;
payment_data.payment_method_data = payment_method_data;
Expand Down
Loading

0 comments on commit 9417bc3

Please sign in to comment.