shipstream / ups-rest-php-sdk
UPS REST API的PHP SDK
Requires
- php: ^8.0
- ext-curl: *
- ext-json: *
- jane-php/open-api-runtime: ^7.6
- php-http/curl-client: ^2.3
- symfony/polyfill-php81: ^1.28
Requires (Dev)
- jane-php/open-api-3: ^7.6
- nyholm/psr7: ^1.8
- phpunit/phpunit: ^9.6
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
脚本。