Handle 3DS redirect: generate tickets on success, show error on failure
- Check redirect_status query param on confirmation page
- On succeeded: generate BilletOrders + send email with PDF tickets
- On failed: show error with retry button
- Success page links to /ma-commande/{reference} for ticket download
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -185,18 +185,28 @@ class OrderController extends AbstractController
|
||||
}
|
||||
|
||||
#[Route('/commande/{id}/confirmation', name: 'app_order_success', requirements: ['id' => '\d+'], methods: ['GET'])]
|
||||
public function success(int $id, EntityManagerInterface $em): Response
|
||||
public function success(int $id, Request $request, EntityManagerInterface $em, BilletOrderService $billetOrderService): Response
|
||||
{
|
||||
$order = $em->getRepository(BilletBuyer::class)->find($id);
|
||||
if (!$order) {
|
||||
throw $this->createNotFoundException();
|
||||
}
|
||||
|
||||
$redirectStatus = $request->query->getString('redirect_status');
|
||||
|
||||
if ('succeeded' === $redirectStatus && BilletBuyer::STATUS_PENDING === $order->getStatus()) {
|
||||
$billetOrderService->generateOrderTickets($order);
|
||||
$billetOrderService->generateAndSendTickets($order);
|
||||
}
|
||||
|
||||
$failed = 'failed' === $redirectStatus;
|
||||
|
||||
return $this->render('order/success.html.twig', [
|
||||
'order' => $order,
|
||||
'failed' => $failed,
|
||||
'breadcrumbs' => [
|
||||
['name' => 'Accueil', 'url' => '/'],
|
||||
['name' => 'Confirmation'],
|
||||
['name' => $failed ? 'Echec' : 'Confirmation'],
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -1,35 +1,49 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Confirmation - E-Ticket{% endblock %}
|
||||
{% block title %}{{ failed|default(false) ? 'Echec' : 'Confirmation' }} - E-Ticket{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="page-container">
|
||||
<div class="max-w-xl mx-auto text-center">
|
||||
<div class="card-brutal p-8">
|
||||
<div class="text-6xl mb-4">✓</div>
|
||||
<h1 class="text-3xl font-black uppercase tracking-tighter italic heading-page mb-4">Commande confirmee</h1>
|
||||
<p class="font-bold text-gray-600 mb-2">Merci {{ order.firstName }} !</p>
|
||||
<p class="text-sm font-bold text-gray-500 mb-6">Votre commande <span class="font-mono text-gray-900">{{ order.reference }}</span> a bien ete enregistree.</p>
|
||||
{% if failed|default(false) %}
|
||||
<div class="text-6xl mb-4 text-red-600">✗</div>
|
||||
<h1 class="text-3xl font-black uppercase tracking-tighter italic heading-page mb-4">Paiement echoue</h1>
|
||||
<p class="font-bold text-gray-600 mb-6">Le paiement n'a pas abouti. Vous pouvez reessayer.</p>
|
||||
<a href="{{ path('app_order_payment', {id: order.id}) }}" class="btn-brutal font-black uppercase text-sm tracking-widest bg-indigo-600 text-white hover:bg-indigo-800 transition-all">
|
||||
Reessayer le paiement
|
||||
</a>
|
||||
{% else %}
|
||||
<div class="text-6xl mb-4 text-green-600">✓</div>
|
||||
<h1 class="text-3xl font-black uppercase tracking-tighter italic heading-page mb-4">Commande confirmee</h1>
|
||||
<p class="font-bold text-gray-600 mb-2">Merci {{ order.firstName }} !</p>
|
||||
<p class="text-sm font-bold text-gray-500 mb-6">Votre commande <span class="font-mono text-gray-900">{{ order.orderNumber }}</span> a bien ete enregistree.</p>
|
||||
|
||||
<div class="border-2 border-gray-900 p-4 bg-gray-50 text-left mb-6">
|
||||
<p class="text-xs font-black uppercase tracking-widest text-gray-500 mb-2">Details</p>
|
||||
{% for item in order.items %}
|
||||
<div class="flex justify-between py-1 text-sm font-bold">
|
||||
<span>{{ item.billetName }} x{{ item.quantity }}</span>
|
||||
<span>{{ item.lineTotalHTDecimal|number_format(2, ',', ' ') }} €</span>
|
||||
<div class="border-2 border-gray-900 p-4 bg-gray-50 text-left mb-6">
|
||||
<p class="text-xs font-black uppercase tracking-widest text-gray-500 mb-2">Details</p>
|
||||
{% for item in order.items %}
|
||||
<div class="flex justify-between py-1 text-sm font-bold">
|
||||
<span>{{ item.billetName }} x{{ item.quantity }}</span>
|
||||
<span>{{ item.lineTotalHTDecimal|number_format(2, ',', ' ') }} €</span>
|
||||
</div>
|
||||
{% endfor %}
|
||||
<div class="flex justify-between pt-2 mt-2 border-t-2 border-gray-900 font-black">
|
||||
<span>Total</span>
|
||||
<span class="text-indigo-600">{{ order.totalHTDecimal|number_format(2, ',', ' ') }} €</span>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
<div class="flex justify-between pt-2 mt-2 border-t-2 border-gray-900 font-black">
|
||||
<span>Total</span>
|
||||
<span class="text-indigo-600">{{ order.totalHTDecimal|number_format(2, ',', ' ') }} €</span>
|
||||
|
||||
<p class="text-xs font-bold text-gray-400 mb-6">Vos billets ont ete envoyes a {{ order.email }}</p>
|
||||
|
||||
<div class="flex flex-col gap-3">
|
||||
<a href="{{ path('app_order_public', {reference: order.reference}) }}" class="btn-brutal font-black uppercase text-sm tracking-widest hover:bg-indigo-600 hover:text-white transition-all">
|
||||
Voir ma commande
|
||||
</a>
|
||||
<a href="{{ path('app_home') }}" class="text-sm font-bold text-gray-500 hover:text-gray-900 transition-colors">
|
||||
Retour a l'accueil
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="text-xs font-bold text-gray-400 mb-6">Un email de confirmation sera envoye a {{ order.email }}</p>
|
||||
|
||||
<a href="{{ path('app_home') }}" class="btn-brutal font-black uppercase text-sm tracking-widest hover:bg-indigo-600 hover:text-white transition-all">
|
||||
Retour a l'accueil
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user