from __future__ import annotations
import stripe
[docs]
class DatatransPaymentError(Exception):
    pass 
[docs]
class DatatransApiError(DatatransPaymentError):
    def __init__(self, code: str, message: str, terminal: bool) -> None:
        super().__init__(f'{code}: {message}')
[docs]
        self.terminal = terminal 
 
[docs]
class SaferpayPaymentError(Exception):
    pass 
[docs]
class SaferpayApiError(SaferpayPaymentError):
    # the following errors should be fine to ignore on our end
    # full list of names: https://saferpay.github.io/jsonapi/#errorhandling
[docs]
    EXPECTED_ERROR_NAMES = frozenset((
        'BLOCKED_BY_RISK_MANAGEMENT',
        'CARD_CHECK_FAILED',
        'CARD_CVC_INVALID',
        'CARD_CVC_REQUIRED',
        'COMMUNICATION_FAILED',
        'COMMUNICATION_TIMEOUT',
        'GENERAL_DECLINED',
        'PAYER_AUTHENTICATION_REQUIRED',
        'PAYMENTMEANS_INVALID',
        'PAYMENTMEANS_NOT_SUPPORTED',
        '3DS_AUTHENTICATION_FAILED',
        'TRANSACTION_ABORTED',
        'TRANSACTION_DECLINED',
        'UNEXPECTED_ERROR_BY_ACQUIRER',
        'UPDATE_CARD_INFORMATION',
    )) 
    def __init__(
        self,
        name: str,
        message: str,
        behavior: str,
        detail: list[str] | None = None
    ) -> None:
        details = tuple(detail) if detail else ()
        super().__init__('\n'.join((
            f'{name}: {message}',
            *details,
        )))
[docs]
        self.behavior = behavior 
    @property
[docs]
    def not_started_or_is_expected_failure(self) -> bool:
        # this is not an expected failure after a redirect
        # but it is an expected failure when we try to cancel
        # stale transactions.
        return (
            self.name == 'TRANSACTION_NOT_STARTED'
            or self.is_expected_failure
        ) 
    @property
[docs]
    def is_expected_failure(self) -> bool:
        return self.name in self.EXPECTED_ERROR_NAMES 
 
# the following exceptions should be caught and logged - the user should be
# informed that the payment failed, but not why
[docs]
CARD_ERRORS = (
    stripe.CardError,
    DatatransPaymentError,
    SaferpayPaymentError,
)