Code Monkey home page Code Monkey logo

fiskaly-sdk-php's Introduction

fiskaly SDK for PHP

The fiskaly SDK includes an HTTP client that is needed1 for accessing the kassensichv.io API that implements a cloud-based, virtual CTSS (Certified Technical Security System) / TSE (Technische Sicherheitseinrichtung) as defined by the German KassenSichV (Kassen­sich­er­ungsver­ord­nung).

Supported Versions

  • PHP 7.1+

Features

  • Automatic authentication handling (fetch/refresh JWT and re-authenticate upon 401 errors).
  • Automatic retries on failures (server errors or network timeouts/issues).
  • Automatic JSON parsing and serialization of request and response bodies.
  • Future: [1] compliance regarding BSI CC-PP-0105-2019 which mandates a locally executed SMA component for creating signed log messages.
  • Future: Automatic offline-handling (collection and documentation according to Anwendungserlass zu § 146a AO)

Integration

Composer

The PHP SDK is available for a download via Composer.

Packagist - Package Repository.

Simply execute this command from the shell in your project directory:

$ composer require fiskaly/fiskaly-sdk-php

Or you can manually add the package to your composer.json file:

"require": {
    "fiskaly/fiskaly-sdk-php": "*"
}

then run

$ composer install 

Finally, be sure to include the autoloader in your code:

<?php
require_once('vendor/autoload.php');

Service

Additionally, to the SDK, you'll also need the fiskaly service. Follow these steps to integrate it into your project:

  1. Go to https://developer.fiskaly.com/downloads#service
  2. Download the appropriate service build for your platform
  3. Start the service

Usage

Demo

<?php
require __DIR__ . '\\vendor\\autoload.php';
use FiskalyClient\FiskalyClient;

/** initialize the fiskaly API client class using credentials */
try {
    $client = FiskalyClient::createUsingCredentials('http://localhost:8080/invoke', $_ENV["FISKALY_API_KEY"], $_ENV["FISKALY_API_SECRET"], 'https://kassensichv.io/api/v1');
} catch (Exception $e) {
    exit($e);
}
/** get version of client and SMAERS */
try {
    $version = $client->getVersion();
    echo "Version: ", $version, "\n\n";
} catch (Exception $e) {
    exit($e);
}

Another way to create FiskalyClient object is using context string. You can get it via getContext method and save it in memory via $_SESSION variable or persistent in cache or database.

<?php
/** initialize the fiskaly API client class using context */
try {
    $client = FiskalyClient::createUsingContext('http://localhost:8080/invoke', $_SESSION["FISKALY_CONTEXT"]);
} catch (Exception $e) {
    exit($e);
}

Client Configuration

The SDK is built on the fiskaly Client which can be configured through the SDK.

A reason why you would do this, is to enable the debug mode.

Enabling the debug mode

The following code snippet demonstrates how to enable the debug mode in the client.

<?php
/** configure client */
try {
    $config_params = array(
        'debug_level' => 4,
        'debug_file' =>  __DIR__ . '../../fiskaly.log',
        'client_timeout' =>  5000,
        'smaers_timeout' =>  2000,
    );
    $config = $client->configure($config_params);
    echo "Configuration: ", $config, "\n\n";
} catch (Exception $e) {
    exit($e);
}

Related

fiskaly-sdk-php's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fiskaly-sdk-php's Issues

Fiskaly Service respons with Error 401 & code "Invalid credentials"

We regularely recive errors of our devices, with the following message:

