Magento 2 Token Based Authentication
The purpose of this document is to give good understanding of how we will integrate to City Chic Magento 2 as they have build their own custom API which differs from the standard Magento 2 REST API. Official CityChic document:
The client have prepared an UAT environment where we can conduct all our tests and the API documentation for the UAT environment can be found here in Swagger https://ccadmin-m2.stage.guidance.com/swagger however in order to access it your IP need to be whitelisted (If you use VPN should be able to access it) also in order all the links mentioned in the scope to work properly first you need to generate your token and place it in the swagger (top right corner).
The backend admin portal for our UAT environment is located at https://ccadmin-m2.stage.guidance.com/sfgadmin
This domain is IP restricted; your IP will need to be whitelisted in order to access it. To get started please contact me in order to request the IP whitelist.
There is a user account setup for WAP: Username: pentagon Password: Bob1rad1 Email: radoslav.chernaev@wearepentagon.com
Please note that there is Google Auth and you will need to contact me for the authentication key.
Their UAT environment has the following stores setup:
Reseller Name | Store ID | Store Code | Warehouse Code |
---|---|---|---|
Walmart | 31 | walmart_us | us_online |
Amazon USA | 32 | amazon_us | us_online |
David Jones AU | 33 | david_jones_au | au_online |
Zalando | 34 | zalando | -- |
General overview of the integration
New Hemi Tables and their fields: account_magento orders_magentoorder_item_magentomagento2_connectormagento2_sellerorder_payment_magento2
orders_magento | Default Value | |
---|---|---|
Shipment Created | checkbox true or false | false |
Shipment ID | Array (we can have more than 1 id) | 0 |
Order Payment ID | integer | 0 |
account_magento | Default Value | |
---|---|---|
Magento 2 Seller | dropdown from where the relevant magneto 2 details will be picked | Empty Value |
order_item_magento | Default Value | |
---|---|---|
Item Id | integer | Empty Value |
magento2_seller (slave table of magento2_connector) | Default Value |
---|
magento2_connector | Default Value | |
---|---|---|
Username | text field | Empty Value |
Password | password field | Empty Value |
Endpoint | text field | Empty Value |
Active | checkbox true or false | false |
order_payment_magento2 (slave table of order_payment) | Default Value | |
---|---|---|
Return Created | checkbox true or false | false |
Return ID | integer field | Empty Value |
magento2_seller (slave table of magento2_connector) | Default Value | |
---|---|---|
Seller | dropdown from where we can select all our Hemi sellers | Empty Value |
Store ID | integer field | Empty Value |
Location | dropdown from where we can select all our Hemi locations | Empty Value |
Account | dropdown from where we can select all our Hemi accounts | Empty Value |
Store Code | text filed | Empty Value |
Warehouse Code | text filed | Empty Value |
Get Inventory | checkbox true or false | false |
Export Orders | checkbox true or false | false |
Get Products | checkbox true or false | false |
Create Shipments | checkbox true or false | false |
Create Return | checkbox true or false | false |
Get Shipments | checkbox true or false | false |
Sent Customer Notification | checkbox true or false | false |
Why do we need all this because we are covering the both flows creating orders in Mangeto and downloading orders from Magento. When we are creating orders in Magento we need to know for which magento store id we are creating them Ebay - Store id:10, Amazon - Store id:20 etc thus in Magento 2 Connector table we will have which Hemi account to which Magento Store ID relates.
In the other case when are getting orders from Magento we will need to have Account Magento where to store the orders.
We can have as many as we need Mangento2 Connections and the crons should run for each active connection.
TOKEN BASED AUTHENTICATION
You will be able to get an access token to the API by making a request similar to this
curl -X POST "https://ccadmin-m2.stage.guidance.com/index.php/rest/V1/integration/admin/token"
-H "Content-Type:application/json"
-d '{"username":"pentagon", "password":"xxxxxx"}'
The token will expire after 24 hours and we will need to check if the token is active before every request. The token and the expiration date will be stored in magento2_connector for the relevant record.
Magento Search Criteria Logic
Here is some documentation on how to create filters in requests for the Magento API https://devdocs.magento.com/guides/v2.4/rest/performing-searches.html
searchCriteria[filter_groups][0][filters][0][field]=updated_at&
searchCriteria[filter_groups][0][filters][0][value]=2020-08-23 00:00:00&
searchCriteria[filter_groups][0][filters][0][condition_type]=from&
searchCriteria[filter_groups][1][filters][0][field]=status&
searchCriteria[filter_groups][1][filters][0][value]=shipped
Basically we are specifying field, value and condition_type. Field indicates which field we would like to filter then the value will be our latest order read record for the cron minus 15 minutes and the condition type is just to say from that period.
Error Handling
There are two types of error payloads we might recieve. One is if the json format is not correct we will get a response like:
<!doctype html>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>There has been an error processing your request</title>
<base href="https://ccadmin-m2.stage.guidance.com/errors/citychic/" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="robots" content="*" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="css/styles.css" type="text/css" />
<link rel="icon" href="images/favicon.ico" type="image/x-icon" />
<link rel="shortcut icon" href="images/favicon.ico" type="image/x-icon" />
</head>
<body>
<h2 style="display:none;">::CLOUDFLARE_ERROR_500S_BOX::</h2>
<div class="page">
<div class="header-container">
<div class="header">
<a href="/" title="City Chic" class="logo"><img src="images/logo.jpg" alt="City Chic" /></a>
</div>
</div>
<div class="main-container">
<main class="page-main">
<h1>There has been an error processing your request</h1>
<p><em>Exception printing is disabled by default for security reasons.</em></p>
<p>Error log record number: d67024305dd84e2e632f2437ae2c7965a85018669a570a72d9970387fd31548d</p>
</main>
</div>
<div class="footer-container">
<div class="footer">
<address class="copyright">Copyright © 2020 City Chic</address>
</div>
</div>
</div>
</body>
</html>
If we have such response we need to store and error like “There has been an error processing your request
. Error log record number: d67024305dd84e2e632f2437ae2c7965a85018669a570a72d9970387fd31548d
“
If the json format is correct but for some reason the request can not be processed we will recieve response like:
{
"message": "Maximum shipping amount allowed to refund is: %1",
"parameters": [
"£0.99"
]
}
There may have many parameters but the important information is from message and as an error we store : "Maximum shipping amount allowed to refund is: 0.99"
Please note %1 related to the first parameter so we in the error we will need to store"Maximum shipping amount allowed to refund is: 0.99"
OAUTH BASED AUTHENTICATION
Full doc details available here - https://devdocs.magento.com/guides/v2.4/get-started/authentication/gs-authentication-oauth.html
As the process of registering the integration proceeds, Magento creates the tokens that the application needs for authentication. It first creates a request token. This token is short-lived and must be exchanged for an access token. Access tokens are long-lived and will not expire unless the merchant revokes access from the application.

