structurize / peppol-php
PHP for sending invoices over peppol using Structurize
Installs: 1
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/structurize/peppol-php
Requires
- php: >=7.0
- structurize/structurize: >=0.0.1
README
This library provides functionality to integrate Peppol services into your PHP 7.0+ applications, including CodeIgniter 3. It has been refactored to be framework-agnostic and Composer-installable.
Installation
Using Composer (Recommended)
-
Require the package: Add the following to your project's
composer.jsonfile:{ "require": { "php": ">=7.0", "structurize/structurize": ">=0.0.1", "your-vendor-name/peppol-lib": "^1.0" // Replace with your actual vendor and package name }, "autoload": { "psr-4": { "PeppolLib\\": "src/" } }, "repositories": [ { "type": "path", "url": "./peppol-lib" // Adjust this path if your Peppol library is not directly in the project root } ] }Note: The
repositoriessection is for local development if thepeppol-libfolder is within your main project. For a standalone package, you would publish it to Packagist. -
Install/Update: Run
composer installorcomposer update.
Manual Installation (Not Recommended for Pure PHP/CodeIgniter)
If you prefer not to use Composer, you would manually copy the src/ and config/ directories into your project and manage autoloading yourself. This is generally not recommended for modern PHP development.
Configuration (config/peppol.php)
After installation, you'll need a config/peppol.php file in your project's root (or a location accessible by your application). This file contains essential settings:
<?php return [ 'api_key' => 'YOUR_STRUCTURIZE_API_KEY', // Replace with your Structurize API Key 'tables' => [ 'companies' => 'companies', 'invoices' => 'invoices', 'invoice_logging' => 'peppol_invoice_logging', ], 'table-fields' => [ 'companies' => [ 'id' => 'id', 'vat_number' => 'vat_number', 'peppol_connected' => 'peppol_connected', 'peppol_scheme_id' => 'peppol_scheme_id', ], 'invoices' => [ 'id' => 'id', 'number' => 'number', 'company_id' => 'company_id', 'peppol_sent' => 'peppol_sent', 'peppol_sent_at' => 'peppol_sent_at', ], ], ];
api_key: Your API key from Structurize.tables: Customize table names if they differ in your database.table-fields: Customize field names if they differ in your database.
Database Setup
The library expects certain tables and columns to exist in your database. You can manually execute the following SQL statements to create/alter your tables. If your framework (e.g., CodeIgniter) has a migration system, adapt these SQL statements accordingly.
companies table
Adds peppol_connected and peppol_scheme_id columns to your existing companies table:
ALTER TABLE `companies` ADD `peppol_connected` TINYINT(1) NOT NULL DEFAULT '0'; ALTER TABLE `companies` ADD `peppol_scheme_id` VARCHAR(255) NULL;
invoices table
Adds peppol_sent and peppol_sent_at columns to your existing invoices table:
ALTER TABLE `invoices` ADD `peppol_sent` TINYINT(1) NOT NULL DEFAULT '0'; ALTER TABLE `invoices` ADD `peppol_sent_at` DATETIME NULL;
peppol_invoice_logging table
Creates the peppol_invoice_logging table:
CREATE TABLE `peppol_invoice_logging` ( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, `success` TINYINT(1) NOT NULL DEFAULT '0', `invoice_id` BIGINT UNSIGNED NOT NULL DEFAULT '0', `send_data` TEXT NULL, `return_data` TEXT NULL, `created_at` TIMESTAMP NULL, `updated_at` TIMESTAMP NULL, INDEX `peppol_invoice_logging_invoice_id_index` (`invoice_id`) );
Usage
Initializing the Library (Pure PHP / Framework-Agnostic)
After Composer installation, you can initialize the services and your custom database models.
// In your bootstrap file or where you need to use the services require_once __DIR__ . '/vendor/autoload.php'; // Composer autoloader use PeppolLib\Services\PeppolService; use PeppolLib\Services\StructurizeService; use PeppolLib\Models\CompanyModel; use PeppolLib\Models\InvoiceModel; use PeppolLib\Models\PeppolLoggingModel; // Load your configuration $config = require __DIR__ . '/config/peppol.php'; // --- Your Database Connection and Model Implementations --- // These are example implementations. You MUST replace them with your actual database logic. // Your models should provide methods like 'get($id)', 'update($id, $data)', 'insert($data)', 'whereNotNull($field)' and 'result()' class MyCompanyModel extends CompanyModel // Extend if you want to reuse basic structure { private $db; // Your database connection (e.g., PDO, mysqli or CodeIgniter's $this->db) public function __construct(array $config, $dbConnection) { parent::__construct($config, $dbConnection); $this->db = $dbConnection; // Initialize your database connection or CodeIgniter's DB object here } public function whereNotNull($field) { // Example: PDO implementation // $stmt = $this->db->prepare("SELECT * FROM {$this->tableName} WHERE {$field} IS NOT NULL"); // $stmt->execute(); // return (object)['result' => fn() => $stmt->fetchAll(PDO::FETCH_OBJ)]; // CodeIgniter example (assuming $this->db is CI's DB object) // return (object)['result' => fn() => $this->db->where($field . ' IS NOT NULL')->get($this->tableName)->result()]; return parent::whereNotNull($field); // For mock data } public function get($id) { return parent::get($id); /* Implement actual DB query */ } public function update($id, array $data) { return parent::update($id, $data); /* Implement actual DB update */ } public function insert(array $data) { return parent::insert($data); /* Implement actual DB insert */ } } class MyInvoiceModel extends InvoiceModel { private $db; public function __construct(array $config, $dbConnection) { parent::__construct($config, $dbConnection); $this->db = $dbConnection; } public function get($id) { return parent::get($id); /* Implement actual DB query */ } public function update($id, array $data) { return parent::update($id, $data); /* Implement actual DB update */ } } class MyPeppolLoggingModel extends PeppolLoggingModel { private $db; public function __construct(array $config, $dbConnection) { parent::__construct($config, $dbConnection); $this->db = $dbConnection; } public function insert(array $data) { return parent::insert($data); /* Implement actual DB insert */ } } // Replace with your actual database connection (e.g., new PDO(...), or CodeIgniter's $CI->db object) $myDbConnection = null; $myCompanyModel = new MyCompanyModel($config, $myDbConnection); $myInvoiceModel = new MyInvoiceModel($config, $myDbConnection); $myPeppolLoggingModel = new MyPeppolLoggingModel($config, $myDbConnection); $structurizeService = new StructurizeService($config); $peppolService = new PeppolService( $structurizeService, $config, function() use ($myCompanyModel) { return $myCompanyModel; }, function() use ($myInvoiceModel) { return $myInvoiceModel; }, function() use ($myPeppolLoggingModel) { return $myPeppolLoggingModel; } );
Usage Example: Sending an Invoice
// ... (previous initialization code for $peppolService) $invoice_data = (object)[ 'id' => 1, 'number' => 'INV-2023-001', 'date' => '2023-01-15', 'due_date' => '2023-02-15', 'total_incl' => 121.00, 'present' => (object)[ 'total_excl' => 100.00, 'total_incl' => 121.00, ], 'lines' => [ (object)['name' => 'Product A', 'description' => 'Description A', 'vat_code' => 21, 'amount' => 1, 'subtotal' => 100.00, 'vat' => 21.00], ], 'company_id' => 1, ]; $result = $peppolService->sendInvoice($invoice_data); if ($result['success']) { echo "Invoice sent successfully!\n"; } else { echo "Error sending invoice: " . ($result['message'] ?? json_encode($result['answer'])) . "\n"; }
Using the CLI Tool
After Composer installation and making the bin/sync-peppol-company executable (chmod +x bin/sync-peppol-company), you can run it from your project root:
./bin/sync-peppol-company
Important: Remember to replace the mock database interaction logic and YOUR_STRUCTURIZE_API_KEY placeholder in config/peppol.php and your custom model implementations with your actual setup.
Further Development
- Model Implementations: The provided
CompanyModel,InvoiceModel, andPeppolLoggingModelare mock implementations. You must replace their methods with actual database interaction logic tailored to your application's database abstraction layer (e.g., PDO, mysqli, or a framework's ORM/DBAL). - Error Handling and Logging: Enhance error handling and logging as required for your application. Consider integrating a dedicated logger.
- Testing: Implement unit and integration tests for the library within your application.
- Structurize Integration: Refer to the
structurize/structurizepackage documentation for more details on advanced usage of the Structurize API.