paytechuz 0.2.10__tar.gz → 0.2.13__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.

Files changed (83) hide show
  1. {paytechuz-0.2.10 → paytechuz-0.2.13}/PKG-INFO +30 -13
  2. {paytechuz-0.2.10 → paytechuz-0.2.13}/README.md +29 -12
  3. paytechuz-0.2.13/examples/paytechuz_fastapi/app/database.py +10 -0
  4. paytechuz-0.2.13/examples/paytechuz_fastapi/app/models.py +17 -0
  5. paytechuz-0.2.13/examples/paytechuz_fastapi/app/typing.py +55 -0
  6. paytechuz-0.2.13/examples/paytechuz_fastapi/app/webhook_handlers.py +28 -0
  7. paytechuz-0.2.13/examples/paytechuz_fastapi/main.py +103 -0
  8. paytechuz-0.2.13/examples/paytechuz_fastapi/payments.db +0 -0
  9. paytechuz-0.2.13/examples/paytechuz_fastapi/run.sh +2 -0
  10. {paytechuz-0.2.10 → paytechuz-0.2.13}/pyproject.toml +1 -1
  11. {paytechuz-0.2.10 → paytechuz-0.2.13}/setup.py +1 -1
  12. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/integrations/fastapi/routes.py +1 -1
  13. paytechuz-0.2.13/src/paytechuz/gateways/__init__.py +0 -0
  14. paytechuz-0.2.13/src/paytechuz/integrations/__init__.py +0 -0
  15. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/paytechuz/integrations/django/webhooks.py +41 -28
  16. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/paytechuz/integrations/fastapi/routes.py +1 -1
  17. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/paytechuz.egg-info/PKG-INFO +30 -13
  18. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/paytechuz.egg-info/SOURCES.txt +9 -0
  19. {paytechuz-0.2.10 → paytechuz-0.2.13}/MANIFEST.in +0 -0
  20. {paytechuz-0.2.10/src/core → paytechuz-0.2.13/examples/paytechuz_fastapi}/__init__.py +0 -0
  21. {paytechuz-0.2.10/src/gateways → paytechuz-0.2.13/examples/paytechuz_fastapi/app}/__init__.py +0 -0
  22. {paytechuz-0.2.10 → paytechuz-0.2.13}/setup.cfg +0 -0
  23. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/__init__.py +0 -0
  24. {paytechuz-0.2.10/src/gateways/click → paytechuz-0.2.13/src/core}/__init__.py +0 -0
  25. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/core/base.py +0 -0
  26. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/core/constants.py +0 -0
  27. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/core/exceptions.py +0 -0
  28. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/core/http.py +0 -0
  29. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/core/payme/errors.py +0 -0
  30. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/core/utils.py +0 -0
  31. {paytechuz-0.2.10/src/gateways/payme → paytechuz-0.2.13/src/gateways}/__init__.py +0 -0
  32. {paytechuz-0.2.10/src/integrations → paytechuz-0.2.13/src/gateways/click}/__init__.py +0 -0
  33. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/gateways/click/client.py +0 -0
  34. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/gateways/click/merchant.py +0 -0
  35. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/gateways/click/webhook.py +0 -0
  36. {paytechuz-0.2.10/src/paytechuz/core → paytechuz-0.2.13/src/gateways/payme}/__init__.py +0 -0
  37. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/gateways/payme/cards.py +0 -0
  38. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/gateways/payme/client.py +0 -0
  39. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/gateways/payme/receipts.py +0 -0
  40. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/gateways/payme/webhook.py +0 -0
  41. {paytechuz-0.2.10/src/paytechuz/gateways → paytechuz-0.2.13/src/integrations}/__init__.py +0 -0
  42. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/integrations/django/__init__.py +0 -0
  43. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/integrations/django/admin.py +0 -0
  44. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/integrations/django/apps.py +0 -0
  45. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/integrations/django/migrations/0001_initial.py +0 -0
  46. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/integrations/django/migrations/__init__.py +0 -0
  47. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/integrations/django/models.py +0 -0
  48. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/integrations/django/signals.py +0 -0
  49. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/integrations/django/views.py +0 -0
  50. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/integrations/django/webhooks.py +0 -0
  51. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/integrations/fastapi/__init__.py +0 -0
  52. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/integrations/fastapi/models.py +0 -0
  53. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/integrations/fastapi/schemas.py +0 -0
  54. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/paytechuz/__init__.py +0 -0
  55. {paytechuz-0.2.10/src/paytechuz/integrations → paytechuz-0.2.13/src/paytechuz/core}/__init__.py +0 -0
  56. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/paytechuz/core/base.py +0 -0
  57. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/paytechuz/core/constants.py +0 -0
  58. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/paytechuz/core/exceptions.py +0 -0
  59. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/paytechuz/core/http.py +0 -0
  60. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/paytechuz/core/payme/errors.py +0 -0
  61. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/paytechuz/core/utils.py +0 -0
  62. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/paytechuz/gateways/click/__init__.py +0 -0
  63. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/paytechuz/gateways/click/client.py +0 -0
  64. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/paytechuz/gateways/click/merchant.py +0 -0
  65. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/paytechuz/gateways/click/webhook.py +0 -0
  66. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/paytechuz/gateways/payme/__init__.py +0 -0
  67. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/paytechuz/gateways/payme/cards.py +0 -0
  68. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/paytechuz/gateways/payme/client.py +0 -0
  69. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/paytechuz/gateways/payme/receipts.py +0 -0
  70. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/paytechuz/gateways/payme/webhook.py +0 -0
  71. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/paytechuz/integrations/django/__init__.py +0 -0
  72. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/paytechuz/integrations/django/admin.py +0 -0
  73. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/paytechuz/integrations/django/apps.py +0 -0
  74. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/paytechuz/integrations/django/migrations/0001_initial.py +0 -0
  75. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/paytechuz/integrations/django/migrations/__init__.py +0 -0
  76. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/paytechuz/integrations/django/models.py +0 -0
  77. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/paytechuz/integrations/django/signals.py +0 -0
  78. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/paytechuz/integrations/django/views.py +0 -0
  79. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/paytechuz/integrations/fastapi/__init__.py +0 -0
  80. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/paytechuz/integrations/fastapi/models.py +0 -0
  81. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/paytechuz/integrations/fastapi/schemas.py +0 -0
  82. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/paytechuz.egg-info/dependency_links.txt +0 -0
  83. {paytechuz-0.2.10 → paytechuz-0.2.13}/src/paytechuz.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: paytechuz
