From 864a8d7b02acda5ea593cae83594962ea249c16d Mon Sep 17 00:00:00 2001 From: AkshayaFoiger <131388445+AkshayaFoiger@users.noreply.github.com> Date: Tue, 30 Jan 2024 17:06:31 +0530 Subject: [PATCH] feat(connector): [Stripe] Metadata to connector metadata mapping (#3295) Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com> --- .../src/connector/stripe/transformers.rs | 83 ++++++++++++------- .../router/src/core/payments/transformers.rs | 1 + crates/router/src/types.rs | 1 + 3 files changed, 56 insertions(+), 29 deletions(-) diff --git a/crates/router/src/connector/stripe/transformers.rs b/crates/router/src/connector/stripe/transformers.rs index 70582c41aa..8d397d0ebb 100644 --- a/crates/router/src/connector/stripe/transformers.rs +++ b/crates/router/src/connector/stripe/transformers.rs @@ -1,4 +1,4 @@ -use std::ops::Deref; +use std::{collections::HashMap, ops::Deref}; use api_models::{self, enums as api_enums, payments}; use common_utils::{ @@ -9,11 +9,11 @@ use common_utils::{ }; use data_models::mandates::AcceptanceType; use error_stack::{IntoReport, ResultExt}; -use masking::{ExposeInterface, ExposeOptionInterface, Secret}; +use masking::{ExposeInterface, ExposeOptionInterface, PeekInterface, Secret}; use serde::{Deserialize, Serialize}; +use serde_json::Value; use time::PrimitiveDateTime; use url::Url; -use uuid::Uuid; use crate::{ collect_missing_value_keys, @@ -105,7 +105,7 @@ pub struct PaymentIntentRequest { pub statement_descriptor_suffix: Option, pub statement_descriptor: Option, #[serde(flatten)] - pub meta_data: StripeMetadata, + pub meta_data: HashMap, pub return_url: String, pub confirm: bool, pub mandate: Option>, @@ -145,12 +145,6 @@ pub struct StripeMetadata { #[derive(Debug, Eq, PartialEq, Serialize)] pub struct SetupIntentRequest { - #[serde(rename = "metadata[order_id]")] - pub metadata_order_id: String, - #[serde(rename = "metadata[txn_id]")] - pub metadata_txn_id: String, - #[serde(rename = "metadata[txn_uuid]")] - pub metadata_txn_uuid: String, pub confirm: bool, pub usage: Option, pub customer: Option>, @@ -159,6 +153,8 @@ pub struct SetupIntentRequest { #[serde(flatten)] pub payment_data: StripePaymentMethodData, pub payment_method_options: Option, // For mandate txns using network_txns_id, needs to be validated + #[serde(flatten)] + pub meta_data: Option>, } #[derive(Debug, Eq, PartialEq, Serialize)] @@ -218,6 +214,8 @@ pub struct ChargesRequest { pub currency: String, pub customer: Secret, pub source: Secret, + #[serde(flatten)] + pub meta_data: Option>, } #[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize)] @@ -1877,15 +1875,15 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for PaymentIntentRequest { None } }); + + let meta_data = get_transaction_metadata(item.request.metadata.clone(), order_id); + 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 statement_descriptor_suffix: item.request.statement_descriptor_suffix.clone(), statement_descriptor: item.request.statement_descriptor.clone(), - meta_data: StripeMetadata { - order_id: Some(order_id), - is_refund_id_as_reference: None, - }, + meta_data, return_url: item .request .router_return_url @@ -1945,10 +1943,6 @@ fn get_payment_method_type_for_saved_payment_method_payment( impl TryFrom<&types::SetupMandateRouterData> for SetupIntentRequest { type Error = error_stack::Report; fn try_from(item: &types::SetupMandateRouterData) -> Result { - let metadata_order_id = item.connector_request_reference_id.clone(); - let metadata_txn_id = format!("{}_{}_{}", item.merchant_id, item.payment_id, "1"); - let metadata_txn_uuid = Uuid::new_v4().to_string(); - //Only cards supported for mandates let pm_type = StripePaymentMethodType::Card; let payment_data = StripePaymentMethodData::try_from(( @@ -1957,17 +1951,20 @@ impl TryFrom<&types::SetupMandateRouterData> for SetupIntentRequest { pm_type, ))?; + let meta_data = Some(get_transaction_metadata( + item.request.metadata.clone(), + item.connector_request_reference_id.clone(), + )); + Ok(Self { confirm: true, - metadata_order_id, - metadata_txn_id, - metadata_txn_uuid, payment_data, return_url: item.request.router_return_url.clone(), off_session: item.request.off_session, usage: item.request.setup_future_usage, payment_method_options: None, customer: item.connector_customer.to_owned().map(Secret::new), + meta_data, }) } } @@ -2355,7 +2352,7 @@ impl pub fn get_connector_metadata( next_action: Option<&StripeNextActionResponse>, amount: i64, -) -> CustomResult, errors::ConnectorError> { +) -> CustomResult, errors::ConnectorError> { let next_action_response = next_action .and_then(|next_action_response| match next_action_response { StripeNextActionResponse::DisplayBankTransferInstructions(response) => { @@ -3058,12 +3055,20 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for ChargesRequest { type Error = error_stack::Report; fn try_from(value: &types::PaymentsAuthorizeRouterData) -> Result { - Ok(Self { - amount: value.request.amount.to_string(), - currency: value.request.currency.to_string(), - customer: Secret::new(value.get_connector_customer_id()?), - source: Secret::new(value.get_preprocessing_id()?), - }) + { + let order_id = value.connector_request_reference_id.clone(); + let meta_data = Some(get_transaction_metadata( + value.request.metadata.clone(), + order_id, + )); + Ok(Self { + amount: value.request.amount.to_string(), + currency: value.request.currency.to_string(), + customer: Secret::new(value.get_connector_customer_id()?), + source: Secret::new(value.get_preprocessing_id()?), + meta_data, + }) + } } } @@ -3169,7 +3174,7 @@ impl #[derive(Debug, Deserialize)] pub struct WebhookEventDataResource { - pub object: serde_json::Value, + pub object: Value, } #[derive(Debug, Deserialize)] @@ -3649,6 +3654,26 @@ pub struct DisputeObj { pub status: String, } +fn get_transaction_metadata( + merchant_metadata: Option>, + order_id: String, +) -> HashMap { + let mut meta_data = HashMap::from([("metadata[order_id]".to_string(), order_id)]); + let mut request_hash_map = HashMap::new(); + + if let Some(metadata) = merchant_metadata { + let hashmap: HashMap = + serde_json::from_str(&metadata.peek().to_string()).unwrap_or(HashMap::new()); + + for (key, value) in hashmap { + request_hash_map.insert(format!("metadata[{}]", key), value.to_string()); + } + + meta_data.extend(request_hash_map) + }; + meta_data +} + #[cfg(test)] mod test_validate_shipping_address_against_payment_method { #![allow(clippy::unwrap_used)] diff --git a/crates/router/src/core/payments/transformers.rs b/crates/router/src/core/payments/transformers.rs index 61917fdcd2..5b05e60150 100644 --- a/crates/router/src/core/payments/transformers.rs +++ b/crates/router/src/core/payments/transformers.rs @@ -1440,6 +1440,7 @@ impl TryFrom> for types::SetupMandateRequ Some(RequestIncrementalAuthorization::True) | Some(RequestIncrementalAuthorization::Default) ), + metadata: payment_data.payment_intent.metadata.clone(), }) } } diff --git a/crates/router/src/types.rs b/crates/router/src/types.rs index 0809ca1782..531ca849a3 100644 --- a/crates/router/src/types.rs +++ b/crates/router/src/types.rs @@ -591,6 +591,7 @@ pub struct SetupMandateRequestData { pub return_url: Option, pub payment_method_type: Option, pub request_incremental_authorization: bool, + pub metadata: Option, } #[derive(Debug, Clone)]