payme-pkg 3.0.25b0__tar.gz → 3.0.26b0__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.
Potentially problematic release.
This version of payme-pkg might be problematic. Click here for more details.
- {payme_pkg-3.0.25b0 → payme_pkg-3.0.26b0}/PKG-INFO +11 -2
- {payme_pkg-3.0.25b0 → payme_pkg-3.0.26b0}/payme/classes/cards.py +1 -1
- {payme_pkg-3.0.25b0 → payme_pkg-3.0.26b0}/payme/classes/client.py +9 -11
- {payme_pkg-3.0.25b0 → payme_pkg-3.0.26b0}/payme/classes/initializer.py +10 -5
- {payme_pkg-3.0.25b0 → payme_pkg-3.0.26b0}/payme/classes/receipts.py +101 -40
- {payme_pkg-3.0.25b0 → payme_pkg-3.0.26b0}/payme/exceptions/webhook.py +25 -36
- payme_pkg-3.0.26b0/payme/migrations/0004_alter_paymetransactions_account_id.py +18 -0
- {payme_pkg-3.0.25b0 → payme_pkg-3.0.26b0}/payme/models.py +1 -1
- {payme_pkg-3.0.25b0 → payme_pkg-3.0.26b0}/payme/types/response/cards.py +3 -13
- {payme_pkg-3.0.25b0 → payme_pkg-3.0.26b0}/payme/types/response/receipts.py +38 -47
- {payme_pkg-3.0.25b0 → payme_pkg-3.0.26b0}/payme/types/response/webhook.py +14 -24
- {payme_pkg-3.0.25b0 → payme_pkg-3.0.26b0}/payme/views.py +12 -10
- {payme_pkg-3.0.25b0 → payme_pkg-3.0.26b0}/payme_pkg.egg-info/PKG-INFO +11 -2
- {payme_pkg-3.0.25b0 → payme_pkg-3.0.26b0}/payme_pkg.egg-info/SOURCES.txt +1 -0
- {payme_pkg-3.0.25b0 → payme_pkg-3.0.26b0}/setup.py +1 -1
- {payme_pkg-3.0.25b0 → payme_pkg-3.0.26b0}/LICENSE.txt +0 -0
- {payme_pkg-3.0.25b0 → payme_pkg-3.0.26b0}/README.md +0 -0
- {payme_pkg-3.0.25b0 → payme_pkg-3.0.26b0}/payme/__init__.py +0 -0
- {payme_pkg-3.0.25b0 → payme_pkg-3.0.26b0}/payme/admin.py +0 -0
- {payme_pkg-3.0.25b0 → payme_pkg-3.0.26b0}/payme/apps.py +0 -0
- {payme_pkg-3.0.25b0 → payme_pkg-3.0.26b0}/payme/classes/__init__.py +0 -0
- {payme_pkg-3.0.25b0 → payme_pkg-3.0.26b0}/payme/classes/http.py +0 -0
- {payme_pkg-3.0.25b0 → payme_pkg-3.0.26b0}/payme/const.py +0 -0
- {payme_pkg-3.0.25b0 → payme_pkg-3.0.26b0}/payme/exceptions/__init__.py +0 -0
- {payme_pkg-3.0.25b0 → payme_pkg-3.0.26b0}/payme/exceptions/general.py +0 -0
- {payme_pkg-3.0.25b0 → payme_pkg-3.0.26b0}/payme/migrations/0001_initial.py +0 -0
- {payme_pkg-3.0.25b0 → payme_pkg-3.0.26b0}/payme/migrations/0002_paymetransactions_fiscal_data.py +0 -0
- {payme_pkg-3.0.25b0 → payme_pkg-3.0.26b0}/payme/migrations/0003_alter_paymetransactions_fiscal_data.py +0 -0
- {payme_pkg-3.0.25b0 → payme_pkg-3.0.26b0}/payme/migrations/__init__.py +0 -0
- {payme_pkg-3.0.25b0 → payme_pkg-3.0.26b0}/payme/types/__init__.py +0 -0
- {payme_pkg-3.0.25b0 → payme_pkg-3.0.26b0}/payme/types/request/__init__.py +0 -0
- {payme_pkg-3.0.25b0 → payme_pkg-3.0.26b0}/payme/types/response/__init__.py +0 -0
- {payme_pkg-3.0.25b0 → payme_pkg-3.0.26b0}/payme/urls.py +0 -0
- {payme_pkg-3.0.25b0 → payme_pkg-3.0.26b0}/payme/util.py +0 -0
- {payme_pkg-3.0.25b0 → payme_pkg-3.0.26b0}/payme_pkg.egg-info/dependency_links.txt +0 -0
- {payme_pkg-3.0.25b0 → payme_pkg-3.0.26b0}/payme_pkg.egg-info/requires.txt +0 -0
- {payme_pkg-3.0.25b0 → payme_pkg-3.0.26b0}/payme_pkg.egg-info/top_level.txt +0 -0
- {payme_pkg-3.0.25b0 → payme_pkg-3.0.26b0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: payme-pkg
|
|
3
|
-
Version: 3.0.
|
|
3
|
+
Version: 3.0.26b0
|
|
4
4
|
Home-page: https://github.com/Muhammadali-Akbarov/payme-pkg
|
|
5
5
|
Author: Muhammadali Akbarov
|
|
6
6
|
Author-email: muhammadali17abc@gmail.com
|
|
@@ -11,6 +11,15 @@ License-File: LICENSE.txt
|
|
|
11
11
|
Requires-Dist: requests==2.*
|
|
12
12
|
Requires-Dist: dataclasses==0.*; python_version < "3.7"
|
|
13
13
|
Requires-Dist: djangorestframework==3.*
|
|
14
|
+
Dynamic: author
|
|
15
|
+
Dynamic: author-email
|
|
16
|
+
Dynamic: description
|
|
17
|
+
Dynamic: description-content-type
|
|
18
|
+
Dynamic: home-page
|
|
19
|
+
Dynamic: keywords
|
|
20
|
+
Dynamic: license
|
|
21
|
+
Dynamic: license-file
|
|
22
|
+
Dynamic: requires-dist
|
|
14
23
|
|
|
15
24
|
<h1 align="center">Payme Software Development Kit</h1>
|
|
16
25
|
|
|
@@ -19,7 +19,7 @@ class Cards:
|
|
|
19
19
|
services. It allows you to create new cards and retrieve verification
|
|
20
20
|
codes for existing cards.
|
|
21
21
|
"""
|
|
22
|
-
def __init__(self, url: str, payme_id: str) ->
|
|
22
|
+
def __init__(self, url: str, payme_id: str) -> "Cards":
|
|
23
23
|
"""
|
|
24
24
|
Initialize the Cards client.
|
|
25
25
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
|
|
2
|
+
from typing import Union
|
|
2
3
|
|
|
3
4
|
from payme.const import Networks
|
|
4
5
|
from payme.classes.cards import Cards
|
|
@@ -10,14 +11,14 @@ class Payme:
|
|
|
10
11
|
"""
|
|
11
12
|
The payme class provides a simple interface
|
|
12
13
|
"""
|
|
13
|
-
|
|
14
14
|
def __init__(
|
|
15
15
|
self,
|
|
16
16
|
payme_id: str,
|
|
17
|
-
fallback_id:
|
|
18
|
-
payme_key:
|
|
19
|
-
is_test_mode: bool = False
|
|
20
|
-
)
|
|
17
|
+
fallback_id: Union[str, None] = None,
|
|
18
|
+
payme_key: Union[str, None] = None,
|
|
19
|
+
is_test_mode: bool = False
|
|
20
|
+
):
|
|
21
|
+
|
|
21
22
|
# initialize payme network
|
|
22
23
|
url = Networks.PROD_NET.value
|
|
23
24
|
|
|
@@ -25,8 +26,5 @@ class Payme:
|
|
|
25
26
|
url = Networks.TEST_NET.value
|
|
26
27
|
|
|
27
28
|
self.cards = Cards(url=url, payme_id=payme_id)
|
|
28
|
-
self.initializer = Initializer(
|
|
29
|
-
|
|
30
|
-
)
|
|
31
|
-
if payme_key:
|
|
32
|
-
self.receipts = Receipts(url=url, payme_id=payme_id, payme_key=payme_key)
|
|
29
|
+
self.initializer = Initializer(payme_id=payme_id, fallback_id=fallback_id, is_test_mode=is_test_mode)
|
|
30
|
+
self.receipts = Receipts(url=url, payme_id=payme_id, payme_key=payme_key) # noqa
|
|
@@ -13,14 +13,17 @@ class Initializer:
|
|
|
13
13
|
The Payme ID associated with your account
|
|
14
14
|
"""
|
|
15
15
|
|
|
16
|
-
def __init__(
|
|
17
|
-
self, payme_id: str = None, fallback_id: str = None, is_test_mode: bool = False
|
|
18
|
-
) -> None:
|
|
16
|
+
def __init__(self, payme_id: str = None, fallback_id: str = None, is_test_mode: bool = False):
|
|
19
17
|
self.payme_id = payme_id
|
|
20
18
|
self.fallback_id = fallback_id
|
|
21
19
|
self.is_test_mode = is_test_mode
|
|
22
20
|
|
|
23
|
-
def generate_pay_link(
|
|
21
|
+
def generate_pay_link(
|
|
22
|
+
self,
|
|
23
|
+
id: int,
|
|
24
|
+
amount: int,
|
|
25
|
+
return_url: str
|
|
26
|
+
) -> str:
|
|
24
27
|
"""
|
|
25
28
|
Generate a payment link for a specific order.
|
|
26
29
|
|
|
@@ -49,7 +52,9 @@ class Initializer:
|
|
|
49
52
|
https://developer.help.paycom.uz/initsializatsiya-platezhey/
|
|
50
53
|
"""
|
|
51
54
|
amount = amount * 100 # Convert amount to the smallest currency unit
|
|
52
|
-
params =
|
|
55
|
+
params = (
|
|
56
|
+
f'm={self.payme_id};ac.{settings.PAYME_ACCOUNT_FIELD}={id};a={amount};c={return_url}'
|
|
57
|
+
)
|
|
53
58
|
params = base64.b64encode(params.encode("utf-8")).decode("utf-8")
|
|
54
59
|
|
|
55
60
|
if self.is_test_mode is True:
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
from typing import Union, Optional
|
|
2
|
+
from urllib.parse import parse_qs
|
|
2
3
|
|
|
3
4
|
from payme.classes.cards import Cards
|
|
4
5
|
from payme.classes.http import HttpClient
|
|
@@ -13,6 +14,7 @@ ALLOWED_METHODS = {
|
|
|
13
14
|
"receipts.check": response.CheckResponse,
|
|
14
15
|
"receipts.get": response.GetResponse,
|
|
15
16
|
"receipts.get_all": response.GetAllResponse,
|
|
17
|
+
"receipts.set_fiscal_data": response.SetFiscalDataResponse,
|
|
16
18
|
}
|
|
17
19
|
|
|
18
20
|
|
|
@@ -20,8 +22,7 @@ class Receipts:
|
|
|
20
22
|
"""
|
|
21
23
|
The Receipts class provides methods to interact with the Payme Receipts.
|
|
22
24
|
"""
|
|
23
|
-
|
|
24
|
-
def __init__(self, payme_id: str, payme_key: str, url: str) -> None:
|
|
25
|
+
def __init__(self, payme_id: str, payme_key: str, url: str) -> "Receipts":
|
|
25
26
|
"""
|
|
26
27
|
Initialize the Receipts client.
|
|
27
28
|
|
|
@@ -33,25 +34,25 @@ class Receipts:
|
|
|
33
34
|
|
|
34
35
|
headers = {
|
|
35
36
|
"X-Auth": f"{payme_id}:{payme_key}",
|
|
36
|
-
"Content-Type": "application/json"
|
|
37
|
+
"Content-Type": "application/json"
|
|
37
38
|
}
|
|
38
39
|
self.http = HttpClient(url, headers)
|
|
39
40
|
|
|
40
41
|
def create(
|
|
41
42
|
self,
|
|
42
43
|
account: dict,
|
|
43
|
-
amount:
|
|
44
|
-
description:
|
|
45
|
-
detail:
|
|
46
|
-
timeout: int = 10
|
|
44
|
+
amount: Union[float, int],
|
|
45
|
+
description: Optional[str] = None,
|
|
46
|
+
detail: Optional[dict] = None,
|
|
47
|
+
timeout: int = 10
|
|
47
48
|
) -> response.CreateResponse:
|
|
48
49
|
"""
|
|
49
50
|
Create a new receipt.
|
|
50
51
|
|
|
51
52
|
:param account: The account details for the receipt.
|
|
52
53
|
:param amount: The amount of the receipt.
|
|
53
|
-
:param description:
|
|
54
|
-
:param detail:
|
|
54
|
+
:param description: Optional description for the receipt.
|
|
55
|
+
:param detail: Optional additional details for the receipt.
|
|
55
56
|
:param timeout: The request timeout duration in seconds (default 10).
|
|
56
57
|
"""
|
|
57
58
|
method = "receipts.create"
|
|
@@ -59,7 +60,7 @@ class Receipts:
|
|
|
59
60
|
"amount": amount,
|
|
60
61
|
"account": account,
|
|
61
62
|
"description": description,
|
|
62
|
-
"detail": detail
|
|
63
|
+
"detail": detail
|
|
63
64
|
}
|
|
64
65
|
return self._post_request(method, params, timeout)
|
|
65
66
|
|
|
@@ -75,7 +76,10 @@ class Receipts:
|
|
|
75
76
|
The request timeout duration in seconds (default is 10).
|
|
76
77
|
"""
|
|
77
78
|
method = "receipts.pay"
|
|
78
|
-
params = {
|
|
79
|
+
params = {
|
|
80
|
+
"id": receipts_id,
|
|
81
|
+
"token": token
|
|
82
|
+
}
|
|
79
83
|
return self._post_request(method, params, timeout)
|
|
80
84
|
|
|
81
85
|
def send(
|
|
@@ -89,10 +93,15 @@ class Receipts:
|
|
|
89
93
|
:param timeout: The request timeout duration in seconds (default 10).
|
|
90
94
|
"""
|
|
91
95
|
method = "receipts.send"
|
|
92
|
-
params = {
|
|
96
|
+
params = {
|
|
97
|
+
"id": receipts_id,
|
|
98
|
+
"phone": phone
|
|
99
|
+
}
|
|
93
100
|
return self._post_request(method, params, timeout)
|
|
94
101
|
|
|
95
|
-
def cancel(
|
|
102
|
+
def cancel(
|
|
103
|
+
self, receipts_id: str, timeout: int = 10
|
|
104
|
+
) -> response.CancelResponse:
|
|
96
105
|
"""
|
|
97
106
|
Cancel the receipt.
|
|
98
107
|
|
|
@@ -100,10 +109,14 @@ class Receipts:
|
|
|
100
109
|
:param timeout: The request timeout duration in seconds (default 10).
|
|
101
110
|
"""
|
|
102
111
|
method = "receipts.cancel"
|
|
103
|
-
params = {
|
|
112
|
+
params = {
|
|
113
|
+
"id": receipts_id
|
|
114
|
+
}
|
|
104
115
|
return self._post_request(method, params, timeout)
|
|
105
116
|
|
|
106
|
-
def check(
|
|
117
|
+
def check(
|
|
118
|
+
self, receipts_id: str, timeout: int = 10
|
|
119
|
+
) -> response.CheckResponse:
|
|
107
120
|
"""
|
|
108
121
|
Check the status of a cheque.
|
|
109
122
|
|
|
@@ -111,10 +124,14 @@ class Receipts:
|
|
|
111
124
|
:param timeout: The request timeout duration in seconds (default 10).
|
|
112
125
|
"""
|
|
113
126
|
method = "receipts.check"
|
|
114
|
-
params = {
|
|
127
|
+
params = {
|
|
128
|
+
"id": receipts_id
|
|
129
|
+
}
|
|
115
130
|
return self._post_request(method, params, timeout)
|
|
116
131
|
|
|
117
|
-
def get(
|
|
132
|
+
def get(
|
|
133
|
+
self, receipts_id: str, timeout: int = 10
|
|
134
|
+
) -> response.GetResponse:
|
|
118
135
|
"""
|
|
119
136
|
Get the details of a specific cheque.
|
|
120
137
|
|
|
@@ -122,23 +139,60 @@ class Receipts:
|
|
|
122
139
|
:param timeout: The request timeout duration in seconds (default 10).
|
|
123
140
|
"""
|
|
124
141
|
method = "receipts.get"
|
|
125
|
-
params = {
|
|
142
|
+
params = {
|
|
143
|
+
"id": receipts_id
|
|
144
|
+
}
|
|
126
145
|
return self._post_request(method, params, timeout)
|
|
127
146
|
|
|
128
147
|
def get_all(
|
|
129
148
|
self, count: int, from_: int, to: int, offset: int, timeout: int = 10
|
|
130
149
|
) -> response.GetAllResponse:
|
|
131
150
|
"""
|
|
132
|
-
|
|
151
|
+
Get all cheques for a specific account.
|
|
133
152
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
153
|
+
:param count: The number of cheques to retrieve.
|
|
154
|
+
:param from_: The start index of the cheques to retrieve.
|
|
155
|
+
:param to: The end index of the cheques to retrieve.
|
|
156
|
+
:param offset: The offset for pagination.
|
|
157
|
+
:param timeout: The request timeout duration in seconds (default 10).
|
|
139
158
|
"""
|
|
140
159
|
method = "receipts.get_all"
|
|
141
|
-
params = {
|
|
160
|
+
params = {
|
|
161
|
+
"count": count,
|
|
162
|
+
"from": from_,
|
|
163
|
+
"to": to,
|
|
164
|
+
"offset": offset
|
|
165
|
+
}
|
|
166
|
+
return self._post_request(method, params, timeout)
|
|
167
|
+
|
|
168
|
+
def set_fiscal_data(
|
|
169
|
+
self, receipt_id: str, qr_code_url: str, timeout: int = 10
|
|
170
|
+
) -> response.SetFiscalDataResponse:
|
|
171
|
+
"""
|
|
172
|
+
Get all cheques for a specific account.
|
|
173
|
+
|
|
174
|
+
:param receipt_id: The ID of the check used for payment.
|
|
175
|
+
:param qr_code_url: URL of the fiscal check from the ofd.uz.
|
|
176
|
+
:param timeout: The request timeout duration in seconds (default 10).
|
|
177
|
+
"""
|
|
178
|
+
method = "receipts.set_fiscal_data"
|
|
179
|
+
|
|
180
|
+
check_params = parse_qs(qr_code_url.split("?")[1])
|
|
181
|
+
terminal_id = check_params["t"][0]
|
|
182
|
+
fiscal_sign = check_params["s"][0]
|
|
183
|
+
fiscal_receipt_id = check_params["r"][0]
|
|
184
|
+
fiscal_date = check_params["c"][0]
|
|
185
|
+
|
|
186
|
+
params = {
|
|
187
|
+
"id": receipt_id, # required
|
|
188
|
+
"fiscal_data": {
|
|
189
|
+
"terminal_id": terminal_id,
|
|
190
|
+
"receipt_id": int(fiscal_receipt_id), # required
|
|
191
|
+
"date": fiscal_date,
|
|
192
|
+
"fiscal_sign": fiscal_sign,
|
|
193
|
+
"qr_code_url": qr_code_url, # required
|
|
194
|
+
}
|
|
195
|
+
}
|
|
142
196
|
return self._post_request(method, params, timeout)
|
|
143
197
|
|
|
144
198
|
def _post_request(
|
|
@@ -163,7 +217,6 @@ class Receipts:
|
|
|
163
217
|
covering creation, payment, sending, cancellation, status checks,
|
|
164
218
|
retrieval of a single receipt, and retrieval of multiple receipts.
|
|
165
219
|
"""
|
|
166
|
-
|
|
167
220
|
# Helper to assert conditions with messaging
|
|
168
221
|
def assert_condition(condition, message, test_case):
|
|
169
222
|
self._assert_and_print(condition, message, test_case=test_case)
|
|
@@ -174,14 +227,14 @@ class Receipts:
|
|
|
174
227
|
account={"id": 12345},
|
|
175
228
|
amount=1000,
|
|
176
229
|
description="Test receipt",
|
|
177
|
-
detail={"key": "value"}
|
|
230
|
+
detail={"key": "value"}
|
|
178
231
|
)
|
|
179
232
|
|
|
180
233
|
# Test 1: Initialization check
|
|
181
234
|
assert_condition(
|
|
182
235
|
isinstance(self, Receipts),
|
|
183
236
|
"Initialized Receipts class successfully.",
|
|
184
|
-
test_case="Initialization Test"
|
|
237
|
+
test_case="Initialization Test"
|
|
185
238
|
)
|
|
186
239
|
|
|
187
240
|
# Test 2: Create and Pay Receipt
|
|
@@ -189,19 +242,21 @@ class Receipts:
|
|
|
189
242
|
assert_condition(
|
|
190
243
|
isinstance(create_response, response.CreateResponse),
|
|
191
244
|
"Created a new receipt successfully.",
|
|
192
|
-
test_case="Receipt Creation Test"
|
|
245
|
+
test_case="Receipt Creation Test"
|
|
193
246
|
)
|
|
194
247
|
|
|
195
248
|
# pylint: disable=W0212
|
|
196
249
|
assert_condition(
|
|
197
250
|
isinstance(create_response.result.receipt._id, str),
|
|
198
251
|
"Created a valid receipt ID.",
|
|
199
|
-
test_case="Receipt ID Test"
|
|
252
|
+
test_case="Receipt ID Test"
|
|
200
253
|
)
|
|
201
254
|
|
|
202
255
|
# Prepare card and verification
|
|
203
256
|
cards_create_response = self.__cards.create(
|
|
204
|
-
number="8600495473316478",
|
|
257
|
+
number="8600495473316478",
|
|
258
|
+
expire="0399",
|
|
259
|
+
save=True
|
|
205
260
|
)
|
|
206
261
|
token = cards_create_response.result.card.token
|
|
207
262
|
self.__cards.get_verify_code(token=token)
|
|
@@ -213,7 +268,7 @@ class Receipts:
|
|
|
213
268
|
assert_condition(
|
|
214
269
|
pay_response.result.receipt.state == 4,
|
|
215
270
|
"Paid the receipt successfully.",
|
|
216
|
-
test_case="Payment Test"
|
|
271
|
+
test_case="Payment Test"
|
|
217
272
|
)
|
|
218
273
|
|
|
219
274
|
# Test 3: Create and Send Receipt
|
|
@@ -223,7 +278,7 @@ class Receipts:
|
|
|
223
278
|
assert_condition(
|
|
224
279
|
send_response.result.success is True,
|
|
225
280
|
"Sent the receipt successfully.",
|
|
226
|
-
test_case="Send Test"
|
|
281
|
+
test_case="Send Test"
|
|
227
282
|
)
|
|
228
283
|
|
|
229
284
|
# Test 4: Create and Cancel Receipt
|
|
@@ -233,7 +288,7 @@ class Receipts:
|
|
|
233
288
|
assert_condition(
|
|
234
289
|
cancel_response.result.receipt.state == 50,
|
|
235
290
|
"Cancelled the receipt successfully.",
|
|
236
|
-
test_case="Cancel Test"
|
|
291
|
+
test_case="Cancel Test"
|
|
237
292
|
)
|
|
238
293
|
|
|
239
294
|
# Test 5: Check Receipt Status
|
|
@@ -241,7 +296,7 @@ class Receipts:
|
|
|
241
296
|
assert_condition(
|
|
242
297
|
check_response.result.state == 50,
|
|
243
298
|
"Checked the receipt status successfully.",
|
|
244
|
-
test_case="Check Test"
|
|
299
|
+
test_case="Check Test"
|
|
245
300
|
)
|
|
246
301
|
|
|
247
302
|
# Test 6: Get Receipt Details
|
|
@@ -249,21 +304,27 @@ class Receipts:
|
|
|
249
304
|
assert_condition(
|
|
250
305
|
get_response.result.receipt._id == receipt_id,
|
|
251
306
|
"Retrieved the receipt details successfully.",
|
|
252
|
-
test_case="Get Test"
|
|
307
|
+
test_case="Get Test"
|
|
253
308
|
)
|
|
254
309
|
|
|
255
310
|
# Test 7: Retrieve All Receipts
|
|
256
311
|
get_all_response = self.get_all(
|
|
257
|
-
count=1,
|
|
312
|
+
count=1,
|
|
313
|
+
from_=1730322122000,
|
|
314
|
+
to=1730398982000,
|
|
315
|
+
offset=0
|
|
258
316
|
)
|
|
259
317
|
assert_condition(
|
|
260
318
|
isinstance(get_all_response.result, list),
|
|
261
319
|
"Retrieved all receipts successfully.",
|
|
262
|
-
test_case="Get All Test"
|
|
320
|
+
test_case="Get All Test"
|
|
263
321
|
)
|
|
264
322
|
|
|
265
323
|
# pylint: disable=W0212
|
|
266
324
|
def _assert_and_print(
|
|
267
|
-
self,
|
|
325
|
+
self,
|
|
326
|
+
condition: bool,
|
|
327
|
+
success_message: str,
|
|
328
|
+
test_case: Optional[str] = None
|
|
268
329
|
):
|
|
269
330
|
self.__cards._assert_and_print(condition, success_message, test_case)
|
|
@@ -1,31 +1,28 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Init Payme base exception.
|
|
3
3
|
"""
|
|
4
|
-
|
|
5
4
|
import logging
|
|
6
|
-
import typing as t
|
|
7
|
-
|
|
8
|
-
from rest_framework import status
|
|
9
5
|
from rest_framework.exceptions import APIException
|
|
10
6
|
|
|
11
7
|
logger = logging.getLogger(__name__)
|
|
12
8
|
|
|
13
|
-
MessageT = t.Optional[t.Union[str, t.Dict[str, str]]]
|
|
14
|
-
|
|
15
9
|
|
|
16
10
|
class BasePaymeException(APIException):
|
|
17
11
|
"""
|
|
18
12
|
BasePaymeException inherits from APIException.
|
|
19
13
|
"""
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
message: MessageT = None
|
|
14
|
+
status_code = 200
|
|
15
|
+
error_code = None
|
|
16
|
+
message = None
|
|
24
17
|
|
|
25
18
|
# pylint: disable=super-init-not-called
|
|
26
19
|
def __init__(self, message: str = None):
|
|
27
20
|
detail: dict = {
|
|
28
|
-
"error": {
|
|
21
|
+
"error": {
|
|
22
|
+
"code": self.error_code,
|
|
23
|
+
"message": self.message,
|
|
24
|
+
"data": message
|
|
25
|
+
}
|
|
29
26
|
}
|
|
30
27
|
logger.error(f"Payme error detail: {detail}")
|
|
31
28
|
self.detail = detail
|
|
@@ -37,8 +34,7 @@ class PermissionDenied(BasePaymeException):
|
|
|
37
34
|
|
|
38
35
|
Raised when the client is not allowed to access the server.
|
|
39
36
|
"""
|
|
40
|
-
|
|
41
|
-
status_code = status.HTTP_200_OK
|
|
37
|
+
status_code = 200
|
|
42
38
|
error_code = -32504
|
|
43
39
|
message = "Permission denied."
|
|
44
40
|
|
|
@@ -49,13 +45,12 @@ class InternalServiceError(BasePaymeException):
|
|
|
49
45
|
|
|
50
46
|
Raised when a transaction fails to perform.
|
|
51
47
|
"""
|
|
52
|
-
|
|
53
|
-
status_code = status.HTTP_200_OK
|
|
48
|
+
status_code = 200
|
|
54
49
|
error_code = -32400
|
|
55
50
|
message = {
|
|
56
51
|
"uz": "Tizimda xatolik yuzaga keldi.",
|
|
57
52
|
"ru": "Внутренняя ошибка сервиса.",
|
|
58
|
-
"en": "Internal service error."
|
|
53
|
+
"en": "Internal service error."
|
|
59
54
|
}
|
|
60
55
|
|
|
61
56
|
|
|
@@ -65,8 +60,7 @@ class MethodNotFound(BasePaymeException):
|
|
|
65
60
|
|
|
66
61
|
Raised when the requested method does not exist.
|
|
67
62
|
"""
|
|
68
|
-
|
|
69
|
-
status_code = status.HTTP_405_METHOD_NOT_ALLOWED
|
|
63
|
+
status_code = 405
|
|
70
64
|
error_code = -32601
|
|
71
65
|
message = "Method not found."
|
|
72
66
|
|
|
@@ -77,13 +71,12 @@ class AccountDoesNotExist(BasePaymeException):
|
|
|
77
71
|
|
|
78
72
|
Raised when an account does not exist or has been deleted.
|
|
79
73
|
"""
|
|
80
|
-
|
|
81
|
-
status_code = status.HTTP_200_OK
|
|
74
|
+
status_code = 200
|
|
82
75
|
error_code = -31050
|
|
83
76
|
message = {
|
|
84
77
|
"uz": "Hisob topilmadi.",
|
|
85
78
|
"ru": "Счет не найден.",
|
|
86
|
-
"en": "Account does not exist."
|
|
79
|
+
"en": "Account does not exist."
|
|
87
80
|
}
|
|
88
81
|
|
|
89
82
|
|
|
@@ -93,13 +86,12 @@ class IncorrectAmount(BasePaymeException):
|
|
|
93
86
|
|
|
94
87
|
Raised when the provided amount is incorrect.
|
|
95
88
|
"""
|
|
96
|
-
|
|
97
|
-
status_code = status.HTTP_200_OK
|
|
89
|
+
status_code = 200
|
|
98
90
|
error_code = -31001
|
|
99
91
|
message = {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
92
|
+
'ru': 'Неверная сумма.',
|
|
93
|
+
'uz': "Noto'g'ri summa.",
|
|
94
|
+
'en': 'Incorrect amount.'
|
|
103
95
|
}
|
|
104
96
|
|
|
105
97
|
|
|
@@ -115,13 +107,12 @@ class TransactionAlreadyExists(BasePaymeException):
|
|
|
115
107
|
error_code (int): The specific error code for this exception.
|
|
116
108
|
message (dict): A dictionary containing localized error messages.
|
|
117
109
|
"""
|
|
118
|
-
|
|
119
|
-
status_code = status.HTTP_200_OK
|
|
110
|
+
status_code = 200
|
|
120
111
|
error_code = -31099
|
|
121
112
|
message = {
|
|
122
113
|
"uz": "Tranzaksiya allaqachon mavjud.",
|
|
123
114
|
"ru": "Транзакция уже существует.",
|
|
124
|
-
"en": "Transaction already exists."
|
|
115
|
+
"en": "Transaction already exists."
|
|
125
116
|
}
|
|
126
117
|
|
|
127
118
|
|
|
@@ -131,13 +122,12 @@ class InvalidFiscalParams(BasePaymeException):
|
|
|
131
122
|
|
|
132
123
|
Raised when the provided fiscal parameters are invalid.
|
|
133
124
|
"""
|
|
134
|
-
|
|
135
|
-
status_code = status.HTTP_200_OK
|
|
125
|
+
status_code = 200
|
|
136
126
|
error_code = -32602
|
|
137
127
|
message = {
|
|
138
128
|
"uz": "Fiskal parameterlarida kamchiliklar bor",
|
|
139
129
|
"ru": "Неверные фискальные параметры.",
|
|
140
|
-
"en": "Invalid fiscal parameters."
|
|
130
|
+
"en": "Invalid fiscal parameters."
|
|
141
131
|
}
|
|
142
132
|
|
|
143
133
|
|
|
@@ -147,13 +137,12 @@ class InvalidAccount(BasePaymeException):
|
|
|
147
137
|
|
|
148
138
|
Raised when the provided account is invalid.
|
|
149
139
|
"""
|
|
150
|
-
|
|
151
|
-
status_code = status.HTTP_200_OK
|
|
140
|
+
status_code = 200
|
|
152
141
|
error_code = -32400
|
|
153
142
|
message = {
|
|
154
143
|
"uz": "Hisob nomida kamchilik bor",
|
|
155
144
|
"ru": "Неверный номер счета.",
|
|
156
|
-
"en": "Invalid account."
|
|
145
|
+
"en": "Invalid account."
|
|
157
146
|
}
|
|
158
147
|
|
|
159
148
|
|
|
@@ -164,5 +153,5 @@ exception_whitelist = (
|
|
|
164
153
|
AccountDoesNotExist,
|
|
165
154
|
TransactionAlreadyExists,
|
|
166
155
|
InvalidFiscalParams,
|
|
167
|
-
InvalidAccount
|
|
156
|
+
InvalidAccount
|
|
168
157
|
)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Generated by Django 5.2.5 on 2025-08-25 19:12
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Migration(migrations.Migration):
|
|
7
|
+
|
|
8
|
+
dependencies = [
|
|
9
|
+
("payme", "0003_alter_paymetransactions_fiscal_data"),
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
operations = [
|
|
13
|
+
migrations.AlterField(
|
|
14
|
+
model_name="paymetransactions",
|
|
15
|
+
name="account_id",
|
|
16
|
+
field=models.CharField(max_length=256),
|
|
17
|
+
),
|
|
18
|
+
]
|
|
@@ -26,7 +26,7 @@ class PaymeTransactions(models.Model):
|
|
|
26
26
|
]
|
|
27
27
|
|
|
28
28
|
transaction_id = models.CharField(max_length=50)
|
|
29
|
-
account_id = models.
|
|
29
|
+
account_id = models.CharField(max_length=256, null=False)
|
|
30
30
|
amount = models.DecimalField(max_digits=10, decimal_places=2)
|
|
31
31
|
state = models.IntegerField(choices=STATE, default=CREATED)
|
|
32
32
|
fiscal_data = models.JSONField(default=dict)
|
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
|
|
1
|
+
from typing import Dict, Optional
|
|
2
2
|
from dataclasses import dataclass
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
@dataclass
|
|
6
5
|
class Common:
|
|
7
6
|
"""
|
|
8
7
|
The common response structure.
|
|
9
8
|
"""
|
|
10
9
|
|
|
11
10
|
@classmethod
|
|
12
|
-
def from_dict(cls, data:
|
|
11
|
+
def from_dict(cls, data: Dict):
|
|
13
12
|
"""
|
|
14
13
|
Prepare fields for nested dataclasses
|
|
15
14
|
"""
|
|
@@ -31,14 +30,13 @@ class Card(Common):
|
|
|
31
30
|
"""
|
|
32
31
|
The card object represents a credit card.
|
|
33
32
|
"""
|
|
34
|
-
|
|
35
33
|
number: str
|
|
36
34
|
expire: str
|
|
37
35
|
token: str
|
|
38
36
|
recurrent: bool
|
|
39
37
|
verify: bool
|
|
40
38
|
type: str
|
|
41
|
-
number_hash:
|
|
39
|
+
number_hash: Optional[str] = None
|
|
42
40
|
|
|
43
41
|
|
|
44
42
|
@dataclass
|
|
@@ -46,7 +44,6 @@ class Result(Common):
|
|
|
46
44
|
"""
|
|
47
45
|
The result object contains the created card.
|
|
48
46
|
"""
|
|
49
|
-
|
|
50
47
|
card: Card
|
|
51
48
|
|
|
52
49
|
|
|
@@ -55,7 +52,6 @@ class CardsCreateResponse(Common):
|
|
|
55
52
|
"""
|
|
56
53
|
The cards.create response.
|
|
57
54
|
"""
|
|
58
|
-
|
|
59
55
|
jsonrpc: str
|
|
60
56
|
result: Result
|
|
61
57
|
|
|
@@ -65,7 +61,6 @@ class VerifyResult(Common):
|
|
|
65
61
|
"""
|
|
66
62
|
The result object for the verification response.
|
|
67
63
|
"""
|
|
68
|
-
|
|
69
64
|
sent: bool
|
|
70
65
|
phone: str
|
|
71
66
|
wait: int
|
|
@@ -76,7 +71,6 @@ class GetVerifyResponse(Common):
|
|
|
76
71
|
"""
|
|
77
72
|
The verification response structure.
|
|
78
73
|
"""
|
|
79
|
-
|
|
80
74
|
jsonrpc: str
|
|
81
75
|
result: VerifyResult
|
|
82
76
|
|
|
@@ -86,7 +80,6 @@ class VerifyResponse(Common):
|
|
|
86
80
|
"""
|
|
87
81
|
The verification response structure.
|
|
88
82
|
"""
|
|
89
|
-
|
|
90
83
|
jsonrpc: str
|
|
91
84
|
result: Result
|
|
92
85
|
|
|
@@ -96,7 +89,6 @@ class RemoveCardResult(Common):
|
|
|
96
89
|
"""
|
|
97
90
|
The result object for the removal response.
|
|
98
91
|
"""
|
|
99
|
-
|
|
100
92
|
success: bool
|
|
101
93
|
|
|
102
94
|
|
|
@@ -105,7 +97,6 @@ class RemoveResponse(Common):
|
|
|
105
97
|
"""
|
|
106
98
|
The remove response structure.
|
|
107
99
|
"""
|
|
108
|
-
|
|
109
100
|
jsonrpc: str
|
|
110
101
|
result: RemoveCardResult
|
|
111
102
|
|
|
@@ -115,6 +106,5 @@ class CheckResponse(Common):
|
|
|
115
106
|
"""
|
|
116
107
|
The check response structure.
|
|
117
108
|
"""
|
|
118
|
-
|
|
119
109
|
jsonrpc: str
|
|
120
110
|
result: Result
|
|
@@ -1,18 +1,16 @@
|
|
|
1
|
-
import typing as t
|
|
2
1
|
from dataclasses import dataclass
|
|
2
|
+
from typing import Dict, Optional, Union
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
@dataclass
|
|
6
5
|
class Common:
|
|
7
6
|
"""
|
|
8
7
|
The common response structure.
|
|
9
8
|
"""
|
|
10
|
-
|
|
11
9
|
jsonrpc: str
|
|
12
10
|
id: int
|
|
13
11
|
|
|
14
12
|
@classmethod
|
|
15
|
-
def from_dict(cls, data:
|
|
13
|
+
def from_dict(cls, data: Dict):
|
|
16
14
|
"""
|
|
17
15
|
Prepare fields for nested dataclasses
|
|
18
16
|
"""
|
|
@@ -34,7 +32,6 @@ class Account(Common):
|
|
|
34
32
|
"""
|
|
35
33
|
The account object represents a user's banking account.
|
|
36
34
|
"""
|
|
37
|
-
|
|
38
35
|
_id: str
|
|
39
36
|
account_number: str
|
|
40
37
|
account_name: str
|
|
@@ -49,11 +46,10 @@ class PaymentMethod(Common):
|
|
|
49
46
|
"""
|
|
50
47
|
The payment method object represents a user's payment method.
|
|
51
48
|
"""
|
|
52
|
-
|
|
53
49
|
name: str
|
|
54
50
|
title: str
|
|
55
51
|
value: str
|
|
56
|
-
main:
|
|
52
|
+
main: Optional[bool] = None
|
|
57
53
|
|
|
58
54
|
|
|
59
55
|
@dataclass
|
|
@@ -61,10 +57,9 @@ class Detail(Common):
|
|
|
61
57
|
"""
|
|
62
58
|
The detail object represents additional details for a receipt.
|
|
63
59
|
"""
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
items: t.Optional[str] = None
|
|
60
|
+
discount: Optional[str] = None
|
|
61
|
+
shipping: Optional[str] = None
|
|
62
|
+
items: Optional[str] = None
|
|
68
63
|
|
|
69
64
|
|
|
70
65
|
# pylint: disable=C0103
|
|
@@ -73,7 +68,6 @@ class MerchantEpos(Common):
|
|
|
73
68
|
"""
|
|
74
69
|
The merchantEpos object represents a user's ePOS.
|
|
75
70
|
"""
|
|
76
|
-
|
|
77
71
|
eposId: str
|
|
78
72
|
eposName: str
|
|
79
73
|
eposType: str
|
|
@@ -85,10 +79,9 @@ class Meta(Common):
|
|
|
85
79
|
"""
|
|
86
80
|
The meta object represents additional metadata for a receipt.
|
|
87
81
|
"""
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
host: t.Any = None
|
|
82
|
+
source: any = None
|
|
83
|
+
owner: any = None
|
|
84
|
+
host: any = None
|
|
92
85
|
|
|
93
86
|
|
|
94
87
|
@dataclass
|
|
@@ -96,18 +89,17 @@ class Merchant:
|
|
|
96
89
|
"""
|
|
97
90
|
The merchant object represents a user's merchant.
|
|
98
91
|
"""
|
|
99
|
-
|
|
100
92
|
_id: str
|
|
101
93
|
name: str
|
|
102
94
|
organization: str
|
|
103
|
-
address:
|
|
104
|
-
business_id:
|
|
105
|
-
epos:
|
|
106
|
-
restrictions:
|
|
107
|
-
date:
|
|
108
|
-
logo:
|
|
109
|
-
type:
|
|
110
|
-
terms:
|
|
95
|
+
address: Optional[str] = None
|
|
96
|
+
business_id: Optional[str] = None
|
|
97
|
+
epos: Optional[MerchantEpos] = None
|
|
98
|
+
restrictions: Optional[str] = None
|
|
99
|
+
date: Optional[int] = None
|
|
100
|
+
logo: Optional[str] = None
|
|
101
|
+
type: Optional[str] = None
|
|
102
|
+
terms: Optional[str] = None
|
|
111
103
|
|
|
112
104
|
|
|
113
105
|
@dataclass
|
|
@@ -115,7 +107,6 @@ class Payer(Common):
|
|
|
115
107
|
"""
|
|
116
108
|
The payer object represents a user's payer.
|
|
117
109
|
"""
|
|
118
|
-
|
|
119
110
|
phone: str
|
|
120
111
|
|
|
121
112
|
|
|
@@ -124,7 +115,6 @@ class Receipt(Common):
|
|
|
124
115
|
"""
|
|
125
116
|
The receipt object represents a payment receipt.
|
|
126
117
|
"""
|
|
127
|
-
|
|
128
118
|
_id: str
|
|
129
119
|
create_time: int
|
|
130
120
|
pay_time: int
|
|
@@ -133,19 +123,19 @@ class Receipt(Common):
|
|
|
133
123
|
type: int
|
|
134
124
|
external: bool
|
|
135
125
|
operation: int
|
|
136
|
-
error:
|
|
137
|
-
description:
|
|
138
|
-
detail:
|
|
139
|
-
currency:
|
|
140
|
-
commission:
|
|
141
|
-
card:
|
|
142
|
-
creator:
|
|
143
|
-
payer:
|
|
144
|
-
amount:
|
|
145
|
-
account:
|
|
146
|
-
merchant:
|
|
147
|
-
processing_id:
|
|
148
|
-
meta:
|
|
126
|
+
error: any = None
|
|
127
|
+
description: str = None
|
|
128
|
+
detail: Detail = None
|
|
129
|
+
currency: int = None
|
|
130
|
+
commission: int = None
|
|
131
|
+
card: str = None
|
|
132
|
+
creator: str = None
|
|
133
|
+
payer: Payer = None
|
|
134
|
+
amount: Union[float, int] = None
|
|
135
|
+
account: list[Account] = None
|
|
136
|
+
merchant: Merchant = None
|
|
137
|
+
processing_id: str = None
|
|
138
|
+
meta: Meta = None
|
|
149
139
|
|
|
150
140
|
|
|
151
141
|
@dataclass
|
|
@@ -153,7 +143,6 @@ class CreateResult(Common):
|
|
|
153
143
|
"""
|
|
154
144
|
The result object for the create response.
|
|
155
145
|
"""
|
|
156
|
-
|
|
157
146
|
receipt: Receipt
|
|
158
147
|
|
|
159
148
|
|
|
@@ -162,7 +151,6 @@ class CreateResponse(Common):
|
|
|
162
151
|
"""
|
|
163
152
|
The create response structure.
|
|
164
153
|
"""
|
|
165
|
-
|
|
166
154
|
result: CreateResult
|
|
167
155
|
|
|
168
156
|
|
|
@@ -178,7 +166,6 @@ class SendResult(Common):
|
|
|
178
166
|
"""
|
|
179
167
|
The result object for the send response.
|
|
180
168
|
"""
|
|
181
|
-
|
|
182
169
|
success: bool
|
|
183
170
|
|
|
184
171
|
|
|
@@ -187,7 +174,6 @@ class SendResponse(Common):
|
|
|
187
174
|
"""
|
|
188
175
|
The send response structure.
|
|
189
176
|
"""
|
|
190
|
-
|
|
191
177
|
result: SendResult
|
|
192
178
|
|
|
193
179
|
|
|
@@ -203,7 +189,6 @@ class CheckResult(Common):
|
|
|
203
189
|
"""
|
|
204
190
|
The result object for the check response.
|
|
205
191
|
"""
|
|
206
|
-
|
|
207
192
|
state: int
|
|
208
193
|
|
|
209
194
|
|
|
@@ -212,7 +197,6 @@ class CheckResponse(Common):
|
|
|
212
197
|
"""
|
|
213
198
|
The check response structure.
|
|
214
199
|
"""
|
|
215
|
-
|
|
216
200
|
result: CheckResult
|
|
217
201
|
|
|
218
202
|
|
|
@@ -228,5 +212,12 @@ class GetAllResponse(Common):
|
|
|
228
212
|
"""
|
|
229
213
|
The result object for the get all response.
|
|
230
214
|
"""
|
|
215
|
+
result: list[Receipt] = None
|
|
216
|
+
|
|
231
217
|
|
|
232
|
-
|
|
218
|
+
@dataclass
|
|
219
|
+
class SetFiscalDataResponse(Common):
|
|
220
|
+
"""
|
|
221
|
+
The result object for the set_fiscal_data response.
|
|
222
|
+
"""
|
|
223
|
+
result: SendResult
|
|
@@ -1,16 +1,15 @@
|
|
|
1
|
-
import typing as t
|
|
2
1
|
from dataclasses import dataclass, field
|
|
2
|
+
from typing import List, Optional, Dict
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
class CommonResponse:
|
|
6
6
|
"""
|
|
7
7
|
The common response structure
|
|
8
8
|
"""
|
|
9
|
-
|
|
10
9
|
def as_resp(self):
|
|
11
|
-
response = {
|
|
10
|
+
response = {'result': {}}
|
|
12
11
|
for key, value in self.__dict__.items():
|
|
13
|
-
response[
|
|
12
|
+
response['result'][key] = value
|
|
14
13
|
return response
|
|
15
14
|
|
|
16
15
|
|
|
@@ -19,7 +18,6 @@ class Shipping(CommonResponse):
|
|
|
19
18
|
"""
|
|
20
19
|
Shipping information response structure
|
|
21
20
|
"""
|
|
22
|
-
|
|
23
21
|
title: str
|
|
24
22
|
price: int
|
|
25
23
|
|
|
@@ -29,7 +27,6 @@ class Item(CommonResponse):
|
|
|
29
27
|
"""
|
|
30
28
|
Item information response structure
|
|
31
29
|
"""
|
|
32
|
-
|
|
33
30
|
discount: int
|
|
34
31
|
title: str
|
|
35
32
|
price: int
|
|
@@ -48,7 +45,7 @@ class Item(CommonResponse):
|
|
|
48
45
|
"code": self.code,
|
|
49
46
|
"units": self.units,
|
|
50
47
|
"vat_percent": self.vat_percent,
|
|
51
|
-
"package_code": self.package_code
|
|
48
|
+
"package_code": self.package_code
|
|
52
49
|
}
|
|
53
50
|
|
|
54
51
|
|
|
@@ -57,12 +54,11 @@ class CheckPerformTransaction(CommonResponse):
|
|
|
57
54
|
"""
|
|
58
55
|
Receipt information response structure for transaction checks.
|
|
59
56
|
"""
|
|
60
|
-
|
|
61
57
|
allow: bool
|
|
62
|
-
additional:
|
|
63
|
-
receipt_type:
|
|
64
|
-
shipping:
|
|
65
|
-
items:
|
|
58
|
+
additional: Optional[Dict[str, str]] = None
|
|
59
|
+
receipt_type: Optional[int] = None
|
|
60
|
+
shipping: Optional[Shipping] = None
|
|
61
|
+
items: List[Item] = field(default_factory=list)
|
|
66
62
|
|
|
67
63
|
def add_item(self, item: Item):
|
|
68
64
|
self.items.append(item)
|
|
@@ -94,10 +90,9 @@ class CreateTransaction(CommonResponse):
|
|
|
94
90
|
"""
|
|
95
91
|
The create transaction request
|
|
96
92
|
"""
|
|
97
|
-
|
|
98
93
|
transaction: str
|
|
99
94
|
state: str
|
|
100
|
-
create_time:
|
|
95
|
+
create_time: str
|
|
101
96
|
|
|
102
97
|
|
|
103
98
|
@dataclass
|
|
@@ -105,10 +100,9 @@ class PerformTransaction(CommonResponse):
|
|
|
105
100
|
"""
|
|
106
101
|
The perform transaction response
|
|
107
102
|
"""
|
|
108
|
-
|
|
109
103
|
transaction: str
|
|
110
104
|
state: str
|
|
111
|
-
perform_time:
|
|
105
|
+
perform_time: str
|
|
112
106
|
|
|
113
107
|
|
|
114
108
|
@dataclass
|
|
@@ -116,7 +110,6 @@ class CancelTransaction(CommonResponse):
|
|
|
116
110
|
"""
|
|
117
111
|
The cancel transaction request
|
|
118
112
|
"""
|
|
119
|
-
|
|
120
113
|
transaction: str
|
|
121
114
|
state: str
|
|
122
115
|
cancel_time: str
|
|
@@ -127,13 +120,12 @@ class CheckTransaction(CommonResponse):
|
|
|
127
120
|
"""
|
|
128
121
|
The check transaction request
|
|
129
122
|
"""
|
|
130
|
-
|
|
131
123
|
transaction: str
|
|
132
124
|
state: str
|
|
133
125
|
reason: str
|
|
134
|
-
create_time:
|
|
135
|
-
perform_time:
|
|
136
|
-
cancel_time:
|
|
126
|
+
create_time: str
|
|
127
|
+
perform_time: Optional[str] = None
|
|
128
|
+
cancel_time: Optional[str] = None
|
|
137
129
|
|
|
138
130
|
|
|
139
131
|
@dataclass
|
|
@@ -141,8 +133,7 @@ class GetStatement(CommonResponse):
|
|
|
141
133
|
"""
|
|
142
134
|
The check perform transactions response
|
|
143
135
|
"""
|
|
144
|
-
|
|
145
|
-
transactions: t.List[t.Dict[str, str | int | t.Dict[str, str | int]]]
|
|
136
|
+
transactions: List[str]
|
|
146
137
|
|
|
147
138
|
|
|
148
139
|
@dataclass
|
|
@@ -150,5 +141,4 @@ class SetFiscalData(CommonResponse):
|
|
|
150
141
|
"""
|
|
151
142
|
The set fiscal data request
|
|
152
143
|
"""
|
|
153
|
-
|
|
154
144
|
success: bool
|
|
@@ -4,6 +4,7 @@ import logging
|
|
|
4
4
|
from decimal import Decimal
|
|
5
5
|
|
|
6
6
|
from django.conf import settings
|
|
7
|
+
from django.core.exceptions import ValidationError
|
|
7
8
|
from django.utils.module_loading import import_string
|
|
8
9
|
from rest_framework import views
|
|
9
10
|
from rest_framework.response import Response
|
|
@@ -33,6 +34,9 @@ def handle_exceptions(func):
|
|
|
33
34
|
logger.error(f"Account does not exist: {exc} {args} {kwargs}")
|
|
34
35
|
raise exceptions.AccountDoesNotExist(str(exc)) from exc
|
|
35
36
|
|
|
37
|
+
except ValidationError:
|
|
38
|
+
raise exceptions.AccountDoesNotExist("Invalid account identifier.")
|
|
39
|
+
|
|
36
40
|
except PaymeTransactions.DoesNotExist as exc:
|
|
37
41
|
logger.error(f"Transaction does not exist: {exc} {args} {kwargs}")
|
|
38
42
|
raise exceptions.AccountDoesNotExist(str(exc)) from exc
|
|
@@ -112,17 +116,11 @@ class PaymeWebHookAPIView(views.APIView):
|
|
|
112
116
|
"""
|
|
113
117
|
Fetch account based on settings and params.
|
|
114
118
|
"""
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
account_value = params['account'].get(account_field)
|
|
119
|
+
account_value = params["account"].get(settings.PAYME_ACCOUNT_FIELD)
|
|
118
120
|
if not account_value:
|
|
119
121
|
raise exceptions.InvalidAccount("Missing account field in parameters.")
|
|
120
122
|
|
|
121
|
-
|
|
122
|
-
if account_field == "order_id":
|
|
123
|
-
account_field = "id"
|
|
124
|
-
|
|
125
|
-
account = AccountModel.objects.get(**{account_field: account_value})
|
|
123
|
+
account = AccountModel.objects.get(pk=account_value)
|
|
126
124
|
|
|
127
125
|
return account
|
|
128
126
|
|
|
@@ -169,13 +167,17 @@ class PaymeWebHookAPIView(views.APIView):
|
|
|
169
167
|
defaults = {
|
|
170
168
|
"amount": amount,
|
|
171
169
|
"state": PaymeTransactions.INITIATING,
|
|
172
|
-
"account_id": account.
|
|
170
|
+
"account_id": account.pk,
|
|
173
171
|
}
|
|
174
172
|
|
|
175
173
|
# Handle already existing transaction with the same ID for one-time payments
|
|
176
174
|
if settings.PAYME_ONE_TIME_PAYMENT:
|
|
177
175
|
# Check for an existing transaction with a different transaction_id for the given account
|
|
178
|
-
if
|
|
176
|
+
if (
|
|
177
|
+
PaymeTransactions.objects.filter(account_id=account.pk)
|
|
178
|
+
.exclude(transaction_id=transaction_id)
|
|
179
|
+
.exists()
|
|
180
|
+
):
|
|
179
181
|
message = f"Transaction {transaction_id} already exists (Payme)."
|
|
180
182
|
logger.warning(message)
|
|
181
183
|
raise exceptions.TransactionAlreadyExists(message)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: payme-pkg
|
|
3
|
-
Version: 3.0.
|
|
3
|
+
Version: 3.0.26b0
|
|
4
4
|
Home-page: https://github.com/Muhammadali-Akbarov/payme-pkg
|
|
5
5
|
Author: Muhammadali Akbarov
|
|
6
6
|
Author-email: muhammadali17abc@gmail.com
|
|
@@ -11,6 +11,15 @@ License-File: LICENSE.txt
|
|
|
11
11
|
Requires-Dist: requests==2.*
|
|
12
12
|
Requires-Dist: dataclasses==0.*; python_version < "3.7"
|
|
13
13
|
Requires-Dist: djangorestframework==3.*
|
|
14
|
+
Dynamic: author
|
|
15
|
+
Dynamic: author-email
|
|
16
|
+
Dynamic: description
|
|
17
|
+
Dynamic: description-content-type
|
|
18
|
+
Dynamic: home-page
|
|
19
|
+
Dynamic: keywords
|
|
20
|
+
Dynamic: license
|
|
21
|
+
Dynamic: license-file
|
|
22
|
+
Dynamic: requires-dist
|
|
14
23
|
|
|
15
24
|
<h1 align="center">Payme Software Development Kit</h1>
|
|
16
25
|
|
|
@@ -22,6 +22,7 @@ payme/exceptions/webhook.py
|
|
|
22
22
|
payme/migrations/0001_initial.py
|
|
23
23
|
payme/migrations/0002_paymetransactions_fiscal_data.py
|
|
24
24
|
payme/migrations/0003_alter_paymetransactions_fiscal_data.py
|
|
25
|
+
payme/migrations/0004_alter_paymetransactions_account_id.py
|
|
25
26
|
payme/migrations/__init__.py
|
|
26
27
|
payme/types/__init__.py
|
|
27
28
|
payme/types/request/__init__.py
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{payme_pkg-3.0.25b0 → payme_pkg-3.0.26b0}/payme/migrations/0002_paymetransactions_fiscal_data.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|