Skip to content

Commit

Permalink
Redirect cancel and capture to new processing page that waits for the…
Browse files Browse the repository at this point in the history
… payment status
  • Loading branch information
LucaGallinari committed Sep 11, 2024
1 parent 8737d5e commit b0139dd
Show file tree
Hide file tree
Showing 7 changed files with 159 additions and 14 deletions.
4 changes: 1 addition & 3 deletions config/services/action.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,7 @@
->public()
->args([
service('webgriffe_sylius_pausepay.logger'),
service('doctrine.orm.entity_manager'),
service('sm.factory'),
service('sylius.order_processing.order_payment_processor.checkout'),
service('router'),
])
->tag('payum.action', ['factory' => PausePayApi::GATEWAY_CODE, 'alias' => 'payum.action.cancel']);

Expand Down
21 changes: 21 additions & 0 deletions config/services/controller.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

declare(strict_types=1);

namespace Symfony\Component\DependencyInjection\Loader\Configurator;

use Webgriffe\SyliusPausePayPlugin\Controller\PaymentController;

return static function (ContainerConfigurator $containerConfigurator) {
$services = $containerConfigurator->services();

$services->set('webgriffe_sylius_pausepay.controller.payment', PaymentController::class)
->args([
service('payum.security.token_storage'),
service('router'),
service('sylius.repository.payment'),
])
->call('setContainer', [service('service_container')])
->tag('controller.service_arguments')
;
};
5 changes: 4 additions & 1 deletion config/shop_ajax_routing.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,8 @@
use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator;

return static function (RoutingConfigurator $routes): void {
// todo
$routes->add('webgriffe_sylius_pausepay_plugin_payment_status', '/payment/{payumToken}/pausepay-status')
->controller(['webgriffe_sylius_pausepay.controller.payment', 'statusAction'])
->methods(['GET'])
;
};
5 changes: 4 additions & 1 deletion config/shop_routing.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,8 @@
use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator;

return static function (RoutingConfigurator $routes): void {
// todo
$routes->add('webgriffe_sylius_pausepay_plugin_payment_process', '/payment/{payumToken}/pausepay-process')
->controller(['webgriffe_sylius_pausepay.controller.payment', 'processAction'])
->methods(['GET'])
;
};
121 changes: 121 additions & 0 deletions src/Controller/PaymentController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
<?php

declare(strict_types=1);

namespace Webgriffe\SyliusPausePayPlugin\Controller;

use Payum\Core\Model\Identity;
use Payum\Core\Security\TokenInterface;
use Payum\Core\Storage\StorageInterface;
use Sylius\Bundle\PayumBundle\Model\GatewayConfigInterface;
use Sylius\Component\Core\Model\PaymentInterface;
use Sylius\Component\Core\Model\PaymentMethodInterface;
use Sylius\Component\Core\Repository\PaymentRepositoryInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Routing\RouterInterface;
use Webgriffe\SyliusPausePayPlugin\Helper\PaymentDetailsHelper;
use Webgriffe\SyliusPausePayPlugin\Payum\PausePayApi;
use Webmozart\Assert\Assert;

