Corporate merch in other countries:AMArmeniaGEGeorgiaTRTürkiyeRSSerbiaAEUAECYCyprusITItalyPTPortugalPLPoland

PHP SDK for Spain

corp-merch/sdk on Packagist — PHP 8.1+, PSR-7/PSR-18, native Laravel and Symfony bridges, readonly DTOs.

Install & init

composer require corp-merch/sdk. $cm = new CorpMerch\Client(apiKey: getenv('CM_KEY'), country: 'Spain'). Uses PSR-18 HTTP client — pass any (Guzzle, Symfony HttpClient, sensible default). Auto-applies IVA 21% and FACe/SII (AEAT) for Spain; hub defaults to Madrid.

Quickstart — submit an order

$order = $cm->orders->create(idempotencyKey: Uuid::v4(), buyer: ['vat_id' => 'EU…'], lines: [['sku' => 'TSH-001', 'qty' => 200]], promisedDate: '2026-07-01'); echo $order->id; echo $order->estimatedIvaAmountCents. Returns readonly Order DTO. Errors thrown as CorpMerch\Exception\ValidationException etc.

Laravel & Symfony bridges

Laravel: install corp-merch/sdk-laravel — registers a singleton bound to config('corp-merch.country'). Symfony: corp-merch/sdk-symfony adds a bundle with autowired client. Both packages ship webhook middlewares that validate signature and dispatch typed events on the framework's event bus.

FAQ

Minimum PHP version?

PHP 8.1 (readonly properties, enums). PHP 8.2 and 8.3 also tested. PHP 7.x not supported.

Which HTTP client?

PSR-18 — bring your own. Default discovery via http-interop/http-factory-discovery, picks up Guzzle or Symfony HttpClient if installed.

How are responses typed?

Readonly DTOs (Order, Invoice, CatalogItem). Enums for statuses (OrderStatus::ACCEPTED etc.). Strict types: declare(strict_types=1) on every file.

Catalog iteration?

foreach ($cm->catalog->iterate(country: 'Spain') as $item) { … } — generator-based, fetches pages lazily. Cancel mid-loop by break with no waste.

Source code?

MIT on GitHub: github.com/corp-merch/sdk-php. PSR-12 codestyle; PHPStan level 9 in CI.

Talk to a specialist