Coverage for functions \ flipdare \ error \ stripe_error_context.py: 80%
49 statements
« prev ^ index » next coverage.py v7.13.0, created at 2026-05-08 12:22 +1000
« prev ^ index » next coverage.py v7.13.0, created at 2026-05-08 12:22 +1000
1#!/usr/bin/env python
2# Copyright (c) 2026 Flipdare Pty Ltd. All rights reserved.
3#
4# This file is part of Flipdare's proprietary software and contains
5# confidential and copyrighted material. Unauthorised copying,
6# modification, distribution, or use of this file is strictly
7# prohibited without prior written permission from Flipdare Pty Ltd.
8#
9# This software includes third-party components licensed under MIT,
10# BSD, and Apache 2.0 licences. See THIRD_PARTY_NOTICES for details.
11#
13from typing import Any, Self
14from flipdare.app_log import LOG
15from flipdare.error.app_error_protocol import AppErrorProtocol
16from flipdare.error.error_context import ErrorContext
17from flipdare.error.formatted_stripe_error import FormattedStripeError
18from flipdare.generated.shared.app_payment_error_code import AppPaymentErrorCode
19from flipdare.message.error_message import ErrorMessage
20from flipdare.payments.payment_types import KnownStripeErrorType
21from flipdare.payments.core.stripe_guard import StripeGuard
23__all__ = ["StripeErrorContext"]
26class StripeErrorContext(ErrorContext):
28 def __init__(
29 self,
30 endpoint: str,
31 *,
32 error_code: AppErrorProtocol,
33 message: str,
34 cause: str | None = None,
35 error: Exception | None = None,
36 ) -> None:
37 super().__init__(
38 endpoint=endpoint,
39 error_code=error_code,
40 message=message,
41 cause=cause,
42 error=error,
43 )
45 @classmethod
46 def from_stripe_error(
47 cls,
48 endpoint: str,
49 error: KnownStripeErrorType,
50 cause: str | None = None,
51 ) -> Self:
52 formatted = FormattedStripeError.from_exception(error)
53 LOG().error(str(formatted)) # fixme: this is a hack. we need to restructure error code.
54 msg = formatted.friendly_user_message
55 return cls(
56 endpoint=endpoint,
57 error_code=formatted.error_code,
58 message=msg,
59 cause=cause,
60 error=error,
61 )
63 @classmethod
64 def from_code(
65 cls,
66 endpoint: str,
67 error_code: AppPaymentErrorCode,
68 pledge_id: str | None = None,
69 intent_id: str | None = None,
70 cause: str | None = None,
71 error: Any | None = None,
72 ) -> Self:
73 from flipdare.error.app_error import AppError
75 message = cls.get_user_message_for_code(
76 error_code,
77 pledge_id=pledge_id,
78 intent_id=intent_id,
79 )
81 if StripeGuard.is_stripe_error(error):
82 error = cls._try_from_stripe_error(
83 endpoint=endpoint,
84 error=error,
85 cause=cause,
86 )
87 if error is not None:
88 return error
90 if isinstance(error, AppError):
91 return cls(
92 endpoint=endpoint,
93 error_code=error_code,
94 message=message,
95 cause=error.message,
96 error=error,
97 )
98 else:
99 return cls(
100 endpoint=endpoint,
101 error_code=error_code,
102 message=message,
103 cause=cause,
104 error=error,
105 )
107 @classmethod
108 def _try_from_stripe_error(
109 cls,
110 endpoint: str,
111 error: Any,
112 cause: str | None = None,
113 ) -> Self | None:
114 if not StripeGuard.is_stripe_error(error):
115 return None
117 formatted = FormattedStripeError.from_exception(error)
118 LOG().error(str(formatted)) # fixme: this is a hack. we need to restructure error code.
119 msg = formatted.friendly_user_message
120 return cls(
121 endpoint=endpoint,
122 error_code=formatted.error_code,
123 message=msg,
124 cause=cause,
125 error=error,
126 )
128 @staticmethod
129 def get_user_message_for_code(
130 error_code: AppPaymentErrorCode,
131 pledge_id: str | None = None,
132 intent_id: str | None = None,
133 ) -> str:
134 user_message = ErrorMessage.for_payment(error_code)
135 if user_message is None:
136 LOG().error(f"No user message found for error code: {error_code}")
137 return ErrorMessage.STR_UNKNOWN_ERROR.formatted_payment_error()
139 try:
140 return user_message.formatted_payment_error(
141 pledge_id=pledge_id,
142 intent_id=intent_id,
143 )
144 except Exception as e:
145 LOG().error(f"Error formatting user message for error code {error_code}: {e}")
146 return ErrorMessage.STR_UNKNOWN_ERROR.formatted_payment_error()