<?php namespace App\Controller; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\Form\Form; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Translation\TranslatorInterface; use Payum\Core\Payum; use Payum\Core\Request\Notify; use Payum\Core\Request\GetHumanStatus; use App\Entity\Flux; use App\Entity\Payment; use App\Entity\User; use App\Entity\GlobalParameter; use Symfony\Component\Serializer\Normalizer\AbstractNormalizer; use App\Security\LoginAuthenticator; use Symfony\Component\Security\Guard\GuardAuthenticatorHandler; /** * Gestion des paiements avec Payum */ class PaymentController extends AbstractController { protected $em; protected $translator; protected $payum; protected $authenticator; protected $guardHandler; public function __construct(EntityManagerInterface $em, TranslatorInterface $translator, LoginAuthenticator $authenticator, GuardAuthenticatorHandler $guardHandler, Payum $payum) { $this->em = $em; $this->translator = $translator; $this->payum = $payum; $this->authenticator = $authenticator; $this->guardHandler = $guardHandler; } /** * Crée une instance de Payment, les tokens associés, et redirige vers la page de paiement */ public function preparePaymentAction(Form $form, $type, $extra_data = null) { // Enregistre les données du Flux en json, pour l'enregistrer une fois le paiement validé $serializer = $this->container->get('serializer'); $toSerialize = Payment::TYPE_ADHESION == $type ? $form->get('cotisation')->getData() : $form->getData(); $data = $serializer->normalize($toSerialize, null, [AbstractNormalizer::ATTRIBUTES => [ 'reference', 'moyen', 'montant', 'role', 'don' => [ 'reference', 'moyen', 'montant', 'role', 'type', 'expediteur' => ['id'], 'destinataire' => ['id'], 'operateur' => ['id'], ], 'expediteur' => ['id'], 'destinataire' => ['id'], 'operateur' => ['id']] ]); $jsondata = $serializer->serialize($data, 'json'); // Prepare CB Payment if ($this->em->getRepository(GlobalParameter::class)->val(GlobalParameter::USE_PAYZEN) === 'true') { $gatewayName = 'payzen'; } else { $this->addFlash( 'error', $this->translator->trans('Une erreur est survenue due à la configuration du paiement dans l\'application. Il est pour l\'instant impossible de payer par CB, merci de contacter votre monnaie locale.') ); return $this->redirectToRoute('index'); } $storage = $this->payum->getStorage('App\Entity\Payment'); $payment = $storage->create(); $payment->setNumber(uniqid()); $payment->setCurrencyCode('978'); $payment->setDescription($type); $payment->setFluxData($jsondata); // Data to persist when payment is valid (other than Flux data) if (null != $extra_data) { $payment->setExtraData($extra_data); } if ($type == Payment::TYPE_ADHESION) { $payment->setTotalAmount($form->get('cotisation')->get('montant')->getData()*100); // 1.23 EUR $payment->setClientId('Nouvel adhérent'); $payment->setClientEmail($form->get('user')->get('email')->getData()); } else { if ($form->has('don') && $form->get('don')->getData()->getMontant() > 0) { $payment->setTotalAmount(($form->get('montant')->getData() * 100) + ($form->get('don')->getData()->getMontant() * 100)); // 1.23 EUR } else { $payment->setTotalAmount($form->get('montant')->getData() * 100); // 1.23 EUR } $payment->setClientId($this->getUser()->getId()); $payment->setClientEmail($this->getUser()->getEmail()); } $storage->update($payment); $captureToken = $this->payum->getTokenFactory()->createCaptureToken( $gatewayName, $payment, 'payment_done' // the route to redirect after capture ); // Symfony creates URLs with http and not https -> replace $targetUrl = preg_replace('/^http:/', 'https:', $captureToken->getTargetUrl()); $afterUrl = preg_replace('/^http:/', 'https:', $captureToken->getAfterUrl()); $captureToken->setTargetUrl($targetUrl); $captureToken->setAfterUrl($afterUrl); $this->em->persist($captureToken); $this->em->flush(); return $this->redirect($captureToken->getTargetUrl()); } /** * Fonction de retour sur le site par l'utilisateur après paiement * * @Route("/payment/done/", name="payment_done") */ public function doneAction(Request $request) { try { $token = $this->payum->getHttpRequestVerifier()->verify($request); } catch (\Exception $e) { // Token expired return $this->redirectToRoute('index'); } // Get payment $gateway = $this->payum->getGateway($token->getGatewayName()); $gateway->execute($status = new GetHumanStatus($token)); $payment = $status->getFirstModel(); if ($payment->getStatus() == GetHumanStatus::STATUS_NEW) { // No notification arrived at this point: execute Notify action $gateway->execute(new Notify($token)); } else { // Invalidate token $this->payum->getHttpRequestVerifier()->invalidate($token); } // Set flash message according to payment status if ($payment->getStatus() == GetHumanStatus::STATUS_CAPTURED || $payment->getStatus() == GetHumanStatus::STATUS_AUTHORIZED) { $type = $payment->getDescription(); if (Payment::TYPE_ACHAT_MONNAIE_ADHERENT == $type || Payment::TYPE_ACHAT_MONNAIE_PRESTA == $type) { $this->addFlash( 'success', $this->translator->trans('Achat de monnaie locale bien effectué !') ); } else if (Payment::TYPE_COTISATION_ADHERENT == $type || Payment::TYPE_COTISATION_PRESTA == $type) { $this->addFlash( 'success', $this->translator->trans('Cotisation bien reçue. Merci !') ); } else if (Payment::TYPE_ADHESION == $type) { $this->addFlash( 'success', $this->translator->trans('Votre adhésion a bien été prise en compte, bienvenue !') ); // Connect new user return $this->guardHandler ->authenticateUserAndHandleSuccess( $this->em->getRepository(User::class)->findOneBy(array('id' => $payment->getClientId())), $request, $this->authenticator, 'main' ); } else if (Payment::TYPE_PAIEMENT_COTISATION_TAV == $type) { $this->addFlash( 'success', $this->translator->trans('Cotisation payée !') ); } } else if ($payment->getStatus() == GetHumanStatus::STATUS_CANCELED || $payment->getStatus() == GetHumanStatus::STATUS_EXPIRED || $payment->getStatus() == GetHumanStatus::STATUS_FAILED) { $this->addFlash( 'error', $this->translator->trans('La transaction a été annulée.') ); } return $this->redirectToRoute('index'); } }