paytechuz 0.1.3__py3-none-any.whl → 0.1.6__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.

paytechuz/__init__.py CHANGED
@@ -1,35 +1,12 @@
1
- """PayTechUZ - Unified payment library for Uzbekistan payment systems.
1
+ """
2
+ PayTechUZ - Unified payment library for Uzbekistan payment systems.
2
3
 
3
4
  This library provides a unified interface for working with Payme and Click
4
5
  payment systems in Uzbekistan. It supports Django, Flask, and FastAPI.
5
6
  """
6
7
  from typing import Any
7
8
 
8
- __version__ = '0.1.1'
9
-
10
-
11
-
12
- # Define dummy classes to avoid import errors
13
- class PaymeGateway:
14
- """Dummy PaymeGateway class to avoid import errors."""
15
- def __init__(self, **kwargs):
16
- pass
17
-
18
-
19
- class ClickGateway:
20
- """Dummy ClickGateway class to avoid import errors."""
21
- def __init__(self, **kwargs):
22
- pass
23
-
24
-
25
- class PaymentGateway:
26
- """Dummy PaymentGateway enum to avoid import errors."""
27
- class PAYME:
28
- value = 'payme'
29
-
30
- class CLICK:
31
- value = 'click'
32
-
9
+ __version__ = '0.2.0-beta'
33
10
 
34
11
  # Import framework integrations - these imports are used to check availability
35
12
  # of frameworks, not for direct usage
@@ -52,6 +29,44 @@ except ImportError:
52
29
  HAS_FLASK = False
53
30
 
54
31
 
32
+ # Import the main classes for easier access
33
+ try:
34
+ from paytechuz.gateways.payme.client import PaymeGateway # noqa: E402
35
+ from paytechuz.gateways.click.client import ClickGateway # noqa: E402
36
+ from paytechuz.core.constants import PaymentGateway # noqa: E402
37
+ except ImportError:
38
+ # Fallback for development mode
39
+ try:
40
+ from .gateways.payme.client import PaymeGateway # noqa: E402
41
+ from .gateways.click.client import ClickGateway # noqa: E402
42
+ from .core.constants import PaymentGateway # noqa: E402
43
+ except ImportError:
44
+ # Dummy classes to avoid import errors
45
+ class PaymeGateway:
46
+ """Dummy PaymeGateway class to avoid import errors."""
47
+ def __init__(self, **kwargs):
48
+ pass
49
+
50
+ def create_payment(self, **kwargs):
51
+ return "https://test.paycom.uz/dummy-payment-url"
52
+
53
+ class ClickGateway:
54
+ """Dummy ClickGateway class to avoid import errors."""
55
+ def __init__(self, **kwargs):
56
+ pass
57
+
58
+ def create_payment(self, **kwargs):
59
+ return {"payment_url": "https://my.click.uz/dummy-payment-url"}
60
+
61
+ class PaymentGateway:
62
+ """Dummy PaymentGateway enum to avoid import errors."""
63
+ class PAYME:
64
+ value = 'payme'
65
+
66
+ class CLICK:
67
+ value = 'click'
68
+
69
+
55
70
  def create_gateway(gateway_type: str, **kwargs) -> Any:
56
71
  """
57
72
  Create a payment gateway instance.
@@ -67,10 +82,9 @@ def create_gateway(gateway_type: str, **kwargs) -> Any:
67
82
  ValueError: If the gateway type is not supported
68
83
  ImportError: If the required gateway module is not available
69
84
  """
70
- # Just use the dummy classes for now
71
- if gateway_type.lower() == 'payme':
85
+ if gateway_type.lower() == PaymentGateway.PAYME.value:
72
86
  return PaymeGateway(**kwargs)
73
- if gateway_type.lower() == 'click':
87
+ if gateway_type.lower() == PaymentGateway.CLICK.value:
74
88
  return ClickGateway(**kwargs)
75
89
 
76
90
  raise ValueError(f"Unsupported gateway type: {gateway_type}")
paytechuz/core/base.py CHANGED
@@ -4,6 +4,7 @@ Base classes for payment gateways.
4
4
  from abc import ABC, abstractmethod
5
5
  from typing import Dict, Any, Optional, Union
6
6
 
7
+
7
8
  class BasePaymentGateway(ABC):
8
9
  """
