add: add payme api
This commit is contained in:
@@ -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',
|
||||||
@@ -148,3 +149,12 @@ 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"
|
||||||
|
|||||||
@@ -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()),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -105,3 +109,57 @@ class VisaMastercardPaymentApiView(GenericAPIView):
|
|||||||
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)
|
||||||
@@ -38,3 +38,4 @@ uvicorn==0.35.0
|
|||||||
vine==5.1.0
|
vine==5.1.0
|
||||||
wcwidth==0.2.13
|
wcwidth==0.2.13
|
||||||
requests
|
requests
|
||||||
|
payme-pkg
|
||||||
Reference in New Issue
Block a user