LauLamanApps / iZettleApi

iZettle Api php intergration
MIT License
12 stars 15 forks source link

Image upload / VAT bug #25

Open chatlumo opened 5 years ago

chatlumo commented 5 years ago

Hello,

How to submit a new product with this API ?

If i use: $library->getProducts()->add($product);

I do have a collection with my new product, but how to submit (post) that to iZettle ?

Thanks.

LauLaman commented 5 years ago

Hi @chatlumo,

You should be able to add a new product like this:

use GuzzleHttp\Client;
use LauLamanApps\IzettleApi\API\Product\Product;
use LauLamanApps\IzettleApi\GuzzleIzettleClient;
use LauLamanApps\IzettleApi\IzettleClientFactory;

$accessToken = '<AccessToken>'; //-- Get from cache

$iZettleClient = new GuzzleIzettleClient(new Client(), 'clientId', 'clientSecret');
$iZettleClient->setAccessToken($accessToken);

$productClient = IzettleClientFactory::getProductClient($iZettleClient);

$product = Product::new(/*..required data..*/);

$productClient->createProduct($product);
chatlumo commented 5 years ago

Hi @LauLaman,

Thank you for your reply !

I tried this:

require_once './vendor/autoload.php';
use GuzzleHttp\Client;
use LauLamanApps\IzettleApi\API\Product\Product;
use LauLamanApps\IzettleApi\GuzzleIzettleClient;
use LauLamanApps\IzettleApi\IzettleClientFactory;

$iZettleClient = new GuzzleIzettleClient(new Client(), $clientId, $clientSecret);
$accessToken = $iZettleClient->getAccessTokenFromUserLogin($login, $password);

$productClient = IzettleClientFactory::getProductClient($iZettleClient);

$category = \LauLamanApps\IzettleApi\API\Product\Category::new('Home');
$categoryCollection = new \LauLamanApps\IzettleApi\API\Product\CategoryCollection();
$categoryCollection->add($category);

$currency = new \Money\Currency('EUR');

$variant = \LauLamanApps\IzettleApi\API\Product\Variant::new('test article', 'test', 'TEST', null, 0, null, new \Money\Money(500, $currency), null, 2.1);
$variantCollection = new \LauLamanApps\IzettleApi\API\Product\VariantCollection();
$variantCollection->add($variant);
$image = new \LauLamanApps\IzettleApi\API\Image('https://mydomain.tld/images/2018.jpg');
$imageCollection = new \LauLamanApps\IzettleApi\API\ImageCollection();
$imageCollection->add($image);
$product = Product::new('test article', '', $categoryCollection, $imageCollection, $variantCollection, 'TEST');

$productClient->createProduct($product);

But i always have:

