Magento 2 – Address verification using USPS API on checkout.

This blogpost is related with address verification using USPS on one page checkout page. Address verification is a very critical part of any E-Commerce application. We have to make sure that address is deliverable, in this post we are using USPS APIs for this.

Note: In this post we are only validating US address as USPS stands for United State Postal Services. 

You can create a different module for this, or if you already have then add below code. If you don’t know how to create module in Magento 2 Then, Follow this.

Let’s verify the address in onepage checkout before order place.

Here I am using my existing module and making some changes for the same.

I have a module /var/www/html/Project_name/app/code/W3solver/TwilioIntegration/. I am using Ubuntu so my path is like this if anyone is using Mac or window path till project name will vary. Create a di.xml file on below path and add the given code, which will override magento core checkout module payment information model:

/var/www/html/Project_name/app/code/W3solver/TwilioIntegration/etc/di.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <preference for="Magento\Checkout\Model\PaymentInformationManagement" type="W3solver\TwilioIntegration\Model\PaymentInformationManagement" />
</config>

Now create the overriden file (PaymentInformationManagement.php) at below path.

/var/www/html/bigmoon/app/code/WestAgile/TwilioIntegration/Model/PaymentInformationManagement.php

Add the below code to your file

<?php
namespace  W3solver\TwilioIntegration\Model;

use Magento\Framework\Exception\CouldNotSaveException;
class PaymentInformationManagement extends \Magento\Checkout\Model\PaymentInformationManagement {

    public function savePaymentInformationAndPlaceOrder(
        $cartId,
        \Magento\Quote\Api\Data\PaymentInterface $paymentMethod,
        \Magento\Quote\Api\Data\AddressInterface $billingAddress = null
    ) {

    	$objectManager = \Magento\Framework\App\ObjectManager::getInstance();

        if(Your_condition )// if you want run this in every condition if(1)
        {
           $address_details = $billingAddress->getStreet();
           $address_detail = $address_details[0];
           $final_address = $address_detail.",".$address_details[1];
           $city = $billingAddress->getCity();
           $state = ($billingAddress->getRegionId() =='12')? 'CA' : 'navada';
           $zipcode = $billingAddress->getPostCode();

           $response =  $this->getStateName($final_address,$city,$state,$zipcode);

           if($response==0)
           {
              throw new CouldNotSaveException(__('Please re-check your shipping address'));
              return false;

           }else{
           $this->savePaymentInformation($cartId, $paymentMethod, $billingAddress);
           try {
                $orderId = $this->cartManagement->placeOrder($cartId);
           } catch (\Exception $e) {
                throw new CouldNotSaveException(
                __('An error occurred on the server. Please try to place the order again.'), $e
                );
           }
            return $orderId;
        }
            //echo $response;
        }
    }

    public function getStateName($final_address,$city,$state,$zipcode){
        $input_xml = <<<EOXML
               <AddressValidateRequest USERID="Your USPS User ID will Come here">
               <Revision>1</Revision>
               <Address ID="0">
               <Address1>$final_address</Address1>
               <Address2></Address2>
               <City>$city</City>
               <State>$state</State>
               <Zip5>$zipcode</Zip5>
               <Zip4></Zip4>
               </Address>
               </AddressValidateRequest>
        EOXML;

        $fields = array(
                'API' => 'Verify',
                'XML' => $input_xml
            );
        $url = 'http://production.shippingapis.com/ShippingAPITest.dll?' . http_build_query($fields);

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 300);
        $data = curl_exec($ch);
        curl_close($ch);

        // Convert the XML result into array
        $array_data = json_decode(json_encode(simplexml_load_string($data)), true);

        if (array_key_exists("Error",$array_data['Address'])){
            return  0;
        }else{
            return 1;
        }
  }
}

Go to your Magento 2 installation from terminal and run “php bin/magento setup:upgrade“.

Try this solution and let us know your thoughts.

Magento 2 – Helloworld – Create Event and Observer

In this blogpost we will learn how to create event and observer in Magento2. Events observer is an important feature to extend core functionality of Magento without overriding. We can attach multiple observer to a single event and add our feature on top of magento core module.

