paytechuz 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.
Potentially problematic release.
This version of paytechuz might be problematic. Click here for more details.
- paytechuz-0.1.0/MANIFEST.in +16 -0
- paytechuz-0.1.0/PKG-INFO +198 -0
- paytechuz-0.1.0/README.md +147 -0
- paytechuz-0.1.0/core/__init__.py +0 -0
- paytechuz-0.1.0/core/base.py +88 -0
- paytechuz-0.1.0/core/constants.py +68 -0
- paytechuz-0.1.0/core/exceptions.py +190 -0
- paytechuz-0.1.0/core/http.py +268 -0
- paytechuz-0.1.0/core/utils.py +192 -0
- paytechuz-0.1.0/gateways/__init__.py +0 -0
- paytechuz-0.1.0/gateways/click/__init__.py +0 -0
- paytechuz-0.1.0/gateways/click/client.py +202 -0
- paytechuz-0.1.0/gateways/click/merchant.py +264 -0
- paytechuz-0.1.0/gateways/click/webhook.py +227 -0
- paytechuz-0.1.0/gateways/payme/__init__.py +0 -0
- paytechuz-0.1.0/gateways/payme/cards.py +222 -0
- paytechuz-0.1.0/gateways/payme/client.py +238 -0
- paytechuz-0.1.0/gateways/payme/receipts.py +336 -0
- paytechuz-0.1.0/gateways/payme/webhook.py +379 -0
- paytechuz-0.1.0/integrations/__init__.py +0 -0
- paytechuz-0.1.0/integrations/django/__init__.py +4 -0
- paytechuz-0.1.0/integrations/django/admin.py +78 -0
- paytechuz-0.1.0/integrations/django/apps.py +21 -0
- paytechuz-0.1.0/integrations/django/migrations/0001_initial.py +51 -0
- paytechuz-0.1.0/integrations/django/migrations/__init__.py +3 -0
- paytechuz-0.1.0/integrations/django/models.py +174 -0
- paytechuz-0.1.0/integrations/django/signals.py +46 -0
- paytechuz-0.1.0/integrations/django/views.py +100 -0
- paytechuz-0.1.0/integrations/django/webhooks.py +880 -0
- paytechuz-0.1.0/integrations/fastapi/__init__.py +21 -0
- paytechuz-0.1.0/integrations/fastapi/models.py +151 -0
- paytechuz-0.1.0/integrations/fastapi/routes.py +1028 -0
- paytechuz-0.1.0/integrations/fastapi/schemas.py +99 -0
- paytechuz-0.1.0/paytechuz.egg-info/PKG-INFO +198 -0
- paytechuz-0.1.0/paytechuz.egg-info/SOURCES.txt +40 -0
- paytechuz-0.1.0/paytechuz.egg-info/dependency_links.txt +1 -0
- paytechuz-0.1.0/paytechuz.egg-info/requires.txt +19 -0
- paytechuz-0.1.0/paytechuz.egg-info/top_level.txt +4 -0
- paytechuz-0.1.0/setup.cfg +4 -0
- paytechuz-0.1.0/setup.py +64 -0
- paytechuz-0.1.0/tests/__init__.py +1 -0
- paytechuz-0.1.0/tests/test_gateway.py +70 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
include LICENSE
|
|
2
|
+
include README.md
|
|
3
|
+
include PYPI_UPLOAD.md
|
|
4
|
+
recursive-include examples *
|
|
5
|
+
recursive-exclude examples *.pyc
|
|
6
|
+
recursive-exclude examples __pycache__
|
|
7
|
+
recursive-exclude examples/shop_env *
|
|
8
|
+
recursive-exclude examples/shop/media *
|
|
9
|
+
recursive-exclude examples/shop/static/img *
|
|
10
|
+
recursive-exclude examples/shop/db.sqlite3
|
|
11
|
+
recursive-exclude tests *.pyc
|
|
12
|
+
recursive-exclude tests __pycache__
|
|
13
|
+
recursive-exclude * *.py[co]
|
|
14
|
+
recursive-exclude * __pycache__
|
|
15
|
+
recursive-exclude * *.so
|
|
16
|
+
recursive-exclude * .DS_Store
|
paytechuz-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: paytechuz
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Unified Python package for Uzbekistan payment gateways (Payme, Click)
|
|
5
|
+
Home-page: https://github.com/Muhammadali-Akbarov/paytechuz
|
|
6
|
+
Author: Muhammadali Akbarov
|
|
7
|
+
Author-email: muhammadali17abc@gmail.com
|
|
8
|
+
License: MIT
|
|
9
|
+
Keywords: paytechuz,payme,click,uzbekistan,payment,gateway,payment-gateway,payment-processing,django,flask,fastapi
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.6
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.7
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
21
|
+
Classifier: Operating System :: OS Independent
|
|
22
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
23
|
+
Requires-Python: >=3.6
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
Requires-Dist: requests<3.0,>=2.0
|
|
26
|
+
Requires-Dist: dataclasses<1.0,>=0.6; python_version < "3.7"
|
|
27
|
+
Provides-Extra: django
|
|
28
|
+
Requires-Dist: django<5.0,>=3.0; extra == "django"
|
|
29
|
+
Requires-Dist: djangorestframework<4.0,>=3.0; extra == "django"
|
|
30
|
+
Provides-Extra: fastapi
|
|
31
|
+
Requires-Dist: fastapi<1.0.0,>=0.68.0; extra == "fastapi"
|
|
32
|
+
Requires-Dist: sqlalchemy<3.0,>=1.4; extra == "fastapi"
|
|
33
|
+
Requires-Dist: httpx<1.0,>=0.20; extra == "fastapi"
|
|
34
|
+
Requires-Dist: python-multipart==0.0.20; extra == "fastapi"
|
|
35
|
+
Requires-Dist: pydantic<2.0,>=1.8; extra == "fastapi"
|
|
36
|
+
Provides-Extra: flask
|
|
37
|
+
Requires-Dist: flask<3.0,>=2.0; extra == "flask"
|
|
38
|
+
Requires-Dist: flask-sqlalchemy<3.0,>=2.5; extra == "flask"
|
|
39
|
+
Dynamic: author
|
|
40
|
+
Dynamic: author-email
|
|
41
|
+
Dynamic: classifier
|
|
42
|
+
Dynamic: description
|
|
43
|
+
Dynamic: description-content-type
|
|
44
|
+
Dynamic: home-page
|
|
45
|
+
Dynamic: keywords
|
|
46
|
+
Dynamic: license
|
|
47
|
+
Dynamic: provides-extra
|
|
48
|
+
Dynamic: requires-dist
|
|
49
|
+
Dynamic: requires-python
|
|
50
|
+
Dynamic: summary
|
|
51
|
+
|
|
52
|
+
# paytechuz
|
|
53
|
+
|
|
54
|
+
paytechuz is a unified payment library for integration with popular payment systems in Uzbekistan (Payme and Click).
|
|
55
|
+
|
|
56
|
+
[](https://badge.fury.io/py/paytechuz)
|
|
57
|
+
[](https://pypi.org/project/paytechuz/)
|
|
58
|
+
[](https://opensource.org/licenses/MIT)
|
|
59
|
+
|
|
60
|
+
## Installation
|
|
61
|
+
|
|
62
|
+
To install paytechuz with all dependencies:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
pip install paytechuz
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
For specific framework support:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
# For Django
|
|
72
|
+
pip install paytechuz[django]
|
|
73
|
+
|
|
74
|
+
# For FastAPI
|
|
75
|
+
pip install paytechuz[fastapi]
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Quick Start
|
|
79
|
+
|
|
80
|
+
### Django Integration
|
|
81
|
+
|
|
82
|
+
1. Add the app to your `INSTALLED_APPS`:
|
|
83
|
+
|
|
84
|
+
```python
|
|
85
|
+
# settings.py
|
|
86
|
+
INSTALLED_APPS = [
|
|
87
|
+
# ...
|
|
88
|
+
'paytechuz.integrations.django',
|
|
89
|
+
]
|
|
90
|
+
|
|
91
|
+
# Payme settings
|
|
92
|
+
PAYME_ID = 'your_payme_merchant_id'
|
|
93
|
+
PAYME_KEY = 'your_payme_merchant_key'
|
|
94
|
+
PAYME_ACCOUNT_MODEL = 'your_app.YourModel' # For example: 'orders.Order'
|
|
95
|
+
PAYME_ACCOUNT_FIELD = 'id' # Field for account identifier
|
|
96
|
+
PAYME_AMOUNT_FIELD = 'amount' # Field for storing payment amount
|
|
97
|
+
PAYME_ONE_TIME_PAYMENT = True # Allow only one payment per account
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
2. Set up the webhook URLs:
|
|
101
|
+
|
|
102
|
+
```python
|
|
103
|
+
# urls.py
|
|
104
|
+
from django.urls import path
|
|
105
|
+
from django.views.decorators.csrf import csrf_exempt
|
|
106
|
+
|
|
107
|
+
from your_app.views import PaymeWebhookView, ClickWebhookView
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
urlpatterns = [
|
|
111
|
+
# ...
|
|
112
|
+
path('payments/payme/', csrf_exempt(PaymeWebhookView.as_view()), name='payme_webhook'),
|
|
113
|
+
path('payments/click/', csrf_exempt(ClickWebhookView.as_view()), name='click_webhook'),
|
|
114
|
+
]
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
3. Create custom webhook handlers:
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
# views.py
|
|
121
|
+
from paytechuz.integrations.django.views import PaymeWebhookView as BasePaymeWebhookView
|
|
122
|
+
from .models import Order
|
|
123
|
+
|
|
124
|
+
class PaymeWebhookView(BasePaymeWebhookView):
|
|
125
|
+
def successfully_payment(self, params, transaction):
|
|
126
|
+
"""Called when payment is successful"""
|
|
127
|
+
order_id = transaction.account_id
|
|
128
|
+
order = Order.objects.get(id=order_id)
|
|
129
|
+
order.status = 'paid'
|
|
130
|
+
order.save()
|
|
131
|
+
|
|
132
|
+
def cancelled_payment(self, params, transaction):
|
|
133
|
+
"""Called when payment is cancelled"""
|
|
134
|
+
order_id = transaction.account_id
|
|
135
|
+
order = Order.objects.get(id=order_id)
|
|
136
|
+
order.status = 'cancelled'
|
|
137
|
+
order.save()
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### FastAPI Integration
|
|
141
|
+
|
|
142
|
+
1. Create a custom webhook handler:
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
from fastapi import APIRouter, Depends, Request
|
|
146
|
+
from sqlalchemy.orm import Session
|
|
147
|
+
|
|
148
|
+
from app.database.db import get_db
|
|
149
|
+
from app.models.models import Order
|
|
150
|
+
from paytechuz.integrations.fastapi import PaymeWebhookHandler
|
|
151
|
+
|
|
152
|
+
# Payme configuration
|
|
153
|
+
PAYME_ID = 'your_payme_id'
|
|
154
|
+
PAYME_KEY = 'your_payme_key'
|
|
155
|
+
|
|
156
|
+
class CustomPaymeWebhookHandler(PaymeWebhookHandler):
|
|
157
|
+
def successfully_payment(self, params, transaction) -> None:
|
|
158
|
+
"""Called when payment is successful"""
|
|
159
|
+
order = self.db.query(Order).filter(Order.id == transaction.account_id).first()
|
|
160
|
+
if order:
|
|
161
|
+
order.status = "paid"
|
|
162
|
+
self.db.commit()
|
|
163
|
+
|
|
164
|
+
def cancelled_payment(self, params, transaction) -> None:
|
|
165
|
+
"""Called when payment is cancelled"""
|
|
166
|
+
order = self.db.query(Order).filter(Order.id == transaction.account_id).first()
|
|
167
|
+
if order:
|
|
168
|
+
order.status = "cancelled"
|
|
169
|
+
self.db.commit()
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
2. Create a webhook endpoint:
|
|
173
|
+
|
|
174
|
+
```python
|
|
175
|
+
router = APIRouter()
|
|
176
|
+
|
|
177
|
+
@router.post("/payments/payme/webhook")
|
|
178
|
+
async def payme_webhook(request: Request, db: Session = Depends(get_db)):
|
|
179
|
+
"""Handle Payme webhook requests"""
|
|
180
|
+
handler = CustomPaymeWebhookHandler(
|
|
181
|
+
db=db,
|
|
182
|
+
payme_id=PAYME_ID,
|
|
183
|
+
payme_key=PAYME_KEY,
|
|
184
|
+
account_model=Order,
|
|
185
|
+
account_field="id",
|
|
186
|
+
amount_field="amount",
|
|
187
|
+
one_time_payment=False
|
|
188
|
+
)
|
|
189
|
+
result = await handler.handle_webhook(request)
|
|
190
|
+
return result
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## Documentation
|
|
194
|
+
|
|
195
|
+
For detailed documentation, see:
|
|
196
|
+
|
|
197
|
+
- [English Documentation](paytechuz/docs/en/index.md)
|
|
198
|
+
- [O'zbek tilidagi hujjatlar](paytechuz/docs/index.md)
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# paytechuz
|
|
2
|
+
|
|
3
|
+
paytechuz is a unified payment library for integration with popular payment systems in Uzbekistan (Payme and Click).
|
|
4
|
+
|
|
5
|
+
[](https://badge.fury.io/py/paytechuz)
|
|
6
|
+
[](https://pypi.org/project/paytechuz/)
|
|
7
|
+
[](https://opensource.org/licenses/MIT)
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
To install paytechuz with all dependencies:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pip install paytechuz
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
For specific framework support:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
# For Django
|
|
21
|
+
pip install paytechuz[django]
|
|
22
|
+
|
|
23
|
+
# For FastAPI
|
|
24
|
+
pip install paytechuz[fastapi]
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Quick Start
|
|
28
|
+
|
|
29
|
+
### Django Integration
|
|
30
|
+
|
|
31
|
+
1. Add the app to your `INSTALLED_APPS`:
|
|
32
|
+
|
|
33
|
+
```python
|
|
34
|
+
# settings.py
|
|
35
|
+
INSTALLED_APPS = [
|
|
36
|
+
# ...
|
|
37
|
+
'paytechuz.integrations.django',
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
# Payme settings
|
|
41
|
+
PAYME_ID = 'your_payme_merchant_id'
|
|
42
|
+
PAYME_KEY = 'your_payme_merchant_key'
|
|
43
|
+
PAYME_ACCOUNT_MODEL = 'your_app.YourModel' # For example: 'orders.Order'
|
|
44
|
+
PAYME_ACCOUNT_FIELD = 'id' # Field for account identifier
|
|
45
|
+
PAYME_AMOUNT_FIELD = 'amount' # Field for storing payment amount
|
|
46
|
+
PAYME_ONE_TIME_PAYMENT = True # Allow only one payment per account
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
2. Set up the webhook URLs:
|
|
50
|
+
|
|
51
|
+
```python
|
|
52
|
+
# urls.py
|
|
53
|
+
from django.urls import path
|
|
54
|
+
from django.views.decorators.csrf import csrf_exempt
|
|
55
|
+
|
|
56
|
+
from your_app.views import PaymeWebhookView, ClickWebhookView
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
urlpatterns = [
|
|
60
|
+
# ...
|
|
61
|
+
path('payments/payme/', csrf_exempt(PaymeWebhookView.as_view()), name='payme_webhook'),
|
|
62
|
+
path('payments/click/', csrf_exempt(ClickWebhookView.as_view()), name='click_webhook'),
|
|
63
|
+
]
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
3. Create custom webhook handlers:
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
# views.py
|
|
70
|
+
from paytechuz.integrations.django.views import PaymeWebhookView as BasePaymeWebhookView
|
|
71
|
+
from .models import Order
|
|
72
|
+
|
|
73
|
+
class PaymeWebhookView(BasePaymeWebhookView):
|
|
74
|
+
def successfully_payment(self, params, transaction):
|
|
75
|
+
"""Called when payment is successful"""
|
|
76
|
+
order_id = transaction.account_id
|
|
77
|
+
order = Order.objects.get(id=order_id)
|
|
78
|
+
order.status = 'paid'
|
|
79
|
+
order.save()
|
|
80
|
+
|
|
81
|
+
def cancelled_payment(self, params, transaction):
|
|
82
|
+
"""Called when payment is cancelled"""
|
|
83
|
+
order_id = transaction.account_id
|
|
84
|
+
order = Order.objects.get(id=order_id)
|
|
85
|
+
order.status = 'cancelled'
|
|
86
|
+
order.save()
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### FastAPI Integration
|
|
90
|
+
|
|
91
|
+
1. Create a custom webhook handler:
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
from fastapi import APIRouter, Depends, Request
|
|
95
|
+
from sqlalchemy.orm import Session
|
|
96
|
+
|
|
97
|
+
from app.database.db import get_db
|
|
98
|
+
from app.models.models import Order
|
|
99
|
+
from paytechuz.integrations.fastapi import PaymeWebhookHandler
|
|
100
|
+
|
|
101
|
+
# Payme configuration
|
|
102
|
+
PAYME_ID = 'your_payme_id'
|
|
103
|
+
PAYME_KEY = 'your_payme_key'
|
|
104
|
+
|
|
105
|
+
class CustomPaymeWebhookHandler(PaymeWebhookHandler):
|
|
106
|
+
def successfully_payment(self, params, transaction) -> None:
|
|
107
|
+
"""Called when payment is successful"""
|
|
108
|
+
order = self.db.query(Order).filter(Order.id == transaction.account_id).first()
|
|
109
|
+
if order:
|
|
110
|
+
order.status = "paid"
|
|
111
|
+
self.db.commit()
|
|
112
|
+
|
|
113
|
+
def cancelled_payment(self, params, transaction) -> None:
|
|
114
|
+
"""Called when payment is cancelled"""
|
|
115
|
+
order = self.db.query(Order).filter(Order.id == transaction.account_id).first()
|
|
116
|
+
if order:
|
|
117
|
+
order.status = "cancelled"
|
|
118
|
+
self.db.commit()
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
2. Create a webhook endpoint:
|
|
122
|
+
|
|
123
|
+
```python
|
|
124
|
+
router = APIRouter()
|
|
125
|
+
|
|
126
|
+
@router.post("/payments/payme/webhook")
|
|
127
|
+
async def payme_webhook(request: Request, db: Session = Depends(get_db)):
|
|
128
|
+
"""Handle Payme webhook requests"""
|
|
129
|
+
handler = CustomPaymeWebhookHandler(
|
|
130
|
+
db=db,
|
|
131
|
+
payme_id=PAYME_ID,
|
|
132
|
+
payme_key=PAYME_KEY,
|
|
133
|
+
account_model=Order,
|
|
134
|
+
account_field="id",
|
|
135
|
+
amount_field="amount",
|
|
136
|
+
one_time_payment=False
|
|
137
|
+
)
|
|
138
|
+
result = await handler.handle_webhook(request)
|
|
139
|
+
return result
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Documentation
|
|
143
|
+
|
|
144
|
+
For detailed documentation, see:
|
|
145
|
+
|
|
146
|
+
- [English Documentation](paytechuz/docs/en/index.md)
|
|
147
|
+
- [O'zbek tilidagi hujjatlar](paytechuz/docs/index.md)
|
|
File without changes
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Base classes for payment gateways.
|
|
3
|
+
"""
|
|
4
|
+
from abc import ABC, abstractmethod
|
|
5
|
+
from typing import Dict, Any, Optional, Union
|
|
6
|
+
|
|
7
|
+
class BasePaymentGateway(ABC):
|
|
8
|
+
"""
|
|
9
|
+
Base class for all payment gateways.
|
|
10
|
+
|
|
11
|
+
This abstract class defines the common interface that all payment gateways
|
|
12
|
+
must implement. It provides a consistent API for creating, checking, and
|
|
13
|
+
canceling payments regardless of the underlying payment provider.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
def __init__(self, is_test_mode: bool = False):
|
|
17
|
+
"""
|
|
18
|
+
Initialize the payment gateway.
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
is_test_mode (bool): Whether to use the test environment
|
|
22
|
+
"""
|
|
23
|
+
self.is_test_mode = is_test_mode
|
|
24
|
+
|
|
25
|
+
@abstractmethod
|
|
26
|
+
def create_payment(self, amount: Union[int, float, str], account_id: Union[int, str], **kwargs) -> Dict[str, Any]:
|
|
27
|
+
"""
|
|
28
|
+
Create a payment.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
amount: The payment amount
|
|
32
|
+
account_id: The account ID or order ID
|
|
33
|
+
**kwargs: Additional parameters specific to the payment gateway
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
Dict containing payment details including transaction ID
|
|
37
|
+
"""
|
|
38
|
+
raise NotImplementedError
|
|
39
|
+
|
|
40
|
+
@abstractmethod
|
|
41
|
+
def check_payment(self, transaction_id: str) -> Dict[str, Any]:
|
|
42
|
+
"""
|
|
43
|
+
Check payment status.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
transaction_id: The transaction ID to check
|
|
47
|
+
|
|
48
|
+
Returns:
|
|
49
|
+
Dict containing payment status and details
|
|
50
|
+
"""
|
|
51
|
+
raise NotImplementedError
|
|
52
|
+
|
|
53
|
+
@abstractmethod
|
|
54
|
+
def cancel_payment(self, transaction_id: str, reason: Optional[str] = None) -> Dict[str, Any]:
|
|
55
|
+
"""
|
|
56
|
+
Cancel payment.
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
transaction_id: The transaction ID to cancel
|
|
60
|
+
reason: Optional reason for cancellation
|
|
61
|
+
|
|
62
|
+
Returns:
|
|
63
|
+
Dict containing cancellation status and details
|
|
64
|
+
"""
|
|
65
|
+
raise NotImplementedError
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class BaseWebhookHandler(ABC):
|
|
70
|
+
"""
|
|
71
|
+
Base class for payment gateway webhook handlers.
|
|
72
|
+
|
|
73
|
+
This abstract class defines the common interface for handling webhook
|
|
74
|
+
callbacks from payment gateways.
|
|
75
|
+
"""
|
|
76
|
+
|
|
77
|
+
@abstractmethod
|
|
78
|
+
def handle_webhook(self, data: Dict[str, Any]) -> Dict[str, Any]:
|
|
79
|
+
"""
|
|
80
|
+
Handle webhook data from payment gateway.
|
|
81
|
+
|
|
82
|
+
Args:
|
|
83
|
+
data: The webhook data received from the payment gateway
|
|
84
|
+
|
|
85
|
+
Returns:
|
|
86
|
+
Dict containing the response to be sent back to the payment gateway
|
|
87
|
+
"""
|
|
88
|
+
raise NotImplementedError
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Constants for payment gateways.
|
|
3
|
+
"""
|
|
4
|
+
from enum import Enum
|
|
5
|
+
|
|
6
|
+
class TransactionState(Enum):
|
|
7
|
+
"""Transaction states."""
|
|
8
|
+
CREATED = 0
|
|
9
|
+
INITIATING = 1
|
|
10
|
+
SUCCESSFULLY = 2
|
|
11
|
+
CANCELED = -2
|
|
12
|
+
CANCELED_DURING_INIT = -1
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class PaymentGateway(Enum):
|
|
16
|
+
"""Payment gateway types."""
|
|
17
|
+
PAYME = "payme"
|
|
18
|
+
CLICK = "click"
|
|
19
|
+
|
|
20
|
+
class PaymeEndpoints:
|
|
21
|
+
"""Payme API endpoints."""
|
|
22
|
+
RECEIPTS_CREATE = "receipts/create"
|
|
23
|
+
RECEIPTS_PAY = "receipts/pay"
|
|
24
|
+
RECEIPTS_SEND = "receipts/send"
|
|
25
|
+
RECEIPTS_CHECK = "receipts/check"
|
|
26
|
+
RECEIPTS_CANCEL = "receipts/cancel"
|
|
27
|
+
RECEIPTS_GET = "receipts/get"
|
|
28
|
+
CARDS_CREATE = "cards/create"
|
|
29
|
+
CARDS_VERIFY = "cards/verify"
|
|
30
|
+
CARDS_CHECK = "cards/check"
|
|
31
|
+
CARDS_REMOVE = "cards/remove"
|
|
32
|
+
CARDS_GET_VERIFY_CODE = "cards/get_verify_code"
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class PaymeNetworks:
|
|
36
|
+
"""Payme API networks."""
|
|
37
|
+
TEST_NET = "https://checkout.test.paycom.uz/api"
|
|
38
|
+
PROD_NET = "https://checkout.paycom.uz/api"
|
|
39
|
+
|
|
40
|
+
class ClickEndpoints:
|
|
41
|
+
"""Click API endpoints."""
|
|
42
|
+
PREPARE = "prepare"
|
|
43
|
+
COMPLETE = "complete"
|
|
44
|
+
MERCHANT_API = "merchant/api"
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class ClickNetworks:
|
|
48
|
+
"""Click API networks."""
|
|
49
|
+
TEST_NET = "https://api.click.uz/v2/merchant"
|
|
50
|
+
PROD_NET = "https://api.click.uz/v2/merchant"
|
|
51
|
+
|
|
52
|
+
class ClickActions:
|
|
53
|
+
"""Click API actions."""
|
|
54
|
+
PREPARE = 0
|
|
55
|
+
COMPLETE = 1
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class PaymeCancelReason:
|
|
59
|
+
"""Payme cancel reason codes."""
|
|
60
|
+
REASON_USER_NOT_FOUND = 1
|
|
61
|
+
REASON_DEBIT_OPERATION_FAILED = 2
|
|
62
|
+
REASON_EXECUTION_ERROR = 3
|
|
63
|
+
REASON_TIMEOUT = 4
|
|
64
|
+
REASON_FUND_RETURNED = 5
|
|
65
|
+
REASON_UNKNOWN = 6
|
|
66
|
+
REASON_CANCELLED_BY_USER = 7
|
|
67
|
+
REASON_SUSPICIOUS_OPERATION = 8
|
|
68
|
+
REASON_MERCHANT_DECISION = 9
|