mirror of
				https://github.com/juspay/hyperswitch.git
				synced 2025-10-31 10:06:32 +08:00 
			
		
		
		
	feat(connector): add dispute webhooks for Stripe (#918)
This commit is contained in:
		| @ -792,7 +792,7 @@ impl api::IncomingWebhook for Adyen { | ||||
|             connector_reason_code: notif.additional_data.chargeback_reason_code, | ||||
|             challenge_required_by: notif.additional_data.defense_period_ends_at, | ||||
|             connector_status: notif.event_code.to_string(), | ||||
|             created_at: notif.event_date.clone(), | ||||
|             created_at: notif.event_date, | ||||
|             updated_at: notif.event_date, | ||||
|         }) | ||||
|     } | ||||
|  | ||||
| @ -2,6 +2,7 @@ use api_models::{enums::DisputeStage, webhooks::IncomingWebhookEvent}; | ||||
| use masking::PeekInterface; | ||||
| use reqwest::Url; | ||||
| use serde::{Deserialize, Serialize}; | ||||
| use time::PrimitiveDateTime; | ||||
|  | ||||
| use crate::{ | ||||
|     connector::utils::PaymentsAuthorizeRequestData, | ||||
| @ -1553,7 +1554,8 @@ pub struct AdyenAdditionalDataWH { | ||||
|     pub hmac_signature: String, | ||||
|     pub dispute_status: Option<DisputeStatus>, | ||||
|     pub chargeback_reason_code: Option<String>, | ||||
|     pub defense_period_ends_at: Option<String>, | ||||
|     #[serde(default, with = "common_utils::custom_serde::iso8601::option")] | ||||
|     pub defense_period_ends_at: Option<PrimitiveDateTime>, | ||||
| } | ||||
|  | ||||
| #[derive(Debug, Deserialize)] | ||||
| @ -1653,7 +1655,8 @@ pub struct AdyenNotificationRequestItemWH { | ||||
|     pub merchant_reference: String, | ||||
|     pub success: String, | ||||
|     pub reason: Option<String>, | ||||
|     pub event_date: Option<String>, | ||||
|     #[serde(default, with = "common_utils::custom_serde::iso8601::option")] | ||||
|     pub event_date: Option<PrimitiveDateTime>, | ||||
| } | ||||
|  | ||||
| #[derive(Debug, Deserialize)] | ||||
|  | ||||
| @ -1083,7 +1083,7 @@ impl api::IncomingWebhook for Checkout { | ||||
|             .parse_struct("CheckoutWebhookBody") | ||||
|             .change_context(errors::ConnectorError::WebhookReferenceIdNotFound)?; | ||||
|  | ||||
|         if checkout::is_chargeback_event(&details.txn_type) { | ||||
|         if checkout::is_chargeback_event(&details.transaction_type) { | ||||
|             return Ok(api_models::webhooks::ObjectReferenceId::PaymentId( | ||||
|                 api_models::payments::PaymentIdType::ConnectorTransactionId( | ||||
|                     details | ||||
| @ -1093,7 +1093,7 @@ impl api::IncomingWebhook for Checkout { | ||||
|                 ), | ||||
|             )); | ||||
|         } | ||||
|         if checkout::is_refund_event(&details.txn_type) { | ||||
|         if checkout::is_refund_event(&details.transaction_type) { | ||||
|             return Ok(api_models::webhooks::ObjectReferenceId::RefundId( | ||||
|                 api_models::webhooks::RefundIdType::ConnectorRefundId( | ||||
|                     details | ||||
| @ -1117,7 +1117,7 @@ impl api::IncomingWebhook for Checkout { | ||||
|             .parse_struct("CheckoutWebhookBody") | ||||
|             .change_context(errors::ConnectorError::WebhookEventTypeNotFound)?; | ||||
|  | ||||
|         Ok(api::IncomingWebhookEvent::from(details.txn_type)) | ||||
|         Ok(api::IncomingWebhookEvent::from(details.transaction_type)) | ||||
|     } | ||||
|  | ||||
|     fn get_webhook_resource_object( | ||||
| @ -1143,12 +1143,14 @@ impl api::IncomingWebhook for Checkout { | ||||
|         Ok(api::disputes::DisputePayload { | ||||
|             amount: dispute_details.data.amount.to_string(), | ||||
|             currency: dispute_details.data.currency, | ||||
|             dispute_stage: api_models::enums::DisputeStage::from(dispute_details.txn_type.clone()), | ||||
|             dispute_stage: api_models::enums::DisputeStage::from( | ||||
|                 dispute_details.transaction_type.clone(), | ||||
|             ), | ||||
|             connector_dispute_id: dispute_details.data.id, | ||||
|             connector_reason: None, | ||||
|             connector_reason_code: dispute_details.data.reason_code, | ||||
|             challenge_required_by: dispute_details.data.evidence_required_by, | ||||
|             connector_status: dispute_details.txn_type.to_string(), | ||||
|             connector_status: dispute_details.transaction_type.to_string(), | ||||
|             created_at: dispute_details.created_on, | ||||
|             updated_at: dispute_details.data.date, | ||||
|         }) | ||||
|  | ||||
| @ -1,6 +1,7 @@ | ||||
| use common_utils::errors::CustomResult; | ||||
| use error_stack::{IntoReport, ResultExt}; | ||||
| use serde::{Deserialize, Serialize}; | ||||
| use time::PrimitiveDateTime; | ||||
| use url::Url; | ||||
|  | ||||
| use crate::{ | ||||
| @ -674,27 +675,27 @@ impl From<CheckoutRedirectResponseStatus> for enums::AttemptStatus { | ||||
|     } | ||||
| } | ||||
|  | ||||
| pub fn is_refund_event(event_code: &CheckoutTxnType) -> bool { | ||||
| pub fn is_refund_event(event_code: &CheckoutTransactionType) -> bool { | ||||
|     matches!( | ||||
|         event_code, | ||||
|         CheckoutTxnType::PaymentRefunded | CheckoutTxnType::PaymentRefundDeclined | ||||
|         CheckoutTransactionType::PaymentRefunded | CheckoutTransactionType::PaymentRefundDeclined | ||||
|     ) | ||||
| } | ||||
|  | ||||
| pub fn is_chargeback_event(event_code: &CheckoutTxnType) -> bool { | ||||
| pub fn is_chargeback_event(event_code: &CheckoutTransactionType) -> bool { | ||||
|     matches!( | ||||
|         event_code, | ||||
|         CheckoutTxnType::DisputeReceived | ||||
|             | CheckoutTxnType::DisputeExpired | ||||
|             | CheckoutTxnType::DisputeAccepted | ||||
|             | CheckoutTxnType::DisputeCanceled | ||||
|             | CheckoutTxnType::DisputeEvidenceSubmitted | ||||
|             | CheckoutTxnType::DisputeEvidenceAcknowledgedByScheme | ||||
|             | CheckoutTxnType::DisputeEvidenceRequired | ||||
|             | CheckoutTxnType::DisputeArbitrationLost | ||||
|             | CheckoutTxnType::DisputeArbitrationWon | ||||
|             | CheckoutTxnType::DisputeWon | ||||
|             | CheckoutTxnType::DisputeLost | ||||
|         CheckoutTransactionType::DisputeReceived | ||||
|             | CheckoutTransactionType::DisputeExpired | ||||
|             | CheckoutTransactionType::DisputeAccepted | ||||
|             | CheckoutTransactionType::DisputeCanceled | ||||
|             | CheckoutTransactionType::DisputeEvidenceSubmitted | ||||
|             | CheckoutTransactionType::DisputeEvidenceAcknowledgedByScheme | ||||
|             | CheckoutTransactionType::DisputeEvidenceRequired | ||||
|             | CheckoutTransactionType::DisputeArbitrationLost | ||||
|             | CheckoutTransactionType::DisputeArbitrationWon | ||||
|             | CheckoutTransactionType::DisputeWon | ||||
|             | CheckoutTransactionType::DisputeLost | ||||
|     ) | ||||
| } | ||||
|  | ||||
| @ -705,20 +706,20 @@ pub struct CheckoutWebhookData { | ||||
|     pub action_id: Option<String>, | ||||
|     pub amount: i32, | ||||
|     pub currency: String, | ||||
|     pub evidence_required_by: Option<String>, | ||||
|     pub evidence_required_by: Option<PrimitiveDateTime>, | ||||
|     pub reason_code: Option<String>, | ||||
|     pub date: Option<String>, | ||||
|     pub date: Option<PrimitiveDateTime>, | ||||
| } | ||||
| #[derive(Debug, Deserialize)] | ||||
| pub struct CheckoutWebhookBody { | ||||
|     #[serde(rename = "type")] | ||||
|     pub txn_type: CheckoutTxnType, | ||||
|     pub transaction_type: CheckoutTransactionType, | ||||
|     pub data: CheckoutWebhookData, | ||||
|     pub created_on: Option<String>, | ||||
|     pub created_on: Option<PrimitiveDateTime>, | ||||
| } | ||||
| #[derive(Debug, Deserialize, strum::Display, Clone)] | ||||
| #[serde(rename_all = "snake_case")] | ||||
| pub enum CheckoutTxnType { | ||||
| pub enum CheckoutTransactionType { | ||||
|     PaymentApproved, | ||||
|     PaymentDeclined, | ||||
|     PaymentRefunded, | ||||
| @ -736,37 +737,35 @@ pub enum CheckoutTxnType { | ||||
|     DisputeLost, | ||||
| } | ||||
|  | ||||
| impl From<CheckoutTxnType> for api::IncomingWebhookEvent { | ||||
|     fn from(txn_type: CheckoutTxnType) -> Self { | ||||
|         match txn_type { | ||||
|             CheckoutTxnType::PaymentApproved => Self::PaymentIntentSuccess, | ||||
|             CheckoutTxnType::PaymentDeclined => Self::PaymentIntentSuccess, | ||||
|             CheckoutTxnType::PaymentRefunded => Self::RefundSuccess, | ||||
|             CheckoutTxnType::PaymentRefundDeclined => Self::RefundFailure, | ||||
|             CheckoutTxnType::DisputeReceived | CheckoutTxnType::DisputeEvidenceRequired => { | ||||
|                 Self::DisputeOpened | ||||
|             } | ||||
|             CheckoutTxnType::DisputeExpired => Self::DisputeExpired, | ||||
|             CheckoutTxnType::DisputeAccepted => Self::DisputeAccepted, | ||||
|             CheckoutTxnType::DisputeCanceled => Self::DisputeCancelled, | ||||
|             CheckoutTxnType::DisputeEvidenceSubmitted | ||||
|             | CheckoutTxnType::DisputeEvidenceAcknowledgedByScheme => Self::DisputeChallenged, | ||||
|             CheckoutTxnType::DisputeWon | CheckoutTxnType::DisputeArbitrationWon => { | ||||
|                 Self::DisputeWon | ||||
|             } | ||||
|             CheckoutTxnType::DisputeLost | CheckoutTxnType::DisputeArbitrationLost => { | ||||
|                 Self::DisputeLost | ||||
| impl From<CheckoutTransactionType> for api::IncomingWebhookEvent { | ||||
|     fn from(transaction_type: CheckoutTransactionType) -> Self { | ||||
|         match transaction_type { | ||||
|             CheckoutTransactionType::PaymentApproved => Self::PaymentIntentSuccess, | ||||
|             CheckoutTransactionType::PaymentDeclined => Self::PaymentIntentSuccess, | ||||
|             CheckoutTransactionType::PaymentRefunded => Self::RefundSuccess, | ||||
|             CheckoutTransactionType::PaymentRefundDeclined => Self::RefundFailure, | ||||
|             CheckoutTransactionType::DisputeReceived | ||||
|             | CheckoutTransactionType::DisputeEvidenceRequired => Self::DisputeOpened, | ||||
|             CheckoutTransactionType::DisputeExpired => Self::DisputeExpired, | ||||
|             CheckoutTransactionType::DisputeAccepted => Self::DisputeAccepted, | ||||
|             CheckoutTransactionType::DisputeCanceled => Self::DisputeCancelled, | ||||
|             CheckoutTransactionType::DisputeEvidenceSubmitted | ||||
|             | CheckoutTransactionType::DisputeEvidenceAcknowledgedByScheme => { | ||||
|                 Self::DisputeChallenged | ||||
|             } | ||||
|             CheckoutTransactionType::DisputeWon | ||||
|             | CheckoutTransactionType::DisputeArbitrationWon => Self::DisputeWon, | ||||
|             CheckoutTransactionType::DisputeLost | ||||
|             | CheckoutTransactionType::DisputeArbitrationLost => Self::DisputeLost, | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl From<CheckoutTxnType> for api_models::enums::DisputeStage { | ||||
|     fn from(code: CheckoutTxnType) -> Self { | ||||
| impl From<CheckoutTransactionType> for api_models::enums::DisputeStage { | ||||
|     fn from(code: CheckoutTransactionType) -> Self { | ||||
|         match code { | ||||
|             CheckoutTxnType::DisputeArbitrationLost | CheckoutTxnType::DisputeArbitrationWon => { | ||||
|                 Self::PreArbitration | ||||
|             } | ||||
|             CheckoutTransactionType::DisputeArbitrationLost | ||||
|             | CheckoutTransactionType::DisputeArbitrationWon => Self::PreArbitration, | ||||
|             _ => Self::Dispute, | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @ -1284,28 +1284,58 @@ impl api::IncomingWebhook for Stripe { | ||||
|         &self, | ||||
|         request: &api::IncomingWebhookRequestDetails<'_>, | ||||
|     ) -> CustomResult<api_models::webhooks::ObjectReferenceId, errors::ConnectorError> { | ||||
|         let details: stripe::StripeWebhookObjectId = request | ||||
|         let details: stripe::WebhookEvent = request | ||||
|             .body | ||||
|             .parse_struct("StripeWebhookObjectId") | ||||
|             .parse_struct("WebhookEvent") | ||||
|             .change_context(errors::ConnectorError::WebhookReferenceIdNotFound)?; | ||||
|  | ||||
|         Ok(api_models::webhooks::ObjectReferenceId::PaymentId( | ||||
|             api_models::payments::PaymentIdType::ConnectorTransactionId(details.data.object.id), | ||||
|         )) | ||||
|         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, | ||||
|                     ), | ||||
|                 ) | ||||
|             } | ||||
|             stripe::WebhookEventObjectType::Dispute => { | ||||
|                 api_models::webhooks::ObjectReferenceId::PaymentId( | ||||
|                     api_models::payments::PaymentIdType::ConnectorTransactionId( | ||||
|                         details | ||||
|                             .event_data | ||||
|                             .event_object | ||||
|                             .payment_intent | ||||
|                             .ok_or(errors::ConnectorError::WebhookReferenceIdNotFound)?, | ||||
|                     ), | ||||
|                 ) | ||||
|             } | ||||
|             _ => Err(errors::ConnectorError::WebhookReferenceIdNotFound)?, | ||||
|         }) | ||||
|     } | ||||
|  | ||||
|     fn get_webhook_event_type( | ||||
|         &self, | ||||
|         request: &api::IncomingWebhookRequestDetails<'_>, | ||||
|     ) -> CustomResult<api::IncomingWebhookEvent, errors::ConnectorError> { | ||||
|         let details: stripe::StripeWebhookObjectEventType = request | ||||
|         let details: stripe::WebhookEvent = request | ||||
|             .body | ||||
|             .parse_struct("StripeWebhookObjectEventType") | ||||
|             .change_context(errors::ConnectorError::WebhookEventTypeNotFound)?; | ||||
|  | ||||
|         Ok(match details.event_type.as_str() { | ||||
|             "payment_intent.payment_failed" => api::IncomingWebhookEvent::PaymentIntentFailure, | ||||
|             "payment_intent.succeeded" => api::IncomingWebhookEvent::PaymentIntentSuccess, | ||||
|             .parse_struct("WebhookEvent") | ||||
|             .change_context(errors::ConnectorError::WebhookReferenceIdNotFound)?; | ||||
|         Ok(match details.event_type { | ||||
|             stripe::WebhookEventType::PaymentIntentFailed => { | ||||
|                 api::IncomingWebhookEvent::PaymentIntentFailure | ||||
|             } | ||||
|             stripe::WebhookEventType::PaymentIntentSucceed => { | ||||
|                 api::IncomingWebhookEvent::PaymentIntentSuccess | ||||
|             } | ||||
|             stripe::WebhookEventType::DisputeCreated => api::IncomingWebhookEvent::DisputeOpened, | ||||
|             stripe::WebhookEventType::DisputeClosed => api::IncomingWebhookEvent::DisputeCancelled, | ||||
|             stripe::WebhookEventType::DisputeUpdated => api::IncomingWebhookEvent::try_from( | ||||
|                 details | ||||
|                     .event_data | ||||
|                     .event_object | ||||
|                     .status | ||||
|                     .ok_or(errors::ConnectorError::WebhookEventTypeNotFound)?, | ||||
|             )?, | ||||
|             _ => Err(errors::ConnectorError::WebhookEventTypeNotFound).into_report()?, | ||||
|         }) | ||||
|     } | ||||
| @ -1314,13 +1344,43 @@ impl api::IncomingWebhook for Stripe { | ||||
|         &self, | ||||
|         request: &api::IncomingWebhookRequestDetails<'_>, | ||||
|     ) -> CustomResult<serde_json::Value, errors::ConnectorError> { | ||||
|         let details: stripe::StripeWebhookObjectResource = request | ||||
|         let details: stripe::WebhookEventObjectResource = request | ||||
|             .body | ||||
|             .parse_struct("StripeWebhookObjectResource") | ||||
|             .parse_struct("WebhookEventObjectResource") | ||||
|             .change_context(errors::ConnectorError::WebhookResourceObjectNotFound)?; | ||||
|  | ||||
|         Ok(details.data.object) | ||||
|     } | ||||
|     fn get_dispute_details( | ||||
|         &self, | ||||
|         request: &api::IncomingWebhookRequestDetails<'_>, | ||||
|     ) -> CustomResult<api::disputes::DisputePayload, errors::ConnectorError> { | ||||
|         let details: stripe::WebhookEvent = request | ||||
|             .body | ||||
|             .parse_struct("WebhookEvent") | ||||
|             .change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?; | ||||
|         Ok(api::disputes::DisputePayload { | ||||
|             amount: details.event_data.event_object.amount.to_string(), | ||||
|             currency: details.event_data.event_object.currency, | ||||
|             dispute_stage: api_models::enums::DisputeStage::Dispute, | ||||
|             connector_dispute_id: details.event_data.event_object.id, | ||||
|             connector_reason: details.event_data.event_object.reason, | ||||
|             connector_reason_code: None, | ||||
|             challenge_required_by: details | ||||
|                 .event_data | ||||
|                 .event_object | ||||
|                 .evidence_details | ||||
|                 .map(|payload| payload.due_by), | ||||
|             connector_status: details | ||||
|                 .event_data | ||||
|                 .event_object | ||||
|                 .status | ||||
|                 .ok_or(errors::ConnectorError::WebhookResourceObjectNotFound)? | ||||
|                 .to_string(), | ||||
|             created_at: Some(details.event_data.event_object.created), | ||||
|             updated_at: None, | ||||
|         }) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl services::ConnectorRedirectResponse for Stripe { | ||||
|  | ||||
| @ -4,6 +4,7 @@ use common_utils::{errors::CustomResult, pii}; | ||||
| use error_stack::{IntoReport, ResultExt}; | ||||
| use masking::{ExposeInterface, ExposeOptionInterface, Secret}; | ||||
| use serde::{Deserialize, Serialize}; | ||||
| use time::PrimitiveDateTime; | ||||
| use url::Url; | ||||
| use uuid::Uuid; | ||||
|  | ||||
| @ -357,6 +358,20 @@ pub enum StripeBankNames { | ||||
|     VanLanschot, | ||||
| } | ||||
|  | ||||
| impl TryFrom<WebhookEventStatus> for api_models::webhooks::IncomingWebhookEvent { | ||||
|     type Error = errors::ConnectorError; | ||||
|     fn try_from(value: WebhookEventStatus) -> Result<Self, Self::Error> { | ||||
|         Ok(match value { | ||||
|             WebhookEventStatus::WarningNeedsResponse => Self::DisputeOpened, | ||||
|             WebhookEventStatus::WarningClosed => Self::DisputeCancelled, | ||||
|             WebhookEventStatus::WarningUnderReview => Self::DisputeChallenged, | ||||
|             WebhookEventStatus::Won => Self::DisputeWon, | ||||
|             WebhookEventStatus::Lost => Self::DisputeLost, | ||||
|             _ => Err(errors::ConnectorError::WebhookEventTypeNotFound)?, | ||||
|         }) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl TryFrom<&api_models::enums::BankNames> for StripeBankNames { | ||||
|     type Error = errors::ConnectorError; | ||||
|     fn try_from(bank: &api_models::enums::BankNames) -> Result<Self, Self::Error> { | ||||
| @ -1566,34 +1581,119 @@ impl<F, T> | ||||
| // } | ||||
|  | ||||
| #[derive(Debug, Deserialize)] | ||||
| pub struct StripeWebhookDataObjectId { | ||||
|     pub id: String, | ||||
| } | ||||
|  | ||||
| #[derive(Debug, Deserialize)] | ||||
| pub struct StripeWebhookDataId { | ||||
|     pub object: StripeWebhookDataObjectId, | ||||
| } | ||||
|  | ||||
| #[derive(Debug, Deserialize)] | ||||
| pub struct StripeWebhookDataResource { | ||||
| pub struct WebhookEventDataResource { | ||||
|     pub object: serde_json::Value, | ||||
| } | ||||
|  | ||||
| #[derive(Debug, Deserialize)] | ||||
| pub struct StripeWebhookObjectResource { | ||||
|     pub data: StripeWebhookDataResource, | ||||
| pub struct WebhookEventObjectResource { | ||||
|     pub data: WebhookEventDataResource, | ||||
| } | ||||
|  | ||||
| #[derive(Debug, Deserialize)] | ||||
| pub struct StripeWebhookObjectEventType { | ||||
| pub struct WebhookEvent { | ||||
|     #[serde(rename = "type")] | ||||
|     pub event_type: String, | ||||
|     pub event_type: WebhookEventType, | ||||
|     #[serde(rename = "data")] | ||||
|     pub event_data: WebhookEventData, | ||||
| } | ||||
|  | ||||
| #[derive(Debug, Deserialize)] | ||||
| pub struct StripeWebhookObjectId { | ||||
|     pub data: StripeWebhookDataId, | ||||
| pub struct WebhookEventData { | ||||
|     #[serde(rename = "object")] | ||||
|     pub event_object: WebhookEventObjectData, | ||||
| } | ||||
|  | ||||
| #[derive(Debug, Deserialize)] | ||||
| pub struct WebhookEventObjectData { | ||||
|     pub id: String, | ||||
|     pub object: WebhookEventObjectType, | ||||
|     pub amount: i32, | ||||
|     pub currency: String, | ||||
|     pub payment_intent: Option<String>, | ||||
|     pub reason: Option<String>, | ||||
|     #[serde(with = "common_utils::custom_serde::timestamp")] | ||||
|     pub created: PrimitiveDateTime, | ||||
|     pub evidence_details: Option<EvidenceDetails>, | ||||
|     pub status: Option<WebhookEventStatus>, | ||||
| } | ||||
|  | ||||
| #[derive(Debug, Deserialize, strum::Display)] | ||||
| #[serde(rename_all = "snake_case")] | ||||
| pub enum WebhookEventObjectType { | ||||
|     PaymentIntent, | ||||
|     Dispute, | ||||
|     Charge, | ||||
| } | ||||
|  | ||||
| #[derive(Debug, Deserialize)] | ||||
| pub enum WebhookEventType { | ||||
|     #[serde(rename = "payment_intent.payment_failed")] | ||||
|     PaymentIntentFailed, | ||||
|     #[serde(rename = "payment_intent.succeeded")] | ||||
|     PaymentIntentSucceed, | ||||
|     #[serde(rename = "charge.dispute.captured")] | ||||
|     ChargeDisputeCaptured, | ||||
|     #[serde(rename = "charge.dispute.created")] | ||||
|     DisputeCreated, | ||||
|     #[serde(rename = "charge.dispute.closed")] | ||||
|     DisputeClosed, | ||||
|     #[serde(rename = "charge.dispute.updated")] | ||||
|     DisputeUpdated, | ||||
|     #[serde(rename = "charge.dispute.funds_reinstated")] | ||||
|     ChargeDisputeFundsReinstated, | ||||
|     #[serde(rename = "charge.dispute.funds_withdrawn")] | ||||
|     ChargeDisputeFundsWithdrawn, | ||||
|     #[serde(rename = "charge.expired")] | ||||
|     ChargeExpired, | ||||
|     #[serde(rename = "charge.failed")] | ||||
|     ChargeFailed, | ||||
|     #[serde(rename = "charge.pending")] | ||||
|     ChargePending, | ||||
|     #[serde(rename = "charge.captured")] | ||||
|     ChargeCaptured, | ||||
|     #[serde(rename = "charge.succeeded")] | ||||
|     ChargeSucceeded, | ||||
|     #[serde(rename = "charge.updated")] | ||||
|     ChargeUpdated, | ||||
|     #[serde(rename = "charge.refunded")] | ||||
|     ChanrgeRefunded, | ||||
|     #[serde(rename = "payment_intent.canceled")] | ||||
|     PaymentIntentCanceled, | ||||
|     #[serde(rename = "payment_intent.created")] | ||||
|     PaymentIntentCreated, | ||||
|     #[serde(rename = "payment_intent.processing")] | ||||
|     PaymentIntentProcessing, | ||||
|     #[serde(rename = "payment_intent.requires_action")] | ||||
|     PaymentIntentRequiresAction, | ||||
|     #[serde(rename = "amount_capturable_updated")] | ||||
|     PaymentIntentAmountCapturableUpdated, | ||||
| } | ||||
|  | ||||
| #[derive(Debug, Serialize, strum::Display, Deserialize, PartialEq)] | ||||
| #[serde(rename_all = "snake_case")] | ||||
| pub enum WebhookEventStatus { | ||||
|     WarningNeedsResponse, | ||||
|     WarningClosed, | ||||
|     WarningUnderReview, | ||||
|     Won, | ||||
|     Lost, | ||||
|     NeedsResponse, | ||||
|     UnderReview, | ||||
|     ChargeRefunded, | ||||
|     Succeeded, | ||||
|     RequiresPaymentMethod, | ||||
|     RequiresConfirmation, | ||||
|     RequiresAction, | ||||
|     Processing, | ||||
|     RequiresCapture, | ||||
|     Canceled, | ||||
| } | ||||
|  | ||||
| #[derive(Debug, Deserialize, PartialEq)] | ||||
| pub struct EvidenceDetails { | ||||
|     #[serde(with = "common_utils::custom_serde::timestamp")] | ||||
|     pub due_by: PrimitiveDateTime, | ||||
| } | ||||
|  | ||||
| impl | ||||
|  | ||||
| @ -1,4 +1,5 @@ | ||||
| use masking::{Deserialize, Serialize}; | ||||
| use time::PrimitiveDateTime; | ||||
|  | ||||
| use crate::{services, types}; | ||||
|  | ||||
| @ -7,7 +8,7 @@ pub struct DisputeId { | ||||
|     pub dispute_id: String, | ||||
| } | ||||
|  | ||||
| #[derive(Default, Debug, Deserialize)] | ||||
| #[derive(Default, Debug)] | ||||
| pub struct DisputePayload { | ||||
|     pub amount: String, | ||||
|     pub currency: String, | ||||
| @ -16,9 +17,9 @@ pub struct DisputePayload { | ||||
|     pub connector_dispute_id: String, | ||||
|     pub connector_reason: Option<String>, | ||||
|     pub connector_reason_code: Option<String>, | ||||
|     pub challenge_required_by: Option<String>, | ||||
|     pub created_at: Option<String>, | ||||
|     pub updated_at: Option<String>, | ||||
|     pub challenge_required_by: Option<PrimitiveDateTime>, | ||||
|     pub created_at: Option<PrimitiveDateTime>, | ||||
|     pub updated_at: Option<PrimitiveDateTime>, | ||||
| } | ||||
|  | ||||
| #[derive(Debug, Clone)] | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 Shankar Singh C
					Shankar Singh C