Blog

Using Gateway Commands to call External APIs in Magento 2

Gateway command

Table of Contents

Gateway Command is a Magento payment gateway component that takes the payload required by a specific payment provider and sends, receives, and processes the provider’s response. A separate gateway command is added for each operation (authorization, capture, etc.) of a specific payment provider.

Gateway command

Gateway commands were introduced in Magento 2 to deal with payment gateways, but they can be used in other ways as well such as calling external APIs and processing their response in magento 2 applications. 

Let’s take a look at how a Gateway Command actually works.

Gateway commands

There are 5 main components of a Gateway command. They are as follows:

  • Request Builder
  • Transfer Factory
  • Gateway Client
  • Response Handler
  • Response Validator

<virtualType name="ExternalApiCall" type="Magento\Payment\Gateway\Command\GatewayCommand">
    <arguments>
        <argument name="requestBuilder" xsi:type="object">ExternalApiAuthTokenRequest</argument>
        <argument name="transferFactory" xsi:type="object">Vendor\Module\Gateway\Http\TransferFactory</argument>
        <argument name="client" xsi:type="object">Vendor\Module\Gateway\Http\Client\TransactionSale</argument>
        <argument name="handler" xsi:type="object">ExternalApiAuthTokenHandler</argument>
        <argument name="validator" xsi:type="object">Vendor\Module\Gateway\Validator\ResponseValidator</argument>
    </arguments>
</virtualType>

Let’s dive into each of the above points separately.

Request Builder

Request Builder is the component of the gateway command that is responsible for building a request from several parts. It enables the implementation of complex, yet atomic and testable, building strategies. Each builder can contain builder composites or have simple logic.

This is the component which gathers the information from different sources and creates the request payload for the API call.

Basic interface

The basic interface for a request builder is 

\Magento\Payment\Gateway\Request\BuilderInterface. Our class should always implement the above interface. The BuilderInterface has a method called “build” which takes a parameter called “buildSubject which is of type array and returns an array as a result which contains the data which you need to have in the request payload.

The parameter “buildSubject” contains the data which has been passed to the API call at the time of call from any class.

Builder composite

\Magento\Payment\Gateway\Request\BuilderComposite is a container for a list of \Magento\Payment\Gateway\Request\BuilderInterface implementations. It gets a list of classes, or types, or virtual type names, and performs a lazy instantiation on an actual BuilderComposite::build([]) call. As a result, you can have as many objects as you need, but only those required for a request for your API call are instantiated.

BuilderComposite implements the composite design pattern.

The concatenation strategy is defined in the BuilderComposite::merge() method. If you need to change the strategy, you must include your custom Builder Composite implementation.

Adding a builder composite

Dependency injection is used in di.xml to add builder composites. A builder composite may include both simple builders as well as other builder composites.

Below is an example of adding request builders through BuilderComposite class.

<virtualType name="ExternalApiAuthTokenRequest" type="Magento\Payment\Gateway\Request\BuilderComposite">
    <arguments>
        <argument name="builders" xsi:type="array">
            <item name="customer" xsi:type="string">Vendor\Module\Gateway\Request\CustomerDataBuilder</item>
            <item name="authData" xsi:type="string">Vendor\Module\Gateway\Request\AuthDataBuilder</item> 
        </argument>
    </arguments>
</virtualType>

Transfer Factory

Transfer Factory enables the creation of transfer objects with all data from request builders. Gateway Client then uses this object to send requests to the gateway processor.

Transfer Builder is used by Transfer Factory to set the required request parameters.

The basic Transfer Factory interface is Magento\Payment\Gateway\Http\TransferFactoryInterface.

The TransferFactoryInterface has a method called “create” which accepts an array parameter which has all the request data merged and sets the data as body of the API call and returns the created object for the gateway client to transfer.

Below is an example of the above method:

public function create(array $request)
 {
    return $this->transferBuilder
        ->setBody($request)
        ->build();
 }

In this example, the transfer factory simply sets request data with Transfer Builder and returns the created object

Below is an example of a more complicated behavior. Here transfer factory sets all required data to process requests using API URL and all data is sent in JSON format.

