Compare commits

...

3 Commits

Author SHA1 Message Date
b79d5a5aca
wip 2025-02-04 22:32:29 +01:00
1fb8e3fa81
add some stuff 2025-02-04 22:32:29 +01:00
2820752248
add success email 2025-02-04 22:32:29 +01:00
8 changed files with 146 additions and 15 deletions

View File

@ -0,0 +1,17 @@
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
class SuccessController extends AbstractController
{
#[Route(path: '/success', name: 'app_success_page', methods: Request::METHOD_GET)]
public function __invoke(): Response
{
return $this->render('ticket/success.html.twig');
}
}

View File

@ -33,7 +33,7 @@ final class TicketController extends AbstractController
return $this->json(['id' => $this->service->handleTicketData($ticketData)->id]); return $this->json(['id' => $this->service->handleTicketData($ticketData)->id]);
} }
#[Route(path: '/success', name: 'app_success', methods: Request::METHOD_GET)] #[Route(path: '/success', name: 'app_order_success', methods: Request::METHOD_GET)]
public function success(Request $request): Response public function success(Request $request): Response
{ {
$sessionId = $request->query->get('session_id'); $sessionId = $request->query->get('session_id');
@ -50,7 +50,7 @@ final class TicketController extends AbstractController
return $this->redirectToRoute('app_ticket'); return $this->redirectToRoute('app_ticket');
} }
return $this->render('ticket/success.html.twig'); return $this->redirectToRoute('app_success_page');
} }
#[Route(path: '/cancelled', name: 'app_cancelled', methods: Request::METHOD_GET)] #[Route(path: '/cancelled', name: 'app_cancelled', methods: Request::METHOD_GET)]

View File

@ -2,6 +2,7 @@
namespace App\Entity; namespace App\Entity;
use App\Enum\TicketData;
use App\Repository\PaymentRepository; use App\Repository\PaymentRepository;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
@ -63,4 +64,11 @@ class Payment
return $this; return $this;
} }
public function getTotal(): float
{
return $this->customer->getTickets()
->map(fn (Ticket $ticket) => TicketData::TICKET_DATA[$ticket->getType()]['price'])
->reduce(fn (float $carry, float $price) => $carry + $price, 0);
}
} }

13
src/Enum/FoodData.php Normal file
View File

@ -0,0 +1,13 @@
<?php
declare(strict_types=1);
namespace App\Enum;
class FoodData
{
public const FOOD_DATA = [
1 => 'Mit Fleisch',
2 => 'Vegetarisch',
3 => 'Vegan'
];
}

View File

@ -0,0 +1,32 @@
<?php
declare(strict_types=1);
namespace App\Service;
use App\Entity\Payment;
use Symfony\Bridge\Twig\Mime\TemplatedEmail;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Mime\Address;
class TicketEmailService
{
public function __construct(
private readonly MailerInterface $mailer,
#[Autowire(env: 'SENDER_MAIL')]
private readonly string $senderMail
) {
}
public function sendSuccessEmail(Payment $payment): void
{
$mail = (new TemplatedEmail())
->htmlTemplate('email/order.html.twig')
->subject('Abiball Ticket')
->from(new Address($this->senderMail, 'Noreply'))
->to($payment->getCustomer()?->getEmail())
->context(['payment' => $payment]);
$this->mailer->send($mail);
}
}

View File

@ -21,6 +21,7 @@ class TicketService
private readonly UrlGeneratorInterface $generator, private readonly UrlGeneratorInterface $generator,
private readonly EntityManagerInterface $em, private readonly EntityManagerInterface $em,
private readonly PaymentRepository $paymentRepository, private readonly PaymentRepository $paymentRepository,
private readonly TicketEmailService $emailService,
#[Autowire(env: 'STRIPE_SECRET_KEY')] #[Autowire(env: 'STRIPE_SECRET_KEY')]
string $stripeKey string $stripeKey
) { ) {
@ -36,18 +37,6 @@ class TicketService
return $session; return $session;
} }
public function saveTicketData(TicketFormData $data, string $sessionId): void
{
$payment = (new Payment())
->setSessionId($sessionId)
->setCompleted(false)
->setCustomer($this->createEntityFromData($data));
$this->em->persist($payment);
$this->em->flush();
}
public function completePayment(string $sessionId): bool public function completePayment(string $sessionId): bool
{ {
if (!$payment = $this->paymentRepository->findOneBy(['sessionId' => $sessionId])) { if (!$payment = $this->paymentRepository->findOneBy(['sessionId' => $sessionId])) {
@ -56,10 +45,24 @@ class TicketService
$payment->setCompleted(true); $payment->setCompleted(true);
$this->em->flush(); $this->em->flush();
dd();
$this->emailService->sendSuccessEmail($payment);
return true; return true;
} }
private function saveTicketData(TicketFormData $data, string $sessionId): void
{
$payment = (new Payment())
->setSessionId($sessionId)
->setCompleted(false)
->setCustomer($this->createEntityFromData($data));
$this->em->persist($payment);
$this->em->flush();
}
private function getLineItems(array $tickets): array private function getLineItems(array $tickets): array
{ {
$lineItems = []; $lineItems = [];
@ -87,7 +90,7 @@ class TicketService
'line_items' => $lineItems, 'line_items' => $lineItems,
'mode' => 'payment', 'mode' => 'payment',
'customer_email' => $email, 'customer_email' => $email,
'success_url' => $this->generator->generate('app_success', [], 0) . '?session_id={CHECKOUT_SESSION_ID}', 'success_url' => $this->generator->generate('app_order_success', [], 0) . '?session_id={CHECKOUT_SESSION_ID}',
'cancel_url' => $this->generator->generate('app_cancelled', [], 0), 'cancel_url' => $this->generator->generate('app_cancelled', [], 0),
]); ]);
} }

30
src/Twig/Ticket.php Normal file
View File

@ -0,0 +1,30 @@
<?php
declare(strict_types=1);
namespace App\Twig;
use App\Enum\FoodData;
use App\Enum\TicketData;
use Twig\Extension\AbstractExtension;
use Twig\TwigFilter;
class Ticket extends AbstractExtension
{
public function getFilters(): array
{
return [
new TwigFilter('food', $this->getFoodName(...)),
new TwigFilter('ticket', $this->getTicket(...))
];
}
public function getFoodName(int $id): string
{
return FoodData::FOOD_DATA[$id] ?? 'N/A';
}
public function getTicket(int $id): array
{
return TicketData::TICKET_DATA[$id] ?? ['name' => 'N/A', 'price' => 'N/A'];
}
}

View File

@ -0,0 +1,28 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Abiball Ticket</title>
</head>
<body>
Hallo {{ payment.customer.firstname }}
<br>
placeholder text
<br>
<br>
<hr>
{% for ticket in payment.customer.tickets %}
Ticket: {{ (ticket.type | ticket)['name'] }} ({{ (ticket.type | ticket)['price'] }}€)
<br>
Essen: {{ ticket.foodType | food }}
<br>
{% if ticket.note %}
Anmerkung: {{ ticket.note }}
<br>
{% endif %}
<hr>
{% endfor %}
<br>
Gesamtpreis: {{ payment.total }}
</body>
</html>