· 4 years ago · May 10, 2021, 04:00 PM
1import functools
2import time
3from dataclasses import dataclass
4from functools import lru_cache
5from typing import Optional, Any, Union, Dict, List
6
7from glQiwiApi.core.abstracts import AbstractRouter
8from glQiwiApi.types import WrapperData
9from glQiwiApi.utils.basics import check_api_method
10
11
12@dataclass
13class QiwiSettings:
14 # Qiwi Wallet
15 TO_CARD: str = '/sinap/api/v2/terms/{privat_card_id}'
16
17 GET_BALANCE: str = '/funding-sources/v2/persons/{phone_number}/accounts'
18
19 TRANSACTIONS: str = '/payment-history/v2/persons/{stripped_number}/payments'
20
21 TO_WALLET: str = '/sinap/api/v2/terms/99/payments'
22
23 TRANSACTION_INFO: str = '/payment-history/v1/transactions/{transaction_id}'
24
25 CHECK_RESTRICTION: str = '/person-profile/v1/persons/{phone_number}/status/restrictions'
26
27 GET_IDENTIFICATION: str = '/identification/v1/persons/{phone_number}/identification'
28
29 GET_LIMITS: str = '/qw-limits/v1/persons/{stripped_number}/actual-limits'
30
31 GET_LIST_OF_CARDS: str = '/cards/v1/cards?vas-alias=qvc-master'
32
33 AUTHENTICATE: str = '/identification/v1/persons/{stripped_number}/identification'
34
35 GET_BILLS: str = '/checkout-api/api/bill/search'
36
37 GET_RECEIPT: str = '/payment-history/v1/transactions/{transaction_id}/cheque/file'
38
39 COMMISSION: str = '/sinap/providers/{special_code}/onlineCommission'
40
41 ACCOUNT_INFO: str = '/person-profile/v1/profile/current'
42
43 FETCH_STATISTICS: str = '/payment-history/v2/persons/{stripped_number}/payments/total'
44
45 LIST_OF_BALANCES: str = '/funding-sources/v2/persons/{stripped_number}/accounts'
46
47 CREATE_NEW_BALANCE: str = '/funding-sources/v2/persons/{stripped_number}/accounts'
48
49 AVAILABLE_BALANCES: str = '/funding-sources/v2/persons/{stripped_number}/accounts/offer'
50
51 SET_DEFAULT_BALANCE: str = '/funding-sources/v2/persons/{stripped_number}/accounts/{currency_alias}'
52
53 BUY_QIWI_MASTER: str = '/sinap/api/v2/terms/28004/payments'
54
55 _CONFIRM_QIWI_MASTER: str = '/cards/v2/persons/{stripped_number}/orders/{order_id}/submit'
56
57 CARDS_QIWI_MASTER: str = '/cards/v1/cards/?vas-alias=qvc-master'
58
59 PRE_QIWI_REQUEST: str = '/cards/v2/persons/{number}/orders'
60
61 # Qiwi P2P
62 CREATE_P2P_BILL: str = '/{bill_id}'
63 CHECK_P2P_BILL_STATUS: str = '/{bill_id}'
64 REJECT_P2P_BILL: str = '/{bill_id}/reject'
65 REFUND_BILL: str = '/{bill_id}/refunds/{refund_id}'
66
67 # Webhooks
68 REG_WEBHOOK: str = '/payment-notifier/v1/hooks'
69
70 GET_CURRENT_WEBHOOK: str = '/payment-notifier/v1/hooks/active'
71
72 SEND_TEST_NOTIFICATION: str = '/payment-notifier/v1/hooks/test'
73
74 GET_WEBHOOK_SECRET: str = '/payment-notifier/v1/hooks/{hook_id}/key'
75
76 DELETE_CURRENT_WEBHOOK: str = '/payment-notifier/v1/hooks/{hook_id}'
77
78 CHANGE_WEBHOOK_SECRET: str = '/payment-notifier/v1/hooks/{hook_id}/newkey'
79
80 # Payload data
81 DEFAULT_QIWI_HEADERS: Optional[Dict[str, Union[str, int]]] = None
82
83 ERROR_CODE_NUMBERS: Optional[Dict[str, Union[str, int]]] = None
84
85 P2P_QIWI_HEADERS: Optional[Dict[str, Union[str, int]]] = None
86
87 def __init__(self, *args, **kwargs):
88 self.DEFAULT_QIWI_HEADERS = {
89 'Content-Type': 'application/json',
90 'Accept': 'application/json',
91 'Authorization': 'Bearer {token}',
92 'Host': 'edge.qiwi.com',
93 }
94 self.P2P_QIWI_HEADERS = {
95 'Authorization': 'Bearer {token}',
96 'Accept': 'application/json',
97 'Content-Type': 'application/json',
98 }
99 self.ERROR_CODE_NUMBERS = {
100 "400": "Недостаточно средств для проведения операции",
101 "401": "Неверный токен или истек срок действия токена API",
102 "403": "Нет прав на данный запрос"
103 "(недостаточно разрешений у токена API)",
104 "404": "Не найдена транзакция или "
105 "отсутствуют платежи с указанными признаками",
106 "423": "Слишком много запросов, сервис временно недоступен",
107 "422": "Неправильно указаны домен/подсеть/хост"
108 " веб-хука(в параметре new_url для URL веб-хука), "
109 "неправильно указаны тип хука или тип транзакции, "
110 "попытка создать хук при наличии уже созданного",
111 "405": "Ошибка, связанная с типом запроса к апи,"
112 "обратитесь к разработчику или откройте issue",
113 "500": "Внутренняя ошибка сервиса",
114 "400_special_bad_proxy": "Ошибка, связанная с использованием прокси"
115 }
116 self.QIWI_MASTER = {
117 "id": str(int(time.time() * 1000)),
118 "sum": {
119 "amount": 2999,
120 "currency": "643"
121 },
122 "paymentMethod": {
123 "type": "Account",
124 "accountId": "643"
125 },
126 "comment": "test",
127 "fields": {
128 "account": "",
129 "vas_alias": "qvc-master"
130 }
131 }
132
133 for key, value in kwargs.items():
134 setattr(self, key, value)
135 for arg in args:
136 setattr(self, arg, arg)
137
138 self.LIMIT_TYPES = [
139 'TURNOVER',
140 'REFILL',
141 'PAYMENTS_P2P',
142 'PAYMENTS_PROVIDER_INTERNATIONALS',
143 'PAYMENTS_PROVIDER_PAYOUT',
144 'WITHDRAW_CASH'
145 ]
146 self.QIWI_TO_CARD.headers = self.DEFAULT_QIWI_HEADERS
147 self.P2P_DATA.headers = self.DEFAULT_QIWI_HEADERS
148 self.QIWI_TO_WALLET.headers = self.DEFAULT_QIWI_HEADERS
149 self.COMMISSION_DATA.headers = self.DEFAULT_QIWI_HEADERS
150
151 QIWI_TO_CARD: WrapperData = WrapperData(
152 json={
153 "id": str(int(time.time() * 1000)),
154 "sum": {
155 "amount": "", "currency": "643"
156 },
157 "paymentMethod": {
158 "type": "Account", "accountId": "643"
159 },
160 "fields": {
161 "account": ""
162 }
163 },
164 headers=DEFAULT_QIWI_HEADERS
165 )
166
167 P2P_DATA: WrapperData = WrapperData(
168 json={
169 "amount": {
170 "currency": "RUB",
171 "value": "{amount}"
172 },
173 "expirationDateTime": "",
174 "comment": "{comment}",
175 "customFields": {
176 "paySourcesFilter": "qw",
177 "themeCode": "Yvan-YKaSh",
178 }
179 },
180
181 headers=P2P_QIWI_HEADERS
182 )
183
184 QIWI_TO_WALLET: WrapperData = WrapperData(
185 json={
186 "id": str(int(time.time() * 1000)),
187 "sum": {
188 "amount": "",
189 "currency": ""
190 },
191 "paymentMethod": {
192 "type": "Account",
193 "accountId": "643"
194 },
195 "comment": "",
196 "fields": {
197 "account": ""
198 }
199 },
200 headers=DEFAULT_QIWI_HEADERS
201 )
202
203 LIMIT_TYPES: Optional[List[str]] = None
204
205 COMMISSION_DATA: WrapperData = WrapperData(
206 json={
207 "account": "",
208 "paymentMethod": {
209 "type": "Account",
210 "accountId": "643"
211 },
212 "purchaseTotals":
213 {
214 "total":
215 {"amount": "",
216 "currency": "643"
217 }
218 }},
219 headers=DEFAULT_QIWI_HEADERS
220 )
221
222 QIWI_MASTER: Dict[str, Union[int, float, str]] = None
223
224
225@lru_cache()
226def get_settings() -> QiwiSettings:
227 settings = QiwiSettings()
228 return settings
229
230
231class QiwiRouter(AbstractRouter):
232 """Class, which deals with all methods, except p2p"""
233 __head__ = "https://edge.qiwi.com"
234
235 @functools.lru_cache()
236 def build_url(self, api_method: str, **kwargs: Any) -> str:
237 check_api_method(api_method)
238 tail_path: Optional[str] = getattr(self.config, api_method, None)
239 pre_build_url = self.__head__ + tail_path
240 return super()._format_url_kwargs(pre_build_url, **kwargs)
241
242 def setup_config(self) -> Any:
243 return get_settings()
244
245
246class QiwiKassaRouter(QiwiRouter):
247 """ QIWI P2P router"""
248 __head__ = "https://api.qiwi.com/partner/bill/v1/bills"
249
250
251__all__ = ('get_settings', "QiwiRouter", "QiwiKassaRouter")
252