PHP code example of prhost / systax-sdk

1. Go to this page and download the library: Download prhost/systax-sdk library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

prhost / systax-sdk example snippets


use Prhost\SystaxSdk\SystaxClient;

// Credenciais de homologação (padrão — superdemo.ws / systax741)
$client = new SystaxClient();

// Credenciais de produção (override)
$client = new SystaxClient(
    username: 'sua_empresa@usuario',
    password: 'sua_senha_producao',
);

// Override completo (incluindo base URL, útil para staging)
$client = new SystaxClient(
    username: 'usuario',
    password:  'senha',
    baseUrl:  'https://app.systax.com.br',
);

new SystaxClient(
    ?string $username  = null,   // padrão: 'superdemo.ws'
    ?string $password  = null,   // padrão: 'systax741'
    ?string $baseUrl   = null,   // padrão: 'https://app.systax.com.br'
    ?ClientInterface $httpClient = null, // injeção de Guzzle customizado (testes)
)

// Forçar busca de novo token
$client->getTokenManager()->fetchToken();

// Forçar renovação de token existente
$client->getTokenManager()->refreshToken();

// Invalidar cache (força nova autenticação na próxima chamada)
$client->getTokenManager()->clearToken();

// Inspecionar token atual em cache
$token = $client->getTokenManager()->getCachedToken(); // null se não autenticado

use Prhost\SystaxSdk\DTO\CestItem;

// Mínimo — apenas NCM (obrigatório)
$item = CestItem::make('39181000');

// Com todos os parâmetros opcionais
$item = CestItem::make(
    ncm:     '39181000',
    exTipi:  '01',         // Código EX da TIPI (opcional)
    uf:      'SP',         // UF de consulta (opcional; vazio = sem filtro de UF)
    data:    '2024-01-01', // Data de vigência (opcional; vazio = data atual)
    id:      '1',          // Sequencial (opcional)
);

$results = $client->cest()->query([
    CestItem::make('39181000'),
    CestItem::make('22089000', uf: 'SP'),
]);

foreach ($results as $result) {
    $result->id;           // string — sequencial
    $result->ncm;          // string — NCM consultado (ex: '39181000')
    $result->exTipi;       // string — EX TIPI consultado
    $result->uf;           // string — UF consultada
    $result->data;         // string — data consultada
    $result->ncmTabela;    // string — NCM na tabela Systax (ex: '3918')
    $result->cest;         // string — código CEST (ex: '1017400')
    $result->descricao;    // string — descrição do CEST
    $result->ufTabela;     // string — UF na tabela CEST Systax
    $result->exTipiTabela; // string — EX TIPI na tabela Systax
    $result->statusCodigo; // int    — código de status (0 = sucesso)
    $result->statusMsg;    // string — mensagem de status
    $result->isSuccess();  // bool   — true se statusCodigo === 0
}

use Prhost\SystaxSdk\SystaxClient;
use Prhost\SystaxSdk\DTO\CestItem;
use Prhost\SystaxSdk\Exceptions\ApiException;

$client = new SystaxClient();

try {
    $results = $client->cest()->query([CestItem::make('39181000')]);

    foreach ($results as $result) {
        echo "NCM: {$result->ncm} | CEST: {$result->cest} | {$result->descricao}\n";
    }
} catch (ApiException $e) {
    // Exemplo: NCM inválida, NCM sem CEST, UF inválida, etc.
    echo "Erro API [{$e->getApiCode()}]: {$e->getApiMessage()}\n";
}

// Página 1 (padrão)
$response = $client->cestV2()->query([
    CestItem::make('22089000'),
]);

// Página específica
$response = $client->cestV2()->query([
    CestItem::make('22089000'),
], offset: 3);

// Com ponteiro para buscar apenas atualizações desde a última sincronização
$response = $client->cestV2()->query([
    CestItem::make('22089000', ponteiro: '20231013095117'),
]);

$response->totalPaginas; // int    — total de páginas disponíveis
$response->totalItens;   // int    — total de itens encontrados
$response->ultPonteiro;  // string — último ponteiro da tabela (usar para próxima sync)
$response->items;        // CestV2Result[]

$item->vigenciaDe;  // string — data inicial da vigência (ex: '2016-10-01')
$item->vigenciaAte; // string — data final da vigência (vazio = vigente)
$item->ponteiro;    // string — ponteiro de atualização deste item

// Primeira sincronização — salvar ultPonteiro
$response  = $client->cestV2()->query([CestItem::make('22089000')]);
$ponteiro  = $response->ultPonteiro; // '20231114020001'

// Próxima sincronização — buscar apenas o que mudou
$response2 = $client->cestV2()->query([
    CestItem::make('22089000', ponteiro: $ponteiro),
]);

if (empty($response2->items)) {
    echo "Nenhuma atualização desde o último ponteiro.\n";
}

// Listar tudo (padrão: 100 por página)
$response = $client->ncm()->list();

// Filtrar por prefixo de NCM (2 a 8 dígitos)
$response = $client->ncm()->list(ncm: '3926');
$response = $client->ncm()->list(ncm: '39269090');

// Filtrar por EX TIPI
$response = $client->ncm()->list(ncm: '39269090', exTipi: '01');

// Filtrar por data de vigência
$response = $client->ncm()->list(vigenciaEm: '2024-01-01');

// Paginação
$response = $client->ncm()->list(ncm: '39', limit: 50, offset: 2);

