Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

refactor(payment_intent_v2): payment intent fields refactoring #5880

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
9de3e5e
make v2 changes for payment intent diesel and domain models
hrithikesh026 Sep 2, 2024
a193623
Merge branch 'main' into payment-intent-diesel-and-domail-models-chan…
Narayanbhat166 Sep 3, 2024
b06e82d
refactor: regroup the migrations
Narayanbhat166 Sep 3, 2024
94b2543
add fields to payment intent from payment attempt
hrithikesh026 Sep 3, 2024
1b97e93
chore: run formatter
hyperswitch-bot[bot] Sep 3, 2024
4f24d01
refactor: make domain models compile for v2
Narayanbhat166 Sep 4, 2024
56dcdc0
chore: cargo clippy
Narayanbhat166 Sep 4, 2024
8d100b1
Merge branch 'main' into payment-intent-diesel-and-domail-models-chan…
Narayanbhat166 Sep 4, 2024
9b517ff
add surcharge_amount and tax_on_surcharge to payment_intent
hrithikesh026 Sep 5, 2024
3f1d00a
refactor: remove unused code related to v1 features
Narayanbhat166 Sep 6, 2024
0daf196
refactor: make v1 compile
Narayanbhat166 Sep 7, 2024
2a25402
refactor: Update imports and remove unused code for v1 features
Narayanbhat166 Sep 7, 2024
95917c8
Merge branch 'main' into payment-intent-diesel-and-domail-models-chan…
Narayanbhat166 Sep 7, 2024
e5a7ba8
chore: run formatter
hyperswitch-bot[bot] Sep 7, 2024
5a5355a
chore: fix v2 errors
Narayanbhat166 Sep 8, 2024
da4c00f
chore: cargo clippy
Narayanbhat166 Sep 8, 2024
e453401
chore: fix ci checks
Narayanbhat166 Sep 9, 2024
f3986f3
chore: fix v2 checks
Narayanbhat166 Sep 9, 2024
dc791c3
make v2 changes for payment attempt diesel model
hrithikesh026 Sep 9, 2024
b263797
make v2 changes for payment attempt domail model
hrithikesh026 Sep 9, 2024
f4b2426
fix migration errors
hrithikesh026 Sep 9, 2024
588c298
refactor: remove payment_v2 feature flag
Narayanbhat166 Sep 9, 2024
3d782d8
refactor: remove payment_v2 feature flag
Narayanbhat166 Sep 9, 2024
426ec3f
Revert "refactor: remove payment_v2 feature flag"
Narayanbhat166 Sep 10, 2024
d003b36
Revert "refactor: remove payment_v2 feature flag"
Narayanbhat166 Sep 10, 2024
6befb81
Revert "fix migration errors"
Narayanbhat166 Sep 10, 2024
8bab2fa
Revert "make v2 changes for payment attempt domail model"
Narayanbhat166 Sep 10, 2024
80326fc
Revert "make v2 changes for payment attempt diesel model"
Narayanbhat166 Sep 10, 2024
360ca8d
Merge branch 'main' into payment-intent-diesel-and-domail-models-chan…
Narayanbhat166 Sep 10, 2024
5f66fea
fix: merge fixes
Narayanbhat166 Sep 10, 2024
3a9e8b0
fix: schema file for v2
Narayanbhat166 Sep 10, 2024
ffdcb00
fix: diesel errors
Narayanbhat166 Sep 10, 2024
4ec2ed4
chore: rename merchant_decision in payment_intent
hrithikesh026 Sep 11, 2024
ac48d75
chore: fix migration consistency
hrithikesh026 Sep 11, 2024
ddf0bfe
Merge branch 'main' into payment-intent-diesel-and-domail-models-chan…
Narayanbhat166 Sep 11, 2024
66bc45c
fix: merge fixes
Narayanbhat166 Sep 11, 2024
b0e8d2e
refactor: make currency and profile id mandatory intent
Narayanbhat166 Sep 12, 2024
9591867
chore: Drop v1 columns and add v2 columns to payment_intent table
Narayanbhat166 Sep 12, 2024
a2f7bdc
wip: fix compilation errors for payment attempt
Narayanbhat166 Sep 12, 2024
b7cb269
refactor: make client secret mandatory and add todo!() for kafkaintent
Narayanbhat166 Sep 13, 2024
3a36b10
chore: fix schema file
Narayanbhat166 Sep 13, 2024
33d7bd3
Merge branch 'main' into payment-intent-diesel-and-domail-models-chan…
Narayanbhat166 Sep 13, 2024
05c4333
chore: cargo clippy
Narayanbhat166 Sep 13, 2024
ea18f1a
refactor: remove amount_to_capture and add apply_mit_exemption
Narayanbhat166 Sep 13, 2024
2453e41
refactor: remove few fields that are not necessary / moved to `featur…
Narayanbhat166 Sep 15, 2024
a31dcea
refactor: add global_payment_id type
Narayanbhat166 Sep 16, 2024
5aafeec
chore: run formatter
hyperswitch-bot[bot] Sep 16, 2024
f30fe4e
refactor: remove charges and move all amount related fields to a struct
Narayanbhat166 Sep 16, 2024
bdeb683
chore: add comments to fields in payment intent domain model
Narayanbhat166 Sep 16, 2024
4230f1c
refactor: make few boolean fields as enum
Narayanbhat166 Sep 16, 2024
ddf0118
chore: cargo clippy
Narayanbhat166 Sep 17, 2024
4de62bc
chore: move enums to common enums
Narayanbhat166 Sep 17, 2024
3f8d42c
Merge branch 'main' into payment-intent-diesel-and-domail-models-chan…
Narayanbhat166 Sep 17, 2024
a5c97e2
chore: fix typos
Narayanbhat166 Sep 17, 2024
3f485ae
chore: rename enum variants
Narayanbhat166 Sep 17, 2024
6918814
chore: rename enum variants for mit exemption
Narayanbhat166 Sep 17, 2024
f5b181a
Merge branch 'main' into payment-intent-diesel-and-domail-models-chan…
Narayanbhat166 Sep 17, 2024
54157af
refactor: throw internal server error instead of duplicate error
Narayanbhat166 Sep 17, 2024
06e324f
feat: add customer_present, payment_link_config, routing_algorithm_id…
Narayanbhat166 Sep 18, 2024
fdb179d
Merge branch 'main' into payment-intent-diesel-and-domail-models-chan…
Narayanbhat166 Sep 18, 2024
63b56d7
fix: merge fixes
Narayanbhat166 Sep 18, 2024
cb8863f
feat: create Url and ClientSecret types
Narayanbhat166 Sep 19, 2024
ee70ec9
refactor: add more domain types and rename PaymentGlobalId to GlobalP…
Narayanbhat166 Sep 19, 2024
f1ca9b7
chore: run formatter
hyperswitch-bot[bot] Sep 19, 2024
97540e5
chore: cargo clippy
Narayanbhat166 Sep 19, 2024
5afdadf
refactor: add a new LengthString domain type
Narayanbhat166 Sep 19, 2024
8f73422
chore: cargo fix
Narayanbhat166 Sep 19, 2024
fd3baed
feat: add a domain type for statement descriptor
Narayanbhat166 Sep 19, 2024
bef11e8
Merge branch 'main' into payment-intent-diesel-and-domail-models-chan…
Narayanbhat166 Sep 19, 2024
e4965fd
chore: move mca migration to primary constraints
Narayanbhat166 Sep 19, 2024
9f41fb7
Merge branch 'main' into payment-intent-diesel-and-domail-models-chan…
Narayanbhat166 Sep 20, 2024
65acf25
chore: run formatter
hyperswitch-bot[bot] Sep 20, 2024
839c716
chore: fix tests
Narayanbhat166 Sep 20, 2024
5b1cf99
chore: run formatter
hyperswitch-bot[bot] Sep 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
154 changes: 1 addition & 153 deletions crates/api_models/src/payments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -68,154 +64,6 @@ pub struct BankCodeResponse {
pub eligible_connectors: Vec<String>,
}

#[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<D>(deserializer: D) -> Result<Self, D::Error>
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<E>(self, value: &str) -> Result<ClientSecret, E>
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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
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 {
Expand Down
36 changes: 36 additions & 0 deletions crates/common_enums/src/enums.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
73 changes: 73 additions & 0 deletions crates/common_enums/src/transformers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1991,6 +1991,79 @@ mod custom_serde {
}
}

impl From<Option<bool>> for super::External3dsAuthenticationRequest {
fn from(value: Option<bool>) -> 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<Option<bool>> for super::EnablePaymentLinkRequest {
fn from(value: Option<bool>) -> Self {
match value {
Some(true) => Self::Enable,
_ => Self::Skip,
}
}
}

impl From<Option<bool>> for super::MitExemptionRequest {
fn from(value: Option<bool>) -> 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<Option<bool>> for super::PresenceOfCustomerDuringPayment {
fn from(value: Option<bool>) -> 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)]
Expand Down
5 changes: 5 additions & 0 deletions crates/common_utils/src/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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";
8 changes: 4 additions & 4 deletions crates/common_utils/src/id_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand All @@ -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};
Expand Down Expand Up @@ -155,6 +154,7 @@ impl<const MAX_LENGTH: u8, const MIN_LENGTH: u8> LengthId<MAX_LENGTH, MIN_LENGTH
Self(alphanumeric_id)
}

#[cfg(feature = "v2")]
/// Create a new LengthId from aplhanumeric id
pub(crate) fn from_alphanumeric_id(
alphanumeric_id: AlphaNumericId,
Expand Down
17 changes: 13 additions & 4 deletions crates/common_utils/src/id_type/global_id.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#![allow(unused)]
pub mod payment;
pub mod payment_methods;

use diesel::{backend::Backend, deserialize::FromSql, serialize::ToSql, sql_types};
use error_stack::ResultExt;
Expand Down Expand Up @@ -34,8 +36,9 @@ impl GlobalEntity {
}
}

/// Cell identifier for an instance / deployment of application
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub(crate) struct CellId(LengthId<CELL_IDENTIFIER_LENGTH, CELL_IDENTIFIER_LENGTH>);
pub struct CellId(LengthId<CELL_IDENTIFIER_LENGTH, CELL_IDENTIFIER_LENGTH>);

#[derive(Debug, Error, PartialEq, Eq)]
pub enum CellIdError {
Expand Down Expand Up @@ -107,7 +110,9 @@ impl GlobalId {
Self(LengthId::new_unchecked(alphanumeric_id))
}

pub fn from_string(input_string: String) -> Result<Self, GlobalIdError> {
pub(crate) fn from_string(
input_string: std::borrow::Cow<'static, str>,
) -> Result<Self, GlobalIdError> {
let length_id = LengthId::from(input_string.into())?;
let input_string = &length_id.0 .0;
let (cell_id, remaining) = input_string
Expand All @@ -118,6 +123,10 @@ impl GlobalId {

Ok(Self(length_id))
}

pub(crate) fn get_string_repr(&self) -> &str {
&self.0 .0 .0
}
}

impl<DB> ToSql<sql_types::Text, DB> for GlobalId
Expand Down Expand Up @@ -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)
}
}

Expand Down Expand Up @@ -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);
}

Expand Down
Loading
Loading