How to setup events

To setup an event we mainly have three steps:-
1. Code from where an event will dispatch
2. Event xml file to know event name for which observer is created.
3. Observer file for our event(this will have the extended functionality)
There are three area for creating events configuration file i.e, events.xml file
1. Under etc/ folder: – This file has configuration which can be used in both admin and frontend area.
2. Under etc/frontend folder: – This file has configuration which can be used for frontend area.
3. Under etc/adminhtml folder: – This file has configuration which can be used for admin area.

Now we will be creating an event observer for ‘customer login’ and will log customer firstname on login of customer in magento application. Let start with the coding part:-
1. Create event.xml

 W3solver/Helloworld/etc/frontend/events.xml

So, in below code we have provided ‘customer_login’ as an event name, observer name is a unique identifier and instance contains class path to our observer file.


<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="customer_login">
        <observer name="w3solver_helloworld_customer_login" instance="W3solver\Helloworld\Observer\login" />
    </event>
</config>

2. Now we have to create observer file with the same path as provided in above class, observer class will extends Observer Interface and our code will be in execute function.

 W3solver\Helloworld\Observer\login.php

namespace W3solver\Helloworld\Observer;
 
use \Psr\Log\LoggerInterface;
use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
 
class Login implements ObserverInterface
{
    
    protected $logger;
   
    public function __construct(LoggerInterface $logger)
    {
        $this->logger = $logger;
    }
 
    public function execute(Observer $observer)
    {
        $customer = $observer->getCustomer();
        $this->logger->warn('Customer Logged IN:' . $customer->getFirstname());
    }
}
 

Now you can check your system.log to get customer firstname.

Dispatch Event

To add your own custom event, you need to add below line of code at a place where you want event to dispatch:-

 $this->_eventManager->dispatch('helloworld_first_event', ['hello_content' => 'you have succesfully created first event']); 

Above code dispatch an event with name “helloworld_first_event” and attached a variable “hello_content”.

How to Join Tables in Magento 2

Joining table in Magento 2 is similar to magento 1, which we normally need to perform our various operation. In this blogpost we will see how to join tables in Magento 2.

Step 1

Setup a collection class as we have did in our last blog post

W3solver\Helloworld\Model\ResourceModel\Hello\Collection.php
<?php 
namespace W3solver\Helloworld\Model\ResourceModel\Hello;

class Collection extends \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection
{
    /**
     * @var string
     */
    protected $_idFieldName = 'id';

    /**
     * Define resource model
     *
     * @return void
     */
    protected function _construct()
    {
        $this->_init('W3solver\Helloworld\Model\Hello', 'W3solver\Helloworld\Model\ResourceModel\Hello');
    }

}

Step 2

Now we will place function that will join two of our tables and will give us the query to join. We will be injecting our hello model in block class constructor to get the collection and will join it with another table in getJoinData function.

<?php

namespace W3solver\Helloworld\Block;

class Hello extends \Magento\Framework\View\Element\Template {

    protected $_helloModelFactory;
    protected $_resource;
    
    public function __construct(
    \Magento\Framework\View\Element\Template\Context $context,
    \W3solver\Helloworld\Model\HelloFactory $helloModelFactory,
    \Magento\Framework\App\ResourceConnection $Resource
    ) {
        $this->_helloModelFactory = $helloModelFactory;
        $this->_resource = $Resource;
        
        parent::__construct($context);
    }

    protected function _prepareLayout()
    {
        $text = $this->getJoinData();
        $this->setText($test);
    }
    
    public function getJoinData(){
        $collection = $this->_helloModelFactory->create()->getCollection();
        $second_table_name = $this->_resource->getTableName('second_table_name'); 
        
        $collection->getSelect()->joinLeft(array('second' => $second_table_name),
                                               'main_table.id = second.customer_id');
        echo $collection->getSelect()->__toString(); 
        exit();
        
    }
} 

Above we have injected hello model of first table and resourceConnection class to get table name. Then we get the collection of first table which is by default alias as “main_table” in magento. This will give you the query which you can verify as per your requirement.

