JSPM

zatca-phase2

1.0.0
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 87
  • Score
    100M100P100Q82478F
  • License MIT

ZATCA Phase 2 e-invoicing integration for Node.js

Package Exports

  • zatca-phase2
  • zatca-phase2/lib/index.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (zatca-phase2) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

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:

  1. Onboarding:

    • Generate CSR (Certificate Signing Request)
    • Submit CSR to ZATCA compliance API
    • Receive CSID via email
    • Verify certificate with CSID
    • Store compliance certificate
  2. 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
  3. Post-Processing:

    • Check invoice status
    • Create credit notes if needed

API Documentation

Certificate Management

  • zatca.certificate.generateCSR(organization) - Generate a Certificate Signing Request
  • zatca.certificate.storeCertificate(certificateId, certificate, type) - Store a certificate
  • zatca.certificate.loadCertificate(certificateId, type) - Load a certificate

API Integration

  • zatca.api.requestComplianceCertificate(csrContent) - Request compliance certificate
  • zatca.api.verifyCertificate(requestId, csid) - Verify certificate with CSID
  • zatca.api.clearInvoice(invoice, signedXml, certificate) - Clear an invoice
  • zatca.api.reportInvoice(invoice, signedXml, certificate) - Report an invoice
  • zatca.api.checkInvoiceStatus(requestId) - Check invoice status

XML Generation

  • zatca.xml.generateInvoiceXml(invoice) - Generate XML for an invoice
  • zatca.xml.generateCreditNoteXml(creditNote, originalInvoice, reason) - Generate XML for a credit note
  • zatca.xml.calculateInvoiceHash(xml) - Calculate hash for an invoice XML

Signing

  • zatca.signing.signInvoice(invoice, invoiceXml, certInfo) - Sign an invoice XML
  • zatca.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 ZATCA
  • zatca.invoice.checkInvoiceStatus(invoice) - Check status of a submitted invoice
  • zatca.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:

  1. Generation of compliant e-invoices in XML format
  2. Digital signing of invoices
  3. QR code generation for simplified invoices
  4. Integration with ZATCA's APIs:
    • Compliance (onboarding)
    • Clearance (for invoices ≥ 1000 SAR)
    • Reporting (for invoices < 1000 SAR)

License

MIT