2024-07-15 06:27:12 +02:00
|
|
|
<?php
|
|
|
|
/**
|
|
|
|
* Invoice Ninja (https://invoiceninja.com).
|
|
|
|
*
|
|
|
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
|
|
|
*
|
|
|
|
* @copyright Copyright (c) 2024. Invoice Ninja LLC (https://invoiceninja.com)
|
|
|
|
*
|
|
|
|
* @license https://www.elastic.co/licensing/elastic-license
|
|
|
|
*/
|
|
|
|
|
2024-07-16 08:49:18 +02:00
|
|
|
namespace App\Services\EDocument\Gateway\Storecove;
|
2024-07-15 06:27:12 +02:00
|
|
|
|
2024-07-16 04:47:42 +02:00
|
|
|
use App\Models\Company;
|
2024-07-15 06:27:12 +02:00
|
|
|
use Illuminate\Support\Facades\Http;
|
2024-08-27 06:47:18 +02:00
|
|
|
use GuzzleHttp\Exception\ClientException;
|
|
|
|
use GuzzleHttp\Exception\ServerException;
|
|
|
|
use Illuminate\Http\Client\RequestException;
|
2024-07-15 06:27:12 +02:00
|
|
|
|
|
|
|
enum HttpVerb: string
|
|
|
|
{
|
|
|
|
case POST = 'post';
|
|
|
|
case PUT = 'put';
|
|
|
|
case GET = 'get';
|
|
|
|
case PATCH = 'patch';
|
|
|
|
case DELETE = 'delete';
|
|
|
|
}
|
|
|
|
|
2024-08-22 08:45:06 +02:00
|
|
|
class Storecove
|
2024-08-27 06:47:18 +02:00
|
|
|
{
|
|
|
|
/** @var mixed $base_url */
|
2024-07-16 08:49:18 +02:00
|
|
|
private string $base_url = 'https://api.storecove.com/api/v2/';
|
2024-08-27 06:47:18 +02:00
|
|
|
|
|
|
|
/** @var mixed $peppol_discovery */
|
2024-07-15 06:27:12 +02:00
|
|
|
private array $peppol_discovery = [
|
|
|
|
"documentTypes" => ["invoice"],
|
|
|
|
"network" => "peppol",
|
|
|
|
"metaScheme" => "iso6523-actorid-upis",
|
|
|
|
"scheme" => "de:lwid",
|
2024-07-16 23:31:56 +02:00
|
|
|
"identifier" => "DE:VAT"
|
2024-07-15 06:27:12 +02:00
|
|
|
];
|
2024-08-27 06:47:18 +02:00
|
|
|
|
|
|
|
/** @var mixed $dbn_discovery */
|
2024-07-15 06:27:12 +02:00
|
|
|
private array $dbn_discovery = [
|
|
|
|
"documentTypes" => ["invoice"],
|
|
|
|
"network" => "dbnalliance",
|
|
|
|
"metaScheme" => "iso6523-actorid-upis",
|
|
|
|
"scheme" => "gln",
|
|
|
|
"identifier" => "1200109963131"
|
|
|
|
];
|
|
|
|
|
2024-08-28 02:48:08 +02:00
|
|
|
public StorecoveRouter $router;
|
|
|
|
|
2024-08-22 08:45:06 +02:00
|
|
|
public function __construct()
|
|
|
|
{
|
2024-08-28 02:48:08 +02:00
|
|
|
$this->router = new StorecoveRouter();
|
2024-08-22 08:45:06 +02:00
|
|
|
}
|
2024-08-27 06:47:18 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Discovery
|
|
|
|
*
|
|
|
|
* @param string $identifier
|
|
|
|
* @param string $scheme
|
|
|
|
* @param string $network
|
|
|
|
* @return bool
|
|
|
|
*/
|
|
|
|
public function discovery(string $identifier, string $scheme, string $network = 'peppol'): bool
|
2024-07-15 06:27:12 +02:00
|
|
|
{
|
|
|
|
$network_data = [];
|
|
|
|
|
|
|
|
match ($network) {
|
|
|
|
'peppol' => $network_data = array_merge($this->peppol_discovery, ['scheme' => $scheme, 'identifier' => $identifier]),
|
|
|
|
'dbn' => $network_data = array_merge($this->dbn_discovery, ['scheme' => $scheme, 'identifier' => $identifier]),
|
|
|
|
default => $network_data = array_merge($this->peppol_discovery, ['scheme' => $scheme, 'identifier' => $identifier]),
|
|
|
|
};
|
|
|
|
|
2024-07-16 04:47:42 +02:00
|
|
|
$uri = "api/v2/discovery/receives";
|
2024-07-15 06:27:12 +02:00
|
|
|
|
|
|
|
$r = $this->httpClient($uri, (HttpVerb::POST)->value, $network_data, $this->getHeaders());
|
|
|
|
|
|
|
|
return ($r->successful() && $r->json()['code'] == 'OK') ? true : false;
|
2024-08-22 08:45:06 +02:00
|
|
|
|
2024-07-15 06:27:12 +02:00
|
|
|
}
|
2024-08-27 06:47:18 +02:00
|
|
|
|
2024-07-15 09:09:58 +02:00
|
|
|
/**
|
2024-08-27 06:47:18 +02:00
|
|
|
* Unused as yet
|
2024-07-15 09:09:58 +02:00
|
|
|
*
|
2024-08-27 06:47:18 +02:00
|
|
|
* @param mixed $document
|
|
|
|
* @return void
|
2024-07-15 09:09:58 +02:00
|
|
|
*/
|
2024-08-01 08:32:35 +02:00
|
|
|
public function sendJsonDocument($document)
|
|
|
|
{
|
|
|
|
|
|
|
|
$payload = [
|
2024-08-27 06:47:18 +02:00
|
|
|
// "legalEntityId" => 290868,
|
2024-08-01 08:32:35 +02:00
|
|
|
"idempotencyGuid" => \Illuminate\Support\Str::uuid(),
|
|
|
|
"routing" => [
|
|
|
|
"eIdentifiers" => [],
|
|
|
|
"emails" => ["david@invoiceninja.com"]
|
|
|
|
],
|
2024-08-22 08:45:06 +02:00
|
|
|
"document" => [
|
2024-08-01 08:32:35 +02:00
|
|
|
"documentType" => "invoice",
|
|
|
|
"invoice" => $document,
|
|
|
|
],
|
|
|
|
];
|
2024-08-22 08:45:06 +02:00
|
|
|
|
2024-08-01 08:32:35 +02:00
|
|
|
$uri = "document_submissions";
|
|
|
|
|
|
|
|
$r = $this->httpClient($uri, (HttpVerb::POST)->value, $payload, $this->getHeaders());
|
|
|
|
|
|
|
|
if($r->successful()) {
|
|
|
|
return $r->json()['guid'];
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
2024-08-27 06:47:18 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Send Document via StoreCove
|
|
|
|
*
|
|
|
|
* @param string $document
|
|
|
|
* @param int $routing_id
|
|
|
|
* @param array $override_payload
|
|
|
|
*
|
|
|
|
* @return string|null
|
|
|
|
*/
|
|
|
|
public function sendDocument(string $document, int $routing_id, array $override_payload = []): ?string
|
2024-07-15 09:09:58 +02:00
|
|
|
{
|
2024-07-16 00:31:56 +02:00
|
|
|
|
|
|
|
$payload = [
|
2024-08-07 04:12:16 +02:00
|
|
|
"legalEntityId" => $routing_id,
|
2024-08-22 08:45:06 +02:00
|
|
|
"idempotencyGuid" => \Illuminate\Support\Str::uuid(),
|
2024-07-18 00:53:19 +02:00
|
|
|
"routing" => [
|
2024-08-08 04:32:31 +02:00
|
|
|
"eIdentifiers" => [],
|
2024-07-18 00:53:19 +02:00
|
|
|
"emails" => ["david@invoiceninja.com"]
|
|
|
|
],
|
2024-08-22 08:45:06 +02:00
|
|
|
"document" => [
|
|
|
|
|
2024-07-16 08:49:18 +02:00
|
|
|
],
|
2024-07-16 00:31:56 +02:00
|
|
|
];
|
|
|
|
|
2024-08-08 04:32:31 +02:00
|
|
|
$payload = array_merge($payload, $override_payload);
|
|
|
|
|
2024-08-08 09:48:24 +02:00
|
|
|
$payload['document']['documentType'] = 'invoice';
|
|
|
|
$payload['document']["rawDocumentData"] = [
|
2024-08-22 08:45:06 +02:00
|
|
|
"document" => base64_encode($document),
|
2024-08-08 09:48:24 +02:00
|
|
|
"parse" => true,
|
2024-08-22 08:45:06 +02:00
|
|
|
"parseStrategy" => "ubl",
|
2024-08-08 09:48:24 +02:00
|
|
|
];
|
|
|
|
|
2024-07-16 08:49:18 +02:00
|
|
|
$uri = "document_submissions";
|
2024-08-22 08:45:06 +02:00
|
|
|
|
2024-07-16 00:31:56 +02:00
|
|
|
$r = $this->httpClient($uri, (HttpVerb::POST)->value, $payload, $this->getHeaders());
|
2024-07-15 09:09:58 +02:00
|
|
|
|
2024-07-16 08:49:18 +02:00
|
|
|
nlog($r->body());
|
2024-08-27 06:47:18 +02:00
|
|
|
// nlog($r->json());
|
2024-07-16 08:49:18 +02:00
|
|
|
|
2024-08-22 08:45:06 +02:00
|
|
|
if($r->successful()) {
|
2024-07-15 09:09:58 +02:00
|
|
|
return $r->json()['guid'];
|
2024-08-22 08:45:06 +02:00
|
|
|
}
|
2024-07-15 09:09:58 +02:00
|
|
|
|
2024-08-27 06:47:18 +02:00
|
|
|
return null;
|
2024-07-15 09:09:58 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2024-08-27 06:47:18 +02:00
|
|
|
/**
|
|
|
|
* Get Sending Evidence
|
|
|
|
*
|
|
|
|
* @param string $guid
|
2024-08-28 00:47:28 +02:00
|
|
|
* @return mixed
|
2024-08-27 06:47:18 +02:00
|
|
|
*/
|
2024-07-16 00:31:56 +02:00
|
|
|
public function getSendingEvidence(string $guid)
|
2024-07-15 09:09:58 +02:00
|
|
|
{
|
2024-07-16 08:49:18 +02:00
|
|
|
$uri = "document_submissions/{$guid}";
|
2024-08-27 06:47:18 +02:00
|
|
|
|
2024-07-15 09:09:58 +02:00
|
|
|
$r = $this->httpClient($uri, (HttpVerb::GET)->value, [], $this->getHeaders());
|
|
|
|
|
2024-08-27 06:47:18 +02:00
|
|
|
if($r->successful())
|
|
|
|
return $r->json();
|
2024-07-15 09:09:58 +02:00
|
|
|
|
2024-08-28 00:47:28 +02:00
|
|
|
return $r;
|
2024-08-27 06:47:18 +02:00
|
|
|
}
|
2024-07-16 04:47:42 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* CreateLegalEntity
|
2024-08-22 08:45:06 +02:00
|
|
|
*
|
2024-08-27 06:47:18 +02:00
|
|
|
* Creates a base entity.
|
|
|
|
*
|
|
|
|
* Following creation, you will also need to create a Peppol Identifier
|
|
|
|
*
|
2024-07-16 04:47:42 +02:00
|
|
|
* @url https://www.storecove.com/docs/#_openapi_legalentitycreate
|
2024-08-27 06:47:18 +02:00
|
|
|
*
|
2024-07-16 04:47:42 +02:00
|
|
|
* @return mixed
|
|
|
|
*/
|
2024-08-28 02:48:08 +02:00
|
|
|
public function createLegalEntity(array $data, ?Company $company = null)
|
2024-07-16 04:47:42 +02:00
|
|
|
{
|
|
|
|
$uri = 'legal_entities';
|
|
|
|
|
2024-08-28 02:48:08 +02:00
|
|
|
if($company){
|
|
|
|
|
|
|
|
$data = array_merge([
|
|
|
|
'city' => $company->settings->city,
|
|
|
|
'country' => $company->country()->iso_3166_2,
|
|
|
|
'county' => $company->settings->state,
|
|
|
|
'line1' => $company->settings->address1,
|
|
|
|
'line2' => $company->settings->address2,
|
|
|
|
'party_name' => $company->settings->name,
|
|
|
|
'tax_registered' => (bool)strlen($company->settings->vat_number ?? '') > 2,
|
|
|
|
'tenant_id' => $company->company_key,
|
|
|
|
'zip' => $company->settings->postal_code,
|
|
|
|
], $data);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2024-07-16 04:47:42 +02:00
|
|
|
$company_defaults = [
|
|
|
|
'acts_as_receiver' => true,
|
|
|
|
'acts_as_sender' => true,
|
|
|
|
'advertisements' => ['invoice'],
|
|
|
|
];
|
|
|
|
|
|
|
|
$payload = array_merge($company_defaults, $data);
|
|
|
|
|
|
|
|
$r = $this->httpClient($uri, (HttpVerb::POST)->value, $payload);
|
|
|
|
|
2024-08-22 08:45:06 +02:00
|
|
|
if($r->successful()) {
|
2024-07-16 04:47:42 +02:00
|
|
|
return $r->json();
|
2024-08-22 08:45:06 +02:00
|
|
|
}
|
2024-07-16 04:47:42 +02:00
|
|
|
|
|
|
|
return $r;
|
|
|
|
|
|
|
|
}
|
2024-08-27 06:47:18 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* GetLegalEntity
|
|
|
|
*
|
|
|
|
* @param int $id
|
|
|
|
* @return mixed
|
|
|
|
*/
|
2024-07-16 08:49:18 +02:00
|
|
|
public function getLegalEntity($id)
|
|
|
|
{
|
|
|
|
|
|
|
|
$uri = "legal_entities/{$id}";
|
|
|
|
|
|
|
|
$r = $this->httpClient($uri, (HttpVerb::GET)->value, []);
|
|
|
|
|
|
|
|
if($r->successful()) {
|
|
|
|
return $r->json();
|
|
|
|
}
|
|
|
|
|
|
|
|
return $r;
|
|
|
|
|
|
|
|
}
|
2024-08-27 06:47:18 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* UpdateLegalEntity
|
|
|
|
*
|
|
|
|
* @param int $id
|
|
|
|
* @param array $data
|
|
|
|
* @return void
|
|
|
|
*/
|
|
|
|
public function updateLegalEntity(int $id, array $data)
|
2024-07-16 04:47:42 +02:00
|
|
|
{
|
|
|
|
|
|
|
|
$uri = "legal_entities/{$id}";
|
|
|
|
|
|
|
|
$r = $this->httpClient($uri, (HttpVerb::PATCH)->value, $data);
|
|
|
|
|
|
|
|
if($r->successful()) {
|
|
|
|
return $r->json();
|
|
|
|
}
|
|
|
|
|
|
|
|
return $r;
|
|
|
|
|
|
|
|
}
|
2024-08-27 06:47:18 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* AddIdentifier
|
|
|
|
*
|
|
|
|
* Add a Peppol identifier to the legal entity
|
|
|
|
*
|
|
|
|
* @param int $legal_entity_id
|
|
|
|
* @param string $identifier
|
|
|
|
* @param string $scheme
|
|
|
|
* @return mixed
|
|
|
|
*/
|
2024-07-17 07:37:54 +02:00
|
|
|
public function addIdentifier(int $legal_entity_id, string $identifier, string $scheme)
|
|
|
|
{
|
|
|
|
$uri = "legal_entities/{$legal_entity_id}/peppol_identifiers";
|
|
|
|
|
|
|
|
$data = [
|
|
|
|
"identifier" => $identifier,
|
|
|
|
"scheme" => $scheme,
|
2024-08-22 08:45:06 +02:00
|
|
|
"superscheme" => "iso6523-actorid-upis",
|
2024-07-17 07:37:54 +02:00
|
|
|
];
|
|
|
|
|
|
|
|
$r = $this->httpClient($uri, (HttpVerb::POST)->value, $data);
|
|
|
|
|
|
|
|
if($r->successful()) {
|
|
|
|
return $r->json();
|
|
|
|
}
|
|
|
|
|
|
|
|
return $r;
|
|
|
|
|
|
|
|
}
|
2024-08-27 06:47:18 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* deleteIdentifier
|
|
|
|
*
|
|
|
|
* @param int $legal_entity_id
|
|
|
|
* @return bool
|
|
|
|
*/
|
|
|
|
public function deleteIdentifier(int $legal_entity_id): bool
|
|
|
|
{
|
|
|
|
$uri = "/legal_entities/{$legal_entity_id}";
|
|
|
|
|
|
|
|
$r = $this->httpClient($uri, (HttpVerb::DELETE)->value, []);
|
|
|
|
|
|
|
|
return $r->successful();
|
|
|
|
}
|
2024-07-17 07:37:54 +02:00
|
|
|
|
2024-07-16 04:47:42 +02:00
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
2024-07-15 06:27:12 +02:00
|
|
|
private function getHeaders(array $headers = [])
|
|
|
|
{
|
|
|
|
|
|
|
|
return array_merge([
|
|
|
|
'Accept' => 'application/json',
|
|
|
|
'Content-type' => 'application/json',
|
|
|
|
], $headers);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2024-07-16 00:31:56 +02:00
|
|
|
private function httpClient(string $uri, string $verb, array $data, ?array $headers = [])
|
2024-07-15 06:27:12 +02:00
|
|
|
{
|
2024-08-22 08:45:06 +02:00
|
|
|
|
2024-08-27 06:47:18 +02:00
|
|
|
try {
|
|
|
|
$r = Http::withToken(config('ninja.storecove_api_key'))
|
|
|
|
->withHeaders($this->getHeaders($headers))
|
|
|
|
->{$verb}("{$this->base_url}{$uri}", $data)->throw();
|
|
|
|
}
|
|
|
|
catch (ClientException $e) {
|
|
|
|
// 4xx errors
|
|
|
|
nlog("Client error: " . $e->getMessage());
|
2024-08-28 02:48:08 +02:00
|
|
|
nlog("Response body: " . $e->getResponse()->getBody()->getContents());
|
2024-08-27 06:47:18 +02:00
|
|
|
} catch (ServerException $e) {
|
|
|
|
// 5xx errors
|
|
|
|
nlog("Server error: " . $e->getMessage());
|
2024-08-28 02:48:08 +02:00
|
|
|
nlog("Response body: " . $e->getResponse()->getBody()->getContents());
|
2024-08-27 06:47:18 +02:00
|
|
|
} catch (RequestException $e) {
|
|
|
|
nlog("Request error: " . $e->getMessage());
|
|
|
|
if ($e->hasResponse()) {
|
2024-08-28 02:48:08 +02:00
|
|
|
nlog("Response body: " . $e->getResponse()->getBody()->getContents());
|
2024-08-27 06:47:18 +02:00
|
|
|
}
|
|
|
|
}
|
2024-07-15 06:27:12 +02:00
|
|
|
|
|
|
|
return $r;
|
|
|
|
}
|
2024-08-22 08:45:06 +02:00
|
|
|
|
|
|
|
}
|