sonnenglas/takealot-php-sdk 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

sonnenglas/takealot-php-sdk

Composer 安装命令:

composer require sonnenglas/takealot-php-sdk

包简介

Framework-agnostic PHP SDK for the Takealot Marketplace API (sales, offers, transactions, balances, returns, shipments) with continuation-token pagination and 429 retry handling.

README 文档

README

Framework-agnostic PHP SDK for the Takealot Marketplace API — read seller sales, offers, transactions, balances, returns, shipments, facilities, and account information from your Takealot Seller account.

Packagist Version Packagist Downloads PHP Version License PHPStan

Features

  • Framework-agnostic. Plain PSR-18 (HTTP client), PSR-17 (factories), and PSR-7 (messages). No Laravel, no Symfony, no global state — drop it into any modern PHP project.
  • Read-only and safe. The SDK wraps the Marketplace API's GET endpoints only. It never creates, updates, or disables anything on your account — so there is no risk of an accidental price change or a disabled offer.
  • Type-safe DTOs. Readonly response objects with strict shape validation. Malformed upstream payloads fail loudly instead of leaking untyped arrays through your code.
  • Continuation-token pagination, two ways. Fetch a single Page and follow the token yourself, or iterate() a lazy Generator that walks every page transparently.
  • Automatic rate-limit handling. HTTP 429 responses are retried automatically, honouring the Retry-After header, with exponential backoff as a fallback. Configurable via maxRetries.
  • Typed exception hierarchy. 400, 401/403, 404, and 429 each map to a distinct exception subclass — no need to grep on status codes.
  • Hardened by default. 8 MiB response body cap, JSON depth limit of 64, and PSR-18 transport-error wrapping that scrubs the X-API-Key header from leaked messages.
  • PHPStan level 9. Strict types throughout, zero static-analysis errors.

Why this SDK?

Takealot does not publish an official PHP SDK at the time of writing. This package is built against the current public Takealot Marketplace API at https://marketplace-api.takealot.com/v1, targets modern PHP (8.2+), and stays out of your dependency-injection container by design.

It is the integration layer SONNENGLAS uses to pull our South African marketplace sales and settlement data into our own systems.

Requirements

  • PHP 8.2 or newer.
  • A PSR-18 HTTP client. Guzzle 7 is the recommended default and is automatically discovered via php-http/discovery.

Installation

composer require sonnenglas/takealot-php-sdk

If you do not already have a PSR-18 client installed:

composer require guzzlehttp/guzzle

php-http/discovery auto-wires any installed PSR-18 client and PSR-17 factories — you only need to inject them manually if you want to override defaults (timeouts, retry middleware, a mock client in tests, etc.).

Quick start

1. Construct the client

Generate an API key in the Takealot Seller Portal under Settings → API Access, then construct the client with it. Everything else is optional.

use Sonnenglas\Takealot\Client;

$client = new Client(apiKey: getenv('TAKEALOT_API_KEY'));

The key is sent as the X-API-Key header on every request. Only one API key can be active per seller account at a time.

2. List a page of sales

$page = $client->sales()->list([
    'order_date__gte' => '2026-06-01',   // inclusive, YYYY-MM-DD, SAST
    'order_date__lte' => '2026-06-30',
    'limit'           => 100,            // 1–100, default 20
    'include_count'   => true,
]);

foreach ($page->items as $sale) {
    printf(
        "Order %d · %s · R%d · %s\n",
        $sale->orderId,
        $sale->sku,
        $sale->sellingPrice,
        $sale->salesRegion ?? 'unknown',
    );
}

echo "Matching sales: " . ($page->count ?? 'n/a') . "\n";
echo $page->hasMore() ? "More pages available.\n" : "Last page.\n";

3. Iterate every sale across pages

iterate() follows the continuation_token for you, so you never have to manage paging by hand:

$totalUnits = 0;

foreach ($client->sales()->iterate(['order_date__gte' => '2026-06-01']) as $sale) {
    $totalUnits += $sale->quantity;
}

echo "Units sold in June: {$totalUnits}\n";

4. Read your account balance

$balances = $client->balances()->get()->balances;   // nested ?Balances breakdown

printf(
    "Available for payout: R%.2f (held back R%.2f)\n",
    $balances?->available ?? 0.0,
    $balances?->heldBack ?? 0.0,
);

Documentation

Supported endpoints

The SDK targets the seller-facing read surface of the Marketplace API. Every collection endpoint supports continuation-token pagination, fields selection, and (where applicable) expands.

Resource Endpoint(s) Accessor Operations
Sales GET /sales $client->sales() list(), iterate()
Offers GET /offers, GET /offers/{id}, GET /offers/by_sku/{sku}, GET /offers/by_barcode/{barcode} $client->offers() list(), iterate(), getById(), getBySku(), getByBarcode()
Transactions GET /transactions $client->transactions() list(), iterate()
Balances GET /balances $client->balances() get()
Returns GET /returns, GET /returns/{id} $client->returns() list(), iterate(), getById()
Shipments GET /shipments, GET /shipments/{id} $client->shipments() list(), iterate(), getById()
Facilities GET /facilities/get_enabled_regions $client->facilities() enabledRegions()
Seller GET /seller $client->seller() get()

