E-Invoicing Module
The E-Invoicing module provides extensible tax authority integration for electronic invoice submission. It supports multiple gateways (ETA for Egypt, ZATCA for Saudi Arabia) with a driver pattern that allows adding future countries without modifying core code.
Architecture
Supported Gateways
| Gateway | Country | API Format | Auth | Status |
|---|---|---|---|---|
| ETA | Egypt | REST + JSON | OAuth 2.0 (JWT) | Implemented |
| ZATCA | Saudi Arabia | REST + UBL 2.1 XML | X.509 mTLS | Implemented |
Key Features
- Per-branch activation — Different branches can use different gateways
- Async submission — Queue-based with exponential backoff retries
- Transaction logging — Full audit trail of every API call
- Encrypted credentials — All secrets stored with Laravel encryption
- Zero coupling — Events guarded by
class_exists(), module removable without breaking Sales/Purchases
Database Tables
| Table | Purpose |
|---|---|
e_invoice_configs | Per company+branch gateway configuration |
e_invoice_documents | Links source docs to e-invoice lifecycle |
e_invoice_submissions | API call transaction log |
API Endpoints
All endpoints under api/einvoicing/ with auth:sanctum middleware.
Configuration (8 endpoints)
| Method | Endpoint | Description |
|---|---|---|
| GET | /config | List gateway configs |
| POST | /config | Create config |
| GET | /config/{id} | Show config |
| PUT | /config/{id} | Update config |
| DELETE | /config/{id} | Delete config |
| POST | /config/{id}/test-connection | Test API connectivity |
| POST | /config/{id}/activate | Activate gateway |
| POST | /config/{id}/deactivate | Deactivate gateway |
Documents (9 endpoints)
| Method | Endpoint | Description |
|---|---|---|
| GET | /documents | List documents (filterable) |
| GET | /documents/{id} | Show document + submissions |
| GET | /documents/{id}/qr | Get QR code (ZATCA) |
| POST | /documents/{id}/submit | Manual submit |
| POST | /documents/{id}/retry | Retry failed |
| POST | /documents/{id}/cancel | Request cancellation |
| POST | /documents/{id}/check-status | Poll status |
| POST | /documents/bulk-submit | Bulk submit |
| POST | /documents/bulk-retry | Bulk retry |
ZATCA Onboarding (4 endpoints)
| Method | Endpoint | Description |
|---|---|---|
| POST | /zatca/generate-csr | Generate CSR |
| POST | /zatca/compliance-csid | Request compliance CSID |
| POST | /zatca/compliance-check | Run compliance check |
| POST | /zatca/production-csid | Request production CSID |
Submissions (2 endpoints)
| Method | Endpoint | Description |
|---|---|---|
| GET | /submissions | List submissions (audit log) |
| GET | /submissions/{id} | Show full request/response |
Scheduled Commands
| Command | Schedule | Description |
|---|---|---|
einvoicing:retry-failed | Every 15 min | Retries failed submissions |
einvoicing:poll-status | Every 5 min | Polls ETA for document status updates |
Gateway Resolution
The system resolves the correct gateway using a priority chain:
- Branch-specific config — If a config exists for the exact
company_id + branch_id, use it - Company-wide config — If no branch config, fall back to
company_id + branch_id = null - No config — Skip e-invoicing silently
This allows multi-country setups: Egypt branches use ETA, Saudi branches use ZATCA.
Adding a New Gateway
- Add a value to
GatewayCodeenum - Create
Modules/EInvoicing/app/Gateways/NewCountry/NewCountryGateway.phpimplementingEInvoiceGateway - Add gateway-specific services in the same directory
- Register in
EInvoiceManagerconstructor - Add nullable credential columns via migration if needed