diff --git a/crates/api_models/src/payments.rs b/crates/api_models/src/payments.rs index 535a5abffc..d1b658dab4 100644 --- a/crates/api_models/src/payments.rs +++ b/crates/api_models/src/payments.rs @@ -18,11 +18,7 @@ use error_stack::ResultExt; use masking::{ExposeInterface, PeekInterface, Secret, SwitchStrategy, WithType}; use router_derive::Setter; use rustc_hash::FxHashMap; -use serde::{ - de::{self, Unexpected, Visitor}, - ser::Serializer, - Deserialize, Deserializer, Serialize, -}; +use serde::{de, ser::Serializer, Deserialize, Deserializer, Serialize}; use strum::Display; use time::{Date, PrimitiveDateTime}; use url::Url; @@ -68,154 +64,6 @@ pub struct BankCodeResponse { pub eligible_connectors: Vec, } -#[derive(Debug, PartialEq, Clone)] -pub struct ClientSecret { - pub payment_id: id_type::PaymentId, - pub secret: String, -} - -impl ClientSecret { - pub fn get_client_secret(&self) -> String { - format!( - "{}_secret_{}", - self.payment_id.get_string_repr(), - self.secret - ) - } -} - -impl<'de> Deserialize<'de> for ClientSecret { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - struct ClientSecretVisitor; - - impl<'de> Visitor<'de> for ClientSecretVisitor { - type Value = ClientSecret; - - fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - formatter.write_str("a string in the format '{payment_id}_secret_{secret}'") - } - - fn visit_str(self, value: &str) -> Result - where - E: de::Error, - { - let (payment_id, secret) = value.rsplit_once("_secret_").ok_or_else(|| { - E::invalid_value(Unexpected::Str(value), &"a string with '_secret_'") - })?; - - let payment_id = - id_type::PaymentId::try_from(std::borrow::Cow::Owned(payment_id.to_owned())) - .map_err(de::Error::custom)?; - - Ok(ClientSecret { - payment_id, - secret: secret.to_owned(), - }) - } - } - - deserializer.deserialize_str(ClientSecretVisitor) - } -} - -impl Serialize for ClientSecret { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - let combined = format!( - "{}_secret_{}", - self.payment_id.get_string_repr(), - self.secret - ); - serializer.serialize_str(&combined) - } -} - -#[cfg(test)] -mod client_secret_tests { - #![allow(clippy::expect_used)] - #![allow(clippy::unwrap_used)] - - use serde_json; - - use super::*; - - #[test] - fn test_serialize_client_secret() { - let client_secret1 = ClientSecret { - payment_id: id_type::PaymentId::try_from(std::borrow::Cow::Borrowed( - "pay_3TgelAms4RQec8xSStjF", - )) - .unwrap(), - secret: "fc34taHLw1ekPgNh92qr".to_string(), - }; - let client_secret2 = ClientSecret { - payment_id: id_type::PaymentId::try_from(std::borrow::Cow::Borrowed( - "pay_3Tgel__Ams4RQ_secret_ec8xSStjF", - )) - .unwrap(), - secret: "fc34taHLw1ekPgNh92qr".to_string(), - }; - - let expected_str1 = r#""pay_3TgelAms4RQec8xSStjF_secret_fc34taHLw1ekPgNh92qr""#; - let expected_str2 = r#""pay_3Tgel__Ams4RQ_secret_ec8xSStjF_secret_fc34taHLw1ekPgNh92qr""#; - - let actual_str1 = - serde_json::to_string(&client_secret1).expect("Failed to serialize client_secret1"); - let actual_str2 = - serde_json::to_string(&client_secret2).expect("Failed to serialize client_secret2"); - - assert_eq!(expected_str1, actual_str1); - assert_eq!(expected_str2, actual_str2); - } - - #[test] - fn test_deserialize_client_secret() { - let client_secret_str1 = r#""pay_3TgelAms4RQec8xSStjF_secret_fc34taHLw1ekPgNh92qr""#; - let client_secret_str2 = - r#""pay_3Tgel__Ams4RQ_secret_ec8xSStjF_secret_fc34taHLw1ekPgNh92qr""#; - let client_secret_str3 = - r#""pay_3Tgel__Ams4RQ_secret_ec8xSStjF_secret__secret_fc34taHLw1ekPgNh92qr""#; - - let expected1 = ClientSecret { - payment_id: id_type::PaymentId::try_from(std::borrow::Cow::Borrowed( - "pay_3TgelAms4RQec8xSStjF", - )) - .unwrap(), - secret: "fc34taHLw1ekPgNh92qr".to_string(), - }; - let expected2 = ClientSecret { - payment_id: id_type::PaymentId::try_from(std::borrow::Cow::Borrowed( - "pay_3Tgel__Ams4RQ_secret_ec8xSStjF", - )) - .unwrap(), - secret: "fc34taHLw1ekPgNh92qr".to_string(), - }; - let expected3 = ClientSecret { - payment_id: id_type::PaymentId::try_from(std::borrow::Cow::Borrowed( - "pay_3Tgel__Ams4RQ_secret_ec8xSStjF_secret_", - )) - .unwrap(), - secret: "fc34taHLw1ekPgNh92qr".to_string(), - }; - - let actual1: ClientSecret = serde_json::from_str(client_secret_str1) - .expect("Failed to deserialize client_secret_str1"); - let actual2: ClientSecret = serde_json::from_str(client_secret_str2) - .expect("Failed to deserialize client_secret_str2"); - let actual3: ClientSecret = serde_json::from_str(client_secret_str3) - .expect("Failed to deserialize client_secret_str3"); - - assert_eq!(expected1, actual1); - assert_eq!(expected2, actual2); - assert_eq!(expected3, actual3); - } -} - /// Passing this object creates a new customer or attaches an existing customer to the payment #[derive(Debug, serde::Deserialize, serde::Serialize, Clone, ToSchema, PartialEq)] pub struct CustomerDetails { diff --git a/crates/common_enums/src/enums.rs b/crates/common_enums/src/enums.rs index 31cb43669b..65ef8d8725 100644 --- a/crates/common_enums/src/enums.rs +++ b/crates/common_enums/src/enums.rs @@ -3213,3 +3213,39 @@ pub enum DeleteStatus { Active, Redacted, } + +/// Whether 3ds authentication is requested or not +#[derive(Clone, Debug, PartialEq, serde::Serialize)] +pub enum External3dsAuthenticationRequest { + /// Request for 3ds authentication + Enable, + /// Skip 3ds authentication + Skip, +} + +/// Whether payment link is requested to be enabled or not for this transaction +#[derive(Clone, Debug, PartialEq, serde::Serialize)] +pub enum EnablePaymentLinkRequest { + /// Request for enabling payment link + Enable, + /// Skip enabling payment link + Skip, +} + +/// Whether mit exemption is requested or not +#[derive(Clone, Debug, PartialEq, serde::Serialize)] +pub enum MitExemptionRequest { + /// Request for applying MIT exemption + Apply, + /// Skip applying MIT exemption + Skip, +} + +/// Whether customer is present / absent during the payment +#[derive(Clone, Debug, PartialEq, serde::Serialize)] +pub enum PresenceOfCustomerDuringPayment { + /// Customer is present during the payment. This is the default value + Present, + /// Customer is absent during the payment + Absent, +} diff --git a/crates/common_enums/src/transformers.rs b/crates/common_enums/src/transformers.rs index fab570542c..db4162a8bb 100644 --- a/crates/common_enums/src/transformers.rs +++ b/crates/common_enums/src/transformers.rs @@ -1991,6 +1991,79 @@ mod custom_serde { } } +impl From> for super::External3dsAuthenticationRequest { + fn from(value: Option) -> Self { + match value { + Some(true) => Self::Enable, + _ => Self::Skip, + } + } +} + +/// Get the boolean value of the `External3dsAuthenticationRequest`. +impl super::External3dsAuthenticationRequest { + pub fn as_bool(&self) -> bool { + match self { + Self::Enable => true, + Self::Skip => false, + } + } +} + +impl super::EnablePaymentLinkRequest { + pub fn as_bool(&self) -> bool { + match self { + Self::Enable => true, + Self::Skip => false, + } + } +} + +impl From> for super::EnablePaymentLinkRequest { + fn from(value: Option) -> Self { + match value { + Some(true) => Self::Enable, + _ => Self::Skip, + } + } +} + +impl From> for super::MitExemptionRequest { + fn from(value: Option) -> Self { + match value { + Some(true) => Self::Apply, + _ => Self::Skip, + } + } +} + +impl super::MitExemptionRequest { + pub fn as_bool(&self) -> bool { + match self { + Self::Apply => true, + Self::Skip => false, + } + } +} + +impl From> for super::PresenceOfCustomerDuringPayment { + fn from(value: Option) -> Self { + match value { + Some(false) => Self::Absent, + _ => Self::Present, + } + } +} + +impl super::PresenceOfCustomerDuringPayment { + pub fn as_bool(&self) -> bool { + match self { + Self::Present => true, + Self::Absent => false, + } + } +} + #[cfg(test)] mod tests { #![allow(clippy::unwrap_used)] diff --git a/crates/common_utils/src/consts.rs b/crates/common_utils/src/consts.rs index 70f00ad9b3..ce9a3b2cae 100644 --- a/crates/common_utils/src/consts.rs +++ b/crates/common_utils/src/consts.rs @@ -147,5 +147,10 @@ pub const ROLE_ID_INTERNAL_VIEW_ONLY_USER: &str = "internal_view_only"; /// Role ID for Internal Admin pub const ROLE_ID_INTERNAL_ADMIN: &str = "internal_admin"; +/// Max length allowed for Description +pub const MAX_DESCRIPTION_LENGTH: u16 = 255; + +/// Max length allowed for Statement Descriptor +pub const MAX_STATEMENT_DESCRIPTOR_LENGTH: u16 = 255; /// Payout flow identifier used for performing GSM operations pub const PAYOUT_FLOW_STR: &str = "payout_flow"; diff --git a/crates/common_utils/src/id_type.rs b/crates/common_utils/src/id_type.rs index 20dc423310..26d2c0cdf6 100644 --- a/crates/common_utils/src/id_type.rs +++ b/crates/common_utils/src/id_type.rs @@ -11,9 +11,8 @@ mod payment; mod profile; mod routing; +#[cfg(feature = "v2")] mod global_id; -#[cfg(all(feature = "v2", feature = "payment_methods_v2"))] -mod payment_methods; pub use customer::CustomerId; use diesel::{ @@ -23,12 +22,12 @@ use diesel::{ serialize::{Output, ToSql}, sql_types, }; +#[cfg(feature = "v2")] +pub use global_id::{payment::GlobalPaymentId, payment_methods::GlobalPaymentMethodId, CellId}; pub use merchant::MerchantId; pub use merchant_connector_account::MerchantConnectorAccountId; pub use organization::OrganizationId; pub use payment::PaymentId; -#[cfg(all(feature = "v2", feature = "payment_methods_v2"))] -pub use payment_methods::GlobalPaymentMethodId; pub use profile::ProfileId; pub use routing::RoutingId; use serde::{Deserialize, Serialize}; @@ -155,6 +154,7 @@ impl LengthId); +pub struct CellId(LengthId); #[derive(Debug, Error, PartialEq, Eq)] pub enum CellIdError { @@ -107,7 +110,9 @@ impl GlobalId { Self(LengthId::new_unchecked(alphanumeric_id)) } - pub fn from_string(input_string: String) -> Result { + pub(crate) fn from_string( + input_string: std::borrow::Cow<'static, str>, + ) -> Result { let length_id = LengthId::from(input_string.into())?; let input_string = &length_id.0 .0; let (cell_id, remaining) = input_string @@ -118,6 +123,10 @@ impl GlobalId { Ok(Self(length_id)) } + + pub(crate) fn get_string_repr(&self) -> &str { + &self.0 .0 .0 + } } impl ToSql for GlobalId @@ -154,7 +163,7 @@ impl<'de> serde::Deserialize<'de> for GlobalId { D: serde::Deserializer<'de>, { let deserialized_string = String::deserialize(deserializer)?; - Self::from_string(deserialized_string).map_err(serde::de::Error::custom) + Self::from_string(deserialized_string.into()).map_err(serde::de::Error::custom) } } @@ -187,7 +196,7 @@ mod global_id_tests { #[test] fn test_global_id_from_string() { let input_string = "12345_cus_abcdefghijklmnopqrstuvwxyz1234567890"; - let global_id = GlobalId::from_string(input_string.to_string()).unwrap(); + let global_id = GlobalId::from_string(input_string.into()).unwrap(); assert_eq!(global_id.0 .0 .0, input_string); } diff --git a/crates/common_utils/src/id_type/global_id/payment.rs b/crates/common_utils/src/id_type/global_id/payment.rs new file mode 100644 index 0000000000..edc7e3fb96 --- /dev/null +++ b/crates/common_utils/src/id_type/global_id/payment.rs @@ -0,0 +1,63 @@ +use crate::errors; + +/// A global id that can be used to identify a payment +#[derive( + Debug, + Clone, + Hash, + PartialEq, + Eq, + serde::Serialize, + serde::Deserialize, + diesel::expression::AsExpression, +)] +#[diesel(sql_type = diesel::sql_types::Text)] +pub struct GlobalPaymentId(super::GlobalId); + +// Database related implementations so that this field can be used directly in the database tables +crate::impl_queryable_id_type!(GlobalPaymentId); + +impl GlobalPaymentId { + /// Get string representation of the id + pub fn get_string_repr(&self) -> &str { + self.0.get_string_repr() + } +} + +// TODO: refactor the macro to include this id use case as well +impl TryFrom> for GlobalPaymentId { + type Error = error_stack::Report; + fn try_from(value: std::borrow::Cow<'static, str>) -> Result { + use error_stack::ResultExt; + let merchant_ref_id = super::GlobalId::from_string(value).change_context( + errors::ValidationError::IncorrectValueProvided { + field_name: "payment_id", + }, + )?; + Ok(Self(merchant_ref_id)) + } +} + +// TODO: refactor the macro to include this id use case as well +impl diesel::serialize::ToSql for GlobalPaymentId +where + DB: diesel::backend::Backend, + super::GlobalId: diesel::serialize::ToSql, +{ + fn to_sql<'b>( + &'b self, + out: &mut diesel::serialize::Output<'b, '_, DB>, + ) -> diesel::serialize::Result { + self.0.to_sql(out) + } +} + +impl diesel::deserialize::FromSql for GlobalPaymentId +where + DB: diesel::backend::Backend, + super::GlobalId: diesel::deserialize::FromSql, +{ + fn from_sql(value: DB::RawValue<'_>) -> diesel::deserialize::Result { + super::GlobalId::from_sql(value).map(Self) + } +} diff --git a/crates/common_utils/src/id_type/payment_methods.rs b/crates/common_utils/src/id_type/global_id/payment_methods.rs similarity index 86% rename from crates/common_utils/src/id_type/payment_methods.rs rename to crates/common_utils/src/id_type/global_id/payment_methods.rs index f5cc215091..5ccb774f6e 100644 --- a/crates/common_utils/src/id_type/payment_methods.rs +++ b/crates/common_utils/src/id_type/global_id/payment_methods.rs @@ -27,9 +27,6 @@ pub enum GlobalPaymentMethodIdError { } impl GlobalPaymentMethodId { - fn get_global_id(&self) -> &GlobalId { - &self.0 - } /// Create a new GlobalPaymentMethodId from celll id information pub fn generate(cell_id: &str) -> error_stack::Result { let cell_id = CellId::from_string(cell_id.to_string())?; @@ -37,18 +34,18 @@ impl GlobalPaymentMethodId { Ok(Self(global_id)) } - pub fn get_string_repr(&self) -> String { - todo!() + pub fn get_string_repr(&self) -> &str { + self.0.get_string_repr() } pub fn generate_from_string(value: String) -> CustomResult { - let id = GlobalId::from_string(value) + let id = GlobalId::from_string(value.into()) .change_context(GlobalPaymentMethodIdError::ConstructionError)?; Ok(Self(id)) } } -impl diesel::Queryable for GlobalPaymentMethodId +impl diesel::Queryable for GlobalPaymentMethodId where DB: diesel::backend::Backend, Self: diesel::deserialize::FromSql, @@ -68,8 +65,7 @@ where &'b self, out: &mut diesel::serialize::Output<'b, '_, DB>, ) -> diesel::serialize::Result { - let id = self.get_global_id(); - id.to_sql(out) + self.0.to_sql(out) } } diff --git a/crates/common_utils/src/id_type/payment.rs b/crates/common_utils/src/id_type/payment.rs index e0269f2bef..c919076e9c 100644 --- a/crates/common_utils/src/id_type/payment.rs +++ b/crates/common_utils/src/id_type/payment.rs @@ -1,7 +1,7 @@ use crate::{ errors::{CustomResult, ValidationError}, generate_id_with_default_len, - id_type::{global_id, AlphaNumericId, LengthId}, + id_type::{AlphaNumericId, LengthId}, }; crate::id_type!( @@ -15,23 +15,10 @@ crate::impl_debug_id_type!(PaymentId); crate::impl_default_id_type!(PaymentId, "pay"); crate::impl_try_from_cow_str_id_type!(PaymentId, "payment_id"); +// Database related implementations so that this field can be used directly in the database tables crate::impl_queryable_id_type!(PaymentId); crate::impl_to_sql_from_sql_id_type!(PaymentId); -/// A global id that can be used to identify a payment -#[derive( - Debug, - Clone, - Hash, - PartialEq, - Eq, - serde::Serialize, - serde::Deserialize, - diesel::expression::AsExpression, -)] -#[diesel(sql_type = diesel::sql_types::Text)] -pub struct PaymentGlobalId(global_id::GlobalId); - impl PaymentId { /// Get the hash key to be stored in redis pub fn get_hash_key_for_kv_store(&self) -> String { diff --git a/crates/common_utils/src/types.rs b/crates/common_utils/src/types.rs index 2206744ef0..9906f3c911 100644 --- a/crates/common_utils/src/types.rs +++ b/crates/common_utils/src/types.rs @@ -5,6 +5,7 @@ pub mod keymanager; pub mod authentication; use std::{ + borrow::Cow, fmt::Display, ops::{Add, Sub}, primitive::i64, @@ -28,13 +29,16 @@ use rust_decimal::{ }; use semver::Version; use serde::{de::Visitor, Deserialize, Deserializer, Serialize}; +use thiserror::Error; use time::PrimitiveDateTime; use utoipa::ToSchema; use crate::{ - consts, + consts::{self, MAX_DESCRIPTION_LENGTH, MAX_STATEMENT_DESCRIPTOR_LENGTH}, errors::{CustomResult, ParsingError, PercentageError, ValidationError}, + fp_utils::when, }; + /// Represents Percentage Value between 0 and 100 both inclusive #[derive(Clone, Default, Debug, PartialEq, Serialize)] pub struct Percentage { @@ -583,6 +587,251 @@ impl StringMajorUnit { } } +#[derive( + Debug, + serde::Deserialize, + AsExpression, + serde::Serialize, + Clone, + PartialEq, + Eq, + Hash, + ToSchema, + PartialOrd, +)] +#[diesel(sql_type = sql_types::Text)] +/// This domain type can be used for any url +pub struct Url(url::Url); + +impl ToSql for Url +where + DB: Backend, + str: ToSql, +{ + fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, DB>) -> diesel::serialize::Result { + let url_string = self.0.as_str(); + url_string.to_sql(out) + } +} + +impl FromSql for Url +where + DB: Backend, + String: FromSql, +{ + fn from_sql(value: DB::RawValue<'_>) -> deserialize::Result { + let val = String::from_sql(value)?; + let url = url::Url::parse(&val)?; + Ok(Self(url)) + } +} + +#[cfg(feature = "v2")] +pub use client_secret_type::ClientSecret; +#[cfg(feature = "v2")] +mod client_secret_type { + use std::fmt; + + use masking::PeekInterface; + + use super::*; + use crate::id_type; + + /// A domain type that can be used to represent a client secret + /// Client secret is generated for a payment and is used to authenticate the client side api calls + #[derive(Debug, PartialEq, Clone, AsExpression)] + #[diesel(sql_type = sql_types::Text)] + pub struct ClientSecret { + /// The payment id of the payment + pub payment_id: id_type::GlobalPaymentId, + /// The secret string + pub secret: masking::Secret, + } + + impl ClientSecret { + pub(crate) fn get_string_repr(&self) -> String { + format!( + "{}_secret_{}", + self.payment_id.get_string_repr(), + self.secret.peek() + ) + } + } + + impl<'de> Deserialize<'de> for ClientSecret { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct ClientSecretVisitor; + + impl<'de> Visitor<'de> for ClientSecretVisitor { + type Value = ClientSecret; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("a string in the format '{payment_id}_secret_{secret}'") + } + + fn visit_str(self, value: &str) -> Result + where + E: serde::de::Error, + { + let (payment_id, secret) = value.rsplit_once("_secret_").ok_or_else(|| { + E::invalid_value( + serde::de::Unexpected::Str(value), + &"a string with '_secret_'", + ) + })?; + + let payment_id = + id_type::GlobalPaymentId::try_from(Cow::Owned(payment_id.to_owned())) + .map_err(serde::de::Error::custom)?; + + Ok(ClientSecret { + payment_id, + secret: masking::Secret::new(secret.to_owned()), + }) + } + } + + deserializer.deserialize_str(ClientSecretVisitor) + } + } + + impl Serialize for ClientSecret { + fn serialize(&self, serializer: S) -> Result + where + S: serde::ser::Serializer, + { + serializer.serialize_str(self.get_string_repr().as_str()) + } + } + + impl ToSql for ClientSecret + where + String: ToSql, + { + fn to_sql<'b>( + &'b self, + out: &mut Output<'b, '_, diesel::pg::Pg>, + ) -> diesel::serialize::Result { + let string_repr = self.get_string_repr(); + >::to_sql( + &string_repr, + &mut out.reborrow(), + ) + } + } + + impl FromSql for ClientSecret + where + DB: Backend, + String: FromSql, + { + fn from_sql(value: DB::RawValue<'_>) -> deserialize::Result { + let string_repr = String::from_sql(value)?; + Ok(serde_json::from_str(&string_repr)?) + } + } + + impl Queryable for ClientSecret + where + DB: Backend, + Self: FromSql, + { + type Row = Self; + + fn build(row: Self::Row) -> deserialize::Result { + Ok(row) + } + } + + #[cfg(test)] + mod client_secret_tests { + #![allow(clippy::expect_used)] + #![allow(clippy::unwrap_used)] + + use serde_json; + + use super::*; + use crate::id_type::GlobalPaymentId; + + #[test] + fn test_serialize_client_secret() { + let global_payment_id = "12345_pay_1a961ed9093c48b09781bf8ab17ba6bd"; + let secret = "fc34taHLw1ekPgNh92qr".to_string(); + + let expected_client_secret_string = format!("\"{global_payment_id}_secret_{secret}\""); + + let client_secret1 = ClientSecret { + payment_id: GlobalPaymentId::try_from(Cow::Borrowed(global_payment_id)).unwrap(), + secret: masking::Secret::new(secret), + }; + + let parsed_client_secret = + serde_json::to_string(&client_secret1).expect("Failed to serialize client_secret1"); + + assert_eq!(expected_client_secret_string, parsed_client_secret); + } + + #[test] + fn test_deserialize_client_secret() { + // This is a valid global id + let global_payment_id_str = "12345_pay_1a961ed9093c48b09781bf8ab17ba6bd"; + let secret = "fc34taHLw1ekPgNh92qr".to_string(); + + let valid_payment_global_id = + GlobalPaymentId::try_from(Cow::Borrowed(global_payment_id_str)) + .expect("Failed to create valid global payment id"); + + // This is an invalid global id because of the cell id being in invalid length + let invalid_global_payment_id = "123_pay_1a961ed9093c48b09781bf8ab17ba6bd"; + + // Create a client secret string which is valid + let valid_client_secret = format!(r#""{global_payment_id_str}_secret_{secret}""#); + + dbg!(&valid_client_secret); + + // Create a client secret string which is invalid + let invalid_client_secret_because_of_invalid_payment_id = + format!(r#""{invalid_global_payment_id}_secret_{secret}""#); + + // Create a client secret string which is invalid because of invalid secret + let invalid_client_secret_because_of_invalid_secret = + format!(r#""{invalid_global_payment_id}""#); + + let valid_client_secret = serde_json::from_str::(&valid_client_secret) + .expect("Failed to deserialize client_secret_str1"); + + let invalid_deser1 = serde_json::from_str::( + &invalid_client_secret_because_of_invalid_payment_id, + ); + + dbg!(&invalid_deser1); + + let invalid_deser2 = serde_json::from_str::( + &invalid_client_secret_because_of_invalid_secret, + ); + + dbg!(&invalid_deser2); + + assert_eq!(valid_client_secret.payment_id, valid_payment_global_id); + + assert_eq!(valid_client_secret.secret.peek(), &secret); + + assert_eq!( + invalid_deser1.err().unwrap().to_string(), + "Incorrect value provided for field: payment_id at line 1 column 70" + ); + + assert_eq!( + invalid_deser2.err().unwrap().to_string(), + "invalid value: string \"123_pay_1a961ed9093c48b09781bf8ab17ba6bd\", expected a string with '_secret_' at line 1 column 42" + ); + } + } +} + /// A type representing a range of time for filtering, including a mandatory start time and an optional end time. #[derive( Debug, Clone, Copy, serde::Serialize, serde::Deserialize, PartialEq, Eq, Hash, ToSchema, @@ -725,31 +974,107 @@ pub struct ChargeRefunds { crate::impl_to_sql_from_sql_json!(ChargeRefunds); -/// Domain type for description -#[derive( - Debug, Clone, PartialEq, Eq, Queryable, serde::Deserialize, serde::Serialize, AsExpression, -)] +/// A common type of domain type that can be used for fields that contain a string with restriction of length +#[derive(Debug, Clone, Serialize, Hash, PartialEq, Eq, AsExpression)] #[diesel(sql_type = sql_types::Text)] -pub struct Description(String); +pub(crate) struct LengthString(String); + +/// Error generated from violation of constraints for MerchantReferenceId +#[derive(Debug, Error, PartialEq, Eq)] +pub(crate) enum LengthStringError { + #[error("the maximum allowed length for this field is {0}")] + /// Maximum length of string violated + MaxLengthViolated(u16), + + #[error("the minimum required length for this field is {0}")] + /// Minimum length of string violated + MinLengthViolated(u8), +} + +impl LengthString { + /// Generates new [MerchantReferenceId] from the given input string + pub fn from(input_string: Cow<'static, str>) -> Result { + let trimmed_input_string = input_string.trim().to_string(); + let length_of_input_string = u16::try_from(trimmed_input_string.len()) + .map_err(|_| LengthStringError::MaxLengthViolated(MAX_LENGTH))?; + + when(length_of_input_string > MAX_LENGTH, || { + Err(LengthStringError::MaxLengthViolated(MAX_LENGTH)) + })?; + + when(length_of_input_string < u16::from(MIN_LENGTH), || { + Err(LengthStringError::MinLengthViolated(MIN_LENGTH)) + })?; + + Ok(Self(trimmed_input_string)) + } + + pub(crate) fn new_unchecked(input_string: String) -> Self { + Self(input_string) + } +} + +impl<'de, const MAX_LENGTH: u16, const MIN_LENGTH: u8> Deserialize<'de> + for LengthString +{ + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let deserialized_string = String::deserialize(deserializer)?; + Self::from(deserialized_string.into()).map_err(serde::de::Error::custom) + } +} + +impl FromSql for LengthString +where + DB: Backend, + String: FromSql, +{ + fn from_sql(bytes: DB::RawValue<'_>) -> deserialize::Result { + let val = String::from_sql(bytes)?; + Ok(Self(val)) + } +} + +impl ToSql + for LengthString +where + DB: Backend, + String: ToSql, +{ + fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, DB>) -> diesel::serialize::Result { + self.0.to_sql(out) + } +} + +impl Queryable for LengthString +where + DB: Backend, + Self: FromSql, +{ + type Row = Self; + fn build(row: Self::Row) -> deserialize::Result { + Ok(row) + } +} + +/// Domain type for description +#[derive(Debug, Clone, PartialEq, Eq, serde::Deserialize, serde::Serialize, AsExpression)] +#[diesel(sql_type = sql_types::Text)] +pub struct Description(LengthString); impl Description { - /// Create a new Description Domain type - pub fn new(value: String) -> Self { - Self(value) + /// Create a new Description Domain type without any length check from a static str + pub fn from_str_unchecked(input_str: &'static str) -> Self { + Self(LengthString::new_unchecked(input_str.to_owned())) } } -impl From for String { - fn from(description: Description) -> Self { - description.0 - } -} - -impl From for Description { - fn from(description: String) -> Self { - Self(description) - } -} +/// Domain type for Statement Descriptor +#[derive(Debug, Clone, PartialEq, Eq, serde::Deserialize, serde::Serialize, AsExpression)] +#[diesel(sql_type = sql_types::Text)] +pub struct StatementDescriptor(LengthString); impl Queryable for Description where @@ -766,18 +1091,51 @@ where impl FromSql for Description where DB: Backend, - String: FromSql, + LengthString: FromSql, { fn from_sql(bytes: DB::RawValue<'_>) -> deserialize::Result { - let val = String::from_sql(bytes)?; - Ok(Self::from(val)) + let val = LengthString::::from_sql(bytes)?; + Ok(Self(val)) } } impl ToSql for Description where DB: Backend, - String: ToSql, + LengthString: ToSql, +{ + fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, DB>) -> diesel::serialize::Result { + self.0.to_sql(out) + } +} + +impl Queryable for StatementDescriptor +where + DB: Backend, + Self: FromSql, +{ + type Row = Self; + + fn build(row: Self::Row) -> deserialize::Result { + Ok(row) + } +} + +impl FromSql for StatementDescriptor +where + DB: Backend, + LengthString: FromSql, +{ + fn from_sql(bytes: DB::RawValue<'_>) -> deserialize::Result { + let val = LengthString::::from_sql(bytes)?; + Ok(Self(val)) + } +} + +impl ToSql for StatementDescriptor +where + DB: Backend, + LengthString: ToSql, { fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, DB>) -> diesel::serialize::Result { self.0.to_sql(out) diff --git a/crates/diesel_models/src/payment_intent.rs b/crates/diesel_models/src/payment_intent.rs index 42424c9bff..c6ebbe671e 100644 --- a/crates/diesel_models/src/payment_intent.rs +++ b/crates/diesel_models/src/payment_intent.rs @@ -17,13 +17,12 @@ pub struct PaymentIntent { pub merchant_id: common_utils::id_type::MerchantId, pub status: storage_enums::IntentStatus, pub amount: MinorUnit, - pub currency: Option, + pub currency: storage_enums::Currency, pub amount_captured: Option, pub customer_id: Option, - pub description: Option, - pub return_url: Option, - pub metadata: Option, - pub statement_descriptor_name: Option, + pub description: Option, + pub return_url: Option, + pub metadata: Option, #[serde(with = "common_utils::custom_serde::iso8601")] pub created_at: PrimitiveDateTime, #[serde(with = "common_utils::custom_serde::iso8601")] @@ -31,48 +30,46 @@ pub struct PaymentIntent { #[serde(default, with = "common_utils::custom_serde::iso8601::option")] pub last_synced: Option, pub setup_future_usage: Option, - pub off_session: Option, - pub client_secret: Option, + pub client_secret: common_utils::types::ClientSecret, pub active_attempt_id: String, #[diesel(deserialize_as = super::OptionalDieselArray)] pub order_details: Option>, - pub allowed_payment_method_types: Option, - pub connector_metadata: Option, - pub feature_metadata: Option, + pub allowed_payment_method_types: Option, + pub connector_metadata: Option, + pub feature_metadata: Option, pub attempt_count: i16, - pub profile_id: Option, + pub profile_id: common_utils::id_type::ProfileId, pub payment_link_id: Option, - pub payment_confirm_source: Option, - pub updated_by: String, pub surcharge_applicable: Option, pub request_incremental_authorization: Option, pub authorization_count: Option, pub session_expiry: Option, pub request_external_three_ds_authentication: Option, - pub charges: Option, pub frm_metadata: Option, pub customer_details: Option, - pub merchant_order_reference_id: Option, - pub is_payment_processor_token_flow: Option, pub shipping_cost: Option, pub organization_id: common_utils::id_type::OrganizationId, pub tax_details: Option, pub skip_external_tax_calculation: Option, - pub merchant_reference_id: String, + pub merchant_reference_id: Option, pub billing_address: Option, pub shipping_address: Option, pub capture_method: Option, pub authentication_type: Option, - pub amount_to_capture: Option, pub prerouting_algorithm: Option, pub surcharge_amount: Option, pub tax_on_surcharge: Option, // Denotes the action(approve or reject) taken by merchant in case of manual review. // Manual review can occur when the transaction is marked as risky by the frm_processor, payment processor or when there is underpayment/over payment incase of crypto payment - pub frm_merchant_decision: Option, - // TODO: change this to global id - pub id: common_utils::id_type::PaymentId, + pub frm_merchant_decision: Option, + pub statement_descriptor: Option, + pub enable_payment_link: Option, + pub apply_mit_exemption: Option, + pub customer_present: Option, + pub routing_algorithm_id: Option, + pub payment_link_config: Option, + pub id: common_utils::id_type::GlobalPaymentId, } #[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "payment_v2")))] @@ -139,10 +136,59 @@ pub struct PaymentIntent { pub skip_external_tax_calculation: Option, } +#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, PartialEq)] +pub struct PaymentLinkConfigRequestForPayments { + /// custom theme for the payment link + pub theme: Option, + /// merchant display logo + pub logo: Option, + /// Custom merchant name for payment link + pub seller_name: Option, + /// Custom layout for sdk + pub sdk_layout: Option, + /// Display only the sdk for payment link + pub display_sdk_only: Option, + /// Enable saved payment method option for payment link + pub enabled_saved_payment_method: Option, + /// Dynamic details related to merchant to be rendered in payment link + pub transaction_details: Option>, +} + +common_utils::impl_to_sql_from_sql_json!(PaymentLinkConfigRequestForPayments); + +#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, PartialEq)] +pub struct PaymentLinkTransactionDetails { + /// Key for the transaction details + pub key: String, + /// Value for the transaction details + pub value: String, + /// UI configuration for the transaction details + pub ui_configuration: Option, +} + +common_utils::impl_to_sql_from_sql_json!(PaymentLinkTransactionDetails); + +#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, PartialEq)] +pub struct TransactionDetailsUiConfiguration { + /// Position of the key-value pair in the UI + pub position: Option, + /// Whether the key should be bold + pub is_key_bold: Option, + /// Whether the value should be bold + pub is_value_bold: Option, +} + +common_utils::impl_to_sql_from_sql_json!(TransactionDetailsUiConfiguration); + #[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize, diesel::AsExpression)] #[diesel(sql_type = diesel::sql_types::Jsonb)] pub struct TaxDetails { + /// This is the tax related information that is calculated irrespective of any payment method. + /// This is calculated when the order is created with shipping details pub default: Option, + + /// This is the tax related information that is calculated based on the payment method + /// This is calculated when calling the /calculate_tax API pub payment_method_type: Option, } @@ -168,13 +214,12 @@ pub struct PaymentIntentNew { pub merchant_id: common_utils::id_type::MerchantId, pub status: storage_enums::IntentStatus, pub amount: MinorUnit, - pub currency: Option, + pub currency: storage_enums::Currency, pub amount_captured: Option, pub customer_id: Option, - pub description: Option, - pub return_url: Option, - pub metadata: Option, - pub statement_descriptor_name: Option, + pub description: Option, + pub return_url: Option, + pub metadata: Option, #[serde(with = "common_utils::custom_serde::iso8601")] pub created_at: PrimitiveDateTime, #[serde(with = "common_utils::custom_serde::iso8601")] @@ -182,18 +227,16 @@ pub struct PaymentIntentNew { #[serde(default, with = "common_utils::custom_serde::iso8601::option")] pub last_synced: Option, pub setup_future_usage: Option, - pub off_session: Option, - pub client_secret: Option, + pub client_secret: common_utils::types::ClientSecret, pub active_attempt_id: String, #[diesel(deserialize_as = super::OptionalDieselArray)] pub order_details: Option>, - pub allowed_payment_method_types: Option, - pub connector_metadata: Option, - pub feature_metadata: Option, + pub allowed_payment_method_types: Option, + pub connector_metadata: Option, + pub feature_metadata: Option, pub attempt_count: i16, - pub profile_id: Option, + pub profile_id: common_utils::id_type::ProfileId, pub payment_link_id: Option, - pub payment_confirm_source: Option, pub updated_by: String, pub surcharge_applicable: Option, pub request_incremental_authorization: Option, @@ -201,29 +244,25 @@ pub struct PaymentIntentNew { #[serde(with = "common_utils::custom_serde::iso8601::option")] pub session_expiry: Option, pub request_external_three_ds_authentication: Option, - pub charges: Option, pub frm_metadata: Option, pub customer_details: Option, - pub merchant_order_reference_id: Option, - pub is_payment_processor_token_flow: Option, pub shipping_cost: Option, pub organization_id: common_utils::id_type::OrganizationId, pub tax_details: Option, pub skip_external_tax_calculation: Option, - pub merchant_reference_id: String, + pub merchant_reference_id: Option, pub billing_address: Option, pub shipping_address: Option, pub capture_method: Option, pub authentication_type: Option, - pub amount_to_capture: Option, pub prerouting_algorithm: Option, pub surcharge_amount: Option, pub tax_on_surcharge: Option, - // Denotes the action(approve or reject) taken by merchant in case of manual review. - // Manual review can occur when the transaction is marked as risky by the frm_processor, payment processor or when there is underpayment/over payment incase of crypto payment - pub frm_merchant_decision: Option, - // TODO: change this to global id - pub id: common_utils::id_type::PaymentId, + pub frm_merchant_decision: Option, + pub statement_descriptor: Option, + pub enable_payment_link: Option, + pub apply_mit_exemption: Option, + pub id: common_utils::id_type::GlobalPaymentId, } #[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "payment_v2")))] @@ -305,7 +344,7 @@ pub enum PaymentIntentUpdate { // incremental_authorization_allowed: Option, }, MetadataUpdate { - metadata: serde_json::Value, + metadata: pii::SecretSerdeValue, updated_by: String, }, Update(Box), @@ -464,9 +503,9 @@ pub struct PaymentIntentUpdateFields { pub billing_address: Option, pub return_url: Option, pub description: Option, - pub statement_descriptor_name: Option, + pub statement_descriptor: Option, pub order_details: Option>, - pub metadata: Option, + pub metadata: Option, pub payment_confirm_source: Option, pub updated_by: String, pub session_expiry: Option, @@ -520,16 +559,14 @@ pub struct PaymentIntentUpdateInternal { pub customer_id: Option, pub return_url: Option, pub setup_future_usage: Option, - pub off_session: Option, - pub metadata: Option, + pub metadata: Option, pub modified_at: PrimitiveDateTime, pub active_attempt_id: Option, pub description: Option, - pub statement_descriptor_name: Option, + pub statement_descriptor: Option, #[diesel(deserialize_as = super::OptionalDieselArray)] pub order_details: Option>, pub attempt_count: Option, - pub payment_confirm_source: Option, pub updated_by: String, pub surcharge_applicable: Option, pub authorization_count: Option, @@ -539,8 +576,6 @@ pub struct PaymentIntentUpdateInternal { pub customer_details: Option, pub billing_address: Option, pub shipping_address: Option, - pub merchant_order_reference_id: Option, - pub is_payment_processor_token_flow: Option, pub frm_merchant_decision: Option, } @@ -590,71 +625,71 @@ pub struct PaymentIntentUpdateInternal { #[cfg(all(feature = "v2", feature = "payment_v2"))] impl PaymentIntentUpdate { pub fn apply_changeset(self, source: PaymentIntent) -> PaymentIntent { - let PaymentIntentUpdateInternal { - amount, - currency, - status, - amount_captured, - customer_id, - return_url, - setup_future_usage, - off_session, - metadata, - modified_at: _, - active_attempt_id, - description, - statement_descriptor_name, - order_details, - attempt_count, - frm_merchant_decision, - payment_confirm_source, - updated_by, - surcharge_applicable, - authorization_count, - session_expiry, - request_external_three_ds_authentication, - frm_metadata, - customer_details, - billing_address, - merchant_order_reference_id, - shipping_address, - is_payment_processor_token_flow, - } = self.into(); - PaymentIntent { - amount: amount.unwrap_or(source.amount), - currency: currency.or(source.currency), - status: status.unwrap_or(source.status), - amount_captured: amount_captured.or(source.amount_captured), - customer_id: customer_id.or(source.customer_id), - return_url: return_url.or(source.return_url), - setup_future_usage: setup_future_usage.or(source.setup_future_usage), - off_session: off_session.or(source.off_session), - metadata: metadata.or(source.metadata), - modified_at: common_utils::date_time::now(), - active_attempt_id: active_attempt_id.unwrap_or(source.active_attempt_id), - description: description.or(source.description), - statement_descriptor_name: statement_descriptor_name - .or(source.statement_descriptor_name), - order_details: order_details.or(source.order_details), - attempt_count: attempt_count.unwrap_or(source.attempt_count), - frm_merchant_decision: frm_merchant_decision.or(source.frm_merchant_decision), - payment_confirm_source: payment_confirm_source.or(source.payment_confirm_source), - updated_by, - surcharge_applicable: surcharge_applicable.or(source.surcharge_applicable), - authorization_count: authorization_count.or(source.authorization_count), - session_expiry: session_expiry.or(source.session_expiry), - request_external_three_ds_authentication: request_external_three_ds_authentication - .or(source.request_external_three_ds_authentication), - frm_metadata: frm_metadata.or(source.frm_metadata), - customer_details: customer_details.or(source.customer_details), - billing_address: billing_address.or(source.billing_address), - shipping_address: shipping_address.or(source.shipping_address), - merchant_order_reference_id: merchant_order_reference_id - .or(source.merchant_order_reference_id), - is_payment_processor_token_flow: is_payment_processor_token_flow - .or(source.is_payment_processor_token_flow), - ..source - } + todo!() + // let PaymentIntentUpdateInternal { + // amount, + // currency, + // status, + // amount_captured, + // customer_id, + // return_url, + // setup_future_usage, + // off_session, + // metadata, + // modified_at: _, + // active_attempt_id, + // description, + // statement_descriptor, + // order_details, + // attempt_count, + // frm_merchant_decision, + // payment_confirm_source, + // updated_by, + // surcharge_applicable, + // authorization_count, + // session_expiry, + // request_external_three_ds_authentication, + // frm_metadata, + // customer_details, + // billing_address, + // merchant_order_reference_id, + // shipping_address, + // is_payment_processor_token_flow, + // } = self.into(); + // PaymentIntent { + // amount: amount.unwrap_or(source.amount), + // currency: currency.unwrap_or(source.currency), + // status: status.unwrap_or(source.status), + // amount_captured: amount_captured.or(source.amount_captured), + // customer_id: customer_id.or(source.customer_id), + // return_url: return_url.or(source.return_url), + // setup_future_usage: setup_future_usage.or(source.setup_future_usage), + // off_session: off_session.or(source.off_session), + // metadata: metadata.or(source.metadata), + // modified_at: common_utils::date_time::now(), + // active_attempt_id: active_attempt_id.unwrap_or(source.active_attempt_id), + // description: description.or(source.description), + // statement_descriptor: statement_descriptor.or(source.statement_descriptor), + // order_details: order_details.or(source.order_details), + // attempt_count: attempt_count.unwrap_or(source.attempt_count), + // frm_merchant_decision: frm_merchant_decision.or(source.frm_merchant_decision), + // payment_confirm_source: payment_confirm_source.or(source.payment_confirm_source), + // updated_by, + // surcharge_applicable: surcharge_applicable.or(source.surcharge_applicable), + // authorization_count: authorization_count.or(source.authorization_count), + // session_expiry: session_expiry.or(source.session_expiry), + // request_external_three_ds_authentication: request_external_three_ds_authentication + // .or(source.request_external_three_ds_authentication), + // frm_metadata: frm_metadata.or(source.frm_metadata), + // customer_details: customer_details.or(source.customer_details), + // billing_address: billing_address.or(source.billing_address), + // shipping_address: shipping_address.or(source.shipping_address), + // merchant_order_reference_id: merchant_order_reference_id + // .or(source.merchant_order_reference_id), + // is_payment_processor_token_flow: is_payment_processor_token_flow + // .or(source.is_payment_processor_token_flow), + // ..source + // } } } @@ -751,508 +786,509 @@ impl PaymentIntentUpdate { #[cfg(all(feature = "v2", feature = "payment_v2"))] impl From for PaymentIntentUpdateInternal { fn from(payment_intent_update: PaymentIntentUpdate) -> Self { - match payment_intent_update { - PaymentIntentUpdate::MetadataUpdate { - metadata, - updated_by, - } => Self { - metadata: Some(metadata), - modified_at: common_utils::date_time::now(), - updated_by, - amount: None, - currency: None, - status: None, - amount_captured: None, - customer_id: None, - return_url: None, - setup_future_usage: None, - off_session: None, - active_attempt_id: None, - description: None, - statement_descriptor_name: None, - order_details: None, - attempt_count: None, - frm_merchant_decision: None, - payment_confirm_source: None, - surcharge_applicable: None, - authorization_count: None, - session_expiry: None, - request_external_three_ds_authentication: None, - frm_metadata: None, - customer_details: None, - billing_address: None, - merchant_order_reference_id: None, - shipping_address: None, - is_payment_processor_token_flow: None, - }, - PaymentIntentUpdate::Update(value) => Self { - amount: Some(value.amount), - currency: Some(value.currency), - setup_future_usage: value.setup_future_usage, - status: Some(value.status), - customer_id: value.customer_id, - shipping_address: value.shipping_address, - billing_address: value.billing_address, - return_url: value.return_url, - description: value.description, - statement_descriptor_name: value.statement_descriptor_name, - order_details: value.order_details, - metadata: value.metadata, - payment_confirm_source: value.payment_confirm_source, - updated_by: value.updated_by, - session_expiry: value.session_expiry, - request_external_three_ds_authentication: value - .request_external_three_ds_authentication, - frm_metadata: value.frm_metadata, - customer_details: value.customer_details, - merchant_order_reference_id: value.merchant_order_reference_id, - amount_captured: None, - off_session: None, - modified_at: common_utils::date_time::now(), - active_attempt_id: None, - attempt_count: None, - frm_merchant_decision: None, - surcharge_applicable: None, - authorization_count: None, - is_payment_processor_token_flow: value.is_payment_processor_token_flow, - }, - PaymentIntentUpdate::PaymentCreateUpdate { - return_url, - status, - customer_id, - shipping_address, - billing_address, - customer_details, - updated_by, - } => Self { - return_url, - status, - customer_id, - customer_details, - modified_at: common_utils::date_time::now(), - updated_by, - amount: None, - currency: None, - amount_captured: None, - setup_future_usage: None, - off_session: None, - metadata: None, - active_attempt_id: None, - description: None, - statement_descriptor_name: None, - order_details: None, - attempt_count: None, - frm_merchant_decision: None, - payment_confirm_source: None, - surcharge_applicable: None, - authorization_count: None, - session_expiry: None, - request_external_three_ds_authentication: None, - frm_metadata: None, - billing_address, - merchant_order_reference_id: None, - shipping_address, - is_payment_processor_token_flow: None, - }, - PaymentIntentUpdate::PGStatusUpdate { status, updated_by } => Self { - status: Some(status), - modified_at: common_utils::date_time::now(), - updated_by, - amount: None, - currency: None, - amount_captured: None, - customer_id: None, - return_url: None, - setup_future_usage: None, - off_session: None, - metadata: None, - active_attempt_id: None, - description: None, - statement_descriptor_name: None, - order_details: None, - attempt_count: None, - frm_merchant_decision: None, - payment_confirm_source: None, - surcharge_applicable: None, - authorization_count: None, - session_expiry: None, - request_external_three_ds_authentication: None, - frm_metadata: None, - customer_details: None, - billing_address: None, - merchant_order_reference_id: None, - shipping_address: None, - is_payment_processor_token_flow: None, - }, - PaymentIntentUpdate::MerchantStatusUpdate { - status, - billing_address, - shipping_address, - updated_by, - } => Self { - status: Some(status), - modified_at: common_utils::date_time::now(), - updated_by, - amount: None, - currency: None, - amount_captured: None, - customer_id: None, - return_url: None, - setup_future_usage: None, - off_session: None, - metadata: None, - active_attempt_id: None, - description: None, - statement_descriptor_name: None, - order_details: None, - attempt_count: None, - frm_merchant_decision: None, - payment_confirm_source: None, - surcharge_applicable: None, - authorization_count: None, - session_expiry: None, - request_external_three_ds_authentication: None, - frm_metadata: None, - customer_details: None, - billing_address, - merchant_order_reference_id: None, - shipping_address, - is_payment_processor_token_flow: None, - }, - PaymentIntentUpdate::ResponseUpdate { - // amount, - // currency, - status, - amount_captured, - // customer_id, - return_url, - updated_by, - } => Self { - // amount, - // currency: Some(currency), - status: Some(status), - amount_captured, - // customer_id, - return_url, - modified_at: common_utils::date_time::now(), - updated_by, - amount: None, - currency: None, - customer_id: None, - setup_future_usage: None, - off_session: None, - metadata: None, - active_attempt_id: None, - description: None, - statement_descriptor_name: None, - order_details: None, - attempt_count: None, - frm_merchant_decision: None, - payment_confirm_source: None, - surcharge_applicable: None, - authorization_count: None, - session_expiry: None, - request_external_three_ds_authentication: None, - frm_metadata: None, - customer_details: None, - billing_address: None, - merchant_order_reference_id: None, - shipping_address: None, - is_payment_processor_token_flow: None, - }, - PaymentIntentUpdate::PaymentAttemptAndAttemptCountUpdate { - active_attempt_id, - attempt_count, - updated_by, - } => Self { - active_attempt_id: Some(active_attempt_id), - attempt_count: Some(attempt_count), - updated_by, - amount: None, - currency: None, - status: None, - amount_captured: None, - customer_id: None, - return_url: None, - setup_future_usage: None, - off_session: None, - metadata: None, - modified_at: common_utils::date_time::now(), - description: None, - statement_descriptor_name: None, - order_details: None, - frm_merchant_decision: None, - payment_confirm_source: None, - surcharge_applicable: None, - authorization_count: None, - session_expiry: None, - request_external_three_ds_authentication: None, - frm_metadata: None, - customer_details: None, - billing_address: None, - merchant_order_reference_id: None, - shipping_address: None, - is_payment_processor_token_flow: None, - }, - PaymentIntentUpdate::StatusAndAttemptUpdate { - status, - active_attempt_id, - attempt_count, - updated_by, - } => Self { - status: Some(status), - active_attempt_id: Some(active_attempt_id), - attempt_count: Some(attempt_count), - updated_by, - amount: None, - currency: None, - amount_captured: None, - customer_id: None, - return_url: None, - setup_future_usage: None, - off_session: None, - metadata: None, - modified_at: common_utils::date_time::now(), - description: None, - statement_descriptor_name: None, - order_details: None, - frm_merchant_decision: None, - payment_confirm_source: None, - surcharge_applicable: None, - authorization_count: None, - session_expiry: None, - request_external_three_ds_authentication: None, - frm_metadata: None, - customer_details: None, - billing_address: None, - merchant_order_reference_id: None, - shipping_address: None, - is_payment_processor_token_flow: None, - }, - PaymentIntentUpdate::ApproveUpdate { - status, - frm_merchant_decision, - updated_by, - } => Self { - status: Some(status), - frm_merchant_decision, - updated_by, - amount: None, - currency: None, - amount_captured: None, - customer_id: None, - return_url: None, - setup_future_usage: None, - off_session: None, - metadata: None, - modified_at: common_utils::date_time::now(), - active_attempt_id: None, - description: None, - statement_descriptor_name: None, - order_details: None, - attempt_count: None, - payment_confirm_source: None, - surcharge_applicable: None, - authorization_count: None, - session_expiry: None, - request_external_three_ds_authentication: None, - frm_metadata: None, - customer_details: None, - billing_address: None, - merchant_order_reference_id: None, - shipping_address: None, - is_payment_processor_token_flow: None, - }, - PaymentIntentUpdate::RejectUpdate { - status, - frm_merchant_decision, - updated_by, - } => Self { - status: Some(status), - frm_merchant_decision, - updated_by, - amount: None, - currency: None, - amount_captured: None, - customer_id: None, - return_url: None, - setup_future_usage: None, - off_session: None, - metadata: None, - modified_at: common_utils::date_time::now(), - active_attempt_id: None, - description: None, - statement_descriptor_name: None, - order_details: None, - attempt_count: None, - payment_confirm_source: None, - surcharge_applicable: None, - authorization_count: None, - session_expiry: None, - request_external_three_ds_authentication: None, - frm_metadata: None, - customer_details: None, - billing_address: None, - merchant_order_reference_id: None, - shipping_address: None, - is_payment_processor_token_flow: None, - }, - PaymentIntentUpdate::SurchargeApplicableUpdate { - surcharge_applicable, - updated_by, - } => Self { - surcharge_applicable, - updated_by, - amount: None, - currency: None, - status: None, - amount_captured: None, - customer_id: None, - return_url: None, - setup_future_usage: None, - off_session: None, - metadata: None, - modified_at: common_utils::date_time::now(), - active_attempt_id: None, - description: None, - statement_descriptor_name: None, - order_details: None, - attempt_count: None, - frm_merchant_decision: None, - payment_confirm_source: None, - authorization_count: None, - session_expiry: None, - request_external_three_ds_authentication: None, - frm_metadata: None, - customer_details: None, - billing_address: None, - merchant_order_reference_id: None, - shipping_address: None, - is_payment_processor_token_flow: None, - }, - PaymentIntentUpdate::IncrementalAuthorizationAmountUpdate { amount } => Self { - amount: Some(amount), - currency: None, - status: None, - amount_captured: None, - customer_id: None, - return_url: None, - setup_future_usage: None, - off_session: None, - metadata: None, - modified_at: common_utils::date_time::now(), - active_attempt_id: None, - description: None, - statement_descriptor_name: None, - order_details: None, - attempt_count: None, - frm_merchant_decision: None, - payment_confirm_source: None, - updated_by: String::default(), - surcharge_applicable: None, - authorization_count: None, - session_expiry: None, - request_external_three_ds_authentication: None, - frm_metadata: None, - customer_details: None, - billing_address: None, - merchant_order_reference_id: None, - shipping_address: None, - is_payment_processor_token_flow: None, - }, - PaymentIntentUpdate::AuthorizationCountUpdate { - authorization_count, - } => Self { - authorization_count: Some(authorization_count), - amount: None, - currency: None, - status: None, - amount_captured: None, - customer_id: None, - return_url: None, - setup_future_usage: None, - off_session: None, - metadata: None, - modified_at: common_utils::date_time::now(), - active_attempt_id: None, - description: None, - statement_descriptor_name: None, - order_details: None, - attempt_count: None, - frm_merchant_decision: None, - payment_confirm_source: None, - updated_by: String::default(), - surcharge_applicable: None, - session_expiry: None, - request_external_three_ds_authentication: None, - frm_metadata: None, - customer_details: None, - billing_address: None, - merchant_order_reference_id: None, - shipping_address: None, - is_payment_processor_token_flow: None, - }, - PaymentIntentUpdate::CompleteAuthorizeUpdate { shipping_address } => Self { - amount: None, - currency: None, - status: None, - amount_captured: None, - customer_id: None, - return_url: None, - setup_future_usage: None, - off_session: None, - metadata: None, - modified_at: common_utils::date_time::now(), - active_attempt_id: None, - description: None, - statement_descriptor_name: None, - order_details: None, - attempt_count: None, - frm_merchant_decision: None, - payment_confirm_source: None, - updated_by: String::default(), - surcharge_applicable: None, - authorization_count: None, - session_expiry: None, - request_external_three_ds_authentication: None, - frm_metadata: None, - customer_details: None, - billing_address: None, - merchant_order_reference_id: None, - shipping_address, - is_payment_processor_token_flow: None, - }, - PaymentIntentUpdate::ManualUpdate { status, updated_by } => Self { - status, - updated_by, - amount: None, - currency: None, - amount_captured: None, - customer_id: None, - return_url: None, - setup_future_usage: None, - off_session: None, - metadata: None, - modified_at: common_utils::date_time::now(), - active_attempt_id: None, - description: None, - statement_descriptor_name: None, - order_details: None, - attempt_count: None, - frm_merchant_decision: None, - payment_confirm_source: None, - surcharge_applicable: None, - authorization_count: None, - session_expiry: None, - request_external_three_ds_authentication: None, - frm_metadata: None, - customer_details: None, - billing_address: None, - merchant_order_reference_id: None, - shipping_address: None, - is_payment_processor_token_flow: None, - }, - } + todo!() + // match payment_intent_update { + // PaymentIntentUpdate::MetadataUpdate { + // metadata, + // updated_by, + // } => Self { + // metadata: Some(metadata), + // modified_at: common_utils::date_time::now(), + // updated_by, + // amount: None, + // currency: None, + // status: None, + // amount_captured: None, + // customer_id: None, + // return_url: None, + // setup_future_usage: None, + // off_session: None, + // active_attempt_id: None, + // description: None, + // statement_descriptor: None, + // order_details: None, + // attempt_count: None, + // frm_merchant_decision: None, + // payment_confirm_source: None, + // surcharge_applicable: None, + // authorization_count: None, + // session_expiry: None, + // request_external_three_ds_authentication: None, + // frm_metadata: None, + // customer_details: None, + // billing_address: None, + // merchant_order_reference_id: None, + // shipping_address: None, + // is_payment_processor_token_flow: None, + // }, + // PaymentIntentUpdate::Update(value) => Self { + // amount: Some(value.amount), + // currency: Some(value.currency), + // setup_future_usage: value.setup_future_usage, + // status: Some(value.status), + // customer_id: value.customer_id, + // shipping_address: value.shipping_address, + // billing_address: value.billing_address, + // return_url: value.return_url, + // description: value.description, + // statement_descriptor: value.statement_descriptor, + // order_details: value.order_details, + // metadata: value.metadata, + // payment_confirm_source: value.payment_confirm_source, + // updated_by: value.updated_by, + // session_expiry: value.session_expiry, + // request_external_three_ds_authentication: value + // .request_external_three_ds_authentication, + // frm_metadata: value.frm_metadata, + // customer_details: value.customer_details, + // merchant_order_reference_id: value.merchant_order_reference_id, + // amount_captured: None, + // off_session: None, + // modified_at: common_utils::date_time::now(), + // active_attempt_id: None, + // attempt_count: None, + // frm_merchant_decision: None, + // surcharge_applicable: None, + // authorization_count: None, + // is_payment_processor_token_flow: value.is_payment_processor_token_flow, + // }, + // PaymentIntentUpdate::PaymentCreateUpdate { + // return_url, + // status, + // customer_id, + // shipping_address, + // billing_address, + // customer_details, + // updated_by, + // } => Self { + // return_url, + // status, + // customer_id, + // customer_details, + // modified_at: common_utils::date_time::now(), + // updated_by, + // amount: None, + // currency: None, + // amount_captured: None, + // setup_future_usage: None, + // off_session: None, + // metadata: None, + // active_attempt_id: None, + // description: None, + // statement_descriptor: None, + // order_details: None, + // attempt_count: None, + // frm_merchant_decision: None, + // payment_confirm_source: None, + // surcharge_applicable: None, + // authorization_count: None, + // session_expiry: None, + // request_external_three_ds_authentication: None, + // frm_metadata: None, + // billing_address, + // merchant_order_reference_id: None, + // shipping_address, + // is_payment_processor_token_flow: None, + // }, + // PaymentIntentUpdate::PGStatusUpdate { status, updated_by } => Self { + // status: Some(status), + // modified_at: common_utils::date_time::now(), + // updated_by, + // amount: None, + // currency: None, + // amount_captured: None, + // customer_id: None, + // return_url: None, + // setup_future_usage: None, + // off_session: None, + // metadata: None, + // active_attempt_id: None, + // description: None, + // statement_descriptor: None, + // order_details: None, + // attempt_count: None, + // frm_merchant_decision: None, + // payment_confirm_source: None, + // surcharge_applicable: None, + // authorization_count: None, + // session_expiry: None, + // request_external_three_ds_authentication: None, + // frm_metadata: None, + // customer_details: None, + // billing_address: None, + // merchant_order_reference_id: None, + // shipping_address: None, + // is_payment_processor_token_flow: None, + // }, + // PaymentIntentUpdate::MerchantStatusUpdate { + // status, + // billing_address, + // shipping_address, + // updated_by, + // } => Self { + // status: Some(status), + // modified_at: common_utils::date_time::now(), + // updated_by, + // amount: None, + // currency: None, + // amount_captured: None, + // customer_id: None, + // return_url: None, + // setup_future_usage: None, + // off_session: None, + // metadata: None, + // active_attempt_id: None, + // description: None, + // statement_descriptor: None, + // order_details: None, + // attempt_count: None, + // frm_merchant_decision: None, + // payment_confirm_source: None, + // surcharge_applicable: None, + // authorization_count: None, + // session_expiry: None, + // request_external_three_ds_authentication: None, + // frm_metadata: None, + // customer_details: None, + // billing_address, + // merchant_order_reference_id: None, + // shipping_address, + // is_payment_processor_token_flow: None, + // }, + // PaymentIntentUpdate::ResponseUpdate { + // // amount, + // // currency, + // status, + // amount_captured, + // // customer_id, + // return_url, + // updated_by, + // } => Self { + // // amount, + // // currency: Some(currency), + // status: Some(status), + // amount_captured, + // // customer_id, + // return_url, + // modified_at: common_utils::date_time::now(), + // updated_by, + // amount: None, + // currency: None, + // customer_id: None, + // setup_future_usage: None, + // off_session: None, + // metadata: None, + // active_attempt_id: None, + // description: None, + // statement_descriptor: None, + // order_details: None, + // attempt_count: None, + // frm_merchant_decision: None, + // payment_confirm_source: None, + // surcharge_applicable: None, + // authorization_count: None, + // session_expiry: None, + // request_external_three_ds_authentication: None, + // frm_metadata: None, + // customer_details: None, + // billing_address: None, + // merchant_order_reference_id: None, + // shipping_address: None, + // is_payment_processor_token_flow: None, + // }, + // PaymentIntentUpdate::PaymentAttemptAndAttemptCountUpdate { + // active_attempt_id, + // attempt_count, + // updated_by, + // } => Self { + // active_attempt_id: Some(active_attempt_id), + // attempt_count: Some(attempt_count), + // updated_by, + // amount: None, + // currency: None, + // status: None, + // amount_captured: None, + // customer_id: None, + // return_url: None, + // setup_future_usage: None, + // off_session: None, + // metadata: None, + // modified_at: common_utils::date_time::now(), + // description: None, + // statement_descriptor: None, + // order_details: None, + // frm_merchant_decision: None, + // payment_confirm_source: None, + // surcharge_applicable: None, + // authorization_count: None, + // session_expiry: None, + // request_external_three_ds_authentication: None, + // frm_metadata: None, + // customer_details: None, + // billing_address: None, + // merchant_order_reference_id: None, + // shipping_address: None, + // is_payment_processor_token_flow: None, + // }, + // PaymentIntentUpdate::StatusAndAttemptUpdate { + // status, + // active_attempt_id, + // attempt_count, + // updated_by, + // } => Self { + // status: Some(status), + // active_attempt_id: Some(active_attempt_id), + // attempt_count: Some(attempt_count), + // updated_by, + // amount: None, + // currency: None, + // amount_captured: None, + // customer_id: None, + // return_url: None, + // setup_future_usage: None, + // off_session: None, + // metadata: None, + // modified_at: common_utils::date_time::now(), + // description: None, + // statement_descriptor: None, + // order_details: None, + // frm_merchant_decision: None, + // payment_confirm_source: None, + // surcharge_applicable: None, + // authorization_count: None, + // session_expiry: None, + // request_external_three_ds_authentication: None, + // frm_metadata: None, + // customer_details: None, + // billing_address: None, + // merchant_order_reference_id: None, + // shipping_address: None, + // is_payment_processor_token_flow: None, + // }, + // PaymentIntentUpdate::ApproveUpdate { + // status, + // frm_merchant_decision, + // updated_by, + // } => Self { + // status: Some(status), + // frm_merchant_decision, + // updated_by, + // amount: None, + // currency: None, + // amount_captured: None, + // customer_id: None, + // return_url: None, + // setup_future_usage: None, + // off_session: None, + // metadata: None, + // modified_at: common_utils::date_time::now(), + // active_attempt_id: None, + // description: None, + // statement_descriptor: None, + // order_details: None, + // attempt_count: None, + // payment_confirm_source: None, + // surcharge_applicable: None, + // authorization_count: None, + // session_expiry: None, + // request_external_three_ds_authentication: None, + // frm_metadata: None, + // customer_details: None, + // billing_address: None, + // merchant_order_reference_id: None, + // shipping_address: None, + // is_payment_processor_token_flow: None, + // }, + // PaymentIntentUpdate::RejectUpdate { + // status, + // frm_merchant_decision, + // updated_by, + // } => Self { + // status: Some(status), + // frm_merchant_decision, + // updated_by, + // amount: None, + // currency: None, + // amount_captured: None, + // customer_id: None, + // return_url: None, + // setup_future_usage: None, + // off_session: None, + // metadata: None, + // modified_at: common_utils::date_time::now(), + // active_attempt_id: None, + // description: None, + // statement_descriptor: None, + // order_details: None, + // attempt_count: None, + // payment_confirm_source: None, + // surcharge_applicable: None, + // authorization_count: None, + // session_expiry: None, + // request_external_three_ds_authentication: None, + // frm_metadata: None, + // customer_details: None, + // billing_address: None, + // merchant_order_reference_id: None, + // shipping_address: None, + // is_payment_processor_token_flow: None, + // }, + // PaymentIntentUpdate::SurchargeApplicableUpdate { + // surcharge_applicable, + // updated_by, + // } => Self { + // surcharge_applicable, + // updated_by, + // amount: None, + // currency: None, + // status: None, + // amount_captured: None, + // customer_id: None, + // return_url: None, + // setup_future_usage: None, + // off_session: None, + // metadata: None, + // modified_at: common_utils::date_time::now(), + // active_attempt_id: None, + // description: None, + // statement_descriptor: None, + // order_details: None, + // attempt_count: None, + // frm_merchant_decision: None, + // payment_confirm_source: None, + // authorization_count: None, + // session_expiry: None, + // request_external_three_ds_authentication: None, + // frm_metadata: None, + // customer_details: None, + // billing_address: None, + // merchant_order_reference_id: None, + // shipping_address: None, + // is_payment_processor_token_flow: None, + // }, + // PaymentIntentUpdate::IncrementalAuthorizationAmountUpdate { amount } => Self { + // amount: Some(amount), + // currency: None, + // status: None, + // amount_captured: None, + // customer_id: None, + // return_url: None, + // setup_future_usage: None, + // off_session: None, + // metadata: None, + // modified_at: common_utils::date_time::now(), + // active_attempt_id: None, + // description: None, + // statement_descriptor: None, + // order_details: None, + // attempt_count: None, + // frm_merchant_decision: None, + // payment_confirm_source: None, + // updated_by: String::default(), + // surcharge_applicable: None, + // authorization_count: None, + // session_expiry: None, + // request_external_three_ds_authentication: None, + // frm_metadata: None, + // customer_details: None, + // billing_address: None, + // merchant_order_reference_id: None, + // shipping_address: None, + // is_payment_processor_token_flow: None, + // }, + // PaymentIntentUpdate::AuthorizationCountUpdate { + // authorization_count, + // } => Self { + // authorization_count: Some(authorization_count), + // amount: None, + // currency: None, + // status: None, + // amount_captured: None, + // customer_id: None, + // return_url: None, + // setup_future_usage: None, + // off_session: None, + // metadata: None, + // modified_at: common_utils::date_time::now(), + // active_attempt_id: None, + // description: None, + // statement_descriptor: None, + // order_details: None, + // attempt_count: None, + // frm_merchant_decision: None, + // payment_confirm_source: None, + // updated_by: String::default(), + // surcharge_applicable: None, + // session_expiry: None, + // request_external_three_ds_authentication: None, + // frm_metadata: None, + // customer_details: None, + // billing_address: None, + // merchant_order_reference_id: None, + // shipping_address: None, + // is_payment_processor_token_flow: None, + // }, + // PaymentIntentUpdate::CompleteAuthorizeUpdate { shipping_address } => Self { + // amount: None, + // currency: None, + // status: None, + // amount_captured: None, + // customer_id: None, + // return_url: None, + // setup_future_usage: None, + // off_session: None, + // metadata: None, + // modified_at: common_utils::date_time::now(), + // active_attempt_id: None, + // description: None, + // statement_descriptor: None, + // order_details: None, + // attempt_count: None, + // frm_merchant_decision: None, + // payment_confirm_source: None, + // updated_by: String::default(), + // surcharge_applicable: None, + // authorization_count: None, + // session_expiry: None, + // request_external_three_ds_authentication: None, + // frm_metadata: None, + // customer_details: None, + // billing_address: None, + // merchant_order_reference_id: None, + // shipping_address, + // is_payment_processor_token_flow: None, + // }, + // PaymentIntentUpdate::ManualUpdate { status, updated_by } => Self { + // status, + // updated_by, + // amount: None, + // currency: None, + // amount_captured: None, + // customer_id: None, + // return_url: None, + // setup_future_usage: None, + // off_session: None, + // metadata: None, + // modified_at: common_utils::date_time::now(), + // active_attempt_id: None, + // description: None, + // statement_descriptor: None, + // order_details: None, + // attempt_count: None, + // frm_merchant_decision: None, + // payment_confirm_source: None, + // surcharge_applicable: None, + // authorization_count: None, + // session_expiry: None, + // request_external_three_ds_authentication: None, + // frm_metadata: None, + // customer_details: None, + // billing_address: None, + // merchant_order_reference_id: None, + // shipping_address: None, + // is_payment_processor_token_flow: None, + // }, + // } } } diff --git a/crates/diesel_models/src/query/payment_intent.rs b/crates/diesel_models/src/query/payment_intent.rs index ccf82d2804..e148c76686 100644 --- a/crates/diesel_models/src/query/payment_intent.rs +++ b/crates/diesel_models/src/query/payment_intent.rs @@ -44,7 +44,7 @@ impl PaymentIntent { #[cfg(all(feature = "v2", feature = "payment_v2"))] pub async fn find_by_global_id( conn: &PgPooledConn, - id: &common_utils::id_type::PaymentId, + id: &common_utils::id_type::GlobalPaymentId, ) -> StorageResult { generics::generic_find_by_id::<::Table, _, _>(conn, id.to_owned()).await } @@ -105,7 +105,7 @@ impl PaymentIntent { } #[cfg(all(feature = "v2", feature = "payment_v2"))] - pub async fn find_optional_by_merchant_id_merchant_reference_id( + pub async fn find_optional_by_merchant_reference_id_merchant_id( conn: &PgPooledConn, merchant_reference_id: &str, merchant_id: &common_utils::id_type::MerchantId, diff --git a/crates/diesel_models/src/schema_v2.rs b/crates/diesel_models/src/schema_v2.rs index ca62d2c477..a66286e02d 100644 --- a/crates/diesel_models/src/schema_v2.rs +++ b/crates/diesel_models/src/schema_v2.rs @@ -836,7 +836,7 @@ diesel::table! { merchant_id -> Varchar, status -> IntentStatus, amount -> Int8, - currency -> Nullable, + currency -> Currency, amount_captured -> Nullable, #[max_length = 64] customer_id -> Nullable, @@ -845,15 +845,12 @@ diesel::table! { #[max_length = 255] return_url -> Nullable, metadata -> Nullable, - #[max_length = 255] - statement_descriptor_name -> Nullable, created_at -> Timestamp, modified_at -> Timestamp, last_synced -> Nullable, setup_future_usage -> Nullable, - off_session -> Nullable, #[max_length = 128] - client_secret -> Nullable, + client_secret -> Varchar, #[max_length = 64] active_attempt_id -> Varchar, order_details -> Nullable>>, @@ -862,10 +859,9 @@ diesel::table! { feature_metadata -> Nullable, attempt_count -> Int2, #[max_length = 64] - profile_id -> Nullable, + profile_id -> Varchar, #[max_length = 255] payment_link_id -> Nullable, - payment_confirm_source -> Nullable, #[max_length = 32] updated_by -> Varchar, surcharge_applicable -> Nullable, @@ -873,29 +869,32 @@ diesel::table! { authorization_count -> Nullable, session_expiry -> Nullable, request_external_three_ds_authentication -> Nullable, - charges -> Nullable, frm_metadata -> Nullable, customer_details -> Nullable, - #[max_length = 255] - merchant_order_reference_id -> Nullable, - is_payment_processor_token_flow -> Nullable, shipping_cost -> Nullable, #[max_length = 32] organization_id -> Varchar, tax_details -> Nullable, skip_external_tax_calculation -> Nullable, #[max_length = 64] - merchant_reference_id -> Varchar, + merchant_reference_id -> Nullable, billing_address -> Nullable, shipping_address -> Nullable, capture_method -> Nullable, authentication_type -> Nullable, - amount_to_capture -> Nullable, prerouting_algorithm -> Nullable, surcharge_amount -> Nullable, tax_on_surcharge -> Nullable, #[max_length = 64] frm_merchant_decision -> Nullable, + #[max_length = 255] + statement_descriptor -> Nullable, + enable_payment_link -> Nullable, + apply_mit_exemption -> Nullable, + customer_present -> Nullable, + #[max_length = 64] + routing_algorithm_id -> Nullable, + payment_link_config -> Nullable, #[max_length = 64] id -> Varchar, } diff --git a/crates/hyperswitch_domain_models/src/payments.rs b/crates/hyperswitch_domain_models/src/payments.rs index fee2155e8d..da56a1dc30 100644 --- a/crates/hyperswitch_domain_models/src/payments.rs +++ b/crates/hyperswitch_domain_models/src/payments.rs @@ -82,70 +82,180 @@ impl PaymentIntent { } #[cfg(all(feature = "v2", feature = "payment_v2",))] - pub fn get_id(&self) -> &id_type::PaymentId { + pub fn get_id(&self) -> &id_type::GlobalPaymentId { &self.id } } +#[cfg(feature = "v2")] +#[derive(Clone, Debug, PartialEq, serde::Serialize)] +pub enum TaxCalculationOverride { + /// Skip calling the external tax provider + Skip, + /// Calculate tax by calling the external tax provider + Calculate, +} + +#[cfg(feature = "v2")] +#[derive(Clone, Debug, PartialEq, serde::Serialize)] +pub enum SurchargeCalculationOverride { + /// Skip calculating surcharge + Skip, + /// Calculate surcharge + Calculate, +} + +#[cfg(feature = "v2")] +impl From> for TaxCalculationOverride { + fn from(value: Option) -> Self { + match value { + Some(true) => TaxCalculationOverride::Calculate, + _ => TaxCalculationOverride::Skip, + } + } +} + +#[cfg(feature = "v2")] +impl From> for SurchargeCalculationOverride { + fn from(value: Option) -> Self { + match value { + Some(true) => SurchargeCalculationOverride::Calculate, + _ => SurchargeCalculationOverride::Skip, + } + } +} + +#[cfg(feature = "v2")] +#[derive(Clone, Debug, PartialEq, serde::Serialize)] +pub struct AmountDetails { + /// The amount of the order in the lowest denomination of currency + order_amount: MinorUnit, + /// The currency of the order + currency: common_enums::Currency, + /// The shipping cost of the order. This has to be collected from the merchant + shipping_cost: Option, + /// Tax details related to the order. This will be calculated by the external tax provider + tax_details: Option, + /// The action to whether calculate tax by calling external tax provider or not + skip_external_tax_calculation: TaxCalculationOverride, + /// The action to whether calculate surcharge or not + skip_surcharge_calculation: SurchargeCalculationOverride, + /// The surcharge amount to be added to the order, collected from the merchant + surcharge_amount: Option, + /// tax on surcharge amount + tax_on_surcharge: Option, +} + +#[cfg(feature = "v2")] +impl AmountDetails { + /// Get the action to whether calculate surcharge or not as a boolean value + fn get_surcharge_action_as_bool(&self) -> bool { + match self.skip_surcharge_calculation { + SurchargeCalculationOverride::Skip => false, + SurchargeCalculationOverride::Calculate => true, + } + } + + /// Get the action to whether calculate external tax or not as a boolean value + fn get_external_tax_action_as_bool(&self) -> bool { + match self.skip_external_tax_calculation { + TaxCalculationOverride::Skip => false, + TaxCalculationOverride::Calculate => true, + } + } +} + #[cfg(all(feature = "v2", feature = "payment_v2"))] #[derive(Clone, Debug, PartialEq, serde::Serialize)] pub struct PaymentIntent { + /// The global identifier for the payment intent. This is generated by the system. + /// The format of the global id is `{cell_id:5}_pay_{time_ordered_uuid:32}`. + pub id: id_type::GlobalPaymentId, + /// The identifier for the merchant. This is automatically derived from the api key used to create the payment. pub merchant_id: id_type::MerchantId, + /// The status of payment intent. pub status: storage_enums::IntentStatus, - pub amount: MinorUnit, - pub currency: Option, + /// The amount related details of the payment + pub amount_details: AmountDetails, + /// The total amount captured for the order. This is the sum of all the captured amounts for the order. pub amount_captured: Option, + /// The identifier for the customer. This is the identifier for the customer in the merchant's system. pub customer_id: Option, - pub description: Option, - pub return_url: Option, - pub metadata: Option, - pub statement_descriptor_name: Option, + /// The description of the order. This will be passed to connectors which support description. + pub description: Option, + /// The return url for the payment. This is the url to which the user will be redirected after the payment is completed. + pub return_url: Option, + /// The metadata for the payment intent. This is the metadata that will be passed to the connectors. + pub metadata: Option, + /// The statement descriptor for the order, this will be displayed in the user's bank statement. + pub statement_descriptor: Option, + /// The time at which the order was created #[serde(with = "common_utils::custom_serde::iso8601")] pub created_at: PrimitiveDateTime, + /// The time at which the order was last modified #[serde(with = "common_utils::custom_serde::iso8601")] pub modified_at: PrimitiveDateTime, #[serde(with = "common_utils::custom_serde::iso8601::option")] pub last_synced: Option, pub setup_future_usage: Option, - pub off_session: Option, - pub client_secret: Option, + /// The client secret that is generated for the payment. This is used to authenticate the payment from client facing apis. + pub client_secret: common_utils::types::ClientSecret, + /// The active attempt for the payment intent. This is the payment attempt that is currently active for the payment intent. pub active_attempt: RemoteStorageObject, + /// The order details for the payment. pub order_details: Option>, - pub allowed_payment_method_types: Option, - pub connector_metadata: Option, - pub feature_metadata: Option, + /// This is the list of payment method types that are allowed for the payment intent. + /// This field allows the merchant to restrict the payment methods that can be used for the payment intent. + pub allowed_payment_method_types: Option, + /// This metadata contains details about + pub connector_metadata: Option, + pub feature_metadata: Option, + /// Number of attempts that have been made for the order pub attempt_count: i16, - pub profile_id: Option, + /// The profile id for the payment. + pub profile_id: id_type::ProfileId, + /// The payment link id for the payment. This is generated only if `enable_payment_link` is set to true. pub payment_link_id: Option, - // Denotes the action(approve or reject) taken by merchant in case of manual review. - // Manual review can occur when the transaction is marked as risky by the frm_processor, payment processor or when there is underpayment/over payment incase of crypto payment - pub frm_merchant_decision: Option, - pub payment_confirm_source: Option, - + /// This Denotes the action(approve or reject) taken by merchant in case of manual review. + /// Manual review can occur when the transaction is marked as risky by the frm_processor, payment processor or when there is underpayment/over payment incase of crypto payment + pub frm_merchant_decision: Option, + /// Denotes the last instance which updated the payment pub updated_by: String, - pub surcharge_applicable: Option, + /// Denotes whether merchant requested for incremental authorization to be enabled for this payment. pub request_incremental_authorization: Option, + /// Denotes the number of authorizations that have been made for the payment. pub authorization_count: Option, + /// Denotes the client secret expiry for the payment. This is the time at which the client secret will expire. #[serde(with = "common_utils::custom_serde::iso8601::option")] pub session_expiry: Option, - pub request_external_three_ds_authentication: Option, - pub charges: Option, + /// Denotes whether merchant requested for 3ds authentication to be enabled for this payment. + pub request_external_three_ds_authentication: common_enums::External3dsAuthenticationRequest, + /// Metadata related to fraud and risk management pub frm_metadata: Option, + /// The details of the customer in a denormalized form. Only a subset of fields are stored. pub customer_details: Option>>, - pub merchant_order_reference_id: Option, - pub is_payment_processor_token_flow: Option, - pub shipping_cost: Option, - pub tax_details: Option, - pub merchant_reference_id: String, + /// The reference id for the order in the merchant's system. This value can be passed by the merchant. + pub merchant_reference_id: Option, + /// The billing address for the order in a denormalized form. pub billing_address: Option>>, + /// The shipping address for the order in a denormalized form. pub shipping_address: Option>>, + /// Capture method for the payment pub capture_method: Option, - pub id: id_type::PaymentId, + /// Authentication type that is requested by the merchant for this payment. pub authentication_type: Option, - pub amount_to_capture: Option, + /// This contains the pre routing results that are done when routing is done during listing the payment methods. pub prerouting_algorithm: Option, - pub surcharge_amount: Option, - pub tax_on_surcharge: Option, + /// The organization id for the payment. This is derived from the merchant account pub organization_id: id_type::OrganizationId, - pub skip_external_tax_calculation: Option, + /// Denotes the request by the merchant whether to enable a payment link for this payment. + pub enable_payment_link: common_enums::EnablePaymentLinkRequest, + /// Denotes the request by the merchant whether to apply MIT exemption for this payment + pub apply_mit_exemption: common_enums::MitExemptionRequest, + /// Denotes whether the customer is present during the payment flow. This information may be used for 3ds authentication + pub customer_present: common_enums::PresenceOfCustomerDuringPayment, + /// Denotes the override for payment link configuration + pub payment_link_config: Option, + /// The straight through routing algorithm id that is used for this payment. This overrides the default routing algorithm that is configured in business profile. + pub routing_algorithm_id: Option, } diff --git a/crates/hyperswitch_domain_models/src/payments/payment_intent.rs b/crates/hyperswitch_domain_models/src/payments/payment_intent.rs index 619ebcce68..eb207a1950 100644 --- a/crates/hyperswitch_domain_models/src/payments/payment_intent.rs +++ b/crates/hyperswitch_domain_models/src/payments/payment_intent.rs @@ -60,7 +60,7 @@ pub trait PaymentIntentInterface { async fn find_payment_intent_by_id( &self, state: &KeyManagerState, - id: &id_type::PaymentId, + id: &id_type::GlobalPaymentId, merchant_key_store: &MerchantKeyStore, storage_scheme: storage_enums::MerchantStorageScheme, ) -> error_stack::Result; @@ -146,120 +146,11 @@ pub struct CustomerData { pub phone_country_code: Option, } -#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "payment_v2")))] -#[derive(Clone, Debug, PartialEq)] -pub struct PaymentIntentNew { - pub payment_id: id_type::PaymentId, - pub merchant_id: id_type::MerchantId, - pub status: storage_enums::IntentStatus, - pub amount: MinorUnit, - pub currency: Option, - pub amount_captured: Option, - pub customer_id: Option, - pub description: Option, - pub return_url: Option, - pub metadata: Option, - pub frm_metadata: Option, - pub connector_id: Option, - pub shipping_address_id: Option, - pub billing_address_id: Option, - pub statement_descriptor_name: Option, - pub statement_descriptor_suffix: Option, - pub created_at: Option, - pub modified_at: Option, - pub last_synced: Option, - pub setup_future_usage: Option, - pub off_session: Option, - pub client_secret: Option, - pub active_attempt: RemoteStorageObject, - pub business_country: Option, - pub business_label: Option, - pub order_details: Option>, - pub allowed_payment_method_types: Option, - pub connector_metadata: Option, - pub feature_metadata: Option, - pub attempt_count: i16, - pub profile_id: Option, - pub merchant_decision: Option, - pub payment_link_id: Option, - pub payment_confirm_source: Option, - - pub updated_by: String, - pub surcharge_applicable: Option, - pub request_incremental_authorization: Option, - pub incremental_authorization_allowed: Option, - pub authorization_count: Option, - pub fingerprint_id: Option, - pub session_expiry: Option, - pub request_external_three_ds_authentication: Option, - pub charges: Option, - pub customer_details: Option>>, - pub billing_details: Option>>, - pub shipping_details: Option>>, - pub is_payment_processor_token_flow: Option, - pub organization_id: id_type::OrganizationId, - pub skip_external_tax_calculation: Option, -} - -#[cfg(all(feature = "v2", feature = "payment_v2"))] -#[derive(Clone, Debug, PartialEq)] -pub struct PaymentIntentNew { - pub payment_id: id_type::PaymentId, - pub merchant_id: id_type::MerchantId, - pub status: storage_enums::IntentStatus, - pub amount: MinorUnit, - pub currency: Option, - pub amount_captured: Option, - pub customer_id: Option, - pub description: Option, - pub return_url: Option, - pub metadata: Option, - pub frm_metadata: Option, - pub connector_id: Option, - pub shipping_address_id: Option, - pub billing_address_id: Option, - pub statement_descriptor_name: Option, - pub statement_descriptor_suffix: Option, - pub created_at: Option, - pub modified_at: Option, - pub last_synced: Option, - pub setup_future_usage: Option, - pub off_session: Option, - pub client_secret: Option, - pub active_attempt: RemoteStorageObject, - pub business_country: Option, - pub business_label: Option, - pub order_details: Option>, - pub allowed_payment_method_types: Option, - pub connector_metadata: Option, - pub feature_metadata: Option, - pub attempt_count: i16, - pub profile_id: Option, - pub merchant_decision: Option, - pub payment_link_id: Option, - pub payment_confirm_source: Option, - - pub updated_by: String, - pub surcharge_applicable: Option, - pub request_incremental_authorization: Option, - pub incremental_authorization_allowed: Option, - pub authorization_count: Option, - pub fingerprint_id: Option, - pub session_expiry: Option, - pub request_external_three_ds_authentication: Option, - pub charges: Option, - pub customer_details: Option>>, - pub billing_details: Option>>, - pub shipping_details: Option>>, - pub is_payment_processor_token_flow: Option, - pub organization_id: id_type::OrganizationId, -} - #[cfg(all(feature = "v2", feature = "payment_v2"))] #[derive(Debug, Clone, Serialize)] pub struct PaymentIntentUpdateFields { - pub amount: MinorUnit, - pub currency: storage_enums::Currency, + pub amount: Option, + pub currency: Option, pub setup_future_usage: Option, pub status: storage_enums::IntentStatus, pub customer_id: Option, @@ -267,9 +158,9 @@ pub struct PaymentIntentUpdateFields { pub billing_address: Option>>, pub return_url: Option, pub description: Option, - pub statement_descriptor_name: Option, + pub statement_descriptor: Option, pub order_details: Option>, - pub metadata: Option, + pub metadata: Option, pub payment_confirm_source: Option, pub updated_by: String, pub session_expiry: Option, @@ -394,6 +285,7 @@ pub enum PaymentIntentUpdate { }, } +// TODO: remove all enum variants and create new variants that should be used for v2 #[cfg(all(feature = "v2", feature = "payment_v2"))] #[derive(Debug, Clone, Serialize)] pub enum PaymentIntentUpdate { @@ -404,7 +296,7 @@ pub enum PaymentIntentUpdate { updated_by: String, }, MetadataUpdate { - metadata: serde_json::Value, + metadata: pii::SecretSerdeValue, updated_by: String, }, Update(Box), @@ -478,14 +370,14 @@ pub struct PaymentIntentUpdateInternal { pub return_url: Option, pub setup_future_usage: Option, pub off_session: Option, - pub metadata: Option, + pub metadata: Option, pub modified_at: Option, pub active_attempt_id: Option, pub description: Option, - pub statement_descriptor_name: Option, + pub statement_descriptor: Option, pub order_details: Option>, pub attempt_count: Option, - pub frm_merchant_decision: Option, + pub frm_merchant_decision: Option, pub payment_confirm_source: Option, pub updated_by: String, pub surcharge_applicable: Option, @@ -547,177 +439,178 @@ pub struct PaymentIntentUpdateInternal { #[cfg(all(feature = "v2", feature = "payment_v2"))] impl From for PaymentIntentUpdateInternal { fn from(payment_intent_update: PaymentIntentUpdate) -> Self { - match payment_intent_update { - PaymentIntentUpdate::MetadataUpdate { - metadata, - updated_by, - } => Self { - metadata: Some(metadata), - modified_at: Some(common_utils::date_time::now()), - updated_by, - ..Default::default() - }, - PaymentIntentUpdate::Update(value) => Self { - amount: Some(value.amount), - currency: Some(value.currency), - setup_future_usage: value.setup_future_usage, - status: Some(value.status), - customer_id: value.customer_id, - return_url: value.return_url, - description: value.description, - statement_descriptor_name: value.statement_descriptor_name, - order_details: value.order_details, - metadata: value.metadata, - payment_confirm_source: value.payment_confirm_source, - updated_by: value.updated_by, - session_expiry: value.session_expiry, - request_external_three_ds_authentication: value - .request_external_three_ds_authentication, - frm_metadata: value.frm_metadata, - customer_details: value.customer_details, - billing_address: value.billing_address, - merchant_order_reference_id: value.merchant_order_reference_id, - shipping_address: value.shipping_address, - is_payment_processor_token_flow: value.is_payment_processor_token_flow, - modified_at: Some(common_utils::date_time::now()), - ..Default::default() - }, - PaymentIntentUpdate::PaymentCreateUpdate { - return_url, - status, - customer_id, - shipping_address, - billing_address, - customer_details, - updated_by, - } => Self { - return_url, - status, - customer_id, - shipping_address, - billing_address, - customer_details, - modified_at: Some(common_utils::date_time::now()), - updated_by, - ..Default::default() - }, - PaymentIntentUpdate::PGStatusUpdate { status, updated_by } => Self { - status: Some(status), - modified_at: Some(common_utils::date_time::now()), - updated_by, - ..Default::default() - }, - PaymentIntentUpdate::MerchantStatusUpdate { - status, - shipping_address, - billing_address, - updated_by, - } => Self { - status: Some(status), - shipping_address, - billing_address, - modified_at: Some(common_utils::date_time::now()), - updated_by, - ..Default::default() - }, - PaymentIntentUpdate::ResponseUpdate { - // amount, - // currency, - status, - amount_captured, - // customer_id, - return_url, - updated_by, - } => Self { - // amount, - // currency: Some(currency), - status: Some(status), - amount_captured, - // customer_id, - return_url, - modified_at: Some(common_utils::date_time::now()), - updated_by, - ..Default::default() - }, - PaymentIntentUpdate::PaymentAttemptAndAttemptCountUpdate { - active_attempt_id, - attempt_count, - updated_by, - } => Self { - active_attempt_id: Some(active_attempt_id), - attempt_count: Some(attempt_count), - updated_by, - modified_at: Some(common_utils::date_time::now()), - ..Default::default() - }, - PaymentIntentUpdate::StatusAndAttemptUpdate { - status, - active_attempt_id, - attempt_count, - updated_by, - } => Self { - status: Some(status), - active_attempt_id: Some(active_attempt_id), - attempt_count: Some(attempt_count), - updated_by, - modified_at: Some(common_utils::date_time::now()), - ..Default::default() - }, - PaymentIntentUpdate::ApproveUpdate { - status, - frm_merchant_decision, - updated_by, - } => Self { - status: Some(status), - frm_merchant_decision, - updated_by, - modified_at: Some(common_utils::date_time::now()), - ..Default::default() - }, - PaymentIntentUpdate::RejectUpdate { - status, - frm_merchant_decision, - updated_by, - } => Self { - status: Some(status), - frm_merchant_decision, - updated_by, - modified_at: Some(common_utils::date_time::now()), - ..Default::default() - }, - PaymentIntentUpdate::SurchargeApplicableUpdate { - surcharge_applicable, - updated_by, - } => Self { - surcharge_applicable: Some(surcharge_applicable), - modified_at: Some(common_utils::date_time::now()), - updated_by, - ..Default::default() - }, - PaymentIntentUpdate::IncrementalAuthorizationAmountUpdate { amount } => Self { - amount: Some(amount), - modified_at: Some(common_utils::date_time::now()), - ..Default::default() - }, - PaymentIntentUpdate::AuthorizationCountUpdate { - authorization_count, - } => Self { - authorization_count: Some(authorization_count), - modified_at: Some(common_utils::date_time::now()), - ..Default::default() - }, - PaymentIntentUpdate::CompleteAuthorizeUpdate { shipping_address } => Self { - shipping_address, - modified_at: Some(common_utils::date_time::now()), - ..Default::default() - }, - PaymentIntentUpdate::ManualUpdate { status, updated_by } => Self { - status, - modified_at: Some(common_utils::date_time::now()), - updated_by, - ..Default::default() - }, - } + todo!() + // match payment_intent_update { + // PaymentIntentUpdate::MetadataUpdate { + // metadata, + // updated_by, + // } => Self { + // metadata: Some(metadata), + // modified_at: Some(common_utils::date_time::now()), + // updated_by, + // ..Default::default() + // }, + // PaymentIntentUpdate::Update(value) => Self { + // amount: Some(value.amount), + // currency: Some(value.currency), + // setup_future_usage: value.setup_future_usage, + // status: Some(value.status), + // customer_id: value.customer_id, + // return_url: value.return_url, + // description: value.description, + // statement_descriptor: value.statement_descriptor, + // order_details: value.order_details, + // metadata: value.metadata, + // payment_confirm_source: value.payment_confirm_source, + // updated_by: value.updated_by, + // session_expiry: value.session_expiry, + // request_external_three_ds_authentication: value + // .request_external_three_ds_authentication, + // frm_metadata: value.frm_metadata, + // customer_details: value.customer_details, + // billing_address: value.billing_address, + // merchant_order_reference_id: value.merchant_order_reference_id, + // shipping_address: value.shipping_address, + // is_payment_processor_token_flow: value.is_payment_processor_token_flow, + // modified_at: Some(common_utils::date_time::now()), + // ..Default::default() + // }, + // PaymentIntentUpdate::PaymentCreateUpdate { + // return_url, + // status, + // customer_id, + // shipping_address, + // billing_address, + // customer_details, + // updated_by, + // } => Self { + // return_url, + // status, + // customer_id, + // shipping_address, + // billing_address, + // customer_details, + // modified_at: Some(common_utils::date_time::now()), + // updated_by, + // ..Default::default() + // }, + // PaymentIntentUpdate::PGStatusUpdate { status, updated_by } => Self { + // status: Some(status), + // modified_at: Some(common_utils::date_time::now()), + // updated_by, + // ..Default::default() + // }, + // PaymentIntentUpdate::MerchantStatusUpdate { + // status, + // shipping_address, + // billing_address, + // updated_by, + // } => Self { + // status: Some(status), + // shipping_address, + // billing_address, + // modified_at: Some(common_utils::date_time::now()), + // updated_by, + // ..Default::default() + // }, + // PaymentIntentUpdate::ResponseUpdate { + // // amount, + // // currency, + // status, + // amount_captured, + // // customer_id, + // return_url, + // updated_by, + // } => Self { + // // amount, + // // currency: Some(currency), + // status: Some(status), + // amount_captured, + // // customer_id, + // return_url, + // modified_at: Some(common_utils::date_time::now()), + // updated_by, + // ..Default::default() + // }, + // PaymentIntentUpdate::PaymentAttemptAndAttemptCountUpdate { + // active_attempt_id, + // attempt_count, + // updated_by, + // } => Self { + // active_attempt_id: Some(active_attempt_id), + // attempt_count: Some(attempt_count), + // updated_by, + // modified_at: Some(common_utils::date_time::now()), + // ..Default::default() + // }, + // PaymentIntentUpdate::StatusAndAttemptUpdate { + // status, + // active_attempt_id, + // attempt_count, + // updated_by, + // } => Self { + // status: Some(status), + // active_attempt_id: Some(active_attempt_id), + // attempt_count: Some(attempt_count), + // updated_by, + // modified_at: Some(common_utils::date_time::now()), + // ..Default::default() + // }, + // PaymentIntentUpdate::ApproveUpdate { + // status, + // frm_merchant_decision, + // updated_by, + // } => Self { + // status: Some(status), + // frm_merchant_decision, + // updated_by, + // modified_at: Some(common_utils::date_time::now()), + // ..Default::default() + // }, + // PaymentIntentUpdate::RejectUpdate { + // status, + // frm_merchant_decision, + // updated_by, + // } => Self { + // status: Some(status), + // frm_merchant_decision, + // updated_by, + // modified_at: Some(common_utils::date_time::now()), + // ..Default::default() + // }, + // PaymentIntentUpdate::SurchargeApplicableUpdate { + // surcharge_applicable, + // updated_by, + // } => Self { + // surcharge_applicable: Some(surcharge_applicable), + // modified_at: Some(common_utils::date_time::now()), + // updated_by, + // ..Default::default() + // }, + // PaymentIntentUpdate::IncrementalAuthorizationAmountUpdate { amount } => Self { + // amount: Some(amount), + // modified_at: Some(common_utils::date_time::now()), + // ..Default::default() + // }, + // PaymentIntentUpdate::AuthorizationCountUpdate { + // authorization_count, + // } => Self { + // authorization_count: Some(authorization_count), + // modified_at: Some(common_utils::date_time::now()), + // ..Default::default() + // }, + // PaymentIntentUpdate::CompleteAuthorizeUpdate { shipping_address } => Self { + // shipping_address, + // modified_at: Some(common_utils::date_time::now()), + // ..Default::default() + // }, + // PaymentIntentUpdate::ManualUpdate { status, updated_by } => Self { + // status, + // modified_at: Some(common_utils::date_time::now()), + // updated_by, + // ..Default::default() + // }, + // } } } @@ -925,143 +818,144 @@ use diesel_models::{ #[cfg(all(feature = "v2", feature = "payment_v2"))] impl From for DieselPaymentIntentUpdate { fn from(value: PaymentIntentUpdate) -> Self { - match value { - PaymentIntentUpdate::ResponseUpdate { - status, - amount_captured, - return_url, - updated_by, - } => Self::ResponseUpdate { - status, - amount_captured, - return_url, - updated_by, - }, - PaymentIntentUpdate::MetadataUpdate { - metadata, - updated_by, - } => Self::MetadataUpdate { - metadata, - updated_by, - }, - PaymentIntentUpdate::Update(value) => { - Self::Update(Box::new(DieselPaymentIntentUpdateFields { - amount: value.amount, - currency: value.currency, - setup_future_usage: value.setup_future_usage, - status: value.status, - customer_id: value.customer_id, - return_url: value.return_url, - description: value.description, - statement_descriptor_name: value.statement_descriptor_name, - order_details: value.order_details, - metadata: value.metadata, - payment_confirm_source: value.payment_confirm_source, - updated_by: value.updated_by, - session_expiry: value.session_expiry, - request_external_three_ds_authentication: value - .request_external_three_ds_authentication, - frm_metadata: value.frm_metadata, - customer_details: value.customer_details.map(Encryption::from), - billing_address: value.billing_address.map(Encryption::from), - shipping_address: value.shipping_address.map(Encryption::from), - merchant_order_reference_id: value.merchant_order_reference_id, - is_payment_processor_token_flow: value.is_payment_processor_token_flow, - })) - } - PaymentIntentUpdate::PaymentCreateUpdate { - return_url, - status, - customer_id, - shipping_address, - billing_address, - customer_details, - updated_by, - } => Self::PaymentCreateUpdate { - return_url, - status, - customer_id, - shipping_address: shipping_address.map(Encryption::from), - billing_address: billing_address.map(Encryption::from), - customer_details: customer_details.map(Encryption::from), - updated_by, - }, - PaymentIntentUpdate::MerchantStatusUpdate { - status, - shipping_address, - billing_address, - updated_by, - } => Self::MerchantStatusUpdate { - status, - shipping_address: shipping_address.map(Encryption::from), - billing_address: billing_address.map(Encryption::from), - updated_by, - }, - PaymentIntentUpdate::PGStatusUpdate { status, updated_by } => { - Self::PGStatusUpdate { status, updated_by } - } - PaymentIntentUpdate::PaymentAttemptAndAttemptCountUpdate { - active_attempt_id, - attempt_count, - updated_by, - } => Self::PaymentAttemptAndAttemptCountUpdate { - active_attempt_id, - attempt_count, - updated_by, - }, - PaymentIntentUpdate::StatusAndAttemptUpdate { - status, - active_attempt_id, - attempt_count, - updated_by, - } => Self::StatusAndAttemptUpdate { - status, - active_attempt_id, - attempt_count, - updated_by, - }, - PaymentIntentUpdate::ApproveUpdate { - status, - frm_merchant_decision, - updated_by, - } => Self::ApproveUpdate { - status, - frm_merchant_decision, - updated_by, - }, - PaymentIntentUpdate::RejectUpdate { - status, - frm_merchant_decision, - updated_by, - } => Self::RejectUpdate { - status, - frm_merchant_decision, - updated_by, - }, - PaymentIntentUpdate::SurchargeApplicableUpdate { - surcharge_applicable, - updated_by, - } => Self::SurchargeApplicableUpdate { - surcharge_applicable: Some(surcharge_applicable), - updated_by, - }, - PaymentIntentUpdate::IncrementalAuthorizationAmountUpdate { amount } => { - Self::IncrementalAuthorizationAmountUpdate { amount } - } - PaymentIntentUpdate::AuthorizationCountUpdate { - authorization_count, - } => Self::AuthorizationCountUpdate { - authorization_count, - }, - PaymentIntentUpdate::CompleteAuthorizeUpdate { shipping_address } => { - Self::CompleteAuthorizeUpdate { - shipping_address: shipping_address.map(Encryption::from), - } - } - PaymentIntentUpdate::ManualUpdate { status, updated_by } => { - Self::ManualUpdate { status, updated_by } - } - } + todo!() + // match value { + // PaymentIntentUpdate::ResponseUpdate { + // status, + // amount_captured, + // return_url, + // updated_by, + // } => Self::ResponseUpdate { + // status, + // amount_captured, + // return_url, + // updated_by, + // }, + // PaymentIntentUpdate::MetadataUpdate { + // metadata, + // updated_by, + // } => Self::MetadataUpdate { + // metadata, + // updated_by, + // }, + // PaymentIntentUpdate::Update(value) => { + // Self::Update(Box::new(DieselPaymentIntentUpdateFields { + // amount: value.amount, + // currency: value.currency, + // setup_future_usage: value.setup_future_usage, + // status: value.status, + // customer_id: value.customer_id, + // return_url: value.return_url, + // description: value.description, + // statement_descriptor: value.statement_descriptor, + // order_details: value.order_details, + // metadata: value.metadata, + // payment_confirm_source: value.payment_confirm_source, + // updated_by: value.updated_by, + // session_expiry: value.session_expiry, + // request_external_three_ds_authentication: value + // .request_external_three_ds_authentication, + // frm_metadata: value.frm_metadata, + // customer_details: value.customer_details.map(Encryption::from), + // billing_address: value.billing_address.map(Encryption::from), + // shipping_address: value.shipping_address.map(Encryption::from), + // merchant_order_reference_id: value.merchant_order_reference_id, + // is_payment_processor_token_flow: value.is_payment_processor_token_flow, + // })) + // } + // PaymentIntentUpdate::PaymentCreateUpdate { + // return_url, + // status, + // customer_id, + // shipping_address, + // billing_address, + // customer_details, + // updated_by, + // } => Self::PaymentCreateUpdate { + // return_url, + // status, + // customer_id, + // shipping_address: shipping_address.map(Encryption::from), + // billing_address: billing_address.map(Encryption::from), + // customer_details: customer_details.map(Encryption::from), + // updated_by, + // }, + // PaymentIntentUpdate::MerchantStatusUpdate { + // status, + // shipping_address, + // billing_address, + // updated_by, + // } => Self::MerchantStatusUpdate { + // status, + // shipping_address: shipping_address.map(Encryption::from), + // billing_address: billing_address.map(Encryption::from), + // updated_by, + // }, + // PaymentIntentUpdate::PGStatusUpdate { status, updated_by } => { + // Self::PGStatusUpdate { status, updated_by } + // } + // PaymentIntentUpdate::PaymentAttemptAndAttemptCountUpdate { + // active_attempt_id, + // attempt_count, + // updated_by, + // } => Self::PaymentAttemptAndAttemptCountUpdate { + // active_attempt_id, + // attempt_count, + // updated_by, + // }, + // PaymentIntentUpdate::StatusAndAttemptUpdate { + // status, + // active_attempt_id, + // attempt_count, + // updated_by, + // } => Self::StatusAndAttemptUpdate { + // status, + // active_attempt_id, + // attempt_count, + // updated_by, + // }, + // PaymentIntentUpdate::ApproveUpdate { + // status, + // frm_merchant_decision, + // updated_by, + // } => Self::ApproveUpdate { + // status, + // frm_merchant_decision, + // updated_by, + // }, + // PaymentIntentUpdate::RejectUpdate { + // status, + // frm_merchant_decision, + // updated_by, + // } => Self::RejectUpdate { + // status, + // frm_merchant_decision, + // updated_by, + // }, + // PaymentIntentUpdate::SurchargeApplicableUpdate { + // surcharge_applicable, + // updated_by, + // } => Self::SurchargeApplicableUpdate { + // surcharge_applicable: Some(surcharge_applicable), + // updated_by, + // }, + // PaymentIntentUpdate::IncrementalAuthorizationAmountUpdate { amount } => { + // Self::IncrementalAuthorizationAmountUpdate { amount } + // } + // PaymentIntentUpdate::AuthorizationCountUpdate { + // authorization_count, + // } => Self::AuthorizationCountUpdate { + // authorization_count, + // }, + // PaymentIntentUpdate::CompleteAuthorizeUpdate { shipping_address } => { + // Self::CompleteAuthorizeUpdate { + // shipping_address: shipping_address.map(Encryption::from), + // } + // } + // PaymentIntentUpdate::ManualUpdate { status, updated_by } => { + // Self::ManualUpdate { status, updated_by } + // } + // } } } @@ -1236,70 +1130,72 @@ impl From for DieselPaymentIntentUpdate { } } +// TODO: evaluate if we will be using the same update struct for v2 as well, uncomment this and make necessary changes if necessary #[cfg(all(feature = "v2", feature = "payment_v2"))] impl From for diesel_models::PaymentIntentUpdateInternal { fn from(value: PaymentIntentUpdateInternal) -> Self { - let modified_at = common_utils::date_time::now(); - let PaymentIntentUpdateInternal { - amount, - currency, - status, - amount_captured, - customer_id, - return_url, - setup_future_usage, - off_session, - metadata, - modified_at: _, - active_attempt_id, - description, - statement_descriptor_name, - order_details, - attempt_count, - frm_merchant_decision, - payment_confirm_source, - updated_by, - surcharge_applicable, - authorization_count, - session_expiry, - request_external_three_ds_authentication, - frm_metadata, - customer_details, - billing_address, - merchant_order_reference_id, - shipping_address, - is_payment_processor_token_flow, - } = value; - Self { - amount, - currency, - status, - amount_captured, - customer_id, - return_url, - setup_future_usage, - off_session, - metadata, - modified_at, - active_attempt_id, - description, - statement_descriptor_name, - order_details, - attempt_count, - frm_merchant_decision, - payment_confirm_source, - updated_by, - surcharge_applicable, - authorization_count, - session_expiry, - request_external_three_ds_authentication, - frm_metadata, - customer_details: customer_details.map(Encryption::from), - billing_address: billing_address.map(Encryption::from), - merchant_order_reference_id, - shipping_address: shipping_address.map(Encryption::from), - is_payment_processor_token_flow, - } + todo!() + // let modified_at = common_utils::date_time::now(); + // let PaymentIntentUpdateInternal { + // amount, + // currency, + // status, + // amount_captured, + // customer_id, + // return_url, + // setup_future_usage, + // off_session, + // metadata, + // modified_at: _, + // active_attempt_id, + // description, + // statement_descriptor, + // order_details, + // attempt_count, + // frm_merchant_decision, + // payment_confirm_source, + // updated_by, + // surcharge_applicable, + // authorization_count, + // session_expiry, + // request_external_three_ds_authentication, + // frm_metadata, + // customer_details, + // billing_address, + // merchant_order_reference_id, + // shipping_address, + // is_payment_processor_token_flow, + // } = value; + // Self { + // amount, + // currency, + // status, + // amount_captured, + // customer_id, + // return_url, + // setup_future_usage, + // off_session, + // metadata, + // modified_at, + // active_attempt_id, + // description, + // statement_descriptor, + // order_details, + // attempt_count, + // frm_merchant_decision, + // payment_confirm_source, + // updated_by, + // surcharge_applicable, + // authorization_count, + // session_expiry, + // request_external_three_ds_authentication, + // frm_metadata, + // customer_details: customer_details.map(Encryption::from), + // billing_address: billing_address.map(Encryption::from), + // merchant_order_reference_id, + // shipping_address: shipping_address.map(Encryption::from), + // is_payment_processor_token_flow, + // } } } @@ -1585,64 +1481,111 @@ impl behaviour::Conversion for PaymentIntent { type NewDstType = DieselPaymentIntentNew; async fn convert(self) -> CustomResult { + let PaymentIntent { + merchant_id, + amount_details, + status, + amount_captured, + customer_id, + description, + return_url, + metadata, + statement_descriptor, + created_at, + modified_at, + last_synced, + setup_future_usage, + client_secret, + active_attempt, + order_details, + allowed_payment_method_types, + connector_metadata, + feature_metadata, + attempt_count, + profile_id, + payment_link_id, + frm_merchant_decision, + updated_by, + request_incremental_authorization, + authorization_count, + session_expiry, + request_external_three_ds_authentication, + frm_metadata, + customer_details, + merchant_reference_id, + billing_address, + shipping_address, + capture_method, + id, + authentication_type, + prerouting_algorithm, + organization_id, + enable_payment_link, + apply_mit_exemption, + customer_present, + routing_algorithm_id, + payment_link_config, + } = self; Ok(DieselPaymentIntent { - merchant_id: self.merchant_id, - status: self.status, - amount: self.amount, - currency: self.currency, - amount_captured: self.amount_captured, - customer_id: self.customer_id, - description: self.description, - return_url: self.return_url, - metadata: self.metadata, - statement_descriptor_name: self.statement_descriptor_name, - created_at: self.created_at, - modified_at: self.modified_at, - last_synced: self.last_synced, - setup_future_usage: self.setup_future_usage, - off_session: self.off_session, - client_secret: self.client_secret, - active_attempt_id: self.active_attempt.get_id(), - order_details: self.order_details, - allowed_payment_method_types: self.allowed_payment_method_types, - connector_metadata: self.connector_metadata, - feature_metadata: self.feature_metadata, - attempt_count: self.attempt_count, - profile_id: self.profile_id, - frm_merchant_decision: self.frm_merchant_decision, - payment_link_id: self.payment_link_id, - payment_confirm_source: self.payment_confirm_source, - updated_by: self.updated_by, - surcharge_applicable: self.surcharge_applicable, - request_incremental_authorization: self.request_incremental_authorization, - authorization_count: self.authorization_count, - session_expiry: self.session_expiry, - request_external_three_ds_authentication: self.request_external_three_ds_authentication, - charges: self.charges, - frm_metadata: self.frm_metadata, - customer_details: self.customer_details.map(Encryption::from), - billing_address: self.billing_address.map(Encryption::from), - merchant_order_reference_id: self.merchant_order_reference_id, - shipping_address: self.shipping_address.map(Encryption::from), - is_payment_processor_token_flow: self.is_payment_processor_token_flow, - capture_method: self.capture_method, - id: self.id, - authentication_type: self.authentication_type, - amount_to_capture: self.amount_to_capture, - prerouting_algorithm: self.prerouting_algorithm, - merchant_reference_id: self.merchant_reference_id, - surcharge_amount: self.surcharge_amount, - tax_on_surcharge: self.tax_on_surcharge, - organization_id: self.organization_id, - shipping_cost: self.shipping_cost, - tax_details: self.tax_details, - skip_external_tax_calculation: self.skip_external_tax_calculation, + skip_external_tax_calculation: Some(amount_details.get_external_tax_action_as_bool()), + surcharge_applicable: Some(amount_details.get_surcharge_action_as_bool()), + merchant_id, + status, + amount: amount_details.order_amount, + currency: amount_details.currency, + amount_captured, + customer_id, + description, + return_url, + metadata, + statement_descriptor, + created_at, + modified_at, + last_synced, + setup_future_usage, + client_secret, + active_attempt_id: active_attempt.get_id(), + order_details, + allowed_payment_method_types, + connector_metadata, + feature_metadata, + attempt_count, + profile_id, + frm_merchant_decision, + payment_link_id, + updated_by, + + request_incremental_authorization, + authorization_count, + session_expiry, + request_external_three_ds_authentication: Some( + request_external_three_ds_authentication.as_bool(), + ), + frm_metadata, + customer_details: customer_details.map(Encryption::from), + billing_address: billing_address.map(Encryption::from), + shipping_address: shipping_address.map(Encryption::from), + capture_method, + id, + authentication_type, + prerouting_algorithm, + merchant_reference_id, + surcharge_amount: amount_details.surcharge_amount, + tax_on_surcharge: amount_details.tax_on_surcharge, + organization_id, + shipping_cost: amount_details.shipping_cost, + tax_details: amount_details.tax_details, + enable_payment_link: Some(enable_payment_link.as_bool()), + apply_mit_exemption: Some(apply_mit_exemption.as_bool()), + customer_present: Some(customer_present.as_bool()), + payment_link_config, + routing_algorithm_id, }) } async fn convert_back( state: &KeyManagerState, storage_model: Self::DstType, - key: &Secret>, + key: &masking::Secret>, key_manager_identifier: keymanager::Identifier, ) -> CustomResult where @@ -1660,22 +1603,36 @@ impl behaviour::Conversion for PaymentIntent { .await .and_then(|val| val.try_into_optionaloperation()) }; + + let amount_details = super::AmountDetails { + order_amount: storage_model.amount, + currency: storage_model.currency, + surcharge_amount: storage_model.surcharge_amount, + tax_on_surcharge: storage_model.tax_on_surcharge, + shipping_cost: storage_model.shipping_cost, + tax_details: storage_model.tax_details, + skip_external_tax_calculation: super::TaxCalculationOverride::from( + storage_model.skip_external_tax_calculation, + ), + skip_surcharge_calculation: super::SurchargeCalculationOverride::from( + storage_model.surcharge_applicable, + ), + }; + Ok::>(Self { merchant_id: storage_model.merchant_id, status: storage_model.status, - amount: storage_model.amount, - currency: storage_model.currency, + amount_details, amount_captured: storage_model.amount_captured, customer_id: storage_model.customer_id, description: storage_model.description, return_url: storage_model.return_url, metadata: storage_model.metadata, - statement_descriptor_name: storage_model.statement_descriptor_name, + statement_descriptor: storage_model.statement_descriptor, created_at: storage_model.created_at, modified_at: storage_model.modified_at, last_synced: storage_model.last_synced, setup_future_usage: storage_model.setup_future_usage, - off_session: storage_model.off_session, client_secret: storage_model.client_secret, active_attempt: RemoteStorageObject::ForeignID(storage_model.active_attempt_id), order_details: storage_model.order_details, @@ -1686,15 +1643,14 @@ impl behaviour::Conversion for PaymentIntent { profile_id: storage_model.profile_id, frm_merchant_decision: storage_model.frm_merchant_decision, payment_link_id: storage_model.payment_link_id, - payment_confirm_source: storage_model.payment_confirm_source, updated_by: storage_model.updated_by, - surcharge_applicable: storage_model.surcharge_applicable, request_incremental_authorization: storage_model.request_incremental_authorization, authorization_count: storage_model.authorization_count, session_expiry: storage_model.session_expiry, - request_external_three_ds_authentication: storage_model - .request_external_three_ds_authentication, - charges: storage_model.charges, + request_external_three_ds_authentication: + common_enums::External3dsAuthenticationRequest::from( + storage_model.request_external_three_ds_authentication, + ), frm_metadata: storage_model.frm_metadata, customer_details: storage_model .customer_details @@ -1704,24 +1660,27 @@ impl behaviour::Conversion for PaymentIntent { .billing_address .async_lift(inner_decrypt) .await?, - merchant_order_reference_id: storage_model.merchant_order_reference_id, shipping_address: storage_model .shipping_address .async_lift(inner_decrypt) .await?, - is_payment_processor_token_flow: storage_model.is_payment_processor_token_flow, capture_method: storage_model.capture_method, id: storage_model.id, merchant_reference_id: storage_model.merchant_reference_id, organization_id: storage_model.organization_id, authentication_type: storage_model.authentication_type, - amount_to_capture: storage_model.amount_to_capture, prerouting_algorithm: storage_model.prerouting_algorithm, - surcharge_amount: storage_model.surcharge_amount, - tax_on_surcharge: storage_model.tax_on_surcharge, - shipping_cost: storage_model.shipping_cost, - tax_details: storage_model.tax_details, - skip_external_tax_calculation: storage_model.skip_external_tax_calculation, + enable_payment_link: common_enums::EnablePaymentLinkRequest::from( + storage_model.enable_payment_link, + ), + apply_mit_exemption: common_enums::MitExemptionRequest::from( + storage_model.apply_mit_exemption, + ), + customer_present: common_enums::PresenceOfCustomerDuringPayment::from( + storage_model.customer_present, + ), + payment_link_config: storage_model.payment_link_config, + routing_algorithm_id: storage_model.routing_algorithm_id, }) } .await @@ -1731,22 +1690,25 @@ impl behaviour::Conversion for PaymentIntent { } async fn construct_new(self) -> CustomResult { + let amount_details = self.amount_details; + Ok(DieselPaymentIntentNew { + surcharge_applicable: Some(amount_details.get_surcharge_action_as_bool()), + skip_external_tax_calculation: Some(amount_details.get_external_tax_action_as_bool()), merchant_id: self.merchant_id, status: self.status, - amount: self.amount, - currency: self.currency, + amount: amount_details.order_amount, + currency: amount_details.currency, amount_captured: self.amount_captured, customer_id: self.customer_id, description: self.description, return_url: self.return_url, metadata: self.metadata, - statement_descriptor_name: self.statement_descriptor_name, + statement_descriptor: self.statement_descriptor, created_at: self.created_at, modified_at: self.modified_at, last_synced: self.last_synced, setup_future_usage: self.setup_future_usage, - off_session: self.off_session, client_secret: self.client_secret, active_attempt_id: self.active_attempt.get_id(), order_details: self.order_details, @@ -1757,32 +1719,30 @@ impl behaviour::Conversion for PaymentIntent { profile_id: self.profile_id, frm_merchant_decision: self.frm_merchant_decision, payment_link_id: self.payment_link_id, - payment_confirm_source: self.payment_confirm_source, updated_by: self.updated_by, - surcharge_applicable: self.surcharge_applicable, + request_incremental_authorization: self.request_incremental_authorization, authorization_count: self.authorization_count, session_expiry: self.session_expiry, - request_external_three_ds_authentication: self.request_external_three_ds_authentication, - charges: self.charges, + request_external_three_ds_authentication: Some( + self.request_external_three_ds_authentication.as_bool(), + ), frm_metadata: self.frm_metadata, customer_details: self.customer_details.map(Encryption::from), billing_address: self.billing_address.map(Encryption::from), - merchant_order_reference_id: self.merchant_order_reference_id, shipping_address: self.shipping_address.map(Encryption::from), - is_payment_processor_token_flow: self.is_payment_processor_token_flow, capture_method: self.capture_method, id: self.id, merchant_reference_id: self.merchant_reference_id, authentication_type: self.authentication_type, - amount_to_capture: self.amount_to_capture, prerouting_algorithm: self.prerouting_algorithm, - surcharge_amount: self.surcharge_amount, - tax_on_surcharge: self.tax_on_surcharge, + surcharge_amount: amount_details.surcharge_amount, + tax_on_surcharge: amount_details.tax_on_surcharge, organization_id: self.organization_id, - shipping_cost: self.shipping_cost, - tax_details: self.tax_details, - skip_external_tax_calculation: self.skip_external_tax_calculation, + shipping_cost: amount_details.shipping_cost, + tax_details: amount_details.tax_details, + enable_payment_link: Some(self.enable_payment_link.as_bool()), + apply_mit_exemption: Some(self.apply_mit_exemption.as_bool()), }) } } diff --git a/crates/router/src/core/customers.rs b/crates/router/src/core/customers.rs index a325f41404..fc7d717d5f 100644 --- a/crates/router/src/core/customers.rs +++ b/crates/router/src/core/customers.rs @@ -656,7 +656,7 @@ impl CustomerDeleteBridge for customers::GlobalId { name: Some(redacted_encrypted_value.clone()), email: Box::new(Some(redacted_encrypted_email)), phone: Box::new(Some(redacted_encrypted_value.clone())), - description: Some(Description::new(REDACTED.to_string())), + description: Some(Description::from_str_unchecked(REDACTED)), phone_country_code: Some(REDACTED.to_string()), metadata: None, connector_customer: None, @@ -898,7 +898,7 @@ impl CustomerDeleteBridge for customers::CustomerId { .switch()?, ), phone: Box::new(Some(redacted_encrypted_value.clone())), - description: Some(Description::new(REDACTED.to_string())), + description: Some(Description::from_str_unchecked(REDACTED)), phone_country_code: Some(REDACTED.to_string()), metadata: None, connector_customer: None, diff --git a/crates/router/src/core/fraud_check.rs b/crates/router/src/core/fraud_check.rs index 7e184b318d..c696c5072b 100644 --- a/crates/router/src/core/fraud_check.rs +++ b/crates/router/src/core/fraud_check.rs @@ -47,6 +47,32 @@ pub mod flows; pub mod operation; pub mod types; +#[cfg(feature = "v2")] +#[instrument(skip_all)] +pub async fn call_frm_service( + state: &SessionState, + payment_data: &OperationData, + frm_data: &mut FrmData, + merchant_account: &domain::MerchantAccount, + key_store: &domain::MerchantKeyStore, + customer: &Option, +) -> RouterResult> +where + F: Send + Clone, + + OperationData: payments::OperationSessionGetters + Send + Sync + Clone, + + // To create connector flow specific interface data + FrmData: ConstructFlowSpecificData, + oss_types::RouterData: FeatureFrm + Send, + + // To construct connector flow specific api + dyn Connector: services::api::ConnectorIntegration, +{ + todo!() +} + +#[cfg(feature = "v1")] #[instrument(skip_all)] pub async fn call_frm_service( state: &SessionState, @@ -350,6 +376,30 @@ where } } +#[cfg(feature = "v2")] +#[allow(clippy::too_many_arguments)] +pub async fn make_frm_data_and_fraud_check_operation<'a, F, D>( + _db: &dyn StorageInterface, + state: &SessionState, + merchant_account: &domain::MerchantAccount, + payment_data: D, + frm_routing_algorithm: FrmRoutingAlgorithm, + profile_id: common_utils::id_type::ProfileId, + frm_configs: FrmConfigsObject, + _customer: &Option, +) -> RouterResult> +where + F: Send + Clone, + D: payments::OperationSessionGetters + + payments::OperationSessionSetters + + Send + + Sync + + Clone, +{ + todo!() +} + +#[cfg(feature = "v1")] #[allow(clippy::too_many_arguments)] pub async fn make_frm_data_and_fraud_check_operation<'a, F, D>( _db: &dyn StorageInterface, diff --git a/crates/router/src/core/fraud_check/flows/fulfillment_flow.rs b/crates/router/src/core/fraud_check/flows/fulfillment_flow.rs index f3eab2dd8d..87ede498ab 100644 --- a/crates/router/src/core/fraud_check/flows/fulfillment_flow.rs +++ b/crates/router/src/core/fraud_check/flows/fulfillment_flow.rs @@ -16,6 +16,20 @@ use crate::{ utils, SessionState, }; +#[cfg(feature = "v2")] +pub async fn construct_fulfillment_router_data<'a>( + _state: &'a SessionState, + _payment_intent: &'a storage::PaymentIntent, + _payment_attempt: &storage::PaymentAttempt, + _merchant_account: &domain::MerchantAccount, + _key_store: &domain::MerchantKeyStore, + _connector: String, + _fulfillment_request: FrmFulfillmentRequest, +) -> RouterResult { + todo!() +} + +#[cfg(feature = "v1")] #[instrument(skip_all)] pub async fn construct_fulfillment_router_data<'a>( state: &'a SessionState, diff --git a/crates/router/src/core/fraud_check/operation/fraud_check_post.rs b/crates/router/src/core/fraud_check/operation/fraud_check_post.rs index 1a8bc1b554..65079f633d 100644 --- a/crates/router/src/core/fraud_check/operation/fraud_check_post.rs +++ b/crates/router/src/core/fraud_check/operation/fraud_check_post.rs @@ -85,6 +85,17 @@ where #[async_trait] impl GetTracker for FraudCheckPost { + #[cfg(feature = "v2")] + async fn get_trackers<'a>( + &'a self, + state: &'a SessionState, + payment_data: PaymentToFrmData, + frm_connector_details: ConnectorDetailsCore, + ) -> RouterResult> { + todo!() + } + + #[cfg(feature = "v1")] #[instrument(skip_all)] async fn get_trackers<'a>( &'a self, diff --git a/crates/router/src/core/fraud_check/operation/fraud_check_pre.rs b/crates/router/src/core/fraud_check/operation/fraud_check_pre.rs index 666028e5df..59a703d2b3 100644 --- a/crates/router/src/core/fraud_check/operation/fraud_check_pre.rs +++ b/crates/router/src/core/fraud_check/operation/fraud_check_pre.rs @@ -71,6 +71,18 @@ where #[async_trait] impl GetTracker for FraudCheckPre { + #[cfg(feature = "v2")] + #[instrument(skip_all)] + async fn get_trackers<'a>( + &'a self, + state: &'a SessionState, + payment_data: PaymentToFrmData, + frm_connector_details: ConnectorDetailsCore, + ) -> RouterResult> { + todo!() + } + + #[cfg(feature = "v1")] #[instrument(skip_all)] async fn get_trackers<'a>( &'a self, diff --git a/crates/router/src/core/payment_methods.rs b/crates/router/src/core/payment_methods.rs index 8e3d2799fd..e51771a280 100644 --- a/crates/router/src/core/payment_methods.rs +++ b/crates/router/src/core/payment_methods.rs @@ -1317,10 +1317,12 @@ async fn get_pm_list_context( hyperswitch_token_data: is_payment_associated.then_some( storage::PaymentTokenData::permanent_card( Some(pm.get_id().clone()), - pm.locker_id.clone().or(Some(pm.get_id().get_string_repr())), pm.locker_id .clone() - .unwrap_or(pm.get_id().get_string_repr()), + .or(Some(pm.get_id().get_string_repr().to_owned())), + pm.locker_id + .clone() + .unwrap_or(pm.get_id().get_string_repr().to_owned()), ), ), }) @@ -1628,7 +1630,7 @@ async fn generate_saved_pm_response( let pma = api::CustomerPaymentMethod { payment_token: parent_payment_method_token.clone(), - payment_method_id: pm.get_id().get_string_repr(), + payment_method_id: pm.get_id().get_string_repr().to_owned(), customer_id: pm.customer_id.to_owned(), payment_method, payment_method_type: pm.payment_method_type, @@ -1642,7 +1644,7 @@ async fn generate_saved_pm_response( && !(off_session_payment_flag && pm.connector_mandate_details.is_some()), last_used_at: Some(pm.last_used_at), is_default: customer.default_payment_method_id.is_some() - && customer.default_payment_method_id.as_ref() == Some(&pm.get_id().get_string_repr()), + && customer.default_payment_method_id.as_deref() == Some(pm.get_id().get_string_repr()), billing: payment_method_billing, }; @@ -1685,19 +1687,13 @@ impl pm_types::SavedPMLPaymentsInfo { Some(common_enums::FutureUsage::OffSession) ); - let profile_id = payment_intent - .profile_id - .as_ref() - .get_required_value("profile_id") - .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable("profile_id is not set in payment_intent")? - .clone(); + let profile_id = &payment_intent.profile_id; let business_profile = core_utils::validate_and_get_business_profile( db, key_manager_state, key_store, - Some(profile_id).as_ref(), + Some(profile_id), merchant_account.get_id(), ) .await?; diff --git a/crates/router/src/core/payment_methods/cards.rs b/crates/router/src/core/payment_methods/cards.rs index efc9621d26..6e3d89195d 100644 --- a/crates/router/src/core/payment_methods/cards.rs +++ b/crates/router/src/core/payment_methods/cards.rs @@ -3341,6 +3341,7 @@ pub async fn list_payment_methods( billing_address_for_calculating_required_fields, customer.as_ref(), ))?; + let req_val = serde_json::to_value(req).ok(); logger::debug!(filtered_payment_methods=?response); diff --git a/crates/router/src/core/payment_methods/transformers.rs b/crates/router/src/core/payment_methods/transformers.rs index d0f63a2dc0..6583d109d5 100644 --- a/crates/router/src/core/payment_methods/transformers.rs +++ b/crates/router/src/core/payment_methods/transformers.rs @@ -546,7 +546,7 @@ pub fn generate_payment_method_response( let resp = api::PaymentMethodResponse { merchant_id: pm.merchant_id.to_owned(), customer_id: pm.customer_id.to_owned(), - payment_method_id: pm.id.get_string_repr(), + payment_method_id: pm.id.get_string_repr().to_owned(), payment_method: pm.payment_method, payment_method_type: pm.payment_method_type, metadata: pm.metadata.clone(), diff --git a/crates/router/src/core/payments.rs b/crates/router/src/core/payments.rs index 3a55bf7777..744b93032b 100644 --- a/crates/router/src/core/payments.rs +++ b/crates/router/src/core/payments.rs @@ -608,6 +608,7 @@ where let cloned_payment_data = payment_data.clone(); let cloned_customer = customer.clone(); + #[cfg(feature = "v1")] operation .to_domain()? .store_extended_card_info_temporarily( @@ -704,6 +705,19 @@ where todo!() } +#[cfg(feature = "v2")] +#[instrument(skip_all)] +async fn populate_surcharge_details( + state: &SessionState, + payment_data: &mut PaymentData, +) -> RouterResult<()> +where + F: Send + Clone, +{ + todo!() +} + +#[cfg(feature = "v1")] #[instrument(skip_all)] async fn populate_surcharge_details( state: &SessionState, @@ -1597,6 +1611,7 @@ where ) .await?; + #[cfg(feature = "v1")] let merchant_recipient_data = if let Some(true) = payment_data .get_payment_intent() .is_payment_processor_token_flow @@ -1614,6 +1629,10 @@ where .await? }; + // TODO: handle how we read `is_processor_token_flow` in v2 and then call `get_merchant_recipient_data` + #[cfg(feature = "v2")] + let merchant_recipient_data = None; + let mut router_data = payment_data .construct_router_data( state, @@ -2357,6 +2376,7 @@ where F: Clone, D: OperationSessionGetters + Send + Sync + Clone, { + #[cfg(feature = "v1")] let profile_id = payment_data .get_payment_intent() .profile_id @@ -2366,6 +2386,9 @@ where .attach_printable("profile_id is not set in payment_intent")? .clone(); + #[cfg(feature = "v2")] + let profile_id = payment_data.get_payment_intent().profile_id.clone(); + let merchant_connector_account = helpers::get_merchant_connector_account( state, merchant_account.get_id(), @@ -2735,6 +2758,24 @@ where Ok(payment_data_and_tokenization_action) } +#[cfg(feature = "v2")] +pub async fn tokenize_in_router_when_confirm_false_or_external_authentication( + state: &SessionState, + operation: &BoxedOperation<'_, F, Req, D>, + payment_data: &mut D, + validate_result: &operations::ValidateResult, + merchant_key_store: &domain::MerchantKeyStore, + customer: &Option, + business_profile: &domain::Profile, +) -> RouterResult +where + F: Send + Clone, + D: OperationSessionGetters + OperationSessionSetters + Send + Sync + Clone, +{ + todo!() +} + +#[cfg(feature = "v1")] pub async fn tokenize_in_router_when_confirm_false_or_external_authentication( state: &SessionState, operation: &BoxedOperation<'_, F, Req, D>, @@ -3806,7 +3847,7 @@ where .await } -#[cfg(all(feature = "v2", feature = "payment_methods_v2"))] +#[cfg(feature = "v2")] pub async fn decide_multiplex_connector_for_normal_or_recurring_payment( state: &SessionState, payment_data: &mut D, @@ -3821,10 +3862,7 @@ where todo!() } -#[cfg(all( - any(feature = "v2", feature = "v1"), - not(feature = "payment_methods_v2") -))] +#[cfg(feature = "v1")] #[allow(clippy::too_many_arguments)] pub async fn decide_multiplex_connector_for_normal_or_recurring_payment( state: &SessionState, @@ -4956,6 +4994,7 @@ pub trait OperationSessionGetters { fn get_authorizations(&self) -> Vec; fn get_attempts(&self) -> Option>; fn get_recurring_details(&self) -> Option<&RecurringDetails>; + // TODO: this should be a mandatory field, should we throw an error instead of returning an Option? fn get_payment_intent_profile_id(&self) -> Option<&id_type::ProfileId>; fn get_currency(&self) -> storage_enums::Currency; fn get_amount(&self) -> api::Amount; @@ -5085,10 +5124,16 @@ impl OperationSessionGetters for PaymentData { self.recurring_details.as_ref() } + #[cfg(feature = "v1")] fn get_payment_intent_profile_id(&self) -> Option<&id_type::ProfileId> { self.payment_intent.profile_id.as_ref() } + #[cfg(feature = "v2")] + fn get_payment_intent_profile_id(&self) -> Option<&id_type::ProfileId> { + Some(&self.payment_intent.profile_id) + } + fn get_currency(&self) -> storage_enums::Currency { self.currency } diff --git a/crates/router/src/core/payments/helpers.rs b/crates/router/src/core/payments/helpers.rs index ac6c236f53..eb51239923 100644 --- a/crates/router/src/core/payments/helpers.rs +++ b/crates/router/src/core/payments/helpers.rs @@ -1142,6 +1142,7 @@ pub fn validate_customer_id_mandatory_cases( } } +#[cfg(feature = "v1")] pub fn create_startpay_url( base_url: &str, payment_attempt: &PaymentAttempt, @@ -2287,6 +2288,20 @@ pub async fn store_in_vault_and_generate_ppmt( Ok(parent_payment_method_token) } +#[cfg(feature = "v2")] +pub async fn store_payment_method_data_in_vault( + state: &SessionState, + payment_attempt: &PaymentAttempt, + payment_intent: &PaymentIntent, + payment_method: enums::PaymentMethod, + payment_method_data: &domain::PaymentMethodData, + merchant_key_store: &domain::MerchantKeyStore, + business_profile: Option<&domain::Profile>, +) -> RouterResult> { + todo!() +} + +#[cfg(feature = "v1")] pub async fn store_payment_method_data_in_vault( state: &SessionState, payment_attempt: &PaymentAttempt, @@ -2997,6 +3012,7 @@ pub fn generate_mandate( } } +#[cfg(feature = "v1")] // A function to manually authenticate the client secret with intent fulfillment time pub fn authenticate_client_secret( request_client_secret: Option<&String>, @@ -3026,6 +3042,34 @@ pub fn authenticate_client_secret( } } +#[cfg(feature = "v2")] +// A function to manually authenticate the client secret with intent fulfillment time +pub fn authenticate_client_secret( + request_client_secret: Option<&common_utils::types::ClientSecret>, + payment_intent: &PaymentIntent, +) -> Result<(), errors::ApiErrorResponse> { + match (request_client_secret, &payment_intent.client_secret) { + (Some(req_cs), pi_cs) => { + if req_cs != pi_cs { + Err(errors::ApiErrorResponse::ClientSecretInvalid) + } else { + let current_timestamp = common_utils::date_time::now(); + + let session_expiry = payment_intent.session_expiry.unwrap_or( + payment_intent + .created_at + .saturating_add(time::Duration::seconds(consts::DEFAULT_SESSION_EXPIRY)), + ); + + fp_utils::when(current_timestamp > session_expiry, || { + Err(errors::ApiErrorResponse::ClientSecretExpired) + }) + } + } + _ => Ok(()), + } +} + pub(crate) fn validate_payment_status_against_allowed_statuses( intent_status: &storage_enums::IntentStatus, allowed_statuses: &[storage_enums::IntentStatus], @@ -3079,6 +3123,18 @@ pub(crate) fn validate_pm_or_token_given( ) } +#[cfg(feature = "v2")] +// A function to perform database lookup and then verify the client secret +pub async fn verify_payment_intent_time_and_client_secret( + state: &SessionState, + merchant_account: &domain::MerchantAccount, + key_store: &domain::MerchantKeyStore, + client_secret: Option, +) -> error_stack::Result, errors::ApiErrorResponse> { + todo!() +} + +#[cfg(feature = "v1")] // A function to perform database lookup and then verify the client secret pub async fn verify_payment_intent_time_and_client_secret( state: &SessionState, @@ -3965,9 +4021,8 @@ impl AttemptType { storage_scheme, ) .await - .to_duplicate_response(errors::ApiErrorResponse::DuplicatePayment { - payment_id: fetched_payment_intent.get_id().to_owned(), - })?; + .to_duplicate_response(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Failed to insert payment attempt")?; let updated_payment_intent = db .update_payment_intent( @@ -5341,6 +5396,7 @@ pub enum PaymentExternalAuthenticationFlow { }, } +#[cfg(feature = "v1")] pub async fn get_payment_external_authentication_flow_during_confirm( state: &SessionState, key_store: &domain::MerchantKeyStore, diff --git a/crates/router/src/core/payments/operations/payment_response.rs b/crates/router/src/core/payments/operations/payment_response.rs index 09292224ca..e0324438b4 100644 --- a/crates/router/src/core/payments/operations/payment_response.rs +++ b/crates/router/src/core/payments/operations/payment_response.rs @@ -42,6 +42,7 @@ use crate::{ utils, }; +#[cfg(feature = "v1")] #[derive(Debug, Clone, Copy, router_derive::PaymentOperation)] #[operation( operations = "post_update_tracker", @@ -49,6 +50,11 @@ use crate::{ )] pub struct PaymentResponse; +#[cfg(feature = "v2")] +#[derive(Debug, Clone, Copy)] +pub struct PaymentResponse; + +#[cfg(feature = "v1")] #[async_trait] impl PostUpdateTracker, types::PaymentsAuthorizeData> for PaymentResponse @@ -304,6 +310,7 @@ impl PostUpdateTracker, types::PaymentsAuthor } } +#[cfg(feature = "v1")] #[async_trait] impl PostUpdateTracker, types::PaymentsIncrementalAuthorizationData> for PaymentResponse @@ -460,6 +467,7 @@ impl PostUpdateTracker, types::PaymentsIncrementalAu } } +#[cfg(feature = "v1")] #[async_trait] impl PostUpdateTracker, types::PaymentsSyncData> for PaymentResponse { async fn update_tracker<'b>( @@ -513,6 +521,7 @@ impl PostUpdateTracker, types::PaymentsSyncData> for } } +#[cfg(feature = "v1")] #[async_trait] impl PostUpdateTracker, types::PaymentsSessionData> for PaymentResponse @@ -545,6 +554,7 @@ impl PostUpdateTracker, types::PaymentsSessionData> } } +#[cfg(feature = "v1")] #[async_trait] impl PostUpdateTracker, types::SdkPaymentsSessionUpdateData> for PaymentResponse @@ -618,6 +628,7 @@ impl PostUpdateTracker, types::SdkPaymentsSessionUpd } } +#[cfg(feature = "v1")] #[async_trait] impl PostUpdateTracker, types::PaymentsCaptureData> for PaymentResponse @@ -650,6 +661,7 @@ impl PostUpdateTracker, types::PaymentsCaptureData> } } +#[cfg(feature = "v1")] #[async_trait] impl PostUpdateTracker, types::PaymentsCancelData> for PaymentResponse { async fn update_tracker<'b>( @@ -680,6 +692,7 @@ impl PostUpdateTracker, types::PaymentsCancelData> f } } +#[cfg(feature = "v1")] #[async_trait] impl PostUpdateTracker, types::PaymentsApproveData> for PaymentResponse @@ -712,6 +725,7 @@ impl PostUpdateTracker, types::PaymentsApproveData> } } +#[cfg(feature = "v1")] #[async_trait] impl PostUpdateTracker, types::PaymentsRejectData> for PaymentResponse { async fn update_tracker<'b>( @@ -742,6 +756,7 @@ impl PostUpdateTracker, types::PaymentsRejectData> f } } +#[cfg(feature = "v1")] #[async_trait] impl PostUpdateTracker, types::SetupMandateRequestData> for PaymentResponse @@ -847,6 +862,7 @@ impl PostUpdateTracker, types::SetupMandateRequestDa } } +#[cfg(feature = "v1")] #[async_trait] impl PostUpdateTracker, types::CompleteAuthorizeData> for PaymentResponse diff --git a/crates/router/src/core/payments/retry.rs b/crates/router/src/core/payments/retry.rs index 64a85e3358..ad643164f1 100644 --- a/crates/router/src/core/payments/retry.rs +++ b/crates/router/src/core/payments/retry.rs @@ -501,9 +501,8 @@ where let payment_attempt = db .insert_payment_attempt(new_payment_attempt, storage_scheme) .await - .to_duplicate_response(errors::ApiErrorResponse::DuplicatePayment { - payment_id: payment_data.get_payment_intent().get_id().to_owned(), - })?; + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Error inserting payment attempt")?; #[cfg(all(feature = "v2", feature = "payment_v2"))] let payment_attempt = db @@ -514,9 +513,8 @@ where storage_scheme, ) .await - .to_duplicate_response(errors::ApiErrorResponse::DuplicatePayment { - payment_id: payment_data.get_payment_intent().get_id().to_owned(), - })?; + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Error inserting payment attempt")?; // update payment_attempt, connector_response and payment_intent in payment_data payment_data.set_payment_attempt(payment_attempt); diff --git a/crates/router/src/core/payments/routing.rs b/crates/router/src/core/payments/routing.rs index a3123e91a1..1909fa25fb 100644 --- a/crates/router/src/core/payments/routing.rs +++ b/crates/router/src/core/payments/routing.rs @@ -819,6 +819,8 @@ pub async fn perform_session_flow_routing( { let mut pm_type_map: FxHashMap> = FxHashMap::default(); + + #[cfg(feature = "v1")] let profile_id = session_input .payment_intent .profile_id @@ -826,6 +828,9 @@ pub async fn perform_session_flow_routing( .get_required_value("profile_id") .change_context(errors::RoutingError::ProfileIdMissing)?; + #[cfg(feature = "v2")] + let profile_id = session_input.payment_intent.profile_id.clone(); + let business_profile = session_input .state .store @@ -885,28 +890,7 @@ pub async fn perform_session_flow_routing( }; #[cfg(feature = "v2")] - let payment_input = dsl_inputs::PaymentInput { - amount: session_input.payment_intent.amount, - currency: session_input - .payment_intent - .currency - .get_required_value("Currency") - .change_context(errors::RoutingError::DslMissingRequiredField { - field_name: "currency".to_string(), - })?, - authentication_type: session_input.payment_attempt.authentication_type, - card_bin: None, - capture_method: session_input - .payment_attempt - .capture_method - .and_then(|cm| cm.foreign_into()), - business_country: None, - business_label: None, - billing_country: session_input - .country - .map(storage_enums::Country::from_alpha2), - setup_future_usage: session_input.payment_intent.setup_future_usage, - }; + let payment_input = todo!(); let metadata = session_input .payment_intent @@ -1155,9 +1139,9 @@ async fn perform_session_routing_for_pm_type( #[cfg(feature = "v2")] pub fn make_dsl_input_for_surcharge( - payment_attempt: &oss_storage::PaymentAttempt, - payment_intent: &oss_storage::PaymentIntent, - billing_address: Option
, + _payment_attempt: &oss_storage::PaymentAttempt, + _payment_intent: &oss_storage::PaymentIntent, + _billing_address: Option
, ) -> RoutingResult { todo!() } diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs index 93fa3ed44b..22c047edfc 100644 --- a/crates/router/src/core/payments/transformers.rs +++ b/crates/router/src/core/payments/transformers.rs @@ -438,6 +438,7 @@ where } } +#[cfg(feature = "v1")] impl ToResponse for api::PaymentsSessionResponse where F: Clone, @@ -472,6 +473,7 @@ where } } +#[cfg(feature = "v1")] impl ToResponse for api::PaymentsDynamicTaxCalculationResponse where F: Clone, @@ -1899,6 +1901,16 @@ impl ConnectorTransactionId for Nexinets { } } +#[cfg(feature = "v2")] +impl TryFrom> for types::PaymentsCaptureData { + type Error = error_stack::Report; + + fn try_from(additional_data: PaymentAdditionalData<'_, F>) -> Result { + todo!() + } +} + +#[cfg(feature = "v1")] impl TryFrom> for types::PaymentsCaptureData { type Error = error_stack::Report; @@ -1952,6 +1964,16 @@ impl TryFrom> for types::PaymentsCaptureD } } +#[cfg(feature = "v2")] +impl TryFrom> for types::PaymentsCancelData { + type Error = error_stack::Report; + + fn try_from(additional_data: PaymentAdditionalData<'_, F>) -> Result { + todo!() + } +} + +#[cfg(feature = "v1")] impl TryFrom> for types::PaymentsCancelData { type Error = error_stack::Report; @@ -2002,6 +2024,16 @@ impl TryFrom> for types::PaymentsApproveD } } +#[cfg(feature = "v2")] +impl TryFrom> for types::SdkPaymentsSessionUpdateData { + type Error = error_stack::Report; + + fn try_from(additional_data: PaymentAdditionalData<'_, F>) -> Result { + todo!() + } +} + +#[cfg(feature = "v1")] impl TryFrom> for types::SdkPaymentsSessionUpdateData { type Error = error_stack::Report; diff --git a/crates/router/src/core/pm_auth.rs b/crates/router/src/core/pm_auth.rs index 2a93f8c215..d6d4df6700 100644 --- a/crates/router/src/core/pm_auth.rs +++ b/crates/router/src/core/pm_auth.rs @@ -796,6 +796,18 @@ async fn get_selected_config_from_redis( Ok(selected_config) } +#[cfg(feature = "v2")] +pub async fn retrieve_payment_method_from_auth_service( + state: &SessionState, + key_store: &domain::MerchantKeyStore, + auth_token: &payment_methods::BankAccountTokenData, + payment_intent: &PaymentIntent, + _customer: &Option, +) -> RouterResult> { + todo!() +} + +#[cfg(feature = "v1")] pub async fn retrieve_payment_method_from_auth_service( state: &SessionState, key_store: &domain::MerchantKeyStore, @@ -839,13 +851,6 @@ pub async fn retrieve_payment_method_from_auth_service( "error while fetching merchant_connector_account from merchant_id and connector name", )?; - #[cfg(feature = "v2")] - let mca = { - let _ = merchant_account; - let _ = connector; - todo!() - }; - let auth_type = pm_auth_helpers::get_connector_auth_type(mca)?; let BankAccountAccessCreds::AccessToken(access_token) = diff --git a/crates/router/src/core/utils.rs b/crates/router/src/core/utils.rs index 75630da14c..53d97b43d9 100644 --- a/crates/router/src/core/utils.rs +++ b/crates/router/src/core/utils.rs @@ -220,6 +220,25 @@ pub async fn construct_payout_router_data<'a, F>( Ok(router_data) } +#[cfg(feature = "v2")] +#[instrument(skip_all)] +#[allow(clippy::too_many_arguments)] +pub async fn construct_refund_router_data<'a, F>( + _state: &'a SessionState, + _connector_id: &str, + _merchant_account: &domain::MerchantAccount, + _key_store: &domain::MerchantKeyStore, + _money: (MinorUnit, enums::Currency), + _payment_intent: &'a storage::PaymentIntent, + _payment_attempt: &storage::PaymentAttempt, + _refund: &'a storage::Refund, + _creds_identifier: Option, + _charges: Option, +) -> RouterResult> { + todo!() +} + +#[cfg(feature = "v1")] #[instrument(skip_all)] #[allow(clippy::too_many_arguments)] pub async fn construct_refund_router_data<'a, F>( @@ -588,6 +607,7 @@ pub fn validate_dispute_stage_and_dispute_status( ) } +#[cfg(feature = "v1")] #[instrument(skip_all)] pub async fn construct_accept_dispute_router_data<'a>( state: &'a SessionState, @@ -681,6 +701,7 @@ pub async fn construct_accept_dispute_router_data<'a>( Ok(router_data) } +#[cfg(feature = "v1")] #[instrument(skip_all)] pub async fn construct_submit_evidence_router_data<'a>( state: &'a SessionState, @@ -773,6 +794,7 @@ pub async fn construct_submit_evidence_router_data<'a>( Ok(router_data) } +#[cfg(feature = "v1")] #[instrument(skip_all)] #[allow(clippy::too_many_arguments)] pub async fn construct_upload_file_router_data<'a>( @@ -871,6 +893,18 @@ pub async fn construct_upload_file_router_data<'a>( Ok(router_data) } +#[cfg(feature = "v2")] +pub async fn construct_payments_dynamic_tax_calculation_router_data<'a, F: Clone>( + state: &'a SessionState, + merchant_account: &domain::MerchantAccount, + _key_store: &domain::MerchantKeyStore, + payment_data: &mut PaymentData, + merchant_connector_account: &MerchantConnectorAccount, +) -> RouterResult { + todo!() +} + +#[cfg(feature = "v1")] pub async fn construct_payments_dynamic_tax_calculation_router_data<'a, F: Clone>( state: &'a SessionState, merchant_account: &domain::MerchantAccount, @@ -978,6 +1012,7 @@ pub async fn construct_payments_dynamic_tax_calculation_router_data<'a, F: Clone Ok(router_data) } +#[cfg(feature = "v1")] #[instrument(skip_all)] pub async fn construct_defend_dispute_router_data<'a>( state: &'a SessionState, @@ -1459,9 +1494,16 @@ impl GetProfileId for MerchantConnectorAccount { } impl GetProfileId for storage::PaymentIntent { + #[cfg(feature = "v1")] fn get_profile_id(&self) -> Option<&common_utils::id_type::ProfileId> { self.profile_id.as_ref() } + + // TODO: handle this in a better way for v2 + #[cfg(feature = "v2")] + fn get_profile_id(&self) -> Option<&common_utils::id_type::ProfileId> { + Some(&self.profile_id) + } } impl GetProfileId for (storage::PaymentIntent, A) { diff --git a/crates/router/src/core/verification/utils.rs b/crates/router/src/core/verification/utils.rs index 787220651f..8193109c25 100644 --- a/crates/router/src/core/verification/utils.rs +++ b/crates/router/src/core/verification/utils.rs @@ -130,13 +130,23 @@ pub fn log_applepay_verification_response_if_error( .map_err(|error| logger::error!(applepay_domain_verification_error= ?error)) }); } + +#[cfg(feature = "v2")] +pub async fn check_if_profile_id_is_present_in_payment_intent( + payment_id: PaymentId, + state: &SessionState, + auth_data: &AuthenticationData, +) -> CustomResult<(), errors::ApiErrorResponse> { + todo!() +} + +#[cfg(feature = "v1")] pub async fn check_if_profile_id_is_present_in_payment_intent( payment_id: PaymentId, state: &SessionState, auth_data: &AuthenticationData, ) -> CustomResult<(), errors::ApiErrorResponse> { let db = &*state.store; - #[cfg(feature = "v1")] let payment_intent = db .find_payment_intent_by_payment_id_merchant_id( &state.into(), @@ -148,15 +158,5 @@ pub async fn check_if_profile_id_is_present_in_payment_intent( .await .change_context(errors::ApiErrorResponse::Unauthorized)?; - #[cfg(feature = "v2")] - let payment_intent = db - .find_payment_intent_by_id( - &state.into(), - &payment_id, - &auth_data.key_store, - auth_data.merchant_account.storage_scheme, - ) - .await - .change_context(errors::ApiErrorResponse::Unauthorized)?; utils::validate_profile_id_from_auth_layer(auth_data.profile_id.clone(), &payment_intent) } diff --git a/crates/router/src/db/kafka_store.rs b/crates/router/src/db/kafka_store.rs index ff7e8145c3..21e00a7f54 100644 --- a/crates/router/src/db/kafka_store.rs +++ b/crates/router/src/db/kafka_store.rs @@ -1718,7 +1718,7 @@ impl PaymentIntentInterface for KafkaStore { async fn find_payment_intent_by_id( &self, state: &KeyManagerState, - payment_id: &id_type::PaymentId, + payment_id: &id_type::GlobalPaymentId, key_store: &domain::MerchantKeyStore, storage_scheme: MerchantStorageScheme, ) -> CustomResult { diff --git a/crates/router/src/services/kafka/payment_intent.rs b/crates/router/src/services/kafka/payment_intent.rs index cb5ec9cf2e..82e33de8c6 100644 --- a/crates/router/src/services/kafka/payment_intent.rs +++ b/crates/router/src/services/kafka/payment_intent.rs @@ -51,13 +51,13 @@ pub struct KafkaPaymentIntent<'a> { pub merchant_id: &'a id_type::MerchantId, pub status: storage_enums::IntentStatus, pub amount: MinorUnit, - pub currency: Option, + pub currency: storage_enums::Currency, pub amount_captured: Option, pub customer_id: Option<&'a id_type::CustomerId>, pub description: Option<&'a String>, pub return_url: Option<&'a String>, pub metadata: Option, - pub statement_descriptor_name: Option<&'a String>, + pub statement_descriptor: Option<&'a String>, #[serde(with = "time::serde::timestamp")] pub created_at: OffsetDateTime, #[serde(with = "time::serde::timestamp")] @@ -69,7 +69,7 @@ pub struct KafkaPaymentIntent<'a> { pub client_secret: Option<&'a String>, pub active_attempt_id: String, pub attempt_count: i16, - pub profile_id: Option<&'a id_type::ProfileId>, + pub profile_id: &'a id_type::ProfileId, pub payment_confirm_source: Option, pub billing_details: Option>>, pub shipping_details: Option>>, @@ -128,42 +128,43 @@ impl<'a> KafkaPaymentIntent<'a> { #[cfg(feature = "v2")] impl<'a> KafkaPaymentIntent<'a> { pub fn from_storage(intent: &'a PaymentIntent) -> Self { - Self { - id: &intent.id, - merchant_id: &intent.merchant_id, - status: intent.status, - amount: intent.amount, - currency: intent.currency, - amount_captured: intent.amount_captured, - customer_id: intent.customer_id.as_ref(), - description: intent.description.as_ref(), - return_url: intent.return_url.as_ref(), - metadata: intent.metadata.as_ref().map(|x| x.to_string()), - statement_descriptor_name: intent.statement_descriptor_name.as_ref(), - created_at: intent.created_at.assume_utc(), - modified_at: intent.modified_at.assume_utc(), - last_synced: intent.last_synced.map(|i| i.assume_utc()), - setup_future_usage: intent.setup_future_usage, - off_session: intent.off_session, - client_secret: intent.client_secret.as_ref(), - active_attempt_id: intent.active_attempt.get_id(), - attempt_count: intent.attempt_count, - profile_id: intent.profile_id.as_ref(), - payment_confirm_source: intent.payment_confirm_source, - // TODO: use typed information here to avoid PII logging - billing_details: None, - shipping_details: None, - customer_email: intent - .customer_details - .as_ref() - .and_then(|value| value.get_inner().peek().as_object()) - .and_then(|obj| obj.get("email")) - .and_then(|email| email.as_str()) - .map(|email| HashedString::from(Secret::new(email.to_string()))), - feature_metadata: intent.feature_metadata.as_ref(), - merchant_order_reference_id: intent.merchant_order_reference_id.as_ref(), - organization_id: &intent.organization_id, - } + // Self { + // id: &intent.id, + // merchant_id: &intent.merchant_id, + // status: intent.status, + // amount: intent.amount, + // currency: intent.currency, + // amount_captured: intent.amount_captured, + // customer_id: intent.customer_id.as_ref(), + // description: intent.description.as_ref(), + // return_url: intent.return_url.as_ref(), + // metadata: intent.metadata.as_ref().map(|x| x.to_string()), + // statement_descriptor: intent.statement_descriptor.as_ref(), + // created_at: intent.created_at.assume_utc(), + // modified_at: intent.modified_at.assume_utc(), + // last_synced: intent.last_synced.map(|i| i.assume_utc()), + // setup_future_usage: intent.setup_future_usage, + // off_session: intent.off_session, + // client_secret: intent.client_secret.as_ref(), + // active_attempt_id: intent.active_attempt.get_id(), + // attempt_count: intent.attempt_count, + // profile_id: &intent.profile_id, + // payment_confirm_source: intent.payment_confirm_source, + // // TODO: use typed information here to avoid PII logging + // billing_details: None, + // shipping_details: None, + // customer_email: intent + // .customer_details + // .as_ref() + // .and_then(|value| value.get_inner().peek().as_object()) + // .and_then(|obj| obj.get("email")) + // .and_then(|email| email.as_str()) + // .map(|email| HashedString::from(Secret::new(email.to_string()))), + // feature_metadata: intent.feature_metadata.as_ref(), + // merchant_order_reference_id: intent.merchant_order_reference_id.as_ref(), + // organization_id: &intent.organization_id, + // } + todo!() } } diff --git a/crates/router/src/services/kafka/payment_intent_event.rs b/crates/router/src/services/kafka/payment_intent_event.rs index 321ce55810..5657846ca4 100644 --- a/crates/router/src/services/kafka/payment_intent_event.rs +++ b/crates/router/src/services/kafka/payment_intent_event.rs @@ -53,13 +53,13 @@ pub struct KafkaPaymentIntentEvent<'a> { pub merchant_id: &'a id_type::MerchantId, pub status: storage_enums::IntentStatus, pub amount: MinorUnit, - pub currency: Option, + pub currency: storage_enums::Currency, pub amount_captured: Option, pub customer_id: Option<&'a id_type::CustomerId>, pub description: Option<&'a String>, pub return_url: Option<&'a String>, pub metadata: Option, - pub statement_descriptor_name: Option<&'a String>, + pub statement_descriptor: Option<&'a String>, #[serde(with = "time::serde::timestamp::milliseconds")] pub created_at: OffsetDateTime, #[serde(with = "time::serde::timestamp::milliseconds")] @@ -71,7 +71,7 @@ pub struct KafkaPaymentIntentEvent<'a> { pub client_secret: Option<&'a String>, pub active_attempt_id: String, pub attempt_count: i16, - pub profile_id: Option<&'a id_type::ProfileId>, + pub profile_id: &'a id_type::ProfileId, pub payment_confirm_source: Option, pub billing_details: Option>>, pub shipping_details: Option>>, @@ -142,42 +142,43 @@ impl<'a> KafkaPaymentIntentEvent<'a> { #[cfg(feature = "v2")] impl<'a> KafkaPaymentIntentEvent<'a> { pub fn from_storage(intent: &'a PaymentIntent) -> Self { - Self { - id: &intent.id, - merchant_id: &intent.merchant_id, - status: intent.status, - amount: intent.amount, - currency: intent.currency, - amount_captured: intent.amount_captured, - customer_id: intent.customer_id.as_ref(), - description: intent.description.as_ref(), - return_url: intent.return_url.as_ref(), - metadata: intent.metadata.as_ref().map(|x| x.to_string()), - statement_descriptor_name: intent.statement_descriptor_name.as_ref(), - created_at: intent.created_at.assume_utc(), - modified_at: intent.modified_at.assume_utc(), - last_synced: intent.last_synced.map(|i| i.assume_utc()), - setup_future_usage: intent.setup_future_usage, - off_session: intent.off_session, - client_secret: intent.client_secret.as_ref(), - active_attempt_id: intent.active_attempt.get_id(), - attempt_count: intent.attempt_count, - profile_id: intent.profile_id.as_ref(), - payment_confirm_source: intent.payment_confirm_source, - // TODO: use typed information here to avoid PII logging - billing_details: None, - shipping_details: None, - customer_email: intent - .customer_details - .as_ref() - .and_then(|value| value.get_inner().peek().as_object()) - .and_then(|obj| obj.get("email")) - .and_then(|email| email.as_str()) - .map(|email| HashedString::from(Secret::new(email.to_string()))), - feature_metadata: intent.feature_metadata.as_ref(), - merchant_order_reference_id: intent.merchant_order_reference_id.as_ref(), - organization_id: &intent.organization_id, - } + // Self { + // id: &intent.id, + // merchant_id: &intent.merchant_id, + // status: intent.status, + // amount: intent.amount, + // currency: intent.currency, + // amount_captured: intent.amount_captured, + // customer_id: intent.customer_id.as_ref(), + // description: intent.description.as_ref(), + // return_url: intent.return_url.as_ref(), + // metadata: intent.metadata.as_ref().map(|x| x.to_string()), + // statement_descriptor: intent.statement_descriptor.as_ref(), + // created_at: intent.created_at.assume_utc(), + // modified_at: intent.modified_at.assume_utc(), + // last_synced: intent.last_synced.map(|i| i.assume_utc()), + // setup_future_usage: intent.setup_future_usage, + // off_session: intent.off_session, + // client_secret: intent.client_secret.as_ref(), + // active_attempt_id: intent.active_attempt.get_id(), + // attempt_count: intent.attempt_count, + // profile_id: &intent.profile_id, + // payment_confirm_source: intent.payment_confirm_source, + // // TODO: use typed information here to avoid PII logging + // billing_details: None, + // shipping_details: None, + // customer_email: intent + // .customer_details + // .as_ref() + // .and_then(|value| value.get_inner().peek().as_object()) + // .and_then(|obj| obj.get("email")) + // .and_then(|email| email.as_str()) + // .map(|email| HashedString::from(Secret::new(email.to_string()))), + // feature_metadata: intent.feature_metadata.as_ref(), + // merchant_order_reference_id: intent.merchant_order_reference_id.as_ref(), + // organization_id: &intent.organization_id, + // } + todo!() } } diff --git a/crates/router/src/types/storage.rs b/crates/router/src/types/storage.rs index 9665642389..13a5291062 100644 --- a/crates/router/src/types/storage.rs +++ b/crates/router/src/types/storage.rs @@ -48,7 +48,7 @@ pub use diesel_models::{ }; pub use hyperswitch_domain_models::payments::{ payment_attempt::{PaymentAttempt, PaymentAttemptNew, PaymentAttemptUpdate}, - payment_intent::{PaymentIntentNew, PaymentIntentUpdate, PaymentIntentUpdateFields}, + payment_intent::{PaymentIntentUpdate, PaymentIntentUpdateFields}, PaymentIntent, }; #[cfg(feature = "payouts")] diff --git a/crates/router/src/utils.rs b/crates/router/src/utils.rs index edeb3f12fa..e6f549f4fc 100644 --- a/crates/router/src/utils.rs +++ b/crates/router/src/utils.rs @@ -370,6 +370,7 @@ pub async fn find_mca_from_authentication_id_type( } } +#[cfg(feature = "v1")] pub async fn get_mca_from_payment_intent( state: &SessionState, merchant_account: &domain::MerchantAccount, diff --git a/crates/storage_impl/src/lib.rs b/crates/storage_impl/src/lib.rs index cadb78944e..974de5be80 100644 --- a/crates/storage_impl/src/lib.rs +++ b/crates/storage_impl/src/lib.rs @@ -332,12 +332,9 @@ impl UniqueConstraints for diesel_models::Address { #[cfg(all(feature = "v2", feature = "payment_v2"))] impl UniqueConstraints for diesel_models::PaymentIntent { fn unique_constraints(&self) -> Vec { - vec![format!( - "pi_{}_{}", - self.merchant_id.get_string_repr(), - self.merchant_reference_id - )] + vec![self.id.get_string_repr().to_owned()] } + fn table_name(&self) -> &str { "PaymentIntent" } @@ -345,6 +342,7 @@ impl UniqueConstraints for diesel_models::PaymentIntent { #[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "payment_v2")))] impl UniqueConstraints for diesel_models::PaymentIntent { + #[cfg(feature = "v1")] fn unique_constraints(&self) -> Vec { vec![format!( "pi_{}_{}", @@ -352,6 +350,12 @@ impl UniqueConstraints for diesel_models::PaymentIntent { self.payment_id.get_string_repr() )] } + + #[cfg(feature = "v2")] + fn unique_constraints(&self) -> Vec { + vec![format!("pi_{}", self.id.get_string_repr())] + } + fn table_name(&self) -> &str { "PaymentIntent" } @@ -437,7 +441,7 @@ impl UniqueConstraints for diesel_models::PaymentMethod { #[cfg(all(feature = "v2", feature = "payment_methods_v2"))] impl UniqueConstraints for diesel_models::PaymentMethod { fn unique_constraints(&self) -> Vec { - vec![self.id.get_string_repr()] + vec![self.id.get_string_repr().to_owned()] } fn table_name(&self) -> &str { "PaymentMethod" diff --git a/crates/storage_impl/src/mock_db/payment_intent.rs b/crates/storage_impl/src/mock_db/payment_intent.rs index e0328871e3..0f1161f644 100644 --- a/crates/storage_impl/src/mock_db/payment_intent.rs +++ b/crates/storage_impl/src/mock_db/payment_intent.rs @@ -167,7 +167,7 @@ impl PaymentIntentInterface for MockDb { async fn find_payment_intent_by_id( &self, _state: &KeyManagerState, - id: &common_utils::id_type::PaymentId, + id: &common_utils::id_type::GlobalPaymentId, _merchant_key_store: &MerchantKeyStore, _storage_scheme: storage_enums::MerchantStorageScheme, ) -> error_stack::Result { diff --git a/crates/storage_impl/src/payments/payment_intent.rs b/crates/storage_impl/src/payments/payment_intent.rs index 97fa5873ca..971c5edfcd 100644 --- a/crates/storage_impl/src/payments/payment_intent.rs +++ b/crates/storage_impl/src/payments/payment_intent.rs @@ -65,6 +65,7 @@ use crate::{ #[async_trait::async_trait] impl PaymentIntentInterface for KVRouterStore { + #[cfg(feature = "v1")] async fn insert_payment_intent( &self, state: &KeyManagerState, @@ -142,6 +143,33 @@ impl PaymentIntentInterface for KVRouterStore { } } + #[cfg(feature = "v2")] + async fn insert_payment_intent( + &self, + state: &KeyManagerState, + payment_intent: PaymentIntent, + merchant_key_store: &MerchantKeyStore, + storage_scheme: MerchantStorageScheme, + ) -> error_stack::Result { + match storage_scheme { + MerchantStorageScheme::PostgresOnly => { + self.router_store + .insert_payment_intent( + state, + payment_intent, + merchant_key_store, + storage_scheme, + ) + .await + } + + MerchantStorageScheme::RedisKv => { + todo!("Implement payment intent insert for kv") + } + } + } + + #[cfg(feature = "v1")] #[instrument(skip_all)] async fn update_payment_intent( &self, @@ -229,6 +257,34 @@ impl PaymentIntentInterface for KVRouterStore { } } + #[cfg(feature = "v2")] + #[instrument(skip_all)] + async fn update_payment_intent( + &self, + state: &KeyManagerState, + this: PaymentIntent, + payment_intent_update: PaymentIntentUpdate, + merchant_key_store: &MerchantKeyStore, + storage_scheme: MerchantStorageScheme, + ) -> error_stack::Result { + match storage_scheme { + MerchantStorageScheme::PostgresOnly => { + self.router_store + .update_payment_intent( + state, + this, + payment_intent_update, + merchant_key_store, + storage_scheme, + ) + .await + } + MerchantStorageScheme::RedisKv => { + todo!() + } + } + } + #[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "payment_v2")))] #[instrument(skip_all)] async fn find_payment_intent_by_payment_id_merchant_id( @@ -294,11 +350,14 @@ impl PaymentIntentInterface for KVRouterStore { async fn find_payment_intent_by_id( &self, state: &KeyManagerState, - id: &common_utils::id_type::PaymentId, + id: &common_utils::id_type::GlobalPaymentId, merchant_key_store: &MerchantKeyStore, _storage_scheme: MerchantStorageScheme, ) -> error_stack::Result { - let conn = pg_connection_read(self).await?; + let conn: bb8::PooledConnection< + '_, + async_bb8_diesel::ConnectionManager, + > = pg_connection_read(self).await?; let diesel_payment_intent = DieselPaymentIntent::find_by_global_id(&conn, id) .await .map_err(|er| { @@ -555,7 +614,7 @@ impl PaymentIntentInterface for crate::RouterStore { async fn find_payment_intent_by_id( &self, state: &KeyManagerState, - id: &common_utils::id_type::PaymentId, + id: &common_utils::id_type::GlobalPaymentId, merchant_key_store: &MerchantKeyStore, _storage_scheme: MerchantStorageScheme, ) -> error_stack::Result { diff --git a/v2_migrations/2024-08-28-081721_add_v2_columns/down.sql b/v2_migrations/2024-08-28-081721_add_v2_columns/down.sql index 427dbcb4d5..de4886b866 100644 --- a/v2_migrations/2024-08-28-081721_add_v2_columns/down.sql +++ b/v2_migrations/2024-08-28-081721_add_v2_columns/down.sql @@ -24,4 +24,10 @@ ALTER TABLE payment_intent DROP COLUMN merchant_reference_id, DROP COLUMN prerouting_algorithm, DROP COLUMN surcharge_amount, DROP COLUMN tax_on_surcharge, - DROP COLUMN frm_merchant_decision; + DROP COLUMN frm_merchant_decision, + DROP COLUMN statement_descriptor, + DROP COLUMN enable_payment_link, + DROP COLUMN apply_mit_exemption, + DROP COLUMN customer_present, + DROP COLUMN routing_algorithm_id, + DROP COLUMN payment_link_config; diff --git a/v2_migrations/2024-08-28-081721_add_v2_columns/up.sql b/v2_migrations/2024-08-28-081721_add_v2_columns/up.sql index 719a8afa30..b89985ae81 100644 --- a/v2_migrations/2024-08-28-081721_add_v2_columns/up.sql +++ b/v2_migrations/2024-08-28-081721_add_v2_columns/up.sql @@ -5,6 +5,7 @@ ADD COLUMN IF NOT EXISTS merchant_reference_id VARCHAR(64), ADD COLUMN IF NOT EXISTS default_billing_address BYTEA DEFAULT NULL, ADD COLUMN IF NOT EXISTS default_shipping_address BYTEA DEFAULT NULL, ADD COLUMN IF NOT EXISTS status "DeleteStatus" NOT NULL DEFAULT 'active'; + CREATE TYPE "OrderFulfillmentTimeOrigin" AS ENUM ('create', 'confirm'); ALTER TABLE business_profile @@ -16,14 +17,19 @@ ADD COLUMN routing_algorithm_id VARCHAR(64) DEFAULT NULL, ADD COLUMN default_fallback_routing JSONB DEFAULT NULL; ALTER TABLE payment_intent -ADD COLUMN merchant_reference_id VARCHAR(64) NOT NULL, +ADD COLUMN merchant_reference_id VARCHAR(64), ADD COLUMN billing_address BYTEA DEFAULT NULL, ADD COLUMN shipping_address BYTEA DEFAULT NULL, ADD COLUMN capture_method "CaptureMethod", ADD COLUMN authentication_type "AuthenticationType", ADD COLUMN amount_to_capture bigint, - ADD COLUMN prerouting_algorithm JSONB, -- straight_through_algorithm from payment_attempt + ADD COLUMN prerouting_algorithm JSONB, ADD COLUMN surcharge_amount bigint, - ADD COLUMN tax_on_surcharge bigint, -- tax_amount from payment_attempt - ADD COLUMN frm_merchant_decision VARCHAR(64); - + ADD COLUMN tax_on_surcharge bigint, + ADD COLUMN frm_merchant_decision VARCHAR(64), + ADD COLUMN statement_descriptor VARCHAR(255), + ADD COLUMN enable_payment_link BOOLEAN, + ADD COLUMN apply_mit_exemption BOOLEAN, + ADD COLUMN customer_present BOOLEAN, + ADD COLUMN routing_algorithm_id VARCHAR(64), + ADD COLUMN payment_link_config JSONB; diff --git a/v2_migrations/2024-08-28-081838_update_v2_primary_key_constraints/down.sql b/v2_migrations/2024-08-28-081838_update_v2_primary_key_constraints/down.sql index 6acb08597f..50f0e89da8 100644 --- a/v2_migrations/2024-08-28-081838_update_v2_primary_key_constraints/down.sql +++ b/v2_migrations/2024-08-28-081838_update_v2_primary_key_constraints/down.sql @@ -1,4 +1,5 @@ -- Backfill for organization table +------------------------ Organization ----------------------- UPDATE ORGANIZATION SET org_id = id WHERE org_id IS NULL; @@ -16,6 +17,7 @@ SET org_name = organization_name WHERE org_name IS NULL AND organization_name IS NOT NULL; +------------------------ Merchant Account ----------------------- -- The new primary key for v2 merchant account will be `id` ALTER TABLE merchant_account DROP CONSTRAINT merchant_account_pkey; @@ -33,6 +35,7 @@ WHERE merchant_id IS NULL; ALTER TABLE merchant_account ADD PRIMARY KEY (merchant_id); +------------------------ Business Profile ----------------------- UPDATE business_profile SET profile_id = id WHERE profile_id IS NULL; @@ -42,6 +45,7 @@ ALTER TABLE business_profile DROP COLUMN id; ALTER TABLE business_profile ADD PRIMARY KEY (profile_id); +------------------------ Merchant Connector Account ----------------------- ALTER TABLE merchant_connector_account DROP CONSTRAINT merchant_connector_account_pkey; UPDATE merchant_connector_account @@ -54,6 +58,9 @@ ADD PRIMARY KEY (merchant_connector_id); ALTER TABLE merchant_connector_account ALTER COLUMN profile_id DROP NOT NULL; +DROP INDEX IF EXISTS merchant_connector_account_profile_id_index; + +------------------------ Customers ----------------------- -- Run this query only when V1 is deprecated ALTER TABLE customers DROP CONSTRAINT customers_pkey; @@ -65,6 +72,7 @@ WHERE customer_id IS NULL; ALTER TABLE customers ADD PRIMARY KEY (merchant_id, customer_id); +------------------------ Payment Intent ----------------------- ALTER TABLE payment_intent DROP CONSTRAINT payment_intent_pkey; UPDATE payment_intent @@ -73,3 +81,12 @@ WHERE payment_id IS NULL; ALTER TABLE payment_intent ADD PRIMARY KEY (payment_id, merchant_id); + +ALTER TABLE payment_intent +ALTER COLUMN profile_id DROP NOT NULL; + +ALTER TABLE payment_intent +ALTER COLUMN currency DROP NOT NULL; + +ALTER TABLE payment_intent +ALTER COLUMN client_secret DROP NOT NULL; diff --git a/v2_migrations/2024-08-28-081838_update_v2_primary_key_constraints/up.sql b/v2_migrations/2024-08-28-081838_update_v2_primary_key_constraints/up.sql index 440391529a..8d89e4bc92 100644 --- a/v2_migrations/2024-08-28-081838_update_v2_primary_key_constraints/up.sql +++ b/v2_migrations/2024-08-28-081838_update_v2_primary_key_constraints/up.sql @@ -69,6 +69,8 @@ ALTER TABLE merchant_connector_account ALTER COLUMN profile_id SET NOT NULL; +CREATE INDEX IF NOT EXISTS merchant_connector_account_profile_id_index ON merchant_connector_account (profile_id); + ------------------------ Customers ----------------------- -- Run this query only when V1 is deprecated ALTER TABLE customers DROP CONSTRAINT IF EXISTS customers_pkey; @@ -88,3 +90,12 @@ ALTER TABLE payment_intent DROP CONSTRAINT payment_intent_pkey; ALTER TABLE payment_intent ADD PRIMARY KEY (id); + +-- This migration is to make fields mandatory in payment_intent table +ALTER TABLE payment_intent +ALTER COLUMN profile_id +SET NOT NULL, + ALTER COLUMN currency +SET NOT NULL, + ALTER COLUMN client_secret +SET NOT NULL; diff --git a/v2_migrations/2024-08-28-081847_drop_v1_columns/down.sql b/v2_migrations/2024-08-28-081847_drop_v1_columns/down.sql index 83b369beac..004c46a67d 100644 --- a/v2_migrations/2024-08-28-081847_drop_v1_columns/down.sql +++ b/v2_migrations/2024-08-28-081847_drop_v1_columns/down.sql @@ -59,4 +59,11 @@ ADD COLUMN IF NOT EXISTS payment_id VARCHAR(64) NOT NULL, ADD COLUMN business_label VARCHAR(64), ADD COLUMN incremental_authorization_allowed BOOLEAN, ADD COLUMN fingerprint_id VARCHAR(64), - ADD COLUMN merchant_decision VARCHAR(64); + ADD COLUMN merchant_decision VARCHAR(64), + ADD COLUMN statement_descriptor_name VARCHAR(255), + ADD COLUMN amount_to_capture BIGINT, + ADD COLUMN off_session BOOLEAN, + ADD COLUMN payment_confirm_source "PaymentSource", + ADD COLUMN merchant_order_reference_id VARCHAR(255), + ADD COLUMN is_payment_processor_token_flow BOOLEAN, + ADD COLUMN charges jsonb; diff --git a/v2_migrations/2024-08-28-081847_drop_v1_columns/up.sql b/v2_migrations/2024-08-28-081847_drop_v1_columns/up.sql index 0879d667f9..0d2fcdd61d 100644 --- a/v2_migrations/2024-08-28-081847_drop_v1_columns/up.sql +++ b/v2_migrations/2024-08-28-081847_drop_v1_columns/up.sql @@ -57,4 +57,11 @@ ALTER TABLE payment_intent DROP COLUMN payment_id, DROP COLUMN business_label, DROP COLUMN incremental_authorization_allowed, DROP COLUMN fingerprint_id, - DROP COLUMN merchant_decision; + DROP COLUMN merchant_decision, + DROP COLUMN statement_descriptor_name, + DROP COLUMN amount_to_capture, + DROP COLUMN off_session, + DROP COLUMN payment_confirm_source, + DROP COLUMN merchant_order_reference_id, + DROP COLUMN is_payment_processor_token_flow, + DROP COLUMN charges; diff --git a/v2_migrations/2024-09-13-075054_create-index-profile-id-mca/down.sql b/v2_migrations/2024-09-13-075054_create-index-profile-id-mca/down.sql deleted file mode 100644 index 32225e3496..0000000000 --- a/v2_migrations/2024-09-13-075054_create-index-profile-id-mca/down.sql +++ /dev/null @@ -1,2 +0,0 @@ --- This file should undo anything in `up.sql` -DROP INDEX IF EXISTS merchant_connector_account_profile_id_index; \ No newline at end of file diff --git a/v2_migrations/2024-09-13-075054_create-index-profile-id-mca/up.sql b/v2_migrations/2024-09-13-075054_create-index-profile-id-mca/up.sql deleted file mode 100644 index f4ca993fef..0000000000 --- a/v2_migrations/2024-09-13-075054_create-index-profile-id-mca/up.sql +++ /dev/null @@ -1,2 +0,0 @@ --- Your SQL goes here -CREATE INDEX IF NOT EXISTS merchant_connector_account_profile_id_index ON merchant_connector_account (profile_id);