use crate::{
MerchantReference, Money, PaymentProvider, PaymentStatus, ProviderReference, WebhookEventId,
};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PaymentEvent {
pub id: Option<WebhookEventId>,
pub provider: PaymentProvider,
pub provider_reference: ProviderReference,
pub merchant_reference: Option<MerchantReference>,
pub status: PaymentStatus,
pub amount: Option<Money>,
pub event_type: PaymentEventType,
pub message: Option<String>,
}
impl PaymentEvent {
#[inline]
#[must_use]
pub const fn id(&self) -> Option<&WebhookEventId> {
self.id.as_ref()
}
#[inline]
#[must_use]
pub const fn provider(&self) -> &PaymentProvider {
&self.provider
}
#[inline]
#[must_use]
pub const fn provider_reference(&self) -> &ProviderReference {
&self.provider_reference
}
#[inline]
#[must_use]
pub const fn merchant_reference(&self) -> Option<&MerchantReference> {
self.merchant_reference.as_ref()
}
#[inline]
#[must_use]
pub const fn status(&self) -> PaymentStatus {
self.status
}
#[inline]
#[must_use]
pub const fn amount(&self) -> Option<&Money> {
self.amount.as_ref()
}
#[inline]
#[must_use]
pub const fn event_type(&self) -> PaymentEventType {
self.event_type
}
#[inline]
#[must_use]
pub fn message(&self) -> Option<&str> {
self.message.as_deref()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum PaymentEventType {
PaymentCreated,
PaymentRequiresAction,
PaymentPending,
PaymentSucceeded,
PaymentFailed,
PaymentCancelled,
PaymentRefunded,
RefundCreated,
RefundFailed,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn payment_event_accessors_return_normalized_fields() {
let amount = Money::new_minor(1_000, "USD").expect("money should be valid");
let event = PaymentEvent {
id: Some(WebhookEventId::new("evt_123").expect("event id should be valid")),
provider: PaymentProvider::Stripe,
provider_reference: ProviderReference::new("pi_123")
.expect("reference should be valid"),
merchant_reference: Some(
MerchantReference::new("ORDER-1").expect("reference should be valid"),
),
status: PaymentStatus::Succeeded,
amount: Some(amount.clone()),
event_type: PaymentEventType::PaymentSucceeded,
message: Some("payment succeeded".to_owned()),
};
assert_eq!(
event.id().expect("event id should be present").as_str(),
"evt_123"
);
assert_eq!(event.provider(), &PaymentProvider::Stripe);
assert_eq!(event.provider_reference().as_str(), "pi_123");
assert_eq!(
event
.merchant_reference()
.expect("merchant reference should be present")
.as_str(),
"ORDER-1"
);
assert_eq!(event.status(), PaymentStatus::Succeeded);
assert_eq!(event.amount(), Some(&amount));
assert_eq!(event.event_type(), PaymentEventType::PaymentSucceeded);
assert_eq!(event.message(), Some("payment succeeded"));
}
#[test]
fn payment_event_accessors_handle_absent_optional_fields() {
let event = PaymentEvent {
id: None,
provider: PaymentProvider::PayPal,
provider_reference: ProviderReference::new("ORDER-1")
.expect("reference should be valid"),
merchant_reference: None,
status: PaymentStatus::Pending,
amount: None,
event_type: PaymentEventType::PaymentPending,
message: None,
};
assert!(event.id().is_none());
assert!(event.merchant_reference().is_none());
assert!(event.amount().is_none());
assert_eq!(event.message(), None);
}
}