SDK - PHP
naprawksef/sdk - wymaga PHP 8.1+ i ext-curl. Bez Guzzle, bez PSR-7. Działa z Laravel, Symfony i czystym PHP.
Instalacja
bash
composer require naprawksef/sdkWymaga PHP 8.1+, ext-curl, ext-json. Brak zewnętrznych pakietów Composer w runtime - dziala out-of-the-box w każdym shared hostingu / Dockerze.
Inicjalizacja
php
<?php
use NaprawKsef\Sdk\NaprawKsef;
require __DIR__ . '/vendor/autoload.php';
$client = new NaprawKsef([
'api_key' => $_ENV['NAPRAW_KSEF_API_KEY'], // nk_live_... lub nk_test_...
'app_name' => 'trawers-erp/7.4.2', // dorzucamy do User-Agent
'timeout_ms' => 30_000,
'max_retries' => 3, // 0 = bez retries
]);Konstruktor waliduje format klucza - błąd konfiguracji rzuca InvalidArgumentException zanim zrobi pierwsze połączenie.
Walidacja XML
php
$result = $client->validate->run(
xml: file_get_contents('faktura.xml'),
filename: 'faktura.xml',
idempotencyKey: "invoice-{$invoice->id}-v3", // opcjonalne
);
if (!$result['valid']) {
foreach ($result['issues'] as $issue) {
printf(
"[%s] %s: %s\n",
$issue['severity'],
$issue['code'],
$issue['message'],
);
}
}Analiza pod korekty FA(3)
php
$analysis = $client->correction->analyze(
xml: file_get_contents('faktura.xml'),
);
print_r($analysis['analysis']['totals']);
print_r($analysis['suggestions']); // top 5 scenariuszy
print_r($analysis['lines_jpk']); // sugestie pól JPK_V7MWebhooks
php
$created = $client->webhooks->create(
name: 'Production receiver',
url: 'https://my-app.com/webhooks/napraw-ksef',
events: ['validation.completed', 'correction.created'],
);
// Plaintext sekret jest dostępny TYLKO RAZ:
echo $created['secret'];
$list = $client->webhooks->list();
$deliveries = $client->webhooks->listDeliveries($created['webhook']['id']);
$client->webhooks->sendTest($created['webhook']['id']); // smoke test
$client->webhooks->update($created['webhook']['id'], ['is_active' => false]);
$client->webhooks->delete($created['webhook']['id']);Weryfikacja podpisu webhooka
Vanilla PHP (CGI / Apache):
php
<?php
use NaprawKsef\Sdk\Webhooks\SignatureVerifier;
require __DIR__ . '/vendor/autoload.php';
$rawBody = file_get_contents('php://input');
$header = $_SERVER['HTTP_X_NK_SIGNATURE'] ?? null;
$result = SignatureVerifier::verify(
secret: $_ENV['NAPRAW_KSEF_WEBHOOK_SECRET'],
rawBody: $rawBody,
header: $header,
);
if (!$result['ok']) {
http_response_code(401);
exit('Invalid signature: ' . $result['reason']);
}
$event = json_decode($rawBody, true);
// handle $event['type']Laravel:
php
use NaprawKsef\Sdk\Webhooks\SignatureVerifier;
public function __invoke(Request $request)
{
$result = SignatureVerifier::verify(
secret: config('services.naprawksef.webhook_secret'),
rawBody: $request->getContent(),
header: $request->header('X-NK-Signature'),
);
abort_if(!$result['ok'], 401, 'Invalid signature: ' . $result['reason']);
$event = $request->json()->all();
// …
return response('ok');
}Więcej w przewodniku Webhooks.
Typowane wyjątki
php
use NaprawKsef\Sdk\Exceptions\{
AuthException,
RateLimitException,
ValidationException,
ServerException,
};
try {
$client->validate->run(xml: $xml);
} catch (RateLimitException $e) {
sleep($e->retryAfterSeconds() ?? 60);
} catch (AuthException $e) {
rotateKey();
} catch (ValidationException $e) {
showFieldErrors($e->details);
} catch (ServerException $e) {
Sentry::captureException($e); // request_id w $e->requestId
}Pełny README
Pełna dokumentacja, lista wyjątków i przykłady receiver'ów Laravel / Symfony żyją w pakiecie: packagist.org/packages/naprawksef/sdk.