django-chelseru 1.1.6__tar.gz → 1.1.8__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.
Files changed (51) hide show
  1. {django_chelseru-1.1.6/django_chelseru.egg-info → django_chelseru-1.1.8}/PKG-INFO +1 -1
  2. {django_chelseru-1.1.6 → django_chelseru-1.1.8/django_chelseru.egg-info}/PKG-INFO +1 -1
  3. {django_chelseru-1.1.6 → django_chelseru-1.1.8}/django_chelseru.egg-info/SOURCES.txt +5 -0
  4. {django_chelseru-1.1.6 → django_chelseru-1.1.8}/drfchelseru/admin.py +2 -1
  5. django_chelseru-1.1.8/drfchelseru/migrations/0018_alter_payment_ref_id.py +18 -0
  6. django_chelseru-1.1.8/drfchelseru/migrations/0019_payment_created_at_payment_status_payment_updated_at.py +30 -0
  7. django_chelseru-1.1.8/drfchelseru/migrations/0020_payment_paid_at.py +18 -0
  8. django_chelseru-1.1.8/drfchelseru/migrations/0021_alter_payment_message.py +18 -0
  9. django_chelseru-1.1.8/drfchelseru/migrations/0022_payment_pay_mode_wallet.py +48 -0
  10. {django_chelseru-1.1.6 → django_chelseru-1.1.8}/drfchelseru/models.py +48 -5
  11. {django_chelseru-1.1.6 → django_chelseru-1.1.8}/drfchelseru/services.py +226 -27
  12. {django_chelseru-1.1.6 → django_chelseru-1.1.8}/drfchelseru/settings.py +2 -1
  13. {django_chelseru-1.1.6 → django_chelseru-1.1.8}/drfchelseru/signals.py +16 -13
  14. {django_chelseru-1.1.6 → django_chelseru-1.1.8}/drfchelseru/urls.py +4 -1
  15. {django_chelseru-1.1.6 → django_chelseru-1.1.8}/drfchelseru/views.py +47 -4
  16. {django_chelseru-1.1.6 → django_chelseru-1.1.8}/setup.py +1 -1
  17. {django_chelseru-1.1.6 → django_chelseru-1.1.8}/LICENSE +0 -0
  18. {django_chelseru-1.1.6 → django_chelseru-1.1.8}/MANIFEST.in +0 -0
  19. {django_chelseru-1.1.6 → django_chelseru-1.1.8}/README.md +0 -0
  20. {django_chelseru-1.1.6 → django_chelseru-1.1.8}/README_PA.md +0 -0
  21. {django_chelseru-1.1.6 → django_chelseru-1.1.8}/django_chelseru.egg-info/dependency_links.txt +0 -0
  22. {django_chelseru-1.1.6 → django_chelseru-1.1.8}/django_chelseru.egg-info/requires.txt +0 -0
  23. {django_chelseru-1.1.6 → django_chelseru-1.1.8}/django_chelseru.egg-info/top_level.txt +0 -0
  24. {django_chelseru-1.1.6 → django_chelseru-1.1.8}/drfchelseru/__init__.py +0 -0
  25. {django_chelseru-1.1.6 → django_chelseru-1.1.8}/drfchelseru/apps.py +0 -0
  26. {django_chelseru-1.1.6 → django_chelseru-1.1.8}/drfchelseru/consumers.py +0 -0
  27. {django_chelseru-1.1.6 → django_chelseru-1.1.8}/drfchelseru/middlewares.py +0 -0
  28. {django_chelseru-1.1.6 → django_chelseru-1.1.8}/drfchelseru/migrations/0001_initial.py +0 -0
  29. {django_chelseru-1.1.6 → django_chelseru-1.1.8}/drfchelseru/migrations/0002_otpcode_session_user.py +0 -0
  30. {django_chelseru-1.1.6 → django_chelseru-1.1.8}/drfchelseru/migrations/0003_rename_mobile_otpcode_mobile_number.py +0 -0
  31. {django_chelseru-1.1.6 → django_chelseru-1.1.8}/drfchelseru/migrations/0004_rename_message_message_sms.py +0 -0
  32. {django_chelseru-1.1.6 → django_chelseru-1.1.8}/drfchelseru/migrations/0005_rename_message_sms_messagesms_chatroom_messagechat.py +0 -0
  33. {django_chelseru-1.1.6 → django_chelseru-1.1.8}/drfchelseru/migrations/0006_alter_chatroom_user_1_alter_chatroom_user_2_and_more.py +0 -0
  34. {django_chelseru-1.1.6 → django_chelseru-1.1.8}/drfchelseru/migrations/0007_chatroom_pinned_for_chatroom_status_chatroom_users_and_more.py +0 -0
  35. {django_chelseru-1.1.6 → django_chelseru-1.1.8}/drfchelseru/migrations/0008_alter_chatroompermissions_user.py +0 -0
  36. {django_chelseru-1.1.6 → django_chelseru-1.1.8}/drfchelseru/migrations/0009_alter_chatroom_status.py +0 -0
  37. {django_chelseru-1.1.6 → django_chelseru-1.1.8}/drfchelseru/migrations/0010_chatroom_banneds_chatroom_descriptions_chatroom_name_and_more.py +0 -0
  38. {django_chelseru-1.1.6 → django_chelseru-1.1.8}/drfchelseru/migrations/0011_alter_chatroom_user_1_alter_chatroom_user_2.py +0 -0
  39. {django_chelseru-1.1.6 → django_chelseru-1.1.8}/drfchelseru/migrations/0012_payment.py +0 -0
  40. {django_chelseru-1.1.6 → django_chelseru-1.1.8}/drfchelseru/migrations/0013_payment_authority_payment_data_payment_status_code.py +0 -0
  41. {django_chelseru-1.1.6 → django_chelseru-1.1.8}/drfchelseru/migrations/0014_payment_gateway_title_payment_gateway_url.py +0 -0
  42. {django_chelseru-1.1.6 → django_chelseru-1.1.8}/drfchelseru/migrations/0015_payment_message.py +0 -0
  43. {django_chelseru-1.1.6 → django_chelseru-1.1.8}/drfchelseru/migrations/0016_payment_card_hash_payment_card_pan_and_more.py +0 -0
  44. {django_chelseru-1.1.6 → django_chelseru-1.1.8}/drfchelseru/migrations/0017_alter_payment_callback_url_alter_payment_gateway_url.py +0 -0
  45. {django_chelseru-1.1.6 → django_chelseru-1.1.8}/drfchelseru/migrations/__init__.py +0 -0
  46. {django_chelseru-1.1.6 → django_chelseru-1.1.8}/drfchelseru/routing.py +0 -0
  47. {django_chelseru-1.1.6 → django_chelseru-1.1.8}/drfchelseru/serializers.py +0 -0
  48. {django_chelseru-1.1.6 → django_chelseru-1.1.8}/drfchelseru/tests.py +0 -0
  49. {django_chelseru-1.1.6 → django_chelseru-1.1.8}/drfchelseru/validators.py +0 -0
  50. {django_chelseru-1.1.6 → django_chelseru-1.1.8}/pyproject.toml +0 -0
  51. {django_chelseru-1.1.6 → django_chelseru-1.1.8}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-chelseru
3
- Version: 1.1.6
3
+ Version: 1.1.8
4
4
  Summary: Authentication system, online and real-time chat, SMS system for Iranian SMS services.
5
5
  Home-page: https://pipdjango.chelseru.com
6
6
  Author: Sobhan Bahman Rashnu
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-chelseru
3
- Version: 1.1.6
3
+ Version: 1.1.8
4
4
  Summary: Authentication system, online and real-time chat, SMS system for Iranian SMS services.
5
5
  Home-page: https://pipdjango.chelseru.com
6
6
  Author: Sobhan Bahman Rashnu
@@ -41,4 +41,9 @@ drfchelseru/migrations/0014_payment_gateway_title_payment_gateway_url.py
41
41
  drfchelseru/migrations/0015_payment_message.py
42
42
  drfchelseru/migrations/0016_payment_card_hash_payment_card_pan_and_more.py
43
43
  drfchelseru/migrations/0017_alter_payment_callback_url_alter_payment_gateway_url.py
44
+ drfchelseru/migrations/0018_alter_payment_ref_id.py
45
+ drfchelseru/migrations/0019_payment_created_at_payment_status_payment_updated_at.py
46
+ drfchelseru/migrations/0020_payment_paid_at.py
47
+ drfchelseru/migrations/0021_alter_payment_message.py
48
+ drfchelseru/migrations/0022_payment_pay_mode_wallet.py
44
49
  drfchelseru/migrations/__init__.py
@@ -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
+ ]
@@ -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.CharField(max_length=25, blank=True, null=True)
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.IntegerField(blank=True, null=True)
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
- print(status_code, message, card_hash, card_pan, ref_id, data_verify, sep='\n')
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.data_verify = data_verify
321
+ self.data = f'{self.data} | {data_verify}'
322
+ # self.data_verify = data_verify
280
323
 
281
324
  self.save()
282
325
  pass
@@ -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).json()
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
- response = {
394
- 'currency': currency,
395
- 'gateway_title': GATEWAY_ZARINPAL,
396
- 'gateway_url': f"https://payment.zarinpal.com/pg/StartPay/{_response['data'].get('authority')}",
397
- 'callback_url': callback_url,
398
- 'authority': _response['data'].get('authority'),
399
- 'status_code': _response['data'].get('code'),
400
- 'message': _response['data'].get('message'),
401
- 'data': _response['data']
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
- response = {
424
- 'status_code': _response['data'].get('status_code'),
425
- 'message': _response['data'].get('message'),
426
- 'card_hash': _response['data'].get('card_hash'),
427
- 'card_pan': _response['data'].get('card_pan'),
428
- 'ref_id': _response['data'].get('ref_id'),
429
- 'data_verify': _response['data'],
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
@@ -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
- GATEWAYS = ((0, GATEWAY_ZARINPAL),)
58
+ GATEWAY_PAYPING = 'PAYPING_IR'
59
+ GATEWAYS = ((0, GATEWAY_ZARINPAL),(1, GATEWAY_PAYPING))
59
60
  CURRENCIES = ((0, 'IRT'), (1, 'IRR'))
60
61
 
61
62
 
@@ -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')
@@ -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/callback/', PaymentCallback.as_view(), name='payment-callback'),
20
+ path('payment/verify/', PaymentCallback.as_view(), name='payment-verify'),
21
+
19
22
  ] + [path('chat/', include(router.urls)),]
@@ -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 and status == 'OK' and authority:
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
- print('response in views: ', response)
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({})
@@ -3,7 +3,7 @@ from setuptools import setup, find_packages
3
3
 
4
4
  setup(
5
5
  name='django-chelseru',
6
- version='1.1.6',
6
+ version='1.1.8',
7
7
  packages=find_packages(),
8
8
  include_package_data=True,
9
9
  install_requires=[
File without changes