hashhesh/selling-partner-api

Amazon Selling Partner API 的 PHP 客户端

dev-master / 5.5.2.x-dev 2023-01-13 09:11 UTC

This package is not auto-updated.

Last update: 2024-09-21 15:04:25 UTC


README

一个用于连接 Amazon Selling Partner API 的 PHP 库。

Total Downloads Latest Stable Version License

如果您觉得这个库很有用,请考虑成为赞助者,或通过下面的按钮进行一次性捐赠。我非常感激您提供的任何形式的支持!

paypal

功能

  • 支持所有 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 类的 lwaClientIdlwaClientSecretlwaRefreshTokenawsAccessKeyIdawsSecretAccessKeyendpoint 属性。方法名称与它们交互的属性名称相匹配:getLwaClientIdsetLwaClientIdgetLwaClientSecret 等。

然后将 $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中定义了这些数组的预定义常量:(NAEUFENA_SANDBOXEU_SANDBOXFE_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

供应商 API

受限操作

当您调用一个受限操作时,会自动生成一个受限数据令牌(RDT)。如果您调用接受dataElements参数的受限操作,您可以将dataElements值作为参数传递给API调用。请查阅getOrdersgetOrdergetOrderItems文档,了解如何将dataElements值传递给这些调用。(在撰写本文时,这些是唯一接受dataElements值的受限操作。)

上传和下载文档

Feeds和Reports API包括涉及上传和下载文档到和从亚马逊的操作。亚马逊加密他们生成的所有文档,并要求所有上传的文档都进行加密。《SellingPartnerApi\Document》类处理所有加密/解密操作,前提是有一个Model\ReportsV20210630\ReportDocumentModel\FeedsV20210630\FeedDocumentModel\FeedsV20210630\CreateFeedDocumentResponse类的实例。当您调用getReportDocumentgetFeedDocumentcreateFeedDocument端点时,亚马逊返回这些类的实例。

下载报告文档

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_idnamephoneis_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;
}