async_yookassa 0.1.0__tar.gz
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.
- async_yookassa-0.1.0/LICENSE +21 -0
- async_yookassa-0.1.0/PKG-INFO +92 -0
- async_yookassa-0.1.0/README.md +75 -0
- async_yookassa-0.1.0/async_yookassa/__init__.py +7 -0
- async_yookassa-0.1.0/async_yookassa/apiclient.py +152 -0
- async_yookassa-0.1.0/async_yookassa/configuration.py +104 -0
- async_yookassa-0.1.0/async_yookassa/enums/__init__.py +0 -0
- async_yookassa-0.1.0/async_yookassa/enums/candellation_details_enums.py +30 -0
- async_yookassa-0.1.0/async_yookassa/enums/card_enums.py +25 -0
- async_yookassa-0.1.0/async_yookassa/enums/confirmation_enums.py +9 -0
- async_yookassa-0.1.0/async_yookassa/enums/fiscalization_enums.py +17 -0
- async_yookassa-0.1.0/async_yookassa/enums/me_enums.py +12 -0
- async_yookassa-0.1.0/async_yookassa/enums/payment_method_data_enums.py +14 -0
- async_yookassa-0.1.0/async_yookassa/enums/payment_method_enums.py +21 -0
- async_yookassa-0.1.0/async_yookassa/enums/payment_response_enums.py +14 -0
- async_yookassa-0.1.0/async_yookassa/enums/receiver_enums.py +7 -0
- async_yookassa-0.1.0/async_yookassa/enums/transfers_enums.py +8 -0
- async_yookassa-0.1.0/async_yookassa/enums/vat_data_enums.py +14 -0
- async_yookassa-0.1.0/async_yookassa/exceptions/__init__.py +0 -0
- async_yookassa-0.1.0/async_yookassa/exceptions/api_error.py +6 -0
- async_yookassa-0.1.0/async_yookassa/exceptions/authorize_error.py +9 -0
- async_yookassa-0.1.0/async_yookassa/exceptions/bad_request_error.py +9 -0
- async_yookassa-0.1.0/async_yookassa/exceptions/configuration_errors.py +6 -0
- async_yookassa-0.1.0/async_yookassa/exceptions/forbidden_error.py +9 -0
- async_yookassa-0.1.0/async_yookassa/exceptions/not_found_error.py +9 -0
- async_yookassa-0.1.0/async_yookassa/exceptions/response_processing_error.py +9 -0
- async_yookassa-0.1.0/async_yookassa/exceptions/too_many_request_error.py +9 -0
- async_yookassa-0.1.0/async_yookassa/exceptions/unauthorized_error.py +11 -0
- async_yookassa-0.1.0/async_yookassa/models/__init__.py +0 -0
- async_yookassa-0.1.0/async_yookassa/models/configuration_submodels/__init__.py +0 -0
- async_yookassa-0.1.0/async_yookassa/models/configuration_submodels/version_model.py +9 -0
- async_yookassa-0.1.0/async_yookassa/models/me_model.py +19 -0
- async_yookassa-0.1.0/async_yookassa/models/me_submodels/__init__.py +0 -0
- async_yookassa-0.1.0/async_yookassa/models/me_submodels/fiscalization_model.py +8 -0
- async_yookassa-0.1.0/async_yookassa/models/payment_request_model.py +79 -0
- async_yookassa-0.1.0/async_yookassa/models/payment_response_model.py +50 -0
- async_yookassa-0.1.0/async_yookassa/models/payment_submodels/__init__.py +0 -0
- async_yookassa-0.1.0/async_yookassa/models/payment_submodels/airline_model.py +57 -0
- async_yookassa-0.1.0/async_yookassa/models/payment_submodels/airline_submodels/__init__.py +0 -0
- async_yookassa-0.1.0/async_yookassa/models/payment_submodels/airline_submodels/legs_model.py +56 -0
- async_yookassa-0.1.0/async_yookassa/models/payment_submodels/airline_submodels/passengers_model.py +6 -0
- async_yookassa-0.1.0/async_yookassa/models/payment_submodels/amount_model.py +35 -0
- async_yookassa-0.1.0/async_yookassa/models/payment_submodels/authorization_details_model.py +11 -0
- async_yookassa-0.1.0/async_yookassa/models/payment_submodels/authorization_details_submodels/__init__.py +0 -0
- async_yookassa-0.1.0/async_yookassa/models/payment_submodels/authorization_details_submodels/three_d_secure_model.py +5 -0
- async_yookassa-0.1.0/async_yookassa/models/payment_submodels/cancellation_details_model.py +10 -0
- async_yookassa-0.1.0/async_yookassa/models/payment_submodels/confirmation_model.py +54 -0
- async_yookassa-0.1.0/async_yookassa/models/payment_submodels/deal_model.py +10 -0
- async_yookassa-0.1.0/async_yookassa/models/payment_submodels/deal_submodels/__init__.py +0 -0
- async_yookassa-0.1.0/async_yookassa/models/payment_submodels/deal_submodels/settlements_model.py +8 -0
- async_yookassa-0.1.0/async_yookassa/models/payment_submodels/invoice_details_model.py +5 -0
- async_yookassa-0.1.0/async_yookassa/models/payment_submodels/payment_method_data_model.py +43 -0
- async_yookassa-0.1.0/async_yookassa/models/payment_submodels/payment_method_model.py +60 -0
- async_yookassa-0.1.0/async_yookassa/models/payment_submodels/payment_method_submodels/__init__.py +0 -0
- async_yookassa-0.1.0/async_yookassa/models/payment_submodels/payment_method_submodels/articles_model.py +25 -0
- async_yookassa-0.1.0/async_yookassa/models/payment_submodels/payment_method_submodels/card_model.py +58 -0
- async_yookassa-0.1.0/async_yookassa/models/payment_submodels/payment_method_submodels/card_product_model.py +6 -0
- async_yookassa-0.1.0/async_yookassa/models/payment_submodels/payment_method_submodels/electronic_certificate_model.py +15 -0
- async_yookassa-0.1.0/async_yookassa/models/payment_submodels/payment_method_submodels/payer_bank_details_model.py +18 -0
- async_yookassa-0.1.0/async_yookassa/models/payment_submodels/payment_method_submodels/vat_data_model.py +27 -0
- async_yookassa-0.1.0/async_yookassa/models/payment_submodels/receipt_model.py +24 -0
- async_yookassa-0.1.0/async_yookassa/models/payment_submodels/receipt_submodels/__init__.py +0 -0
- async_yookassa-0.1.0/async_yookassa/models/payment_submodels/receipt_submodels/customer_model.py +8 -0
- async_yookassa-0.1.0/async_yookassa/models/payment_submodels/receipt_submodels/mark_code_info_model.py +15 -0
- async_yookassa-0.1.0/async_yookassa/models/payment_submodels/receipt_submodels/mark_quantity_model.py +6 -0
- async_yookassa-0.1.0/async_yookassa/models/payment_submodels/receipt_submodels/payment_subject_industry_details_model.py +26 -0
- async_yookassa-0.1.0/async_yookassa/models/payment_submodels/receipt_submodels/receipt_item_model.py +67 -0
- async_yookassa-0.1.0/async_yookassa/models/payment_submodels/receipt_submodels/receipt_operational_details_model.py +9 -0
- async_yookassa-0.1.0/async_yookassa/models/payment_submodels/receiver_model.py +30 -0
- async_yookassa-0.1.0/async_yookassa/models/payment_submodels/recipient_model.py +9 -0
- async_yookassa-0.1.0/async_yookassa/models/payment_submodels/transfers_model.py +24 -0
- async_yookassa-0.1.0/async_yookassa/models/user_agent_model.py +84 -0
- async_yookassa-0.1.0/async_yookassa/payment.py +65 -0
- async_yookassa-0.1.0/pyproject.toml +18 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Ivan Ashikhmin
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: async_yookassa
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary:
|
|
5
|
+
Author: prodream
|
|
6
|
+
Author-email: sushkoos@gmail.com
|
|
7
|
+
Requires-Python: >=3.12,<4.0
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
11
|
+
Requires-Dist: distro (>=1.9.0,<2.0.0)
|
|
12
|
+
Requires-Dist: httpx (>=0.27.2,<0.28.0)
|
|
13
|
+
Requires-Dist: pre-commit (>=4.0.1,<5.0.0)
|
|
14
|
+
Requires-Dist: pydantic[email] (>=2.9.2,<3.0.0)
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
|
|
17
|
+
# Async YooKassa (unofficial)
|
|
18
|
+
|
|
19
|
+
Неофициальный клиент для работы с платежами по [API ЮKassa](https://yookassa.ru/developers/api)
|
|
20
|
+
|
|
21
|
+
За основу взята [официальная библиотека от ЮМани](https://git.yoomoney.ru/projects/SDK/repos/yookassa-sdk-python/browse).
|
|
22
|
+
|
|
23
|
+
## Цель
|
|
24
|
+
Заменить синхронный `requests` на асинхронный `httpx`, также переложить валидацию данных на `Pydantic`.
|
|
25
|
+
|
|
26
|
+
## Реализовано на данный момент
|
|
27
|
+
|
|
28
|
+
* Модели данных запроса и ответа платежа, а также необходимые для них модели.
|
|
29
|
+
* Класс `Configuration`, для определения авторизации по апи.
|
|
30
|
+
* Класс `Payment` с возможностью создать платёж.
|
|
31
|
+
* Класс `APIClient` для выполнения запросов к API.
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
## Требования
|
|
35
|
+
|
|
36
|
+
1. Python >=3.12 (на момент разработки)
|
|
37
|
+
2. pip
|
|
38
|
+
|
|
39
|
+
## Установка
|
|
40
|
+
### C помощью pip
|
|
41
|
+
|
|
42
|
+
1. Установите pip.
|
|
43
|
+
2. В консоли выполните команду
|
|
44
|
+
```bash
|
|
45
|
+
pip install --upgrade yookassa
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Начало работы
|
|
49
|
+
|
|
50
|
+
1. Импортируйте модуль
|
|
51
|
+
```python
|
|
52
|
+
import async_yookassa
|
|
53
|
+
```
|
|
54
|
+
2. Установите данные для конфигурации
|
|
55
|
+
```python
|
|
56
|
+
from async_yookassa import Configuration
|
|
57
|
+
|
|
58
|
+
Configuration.configure(account_id='<Идентификатор магазина>', secret_key='<Секретный ключ>')
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
или
|
|
62
|
+
|
|
63
|
+
```python
|
|
64
|
+
from async_yookassa import Configuration
|
|
65
|
+
|
|
66
|
+
Configuration.account_id = '<Идентификатор магазина>'
|
|
67
|
+
Configuration.secret_key = '<Секретный ключ>'
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
или через oauth
|
|
71
|
+
|
|
72
|
+
```python
|
|
73
|
+
from async_yookassa import Configuration
|
|
74
|
+
|
|
75
|
+
Configuration.configure_auth_token(token='<Oauth Token>')
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Если вы согласны участвовать в развитии SDK, вы можете передать данные о вашем фреймворке, cms или модуле:
|
|
79
|
+
```python
|
|
80
|
+
from async_yookassa import Configuration
|
|
81
|
+
from async_yookassa.models.configuration_submodels.version_model import Version
|
|
82
|
+
|
|
83
|
+
Configuration.configure('<Идентификатор магазина>', '<Секретный ключ>')
|
|
84
|
+
Configuration.configure_user_agent(
|
|
85
|
+
framework=Version(name='Django', version='2.2.3'),
|
|
86
|
+
cms=Version(name='Wagtail', version='2.6.2'),
|
|
87
|
+
module=Version(name='Y.CMS', version='0.0.1')
|
|
88
|
+
)
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
3. Вызовите нужный метод API. [Подробнее в документации к API ЮKassa](https://yookassa.ru/developers/api)
|
|
92
|
+
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Async YooKassa (unofficial)
|
|
2
|
+
|
|
3
|
+
Неофициальный клиент для работы с платежами по [API ЮKassa](https://yookassa.ru/developers/api)
|
|
4
|
+
|
|
5
|
+
За основу взята [официальная библиотека от ЮМани](https://git.yoomoney.ru/projects/SDK/repos/yookassa-sdk-python/browse).
|
|
6
|
+
|
|
7
|
+
## Цель
|
|
8
|
+
Заменить синхронный `requests` на асинхронный `httpx`, также переложить валидацию данных на `Pydantic`.
|
|
9
|
+
|
|
10
|
+
## Реализовано на данный момент
|
|
11
|
+
|
|
12
|
+
* Модели данных запроса и ответа платежа, а также необходимые для них модели.
|
|
13
|
+
* Класс `Configuration`, для определения авторизации по апи.
|
|
14
|
+
* Класс `Payment` с возможностью создать платёж.
|
|
15
|
+
* Класс `APIClient` для выполнения запросов к API.
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
## Требования
|
|
19
|
+
|
|
20
|
+
1. Python >=3.12 (на момент разработки)
|
|
21
|
+
2. pip
|
|
22
|
+
|
|
23
|
+
## Установка
|
|
24
|
+
### C помощью pip
|
|
25
|
+
|
|
26
|
+
1. Установите pip.
|
|
27
|
+
2. В консоли выполните команду
|
|
28
|
+
```bash
|
|
29
|
+
pip install --upgrade yookassa
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Начало работы
|
|
33
|
+
|
|
34
|
+
1. Импортируйте модуль
|
|
35
|
+
```python
|
|
36
|
+
import async_yookassa
|
|
37
|
+
```
|
|
38
|
+
2. Установите данные для конфигурации
|
|
39
|
+
```python
|
|
40
|
+
from async_yookassa import Configuration
|
|
41
|
+
|
|
42
|
+
Configuration.configure(account_id='<Идентификатор магазина>', secret_key='<Секретный ключ>')
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
или
|
|
46
|
+
|
|
47
|
+
```python
|
|
48
|
+
from async_yookassa import Configuration
|
|
49
|
+
|
|
50
|
+
Configuration.account_id = '<Идентификатор магазина>'
|
|
51
|
+
Configuration.secret_key = '<Секретный ключ>'
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
или через oauth
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
from async_yookassa import Configuration
|
|
58
|
+
|
|
59
|
+
Configuration.configure_auth_token(token='<Oauth Token>')
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Если вы согласны участвовать в развитии SDK, вы можете передать данные о вашем фреймворке, cms или модуле:
|
|
63
|
+
```python
|
|
64
|
+
from async_yookassa import Configuration
|
|
65
|
+
from async_yookassa.models.configuration_submodels.version_model import Version
|
|
66
|
+
|
|
67
|
+
Configuration.configure('<Идентификатор магазина>', '<Секретный ключ>')
|
|
68
|
+
Configuration.configure_user_agent(
|
|
69
|
+
framework=Version(name='Django', version='2.2.3'),
|
|
70
|
+
cms=Version(name='Wagtail', version='2.6.2'),
|
|
71
|
+
module=Version(name='Y.CMS', version='0.0.1')
|
|
72
|
+
)
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
3. Вызовите нужный метод API. [Подробнее в документации к API ЮKassa](https://yookassa.ru/developers/api)
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
from base64 import b64encode
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
from httpx import AsyncClient, AsyncHTTPTransport, Response
|
|
5
|
+
|
|
6
|
+
from async_yookassa import Configuration
|
|
7
|
+
from async_yookassa.exceptions.api_error import APIError
|
|
8
|
+
from async_yookassa.exceptions.bad_request_error import BadRequestError
|
|
9
|
+
from async_yookassa.exceptions.forbidden_error import ForbiddenError
|
|
10
|
+
from async_yookassa.exceptions.not_found_error import NotFoundError
|
|
11
|
+
from async_yookassa.exceptions.response_processing_error import ResponseProcessingError
|
|
12
|
+
from async_yookassa.exceptions.too_many_request_error import TooManyRequestsError
|
|
13
|
+
from async_yookassa.exceptions.unauthorized_error import UnauthorizedError
|
|
14
|
+
from async_yookassa.models.payment_request_model import PaymentRequest
|
|
15
|
+
from async_yookassa.models.user_agent_model import UserAgent
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class APIClient:
|
|
19
|
+
"""
|
|
20
|
+
Класс клиента API.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
def __init__(self):
|
|
24
|
+
self.configuration = Configuration.instantiate()
|
|
25
|
+
self.endpoint = Configuration.api_endpoint()
|
|
26
|
+
self.account_id = self.configuration.account_id
|
|
27
|
+
self.secret_key = self.configuration.secret_key
|
|
28
|
+
self.auth_token = self.configuration.auth_token
|
|
29
|
+
self.transport = AsyncHTTPTransport(retries=self.configuration.max_attempts)
|
|
30
|
+
self.async_client = AsyncClient(timeout=self.configuration.timeout, transport=self.transport)
|
|
31
|
+
|
|
32
|
+
self.user_agent = UserAgent()
|
|
33
|
+
if self.configuration.agent_framework:
|
|
34
|
+
self.user_agent.framework = self.configuration.agent_framework
|
|
35
|
+
if self.configuration.agent_cms:
|
|
36
|
+
self.user_agent.cms = self.configuration.agent_cms
|
|
37
|
+
if self.configuration.agent_module:
|
|
38
|
+
self.user_agent.module = self.configuration.agent_module
|
|
39
|
+
|
|
40
|
+
async def request(
|
|
41
|
+
self,
|
|
42
|
+
body: PaymentRequest | None = None,
|
|
43
|
+
method: str = "",
|
|
44
|
+
path: str = "",
|
|
45
|
+
query_params: dict[str, str] | None = None,
|
|
46
|
+
headers: dict[str, str] | None = None,
|
|
47
|
+
) -> dict[str, Any]:
|
|
48
|
+
"""
|
|
49
|
+
Подготовка запроса.
|
|
50
|
+
|
|
51
|
+
:param method: HTTP метод
|
|
52
|
+
:param path: URL запроса
|
|
53
|
+
:param query_params: Словарь GET параметров запроса
|
|
54
|
+
:param headers: Словарь заголовков запроса
|
|
55
|
+
:param body: Тело запроса
|
|
56
|
+
:return: Ответ на запрос в формате JSON
|
|
57
|
+
"""
|
|
58
|
+
if isinstance(body, PaymentRequest):
|
|
59
|
+
body = body.model_dump()
|
|
60
|
+
|
|
61
|
+
request_headers = self.prepare_request_headers(headers=headers)
|
|
62
|
+
raw_response = await self.execute(
|
|
63
|
+
body=body, method=method, path=path, query_params=query_params, request_headers=request_headers
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
if raw_response.status_code != 200:
|
|
67
|
+
self.__handle_error(raw_response=raw_response)
|
|
68
|
+
|
|
69
|
+
return raw_response.json()
|
|
70
|
+
|
|
71
|
+
async def execute(
|
|
72
|
+
self,
|
|
73
|
+
method: str,
|
|
74
|
+
path: str,
|
|
75
|
+
request_headers: dict[str, str],
|
|
76
|
+
query_params: dict[str, str] | None = None,
|
|
77
|
+
body: dict[str, Any] | None = None,
|
|
78
|
+
) -> Response:
|
|
79
|
+
"""
|
|
80
|
+
Выполнение запроса.
|
|
81
|
+
|
|
82
|
+
:param body: Тело запроса
|
|
83
|
+
:param method: HTTP метод
|
|
84
|
+
:param path: URL запроса
|
|
85
|
+
:param query_params: Массив GET параметров запроса
|
|
86
|
+
:param request_headers: Массив заголовков запроса
|
|
87
|
+
:return: Response
|
|
88
|
+
"""
|
|
89
|
+
async with self.async_client as client:
|
|
90
|
+
# self.log_request(body, method, path, query_params, request_headers)
|
|
91
|
+
|
|
92
|
+
raw_response = await client.request(
|
|
93
|
+
method=method, url=self.endpoint + path, params=query_params, headers=request_headers, json=body
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
# self.log_response(raw_response.content, self.get_response_info(raw_response), raw_response.headers)
|
|
97
|
+
|
|
98
|
+
return raw_response
|
|
99
|
+
|
|
100
|
+
def prepare_request_headers(self, headers: dict[str, str]) -> dict[str, str]:
|
|
101
|
+
"""
|
|
102
|
+
Подготовка заголовков запроса.
|
|
103
|
+
|
|
104
|
+
:param headers: Словарь заголовков запроса
|
|
105
|
+
:return: Словарь заголовков запроса
|
|
106
|
+
"""
|
|
107
|
+
request_headers = {"Content-type": "application/json"}
|
|
108
|
+
if self.auth_token is not None:
|
|
109
|
+
auth_headers = {"Authorization": "Bearer " + self.auth_token}
|
|
110
|
+
else:
|
|
111
|
+
auth_headers = {"Authorization": self.basic_auth(self.account_id, self.secret_key)}
|
|
112
|
+
|
|
113
|
+
request_headers.update(auth_headers)
|
|
114
|
+
|
|
115
|
+
request_headers.update({"YM-User-Agent": self.user_agent.get_header_string()})
|
|
116
|
+
|
|
117
|
+
if isinstance(headers, dict):
|
|
118
|
+
request_headers.update(headers)
|
|
119
|
+
return request_headers
|
|
120
|
+
|
|
121
|
+
@staticmethod
|
|
122
|
+
def basic_auth(username: str, password: str) -> str:
|
|
123
|
+
"""
|
|
124
|
+
Формирование токена для Basic авторизации.
|
|
125
|
+
|
|
126
|
+
:param username: Идентификатор аккаунта
|
|
127
|
+
:param password: Секретный ключ магазина
|
|
128
|
+
:return: Строка авторизации
|
|
129
|
+
"""
|
|
130
|
+
token = b64encode(f"{username}:{password}".encode()).decode("ascii")
|
|
131
|
+
return f"Basic {token}"
|
|
132
|
+
|
|
133
|
+
@staticmethod
|
|
134
|
+
def __handle_error(raw_response):
|
|
135
|
+
"""
|
|
136
|
+
Выбрасывает исключение по коду ошибки.
|
|
137
|
+
"""
|
|
138
|
+
http_code = raw_response.status_code
|
|
139
|
+
if http_code == BadRequestError.HTTP_CODE:
|
|
140
|
+
raise BadRequestError(raw_response.json())
|
|
141
|
+
elif http_code == ForbiddenError.HTTP_CODE:
|
|
142
|
+
raise ForbiddenError(raw_response.json())
|
|
143
|
+
elif http_code == NotFoundError.HTTP_CODE:
|
|
144
|
+
raise NotFoundError(raw_response.json())
|
|
145
|
+
elif http_code == TooManyRequestsError.HTTP_CODE:
|
|
146
|
+
raise TooManyRequestsError(raw_response.json())
|
|
147
|
+
elif http_code == UnauthorizedError.HTTP_CODE:
|
|
148
|
+
raise UnauthorizedError(raw_response.json())
|
|
149
|
+
elif http_code == ResponseProcessingError.HTTP_CODE:
|
|
150
|
+
raise ResponseProcessingError(raw_response.json())
|
|
151
|
+
else:
|
|
152
|
+
raise APIError(raw_response.text)
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from typing import Self
|
|
3
|
+
|
|
4
|
+
from async_yookassa.exceptions.configuration_errors import ConfigurationError
|
|
5
|
+
from async_yookassa.models.configuration_submodels.version_model import Version
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@dataclass
|
|
9
|
+
class Configuration:
|
|
10
|
+
api_url: str = "https://api.yookassa.ru/v3"
|
|
11
|
+
account_id: str | None = None
|
|
12
|
+
secret_key: str | None = None
|
|
13
|
+
timeout: int = 1800
|
|
14
|
+
max_attempts: int = 3
|
|
15
|
+
auth_token: str | None = None
|
|
16
|
+
agent_framework: Version | None = None
|
|
17
|
+
agent_cms: Version | None = None
|
|
18
|
+
agent_module: Version | None = None
|
|
19
|
+
|
|
20
|
+
def __post_init__(self):
|
|
21
|
+
self.assert_has_api_credentials()
|
|
22
|
+
|
|
23
|
+
@classmethod
|
|
24
|
+
def configure(cls, account_id: str, secret_key: str, **kwargs) -> None:
|
|
25
|
+
"""
|
|
26
|
+
Устанавливает настройки конфигурации для базовой авторизации.
|
|
27
|
+
|
|
28
|
+
:param account_id: Идентификатор магазина.
|
|
29
|
+
:param secret_key: Секретный ключ.
|
|
30
|
+
:param kwargs: Словарь с дополнительными параметрами.
|
|
31
|
+
"""
|
|
32
|
+
cls.account_id = account_id
|
|
33
|
+
cls.secret_key = secret_key
|
|
34
|
+
cls.auth_token = None
|
|
35
|
+
cls.api_url = kwargs.get("api_url", cls.api_url)
|
|
36
|
+
cls.timeout = kwargs.get("timeout", cls.timeout)
|
|
37
|
+
cls.max_attempts = kwargs.get("max_attempts", cls.max_attempts)
|
|
38
|
+
|
|
39
|
+
@classmethod
|
|
40
|
+
def configure_auth_token(cls, token: str, **kwargs) -> None:
|
|
41
|
+
"""
|
|
42
|
+
Устанавливает настройки конфигурации для авторизации по OAuth.
|
|
43
|
+
|
|
44
|
+
:param token: Ключ OAuth.
|
|
45
|
+
:param kwargs: Словарь с дополнительными параметрами.
|
|
46
|
+
"""
|
|
47
|
+
cls.account_id = None
|
|
48
|
+
cls.secret_key = None
|
|
49
|
+
cls.auth_token = token
|
|
50
|
+
cls.api_url = kwargs.get("api_url", cls.api_url)
|
|
51
|
+
cls.timeout = kwargs.get("timeout", cls.timeout)
|
|
52
|
+
cls.max_attempts = kwargs.get("max_attempts", cls.max_attempts)
|
|
53
|
+
|
|
54
|
+
def configure_user_agent(
|
|
55
|
+
self, framework: Version | None = None, cms: Version | None = None, module: Version | None = None
|
|
56
|
+
) -> None:
|
|
57
|
+
"""
|
|
58
|
+
Устанавливает настройки конфигурации для User-Agent.
|
|
59
|
+
|
|
60
|
+
:param framework: Версия фреймворка.
|
|
61
|
+
:param cms: Версия CMS.
|
|
62
|
+
:param module: Версия модуля.
|
|
63
|
+
"""
|
|
64
|
+
if isinstance(framework, Version):
|
|
65
|
+
self.agent_framework = framework
|
|
66
|
+
if isinstance(cms, Version):
|
|
67
|
+
self.agent_cms = cms
|
|
68
|
+
if isinstance(module, Version):
|
|
69
|
+
self.agent_module = module
|
|
70
|
+
|
|
71
|
+
@classmethod
|
|
72
|
+
def instantiate(cls) -> Self:
|
|
73
|
+
"""
|
|
74
|
+
Получение объекта конфигурации.
|
|
75
|
+
|
|
76
|
+
:return: Объект конфигурации
|
|
77
|
+
"""
|
|
78
|
+
return cls(
|
|
79
|
+
account_id=cls.account_id,
|
|
80
|
+
secret_key=cls.secret_key,
|
|
81
|
+
timeout=cls.timeout,
|
|
82
|
+
max_attempts=cls.max_attempts,
|
|
83
|
+
auth_token=cls.auth_token,
|
|
84
|
+
agent_framework=cls.agent_framework,
|
|
85
|
+
agent_cms=cls.agent_cms,
|
|
86
|
+
agent_module=cls.agent_module,
|
|
87
|
+
api_url=cls.api_url,
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
@staticmethod
|
|
91
|
+
def api_endpoint() -> str:
|
|
92
|
+
"""Возвращает URL для API Кассы."""
|
|
93
|
+
return Configuration.api_url
|
|
94
|
+
|
|
95
|
+
def has_api_credentials(self) -> bool:
|
|
96
|
+
"""Проверка наличия параметров базовой авторизации."""
|
|
97
|
+
return self.account_id is not None and self.secret_key is not None
|
|
98
|
+
|
|
99
|
+
def assert_has_api_credentials(self) -> None:
|
|
100
|
+
"""Проверка наличия API параметров, выброс исключения ConfigurationError при ошибке."""
|
|
101
|
+
if self.auth_token is None and not self.has_api_credentials():
|
|
102
|
+
raise ConfigurationError("account_id and secret_key are required")
|
|
103
|
+
elif self.auth_token and self.has_api_credentials():
|
|
104
|
+
raise ConfigurationError("Could not configure authorization with both auth_token and basic auth")
|
|
File without changes
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class PartyEnum(str, Enum):
|
|
5
|
+
yoo_money = "yoo_money"
|
|
6
|
+
payment_network = "payment_network"
|
|
7
|
+
merchant = "merchant"
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class ReasonEnum(str, Enum):
|
|
11
|
+
three_d_secure_failed = "3d_secure_failed"
|
|
12
|
+
call_issuer = "call_issuer"
|
|
13
|
+
canceled_by_merchant = "canceled_by_merchant"
|
|
14
|
+
card_expired = "card_expired"
|
|
15
|
+
country_forbidden = "country_forbidden"
|
|
16
|
+
deal_expired = "deal_expired"
|
|
17
|
+
expired_on_capture = "expired_on_capture"
|
|
18
|
+
expired_on_confirmation = "expired_on_confirmation"
|
|
19
|
+
fraud_suspected = "fraud_suspected"
|
|
20
|
+
general_decline = "general_decline"
|
|
21
|
+
identification_required = "identification_required"
|
|
22
|
+
insufficient_funds = "insufficient_funds"
|
|
23
|
+
internal_timeout = "internal_timeout"
|
|
24
|
+
invalid_card_number = "invalid_card_number"
|
|
25
|
+
invalid_csc = "invalid_csc"
|
|
26
|
+
issuer_unavailable = "issuer_unavailable"
|
|
27
|
+
payment_method_limit_exceeded = "payment_method_limit_exceeded"
|
|
28
|
+
payment_method_restricted = "payment_method_restricted"
|
|
29
|
+
permission_revoked = "permission_revoked"
|
|
30
|
+
unsupported_mobile_operator = "unsupported_mobile_operator"
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class CardTypeEnum(str, Enum):
|
|
5
|
+
MasterCard = "MasterCard"
|
|
6
|
+
Visa = "Visa"
|
|
7
|
+
Mir = "Mir"
|
|
8
|
+
UnionPay = "UnionPay"
|
|
9
|
+
JCB = "JCB"
|
|
10
|
+
AmericanExpress = "AmericanExpress"
|
|
11
|
+
DinersClub = "DinersClub"
|
|
12
|
+
DiscoverCard = "DiscoverCard"
|
|
13
|
+
InstaPayment = "InstaPayment"
|
|
14
|
+
InstaPaymentTM = "InstaPaymentTM"
|
|
15
|
+
Laser = "Laser"
|
|
16
|
+
Dankort = "Dankort"
|
|
17
|
+
Solo = "Solo"
|
|
18
|
+
Switch = "Switch"
|
|
19
|
+
Unknown = "Unknown"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class SourceEnum(str, Enum):
|
|
23
|
+
mir_pay = "mir_pay"
|
|
24
|
+
apple_pay = "apple_pay"
|
|
25
|
+
google_pay = "google_pay"
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class FiscalizationProviderEnum(str, Enum):
|
|
5
|
+
fns = "fns"
|
|
6
|
+
avanpost = "avanpost"
|
|
7
|
+
a_qsi = "a_qsi"
|
|
8
|
+
atol = "atol"
|
|
9
|
+
business_ru = "business_ru"
|
|
10
|
+
evotor = "evotor"
|
|
11
|
+
first_ofd = "first_ofd"
|
|
12
|
+
kit_invest = "kit_invest"
|
|
13
|
+
life_pay = "life_pay"
|
|
14
|
+
mertrade = "mertrade"
|
|
15
|
+
modul_kassa = "modul_kassa"
|
|
16
|
+
rocket = "rocket"
|
|
17
|
+
shtrih_m = "shtrih_m"
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class PaymentMethodDataTypeEnum(str, Enum):
|
|
5
|
+
sber_loan = "sber_loan"
|
|
6
|
+
mobile_balance = "mobile_balance"
|
|
7
|
+
bank_card = "bank_card"
|
|
8
|
+
cash = "cash"
|
|
9
|
+
sbp = "sbp"
|
|
10
|
+
b2b_sberbank = "b2b_sberbank"
|
|
11
|
+
electronic_certificate = "electronic_certificate"
|
|
12
|
+
yoo_money = "yoo_money"
|
|
13
|
+
sberbank = "sberbank"
|
|
14
|
+
tinkoff_bank = "tinkoff_bank"
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class PaymentMethodTypeEnum(str, Enum):
|
|
5
|
+
sber_loan = "sber_loan"
|
|
6
|
+
alfabank = "alfabank"
|
|
7
|
+
mobile_balance = "mobile_balance"
|
|
8
|
+
bank_card = "bank_card"
|
|
9
|
+
installments = "installments"
|
|
10
|
+
cash = "cash"
|
|
11
|
+
sbp = "sbp"
|
|
12
|
+
b2b_sberbank = "b2b_sberbank"
|
|
13
|
+
electronic_certificate = "electronic_certificate"
|
|
14
|
+
yoo_money = "yoo_money"
|
|
15
|
+
apple_pay = "apple_pay"
|
|
16
|
+
google_pay = "google_pay"
|
|
17
|
+
qiwi = "qiwi"
|
|
18
|
+
sberbank = "sberbank"
|
|
19
|
+
tinkoff_bank = "tinkoff_bank"
|
|
20
|
+
wechat = "wechat"
|
|
21
|
+
webmoney = "webmoney"
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class PaymentResponseStatusEnum(str, Enum):
|
|
5
|
+
pending = "pending"
|
|
6
|
+
waiting_for_capture = "waiting_for_capture"
|
|
7
|
+
succeeded = "succeeded"
|
|
8
|
+
canceled = "canceled"
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class ReceiptRegistrationEnum(str, Enum):
|
|
12
|
+
pending = "pending"
|
|
13
|
+
succeeded = "succeeded"
|
|
14
|
+
canceled = "canceled"
|
|
File without changes
|