Magento 2- Helloworld – Add new table and access using model

In this blogpost we will focus on to create a new table and add some data into it. Then we will be saving some data to table and will get the data using model class. We will be covering:-

Setup file
Models
Resource Models
Collection Models

Step 1

We will first create setup file, Magento 2 has installSchema.php file, which is executed on installation of module and is responsible for schema related modification in database. There is no version related concept in Magento2 for setup files as it was in Magento 1.
In our setup script we will be creating a table ‘w3solver_helloworld’ which has following field:-

Id
Title
Created At
Updated At
W3solver\Helloworld\Setup
<?php

namespace W3solver\Helloworld\Setup;

class InstallSchema implements \Magento\Framework\Setup\InstallSchemaInterface {

    public function install(\Magento\Framework\Setup\SchemaSetupInterface $setup, \Magento\Framework\Setup\ModuleContextInterface $context) {

        $installer = $setup;
        $installer->startSetup();

        $table = $installer->getConnection()->newTable(
                                $installer->getTable('w3solver_helloworld')
                        )->addColumn(
                                'id', \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER, null, [ 'identity' => true, 'nullable' => false, 'primary' => true, 'unsigned' => true,], 'ID')
                        ->addColumn(
                                'title', \Magento\Framework\DB\Ddl\Table::TYPE_TEXT, 255, [ 'nullable' => false,], 'Title')
                        ->addColumn(
                                'created_at', \Magento\Framework\DB\Ddl\Table::TYPE_TIMESTAMP, null, [ 'nullable' => false, 'default' => \Magento\Framework\DB\Ddl\Table::TIMESTAMP_INIT,], 'Created At'
                        )->addColumn(
                'updated_at', \Magento\Framework\DB\Ddl\Table::TYPE_TIMESTAMP, null, [ 'nullable' => false, 'default' => \Magento\Framework\DB\Ddl\Table::TIMESTAMP_INIT_UPDATE,], 'Updated At'
        );
        $installer->getConnection()->createTable($table);

        $installer->endSetup();
    }

}

You need to execute setup:upgrade command to see the table in database. If even after running the command table is not created then you need to review setup_module table and execute the following sql

DELETE from setup_module where module = 'W3solver_Helloworld';

Step 2

Now we have got the table definition installed, lets take a look at CRUD Model files.
We will be covering about four files:-

W3solver/Helloworld/Model/Hello.php
W3solver/Helloworld/Model/ResourceModel/Hello.php
W3solver/Helloworld/Model/ResourceModel/Hello/Collection.php
W3solver/Helloworld/Model/HelloInterface.php

Firstly lets create a base model:-

<?php

namespace W3solver\Helloworld\Model;

class Hello extends \Magento\Framework\Model\AbstractModel implements HelloInterface, \Magento\Framework\DataObject\IdentityInterface
{
    const CACHE_TAG = 'w3solver_helloworld';
 
    protected function _construct()
    {
        $this->_init('W3solver\Helloworld\Model\ResourceModel\Hello');
    }
 
    public function getIdentities()
    {
        return [self::CACHE_TAG . '_' . $this->getId()];
    }
    
    public function getId()
    {
        return $this->getData(self::ID);
    }

    public function getTitle()
    {
        return $this->getData(self::TITLE);
    }

    public function getCreatedAt()
    {
        return $this->getData(self::CREATED_AT);
    }

    public function getUpdatedAt()
    {
        return $this->getData(self::UPDATED_AT);
    }

    public function setId($id)
    {
        return $this->setData(self::ID, $id);
    }

    public function setTitle($title)
    {
        return $this->setData(self::TITLE, $title);
    }

    public function setCreatedAt($created_at)
    {
        return $this->setData(self::CREATED_AT, $created_at);
    }

    public function setUpdatedAt($updated_at)
    {
        return $this->setData(self::UPDATED_AT, $updated_at);
    }

}
?>

All Magento CRUD model extends

 Magento\Framework\Model\AbstractModel

And as you have seen that this model is implementing HelloInterface and IdentityInterface. IdentityInterface forces developer to implement a getidentities function