9
10
  Base class for all payment gateways.
@@ -23,7 +24,12 @@ class BasePaymentGateway(ABC):
23
24
  self.is_test_mode = is_test_mode
24
25
 
25
26
  @abstractmethod
26
- def create_payment(self, amount: Union[int, float, str], account_id: Union[int, str], **kwargs) -> Dict[str, Any]:
27
+ def create_payment(
28
+ self,
29
+ amount: Union[int, float, str],
30
+ account_id: Union[int, str],
31
+ **kwargs
32
+ ) -> Dict[str, Any]:
27
33
  """
28
34
  Create a payment.
29
35
 
@@ -51,7 +57,11 @@ class BasePaymentGateway(ABC):
51
57
  raise NotImplementedError
52
58
 
53
59
  @abstractmethod
54
- def cancel_payment(self, transaction_id: str, reason: Optional[str] = None) -> Dict[str, Any]:
60
+ def cancel_payment(
61
+ self,
62
+ transaction_id: str,
63
+ reason: Optional[str] = None
64
+ ) -> Dict[str, Any]:
55
65
  """
56
66
  Cancel payment.
57
67
 
@@ -65,7 +75,6 @@ class BasePaymentGateway(ABC):
65
75
  raise NotImplementedError
66
76
 
67
77
 
68
-
69
78
  class BaseWebhookHandler(ABC):
70
79
  """
71
80
  Base class for payment gateway webhook handlers.
paytechuz/core/http.py CHANGED
@@ -8,7 +8,7 @@ from typing import Dict, Any, Optional, Union, List
8
8
  import requests
9
9
  from requests.exceptions import RequestException, Timeout, ConnectionError
10
10
 
11
- from paytechuz.core.exceptions import (
11
+ from .exceptions import (
12
12
  ExternalServiceError,
13
13
  TimeoutError as PaymentTimeoutError,
14
14
  InternalServiceError
paytechuz/core/utils.py CHANGED
@@ -157,7 +157,7 @@ def handle_exceptions(func):
157
157
  Returns:
158
158
  Decorated function
159
159
  """
160
- from paytechuz.core.exceptions import (
160
+ from .exceptions import (
161
161
  InternalServiceError,
162
162
  exception_whitelist
163
163
  )
@@ -0,0 +1,2 @@
1
+ """Click payment gateway implementation."""
2
+ from .client import ClickGateway # noqa: F401
@@ -4,11 +4,11 @@ Click payment gateway client.
4
4
  import logging
5
5
  from typing import Dict, Any, Optional, Union
6
6
 
7
- from paytechuz.core.base import BasePaymentGateway
8
- from paytechuz.core.http import HttpClient
9
- from paytechuz.core.constants import ClickNetworks
10
- from paytechuz.core.utils import format_amount, handle_exceptions
11
- from paytechuz.gateways.click.merchant import ClickMerchantApi
7
+ from ....core.base import BasePaymentGateway
8
+ from ....core.http import HttpClient
9
+ from ....core.constants import ClickNetworks
10
+ from ....core.utils import format_amount, handle_exceptions
11
+ from .merchant import ClickMerchantApi
12
12
 
13
13
  logger = logging.getLogger(__name__)
14
14
 
@@ -5,9 +5,9 @@ import hashlib
5
5
  import logging
6
6
  from typing import Dict, Any, Optional, Union
7
7
 
8
- from paytechuz.core.http import HttpClient
9
- from paytechuz.core.constants import ClickEndpoints
10
- from paytechuz.core.utils import handle_exceptions, generate_timestamp
8
+ from ....core.http import HttpClient
9
+ from ....core.constants import ClickEndpoints
10
+ from ....core.utils import handle_exceptions, generate_timestamp
11
11
 
12
12
  logger = logging.getLogger(__name__)
13
13
 
@@ -0,0 +1,2 @@
1
+ """Payme payment gateway implementation."""
2
+ from .client import PaymeGateway # noqa: F401
@@ -4,9 +4,9 @@ Payme cards operations.
4
4
  import logging
5
5
  from typing import Dict, Any
6
6
 
7
- from paytechuz.core.http import HttpClient
8
- from paytechuz.core.constants import PaymeEndpoints
9
- from paytechuz.core.utils import handle_exceptions
7
+ from ....core.http import HttpClient
8
+ from ....core.constants import PaymeEndpoints
9
+ from ....core.utils import handle_exceptions
10
10
 
11
11
  logger = logging.getLogger(__name__)
12
12
 
@@ -3,16 +3,18 @@ Payme payment gateway client.
3
3
  """
4
4
  import logging
5
5
  from typing import Dict, Any, Optional, Union
6
+ import base64
6
7
 
7
- from paytechuz.core.base import BasePaymentGateway
8
- from paytechuz.core.http import HttpClient
9
- from paytechuz.core.constants import PaymeNetworks
10
- from paytechuz.core.utils import format_amount, handle_exceptions
11
- from paytechuz.gateways.payme.cards import PaymeCards
12
- from paytechuz.gateways.payme.receipts import PaymeReceipts
8
+ from ....core.base import BasePaymentGateway
9
+ from ....core.http import HttpClient
10
+ from ....core.constants import PaymeNetworks
11
+ from ....core.utils import format_amount, handle_exceptions
12
+ from .cards import PaymeCards
13
+ from .receipts import PaymeReceipts
13
14
 
14
15
  logger = logging.getLogger(__name__)
15
16
 
17
+
16
18
  class PaymeGateway(BasePaymentGateway):
17
19
  """
18
20
  Payme payment gateway implementation.
@@ -56,116 +58,138 @@ class PaymeGateway(BasePaymentGateway):
56
58
  payme_key=payme_key
57
59
  )
58
60
 
61
+ def generate_pay_link(
62
+ self,
63
+ id: Union[int, str],
64
+ amount: Union[int, float, str],
65
+ return_url: str,
66
+ account_field_name: str = "order_id"
67
+ ) -> str:
68
+ """
69
+ Generate a payment link for a specific order.
70
+
71
+ Parameters
72
+ ----------
73
+ id : Union[int, str]
74
+ Unique identifier for the account/order.
75
+ amount : Union[int, float, str]
76
+ Payment amount in som.
77
+ return_url : str
78
+ URL to redirect after payment completion.
79
+ account_field_name : str, optional
80
+ Field name for account identifier (default: "order_id").
81
+
82
+ Returns
83
+ -------
84
+ str
85
+ Payme checkout URL with encoded parameters.
86
+
87
+ References
88
+ ----------
89
+ https://developer.help.paycom.uz/initsializatsiya-platezhey/
90
+ """
91
+ # Convert amount to tiyin (1 som = 100 tiyin)
92
+ amount_tiyin = int(float(amount) * 100)
93
+
94
+ # Build parameters
95
+ params = (
96
+ f'm={self.payme_id};'
97
+ f'ac.{account_field_name}={id};'
98
+ f'a={amount_tiyin};'
99
+ f'c={return_url}'
100
+ )
101
+ encoded_params = base64.b64encode(params.encode("utf-8")).decode("utf-8")
102
+
103
+ # Return URL based on environment
104
+ base_url = "https://test.paycom.uz" if self.is_test_mode else "https://checkout.paycom.uz"
105
+ return f"{base_url}/{encoded_params}"
106
+
107
+ async def generate_pay_link_async(
108
+ self,
109
+ id: Union[int, str],
110
+ amount: Union[int, float, str],
111
+ return_url: str,
112
+ account_field_name: str = "order_id"
113
+ ) -> str:
114
+ """
115
+ Async version of generate_pay_link.
116
+
117
+ Parameters
118
+ ----------
119
+ id : Union[int, str]
120
+ Unique identifier for the account/order.
121
+ amount : Union[int, float, str]
122
+ Payment amount in som.
123
+ return_url : str
124
+ URL to redirect after payment completion.
125
+ account_field_name : str, optional
126
+ Field name for account identifier (default: "order_id").
127
+
128
+ Returns
129
+ -------
130
+ str
131
+ Payme checkout URL with encoded parameters.
132
+ """
133
+ return self.generate_pay_link(
134
+ id=id,
135
+ amount=amount,
136
+ return_url=return_url,
137
+ account_field_name=account_field_name
138
+ )
139
+
59
140
  @handle_exceptions
60
141
  def create_payment(
61
142
  self,
143
+ id: Union[int, str],
62
144
  amount: Union[int, float, str],
63
- account_id: Union[int, str],
64
- **kwargs
65
- ) -> Dict[str, Any]:
145
+ return_url: str = "",
146
+ account_field_name: str = "order_id"
147
+ ) -> str:
66
148
  """
67
- Create a payment using Payme receipts.
149
+ Create a payment using Payme.
68
150
 
69
151
  Args:
70
- amount: The payment amount in som
71
- account_id: The account ID or order ID
72
- **kwargs: Additional parameters for the payment
73
- - description: Payment description
74
- - detail: Payment details
75
- - callback_url: URL to redirect after payment
76
- - return_url: URL to return after payment
77
- - phone: Customer phone number
78
- - email: Customer email
79
- - language: Language code (uz, ru, en)
80
- - expire_minutes: Payment expiration time in minutes
152
+ amount: Payment amount in som
153
+ account_id: Account or order ID
154
+ return_url: Return URL after payment (default: "")
155
+ account_field_name: Field name for account ID (default: "order_id")
81
156
 
82
157
  Returns:
83
- Dict containing payment details including transaction ID and payment URL
158
+ str: Payme payment URL
159
+ """
160
+ return self.generate_pay_link(
161
+ id=id,
162
+ amount=amount,
163
+ return_url=return_url,
164
+ account_field_name=account_field_name
165
+ )
166
+
167
+ @handle_exceptions
168
+ async def create_payment_async(
169
+ self,
170
+ id: Union[int, str],
171
+ amount: Union[int, float, str],
172
+ return_url: str = "",
173
+ account_field_name: str = "order_id"
174
+ ) -> str:
84
175
  """
85
- # Format amount to tiyin (1 som = 100 tiyin)
86
- amount_tiyin = format_amount(amount)
87
-
88
- # Extract additional parameters
89
- description = kwargs.get('description', f'Payment for account {account_id}')
90
- detail = kwargs.get('detail', {})
91
- callback_url = kwargs.get('callback_url')
92
- return_url = kwargs.get('return_url')
93
- phone = kwargs.get('phone')
94
- email = kwargs.get('email')
95
- language = kwargs.get('language', 'uz')
96
- expire_minutes = kwargs.get('expire_minutes', 60) # Default 1 hour
97
-
98
- # Check if we have a merchant key
99
- if self.payme_key:
100
- # Create receipt using the API
101
- receipt_data = self.receipts.create(
102
- amount=amount_tiyin,
103
- account={"account_id": str(account_id)},
104
- description=description,
105
- detail=detail,
106
- callback_url=callback_url,
107
- return_url=return_url,
108
- phone=phone,
109
- email=email,
110
- language=language,
111
- expire_minutes=expire_minutes
112
- )
113
-
114
- # Extract receipt ID and payment URL
115
- receipt_id = receipt_data.get('receipt', {}).get('_id')
116
- payment_url = receipt_data.get('receipt', {}).get('pay_url')
117
-
118
- return {
119
- 'transaction_id': receipt_id,
120
- 'payment_url': payment_url,
121
- 'amount': amount,
122
- 'account_id': account_id,
123
- 'status': 'created',
124
- 'raw_response': receipt_data
125
- }
126
- else:
127
- # Generate a payment URL using payme-pkg style
128
- # This is a fallback method that doesn't require authentication
129
- import base64
130
- from paytechuz.core.utils import generate_id
131
-
132
- # Generate a unique transaction ID
133
- transaction_id = generate_id("payme")
134
-
135
- # Format amount to the smallest currency unit (tiyin)
136
- # amount_tiyin is already in tiyin format
137
-
138
- # Build the payment parameters string
139
- # Format: m=merchant_id;ac.field=value;a=amount;c=callback_url
140
- params_str = f"m={self.payme_id};ac.id={account_id};a={amount_tiyin}"
141
-
142
- # Add callback URL if provided (this is used for return URL in payme-pkg)
143
- if return_url:
144
- params_str += f";c={return_url}"
145
-
146
- # Encode the parameters string to base64
147
- encoded_params = base64.b64encode(params_str.encode("utf-8")).decode("utf-8")
148
-
149
- # Build the payment URL
150
- if self.is_test_mode:
151
- payment_url = f"https://test.paycom.uz/{encoded_params}"
152
- else:
153
- payment_url = f"https://checkout.paycom.uz/{encoded_params}"
154
-
155
- # Print the parameters for debugging
156
- print("Payme payment parameters:")
157
- print(f"Parameters string: {params_str}")
158
- print(f"Encoded parameters: {encoded_params}")
159
- print(f"Payment URL: {payment_url}")
160
-
161
- return {
162
- 'transaction_id': transaction_id,
163
- 'payment_url': payment_url,
164
- 'amount': amount,
165
- 'account_id': account_id,
166
- 'status': 'created',
167
- 'raw_response': {}
168
- }
176
+ Async version of create_payment.
177
+
178
+ Args:
179
+ amount: Payment amount in som
180
+ account_id: Account or order ID
181
+ return_url: Return URL after payment (default: "")
182
+ account_field_name: Field name for account ID (default: "order_id")
183
+
184
+ Returns:
185
+ str: Payme payment URL
186
+ """
187
+ return await self.generate_pay_link_async(
188
+ id=id,
189
+ amount=amount,
190
+ return_url=return_url,
191
+ account_field_name=account_field_name
192
+ )
169
193
 
