serato/sws-php-sdk

此包的最新版本(v5.0.1)没有可用的许可证信息。

用于与 Serato Web Services 交互的 PHP SDK

v5.0.1 2024-07-17 19:49 UTC

README

一个用于与 SWS 网络服务交互的 PHP SDK。

注意:目前仅限于使用 服务器端应用程序授权工作流程 的应用程序。

在 Serato Checkout 库中,所有 PHP 代码都位于 Serato\SwsSdk 命名空间中。

风格指南

请确保代码遵循 PHP-FIG PSR-2 编码风格指南

使用 PHP_CodeSniffer 验证您的代码是否符合编码标准

$ ./vendor/bin/phpcs

PHPStan

使用 PHPStan 进行静态代码分析

$ vendor/bin/phpstan analyse

单元测试

PHPUnit 的配置定义在 phpunit.xml 中。

运行测试

$ php vendor/bin/phpunit

用法

关键概念

  • 使用 Serato\SwsSdk\Sdk 类提供配置数据给 SDK。一旦配置完毕,可以使用 Sdk 实例来创建客户端。
  • 客户端与特定的 SWS 网络服务交互。客户端扩展 Serato\SwsSdk\Client,而 Serato\SwsSdk\Client 又扩展 GuzzleHttp\Client
  • 客户端执行命令。命令封装了用于向 SWS 网络服务的特定 HTTP 终端的 HTTP 方法、URI 路径和参数。命令扩展 Serato\SwsSdk\Command
  • SWS 网络服务端点使用两种基于 HTTP 的身份验证方式之一:HTTP BasicBearer token(通过 JWT)。使用 Bearer token 身份验证与端点交互的命令需要在执行时提供载体令牌值。
  • 当客户端执行命令时,它会返回一个 Serato\SwsSdk\Result 对象或抛出异常。
  • Serato\SwsSdk\Result 对象封装了来自 SWS 网络服务的 HTTP 响应,并提供了对数据的原生 PHP 数组访问。它们还提供了对底层 Psr\Http\Message\ResponseInterface 响应对象的访问。

配置 SDK

使用 Serato\SwsSdk\Sdk::create 静态方法

Serato\SwsSdk\Sdk::create 静态方法是创建 SDK 实例的首选方式。该方法需要一个 Serato\ServiceDiscovery\HostName 实例,并从这个实例派生出 SWS 网络服务的端点 URI。

它还需要一个客户端应用程序 ID 和客户端应用程序密码。

它还可以提供一个 HTTP 请求超时(表示秒数的浮点数),以及一个可调用的函数,该函数在底层的 Guzzle HTTP 库中传输 HTTP 请求(通常用于提供测试目的的模拟请求处理器)。

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);

使用 Serato\SwsSdk\Sdk 构造函数

几乎在所有情况下,Serato\SwsSdk\Sdk::create 方法是配置 SDK 的首选方式。但如果您需要向 SDK 提供非标准配置(例如,使用来自不同环境的不同的服务端点),您可以直接调用 SDK 构造函数。

Serato\SwsSdk\Sdk 构造函数接受一个 $args 数组、一个客户端应用程序 ID 和客户端应用程序密码。

$args 用于指定各种 SWS 网络服务的端点,并提供对底层 GuzzleHttp\Client 的额外配置。

可以通过设置 $argsSdk::BASE_URI 键来指定自定义端点,该键为具有以下键的数组

  • Sdk::BASE_URI_ID
  • Sdk::BASE_URI_LICENSE
  • Sdk::BASE_URI_PROFILE
  • Sdk::BASE_URI_ECOM
  • Sdk::BASE_URI_DA
  • Sdk::BASE_URI_NOTIFICATIONS

每个键的值是对应 SWS 网络服务的完整基本 URI(包括协议)。

$args 可以接受一个 'timeout' 键,用于设置所有请求的超时时间。超时值是表示请求超时前秒数的浮点数。

