csobpg 0.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. csobpg/__init__.py +1 -0
  2. csobpg/http/__init__.py +17 -0
  3. csobpg/http/base.py +104 -0
  4. csobpg/http/requests_client.py +46 -0
  5. csobpg/http/urllib_client.py +62 -0
  6. csobpg/v19/__init__.py +18 -0
  7. csobpg/v19/api.py +209 -0
  8. csobpg/v19/errors.py +225 -0
  9. csobpg/v19/key.py +36 -0
  10. csobpg/v19/request/__init__.py +9 -0
  11. csobpg/v19/request/base.py +39 -0
  12. csobpg/v19/request/dttm.py +30 -0
  13. csobpg/v19/request/echo.py +16 -0
  14. csobpg/v19/request/fields.py +64 -0
  15. csobpg/v19/request/payment_close.py +26 -0
  16. csobpg/v19/request/payment_init/__init__.py +143 -0
  17. csobpg/v19/request/payment_init/cart.py +66 -0
  18. csobpg/v19/request/payment_init/currency.py +17 -0
  19. csobpg/v19/request/payment_init/customer/__init__.py +13 -0
  20. csobpg/v19/request/payment_init/customer/account.py +69 -0
  21. csobpg/v19/request/payment_init/customer/data.py +75 -0
  22. csobpg/v19/request/payment_init/customer/login.py +47 -0
  23. csobpg/v19/request/payment_init/order/__init__.py +16 -0
  24. csobpg/v19/request/payment_init/order/address.py +58 -0
  25. csobpg/v19/request/payment_init/order/data.py +142 -0
  26. csobpg/v19/request/payment_init/order/delivery.py +38 -0
  27. csobpg/v19/request/payment_init/payment.py +18 -0
  28. csobpg/v19/request/payment_init/webpage.py +41 -0
  29. csobpg/v19/request/payment_process.py +25 -0
  30. csobpg/v19/request/payment_refund.py +26 -0
  31. csobpg/v19/request/payment_reverse.py +19 -0
  32. csobpg/v19/request/payment_status.py +25 -0
  33. csobpg/v19/request/url.py +9 -0
  34. csobpg/v19/response/__init__.py +19 -0
  35. csobpg/v19/response/base.py +93 -0
  36. csobpg/v19/response/payment_close.py +66 -0
  37. csobpg/v19/response/payment_init.py +66 -0
  38. csobpg/v19/response/payment_process.py +76 -0
  39. csobpg/v19/response/payment_refund.py +13 -0
  40. csobpg/v19/response/payment_reverse.py +61 -0
  41. csobpg/v19/response/payment_status.py +319 -0
  42. csobpg/v19/signature.py +72 -0
  43. csobpg-0.0.1.dist-info/LICENSE +21 -0
  44. csobpg-0.0.1.dist-info/METADATA +160 -0
  45. csobpg-0.0.1.dist-info/RECORD +46 -0
  46. csobpg-0.0.1.dist-info/WHEEL +4 -0
