serato / sws-php-sdk
PHP SDK for Serato Web Services
Installs: 117 990
Dependents: 1
Suggesters: 0
Security: 0
Stars: 1
Watchers: 14
Forks: 13
Open Issues: 0
Requires
- php: ^7.1 || ^8.0
- guzzlehttp/guzzle: ^6.0.0
- serato/sws-discovery: ^3.0
Requires (Dev)
- aws/aws-sdk-php: ^3.0
- enlightn/security-checker: ^1.4 || ^2
- phpstan/phpstan: ^1.4
- phpstan/phpstan-phpunit: ^1.0
- phpunit/phpunit: ^7 || ^8
- squizlabs/php_codesniffer: ^3.0
- dev-master
- v5.0.1
- v5.0.0
- v4.0.3
- v4.0.2
- v4.0.1
- v4.0.0
- v3.5.2
- v3.5.1
- v3.5.0
- v3.4.0
- v3.3.1
- v3.3.0
- v3.2.0
- v3.1.1
- v3.1.0
- v3.0.1
- v3.0.0
- v2.8.1
- v2.8.0
- v2.7.0
- v2.6.0
- v2.5.0
- v2.4.0
- v2.3.2
- v2.3.1
- v2.3.0
- v2.2.3
- v2.2.2
- v2.2.0
- v2.1.4
- v2.1.3
- v2.1.2
- v2.1.1
- v2.1.0
- v2.0.7
- v2.0.6
- v2.0.5
- v2.0.4
- v2.0.3
- v2.0.2
- v2.0.1
- v2.0.0
- v1.0.3
- v1.0.2
- v1.0.1
- v1.0.0
- dev-feature-php8
- dev-WEB-9960
- dev-WEB-5665-test
- dev-WEB-5732
- dev-test-version-bump
This package is auto-updated.
Last update: 2024-11-22 04:26:52 UTC
README
A PHP SDK for interacting with SWS web services.
Note: currently limited to applications that use the Server Side Application Authorisation Workflow
All PHP code within the Serato Checkout library exists within the Serato\SwsSdk
namespace.
Style guide
Please ensure code adheres to the PHP-FIG PSR-2 Coding Style Guide
Use PHP_CodeSniffer to validate your code against coding standards:
$ ./vendor/bin/phpcs
PHPStan
Use PHPStan for static code analysis:
$ vendor/bin/phpstan analyse
Unit tests
Configuration for PHPUnit is defined within phpunit.xml.
To run tests:
$ php vendor/bin/phpunit
Usage
Key Concepts
- The
Serato\SwsSdk\Sdk
class is used to provided configuration data into the SDK. Once configured, anSdk
instance can be used to create clients. - A client interacts with a specific SWS web service. A client extends
Serato\SwsSdk\Client
which in turn extendsGuzzleHttp\Client
. - Clients execute commands. A command encapsulates the HTTP method, URI path and parameters
used for a request to a specific HTTP endpoint of an SWS web service. Commands extend
Serato\SwsSdk\Command
. - SWS web service endpoints use one of two means of HTTP based authentication: HTTP
Basic
, orBearer token
(via JWT). Commands that interact with endpoints usingBearer token
authentication require the bearer token value to be provided to them at execution time. - When a client executes a command it returns a
Serato\SwsSdk\Result
object or throws an exception. Serato\SwsSdk\Result
objects wrap the HTTP response from an SWS web service and provide native PHP array access to it's data. They also provided access to the underlyingPsr\Http\Message\ResponseInterface
response object.
Configuring the SDK
Using the Serato\SwsSdk\Sdk::create
static method
The Serato\SwsSdk\Sdk::create
static method is the preferred way to create an SDK instance. The method requires a
Serato\ServiceDiscovery\HostName
instance and derives endpoint URIs for the SWS web services from this instance.
It also requires a client application ID amd client application password.
It can optionally be provided with an HTTP request timeout (a float representing a number of seconds), and a callable that transfers HTTP requests over the wire within the underlying Guzzle HTTP library (typically this is used to provide a mock request handler for testing purposes).
use Serato\SwsSdk\Sdk; use Serato\ServiceDiscovery\HostName; use GuzzleHttp\HandlerStack; use GuzzleHttp\Psr7\Response; /* Configure the SDK using a `Serato\ServiceDiscovery\HostName` instance with default timeout and no custom Guzzle handler */ $hostNames = new HostName('production', 1); $sdk = Sdk::create($hostNames, 'my_app_id', 'my_app_secrety_pass'); /* Configure the SDK using a `Serato\ServiceDiscovery\HostName` instance with custom timeout and custom Guzzle handler */ // Create `Serato\ServiceDiscovery\HostName` instance $hostNames = new HostName('test', 2); // Create a mock handler $mock = new MockHandler([ new Response(200, ['X-Foo' => 'Bar']) ]); $handler = HandlerStack::create($mock); $sdk = Sdk::create($hostNames, 'my_app_id', 'my_app_secrety_pass', 3.2, $handler);
Using the Serato\SwsSdk\Sdk
constructor
In almost all cases the Serato\SwsSdk\Sdk::create
method is the preferred way of configuring the SDK. But if you need
to provide a non-standard configuration to the SDK (eg. using service endpoints from differing environments) you can call
the SDK constructor directly.
The Serato\SwsSdk\Sdk
constructor takes an $args
array, a client application ID amd client application password.
$args
is used to specify the endpoints of the various SWS web services, as well as providing additional configuration to the underlying GuzzleHttp\Client
.
Custom endpoints can be specified by setting the $args
Sdk::BASE_URI
key with an array with the following keys:
Sdk::BASE_URI_ID
Sdk::BASE_URI_LICENSE
Sdk::BASE_URI_PROFILE
Sdk::BASE_URI_ECOM
Sdk::BASE_URI_DA
Sdk::BASE_URI_NOTIFICATIONS
The value of each key is the full base URI (including protocol) of the respective SWS web services.
$args
can take a 'timeout'
key which sets the request timeout for all requests. Timeout values are floats
representing the number of seconds before the request times out.
$args
can also take a 'handler'
key that defines a custom HTTP handler for use by the underlying
GuzzleHttp library. The primary use for this is for mocking various HTTP responses (see Testing clients below for more).
use Serato\SwsSdk\Sdk; use GuzzleHttp\HandlerStack; use GuzzleHttp\Psr7\Response; /* Configure the SDK to use custom SWS endpoints, a non-standard timeout and a Guzzle MockHandler */ // Create a mock handler $mock = new MockHandler([ new Response(200, ['X-Foo' => 'Bar']) ]); $handler = HandlerStack::create($mock); $args = [ Sdk::BASE_URI => [ Sdk::BASE_URI_ID => 'http://id.server.com', Sdk::BASE_URI_LICENSE => 'https://license.server.com', Sdk::BASE_URI_PROFILE => 'https://profile.server.com', Sdk::BASE_URI_ECOM => 'https://ecom.server.com' ], 'handler' => $handler, 'timeout' => 3.2 ]; $sdk = new Sdk($args, 'my_app_id', 'my_app_secrety_pass');
Creating clients
An instance of Serato\SwsSdk\Sdk
can be used to create service clients.
A clients interacts with a specific SWS service using the configuration parameters
passed to a Serato\SwsSdk\Sdk
instance.
There are currently six clients available:
Serato\SwsSdk\Identity\IdentityClient
- A client for interacting with SWS Identity Service.Serato\SwsSdk\License\LicenseClient
- A client for interacting with SWS License Service.Serato\SwsSdk\Profile\ProfileClient
- A client for interacting with SWS Profile Service.Serato\SwsSdk\Ecom\EcomClient
- A client for interacting with SWS Ecom Service.Serato\SwsSdk\Da\DaClient
- A client for interacting with SWS DA Service.Serato\SwsSdk\Notifications\NotificationsClient
- A client for interacting with SWS Notifications Service.
use Serato\SwsSdk\Sdk; /* Create clients from an Sdk instance */ $args = ['env' => Sdk::ENV_PRODUCTION]; $sdk = new Sdk($args, 'my_app_id', 'my_app_secrety_pass'); $identityClient = $sdk->createIdentityClient(); $licenseClient = $sdk->createLicenseClient(); $profileClient = $sdk->createProfileClient(); $ecomClient = $sdk->createEcomClient();
Executing commands
Commands correspond to a specific endpoint on an SWS service. Commands require arguments that map directly to the request parameters allowed by the corresponding endpoint.
The PHP API documention lists the allowed arguments for each command class.
Commands can be explictly created then passed to the Serato\SwsSdk\Client::executeCommand
method. But it is simpler to use the magic methods of a client that map a command
to a client method name.
The PHP API documention provides the magic method name for each command class.
use Serato\SwsSdk\Sdk; use Serato\SwsSdk\License\Command\ProductGet; $args = ['env' => Sdk::ENV_PRODUCTION]; $sdk = new Sdk($args, 'my_app_id', 'my_app_secrety_pass'); $identityClient = $sdk->createIdentityClient(); $licenseClient = $sdk->createLicenseClient(); /* Command that uses HTTP `Basic` auth */ // Explicitly create a `ProductGet` command and execute it $commandArgs = ['product_id' => 'SDJ-1234-1234']; $command = new ProductGet('my_app', 'my_pass', 'https://sws.endpoint.url', $commandArgs); $result = $licenseClient->executeCommand($command); // Simpler: Use the `LicenseClient::getProduct` magic method to execute the `ProductGet` command $commandArgs = ['product_id' => 'SDJ-1234-1234']; $result = $licenseClient->getProduct($commandArgs); /* Command that uses `Bearer token` auth */ // Explicitly create a `UserGet` command and execute it $bearerToken = 'my_bearer_token_value'; $command = new UserGet('my_app', 'my_pass', 'https://sws.endpoint.url'); $result = $identityClient->executeCommand($command, $bearerToken); // Simpler: Use the `IdentityClient::getUser` magic method to execute the `UserGet` command $result = $identityClient->getProduct($bearerToken);
Working with Results
A successfully executed command returns a Serato\SwsSdk\Result
instance.
A Result
object takes a response from a SWS web service and parses the message body
so that the contents of the response body can be accessed using native PHP array accessor
syntax.
The Result
object also has a Result::getResponse
method that returns the underlying
Psr\Http\Message\ResponseInterface
response object.
use Serato\SwsSdk\Sdk; use Serato\SwsSdk\License\Command\ProductGet; $args = ['env' => Sdk::ENV_PRODUCTION]; $sdk = new Sdk($args, 'my_app_id', 'my_app_secrety_pass'); $licenseClient = $sdk->createLicenseClient(); $commandArgs = ['product_id' => 'SDJ-1234-1234']; $result = $licenseClient->getProduct($commandArgs); // Echo the product ID echo $result['id']; // Echo the number of licenses in the product echo count($result['licenses']); // Access the `Psr\Http\Message\ResponseInterface` response object $response = $result->getResponse();
Exceptions
When a command execution results in a non-200 HTTP response from a SWS web service an exeception is thrown.
All exception classes in the SDK extend Serato\SwsSdk\Exception\ResponseException
.
ResponseException
extends the base PHP RuntimeException
class.
ResponseException
classes have a ResponseException::getResult
method which returns a
Result
object, providing access the underlying response from the web service.
Specific exception classes handle each type of expected non-200 HTTP response. The code
property of the exception class is used in one of two different ways in each child
exception class
Serato\SwsSdk\Exception\AccessDeniedException
:code
is the error code as specified in the response message body.Serato\SwsSdk\Exception\BadRequestException
:code
is the error code as specified in the response message body.Serato\SwsSdk\Exception\ResourceNotFoundException
:code
is the HTTP response code. ie. 404.Serato\SwsSdk\Exception\ServerApplicationErrorException
:code
is the HTTP response code. ie. 500.Serato\SwsSdk\Exception\ServiceUnavailableException
:code
is the HTTP response code. ie. 503.
Requests resulting in connection errors (timeouts, failed DNS lookups etc) do not throw SDK-specific
exceptions and instead throw a GuzzleHttp\Exception\ConnectException
provided by Guzzle.
Testing clients
Because clients in the SDK extend GuzzleHttp\Client
requests to SWS services can be mocked using Guzzle's
GuzzleHttp\Handler\MockHandler
.
The Guzzle documentation provides a good overview of how to
create mock responses and provide them to a GuzzleHttp\Handler\MockHandler
instance.
The mock handler can then be provided to SwsSdk clients via the Serato\SwsSdk\Sdk
class.
use Serato\SwsSdk\Sdk; use GuzzleHttp\Handler\MockHandler; use GuzzleHttp\HandlerStack; use GuzzleHttp\Psr7\Response; // Create a mock handler and queue two responses. $mock = new MockHandler([ new Response(200, [/* Headers */], '{"id":"SDJ-1111-11111"}'), new Response(200, [/* Headers */], '{"id":"SDJ-2222-22222"}') ]); $handler = HandlerStack::create($mock); $args = [ 'env' => Sdk::ENV_STAGING, 'handler' => $handler ]; $sdk = new Sdk($args, 'my_app_id', 'my_app_secrety_pass'); // Client is created with the `handler` option as specified in the `Sdk` constructor $licenseClient = $sdk->createLicenseClient(); // Execute the first command. The mock handler returns the first response from the stack. $result = $licenseClient->getProduct(['product_id' => 'SDJ-1234-1234']); // Will echo 'SDJ-1111-11111' echo $result['id']; // Will echo the raw response body '{"id":"SDJ-1111-11111"}' echo $result->getResponse()->getBody(); // Execute the first second. The mock handler returns the second response from the stack. $result = $licenseClient->getProduct(['product_id' => 'SDJ-1234-1234']); // Will echo 'SDJ-2222-22222' echo $result['id']; // Will echo the raw response body '{"id":"SDJ-2222-22222"}' echo $result->getResponse()->getBody();
The mock handler stack can also include exceptions:
use Serato\SwsSdk\Sdk; use GuzzleHttp\Handler\MockHandler; use GuzzleHttp\HandlerStack; use GuzzleHttp\Psr7\Response; use Exception; // Create a mock handler and queue two responses. $mock = new MockHandler([ new Response(200, [/* Headers */], '{"id":"SDJ-1111-11111"}'), new Exception ]); $handler = HandlerStack::create($mock); $args = [ 'env' => Sdk::ENV_STAGING, 'handler' => $handler ]; $sdk = new Sdk($args, 'my_app_id', 'my_app_secrety_pass'); // Client is created with the `handler` option as specified in the `Sdk` constructor $licenseClient = $sdk->createLicenseClient(); // Execute the first command. The mock handler returns the first response from the stack. $result = $licenseClient->getProduct(['product_id' => 'SDJ-1234-1234']); // Will echo 'SDJ-1111-11111' echo $result['id']; // Throws Exception $result = $licenseClient->getProduct(['product_id' => 'SDJ-5678-4321']);