The flow will include couple of steps once Magento 2 provides the OAuth consumer key and secret we can use the to obtain request token and request token secret. Then we have one more step which uses the request token in order to obtain the access token and access token secret.
POST Request token and request token secret
API CALL - POST /oauth/token/request
You must include these request parameters in the Authorization
header in the call:
PARAMETER | Mapping | DESCRIPTION |
---|---|---|
oauth_consumer_key |
The consumer key is generated when you create the integration. | |
oauth_signature_method |
The name of the signature method used to sign the request. Must be the value HMAC-SHA1 . |
|
oauth_signature |
A generated value (signature) | |
oauth_nonce |
A random value that is uniquely generated by the application. | |
oauth_timestamp |
A positive integer, expressed in the number of seconds since January 1, 1970 00:00:00 GMT. | |
oauth_version |
The OAuth version. |
The response contains these fields:
-
oauth_token
. The token to be used when requesting an access token.oauth_token_secret
. A secret value that establishes ownership of the token.
A valid response looks like this:
oauth_token=4cqw0r7vo0s5goyyqnjb72sqj3vxwr0h&oauth_token_secret=rig3x3j5a9z5j6d4ubjwyf9f1l21itrr
POST Access token and access token secret
API CALL - POST /oauth/token/access
The request token must be exchanged for an access token. Use the following API to get an access token from Magento:
You must include these request parameters in the Authorization
header in the call:
PARAMETER | Mapping | DESCRIPTION |
---|---|---|
oauth_consumer_key |
The consumer key value that you retrieve after you register the integration. | |
oauth_nonce |
A random value that is uniquely generated by the application. | |
oauth_signature |
A generated value (signature) | |
oauth_signature_method |
The name of the signature method used to sign the request. Must be the value HMAC-SHA1 . |
|
oauth_timestamp |
A positive integer, expressed in the number of seconds since January 1, 1970 00:00:00 GMT. | |
oauth_version |
The OAuth version. | |
oauth_token |
The oauth_token value, or request token, obtained in |
Get a request token
. |
| oauth_verifier
| | The verification code that is tied to the consumer and request token. It is sent as part of the initial POST operation when the integration is activated. |
A valid response looks like this: oauth_token=0lnuajnuzeei2o8xcddii5us77xnb6v0&oauth_token_secret=1c6d2hycnir5ygf39fycs6zhtaagx8pd
The response contains these fields:
-
oauth_token
. The access token that provides access to protected resources.oauth_token_secret
. The secret that is associated with the access token.
Generating the OAuth-singature
All OAuth handshake requests and Web Api requests include the signature as part of Authorization header. Its generated as follows:
You concatenate a set of URL-encoded attributes and parameters to construct the signature base string.
Use the ampersand (&
) character to concatenate these attributes and parameters:
- HTTP method
- URL
-
oauth_nonce
oauth_signature_method
oauth_timestamp
oauth_version
oauth_consumer_key
oauth_token
To generate the signature, you must use the HMAC-SHA1 signature method. The signing key is the concatenated values of the consumer secret and token secret separated by the ampersand (&
) character (ASCII code 38), even if empty. You must use parameter encoding to encode each value.
Changes in the WEB APIs
After the integration is authorized to make API calls, third-party applications (registered as integrations in Magento) can invoke Magento web APIs by using the access token.
To use the access token to make web API calls:
GET /rest/V1/products/1234
You must include these request parameters in the Authorization
request header in the call:
-
oauth_consumer_key
. The customer key value provided after the registration of the application.oauth_nonce
. A random value, uniquely generated by the application.oauth_signature_method
. The name of the signature method used to sign the request. Valid values are:HMAC-SHA1
,RSA-SHA1
, andPLAINTEXT
.oauth_signature
. A generated value (signature).oauth_timestamp
. A positive integer, expressed in the number of seconds since January 1, 1970 00:00:00 GMT.oauth_token
. Theoauth_token
, or access token, value obtained in Get an access token.