Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(router): changed payment method token TTL to api contract based config from const value #5115

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 2 additions & 8 deletions api-reference/openapi_spec.json
Original file line number Diff line number Diff line change
Expand Up @@ -6902,7 +6902,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 @@ -7050,7 +7050,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 @@ -11321,12 +11321,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 @@ -920,8 +916,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 @@ -1005,8 +1000,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 @@ -1085,8 +1079,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 @@ -3511,6 +3511,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 @@ -3659,19 +3684,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 @@ -3690,18 +3719,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 @@ -3731,29 +3751,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 @@ -1440,6 +1441,7 @@ where
&merchant_connector_account,
key_store,
customer,
Some(business_profile),
)
.await?;
*payment_data = pd;
Expand Down Expand Up @@ -2306,6 +2308,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 @@ -2372,6 +2375,7 @@ where
validate_result.storage_scheme,
merchant_key_store,
customer,
business_profile,
)
.await?;
payment_data.payment_method_data = payment_method_data;
Expand All @@ -2390,6 +2394,7 @@ where
validate_result.storage_scheme,
merchant_key_store,
customer,
business_profile,
)
.await?;

Expand Down Expand Up @@ -2431,6 +2436,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 @@ -2449,6 +2455,7 @@ where
validate_result.storage_scheme,
merchant_key_store,
customer,
business_profile,
)
.await?;
payment_data.payment_method_data = payment_method_data;
Expand Down
Loading
Loading