diff --git a/crates/diesel_models/src/payment_attempt.rs b/crates/diesel_models/src/payment_attempt.rs index 0aeef652d0..c45eee7b0c 100644 --- a/crates/diesel_models/src/payment_attempt.rs +++ b/crates/diesel_models/src/payment_attempt.rs @@ -1,3 +1,4 @@ +use common_utils::pii; use diesel::{AsChangeset, Identifiable, Insertable, Queryable}; use serde::{Deserialize, Serialize}; use time::PrimitiveDateTime; @@ -72,6 +73,7 @@ pub struct PaymentAttempt { pub charge_id: Option, pub client_source: Option, pub client_version: Option, + pub customer_acceptance: Option, } impl PaymentAttempt { @@ -155,6 +157,7 @@ pub struct PaymentAttemptNew { pub charge_id: Option, pub client_source: Option, pub client_version: Option, + pub customer_acceptance: Option, } impl PaymentAttemptNew { @@ -240,6 +243,7 @@ pub enum PaymentAttemptUpdate { payment_method_billing_address_id: Option, client_source: Option, client_version: Option, + customer_acceptance: Option, }, VoidUpdate { status: storage_enums::AttemptStatus, @@ -410,6 +414,7 @@ pub struct PaymentAttemptUpdateInternal { charge_id: Option, client_source: Option, client_version: Option, + customer_acceptance: Option, } impl PaymentAttemptUpdateInternal { @@ -478,6 +483,7 @@ impl PaymentAttemptUpdate { charge_id, client_source, client_version, + customer_acceptance, } = PaymentAttemptUpdateInternal::from(self).populate_derived_fields(&source); PaymentAttempt { amount: amount.unwrap_or(source.amount), @@ -529,6 +535,7 @@ impl PaymentAttemptUpdate { charge_id: charge_id.or(source.charge_id), client_source: client_source.or(source.client_source), client_version: client_version.or(source.client_version), + customer_acceptance: customer_acceptance.or(source.customer_acceptance), ..source } } @@ -617,6 +624,7 @@ impl From for PaymentAttemptUpdateInternal { payment_method_id, client_source, client_version, + customer_acceptance, } => Self { amount: Some(amount), currency: Some(currency), @@ -648,6 +656,7 @@ impl From for PaymentAttemptUpdateInternal { capture_method, client_source, client_version, + customer_acceptance, ..Default::default() }, PaymentAttemptUpdate::VoidUpdate { diff --git a/crates/diesel_models/src/schema.rs b/crates/diesel_models/src/schema.rs index 8d51e378fd..053e436394 100644 --- a/crates/diesel_models/src/schema.rs +++ b/crates/diesel_models/src/schema.rs @@ -820,6 +820,7 @@ diesel::table! { client_source -> Nullable, #[max_length = 64] client_version -> Nullable, + customer_acceptance -> Nullable, } } diff --git a/crates/diesel_models/src/user/sample_data.rs b/crates/diesel_models/src/user/sample_data.rs index 1ffaa33a21..1d9cd87ad4 100644 --- a/crates/diesel_models/src/user/sample_data.rs +++ b/crates/diesel_models/src/user/sample_data.rs @@ -76,6 +76,7 @@ pub struct PaymentAttemptBatchNew { pub charge_id: Option, pub client_source: Option, pub client_version: Option, + pub customer_acceptance: Option, } #[allow(dead_code)] @@ -139,6 +140,7 @@ impl PaymentAttemptBatchNew { charge_id: self.charge_id, client_source: self.client_source, client_version: self.client_version, + customer_acceptance: self.customer_acceptance, } } } diff --git a/crates/hyperswitch_domain_models/src/mandates.rs b/crates/hyperswitch_domain_models/src/mandates.rs index 5bf9f0c951..c1380fe51c 100644 --- a/crates/hyperswitch_domain_models/src/mandates.rs +++ b/crates/hyperswitch_domain_models/src/mandates.rs @@ -43,7 +43,7 @@ pub struct MandateData { pub mandate_type: Option, } -#[derive(Default, Eq, PartialEq, Debug, Clone, serde::Deserialize)] +#[derive(Default, Eq, PartialEq, Debug, Clone, serde::Deserialize, serde::Serialize)] pub struct CustomerAcceptance { /// Type of acceptance provided by the pub acceptance_type: AcceptanceType, @@ -54,7 +54,7 @@ pub struct CustomerAcceptance { pub online: Option, } -#[derive(Default, Debug, PartialEq, Eq, Clone, serde::Deserialize)] +#[derive(Default, Debug, PartialEq, Eq, Clone, serde::Deserialize, serde::Serialize)] #[serde(rename_all = "lowercase")] pub enum AcceptanceType { Online, @@ -62,7 +62,7 @@ pub enum AcceptanceType { Offline, } -#[derive(Default, Eq, PartialEq, Debug, Clone, serde::Deserialize)] +#[derive(Default, Eq, PartialEq, Debug, Clone, serde::Deserialize, serde::Serialize)] pub struct OnlineMandate { /// Ip address of the customer machine from which the mandate was created #[serde(skip_deserializing)] diff --git a/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs b/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs index c7372fc86b..e7ccd6f33a 100644 --- a/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs +++ b/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs @@ -2,6 +2,7 @@ use api_models::enums::Connector; use common_enums as storage_enums; use common_utils::{ errors::{CustomResult, ValidationError}, + pii, types::MinorUnit, }; use error_stack::ResultExt; @@ -175,6 +176,7 @@ pub struct PaymentAttempt { pub charge_id: Option, pub client_source: Option, pub client_version: Option, + pub customer_acceptance: Option, } impl PaymentAttempt { @@ -264,6 +266,7 @@ pub struct PaymentAttemptNew { pub charge_id: Option, pub client_source: Option, pub client_version: Option, + pub customer_acceptance: Option, } impl PaymentAttemptNew { @@ -346,6 +349,7 @@ pub enum PaymentAttemptUpdate { payment_method_id: Option, client_source: Option, client_version: Option, + customer_acceptance: Option, }, RejectUpdate { status: storage_enums::AttemptStatus, diff --git a/crates/router/src/core/payments/helpers.rs b/crates/router/src/core/payments/helpers.rs index 4249955c24..da44703732 100644 --- a/crates/router/src/core/payments/helpers.rs +++ b/crates/router/src/core/payments/helpers.rs @@ -3712,6 +3712,7 @@ impl AttemptType { charge_id: None, client_source: old_payment_attempt.client_source, client_version: old_payment_attempt.client_version, + customer_acceptance: old_payment_attempt.customer_acceptance, } } diff --git a/crates/router/src/core/payments/operations/payment_confirm.rs b/crates/router/src/core/payments/operations/payment_confirm.rs index 3af3bc5219..2955b0c385 100644 --- a/crates/router/src/core/payments/operations/payment_confirm.rs +++ b/crates/router/src/core/payments/operations/payment_confirm.rs @@ -341,7 +341,17 @@ impl GetTracker, api::PaymentsRequest> for Pa .change_context(errors::ApiErrorResponse::InvalidDataValue { field_name: "browser_info", })?; - let customer_acceptance = request.customer_acceptance.clone().map(From::from); + let customer_acceptance = request.customer_acceptance.clone().or(payment_attempt + .customer_acceptance + .clone() + .map(|customer_acceptance| { + customer_acceptance + .expose() + .parse_value("CustomerAcceptance") + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Failed while deserializing customer_acceptance") + }) + .transpose()?); let recurring_details = request.recurring_details.clone(); @@ -360,6 +370,16 @@ impl GetTracker, api::PaymentsRequest> for Pa payment_attempt.capture_method = request.capture_method.or(payment_attempt.capture_method); + payment_attempt.customer_acceptance = request + .customer_acceptance + .clone() + .map(|customer_acceptance| customer_acceptance.encode_to_value()) + .transpose() + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Failed while encoding customer_acceptance to value")? + .map(masking::Secret::new) + .or(payment_attempt.customer_acceptance); + currency = payment_attempt.currency.get_required_value("currency")?; amount = payment_attempt.get_total_amount().into(); @@ -616,7 +636,7 @@ impl GetTracker, api::PaymentsRequest> for Pa mandate_id: None, mandate_connector, setup_mandate, - customer_acceptance, + customer_acceptance: customer_acceptance.map(From::from), token, address: PaymentAddress::new( shipping_address.as_ref().map(From::from), @@ -1211,6 +1231,7 @@ impl UpdateTracker, api::PaymentsRequest> for Paymen payment_method_id: m_payment_method_id, client_source, client_version, + customer_acceptance: payment_data.payment_attempt.customer_acceptance, }, storage_scheme, ) diff --git a/crates/router/src/core/payments/operations/payment_create.rs b/crates/router/src/core/payments/operations/payment_create.rs index b7076d0782..18dc2c5f39 100644 --- a/crates/router/src/core/payments/operations/payment_create.rs +++ b/crates/router/src/core/payments/operations/payment_create.rs @@ -281,6 +281,7 @@ impl GetTracker, api::PaymentsRequest> for Pa &payment_method_info, merchant_key_store, profile_id, + &customer_acceptance, ) .await?; @@ -796,6 +797,7 @@ impl PaymentCreate { payment_method_info: &Option, key_store: &domain::MerchantKeyStore, profile_id: String, + customer_acceptance: &Option, ) -> RouterResult<( storage::PaymentAttemptNew, Option, @@ -966,6 +968,13 @@ impl PaymentCreate { charge_id: None, client_source: None, client_version: None, + customer_acceptance: customer_acceptance + .clone() + .map(|customer_acceptance| customer_acceptance.encode_to_value()) + .transpose() + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Failed to serialize customer_acceptance")? + .map(Secret::new), }, additional_pm_data, )) diff --git a/crates/storage_impl/src/mock_db/payment_attempt.rs b/crates/storage_impl/src/mock_db/payment_attempt.rs index 547fc9f7d7..ee183968e2 100644 --- a/crates/storage_impl/src/mock_db/payment_attempt.rs +++ b/crates/storage_impl/src/mock_db/payment_attempt.rs @@ -157,6 +157,7 @@ impl PaymentAttemptInterface for MockDb { charge_id: payment_attempt.charge_id, client_source: payment_attempt.client_source, client_version: payment_attempt.client_version, + customer_acceptance: payment_attempt.customer_acceptance, }; payment_attempts.push(payment_attempt.clone()); Ok(payment_attempt) diff --git a/crates/storage_impl/src/payments/payment_attempt.rs b/crates/storage_impl/src/payments/payment_attempt.rs index f464ef66a1..7a56cae174 100644 --- a/crates/storage_impl/src/payments/payment_attempt.rs +++ b/crates/storage_impl/src/payments/payment_attempt.rs @@ -418,6 +418,7 @@ impl PaymentAttemptInterface for KVRouterStore { charge_id: payment_attempt.charge_id.clone(), client_source: payment_attempt.client_source.clone(), client_version: payment_attempt.client_version.clone(), + customer_acceptance: payment_attempt.customer_acceptance.clone(), }; let field = format!("pa_{}", created_attempt.attempt_id); @@ -1202,6 +1203,7 @@ impl DataModelExt for PaymentAttempt { charge_id: self.charge_id, client_source: self.client_source, client_version: self.client_version, + customer_acceptance: self.customer_acceptance, } } @@ -1268,6 +1270,7 @@ impl DataModelExt for PaymentAttempt { charge_id: storage_model.charge_id, client_source: storage_model.client_source, client_version: storage_model.client_version, + customer_acceptance: storage_model.customer_acceptance, } } } @@ -1339,6 +1342,7 @@ impl DataModelExt for PaymentAttemptNew { charge_id: self.charge_id, client_source: self.client_source, client_version: self.client_version, + customer_acceptance: self.customer_acceptance, } } @@ -1404,6 +1408,7 @@ impl DataModelExt for PaymentAttemptNew { charge_id: storage_model.charge_id, client_source: storage_model.client_source, client_version: storage_model.client_version, + customer_acceptance: storage_model.customer_acceptance, } } } @@ -1528,6 +1533,7 @@ impl DataModelExt for PaymentAttemptUpdate { payment_method_billing_address_id, client_source, client_version, + customer_acceptance, } => DieselPaymentAttemptUpdate::ConfirmUpdate { amount: amount.get_amount_as_i64(), currency, @@ -1560,6 +1566,7 @@ impl DataModelExt for PaymentAttemptUpdate { payment_method_billing_address_id, client_source, client_version, + customer_acceptance, }, Self::VoidUpdate { status, @@ -1863,6 +1870,7 @@ impl DataModelExt for PaymentAttemptUpdate { payment_method_billing_address_id, client_source, client_version, + customer_acceptance, } => Self::ConfirmUpdate { amount: MinorUnit::new(amount), currency, @@ -1893,6 +1901,7 @@ impl DataModelExt for PaymentAttemptUpdate { payment_method_billing_address_id, client_source, client_version, + customer_acceptance, }, DieselPaymentAttemptUpdate::VoidUpdate { status, diff --git a/migrations/2024-07-11-072518_add_customer_acceptance_in_payment_attempt/down.sql b/migrations/2024-07-11-072518_add_customer_acceptance_in_payment_attempt/down.sql new file mode 100644 index 0000000000..ef3393a5ed --- /dev/null +++ b/migrations/2024-07-11-072518_add_customer_acceptance_in_payment_attempt/down.sql @@ -0,0 +1 @@ +ALTER TABLE payment_attempt DROP COLUMN IF EXISTS customer_acceptance; \ No newline at end of file diff --git a/migrations/2024-07-11-072518_add_customer_acceptance_in_payment_attempt/up.sql b/migrations/2024-07-11-072518_add_customer_acceptance_in_payment_attempt/up.sql new file mode 100644 index 0000000000..54e5f4aed0 --- /dev/null +++ b/migrations/2024-07-11-072518_add_customer_acceptance_in_payment_attempt/up.sql @@ -0,0 +1,2 @@ +-- Your SQL goes here +ALTER TABLE payment_attempt ADD COLUMN IF NOT EXISTS customer_acceptance JSONB DEFAULT NULL;