$args 还可以接受一个 'handler' 键,它定义了一个自定义的 HTTP 处理器,该处理器由底层的 GuzzleHttp 库使用。其主要用途是模拟各种 HTTP 响应(有关更多信息,请参见下面的 测试客户端)。

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');

创建客户端

可以使用 Serato\SwsSdk\Sdk 的实例来创建服务客户端。

客户端通过传递给 Serato\SwsSdk\Sdk 实例的配置参数与特定的 SWS 服务交互。

目前有六个客户端可用

  • Serato\SwsSdk\Identity\IdentityClient - 与 SWS 身份服务交互的客户端。
  • Serato\SwsSdk\License\LicenseClient - 与 SWS 许可服务交互的客户端。
  • Serato\SwsSdk\Profile\ProfileClient - 与 SWS 个人资料服务交互的客户端。
  • Serato\SwsSdk\Ecom\EcomClient - 与 SWS Ecom 服务交互的客户端。
  • Serato\SwsSdk\Da\DaClient - 与 SWS DA 服务交互的客户端。
  • Serato\SwsSdk\Notifications\NotificationsClient - 与 SWS 通知服务交互的客户端。
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();

执行命令

命令对应于 SWS 服务上的特定端点。命令需要参数,这些参数直接映射到对应端点允许的请求参数。

PHP API 文档列出了每个命令类的允许参数。

可以显式创建命令并将其传递给 Serato\SwsSdk\Client::executeCommand 方法。但使用客户端的魔术方法来将命令映射到客户端方法名会更简单。

PHP API 文档为每个命令类提供了魔术方法名。

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);

处理结果

成功执行的命令返回一个 Serato\SwsSdk\Result 实例。

Result 对象从 SWS 网络服务获取响应并解析消息体,以便可以使用原生的 PHP 数组访问器语法访问响应体的内容。

Result 对象还有一个 Result::getResponse 方法,它返回底层的 Psr\Http\Message\ResponseInterface 响应对象。

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();

异常

当命令执行导致 SWS 网络服务的非 200 HTTP 响应时,将抛出异常。

SDK 中的所有异常类都扩展了 Serato\SwsSdk\Exception\ResponseExceptionResponseException 扩展了基于 PHP 的基本 RuntimeException 类。

ResponseException 类有一个 ResponseException::getResult 方法,该方法返回一个 Result 对象,从而提供对底层 Web 服务响应的访问。

特定的异常类处理每种预期的非 200 HTTP 响应。异常类的 code 属性在每个子异常类中以两种不同方式之一使用

  • Serato\SwsSdk\Exception\AccessDeniedException: code 是响应消息体中指定的错误代码。
  • Serato\SwsSdk\Exception\BadRequestException: code 是响应消息体中指定的错误代码。
  • Serato\SwsSdk\Exception\ResourceNotFoundException: code 是 HTTP 响应代码。例如,404。
  • Serato\SwsSdk\Exception\ServerApplicationErrorException: code 是 HTTP 响应代码。例如,500。
  • Serato\SwsSdk\Exception\ServiceUnavailableException: code 是 HTTP 响应代码。例如,503。

导致连接错误(超时、失败的 DNS 查找等)的请求不会抛出 SDK 特定的异常,而是抛出 Guzzle 提供的 GuzzleHttp\Exception\ConnectException

测试客户端

因为SDK中的客户端可以扩展对SWS服务的GuzzleHttp\Client请求,所以可以使用Guzzle的GuzzleHttp\Handler\MockHandler进行模拟。

Guzzle的[官方文档](http://guzzle.readthedocs.io/en/latest/testing.html)提供了如何创建模拟响应并将它们提供给GuzzleHttp\Handler\MockHandler实例的详细概述。

然后,可以通过Serato\SwsSdk\Sdk类将模拟处理程序提供给SwsSdk客户端。

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();

模拟处理程序堆栈还可以包括异常。

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']);