add: add payme api

This commit is contained in:
behruz-dev
2025-09-16 21:30:23 +05:00
parent 795eb7a5a9
commit 0252033586
7 changed files with 97 additions and 16 deletions

View File

@@ -25,6 +25,7 @@ INSTALLED_APPS = [
'rest_framework', 'rest_framework',
'rest_framework_simplejwt', 'rest_framework_simplejwt',
'corsheaders', 'corsheaders',
'payme',
# apps # apps
'core.apps.accounts', 'core.apps.accounts',
'core.apps.orders', 'core.apps.orders',
@@ -147,4 +148,13 @@ ALLOWED_ATMOS_IPS = []
CONSUMER_KEY = env.str('CONSUMER_KEY') CONSUMER_KEY = env.str('CONSUMER_KEY')
CONSUMER_SECRET = env.str('CONSUMER_SECRET') 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')
PAYME_ID = env.str('PAYME_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"

View File

@@ -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()),
] ]

View File

@@ -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):

View File

@@ -20,4 +20,13 @@ class VisaPaymentSerializer(serializers.Serializer):
def validate_order_number(self, value): def validate_order_number(self, value):
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

View File

@@ -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()),
] ]

View File

@@ -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({'success': True, 'link': 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)

View File

@@ -37,4 +37,5 @@ uritemplate==4.2.0
uvicorn==0.35.0 uvicorn==0.35.0
vine==5.1.0 vine==5.1.0
wcwidth==0.2.13 wcwidth==0.2.13
requests requests
payme-pkg