[ERROR] 2021/08/13 08:44:08 auth.go:105: incorrect status code 401
[ERROR] 2021/08/13 08:44:08 auth.go:106: response body: {"status_code":401,"error":"Method Not Allowed","message":"Invalid credentials"}
[ERROR] 2021/08/13 08:44:08 request.go:227: authentication error: HTTP error: {{"body":"{"status_code":401,"error":"Method Not Allowed","message":"Invalid credentials"}","headers":{"access-control-allow-origin":[""],"access-control-expose-headers":["X-Request-ID"],"content-length":["80"],"content-type":["application/json; charset=utf-8"],"date":["Fri, 13 Aug 2021 08:44:08 GMT"],"response-time":["0.013"],"strict-transport-security":["max-age=15724800; includeSubDomains"],"vary":["Origin"],"x-request-id":["***"],"x-response-time":["0.013"]},"status":401}}
[ERROR] 2021/08/13 08:44:08 request.go:338: building http request error: HTTP error: {{"body":"{"status_code":401,"error":"Method Not Allowed","message":"Invalid credentials"}","headers":{"access-control-allow-origin":[""],"access-control-expose-headers":["X-Request-ID"],"content-length":["80"],"content-type":["application/json; charset=utf-8"],"date":["Fri, 13 Aug 2021 08:44:08 GMT"],"response-time":["0.013"],"strict-transport-security":["max-age=15724800; includeSubDomains"],"vary":["Origin"],"x-request-id":["***"],"x-response-time":["0.013"]},"status":401}}
[ERROR] 2021/08/13 08:44:08 auth.go:105: incorrect status code 401
[ERROR] 2021/08/13 08:44:08 auth.go:106: response body: {"status_code":401,"error":"Method Not Allowed","message":"Invalid credentials"}
[ERROR] 2021/08/13 08:44:08 request.go:227: authentication error: HTTP error: {{"body":"{"status_code":401,"error":"Method Not Allowed","message":"Invalid credentials"}","headers":{"access-control-allow-origin":[""],"access-control-expose-headers":["X-Request-ID"],"content-length":["80"],"content-type":["application/json; charset=utf-8"],"date":["Fri, 13 Aug 2021 08:44:08 GMT"],"response-time":["0.017"],"strict-transport-security":["max-age=15724800; includeSubDomains"],"vary":["Origin"],"x-request-id":["***"],"x-response-time":["0.017"]},"status":401}}
[ERROR] 2021/08/13 08:44:08 request.go:338: building http request error: HTTP error: {{"body":"{"status_code":401,"error":"Method Not Allowed","message":"Invalid credentials"}","headers":{"access-control-allow-origin":[""],"access-control-expose-headers":["X-Request-ID"],"content-length":["80"],"content-type":["application/json; charset=utf-8"],"date":["Fri, 13 Aug 2021 08:44:08 GMT"],"response-time":["0.017"],"strict-transport-security":["max-age=15724800; includeSubDomains"],"vary":["Origin"],"x-request-id":["***"],"x-response-time":["0.017"]},"status":401}}
[ERROR] 2021/08/13 08:44:08 request.go:272: failed to do http request, error HTTP error: {{"body":"{"status_code":401,"error":"Method Not Allowed","message":"Invalid credentials"}","headers":{"access-control-allow-origin":[""],"access-control-expose-headers":["X-Request-ID"],"content-length":["80"],"content-type":["application/json; charset=utf-8"],"date":["Fri, 13 Aug 2021 08:44:08 GMT"],"response-time":["0.017"],"strict-transport-security":["max-age=15724800; includeSubDomains"],"vary":["Origin"],"x-request-id":["***"],"x-response-time":["0.017"]},"status":401}}
[ERROR] 2021/08/13 08:44:08 request.go:159: request error: HTTP error: {{"body":"{"status_code":401,"error":"Method Not Allowed","message":"Invalid credentials"}","headers":{"access-control-allow-origin":[""],"access-control-expose-headers":["X-Request-ID"],"content-length":["80"],"content-type":["application/json; charset=utf-8"],"date":["Fri, 13 Aug 2021 08:44:08 GMT"],"response-time":["0.017"],"strict-transport-security":["max-age=15724800; includeSubDomains"],"vary":["Origin"],"x-request-id":["***"],"x-response-time":["0.017"]},"status":401}}

Even though, after a few retries, the data will be transmittet, without any intervention. It just spams our logging.

Fiskaly Service respons with Error 500 & code "SlowDown"

We have got the following Error on a few of our devices, two days ago:

[ERROR] 2021/08/11 17:11:36 request.go:159: request error: HTTP error: {{"body":"{"status_code":500,"error":"Internal Server Error","code":"SlowDown","message":"Internal Server Error"}","headers":{"access-control-allow-origin":[""],"access-control-expose-headers":["X-Request-ID"],"content-length":["103"],"content-type":["application/json; charset=utf-8"],"date":["Wed, 11 Aug 2021 17:11:36 GMT"],"response-time":["10.136"],"strict-transport-security":["max-age=15724800; includeSubDomains"],"vary":["Origin"],"x-request-id":["***"],"x-response-time":["10.136"]},"status":500}}

Somehow it worked after a few retries.

PHP8

public static function createUsingCredentials($fiskaly_service, $api_key = '', $api_secret = '', $base_url, $email = '', $password = '', $organization_id = '', $environment = '')

Small change for PHP8.
Optional parameter at the end, or set it to =''

Path must not contain "?" when finalizing transaction

