0

I am working on creating a functionality where I have added a "buy now" button on the product page, when the user clicks that button then a popup form appears, entering all necessary details in that form & clicking on order now.

I post data to the controller where currently I have added static code to create order programmatically.

Order gets created successfully, but I need to redirect the customer too on the thank you/success page once the order is created. But I am facing issues & not sure how to manage sessions to redirect users to the success/thank you page.

here is the controller file code :

namespace Hs\BuyNow\Controller\Cart;
class Now extends \Magento\Framework\App\Action\Action
{
    public function __construct(\Magento\Framework\View\Result\PageFactory $pageFactory, \Magento\Framework\App\Action\Context $context, \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Catalog\Model\Product $product, \Magento\Framework\Data\Form\FormKey $formkey, \Magento\Quote\Model\QuoteFactory $quote, \Magento\Quote\Model\QuoteManagement $quoteManagement, \Magento\Customer\Model\CustomerFactory $customerFactory, \Magento\Customer\Api\CustomerRepositoryInterface $customerRepository, \Magento\Sales\Model\Service\OrderService $orderService, \Magento\Framework\App\Request\Http $request,
    \Magento\Framework\Controller\ResultFactory $resultPageFactory,
    \Magento\Checkout\Model\Session $checkoutSession,
    \Magento\Quote\Api\GuestCartManagementInterface $guestcartManagement
    )
    {
        $this->storeManager = $storeManager;
        $this->product = $product;
        $this->formkey = $formkey;
        $this->quote = $quote;
        $this->quoteManagement = $quoteManagement;
        $this->customerFactory = $customerFactory;
        $this->customerRepository = $customerRepository;
        $this->orderService = $orderService;
        $this->_pageFactory = $pageFactory;
        $this->request = $request;
        $this->resultRedirect = $context->getResultFactory();
        $this->_checkoutSession = $checkoutSession;
        $this->guestcartManagement = $guestcartManagement;
        parent::__construct($context);
    }
    public function createOrder($order)
    {
        $store = $this->storeManager->getStore();
        $websiteId = $this->storeManager->getStore()->getWebsiteId();
        $customer = $this->customerFactory->create();
        $customer->setWebsiteId($websiteId);
        $customer->loadByEmail($order['email']); // load customet by email address
        if (!$customer->getEntityId()) {
        //If not avilable then create this customer
        $customer->setWebsiteId($websiteId)->setStore($store)->setFirstname($order['shipping_address']['firstname'])->setLastname($order['shipping_address']['lastname'])->setEmail($order['email'])->setPassword($order['email']);
        $customer->save();
        }
        $quote = $this->quote->create(); // Create Quote Object
        $quote->setStore($store); // Set Store
        $customer = $this->customerRepository->getById($customer->getEntityId());
        $quote->setCurrency();
        $quote->assignCustomer($customer); // Assign quote to Customer
        //add items in quote
        foreach ($order['items'] as $item) {
        $product = $this->product->load($item['product_id']);
        $product->setPrice(59);
        $quote->addProduct($product, intval($item['qty']));
        }
        $quote->getBillingAddress()->addData($order['shipping_address']);
        $quote->getShippingAddress()->addData($order['shipping_address']);
        // Collect Rates and Set Shipping & Payment Method
        $shippingAddress = $quote->getShippingAddress();
        $shippingAddress->setCollectShippingRates(true)->collectShippingRates()->setShippingMethod('freeshipping_freeshipping');
        $quote->setPaymentMethod('cod');
        $quote->setInventoryProcessed(false);
        $quote->save();
        // Set Sales Order Payment
        $quote->getPayment()->importData(['method' => 'checkmo']);
        // Collect Totals & Save Quote
        $quote->collectTotals()->save();
        $orderId = $this->guestCartManagement->placeOrder($quote->getId());
        $orderdata->setEmailSent(0);
        $orderdata = $orderdata->getIncrementId();
    }
    public function execute()
    {
        $order = [
            'currency_id' => 'USD',
            'email' => '[email protected]',
            'shipping_address' => ['firstname' => 'John',
            'lastname' => 'Any',
            'street' => 'xxxxxx',
            'city' => 'xxxxxxx',
            'country_id' => 'US',
            'region' => 'xxxxx',
            'postcode' => '85001',
            'telephone' => '52556542',
            'fax' => '3242322556',
            'save_in_address_book' => 1],
            'items' => [
            ['product_id' => '6', 'qty' => 1],
            ]
        ];
        $this->createOrder($order);
        $resultRedirect = $this->resultRedirectFactory->create();
        $resultRedirect->setPath('checkout/onepage/success');
        return $resultRedirect;
    }
}

ANY HELP OR IDEAS OR NEW ALTERNATIVE APPROACH WOULD BE HIGHLY APPRECIATED.

THANK YOU

5
  • any thoughts on this ? Apr 3, 2022 at 9:34
  • any thoughts on this ? Apr 3, 2022 at 9:41
  • Can you please elaborate on what is exactly happening? I see you are already redirecting it to a success page. Are you being redirected to somewhere else? Apr 3, 2022 at 10:58
  • Also, I haven't checked everything in your code but if you are already creating a customer and assigning it to a quote then you should use \Magento\Quote\Api\CartManagementInterface instead of \Magento\Quote\Api\GuestCartManagementInterface otherwise your checkout method will be set as "guest". Check this link: mage2.pro/t/topic/732 Apr 3, 2022 at 11:07
  • As for session updates, whether you use CartManagementInterface or GuestCartManagementInterface it is suppose to update checkout session with last quote and order details because these ManagementInterfaces use \Magento\Quote\Model\QuoteManagement::submit($quote) internally which updates the checkout session. Apr 3, 2022 at 11:10

1 Answer 1

2

I would recommend checking the InstantPurchase module, it should be a standard part of Magento - https://docs.magento.com/user-guide/sales/checkout-instant-purchase.html

Customer requirements
  • Customer is signed in to their account.
  • Customer account has a default billing and shipping address.
  • At least one shipping method is available for the country that is specified in the default shipping address.
  • Customer account has a stored payment method with vault enabled.

The following payment methods can be used to provide secure access to saved credit card information:

  • Braintree Credit Cards
  • Braintree with PayPal Enabled
  • PayPal Payflow Pro
  • Instant Purchase cannot be used with Braintree Credit Cards if 3D Secure is enabled.

If for some reason it doesn't fulfill the use-case exactly, you can build your solution on top of it and do not reinvent the wheel https://github.com/magento/magento2/tree/2.4-develop/app/code/Magento/InstantPurchase

Anyway, to your original question:

Redirect is not possible probably because of request validation in Magento/Checkout/Controller/Onepage/Success.

The validation in Magento/Checkout/Model/Session/SuccessValidator class checks following:

 /**
 * @return bool
 */
public function isValid()
{
    if (!$this->checkoutSession->getLastSuccessQuoteId()) {
        return false;
    }

    if (!$this->checkoutSession->getLastQuoteId() || !$this->checkoutSession->getLastOrderId()) {
        return false;
    }
    return true;
}

So if you inject the correct values into the checkout session that are checked in the validator, everything should work out of the box.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.