diff --git a/app/controllers/api/v1/events_controller.rb b/app/controllers/api/v1/events_controller.rb index 608b11f..074edae 100755 --- a/app/controllers/api/v1/events_controller.rb +++ b/app/controllers/api/v1/events_controller.rb @@ -65,7 +65,8 @@ module Api render json: { status: "success", message: "Cart stored successfully" } rescue => e - Rails.logger.error "Error storing cart: #{e.message}" + error_message = e.message.present? ? e.message : "Erreur inconnue" + Rails.logger.error "Error storing cart: #{error_message}" render json: { status: "error", message: "Failed to store cart" }, status: 500 end diff --git a/app/controllers/events_controller.rb b/app/controllers/events_controller.rb index 0005efe..64a3cb9 100755 --- a/app/controllers/events_controller.rb +++ b/app/controllers/events_controller.rb @@ -5,7 +5,7 @@ class EventsController < ApplicationController include StripeConcern - before_action :authenticate_user!, only: [ :checkout, :process_names, :payment_success, :download_ticket ] + before_action :authenticate_user!, only: [ :checkout, :process_names, :download_ticket ] before_action :set_event, only: [ :show, :checkout, :process_names ] # Display all events @@ -92,77 +92,6 @@ class EventsController < ApplicationController end - # Handle successful payment - def payment_success - session_id = params[:session_id] - event_id = params[:event_id] - - # Check if Stripe is properly configured - stripe_configured = Rails.application.config.stripe[:secret_key].present? - Rails.logger.debug "Payment success - Stripe configured: #{stripe_configured}" - - unless stripe_configured - redirect_to dashboard_path, alert: "Le système de paiement n'est pas correctement configuré. Veuillez contacter l'administrateur." - return - end - - # Stripe is now initialized at application startup, no need to initialize here - Rails.logger.debug "Payment success - Using globally initialized Stripe" - - begin - session = Stripe::Checkout::Session.retrieve(session_id) - - if session.payment_status == "paid" - # Create tickets - @event = Event.find(event_id) - order_items = JSON.parse(session.metadata["order_items"]) - @tickets = [] - - # Get names from session if they exist - ticket_names = session.metadata["ticket_names"] ? JSON.parse(session.metadata["ticket_names"]) : {} - - order_items.each do |item| - ticket_type = TicketType.find(item["ticket_type_id"]) - item["quantity"].times do |i| - # Get names if this ticket type requires them - first_name = nil - last_name = nil - - if ticket_type.requires_id - name_key = "#{ticket_type.id}_#{i}" - names = ticket_names[name_key] || {} - first_name = names["first_name"] - last_name = names["last_name"] - end - - ticket = Ticket.create!( - user: current_user, - ticket_type: ticket_type, - status: "active", - first_name: first_name, - last_name: last_name - ) - @tickets << ticket - - # Send confirmation email for each ticket - TicketMailer.purchase_confirmation(ticket).deliver_now - end - end - - # Clear session data - session.delete(:pending_cart) - session.delete(:ticket_names) - - render "payment_success" - else - redirect_to event_path(@event.slug, @event), alert: "Le paiement n'a pas été complété avec succès" - end - rescue Stripe::StripeError => e - redirect_to dashboard_path, alert: "Erreur lors du traitement de votre confirmation de paiement : #{e.message}" - rescue => e - redirect_to dashboard_path, alert: "Une erreur inattendue s'est produite : #{e.message}" - end - end # Download ticket PDF def download_ticket @@ -267,7 +196,7 @@ class EventsController < ApplicationController payment_method_types: [ "card" ], line_items: line_items, mode: "payment", - success_url: payment_success_url(event_id: @event.id, session_id: "{CHECKOUT_SESSION_ID}"), + success_url: payment_success_url(session_id: "{CHECKOUT_SESSION_ID}"), cancel_url: event_url(@event.slug, @event), customer_email: current_user.email, metadata: { @@ -281,8 +210,9 @@ class EventsController < ApplicationController Rails.logger.debug "Redirecting to Stripe session URL: #{session.url}" redirect_to session.url, allow_other_host: true rescue Stripe::StripeError => e - Rails.logger.error "Stripe error: #{e.message}" - redirect_to event_path(@event.slug, @event), alert: "Erreur de traitement du paiement : #{e.message}" + error_message = e.message.present? ? e.message : "Erreur Stripe inconnue" + Rails.logger.error "Stripe error: #{error_message}" + redirect_to event_path(@event.slug, @event), alert: "Erreur de traitement du paiement : #{error_message}" end end end diff --git a/app/controllers/tickets_controller.rb b/app/controllers/tickets_controller.rb index 4847f71..51d5698 100644 --- a/app/controllers/tickets_controller.rb +++ b/app/controllers/tickets_controller.rb @@ -3,7 +3,7 @@ # This controller permit users to create a new ticket for an event, # complete their details and proceed to payment class TicketsController < ApplicationController - before_action :authenticate_user!, only: [ :new ] + before_action :authenticate_user!, only: [ :new, :payment_success, :payment_cancel ] before_action :set_event, only: [ :new ] # Handle new ticket creation @@ -84,7 +84,8 @@ class TicketsController < ApplicationController end end rescue => e - flash[:alert] = "Une erreur est survenue: #{e.message}" + error_message = e.message.present? ? e.message : "Erreur inconnue" + flash[:alert] = "Une erreur est survenue: #{error_message}" redirect_to ticket_new_path(params[:slug], params[:id]) end @@ -117,12 +118,83 @@ class TicketsController < ApplicationController begin @checkout_session = create_stripe_session rescue => e - Rails.logger.error "Stripe checkout session creation failed: #{e.message}" + error_message = e.message.present? ? e.message : "Erreur Stripe inconnue" + Rails.logger.error "Stripe checkout session creation failed: #{error_message}" flash[:alert] = "Erreur lors de la création de la session de paiement" end end end + # Handle successful payment + def payment_success + session_id = params[:session_id] + + # Check if Stripe is properly configured + stripe_configured = Rails.application.config.stripe[:secret_key].present? + Rails.logger.debug "Payment success - Stripe configured: #{stripe_configured}" + + unless stripe_configured + redirect_to dashboard_path, alert: "Le système de paiement n'est pas correctement configuré. Veuillez contacter l'administrateur." + return + end + + # Stripe is now initialized at application startup, no need to initialize here + Rails.logger.debug "Payment success - Using globally initialized Stripe" + + begin + stripe_session = Stripe::Checkout::Session.retrieve(session_id) + + if stripe_session.payment_status == "paid" + # Get event_id and ticket_ids from session metadata + event_id = stripe_session.metadata["event_id"] + ticket_ids_data = stripe_session.metadata["ticket_ids"] + + unless event_id.present? && ticket_ids_data.present? + redirect_to dashboard_path, alert: "Informations de commande manquantes" + return + end + + # Update existing draft tickets to active + @event = Event.find(event_id) + ticket_ids = ticket_ids_data.split(",") + @tickets = current_user.tickets.where(id: ticket_ids, status: "draft") + + if @tickets.empty? + redirect_to dashboard_path, alert: "Billets non trouvés" + return + end + + @tickets.update_all(status: "active") + + # Send confirmation emails + @tickets.each do |ticket| + TicketMailer.purchase_confirmation(ticket).deliver_now + end + + # Clear session data + session.delete(:pending_cart) + session.delete(:ticket_names) + session.delete(:draft_ticket_ids) + + render "payment_success" + else + redirect_to dashboard_path, alert: "Le paiement n'a pas été complété avec succès" + end + rescue Stripe::StripeError => e + error_message = e.message.present? ? e.message : "Erreur Stripe inconnue" + redirect_to dashboard_path, alert: "Erreur lors du traitement de votre confirmation de paiement : #{error_message}" + rescue => e + error_message = e.message.present? ? e.message : "Erreur inconnue" + Rails.logger.error "Payment success error: #{e.class} - #{error_message}" + redirect_to dashboard_path, alert: "Une erreur inattendue s'est produite : #{error_message}" + end + end + + # Handle payment failure/cancellation + def payment_cancel + redirect_to dashboard_path, alert: "Le paiement a été annulé" + end + def show @ticket = current_user.tickets.includes(:ticket_type, :event).find(params[:ticket_id]) @event = @ticket.event @@ -160,7 +232,7 @@ class TicketsController < ApplicationController line_items: line_items, mode: "payment", success_url: payment_success_url + "?session_id={CHECKOUT_SESSION_ID}", - cancel_url: ticket_checkout_url(@event.slug, @event.id), + cancel_url: payment_cancel_url, metadata: { event_id: @event.id, user_id: current_user.id, diff --git a/app/javascript/controllers/flash_message_controller.js b/app/javascript/controllers/flash_message_controller.js index f23188f..01c6914 100755 --- a/app/javascript/controllers/flash_message_controller.js +++ b/app/javascript/controllers/flash_message_controller.js @@ -1,41 +1,46 @@ -import { Controller } from "@hotwired/stimulus" +import { Controller } from "@hotwired/stimulus"; // Controller for handling flash messages // Automatically dismisses messages after a timeout and handles manual closing export default class extends Controller { // Define targets for the controller - static targets = ["message"] + static targets = ["message"]; // Initialize the controller when it connects to the DOM connect() { - console.log("FlashMessageController mounted", this.element); + // console.log("FlashMessageController mounted", this.element); + console.log("FlashMessageController mounted"); // Initialize Lucide icons for this element if available - if (typeof lucide !== 'undefined') { + if (typeof lucide !== "undefined") { lucide.createIcons({ within: this.element }); } // Auto-dismiss after 2 seconds this.timeout = setTimeout(() => { - this.close() - }, 5000) + this.close(); + }, 5000); } // Clean up the timeout when the controller disconnects disconnect() { if (this.timeout) { - clearTimeout(this.timeout) + clearTimeout(this.timeout); } } // Close the flash message with a fade-out animation close() { // Add opacity transition classes - this.element.classList.add('opacity-0', 'transition-opacity', 'duration-300') + this.element.classList.add( + "opacity-0", + "transition-opacity", + "duration-300", + ); // Remove element after transition completes setTimeout(() => { - this.element.remove() - }, 300) + this.element.remove(); + }, 300); } } diff --git a/app/views/tickets/checkout.html.erb b/app/views/tickets/checkout.html.erb index f587b81..3044083 100644 --- a/app/views/tickets/checkout.html.erb +++ b/app/views/tickets/checkout.html.erb @@ -110,20 +110,63 @@ -