Improve Payment Service: Add Transaction Safety and Error Handling

main
Razmig Sarkissian 3 weeks ago
parent 8de8a9ac49
commit 11d6913807
  1. 94
      tournaments/services/payment_service.py

@ -4,8 +4,10 @@ from django.urls import reverse
from django.http import HttpResponse from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_POST from django.views.decorators.http import require_POST
from django.db import transaction
import stripe import stripe
from datetime import datetime, timedelta from datetime import datetime, timedelta
import traceback
from ..models import TeamRegistration, PlayerRegistration, Tournament from ..models import TeamRegistration, PlayerRegistration, Tournament
from ..models.player_registration import PlayerPaymentType from ..models.player_registration import PlayerPaymentType
@ -544,47 +546,67 @@ class PaymentService:
team_registration_id = metadata.get('team_registration_id') team_registration_id = metadata.get('team_registration_id')
registration_type = metadata.get('registration_type') registration_type = metadata.get('registration_type')
if tournament_id and registration_type == 'cart': # Wrap all database operations in an atomic transaction
try: # This ensures either all changes are saved or none are
tournament = Tournament.objects.get(id=tournament_id)
tournament.reserved_spots = max(0, tournament.reserved_spots - 1)
tournament.save()
print(f"Decreased reserved spots for tournament {tournament_id} after payment failure")
except Tournament.DoesNotExist:
print(f"Tournament not found with ID: {tournament_id}")
except Exception as e:
print(f"Error saving tournament for team registration: {str(e)}")
if not team_registration_id:
print("No team registration ID found in session")
return False
try: try:
print(f"Looking for team registration with ID: {team_registration_id}") with transaction.atomic():
team_registration = TeamRegistration.objects.get(id=team_registration_id) if tournament_id and registration_type == 'cart':
if tournament_id and registration_type == 'cart' and team_registration.tournament is None: try:
try: tournament = Tournament.objects.get(id=tournament_id)
tournament = Tournament.objects.get(id=tournament_id) tournament.reserved_spots = max(0, tournament.reserved_spots - 1)
team_registration.tournament = tournament tournament.save()
team_registration.save() print(f"Decreased reserved spots for tournament {tournament_id}")
print(f"Saved tournament for team registration {team_registration.id}") except Tournament.DoesNotExist:
except Tournament.DoesNotExist: print(f"Tournament not found with ID: {tournament_id}")
print(f"Tournament not found with ID: {tournament_id}") except Exception as e:
except Exception as e: print(f"Error saving tournament for team registration: {str(e)}")
print(f"Error saving tournament for team registration: {str(e)}")
if not team_registration_id:
if team_registration.is_paid(): print("No team registration ID found in session")
return True return False
team_registration.confirm_registration(checkout_session.payment_intent) print(f"Looking for team registration with ID: {team_registration_id}")
team_registration = TeamRegistration.objects.get(id=team_registration_id)
if tournament_id and registration_type == 'cart' and team_registration.tournament is None:
try:
tournament = Tournament.objects.get(id=tournament_id)
team_registration.tournament = tournament
team_registration.save()
print(f"Saved tournament for team registration {team_registration.id}")
except Tournament.DoesNotExist:
print(f"Tournament not found with ID: {tournament_id}")
except Exception as e:
print(f"Error saving tournament for team registration: {str(e)}")
if team_registration.is_paid():
print(f"Team registration {team_registration.id} is already paid")
return True
# Update player registration with payment info
team_registration.confirm_registration(checkout_session.payment_intent)
print(f"✅ Registration confirmed and committed to database")
TournamentEmailService.send_payment_confirmation(team_registration, checkout_session.payment_intent)
return True
except TeamRegistration.DoesNotExist: except TeamRegistration.DoesNotExist:
print(f"Team registration not found with ID: {team_registration_id}") print(f"Team registration not found with ID: {team_registration_id}")
return False
except Exception as e: except Exception as e:
print(f"Error in _process_direct_payment: {str(e)}") print(f"❌ Error in process_direct_payment database operations: {str(e)}")
return False traceback.print_exc()
return False
# After successful database commit, send confirmation email
# Email failures won't affect the payment confirmation
try:
print(f"Sending payment confirmation email...")
TournamentEmailService.send_payment_confirmation(team_registration, checkout_session.payment_intent)
print(f"✅ Email sent successfully")
except Exception as email_error:
print(f" Warning: Email sending failed but payment was confirmed: {str(email_error)}")
traceback.print_exc()
# Don't return False - payment is still confirmed
return True
@staticmethod @staticmethod
@csrf_exempt @csrf_exempt

Loading…
Cancel
Save