From 3e8b3e5d92705c7d33f606d37080c041dec545f7 Mon Sep 17 00:00:00 2001 From: Shankar Singh C Date: Sun, 22 Dec 2024 13:50:57 +0530 Subject: [PATCH] address pr comments --- .../api-reference/relay/relay--retrieve.mdx | 3 - crates/common_enums/src/enums.rs | 3 +- crates/common_utils/src/id_type/relay.rs | 11 -- crates/diesel_models/src/query/relay.rs | 10 +- crates/diesel_models/src/relay.rs | 77 +++++---- crates/hyperswitch_domain_models/src/relay.rs | 35 ++++- crates/router/src/consts.rs | 2 - crates/router/src/core/relay.rs | 146 +----------------- crates/router/src/core/relay/utils.rs | 139 +++++++++++++++++ crates/router/src/routes/app.rs | 5 +- crates/router/src/routes/lock_utils.rs | 4 +- crates/router/src/routes/relay.rs | 2 +- crates/router/src/services/authentication.rs | 2 +- 13 files changed, 221 insertions(+), 218 deletions(-) delete mode 100644 api-reference/api-reference/relay/relay--retrieve.mdx create mode 100644 crates/router/src/core/relay/utils.rs diff --git a/api-reference/api-reference/relay/relay--retrieve.mdx b/api-reference/api-reference/relay/relay--retrieve.mdx deleted file mode 100644 index d65e62d31d74..000000000000 --- a/api-reference/api-reference/relay/relay--retrieve.mdx +++ /dev/null @@ -1,3 +0,0 @@ ---- -openapi: openapi_spec get /relay/{relay_id} ---- \ No newline at end of file diff --git a/crates/common_enums/src/enums.rs b/crates/common_enums/src/enums.rs index 1cf2a58fc1c7..193998c3fd1c 100644 --- a/crates/common_enums/src/enums.rs +++ b/crates/common_enums/src/enums.rs @@ -3422,10 +3422,9 @@ impl From for TransactionType { impl From for RelayStatus { fn from(refund_status: RefundStatus) -> Self { match refund_status { - RefundStatus::Failure => Self::Failure, + RefundStatus::Failure | RefundStatus::TransactionFailure => Self::Failure, RefundStatus::ManualReview | RefundStatus::Pending => Self::Pending, RefundStatus::Success => Self::Success, - RefundStatus::TransactionFailure => Self::Failure, } } } diff --git a/crates/common_utils/src/id_type/relay.rs b/crates/common_utils/src/id_type/relay.rs index c818671e0e5e..3ad64729fb73 100644 --- a/crates/common_utils/src/id_type/relay.rs +++ b/crates/common_utils/src/id_type/relay.rs @@ -1,5 +1,3 @@ -use std::str::FromStr; - crate::id_type!( RelayId, "A type for relay_id that can be used for relay ids" @@ -13,12 +11,3 @@ crate::impl_queryable_id_type!(RelayId); crate::impl_to_sql_from_sql_id_type!(RelayId); crate::impl_debug_id_type!(RelayId); - -impl FromStr for RelayId { - type Err = error_stack::Report; - - fn from_str(s: &str) -> Result { - let cow_string = std::borrow::Cow::Owned(s.to_string()); - Self::try_from(cow_string) - } -} diff --git a/crates/diesel_models/src/query/relay.rs b/crates/diesel_models/src/query/relay.rs index 77d2a90f6a53..28ede3cd61a8 100644 --- a/crates/diesel_models/src/query/relay.rs +++ b/crates/diesel_models/src/query/relay.rs @@ -1,4 +1,4 @@ -use diesel::{associations::HasTable, BoolExpressionMethods, ExpressionMethods}; +use diesel::{associations::HasTable, ExpressionMethods}; use super::generics; use crate::{ @@ -25,13 +25,7 @@ impl Relay { _, _, _, - >( - conn, - dsl::id - .eq(self.id.to_owned()) - .and(dsl::merchant_id.eq(self.merchant_id.to_owned())), - relay, - ) + >(conn, dsl::id.eq(self.id.to_owned()), relay) .await { Err(error) => match error.current_context() { diff --git a/crates/diesel_models/src/relay.rs b/crates/diesel_models/src/relay.rs index d4e4c2900772..28b61546cb97 100644 --- a/crates/diesel_models/src/relay.rs +++ b/crates/diesel_models/src/relay.rs @@ -1,9 +1,8 @@ +use crate::{enums as storage_enums, schema::relay}; use common_utils::pii; use diesel::{AsChangeset, Identifiable, Insertable, Queryable, Selectable}; use time::PrimitiveDateTime; -use crate::{enums as storage_enums, schema::relay}; - #[derive( Clone, Debug, @@ -66,17 +65,17 @@ pub struct RelayNew { pub response_data: Option, } -#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] -pub enum RelayUpdate { - ErrorUpdate { - error_code: String, - error_reason: String, - }, - StatusUpdate { - connector_reference_id: Option, - status: storage_enums::RelayStatus, - }, -} +// #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] +// pub enum RelayUpdate { +// ErrorUpdate { +// error_code: String, +// error_reason: String, +// }, +// StatusUpdate { +// connector_reference_id: Option, +// status: storage_enums::RelayStatus, +// }, +// } #[derive(Clone, Debug, AsChangeset, router_derive::DebugAsDisplay)] #[table_name = "relay"] @@ -88,29 +87,29 @@ pub struct RelayUpdateInternal { pub modified_at: PrimitiveDateTime, } -impl From for RelayUpdateInternal { - fn from(value: RelayUpdate) -> Self { - match value { - RelayUpdate::ErrorUpdate { - error_code, - error_reason, - } => Self { - error_code: Some(error_code), - error_reason: Some(error_reason), - connector_reference_id: None, - status: None, - modified_at: common_utils::date_time::now(), - }, - RelayUpdate::StatusUpdate { - connector_reference_id, - status, - } => Self { - connector_reference_id, - status: Some(status), - error_code: None, - error_reason: None, - modified_at: common_utils::date_time::now(), - }, - } - } -} +// impl From for RelayUpdateInternal { +// fn from(value: RelayUpdate) -> Self { +// match value { +// RelayUpdate::ErrorUpdate { +// error_code, +// error_reason, +// } => Self { +// error_code: Some(error_code), +// error_reason: Some(error_reason), +// connector_reference_id: None, +// status: None, +// modified_at: common_utils::date_time::now(), +// }, +// RelayUpdate::StatusUpdate { +// connector_reference_id, +// status, +// } => Self { +// connector_reference_id, +// status: Some(status), +// error_code: None, +// error_reason: None, +// modified_at: common_utils::date_time::now(), +// }, +// } +// } +// } diff --git a/crates/hyperswitch_domain_models/src/relay.rs b/crates/hyperswitch_domain_models/src/relay.rs index bd3fac9038e7..0cf2e294306e 100644 --- a/crates/hyperswitch_domain_models/src/relay.rs +++ b/crates/hyperswitch_domain_models/src/relay.rs @@ -44,11 +44,13 @@ impl From for api_models::relay::RelayResponse { ); let data = value.request_data.map(|relay_data| match relay_data { - RelayData::Refund(relay_refund_request) => api_models::relay::RelayRefundRequest { - amount: relay_refund_request.amount, - currency: relay_refund_request.currency, - reason: relay_refund_request.reason, - }, + RelayData::Refund(relay_refund_request) => { + api_models::relay::RelayData::Refund(api_models::relay::RelayRefundRequest { + amount: relay_refund_request.amount, + currency: relay_refund_request.currency, + reason: relay_refund_request.reason, + }) + } }); Self { id: value.id, @@ -58,7 +60,7 @@ impl From for api_models::relay::RelayResponse { connector_id: value.connector_id, profile_id: value.profile_id, relay_type: value.relay_type, - data: data.map(api_models::relay::RelayData::Refund), + data: data, connector_reference_id: value.connector_reference_id, } } @@ -67,11 +69,11 @@ impl From for api_models::relay::RelayResponse { #[derive(Debug, Clone, Deserialize, Serialize)] #[serde(rename_all = "snake_case", untagged)] pub enum RelayData { - Refund(RelayRefundRequest), + Refund(RelayRefundData), } #[derive(Debug, Clone, Deserialize, Serialize)] -pub struct RelayRefundRequest { +pub struct RelayRefundData { pub amount: MinorUnit, pub currency: enums::Currency, pub reason: Option, @@ -90,6 +92,23 @@ pub enum RelayUpdate { }, } +// impl From> for RelayUpdate { +// fn from(value: Result) -> Self { +// match value.response { +// Err(error) => hyperswitch_domain_models::relay::RelayUpdate::ErrorUpdate { +// error_code: error.code, +// error_reason: error.message, +// status: common_enums::RelayStatus::Failure, +// }, +// Ok(response) => hyperswitch_domain_models::relay::RelayUpdate::StatusUpdate { +// connector_reference_id: Some(response.connector_refund_id), +// status: common_enums::RelayStatus::from(response.refund_status), +// }, +// } +// } +// } + + impl From for RelayUpdateInternal { fn from(value: RelayUpdate) -> Self { match value { diff --git a/crates/router/src/consts.rs b/crates/router/src/consts.rs index 04b837528a41..823f0a4bf04f 100644 --- a/crates/router/src/consts.rs +++ b/crates/router/src/consts.rs @@ -37,8 +37,6 @@ pub const FINGERPRINT_SECRET_LENGTH: usize = 64; pub const DEFAULT_LIST_API_LIMIT: u16 = 10; -pub const X_PROFILE_ID: &str = "X-Profile-Id"; - // String literals pub(crate) const UNSUPPORTED_ERROR_MESSAGE: &str = "Unsupported response type"; pub(crate) const LOW_BALANCE_ERROR_MESSAGE: &str = "Insufficient balance in the payment method"; diff --git a/crates/router/src/core/relay.rs b/crates/router/src/core/relay.rs index 83225273e37f..b0675d801e29 100644 --- a/crates/router/src/core/relay.rs +++ b/crates/router/src/core/relay.rs @@ -1,5 +1,3 @@ -use std::str::FromStr; - use api_models::relay as relay_models; use common_utils::{ self, @@ -7,7 +5,6 @@ use common_utils::{ id_type::{self, GenerateId}, }; use error_stack::ResultExt; -use hyperswitch_domain_models::types; use super::errors::{self, ConnectorErrorExt, RouterResponse, RouterResult, StorageErrorExt}; use crate::{ @@ -21,9 +18,7 @@ use crate::{ }, }; -const IRRELEVANT_PAYMENT_INTENT_ID: &str = "irrelevant_payment_intent_id"; - -const IRRELEVANT_PAYMENT_ATTEMPT_ID: &str = "irrelevant_payment_attempt_id"; +pub mod utils; pub async fn relay( state: SessionState, @@ -111,17 +106,15 @@ pub async fn relay_refund( hyperswitch_domain_models::router_response_types::RefundsResponseData, > = connector_data.connector.get_connector_integration(); - let relay_id = id_type::RelayId::generate(); - - let relay_domain = - get_relay_domain_model(req, merchant_account.get_id(), profile.get_id(), &relay_id); + let relay_domain = get_relay_domain_model(req, merchant_account.get_id(), profile.get_id()); let relay_record = db .insert_relay(key_manager_state, &key_store, relay_domain) .await - .change_context(errors::ApiErrorResponse::InternalServerError)?; + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Failed to insert a relay record in db")?; - let router_data = construct_relay_refund_router_data( + let router_data = utils::construct_relay_refund_router_data( &state, &connector_account.connector_name, merchant_id, @@ -162,131 +155,6 @@ pub async fn relay_refund( Ok(response) } -pub async fn construct_relay_refund_router_data<'a, F>( - state: &'a SessionState, - connector_name: &str, - merchant_id: &id_type::MerchantId, - connector_account: &domain::MerchantConnectorAccount, - relay_record: &hyperswitch_domain_models::relay::Relay, -) -> RouterResult> { - let connector_auth_type = connector_account - .get_connector_account_details() - .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable("Failed while parsing value for ConnectorAuthType")?; - - let webhook_url = Some(payments::helpers::create_webhook_url( - &state.base_url.clone(), - merchant_id, - connector_name, - )); - - let supported_connector = &state - .conf - .multiple_api_version_supported_connectors - .supported_connectors; - - let connector_enum = api_models::enums::Connector::from_str(connector_name) - .change_context(errors::ConnectorError::InvalidConnectorName) - .change_context(errors::ApiErrorResponse::InvalidDataValue { - field_name: "connector", - }) - .attach_printable_lazy(|| format!("unable to parse connector name {connector_name:?}"))?; - - let connector_api_version = if supported_connector.contains(&connector_enum) { - state - .store - .find_config_by_key(&format!("connector_api_version_{connector_name}")) - .await - .map(|value| value.config) - .ok() - } else { - None - }; - - let hyperswitch_domain_models::relay::RelayData::Refund(relay_refund_data) = relay_record - .request_data - .clone() - .get_required_value("refund relay data") - .change_context(errors::ApiErrorResponse::InternalServerError)?; - - let relay_id_string = relay_record.id.get_string_repr().to_string(); - - let router_data = hyperswitch_domain_models::router_data::RouterData { - flow: std::marker::PhantomData, - merchant_id: merchant_id.clone(), - customer_id: None, - connector: connector_name.to_string(), - payment_id: IRRELEVANT_PAYMENT_INTENT_ID.to_string(), - attempt_id: IRRELEVANT_PAYMENT_ATTEMPT_ID.to_string(), - status: common_enums::AttemptStatus::Charged, - payment_method: common_enums::PaymentMethod::default(), - connector_auth_type, - description: None, - return_url: None, - address: hyperswitch_domain_models::payment_address::PaymentAddress::default(), - auth_type: common_enums::AuthenticationType::default(), - connector_meta_data: None, - connector_wallets_details: None, - amount_captured: None, - payment_method_status: None, - minor_amount_captured: None, - request: hyperswitch_domain_models::router_request_types::RefundsData { - refund_id: relay_id_string.clone(), - connector_transaction_id: relay_record.connector_resource_id.clone(), - refund_amount: relay_refund_data.amount.get_amount_as_i64(), - minor_refund_amount: relay_refund_data.amount, - currency: relay_refund_data.currency, - payment_amount: relay_refund_data.amount.get_amount_as_i64(), - minor_payment_amount: relay_refund_data.amount, - webhook_url, - connector_metadata: None, - reason: relay_refund_data.reason, - connector_refund_id: relay_record.connector_reference_id.clone(), - browser_info: None, - split_refunds: None, - integrity_object: None, - refund_status: common_enums::RefundStatus::from(relay_record.status), - }, - - response: Ok( - hyperswitch_domain_models::router_response_types::RefundsResponseData { - connector_refund_id: relay_record.connector_resource_id.clone(), - refund_status: common_enums::RefundStatus::default(), - }, - ), - access_token: None, - session_token: None, - reference_id: None, - payment_method_token: None, - connector_customer: None, - recurring_mandate_payment_data: None, - preprocessing_id: None, - connector_request_reference_id: relay_id_string.clone(), - #[cfg(feature = "payouts")] - payout_method_data: None, - #[cfg(feature = "payouts")] - quote_id: None, - test_mode: connector_account.test_mode, - payment_method_balance: None, - connector_api_version, - connector_http_status_code: None, - external_latency: None, - apple_pay_flow: None, - frm_metadata: None, - refund_id: Some(relay_id_string), - dispute_id: None, - connector_response: None, - integrity_check: Ok(()), - additional_merchant_data: None, - header_payload: None, - connector_mandate_request_reference_id: None, - authentication_id: None, - psd2_sca_exemption_type: None, - }; - - Ok(router_data) -} - // validate relay request pub fn validate_relay_refund_request( relay_request: &relay_models::RelayRequest, @@ -318,8 +186,8 @@ pub fn get_relay_domain_model( relay_request: &relay_models::RelayRequest, merchant_id: &id_type::MerchantId, profile_id: &id_type::ProfileId, - relay_id: &id_type::RelayId, ) -> hyperswitch_domain_models::relay::Relay { + let relay_id = id_type::RelayId::generate(); hyperswitch_domain_models::relay::Relay { id: relay_id.clone(), connector_resource_id: relay_request.connector_resource_id.clone(), @@ -342,7 +210,7 @@ impl ForeignFrom for hyperswitch_domain_models::relay:: fn foreign_from(relay: relay_models::RelayData) -> Self { match relay { relay_models::RelayData::Refund(relay_refund_request) => { - Self::Refund(hyperswitch_domain_models::relay::RelayRefundRequest { + Self::Refund(hyperswitch_domain_models::relay::RelayRefundData { amount: relay_refund_request.amount, currency: relay_refund_request.currency, reason: relay_refund_request.reason, diff --git a/crates/router/src/core/relay/utils.rs b/crates/router/src/core/relay/utils.rs new file mode 100644 index 000000000000..453b712a79cc --- /dev/null +++ b/crates/router/src/core/relay/utils.rs @@ -0,0 +1,139 @@ +use common_utils::{ext_traits::OptionExt, id_type}; +use error_stack::ResultExt; + +use crate::{ + core::payments, + db::{ + domain, + errors::{self, RouterResult}, + }, + routes::SessionState, +}; +use std::str::FromStr; + +use hyperswitch_domain_models::{router_data::ErrorResponse, types}; + +const IRRELEVANT_PAYMENT_INTENT_ID: &str = "irrelevant_payment_intent_id"; + +const IRRELEVANT_PAYMENT_ATTEMPT_ID: &str = "irrelevant_payment_attempt_id"; + +pub async fn construct_relay_refund_router_data<'a, F>( + state: &'a SessionState, + connector_name: &str, + merchant_id: &id_type::MerchantId, + connector_account: &domain::MerchantConnectorAccount, + relay_record: &hyperswitch_domain_models::relay::Relay, +) -> RouterResult> { + let connector_auth_type = connector_account + .get_connector_account_details() + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Failed while parsing value for ConnectorAuthType")?; + + let webhook_url = Some(payments::helpers::create_webhook_url( + &state.base_url.clone(), + merchant_id, + connector_name, + )); + + let supported_connector = &state + .conf + .multiple_api_version_supported_connectors + .supported_connectors; + + let connector_enum = api_models::enums::Connector::from_str(connector_name) + .change_context(errors::ConnectorError::InvalidConnectorName) + .change_context(errors::ApiErrorResponse::InvalidDataValue { + field_name: "connector", + }) + .attach_printable_lazy(|| format!("unable to parse connector name {connector_name:?}"))?; + + let connector_api_version = if supported_connector.contains(&connector_enum) { + state + .store + .find_config_by_key(&format!("connector_api_version_{connector_name}")) + .await + .map(|value| value.config) + .ok() + } else { + None + }; + + let hyperswitch_domain_models::relay::RelayData::Refund(relay_refund_data) = relay_record + .request_data + .clone() + .get_required_value("refund relay data") + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Failed to obtain relay data to construct relay refund data")?; + + let relay_id_string = relay_record.id.get_string_repr().to_string(); + + let router_data = hyperswitch_domain_models::router_data::RouterData { + flow: std::marker::PhantomData, + merchant_id: merchant_id.clone(), + customer_id: None, + connector: connector_name.to_string(), + payment_id: IRRELEVANT_PAYMENT_INTENT_ID.to_string(), + attempt_id: IRRELEVANT_PAYMENT_ATTEMPT_ID.to_string(), + status: common_enums::AttemptStatus::Charged, + payment_method: common_enums::PaymentMethod::default(), + connector_auth_type, + description: None, + return_url: None, + address: hyperswitch_domain_models::payment_address::PaymentAddress::default(), + auth_type: common_enums::AuthenticationType::default(), + connector_meta_data: None, + connector_wallets_details: None, + amount_captured: None, + payment_method_status: None, + minor_amount_captured: None, + request: hyperswitch_domain_models::router_request_types::RefundsData { + refund_id: relay_id_string.clone(), + connector_transaction_id: relay_record.connector_resource_id.clone(), + refund_amount: relay_refund_data.amount.get_amount_as_i64(), + minor_refund_amount: relay_refund_data.amount, + currency: relay_refund_data.currency, + payment_amount: relay_refund_data.amount.get_amount_as_i64(), + minor_payment_amount: relay_refund_data.amount, + webhook_url, + connector_metadata: None, + reason: relay_refund_data.reason, + connector_refund_id: relay_record.connector_reference_id.clone(), + browser_info: None, + split_refunds: None, + integrity_object: None, + refund_status: common_enums::RefundStatus::from(relay_record.status), + }, + + response: Err(ErrorResponse::default()), + access_token: None, + session_token: None, + reference_id: None, + payment_method_token: None, + connector_customer: None, + recurring_mandate_payment_data: None, + preprocessing_id: None, + connector_request_reference_id: relay_id_string.clone(), + #[cfg(feature = "payouts")] + payout_method_data: None, + #[cfg(feature = "payouts")] + quote_id: None, + test_mode: connector_account.test_mode, + payment_method_balance: None, + connector_api_version, + connector_http_status_code: None, + external_latency: None, + apple_pay_flow: None, + frm_metadata: None, + refund_id: Some(relay_id_string), + dispute_id: None, + connector_response: None, + integrity_check: Ok(()), + additional_merchant_data: None, + header_payload: None, + connector_mandate_request_reference_id: None, + authentication_id: None, + psd2_sca_exemption_type: None, + }; + + Ok(router_data) +} diff --git a/crates/router/src/routes/app.rs b/crates/router/src/routes/app.rs index 03847bd58d12..66adf94ad291 100644 --- a/crates/router/src/routes/app.rs +++ b/crates/router/src/routes/app.rs @@ -54,8 +54,7 @@ use super::verification::{apple_pay_merchant_registration, retrieve_apple_pay_ve #[cfg(feature = "oltp")] use super::webhooks::*; use super::{ - admin, api_keys, cache::*, connector_onboarding, disputes, files, gsm, health::*, profiles, - user, user_role, + admin, api_keys, cache::*, connector_onboarding, disputes, files, gsm, health::*, profiles, relay, user, user_role }; #[cfg(feature = "v1")] use super::{apple_pay_certificates_migration, blocklist, payment_link, webhook_events}; @@ -592,7 +591,7 @@ impl Relay { pub fn server(state: AppState) -> Scope { web::scope("/relay") .app_data(web::Data::new(state)) - .service(web::resource("").route(web::post().to(super::relay::relay))) + .service(web::resource("").route(web::post().to(relay::relay))) } } diff --git a/crates/router/src/routes/lock_utils.rs b/crates/router/src/routes/lock_utils.rs index 887df796536c..3b468a0a68fe 100644 --- a/crates/router/src/routes/lock_utils.rs +++ b/crates/router/src/routes/lock_utils.rs @@ -37,6 +37,7 @@ pub enum ApiIdentifier { Recon, Poll, ApplePayCertificatesMigration, + Relay, } impl From for ApiIdentifier { @@ -164,7 +165,8 @@ impl From for ApiIdentifier { | Flow::RefundsFilters | Flow::RefundsAggregate | Flow::RefundsManualUpdate - | Flow::Relay => Self::Refunds, + => Self::Refunds, + Flow::Relay => Self::Relay, Flow::FrmFulfillment | Flow::IncomingWebhookReceive diff --git a/crates/router/src/routes/relay.rs b/crates/router/src/routes/relay.rs index 09d4aa6ac808..fb1633398fd9 100644 --- a/crates/router/src/routes/relay.rs +++ b/crates/router/src/routes/relay.rs @@ -8,7 +8,7 @@ use crate::{ }; #[instrument(skip_all, fields(flow = ?Flow::Relay))] -#[cfg(all(feature = "olap", feature = "v1"))] +#[cfg(all(feature = "oltp", feature = "v1"))] pub async fn relay( state: web::Data, req: actix_web::HttpRequest, diff --git a/crates/router/src/services/authentication.rs b/crates/router/src/services/authentication.rs index 7f999dff3da7..88608316640a 100644 --- a/crates/router/src/services/authentication.rs +++ b/crates/router/src/services/authentication.rs @@ -541,7 +541,7 @@ where .attach_printable("Failed to fetch merchant key store for the merchant id")?; let profile_id = - get_header_value_by_key(consts::X_PROFILE_ID.to_string(), request_headers)? + get_header_value_by_key(headers::X_PROFILE_ID.to_string(), request_headers)? .map(id_type::ProfileId::from_str) .transpose() .change_context(errors::ValidationError::IncorrectValueProvided {