3
- Version: 0.2.10
3
+ Version: 0.2.13
4
4
  Summary: Unified Python package for Uzbekistan payment gateways
5
5
  Home-page: https://github.com/Muhammadali-Akbarov/paytechuz
6
6
  Author: Muhammadali Akbarov
@@ -17,10 +17,13 @@ Dynamic: requires-python
17
17
 
18
18
  [![PyPI version](https://badge.fury.io/py/paytechuz.svg)](https://badge.fury.io/py/paytechuz)
19
19
  [![Python Versions](https://img.shields.io/pypi/pyversions/paytechuz.svg)](https://pypi.org/project/paytechuz/)
20
+ [![Documentation](https://img.shields.io/badge/docs-pay--tech.uz-blue.svg)](https://pay-tech.uz)
20
21
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
21
22
 
22
23
  PayTechUZ is a unified payment library for integrating with popular payment systems in Uzbekistan. It provides a simple and consistent interface for working with Payme and Click payment gateways.
23
24
 
25
+ 📖 **[Complete Documentation](https://pay-tech.uz)** | 🚀 **[Quick Start Guide](https://pay-tech.uz/quickstart)**
26
+
24
27
  ## Features
25
28
 
26
29
  - 🔄 **API**: Consistent interface for multiple payment providers
@@ -49,6 +52,8 @@ pip install paytechuz[fastapi]
49
52
 
50
53
  ## Quick Start
51
54
 
55
+ > 💡 **Need help?** Check out our [complete documentation](https://pay-tech.uz) for detailed guides and examples.
56
+
52
57
  ### Generate Payment Links
53
58
 
54
59
  ```python
@@ -121,18 +126,26 @@ INSTALLED_APPS = [
121
126
  'paytechuz.integrations.django',
122
127
  ]
123
128
 
124
- PAYME_ID = 'your_payme_merchant_id'
125
- PAYME_KEY = 'your_payme_merchant_key'
126
- PAYME_ACCOUNT_MODEL = 'your_app.models.Order' # For example: 'orders.models.Order'
127
- PAYME_ACCOUNT_FIELD = 'id'
128
- PAYME_AMOUNT_FIELD = 'amount' # Field for storing payment amount
129
- PAYME_ONE_TIME_PAYMENT = True # Allow only one payment per account
130
-
131
- CLICK_SERVICE_ID = 'your_click_service_id'
132
- CLICK_MERCHANT_ID = 'your_click_merchant_id'
133
- CLICK_SECRET_KEY = 'your_click_secret_key'
134
- CLICK_ACCOUNT_MODEL = 'your_app.models.Order'
135
- CLICK_COMMISSION_PERCENT = 0.0
129
+ PAYTECHUZ = {
130
+ 'PAYME': {
131
+ 'PAYME_ID': 'your_payme_id',
132
+ 'PAYME_KEY': 'your_payme_key',
133
+ 'ACCOUNT_MODEL': 'your_app.models.Order', # For example: 'orders.models.Order'
134
+ 'ACCOUNT_FIELD': 'id',
135
+ 'AMOUNT_FIELD': 'amount',
136
+ 'ONE_TIME_PAYMENT': True,
137
+ 'IS_TEST_MODE': True, # Set to False in production
138
+ },
139
+ 'CLICK': {
140
+ 'SERVICE_ID': 'your_service_id',
141
+ 'MERCHANT_ID': 'your_merchant_id',
142
+ 'MERCHANT_USER_ID': 'your_merchant_user_id',
143
+ 'SECRET_KEY': 'your_secret_key',
144
+ 'ACCOUNT_MODEL': 'your_app.models.Order',
145
+ 'COMMISSION_PERCENT': 0.0,
146
+ 'IS_TEST_MODE': True, # Set to False in production
147
+ }
148
+ }
136
149
  ```
137
150
 
138
151
  3. Create webhook handlers:
@@ -313,6 +326,10 @@ Detailed documentation is available in multiple languages:
313
326
 
314
327
  Contributions are welcome! Please feel free to submit a Pull Request.
315
328
 
329
+ 📖 **Documentation:** [pay-tech.uz](https://pay-tech.uz)
330
+ 🐛 **Issues:** [GitHub Issues](https://github.com/PayTechUz/paytechuz-py/issues)
331
+ 💬 **Support:** [Telegram](https://t.me/paytechuz)
332
+
316
333
  ## License
317
334
 
318
335
  This project is licensed under the MIT License - see the LICENSE file for details.
@@ -2,10 +2,13 @@
2
2
 
3
3
  [![PyPI version](https://badge.fury.io/py/paytechuz.svg)](https://badge.fury.io/py/paytechuz)
4
4
  [![Python Versions](https://img.shields.io/pypi/pyversions/paytechuz.svg)](https://pypi.org/project/paytechuz/)
5
+ [![Documentation](https://img.shields.io/badge/docs-pay--tech.uz-blue.svg)](https://pay-tech.uz)
5
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
7
 
7
8
  PayTechUZ is a unified payment library for integrating with popular payment systems in Uzbekistan. It provides a simple and consistent interface for working with Payme and Click payment gateways.
8
9
 
10
+ 📖 **[Complete Documentation](https://pay-tech.uz)** | 🚀 **[Quick Start Guide](https://pay-tech.uz/quickstart)**
11
+
9
12
  ## Features
10
13
 
11
14
  - 🔄 **API**: Consistent interface for multiple payment providers
@@ -34,6 +37,8 @@ pip install paytechuz[fastapi]
34
37
 
35
38
  ## Quick Start
36
39
 
40
+ > 💡 **Need help?** Check out our [complete documentation](https://pay-tech.uz) for detailed guides and examples.
41
+
37
42
  ### Generate Payment Links
38
43
 
39
44
  ```python
@@ -106,18 +111,26 @@ INSTALLED_APPS = [
106
111
  'paytechuz.integrations.django',
107
112
  ]
108
113
 
109
- PAYME_ID = 'your_payme_merchant_id'
110
- PAYME_KEY = 'your_payme_merchant_key'
111
- PAYME_ACCOUNT_MODEL = 'your_app.models.Order' # For example: 'orders.models.Order'
112
- PAYME_ACCOUNT_FIELD = 'id'
113
- PAYME_AMOUNT_FIELD = 'amount' # Field for storing payment amount
114
- PAYME_ONE_TIME_PAYMENT = True # Allow only one payment per account
115
-
116
- CLICK_SERVICE_ID = 'your_click_service_id'
117
- CLICK_MERCHANT_ID = 'your_click_merchant_id'
118
- CLICK_SECRET_KEY = 'your_click_secret_key'
119
- CLICK_ACCOUNT_MODEL = 'your_app.models.Order'
120
- CLICK_COMMISSION_PERCENT = 0.0
114
+ PAYTECHUZ = {
115
+ 'PAYME': {
116
+ 'PAYME_ID': 'your_payme_id',
117
+ 'PAYME_KEY': 'your_payme_key',
118
+ 'ACCOUNT_MODEL': 'your_app.models.Order', # For example: 'orders.models.Order'
119
+ 'ACCOUNT_FIELD': 'id',
120
+ 'AMOUNT_FIELD': 'amount',
121
+ 'ONE_TIME_PAYMENT': True,
122
+ 'IS_TEST_MODE': True, # Set to False in production
123
+ },
124
+ 'CLICK': {
125
+ 'SERVICE_ID': 'your_service_id',
126
+ 'MERCHANT_ID': 'your_merchant_id',
127
+ 'MERCHANT_USER_ID': 'your_merchant_user_id',
128
+ 'SECRET_KEY': 'your_secret_key',
129
+ 'ACCOUNT_MODEL': 'your_app.models.Order',
130
+ 'COMMISSION_PERCENT': 0.0,
131
+ 'IS_TEST_MODE': True, # Set to False in production
132
+ }
133
+ }
121
134
  ```
122
135
 
123
136
  3. Create webhook handlers:
@@ -298,6 +311,10 @@ Detailed documentation is available in multiple languages:
298
311
 
299
312
  Contributions are welcome! Please feel free to submit a Pull Request.
300
313
 
314
+ 📖 **Documentation:** [pay-tech.uz](https://pay-tech.uz)
315
+ 🐛 **Issues:** [GitHub Issues](https://github.com/PayTechUz/paytechuz-py/issues)
316
+ 💬 **Support:** [Telegram](https://t.me/paytechuz)
317
+
301
318
  ## License
302
319
 
303
320
  This project is licensed under the MIT License - see the LICENSE file for details.
@@ -0,0 +1,10 @@
1
+ from sqlalchemy import create_engine
2
+ from sqlalchemy.orm import sessionmaker, declarative_base
3
+
4
+ SQLALCHEMY_DATABASE_URL = "sqlite:///payments.db"
5
+
6
+ engine = create_engine(SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False})
7
+
8
+ SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
9
+
10
+ Base = declarative_base()
@@ -0,0 +1,17 @@
1
+ from datetime import datetime, timezone
2
+ from sqlalchemy import Column, Integer, String, Float, DateTime
3
+ from app.database import Base
4
+ from paytechuz.integrations.fastapi.models import run_migrations
5
+
6
+ class Order(Base):
7
+ __tablename__ = "orders"
8
+
9
+ id = Column(Integer, primary_key=True, index=True)
10
+ product_name = Column(String, index=True)
11
+ amount = Column(Float)
12
+ status = Column(String, default="pending")
13
+ created_at = Column(DateTime, default=lambda: datetime.now(timezone.utc))
14
+
15
+ def init_db(engine):
16
+ run_migrations(engine) # Creates Payme/Click payment tables
17
+ Base.metadata.create_all(bind=engine)
@@ -0,0 +1,55 @@
1
+ from pydantic import BaseModel
2
+ from typing import Optional
3
+ from datetime import datetime
4
+
5
+ class OrderCreate(BaseModel):
6
+ """Order yaratish uchun request model"""
7
+ product_name: str
8
+ amount: float
9
+ description: Optional[str] = None
10
+ payment_method: str # "payme" yoki "click"
11
+ return_url: Optional[str] = "https://example.com/return"
12
+
13
+ class OrderResponse(BaseModel):
14
+ """Order ma'lumotlarini qaytarish uchun response model"""
15
+ id: int
16
+ product_name: str
17
+ amount: float
18
+ status: str
19
+ created_at: datetime
20
+ payment_method: str
21
+ payment_link: str
22
+
23
+ class Config:
24
+ from_attributes = True
25
+
26
+ class PaymentLinkRequest(BaseModel):
27
+ """To'lov linkini generatsiya qilish uchun request model"""
28
+ order_id: int
29
+ payment_method: str # "payme" yoki "click"
30
+ return_url: Optional[str] = "https://example.com/return"
31
+
32
+ class PaymentLinkResponse(BaseModel):
33
+ """To'lov linkini qaytarish uchun response model"""
34
+ order_id: int
35
+ payment_method: str
36
+ payment_link: str
37
+
38
+ class OrderUpdate(BaseModel):
39
+ """Order yangilash uchun request model"""
40
+ product_name: Optional[str] = None
41
+ amount: Optional[float] = None
42
+ status: Optional[str] = None
43
+ description: Optional[str] = None
44
+
45
+ class OrderListResponse(BaseModel):
46
+ """Orderlar ro'yxatini qaytarish uchun response model"""
47
+ orders: list[OrderResponse]
48
+ total: int
49
+ skip: int
50
+ limit: int
51
+
52
+ class ErrorResponse(BaseModel):
53
+ """Xatolik xabarini qaytarish uchun response model"""
54
+ detail: str
55
+ error_code: Optional[str] = None
@@ -0,0 +1,28 @@
1
+ from app.models import Order
2
+ from paytechuz.integrations.fastapi import PaymeWebhookHandler, ClickWebhookHandler
3
+
4
+ class CustomPaymeWebhookHandler(PaymeWebhookHandler):
5
+ def successfully_payment(self, params, transaction):
6
+ order = self.db.query(Order).filter(Order.id == transaction.account_id).first()
7
+ if order:
8
+ order.status = "paid"
9
+ self.db.commit()
10
+
11
+ def cancelled_payment(self, params, transaction):
12
+ order = self.db.query(Order).filter(Order.id == transaction.account_id).first()
13
+ if order:
14
+ order.status = "cancelled"
15
+ self.db.commit()
16
+
17
+ class CustomClickWebhookHandler(ClickWebhookHandler):
18
+ def successfully_payment(self, params, transaction):
19
+ order = self.db.query(Order).filter(Order.id == transaction.account_id).first()
20
+ if order:
21
+ order.status = "paid"
22
+ self.db.commit()
23
+
24
+ def cancelled_payment(self, params, transaction):
25
+ order = self.db.query(Order).filter(Order.id == transaction.account_id).first()
26
+ if order:
27
+ order.status = "cancelled"
28
+ self.db.commit()
@@ -0,0 +1,103 @@
1
+ from fastapi import FastAPI, Request, Depends, HTTPException
2
+ from sqlalchemy.orm import Session
3
+
4
+ from app.database import SessionLocal, engine
5
+ from app.models import init_db, Order
6
+ from app.webhook_handlers import CustomPaymeWebhookHandler, CustomClickWebhookHandler
7
+ from app.typing import (
8
+ OrderCreate,
9
+ OrderResponse
10
+ )
11
+
12
+ from paytechuz.gateways.payme import PaymeGateway
13
+ from paytechuz.gateways.click import ClickGateway
14
+
15
+ app = FastAPI()
16
+
17
+ init_db(engine)
18
+
19
+ payme = PaymeGateway(
20
+ payme_id="your_payme_id",
21
+ payme_key="your_payme_key",
22
+ is_test_mode=True # Set to False in production environment
23
+ )
24
+
25
+ click = ClickGateway(
26
+ service_id="your_service_id",
27
+ merchant_id="your_merchant_id",
28
+ merchant_user_id="your_merchant_user_id",
29
+ secret_key="your_secret_key",
30
+ is_test_mode=True # Set to False in production environment
31
+ )
32
+
33
+
34
+ def get_db():
35
+ db = SessionLocal()
36
+ try:
37
+ yield db
38
+ finally:
39
+ db.close()
40
+
41
+
42
+ @app.post("/orders/", response_model=OrderResponse)
43
+ async def create_order(order_data: OrderCreate, db: Session = Depends(get_db)):
44
+ """Create a new order with payment link"""
45
+ if order_data.payment_method.lower() not in ["payme", "click"]:
46
+ raise HTTPException(status_code=400, detail="Invalid payment method. Use 'payme' or 'click'")
47
+
48
+ db_order = Order(
49
+ product_name=order_data.product_name,
50
+ amount=order_data.amount,
51
+ status="pending"
52
+ )
53
+ db.add(db_order)
54
+ db.commit()
55
+ db.refresh(db_order)
56
+
57
+ if order_data.payment_method.lower() == "payme":
58
+ payment_link = payme.create_payment(
59
+ id=str(db_order.id),
60
+ amount=int(db_order.amount * 100), # Convert to smallest currency unit
61
+ return_url=order_data.return_url
62
+ )
63
+ else: # click
64
+ payment_link = click.create_payment(
65
+ id=str(db_order.id),
66
+ amount=int(db_order.amount * 100), # Convert to smallest currency unit
67
+ description=db_order.product_name,
68
+ return_url=order_data.return_url
69
+ )
70
+
71
+ return OrderResponse(
72
+ id=db_order.id,
73
+ product_name=db_order.product_name,
74
+ amount=db_order.amount,
75
+ status=db_order.status,
76
+ created_at=db_order.created_at,
77
+ payment_method=order_data.payment_method.lower(),
78
+ payment_link=payment_link
79
+ )
80
+
81
+
82
+ @app.post("/payments/payme/webhook")
83
+ async def payme_webhook(request: Request, db: Session = Depends(get_db)):
84
+ handler = CustomPaymeWebhookHandler(
85
+ db=db,
86
+ payme_id="your_payme_id",
87
+ payme_key="your_payme_key",
88
+ account_model=Order,
89
+ account_field='id',
90
+ amount_field='amount'
91
+ )
92
+ return await handler.handle_webhook(request)
93
+
94
+ @app.post("/payments/click/webhook")
95
+ async def click_webhook(request: Request, db: Session = Depends(get_db)):
96
+ handler = CustomClickWebhookHandler(
97
+ db=db,
98
+ service_id="your_service_id",
99
+ merchant_id="your_merchant_id",
100
+ secret_key="your_secret_key",
101
+ account_model=Order
102
+ )
103
+ return await handler.handle_webhook(request)
@@ -0,0 +1,2 @@
1
+ uvicorn main:app --reload --host 0.0.0.0 --port 8000
2
+
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "paytechuz"
7
- version = "0.2.10"
7
+ version = "0.2.13"
8
8
  description = "Unified Python package for Uzbekistan payment gateways"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.7"
@@ -8,7 +8,7 @@ long_description = (here / "README.md").read_text(encoding="utf-8")
8
8
 
9
9
  setup(
10
10
  name='paytechuz',
11
- version='0.2.10',
11
+ version='0.2.13',
12
12
  license='MIT',
13
13
  author="Muhammadali Akbarov",
14
14
  author_email='muhammadali17abc@gmail.com',
@@ -357,7 +357,7 @@ class PaymeWebhookHandler:
357
357
  # Check for existing transactions in non-final states
358
358
  existing_transactions = self.db.query(PaymentTransaction).filter(
359
359
  PaymentTransaction.gateway == PaymentTransaction.PAYME,
360
- PaymentTransaction.account_id == account.id
360
+ PaymentTransaction.account_id == str(account.id)
361
361
  ).filter(
362
362
  PaymentTransaction.transaction_id != transaction_id
363
363
  ).all()
File without changes
@@ -38,30 +38,37 @@ class PaymeWebhook(View):
38
38
  def __init__(self, **kwargs):
39
39
  super().__init__(**kwargs)
40
40
 
41
- # Try to get the account model from settings
42
- # Get the account model from settings
43
- account_model_path = getattr(
44
- settings, 'PAYME_ACCOUNT_MODEL', 'django.contrib.auth.models.User'
41
+ paytechuz_settings = getattr(settings, 'PAYTECHUZ', {})
42
+ payme_settings = paytechuz_settings.get('PAYME', {})
43
+
44
+ self.payme_id = payme_settings.get('PAYME_ID') or getattr(settings, 'PAYME_ID', '')
45
+ self.payme_key = payme_settings.get('PAYME_KEY') or getattr(settings, 'PAYME_KEY', '')
46
+
47
+ account_model_path = (
48
+ payme_settings.get('ACCOUNT_MODEL') or
49
+ getattr(settings, 'PAYME_ACCOUNT_MODEL', 'django.contrib.auth.models.User')
45
50
  )
46
51
  try:
47
52
  self.account_model = import_string(account_model_path)
48
53
  except ImportError:
49
- # If the model is not found, log an error and raise an exception
50
54
  logger.error(
51
- "Could not import %s. Check PAYME_ACCOUNT_MODEL setting.",
55
+ "Could not import %s. Check PAYTECHUZ.PAYME.ACCOUNT_MODEL setting.",
52
56
  account_model_path
53
57
  )
54
- raise ImportError(
55
- f"Import error: {account_model_path}"
56
- ) from None
58
+ raise ImportError(f"Import error: {account_model_path}") from None
57
59
 
58
- self.account_field = getattr(settings, 'PAYME_ACCOUNT_FIELD', 'id')
59
- self.amount_field = getattr(settings, 'PAYME_AMOUNT_FIELD', 'amount')
60
- self.one_time_payment = getattr(
61
- settings, 'PAYME_ONE_TIME_PAYMENT', True
60
+ self.account_field = (
61
+ payme_settings.get('ACCOUNT_FIELD') or
62
+ getattr(settings, 'PAYME_ACCOUNT_FIELD', 'id')
63
+ )
64
+ self.amount_field = (
65
+ payme_settings.get('AMOUNT_FIELD') or
66
+ getattr(settings, 'PAYME_AMOUNT_FIELD', 'amount')
67
+ )
68
+ self.one_time_payment = (
69
+ payme_settings.get('ONE_TIME_PAYMENT') or
70
+ getattr(settings, 'PAYME_ONE_TIME_PAYMENT', True)
62
71
  )
63
- self.payme_id = getattr(settings, 'PAYME_ID', '')
64
- self.payme_key = getattr(settings, 'PAYME_KEY', '')
65
72
 
66
73
  def post(self, request, **_):
67
74
  """
@@ -580,27 +587,33 @@ class ClickWebhook(View):
580
587
  def __init__(self, **kwargs):
581
588
  super().__init__(**kwargs)
582
589
 
583
- # Try to get the account model from settings
584
- # Get the account model from settings
585
- account_model_path = getattr(
586
- settings, 'CLICK_ACCOUNT_MODEL', 'django.contrib.auth.models.User'
590
+ paytechuz_settings = getattr(settings, 'PAYTECHUZ', {})
591
+ click_settings = paytechuz_settings.get('CLICK', {})
592
+
593
+ account_model_path = (
594
+ click_settings.get('ACCOUNT_MODEL') or
595
+ getattr(settings, 'CLICK_ACCOUNT_MODEL')
587
596
  )
588
597
  try:
589
598
  self.account_model = import_string(account_model_path)
590
599
  except ImportError:
591
- # If the model is not found, log an error and raise an exception
592
600
  logger.error(
593
- "Could not import %s. Check CLICK_ACCOUNT_MODEL setting.",
601
+ "Could not import %s. Check PAYTECHUZ.CLICK.ACCOUNT_MODEL setting.",
594
602
  account_model_path
595
603
  )
596
- raise ImportError(
597
- f"Import error: {account_model_path}"
598
- ) from None
604
+ raise ImportError(f"Import error: {account_model_path}") from None
599
605
 
600
- self.service_id = getattr(settings, 'CLICK_SERVICE_ID', '')
601
- self.secret_key = getattr(settings, 'CLICK_SECRET_KEY', '')
602
- self.commission_percent = getattr(
603
- settings, 'CLICK_COMMISSION_PERCENT', 0.0
606
+ self.service_id = (
607
+ click_settings.get('SERVICE_ID') or
608
+ getattr(settings, 'CLICK_SERVICE_ID', '')
609
+ )
610
+ self.secret_key = (
611
+ click_settings.get('SECRET_KEY') or
612
+ getattr(settings, 'CLICK_SECRET_KEY', '')
613
+ )
614
+ self.commission_percent = (
615
+ click_settings.get('COMMISSION_PERCENT') or
616
+ getattr(settings, 'CLICK_COMMISSION_PERCENT', 0.0)
604
617
  )
605
618
 
606
619
  def post(self, request, **_):
@@ -356,7 +356,7 @@ class PaymeWebhookHandler:
356
356
  # Check for existing transactions in non-final states
357
357
  existing_transactions = self.db.query(PaymentTransaction).filter(
358
358
  PaymentTransaction.gateway == PaymentTransaction.PAYME,
359
- PaymentTransaction.account_id == account.id
359
+ PaymentTransaction.account_id == str(account.id)
360
360
  ).filter(
361
361
  PaymentTransaction.transaction_id != transaction_id
362
362
  ).all()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: paytechuz
3
- Version: 0.2.10
3
+ Version: 0.2.13
4
4
  Summary: Unified Python package for Uzbekistan payment gateways
5
5
  Home-page: https://github.com/Muhammadali-Akbarov/paytechuz
6
6
  Author: Muhammadali Akbarov
@@ -17,10 +17,13 @@ Dynamic: requires-python
17
17
 
18
18
  [![PyPI version](https://badge.fury.io/py/paytechuz.svg)](https://badge.fury.io/py/paytechuz)
19
19
  [![Python Versions](https://img.shields.io/pypi/pyversions/paytechuz.svg)](https://pypi.org/project/paytechuz/)
20
+ [![Documentation](https://img.shields.io/badge/docs-pay--tech.uz-blue.svg)](https://pay-tech.uz)
20
21
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
21
22
 
22
23
  PayTechUZ is a unified payment library for integrating with popular payment systems in Uzbekistan. It provides a simple and consistent interface for working with Payme and Click payment gateways.
23
24
 
25
+ 📖 **[Complete Documentation](https://pay-tech.uz)** | 🚀 **[Quick Start Guide](https://pay-tech.uz/quickstart)**
26
+
24
27
  ## Features
25
28
 
26
29
  - 🔄 **API**: Consistent interface for multiple payment providers
@@ -49,6 +52,8 @@ pip install paytechuz[fastapi]
49
52
 
50
53
  ## Quick Start
51
54
 
55
+ > 💡 **Need help?** Check out our [complete documentation](https://pay-tech.uz) for detailed guides and examples.
56
+
52
57
  ### Generate Payment Links
53
58
 
54
59
  ```python
@@ -121,18 +126,26 @@ INSTALLED_APPS = [
121
126
  'paytechuz.integrations.django',
122
127
  ]
123
128
 
124
- PAYME_ID = 'your_payme_merchant_id'
125
- PAYME_KEY = 'your_payme_merchant_key'
126
- PAYME_ACCOUNT_MODEL = 'your_app.models.Order' # For example: 'orders.models.Order'
127
- PAYME_ACCOUNT_FIELD = 'id'
128
- PAYME_AMOUNT_FIELD = 'amount' # Field for storing payment amount
129
- PAYME_ONE_TIME_PAYMENT = True # Allow only one payment per account
130
-
131
- CLICK_SERVICE_ID = 'your_click_service_id'
132
- CLICK_MERCHANT_ID = 'your_click_merchant_id'
133
- CLICK_SECRET_KEY = 'your_click_secret_key'
134
- CLICK_ACCOUNT_MODEL = 'your_app.models.Order'
135
- CLICK_COMMISSION_PERCENT = 0.0
129
+ PAYTECHUZ = {
130
+ 'PAYME': {
131
+ 'PAYME_ID': 'your_payme_id',
132
+ 'PAYME_KEY': 'your_payme_key',
133
+ 'ACCOUNT_MODEL': 'your_app.models.Order', # For example: 'orders.models.Order'
134
+ 'ACCOUNT_FIELD': 'id',
135
+ 'AMOUNT_FIELD': 'amount',
136
+ 'ONE_TIME_PAYMENT': True,
137
+ 'IS_TEST_MODE': True, # Set to False in production
138
+ },
139
+ 'CLICK': {
140
+ 'SERVICE_ID': 'your_service_id',
141
+ 'MERCHANT_ID': 'your_merchant_id',
142
+ 'MERCHANT_USER_ID': 'your_merchant_user_id',
143
+ 'SECRET_KEY': 'your_secret_key',
144
+ 'ACCOUNT_MODEL': 'your_app.models.Order',
145
+ 'COMMISSION_PERCENT': 0.0,
146
+ 'IS_TEST_MODE': True, # Set to False in production
147
+ }
148
+ }
136
149
  ```
137
150
 
138
151
  3. Create webhook handlers:
@@ -313,6 +326,10 @@ Detailed documentation is available in multiple languages:
313
326
 
314
327
  Contributions are welcome! Please feel free to submit a Pull Request.
315
328
 
329
+ 📖 **Documentation:** [pay-tech.uz](https://pay-tech.uz)
330
+ 🐛 **Issues:** [GitHub Issues](https://github.com/PayTechUz/paytechuz-py/issues)
331
+ 💬 **Support:** [Telegram](https://t.me/paytechuz)
332
+
316
333
  ## License
317
334
 
318
335
  This project is licensed under the MIT License - see the LICENSE file for details.
@@ -2,6 +2,15 @@ MANIFEST.in
2
2
  README.md
3
3
  pyproject.toml
4
4
  setup.py
5
+ examples/paytechuz_fastapi/__init__.py
6
+ examples/paytechuz_fastapi/main.py
7
+ examples/paytechuz_fastapi/payments.db
8
+ examples/paytechuz_fastapi/run.sh
9
+ examples/paytechuz_fastapi/app/__init__.py
10
+ examples/paytechuz_fastapi/app/database.py
11
+ examples/paytechuz_fastapi/app/models.py
12
+ examples/paytechuz_fastapi/app/typing.py
13
+ examples/paytechuz_fastapi/app/webhook_handlers.py
5
14
  src/__init__.py
6
15
  src/core/__init__.py
7
16
  src/core/base.py
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes