paytechuz 0.1.1__py3-none-any.whl → 0.1.3__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 +28 -14
- paytechuz/core/__init__.py +0 -0
- paytechuz/core/base.py +88 -0
- paytechuz/core/constants.py +68 -0
- paytechuz/core/exceptions.py +190 -0
- paytechuz/core/http.py +268 -0
- paytechuz/core/payme/errors.py +25 -0
- paytechuz/core/utils.py +192 -0
- paytechuz/gateways/__init__.py +0 -0
- paytechuz/gateways/click/__init__.py +0 -0
- paytechuz/gateways/click/client.py +202 -0
- paytechuz/gateways/click/merchant.py +264 -0
- paytechuz/gateways/click/webhook.py +227 -0
- paytechuz/gateways/payme/__init__.py +0 -0
- paytechuz/gateways/payme/cards.py +222 -0
- paytechuz/gateways/payme/client.py +238 -0
- paytechuz/gateways/payme/receipts.py +336 -0
- paytechuz/gateways/payme/webhook.py +379 -0
- paytechuz/integrations/__init__.py +0 -0
- paytechuz/integrations/django/__init__.py +4 -0
- paytechuz/integrations/django/admin.py +78 -0
- paytechuz/integrations/django/apps.py +21 -0
- paytechuz/integrations/django/migrations/0001_initial.py +51 -0
- paytechuz/integrations/django/migrations/__init__.py +3 -0
- paytechuz/integrations/django/models.py +174 -0
- paytechuz/integrations/django/signals.py +46 -0
- paytechuz/integrations/django/views.py +100 -0
- paytechuz/integrations/django/webhooks.py +880 -0
- paytechuz/integrations/fastapi/__init__.py +21 -0
- paytechuz/integrations/fastapi/models.py +151 -0
- paytechuz/integrations/fastapi/routes.py +1028 -0
- paytechuz/integrations/fastapi/schemas.py +99 -0
- {paytechuz-0.1.1.dist-info → paytechuz-0.1.3.dist-info}/METADATA +1 -1
- paytechuz-0.1.3.dist-info/RECORD +36 -0
- paytechuz-0.1.3.dist-info/top_level.txt +1 -0
- paytechuz-0.1.1.dist-info/RECORD +0 -5
- paytechuz-0.1.1.dist-info/top_level.txt +0 -4
- {paytechuz-0.1.1.dist-info → paytechuz-0.1.3.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""
|
|
2
|
+
FastAPI integration for PayTechUZ.
|
|
3
|
+
"""
|
|
4
|
+
# These imports are available for users of the package
|
|
5
|
+
from .models import Base, PaymentTransaction # noqa: F401
|
|
6
|
+
from .schemas import ( # noqa: F401
|
|
7
|
+
PaymentTransactionBase,
|
|
8
|
+
PaymentTransactionCreate,
|
|
9
|
+
PaymentTransaction as PaymentTransactionSchema,
|
|
10
|
+
PaymentTransactionList,
|
|
11
|
+
PaymeWebhookRequest,
|
|
12
|
+
PaymeWebhookResponse,
|
|
13
|
+
PaymeWebhookErrorResponse,
|
|
14
|
+
ClickWebhookRequest,
|
|
15
|
+
ClickWebhookResponse
|
|
16
|
+
)
|
|
17
|
+
from .routes import ( # noqa: F401
|
|
18
|
+
router,
|
|
19
|
+
PaymeWebhookHandler,
|
|
20
|
+
ClickWebhookHandler
|
|
21
|
+
)
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"""
|
|
2
|
+
FastAPI models for PayTechUZ.
|
|
3
|
+
"""
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
from typing import Dict, Any, Optional
|
|
6
|
+
|
|
7
|
+
from sqlalchemy import Column, Integer, String, Float, DateTime, JSON
|
|
8
|
+
from sqlalchemy.ext.declarative import declarative_base
|
|
9
|
+
|
|
10
|
+
Base = declarative_base()
|
|
11
|
+
|
|
12
|
+
class PaymentTransaction(Base):
|
|
13
|
+
"""
|
|
14
|
+
Payment transaction model for storing payment information.
|
|
15
|
+
"""
|
|
16
|
+
__tablename__ = "payments"
|
|
17
|
+
|
|
18
|
+
# Payment gateway choices
|
|
19
|
+
PAYME = 'payme'
|
|
20
|
+
CLICK = 'click'
|
|
21
|
+
|
|
22
|
+
# Transaction states
|
|
23
|
+
CREATED = 0
|
|
24
|
+
INITIATING = 1
|
|
25
|
+
SUCCESSFULLY = 2
|
|
26
|
+
CANCELLED = -2
|
|
27
|
+
CANCELLED_DURING_INIT = -1
|
|
28
|
+
|
|
29
|
+
id = Column(Integer, primary_key=True, index=True)
|
|
30
|
+
gateway = Column(String(10), index=True) # 'payme' or 'click'
|
|
31
|
+
transaction_id = Column(String(255), index=True)
|
|
32
|
+
account_id = Column(String(255), index=True)
|
|
33
|
+
amount = Column(Float)
|
|
34
|
+
state = Column(Integer, default=CREATED, index=True)
|
|
35
|
+
reason = Column(Integer, nullable=True) # Reason for cancellation
|
|
36
|
+
extra_data = Column(JSON, default={})
|
|
37
|
+
created_at = Column(DateTime, default=datetime.utcnow, index=True)
|
|
38
|
+
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, index=True)
|
|
39
|
+
performed_at = Column(DateTime, nullable=True, index=True)
|
|
40
|
+
cancelled_at = Column(DateTime, nullable=True, index=True)
|
|
41
|
+
|
|
42
|
+
@classmethod
|
|
43
|
+
def create_transaction(
|
|
44
|
+
cls,
|
|
45
|
+
db,
|
|
46
|
+
gateway: str,
|
|
47
|
+
transaction_id: str,
|
|
48
|
+
account_id: str,
|
|
49
|
+
amount: float,
|
|
50
|
+
extra_data: Optional[Dict[str, Any]] = None
|
|
51
|
+
) -> "PaymentTransaction":
|
|
52
|
+
"""
|
|
53
|
+
Create a new transaction or get an existing one.
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
db: Database session
|
|
57
|
+
gateway: Payment gateway (payme or click)
|
|
58
|
+
transaction_id: Transaction ID from the payment system
|
|
59
|
+
account_id: Account or order ID
|
|
60
|
+
amount: Payment amount
|
|
61
|
+
extra_data: Additional data for the transaction
|
|
62
|
+
|
|
63
|
+
Returns:
|
|
64
|
+
PaymentTransaction instance
|
|
65
|
+
"""
|
|
66
|
+
# Check if transaction already exists
|
|
67
|
+
transaction = db.query(cls).filter(
|
|
68
|
+
cls.gateway == gateway,
|
|
69
|
+
cls.transaction_id == transaction_id
|
|
70
|
+
).first()
|
|
71
|
+
|
|
72
|
+
if transaction:
|
|
73
|
+
return transaction
|
|
74
|
+
|
|
75
|
+
# Create new transaction
|
|
76
|
+
transaction = cls(
|
|
77
|
+
gateway=gateway,
|
|
78
|
+
transaction_id=transaction_id,
|
|
79
|
+
account_id=str(account_id),
|
|
80
|
+
amount=amount,
|
|
81
|
+
state=cls.CREATED,
|
|
82
|
+
extra_data=extra_data or {}
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
db.add(transaction)
|
|
86
|
+
db.commit()
|
|
87
|
+
db.refresh(transaction)
|
|
88
|
+
|
|
89
|
+
return transaction
|
|
90
|
+
|
|
91
|
+
def mark_as_paid(self, db) -> "PaymentTransaction":
|
|
92
|
+
"""
|
|
93
|
+
Mark the transaction as paid.
|
|
94
|
+
|
|
95
|
+
Args:
|
|
96
|
+
db: Database session
|
|
97
|
+
|
|
98
|
+
Returns:
|
|
99
|
+
PaymentTransaction instance
|
|
100
|
+
"""
|
|
101
|
+
if self.state != self.SUCCESSFULLY:
|
|
102
|
+
self.state = self.SUCCESSFULLY
|
|
103
|
+
self.performed_at = datetime.utcnow()
|
|
104
|
+
|
|
105
|
+
db.commit()
|
|
106
|
+
db.refresh(self)
|
|
107
|
+
|
|
108
|
+
return self
|
|
109
|
+
|
|
110
|
+
def mark_as_cancelled(self, db, reason: Optional[str] = None) -> "PaymentTransaction":
|
|
111
|
+
"""
|
|
112
|
+
Mark the transaction as cancelled.
|
|
113
|
+
|
|
114
|
+
Args:
|
|
115
|
+
db: Database session
|
|
116
|
+
reason: Reason for cancellation
|
|
117
|
+
|
|
118
|
+
Returns:
|
|
119
|
+
PaymentTransaction instance
|
|
120
|
+
"""
|
|
121
|
+
# If reason is not provided, use default reason from PaymeCancelReason
|
|
122
|
+
if reason is None:
|
|
123
|
+
# Import here to avoid circular imports
|
|
124
|
+
from paytechuz.core.constants import PaymeCancelReason
|
|
125
|
+
reason_code = PaymeCancelReason.REASON_FUND_RETURNED # Default reason 5
|
|
126
|
+
else:
|
|
127
|
+
# Convert reason to int if it's a string
|
|
128
|
+
if isinstance(reason, str) and reason.isdigit():
|
|
129
|
+
reason_code = int(reason)
|
|
130
|
+
else:
|
|
131
|
+
reason_code = reason
|
|
132
|
+
|
|
133
|
+
# Only update state if not already cancelled
|
|
134
|
+
if self.state not in [self.CANCELLED, self.CANCELLED_DURING_INIT]:
|
|
135
|
+
# Always set state to CANCELLED (-2) for Payme API compatibility
|
|
136
|
+
# regardless of the current state
|
|
137
|
+
self.state = self.CANCELLED
|
|
138
|
+
self.cancelled_at = datetime.utcnow()
|
|
139
|
+
|
|
140
|
+
# Store the reason directly in the reason column
|
|
141
|
+
self.reason = reason_code
|
|
142
|
+
|
|
143
|
+
# For backward compatibility, also store in extra_data
|
|
144
|
+
extra_data = self.extra_data or {}
|
|
145
|
+
extra_data['cancel_reason'] = reason_code
|
|
146
|
+
self.extra_data = extra_data
|
|
147
|
+
|
|
148
|
+
db.commit()
|
|
149
|
+
db.refresh(self)
|
|
150
|
+
|
|
151
|
+
return self
|