Add billing system: subscription, webhooks, and access control
- Add billing fields to User (isBilling, billingAmount, billingState, billingStripeSubscriptionId) and OrganizerInvitation (billingAmount) - Registration: organizer gets billingState="poor" (pending review) - Admin approval: sets isBilling=true, billingAmount from form, state="good" - Invitation: billingAmount from invitation, if 0 then isBilling=false - ROLE_ROOT accounts: billing free (amount=0, state="good") - Block Stripe Connect creation and all organizer features if state is "poor" or "suspendu" - Hide Stripe configuration section if billing not settled - Add billing checkout via Stripe subscription with success route - Webhooks: checkout.session.completed activates billing, invoice.payment_failed and customer.subscription.deleted suspend account and disable online events - Show billing alert on /mon-compte with amount and subscribe button - Display billing info in invitation email and landing page - Add email templates for billing activated/failed/cancelled Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -30,7 +30,21 @@
|
||||
|
||||
{% else %}
|
||||
|
||||
{% if isOrganizer %}
|
||||
{% if isOrganizer and app.user.billing and app.user.billingState != 'good' %}
|
||||
<div class="card-brutal-error p-8 text-center mb-8">
|
||||
<div class="text-4xl mb-4">⚠</div>
|
||||
{% if app.user.billingState == 'suspendu' %}
|
||||
<h2 class="text-xl font-black uppercase tracking-tighter italic mb-2">Abonnement suspendu</h2>
|
||||
<p class="font-bold text-gray-700 text-sm mb-4">Votre abonnement a ete suspendu suite a un echec de paiement. Vos evenements ne sont plus accessibles. Regularisez votre situation pour reactiver votre compte.</p>
|
||||
{% else %}
|
||||
<h2 class="text-xl font-black uppercase tracking-tighter italic mb-2">Abonnement requis</h2>
|
||||
<p class="font-bold text-gray-700 text-sm mb-4">Vous devez regler les frais de votre abonnement pour utiliser notre plateforme. Votre abonnement mensuel est de <strong>{{ (app.user.billingAmount / 100)|number_format(2, ',', ' ') }} €</strong>.</p>
|
||||
{% endif %}
|
||||
<a href="{{ path('app_account_billing_subscribe') }}" class="btn-brutal font-black uppercase text-xs tracking-widest hover:bg-indigo-600 hover:text-black transition-all">Regler mon abonnement</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if isOrganizer and (not app.user.billing or app.user.billingState == 'good') %}
|
||||
{% if not app.user.stripeAccountId %}
|
||||
<div class="card-brutal-warn mb-8">
|
||||
<h2 class="text-sm font-black uppercase tracking-widest mb-2">Configuration Stripe requise
|
||||
|
||||
12
templates/email/billing_activated.html.twig
Normal file
12
templates/email/billing_activated.html.twig
Normal file
@@ -0,0 +1,12 @@
|
||||
{% extends 'email/base.html.twig' %}
|
||||
|
||||
{% block title %}Abonnement active{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h2>Bonjour {{ firstName }},</h2>
|
||||
<p>Votre abonnement E-Ticket de <strong>{{ amount }} €/mois</strong> a ete active avec succes.</p>
|
||||
<p>Vous pouvez desormais utiliser toutes les fonctionnalites de la plateforme.</p>
|
||||
<p style="text-align:center;margin:32px 0;">
|
||||
<a href="{{ url('app_account') }}" class="btn">Acceder a mon compte</a>
|
||||
</p>
|
||||
{% endblock %}
|
||||
12
templates/email/billing_cancelled.html.twig
Normal file
12
templates/email/billing_cancelled.html.twig
Normal file
@@ -0,0 +1,12 @@
|
||||
{% extends 'email/base.html.twig' %}
|
||||
|
||||
{% block title %}Abonnement annule{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h2>Bonjour {{ firstName }},</h2>
|
||||
<p>Votre abonnement E-Ticket a ete <strong>annule</strong>.</p>
|
||||
<p>Votre compte organisateur est suspendu. Pour reactiver vos services, souscrivez a un nouvel abonnement depuis votre espace.</p>
|
||||
<p style="text-align:center;margin:32px 0;">
|
||||
<a href="{{ url('app_account') }}" class="btn">Acceder a mon compte</a>
|
||||
</p>
|
||||
{% endblock %}
|
||||
13
templates/email/billing_failed.html.twig
Normal file
13
templates/email/billing_failed.html.twig
Normal file
@@ -0,0 +1,13 @@
|
||||
{% extends 'email/base.html.twig' %}
|
||||
|
||||
{% block title %}Echec de paiement{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h2>Bonjour {{ firstName }},</h2>
|
||||
<p>Le paiement de votre abonnement E-Ticket a <strong>echoue</strong>.</p>
|
||||
<p>Votre compte organisateur est suspendu jusqu'a la regularisation du paiement. Veuillez mettre a jour votre moyen de paiement.</p>
|
||||
<p>Si vous pensez qu'il s'agit d'une erreur, contactez <a href="mailto:contact@e-cosplay.fr">contact@e-cosplay.fr</a>.</p>
|
||||
<p style="text-align:center;margin:32px 0;">
|
||||
<a href="{{ url('app_account') }}" class="btn">Acceder a mon compte</a>
|
||||
</p>
|
||||
{% endblock %}
|
||||
@@ -16,6 +16,15 @@
|
||||
avec un taux de commission de {{ invitation.commissionRate }}%
|
||||
{% endif %}
|
||||
</p>
|
||||
{% if invitation.billingAmount is not null %}
|
||||
<p style="margin: 8px 0 0; font-size: 13px; font-weight: 700; color: #111827;">
|
||||
{% if invitation.billingAmount == 0 %}
|
||||
Aucun abonnement mensuel — utilisation gratuite de la plateforme.
|
||||
{% else %}
|
||||
Abonnement mensuel : <strong>{{ (invitation.billingAmount / 100)|number_format(2, ',', ' ') }} €/mois</strong>
|
||||
{% endif %}
|
||||
</p>
|
||||
{% endif %}
|
||||
<p style="margin: 6px 0 0; font-size: 12px; font-weight: 700; color: #374151;">(hors frais de commission Stripe)</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
@@ -27,6 +27,15 @@
|
||||
{% if invitation.commissionRate is not null %}
|
||||
<p class="text-sm font-bold text-gray-400 mt-1">Taux de commission E-Ticket : {{ invitation.commissionRate }}% <span class="text-gray-500">(hors frais Stripe)</span></p>
|
||||
{% endif %}
|
||||
{% if invitation.billingAmount is not null %}
|
||||
<p class="text-sm font-bold mt-3">
|
||||
{% if invitation.billingAmount == 0 %}
|
||||
<span class="text-green-400">Aucun abonnement mensuel — utilisation gratuite</span>
|
||||
{% else %}
|
||||
<span class="text-[#fabf04]">Abonnement mensuel : {{ (invitation.billingAmount / 100)|number_format(2, ',', ' ') }} €/mois</span>
|
||||
{% endif %}
|
||||
</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</section>
|
||||
{% endif %}
|
||||
|
||||
Reference in New Issue
Block a user