1.1.3 • Published 4 months ago

dgii-ecf v1.1.3

Weekly downloads
-
License
MIT
Repository
github
Last release
4 months ago

DGII-eCF

npm version Node.js CI

DGII-eCF (DGII) - Dirección General de Impuestos Internos de República Dominicana.

  • Este paquete contiene las herramientas necesarias para autenticar y firmar archivos eletrónicos para realizar la facturación electrónica para aplicaciones nodejs.

  • This package contains the necessary tools to authenticate and sign electronic files to perform electronic invoicing for nodejs applications.

Do not try to use on frontend application like Reactjs, only use it on the server side due to sensitive informations

>> Video Tutorial <<

Installation

Install dgii-ecf with npm

  npm install dgii-ecf

Usage/Examples

This package expose three main clases ECF, P12Reader, Signature

Requirements

You need a valid certificate if you don't have one you need to request a new one your business or client business DigiFirma

Step One

Use P12Reader to read the certificate .p12

import { P12Reader } from 'dgii-ecf';

const secret = 'certificate_passphrase'

const reader = new P12Reader(secret);
    const certs = reader.getKeyFromFile(
      path.resolve(__dirname, '../../test_cert/[your_identity.p12]')
    );

certs will contain a object P12ReaderData with

{ cert: string, key: string }

Step two

Use the cert object to initialize the ECF object, is important to pass this object, with the certificate we will be able to authenticate with the DGII, sign documents and interact with the api.

import ECF, { P12Reader } from 'dgii-ecf'

const auth = new ECF(certs);
const tokenData = await auth.authenticate();

The method authenticate will perform two API requests:

  • Get the initial XML called SEED
  • After getting the seed, the method will sign the document using Signature and will make another API request to get the access token
  • buyerHost?: string Optional parameter, allow to use the same method to perform authentication againt a buyer authorized to receive eCF const tokenData = await auth authenticate('https://ecf.dgii.gov.do/Testecf/emisorreceptor');

auth.authenticate return an optional object with the token and expiration, however, internally the token gets set into the header of every following request, Authorization: access token.

Target diferent environment

By default the ECF class init target the development environment, currently the class support the three environment supported by DGII:

  • TesteCF Test environment
  • CerteCF Certification environment
  • eCF Production
import ECF, { ENVIRONMENT } from 'dgii-ecf'

const auth = new ECF(certs, ENVIRONMENT.PROD); //PRODUCTION ENV

Transformers

Convert the JSON to a XML

    const transformer = new Transformer();
    const xml = transformer.json2xml(anyJsonDocument);

Options

Signature this class help to sign XML documents.

import { Signature } from 'dgii-ecf'

//Read the certificate
const reader = new P12Reader(secret);
const certs = reader.getKeyFromFile(
    path.resolve(__dirname, '../../test_cert/4303328_identity.p12')
);

if (!certs.key || !certs.cert) {
  return;
}

//Get the XML file to add the signature

const seedXml = fs.readFileSync(
    path.resolve(__dirname, 'sample/seed.xml'),
    'utf-8'
);

//Sign the document
const signature = new Signature(certs.key, certs.cert);
const signedXml = signature.signXml(seedXml, 'SemillaModel');

Send Electronic Document eFC

Send credit invoice using the api method

  //Authentication
  const ecf = new ECF(certs, ENVIRONMENT.DEV); // select the environment TEST, CERT, PROD
  const auth = await ecf.authenticate();

  //Sign invoice
  const signature = new Signature(certs.key, certs.cert);
  // Optional If the input is JSON transform it to XML
  const transformer = new Transformer();
  const xml = transformer.json2xml(JsonECF31Invoice);
  //------------------------------------------------

  //Create the name convention RNCEmisor + eCF.xml
  const fileName = `${rnc}${noEcf}.xml`;
  //Add the signature to the XML targetting the main wrapper in this case `ECF` (credito fiscal) it can be | ECF | ARECF | ACECF | ANECF | RFCE 
  const signedXml = signature.signXml(xml, 'ECF');
  //SEND the document to the DGII
  const response = await ecf.sendElectronicDocument(signedXml, fileName); //Optional third parameter is buyerHost?:string to send the invoice to the buyer 

API Methods

Track ID

Get response by track ID

const ecf = new ECF(certs, ENVIRONMENT.DEV);
const response = await ecf.statusTrackId(trackId);
{
    "trackId": "d2b6e27c-3908-46f3-afaa-2207b9501b4b",
    "codigo": "1",
    "estado": "Aceptado",
    "rnc": "130862346",
    "encf": "E310005000201",
    "secuenciaUtilizada": true,
    "fechaRecepcion": "8/15/2023 6:06:57 AM",
    "mensajes": [
        {
            "valor": "",
            "codigo": 0
        }
    ]
}
Customer Directory

Return the URL availables for the customers who can receive ECF online, for low environment the API will swift to a test default DGII

    const ecf = new ECF(certs, ENVIRONMENT.DEV);
    const rnc = 'any rnc';
    const response = await ecf.getCustomerDirectory(rnc);
Summary Invoice (Factura de consumo < 250K)

Send invoice summary (32) less than 250k Pesos.

    const ecf = new ECF(certs, ENVIRONMENT.DEV);
    await ecf.authenticate();

    const securityCode = generateRandomAlphaNumeric(); //6 digit password
    
    const signature = new Signature(certs.key, certs.cert);
    const transformer = new Transformer();
    const xml = transformer.json2xml(JsonECF32Summary);

    const fileName = `${rnc}${noEcf}.xml`;
    const signedXml = signature.signXml(xml, 'RFCE');
    const response = await ecf.sendSummary(signedXml, fileName);