Fatal error: Uncaught GuzzleHttp\Exception\ClientException: Client error: `POST https://products.izettle.com/organizations/self/products` resulted in a `422 Unprocessable Entity` response: {"developerMessage":"The request entity has constraint violations","errorType":"CONSTRAINT_VIOLATION","violations":[{"pr (truncated...) in /vendor/guzzlehttp/guzzle/src/Exception/RequestException.php on line 121

Do you have an idea why ?

LauLaman commented 5 years ago

Hi @chatlumo

I tried your example data and got the following exception back from iZettle:

{
    "developerMessage": "VAT value=2.1 is not allowed in country=NL, allowedVats=[21, 6, 0]",
    "errorType": "VAT_NOT_ALLOWED_IN_COUNTRY",
    "violations": []
}

Can you put a try catch block around the createProduct() like so to get the error message?

try {
    $productClient->createProduct($product);
} catch (\Exception $exception) {
    echo $exception->getResponse()->getBody()->getContents();
}

~i'll improve the error reporting for this in the next version~

with version 0.9.3 you can now catch LauLamanApps\IzettleApi\Exception\UnprocessableEntityException and assess the error like:

$e->getMessage();
$e->getErrorType();
$e->getViolations();
chatlumo commented 5 years ago

Thansk, now i have this message:

{
    "developerMessage": "The` request entity has constraint violations",
    "errorType": "CONSTRAINT_VIOLATION",
    "violations": [{
        "propertyName": "vatPercentage",
        "developerMessage": "numeric value out of bounds (<3 digits>.<1 digits> expected)",
        "constraintType": "DIGIT_OUT_OF_BOUNDS",
        "value": "2.100000000000000088817841970012523233890533447265625"
    }]
}
LauLaman commented 5 years ago

OK to be sure that we send the correct data to iZettle can you please output the following information:

if you did not update to v 0.9.3 yet:

try {
    $productClient->createProduct($product);
} catch (\Exception $exception) {
    echo GuzzleHttp\Psr7\str($err->getRequest());
}

otherwise you'll need to change the GuzzleIzettleClient.php file on line 158

# LauLamanApps\IzettleApi\GuzzleIzettleClient.php:L158
try {
    return $this->guzzleClient->post($url, $options);
} catch (ClientException $exception) {
    echo GuzzleHttp\Psr7\str($exception->getRequest());
}

the output should look something like this (DON'T forget to remove sensitive data like access tokens ed.)

POST /organizations/self/products HTTP/1.1
User-Agent: GuzzleHttp/6.3.3 curl/7.54.0 PHP/7.1.19
Host: products.izettle.com
Authorization: Bearer [token]
content-type: application/json
Accept: application/json

{"uuid":"9ebf3bfc-d2a7-11e8-ba65-8c8590ab443e","categories":["9ebe85d6-d2a7-11e8-a8de-8c8590ab443e"],"name":"test article","description":"","imageLookupKeys":["https:\/\/mydomain.tld\/images\/2018.jpg"],"variants":[{"uuid":"9ebef2d2-d2a7-11e8-806a-8c8590ab443e","name":"test article","description":"test","sku":"TEST","barcode":null,"defaultQuantity":0,"unitName":null,"price":{"amount":"500","currencyId":"EUR"},"vatPercentage":2.1}],"externalReference":"TEST"}
chatlumo commented 5 years ago

Thanks,

This is the result:

POST /organizations/self/products HTTP/1.1 
User-Agent: GuzzleHttp/6.3.3 curl/7.60.0 PHP/7.1.20 
Host: products.izettle.com 
Authorization: Bearer eyJr... 
content-type: application/json 
Accept: application/json 

{"uuid":"694c3728-d2fb-11e8-8534-8d6d0d88d461","categories":["694bbdfc-d2fb-11e8-9a88-057873fc826e"],"name":"test article","description":"","imageLookupKeys":["https:\/\/mydomain.org\/2018.jpg"],"variants":[{"uuid":"694c0ee2-d2fb-11e8-b914-5b075e5d458d","name":"test article","description":"test","sku":"TEST","barcode":null,"defaultQuantity":0,"unitName":null,"price":{"amount":"500","currencyId":"EUR"},"vatPercentage":2.100000000000000088817841970012523233890533447265625}],"externalReference":"TEST"}

I don't know why my VAT which is 2.1 become 2.100000000000000088817841970012523233890533447265625.

chatlumo commented 5 years ago

However if i test with a VAT of 5.5 it's working. And in the iZettle dashboard, i can set up for each variant a VAT (for France - FR) of 0, 2.1, 5.5, 10 or 20 %.

In addition of that, how to add an online image to the product ? Because $image = new \LauLamanApps\IzettleApi\API\Image('https://mydomain.org/2018.jpg'); $imageCollection = new \LauLamanApps\IzettleApi\API\ImageCollection(); $imageCollection->add($image); doesn't work. Name of image is well saved but not image itself.

LauLaman commented 5 years ago

@chatlumo very interesting.

You're using a curl version that is slightly newer than the version i'm using the same goes for your PHP version, So that should not be it.

I am very curious on where the float changes in the process. I'm, not being able to duplicate the problem. And can't debug the french restrictions. Can you do some debugging on the float? Clearly it changes somewhere.

You directly access it by doing something like:

$variant = Variant::new('test article', 'test', 'TEST', null, 0, null, Money::Eur(500), null, 2.1);

echo $variant->getVatPercentage();

you can also play around with some casting like:

$variant = Variant::new('test article', 'test', 'TEST', null, 0, null, Money::Eur(500), null, (float)'2.1');

$variant = Variant::new('test article', 'test', 'TEST', null, 0, null, Money::Eur(500), null, floatval('2.1'));

Let me know what you'll find.

I'll take a look at the Image.

LauLaman commented 5 years ago

@chatlumo

You should be able to create images like this:

$imageClient = IzettleClientFactory::getImageClient($iZettleClient);

//use a url
$image = new ImageUrlUpload('https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png');

// or upload a file form disk
$image = new ImageFileUpload('/var/whatever/your/path/may/be/file.jpg');

// post to iZettle
$image = $imageClient->postImage($image);

however i was not able to do this and checked the iZettle documentation which is broken at this moment. I've opened a issue in the official iZettle Api documentation: https://github.com/iZettle/api-documentation/issues/51

chatlumo commented 5 years ago

Hi,

I tried all variants to put 2.1, echo is always good but the json in the request is always bad.

For the image (with url), i have Fatal error: Uncaught GuzzleHttp\Exception\ClientException: Client error: POST https://image.izettle.com/organizations//products resulted in a 404 Not Found response: {"code":404,"message":"HTTP 404 Not Found"}`

LauLaman commented 5 years ago

Floats are a b*tch in PHP. Lets change them to a string value, that should fix it.

To be changed in v 1.0