public function create(array $request)
{
    return $this->transferBuilder
        ->setMethod(Curl::POST)
        ->setHeaders(['Content-Type' => 'application/json'])
        ->setBody(json_encode($request, JSON_UNESCAPED_SLASHES))
        ->setUri($this->getUrl())
        ->build();
}

Gateway Client

Gateway Client is a component of the Magento Gateway Command that transfers the payload to the gateway provider and gets the response.

Basic interface

The basic interface for a gateway client is Magento\Payment\Gateway\Http\ClientInterface.

A gateway client receives a called Transfer object. The client can be configured with a response converter using dependency injection via di.xml.

Default implementations

The below gateway client implementations can be used out-of-the-box:

\Magento\Payment\Gateway\Http\Client\Zend

\Magento\Payment\Gateway\Http\Client\Soap

Example

Below is an example of how a Zend client can be added in di.xml:

...
<virtualType name="ExternalApiJsonConverterZendClient" type="Magento\Payment\Gateway\Http\Client\Zend">
    <arguments>
        <argument name="converter" xsi:type="object">Vendor\Module\Gateway\Http\Converter\JsonConverter</argument>
        <argument name="logger" xsi:type="object">CustomLogger</argument>
    </arguments>
</virtualType>
...

The above Converter class must implement “Magento\Payment\Gateway\Http\ConverterInterface” interface which has a method called “convert”. We can implement that method in our custom converter class and process the data and convert to the desired form.

Response Handler

Response Handler is the component of Magento Gateway Command, that processes gateway provider response. In other words, it is used to process the response received from the API. The handler class can be used to perform any type of processing on the received response data. Some of the operations may be as follows:

  • Use the API response as source of data to provide response to an internal API call.
  • Save information that was provided in the response in database.
  • Use the information as data for a new request.

Interface

Basic interface for a response handler is Magento\Payment\Gateway\Response\HandlerInterface

Useful implementations

\Magento\Payment\Gateway\Response\HandlerChain might be used as a basic container of response handlers,

The following is an example of Response Handler class:

public function handle(array $handlingSubject, array $response)
    {
        $cacheData = [];
        $oauthTokenObject = $this->oauthTokenInterfaceFactory->create();
        $this->dataObjectHelper->populateWithArray(
            $oauthTokenObject,
            $response,
            Vendor\Module\Api\Data\OauthTokenInterface'
        );
        $cacheData[OauthTokenInterface::EXPIRE_TIME] = $expiresTime;
        $cacheData[OauthTokenInterface::BEARER_TOKEN] = $oauthTokenObject->getAccessToken();
        $this->cache->save(
            $this->jsonEncoder->encode($cacheData),
            self::CACHE_ID,
            [\Magento\Framework\App\Cache\Type\Config::CACHE_TAG]
        );
    }

The above method is getting the oAuth token data in response and as part of the operation, it is storing the latest token in cache for further usage of the APIs. 

Response Validator

Response Validator is a component of the Magento Gateway Command that performs gateway response verification. This may include low-level data formatting, security verification, and even the execution of some store-specific business logic.

The Response Validator returns a Result object with the validation result as a Boolean value and the error description as a list of Phrase.

Interfaces

Response Validator must implement Magento\Payment\Gateway\Validator\ValidatorInterface

Result class must implement Magento\Payment\Gateway\Validator\ResultInterface

An external API integration can have multiple response validators, which should be added to the provider’s validator pool using dependency injection via di.xml.

Useful implementations

  • \Magento\Payment\Gateway\Validator\AbstractValidator: an abstract class with ability to create a Result object. Specific response validator implementations can inherit from this.
  • \Magento\Payment\Gateway\Validator\ValidatorComposite: a chain of Validator objects, which are executed one by one, and the results are aggregated into a single Result object.This chain can be set to terminate when certain validators fail.
  • \Magento\Payment\Gateway\Validator\Result: base class for Result object. You can still create your own Result, but the default one covers the majority of cases.

The following is an example of Response Validator:

public function validate(array $validationSubject)
    {
        $isValid = false;
        $failedExceptionMessage = [];
        if (isset($validationSubject['response']['error'])) {
            $failedExceptionMessage = [$validationSubject['response']['message']];
        } else {
            $isValid = true;
        }
        return $this->createResult($isValid, $failedExceptionMessage);
    }

