diff --git a/config/settings/base.py b/config/settings/base.py index f90e8db..c562220 100644 --- a/config/settings/base.py +++ b/config/settings/base.py @@ -139,4 +139,8 @@ CSRF_TRUSTED_ORIGINS = [ "https://acargo.felixits.uz", 'http://localhost:8002', 'http://127.0.0.1:8002', -] \ No newline at end of file +] + +ALLOWED_ATMOS_IPS = [] +CONSUMER_KEY = '' +CONSUMER_SECRET = '' \ No newline at end of file diff --git a/core/apps/common/migrations/0004_country.py b/core/apps/common/migrations/0004_country.py new file mode 100644 index 0000000..4decc09 --- /dev/null +++ b/core/apps/common/migrations/0004_country.py @@ -0,0 +1,27 @@ +# Generated by Django 5.2 on 2025-08-27 15:43 + +import uuid +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('common', '0003_alter_service_options'), + ] + + operations = [ + migrations.CreateModel( + name='Country', + fields=[ + ('id', models.UUIDField(db_index=True, default=uuid.uuid4, editable=False, primary_key=True, serialize=False, unique=True)), + ('created_at', models.DateField(auto_now_add=True)), + ('updated_at', models.DateField(auto_now=True)), + ('name', models.CharField(max_length=200)), + ], + options={ + 'verbose_name': 'Davlat', + 'verbose_name_plural': 'Davlatlar', + }, + ), + ] diff --git a/core/apps/common/models.py b/core/apps/common/models.py index c4346ce..586d7f1 100644 --- a/core/apps/common/models.py +++ b/core/apps/common/models.py @@ -123,3 +123,14 @@ class SiteConfig(BaseModel): class Meta: verbose_name = 'sayt sozlamalari' verbose_name_plural = 'sayt sozlamalari' + + +class Country(BaseModel): + name = models.CharField(max_length=200) + + def __str__(self): + return self.name + + class Meta: + verbose_name = 'Davlat' + verbose_name_plural = 'Davlatlar' \ No newline at end of file diff --git a/core/apps/common/views.py b/core/apps/common/views.py index 81d2eee..0b2f1ac 100644 --- a/core/apps/common/views.py +++ b/core/apps/common/views.py @@ -43,4 +43,4 @@ class NewsListApiView(generics.ListAPIView): class ContactUsApiView(generics.CreateAPIView): serializer_class = serializers.ContactUsSerializer queryset = models.ContactUs.objects.all() - \ No newline at end of file + diff --git a/core/apps/orders/migrations/0004_order_location_from_order_location_from_en_and_more.py b/core/apps/orders/migrations/0004_order_location_from_order_location_from_en_and_more.py new file mode 100644 index 0000000..415511b --- /dev/null +++ b/core/apps/orders/migrations/0004_order_location_from_order_location_from_en_and_more.py @@ -0,0 +1,55 @@ +# Generated by Django 5.2 on 2025-08-27 15:43 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('common', '0004_country'), + ('orders', '0003_order_order_number'), + ] + + operations = [ + migrations.AddField( + model_name='order', + name='location_from', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='location_from', to='common.country'), + ), + migrations.AddField( + model_name='order', + name='location_from_en', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='location_from', to='common.country'), + ), + migrations.AddField( + model_name='order', + name='location_from_ru', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='location_from', to='common.country'), + ), + migrations.AddField( + model_name='order', + name='location_from_uz', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='location_from', to='common.country'), + ), + migrations.AddField( + model_name='order', + name='location_to', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='location_to', to='common.country'), + ), + migrations.AddField( + model_name='order', + name='location_to_en', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='location_to', to='common.country'), + ), + migrations.AddField( + model_name='order', + name='location_to_ru', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='location_to', to='common.country'), + ), + migrations.AddField( + model_name='order', + name='location_to_uz', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='location_to', to='common.country'), + ), + ] diff --git a/core/apps/orders/models.py b/core/apps/orders/models.py index d2a60ba..8a41350 100644 --- a/core/apps/orders/models.py +++ b/core/apps/orders/models.py @@ -2,6 +2,7 @@ from django.db import models from core.apps.common.models import BaseModel from core.apps.accounts.models import User +from core.apps.common.models import Country class Order(BaseModel): @@ -21,21 +22,12 @@ class Order(BaseModel): total_price = models.PositiveBigIntegerField() is_paid = models.BooleanField(default=False) location = models.CharField(max_length=200) - location_to = models.CharField(max_length=200, null=True) - location_from = models.CharField(max_length=200, null=True) + location_to = models.ForeignKey(Country, on_delete=models.SET_NULL, null=True, related_name='location_to') + location_from = models.ForeignKey(Country, on_delete=models.SET_NULL, null=True, related_name='location_from') def __str__(self): return f'{self.user} user order {self.name}' - def save(self, *args, **kwargs): - if not self.order_number: - last_order = Order.objects.all().order_by('-order_number').first() - if last_order: - self.order_number = last_order.order_number + 1 - else: - self.order_number = 1 - super().save(*args, **kwargs) - class Meta: verbose_name = 'Buyurtma' verbose_name_plural = 'buyurtmalar' diff --git a/core/apps/payment/views.py b/core/apps/payment/views.py index 2a685d1..86a2eed 100644 --- a/core/apps/payment/views.py +++ b/core/apps/payment/views.py @@ -1,5 +1,5 @@ import hashlib - +from django.conf import settings from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status @@ -7,7 +7,6 @@ from rest_framework import status from core.apps.orders.models import Order API_KEY = "ATMOS_API_KEY" -ALLOWED_ATMOS_IPS = ["185.8.212.47"] def get_client_ip(request): @@ -25,7 +24,7 @@ class AtmosCallbackApiView(APIView): def post(self, request): client_ip = get_client_ip(request) - if client_ip not in ALLOWED_ATMOS_IPS: + if client_ip not in settings.ALLOWED_ATMOS_IPS: return Response({"status": 0, "message": "IP ruxsat etilmagan"}, status=403) data = request.data if not data: diff --git a/core/services/payment.py b/core/services/payment.py new file mode 100644 index 0000000..39d75fe --- /dev/null +++ b/core/services/payment.py @@ -0,0 +1,58 @@ +import requests +import base64 + + +class Atmos: + def __init__(self, consumer_key, consumer_secret, terminal_id, store_id): + self.consumer_key = consumer_key + self.consumer_secret = consumer_secret + self.terminal_id = terminal_id + self.store_id = store_id + + def login(self): + credentials = f"{self.consumer_key}:{self.consumer_secret}" + encoded_credentials = base64.b64encode(credentials.encode()).decode() + + headers = { + "Authorization": f"Basic {encoded_credentials}", + "Content-Type": "application/x-www-form-urlencoded", + } + + data = { + "grant_type": "client_credentials" + } + url = 'https://apigw.atmos.uz/token' + res = requests.post(url, headers=headers, data=data) + if 'access_token' in res.json(): + return res.json()['access_token'] + else: + return None + + def create_transaction(self, amount, account): + access_token = self.login() + + url = 'https://apigw.atmos.uz/merchant/pay/create' + headers = { + 'Authorization': f'Bearer {access_token}', + 'Content-Type': 'application/json', + } + data = { + 'amount': amount, + 'account': account, + 'terminal_id': self.terminal_id, + 'store_id': self.store_id + } + + res = requests.post(url, headers=headers, data=data) + if res.json()['result']['code'] == 'OK': + return res.json() + else: + return None + + def generate_url(self, transaction_id, redirect_url): + url = f'https://test-checkout.pays.uz/invoice/get?storeId={self.store_id}&transactionId={transaction_id}&redirectLink={redirect_url}' + + res = requests.get(url) + return res.json() + + \ No newline at end of file