When I try to finalize a transaction this exception is throwned: "Invalid params". This is caused due to this error: "path must not contain "?"".

This is the PUT url: /tss/301fcd8f-7304-4f64-b684-63f8ccbca6a8/tx/bf411dc7-caac-40b2-bdd2-606316f09f52?latest_revision=1.

I don't remember this happened last time I checked (31 december 2020). Is this a Google Cloud issue maybe and can I solve it on my side?

0 => array:6 [
    "file" => "/var/www/html/test/vendor/fiskaly/fiskaly-sdk-php/src/FiskalyClient.php"
    "line" => 320
    "function" => "throwOnError"
    "class" => "FiskalyClient\errors\FiskalyErrorHandler"
    "type" => "::"
    "args" => array:1 [
      0 => Datto\JsonRpc\Responses\ErrorResponse {#598
        -message: "Invalid params"
        -code: -32602
        -data: "path must not contain "?""
        -id: 0
      }
    ]
  ]
1 => array:6 [
    "file" => "/var/www/html/test/Fiskaly/Client.php"
    "line" => 134
    "function" => "request"
    "class" => "FiskalyClient\FiskalyClient"
    "type" => "->"
    "args" => array:5 [
      0 => "PUT"
      1 => "/tss/301fcd8f-7304-4f64-b684-63f8ccbca6a8/tx/bf411dc7-caac-40b2-bdd2-606316f09f52?latest_revision=1"
      2 => null
      3 => null
      4 => "eyJzdGF0ZSI6IkZJTklTSEVEIiwiY2xpZW50X2lkIjoiNzUyYzkyZWItYzE5NS00OWI3LWE0MTAtNmQ5YzlkOTAzZDdhIiwic3RhbmRhcmRfdjEiOnsicmVjZWlwdCI6eyJyZWNlaXB0X3R5cGUiOiJSRUNFSVBUIiwiYW1vdW50c19wZXJfdmF0X3JhdGUiOnsidmF0X3JhdGUiOiJOT1JNQUwiLCJhbW91bnQiOiIxMi41In0sImFtb3VudHNfcGVyX3BheW1lbnRfdHlwZSI6eyJwYXltZW50X3R5cGUiOiJOT05fQ0FTSCIsImFtb3VudCI6IjEyLjUifX19fQ=="
    ]
  ]

States should be array exception

I'm trying to make responses, but if the state has to be array I can't make it work. My Code is the following:

$query = new stdClass();
$query->states = array("FINISHED")

If I now pass it to the response() method then I get the exception state should be an array.

Im passing $query in the $query parameter of the method (not converted to JSON or something like that).

Fiskaly Service respons with Error 503, "failed to fetch remote JWK"

We have seen the following issue recently:

[ERROR] 2021/08/13 08:50:03 auth.go:132: failed to parse organization_id and env from token: failed to fetch remote JWK (status = 503)
[ERROR] 2021/08/13 08:50:03 request.go:227: authentication error: failed to fetch remote JWK (status = 503)
[ERROR] 2021/08/13 08:50:03 request.go:338: building http request error: failed to fetch remote JWK (status = 503)
[ERROR] 2021/08/13 08:50:03 request.go:272: failed to do http request, error failed to fetch remote JWK (status = 503)
[ERROR] 2021/08/13 08:50:03 request.go:159: request error: failed to fetch remote JWK (status = 503)

It seemed, like the issue let the fiskaly-client crash.
At least, it was unreachable for some moments after the occurence.

Some errors don't work as expected

[PHPUnit\Framework\Exception] Undefined index: code

#1  vendor/fiskaly/fiskaly-sdk-php/src/errors/FiskalyErrorHandler.php:30
#2  vendor/fiskaly/fiskaly-sdk-php/src/FiskalyClient.php:307


    public static function throwOnError($response)
    {
        if ($response instanceof ErrorResponse) {
            if ($response->getCode() == self::$HTTP_ERROR) {
                $responseData = $response->getData();
                $errorBody = json_decode(base64_decode($responseData['response']['body']), true);
                $requestId = $responseData['response']['headers']['x-request-id'][0];

                throw new FiskalyHttpException($errorBody['message'], $errorBody['code'], $errorBody['error'], $errorBody['status_code'], $requestId);
            } elseif ($response->getCode() == self::$HTTP_TIMEOUT_ERROR) {
                throw new FiskalyHttpTimeoutException($response->getMessage());
            } else {
                throw new FiskalyClientException($response->getMessage(), $response->getCode(), $response->getData());
            }
        }
    }

Some errors don't contain the key ['code']

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.