Get all the tracks IDs

Return all the tracking associated with a NCF

    const ecf = new ECF(certs, ENVIRONMENT.DEV);
    const response = await ecf.trackStatuses(rnc, noEcf);
Inquiry Status

Web service responsible for responding to the validity or status of an e-CF to a receiver or even to an issuer, through the presentation of the issuing RNC, e-NCF and two conditional fields to the validity of the voucher, RNC Buyer and the code of security

    const ecf = new ECF(certs, ENVIRONMENT.DEV);
    const statusResponse = await ecf.inquiryStatus(
     RNCEmisor,
     noEcf,
     RNCComprador,
     securityCode
    );
Commercial approval

Web service responsible for receiving commercial approvals issued by receiving taxpayers, which consists of the approval of a transaction carried out between two taxpayers and for which an electronic receipt was received from an issuer.

 const ecf = new ECF(certs, ENVIRONMENT.DEV);
   await ecf.sendCommercialApproval(signedXml, fileName)
Void eCF

Web service responsible for receiving and voiding unused sequence ranges (e‐NCF) through a request XML containing the electronic receipt code, a series of ranges, from and to, as well as a token associated with a session valid.

 const ecf = new ECF(certs, ENVIRONMENT.DEV);
   await ecf.voidENCF(signedXml, fileName)

Utils

Current format date time

import {getCurrentFormattedDateTime} from "dgii-ecf";
getCurrentFormattedDateTime()

Generate alphenumeric 6 digit random password, default lenth length = 6

import { generateRandomAlphaNumeric } from "dgii-ecf";
generateRandomAlphaNumeric(length)

Generate Code QR URL for FC

import { generateFcQRCodeURL } from "dgii-ecf";
generateFcQRCodeURL(rncemisor: string, encf: string, montototal: number, codigoseguridad: string, env: ENVIRONMENT)
import { generateEcfQRCodeURL } from "dgii-ecf";
generateEcfQRCodeURL(rncemisor: string, rncComprador: string, encf: string, montototal: number, fechaEmision: string, fechaFirma: string, codigoseguridad: string, env: ENVIRONMENT)

This utility is invaluable for processing commercial approvals. When receiving commercial approval from DGII, this tool facilitates the extraction of XML content from the response body.

import { getXmlFromBodyResponse } from "dgii-ecf";
//lasTagName default ACECF
getXmlFromBodyResponse(rawBody: string, lasTagName?:string) 

Sender Receiver

Contain methods that allow to format the responses for the communication between sender and receptos and commertial approvals. It validate ecfType, format, customer RNC

const senderReciver = new SenderReceiver();
const response = senderReciver.getECFDataFromXML(
        data,
        '130862346',
        ReveivedStatus['e-CF Recibido']
      );
export enum NoReceivedCode {
  'Error de especificación' = '1',
  'Error de Firma Digital' = '2',
  'Envío duplicado' = '3',
  'RNC Comprador no corresponde' = '4',
}
export enum ReveivedStatus {
  'e-CF Recibido' = '0',
  'e-CF No Recibido' = '1',
}

Formatter

  <ARECF>
          <DetalleAcusedeRecibo>
              <Version>1.0</Version>
              <RNCEmisor>131880738</RNCEmisor>
              <RNCComprador>130862346</RNCComprador>
              <eNCF>E310000000007</eNCF>
              <Estado>0</Estado>
              <CodigoMotivoNoRecibido/>
              <FechaHoraAcuseRecibo>15-04-2023 15:21:55</FechaHoraAcuseRecibo>
          </DetalleAcusedeRecibo>
      </ARECF>

More Information ARECF

Run Test local environment

This repo performs the unit test connecting to the DGII test environment

  • First: In order to pass the test locally the first step is to plate your certificate into the directory src/test_cert current emtpy, for security reason .p12 gets ignored.
  • Second: create a .env file and set a variable CERTIFICATE_TEST_PASSWORD='_YOUT_PASSWORD_' with the passphrase secret of your certificate.

Install dependencies

  npm install

Run the test

  npm run test

Test watcher

  npm run test:watch

Authors

🔗 Links

portfolio linkedin twitter

Related

For more technical documentation related with Electronic Invoice:

1.1.3

4 months ago

1.1.2

5 months ago

1.1.0

5 months ago

1.0.0

8 months ago

0.1.10

9 months ago

0.1.11

9 months ago

0.1.12

9 months ago

0.1.13

9 months ago

0.1.14

9 months ago

0.1.15

9 months ago

0.1.13-0

9 months ago

1.0.4

5 months ago

0.2.17

8 months ago

0.2.16

9 months ago

1.0.4-0

6 months ago

0.2.15

9 months ago

0.2.14

9 months ago

0.2.13

9 months ago

0.2.12

9 months ago

0.2.11

9 months ago

1.0.3-0

6 months ago

0.2.10

9 months ago

0.2.1

9 months ago

0.2.0

9 months ago

0.1.12-0

9 months ago

0.2.7

9 months ago

0.1.16

9 months ago

0.1.8

9 months ago

0.2.6

9 months ago

0.1.17

9 months ago

0.1.7

9 months ago

0.2.9

9 months ago

0.2.8

9 months ago

0.1.9

9 months ago

0.2.3

9 months ago

0.1.4

9 months ago

0.2.2

9 months ago

0.2.5

9 months ago

0.1.6

9 months ago

0.2.4

9 months ago

0.1.3

1 year ago

0.1.2

1 year ago

0.1.1

1 year ago

0.1.0

1 year ago