shipstream/ups-rest-php-sdk

UPS REST API的PHP SDK

2.3.2 2024-08-30 15:26 UTC

This package is auto-updated.

Last update: 2024-08-30 15:39:29 UTC


README

ShipStream提供的UPS REST API PHP SDK。

安装

composer require shipstream/ups-rest-php-sdk

注意:最新版本仅与PHP 8.x兼容。对于PHP 7.4支持,请在上述命令中追加^1.0版本约束。

基本用法

使用配置对象创建UPS客户端实例

$config = new \ShipStream\Ups\Config([
    // Whether to send the requests to the UPS Customer Integration Environment instead of the production environment.
    // Optional, defaults to false.
    'use_testing_environment' => true,
    // The grant type to use for obtaining an access token. Available options: 'client_credentials', 'authorization_code'.
    // Optional, defaults to 'client_credentials'.
    'grant_type' => \ShipStream\Ups\Config::GRANT_TYPE_CLIENT_CREDENTIALS,
    // Your Client ID obtained from UPS Developer portal.
    'client_id' => 'your_client_id',
    // Your Client Secret obtained from UPS Developer portal.
    'client_secret' => 'your_client_secret',
    // The URL to redirect to after authenticating with UPS using Authorization Code flow.
    // Required only when using Authorization Code flow, defaults to an empty string.
    'redirect_uri' => 'https://example.com/oauth/callback',
]);

$client = \ShipStream\Ups\ClientFactory::create($config);

客户端对象包含用于UPS OpenAPI定义文件中每个端点的所有方法,这些方法带有PHPDoc注释,描述了参数和返回类型,以及任何抛出的异常。每个端点的方法名称基于OpenAPI规范中的operationId属性。

以下是一个使用跟踪API的示例

try {
    $response = $client->getSingleTrackResponseUsingGET('1ZXXXXXXXXXXXXXXXX', $queryParams = [], $headers = [
        'transId' => 'Track-1ZXXXXXXXXXXXXXXXX-'.time(),
        'transactionSrc' => 'testing'
    ]);
    // Do something with the response
} catch (
    \ShipStream\Ups\Api\Exception\GetSingleTrackResponseUsingGETNotFoundException |
    \ShipStream\Ups\Api\Exception\GetSingleTrackResponseUsingGETBadRequestException |
    \ShipStream\Ups\Api\Exception\GetSingleTrackResponseUsingGETInternalServerErrorException |
    \ShipStream\Ups\Api\Exception\GetSingleTrackResponseUsingGETServiceUnavailableException $e
) {
    $errors = $e->getErrorResponse()->getResponse()->getErrors();
    $errors = array_map(fn ($error) => $error->getMessage(), $errors);
    echo 'Error: '.implode(' - ', $errors)."\n";
} catch (\ShipStream\Ups\Api\Exception\UnexpectedStatusCodeException $e) {
    echo "Unexpected response received from UPS: {$e->getMessage()}\n";
} catch (\ShipStream\Ups\Exception\AuthenticationException $e) {
    echo "Authentication error: {$e->getMessage()}\n";
}

身份验证

客户端凭证

使用客户端凭证流程开箱即用,无需额外步骤,因为访问令牌的生成和刷新是内部处理的。

授权码

要开始使用授权码流程,将grant_type配置设置为Config::GRANT_TYPE_AUTHORIZATION_CODE,然后调用authorizeClient端点,并将用户重定向到返回的登录URL。

$response = $client->authorizeClient([
    'client_id' => $client->getConfig()->getClientId(),
    'redirect_uri' => $client->getConfig()->getRedirectUri(),
    'response_type' => 'code'
]);

// Redirect the user to the login page
header('Location: ' . $response->getLocation());

用户登录后,将重定向回您的应用程序,并使用授权码生成访问令牌。

$client->exchangeAuthorizationCode($_GET['code']);

只要刷新令牌仍然有效,内部将处理访问令牌的刷新。您可以通过调用$client->getAccessToken()在任何时候检查客户端是否已认证,它尝试从缓存中检索访问令牌并在必要时刷新它,否则抛出AuthenticationException

防止刷新过期令牌时的竞争条件

当多个PHP进程在访问令牌过期时尝试调用端点时,可能会发生竞争条件,导致一个进程成功刷新令牌,而其他进程将因Invalid Refresh Token或类似错误而失败。为帮助防止这种情况,可以通过将任何实现AccessTokenLock接口的类作为第三个参数传递给客户端工厂来启用锁定。提供了一种名为FileAccessTokenLock的内置实现,它接受可写文件路径并用于锁定。示例

$client = \ShipStream\Ups\ClientFactory::create(
    $config,
    null,
    new \ShipStream\Ups\Authentication\FileAccessTokenLock('/tmp/ups-sdk-token.lock')
);

缓存访问令牌

该库默认使用内存缓存来缓存访问令牌,这在快速测试时很有用,但对于生产环境,您可能希望使用类似Redis或文件系统缓存的东西,以避免在每次请求时都生成访问令牌。为此,客户端工厂接受第二个参数,该参数可以是实现AccessTokenCache接口的任何对象。例如,Redis实现可能看起来像这样

class RedisAccessTokenCache implements \ShipStream\Ups\Authentication\AccessTokenCache
{
    private $predis;

    public function __construct(\Predis\Client $predis)
    {
        $this->predis = $predis;
    }
    public function save(\ShipStream\Ups\Authentication\AccessToken $accessToken)
    {
        $clientId = $accessToken->getClientId();
        $accessTokenKey = "access_token:$clientId";
        $this->predis->set($accessTokenKey, serialize($accessToken));
    }
    public function retrieve(string $clientId): ?\ShipStream\Ups\Authentication\AccessToken
    {
        $accessTokenKey = "access_token:$clientId";
        $cachedAccessToken = $this->predis->get($accessTokenKey);
        if ($cachedAccessToken !== false) {
            return unserialize($cachedAccessToken, ['allowed_classes' => [\ShipStream\Ups\Authentication\AccessToken::class]]);
        }
        return null;
    }
}
$client = \ShipStream\Ups\ClientFactory::create($config, new RedisAccessTokenCache(new \Predis\Client()));

使用自定义HTTP客户端

如果您希望自定义如何发起HTTP请求,例如用于日志记录或添加额外的头信息,客户端工厂支持一个可以接受任何实现PSR-18标准的HTTP客户端的第三个参数。例如:

$client = \ShipStream\Ups\ClientFactory::create($config, null, new \GuzzleHttp\Client());

请注意,HTTP客户端不能在收到4xx和5xx响应时抛出异常,因为这些响应应由SDK处理。

开发

ShipStream\Ups\Api命名空间下的所有类都是使用janephp生成的。

当需要重新生成类时,运行generate.sh脚本。