Skip to content

Latest commit

 

History

History
294 lines (205 loc) · 15.6 KB

README.md

File metadata and controls

294 lines (205 loc) · 15.6 KB

AmazonDRS

This library allows your agent code to work with the Amazon Dash Replenishment Service via the RESTful API.

This version of the library supports the following functionality:

  • Device authentication on the Dash Replenishment Service
  • Placing test orders for Amazon goods
  • Canceling test orders
  • Placing real orders for Amazon goods

To add this library to your project, add #require "AmazonDRS.agent.lib.nut:1.0.0" to the top of your agent code.

Library Usage

Prerequisites

Before using the library you need to have:

Authentication

This library needs a Refresh Token to be able to call the Amazon's DRS API. The Refresh Token can be acquired with the login() method. Also, it can be acquired with any other application-specific way and then passed in with the setRefreshToken() method.

The login() method provides the following authentication flow:

  1. a user opens the agent's URL in a browser
  2. the library handles this request and redirects the user to the Amazon login page or to the Amazon device's settings page if the user is already logged in
  3. the user sets up the device in the Amazon's UI
  4. the Amazon's LWA redirects the user back to the agent's URL with an authorization code
  5. the agent receives this code and acquires security tokens (Refresh Token and Access Token)

More about authentication here and here. Also, see the provided example.

Note: After each restart of the agent the Refresh Token should be passed in to the library. So if you don't want to go through the authentication steps again, you may save the token in the agent's persistent storage and set it with the setRefreshToken() method after each restart of the agent.

Test Orders

For testing purposes, Amazon DRS allows making test orders. Test orders are those that made by a DRS device authenticated as a test device. So it is determined at the step of authentication whether the device is for testing or not. Due to this the login() method has a parameter testDevice. But if you set a Refresh Token manually with the setRefreshToken() method, only you know whether this token was obtained for testing or not and such testDevice parameter is not required here.

Only test orders can be canceled with the cancelTestOrder() method.

Callbacks

All requests that are made to the Amazon platform occur asynchronously. Every method that sends a request has an optional parameter which takes a callback function that will be executed when the operation is completed, whether successfully or not. The callback’s parameters are listed in the corresponding method description, but every callback has at least one parameter, error. If error is 0, the operation has been executed successfully. Otherwise, error is a code of an error.

AmazonDRS Class

Constructor: AmazonDRS(clientId, clientSecret)

This method returns a new AmazonDRS instance.

Parameter Data Type Required? Description
clientId String Yes Client ID of your LWA Security Profile. For information, please see here.
clientSecret String Yes Client Secret of your LWA Security Profile. For information, please see here.

login(deviceModel, deviceSerial[, onAuthenticated[, testDevice]])

This method allows to authenticate the agent on the Amazon and get required security tokens. The method automatically sets the obtained tokens to be used for DRS API calls, so you do not need to call the setRefreshToken() method. For more information, please read about authentication.

Either this method or setRefreshToken() should be called and authentication should be done before making any DRS-related requests.

If you are going to use this method, please add #require "Rocky.class.nut:2.0.1" to the top of your agent code.

If the Rocky library is not included, the method will throw an exception.

Parameter Data Type Required? Description
deviceModel String Yes Device Model. For information, please see here.
deviceSerial String Yes Device Serial. For information, please see here.
onAuthenticated Function Optional Callback called when the operation is completed or an error happens.
testDevice Boolean Optional True if it is a test device. False by default. For more information, please see here and the Test Orders section.

The method returns nothing. A result of the operation may be obtained via the onAuthenticated callback if specified in this method.

Callback: onAuthenticated(error, response)

Parameter Data Type Description
error Integer 0 if the authentication is successful, an error code otherwise. See possible HTTP error codes here.
response Table Key-value table with the response provided by Amazon server. May be null. See here about the response format. Also may contain error details described here and here.

Example

#require "Rocky.class.nut:2.0.1"
#require "AmazonDRS.agent.lib.nut:1.0.0"

const AMAZON_DRS_CLIENT_ID = "<YOUR_AMAZON_CLIENT_ID>";
const AMAZON_DRS_CLIENT_SECRET = "<YOUR_AMAZON_CLIENT_SECRET>";
const AMAZON_DRS_DEVICE_MODEL = "<YOUR_AMAZON_DEVICE_MODEL>";
const AMAZON_DRS_DEVICE_SERIAL = "<YOUR_AMAZON_DEVICE_SERIAL>";

testDevice <- true;

function onAuthenticated(error, response) {
    if (error != 0) {
        server.error("Error authenticating: code = " + error + " response = " + http.jsonencode(response));
        return;
    }
    server.log("Successfully authenticated!");
}

client <- AmazonDRS(AMAZON_DRS_CLIENT_ID, AMAZON_DRS_CLIENT_SECRET);
client.login(AMAZON_DRS_DEVICE_MODEL, AMAZON_DRS_DEVICE_SERIAL, onAuthenticated.bindenv(this), testDevice);

setRefreshToken(refreshToken)

This method allows setting a Refresh Token manually. For more information, please read about authentication.

Either this method or login() should be called and authentication should be done before making any DRS-related requests.

Parameter Data Type Required? Description
refreshToken String Yes A Refresh Token used to acquire an Access Token and refresh it when expired.

The method returns nothing.

Example

#require "AmazonDRS.agent.lib.nut:1.0.0"

const AMAZON_DRS_CLIENT_ID = "<YOUR_AMAZON_CLIENT_ID>";
const AMAZON_DRS_CLIENT_SECRET = "<YOUR_AMAZON_CLIENT_SECRET>";
const AMAZON_DRS_REFRESH_TOKEN = "<YOUR_AMAZON_VALID_REFRESH_TOKEN>";

client <- AmazonDRS(AMAZON_DRS_CLIENT_ID, AMAZON_DRS_CLIENT_SECRET);
client.setRefreshToken(AMAZON_DRS_REFRESH_TOKEN);

getRefreshToken()

The method returns a string with the Refresh Token or null if it is not set.

replenish(slotId[, onReplenished])

This method places an order for a device/slot combination. For more information, please see the Amazon DRS documentation.

Parameter Data Type Required? Description
slotId String Yes ID of a slot to place an order for it.
onReplenished Function Optional Callback called when the operation is completed or an error happens.

The method returns nothing. A result of the operation may be obtained via the onReplenished callback if specified in this method.

Callback: onReplenished(error, response)

Parameter Data Type Description
error Integer 0 if the operation is completed successfully, an error code otherwise. See possible HTTP error codes here.
response Table Key-value table with the response provided by Amazon server. May be null. See response example. Also may contain error details.

Example

const AMAZON_DRS_SLOT_ID = "<YOUR_AMAZON_SLOT_ID>";

function onReplenished(error, response) {
    if (error != 0) {
        server.error("Error replenishing: code = " + error + " response = " + http.jsonencode(response));
        return;
    }
    server.log("An order has been placed. Response from server: " + http.jsonencode(response));
}

// It is supposed that the client has been authenticated with either login() method or setRefreshToken() method
client.replenish(AMAZON_DRS_SLOT_ID, onReplenished.bindenv(this));

cancelTestOrder([slotId[, onCanceled]])

This method cancels test orders for one or all slots in the device. For more information, please see the Amazon DRS documentation.

The method can only be used for the orders made by a test device (a device authenticated as a test one). The library does not check if your device authenticated as a test one or not, so you are responsible for this check. See the Test Orders section.

Parameter Data Type Required? Description
slotId String Optional ID of a slot to be canceled. If is null or not specified, test orders for all slots in the device will be canceled.
onCanceled Function Optional Callback called when the operation is completed or an error happens.

The method returns nothing. A result of the operation may be obtained via the onCanceled callback if specified in this method.

Callback: onCanceled(error, response)

Parameter Data Type Description
error Integer 0 if the operation is completed successfully, an error code otherwise. See possible HTTP error codes here.
response Table Key-value table with the response provided by Amazon server. May be null. See response example. Also may contain error details.

Example

const AMAZON_DRS_SLOT_ID = "<YOUR_AMAZON_SLOT_ID>";

function onCanceled(error, response) {
    if (error != 0) {
        server.error("Error canceling: code = " + error + " response = " + http.jsonencode(response));
        return;
    }
    server.log("The order has been canceled. Response from server: " + http.jsonencode(response));
}

// It is supposed that client has been authenticated with either login() method or setRefreshToken() method
// as a test DRS device
client.cancelTestOrder(AMAZON_DRS_SLOT_ID, onCanceled.bindenv(this));

setDebug(value)

This method enables (value is true) or disables (value is false) the library debug output (including error logging). It is disabled by default. The method returns nothing.

Error code

An Integer error code which specifies a concrete error (if any) happened during an operation.

Error Code Description
0 No error.
1-99 Internal errors of the HTTP API.
100-999 HTTP error codes from Amazon server. See methods' descriptions for more information.
1000 The client is not authenticated. E.g. Refresh Token is invalid or not set.
1001 The authentication process is already started.
1010 General error.

Examples

Working examples are provided in the examples directory and described here.

The following example shows proper usage of login(), setRefreshToken() and getRefreshToken() methods.

Example: Store And Load Refresh Token

#require "Rocky.class.nut:2.0.1"
#require "AmazonDRS.agent.lib.nut:1.0.0"

const AMAZON_DRS_CLIENT_ID = "<YOUR_AMAZON_CLIENT_ID>";
const AMAZON_DRS_CLIENT_SECRET = "<YOUR_AMAZON_CLIENT_SECRET>";
const AMAZON_DRS_DEVICE_MODEL = "<YOUR_AMAZON_DEVICE_MODEL>";
const AMAZON_DRS_DEVICE_SERIAL = "<YOUR_AMAZON_DEVICE_SERIAL>";

function getStoredRefreshToken() {
    local persist = server.load();
    local amazonDRS = {};
    if ("amazonDRS" in persist) amazonDRS = persist.amazonDRS;

    // Load credentials if we have them
    if ("refreshToken" in amazonDRS) {
        server.log("Refresh Token found!");
        return amazonDRS.refreshToken;
    }
    return null;
}

client <- AmazonDRS(AMAZON_DRS_CLIENT_ID, AMAZON_DRS_CLIENT_SECRET);

refreshToken = getStoredRefreshToken();
if (refreshToken != null) {
    client.setRefreshToken(refreshToken);
} else {
    function onAuthenticated(error, response) {
        if (error != 0) {
            server.error("Error authenticating: code = " + error + " response = " + http.jsonencode(response));
            return;
        }
        refreshToken = client.getRefreshToken();
        client.setRefreshToken(refreshToken);
        local persist = server.load();
        persist.amazonDRS <- { "refreshToken" : refreshToken };
        server.save(persist);
        server.log("Successfully authenticated!");
        server.log("Refresh Token saved!");
    }
    
    local testDevice = true;
    client.login(AMAZON_DRS_DEVICE_MODEL, AMAZON_DRS_DEVICE_SERIAL, onAuthenticated.bindenv(this), testDevice);
    server.log("Log in please!");
}

Testing

Tests for the library are provided in the tests directory and described here.

License

The AmazonDRS library is licensed under the MIT License