PlaceOrder.php 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\InstantPurchase\Controller\Button;
  7. use Exception;
  8. use Magento\Catalog\Api\ProductRepositoryInterface;
  9. use Magento\Customer\Model\Session;
  10. use Magento\Framework\App\Action\Action;
  11. use Magento\Framework\App\Action\Context;
  12. use Magento\Framework\App\RequestInterface;
  13. use Magento\Framework\Controller\Result\Json as JsonResult;
  14. use Magento\Framework\Controller\ResultFactory;
  15. use Magento\Framework\Data\Form\FormKey\Validator as FormKeyValidator;
  16. use Magento\Framework\Exception\LocalizedException;
  17. use Magento\Framework\Exception\NoSuchEntityException;
  18. use Magento\InstantPurchase\Model\InstantPurchaseOptionLoadingFactory;
  19. use Magento\InstantPurchase\Model\PlaceOrder as PlaceOrderModel;
  20. use Magento\Sales\Api\OrderRepositoryInterface;
  21. use Magento\Store\Model\StoreManagerInterface;
  22. /**
  23. * Instant Purchase order placement.
  24. *
  25. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  26. */
  27. class PlaceOrder extends Action
  28. {
  29. /**
  30. * List of request params that handled by the controller.
  31. *
  32. * @var array
  33. */
  34. private static $knownRequestParams = [
  35. 'form_key',
  36. 'product',
  37. 'instant_purchase_payment_token',
  38. 'instant_purchase_shipping_address',
  39. 'instant_purchase_billing_address',
  40. ];
  41. /**
  42. * @var StoreManagerInterface
  43. */
  44. private $storeManager;
  45. /**
  46. * @var Session
  47. */
  48. private $customerSession;
  49. /**
  50. * @var FormKeyValidator
  51. */
  52. private $formKeyValidator;
  53. /**
  54. * @var InstantPurchaseOptionLoadingFactory
  55. */
  56. private $instantPurchaseOptionLoadingFactory;
  57. /**
  58. * @var ProductRepositoryInterface
  59. */
  60. private $productRepository;
  61. /**
  62. * @var PlaceOrderModel
  63. */
  64. private $placeOrder;
  65. /**
  66. * @var OrderRepositoryInterface
  67. */
  68. private $orderRepository;
  69. /**
  70. * @param Context $context
  71. * @param StoreManagerInterface $storeManager
  72. * @param Session $customerSession
  73. * @param FormKeyValidator $formKeyValidator
  74. * @param InstantPurchaseOptionLoadingFactory $instantPurchaseOptionLoadingFactory
  75. * @param ProductRepositoryInterface $productRepository
  76. * @param PlaceOrderModel $placeOrder
  77. * @param OrderRepositoryInterface $orderRepository
  78. */
  79. public function __construct(
  80. Context $context,
  81. StoreManagerInterface $storeManager,
  82. Session $customerSession,
  83. FormKeyValidator $formKeyValidator,
  84. InstantPurchaseOptionLoadingFactory $instantPurchaseOptionLoadingFactory,
  85. ProductRepositoryInterface $productRepository,
  86. PlaceOrderModel $placeOrder,
  87. OrderRepositoryInterface $orderRepository
  88. ) {
  89. parent::__construct($context);
  90. $this->storeManager = $storeManager;
  91. $this->customerSession = $customerSession;
  92. $this->formKeyValidator = $formKeyValidator;
  93. $this->instantPurchaseOptionLoadingFactory = $instantPurchaseOptionLoadingFactory;
  94. $this->productRepository = $productRepository;
  95. $this->placeOrder = $placeOrder;
  96. $this->orderRepository = $orderRepository;
  97. }
  98. /**
  99. * Place an order for a customer.
  100. *
  101. * @return JsonResult
  102. */
  103. public function execute()
  104. {
  105. $request = $this->getRequest();
  106. if (!$this->doesRequestContainAllKnowParams($request)) {
  107. return $this->createResponse($this->createGenericErrorMessage(), false);
  108. }
  109. if (!$this->formKeyValidator->validate($request)) {
  110. return $this->createResponse($this->createGenericErrorMessage(), false);
  111. }
  112. $paymentTokenPublicHash = (string)$request->getParam('instant_purchase_payment_token');
  113. $shippingAddressId = (int)$request->getParam('instant_purchase_shipping_address');
  114. $billingAddressId = (int)$request->getParam('instant_purchase_billing_address');
  115. $carrierCode = (string)$request->getParam('instant_purchase_carrier');
  116. $shippingMethodCode = (string)$request->getParam('instant_purchase_shipping');
  117. $productId = (int)$request->getParam('product');
  118. $productRequest = $this->getRequestUnknownParams($request);
  119. try {
  120. $customer = $this->customerSession->getCustomer();
  121. $instantPurchaseOption = $this->instantPurchaseOptionLoadingFactory->create(
  122. $customer->getId(),
  123. $paymentTokenPublicHash,
  124. $shippingAddressId,
  125. $billingAddressId,
  126. $carrierCode,
  127. $shippingMethodCode
  128. );
  129. $store = $this->storeManager->getStore();
  130. $product = $this->productRepository->getById(
  131. $productId,
  132. false,
  133. $store->getId(),
  134. false
  135. );
  136. $orderId = $this->placeOrder->placeOrder(
  137. $store,
  138. $customer,
  139. $instantPurchaseOption,
  140. $product,
  141. $productRequest
  142. );
  143. } catch (NoSuchEntityException $e) {
  144. return $this->createResponse($this->createGenericErrorMessage(), false);
  145. } catch (Exception $e) {
  146. return $this->createResponse(
  147. $e instanceof LocalizedException ? $e->getMessage() : $this->createGenericErrorMessage(),
  148. false
  149. );
  150. }
  151. $order = $this->orderRepository->get($orderId);
  152. $message = __('Your order number is: %1.', $order->getIncrementId());
  153. return $this->createResponse($message, true);
  154. }
  155. /**
  156. * Creates error message without exposing error details.
  157. *
  158. * @return string
  159. */
  160. private function createGenericErrorMessage(): string
  161. {
  162. return (string)__('Something went wrong while processing your order. Please try again later.');
  163. }
  164. /**
  165. * Checks if all parameters that should be handled are passed.
  166. *
  167. * @param RequestInterface $request
  168. * @return bool
  169. */
  170. private function doesRequestContainAllKnowParams(RequestInterface $request): bool
  171. {
  172. foreach (self::$knownRequestParams as $knownRequestParam) {
  173. if ($request->getParam($knownRequestParam) === null) {
  174. return false;
  175. }
  176. }
  177. return true;
  178. }
  179. /**
  180. * Filters out parameters that handled by controller.
  181. *
  182. * @param RequestInterface $request
  183. * @return array
  184. */
  185. private function getRequestUnknownParams(RequestInterface $request): array
  186. {
  187. $requestParams = $request->getParams();
  188. $unknownParams = [];
  189. foreach ($requestParams as $param => $value) {
  190. if (!isset(self::$knownRequestParams[$param])) {
  191. $unknownParams[$param] = $value;
  192. }
  193. }
  194. return $unknownParams;
  195. }
  196. /**
  197. * Creates response with a operation status message.
  198. *
  199. * @param string $message
  200. * @param bool $successMessage
  201. * @return JsonResult
  202. */
  203. private function createResponse(string $message, bool $successMessage): JsonResult
  204. {
  205. /** @var JsonResult $result */
  206. $result = $this->resultFactory->create(ResultFactory::TYPE_JSON);
  207. $result->setData([
  208. 'response' => $message
  209. ]);
  210. if ($successMessage) {
  211. $this->messageManager->addSuccessMessage($message);
  212. } else {
  213. $this->messageManager->addErrorMessage($message);
  214. }
  215. return $result;
  216. }
  217. }