Magento – How to get customer details in checkout_onepage_controller_success_action observer

event-observerfatal errormagento2

I am creating an observer where I want to change group id of customer after placing an order.

I am getting this error:

Fatal error: Call to a member function getCustomerId() on null in
C:\xampp\htdocs\Magento2\app\code\Vendor\MyModule\Observer\ChangeCustomerGroupAfterOrder.php
on line 30

events.xml:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">

    <event name="checkout_onepage_controller_success_action">
        <observer name="persistence_one" instance="Vendor\MyModule\Observer\ChangeCustomerGroupAfterOrder"  />
    </event>
</config>

Here is my observer/ChangeCustomerGroupAfterOrder.php

<?php

namespace Vendor\MyModule\Observer;

use Magento\Framework\Event\ObserverInterface;



class ChangeCustomerGroupAfterOrder implements ObserverInterface
{
    const CUSTOMER_GROUP_ID = 1;
    protected $_logger;
    protected $customer;
    protected $_customerRepositoryInterface;



    public function __construct(
        \Magento\Customer\Api\CustomerRepositoryInterface $customerRepositoryInterface,
         \Magento\Customer\Model\Customer $customer,
        \Psr\Log\LoggerInterface $logger
    ) {
        $this->_customerRepositoryInterface = $customerRepositoryInterface;
        $this->logger = $logger;
        $this->customer =$customer;
    }

    public function execute(\Magento\Framework\Event\Observer $observer)
    {
        $order = $observer->getEvent()->getOrder();
        foreach ($order->getAllItems() as $item) {

        }
        $customerId = $order->getCustomerId();
        $customers = $this->customer->load($customerId);
        $name = $customers->getName(); //customer name
        $groupid = $customers->getGroupId();
        $this->_logger->addDebug(' Customer ID: ' . $customerId . ', Customer Name: ' . $name . ', GroupId:' . $groupid);

        $this->logger->debug(' SUPRIYA AfterOrder Observer Is called!' . $customers->getFirstname());
        if ($customers->getGroupId() == 7) {
            $customers->setGroupId(self::CUSTOMER_GROUP_ID);
            $this->_customerRepositoryInterface->save($customers);
        }
    }
}

Best Answer

checkout_onepage_controller_success_action only dispatches the last order id:

    $this->_eventManager->dispatch(
        'checkout_onepage_controller_success_action',
        ['order_ids' => [$session->getLastOrderId()]]
    );

So you'll have to load the order first in order to get the customer id. Replace this code:

$order = $observer->getEvent()->getOrder();

With:

$orderId = $observer->getEvent()->getOrderIds();
$order = $this->_orderRepositoryInterface->get($orderId);

Then update your constructor with:

protected $_orderRepositoryInterface;

public function __construct(
    \Magento\Customer\Api\CustomerRepositoryInterface $customerRepositoryInterface,
     \Magento\Customer\Model\Customer $customer,
    \Psr\Log\LoggerInterface $logger,
    \Magento\Sales\Api\OrderRepositoryInterface $orderRepositoryInterface
) {
    $this->_customerRepositoryInterface = $customerRepositoryInterface;
    $this->_orderRepositoryInterface = $orderRepositoryInterface;
    $this->logger = $logger;
    $this->customer =$customer;
}

Suggestion

Do not load the customer using the \Magento\Customer\Model\Customer model and use service contract instead. You are already using the repository interface in your constructor so you only need to remove those lines:

\Magento\Customer\Model\Customer $customer,

And:

$this->customer =$customer;

And:

protected $customer;     

Finally, you can replace:

$customers = $this->customer->load($customerId);

With:

$customers = $this->_customerRepositoryInterface->getById($customerId);
Related Topic