public function getIdentities()
    {
        return [self::CACHE_TAG . '_' . $this->getId()];
    }

This interface is basically used for model which require cache refresh after CRUD operations. Method getIdentities will return a unique id for each instance of this model, which is cacheable.
Apart from this model class has also implemented HelloInterface. Magento 2 strongly recommends to use PHP Interfaces, Interface plays important role when we use service contracts based API. So we will be creating an interface for our model. We will be adding all getter and method in the interface.

W3solver\Helloworld\Model\HelloInterface
<?php
namespace W3solver\Helloworld\Model;

interface HelloInterface
{
    const ID     = 'id';
    const TITLE    = 'title';
    const CREATED_AT = 'created_at';
    const UPDATED_AT   = 'updated_at';
    
    public function getId();

    public function getTitle();

    public function getCreatedAt();

    public function getUpdatedAt();

    public function setId($id);

    public function setTitle($title);

    public function setCreatedAt($createdAt);

    public function setUpdatedAt($updatedAt);

}

Step 3

Model mainly contain the overall database logic but actual sql queries get executed using resource model. So lets have our resource model

W3solver\Helloworld\Model\ResourceModel\Hello.php
<?php

namespace W3solver\Helloworld\Model\ResourceModel;

class Hello extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb {

    protected $_date;

    public function __construct(
    \Magento\Framework\Model\ResourceModel\Db\Context $context, \Magento\Framework\Stdlib\DateTime\DateTime $date, $resourcePrefix = null
    ) {
        parent::__construct($context, $resourcePrefix);
        $this->_date = $date;
    }

    protected function _construct() {
        $this->_init('w3solver_helloworld', 'id');
    }

    protected function _beforeSave(\Magento\Framework\Model\AbstractModel $object) {

        if ($object->isObjectNew() && !$object->hasCreatedAt()) {
            $object->setCreatedAt($this->_date->gmtDate());
        }

        $object->setUpdatedAt($this->_date->gmtDate());

        return parent::_beforeSave($object);
    }

}

Collection

W3solver\Helloworld\Model\ResourceModel\Hello\Collection.php
<?php 
namespace W3solver\Helloworld\Model\ResourceModel\Hello;

class Collection extends \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection
{
    /**
     * @var string
     */
    protected $_idFieldName = 'id';

    /**
     * Define resource model
     *
     * @return void
     */
    protected function _construct()
    {
        $this->_init('W3solver\Helloworld\Model\Hello', 'W3solver\Helloworld\Model\ResourceModel\Hello');
    }

}

Step 4

Now we will be changing our block file to get the text value from table/model.

<?php

namespace W3solver\Helloworld\Block;

class Hello extends \Magento\Framework\View\Element\Template {

    protected $_helloModelFactory;
    
    public function __construct(
    \Magento\Framework\View\Element\Template\Context $context,
    \W3solver\Helloworld\Model\HelloFactory $helloModelFactory
    ) {
        $this->_helloModelFactory = $helloModelFactory;
        parent::__construct($context);
    }

    protected function _prepareLayout()
    {
/* Since our table is just created so here we are first making an entry in database*/
        $test = $this->_helloModelFactory->create();
        $test->setTitle('Hello World');
        $test->save();
        $this->setText($test->getData('title'));
    }
}

Magento 2- Hello World – Layout/Blocks

So in our previous blog we have shown text using controller but now we will show it through our template file by using layout and block, and this is the recommended way. We will be using the module created in previous blog W3solver_Helloworld

Step1

Now we will be replacing the controller execute function code so that we can call layout file and render the output. In Magento 2 we do not have Mage class to initialize block, model, helper, here we use dependency injection i.e, whatever functions we want to use we will be injecting those classes through constructor such as we did in below code by injecting ‘PageFactory’

 W3solver/Helloworld/Controller/Hello/Index.php 
<?php
namespace W3solver\Helloworld\Controller\Hello;

 class Index extends \Magento\Framework\App\Action\Action
{
    protected $_resultPageFactory;
    
