Bug: [FEATURE]  unix timestamp to primitive date time 



### Feature Description

add a deserialization logic to convert unix timestamp to primitive date time so that there will no need to timestamp conversion in connectors

### Possible Implementation

need to implement a new trait which has implementations of converting unix timestamp to required date time format 

### Have you spent some time to check if this feature request has been raised before?

- [X] I checked and didn't find similar issue

### Have you read the Contributing Guidelines?

- [X] I have read the [Contributing Guidelines](https://github.com/juspay/hyperswitch/blob/main/docs/CONTRIBUTING.md)

### Are you willing to submit a PR?

Yes I am willing to submit a PR!
diff --git a/crates/api_models/src/disputes.rs b/crates/api_models/src/disputes.rs
index 8dc56fba940..da3463185d7 100644
--- a/crates/api_models/src/disputes.rs
+++ b/crates/api_models/src/disputes.rs
@@ -31,11 +31,14 @@ pub struct DisputeResponse {
     /// Reason code of dispute sent by connector
     pub connector_reason_code: Option<String>,
     /// Evidence deadline of dispute sent by connector
-    pub challenge_required_by: Option<String>,
+    #[serde(with = "common_utils::custom_serde::iso8601::option")]
+    pub challenge_required_by: Option<PrimitiveDateTime>,
     /// Dispute created time sent by connector
-    pub created_at: Option<String>,
+    #[serde(with = "common_utils::custom_serde::iso8601::option")]
+    pub created_at: Option<PrimitiveDateTime>,
     /// Dispute updated time sent by connector
-    pub updated_at: Option<String>,
+    #[serde(with = "common_utils::custom_serde::iso8601::option")]
+    pub updated_at: Option<PrimitiveDateTime>,
     /// Time at which dispute is received
     pub received_at: String,
 }
diff --git a/crates/api_models/src/enums.rs b/crates/api_models/src/enums.rs
index 229c034f46d..6cdf4dbcf34 100644
--- a/crates/api_models/src/enums.rs
+++ b/crates/api_models/src/enums.rs
@@ -877,6 +877,7 @@ impl From<AttemptStatus> for IntentStatus {
     frunk::LabelledGeneric,
     ToSchema,
 )]
+#[serde(rename_all = "snake_case")]
 pub enum DisputeStage {
     PreDispute,
     #[default]
@@ -898,6 +899,7 @@ pub enum DisputeStage {
     frunk::LabelledGeneric,
     ToSchema,
 )]
+#[serde(rename_all = "snake_case")]
 pub enum DisputeStatus {
     #[default]
     DisputeOpened,
diff --git a/crates/common_utils/src/custom_serde.rs b/crates/common_utils/src/custom_serde.rs
index 2d797a5bda9..d64abe38e5b 100644
--- a/crates/common_utils/src/custom_serde.rs
+++ b/crates/common_utils/src/custom_serde.rs
@@ -86,6 +86,74 @@ pub mod iso8601 {
     }
 }
 
