Fakturoid PHP lib
PHP library for Fakturoid.cz. Please see API for more documentation. New account just for testing API and using separate user (created via "Nastavení > Uživatelé a oprávnění") for production usage is highly recommended.
Installation
The recommended way to install is through Composer:
composer require fakturoid/fakturoid-php
Library requires PHP 5.3.0 (or later) and ext-curl
and ext-json
extensions.
Usage
require_once '/path/to/lib/Fakturoid.php';
$f = new Fakturoid\Client('..slug..', '..user@email.cz..', '..api_key..', 'PHPlib <your@email.cz>');
// create subject
$response = $f->createSubject(array('name' => 'Firma s.r.o.', 'email' => 'aloha@pokus.cz'));
$subject = $response->getBody();
// create invoice with lines
$lines = array(array('name' => 'Big sale', 'quantity' => 1, 'unit_price' => 1000));
$response = $f->createInvoice(array('subject_id' => $subject->id, 'lines' => $lines));
$invoice = $response->getBody();
// send created invoice
$f->fireInvoice($invoice->id, 'deliver');
// to mark invoice as paid
$f->fireInvoice($invoice->id, 'pay'); // or 'pay_proforma' for paying proforma and 'pay_partial_proforma' for partial proforma
// you can also take advantage of caching (via ETag and Last-Modified headers).
$response = $f->getInvoice(123);
$status = $response->getStatusCode(); // 200
$invoice = $response->getBody(); // stdClass Object
$etag = $response->getHeader('ETag'); // 'W/"6e0d839fb2edb9eadcd9ecda2d227c96"'
$lastModified = $response->getHeader('Last-Modified'); // "Wed, 28 Mar 2018 03:11:14 GMT"
$response = $f->getInvoice(123, array('If-None-Match' => $etag, 'If-Modified-Since' => $lastModified));
$status = $response->getStatusCode(); // 304 Not Modified
$invoice = $response->getBody(); // null
Downloading an invoice PDF
$invoiceId = 123;
$response = $f->getInvoicePdf($invoiceId);
$data = $response->getBody();
file_put_contents("{$invoiceId}.pdf", $data);
If you call $f->getInvoicePdf()
right after creating an invoice, you'll get
a status code 204
(No Content
) with empty body, this means the invoice PDF
hasn't yet been generated and you should try again a second or two later.
More info in API docs.
$invoiceId = 123;
// This is just an example, you may want to do this in a background job and be more defensive.
while (true) {
$response = $f->getInvoicePdf($invoiceId);
if ($response->getStatusCode() == 200) {
$data = $response->getBody();
file_put_contents("{$invoiceId}.pdf", $data);
break;
}
sleep(1);
}
custom_id
Using You can use custom_id
attribute to store your application record ID into our record.
Invoices and subjects can be filtered to find a particular record:
$response = $f->getSubjects(array('custom_id' => '10'));
$subjects = $response->getBody();
$subject = null;
if (count($subjects) > 0) {
$subject = $subjects[0];
}
As for subjects, Fakturoid won't let you create two records with the same custom_id
so you don't have to worry about multiple results.
Also note that the field always returns a string.
InventoryItem resource
To get all inventory items:
$f->getInventoryItems();
To filter inventory items by certain SKU code or article number:
$f->getInventoryItems(array('sku' => 'SKU1234'));
$f->getInventoryItems(array('article_number' => 'IAN321'));
To search inventory items (searches in name
, article_number
and sku
):
$f->searchInventoryItems(array('query' => 'Item name'));
To get all archived inventory items:
$f->getArchivedInventoryItems();
To get a single inventory item:
$f->getInventoryItem($inventoryItemId);
To create an inventory item:
$data = array(
'name' => 'Item name',
'sku' => 'SKU12345',
'track_quantity' => true,
'quantity' => 100,
'native_purchase_price' => 500,
'native_retail_price' => 1000
);
$f->createInventoryItem($data);
To update an inventory item:
$f->updateInventoryItem($inventoryItemId, array('name' => 'Another name'));
To archive an inventory item:
$f->archiveInventoryItem($inventoryItemId);
To unarchive an inventory item:
$f->unarchiveInventoryItem($inventoryItemId);
To delete an inventory item:
$f->deleteInventoryItem($inventoryItemId);
InventoryMove resource
To get get all inventory moves across all inventory items:
$f->getInventoryMoves();
To get inventory moves for a single inventory item:
$f->getInventoryMoves(array('inventory_item_id' => $inventoryItemId));
To get a single inventory move:
$f->getInventoryMove($inventoryItemId, $inventoryMoveId);
To create a stock-in inventory move:
$f->createInventoryMove(
$inventoryItemId,
array(
'direction' => 'in',
'moved_on' => '2023-01-12',
'quantity_change' => 5,
'purchase_price' => '249.99',
'purchase_currency' => 'CZK',
'private_note' => 'Bought with discount'
)
)
To create a stock-out inventory move:
$f->createInventoryMove(
$inventoryItemId,
array(
'direction' => 'out',
'moved_on' => '2023-01-12',
'quantity_change' => '1.5',
'retail_price' => 50,
'retail_currency' => 'EUR',
'native_retail_price' => '1250'
)
);
To update an inventory move:
$f->updateInventoryMove($inventoryItemId, $inventoryMoveId, array('moved_on' => '2023-01-11'));
To delete an inventory move:
$f->deleteInventoryMove($inventoryItemId, $inventoryMoveId);
Handling errors
Library raises Fakturoid\Exception
if server returns code 4xx
or 5xx
. You can get response code and response body by calling getCode()
or getMessage()
.
try {
$subject = $f->createSubject(array('name' => '', 'email' => 'aloha@pokus.cz'));
} catch (Fakturoid\Exception $e) {
$e->getCode(); // 422
$e->getMessage(); // '{"errors":{"name":["je povinná položka","je příliš krátký/á/é (min. 2 znaků)"]}}'
}
Common problems
- Ensure you have certificates for curl present - either globaly in
php.ini
or callcurl_setopt($ch, CURLOPT_CAINFO, "/path/to/cacert.pem")
. - In case of problem please contact our invoicing robot on podpora@fakturoid.cz.
Development
- To run tests, PHPUnit requires
ext-dom
extension (typically aphp-xml
package on Debian) andext-mbstring
extension (php-mbstring
package). - If you wish to generate code coverage (and have more intelligent stack traces), you will need Xdebug
(
php-xdebug
package), it will hook itself into PHPUnit automatically.
macOS
$ brew install php
$ brew install composer
$ arch -arm64 pecl install xdebug # For Apple M1 chips
# Reload terminal
$ composer install
Debian
$ sudo aptitude install php php-curl php-xml php-mbstring php-xdebug composer
$ composer install
Testing
Both commands do the same but the second version is a bit faster.
$ composer test
$ vendor/bin/phpunit
$ XDEBUG_MODE=coverage composer test # Generates coverage
$ XDEBUG_MODE=coverage vendor/bin/phpunit
Code-Style Check
Both commands do the same but the second version seems to have a more intelliget output.
$ composer lint
$ vendor/bin/phpcs --standard=PSR2 lib