170
194
  @handle_exceptions
171
195
  def check_payment(self, transaction_id: str) -> Dict[str, Any]:
@@ -5,9 +5,9 @@ Payme receipts operations.
5
5
  import logging
6
6
  from typing import Dict, Any, Optional
7
7
 
8
- from paytechuz.core.http import HttpClient
9
- from paytechuz.core.constants import PaymeEndpoints
10
- from paytechuz.core.utils import handle_exceptions, generate_basic_auth
8
+ from ....core.http import HttpClient
9
+ from ....core.constants import PaymeEndpoints
10
+ from ....core.utils import handle_exceptions, generate_basic_auth
11
11
 
12
12
  logger = logging.getLogger(__name__)
13
13
 
@@ -0,0 +1,157 @@
1
+ Metadata-Version: 2.4
2
+ Name: paytechuz
3
+ Version: 0.1.6
4
+ Summary: Unified Python package for Uzbekistan payment gateways
5
+ Home-page: https://github.com/Muhammadali-Akbarov/paytechuz
6
+ Author: Muhammadali Akbarov
7
+ Author-email: muhammadali17abc@gmail.com
8
+ License: MIT
9
+ Requires-Python: >=3.6
10
+ Description-Content-Type: text/markdown
11
+ Dynamic: author
12
+ Dynamic: author-email
13
+ Dynamic: home-page
14
+ Dynamic: requires-python
15
+
16
+ # PayTechUZ
17
+
18
+ [![PyPI version](https://badge.fury.io/py/paytechuz.svg)](https://badge.fury.io/py/paytechuz)
19
+ [![Python Versions](https://img.shields.io/pypi/pyversions/paytechuz.svg)](https://pypi.org/project/paytechuz/)
20
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
21
+ ## Installation
22
+
23
+ ### Basic Installation
24
+
25
+ ```bash
26
+ pip install paytechuz
27
+ ```
28
+
29
+ ### Framework-Specific Installation
30
+
31
+ ```bash
32
+ # For Django
33
+ pip install paytechuz[django]
34
+
35
+ # For FastAPI
36
+ pip install paytechuz[fastapi]
37
+ ```
38
+
39
+ ## Quick Start
40
+
41
+ ### Generate Payment Links
42
+
43
+ ```python
44
+ from paytechuz import create_gateway, PaymentGateway
45
+
46
+ # Initialize gateways
47
+ payme = create_gateway(PaymentGateway.PAYME.value,
48
+ payme_id="your_payme_id",
49
+ payme_key="your_payme_key",
50
+ is_test_mode=True
51
+ )
52
+
53
+ click = create_gateway(PaymentGateway.CLICK.value,
54
+ service_id="your_service_id",
55
+ merchant_id="your_merchant_id",
56
+ merchant_user_id="your_merchant_user_id",
57
+ secret_key="your_secret_key",
58
+ is_test_mode=True
59
+ )
60
+
61
+ # Generate payment links
62
+ payme_link = payme.create_payment(
63
+ id="order_123",
64
+ amount=150000, # amount in UZS
65
+ return_url="https://example.com/return"
66
+ )
67
+
68
+ click_link = click.create_payment(
69
+ amount=150000, # amount in UZS
70
+ account_id="order_123",
71
+ description="Test payment",
72
+ return_url="https://example.com/return"
73
+ )
74
+ ```
75
+
76
+ ### Django Integration
77
+
78
+ 1. Add to `INSTALLED_APPS`:
79
+
80
+ ```python
81
+ # settings.py
82
+ INSTALLED_APPS = [
83
+ # ...
84
+ 'paytechuz.integrations.django',
85
+ ]
86
+
87
+ PAYME_ID = 'your_payme_merchant_id'
88
+ PAYME_KEY = 'your_payme_merchant_key'
89
+ PAYME_ACCOUNT_MODEL = 'your_app.models.YourModel' # For example: 'orders.models.Order'
90
+ PAYME_ACCOUNT_FIELD = 'id'
91
+ PAYME_AMOUNT_FIELD = 'amount' # Field for storing payment amount
92
+ PAYME_ONE_TIME_PAYMENT = True # Allow only one payment per account
93
+
94
+ CLICK_SERVICE_ID = 'your_click_service_id'
95
+ CLICK_MERCHANT_ID = 'your_click_merchant_id'
96
+ CLICK_SECRET_KEY = 'your_click_secret_key'
97
+ CLICK_ACCOUNT_MODEL = 'your_app.models.YourModel'
98
+ CLICK_COMMISSION_PERCENT = 0.0
99
+ ```
100
+
101
+ 2. Create webhook handlers:
102
+
103
+ ```python
104
+ # views.py
105
+ from paytechuz.integrations.django.views import PaymeWebhookView
106
+ from .models import Order
107
+
108
+ class PaymeWebhookView(PaymeWebhookView):
109
+ def successfully_payment(self, params, transaction):
110
+ order = Order.objects.get(id=transaction.account_id)
111
+ order.status = 'paid'
112
+ order.save()
113
+
114
+ def cancelled_payment(self, params, transaction):
115
+ order = Order.objects.get(id=transaction.account_id)
116
+ order.status = 'cancelled'
117
+ order.save()
118
+ ```
119
+
120
+ ### FastAPI Integration
121
+
122
+ 1. Create webhook handler:
123
+
124
+ ```python
125
+ from fastapi import FastAPI, Request
126
+ from paytechuz.integrations.fastapi import PaymeWebhookHandler
127
+
128
+ app = FastAPI()
129
+
130
+ class CustomPaymeWebhookHandler(PaymeWebhookHandler):
131
+ def successfully_payment(self, params, transaction):
132
+ # Handle successful payment
133
+ order = self.db.query(Order).filter(Order.id == transaction.account_id).first()
134
+ order.status = "paid"
135
+ self.db.commit()
136
+
137
+ def cancelled_payment(self, params, transaction):
138
+ # Handle cancelled payment
139
+ order = self.db.query(Order).filter(Order.id == transaction.account_id).first()
140
+ order.status = "cancelled"
141
+ self.db.commit()
142
+
143
+ @app.post("/payments/payme/webhook")
144
+ async def payme_webhook(request: Request):
145
+ handler = CustomPaymeWebhookHandler(
146
+ payme_id="your_merchant_id",
147
+ payme_key="your_merchant_key"
148
+ )
149
+ return await handler.handle_webhook(request)
150
+ ```
151
+
152
+ ## Documentation
153
+
154
+ Detailed documentation is available in multiple languages:
155
+
156
+ - 📖 [English Documentation](docs/en/index.md)
157
+ - 📖 [O'zbek tilidagi hujjatlar](docs/uz/index.md)
@@ -1,20 +1,20 @@
1
- paytechuz/__init__.py,sha256=qLjm35Dc7UqnetOcbXgc_vP5FnzAq810h7T1YBhjeiQ,1937
1
+ paytechuz/__init__.py,sha256=IpHrtevEvKObpWfZjT286sZSEYFJyzSYfiZAiIm0CYE,2856
2
2
  paytechuz/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- paytechuz/core/base.py,sha256=bHmRMYZ97Kj76a4kL7UMRcecnZF-rKnBYZddQvRtRmQ,2497
3
+ paytechuz/core/base.py,sha256=pW_0QrlyX0F8XVToeeDEI78ygAF2IgvvvyUGYMHH9bs,2565
4
4
  paytechuz/core/constants.py,sha256=P2zeZ_cfZIttdC1vqkpIngkfRFh6loWzJYEgzQb5cKA,1660
5
5
  paytechuz/core/exceptions.py,sha256=XMJkqiponTkvhjoh3S2iFNuU3UbBdFW4130kd0hpudg,5489
6
- paytechuz/core/http.py,sha256=qmLR6ujxmIPjwoTS4vvKRIvDnNcpl84sS1HmVB890b0,7686
7
- paytechuz/core/utils.py,sha256=ETHMzwu7_dirc-QfBUjpSTQmyS6_vBiNq97Dq9CNZto,4718
6
+ paytechuz/core/http.py,sha256=1PFv_Fo62GtfyYKUK2nsT4AaeQNuMgZlFUFL1q9p2MI,7672
7
+ paytechuz/core/utils.py,sha256=EbNtDweR1ABOtCu4D6cYlolM0t_fbiE3gNoc_qfcKKA,4704
8
8
  paytechuz/core/payme/errors.py,sha256=CZE62MbYDMsRfNIX23Syt6of_tPMMGLnXhYMii4hw3A,542
9
9
  paytechuz/gateways/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
- paytechuz/gateways/click/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
- paytechuz/gateways/click/client.py,sha256=XTri3iogq4_MgvZehBK2CScVCMubvg1GNXV9whGAS6I,6663
12
- paytechuz/gateways/click/merchant.py,sha256=vJ_DivA1KfRT5p3sfA5yZGMYXoUmVbAM7QHvaXr6VCU,7254
10
+ paytechuz/gateways/click/__init__.py,sha256=35RPIrZYHgMWDzxjQkJMZYjzHDa8cY_BqQztCdZZmBM,90
11
+ paytechuz/gateways/click/client.py,sha256=YWvgkBoBeZf9SIYi09kIMiiWkf6M5wbR4Jc8k1z5mRA,6615
12
+ paytechuz/gateways/click/merchant.py,sha256=9xbn7LD7CMBE0k6h5AVcsWpDjOaWudhxvf2QrmqbkoA,7236
13
13
  paytechuz/gateways/click/webhook.py,sha256=rph-NmjjnBKMW4rcxQTXrHHdK-uMrU39kXnbqK56leo,7936
14
- paytechuz/gateways/payme/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
- paytechuz/gateways/payme/cards.py,sha256=aL6su_ZTCBPU8qmrz2Jcw_Wn7Zf9RwIu8k10o4AWFTs,5420
16
- paytechuz/gateways/payme/client.py,sha256=C1OQWLo7LIAF3xbFOLyCaJ3xFwQaFVpaxWCYajCltTY,8201
17
- paytechuz/gateways/payme/receipts.py,sha256=DdrZMPeDvQmGyqAEOTmtUorfcIVVb3t2tg31l7TXqHo,8904
14
+ paytechuz/gateways/payme/__init__.py,sha256=KcVkYvAEblL4ASVAOrUofRBwywAkTZIgRXoBaCbYtv8,90
15
+ paytechuz/gateways/payme/cards.py,sha256=0uAfPD5tZZg0puqOjkodcWUxhMgqKeyvFpgenruMuSQ,5402
16
+ paytechuz/gateways/payme/client.py,sha256=TK1ZwWHcabbPiRujbPOTFchPSjyt7V13KP6xfCgSm2A,7783
17
+ paytechuz/gateways/payme/receipts.py,sha256=uLoFpowIqZtj3lPWmUvmpBEGfhwAPWt5Sl16OJHfiEI,8886
18
18
  paytechuz/gateways/payme/webhook.py,sha256=-0O8vzMtiu4U8FWFKDA6EfyoX4NEGqcEq-T0yNtVhM4,12374
19
19
  paytechuz/integrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
20
  paytechuz/integrations/django/__init__.py,sha256=YDgD1Ux1E3CJxQMT-9tulhXmuLOEaUSv320LeaVgJ00,116
@@ -30,7 +30,7 @@ paytechuz/integrations/fastapi/__init__.py,sha256=DLnhAZQZf2ghu8BuFFfE7FzbNKWQQ2
30
30
  paytechuz/integrations/fastapi/models.py,sha256=eWGUpiKufj47AK8Hld4A91jRDj0ZKQzAf95CyUozmvo,4638
31
31
  paytechuz/integrations/fastapi/routes.py,sha256=D17QeyY4-aX6tCNmk5h3UiavukvVrE5e6JOFCy4t_n8,36629
32
32
  paytechuz/integrations/fastapi/schemas.py,sha256=CkNohj22mQQje8Pu_IkTQwUPAoYHNOKXlGjqaRX_SGQ,3784
33
- paytechuz-0.1.3.dist-info/METADATA,sha256=fLZlC2jeUhspOlm3nmb0HzKy29Qa6N2K2T-u4y06gfU,6058
34
- paytechuz-0.1.3.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
35
- paytechuz-0.1.3.dist-info/top_level.txt,sha256=oloyKGNVj9Z2h3wpKG5yPyTlpdpWW0-CWr-j-asCWBc,10
36
- paytechuz-0.1.3.dist-info/RECORD,,
33
+ paytechuz-0.1.6.dist-info/METADATA,sha256=2h0tyvJXvI-SAhqacd6Mdl-CuljKpLpb2q5FMNdB3dM,4149
34
+ paytechuz-0.1.6.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
35
+ paytechuz-0.1.6.dist-info/top_level.txt,sha256=oloyKGNVj9Z2h3wpKG5yPyTlpdpWW0-CWr-j-asCWBc,10
36
+ paytechuz-0.1.6.dist-info/RECORD,,
@@ -1,198 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: paytechuz
3
- Version: 0.1.3
4
- Summary: Unified Python package for Uzbekistan payment gateways
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
- [![PyPI version](https://badge.fury.io/py/paytechuz.svg)](https://badge.fury.io/py/paytechuz)
57
- [![Python Versions](https://img.shields.io/pypi/pyversions/paytechuz.svg)](https://pypi.org/project/paytechuz/)
58
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](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)