SubscriptionController
extends AbstractController
in package
Contrôleur du parcours de souscription à l'abonnement Pro pour un utilisateur final.
Il expose la page de choix du cycle de facturation (mensuel / annuel), crée l'abonnement
et le paiement associés au statut « en attente », puis délègue l'encaissement à Stripe
(le canal Orange Money est présent mais volontairement désactivé). L'identifiant de
l'abonnement en attente transite par la session HTTP (pending_subscription_id) entre
la redirection vers Stripe et le retour sur les routes de succès ou d'annulation.
L'accès à la souscription est conditionné par SubscriptionService::canUpgrade() :
un utilisateur possédant déjà un abonnement payant actif est renvoyé vers sa liste de cartes.
Aucun préfixe de route au niveau de la classe. Réservé à ROLE_USER.
Attributes
- #[IsGranted]
- 'ROLE_USER'
Table of Contents
Properties
- $entityManager : EntityManagerInterface
- $mailerService : MailerService
- $stripeService : StripeService
- $subscriptionService : SubscriptionService
Methods
- __construct() : mixed
- processUpgradeToPro() : Response
- Traite l'upgrade vers Pro avec la méthode de paiement sélectionnée
- subscriptionCancel() : Response
- Gère l'annulation du paiement
- subscriptionDetails() : Response
- Affiche les détails de l'abonnement actuel
- subscriptionSuccess() : Response
- Gère le succès du paiement et active l'abonnement
- upgradeToProPage() : Response
- Affiche la page de sélection du plan Pro avec les options de paiement
- processCreditCardPayment() : Response
- Traite le paiement par carte bancaire via Stripe
- processOrangeMoneyPayment() : Response
- Traite le paiement Orange Money pour l'abonnement Pro
Properties
$entityManager
private
EntityManagerInterface
$entityManager
$mailerService
private
MailerService
$mailerService
$stripeService
private
StripeService
$stripeService
$subscriptionService
private
SubscriptionService
$subscriptionService
Methods
__construct()
public
__construct(EntityManagerInterface $entityManager, SubscriptionService $subscriptionService, StripeService $stripeService, MailerService $mailerService) : mixed
Parameters
- $entityManager : EntityManagerInterface
-
Gestionnaire Doctrine utilisé pour la persistance des entités Subscription et Payment ainsi que pour les transactions explicites.
- $subscriptionService : SubscriptionService
-
Service métier des abonnements : contrôle d'éligibilité à l'upgrade et activation d'un abonnement.
- $stripeService : StripeService
-
Passerelle Stripe utilisée pour créer les sessions de paiement Checkout.
- $mailerService : MailerService
-
Service d'envoi des e-mails transactionnels (confirmation d'abonnement).
processUpgradeToPro()
Traite l'upgrade vers Pro avec la méthode de paiement sélectionnée
public
processUpgradeToPro(Request $request, SessionInterface $session) : Response
Recontrôle l'éligibilité de l'utilisateur (SubscriptionService::canUpgrade())
et la présence du plan Pro. Crée ensuite, à l'intérieur d'une transaction Doctrine explicite,
une Subscription au statut Subscription::STATUS_PENDING (cycle mensuel ou annuel,
montant, date de début à maintenant, renouvellement automatique activé) et un Payment
au statut Payment::PENDING_STATUS. L'identifiant de l'abonnement est mémorisé en session
sous la clé pending_subscription_id pour être relu au retour de Stripe. Le champ POST
payment_method aiguille ensuite vers self::processOrangeMoneyPayment() ou
self::processCreditCardPayment() ; toute autre valeur lève une exception.
En cas d'exception (quelle qu'en soit l'origine), la transaction est annulée (rollback),
un flash error contenant le message est posé et l'utilisateur revient sur le formulaire.
À noter : le commit n'a lieu qu'après l'appel de la méthode de paiement, qui retourne
généralement une redirection.
Route : /upgrade-to-pro/process (POST), nom app_subscription_upgrade_to_pro_process.
Parameters
- $request : Request
-
Requête POST portant
payment_method,billing_cycleet, le cas échéant,orange_money_number. - $session : SessionInterface
-
Session HTTP servant à stocker
pending_subscription_id.
Attributes
- #[Route]
- '/upgrade-to-pro/process'
- $name: 'app_subscription_upgrade_to_pro_process'
- $methods: ['POST']
Return values
Response —Redirection vers Stripe Checkout (carte bancaire), redirection vers
app_subscription_upgrade_to_pro (Orange Money indisponible, erreur de
traitement ou plan manquant) ou vers app_cards_list (abonnement déjà actif).
subscriptionCancel()
Gère l'annulation du paiement
public
subscriptionCancel(SessionInterface $session) : Response
Page de retour appelée par Stripe lorsque l'utilisateur abandonne le paiement. Si la clé de
session pending_subscription_id existe, l'abonnement correspondant est chargé et, s'il est
toujours au statut Subscription::STATUS_PENDING, il est basculé en
Subscription::STATUS_CANCELLED avec horodatage d'annulation et motif
« Paiement annulé par l'utilisateur », puis persisté. La clé de session est retirée dans tous
les cas où elle était présente. Le paiement en attente associé n'est en revanche pas modifié.
Route : /subscription/cancel (toutes méthodes), nom app_subscription_cancel.
Parameters
- $session : SessionInterface
-
Session HTTP contenant éventuellement
pending_subscription_id.
Attributes
- #[Route]
- '/subscription/cancel'
- $name: 'app_subscription_cancel'
Return values
Response —Rendu de subscription/cancel.html.twig, précédé d'un flash info.
subscriptionDetails()
Affiche les détails de l'abonnement actuel
public
subscriptionDetails() : Response
Récupère l'abonnement actif de l'utilisateur connecté via User::getActiveSubscription()
et le transmet au template. Aucune vérification supplémentaire n'est faite : la valeur
transmise peut être null si l'utilisateur n'a aucun abonnement actif, le template devant
gérer ce cas.
Route : /subscription/details (toutes méthodes), nom app_subscription_details.
Attributes
- #[Route]
- '/subscription/details'
- $name: 'app_subscription_details'
Return values
Response —Rendu de subscription/details.html.twig avec l'abonnement actif et l'utilisateur.
subscriptionSuccess()
Gère le succès du paiement et active l'abonnement
public
subscriptionSuccess(SessionInterface $session) : Response
Page de retour appelée par Stripe après un paiement. Relit pending_subscription_id en session
puis charge l'abonnement correspondant ; en cas de clé absente ou d'abonnement introuvable,
un flash error est posé et l'utilisateur est redirigé vers app_cards_list.
Attention : le paiement n'est pas revérifié auprès de Stripe, le simple accès à cette route
déclenche l'activation via SubscriptionService::activateSubscription()
(qui annule l'éventuel abonnement précédent et calcule les dates de fin et de prochaine
facturation). Le premier Payment en statut Payment::PENDING_STATUS de
l'utilisateur — et non celui explicitement créé lors de l'upgrade — passe alors en
Payment::COMPLETED_STATUS. La clé de session est ensuite supprimée et un e-mail de
confirmation est envoyé. Toute exception d'activation ou d'envoi d'e-mail est convertie
en flash error sans interrompre le rendu de la page.
Route : /subscription/success (toutes méthodes), nom app_subscription_success.
Parameters
- $session : SessionInterface
-
Session HTTP contenant
pending_subscription_id.
Attributes
- #[Route]
- '/subscription/success'
- $name: 'app_subscription_success'
Return values
Response —Rendu de subscription/success.html.twig avec l'abonnement, ou redirection
vers app_cards_list si aucun abonnement en attente n'est retrouvé.
upgradeToProPage()
Affiche la page de sélection du plan Pro avec les options de paiement
public
upgradeToProPage(Request $request) : Response
Vérifie d'abord l'éligibilité de l'utilisateur courant via
SubscriptionService::canUpgrade() : s'il dispose déjà d'un abonnement
payant actif, un message flash info est ajouté et il est redirigé vers app_cards_list.
Charge ensuite le Plan dont le nom est exactement Pro ; en son absence, un flash
error est posé et l'utilisateur est renvoyé vers app_tarifs. Le cycle de facturation est
lu dans le paramètre de requête cycle (valeur par défaut monthly) et détermine le prix
affiché (tarif annuel si yearly, mensuel sinon). Aucune écriture en base n'est effectuée ici.
Route : /upgrade-to-pro (toutes méthodes), nom app_subscription_upgrade_to_pro.
Parameters
- $request : Request
-
Requête HTTP dont le paramètre de query
cycleporte le cycle souhaité.
Attributes
- #[Route]
- '/upgrade-to-pro'
- $name: 'app_subscription_upgrade_to_pro'
Return values
Response —Rendu de subscription/upgrade_to_pro.html.twig avec le plan, le cycle,
le prix et l'utilisateur ; ou une redirection vers app_cards_list
(abonnement déjà actif) ou app_tarifs (plan Pro absent).
processCreditCardPayment()
Traite le paiement par carte bancaire via Stripe
private
processCreditCardPayment(Subscription $subscription, Payment $payment, Request $request) : Response
Construit une ligne de facturation unique (quantité 1) libellée « gnf, dont le montant unitaire est le montant de l'abonnement converti en entier,
accompagnée du visuel BCard hébergé sur card.binn.pro. Positionne
Payment::CREDIT_CARD sur le paiement et effectue un flush, puis crée une session
Stripe Checkout via StripeService::createCheckoutSession() avec les URL
absolues de retour app_subscription_success et app_subscription_cancel. Aucun identifiant
de session Stripe n'est stocké en base : le rattachement au retour se fait uniquement via
la clé de session pending_subscription_id.
Parameters
- $subscription : Subscription
-
Abonnement en attente fournissant le plan, le cycle et le montant.
- $payment : Payment
-
Paiement en attente dont la méthode est mise à jour.
- $request : Request
-
Requête HTTP courante (non exploitée dans le corps de la méthode).
Tags
Return values
Response —Redirection HTTP vers l'URL de la session Stripe Checkout.
processOrangeMoneyPayment()
Traite le paiement Orange Money pour l'abonnement Pro
private
processOrangeMoneyPayment(Subscription $subscription, Payment $payment, string|null $orangeMoneyNumber) : Response
Exige un numéro Orange Money non vide, sans quoi une exception est levée (elle est rattrapée
par self::processUpgradeToPro() qui annule alors la transaction). Enregistre la méthode
de paiement Payment::ORANGE_MONEY sur le paiement puis effectue un flush.
Le canal Orange Money n'étant pas encore opérationnel, la méthode se termine systématiquement
par un flash info d'indisponibilité et une redirection vers le formulaire d'upgrade
en conservant le cycle de facturation de l'abonnement. L'abonnement reste donc « en attente ».
Parameters
- $subscription : Subscription
-
Abonnement en attente créé pour cet upgrade.
- $payment : Payment
-
Paiement en attente rattaché à l'utilisateur.
- $orangeMoneyNumber : string|null
-
Numéro Orange Money saisi dans le formulaire.
Tags
Return values
Response —Redirection vers app_subscription_upgrade_to_pro avec le cycle courant.