Paquetecompense/sdk (namespace Compense\Sdk)
Versión1.1.0 · API v1
RequisitosPHP 8.1+ (declare(strict_types=1), DTO readonly)
HTTPCualquier cliente PSR-18 + fábricas PSR-17, descubiertos con php-http/discovery (Guzzle sugerido)
RepositorioAppiasoft/compense-saas-sdk-php · guías en docs/ · ejemplos en examples/ (PHP plano y Laravel)

Instalar #

Shell
composer require compense/sdk guzzlehttp/guzzle
# o con Symfony HttpClient:
composer require compense/sdk symfony/http-client nyholm/psr7

Cliente #

PHP
<?php
declare(strict_types=1);

use Compense\Sdk\CompenseClient;
use Compense\Sdk\RetryConfig;

$client = new CompenseClient(
    apiKey: getenv('COMPENSE_API_KEY'),        // cmp_...
    environment: 'sandbox',                    // 'production' (defecto) | 'sandbox' | 'dev'; o baseUrl: '...'
    timeout: 30.0,                             // se aplica cuando el SDK construye Guzzle
    retry: new RetryConfig(maxAttempts: 3, retryWrites: false),
    httpClient: null,                          // cualquier PSR-18 (contenedor, mocks…)
    logger: $psrLogger,                        // PSR-3: avisos de deprecación
);

Si pasas tu propio httpClient, configura en él el timeout. Las fábricas PSR-17 (requestFactory:, streamFactory:) se descubren solas si no las das.

Laravel #

Registra un singleton en un service provider y recíbelo por inyección:

PHP
// app/Providers/CompenseServiceProvider.php
$this->app->singleton(CompenseClient::class, static fn (): CompenseClient => new CompenseClient(
    apiKey: (string) config('services.compense.key'),
    environment: (string) config('services.compense.environment', 'sandbox'),
    timeout: 30.0,
    retry: new RetryConfig(maxAttempts: 3),
    logger: Log::channel('stack'),
));

// En un controlador:
public function store(Request $request, CompenseClient $compense) { /* ... */ }

En Symfony, registra CompenseClient como servicio pasándole tu Psr\Http\Client\ClientInterface.

Convenciones #

  • Métodos en camelCase con argumentos con nombre de PHP 8: $client->wallet->bills->pay(document: '1032456789', billerCode: 'EPM', reference: '123456789', amount: '90000').
  • Escrituras → Compense\Sdk\Model\Transaction; lecturas → modelos (Balance, Resolution, Page, OffsetPage…) o array. Todo modelo guarda el cuerpo en ->raw.
  • Módulo administrativo: los campos extra van como argumentos con nombre usando los nombres del contrato (first_name: 'Ana', bank_account: '...').
  • Decisiones: Compense\Sdk\Model\Decision::APPROVE / Decision::REJECT. Afiliados: new Compense\Sdk\Model\AffiliateRef('CC', '1032456789') o un array.
  • Montos: int, string o Stringable decimal; Money::normalize() da el mismo texto que Python.

Errores #

Namespace Compense\Sdk\Exception: CompenseException › CompenseConfigException, TransportException (fallo PSR-18, con el original en getPrevious()) y CompenseApiException › AuthException, NotFoundException, IdempotencyConflictException, ValidationException (errors()), RateLimitException (retryAfter), UpstreamException, ServerException. Propiedades: status, title, detail, traceId, problem.

Paginación #

Page (hasNext()) y OffsetPage (hasMore, nextOffset) son iterables y contables; recorre con un bucle do … while (Paginación).

Webhooks #

PHP
use Compense\Sdk\Webhook\Webhook;
use Compense\Sdk\Webhook\WebhookVerificationException;

$event = Webhook::verify(file_get_contents('php://input'), getallheaders(), [$newSecret, $oldSecret]);
// Laravel: Webhook::verify($request->getContent(), $request->headers->all(), $secrets)
// PSR-7:   Webhook::verifyRequest($request, $secrets)
$event->eventId; $event->event(); $event->resource(); $event->isTest();

Controlador de Laravel completo en Verificar la firma.

Pruebas #

Inyecta cualquier cliente PSR-18 falso (por ejemplo php-http/mock-client o un Psr\Http\Client\ClientInterface propio) en httpClient: y verifica las peticiones que recibe. Para pruebas de integración, usa una llave de sandbox.

Desarrollo del SDK #

Todo corre en Docker: make test (PHPUnit en PHP 8.3), make test81 (PHP 8.1) y make analyse (PHPStan nivel máximo).