You are here

class PaymentCheckoutController in Commerce Core 8.2

Provides checkout endpoints for off-site payments.

Hierarchy

Expanded class hierarchy of PaymentCheckoutController

File

modules/payment/src/Controller/PaymentCheckoutController.php, line 22

Namespace

Drupal\commerce_payment\Controller
View source
class PaymentCheckoutController implements ContainerInjectionInterface {

  /**
   * The checkout order manager.
   *
   * @var \Drupal\commerce_checkout\CheckoutOrderManagerInterface
   */
  protected $checkoutOrderManager;

  /**
   * The messenger.
   *
   * @var \Drupal\Core\Messenger\MessengerInterface
   */
  protected $messenger;

  /**
   * The logger.
   *
   * @var \Psr\Log\LoggerInterface
   */
  protected $logger;

  /**
   * Constructs a new PaymentCheckoutController object.
   *
   * @param \Drupal\commerce_checkout\CheckoutOrderManagerInterface $checkout_order_manager
   *   The checkout order manager.
   * @param \Drupal\Core\Messenger\MessengerInterface $messenger
   *   The messenger.
   * @param \Psr\Log\LoggerInterface $logger
   *   The logger.
   */
  public function __construct(CheckoutOrderManagerInterface $checkout_order_manager, MessengerInterface $messenger, LoggerInterface $logger) {
    $this->checkoutOrderManager = $checkout_order_manager;
    $this->messenger = $messenger;
    $this->logger = $logger;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static($container
      ->get('commerce_checkout.checkout_order_manager'), $container
      ->get('messenger'), $container
      ->get('logger.channel.commerce_payment'));
  }

  /**
   * Provides the "return" checkout payment page.
   *
   * Redirects to the next checkout page, completing checkout.
   *
   * @param \Symfony\Component\HttpFoundation\Request $request
   *   The request.
   * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
   *   The route match.
   */
  public function returnPage(Request $request, RouteMatchInterface $route_match) {

    /** @var \Drupal\commerce_order\Entity\OrderInterface $order */
    $order = $route_match
      ->getParameter('commerce_order');
    $step_id = $route_match
      ->getParameter('step');
    $this
      ->validateStepId($step_id, $order);

    /** @var \Drupal\commerce_payment\Entity\PaymentGatewayInterface $payment_gateway */
    $payment_gateway = $order
      ->get('payment_gateway')->entity;
    $payment_gateway_plugin = $payment_gateway
      ->getPlugin();
    if (!$payment_gateway_plugin instanceof OffsitePaymentGatewayInterface) {
      throw new AccessException('The payment gateway for the order does not implement ' . OffsitePaymentGatewayInterface::class);
    }

    /** @var \Drupal\commerce_checkout\Entity\CheckoutFlowInterface $checkout_flow */
    $checkout_flow = $order
      ->get('checkout_flow')->entity;
    $checkout_flow_plugin = $checkout_flow
      ->getPlugin();
    try {
      $payment_gateway_plugin
        ->onReturn($order, $request);
      $redirect_step_id = $checkout_flow_plugin
        ->getNextStepId($step_id);
    } catch (PaymentGatewayException $e) {
      $this->logger
        ->error($e
        ->getMessage());
      $this->messenger
        ->addError(t('Payment failed at the payment server. Please review your information and try again.'));
      $redirect_step_id = $checkout_flow_plugin
        ->getPreviousStepId($step_id);
    }
    $checkout_flow_plugin
      ->redirectToStep($redirect_step_id);
  }

  /**
   * Provides the "cancel" checkout payment page.
   *
   * Redirects to the previous checkout page.
   *
   * @param \Symfony\Component\HttpFoundation\Request $request
   *   The request.
   * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
   *   The route match.
   */
  public function cancelPage(Request $request, RouteMatchInterface $route_match) {

    /** @var \Drupal\commerce_order\Entity\OrderInterface $order */
    $order = $route_match
      ->getParameter('commerce_order');
    $step_id = $route_match
      ->getParameter('step');
    $this
      ->validateStepId($step_id, $order);

    /** @var \Drupal\commerce_payment\Entity\PaymentGatewayInterface $payment_gateway */
    $payment_gateway = $order
      ->get('payment_gateway')->entity;
    $payment_gateway_plugin = $payment_gateway
      ->getPlugin();
    if (!$payment_gateway_plugin instanceof OffsitePaymentGatewayInterface) {
      throw new AccessException('The payment gateway for the order does not implement ' . OffsitePaymentGatewayInterface::class);
    }

    /** @var \Drupal\commerce_checkout\Entity\CheckoutFlowInterface $checkout_flow */
    $checkout_flow = $order
      ->get('checkout_flow')->entity;
    $checkout_flow_plugin = $checkout_flow
      ->getPlugin();
    $payment_gateway_plugin
      ->onCancel($order, $request);
    $previous_step_id = $checkout_flow_plugin
      ->getPreviousStepId($step_id);
    $checkout_flow_plugin
      ->redirectToStep($previous_step_id);
  }

  /**
   * Validates the requested step ID.
   *
   * Redirects to the actual step ID if the requested one is no longer
   * available. This can happen if payment was already cancelled, or if the
   * payment "notify" endpoint created the payment and placed the order
   * before the customer returned to the site.
   *
   * @param string $requested_step_id
   *   The requested step ID, usually "payment".
   * @param \Drupal\commerce_order\Entity\OrderInterface $order
   *   The order.
   *
   * @throws \Drupal\commerce\Response\NeedsRedirectException
   */
  protected function validateStepId($requested_step_id, OrderInterface $order) {
    $step_id = $this->checkoutOrderManager
      ->getCheckoutStepId($order);
    if ($requested_step_id != $step_id) {
      throw new NeedsRedirectException(Url::fromRoute('commerce_checkout.form', [
        'commerce_order' => $order
          ->id(),
        'step' => $step_id,
      ])
        ->toString());
    }
  }

}

Members

Namesort descending Modifiers Type Description Overrides
PaymentCheckoutController::$checkoutOrderManager protected property The checkout order manager.
PaymentCheckoutController::$logger protected property The logger.
PaymentCheckoutController::$messenger protected property The messenger.
PaymentCheckoutController::cancelPage public function Provides the "cancel" checkout payment page.
PaymentCheckoutController::create public static function Instantiates a new instance of this class. Overrides ContainerInjectionInterface::create
PaymentCheckoutController::returnPage public function Provides the "return" checkout payment page.
PaymentCheckoutController::validateStepId protected function Validates the requested step ID.
PaymentCheckoutController::__construct public function Constructs a new PaymentCheckoutController object.