1use serde::{Deserialize, Serialize};
4use std::collections::HashMap;
5
6use super::payment_request::PaymentCurrencyAmount;
7
8#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
10pub struct Success {
11 pub merchant_confirmation_id: String,
13 #[serde(skip_serializing_if = "Option::is_none")]
15 pub psp_confirmation_id: Option<String>,
16 #[serde(skip_serializing_if = "Option::is_none")]
18 pub network_confirmation_id: Option<String>,
19}
20
21#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
23pub struct Error {
24 pub error_message: String,
26}
27
28#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
30pub struct Failure {
31 pub failure_message: String,
33}
34
35#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
40#[serde(untagged)]
41pub enum PaymentStatus {
42 Success(Success),
43 Error(Error),
44 Failure(Failure),
45}
46
47#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
52pub struct PaymentReceipt {
53 pub payment_mandate_id: String,
55 pub timestamp: String,
57 pub payment_id: String,
59 pub amount: PaymentCurrencyAmount,
61 pub payment_status: PaymentStatus,
63 #[serde(skip_serializing_if = "Option::is_none")]
65 pub payment_method_details: Option<HashMap<String, serde_json::Value>>,
66}
67
68#[cfg(test)]
69mod tests {
70 use super::*;
71
72 #[test]
73 fn success_receipt_roundtrip() {
74 let receipt = PaymentReceipt {
75 payment_mandate_id: "pm_123".into(),
76 timestamp: "2025-09-16T12:00:00Z".into(),
77 payment_id: "pay_456".into(),
78 amount: PaymentCurrencyAmount {
79 currency: "USD".into(),
80 value: 120.0,
81 },
82 payment_status: PaymentStatus::Success(Success {
83 merchant_confirmation_id: "mc_789".into(),
84 psp_confirmation_id: Some("psp_101".into()),
85 network_confirmation_id: None,
86 }),
87 payment_method_details: None,
88 };
89 let json = serde_json::to_string(&receipt).unwrap();
90 let back: PaymentReceipt = serde_json::from_str(&json).unwrap();
91 assert_eq!(receipt, back);
92 }
93
94 #[test]
95 fn error_receipt() {
96 let receipt = PaymentReceipt {
97 payment_mandate_id: "pm_123".into(),
98 timestamp: "2025-09-16T12:00:00Z".into(),
99 payment_id: "pay_456".into(),
100 amount: PaymentCurrencyAmount {
101 currency: "USD".into(),
102 value: 120.0,
103 },
104 payment_status: PaymentStatus::Error(Error {
105 error_message: "Card declined".into(),
106 }),
107 payment_method_details: None,
108 };
109 let json = serde_json::to_string(&receipt).unwrap();
110 assert!(json.contains("error_message"));
111 let back: PaymentReceipt = serde_json::from_str(&json).unwrap();
112 assert_eq!(receipt, back);
113 }
114
115 #[test]
116 fn failure_receipt() {
117 let receipt = PaymentReceipt {
118 payment_mandate_id: "pm_123".into(),
119 timestamp: "2025-09-16T12:00:00Z".into(),
120 payment_id: "pay_456".into(),
121 amount: PaymentCurrencyAmount {
122 currency: "USD".into(),
123 value: 120.0,
124 },
125 payment_status: PaymentStatus::Failure(Failure {
126 failure_message: "Insufficient funds".into(),
127 }),
128 payment_method_details: None,
129 };
130 let json = serde_json::to_string(&receipt).unwrap();
131 assert!(json.contains("failure_message"));
132 let back: PaymentReceipt = serde_json::from_str(&json).unwrap();
133 assert_eq!(receipt, back);
134 }
135}