Skip to content

timothydc/laravel-lightspeed-retail-api

Repository files navigation

laravel-lightspeed-retail-api

Latest Version on Packagist Total Downloads

Version Guidance

Version PHP Version Lightspeed Version Support
alpha ^7.4 | ^8.0 2 | 3 Unsupported since 2023-11-14
1.0 ^7.4 | ^8.0 2 | 3 Unsupported since 2024-10-21
2.0 ^8.0 2 | 3 New features

This package should be up to date with the Lightspeed API changes from 2024-07-31.

Installation

Via Composer

composer require timothydc/laravel-lightspeed-retail-api

Usage

For general information on how to use the Lightspeed Retail API, refer to the official documentation.

Register API client

Before creating an API connection, you will need to sign up for an API client with Lightspeed Retail. You can do this via the client portal.

The API client is developer friendly, you can set https://your-domain.test as your redirect URI. Remember the value of your redirect URI, we will need it later on.

Configure .env

After your API client is approved you will receive a key and secret. Add those values to your .env file.

LIGHTSPEED_RETAIL_API_KEY=xxx
LIGHTSPEED_RETAIL_API_SECRET=xxx

Publish resources

You can publish all resources, or you may choose to publish them separately:

php artisan vendor:publish --tag="lightspeed-api"

php artisan vendor:publish --tag="lightspeed-api:config"
php artisan vendor:publish --tag="lightspeed-api:migrations"

The API tokens are stored in the database, by default. So run your migrations.

php artisan migrate

Request initial access token

Before we can request an access token you need to connect your Retail POS to this app.

You can manage the access level to your POS data via a scope. Choose a $scope from the options in TimothyDC\LightspeedRetailApi\Scope. More information on the scopes can be found in the documentation.

Via command line

php artisan retail:auth

The command will ask you about the scope, and you will get an URL in return. Excellent deal!

Via controller

use TimothyDC\LightspeedRetailApi\Scope;
use TimothyDC\LightspeedRetailApi\Facades\LightspeedRetailApi;

$scope = Scope::EMPLOYEE_ALL;

return redirect()->to(LightspeedRetailApi::redirectToAuthorizationPortal($scope));

After requesting your initial access token you will be redirected to the Redirect URI you provided when configuring your client information via the Lightspeed Retail API Client.

Configure routing

Register the following route in your routes/web.php. Update your-redirect-uri with the redirect URI you entered in the API client.

use \TimothyDC\LightspeedRetailApi\Http\Controllers\SaveAccessTokenController;

Route::get('your-redirect-uri', [SaveAccessTokenController::class, '__invoke']);

Configure controller

The SaveAccessTokenController will store the initial access token and make follow-up request for the refresh token. Afterwards you will be redirected to RouteServiceProvider::HOME. If you would like to alter the redirect you may extend this controller.

Make API calls

You can now access the API. All resources return a Laravel collection... which means lots of fun!

use TimothyDC\LightspeedRetailApi\Facades\LightspeedRetailApi;

// get all
$account = LightspeedRetailApi::api()->account()->get();

// filter with GET with a limit and custom sorting (full details: https://developers.lightspeedhq.com/retail/introduction/parameters/)
$categories = LightspeedRetailApi::api()->category()->get(null, ['limit' => 10, 'sort' => 'name']);

// get category with ID 20
$categories = LightspeedRetailApi::api()->category()->get(20);

// same as above, but better
$categories = LightspeedRetailApi::api()->category()->first(20);

Note that not all resources are added (yet). Feel free to add them yourself via a pull request! If you would like to filter the GET-results you can look at the query parameters API

// advanced filtering

// get categories with an ID > 10
$categories = LightspeedRetailApi::api()->category()->get(null, ['categoryID' => ['operator' => '>', 'value' => 10]]);

// get products with their "Category" and "Note" relation
$products = LightspeedRetailApi::api()->item()->get(null, ['load_relations' => ['Category', 'Note']]);

