Skip to content

Commit

Permalink
Add mutation for setting payment method and placing order
Browse files Browse the repository at this point in the history
This matching the existing frontend checkout flow and allows capturing
additional information for fraud tools such as Kount when placing orders.

Fixes #716
  • Loading branch information
pmclain committed May 22, 2019
1 parent 82fac95 commit f73b752
Show file tree
Hide file tree
Showing 6 changed files with 680 additions and 32 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\QuoteGraphQl\Model\Cart;

use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException;
use Magento\Quote\Api\Data\PaymentInterface;
use Magento\Quote\Api\Data\PaymentInterfaceFactory;
use Magento\Quote\Api\PaymentMethodManagementInterface;
use Magento\Quote\Model\Quote;

class SetPaymentMethodOnCart
{
/**
* @var PaymentMethodManagementInterface
*/
private $paymentMethodManagement;

/**
* @var PaymentInterfaceFactory
*/
private $paymentFactory;

/**
* @param PaymentMethodManagementInterface $paymentMethodManagement
* @param PaymentInterfaceFactory $paymentFactory
*/
public function __construct(
PaymentMethodManagementInterface $paymentMethodManagement,
PaymentInterfaceFactory $paymentFactory
) {
$this->paymentMethodManagement = $paymentMethodManagement;
$this->paymentFactory = $paymentFactory;
}

public function execute(array $paymentData, Quote $cart): Quote
{
if (!isset($paymentData['code']) || empty($paymentData['code'])) {
throw new GraphQlInputException(__('Required parameter "code" for "payment_method" is missing.'));
}
$paymentMethodCode = $paymentData['code'];

$poNumber = $paymentData['purchase_order_number'] ?? null;
$additionalData = $paymentData['additional_data'] ?? [];

$payment = $this->paymentFactory->create([
'data' => [
PaymentInterface::KEY_METHOD => $paymentMethodCode,
PaymentInterface::KEY_PO_NUMBER => $poNumber,
PaymentInterface::KEY_ADDITIONAL_DATA => $additionalData,
]
]);

try {
$this->paymentMethodManagement->set($cart->getId(), $payment);
} catch (NoSuchEntityException $e) {
throw new GraphQlNoSuchEntityException(__($e->getMessage()), $e);
} catch (LocalizedException $e) {
throw new GraphQlInputException(__($e->getMessage()), $e);
}

return $cart;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\QuoteGraphQl\Model\Resolver;

use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\GraphQl\Config\Element\Field;
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException;
use Magento\Framework\GraphQl\Query\ResolverInterface;
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
use Magento\Quote\Api\CartManagementInterface;
use Magento\QuoteGraphQl\Model\Cart\GetCartForUser;
use Magento\Sales\Api\OrderRepositoryInterface;

/**
* @inheritdoc
*/
class SetPaymentAndPlaceOrder implements ResolverInterface
{
/**
* @var CartManagementInterface
*/
private $cartManagement;

/**
* @var GetCartForUser
*/
private $getCartForUser;

/**
* @var OrderRepositoryInterface
*/
private $orderRepository;

/**
* @var \Magento\QuoteGraphQl\Model\Cart\SetPaymentMethodOnCart
*/
private $setPaymentMethodOnCart;

/**
* @param GetCartForUser $getCartForUser
* @param CartManagementInterface $cartManagement
* @param OrderRepositoryInterface $orderRepository
* @param \Magento\QuoteGraphQl\Model\Cart\SetPaymentMethodOnCart $setPaymentMethodOnCart
*/
public function __construct(
GetCartForUser $getCartForUser,
CartManagementInterface $cartManagement,
OrderRepositoryInterface $orderRepository,
\Magento\QuoteGraphQl\Model\Cart\SetPaymentMethodOnCart $setPaymentMethodOnCart
) {
$this->getCartForUser = $getCartForUser;
$this->cartManagement = $cartManagement;
$this->orderRepository = $orderRepository;
$this->setPaymentMethodOnCart = $setPaymentMethodOnCart;
}

/**
* @inheritdoc
*/
public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null)
{
if (!isset($args['input']['cart_id']) || empty($args['input']['cart_id'])) {
throw new GraphQlInputException(__('Required parameter "cart_id" is missing'));
}
$maskedCartId = $args['input']['cart_id'];

if (!isset($args['input']['payment_method']['code']) || empty($args['input']['payment_method']['code'])) {
throw new GraphQlInputException(__('Required parameter "code" for "payment_method" is missing.'));
}
$paymentData = $args['input']['payment_method'];

$cart = $this->getCartForUser->execute($maskedCartId, $context->getUserId());
$cart = $this->setPaymentMethodOnCart->execute($paymentData, $cart);

if ($context->getUserId() === 0) {
if (!$cart->getCustomerEmail()) {
throw new GraphQlInputException(__("Guest email for cart is missing. Please enter"));
}
$cart->setCheckoutMethod(CartManagementInterface::METHOD_GUEST);
}

try {
$orderId = $this->cartManagement->placeOrder($cart->getId());
$order = $this->orderRepository->get($orderId);

return [
'order' => [
'order_id' => $order->getIncrementId(),
],
];
} catch (NoSuchEntityException $e) {
throw new GraphQlNoSuchEntityException(__($e->getMessage()), $e);
} catch (LocalizedException $e) {
throw new GraphQlInputException(__('Unable to place order: %message', ['message' => $e->getMessage()]), $e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,28 +30,20 @@ class SetPaymentMethodOnCart implements ResolverInterface
private $getCartForUser;

/**
* @var PaymentMethodManagementInterface
* @var \Magento\QuoteGraphQl\Model\Cart\SetPaymentMethodOnCart
*/
private $paymentMethodManagement;

/**
* @var PaymentInterfaceFactory
*/
private $paymentFactory;
private $setPaymentMethodOnCart;

/**
* @param GetCartForUser $getCartForUser
* @param PaymentMethodManagementInterface $paymentMethodManagement
* @param PaymentInterfaceFactory $paymentFactory
* @param \Magento\QuoteGraphQl\Model\Cart\SetPaymentMethodOnCart $setPaymentMethodOnCart
*/
public function __construct(
GetCartForUser $getCartForUser,
PaymentMethodManagementInterface $paymentMethodManagement,
PaymentInterfaceFactory $paymentFactory
\Magento\QuoteGraphQl\Model\Cart\SetPaymentMethodOnCart $setPaymentMethodOnCart
) {
$this->getCartForUser = $getCartForUser;
$this->paymentMethodManagement = $paymentMethodManagement;
$this->paymentFactory = $paymentFactory;
$this->setPaymentMethodOnCart = $setPaymentMethodOnCart;
}

/**
Expand All @@ -67,27 +59,10 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value
if (!isset($args['input']['payment_method']['code']) || empty($args['input']['payment_method']['code'])) {
throw new GraphQlInputException(__('Required parameter "code" for "payment_method" is missing.'));
}
$paymentMethodCode = $args['input']['payment_method']['code'];

$poNumber = $args['input']['payment_method']['purchase_order_number'] ?? null;
$additionalData = $args['input']['payment_method']['additional_data'] ?? [];
$paymentData = $args['input']['payment_method'];

$cart = $this->getCartForUser->execute($maskedCartId, $context->getUserId());
$payment = $this->paymentFactory->create([
'data' => [
PaymentInterface::KEY_METHOD => $paymentMethodCode,
PaymentInterface::KEY_PO_NUMBER => $poNumber,
PaymentInterface::KEY_ADDITIONAL_DATA => $additionalData,
]
]);

try {
$this->paymentMethodManagement->set($cart->getId(), $payment);
} catch (NoSuchEntityException $e) {
throw new GraphQlNoSuchEntityException(__($e->getMessage()), $e);
} catch (LocalizedException $e) {
throw new GraphQlInputException(__($e->getMessage()), $e);
}
$cart = $this->setPaymentMethodOnCart->execute($paymentData, $cart);

return [
'cart' => [
Expand Down
1 change: 1 addition & 0 deletions app/code/Magento/QuoteGraphQl/etc/schema.graphqls
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ type Mutation {
setShippingMethodsOnCart(input: SetShippingMethodsOnCartInput): SetShippingMethodsOnCartOutput @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\SetShippingMethodsOnCart")
setPaymentMethodOnCart(input: SetPaymentMethodOnCartInput): SetPaymentMethodOnCartOutput @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\SetPaymentMethodOnCart")
setGuestEmailOnCart(input: SetGuestEmailOnCartInput): SetGuestEmailOnCartOutput @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\SetGuestEmailOnCart")
setPaymentMethodAndPlaceOrder(input: SetPaymentMethodOnCartInput): PlaceOrderOutput @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\SetPaymentAndPlaceOrder")
placeOrder(input: PlaceOrderInput): PlaceOrderOutput @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\PlaceOrder")
}

Expand Down
Loading

0 comments on commit f73b752

Please sign in to comment.