hashhesh / selling-partner-api
Amazon Selling Partner API 的 PHP 客户端
Requires
- php: >=7.3
- ext-curl: *
- ext-json: *
- ext-mbstring: *
- hashhesh/aws-sdk-php: dev-master
- hashhesh/guzzle: dev-master
- hashhesh/promises: dev-master
- hashhesh/psr7: dev-master
- phpoffice/phpspreadsheet: ^1.19
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.4
- phpunit/phpunit: ^8.0 || ^9.0
This package is not auto-updated.
Last update: 2024-09-21 15:04:25 UTC
README
一个用于连接 Amazon Selling Partner API 的 PHP 库。
如果您觉得这个库很有用,请考虑成为赞助者,或通过下面的按钮进行一次性捐赠。我非常感激您提供的任何形式的支持!
功能
- 支持所有 Selling Partner API 操作(卖家和供应商)(截至 2022 年 11 月 13 日)(查看此处获取所有调用的文档链接)
- 支持使用 IAM 用户和 IAM 角色ARN制作的应用程序(文档)
- 自动生成所有需要它们的受限数据令牌 - 无需对令牌 API 进行额外调用
- 包括一个用于上传和下载数据包/报告文档的
Document
辅助类
赞助者
安装
composer require jlevers/selling-partner-api
目录
请查看下面的入门部分以获取快速概览。
此 README 被分为几个部分
入门
先决条件
要开始,您需要一些东西
- Selling Partner API 开发者账户
- 配置用于使用 Selling Partner API 的 AWS IAM 用户或角色
- Selling Partner API 应用程序
如果您想了解更多有关如何设置这些内容的详细信息,请查看这篇博客文章。它提供了整个设置过程的详细说明。
设置
Configuration
构造函数接受单个参数:一个关联数组,其中包含连接到 Selling Partner API 所需的所有配置信息
$config = new SellingPartnerApi\Configuration([ "lwaClientId" => "<LWA client ID>", "lwaClientSecret" => "<LWA client secret>", "lwaRefreshToken" => "<LWA refresh token>", "awsAccessKeyId" => "<AWS access key ID>", "awsSecretAccessKey" => "<AWS secret access key>", // If you're not working in the North American marketplace, change // this to another endpoint from lib/Endpoint.php "endpoint" => SellingPartnerApi\Endpoint::NA, ]);
如果您使用 IAM 角色ARN而不是用户ARN创建了 Selling Partner API 应用程序,请在配置数组中传递该角色ARN
$config = new SellingPartnerApi\Configuration([ "lwaClientId" => "<LWA client ID>", "lwaClientSecret" => "<LWA client secret>", "lwaRefreshToken" => "<LWA refresh token>", "awsAccessKeyId" => "<AWS access key ID>", "awsSecretAccessKey" => "<AWS secret access key>", // If you're not working in the North American marketplace, change // this to another endpoint from lib/Endpoint.php "endpoint" => SellingPartnerApi\Endpoint::NA, "roleArn" => "<Role ARN>", ]);
存在 getter 和 setter 方法用于 Configuration
类的 lwaClientId
、lwaClientSecret
、lwaRefreshToken
、awsAccessKeyId
、awsSecretAccessKey
和 endpoint
属性。方法名称与它们交互的属性名称相匹配:getLwaClientId
、setLwaClientId
、getLwaClientSecret
等。
然后将 $config
传递给任何 SellingPartnerApi\Api\*Api
类的构造函数。请参阅示例部分以获取完整示例。
配置选项
传递给 Configuration
构造函数的数组接受以下键
lwaClientId (string)
:必需。用于执行 API 请求的 SP API 应用程序的 LWA 客户端 ID。lwaClientSecret (string)
:必需。用于执行 API 请求的 SP API 应用程序的 LWA 客户端密钥。lwaRefreshToken (字符串)
:用于执行API请求的SP API应用的LWA刷新令牌。必需的,除非您只是使用Configuration
实例调用无授权操作。awsAccessKeyId (字符串)
:必需的。具有SP API ExecuteAPI权限的AWS IAM用户访问密钥ID。awsSecretAccessKey (字符串)
:必需的。具有SP API ExecuteAPI权限的AWS IAM用户密钥。endpoint (数组)
:必需的。包含url
键(端点URL)和region
键(AWS区域)的数组。在lib/Endpoint.php
中定义了这些数组的预定义常量:(NA
、EU
、FE
和NA_SANDBOX
、EU_SANDBOX
、FE_SANDBOX
。更多详情请见此处。accessToken (字符串)
:由刷新令牌生成的访问令牌。accessTokenExpiration (整数)
:与accessToken
过期时间对应的Unix时间戳。如果提供了accessToken
,则必需accessTokenExpiration
(反之亦然)。onUpdateCredentials (可调用|闭包)
:当生成新的访问令牌时调用的回调函数。该函数应接受一个类型为SellingPartnerApi\Credentials
的单个参数。roleArn (字符串)
:如果您使用AWS IAM角色ARN而不是用户ARN设置了SP API应用,请在此处传入该ARN。authenticationClient (GuzzleHttp\ClientInterface)
:可选的GuzzleHttp\ClientInterface
对象,用于从刷新令牌生成访问令牌。tokensApi (SellingPartnerApi\Api\TokensApi)
:可选的SellingPartnerApi\Api\TokensApi
对象,用于在调用受限制操作时获取受限数据令牌(RDT)。authorizationSigner (SellingPartnerApi\Contract\AuthorizationSignerContract)
:可选的SellingPartnerApi\Contract\AuthorizationSignerContract
实现。参见自定义授权签名者部分。requestSigner (SellingPartnerApi\Contract\RequestSignerContract)
:可选的SellingPartnerApi\Contract\RequestSignerContract
实现。参见自定义请求签名者部分。
示例
此示例假定您有权访问Seller Insights
Selling Partner API角色,但一般格式适用于任何Selling Partner API请求。
<?php require_once(__DIR__ . '/vendor/autoload.php'); use SellingPartnerApi\Api\SellersV1Api as SellersApi; use SellingPartnerApi\Configuration; use SellingPartnerApi\Endpoint; $config = new Configuration([ "lwaClientId" => "amzn1.application-oa2-client.....", "lwaClientSecret" => "abcd....", "lwaRefreshToken" => "Aztr|IwEBI....", "awsAccessKeyId" => "AKIA....", "awsSecretAccessKey" => "ABCD....", // If you're not working in the North American marketplace, change // this to another endpoint from lib/Endpoint.php "endpoint" => Endpoint::NA ]); $api = new SellersApi($config); try { $result = $api->getMarketplaceParticipations(); print_r($result); } catch (Exception $e) { echo 'Exception when calling SellersApi->getMarketplaceParticipations: ', $e->getMessage(), PHP_EOL; } ?>
调试模式
当您进行API请求时,要获取调试输出,可以调用$config->setDebug(true)
。默认情况下,调试输出通过php://output
发送到stdout
,但您可以使用$config->setDebugFile('<path>')
将其重定向到文件。
<?php require_once(__DIR__ . '/vendor/autoload.php'); use SellingPartnerApi\Configuration; $config = new Configuration([/* ... */]); $config->setDebug(true); // To redirect debug info to a file: $config->setDebugFile('./debug.log');
支持的 API 段
每个API类名都包含API的版本。这允许在单个版本的这个包中访问同一API的多个版本。这使得类名看起来有点丑,但允许同时使用同一API段的旧版和新版,这通常很有用。可以通过格式化use
语句来修复这些更丑陋的名称:
use SellingPartnerApi\Api\SellersV1Api as SellersApi; use SellingPartnerApi\Model\SellersV1 as Sellers;
这也意味着,如果引入了现有API的新版本,库可以更新以包含该新版本,而不会引入破坏性更改。
卖家 API
- A+内容API(2020-11-01)
- 授权API(V1)
- 目录项API(2022-04-01)
- 目录项API(2021-12-01)
- 目录项API(V0)
- EasyShip API(2022-03-23)
- FBA入库API(V0)
- FBA入库资格API(V1)
- FBA库存API(V1)
- FBA出库API(2020-07-01)
- Feeds API(2021-06-30)
- 费用API(V0)
- 财务API(V0)
- 商品列表API(2021-08-01)
- 商品列表限制API(2021-08-01)
- 商户履约API(V0)
- 消息API(V1)
- 通知API(V1)
- 订单API(V0)
- 商品定价API(V0)
- 商品类型定义API(2020-09-01)
- 报告API(2021-06-30)
- 销售API(V1)
- 卖家API(V1)
- 服务API(V1)
- 运输发票API(V0)
- 运输API(V1)
- 运输API(V2)
- 轻小件API(V1)
- 请求API(V1)
- 受限数据令牌API(2021-03-01)
- 上传API(2020-11-01)
供应商 API
- 直接履约库存API(V1)
- 直接履约订单API(V1)
- 直接履约订单API(2021-12-28)
- 直接履约支付API(V1)
- 直接履约沙箱API(2021-10-28)
- 直接履约运输API(V1)
- 直接履约运输API(2021-12-28)
- 直接履约交易API(V1)
- 直接履约交易API(2021-12-28)
- 发票API(V1)
- 订单API(V1)
- 运输API(V1)
- 交易状态API(V1)
受限操作
当您调用一个受限操作时,会自动生成一个受限数据令牌(RDT)。如果您调用接受dataElements
参数的受限操作,您可以将dataElements
值作为参数传递给API调用。请查阅getOrders、getOrder和getOrderItems文档,了解如何将dataElements
值传递给这些调用。(在撰写本文时,这些是唯一接受dataElements
值的受限操作。)
上传和下载文档
Feeds和Reports API包括涉及上传和下载文档到和从亚马逊的操作。亚马逊加密他们生成的所有文档,并要求所有上传的文档都进行加密。《SellingPartnerApi\Document》类处理所有加密/解密操作,前提是有一个Model\ReportsV20210630\ReportDocument
、Model\FeedsV20210630\FeedDocument
或Model\FeedsV20210630\CreateFeedDocumentResponse
类的实例。当您调用getReportDocument
、getFeedDocument
和createFeedDocument
端点时,亚马逊返回这些类的实例。
下载报告文档
use SellingPartnerApi\Api\ReportsV20210630Api as ReportsApi; use SellingPartnerApi\ReportType; // Assume we've already fetched a report document ID, and that a $config object was defined above $documentId = 'foo.1234'; $reportType = ReportType::GET_FLAT_FILE_OPEN_LISTINGS_DATA; $reportsApi = new ReportsApi($config); $reportDocumentInfo = $reportsApi->getReportDocument($documentId, $reportType['name']); $docToDownload = new SellingPartnerApi\Document($reportDocumentInfo, $reportType); $contents = $docToDownload->download(); // The raw report text /* * - Array of associative arrays, (each sub array corresponds to a row of the report) if content type is ContentType::TAB or ContentType::CSV * - A nested associative array (from json_decode) if content type is ContentType::JSON * - The raw report data if content type is ContentType::PLAIN or ContentType::PDF * - PHPOffice Spreadsheet object if content type is ContentType::XLSX * - SimpleXML object if the content type is ContentType::XML */ $data = $docToDownload->getData(); // ... do something with report data
如果您正在操作大量报告,可以使用downloadStream()
来最小化内存消耗。downloadStream()
将返回一个Psr\Http\Message\StreamInterface
。
// line to replace >>>>$contents = $docToDownload->download(); // The raw report text $streamContents = $docToDownload->downloadStream(); // The raw report stream
上传数据包文档
use SellingPartnerApi\Api\FeedsV20210630Api as FeedsApi; use SellingPartnerApi\FeedType; use SellingPartnerApi\Model\FeedsV20210630 as Feeds; $feedType = FeedType::POST_PRODUCT_PRICING_DATA; $feedsApi = new FeedsApi($config); // Create feed document $createFeedDocSpec = new Feeds\CreateFeedDocumentSpecification(['content_type' => $feedType['contentType']]); $feedDocumentInfo = $feedsApi->createFeedDocument($createFeedDocSpec); $feedDocumentId = $feedDocumentInfo->getFeedDocumentId(); // Upload feed contents to document $feedContents = file_get_contents('<your/feed/file.xml>'); // The Document constructor accepts a custom \HeGuzzleHttp\Client object as an optional 3rd parameter. If that // parameter is passed, your custom Guzzle client will be used when uploading the feed document contents to Amazon. $docToUpload = new SellingPartnerApi\Document($feedDocumentInfo, $feedType); $docToUpload->upload($feedContents); $createFeedSpec = new Feeds\CreateFeedSpecification(); $createFeedSpec->setMarketplaceIds(['ATVPDKIKX0DER']); $createFeedSpec->setInputFeedDocumentId($feedDocumentId); $createFeedSpec->setFeedType($feedType['name']); $createFeedResult = $feedsApi->createFeed($createFeedSpec); $feedId = $createFeedResult->getFeedId();
如果您正在操作大量feed文档,可以将Guzzle可以转换为流的对象传递给upload()
。
下载数据包结果文档
这非常类似于下载报告文档
use SellingPartnerApi\Api\FeedsV20210630Api as FeedsApi; use SellingPartnerApi\FeedType; $feedType = FeedType::POST_PRODUCT_PRICING_DATA; $feedsApi = new FeedsApi($config); // ... // Create and upload a feed document, and wait for it to finish processing // ... $feedId = '1234567890'; // From the createFeed call $feed = $api->getFeed($feedId); $feedResultDocumentId = $feed->resultFeedDocumentId; $feedResultDocument = $api->getFeedDocument($feedResultDocumentId); $docToDownload = new SellingPartnerApi\Document($feedResultDocument, $feedType); $contents = $docToDownload->download(); // The raw report data $data = $docToDownload->getData(); // Parsed/formatted report data
使用模型类
大多数操作都与一个或多个模型相关联。这些模型是包含执行某种类型的API请求所需数据的类,或包含特定请求类型返回的数据的类。所有模型都共享相同的一般接口:您可以在初始化时指定模型的所有属性,或者在实际之后设置每个属性。以下是一个使用服务API的Buyer
模型的示例(文档,源代码)。
买家模型有四个属性:buyer_id
、name
、phone
和is_prime_member
。(如果你想知道如何自己确定模型具有哪些属性,请查看上面的docs
链接。)要创建一个具有所有这些属性的Buyer
模型实例
$buyer = new SellingPartnerApi\Model\ServiceV1\Buyer([ "buyer_id" => "ABCDEFGHIJKLMNOPQRSTU0123456", "name" => "Jane Doe", "phone" => "+12345678901", "is_prime_member" => true ]);
或者,你可以创建一个Buyer
模型实例,然后填充其字段
$buyer = new SellingPartnerApi\Model\ServiceV1\Buyer(); $buyer->buyerId = "ABCDEFGHIJKLMNOPQRSTU0123456"; $buyer->name = "Jane Doe"; $buyer->phone = "+12345678901"; $buyer->isPrimeMember = true;
每个模型也具有你可能期望的属性访问器
$buyer->buyerId; // -> "ABCDEFGHIJKLMNOPQRSTU0123456" $buyer->name; // -> "Jane Doe" $buyer->phone; // -> "+12345678901" $buyer->isPrimeMember; // -> true
模型可以(并且通常确实如此)具有其他模型作为属性
$serviceJob = new SellingPartnerApi\Model\ServiceV1\Buyer([ // ... "buyer" => $buyer, // ... ]); $serviceJob->buyer; // -> [Buyer instance] $serviceJob->buyer->name; // -> "Jane Doe"
响应头
亚马逊在每个SP API响应中包含了一些有用的头部信息。如果你需要这些信息,可以通过在响应对象上调用getHeaders()
来获取响应头部的关联数组。例如
<?php require_once(__DIR__ . '/vendor/autoload.php'); use SellingPartnerApi\Api\SellersV1Api as SellersApi; use SellingPartnerApi\Configuration; use SellingPartnerApi\Endpoint; $config = new Configuration([...]); $api = new Api\SellersApi($config); try { $result = $api->getMarketplaceParticipations(); $headers = $result->headers; print_r($headers); } catch (Exception $e) { echo 'Exception when calling SellersApi->getMarketplaceParticipations: ', $e->getMessage(), PHP_EOL; }
自定义授权签名器
在签名API请求的过程中,你可能需要进行自定义操作。你可以通过创建一个实现AuthorizationSignerContract接口的实例,并将其传递到Configuration
构造函数数组中,来创建一个自定义授权签名器。
// CustomAuthorizationSigner.php use HeGuzzleHttp\Psr7\Request; use SellingPartnerApi\Contract\AuthorizationSignerContract; class CustomAuthorizationSigner implements AuthorizationSignerContract { public function sign(Request $request, Credentials $credentials): Request { // Calculate request signature and request date. $requestDate = '20220426T202300Z'; $signatureHeaderValue = 'some calculated signature value'; $signedRequest = $request ->withHeader('Authorization', $signatureHeaderValue) ->withHeader('x-amz-date', $requestDate); return $signedRequest; } // ... } // Consumer code <?php require_once(__DIR__ . '/vendor/autoload.php'); use SellingPartnerApi\Api\SellersV1Api as SellersApi; use SellingPartnerApi\Configuration; use SellingPartnerApi\Endpoint; use CustomAuthorizationSigner; $config = new Configuration([ ..., 'authorizationSigner' => new CustomAuthorizationSigner(), ]); $api = new SellersApi($config); try { $result = $api->getMarketplaceParticipations(); print_r($result); } catch (Exception $e) { echo 'Exception when calling SellersApi->getMarketplaceParticipations: ', $e->getMessage(), PHP_EOL; }
自定义请求签名器
你可能还需要自定义整个请求签名过程——例如,如果你需要在签名请求的过程中调用外部服务。你可以通过创建一个实现RequestSignerContract接口的实例,并将其传递到Configuration
构造函数数组中来完成此操作。
// RemoteRequestSigner.php use HeGuzzleHttp\Psr7\Request; use SellingPartnerApi\Contract\RequestSignerContract; class RemoteRequestSigner implements RequestSignerContract { public function signRequest( Request $request, ?string $scope = null, ?string $restrictedPath = null, ?string $operation = null ): Request { // Sign request by sending HTTP call // to external/separate service instance. return $signedRequest; } } // Consumer code <?php require_once(__DIR__ . '/vendor/autoload.php'); use SellingPartnerApi\Api\SellersV1Api as SellersApi; use SellingPartnerApi\Configuration; use SellingPartnerApi\Endpoint; use RemoteRequestSigner; $config = new Configuration([ ..., 'requestSigner' => new RemoteRequestSigner(), ]); $api = new SellersApi($config); try { $result = $api->getMarketplaceParticipations(); print_r($result); } catch (Exception $e) { echo 'Exception when calling SellersApi->getMarketplaceParticipations: ', $e->getMessage(), PHP_EOL; }