+/// Use the UNIX timestamp when serializing and deserializing an
+/// [`PrimitiveDateTime`][PrimitiveDateTime].
+///
+/// [PrimitiveDateTime]: ::time::PrimitiveDateTime
+pub mod timestamp {
+
+    use serde::{Deserializer, Serialize, Serializer};
+    use time::{serde::timestamp, PrimitiveDateTime, UtcOffset};
+
+    /// Serialize a [`PrimitiveDateTime`] using UNIX timestamp.
+    pub fn serialize<S>(date_time: &PrimitiveDateTime, serializer: S) -> Result<S::Ok, S::Error>
+    where
+        S: Serializer,
+    {
+        date_time
+            .assume_utc()
+            .unix_timestamp()
+            .serialize(serializer)
+    }
+
+    /// Deserialize an [`PrimitiveDateTime`] from UNIX timestamp.
+    pub fn deserialize<'a, D>(deserializer: D) -> Result<PrimitiveDateTime, D::Error>
+    where
+        D: Deserializer<'a>,
+    {
+        timestamp::deserialize(deserializer).map(|offset_date_time| {
+            let utc_date_time = offset_date_time.to_offset(UtcOffset::UTC);
+            PrimitiveDateTime::new(utc_date_time.date(), utc_date_time.time())
+        })
+    }
+
+    /// Use the UNIX timestamp when serializing and deserializing an
+    /// [`Option<PrimitiveDateTime>`][PrimitiveDateTime].
+    ///
+    /// [PrimitiveDateTime]: ::time::PrimitiveDateTime
+    pub mod option {
+        use serde::Serialize;
+
+        use super::*;
+
+        /// Serialize an [`Option<PrimitiveDateTime>`] from UNIX timestamp.
+        pub fn serialize<S>(
+            date_time: &Option<PrimitiveDateTime>,
+            serializer: S,
+        ) -> Result<S::Ok, S::Error>
+        where
+            S: Serializer,
+        {
+            date_time
+                .map(|date_time| date_time.assume_utc().unix_timestamp())
+                .serialize(serializer)
+        }
+
+        /// Deserialize an [`Option<PrimitiveDateTime>`] from UNIX timestamp.
+        pub fn deserialize<'a, D>(deserializer: D) -> Result<Option<PrimitiveDateTime>, D::Error>
+        where
+            D: Deserializer<'a>,
+        {
+            timestamp::option::deserialize(deserializer).map(|option_offset_date_time| {
+                option_offset_date_time.map(|offset_date_time| {
+                    let utc_date_time = offset_date_time.to_offset(UtcOffset::UTC);
+                    PrimitiveDateTime::new(utc_date_time.date(), utc_date_time.time())
+                })
+            })
+        }
+    }
+}
+
 /// <https://github.com/serde-rs/serde/issues/994#issuecomment-316895860>
 
 pub mod json_string {
diff --git a/crates/router/src/connector/adyen.rs b/crates/router/src/connector/adyen.rs
index 31d3740bf5e..097f3c7afdc 100644
--- a/crates/router/src/connector/adyen.rs
+++ b/crates/router/src/connector/adyen.rs
@@ -796,7 +796,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,
         })
     }
diff --git a/crates/router/src/connector/adyen/transformers.rs b/crates/router/src/connector/adyen/transformers.rs
index 570ad607f0c..d1ed7342696 100644
--- a/crates/router/src/connector/adyen/transformers.rs
+++ b/crates/router/src/connector/adyen/transformers.rs
@@ -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)]
diff --git a/crates/router/src/connector/checkout.rs b/crates/router/src/connector/checkout.rs
index 25e4a6e14e8..15bf2e2907e 100644
--- a/crates/router/src/connector/checkout.rs
+++ b/crates/router/src/connector/checkout.rs
@@ -879,7 +879,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
@@ -889,7 +889,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
@@ -913,7 +913,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(
@@ -939,12 +939,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,
         })
diff --git a/crates/router/src/connector/checkout/transformers.rs b/crates/router/src/connector/checkout/transformers.rs
index 1de1256d7ee..0c61906fff4 100644
--- a/crates/router/src/connector/checkout/transformers.rs
+++ b/crates/router/src/connector/checkout/transformers.rs
@@ -1,5 +1,6 @@
 use error_stack::IntoReport;
 use serde::{Deserialize, Serialize};
+use time::PrimitiveDateTime;
 use url::Url;
 
 use crate::{
@@ -673,27 +674,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
     )
 }
 
@@ -704,20 +705,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,
@@ -735,37 +736,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,
         }
     }
diff --git a/crates/router/src/connector/stripe.rs b/crates/router/src/connector/stripe.rs
index dbdcb7cf485..ce95fc6507d 100644
--- a/crates/router/src/connector/stripe.rs
+++ b/crates/router/src/connector/stripe.rs
@@ -1285,28 +1285,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()?,
         })
     }
