commerce_api-8.x-1.x-dev/src/Resource/PaymentGateway/PaymentApproveResource.php

src/Resource/PaymentGateway/PaymentApproveResource.php
<?php

declare(strict_types=1);

namespace Drupal\commerce_api\Resource\PaymentGateway;

use Drupal\commerce_api\Resource\FixIncludeTrait;
use Drupal\commerce_order\Entity\OrderInterface;
use Drupal\commerce_order\Exception\OrderVersionMismatchException;
use Drupal\commerce_payment\Entity\PaymentGatewayInterface;
use Drupal\commerce_payment\Exception\PaymentGatewayException;
use Drupal\commerce_payment\Plugin\Commerce\PaymentGateway\OffsitePaymentGatewayInterface;
use Drupal\Core\Database\Connection;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Entity\EntityStorageException;
use Drupal\Core\Render\RenderContext;
use Drupal\Core\Render\RendererInterface;
use Drupal\jsonapi_resources\Resource\EntityResourceBase;
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\ConflictHttpException;
use Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException;

/**
 * Resource for off-site payment transactions.
 *
 * @see \Drupal\commerce_payment\Controller\PaymentCheckoutController.
 */
final class PaymentApproveResource extends EntityResourceBase implements ContainerInjectionInterface {

  use FixIncludeTrait;

  /**
   * Constructs a new OnReturnResource object.
   *
   * @param \Psr\Log\LoggerInterface $logger
   *   The logger.
   * @param \Drupal\Core\Render\RendererInterface $renderer
   *   The renderer.
   * @param \Drupal\Core\Database\Connection $connection
   *   The database connection.
   */
  public function __construct(private LoggerInterface $logger, private RendererInterface $renderer, private Connection $connection) {}

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

  /**
   * Process the request.
   *
   * @param \Symfony\Component\HttpFoundation\Request $request
   *   The request.
   * @param \Drupal\commerce_order\Entity\OrderInterface $commerce_order
   *   The order.
   */
  public function process(Request $request, OrderInterface $commerce_order) {
    $transaction = $this->connection->startTransaction();
    try {
      return $this->doProcess($request, $commerce_order);
    }
    catch (EntityStorageException $exception) {
      if ($exception->getPrevious() instanceof OrderVersionMismatchException) {
        $transaction->rollBack();
        throw new ConflictHttpException($exception->getMessage(), $exception);
      }
      throw $exception;
    }
  }

  /**
   * Process the request.
   *
   * @param \Symfony\Component\HttpFoundation\Request $request
   *   The request.
   * @param \Drupal\commerce_order\Entity\OrderInterface $order
   *   The order.
   */
  private function doProcess(Request $request, OrderInterface $order) {
    // @todo should this actually be a "not allowed" exception?
    //   instead be kind and just return the order object to be reentrant.
    if (!$order->getState()->isTransitionAllowed('place')) {
      $this->fixOrderInclude($request);
      $top_level_data = $this->createIndividualDataFromEntity($order);
      return $this->createJsonapiResponse($top_level_data, $request);
    }

    if ($order->get('payment_gateway')->isEmpty()) {
      throw new UnprocessableEntityHttpException('A payment gateway is not set for this order.');
    }
    $payment_gateway = $order->get('payment_gateway')->entity;
    if (!$payment_gateway instanceof PaymentGatewayInterface) {
      throw new UnprocessableEntityHttpException('A payment gateway is not set for this order.');
    }

    $payment_gateway_plugin = $payment_gateway->getPlugin();
    if (!$payment_gateway_plugin instanceof OffsitePaymentGatewayInterface) {
      throw new UnprocessableEntityHttpException('The payment gateway for the order does not implement ' . OffsitePaymentGatewayInterface::class);
    }

    try {
      $payment_gateway_plugin->onReturn($order, $request);
    }
    catch (PaymentGatewayException $e) {
      $this->logger->error($e->getMessage());
      throw new UnprocessableEntityHttpException(
        'Payment failed at the payment server. Please review your information and try again.',
        $e
      );
    }

    // The on return method is concerned with creating/completing payments, so
    // we can assume the order has been finished and place it.
    $render_context = new RenderContext();
    $this->renderer->executeInRenderContext($render_context, function () use ($order) {
      $order->getState()->applyTransitionById('place');
      $order->save();
    });

    $this->fixOrderInclude($request);
    $top_level_data = $this->createIndividualDataFromEntity($order);
    return $this->createJsonapiResponse($top_level_data, $request);
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc