Skip to end of metadata
Go to start of metadata

When internal capabilities are not enough (typically this happens with B2B stores which have customer-specific rules and contracts to follow), Shopamine has the ability to obtain prices from an external web service in real-time. To use this capability you should implement a HTTP-accessible service which will receive queries from Shopamine as they are needed, and which should respond with price data for the given query.

The incoming query will contain the user's email address and a number of item IDs together with quantities of interest (usually the quantity will be 1, but when in basket and in checkout the quantity might be bigger). The incoming item ID can be either "external_id" or "sku" from the rest of the API, configurable in Shopamine. Quantities will always be integers.

There are two ways in which the query can be encoded, either as parameters in the URL, or as a JSON document. The latter is probably slightly more robust, but also probably a bit harder to implement. Which way is used is configurable in Shopamine.

URL query format

If the query is in the URL, you have four choices:

  • The entire query is in one parameter, and you can configure the separator between items and between an item's ID and quantity. For example, it the separators are , and : respectively, a query for three SKUs might look like this:

    http://.../getUserPrices?user=john@example.com&items=SKU0001:1,SKU0015:1,SKU0451:12

    You specify the URL, both parameter names (user and items in the example) and the separators in configuration.

  • The query includes one parameter for each item. The parameter name is always the same or can include a counter, and there is a separator between the item's ID and quantity. For example, if separator is : and a counter is included, the query from above would instead look like this:

    http://.../getUserPrices?email=john@example.com&item1=SKU0001:1&item2=SKU0015:1&item3=SKU0451:12

    For something PHP-like, it would probably be easier if there was no counter and the parameter name included brackets instead:

    http://.../getUserPrices.php?who=john@example.com&item[]=SKU0001:1&item[]=SKU0015:1&item[]=SKU0451:12

    Again, you can specify the URL, both parameter names, whether to include a counter or not and the separator in configuration.

  • The query includes two parameters for each item. One contains the item's ID and the other its quantity. You can include counters or not. With a counter, the query might look like this:

    http://.../prices?user=john@example.com&item1=SKU0001&qty1=1&item2=SKU0015&qty2=1&item3=SKU0451&qty3=12
  • The last option is to have the item's ID be the parameter name and the quantity its value:

    http://.../getPrices?_email=john@example.com&SKU0001=1&SKU0015=1&SKU0451=12

To Shopamine they are all the same. You should choose the one which you find the easiest to implement in your system of choice. If you're using any of the separator-based modes (the first two), you should choose a separator which will not conflict with any characters in item IDs.

JSON query format

If you'd prefer to receive queries in JSON format, that is also an option. Shopamine will make a POST request to an URL of your choice with contents like this example:

{
    "v": 1,
    "user_email": "john@example.com",
    "query": {
        "SKU0001": 1,
        "SKU0015": 1,
        "SKU0451": 12
    }
}

The "v" field contains the version, which will currently always be 1. If a richer query format will eventually be introduced, it will be of a different version and we plan to support version 1 indefinitely.

Response format

The response expected is basically a table of data, with one line per item. For encoding efficiency, it is simply an JSON array of arrays, with some metainfo in the envelope document to describe what the table actually contains. For example, here's a simple response to the above query:

{
    "v": 1,
    "currency": "EUR",
    "columns": [
          "id",      "base_price", "final_price"
    ],
    "data: [
        [ "SKU0001",       180.0,         155.0 ],
        [ "SKU0015",        12.0,          12.0 ],
        [ "SKU0451",        75.0,          44.5 ]
    ]
}

We currently support the following columns:

  • "id" which contains the item ID. It must be present and must match one of the IDs from the query.
  • "base_price" which contains the item's price before discounts and taxes.
  • "discount_rate" which contains the discount rate that the user was given for this item. It must be a number between 0 and 1, inclusive. Note that this is not a percentage, so a 25% discount should be represented by 0.25.
  • "final_price" which contains the final item price the user must pay (before taxes)

The response must include "id", and at least one of "base_price" or "final_price". If "discount_rate" is included it will be taken into account. If not, it will be computed from "base_price" and "final_price" if both are present, and assumed to be 0 otherwise.

The recommended combinations of fields are these (in order of preference):

  • id, base_price, final_price
  • id, base_price, discount_rate
  • id, discount_rate, final_price
  • id, final_price

The prices returned should always be for one item, regardless of the quantity in the query. They should also not include any taxes. Future versions may allow returning prices for total quantities and with taxes included.

Currently, the response must be in the shop's base currency, in EU that's typically EUR.

Error responses

If the user is not recognized or has no special prices, please simply return this:

{ "v": 1 }

In that case (and also for items not included in the returned data) the user will be shown the default prices configured in Shopamine.

On the other hand, if some error occurs, please return a response like this:

{
    "error": "...",
    "public_error": "..."
}

If public_error is present, it will be shown to the user as-is. Otherwise he will be shown a generic error message.

Any/both of the errors will be logged in the shop's logs to help resolve problems.

Other considerations

  • The response should include a header Content-Type: application/json. The charset used must be UTF-8.
  • The request can be done either via HTTP or HTTPS. HTTP is considerably faster, so provides a better user experience, but obviously it is less secure. If the pricing information is considered very sensitive, HTTPS should be used instead.
  • The request can be done without authentication, or by any of these authentication methods:
    • Including a security token in the URL itself (https://.../getPrices?token=[sometoken]&user=john@example.com...). The parameter name can be anything.
    • Using HTTP Basic authentication (username+password, as specified in RFC 2617, section 2)
    • Using Bearer token authentication (a token is included in HTTP headers, as specified in RFC 6750, section 2.1)
  • For queries involving many items using URL parameters, several HTTP requests will be made so that the URLs are not too long. The default limit is 2000 total characters.
  • If JSON queries are used, there will usually be only one request per page view containing all the items.

 

 

  • No labels
Write a comment…