1use crate::category::Category;
19use crate::response_code::{ResponseCode, ServiceCode};
20
21#[derive(Debug, thiserror::Error)]
23#[non_exhaustive]
24pub enum Error {
25 #[error("Bad Request")]
27 BadRequest,
28 #[error("Invalid Field Format {0}")]
30 InvalidFieldFormat(String),
31 #[error("Invalid Mandatory Field {0}")]
33 InvalidMandatoryField(String),
34 #[error("Unauthorized. {0}")]
38 Unauthorized(String),
39 #[error("Invalid Token (B2B)")]
42 InvalidTokenB2B,
43 #[error("Invalid Customer Token")]
46 InvalidCustomerToken,
47 #[error("Token Not Found (B2B)")]
50 TokenNotFoundB2B,
51 #[error("Customer Token Not Found")]
54 CustomerTokenNotFound,
55 #[error("Transaction Expired")]
57 TransactionExpired,
58 #[error("Feature Not Allowed {0}")]
60 FeatureNotAllowed(String),
61 #[error("Exceeds Transaction Amount Limit")]
63 ExceedsTransactionAmountLimit,
64 #[error("Suspected Fraud")]
66 SuspectedFraud,
67 #[error("Activity Count Limit Exceeded")]
69 ActivityCountLimitExceeded,
70 #[error("Do Not Honor")]
72 DoNotHonor,
73 #[error("Feature Not Allowed At This Time. {0}")]
75 FeatureNotAllowedAtThisTime(String),
76 #[error("Card Blocked")]
78 CardBlocked,
79 #[error("Card Expired")]
81 CardExpired,
82 #[error("Dormant Account")]
84 DormantAccount,
85 #[error("Need To Set Token Limit")]
87 NeedToSetTokenLimit,
88 #[error("OTP Blocked")]
90 OTPBlocked,
91 #[error("OTP Lifetime Expired")]
93 OTPLifetimeExpired,
94 #[error("OTP Sent To Cardholder")]
96 OTPSentToCardholder,
97 #[error("Insufficient Funds")]
99 InsufficientFunds,
100 #[error("Transaction Not Permitted. {0}")]
102 TransactionNotPermitted(String),
103 #[error("Suspend Transaction")]
105 SuspendTransaction,
106 #[error("Token Limit Exceeded")]
108 TokenLimitExceeded,
109 #[error("Inactive Card/Account/Customer")]
111 InactiveCardOrAccountOrCustomer,
112 #[error("Merchant Blacklisted")]
114 MerchantBlacklisted,
115 #[error("Merchant Limit Exceed")]
117 MerchantLimitExceed,
118 #[error("Set Limit Not Allowed")]
120 SetLimitNotAllowed,
121 #[error("Token Limit Invalid")]
124 TokenLimitInvalid,
125 #[error("Account Limit Exceed")]
127 AccountLimitExceed,
128 #[error("Invalid Transaction Status")]
130 InvalidTransactionStatus,
131 #[error("Transaction Not Found")]
133 TransactionNotFound,
134 #[error("Invalid Routing")]
136 InvalidRouting,
137 #[error("Bank Not Supported By Switch")]
139 BankNotSupportedBySwitch,
140 #[error("Transaction Cancelled")]
142 TransactionCancelled,
143 #[error("Merchant Is Not Registered For Card Registration Services")]
145 MerchantNotRegisteredForCardRegistrationServices,
146 #[error("Need To Request OTP")]
148 NeedToRequestOTP,
149 #[error("Journey Not Found")]
151 JourneyNotFound,
152 #[error("Invalid Merchant")]
154 InvalidMerchant,
155 #[error("No Issuer")]
157 NoIssuer,
158 #[error("Invalid API Transition")]
160 InvalidAPITransition,
161 #[error("Invalid Card/Account/Customer {0}/Virtual Account")]
164 InvalidCardOrAccountOrCustomerOrVirtualAccount(String),
165 #[error("Invalid Bill/Virtual Account {0}")]
167 InvalidBillOrVirtualAccountWithReason(String),
168 #[error("Invalid Amount")]
170 InvalidAmount,
171 #[error("Paid Bill")]
173 PaidBill,
174 #[error("Invalid OTP")]
176 InvalidOTP,
177 #[error("Partner Not Found")]
179 PartnerNotFound,
180 #[error("Invalid Terminal")]
182 InvalidTerminal,
183 #[error("Inconsistent Request")]
186 InconsistentRequest,
187 #[error("Invalid Bill/Virtual Account")]
189 InvalidBillOrVirtualAccount,
190 #[error("Requested Function Is Not Supported")]
192 RequestedFunctionIsNotSupported,
193 #[error("Requested Operation Is Not Allowed")]
196 RequestedOperationIsNotAllowed,
197 #[error("Conflict")]
199 Conflict,
200 #[error("Duplicate partnerReferenceNo")]
203 DuplicatePartnerReferenceNo,
204 #[error("Too Many Requests")]
206 TooManyRequests,
207 #[error("General Error")]
209 GeneralError,
210 #[error("Internal Server Error")]
212 InternalServerError,
213 #[error("External Server Error")]
215 ExternalServerError,
216 #[error("Timeout")]
218 Timeout,
219
220 #[cfg(feature = "crypto")]
223 #[error("crypto error: {0}")]
224 Crypto(#[from] kamu_snap_crypto::Error),
225}
226
227impl Error {
228 pub fn category(&self) -> Category {
230 match self {
231 Self::BadRequest => Category::System,
232 Self::InvalidFieldFormat(_) => Category::Message,
233 Self::InvalidMandatoryField(_) => Category::Message,
234 Self::Unauthorized(_) => Category::System,
235 Self::InvalidTokenB2B => Category::System,
236 Self::InvalidCustomerToken => Category::System,
237 Self::TokenNotFoundB2B => Category::System,
238 Self::CustomerTokenNotFound => Category::System,
239 Self::TransactionExpired => Category::Business,
240 Self::FeatureNotAllowed(_) => Category::System,
241 Self::ExceedsTransactionAmountLimit => Category::Business,
242 Self::SuspectedFraud => Category::Business,
243 Self::ActivityCountLimitExceeded => Category::Business,
244 Self::DoNotHonor => Category::Business,
245 Self::FeatureNotAllowedAtThisTime(_) => Category::System,
246 Self::CardBlocked => Category::Business,
247 Self::CardExpired => Category::Business,
248 Self::DormantAccount => Category::Business,
249 Self::NeedToSetTokenLimit => Category::Business,
250 Self::OTPBlocked => Category::System,
251 Self::OTPLifetimeExpired => Category::System,
252 Self::OTPSentToCardholder => Category::System,
253 Self::InsufficientFunds => Category::Business,
254 Self::TransactionNotPermitted(_) => Category::Business,
255 Self::SuspendTransaction => Category::Business,
256 Self::TokenLimitExceeded => Category::Business,
257 Self::InactiveCardOrAccountOrCustomer => Category::Business,
258 Self::MerchantBlacklisted => Category::Business,
259 Self::MerchantLimitExceed => Category::Business,
260 Self::SetLimitNotAllowed => Category::Business,
261 Self::TokenLimitInvalid => Category::Business,
262 Self::AccountLimitExceed => Category::Business,
263 Self::InvalidTransactionStatus => Category::Business,
264 Self::TransactionNotFound => Category::Business,
265 Self::InvalidRouting => Category::System,
266 Self::BankNotSupportedBySwitch => Category::System,
267 Self::TransactionCancelled => Category::Business,
268 Self::MerchantNotRegisteredForCardRegistrationServices => Category::Business,
269 Self::NeedToRequestOTP => Category::System,
270 Self::JourneyNotFound => Category::System,
271 Self::InvalidMerchant => Category::Business,
272 Self::NoIssuer => Category::Business,
273 Self::InvalidAPITransition => Category::System,
274 Self::InvalidCardOrAccountOrCustomerOrVirtualAccount(_) => Category::Business,
275 Self::InvalidBillOrVirtualAccountWithReason(_) => Category::Business,
276 Self::InvalidAmount => Category::Business,
277 Self::PaidBill => Category::Business,
278 Self::InvalidOTP => Category::System,
279 Self::PartnerNotFound => Category::Business,
280 Self::InvalidTerminal => Category::Business,
281 Self::InconsistentRequest => Category::Business,
282 Self::InvalidBillOrVirtualAccount => Category::Business,
283 Self::RequestedFunctionIsNotSupported => Category::System,
284 Self::RequestedOperationIsNotAllowed => Category::Business,
285 Self::Conflict => Category::System,
286 Self::DuplicatePartnerReferenceNo => Category::System,
287 Self::TooManyRequests => Category::System,
288 Self::GeneralError => Category::System,
289 Self::InternalServerError => Category::System,
290 Self::ExternalServerError => Category::System,
291 Self::Timeout => Category::System,
292 #[cfg(feature = "crypto")]
293 Self::Crypto(_) => Category::System,
294 }
295 }
296
297 pub fn http_status(&self) -> http::StatusCode {
299 match self {
300 Self::BadRequest | Self::InvalidFieldFormat(_) | Self::InvalidMandatoryField(_) => {
301 http::StatusCode::BAD_REQUEST
302 }
303
304 Self::Unauthorized(_)
305 | Self::InvalidTokenB2B
306 | Self::InvalidCustomerToken
307 | Self::TokenNotFoundB2B
308 | Self::CustomerTokenNotFound => http::StatusCode::UNAUTHORIZED,
309
310 Self::TransactionExpired
311 | Self::FeatureNotAllowed(_)
312 | Self::ExceedsTransactionAmountLimit
313 | Self::SuspectedFraud
314 | Self::ActivityCountLimitExceeded
315 | Self::DoNotHonor
316 | Self::FeatureNotAllowedAtThisTime(_)
317 | Self::CardBlocked
318 | Self::CardExpired
319 | Self::DormantAccount
320 | Self::NeedToSetTokenLimit
321 | Self::OTPBlocked
322 | Self::OTPLifetimeExpired
323 | Self::OTPSentToCardholder
324 | Self::InsufficientFunds
325 | Self::TransactionNotPermitted(_)
326 | Self::SuspendTransaction
327 | Self::TokenLimitExceeded
328 | Self::InactiveCardOrAccountOrCustomer
329 | Self::MerchantBlacklisted
330 | Self::MerchantLimitExceed
331 | Self::SetLimitNotAllowed
332 | Self::TokenLimitInvalid
333 | Self::AccountLimitExceed => http::StatusCode::FORBIDDEN,
334
335 Self::InvalidOTP
336 | Self::InvalidTransactionStatus
337 | Self::TransactionCancelled
338 | Self::MerchantNotRegisteredForCardRegistrationServices
339 | Self::PaidBill
340 | Self::PartnerNotFound
341 | Self::JourneyNotFound
342 | Self::InvalidMerchant
343 | Self::NoIssuer
344 | Self::TransactionNotFound
345 | Self::InconsistentRequest
346 | Self::InvalidAmount
347 | Self::InvalidAPITransition
348 | Self::InvalidRouting
349 | Self::BankNotSupportedBySwitch
350 | Self::InvalidTerminal
351 | Self::InvalidCardOrAccountOrCustomerOrVirtualAccount(_)
352 | Self::InvalidBillOrVirtualAccountWithReason(_)
353 | Self::InvalidBillOrVirtualAccount
354 | Self::NeedToRequestOTP => http::StatusCode::NOT_FOUND,
355
356 Self::RequestedFunctionIsNotSupported | Self::RequestedOperationIsNotAllowed => {
357 http::StatusCode::METHOD_NOT_ALLOWED
358 }
359
360 Self::Conflict | Self::DuplicatePartnerReferenceNo => http::StatusCode::CONFLICT,
361
362 Self::TooManyRequests => http::StatusCode::TOO_MANY_REQUESTS,
363
364 Self::GeneralError | Self::InternalServerError | Self::ExternalServerError => {
365 http::StatusCode::INTERNAL_SERVER_ERROR
366 }
367
368 Self::Timeout => http::StatusCode::GATEWAY_TIMEOUT,
369
370 #[cfg(feature = "crypto")]
371 Self::Crypto(_) => http::StatusCode::UNAUTHORIZED,
372 }
373 }
374
375 pub fn case_code(&self) -> u8 {
377 match self {
378 Self::BadRequest => 0,
379 Self::InvalidFieldFormat(_) => 1,
380 Self::InvalidMandatoryField(_) => 2,
381 Self::Unauthorized(_) => 0,
382 Self::InvalidTokenB2B => 1,
383 Self::InvalidCustomerToken => 2,
384 Self::TokenNotFoundB2B => 3,
385 Self::CustomerTokenNotFound => 4,
386 Self::TransactionExpired => 0,
387 Self::FeatureNotAllowed(_) => 1,
388 Self::ExceedsTransactionAmountLimit => 2,
389 Self::SuspectedFraud => 3,
390 Self::ActivityCountLimitExceeded => 4,
391 Self::DoNotHonor => 5,
392 Self::FeatureNotAllowedAtThisTime(_) => 6,
393 Self::CardBlocked => 7,
394 Self::CardExpired => 8,
395 Self::DormantAccount => 9,
396 Self::NeedToSetTokenLimit => 10,
397 Self::OTPBlocked => 11,
398 Self::OTPLifetimeExpired => 12,
399 Self::OTPSentToCardholder => 13,
400 Self::InsufficientFunds => 14,
401 Self::TransactionNotPermitted(_) => 15,
402 Self::SuspendTransaction => 16,
403 Self::TokenLimitExceeded => 17,
404 Self::InactiveCardOrAccountOrCustomer => 18,
405 Self::MerchantBlacklisted => 19,
406 Self::MerchantLimitExceed => 20,
407 Self::SetLimitNotAllowed => 21,
408 Self::TokenLimitInvalid => 22,
409 Self::AccountLimitExceed => 23,
410 Self::InvalidTransactionStatus => 0,
411 Self::TransactionNotFound => 1,
412 Self::InvalidRouting => 2,
413 Self::BankNotSupportedBySwitch => 3,
414 Self::TransactionCancelled => 4,
415 Self::MerchantNotRegisteredForCardRegistrationServices => 5,
416 Self::NeedToRequestOTP => 6,
417 Self::JourneyNotFound => 7,
418 Self::InvalidMerchant => 8,
419 Self::NoIssuer => 9,
420 Self::InvalidAPITransition => 10,
421 Self::InvalidCardOrAccountOrCustomerOrVirtualAccount(_) => 11,
422 Self::InvalidBillOrVirtualAccountWithReason(_) => 12,
423 Self::InvalidAmount => 13,
424 Self::PaidBill => 14,
425 Self::InvalidOTP => 15,
426 Self::PartnerNotFound => 16,
427 Self::InvalidTerminal => 17,
428 Self::InconsistentRequest => 18,
429 Self::InvalidBillOrVirtualAccount => 19,
430 Self::RequestedFunctionIsNotSupported => 0,
431 Self::RequestedOperationIsNotAllowed => 1,
432 Self::Conflict => 0,
433 Self::DuplicatePartnerReferenceNo => 1,
434 Self::TooManyRequests => 0,
435 Self::GeneralError => 0,
436 Self::InternalServerError => 1,
437 Self::ExternalServerError => 2,
438 Self::Timeout => 0,
439 #[cfg(feature = "crypto")]
440 Self::Crypto(_) => 0,
441 }
442 }
443
444 pub fn response_code(&self, service: ServiceCode) -> ResponseCode {
446 ResponseCode::from_parts(self.http_status().as_u16(), service, self.case_code())
447 }
448
449 pub fn from_http_and_case(http: u16, case: u8) -> Option<Self> {
453 use Error::*;
454 Some(match (http, case) {
455 (400, 0) => BadRequest,
456 (400, 1) => InvalidFieldFormat(String::new()),
457 (400, 2) => InvalidMandatoryField(String::new()),
458
459 (401, 0) => Unauthorized(String::new()),
460 (401, 1) => InvalidTokenB2B,
461 (401, 2) => InvalidCustomerToken,
462 (401, 3) => TokenNotFoundB2B,
463 (401, 4) => CustomerTokenNotFound,
464
465 (403, 0) => TransactionExpired,
466 (403, 1) => FeatureNotAllowed(String::new()),
467 (403, 2) => ExceedsTransactionAmountLimit,
468 (403, 3) => SuspectedFraud,
469 (403, 4) => ActivityCountLimitExceeded,
470 (403, 5) => DoNotHonor,
471 (403, 6) => FeatureNotAllowedAtThisTime(String::new()),
472 (403, 7) => CardBlocked,
473 (403, 8) => CardExpired,
474 (403, 9) => DormantAccount,
475 (403, 10) => NeedToSetTokenLimit,
476 (403, 11) => OTPBlocked,
477 (403, 12) => OTPLifetimeExpired,
478 (403, 13) => OTPSentToCardholder,
479 (403, 14) => InsufficientFunds,
480 (403, 15) => TransactionNotPermitted(String::new()),
481 (403, 16) => SuspendTransaction,
482 (403, 17) => TokenLimitExceeded,
483 (403, 18) => InactiveCardOrAccountOrCustomer,
484 (403, 19) => MerchantBlacklisted,
485 (403, 20) => MerchantLimitExceed,
486 (403, 21) => SetLimitNotAllowed,
487 (403, 22) => TokenLimitInvalid,
488 (403, 23) => AccountLimitExceed,
489
490 (404, 0) => InvalidTransactionStatus,
491 (404, 1) => TransactionNotFound,
492 (404, 2) => InvalidRouting,
493 (404, 3) => BankNotSupportedBySwitch,
494 (404, 4) => TransactionCancelled,
495 (404, 5) => MerchantNotRegisteredForCardRegistrationServices,
496 (404, 6) => NeedToRequestOTP,
497 (404, 7) => JourneyNotFound,
498 (404, 8) => InvalidMerchant,
499 (404, 9) => NoIssuer,
500 (404, 10) => InvalidAPITransition,
501 (404, 11) => InvalidCardOrAccountOrCustomerOrVirtualAccount(String::new()),
502 (404, 12) => InvalidBillOrVirtualAccountWithReason(String::new()),
503 (404, 13) => InvalidAmount,
504 (404, 14) => PaidBill,
505 (404, 15) => InvalidOTP,
506 (404, 16) => PartnerNotFound,
507 (404, 17) => InvalidTerminal,
508 (404, 18) => InconsistentRequest,
509 (404, 19) => InvalidBillOrVirtualAccount,
510
511 (405, 0) => RequestedFunctionIsNotSupported,
512 (405, 1) => RequestedOperationIsNotAllowed,
513
514 (409, 0) => Conflict,
515 (409, 1) => DuplicatePartnerReferenceNo,
516
517 (429, 0) => TooManyRequests,
518
519 (500, 0) => GeneralError,
520 (500, 1) => InternalServerError,
521 (500, 2) => ExternalServerError,
522
523 (504, 0) => Timeout,
524
525 _ => return None,
526 })
527 }
528}