From e659e7029e758ef46b4fd12b262a58d0c3f5e5c0 Mon Sep 17 00:00:00 2001 From: Sakil Mostak <73734619+Sakilmostak@users.noreply.github.com> Date: Fri, 8 Sep 2023 15:13:49 +0530 Subject: [PATCH] refactor(connector): [Stripe] Using `connector_request_reference_id` as object_reference_id for Webhooks (#2064) --- crates/router/src/connector/stripe.rs | 64 ++++++++++++++++--- .../src/connector/stripe/transformers.rs | 61 +++++++++--------- 2 files changed, 84 insertions(+), 41 deletions(-) diff --git a/crates/router/src/connector/stripe.rs b/crates/router/src/connector/stripe.rs index 3e8c31ef66..b7cb260cb7 100644 --- a/crates/router/src/connector/stripe.rs +++ b/crates/router/src/connector/stripe.rs @@ -1733,14 +1733,38 @@ impl api::IncomingWebhook for Stripe { Ok(match details.event_data.event_object.object { stripe::WebhookEventObjectType::PaymentIntent => { - api_models::webhooks::ObjectReferenceId::PaymentId( - api_models::payments::PaymentIdType::ConnectorTransactionId( - details.event_data.event_object.id, + match details.event_data.event_object.metadata { + // if order_id is present + Some(meta_data) => api_models::webhooks::ObjectReferenceId::PaymentId( + api_models::payments::PaymentIdType::PaymentAttemptId(meta_data.order_id), ), - ) + // else used connector_transaction_id + None => api_models::webhooks::ObjectReferenceId::PaymentId( + api_models::payments::PaymentIdType::ConnectorTransactionId( + details.event_data.event_object.id, + ), + ), + } } - - stripe::WebhookEventObjectType::Charge | stripe::WebhookEventObjectType::Dispute => { + stripe::WebhookEventObjectType::Charge => { + match details.event_data.event_object.metadata { + // if order_id is present + Some(meta_data) => api_models::webhooks::ObjectReferenceId::PaymentId( + api_models::payments::PaymentIdType::PaymentAttemptId(meta_data.order_id), + ), + // else used connector_transaction_id + None => api_models::webhooks::ObjectReferenceId::PaymentId( + api_models::payments::PaymentIdType::ConnectorTransactionId( + details + .event_data + .event_object + .payment_intent + .ok_or(errors::ConnectorError::WebhookReferenceIdNotFound)?, + ), + ), + } + } + stripe::WebhookEventObjectType::Dispute => { api_models::webhooks::ObjectReferenceId::PaymentId( api_models::payments::PaymentIdType::ConnectorTransactionId( details @@ -1759,11 +1783,31 @@ impl api::IncomingWebhook for Stripe { ) } stripe::WebhookEventObjectType::Refund => { - api_models::webhooks::ObjectReferenceId::RefundId( - api_models::webhooks::RefundIdType::ConnectorRefundId( - details.event_data.event_object.id, + match details.event_data.event_object.metadata { + // if meta_data is present + Some(meta_data) => { + // Issue: 2076 + match meta_data.is_refund_id_as_reference { + // if the order_id is refund_id + Some(_) => api_models::webhooks::ObjectReferenceId::RefundId( + api_models::webhooks::RefundIdType::RefundId(meta_data.order_id), + ), + // if the order_id is payment_id + // since payment_id was being passed before the deployment of this pr + _ => api_models::webhooks::ObjectReferenceId::RefundId( + api_models::webhooks::RefundIdType::ConnectorRefundId( + details.event_data.event_object.id, + ), + ), + } + } + // else use connector_transaction_id + None => api_models::webhooks::ObjectReferenceId::RefundId( + api_models::webhooks::RefundIdType::ConnectorRefundId( + details.event_data.event_object.id, + ), ), - ) + } } }) } diff --git a/crates/router/src/connector/stripe/transformers.rs b/crates/router/src/connector/stripe/transformers.rs index ef23f4ddab..9dc6689f46 100644 --- a/crates/router/src/connector/stripe/transformers.rs +++ b/crates/router/src/connector/stripe/transformers.rs @@ -96,12 +96,8 @@ pub struct PaymentIntentRequest { pub currency: String, pub statement_descriptor_suffix: Option, pub statement_descriptor: Option, - #[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, + #[serde(flatten)] + pub meta_data: StripeMetadata, pub return_url: String, pub confirm: bool, pub mandate: Option>, @@ -124,6 +120,21 @@ pub struct PaymentIntentRequest { pub payment_method_types: Option, } +// Field rename is required only in case of serialization as it is passed in the request to the connector. +// Deserialization is happening only in case of webhooks, where fields name should be used as defined in the struct. +// Whenever adding new fields, Please ensure it doesn't break the webhook flow +#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)] +pub struct StripeMetadata { + // merchant_reference_id + #[serde(rename(serialize = "metadata[order_id]"))] + pub order_id: String, + // to check whether the order_id is refund_id or payemnt_id + // before deployment, order id is set to payemnt_id in refunds but now it is set as refund_id + // it is set as string instead of bool because stripe pass it as string even if we set it as bool + #[serde(rename(serialize = "metadata[is_refund_id_as_reference]"))] + pub is_refund_id_as_reference: Option, +} + #[derive(Debug, Eq, PartialEq, Serialize)] pub struct SetupIntentRequest { #[serde(rename = "metadata[order_id]")] @@ -1537,9 +1548,7 @@ impl TryFrom<&payments::GooglePayWalletData> for StripePaymentMethodData { impl TryFrom<&types::PaymentsAuthorizeRouterData> for PaymentIntentRequest { type Error = error_stack::Report; fn try_from(item: &types::PaymentsAuthorizeRouterData) -> 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(); //Fetch autogenerated txn_uuid from Database. + let order_id = item.connector_request_reference_id.clone(); let shipping_address = match item.address.shipping.clone() { Some(mut shipping) => StripeShippingAddress { @@ -1720,9 +1729,10 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for PaymentIntentRequest { 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(), - metadata_order_id, - metadata_txn_id, - metadata_txn_uuid, + meta_data: StripeMetadata { + order_id, + is_refund_id_as_reference: None, + }, return_url: item .request .router_return_url @@ -1838,13 +1848,6 @@ impl TryFrom<&types::ConnectorCustomerRouterData> for CustomerRequest { } } -#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)] -pub struct StripeMetadata { - pub order_id: String, - pub txn_id: String, - pub txn_uuid: String, -} - #[derive(Clone, Default, Debug, Eq, PartialEq, Deserialize, Serialize)] #[serde(rename_all = "snake_case")] pub enum StripePaymentStatus { @@ -2505,31 +2508,26 @@ pub struct BacsFinancialDetails { // REFUND : // Type definition for Stripe RefundRequest -#[derive(Default, Debug, Serialize)] +#[derive(Debug, Serialize)] pub struct RefundRequest { pub amount: Option, //amount in cents, hence passed as integer pub payment_intent: String, - #[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, + #[serde(flatten)] + pub meta_data: StripeMetadata, } impl TryFrom<&types::RefundsRouterData> for RefundRequest { type Error = error_stack::Report; fn try_from(item: &types::RefundsRouterData) -> Result { let amount = item.request.refund_amount; - let metadata_txn_id = "Fetch txn_id from DB".to_string(); - let metadata_txn_uuid = "Fetch txn_id from DB".to_string(); let payment_intent = item.request.connector_transaction_id.clone(); Ok(Self { amount: Some(amount), payment_intent, - metadata_order_id: item.payment_id.clone(), - metadata_txn_id, - metadata_txn_uuid, + meta_data: StripeMetadata { + order_id: item.request.refund_id.clone(), + is_refund_id_as_reference: Some("true".to_string()), + }, }) } } @@ -3037,6 +3035,7 @@ pub struct WebhookEventObjectData { pub created: PrimitiveDateTime, pub evidence_details: Option, pub status: Option, + pub metadata: Option, } #[derive(Debug, Deserialize, strum::Display)]