If you need to authenticate Shoptet administrator users using Shoptet login credentials, for example to save the settings for the individual installation of your addon, you can use the OAuth server functionality.
By using this user authentication mechanism, you will be sure that the user is the actual administrator of the e-shop and you do not need to address its access credentials and authorization to edit the settings of your addon.
This is only a verification mechanism and does not allow you to save data (typically addon settings) – you must save the data yourself in your data structure.
The procedure assumes that you have an e-shop number stored in your API access token database. In other words, you need to use the correct API access token
from the e-shop number shopId
.
The first step to identify a user and their e-shop is to determine the hostname OAuth server, against which you will validate the user’s identity.
Fill in your settings URL into addons settings » tab “Description” » field “Addon settings url”.
If you use placeholder #SHOP_ID#
into the URL, it will be replaced by the actual e-shop id. For example https://www.my-server.com/shoptet/addons/my-addon/settings?eshopId=#SHOP_ID#
will be replaced by https://www.my-server.cz/shoptet/addons/my-addon/settings?eshopId=12345
If you enter #LANGUAGE#
into the URL, this will be replaced by the actual e-shop language. For example https://www.my-server.com/shoptet/addons/my-addon/settings?language=#LANGUAGE#
will be replaced by https://www.my-server.com/shoptet/addons/my-addon/setting?language=cs
From the eshopId
you receive, you will find the corresponding API access token
in your database and call the endpoint Eshop info. In the response, check array data.urls[]
and look for object with ident
having value oauth
and use the value of url
field as an OAuth server address of the user, who was logged in.
Please be aware, that domain can change, so it is recommended to register eshop:projectDomain
webhook and update the domain in your system if needed.
<?php
$baseOAuthUrl = current(array_filter($response['data']['urls'], function ($url) {
return $url['ident'] == 'oauth';
}, ARRAY_FILTER_USE_BOTH))['url'];
This will be something like https://example.myshoptet.com/action/OAuthServer/
There are two ways used in Shoptet:
You will redirect the e-shop user to the Oauth server.
$_SESSION['base_oauth_url'] = $baseOAuthUrl;
Save URL to current user (e.g. into session) – the value will be needed in the next step.
Assemble url to redirect the user to.
// $_SESSION['base_oauth_url'] contains the ending slash
$url = $_SESSION['base_oauth_url'] . 'authorize';
Add GET parameters to url:
// Your client id in OAuth server
// This is an example only, the specific value can be found in
// the e-shop administration -> Link -> API partner -> Access to API
$param['client_id'] = 'wae54...slekn';
// authorization group in OAuth server, enter 'basic_eshop'
$param['scope'] = 'basic_eshop';
To increase the security, add state
parameter.
$state = uniqid();
$_SESSION["state"] = $state;
$param['state'] = $state;
The state parameter is not mandatory, it is used as protection against XSRF attacks. The state
value must be generated and saved to the user. When you add state
to the request to the OAuth server, the parameter and its value will be added to the reply from authorization server. To check, see below.
Then you add response_type
and redirect_uri
parameters.
// response_type is always 'code'
$param['response_type'] = 'code';
// returning url (to your server), to which the OAuth server redirects the user after sucessful verification
// redirect_uri must be entered in addon settins as "URL for user authorization".
// The OAuth server inspects whether the addresses are matching;
// if the address entered in administration does not match with address sent,
// the OAuth server responds with error
$param['redirect_uri'] = 'https://www.my-server.com/shoptet/addon/my-addon/code';
// Then create the url and redirect the user to OAuth server
$url = $url . "?" . http_build_query($param);
header("Location: " . $url);
The OAuth server authenticates the user and redirects it to your redirect_uri
.
In GET parameters, you get the value code
and optionally also the state
.
$code = $_GET['code'];
$state = $_GET['state'];
// Check state parameters. When the values are different, someone other than you
// initiated the request and your code should not continue.
if ($state != $_SESSION['state]) {
die('State parameters do not macth');
}
In this case you obtain the oauth code simply from the the URL, typically GET parameters (depends on where you place the #OAUTH_CODE#
placeholder), for example:
$code = $_GET['code'];
Next step is to get the OAuth access token, which will provide you with the identity of the user or e-shop. ATTENTION: This OAuth access token is different from the OAuth access token you get when you install the addon.
The request is sent in the background, without the user’s knowledge.
$data = [
// $code is the value from the GET parameter
'code' => $code,
// grant_type is always 'authorization_code'
'grant_type' => 'authorization_code',
// Your client id in OAuth server
// This is an example only, the specific value can be found in
// e-shop administration -> Link -> API partner -> Access to API
'client_id' => '<your client id>',
// Your secret string for communication with OAuth server.
// The specific value can be found in e-shop administration -> Link -> API partner -> Access to API.
// Contact Shoptet, if client_secret is not available (for older API partners, it was not generated automatically)
'client_secret' => '<your client secret>',
// redirect_uri must be entered in addon settings as "URL for user authorization".
// The OAuth server inspects whether the addresses are matching;
// if the address entered in administration does not match with address sent, the OAuth server responds with error
'redirect_uri' => 'https://www.my-server.com/shoptet/addon/my-addon/code',
// Enter 'basic_eshop'
'scope' => 'basic_eshop'
];
$url = $_SESSION['base_oauth_url'] . 'token';
Send POST request:
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_POST, TRUE);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
die("CURL Error: " . $err);
}
The reply will contain the access_token
in JSON format:
{
"access_token": "90r3azmxy6dbxzpjfxj237cjt8rp0f4hq6uygone78i4n4zk47xb649pls1097fc0xs501hjhpv9tlj2k9hc6xhutymtthet8dzx0sm1ih7r6ml6gf6hc4dixqn48l0r5qk1ynqp0fvojief30b2f70rnedfcy2zyqhkin326ynvdv404hn1xw8nqct6rkn9h4xm9za2i53pbb8hqkmz37qdpol5yr3dciftn0vl04jfvpxg4l36lnw9vsqdyke",
"expires_in": 43200,
"token_type": "bearer",
"scope": "basic_eshop"
}
$response = json_decode($response, TRUE);
$accessToken = $response['access_token'];
The e-shop’s identity is obtained from the OAuth server response.
Submit a request to the OAuth server with an authorization header having the OAuth access token value.
Assemble the url you will be sending the request to:
$url = $_SESSION['base_oauth_url'] . 'resource?method=getBasicEshop';
The OAuth access token is sent in the request header:
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_HTTPHEADER, ['Authorization: Bearer ' . $accessToken]);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
$response = curl_exec($curl);
curl_close($curl);
If the request is processed OK, it contains $response
key success
with value true
.
{
"success":true,
"data": {
"user": {
"email": "novak@fenix.myshoptet.com",
"name": "Jan Novak"
},
"project": {
"id": 159834,
"url": "https://fenix.myshoptet.com/",
"name": "Fenix"
}
}
}
In $response
in the data object is theid
and url
, which identifies the e-shop.
$response = json_decode($response, TRUE);
$_SESSION['project_id'] = $response['data']['project']['id'];
Getting the project_id
gives you the linked current user of your pages with the e-shop administrator.
Error identification
If the error occurs, in the $response
key, there is an error
and error_description
{
"error": "You must use `client_secret`. Please contact us to obtain one.",
"error_description": null
}