use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use super::payment_request::PaymentCurrencyAmount;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Success {
pub merchant_confirmation_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub psp_confirmation_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub network_confirmation_id: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Error {
pub error_message: String,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Failure {
pub failure_message: String,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(untagged)]
pub enum PaymentStatus {
Success(Success),
Error(Error),
Failure(Failure),
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PaymentReceipt {
pub payment_mandate_id: String,
pub timestamp: String,
pub payment_id: String,
pub amount: PaymentCurrencyAmount,
pub payment_status: PaymentStatus,
#[serde(skip_serializing_if = "Option::is_none")]
pub payment_method_details: Option<HashMap<String, serde_json::Value>>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn success_receipt_roundtrip() {
let receipt = PaymentReceipt {
payment_mandate_id: "pm_123".into(),
timestamp: "2025-09-16T12:00:00Z".into(),
payment_id: "pay_456".into(),
amount: PaymentCurrencyAmount {
currency: "USD".into(),
value: 120.0,
},
payment_status: PaymentStatus::Success(Success {
merchant_confirmation_id: "mc_789".into(),
psp_confirmation_id: Some("psp_101".into()),
network_confirmation_id: None,
}),
payment_method_details: None,
};
let json = serde_json::to_string(&receipt).unwrap();
let back: PaymentReceipt = serde_json::from_str(&json).unwrap();
assert_eq!(receipt, back);
}
#[test]
fn error_receipt() {
let receipt = PaymentReceipt {
payment_mandate_id: "pm_123".into(),
timestamp: "2025-09-16T12:00:00Z".into(),
payment_id: "pay_456".into(),
amount: PaymentCurrencyAmount {
currency: "USD".into(),
value: 120.0,
},
payment_status: PaymentStatus::Error(Error {
error_message: "Card declined".into(),
}),
payment_method_details: None,
};
let json = serde_json::to_string(&receipt).unwrap();
assert!(json.contains("error_message"));
let back: PaymentReceipt = serde_json::from_str(&json).unwrap();
assert_eq!(receipt, back);
}
#[test]
fn failure_receipt() {
let receipt = PaymentReceipt {
payment_mandate_id: "pm_123".into(),
timestamp: "2025-09-16T12:00:00Z".into(),
payment_id: "pay_456".into(),
amount: PaymentCurrencyAmount {
currency: "USD".into(),
value: 120.0,
},
payment_status: PaymentStatus::Failure(Failure {
failure_message: "Insufficient funds".into(),
}),
payment_method_details: None,
};
let json = serde_json::to_string(&receipt).unwrap();
assert!(json.contains("failure_message"));
let back: PaymentReceipt = serde_json::from_str(&json).unwrap();
assert_eq!(receipt, back);
}
}