paytechuz 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of paytechuz might be problematic. Click here for more details.
- core/__init__.py +0 -0
- core/base.py +88 -0
- core/constants.py +68 -0
- core/exceptions.py +190 -0
- core/http.py +268 -0
- core/utils.py +192 -0
- gateways/__init__.py +0 -0
- gateways/click/__init__.py +0 -0
- gateways/click/client.py +202 -0
- gateways/click/merchant.py +264 -0
- gateways/click/webhook.py +227 -0
- gateways/payme/__init__.py +0 -0
- gateways/payme/cards.py +222 -0
- gateways/payme/client.py +238 -0
- gateways/payme/receipts.py +336 -0
- gateways/payme/webhook.py +379 -0
- integrations/__init__.py +0 -0
- integrations/django/__init__.py +4 -0
- integrations/django/admin.py +78 -0
- integrations/django/apps.py +21 -0
- integrations/django/migrations/0001_initial.py +51 -0
- integrations/django/migrations/__init__.py +3 -0
- integrations/django/models.py +174 -0
- integrations/django/signals.py +46 -0
- integrations/django/views.py +100 -0
- integrations/django/webhooks.py +880 -0
- integrations/fastapi/__init__.py +21 -0
- integrations/fastapi/models.py +151 -0
- integrations/fastapi/routes.py +1028 -0
- integrations/fastapi/schemas.py +99 -0
- paytechuz-0.1.0.dist-info/METADATA +198 -0
- paytechuz-0.1.0.dist-info/RECORD +36 -0
- paytechuz-0.1.0.dist-info/WHEEL +5 -0
- paytechuz-0.1.0.dist-info/top_level.txt +4 -0
- tests/__init__.py +1 -0
- tests/test_gateway.py +70 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"""
|
|
2
|
+
FastAPI schemas for PayTechUZ.
|
|
3
|
+
"""
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
from typing import Dict, Any, Optional, List
|
|
6
|
+
|
|
7
|
+
from pydantic import BaseModel, Field
|
|
8
|
+
|
|
9
|
+
class PaymentTransactionBase(BaseModel):
|
|
10
|
+
"""
|
|
11
|
+
Base schema for payment transaction.
|
|
12
|
+
"""
|
|
13
|
+
gateway: str = Field(..., description="Payment gateway (payme or click)")
|
|
14
|
+
transaction_id: str = Field(..., description="Transaction ID from the payment system")
|
|
15
|
+
account_id: str = Field(..., description="Account or order ID")
|
|
16
|
+
amount: float = Field(..., description="Payment amount")
|
|
17
|
+
state: int = Field(0, description="Transaction state")
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class PaymentTransactionCreate(PaymentTransactionBase):
|
|
21
|
+
"""
|
|
22
|
+
Schema for creating a payment transaction.
|
|
23
|
+
"""
|
|
24
|
+
extra_data: Optional[Dict[str, Any]] = Field(None, description="Additional data for the transaction")
|
|
25
|
+
|
|
26
|
+
class PaymentTransaction(PaymentTransactionBase):
|
|
27
|
+
"""
|
|
28
|
+
Schema for payment transaction.
|
|
29
|
+
"""
|
|
30
|
+
id: int = Field(..., description="Transaction ID")
|
|
31
|
+
extra_data: Dict[str, Any] = Field({}, description="Additional data for the transaction")
|
|
32
|
+
created_at: datetime = Field(..., description="Creation timestamp")
|
|
33
|
+
updated_at: datetime = Field(..., description="Last update timestamp")
|
|
34
|
+
performed_at: Optional[datetime] = Field(None, description="Payment timestamp")
|
|
35
|
+
cancelled_at: Optional[datetime] = Field(None, description="Cancellation timestamp")
|
|
36
|
+
|
|
37
|
+
class Config:
|
|
38
|
+
"""
|
|
39
|
+
Pydantic configuration.
|
|
40
|
+
"""
|
|
41
|
+
orm_mode = True
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class PaymentTransactionList(BaseModel):
|
|
45
|
+
"""
|
|
46
|
+
Schema for a list of payment transactions.
|
|
47
|
+
"""
|
|
48
|
+
transactions: List[PaymentTransaction] = Field(..., description="List of transactions")
|
|
49
|
+
total: int = Field(..., description="Total number of transactions")
|
|
50
|
+
|
|
51
|
+
class PaymeWebhookRequest(BaseModel):
|
|
52
|
+
"""
|
|
53
|
+
Schema for Payme webhook request.
|
|
54
|
+
"""
|
|
55
|
+
method: str = Field(..., description="Method name")
|
|
56
|
+
params: Dict[str, Any] = Field(..., description="Method parameters")
|
|
57
|
+
id: int = Field(..., description="Request ID")
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class PaymeWebhookResponse(BaseModel):
|
|
61
|
+
"""
|
|
62
|
+
Schema for Payme webhook response.
|
|
63
|
+
"""
|
|
64
|
+
jsonrpc: str = Field("2.0", description="JSON-RPC version")
|
|
65
|
+
id: int = Field(..., description="Request ID")
|
|
66
|
+
result: Dict[str, Any] = Field(..., description="Response result")
|
|
67
|
+
|
|
68
|
+
class PaymeWebhookErrorResponse(BaseModel):
|
|
69
|
+
"""
|
|
70
|
+
Schema for Payme webhook error response.
|
|
71
|
+
"""
|
|
72
|
+
jsonrpc: str = Field("2.0", description="JSON-RPC version")
|
|
73
|
+
id: int = Field(..., description="Request ID")
|
|
74
|
+
error: Dict[str, Any] = Field(..., description="Error details")
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class ClickWebhookRequest(BaseModel):
|
|
78
|
+
"""
|
|
79
|
+
Schema for Click webhook request.
|
|
80
|
+
"""
|
|
81
|
+
click_trans_id: str = Field(..., description="Click transaction ID")
|
|
82
|
+
service_id: str = Field(..., description="Service ID")
|
|
83
|
+
merchant_trans_id: str = Field(..., description="Merchant transaction ID")
|
|
84
|
+
amount: str = Field(..., description="Payment amount")
|
|
85
|
+
action: str = Field(..., description="Action (0 - prepare, 1 - complete)")
|
|
86
|
+
sign_time: str = Field(..., description="Signature timestamp")
|
|
87
|
+
sign_string: str = Field(..., description="Signature string")
|
|
88
|
+
error: Optional[str] = Field(None, description="Error code")
|
|
89
|
+
error_note: Optional[str] = Field(None, description="Error note")
|
|
90
|
+
|
|
91
|
+
class ClickWebhookResponse(BaseModel):
|
|
92
|
+
"""
|
|
93
|
+
Schema for Click webhook response.
|
|
94
|
+
"""
|
|
95
|
+
click_trans_id: str = Field(..., description="Click transaction ID")
|
|
96
|
+
merchant_trans_id: str = Field(..., description="Merchant transaction ID")
|
|
97
|
+
merchant_prepare_id: Optional[int] = Field(None, description="Merchant prepare ID")
|
|
98
|
+
error: int = Field(0, description="Error code")
|
|
99
|
+
error_note: str = Field("Success", description="Error note")
|
|
@@ -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,36 @@
|
|
|
1
|
+
core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
core/base.py,sha256=bHmRMYZ97Kj76a4kL7UMRcecnZF-rKnBYZddQvRtRmQ,2497
|
|
3
|
+
core/constants.py,sha256=P2zeZ_cfZIttdC1vqkpIngkfRFh6loWzJYEgzQb5cKA,1660
|
|
4
|
+
core/exceptions.py,sha256=XMJkqiponTkvhjoh3S2iFNuU3UbBdFW4130kd0hpudg,5489
|
|
5
|
+
core/http.py,sha256=qmLR6ujxmIPjwoTS4vvKRIvDnNcpl84sS1HmVB890b0,7686
|
|
6
|
+
core/utils.py,sha256=ETHMzwu7_dirc-QfBUjpSTQmyS6_vBiNq97Dq9CNZto,4718
|
|
7
|
+
gateways/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
+
gateways/click/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
|
+
gateways/click/client.py,sha256=XTri3iogq4_MgvZehBK2CScVCMubvg1GNXV9whGAS6I,6663
|
|
10
|
+
gateways/click/merchant.py,sha256=vJ_DivA1KfRT5p3sfA5yZGMYXoUmVbAM7QHvaXr6VCU,7254
|
|
11
|
+
gateways/click/webhook.py,sha256=rph-NmjjnBKMW4rcxQTXrHHdK-uMrU39kXnbqK56leo,7936
|
|
12
|
+
gateways/payme/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
|
+
gateways/payme/cards.py,sha256=aL6su_ZTCBPU8qmrz2Jcw_Wn7Zf9RwIu8k10o4AWFTs,5420
|
|
14
|
+
gateways/payme/client.py,sha256=C1OQWLo7LIAF3xbFOLyCaJ3xFwQaFVpaxWCYajCltTY,8201
|
|
15
|
+
gateways/payme/receipts.py,sha256=DdrZMPeDvQmGyqAEOTmtUorfcIVVb3t2tg31l7TXqHo,8904
|
|
16
|
+
gateways/payme/webhook.py,sha256=-0O8vzMtiu4U8FWFKDA6EfyoX4NEGqcEq-T0yNtVhM4,12374
|
|
17
|
+
integrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
18
|
+
integrations/django/__init__.py,sha256=YDgD1Ux1E3CJxQMT-9tulhXmuLOEaUSv320LeaVgJ00,116
|
|
19
|
+
integrations/django/admin.py,sha256=6fs6GiKcdc-hGlLxJ0BthY7TFo_2RVVJRhQwhxMroCY,2664
|
|
20
|
+
integrations/django/apps.py,sha256=57svd2aqSuoASWMI3Jnh70ZXrYN1oQ8EnvLl_5LNyl0,473
|
|
21
|
+
integrations/django/models.py,sha256=83PjBnombavEjfPm2EcVFo2R5BO6VRIjp0MlNCp-fbg,5819
|
|
22
|
+
integrations/django/signals.py,sha256=VtNYEAnu13wi9PqadEaCU9LY_k2tY26AS4bnPIAqw7M,1319
|
|
23
|
+
integrations/django/views.py,sha256=nP2HRMx02tMbdv_KfDqIA5vQAwZ6TUuZazrZ2zoNfqQ,3029
|
|
24
|
+
integrations/django/webhooks.py,sha256=cP_Jc3VlyyvyzDbBd2yEVHikw60th1_-L9_vtsRfwgs,31335
|
|
25
|
+
integrations/django/migrations/0001_initial.py,sha256=YLDUp1w0V3Zvuz5TssQDrx3PlccduoHqdLD109Hg8Z4,2326
|
|
26
|
+
integrations/django/migrations/__init__.py,sha256=KLQ5NdjOMLDS21-u3b_g08G1MjPMMhG95XI_N8m4FSo,41
|
|
27
|
+
integrations/fastapi/__init__.py,sha256=DLnhAZQZf2ghu8BuFFfE7FzbNKWQQ2SLG8qxldRuwR4,565
|
|
28
|
+
integrations/fastapi/models.py,sha256=eWGUpiKufj47AK8Hld4A91jRDj0ZKQzAf95CyUozmvo,4638
|
|
29
|
+
integrations/fastapi/routes.py,sha256=D17QeyY4-aX6tCNmk5h3UiavukvVrE5e6JOFCy4t_n8,36629
|
|
30
|
+
integrations/fastapi/schemas.py,sha256=CkNohj22mQQje8Pu_IkTQwUPAoYHNOKXlGjqaRX_SGQ,3784
|
|
31
|
+
tests/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
32
|
+
tests/test_gateway.py,sha256=BlFu1rpUkwvyvz0FnMW0Ql2h1_oolKsiu1O29i4_5tY,2028
|
|
33
|
+
paytechuz-0.1.0.dist-info/METADATA,sha256=pAGMLutaf31x74N9PXdcu-QzUVZ-lO27M6tpPwKshNY,6073
|
|
34
|
+
paytechuz-0.1.0.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
|
35
|
+
paytechuz-0.1.0.dist-info/top_level.txt,sha256=R3fFUS1l6Qekw12fn3uEDdEXoU3hM1KY6QsBFpGWEh0,33
|
|
36
|
+
paytechuz-0.1.0.dist-info/RECORD,,
|
tests/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
tests/test_gateway.py
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Tests for the gateway module.
|
|
3
|
+
"""
|
|
4
|
+
import unittest
|
|
5
|
+
from unittest.mock import patch, MagicMock
|
|
6
|
+
|
|
7
|
+
from paytechuz import create_gateway
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class TestCreateGateway(unittest.TestCase):
|
|
11
|
+
"""
|
|
12
|
+
Test the create_gateway function.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
def test_create_payme_gateway(self):
|
|
16
|
+
"""
|
|
17
|
+
Test creating a Payme gateway.
|
|
18
|
+
"""
|
|
19
|
+
with patch('paytechuz.gateway.PaymeGateway') as mock_payme:
|
|
20
|
+
mock_instance = MagicMock()
|
|
21
|
+
mock_payme.return_value = mock_instance
|
|
22
|
+
|
|
23
|
+
gateway = create_gateway(
|
|
24
|
+
'payme',
|
|
25
|
+
payme_id='test-id',
|
|
26
|
+
payme_key='test-key',
|
|
27
|
+
is_test_mode=True
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
self.assertEqual(gateway, mock_instance)
|
|
31
|
+
mock_payme.assert_called_once_with(
|
|
32
|
+
payme_id='test-id',
|
|
33
|
+
payme_key='test-key',
|
|
34
|
+
is_test_mode=True
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
def test_create_click_gateway(self):
|
|
38
|
+
"""
|
|
39
|
+
Test creating a Click gateway.
|
|
40
|
+
"""
|
|
41
|
+
with patch('paytechuz.gateway.ClickGateway') as mock_click:
|
|
42
|
+
mock_instance = MagicMock()
|
|
43
|
+
mock_click.return_value = mock_instance
|
|
44
|
+
|
|
45
|
+
gateway = create_gateway(
|
|
46
|
+
'click',
|
|
47
|
+
service_id='test-service-id',
|
|
48
|
+
merchant_id='test-merchant-id',
|
|
49
|
+
secret_key='test-secret-key',
|
|
50
|
+
is_test_mode=True
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
self.assertEqual(gateway, mock_instance)
|
|
54
|
+
mock_click.assert_called_once_with(
|
|
55
|
+
service_id='test-service-id',
|
|
56
|
+
merchant_id='test-merchant-id',
|
|
57
|
+
secret_key='test-secret-key',
|
|
58
|
+
is_test_mode=True
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
def test_invalid_gateway_type(self):
|
|
62
|
+
"""
|
|
63
|
+
Test creating a gateway with an invalid type.
|
|
64
|
+
"""
|
|
65
|
+
with self.assertRaises(ValueError):
|
|
66
|
+
create_gateway('invalid')
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
if __name__ == '__main__':
|
|
70
|
+
unittest.main()
|