// get sales sorted by timestamp in descending order
$sales = LightspeedRetailApi::api()->sale()->get(null, ['sort' => '-timestamp']);

Pagination

As of V3 of the Lightspeed Retail API the pagination works cursor based. The full details of on how pagination works, you can find in the Pagination API documentation

use \TimothyDC\LightspeedRetailApi\Services\Lightspeed\ResourceSale;

$response = LightspeedRetailApi::api()->sale()->getWithPagination();

$attributes = $response['@attributes'];

// collect([
//      'next' => (request url),
//      'previous' => (request url),
//      'after' => (token),
//      'before' => (token),
//  ])

$sales = $response[ResourceSale::$resource];

// Sales data as a collection

To get the next page of the resource, add the 'after' token to your request.

$response = LightspeedRetailApi::api()->sale()->getWithPagination(null, ['after' => $attributes->after]);

The 'after' attribute will be empty on the last page and the 'before' attribute will be empty on the first page. This is the same as the 'next' and 'previous' attributes as described in the Pagination API documentation


Automatic model synchronisation [optional]

If you would like to automatically synchronise your data to Lightspeed, you can add the HasLightspeedRetailResources trait and the AutomaticSynchronisationInterface interface to your model

In getLightspeedRetailResourceMapping() you want to map your model fields to the Lightspeed resource. The order of the resources is the order of the synchronisation. In the example below we put the manufacturer resource before the product resource because we need the manufacturer id for when we are syncing the product.

In getLightspeedRetailResourceName() you need to define the Lightspeed resource that represents your model. For example:

public function getLightspeedRetailResourceName(): string
{
    return \TimothyDC\LightspeedRetailApi\Services\Lightspeed\ResourceItem::$resource;
}

Don't forget to add the HasLightspeedRetailResources trait to your manufacturer resource too.

use TimothyDC\LightspeedRetailApi\Traits\HasLightspeedRetailResources;
use TimothyDC\LightspeedRetailApi\Services\Lightspeed\{ResourceItem, ResourceVendor};

class Product extends \Illuminate\Database\Eloquent\Model
{
    use HasLightspeedRetailResources;

    public static function getLightspeedRetailResourceMapping(): array
    {
        return [
            ResourceVendor::$resource => [
                ResourceVendor::$name => 'product_vendor'
            ],
            ResourceItem::$resource => [
                ResourceItem::$description => 'name',
                ResourceItem::$manufacturerId => ['manufacturer_id', 'manufacturer.id'],
                ResourceItem::$archived => ['active', 'archive'],
            ],
        ];
    }
}

You will notice some resources in the mapping have an array value. The first item in the array references the value which will be checked for a change, The second item is the value that will be sent to Lightspeed. It also accepts mutators:

In case of a relationship, the first value is the local foreign key. The second, is the related primary key.

public function getArchivedAttribute(): bool
{
    return $this->attributes['active'] === false;
}

By default, the synchronisation process listens to your model events created, updated and deleted. Update the array if you want to listen to other events.

use TimothyDC\LightspeedRetailApi\Traits\HasLightspeedRetailResources;

class Product extends \Illuminate\Database\Eloquent\Model
{
    use HasLightspeedRetailResources;

    public static function getLightspeedRetailApiTriggerEvents(): array
    {
        return ['created', 'updated', 'deleted'];
    }
}

If you would like to send fields to Lightspeed, even when the value isn't changed. You can add them to the $lsForceSyncFields array.

use TimothyDC\LightspeedRetailApi\Traits\HasLightspeedRetailResources;

class Product extends \Illuminate\Database\Eloquent\Model
{
    use HasLightspeedRetailResources;

    public array $lsForceSyncFields = ['ean'];
}

Change log

Please see the changelog for more information on what has changed recently.

Contributing

Please see contributing.md for details and a todolist.

Security

If you discover any security related issues, please email [email protected] instead of using the issue tracker.

Credits

License

MIT. Please see the license file for more information.