Selling Partner API for PHP

repository·main·Indexed 19 days ago

https://github.com/jlevers/selling-partner-api

A PHP library for connecting to Amazon's Selling Partner API (SP-API), supporting both Seller and Vendor API operations. The library handles OAuth flows, Restricted Data Token (RDT) generation, and document management for reports and feeds. It features versioned accessor methods for API segments, DTO-based requests, and integration with Saloon for debugging and response handling.

Tokens
14K
Snippets
44
Records
49
Agent score
66%

What's inside jlevers-selling-partner-api

  1. Handle restricted operations and data elements

    main

    When calling restricted operations, a Restricted Data Token (RDT) is automatically generated. If the operation accepts a dataElements parameter (currently only getOrder, getOrders, and getOrderItems), you must specify the restricted data elements you wish to retrieve when initializing the connector via SellingPartnerApi::make().

    Important: Do not specify dataElements when calling restricted operations on a sandbox endpoint (e.g., Endpoint::NA_SANDBOX), as RDTs are not required in the sandbox environment.

    To make calls on behalf of a delegatee application, pass the delegatee parameter to SellingPartnerApi::make(). This ensures the connector generates a token for the delegatee instead of the main application.

  2. How API versioning works in Selling Partner API for PHP

    main
    The library uses versioned accessor methods for every API segment. This design allows multiple versions of the same API (e.g., v0 and v2022-04-01 of the Catalog Items API) to be available simultaneously within a single package version. This prevents breaking changes when Amazon introduces new API versions and allows developers to migrate at their own pace by calling the specific versioned method they require.
  3. Implement the SP API OAuth flow

    main

    The library provides an OAuth class to manage the two main stages of the Amazon Selling Partner API OAuth flow.

    1. Building Authorization URIs

    Use OAuth::getAuthorizationUri() to generate the URL where you redirect the seller. You must provide your client credentials, a redirect URI, a base64-encoded state string for security, and the target Marketplace.

    2. Generating a Refresh Token

    When the user is redirected back to your site, Amazon includes an spapi_oauth_code in the query parameters. Use OAuth::getRefreshToken($authCode) to exchange this code for a permanent refresh token. This token can then be used to initialize a seller connector via SellingPartnerApi::seller().

    // --- Stage 1: Generate Authorization URI ---
    use SellingPartnerApi\Enums\Marketplace;
    use SellingPartnerApi\OAuth;
    
    $oauth = new OAuth(
        clientId: 'amzn1.application-oa2-client.asdfqwertyuiop...',
        clientSecret: 'amzn1.oa2-cs.v1.1234567890asdfghjkl...',
        redirectUri: 'https://example.com/redirect',
    );
    
    $authUrl = $oauth->getAuthorizationUri(
        appId: 'amzn1.sp.solution...',
        state: 'unique-base64-encoded-string',
        marketplace: Marketplace::US,
        draftApp: false,
    );
    // Redirect user to $authUrl...
    
    // --- Stage 2: Exchange Code for Refresh Token ---
    // After redirect, capture the 'spapi_oauth_code' from the query string
    $authCode = $_GET['spapi_oauth_code'];
    $refreshToken = $oauth->getRefreshToken($authCode);
    
    // Use the refresh token to make API calls
    $connector = SellingPartnerApi::seller(/* ... credentials using $refreshToken ... */);
  4. Upload a feed document

    main

    To upload a feed, you must first create a feed document specification, obtain a document ID, and then upload the content. The FeedDocument::upload() method supports both strings and Guzzle-compatible streams for handling large files.

    Workflow:

    1. Determine the content type using CreateFeedDocumentResponse::getContentType($feedType).
    2. Create a CreateFeedDocumentSpecification and call createFeedDocument().
    3. Use the resulting FeedDocument DTO to upload() your file contents.
    4. Create the actual feed using createFeed() with a CreateFeedSpecification containing the inputFeedDocumentId.
    use SellingPartnerApi\Seller\FeedsV20210630\Dto\CreateFeedDocumentSpecification;
    use SellingPartnerApi\Seller\FeedsV20210630\Dto\CreateFeedSpecification;
    use SellingPartnerApi\Seller\FeedsV20210630\Responses\CreateFeedDocumentResponse;
    
    $feedType = 'POST_PRODUCT_PRICING_DATA';
    $connector = SellingPartnerApi::seller(/* ... */);
    $feedsApi = $connector->feedsV20210630();
    
    // 1. Create feed document
    $contentType = CreateFeedDocumentResponse::getContentType($feedType);
    $createFeedDoc = new CreateFeedDocumentSpecification($contentType);
    $createDocumentResponse = $feedsApi->createFeedDocument($createFeedDoc);
    $feedDocument = $createDocumentResponse->dto();
    
    // 2. Upload feed contents
    $feedContents = file_get_contents('your/feed/file.xml');
    $feedDocument->upload($feedType, $feedContents);
    
    // 3. Create the feed
    $createFeedSpec = new CreateFeedSpecification(
        marketplaceIds: ['ATVPDKIKX0DER'],
        inputFeedDocumentId: $feedDocument->feedDocumentId,
        feedType: $feedType,
    );
    
    $createFeedResponse = $feedsApi->createFeed($createFeedSpec);
    $feedId = $createFeedResponse->dto()->feedId;
  5. Initialize a Selling Partner API connector

    main

    The SellingPartnerApi class acts as a factory to generate either seller() or vendor() API connector instances. You must provide your LWA (Login with Amazon) credentials and specify the appropriate endpoint.

    Note: If you are upgrading from older versions of this library, you no longer need to provide AWS IAM credentials, as the SP API no longer uses them for authentication.

    use SellingPartnerApi\
    use SellingPartnerApi\Enums\Endpoint;
    
    $connector = SellingPartnerApi::seller(
        clientId: 'amzn1.application-oa2-client.asdfqwertyuiop...',
        clientSecret: 'amzn1.oa2-cs.v1.1234567890asdfghjkl...',
        refreshToken: 'Atzr|IwEBIA...',
        endpoint: Endpoint::NA,  // Or Endpoint::EU, Endpoint::FE, Endpoint::NA_SANDBOX, etc.
    );
  6. Make API calls and handle responses

    main

    Once a connector is initialized, access API segments (like ordersV0()) and call their methods. Responses are instances of Saloon\Response. You can retrieve the raw JSON using $response->json() or automatically parse it into a Data Transfer Object (DTO) using $response->dto() to access data via properties.

    $ordersApi = $connector->ordersV0();
    $response = $ordersApi->getOrders(
        createdAfter: new DateTime('2024-01-01'),
        marketplaceIds: ['ATVPDKIKX0DER'],
    );
    
    // Access raw JSON
    $json = $response->json();
    
    // Access via DTO
    $dto = $response->dto();
    $purchaseDate = $dto->payload->orders[0]->purchaseDate;
  7. Manage and generate API schemas with the Schema class

    main

    The SellingPartnerApi\ Generator\Schema class is used to manage Amazon Selling Partner API schemas. It allows you to discover available APIs, download their raw definitions, refactor them into a usable format, and generate PHP code.

    Key workflows:

    1. Discovery: Use Schema::all() or Schema::where() to find available APIs by category or code.
    2. Download: Call download() to fetch the raw Amazon schema files.
    3. Refactor: Call refactor() to convert raw Amazon schemas into the internal format required for code generation.
    4. Generate: Call generate() to produce the final PHP code for all versions of the schema.
    use SellingPartnerApi\Generator\Schema;
    use SellingPartnerApi\Enums\ApiCategory;
    
    // 1. Find a specific schema
    $schemas = Schema::where([ApiCategory::SALES], ['orders']);
    $schema = $schemas[0];
    
    // 2. Run the generation pipeline
    $schema->download();
    $schema->refactor();
    $schema->generate();
  8. Configure SellingPartnerApi builder options

    main

    The SellingPartnerApi::seller() and SellingPartnerApi::vendor() methods accept the following configuration arguments:

    ArgumentTypeDescription
    clientIdstringRequired. The LWA client ID of the SP API application.
    clientSecretstringRequired. The LWA client secret of the SP API application.
    refreshTokenstringRequired (unless using grantless operations). The LWA refresh token. For grantless operations, pass 'grantless'.
    endpointEndpointRequired. An instance of SellingPartnerApi\Enums\Endpoint (e.g., Endpoint::NA, Endpoint::EU, Endpoint::FE, or their _SANDBOX variants).
    dataElementsarrayOptional. Data elements to pass to restricted operations.
    delegateestringOptional. The application ID of a delegatee application to generate RDTs on behalf of.
    authenticationClientGuzzleHttp\ClientOptional. A Guzzle client instance for generating access tokens. Defaults to the Saloon Guzzle client.
    cacheSellingPartnerApi\Contracts\TokenCacheOptional. A cache interface for access tokens. Defaults to in-memory. Set to null to disable caching.
  9. Debug API requests and responses

    main

    Since this library is built on Saloon, you can use Saloon's debugging hooks. Use debugRequest() to intercept and inspect requests, or use the built-in helper methods to write debug data directly to files.

    Available file-based debug methods:

    • debugRequestToFile($outputPath, $die = false)
    • debugResponseToFile($outputPath, $die = false)
    • debugToFile($outputPath, $die = false)
    use Psr\Http\Message\RequestInterface;
    use Saloon\Http\PendingRequest;
    use SellingPartnerApi\SellingPartnerApi;
    use SellingPartnerApi\Enums\Endpoint;
    
    $connector = SellingPartnerApi::seller(
        clientId: 'amzn1.application-oa2-client.asdfqwertyuiop...',
        clientSecret: 'amzn1.oa2-cs.v1.1234567890asdfghjkl...',
        refreshToken: 'Atzr|IwEBIA...',
        endpoint: Endpoint::NA,
    );
    
    $connector->debugRequest(
        function (PendingRequest $pendingRequest, RequestInterface $psrRequest) {
            var_dump($pendingRequest->headers()->all(), $psrRequest);
        }
    );
  10. Download a feed result document

    main

    Downloading a feed result document follows a pattern similar to downloading a report document. Use the getFeedDocument() method to retrieve the FeedDocument DTO, then call download() on that DTO.

    use SellingPartnerApi\SellingPartnerApi;
    
    $feedType = 'POST_PRODUCT_PRICING_DATA';
    $documentId = '1234567890.asdf';
    
    $connector = SellingPartnerApi::seller(/* ... */);
    $response = $connector->feedsV20210630()->getFeedDocument($documentId);
    $feedDocument = $response->dto();
    
    $contents = $feedDocument->download($feedType);
  11. Use DTOs for API requests

    main

    Many API methods require specific DTOs as parameters instead of plain arrays. You must instantiate the appropriate DTO classes (found within the segment's Dto namespace) to construct your requests.

    <?php
    
    use SellingPartnerApi\Seller\OrdersV0\Dto;
    use SellingPartnerApi\SellingPartnerApi;
    
    $confirmShipmentRequest = new Dto\ConfirmShipmentRequest(
        packageDetail: new Dto\PackageDetail(
            packageReferenceId: 'PKG123',
            carrierCode: 'USPS',
            trackingNumber: 'ASDF1234567890',
            shipDate: new DateTime('2024-01-01 12:00:00'),
            orderItems: [
                new Dto\ConfirmShipmentOrderItem(
                    orderItemId: '1234567890',
                    quantity: 1,
                ),
                new Dto\ConfirmShipmentOrderItem(
                    orderItemId: '0987654321',
                    quantity: 2,
                )
            ],
        ),
        marketplaceId: 'ATVPDKIKX0DER',
    );
    
    $response = $ordersApi->confirmShipment(
        orderId: '123-4567890-1234567',
        confirmShipmentRequest: $confirmShipmentRequest,
    );