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

@@ -1,174 +0,0 @@
1
- """
2
- Django models for PayTechUZ.
3
- """
4
- from django.db import models
5
- from django.utils import timezone
6
-
7
-
8
- class PaymentTransaction(models.Model):
9
- """
10
- Payment transaction model for storing payment information.
11
- """
12
- # Payment gateway choices
13
- PAYME = 'payme'
14
- CLICK = 'click'
15
-
16
- GATEWAY_CHOICES = [
17
- (PAYME, 'Payme'),
18
- (CLICK, 'Click'),
19
- ]
20
-
21
- # Transaction states
22
- CREATED = 0
23
- INITIATING = 1
24
- SUCCESSFULLY = 2
25
- CANCELLED = -2
26
- CANCELLED_DURING_INIT = -1
27
-
28
- STATE_CHOICES = [
29
- (CREATED, "Created"),
30
- (INITIATING, "Initiating"),
31
- (SUCCESSFULLY, "Successfully"),
32
- (CANCELLED, "Cancelled after successful performed"),
33
- (CANCELLED_DURING_INIT, "Cancelled during initiation"),
34
- ]
35
-
36
- gateway = models.CharField(max_length=10, choices=GATEWAY_CHOICES)
37
- transaction_id = models.CharField(max_length=255)
38
- account_id = models.CharField(max_length=255)
39
- amount = models.DecimalField(max_digits=15, decimal_places=2)
40
- state = models.IntegerField(choices=STATE_CHOICES, default=CREATED)
41
- reason = models.IntegerField(null=True, blank=True) # Reason for cancellation
42
- extra_data = models.JSONField(default=dict, blank=True)
43
- created_at = models.DateTimeField(auto_now_add=True, db_index=True)
44
- updated_at = models.DateTimeField(auto_now=True, db_index=True)
45
- performed_at = models.DateTimeField(null=True, blank=True, db_index=True)
46
- cancelled_at = models.DateTimeField(null=True, blank=True, db_index=True)
47
-
48
- class Meta:
49
- """
50
- Model Meta options.
51
- """
52
- verbose_name = "Payment Transaction"
53
- verbose_name_plural = "Payment Transactions"
54
- ordering = ["-created_at"]
55
- db_table = "payments"
56
- unique_together = [['gateway', 'transaction_id']]
57
- indexes = [
58
- models.Index(fields=['account_id']),
59
- models.Index(fields=['state']),
60
- ]
61
-
62
- def __str__(self):
63
- """
64
- String representation of the PaymentTransaction model.
65
- """
66
- return f"{self.get_gateway_display()} Transaction #{self.transaction_id} - {self.amount}"
67
-
68
- def mark_as_paid(self):
69
- """
70
- Mark the transaction as paid.
71
- """
72
- if self.state != self.SUCCESSFULLY:
73
- self.state = self.SUCCESSFULLY
74
- self.performed_at = timezone.now()
75
- self.save()
76
- return self
77
-
78
- def mark_as_cancelled(self, reason=None):
79
- """
80
- Mark the transaction as cancelled.
81
-
82
- Args:
83
- reason: Reason for cancellation (integer code)
84
-
85
- Returns:
86
- PaymentTransaction instance
87
- """
88
- if self.state not in [self.CANCELLED, self.CANCELLED_DURING_INIT]:
89
- # Always set state to CANCELLED (-2) for Payme API compatibility
90
- # regardless of the current state
91
- self.state = self.CANCELLED
92
- self.cancelled_at = timezone.now()
93
-
94
- # Store reason directly in the reason column if provided
95
- if reason is not None:
96
- # Convert reason to int if it's a string
97
- if isinstance(reason, str) and reason.isdigit():
98
- reason_code = int(reason)
99
- else:
100
- reason_code = reason
101
- self.reason = reason_code
102
-
103
- # For backward compatibility, also store in extra_data
104
- extra_data = self.extra_data or {}
105
- extra_data['cancel_reason'] = reason_code
106
- self.extra_data = extra_data
107
-
108
- self.save()
109
- return self
110
-
111
- @classmethod
112
- def create_transaction(cls, gateway, transaction_id, account_id, amount, extra_data=None):
113
- """
114
- Create a new transaction or get an existing one.
115
-
116
- Args:
117
- gateway: Payment gateway (payme or click)
118
- transaction_id: Transaction ID from the payment system
119
- account_id: Account or order ID
120
- amount: Payment amount
121
- extra_data: Additional data for the transaction
122
-
123
- Returns:
124
- PaymentTransaction instance
125
- """
126
- transaction, created = cls.objects.get_or_create(
127
- gateway=gateway,
128
- transaction_id=transaction_id,
129
- defaults={
130
- 'account_id': str(account_id),
131
- 'amount': amount,
132
- 'state': cls.CREATED,
133
- 'extra_data': extra_data or {}
134
- }
135
- )
136
-
137
- return transaction
138
-
139
- @classmethod
140
- def update_transaction(cls, gateway, transaction_id, state=None, extra_data=None):
141
- """
142
- Update an existing transaction.
143
-
144
- Args:
145
- gateway: Payment gateway (payme or click)
146
- transaction_id: Transaction ID from the payment system
147
- state: New state for the transaction
148
- extra_data: Additional data to update
149
-
150
- Returns:
151
- PaymentTransaction instance or None if not found
152
- """
153
- try:
154
- transaction = cls.objects.get(gateway=gateway, transaction_id=transaction_id)
155
-
156
- if state is not None:
157
- transaction.state = state
158
-
159
- # Update timestamps based on state
160
- if state == cls.SUCCESSFULLY:
161
- transaction.performed_at = timezone.now()
162
- elif state in [cls.CANCELLED, cls.CANCELLED_DURING_INIT]:
163
- transaction.cancelled_at = timezone.now()
164
-
165
- # Update extra_data if provided
166
- if extra_data:
167
- current_extra_data = transaction.extra_data or {}
168
- current_extra_data.update(extra_data)
169
- transaction.extra_data = current_extra_data
170
-
171
- transaction.save()
172
- return transaction
173
- except cls.DoesNotExist:
174
- return None
@@ -1,46 +0,0 @@
1
- """
2
- Django signals for PayTechUZ.
3
- """
4
- from django.db.models.signals import post_save
5
- from django.dispatch import Signal, receiver
6
-
7
- from .models import PaymentTransaction
8
-
9
- # Custom signals
10
- payment_successful = Signal()
11
- payment_cancelled = Signal()
12
- payment_created = Signal()
13
-
14
- # Signal handlers
15
- @receiver(post_save, sender=PaymentTransaction)
16
- def handle_transaction_state_change(sender, instance, created, **kwargs):
17
- """
18
- Handle transaction state changes.
19
-
20
- Args:
21
- sender: The model class
22
- instance: The actual instance being saved
23
- created: A boolean; True if a new record was created
24
- **kwargs: Additional keyword arguments
25
- """
26
- # Skip if the transaction was just created
27
- if created:
28
- payment_created.send(
29
- sender=sender,
30
- transaction=instance
31
- )
32
- return
33
-
34
- # Check if the transaction was marked as paid
35
- if instance.state == PaymentTransaction.SUCCESSFULLY:
36
- payment_successful.send(
37
- sender=sender,
38
- transaction=instance
39
- )
40
-
41
- # Check if the transaction was marked as cancelled
42
- elif instance.state in [PaymentTransaction.CANCELLED, PaymentTransaction.CANCELLED_DURING_INIT]:
43
- payment_cancelled.send(
44
- sender=sender,
45
- transaction=instance
46
- )
@@ -1,102 +0,0 @@
1
- """
2
- Django views for PayTechUZ.
3
- """
4
- import logging
5
- from django.views.decorators.csrf import csrf_exempt
6
- from django.utils.decorators import method_decorator
7
-
8
- from .webhooks import PaymeWebhook, ClickWebhook
9
-
10
- logger = logging.getLogger(__name__)
11
-
12
-
13
- @method_decorator(csrf_exempt, name='dispatch')
14
- class PaymeWebhookView(PaymeWebhook):
15
- """
16
- Default Payme webhook view.
17
-
18
- This view handles webhook requests from the Payme payment system.
19
- You can extend this class and override the event methods to customize
20
- the behavior.
21
-
22
- Example:
23
- ```python
24
- from paytechuz.integrations.django.views import PaymeWebhookView
25
-
26
- class CustomPaymeWebhookView(PaymeWebhookView):
27
- def successfully_payment(self, params, transaction):
28
- # Your custom logic here
29
- print(f"Payment successful: {transaction.transaction_id}")
30
-
31
- # Update your order status
32
- order = Order.objects.get(id=transaction.account_id)
33
- order.status = 'paid'
34
- order.save()
35
- ```
36
- """
37
-
38
- def successfully_payment(self, params, transaction):
39
- """
40
- Called when a payment is successful.
41
-
42
- Args:
43
- params: Request parameters
44
- transaction: Transaction object
45
- """
46
- logger.info(f"Payme payment successful: {transaction.transaction_id}")
47
-
48
- def cancelled_payment(self, params, transaction):
49
- """
50
- Called when a payment is cancelled.
51
-
52
- Args:
53
- params: Request parameters
54
- transaction: Transaction object
55
- """
56
- logger.info(f"Payme payment cancelled: {transaction.transaction_id}")
57
-
58
-
59
- @method_decorator(csrf_exempt, name='dispatch')
60
- class ClickWebhookView(ClickWebhook):
61
- """
62
- Default Click webhook view.
63
-
64
- This view handles webhook requests from the Click payment system.
65
- You can extend this class and override the event methods to customize
66
- the behavior.
67
-
68
- Example:
69
- ```python
70
- from paytechuz.integrations.django.views import ClickWebhookView
71
-
72
- class CustomClickWebhookView(ClickWebhookView):
73
- def successfully_payment(self, params, transaction):
74
- # Your custom logic here
75
- print(f"Payment successful: {transaction.transaction_id}")
76
-
77
- # Update your order status
78
- order = Order.objects.get(id=transaction.account_id)
79
- order.status = 'paid'
80
- order.save()
81
- ```
82
- """
83
-
84
- def successfully_payment(self, params, transaction):
85
- """
86
- Called when a payment is successful.
87
-
88
- Args:
89
- params: Request parameters
90
- transaction: Transaction object
91
- """
92
- logger.info(f"Click payment successful: {transaction.transaction_id}")
93
-
94
- def cancelled_payment(self, params, transaction):
95
- """
96
- Called when a payment is cancelled.
97
-
98
- Args:
99
- params: Request parameters
100
- transaction: Transaction object
101
- """
102
- logger.info(f"Click payment cancelled: {transaction.transaction_id}")