The above class is extending the \Magento\Payment\Gateway\Validator\AbstractValidator class which has the “createResult” method that returns a ResultInterface as the response of the method.

To summarize the above operations, we have used Magento’s Gateway command feature which was initially developed for implementing payment gateways and utilized it for a custom API call to an external system from our Magento application. We used virtualType and type in di.xml to define the CommandPool which defined our set of commands, GatewayCommand which was the actual API command, RequestBuilder which created the request payload for the API, TransferFactory which merged all the request data and sent to gateway client, the we used the Zend Client to convert the data to JSON format. Response handler, which was used to save the response data in the cache for further use. Response Validator, to check the data received for integrity. 

Below is an example of the source of the API call where the API call starts its procedure:

public function execute(array $commandSubject)
    {
        /**
         * Setting a default request_type if not present
         *
         * @var string
         */
        $requestType = (isset($commandSubject['request_type']))
            ? $commandSubject['request_type']
            : \Zend_Http_Client::GET;

        /**
         * Setting no extra headers if none defined
         *
         * @var array
         */
        $headers = (isset($commandSubject['headers']))
            ? $commandSubject['headers']
            : [];

        $auth = (isset($commandSubject['auth']))
            ? $commandSubject['auth']
            : [];
        $transfer = $this->transferFactory->create(
            $this->requestBuilder->build($commandSubject),
            $commandSubject['url'],
            $requestType,
            [],
            $headers,
            [],
            $auth
        );

        $response = $this->client->placeRequest($transfer);
        $this->setResponse($response);

        if ($this->validator !== null) {
            $result = $this->validator->validate(
                array_merge($commandSubject, ['response' => $response])
            );
            if (!$result->isValid()) {
                $this->logExceptions($result->getFailsDescription());
                // throw actual error response
                $errorMessage = $result->getFailsDescription();
                throw new CommandException(
                    __(reset($errorMessage))
                );
            }
        }

        if ($this->handler) {
            $this->handler->handle(
                $commandSubject,
                $response
            );
        }

        return $this;
    }

All the classes required for a Gateway command to work need to be present in the Gateway Folder in your module. E.g: Vendor\Module\Gateway\. The folder structure can be as below:

  • Vendor\Module\Gateway\Command\: The base class for the command resides in this folder.
  • Vendor\Module\Gateway\Http\: The classes for TransferFactory and Client resides in this folder.
  • Vendor\Module\Gateway\Request\: The classes for RequestBuilder resides in this folder.
  • Vendor\Module\Gateway\Response\: The classes for ResponseHandlers resides in this folder.
  • Vendor\Module\Gateway\Validator\: The classes for Validators resides in this folder.

The above process can be used to call any external or internal API for that matter. This method is alot more structured way of calling an external API and it uses curl as the base as well.

Picture of Hariharasubramaniam B

Hariharasubramaniam B

Magento2 developer with strong passion for learning new tech, having good problem solving, programming and coordinating skills who tends to follow the best coding standards and practices.

You May Also Like

Latest Blogs

Magento Development Company

Let’s talk

Our Offices

DTECH, Techno Hub 1, Dubai Silicon Oasis Authority, United Arab Emirates – Dubai – United Arab Emirates

Singapore

Codilar Digital Pte Ltd, 68 Circular Road, #02-01, 049422, Singapore

India

Bengaluru

7th Floor, Jupiter Block ,Prestige Tech Park, Kadubeesanahalli, Bellandur Amanikere, Bengaluru, Karnataka 560103

Calicut

SBC No 4 & 6 upper basement, Sahya Building
KSITIL SEZ, Cyberpark Kozhikode Park Rd, Nellikkode, Kozhikode, Kerala 673016

Kolkata

Astra Towers, ANO -523 ,North Block, Action Area IIC, Newtown, Kolkata, West Bengal 700135

Ahmedabad

Codilar Technologies, Connekt, 13th Floor, Gala Empire, Opposite T.V. Tower, Drive In Rd, Memnagar, Ahmedabad, Gujarat – 380052

Oman

Building No. 2/796, Way No. 43, Block No. 336, Al Khud 132, Muscat, Oman

Codilar

© Copyright Codilar 2025. All Rights Reserved. Privacy Policy

Send Feedback

Request PWA Demo