/**
* @psalm-suppress PropertyNotSetInConstructor
*
* @psalm-type PaymentDetails array{uuid: string, redirect_url: string, created_at: string, status?: string}
*/
final class PaymentController extends AbstractController
{
public function __construct(
private StorageInterface $tokenStorage,
private RouterInterface $router,
private PaymentRepositoryInterface $paymentRepository,
) {
}

public function processAction(string $payumToken): Response
{
if ($payumToken === '') {
throw $this->createNotFoundException();
}

$token = $this->tokenStorage->find($payumToken);
if (!$token instanceof TokenInterface) {
throw $this->createNotFoundException();
}

$paymentDetails = $this->retrieveDetailsFromToken($token);

$redirectUrl = PaymentDetailsHelper::getRedirectUrl($paymentDetails);
$paymentStatusUrl = $this->router->generate(
'webgriffe_sylius_pausepay_plugin_payment_status',
['payumToken' => $payumToken],
UrlGeneratorInterface::ABSOLUTE_URL,
);

return $this->render('@WebgriffeSyliusPausePayPlugin/Process/index.html.twig', [
'afterUrl' => $token->getAfterUrl(),
'paymentStatusUrl' => $paymentStatusUrl,
'redirectUrl' => $redirectUrl,
]);
}

public function statusAction(string $payumToken): Response
{
if ($payumToken === '') {
throw $this->createNotFoundException();
}

$token = $this->tokenStorage->find($payumToken);
if (!$token instanceof TokenInterface) {
throw $this->createNotFoundException();
}

$paymentDetails = $this->retrieveDetailsFromToken($token);
$paymentStatus = PaymentDetailsHelper::getPaymentStatus($paymentDetails);

return $this->json(['captured' => $paymentStatus !== null]);
}

/**
* @return PaymentDetails
*/
private function retrieveDetailsFromToken(TokenInterface $token): array
{
$paymentIdentity = $token->getDetails();
Assert::isInstanceOf($paymentIdentity, Identity::class);

/** @var PaymentInterface|null $syliusPayment */
$syliusPayment = $this->paymentRepository->find($paymentIdentity->getId());
Assert::nullOrIsInstanceOf($syliusPayment, PaymentInterface::class);
if (!$syliusPayment instanceof PaymentInterface) {
throw $this->createNotFoundException();
}

$this->assertPausePayPayment($syliusPayment);

$paymentDetails = $syliusPayment->getDetails();
if (!PaymentDetailsHelper::areValid($paymentDetails)) {
throw $this->createAccessDeniedException();
}

return $paymentDetails;
}

private function assertPausePayPayment(PaymentInterface $syliusPayment): void
{
$paymentMethod = $syliusPayment->getMethod();
if (!$paymentMethod instanceof PaymentMethodInterface) {
throw $this->createAccessDeniedException();
}

$paymentGatewayConfig = $paymentMethod->getGatewayConfig();
if (!$paymentGatewayConfig instanceof GatewayConfigInterface) {
throw $this->createAccessDeniedException();
}
/** @psalm-suppress DeprecatedMethod */
if ($paymentGatewayConfig->getFactoryName() !== PausePayApi::GATEWAY_CODE) {
throw $this->createAccessDeniedException();
}
}
}
8 changes: 4 additions & 4 deletions src/Payum/Action/CancelAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public function execute($request): void
$paymentDetails = $payment->getDetails();
PaymentDetailsHelper::assertPaymentDetailsAreValid($paymentDetails);

$this->logger->info('Redirecting the user to the Sylius Pagolight waiting page.');
$this->logInfo($payment, 'Redirecting the user to the Sylius PausePay waiting page.');

$order = $payment->getOrder();
Assert::isInstanceOf($order, OrderInterface::class);
Expand All @@ -59,8 +59,8 @@ public function execute($request): void
$payment->setDetails($paymentDetails);

throw new HttpRedirect(
$this->router->generate('webgriffe_sylius_pagolight_plugin_payment_process', [
'tokenValue' => $order->getTokenValue(),
$this->router->generate('webgriffe_sylius_pausepay_plugin_payment_process', [
'payumToken' => $order->getTokenValue(),
'_locale' => $order->getLocaleCode(),
]),
);
Expand All @@ -73,6 +73,6 @@ public function supports($request): bool

private function logInfo(SyliusPaymentInterface $payment, string $message, array $context = []): void
{
$this->logger->info(sprintf('[Payment #%s]: %s.', (string) $payment->getId(), $message,), $context);
$this->logger->info(sprintf('[Payment #%s]: %s.', (string) $payment->getId(), $message, ), $context);
}
}
9 changes: 4 additions & 5 deletions src/Payum/Action/CaptureAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ public function execute($request): void

$this->logInfo($payment, 'Start capture action', );

$captureToken = $request->getToken();
Assert::isInstanceOf($captureToken, TokenInterface::class);

$paymentDetails = $payment->getDetails();

if ($paymentDetails !== []) {
Expand All @@ -79,16 +82,12 @@ public function execute($request): void

throw new HttpRedirect(
$this->router->generate('webgriffe_sylius_pausepay_plugin_payment_process', [
'tokenValue' => $order->getTokenValue(),
'payumToken' => $captureToken->getHash(),
'_locale' => $order->getLocaleCode(),
]),
);
}

// todo: verify urls
$captureToken = $request->getToken();
Assert::isInstanceOf($captureToken, TokenInterface::class);

$captureUrl = $captureToken->getTargetUrl();

$cancelToken = $this->tokenFactory->createToken(
Expand Down

0 comments on commit b0139dd

Please sign in to comment.