diff --git a/connector-template/transformers.rs b/connector-template/transformers.rs index 40e3c2a366..fb08c1026f 100644 --- a/connector-template/transformers.rs +++ b/connector-template/transformers.rs @@ -128,7 +128,8 @@ impl TryFrom Option Self { + Self::Stripe(StripeChargeType::default()) + } +} + +#[derive( + Clone, + Debug, + Default, + Hash, + Eq, + PartialEq, + ToSchema, + serde::Serialize, + serde::Deserialize, + strum::Display, + strum::EnumString, +)] +#[serde(rename_all = "lowercase")] +#[strum(serialize_all = "lowercase")] +pub enum StripeChargeType { + #[default] + Direct, + Destination, +} + #[cfg(feature = "frm")] pub fn convert_frm_connector(connector_name: &str) -> Option { FrmConnectors::from_str(connector_name).ok() diff --git a/crates/api_models/src/payments.rs b/crates/api_models/src/payments.rs index 60952ee501..f0ce3839fc 100644 --- a/crates/api_models/src/payments.rs +++ b/crates/api_models/src/payments.rs @@ -474,6 +474,23 @@ pub struct PaymentsRequest { /// Details required for recurring payment pub recurring_details: Option, + + /// Fee information to be charged on the payment being collected + pub charges: Option, +} + +#[derive(Debug, serde::Deserialize, serde::Serialize, Clone, ToSchema)] +#[serde(rename_all = "snake_case")] +pub struct PaymentChargeRequest { + /// Stripe's charge type + #[schema(value_type = PaymentChargeType, example = "direct")] + pub charge_type: api_enums::PaymentChargeType, + + /// Platform fees to be collected on the payment + pub fees: i64, + + /// Identifier for the reseller's account to send the funds to + pub transfer_account_id: String, } impl PaymentsRequest { @@ -3426,11 +3443,30 @@ pub struct PaymentsResponse { #[serde(default, with = "common_utils::custom_serde::iso8601::option")] pub updated: Option, + /// Fee information to be charged on the payment being collected + pub charges: Option, + /// You can specify up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. FRM Metadata is useful for storing additional, structured information on an object related to FRM. #[schema(value_type = Option, example = r#"{ "fulfillment_method" : "deliver", "coverage_request" : "fraud" }"#)] pub frm_metadata: Option, } +#[derive(Setter, Clone, Default, Debug, PartialEq, serde::Serialize, ToSchema)] +pub struct PaymentChargeResponse { + /// Identifier for charge created for the payment + pub charge_id: Option, + + /// Type of charge (connector specific) + #[schema(value_type = PaymentChargeType, example = "direct")] + pub charge_type: api_enums::PaymentChargeType, + + /// Platform fees collected on the payment + pub application_fees: i64, + + /// Identifier for the reseller's account where the funds were transferred + pub transfer_account_id: String, +} + #[derive(Setter, Clone, Default, Debug, PartialEq, serde::Serialize, ToSchema)] pub struct ExternalAuthenticationDetailsResponse { /// Authentication Type - Challenge / Frictionless diff --git a/crates/api_models/src/refunds.rs b/crates/api_models/src/refunds.rs index 369aa0a660..881cc3912e 100644 --- a/crates/api_models/src/refunds.rs +++ b/crates/api_models/src/refunds.rs @@ -1,6 +1,7 @@ use std::collections::HashMap; use common_utils::pii; +pub use common_utils::types::ChargeRefunds; use serde::{Deserialize, Serialize}; use time::PrimitiveDateTime; use utoipa::ToSchema; @@ -53,6 +54,10 @@ pub struct RefundRequest { /// Merchant connector details used to make payments. #[schema(value_type = Option)] pub merchant_connector_details: Option, + + /// Charge specific fields for controlling the revert of funds from either platform or connected account + #[schema(value_type = Option)] + pub charges: Option, } #[derive(Default, Debug, Clone, Deserialize)] @@ -137,6 +142,9 @@ pub struct RefundResponse { pub profile_id: Option, /// The merchant_connector_id of the processor through which this payment went through pub merchant_connector_id: Option, + /// Charge specific fields for controlling the revert of funds from either platform or connected account + #[schema(value_type = Option)] + pub charges: Option, } #[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize, ToSchema)] @@ -168,7 +176,7 @@ pub struct RefundListRequest { pub refund_status: Option>, } -#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize, ToSchema)] +#[derive(Debug, Clone, Eq, PartialEq, Serialize, ToSchema)] pub struct RefundListResponse { /// The number of refunds included in the list pub count: usize, diff --git a/crates/common_utils/Cargo.toml b/crates/common_utils/Cargo.toml index e6fd27da31..ff64d6517c 100644 --- a/crates/common_utils/Cargo.toml +++ b/crates/common_utils/Cargo.toml @@ -39,8 +39,8 @@ thiserror = "1.0.58" time = { version = "0.3.35", features = ["serde", "serde-well-known", "std"] } tokio = { version = "1.37.0", features = ["macros", "rt-multi-thread"], optional = true } semver = { version = "1.0.22", features = ["serde"] } -uuid = { version = "1.8.0", features = ["v7"] } utoipa = { version = "4.2.0", features = ["preserve_order", "preserve_path_order"] } +uuid = { version = "1.8.0", features = ["v7"] } # First party crates common_enums = { version = "0.1.0", path = "../common_enums" } diff --git a/crates/common_utils/src/types.rs b/crates/common_utils/src/types.rs index 6574d1f1af..d9a7aef3f5 100644 --- a/crates/common_utils/src/types.rs +++ b/crates/common_utils/src/types.rs @@ -17,7 +17,7 @@ use diesel::{ }; use error_stack::{report, ResultExt}; use semver::Version; -use serde::{de::Visitor, Deserialize, Deserializer}; +use serde::{de::Visitor, Deserialize, Deserializer, Serialize}; use utoipa::ToSchema; use crate::{ @@ -25,7 +25,7 @@ use crate::{ errors::{CustomResult, ParsingError, PercentageError}, }; /// Represents Percentage Value between 0 and 100 both inclusive -#[derive(Clone, Default, Debug, PartialEq, serde::Serialize)] +#[derive(Clone, Default, Debug, PartialEq, Serialize)] pub struct Percentage { // this value will range from 0 to 100, decimal length defined by precision macro /// Percentage value ranging between 0 and 100 @@ -160,7 +160,7 @@ impl<'de, const PRECISION: u8> Deserialize<'de> for Percentage { } /// represents surcharge type and value -#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)] +#[derive(Clone, Debug, PartialEq, Serialize, serde::Deserialize)] #[serde(rename_all = "snake_case", tag = "type", content = "value")] pub enum Surcharge { /// Fixed Surcharge value @@ -172,7 +172,7 @@ pub enum Surcharge { /// This struct lets us represent a semantic version type #[derive(Debug, Clone, PartialEq, Eq, FromSqlRow, AsExpression, Ord, PartialOrd)] #[diesel(sql_type = Jsonb)] -#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Serialize, serde::Deserialize)] pub struct SemanticVersion(#[serde(with = "Version")] Version); impl SemanticVersion { @@ -226,6 +226,48 @@ where } } +#[derive( + Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq, FromSqlRow, AsExpression, ToSchema, +)] +#[diesel(sql_type = Jsonb)] +/// Charge object for refunds +pub struct ChargeRefunds { + /// Identifier for charge created for the payment + pub charge_id: String, + + /// Toggle for reverting the application fee that was collected for the payment. + /// If set to false, the funds are pulled from the destination account. + pub revert_platform_fee: Option, + + /// Toggle for reverting the transfer that was made during the charge. + /// If set to false, the funds are pulled from the main platform's account. + pub revert_transfer: Option, +} + +impl FromSql for ChargeRefunds +where + serde_json::Value: FromSql, +{ + fn from_sql(bytes: DB::RawValue<'_>) -> deserialize::Result { + let value = >::from_sql(bytes)?; + Ok(serde_json::from_value(value)?) + } +} + +impl ToSql for ChargeRefunds +where + serde_json::Value: ToSql, +{ + fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, diesel::pg::Pg>) -> diesel::serialize::Result { + let value = serde_json::to_value(self)?; + + // the function `reborrow` only works in case of `Pg` backend. But, in case of other backends + // please refer to the diesel migration blog: + // https://github.com/Diesel-rs/Diesel/blob/master/guide_drafts/migration_guide.md#changed-tosql-implementations + >::to_sql(&value, &mut out.reborrow()) + } +} + /// This Unit struct represents MinorUnit in which core amount works #[derive( Default, diff --git a/crates/diesel_models/src/payment_attempt.rs b/crates/diesel_models/src/payment_attempt.rs index ffa9aee115..6bb286b42a 100644 --- a/crates/diesel_models/src/payment_attempt.rs +++ b/crates/diesel_models/src/payment_attempt.rs @@ -70,6 +70,7 @@ pub struct PaymentAttempt { pub mandate_data: Option, pub fingerprint_id: Option, pub payment_method_billing_address_id: Option, + pub charge_id: Option, pub client_source: Option, pub client_version: Option, } @@ -152,6 +153,7 @@ pub struct PaymentAttemptNew { pub mandate_data: Option, pub fingerprint_id: Option, pub payment_method_billing_address_id: Option, + pub charge_id: Option, pub client_source: Option, pub client_version: Option, } @@ -281,6 +283,7 @@ pub enum PaymentAttemptUpdate { unified_code: Option>, unified_message: Option>, payment_method_data: Option, + charge_id: Option, }, UnresolvedResponseUpdate { status: storage_enums::AttemptStatus, @@ -334,6 +337,7 @@ pub enum PaymentAttemptUpdate { encoded_data: Option, connector_transaction_id: Option, connector: Option, + charge_id: Option, updated_by: String, }, IncrementalAuthorizationAmountUpdate { @@ -394,6 +398,7 @@ pub struct PaymentAttemptUpdateInternal { authentication_id: Option, fingerprint_id: Option, payment_method_billing_address_id: Option, + charge_id: Option, client_source: Option, client_version: Option, } @@ -461,6 +466,7 @@ impl PaymentAttemptUpdate { authentication_id, payment_method_billing_address_id, fingerprint_id, + charge_id, client_source, client_version, } = PaymentAttemptUpdateInternal::from(self).populate_derived_fields(&source); @@ -511,6 +517,7 @@ impl PaymentAttemptUpdate { payment_method_billing_address_id: payment_method_billing_address_id .or(source.payment_method_billing_address_id), fingerprint_id: fingerprint_id.or(source.fingerprint_id), + charge_id: charge_id.or(source.charge_id), client_source: client_source.or(source.client_source), client_version: client_version.or(source.client_version), ..source @@ -698,6 +705,7 @@ impl From for PaymentAttemptUpdateInternal { unified_code, unified_message, payment_method_data, + charge_id, } => Self { status: Some(status), connector: connector.map(Some), @@ -719,6 +727,7 @@ impl From for PaymentAttemptUpdateInternal { unified_code, unified_message, payment_method_data, + charge_id, ..Default::default() }, PaymentAttemptUpdate::ErrorUpdate { @@ -841,12 +850,14 @@ impl From for PaymentAttemptUpdateInternal { connector_transaction_id, connector, updated_by, + charge_id, } => Self { authentication_data, encoded_data, connector_transaction_id, connector: connector.map(Some), updated_by, + charge_id, ..Default::default() }, PaymentAttemptUpdate::IncrementalAuthorizationAmountUpdate { diff --git a/crates/diesel_models/src/payment_intent.rs b/crates/diesel_models/src/payment_intent.rs index 5b5eb0f79e..2c99255467 100644 --- a/crates/diesel_models/src/payment_intent.rs +++ b/crates/diesel_models/src/payment_intent.rs @@ -58,6 +58,7 @@ pub struct PaymentIntent { pub session_expiry: Option, pub fingerprint_id: Option, pub request_external_three_ds_authentication: Option, + pub charges: Option, pub frm_metadata: Option, } @@ -112,6 +113,7 @@ pub struct PaymentIntentNew { pub session_expiry: Option, pub fingerprint_id: Option, pub request_external_three_ds_authentication: Option, + pub charges: Option, pub frm_metadata: Option, } @@ -242,6 +244,7 @@ pub struct PaymentIntentUpdateInternal { pub session_expiry: Option, pub fingerprint_id: Option, pub request_external_three_ds_authentication: Option, + pub charges: Option, pub frm_metadata: Option, } @@ -278,6 +281,7 @@ impl PaymentIntentUpdate { session_expiry, fingerprint_id, request_external_three_ds_authentication, + charges, frm_metadata, } = self.into(); PaymentIntent { @@ -316,6 +320,7 @@ impl PaymentIntentUpdate { 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), + charges: charges.or(source.charges), frm_metadata: frm_metadata.or(source.frm_metadata), ..source diff --git a/crates/diesel_models/src/query/connector_response.rs b/crates/diesel_models/src/query/connector_response.rs index 952db945ae..bdc24139ab 100644 --- a/crates/diesel_models/src/query/connector_response.rs +++ b/crates/diesel_models/src/query/connector_response.rs @@ -22,6 +22,7 @@ impl ConnectorResponseNew { connector_transaction_id: self.connector_transaction_id.clone(), connector: self.connector_name.clone(), updated_by: self.updated_by.clone(), + charge_id: self.charge_id.clone(), }; let _payment_attempt: Result = @@ -63,12 +64,14 @@ impl ConnectorResponse { authentication_data, encoded_data, connector_name, + charge_id, updated_by, } => PaymentAttemptUpdate::ConnectorResponse { authentication_data, encoded_data, connector_transaction_id, connector: connector_name, + charge_id, updated_by, }, ConnectorResponseUpdate::ErrorUpdate { @@ -79,6 +82,7 @@ impl ConnectorResponse { encoded_data: None, connector_transaction_id: None, connector: connector_name, + charge_id: None, updated_by, }, }; diff --git a/crates/diesel_models/src/refund.rs b/crates/diesel_models/src/refund.rs index 0ee486bae4..aac282992a 100644 --- a/crates/diesel_models/src/refund.rs +++ b/crates/diesel_models/src/refund.rs @@ -1,4 +1,4 @@ -use common_utils::pii; +use common_utils::{pii, types::ChargeRefunds}; use diesel::{AsChangeset, Identifiable, Insertable, Queryable}; use serde::{Deserialize, Serialize}; use time::PrimitiveDateTime; @@ -39,6 +39,7 @@ pub struct Refund { pub profile_id: Option, pub updated_by: String, pub merchant_connector_id: Option, + pub charges: Option, } #[derive( @@ -81,6 +82,7 @@ pub struct RefundNew { pub profile_id: Option, pub updated_by: String, pub merchant_connector_id: Option, + pub charges: Option, } #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] @@ -275,7 +277,8 @@ mod tests { "refund_error_code": null, "profile_id": null, "updated_by": "admin", - "merchant_connector_id": null + "merchant_connector_id": null, + "charges": null }"#; let deserialized = serde_json::from_str::(serialized_refund); diff --git a/crates/diesel_models/src/schema.rs b/crates/diesel_models/src/schema.rs index ba540f7f0b..de5b536dcd 100644 --- a/crates/diesel_models/src/schema.rs +++ b/crates/diesel_models/src/schema.rs @@ -785,6 +785,8 @@ diesel::table! { #[max_length = 64] payment_method_billing_address_id -> Nullable, #[max_length = 64] + charge_id -> Nullable, + #[max_length = 64] client_source -> Nullable, #[max_length = 64] client_version -> Nullable, @@ -856,6 +858,7 @@ diesel::table! { #[max_length = 64] fingerprint_id -> Nullable, request_external_three_ds_authentication -> Nullable, + charges -> Nullable, frm_metadata -> Nullable, } } @@ -1094,6 +1097,7 @@ diesel::table! { updated_by -> Varchar, #[max_length = 32] merchant_connector_id -> Nullable, + charges -> Nullable, } } diff --git a/crates/diesel_models/src/user/sample_data.rs b/crates/diesel_models/src/user/sample_data.rs index 298d82cf31..1ffaa33a21 100644 --- a/crates/diesel_models/src/user/sample_data.rs +++ b/crates/diesel_models/src/user/sample_data.rs @@ -73,6 +73,7 @@ pub struct PaymentAttemptBatchNew { pub mandate_data: Option, pub payment_method_billing_address_id: Option, pub fingerprint_id: Option, + pub charge_id: Option, pub client_source: Option, pub client_version: Option, } @@ -135,6 +136,7 @@ impl PaymentAttemptBatchNew { mandate_data: self.mandate_data, payment_method_billing_address_id: self.payment_method_billing_address_id, fingerprint_id: self.fingerprint_id, + charge_id: self.charge_id, client_source: self.client_source, client_version: self.client_version, } diff --git a/crates/hyperswitch_domain_models/src/payments.rs b/crates/hyperswitch_domain_models/src/payments.rs index 0491081e87..b9adc162c4 100644 --- a/crates/hyperswitch_domain_models/src/payments.rs +++ b/crates/hyperswitch_domain_models/src/payments.rs @@ -60,5 +60,6 @@ pub struct PaymentIntent { #[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, } diff --git a/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs b/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs index ff4c7ac017..ac0c74ea91 100644 --- a/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs +++ b/crates/hyperswitch_domain_models/src/payments/payment_attempt.rs @@ -167,6 +167,7 @@ pub struct PaymentAttempt { pub mandate_data: Option, pub payment_method_billing_address_id: Option, pub fingerprint_id: Option, + pub charge_id: Option, pub client_source: Option, pub client_version: Option, } @@ -255,6 +256,7 @@ pub struct PaymentAttemptNew { pub mandate_data: Option, pub payment_method_billing_address_id: Option, pub fingerprint_id: Option, + pub charge_id: Option, pub client_source: Option, pub client_version: Option, } @@ -381,6 +383,7 @@ pub enum PaymentAttemptUpdate { unified_code: Option>, unified_message: Option>, payment_method_data: Option, + charge_id: Option, }, UnresolvedResponseUpdate { status: storage_enums::AttemptStatus, @@ -434,6 +437,7 @@ pub enum PaymentAttemptUpdate { encoded_data: Option, connector_transaction_id: Option, connector: Option, + charge_id: Option, updated_by: String, }, IncrementalAuthorizationAmountUpdate { diff --git a/crates/hyperswitch_domain_models/src/payments/payment_intent.rs b/crates/hyperswitch_domain_models/src/payments/payment_intent.rs index a3353e6dfa..5cf6f1219f 100644 --- a/crates/hyperswitch_domain_models/src/payments/payment_intent.rs +++ b/crates/hyperswitch_domain_models/src/payments/payment_intent.rs @@ -115,6 +115,7 @@ pub struct PaymentIntentNew { pub fingerprint_id: Option, pub session_expiry: Option, pub request_external_three_ds_authentication: Option, + pub charges: Option, } #[derive(Debug, Clone, Serialize, Deserialize)] diff --git a/crates/hyperswitch_domain_models/src/router_request_types.rs b/crates/hyperswitch_domain_models/src/router_request_types.rs index e95f6efd37..026a191977 100644 --- a/crates/hyperswitch_domain_models/src/router_request_types.rs +++ b/crates/hyperswitch_domain_models/src/router_request_types.rs @@ -315,6 +315,33 @@ pub struct RefundsData { /// Arbitrary metadata required for refund pub connector_metadata: Option, pub browser_info: Option, + /// Charges associated with the payment + pub charges: Option, +} + +#[derive(Debug, serde::Deserialize, Clone)] +pub struct ChargeRefunds { + pub charge_id: String, + pub transfer_account_id: String, + pub charge_type: api_models::enums::PaymentChargeType, + pub options: ChargeRefundsOptions, +} + +#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] +pub enum ChargeRefundsOptions { + Destination(DestinationChargeRefund), + Direct(DirectChargeRefund), +} + +#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] +pub struct DirectChargeRefund { + pub revert_platform_fee: bool, +} + +#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] +pub struct DestinationChargeRefund { + pub revert_platform_fee: bool, + pub revert_transfer: bool, } #[derive(Debug, Clone)] diff --git a/crates/openapi/src/openapi.rs b/crates/openapi/src/openapi.rs index b040cb0089..8830c68993 100644 --- a/crates/openapi/src/openapi.rs +++ b/crates/openapi/src/openapi.rs @@ -521,6 +521,11 @@ Never share your secret api keys. Keep them guarded and secure. api_models::webhook_events::OutgoingWebhookRequestContent, api_models::webhook_events::OutgoingWebhookResponseContent, api_models::enums::WebhookDeliveryAttempt, + api_models::enums::PaymentChargeType, + api_models::enums::StripeChargeType, + api_models::payments::PaymentChargeRequest, + api_models::payments::PaymentChargeResponse, + api_models::refunds::ChargeRefunds, )), modifiers(&SecurityAddon) )] diff --git a/crates/router/src/connector/aci/transformers.rs b/crates/router/src/connector/aci/transformers.rs index d818fb80db..8415453b6a 100644 --- a/crates/router/src/connector/aci/transformers.rs +++ b/crates/router/src/connector/aci/transformers.rs @@ -771,6 +771,7 @@ impl network_txn_id: None, connector_response_reference_id: Some(item.response.id), incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) diff --git a/crates/router/src/connector/adyen/transformers.rs b/crates/router/src/connector/adyen/transformers.rs index 6e86bfb305..1c24009c54 100644 --- a/crates/router/src/connector/adyen/transformers.rs +++ b/crates/router/src/connector/adyen/transformers.rs @@ -3185,6 +3185,7 @@ impl TryFrom> network_txn_id: None, connector_response_reference_id: Some(item.response.reference), incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) @@ -3219,6 +3220,7 @@ impl network_txn_id: None, connector_response_reference_id: None, incremental_authorization_allowed: None, + charge_id: None, }), payment_method_balance: Some(types::PaymentMethodBalance { amount: item.response.balance.value, @@ -3283,6 +3285,7 @@ pub fn get_adyen_response( network_txn_id, connector_response_reference_id: Some(response.merchant_reference), incremental_authorization_allowed: None, + charge_id: None, }; Ok((status, error, payments_response_data)) } @@ -3345,6 +3348,7 @@ pub fn get_webhook_response( network_txn_id: None, connector_response_reference_id: Some(response.merchant_reference_id), incremental_authorization_allowed: None, + charge_id: None, }; Ok((status, error, payments_response_data)) } @@ -3417,6 +3421,7 @@ pub fn get_redirection_response( .clone() .or(response.psp_reference), incremental_authorization_allowed: None, + charge_id: None, }; Ok((status, error, payments_response_data)) } @@ -3474,6 +3479,7 @@ pub fn get_present_to_shopper_response( .clone() .or(response.psp_reference), incremental_authorization_allowed: None, + charge_id: None, }; Ok((status, error, payments_response_data)) } @@ -3530,6 +3536,7 @@ pub fn get_qr_code_response( .clone() .or(response.psp_reference), incremental_authorization_allowed: None, + charge_id: None, }; Ok((status, error, payments_response_data)) } @@ -3566,6 +3573,7 @@ pub fn get_redirection_error_response( network_txn_id: None, connector_response_reference_id: None, incremental_authorization_allowed: None, + charge_id: None, }; Ok((status, error, payments_response_data)) @@ -3932,6 +3940,7 @@ impl TryFrom> network_txn_id: None, connector_response_reference_id: Some(item.response.reference), incremental_authorization_allowed: None, + charge_id: None, }), amount_captured: Some(0), ..item.data diff --git a/crates/router/src/connector/airwallex/transformers.rs b/crates/router/src/connector/airwallex/transformers.rs index fe0cd021eb..587a14caed 100644 --- a/crates/router/src/connector/airwallex/transformers.rs +++ b/crates/router/src/connector/airwallex/transformers.rs @@ -557,6 +557,7 @@ impl network_txn_id: None, connector_response_reference_id: None, incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) @@ -599,6 +600,7 @@ impl network_txn_id: None, connector_response_reference_id: None, incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) diff --git a/crates/router/src/connector/authorizedotnet/transformers.rs b/crates/router/src/connector/authorizedotnet/transformers.rs index 8069b925d4..3e4d0a382e 100644 --- a/crates/router/src/connector/authorizedotnet/transformers.rs +++ b/crates/router/src/connector/authorizedotnet/transformers.rs @@ -385,6 +385,7 @@ impl network_txn_id: None, connector_response_reference_id: None, incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }), @@ -922,6 +923,7 @@ impl transaction_response.transaction_id.clone(), ), incremental_authorization_allowed: None, + charge_id: None, }), }, ..item.data @@ -994,6 +996,7 @@ impl transaction_response.transaction_id.clone(), ), incremental_authorization_allowed: None, + charge_id: None, }), }, ..item.data @@ -1318,6 +1321,7 @@ impl network_txn_id: None, connector_response_reference_id: Some(transaction.transaction_id.clone()), incremental_authorization_allowed: None, + charge_id: None, }), status: payment_status, ..item.data diff --git a/crates/router/src/connector/bambora/transformers.rs b/crates/router/src/connector/bambora/transformers.rs index 5fd8c5658a..af4afeca10 100644 --- a/crates/router/src/connector/bambora/transformers.rs +++ b/crates/router/src/connector/bambora/transformers.rs @@ -447,6 +447,7 @@ impl network_txn_id: None, connector_response_reference_id: Some(pg_response.order_number.to_string()), incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }), @@ -473,6 +474,7 @@ impl item.data.connector_request_reference_id.to_string(), ), incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) @@ -522,6 +524,7 @@ impl network_txn_id: None, connector_response_reference_id: Some(item.response.order_number.to_string()), incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) @@ -574,6 +577,7 @@ impl network_txn_id: None, connector_response_reference_id: Some(item.response.order_number.to_string()), incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) @@ -615,6 +619,7 @@ impl network_txn_id: None, connector_response_reference_id: Some(item.response.order_number.to_string()), incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) @@ -656,6 +661,7 @@ impl network_txn_id: None, connector_response_reference_id: Some(item.response.order_number.to_string()), incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) diff --git a/crates/router/src/connector/bankofamerica/transformers.rs b/crates/router/src/connector/bankofamerica/transformers.rs index 4a5d99023c..90151f12ae 100644 --- a/crates/router/src/connector/bankofamerica/transformers.rs +++ b/crates/router/src/connector/bankofamerica/transformers.rs @@ -415,6 +415,7 @@ impl .unwrap_or(info_response.id), ), incremental_authorization_allowed: None, + charge_id: None, }), }, connector_response, @@ -1645,6 +1646,7 @@ fn get_payment_response( .unwrap_or(info_response.id.clone()), ), incremental_authorization_allowed: None, + charge_id: None, }) } } @@ -1697,6 +1699,7 @@ impl .unwrap_or(info_response.id.clone()), ), incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }), @@ -2052,6 +2055,7 @@ impl network_txn_id: None, connector_response_reference_id, incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) @@ -2452,6 +2456,7 @@ impl .map(|cref| cref.code) .unwrap_or(Some(app_response.id)), incremental_authorization_allowed: None, + charge_id: None, }), connector_response, ..item.data @@ -2470,6 +2475,7 @@ impl network_txn_id: None, connector_response_reference_id: Some(error_response.id), incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }), diff --git a/crates/router/src/connector/billwerk/transformers.rs b/crates/router/src/connector/billwerk/transformers.rs index 372a65af9f..811076a11d 100644 --- a/crates/router/src/connector/billwerk/transformers.rs +++ b/crates/router/src/connector/billwerk/transformers.rs @@ -276,6 +276,7 @@ impl network_txn_id: None, connector_response_reference_id: Some(item.response.handle), incremental_authorization_allowed: None, + charge_id: None, }; Ok(Self { status: enums::AttemptStatus::from(item.response.state), diff --git a/crates/router/src/connector/bitpay/transformers.rs b/crates/router/src/connector/bitpay/transformers.rs index a70c4ba3ac..8a54c79b18 100644 --- a/crates/router/src/connector/bitpay/transformers.rs +++ b/crates/router/src/connector/bitpay/transformers.rs @@ -172,6 +172,7 @@ impl .order_id .or(Some(item.response.data.id)), incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) diff --git a/crates/router/src/connector/bluesnap.rs b/crates/router/src/connector/bluesnap.rs index dff76576ac..f2a903c91f 100644 --- a/crates/router/src/connector/bluesnap.rs +++ b/crates/router/src/connector/bluesnap.rs @@ -728,6 +728,7 @@ impl ConnectorIntegration network_txn_id: None, connector_response_reference_id: Some(item.response.transaction_id), incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) diff --git a/crates/router/src/connector/boku/transformers.rs b/crates/router/src/connector/boku/transformers.rs index c22b656773..2ff3e24765 100644 --- a/crates/router/src/connector/boku/transformers.rs +++ b/crates/router/src/connector/boku/transformers.rs @@ -274,6 +274,7 @@ impl TryFrom network_txn_id: None, connector_response_reference_id: None, incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) @@ -263,6 +264,7 @@ impl network_txn_id: None, connector_response_reference_id: None, incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }), @@ -427,6 +429,7 @@ impl network_txn_id: None, connector_response_reference_id: None, incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) @@ -445,6 +448,7 @@ impl network_txn_id: None, connector_response_reference_id: None, incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }), @@ -489,6 +493,7 @@ impl network_txn_id: None, connector_response_reference_id: None, incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) @@ -534,6 +539,7 @@ impl network_txn_id: None, connector_response_reference_id: None, incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) @@ -1062,6 +1068,7 @@ impl TryFrom> network_txn_id: None, connector_response_reference_id: None, incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) @@ -1160,6 +1167,7 @@ impl network_txn_id: None, connector_response_reference_id: None, incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) @@ -1258,6 +1266,7 @@ impl network_txn_id: None, connector_response_reference_id: None, incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) diff --git a/crates/router/src/connector/braintree/transformers.rs b/crates/router/src/connector/braintree/transformers.rs index e278ff40b4..a939f0a83f 100644 --- a/crates/router/src/connector/braintree/transformers.rs +++ b/crates/router/src/connector/braintree/transformers.rs @@ -282,6 +282,7 @@ impl network_txn_id: None, connector_response_reference_id: Some(id), incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) diff --git a/crates/router/src/connector/cashtocode/transformers.rs b/crates/router/src/connector/cashtocode/transformers.rs index f8c275df33..ba55fca9b8 100644 --- a/crates/router/src/connector/cashtocode/transformers.rs +++ b/crates/router/src/connector/cashtocode/transformers.rs @@ -268,6 +268,7 @@ impl network_txn_id: None, connector_response_reference_id: None, incremental_authorization_allowed: None, + charge_id: None, }), ) } @@ -312,6 +313,7 @@ impl network_txn_id: None, connector_response_reference_id: None, incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) diff --git a/crates/router/src/connector/checkout/transformers.rs b/crates/router/src/connector/checkout/transformers.rs index ddf65d23aa..c92d75f1de 100644 --- a/crates/router/src/connector/checkout/transformers.rs +++ b/crates/router/src/connector/checkout/transformers.rs @@ -681,6 +681,7 @@ impl TryFrom> item.response.reference.unwrap_or(item.response.id), ), incremental_authorization_allowed: None, + charge_id: None, }; Ok(Self { status, @@ -733,6 +734,7 @@ impl TryFrom> item.response.reference.unwrap_or(item.response.id), ), incremental_authorization_allowed: None, + charge_id: None, }; Ok(Self { status, @@ -808,6 +810,7 @@ impl TryFrom> network_txn_id: None, connector_response_reference_id: None, incremental_authorization_allowed: None, + charge_id: None, }), status: response.into(), ..item.data @@ -908,6 +911,7 @@ impl TryFrom> network_txn_id: None, connector_response_reference_id: item.response.reference, incremental_authorization_allowed: None, + charge_id: None, }), status, amount_captured, diff --git a/crates/router/src/connector/coinbase/transformers.rs b/crates/router/src/connector/coinbase/transformers.rs index f02984136b..82a6add72e 100644 --- a/crates/router/src/connector/coinbase/transformers.rs +++ b/crates/router/src/connector/coinbase/transformers.rs @@ -149,6 +149,7 @@ impl network_txn_id: None, connector_response_reference_id: Some(item.response.data.id.clone()), incremental_authorization_allowed: None, + charge_id: None, }), |context| { Ok(types::PaymentsResponseData::TransactionUnresolvedResponse{ diff --git a/crates/router/src/connector/cryptopay/transformers.rs b/crates/router/src/connector/cryptopay/transformers.rs index d9d164ac20..1a1f23b93b 100644 --- a/crates/router/src/connector/cryptopay/transformers.rs +++ b/crates/router/src/connector/cryptopay/transformers.rs @@ -190,6 +190,7 @@ impl .custom_id .or(Some(item.response.data.id)), incremental_authorization_allowed: None, + charge_id: None, }) }; diff --git a/crates/router/src/connector/cybersource/transformers.rs b/crates/router/src/connector/cybersource/transformers.rs index a9b1c37ae9..f1774a0de3 100644 --- a/crates/router/src/connector/cybersource/transformers.rs +++ b/crates/router/src/connector/cybersource/transformers.rs @@ -1778,6 +1778,7 @@ fn get_payment_response( .unwrap_or(info_response.id.clone()), ), incremental_authorization_allowed, + charge_id: None, }) } } @@ -1878,6 +1879,7 @@ impl .unwrap_or(info_response.id.clone()), ), incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }), @@ -2246,6 +2248,7 @@ impl network_txn_id: None, connector_response_reference_id, incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) @@ -2486,6 +2489,7 @@ impl incremental_authorization_allowed: Some( mandate_status == enums::AttemptStatus::Authorized, ), + charge_id: None, }), }, connector_response, @@ -2645,6 +2649,7 @@ impl .map(|cref| cref.code) .unwrap_or(Some(app_response.id)), incremental_authorization_allowed, + charge_id: None, }), ..item.data }) @@ -2662,6 +2667,7 @@ impl network_txn_id: None, connector_response_reference_id: Some(error_response.id), incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }), diff --git a/crates/router/src/connector/dlocal/transformers.rs b/crates/router/src/connector/dlocal/transformers.rs index c073dc03cc..b736c6a6c5 100644 --- a/crates/router/src/connector/dlocal/transformers.rs +++ b/crates/router/src/connector/dlocal/transformers.rs @@ -330,6 +330,7 @@ impl network_txn_id: None, connector_response_reference_id: item.response.order_id.clone(), incremental_authorization_allowed: None, + charge_id: None, }; Ok(Self { status: enums::AttemptStatus::from(item.response.status), @@ -370,6 +371,7 @@ impl network_txn_id: None, connector_response_reference_id: item.response.order_id.clone(), incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) @@ -407,6 +409,7 @@ impl network_txn_id: None, connector_response_reference_id: item.response.order_id.clone(), incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) @@ -444,6 +447,7 @@ impl network_txn_id: None, connector_response_reference_id: Some(item.response.order_id.clone()), incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) diff --git a/crates/router/src/connector/dummyconnector/transformers.rs b/crates/router/src/connector/dummyconnector/transformers.rs index 52c9522842..2cf5960bf7 100644 --- a/crates/router/src/connector/dummyconnector/transformers.rs +++ b/crates/router/src/connector/dummyconnector/transformers.rs @@ -259,6 +259,7 @@ impl TryFrom gateway_resp.transaction_processing_details.order_id, ), incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) @@ -412,6 +413,7 @@ impl TryFrom network_txn_id: None, connector_response_reference_id: Some(transaction_id.to_string()), incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) @@ -326,6 +327,7 @@ impl network_txn_id: None, connector_response_reference_id: Some(transaction_id.to_string()), incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) @@ -394,6 +396,7 @@ impl TryFrom> network_txn_id: None, connector_response_reference_id: Some(item.response.transaction_id.to_string()), incremental_authorization_allowed: None, + charge_id: None, }), amount_captured: None, ..item.data @@ -462,6 +465,7 @@ impl network_txn_id: None, connector_response_reference_id: Some(transaction_id.to_string()), incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) diff --git a/crates/router/src/connector/globalpay/transformers.rs b/crates/router/src/connector/globalpay/transformers.rs index 6653205c06..3bdc3360a7 100644 --- a/crates/router/src/connector/globalpay/transformers.rs +++ b/crates/router/src/connector/globalpay/transformers.rs @@ -235,6 +235,7 @@ fn get_payment_response( network_txn_id: None, connector_response_reference_id: response.reference, incremental_authorization_allowed: None, + charge_id: None, }), } } diff --git a/crates/router/src/connector/globepay/transformers.rs b/crates/router/src/connector/globepay/transformers.rs index efe9645493..dc0f970481 100644 --- a/crates/router/src/connector/globepay/transformers.rs +++ b/crates/router/src/connector/globepay/transformers.rs @@ -194,6 +194,7 @@ impl network_txn_id: None, connector_response_reference_id: None, incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) @@ -268,6 +269,7 @@ impl network_txn_id: None, connector_response_reference_id: None, incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) diff --git a/crates/router/src/connector/gocardless/transformers.rs b/crates/router/src/connector/gocardless/transformers.rs index b94dd73dd2..ee1ff91cd4 100644 --- a/crates/router/src/connector/gocardless/transformers.rs +++ b/crates/router/src/connector/gocardless/transformers.rs @@ -512,6 +512,7 @@ impl redirection_data: None, mandate_reference, network_txn_id: None, + charge_id: None, }), status: enums::AttemptStatus::Charged, ..item.data @@ -664,6 +665,7 @@ impl network_txn_id: None, connector_response_reference_id: None, incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) @@ -699,6 +701,7 @@ impl network_txn_id: None, connector_response_reference_id: None, incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) diff --git a/crates/router/src/connector/helcim/transformers.rs b/crates/router/src/connector/helcim/transformers.rs index 655d8a8663..a3341ddab4 100644 --- a/crates/router/src/connector/helcim/transformers.rs +++ b/crates/router/src/connector/helcim/transformers.rs @@ -369,6 +369,7 @@ impl network_txn_id: None, connector_response_reference_id: item.response.invoice_number.clone(), incremental_authorization_allowed: None, + charge_id: None, }), status: enums::AttemptStatus::from(item.response), ..item.data @@ -424,6 +425,7 @@ impl network_txn_id: None, connector_response_reference_id: item.response.invoice_number.clone(), incremental_authorization_allowed: None, + charge_id: None, }), status: enums::AttemptStatus::from(item.response), ..item.data @@ -483,6 +485,7 @@ impl network_txn_id: None, connector_response_reference_id: item.response.invoice_number.clone(), incremental_authorization_allowed: None, + charge_id: None, }), status: enums::AttemptStatus::from(item.response), ..item.data @@ -569,6 +572,7 @@ impl network_txn_id: None, connector_response_reference_id: item.response.invoice_number.clone(), incremental_authorization_allowed: None, + charge_id: None, }), status: enums::AttemptStatus::from(item.response), ..item.data @@ -631,6 +635,7 @@ impl network_txn_id: None, connector_response_reference_id: item.response.invoice_number.clone(), incremental_authorization_allowed: None, + charge_id: None, }), status: enums::AttemptStatus::from(item.response), ..item.data diff --git a/crates/router/src/connector/iatapay/transformers.rs b/crates/router/src/connector/iatapay/transformers.rs index 3e337d3a74..5daa33ab94 100644 --- a/crates/router/src/connector/iatapay/transformers.rs +++ b/crates/router/src/connector/iatapay/transformers.rs @@ -300,6 +300,7 @@ fn get_iatpay_response( network_txn_id: None, connector_response_reference_id: connector_response_reference_id.clone(), incremental_authorization_allowed: None, + charge_id: None, }, |checkout_methods| types::PaymentsResponseData::TransactionResponse { resource_id: id, @@ -313,6 +314,7 @@ fn get_iatpay_response( network_txn_id: None, connector_response_reference_id: connector_response_reference_id.clone(), incremental_authorization_allowed: None, + charge_id: None, }, ); Ok((status, error, payment_response_data)) diff --git a/crates/router/src/connector/klarna/transformers.rs b/crates/router/src/connector/klarna/transformers.rs index db77b9c30c..15fed065f0 100644 --- a/crates/router/src/connector/klarna/transformers.rs +++ b/crates/router/src/connector/klarna/transformers.rs @@ -161,6 +161,7 @@ impl TryFrom> network_txn_id: None, connector_response_reference_id: Some(item.response.order_id.clone()), incremental_authorization_allowed: None, + charge_id: None, }), status: item.response.fraud_status.into(), ..item.data diff --git a/crates/router/src/connector/mifinity/transformers.rs b/crates/router/src/connector/mifinity/transformers.rs index 486d91cd57..b37602e8d7 100644 --- a/crates/router/src/connector/mifinity/transformers.rs +++ b/crates/router/src/connector/mifinity/transformers.rs @@ -134,6 +134,7 @@ impl network_txn_id: None, connector_response_reference_id: None, incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) diff --git a/crates/router/src/connector/mollie/transformers.rs b/crates/router/src/connector/mollie/transformers.rs index a9fe46cb59..9320aee8d7 100644 --- a/crates/router/src/connector/mollie/transformers.rs +++ b/crates/router/src/connector/mollie/transformers.rs @@ -540,6 +540,7 @@ impl network_txn_id: None, connector_response_reference_id: Some(item.response.id), incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) diff --git a/crates/router/src/connector/multisafepay/transformers.rs b/crates/router/src/connector/multisafepay/transformers.rs index 400e5ecd11..8f2cf5f833 100644 --- a/crates/router/src/connector/multisafepay/transformers.rs +++ b/crates/router/src/connector/multisafepay/transformers.rs @@ -699,6 +699,7 @@ impl payment_response.data.order_id.clone(), ), incremental_authorization_allowed: None, + charge_id: None, }) }, ..item.data diff --git a/crates/router/src/connector/nexinets/transformers.rs b/crates/router/src/connector/nexinets/transformers.rs index c6ef4ea1ba..e8c606d7c5 100644 --- a/crates/router/src/connector/nexinets/transformers.rs +++ b/crates/router/src/connector/nexinets/transformers.rs @@ -372,6 +372,7 @@ impl network_txn_id: None, connector_response_reference_id: Some(item.response.order_id), incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) @@ -455,6 +456,7 @@ impl network_txn_id: None, connector_response_reference_id: Some(item.response.order.order_id), incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) diff --git a/crates/router/src/connector/nmi/transformers.rs b/crates/router/src/connector/nmi/transformers.rs index fdc65963fe..2a8498bfba 100644 --- a/crates/router/src/connector/nmi/transformers.rs +++ b/crates/router/src/connector/nmi/transformers.rs @@ -225,6 +225,7 @@ impl network_txn_id: None, connector_response_reference_id: Some(item.response.transactionid), incremental_authorization_allowed: None, + charge_id: None, }), enums::AttemptStatus::AuthenticationPending, ), @@ -378,6 +379,7 @@ impl network_txn_id: None, connector_response_reference_id: Some(item.response.orderid), incremental_authorization_allowed: None, + charge_id: None, }), if let Some(diesel_models::enums::CaptureMethod::Automatic) = item.data.request.capture_method @@ -754,6 +756,7 @@ impl network_txn_id: None, connector_response_reference_id: Some(item.response.orderid), incremental_authorization_allowed: None, + charge_id: None, }), enums::AttemptStatus::CaptureInitiated, ), @@ -848,6 +851,7 @@ impl network_txn_id: None, connector_response_reference_id: Some(item.response.orderid), incremental_authorization_allowed: None, + charge_id: None, }), enums::AttemptStatus::Charged, ), @@ -904,6 +908,7 @@ impl TryFrom> network_txn_id: None, connector_response_reference_id: Some(item.response.orderid), incremental_authorization_allowed: None, + charge_id: None, }), if let Some(diesel_models::enums::CaptureMethod::Automatic) = item.data.request.capture_method @@ -954,6 +959,7 @@ impl network_txn_id: None, connector_response_reference_id: Some(item.response.orderid), incremental_authorization_allowed: None, + charge_id: None, }), enums::AttemptStatus::VoidInitiated, ), @@ -1004,6 +1010,7 @@ impl TryFrom network_txn_id: None, connector_response_reference_id, incremental_authorization_allowed: None, + charge_id: None, }) } }, diff --git a/crates/router/src/connector/nuvei/transformers.rs b/crates/router/src/connector/nuvei/transformers.rs index e0d7a58566..ace33e3e30 100644 --- a/crates/router/src/connector/nuvei/transformers.rs +++ b/crates/router/src/connector/nuvei/transformers.rs @@ -1472,6 +1472,7 @@ where network_txn_id: None, connector_response_reference_id: response.order_id, incremental_authorization_allowed: None, + charge_id: None, }) }, ..item.data diff --git a/crates/router/src/connector/opayo/transformers.rs b/crates/router/src/connector/opayo/transformers.rs index e00f9a331a..327ec5def0 100644 --- a/crates/router/src/connector/opayo/transformers.rs +++ b/crates/router/src/connector/opayo/transformers.rs @@ -128,6 +128,7 @@ impl network_txn_id: None, connector_response_reference_id: Some(item.response.transaction_id), incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) diff --git a/crates/router/src/connector/opennode/transformers.rs b/crates/router/src/connector/opennode/transformers.rs index 09da5fc8f9..8f1579ac1f 100644 --- a/crates/router/src/connector/opennode/transformers.rs +++ b/crates/router/src/connector/opennode/transformers.rs @@ -144,6 +144,7 @@ impl network_txn_id: None, connector_response_reference_id: item.response.data.order_id, incremental_authorization_allowed: None, + charge_id: None, }) } else { Ok(types::PaymentsResponseData::TransactionUnresolvedResponse { diff --git a/crates/router/src/connector/payeezy/transformers.rs b/crates/router/src/connector/payeezy/transformers.rs index a8442f7ea8..9b6da9a0e9 100644 --- a/crates/router/src/connector/payeezy/transformers.rs +++ b/crates/router/src/connector/payeezy/transformers.rs @@ -433,6 +433,7 @@ impl .unwrap_or(item.response.transaction_id), ), incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) diff --git a/crates/router/src/connector/payme/transformers.rs b/crates/router/src/connector/payme/transformers.rs index bf20eb1a0b..634c0a17c7 100644 --- a/crates/router/src/connector/payme/transformers.rs +++ b/crates/router/src/connector/payme/transformers.rs @@ -251,6 +251,7 @@ impl TryFrom<&PaymePaySaleResponse> for types::PaymentsResponseData { network_txn_id: None, connector_response_reference_id: None, incremental_authorization_allowed: None, + charge_id: None, }) } } @@ -317,6 +318,7 @@ impl From<&SaleQuery> for types::PaymentsResponseData { network_txn_id: None, connector_response_reference_id: None, incremental_authorization_allowed: None, + charge_id: None, } } } @@ -525,6 +527,7 @@ impl network_txn_id: None, connector_response_reference_id: None, incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }), @@ -1080,6 +1083,7 @@ impl TryFrom> network_txn_id: None, connector_response_reference_id: None, incremental_authorization_allowed: None, + charge_id: None, }) }; Ok(Self { diff --git a/crates/router/src/connector/payone/transformers.rs b/crates/router/src/connector/payone/transformers.rs index e9eb3b9ddd..ebe34111ab 100644 --- a/crates/router/src/connector/payone/transformers.rs +++ b/crates/router/src/connector/payone/transformers.rs @@ -129,6 +129,7 @@ impl network_txn_id: None, connector_response_reference_id: None, incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) diff --git a/crates/router/src/connector/paypal.rs b/crates/router/src/connector/paypal.rs index f82317b5af..9ff6b84a06 100644 --- a/crates/router/src/connector/paypal.rs +++ b/crates/router/src/connector/paypal.rs @@ -787,7 +787,8 @@ impl network_txn_id: None, connector_response_reference_id: None, incremental_authorization_allowed: None, - }), + charge_id: None, + }), ..data.clone() }) } @@ -837,6 +838,7 @@ impl network_txn_id: None, connector_response_reference_id: None, incremental_authorization_allowed: None, + charge_id: None, }), ..data.clone() }) diff --git a/crates/router/src/connector/paypal/transformers.rs b/crates/router/src/connector/paypal/transformers.rs index 171d07f651..0ea1331c44 100644 --- a/crates/router/src/connector/paypal/transformers.rs +++ b/crates/router/src/connector/paypal/transformers.rs @@ -1163,6 +1163,7 @@ impl .clone() .or(Some(item.response.id)), incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) @@ -1268,6 +1269,7 @@ impl purchase_units.map_or(item.response.id, |item| item.invoice_id.clone()), ), incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) @@ -1305,6 +1307,7 @@ impl network_txn_id: None, connector_response_reference_id: None, incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) @@ -1355,6 +1358,7 @@ impl network_txn_id: None, connector_response_reference_id: None, incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) @@ -1423,6 +1427,7 @@ impl .clone() .or(Some(item.response.supplementary_data.related_ids.order_id)), incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) @@ -1758,6 +1763,7 @@ impl TryFrom> .invoice_id .or(Some(item.response.id)), incremental_authorization_allowed: None, + charge_id: None, }), amount_captured: Some(amount_captured), ..item.data @@ -1809,6 +1815,7 @@ impl .invoice_id .or(Some(item.response.id)), incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) diff --git a/crates/router/src/connector/payu/transformers.rs b/crates/router/src/connector/payu/transformers.rs index 575f199b73..5365fc74ef 100644 --- a/crates/router/src/connector/payu/transformers.rs +++ b/crates/router/src/connector/payu/transformers.rs @@ -211,6 +211,7 @@ impl .ext_order_id .or(Some(item.response.order_id)), incremental_authorization_allowed: None, + charge_id: None, }), amount_captured: None, ..item.data @@ -264,6 +265,7 @@ impl network_txn_id: None, connector_response_reference_id: None, incremental_authorization_allowed: None, + charge_id: None, }), amount_captured: None, ..item.data @@ -350,6 +352,7 @@ impl .ext_order_id .or(Some(item.response.order_id)), incremental_authorization_allowed: None, + charge_id: None, }), amount_captured: None, ..item.data @@ -484,6 +487,7 @@ impl .clone() .or(Some(order.order_id.clone())), incremental_authorization_allowed: None, + charge_id: None, }), amount_captured: Some( order diff --git a/crates/router/src/connector/placetopay/transformers.rs b/crates/router/src/connector/placetopay/transformers.rs index e400dc9b39..ef6bde8f1a 100644 --- a/crates/router/src/connector/placetopay/transformers.rs +++ b/crates/router/src/connector/placetopay/transformers.rs @@ -279,6 +279,7 @@ impl network_txn_id: None, connector_response_reference_id: None, incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) diff --git a/crates/router/src/connector/powertranz/transformers.rs b/crates/router/src/connector/powertranz/transformers.rs index 6b0675b161..e47e0f5120 100644 --- a/crates/router/src/connector/powertranz/transformers.rs +++ b/crates/router/src/connector/powertranz/transformers.rs @@ -337,6 +337,7 @@ impl network_txn_id: None, connector_response_reference_id: Some(item.response.order_identifier), incremental_authorization_allowed: None, + charge_id: None, }), Err, ); diff --git a/crates/router/src/connector/prophetpay/transformers.rs b/crates/router/src/connector/prophetpay/transformers.rs index 7a8cd6e14d..6862c7c4c8 100644 --- a/crates/router/src/connector/prophetpay/transformers.rs +++ b/crates/router/src/connector/prophetpay/transformers.rs @@ -207,6 +207,7 @@ impl network_txn_id: None, connector_response_reference_id: None, incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) @@ -406,6 +407,7 @@ impl network_txn_id: None, connector_response_reference_id: None, incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) @@ -456,6 +458,7 @@ impl network_txn_id: None, connector_response_reference_id: None, incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) @@ -506,6 +509,7 @@ impl network_txn_id: None, connector_response_reference_id: None, incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) diff --git a/crates/router/src/connector/rapyd/transformers.rs b/crates/router/src/connector/rapyd/transformers.rs index d949a30a01..128fca65a9 100644 --- a/crates/router/src/connector/rapyd/transformers.rs +++ b/crates/router/src/connector/rapyd/transformers.rs @@ -480,6 +480,7 @@ impl network_txn_id: None, connector_response_reference_id: None, incremental_authorization_allowed: None, + charge_id: None, }), ) } diff --git a/crates/router/src/connector/shift4/transformers.rs b/crates/router/src/connector/shift4/transformers.rs index 30f327c700..7a8bc2587f 100644 --- a/crates/router/src/connector/shift4/transformers.rs +++ b/crates/router/src/connector/shift4/transformers.rs @@ -677,6 +677,7 @@ impl network_txn_id: None, connector_response_reference_id: None, incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) @@ -719,6 +720,7 @@ impl network_txn_id: None, connector_response_reference_id: Some(item.response.id), incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) diff --git a/crates/router/src/connector/square/transformers.rs b/crates/router/src/connector/square/transformers.rs index 0de122d5da..184b182436 100644 --- a/crates/router/src/connector/square/transformers.rs +++ b/crates/router/src/connector/square/transformers.rs @@ -381,6 +381,7 @@ impl network_txn_id: None, connector_response_reference_id: item.response.payment.reference_id, incremental_authorization_allowed: None, + charge_id: None, }), amount_captured, ..item.data diff --git a/crates/router/src/connector/stax/transformers.rs b/crates/router/src/connector/stax/transformers.rs index 6477b2325e..d307265402 100644 --- a/crates/router/src/connector/stax/transformers.rs +++ b/crates/router/src/connector/stax/transformers.rs @@ -360,6 +360,7 @@ impl item.response.idempotency_id.unwrap_or(item.response.id), ), incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) diff --git a/crates/router/src/connector/stripe.rs b/crates/router/src/connector/stripe.rs index b41c331b74..febb039768 100644 --- a/crates/router/src/connector/stripe.rs +++ b/crates/router/src/connector/stripe.rs @@ -877,6 +877,21 @@ impl )]; let mut api_key = self.get_auth_header(&req.connector_auth_type)?; header.append(&mut api_key); + + req.request + .charges + .as_ref() + .map(|charge| match &charge.charge_type { + api::enums::PaymentChargeType::Stripe(stripe_charge) => { + if stripe_charge == &api::enums::StripeChargeType::Direct { + let mut customer_account_header = vec![( + headers::STRIPE_COMPATIBLE_CONNECT_ACCOUNT.to_string(), + charge.transfer_account_id.clone().into_masked(), + )]; + header.append(&mut customer_account_header); + } + } + }); Ok(header) } @@ -1355,6 +1370,21 @@ impl services::ConnectorIntegration { + if stripe_charge == &api::enums::StripeChargeType::Direct { + let mut customer_account_header = vec![( + headers::STRIPE_COMPATIBLE_CONNECT_ACCOUNT.to_string(), + charge.transfer_account_id.clone().into_masked(), + )]; + header.append(&mut customer_account_header); + } + } + }); Ok(header) } @@ -1375,8 +1405,13 @@ impl services::ConnectorIntegration, _connectors: &settings::Connectors, ) -> CustomResult { - let connector_req = stripe::RefundRequest::try_from(req)?; - Ok(RequestContent::FormUrlEncoded(Box::new(connector_req))) + let request_body = match req.request.charges.as_ref() { + None => RequestContent::FormUrlEncoded(Box::new(stripe::RefundRequest::try_from(req)?)), + Some(_) => RequestContent::FormUrlEncoded(Box::new( + stripe::ChargeRefundRequest::try_from(req)?, + )), + }; + Ok(request_body) } fn build_request( diff --git a/crates/router/src/connector/stripe/transformers.rs b/crates/router/src/connector/stripe/transformers.rs index da524bea4c..55b0d7f467 100644 --- a/crates/router/src/connector/stripe/transformers.rs +++ b/crates/router/src/connector/stripe/transformers.rs @@ -157,6 +157,18 @@ pub struct PaymentIntentRequest { pub expand: Option, #[serde(flatten)] pub browser_info: Option, + #[serde(flatten)] + pub charges: Option, +} + +#[derive(Debug, Eq, PartialEq, Serialize)] +pub struct IntentCharges { + pub application_fee_amount: i64, + #[serde( + rename = "transfer_data[destination]", + skip_serializing_if = "Option::is_none" + )] + pub destination_account_id: Option, } // Field rename is required only in case of serialization as it is passed in the request to the connector. @@ -1826,6 +1838,25 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for PaymentIntentRequest { None }; + let (charges, customer) = match &item.request.charges { + Some(charges) => { + let charges = match &charges.charge_type { + api_enums::PaymentChargeType::Stripe(charge_type) => match charge_type { + api_enums::StripeChargeType::Direct => Some(IntentCharges { + application_fee_amount: charges.fees, + destination_account_id: None, + }), + api_enums::StripeChargeType::Destination => Some(IntentCharges { + application_fee_amount: charges.fees, + destination_account_id: Some(charges.transfer_account_id.clone()), + }), + }, + }; + (charges, None) + } + None => (None, item.connector_customer.to_owned().map(Secret::new)), + }; + Ok(Self { amount: item.request.amount, //hopefully we don't loose some cents here currency: item.request.currency.to_string(), //we need to copy the value and not transfer ownership @@ -1845,13 +1876,14 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for PaymentIntentRequest { payment_data, payment_method_options, payment_method, - customer: item.connector_customer.to_owned().map(Secret::new), + customer, setup_mandate_details, off_session: item.request.off_session, setup_future_usage: item.request.setup_future_usage, payment_method_types, expand: Some(ExpandableObjects::LatestCharge), browser_info, + charges, }) } } @@ -2350,6 +2382,14 @@ impl item.response.id.clone(), )) } else { + let charge_id = item + .response + .latest_charge + .as_ref() + .map(|charge| match charge { + StripeChargeEnum::ChargeId(charge_id) => charge_id.clone(), + StripeChargeEnum::ChargeObject(charge) => charge.id.clone(), + }); Ok(types::PaymentsResponseData::TransactionResponse { resource_id: types::ResponseId::ConnectorTransactionId(item.response.id.clone()), redirection_data, @@ -2358,6 +2398,7 @@ impl network_txn_id, connector_response_reference_id: Some(item.response.id), incremental_authorization_allowed: None, + charge_id, }) }; @@ -2533,6 +2574,14 @@ impl }), _ => None, }; + let charge_id = item + .response + .latest_charge + .as_ref() + .map(|charge| match charge { + StripeChargeEnum::ChargeId(charge_id) => charge_id.clone(), + StripeChargeEnum::ChargeObject(charge) => charge.id.clone(), + }); Ok(types::PaymentsResponseData::TransactionResponse { resource_id: types::ResponseId::ConnectorTransactionId(item.response.id.clone()), redirection_data, @@ -2541,6 +2590,7 @@ impl network_txn_id: network_transaction_id, connector_response_reference_id: Some(item.response.id.clone()), incremental_authorization_allowed: None, + charge_id, }) }; @@ -2614,6 +2664,7 @@ impl network_txn_id: network_transaction_id, connector_response_reference_id: Some(item.response.id), incremental_authorization_allowed: None, + charge_id: None, }) }; @@ -2817,6 +2868,50 @@ impl TryFrom<&types::RefundsRouterData> for RefundRequest { } } +#[derive(Debug, Serialize)] +pub struct ChargeRefundRequest { + pub charge: String, + pub refund_application_fee: Option, + pub reverse_transfer: Option, + pub amount: Option, //amount in cents, hence passed as integer + #[serde(flatten)] + pub meta_data: StripeMetadata, +} + +impl TryFrom<&types::RefundsRouterData> for ChargeRefundRequest { + type Error = error_stack::Report; + fn try_from(item: &types::RefundsRouterData) -> Result { + let amount = item.request.refund_amount; + match item.request.charges.as_ref() { + None => Err(errors::ConnectorError::MissingRequiredField { + field_name: "charges", + } + .into()), + Some(charges) => { + let (refund_application_fee, reverse_transfer) = match charges.options { + types::ChargeRefundsOptions::Direct(types::DirectChargeRefund { + revert_platform_fee, + }) => (Some(revert_platform_fee), None), + types::ChargeRefundsOptions::Destination(types::DestinationChargeRefund { + revert_platform_fee, + revert_transfer, + }) => (Some(revert_platform_fee), Some(revert_transfer)), + }; + Ok(Self { + charge: charges.charge_id.clone(), + refund_application_fee, + reverse_transfer, + amount: Some(amount), + meta_data: StripeMetadata { + order_id: Some(item.request.refund_id.clone()), + is_refund_id_as_reference: Some("true".to_string()), + }, + }) + } + } + } +} + // Type definition for Stripe Refund Response #[derive(Default, Debug, Serialize, Deserialize, Clone)] @@ -3248,8 +3343,9 @@ impl TryFrom types::PaymentsRes network_txn_id: None, connector_response_reference_id: Some(connector_response.transaction_id), incremental_authorization_allowed: None, + charge_id: None, } } @@ -242,6 +243,7 @@ fn get_payments_sync_response( .clone(), ), incremental_authorization_allowed: None, + charge_id: None, } } diff --git a/crates/router/src/connector/volt/transformers.rs b/crates/router/src/connector/volt/transformers.rs index 814eefaf5f..a78ecc9444 100644 --- a/crates/router/src/connector/volt/transformers.rs +++ b/crates/router/src/connector/volt/transformers.rs @@ -283,6 +283,7 @@ impl network_txn_id: None, connector_response_reference_id: Some(item.response.id), incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) @@ -364,6 +365,7 @@ impl .merchant_internal_reference .or(Some(payment_response.id)), incremental_authorization_allowed: None, + charge_id: None, }) }, ..item.data @@ -404,6 +406,7 @@ impl .merchant_internal_reference .or(Some(webhook_response.payment)), incremental_authorization_allowed: None, + charge_id: None, }) }, ..item.data diff --git a/crates/router/src/connector/worldline/transformers.rs b/crates/router/src/connector/worldline/transformers.rs index 1966c65a0a..06d608a172 100644 --- a/crates/router/src/connector/worldline/transformers.rs +++ b/crates/router/src/connector/worldline/transformers.rs @@ -582,6 +582,7 @@ impl TryFrom TryFrom> network_txn_id: None, connector_response_reference_id: None, incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) diff --git a/crates/router/src/connector/zen/transformers.rs b/crates/router/src/connector/zen/transformers.rs index 67538b819d..0f067ab935 100644 --- a/crates/router/src/connector/zen/transformers.rs +++ b/crates/router/src/connector/zen/transformers.rs @@ -946,6 +946,7 @@ fn get_zen_response( network_txn_id: None, connector_response_reference_id: None, incremental_authorization_allowed: None, + charge_id: None, }; Ok((status, error, payment_response_data)) } @@ -989,6 +990,7 @@ impl TryFrom network_txn_id: None, connector_response_reference_id: Some(item.response.mer_ref.clone()), incremental_authorization_allowed: None, + charge_id: None, }), ..item.data }) @@ -425,6 +426,7 @@ impl TryFrom( connector_metadata, connector_response_reference_id, incremental_authorization_allowed, + charge_id, .. } => { payment_data @@ -959,6 +960,7 @@ async fn payment_response_update_tracker( authentication_data, encoded_data, payment_method_data: additional_payment_method_data, + charge_id, }), ), }; diff --git a/crates/router/src/core/payments/retry.rs b/crates/router/src/core/payments/retry.rs index 7c6c6336fc..3bafd77740 100644 --- a/crates/router/src/core/payments/retry.rs +++ b/crates/router/src/core/payments/retry.rs @@ -360,6 +360,7 @@ where resource_id, connector_metadata, redirection_data, + charge_id, .. }) => { let encoded_data = payment_data.payment_attempt.encoded_data.clone(); @@ -407,6 +408,7 @@ where unified_code: None, unified_message: None, payment_method_data: additional_payment_method_data, + charge_id, }, storage_scheme, ) diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs index ca068f1d59..11ce9cd7ed 100644 --- a/crates/router/src/core/payments/transformers.rs +++ b/crates/router/src/core/payments/transformers.rs @@ -1,13 +1,16 @@ use std::{fmt::Debug, marker::PhantomData, str::FromStr}; -use api_models::payments::{FrmMessage, GetAddressFromPaymentMethodData, RequestSurchargeDetails}; +use api_models::payments::{ + FrmMessage, GetAddressFromPaymentMethodData, PaymentChargeRequest, PaymentChargeResponse, + RequestSurchargeDetails, +}; #[cfg(feature = "payouts")] use api_models::payouts::PayoutAttemptResponse; use common_enums::RequestIncrementalAuthorization; use common_utils::{consts::X_HS_LATENCY, fp_utils, types::MinorUnit}; use diesel_models::ephemeral_key; use error_stack::{report, ResultExt}; -use masking::{Maskable, Secret}; +use masking::{Maskable, PeekInterface, Secret}; use router_env::{instrument, tracing}; use super::{flows::Feature, types::AuthenticationData, PaymentData}; @@ -86,6 +89,7 @@ where network_txn_id: None, connector_response_reference_id: None, incremental_authorization_allowed: None, + charge_id: None, }); let additional_data = PaymentAdditionalData { @@ -637,6 +641,28 @@ where ) }); + let charges_response = match payment_intent.charges { + None => None, + Some(charges) => { + let payment_charges: PaymentChargeRequest = charges + .peek() + .clone() + .parse_value("PaymentChargeRequest") + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable(format!( + "Failed to parse PaymentChargeRequest for payment_intent {}", + payment_intent.payment_id + ))?; + + Some(PaymentChargeResponse { + charge_id: payment_attempt.charge_id, + charge_type: payment_charges.charge_type, + application_fees: payment_charges.fees, + transfer_account_id: payment_charges.transfer_account_id, + }) + } + }; + services::ApplicationResponse::JsonWithHeaders(( response .set_net_amount(payment_attempt.net_amount) @@ -788,6 +814,7 @@ where .set_customer(customer_details_response.clone()) .set_browser_info(payment_attempt.browser_info) .set_updated(Some(payment_intent.modified_at)) + .set_charges(charges_response) .set_frm_metadata(payment_intent.frm_metadata) .to_owned(), headers, @@ -1166,6 +1193,16 @@ impl TryFrom> for types::PaymentsAuthoriz .map(|customer| customer.clone().into_inner()) }); + let charges = match payment_data.payment_intent.charges { + Some(charges) => charges + .peek() + .clone() + .parse_value("PaymentCharges") + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Failed to parse charges in to PaymentCharges")?, + None => None, + }; + Ok(Self { payment_method_data: From::from( payment_method_data.get_required_value("payment_method_data")?, @@ -1209,6 +1246,7 @@ impl TryFrom> for types::PaymentsAuthoriz .map(AuthenticationData::foreign_try_from) .transpose()?, customer_acceptance: payment_data.customer_acceptance, + charges, }) } } diff --git a/crates/router/src/core/payments/types.rs b/crates/router/src/core/payments/types.rs index e3a1daf39a..eb3a711b5b 100644 --- a/crates/router/src/core/payments/types.rs +++ b/crates/router/src/core/payments/types.rs @@ -374,3 +374,10 @@ impl ForeignTryFrom<&storage::Authentication> for AuthenticationData { } } } + +#[derive(Debug, serde::Deserialize, Clone)] +pub struct PaymentCharges { + pub charge_type: api_models::enums::PaymentChargeType, + pub fees: i64, + pub transfer_account_id: String, +} diff --git a/crates/router/src/core/refunds.rs b/crates/router/src/core/refunds.rs index 987d627f56..b9861ea1f2 100644 --- a/crates/router/src/core/refunds.rs +++ b/crates/router/src/core/refunds.rs @@ -5,8 +5,9 @@ use std::collections::HashMap; #[cfg(feature = "olap")] use api_models::admin::MerchantConnectorInfo; -use common_utils::ext_traits::AsyncExt; +use common_utils::ext_traits::{AsyncExt, ValueExt}; use error_stack::{report, ResultExt}; +use masking::PeekInterface; use router_env::{instrument, tracing}; use scheduler::{consumer::types::process_data, utils as process_tracker_utils}; #[cfg(feature = "olap")] @@ -16,7 +17,7 @@ use crate::{ consts, core::{ errors::{self, ConnectorErrorExt, RouterResponse, RouterResult, StorageErrorExt}, - payments::{self, access_token}, + payments::{self, access_token, types::PaymentCharges}, utils as core_utils, }, db, logger, @@ -28,6 +29,7 @@ use crate::{ domain, storage::{self, enums}, transformers::{ForeignFrom, ForeignInto}, + ChargeRefunds, }, utils::{self, OptionExt}, workflows::payment_sync, @@ -128,6 +130,7 @@ pub async fn refund_create_core( .map(services::ApplicationResponse::Json) } +#[allow(clippy::too_many_arguments)] #[instrument(skip_all)] pub async fn trigger_refund_to_gateway( state: &AppState, @@ -137,6 +140,7 @@ pub async fn trigger_refund_to_gateway( payment_attempt: &storage::PaymentAttempt, payment_intent: &storage::PaymentIntent, creds_identifier: Option, + charges: Option, ) -> RouterResult { let routed_through = payment_attempt .connector @@ -179,6 +183,7 @@ pub async fn trigger_refund_to_gateway( payment_attempt, refund, creds_identifier, + charges, ) .await?; @@ -458,6 +463,7 @@ pub async fn sync_refund_with_gateway( payment_attempt, refund, creds_identifier, + None, ) .await?; @@ -588,6 +594,39 @@ pub async fn validate_and_create_refund( ) -> RouterResult { let db = &*state.store; + // Validate charge_id and refund options + let charges = match ( + payment_intent.charges.as_ref(), + payment_attempt.charge_id.as_ref(), + ) { + (Some(charges), Some(charge_id)) => { + let refund_charge_request = req.charges.clone().get_required_value("charges")?; + utils::when(*charge_id != refund_charge_request.charge_id, || { + Err(report!(errors::ApiErrorResponse::InvalidDataValue { + field_name: "charges.charge_id" + })) + .attach_printable("charge_id sent in request mismatches with original charge_id") + })?; + let payment_charges: PaymentCharges = charges + .peek() + .clone() + .parse_value("PaymentCharges") + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Failed to parse charges in to PaymentCharges")?; + let options = validator::validate_charge_refund( + &refund_charge_request, + &payment_charges.charge_type, + )?; + Some(ChargeRefunds { + charge_id: charge_id.to_string(), + charge_type: payment_charges.charge_type, + transfer_account_id: payment_charges.transfer_account_id, + options, + }) + } + _ => None, + }; + // Only for initial dev and testing let refund_type = req.refund_type.unwrap_or_default(); @@ -678,6 +717,7 @@ pub async fn validate_and_create_refund( .set_refund_reason(req.reason) .set_profile_id(payment_intent.profile_id.clone()) .set_merchant_connector_id(payment_attempt.merchant_connector_id.clone()) + .set_charges(req.charges) .to_owned(); let refund = match db @@ -694,6 +734,7 @@ pub async fn validate_and_create_refund( payment_attempt, payment_intent, creds_identifier, + charges, ) .await? } @@ -832,6 +873,7 @@ pub async fn get_filters_for_refunds( impl ForeignFrom for api::RefundResponse { fn foreign_from(refund: storage::Refund) -> Self { let refund = refund; + Self { payment_id: refund.payment_id, refund_id: refund.refund_id, @@ -847,6 +889,7 @@ impl ForeignFrom for api::RefundResponse { updated_at: Some(refund.updated_at), connector: refund.connector, merchant_connector_id: refund.merchant_connector_id, + charges: refund.charges, } } } @@ -864,6 +907,7 @@ pub async fn schedule_refund_execution( payment_attempt: &storage::PaymentAttempt, payment_intent: &storage::PaymentIntent, creds_identifier: Option, + charges: Option, ) -> RouterResult { // refunds::RefundResponse> { let db = &*state.store; @@ -900,6 +944,7 @@ pub async fn schedule_refund_execution( payment_attempt, payment_intent, creds_identifier, + charges, ) .await } @@ -1079,6 +1124,41 @@ pub async fn trigger_refund_execute_workflow( .await .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?; + let charges = match ( + payment_intent.charges.as_ref(), + payment_attempt.charge_id.as_ref(), + ) { + (Some(charges), Some(charge_id)) => { + let refund_charge_request = + refund.charges.clone().get_required_value("charges")?; + utils::when(*charge_id != refund_charge_request.charge_id, || { + Err(report!(errors::ApiErrorResponse::InvalidDataValue { + field_name: "charges.charge_id" + })) + .attach_printable( + "charge_id sent in request mismatches with original charge_id", + ) + })?; + let payment_charges: PaymentCharges = charges + .peek() + .clone() + .parse_value("PaymentCharges") + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Failed to parse charges in to PaymentCharges")?; + let options = validator::validate_charge_refund( + &refund_charge_request, + &payment_charges.charge_type, + )?; + Some(ChargeRefunds { + charge_id: charge_id.to_string(), + charge_type: payment_charges.charge_type, + transfer_account_id: payment_charges.transfer_account_id, + options, + }) + } + _ => None, + }; + //trigger refund request to gateway let updated_refund = trigger_refund_to_gateway( state, @@ -1088,6 +1168,7 @@ pub async fn trigger_refund_execute_workflow( &payment_attempt, &payment_intent, None, + charges, ) .await?; add_refund_sync_task( diff --git a/crates/router/src/core/refunds/validator.rs b/crates/router/src/core/refunds/validator.rs index 49248ae4fe..3788b8ac26 100644 --- a/crates/router/src/core/refunds/validator.rs +++ b/crates/router/src/core/refunds/validator.rs @@ -4,7 +4,11 @@ use time::PrimitiveDateTime; use crate::{ core::errors::{self, CustomResult, RouterResult}, - types::storage::{self, enums}, + types::{ + self, + api::enums as api_enums, + storage::{self, enums}, + }, utils::{self, OptionExt}, }; @@ -144,3 +148,28 @@ pub fn validate_for_valid_refunds( _ => Ok(()), } } + +pub fn validate_charge_refund( + charges: &common_utils::types::ChargeRefunds, + charge_type: &api_enums::PaymentChargeType, +) -> RouterResult { + match charge_type { + api_enums::PaymentChargeType::Stripe(api_enums::StripeChargeType::Direct) => Ok( + types::ChargeRefundsOptions::Direct(types::DirectChargeRefund { + revert_platform_fee: charges + .revert_platform_fee + .get_required_value("revert_platform_fee")?, + }), + ), + api_enums::PaymentChargeType::Stripe(api_enums::StripeChargeType::Destination) => Ok( + types::ChargeRefundsOptions::Destination(types::DestinationChargeRefund { + revert_platform_fee: charges + .revert_platform_fee + .get_required_value("revert_platform_fee")?, + revert_transfer: charges + .revert_transfer + .get_required_value("revert_transfer")?, + }), + ), + } +} diff --git a/crates/router/src/core/utils.rs b/crates/router/src/core/utils.rs index 237d8b6223..ca464cc627 100644 --- a/crates/router/src/core/utils.rs +++ b/crates/router/src/core/utils.rs @@ -223,6 +223,7 @@ pub async fn construct_refund_router_data<'a, F>( payment_attempt: &storage::PaymentAttempt, refund: &'a storage::Refund, creds_identifier: Option, + charges: Option, ) -> RouterResult> { let profile_id = get_profile_id_from_business_details( payment_intent.business_country, @@ -330,6 +331,7 @@ pub async fn construct_refund_router_data<'a, F>( reason: refund.refund_reason.clone(), connector_refund_id: refund.connector_refund_id.clone(), browser_info, + charges, }, response: Ok(types::RefundsResponseData { diff --git a/crates/router/src/db/refund.rs b/crates/router/src/db/refund.rs index 3b24dd3960..1b1bfed387 100644 --- a/crates/router/src/db/refund.rs +++ b/crates/router/src/db/refund.rs @@ -394,6 +394,7 @@ mod storage { profile_id: new.profile_id.clone(), updated_by: new.updated_by.clone(), merchant_connector_id: new.merchant_connector_id.clone(), + charges: new.charges.clone(), }; let field = format!( @@ -848,6 +849,7 @@ impl RefundInterface for MockDb { profile_id: new.profile_id, updated_by: new.updated_by, merchant_connector_id: new.merchant_connector_id, + charges: new.charges, }; refunds.push(refund.clone()); Ok(refund) diff --git a/crates/router/src/types.rs b/crates/router/src/types.rs index 7f2f0764b5..e2f2f6c0b7 100644 --- a/crates/router/src/types.rs +++ b/crates/router/src/types.rs @@ -35,8 +35,9 @@ pub use hyperswitch_domain_models::{ PaymentMethodBalance, PaymentMethodToken, RecurringMandatePaymentData, RouterData, }, router_request_types::{ - AcceptDisputeRequestData, AccessTokenRequestData, BrowserInformation, - DefendDisputeRequestData, RefundsData, ResponseId, RetrieveFileRequestData, + AcceptDisputeRequestData, AccessTokenRequestData, BrowserInformation, ChargeRefunds, + ChargeRefundsOptions, DefendDisputeRequestData, DestinationChargeRefund, + DirectChargeRefund, RefundsData, ResponseId, RetrieveFileRequestData, SubmitEvidenceRequestData, UploadFileRequestData, VerifyWebhookSourceRequestData, }, }; @@ -349,6 +350,7 @@ pub struct PaymentsAuthorizeData { pub request_incremental_authorization: bool, pub metadata: Option, pub authentication_data: Option, + pub charges: Option, } #[derive(Debug, Clone, Default)] @@ -806,6 +808,7 @@ pub enum PaymentsResponseData { network_txn_id: Option, connector_response_reference_id: Option, incremental_authorization_allowed: Option, + charge_id: Option, }, MultipleCaptureResponse { // pending_capture_id_list: Vec, @@ -1169,6 +1172,7 @@ impl From<&SetupMandateRouterData> for PaymentsAuthorizeData { metadata: None, authentication_data: None, customer_acceptance: data.request.customer_acceptance.clone(), + charges: None, // TODO: allow charges on mandates? } } } diff --git a/crates/router/src/types/api/verify_connector.rs b/crates/router/src/types/api/verify_connector.rs index d35abd233f..cf7ba2382a 100644 --- a/crates/router/src/types/api/verify_connector.rs +++ b/crates/router/src/types/api/verify_connector.rs @@ -52,6 +52,7 @@ impl VerifyConnectorData { request_incremental_authorization: false, authentication_data: None, customer_acceptance: None, + charges: None, } } diff --git a/crates/router/src/utils/user/sample_data.rs b/crates/router/src/utils/user/sample_data.rs index ef39a5fca1..8936b2af67 100644 --- a/crates/router/src/utils/user/sample_data.rs +++ b/crates/router/src/utils/user/sample_data.rs @@ -218,6 +218,7 @@ pub async fn generate_sample_data( fingerprint_id: None, session_expiry: Some(session_expiry), request_external_three_ds_authentication: None, + charges: None, frm_metadata: Default::default(), }; let payment_attempt = PaymentAttemptBatchNew { @@ -295,6 +296,7 @@ pub async fn generate_sample_data( profile_id: payment_intent.profile_id.clone(), updated_by: merchant_from_db.storage_scheme.to_string(), merchant_connector_id: payment_attempt.merchant_connector_id.clone(), + charges: None, }) } else { None diff --git a/crates/router/tests/connectors/aci.rs b/crates/router/tests/connectors/aci.rs index 3548bc5e5b..b4eafee4c8 100644 --- a/crates/router/tests/connectors/aci.rs +++ b/crates/router/tests/connectors/aci.rs @@ -75,6 +75,7 @@ fn construct_payment_router_data() -> types::PaymentsAuthorizeRouterData { metadata: None, authentication_data: None, customer_acceptance: None, + ..utils::PaymentAuthorizeType::default().0 }, response: Err(types::ErrorResponse::default()), address: PaymentAddress::new( @@ -152,6 +153,7 @@ fn construct_refund_router_data() -> types::RefundsRouterData { reason: None, connector_refund_id: None, browser_info: None, + ..utils::PaymentRefundType::default().0 }, response: Err(types::ErrorResponse::default()), address: PaymentAddress::default(), diff --git a/crates/router/tests/connectors/adyen.rs b/crates/router/tests/connectors/adyen.rs index 4d4318064e..ff703dd84e 100644 --- a/crates/router/tests/connectors/adyen.rs +++ b/crates/router/tests/connectors/adyen.rs @@ -182,6 +182,7 @@ impl AdyenTest { metadata: None, authentication_data: None, customer_acceptance: None, + ..utils::PaymentAuthorizeType::default().0 }) } } diff --git a/crates/router/tests/connectors/bitpay.rs b/crates/router/tests/connectors/bitpay.rs index 2dd90e704b..85026c9c44 100644 --- a/crates/router/tests/connectors/bitpay.rs +++ b/crates/router/tests/connectors/bitpay.rs @@ -99,6 +99,7 @@ fn payment_method_details() -> Option { metadata: None, authentication_data: None, customer_acceptance: None, + ..utils::PaymentAuthorizeType::default().0 }) } diff --git a/crates/router/tests/connectors/cashtocode.rs b/crates/router/tests/connectors/cashtocode.rs index 60620d1b4c..76887fa044 100644 --- a/crates/router/tests/connectors/cashtocode.rs +++ b/crates/router/tests/connectors/cashtocode.rs @@ -72,6 +72,7 @@ impl CashtocodeTest { metadata: None, authentication_data: None, customer_acceptance: None, + ..utils::PaymentAuthorizeType::default().0 }) } diff --git a/crates/router/tests/connectors/coinbase.rs b/crates/router/tests/connectors/coinbase.rs index 5dd42a2c97..306255c94c 100644 --- a/crates/router/tests/connectors/coinbase.rs +++ b/crates/router/tests/connectors/coinbase.rs @@ -101,6 +101,7 @@ fn payment_method_details() -> Option { metadata: None, authentication_data: None, customer_acceptance: None, + ..utils::PaymentAuthorizeType::default().0 }) } diff --git a/crates/router/tests/connectors/cryptopay.rs b/crates/router/tests/connectors/cryptopay.rs index c26bad8c56..6d52a174b5 100644 --- a/crates/router/tests/connectors/cryptopay.rs +++ b/crates/router/tests/connectors/cryptopay.rs @@ -99,6 +99,7 @@ fn payment_method_details() -> Option { metadata: None, authentication_data: None, customer_acceptance: None, + ..utils::PaymentAuthorizeType::default().0 }) } diff --git a/crates/router/tests/connectors/opennode.rs b/crates/router/tests/connectors/opennode.rs index 1e2cea554e..91162b829e 100644 --- a/crates/router/tests/connectors/opennode.rs +++ b/crates/router/tests/connectors/opennode.rs @@ -100,6 +100,7 @@ fn payment_method_details() -> Option { metadata: None, authentication_data: None, customer_acceptance: None, + ..utils::PaymentAuthorizeType::default().0 }) } diff --git a/crates/router/tests/connectors/utils.rs b/crates/router/tests/connectors/utils.rs index cd1a44a702..6718611b0c 100644 --- a/crates/router/tests/connectors/utils.rs +++ b/crates/router/tests/connectors/utils.rs @@ -423,6 +423,7 @@ pub trait ConnectorActions: Connector { reason: None, connector_refund_id: Some(refund_id), browser_info: None, + charges: None, }), payment_info, ); @@ -942,6 +943,7 @@ impl Default for PaymentAuthorizeType { metadata: None, authentication_data: None, customer_acceptance: None, + charges: None, }; Self(data) } @@ -1018,6 +1020,7 @@ impl Default for PaymentRefundType { reason: Some("Customer returned product".to_string()), connector_refund_id: None, browser_info: None, + charges: None, }; Self(data) } @@ -1081,6 +1084,7 @@ pub fn get_connector_metadata( network_txn_id: _, connector_response_reference_id: _, incremental_authorization_allowed: _, + charge_id: _, }) => connector_metadata, _ => None, } diff --git a/crates/router/tests/connectors/worldline.rs b/crates/router/tests/connectors/worldline.rs index 36d0bba6c4..e26ba15eb2 100644 --- a/crates/router/tests/connectors/worldline.rs +++ b/crates/router/tests/connectors/worldline.rs @@ -111,6 +111,7 @@ impl WorldlineTest { metadata: None, authentication_data: None, customer_acceptance: None, + ..utils::PaymentAuthorizeType::default().0 }) } } diff --git a/crates/storage_impl/src/mock_db/payment_attempt.rs b/crates/storage_impl/src/mock_db/payment_attempt.rs index cc2f2abc00..0e8df898f1 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 { mandate_data: payment_attempt.mandate_data, payment_method_billing_address_id: payment_attempt.payment_method_billing_address_id, fingerprint_id: payment_attempt.fingerprint_id, + charge_id: payment_attempt.charge_id, client_source: payment_attempt.client_source, client_version: payment_attempt.client_version, }; diff --git a/crates/storage_impl/src/mock_db/payment_intent.rs b/crates/storage_impl/src/mock_db/payment_intent.rs index 8ad010be13..a12b06b291 100644 --- a/crates/storage_impl/src/mock_db/payment_intent.rs +++ b/crates/storage_impl/src/mock_db/payment_intent.rs @@ -108,6 +108,7 @@ impl PaymentIntentInterface for MockDb { fingerprint_id: new.fingerprint_id, session_expiry: new.session_expiry, request_external_three_ds_authentication: new.request_external_three_ds_authentication, + charges: new.charges, frm_metadata: new.frm_metadata, }; payment_intents.push(payment_intent.clone()); diff --git a/crates/storage_impl/src/payments/payment_attempt.rs b/crates/storage_impl/src/payments/payment_attempt.rs index fb9a5882ee..1e60c3e02f 100644 --- a/crates/storage_impl/src/payments/payment_attempt.rs +++ b/crates/storage_impl/src/payments/payment_attempt.rs @@ -413,6 +413,7 @@ impl PaymentAttemptInterface for KVRouterStore { .payment_method_billing_address_id .clone(), fingerprint_id: payment_attempt.fingerprint_id.clone(), + charge_id: payment_attempt.charge_id.clone(), client_source: payment_attempt.client_source.clone(), client_version: payment_attempt.client_version.clone(), }; @@ -1197,6 +1198,7 @@ impl DataModelExt for PaymentAttempt { mandate_data: self.mandate_data.map(|d| d.to_storage_model()), payment_method_billing_address_id: self.payment_method_billing_address_id, fingerprint_id: self.fingerprint_id, + charge_id: self.charge_id, client_source: self.client_source, client_version: self.client_version, } @@ -1263,6 +1265,7 @@ impl DataModelExt for PaymentAttempt { .map(MandateDetails::from_storage_model), payment_method_billing_address_id: storage_model.payment_method_billing_address_id, fingerprint_id: storage_model.fingerprint_id, + charge_id: storage_model.charge_id, client_source: storage_model.client_source, client_version: storage_model.client_version, } @@ -1333,6 +1336,7 @@ impl DataModelExt for PaymentAttemptNew { mandate_data: self.mandate_data.map(|d| d.to_storage_model()), payment_method_billing_address_id: self.payment_method_billing_address_id, fingerprint_id: self.fingerprint_id, + charge_id: self.charge_id, client_source: self.client_source, client_version: self.client_version, } @@ -1397,6 +1401,7 @@ impl DataModelExt for PaymentAttemptNew { .map(MandateDetails::from_storage_model), payment_method_billing_address_id: storage_model.payment_method_billing_address_id, fingerprint_id: storage_model.fingerprint_id, + charge_id: storage_model.charge_id, client_source: storage_model.client_source, client_version: storage_model.client_version, } @@ -1585,6 +1590,7 @@ impl DataModelExt for PaymentAttemptUpdate { unified_code, unified_message, payment_method_data, + charge_id, } => DieselPaymentAttemptUpdate::ResponseUpdate { status, connector, @@ -1606,6 +1612,7 @@ impl DataModelExt for PaymentAttemptUpdate { unified_code, unified_message, payment_method_data, + charge_id, }, Self::UnresolvedResponseUpdate { status, @@ -1709,12 +1716,14 @@ impl DataModelExt for PaymentAttemptUpdate { encoded_data, connector_transaction_id, connector, + charge_id, updated_by, } => DieselPaymentAttemptUpdate::ConnectorResponse { authentication_data, encoded_data, connector_transaction_id, connector, + charge_id, updated_by, }, Self::IncrementalAuthorizationAmountUpdate { @@ -1913,6 +1922,7 @@ impl DataModelExt for PaymentAttemptUpdate { unified_code, unified_message, payment_method_data, + charge_id, } => Self::ResponseUpdate { status, connector, @@ -1933,6 +1943,7 @@ impl DataModelExt for PaymentAttemptUpdate { unified_code, unified_message, payment_method_data, + charge_id, }, DieselPaymentAttemptUpdate::UnresolvedResponseUpdate { status, @@ -2034,12 +2045,14 @@ impl DataModelExt for PaymentAttemptUpdate { encoded_data, connector_transaction_id, connector, + charge_id, updated_by, } => Self::ConnectorResponse { authentication_data, encoded_data, connector_transaction_id, connector, + charge_id, updated_by, }, DieselPaymentAttemptUpdate::IncrementalAuthorizationAmountUpdate { diff --git a/crates/storage_impl/src/payments/payment_intent.rs b/crates/storage_impl/src/payments/payment_intent.rs index 0ac963ae81..f40a9c3e2d 100644 --- a/crates/storage_impl/src/payments/payment_intent.rs +++ b/crates/storage_impl/src/payments/payment_intent.rs @@ -118,6 +118,7 @@ impl PaymentIntentInterface for KVRouterStore { session_expiry: new.session_expiry, request_external_three_ds_authentication: new .request_external_three_ds_authentication, + charges: new.charges.clone(), }; let redis_entry = kv::TypedSql { op: kv::DBOperation::Insert { @@ -849,6 +850,7 @@ impl DataModelExt for PaymentIntentNew { fingerprint_id: self.fingerprint_id, session_expiry: self.session_expiry, request_external_three_ds_authentication: self.request_external_three_ds_authentication, + charges: self.charges, } } @@ -897,6 +899,7 @@ impl DataModelExt for PaymentIntentNew { session_expiry: storage_model.session_expiry, request_external_three_ds_authentication: storage_model .request_external_three_ds_authentication, + charges: storage_model.charges, } } } @@ -948,6 +951,7 @@ impl DataModelExt for PaymentIntent { fingerprint_id: self.fingerprint_id, session_expiry: self.session_expiry, request_external_three_ds_authentication: self.request_external_three_ds_authentication, + charges: self.charges, frm_metadata: self.frm_metadata, } } @@ -997,6 +1001,7 @@ impl DataModelExt for PaymentIntent { session_expiry: storage_model.session_expiry, request_external_three_ds_authentication: storage_model .request_external_three_ds_authentication, + charges: storage_model.charges, frm_metadata: storage_model.frm_metadata, } } diff --git a/migrations/2024-05-06-165401_add_charges_in_payment_intent/down.sql b/migrations/2024-05-06-165401_add_charges_in_payment_intent/down.sql new file mode 100644 index 0000000000..53c2368276 --- /dev/null +++ b/migrations/2024-05-06-165401_add_charges_in_payment_intent/down.sql @@ -0,0 +1,5 @@ +ALTER TABLE payment_intent DROP COLUMN IF EXISTS charges; + +ALTER TABLE payment_attempt DROP COLUMN IF EXISTS charge_id; + +ALTER TABLE refund DROP COLUMN IF EXISTS charges; diff --git a/migrations/2024-05-06-165401_add_charges_in_payment_intent/up.sql b/migrations/2024-05-06-165401_add_charges_in_payment_intent/up.sql new file mode 100644 index 0000000000..c2f1ce14d8 --- /dev/null +++ b/migrations/2024-05-06-165401_add_charges_in_payment_intent/up.sql @@ -0,0 +1,6 @@ +ALTER TABLE payment_intent ADD COLUMN IF NOT EXISTS charges jsonb; + +ALTER TABLE payment_attempt +ADD COLUMN IF NOT EXISTS charge_id VARCHAR(64); + +ALTER TABLE refund ADD COLUMN IF NOT EXISTS charges jsonb; diff --git a/openapi/openapi_spec.json b/openapi/openapi_spec.json index 26eb8997c1..47da1ae107 100644 --- a/openapi/openapi_spec.json +++ b/openapi/openapi_spec.json @@ -7317,6 +7317,29 @@ "CashappQr": { "type": "object" }, + "ChargeRefunds": { + "type": "object", + "description": "Charge object for refunds", + "required": [ + "charge_id" + ], + "properties": { + "charge_id": { + "type": "string", + "description": "Identifier for charge created for the payment" + }, + "revert_platform_fee": { + "type": "boolean", + "description": "Toggle for reverting the application fee that was collected for the payment.\nIf set to false, the funds are pulled from the destination account.", + "nullable": true + }, + "revert_transfer": { + "type": "boolean", + "description": "Toggle for reverting the transfer that was made during the charge.\nIf set to false, the funds are pulled from the main platform's account.", + "nullable": true + } + } + }, "Comparison": { "type": "object", "description": "Represents a single comparison condition.", @@ -12529,6 +12552,70 @@ } } }, + "PaymentChargeRequest": { + "type": "object", + "required": [ + "charge_type", + "fees", + "transfer_account_id" + ], + "properties": { + "charge_type": { + "$ref": "#/components/schemas/PaymentChargeType" + }, + "fees": { + "type": "integer", + "format": "int64", + "description": "Platform fees to be collected on the payment" + }, + "transfer_account_id": { + "type": "string", + "description": "Identifier for the reseller's account to send the funds to" + } + } + }, + "PaymentChargeResponse": { + "type": "object", + "required": [ + "charge_type", + "application_fees", + "transfer_account_id" + ], + "properties": { + "charge_id": { + "type": "string", + "description": "Identifier for charge created for the payment", + "nullable": true + }, + "charge_type": { + "$ref": "#/components/schemas/PaymentChargeType" + }, + "application_fees": { + "type": "integer", + "format": "int64", + "description": "Platform fees collected on the payment" + }, + "transfer_account_id": { + "type": "string", + "description": "Identifier for the reseller's account where the funds were transferred" + } + } + }, + "PaymentChargeType": { + "oneOf": [ + { + "type": "object", + "required": [ + "Stripe" + ], + "properties": { + "Stripe": { + "$ref": "#/components/schemas/StripeChargeType" + } + } + } + ] + }, "PaymentCreatePaymentLinkConfig": { "allOf": [ { @@ -13954,6 +14041,14 @@ } ], "nullable": true + }, + "charges": { + "allOf": [ + { + "$ref": "#/components/schemas/PaymentChargeRequest" + } + ], + "nullable": true } } }, @@ -14327,6 +14422,14 @@ } ], "nullable": true + }, + "charges": { + "allOf": [ + { + "$ref": "#/components/schemas/PaymentChargeRequest" + } + ], + "nullable": true } } }, @@ -14834,6 +14937,14 @@ } ], "nullable": true + }, + "charges": { + "allOf": [ + { + "$ref": "#/components/schemas/PaymentChargeRequest" + } + ], + "nullable": true } }, "additionalProperties": false @@ -15359,6 +15470,14 @@ "example": "2022-09-10T10:11:12Z", "nullable": true }, + "charges": { + "allOf": [ + { + "$ref": "#/components/schemas/PaymentChargeResponse" + } + ], + "nullable": true + }, "frm_metadata": { "type": "object", "description": "You can specify up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. FRM Metadata is useful for storing additional, structured information on an object related to FRM.", @@ -15847,6 +15966,14 @@ } ], "nullable": true + }, + "charges": { + "allOf": [ + { + "$ref": "#/components/schemas/PaymentChargeRequest" + } + ], + "nullable": true } } }, @@ -17096,6 +17223,14 @@ } ], "nullable": true + }, + "charges": { + "allOf": [ + { + "$ref": "#/components/schemas/ChargeRefunds" + } + ], + "nullable": true } }, "additionalProperties": false @@ -17177,6 +17312,14 @@ "type": "string", "description": "The merchant_connector_id of the processor through which this payment went through", "nullable": true + }, + "charges": { + "allOf": [ + { + "$ref": "#/components/schemas/ChargeRefunds" + } + ], + "nullable": true } } }, @@ -18198,6 +18341,13 @@ "propertyName": "type" } }, + "StripeChargeType": { + "type": "string", + "enum": [ + "direct", + "destination" + ] + }, "SurchargeDetailsResponse": { "type": "object", "required": [