class CheckoutController in Commerce PayPal 8
PayPal checkout controller.
Hierarchy
- class \Drupal\Core\Controller\ControllerBase implements ContainerInjectionInterface uses LoggerChannelTrait, MessengerTrait, LinkGeneratorTrait, RedirectDestinationTrait, UrlGeneratorTrait, StringTranslationTrait
- class \Drupal\commerce_paypal\Controller\CheckoutController
Expanded class hierarchy of CheckoutController
File
- src/
Controller/ CheckoutController.php, line 27
Namespace
Drupal\commerce_paypal\ControllerView source
class CheckoutController extends ControllerBase {
/**
* The PayPal Checkout SDK factory.
*
* @var \Drupal\commerce_paypal\CheckoutSdkFactoryInterface
*/
protected $checkoutSdkFactory;
/**
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* The logger.
*
* @var \Psr\Log\LoggerInterface
*/
protected $logger;
/**
* The messenger.
*
* @var \Drupal\Core\Messenger\MessengerInterface
*/
protected $messenger;
/**
* Constructs a PayPalCheckoutController object.
*
* @param \Drupal\commerce_paypal\CheckoutSdkFactoryInterface $checkout_sdk_factory
* The PayPal Checkout SDK factory.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
* @param \Psr\Log\LoggerInterface $logger
* The logger.
* @param \Drupal\Core\Messenger\MessengerInterface $messenger
* The messenger.
*/
public function __construct(CheckoutSdkFactoryInterface $checkout_sdk_factory, EntityTypeManagerInterface $entity_type_manager, LoggerInterface $logger, MessengerInterface $messenger) {
$this->checkoutSdkFactory = $checkout_sdk_factory;
$this->entityTypeManager = $entity_type_manager;
$this->logger = $logger;
$this->messenger = $messenger;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static($container
->get('commerce_paypal.checkout_sdk_factory'), $container
->get('entity_type.manager'), $container
->get('logger.channel.commerce_paypal'), $container
->get('messenger'));
}
/**
* Create/update the order in PayPal.
*
* @param \Drupal\commerce_order\Entity\OrderInterface $commerce_order
* The order.
* @param \Drupal\commerce_payment\Entity\PaymentGatewayInterface $commerce_payment_gateway
* The payment gateway.
* @param \Symfony\Component\HttpFoundation\Request $request
* The request.
*
* @return \Symfony\Component\HttpFoundation\Response
* A response.
*/
public function onCreate(OrderInterface $commerce_order, PaymentGatewayInterface $commerce_payment_gateway, Request $request) {
if (!$commerce_payment_gateway
->getPlugin() instanceof CheckoutInterface) {
throw new AccessException('Invalid payment gateway provided.');
}
$config = $commerce_payment_gateway
->getPluginConfiguration();
$sdk = $this->checkoutSdkFactory
->get($config);
try {
$address = NULL;
$body = [];
if ($request
->getContent()) {
$body = Json::decode($request
->getContent());
// Check if a billing profile or an address was sent.
// When this route is called in the context of the Custom card fields, the
// form is not yet submitted which means the billing profile is not yet
// associated with the order, so we extract it from the DOM and pass it
// to the controller.
// If we don't do that, then the "payer" will be considered as anonymous
// by PayPal.
$address = $this
->extractAddress($commerce_order, $request);
}
$commerce_order
->set('payment_gateway', $commerce_payment_gateway);
$commerce_order
->setData('paypal_checkout_flow', $body['flow'] ?? 'mark');
$response = $sdk
->createOrder($commerce_order, $address);
$paypal_order = Json::decode($response
->getBody()
->getContents());
$commerce_order
->setData('paypal_order_id', $paypal_order['id']);
$commerce_order
->setRefreshState(OrderInterface::REFRESH_SKIP);
$commerce_order
->save();
return new JsonResponse([
'id' => $paypal_order['id'],
]);
} catch (BadResponseException $exception) {
$this->logger
->error($exception
->getResponse()
->getBody()
->getContents());
return new Response('', Response::HTTP_BAD_REQUEST);
}
}
/**
* React to the PayPal checkout "onApprove" JS SDK callback.
*
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
* The route match.
* @param \Symfony\Component\HttpFoundation\Request $request
* The request.
*
* @return \Symfony\Component\HttpFoundation\Response
* A response.
*/
public function onApprove(RouteMatchInterface $route_match, Request $request) {
/** @var \Drupal\commerce_order\Entity\OrderInterface $order */
$order = $route_match
->getParameter('commerce_order');
/** @var \Drupal\commerce_payment\Entity\PaymentGatewayInterface $payment_gateway */
$payment_gateway = $route_match
->getParameter('commerce_payment_gateway');
$payment_gateway_plugin = $payment_gateway
->getPlugin();
if (!$payment_gateway_plugin instanceof CheckoutInterface) {
throw new AccessException('Unsupported payment gateway provided.');
}
try {
// Note that we're using a custom route instead of the payment return
// one since the payment return callback cannot be called from the cart
// page.
$payment_gateway_plugin
->onReturn($order, $request);
$step_id = $order
->get('checkout_step')->value;
// Redirect to the next checkout step if the current checkout step is
// known, which isn't the case when in the "shortcut" flow.
if (!empty($step_id)) {
/** @var \Drupal\commerce_checkout\Entity\CheckoutFlowInterface $checkout_flow */
$checkout_flow = $order
->get('checkout_flow')->entity;
$checkout_flow_plugin = $checkout_flow
->getPlugin();
$step_id = $checkout_flow_plugin
->getNextStepId($step_id);
$order
->set('checkout_step', $step_id);
}
$order
->save();
$redirect_url = Url::fromRoute('commerce_checkout.form', [
'commerce_order' => $order
->id(),
'step' => $step_id,
])
->toString();
return new JsonResponse([
'redirectUrl' => $redirect_url,
]);
} catch (PaymentGatewayException $e) {
// When the payment fails, we don't instruct the JS to redirect, the page
// will be reloaded to show errors.
$this->logger
->error($e
->getMessage());
$this->messenger
->addError(t('Payment failed at the payment server. Please review your information and try again.'));
return new JsonResponse();
}
}
/**
* Extracts the billing address from the request body.
*
* @param \Drupal\commerce_order\Entity\OrderInterface $order
* The order.
* @param \Symfony\Component\HttpFoundation\Request $request
* The request.
*
* @return \Drupal\address\AddressInterface|null
* The address, NULL if empty.
*/
protected function extractAddress(OrderInterface $order, Request $request) {
$body = Json::decode($request
->getContent());
// If the "profile copy" checkbox is checked, attempt to use the
// shipping profile as the source of the address.
if (!empty($body['profileCopy'])) {
$profiles = $order
->collectProfiles();
if (isset($profiles['shipping']) && !$profiles['shipping']
->get('address')
->isEmpty()) {
return $profiles['shipping']
->get('address')
->first();
}
}
/** @var \Drupal\profile\ProfileStorageInterface $profile_storage */
$profile_storage = $this->entityTypeManager
->getStorage('profile');
if (!empty($body['profile'])) {
// When "_original" is passed, attempt to load/use the default profile.
if ($body['profile'] === '_original') {
$profile = $profile_storage
->loadByUser($order
->getCustomer(), 'customer');
}
else {
$profile = $profile_storage
->load($body['profile']);
}
if ($profile && $profile
->access('view') && !$profile
->get('address')
->isEmpty()) {
return $profile
->get('address')
->first();
}
}
elseif (!empty($body['address'])) {
$profile = $profile_storage
->create([
'type' => 'customer',
'address' => $body['address'],
]);
return $profile
->get('address')
->first();
}
return NULL;
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
CheckoutController:: |
protected | property | The PayPal Checkout SDK factory. | |
CheckoutController:: |
protected | property |
The entity type manager. Overrides ControllerBase:: |
|
CheckoutController:: |
protected | property | The logger. | |
CheckoutController:: |
protected | property |
The messenger. Overrides MessengerTrait:: |
|
CheckoutController:: |
public static | function |
Instantiates a new instance of this class. Overrides ControllerBase:: |
|
CheckoutController:: |
protected | function | Extracts the billing address from the request body. | |
CheckoutController:: |
public | function | React to the PayPal checkout "onApprove" JS SDK callback. | |
CheckoutController:: |
public | function | Create/update the order in PayPal. | |
CheckoutController:: |
public | function | Constructs a PayPalCheckoutController object. | |
ControllerBase:: |
protected | property | The configuration factory. | |
ControllerBase:: |
protected | property | The current user service. | 1 |
ControllerBase:: |
protected | property | The entity form builder. | |
ControllerBase:: |
protected | property | The entity manager. | |
ControllerBase:: |
protected | property | The form builder. | 2 |
ControllerBase:: |
protected | property | The key-value storage. | 1 |
ControllerBase:: |
protected | property | The language manager. | 1 |
ControllerBase:: |
protected | property | The module handler. | 2 |
ControllerBase:: |
protected | property | The state service. | |
ControllerBase:: |
protected | function | Returns the requested cache bin. | |
ControllerBase:: |
protected | function | Retrieves a configuration object. | |
ControllerBase:: |
private | function | Returns the service container. | |
ControllerBase:: |
protected | function | Returns the current user. | 1 |
ControllerBase:: |
protected | function | Retrieves the entity form builder. | |
ControllerBase:: |
protected | function | Retrieves the entity manager service. | |
ControllerBase:: |
protected | function | Retrieves the entity type manager. | |
ControllerBase:: |
protected | function | Returns the form builder service. | 2 |
ControllerBase:: |
protected | function | Returns a key/value storage collection. | 1 |
ControllerBase:: |
protected | function | Returns the language manager service. | 1 |
ControllerBase:: |
protected | function | Returns the module handler. | 2 |
ControllerBase:: |
protected | function |
Returns a redirect response object for the specified route. Overrides UrlGeneratorTrait:: |
|
ControllerBase:: |
protected | function | Returns the state storage service. | |
LinkGeneratorTrait:: |
protected | property | The link generator. | 1 |
LinkGeneratorTrait:: |
protected | function | Returns the link generator. | |
LinkGeneratorTrait:: |
protected | function | Renders a link to a route given a route name and its parameters. | |
LinkGeneratorTrait:: |
public | function | Sets the link generator service. | |
LoggerChannelTrait:: |
protected | property | The logger channel factory service. | |
LoggerChannelTrait:: |
protected | function | Gets the logger for a specific channel. | |
LoggerChannelTrait:: |
public | function | Injects the logger channel factory. | |
MessengerTrait:: |
public | function | Gets the messenger. | 29 |
MessengerTrait:: |
public | function | Sets the messenger. | |
RedirectDestinationTrait:: |
protected | property | The redirect destination service. | 1 |
RedirectDestinationTrait:: |
protected | function | Prepares a 'destination' URL query parameter for use with \Drupal\Core\Url. | |
RedirectDestinationTrait:: |
protected | function | Returns the redirect destination service. | |
RedirectDestinationTrait:: |
public | function | Sets the redirect destination service. | |
StringTranslationTrait:: |
protected | property | The string translation service. | 1 |
StringTranslationTrait:: |
protected | function | Formats a string containing a count of items. | |
StringTranslationTrait:: |
protected | function | Returns the number of plurals supported by a given language. | |
StringTranslationTrait:: |
protected | function | Gets the string translation service. | |
StringTranslationTrait:: |
public | function | Sets the string translation service to use. | 2 |
StringTranslationTrait:: |
protected | function | Translates a string to the current language or to a given language. | |
UrlGeneratorTrait:: |
protected | property | The url generator. | |
UrlGeneratorTrait:: |
protected | function | Returns the URL generator service. | |
UrlGeneratorTrait:: |
public | function | Sets the URL generator service. | |
UrlGeneratorTrait:: |
protected | function | Generates a URL or path for a specific route based on the given parameters. |