ZATCA Phase 2 Integration for Node.js
A comprehensive library for integrating with the ZATCA (Zakat, Tax and Customs Authority) Phase 2 e-invoicing system in Saudi Arabia.
Features
- Certificate generation and management
- XML generation compliant with ZATCA standards
- QR code generation for invoices
- Digital signing of invoices
- Integration with ZATCA APIs (compliance, reporting, clearance)
- Invoice status verification
- Credit note generation
Installation
npm install zatca-phase2
Configuration
Create a configuration file or use environment variables:
ZATCA_ORG_NAME=Your Company Name
ZATCA_TAX_NUMBER=Your VAT Registration Number
ZATCA_PRODUCTION=false
ZATCA_PIH=Your Production Integration Handler
LOG_LEVEL=info
Quick Start
const zatca = require('zatca-phase2');
// Generate CSR
async function generateCSR() {
const organization = {
name: 'Your Company Name',
city: 'Riyadh',
region: 'Riyadh Region',
email: 'your@email.com'
};
const certInfo = await zatca.generateCSR(organization);
console.log('CSR generated:', certInfo.csr);
return certInfo;
}
// Submit invoice
async function submitInvoice(certificateId) {
const invoice = {
invoiceNumber: 'INV-123',
issueDate: new Date(),
supplierName: 'Your Company',
supplierTaxNumber: '123456789012345',
customerName: 'Customer',
customerTaxNumber: '987654321098765',
totalAmount: 115.00,
vatAmount: 15.00,
items: [
{
name: 'Product',
quantity: 1,
unitPrice: 100.00,
taxRate: 15,
taxAmount: 15.00,
totalAmount: 115.00
}
]
};
const certInfo = {
certificateId: certificateId,
type: 'compliance',
token: 'your-auth-token'
};
const response = await zatca.submitInvoice(invoice, certInfo);
console.log('Invoice submitted:', response);
}
// Generate QR code
async function generateQRCode(invoice) {
const qrCode = await zatca.generateQRCode(invoice);
console.log('QR code generated:', qrCode);
return qrCode;
}
Complete Integration Flow
The typical integration flow with ZATCA consists of the following steps:
Onboarding:
- Generate CSR (Certificate Signing Request)
- Submit CSR to ZATCA compliance API
- Receive CSID via email
- Verify certificate with CSID
- Store compliance certificate
Invoice Processing:
- Create invoice data
- Generate invoice XML
- Sign XML using compliance certificate
- Submit for clearance (invoices ≥ 1000 SAR) or reporting (invoices < 1000 SAR)
- Process ZATCA response
- Generate QR code for the invoice
Post-Processing:
- Check invoice status
- Create credit notes if needed
API Documentation
Certificate Management
zatca.certificate.generateCSR(organization)
- Generate a Certificate Signing Requestzatca.certificate.storeCertificate(certificateId, certificate, type)
- Store a certificatezatca.certificate.loadCertificate(certificateId, type)
- Load a certificate
API Integration
zatca.api.requestComplianceCertificate(csrContent)
- Request compliance certificatezatca.api.verifyCertificate(requestId, csid)
- Verify certificate with CSIDzatca.api.clearInvoice(invoice, signedXml, certificate)
- Clear an invoicezatca.api.reportInvoice(invoice, signedXml, certificate)
- Report an invoicezatca.api.checkInvoiceStatus(requestId)
- Check invoice status
XML Generation
zatca.xml.generateInvoiceXml(invoice)
- Generate XML for an invoicezatca.xml.generateCreditNoteXml(creditNote, originalInvoice, reason)
- Generate XML for a credit notezatca.xml.calculateInvoiceHash(xml)
- Calculate hash for an invoice XML
Signing
zatca.signing.signInvoice(invoice, invoiceXml, certInfo)
- Sign an invoice XMLzatca.signing.calculateInvoiceHash(invoice, invoiceXml)
- Calculate hash for an invoice
QR Code
zatca.qrcode.generateQRCode(invoice)
- Generate QR code for an invoice
Invoice Processing
zatca.invoice.submitInvoice(invoice, certInfo)
- Process and submit an invoice to ZATCAzatca.invoice.checkInvoiceStatus(invoice)
- Check status of a submitted invoicezatca.invoice.createCreditNote(originalInvoice, reason, certInfo)
- Create a credit note for an invoice
Project Structure
zatca-phase2/
├── lib/ # Core library code
│ ├── api/ # API integration
│ │ ├── client.js # HTTP client implementation
│ │ ├── compliance.js # Compliance API methods
│ │ ├── reporting.js # Reporting API methods
│ │ ├── clearance.js # Clearance API methods
│ │ └── index.js # API module exports
│ ├── certificate/ # Certificate management
│ │ ├── generate.js # CSR generation
│ │ ├── store.js # Certificate storage
│ │ └── index.js # Certificate module exports
│ ├── invoice/ # Invoice processing
│ │ ├── submit.js # Invoice submission
│ │ ├── status.js # Status checking
│ │ ├── credit-note.js # Credit note generation
│ │ └── index.js # Invoice module exports
│ ├── qrcode/ # QR code generation
│ │ ├── generate.js # QR code generation
│ │ ├── tlv.js # TLV data formatting
│ │ └── index.js # QR code module exports
│ ├── signing/ # XML signing
│ │ ├── sign.js # XML signing implementation
│ │ ├── hash.js # Hash calculation
│ │ └── index.js # Signing module exports
│ ├── xml/ # XML generation
│ │ ├── invoice.js # Invoice XML generation
│ │ ├── credit-note.js # Credit note XML generation
│ │ └── index.js # XML module exports
│ ├── utils/ # Utility functions
│ │ ├── date.js # Date formatting utilities
│ │ ├── validation.js # Data validation
│ │ ├── logger.js # Logging utilities
│ │ └── index.js # Utils module exports
│ ├── errors/ # Error handling
│ │ ├── zatca-error.js # Custom error classes
│ │ └── index.js # Errors module exports
│ └── index.js # Main library entry point
├── config/ # Configuration
│ └── default.js # Default configuration
├── examples/ # Example usage scripts
│ ├── generate-certificate.js # Certificate generation example
│ ├── verify-certificate.js # Certificate verification example
│ ├── submit-invoice.js # Invoice submission example
│ ├── check-invoice-status.js # Status checking example
│ └── create-credit-note.js # Credit note example
├── test/ # Test suite
│ ├── unit/ # Unit tests
│ │ ├── api.test.js # API tests
│ │ ├── certificate.test.js # Certificate tests
│ │ └── xml.test.js # XML tests
│ └── setup.js # Test setup
├── scripts/ # Build scripts
│ └── build.js # Build script
├── LICENSE # MIT License
├── README.md # Documentation
├── package.json # Package manifest
├── .eslintrc.js # ESLint configuration
├── jsdoc.json # JSDoc configuration
└── .gitignore # Git ignore file
Error Handling
The library uses custom ZatcaError
class for error handling:
try {
await zatca.submitInvoice(invoice, certInfo);
} catch (error) {
if (error.name === 'ZatcaError') {
console.error(`Error code: ${error.code}`);
console.error(`Error message: ${error.message}`);
console.error(`Error details:`, error.details);
} else {
console.error('Unexpected error:', error);
}
}
Examples
Certificate Generation
const zatca = require('zatca-phase2');
const fs = require('fs').promises;
async function onboarding() {
try {
// Generate CSR
const certInfo = await zatca.certificate.generateCSR({
name: 'Your Company Name',
city: 'Riyadh',
region: 'Riyadh Region',
email: 'your@email.com'
});
console.log('CSR generated with ID:', certInfo.certificateId);
console.log('CSR content:', certInfo.csr);
// Request compliance certificate
const response = await zatca.api.requestComplianceCertificate(certInfo.csr);
console.log('Request ID:', response.requestID);
// Save request ID for later verification
await fs.writeFile('request-id.txt', response.requestID);
console.log('Please check your email for CSID and run the verification step');
} catch (error) {
console.error('Onboarding failed:', error);
}
}
async function verifyCertificate() {
try {
// Read saved request ID
const requestId = await fs.readFile('request-id.txt', 'utf8');
// Get CSID from user
const csid = process.argv[2];
if (!csid) {
console.error('Please provide CSID as argument');
process.exit(1);
}
// Get certificate ID
const certificateId = process.argv[3];
if (!certificateId) {
console.error('Please provide certificate ID as argument');
process.exit(1);
}
// Verify certificate
const response = await zatca.api.verifyCertificate(requestId, csid);
// Store certificate
await zatca.certificate.storeCertificate(
certificateId,
response.certificate,
'compliance'
);
console.log('Certificate verified and stored successfully!');
} catch (error) {
console.error('Verification failed:', error);
}
}
Invoice Submission
const zatca = require('zatca-phase2');
const fs = require('fs').promises;
async function submitInvoice() {
try {
// Prepare invoice data
const invoice = {
invoiceNumber: `INV-${Date.now()}`,
issueDate: new Date(),
supplierName: 'Your Company',
supplierTaxNumber: '123456789012345',
customerName: 'Customer XYZ',
customerTaxNumber: '987654321098765',
totalAmount: 1150.00,
vatAmount: 150.00,
items: [
{
name: 'Product A',
quantity: 1,
unitPrice: 1000.00,
taxRate: 15,
taxAmount: 150.00,
totalAmount: 1150.00
}
]
};
// Get certificate ID
const certificateId = process.argv[2];
if (!certificateId) {
console.error('Please provide certificate ID as argument');
process.exit(1);
}
// Certificate info
const certInfo = {
certificateId: certificateId,
type: 'compliance',
token: 'your-auth-token'
};
// Submit invoice
const response = await zatca.submitInvoice(invoice, certInfo);
console.log('Invoice submitted successfully!');
console.log('Request ID:', response.requestID);
// Generate QR code
const qrCode = await zatca.generateQRCode(invoice);
console.log('QR code generated:', qrCode.substring(0, 50) + '...');
// Save request ID for later status check
await fs.writeFile('invoice-request-id.txt', response.requestID);
} catch (error) {
console.error('Invoice submission failed:', error);
}
}
async function checkInvoiceStatus() {
try {
// Read saved request ID
const requestId = await fs.readFile('invoice-request-id.txt', 'utf8');
// Create invoice object with zatcaResponse
const invoice = {
zatcaResponse: { requestID: requestId }
};
// Check status
const statusResponse = await zatca.invoice.checkInvoiceStatus(invoice);
console.log('Invoice status:', statusResponse.status);
console.log('Full response:', statusResponse);
} catch (error) {
console.error('Status check failed:', error);
}
}
ZATCA Compliance Requirements
This library implements the technical requirements specified in the ZATCA e-invoicing Phase 2 documentation, including:
- Generation of compliant e-invoices in XML format
- Digital signing of invoices
- QR code generation for simplified invoices
- Integration with ZATCA's APIs:
- Compliance (onboarding)
- Clearance (for invoices ≥ 1000 SAR)
- Reporting (for invoices < 1000 SAR)
License
MIT