Quickstart - Intégration en 15 minutes

Ce guide permet d'intégrer EFact dans une application existante et de voir une facture passer du statut pending à accepted (mock en V0.1).

Prérequis

  • • Un compte EFact avec une clé API secrète (sk_live_xxx ou sk_test_xxx)
  • • Node.js ≥ 18 (pour le SDK Node) ou Java 21 (pour le SDK Java)
  • • Une app React pour afficher le statut (optionnel mais recommandé)

Étape 1 - Installer le SDK backend

Node.js / TypeScript

Node.js Installation
npm install @itzenata/efact-node
# ou
yarn add @itzenata/efact-node

Java / Maven

Maven Dependency
<dependency>
  <groupId>com.itzenata</groupId>
  <artifactId>efact-java</artifactId>
  <version>0.1.0</version>
</dependency>

Étape 2 - Créer une Invoice

Node.js / TypeScript

Node.js Create Invoice
import { Itzenata } from '@itzenata/efact-node'

const itz = new Itzenata(process.env.ITZENATA_SECRET_KEY)

const invoice = await itz.invoices.create({
  amount: 12000,           // montant en centimes DH (= 120.00 DH)
  currency: 'MAD',
  customer: {
    ice: '00123456789',    // Identifiant Commun Entreprise
    name: 'Client SARL',
    address: 'Casablanca, Maroc'
  },
  lines: [
    { description: 'Service de conseil', quantity: 1, unit_price: 12000 }
  ],
  metadata: {
    internal_id: 'INV-2026-042'  // votre ID interne - retrouvable dans les webhooks
  }
})

// À retourner au frontend
return Response.json({ clientSecret: invoice.clientSecret })

Java / Spring Boot

Java Create Invoice
private final Itzenata itz = new Itzenata(System.getenv("ITZENATA_SECRET_KEY"));

@PostMapping("/api/invoices")
public Map<String, String> createInvoice() {
  Invoice invoice = itz.invoices().create(
    InvoiceCreateParams.builder()
      .amount(12000L)
      .currency("MAD")
      .customer(Customer.builder()
        .ice("00123456789")
        .name("Client SARL")
        .address("Casablanca, Maroc")
        .build())
      .addLine(Line.builder()
        .description("Service de conseil")
        .quantity(1)
        .unitPrice(12000L)
        .build())
      .putMetadata("internal_id", "INV-2026-042")
      .build()
  );

  return Map.of("clientSecret", invoice.getClientSecret());
}

Ce qui se passe côté EFact : Notre API valide votre requête, génère immédiatement le fichier XML UBL 2.1 conforme, et place la facture en file d'attente pour un traitement asynchrone (signature électronique et transmission DGI). Elle vous retourne instantanément un client_secret unique.

Étape 3 - Afficher le statut côté frontend

Installation

React SDK Installation
npm install @itzenata/efact-react

Composant React

React Component
import { ItzenataProvider, InvoiceStatus } from '@itzenata/efact-react'

// clientSecret vient de votre backend (étape 2)
export function InvoicePage({ clientSecret }: { clientSecret: string }) {
  return (
    <ItzenataProvider publishableKey="pk_live_xxx">
      <InvoiceStatus clientSecret={clientSecret} />
    </ItzenataProvider>
  )
}

Le composant <InvoiceStatus /> affiche automatiquement :

  • • L'état courant (pending signing transmitted accepted)
  • • Le QR code DGI une fois la facture signée
  • • Les liens de téléchargement PDF + XML signé
  • • Le bouton "Renvoyer" si la facture est rejected

Étape 4 - Recevoir les events asynchrones (webhook)

Configurer l'endpoint dans le dashboard

  1. 1. Aller dans Dashboard > Webhooks > Ajouter
  2. 2. Renseigner votre URL publique (ex : https://monapp.ma/webhooks/efact)
  3. 3. Sélectionner les events : invoice.accepted, invoice.rejected
  4. 4. Copier le webhook_secret généré

Traiter le webhook

Webhook Handler
import { Itzenata } from '@itzenata/efact-node'
const itz = new Itzenata(process.env.ITZENATA_SECRET_KEY)

export async function POST(req: Request) {
  const payload = await req.text()
  const signature = req.headers.get('itzenata-signature') ?? ''

  const event = itz.webhooks.constructEvent(
    payload,
    signature,
    process.env.ITZENATA_WEBHOOK_SECRET
  )

  switch (event.type) {
    case 'invoice.accepted':
      await db.invoice.update({
        where: { id: event.data.metadata.internal_id },
        data: { status: 'dgi_accepted', dgi_id: event.data.dgi_id }
      })
      break

    case 'invoice.rejected':
      await notifyAccountant(event.data.rejection_reason)
      break
  }

  return new Response('ok', { status: 200 })
}

Résultat attendu

En moins de 15 minutes, votre application :

  1. 1. Crée une Invoice via 3 lignes de SDK
  2. 2. Affiche le statut en temps réel dans un composant React
  3. 3. Reçoit la confirmation DGI via webhook et met à jour sa base de données

Étapes suivantes