csobpg/__init__.py ADDED
@@ -0,0 +1 @@
1
+ """The library package."""
@@ -0,0 +1,17 @@
1
+ """Package for dealing with HTTP."""
2
+
3
+ from .base import (
4
+ HTTPClient,
5
+ HTTPConnectionError,
6
+ HTTPRequestError,
7
+ HTTPResponse,
8
+ HTTPTimeoutError,
9
+ )
10
+
11
+ __all__ = [
12
+ "HTTPClient",
13
+ "HTTPConnectionError",
14
+ "HTTPRequestError",
15
+ "HTTPResponse",
16
+ "HTTPTimeoutError",
17
+ ]
csobpg/http/base.py ADDED
@@ -0,0 +1,104 @@
1
+ """Base client."""
2
+
3
+ import json as jsonlib
4
+ from abc import ABC, abstractmethod
5
+ from typing import Optional
6
+
7
+
8
+ class HTTPRequestError(Exception):
9
+ """Base HTTP request error."""
10
+
11
+
12
+ class HTTPConnectionError(HTTPRequestError):
13
+ """Any error related to connection."""
14
+
15
+
16
+ class HTTPTimeoutError(HTTPRequestError):
17
+ """HTTP request timed out."""
18
+
19
+
20
+ class HTTPInvalidResponseError(HTTPRequestError):
21
+ """HTTP response is invalid."""
22
+
23
+
24
+ class HTTPResponse:
25
+ """HTTP response wrapper."""
26
+
27
+ def __init__(
28
+ self, status_code: int, body: Optional[bytes], headers: dict
29
+ ) -> None:
30
+ self.status_code = status_code
31
+ self.body = body or b""
32
+ self._headers = headers
33
+
34
+ self._json = None
35
+
36
+ @property
37
+ # TODO: return dict
38
+ def json(self) -> Optional[dict]:
39
+ """Return body as JSON."""
40
+ if self._json is not None:
41
+ return self._json
42
+
43
+ headers = {key.lower(): val for key, val in self._headers.items()}
44
+ if "application/json" in headers.get("content-type", ""):
45
+ try:
46
+ self._json = jsonlib.loads(self.body)
47
+ except Exception as exc:
48
+ raise HTTPInvalidResponseError(
49
+ f"Invalid JSON in response: {exc}"
50
+ ) from exc
51
+
52
+ return self._json
53
+
54
+ def __str__(self) -> str:
55
+ return f"{self.__class__.__name__}(status={self.status_code})"
56
+
57
+ def __repr__(self) -> str:
58
+ return (
59
+ f"{self.__class__.__name__}("
60
+ f"status={self.status_code}, "
61
+ f"body={self.body}, "
62
+ f"headers={self._headers}"
63
+ ")"
64
+ )
65
+
66
+
67
+ class HTTPClient(ABC):
68
+ """Base HTTP client."""
69
+
70
+ def __init__(self, request_timeout: float = 5) -> None:
71
+ self.request_timeout = request_timeout
72
+
73
+ # pylint: disable=too-many-arguments
74
+ @abstractmethod
75
+ def _request(
76
+ self,
77
+ method: str,
78
+ url: str,
79
+ json: Optional[dict] = None,
80
+ headers: Optional[dict] = None,
81
+ ) -> HTTPResponse:
82
+ """Perform request.
83
+
84
+ This method must handle all possible HTTP exceptions and raise them
85
+ as `HTTPRequestError`.
86
+
87
+ Headers may be extended if necessary.
88
+ """
89
+
90
+ def request(
91
+ self,
92
+ method: str,
93
+ url: str,
94
+ json: Optional[dict] = None,
95
+ headers: Optional[dict] = None,
96
+ ) -> HTTPResponse:
97
+ """Perform HTTP request with a given HTTP method.
98
+
99
+ :param method: HTTP method to use
100
+ :param url: API URL
101
+ :param json: JSON data to post
102
+ :param headers: headers
103
+ """
104
+ return self._request(method, url, json, headers=headers)
@@ -0,0 +1,46 @@
1
+ """HTTP client which uses `requests` under the hood."""
2
+
3
+ from typing import Optional
4
+
5
+ import requests
6
+
7
+ from .base import (
8
+ HTTPClient,
9
+ HTTPConnectionError,
10
+ HTTPRequestError,
11
+ HTTPResponse,
12
+ HTTPTimeoutError,
13
+ )
14
+
15
+
16
+ class RequestsHTTPClient(HTTPClient):
17
+ """`requests` HTTP client."""
18
+
19
+ def __init__(self, request_timeout: float = 5) -> None:
20
+ super().__init__(request_timeout)
21
+ self._session = requests.Session()
22
+
23
+ def _request(
24
+ self,
25
+ method: str,
26
+ url: str,
27
+ json: Optional[dict] = None,
28
+ headers: Optional[dict] = None,
29
+ ) -> HTTPResponse:
30
+ try:
31
+ response: requests.Response = getattr(
32
+ self._session, method.lower()
33
+ )(url, json=json, timeout=self.request_timeout, headers=headers)
34
+ except ConnectionError as exc:
35
+ raise HTTPConnectionError(exc) from exc
36
+ except requests.Timeout as exc:
37
+ raise HTTPTimeoutError(exc) from exc
38
+ except requests.RequestException as exc:
39
+ raise HTTPRequestError(exc) from exc
40
+
41
+ return HTTPResponse(
42
+ response.status_code, response.content, dict(response.headers)
43
+ )
44
+
45
+ def __str__(self) -> str:
46
+ return self.__class__.__name__
@@ -0,0 +1,62 @@
1
+ """HTTP client which uses `urllib` under the hood."""
2
+
3
+ import json as _jsonlib
4
+ import urllib
5
+ import urllib.error
6
+ import urllib.parse
7
+ import urllib.request
8
+ from typing import Optional
9
+
10
+ from .base import (
11
+ HTTPClient,
12
+ HTTPConnectionError,
13
+ HTTPRequestError,
14
+ HTTPResponse,
15
+ HTTPTimeoutError,
16
+ )
17
+
18
+
19
+ class UrllibHTTPClient(HTTPClient):
20
+ """`urllib` HTTP client."""
21
+
22
+ # pylint: disable=too-many-arguments
23
+ def _request(
24
+ self,
25
+ method: str,
26
+ url: str,
27
+ json: Optional[dict] = None,
28
+ headers: Optional[dict] = None,
29
+ ) -> HTTPResponse:
30
+ headers = headers or {}
31
+ data = None
32
+
33
+ if json:
34
+ headers["Content-Type"] = "application/json"
35
+ data = _jsonlib.dumps(json).encode()
36
+
37
+ try:
38
+ with urllib.request.urlopen(
39
+ urllib.request.Request(
40
+ url,
41
+ data=data,
42
+ headers=headers,
43
+ method=method.upper(),
44
+ ),
45
+ timeout=self.request_timeout,
46
+ ) as response:
47
+ return HTTPResponse(
48
+ response.status, response.read(), dict(response.headers)
49
+ )
50
+ except ConnectionError as exc:
51
+ raise HTTPConnectionError(exc) from exc
52
+ except TimeoutError as exc:
53
+ raise HTTPTimeoutError(exc) from exc
54
+ except urllib.error.HTTPError as exc:
55
+ return HTTPResponse(
56
+ exc.status or 500, exc.read(), dict(exc.headers)
57
+ )
58
+ except urllib.error.URLError as exc:
59
+ raise HTTPRequestError(exc) from exc
60
+
61
+ def __str__(self) -> str:
62
+ return self.__class__.__name__
csobpg/v19/__init__.py ADDED
@@ -0,0 +1,18 @@
1
+ """Client for API v.1.9."""
2
+
3
+ from .api import APIClient
4
+ from .key import FileRSAKey, RAMRSAKey, RSAKey
5
+ from .request.payment_init.cart import Cart, CartItem
6
+ from .request.payment_init.currency import Currency
7
+ from .response import PaymentStatus
8
+
9
+ __all__ = (
10
+ "APIClient",
11
+ "Cart",
12
+ "CartItem",
13
+ "Currency",
14
+ "RAMRSAKey",
15
+ "FileRSAKey",
16
+ "RSAKey",
17
+ "PaymentStatus",
18
+ )
csobpg/v19/api.py ADDED
@@ -0,0 +1,209 @@
1
+ """API client."""
2
+
3
+ from typing import Optional, Union
4
+
5
+ from csobpg.http import HTTPClient
6
+ from csobpg.http.urllib_client import UrllibHTTPClient
7
+
8
+ from .key import FileRSAKey, RAMRSAKey, RSAKey
9
+ from .request import EchoRequest as _EchoRequest
10
+ from .request import PaymentCloseRequest as _PaymentCloseRequest
11
+ from .request import PaymentInitRequest as _PaymentInitRequest
12
+ from .request import PaymentProcessRequest as _PaymentProcessRequest
13
+ from .request import PaymentRefundRequest as _PaymentRefundRequest
14
+ from .request import PaymentReverseRequest as _PaymentReverseRequest
15
+ from .request import PaymentStatusRequest as _PaymentStatusRequest
16
+ from .request import payment_init as _payment_init
17
+ from .response import (
18
+ PaymentCloseResponse,
19
+ PaymentInitResponse,
20
+ PaymentProcessResponse,
21
+ PaymentRefundResponse,
22
+ PaymentReverseResponse,
23
+ PaymentStatusResponse,
24
+ )
25
+
26
+
27
+ class APIClient:
28
+ """API client."""
29
+
30
+ def __init__(
31
+ self,
32
+ merchant_id: str,
33
+ private_key: Union[str, RSAKey],
34
+ public_key: Union[str, RSAKey],
35
+ base_url: str = "https://api.platebnibrana.csob.cz/api/v1.9",
36
+ http_client: HTTPClient = UrllibHTTPClient(),
37
+ ) -> None:
38
+ # pylint:disable=too-many-arguments
39
+ self.merchant_id = merchant_id
40
+ self.base_url = base_url.rstrip("/")
41
+
42
+ if isinstance(private_key, str):
43
+ self.private_key = FileRSAKey(private_key)
44
+ else:
45
+ self.private_key = private_key
46
+
47
+ if isinstance(public_key, str):
48
+ self.public_key = RAMRSAKey(public_key)
49
+ else:
50
+ self.public_key = public_key
51
+
52
+ self._http_client = http_client
53
+
54
+ def init_payment(
55
+ self,
56
+ order_no: str,
57
+ total_amount: int,
58
+ return_url: str,
59
+ return_method: _payment_init.ReturnMethod = _payment_init.ReturnMethod.POST,
60
+ payment_operation: _payment_init.PaymentOperation = _payment_init.PaymentOperation.PAYMENT,
61
+ payment_method: _payment_init.PaymentMethod = _payment_init.PaymentMethod.CARD,
62
+ currency: _payment_init.Currency = _payment_init.Currency.CZK,
63
+ close_payment: bool = True,
64
+ ttl_sec: int = 600,
65
+ cart: Optional[_payment_init.Cart] = None,
66
+ customer: Optional[_payment_init.CustomerData] = None,
67
+ order: Optional[_payment_init.OrderData] = None,
68
+ merchant_data: Optional[bytes] = None,
69
+ customer_id: Optional[str] = None,
70
+ payment_expiry: Optional[int] = None,
71
+ # pylint:disable=line-too-long, too-many-locals
72
+ page_appearance: _payment_init.WebPageAppearanceConfig = _payment_init.WebPageAppearanceConfig(),
73
+ ) -> PaymentInitResponse:
74
+ """Init payment."""
75
+ request = _PaymentInitRequest(
76
+ self.merchant_id,
77
+ str(self.private_key),
78
+ order_no=order_no,
79
+ total_amount=total_amount,
80
+ return_url=return_url,
81
+ return_method=return_method,
82
+ payment_operation=payment_operation,
83
+ payment_method=payment_method,
84
+ currency=currency,
85
+ close_payment=close_payment,
86
+ ttl_sec=ttl_sec,
87
+ cart=cart,
88
+ customer=customer,
89
+ order=order,
90
+ merchant_data=merchant_data,
91
+ customer_id=customer_id,
92
+ payment_expiry=payment_expiry,
93
+ page_appearance=page_appearance,
94
+ )
95
+ return PaymentInitResponse.from_json(
96
+ self._call_api(
97
+ "post",
98
+ self._build_url(request.endpoint),
99
+ json=request.to_json(),
100
+ ),
101
+ str(self.public_key),
102
+ )
103
+
104
+ def get_payment_status(self, pay_id: str) -> PaymentStatusResponse:
105
+ """Request payment status information."""
106
+ request = _PaymentStatusRequest(
107
+ self.merchant_id, str(self.private_key), pay_id
108
+ )
109
+ return PaymentStatusResponse.from_json(
110
+ self._call_api("get", url=self._build_url(request.endpoint)),
111
+ str(self.public_key),
112
+ )
113
+
114
+ def reverse_payment(self, pay_id: str) -> PaymentReverseResponse:
115
+ """Reverse payment.
116
+
117
+ :param pay_id: payment ID
118
+ """
119
+ request = _PaymentReverseRequest(
120
+ self.merchant_id, str(self.private_key), pay_id
121
+ )
122
+ return PaymentReverseResponse.from_json(
123
+ self._call_api(
124
+ "put", self._build_url(request.endpoint), request.to_json()
125
+ ),
126
+ str(self.public_key),
127
+ )
128
+
129
+ def close_payment(
130
+ self, pay_id: str, total_amount: Optional[int] = None
131
+ ) -> PaymentCloseResponse:
132
+ """Close payment (move to settlement).
133
+
134
+ :param total_amount: close the payment with this amount. It must be
135
+ less or equal to the original amount and provided in hundredths of
136
+ the base currency
137
+ """
138
+ request = _PaymentCloseRequest(
139
+ self.merchant_id, str(self.private_key), pay_id, total_amount
140
+ )
141
+ return PaymentCloseResponse.from_json(
142
+ self._call_api(
143
+ "put",
144
+ self._build_url(request.endpoint),
145
+ json=request.to_json(),
146
+ ),
147
+ str(self.public_key),
148
+ )
149
+
150
+ def refund_payment(
151
+ self, pay_id: str, amount: Optional[int] = None
152
+ ) -> PaymentRefundResponse:
153
+ """Refund payment.
154
+
155
+ :param pay_id: payment ID
156
+ :param amount: amount to refund. It must be less or equal to the
157
+ original amount and provided in hundredths of the base currency.
158
+ If not provided, the full amount will be refunded.
159
+ """
160
+ request = _PaymentRefundRequest(
161
+ self.merchant_id, str(self.private_key), pay_id, amount
162
+ )
163
+ return PaymentRefundResponse.from_json(
164
+ self._call_api(
165
+ "put", self._build_url(request.endpoint), request.to_json()
166
+ ),
167
+ str(self.public_key),
168
+ )
169
+
170
+ def get_payment_process_url(self, pay_id: str) -> str:
171
+ """Build payment URL.
172
+
173
+ :param pay_id: pay_id obtained from `payment_init`
174
+ :return: url to process payment
175
+ """
176
+ return self._build_url(
177
+ _PaymentProcessRequest(
178
+ self.merchant_id, str(self.private_key), pay_id
179
+ ).endpoint
180
+ )
181
+
182
+ def echo(self) -> None:
183
+ """Make an echo request."""
184
+ request = _EchoRequest(self.merchant_id, str(self.private_key))
185
+ self._call_api(
186
+ "post", self._build_url(request.endpoint), request.to_json()
187
+ )
188
+
189
+ def process_gateway_return(self, datadict: dict) -> PaymentProcessResponse:
190
+ """Process gateway return."""
191
+ data = {}
192
+
193
+ for key in datadict:
194
+ data[key] = (
195
+ int(datadict[key])
196
+ if key in ("resultCode", "paymentStatus")
197
+ else datadict[key]
198
+ )
199
+
200
+ return PaymentProcessResponse.from_json(data, str(self.public_key))
201
+
202
+ def _call_api(
203
+ self, method: str, url: str, json: Optional[dict] = None
204
+ ) -> dict:
205
+ http_response = self._http_client.request(method, url, json)
206
+ return http_response.json or {}
207
+
208
+ def _build_url(self, endpoint: str) -> str:
209
+ return f"{self.base_url}/{endpoint.strip('/')}/"
csobpg/v19/errors.py ADDED
@@ -0,0 +1,225 @@
1
+ """API errors."""
2
+
3
+
4
+ class APIClientError(Exception):
5
+ """API client error."""
6
+
7
+
8
+ class APIInvalidSignatureError(APIClientError):
9
+ """API returned invalid signature."""
10
+
11
+
12
+ class APIError(Exception):
13
+ """API error."""
14
+
15
+ def __init__(self, code: int, message: str) -> None:
16
+ """Init API error.
17
+
18
+ :param code: error code
19
+ :message: error message
20
+ """
21
+ self.code = code
22
+ self.message = message
23
+ super().__init__(f"{self.code}: {self.message}")
24
+
25
+
26
+ class APIMissingParamError(APIError):
27
+ """API missing param error."""
28
+
29
+ def __init__(self, message: str) -> None:
30
+ super().__init__(100, message)
31
+
32
+
33
+ class APIInvalidParamError(APIError):
34
+ """API invalid param error."""
35
+
36
+ def __init__(self, message: str) -> None:
37
+ super().__init__(110, message)
38
+
39
+
40
+ class APIMerchantBlockedError(APIError):
41
+ """API merchant is blocked error."""
42
+
43
+ def __init__(self, message: str) -> None:
44
+ super().__init__(120, message)
45
+
46
+
47
+ class APISessionExpiredError(APIError):
48
+ """API session (request) expired error."""
49
+
50
+ def __init__(self, message: str) -> None:
51
+ super().__init__(130, message)
52
+
53
+
54
+ class APIPaymentNotFoundError(APIError):
55
+ """API payment not found error."""
56
+
57
+ def __init__(self, message: str) -> None:
58
+ super().__init__(140, message)
59
+
60
+
61
+ class APIPaymentInInvalidStateError(APIError):
62
+ """API payment is in invalid state error."""
63
+
64
+ def __init__(self, message: str) -> None:
65
+ super().__init__(150, message)
66
+
67
+
68
+ class APIPaymentMethodDisabledError(APIError):
69
+ """API payment method is disabled error."""
70
+
71
+ def __init__(self, message: str) -> None:
72
+ super().__init__(160, message)
73
+
74
+
75
+ class APIPaymentMethodUnavailableError(APIError):
76
+ """API payment method is unavailable error."""
77
+
78
+ def __init__(self, message: str) -> None:
79
+ super().__init__(170, message)
80
+
81
+
82
+ class APIOperationNotAllowedError(APIError):
83
+ """API operation is not allowed error."""
84
+
85
+ def __init__(self, message: str) -> None:
86
+ super().__init__(180, message)
87
+
88
+
89
+ class APIPaymentMethodError(APIError):
90
+ """API payment method error."""
91
+
92
+ def __init__(self, message: str) -> None:
93
+ super().__init__(190, message)
94
+
95
+
96
+ class APIDuplicatePurchaseIDError(APIError):
97
+ """API duplicate purchaseId error."""
98
+
99
+ def __init__(self, message: str) -> None:
100
+ super().__init__(200, message)
101
+
102
+
103
+ class APIEETRejectedError(APIError):
104
+ """API EET rejected error."""
105
+
106
+ def __init__(self, message: str) -> None:
107
+ super().__init__(500, message)
108
+
109
+
110
+ class APIMallPaymentPrecheckDeclinedError(APIError):
111
+ """API mall payment declined in pre-check error."""
112
+
113
+ def __init__(self, message: str) -> None:
114
+ super().__init__(600, message)
115
+
116
+
117
+ class APIOneClickTemplateNotFoundError(APIError):
118
+ """API one click template not found error."""
119
+
120
+ def __init__(self, message: str) -> None:
121
+ super().__init__(700, message)
122
+
123
+
124
+ class APIOneClickTemplatePaymentExpiredError(APIError):
125
+ """API one click template payment expired error."""
126
+
127
+ def __init__(self, message: str) -> None:
128
+ super().__init__(710, message)
129
+
130
+
131
+ class APIOneClickTemplateCardExpiredError(APIError):
132
+ """API one click template card expired error."""
133
+
134
+ def __init__(self, message: str) -> None:
135
+ super().__init__(720, message)
136
+
137
+
138
+ class APIOneClickTemplateCustomerRejectedError(APIError):
139
+ """API one click template customer rejected error.
140
+
141
+ the OneClick template was cancelled at the customer's request.
142
+ """
143
+
144
+ def __init__(self, message: str) -> None:
145
+ super().__init__(730, message)
146
+
147
+
148
+ class APIOneClickTemplatePaymentReversedError(APIError):
149
+ """API one click template payment reversed error."""
150
+
151
+ def __init__(self, message: str) -> None:
152
+ super().__init__(740, message)
153
+
154
+
155
+ class APICardholderAccountClosedError(APIError):
156
+ """API cardholder account closed error."""
157
+
158
+ def __init__(self, message: str) -> None:
159
+ super().__init__(750, message)
160
+
161
+
162
+ class APICustomerNotFoundError(APIError):
163
+ """API customer not found error."""
164
+
165
+ def __init__(self, message: str) -> None:
166
+ super().__init__(800, message)
167
+
168
+
169
+ class APICustomerFoundNoSavedCardsError(APIError):
170
+ """API customer found no saved cards error."""
171
+
172
+ def __init__(self, message: str) -> None:
173
+ super().__init__(810, message)
174
+
175
+
176
+ class APICustomerFoundSavedCardsFoundError(APIError):
177
+ """API customer found saved cards found error."""
178
+
179
+ def __init__(self, message: str) -> None:
180
+ super().__init__(820, message)
181
+
182
+
183
+ class APIInternalError(APIError):
184
+ """API internal error."""
185
+
186
+ def __init__(self, message: str) -> None:
187
+ super().__init__(900, message)
188
+
189
+
190
+ _ERROR_FOR_CODE = {
191
+ 100: APIMissingParamError,
192
+ 110: APIInvalidParamError,
193
+ 120: APIMerchantBlockedError,
194
+ 130: APISessionExpiredError,
195
+ 140: APIPaymentNotFoundError,
196
+ 150: APIPaymentInInvalidStateError,
197
+ 160: APIPaymentMethodDisabledError,
198
+ 170: APIPaymentMethodUnavailableError,
199
+ 180: APIOperationNotAllowedError,
200
+ 190: APIPaymentMethodError,
201
+ 200: APIDuplicatePurchaseIDError,
202
+ 500: APIEETRejectedError,
203
+ 600: APIMallPaymentPrecheckDeclinedError,
204
+ 700: APIOneClickTemplateNotFoundError,
205
+ 710: APIOneClickTemplatePaymentExpiredError,
206
+ 720: APIOneClickTemplateCardExpiredError,
207
+ 730: APIOneClickTemplateCustomerRejectedError,
208
+ 740: APIOneClickTemplatePaymentReversedError,
209
+ 750: APICardholderAccountClosedError,
210
+ 800: APICustomerNotFoundError,
211
+ 810: APICustomerFoundNoSavedCardsError,
212
+ 820: APICustomerFoundSavedCardsFoundError,
213
+ 900: APIInternalError,
214
+ }
215
+
216
+
217
+ def raise_for_result_code(result_code: int, result_message: str) -> None:
218
+ """Raise APIError if resultCode != 0."""
219
+ if result_code == 0:
220
+ return
221
+
222
+ try:
223
+ raise _ERROR_FOR_CODE[result_code](result_message)
224
+ except KeyError:
225
+ raise APIError(result_code, result_message) from None