diff --git a/CHANGELOG.md b/CHANGELOG.md index 0aa00381bf62..412b42afc2eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,25 @@ All notable changes to HyperSwitch will be documented here. - - - +## 1.75.0 (2023-11-09) + +### Features + +- **events:** Add extracted fields based on req/res types ([#2795](https://github.com/juspay/hyperswitch/pull/2795)) ([`8985794`](https://github.com/juspay/hyperswitch/commit/89857941b09c5fbe0f3e7d5b4f908bb144ae162d)) +- **router:** + - Added merchant custom name support for payment link ([#2685](https://github.com/juspay/hyperswitch/pull/2685)) ([`8b15189`](https://github.com/juspay/hyperswitch/commit/8b151898dc0d8eefe5ed2bbdafe59e8f58b4698c)) + - Add `gateway_status_map` CRUD APIs ([#2809](https://github.com/juspay/hyperswitch/pull/2809)) ([`5c9e235`](https://github.com/juspay/hyperswitch/commit/5c9e235bd30dd3e03d086a83613edfcc62b2ead2)) + +### Bug Fixes + +- **analytics:** Added hs latency to api event for paymentconfirm call ([#2787](https://github.com/juspay/hyperswitch/pull/2787)) ([`aab8f60`](https://github.com/juspay/hyperswitch/commit/aab8f6035c16ca19009f8f1e0db688c17bc0b2b6)) +- [mollie] locale validation irrespective of auth type ([#2814](https://github.com/juspay/hyperswitch/pull/2814)) ([`25a73c2`](https://github.com/juspay/hyperswitch/commit/25a73c29a4c4715a54862dd6a28c875fd3752f63)) + +**Full Changelog:** [`v1.74.0...v1.75.0`](https://github.com/juspay/hyperswitch/compare/v1.74.0...v1.75.0) + +- - - + + ## 1.74.0 (2023-11-08) ### Features diff --git a/README.md b/README.md index e6e9baa07f7d..129a0512d4a0 100644 --- a/README.md +++ b/README.md @@ -64,13 +64,16 @@ The fastest and easiest way to try hyperswitch is via our CDK scripts 1. Click on the following button for a quick standalone deployment on AWS, suitable for prototyping. No code or setup is required in your system and the deployment is covered within the AWS free-tier setup. - +   Click here if you have not bootstrapped your region before deploying + +   + 2. Sign-in to your AWS console. 3. Follow the instructions provided on the console to successfully deploy Hyperswitch -For an early access to the production-ready setup fill this Early Access Form +For an early access to the production-ready setup fill this Early Access Form

🔌 Fast Integration for Stripe Users