    public function __construct(
        \Magento\Framework\App\Action\Context $context,
        \Magento\Framework\View\Result\PageFactory $resultPageFactory)
    {
        $this->_resultPageFactory = $resultPageFactory;  
        return parent::__construct($context);
    }
     
    public function execute()
    {
        return $this->_resultPageFactory->create(); 
    } 
}

Step 2

Now we will be creating our layout file, in Magento 2 for every route layout file is different, the handle in magento1 are now converted to a separate new files in Magento2. We have one default.xml file where we can put code which needs to be called for all action. All of our layout file stays at

view/frontend/layout

Path of our layout file is

W3solver/Helloworld/view/frontend/layout/helloworld_hello_index.xml
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd">       
    <referenceContainer name="content">
        <block template="hello.phtml" class="W3solver\Helloworld\Block\Hello" name="hello"/>
    </referenceContainer>
</page>

Step 3

Above file tells the template to be used and block class name, thus in this step we will create our block class and template file. Here we have set some text so that we can retrieve it in our template

W3solver/Helloworld/Block/Hello.php
namespace W3solver\Helloworld\Block;

class Hello extends \Magento\Framework\View\Element\Template {
    public function __construct(
    \Magento\Framework\View\Element\Template\Context $context
    ) {
        parent::__construct($context);
    }

    protected function _prepareLayout()
    {
        $this->setText('Hello World');
    }
}

In Magento2 all template file reside in view/frontend/templates folder. Our template file path will be

W3solver/Helloworld/view/frontend/template/hello.phtml
<?php echo $block->getText(); ?>

If everything is followed correctly then you must be able to get the text through template, just drop in your comments if you have any issues.

Magento2 – HelloWorld – Module Development Part-1

In this blog post we will see how to create a simple hello world module in magento2. In magento2 we do not have code pool, all our module resides in app/code folder. This blog will result in a very basic module that will print text “hello world” through controller.

Step 1

We have name our module as W3solver_Helloworld where W3solver is Namespace and Helloworld is our module name. Similar to magento1 we will create W3solver/Helloworld folder

app/code/W3solver/Helloworld

Step 2

Now, we will register our module by creating registration.php file and adding following code in it.

app/code/W3solver/Helloworld/registration.php
<?php
\Magento\Framework\Component\ComponentRegistrar::register(
        \Magento\Framework\Component\ComponentRegistrar::MODULE, 'W3solver_Helloworld', __DIR__
); 

Step 3

Create a module.xml file

app/code/w3solver/Helloworld/etc/module.xml
<?xml version="1.0" encoding="UTF-8"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="W3solver_Helloworld" schema_version="1.0.0" setup_version="1.0.0" >
    </module>
</config>

Step 4

Now your module is ready and we can enable it by running setup:upgrade command

Path_to_magento_directory >php bin\magento setup:upgrade

After executing above command you can assure that your module is enabled by checking in config.php file in app/code/W3solver/Helloworld/etc/config.php, there must be one line added:-

...
'W3solver_Helloworld' => 1,
....

Step 5

Now let’s create a url or route for our module. As in Magento1 routes are divided into 3 parts module_route_id/controllername/actionname
This firstly we have to write code for defining route_id, for that we will create routes.xml, path for route file depend whether we are creating admin or frontend controller. If we are creating frontend controller then we have following path and code

W3solver/Helloworld/etc/frontend/routes.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
    <router id="standard">
        <route id="helloworld" frontName="helloworld">
            <module name="W3solver_Helloworld" />
        </route>
    </router>
</config>

Next, we have to define our controller and action
Suppose our controller name is hello and action is index, so we will create a index.php controller file

W3solver/Helloworld/Controller/Hello/Index.php
<?php
namespace W3solver\Helloworld\Controller\Hello;
  
class Index extends \Magento\Framework\App\Action\Action
{
    public function __construct(
        \Magento\Framework\App\Action\Context $context)
    {
        return parent::__construct($context);
    }
     
    public function execute()
    {
        echo 'Hello World';
        exit;
    } 
}

If everything is followed correctly then you must be viewing “hello world” text.

http://XXX/helloworld/hello/index

Output

Hello World