Skip to content

Commit

Permalink
Merge branch 'main' into feat/authentication_analytics_2
Browse files Browse the repository at this point in the history
  • Loading branch information
vsrivatsa-juspay committed Apr 23, 2024
2 parents 89b407d + 589cb4c commit 26f2c05
Show file tree
Hide file tree
Showing 12 changed files with 377 additions and 88 deletions.
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,25 @@ All notable changes to HyperSwitch will be documented here.

- - -

## 2024.04.23.0

### Features

- **euclied_wasm:** [NMI] Add configs for extended 3DS ([#4422](https://github.com/juspay/hyperswitch/pull/4422)) ([`b8be10d`](https://github.com/juspay/hyperswitch/commit/b8be10de52e40d2327819d33c6c1ec40a459bdd5))
- **router:** Add poll ability in external 3ds authorization flow ([#4393](https://github.com/juspay/hyperswitch/pull/4393)) ([`4476553`](https://github.com/juspay/hyperswitch/commit/447655382bcf2fdd69a1ec6a56e5e4df8a8feef2))

### Refactors

- **wallet:** Use `billing.phone` instead of `telephone_number` ([#4329](https://github.com/juspay/hyperswitch/pull/4329)) ([`3e6bc19`](https://github.com/juspay/hyperswitch/commit/3e6bc191fd5804feface9ee1a0cb7ddbbe025569))

### Miscellaneous Tasks

- Add wasm toml configs for netcetera authnetication connector ([#4426](https://github.com/juspay/hyperswitch/pull/4426)) ([`4851da1`](https://github.com/juspay/hyperswitch/commit/4851da1595074dbb2760e76f83403e8ac9f7895f))

**Full Changelog:** [`2024.04.22.0...2024.04.23.0`](https://github.com/juspay/hyperswitch/compare/2024.04.22.0...2024.04.23.0)

- - -

## 2024.04.22.0

### Features
Expand Down
3 changes: 2 additions & 1 deletion crates/openapi/src/routes/poll.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
("poll_id" = String, Path, description = "The identifier for poll")
),
responses(
(status = 200, description = "The poll status was retrieved successfully", body = PollResponse)
(status = 200, description = "The poll status was retrieved successfully", body = PollResponse),
(status = 404, description = "Poll not found")
),
tag = "Poll",
operation_id = "Retrieve Poll Status",
Expand Down
32 changes: 32 additions & 0 deletions crates/redis_interface/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,21 @@ impl super::RedisConnectionPool {
.change_context(errors::RedisError::SetFailed)
}

pub async fn set_key_without_modifying_ttl<V>(
&self,
key: &str,
value: V,
) -> CustomResult<(), errors::RedisError>
where
V: TryInto<RedisValue> + Debug + Send + Sync,
V::Error: Into<fred::error::RedisError> + Send + Sync,
{
self.pool
.set(key, value, Some(Expiration::KEEPTTL), None, false)
.await
.change_context(errors::RedisError::SetFailed)
}

pub async fn set_multiple_keys_if_not_exist<V>(
&self,
value: V,
Expand Down Expand Up @@ -96,6 +111,23 @@ impl super::RedisConnectionPool {
self.set_key(key, serialized.as_slice()).await
}

#[instrument(level = "DEBUG", skip(self))]
pub async fn serialize_and_set_key_without_modifying_ttl<V>(
&self,
key: &str,
value: V,
) -> CustomResult<(), errors::RedisError>
where
V: serde::Serialize + Debug,
{
let serialized = value
.encode_to_vec()
.change_context(errors::RedisError::JsonSerializationFailed)?;

self.set_key_without_modifying_ttl(key, serialized.as_slice())
.await
}

#[instrument(level = "DEBUG", skip(self))]
pub async fn serialize_and_set_key_with_expiry<V>(
&self,
Expand Down
7 changes: 7 additions & 0 deletions crates/router/src/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,10 @@ pub const AUTHENTICATION_ID_PREFIX: &str = "authn";

// URL for checking the outgoing call
pub const OUTGOING_CALL_URL: &str = "https://api.stripe.com/healthcheck";

// 15 minutes = 900 seconds
pub const POLL_ID_TTL: i64 = 900;

// Default Poll Config
pub const DEFAULT_POLL_DELAY_IN_SECS: i8 = 2;
pub const DEFAULT_POLL_FREQUENCY: i8 = 5;
45 changes: 39 additions & 6 deletions crates/router/src/core/authentication.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@ use api_models::payments;
use common_enums::Currency;
use common_utils::{errors::CustomResult, ext_traits::ValueExt};
use error_stack::{report, ResultExt};
use masking::PeekInterface;
use masking::{ExposeInterface, PeekInterface};

use super::errors;
use crate::{
consts::POLL_ID_TTL,
core::{errors::ApiErrorResponse, payments as payments_core},
routes::AppState,
types::{self as core_types, api, authentication::AuthenticationResponseData, storage},
utils::OptionExt,
utils::{check_if_pull_mechanism_for_external_3ds_enabled_from_connector_metadata, OptionExt},
};

#[allow(clippy::too_many_arguments)]
Expand Down Expand Up @@ -117,12 +118,19 @@ pub async fn perform_post_authentication<F: Clone + Send>(
authentication,
should_continue_confirm_transaction,
} => {
// let (auth, authentication_data) = authentication;
let is_pull_mechanism_enabled =
check_if_pull_mechanism_for_external_3ds_enabled_from_connector_metadata(
merchant_connector_account
.get_metadata()
.map(|metadata| metadata.expose()),
);
let authentication_status =
if !authentication.authentication_status.is_terminal_status() {
if !authentication.authentication_status.is_terminal_status()
&& is_pull_mechanism_enabled
{
let router_data = transformers::construct_post_authentication_router_data(
authentication_connector.clone(),
business_profile,
business_profile.clone(),
merchant_connector_account,
&authentication,
)?;
Expand All @@ -132,7 +140,7 @@ pub async fn perform_post_authentication<F: Clone + Send>(
let updated_authentication = utils::update_trackers(
state,
router_data,
authentication,
authentication.clone(),
payment_data.token.clone(),
None,
)
Expand All @@ -147,6 +155,31 @@ pub async fn perform_post_authentication<F: Clone + Send>(
if !(authentication_status == api_models::enums::AuthenticationStatus::Success) {
*should_continue_confirm_transaction = false;
}
// When authentication status is non-terminal, Set poll_id in redis to allow the fetch status of poll through retrieve_poll_status api from client
if !authentication_status.is_terminal_status() {
let req_poll_id = super::utils::get_external_authentication_request_poll_id(
&payment_data.payment_intent.payment_id,
);
let poll_id = super::utils::get_poll_id(
business_profile.merchant_id.clone(),
req_poll_id.clone(),
);
let redis_conn = state
.store
.get_redis_conn()
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Failed to get redis connection")?;
redis_conn
.set_key_with_expiry(
&poll_id,
api_models::poll::PollStatus::Pending.to_string(),
POLL_ID_TTL,
)
.await
.change_context(errors::StorageError::KVError)
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Failed to add poll_id in redis")?;
}
}
types::PostAuthenthenticationFlowInput::PaymentMethodAuthNFlow { other_fields: _ } => {
// todo!("Payment method post authN operation");
Expand Down

0 comments on commit 26f2c05

Please sign in to comment.