diff --git a/crates/api_models/src/events.rs b/crates/api_models/src/events.rs index 78f34b4b87fa..23e7c9dc706a 100644 --- a/crates/api_models/src/events.rs +++ b/crates/api_models/src/events.rs @@ -1,4 +1,5 @@ pub mod customer; +pub mod gsm; pub mod payment; #[cfg(feature = "payouts")] pub mod payouts; diff --git a/crates/api_models/src/events/gsm.rs b/crates/api_models/src/events/gsm.rs new file mode 100644 index 000000000000..d984ae1ff698 --- /dev/null +++ b/crates/api_models/src/events/gsm.rs @@ -0,0 +1,33 @@ +use common_utils::events::{ApiEventMetric, ApiEventsType}; + +use crate::gsm; + +impl ApiEventMetric for gsm::GsmCreateRequest { + fn get_api_event_type(&self) -> Option { + Some(ApiEventsType::Gsm) + } +} + +impl ApiEventMetric for gsm::GsmUpdateRequest { + fn get_api_event_type(&self) -> Option { + Some(ApiEventsType::Gsm) + } +} + +impl ApiEventMetric for gsm::GsmRetrieveRequest { + fn get_api_event_type(&self) -> Option { + Some(ApiEventsType::Gsm) + } +} + +impl ApiEventMetric for gsm::GsmDeleteRequest { + fn get_api_event_type(&self) -> Option { + Some(ApiEventsType::Gsm) + } +} + +impl ApiEventMetric for gsm::GsmDeleteResponse { + fn get_api_event_type(&self) -> Option { + Some(ApiEventsType::Gsm) + } +} diff --git a/crates/api_models/src/gsm.rs b/crates/api_models/src/gsm.rs new file mode 100644 index 000000000000..6bd8fd99dd93 --- /dev/null +++ b/crates/api_models/src/gsm.rs @@ -0,0 +1,75 @@ +use crate::enums; + +#[derive(Debug, serde::Deserialize, serde::Serialize)] +pub struct GsmCreateRequest { + pub connector: enums::Connector, + pub flow: String, + pub sub_flow: String, + pub code: String, + pub message: String, + pub status: String, + pub router_error: Option, + pub decision: GsmDecision, + pub step_up_possible: bool, +} + +#[derive(Debug, serde::Deserialize, serde::Serialize)] +pub struct GsmRetrieveRequest { + pub connector: enums::Connector, + pub flow: String, + pub sub_flow: String, + pub code: String, + pub message: String, +} + +#[derive( + Default, + Clone, + Copy, + Debug, + strum::Display, + PartialEq, + Eq, + serde::Serialize, + serde::Deserialize, + strum::EnumString, +)] +#[serde(rename_all = "snake_case")] +#[strum(serialize_all = "snake_case")] +pub enum GsmDecision { + Retry, + Requeue, + #[default] + DoDefault, +} + +#[derive(Debug, serde::Deserialize, serde::Serialize)] +pub struct GsmUpdateRequest { + pub connector: String, + pub flow: String, + pub sub_flow: String, + pub code: String, + pub message: String, + pub status: Option, + pub router_error: Option, + pub decision: Option, + pub step_up_possible: Option, +} + +#[derive(Debug, serde::Deserialize, serde::Serialize)] +pub struct GsmDeleteRequest { + pub connector: String, + pub flow: String, + pub sub_flow: String, + pub code: String, + pub message: String, +} + +#[derive(Debug, serde::Serialize)] +pub struct GsmDeleteResponse { + pub gsm_rule_delete: bool, + pub connector: String, + pub flow: String, + pub sub_flow: String, + pub code: String, +} diff --git a/crates/api_models/src/lib.rs b/crates/api_models/src/lib.rs index 9fff344b9ff7..5da916b14817 100644 --- a/crates/api_models/src/lib.rs +++ b/crates/api_models/src/lib.rs @@ -11,6 +11,7 @@ pub mod ephemeral_key; pub mod errors; pub mod events; pub mod files; +pub mod gsm; pub mod mandates; pub mod organization; pub mod payment_methods; diff --git a/crates/api_models/src/payments.rs b/crates/api_models/src/payments.rs index c1880d58ad19..196dd108333b 100644 --- a/crates/api_models/src/payments.rs +++ b/crates/api_models/src/payments.rs @@ -3100,6 +3100,8 @@ pub struct PaymentLinkObject { #[serde(default, with = "common_utils::custom_serde::iso8601::option")] pub link_expiry: Option, pub merchant_custom_domain_name: Option, + /// Custom merchant name for payment link + pub custom_merchant_name: Option, } #[derive(Default, Debug, serde::Deserialize, Clone, ToSchema, serde::Serialize)] @@ -3143,11 +3145,11 @@ pub struct PaymentLinkDetails { pub pub_key: String, pub client_secret: String, pub payment_id: String, - #[serde(with = "common_utils::custom_serde::iso8601")] - pub expiry: PrimitiveDateTime, + #[serde(with = "common_utils::custom_serde::iso8601::option")] + pub expiry: Option, pub merchant_logo: String, pub return_url: String, - pub merchant_name: crypto::OptionalEncryptableName, + pub merchant_name: String, pub order_details: Vec, pub max_items_visible_after_collapse: i8, } diff --git a/crates/common_utils/src/events.rs b/crates/common_utils/src/events.rs index 1d487364031d..8c52f6c36d63 100644 --- a/crates/common_utils/src/events.rs +++ b/crates/common_utils/src/events.rs @@ -41,6 +41,7 @@ pub enum ApiEventsType { Routing, ResourceListAPI, PaymentRedirectionResponse, + Gsm, // TODO: This has to be removed once the corresponding apiEventTypes are created Miscellaneous, } diff --git a/crates/data_models/src/payments/payment_attempt.rs b/crates/data_models/src/payments/payment_attempt.rs index 734de8fe4a55..cdd41ea9db2d 100644 --- a/crates/data_models/src/payments/payment_attempt.rs +++ b/crates/data_models/src/payments/payment_attempt.rs @@ -286,6 +286,8 @@ pub enum PaymentAttemptUpdate { connector_response_reference_id: Option, amount_capturable: Option, updated_by: String, + authentication_data: Option, + encoded_data: Option, }, UnresolvedResponseUpdate { status: storage_enums::AttemptStatus, diff --git a/crates/diesel_models/src/connector_response.rs b/crates/diesel_models/src/connector_response.rs deleted file mode 100644 index 863ce28ee0ae..000000000000 --- a/crates/diesel_models/src/connector_response.rs +++ /dev/null @@ -1,122 +0,0 @@ -use diesel::{AsChangeset, Identifiable, Insertable, Queryable}; -use serde::{Deserialize, Serialize}; -use time::PrimitiveDateTime; - -use crate::schema::connector_response; - -#[derive(Clone, Debug, Deserialize, Serialize, Insertable, router_derive::DebugAsDisplay)] -#[diesel(table_name = connector_response)] -#[serde(deny_unknown_fields)] -pub struct ConnectorResponseNew { - pub payment_id: String, - pub merchant_id: String, - pub attempt_id: String, - #[serde(with = "common_utils::custom_serde::iso8601")] - pub created_at: PrimitiveDateTime, - #[serde(with = "common_utils::custom_serde::iso8601")] - pub modified_at: PrimitiveDateTime, - pub connector_name: Option, - pub connector_transaction_id: Option, - pub authentication_data: Option, - pub encoded_data: Option, - pub updated_by: String, -} - -#[derive(Clone, Debug, Deserialize, Serialize, Identifiable, Queryable)] -#[diesel(table_name = connector_response)] -pub struct ConnectorResponse { - pub id: i32, - pub payment_id: String, - pub merchant_id: String, - pub attempt_id: String, - #[serde(with = "common_utils::custom_serde::iso8601")] - pub created_at: PrimitiveDateTime, - #[serde(with = "common_utils::custom_serde::iso8601")] - pub modified_at: PrimitiveDateTime, - pub connector_name: Option, - pub connector_transaction_id: Option, - pub authentication_data: Option, - pub encoded_data: Option, - pub updated_by: String, -} - -#[derive(Clone, Default, Debug, Deserialize, AsChangeset, Serialize)] -#[diesel(table_name = connector_response)] -pub struct ConnectorResponseUpdateInternal { - pub connector_transaction_id: Option, - pub authentication_data: Option, - pub modified_at: Option, - pub encoded_data: Option, - pub connector_name: Option, - pub updated_by: String, -} - -#[derive(Clone, Debug, Serialize, Deserialize)] -pub enum ConnectorResponseUpdate { - ResponseUpdate { - connector_transaction_id: Option, - authentication_data: Option, - encoded_data: Option, - connector_name: Option, - updated_by: String, - }, - ErrorUpdate { - connector_name: Option, - updated_by: String, - }, -} - -impl ConnectorResponseUpdate { - pub fn apply_changeset(self, source: ConnectorResponse) -> ConnectorResponse { - let connector_response_update: ConnectorResponseUpdateInternal = self.into(); - ConnectorResponse { - modified_at: connector_response_update - .modified_at - .unwrap_or_else(common_utils::date_time::now), - connector_name: connector_response_update - .connector_name - .or(source.connector_name), - connector_transaction_id: source - .connector_transaction_id - .or(connector_response_update.connector_transaction_id), - authentication_data: connector_response_update - .authentication_data - .or(source.authentication_data), - encoded_data: connector_response_update - .encoded_data - .or(source.encoded_data), - updated_by: connector_response_update.updated_by, - ..source - } - } -} - -impl From for ConnectorResponseUpdateInternal { - fn from(connector_response_update: ConnectorResponseUpdate) -> Self { - match connector_response_update { - ConnectorResponseUpdate::ResponseUpdate { - connector_transaction_id, - authentication_data, - encoded_data, - connector_name, - updated_by, - } => Self { - connector_transaction_id, - authentication_data, - encoded_data, - modified_at: Some(common_utils::date_time::now()), - connector_name, - updated_by, - }, - ConnectorResponseUpdate::ErrorUpdate { - connector_name, - updated_by, - } => Self { - connector_name, - modified_at: Some(common_utils::date_time::now()), - updated_by, - ..Self::default() - }, - } - } -} diff --git a/crates/diesel_models/src/gsm.rs b/crates/diesel_models/src/gsm.rs index d5b3122c7806..2e824758aa5a 100644 --- a/crates/diesel_models/src/gsm.rs +++ b/crates/diesel_models/src/gsm.rs @@ -1,6 +1,9 @@ //! Gateway status mapping -use common_utils::custom_serde; +use common_utils::{ + custom_serde, + events::{ApiEventMetric, ApiEventsType}, +}; use diesel::{AsChangeset, Identifiable, Insertable, Queryable}; use time::PrimitiveDateTime; @@ -95,3 +98,9 @@ impl From for GatewayStatusMapperUpdateInternal { } } } + +impl ApiEventMetric for GatewayStatusMap { + fn get_api_event_type(&self) -> Option { + Some(ApiEventsType::Gsm) + } +} diff --git a/crates/diesel_models/src/kv.rs b/crates/diesel_models/src/kv.rs index 81fa7a88ee3b..f56ef8304186 100644 --- a/crates/diesel_models/src/kv.rs +++ b/crates/diesel_models/src/kv.rs @@ -3,7 +3,6 @@ use serde::{Deserialize, Serialize}; use crate::{ address::{Address, AddressNew, AddressUpdateInternal}, - connector_response::{ConnectorResponse, ConnectorResponseNew, ConnectorResponseUpdate}, errors, payment_attempt::{PaymentAttempt, PaymentAttemptNew, PaymentAttemptUpdate}, payment_intent::{PaymentIntentNew, PaymentIntentUpdate}, @@ -51,7 +50,6 @@ pub enum Insertable { PaymentIntent(PaymentIntentNew), PaymentAttempt(PaymentAttemptNew), Refund(RefundNew), - ConnectorResponse(ConnectorResponseNew), Address(Box), ReverseLookUp(ReverseLookupNew), } @@ -62,16 +60,9 @@ pub enum Updateable { PaymentIntentUpdate(PaymentIntentUpdateMems), PaymentAttemptUpdate(PaymentAttemptUpdateMems), RefundUpdate(RefundUpdateMems), - ConnectorResponseUpdate(ConnectorResponseUpdateMems), AddressUpdate(Box), } -#[derive(Debug, Serialize, Deserialize)] -pub struct ConnectorResponseUpdateMems { - pub orig: ConnectorResponse, - pub update_data: ConnectorResponseUpdate, -} - #[derive(Debug, Serialize, Deserialize)] pub struct AddressUpdateMems { pub orig: Address, diff --git a/crates/diesel_models/src/lib.rs b/crates/diesel_models/src/lib.rs index 08d74fb8fd37..46a6965b3a7b 100644 --- a/crates/diesel_models/src/lib.rs +++ b/crates/diesel_models/src/lib.rs @@ -4,7 +4,7 @@ pub mod business_profile; pub mod capture; pub mod cards_info; pub mod configs; -pub mod connector_response; + pub mod customers; pub mod dispute; pub mod encryption; @@ -44,10 +44,10 @@ use diesel_impl::{DieselArray, OptionalDieselArray}; pub type StorageResult = error_stack::Result; pub type PgPooledConn = async_bb8_diesel::Connection; pub use self::{ - address::*, api_keys::*, cards_info::*, configs::*, connector_response::*, customers::*, - dispute::*, ephemeral_key::*, events::*, file::*, locker_mock_up::*, mandate::*, - merchant_account::*, merchant_connector_account::*, payment_attempt::*, payment_intent::*, - payment_method::*, process_tracker::*, refund::*, reverse_lookup::*, + address::*, api_keys::*, cards_info::*, configs::*, customers::*, dispute::*, ephemeral_key::*, + events::*, file::*, locker_mock_up::*, mandate::*, merchant_account::*, + merchant_connector_account::*, payment_attempt::*, payment_intent::*, payment_method::*, + process_tracker::*, refund::*, reverse_lookup::*, }; /// The types and implementations provided by this module are required for the schema generated by diff --git a/crates/diesel_models/src/payment_attempt.rs b/crates/diesel_models/src/payment_attempt.rs index 058086106111..ce388fea10eb 100644 --- a/crates/diesel_models/src/payment_attempt.rs +++ b/crates/diesel_models/src/payment_attempt.rs @@ -203,6 +203,8 @@ pub enum PaymentAttemptUpdate { connector_response_reference_id: Option, amount_capturable: Option, updated_by: String, + authentication_data: Option, + encoded_data: Option, }, UnresolvedResponseUpdate { status: storage_enums::AttemptStatus, @@ -478,6 +480,8 @@ impl From for PaymentAttemptUpdateInternal { connector_response_reference_id, amount_capturable, updated_by, + authentication_data, + encoded_data, } => Self { status: Some(status), connector, @@ -494,6 +498,8 @@ impl From for PaymentAttemptUpdateInternal { connector_response_reference_id, amount_capturable, updated_by, + authentication_data, + encoded_data, ..Default::default() }, PaymentAttemptUpdate::ErrorUpdate { diff --git a/crates/diesel_models/src/payment_link.rs b/crates/diesel_models/src/payment_link.rs index 4b182a8155a5..50cc5e89cee9 100644 --- a/crates/diesel_models/src/payment_link.rs +++ b/crates/diesel_models/src/payment_link.rs @@ -20,8 +20,8 @@ pub struct PaymentLink { pub last_modified_at: PrimitiveDateTime, #[serde(default, with = "common_utils::custom_serde::iso8601::option")] pub fulfilment_time: Option, + pub custom_merchant_name: Option, } - #[derive( Clone, Debug, @@ -47,4 +47,5 @@ pub struct PaymentLinkNew { pub last_modified_at: Option, #[serde(default, with = "common_utils::custom_serde::iso8601::option")] pub fulfilment_time: Option, + pub custom_merchant_name: Option, } diff --git a/crates/diesel_models/src/query.rs b/crates/diesel_models/src/query.rs index ac3eeba44359..f315327702ad 100644 --- a/crates/diesel_models/src/query.rs +++ b/crates/diesel_models/src/query.rs @@ -4,7 +4,7 @@ pub mod business_profile; mod capture; pub mod cards_info; pub mod configs; -pub mod connector_response; + pub mod customers; pub mod dispute; pub mod events; diff --git a/crates/diesel_models/src/schema.rs b/crates/diesel_models/src/schema.rs index 50531e432adc..6c9cea035b3f 100644 --- a/crates/diesel_models/src/schema.rs +++ b/crates/diesel_models/src/schema.rs @@ -157,31 +157,6 @@ diesel::table! { } } -diesel::table! { - use diesel::sql_types::*; - use crate::enums::diesel_exports::*; - - connector_response (id) { - id -> Int4, - #[max_length = 64] - payment_id -> Varchar, - #[max_length = 64] - merchant_id -> Varchar, - #[max_length = 64] - attempt_id -> Varchar, - created_at -> Timestamp, - modified_at -> Timestamp, - #[max_length = 64] - connector_name -> Nullable, - #[max_length = 128] - connector_transaction_id -> Nullable, - authentication_data -> Nullable, - encoded_data -> Nullable, - #[max_length = 32] - updated_by -> Varchar, - } -} - diesel::table! { use diesel::sql_types::*; use crate::enums::diesel_exports::*; @@ -691,6 +666,8 @@ diesel::table! { created_at -> Timestamp, last_modified_at -> Timestamp, fulfilment_time -> Nullable, + #[max_length = 64] + custom_merchant_name -> Nullable, } } @@ -930,7 +907,6 @@ diesel::allow_tables_to_appear_in_same_query!( captures, cards_info, configs, - connector_response, customers, dispute, events, diff --git a/crates/drainer/src/lib.rs b/crates/drainer/src/lib.rs index 19abe9ba3aad..7ccfd600d662 100644 --- a/crates/drainer/src/lib.rs +++ b/crates/drainer/src/lib.rs @@ -206,7 +206,6 @@ async fn drainer( let payment_attempt = "payment_attempt"; let refund = "refund"; let reverse_lookup = "reverse_lookup"; - let connector_response = "connector_response"; let address = "address"; match db_op { // TODO: Handle errors @@ -230,13 +229,6 @@ async fn drainer( kv::Insertable::Refund(a) => { macro_util::handle_resp!(a.insert(&conn).await, insert_op, refund) } - kv::Insertable::ConnectorResponse(a) => { - macro_util::handle_resp!( - a.insert(&conn).await, - insert_op, - connector_response - ) - } kv::Insertable::Address(addr) => { macro_util::handle_resp!(addr.insert(&conn).await, insert_op, address) } @@ -283,11 +275,6 @@ async fn drainer( refund ) } - kv::Updateable::ConnectorResponseUpdate(a) => macro_util::handle_resp!( - a.orig.update(&conn, a.update_data).await, - update_op, - connector_response - ), kv::Updateable::AddressUpdate(a) => macro_util::handle_resp!( a.orig.update(&conn, a.update_data).await, update_op, diff --git a/crates/router/src/core.rs b/crates/router/src/core.rs index d87ff64003b4..817fafdae520 100644 --- a/crates/router/src/core.rs +++ b/crates/router/src/core.rs @@ -8,6 +8,7 @@ pub mod customers; pub mod disputes; pub mod errors; pub mod files; +pub mod gsm; pub mod mandate; pub mod metrics; pub mod payment_link; diff --git a/crates/router/src/core/gsm.rs b/crates/router/src/core/gsm.rs new file mode 100644 index 000000000000..d25860674570 --- /dev/null +++ b/crates/router/src/core/gsm.rs @@ -0,0 +1,137 @@ +use api_models::gsm as gsm_api_types; +use diesel_models::gsm as storage; +use error_stack::{IntoReport, ResultExt}; +use router_env::{instrument, tracing}; + +use crate::{ + core::{ + errors, + errors::{RouterResponse, StorageErrorExt}, + }, + db::gsm::GsmInterface, + services, + types::{self, transformers::ForeignInto}, + AppState, +}; + +#[instrument(skip_all)] +pub async fn create_gsm_rule( + state: AppState, + gsm_rule: gsm_api_types::GsmCreateRequest, +) -> RouterResponse { + let db = state.store.as_ref(); + GsmInterface::add_gsm_rule(db, gsm_rule.foreign_into()) + .await + .to_duplicate_response(errors::ApiErrorResponse::GenericDuplicateError { + message: "GSM with given key already exists in our records".to_string(), + }) + .map(services::ApplicationResponse::Json) +} + +#[instrument(skip_all)] +pub async fn retrieve_gsm_rule( + state: AppState, + gsm_request: gsm_api_types::GsmRetrieveRequest, +) -> RouterResponse { + let db = state.store.as_ref(); + let gsm_api_types::GsmRetrieveRequest { + connector, + flow, + sub_flow, + code, + message, + } = gsm_request; + GsmInterface::find_gsm_rule(db, connector.to_string(), flow, sub_flow, code, message) + .await + .to_not_found_response(errors::ApiErrorResponse::GenericNotFoundError { + message: "GSM with given key does not exist in our records".to_string(), + }) + .map(services::ApplicationResponse::Json) +} + +#[instrument(skip_all)] +pub async fn update_gsm_rule( + state: AppState, + gsm_request: gsm_api_types::GsmUpdateRequest, +) -> RouterResponse { + let db = state.store.as_ref(); + let gsm_api_types::GsmUpdateRequest { + connector, + flow, + sub_flow, + code, + message, + decision, + status, + router_error, + step_up_possible, + } = gsm_request; + GsmInterface::update_gsm_rule( + db, + connector.to_string(), + flow, + sub_flow, + code, + message, + storage::GatewayStatusMappingUpdate { + decision: decision.map(|d| d.to_string()), + status, + router_error: Some(router_error), + step_up_possible, + }, + ) + .await + .to_not_found_response(errors::ApiErrorResponse::GenericNotFoundError { + message: "GSM with given key does not exist in our records".to_string(), + }) + .attach_printable("Failed while updating Gsm rule") + .map(services::ApplicationResponse::Json) +} + +#[instrument(skip_all)] +pub async fn delete_gsm_rule( + state: AppState, + gsm_request: gsm_api_types::GsmDeleteRequest, +) -> RouterResponse { + let db = state.store.as_ref(); + let gsm_api_types::GsmDeleteRequest { + connector, + flow, + sub_flow, + code, + message, + } = gsm_request; + match GsmInterface::delete_gsm_rule( + db, + connector.to_string(), + flow.to_owned(), + sub_flow.to_owned(), + code.to_owned(), + message.to_owned(), + ) + .await + .to_not_found_response(errors::ApiErrorResponse::GenericNotFoundError { + message: "GSM with given key does not exist in our records".to_string(), + }) + .attach_printable("Failed while Deleting Gsm rule") + { + Ok(is_deleted) => { + if is_deleted { + Ok(services::ApplicationResponse::Json( + gsm_api_types::GsmDeleteResponse { + gsm_rule_delete: true, + connector, + flow, + sub_flow, + code, + }, + )) + } else { + Err(errors::ApiErrorResponse::InternalServerError) + .into_report() + .attach_printable("Failed while Deleting Gsm rule, got response as false") + } + } + Err(err) => Err(err), + } +} diff --git a/crates/router/src/core/payment_link.rs b/crates/router/src/core/payment_link.rs index 2c51fa0c3cbb..0012efc86c9f 100644 --- a/crates/router/src/core/payment_link.rs +++ b/crates/router/src/core/payment_link.rs @@ -1,6 +1,6 @@ use api_models::admin as admin_types; -use common_utils::ext_traits::AsyncExt; use error_stack::{IntoReport, ResultExt}; +use masking::PeekInterface; use super::errors::{self, RouterResult, StorageErrorExt}; use crate::{ @@ -43,6 +43,11 @@ pub async fn intiate_payment_link_flow( .await .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?; + let payment_link_id = payment_intent + .payment_link_id + .get_required_value("payment_link_id") + .change_context(errors::ApiErrorResponse::PaymentLinkNotFound)?; + helpers::validate_payment_status_against_not_allowed_statuses( &payment_intent.status, &[ @@ -55,20 +60,10 @@ pub async fn intiate_payment_link_flow( "create payment link", )?; - let fulfillment_time = payment_intent - .payment_link_id - .as_ref() - .async_and_then(|pli| async move { - db.find_payment_link_by_payment_link_id(pli) - .await - .ok()? - .fulfilment_time - .ok_or(errors::ApiErrorResponse::PaymentNotFound) - .ok() - }) + let payment_link = db + .find_payment_link_by_payment_link_id(&payment_link_id) .await - .get_required_value("fulfillment_time") - .change_context(errors::ApiErrorResponse::PaymentNotFound)?; + .to_not_found_response(errors::ApiErrorResponse::PaymentLinkNotFound)?; let payment_link_config = merchant_account .payment_link_config @@ -108,10 +103,15 @@ pub async fn intiate_payment_link_flow( amount: payment_intent.amount, currency, payment_id: payment_intent.payment_id, - merchant_name: merchant_account.merchant_name, + merchant_name: payment_link.custom_merchant_name.unwrap_or( + merchant_account + .merchant_name + .map(|merchant_name| merchant_name.into_inner().peek().to_owned()) + .unwrap_or_default(), + ), order_details, return_url, - expiry: fulfillment_time, + expiry: payment_link.fulfilment_time, pub_key, client_secret, merchant_logo: payment_link_config diff --git a/crates/router/src/core/payments.rs b/crates/router/src/core/payments.rs index 98ab158e7935..a114b20380bf 100644 --- a/crates/router/src/core/payments.rs +++ b/crates/router/src/core/payments.rs @@ -1578,7 +1578,6 @@ where pub payment_intent: storage::PaymentIntent, pub payment_attempt: storage::PaymentAttempt, pub multiple_capture_data: Option, - pub connector_response: storage::ConnectorResponse, pub amount: api::Amount, pub mandate_id: Option, pub mandate_connector: Option, @@ -1671,10 +1670,7 @@ pub fn should_call_connector( !matches!( payment_data.payment_intent.status, storage_enums::IntentStatus::Failed | storage_enums::IntentStatus::Succeeded - ) && payment_data - .connector_response - .authentication_data - .is_none() + ) && payment_data.payment_attempt.authentication_data.is_none() } "PaymentStatus" => { matches!( diff --git a/crates/router/src/core/payments/helpers.rs b/crates/router/src/core/payments/helpers.rs index fd9fd7361da3..4ee2fd4b94d3 100644 --- a/crates/router/src/core/payments/helpers.rs +++ b/crates/router/src/core/payments/helpers.rs @@ -2998,60 +2998,6 @@ impl AttemptType { } } } - - #[instrument(skip_all)] - pub async fn get_or_insert_connector_response( - &self, - payment_attempt: &PaymentAttempt, - db: &dyn StorageInterface, - storage_scheme: storage::enums::MerchantStorageScheme, - ) -> RouterResult { - match self { - Self::New => db - .insert_connector_response( - payments::PaymentCreate::make_connector_response(payment_attempt), - storage_scheme, - ) - .await - .to_duplicate_response(errors::ApiErrorResponse::DuplicatePayment { - payment_id: payment_attempt.payment_id.clone(), - }), - Self::SameOld => db - .find_connector_response_by_payment_id_merchant_id_attempt_id( - &payment_attempt.payment_id, - &payment_attempt.merchant_id, - &payment_attempt.attempt_id, - storage_scheme, - ) - .await - .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound), - } - } - - #[instrument(skip_all)] - pub async fn get_connector_response( - &self, - db: &dyn StorageInterface, - payment_id: &str, - merchant_id: &str, - attempt_id: &str, - storage_scheme: storage_enums::MerchantStorageScheme, - ) -> RouterResult { - match self { - Self::New => Err(errors::ApiErrorResponse::InternalServerError) - .into_report() - .attach_printable("Precondition failed, the attempt type should not be `New`"), - Self::SameOld => db - .find_connector_response_by_payment_id_merchant_id_attempt_id( - payment_id, - merchant_id, - attempt_id, - storage_scheme, - ) - .await - .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound), - } - } } #[inline(always)] diff --git a/crates/router/src/core/payments/operations/payment_approve.rs b/crates/router/src/core/payments/operations/payment_approve.rs index 4cd1bae04dee..d5d0d2d01765 100644 --- a/crates/router/src/core/payments/operations/payment_approve.rs +++ b/crates/router/src/core/payments/operations/payment_approve.rs @@ -161,16 +161,6 @@ impl ) .await?; - let connector_response = db - .find_connector_response_by_payment_id_merchant_id_attempt_id( - &payment_attempt.payment_id, - &payment_attempt.merchant_id, - &payment_attempt.attempt_id, - storage_scheme, - ) - .await - .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?; - let redirect_response = request .feature_metadata .as_ref() @@ -224,7 +214,6 @@ impl payment_intent, payment_attempt, currency, - connector_response, amount, email: request.email.clone(), mandate_id: None, diff --git a/crates/router/src/core/payments/operations/payment_cancel.rs b/crates/router/src/core/payments/operations/payment_cancel.rs index 43fdc440e64d..f734afef7826 100644 --- a/crates/router/src/core/payments/operations/payment_cancel.rs +++ b/crates/router/src/core/payments/operations/payment_cancel.rs @@ -106,15 +106,6 @@ impl ) .await?; - let connector_response = db - .find_connector_response_by_payment_id_merchant_id_attempt_id( - &payment_attempt.payment_id, - &payment_attempt.merchant_id, - &payment_attempt.attempt_id, - storage_scheme, - ) - .await - .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?; let currency = payment_attempt.currency.get_required_value("currency")?; let amount = payment_attempt.amount.into(); @@ -161,7 +152,7 @@ impl refunds: vec![], disputes: vec![], attempts: None, - connector_response, + sessions_token: vec![], card_cvc: None, creds_identifier, diff --git a/crates/router/src/core/payments/operations/payment_capture.rs b/crates/router/src/core/payments/operations/payment_capture.rs index 1cfcbce5532f..6e794b1ba618 100644 --- a/crates/router/src/core/payments/operations/payment_capture.rs +++ b/crates/router/src/core/payments/operations/payment_capture.rs @@ -3,7 +3,6 @@ use std::marker::PhantomData; use api_models::enums::FrmSuggestion; use async_trait::async_trait; use common_utils::ext_traits::AsyncExt; -use diesel_models::connector_response::ConnectorResponse; use error_stack::ResultExt; use router_env::{instrument, tracing}; @@ -20,7 +19,7 @@ use crate::{ types::{ api::{self, PaymentIdTypeExt}, domain, - storage::{self, enums, payment_attempt::PaymentAttemptExt, ConnectorResponseExt}, + storage::{self, enums, payment_attempt::PaymentAttemptExt}, }, utils::OptionExt, }; @@ -89,9 +88,7 @@ impl helpers::validate_capture_method(capture_method)?; - let (multiple_capture_data, connector_response) = if capture_method - == enums::CaptureMethod::ManualMultiple - { + let multiple_capture_data = if capture_method == enums::CaptureMethod::ManualMultiple { let amount_to_capture = request .amount_to_capture .get_required_value("amount_to_capture")?; @@ -121,37 +118,13 @@ impl .to_not_found_response(errors::ApiErrorResponse::DuplicatePayment { payment_id: payment_id.clone(), })?; - let new_connector_response = db - .insert_connector_response( - ConnectorResponse::make_new_connector_response( - capture.payment_id.clone(), - capture.merchant_id.clone(), - capture.capture_id.clone(), - Some(capture.connector.clone()), - storage_scheme.to_string(), - ), - storage_scheme, - ) - .await - .to_not_found_response(errors::ApiErrorResponse::DuplicatePayment { payment_id })?; - ( - Some(MultipleCaptureData::new_for_create( - previous_captures, - capture, - )), - new_connector_response, - ) + + Some(MultipleCaptureData::new_for_create( + previous_captures, + capture, + )) } else { - let connector_response = db - .find_connector_response_by_payment_id_merchant_id_attempt_id( - &payment_attempt.payment_id, - &payment_attempt.merchant_id, - &payment_attempt.attempt_id, - storage_scheme, - ) - .await - .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?; - (None, connector_response) + None }; currency = payment_attempt.currency.get_required_value("currency")?; @@ -223,7 +196,6 @@ impl refunds: vec![], disputes: vec![], attempts: None, - connector_response, sessions_token: vec![], card_cvc: None, creds_identifier, diff --git a/crates/router/src/core/payments/operations/payment_complete_authorize.rs b/crates/router/src/core/payments/operations/payment_complete_authorize.rs index 4e87b3869431..038d34ea290f 100644 --- a/crates/router/src/core/payments/operations/payment_complete_authorize.rs +++ b/crates/router/src/core/payments/operations/payment_complete_authorize.rs @@ -170,16 +170,6 @@ impl ) .await?; - let connector_response = db - .find_connector_response_by_payment_id_merchant_id_attempt_id( - &payment_attempt.payment_id, - &payment_attempt.merchant_id, - &payment_attempt.attempt_id, - storage_scheme, - ) - .await - .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?; - let redirect_response = request .feature_metadata .as_ref() @@ -219,7 +209,6 @@ impl payment_intent, payment_attempt, currency, - connector_response, amount, email: request.email.clone(), mandate_id: None, diff --git a/crates/router/src/core/payments/operations/payment_confirm.rs b/crates/router/src/core/payments/operations/payment_confirm.rs index 5de281a5e63c..21f7db3d0b41 100644 --- a/crates/router/src/core/payments/operations/payment_confirm.rs +++ b/crates/router/src/core/payments/operations/payment_confirm.rs @@ -157,77 +157,49 @@ impl }) .map(|x| x.transpose()); - let (mut payment_attempt, shipping_address, billing_address, connector_response) = - match payment_intent.status { - api_models::enums::IntentStatus::RequiresCustomerAction - | api_models::enums::IntentStatus::RequiresMerchantAction - | api_models::enums::IntentStatus::RequiresPaymentMethod - | api_models::enums::IntentStatus::RequiresConfirmation => { - let attempt_type = helpers::AttemptType::SameOld; - - let attempt_id = payment_intent.active_attempt.get_id(); - let connector_response_fut = attempt_type.get_connector_response( + let (mut payment_attempt, shipping_address, billing_address) = match payment_intent.status { + api_models::enums::IntentStatus::RequiresCustomerAction + | api_models::enums::IntentStatus::RequiresMerchantAction + | api_models::enums::IntentStatus::RequiresPaymentMethod + | api_models::enums::IntentStatus::RequiresConfirmation => { + let (payment_attempt, shipping_address, billing_address, _) = futures::try_join!( + payment_attempt_fut, + shipping_address_fut, + billing_address_fut, + config_update_fut + )?; + + (payment_attempt, shipping_address, billing_address) + } + _ => { + let (mut payment_attempt, shipping_address, billing_address, _) = futures::try_join!( + payment_attempt_fut, + shipping_address_fut, + billing_address_fut, + config_update_fut + )?; + + let attempt_type = helpers::get_attempt_type( + &payment_intent, + &payment_attempt, + request, + "confirm", + )?; + + (payment_intent, payment_attempt) = attempt_type + .modify_payment_intent_and_payment_attempt( + // 3 + request, + payment_intent, + payment_attempt, db, - &payment_intent.payment_id, - &payment_intent.merchant_id, - attempt_id.as_str(), storage_scheme, - ); - - let (payment_attempt, shipping_address, billing_address, connector_response, _) = - futures::try_join!( - payment_attempt_fut, - shipping_address_fut, - billing_address_fut, - connector_response_fut, - config_update_fut - )?; - - ( - payment_attempt, - shipping_address, - billing_address, - connector_response, ) - } - _ => { - let (mut payment_attempt, shipping_address, billing_address, _) = futures::try_join!( - payment_attempt_fut, - shipping_address_fut, - billing_address_fut, - config_update_fut - )?; - - let attempt_type = helpers::get_attempt_type( - &payment_intent, - &payment_attempt, - request, - "confirm", - )?; - - (payment_intent, payment_attempt) = attempt_type - .modify_payment_intent_and_payment_attempt( - // 3 - request, - payment_intent, - payment_attempt, - db, - storage_scheme, - ) - .await?; - - let connector_response = attempt_type - .get_or_insert_connector_response(&payment_attempt, db, storage_scheme) - .await?; + .await?; - ( - payment_attempt, - shipping_address, - billing_address, - connector_response, - ) - } - }; + (payment_attempt, shipping_address, billing_address) + } + }; payment_intent.order_details = request .get_order_details_as_value() @@ -354,7 +326,6 @@ impl payment_intent, payment_attempt, currency, - connector_response, amount, email: request.email.clone(), mandate_id: None, diff --git a/crates/router/src/core/payments/operations/payment_create.rs b/crates/router/src/core/payments/operations/payment_create.rs index 909f4d456530..97bb84371306 100644 --- a/crates/router/src/core/payments/operations/payment_create.rs +++ b/crates/router/src/core/payments/operations/payment_create.rs @@ -62,7 +62,7 @@ impl let ephemeral_key = Self::get_ephemeral_key(request, state, merchant_account).await; let merchant_id = &merchant_account.merchant_id; let storage_scheme = merchant_account.storage_scheme; - let (payment_intent, payment_attempt, connector_response); + let (payment_intent, payment_attempt); let money @ (amount, currency) = payments_create_request_validation(request)?; @@ -196,16 +196,6 @@ impl payment_id: payment_id.clone(), })?; - connector_response = db - .insert_connector_response( - Self::make_connector_response(&payment_attempt), - storage_scheme, - ) - .await - .to_duplicate_response(errors::ApiErrorResponse::DuplicatePayment { - payment_id: payment_id.clone(), - })?; - let mandate_id = request .mandate_id .as_ref() @@ -300,7 +290,6 @@ impl disputes: vec![], attempts: None, force_sync: None, - connector_response, sessions_token: vec![], card_cvc: request.card_cvc.clone(), creds_identifier, @@ -727,24 +716,6 @@ impl PaymentCreate { }) } - #[instrument(skip_all)] - pub fn make_connector_response( - payment_attempt: &PaymentAttempt, - ) -> storage::ConnectorResponseNew { - storage::ConnectorResponseNew { - payment_id: payment_attempt.payment_id.clone(), - merchant_id: payment_attempt.merchant_id.clone(), - attempt_id: payment_attempt.attempt_id.clone(), - created_at: payment_attempt.created_at, - modified_at: payment_attempt.modified_at, - connector_name: payment_attempt.connector.clone(), - connector_transaction_id: None, - authentication_data: None, - encoded_data: None, - updated_by: payment_attempt.updated_by.clone(), - } - } - #[instrument(skip_all)] pub async fn get_ephemeral_key( request: &api::PaymentsRequest, @@ -813,6 +784,7 @@ async fn create_payment_link( created_at, last_modified_at, fulfilment_time: payment_link_object.link_expiry, + custom_merchant_name: payment_link_object.custom_merchant_name, }; let payment_link_db = db .insert_payment_link(payment_link_req) diff --git a/crates/router/src/core/payments/operations/payment_method_validate.rs b/crates/router/src/core/payments/operations/payment_method_validate.rs index 33f6c23c8363..7e4fe0951b03 100644 --- a/crates/router/src/core/payments/operations/payment_method_validate.rs +++ b/crates/router/src/core/payments/operations/payment_method_validate.rs @@ -7,7 +7,7 @@ use error_stack::ResultExt; use router_derive::PaymentOperation; use router_env::{instrument, tracing}; -use super::{BoxedOperation, Domain, GetTracker, PaymentCreate, UpdateTracker, ValidateRequest}; +use super::{BoxedOperation, Domain, GetTracker, UpdateTracker, ValidateRequest}; use crate::{ consts, core::{ @@ -89,7 +89,7 @@ impl let merchant_id = &merchant_account.merchant_id; let storage_scheme = merchant_account.storage_scheme; - let (payment_intent, payment_attempt, connector_response); + let (payment_intent, payment_attempt); let payment_id = payment_id .get_payment_intent_id() @@ -135,19 +135,6 @@ impl } }?; - connector_response = match db - .insert_connector_response( - PaymentCreate::make_connector_response(&payment_attempt), - storage_scheme, - ) - .await - { - Ok(connector_resp) => Ok(connector_resp), - Err(err) => { - Err(err.change_context(errors::ApiErrorResponse::VerificationFailed { data: None })) - } - }?; - let creds_identifier = request .merchant_connector_details .as_ref() @@ -180,7 +167,6 @@ impl mandate_connector: None, setup_mandate: request.mandate_data.clone().map(Into::into), token: request.payment_token.clone(), - connector_response, payment_method_data: request.payment_method_data.clone(), confirm: Some(true), address: types::PaymentAddress::default(), diff --git a/crates/router/src/core/payments/operations/payment_reject.rs b/crates/router/src/core/payments/operations/payment_reject.rs index 415ab3eccfe7..a6c2561aaeed 100644 --- a/crates/router/src/core/payments/operations/payment_reject.rs +++ b/crates/router/src/core/payments/operations/payment_reject.rs @@ -104,15 +104,6 @@ impl ) .await?; - let connector_response = db - .find_connector_response_by_payment_id_merchant_id_attempt_id( - &payment_attempt.payment_id, - &payment_attempt.merchant_id, - &payment_attempt.attempt_id, - storage_scheme, - ) - .await - .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?; let currency = payment_attempt.currency.get_required_value("currency")?; let amount = payment_attempt.amount.into(); @@ -147,7 +138,7 @@ impl refunds: vec![], disputes: vec![], attempts: None, - connector_response, + sessions_token: vec![], card_cvc: None, creds_identifier: None, diff --git a/crates/router/src/core/payments/operations/payment_response.rs b/crates/router/src/core/payments/operations/payment_response.rs index 60d3bc165a97..77c344949660 100644 --- a/crates/router/src/core/payments/operations/payment_response.rs +++ b/crates/router/src/core/payments/operations/payment_response.rs @@ -296,10 +296,7 @@ async fn payment_response_update_tracker( router_data: types::RouterData, storage_scheme: enums::MerchantStorageScheme, ) -> RouterResult> { - let (capture_update, mut payment_attempt_update, connector_response_update) = match router_data - .response - .clone() - { + let (capture_update, mut payment_attempt_update) = match router_data.response.clone() { Err(err) => { let (capture_update, attempt_update) = match payment_data.multiple_capture_data { Some(multiple_capture_data) => { @@ -356,14 +353,7 @@ async fn payment_response_update_tracker( ) } }; - ( - capture_update, - attempt_update, - Some(storage::ConnectorResponseUpdate::ErrorUpdate { - connector_name: Some(router_data.connector.clone()), - updated_by: storage_scheme.to_string(), - }), - ) + (capture_update, attempt_update) } Ok(payments_response) => match payments_response { types::PaymentsResponseData::PreProcessingResponse { @@ -394,7 +384,7 @@ async fn payment_response_update_tracker( updated_by: storage_scheme.to_string(), }; - (None, Some(payment_attempt_update), None) + (None, Some(payment_attempt_update)) } types::PaymentsResponseData::TransactionResponse { resource_id, @@ -409,8 +399,7 @@ async fn payment_response_update_tracker( | types::ResponseId::EncodedData(id) => Some(id), }; - let encoded_data = payment_data.connector_response.encoded_data.clone(); - let connector_name = router_data.connector.clone(); + let encoded_data = payment_data.payment_attempt.encoded_data.clone(); let authentication_data = redirection_data .map(|data| utils::Encode::::encode_to_value(&data)) @@ -478,23 +467,13 @@ async fn payment_response_update_tracker( None }, updated_by: storage_scheme.to_string(), + authentication_data, + encoded_data, }), ), }; - let connector_response_update = storage::ConnectorResponseUpdate::ResponseUpdate { - connector_transaction_id, - authentication_data, - encoded_data, - connector_name: Some(connector_name), - updated_by: storage_scheme.to_string(), - }; - - ( - capture_updates, - payment_attempt_update, - Some(connector_response_update), - ) + (capture_updates, payment_attempt_update) } types::PaymentsResponseData::TransactionUnresolvedResponse { resource_id, @@ -519,14 +498,13 @@ async fn payment_response_update_tracker( connector_response_reference_id, updated_by: storage_scheme.to_string(), }), - None, ) } - types::PaymentsResponseData::SessionResponse { .. } => (None, None, None), - types::PaymentsResponseData::SessionTokenResponse { .. } => (None, None, None), - types::PaymentsResponseData::TokenizationResponse { .. } => (None, None, None), - types::PaymentsResponseData::ConnectorCustomerResponse { .. } => (None, None, None), - types::PaymentsResponseData::ThreeDSEnrollmentResponse { .. } => (None, None, None), + types::PaymentsResponseData::SessionResponse { .. } => (None, None), + types::PaymentsResponseData::SessionTokenResponse { .. } => (None, None), + types::PaymentsResponseData::TokenizationResponse { .. } => (None, None), + types::PaymentsResponseData::ConnectorCustomerResponse { .. } => (None, None), + types::PaymentsResponseData::ThreeDSEnrollmentResponse { .. } => (None, None), types::PaymentsResponseData::MultipleCaptureResponse { capture_sync_response_list, } => match payment_data.multiple_capture_data { @@ -535,13 +513,9 @@ async fn payment_response_update_tracker( &multiple_capture_data, capture_sync_response_list, )?; - ( - Some((multiple_capture_data, capture_update_list)), - None, - None, - ) + (Some((multiple_capture_data, capture_update_list)), None) } - None => (None, None, None), + None => (None, None), }, }, }; @@ -571,40 +545,18 @@ async fn payment_response_update_tracker( // Stage 1 let payment_attempt = payment_data.payment_attempt.clone(); - let connector_response = payment_data.connector_response.clone(); - - let payment_attempt_fut = Box::pin(async move { - Ok::<_, error_stack::Report>(match payment_attempt_update { - Some(payment_attempt_update) => db - .update_payment_attempt_with_attempt_id( - payment_attempt, - payment_attempt_update, - storage_scheme, - ) - .await - .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?, - None => payment_attempt, - }) - }); - - let connector_response_fut = Box::pin(async move { - Ok::<_, error_stack::Report>(match connector_response_update { - Some(connector_response_update) => db - .update_connector_response( - connector_response, - connector_response_update, - storage_scheme, - ) - .await - .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?, - None => connector_response, - }) - }); - - let (payment_attempt, connector_response) = - futures::try_join!(payment_attempt_fut, connector_response_fut)?; - payment_data.payment_attempt = payment_attempt; - payment_data.connector_response = connector_response; + + payment_data.payment_attempt = match payment_attempt_update { + Some(payment_attempt_update) => db + .update_payment_attempt_with_attempt_id( + payment_attempt, + payment_attempt_update, + storage_scheme, + ) + .await + .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?, + None => payment_attempt, + }; let amount_captured = get_total_amount_captured( router_data.request, diff --git a/crates/router/src/core/payments/operations/payment_session.rs b/crates/router/src/core/payments/operations/payment_session.rs index 354c62648bb3..52677ab3cc8d 100644 --- a/crates/router/src/core/payments/operations/payment_session.rs +++ b/crates/router/src/core/payments/operations/payment_session.rs @@ -126,20 +126,6 @@ impl payment_intent.shipping_address_id = shipping_address.clone().map(|x| x.address_id); payment_intent.billing_address_id = billing_address.clone().map(|x| x.address_id); - let connector_response = db - .find_connector_response_by_payment_id_merchant_id_attempt_id( - &payment_intent.payment_id, - &payment_intent.merchant_id, - &payment_attempt.attempt_id, - storage_scheme, - ) - .await - .map_err(|error| { - error - .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable("Database error when finding connector response") - })?; - let customer_details = payments::CustomerDetails { customer_id: payment_intent.customer_id.clone(), name: None, @@ -190,7 +176,6 @@ impl disputes: vec![], attempts: None, sessions_token: vec![], - connector_response, card_cvc: None, creds_identifier, pm_token: None, diff --git a/crates/router/src/core/payments/operations/payment_start.rs b/crates/router/src/core/payments/operations/payment_start.rs index e9fa301bf07b..5578f6b3dc15 100644 --- a/crates/router/src/core/payments/operations/payment_start.rs +++ b/crates/router/src/core/payments/operations/payment_start.rs @@ -126,20 +126,6 @@ impl ..CustomerDetails::default() }; - let connector_response = db - .find_connector_response_by_payment_id_merchant_id_attempt_id( - &payment_intent.payment_id, - &payment_intent.merchant_id, - &payment_attempt.attempt_id, - storage_scheme, - ) - .await - .map_err(|error| { - error - .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable("Database error when finding connector response") - })?; - Ok(( Box::new(self), PaymentData { @@ -150,7 +136,6 @@ impl email: None, mandate_id: None, mandate_connector: None, - connector_response, setup_mandate: None, token: payment_attempt.payment_token.clone(), address: PaymentAddress { diff --git a/crates/router/src/core/payments/operations/payment_status.rs b/crates/router/src/core/payments/operations/payment_status.rs index 96aac6c9d79b..83e7131b2675 100644 --- a/crates/router/src/core/payments/operations/payment_status.rs +++ b/crates/router/src/core/payments/operations/payment_status.rs @@ -226,7 +226,7 @@ async fn get_tracker_for_sync< PaymentData, Option, )> { - let (payment_intent, payment_attempt, currency, amount); + let (payment_intent, mut payment_attempt, currency, amount); (payment_intent, payment_attempt) = get_payment_intent_payment_attempt( db, @@ -250,18 +250,7 @@ async fn get_tracker_for_sync< let payment_id_str = payment_attempt.payment_id.clone(); - let mut connector_response = db - .find_connector_response_by_payment_id_merchant_id_attempt_id( - &payment_intent.payment_id, - &payment_intent.merchant_id, - &payment_attempt.attempt_id, - storage_scheme, - ) - .await - .change_context(errors::ApiErrorResponse::PaymentNotFound) - .attach_printable("Database error when finding connector response")?; - - connector_response.encoded_data = request.param.clone(); + payment_attempt.encoded_data = request.param.clone(); currency = payment_attempt.currency.get_required_value("currency")?; amount = payment_attempt.amount.into(); @@ -349,7 +338,7 @@ async fn get_tracker_for_sync< format!("Error while retrieving frm_response, merchant_id: {}, payment_id: {payment_id_str}", &merchant_account.merchant_id) }); - let contains_encoded_data = connector_response.encoded_data.is_some(); + let contains_encoded_data = payment_attempt.encoded_data.is_some(); let creds_identifier = request .merchant_connector_details @@ -373,7 +362,6 @@ async fn get_tracker_for_sync< PaymentData { flow: PhantomData, payment_intent, - connector_response, currency, amount, email: None, diff --git a/crates/router/src/core/payments/operations/payment_update.rs b/crates/router/src/core/payments/operations/payment_update.rs index 622d09754396..0a49c830b732 100644 --- a/crates/router/src/core/payments/operations/payment_update.rs +++ b/crates/router/src/core/payments/operations/payment_update.rs @@ -219,20 +219,6 @@ impl )?; } - let connector_response = db - .find_connector_response_by_payment_id_merchant_id_attempt_id( - &payment_intent.payment_id, - &payment_intent.merchant_id, - &payment_attempt.attempt_id, - storage_scheme, - ) - .await - .map_err(|error| { - error - .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable("Database error when finding connector response") - })?; - let mandate_id = request .mandate_id .as_ref() @@ -341,7 +327,6 @@ impl refunds: vec![], disputes: vec![], attempts: None, - connector_response, sessions_token: vec![], card_cvc: request.card_cvc.clone(), creds_identifier, diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs index c62529826387..6c6b4ae9339f 100644 --- a/crates/router/src/core/payments/transformers.rs +++ b/crates/router/src/core/payments/transformers.rs @@ -460,14 +460,8 @@ where let output = Ok(match payment_request { Some(_request) => { - if payments::is_start_pay(&operation) - && payment_data - .connector_response - .authentication_data - .is_some() - { - let redirection_data = payment_data - .connector_response + if payments::is_start_pay(&operation) && payment_attempt.authentication_data.is_some() { + let redirection_data = payment_attempt .authentication_data .get_required_value("redirection_data")?; @@ -523,16 +517,15 @@ where display_to_timestamp: wait_screen_data.display_to_timestamp, } })) - .or(payment_data - .connector_response - .authentication_data - .map(|_| api_models::payments::NextActionData::RedirectToUrl { + .or(payment_attempt.authentication_data.as_ref().map(|_| { + api_models::payments::NextActionData::RedirectToUrl { redirect_to_url: helpers::create_startpay_url( server, &payment_attempt, &payment_intent, ), - })); + } + })); }; // next action check for third party sdk session (for ex: Apple pay through trustpay has third party sdk session response) @@ -1056,7 +1049,7 @@ impl TryFrom> for types::PaymentsSyncData } None => types::ResponseId::NoResponseId, }, - encoded_data: payment_data.connector_response.encoded_data, + encoded_data: payment_data.payment_attempt.encoded_data, capture_method: payment_data.payment_attempt.capture_method, connector_meta: payment_data.payment_attempt.connector_metadata, sync_type: match payment_data.multiple_capture_data { @@ -1356,7 +1349,7 @@ impl TryFrom> for types::CompleteAuthoriz browser_info, email: payment_data.email, payment_method_data: payment_data.payment_method_data, - connector_transaction_id: payment_data.connector_response.connector_transaction_id, + connector_transaction_id: payment_data.payment_attempt.connector_transaction_id, redirect_response, connector_meta: payment_data.payment_attempt.connector_metadata, }) diff --git a/crates/router/src/db.rs b/crates/router/src/db.rs index 3efef2c40f29..6fe34d8dd69b 100644 --- a/crates/router/src/db.rs +++ b/crates/router/src/db.rs @@ -5,7 +5,6 @@ pub mod cache; pub mod capture; pub mod cards_info; pub mod configs; -pub mod connector_response; pub mod customers; pub mod dispute; pub mod ephemeral_key; @@ -52,7 +51,6 @@ pub trait StorageInterface: + api_keys::ApiKeyInterface + configs::ConfigInterface + capture::CaptureInterface - + connector_response::ConnectorResponseInterface + customers::CustomerInterface + dispute::DisputeInterface + ephemeral_key::EphemeralKeyInterface diff --git a/crates/router/src/db/connector_response.rs b/crates/router/src/db/connector_response.rs deleted file mode 100644 index 354231d136ec..000000000000 --- a/crates/router/src/db/connector_response.rs +++ /dev/null @@ -1,343 +0,0 @@ -use error_stack::{IntoReport, ResultExt}; -use router_env::{instrument, tracing}; - -use super::{MockDb, Store}; -use crate::{ - core::errors::{self, CustomResult}, - types::storage::{self as storage_type, enums}, -}; - -#[async_trait::async_trait] -pub trait ConnectorResponseInterface { - async fn insert_connector_response( - &self, - connector_response: storage_type::ConnectorResponseNew, - storage_scheme: enums::MerchantStorageScheme, - ) -> CustomResult; - - async fn find_connector_response_by_payment_id_merchant_id_attempt_id( - &self, - payment_id: &str, - merchant_id: &str, - attempt_id: &str, - storage_scheme: enums::MerchantStorageScheme, - ) -> CustomResult; - - async fn update_connector_response( - &self, - this: storage_type::ConnectorResponse, - payment_attempt: storage_type::ConnectorResponseUpdate, - storage_scheme: enums::MerchantStorageScheme, - ) -> CustomResult; -} - -#[cfg(not(feature = "kv_store"))] -mod storage { - use error_stack::IntoReport; - use router_env::{instrument, tracing}; - - use super::Store; - use crate::{ - connection, - core::errors::{self, CustomResult}, - types::storage::{self as storage_type, enums}, - }; - - #[async_trait::async_trait] - impl super::ConnectorResponseInterface for Store { - #[instrument(skip_all)] - async fn insert_connector_response( - &self, - connector_response: storage_type::ConnectorResponseNew, - _storage_scheme: enums::MerchantStorageScheme, - ) -> CustomResult { - let conn = connection::pg_connection_write(self).await?; - connector_response - .insert(&conn) - .await - .map_err(Into::into) - .into_report() - } - - #[instrument(skip_all)] - async fn find_connector_response_by_payment_id_merchant_id_attempt_id( - &self, - payment_id: &str, - merchant_id: &str, - attempt_id: &str, - _storage_scheme: enums::MerchantStorageScheme, - ) -> CustomResult { - let conn = connection::pg_connection_read(self).await?; - storage_type::ConnectorResponse::find_by_payment_id_merchant_id_attempt_id( - &conn, - payment_id, - merchant_id, - attempt_id, - ) - .await - .map_err(Into::into) - .into_report() - } - - async fn update_connector_response( - &self, - this: storage_type::ConnectorResponse, - connector_response_update: storage_type::ConnectorResponseUpdate, - _storage_scheme: enums::MerchantStorageScheme, - ) -> CustomResult { - let conn = connection::pg_connection_write(self).await?; - this.update(&conn, connector_response_update) - .await - .map_err(Into::into) - .into_report() - } - } -} - -#[cfg(feature = "kv_store")] -mod storage { - - use diesel_models::enums as storage_enums; - use error_stack::{IntoReport, ResultExt}; - use redis_interface::HsetnxReply; - use router_env::{instrument, tracing}; - use storage_impl::redis::kv_store::{kv_wrapper, KvOperation}; - - use super::Store; - use crate::{ - connection, - core::errors::{self, CustomResult}, - types::storage::{self as storage_type, enums, kv}, - utils::db_utils, - }; - - #[async_trait::async_trait] - impl super::ConnectorResponseInterface for Store { - #[instrument(skip_all)] - async fn insert_connector_response( - &self, - connector_response: storage_type::ConnectorResponseNew, - storage_scheme: enums::MerchantStorageScheme, - ) -> CustomResult { - let conn = connection::pg_connection_write(self).await?; - - match storage_scheme { - storage_enums::MerchantStorageScheme::PostgresOnly => connector_response - .insert(&conn) - .await - .map_err(Into::into) - .into_report(), - storage_enums::MerchantStorageScheme::RedisKv => { - let merchant_id = &connector_response.merchant_id; - let payment_id = &connector_response.payment_id; - let attempt_id = &connector_response.attempt_id; - - let key = format!("mid_{merchant_id}_pid_{payment_id}"); - let field = format!("connector_resp_{merchant_id}_{payment_id}_{attempt_id}"); - - let created_connector_resp = storage_type::ConnectorResponse { - id: Default::default(), - payment_id: connector_response.payment_id.clone(), - merchant_id: connector_response.merchant_id.clone(), - attempt_id: connector_response.attempt_id.clone(), - created_at: connector_response.created_at, - modified_at: connector_response.modified_at, - connector_name: connector_response.connector_name.clone(), - connector_transaction_id: connector_response - .connector_transaction_id - .clone(), - authentication_data: connector_response.authentication_data.clone(), - encoded_data: connector_response.encoded_data.clone(), - updated_by: storage_scheme.to_string(), - }; - - let redis_entry = kv::TypedSql { - op: kv::DBOperation::Insert { - insertable: kv::Insertable::ConnectorResponse( - connector_response.clone(), - ), - }, - }; - - match kv_wrapper::( - self, - KvOperation::HSetNx(&field, &created_connector_resp, redis_entry), - &key, - ) - .await - .change_context(errors::StorageError::KVError)? - .try_into_hsetnx() - { - Ok(HsetnxReply::KeyNotSet) => Err(errors::StorageError::DuplicateValue { - entity: "address", - key: Some(key), - }) - .into_report(), - Ok(HsetnxReply::KeySet) => Ok(created_connector_resp), - Err(er) => Err(er).change_context(errors::StorageError::KVError), - } - } - } - } - - #[instrument(skip_all)] - async fn find_connector_response_by_payment_id_merchant_id_attempt_id( - &self, - payment_id: &str, - merchant_id: &str, - attempt_id: &str, - storage_scheme: enums::MerchantStorageScheme, - ) -> CustomResult { - let conn = connection::pg_connection_read(self).await?; - let database_call = || async { - storage_type::ConnectorResponse::find_by_payment_id_merchant_id_attempt_id( - &conn, - payment_id, - merchant_id, - attempt_id, - ) - .await - .map_err(Into::into) - .into_report() - }; - match storage_scheme { - storage_enums::MerchantStorageScheme::PostgresOnly => database_call().await, - storage_enums::MerchantStorageScheme::RedisKv => { - let key = format!("mid_{merchant_id}_pid_{payment_id}"); - let field = format!("connector_resp_{merchant_id}_{payment_id}_{attempt_id}"); - - db_utils::try_redis_get_else_try_database_get( - async { - kv_wrapper( - self, - KvOperation::::HGet(&field), - key, - ) - .await? - .try_into_hget() - }, - database_call, - ) - .await - } - } - } - - async fn update_connector_response( - &self, - this: storage_type::ConnectorResponse, - connector_response_update: storage_type::ConnectorResponseUpdate, - storage_scheme: enums::MerchantStorageScheme, - ) -> CustomResult { - let conn = connection::pg_connection_write(self).await?; - match storage_scheme { - storage_enums::MerchantStorageScheme::PostgresOnly => this - .update(&conn, connector_response_update) - .await - .map_err(Into::into) - .into_report(), - storage_enums::MerchantStorageScheme::RedisKv => { - let key = format!("mid_{}_pid_{}", this.merchant_id, this.payment_id); - let updated_connector_response = connector_response_update - .clone() - .apply_changeset(this.clone()); - let redis_value = serde_json::to_string(&updated_connector_response) - .into_report() - .change_context(errors::StorageError::KVError)?; - let field = format!( - "connector_resp_{}_{}_{}", - &updated_connector_response.merchant_id, - &updated_connector_response.payment_id, - &updated_connector_response.attempt_id - ); - - let redis_entry = kv::TypedSql { - op: kv::DBOperation::Update { - updatable: kv::Updateable::ConnectorResponseUpdate( - kv::ConnectorResponseUpdateMems { - orig: this, - update_data: connector_response_update, - }, - ), - }, - }; - - kv_wrapper::<(), _, _>( - self, - KvOperation::Hset::( - (&field, redis_value), - redis_entry, - ), - &key, - ) - .await - .change_context(errors::StorageError::KVError)? - .try_into_hset() - .change_context(errors::StorageError::KVError)?; - - Ok(updated_connector_response) - } - } - } - } -} - -#[async_trait::async_trait] -impl ConnectorResponseInterface for MockDb { - #[instrument(skip_all)] - async fn insert_connector_response( - &self, - new: storage_type::ConnectorResponseNew, - storage_scheme: enums::MerchantStorageScheme, - ) -> CustomResult { - let mut connector_response = self.connector_response.lock().await; - let response = storage_type::ConnectorResponse { - id: connector_response - .len() - .try_into() - .into_report() - .change_context(errors::StorageError::MockDbError)?, - payment_id: new.payment_id, - merchant_id: new.merchant_id, - attempt_id: new.attempt_id, - created_at: new.created_at, - modified_at: new.modified_at, - connector_name: new.connector_name, - connector_transaction_id: new.connector_transaction_id, - authentication_data: new.authentication_data, - encoded_data: new.encoded_data, - updated_by: storage_scheme.to_string(), - }; - connector_response.push(response.clone()); - Ok(response) - } - - #[instrument(skip_all)] - async fn find_connector_response_by_payment_id_merchant_id_attempt_id( - &self, - _payment_id: &str, - _merchant_id: &str, - _attempt_id: &str, - _storage_scheme: enums::MerchantStorageScheme, - ) -> CustomResult { - // [#172]: Implement function for `MockDb` - Err(errors::StorageError::MockDbError)? - } - - // safety: interface only used for testing - #[allow(clippy::unwrap_used)] - async fn update_connector_response( - &self, - this: storage_type::ConnectorResponse, - connector_response_update: storage_type::ConnectorResponseUpdate, - _storage_scheme: enums::MerchantStorageScheme, - ) -> CustomResult { - let mut connector_response = self.connector_response.lock().await; - let response = connector_response - .iter_mut() - .find(|item| item.id == this.id) - .unwrap(); - *response = connector_response_update.apply_changeset(response.clone()); - Ok(response.clone()) - } -} diff --git a/crates/router/src/lib.rs b/crates/router/src/lib.rs index 21ebfc06137b..38efe8b75134 100644 --- a/crates/router/src/lib.rs +++ b/crates/router/src/lib.rs @@ -142,6 +142,7 @@ pub fn mk_app( .service(routes::Files::server(state.clone())) .service(routes::Disputes::server(state.clone())) .service(routes::Routing::server(state.clone())) + .service(routes::Gsm::server(state.clone())) } #[cfg(all(feature = "olap", feature = "kms"))] diff --git a/crates/router/src/routes.rs b/crates/router/src/routes.rs index 38f95c4cdda8..47b9f23cf8cb 100644 --- a/crates/router/src/routes.rs +++ b/crates/router/src/routes.rs @@ -10,6 +10,7 @@ pub mod disputes; pub mod dummy_connector; pub mod ephemeral_key; pub mod files; +pub mod gsm; pub mod health; pub mod lock_utils; pub mod mandates; @@ -36,7 +37,7 @@ pub use self::app::Routing; pub use self::app::Verify; pub use self::app::{ ApiKeys, AppState, BusinessProfile, Cache, Cards, Configs, Customers, Disputes, EphemeralKey, - Files, Health, Mandates, MerchantAccount, MerchantConnectorAccount, PaymentLink, + Files, Gsm, Health, Mandates, MerchantAccount, MerchantConnectorAccount, PaymentLink, PaymentMethods, Payments, Refunds, Webhooks, }; #[cfg(feature = "stripe")] diff --git a/crates/router/src/routes/app.rs b/crates/router/src/routes/app.rs index 8dbc440aa7de..0b97df1e7fc3 100644 --- a/crates/router/src/routes/app.rs +++ b/crates/router/src/routes/app.rs @@ -19,7 +19,7 @@ use super::routing as cloud_routing; #[cfg(all(feature = "olap", feature = "kms"))] use super::verification::{apple_pay_merchant_registration, retrieve_apple_pay_verified_domains}; #[cfg(feature = "olap")] -use super::{admin::*, api_keys::*, disputes::*, files::*}; +use super::{admin::*, api_keys::*, disputes::*, files::*, gsm::*}; use super::{cache::*, health::*, payment_link::*}; #[cfg(any(feature = "olap", feature = "oltp"))] use super::{configs::*, customers::*, mandates::*, payments::*, refunds::*}; @@ -676,6 +676,20 @@ impl BusinessProfile { } } +pub struct Gsm; + +#[cfg(feature = "olap")] +impl Gsm { + pub fn server(state: AppState) -> Scope { + web::scope("/gsm") + .app_data(web::Data::new(state)) + .service(web::resource("").route(web::post().to(create_gsm_rule))) + .service(web::resource("/get").route(web::post().to(get_gsm_rule))) + .service(web::resource("/update").route(web::post().to(update_gsm_rule))) + .service(web::resource("/delete").route(web::post().to(delete_gsm_rule))) + } +} + #[cfg(all(feature = "olap", feature = "kms"))] pub struct Verify; diff --git a/crates/router/src/routes/gsm.rs b/crates/router/src/routes/gsm.rs new file mode 100644 index 000000000000..02d943792dba --- /dev/null +++ b/crates/router/src/routes/gsm.rs @@ -0,0 +1,93 @@ +use actix_web::{web, HttpRequest, Responder}; +use api_models::gsm as gsm_api_types; +use router_env::{instrument, tracing, Flow}; + +use super::app::AppState; +use crate::{ + core::{api_locking, gsm}, + services::{api, authentication as auth}, +}; + +#[instrument(skip_all, fields(flow = ?Flow::GsmRuleCreate))] +pub async fn create_gsm_rule( + state: web::Data, + req: HttpRequest, + json_payload: web::Json, +) -> impl Responder { + let payload = json_payload.into_inner(); + + let flow = Flow::GsmRuleCreate; + Box::pin(api::server_wrap( + flow, + state.clone(), + &req, + payload, + |state, _, payload| gsm::create_gsm_rule(state, payload), + &auth::AdminApiAuth, + api_locking::LockAction::NotApplicable, + )) + .await +} + +#[instrument(skip_all, fields(flow = ?Flow::GsmRuleRetrieve))] +pub async fn get_gsm_rule( + state: web::Data, + req: HttpRequest, + json_payload: web::Json, +) -> impl Responder { + let gsm_retrieve_req = json_payload.into_inner(); + let flow = Flow::GsmRuleRetrieve; + Box::pin(api::server_wrap( + flow, + state.clone(), + &req, + gsm_retrieve_req, + |state, _, gsm_retrieve_req| gsm::retrieve_gsm_rule(state, gsm_retrieve_req), + &auth::AdminApiAuth, + api_locking::LockAction::NotApplicable, + )) + .await +} + +#[instrument(skip_all, fields(flow = ?Flow::GsmRuleUpdate))] +pub async fn update_gsm_rule( + state: web::Data, + req: HttpRequest, + json_payload: web::Json, +) -> impl Responder { + let payload = json_payload.into_inner(); + + let flow = Flow::GsmRuleUpdate; + Box::pin(api::server_wrap( + flow, + state.clone(), + &req, + payload, + |state, _, payload| gsm::update_gsm_rule(state, payload), + &auth::AdminApiAuth, + api_locking::LockAction::NotApplicable, + )) + .await +} + +#[instrument(skip_all, fields(flow = ?Flow::GsmRuleDelete))] +pub async fn delete_gsm_rule( + state: web::Data, + req: HttpRequest, + json_payload: web::Json, +) -> impl Responder { + let payload = json_payload.into_inner(); + + let flow = Flow::GsmRuleDelete; + + Box::pin(api::server_wrap( + flow, + state, + &req, + payload, + |state, _, payload| gsm::delete_gsm_rule(state, payload), + &auth::AdminApiAuth, + api_locking::LockAction::NotApplicable, + )) + .await +} diff --git a/crates/router/src/routes/lock_utils.rs b/crates/router/src/routes/lock_utils.rs index 14614268d79d..4e6fc1870f56 100644 --- a/crates/router/src/routes/lock_utils.rs +++ b/crates/router/src/routes/lock_utils.rs @@ -23,6 +23,7 @@ pub enum ApiIdentifier { ApiKeys, PaymentLink, Routing, + Gsm, } impl From for ApiIdentifier { @@ -129,6 +130,10 @@ impl From for ApiIdentifier { Flow::Verification => Self::Verification, Flow::PaymentLinkInitiate | Flow::PaymentLinkRetrieve => Self::PaymentLink, + Flow::GsmRuleCreate + | Flow::GsmRuleRetrieve + | Flow::GsmRuleUpdate + | Flow::GsmRuleDelete => Self::Gsm, } } } diff --git a/crates/router/src/types.rs b/crates/router/src/types.rs index 8f08ce062560..f2e86a4bf335 100644 --- a/crates/router/src/types.rs +++ b/crates/router/src/types.rs @@ -1193,3 +1193,5 @@ impl } } } + +pub type GsmResponse = storage::GatewayStatusMap; diff --git a/crates/router/src/types/storage.rs b/crates/router/src/types/storage.rs index 1e7c34a420b1..c63ff5fb7f86 100644 --- a/crates/router/src/types/storage.rs +++ b/crates/router/src/types/storage.rs @@ -4,7 +4,6 @@ pub mod business_profile; pub mod capture; pub mod cards_info; pub mod configs; -pub mod connector_response; pub mod customers; pub mod dispute; pub mod enums; @@ -41,11 +40,11 @@ pub use data_models::payments::{ }; pub use self::{ - address::*, api_keys::*, capture::*, cards_info::*, configs::*, connector_response::*, - customers::*, dispute::*, ephemeral_key::*, events::*, file::*, gsm::*, locker_mock_up::*, - mandate::*, merchant_account::*, merchant_connector_account::*, merchant_key_store::*, - payment_link::*, payment_method::*, payout_attempt::*, payouts::*, process_tracker::*, - refund::*, reverse_lookup::*, routing_algorithm::*, + address::*, api_keys::*, capture::*, cards_info::*, configs::*, customers::*, dispute::*, + ephemeral_key::*, events::*, file::*, gsm::*, locker_mock_up::*, mandate::*, + merchant_account::*, merchant_connector_account::*, merchant_key_store::*, payment_link::*, + payment_method::*, payout_attempt::*, payouts::*, process_tracker::*, refund::*, + reverse_lookup::*, routing_algorithm::*, }; use crate::types::api::routing; diff --git a/crates/router/src/types/storage/connector_response.rs b/crates/router/src/types/storage/connector_response.rs deleted file mode 100644 index c93c231e3d1c..000000000000 --- a/crates/router/src/types/storage/connector_response.rs +++ /dev/null @@ -1,41 +0,0 @@ -pub use diesel_models::{ - connector_response::{ - ConnectorResponse, ConnectorResponseNew, ConnectorResponseUpdate, - ConnectorResponseUpdateInternal, - }, - enums::MerchantStorageScheme, -}; - -pub trait ConnectorResponseExt { - fn make_new_connector_response( - payment_id: String, - merchant_id: String, - attempt_id: String, - connector: Option, - storage_scheme: String, - ) -> ConnectorResponseNew; -} - -impl ConnectorResponseExt for ConnectorResponse { - fn make_new_connector_response( - payment_id: String, - merchant_id: String, - attempt_id: String, - connector: Option, - storage_scheme: String, - ) -> ConnectorResponseNew { - let now = common_utils::date_time::now(); - ConnectorResponseNew { - payment_id, - merchant_id, - attempt_id, - created_at: now, - modified_at: now, - connector_name: connector, - connector_transaction_id: None, - authentication_data: None, - encoded_data: None, - updated_by: storage_scheme, - } - } -} diff --git a/crates/router/src/types/storage/kv.rs b/crates/router/src/types/storage/kv.rs index 2afc73e6637d..6bb6c38e7b26 100644 --- a/crates/router/src/types/storage/kv.rs +++ b/crates/router/src/types/storage/kv.rs @@ -1,4 +1,4 @@ pub use diesel_models::kv::{ - AddressUpdateMems, ConnectorResponseUpdateMems, DBOperation, Insertable, - PaymentAttemptUpdateMems, PaymentIntentUpdateMems, RefundUpdateMems, TypedSql, Updateable, + AddressUpdateMems, DBOperation, Insertable, PaymentAttemptUpdateMems, PaymentIntentUpdateMems, + RefundUpdateMems, TypedSql, Updateable, }; diff --git a/crates/router/src/types/transformers.rs b/crates/router/src/types/transformers.rs index 83ca0d014dc8..1cd016de18e6 100644 --- a/crates/router/src/types/transformers.rs +++ b/crates/router/src/types/transformers.rs @@ -1,6 +1,6 @@ // use actix_web::HttpMessage; use actix_web::http::header::HeaderMap; -use api_models::{enums as api_enums, payments, routing::ConnectorSelection}; +use api_models::{enums as api_enums, gsm as gsm_api_types, payments, routing::ConnectorSelection}; use common_utils::{ consts::X_HS_LATENCY, crypto::Encryptable, @@ -1031,3 +1031,19 @@ impl ForeignFrom } } } + +impl ForeignFrom for storage::GatewayStatusMappingNew { + fn foreign_from(value: gsm_api_types::GsmCreateRequest) -> Self { + Self { + connector: value.connector.to_string(), + flow: value.flow, + sub_flow: value.sub_flow, + code: value.code, + message: value.message, + decision: value.decision.to_string(), + status: value.status, + router_error: value.router_error, + step_up_possible: value.step_up_possible, + } + } +} diff --git a/crates/router_env/src/logger/types.rs b/crates/router_env/src/logger/types.rs index 9822432115b0..0c9751aee440 100644 --- a/crates/router_env/src/logger/types.rs +++ b/crates/router_env/src/logger/types.rs @@ -235,6 +235,14 @@ pub enum Flow { BusinessProfileList, /// Different verification flows Verification, + /// Gsm Rule Creation flow + GsmRuleCreate, + /// Gsm Rule Retrieve flow + GsmRuleRetrieve, + /// Gsm Rule Update flow + GsmRuleUpdate, + /// Gsm Rule Delete flow + GsmRuleDelete, } /// diff --git a/crates/storage_impl/src/connector_response.rs b/crates/storage_impl/src/connector_response.rs deleted file mode 100644 index 7d4ff6df94d9..000000000000 --- a/crates/storage_impl/src/connector_response.rs +++ /dev/null @@ -1,5 +0,0 @@ -use diesel_models::connector_response::ConnectorResponse; - -use crate::redis::kv_store::KvStorePartition; - -impl KvStorePartition for ConnectorResponse {} diff --git a/crates/storage_impl/src/lib.rs b/crates/storage_impl/src/lib.rs index cef4a8981a43..00d8703940c7 100644 --- a/crates/storage_impl/src/lib.rs +++ b/crates/storage_impl/src/lib.rs @@ -8,7 +8,6 @@ use redis::{kv_store::RedisConnInterface, RedisStore}; mod address; pub mod config; pub mod connection; -mod connector_response; pub mod database; pub mod errors; mod lookup; diff --git a/crates/storage_impl/src/mock_db.rs b/crates/storage_impl/src/mock_db.rs index 76bdb1160ccc..33f3f7a77f27 100644 --- a/crates/storage_impl/src/mock_db.rs +++ b/crates/storage_impl/src/mock_db.rs @@ -27,7 +27,6 @@ pub struct MockDb { pub customers: Arc>>, pub refunds: Arc>>, pub processes: Arc>>, - pub connector_response: Arc>>, pub redis: Arc, pub api_keys: Arc>>, pub ephemeral_keys: Arc>>, @@ -57,7 +56,6 @@ impl MockDb { customers: Default::default(), refunds: Default::default(), processes: Default::default(), - connector_response: Default::default(), redis: Arc::new( RedisStore::new(redis) .await diff --git a/crates/storage_impl/src/payments/payment_attempt.rs b/crates/storage_impl/src/payments/payment_attempt.rs index e3047221b6f5..21002917df83 100644 --- a/crates/storage_impl/src/payments/payment_attempt.rs +++ b/crates/storage_impl/src/payments/payment_attempt.rs @@ -1062,7 +1062,6 @@ impl DataModelExt for PaymentAttemptNew { connector_response_reference_id: self.connector_response_reference_id, multiple_capture_count: self.multiple_capture_count, amount_capturable: self.amount_capturable, - updated_by: self.updated_by, authentication_data: self.authentication_data, encoded_data: self.encoded_data, @@ -1244,6 +1243,8 @@ impl DataModelExt for PaymentAttemptUpdate { connector_response_reference_id, amount_capturable, updated_by, + authentication_data, + encoded_data, } => DieselPaymentAttemptUpdate::ResponseUpdate { status, connector, @@ -1259,6 +1260,8 @@ impl DataModelExt for PaymentAttemptUpdate { connector_response_reference_id, amount_capturable, updated_by, + authentication_data, + encoded_data, }, Self::UnresolvedResponseUpdate { status, @@ -1481,6 +1484,8 @@ impl DataModelExt for PaymentAttemptUpdate { connector_response_reference_id, amount_capturable, updated_by, + authentication_data, + encoded_data, } => Self::ResponseUpdate { status, connector, @@ -1496,6 +1501,8 @@ impl DataModelExt for PaymentAttemptUpdate { connector_response_reference_id, amount_capturable, updated_by, + authentication_data, + encoded_data, }, DieselPaymentAttemptUpdate::UnresolvedResponseUpdate { status, diff --git a/migrations/2023-10-25-070909_add_merchant_custom_name_payment_link/down.sql b/migrations/2023-10-25-070909_add_merchant_custom_name_payment_link/down.sql new file mode 100644 index 000000000000..84f009021df8 --- /dev/null +++ b/migrations/2023-10-25-070909_add_merchant_custom_name_payment_link/down.sql @@ -0,0 +1,2 @@ +-- This file should undo anything in `up.sql` +ALTER TABLE payment_link DROP COLUMN custom_merchant_name; diff --git a/migrations/2023-10-25-070909_add_merchant_custom_name_payment_link/up.sql b/migrations/2023-10-25-070909_add_merchant_custom_name_payment_link/up.sql new file mode 100644 index 000000000000..c4fa756e57a0 --- /dev/null +++ b/migrations/2023-10-25-070909_add_merchant_custom_name_payment_link/up.sql @@ -0,0 +1,2 @@ +-- Your SQL goes here +ALTER TABLE payment_link ADD COLUMN custom_merchant_name VARCHAR(64); \ No newline at end of file diff --git a/migrations/2023-11-08-144951_drop_connector_response_table/down.sql b/migrations/2023-11-08-144951_drop_connector_response_table/down.sql new file mode 100644 index 000000000000..ff9ca4e4f9c7 --- /dev/null +++ b/migrations/2023-11-08-144951_drop_connector_response_table/down.sql @@ -0,0 +1,34 @@ +-- This file should undo anything in `up.sql` +CREATE TABLE connector_response ( + id SERIAL PRIMARY KEY, + payment_id VARCHAR(255) NOT NULL, + merchant_id VARCHAR(255) NOT NULL, + txn_id VARCHAR(255) NOT NULL, + created_at TIMESTAMP NOT NULL DEFAULT now()::TIMESTAMP, + modified_at TIMESTAMP NOT NULL DEFAULT now()::TIMESTAMP, + connector_name VARCHAR(32) NOT NULL, + connector_transaction_id VARCHAR(255), + authentication_data JSON, + encoded_data TEXT +); + +CREATE UNIQUE INDEX connector_response_id_index ON connector_response (payment_id, merchant_id, txn_id); + +ALTER TABLE connector_response ALTER COLUMN connector_name DROP NOT NULL; +ALTER TABLE connector_response RENAME COLUMN txn_id TO attempt_id; +ALTER TABLE connector_response + ALTER COLUMN payment_id TYPE VARCHAR(64), + ALTER COLUMN merchant_id TYPE VARCHAR(64), + ALTER COLUMN attempt_id TYPE VARCHAR(64), + ALTER COLUMN connector_name TYPE VARCHAR(64), + ALTER COLUMN connector_transaction_id TYPE VARCHAR(128); + + + +ALTER TABLE connector_response +ALTER COLUMN modified_at DROP DEFAULT; + +ALTER TABLE connector_response +ALTER COLUMN created_at DROP DEFAULT; + +ALTER TABLE connector_response ADD column updated_by VARCHAR(32) NOT NULL DEFAULT 'postgres_only'; diff --git a/migrations/2023-11-08-144951_drop_connector_response_table/up.sql b/migrations/2023-11-08-144951_drop_connector_response_table/up.sql new file mode 100644 index 000000000000..0059a6b38dc1 --- /dev/null +++ b/migrations/2023-11-08-144951_drop_connector_response_table/up.sql @@ -0,0 +1,2 @@ +-- Your SQL goes here +DROP TABLE connector_response; --NOT to run in deployment envs \ No newline at end of file diff --git a/openapi/openapi_spec.json b/openapi/openapi_spec.json index 5af67e499275..6e61f2eb614e 100644 --- a/openapi/openapi_spec.json +++ b/openapi/openapi_spec.json @@ -7866,6 +7866,11 @@ "merchant_custom_domain_name": { "type": "string", "nullable": true + }, + "custom_merchant_name": { + "type": "string", + "description": "Custom merchant name for payment link", + "nullable": true } } },