diff --git a/config/settings/base.py b/config/settings/base.py index ab31e8e..ef6cead 100644 --- a/config/settings/base.py +++ b/config/settings/base.py @@ -147,4 +147,8 @@ ALLOWED_ATMOS_IPS = [] CONSUMER_KEY = env.str('CONSUMER_KEY') CONSUMER_SECRET = env.str('CONSUMER_SECRET') STORE_ID = env.str('STORE_ID') -API_KEY = env.str('API_KEY') \ No newline at end of file +API_KEY = env.str('API_KEY') + +GLOBAL_CONSUMER_KEY = env.str('GLOBAL_CONSUMER_KEY') +GLOBAL_CONSUMER_SECRET = env.str('GLOBAL_CONSUMER_SECRET') +GLOBAL_STORE_ID = env.str('GLOBAL_STORE_ID') \ No newline at end of file diff --git a/core/apps/payment/serializers.py b/core/apps/payment/serializers.py index b3e6b2d..28b7fa6 100644 --- a/core/apps/payment/serializers.py +++ b/core/apps/payment/serializers.py @@ -7,6 +7,16 @@ class PaymentSerializer(serializers.Serializer): order_number = serializers.IntegerField() price = serializers.IntegerField() + def validate_order_number(self, value): + if not Order.objects.filter(order_number=value).exists(): + raise serializers.ValidationError("Order not found") + return value + + +class VisaPaymentSerializer(serializers.Serializer): + amount = serializers.IntegerField() + order_number = serializers.IntegerField() + def validate_order_number(self, value): if not Order.objects.filter(order_number=value).exists(): raise serializers.ValidationError("Order not found") diff --git a/core/apps/payment/urls.py b/core/apps/payment/urls.py index 51e31ed..ca556d6 100644 --- a/core/apps/payment/urls.py +++ b/core/apps/payment/urls.py @@ -1,8 +1,9 @@ from django.urls import path -from .views import AtmosCallbackApiView, PaymentGenerateLinkApiView +from .views import AtmosCallbackApiView, PaymentGenerateLinkApiView, VisaMastercardPaymentApiView urlpatterns = [ path('callback/', AtmosCallbackApiView.as_view()), path('payment/', PaymentGenerateLinkApiView.as_view()), + path('visa_mastercard/payment/', VisaMastercardPaymentApiView.as_view()), ] \ No newline at end of file diff --git a/core/apps/payment/views.py b/core/apps/payment/views.py index 5ecf089..0816954 100644 --- a/core/apps/payment/views.py +++ b/core/apps/payment/views.py @@ -1,7 +1,5 @@ import hashlib -import logging - -logger = logging.getLogger(__name__) +import uuid from django.conf import settings @@ -11,7 +9,7 @@ from rest_framework.response import Response from rest_framework import status, permissions from core.apps.orders.models import Order -from core.apps.payment.serializers import PaymentSerializer +from core.apps.payment.serializers import PaymentSerializer, VisaPaymentSerializer from core.services.payment import Atmos @@ -44,15 +42,9 @@ class AtmosCallbackApiView(APIView): invoice = data.get("invoice") amount = data.get("amount") sign = data.get("sign") - logger.info(f"Atmos yuborgan SIGN: {sign}") - print("Atmos yuborgan SIGN:", sign) check_string = f"{store_id}{transaction_id}{invoice}{amount}{settings.API_KEY}" - print(check_string) generated_sign = hashlib.md5(check_string.encode()).hexdigest() - logger.info(f"Biz generatsiya qilgan SIGN: {generated_sign}") - print("Biz generatsiya qilgan SIGN:", generated_sign) - if generated_sign != sign: return Response( @@ -68,12 +60,6 @@ class AtmosCallbackApiView(APIView): status=status.HTTP_200_OK ) - # if str(order.total_price) != str(amount): - # return Response( - # {"status": 0, "message": f"Инвойс с номером {invoice} отсутствует в системе"}, - # status=status.HTTP_200_OK - # ) - order.is_paid = True order.save() @@ -101,3 +87,21 @@ class PaymentGenerateLinkApiView(GenericAPIView): status=200 ) + +class VisaMastercardPaymentApiView(GenericAPIView): + queryset = None + permission_classes = [permissions.IsAuthenticated] + serializer_class = VisaPaymentSerializer + + def post(self, request): + serializer = self.serializer_class(data=request.data) + if not serializer.is_valid(): + return Response({'success': False, 'message': serializer.errors}, status=400) + data = serializer.validated_data + service = Atmos() + res = service.global_payment( + account=data.get('order_number'), + request_id=str(uuid.uuid4()), + amount=data.get('amount'), + ) + return Response(res) \ No newline at end of file diff --git a/core/services/payment.py b/core/services/payment.py index 20a031a..80c2d5d 100644 --- a/core/services/payment.py +++ b/core/services/payment.py @@ -9,7 +9,10 @@ class Atmos: self.consumer_secret = settings.CONSUMER_SECRET self.terminal_id = terminal_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): credentials = f"{self.consumer_key}:{self.consumer_secret}" encoded_credentials = base64.b64encode(credentials.encode()).decode() @@ -46,4 +49,41 @@ class Atmos: url = f'http://test-checkout.pays.uz/invoice/get?storeId={self.store_id}&transactionId={transaction_id}&redirectLink={redirect_url}' return url - \ No newline at end of file + + # 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 = { + "grant_type": "client_credentials" + } + url = 'https://apigw.atmos.uz/token' + res = requests.post(url, headers=headers, data=data) + return res.json()['access_token'] + + def global_payment(self, request_id, account, amount): + access = self.login_global_payment() + url = 'https://apigw.atmos.uz/checkout/invoice/create' + headers = { + 'Authorization': f'Bearer {access}', + 'Content-Type': 'application/json', + } + data = { + "request_id": request_id, + "store_id": self.global_store_id, + "account": str(account), + "amount": amount * 100, + "success_url": "https://wisdom.uz", + } + + res = requests.post(url=url, headers=headers, json=data) + if res.status_code == 200: + return res.json() + else: + return res.json() \ No newline at end of file