Single-item lookups (getById(), getBySku(), getByBarcode(), returns()->getById(), shipments()->getById()) return the DTO, or null when the item does not exist (HTTP 404) — they do not throw on a missing item.

Write operations are out of scope. The Marketplace API exposes offer-management endpoints (POST /offers, PATCH /offers/{id}, POST /offers/batch). This SDK deliberately does not wrap them — it is a read-only client. Call them directly if you need to mutate offers.

Pagination

Collection endpoints return a Page:

$page = $client->sales()->list(['limit' => 50]);

$page->items;             // list<Sale>
$page->continuationToken; // string|null — the token for the next page
$page->count;             // int|null — total matches (only with include_count=true)
$page->hasMore();         // bool — true when continuationToken !== null

To walk every page manually, feed the token back in. When a continuation token is supplied, all other query parameters are ignored by the API — pass the token alone:

$params = ['order_date__gte' => '2026-06-01', 'limit' => 100];

do {
    $page = $client->sales()->list($params);

    foreach ($page->items as $sale) {
        // ...
    }

    $params = ['continuation_token' => $page->continuationToken];
} while ($page->hasMore());

Or let the SDK do it for you with iterate() — see the pagination guide.

Rate limiting & retries

The client retries HTTP 429 responses automatically:

  • It reads the Retry-After header (integer seconds or an HTTP-date) and waits that long before retrying, capped at 60 seconds per attempt.
  • If no usable Retry-After is present, it falls back to exponential backoff (1s, 2s, 4s, …, capped at 60s).
  • After maxRetries (default 3) exhausted attempts, it throws RateLimitException, which exposes $retryAfter for your own scheduling.

Tune or disable retries via the constructor:

// More patient: up to 5 retries.
$client = new Client(apiKey: $key, maxRetries: 5);

// Fail fast: no automatic retries.
$client = new Client(apiKey: $key, maxRetries: 0);

See the rate-limiting guide for details and for how to inject a no-op sleeper in tests.

Error handling

All SDK exceptions extend Sonnenglas\Takealot\Exceptions\TakealotException.

HTTP Exception When
400 ValidationException Invalid query parameters or filters.
401 / 403 AuthenticationException Missing, invalid, or deactivated API key.
404 NotFoundException A missing resource. Single-item lookups catch this and return null instead.
429 RateLimitException ($retryAfter) Rate limit hit after automatic retries were exhausted.
other ApiException Any other 4xx/5xx, oversized body, or malformed JSON.
TransportException The PSR-18 client failed (DNS / TCP / TLS / timeout). statusCode is 0.

ApiException (and therefore every subclass) carries $statusCode and the decoded $responseBody:

use Sonnenglas\Takealot\Exceptions\AuthenticationException;
use Sonnenglas\Takealot\Exceptions\RateLimitException;
use Sonnenglas\Takealot\Exceptions\TakealotException;

try {
    $page = $client->sales()->list(['order_date__gte' => '2026-06-01']);
} catch (AuthenticationException $e) {
    // Check that TAKEALOT_API_KEY is set and still active in the Seller Portal.
    throw $e;
} catch (RateLimitException $e) {
    sleep($e->retryAfter ?? 5);
    // ...retry...
} catch (TakealotException $e) {
    error_log("Takealot API error ({$e->getCode()}): {$e->getMessage()}");
    throw $e;
}

See the error-handling guide for the full decision matrix.

Testing

The SDK is built test-first against php-http/mock-client, so you can exercise every code path without touching the live API. Swap in a mock PSR-18 client and a no-op Sleeper to make retry tests instant:

use GuzzleHttp\Psr7\HttpFactory;
use GuzzleHttp\Psr7\Response;
use Http\Mock\Client as MockClient;
use Sonnenglas\Takealot\Client;

$mock = new MockClient();
$mock->addResponse(new Response(200, [], json_encode([
    'items' => [/* ...sale rows... */],
    'limit' => 20,
], JSON_THROW_ON_ERROR)));

$factory = new HttpFactory();
$client = new Client(
    apiKey: 'key_test',
    httpClient: $mock,
    requestFactory: $factory,
);

$page = $client->sales()->list(['limit' => 20]);

Run the SDK's own suite with:

composer test       # PHPUnit
composer phpstan    # PHPStan level 9
composer check      # phpstan + test together

Versioning

This project follows Semantic Versioning 2.0.0. See CHANGELOG.md for the release history.

Contributing

Pull requests, issues, and discussions are welcome. Please read CONTRIBUTING.md before opening a PR — it covers the dev setup, coding standards, and the test-first workflow used throughout the codebase.

Security vulnerabilities should be reported privately — see SECURITY.md.

License

Released under the MIT License.

Credits

Built and maintained by SONNENGLAS.

If this SDK saves you time, please consider starring the GitHub repository.

统计信息

  • 总下载量: 0
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 1
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-06-23

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固