django-chelseru 1.1.6__py3-none-any.whl → 1.1.8__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.
- {django_chelseru-1.1.6.dist-info → django_chelseru-1.1.8.dist-info}/METADATA +1 -1
- {django_chelseru-1.1.6.dist-info → django_chelseru-1.1.8.dist-info}/RECORD +17 -12
- drfchelseru/admin.py +2 -1
- drfchelseru/migrations/0018_alter_payment_ref_id.py +18 -0
- drfchelseru/migrations/0019_payment_created_at_payment_status_payment_updated_at.py +30 -0
- drfchelseru/migrations/0020_payment_paid_at.py +18 -0
- drfchelseru/migrations/0021_alter_payment_message.py +18 -0
- drfchelseru/migrations/0022_payment_pay_mode_wallet.py +48 -0
- drfchelseru/models.py +48 -5
- drfchelseru/services.py +226 -27
- drfchelseru/settings.py +2 -1
- drfchelseru/signals.py +16 -13
- drfchelseru/urls.py +4 -1
- drfchelseru/views.py +47 -4
- {django_chelseru-1.1.6.dist-info → django_chelseru-1.1.8.dist-info}/WHEEL +0 -0
- {django_chelseru-1.1.6.dist-info → django_chelseru-1.1.8.dist-info}/licenses/LICENSE +0 -0
- {django_chelseru-1.1.6.dist-info → django_chelseru-1.1.8.dist-info}/top_level.txt +0 -0
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
django_chelseru-1.1.
|
|
1
|
+
django_chelseru-1.1.8.dist-info/licenses/LICENSE,sha256=VupU5KV4NteHaNQb-WH31G_WZWezxXoomjiCIAHoQJo,1089
|
|
2
2
|
drfchelseru/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
-
drfchelseru/admin.py,sha256=
|
|
3
|
+
drfchelseru/admin.py,sha256=uamcWPCCw9_dD00XL8Brp8A1NvfhB5FtUfF9DWQCK9c,1022
|
|
4
4
|
drfchelseru/apps.py,sha256=hOTTzFGLXiTPZeN8p_LLcSECLtsR2Q0SUo8zJzgM-qQ,211
|
|
5
5
|
drfchelseru/consumers.py,sha256=c8h9JYu5QUSKRREFrIrkjpkEQTzG5V8eg2lriaZODsc,2614
|
|
6
6
|
drfchelseru/middlewares.py,sha256=Ej_9GTlVPzfzYAUqxUn7VHJRdlywQmrbSIW43yK5q5U,3818
|
|
7
|
-
drfchelseru/models.py,sha256=
|
|
7
|
+
drfchelseru/models.py,sha256=jQ5IbS5q4GufZC9W_zgX1Qg8YU_f8V-Jusbh5hQYPhQ,11214
|
|
8
8
|
drfchelseru/routing.py,sha256=shAlgzcIwVuVPlvKeWBLCqr6PuBTHyIrWNgHEfnqrxg,165
|
|
9
9
|
drfchelseru/serializers.py,sha256=I3kS2NhzIprY8-WWhjQPShAom6R7epg7do7RnDkpnys,1421
|
|
10
|
-
drfchelseru/services.py,sha256=
|
|
11
|
-
drfchelseru/settings.py,sha256=
|
|
12
|
-
drfchelseru/signals.py,sha256=
|
|
10
|
+
drfchelseru/services.py,sha256=9sHlY-_Prd1Wl1WTddT-e1nE7rYKlDjFaYl6FGjwvTA,27142
|
|
11
|
+
drfchelseru/settings.py,sha256=zzOKwaciRMOhf5tQM4jAT4_80nggTwl_HqCby7TCUaE,11385
|
|
12
|
+
drfchelseru/signals.py,sha256=CI1mZR5RrdOddXBnPC1eMdt9iQkYFDypfgogtfTc2eQ,2714
|
|
13
13
|
drfchelseru/tests.py,sha256=mrbGGRNg5jwbTJtWWa7zSKdDyeB4vmgZCRc2nk6VY-g,60
|
|
14
|
-
drfchelseru/urls.py,sha256=
|
|
14
|
+
drfchelseru/urls.py,sha256=qD3As2gSCEaNDxgU0ejIADLUt9t2EvoaTmqeiV1LRSA,898
|
|
15
15
|
drfchelseru/validators.py,sha256=jAJASfG4kPcqrGxxIcoR8VjS4L4n_EzZuxJtQ1g9qmo,480
|
|
16
|
-
drfchelseru/views.py,sha256=
|
|
16
|
+
drfchelseru/views.py,sha256=shi3cd19Zxk-nCFr-cK40PtArS3Howu7d6t7x_dxFlE,18079
|
|
17
17
|
drfchelseru/migrations/0001_initial.py,sha256=LfkWAeQuPXNW3_igM-w_pyKafCeHQF3aReYgMXfMzEE,1034
|
|
18
18
|
drfchelseru/migrations/0002_otpcode_session_user.py,sha256=c3oyBTQo2kjsKr5r_XQrqaq-66F7pui-4H4mEyAXgJk,3126
|
|
19
19
|
drfchelseru/migrations/0003_rename_mobile_otpcode_mobile_number.py,sha256=eiD7t6etg6nOeT7BhJrSfEcR1yTPePXtATgtyu30520,377
|
|
@@ -31,8 +31,13 @@ drfchelseru/migrations/0014_payment_gateway_title_payment_gateway_url.py,sha256=
|
|
|
31
31
|
drfchelseru/migrations/0015_payment_message.py,sha256=7aysohtF5ajAGFB88IRIy4nRagSi6GOIkQb9sTZp91o,436
|
|
32
32
|
drfchelseru/migrations/0016_payment_card_hash_payment_card_pan_and_more.py,sha256=bRGD0ZMJWW3R_c3mFAHsTMC8am2Xymh-48XRPVKmgvc,887
|
|
33
33
|
drfchelseru/migrations/0017_alter_payment_callback_url_alter_payment_gateway_url.py,sha256=CzlVrPM3L7Iv1lgjM6-MSBdw38y5uaBH9Oc6PCSImCQ,574
|
|
34
|
+
drfchelseru/migrations/0018_alter_payment_ref_id.py,sha256=qNFvyHMmEOoJ_MYBVunokUCcOaX2xj9ammg65P9xaIA,439
|
|
35
|
+
drfchelseru/migrations/0019_payment_created_at_payment_status_payment_updated_at.py,sha256=jaQUgX0lnyrZqhSMwJ-UEc5NDJ-skS8D1T4P3VHlvCE,937
|
|
36
|
+
drfchelseru/migrations/0020_payment_paid_at.py,sha256=H6cr-tfjJVjN3tCsCD8ecg9JGJpLVWOXzqTp5hpnolY,432
|
|
37
|
+
drfchelseru/migrations/0021_alter_payment_message.py,sha256=g5qIvQ-wecdXGcMf7ZhyfL2u85QpgMUOADHE7t4QHog,397
|
|
38
|
+
drfchelseru/migrations/0022_payment_pay_mode_wallet.py,sha256=241lZITO1jQHqXkJKYm8DKUh7w9rmROh65LzNifP3BA,1521
|
|
34
39
|
drfchelseru/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
35
|
-
django_chelseru-1.1.
|
|
36
|
-
django_chelseru-1.1.
|
|
37
|
-
django_chelseru-1.1.
|
|
38
|
-
django_chelseru-1.1.
|
|
40
|
+
django_chelseru-1.1.8.dist-info/METADATA,sha256=OOjipNbIe83ImvKJ2ZWUihnIMfKSNcDPBBBAec9E5qY,10944
|
|
41
|
+
django_chelseru-1.1.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
42
|
+
django_chelseru-1.1.8.dist-info/top_level.txt,sha256=fsaO1F03W3j4AYi0TfDGv5Cjb_Qrh6RSkwkWqfqaMns,12
|
|
43
|
+
django_chelseru-1.1.8.dist-info/RECORD,,
|
drfchelseru/admin.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from django.contrib import admin
|
|
2
|
-
from .models import User, OTPCode, Session, MessageSMS, ChatRoom, MessageChat, ChatRoomPermissions, Organization, Payment
|
|
2
|
+
from .models import User, OTPCode, Session, MessageSMS, ChatRoom, MessageChat, ChatRoomPermissions, Organization, Payment, Wallet
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
@admin.register(User)
|
|
@@ -32,3 +32,4 @@ admin.site.register(MessageChat)
|
|
|
32
32
|
admin.site.register(ChatRoomPermissions)
|
|
33
33
|
admin.site.register(Organization)
|
|
34
34
|
admin.site.register(Payment)
|
|
35
|
+
admin.site.register(Wallet)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Generated by Django 5.1.6 on 2025-08-28 09:21
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Migration(migrations.Migration):
|
|
7
|
+
|
|
8
|
+
dependencies = [
|
|
9
|
+
("drfchelseru", "0017_alter_payment_callback_url_alter_payment_gateway_url"),
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
operations = [
|
|
13
|
+
migrations.AlterField(
|
|
14
|
+
model_name="payment",
|
|
15
|
+
name="ref_id",
|
|
16
|
+
field=models.BigIntegerField(blank=True, null=True),
|
|
17
|
+
),
|
|
18
|
+
]
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Generated by Django 5.1.6 on 2025-08-28 20:03
|
|
2
|
+
|
|
3
|
+
import django.utils.timezone
|
|
4
|
+
from django.db import migrations, models
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Migration(migrations.Migration):
|
|
8
|
+
|
|
9
|
+
dependencies = [
|
|
10
|
+
('drfchelseru', '0018_alter_payment_ref_id'),
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
operations = [
|
|
14
|
+
migrations.AddField(
|
|
15
|
+
model_name='payment',
|
|
16
|
+
name='created_at',
|
|
17
|
+
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
|
|
18
|
+
preserve_default=False,
|
|
19
|
+
),
|
|
20
|
+
migrations.AddField(
|
|
21
|
+
model_name='payment',
|
|
22
|
+
name='status',
|
|
23
|
+
field=models.CharField(choices=[('paid', 'paid'), ('unpaid', 'unpaid'), ('canceled', 'canceled'), ('refounded', 'refounded')], default='unpaid', max_length=15),
|
|
24
|
+
),
|
|
25
|
+
migrations.AddField(
|
|
26
|
+
model_name='payment',
|
|
27
|
+
name='updated_at',
|
|
28
|
+
field=models.DateTimeField(auto_now=True),
|
|
29
|
+
),
|
|
30
|
+
]
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Generated by Django 5.1.6 on 2025-09-01 15:45
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Migration(migrations.Migration):
|
|
7
|
+
|
|
8
|
+
dependencies = [
|
|
9
|
+
('drfchelseru', '0019_payment_created_at_payment_status_payment_updated_at'),
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
operations = [
|
|
13
|
+
migrations.AddField(
|
|
14
|
+
model_name='payment',
|
|
15
|
+
name='paid_at',
|
|
16
|
+
field=models.TextField(blank=True, null=True),
|
|
17
|
+
),
|
|
18
|
+
]
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Generated by Django 5.1.6 on 2025-09-01 16:28
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Migration(migrations.Migration):
|
|
7
|
+
|
|
8
|
+
dependencies = [
|
|
9
|
+
('drfchelseru', '0020_payment_paid_at'),
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
operations = [
|
|
13
|
+
migrations.AlterField(
|
|
14
|
+
model_name='payment',
|
|
15
|
+
name='message',
|
|
16
|
+
field=models.TextField(blank=True, null=True),
|
|
17
|
+
),
|
|
18
|
+
]
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Generated by Django 5.1.6 on 2025-09-04 09:15
|
|
2
|
+
|
|
3
|
+
import django.db.models.deletion
|
|
4
|
+
from django.conf import settings
|
|
5
|
+
from django.db import migrations, models
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Migration(migrations.Migration):
|
|
9
|
+
|
|
10
|
+
dependencies = [
|
|
11
|
+
("drfchelseru", "0021_alter_payment_message"),
|
|
12
|
+
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
operations = [
|
|
16
|
+
migrations.AddField(
|
|
17
|
+
model_name="payment",
|
|
18
|
+
name="pay_mode",
|
|
19
|
+
field=models.IntegerField(
|
|
20
|
+
choices=[(1, "Charge wallet"), (2, "Only pay")], default=1
|
|
21
|
+
),
|
|
22
|
+
),
|
|
23
|
+
migrations.CreateModel(
|
|
24
|
+
name="Wallet",
|
|
25
|
+
fields=[
|
|
26
|
+
(
|
|
27
|
+
"id",
|
|
28
|
+
models.BigAutoField(
|
|
29
|
+
auto_created=True,
|
|
30
|
+
primary_key=True,
|
|
31
|
+
serialize=False,
|
|
32
|
+
verbose_name="ID",
|
|
33
|
+
),
|
|
34
|
+
),
|
|
35
|
+
("amount", models.FloatField(default=0.0)),
|
|
36
|
+
("created_at", models.DateTimeField(auto_now_add=True)),
|
|
37
|
+
("updated_at", models.DateTimeField(auto_now=True)),
|
|
38
|
+
(
|
|
39
|
+
"user",
|
|
40
|
+
models.OneToOneField(
|
|
41
|
+
on_delete=django.db.models.deletion.CASCADE,
|
|
42
|
+
related_name="wallet_drf_chelseru",
|
|
43
|
+
to=settings.AUTH_USER_MODEL,
|
|
44
|
+
),
|
|
45
|
+
),
|
|
46
|
+
],
|
|
47
|
+
),
|
|
48
|
+
]
|
drfchelseru/models.py
CHANGED
|
@@ -167,8 +167,36 @@ class MessageChat(models.Model):
|
|
|
167
167
|
return f"iD: {self.id} | Message from {self.sender.username} at {self.timestamp} | Chatroom ID: {self.chat_room.id}"
|
|
168
168
|
|
|
169
169
|
|
|
170
|
+
class Wallet(models.Model):
|
|
171
|
+
user = models.OneToOneField(default_user, on_delete=models.CASCADE, related_name='wallet_drf_chelseru')
|
|
172
|
+
amount = models.FloatField(default=0.0)
|
|
173
|
+
created_at = models.DateTimeField(auto_now_add=True)
|
|
174
|
+
updated_at = models.DateTimeField(auto_now=True)
|
|
175
|
+
|
|
176
|
+
def __str__(self) -> str:
|
|
177
|
+
return f'{self.user} - {self.amount}'
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
class PayMode(models.IntegerChoices):
|
|
181
|
+
CHARGE_WALLET = 1, 'Charge wallet'
|
|
182
|
+
ONLY_PAY = 2, 'Only pay'
|
|
183
|
+
|
|
184
|
+
|
|
170
185
|
class Payment(models.Model):
|
|
186
|
+
PAID = 'paid'
|
|
187
|
+
UNPAID = 'unpaid'
|
|
188
|
+
CANCELED = 'canceled'
|
|
189
|
+
REFOUNDED = 'refounded'
|
|
190
|
+
STATUS_CHOICES = [
|
|
191
|
+
(PAID, 'paid'),
|
|
192
|
+
(UNPAID, 'unpaid'),
|
|
193
|
+
(CANCELED, 'canceled'),
|
|
194
|
+
(REFOUNDED, 'refounded')
|
|
195
|
+
]
|
|
196
|
+
|
|
197
|
+
status = models.CharField(max_length=15, choices=STATUS_CHOICES, default=UNPAID)
|
|
171
198
|
user = models.ForeignKey(default_user, models.DO_NOTHING)
|
|
199
|
+
pay_mode = models.IntegerField(choices=PayMode.choices, default=PayMode.CHARGE_WALLET)
|
|
172
200
|
order_id = models.CharField(max_length=20)
|
|
173
201
|
amount = models.FloatField()
|
|
174
202
|
description = models.TextField()
|
|
@@ -181,14 +209,19 @@ class Payment(models.Model):
|
|
|
181
209
|
gateway_url = models.URLField(blank=True, null=True)
|
|
182
210
|
authority = models.TextField(blank=True, null=True)
|
|
183
211
|
status_code = models.IntegerField(blank=True, null=True)
|
|
184
|
-
message = models.
|
|
212
|
+
message = models.TextField(blank=True, null=True)
|
|
185
213
|
card_hash = models.TextField(blank=True, null=True)
|
|
186
214
|
card_pan = models.TextField(blank=True, null=True)
|
|
187
|
-
ref_id = models.
|
|
215
|
+
ref_id = models.BigIntegerField(blank=True, null=True)
|
|
188
216
|
|
|
189
217
|
data = models.TextField(blank=True, null=True)
|
|
190
218
|
data_verify = models.TextField(blank=True, null=True)
|
|
191
219
|
|
|
220
|
+
paid_at = models.TextField(blank=True, null=True)
|
|
221
|
+
|
|
222
|
+
created_at = models.DateTimeField(auto_now_add=True)
|
|
223
|
+
updated_at = models.DateTimeField(auto_now=True)
|
|
224
|
+
|
|
192
225
|
def __str__(self):
|
|
193
226
|
return f'payment id: {self.id} - order id: {self.order_id} amount: {self.amount}'
|
|
194
227
|
|
|
@@ -204,6 +237,7 @@ class Payment(models.Model):
|
|
|
204
237
|
message
|
|
205
238
|
data
|
|
206
239
|
'''
|
|
240
|
+
|
|
207
241
|
currency = kwargs.get('currency')
|
|
208
242
|
gateway_title = kwargs.get('gateway_title')
|
|
209
243
|
gateway_url = kwargs.get('gateway_url')
|
|
@@ -237,13 +271,14 @@ class Payment(models.Model):
|
|
|
237
271
|
self.message = message
|
|
238
272
|
|
|
239
273
|
if data is not None:
|
|
240
|
-
self.data = data
|
|
274
|
+
self.data = f'{self.data} | {data}'
|
|
241
275
|
|
|
242
276
|
self.save()
|
|
243
277
|
|
|
244
278
|
def set_verify_data(self, **kwargs: dict):
|
|
245
279
|
'''
|
|
246
280
|
inputs:
|
|
281
|
+
is_pay 0=False, 1=True
|
|
247
282
|
status_code
|
|
248
283
|
message
|
|
249
284
|
card_hash
|
|
@@ -251,14 +286,21 @@ class Payment(models.Model):
|
|
|
251
286
|
ref_id
|
|
252
287
|
data_verify
|
|
253
288
|
'''
|
|
289
|
+
is_pay = kwargs.get('is_pay')
|
|
254
290
|
status_code = kwargs.get('status_code')
|
|
255
291
|
message = kwargs.get('message')
|
|
256
292
|
card_hash = kwargs.get('card_hash')
|
|
257
293
|
card_pan = kwargs.get('card_pan')
|
|
258
294
|
ref_id = kwargs.get('ref_id')
|
|
259
295
|
data_verify = kwargs.get('data_verify')
|
|
296
|
+
|
|
260
297
|
|
|
261
|
-
|
|
298
|
+
if is_pay == 1:
|
|
299
|
+
if self.status != self.PAID:
|
|
300
|
+
self.status = self.PAID
|
|
301
|
+
if hasattr(self.user, 'wallet_drf_chelseru'):
|
|
302
|
+
self.user.wallet_drf_chelseru.amount += self.amount
|
|
303
|
+
self.user.wallet_drf_chelseru.save()
|
|
262
304
|
|
|
263
305
|
if status_code is not None:
|
|
264
306
|
self.status_code = status_code
|
|
@@ -276,7 +318,8 @@ class Payment(models.Model):
|
|
|
276
318
|
self.ref_id = ref_id
|
|
277
319
|
|
|
278
320
|
if data_verify is not None:
|
|
279
|
-
self.
|
|
321
|
+
self.data = f'{self.data} | {data_verify}'
|
|
322
|
+
# self.data_verify = data_verify
|
|
280
323
|
|
|
281
324
|
self.save()
|
|
282
325
|
pass
|
drfchelseru/services.py
CHANGED
|
@@ -5,7 +5,7 @@ from zeep import Client
|
|
|
5
5
|
from rest_framework.status import HTTP_200_OK, HTTP_204_NO_CONTENT, HTTP_500_INTERNAL_SERVER_ERROR, HTTP_502_BAD_GATEWAY, HTTP_401_UNAUTHORIZED, HTTP_400_BAD_REQUEST
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
from .settings import sms_init_check, bank_init_check, GATEWAY_ZARINPAL
|
|
8
|
+
from .settings import sms_init_check, bank_init_check, GATEWAY_ZARINPAL, GATEWAY_PAYPING
|
|
9
9
|
from .models import Payment
|
|
10
10
|
|
|
11
11
|
|
|
@@ -241,6 +241,137 @@ def send_message(mobile_number, message_text, data=None, template_id=None):
|
|
|
241
241
|
|
|
242
242
|
|
|
243
243
|
|
|
244
|
+
class PaypingIR:
|
|
245
|
+
"""
|
|
246
|
+
https://api.payping.ir/v3/pay
|
|
247
|
+
"amount": 1000,
|
|
248
|
+
"returnUrl": "https://viriakala.ir/skh-charge-wallet-successfully.php",
|
|
249
|
+
"payerIdentity": "09167332792",
|
|
250
|
+
"payerName": "bahman rashnu",
|
|
251
|
+
"description": "text descriptioni",
|
|
252
|
+
"clientRefId": "self.id"
|
|
253
|
+
"""
|
|
254
|
+
def __init__(self, merchant_id):
|
|
255
|
+
self.merchant_id = merchant_id
|
|
256
|
+
self.headers = {'Content-type': 'application/json', 'Authorization': f'Bearer {merchant_id}'}
|
|
257
|
+
|
|
258
|
+
def create_payment(self, amount, callback_url, description, order_id=None, mobile=None, email=None, currency=None, client_refid=None, **metadata):
|
|
259
|
+
url = 'https://api.payping.ir/v3/pay'
|
|
260
|
+
try:
|
|
261
|
+
data = {}
|
|
262
|
+
# data['merchant_id'] = self.merchant_id
|
|
263
|
+
data['amount'] = amount
|
|
264
|
+
data['returnUrl'] = callback_url
|
|
265
|
+
data['description'] = description
|
|
266
|
+
if order_id:
|
|
267
|
+
data['order_id'] = order_id
|
|
268
|
+
|
|
269
|
+
if mobile:
|
|
270
|
+
data['payerIdentity'] = mobile
|
|
271
|
+
|
|
272
|
+
if email:
|
|
273
|
+
data['payerName'] = email
|
|
274
|
+
|
|
275
|
+
if client_refid:
|
|
276
|
+
data['clientRefId'] = str(client_refid)
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
response = requests.post(url, data=json.dumps(data), headers=self.headers)
|
|
280
|
+
status_code = response.status_code
|
|
281
|
+
response = response.json()
|
|
282
|
+
error_data = {}
|
|
283
|
+
match status_code:
|
|
284
|
+
case 200:
|
|
285
|
+
return response
|
|
286
|
+
|
|
287
|
+
case 400:
|
|
288
|
+
if 'metaData' in response:
|
|
289
|
+
meta_data = response['metaData']
|
|
290
|
+
else:
|
|
291
|
+
meta_data = response
|
|
292
|
+
|
|
293
|
+
error_data['message'] = meta_data.get('errors') # ' | '.join(list(map(lambda x:x['message'], meta_data.get('errors'))))
|
|
294
|
+
error_data['code'] = meta_data.get('code')
|
|
295
|
+
error_data['payping_trace_id'] = response['paypingTraceId']
|
|
296
|
+
case 500:
|
|
297
|
+
error_data['message'] = 'There was a problem with the server. Check the error code with your payment service support.'
|
|
298
|
+
error_data['code'] = 500
|
|
299
|
+
case 503:
|
|
300
|
+
error_data['message'] = 'The server is currently unable to respond. Check the error code with your payment service support.'
|
|
301
|
+
error_data['code'] = 503
|
|
302
|
+
case 401:
|
|
303
|
+
error_data['message'] = 'Check the API code, payment service cannot be accessed. Check the error code with your payment service support.'
|
|
304
|
+
error_data['code'] = 401
|
|
305
|
+
case 403:
|
|
306
|
+
error_data['message'] = 'Unauthorized access. Check the error code with your payment service support.'
|
|
307
|
+
error_data['code'] = 403
|
|
308
|
+
case 404:
|
|
309
|
+
error_data['message'] = 'The requested item is not available. Check the error code with your payment service support.'
|
|
310
|
+
error_data['code'] = 404
|
|
311
|
+
except:
|
|
312
|
+
pass
|
|
313
|
+
return {'errors' : error_data}
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
def verify_payment(self, authority, amount, payment_refid, card_number, card_hash_pan):
|
|
317
|
+
'''
|
|
318
|
+
authority = payment_code
|
|
319
|
+
amount
|
|
320
|
+
payment_refid: int
|
|
321
|
+
'''
|
|
322
|
+
url = 'https://api.payping.ir/v3/pay/verify'
|
|
323
|
+
try:
|
|
324
|
+
data = {
|
|
325
|
+
"paymentRefId": payment_refid,
|
|
326
|
+
"paymentCode": authority,
|
|
327
|
+
"amount": amount
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
response = requests.post(url=url, data=json.dumps(data), headers=self.headers)
|
|
331
|
+
status_code = response.status_code
|
|
332
|
+
response = response.json()
|
|
333
|
+
error_data = {
|
|
334
|
+
'card_number': card_number,
|
|
335
|
+
'card_hash_pan': card_hash_pan,
|
|
336
|
+
'ref_id': payment_refid,
|
|
337
|
+
}
|
|
338
|
+
match status_code:
|
|
339
|
+
case 200:
|
|
340
|
+
print(f'200: {response}')
|
|
341
|
+
return response
|
|
342
|
+
|
|
343
|
+
case 400 | 409:
|
|
344
|
+
if 'metaData' in response:
|
|
345
|
+
meta_data = response.get('metaData')
|
|
346
|
+
else:
|
|
347
|
+
meta_data = response
|
|
348
|
+
|
|
349
|
+
error_data['message'] = meta_data.get('errors')
|
|
350
|
+
error_data['payping_trace_id'] = response.get('traceId')
|
|
351
|
+
|
|
352
|
+
if meta_data.get('code') == 110:
|
|
353
|
+
error_data['code'] = 110
|
|
354
|
+
error_data['message'] = meta_data.get('message')
|
|
355
|
+
|
|
356
|
+
case 500:
|
|
357
|
+
error_data['message'] = 'There was a problem with the server. Check the error code with your payment service support.'
|
|
358
|
+
error_data['code'] = 500
|
|
359
|
+
case 503:
|
|
360
|
+
error_data['message'] = 'The server is currently unable to respond. Check the error code with your payment service support.'
|
|
361
|
+
error_data['code'] = 503
|
|
362
|
+
case 401:
|
|
363
|
+
error_data['message'] = 'Check the API code, payment service cannot be accessed. Check the error code with your payment service support.'
|
|
364
|
+
error_data['code'] = 401
|
|
365
|
+
case 403:
|
|
366
|
+
error_data['message'] = 'Unauthorized access. Check the error code with your payment service support.'
|
|
367
|
+
error_data['code'] = 403
|
|
368
|
+
case 404:
|
|
369
|
+
error_data['message'] = 'The requested item is not available. Check the error code with your payment service support.'
|
|
370
|
+
error_data['code'] = 404
|
|
371
|
+
except:
|
|
372
|
+
pass
|
|
373
|
+
return {'errors' : error_data}
|
|
374
|
+
|
|
244
375
|
|
|
245
376
|
class ZarinpalCom:
|
|
246
377
|
"""
|
|
@@ -311,6 +442,10 @@ class ZarinpalCom:
|
|
|
311
442
|
data['currency'] = currency
|
|
312
443
|
|
|
313
444
|
response = requests.post(url=url, data=data)
|
|
445
|
+
|
|
446
|
+
if 'errors' in response.json() and 'code' in response.json()['errors']:
|
|
447
|
+
return {'errors': response.json()['errors']}
|
|
448
|
+
|
|
314
449
|
return response.json()
|
|
315
450
|
|
|
316
451
|
except:
|
|
@@ -362,17 +497,19 @@ class ZarinpalCom:
|
|
|
362
497
|
'authority': authority
|
|
363
498
|
}
|
|
364
499
|
|
|
365
|
-
print(data)
|
|
366
|
-
|
|
367
500
|
try:
|
|
368
|
-
response = requests.post(url=url, data=data)
|
|
501
|
+
response = requests.post(url=url, data=data)
|
|
502
|
+
response = response.json()
|
|
503
|
+
if 'errors' in response and 'code' in response['errors']:
|
|
504
|
+
return {'errors': response['errors']}
|
|
505
|
+
|
|
369
506
|
return response
|
|
370
507
|
except:
|
|
371
508
|
return False
|
|
372
509
|
|
|
373
510
|
|
|
374
511
|
|
|
375
|
-
def create_payment(amount, description, merchant_id=None, callback_url=None, order_id=None, mobile=None, email=None, currency=None, **kwargs):
|
|
512
|
+
def create_payment(amount, description, merchant_id=None, callback_url=None, order_id=None, mobile=None, email=None, currency=None, client_refid=None, **kwargs):
|
|
376
513
|
try:
|
|
377
514
|
ickeck = bank_init_check()
|
|
378
515
|
gateway = ickeck['gateway']
|
|
@@ -383,23 +520,51 @@ def create_payment(amount, description, merchant_id=None, callback_url=None, ord
|
|
|
383
520
|
if not currency:
|
|
384
521
|
currency = ickeck['settings'].get('currency')
|
|
385
522
|
|
|
386
|
-
callback_url = callback_url + '/payment/callback/' if callback_url[-1] != '/' else callback_url + 'payment/callback/'
|
|
523
|
+
# callback_url = callback_url + '/payment/callback/' if callback_url[-1] != '/' else callback_url + 'payment/callback/'
|
|
387
524
|
|
|
388
525
|
response = None
|
|
389
526
|
match gateway:
|
|
390
|
-
case GATEWAY_ZARINPAL:
|
|
527
|
+
case gw if gw == GATEWAY_ZARINPAL:
|
|
391
528
|
gw = ZarinpalCom(merchant_id=merchant_id)
|
|
392
529
|
_response = gw.create_payment(amount, callback_url, description, order_id, mobile, email, currency)
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
530
|
+
if 'data' not in _response:
|
|
531
|
+
response = {
|
|
532
|
+
'callback_url': callback_url,
|
|
533
|
+
'message': _response['errors'].get('message'),
|
|
534
|
+
'status_code': _response['errors'].get('code'),
|
|
535
|
+
'data': _response['errors']
|
|
536
|
+
}
|
|
537
|
+
else:
|
|
538
|
+
response = {
|
|
539
|
+
'currency': currency,
|
|
540
|
+
'gateway_title': GATEWAY_ZARINPAL,
|
|
541
|
+
'gateway_url': f"https://payment.zarinpal.com/pg/StartPay/{_response['data'].get('authority')}",
|
|
542
|
+
'callback_url': callback_url,
|
|
543
|
+
'authority': _response['data'].get('authority'),
|
|
544
|
+
'status_code': _response['data'].get('code'),
|
|
545
|
+
'message': _response['data'].get('message'),
|
|
546
|
+
'data': _response['data']
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
case gw if gw == GATEWAY_PAYPING:
|
|
550
|
+
gw = PaypingIR(merchant_id=merchant_id)
|
|
551
|
+
_response = gw.create_payment(amount, callback_url, description, order_id, mobile, email, client_refid)
|
|
552
|
+
if 'errors' in _response:
|
|
553
|
+
response = {
|
|
554
|
+
'callback_url': callback_url,
|
|
555
|
+
'message': _response['errors'].get('message'),
|
|
556
|
+
'status_code': _response['errors'].get('code'),
|
|
557
|
+
'data': _response['errors']
|
|
558
|
+
}
|
|
559
|
+
else:
|
|
560
|
+
response = {
|
|
561
|
+
'gateway_title': GATEWAY_PAYPING,
|
|
562
|
+
'gateway_url': _response['url'],
|
|
563
|
+
'callback_url': callback_url,
|
|
564
|
+
'authority': _response['paymentCode'],
|
|
565
|
+
'status_code': 100,
|
|
566
|
+
'data': _response
|
|
567
|
+
}
|
|
403
568
|
|
|
404
569
|
if response is not None:
|
|
405
570
|
return response
|
|
@@ -409,7 +574,7 @@ def create_payment(amount, description, merchant_id=None, callback_url=None, ord
|
|
|
409
574
|
pass
|
|
410
575
|
|
|
411
576
|
|
|
412
|
-
def verify_payment(authority, amount, merchant_id=None):
|
|
577
|
+
def verify_payment(authority, amount, merchant_id=None, payment_refid:int=None, card_number:str=None, card_hash_pan:str=None):
|
|
413
578
|
try:
|
|
414
579
|
ickeck = bank_init_check()
|
|
415
580
|
gateway = ickeck['gateway']
|
|
@@ -417,17 +582,51 @@ def verify_payment(authority, amount, merchant_id=None):
|
|
|
417
582
|
merchant_id = ickeck['settings'].get('merchant_id')
|
|
418
583
|
response = None
|
|
419
584
|
match gateway:
|
|
420
|
-
case GATEWAY_ZARINPAL:
|
|
585
|
+
case gw if gw == GATEWAY_ZARINPAL:
|
|
421
586
|
gw = ZarinpalCom(merchant_id=merchant_id)
|
|
422
587
|
_response = gw.verify_payment(authority, amount)
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
588
|
+
if 'data' not in _response:
|
|
589
|
+
response = {
|
|
590
|
+
'is_pay': 1 if _response['errors'].get('code') in [101, 100] else 0,
|
|
591
|
+
'status_code': _response['errors'].get('code'),
|
|
592
|
+
'message': _response['errors'].get('message'),
|
|
593
|
+
'data_verify': _response['errors'],
|
|
594
|
+
}
|
|
595
|
+
else:
|
|
596
|
+
response = {
|
|
597
|
+
'is_pay': 1 if _response['data'].get('code') in [101, 100] else 0,
|
|
598
|
+
'status_code': _response['data'].get('code'),
|
|
599
|
+
'message': _response['data'].get('message'),
|
|
600
|
+
'card_hash': _response['data'].get('card_hash'),
|
|
601
|
+
'card_pan': _response['data'].get('card_pan'),
|
|
602
|
+
'ref_id': _response['data'].get('ref_id'),
|
|
603
|
+
'data_verify': _response['data'],
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
case gw if gw == GATEWAY_PAYPING:
|
|
607
|
+
gw = PaypingIR(merchant_id=merchant_id)
|
|
608
|
+
_response = gw.verify_payment(authority, int(amount), payment_refid, card_number, card_hash_pan)
|
|
609
|
+
if 'errors' in _response:
|
|
610
|
+
response = {
|
|
611
|
+
'is_pay': 1 if _response['errors'].get('code') == 110 else 0,
|
|
612
|
+
'message': _response['errors'].get('message'),
|
|
613
|
+
'status_code': _response['errors'].get('code'),
|
|
614
|
+
'ref_id': _response['errors'].get('ref_id'),
|
|
615
|
+
'card_pan': _response['errors'].get('card_number'),
|
|
616
|
+
'card_hash': _response['errors'].get('card_hash_pan'),
|
|
617
|
+
'data_verify': _response['errors']
|
|
618
|
+
}
|
|
619
|
+
else:
|
|
620
|
+
response = {
|
|
621
|
+
'is_pay': 1 if 'code' in _response and _response.get('code') not in [500, 503, 401, 403, 404, 200, 400] else 0,
|
|
622
|
+
'message': _response['code'],
|
|
623
|
+
'status_code': 100,
|
|
624
|
+
'ref_id': _response['paymentRefId'],
|
|
625
|
+
'card_pan': _response['cardNumber'],
|
|
626
|
+
'card_hash': _response['cardHashPan'],
|
|
627
|
+
'paid_at': _response['payedDate'],
|
|
628
|
+
'data_verify': _response
|
|
629
|
+
}
|
|
431
630
|
|
|
432
631
|
if response is not None:
|
|
433
632
|
return response
|
drfchelseru/settings.py
CHANGED
|
@@ -55,7 +55,8 @@ AUTH_SERVICES = [(0, AUTH_SERVICE_JWT)]
|
|
|
55
55
|
SMS_SERVICES = [(0, 'PARSIAN_WEBCO_IR'),(1, 'MELI_PAYAMAK_COM') ,(2, 'KAVENEGAR_COM')]
|
|
56
56
|
|
|
57
57
|
GATEWAY_ZARINPAL = 'ZARINPAL_COM'
|
|
58
|
-
|
|
58
|
+
GATEWAY_PAYPING = 'PAYPING_IR'
|
|
59
|
+
GATEWAYS = ((0, GATEWAY_ZARINPAL),(1, GATEWAY_PAYPING))
|
|
59
60
|
CURRENCIES = ((0, 'IRT'), (1, 'IRR'))
|
|
60
61
|
|
|
61
62
|
|
drfchelseru/signals.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from django.contrib.auth.models import User as DefaultUser
|
|
2
|
-
from .models import User
|
|
2
|
+
from .models import User, Payment, Wallet
|
|
3
3
|
from django.db.models.signals import post_save, pre_save
|
|
4
4
|
from django.dispatch import receiver
|
|
5
5
|
import requests
|
|
@@ -14,15 +14,6 @@ from asgiref.sync import sync_to_async
|
|
|
14
14
|
UserGet = get_user_model()
|
|
15
15
|
|
|
16
16
|
|
|
17
|
-
# @receiver(post_save, sender=User)
|
|
18
|
-
# def create_user_profile(sender, instance, created, **kwargs):
|
|
19
|
-
# if created:
|
|
20
|
-
# mobile.objects.create(user=instance)
|
|
21
|
-
|
|
22
|
-
# @receiver(post_save, sender=User)
|
|
23
|
-
# def save_user_profile(sender, instance, **kwargs):
|
|
24
|
-
# instance.mobile.save()
|
|
25
|
-
|
|
26
17
|
@receiver(pre_save, sender=User)
|
|
27
18
|
def create_user_if_not_exists(sender, instance, **kwargs):
|
|
28
19
|
if not instance.user_id:
|
|
@@ -30,6 +21,8 @@ def create_user_if_not_exists(sender, instance, **kwargs):
|
|
|
30
21
|
defaults={'username': f'G{instance.group}-{instance.mobile}'})
|
|
31
22
|
if created:
|
|
32
23
|
instance.user = default_user
|
|
24
|
+
Wallet.objects.create(user=default_user)
|
|
25
|
+
|
|
33
26
|
|
|
34
27
|
@receiver(post_save, sender=DefaultUser)
|
|
35
28
|
def send_email_after_create(sender, instance, **kwargs):
|
|
@@ -48,8 +41,6 @@ def send_email_after_create(sender, instance, **kwargs):
|
|
|
48
41
|
|
|
49
42
|
|
|
50
43
|
|
|
51
|
-
|
|
52
|
-
|
|
53
44
|
@sync_to_async
|
|
54
45
|
def get_user(validated_token):
|
|
55
46
|
try:
|
|
@@ -73,4 +64,16 @@ class JWTAuthMiddleware(BaseMiddleware):
|
|
|
73
64
|
else:
|
|
74
65
|
scope["user"] = AnonymousUser()
|
|
75
66
|
|
|
76
|
-
return await super().__call__(scope, receive, send)
|
|
67
|
+
return await super().__call__(scope, receive, send)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
# @receiver(post_save, sender=Payment)
|
|
72
|
+
# def charge_wallet_after_pay(sender, instance, **kwargs):
|
|
73
|
+
# if instance.status == Payment.PAID:
|
|
74
|
+
# if hasattr(instance.user, 'wallet_drf_chelseru'):
|
|
75
|
+
# print('ok')
|
|
76
|
+
# instance.user.wallet_drf_chelseru.amount += instance.amount
|
|
77
|
+
# instance.save()
|
|
78
|
+
# else:
|
|
79
|
+
# print('nok')
|
drfchelseru/urls.py
CHANGED
|
@@ -10,10 +10,13 @@ router.register(r'messages', MessageViewSet, basename='messages')
|
|
|
10
10
|
|
|
11
11
|
urlpatterns = [
|
|
12
12
|
path('message/send/', MessageSend.as_view(), name='message-send'),
|
|
13
|
+
|
|
13
14
|
path('otp/send/', OTPCodeSend.as_view(), name='otp-send'),
|
|
14
15
|
path('authenticate/', Authentication.as_view(), name='auth'),
|
|
16
|
+
|
|
15
17
|
path('sessions/', SessionList.as_view(), name='sessions'),
|
|
16
18
|
|
|
17
19
|
path('payment/create/', PaymentCreate.as_view(), name='payment-create'),
|
|
18
|
-
path('payment/
|
|
20
|
+
path('payment/verify/', PaymentCallback.as_view(), name='payment-verify'),
|
|
21
|
+
|
|
19
22
|
] + [path('chat/', include(router.urls)),]
|
drfchelseru/views.py
CHANGED
|
@@ -301,7 +301,8 @@ class PaymentCreate(APIView):
|
|
|
301
301
|
data['email'] = self.request.user.email
|
|
302
302
|
|
|
303
303
|
obj = self.model.objects.create(user=request.user, amount=data['amount'], description=data['description'], mobile=data['mobile'], email=data['email'])
|
|
304
|
-
|
|
304
|
+
data['client_refid'] = obj.user.id
|
|
305
|
+
|
|
305
306
|
if 'callback_url' in request.data:
|
|
306
307
|
data['callback_url'] = request.data['callback_url']
|
|
307
308
|
obj.callback_url = data['callback_url']
|
|
@@ -349,14 +350,56 @@ class PaymentCallback(APIView):
|
|
|
349
350
|
authority = request.GET.get('Authority')
|
|
350
351
|
status = request.GET.get('Status')
|
|
351
352
|
|
|
352
|
-
if status
|
|
353
|
+
if status and authority:
|
|
354
|
+
# and status == 'OK'
|
|
353
355
|
try:
|
|
354
356
|
obj = self.model.objects.get(authority=authority)
|
|
355
357
|
response = verify_payment(authority=authority, amount=obj.amount)
|
|
356
|
-
|
|
358
|
+
if response is None:
|
|
359
|
+
return Response({'error': 'callback data is none, please check your gateway settings.'}, status=HTTP_400_BAD_REQUEST)
|
|
360
|
+
|
|
357
361
|
obj.set_verify_data(**response)
|
|
358
362
|
return Response({'details': response}, status=HTTP_200_OK)
|
|
359
363
|
except self.model.DoesNotExist:
|
|
360
364
|
return Response({'error': 'payment not found.'}, status=HTTP_404_NOT_FOUND)
|
|
361
365
|
|
|
362
|
-
return Response({'error': 'The transaction was unsuccessful or canceled.'}, status=HTTP_400_BAD_REQUEST)
|
|
366
|
+
return Response({'error': 'The transaction was unsuccessful or canceled.'}, status=HTTP_400_BAD_REQUEST)
|
|
367
|
+
|
|
368
|
+
def post(self, request):
|
|
369
|
+
# print(request.data)
|
|
370
|
+
if 'paymentCode' in request.data:
|
|
371
|
+
authority = request.POST.get('paymentCode')
|
|
372
|
+
else:
|
|
373
|
+
authority = request.POST.get('authority')
|
|
374
|
+
|
|
375
|
+
if 'paymentRefId' in request.data:
|
|
376
|
+
payment_refid = request.POST.get('paymentRefId')
|
|
377
|
+
else:
|
|
378
|
+
payment_refid = None
|
|
379
|
+
|
|
380
|
+
if 'gatewayAmount' in request.data:
|
|
381
|
+
gateway_amount = request.POST.get('gatewayAmount')
|
|
382
|
+
|
|
383
|
+
if 'cardNumber' in request.data:
|
|
384
|
+
card_number = request.POST.get('cardNumber')
|
|
385
|
+
else:
|
|
386
|
+
card_number = None
|
|
387
|
+
|
|
388
|
+
if 'cardHashPan' in request.data:
|
|
389
|
+
card_hash_pan = request.POST.get('cardHashPan')
|
|
390
|
+
else:
|
|
391
|
+
card_hash_pan = None
|
|
392
|
+
|
|
393
|
+
try:
|
|
394
|
+
obj = self.model.objects.get(authority=authority)
|
|
395
|
+
response = verify_payment(authority=authority, amount=obj.amount, payment_refid=payment_refid, card_number=card_number, card_hash_pan=card_hash_pan)
|
|
396
|
+
|
|
397
|
+
if response is None:
|
|
398
|
+
return Response({'error': 'callback data is none, please check your gateway settings.'}, status=HTTP_400_BAD_REQUEST)
|
|
399
|
+
|
|
400
|
+
obj.set_verify_data(**response)
|
|
401
|
+
return Response({'details': response}, status=HTTP_200_OK)
|
|
402
|
+
|
|
403
|
+
except self.model.DoesNotExist:
|
|
404
|
+
return Response({'error': 'payment not found.'}, status=HTTP_404_NOT_FOUND)
|
|
405
|
+
return Response({})
|
|
File without changes
|
|
File without changes
|
|
File without changes
|