/procountor-php

Fork of procountor-php package. Some parts have been completly rewritten for compatibility with DI, PSR, PHPDoc, Laravel, PHP8 etc.

Primary LanguagePHPMIT LicenseMIT

procountor-php

First and foremost, this repository is a fork of https://github.com/Fisplay/procountor-php and not compatible with the original one (and still under active development, no stable version yet). I'm still using most of the underlying resources, but everything around them is largely rewritten.

Credits

Credit where credit is due, this project is based on other people's hard work. See the original repositroy here.

What's chamged?

  • No more hard dependencies. Loggers, HTTP clients, you name it, all injected & easily replaced.
  • Modernized test suite (uses Pest)
  • PHP8 compatibility
  • Code is documented with phpdoc instead of generic comments (still WIP)
  • PSR compatible;
    • PSR-3 logger interfaces
    • PSR-6 cache interfaces
    • PSR-7 HTTP Message interfaces
    • PSR-17 HTTP Factories
    • PSR-18 HTTP Clients
  • Laravel compatible (can be installed as a Laravel package)
    • ServiceProvider to register client
    • ServiceProvider to register resources (parital)
    • Config
    • Facades for resources (partial)
    • Helper for authorization flow (partial)
    • Jobs for create -operations

Tested working API's

  • Invoices
    • Create invoice
    • List invoices

TODO

  • Check each resource against current Procountor API
  • Export documentation to static site
  • Write facades
  • Finalize authorization flow (view?)

About Guzzle HTTP client

This library relies on PSR spec which explicitly prohibits HTTP Client library from throwing on HTTP 4XX/5XX response code ranges. GuzzleHttp by default throws their own BadResponseException on HTTP 4XX/5XX responses, so make sure to set http_errors config parameter to false before injection.

Usage

As one of the main golas was to increase flexibility & testability by leveraging DI, I higly suggest that you use this project only if you are already using DI containers. Examples below will use the Invoices resource, but the process & functionality is pretty much the same regardless of the resource.

Configuring the environment

Environment is contained on its own class, and it's up to you where you want to pull the constructor arguments (dotenv, Laravel config, anyhting goes). Example below uses Laravel's config helper.

Dependencies:

use Procountor\Procountor\Environment;
use PhpExtended\HttpMessage\UriFactory;

new Environment(
    config('procountor.client_id'),
    config('procountor.client_secret'),
    config('procountor.api_key'),
    config('procountor.base_uri'),
    config('procountor.redirect_uri'),
    new UriFactory()
);

Creating an API Client

An API Client is an abstraction over stuff that handles the serialization & deserialization, HTTP communication etc. Its an essential dependecy for each resource, so every time you want to do anything with a resource, you must create an instance of an API client fist.

Dependencies:

use Cache\Adapter\PHPArray\ArrayCachePool;
use GuzzleHttp\Client as GuzzleHttpClient;
use PhpExtended\HttpMessage\{RequestFactory, StreamFactory};
use PhpExtended\HttpMessage\UriFactory;
use Psr\Log\NullLogger;

new Client(
    new GuzzleHttpClient(),
    new RequestFactory(),
    new StreamFactory(),
    new NullLogger(),
    $environment, // example above
    new ArrayCachePool()
);

Usign API resources

Procountor's official API documentation is probably your best friend here.

Dependeicies:

  • API client configured above
  • If you want to create resources, you must implement your own adapter;
    use \Procountor\Interfaces\Write\Invoice as InvoiceInterface;
    
    class MyInvoiceAdapter implements InvoiceInterface
    {
        private $data;
    
        public function __construct($yourdata) {
            // you are free to implement this however you see fit
            $this->data = $yourdata;
        }
    
        // then create the related getters:
    
        public function getPartnerId() {
            return $this->data->partnerid;
        }
        // ...etc
    }
use Procountor\Procountor\Resources\Invoices;

$invoicesApi = new Invoices($client);

// Listing resources
$invoices = $invoicesApi->get();

// Fetching a singular resource, takes a resource ID as argument
$invoicesApi->get(1212);

// Creating a resource (see note about adapters above)
$invoicesApi->post(new MyInvoiceAdapter($someData));

Further reading: