Compare commits
10 Commits
20d31903cd
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f5b7600e2b | ||
|
|
abc6a00fe8 | ||
|
|
c47c33a1fe | ||
|
|
b8b68d0dbb | ||
|
|
0252033586 | ||
|
|
795eb7a5a9 | ||
|
|
f5a4f879be | ||
|
|
260333cea9 | ||
|
|
787dd0a50a | ||
|
|
02bcae05a3 |
@@ -15,3 +15,9 @@ EMAIL_BACKEND='django.core.mail.backends.smtp.EmailBackend'
|
|||||||
EMAIL_HOST='smtp.gmail.com'
|
EMAIL_HOST='smtp.gmail.com'
|
||||||
EMAIL_PORT=587
|
EMAIL_PORT=587
|
||||||
EMAIL_USE_TLS=True
|
EMAIL_USE_TLS=True
|
||||||
|
|
||||||
|
|
||||||
|
CONSUMER_KEY=
|
||||||
|
CONSUMER_SECRET=
|
||||||
|
STORE_ID=
|
||||||
|
API_KEY=
|
||||||
@@ -25,6 +25,8 @@ INSTALLED_APPS = [
|
|||||||
'rest_framework',
|
'rest_framework',
|
||||||
'rest_framework_simplejwt',
|
'rest_framework_simplejwt',
|
||||||
'corsheaders',
|
'corsheaders',
|
||||||
|
'payme',
|
||||||
|
"ckeditor",
|
||||||
# apps
|
# apps
|
||||||
'core.apps.accounts',
|
'core.apps.accounts',
|
||||||
'core.apps.orders',
|
'core.apps.orders',
|
||||||
@@ -149,6 +151,20 @@ CONSUMER_SECRET = env.str('CONSUMER_SECRET')
|
|||||||
STORE_ID = env.str('STORE_ID')
|
STORE_ID = env.str('STORE_ID')
|
||||||
API_KEY = env.str('API_KEY')
|
API_KEY = env.str('API_KEY')
|
||||||
|
|
||||||
GLOBAL_CONSUMER_KEY = env.str('GLOBAL_CONSUMER_KEY')
|
|
||||||
GLOBAL_CONSUMER_SECRET = env.str('GLOBAL_CONSUMER_SECRET')
|
PAYME_ID = env.str('PAYME_ID')
|
||||||
GLOBAL_STORE_ID = env.str('GLOBAL_STORE_ID')
|
PAYME_KEY = env.str('PAYME_KEY')
|
||||||
|
PAYME_ACCOUNT_FIELD = "order_number"
|
||||||
|
PAYME_AMOUNT_FIELD = "total_price"
|
||||||
|
PAYME_ACCOUNT_MODEL = "core.apps.orders.models.Order"
|
||||||
|
PAYME_ONE_TIME_PAYMENT = True
|
||||||
|
PAYME_ACCOUNT_FIELD_TYPE = "int"
|
||||||
|
|
||||||
|
|
||||||
|
CKEDITOR_CONFIGS = {
|
||||||
|
"default": {
|
||||||
|
"toolbar": "full",
|
||||||
|
"height": 300,
|
||||||
|
"width": "100%",
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,6 +8,8 @@ from rest_framework.permissions import IsAdminUser
|
|||||||
from drf_yasg.views import get_schema_view
|
from drf_yasg.views import get_schema_view
|
||||||
from drf_yasg import openapi
|
from drf_yasg import openapi
|
||||||
|
|
||||||
|
from core.apps.payment.views import PaymeCallBackAPIView
|
||||||
|
|
||||||
|
|
||||||
schema_view = get_schema_view(
|
schema_view = get_schema_view(
|
||||||
openapi.Info(
|
openapi.Info(
|
||||||
@@ -34,7 +36,8 @@ urlpatterns = [
|
|||||||
path('orders/', include('core.apps.orders.urls')),
|
path('orders/', include('core.apps.orders.urls')),
|
||||||
path('payment/', include('core.apps.payment.urls')),
|
path('payment/', include('core.apps.payment.urls')),
|
||||||
]
|
]
|
||||||
))
|
)),
|
||||||
|
path('payment/update/', PaymeCallBackAPIView.as_view()),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
# Generated by Django 5.2 on 2025-09-27 14:37
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('common', '0007_userterms_text_en_userterms_text_ru_and_more'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='aboutus',
|
||||||
|
name='full_text',
|
||||||
|
field=models.TextField(null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='news',
|
||||||
|
name='full_text',
|
||||||
|
field=models.TextField(null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='service',
|
||||||
|
name='full_text',
|
||||||
|
field=models.TextField(null=True),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
# Generated by Django 5.2 on 2025-09-27 14:38
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('common', '0008_aboutus_full_text_news_full_text_service_full_text'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='aboutus',
|
||||||
|
name='full_text_en',
|
||||||
|
field=models.TextField(null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='aboutus',
|
||||||
|
name='full_text_ru',
|
||||||
|
field=models.TextField(null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='aboutus',
|
||||||
|
name='full_text_uz',
|
||||||
|
field=models.TextField(null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='news',
|
||||||
|
name='full_text_en',
|
||||||
|
field=models.TextField(null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='news',
|
||||||
|
name='full_text_ru',
|
||||||
|
field=models.TextField(null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='news',
|
||||||
|
name='full_text_uz',
|
||||||
|
field=models.TextField(null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='service',
|
||||||
|
name='full_text_en',
|
||||||
|
field=models.TextField(null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='service',
|
||||||
|
name='full_text_ru',
|
||||||
|
field=models.TextField(null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='service',
|
||||||
|
name='full_text_uz',
|
||||||
|
field=models.TextField(null=True),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
# Generated by Django 5.2 on 2025-09-27 17:57
|
||||||
|
|
||||||
|
import ckeditor.fields
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('common', '0009_aboutus_full_text_en_aboutus_full_text_ru_and_more'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='aboutus',
|
||||||
|
name='full_text',
|
||||||
|
field=ckeditor.fields.RichTextField(null=True),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='aboutus',
|
||||||
|
name='full_text_en',
|
||||||
|
field=ckeditor.fields.RichTextField(null=True),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='aboutus',
|
||||||
|
name='full_text_ru',
|
||||||
|
field=ckeditor.fields.RichTextField(null=True),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='aboutus',
|
||||||
|
name='full_text_uz',
|
||||||
|
field=ckeditor.fields.RichTextField(null=True),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='news',
|
||||||
|
name='full_text',
|
||||||
|
field=ckeditor.fields.RichTextField(null=True),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='news',
|
||||||
|
name='full_text_en',
|
||||||
|
field=ckeditor.fields.RichTextField(null=True),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='news',
|
||||||
|
name='full_text_ru',
|
||||||
|
field=ckeditor.fields.RichTextField(null=True),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='news',
|
||||||
|
name='full_text_uz',
|
||||||
|
field=ckeditor.fields.RichTextField(null=True),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='service',
|
||||||
|
name='full_text',
|
||||||
|
field=ckeditor.fields.RichTextField(null=True),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='service',
|
||||||
|
name='full_text_en',
|
||||||
|
field=ckeditor.fields.RichTextField(null=True),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='service',
|
||||||
|
name='full_text_ru',
|
||||||
|
field=ckeditor.fields.RichTextField(null=True),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='service',
|
||||||
|
name='full_text_uz',
|
||||||
|
field=ckeditor.fields.RichTextField(null=True),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
import uuid
|
import uuid
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
|
from ckeditor.fields import RichTextField
|
||||||
|
|
||||||
|
|
||||||
class BaseModel(models.Model):
|
class BaseModel(models.Model):
|
||||||
id = models.UUIDField(primary_key=True, editable=False, unique=True, db_index=True, default=uuid.uuid4)
|
id = models.UUIDField(primary_key=True, editable=False, unique=True, db_index=True, default=uuid.uuid4)
|
||||||
@@ -32,6 +34,7 @@ class Banner(BaseModel):
|
|||||||
class AboutUs(BaseModel):
|
class AboutUs(BaseModel):
|
||||||
title = models.CharField(max_length=200)
|
title = models.CharField(max_length=200)
|
||||||
description = models.TextField()
|
description = models.TextField()
|
||||||
|
full_text = RichTextField(null=True)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.title
|
return self.title
|
||||||
@@ -67,6 +70,7 @@ class Service(BaseModel):
|
|||||||
text = models.TextField()
|
text = models.TextField()
|
||||||
icon = models.ImageField(upload_to='service/icons/')
|
icon = models.ImageField(upload_to='service/icons/')
|
||||||
image = models.ImageField(upload_to='service/images/')
|
image = models.ImageField(upload_to='service/images/')
|
||||||
|
full_text = RichTextField(null=True)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.title
|
return self.title
|
||||||
@@ -104,6 +108,7 @@ class News(BaseModel):
|
|||||||
image = models.ImageField(unique='news/images/')
|
image = models.ImageField(unique='news/images/')
|
||||||
title = models.CharField(max_length=300)
|
title = models.CharField(max_length=300)
|
||||||
text = models.TextField()
|
text = models.TextField()
|
||||||
|
full_text = RichTextField(null=True)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.title
|
return self.title
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ class AboutUsSerializer(serializers.ModelSerializer):
|
|||||||
class Meta:
|
class Meta:
|
||||||
model = models.AboutUs
|
model = models.AboutUs
|
||||||
fields = [
|
fields = [
|
||||||
'id', 'title', 'description', 'images', 'features'
|
'id', 'title', 'description', 'full_text', 'images', 'features'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@@ -50,14 +50,14 @@ class ServiceListSerializer(serializers.ModelSerializer):
|
|||||||
class Meta:
|
class Meta:
|
||||||
model = models.Service
|
model = models.Service
|
||||||
fields = [
|
fields = [
|
||||||
'id', 'title', 'text', 'icon', 'image',
|
'id', 'title', 'text', 'icon', 'image', 'full_text'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class NewsSerializer(serializers.ModelSerializer):
|
class NewsSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = models.News
|
model = models.News
|
||||||
fields = ['id', 'image', 'title', 'text']
|
fields = ['id', 'image', 'title', 'text', 'full_text']
|
||||||
|
|
||||||
|
|
||||||
class ContactUsSerializer(serializers.ModelSerializer):
|
class ContactUsSerializer(serializers.ModelSerializer):
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ class BannerTranslation(translator.TranslationOptions):
|
|||||||
@translator.register(models.AboutUs)
|
@translator.register(models.AboutUs)
|
||||||
class AboutUsTranslation(translator.TranslationOptions):
|
class AboutUsTranslation(translator.TranslationOptions):
|
||||||
fields = [
|
fields = [
|
||||||
'title', 'description',
|
'title', 'description', 'full_text'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@@ -27,14 +27,14 @@ class AboutUsFeatureTranslation(translator.TranslationOptions):
|
|||||||
@translator.register(models.Service)
|
@translator.register(models.Service)
|
||||||
class ServiceTranslation(translator.TranslationOptions):
|
class ServiceTranslation(translator.TranslationOptions):
|
||||||
fields = [
|
fields = [
|
||||||
'title', 'text',
|
'title', 'text', 'full_text'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@translator.register(models.News)
|
@translator.register(models.News)
|
||||||
class NewsTranslation(translator.TranslationOptions):
|
class NewsTranslation(translator.TranslationOptions):
|
||||||
fields = [
|
fields = [
|
||||||
'title', 'text'
|
'title', 'text', 'full_text'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ from rest_framework import generics
|
|||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
|
|
||||||
from core.apps.common import models, serializers
|
from core.apps.common import models, serializers
|
||||||
from core.apps.payment.views import get_client_ip
|
|
||||||
|
|
||||||
|
|
||||||
class SiteConfigApiView(generics.GenericAPIView):
|
class SiteConfigApiView(generics.GenericAPIView):
|
||||||
|
|||||||
@@ -21,3 +21,12 @@ class VisaPaymentSerializer(serializers.Serializer):
|
|||||||
if not Order.objects.filter(order_number=value).exists():
|
if not Order.objects.filter(order_number=value).exists():
|
||||||
raise serializers.ValidationError("Order not found")
|
raise serializers.ValidationError("Order not found")
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
class PaymeSerializer(serializers.Serializer):
|
||||||
|
order_id = serializers.UUIDField()
|
||||||
|
|
||||||
|
def validate_order_id(self, value):
|
||||||
|
if not Order.objects.filter(id=value).exists():
|
||||||
|
raise serializers.ValidationError("order not found")
|
||||||
|
return value
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
from django.urls import path
|
from django.urls import path
|
||||||
|
|
||||||
from .views import AtmosCallbackApiView, PaymentGenerateLinkApiView, VisaMastercardPaymentApiView
|
from .views import AtmosCallbackApiView, PaymentGenerateLinkApiView, VisaMastercardPaymentApiView, PayPaymeApiView
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('callback/', AtmosCallbackApiView.as_view()),
|
path('callback/', AtmosCallbackApiView.as_view()),
|
||||||
path('payment/', PaymentGenerateLinkApiView.as_view()),
|
path('payment/', PaymentGenerateLinkApiView.as_view()),
|
||||||
path('visa_mastercard/payment/', VisaMastercardPaymentApiView.as_view()),
|
path('visa_mastercard/payment/', VisaMastercardPaymentApiView.as_view()),
|
||||||
|
path('payme/', PayPaymeApiView.as_view()),
|
||||||
]
|
]
|
||||||
@@ -1,6 +1,9 @@
|
|||||||
import hashlib
|
import hashlib
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
|
from payme.views import PaymeWebHookAPIView, PaymeTransactions
|
||||||
|
from payme import Payme
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
from rest_framework.generics import GenericAPIView
|
from rest_framework.generics import GenericAPIView
|
||||||
@@ -9,17 +12,18 @@ from rest_framework.response import Response
|
|||||||
from rest_framework import status, permissions
|
from rest_framework import status, permissions
|
||||||
|
|
||||||
from core.apps.orders.models import Order
|
from core.apps.orders.models import Order
|
||||||
from core.apps.payment.serializers import PaymentSerializer, VisaPaymentSerializer
|
from core.apps.payment.serializers import PaymentSerializer, VisaPaymentSerializer, PaymeSerializer
|
||||||
from core.services.payment import Atmos
|
from core.services.payment import Atmos
|
||||||
|
|
||||||
|
payme = Payme(settings.PAYME_ID)
|
||||||
|
|
||||||
def get_client_ip(request):
|
# def get_client_ip(request):
|
||||||
x_forwarded_for = request.META.get("HTTP_X_FORWARDED_FOR")
|
# x_forwarded_for = request.META.get("HTTP_X_FORWARDED_FOR")
|
||||||
if x_forwarded_for:
|
# if x_forwarded_for:
|
||||||
ip = x_forwarded_for.split(",")[0]
|
# ip = x_forwarded_for.split(",")[0]
|
||||||
else:
|
# else:
|
||||||
ip = request.META.get("REMOTE_ADDR")
|
# ip = request.META.get("REMOTE_ADDR")
|
||||||
return ip
|
# return ip
|
||||||
|
|
||||||
|
|
||||||
class AtmosCallbackApiView(APIView):
|
class AtmosCallbackApiView(APIView):
|
||||||
@@ -27,7 +31,7 @@ class AtmosCallbackApiView(APIView):
|
|||||||
permission_classes = []
|
permission_classes = []
|
||||||
|
|
||||||
def post(self, request):
|
def post(self, request):
|
||||||
client_ip = get_client_ip(request)
|
# client_ip = get_client_ip(request)
|
||||||
# if client_ip not in settings.ALLOWED_ATMOS_IPS:
|
# if client_ip not in settings.ALLOWED_ATMOS_IPS:
|
||||||
# return Response({"status": 0, "message": "IP ruxsat etilmagan"}, status=403)
|
# return Response({"status": 0, "message": "IP ruxsat etilmagan"}, status=403)
|
||||||
data = request.data
|
data = request.data
|
||||||
@@ -104,4 +108,58 @@ class VisaMastercardPaymentApiView(GenericAPIView):
|
|||||||
request_id=str(uuid.uuid4()),
|
request_id=str(uuid.uuid4()),
|
||||||
amount=data.get('amount'),
|
amount=data.get('amount'),
|
||||||
)
|
)
|
||||||
return Response(res)
|
return Response({'success': True, 'link': res})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class PaymeCallBackAPIView(PaymeWebHookAPIView):
|
||||||
|
def handle_created_payment(self, params, result, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Handle the successful payment. You can override this method
|
||||||
|
"""
|
||||||
|
print(f"Transaction created for this params: {params} and cr_result: {result}")
|
||||||
|
|
||||||
|
def handle_successfully_payment(self, params, result, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Handle the successful payment. You can override this method
|
||||||
|
"""
|
||||||
|
transaction = PaymeTransactions.get_by_transaction_id(
|
||||||
|
transaction_id=params['id']
|
||||||
|
)
|
||||||
|
order = Order.objects.get(id=transaction.id)
|
||||||
|
order.is_paid = True
|
||||||
|
order.save()
|
||||||
|
print(f"Transaction successfully performed for this params: {params} and performed_result: {result}")
|
||||||
|
|
||||||
|
def handle_cancelled_payment(self, params, result, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Handle the cancelled payment. You can override this method
|
||||||
|
"""
|
||||||
|
transaction = PaymeTransactions.get_by_transaction_id(
|
||||||
|
transaction_id=params['id']
|
||||||
|
)
|
||||||
|
if transaction.state == PaymeTransactions.CANCELED:
|
||||||
|
order = Order.objects.get(id=transaction.id)
|
||||||
|
order.is_paid = False
|
||||||
|
order.save()
|
||||||
|
print(f"Transaction cancelled for this params: {params} and cancelled_result: {result}")
|
||||||
|
|
||||||
|
|
||||||
|
class PayPaymeApiView(GenericAPIView):
|
||||||
|
serializer_class = PaymeSerializer
|
||||||
|
permission_classes = [permissions.IsAuthenticated]
|
||||||
|
queryset = Order.objects.all()
|
||||||
|
|
||||||
|
def post(self, request):
|
||||||
|
serializer = self.serializer_class(data=request.data)
|
||||||
|
if serializer.is_valid():
|
||||||
|
order_id = serializer.validated_data.get('order_id')
|
||||||
|
order = Order.objects.get(id=order_id)
|
||||||
|
payment_link = payme.initializer.generate_pay_link(
|
||||||
|
id=order_id,
|
||||||
|
amount=order.total_price * 100,
|
||||||
|
return_url="https://wisdom.uz",
|
||||||
|
)
|
||||||
|
|
||||||
|
return Response({'success': True, 'link': payment_link}, status=200)
|
||||||
@@ -9,9 +9,6 @@ class Atmos:
|
|||||||
self.consumer_secret = settings.CONSUMER_SECRET
|
self.consumer_secret = settings.CONSUMER_SECRET
|
||||||
self.terminal_id = terminal_id
|
self.terminal_id = terminal_id
|
||||||
self.store_id = settings.STORE_ID
|
self.store_id = settings.STORE_ID
|
||||||
self.global_consumer_key = settings.GLOBAL_CONSUMER_KEY
|
|
||||||
self.global_consumer_secret = settings.GLOBAL_CONSUMER_SECRET
|
|
||||||
self.global_store_id = settings.GLOBAL_STORE_ID
|
|
||||||
|
|
||||||
def login(self):
|
def login(self):
|
||||||
credentials = f"{self.consumer_key}:{self.consumer_secret}"
|
credentials = f"{self.consumer_key}:{self.consumer_secret}"
|
||||||
@@ -22,44 +19,6 @@ class Atmos:
|
|||||||
"Content-Type": "application/x-www-form-urlencoded",
|
"Content-Type": "application/x-www-form-urlencoded",
|
||||||
}
|
}
|
||||||
|
|
||||||
data = {
|
|
||||||
"grant_type": "client_credentials"
|
|
||||||
}
|
|
||||||
url = 'https://partner.atmos.uz/token'
|
|
||||||
res = requests.post(url, headers=headers, data=data)
|
|
||||||
return res.json()['access_token']
|
|
||||||
|
|
||||||
def create_transaction(self, amount, account):
|
|
||||||
access_token = self.login()
|
|
||||||
|
|
||||||
url = 'https://partner.atmos.uz/merchant/pay/create'
|
|
||||||
headers = {
|
|
||||||
'Authorization': f'Bearer {access_token}',
|
|
||||||
}
|
|
||||||
data = {
|
|
||||||
'amount': int(amount) * 100,
|
|
||||||
'account': str(account),
|
|
||||||
'store_id': f'{self.store_id}'
|
|
||||||
}
|
|
||||||
|
|
||||||
res = requests.post(url, headers=headers, json=data)
|
|
||||||
return res.json()
|
|
||||||
|
|
||||||
def generate_url(self, transaction_id, redirect_url):
|
|
||||||
url = f'http://test-checkout.pays.uz/invoice/get?storeId={self.store_id}&transactionId={transaction_id}&redirectLink={redirect_url}'
|
|
||||||
return url
|
|
||||||
|
|
||||||
|
|
||||||
# Visa/MasterCard
|
|
||||||
def login_global_payment(self):
|
|
||||||
credentials = f"{self.global_consumer_key}:{self.global_consumer_secret}"
|
|
||||||
encoded_credentials = base64.b64encode(credentials.encode()).decode()
|
|
||||||
|
|
||||||
headers = {
|
|
||||||
"Authorization": f"Basic {encoded_credentials}",
|
|
||||||
"Content-Type": "application/x-www-form-urlencoded",
|
|
||||||
}
|
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
"grant_type": "client_credentials"
|
"grant_type": "client_credentials"
|
||||||
}
|
}
|
||||||
@@ -67,8 +26,32 @@ class Atmos:
|
|||||||
res = requests.post(url, headers=headers, data=data)
|
res = requests.post(url, headers=headers, data=data)
|
||||||
return res.json()['access_token']
|
return res.json()['access_token']
|
||||||
|
|
||||||
|
def create_transaction(self, amount, account):
|
||||||
|
access_token = self.login()
|
||||||
|
|
||||||
|
url = 'https://apigw.atmos.uz/merchant/pay/create'
|
||||||
|
headers = {
|
||||||
|
'Authorization': f'Bearer {access_token}',
|
||||||
|
}
|
||||||
|
data = {
|
||||||
|
'amount': int(amount) * 100,
|
||||||
|
'account': str(account),
|
||||||
|
'store_id': f'{self.store_id}'
|
||||||
|
}
|
||||||
|
|
||||||
|
res = requests.post(url, headers=headers, json=data)
|
||||||
|
return res.json()
|
||||||
|
|
||||||
|
def generate_url(self, transaction_id, redirect_url):
|
||||||
|
# url = f'https://checkout.pays.uz/invoice/get?storeId={self.store_id}&transactionId={transaction_id}&redirectLink={redirect_url}'
|
||||||
|
url = f'http://test-checkout.pays.uz/invoice/get?storeId={self.store_id}&transactionId={transaction_id}&redirectLink={redirect_url}'
|
||||||
|
|
||||||
|
return url
|
||||||
|
|
||||||
|
|
||||||
|
# Visa/MasterCard
|
||||||
def global_payment(self, request_id, account, amount):
|
def global_payment(self, request_id, account, amount):
|
||||||
access = self.login_global_payment()
|
access = self.login()
|
||||||
url = 'https://apigw.atmos.uz/checkout/invoice/create'
|
url = 'https://apigw.atmos.uz/checkout/invoice/create'
|
||||||
headers = {
|
headers = {
|
||||||
'Authorization': f'Bearer {access}',
|
'Authorization': f'Bearer {access}',
|
||||||
@@ -76,17 +59,14 @@ class Atmos:
|
|||||||
}
|
}
|
||||||
data = {
|
data = {
|
||||||
"request_id": request_id,
|
"request_id": request_id,
|
||||||
"store_id": self.global_store_id,
|
"store_id": self.store_id,
|
||||||
"account": str(account),
|
"account": str(account),
|
||||||
"amount": amount * 100,
|
"amount": amount * 100,
|
||||||
"success_url": "https://wisdom.uz",
|
"success_url": "https://wisdom.uz",
|
||||||
}
|
}
|
||||||
|
|
||||||
res = requests.post(url=url, headers=headers, json=data, proxies={
|
res = requests.post(url=url, headers=headers, json=data)
|
||||||
'http': 'http://94.230.232.47:8080',
|
|
||||||
'https': 'http://94.230.232.47:8080',
|
|
||||||
})
|
|
||||||
if res.status_code == 200:
|
if res.status_code == 200:
|
||||||
return res.json()
|
return res.json()['url']
|
||||||
else:
|
else:
|
||||||
return res.json()
|
return res.json()
|
||||||
@@ -20,6 +20,8 @@ services:
|
|||||||
dockerfile: ./docker/Dockerfile.nginx
|
dockerfile: ./docker/Dockerfile.nginx
|
||||||
depends_on:
|
depends_on:
|
||||||
- web
|
- web
|
||||||
|
restart: always
|
||||||
|
|
||||||
|
|
||||||
web:
|
web:
|
||||||
networks:
|
networks:
|
||||||
@@ -39,6 +41,7 @@ services:
|
|||||||
- 8.8.8.8
|
- 8.8.8.8
|
||||||
- 8.8.4.4
|
- 8.8.4.4
|
||||||
- 1.1.1.1
|
- 1.1.1.1
|
||||||
|
restart: always
|
||||||
|
|
||||||
db:
|
db:
|
||||||
image: postgres:17
|
image: postgres:17
|
||||||
@@ -50,6 +53,8 @@ services:
|
|||||||
POSTGRES_DB: ${POSTGRES_DB}
|
POSTGRES_DB: ${POSTGRES_DB}
|
||||||
volumes:
|
volumes:
|
||||||
- pd_data:/var/lib/postgresql/data
|
- pd_data:/var/lib/postgresql/data
|
||||||
|
restart: always
|
||||||
|
|
||||||
|
|
||||||
redis:
|
redis:
|
||||||
networks:
|
networks:
|
||||||
@@ -57,6 +62,8 @@ services:
|
|||||||
image: redis
|
image: redis
|
||||||
ports:
|
ports:
|
||||||
- "6380:6379"
|
- "6380:6379"
|
||||||
|
restart: always
|
||||||
|
|
||||||
|
|
||||||
celery:
|
celery:
|
||||||
networks:
|
networks:
|
||||||
@@ -70,3 +77,4 @@ services:
|
|||||||
- web
|
- web
|
||||||
volumes:
|
volumes:
|
||||||
- "./:/code"
|
- "./:/code"
|
||||||
|
restart: always
|
||||||
|
|||||||
@@ -38,3 +38,5 @@ uvicorn==0.35.0
|
|||||||
vine==5.1.0
|
vine==5.1.0
|
||||||
wcwidth==0.2.13
|
wcwidth==0.2.13
|
||||||
requests
|
requests
|
||||||
|
payme-pkg
|
||||||
|
django-ckeditor
|
||||||
|
|||||||
Reference in New Issue
Block a user