sysix / lexoffice-php-api Goto Github PK
View Code? Open in Web Editor NEWSimple API Integration for lexoffice
License: MIT License
Simple API Integration for lexoffice
License: MIT License
I tried to upgrade Symfony 5.4 to 6.0, there this package prevented the upgrade, once I removed it the upgrade could be done. On a Symfony 6.0 installation the package installation fails:
Using version ^0.14.1 for clicksports/lex-office-api
./composer.json has been updated
Running composer update clicksports/lex-office-api
Loading composer repositories with package information
Updating dependencies
Your requirements could not be resolved to an installable set of packages.
Problem 1
- Root composer.json requires clicksports/lex-office-api ^0.14.1 -> satisfiable by clicksports/lex-office-api[0.14.1].
- clicksports/lex-office-api 0.14.1 requires psr/cache ^1.0 -> found psr/cache[1.0.0, 1.0.1] but the package is fixed to 2.0.0 (lock file version) by a partial update and that version does not match. Make sure you list it as an argument for the update command.
Use the option --with-all-dependencies (-W) to allow upgrades, downgrades and removals for packages currently locked to specific versions.
You can also try re-running composer require with an explicit version constraint, e.g. "composer require clicksports/lex-office-api:*" to figure out if any version is installable, or "composer require clicksports/lex-office-api:^2.1" if you know which you need.
Installation failed, reverting ./composer.json and ./composer.lock to their original content.
I want to get a specific customer list of invoices, vouchers, and activities. Can we achieve this?
I tried to filter but not work. @Sysix
$api = $this->api->newRequest('POST', $this->resource . '/' . rawurlencode($id), [
should be
$api = $this->api->newRequest('POST', $this->resource . '/' . rawurlencode($id) . '/files', [
https://developers.lexoffice.io/docs/#vouchers-endpoint-upload-a-file-to-a-voucher
https://developers.lexoffice.io/docs/#files-endpoint
First of all a big thank you for the continuous work on the client! Nice to see the update to 1.0.
I have a general question regarding caching:
In the previous version I used a cache interface as recommended with a lifetime of 3600 seconds.
But I quickly ran into a problem: e.g. when updating a contact via the api, on following get requests I received the old data, as it was still cached. Therefore I disabled the cache, which is not ideal. How must I proceed in such a case; how can I clean the cache? Any advice?
Thanks in advance!
Hello,
I tried to install the package with the command from the readme file:
composer require clicksports/lex-office-api
The project is a Symfony 5.1.x project.
The output is the following. Is the lexoffice-php-api package compatible with Guzzlehttp 7.2.0? And if so, how to install it?
Thanks
Using version ^0.11.0 for clicksports/lex-office-api
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Restricting packages listed in "symfony/symfony" to "5.1.*"
Your requirements could not be resolved to an installable set of packages.
Problem 1
- Installation request for clicksports/lex-office-api ^0.11.0 -> satisfiable by clicksports/lex-office-api[0.11.0].
- Conclusion: remove guzzlehttp/guzzle 7.2.0
- Conclusion: don't install guzzlehttp/guzzle 7.2.0
- clicksports/lex-office-api 0.11.0 requires guzzlehttp/guzzle ^6.3 -> satisfiable by guzzlehttp/guzzle[6.3.0, 6.3.1, 6.3.2, 6.3.3, 6.4.0, 6.4.1, 6.5.0, 6.5.1, 6.5.2, 6.5.3, 6.5.4, 6.5.5].
- Can only install one of: guzzlehttp/guzzle[6.3.0, 7.2.0].
- Can only install one of: guzzlehttp/guzzle[6.3.1, 7.2.0].
- Can only install one of: guzzlehttp/guzzle[6.3.2, 7.2.0].
- Can only install one of: guzzlehttp/guzzle[6.3.3, 7.2.0].
- Can only install one of: guzzlehttp/guzzle[6.4.0, 7.2.0].
- Can only install one of: guzzlehttp/guzzle[6.4.1, 7.2.0].
- Can only install one of: guzzlehttp/guzzle[6.5.0, 7.2.0].
- Can only install one of: guzzlehttp/guzzle[6.5.1, 7.2.0].
- Can only install one of: guzzlehttp/guzzle[6.5.2, 7.2.0].
- Can only install one of: guzzlehttp/guzzle[6.5.3, 7.2.0].
- Can only install one of: guzzlehttp/guzzle[6.5.4, 7.2.0].
- Can only install one of: guzzlehttp/guzzle[6.5.5, 7.2.0].
- Installation request for guzzlehttp/guzzle (locked at 7.2.0) -> satisfiable by guzzlehttp/guzzle[7.2.0].
Installation failed, reverting ./composer.json to its original content.
Is there a way to show the full exception or just throw the original GuzzleException which contains the full body?
Missing options (optional):
in
Documentation: https://developers.lexoffice.io/docs/#voucherlist-endpoint-retrieve-and-filter-voucherlist
The reason for this issue is, that I have more than 10000 vouchers in my lexoffice account. When requesting all of them, I get
Fatal error: Uncaught GuzzleHttp\Exception\ServerException: Server error: `GET https://api.lexoffice.io/v1/voucherlist?page=100&size=100&sort=voucherNumber,DESC&voucherType=salesinvoice&voucherStatus=draft,open,paid,paidoff,voided,accepted,rejected` resulted in a `500 Internal Server Error` response:
{ "timestamp" : "2022-07-01T09:50:53.481+02:00", "status" : 500, "error" : "Internal Server Error", "path": "/v1/vouche (truncated...)
in /lexoffice-scanner/vendor/guzzlehttp/guzzle/src/Exception/RequestException.php:113
I think this could be solved by reducing the result (I just need the last month).
Code:
$client = $api->voucherlist();
$client->sortDirection = 'DESC';
$client->sortColumn = 'voucherNumber';
$client->types = [
'salesinvoice'
];
$client->statuses = [
'draft',
'open',
'paid',
'paidoff',
'voided',
'accepted',
'rejected'
];
$response = $client->getAll();
We're refactoring to v1 right now and want to evaluate the response-code. In case of any unexpected response-code (e.g. != 201), a custom exception should be thrown containing the response body for logging (or displaying the error).
The issue is, that $json = Utils::getJsonFromResponse($response);
is always null if the API's response header for content-type
does not match exactly application/json
(e.g. if it contains application/json; charset=utf-8
. This can happen if reverse proxies or API mockup services are used for testing).
Change this line to the following:
if (strpos($response->getHeaderLine('Content-Type'), 'application/json') !== false) {
// or
if (str_contains($response->getHeaderLine('Content-Type'), 'application/json')) {
Also it would be awesome if the parameter flag assoc
could be added, like Utils::getJsonFromResponse($response, true)
, to return the JSON as associative array instead of always having it as object:
public static function getJsonFromResponse(ResponseInterface $response, $assoc = false): mixed
{
$body = $response->getBody()->__toString();
if (strpos($response->getHeaderLine('Content-Type'), 'application/json') !== false) {
return self::jsonDecode($body, $assoc);
}
return null;
}
[08-Jul-2022 06:37:21 UTC] PHP Fatal error: Uncaught GuzzleHttp\Exception\ClientException: Client error: POST https://api.lexoffice.io/v1/contacts
resulted in a 400 Bad Request
response:
{"IssueList":[{"i18nKey":"missing_entity","source":"roles","type":"validation_failure"},{"i18nKey":"missing_entity","sou (truncated...)
in /home/schwimms/public_html/lex/vendor/guzzlehttp/guzzle/src/Exception/RequestException.php:113
that is the error.
The lexoffice api supports an update method for contacts. Why is it missing from the client?
For now I copied following part from the voucher client to the contact client:
/**
* @param string $id
* @param array $data
* @return ResponseInterface
* @throws CacheException
* @throws LexOfficeApiException
*/
public function update(string $id, array $data)
{
$api = $this->api->newRequest('PUT', $this->resource . '/' . $id);
$api->request = $api->request->withBody($this->createStream($data));
return $api->getResponse();
}
Works just fine, this way I can update the contacts in lexoffice.
the LICENSE file should be updated every year.
There is a nice github action to automate it:
https://github.com/FantasticFiasco/action-update-license-year
When I try to request something and the lexoffice api answers with a 4xx or 5xx status code, a GuzzleException and after that a LexOfficeApiException is thrown.
This is not exactly the kind of behaviour I expect, as I want to be able to display the error which I received. Therefore I need the response and its body.
Currently I have a workaround: I simply changed the method for sending the request in \Clicksports\LexOffice\App:getResponse
on Line 144 from
$this->client->send()
to $this->client->sendRequest()
.
But I'm still interested why it's currently handled like that?
EDIT:
I just found the closed issue #120 , where @Sysix already wrote how to access the response.
You can access the response body with $lexOfficeException->getPrevious()->getResponse()->getBody()->__toString();
So basically this issue is redundant. Maybe this information should be added to the readme?
I'm not able to create a contact with address information and I'm sure I'm doing something wrong. Maybe someone is able to provide me with additional information.
I already tried a addresses
array with billing
key but the response is always the same. Based from the documentation it should be an addresses
object so I thought it might be more suitable to use a stdClass()
object.
$roles = (new \stdClass());
$roles->customer = (new \stdClass());
$addresses = (new \stdClass());
$addresses->billing = array(
'street' => $form->data->street,
);
$data = array(
'roles' => $roles,
'person' => [
'firstName' => $form->data->name,
'lastName' => $form->data->name,
],
'countryCode' => 'DE',
'addresses' => $addresses,
'emailAddresses' => [
'private' => [
$form->data->email,
],
],
'phoneNumbers' => [
'private' => [
$form->data->phone,
],
],
);
^ {#820 ▼
+"requestId": "3316d4b1-4564-4e0c-90f3-59fbb822e2b8"
+"IssueList": array:2 [▼
0 => {#816 ▼
+"i18nKey": "missing_entity"
+"source": "addresses"
+"type": "validation_failure"
}
1 => {#827 ▼
+"i18nKey": "missing_entity"
+"source": "billing"
+"type": "validation_failure"
}
]
}
Maybe some dont want to get declined voucher's or a specific type of voucher
Not sure if this should be a feature inside this library, or if a rate-limit is more a task for the custom API-client implementation. We've implemented the rate-limit using symfony/rate-limiter
with token-bucket limiter which works amazing. Little downside is, that our API-service needs to implement the logic right before each API request (e.g. $this->api->voucher()->create($data);
). So it's a bit of repeating-code always adding the check before each API request.
Because the LexOffice API introduces the rate-limit for everyone, maybe it makes sense to have it implemented inside this library (including configuration options in case there will be different limits for different plans in the future, or to disable it entirely). We think a good place would be in Api::getResponse()
, right before $this->client->send($this->request)
?!
Any feedback appreciated.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.