1use super::action::Action;
2use serde::{Deserialize, Deserializer, Serialize, Serializer};
3use std::fmt;
4
5#[derive(Serialize, Deserialize, Debug, Clone)]
6#[serde(rename_all = "camelCase")]
7pub struct AdditionalData {
8 pub card_holder_name: String,
9 pub issuer_country: String,
10 pub card_summary: String,
11 pub expiry_date: String, pub payment_method: String, pub alias: Option<String>,
17 pub alias_type: Option<String>,
18
19 #[serde(rename = "recurring.recurringDetailReference")]
20 #[serde(skip_serializing_if = "Option::is_none")]
21 #[serde(default)]
22 pub recurring_detail_reference: Option<String>,
23}
24
25#[derive(Serialize, Deserialize, Debug, Clone)]
26#[serde(tag = "resultCode")]
27pub enum Response {
28 #[serde(rename_all = "camelCase")]
31 AuthenticationFinished {},
32
33 #[serde(rename_all = "camelCase")]
37 AuthenticationNotRequired {},
38
39 #[serde(rename_all = "camelCase")]
42 Authorised {
43 #[serde(skip_serializing_if = "Option::is_none")]
44 #[serde(default)]
45 additional_data: Option<AdditionalData>,
46
47 psp_reference: String,
48
49 merchant_reference: String,
50 },
51
52 #[serde(rename_all = "camelCase")]
55 Cancelled {
56 #[serde(rename = "refusalReasonCode")]
57 #[serde(skip_serializing_if = "Option::is_none")]
58 #[serde(default)]
59 refusal_reason: Option<RefusalReason>,
60
61 psp_reference: String,
62 },
63
64 ChallengeShopper { action: Action },
67
68 #[serde(rename_all = "camelCase")]
71 Error {
72 #[serde(rename = "refusalReasonCode")]
73 refusal_reason: RefusalReason,
74
75 psp_reference: String,
76 },
77
78 #[serde(rename_all = "camelCase")]
81 IdentifyShopper { action: Action },
82
83 #[serde(rename_all = "camelCase")]
86 PartiallyAuthorised {},
87
88 #[serde(rename_all = "camelCase")]
92 Pending { action: Action },
93
94 #[serde(rename_all = "camelCase")]
97 PresentToShopper {},
98
99 #[serde(rename_all = "camelCase")]
102 Received {},
103
104 #[serde(rename_all = "camelCase")]
107 RedirectShopper { action: Action },
108
109 #[serde(rename_all = "camelCase")]
112 Refused {
113 #[serde(rename = "refusalReasonCode")]
114 refusal_reason: RefusalReason,
115
116 psp_reference: String,
117 },
118}
119
120#[derive(Clone, Debug, PartialEq)]
123pub enum RefusalReason {
124 Refused,
126
127 Referral,
129
130 AcquirerError,
132
133 BlockedCard,
135
136 ExpiredCard,
138
139 InvalidAmount,
141
142 InvalidCardNumber,
144
145 IssuerUnavailable,
147
148 NotSupported,
150
151 ThreeDNotAuthenticated,
153
154 NotEnoughBalance,
156
157 AcquirerFraud,
159
160 Cancelled,
162
163 ShopperCancelled,
165
166 InvalidPin,
168
169 PinTriesExceeded,
171
172 PinValidationNotPossible,
174
175 Fraud,
177
178 NotSubmitted,
180
181 FraudCancelled,
183
184 TransactionNotPermitted,
186
187 CvcDeclined,
189
190 RestrictedCard,
192
193 RevocationOfAuth,
195
196 DeclinedNonGeneric,
198
199 WithdrawalAmountExceeded,
201
202 WithdrawalCountExceeded,
204
205 IssuerSuspectedFraud,
207
208 AvsDeclined,
210
211 CardRequiresOnlinePin,
213
214 NoCheckingAccountAvailable,
216
217 NoSavingsAccountAvailable,
219
220 MobilePinRequired,
222
223 ContactlessFallback,
225
226 AuthenticationRequired,
228
229 RReqNotReceived,
231
232 CurrentAidInPenaltyBox,
234
235 CvmRequiredRestartPayment,
237
238 ThreeDsAuthenticationError,
240
241 TransactionBlockedByAdyen,
243}
244
245impl Serialize for RefusalReason {
246 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
247 where
248 S: Serializer,
249 {
250 let code = match self {
251 RefusalReason::Refused => "2",
252 RefusalReason::Referral => "3",
253 RefusalReason::AcquirerError => "4",
254 RefusalReason::BlockedCard => "5",
255 RefusalReason::ExpiredCard => "6",
256 RefusalReason::InvalidAmount => "7",
257 RefusalReason::InvalidCardNumber => "8",
258 RefusalReason::IssuerUnavailable => "9",
259 RefusalReason::NotSupported => "10",
260 RefusalReason::ThreeDNotAuthenticated => "11",
261 RefusalReason::NotEnoughBalance => "12",
262 RefusalReason::AcquirerFraud => "14",
263 RefusalReason::Cancelled => "15",
264 RefusalReason::ShopperCancelled => "16",
265 RefusalReason::InvalidPin => "17",
266 RefusalReason::PinTriesExceeded => "18",
267 RefusalReason::PinValidationNotPossible => "19",
268 RefusalReason::Fraud => "20",
269 RefusalReason::NotSubmitted => "21",
270 RefusalReason::FraudCancelled => "22",
271 RefusalReason::TransactionNotPermitted => "23",
272 RefusalReason::CvcDeclined => "24",
273 RefusalReason::RestrictedCard => "25",
274 RefusalReason::RevocationOfAuth => "26",
275 RefusalReason::DeclinedNonGeneric => "27",
276 RefusalReason::WithdrawalAmountExceeded => "28",
277 RefusalReason::WithdrawalCountExceeded => "29",
278 RefusalReason::IssuerSuspectedFraud => "31",
279 RefusalReason::AvsDeclined => "32",
280 RefusalReason::CardRequiresOnlinePin => "33",
281 RefusalReason::NoCheckingAccountAvailable => "34",
282 RefusalReason::NoSavingsAccountAvailable => "35",
283 RefusalReason::MobilePinRequired => "36",
284 RefusalReason::ContactlessFallback => "37",
285 RefusalReason::AuthenticationRequired => "38",
286 RefusalReason::RReqNotReceived => "39",
287 RefusalReason::CurrentAidInPenaltyBox => "40",
288 RefusalReason::CvmRequiredRestartPayment => "41",
289 RefusalReason::ThreeDsAuthenticationError => "42",
290 RefusalReason::TransactionBlockedByAdyen => "46",
291 };
292 serializer.serialize_str(code)
293 }
294}
295
296impl<'de> Deserialize<'de> for RefusalReason {
297 fn deserialize<D>(deserializer: D) -> Result<RefusalReason, D::Error>
298 where
299 D: Deserializer<'de>,
300 {
301 struct RefusalReasonVisitor;
302
303 impl<'de> serde::de::Visitor<'de> for RefusalReasonVisitor {
304 type Value = RefusalReason;
305
306 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
307 formatter.write_str("a string representing a refusal reason code")
308 }
309
310 fn visit_str<E>(self, value: &str) -> Result<RefusalReason, E>
311 where
312 E: serde::de::Error,
313 {
314 match value {
315 "2" => Ok(RefusalReason::Refused),
316 "3" => Ok(RefusalReason::Referral),
317 "4" => Ok(RefusalReason::AcquirerError),
318 "5" => Ok(RefusalReason::BlockedCard),
319 "6" => Ok(RefusalReason::ExpiredCard),
320 "7" => Ok(RefusalReason::InvalidAmount),
321 "8" => Ok(RefusalReason::InvalidCardNumber),
322 "9" => Ok(RefusalReason::IssuerUnavailable),
323 "10" => Ok(RefusalReason::NotSupported),
324 "11" => Ok(RefusalReason::ThreeDNotAuthenticated),
325 "12" => Ok(RefusalReason::NotEnoughBalance),
326 "14" => Ok(RefusalReason::AcquirerFraud),
327 "15" => Ok(RefusalReason::Cancelled),
328 "16" => Ok(RefusalReason::ShopperCancelled),
329 "17" => Ok(RefusalReason::InvalidPin),
330 "18" => Ok(RefusalReason::PinTriesExceeded),
331 "19" => Ok(RefusalReason::PinValidationNotPossible),
332 "20" => Ok(RefusalReason::Fraud),
333 "21" => Ok(RefusalReason::NotSubmitted),
334 "22" => Ok(RefusalReason::FraudCancelled),
335 "23" => Ok(RefusalReason::TransactionNotPermitted),
336 "24" => Ok(RefusalReason::CvcDeclined),
337 "25" => Ok(RefusalReason::RestrictedCard),
338 "26" => Ok(RefusalReason::RevocationOfAuth),
339 "27" => Ok(RefusalReason::DeclinedNonGeneric),
340 "28" => Ok(RefusalReason::WithdrawalAmountExceeded),
341 "29" => Ok(RefusalReason::WithdrawalCountExceeded),
342 "31" => Ok(RefusalReason::IssuerSuspectedFraud),
343 "32" => Ok(RefusalReason::AvsDeclined),
344 "33" => Ok(RefusalReason::CardRequiresOnlinePin),
345 "34" => Ok(RefusalReason::NoCheckingAccountAvailable),
346 "35" => Ok(RefusalReason::NoSavingsAccountAvailable),
347 "36" => Ok(RefusalReason::MobilePinRequired),
348 "37" => Ok(RefusalReason::ContactlessFallback),
349 "38" => Ok(RefusalReason::AuthenticationRequired),
350 "39" => Ok(RefusalReason::RReqNotReceived),
351 "40" => Ok(RefusalReason::CurrentAidInPenaltyBox),
352 "41" => Ok(RefusalReason::CvmRequiredRestartPayment),
353 "42" => Ok(RefusalReason::ThreeDsAuthenticationError),
354 "46" => Ok(RefusalReason::TransactionBlockedByAdyen),
355 _ => Err(serde::de::Error::unknown_variant(
356 value,
357 &[
358 "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "14", "15",
359 "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27",
360 "28", "29", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40",
361 "41", "42", "46",
362 ],
363 )),
364 }
365 }
366 }
367
368 deserializer.deserialize_str(RefusalReasonVisitor)
369 }
370}