Magento 2 supports REST (Representational State Transfer) and SOAP (Simple Object Access Protocol), much like the old version of Magento we were used to. Official documentation is mostly based on raw curl request without examples in some specific language. PHP is what we do and there will be many people using it as well, so we tried to give you real PHP examples of how to connect and use Magento 2 API.
There are three user types that have access to API in Magento and those are:
1) Guest user
They have access to resources with anonymous permission.
2) Administrator/Integration
They have access to resources for which are authorized by configuration.
3) Customer
They have access to resources with self or anonymus permission.
There are three types of authentication that we can use:
1) Token-based authentication
Idea here is to provide username and password during initial connection and receive the token to be used for requests that follow, until token expires.
Here is example using rest API via PHP
<?php
$userData = array("username" => "USERNAMe", "password" => "PASSWORD");
$ch = curl_init("http://www.YOUR_DOMIAN.com/rest/V1/integration/admin/token");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($userData));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-Type: application/json", "Content-Lenght: " . strlen(json_encode($userData))));
$token = curl_exec($ch);
$ch = curl_init("http://www.YOUR_DOMIAN.com/rest/V1/products/LC515");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-Type: application/json", "Authorization: Bearer " . json_decode($token)));
$result = curl_exec($ch);
var_dump($result);
Note :- make sure username is admin user with proper resources should be assigned
OAuth-based authentication
Access to API is allowed via OAuth 1.0a (https://en.wikipedia.org/wiki/OAuth).
In this case, think of Magento API as a service that allows access to resources to third party via approval gotten from resource owners.
For example, getting customer (resource owner) info from Magento API (service) from third party application (client).
This is little bit out of the scope for this article and separate article is in preparation, however there is simple example of using integration without “Identity link URL” and “Callback URL”.
What you need to do is to go to System > Integrations and add new integration without “Identity link URL” and “Callback URL”. Remember to edit resource access on API tab.
Then run this script:
<?php
function sign($method, $url, $data, $consumerSecret, $tokenSecret)
{
$url = urlEncodeAsZend($url);
$data = urlEncodeAsZend(http_build_query($data, '', '&'));
$data = implode('&', [$method, $url, $data]);
$secret = implode('&', [$consumerSecret, $tokenSecret]);
return base64_encode(hash_hmac('sha1', $data, $secret, true));
}
function urlEncodeAsZend($value)
{
$encoded = rawurlencode($value);
$encoded = str_replace('%7E', '~', $encoded);
return $encoded;
}
// REPLACE WITH YOUR ACTUAL DATA OBTAINED WHILE CREATING NEW INTEGRATION
$consumerKey = '0b3d76jra3log3i2dthslvf0fg54avjv';
$consumerSecret = 'yk8ypwrqrjepa01g3bt0f57ii6kgkqb4';
$accessToken = 'pjhpgtv3un78h83wmhcbk0s8nuxbfhx0';
$accessTokenSecret = 'ryf7sqesnrsn23aifragqywttbm3gkch';
$method = 'GET';
$url = 'http://www.YOUR_DOMIAN..com/rest/V1/products/LC515';
//
$data = [
'oauth_consumer_key' => $consumerKey,
'oauth_nonce' => md5(uniqid(rand(), true)),
'oauth_signature_method' => 'HMAC-SHA1',
'oauth_timestamp' => time(),
'oauth_token' => $accessToken,
'oauth_version' => '1.0',
];
$data['oauth_signature'] = sign($method, $url, $data, $consumerSecret, $accessTokenSecret);
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_URL => $url,
CURLOPT_HTTPHEADER => [
'Authorization: OAuth ' . http_build_query($data, '', ',')
]
]);
$result = curl_exec($curl);
curl_close($curl);
var_dump($result);
few API we need to use searchCriteria ex :-
GET http://<magento_host>/index.php/rest/V1/products?
searchCriteria[filter_groups][0][filters][0][field]=name&
searchCriteria[filter_groups][0][filters][0][value]=%25Leggings%25&
searchCriteria[filter_groups][0][filters][0][condition_type]=like&
searchCriteria[filter_groups][0][filters][1][field]=name&
searchCriteria[filter_groups][0][filters][1][value]=%25Parachute%25&
searchCriteria[filter_groups][0][filters][1][condition_type]=like
refer
http://devdocs.magento.com/guides/v2.1/howdoi/webapi/search-criteria.html
I am assuming that AppFactory\Core\Api\SettingInterface::get()
is a REST endpoint. In that case in phpdoc comments you need to define what this will return. Magento REST handler will take that value and process it to remove all data that are unnecessary. What's left will be encoded into JSON so in javascript you can retrieve it as already proper JS hash and not json-encoded string.
The trick about those endpoint is that you need to define very precisely what will you return. Magento will not be able to process something as general as "array" where you will set whatever you like.
In your case, in order not to try playing with array of strings, it will be easier to create an interface that your endpoint will return.
<?php
namespace AppFactory\Core\Api;
/**
* @api
*/
interface SettingsInterface
{
/**
* @return Data\SettingsInterface
*/
public function get();
}
Now when you return an instance of an object implementing that interface Magento will read its phpdocs and will process their return values.
Now create a file in AppFactory\Core\Api\Data\SettingsInterface
as follows
<?php
namespace AppFactory\Core\Api\Data;
interface SettingsInterface
{
/**
* @return int[]
**/
public function getSettings();
/**
* @return string[]
**/
public function getExtra();
}
Now when you create actual class that will implement those 2 get methods and you will return it in AppFactory\Core\Api\SettingsInterface::get()
then magento will return something like
{
"settings": [1, 2, 5],
"extra": ["my","array","of","strings"]
}
If you want another level you need to create another interface which will keep settings
structure and add it as a return value for AppFactory\Core\Api\Data\SettingsInterface::getSettings()
.
If you need to have something that will be dynamic and you do not want or can't prepare this structure interface then you can try setting json-encoded string and place @return string
for any of the fields. This way however you will have to make sure to manually decode that string after receiving the response as then your response will look like this:
{
"settings": [1, 2, 5],
"extra": "{\"test\":\"string\",\"value\":8}"
}
and in order to use response.extra.test
you will have to first do response.extra = JSON.parse(response.extra);
manually
Best Answer
I had the same problem, and finally I did this:
It is not the best solution but it's the only way it works.