Files
goodtimes/manage_wallets/api/views.py
2024-08-23 17:25:08 +05:30

451 lines
16 KiB
Python

import json
from django.shortcuts import get_object_or_404
import requests
from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView
from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decorator
from accounts.models import IAmPrincipal, IAmPrincipalType
from goodtimes import services, constants
from decimal import Decimal
from manage_referrals.models import GoodTimeCoins
from manage_wallets import models
from django.conf import settings
from django.utils import timezone
from . import serializers
from goodtimes.utils import ApiResponse
# from PayTm import Checksum, check
# from Paytm_Python.paytmchecksum import PaytmChecksum
# from paytmchecksum import PaytmChecksum
# from nifty11_project.services import SMSError, SMSService
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework_simplejwt.authentication import JWTAuthentication
import stripe
@method_decorator(csrf_exempt, name="dispatch")
class StripeWebhookTest(APIView):
authentication_classes = []
permission_classes = [AllowAny]
def post(self, request):
stripe.api_key = settings.STRIPE_SECRET_KEY
payload = request.body
print("payload", payload)
sig_header = request.META["HTTP_STRIPE_SIGNATURE"]
# endpoint_secret = settings.STRIPE_WEBHOOK_SECRET
endpoint_secret = (
"whsec_ccf1f87295603cdd1733995ee2d3c0d6f74c7ceaf28916ea45114a54b7ce1d0f"
)
event = None
try:
event = stripe.Webhook.construct_event(payload, sig_header, endpoint_secret)
except ValueError as e:
value_error_response = {
"status": status.HTTP_400_BAD_REQUEST,
"message": constants.ERROR_OCCURR.format(str(e)),
"errors": str(e),
}
return ApiResponse.error(**value_error_response)
except stripe.error.SignatureVerificationError as e:
signature_error_response = {
"status": status.HTTP_400_BAD_REQUEST,
"message": constants.ERROR_OCCURR.format(str(e)),
"errors": str(e),
}
return ApiResponse.error(**signature_error_response)
if event["type"] == "payment_intent.succeeded":
payment_intent = event["data"]["object"]
print("Intent succ")
print("payment_intent: ", payment_intent)
metadata = event.data.object.metadata
print("metadata: ", metadata)
principal_id = metadata.get("principal_id")
principal_type = metadata.get("principal_type")
print("user_id: ", principal_id)
print("user_type: ", principal_type)
try:
principal = IAmPrincipal.objects.get(id=principal_id)
except IAmPrincipal.DoesNotExist as e:
error_response = {
"status": status.HTTP_404_NOT_FOUND,
"message": constants.RECORD_NOT_FOUND,
"errors": str(e),
}
return ApiResponse.error(**error_response)
wallet_manager = services.WalletManager(
principal=get_object_or_404(IAmPrincipal, id=principal_id),
principal_type=principal_type,
)
deposit_amount = event.data.object.amount
deposit_transaction = wallet_manager.deposit(
deposit_amount, "merchant_deposit"
)
print("Passed Through principal_wallet Object")
success_response = {
"status": status.HTTP_200_OK,
"message": "Webhook received, payment succeeded",
}
return ApiResponse.success(**success_response)
else:
intent_response = {
"status": status.HTTP_400_BAD_REQUEST,
"message": "Webhook received, but payment failed",
}
return ApiResponse.success(**intent_response)
class GetWallet(APIView):
authentication_classes = [JWTAuthentication]
permission_classes = [IsAuthenticated]
model = models.Wallet
def get(self, request):
try:
# Get the Wallet associated with the request.user
wallet_obj = models.Wallet.objects.get(principal_id=request.user.id)
# Serialize the wallet data
serializer = serializers.WalletSerializer(wallet_obj)
return ApiResponse.success(
status=status.HTTP_200_OK,
message=constants.SUCCESS,
data=serializer.data,
)
except Exception as e:
# Handle any exceptions and return an error response
error_response = {
"status": status.HTTP_400_BAD_REQUEST,
"message": constants.FAILURE,
"errors": str(e),
}
return ApiResponse.error(**error_response)
class TransactionView(APIView):
authentication_classes = [JWTAuthentication]
permission_classes = [IsAuthenticated]
def get(self, request):
queryset = models.Transaction.objects.filter(
principal_id=request.user.id,
transaction_status__in=[
models.TransactionStatus.SUCCESS,
models.TransactionStatus.FAIL,
],
).order_by("-created_on")
serializer = serializers.TransactionSerializer(queryset, many=True)
response = {
"status": status.HTTP_200_OK,
"message": constants.SUCCESS,
"data": serializer.data,
}
return ApiResponse.success(**response)
class TestWebhookAPI(APIView):
authentication_classes = []
permission_classes = [AllowAny]
# event = None
def post(self, request):
event = request.data.get("event", {})
print(event)
# return Response({"data": data})
if event.get("type") == "payment_intent.succeeded":
payment_intent = event.get("data", {}).get("object", {})
print("Intent succ")
print("payment_intent: ", payment_intent)
metadata = payment_intent.get("metadata", {})
print("metadata: ", metadata)
principal_id = metadata.get("principal_id")
principal_type = metadata.get("principal_type")
print("user_id: ", principal_id)
print("user_type: ", principal_type)
try:
principal = IAmPrincipal.objects.get(id=principal_id)
except IAmPrincipal.DoesNotExist as e:
principal_error_response = {
"status": status.HTTP_404_NOT_FOUND,
"message": constants.RECORD_NOT_FOUND,
"errors": str(e),
}
return ApiResponse.error(**principal_error_response)
wallet_manager = services.WalletManager(
principal=get_object_or_404(IAmPrincipal, id=principal_id),
principal_type=principal_type,
)
deposit_amount = event.get("data", {}).get("object", {}).get("amount", {})
deposit_transaction = wallet_manager.deposit(
deposit_amount, "merchant_deposit"
)
print("Passed Through principal_wallet Object")
success_response = {
"status": status.HTTP_200_OK,
"message": "Webhook received, payment succeeded",
}
return ApiResponse.success(**success_response)
else:
intent_response = {
"status": status.HTTP_400_BAD_REQUEST,
"message": "Webhook received, but payment failed",
}
return ApiResponse.success(**intent_response)
class TestWebhookAPIWithdraw(APIView):
authentication_classes = []
permission_classes = [AllowAny]
# event = None
def post(self, request):
event = request.data.get("event", {})
print(event)
# return Response({"data": data})
if event.get("type") == "payment_intent.succeeded":
payment_intent = event.get("data", {}).get("object", {})
print("Intent succ")
print("payment_intent: ", payment_intent)
metadata = payment_intent.get("metadata", {})
print("metadata: ", metadata)
principal_id = metadata.get("principal_id")
principal_type = metadata.get("principal_type")
print("user_id: ", principal_id)
print("user_type: ", principal_type)
try:
principal = IAmPrincipal.objects.get(id=principal_id)
except IAmPrincipal.DoesNotExist as e:
error_response = {
"status": status.HTTP_404_NOT_FOUND,
"message": constants.RECORD_NOT_FOUND,
"errors": str(e),
}
return ApiResponse.error(**error_response)
wallet_manager = services.WalletManager(
principal=get_object_or_404(IAmPrincipal, id=principal_id),
principal_type=principal_type,
)
withdraw_amount = event.get("data", {}).get("object", {}).get("amount", {})
try:
withdraw_transaction = wallet_manager.withdraw(
withdraw_amount, "player_deposit"
)
except Exception as e:
exception_response = {
"status": status.HTTP_400_BAD_REQUEST,
"message": constants.WITHDRAWAL_FAILED,
"errors": str(e),
}
return ApiResponse.error(**exception_response)
print("Passed Through principal_wallet Object")
success_response = {
"status": status.HTTP_200_OK,
"message": "Webhook received, payment succeeded",
}
return ApiResponse.success(**success_response)
else:
intent_response = {
"status": status.HTTP_400_BAD_REQUEST,
"message": "Webhook received, but payment failed",
}
return ApiResponse.success(**intent_response)
class CreateStripeConnectAccount(APIView):
authentication_classes = [JWTAuthentication]
permission_classes = [IsAuthenticated]
def post(self, request):
stripe.api_key = settings.STRIPE_SECRET_KEY
# country_code = request.data.get("country_code")
try:
account = stripe.Account.create(
country="GB",
email=request.user.email,
type="express",
capabilities={
"card_payments": {"requested": True},
"transfers": {"requested": True},
},
business_type="individual",
business_profile={
"name": request.user.first_name,
"support_email": request.user.email,
},
tos_acceptance={"service_agreement": "recipient"},
)
except Exception as e:
exception_response = {
"status": status.HTTP_400_BAD_REQUEST,
"message": constants.FAILURE,
"errors": str(e),
}
return ApiResponse.error(**exception_response)
link = stripe.AccountLink.create(
account=account.id,
refresh_url=request.build_absolute_uri("/subscriptions/success/"),
return_url=request.build_absolute_uri("/subscriptions/cancel/"),
type="account_onboarding",
)
models.StripeConnectAccount.objects.create(
principal=request.user,
stripe_connect_id=account.id,
)
intent_response = {
"data": link.url,
"status": status.HTTP_200_OK,
"message": "Link Sent",
}
return ApiResponse.success(**intent_response)
class PrincipalBankAccountCreateAPIView(APIView):
authentication_classes = [JWTAuthentication]
permission_classes = [IsAuthenticated]
def post(self, request, *args, **kwargs):
serializer = serializers.PrincipalBankAccountSerializer(
data=request.data, context={"request": request}
)
if serializer.is_valid():
serializer.save()
intent_response = {
"data": serializer.data,
"status": status.HTTP_200_OK,
"message": "Successfully Added Bank Account",
}
return ApiResponse.success(**intent_response)
exception_response = {
"status": status.HTTP_400_BAD_REQUEST,
"message": constants.FAILURE,
"errors": serializer.errors,
}
return ApiResponse.error(**exception_response)
class WithdrawalRequestCreateAPI(APIView):
authentication_classes = [JWTAuthentication]
permission_classes = [IsAuthenticated]
def post(self, request, *args, **kwargs):
user = request.user
wallet = models.Wallet.objects.filter(principal=user).first()
coins_amount = (
GoodTimeCoins.objects.filter(active=True, deleted=False)
.last()
.value_in_pound
)
# Check if the user has a wallet and sufficient coins
if wallet is None or wallet.coins <= 0:
return ApiResponse.error(
errors="Insufficient balance.",
status=status.HTTP_400_BAD_REQUEST,
message=constants.FAILURE,
)
amount = coins_amount * wallet.coins
print("amount: ", amount)
serializer = serializers.WithdrawalRequestSerializer(data=request.data)
if serializer.is_valid():
notes = serializer.validated_data.get("notes") or "No Notes by User"
# Save the withdrawal request with notes (either provided or default)
serializer.save(
principal=user,
created_on=timezone.now(),
coins=wallet.coins,
notes=notes,
amount=amount,
)
# Reset the wallet's coins to 0
wallet.coins = 0
wallet.save()
return ApiResponse.success(
data=serializer.data,
status=status.HTTP_200_OK,
message="Request Sent Successfully",
)
else:
return ApiResponse.error(
errors=serializer.errors,
status=status.HTTP_400_BAD_REQUEST,
message=constants.FAILURE,
)
class WithdrawalRequestView(APIView):
authentication_classes = [JWTAuthentication]
permission_classes = [IsAuthenticated]
def get(self, request):
# Get the logged-in principal
principal = request.user
# Filter withdrawal requests by the logged-in principal
withdrawal_requests = models.WithdrawalRequest.objects.filter(
principal=principal
).order_by("-created_on")
serializer = serializers.WithdrawalRequestViewSerializer(
withdrawal_requests, many=True
)
return ApiResponse.success(
data=serializer.data,
status=status.HTTP_200_OK,
message=constants.SUCCESS,
)
class PrincipalBankAccountCheck(APIView):
authentication_classes = [JWTAuthentication]
permission_classes = [IsAuthenticated]
def get(self, request):
queryset = models.PrincipalBankAccount.objects.filter(principal=request.user)
if queryset:
response = {
"status": status.HTTP_200_OK,
"message": constants.SUCCESS,
"data": True,
}
return ApiResponse.success(**response)
false_response = {
"status": status.HTTP_200_OK,
"message": constants.SUCCESS,
"data": False,
}
return ApiResponse.success(**false_response)