Compare commits
3 Commits
7f540e8bb5
...
b79d5a5aca
Author | SHA1 | Date | |
---|---|---|---|
b79d5a5aca | |||
1fb8e3fa81 | |||
2820752248 |
17
src/Controller/SuccessController.php
Normal file
17
src/Controller/SuccessController.php
Normal 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');
|
||||||
|
}
|
||||||
|
}
|
@ -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)]
|
||||||
|
@ -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
13
src/Enum/FoodData.php
Normal 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'
|
||||||
|
];
|
||||||
|
}
|
32
src/Service/TicketEmailService.php
Normal file
32
src/Service/TicketEmailService.php
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
@ -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
30
src/Twig/Ticket.php
Normal 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'];
|
||||||
|
}
|
||||||
|
}
|
28
templates/email/order.html.twig
Normal file
28
templates/email/order.html.twig
Normal 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>
|
Loading…
x
Reference in New Issue
Block a user