This package is not production ready yet!
PHP API client that allows you to interact with the KSEF API Krajowy System e-Faktur
Main features:
- Support for authorization using qualified certificates, KSeF certificates, KSeF tokens, and trusted ePUAP signatures (manual mode)
- Support for async batch send multiple invoices
- Logical invoice structure mapped to DTOs and ValueObjects
- Automatic access token refresh
- CSR (Certificate Signing Request) handling
- KSeF exception handling
- QR codes generation
| KSEF Version | Branch | Release Version |
|---|---|---|
| 2.0 | main | ^0.3 |
| 1.0 | 0.2.x | 0.2.* |
- Get Started
- Authorization
- Resources
- Examples
- Testing
- Roadmap
- Special thanks
Requires PHP 8.1+
First, install ksef-php-client via the Composer package manager:
composer require n1ebieski/ksef-php-clientEnsure that the php-http/discovery composer plugin is allowed to run or install a client manually if your project does not already have a PSR-18 client integrated.
composer require guzzlehttp/guzzleuse N1ebieski\KSEFClient\ClientBuilder;
use N1ebieski\KSEFClient\ValueObjects\Mode;
use N1ebieski\KSEFClient\Factories\EncryptionKeyFactory;
$client = (new ClientBuilder())
->withMode(Mode::Production) // Choice between: Test, Demo, Production
->withApiUrl($_ENV['KSEF_API_URL']) // Optional, default is set by Mode selection
->withHttpClient(new \GuzzleHttp\Client(...)) // Optional PSR-18 implementation, default is set by Psr18ClientDiscovery::find()
->withLogger(new \Monolog\Logger(...)) // Optional PSR-3 implementation, default is set by PsrDiscovery\Discover::log()
->withLogPath($_ENV['PATH_TO_LOG_FILE'], $_ENV['LOG_LEVEL']) // Optional, level: null disables logging
->withAccessToken($_ENV['ACCESS_TOKEN'], $_ENV['VALID_UNTIL']) // Optional, if present, auto authorization is skipped
->withRefreshToken($_ENV['REFRESH_TOKEN'], $_ENV['VALID_UNTIL']) // Optional, if present, auto refresh access token is enabled
->withKsefToken($_ENV['KSEF_TOKEN']) // Required for API Token authorization. Optional otherwise
->withCertificatePath($_ENV['PATH_TO_CERTIFICATE'], $_ENV['CERTIFICATE_PASSPHRASE']) // Required .p12 file for Certificate authorization. Optional otherwise
->withVerifyCertificateChain(true) // Optional. Explanation https://ksef-test.mf.gov.pl/docs/v2/index.html#tag/Uzyskiwanie-dostepu/paths/~1api~1v2~1auth~1xades-signature/post
->withEncryptionKey(EncryptionKeyFactory::makeRandom()) // Required for invoice resources. Remember to save this value!
->withIdentifier('NIP_NUMBER') // Required for authorization. Optional otherwise
->withAsyncMaxConcurrency(8) // Optional. Maximum concurrent send operations during asynchronous sending
->build();Each resource supports mapping through both an array and a DTO, for example:
use N1ebieski\KSEFClient\Requests\Auth\Status\StatusRequest;
use N1ebieski\KSEFClient\Requests\ValueObjects\ReferenceNumber;
$authorisationStatusResponse = $client->auth()->status(new StatusRequest(
referenceNumber: ReferenceNumber::from('20250508-EE-B395BBC9CD-A7DB4E6095-BD')
))->object();or:
$authorisationStatusResponse = $client->auth()->status([
'referenceNumber' => '20250508-EE-B395BBC9CD-A7DB4E6095-BD'
])->object();use N1ebieski\KSEFClient\ClientBuilder;
$client = (new ClientBuilder())
->withKsefToken($_ENV['KSEF_KEY'])
->withIdentifier('NIP_NUMBER')
->build();
// Do something with the available resourcesuse N1ebieski\KSEFClient\ClientBuilder;
$client = (new ClientBuilder())
->withCertificatePath($_ENV['PATH_TO_CERTIFICATE'], $_ENV['CERTIFICATE_PASSPHRASE'])
->withIdentifier('NIP_NUMBER')
->build();
// Do something with the available resourcesuse N1ebieski\KSEFClient\ClientBuilder;
use N1ebieski\KSEFClient\Support\Utility;
use N1ebieski\KSEFClient\Requests\Auth\DTOs\XadesSignature;
use N1ebieski\KSEFClient\Requests\Auth\XadesSignature\XadesSignatureXmlRequest;
$client = (new ClientBuilder())->build();
$nip = 'NIP_NUMBER';
$authorisationChallengeResponse = $client->auth()->challenge()->object();
$xml = XadesSignature::from([
'challenge' => $authorisationChallengeResponse->challenge,
'contextIdentifierGroup' => [
'identifierGroup' => [
'nip' => $nip
]
],
'subjectIdentifierType' => 'certificateSubject'
])->toXml();
$signedXml = 'SIGNED_XML_DOCUMENT'; // Sign a xml document via Szafir, ePUAP etc.
$authorisationAccessResponse = $client->auth()->xadesSignature(
new XadesSignatureXmlRequest($signedXml)
)->object();
$client = $client->withAccessToken($authorisationAccessResponse->authenticationToken->token);
$authorisationStatusResponse = Utility::retry(function () use ($client, $authorisationAccessResponse) {
$authorisationStatusResponse = $client->auth()->status([
'referenceNumber' => $authorisationAccessResponse->referenceNumber
])->object();
if ($authorisationStatusResponse->status->code === 200) {
return $authorisationStatusResponse;
}
if ($authorisationStatusResponse->status->code >= 400) {
throw new RuntimeException(
$authorisationStatusResponse->status->description,
$authorisationStatusResponse->status->code
);
}
});
$authorisationTokenResponse = $client->auth()->token()->redeem()->object();
$client = $client
->withAccessToken(
token: $authorisationTokenResponse->accessToken->token,
validUntil: $authorisationTokenResponse->accessToken->validUntil
)
->withRefreshToken(
token: $authorisationTokenResponse->refreshToken->token,
validUntil: $authorisationTokenResponse->refreshToken->validUntil
);
// Do something with the available resources$response = $client->auth()->challenge()->object();use N1ebieski\KSEFClient\Requests\Auth\XadesSignature\XadesSignatureRequest;
$response = $client->auth()->xadesSignature(
new XadesSignatureRequest(...)
)->object();or:
use N1ebieski\KSEFClient\Requests\Auth\XadesSignature\XadesSignatureXmlRequest;
$response = $client->auth()->xadesSignature(
new XadesSignatureXmlRequest(...)
)->object();use N1ebieski\KSEFClient\Requests\Auth\Status\StatusRequest;
$response = $client->auth()->status(
new StatusRequest(...)
)->object();$response = $client->auth()->token()->redeem()->object();$response = $client->auth()->token()->refresh()->object();https://ksef-test.mf.gov.pl/docs/v2/index.html#tag/Aktywne-sesje/paths/~1api~1v2~1auth~1sessions/get
use N1ebieski\KSEFClient\Requests\Auth\Sessions\List\ListRequest;
$response = $client->auth()->sessions()->list(
new ListRequest(...)
)->object();$response = $client->auth()->sessions()->revokeCurrent()->object();use N1ebieski\KSEFClient\Requests\Auth\Sessions\Revoke\RevokeRequest;
$response = $client->auth()->sessions()->revoke(
new RevokeRequest(...)
)->object();$response = $client->security()->publicKeyCertificates()->object();use N1ebieski\KSEFClient\Requests\Sessions\Invoices\Upo\UpoRequest;
$response = $client->sessions()->invoices()->upo(
new UpoRequest(...)
)->body();use N1ebieski\KSEFClient\Requests\Sessions\Invoices\KsefUpo\KsefUpoRequest;
$response = $client->sessions()->invoices()->ksefUpo(
new KsefUpoRequest(...)
)->body();use N1ebieski\KSEFClient\Requests\Sessions\Invoices\Status\StatusRequest;
$response = $client->sessions()->invoices()->status(
new StatusRequest(...)
)->object();use N1ebieski\KSEFClient\Requests\Sessions\Online\Open\OpenRequest;
$response = $client->sessions()->online()->open(
new OpenRequest(...)
)->object();use N1ebieski\KSEFClient\Requests\Sessions\Online\Close\CloseRequest;
$response = $client->sessions()->online()->close(
new CloseRequest(...)
)->status();for DTO invoice:
use N1ebieski\KSEFClient\Requests\Sessions\Online\Send\SendRequest;
$response = $client->sessions()->online()->send(
new SendRequest(...)
)->object();for XML invoice:
use N1ebieski\KSEFClient\Requests\Sessions\Online\Send\SendXmlRequest;
$response = $client->sessions()->online()->send(
new SendXmlRequest(...)
)->object();for DTOs invoices:
use N1ebieski\KSEFClient\Requests\Sessions\Batch\OpenAndSend\OpenAndSendRequest;
$response = $client->sessions()->batch()->openAndSend(
new OpenAndSendRequest(...)
)->object();for XMLs invoices:
use N1ebieski\KSEFClient\Requests\Sessions\Batch\OpenAndSend\OpenAndSendXmlRequest;
$response = $client->sessions()->batch()->openAndSend(
new OpenAndSendXmlRequest(...)
)->object();for ZIP invoices:
use N1ebieski\KSEFClient\Requests\Sessions\Batch\OpenAndSend\OpenAndSendZipRequest;
$response = $client->sessions()->batch()->openAndSend(
new OpenAndSendZipRequest(...)
)->object();use N1ebieski\KSEFClient\Requests\Sessions\Batch\Close\CloseRequest;
$response = $client->sessions()->batch()->close(
new CloseRequest(...)
)->status();use N1ebieski\KSEFClient\Requests\Sessions\Status\StatusRequest;
$response = $client->sessions()->status(
new StatusRequest(...)
)->object();use N1ebieski\KSEFClient\Requests\Invoices\Download\DownloadRequest;
$response = $client->invoices()->download(
new DownloadRequest(...)
)->body();use N1ebieski\KSEFClient\Requests\Invoices\Query\Metadata\MetadataRequest;
$response = $client->invoices()->query()->metadata(
new MetadataRequest(...)
)->object();use N1ebieski\KSEFClient\Requests\Invoices\Exports\Init\InitRequest;
$response = $client->invoices()->exports()->init(
new InitRequest(...)
)->object();use N1ebieski\KSEFClient\Requests\Invoices\Exports\Status\StatusRequest;
$response = $client->invoices()->exports()->status(
new StatusRequest(...)
)->object();$response = $client->certificates()->limits()->object();$response = $client->certificates()->enrollments()->data()->object();use N1ebieski\KSEFClient\Requests\Certificates\Enrollments\Send\SendRequest;
$response = $client->certificates()->enrollments()->send(
new SendRequest(...)
)->object();use N1ebieski\KSEFClient\Requests\Certificates\Enrollments\Status\StatusRequest;
$response = $client->certificates()->enrollments()->status(
new StatusRequest(...)
)->object();use N1ebieski\KSEFClient\Requests\Certificates\Retrieve\RetrieveRequest;
$response = $client->certificates()->retrieve(
new RetrieveRequest(...)
)->object();use N1ebieski\KSEFClient\Requests\Certificates\Revoke\RevokeRequest;
$response = $client->certificates()->revoke(
new RevokeRequest(...)
)->status();use N1ebieski\KSEFClient\Requests\Certificates\Query\QueryRequest;
$response = $client->certificates()->query(
new QueryRequest(...)
)->object();https://ksef-test.mf.gov.pl/docs/v2/index.html#tag/Tokeny-KSeF/paths/~1api~1v2~1tokens/post
use N1ebieski\KSEFClient\Requests\Tokens\Create\CreateRequest;
$response = $client->tokens()->create(
new CreateRequest(...)
)->object();https://ksef-test.mf.gov.pl/docs/v2/index.html#tag/Tokeny-KSeF/paths/~1api~1v2~1tokens/get
use N1ebieski\KSEFClient\Requests\Tokens\List\ListRequest;
$response = $client->tokens()->list(
new ListRequest(...)
)->object();use N1ebieski\KSEFClient\Requests\Tokens\Status\StatusRequest;
$response = $client->tokens()->list(
new StatusRequest(...)
)->object();use N1ebieski\KSEFClient\Requests\Tokens\Revoke\RevokeRequest;
$response = $client->tokens()->revoke(
new RevokeRequest(...)
)->status();use N1ebieski\KSEFClient\Requests\Testdata\Person\Create\CreateRequest;
$response = $client->testdata()->person()->create(
new CreateRequest(...)
)->status();use N1ebieski\KSEFClient\Requests\Testdata\Person\Remove\RemoveRequest;
$response = $client->testdata()->person()->remove(
new RemoveRequest(...)
)->status();<?php
use N1ebieski\KSEFClient\Actions\ConvertCertificateToPkcs12\ConvertCertificateToPkcs12Action;
use N1ebieski\KSEFClient\Actions\ConvertCertificateToPkcs12\ConvertCertificateToPkcs12Handler;
use N1ebieski\KSEFClient\Actions\ConvertDerToPem\ConvertDerToPemAction;
use N1ebieski\KSEFClient\Actions\ConvertDerToPem\ConvertDerToPemHandler;
use N1ebieski\KSEFClient\Actions\ConvertPemToDer\ConvertPemToDerAction;
use N1ebieski\KSEFClient\Actions\ConvertPemToDer\ConvertPemToDerHandler;
use N1ebieski\KSEFClient\ClientBuilder;
use N1ebieski\KSEFClient\DTOs\DN;
use N1ebieski\KSEFClient\Factories\CSRFactory;
use N1ebieski\KSEFClient\Support\Utility;
use N1ebieski\KSEFClient\ValueObjects\Certificate;
use N1ebieski\KSEFClient\ValueObjects\Mode;
use N1ebieski\KSEFClient\ValueObjects\PrivateKeyType;
$client = (new ClientBuilder())
->withMode(Mode::Test)
->withIdentifier('NIP_NUMBER')
// To generate the KSEF certificate, you have to authorize the qualified certificate the first time
->withCertificatePath($_ENV['PATH_TO_CERTIFICATE'], $_ENV['CERTIFICATE_PASSPHRASE'])
->build();
$dataResponse = $client->certificates()->enrollments()->data()->json();
$dn = DN::from($dataResponse);
// You can choose beetween EC or RSA private key type
$csr = CSRFactory::make($dn, PrivateKeyType::EC);
$csrToDer = (new ConvertPemToDerHandler())->handle(new ConvertPemToDerAction($csr->raw));
$sendResponse = $client->certificates()->enrollments()->send([
'certificateName' => 'My first certificate',
'certificateType' => 'Authentication',
'csr' => base64_encode($csrToDer),
])->object();
$statusResponse = Utility::retry(function () use ($client, $sendResponse) {
$statusResponse = $client->certificates()->enrollments()->status([
'referenceNumber' => $sendResponse->referenceNumber
])->object();
if ($statusResponse->status->code === 200) {
return $statusResponse;
}
if ($statusResponse->status->code >= 400) {
throw new RuntimeException(
$statusResponse->status->description,
$statusResponse->status->code
);
}
});
$retrieveResponse = $client->certificates()->retrieve([
'certificateSerialNumbers' => [$statusResponse->certificateSerialNumber]
])->object();
$certificate = base64_decode($retrieveResponse->certificates[0]->certificate);
$certificateToPem = (new ConvertDerToPemHandler())->handle(
new ConvertDerToPemAction($certificate, 'CERTIFICATE')
);
$certificateToPkcs12 = (new ConvertCertificateToPkcs12Handler())->handle(
new ConvertCertificateToPkcs12Action(
certificate: new Certificate($certificateToPem, [], $csr->privateKey),
passphrase: 'password'
)
);
file_put_contents(Utility::basePath('config/certificates/ksef-certificate.p12'), $certificateToPkcs12);<?php
use Endroid\QrCode\Builder\Builder as QrCodeBuilder;
use Endroid\QrCode\Label\Font\OpenSans;
use Endroid\QrCode\RoundBlockSizeMode;
use N1ebieski\KSEFClient\Actions\ConvertEcdsaDerToRaw\ConvertEcdsaDerToRawHandler;
use N1ebieski\KSEFClient\Actions\GenerateQRCodes\GenerateQRCodesAction;
use N1ebieski\KSEFClient\Actions\GenerateQRCodes\GenerateQRCodesHandler;
use N1ebieski\KSEFClient\ClientBuilder;
use N1ebieski\KSEFClient\DTOs\QRCodes;
use N1ebieski\KSEFClient\DTOs\Requests\Sessions\Faktura;
use N1ebieski\KSEFClient\Factories\EncryptionKeyFactory;
use N1ebieski\KSEFClient\Support\Utility;
use N1ebieski\KSEFClient\Testing\Fixtures\DTOs\Requests\Sessions\FakturaSprzedazyTowaruFixture;
use N1ebieski\KSEFClient\Testing\Fixtures\Requests\Sessions\Online\Send\SendRequestFixture;
use N1ebieski\KSEFClient\ValueObjects\Mode;
$encryptionKey = EncryptionKeyFactory::makeRandom();
$client = (new ClientBuilder())
->withMode(Mode::Test)
->withIdentifier('NIP_NUMBER')
->withCertificatePath($_ENV['PATH_TO_CERTIFICATE'], $_ENV['CERTIFICATE_PASSPHRASE'])
->withEncryptionKey($encryptionKey)
->build();
$openResponse = $client->sessions()->online()->open([
'formCode' => 'FA (3)',
])->object();
$fakturaFixture = (new FakturaSprzedazyTowaruFixture())->withRandomInvoiceNumber()->withTodayDate();
$fixture = (new SendRequestFixture())->withFakturaFixture($fakturaFixture);
// For sending invoice as DTO use SendRequest or array
// For sending invoice as XML use SendXmlRequest
$sendResponse = $client->sessions()->online()->send([
...$fixture->data,
'referenceNumber' => $openResponse->referenceNumber,
])->object();
$closeResponse = $client->sessions()->online()->close([
'referenceNumber' => $openResponse->referenceNumber
]);
$statusResponse = Utility::retry(function () use ($client, $openResponse, $sendResponse) {
$statusResponse = $client->sessions()->invoices()->status([
'referenceNumber' => $openResponse->referenceNumber,
'invoiceReferenceNumber' => $sendResponse->referenceNumber
])->object();
if ($statusResponse->status->code === 200) {
return $statusResponse;
}
if ($statusResponse->status->code >= 400) {
throw new RuntimeException(
$statusResponse->status->description,
$statusResponse->status->code
);
}
});
$upo = $client->sessions()->invoices()->upo([
'referenceNumber' => $openResponse->referenceNumber,
'invoiceReferenceNumber' => $sendResponse->referenceNumber
])->body();
$faktura = Faktura::from($fakturaFixture->data);
$generateQRCodesHandler = new GenerateQRCodesHandler(
qrCodeBuilder: (new QrCodeBuilder())
->roundBlockSizeMode(RoundBlockSizeMode::Enlarge)
->labelFont(new OpenSans(size: 12)),
convertEcdsaDerToRawHandler: new ConvertEcdsaDerToRawHandler()
);
/** @var QRCodes $qrCodes */
$qrCodes = $generateQRCodesHandler->handle(GenerateQRCodesAction::from([
'nip' => $faktura->podmiot1->daneIdentyfikacyjne->nip,
'invoiceCreatedAt' => $faktura->fa->p_1->value,
'document' => $faktura->toXml(),
'ksefNumber' => $statusResponse->ksefNumber
]));
// Invoice link
file_put_contents(Utility::basePath("var/qr/code1.png"), $qrCodes->code1);<?php
use N1ebieski\KSEFClient\ClientBuilder;
use N1ebieski\KSEFClient\Factories\EncryptionKeyFactory;
use N1ebieski\KSEFClient\Support\Utility;
use N1ebieski\KSEFClient\Testing\Fixtures\DTOs\Requests\Sessions\FakturaSprzedazyTowaruFixture;
use N1ebieski\KSEFClient\ValueObjects\Mode;
$encryptionKey = EncryptionKeyFactory::makeRandom();
$client = (new ClientBuilder())
->withMode(Mode::Test)
->withIdentifier('NIP_NUMBER')
->withCertificatePath($_ENV['PATH_TO_CERTIFICATE'], $_ENV['CERTIFICATE_PASSPHRASE'])
->withEncryptionKey($encryptionKey)
->build();
$faktury = array_map(
fn () => (new FakturaSprzedazyTowaruFixture())
->withTodayDate()
->withRandomInvoiceNumber()
->data,
range(1, 100)
);
// For sending invoices as DTOs use OpenAndSendRequest or array
// For sending invoices as XMLs use OpenAndSendXmlRequest
// For sending invoices as ZIP use OpenAndSendZipRequest
$openResponse = $client->sessions()->batch()->openAndSend([
'formCode' => 'FA (3)',
'faktury' => $faktury
])->object();
$client->sessions()->batch()->close([
'referenceNumber' => $openResponse->referenceNumber
]);
$statusResponse = Utility::retry(function () use ($client, $openResponse) {
$statusResponse = $client->sessions()->status([
'referenceNumber' => $openResponse->referenceNumber,
])->object();
if ($statusResponse->status->code === 200) {
return $statusResponse;
}
if ($statusResponse->status->code >= 400) {
throw new RuntimeException(
$statusResponse->status->description,
$statusResponse->status->code
);
}
});
$upo = file_get_contents($statusResponse->upo->pages[0]->downloadUrl);<?php
use Endroid\QrCode\Builder\Builder as QrCodeBuilder;
use Endroid\QrCode\Label\Font\OpenSans;
use Endroid\QrCode\RoundBlockSizeMode;
use N1ebieski\KSEFClient\Actions\ConvertEcdsaDerToRaw\ConvertEcdsaDerToRawHandler;
use N1ebieski\KSEFClient\Actions\GenerateQRCodes\GenerateQRCodesAction;
use N1ebieski\KSEFClient\Actions\GenerateQRCodes\GenerateQRCodesHandler;
use N1ebieski\KSEFClient\DTOs\QRCodes;
use N1ebieski\KSEFClient\DTOs\Requests\Sessions\Faktura;
use N1ebieski\KSEFClient\Factories\CertificateFactory;
use N1ebieski\KSEFClient\Support\Utility;
use N1ebieski\KSEFClient\Testing\Fixtures\DTOs\Requests\Sessions\FakturaSprzedazyTowaruFixture;
use N1ebieski\KSEFClient\ValueObjects\CertificatePath;
$nip = 'NIP_NUMBER';
// From https://ksef-test.mf.gov.pl/docs/v2/index.html#tag/Certyfikaty/paths/~1api~1v2~1certificates~1query/post
$certificateSerialNumber = $_ENV['CERTIFICATE_SERIAL_NUMBER'];
// Remember: this certificate must be "Offline" type, not "Authentication"
$certificate = CertificateFactory::make(
CertificatePath::from($_ENV['PATH_TO_CERTIFICATE'], $_ENV['CERTIFICATE_PASSPHRASE'])
);
$fakturaFixture = (new FakturaSprzedazyTowaruFixture())->withTodayDate()->withRandomInvoiceNumber();
$faktura = Faktura::from($fakturaFixture->data);
$generateQRCodesHandler = new GenerateQRCodesHandler(
qrCodeBuilder: (new QrCodeBuilder())
->roundBlockSizeMode(RoundBlockSizeMode::Enlarge)
->labelFont(new OpenSans(size: 12)),
convertEcdsaDerToRawHandler: new ConvertEcdsaDerToRawHandler()
);
/** @var QRCodes $qrCodes */
$qrCodes = $generateQRCodesHandler->handle(GenerateQRCodesAction::from([
'nip' => $faktura->podmiot1->daneIdentyfikacyjne->nip,
'invoiceCreatedAt' => $faktura->fa->p_1->value,
'document' => $faktura->toXml(),
'certificate' => $certificate,
'certificateSerialNumber' => $certificateSerialNumber,
'contextIdentifierGroup' => [
'identifierGroup' => [
'nip' => $nip
]
]
]));
// Invoice link
file_put_contents(Utility::basePath("var/qr/code1.png"), $qrCodes->code1);
// Certificate verification link
file_put_contents(Utility::basePath("var/qr/code2.png"), $qrCodes->code2);<?php
use N1ebieski\KSEFClient\Actions\DecryptDocument\DecryptDocumentAction;
use N1ebieski\KSEFClient\Actions\DecryptDocument\DecryptDocumentHandler;
use N1ebieski\KSEFClient\ClientBuilder;
use N1ebieski\KSEFClient\Factories\EncryptionKeyFactory;
use N1ebieski\KSEFClient\Support\Utility;
use N1ebieski\KSEFClient\ValueObjects\Mode;
$encryptionKey = EncryptionKeyFactory::makeRandom();
$client = (new ClientBuilder())
->withMode(Mode::Test)
->withIdentifier($_ENV['NIP_NUMBER'])
->withCertificatePath($_ENV['PATH_TO_CERTIFICATE'], $_ENV['CERTIFICATE_PASSPHRASE'])
->withEncryptionKey($encryptionKey)
->build();
$initResponse = $client->invoices()->exports()->init([
'filters' => [
'subjectType' => 'Subject1',
'dateRange' => [
'dateType' => 'Invoicing',
'from' => new DateTimeImmutable('-1 day'),
'to' => new DateTimeImmutable()
],
]
])->object();
$statusResponse = Utility::retry(function () use ($client, $initResponse) {
$statusResponse = $client->invoices()->exports()->status([
'operationReferenceNumber' => $initResponse->operationReferenceNumber
])->object();
if ($statusResponse->status->code === 200) {
return $statusResponse;
}
if ($statusResponse->status->code >= 400) {
throw new RuntimeException(
$statusResponse->status->description,
$statusResponse->status->code
);
}
});
$decryptDocumentHandler = new DecryptDocumentHandler();
// Downloading...
foreach ($statusResponse->package->parts as $part) {
$contents = file_get_contents($part->url);
$contents = $decryptDocumentHandler->handle(new DecryptDocumentAction(
document: $contents,
encryptionKey: $encryptionKey
));
$name = rtrim($part->partName, '.aes');
file_put_contents(Utility::basePath("var/zip/{$name}"), $contents);
}The package uses unit tests via Pest.
Pest configuration is located in tests/Pest
TestCase is located in tests/AbstractTestCase
Fake request and responses fixtures for resources are located in src/Testing/Fixtures/Requests
Run all tests:
composer installvendor/bin/pest- Implementation of other endpoints
- Prepare the package for release candidate
Special thanks to:
- all the helpful people on the 4programmers.net forum
- authors of the repository grafinet/xades-tools for the Xades document signing tool