@@ -1315,13 +1345,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 {
diff --git a/crates/router/src/connector/stripe/transformers.rs b/crates/router/src/connector/stripe/transformers.rs
index 7b7cbe86945..8a296f19443 100644
--- a/crates/router/src/connector/stripe/transformers.rs
+++ b/crates/router/src/connector/stripe/transformers.rs
@@ -4,6 +4,7 @@ use common_utils::{errors::CustomResult, fp_utils, 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> {
@@ -1573,34 +1588,119 @@ impl<F, T>
 // }
 
 #[derive(Debug, Deserialize)]
-pub struct StripeWebhookDataObjectId {
-    pub id: String,
+pub struct WebhookEventDataResource {
+    pub object: serde_json::Value,
 }
 
 #[derive(Debug, Deserialize)]
-pub struct StripeWebhookDataId {
-    pub object: StripeWebhookDataObjectId,
+pub struct WebhookEventObjectResource {
+    pub data: WebhookEventDataResource,
 }
 
 #[derive(Debug, Deserialize)]
-pub struct StripeWebhookDataResource {
-    pub object: serde_json::Value,
+pub struct WebhookEvent {
+    #[serde(rename = "type")]
+    pub event_type: WebhookEventType,
+    #[serde(rename = "data")]
+    pub event_data: WebhookEventData,
 }
 
 #[derive(Debug, Deserialize)]
-pub struct StripeWebhookObjectResource {
-    pub data: StripeWebhookDataResource,
+pub struct WebhookEventData {
+    #[serde(rename = "object")]
+    pub event_object: WebhookEventObjectData,
 }
 
 #[derive(Debug, Deserialize)]
-pub struct StripeWebhookObjectEventType {
-    #[serde(rename = "type")]
-    pub event_type: String,
+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 struct StripeWebhookObjectId {
-    pub data: StripeWebhookDataId,
+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
diff --git a/crates/router/src/types/api/disputes.rs b/crates/router/src/types/api/disputes.rs
index 246c4b15cf6..e8eba9ff5d1 100644
--- a/crates/router/src/types/api/disputes.rs
+++ b/crates/router/src/types/api/disputes.rs
@@ -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)]
diff --git a/crates/storage_models/src/dispute.rs b/crates/storage_models/src/dispute.rs
index 7022f399acc..bf9c5146505 100644
--- a/crates/storage_models/src/dispute.rs
+++ b/crates/storage_models/src/dispute.rs
@@ -1,11 +1,11 @@
 use common_utils::custom_serde;
 use diesel::{AsChangeset, Identifiable, Insertable, Queryable};
-use serde::{Deserialize, Serialize};
+use serde::Serialize;
 use time::PrimitiveDateTime;
 
 use crate::{enums as storage_enums, schema::dispute};
 
-#[derive(Clone, Debug, Deserialize, Insertable, Serialize, router_derive::DebugAsDisplay)]
+#[derive(Clone, Debug, Insertable, Serialize, router_derive::DebugAsDisplay)]
 #[diesel(table_name = dispute)]
 #[serde(deny_unknown_fields)]
 pub struct DisputeNew {
@@ -21,13 +21,13 @@ pub struct DisputeNew {
     pub connector_dispute_id: String,
     pub connector_reason: Option<String>,
     pub connector_reason_code: Option<String>,
-    pub challenge_required_by: Option<String>,
-    pub dispute_created_at: Option<String>,
-    pub updated_at: Option<String>,
+    pub challenge_required_by: Option<PrimitiveDateTime>,
+    pub dispute_created_at: Option<PrimitiveDateTime>,
+    pub updated_at: Option<PrimitiveDateTime>,
     pub connector: String,
 }
 
-#[derive(Clone, Debug, Deserialize, Serialize, Identifiable, Queryable)]
+#[derive(Clone, Debug, Serialize, Identifiable, Queryable)]
 #[diesel(table_name = dispute)]
 pub struct Dispute {
     #[serde(skip_serializing)]
@@ -44,9 +44,9 @@ pub struct Dispute {
     pub connector_dispute_id: String,
     pub connector_reason: Option<String>,
     pub connector_reason_code: Option<String>,
-    pub challenge_required_by: Option<String>,
-    pub dispute_created_at: Option<String>,
-    pub updated_at: Option<String>,
+    pub challenge_required_by: Option<PrimitiveDateTime>,
+    pub dispute_created_at: Option<PrimitiveDateTime>,
+    pub updated_at: Option<PrimitiveDateTime>,
     #[serde(with = "custom_serde::iso8601")]
     pub created_at: PrimitiveDateTime,
     #[serde(with = "custom_serde::iso8601")]
@@ -62,8 +62,8 @@ pub enum DisputeUpdate {
         connector_status: String,
         connector_reason: Option<String>,
         connector_reason_code: Option<String>,
-        challenge_required_by: Option<String>,
-        updated_at: Option<String>,
+        challenge_required_by: Option<PrimitiveDateTime>,
+        updated_at: Option<PrimitiveDateTime>,
     },
     StatusUpdate {
         dispute_status: storage_enums::DisputeStatus,
@@ -79,8 +79,8 @@ pub struct DisputeUpdateInternal {
     connector_status: Option<String>,
     connector_reason: Option<String>,
     connector_reason_code: Option<String>,
-    challenge_required_by: Option<String>,
-    updated_at: Option<String>,
+    challenge_required_by: Option<PrimitiveDateTime>,
+    updated_at: Option<PrimitiveDateTime>,
     modified_at: Option<PrimitiveDateTime>,
 }
 
diff --git a/crates/storage_models/src/schema.rs b/crates/storage_models/src/schema.rs
index 2a642a42ee7..f381044d493 100644
--- a/crates/storage_models/src/schema.rs
+++ b/crates/storage_models/src/schema.rs
@@ -128,9 +128,9 @@ diesel::table! {
         connector_dispute_id -> Varchar,
         connector_reason -> Nullable<Varchar>,
         connector_reason_code -> Nullable<Varchar>,
-        challenge_required_by -> Nullable<Varchar>,
-        dispute_created_at -> Nullable<Varchar>,
-        updated_at -> Nullable<Varchar>,
+        challenge_required_by -> Nullable<Timestamp>,
+        dispute_created_at -> Nullable<Timestamp>,
+        updated_at -> Nullable<Timestamp>,
         created_at -> Timestamp,
         modified_at -> Timestamp,
         connector -> Varchar,
diff --git a/migrations/2023-04-26-062424_alter_dispute_table/down.sql b/migrations/2023-04-26-062424_alter_dispute_table/down.sql
new file mode 100644
index 00000000000..9cc7d7c77c4
--- /dev/null
+++ b/migrations/2023-04-26-062424_alter_dispute_table/down.sql
@@ -0,0 +1,4 @@
+ALTER TABLE dispute
+ALTER COLUMN challenge_required_by TYPE VARCHAR(255),
+ALTER COLUMN dispute_created_at TYPE VARCHAR(255),
+ALTER COLUMN updated_at TYPE VARCHAR(255)
\ No newline at end of file
diff --git a/migrations/2023-04-26-062424_alter_dispute_table/up.sql b/migrations/2023-04-26-062424_alter_dispute_table/up.sql
new file mode 100644
index 00000000000..201e67a40ff
--- /dev/null
+++ b/migrations/2023-04-26-062424_alter_dispute_table/up.sql
@@ -0,0 +1,4 @@
+ALTER TABLE dispute
+ALTER COLUMN challenge_required_by TYPE TIMESTAMP USING dispute_created_at::TIMESTAMP,
+ALTER COLUMN dispute_created_at TYPE TIMESTAMP USING dispute_created_at::TIMESTAMP,
+ALTER COLUMN updated_at TYPE TIMESTAMP USING dispute_created_at::TIMESTAMP
\ No newline at end of file

## Type of Change
<!-- Put an `x` in the boxes that apply -->

- [ ] Bugfix
- [x] New feature
- [ ] Enhancement
- [ ] Refactoring
- [ ] Dependency updates

## Description
Implemented Dispute Webhooks for Stripe
<!-- Describe your changes in detail -->


### Additional Changes

- [x] This PR modifies the database schema
- [ ] This PR modifies application configuration/environment variables

<!-- 
Provide links to the files with corresponding changes.

Following are the paths where you can find config files:
1. `config`
2. `crates/router/src/configs`
3. `loadtest/config`
-->


## Motivation and Context
<!--
Why is this change required? What problem does it solve?
If it fixes an open issue, please link to the issue here.

If you don't have an issue, we'd recommend starting with one first so the PR
can focus on the implementation (unless its an obvious bug or documentation fix
that will have little conversation).
-->
Fixes #967.

## How did you test it?
I tested this change manually

Out going webhook to merchant
<img width="1144" alt="Screenshot 2023-04-19 at 1 15 10 PM" src="https://user-images.githubusercontent.com/83439957/233008843-1fba37a8-7908-4232-8e19-df7d2ae7cd5b.png">


<!--
Did you write an integration/unit/API test to verify the code changes?
Or did you test this change manually (provide relevant screenshots)?
-->


## Checklist
<!-- Put an `x` in the boxes that apply -->

- [x] I formatted the code `cargo +nightly fmt --all`
- [x] I addressed lints thrown by `cargo clippy`
- [x] I reviewed submitted code
- [ ] I added unit tests for my changes where possible
- [ ] I added a [CHANGELOG](/CHANGELOG.md) entry if applicable
