refactor(connector): [Stripe] Using connector_request_reference_id as object_reference_id for Webhooks (#2064)

This commit is contained in:
Sakil Mostak
2023-09-08 15:13:49 +05:30
committed by GitHub
parent 517c5c4165
commit e659e7029e
2 changed files with 84 additions and 41 deletions

View File

@ -1733,14 +1733,38 @@ impl api::IncomingWebhook for Stripe {
Ok(match details.event_data.event_object.object { Ok(match details.event_data.event_object.object {
stripe::WebhookEventObjectType::PaymentIntent => { stripe::WebhookEventObjectType::PaymentIntent => {
api_models::webhooks::ObjectReferenceId::PaymentId( match details.event_data.event_object.metadata {
api_models::payments::PaymentIdType::ConnectorTransactionId( // if order_id is present
details.event_data.event_object.id, 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::Charge | stripe::WebhookEventObjectType::Dispute => { 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::webhooks::ObjectReferenceId::PaymentId(
api_models::payments::PaymentIdType::ConnectorTransactionId( api_models::payments::PaymentIdType::ConnectorTransactionId(
details details
@ -1759,11 +1783,31 @@ impl api::IncomingWebhook for Stripe {
) )
} }
stripe::WebhookEventObjectType::Refund => { stripe::WebhookEventObjectType::Refund => {
api_models::webhooks::ObjectReferenceId::RefundId( match details.event_data.event_object.metadata {
api_models::webhooks::RefundIdType::ConnectorRefundId( // if meta_data is present
details.event_data.event_object.id, 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,
),
), ),
) }
} }
}) })
} }

View File

@ -96,12 +96,8 @@ pub struct PaymentIntentRequest {
pub currency: String, pub currency: String,
pub statement_descriptor_suffix: Option<String>, pub statement_descriptor_suffix: Option<String>,
pub statement_descriptor: Option<String>, pub statement_descriptor: Option<String>,
#[serde(rename = "metadata[order_id]")] #[serde(flatten)]
pub metadata_order_id: String, pub meta_data: StripeMetadata,
#[serde(rename = "metadata[txn_id]")]
pub metadata_txn_id: String,
#[serde(rename = "metadata[txn_uuid]")]
pub metadata_txn_uuid: String,
pub return_url: String, pub return_url: String,
pub confirm: bool, pub confirm: bool,
pub mandate: Option<Secret<String>>, pub mandate: Option<Secret<String>>,
@ -124,6 +120,21 @@ pub struct PaymentIntentRequest {
pub payment_method_types: Option<StripePaymentMethodType>, pub payment_method_types: Option<StripePaymentMethodType>,
} }
// 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<String>,
}
#[derive(Debug, Eq, PartialEq, Serialize)] #[derive(Debug, Eq, PartialEq, Serialize)]
pub struct SetupIntentRequest { pub struct SetupIntentRequest {
#[serde(rename = "metadata[order_id]")] #[serde(rename = "metadata[order_id]")]
@ -1537,9 +1548,7 @@ impl TryFrom<&payments::GooglePayWalletData> for StripePaymentMethodData {
impl TryFrom<&types::PaymentsAuthorizeRouterData> for PaymentIntentRequest { impl TryFrom<&types::PaymentsAuthorizeRouterData> for PaymentIntentRequest {
type Error = error_stack::Report<errors::ConnectorError>; type Error = error_stack::Report<errors::ConnectorError>;
fn try_from(item: &types::PaymentsAuthorizeRouterData) -> Result<Self, Self::Error> { fn try_from(item: &types::PaymentsAuthorizeRouterData) -> Result<Self, Self::Error> {
let metadata_order_id = item.connector_request_reference_id.clone(); let 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 shipping_address = match item.address.shipping.clone() { let shipping_address = match item.address.shipping.clone() {
Some(mut shipping) => StripeShippingAddress { 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 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_suffix: item.request.statement_descriptor_suffix.clone(),
statement_descriptor: item.request.statement_descriptor.clone(), statement_descriptor: item.request.statement_descriptor.clone(),
metadata_order_id, meta_data: StripeMetadata {
metadata_txn_id, order_id,
metadata_txn_uuid, is_refund_id_as_reference: None,
},
return_url: item return_url: item
.request .request
.router_return_url .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)] #[derive(Clone, Default, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
pub enum StripePaymentStatus { pub enum StripePaymentStatus {
@ -2505,31 +2508,26 @@ pub struct BacsFinancialDetails {
// REFUND : // REFUND :
// Type definition for Stripe RefundRequest // Type definition for Stripe RefundRequest
#[derive(Default, Debug, Serialize)] #[derive(Debug, Serialize)]
pub struct RefundRequest { pub struct RefundRequest {
pub amount: Option<i64>, //amount in cents, hence passed as integer pub amount: Option<i64>, //amount in cents, hence passed as integer
pub payment_intent: String, pub payment_intent: String,
#[serde(rename = "metadata[order_id]")] #[serde(flatten)]
pub metadata_order_id: String, pub meta_data: StripeMetadata,
#[serde(rename = "metadata[txn_id]")]
pub metadata_txn_id: String,
#[serde(rename = "metadata[txn_uuid]")]
pub metadata_txn_uuid: String,
} }
impl<F> TryFrom<&types::RefundsRouterData<F>> for RefundRequest { impl<F> TryFrom<&types::RefundsRouterData<F>> for RefundRequest {
type Error = error_stack::Report<errors::ConnectorError>; type Error = error_stack::Report<errors::ConnectorError>;
fn try_from(item: &types::RefundsRouterData<F>) -> Result<Self, Self::Error> { fn try_from(item: &types::RefundsRouterData<F>) -> Result<Self, Self::Error> {
let amount = item.request.refund_amount; 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(); let payment_intent = item.request.connector_transaction_id.clone();
Ok(Self { Ok(Self {
amount: Some(amount), amount: Some(amount),
payment_intent, payment_intent,
metadata_order_id: item.payment_id.clone(), meta_data: StripeMetadata {
metadata_txn_id, order_id: item.request.refund_id.clone(),
metadata_txn_uuid, is_refund_id_as_reference: Some("true".to_string()),
},
}) })
} }
} }
@ -3037,6 +3035,7 @@ pub struct WebhookEventObjectData {
pub created: PrimitiveDateTime, pub created: PrimitiveDateTime,
pub evidence_details: Option<EvidenceDetails>, pub evidence_details: Option<EvidenceDetails>,
pub status: Option<WebhookEventStatus>, pub status: Option<WebhookEventStatus>,
pub metadata: Option<StripeMetadata>,
} }
#[derive(Debug, Deserialize, strum::Display)] #[derive(Debug, Deserialize, strum::Display)]