from django.shortcuts import get_object_or_404, redirect from django.conf import settings from django.urls import reverse from django.contrib import messages import stripe from ..models import TeamRegistration, PlayerRegistration, Tournament from ..models.player_registration import PlayerPaymentType, RegistrationStatus from .email_service import TournamentEmailService from .tournament_registration import RegistrationCartManager from ..utils.extensions import is_not_sqlite_backend class PaymentService: """ Service for handling payment processing for tournament registrations """ def __init__(self, request): self.request = request self.stripe_api_key = settings.STRIPE_SECRET_KEY def create_checkout_session(self, tournament_id, team_fee, cart_data=None, team_registration_id=None): """ Create a Stripe checkout session for tournament payment """ stripe.api_key = self.stripe_api_key tournament = get_object_or_404(Tournament, id=tournament_id) # Get user email if authenticated customer_email = self.request.user.email if self.request.user.is_authenticated else None # Determine the appropriate cancel URL based on the context if team_registration_id: # If we're paying for an existing registration, go back to tournament info cancel_url = self.request.build_absolute_uri( reverse('tournament-info', kwargs={'tournament_id': tournament_id}) ) else: # If we're in the registration process, go back to registration form cancel_url = self.request.build_absolute_uri( reverse('register_tournament', kwargs={'tournament_id': tournament_id}) ) # Common checkout session parameters checkout_session_params = { 'payment_method_types': ['card'], 'line_items': [{ 'price_data': { 'currency': 'eur', 'product_data': { 'name': f'{tournament.broadcast_display_name()} du {tournament.formatted_start_date()}', 'description': f'Lieu {tournament.event.club.name}', }, 'unit_amount': int(team_fee * 100), # Amount in cents }, 'quantity': 1, }], 'mode': 'payment', 'success_url': self.request.build_absolute_uri( reverse('tournament-payment-success', kwargs={'tournament_id': tournament_id}) ), 'cancel_url': cancel_url, 'metadata': { 'tournament_id': str(tournament_id), # Convert UUID to string 'user_id': str(self.request.user.id) if self.request.user.is_authenticated else None, # Convert UUID to string 'source_page': 'tournament_info' if team_registration_id else 'register_tournament', } } # Add cart or team data to metadata based on payment context if cart_data: checkout_session_params['metadata']['registration_cart_id'] = str(cart_data['cart_id']) # Convert to string elif team_registration_id: checkout_session_params['metadata']['team_registration_id'] = str(team_registration_id) # Convert to string self.request.session['team_registration_id'] = str(team_registration_id) # Convert to string # Add customer_email if available if customer_email: checkout_session_params['customer_email'] = customer_email # Create the checkout session checkout_session = stripe.checkout.Session.create(**checkout_session_params) # Store checkout session ID and source page in session self.request.session['stripe_checkout_session_id'] = checkout_session.id self.request.session['payment_source_page'] = 'tournament_info' if team_registration_id else 'register_tournament' self.request.session.modified = True return checkout_session def process_successful_payment(self, tournament_id, checkout_session): """ Process a successful Stripe payment Returns a tuple (success, redirect_response) """ print(f"Processing payment for tournament {tournament_id}") tournament = get_object_or_404(Tournament, id=tournament_id) # Check if this is a payment for an existing team registration team_registration_id = self.request.session.get('team_registration_id') print(f"Team registration ID from session: {team_registration_id}") # Track payment statuses for debugging payment_statuses = [] if team_registration_id: success = self._process_direct_payment(checkout_session) payment_statuses.append(success) print(f"Direct payment processing result: {success}") else: # This is a payment during registration process success = self._process_registration_payment(tournament, checkout_session) payment_statuses.append(success) print(f"Registration payment processing result: {success}") # Print combined payment status print(f"Payment statuses: {payment_statuses}") print(any(payment_statuses)) # Clear checkout session ID if 'stripe_checkout_session_id' in self.request.session: del self.request.session['stripe_checkout_session_id'] return any(payment_statuses) def _process_direct_payment(self, checkout_session): """Process payment for an existing team registration""" team_registration_id = self.request.session.get('team_registration_id') if not team_registration_id: print("No team registration ID found in session") return False try: print(f"Looking for team registration with ID: {team_registration_id}") team_registration = TeamRegistration.objects.get(id=team_registration_id) success = self._update_registration_payment_info( team_registration, checkout_session.payment_intent ) # Clean up session if 'team_registration_id' in self.request.session: del self.request.session['team_registration_id'] return success except TeamRegistration.DoesNotExist: print(f"Team registration not found with ID: {team_registration_id}") return False except Exception as e: print(f"Error in _process_direct_payment: {str(e)}") return False def _process_registration_payment(self, tournament, checkout_session): """Process payment made during registration""" cart_manager = RegistrationCartManager(self.request) cart_data = cart_manager.get_cart_data() # Checkout and create registration success, result = cart_manager.checkout() if not success: return False # Process payment for the new registration team_registration = result # result is team_registration object self._update_registration_payment_info( team_registration, checkout_session.payment_intent ) # Send confirmation email if appropriate waiting_list_position = cart_data.get('waiting_list_position', -1) if is_not_sqlite_backend(): email_service = TournamentEmailService() email_service.send_registration_confirmation( self.request, tournament, team_registration, waiting_list_position ) return True def _update_registration_payment_info(self, team_registration, payment_intent_id): """Update player registrations with payment information""" player_registrations = PlayerRegistration.objects.filter(team_registration=team_registration) for player_reg in player_registrations: player_reg.payment_type = PlayerPaymentType.CREDIT_CARD player_reg.registration_status = RegistrationStatus.CONFIRMED player_reg.payment_id = payment_intent_id player_reg.save() return True