// Ordenação: campo|direção
$response = $client->ncm()->list(order: ['ncm|asc', 'descricao|desc']);

// Buscar por ID interno Systax
$response = $client->ncm()->findById(1039194);

$client->ncm()->list(
    ?string $ncm        = null,  // 2–8 dígitos
    ?string $exTipi     = null,
    ?string $vigenciaEm = null,  // YYYY-MM-DD
    ?int    $id         = null,  // ID interno Systax
    int     $limit      = 100,
    int     $offset     = 1,
    ?array  $order      = null,  // ex: ['ncm|asc']
): NcmResponse

$response->success;     // bool   — true se consulta OK
$response->message;     // string — 'ok' em caso de sucesso
$response->recordCount; // int    — total de registros retornados
$response->data;        // NcmResult[]

$item->id;          // int         — ID interno Systax (ex: 1039194)
$item->ncm;         // string      — código NCM de 8 dígitos (ex: '39269090')
$item->exTipi;      // string|null — código EX TIPI (null se não houver)
$item->vigenciaDe;  // string|null — data início de vigência (ex: '2022-04-01')
$item->vigenciaAte; // string|null — data fim de vigência (null = vigente)
$item->aliquota;    // float       — alíquota IPI (ex: 14.5)
$item->descricao;   // string      — descrição da NCM
$item->nota;        // string|null — nota complementar de legislação

use Prhost\SystaxSdk\SystaxClient;
use Prhost\SystaxSdk\Exceptions\AuthException;

$client = new SystaxClient();

try {
    $response = $client->ncm()->list(ncm: '3926', limit: 10);

    echo "Total: {$response->recordCount}\n";

    foreach ($response->data as $ncm) {
        echo "{$ncm->ncm} — {$ncm->descricao} | Alíquota: {$ncm->aliquota}%\n";
        if ($ncm->exTipi) {
            echo "  EX TIPI: {$ncm->exTipi}\n";
        }
    }
} catch (AuthException $e) {
    echo "Falha de autenticação: {$e->getMessage()}\n";
}

use Prhost\SystaxSdk\Exceptions\AuthException;
use Prhost\SystaxSdk\Exceptions\ApiException;
use Prhost\SystaxSdk\Exceptions\SystaxException;

try {
    $results = $client->cest()->query([CestItem::make('99999999')]);
} catch (AuthException $e) {
    // Problema de autenticação — verificar credenciais ou token
    logger()->error('Systax auth error', ['message' => $e->getMessage()]);
} catch (ApiException $e) {
    // Erro de negócio (NCM inválida, sem CEST, etc.)
    logger()->warning('Systax API error', [
        'code'    => $e->getApiCode(),
        'message' => $e->getApiMessage(),
    ]);
} catch (SystaxException $e) {
    // Qualquer outro erro do SDK
    logger()->error('Systax SDK error', ['message' => $e->getMessage()]);
}

use GuzzleHttp\Client;
use GuzzleHttp\Handler\MockHandler;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Psr7\Response;

$mock  = new MockHandler([
    new Response(200, [], '{"success":true,"status":"OK","token":"jwt...","expires_in":3600}'),
    new Response(200, [], file_get_contents(__DIR__ . '/../../Fixtures/cest_response.json')),
]);
$stack = HandlerStack::create($mock);
$http  = new Client(['handler' => $stack, 'http_errors' => false]);

tests/
├── Fixtures/
│   ├── auth_error_response.json   — resposta 401 simulada
│   ├── token_response.json        — resposta de token válido
│   ├── cest_response.json         — resposta CEST v1
│   ├── cestv2_response.json       — resposta CEST v2 (com paginação)
│   └── ncm_response.json          — resposta NCM
└── Unit/
    ├── Auth/
    │   └── TokenManagerTest.php   — 9 testes: fetch, cache, refresh, erros
    ├── Resources/
    │   ├── CestResourceTest.php   — 10 testes: parse, erros, cache token
    │   ├── CestV2ResourceTest.php — 8 testes: paginação, ponteiro, vigência
    │   └── NcmResourceTest.php    — 9 testes: list, findById, campos, erros
    └── SystaxClientTest.php       — 14 testes: credenciais, lazy resources

├── .gitignore
├── composer.json
├── phpunit.xml
├── src/
│   ├── SystaxClient.php
│   ├── Config.php
│   ├── Auth/
│   │   └── TokenManager.php
│   ├── DTO/
│   │   ├── CestItem.php
│   │   ├── CestResult.php
│   │   ├── CestV2Result.php
│   │   ├── CestV2Response.php
│   │   ├── NcmResult.php
│   │   ├── NcmResponse.php
│   │   └── TokenResponse.php
│   ├── Resources/
│   │   ├── CestResource.php
│   │   ├── CestV2Resource.php
│   │   └── NcmResource.php
│   └── Exceptions/
│       ├── SystaxException.php
│       ├── AuthException.php
│       └── ApiException.php
└── tests/
    ├── Fixtures/
    │   ├── token_response.json
    │   ├── auth_error_response.json
    │   ├── cest_response.json
    │   ├── cestv2_response.json
    │   └── ncm_response.json
    └── Unit/
        ├── Auth/
        │   └── TokenManagerTest.php
        ├── Resources/
        │   ├── CestResourceTest.php
        │   ├── CestV2ResourceTest.php
        │   └── NcmResourceTest.php
        └── SystaxClientTest.php